diff --git a/src/gb/GB.cpp b/src/gb/GB.cpp index 16517d37..f571d2c1 100644 --- a/src/gb/GB.cpp +++ b/src/gb/GB.cpp @@ -4376,6 +4376,7 @@ bool gbUpdateSizes() case 0x1e: case 0x22: case 0xfd: + case 0xfe: case 0xff: gbBattery = 1; break; @@ -4399,6 +4400,7 @@ bool gbUpdateSizes() case 0x0f: case 0x10: // mbc3 case 0xfd: // tama5 + case 0xfe: gbRTCPresent = 1; break; default: diff --git a/src/gb/gbMemory.cpp b/src/gb/gbMemory.cpp index d1a6e61e..02a559fc 100644 --- a/src/gb/gbMemory.cpp +++ b/src/gb/gbMemory.cpp @@ -1000,14 +1000,33 @@ mapperHuC3 gbDataHuC3 = { 0, // RAM read value 0, // Register 1 0, // Register 2 - 0, // Register 3 - 0, // Register 4 - 0, // Register 5 - 0, // Register 6 - 0, // Register 7 - 0 // Register 8 + 0, // DateTime + 0, // WritingTime + 0, // ModeFlag + 0, // ClockShift + 0 // lastTime }; +void memoryupdateHuC3Latch() { + uint64_t now = time(NULL); + uint64_t diff = now - gbDataHuC3.mapperLastTime; + + if (diff > 0) { + unsigned minute = (diff / 60) % 1440; + unsigned day = (diff / 86400) & 0xFFF; + + gbDataHuC3.mapperDateTime = (day << 12) | minute; + } +} + +void memoryupdateHuC3Clock() { + uint64_t now = time(NULL); + unsigned minute = (gbDataHuC3.mapperWritingTime & 0xFFF) % 1440; + unsigned day = (gbDataHuC3.mapperWritingTime & 0xFFF000) >> 12; + + gbDataHuC3.mapperLastTime = now - minute * 60 - day * 86400; +} + // HuC3 ROM write registers void mapperHuC3ROM(uint16_t address, uint8_t value) { @@ -1066,7 +1085,7 @@ uint8_t mapperHuC3ReadRAM(uint16_t address) // HuC3 RAM write void mapperHuC3RAM(uint16_t address, uint8_t value) { - int* p; + //int* p; if (gbDataHuC3.mapperRAMFlag < 0x0b || gbDataHuC3.mapperRAMFlag > 0x0e) { if (gbDataHuC3.mapperRAMEnable) { @@ -1082,20 +1101,43 @@ void mapperHuC3RAM(uint16_t address, uint8_t value) } else { switch (value & 0xf0) { case 0x10: - p = &gbDataHuC3.mapperRegister2; + /*p = &gbDataHuC3.mapperRegister2; gbDataHuC3.mapperRAMValue = *(p + gbDataHuC3.mapperRegister1++); if (gbDataHuC3.mapperRegister1 > 6) - gbDataHuC3.mapperRegister1 = 0; + gbDataHuC3.mapperRegister1 = 0;*/ + + // read time + memoryupdateHuC3Latch(); + if (gbDataHuC3.mapperModeFlag == HUC3_READ) { + gbDataHuC3.mapperRAMValue = (gbDataHuC3.mapperDateTime >> gbDataHuC3.mapperClockShift) & 0x0F; + gbDataHuC3.mapperClockShift += 4; + if (gbDataHuC3.mapperClockShift > 24) + gbDataHuC3.mapperClockShift = 0; + } break; case 0x30: - p = &gbDataHuC3.mapperRegister2; + /*p = &gbDataHuC3.mapperRegister2; *(p + gbDataHuC3.mapperRegister1++) = value & 0x0f; if (gbDataHuC3.mapperRegister1 > 6) gbDataHuC3.mapperRegister1 = 0; - gbDataHuC3.mapperAddress = (gbDataHuC3.mapperRegister6 << 24) | (gbDataHuC3.mapperRegister5 << 16) | (gbDataHuC3.mapperRegister4 << 8) | (gbDataHuC3.mapperRegister3 << 4) | (gbDataHuC3.mapperRegister2); + gbDataHuC3.mapperAddress = (gbDataHuC3.mapperRegister6 << 24) | (gbDataHuC3.mapperRegister5 << 16) | (gbDataHuC3.mapperRegister4 << 8) | (gbDataHuC3.mapperRegister3 << 4) | (gbDataHuC3.mapperRegister2);*/ + + // write time + if (gbDataHuC3.mapperModeFlag == HUC3_WRITE) { + if (gbDataHuC3.mapperClockShift == 0) + gbDataHuC3.mapperWritingTime = 0; + if (gbDataHuC3.mapperClockShift <= 24) { + gbDataHuC3.mapperWritingTime |= (value & 0x0F) << gbDataHuC3.mapperClockShift; + gbDataHuC3.mapperClockShift += 4; + if (gbDataHuC3.mapperClockShift == 24) { + memoryupdateHuC3Clock(); + gbDataHuC3.mapperModeFlag = HUC3_READ; + } + } + } break; case 0x40: - gbDataHuC3.mapperRegister1 = (gbDataHuC3.mapperRegister1 & 0xf0) | (value & 0x0f); + /*gbDataHuC3.mapperRegister1 = (gbDataHuC3.mapperRegister1 & 0xf0) | (value & 0x0f); gbDataHuC3.mapperRegister2 = (gbDataHuC3.mapperAddress & 0x0f); gbDataHuC3.mapperRegister3 = ((gbDataHuC3.mapperAddress >> 4) & 0x0f); gbDataHuC3.mapperRegister4 = ((gbDataHuC3.mapperAddress >> 8) & 0x0f); @@ -1103,13 +1145,35 @@ void mapperHuC3RAM(uint16_t address, uint8_t value) gbDataHuC3.mapperRegister6 = ((gbDataHuC3.mapperAddress >> 24) & 0x0f); gbDataHuC3.mapperRegister7 = 0; gbDataHuC3.mapperRegister8 = 0; - gbDataHuC3.mapperRAMValue = 0; + gbDataHuC3.mapperRAMValue = 0;*/ + + // some kind of mode shift + switch(value & 0x0F) { + case 0x0: + // shift reset? + gbDataHuC3.mapperClockShift = 0; + break; + case 0x3: + // write time? + gbDataHuC3.mapperModeFlag = HUC3_WRITE; + gbDataHuC3.mapperClockShift = 0; + break; + case 0x7: + gbDataHuC3.mapperModeFlag = HUC3_READ; + gbDataHuC3.mapperClockShift = 0; + break; + // others are unimplemented so far + } break; case 0x50: - gbDataHuC3.mapperRegister1 = (gbDataHuC3.mapperRegister1 & 0x0f) | ((value << 4) & 0x0f); + //gbDataHuC3.mapperRegister1 = (gbDataHuC3.mapperRegister1 & 0x0f) | ((value << 4) & 0x0f); + break; + case 0x60: + gbDataHuC3.mapperModeFlag = HUC3_READ; // ??? + gbDataHuC3.mapperRAMValue = 1; break; default: - gbDataHuC3.mapperRAMValue = 1; + //gbDataHuC3.mapperRAMValue = 1; break; } } diff --git a/src/gb/gbMemory.h b/src/gb/gbMemory.h index 0ca97506..e901be0b 100644 --- a/src/gb/gbMemory.h +++ b/src/gb/gbMemory.h @@ -77,6 +77,12 @@ struct mapperHuC1 { int mapperRAMAddress; }; +enum { + HUC3_READ = 0, + HUC3_WRITE = 1, + HUC3_NONE = 2 +}; + struct mapperHuC3 { int mapperRAMEnable; int mapperROMBank; @@ -87,12 +93,14 @@ struct mapperHuC3 { int mapperRAMValue; int mapperRegister1; int mapperRegister2; - int mapperRegister3; - int mapperRegister4; - int mapperRegister5; - int mapperRegister6; - int mapperRegister7; - int mapperRegister8; + int mapperDateTime; + int mapperWritingTime; + int mapperModeFlag; + int mapperClockShift; + union { + time_t mapperLastTime; + uint64_t _time_pad; /* so that 32bit and 64bit saves are compatible */ + }; }; struct mapperTAMA5 { @@ -196,4 +204,6 @@ extern void memoryUpdateMapGS3(); #define TAMA5_RTC_DATA_SIZE sizeof(int) * 14 + sizeof(uint64_t) +#define HUC3_RTC_DATA_SIZE sizeof(int) * 4 + sizeof(uint64_t) + #endif // GBMEMORY_H diff --git a/src/libretro/libretro.cpp b/src/libretro/libretro.cpp index 61d3ef05..2b3508ec 100644 --- a/src/libretro/libretro.cpp +++ b/src/libretro/libretro.cpp @@ -161,6 +161,9 @@ static void set_gbPalette(void) } } +extern void memoryupdateHuC3Clock(); +extern void memoryupdateHuC3Latch(); + static void* gb_rtcdata_prt(void) { switch (gbRomType) { @@ -169,6 +172,8 @@ static void* gb_rtcdata_prt(void) return &gbDataMBC3.mapperSeconds; case 0xfd: // TAMA5 + extended return &gbDataTAMA5.mapperSeconds; + case 0xfe: // HuC3 + Clock + return &gbDataHuC3.mapperDateTime; } return NULL; } @@ -181,6 +186,8 @@ static size_t gb_rtcdata_size(void) return MBC3_RTC_DATA_SIZE; case 0xfd: // TAMA5 + extended return TAMA5_RTC_DATA_SIZE; + case 0xfe: // HuC3 + Clock + return HUC3_RTC_DATA_SIZE; } return 0; } @@ -231,6 +238,10 @@ static void gbInitRTC(void) gbDataTAMA5.mapperControl = (gbDataTAMA5.mapperControl & 0xfe) | (lt->tm_yday > 255 ? 1 : 0); } break; + case 0xfe: + //memoryupdateHuC3Clock(); + memoryupdateHuC3Latch(); + break; } } @@ -298,7 +309,7 @@ void* retro_get_memory_data(unsigned id) data = (gbCgbMode ? gbVram : (gbMemory + 0x8000)); break; case RETRO_MEMORY_RTC: - if (gbBattery && gbRTCPresent) + //if (gbBattery/* && gbRTCPresent*/) data = gb_rtcdata_prt(); break; } @@ -1425,6 +1436,10 @@ void retro_run(void) if (!gbDataTAMA5.mapperLastTime) initRTC = true; break; + case 0xfe: + if (!gbDataHuC3.mapperLastTime) + initRTC = true; + break; } /* Initialize RTC using local time if needed */ if (initRTC)