mirror of https://github.com/mgba-emu/mgba.git
GB MBC: Emulate TAMA6 timer disabling
This commit is contained in:
parent
51784b1996
commit
1985713c3a
|
@ -50,12 +50,17 @@ struct GBMBCHuC3SaveBuffer {
|
|||
uint64_t latchedUnix;
|
||||
};
|
||||
|
||||
DECL_BITFIELD(GBMBCTAMA5SaveFlags, uint32_t);
|
||||
DECL_BIT(GBMBCTAMA5SaveFlags, Disabled, 0);
|
||||
|
||||
struct GBMBCTAMA5SaveBuffer {
|
||||
uint8_t rtcTimerPage[0x8];
|
||||
uint8_t rtcAlarmPage[0x8];
|
||||
uint8_t rtcFreePage0[0x8];
|
||||
uint8_t rtcFreePage1[0x8];
|
||||
uint64_t latchedUnix;
|
||||
GBMBCTAMA5SaveFlags flags;
|
||||
uint32_t padding;
|
||||
};
|
||||
|
||||
void GBMBCRTCRead(struct GB* gb);
|
||||
|
|
|
@ -123,6 +123,8 @@ enum GBTAMA6RTCRegister {
|
|||
};
|
||||
|
||||
enum GBTAMA6Command {
|
||||
GBTAMA6_DISABLE_TIMER = 0x0,
|
||||
GBTAMA6_ENABLE_TIMER = 0x1,
|
||||
GBTAMA6_MINUTE_WRITE = 0x4,
|
||||
GBTAMA6_HOUR_WRITE = 0x5,
|
||||
GBTAMA6_MINUTE_READ = 0x6,
|
||||
|
@ -206,6 +208,7 @@ struct GBPocketCamState {
|
|||
|
||||
struct GBTAMA5State {
|
||||
uint8_t reg;
|
||||
bool disabled;
|
||||
uint8_t registers[GBTAMA5_MAX];
|
||||
uint8_t rtcTimerPage[GBTAMA6_RTC_MAX];
|
||||
};
|
||||
|
|
27
src/gb/mbc.c
27
src/gb/mbc.c
|
@ -1572,7 +1572,7 @@ static int _tama6DayOfYearToDayOfMonth(int day, int year) {
|
|||
return day - _daysToMonth[12];
|
||||
}
|
||||
|
||||
static void _latchTAMA6Rtc(struct mRTCSource* rtc, uint8_t* timerRegs, time_t* rtcLastLatch) {
|
||||
static void _latchTAMA6Rtc(struct mRTCSource* rtc, struct GBTAMA5State* tama5, time_t* rtcLastLatch) {
|
||||
time_t t;
|
||||
if (rtc) {
|
||||
if (rtc->sample) {
|
||||
|
@ -1585,10 +1585,11 @@ static void _latchTAMA6Rtc(struct mRTCSource* rtc, uint8_t* timerRegs, time_t* r
|
|||
time_t currentLatch = t;
|
||||
t -= *rtcLastLatch;
|
||||
*rtcLastLatch = currentLatch;
|
||||
if (!t) {
|
||||
if (!t || tama5->disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t* timerRegs = tama5->rtcTimerPage;
|
||||
int64_t diff;
|
||||
diff = timerRegs[GBTAMA6_RTC_PA0_SECOND_1] + timerRegs[GBTAMA6_RTC_PA0_SECOND_10] * 10 + t % 60;
|
||||
if (diff < 0) {
|
||||
|
@ -1691,6 +1692,14 @@ void _GBTAMA5(struct GB* gb, uint16_t address, uint8_t value) {
|
|||
break;
|
||||
case 0x2: // Other commands
|
||||
switch (address) {
|
||||
case GBTAMA6_DISABLE_TIMER:
|
||||
tama5->disabled = true;
|
||||
break;
|
||||
case GBTAMA6_ENABLE_TIMER:
|
||||
tama5->disabled = false;
|
||||
tama5->rtcTimerPage[GBTAMA6_RTC_PA0_SECOND_1] = 0;
|
||||
tama5->rtcTimerPage[GBTAMA6_RTC_PA0_SECOND_10] = 0;
|
||||
break;
|
||||
case GBTAMA6_MINUTE_WRITE:
|
||||
tama5->rtcTimerPage[GBTAMA6_RTC_PA0_MINUTE_1] = out & 0xF;
|
||||
tama5->rtcTimerPage[GBTAMA6_RTC_PA0_MINUTE_10] = out >> 4;
|
||||
|
@ -1746,7 +1755,7 @@ uint8_t _GBTAMA5Read(struct GBMemory* memory, uint16_t address) {
|
|||
break;
|
||||
case 0x2:
|
||||
mLOG(GB_MBC, STUB, "TAMA5 unknown read %s: %02X", tama5->reg == GBTAMA5_READ_HI ? "hi" : "lo", address);
|
||||
_latchTAMA6Rtc(memory->rtc, tama5->rtcTimerPage, &memory->rtcLastLatch);
|
||||
_latchTAMA6Rtc(memory->rtc, tama5, &memory->rtcLastLatch);
|
||||
switch (address) {
|
||||
case GBTAMA6_MINUTE_READ:
|
||||
value = (tama5->rtcTimerPage[GBTAMA6_RTC_PA0_MINUTE_10] << 4) | tama5->rtcTimerPage[GBTAMA6_RTC_PA0_MINUTE_1];
|
||||
|
@ -1764,7 +1773,7 @@ uint8_t _GBTAMA5Read(struct GBMemory* memory, uint16_t address) {
|
|||
mLOG(GB_MBC, GAME_ERROR, "TAMA5 reading RTC incorrectly");
|
||||
break;
|
||||
}
|
||||
_latchTAMA6Rtc(memory->rtc, tama5->rtcTimerPage, &memory->rtcLastLatch);
|
||||
_latchTAMA6Rtc(memory->rtc, tama5, &memory->rtcLastLatch);
|
||||
value = tama5->rtcTimerPage[tama5->registers[GBTAMA5_WRITE_LO]];
|
||||
break;
|
||||
default:
|
||||
|
@ -2219,6 +2228,10 @@ void GBMBCTAMA5Read(struct GB* gb) {
|
|||
gb->memory.mbcState.tama5.rtcTimerPage[i * 2 + 1] = buffer.rtcTimerPage[i] >> 4;
|
||||
}
|
||||
LOAD_64LE(gb->memory.rtcLastLatch, 0, &buffer.latchedUnix);
|
||||
|
||||
uint32_t flags;
|
||||
LOAD_32LE(flags, 0, &buffer.flags);
|
||||
gb->memory.mbcState.tama5.disabled = GBMBCTAMA5SaveFlagsGetDisabled(flags);
|
||||
}
|
||||
|
||||
void GBMBCTAMA5Write(struct GB* gb) {
|
||||
|
@ -2227,7 +2240,7 @@ void GBMBCTAMA5Write(struct GB* gb) {
|
|||
return;
|
||||
}
|
||||
|
||||
struct GBMBCTAMA5SaveBuffer buffer;
|
||||
struct GBMBCTAMA5SaveBuffer buffer = {0};
|
||||
size_t i;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
buffer.rtcTimerPage[i] = gb->memory.mbcState.tama5.rtcTimerPage[i * 2] & 0xF;
|
||||
|
@ -2238,5 +2251,9 @@ void GBMBCTAMA5Write(struct GB* gb) {
|
|||
}
|
||||
STORE_64LE(gb->memory.rtcLastLatch, 0, &buffer.latchedUnix);
|
||||
|
||||
uint32_t flags = 0;
|
||||
flags = GBMBCTAMA5SaveFlagsSetDisabled(flags, gb->memory.mbcState.tama5.disabled);
|
||||
STORE_32LE(flags, 0, &buffer.flags);
|
||||
|
||||
_appendSaveSuffix(gb, &buffer, sizeof(buffer));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue