diff --git a/mbc1.cpp b/mbc1.cpp index 8ced06b..7b979cf 100644 --- a/mbc1.cpp +++ b/mbc1.cpp @@ -9,194 +9,74 @@ namespace mbc1 #define ROM_BANK_SIZE 0x4000 #define RAM_BANK_SIZE 0x2000 - uint8_t bootrom[256]; uint8_t *rom; - uint8_t vram[8192]; uint8_t exram[4 * RAM_BANK_SIZE]; - uint8_t wram[8192]; - uint8_t hram[512]; - - uint8_t tags[65536]; uint8_t current_rom_bank = 1; uint8_t current_ram_bank = 0; bool ram_enabled = false; bool banking_mode = false; // false = ROM banking mode, true = RAM banking mode - uint8_t getKeypad(uint8_t value) - { - const uint8_t *keys = SDL_GetKeyboardState(NULL); - value = value & 0xf0; - if (value & 0x10) { - if (!keys[SDL_SCANCODE_RETURN]) value = value | 0x8; - if (!keys[SDL_SCANCODE_SPACE]) value = value | 0x4; - if (!keys[SDL_SCANCODE_Z]) value = value | 0x2; - if (!keys[SDL_SCANCODE_X]) value = value | 0x1; - } else if (value & 0x20) { - if (!keys[SDL_SCANCODE_DOWN]) value = value | 0x8; - if (!keys[SDL_SCANCODE_UP]) value = value | 0x4; - if (!keys[SDL_SCANCODE_LEFT]) value = value | 0x2; - if (!keys[SDL_SCANCODE_RIGHT]) value = value | 0x1; - } else { - value = value | 0x0f; - } - return value; - } - - uint8_t readMem(uint16_t address) - { - if (address < 0x8000) { - if ( (address < 0x0100) && ((hram[0x150]&0x01)==0) ) return bootrom[address]; - if (address < 0x4000) { - // ROM Bank 0 - return rom[address]; - } else { - // Switchable ROM bank - uint32_t banked_address = (current_rom_bank * ROM_BANK_SIZE) + (address - 0x4000); - return rom[banked_address]; - } - } else if (address < 0xA000) { - return vram[address - 0x8000]; - } else if (address < 0xC000) { - if (ram_enabled) { - uint32_t banked_address = (current_ram_bank * RAM_BANK_SIZE) + (address - 0xA000); - return exram[banked_address]; - } - return 0xFF; // Return open bus value when RAM is disabled - } else if (address < 0xE000) { - return wram[address - 0xC000]; - } else if (address < 0xFE00) { - return wram[address - 0xE000]; - } else { - if (address==0xFF00) { - hram[address - 0XFE00] = getKeypad(hram[address - 0XFE00]); - } - return hram[address - 0XFE00]; - } - } - - void writeMem(uint16_t address, uint8_t value) - { - if (address < 0x8000) { - if (address < 0x2000) { - // Enable/disable RAM - ram_enabled = (value & 0x0F) == 0x0A; - } else if (address < 0x4000) { - // Select ROM bank - value &= 0x1F; // Lower 5 bits are used - if (value == 0) value = 1; // Bank 0 is not allowed - current_rom_bank = (current_rom_bank & 0x60) | value; - } else if (address < 0x6000) { - // Select RAM bank or upper bits of ROM bank - if (banking_mode) { - current_ram_bank = value & 0x03; // 2 bits for RAM bank - } else { - current_rom_bank = (current_rom_bank & 0x1F) | ((value & 0x03) << 5); - } - } else { - // Select banking mode - banking_mode = value & 0x01; - } - } else if (address < 0xA000) { - vram[address - 0x8000] = value; - } else if (address < 0xC000) { - if (ram_enabled) { - uint32_t banked_address = (current_ram_bank * RAM_BANK_SIZE) + (address - 0xA000); - exram[banked_address] = value; - } - } else if (address < 0xE000) { - wram[address - 0xC000] = value; - } else if (address < 0xFE00) { - wram[address - 0xE000] = value; - } else { - if ( (address==0xFF50) && ((value&0x01) != 1) ) return; //Only allow disabling boot room - if ( (address==0xFF00) ) { value = value & 0x30; } - if ( (address==0xFF04) ) { hram[address-0xFE00] = 0; return; } - if ( (address==0xFF0F) ) { hram[address-0xFE00] = value; sm83::processInterrupts(); return; } - if ( (address==0xFF46) ) mem::init_dma_transfer(value); - hram[address - 0xFE00] = value; - } - } - - uint8_t getTag(uint16_t address) - { - return tags[address]; - } - - void setTag(uint16_t address, uint8_t value) - { - tags[address] = value; - } - - void saveState(FILE* f) - { - - } - - void loadState(FILE *f) - { - - } - - uint8_t* rawPtr(uint16_t address) - { - if (address < 0x8000) { - if ( (address < 0x0100) && ((hram[0x150]&0x01)==0) ) return &bootrom[address]; - if (address < 0x4000) { - // ROM Bank 0 - return &rom[address]; - } else { - // Switchable ROM bank - uint32_t banked_address = (current_rom_bank * ROM_BANK_SIZE) + (address - 0x4000); - return &rom[banked_address]; - } - } else if (address < 0xA000) { - return &vram[address - 0x8000]; - } else if (address < 0xC000) { - if (ram_enabled) { - uint32_t banked_address = (current_ram_bank * RAM_BANK_SIZE) + (address - 0xA000); - return &exram[banked_address]; - } - return nullptr; // Return open bus value when RAM is disabled - } else if (address < 0xE000) { - return &wram[address - 0xC000]; - } else if (address < 0xFE00) { - return &wram[address - 0xE000]; - } else { - return &hram[address - 0XFE00]; - } - } - void reset() { - FILE *f = fopen("dmg_boot.bin", "rb"); - if (!f) { printf("ABORTING: 'dmg_boot.bin' not found!\n"); exit(1); } - fseek(f, 0, SEEK_END); - const int size = ftell(f); - fseek(f, 0, SEEK_SET); - fread(bootrom, size, 1, f); - fclose(f); - - for (int i=0; i<8192; ++i) { vram[i] = 0; } for (int i=0; i<4*RAM_BANK_SIZE; ++i) { exram[i] = 0; } - for (int i=0; i<8192; ++i) { wram[i] = 0; } - for (int i=0; i<512; ++i) { hram[i] = 0; } - for (int i=0; i<65536; ++i) { tags[i] = MEMTAG_NONE; } + } + + uint8_t readRom(uint16_t address) + { + if (address < 0x4000) { + // ROM Bank 0 + return rom[address]; + } else { + // Switchable ROM bank + uint32_t banked_address = (current_rom_bank * ROM_BANK_SIZE) + (address - 0x4000); + return rom[banked_address]; + } + } + + void writeRom(uint16_t address, uint8_t value) + { + if (address < 0x2000) { + // Enable/disable RAM + ram_enabled = (value & 0x0F) == 0x0A; + } else if (address < 0x4000) { + // Select ROM bank + value &= 0x1F; // Lower 5 bits are used + if (value == 0) value = 1; // Bank 0 is not allowed + current_rom_bank = (current_rom_bank & 0x60) | value; + } else if (address < 0x6000) { + // Select RAM bank or upper bits of ROM bank + if (banking_mode) { + current_ram_bank = value & 0x03; // 2 bits for RAM bank + } else { + current_rom_bank = (current_rom_bank & 0x1F) | ((value & 0x03) << 5); + } + } else { + // Select banking mode + banking_mode = value & 0x01; + } + } + + uint8_t readRam(uint16_t address) + { + if (ram_enabled) { + uint32_t banked_address = (current_ram_bank * RAM_BANK_SIZE) + (address - 0xa000); + return exram[banked_address]; + } + return 0xff; // Return open bus value when RAM is disabled + } + + void writeRam(uint16_t address, uint8_t value) + { + if (ram_enabled) { + uint32_t banked_address = (current_ram_bank * RAM_BANK_SIZE) + (address - 0xa000); + exram[banked_address] = value; + } } void init(uint8_t *rom, uint32_t rom_size, uint32_t ram_size) { - mem::readMem = mbc1::readMem; - mem::writeMem = mbc1::writeMem; - mem::getTag = mbc1::getTag; - mem::setTag = mbc1::setTag; - mem::saveState = mbc1::saveState; - mem::loadState = mbc1::loadState; - mem::reset = mbc1::reset; - mem::rawPtr = mbc1::rawPtr; - mbc1::rom = rom; - reset(); } } \ No newline at end of file diff --git a/mbc1.h b/mbc1.h index 8452049..48ab939 100644 --- a/mbc1.h +++ b/mbc1.h @@ -4,4 +4,10 @@ namespace mbc1 { void init(uint8_t *rom, uint32_t rom_size, uint32_t ram_size); + + void reset(); + uint8_t readRom(uint16_t address); + void writeRom(uint16_t address, uint8_t value); + uint8_t readRam(uint16_t address); + void writeRam(uint16_t address, uint8_t value); } diff --git a/mbc_none.cpp b/mbc_none.cpp index c8f2f31..20f2b4e 100644 --- a/mbc_none.cpp +++ b/mbc_none.cpp @@ -1,152 +1,22 @@ #include "mbc_none.h" -#include "mem.h" -#include "sm83.h" -#include -#include namespace mbc_none { - uint8_t bootrom[256]; uint8_t *rom; - uint8_t vram[8192]; - uint8_t exram[8192]; - uint8_t wram[8192]; - uint8_t hram[512]; - uint8_t tags[65536]; + void reset() { } // nothing to do - uint8_t getKeypad(uint8_t value) - { - const uint8_t *keys = SDL_GetKeyboardState(NULL); - value = value & 0xf0; - if (value & 0x10) { - if (!keys[SDL_SCANCODE_RETURN]) value = value | 0x8; - if (!keys[SDL_SCANCODE_SPACE]) value = value | 0x4; - if (!keys[SDL_SCANCODE_Z]) value = value | 0x2; - if (!keys[SDL_SCANCODE_X]) value = value | 0x1; - } else if (value & 0x20) { - if (!keys[SDL_SCANCODE_DOWN]) value = value | 0x8; - if (!keys[SDL_SCANCODE_UP]) value = value | 0x4; - if (!keys[SDL_SCANCODE_LEFT]) value = value | 0x2; - if (!keys[SDL_SCANCODE_RIGHT]) value = value | 0x1; - } else { - value = value | 0x0f; - } - return value; - } + uint8_t readRom(uint16_t address) { return rom[address]; } - uint8_t readMem(uint16_t address) - { - if (address < 0x8000) { - if ( (address < 0x0100) && ((hram[0x150]&0x01)==0) ) return bootrom[address]; - return rom[address]; - } else if (address < 0xA000) { - return vram[address - 0x8000]; - } else if (address < 0xC000) { - return exram[address - 0xA000]; - } else if (address < 0xE000) { - return wram[address - 0xC000]; - } else if (address < 0xFE00) { - return wram[address - 0xE000]; - } else { - if (address==0xFF00) { - hram[address - 0XFE00] = getKeypad(hram[address - 0XFE00]); - } - return hram[address - 0XFE00]; - } - } + void writeRom(uint16_t address, uint8_t value) { } // do nothing - void writeMem(uint16_t address, uint8_t value) - { - if (address < 0x8000) { - // Read Only Memory, you know... - //rom[address] = value; - } else if (address < 0xA000) { - vram[address - 0x8000] = value; - } else if (address < 0xC000) { - exram[address - 0xA000] = value; - } else if (address < 0xE000) { - wram[address - 0xC000] = value; - } else if (address < 0xFE00) { - wram[address - 0xE000] = value; - } else { - if ( (address==0xFF50) && ((value&0x01) != 1) ) return; //Only allow disabling boot room - if ( (address==0xFF00) ) { value = value & 0x30; } - if ( (address==0xFF04) ) { hram[address-0xFE00] = 0; return; } - if ( (address==0xFF0F) ) { hram[address-0xFE00] = value; sm83::processInterrupts(); return; } - if ( (address==0xFF46) ) mem::init_dma_transfer(value); - hram[address - 0xFE00] = value; - } - } + uint8_t readRam(uint16_t address) { return 0xff; } - uint8_t getTag(uint16_t address) - { - return tags[address]; - } - - void setTag(uint16_t address, uint8_t value) - { - tags[address] = value; - } - - void saveState(FILE* f) - { - - } - - void loadState(FILE *f) - { - - } - - uint8_t* rawPtr(uint16_t address) - { - if (address < 0x8000) { - if ( (address < 0x0100) && ((hram[0x150]&0x01)==0) ) return &bootrom[address]; - return &rom[address]; - } else if (address < 0xA000) { - return &vram[address - 0x8000]; - } else if (address < 0xC000) { - return &exram[address - 0xA000]; - } else if (address < 0xE000) { - return &wram[address - 0xC000]; - } else if (address < 0xFE00) { - return &wram[address - 0xE000]; - } else { - return &hram[address - 0XFE00]; - } - } - - void reset() - { - FILE *f = fopen("dmg_boot.bin", "rb"); - if (!f) { printf("ABORTING: 'dmg_boot.bin' not found!\n"); exit(1); } - fseek(f, 0, SEEK_END); - const int size = ftell(f); - fseek(f, 0, SEEK_SET); - fread(bootrom, size, 1, f); - fclose(f); - - for (int i=0; i<8192; ++i) { vram[i] = 0; } - for (int i=0; i<8192; ++i) { exram[i] = 0; } - for (int i=0; i<8192; ++i) { wram[i] = 0; } - for (int i=0; i<512; ++i) { hram[i] = 0; } - for (int i=0; i<65536; ++i) { tags[i] = MEMTAG_NONE; } - } + void writeRam(uint16_t address, uint8_t value) { } // do nothing void init(uint8_t *rom, uint32_t rom_size, uint32_t ram_size) { - mem::readMem = mbc_none::readMem; - mem::writeMem = mbc_none::writeMem; - mem::getTag = mbc_none::getTag; - mem::setTag = mbc_none::setTag; - mem::saveState = mbc_none::saveState; - mem::loadState = mbc_none::loadState; - mem::reset = mbc_none::reset; - mem::rawPtr = mbc_none::rawPtr; - mbc_none::rom = rom; - reset(); } } \ No newline at end of file diff --git a/mbc_none.h b/mbc_none.h index be6465f..523d4cc 100644 --- a/mbc_none.h +++ b/mbc_none.h @@ -4,4 +4,10 @@ namespace mbc_none { void init(uint8_t *rom, uint32_t rom_size, uint32_t ram_size); + + void reset(); + uint8_t readRom(uint16_t address); + void writeRom(uint16_t address, uint8_t value); + uint8_t readRam(uint16_t address); + void writeRam(uint16_t address, uint8_t value); } diff --git a/mem.cpp b/mem.cpp index 9ce33e7..ba2a132 100644 --- a/mem.cpp +++ b/mem.cpp @@ -2,21 +2,34 @@ #include "sm83.h" #include #include +#include #include "mbc_none.h" #include "mbc1.h" + +#define DIV hram[0x104] // 0xff04 - 0xfe00 +#define TIMA hram[0x105] // 0xff05 - 0xfe00 +#define TMA hram[0x106] // 0xff06 - 0xfe00 +#define TAC hram[0x107] // 0xff07 - 0xfe00 namespace mem { - void (*reset)(void); - uint8_t(*readMem)(uint16_t); - void (*writeMem)(uint16_t, uint8_t); - uint8_t(*getTag)(uint16_t); - void (*setTag)(uint16_t, uint8_t); - void (*saveState)(FILE*); - void (*loadState)(FILE*); - uint8_t*(*rawPtr)(uint16_t); - + void (*resetMbc)(void); + uint8_t (*readRom)(uint16_t); + void (*writeRom)(uint16_t, uint8_t); + uint8_t (*readRam)(uint16_t); + void (*writeRam)(uint16_t, uint8_t); + + uint8_t bootrom[256]; + uint8_t *rom; + uint8_t vram[8192]; + uint8_t wram[8192]; + uint8_t hram[512]; + + uint8_t tags[65536]; + char *title = nullptr; + uint32_t rom_size = 0; + uint32_t ram_size = 0; uint16_t dma_address = 0; uint8_t dma_pos = 160; @@ -27,27 +40,142 @@ namespace mem void init(uint8_t* rom, const int size) { - //if (memory) free(memory); - //memory = (uint8_t*)malloc(size); title = (char*)&rom[0x134]; uint8_t mapper_type = rom[0x147]; - uint32_t rom_size = 32768 * (1 << rom[0x148]); + rom_size = 32768 * (1 << rom[0x148]); int sizes[] = { 0, 0, 8, 32, 128, 64}; - uint32_t ram_size = sizes[rom[0x149]] * 1024; + ram_size = sizes[rom[0x149]] * 1024; switch (mapper_type) { case 0x00: mbc_none::init(rom, rom_size, ram_size); + mem::resetMbc = mbc_none::reset; + mem::readRom = mbc_none::readRom; + mem::writeRom = mbc_none::writeRom; + mem::readRam = mbc_none::readRam; + mem::writeRam = mbc_none::writeRam; break; case 0x01: case 0x02: case 0x03: mbc1::init(rom, rom_size, ram_size); + mem::resetMbc = mbc1::reset; + mem::readRom = mbc1::readRom; + mem::writeRom = mbc1::writeRom; + mem::readRam = mbc1::readRam; + mem::writeRam = mbc1::writeRam; break; }; } + void reset() + { + FILE *f = fopen("dmg_boot.bin", "rb"); + if (!f) { printf("ABORTING: 'dmg_boot.bin' not found!\n"); exit(1); } + fseek(f, 0, SEEK_END); + const int size = ftell(f); + fseek(f, 0, SEEK_SET); + fread(bootrom, size, 1, f); + fclose(f); + + for (int i=0; i<8192; ++i) { vram[i] = 0; } + for (int i=0; i<8192; ++i) { wram[i] = 0; } + for (int i=0; i<512; ++i) { hram[i] = 0; } + for (int i=0; i<65536; ++i) { tags[i] = MEMTAG_NONE; } + + resetMbc(); + } + + uint8_t getKeypad(uint8_t value) + { + const uint8_t *keys = SDL_GetKeyboardState(NULL); + value = value & 0xf0; + if (value & 0x10) { + if (!keys[SDL_SCANCODE_RETURN]) value = value | 0x8; + if (!keys[SDL_SCANCODE_SPACE]) value = value | 0x4; + if (!keys[SDL_SCANCODE_Z]) value = value | 0x2; + if (!keys[SDL_SCANCODE_X]) value = value | 0x1; + } else if (value & 0x20) { + if (!keys[SDL_SCANCODE_DOWN]) value = value | 0x8; + if (!keys[SDL_SCANCODE_UP]) value = value | 0x4; + if (!keys[SDL_SCANCODE_LEFT]) value = value | 0x2; + if (!keys[SDL_SCANCODE_RIGHT]) value = value | 0x1; + } else { + value = value | 0x0f; + } + return value; + } + + uint8_t readMem(uint16_t address) + { + if (address < 0x8000) { + if ( (address < 0x0100) && ((hram[0x150]&0x01)==0) ) return bootrom[address]; + return readRom(address); + } else if (address < 0xA000) { + return vram[address - 0x8000]; + } else if (address < 0xC000) { + return readRam(address); + } else if (address < 0xE000) { + return wram[address - 0xC000]; + } else if (address < 0xFE00) { + return wram[address - 0xE000]; + } else { + if (address==0xFF00) { + hram[address - 0XFE00] = getKeypad(hram[address - 0XFE00]); + } + return hram[address - 0XFE00]; + } + } + + void writeMem(uint16_t address, uint8_t value) + { + if (address < 0x8000) { + writeRom(address, value); + } else if (address < 0xA000) { + vram[address - 0x8000] = value; + } else if (address < 0xC000) { + writeRam(address, value); + } else if (address < 0xE000) { + wram[address - 0xC000] = value; + } else if (address < 0xFE00) { + wram[address - 0xE000] = value; + } else { + if ( (address==0xFF50) && ((value&0x01) != 1) ) return; //Only allow disabling boot room + if ( (address==0xFF00) ) { value = value & 0x30; } + if ( (address==0xFF04) ) { hram[address-0xFE00] = 0; return; } + if ( (address==0xFF0F) ) { hram[address-0xFE00] = value; sm83::processInterrupts(); return; } + if ( (address==0xFF46) ) mem::init_dma_transfer(value); + hram[address - 0xFE00] = value; + } + } + + uint8_t getTag(uint16_t address) + { + return tags[address]; + } + + void setTag(uint16_t address, uint8_t value) + { + tags[address] = value; + } + + void saveState(FILE* f) + { + + } + + void loadState(FILE* f) + { + + } + + uint8_t *rawPtr(uint16_t address) + { + return &hram[address-0xfe00]; + } + + void init_dma_transfer(uint8_t source) { dma_address = source << 8; @@ -62,21 +190,19 @@ namespace mem div_counter += dt; if (div_counter>=256) { div_counter -= 256; - uint8_t *div = mem::rawPtr(0xff04); - *div = *div + 1; + DIV++; } // Timer - uint8_t *t_regs = mem::rawPtr(0xff05); - if (*(t_regs+2)&0x4) { // if bit 3 of mem(0xff07) is 1, timer enabled - uint16_t freq = timer_frequencies[*(t_regs+2)&0x03]; + if (TAC&0x4) { // if bit 3 of mem(0xff07) is 1, timer enabled + uint16_t freq = timer_frequencies[TAC&0x03]; timer_counter += dt; if (timer_counter>=freq) { timer_counter -= freq; - if ((*t_regs)<255) - (*t_regs)++; + if (TIMA<255) + TIMA++; else { - *t_regs = *(t_regs+1); + TIMA = TMA; sm83::interrupt(INTERRUPT_TIMER); } } @@ -88,7 +214,7 @@ namespace mem dma_dots += dt; while (dma_dots >= 4 && dma_pos<160) { dma_dots -= 4; - mem::writeMem(0xfe00|dma_pos, mem::readMem(dma_address|dma_pos)); + hram[dma_pos] = mem::readMem(dma_address|dma_pos); dma_pos++; } } diff --git a/mem.h b/mem.h index 1ce6bab..603b9eb 100644 --- a/mem.h +++ b/mem.h @@ -25,18 +25,18 @@ namespace mem #define MBC7 7 void init(uint8_t* rom, const int size); - extern void (*reset)(void); + void reset(); - extern uint8_t(*readMem)(uint16_t); - extern void (*writeMem)(uint16_t, uint8_t); + uint8_t readMem(uint16_t address); + void writeMem(uint16_t address, uint8_t value); - extern uint8_t(*getTag)(uint16_t); - extern void (*setTag)(uint16_t, uint8_t); + uint8_t getTag(uint16_t address); + void setTag(uint16_t address, uint8_t value); - extern void (*saveState)(FILE*); - extern void (*loadState)(FILE*); + void saveState(FILE* f); + void loadState(FILE* f); - extern uint8_t*(*rawPtr)(uint16_t); + uint8_t *rawPtr(uint16_t address); void init_dma_transfer(uint8_t source); void update_mapped(const uint32_t dt); diff --git a/sm83.cpp b/sm83.cpp index 06344f6..b5630ca 100644 --- a/sm83.cpp +++ b/sm83.cpp @@ -592,9 +592,9 @@ namespace sm83 void HALT() { if (!halted) { - uint8_t *IE = mem::rawPtr(0xffff); - uint8_t *IF = mem::rawPtr(0xff0f); - if ( (ime==0) && ((*IF & *IE) != 0) ) { + const uint8_t IE = mem::readMem(0xffff); + const uint8_t IF = mem::readMem(0xff0f); + if ( (ime==0) && ((IF & IE) != 0) ) { // [TODO] HALT BUG if (pending_ei==2) rPC--; return;