diff --git a/Makefile b/Makefile index 964a22a..d4af31c 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,8 @@ else $(error Unsupported host/building OS <$(UNAME_S)>) endif +DOLPHIN_REVISION ?= 36 + BUILD_DIR := build TOOLS_DIR := $(BUILD_DIR)/tools BASEROM_DIR := baserom @@ -111,8 +113,7 @@ CC = $(MWCC) ######################## Flags ############################# CHARFLAGS := -char unsigned - -CFLAGS = $(CHARFLAGS) -nodefaults -proc gekko -fp hard -Cpp_exceptions off -enum int -warn pragmas -requireprotos -pragma 'cats off' +CFLAGS = $(CHARFLAGS) -nodefaults -proc gekko -fp hard -Cpp_exceptions off -enum int -warn pragmas -requireprotos -pragma 'cats off' -DDOLPHIN_REVISION=$(DOLPHIN_REVISION) INCLUDES := -Iinclude -Iinclude/libc -ir src ASFLAGS = -mgekko -I src -I include @@ -126,8 +127,10 @@ build/debug/src/card/CARDRename.o: CHARFLAGS := -char signed build/release/src/card/CARDRename.o: CHARFLAGS := -char signed build/debug/src/card/CARDOpen.o: CHARFLAGS := -char signed build/release/src/card/CARDOpen.o: CHARFLAGS := -char signed +ifneq ($(DOLPHIN_REVISION),37) build/debug/src/dvd/%.o: CFLAGS += -char signed build/release/src/dvd/%.o: CFLAGS += -char signed +endif build/debug/src/demo/%.o: CFLAGS += -char signed build/release/src/demo/%.o: CFLAGS += -char signed @@ -293,6 +296,7 @@ dvd_c_files := \ src/dvd/dvdfs.c \ src/dvd/dvd.c \ src/dvd/dvdqueue.c \ + src/dvd/dvderror.c \ src/dvd/fstload.c dvd.a : $(addprefix $(BUILD_DIR)/release/,$(dvd_c_files:.c=.o)) dvdD.a : $(addprefix $(BUILD_DIR)/debug/,$(dvd_c_files:.c=.o)) @@ -377,6 +381,7 @@ os_c_files := \ src/os/OSMessage.c \ src/os/OSMemory.c \ src/os/OSMutex.c \ + src/os/OSReboot.c \ src/os/OSReset.c \ src/os/OSResetSW.c \ src/os/OSRtc.c \ diff --git a/include/dolphin/card.h b/include/dolphin/card.h index 89752f2..384a6b2 100644 --- a/include/dolphin/card.h +++ b/include/dolphin/card.h @@ -163,6 +163,7 @@ typedef struct CARDID { #define CARD_RESULT_CANCELED -14 #define CARD_RESULT_FATAL_ERROR -128 +// TODO: This should be private #define CARDIsValidBlockNo(card, blockNo) ((blockNo) >= CARD_NUM_SYSTEM_BLOCK && (blockNo) < (card)->cBlock) #define CARD_READ_SIZE 512 diff --git a/include/dolphin/card/CARDCheck.h b/include/dolphin/card/CARDCheck.h index bc0f8a0..3314c9d 100644 --- a/include/dolphin/card/CARDCheck.h +++ b/include/dolphin/card/CARDCheck.h @@ -1,6 +1,9 @@ #ifndef _DOLPHIN_CARDCHECK_H_ #define _DOLPHIN_CARDCHECK_H_ +#if DOLPHIN_REVISION >= 37 +s32 CARDCheckExAsync(s32 chan, s32 *xferBytes, CARDCallback callback); +#endif s32 CARDCheckAsync(s32 chan, CARDCallback callback); long CARDCheck(long chan); diff --git a/include/dolphin/dvd.h b/include/dolphin/dvd.h index bc0e46d..b2fcc35 100644 --- a/include/dolphin/dvd.h +++ b/include/dolphin/dvd.h @@ -90,6 +90,7 @@ void (* DVDLowSetResetCoverCallback(void (* callback)(unsigned long)))(unsigned int DVDLowBreak(); void (* DVDLowClearCallback())(unsigned long); unsigned long DVDLowGetCoverStatus(); +BOOL DVDCheckDisk(void); // dvd.c void DVDInit(); diff --git a/include/dolphin/os.h b/include/dolphin/os.h index 424bfaa..6609200 100644 --- a/include/dolphin/os.h +++ b/include/dolphin/os.h @@ -70,6 +70,7 @@ unsigned int __gUnknown800030C0[2] : (OS_BASE_CACHED | 0x30C0); #define OSTicksToMicroseconds(ticks) ((ticks)*8 / (OS_TIMER_CLOCK/125000)) #define OSSecondsToTicks(sec) ((sec) * (OS_TIMER_CLOCK)) #define OSMillisecondsToTicks(msec) ((msec) * (OS_TIMER_CLOCK / 1000)) +#define OSMicrosecondsToTicks(usec) (((usec) * (OS_TIMER_CLOCK / 125000)) / 8) #define OSNanosecondsToTicks(nsec) (((nsec) * (OS_TIMER_CLOCK / 125000)) / 8000) #define OSMicrosecondsToTicks(usec) (((usec) * (OS_TIMER_CLOCK / 125000)) / 8) diff --git a/include/dolphin/os/OSRtc.h b/include/dolphin/os/OSRtc.h index 12c9ab5..57d630d 100644 --- a/include/dolphin/os/OSRtc.h +++ b/include/dolphin/os/OSRtc.h @@ -38,7 +38,12 @@ typedef struct OSSramEx { unsigned char flashID[2][12]; unsigned long wirelessKeyboardID; unsigned short wirelessPadID[4]; +#if DOLPHIN_REVISION >= 37 + u8 dvdErrorCode; + u8 _padding0; +#else unsigned short _padding0; +#endif unsigned char flashIDCheckSum[2]; unsigned char _padding1[4]; } OSSramEx; diff --git a/include/dolphin/os/OSThread.h b/include/dolphin/os/OSThread.h index 5a206cc..53cf430 100644 --- a/include/dolphin/os/OSThread.h +++ b/include/dolphin/os/OSThread.h @@ -70,14 +70,29 @@ enum OS_THREAD_STATE #define OS_THREAD_STACK_MAGIC 0xDEADBABE +typedef void (*OSIdleFunction)(void *param); + void OSInitThreadQueue(OSThreadQueue *queue); +OSThread *OSGetCurrentThread(void); +BOOL OSIsThreadSuspended(OSThread *thread); +BOOL OSIsThreadTerminated(OSThread *thread); +s32 OSDisableScheduler(void); +s32 OSEnableScheduler(void); +void OSYieldThread(void); +BOOL OSCreateThread(OSThread *thread, void *(*func)(void *), void *param, void *stack, u32 stackSize, OSPriority priority, u16 attr); +void OSExitThread(void *val); +void OSCancelThread(OSThread *thread); +BOOL OSJoinThread(OSThread *thread, void *val); +void OSDetachThread(OSThread *thread); +s32 OSResumeThread(OSThread *thread); +s32 OSSuspendThread(OSThread *thread); void OSSleepThread(OSThreadQueue *queue); void OSWakeupThread(OSThreadQueue *queue); -s32 OSSuspendThread(OSThread *thread); -s32 OSResumeThread(OSThread* thread); -OSThread* OSGetCurrentThread(void); -s32 OSEnableScheduler(void); -s32 OSDisableScheduler(void); +BOOL OSSetThreadPriority(OSThread *thread, OSPriority priority); +OSPriority OSGetThreadPriority(OSThread *thread); +OSThread *OSSetIdleFunction(OSIdleFunction idleFunction, void *param, void *stack, u32 stackSize); +OSThread *OSGetIdleFunction(void); +long OSCheckActiveThreads(void); #define IsSuspended(suspend) (suspend > 0) diff --git a/include/dolphin/pad.h b/include/dolphin/pad.h index 7cbb48d..c45f406 100644 --- a/include/dolphin/pad.h +++ b/include/dolphin/pad.h @@ -57,7 +57,11 @@ typedef struct PADStatus int PADReset(unsigned long mask); BOOL PADRecalibrate(u32 mask); BOOL PADInit(); -void PADRead(struct PADStatus * status); +#if DOLPHIN_REVISION >= 37 +u32 PADRead(struct PADStatus *status); +#else +void PADRead(struct PADStatus *status); +#endif void PADSetSamplingRate(unsigned long msec); void __PADTestSamplingRate(unsigned long tvmode); void PADControlAllMotors(const u32 *commandArray); diff --git a/src/card/CARDBios.c b/src/card/CARDBios.c index b6959f7..f6058d4 100644 --- a/src/card/CARDBios.c +++ b/src/card/CARDBios.c @@ -41,6 +41,9 @@ void __CARDExtHandler(s32 chan, OSContext *context) { card->attached = FALSE; card->result = CARD_RESULT_NOCARD; EXISetExiCallback(chan, 0); +#if DOLPHIN_REVISION >= 37 + OSCancelAlarm(&card->alarm); +#endif callback = card->exiCallback; if (callback) @@ -113,17 +116,28 @@ void __CARDExiHandler(s32 chan, OSContext *context) { void __CARDTxHandler(s32 chan, OSContext *context) { CARDControl *card; CARDCallback callback; +#if DOLPHIN_REVISION >= 37 + BOOL r31; +#endif ASSERTLINE(0x12D, 0 <= chan && chan < 2); card = &__CARDBlock[chan]; +#if DOLPHIN_REVISION >= 37 + r31 = !EXIDeselect(chan); +#else !EXIDeselect(chan); +#endif !EXIUnlock(chan); callback = card->txCallback; if (callback) { card->txCallback = NULL; +#if DOLPHIN_REVISION >= 37 + callback(chan, (!r31 && EXIProbe(chan)) ? CARD_RESULT_READY : CARD_RESULT_NOCARD); +#else callback(chan, (EXIProbe(chan)) ? CARD_RESULT_READY : CARD_RESULT_NOCARD); +#endif } } @@ -280,6 +294,12 @@ static void TimeoutHandler(OSAlarm *alarm, OSContext *context) { } } +#if DOLPHIN_REVISION >= 37 + if (!card->attached) { + return; + } +#endif + ASSERTLINE(0x20E, 0 <= chan && chan < 2); EXISetExiCallback(chan, NULL); @@ -297,9 +317,13 @@ static void SetupTimeoutAlarm(CARDControl *card) { { case 0xF3: break; + case 0xF2: +#if DOLPHIN_REVISION >= 37 + OSSetAlarm(&card->alarm, OSMillisecondsToTicks(100), TimeoutHandler); + break; +#endif case 0xF4: case 0xF1: - case 0xF2: OSSetAlarm(&card->alarm, OSSecondsToTicks((OSTime)2) * (card->sectorSize / 0x2000), TimeoutHandler); break; @@ -709,15 +733,19 @@ s32 CARDFreeBlocks(s32 chan, s32 *byteNotUsed, s32 *filesNotUsed) { return __CARDPutControlBlock(card, CARD_RESULT_BROKEN); } - *byteNotUsed = (s32)(card->sectorSize * fat[CARD_FAT_FREEBLOCKS]); + if (DOLPHIN_REVISION < 37 || byteNotUsed != NULL) { + *byteNotUsed = (s32)(card->sectorSize * fat[CARD_FAT_FREEBLOCKS]); + } - *filesNotUsed = 0; - for (fileNo = 0; fileNo < CARD_MAX_FILE; fileNo++) - { - ent = &dir[fileNo]; - if (ent->fileName[0] == 0xff) + if (DOLPHIN_REVISION < 37 || filesNotUsed != NULL) { + *filesNotUsed = 0; + for (fileNo = 0; fileNo < CARD_MAX_FILE; fileNo++) { - ++*filesNotUsed; + ent = &dir[fileNo]; + if (ent->fileName[0] == 0xff) + { + ++*filesNotUsed; + } } } @@ -753,6 +781,10 @@ long CARDGetMemSize(long chan, unsigned short * size) { s32 CARDGetSectorSize(s32 chan, u32 *size) { struct CARDControl *card; long result; +#if DOLPHIN_REVISION >= 37 + BOOL enabled; + CARDControl *tmp; +#endif result = __CARDGetControlBlock(chan, &card); if (result < 0) @@ -760,7 +792,19 @@ s32 CARDGetSectorSize(s32 chan, u32 *size) { return result; } *size = card->sectorSize; +#if DOLPHIN_REVISION >= 37 + tmp = card; + enabled = OSDisableInterrupts(); + if (tmp->attached) { + tmp->result = 0; + } else if (tmp->result == -1) { + tmp->result = 0; + } + OSRestoreInterrupts(enabled); + return 0; +#else return __CARDPutControlBlock(card, 0); +#endif } s32 __CARDSync(s32 chan) { diff --git a/src/card/CARDCheck.c b/src/card/CARDCheck.c index 0fe3a82..e634387 100644 --- a/src/card/CARDCheck.c +++ b/src/card/CARDCheck.c @@ -189,7 +189,148 @@ s32 __CARDVerify(CARDControl *card) { } } +#if DOLPHIN_REVISION >= 37 +s32 CARDCheckExAsync(s32 chan, s32 *xferBytes, CARDCallback callback) +{ + CARDControl *card; + CARDDir *dir[2]; + u16 *fat[2]; + u16 *map; + s32 result; + int errors; + int currentFat; + int currentDir; + s32 fileNo; + u16 iBlock; + u16 cBlock; + u16 cFree; + BOOL updateFat = FALSE; + BOOL updateDir = FALSE; + BOOL updateOrphan = FALSE; + + if (xferBytes) + *xferBytes = 0; + + result = __CARDGetControlBlock(chan, &card); + if (result < 0) + return result; + + result = VerifyID(card); + if (result < 0) + return __CARDPutControlBlock(card, result); + + errors = VerifyDir(card, ¤tDir); + errors += VerifyFAT(card, ¤tFat); + if (1 < errors) + return __CARDPutControlBlock(card, CARD_RESULT_BROKEN); + + dir[0] = (CARDDir *)((u8 *)card->workArea + (1 + 0) * CARD_SYSTEM_BLOCK_SIZE); + dir[1] = (CARDDir *)((u8 *)card->workArea + (1 + 1) * CARD_SYSTEM_BLOCK_SIZE); + fat[0] = (u16 *)((u8 *)card->workArea + (3 + 0) * CARD_SYSTEM_BLOCK_SIZE); + fat[1] = (u16 *)((u8 *)card->workArea + (3 + 1) * CARD_SYSTEM_BLOCK_SIZE); + + switch (errors) + { + case 0: break; + case 1: + if (!card->currentDir) + { + card->currentDir = dir[currentDir]; + memcpy(dir[currentDir], dir[currentDir ^ 1], CARD_SYSTEM_BLOCK_SIZE); + updateDir = TRUE; + } + else + { + card->currentFat = fat[currentFat]; + memcpy(fat[currentFat], fat[currentFat ^ 1], CARD_SYSTEM_BLOCK_SIZE); + updateFat = TRUE; + } + break; + } + + map = fat[currentFat ^ 1]; + memset(map, 0, CARD_SYSTEM_BLOCK_SIZE); + + for (fileNo = 0; fileNo < CARD_MAX_FILE; fileNo++) + { + CARDDir *ent; + + ent = &card->currentDir[fileNo]; + if (ent->gameName[0] == 0xff) + continue; + + for (iBlock = ent->startBlock, cBlock = 0; iBlock != 0xFFFF && cBlock < ent->length; + iBlock = card->currentFat[iBlock], ++cBlock) + { + if (!CARDIsValidBlockNo(card, iBlock) || 1 < ++map[iBlock]) + return __CARDPutControlBlock(card, CARD_RESULT_BROKEN); + } + if (cBlock != ent->length || iBlock != 0xFFFF) + return __CARDPutControlBlock(card, CARD_RESULT_BROKEN); + } + + cFree = 0; + for (iBlock = CARD_NUM_SYSTEM_BLOCK; iBlock < card->cBlock; iBlock++) + { + u16 nextBlock; + + nextBlock = card->currentFat[iBlock]; + if (map[iBlock] == 0) + { + if (nextBlock != CARD_FAT_AVAIL) + { + card->currentFat[iBlock] = CARD_FAT_AVAIL; + updateOrphan = TRUE; + } + cFree++; + } + else if (!CARDIsValidBlockNo(card, nextBlock) && nextBlock != 0xFFFF) + return __CARDPutControlBlock(card, CARD_RESULT_BROKEN); + } + if (cFree != card->currentFat[CARD_FAT_FREEBLOCKS]) + { + card->currentFat[CARD_FAT_FREEBLOCKS] = cFree; + updateOrphan = TRUE; + } + if (updateOrphan) + { + __CARDCheckSum(&card->currentFat[CARD_FAT_CHECKCODE], CARD_SYSTEM_BLOCK_SIZE - sizeof(u32), + &card->currentFat[CARD_FAT_CHECKSUM], &card->currentFat[CARD_FAT_CHECKSUMINV]); + } + + memcpy(fat[currentFat ^ 1], fat[currentFat], CARD_SYSTEM_BLOCK_SIZE); + + if (updateDir) + { + if (xferBytes) + *xferBytes = CARD_SYSTEM_BLOCK_SIZE; + return __CARDUpdateDir(chan, callback); + } + + if (updateFat | updateOrphan) + { + if (xferBytes) + *xferBytes = CARD_SYSTEM_BLOCK_SIZE; + return __CARDUpdateFatBlock(chan, card->currentFat, callback); + } + + __CARDPutControlBlock(card, CARD_RESULT_READY); + if (callback) + { + BOOL enabled = OSDisableInterrupts(); + callback(chan, CARD_RESULT_READY); + OSRestoreInterrupts(enabled); + } + return CARD_RESULT_READY; +} +#endif + s32 CARDCheckAsync(s32 chan, CARDCallback callback) { +#if DOLPHIN_REVISION >= 37 + s32 xferBytes; + + return CARDCheckExAsync(chan, &xferBytes, callback); +#else CARDControl *card; CARDDir *dir[2]; u16 *fat[2]; @@ -314,6 +455,7 @@ s32 CARDCheckAsync(s32 chan, CARDCallback callback) { } return __CARDPutControlBlock(card, CARD_RESULT_READY); +#endif } long CARDCheck(long chan) { diff --git a/src/card/CARDCreate.c b/src/card/CARDCreate.c index 3401acd..ccfd4f8 100644 --- a/src/card/CARDCreate.c +++ b/src/card/CARDCreate.c @@ -29,6 +29,9 @@ static void CreateCallbackFat(long chan, long result) { ent->iconFormat = 0; ent->iconSpeed = 0; ent->commentAddr = -1; +#if DOLPHIN_REVISION >= 37 + __CARDSetIconSpeed(ent, 0, CARD_STAT_SPEED_FAST); +#endif card->fileInfo->offset = 0; card->fileInfo->iBlock = ent->startBlock; ent->time = OSTicksToSeconds(OSGetTime()); diff --git a/src/card/CARDMount.c b/src/card/CARDMount.c index 87a49e0..4db7ba0 100644 --- a/src/card/CARDMount.c +++ b/src/card/CARDMount.c @@ -19,7 +19,11 @@ static u32 LatencyTable[8] = // functions static s32 DoMount(s32 chan); +#if DOLPHIN_REVISION >= 37 +static void DoUnmount(s32 chan, s32 result); +#else static void DoUnmount(s32 chan); +#endif int CARDProbe(long chan) { EXIProbe(chan); @@ -30,6 +34,9 @@ s32 CARDProbeEx(s32 chan, s32 *memSize, s32 *sectorSize) { CARDControl *card; BOOL enabled; s32 result; +#if DOLPHIN_REVISION >= 37 + int r3; +#endif if (chan < 0 || 2 <= chan) return CARD_RESULT_FATAL_ERROR; @@ -37,16 +44,26 @@ s32 CARDProbeEx(s32 chan, s32 *memSize, s32 *sectorSize) { card = &__CARDBlock[chan]; enabled = OSDisableInterrupts(); +#if DOLPHIN_REVISION >= 37 + r3 = EXIProbeEx(chan); + if (r3 == -1) + result = CARD_RESULT_NOCARD; + else if (r3 == 0) + result = CARD_RESULT_BUSY; +#else if (EXIProbe(chan) == 0) result = CARD_RESULT_NOCARD; +#endif else if (card->attached) { if (card->mountStep < 1) result = CARD_RESULT_BUSY; else { - *memSize = card->size; - *sectorSize = card->sectorSize; + if (DOLPHIN_REVISION < 37 || memSize != NULL) + *memSize = card->size; + if (DOLPHIN_REVISION < 37 || sectorSize != NULL) + *sectorSize = card->sectorSize; result = CARD_RESULT_READY; } } @@ -58,8 +75,10 @@ s32 CARDProbeEx(s32 chan, s32 *memSize, s32 *sectorSize) { result = CARD_RESULT_WRONGDEVICE; else { - *memSize = (s32)(id & 0xfc); - *sectorSize = SectorSizeTable[(id & 0x00003800) >> 11]; + if (DOLPHIN_REVISION < 37 || memSize != NULL) + *memSize = (s32)(id & 0xfc); + if (DOLPHIN_REVISION < 37 || sectorSize != NULL) + *sectorSize = SectorSizeTable[(id & 0x00003800) >> 11]; result = CARD_RESULT_READY; } @@ -166,7 +185,11 @@ static s32 DoMount(s32 chan) { error: EXIUnlock(chan); +#if DOLPHIN_REVISION >= 37 + DoUnmount(chan, result); +#else DoUnmount(chan); +#endif return result; } @@ -195,7 +218,13 @@ void __CARDMountCallback(s32 chan, s32 result) { return; break; case CARD_RESULT_IOERROR: - case CARD_RESULT_NOCARD: DoUnmount(chan); break; + case CARD_RESULT_NOCARD: +#if DOLPHIN_REVISION >= 37 + DoUnmount(chan, result); +#else + DoUnmount(chan); +#endif + break; } callback = card->apiCallback; @@ -246,6 +275,9 @@ s32 CARDMountAsync(s32 chan, void *workArea, CARDCallback detachCallback, CARDCa card->mountStep = 0; card->attached = TRUE; EXISetExiCallback(chan, 0); +#if DOLPHIN_REVISION >= 37 + OSCancelAlarm(&card->alarm); +#endif card->currentDir = 0; card->currentFat = 0; @@ -268,7 +300,12 @@ s32 CARDMount(s32 chan, void *workArea, CARDCallback detachCallback) { return __CARDSync(chan); } -static void DoUnmount(s32 chan) { +#if DOLPHIN_REVISION >= 37 +static void DoUnmount(s32 chan, s32 result) +#else +static void DoUnmount(s32 chan) +#endif +{ CARDControl *card; BOOL enabled; @@ -280,8 +317,15 @@ static void DoUnmount(s32 chan) { { EXISetExiCallback(chan, 0); EXIDetach(chan); +#if DOLPHIN_REVISION >= 37 + OSCancelAlarm(&card->alarm); +#endif card->attached = FALSE; +#if DOLPHIN_REVISION >= 37 + card->result = result; +#else card->result = CARD_RESULT_NOCARD; +#endif card->mountStep = 0; } OSRestoreInterrupts(enabled); @@ -296,6 +340,10 @@ s32 CARDUnmount(s32 chan) { result = __CARDGetControlBlock(chan, &card); if (result < 0) return result; +#if DOLPHIN_REVISION >= 37 + DoUnmount(chan, CARD_RESULT_NOCARD); +#else DoUnmount(chan); +#endif return CARD_RESULT_READY; } diff --git a/src/card/CARDRead.c b/src/card/CARDRead.c index 698ce86..c230b6f 100644 --- a/src/card/CARDRead.c +++ b/src/card/CARDRead.c @@ -79,10 +79,14 @@ static void ReadCallback(s32 chan, s32 result) { goto error; } +#if DOLPHIN_REVISION >= 37 + length = TRUNC(fileInfo->offset + card->sectorSize, card->sectorSize) - fileInfo->offset; +#else // something funky is going on here; these conflicting casts are needed to match both debug // and retail regalloc and codegen. Perhaps the macro is different, but for the life of me // i cant figure this one out. Fake for now. Maybe? Unless the macro is just weird. length = TRUNC((int)fileInfo->offset + (long)card->sectorSize + card->sectorSize - 1, card->sectorSize) - fileInfo->offset; +#endif fileInfo->length -= length; if (fileInfo->length <= 0) goto error; diff --git a/src/card/CARDStat.c b/src/card/CARDStat.c index 8277f87..a31bc43 100644 --- a/src/card/CARDStat.c +++ b/src/card/CARDStat.c @@ -18,6 +18,9 @@ static void UpdateIconOffsets(CARDDir *ent, CARDStat *stat) { stat->bannerFormat = 0; stat->iconFormat = 0; stat->iconSpeed = 0; +#if DOLPHIN_REVISION >= 37 + offset = 0; +#endif } iconTlut = FALSE; @@ -119,8 +122,15 @@ s32 CARDSetStatusAsync(s32 chan, s32 fileNo, CARDStat *stat, CARDCallback callba ASSERTLINE(0xD5, 0 <= fileNo && fileNo < CARD_MAX_FILE); ASSERTLINE(0xD6, 0 <= chan && chan < 2); +#if DOLPHIN_REVISION >= 37 + if (fileNo < 0 || CARD_MAX_FILE <= fileNo || (stat->iconAddr != 0xffffffff && CARD_READ_SIZE <= stat->iconAddr) + || (stat->commentAddr != 0xffffffff + && CARD_SYSTEM_BLOCK_SIZE - CARD_COMMENT_SIZE < stat->commentAddr % CARD_SYSTEM_BLOCK_SIZE)) + return CARD_RESULT_FATAL_ERROR; +#else if (fileNo < 0 || CARD_MAX_FILE <= fileNo) return CARD_RESULT_FATAL_ERROR; +#endif result = __CARDGetControlBlock(chan, &card); if (result < 0) @@ -139,6 +149,11 @@ s32 CARDSetStatusAsync(s32 chan, s32 fileNo, CARDStat *stat, CARDCallback callba ent->commentAddr = stat->commentAddr; UpdateIconOffsets(ent, stat); +#if DOLPHIN_REVISION >= 37 + if (ent->iconAddr == 0xffffffff) + __CARDSetIconSpeed(ent, 0, CARD_STAT_SPEED_FAST); +#endif + ent->time = (u32)OSTicksToSeconds(OSGetTime()); result = __CARDUpdateDir(chan, callback); if (result < 0) diff --git a/src/card/CARDUnlock.c b/src/card/CARDUnlock.c index b29f5d2..7654e08 100644 --- a/src/card/CARDUnlock.c +++ b/src/card/CARDUnlock.c @@ -368,6 +368,9 @@ static void DoneCallback(void *_task) { EXIUnlock(chan); __CARDMountCallback(chan, CARD_RESULT_NOCARD); +#if DOLPHIN_REVISION >= 37 + return; +#endif } rshift = (u32)((dummy + 4 + card->latency) * 8 + 1); @@ -382,12 +385,18 @@ static void DoneCallback(void *_task) { EXIUnlock(chan); __CARDMountCallback(chan, CARD_RESULT_NOCARD); +#if DOLPHIN_REVISION >= 37 + return; +#endif } result = __CARDReadStatus(chan, &unk); if (!EXIProbe(chan)) { EXIUnlock(chan); __CARDMountCallback(chan, CARD_RESULT_NOCARD); +#if DOLPHIN_REVISION >= 37 + return; +#endif } if (result == CARD_RESULT_READY && !(unk & 0x40)) { diff --git a/src/card/__card.h b/src/card/__card.h index caea3d8..ee95e55 100644 --- a/src/card/__card.h +++ b/src/card/__card.h @@ -4,6 +4,9 @@ #include #include +#define __CARDSetIconSpeed(stat, n, f) \ + ((stat)->iconSpeed = (u16)(((stat)->iconSpeed & ~(CARD_STAT_SPEED_MASK << (2 * (n)))) | ((f) << (2 * (n))))) + // CARDStatEx.c long __CARDGetStatusEx(long chan, long fileNo, struct CARDDir * dirent); long __CARDSetStatusExAsync(long chan, long fileNo, struct CARDDir * dirent, void (* callback)(long, long)); diff --git a/src/dvd/__dvd.h b/src/dvd/__dvd.h index e2ee7bf..2191e4c 100644 --- a/src/dvd/__dvd.h +++ b/src/dvd/__dvd.h @@ -5,6 +5,7 @@ // dvd.c void __DVDAudioBufferConfig(struct DVDCommandBlock * block, unsigned long enable, unsigned long size, void (* callback)(long, struct DVDCommandBlock *)); +void __DVDPrepareResetAsync(DVDCBCallback callback); // dvdfs.c extern struct OSThreadQueue __DVDThreadQueue; @@ -13,6 +14,9 @@ extern unsigned long __DVDLongFileNameFlag; void __DVDFSInit(); // dvdlow.c +#if DOLPHIN_REVISION >= 37 +void __DVDInitWA(void); +#endif void __DVDInterruptHandler(short unused, struct OSContext * context); // dvdqueue.c diff --git a/src/dvd/dvd.c b/src/dvd/dvd.c index 8e23d77..d427378 100644 --- a/src/dvd/dvd.c +++ b/src/dvd/dvd.c @@ -7,20 +7,30 @@ static unsigned char * tmpBuffer[32] ATTRIBUTE_ALIGN(32); static struct DVDCommandBlock DummyCommandBlock; +#if DOLPHIN_REVISION >= 37 +static OSAlarm ResetAlarm; +#endif static int autoInvalidation = 1; - +#if DOLPHIN_REVISION >= 37 +static OSThreadQueue __DVDThreadQueue; +#endif static struct DVDCommandBlock *executing; +#if DOLPHIN_REVISION < 37 static void * tmp; +#endif static struct DVDDiskID * currID; static struct OSBootInfo_s * bootInfo; static volatile int PauseFlag; static volatile int PausingFlag; static int AutoFinishing; +#if DOLPHIN_REVISION >= 37 +static int FatalErrorFlag; +#endif static volatile unsigned long CurrCommand; static volatile unsigned long Canceling; static struct DVDCommandBlock * CancelingCommandBlock; -static void (* CancelCallback)(long, struct DVDCommandBlock *); +static DVDCBCallback CancelCallback; static volatile unsigned long ResumeFromHere; static volatile unsigned long CancelLastError; static unsigned long LastError; @@ -35,6 +45,9 @@ void (* LastState)(struct DVDCommandBlock *); static void stateReadingFST(); static void cbForStateReadingFST(unsigned long intType); +#if DOLPHIN_REVISION >= 37 +static void stateTimeout(void); +#endif static void stateError(); static void stateGettingError(); static unsigned long CategorizeError(unsigned long error); @@ -70,9 +83,15 @@ static void cbForCancelAllSync(); void DVDInit() { if (DVDInitialized == 0) { +#if DOLPHIN_REVISION >= 37 + OSInitAlarm(); +#endif DVDInitialized = 1; __DVDFSInit(); __DVDClearWaitingQueue(); +#if DOLPHIN_REVISION >= 37 + __DVDInitWA(); +#endif bootInfo = (void*)OSPhysicalToCached(0); currID = &bootInfo->DVDDiskID; __OSSetInterruptHandler(0x15, __DVDInterruptHandler); @@ -104,6 +123,14 @@ static void stateReadingFST() { static void cbForStateReadingFST(unsigned long intType) { struct DVDCommandBlock * finished; +#if DOLPHIN_REVISION >= 37 + if (intType == 16) { + executing->state = -1; + stateTimeout(); + return; + } +#endif + ASSERTLINE(0x229, (intType & DVD_INTTYPE_CVR) == 0); if (intType & 1) { ASSERTLINE(0x22E, (intType & DVD_INTTYPE_DE) == 0); @@ -121,6 +148,55 @@ static void cbForStateReadingFST(unsigned long intType) { stateGettingError(); } +#if DOLPHIN_REVISION >= 37 +#pragma dont_inline on +static void cbForStateError(u32 intType) { + struct DVDCommandBlock *r31; + + if (intType == 16) { + executing->state = -1; + stateTimeout(); + return; + } + FatalErrorFlag = 1; + r31 = executing; + executing = &DummyCommandBlock; + if (r31->callback) { + r31->callback(-1, r31); + } + if (Canceling) { + Canceling = 0; + if (CancelCallback) { + CancelCallback(0, r31); + } + } + stateReady(); +} +#pragma dont_inline reset + +void __DVDStoreErrorCode(u32); + +static void stateTimeout(void) { + struct DVDCommandBlock *r31; + + __DVDStoreErrorCode(0x1234568); + DVDReset(); + FatalErrorFlag = 1; + r31 = executing; + executing = &DummyCommandBlock; + if (r31->callback) { + r31->callback(-1, r31); + } + if (Canceling) { + Canceling = 0; + if (CancelCallback) { + CancelCallback(0, r31); + } + } + stateReady(); +} +#endif + static void stateError() { struct DVDCommandBlock * finished; int unused; @@ -137,24 +213,44 @@ static void stateGettingError() { } static unsigned long CategorizeError(unsigned long error) { +#if DOLPHIN_REVISION >= 37 + if (error == 0x20400) { + LastError = error; + return 1; + } +#else if (error == 1) { return 1; } +#endif error &= 0x00FFFFFF; +#if DOLPHIN_REVISION < 37 if (error == 0x31100) { return 2; } +#endif if ((error == 0x62800) || (error == 0x23A00) || (error == 0xB5A01)) { return 0; } NumInternalRetry += 1; if (NumInternalRetry == 2) { if (error == LastError) { +#if DOLPHIN_REVISION >= 37 + LastError = error; // why? +#endif return 1; } +#if DOLPHIN_REVISION >= 37 + LastError = error; +#endif return 2; } LastError = error; +#if DOLPHIN_REVISION >= 37 + if (error == 0x31100 || executing->command == 5) { + return 2; + } +#endif return 3; } @@ -173,22 +269,54 @@ static int ResetWorkAround(unsigned long error) { return 0; } +#if DOLPHIN_REVISION >= 37 +void cbForUnrecoveredError(u32 intType); +#endif + static void cbForStateGettingError(unsigned long intType) { +#if DOLPHIN_REVISION >= 37 + struct DVDCommandBlock * finished; +#endif unsigned long error; unsigned long status; long result; unsigned long errorCategory; +#if DOLPHIN_REVISION < 37 struct DVDCommandBlock * finished; +#endif +#if DOLPHIN_REVISION >= 37 + if (intType == 0x10) { + executing->state = -1; + __DVDStoreErrorCode(0x1234568); + DVDReset(); + cbForStateError(0); + return; + } +#endif if (intType & DVD_INTTYPE_DE) { executing->state = DVD_STATE_FATAL_ERROR; +#if DOLPHIN_REVISION >= 37 + __DVDStoreErrorCode(0x1234567); + DVDLowStopMotor(cbForStateError); +#else stateError(0); +#endif return; } + ASSERTLINE(0x30F, intType == DVD_INTTYPE_TC); error = __DIRegs[8]; +#if DOLPHIN_REVISION >= 37 + status = error & 0xFF000000; +#endif errorCategory = CategorizeError(error); if (errorCategory == 1) { +#if DOLPHIN_REVISION >= 37 + executing->state = DVD_STATE_FATAL_ERROR; + __DVDStoreErrorCode(error); + DVDLowStopMotor(cbForStateError); +#else if (Canceling != 0U) { ResumeFromHere = 5; Canceling = 0; @@ -209,8 +337,77 @@ static void cbForStateGettingError(unsigned long intType) { } executing->state = DVD_STATE_FATAL_ERROR; stateError(error); +#endif return; - } else if (errorCategory == 2) { + } +#if DOLPHIN_REVISION >= 37 + else { + int r4; + int r0; + if (errorCategory == 2 || errorCategory == 3) { + r4 = 0; + } else if (status == 0x1000000) { + r4 = 4; + } else if (status == 0x2000000) { + r4 = 6; + } else if (status == 0x3000000) { + r4 = 3; + } else { + r4 = 5; + } + if (Canceling) { + ResumeFromHere = r4; + Canceling = 0; + finished = executing; + executing = &DummyCommandBlock; + finished->state = 10; + if (finished->callback) { + finished->callback(-3, finished); + } + if (CancelCallback) { + CancelCallback(0, finished); + } + stateReady(); + r0 = 1; + } + else { + r0 = 0; + } + if (r0) { + return; + } + if (errorCategory == 2) { + __DVDStoreErrorCode(error); + stateGoToRetry(); + return; + } else if (errorCategory == 3) { + if ((error & 0xFFFFFF) == 0x31100) { + DVDLowSeek(executing->offset, cbForUnrecoveredError); + return; + } + LastState(executing); + return; + } + if (status == 0x1000000) { + executing->state = 5; + stateMotorStopped(); + return; + } else if (status == 0x2000000) { + executing->state = 3; + stateCoverClosed(); + return; + } else if (status == 0x3000000) { + executing->state = 4; + stateMotorStopped(); + return; + } else { + executing->state = -1; + __DVDStoreErrorCode(0x1234567); + DVDLowStopMotor(cbForStateError); + } + } +#else + else if (errorCategory == 2) { stateGoToRetry(); return; } else if (errorCategory == 3) { @@ -245,9 +442,9 @@ static void cbForStateGettingError(unsigned long intType) { ASSERTLINE(0x37B, FALSE); executing->state = DVD_STATE_FATAL_ERROR; } - if (CurrCommand == DVD_COMMAND_INITSTREAM || CurrCommand == DVD_COMMAND_CANCELSTREAM - || CurrCommand == DVD_COMMAND_STOP_STREAM_AT_END || CurrCommand == DVD_COMMAND_REQUEST_AUDIO_ERROR - || CurrCommand == DVD_COMMAND_REQUEST_PLAY_ADDR || CurrCommand == DVD_COMMAND_REQUEST_START_ADDR + if (CurrCommand == DVD_COMMAND_INITSTREAM || CurrCommand == DVD_COMMAND_CANCELSTREAM + || CurrCommand == DVD_COMMAND_STOP_STREAM_AT_END || CurrCommand == DVD_COMMAND_REQUEST_AUDIO_ERROR + || CurrCommand == DVD_COMMAND_REQUEST_PLAY_ADDR || CurrCommand == DVD_COMMAND_REQUEST_START_ADDR || CurrCommand == DVD_COMMAND_REQUEST_LENGTH) { if ((status + 0xFF000000) == 0) { result = -3; @@ -300,24 +497,107 @@ static void cbForStateGettingError(unsigned long intType) { stateMotorStopped(); } return; - } + } +#endif } +#if DOLPHIN_REVISION >= 37 +static void cbForUnrecoveredErrorRetry(u32 intType); + +static void cbForUnrecoveredError(u32 intType) { + if (intType == 16) { + executing->state = -1; + __DVDStoreErrorCode(0x1234568); + DVDReset(); + cbForStateError(0); + return; + } + if (intType & 1) { + stateGoToRetry(); + } else { + DVDLowRequestError(cbForUnrecoveredErrorRetry); + } +} + +static void cbForUnrecoveredErrorRetry(u32 intType) +{ + if (intType == 16) { + executing->state = -1; + __DVDStoreErrorCode(0x1234568); + DVDReset(); + cbForStateError(0); + return; + } + executing->state = -1; + if (intType & 2) { + __DVDStoreErrorCode(0x1234567); + DVDLowStopMotor(cbForStateError); + } else { + __DVDStoreErrorCode(__DIRegs[8]); + DVDLowStopMotor(cbForStateError); + } +} + +#endif + static void stateGoToRetry() { DVDLowStopMotor(cbForStateGoToRetry); } +#if DOLPHIN_REVISION >= 37 +static int someinline(int arg0) +{ + struct DVDCommandBlock *r31; + + NumInternalRetry = 0; + if (Canceling != 0U) { + ResumeFromHere = arg0; + Canceling = 0U; + r31 = executing; + executing = &DummyCommandBlock; + r31->state = 10; + if (r31->callback) { + r31->callback(-3, r31); + } + if (CancelCallback) { + CancelCallback(0, r31); + } + stateReady(); + return 1; + } + return 0; +} +#endif + static void cbForStateGoToRetry(unsigned long intType) { struct DVDCommandBlock * finished; +#if DOLPHIN_REVISION >= 37 + int r0; +#endif + +#if DOLPHIN_REVISION >= 37 + if (intType == 16) { + executing->state = -1; + __DVDStoreErrorCode(0x1234568); + DVDReset(); + cbForStateError(0); + return; + } +#endif if (intType & 2) { executing->state = DVD_STATE_FATAL_ERROR; +#if DOLPHIN_REVISION >= 37 + __DVDStoreErrorCode(0x1234567); + DVDLowStopMotor(cbForStateError); +#else stateError(0); +#endif return; } ASSERTLINE(0x3D9, intType == DVD_INTTYPE_TC); NumInternalRetry = 0; - if ((CurrCommand == DVD_COMMAND_BSREAD) || (CurrCommand == DVD_COMMAND_READID) + if ((CurrCommand == DVD_COMMAND_BSREAD) || (CurrCommand == DVD_COMMAND_READID) || (CurrCommand == DVD_COMMAND_AUDIO_BUFFER_CONFIG) || (CurrCommand == DVD_COMMAND_BS_CHANGE_DISK)) { ResetRequired = 1; } @@ -326,37 +606,58 @@ static void cbForStateGoToRetry(unsigned long intType) { Canceling = 0; finished = executing; executing = &DummyCommandBlock; - if (finished->state == DVD_STATE_BUSY) { + if (DOLPHIN_REVISION >= 37 || finished->state == DVD_STATE_BUSY) { finished->state = DVD_STATE_CANCELED; if (finished->callback) { +#if DOLPHIN_REVISION >= 37 + finished->callback(-3, finished); +#else finished->callback(-6, finished); +#endif } if (CancelCallback) { CancelCallback(0, finished); } } +#if DOLPHIN_REVISION >= 37 + stateReady(); + r0 = 1; +#else stateReady(); return; +#endif } +#if DOLPHIN_REVISION >= 37 + else { + r0 = 0; + } + if (!r0) { + executing->state = DVD_STATE_RETRY; + stateMotorStopped(); + } +#else executing->state = DVD_STATE_RETRY; stateMotorStopped(); +#endif } static void stateCheckID() { switch(CurrCommand) { +#if DOLPHIN_REVISION < 37 case DVD_COMMAND_READ: case DVD_COMMAND_SEEK: if (memcmp(&tmpBuffer, currID, 0x20)) { DVDLowStopMotor(cbForStateCheckID1); - return; + break; } LastState = stateCheckID3; stateCheckID3(executing); return; +#endif case DVD_COMMAND_CHANGE_DISK: if (memcmp(&tmpBuffer, executing->id, 0x1C)) { DVDLowStopMotor(cbForStateCheckID1); - return; + break; } memcpy(currID, &tmpBuffer, 0x20); executing->state = DVD_STATE_BUSY; @@ -364,9 +665,20 @@ static void stateCheckID() { LastState = stateCheckID2; stateCheckID2(executing); break; +#if DOLPHIN_REVISION >= 37 + default: + if (memcmp(&tmpBuffer, currID, 0x20)) { + DVDLowStopMotor(cbForStateCheckID1); + break; + } + LastState = stateCheckID3; + stateCheckID3(executing); + break; +#else default: ASSERTLINE(0x452, FALSE); - return; + break; +#endif } } @@ -379,12 +691,32 @@ static void stateCheckID2() { } static void cbForStateCheckID1(unsigned long intType) { +#if DOLPHIN_REVISION >= 37 + if (intType == 16) { + executing->state = -1; + __DVDStoreErrorCode(0x1234568); + DVDReset(); + cbForStateError(0); + return; + } +#endif if (intType & DVD_INTTYPE_DE) { executing->state = DVD_STATE_FATAL_ERROR; +#if DOLPHIN_REVISION >= 37 + __DVDStoreErrorCode(0x1234567); + DVDLowStopMotor(cbForStateError); +#else stateError(0); +#endif return; } + ASSERTLINE(0x478, intType == DVD_INTTYPE_TC); +#if DOLPHIN_REVISION >= 37 + if (someinline(1)) { + return; + } +#else NumInternalRetry = 0; if (Canceling != 0U) { ResumeFromHere = 1; @@ -392,11 +724,21 @@ static void cbForStateCheckID1(unsigned long intType) { stateReady(); return; } +#endif executing->state = DVD_STATE_WRONG_DISK; stateMotorStopped(); } static void cbForStateCheckID2(unsigned long intType) { +#if DOLPHIN_REVISION >= 37 + if (intType == 16) { + executing->state = -1; + __DVDStoreErrorCode(0x1234568); + DVDReset(); + cbForStateError(0); + return; + } +#endif ASSERTLINE(0x494, (intType & DVD_INTTYPE_CVR) == 0); if (intType & DVD_INTTYPE_TC) { ASSERTLINE(0x499, (intType & DVD_INTTYPE_DE) == 0); @@ -409,9 +751,24 @@ static void cbForStateCheckID2(unsigned long intType) { } static void cbForStateCheckID3(unsigned long intType) { +#if DOLPHIN_REVISION >= 37 + if (intType == 16) { + executing->state = -1; + __DVDStoreErrorCode(0x1234568); + DVDReset(); + cbForStateError(0); + return; + } +#endif + ASSERTLINE(0x4B4, (intType & DVD_INTTYPE_CVR) == 0); if (intType & DVD_INTTYPE_TC) { ASSERTLINE(0x4B9, (intType & DVD_INTTYPE_DE) == 0); +#if DOLPHIN_REVISION >= 37 + if (someinline(0)) { + return; + } +#else NumInternalRetry = 0; if (Canceling != 0) { ResumeFromHere = 0; @@ -419,6 +776,7 @@ static void cbForStateCheckID3(unsigned long intType) { stateReady(); return; } +#endif executing->state = DVD_STATE_BUSY; stateBusy(executing); return; @@ -427,6 +785,15 @@ static void cbForStateCheckID3(unsigned long intType) { stateGettingError(); } +#if DOLPHIN_REVISION >= 37 +static void AlarmHandler(OSAlarm *alarm, OSContext *context) { + DVDReset(); + DCInvalidateRange(&tmpBuffer, 0x20); + LastState = stateCoverClosed_CMD; + stateCoverClosed_CMD(executing); +} +#endif + static void stateCoverClosed() { struct DVDCommandBlock * finished; @@ -439,15 +806,24 @@ static void stateCoverClosed() { finished = executing; executing = &DummyCommandBlock; if (finished->callback) { +#if DOLPHIN_REVISION >= 37 + finished->callback(-4, finished); +#else finished->callback(-2, finished); +#endif } stateReady(); return; } DVDReset(); +#if DOLPHIN_REVISION >= 37 + OSCreateAlarm(&ResetAlarm); + OSSetAlarm(&ResetAlarm, OSMillisecondsToTicks(1150), AlarmHandler); +#else DCInvalidateRange(&tmpBuffer, 0x20); LastState = stateCoverClosed_CMD; stateCoverClosed_CMD(executing); +#endif return; } @@ -456,6 +832,15 @@ static void stateCoverClosed_CMD() { } static void cbForStateCoverClosed(unsigned long intType) { +#if DOLPHIN_REVISION >= 37 + if (intType == 16) { + executing->state = -1; + __DVDStoreErrorCode(0x1234568); + DVDReset(); + cbForStateError(0); + return; + } +#endif ASSERTLINE(0x510, (intType & DVD_INTTYPE_CVR) == 0); if (intType & DVD_INTTYPE_TC) { ASSERTLINE(0x515, (intType & DVD_INTTYPE_DE) == 0); @@ -480,6 +865,10 @@ static void cbForStateMotorStopped(unsigned long intType) { } static void stateReady() { +#if DOLPHIN_REVISION >= 37 + struct DVDCommandBlock * finished; +#endif + if (__DVDCheckWaitingQueue() == 0) { executing = NULL; return; @@ -490,6 +879,18 @@ static void stateReady() { return; } executing = __DVDPopWaitingQueue(); +#if DOLPHIN_REVISION >= 37 + if (FatalErrorFlag) { + executing->state = -1; + finished = executing; + executing = &DummyCommandBlock; + if (finished->callback) { + finished->callback(-1, finished); + } + stateReady(); + return; + } +#endif CurrCommand = executing->command; if (ResumeFromHere != 0) { switch (ResumeFromHere) { @@ -519,7 +920,12 @@ static void stateReady() { break; case 5: executing->state = DVD_STATE_FATAL_ERROR; +#if DOLPHIN_REVISION >= 37 + __DVDStoreErrorCode(CancelLastError); + DVDLowStopMotor(cbForStateError); +#else stateError(CancelLastError); +#endif break; } ResumeFromHere = 0; @@ -540,7 +946,11 @@ static void stateBusy(struct DVDCommandBlock * block) { case DVD_COMMAND_READ: case DVD_COMMAND_BSREAD: __DIRegs[1] = __DIRegs[1]; +#if DOLPHIN_REVISION >= 37 + block->currTransferSize = (block->length - block->transferredSize > 0x80000) ? 0x80000 : (block->length - block->transferredSize); +#else block->currTransferSize = (block->length - block->transferredSize > 0x600000) ? 0x600000 : (block->length - block->transferredSize); +#endif DVDLowRead((char*)block->addr + block->transferredSize, block->currTransferSize, block->offset + block->transferredSize, cbForStateBusy); return; case DVD_COMMAND_SEEK: @@ -603,11 +1013,28 @@ static void stateBusy(struct DVDCommandBlock * block) { static void cbForStateBusy(unsigned long intType) { struct DVDCommandBlock * finished; long result; +#if DOLPHIN_REVISION >= 37 + BOOL r0; +#endif +#if DOLPHIN_REVISION >= 37 + if (intType == 16) { + executing->state = -1; + __DVDStoreErrorCode(0x1234568); + DVDReset(); + cbForStateError(0); + return; + } +#endif if ((CurrCommand == DVD_COMMAND_CHANGE_DISK) || (CurrCommand == DVD_COMMAND_BS_CHANGE_DISK)) { if (intType & DVD_INTTYPE_DE) { executing->state = DVD_STATE_FATAL_ERROR; +#if DOLPHIN_REVISION >= 37 + __DVDStoreErrorCode(0x1234567); + DVDLowStopMotor(cbForStateError); +#else stateError(0U); +#endif return; } ASSERTLINE(0x64B, intType == DVD_INTTYPE_TC); @@ -616,26 +1043,47 @@ static void cbForStateBusy(unsigned long intType) { ResetRequired = 1; } if (Canceling != 0U) { +#if DOLPHIN_REVISION >= 37 + ResumeFromHere = 7; + Canceling = 0; +#else Canceling = 0; ResumeFromHere = 7; +#endif finished = executing; executing = &DummyCommandBlock; finished->state = DVD_STATE_CANCELED; if (finished->callback) { +#if DOLPHIN_REVISION >= 37 + finished->callback(-3, finished); +#else finished->callback(-6, finished); +#endif } if (CancelCallback) { CancelCallback(0, finished); } stateReady(); +#if DOLPHIN_REVISION >= 37 + r0 = TRUE; +#else + return; +#endif + } +#if DOLPHIN_REVISION >= 37 + else { + r0 = FALSE; + } + if (r0) { return; } +#endif executing->state = DVD_STATE_MOTOR_STOPPED; stateMotorStopped(); return; } ASSERTLINE(0x671, (intType & DVD_INTTYPE_CVR) == 0); - if ((CurrCommand == DVD_COMMAND_READ) || (CurrCommand == DVD_COMMAND_BSREAD) + if ((CurrCommand == DVD_COMMAND_READ) || (CurrCommand == DVD_COMMAND_BSREAD) || (CurrCommand == DVD_COMMAND_READID) || (CurrCommand == DVD_COMMAND_INQUIRY)) { executing->transferredSize += executing->currTransferSize - __DIRegs[6]; } @@ -645,7 +1093,11 @@ static void cbForStateBusy(unsigned long intType) { executing = &DummyCommandBlock; finished->state = DVD_STATE_CANCELED; if (finished->callback) { +#if DOLPHIN_REVISION >= 37 + finished->callback(-3, finished); +#else finished->callback(-6, finished); +#endif } if (CancelCallback) { CancelCallback(0, finished); @@ -655,6 +1107,11 @@ static void cbForStateBusy(unsigned long intType) { } if (intType & 1) { ASSERTLINE(0x697, (intType & DVD_INTTYPE_DE) == 0); +#if DOLPHIN_REVISION >= 37 + if (someinline(0)) { + return; + } +#else NumInternalRetry = 0; if (Canceling != 0U) { Canceling = 0; @@ -670,7 +1127,8 @@ static void cbForStateBusy(unsigned long intType) { stateReady(); return; } - if (CurrCommand == DVD_COMMAND_READ || CurrCommand == DVD_COMMAND_BSREAD +#endif + if (CurrCommand == DVD_COMMAND_READ || CurrCommand == DVD_COMMAND_BSREAD || CurrCommand == DVD_COMMAND_READID || CurrCommand == DVD_COMMAND_INQUIRY) { if (executing->transferredSize != executing->length) { stateBusy(executing); @@ -684,9 +1142,9 @@ static void cbForStateBusy(unsigned long intType) { } stateReady(); return; - } else if (CurrCommand == DVD_COMMAND_REQUEST_AUDIO_ERROR || CurrCommand == DVD_COMMAND_REQUEST_PLAY_ADDR + } else if (CurrCommand == DVD_COMMAND_REQUEST_AUDIO_ERROR || CurrCommand == DVD_COMMAND_REQUEST_PLAY_ADDR || CurrCommand == DVD_COMMAND_REQUEST_START_ADDR || CurrCommand == DVD_COMMAND_REQUEST_LENGTH) { - + if (CurrCommand == DVD_COMMAND_REQUEST_START_ADDR || CurrCommand == DVD_COMMAND_REQUEST_PLAY_ADDR) { result = __DIRegs[8] * 4; } else { @@ -708,7 +1166,11 @@ static void cbForStateBusy(unsigned long intType) { executing = &DummyCommandBlock; finished->state = DVD_STATE_IGNORED; if (finished->callback) { +#if DOLPHIN_REVISION >= 37 + finished->callback(-2, finished); +#else finished->callback(-5, finished); +#endif } stateReady(); return; @@ -737,7 +1199,47 @@ static void cbForStateBusy(unsigned long intType) { return; } } else { +#if DOLPHIN_REVISION >= 37 + if (CurrCommand == 14) { + executing->state = -1; + __DVDStoreErrorCode(0x1234567); + DVDLowStopMotor(cbForStateError); + return; + } + if ((CurrCommand == 1 || CurrCommand == 4 || CurrCommand == 5 || CurrCommand == 14) + && executing->transferredSize == executing->length) { + if (Canceling != 0U) { + ResumeFromHere = 0; + Canceling = 0; + finished = executing; + executing = &DummyCommandBlock; + finished->state = DVD_STATE_CANCELED; + if (finished->callback) { + finished->callback(-3, finished); + } + if (CancelCallback) { + CancelCallback(0, finished); + } + stateReady(); + r0 = TRUE; + } else { + r0 = FALSE; + } + if (r0) { + return; + } + finished = executing; + executing = &DummyCommandBlock; + finished->state = 0; + if (finished->callback) { + finished->callback(finished->transferredSize, finished); + } + stateReady(); + return; + } +#else ASSERTLINE(0x728, intType == DVD_INTTYPE_DE); +#endif stateGettingError(); } } @@ -746,7 +1248,7 @@ static int issueCommand(long prio, struct DVDCommandBlock * block) { int level; int result; - if (autoInvalidation != 0 && (block->command == DVD_COMMAND_READ || block->command == DVD_COMMAND_BSREAD + if (autoInvalidation != 0 && (block->command == DVD_COMMAND_READ || block->command == DVD_COMMAND_BSREAD || block->command == DVD_COMMAND_READID || block->command == DVD_COMMAND_INQUIRY)) { DCInvalidateRange(block->addr, block->length); } @@ -863,7 +1365,7 @@ long DVDCancelStream(struct DVDCommandBlock * block) { result = DVDCancelStreamAsync(block, cbForCancelStreamSync); if (result == 0) { - return -1; + return -1; } enabled = OSDisableInterrupts(); @@ -872,7 +1374,7 @@ long DVDCancelStream(struct DVDCommandBlock * block) { if (state != DVD_STATE_BUSY && state != DVD_STATE_WAITING) { retVal = ResultForSyncCommand; break; - } + } OSSleepThread(&__DVDThreadQueue); } OSRestoreInterrupts(enabled); @@ -901,7 +1403,7 @@ long DVDStopStreamAtEnd(struct DVDCommandBlock * block) { result = DVDStopStreamAtEndAsync(block, cbForStopStreamAtEndSync); if (result == 0) { - return -1; + return -1; } enabled = OSDisableInterrupts(); @@ -910,7 +1412,7 @@ long DVDStopStreamAtEnd(struct DVDCommandBlock * block) { if (state != DVD_STATE_BUSY && state != DVD_STATE_WAITING) { retVal = ResultForSyncCommand; break; - } + } OSSleepThread(&__DVDThreadQueue); } OSRestoreInterrupts(enabled); @@ -948,7 +1450,7 @@ long DVDGetStreamErrorStatus(struct DVDCommandBlock * block) { if (state != DVD_STATE_BUSY && state != DVD_STATE_WAITING) { retVal = ResultForSyncCommand; break; - } + } OSSleepThread(&__DVDThreadQueue); } OSRestoreInterrupts(enabled); @@ -986,7 +1488,7 @@ long DVDGetStreamPlayAddr(struct DVDCommandBlock * block) { if (state != DVD_STATE_BUSY && state != DVD_STATE_WAITING) { retVal = ResultForSyncCommand; break; - } + } OSSleepThread(&__DVDThreadQueue); } OSRestoreInterrupts(enabled); @@ -1024,7 +1526,7 @@ long DVDGetStreamStartAddr(struct DVDCommandBlock * block) { if (state != DVD_STATE_BUSY && state != DVD_STATE_WAITING) { retVal = ResultForSyncCommand; break; - } + } OSSleepThread(&__DVDThreadQueue); } OSRestoreInterrupts(enabled); @@ -1062,7 +1564,7 @@ long DVDGetStreamLength(struct DVDCommandBlock * block) { if (state != DVD_STATE_BUSY && state != DVD_STATE_WAITING) { retVal = ResultForSyncCommand; break; - } + } OSSleepThread(&__DVDThreadQueue); } OSRestoreInterrupts(enabled); @@ -1168,7 +1670,7 @@ long DVDInquiry(struct DVDCommandBlock * block, struct DVDDriveInfo * info) { enabled = OSDisableInterrupts(); while(1) { state = block->state; - if (state != DVD_STATE_BUSY && state != DVD_STATE_WAITING) { + if (state != DVD_STATE_BUSY && state != DVD_STATE_WAITING) { retVal = ResultForSyncCommand; break; } @@ -1204,6 +1706,34 @@ long DVDGetCommandBlockStatus(struct DVDCommandBlock * block) { } long DVDGetDriveStatus() { +#if DOLPHIN_REVISION >= 37 + s32 status; + BOOL enabled; + u8 unused[8]; + + enabled = OSDisableInterrupts(); + if (FatalErrorFlag) { + status = -1; + } else if (PausingFlag) { + status = 8; + } else { + struct DVDCommandBlock *block = executing; + if (block == NULL) { + status = 0; + } else if (block == &DummyCommandBlock) { + status = 0; + } else { + BOOL enabled = OSDisableInterrupts(); + status = block->state; + if (status == 3) { + status = 1; + } + OSRestoreInterrupts(enabled); + } + } + OSRestoreInterrupts(enabled); + return status; +#else struct DVDCommandBlock * block; if (PausingFlag != 0) { @@ -1217,6 +1747,7 @@ long DVDGetDriveStatus() { return 0; } return block->state; +#endif } int DVDSetAutoInvalidation(int autoInval) { @@ -1255,8 +1786,10 @@ int DVDCancelAsync(struct DVDCommandBlock * block, void (* callback)(long, struc void (* old)(unsigned long); enabled = OSDisableInterrupts(); +#if DOLPHIN_REVISION < 37 Canceling = 0; CancelCallback = NULL; +#endif switch(block->state) { case DVD_STATE_FATAL_ERROR: @@ -1272,17 +1805,23 @@ int DVDCancelAsync(struct DVDCommandBlock * block, void (* callback)(long, struc return 0; } Canceling = 1; +#if DOLPHIN_REVISION < 37 CancelingCommandBlock = block; +#endif CancelCallback = callback; if (block->command == DVD_COMMAND_BSREAD || block->command == DVD_COMMAND_READ) { DVDLowBreak(); } break; - case DVD_STATE_WAITING: + case DVD_STATE_WAITING: __DVDDequeueWaitingQueue(block); block->state = DVD_STATE_CANCELED; if (block->callback) { +#if DOLPHIN_REVISION >= 37 + block->callback(-3, block); +#else block->callback(-6, block); +#endif } if (callback) { callback(0, block); @@ -1290,20 +1829,27 @@ int DVDCancelAsync(struct DVDCommandBlock * block, void (* callback)(long, struc break; case DVD_STATE_COVER_CLOSED: switch(block->command) { - case DVD_COMMAND_BSREAD: - case DVD_COMMAND_READID: - case DVD_COMMAND_AUDIO_BUFFER_CONFIG: + case DVD_COMMAND_BSREAD: + case DVD_COMMAND_READID: + case DVD_COMMAND_AUDIO_BUFFER_CONFIG: case DVD_COMMAND_BS_CHANGE_DISK: if (callback) { callback(0, block); } break; +#if DOLPHIN_REVISION >= 37 + default: +#else case DVD_COMMAND_READ: +#endif if (Canceling != 0U) { OSRestoreInterrupts(enabled); return 0; } Canceling = 1U; +#if DOLPHIN_REVISION >= 37 + CancelCallback = callback; +#else CancelingCommandBlock = block; block->state = DVD_STATE_CANCELED; if (block->callback) { @@ -1312,6 +1858,7 @@ int DVDCancelAsync(struct DVDCommandBlock * block, void (* callback)(long, struc if (callback) { callback(0, block); } +#endif break; } break; @@ -1323,6 +1870,9 @@ int DVDCancelAsync(struct DVDCommandBlock * block, void (* callback)(long, struc old = DVDLowClearCallback(); ASSERTLINE(0xBDB, old == cbForStateMotorStopped); if (old != cbForStateMotorStopped) { +#if DOLPHIN_REVISION >= 37 + OSRestoreInterrupts(enabled); +#endif return 0; } if (block->state == DVD_STATE_NO_DISK) { @@ -1342,7 +1892,11 @@ int DVDCancelAsync(struct DVDCommandBlock * block, void (* callback)(long, struc } block->state = DVD_STATE_CANCELED; if (block->callback) { +#if DOLPHIN_REVISION >= 37 + block->callback(-3, block); +#else block->callback(-6, block); +#endif } if (callback) { callback(0, block); @@ -1439,3 +1993,92 @@ static void cbForCancelAllSync() { struct DVDDiskID * DVDGetCurrentDiskID() { return (void*)OSPhysicalToCached(0); } + +#if DOLPHIN_REVISION >= 37 +BOOL DVDCheckDisk(void) { + BOOL enabled = OSDisableInterrupts(); + int r4; + BOOL ret; + u32 reg; + + if (FatalErrorFlag) { + r4 = -1; + } else if (PausingFlag) { + r4 = 8; + } else if (executing == NULL) { + r4 = 0; + } else if (executing == &DummyCommandBlock) { + r4 = 0; + } else { + r4 = executing->state; + } + switch (r4) { + case 1: + case 2: + case 9: + case 10: + ret = TRUE; + break; + case -1: + case 3: + case 4: + case 5: + case 6: + case 7: + case 11: + ret = FALSE; + break; + case 0: + case 8: + reg = __DIRegs[1]; + if (((reg >> 2) & 1) || (reg & 1)) + ret = FALSE; + else + ret = TRUE; + break; + } + OSRestoreInterrupts(enabled); + return ret; +} + +void __DVDPrepareResetAsync(DVDCBCallback callback) { + BOOL enabled3; + BOOL enabled2; + BOOL enabled4; + BOOL enabled = OSDisableInterrupts(); + DVDCommandBlock *block; + + __DVDClearWaitingQueue(); + if (Canceling) { + CancelCallback = callback; + } else { + if (executing) { + executing->callback = NULL; + } + enabled2 = OSDisableInterrupts(); + enabled3 = OSDisableInterrupts(); + PauseFlag = 1; + if (executing == NULL) { + PausingFlag = 1; + } + OSRestoreInterrupts(enabled3); + while ((block = __DVDPopWaitingQueue()) != NULL) { + DVDCancelAsync(block, 0); + } + if (executing) { + DVDCancelAsync(executing, callback); + } else if (callback) { + callback(0, NULL); + } + enabled4 = OSDisableInterrupts(); + PauseFlag = 0; + if (PausingFlag) { + PausingFlag = 0; + stateReady(); + } + OSRestoreInterrupts(enabled4); + OSRestoreInterrupts(enabled2); + } + OSRestoreInterrupts(enabled); +} +#endif diff --git a/src/dvd/dvderror.c b/src/dvd/dvderror.c new file mode 100644 index 0000000..37b83bc --- /dev/null +++ b/src/dvd/dvderror.c @@ -0,0 +1,59 @@ +#if DOLPHIN_REVISION >= 37 + +#include +#include + +#include "__dvd.h" +#include "__os.h" + +static u32 ErrorTable[] = { + 0, 0x00023A00, 0x00062800, 0x00030200, 0x00031100, 0x00052000, + 0x00052001, 0x00052100, 0x00052400, 0x00052401, 0x00052402, 0x000B5A01, + 0x00056300, 0x00020401, 0x00020400, 0x00040800 +}; + +static u8 ErrorCode2Num(u32 errorCode) { + u32 i; + + for (i = 0; i < sizeof(ErrorTable) / sizeof(ErrorTable[0]); i++) { + if (ErrorTable[i] == errorCode) { + return (u8)i; + } + } + + return 29; +} + +static u8 Convert(u32 error) { + u32 statusCode; + u32 errorCode; + u8 errorNum; + + if (error == 0x01234567) + return 255; + + if (error == 0x01234568) + return 254; + + statusCode = (error & 0xff000000) >> 24; + errorCode = error & 0x00ffffff; + + errorNum = ErrorCode2Num(errorCode); + if (statusCode >= 6) + statusCode = 6; + + return (u8)(statusCode * 30 + errorNum); +} + +void __DVDStoreErrorCode(u32 error) { + OSSramEx* sram; + u8 num; + + num = Convert(error); + + sram = __OSLockSramEx(); + sram->dvdErrorCode = num; + __OSUnlockSramEx(TRUE); +} + +#endif diff --git a/src/dvd/dvdfs.c b/src/dvd/dvdfs.c index 70ced01..aefade9 100644 --- a/src/dvd/dvdfs.c +++ b/src/dvd/dvdfs.c @@ -61,6 +61,12 @@ static BOOL isSame(const char* path, const char* string) { return FALSE; } +#if DOLPHIN_REVISION >= 37 +#define LINEOFFS 10 +#else +#define LINEOFFS 0 +#endif + s32 DVDConvertPathToEntrynum(char* pathPtr) { const char* ptr; char* stringPtr; @@ -123,7 +129,7 @@ s32 DVDConvertPathToEntrynum(char* pathPtr) { illegal = TRUE; if (illegal) - OSPanic(__FILE__, 0x16B, + OSPanic(__FILE__, 0x16B+LINEOFFS, "DVDConvertEntrynumToPath(possibly DVDOpen or DVDChangeDir or DVDOpenDir): " "specified directory or file (%s) doesn't match standard 8.3 format. This is a " "temporary restriction and will be removed soon\n", @@ -307,11 +313,11 @@ BOOL DVDReadAsyncPrio(DVDFileInfo* fileInfo, void* addr, s32 length, s32 offset, ASSERTMSGLINE(0x2D0, !(offset & 3), "DVDReadAsync(): offset must be multiple of 4 byte "); if (!((0 <= offset) && (offset < fileInfo->length))) { - OSPanic(__FILE__, 0x2D5, "DVDReadAsync(): specified area is out of the file "); + OSPanic(__FILE__, 0x2D5+LINEOFFS, "DVDReadAsync(): specified area is out of the file "); } if (!((0 <= offset + length) && (offset + length < fileInfo->length + DVD_MIN_TRANSFER_SIZE))) { - OSPanic(__FILE__, 0x2DB, "DVDReadAsync(): specified area is out of the file "); + OSPanic(__FILE__, 0x2DB+LINEOFFS, "DVDReadAsync(): specified area is out of the file "); } fileInfo->callback = callback; @@ -495,6 +501,13 @@ void * DVDGetFSTLocation() { #define RoundUp32KB(x) (((u32)(x) + 32 * 1024 - 1) & ~(32 * 1024 - 1)) #define Is32KBAligned(x) (((u32)(x) & (32 * 1024 - 1)) == 0) +#undef LINEOFFS +#if DOLPHIN_REVISION >= 37 +#define LINEOFFS 12 +#else +#define LINEOFFS 0 +#endif + BOOL DVDPrepareStreamAsync(DVDFileInfo* fileInfo, u32 length, u32 offset, DVDCallback callback) { u32 start; @@ -503,7 +516,7 @@ BOOL DVDPrepareStreamAsync(DVDFileInfo* fileInfo, u32 length, u32 offset, DVDCal start = fileInfo->startAddr + offset; if (!Is32KBAligned(start)) { - OSPanic(__FILE__, 0x472, + OSPanic(__FILE__, 0x472+LINEOFFS, "DVDPrepareStreamAsync(): Specified start address (filestart(0x%x) + offset(0x%x)) is " "not 32KB aligned", fileInfo->startAddr, offset); @@ -513,13 +526,13 @@ BOOL DVDPrepareStreamAsync(DVDFileInfo* fileInfo, u32 length, u32 offset, DVDCal length = fileInfo->length - offset; if (!Is32KBAligned(length)) { - OSPanic(__FILE__, 0x47C, + OSPanic(__FILE__, 0x47C+LINEOFFS, "DVDPrepareStreamAsync(): Specified length (0x%x) is not a multiple of 32768(32*1024)", length); } if (!((offset < fileInfo->length) && (offset + length <= fileInfo->length))) { - OSPanic(__FILE__, 0x484, + OSPanic(__FILE__, 0x484+LINEOFFS, "DVDPrepareStreamAsync(): The area specified (offset(0x%x), length(0x%x)) is out of " "the file", offset, length); diff --git a/src/dvd/dvdlow.c b/src/dvd/dvdlow.c index 0df114f..114dd40 100644 --- a/src/dvd/dvdlow.c +++ b/src/dvd/dvdlow.c @@ -5,12 +5,76 @@ #include "__os.h" // .sbss +#if DOLPHIN_REVISION >= 37 +static volatile BOOL StopAtNextInt; +static u32 LastLength; +#endif static void (* Callback)(unsigned long); // size: 0x4, address: 0x0 static void (* ResetCoverCallback)(unsigned long); // size: 0x4, address: 0x4 static volatile long long LastResetEnd; // size: 0x8, address: 0x8 static volatile unsigned long ResetOccurred; // size: 0x4, address: 0x10 -static int WaitingCoverClose; // size: 0x4, address: 0x14 +static volatile int WaitingCoverClose; // size: 0x4, address: 0x14 static volatile int Breaking; // size: 0x4, address: 0x18 +#if DOLPHIN_REVISION >= 37 +static volatile u32 WorkAroundType; +static s32 WorkAroundSeekLocation; +static volatile OSTime LastReadFinished; +static OSTime LastReadIssued; +static volatile BOOL LastCommandWasRead; +static volatile s32 NextCommandNumber; +static BOOL FirstRead = TRUE; +#endif + +#if DOLPHIN_REVISION >= 37 +static struct DVDCommand { + s32 command; + void *address; + u32 length; + u32 offset; + void (*callback)(u32); +} CommandList[3]; +static OSAlarm AlarmForWA; +static OSAlarm AlarmForTimeout; +static OSAlarm AlarmForBreak; +struct SomeStruct { + void *addr; + u32 length; + u32 offset; +}; +static struct SomeStruct Prev; +static struct SomeStruct Curr; +#endif + +#if DOLPHIN_REVISION >= 37 +static void Read(void *addr, u32 length, u32 offset, void (*callback)(u32)); +void __DVDLowSetWAType(u32 type, s32 seekLoc); + +void __DVDInitWA(void) { + NextCommandNumber = 0; + CommandList[0].command = -1; + __DVDLowSetWAType(0, 0); + OSInitAlarm(); +} + +static BOOL ProcessNextCommand(void) { + s32 n = NextCommandNumber; + + if (CommandList[n].command == 1) { + NextCommandNumber++; + Read( + CommandList[n].address, + CommandList[n].length, + CommandList[n].offset, + CommandList[n].callback); + return TRUE; + } else if (CommandList[n].command == 2) { + NextCommandNumber++; + DVDLowSeek(CommandList[n].offset, CommandList[n].callback); + return TRUE; + } + return FALSE; +} +#endif void __DVDInterruptHandler(short unused, struct OSContext * context) { struct OSContext exceptionContext; @@ -20,6 +84,21 @@ void __DVDInterruptHandler(short unused, struct OSContext * context) { unsigned long mask; cause = 0; +#if DOLPHIN_REVISION >= 37 + OSCancelAlarm(&AlarmForTimeout); + if (LastCommandWasRead) { + LastReadFinished = __OSGetSystemTime(); + FirstRead = FALSE; + Prev.addr = Curr.addr; + Prev.length = Curr.length; + Prev.offset = Curr.offset; + if (StopAtNextInt == TRUE) { + cause |= 8; + } + } + LastCommandWasRead = FALSE; + StopAtNextInt = FALSE; +#endif reg = __DIRegs[0]; mask = (reg & 0x0000002A); intr = (reg & 0x00000054) & (mask << 1); @@ -60,26 +139,200 @@ void __DVDInterruptHandler(short unused, struct OSContext * context) { } else { __DIRegs[1] = 0; } + if ((cause & 8) && (Breaking == 0)) { cause &= 0xFFFFFFF7; } +#if DOLPHIN_REVISION >= 37 + if (cause & 1) { + if (ProcessNextCommand()) { + return; + } + } + else { + CommandList[0].command = -1; + NextCommandNumber = 0; + } +#endif OSClearContext(&exceptionContext); OSSetCurrentContext(&exceptionContext); if (cause != 0) { +#if DOLPHIN_REVISION >= 37 + void (*cb)() = Callback; + Callback = NULL; + if (cb) { + cb(cause); + } +#else if (Callback) { Callback(cause); } +#endif Breaking = 0; } OSClearContext(&exceptionContext); OSSetCurrentContext(context); } +#if DOLPHIN_REVISION >= 37 +static void AlarmHandler(OSAlarm *alarm, OSContext *context) { + ProcessNextCommand(); +} + +static void AlarmHandlerForTimeout(OSAlarm *alarm, OSContext *context) { + void (*cb)(u32); + OSContext exceptionContext; + + __OSMaskInterrupts(0x400); + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + cb = Callback; + Callback = NULL; + if (cb) { + cb(0x10); + } + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); +} + +static void SetTimeoutAlarm(s64 timeout) { + OSCreateAlarm(&AlarmForTimeout); + OSSetAlarm(&AlarmForTimeout, timeout, AlarmHandlerForTimeout); +} + +static void Read(void *addr, u32 length, u32 offset, void (*callback)(u32)) { + u32 r30; + StopAtNextInt = FALSE; + Callback = callback; + LastCommandWasRead = TRUE; + LastReadIssued = __OSGetSystemTime(); + __DIRegs[2] = 0xA8000000; + __DIRegs[3] = (offset >> 2); + __DIRegs[4] = (length); + __DIRegs[5] = (u32)addr; + __DIRegs[6] = (length); + LastLength = length; + __DIRegs[7] = 3; + if (length > 0xA00000) { + r30 = OS_TIMER_CLOCK * 20; + OSCreateAlarm(&AlarmForTimeout); + OSSetAlarm(&AlarmForTimeout, r30, AlarmHandlerForTimeout); + } else { + r30 = OS_TIMER_CLOCK * 10; + OSCreateAlarm(&AlarmForTimeout); + OSSetAlarm(&AlarmForTimeout, r30, AlarmHandlerForTimeout); + } +} + +static void DoJustRead(void *addr, u32 length, u32 offset, void (*callback)(u32)) { + CommandList[0].command = -1; + NextCommandNumber = 0; + Read(addr, length, offset, callback); +} + +static void SeekTwiceBeforeRead(void *addr, u32 length, u32 offset, void (*callback)(u32)) { + u32 offsetToSeek; + + if ((offset & ~0x7FFF) == 0) { + offsetToSeek = 0; + } else { + offsetToSeek = (offset & ~0x7FFF) + WorkAroundSeekLocation; + } + + CommandList[0].command = 2; + CommandList[0].offset = offsetToSeek; + CommandList[0].callback = callback; + + CommandList[1].command = 1; + CommandList[1].address = addr; + CommandList[1].length = length; + CommandList[1].offset = offset; + CommandList[1].callback = callback; + + CommandList[2].command = -1; + + NextCommandNumber = 0; + DVDLowSeek(offsetToSeek, callback); +} + +static void WaitBeforeRead(void* addr, u32 length, u32 offset, void (* callback)(unsigned long), + OSTime timeout) { + CommandList[0].command = 1; + CommandList[0].address = addr; + CommandList[0].length = length; + CommandList[0].offset = offset; + CommandList[0].callback = callback; + CommandList[1].command = -1; + NextCommandNumber = 0; + OSCreateAlarm(&AlarmForWA); + OSSetAlarm(&AlarmForWA, timeout, AlarmHandler); +} + +static BOOL AudioBufferOn(void) { + struct DVDDiskID *id = DVDGetCurrentDiskID(); + + if (id->streaming) + return TRUE; + else + return FALSE; +} + +static BOOL HitCache(struct SomeStruct *cur, struct SomeStruct *prev) { + u32 blockNumOfPrevEnd = (prev->offset + prev->length - 1) >> 15; + u32 blockNumOfCurrStart = (cur->offset >> 15); + u32 cacheBlockSize = AudioBufferOn() ? 5 : 15; + + if (blockNumOfCurrStart > blockNumOfPrevEnd - 2 + || blockNumOfCurrStart < blockNumOfPrevEnd + cacheBlockSize + 3) { + return TRUE; + } else { + return FALSE; + } +} + +#endif + int DVDLowRead(void * addr, unsigned long length, unsigned long offset, void (* callback)(unsigned long)) { +#if DOLPHIN_REVISION >= 37 + unsigned long blockNumOfPrevEnd; // r25 + long long diff; // r22 +#endif + ASSERTMSGLINE(0x143, !OFFSET(addr, 32), "DVDLowRead(): address must be aligned with 32 byte boundary."); ASSERTMSGLINE(0x144, !(length % 32), "DVDLowRead(): length must be a multiple of 32."); ASSERTMSGLINE(0x145, !(offset % 4), "DVDLowRead(): offset must be a multiple of 4."); ASSERTMSGLINE(0x147, (length != 0), "DVD read: 0 was specified to length of the read\n"); +#if DOLPHIN_REVISION >= 37 + __DIRegs[6] = length; + Curr.addr = addr; + Curr.length = length; + Curr.offset = offset; + + if (WorkAroundType == 0) { + DoJustRead(addr, length, offset, callback); + } else if (WorkAroundType == 1) { + if (FirstRead) { + SeekTwiceBeforeRead(addr, length, offset, callback); + } else if (!HitCache(&Curr, &Prev)) { + DoJustRead(addr, length, offset, callback); + } else { + + blockNumOfPrevEnd = (Prev.offset + Prev.length - 1) >> 15; + if (blockNumOfPrevEnd == (Curr.offset >> 15) + || blockNumOfPrevEnd + 1 == (Curr.offset >> 15)) { + diff = __OSGetSystemTime() - LastReadFinished; + if (OSMillisecondsToTicks(5) < diff) { + DoJustRead(addr, length, offset, callback); + } else { + WaitBeforeRead(addr, length, offset, callback, OSMillisecondsToTicks(5) - diff + OSMicrosecondsToTicks(500)); + } + } else { + SeekTwiceBeforeRead(addr, length, offset, callback); + } + } + } + return 1; +#else Callback = callback; __DIRegs[2] = 0xA8000000; __DIRegs[3] = (offset >> 2); @@ -88,20 +341,30 @@ int DVDLowRead(void * addr, unsigned long length, unsigned long offset, void (* __DIRegs[6] = (length); __DIRegs[7] = 3; return 1; +#endif } int DVDLowSeek(unsigned long offset, void (* callback)(unsigned long)) { ASSERTMSGLINE(0x166, !(offset % 4), "DVDLowSeek(): offset must be a multiple of 4."); Callback = callback; +#if DOLPHIN_REVISION >= 37 + StopAtNextInt = FALSE; +#endif __DIRegs[2] = 0xAB000000; __DIRegs[3] = (offset >> 2); __DIRegs[7] = 1; +#if DOLPHIN_REVISION >= 37 + SetTimeoutAlarm(OSSecondsToTicks(10)); +#endif return 1; } int DVDLowWaitCoverClose(void (* callback)(unsigned long)) { Callback = callback; WaitingCoverClose = 1; +#if DOLPHIN_REVISION >= 37 + StopAtNextInt = FALSE; +#endif __DIRegs[1] = 2; return 1; } @@ -109,66 +372,111 @@ int DVDLowWaitCoverClose(void (* callback)(unsigned long)) { int DVDLowReadDiskID(struct DVDDiskID * diskID, void (* callback)(unsigned long)) { ASSERTMSGLINE(0x19B, !OFFSET(diskID, 32), "DVDLowReadID(): id must be aligned with 32 byte boundary."); Callback = callback; +#if DOLPHIN_REVISION >= 37 + StopAtNextInt = FALSE; +#endif __DIRegs[2] = 0xA8000040; __DIRegs[3] = 0; __DIRegs[4] = 0x20; __DIRegs[5] = (u32)diskID; __DIRegs[6] = 0x20; __DIRegs[7] = 3; +#if DOLPHIN_REVISION >= 37 + SetTimeoutAlarm(OSSecondsToTicks(10)); +#endif return 1; } int DVDLowStopMotor(void (* callback)(unsigned long)) { Callback = callback; +#if DOLPHIN_REVISION >= 37 + StopAtNextInt = FALSE; +#endif __DIRegs[2] = 0xE3000000; __DIRegs[7] = 1; +#if DOLPHIN_REVISION >= 37 + SetTimeoutAlarm(OSSecondsToTicks(10)); +#endif return 1; } int DVDLowRequestError(void (* callback)(unsigned long)) { Callback = callback; +#if DOLPHIN_REVISION >= 37 + StopAtNextInt = FALSE; +#endif __DIRegs[2] = 0xE0000000; __DIRegs[7] = 1; +#if DOLPHIN_REVISION >= 37 + SetTimeoutAlarm(OSSecondsToTicks(10)); +#endif return 1; } int DVDLowInquiry(struct DVDDriveInfo * info, void (* callback)(unsigned long)) { Callback = callback; +#if DOLPHIN_REVISION >= 37 + StopAtNextInt = FALSE; +#endif __DIRegs[2] = 0x12000000; __DIRegs[4] = 0x20; __DIRegs[5] = (u32)info; __DIRegs[6] = 0x20; __DIRegs[7] = 3; +#if DOLPHIN_REVISION >= 37 + SetTimeoutAlarm(OSSecondsToTicks(10)); +#endif return 1; } int DVDLowAudioStream(unsigned long subcmd, unsigned long length, unsigned long offset, void (* callback)(unsigned long)) { Callback = callback; +#if DOLPHIN_REVISION >= 37 + StopAtNextInt = FALSE; +#endif __DIRegs[2] = (subcmd | 0xE1000000); __DIRegs[3] = (offset >> 2); __DIRegs[4] = length; __DIRegs[7] = 1; +#if DOLPHIN_REVISION >= 37 + SetTimeoutAlarm(OSSecondsToTicks(10)); +#endif return 1; } int DVDLowRequestAudioStatus(unsigned long subcmd, void (* callback)(unsigned long)) { Callback = callback; +#if DOLPHIN_REVISION >= 37 + StopAtNextInt = FALSE; +#endif __DIRegs[2] = (subcmd | 0xE2000000); __DIRegs[7] = 1; +#if DOLPHIN_REVISION >= 37 + SetTimeoutAlarm(OSSecondsToTicks(10)); +#endif return 1; } int DVDLowAudioBufferConfig(int enable, unsigned long size, void (* callback)(unsigned long)) { +#if DOLPHIN_REVISION < 37 unsigned long bufSize; unsigned long trigger; +#endif Callback = callback; +#if DOLPHIN_REVISION >= 37 + StopAtNextInt = FALSE; +#else bufSize = size & 0xF; trigger = (size >> 4) & 0xF; ASSERTLINE(0x25B, bufSize < 16); ASSERTLINE(0x25C, trigger <= 2); +#endif __DIRegs[2] = ((enable ? 0x10000 : 0) | 0xE4000000 | size); __DIRegs[7] = 1; +#if DOLPHIN_REVISION >= 37 + SetTimeoutAlarm(OSSecondsToTicks(10)); +#endif return 1; } @@ -180,7 +488,7 @@ void DVDLowReset() { reg = __PIRegs[9]; __PIRegs[9] = (reg & 0xFFFFFFFB) | 1; resetStart = __OSGetSystemTime(); - while((__OSGetSystemTime() - resetStart) < OSMicrosecondsToTicks(12)) + while((__OSGetSystemTime() - resetStart) < OSMicrosecondsToTicks(12)) ; __PIRegs[9] = (reg | 4 | 1); ResetOccurred = 1; @@ -199,12 +507,16 @@ void (* DVDLowSetResetCoverCallback(void (* callback)(unsigned long)))(unsigned } int DVDLowBreak() { +#if DOLPHIN_REVISION >= 37 + StopAtNextInt = TRUE; +#else unsigned long statusReg; statusReg = __DIRegs[0]; statusReg |= 0x41; __DIRegs[0] = statusReg; +#endif Breaking = 1; return 1; } @@ -227,3 +539,13 @@ unsigned long DVDLowGetCoverStatus() { } return 2; } + +#if DOLPHIN_REVISION >= 37 +void __DVDLowSetWAType(u32 type, s32 seekLoc) +{ + BOOL enabled = OSDisableInterrupts(); + WorkAroundType = type; + WorkAroundSeekLocation = seekLoc; + OSRestoreInterrupts(enabled); +} +#endif diff --git a/src/dvd/dvdqueue.c b/src/dvd/dvdqueue.c index 8a1798e..304093e 100644 --- a/src/dvd/dvdqueue.c +++ b/src/dvd/dvdqueue.c @@ -59,6 +59,9 @@ struct DVDCommandBlock * __DVDPopWaitingQueue(void) { for(i = 0; i < 4; i++) { q = (struct DVDCommandBlock *)&WaitingQueue[i]; if (q->next != q) { +#if DOLPHIN_REVISION >= 37 + OSRestoreInterrupts(enabled); +#endif return PopWaitingQueuePrio(i); } } @@ -75,6 +78,9 @@ int __DVDCheckWaitingQueue(void) { for(i = 0; i < 4; i++) { q = (struct DVDCommandBlock *)&WaitingQueue[i]; if (q->next != q) { +#if DOLPHIN_REVISION >= 37 + OSRestoreInterrupts(enabled); +#endif return 1; } } diff --git a/src/dvd/fstload.c b/src/dvd/fstload.c index 8a80551..0ccb028 100644 --- a/src/dvd/fstload.c +++ b/src/dvd/fstload.c @@ -32,7 +32,11 @@ static void cb(long result, struct DVDCommandBlock * block) { } if (result == -1) { return; +#if DOLPHIN_REVISION >= 37 + } else if (result == -4) { +#else } else if (result == -2) { +#endif status = 0; DVDReset(); DVDReadDiskID(block, idTmp, cb); diff --git a/src/hio/hio.c b/src/hio/hio.c index f3ecf60..9e549bd 100644 --- a/src/hio/hio.c +++ b/src/hio/hio.c @@ -4,6 +4,8 @@ #include #include +#include "__os.h" + static s32 Chan = -1; static HIOCallback ExiCallback; static HIOCallback TxCallback; @@ -161,9 +163,15 @@ BOOL HIOReadMailbox(u32 *word) int err; u32 cmd; +#if DOLPHIN_REVISION >= 37 + if (Chan == -1 || __OSGetDIConfig() == 0xFFu) { + return 0; + } +#else if (Chan == -1) { return 0; } +#endif if (EXILock(Chan, 0, 0) == 0) { return 0; } @@ -187,9 +195,15 @@ BOOL HIOWriteMailbox(u32 word) int err; u32 cmd; +#if DOLPHIN_REVISION >= 37 + if (Chan == -1 || __OSGetDIConfig() == 0xFFu) { + return 0; + } +#else if (Chan == -1) { return 0; } +#endif if (EXILock(Chan, 0, 0) == 0) { return 0; } @@ -211,9 +225,15 @@ BOOL HIORead(u32 addr, void *buffer, s32 size) int err; u32 cmd; +#if DOLPHIN_REVISION >= 37 + if (Chan == -1 || __OSGetDIConfig() == 0xFFu) { + return 0; + } +#else if (Chan == -1) { return 0; } +#endif ASSERTLINE(0x145, (addr % 4) == 0); if (EXILock(Chan, 0, 0) == 0) { return 0; @@ -238,9 +258,15 @@ BOOL HIOWrite(u32 addr, void *buffer, s32 size) int err; u32 cmd; +#if DOLPHIN_REVISION >= 37 + if (Chan == -1 || __OSGetDIConfig() == 0xFFu) { + return 0; + } +#else if (Chan == -1) { return 0; } +#endif ASSERTLINE(0x167, (addr % 4) == 0); if (EXILock(Chan, 0, 0) == 0) { return 0; diff --git a/src/os/OS.c b/src/os/OS.c index c25e1fb..ca62f73 100644 --- a/src/os/OS.c +++ b/src/os/OS.c @@ -26,6 +26,7 @@ void EnableMetroTRKInterrupts(void); #define OS_DEBUG_ADDRESS_2 0x800030E9 #define DB_EXCEPTIONRET_OFFSET 0xC #define DB_EXCEPTIONDEST_OFFSET 0x8 +extern u32 UNK_REG_CC006000[] : 0xCC006000; extern unsigned long __DVDLongFileNameFlag; extern unsigned long __PADSpec; @@ -108,6 +109,23 @@ unsigned long OSGetConsoleType() { return BootInfo->consoleType; } +#if DOLPHIN_REVISION == 37 +# define BUILD_DATE "Jul 19 2001" +# define BUILD_TIMESTAMP "05:43:42" +#elif DOLPHIN_REVISION == 36 +# define BUILD_DATE "May 22 2001" +# if DEBUG +# define BUILD_TIMESTAMP "01:47:06" +# else +# define BUILD_TIMESTAMP "02:04:48" +# endif +#else +# error Build date and timestamp unknown +#endif + +#define _STRINGIFY(x) #x +#define STRINGIFY(x) _STRINGIFY(x) + void OSInit() { unsigned long consoleType; void * bi2StartAddr; @@ -148,12 +166,8 @@ void OSInit() { BootInfo->consoleType = OS_CONSOLE_RETAIL1; } BootInfo->consoleType += (__PIRegs[11] & 0xF0000000) >> 28; - OSReport("\nDolphin OS $Revision: 36 $.\n"); -#if DEBUG - OSReport("Kernel built : %s %s\n", "May 22 2001", "01:47:06"); -#else - OSReport("Kernel built : %s %s\n", "May 22 2001", "02:04:48"); -#endif + OSReport("\nDolphin OS $Revision: " STRINGIFY(DOLPHIN_REVISION) " $.\n"); + OSReport("Kernel built : %s %s\n", BUILD_DATE, BUILD_TIMESTAMP); OSReport("Console Type : "); // work out what console type this corresponds to and report it @@ -450,3 +464,9 @@ void __OSPSInit(void) } // clang-format on } + +#if DOLPHIN_REVISION >= 37 +u32 __OSGetDIConfig(void) { + return (u8)UNK_REG_CC006000[9]; +} +#endif diff --git a/src/os/OSCache.c b/src/os/OSCache.c index f52b101..d61f0f4 100644 --- a/src/os/OSCache.c +++ b/src/os/OSCache.c @@ -198,7 +198,11 @@ asm void DCZeroRange(register void* addr, register u32 nBytes) { mtctr nBytes @1 +#if DOLPHIN_REVISION >= 37 + dcbst r0, addr +#else dcbz r0, addr +#endif addi addr, addr, 32 bdnz @1 diff --git a/src/os/OSExi.c b/src/os/OSExi.c index 760585c..b28cf2e 100644 --- a/src/os/OSExi.c +++ b/src/os/OSExi.c @@ -2,6 +2,8 @@ #include #include +#include "__os.h" + typedef void (*EXICallback)(s32, OSContext*); struct EXIControl { @@ -35,6 +37,9 @@ struct EXIControl { #define EXI_WRITE 1 static struct EXIControl Ecb[3]; +#if DOLPHIN_REVISION >= 37 +static u8 bssFiller[0x10]; +#endif static void SetExiInterruptMask(long chan, struct EXIControl * exi); static void CompleteTransfer(long chan); @@ -208,7 +213,13 @@ int EXISync(long chan) { enabled = OSDisableInterrupts(); if (exi->state & 4) { CompleteTransfer(chan); +#if DOLPHIN_REVISION >= 37 + if (__OSGetDIConfig() != 0xFFu || exi->immLen != 4 + || ((u32)__EXIRegs[(chan * 5)] & 0x70) || (u32)__EXIRegs[chan * 5 + 4] != 0x01010000) + rc = 1; +#else rc = 1; +#endif } OSRestoreInterrupts(enabled); break; @@ -420,7 +431,11 @@ int EXIDeselect(long chan) { } } OSRestoreInterrupts(enabled); +#if DOLPHIN_REVISION >= 37 + if ((chan != 2) && (cpr & 0x80)) { +#else if ((chan == 0) && (cpr & 0x80)) { +#endif if (EXIProbe(chan) != 0) { return 1; } diff --git a/src/os/OSFont.c b/src/os/OSFont.c index 5e8d0da..74a96b8 100644 --- a/src/os/OSFont.c +++ b/src/os/OSFont.c @@ -493,7 +493,12 @@ char * OSGetFontTexture(char * string, void ** image, long * x, long * y, long * string++; if (OSGetFontEncode() == OS_FONT_ENCODE_SJIS) { - if ((((code >= 0x80) && (code <= 0x9F)) || ((code >= 0xE0) && (code <= 0xFF))) && ((s8)*string != 0U)) { + if ((((code >= 0x80) && (code <= 0x9F)) || ((code >= 0xE0) && (code <= 0xFF))) +#if DOLPHIN_REVISION >= 37 + && (*string != 0U)) { +#else + && ((s8)*string != 0U)) { +#endif code = (code << 8) | (*string++); // Shift-JIS encoded byte } } @@ -526,7 +531,12 @@ char * OSGetFontWidth(char * string, long * width) { string++; if (OSGetFontEncode() == OS_FONT_ENCODE_SJIS) { - if ((((code >= 0x80) && (code <= 0x9F)) || ((code >= 0xE0) && (code <= 0xFF))) && ((s8)*string != 0U)) { + if ((((code >= 0x80) && (code <= 0x9F)) || ((code >= 0xE0) && (code <= 0xFF))) +#if DOLPHIN_REVISION >= 37 + && (*string != 0U)) { +#else + && ((s8)*string != 0U)) { +#endif code = (code << 8) | (*string++); // Shift-JIS encoded byte } } diff --git a/src/os/OSReboot.c b/src/os/OSReboot.c new file mode 100644 index 0000000..3d90c25 --- /dev/null +++ b/src/os/OSReboot.c @@ -0,0 +1,118 @@ +#if DOLPHIN_REVISION >= 37 + +// We currently do not have debug info for this file, so parameters and local +// variables are guessed. + +#include +#include + +extern void __DVDPrepareResetAsync(); + +#include "__os.h" + +struct bb2struct +{ + u32 _00; + u32 _04; + s32 _08; // size? + u32 FSTMaxLength; + void* FSTLocationInRam; + u32 unk14; + u32 unk18; +}; + +static struct bb2struct Header; +static volatile BOOL Prepared; + +extern u32 UNK_817FFFF8 : 0x817FFFF8; +extern u32 UNK_817FFFFC : 0x817FFFFC; +extern u8 UNK_800030E2 : 0x800030E2; + +#pragma dont_inline on +static void Run(register void *arg0) +{ + register void *dumb = arg0; + + OSDisableInterrupts(); + ICFlashInvalidate(); + asm { + sync + isync + mtlr arg0 + blr + } +} +#pragma dont_inline reset + +static void Callback(void) { + + Prepared = TRUE; +} + +#pragma peephole off + +static void someinline(void *ptr, u32 size, u32 arg2) +{ + DVDCommandBlock sp40; + u32 unused; + + while (!Prepared) { + } + DVDReadAbsAsyncForBS(&sp40, ptr, size, arg2, NULL); + while(1) + { + switch (sp40.state) { + case -1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + __OSDoHotReset(UNK_817FFFFC); + break; + case 0: + return; + default: + case 1: + break; + } + } +} + +void __OSReboot(unsigned long resetCode, int forceMenu /* unused */) +{ + OSContext sp70; + u32 r30; + u32 r4; + + OSDisableInterrupts(); + UNK_817FFFFC = resetCode; + UNK_817FFFF8 = 0; + UNK_800030E2 = 1; + OSClearContext(&sp70); + OSSetCurrentContext(&sp70); + DVDInit(); + __DVDPrepareResetAsync(Callback); + if (!DVDCheckDisk()) { + __OSDoHotReset(UNK_817FFFFC); + } + __OSMaskInterrupts(~0x1F); + __OSUnmaskInterrupts(0x400); + OSEnableInterrupts(); + someinline(&Header, 32, 0x2440); + + + r4 = Header.unk14 + 32; + r30 = OSRoundUp32B(Header.unk18); + someinline((void *)0x81300000, r30, (u32)(r4 + 0x2440)); + + ICInvalidateRange((void *)0x81300000, r30); + Run((void *)0x81300000); +} + +#endif // DOLPHIN_REVISION >= 37 diff --git a/src/os/OSReset.c b/src/os/OSReset.c index 25c9448..3b02a40 100644 --- a/src/os/OSReset.c +++ b/src/os/OSReset.c @@ -127,6 +127,15 @@ static asm void Reset(unsigned long resetCode) { b L_000001A0 } +#if DOLPHIN_REVISION >= 37 +void __OSDoHotReset(u32 resetCode) { + OSDisableInterrupts(); + __VIRegs[1] = 0; + ICFlashInvalidate(); + Reset(resetCode << 3); +} +#endif + void OSResetSystem(int reset, unsigned long resetCode, int forceMenu) { int rc; int enabled; @@ -145,10 +154,33 @@ void OSResetSystem(int reset, unsigned long resetCode, int forceMenu) { enabled = OSDisableInterrupts(); rc = CallResetFunctions(1); ASSERTLINE(0x117, rc); +#if DOLPHIN_REVISION >= 37 + if (reset == 1) { + OSDisableInterrupts(); + __VIRegs[1] = 0; + ICFlashInvalidate(); + Reset(resetCode * 8); + } else { + OSThread *thread = UNK_800000DC; + while (thread != NULL) { + OSThread *next = thread->linkActive.next; + switch (thread->state) { + case 1: + case 4: + OSCancelThread(thread); + break; + } + thread = next; + } + OSEnableScheduler(); + __OSReboot(resetCode, forceMenu); + } +#else if (reset != 0) { ICFlashInvalidate(); Reset(resetCode * 8); } +#endif OSRestoreInterrupts(enabled); OSEnableScheduler(); } diff --git a/src/os/OSResetSW.c b/src/os/OSResetSW.c index 9bc6047..876f71a 100644 --- a/src/os/OSResetSW.c +++ b/src/os/OSResetSW.c @@ -5,11 +5,37 @@ static OSResetCallback ResetCallback; static int Down; +#if DOLPHIN_REVISION >= 37 +static int LastState; +static long long HoldUp; +static long long HoldDown; +#else static long long Hold; +#endif void __OSResetSWInterruptHandler(short exception, struct OSContext *context) { OSResetCallback callback; +#if DOLPHIN_REVISION >= 37 + HoldDown = __OSGetSystemTime(); + do { + if (__OSGetSystemTime() - HoldDown >= OSMicrosecondsToTicks(100)) + break; + } while (!(__PIRegs[0] & 0x10000)); + + if (!(__PIRegs[0] & 0x10000)) { + Down = 1; + LastState = 1; + __OSMaskInterrupts(0x200); + if (ResetCallback != NULL) { + callback = ResetCallback; + ResetCallback = NULL; + callback(); + } + } + __PIRegs[0] = 2; +#else + Down = 1; __PIRegs[0] = 2; __OSMaskInterrupts(0x200); @@ -19,6 +45,7 @@ void __OSResetSWInterruptHandler(short exception, struct OSContext *context) { ResetCallback = NULL; callback(); } +#endif } OSResetCallback OSSetResetCallback(OSResetCallback callback) { @@ -47,6 +74,29 @@ int OSGetResetSwitchState() { enabled = OSDisableInterrupts(); reg = __PIRegs[0]; +#if DOLPHIN_REVISION >= 37 + if (!(reg & 0x10000)) { + if (Down == 0) { + Down = 1; + state = (HoldUp != 0) ? 1 : 0; + HoldDown = __OSGetSystemTime(); + } + else { + state = (HoldUp != 0 || (__OSGetSystemTime() - HoldDown) > OSMicrosecondsToTicks(100)) ? 1 : 0; + } + } else if (Down != 0) { + Down = 0; + state = LastState; + if (LastState != 0) + HoldUp = __OSGetSystemTime(); + } else if (HoldUp && (__OSGetSystemTime() - HoldUp) < OSMillisecondsToTicks(40)) { + state = 1; + } else { + state = 0; + HoldUp = 0; + } + LastState = state; +#else if (!(reg & 0x10000)) { Down = 1; state = 1; @@ -65,6 +115,7 @@ int OSGetResetSwitchState() { state = 0; Hold = 0; } +#endif OSRestoreInterrupts(enabled); return state; } diff --git a/src/os/OSRtc.c b/src/os/OSRtc.c index 708868c..8053956 100644 --- a/src/os/OSRtc.c +++ b/src/os/OSRtc.c @@ -172,6 +172,11 @@ static int UnlockSram(int commit, unsigned long offset) { if (commit != 0) { if (offset == 0) { struct OSSram * sram = (struct OSSram *)&Scb.sram[0]; +#if DOLPHIN_REVISION >= 37 + if ((u32)(sram->flags & 3) > 2) { + sram->flags &= ~3; + } +#endif sram->checkSum = sram->checkSumInv = 0; for(p = (unsigned short*)&sram->counterBias; p < ((u16*)&Scb.sram[sizeof (struct OSSram)]); p++) { sram->checkSum += *p; diff --git a/src/os/OSSerial.c b/src/os/OSSerial.c index 60ae7d0..b71f6e7 100644 --- a/src/os/OSSerial.c +++ b/src/os/OSSerial.c @@ -220,14 +220,20 @@ unsigned long SIEnablePolling(unsigned long poll) { } enabled = OSDisableInterrupts(); +#if DOLPHIN_REVISION >= 37 + poll >>= 24; + Si.poll &= ~((poll >> 4) & 0xF); + poll &= 0x03FFFFF0 | ((poll >> 4) & 0xF); + poll &= 0xFC0000FF; +#else __SIRegs[0x30/4] = 0; poll = poll >> 24; en = poll & 0xF0; ASSERTLINE(0x202, en); poll &= ((en >> 4) | 0x03FFFFF0); poll &= 0xFC0000FF; - Si.poll &= ~(en >> 4); +#endif Si.poll |= poll; poll = Si.poll; __SIRegs[0x38/4] = 0x80000000; diff --git a/src/os/OSThread.c b/src/os/OSThread.c index 33f674d..cc5a443 100644 --- a/src/os/OSThread.c +++ b/src/os/OSThread.c @@ -161,11 +161,11 @@ static void OSInitMutexQueue(struct OSMutexQueue * queue) { } #endif -void OSInitThreadQueue(struct OSThreadQueue * queue) { +void OSInitThreadQueue(OSThreadQueue *queue) { queue->head = queue->tail = 0; } -struct OSThread * OSGetCurrentThread() { +OSThread *OSGetCurrentThread(void) { return __gCurrentThread; } @@ -175,14 +175,14 @@ static void __OSSwitchThread(struct OSThread * nextThread) { OSLoadContext(&nextThread->context); } -int OSIsThreadSuspended(struct OSThread * thread) { +BOOL OSIsThreadSuspended(OSThread *thread) { if (thread->suspend > 0) { return 1; } return 0; } -int OSIsThreadTerminated(struct OSThread * thread) { +BOOL OSIsThreadTerminated(OSThread *thread) { return (thread->state == 8 || thread->state == 0) ? 1 : 0; } @@ -405,8 +405,8 @@ void OSYieldThread(void) { OSRestoreInterrupts(enabled); } -int OSCreateThread(struct OSThread * thread, void * (* func)(void *), void * param, void * stack, unsigned long stackSize, long priority, unsigned short attr) { - int enabled; +BOOL OSCreateThread(OSThread *thread, void *(*func)(void *), void *param, void *stack, u32 stackSize, OSPriority priority, u16 attr) { + BOOL enabled; unsigned long sp; ASSERTMSGLINE(0x31C, ((priority >= 0) && (priority <= 0x1F)), "OSCreateThread(): priority out of range (0 <= priority <= 31)."); @@ -450,7 +450,7 @@ int OSCreateThread(struct OSThread * thread, void * (* func)(void *), void * par return 1; } -void OSExitThread(void * val) { +void OSExitThread(void *val) { int enabled = OSDisableInterrupts(); struct OSThread * currentThread = OSGetCurrentThread(); @@ -482,7 +482,7 @@ void OSExitThread(void * val) { OSRestoreInterrupts(enabled); } -void OSCancelThread(struct OSThread * thread) { +void OSCancelThread(OSThread *thread) { int enabled = OSDisableInterrupts(); ASSERTMSG1LINE(0x37E, __OSIsThreadActive(thread) != 0, @@ -522,7 +522,7 @@ void OSCancelThread(struct OSThread * thread) { OSRestoreInterrupts(enabled); } -int OSJoinThread(struct OSThread * thread, void * val) { +BOOL OSJoinThread(OSThread *thread, void *val) { int enabled = OSDisableInterrupts(); ASSERTMSG1LINE(0x3CA, __OSIsThreadActive(thread) != 0, "OSJoinThread(): thread %p is not active.", thread); @@ -547,7 +547,7 @@ int OSJoinThread(struct OSThread * thread, void * val) { return 0; } -void OSDetachThread(struct OSThread * thread) { +void OSDetachThread(OSThread *thread) { int enabled = OSDisableInterrupts(); ASSERTMSG1LINE(0x3FC, __OSIsThreadActive(thread) != 0, "OSDetachThread(): thread %p is not active.", thread); @@ -561,7 +561,7 @@ void OSDetachThread(struct OSThread * thread) { OSRestoreInterrupts(enabled); } -long OSResumeThread(struct OSThread * thread) { +s32 OSResumeThread(OSThread *thread) { int enabled = OSDisableInterrupts(); long suspendCount; @@ -592,7 +592,7 @@ long OSResumeThread(struct OSThread * thread) { return suspendCount; } -long OSSuspendThread(struct OSThread * thread) { +s32 OSSuspendThread(OSThread *thread) { int enabled = OSDisableInterrupts(); long suspendCount; @@ -625,7 +625,7 @@ long OSSuspendThread(struct OSThread * thread) { return suspendCount; } -void OSSleepThread(struct OSThreadQueue * queue) { +void OSSleepThread(OSThreadQueue *queue) { int enabled = OSDisableInterrupts(); struct OSThread * currentThread = OSGetCurrentThread(); @@ -642,7 +642,7 @@ void OSSleepThread(struct OSThreadQueue * queue) { OSRestoreInterrupts(enabled); } -void OSWakeupThread(struct OSThreadQueue * queue) { +void OSWakeupThread(OSThreadQueue *queue) { int enabled = OSDisableInterrupts(); while (queue->head) { @@ -662,7 +662,7 @@ void OSWakeupThread(struct OSThreadQueue * queue) { OSRestoreInterrupts(enabled); } -int OSSetThreadPriority(struct OSThread * thread, long priority) { +BOOL OSSetThreadPriority(OSThread *thread, OSPriority priority) { int enabled; ASSERTMSGLINE(0x4C3, (priority >= 0) && (priority <= 0x1F), "OSSetThreadPriority(): priority out of range (0 <= priority <= 31)."); @@ -684,11 +684,11 @@ int OSSetThreadPriority(struct OSThread * thread, long priority) { return 1; } -long OSGetThreadPriority(struct OSThread * thread) { +OSPriority OSGetThreadPriority(OSThread *thread) { return thread->base; } -struct OSThread * OSSetIdleFunction(void (* idleFunction)(void *), void * param, void * stack, unsigned long stackSize) { +OSThread *OSSetIdleFunction(OSIdleFunction idleFunction, void *param, void *stack, u32 stackSize) { if(idleFunction) { if (IdleThread.state == 0) { OSCreateThread(&IdleThread, (void*)idleFunction, param, stack, stackSize, 0x1F, 1); @@ -701,7 +701,7 @@ struct OSThread * OSSetIdleFunction(void (* idleFunction)(void *), void * param, return NULL; } -struct OSThread * OSGetIdleFunction() { +OSThread *OSGetIdleFunction(void) { if (IdleThread.state != 0) { return &IdleThread; } @@ -749,7 +749,7 @@ static int IsMember(struct OSThreadQueue * queue, struct OSThread * thread) { OSPanic(__FILE__, line, ""); \ } -long OSCheckActiveThreads() { +long OSCheckActiveThreads(void) { struct OSThread * thread; long prio; long cThread; diff --git a/src/os/OSUartExi.c b/src/os/OSUartExi.c index 88da718..7d9b3bf 100644 --- a/src/os/OSUartExi.c +++ b/src/os/OSUartExi.c @@ -57,7 +57,11 @@ int WriteUARTN(void *buf, u32 len) { } while ((u32)ptr - (u32)buf < len) { +#if DOLPHIN_REVISION >= 37 + if (*(u8*)ptr == 0xA) { +#else if (*(s8*)ptr == 0xA) { +#endif *ptr = 0xD; } ptr++; diff --git a/src/os/__os.h b/src/os/__os.h index 68ad4ee..e35f7c2 100644 --- a/src/os/__os.h +++ b/src/os/__os.h @@ -3,11 +3,16 @@ #include +OSThread *UNK_800000DC : 0x800000DC; + // OS.c extern char * __OSExceptionNames[15]; // D ONLY unsigned long __OSIsDebuggerPresent(void); void __OSPSInit(void); +#if DOLPHIN_REVISION >= 37 +u32 __OSGetDIConfig(void); +#endif // OSAlloc.c extern volatile int __OSCurrHeap; @@ -46,6 +51,16 @@ void __OSUnlockAllMutex(struct OSThread *thread); int __OSCheckDeadLock(struct OSThread *thread); int __OSCheckMutexes(struct OSThread *thread); +#if DOLPHIN_REVISION >= 37 +// OSReboot.c +void __OSReboot(unsigned long resetCode, int forceMenu); +#endif + +// OSReset.c +#if DOLPHIN_REVISION >= 37 +void __OSDoHotReset(u32 resetCode); +#endif + // OSResetSW.c void __OSResetSWInterruptHandler(short exception, struct OSContext *context); diff --git a/src/pad/Pad.c b/src/pad/Pad.c index 36a8d1c..141c5cd 100644 --- a/src/pad/Pad.c +++ b/src/pad/Pad.c @@ -10,23 +10,6 @@ (PAD_BUTTON_LEFT | PAD_BUTTON_RIGHT | PAD_BUTTON_DOWN | PAD_BUTTON_UP | PAD_TRIGGER_Z | PAD_TRIGGER_R \ | PAD_TRIGGER_L | PAD_BUTTON_A | PAD_BUTTON_B | PAD_BUTTON_X | PAD_BUTTON_Y | PAD_BUTTON_MENU | 0x2000 | 0x0080) -u16 __OSWirelessPadFixMode : 0x800030E0; - -static long ResettingChan = 0x00000020; // size: 0x4, address: 0x0 -static unsigned long AnalogMode = 0x00000300; // size: 0x4, address: 0x4 -static unsigned long Spec = 0x00000005; // size: 0x4, address: 0x8 - -static int Initialized; // size: 0x4, address: 0x0 -static unsigned long EnabledBits; // size: 0x4, address: 0x4 -static unsigned long ResettingBits; // size: 0x4, address: 0x8 -static unsigned long ProbingBits; // size: 0x4, address: 0xC -static unsigned long RecalibrateBits; // size: 0x4, address: 0x10 -static unsigned long WaitingBits; // size: 0x4, address: 0x14 -static unsigned long CheckingBits; // size: 0x4, address: 0x18 - -static unsigned long Type[4]; // size: 0x10, address: 0x0 -static struct PADStatus Origin[4]; // size: 0x30, address: 0x10 - // functions static u16 GetWirelessID(long chan); static void SetWirelessID(long chan, u16 id); @@ -43,7 +26,6 @@ int PADReset(unsigned long mask); BOOL PADRecalibrate(u32 mask); BOOL PADInit(); static void PADReceiveCheckCallback(s32 chan, unsigned long error, OSContext *arg2); -void PADRead(struct PADStatus * status); void PADSetSamplingRate(unsigned long msec); void __PADTestSamplingRate(unsigned long tvmode); void PADControlAllMotors(const u32 *commandArray); @@ -60,7 +42,36 @@ BOOL PADSync(void); void PADSetAnalogMode(u32 mode); static BOOL OnReset(BOOL f); +u16 __OSWirelessPadFixMode : 0x800030E0; + +static long ResettingChan = 0x00000020; // size: 0x4, address: 0x0 +#if DOLPHIN_REVISION >= 37 +static u32 XPatchBits = 0xF0000000; +#endif +static unsigned long AnalogMode = 0x00000300; // size: 0x4, address: 0x4 +static unsigned long Spec = 0x00000005; // size: 0x4, address: 0x8 + +static int Initialized; // size: 0x4, address: 0x0 +static unsigned long EnabledBits; // size: 0x4, address: 0x4 +static unsigned long ResettingBits; // size: 0x4, address: 0x8 +static unsigned long ProbingBits; // size: 0x4, address: 0xC +static unsigned long RecalibrateBits; // size: 0x4, address: 0x10 +static unsigned long WaitingBits; // size: 0x4, address: 0x14 +static unsigned long CheckingBits; // size: 0x4, address: 0x18 +#if DOLPHIN_REVISION >= 37 +static int cmdTypeAndStatus; +static u32 PADType[4]; +#endif +static unsigned long Type[4]; // size: 0x10, address: 0x0 +static struct PADStatus Origin[4]; // size: 0x30, address: 0x10 +#if DOLPHIN_REVISION >= 37 +u32 CmdProbeDevice[4]; +#endif static void (* MakeStatus)(long, struct PADStatus *, unsigned long *) = SPEC2_MakeStatus; // size: 0x4, address: 0xC +#if DOLPHIN_REVISION >= 37 +static u32 cmdReadOrigin = 0x41000000; +static u32 cmdCalibrate = 0x42000000; +#endif static OSResetFunctionInfo ResetFunctionInfo = { OnReset, @@ -90,6 +101,38 @@ static void SetWirelessID(long chan, u16 id) { __OSUnlockSramEx(0); } +#if DOLPHIN_REVISION >= 37 // got moved +static void PADEnable(long chan) { + unsigned long cmd; + unsigned long chanBit; + unsigned long data[2]; + u8 unused[4]; + + chanBit = 0x80000000 >> chan; + EnabledBits |= chanBit; + SIGetResponse(chan, &data); + ASSERTLINE(0x1C4, !(Type[chan] & RES_WIRELESS_LITE)); + cmd = (AnalogMode | 0x400000); + SISetCommand(chan, cmd); + SIEnablePolling(EnabledBits); +} + +static void PADDisable(long chan) { + int enabled; + unsigned long chanBit; + + enabled = OSDisableInterrupts(); + chanBit = 0x80000000 >> chan; + SIDisablePolling(chanBit); + EnabledBits &= ~chanBit; + WaitingBits &= ~chanBit; + CheckingBits &= ~chanBit; + ProbingBits &= ~chanBit; + SetWirelessID(chan, 0); + OSRestoreInterrupts(enabled); +} +#endif + static int DoReset() { int rc; unsigned long frame; @@ -98,10 +141,17 @@ static int DoReset() { rc = 1; ResettingChan = __cntlzw(ResettingBits); if ((ResettingChan >= 0) && (ResettingChan < 4)) { +#if DOLPHIN_REVISION >= 37 + memset(&Origin[ResettingChan], 0, 0xC); + Type[ResettingChan] = 0; + PADType[ResettingChan] = 0; + rc = SITransfer(ResettingChan, &cmdTypeAndStatus, 1, &Type[ResettingChan], 3, PADResetCallback, 0); +#else frame = 0; memset(&Origin[ResettingChan], 0, 0xC); Type[ResettingChan] = 0; rc = SITransfer(ResettingChan, &frame, 1, &Type[ResettingChan], 3, PADResetCallback, 0); +#endif chanBit = (0x80000000 >> ResettingChan); ResettingBits &= ~chanBit; if (rc == 0) { @@ -112,6 +162,7 @@ static int DoReset() { return rc; } +#if DOLPHIN_REVISION < 37 // got moved static void PADEnable(long chan) { unsigned long cmd; unsigned long chanBit; @@ -125,12 +176,16 @@ static void PADEnable(long chan) { SISetCommand(chan, cmd); SIEnablePolling(EnabledBits); } +#endif static void ProbeWireless(long chan) { unsigned long cmd; unsigned long chanBit; unsigned long data[2]; unsigned long type; +#if DOLPHIN_REVISION >= 37 + u8 unused[4]; +#endif chanBit = 0x80000000 >> chan; EnabledBits |= chanBit; @@ -166,6 +221,7 @@ static void PADProbeCallback(s32 chan, u32 error, OSContext *context) { DoReset(); } +#if DOLPHIN_REVISION < 37 // got moved static void PADDisable(long chan) { int enabled; unsigned long chanBit; @@ -180,11 +236,14 @@ static void PADDisable(long chan) { SetWirelessID(chan, 0); OSRestoreInterrupts(enabled); } +#endif static void UpdateOrigin(s32 chan) { - PADStatus *origin; +#if DOLPHIN_REVISION >= 37 + u32 chanBit = PAD_CHAN0_BIT >> chan; +#endif + PADStatus *origin = &Origin[chan]; - origin = &Origin[chan]; switch (AnalogMode & 0x00000700u) { case 0x00000000u: @@ -216,6 +275,13 @@ static void UpdateOrigin(s32 chan) { origin->stickY -= 128; origin->substickX -= 128; origin->substickY -= 128; +#if DOLPHIN_REVISION >= 37 + if (XPatchBits & chanBit) + { + if (64 < origin->stickX && (Type[chan] & 0xffff0000) == SI_GC_CONTROLLER) + origin->stickX = 0; + } +#endif } static void PADOriginCallback(s32 chan, u32 error, OSContext *context) { @@ -253,18 +319,29 @@ static void PADFixCallback(long unused, unsigned long error, struct OSContext *c return; } if ((type & 0x40000000) && !(type & 0x80000) && !(type & 0x40000)) { +#if DOLPHIN_REVISION >= 37 + SITransfer(ResettingChan, &cmdReadOrigin, 1, &Origin[ResettingChan], 10, PADOriginCallback, 0); +#else frame = 0x41000000; SITransfer(ResettingChan, &frame, 1, &Origin[ResettingChan], 0xA, PADOriginCallback, 0); +#endif return; } +#if DOLPHIN_REVISION >= 37 + SITransfer(ResettingChan, &CmdProbeDevice[ResettingChan], 3, &Origin[ResettingChan], 8, PADProbeCallback, 0); +#else frame = (ResettingChan << 0x16) | 0x4D000000 | (__OSWirelessPadFixMode << 8) & 0x3FFF00u; SITransfer(ResettingChan, &frame, 3, &Origin[ResettingChan], 8, PADProbeCallback, 0); +#endif return; } DoReset(); } unsigned long __PADFixBits; // size: 0x4, address: 0x24 +#if DOLPHIN_REVISION >= 37 +u32 bss_60[4]; +#endif static void PADResetCallback(long unused, unsigned long error, struct OSContext *context) { unsigned long type; @@ -272,12 +349,25 @@ static void PADResetCallback(long unused, unsigned long error, struct OSContext unsigned long recalibrate; unsigned long chanBit; int fix; +#if DOLPHIN_REVISION < 37 unsigned long frame; +#endif ASSERTLINE(0x2E9, 0 <= ResettingChan && ResettingChan < SI_MAX_CHAN); +#if DOLPHIN_REVISION >= 37 + if ((error & 0xF) != 0) { + Type[ResettingChan] = 0; + } +#endif + +#if DOLPHIN_REVISION >= 37 + chanBit = 0x80000000 >> ResettingChan; + PADType[ResettingChan] = (type = Type[ResettingChan]); +#else type = Type[ResettingChan]; chanBit = 0x80000000 >> ResettingChan; +#endif recalibrate = RecalibrateBits & chanBit; RecalibrateBits &= ~chanBit; fix = __PADFixBits & chanBit; @@ -298,6 +388,14 @@ static void PADResetCallback(long unused, unsigned long error, struct OSContext DoReset(); return; } +#if DOLPHIN_REVISION >= 37 + if (recalibrate != 0) { + SITransfer(ResettingChan, &cmdCalibrate, 3, &Origin[ResettingChan], 0xA, PADOriginCallback, 0); + return; + } + SITransfer(ResettingChan, &cmdReadOrigin, 1, &Origin[ResettingChan], 0xA, PADOriginCallback, 0); + return; +#else if (recalibrate != 0) { frame = 0x42000000; SITransfer(ResettingChan, &frame, 3, &Origin[ResettingChan], 0xA, PADOriginCallback, 0); @@ -306,11 +404,17 @@ static void PADResetCallback(long unused, unsigned long error, struct OSContext frame = 0x41000000; SITransfer(ResettingChan, &frame, 1, &Origin[ResettingChan], 0xA, PADOriginCallback, 0); return; +#endif } id = (GetWirelessID(ResettingChan) << 8); if ((fix != 0) && (id & 0x100000)) { +#if DOLPHIN_REVISION >= 37 + bss_60[ResettingChan] = (id & 0xCFFF00) | 0x4E100000; + SITransfer(ResettingChan, &bss_60[ResettingChan], 3, &Type[ResettingChan], 3, PADFixCallback, 0); +#else frame = (id & 0xCFFF00) | 0x4E000000 | 0x100000; SITransfer(ResettingChan, &frame, 3, &Type[ResettingChan], 3, PADFixCallback, 0); +#endif return; } if (type & 0x100000) { @@ -320,27 +424,46 @@ static void PADResetCallback(long unused, unsigned long error, struct OSContext id |= 0x100000; SetWirelessID(ResettingChan, (u16)(id >> 8) & 0xFFFFFF); } +#if DOLPHIN_REVISION >= 37 + bss_60[ResettingChan] = id | 0x4E000000; + SITransfer(ResettingChan, &bss_60[ResettingChan], 3, &Type[ResettingChan], 3, PADFixCallback, 0); +#else frame = id | 0x4E000000; SITransfer(ResettingChan, &frame, 3, &Type[ResettingChan], 3, PADFixCallback, 0); +#endif return; } if ((type & 0x40000000) && !(type & 0x80000) && !(type & 0x40000)) { +#if DOLPHIN_REVISION >= 37 + SITransfer(ResettingChan, &cmdReadOrigin, 1, &Origin[ResettingChan], 10, PADOriginCallback, 0); +#else frame = 0x41000000; SITransfer(ResettingChan, &frame, 1, &Origin[ResettingChan], 0xA, PADOriginCallback, 0); +#endif return; } +#if DOLPHIN_REVISION >= 37 + SITransfer(ResettingChan, &CmdProbeDevice[ResettingChan], 3, &Origin[ResettingChan], 8, PADProbeCallback, 0); +#else frame = (ResettingChan << 0x16) | 0x4D000000 | ((__OSWirelessPadFixMode << 8) & 0x3FFF00u); SITransfer(ResettingChan, &frame, 3, &Origin[ResettingChan], 8, PADProbeCallback, 0); +#endif return; } if (type & 0x40000000) { unsigned long id = (type & 0xCFFF00); id |= 0x100000; SetWirelessID(ResettingChan, (u16)(id >> 8) & 0xFFFFFF); +#if DOLPHIN_REVISION >= 37 + bss_60[ResettingChan] = id | 0x4E000000; + SITransfer(ResettingChan, &bss_60[ResettingChan], 3, &Type[ResettingChan], 3, PADFixCallback, 0); +#else frame = id | 0x4E000000; SITransfer(ResettingChan, &frame, 3, &Type[ResettingChan], 3, PADFixCallback, 0); +#endif return; } + SetWirelessID(ResettingChan, 0); ProbeWireless(ResettingChan); DoReset(); @@ -389,6 +512,9 @@ BOOL PADRecalibrate(u32 mask) { unsigned long __PADSpec; // size: 0x4, address: 0x20 BOOL PADInit() { +#if DOLPHIN_REVISION >= 37 + s32 chan; +#endif if (!Initialized) { if (__PADSpec) @@ -401,7 +527,10 @@ BOOL PADInit() { = (u16)((((time)&0xffff) + ((time >> 16) & 0xffff) + ((time >> 32) & 0xffff) + ((time >> 48) & 0xffff)) & 0x3fffu); } - +#if DOLPHIN_REVISION >= 37 + for (chan = 0; chan < SI_MAX_CHAN; ++chan) + CmdProbeDevice[chan] = (0x4D << 24) | (chan << 22) | ((__OSWirelessPadFixMode & 0x3fffu) << 8); +#endif Initialized = TRUE; PADSetSamplingRate(0); @@ -421,21 +550,34 @@ static void PADReceiveCheckCallback(s32 chan, unsigned long error, OSContext *ar CheckingBits &= ~chanBit; if (EnabledBits & chanBit) { if (!(error & 0xF) && (type & 0x80000000) && (type & 0x02000000) && (type & 0x40000000) && !(type & 0x04000000)) { +#if DOLPHIN_REVISION >= 37 + SITransfer(chan, &cmdReadOrigin, 1, &Origin[chan], 0xA, PADOriginUpdateCallback, 0); +#else frame = 0x41000000; SITransfer(chan, &frame, 1, &Origin[chan], 0xA, PADOriginUpdateCallback, 0); +#endif return; } PADDisable(chan); } } -void PADRead(struct PADStatus * status) { +#if DOLPHIN_REVISION >= 37 +u32 +#else +void +#endif +PADRead(struct PADStatus * status) { long chan; unsigned long data[2]; unsigned long chanBit; unsigned long sr; int chanShift; +#if DOLPHIN_REVISION >= 37 + u32 motor = 0; +#else unsigned long frame; +#endif int enabled; for(chan = 0; chan < 4; chan++, status++) { @@ -455,10 +597,16 @@ void PADRead(struct PADStatus * status) { memset(status, 0, 0xA); if (!(CheckingBits & chanBit)) { enabled = OSDisableInterrupts(); +#if DOLPHIN_REVISION >= 37 + if (SITransfer(chan, &cmdTypeAndStatus, 1, &Type[chan], 3, PADReceiveCheckCallback, 0) != 0) { + CheckingBits |= chanBit; + } +#else frame = 0; if (SITransfer(chan, &frame, 1, &Type[chan], 3, PADReceiveCheckCallback, 0) != 0) { CheckingBits |= chanBit; } +#endif OSRestoreInterrupts(enabled); } } else { @@ -466,30 +614,50 @@ void PADRead(struct PADStatus * status) { status->err = -1; memset(status, 0, 0xA); } - } else if (!(sr & (0x20 << chanShift))) { - status->err = -3; - memset(status, 0, 0xA); } else { - SIGetResponse(chan, &data); - if (data[0] & 0x80000000) { - status->err = -3; - memset(status, 0, 0xA); - } else if (ProbingBits & chanBit) { - status->err = -1; - memset(status, 0, 0xA); - } else if (status->button & 0x2000) { +#if DOLPHIN_REVISION >= 37 + if (!(ProbingBits & chanBit) && !(Type[chan] & 0x20000000)) + motor |= chanBit; +#endif + if (!(sr & (0x20 << chanShift))) { status->err = -3; memset(status, 0, 0xA); - frame = 0x41000000; - SITransfer(chan, &frame, 1, &Origin[chan], 0xA, PADOriginUpdateCallback, 0); } else { - status->err = 0; - MakeStatus(chan, status, data); - status->button &= 0xFFFFFF7F; + SIGetResponse(chan, &data); + if (data[0] & 0x80000000) { + status->err = -3; + memset(status, 0, 0xA); + } else if (ProbingBits & chanBit) { + status->err = -1; + memset(status, 0, 0xA); + } else { +#if DOLPHIN_REVISION >= 37 + MakeStatus(chan, status, data); +#endif + if (status->button & 0x2000) { + status->err = -3; + memset(status, 0, 0xA); +#if DOLPHIN_REVISION >= 37 + SITransfer(chan, &cmdReadOrigin, 1, &Origin[chan], 0xA, PADOriginUpdateCallback, 0); +#else + frame = 0x41000000; + SITransfer(chan, &frame, 1, &Origin[chan], 0xA, PADOriginUpdateCallback, 0); +#endif + } else { + status->err = 0; +#if DOLPHIN_REVISION < 37 + MakeStatus(chan, status, data); +#endif + status->button &= 0xFFFFFF7F; + } + } } } } } +#if DOLPHIN_REVISION >= 37 + return motor; +#endif } typedef struct XY { @@ -545,7 +713,13 @@ void PADSetSamplingRate(unsigned long msec) { xy = XYPAL; break; default: - OSPanic("Pad.c", 0x4DF, "PADSetSamplingRate: unknown TV format"); + OSPanic("Pad.c", +#if DOLPHIN_REVISION >= 37 + 0x510, +#else + 0x4DF, +#endif + "PADSetSamplingRate: unknown TV format"); } SISetXY(xy[msec].line, xy[msec].count); SIEnablePolling(EnabledBits); @@ -565,9 +739,9 @@ void __PADTestSamplingRate(unsigned long tvmode) { for(msec = 0; msec <= 0xB; msec++) { line = xy[msec].line; count = xy[msec].count; - OSReport("%2d[msec]: count %3d, line %3d, last %3d, diff0 %2d.%03d, diff1 %2d.%03d\n", msec, count, line, (line * (count - 1)) + LATENCY, + OSReport("%2d[msec]: count %3d, line %3d, last %3d, diff0 %2d.%03d, diff1 %2d.%03d\n", msec, count, line, (line * (count - 1)) + LATENCY, (line * 636) / 10000, - (line * 636) % 10000, + (line * 636) % 10000, 636 * (263 - line * (count - 1)) / 10000, 636 * (263 - line * (count - 1)) % 10000); ASSERTLINE(0x505, line * (count - 1) + LATENCY < 263); @@ -582,9 +756,9 @@ void __PADTestSamplingRate(unsigned long tvmode) { for(msec = 0; msec <= 0xB; msec++) { line = xy[msec].line; count = xy[msec].count; - OSReport("%2d[msec]: count %3d, line %3d, last %3d, diff0 %2d.%03d, diff1 %2d.%03d\n", msec, count, line, (line * (count - 1)) + LATENCY, + OSReport("%2d[msec]: count %3d, line %3d, last %3d, diff0 %2d.%03d, diff1 %2d.%03d\n", msec, count, line, (line * (count - 1)) + LATENCY, (line * 640) / 10000, - (line * 640) % 10000, + (line * 640) % 10000, 640 * (313 - line * (count - 1)) / 10000, 640 * (313 - line * (count - 1)) % 10000); ASSERTLINE(0x51D, line * (count - 1) + LATENCY < 313); diff --git a/src/vi/vi.c b/src/vi/vi.c index ee1e4d7..8a5d9a1 100644 --- a/src/vi/vi.c +++ b/src/vi/vi.c @@ -92,7 +92,11 @@ static VITiming timing[7] = { 5, 287, 35, 35, 2, 2, 13, 11, 13, 11, 619, 621, 619, 621, 626, 432, 64, 75, 106, 172, 380, 133, 420 }, { 6, 240, 24, 25, 3, 2, 16, 15, 14, 13, 518, 517, 516, 519, 525, 429, 64, 78, 112, 162, 373, 122, 412 }, { 6, 240, 24, 24, 4, 4, 16, 14, 16, 14, 518, 520, 518, 520, 526, 429, 64, 78, 112, 162, 373, 122, 412 }, +#if DOLPHIN_REVISION >= 37 + { 12, 480, 48, 48, 6, 6, 24, 24, 24, 24, 1038, 1038, 1038, 1038, 1050, 429, 64, 71, 105, 162, 373, 122, 412 }, +#else { 12, 480, 44, 44, 10, 10, 24, 24, 24, 24, 1038, 1038, 1038, 1038, 1050, 429, 64, 71, 105, 162, 373, 122, 412 }, +#endif }; static u16 taps[25] = { 0x01F0, 0x01DC, @@ -626,9 +630,17 @@ static void setVerticalRegs(u16 dispPosY, u16 dispSizeY, u8 equ, u16 acv, u16 pr } actualAcv = dispSizeY / c; if (black) { +#if DOLPHIN_REVISION >= 37 + actualPrbOdd += (actualAcv * 2) - 2; +#else actualPrbOdd += dispSizeY - 2; +#endif actualPsbOdd += 2; +#if DOLPHIN_REVISION >= 37 + actualPrbEven += (actualAcv * 2) - 2; +#else actualPrbEven += dispSizeY - 2; +#endif actualPsbEven += 2; actualAcv = 0; } @@ -671,6 +683,9 @@ void VIConfigure(GXRenderModeObj *rm) enabled = OSDisableInterrupts(); if (rm->viTVmode == VI_TVMODE_NTSC_PROG) { HorVer.nonInter = 2; +#if DOLPHIN_REVISION >= 37 + changeMode = 1; +#endif } else { newNonInter = rm->viTVmode & 1; if (HorVer.nonInter != newNonInter) { @@ -714,10 +729,23 @@ void VIConfigure(GXRenderModeObj *rm) } setInterruptRegs(tm); reg = regs[1]; +#if DOLPHIN_REVISION >= 37 + if (HorVer.nonInter == 2) { + SET_REG_FIELD(0x66A, reg, 1, 2, 1); + } else { + SET_REG_FIELD(0x66A, reg, 1, 2, (HorVer.nonInter & 1)); + } +#else SET_REG_FIELD(0x66A, reg, 1, 2, (HorVer.nonInter & 1)); +#endif SET_REG_FIELD(0x66B, reg, 2, 8, HorVer.tv); regs[1] = reg; MARK_CHANGED(1); +#if DOLPHIN_REVISION >= 37 + reg = regs[54]; + regs[54] = (rm->viTVmode != 2) ? (reg & ~1) : ((reg & ~1) | 1); + MARK_CHANGED(54); +#endif setScalingRegs(HorVer.PanSizeX, HorVer.DispSizeX, HorVer.threeD); setHorizontalRegs(tm, HorVer.AdjustedDispPosX, HorVer.DispSizeX); setBBIntervalRegs(tm);