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_MMM01 = 0x10,
|
||||||
GB_HuC1 = 0x11,
|
GB_HuC1 = 0x11,
|
||||||
GB_HuC3 = 0x12,
|
GB_HuC3 = 0x12,
|
||||||
|
GB_POCKETCAM = 0x13,
|
||||||
GB_MBC3_RTC = 0x103,
|
GB_MBC3_RTC = 0x103,
|
||||||
GB_MBC5_RUMBLE = 0x105
|
GB_MBC5_RUMBLE = 0x105
|
||||||
};
|
};
|
||||||
|
|
|
@ -36,7 +36,6 @@ struct GBMBCRTCSaveBuffer {
|
||||||
void GBMBCRTCRead(struct GB* gb);
|
void GBMBCRTCRead(struct GB* gb);
|
||||||
void GBMBCRTCWrite(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);
|
void GBMBC7Write(struct GBMemory*, uint16_t address, uint8_t value);
|
||||||
|
|
||||||
CXX_GUARD_END
|
CXX_GUARD_END
|
||||||
|
|
|
@ -63,7 +63,8 @@ enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GBMemory;
|
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_BITFIELD(GBMBC7Field, uint8_t);
|
||||||
DECL_BIT(GBMBC7Field, SK, 6);
|
DECL_BIT(GBMBC7Field, SK, 6);
|
||||||
|
@ -98,9 +99,14 @@ struct GBMBC7State {
|
||||||
GBMBC7Field field;
|
GBMBC7Field field;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct GBPocketCamState {
|
||||||
|
bool registersActive;
|
||||||
|
};
|
||||||
|
|
||||||
union GBMBCState {
|
union GBMBCState {
|
||||||
struct GBMBC1State mbc1;
|
struct GBMBC1State mbc1;
|
||||||
struct GBMBC7State mbc7;
|
struct GBMBC7State mbc7;
|
||||||
|
struct GBPocketCamState pocketCam;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mRotationSource;
|
struct mRotationSource;
|
||||||
|
@ -109,7 +115,8 @@ struct GBMemory {
|
||||||
uint8_t* romBase;
|
uint8_t* romBase;
|
||||||
uint8_t* romBank;
|
uint8_t* romBank;
|
||||||
enum GBMemoryBankControllerType mbcType;
|
enum GBMemoryBankControllerType mbcType;
|
||||||
GBMemoryBankController mbc;
|
GBMemoryBankControllerWrite mbcWrite;
|
||||||
|
GBMemoryBankControllerRead mbcRead;
|
||||||
union GBMBCState mbcState;
|
union GBMBCState mbcState;
|
||||||
int currentBank;
|
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 _GBMBC6(struct GB*, uint16_t address, uint8_t value);
|
||||||
static void _GBMBC7(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 _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) {
|
void GBMBCSwitchBank(struct GB* gb, int bank) {
|
||||||
size_t bankStart = bank * GB_SIZE_CART_BANK0;
|
size_t bankStart = bank * GB_SIZE_CART_BANK0;
|
||||||
|
@ -148,6 +152,12 @@ void GBMBCInit(struct GB* gb) {
|
||||||
case 0x22:
|
case 0x22:
|
||||||
gb->memory.mbcType = GB_MBC7;
|
gb->memory.mbcType = GB_MBC7;
|
||||||
break;
|
break;
|
||||||
|
case 0xFC:
|
||||||
|
gb->memory.mbcType = GB_POCKETCAM;
|
||||||
|
break;
|
||||||
|
case 0xFD:
|
||||||
|
gb->memory.mbcType = GB_HuC1;
|
||||||
|
break;
|
||||||
case 0xFE:
|
case 0xFE:
|
||||||
gb->memory.mbcType = GB_HuC3;
|
gb->memory.mbcType = GB_HuC3;
|
||||||
break;
|
break;
|
||||||
|
@ -156,51 +166,57 @@ void GBMBCInit(struct GB* gb) {
|
||||||
} else {
|
} else {
|
||||||
gb->memory.mbcType = GB_MBC_NONE;
|
gb->memory.mbcType = GB_MBC_NONE;
|
||||||
}
|
}
|
||||||
|
gb->memory.mbcRead = NULL;
|
||||||
switch (gb->memory.mbcType) {
|
switch (gb->memory.mbcType) {
|
||||||
case GB_MBC_NONE:
|
case GB_MBC_NONE:
|
||||||
gb->memory.mbc = _GBMBCNone;
|
gb->memory.mbcWrite = _GBMBCNone;
|
||||||
break;
|
break;
|
||||||
case GB_MBC1:
|
case GB_MBC1:
|
||||||
gb->memory.mbc = _GBMBC1;
|
gb->memory.mbcWrite = _GBMBC1;
|
||||||
break;
|
break;
|
||||||
case GB_MBC2:
|
case GB_MBC2:
|
||||||
gb->memory.mbc = _GBMBC2;
|
gb->memory.mbcWrite = _GBMBC2;
|
||||||
gb->sramSize = 0x200;
|
gb->sramSize = 0x200;
|
||||||
break;
|
break;
|
||||||
case GB_MBC3:
|
case GB_MBC3:
|
||||||
gb->memory.mbc = _GBMBC3;
|
gb->memory.mbcWrite = _GBMBC3;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
mLOG(GB_MBC, WARN, "Unknown MBC type: %02X", cart->type);
|
mLOG(GB_MBC, WARN, "Unknown MBC type: %02X", cart->type);
|
||||||
// Fall through
|
// Fall through
|
||||||
case GB_MBC5:
|
case GB_MBC5:
|
||||||
gb->memory.mbc = _GBMBC5;
|
gb->memory.mbcWrite = _GBMBC5;
|
||||||
break;
|
break;
|
||||||
case GB_MBC6:
|
case GB_MBC6:
|
||||||
mLOG(GB_MBC, WARN, "unimplemented MBC: MBC6");
|
mLOG(GB_MBC, WARN, "unimplemented MBC: MBC6");
|
||||||
gb->memory.mbc = _GBMBC6;
|
gb->memory.mbcWrite = _GBMBC6;
|
||||||
break;
|
break;
|
||||||
case GB_MBC7:
|
case GB_MBC7:
|
||||||
gb->memory.mbc = _GBMBC7;
|
gb->memory.mbcWrite = _GBMBC7;
|
||||||
|
gb->memory.mbcRead = _GBMBC7Read;
|
||||||
gb->sramSize = GB_SIZE_EXTERNAL_RAM;
|
gb->sramSize = GB_SIZE_EXTERNAL_RAM;
|
||||||
break;
|
break;
|
||||||
case GB_MMM01:
|
case GB_MMM01:
|
||||||
mLOG(GB_MBC, WARN, "unimplemented MBC: MMM01");
|
mLOG(GB_MBC, WARN, "unimplemented MBC: MMM01");
|
||||||
gb->memory.mbc = _GBMBC1;
|
gb->memory.mbcWrite = _GBMBC1;
|
||||||
break;
|
break;
|
||||||
case GB_HuC1:
|
case GB_HuC1:
|
||||||
mLOG(GB_MBC, WARN, "unimplemented MBC: HuC-1");
|
mLOG(GB_MBC, WARN, "unimplemented MBC: HuC-1");
|
||||||
gb->memory.mbc = _GBMBC1;
|
gb->memory.mbcWrite = _GBMBC1;
|
||||||
break;
|
break;
|
||||||
case GB_HuC3:
|
case GB_HuC3:
|
||||||
gb->memory.mbc = _GBHuC3;
|
gb->memory.mbcWrite = _GBHuC3;
|
||||||
break;
|
break;
|
||||||
case GB_MBC3_RTC:
|
case GB_MBC3_RTC:
|
||||||
memset(gb->memory.rtcRegs, 0, sizeof(gb->memory.rtcRegs));
|
memset(gb->memory.rtcRegs, 0, sizeof(gb->memory.rtcRegs));
|
||||||
gb->memory.mbc = _GBMBC3;
|
gb->memory.mbcWrite = _GBMBC3;
|
||||||
break;
|
break;
|
||||||
case GB_MBC5_RUMBLE:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,7 +366,8 @@ void _GBMBC2(struct GB* gb, uint16_t address, uint8_t value) {
|
||||||
// TODO
|
// TODO
|
||||||
mLOG(GB_MBC, STUB, "MBC2 unknown address: %04X:%02X", address, value);
|
mLOG(GB_MBC, STUB, "MBC2 unknown address: %04X:%02X", address, value);
|
||||||
break;
|
break;
|
||||||
}}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void _GBMBC3(struct GB* gb, uint16_t address, uint8_t value) {
|
void _GBMBC3(struct GB* gb, uint16_t address, uint8_t value) {
|
||||||
struct GBMemory* memory = &gb->memory;
|
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;
|
struct GBMBC7State* mbc7 = &memory->mbcState.mbc7;
|
||||||
switch (address & 0xF0) {
|
switch (address & 0xF0) {
|
||||||
case 0x00:
|
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) {
|
void GBMBCRTCRead(struct GB* gb) {
|
||||||
struct GBMBCRTCSaveBuffer rtcBuffer;
|
struct GBMBCRTCSaveBuffer rtcBuffer;
|
||||||
struct VFile* vf = gb->sramVf;
|
struct VFile* vf = gb->sramVf;
|
||||||
|
|
|
@ -99,7 +99,8 @@ void GBMemoryInit(struct GB* gb) {
|
||||||
gb->memory.romSize = 0;
|
gb->memory.romSize = 0;
|
||||||
gb->memory.sram = 0;
|
gb->memory.sram = 0;
|
||||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||||
gb->memory.mbc = 0;
|
gb->memory.mbcRead = NULL;
|
||||||
|
gb->memory.mbcWrite = NULL;
|
||||||
|
|
||||||
gb->memory.rtc = NULL;
|
gb->memory.rtc = NULL;
|
||||||
|
|
||||||
|
@ -215,10 +216,10 @@ uint8_t GBLoad8(struct LR35902Core* cpu, uint16_t address) {
|
||||||
case GB_REGION_EXTERNAL_RAM + 1:
|
case GB_REGION_EXTERNAL_RAM + 1:
|
||||||
if (memory->rtcAccess) {
|
if (memory->rtcAccess) {
|
||||||
return memory->rtcRegs[memory->activeRtcReg];
|
return memory->rtcRegs[memory->activeRtcReg];
|
||||||
|
} else if (memory->mbcRead) {
|
||||||
|
return memory->mbcRead(memory, address);
|
||||||
} else if (memory->sramAccess) {
|
} else if (memory->sramAccess) {
|
||||||
return memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)];
|
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) {
|
} else if (memory->mbcType == GB_HuC3) {
|
||||||
return 0x01; // TODO: Is this supposed to be the current SRAM bank?
|
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 + 1:
|
||||||
case GB_REGION_CART_BANK1 + 2:
|
case GB_REGION_CART_BANK1 + 2:
|
||||||
case GB_REGION_CART_BANK1 + 3:
|
case GB_REGION_CART_BANK1 + 3:
|
||||||
memory->mbc(gb, address, value);
|
memory->mbcWrite(gb, address, value);
|
||||||
cpu->memory.setActiveRegion(cpu, cpu->pc);
|
cpu->memory.setActiveRegion(cpu, cpu->pc);
|
||||||
return;
|
return;
|
||||||
case GB_REGION_VRAM:
|
case GB_REGION_VRAM:
|
||||||
|
@ -391,8 +392,8 @@ uint8_t GBView8(struct LR35902Core* cpu, uint16_t address, int segment) {
|
||||||
} else {
|
} else {
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
}
|
}
|
||||||
} else if (memory->mbcType == GB_MBC7) {
|
} else if (memory->mbcRead) {
|
||||||
return GBMBC7Read(memory, address);
|
return memory->mbcRead(memory, address);
|
||||||
} else if (memory->mbcType == GB_HuC3) {
|
} else if (memory->mbcType == GB_HuC3) {
|
||||||
return 0x01; // TODO: Is this supposed to be the current SRAM bank?
|
return 0x01; // TODO: Is this supposed to be the current SRAM bank?
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue