diff --git a/asm/Dolphin/os/OSFont.s b/asm/Dolphin/os/OSFont.s index 7852ffd3..27b5f29e 100644 --- a/asm/Dolphin/os/OSFont.s +++ b/asm/Dolphin/os/OSFont.s @@ -1044,7 +1044,7 @@ lbl_80380FE0: /* 80380FE0 0037DF40 38 7C 00 00 */ addi r3, r28, 0 /* 80380FE4 0037DF44 38 9F 00 00 */ addi r4, r31, 0 /* 80380FE8 0037DF48 38 BE 00 00 */ addi r5, r30, 0 -/* 80380FEC 0037DF4C 48 00 2F 01 */ bl sub_80383eec +/* 80380FEC 0037DF4C 48 00 2F 01 */ bl __OSReadROM /* 80380FF0 0037DF50 2C 03 00 00 */ cmpwi r3, 0 /* 80380FF4 0037DF54 41 82 FF EC */ beq lbl_80380FE0 /* 80380FF8 0037DF58 7F DE FA 14 */ add r30, r30, r31 diff --git a/asm/Dolphin/os/OSRtc.s b/asm/Dolphin/os/OSRtc.s index 89c5a220..c8b4ff0a 100644 --- a/asm/Dolphin/os/OSRtc.s +++ b/asm/Dolphin/os/OSRtc.s @@ -488,8 +488,8 @@ __OSSyncSram: /* 80383EE4 00380E44 80 63 00 4C */ lwz r3, 0x4c(r3) /* 80383EE8 00380E48 4E 80 00 20 */ blr -.global sub_80383eec -sub_80383eec: +.global __OSReadROM +__OSReadROM: /* 80383EEC 00380E4C 7C 08 02 A6 */ mflr r0 /* 80383EF0 00380E50 90 01 00 04 */ stw r0, 4(r1) /* 80383EF4 00380E54 94 21 FF D8 */ stwu r1, -0x28(r1) @@ -687,8 +687,8 @@ lbl_80384178: /* 8038419C 003810FC 7C 08 03 A6 */ mtlr r0 /* 803841A0 00381100 4E 80 00 20 */ blr -.global sub_803841a4 -sub_803841a4: +.global OSSetProgressiveMode +OSSetProgressiveMode: /* 803841A4 00381104 7C 08 02 A6 */ mflr r0 /* 803841A8 00381108 3C 80 80 54 */ lis r4, Scb@ha /* 803841AC 0038110C 90 01 00 04 */ stw r0, 4(r1) diff --git a/asm/Kyoto/Graphics/DolphinCGraphics.s b/asm/Kyoto/Graphics/DolphinCGraphics.s index 90b3e8ae..c4f6eafb 100644 --- a/asm/Kyoto/Graphics/DolphinCGraphics.s +++ b/asm/Kyoto/Graphics/DolphinCGraphics.s @@ -572,7 +572,7 @@ SetProgressiveMode__9CGraphicsFb: /* 8030962C 0030658C 7C 04 00 D0 */ neg r0, r4 /* 80309630 00306590 7C 00 23 78 */ or r0, r0, r4 /* 80309634 00306594 54 03 0F FE */ srwi r3, r0, 0x1f -/* 80309638 00306598 48 07 AB 6D */ bl sub_803841a4 +/* 80309638 00306598 48 07 AB 6D */ bl OSSetProgressiveMode /* 8030963C 0030659C 57 C3 06 3E */ clrlwi r3, r30, 0x18 /* 80309640 003065A0 57 E0 06 3E */ clrlwi r0, r31, 0x18 /* 80309644 003065A4 7C 03 00 40 */ cmplw r3, r0 diff --git a/include/dolphin/OSRtcPriv.h b/include/dolphin/OSRtcPriv.h index d5e1e0c5..78beefcd 100644 --- a/include/dolphin/OSRtcPriv.h +++ b/include/dolphin/OSRtcPriv.h @@ -12,7 +12,6 @@ typedef struct OSSram { s8 displayOffsetH; u8 ntd; u8 language; - u8 flags; } OSSram; diff --git a/src/Dolphin/os/OSRtc.c b/src/Dolphin/os/OSRtc.c new file mode 100644 index 00000000..83d0e92e --- /dev/null +++ b/src/Dolphin/os/OSRtc.c @@ -0,0 +1,326 @@ +#include "dolphin/OSRtcPriv.h" +#include "dolphin/os.h" + +#define RTC_CMD_READ 0x20000000 +#define RTC_CMD_WRITE 0xa0000000 + +#define RTC_SRAM_ADDR 0x00000100 +#define RTC_SRAM_SIZE 64 + +#define RTC_CHAN 0 +#define RTC_DEV 1 +#define RTC_FREQ 3 // EXI_FREQ_8M + +typedef struct SramControlBlock { + u8 sram[RTC_SRAM_SIZE]; + u32 offset; + BOOL enabled; + BOOL locked; + BOOL sync; + void (*callback)(void); +} SramControlBlock; + +static SramControlBlock Scb ATTRIBUTE_ALIGN(32); + +static BOOL GetRTC(u32* rtc) { + BOOL err; + u32 cmd; + + if (!EXILock(RTC_CHAN, RTC_DEV, 0)) { + return FALSE; + } + if (!EXISelect(RTC_CHAN, RTC_DEV, RTC_FREQ)) { + EXIUnlock(RTC_CHAN); + return FALSE; + } + + cmd = RTC_CMD_READ; + err = FALSE; + err |= !EXIImm(RTC_CHAN, &cmd, 4, 0x12345, NULL); + err |= !EXISync(RTC_CHAN); + err |= !EXIImm(RTC_CHAN, &cmd, 4, 0x17231, NULL); + err |= !EXISync(RTC_CHAN); + err |= !EXIDeselect(RTC_CHAN); + EXIUnlock(RTC_CHAN); + + *rtc = cmd; + + return !err; +} + +BOOL __OSGetRTC(u32* rtc) { + BOOL err; + u32 t0; + u32 t1; + int i; + + for (i = 0; i < 16; i++) { + err = FALSE; + err |= !GetRTC(&t0); + err |= !GetRTC(&t1); + if (err) { + break; + } + if (t0 == t1) { + *rtc = t0; + return TRUE; + } + } + return FALSE; +} + +BOOL __OSSetRTC(u32 rtc) { + BOOL err; + u32 cmd; + + if (!EXILock(RTC_CHAN, RTC_DEV, 0)) { + return FALSE; + } + if (!EXISelect(RTC_CHAN, RTC_DEV, RTC_FREQ)) { + EXIUnlock(RTC_CHAN); + return FALSE; + } + + cmd = RTC_CMD_WRITE; + err = FALSE; + err |= !EXIImm(RTC_CHAN, &cmd, 4, 0x54321, NULL); + err |= !EXISync(RTC_CHAN); + err |= !EXIImm(RTC_CHAN, &rtc, 4, 0x12345, NULL); + err |= !EXISync(RTC_CHAN); + err |= !EXIDeselect(RTC_CHAN); + EXIUnlock(RTC_CHAN); + + return !err; +} + +static BOOL ReadSram(void* buffer) { + BOOL err; + u32 cmd; + + DCInvalidateRange(buffer, RTC_SRAM_SIZE); + + if (!EXILock(RTC_CHAN, RTC_DEV, 0)) { + return FALSE; + } + if (!EXISelect(RTC_CHAN, RTC_DEV, RTC_FREQ)) { + EXIUnlock(RTC_CHAN); + return FALSE; + } + + cmd = RTC_CMD_READ | RTC_SRAM_ADDR; + err = FALSE; + err |= !EXIImm(RTC_CHAN, &cmd, 4, 1, NULL); + err |= !EXISync(RTC_CHAN); + err |= !EXIDma(RTC_CHAN, buffer, RTC_SRAM_SIZE, 0, NULL); + err |= !EXISync(RTC_CHAN); + err |= !EXIDeselect(RTC_CHAN); + EXIUnlock(RTC_CHAN); + + return !err; +} + +BOOL WriteSram(void* buffer, u32 offset, u32 size); +static void WriteSramCallback(s32 chan, OSContext* context) { + Scb.sync = WriteSram(Scb.sram + Scb.offset, Scb.offset, RTC_SRAM_SIZE - Scb.offset); + if (Scb.sync) { + Scb.offset = RTC_SRAM_SIZE; + } +} + +BOOL WriteSram(void* buffer, u32 offset, u32 size) { + BOOL err; + u32 cmd; + + if (!EXILock(RTC_CHAN, RTC_DEV, WriteSramCallback)) { + return FALSE; + } + if (!EXISelect(RTC_CHAN, RTC_DEV, RTC_FREQ)) { + EXIUnlock(RTC_CHAN); + return FALSE; + } + + offset <<= 6; + cmd = RTC_CMD_WRITE | RTC_SRAM_ADDR + offset; + err = FALSE; + err |= !EXIImm(RTC_CHAN, &cmd, 4, 1, NULL); + err |= !EXISync(RTC_CHAN); + err |= !EXIImmEx(RTC_CHAN, buffer, (s32)size, 1); + err |= !EXIDeselect(RTC_CHAN); + EXIUnlock(RTC_CHAN); + + return !err; +} + +void __OSInitSram() { + Scb.locked = Scb.enabled = FALSE; + Scb.sync = ReadSram(Scb.sram); + Scb.offset = RTC_SRAM_SIZE; +} + +static void* LockSram(u32 offset) { + BOOL enabled; + enabled = OSDisableInterrupts(); + + if (Scb.locked != FALSE) { + OSRestoreInterrupts(enabled); + return NULL; + } + + Scb.enabled = enabled; + Scb.locked = TRUE; + + return Scb.sram + offset; +} + +OSSram* __OSLockSram() { return LockSram(0); } + +OSSramEx* __OSLockSramEx() { return LockSram(sizeof(OSSram)); } + +static BOOL UnlockSram(BOOL commit, u32 offset) { + u16* p; + + if (commit) { + if (offset == 0) { + OSSram* sram = (OSSram*)Scb.sram; + + if (2u < (sram->flags & 3)) { + sram->flags &= ~3; + } + + sram->checkSum = sram->checkSumInv = 0; + for (p = (u16*)&sram->counterBias; p < (u16*)(Scb.sram + sizeof(OSSram)); p++) { + sram->checkSum += *p; + sram->checkSumInv += ~*p; + } + } + + if (offset < Scb.offset) { + Scb.offset = offset; + } + + Scb.sync = WriteSram(Scb.sram + Scb.offset, Scb.offset, RTC_SRAM_SIZE - Scb.offset); + if (Scb.sync) { + Scb.offset = RTC_SRAM_SIZE; + } + } + Scb.locked = FALSE; + OSRestoreInterrupts(Scb.enabled); + return Scb.sync; +} + +BOOL __OSUnlockSram(BOOL commit) { return UnlockSram(commit, 0); } + +BOOL __OSUnlockSramEx(BOOL commit) { return UnlockSram(commit, sizeof(OSSram)); } + +BOOL __OSSyncSram() { return Scb.sync; } + +BOOL __OSReadROM(void* buffer, s32 length, s32 offset) { + BOOL err; + u32 cmd; + + DCInvalidateRange(buffer, (u32)length); + + if (!EXILock(RTC_CHAN, RTC_DEV, 0)) { + return FALSE; + } + if (!EXISelect(RTC_CHAN, RTC_DEV, RTC_FREQ)) { + EXIUnlock(RTC_CHAN); + return FALSE; + } + + cmd = (u32)(offset << 6); + err = FALSE; + err |= !EXIImm(RTC_CHAN, &cmd, 4, 1, NULL); + err |= !EXISync(RTC_CHAN); + err |= !EXIDma(RTC_CHAN, buffer, length, 0, NULL); + err |= !EXISync(RTC_CHAN); + err |= !EXIDeselect(RTC_CHAN); + EXIUnlock(RTC_CHAN); + + return !err; +} + +u32 OSGetSoundMode() { + OSSram* sram; + u32 mode; + + sram = __OSLockSram(); + mode = (sram->flags & 0x4) ? OS_SOUND_MODE_STEREO : OS_SOUND_MODE_MONO; + __OSUnlockSram(FALSE); + return mode; +} + +void OSSetSoundMode(u32 mode) { + OSSram* sram; + mode <<= 2; + mode &= 4; + + sram = __OSLockSram(); + if (mode == (sram->flags & 4)) { + __OSUnlockSram(FALSE); + return; + } + + sram->flags &= ~4; + sram->flags |= mode; + __OSUnlockSram(TRUE); +} + +u32 OSGetProgressiveMode() { + OSSram* sram; + u32 mode; + + sram = __OSLockSram(); + mode = (sram->flags & 0x80) >> 7; + __OSUnlockSram(FALSE); + return mode; +} + +void OSSetProgressiveMode(u32 mode) { + OSSram* sram; + mode <<= 7; + mode &= 0x80; + + sram = __OSLockSram(); + if (mode == (sram->flags & 0x80)) { + __OSUnlockSram(FALSE); + return; + } + + sram->flags &= ~0x80; + sram->flags |= mode; + __OSUnlockSram(TRUE); +} + +u8 OSGetLanguage() { + OSSram* sram; + u8 language; + + sram = __OSLockSram(); + language = sram->language; + __OSUnlockSram(FALSE); + return language; +} + +u32 OSGetWirelessID(u32 channel) { + OSSramEx* sram; + u16 id; + + sram = __OSLockSramEx(); + id = sram->wirelessPadID[channel]; + __OSUnlockSramEx(FALSE); + return id; +} + +void OSSetWirelessID(u32 channel, u16 id) { + OSSramEx* sram; + + sram = __OSLockSramEx(); + if (sram->wirelessPadID[channel] != id) { + sram->wirelessPadID[channel] = id; + __OSUnlockSramEx(TRUE); + return; + } + + __OSUnlockSramEx(FALSE); +}