mbc2 passing
This commit is contained in:
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@ -9,7 +9,7 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "Debug",
|
"name": "Debug",
|
||||||
"program": "${workspaceFolder}/build/gbemu/Debug/gbemu.exe",
|
"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}"
|
"cwd": "${workspaceFolder}"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
226
lib/cart.c
226
lib/cart.c
@ -13,16 +13,24 @@ bool cart_mbc1() {
|
|||||||
return BETWEEN(ctx.header->type, 1, 3);
|
return BETWEEN(ctx.header->type, 1, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool cart_mbc2() {
|
||||||
|
return BETWEEN(ctx.header->type, 5, 6);
|
||||||
|
}
|
||||||
|
|
||||||
bool cart_mbc3() {
|
bool cart_mbc3() {
|
||||||
return BETWEEN(ctx.header->type, 15, 19);
|
return BETWEEN(ctx.header->type, 15, 19);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool cart_mbc5() {
|
||||||
|
return BETWEEN(ctx.header->type, 25, 30)
|
||||||
|
}
|
||||||
|
|
||||||
bool cart_mbc() {
|
bool cart_mbc() {
|
||||||
return cart_mbc1() || cart_mbc3();
|
return cart_mbc1() || cart_mbc2() || cart_mbc3() || cart_mbc5();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cart_battery() {
|
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[] = {
|
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.ram_bank = ctx.ram_banks[0];
|
||||||
ctx.rom_bank_x = ctx.rom_data + 0x4000;
|
ctx.rom_bank_x = ctx.rom_data + 0x4000;
|
||||||
ctx.rom_bank_x2 = ctx.rom_data;
|
ctx.rom_bank_x2 = ctx.rom_data;
|
||||||
@ -286,6 +299,8 @@ u8 cart_read(u16 address){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if((address & 0xE000) == 0xA000) {
|
if((address & 0xE000) == 0xA000) {
|
||||||
|
if(cart_mbc2())
|
||||||
|
address &= 0xE1FF;
|
||||||
if (!ctx.ram_enabled) {
|
if (!ctx.ram_enabled) {
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
}
|
}
|
||||||
@ -294,7 +309,7 @@ u8 cart_read(u16 address){
|
|||||||
return 0xFF;
|
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];
|
return ctx.rom_bank_x[address - 0x4000];
|
||||||
@ -307,95 +322,82 @@ void cart_write(u16 address, u8 value){
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(address < 0x2000) {
|
if(cart_mbc2()) {
|
||||||
ctx.ram_enabled = ((value & 0xF) == 0xA);
|
if(address < 0x4000){
|
||||||
}
|
if(address & 0x100) {
|
||||||
|
|
||||||
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;
|
value &= 0b1111;
|
||||||
//printf("Bank Value after filter: %d\n", value);
|
if(value == 0) {
|
||||||
switch(ctx.header->rom_size) {
|
value = 1;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
ctx.ram_bank_value = value & 0b11;
|
||||||
if (ctx.ram_banking) {
|
if(ctx.ram_banking) {
|
||||||
if(cart_need_save()) {
|
if(cart_need_save()) {
|
||||||
cart_battery_save();
|
cart_battery_save();
|
||||||
}
|
}
|
||||||
@ -405,20 +407,60 @@ void cart_write(u16 address, u8 value){
|
|||||||
(ctx.header->ram_size == 4)) {
|
(ctx.header->ram_size == 4)) {
|
||||||
ctx.ram_bank = ctx.ram_banks[ctx.ram_bank_value];
|
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((address & 0xE000) == 0xA000) {
|
||||||
if(!ctx.ram_enabled)
|
if(cart_mbc2())
|
||||||
|
address &= 0xE1FF;
|
||||||
|
|
||||||
|
if(!ctx.ram_enabled){
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(!ctx.ram_bank)
|
if(!ctx.ram_bank)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ctx.ram_bank[address - 0xA000] = value;
|
ctx.ram_bank[address - 0xA000] = cart_mbc2() ? value & 0xF : value;
|
||||||
|
|
||||||
if(ctx.battery) {
|
if(ctx.battery) {
|
||||||
ctx.need_save = true;
|
ctx.need_save = true;
|
||||||
|
Reference in New Issue
Block a user