From 9f0715c82550aaae187342711b42bc7f080850f4 Mon Sep 17 00:00:00 2001 From: Samuel Walker Date: Fri, 30 May 2025 12:30:54 -0600 Subject: [PATCH] mbc2 passing --- .vscode/launch.json | 2 +- lib/cart.c | 226 ++++++++++++++++++++++++++------------------ 2 files changed, 135 insertions(+), 93 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 2cb39d5..fa27ddc 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -9,7 +9,7 @@ "request": "launch", "name": "Debug", "program": "${workspaceFolder}/build/gbemu/Debug/gbemu.exe", - "args": [ "C:\\Users\\piwalker\\Downloads\\mts-20240926-1737-443f6e1\\mts-20240926-1737-443f6e1\\emulator-only\\mbc1\\rom_512kb.gb" ], + "args": [ "C:\\Users\\piwalker\\Downloads\\mts-20240926-1737-443f6e1\\mts-20240926-1737-443f6e1\\emulator-only\\mbc2\\ram.gb" ], "cwd": "${workspaceFolder}" } ] diff --git a/lib/cart.c b/lib/cart.c index 41e973f..a1ffcde 100644 --- a/lib/cart.c +++ b/lib/cart.c @@ -13,16 +13,24 @@ bool cart_mbc1() { return BETWEEN(ctx.header->type, 1, 3); } +bool cart_mbc2() { + return BETWEEN(ctx.header->type, 5, 6); +} + bool cart_mbc3() { return BETWEEN(ctx.header->type, 15, 19); } +bool cart_mbc5() { + return BETWEEN(ctx.header->type, 25, 30) +} + bool cart_mbc() { - return cart_mbc1() || cart_mbc3(); + return cart_mbc1() || cart_mbc2() || cart_mbc3() || cart_mbc5(); } bool cart_battery() { - return ctx.header->type == 3 || BETWEEN(ctx.header->type, 15, 16) || ctx.header->type == 19; + return ctx.header->type == 3 || BETWEEN(ctx.header->type, 15, 16) || ctx.header->type == 19 || ctx.header->type == 6; } static const char *ROM_TYPES[] = { @@ -160,6 +168,11 @@ void cart_setup_bamking() { } } + if(cart_mbc2()) { + ctx.ram_banks[0] = malloc(0x2000); + memset(ctx.ram_banks[0], 0, 0x2000); + } + ctx.ram_bank = ctx.ram_banks[0]; ctx.rom_bank_x = ctx.rom_data + 0x4000; ctx.rom_bank_x2 = ctx.rom_data; @@ -286,6 +299,8 @@ u8 cart_read(u16 address){ } if((address & 0xE000) == 0xA000) { + if(cart_mbc2()) + address &= 0xE1FF; if (!ctx.ram_enabled) { return 0xFF; } @@ -294,7 +309,7 @@ u8 cart_read(u16 address){ return 0xFF; } - return ctx.ram_bank[address - 0xA000]; + return cart_mbc2() ? ctx.ram_bank[address - 0xA000] | 0xF0 : ctx.ram_bank[address - 0xA000]; } return ctx.rom_bank_x[address - 0x4000]; @@ -307,95 +322,82 @@ void cart_write(u16 address, u8 value){ return; } - if(address < 0x2000) { - ctx.ram_enabled = ((value & 0xF) == 0xA); - } - - if((address & 0xE000) == 0x2000) { - //rom bank - if(cart_mbc3()) { - value &= 0b1111111; - if(value == 0) { - value = 1; - } - ctx.rom_bank_value = value; - ctx.rom_bank_x = ctx.rom_data + (0x4000 * ctx.rom_bank_value); - }else { - //printf("Bank Value: %d\n", value); - value &= 0b11111; - if(value == 0) { - value = 1; - } - if(ctx.is_multicart) + if(cart_mbc2()) { + if(address < 0x4000){ + if(address & 0x100) { value &= 0b1111; - //printf("Bank Value after filter: %d\n", value); - switch(ctx.header->rom_size) { - case 0: value &= 0b1; break; - case 1: value &= 0b11; break; - case 2: value &= 0b111; break; - case 3: value &= 0b1111; break; - default: break; - } - ctx.rom_bank_value = value; - if(ctx.header->rom_size >= 5) { - ctx.rom_bank_x = ctx.rom_data + (0x4000 * (ctx.rom_bank_value+ctx.rom_bank_value_2)); - //printf("(REG1 >5) Banked %d\n", ctx.rom_bank_value+ctx.rom_bank_value_2); - return; - } - ctx.rom_bank_x = ctx.rom_data + (0x4000 * ctx.rom_bank_value); - //printf("(REG1 <5) Banked %d\n", ctx.rom_bank_value); - } - } - - if((address & 0xE000) == 0x4000) { - //ram bank number - if(cart_mbc1() && ctx.header->rom_size >= 5) { - if(ctx.header->rom_size == 5) - value &= 0b1; - ctx.rom_bank_value_2 = (value & 0b11) << 5; - if(ctx.is_multicart) - ctx.rom_bank_value_2 = (value & 0b11) << 4; - ctx.rom_bank_x = ctx.rom_data + (0x4000 * (ctx.rom_bank_value+ctx.rom_bank_value_2)); - //printf("(REG2 >5) Banked %d\n", ctx.rom_bank_value+ctx.rom_bank_value_2); - if(ctx.banking_mode) - ctx.rom_bank_x2 = ctx.rom_data + (0x4000 * (ctx.rom_bank_value_2)); - return; - } - ctx.ram_bank_value = value & 0b11; - if(ctx.ram_banking) { - if(cart_need_save()) { - cart_battery_save(); - } - if((ctx.header->ram_size == 2 && ctx.ram_bank_value == 0) || - (ctx.header->ram_size == 3 && ctx.ram_bank_value < 4) || - (ctx.header->ram_size == 5 && ctx.ram_bank_value < 8) || - (ctx.header->ram_size == 4)) { - ctx.ram_bank = ctx.ram_banks[ctx.ram_bank_value]; - } - - } - } - - if((address & 0xE000) == 0x6000) { - //banking mode select - if(cart_mbc1()){ - ctx.banking_mode = value & 1; - - ctx.ram_banking = ctx.banking_mode; - - if(cart_mbc1() && ctx.header->rom_size >= 5) { - if(ctx.banking_mode) { - ctx.rom_bank_value_2 = (value & 0b11) << 5; - ctx.rom_bank_x = ctx.rom_data + (0x4000 * (ctx.rom_bank_value+ctx.rom_bank_value_2)); - ctx.rom_bank_x2 = ctx.rom_data + (0x4000 * (ctx.rom_bank_value_2)); - } else { - ctx.rom_bank_x = ctx.rom_data + (0x4000 * (ctx.rom_bank_value)); - ctx.rom_bank_x2 = ctx.rom_data; + if(value == 0) { + value = 1; } + switch(ctx.header->rom_size) { + case 0: value &= 0b1; break; + case 1: value &= 0b11; break; + case 2: value &= 0b111; break; + default: break; + } + ctx.rom_bank_value = value; + ctx.rom_bank_x = ctx.rom_data + (0x4000 * ctx.rom_bank_value); + } else { + ctx.ram_enabled = ((value & 0xF) == 0xA); + } + } + } else { + if(address < 0x2000) { + ctx.ram_enabled = ((value & 0xF) == 0xA); + } + + if((address & 0xE000) == 0x2000) { + //rom bank + if(cart_mbc3()) { + value &= 0b1111111; + if(value == 0) { + value = 1; + } + ctx.rom_bank_value = value; + ctx.rom_bank_x = ctx.rom_data + (0x4000 * ctx.rom_bank_value); + }else { + //printf("Bank Value: %d\n", value); + value &= 0b11111; + if(value == 0) { + value = 1; + } + if(ctx.is_multicart) + value &= 0b1111; + //printf("Bank Value after filter: %d\n", value); + switch(ctx.header->rom_size) { + case 0: value &= 0b1; break; + case 1: value &= 0b11; break; + case 2: value &= 0b111; break; + case 3: value &= 0b1111; break; + default: break; + } + ctx.rom_bank_value = value; + if(ctx.header->rom_size >= 5) { + ctx.rom_bank_x = ctx.rom_data + (0x4000 * (ctx.rom_bank_value+ctx.rom_bank_value_2)); + //printf("(REG1 >5) Banked %d\n", ctx.rom_bank_value+ctx.rom_bank_value_2); + return; + } + ctx.rom_bank_x = ctx.rom_data + (0x4000 * ctx.rom_bank_value); + //printf("(REG1 <5) Banked %d\n", ctx.rom_bank_value); + } + } + + if((address & 0xE000) == 0x4000) { + //ram bank number + if(cart_mbc1() && ctx.header->rom_size >= 5) { + if(ctx.header->rom_size == 5) + value &= 0b1; + ctx.rom_bank_value_2 = (value & 0b11) << 5; + if(ctx.is_multicart) + ctx.rom_bank_value_2 = (value & 0b11) << 4; + ctx.rom_bank_x = ctx.rom_data + (0x4000 * (ctx.rom_bank_value+ctx.rom_bank_value_2)); + //printf("(REG2 >5) Banked %d\n", ctx.rom_bank_value+ctx.rom_bank_value_2); + if(ctx.banking_mode) + ctx.rom_bank_x2 = ctx.rom_data + (0x4000 * (ctx.rom_bank_value_2)); return; } - - if (ctx.ram_banking) { + ctx.ram_bank_value = value & 0b11; + if(ctx.ram_banking) { if(cart_need_save()) { cart_battery_save(); } @@ -405,20 +407,60 @@ void cart_write(u16 address, u8 value){ (ctx.header->ram_size == 4)) { ctx.ram_bank = ctx.ram_banks[ctx.ram_bank_value]; } - } else { - ctx.ram_bank = ctx.ram_banks[0]; + + } + } + + if((address & 0xE000) == 0x6000) { + //banking mode select + if(cart_mbc1()){ + ctx.banking_mode = value & 1; + + ctx.ram_banking = ctx.banking_mode; + + if(cart_mbc1() && ctx.header->rom_size >= 5) { + if(ctx.banking_mode) { + ctx.rom_bank_value_2 = (value & 0b11) << 5; + ctx.rom_bank_x = ctx.rom_data + (0x4000 * (ctx.rom_bank_value+ctx.rom_bank_value_2)); + ctx.rom_bank_x2 = ctx.rom_data + (0x4000 * (ctx.rom_bank_value_2)); + } else { + ctx.rom_bank_x = ctx.rom_data + (0x4000 * (ctx.rom_bank_value)); + ctx.rom_bank_x2 = ctx.rom_data; + } + return; + } + + if (ctx.ram_banking) { + if(cart_need_save()) { + cart_battery_save(); + } + if((ctx.header->ram_size == 2 && ctx.ram_bank_value == 0) || + (ctx.header->ram_size == 3 && ctx.ram_bank_value < 4) || + (ctx.header->ram_size == 5 && ctx.ram_bank_value < 8) || + (ctx.header->ram_size == 4)) { + ctx.ram_bank = ctx.ram_banks[ctx.ram_bank_value]; + } + } else { + ctx.ram_bank = ctx.ram_banks[0]; + } } } } + + if((address & 0xE000) == 0xA000) { - if(!ctx.ram_enabled) + if(cart_mbc2()) + address &= 0xE1FF; + + if(!ctx.ram_enabled){ return; + } if(!ctx.ram_bank) return; - ctx.ram_bank[address - 0xA000] = value; + ctx.ram_bank[address - 0xA000] = cart_mbc2() ? value & 0xF : value; if(ctx.battery) { ctx.need_save = true;