GB MBC: Minor refactoring, basic Pocket Cam support

This commit is contained in:
Vicki Pfau 2017-06-07 23:06:28 -07:00
parent a4faf9f079
commit 49ccb3d080
5 changed files with 94 additions and 23 deletions

View File

@ -30,6 +30,7 @@ enum GBMemoryBankControllerType {
GB_MMM01 = 0x10,
GB_HuC1 = 0x11,
GB_HuC3 = 0x12,
GB_POCKETCAM = 0x13,
GB_MBC3_RTC = 0x103,
GB_MBC5_RUMBLE = 0x105
};

View File

@ -36,7 +36,6 @@ struct GBMBCRTCSaveBuffer {
void GBMBCRTCRead(struct GB* gb);
void GBMBCRTCWrite(struct GB* gb);
uint8_t GBMBC7Read(struct GBMemory*, uint16_t address);
void GBMBC7Write(struct GBMemory*, uint16_t address, uint8_t value);
CXX_GUARD_END

View File

@ -63,7 +63,8 @@ enum {
};
struct GBMemory;
typedef void (*GBMemoryBankController)(struct GB*, uint16_t address, uint8_t value);
typedef void (*GBMemoryBankControllerWrite)(struct GB*, uint16_t address, uint8_t value);
typedef uint8_t (*GBMemoryBankControllerRead)(struct GBMemory*, uint16_t address);
DECL_BITFIELD(GBMBC7Field, uint8_t);
DECL_BIT(GBMBC7Field, SK, 6);
@ -98,9 +99,14 @@ struct GBMBC7State {
GBMBC7Field field;
};
struct GBPocketCamState {
bool registersActive;
};
union GBMBCState {
struct GBMBC1State mbc1;
struct GBMBC7State mbc7;
struct GBPocketCamState pocketCam;
};
struct mRotationSource;
@ -109,7 +115,8 @@ struct GBMemory {
uint8_t* romBase;
uint8_t* romBank;
enum GBMemoryBankControllerType mbcType;
GBMemoryBankController mbc;
GBMemoryBankControllerWrite mbcWrite;
GBMemoryBankControllerRead mbcRead;
union GBMBCState mbcState;
int currentBank;

View File

@ -28,6 +28,10 @@ static void _GBMBC5(struct GB*, uint16_t address, uint8_t value);
static void _GBMBC6(struct GB*, uint16_t address, uint8_t value);
static void _GBMBC7(struct GB*, uint16_t address, uint8_t value);
static void _GBHuC3(struct GB*, uint16_t address, uint8_t value);
static void _GBPocketCam(struct GB* gb, uint16_t address, uint8_t value);
static uint8_t _GBMBC7Read(struct GBMemory*, uint16_t address);
static uint8_t _GBPocketCamRead(struct GBMemory*, uint16_t address);
void GBMBCSwitchBank(struct GB* gb, int bank) {
size_t bankStart = bank * GB_SIZE_CART_BANK0;
@ -148,6 +152,12 @@ void GBMBCInit(struct GB* gb) {
case 0x22:
gb->memory.mbcType = GB_MBC7;
break;
case 0xFC:
gb->memory.mbcType = GB_POCKETCAM;
break;
case 0xFD:
gb->memory.mbcType = GB_HuC1;
break;
case 0xFE:
gb->memory.mbcType = GB_HuC3;
break;
@ -156,51 +166,57 @@ void GBMBCInit(struct GB* gb) {
} else {
gb->memory.mbcType = GB_MBC_NONE;
}
gb->memory.mbcRead = NULL;
switch (gb->memory.mbcType) {
case GB_MBC_NONE:
gb->memory.mbc = _GBMBCNone;
gb->memory.mbcWrite = _GBMBCNone;
break;
case GB_MBC1:
gb->memory.mbc = _GBMBC1;
gb->memory.mbcWrite = _GBMBC1;
break;
case GB_MBC2:
gb->memory.mbc = _GBMBC2;
gb->memory.mbcWrite = _GBMBC2;
gb->sramSize = 0x200;
break;
case GB_MBC3:
gb->memory.mbc = _GBMBC3;
gb->memory.mbcWrite = _GBMBC3;
break;
default:
mLOG(GB_MBC, WARN, "Unknown MBC type: %02X", cart->type);
// Fall through
case GB_MBC5:
gb->memory.mbc = _GBMBC5;
gb->memory.mbcWrite = _GBMBC5;
break;
case GB_MBC6:
mLOG(GB_MBC, WARN, "unimplemented MBC: MBC6");
gb->memory.mbc = _GBMBC6;
gb->memory.mbcWrite = _GBMBC6;
break;
case GB_MBC7:
gb->memory.mbc = _GBMBC7;
gb->memory.mbcWrite = _GBMBC7;
gb->memory.mbcRead = _GBMBC7Read;
gb->sramSize = GB_SIZE_EXTERNAL_RAM;
break;
case GB_MMM01:
mLOG(GB_MBC, WARN, "unimplemented MBC: MMM01");
gb->memory.mbc = _GBMBC1;
gb->memory.mbcWrite = _GBMBC1;
break;
case GB_HuC1:
mLOG(GB_MBC, WARN, "unimplemented MBC: HuC-1");
gb->memory.mbc = _GBMBC1;
gb->memory.mbcWrite = _GBMBC1;
break;
case GB_HuC3:
gb->memory.mbc = _GBHuC3;
gb->memory.mbcWrite = _GBHuC3;
break;
case GB_MBC3_RTC:
memset(gb->memory.rtcRegs, 0, sizeof(gb->memory.rtcRegs));
gb->memory.mbc = _GBMBC3;
gb->memory.mbcWrite = _GBMBC3;
break;
case GB_MBC5_RUMBLE:
gb->memory.mbc = _GBMBC5;
gb->memory.mbcWrite = _GBMBC5;
break;
case GB_POCKETCAM:
gb->memory.mbcWrite = _GBPocketCam;
gb->memory.mbcRead = _GBPocketCamRead;
break;
}
@ -350,7 +366,8 @@ void _GBMBC2(struct GB* gb, uint16_t address, uint8_t value) {
// TODO
mLOG(GB_MBC, STUB, "MBC2 unknown address: %04X:%02X", address, value);
break;
}}
}
}
void _GBMBC3(struct GB* gb, uint16_t address, uint8_t value) {
struct GBMemory* memory = &gb->memory;
@ -466,7 +483,7 @@ void _GBMBC7(struct GB* gb, uint16_t address, uint8_t value) {
}
}
uint8_t GBMBC7Read(struct GBMemory* memory, uint16_t address) {
uint8_t _GBMBC7Read(struct GBMemory* memory, uint16_t address) {
struct GBMBC7State* mbc7 = &memory->mbcState.mbc7;
switch (address & 0xF0) {
case 0x00:
@ -674,6 +691,52 @@ void _GBHuC3(struct GB* gb, uint16_t address, uint8_t value) {
}
}
void _GBPocketCam(struct GB* gb, uint16_t address, uint8_t value) {
struct GBMemory* memory = &gb->memory;
int bank = value & 0x3F;
switch (address >> 13) {
case 0x0:
switch (value) {
case 0:
memory->sramAccess = false;
break;
case 0xA:
memory->sramAccess = true;
GBMBCSwitchSramBank(gb, memory->sramCurrentBank);
break;
default:
// TODO
mLOG(GB_MBC, STUB, "Pocket Cam unknown value %02X", value);
break;
}
break;
case 0x1:
GBMBCSwitchBank(gb, bank);
break;
case 0x2:
if (value < 0x10) {
GBMBCSwitchSramBank(gb, value);
memory->mbcState.pocketCam.registersActive = false;
} else {
memory->mbcState.pocketCam.registersActive = true;
}
break;
default:
mLOG(GB_MBC, STUB, "Pocket Cam unknown address: %04X:%02X", address, value);
break;
}
}
uint8_t _GBPocketCamRead(struct GBMemory* memory, uint16_t address) {
if (memory->mbcState.pocketCam.registersActive) {
return 0;
}
if (!memory->sramAccess) {
return 0xFF;
}
return memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)];
}
void GBMBCRTCRead(struct GB* gb) {
struct GBMBCRTCSaveBuffer rtcBuffer;
struct VFile* vf = gb->sramVf;

View File

@ -99,7 +99,8 @@ void GBMemoryInit(struct GB* gb) {
gb->memory.romSize = 0;
gb->memory.sram = 0;
gb->memory.mbcType = GB_MBC_AUTODETECT;
gb->memory.mbc = 0;
gb->memory.mbcRead = NULL;
gb->memory.mbcWrite = NULL;
gb->memory.rtc = NULL;
@ -215,10 +216,10 @@ uint8_t GBLoad8(struct LR35902Core* cpu, uint16_t address) {
case GB_REGION_EXTERNAL_RAM + 1:
if (memory->rtcAccess) {
return memory->rtcRegs[memory->activeRtcReg];
} else if (memory->mbcRead) {
return memory->mbcRead(memory, address);
} else if (memory->sramAccess) {
return memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)];
} else if (memory->mbcType == GB_MBC7) {
return GBMBC7Read(memory, address);
} else if (memory->mbcType == GB_HuC3) {
return 0x01; // TODO: Is this supposed to be the current SRAM bank?
}
@ -274,7 +275,7 @@ void GBStore8(struct LR35902Core* cpu, uint16_t address, int8_t value) {
case GB_REGION_CART_BANK1 + 1:
case GB_REGION_CART_BANK1 + 2:
case GB_REGION_CART_BANK1 + 3:
memory->mbc(gb, address, value);
memory->mbcWrite(gb, address, value);
cpu->memory.setActiveRegion(cpu, cpu->pc);
return;
case GB_REGION_VRAM:
@ -391,8 +392,8 @@ uint8_t GBView8(struct LR35902Core* cpu, uint16_t address, int segment) {
} else {
return 0xFF;
}
} else if (memory->mbcType == GB_MBC7) {
return GBMBC7Read(memory, address);
} else if (memory->mbcRead) {
return memory->mbcRead(memory, address);
} else if (memory->mbcType == GB_HuC3) {
return 0x01; // TODO: Is this supposed to be the current SRAM bank?
}