Support for an alternative MBC1 wiring, should solve most N-in-1 carts (Issue #3)

This commit is contained in:
Lior Halphon 2016-07-09 19:25:13 +03:00
parent c6bafe3fc3
commit bd7f8f2555
5 changed files with 58 additions and 13 deletions

View File

@ -854,9 +854,14 @@ static bool mbc(GB_gameboy_t *gb, char *arguments)
GB_log(gb, "Current mapped RAM bank: %x\n", gb->mbc_ram_bank); GB_log(gb, "Current mapped RAM bank: %x\n", gb->mbc_ram_bank);
GB_log(gb, "RAM is curently %s\n", gb->mbc_ram_enable? "enabled" : "disabled"); GB_log(gb, "RAM is curently %s\n", gb->mbc_ram_enable? "enabled" : "disabled");
} }
if (cartridge->mbc_type == GB_MBC1) { if (cartridge->mbc_type == GB_MBC1 && gb->mbc1_wiring == GB_STANDARD_MBC1_WIRING) {
GB_log(gb, "MBC1 banking mode is %s\n", gb->mbc1.mode == 1 ? "RAM" : "ROM"); GB_log(gb, "MBC1 banking mode is %s\n", gb->mbc1.mode == 1 ? "RAM" : "ROM");
} }
if (cartridge->mbc_type == GB_MBC1 && gb->mbc1_wiring == GB_MBC1M_WIRING) {
GB_log(gb, "MBC1 uses MBC1M wiring. \n");
GB_log(gb, "Current mapped ROM0 bank: %x\n", gb->mbc_rom0_bank);
GB_log(gb, "MBC1 multicart banking mode is %s\n", gb->mbc1.mode == 1 ? "enabled" : "disabled");
}
} }
else { else {

View File

@ -165,12 +165,7 @@ int GB_load_rom(GB_gameboy_t *gb, const char *path)
memset(gb->rom, 0xFF, gb->rom_size); /* Pad with 0xFFs */ memset(gb->rom, 0xFF, gb->rom_size); /* Pad with 0xFFs */
fread(gb->rom, gb->rom_size, 1, f); fread(gb->rom, gb->rom_size, 1, f);
fclose(f); fclose(f);
gb->cartridge_type = &GB_cart_defs[gb->rom[0x147]]; GB_configure_cart(gb);
if (gb->cartridge_type->has_ram) {
static const int ram_sizes[256] = {0, 0x800, 0x2000, 0x8000, 0x20000, 0x10000};
gb->mbc_ram_size = ram_sizes[gb->rom[0x149]];
gb->mbc_ram = malloc(gb->mbc_ram_size);
}
return 0; return 0;
} }

View File

@ -312,6 +312,10 @@ typedef struct GB_gameboy_s {
uint8_t *rom; uint8_t *rom;
uint32_t rom_size; uint32_t rom_size;
const GB_cartridge_t *cartridge_type; const GB_cartridge_t *cartridge_type;
enum {
GB_STANDARD_MBC1_WIRING,
GB_MBC1M_WIRING,
} mbc1_wiring;
/* Various RAMs */ /* Various RAMs */
uint8_t *ram; uint8_t *ram;

View File

@ -1,4 +1,6 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "gb.h" #include "gb.h"
const GB_cartridge_t GB_cart_defs[256] = { const GB_cartridge_t GB_cart_defs[256] = {
@ -50,14 +52,32 @@ void GB_update_mbc_mappings(GB_gameboy_t *gb)
switch (gb->cartridge_type->mbc_type) { switch (gb->cartridge_type->mbc_type) {
case GB_NO_MBC: case GB_MBC4: return; case GB_NO_MBC: case GB_MBC4: return;
case GB_MBC1: case GB_MBC1:
/* Standard MBC1 wiring: */ /* Todo: some obscure behaviors of MBC1 are not supported. See http://forums.nesdev.com/viewtopic.php?f=20&t=14099 */
if (gb->mbc1.mode == 0) { if (gb->mbc1.mode == 0) {
switch (gb->mbc1_wiring) {
case GB_STANDARD_MBC1_WIRING:
gb->mbc_rom_bank = gb->mbc1.bank_low | (gb->mbc1.bank_high << 5); gb->mbc_rom_bank = gb->mbc1.bank_low | (gb->mbc1.bank_high << 5);
gb->mbc_ram_bank = 0; gb->mbc_ram_bank = 0;
break;
case GB_MBC1M_WIRING:
gb->mbc_rom_bank = (gb->mbc1.bank_low & 0xF) | (gb->mbc1.bank_high << 4);
gb->mbc_ram_bank = 0;
gb->mbc_rom0_bank = 0;
}
} }
else { else {
switch (gb->mbc1_wiring) {
case GB_STANDARD_MBC1_WIRING:
gb->mbc_rom_bank = gb->mbc1.bank_low; gb->mbc_rom_bank = gb->mbc1.bank_low;
gb->mbc_ram_bank = gb->mbc1.bank_high; gb->mbc_ram_bank = gb->mbc1.bank_high;
break;
case GB_MBC1M_WIRING:
gb->mbc_rom_bank = (gb->mbc1.bank_low & 0xF) | (gb->mbc1.bank_high << 4);
gb->mbc_rom0_bank = gb->mbc1.bank_high << 4;
gb->mbc_ram_bank = 0;
}
} }
break; break;
case GB_MBC2: case GB_MBC2:
@ -76,3 +96,24 @@ void GB_update_mbc_mappings(GB_gameboy_t *gb)
gb->mbc_rom_bank = 1; gb->mbc_rom_bank = 1;
} }
} }
void GB_configure_cart(GB_gameboy_t *gb)
{
gb->cartridge_type = &GB_cart_defs[gb->rom[0x147]];
if (gb->cartridge_type->has_ram) {
static const int ram_sizes[256] = {0, 0x800, 0x2000, 0x8000, 0x20000, 0x10000};
gb->mbc_ram_size = ram_sizes[gb->rom[0x149]];
gb->mbc_ram = malloc(gb->mbc_ram_size);
}
/* MBC1 has at least 3 types of wiring (We currently support two (Standard and 4bit-MBC1M) of these).
See http://forums.nesdev.com/viewtopic.php?f=20&t=14099 */
/* Attempt to "guess" wiring */
if (gb->cartridge_type->mbc_type == GB_MBC1) {
if (gb->rom_size >= 0x44000 && memcmp(gb->rom + 0x104, gb->rom + 0x40104, 0x30) == 0) {
gb->mbc1_wiring = GB_MBC1M_WIRING;
}
}
}

View File

@ -4,5 +4,5 @@
extern const GB_cartridge_t GB_cart_defs[256]; extern const GB_cartridge_t GB_cart_defs[256];
void GB_update_mbc_mappings(GB_gameboy_t *gb); void GB_update_mbc_mappings(GB_gameboy_t *gb);
void GB_configure_cart(GB_gameboy_t *gb);
#endif /* MBC_h */ #endif /* MBC_h */