/* SPDX-License-Identifier: Unlicense */ #include "bus.hpp" #include "musashi-m68k/m68k.h" #include "utils.hpp" #include #include #include #include #include #include unsigned char g_rom[ROM_SIZE] = {}; unsigned char g_ram[RAM_SIZE] = {}; unsigned char g_io1[IO1_SIZE] = {}; unsigned char g_io2[IO2_SIZE] = {}; std::vector code_bkpts{}, read_bkpts{}, write_bkpts{}, access_bkpts{}; static void exit_error(const char* fmt, ...) { va_list args; va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); fprintf(stderr, "\n"); unsigned int pc = m68k_get_reg(NULL, M68K_REG_PPC); char buff[100]; m68k_disassemble(buff, pc, M68K_CPU_TYPE_68000); fprintf(stderr, "%08x: %s\n", pc, buff); exit(EXIT_FAILURE); } static inline bool is_in_range(uint32_t value, uint32_t begin, uint32_t length) { return value >= begin && value <= begin + length; } enum bitness { BITNESS_8, BITNESS_16, BITNESS_32, }; struct read_result { unsigned int result; bool successful; }; static inline unsigned int memory_read_concrete( enum bitness bitness, unsigned char const * base, unsigned int address) { switch (bitness) { case BITNESS_8: return base[address]; case BITNESS_16: return (base[address] << 8) | base[address + 1]; case BITNESS_32: return (base[address] << 24) | (base[address + 1] << 16) | (base[address + 2] << 8) | base[address + 3]; } UNREACHABLE; } static inline struct read_result memory_read( enum bitness bitness, unsigned int address) { if (is_in_range(address, ROM_START, ROM_SIZE)) { return read_result{ memory_read_concrete(bitness, g_rom, address - ROM_START), true, }; } else if (is_in_range(address, RAM_START, RAM_SIZE)) { return read_result{ memory_read_concrete(bitness, g_ram, address - RAM_START), true, }; } else if (is_in_range(address, IO1_START, IO1_SIZE)) { return read_result{ memory_read_concrete(bitness, g_io1, address - IO1_START), true, }; } else if (is_in_range(address, IO2_START, IO2_SIZE)) { return read_result{ memory_read_concrete(bitness, g_io2, address - IO2_START), true, }; } return read_result{0, false}; } static inline void memory_write_concrete( enum bitness bitness, unsigned char * base, unsigned int address, unsigned int value) { switch (bitness) { case BITNESS_8: base[address] = value & 0xff; break; case BITNESS_16: base[address + 0] = (value >> 8) & 0xff; base[address + 1] = value & 0xff; break; case BITNESS_32: base[address + 0] = (value >> 24) & 0xff; base[address + 1] = (value >> 16) & 0xff; base[address + 2] = (value >> 8) & 0xff; base[address + 3] = value & 0xff; break; } } static inline bool memory_write( enum bitness bitness, unsigned int address, unsigned int value) { if (is_in_range(address, ROM_START, ROM_SIZE)) { memory_write_concrete(bitness, g_rom, address - ROM_START, value); return true; } else if (is_in_range(address, RAM_START, RAM_SIZE)) { memory_write_concrete(bitness, g_ram, address - RAM_START, value); return true; } else if (is_in_range(address, IO1_START, IO1_SIZE)) { memory_write_concrete(bitness, g_io1, address - IO1_START, value); return true; } else if (is_in_range(address, IO2_START, IO2_SIZE)) { memory_write_concrete(bitness, g_io2, address - IO2_START, value); return true; } return false; } #define MASK_24(X) ((X) & (0xFF << 24)) extern void m68k_read_callback(const uint32_t address, const uint32_t size); extern void m68k_write_callback(const uint32_t address, const uint32_t size); unsigned int m68k_read_memory_8(unsigned int address) { assert(MASK_24(address) == 0); // Just curious m68k_read_callback(address, 4); const struct read_result ret = memory_read(BITNESS_8, address); if (!ret.successful) exit_error("Read error u8 @%08x", address); return ret.result; } unsigned int m68k_read_memory_16(unsigned int address) { m68k_read_callback(address, 2); assert(MASK_24(address) == 0); // Just curious const struct read_result ret = memory_read(BITNESS_16, address); if (!ret.successful) exit_error("Read error u16 @%08x", address); return ret.result; } unsigned int m68k_read_memory_32(unsigned int address) { m68k_read_callback(address, 1); assert(MASK_24(address) == 0); // Just curious const struct read_result ret = memory_read(BITNESS_32, address); if (!ret.successful) exit_error("Read error u32 @%08x", address); return ret.result; } unsigned int m68k_read_disassembler_16(unsigned int address) { assert(MASK_24(address) == 0); // Just curious const struct read_result ret = memory_read(BITNESS_16, address); if (!ret.successful) exit_error("Disasm read error u16 @0x%08x", address); return ret.result; } unsigned int m68k_read_disassembler_32(unsigned int address) { assert(MASK_24(address) == 0); // Just curious const struct read_result ret = memory_read(BITNESS_32, address); if (!ret.successful) exit_error("Disasm read error u32 @0x%08x", address); return ret.result; } void m68k_write_memory_8(unsigned int address, unsigned int value) { assert(MASK_24(address) == 0); // Just curious m68k_write_callback(address, 1); const bool successful = memory_write(BITNESS_8, address, value); if (!successful) exit_error("Attempted to write %02x (u8) to address %08x", value&0xff, address); } void m68k_write_memory_16(unsigned int address, unsigned int value) { assert(MASK_24(address) == 0); // Just curious m68k_write_callback(address, 2); const bool successful = memory_write(BITNESS_16, address, value); if (!successful) exit_error("Attempted to write %04x (u16) to address %08x", value&0xffff, address); } void m68k_write_memory_32(unsigned int address, unsigned int value) { assert(MASK_24(address) == 0); // Just curious m68k_write_callback(address, 4); const bool successful = memory_write(BITNESS_16, address, value); if (!successful) exit_error("Attempted to write %08x (u32) to address %08x", value, address); }