diff --git a/source/io.c b/source/io.c index 539f79e..14ea204 100644 --- a/source/io.c +++ b/source/io.c @@ -41,6 +41,7 @@ extern uint32_t romAddressMask; extern uint16_t *internalEeprom; extern nec_Regs I; extern uint64_t nec_monotonicCycles; +extern uint32_t sramSize; enum { @@ -827,10 +828,20 @@ void cpu_writeport(uint32_t port, uint8_t value) /* Hardware */ case 0xA0: + /* Force cart handshake to be set */ ws_ioRam[port] |= 0x80; - break; +#ifdef USE_PAGED_MEMORY_ACCESS + if (value & 0x01) + { + Log(TLOG_WARNING, "A0", "Oh yeah %02X BABY", value); + uint32_t romSize; + uint8_t *rom = getRom(&romSize); + set_memory_bank(0xF, ws_get_page_ptr(rom, romSize, (ws_ioRam[0xC0] & 0x0F << 4) + 0x0F)); + } + break; +#endif /* Timers */ case 0xA2: case 0xA4: @@ -993,11 +1004,61 @@ void cpu_writeport(uint32_t port, uint8_t value) /* MBC */ +#ifndef USE_PAGED_MEMORY_ACCESS case 0xC0: case 0xC1: case 0xC2: case 0xC3: break; +#else + case 0xC0: + { + /* page 4 to F */ + uint32_t romSize; + uint8_t *rom = getRom(&romSize); + for (int i = 0x04 ; i < 0x10 ; i++) + { + set_memory_bank(i, ws_get_page_ptr(rom, romSize, (value << 4) + i)); + } + + if (!(ws_ioRam[0xA0] & 0x01)) + { + set_irom_overlay(); + } + break; + } + + case 0xC1: + /* Sram bank */ + if (sramSize > 0) + { + uint32_t sramSize; + uint8_t *sram = getSram(&sramSize); + set_memory_bank(0x1, ws_get_page_ptr(sram, sramSize, value)); + } + break; + + case 0xC2: + { + /* page 4 to F */ + uint32_t romSize; + uint8_t *rom = getRom(&romSize); + /* Page 2 */ + set_memory_bank(0x2, ws_get_page_ptr(rom, romSize, value)); + break; + } + + case 0xC3: + { + /* page 4 to F */ + uint32_t romSize; + uint8_t *rom = getRom(&romSize); + /* Page 3 */ + set_memory_bank(0x3, ws_get_page_ptr(rom, romSize, value)); + break; + } + +#endif /* Cart EEPROM */ case 0xC4: /* Data High */ diff --git a/source/memory.c b/source/memory.c index 5388936..710569c 100644 --- a/source/memory.c +++ b/source/memory.c @@ -124,6 +124,7 @@ void dump_memory() fclose(fp); } +#ifndef USE_PAGED_MEMORY_ACCESS //////////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////// @@ -255,7 +256,82 @@ uint8_t cpu_readmem20(uint32_t addr) return (0x90); } +#else +/* 256 page of 12 bits */ +uint8_t *pagedMemory[0x100]; +/* Memory address is 20bit and split in 8 (page) - 12 (offset) */ +void cpu_writemem20(uint32_t addr, uint8_t value) +{ + uint8_t page = addr >> 12; + uint16_t offset = addr & 0xFFF; + if (page < 0x30) + { + /* Unmapped will be NULL so just check to be sure */ + if (pagedMemory[page]) + { + pagedMemory[page][offset] = value; + } + } +} + +uint8_t cpu_readmem20(uint32_t addr) +{ + uint8_t page = addr >> 12; + uint16_t offset = addr & 0xFFF; + if (pagedMemory[page]) + { + return pagedMemory[page][offset]; + } + return 0x90; +} + +/* Set memory bank with a granularity of 4-16 as it is the most common on the WonderSwan */ +void set_memory_bank(uint8_t bank, uint8_t *pointer) +{ + uint8_t page = bank << 4; + for(int i = 0; i < 16; i++) + { + pagedMemory[page | i] = pointer + (i * 0x1000); + } +} + +void set_memory_page(uint8_t page, uint8_t *pointer) +{ + pagedMemory[page] = pointer; +} + +void set_irom_overlay() +{ + /* Setup the boot rom */ + if (ws_get_system() == WS_SYSTEM_MONO) + { + set_memory_page(0xFF, internalBWIRom); + } + else if (ws_get_system() == WS_SYSTEM_COLOR) + { + set_memory_page(0xFE, internalColorIRom); + set_memory_page(0xFF, internalColorIRom + 0x1000); + } + else if (ws_get_system() == WS_SYSTEM_CRYSTAL) + { + set_memory_page(0xFE, internalCrystalIRom); + set_memory_page(0xFF, internalCrystalIRom + 0x1000); + } +} + +uint8_t *getRom(uint32_t *size) +{ + *size = romSize; + return ws_rom; +} + +uint8_t *getSram(uint32_t *size) +{ + *size = sramSize; + return ws_staticRam; +} +#endif //////////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////////// @@ -414,6 +490,37 @@ void ws_memory_init(uint8_t *rom, uint32_t wsRomSize) } romAddressMask = romSize - 1; + + +#ifdef USE_PAGED_MEMORY_ACCESS + for(int i = 0; i < 0x100; i++) + { + pagedMemory[i] = NULL; + } + + /* IRAM */ + set_memory_bank(0, internalRam); + for(int i = 0x4; i < 0x10; i++) + { + set_memory_page(i, NULL); + } + + /* Cart SRAM */ + if (sramSize > 0) + { + set_memory_bank(0x1, ws_get_page_ptr(ws_staticRam, sramSize, 0xFF)); + } + + set_memory_bank(0x2, ws_get_page_ptr(ws_rom, romSize, 0xFF)); + set_memory_bank(0x3, ws_get_page_ptr(ws_rom, romSize, 0xFF)); + + for(int i = 0x04; i < 0x10; i++) + { + set_memory_bank(i, ws_get_page_ptr(ws_rom, romSize, 0xF0 + i)); + } + + set_irom_overlay(); +#endif } //////////////////////////////////////////////////////////////////////////////// diff --git a/source/memory.h b/source/memory.h index f33a80f..b0714a9 100644 --- a/source/memory.h +++ b/source/memory.h @@ -36,6 +36,27 @@ char *create_file(char *filename, uint32_t size); char *load_file(char *filename); void dump_memory(); +//#define USE_PAGED_MEMORY_ACCESS +#ifdef USE_PAGED_MEMORY_ACCESS +/*** + * Set a memory page with a ganularity of 4-16 + * @param bank: the bank (0-F) to set + * @param pointer: a pointer to the memory to set + */ +void set_memory_bank(uint8_t bank, uint8_t *pointer); + +/*** + * Set a memory page with a ganularity of 8-12 + * @param bank: the bank (0-FF) to set + * @param pointer: a pointer to the memory to set + */ +void set_memory_page(uint8_t page, uint8_t *pointer); + +void set_irom_overlay(); + +uint8_t *getRom(uint32_t *size); +uint8_t *getSram(uint32_t *size); +#endif #define BW_IEEPROM_SIZE (128) #define COLOR_IEEPROM_SIZE (2048) diff --git a/source/rom.c b/source/rom.c index 3146137..a040bcc 100644 --- a/source/rom.c +++ b/source/rom.c @@ -183,4 +183,3 @@ uint32_t ws_rom_eepromSize(uint8_t *wsrom, uint32_t wsromSize) return (0); } -