#include "global.h" #include "dolphin/os/OSRtc.h" #include "dolphin/os/OSInterrupt.h" static void WriteSramCallback(s32 chan, OSContext* context); static BOOL WriteSram(void* buffer, u32 offset, u32 size); static BOOL UnlockSram(BOOL commit, u32 offset); static SramControlBlock Scb ALIGN_DECL(32); 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; } } static inline 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) { 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(void) { 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(void) { return Scb.sync; } 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); } u8 OSGetLanguage() { OSSram* sram; u8 language; sram = __OSLockSram(); language = sram->language; __OSUnlockSram(FALSE); return language; } u32 OSGetEuRgb60Mode() { OSSram* sram; u32 on; sram = __OSLockSram(); on = (sram->ntd >> 6) & 0x1; __OSUnlockSram(FALSE); return on; } void OSSetEuRgb60Mode(u32 mode) { OSSram *sram; mode <<= 6; mode &= 0x40; sram = __OSLockSram(); if (mode == (sram->ntd & 0x40)) { __OSUnlockSram(FALSE); return; } sram->ntd &= ~0x40; sram->ntd |= 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); } u16 OSGetWirelessID(s32 channel) { OSSramEx* sram; u16 id; sram = __OSLockSramEx(); id = sram->wirelessPadID[channel]; __OSUnlockSramEx(FALSE); return id; } void OSSetWirelessID(s32 channel, u16 id) { OSSramEx* sram; sram = __OSLockSramEx(); if (sram->wirelessPadID[channel] != id) { sram->wirelessPadID[channel] = id; __OSUnlockSramEx(TRUE); return; } __OSUnlockSramEx(FALSE); }