diff --git a/include/bus.hh b/include/bus.hh index 2d1c607..6667b03 100644 --- a/include/bus.hh +++ b/include/bus.hh @@ -39,7 +39,8 @@ class Bus { std::optional> write(uint32_t); #define MEMORY_REGION(name, start) \ - static constexpr uint32_t name##_START = start; + static constexpr uint32_t name##_START = start; \ + static constexpr uint8_t name##_REGION = start >> 24 & 0xFF; #define DECL_MEMORY(name, ident, start, end) \ MEMORY_REGION(name, start) \ @@ -70,6 +71,7 @@ class Bus { MEMORY_REGION(ROM_2, 0x0C000000) #undef MEMORY_REGION + std::vector rom; std::unique_ptr io; diff --git a/src/bus.cc b/src/bus.cc index 33649a7..727d883 100644 --- a/src/bus.cc +++ b/src/bus.cc @@ -41,21 +41,36 @@ Bus::init(std::array&& bios, std::vector&& rom) { template std::optional> Bus::read(uint32_t address) const { + + switch (address >> 24 & 0xFF) { + #define MATCHES(AREA, area) \ - if (address >= AREA##_START && address < AREA##_START + area.size()) \ + case AREA##_REGION: \ + if (address > AREA##_START + area.size() - N) \ + break; \ return std::span(&area[address - AREA##_START], N); - MATCHES(BIOS, bios) - MATCHES(BOARD_WRAM, board_wram) - MATCHES(CHIP_WRAM, chip_wram) - MATCHES(PALETTE_RAM, palette_ram) - MATCHES(VRAM, vram) - MATCHES(OAM_OBJ_ATTR, oam_obj_attr) - MATCHES(ROM_0, rom) - MATCHES(ROM_1, rom) - MATCHES(ROM_2, rom) +#define MATCHES_PAK(AREA, area) \ + case AREA##_REGION: \ + case AREA##_REGION + 1: \ + if (address > AREA##_START + area.size() - N) \ + break; \ + return std::span(&area[address - AREA##_START], N); + MATCHES(BIOS, bios) + MATCHES(BOARD_WRAM, board_wram) + MATCHES(CHIP_WRAM, chip_wram) + MATCHES(PALETTE_RAM, palette_ram) + MATCHES(VRAM, vram) + MATCHES(OAM_OBJ_ATTR, oam_obj_attr) + + MATCHES_PAK(ROM_0, rom) + MATCHES_PAK(ROM_1, rom) + MATCHES_PAK(ROM_2, rom) + +#undef MATCHES_PAK #undef MATCHES + } glogger.error("Invalid memory region read"); return {}; @@ -64,17 +79,23 @@ Bus::read(uint32_t address) const { template std::optional> Bus::write(uint32_t address) { + + switch (address >> 24 & 0xFF) { + #define MATCHES(AREA, area) \ - if (address >= AREA##_START && address < AREA##_START + area.size()) \ + case AREA##_REGION: \ + if (address > AREA##_START + area.size() - N) \ + break; \ return std::span(&area[address - AREA##_START], N); - MATCHES(BOARD_WRAM, board_wram) - MATCHES(CHIP_WRAM, chip_wram) - MATCHES(PALETTE_RAM, palette_ram) - MATCHES(VRAM, vram) - MATCHES(OAM_OBJ_ATTR, oam_obj_attr) + MATCHES(BOARD_WRAM, board_wram) + MATCHES(CHIP_WRAM, chip_wram) + MATCHES(PALETTE_RAM, palette_ram) + MATCHES(VRAM, vram) + MATCHES(OAM_OBJ_ATTR, oam_obj_attr) #undef MATCHES + } glogger.error("Invalid memory region written"); return {};