Permalink
Browse files

GB MBC: Add MBC6 SRAM support

  • Loading branch information...
endrift committed Apr 19, 2018
1 parent f23f221 commit 4a10ea2f699d0d2bade8df17d513ba5f90bef949
Showing with 65 additions and 3 deletions.
  1. +1 −0 include/mgba/internal/gb/mbc.h
  2. +6 −0 include/mgba/internal/gb/memory.h
  3. +55 −3 src/gb/mbc.c
  4. +3 −0 src/gb/memory.c
@@ -21,6 +21,7 @@ void GBMBCSwitchBank(struct GB* gb, int bank);
void GBMBCSwitchBank0(struct GB* gb, int bank);
void GBMBCSwitchHalfBank(struct GB* gb, int half, int bank);
void GBMBCSwitchSramBank(struct GB* gb, int bank);
+void GBMBCSwitchSramHalfBank(struct GB* gb, int half, int bank);
enum GBCam {
GBCAM_WIDTH = 128,
@@ -26,6 +26,8 @@ enum {
GB_BASE_CART_HALFBANK2 = 0x6000,
GB_BASE_VRAM = 0x8000,
GB_BASE_EXTERNAL_RAM = 0xA000,
+ GB_BASE_EXTERNAL_RAM_HALFBANK0 = 0xA000,
+ GB_BASE_EXTERNAL_RAM_HALFBANK1 = 0xB000,
GB_BASE_WORKING_RAM_BANK0 = 0xC000,
GB_BASE_WORKING_RAM_BANK1 = 0xD000,
GB_BASE_OAM = 0xFE00,
@@ -53,6 +55,7 @@ enum {
GB_SIZE_VRAM = 0x4000,
GB_SIZE_VRAM_BANK0 = 0x2000,
GB_SIZE_EXTERNAL_RAM = 0x2000,
+ GB_SIZE_EXTERNAL_RAM_HALFBANK = 0x1000,
GB_SIZE_WORKING_RAM = 0x8000,
GB_SIZE_WORKING_RAM_BANK0 = 0x1000,
GB_SIZE_OAM = 0xA0,
@@ -110,6 +113,9 @@ struct GBMBC1State {
struct GBMBC6State {
int currentBank1;
uint8_t* romBank1;
+ bool sramAccess;
+ int currentSramBank1;
+ uint8_t* sramBank1;
};
struct GBMBC7State {
View
@@ -32,6 +32,7 @@ static void _GBPocketCam(struct GB* gb, uint16_t address, uint8_t value);
static void _GBTAMA5(struct GB* gb, uint16_t address, uint8_t value);
static uint8_t _GBMBC2Read(struct GBMemory*, uint16_t address);
+static uint8_t _GBMBC6Read(struct GBMemory*, uint16_t address);
static uint8_t _GBMBC7Read(struct GBMemory*, uint16_t address);
static void _GBMBC7Write(struct GBMemory* memory, uint16_t address, uint8_t value);
@@ -114,6 +115,22 @@ void GBMBCSwitchSramBank(struct GB* gb, int bank) {
gb->memory.sramCurrentBank = bank;
}
+void GBMBCSwitchSramHalfBank(struct GB* gb, int half, int bank) {
+ size_t bankStart = bank * GB_SIZE_EXTERNAL_RAM_HALFBANK;
+ if (bankStart + GB_SIZE_EXTERNAL_RAM_HALFBANK > gb->sramSize) {
+ mLOG(GB_MBC, GAME_ERROR, "Attempting to switch to an invalid RAM bank: %0X", bank);
+ bankStart &= (gb->sramSize - 1);
+ bank = bankStart / GB_SIZE_EXTERNAL_RAM_HALFBANK;
+ }
+ if (!half) {
+ gb->memory.sramBank = &gb->memory.sram[bankStart];
+ gb->memory.sramCurrentBank = bank;
+ } else {
+ gb->memory.mbcState.mbc6.sramBank1 = &gb->memory.sram[bankStart];
+ gb->memory.mbcState.mbc6.currentSramBank1 = bank;
+ }
+}
+
void GBMBCInit(struct GB* gb) {
const struct GBCartridge* cart = (const struct GBCartridge*) &gb->memory.rom[0x100];
if (gb->memory.rom) {
@@ -230,6 +247,7 @@ void GBMBCInit(struct GB* gb) {
case GB_MBC6:
mLOG(GB_MBC, WARN, "unimplemented MBC: MBC6");
gb->memory.mbcWrite = _GBMBC6;
+ gb->memory.mbcRead = _GBMBC6Read;
break;
case GB_MBC7:
gb->memory.mbcWrite = _GBMBC7;
@@ -536,18 +554,23 @@ void _GBMBC6(struct GB* gb, uint16_t address, uint8_t value) {
case 0:
switch (value) {
case 0:
- memory->sramAccess = false;
+ memory->mbcState.mbc6.sramAccess = false;
break;
case 0xA:
- memory->sramAccess = true;
- GBMBCSwitchSramBank(gb, memory->sramCurrentBank);
+ memory->mbcState.mbc6.sramAccess = true;
break;
default:
// TODO
mLOG(GB_MBC, STUB, "MBC6 unknown value %02X", value);
break;
}
break;
+ case 0x1:
+ GBMBCSwitchSramHalfBank(gb, 0, bank);
+ break;
+ case 0x2:
+ GBMBCSwitchSramHalfBank(gb, 1, bank);
+ break;
case 0x8:
case 0x9:
GBMBCSwitchHalfBank(gb, 0, bank);
@@ -556,12 +579,41 @@ void _GBMBC6(struct GB* gb, uint16_t address, uint8_t value) {
case 0xD:
GBMBCSwitchHalfBank(gb, 1, bank);
break;
+ case 0x28:
+ case 0x29:
+ case 0x2A:
+ case 0x2B:
+ if (memory->mbcState.mbc6.sramAccess) {
+ memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM_HALFBANK - 1)] = value;
+ }
+ break;
+ case 0x2C:
+ case 0x2D:
+ case 0x2E:
+ case 0x2F:
+ if (memory->mbcState.mbc6.sramAccess) {
+ memory->mbcState.mbc6.sramBank1[address & (GB_SIZE_EXTERNAL_RAM_HALFBANK - 1)] = value;
+ }
+ break;
default:
mLOG(GB_MBC, STUB, "MBC6 unknown address: %04X:%02X", address, value);
break;
}
}
+uint8_t _GBMBC6Read(struct GBMemory* memory, uint16_t address) {
+ if (!memory->mbcState.mbc6.sramAccess) {
+ return 0xFF;
+ }
+ switch (address >> 12) {
+ case 0xA:
+ return memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM_HALFBANK - 1)];
+ case 0xB:
+ return memory->mbcState.mbc6.sramBank1[address & (GB_SIZE_EXTERNAL_RAM_HALFBANK - 1)];
+ }
+ return 0xFF;
+}
+
void _GBMBC7(struct GB* gb, uint16_t address, uint8_t value) {
int bank = value & 0x7F;
switch (address >> 13) {
View
@@ -183,6 +183,9 @@ void GBMemoryReset(struct GB* gb) {
case GB_MBC6:
GBMBCSwitchHalfBank(gb, 0, 2);
GBMBCSwitchHalfBank(gb, 1, 3);
+ gb->memory.mbcState.mbc6.sramAccess = false;
+ GBMBCSwitchSramHalfBank(gb, 0, 0);
+ GBMBCSwitchSramHalfBank(gb, 0, 1);
break;
default:
memset(&gb->memory.mbcState, 0, sizeof(gb->memory.mbcState));

0 comments on commit 4a10ea2

Please sign in to comment.