mirror of https://github.com/mgba-emu/mgba.git
GB MBC: Initial HuC-3 save format
This commit is contained in:
parent
c829cd2e70
commit
26aea8544f
2
CHANGES
2
CHANGES
|
@ -7,7 +7,7 @@ Features:
|
||||||
- Cheat code support in homebrew ports
|
- Cheat code support in homebrew ports
|
||||||
- Acclerometer and gyro support for controllers on PC
|
- Acclerometer and gyro support for controllers on PC
|
||||||
- Support for combo "Super Game Boy Color" SGB + GBC ROM hacks
|
- Support for combo "Super Game Boy Color" SGB + GBC ROM hacks
|
||||||
- Improved support for HuC-3 mapper
|
- Improved support for HuC-3 mapper, including RTC
|
||||||
- Support for 64 kiB SRAM saves used in some bootlegs
|
- Support for 64 kiB SRAM saves used in some bootlegs
|
||||||
- Discord Rich Presence now supports time elapsed
|
- Discord Rich Presence now supports time elapsed
|
||||||
- Additional scaling shaders
|
- Additional scaling shaders
|
||||||
|
|
|
@ -42,9 +42,18 @@ struct GBMBCRTCSaveBuffer {
|
||||||
uint32_t latchedDaysHi;
|
uint32_t latchedDaysHi;
|
||||||
uint64_t unixTime;
|
uint64_t unixTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct GBMBCHuC3SaveBuffer {
|
||||||
|
uint8_t regs[0x80];
|
||||||
|
uint64_t latchedUnix;
|
||||||
|
};
|
||||||
|
|
||||||
void GBMBCRTCRead(struct GB* gb);
|
void GBMBCRTCRead(struct GB* gb);
|
||||||
void GBMBCRTCWrite(struct GB* gb);
|
void GBMBCRTCWrite(struct GB* gb);
|
||||||
|
|
||||||
|
void GBMBCHuC3Read(struct GB* gb);
|
||||||
|
void GBMBCHuC3Write(struct GB* gb);
|
||||||
|
|
||||||
CXX_GUARD_END
|
CXX_GUARD_END
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
12
src/gb/gb.c
12
src/gb/gb.c
|
@ -143,8 +143,12 @@ void GBYankROM(struct GB* gb) {
|
||||||
static void GBSramDeinit(struct GB* gb) {
|
static void GBSramDeinit(struct GB* gb) {
|
||||||
if (gb->sramVf) {
|
if (gb->sramVf) {
|
||||||
gb->sramVf->unmap(gb->sramVf, gb->memory.sram, gb->sramSize);
|
gb->sramVf->unmap(gb->sramVf, gb->memory.sram, gb->sramSize);
|
||||||
if (gb->memory.mbcType == GB_MBC3_RTC && gb->sramVf == gb->sramRealVf) {
|
if (gb->sramVf == gb->sramRealVf) {
|
||||||
GBMBCRTCWrite(gb);
|
if (gb->memory.mbcType == GB_MBC3_RTC) {
|
||||||
|
GBMBCRTCWrite(gb);
|
||||||
|
} else if (gb->memory.mbcType == GB_HuC3) {
|
||||||
|
GBMBCHuC3Write(gb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
gb->sramVf = NULL;
|
gb->sramVf = NULL;
|
||||||
} else if (gb->memory.sram) {
|
} else if (gb->memory.sram) {
|
||||||
|
@ -163,6 +167,8 @@ bool GBLoadSave(struct GB* gb, struct VFile* vf) {
|
||||||
|
|
||||||
if (gb->memory.mbcType == GB_MBC3_RTC) {
|
if (gb->memory.mbcType == GB_MBC3_RTC) {
|
||||||
GBMBCRTCRead(gb);
|
GBMBCRTCRead(gb);
|
||||||
|
} else if (gb->memory.mbcType == GB_HuC3) {
|
||||||
|
GBMBCHuC3Read(gb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return vf;
|
return vf;
|
||||||
|
@ -246,6 +252,8 @@ void GBSramClean(struct GB* gb, uint32_t frameCount) {
|
||||||
}
|
}
|
||||||
if (gb->memory.mbcType == GB_MBC3_RTC) {
|
if (gb->memory.mbcType == GB_MBC3_RTC) {
|
||||||
GBMBCRTCWrite(gb);
|
GBMBCRTCWrite(gb);
|
||||||
|
} else if (gb->memory.mbcType == GB_HuC3) {
|
||||||
|
GBMBCHuC3Write(gb);
|
||||||
}
|
}
|
||||||
if (gb->sramVf == gb->sramRealVf) {
|
if (gb->sramVf == gb->sramRealVf) {
|
||||||
if (gb->memory.sram && gb->sramVf->sync(gb->sramVf, gb->memory.sram, gb->sramSize)) {
|
if (gb->memory.sram && gb->sramVf->sync(gb->sramVf, gb->memory.sram, gb->sramSize)) {
|
||||||
|
|
59
src/gb/mbc.c
59
src/gb/mbc.c
|
@ -440,6 +440,8 @@ void GBMBCInit(struct GB* gb) {
|
||||||
|
|
||||||
if (gb->memory.mbcType == GB_MBC3_RTC) {
|
if (gb->memory.mbcType == GB_MBC3_RTC) {
|
||||||
GBMBCRTCRead(gb);
|
GBMBCRTCRead(gb);
|
||||||
|
} else if (gb->memory.mbcType == GB_HuC3) {
|
||||||
|
GBMBCHuC3Read(gb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1692,6 +1694,21 @@ uint8_t _GBHitekRead(struct GBMemory* memory, uint16_t address) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _appendSaveSuffix(struct GB* gb, const void* buffer, size_t size) {
|
||||||
|
struct VFile* vf = gb->sramVf;
|
||||||
|
if ((size_t) vf->size(vf) < gb->sramSize + size) {
|
||||||
|
// Writing past the end of the file can invalidate the file mapping
|
||||||
|
vf->unmap(vf, gb->memory.sram, gb->sramSize);
|
||||||
|
gb->memory.sram = NULL;
|
||||||
|
}
|
||||||
|
vf->seek(vf, gb->sramSize, SEEK_SET);
|
||||||
|
vf->write(vf, buffer, size);
|
||||||
|
if (!gb->memory.sram) {
|
||||||
|
gb->memory.sram = vf->map(vf, gb->sramSize, MAP_WRITE);
|
||||||
|
GBMBCSwitchSramBank(gb, gb->memory.sramCurrentBank);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
@ -1735,15 +1752,41 @@ void GBMBCRTCWrite(struct GB* gb) {
|
||||||
STORE_32LE(gb->memory.rtcRegs[4], 0, &rtcBuffer.latchedDaysHi);
|
STORE_32LE(gb->memory.rtcRegs[4], 0, &rtcBuffer.latchedDaysHi);
|
||||||
STORE_64LE(gb->memory.rtcLastLatch, 0, &rtcBuffer.unixTime);
|
STORE_64LE(gb->memory.rtcLastLatch, 0, &rtcBuffer.unixTime);
|
||||||
|
|
||||||
if ((size_t) vf->size(vf) < gb->sramSize + sizeof(rtcBuffer)) {
|
_appendSaveSuffix(gb, &rtcBuffer, sizeof(rtcBuffer));
|
||||||
// Writing past the end of the file can invalidate the file mapping
|
}
|
||||||
vf->unmap(vf, gb->memory.sram, gb->sramSize);
|
|
||||||
gb->memory.sram = NULL;
|
void GBMBCHuC3Read(struct GB* gb) {
|
||||||
|
struct GBMBCHuC3SaveBuffer buffer;
|
||||||
|
struct VFile* vf = gb->sramVf;
|
||||||
|
if (!vf) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
vf->seek(vf, gb->sramSize, SEEK_SET);
|
vf->seek(vf, gb->sramSize, SEEK_SET);
|
||||||
vf->write(vf, &rtcBuffer, sizeof(rtcBuffer));
|
if (vf->read(vf, &buffer, sizeof(buffer)) < (ssize_t) sizeof(buffer)) {
|
||||||
if (!gb->memory.sram) {
|
return;
|
||||||
gb->memory.sram = vf->map(vf, gb->sramSize, MAP_WRITE);
|
|
||||||
GBMBCSwitchSramBank(gb, gb->memory.sramCurrentBank);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < 0x80; ++i) {
|
||||||
|
gb->memory.mbcState.huc3.registers[i * 2] = buffer.regs[i] & 0xF;
|
||||||
|
gb->memory.mbcState.huc3.registers[i * 2 + 1] = buffer.regs[i] >> 4;
|
||||||
|
}
|
||||||
|
LOAD_64LE(gb->memory.rtcLastLatch, 0, &buffer.latchedUnix);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GBMBCHuC3Write(struct GB* gb) {
|
||||||
|
struct VFile* vf = gb->sramVf;
|
||||||
|
if (!vf) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GBMBCHuC3SaveBuffer buffer;
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < 0x80; ++i) {
|
||||||
|
buffer.regs[i] = gb->memory.mbcState.huc3.registers[i * 2] & 0xF;
|
||||||
|
buffer.regs[i] |= gb->memory.mbcState.huc3.registers[i * 2 + 1] << 4;
|
||||||
|
}
|
||||||
|
STORE_64LE(gb->memory.rtcLastLatch, 0, &buffer.latchedUnix);
|
||||||
|
|
||||||
|
_appendSaveSuffix(gb, &buffer, sizeof(buffer));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue