mirror of https://github.com/mgba-emu/mgba.git
GB MBC: Minor refactoring, basic Pocket Cam support
This commit is contained in:
parent
a4faf9f079
commit
49ccb3d080
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
91
src/gb/mbc.c
91
src/gb/mbc.c
|
@ -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;
|
||||
|
|
|
@ -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?
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue