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/demo/DEMOInit.h b/include/dolphin/demo/DEMOInit.h index adfb372..8979e11 100644 --- a/include/dolphin/demo/DEMOInit.h +++ b/include/dolphin/demo/DEMOInit.h @@ -15,7 +15,11 @@ void DEMOSetTevColorIn(enum _GXTevStageID stage, enum _GXTevColorArg a, enum _GX void DEMOSetTevOp(enum _GXTevStageID id, enum _GXTevMode mode); struct _GXRenderModeObj * DEMOGetRenderModeObj(); u32 DEMOGetCurrentBuffer(void); +#if DOLPHIN_REVISION >= 45 +void DEMOEnableGPHangWorkaround(unsigned long timeoutFrames); +#else void DEMOEnableBypassWorkaround(unsigned long timeoutFrames); +#endif void DEMOReInit(struct _GXRenderModeObj * mode); #endif // _DOLPHIN_DEMOINIT_H_ 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/mtx.h b/include/dolphin/mtx.h index 8267093..c0d54c8 100644 --- a/include/dolphin/mtx.h +++ b/include/dolphin/mtx.h @@ -33,47 +33,61 @@ typedef f32 (*ROMtxPtr)[3]; void MTXScale(Mtx m, f32 xS, f32 yS, f32 zS); void MTXOrtho(Mtx44 m, f32 t, f32 b, f32 l, f32 r, f32 n, f32 f); +#if DOLPHIN_REVISION >= 45 +void C_MTXScale(Mtx m, f32 xS, f32 yS, f32 zS); +void C_MTXOrtho(Mtx44 m, f32 t, f32 b, f32 l, f32 r, f32 n, f32 f); +void PSMTXScale(Mtx m, f32 xS, f32 yS, f32 zS); +void PSMTXOrtho(Mtx44 m, f32 t, f32 b, f32 l, f32 r, f32 n, f32 f); +#endif void C_MTXFrustum(Mtx44 m, f32 t, f32 b, f32 l, f32 r, f32 n, f32 f); void C_MTXPerspective(Mtx44 m, f32 fovY, f32 aspect, f32 n, f32 f); void C_MTXLookAt(Mtx m, Point3dPtr camPos, VecPtr camUp, Point3dPtr target); #ifdef DEBUG -#define VECSquareMag C_VECSquareMag -#define VECNormalize C_VECNormalize -#define VECAdd C_VECAdd -#define VECDotProduct C_VECDotProduct +#define VECSquareMag C_VECSquareMag +#define VECNormalize C_VECNormalize +#define VECAdd C_VECAdd +#define VECDotProduct C_VECDotProduct #define VECSquareDistance C_VECSquareDistance -#define VECCrossProduct C_VECCrossProduct -#define MTXMultVec C_MTXMultVec -#define MTXMultVecArray C_MTXMultVecArray -#define MTXCopy C_MTXCopy -#define MTXConcat C_MTXConcat -#define MTXInverse C_MTXInverse -#define MTXTranspose C_MTXTranspose -#define MTXIdentity C_MTXIdentity +#define VECCrossProduct C_VECCrossProduct +#define MTXMultVec C_MTXMultVec +#define MTXMultVecArray C_MTXMultVecArray +#define MTXCopy C_MTXCopy +#define MTXConcat C_MTXConcat +#define MTXInverse C_MTXInverse +#define MTXTranspose C_MTXTranspose +#define MTXIdentity C_MTXIdentity +#if DOLPHIN_REVISION >= 45 +#define MTXOrtho C_MTXOrtho +#define MTXScale C_MTXScale +#endif #else -#define VECSquareMag PSVECSquareMag -#define VECNormalize PSVECNormalize -#define VECAdd PSVECAdd -#define VECDotProduct PSVECDotProduct +#define VECSquareMag PSVECSquareMag +#define VECNormalize PSVECNormalize +#define VECAdd PSVECAdd +#define VECDotProduct PSVECDotProduct #define VECSquareDistance PSVECSquareDistance -#define VECCrossProduct PSVECCrossProduct -#define MTXMultVec PSMTXMultVec -#define MTXMultVecArray PSMTXMultVecArray -#define MTXCopy PSMTXCopy -#define MTXConcat PSMTXConcat -#define MTXInverse PSMTXInverse -#define MTXTranspose PSMTXTranspose -#define MTXIdentity PSMTXIdentity +#define VECCrossProduct PSVECCrossProduct +#define MTXMultVec PSMTXMultVec +#define MTXMultVecArray PSMTXMultVecArray +#define MTXCopy PSMTXCopy +#define MTXConcat PSMTXConcat +#define MTXInverse PSMTXInverse +#define MTXTranspose PSMTXTranspose +#define MTXIdentity PSMTXIdentity +#if DOLPHIN_REVISION >= 45 +#define MTXOrtho PSMTXOrtho +#define MTXScale PSMTXScale +#endif #endif // asm only -#define MTXReorder PSMTXReorder -#define MTXROMultVecArray PSMTXROMultVecArray -#define MTXROSkin2VecArray PSMTXROSkin2VecArray +#define MTXReorder PSMTXReorder +#define MTXROMultVecArray PSMTXROMultVecArray +#define MTXROSkin2VecArray PSMTXROSkin2VecArray #define MTXROMultS16VecArray PSMTXROMultS16VecArray -#define MTXMultS16VecArray PSMTXMultS16VecArray +#define MTXMultS16VecArray PSMTXMultS16VecArray // mtx.c // functions diff --git a/include/dolphin/os.h b/include/dolphin/os.h index 424bfaa..aae88ad 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) @@ -173,6 +174,11 @@ void *OSUncachedToCached(void *ucaddr); #define OSUncachedToCached(ucaddr) ((void*) ((u8*)(ucaddr) - (OS_BASE_UNCACHED - OS_BASE_CACHED))) #endif +#if DOLPHIN_REVISION >= 45 +#define OS_PROGRESSIVE_MODE_OFF 0 +#define OS_PROGRESSIVE_MODE_ON 1 +#endif + #ifdef __cplusplus } #endif diff --git a/include/dolphin/os/OSError.h b/include/dolphin/os/OSError.h index 157e1ec..6a2e3f4 100644 --- a/include/dolphin/os/OSError.h +++ b/include/dolphin/os/OSError.h @@ -25,7 +25,12 @@ typedef void (*OSErrorHandler)(OSError error, OSContext *context, ...); #define OS_ERROR_BREAKPOINT 12 #define OS_ERROR_SYSTEM_INTERRUPT 13 #define OS_ERROR_THERMAL_INTERRUPT 14 +#if DOLPHIN_REVISION >= 45 +#define OS_ERROR_PROTECTION 15 +#define OS_ERROR_MAX (OS_ERROR_PROTECTION + 1) +#else #define OS_ERROR_MAX (OS_ERROR_THERMAL_INTERRUPT + 1) +#endif OSErrorHandler OSSetErrorHandler(OSError error, OSErrorHandler handler); diff --git a/include/dolphin/os/OSModule.h b/include/dolphin/os/OSModule.h index 1fedf29..3e74805 100644 --- a/include/dolphin/os/OSModule.h +++ b/include/dolphin/os/OSModule.h @@ -7,7 +7,11 @@ extern "C" { #endif +#if DOLPHIN_REVISION >= 45 +#define OS_MODULE_VERSION 2 +#else #define OS_MODULE_VERSION 1 +#endif typedef struct OSModuleHeader OSModuleHeader; typedef u32 OSModuleID; diff --git a/include/dolphin/os/OSRtc.h b/include/dolphin/os/OSRtc.h index 12c9ab5..2bc4efa 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; @@ -50,6 +55,11 @@ void OSSetVideoMode(unsigned long mode); unsigned char OSGetLanguage(); void OSSetLanguage(unsigned char language); +#if DOLPHIN_REVISION >= 45 +u16 OSGetWirelessID(s32 chan); +void OSSetWirelessID(s32 chan, u16 id); +#endif + #ifdef __cplusplus } #endif diff --git a/include/dolphin/os/OSSerial.h b/include/dolphin/os/OSSerial.h index 8db28c6..5786338 100644 --- a/include/dolphin/os/OSSerial.h +++ b/include/dolphin/os/OSSerial.h @@ -53,7 +53,11 @@ struct SIPacket { void * input; unsigned long inputBytes; void (* callback)(long, unsigned long, struct OSContext *); +#if DOLPHIN_REVISION >= 45 + long long fire; +#else long long time; +#endif }; int SIBusy(); @@ -66,8 +70,16 @@ void SITransferCommands(); unsigned long SISetXY(unsigned long x, unsigned long y); unsigned long SIEnablePolling(unsigned long poll); unsigned long SIDisablePolling(unsigned long poll); -void SIGetResponse(long chan, void * data); +#if DOLPHIN_REVISION >= 45 +int +#else +void +#endif +SIGetResponse(long chan, void * data); int SITransfer(long chan, void * output, unsigned long outputBytes, void * input, unsigned long inputBytes, void (* callback)(long, unsigned long, struct OSContext *), long long time); +#if DOLPHIN_REVISION >= 45 +u32 SIGetType(s32 chan); +#endif #endif // _DOLPHIN_OSSERIAL_H 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/nonmatchings/GXRedirectWriteGatherPipe.s b/nonmatchings/GXRedirectWriteGatherPipe.s index 9058519..023fb85 100644 --- a/nonmatchings/GXRedirectWriteGatherPipe.s +++ b/nonmatchings/GXRedirectWriteGatherPipe.s @@ -12,16 +12,26 @@ /* 000013EC 00001420 28 00 00 00 */ cmplwi r0, 0x0 /* 000013F0 00001424 41 82 00 18 */ beq L_00001408 /* 000013F4 00001428 38 7F 00 14 */ addi r3, r31, 0x14 +#if DOLPHIN_REVISION >= 45 +/* 000013F8 0000142C 38 80 05 A6 */ li r4, 0x5b8 +/* 000013FC 00001430 38 BF 04 F0 */ addi r5, r31, 0x48c +#else /* 000013F8 0000142C 38 80 05 A6 */ li r4, 0x5a6 /* 000013FC 00001430 38 BF 04 F0 */ addi r5, r31, 0x4f0 +#endif /* 00001400 00001434 4C C6 31 82 */ crclr 4*cr1+eq /* 00001404 00001438 48 00 00 01 */ bl OSPanic L_00001408: /* 00001408 0000143C 57 A0 06 FF */ clrlwi. r0, r29, 27 /* 0000140C 00001440 41 82 00 18 */ beq L_00001424 /* 00001410 00001444 38 7F 00 14 */ addi r3, r31, 0x14 +#if DOLPHIN_REVISION >= 45 +/* 00001414 00001448 38 80 05 A7 */ li r4, 0x5b9 +/* 00001418 0000144C 38 BF 05 34 */ addi r5, r31, 0x4d0 +#else /* 00001414 00001448 38 80 05 A7 */ li r4, 0x5a7 /* 00001418 0000144C 38 BF 05 34 */ addi r5, r31, 0x534 +#endif /* 0000141C 00001450 4C C6 31 82 */ crclr 4*cr1+eq /* 00001420 00001454 48 00 00 01 */ bl OSPanic L_00001424: @@ -29,8 +39,13 @@ L_00001424: /* 00001428 0000145C 2C 00 00 00 */ cmpwi r0, 0x0 /* 0000142C 00001460 41 82 00 18 */ beq L_00001444 /* 00001430 00001464 38 7F 00 14 */ addi r3, r31, 0x14 +#if DOLPHIN_REVISION >= 45 +/* 00001434 00001468 38 80 05 A9 */ li r4, 0x5bb +/* 00001438 0000146C 38 BF 05 5C */ addi r5, r31, 0x4f8 +#else /* 00001434 00001468 38 80 05 A9 */ li r4, 0x5a9 /* 00001438 0000146C 38 BF 05 5C */ addi r5, r31, 0x55c +#endif /* 0000143C 00001470 4C C6 31 82 */ crclr 4*cr1+eq /* 00001440 00001474 48 00 00 01 */ bl OSPanic L_00001444: @@ -69,7 +84,11 @@ L_0000148C: /* 000014BC 000014F0 57 A0 D9 D5 */ rlwinm. r0, r29, 27, 7, 10 /* 000014C0 000014F4 41 82 00 18 */ beq L_000014D8 /* 000014C4 000014F8 38 7F 00 14 */ addi r3, r31, 0x14 +#if DOLPHIN_REVISION >= 45 +/* 000014C8 000014FC 38 80 05 C8 */ li r4, 0x5da +#else /* 000014C8 000014FC 38 80 05 C8 */ li r4, 0x5c8 +#endif /* 000014CC 00001500 38 BF 03 98 */ addi r5, r31, 0x398 /* 000014D0 00001504 4C C6 31 82 */ crclr 4*cr1+eq /* 000014D4 00001508 48 00 00 01 */ bl OSPanic diff --git a/nonmatchings/GXRestoreWriteGatherPipe.s b/nonmatchings/GXRestoreWriteGatherPipe.s index 84d1583..1b1c219 100644 --- a/nonmatchings/GXRestoreWriteGatherPipe.s +++ b/nonmatchings/GXRestoreWriteGatherPipe.s @@ -9,8 +9,13 @@ /* 00001538 0000156C 2C 00 00 00 */ cmpwi r0, 0x0 /* 0000153C 00001570 40 82 00 18 */ bne L_00001554 /* 00001540 00001574 38 7E 00 14 */ addi r3, r30, 0x14 +#if DOLPHIN_REVISION >= 45 +/* 00001544 00001578 38 80 05 E1 */ li r4, 0x5f3 +/* 00001548 0000157C 38 BE 05 84 */ addi r5, r30, 0x520 +#else /* 00001544 00001578 38 80 05 E1 */ li r4, 0x5e1 /* 00001548 0000157C 38 BE 05 84 */ addi r5, r30, 0x584 +#endif /* 0000154C 00001580 4C C6 31 82 */ crclr 4*cr1+eq /* 00001550 00001584 48 00 00 01 */ bl OSPanic L_00001554: @@ -53,7 +58,11 @@ L_00001588: /* 000015D8 0000160C 54 60 D9 55 */ rlwinm. r0, r3, 27, 5, 10 /* 000015DC 00001610 41 82 00 18 */ beq L_000015F4 /* 000015E0 00001614 38 7E 00 14 */ addi r3, r30, 0x14 +#if DOLPHIN_REVISION >= 45 +/* 000015E4 00001618 38 80 05 FB */ li r4, 0x60d +#else /* 000015E4 00001618 38 80 05 FB */ li r4, 0x5fb +#endif /* 000015E8 0000161C 38 BE 03 98 */ addi r5, r30, 0x398 /* 000015EC 00001620 4C C6 31 82 */ crclr 4*cr1+eq /* 000015F0 00001624 48 00 00 01 */ bl OSPanic diff --git a/nonmatchings/GXSetCPUFifo.s b/nonmatchings/GXSetCPUFifo.s index a4f69cf..83ee0cc 100644 --- a/nonmatchings/GXSetCPUFifo.s +++ b/nonmatchings/GXSetCPUFifo.s @@ -27,7 +27,11 @@ /* 00000640 00000674 54 60 D9 55 */ rlwinm. r0, r3, 27, 5, 10 /* 00000644 00000678 41 82 00 18 */ beq L_0000065C /* 00000648 0000067C 38 7C 00 14 */ addi r3, r28, 0x14 +#if DOLPHIN_REVISION >= 45 +/* 0000064C 00000680 38 80 02 94 */ li r4, 0x29f +#else /* 0000064C 00000680 38 80 02 94 */ li r4, 0x294 +#endif /* 00000650 00000684 38 BC 03 98 */ addi r5, r28, 0x398 /* 00000654 00000688 4C C6 31 82 */ crclr 4*cr1+eq /* 00000658 0000068C 48 00 00 01 */ bl OSPanic @@ -77,7 +81,11 @@ L_000006C4: /* 000006FC 00000730 54 60 D9 55 */ rlwinm. r0, r3, 27, 5, 10 /* 00000700 00000734 41 82 00 18 */ beq L_00000718 /* 00000704 00000738 38 7C 00 14 */ addi r3, r28, 0x14 +#if DOLPHIN_REVISION >= 45 +/* 00000708 0000073C 38 80 02 B7 */ li r4, 0x2c2 +#else /* 00000708 0000073C 38 80 02 B7 */ li r4, 0x2b7 +#endif /* 0000070C 00000740 38 BC 03 98 */ addi r5, r28, 0x398 /* 00000710 00000744 4C C6 31 82 */ crclr 4*cr1+eq /* 00000714 00000748 48 00 00 01 */ bl OSPanic diff --git a/src/card/CARDBios.c b/src/card/CARDBios.c index b6959f7..6038b0a 100644 --- a/src/card/CARDBios.c +++ b/src/card/CARDBios.c @@ -1,3 +1,6 @@ +#if DOLPHIN_REVISION >= 45 +#include // need NULL to be defined as 0L +#endif #include #include #include @@ -28,19 +31,29 @@ void __CARDSyncCallback(s32 chan, s32 result) { OSWakeupThread(&card->threadQueue); } +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 16 : 0) + void __CARDExtHandler(s32 chan, OSContext *context) { CARDControl *card; CARDCallback callback; - ASSERTLINE(0xB6, 0 <= chan && chan < 2); + ASSERTLINE(0xB6+LINE_OFFSET, 0 <= chan && chan < 2); + +#undef LINE_OFFSET +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 19 : 0) card = &__CARDBlock[chan]; if (card->attached) { - ASSERTLINE(0xBA, card->txCallback == 0); + ASSERTLINE(0xBA+LINE_OFFSET, card->txCallback == 0); card->attached = FALSE; +#if DOLPHIN_REVISION < 45 card->result = CARD_RESULT_NOCARD; +#endif EXISetExiCallback(chan, 0); +#if DOLPHIN_REVISION >= 37 + OSCancelAlarm(&card->alarm); +#endif callback = card->exiCallback; if (callback) @@ -48,6 +61,11 @@ void __CARDExtHandler(s32 chan, OSContext *context) { card->exiCallback = 0; callback(chan, CARD_RESULT_NOCARD); } +#if DOLPHIN_REVISION >= 37 + if (card->result != -1) { + card->result = -3; + } +#endif callback = card->extCallback; if (callback && CARD_MAX_MOUNT_STEP <= card->mountStep) @@ -58,13 +76,16 @@ void __CARDExtHandler(s32 chan, OSContext *context) { } } +#undef LINE_OFFSET +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 29 : 0) + void __CARDExiHandler(s32 chan, OSContext *context) { CARDControl *card; CARDCallback callback; u8 status; s32 result; - ASSERTLINE(0xDC, 0 <= chan && chan < 2); + ASSERTLINE(0xDC+LINE_OFFSET, 0 <= chan && chan < 2); card = &__CARDBlock[chan]; @@ -110,20 +131,34 @@ void __CARDExiHandler(s32 chan, OSContext *context) { } } +#undef LINE_OFFSET +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 30 : 0) + void __CARDTxHandler(s32 chan, OSContext *context) { CARDControl *card; CARDCallback callback; +#if DOLPHIN_REVISION >= 37 + BOOL r31; +#endif - ASSERTLINE(0x12D, 0 <= chan && chan < 2); + ASSERTLINE(0x12D+LINE_OFFSET, 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 } } @@ -131,7 +166,7 @@ void __CARDUnlockedHandler(s32 chan, OSContext *context) { CARDControl *card; CARDCallback callback; - ASSERTLINE(0x15C, 0 <= chan && chan < 2); + ASSERTLINE(0x15C+LINE_OFFSET, 0 <= chan && chan < 2); card = &__CARDBlock[chan]; callback = card->unlockCallback; @@ -146,7 +181,7 @@ int __CARDReadNintendoID(s32 chan, u32 *id) { BOOL err; u32 cmd; - ASSERTLINE(0x16F, 0 <= chan && chan < 2); + ASSERTLINE(0x16F+LINE_OFFSET, 0 <= chan && chan < 2); if (!EXISelect(chan, 0, 0)) { return CARD_RESULT_NOCARD; @@ -173,7 +208,7 @@ s32 __CARDEnableInterrupt(s32 chan, BOOL enable) { BOOL err; u32 cmd; - ASSERTLINE(0x190, 0 <= chan && chan < 2); + ASSERTLINE(0x190+LINE_OFFSET, 0 <= chan && chan < 2); if (!EXISelect(chan, 0, 4)) { return CARD_RESULT_NOCARD; @@ -191,7 +226,7 @@ s32 __CARDReadStatus(s32 chan, u8 *status) { BOOL err; u32 cmd; - ASSERTLINE(0x1A3, 0 <= chan && chan < 2); + ASSERTLINE(0x1A3+LINE_OFFSET, 0 <= chan && chan < 2); if (!EXISelect(chan, 0, 4)) { return CARD_RESULT_NOCARD; @@ -211,7 +246,7 @@ s32 __CARDClearStatus(s32 chan) { BOOL err; u32 cmd; - ASSERTLINE(0x1B8, 0 <= chan && chan < 2); + ASSERTLINE(0x1B8+LINE_OFFSET, 0 <= chan && chan < 2); if (!EXISelect(chan, 0, 4)) { return CARD_RESULT_NOCARD; @@ -230,7 +265,7 @@ long __CARDSleep(long chan) { int err; unsigned long cmd; - ASSERTLINE(0x1CB, 0 <= chan && chan < 2); + ASSERTLINE(0x1CB+LINE_OFFSET, 0 <= chan && chan < 2); if (!EXISelect(chan, 0, 4)) { return CARD_RESULT_NOCARD; @@ -251,7 +286,7 @@ long __CARDWakeup(long chan) { int err; unsigned long cmd; - ASSERTLINE(0x1DE, 0 <= chan && chan < 2); + ASSERTLINE(0x1DE+LINE_OFFSET, 0 <= chan && chan < 2); if (!EXISelect(chan, 0, 4)) { return CARD_RESULT_NOCARD; } @@ -280,7 +315,18 @@ static void TimeoutHandler(OSAlarm *alarm, OSContext *context) { } } - ASSERTLINE(0x20E, 0 <= chan && chan < 2); +#if DOLPHIN_REVISION == 37 + if (!card->attached) { + return; + } +#endif + + ASSERTLINE(0x20E+LINE_OFFSET, 0 <= chan && chan < 2); +#if DOLPHIN_REVISION >= 45 + if (!card->attached) { + return; + } +#endif EXISetExiCallback(chan, NULL); callback = card->exiCallback; @@ -297,19 +343,26 @@ 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; } } +#undef LINE_OFFSET +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 41 : 0) + static s32 Retry(s32 chan) { CARDControl *card; - ASSERTLINE(0x247, 0 <= chan && chan < 2); + ASSERTLINE(0x247+LINE_OFFSET, 0 <= chan && chan < 2); card = &__CARDBlock[chan]; if (!EXISelect(chan, 0, 4)) @@ -357,7 +410,7 @@ static void UnlockedCallback(s32 chan, s32 result) { CARDCallback callback; CARDControl *card; - ASSERTLINE(0x287, 0 <= chan && chan < 2); + ASSERTLINE(0x287+LINE_OFFSET, 0 <= chan && chan < 2); card = &__CARDBlock[chan]; if (result >= 0) @@ -401,16 +454,30 @@ static void UnlockedCallback(s32 chan, s32 result) { } } +#undef LINE_OFFSET +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 45 : 0) + static s32 __CARDStart(s32 chan, CARDCallback txCallback, CARDCallback exiCallback) { +#if DOLPHIN_REVISION >= 45 + BOOL enabled; +#endif CARDControl *card; s32 result; - ASSERTLINE(0x2C5, 0 <= chan && chan < 2); +#if DOLPHIN_REVISION >= 45 + enabled = OSDisableInterrupts(); +#endif + + ASSERTLINE(0x2C5+LINE_OFFSET, 0 <= chan && chan < 2); card = &__CARDBlock[chan]; if (!card->attached) { +#if DOLPHIN_REVISION >= 45 + result = CARD_RESULT_NOCARD; +#else return CARD_RESULT_NOCARD; +#endif } else { @@ -426,7 +493,11 @@ static s32 __CARDStart(s32 chan, CARDCallback txCallback, CARDCallback exiCallba card->unlockCallback = UnlockedCallback; if (!EXILock(chan, 0, __CARDUnlockedHandler)) { +#if DOLPHIN_REVISION >= 45 + result = CARD_RESULT_BUSY; +#else return CARD_RESULT_BUSY; +#endif } else { @@ -435,17 +506,30 @@ static s32 __CARDStart(s32 chan, CARDCallback txCallback, CARDCallback exiCallba if (!EXISelect(chan, 0, 4)) { EXIUnlock(chan); +#if DOLPHIN_REVISION >= 45 + result = CARD_RESULT_NOCARD; +#else return CARD_RESULT_NOCARD; +#endif } else { SetupTimeoutAlarm(card); +#if DOLPHIN_REVISION >= 45 + result = CARD_RESULT_READY; +#else return CARD_RESULT_READY; +#endif } } } +#if DOLPHIN_REVISION >= 45 + OSRestoreInterrupts(enabled); + return result; +#else return CARD_RESULT_READY; +#endif } #define AD1(x) ((u8)(((x) >> 17) & 0x7f)) @@ -454,15 +538,18 @@ static s32 __CARDStart(s32 chan, CARDCallback txCallback, CARDCallback exiCallba #define AD3(x) ((u8)(((x) >> 7) & 0x03)) #define BA(x) ((u8)((x)&0x7f)) +#undef LINE_OFFSET +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 55 : 0) + s32 __CARDReadSegment(s32 chan, CARDCallback callback) { CARDControl *card; s32 result; - ASSERTLINE(0x2F9, 0 <= chan && chan < 2); + ASSERTLINE(0x2F9+LINE_OFFSET, 0 <= chan && chan < 2); card = &__CARDBlock[chan]; - ASSERTLINE(0x2FB, card->addr % CARD_SEG_SIZE == 0); - ASSERTLINE(0x2FC, card->addr < (u32) card->size * 1024 * 1024 / 8); + ASSERTLINE(0x2FB+LINE_OFFSET, card->addr % CARD_SEG_SIZE == 0); + ASSERTLINE(0x2FC+LINE_OFFSET, card->addr < (u32) card->size * 1024 * 1024 / 8); card->cmd[0] = 0x52; card->cmd[1] = AD1(card->addr); card->cmd[2] = AD2(card->addr); @@ -475,34 +562,56 @@ s32 __CARDReadSegment(s32 chan, CARDCallback callback) { result = __CARDStart(chan, callback, 0); if (result == CARD_RESULT_BUSY) { +#if DOLPHIN_REVISION >= 45 + result = CARD_RESULT_READY; +#else return CARD_RESULT_READY; +#endif } - if (result < 0) - { - return result; - } - if (!EXIImmEx(chan, card->cmd, card->cmdlen, 1) || - !EXIImmEx(chan, (u8 *)card->workArea + sizeof(CARDID), card->latency, - 1) || // XXX use DMA if possible - !EXIDma(chan, card->buffer, 512, card->mode, __CARDTxHandler)) - { - card->txCallback = NULL; - EXIDeselect(chan); - EXIUnlock(chan); - return CARD_RESULT_NOCARD; +#if DOLPHIN_REVISION >= 45 + else if (result >= 0) { +#else + if (result < 0) { + return result; + } +#endif + if (!EXIImmEx(chan, card->cmd, card->cmdlen, 1) || + !EXIImmEx(chan, (u8 *)card->workArea + sizeof(CARDID), card->latency, + 1) || // XXX use DMA if possible + !EXIDma(chan, card->buffer, 512, card->mode, __CARDTxHandler)) + { + card->txCallback = NULL; + EXIDeselect(chan); + EXIUnlock(chan); +#if DOLPHIN_REVISION >= 45 + result = CARD_RESULT_NOCARD; +#else + return CARD_RESULT_NOCARD; +#endif + } +#if DOLPHIN_REVISION >= 45 + else { + result = CARD_RESULT_READY; + } } + return result; +#else return CARD_RESULT_READY; +#endif } +#undef LINE_OFFSET +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 56 : 0) + s32 __CARDWritePage(s32 chan, CARDCallback callback) { CARDControl *card; s32 result; - ASSERTLINE(0x331, 0 <= chan && chan < 2); + ASSERTLINE(0x331+LINE_OFFSET, 0 <= chan && chan < 2); card = &__CARDBlock[chan]; - ASSERTLINE(0x333, card->addr % CARD_PAGE_SIZE == 0); - ASSERTLINE(0x334, card->addr < (u32) card->size * 1024 * 1024 / 8); + ASSERTLINE(0x333+LINE_OFFSET, card->addr % CARD_PAGE_SIZE == 0); + ASSERTLINE(0x334+LINE_OFFSET, card->addr < (u32) card->size * 1024 * 1024 / 8); card->cmd[0] = 0xF2; card->cmd[1] = AD1(card->addr); card->cmd[2] = AD2(card->addr); @@ -515,28 +624,51 @@ s32 __CARDWritePage(s32 chan, CARDCallback callback) { result = __CARDStart(chan, 0, callback); if (result == CARD_RESULT_BUSY) { +#if DOLPHIN_REVISION >= 45 + result = CARD_RESULT_READY; +#else return CARD_RESULT_READY; +#endif } - if (result < 0) - { - return result; - } - if (!EXIImmEx(chan, card->cmd, card->cmdlen, 1) || - !EXIDma(chan, card->buffer, 128, card->mode, __CARDTxHandler)) - { - card->exiCallback = 0; - EXIDeselect(chan); - EXIUnlock(chan); - return CARD_RESULT_NOCARD; +#if DOLPHIN_REVISION >= 45 + else if (result >= 0) { +#else + if (result < 0) + { + return result; + } +#endif + if (!EXIImmEx(chan, card->cmd, card->cmdlen, 1) || + !EXIDma(chan, card->buffer, 128, card->mode, __CARDTxHandler)) + { + card->exiCallback = 0; + EXIDeselect(chan); + EXIUnlock(chan); +#if DOLPHIN_REVISION >= 45 + result = CARD_RESULT_NOCARD; +#else + return CARD_RESULT_NOCARD; +#endif + } +#if DOLPHIN_REVISION >= 45 + else { + result = CARD_RESULT_READY; + } } + return result; +#else return CARD_RESULT_READY; +#endif } +#undef LINE_OFFSET +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 57 : 0) + long __CARDErase(long chan, void (* callback)(long, long)) { struct CARDControl * card; long result; - ASSERTLINE(0x364, 0 <= chan && chan < 2); + ASSERTLINE(0x364+LINE_OFFSET, 0 <= chan && chan < 2); card = &__CARDBlock[chan]; card->cmd[0] = 0xF4; @@ -547,18 +679,34 @@ long __CARDErase(long chan, void (* callback)(long, long)) { card->retry = 3; result = __CARDStart(chan, 0, callback); if (result == -1) { +#if DOLPHIN_REVISION >= 45 + result = 0; +#else return 0; +#endif } - if (result < 0) { - return result; - } - result = 0; - if (EXIImmEx(chan, &card->cmd, card->cmdlen, 1) == 0) { - result = -3; - card->exiCallback = 0; +#if DOLPHIN_REVISION >= 45 + else if (result >= 0) { +#else + if (result < 0) { + return result; + } + result = 0; +#endif + if (EXIImmEx(chan, &card->cmd, card->cmdlen, 1) == 0) { + result = -3; + card->exiCallback = 0; + } +#if DOLPHIN_REVISION >= 45 + else { + result = 0; + } +#endif + EXIDeselect(chan); + EXIUnlock(chan); +#if DOLPHIN_REVISION >= 45 } - EXIDeselect(chan); - EXIUnlock(chan); +#endif return result; } @@ -566,11 +714,11 @@ s32 __CARDEraseSector(s32 chan, u32 addr, CARDCallback callback) { s32 result; CARDControl *card; - ASSERTLINE(0x394, 0 <= chan && chan < 2); + ASSERTLINE(0x394+LINE_OFFSET, 0 <= chan && chan < 2); card = &__CARDBlock[chan]; - ASSERTLINE(0x396, addr % card->sectorSize == 0); - ASSERTLINE(0x397, addr < (u32) card->size * 1024 * 1024 / 8); + ASSERTLINE(0x396+LINE_OFFSET, addr % card->sectorSize == 0); + ASSERTLINE(0x397+LINE_OFFSET, addr < (u32) card->size * 1024 * 1024 / 8); card->cmd[0] = 0xF1; card->cmd[1] = AD1(addr); card->cmd[2] = AD2(addr); @@ -582,22 +730,36 @@ s32 __CARDEraseSector(s32 chan, u32 addr, CARDCallback callback) { if (result == CARD_RESULT_BUSY) { +#if DOLPHIN_REVISION >= 45 + result = CARD_RESULT_READY; +#else return CARD_RESULT_READY; +#endif } - if (result < 0) - { - return result; - } - - result = CARD_RESULT_READY; - if (!EXIImmEx(chan, card->cmd, card->cmdlen, 1)) - { - result = CARD_RESULT_NOCARD; - card->exiCallback = NULL; +#if DOLPHIN_REVISION >= 45 + else if (result >= 0) { +#else + if (result < 0) + { + return result; + } + result = CARD_RESULT_READY; +#endif + if (!EXIImmEx(chan, card->cmd, card->cmdlen, 1)) + { + result = CARD_RESULT_NOCARD; + card->exiCallback = NULL; + } +#if DOLPHIN_REVISION >= 45 + else { + result = 0; + } +#endif + EXIDeselect(chan); + EXIUnlock(chan); +#if DOLPHIN_REVISION >= 45 } - - EXIDeselect(chan); - EXIUnlock(chan); +#endif return result; } @@ -660,25 +822,38 @@ s32 __CARDGetControlBlock(s32 chan, CARDControl **pcard) { return result; } +#undef LINE_OFFSET +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 43 : 0) + s32 __CARDPutControlBlock(CARDControl *card, s32 result) { BOOL enabled; - ASSERTLINE(0x43A, result != CARD_RESULT_BUSY); + ASSERTLINE(0x43A+LINE_OFFSET, result != CARD_RESULT_BUSY); enabled = OSDisableInterrupts(); if (card->attached) { card->result = result; - } else { + } +#if DOLPHIN_REVISION >= 45 + else if (card->result == -1) { + card->result = result; + } +#else + else { ASSERTLINE(0x442, card->result == CARD_RESULT_NOCARD); } +#endif OSRestoreInterrupts(enabled); return result; } +#undef LINE_OFFSET +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 49 : 0) + s32 CARDGetResultCode(s32 chan) { CARDControl *card; - ASSERTLINE(0x455, 0 <= chan && chan < 2); + ASSERTLINE(0x455+LINE_OFFSET, 0 <= chan && chan < 2); if (chan < 0 || chan >= 2) { @@ -709,15 +884,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 +932,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 +943,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..13cc2cb 100644 --- a/src/card/CARDCheck.c +++ b/src/card/CARDCheck.c @@ -1,3 +1,6 @@ +#if DOLPHIN_REVISION >= 45 +#include // need NULL to be defined as 0L +#endif #include #include @@ -8,11 +11,14 @@ static s32 VerifyID(CARDControl *card); static s32 VerifyDir(CARDControl *card, int *outCurrent); static s32 VerifyFAT(CARDControl *card, int *outCurrent); +#undef LINE_OFFSET +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 7 : 0) + void __CARDCheckSum(void *ptr, int length, u16 *checksum, u16 *checksumInv) { u16 *p; int i; - ASSERTLINE(0x44, length % sizeof(u16) == 0); + ASSERTLINE(0x44+LINE_OFFSET, length % sizeof(u16) == 0); length /= sizeof(u16); *checksum = *checksumInv = 0; @@ -181,15 +187,175 @@ s32 __CARDVerify(CARDControl *card) { switch (errors) { case 0: - ASSERTLINE(0x11F, card->currentDir); - ASSERTLINE(0x120, card->currentFat); + ASSERTLINE(0x11F+LINE_OFFSET, card->currentDir); + ASSERTLINE(0x120+LINE_OFFSET, card->currentFat); return CARD_RESULT_READY; case 1: return CARD_RESULT_BROKEN; default: return CARD_RESULT_BROKEN; } } +#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 DOLPHIN_REVISION >= 45 + ASSERTLINE(0x152, 0 <= chan && chan < 2); +#endif + + 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); + +#if DOLPHIN_REVISION >= 45 + ASSERTLINE(0x171, errors == 0 || errors == 1); +#endif + + switch (errors) + { + case 0: +#if DOLPHIN_REVISION >= 45 + ASSERTLINE(0x175, card->currentDir); + ASSERTLINE(0x176, card->currentFat); +#endif + break; + case 1: + if (!card->currentDir) + { +#if DOLPHIN_REVISION >= 45 + ASSERTLINE(0x17B, card->currentFat); +#endif + card->currentDir = dir[currentDir]; + memcpy(dir[currentDir], dir[currentDir ^ 1], CARD_SYSTEM_BLOCK_SIZE); + updateDir = TRUE; + } + else + { +#if DOLPHIN_REVISION >= 45 + ASSERTLINE(0x182, !card->currentFat); +#endif + 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,13 +480,32 @@ s32 CARDCheckAsync(s32 chan, CARDCallback callback) { } return __CARDPutControlBlock(card, CARD_RESULT_READY); +#endif +} + +#if DOLPHIN_REVISION >= 45 +long CARDCheckEx(long chan, long *xferBytes) +{ + long result = CARDCheckExAsync(chan, xferBytes, __CARDSyncCallback); + + if (result < 0 || xferBytes == NULL) { + return result; + } + return __CARDSync(chan); } +#endif long CARDCheck(long chan) { +#if DOLPHIN_REVISION >= 45 + long xferBytes; + + return CARDCheckEx(chan, &xferBytes); +#else long result = CARDCheckAsync(chan, __CARDSyncCallback); if (result < 0) { return result; } return __CARDSync(chan); +#endif } diff --git a/src/card/CARDCreate.c b/src/card/CARDCreate.c index 3401acd..de41327 100644 --- a/src/card/CARDCreate.c +++ b/src/card/CARDCreate.c @@ -3,6 +3,9 @@ #include "__card.h" +#undef LINE_OFFSET +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 3 : 0) + static void CreateCallbackFat(long chan, long result); static void CreateCallbackFat(long chan, long result) { @@ -22,13 +25,16 @@ static void CreateCallbackFat(long chan, long result) { memcpy(ent->company, __CARDDiskID->company, sizeof(ent->company)); ent->permission = 4; ent->copyTimes = 0; - ASSERTLINE(0x66, CARDIsValidBlockNo(card, card->startBlock)); + ASSERTLINE(0x66+LINE_OFFSET, CARDIsValidBlockNo(card, card->startBlock)); ent->startBlock = (u16) card->startBlock; ent->bannerFormat = 0; ent->iconAddr = -1; 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()); @@ -45,6 +51,9 @@ after:; } } +#undef LINE_OFFSET +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 5 : 0) + s32 CARDCreateAsync(s32 chan, const char* fileName, u32 size, CARDFileInfo* fileInfo, CARDCallback callback) { CARDControl* card; @@ -55,8 +64,8 @@ s32 CARDCreateAsync(s32 chan, const char* fileName, u32 size, CARDFileInfo* file u16* fat; s32 result; - ASSERTLINE(0xA4, 0 <= chan && chan < 2); - ASSERTLINE(0xA5, strlen(fileName) <= CARD_FILENAME_MAX); + ASSERTLINE(0xA4+LINE_OFFSET, 0 <= chan && chan < 2); + ASSERTLINE(0xA5+LINE_OFFSET, strlen(fileName) <= CARD_FILENAME_MAX); if (strlen(fileName) > (u32)CARD_FILENAME_MAX) { return CARD_RESULT_NAMETOOLONG; @@ -67,7 +76,7 @@ s32 CARDCreateAsync(s32 chan, const char* fileName, u32 size, CARDFileInfo* file return result; } - ASSERTLINE(0xB1, 0 < size && (size % card->sectorSize) == 0); + ASSERTLINE(0xB1+LINE_OFFSET, 0 < size && (size % card->sectorSize) == 0); if (size <= 0 || (size % card->sectorSize) != 0) { return CARD_RESULT_FATAL_ERROR; 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..06e55f6 100644 --- a/src/card/CARDRead.c +++ b/src/card/CARDRead.c @@ -9,6 +9,9 @@ // functions static void ReadCallback(s32 chan, s32 result); +#undef LINE_OFFSET +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 3 : 0) + s32 __CARDSeek(CARDFileInfo *fileInfo, s32 length, s32 offset, CARDControl **pcard) { CARDControl *card; CARDDir *dir; @@ -16,15 +19,15 @@ s32 __CARDSeek(CARDFileInfo *fileInfo, s32 length, s32 offset, CARDControl **pca s32 result; u16 *fat; - ASSERTLINE(0x57, 0 <= fileInfo->chan && fileInfo->chan < 2); - ASSERTLINE(0x58, 0 <= fileInfo->fileNo && fileInfo->fileNo < CARD_MAX_FILE); + ASSERTLINE(0x57+LINE_OFFSET, 0 <= fileInfo->chan && fileInfo->chan < 2); + ASSERTLINE(0x58+LINE_OFFSET, 0 <= fileInfo->fileNo && fileInfo->fileNo < CARD_MAX_FILE); result = __CARDGetControlBlock(fileInfo->chan, &card); if (result < 0) return result; - ASSERTLINE(0x5F, CARDIsValidBlockNo(card, fileInfo->iBlock)); - ASSERTLINE(0x60, fileInfo->offset < card->cBlock * card->sectorSize); + ASSERTLINE(0x5F+LINE_OFFSET, CARDIsValidBlockNo(card, fileInfo->iBlock)); + ASSERTLINE(0x60+LINE_OFFSET, fileInfo->offset < card->cBlock * card->sectorSize); if (!CARDIsValidBlockNo(card, fileInfo->iBlock) || card->cBlock * card->sectorSize <= fileInfo->offset) return __CARDPutControlBlock(card, CARD_RESULT_FATAL_ERROR); @@ -32,7 +35,7 @@ s32 __CARDSeek(CARDFileInfo *fileInfo, s32 length, s32 offset, CARDControl **pca dir = __CARDGetDirBlock(card); ent = &dir[fileInfo->fileNo]; - ASSERTLINE(0x6A, ent->gameName[0] != 0xff); + ASSERTLINE(0x6A+LINE_OFFSET, ent->gameName[0] != 0xff); if (ent->length * card->sectorSize <= offset || ent->length * card->sectorSize < offset + length) return __CARDPutControlBlock(card, CARD_RESULT_LIMIT); @@ -79,10 +82,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; @@ -96,8 +103,8 @@ static void ReadCallback(s32 chan, s32 result) { goto error; } - ASSERTLINE(0xBC, OFFSET(fileInfo->length, CARD_SEG_SIZE) == 0); - ASSERTLINE(0xBD, OFFSET(fileInfo->offset, card->sectorSize) == 0); + ASSERTLINE(0xBC+LINE_OFFSET, OFFSET(fileInfo->length, CARD_SEG_SIZE) == 0); + ASSERTLINE(0xBD+LINE_OFFSET, OFFSET(fileInfo->offset, card->sectorSize) == 0); result = __CARDRead(chan, card->sectorSize * (u32)fileInfo->iBlock, (fileInfo->length < card->sectorSize) ? fileInfo->length : card->sectorSize, card->buffer, @@ -111,7 +118,7 @@ static void ReadCallback(s32 chan, s32 result) { callback = card->apiCallback; card->apiCallback = NULL; __CARDPutControlBlock(card, result); - ASSERTLINE(0xCE, callback); + ASSERTLINE(0xCE+LINE_OFFSET, callback); callback(chan, result); } @@ -121,9 +128,9 @@ s32 CARDReadAsync(CARDFileInfo *fileInfo, void *buf, s32 length, s32 offset, CAR CARDDir *dir; CARDDir *ent; - ASSERTLINE(0xF0, buf && OFFSET(buf, 32) == 0); - ASSERTLINE(0xF1, OFFSET(offset, CARD_SEG_SIZE) == 0); - ASSERTLINE(0xF2, 0 < length && OFFSET(length, CARD_SEG_SIZE) == 0); + ASSERTLINE(0xF0+LINE_OFFSET, buf && OFFSET(buf, 32) == 0); + ASSERTLINE(0xF1+LINE_OFFSET, OFFSET(offset, CARD_SEG_SIZE) == 0); + ASSERTLINE(0xF2+LINE_OFFSET, 0 < length && OFFSET(length, CARD_SEG_SIZE) == 0); if (OFFSET(offset, CARD_SEG_SIZE) != 0 || OFFSET(length, CARD_SEG_SIZE) != 0) return CARD_RESULT_FATAL_ERROR; @@ -164,8 +171,8 @@ s32 CARDCancel(CARDFileInfo *fileInfo) { s32 result; CARDControl *card; - ASSERTLINE(0x14D, 0 <= fileInfo->chan && fileInfo->chan < 2); - ASSERTLINE(0x14E, 0 <= fileInfo->fileNo && fileInfo->fileNo < CARD_MAX_FILE); + ASSERTLINE(0x14D+LINE_OFFSET, 0 <= fileInfo->chan && fileInfo->chan < 2); + ASSERTLINE(0x14E+LINE_OFFSET, 0 <= fileInfo->fileNo && fileInfo->fileNo < CARD_MAX_FILE); intrEnabled = OSDisableInterrupts(); diff --git a/src/card/CARDStat.c b/src/card/CARDStat.c index 8277f87..7ed7ffb 100644 --- a/src/card/CARDStat.c +++ b/src/card/CARDStat.c @@ -7,6 +7,9 @@ // functions static void UpdateIconOffsets(CARDDir *ent, CARDStat *stat); +#undef LINE_OFFSET +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 12 : 0) + static void UpdateIconOffsets(CARDDir *ent, CARDStat *stat) { u32 offset; BOOL iconTlut; @@ -18,6 +21,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; @@ -75,8 +81,8 @@ s32 CARDGetStatus(s32 chan, s32 fileNo, CARDStat *stat) { CARDDir *ent; s32 result; - ASSERTLINE(0x97, 0 <= chan && chan < 2); - ASSERTLINE(0x98, 0 <= fileNo && fileNo < CARD_MAX_FILE); + ASSERTLINE(0x97+LINE_OFFSET, 0 <= chan && chan < 2); + ASSERTLINE(0x98+LINE_OFFSET, 0 <= fileNo && fileNo < CARD_MAX_FILE); if (fileNo < 0 || CARD_MAX_FILE <= fileNo) return CARD_RESULT_FATAL_ERROR; @@ -116,11 +122,22 @@ s32 CARDSetStatusAsync(s32 chan, s32 fileNo, CARDStat *stat, CARDCallback callba CARDDir *ent; s32 result; - ASSERTLINE(0xD5, 0 <= fileNo && fileNo < CARD_MAX_FILE); - ASSERTLINE(0xD6, 0 <= chan && chan < 2); - + ASSERTLINE(0xD5+LINE_OFFSET, 0 <= fileNo && fileNo < CARD_MAX_FILE); + ASSERTLINE(0xD6+LINE_OFFSET, 0 <= chan && chan < 2); +#if DOLPHIN_REVISION >= 45 + ASSERTMSGLINE(0xEA, stat->iconAddr == 0xFFFFFFFF || stat->iconAddr < CARD_READ_SIZE, "CARDSetStatus[Async](): stat->iconAddr must be 0xffffffff or less than CARD_READ_SIZE."); + ASSERTMSGLINE(0xED, stat->commentAddr == 0xFFFFFFFF || (stat->commentAddr & 0x1FFF) <= 0x1FC0, "CARDSetStatus[Async](): comment strings (set by stat->commentAddr) must not cross 8KB byte boundary."); +#endif + +#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 +156,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..2f1c4d8 100644 --- a/src/card/CARDUnlock.c +++ b/src/card/CARDUnlock.c @@ -98,12 +98,14 @@ static u32 bitrev(u32 data) { #define SEC_AD3(x) ((u8)(((x) >> 19) & 0x03)) #define SEC_BA(x) ((u8)(((x) >> 12) & 0x7f)) +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 4 : 0) + static s32 ReadArrayUnlock(s32 chan, u32 data, void *rbuf, s32 rlen, s32 mode) { CARDControl *card; BOOL err; u8 cmd[5]; - ASSERTLINE(0xD1, 0 <= chan && chan < 2); + ASSERTLINE(0xD1+LINE_OFFSET, 0 <= chan && chan < 2); card = &__CARDBlock[chan]; if (!EXISelect(chan, 0, 4)) @@ -312,7 +314,7 @@ static void InitCallback(void *_task) break; } - ASSERTLINE(0x1E3, 0 <= chan && chan < 2); + ASSERTLINE(0x1E3+LINE_OFFSET, 0 <= chan && chan < 2); param = (CARDDecParam *)card->workArea; @@ -353,7 +355,7 @@ static void DoneCallback(void *_task) break; } - ASSERTLINE(0x214, 0 <= chan && chan < 2); + ASSERTLINE(0x214+LINE_OFFSET, 0 <= chan && chan < 2); param = (CARDDecParam *)card->workArea; input = (u8 *)((u8 *)param + sizeof(CARDDecParam)); @@ -368,6 +370,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 +387,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/demo/DEMOInit.c b/src/demo/DEMOInit.c index c4180f7..800938f 100644 --- a/src/demo/DEMOInit.c +++ b/src/demo/DEMOInit.c @@ -5,6 +5,7 @@ #include #include "__demo.h" +#include "__gx.h" extern unsigned char DemoStatEnable; // size: 0x1, address: 0x0 @@ -18,7 +19,11 @@ static unsigned char DemoFirstFrame = 1; // size: 0x1, address: 0x0 static void * DefaultFifo = NULL; // size: 0x4, address: 0x0 static GXFifoObj *DefaultFifoObj = NULL; // size: 0x4, address: 0x4 static struct _GXRenderModeObj * rmode; // size: 0x4, address: 0x8 +#if DOLPHIN_REVISION >= 45 +static int GPHangWorkaround; +#else static int BypassWorkaround; // size: 0x4, address: 0xC +#endif static unsigned long FrameCount; // size: 0x4, address: 0x10 static unsigned long FrameMissThreshold; // size: 0x4, address: 0x14 void * DemoFrameBuffer1; // size: 0x4, address: 0x20 @@ -31,9 +36,16 @@ static void __DEMOInitMem(); static void __DEMOInitGX(); static void __DEMOInitVI(); static void __DEMOInitForEmu(); +#if DOLPHIN_REVISION >= 45 +static void __NoHangRetraceCallback(); +static void __NoHangDoneRender(); +void DEMOSetGPHangMetric(u8 enable); +static void __DEMODiagnoseHang(); +#else static void __BypassRetraceCallback(); static void __BypassDoneRender(); static void LoadMemInfo(); +#endif void DEMOInit(struct _GXRenderModeObj * mode) { OSInit(); @@ -49,6 +61,8 @@ void DEMOInit(struct _GXRenderModeObj * mode) { __DEMOInitVI(); } +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 14 : 0) + static void __DEMOInitRenderMode(struct _GXRenderModeObj * mode) { if (mode != NULL) { rmode = mode; @@ -65,7 +79,7 @@ static void __DEMOInitRenderMode(struct _GXRenderModeObj * mode) { rmode = &GXMpal480IntDf; break; default: - OSPanic(__FILE__, 0x1A6, "DEMOInit: invalid TV format\n"); + OSPanic(__FILE__, 0x1A6+LINE_OFFSET, "DEMOInit: invalid TV format\n"); break; } GXAdjustForOverscan(rmode, &rmodeobj, 0, 0x10); @@ -82,10 +96,12 @@ static void __DEMOInitMem() { DemoCurrentBuffer = DemoFrameBuffer2; arenaLo = (void*)(((u32)DemoFrameBuffer2 + fbSize + 0x1F) & 0xFFFFFFE0); OSSetArenaLo(arenaLo); +#if DOLPHIN_REVISION < 45 if (((OSGetConsoleType() + 0xF0000000) == 4U) && ((OSGetPhysicalMemSize() + 0xFFC00000) != 0U) && (OSGetConsoleSimulatedMemSize() < 0x01800000U)) { LoadMemInfo(); return; } +#endif arenaLo = OSGetArenaLo(); arenaHi = OSGetArenaHi(); arenaLo = OSInitAlloc(arenaLo, arenaHi, 1); @@ -97,7 +113,13 @@ static void __DEMOInitMem() { } static void __DEMOInitGX() { - GXSetViewport(0.0f, 0.0f, rmode->fbWidth, rmode->xfbHeight, 0.0f, 1.0f); + GXSetViewport(0.0f, 0.0f, rmode->fbWidth, +#if DOLPHIN_REVISION >= 45 + rmode->efbHeight, +#else + rmode->xfbHeight, +#endif + 0.0f, 1.0f); GXSetScissor(0, 0, rmode->fbWidth, rmode->efbHeight); GXSetDispCopySrc(0, 0, rmode->fbWidth, rmode->efbHeight); GXSetDispCopyDst(rmode->fbWidth, rmode->xfbHeight); @@ -129,27 +151,54 @@ static void __DEMOInitVI() { } static void __DEMOInitForEmu() { - + } void DEMOBeforeRender() { - if (BypassWorkaround != 0) { +#if DOLPHIN_REVISION >= 45 + if (GPHangWorkaround) { + GXSetDrawSync(0xFEEB); + GXClearGPMetric(); + } +#else + if (BypassWorkaround) { GXSetDrawSync(0xFEEB); } +#endif if (rmode->field_rendering != 0) { - GXSetViewportJitter(0.0f, 0.0f, rmode->fbWidth, rmode->xfbHeight, 0.0f, 1.0f, VIGetNextField()); + GXSetViewportJitter(0.0f, 0.0f, rmode->fbWidth, +#if DOLPHIN_REVISION >= 45 + rmode->efbHeight, +#else + rmode->xfbHeight, +#endif + 0.0f, 1.0f, VIGetNextField()); } else { - GXSetViewport(0.0f, 0.0f, rmode->fbWidth, rmode->xfbHeight, 0.0f, 1.0f); + GXSetViewport(0.0f, 0.0f, rmode->fbWidth, +#if DOLPHIN_REVISION >= 45 + rmode->efbHeight, +#else + rmode->xfbHeight, +#endif + 0.0f, 1.0f); } GXInvalidateVtxCache(); GXInvalidateTexAll(); } void DEMODoneRender() { - if (BypassWorkaround != 0) { +#if DOLPHIN_REVISION >= 45 + if (GPHangWorkaround) { + ASSERTMSGLINE(0x2C1, !DemoStatEnable, "DEMOStats and GP hang diagnosis are mutually exclusive"); + __NoHangDoneRender(); + return; + } +#else + if (BypassWorkaround) { __BypassDoneRender(); return; } +#endif if (DemoStatEnable != 0) { GXDrawDone(); DEMOUpdateStats(1); @@ -213,6 +262,9 @@ void DEMOSetTevColorIn(enum _GXTevStageID stage, enum _GXTevColorArg a, enum _GX } } +#undef LINE_OFFSET +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? -1 : 0) + void DEMOSetTevOp(enum _GXTevStageID id, enum _GXTevMode mode) { enum _GXTevColorArg carg; enum _GXTevAlphaArg aarg; @@ -241,11 +293,15 @@ void DEMOSetTevOp(enum _GXTevStageID id, enum _GXTevMode mode) { GXSetTevAlphaIn(id, 7, 7, 7, 4); break; case 4: +#if DOLPHIN_REVISION >= 45 + DEMOSetTevColorIn(id, 0xF, 0xF, 0xF, carg); +#else GXSetTevColorIn(id, 0xF, 0xF, 0xF, carg); +#endif GXSetTevAlphaIn(id, 7, 7, 7, aarg); break; default: - ASSERTMSGLINE(0x367, FALSE, "DEMOSetTevOp: Invalid Tev Mode"); + ASSERTMSGLINE(0x367+LINE_OFFSET, FALSE, "DEMOSetTevOp: Invalid Tev Mode"); break; } GXSetTevColorOp(id, 0, 0, 0, 1, 0); @@ -260,6 +316,132 @@ u32 DEMOGetCurrentBuffer(void) { return (u32)DemoCurrentBuffer; } +#if DOLPHIN_REVISION >= 45 +void DEMOEnableGPHangWorkaround(unsigned long timeoutFrames) { + if (timeoutFrames) { + ASSERTMSGLINE(0x3B1, !DemoStatEnable, "DEMOStats and GP hang diagnosis are mutually exclusive"); + GPHangWorkaround = 1; + FrameMissThreshold = timeoutFrames; + VISetPreRetraceCallback(__NoHangRetraceCallback); + DEMOSetGPHangMetric(1); + } else { + GPHangWorkaround = 0; + FrameMissThreshold = 0; + DEMOSetGPHangMetric(0); + VISetPreRetraceCallback(0); + } +} + +static void __NoHangRetraceCallback() { + u32 ovc; + u8 overhi; + u8 junk; + u32 unused; + static u32 ovFrameCount; + static u32 lastOvc; + + FrameCount++; + GXGetGPStatus(&overhi, &junk, &junk, &junk, &junk); + ovc = GXGetOverflowCount(); + if (overhi && ovc == lastOvc) { + ovFrameCount++; + if (ovFrameCount >= FrameMissThreshold) { + OSReport("---------WARNING : HANG AT HIGH WATERMARK----------\n"); + __DEMODiagnoseHang(); + OSPanic(__FILE__, 0x3EC, "Halting program"); + } + } else { + lastOvc = ovc; + ovFrameCount = 0; + } +} + +static void __NoHangDoneRender() { + int abort; + + abort = 0; + GXCopyDisp(DemoCurrentBuffer, 1); + GXSetDrawSync(0xB00B); + FrameCount = 0; + while ((GXReadDrawSync() != 0xB00B) && (abort == 0)) { + if (FrameCount >= FrameMissThreshold) { + OSReport("---------WARNING : ABORTING FRAME----------\n"); + abort = 1; + __DEMODiagnoseHang(); + DEMOReInit(rmode); + DEMOSetGPHangMetric(1); + } + } + DEMOSwapBuffers(); +} + +void DEMOSetGPHangMetric(u8 enable) { + if (enable) { + GXSetGPMetric(0x23, 0x16); + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x2402C004); + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x23000020); + GX_WRITE_U8(0x10); + GX_WRITE_U16(0); + GX_WRITE_U16(0x1006); + GX_WRITE_U32(0x84400); + } else { + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x24000000); + GX_WRITE_U8(0x61); + GX_WRITE_U32(0x23000000); + GX_WRITE_U8(0x10); + GX_WRITE_U16(0); + GX_WRITE_U16(0x1006); + GX_WRITE_U32(0); + } +} + +static void __DEMODiagnoseHang() { + u32 xfTop0; + u32 xfBot0; + u32 suRdy0; + u32 r0Rdy0; + u32 xfTop1; + u32 xfBot1; + u32 suRdy1; + u32 r0Rdy1; + u32 xfTopD; + u32 xfBotD; + u32 suRdyD; + u32 r0RdyD; + u8 readIdle; + u8 cmdIdle; + u8 junk; + + GXReadXfRasMetric(&xfBot0, &xfTop0, &r0Rdy0, &suRdy0); + GXReadXfRasMetric(&xfBot1, &xfTop1, &r0Rdy1, &suRdy1); + xfTopD = (xfTop1 - xfTop0) == 0; + xfBotD = (xfBot1 - xfBot0) == 0; + suRdyD = (suRdy1 - suRdy0) != 0; + r0RdyD = (r0Rdy1 - r0Rdy0) != 0; + GXGetGPStatus(&junk, &junk, &readIdle, &cmdIdle, &junk); + OSReport("GP status %d%d%d%d%d%d --> ", readIdle, cmdIdle, xfTopD, xfBotD, suRdyD, r0RdyD); + if (!xfBotD && suRdyD) { + OSReport("GP hang due to XF stall bug.\n"); + return; + } + if (!xfTopD && xfBotD && suRdyD) { + OSReport("GP hang due to unterminated primitive.\n"); + return; + } + if (!cmdIdle && xfTopD && xfBotD && suRdyD) { + OSReport("GP hang due to illegal instruction.\n"); + return; + } + if (readIdle && cmdIdle && xfTopD && xfBotD && suRdyD && r0RdyD) { + OSReport("GP appears to be not hung (waiting for input).\n"); + return; + } + OSReport("GP is in unknown state.\n"); +} +#else void DEMOEnableBypassWorkaround(unsigned long timeoutFrames) { BypassWorkaround = 1; FrameMissThreshold = timeoutFrames; @@ -286,6 +468,7 @@ static void __BypassDoneRender() { } DEMOSwapBuffers(); } +#endif void DEMOReInit(struct _GXRenderModeObj * mode) { GXFifoObj tmpobj; @@ -310,6 +493,7 @@ void DEMOReInit(struct _GXRenderModeObj * mode) { OSFreeToHeap(__OSCurrHeap, tmpFifo); } +#if DOLPHIN_REVISION < 45 static void LoadMemInfo() { void * arenaHiOld; void * arenaLo; @@ -374,3 +558,4 @@ static void LoadMemInfo() { DVDClose(&fileInfo); OSDumpHeap(__OSCurrHeap); } +#endif diff --git a/src/demo/DEMOPad.c b/src/demo/DEMOPad.c index d5be90f..f52cad2 100644 --- a/src/demo/DEMOPad.c +++ b/src/demo/DEMOPad.c @@ -27,41 +27,52 @@ void DEMOPadInit(); static void DEMOPadCopy(struct PADStatus * pad, DEMODMPad *dmpad) { unsigned short dirs; - dirs = 0; - if (pad->stickX < -0x30) { - dirs |= 0x4000; - } - if (pad->stickX > 0x30) { - dirs |= 0x8000; - } - if (pad->stickY < -0x30) { - dirs |= 0x2000; - } - if (pad->stickY > 0x30) { - dirs |= 0x1000; - } - if (pad->substickX < -0x30) { - dirs |= 0x400; - } - if (pad->substickX > 0x30) { - dirs |= 0x800; - } - if (pad->substickY < -0x30) { - dirs |= 0x200; - } - if (pad->substickY > 0x30) { - dirs |= 0x100; +#if DOLPHIN_REVISION >= 45 + if (pad->err != PAD_ERR_TRANSFER) { +#endif + dirs = 0; + if (pad->stickX < -0x30) { + dirs |= 0x4000; + } + if (pad->stickX > 0x30) { + dirs |= 0x8000; + } + if (pad->stickY < -0x30) { + dirs |= 0x2000; + } + if (pad->stickY > 0x30) { + dirs |= 0x1000; + } + if (pad->substickX < -0x30) { + dirs |= 0x400; + } + if (pad->substickX > 0x30) { + dirs |= 0x800; + } + if (pad->substickY < -0x30) { + dirs |= 0x200; + } + if (pad->substickY > 0x30) { + dirs |= 0x100; + } + dmpad->dirsNew = (dirs & (dmpad->dirs ^ dirs)); + dmpad->dirsReleased = (dmpad->dirs & (dmpad->dirs ^ dirs)); + dmpad->dirs = dirs; + dmpad->buttonDown = (pad->button & (dmpad->pst.button ^ pad->button)); + dmpad->buttonUp = (dmpad->pst.button & (dmpad->pst.button ^ pad->button)); + dmpad->stickDeltaX = (pad->stickX - dmpad->pst.stickX); + dmpad->stickDeltaY = (pad->stickY - dmpad->pst.stickY); + dmpad->substickDeltaX = (pad->substickX - dmpad->pst.substickX); + dmpad->substickDeltaY = (pad->substickY - dmpad->pst.substickY); + dmpad->pst = *pad; +#if DOLPHIN_REVISION >= 45 + } else { + dmpad->dirsNew = dmpad->dirsReleased = 0; + dmpad->buttonDown = dmpad->buttonUp = 0; + dmpad->stickDeltaX = dmpad->stickDeltaY = 0; + dmpad->substickDeltaX = dmpad->substickDeltaY = 0; } - dmpad->dirsNew = (dirs & (dmpad->dirs ^ dirs)); - dmpad->dirsReleased = (dmpad->dirs & (dmpad->dirs ^ dirs)); - dmpad->dirs = dirs; - dmpad->buttonDown = (pad->button & (dmpad->pst.button ^ pad->button)); - dmpad->buttonUp = (dmpad->pst.button & (dmpad->pst.button ^ pad->button)); - dmpad->stickDeltaX = (pad->stickX - dmpad->pst.stickX); - dmpad->stickDeltaY = (pad->stickY - dmpad->pst.stickY); - dmpad->substickDeltaX = (pad->substickX - dmpad->pst.substickX); - dmpad->substickDeltaY = (pad->substickY - dmpad->pst.substickY); - dmpad->pst = *pad; +#endif } void DEMOPadRead() { @@ -78,9 +89,13 @@ void DEMOPadRead() { } else if (Pad[i].err == -1) { ResetReq |= PadChanMask[i]; } +#if DOLPHIN_REVISION < 45 if (Pad[i].err != -3) { +#endif DEMOPadCopy(&Pad[i], &DemoPad[i]); +#if DOLPHIN_REVISION < 45 } +#endif } if (ResetReq != 0) { PADReset(ResetReq); diff --git a/src/demo/DEMOPuts.c b/src/demo/DEMOPuts.c index 3d5de56..b50cde5 100644 --- a/src/demo/DEMOPuts.c +++ b/src/demo/DEMOPuts.c @@ -44,13 +44,24 @@ void DEMOLoadFont(enum _GXTexMapID texMap, enum _GXTexMtx texMtx, DMTexFlt texFl width = 64; height = 0x1800 / width; GXInitTexObj(&fontTexObj,(void*)DEMOFontBitmap, width, (u16)height, 0, 0, 0, 0); +#if DOLPHIN_REVISION < 45 fontShift = 1; +#endif if (texFlt == 0) { GXInitTexObjLOD(&fontTexObj, 0, 0, 0, 0, 0, 0.0f, 0.0f, 0.0f); fontShift = 0; } +#if DOLPHIN_REVISION >= 45 + else { + fontShift = 1; + } +#endif GXLoadTexObj(&fontTexObj, texMap); +#if DOLPHIN_REVISION >= 45 + MTXScale(fontTMtx, 1.0f / (width), 1.0f / ((u16)height), 1.0f); +#else MTXScale(fontTMtx, 1.0f / (width - !fontShift), 1.0f / ((u16)height - !fontShift), 1.0f); +#endif GXLoadTexMtxImm(fontTMtx, texMtx, 1); GXSetNumTexGens(1); GXSetTexCoordGen(0, 1, 4, texMtx); @@ -60,7 +71,11 @@ void DEMOSetupScrnSpc(long width, long height, float depth) { float pMtx[4][4]; float mMtx[3][4]; +#if DOLPHIN_REVISION >= 45 // Why? + C_MTXOrtho(pMtx, 0.0f, height, 0.0f, width, 0.0f, -depth); +#else MTXOrtho(pMtx, 0.0f, height, 0.0f, width, 0.0f, -depth); +#endif GXSetProjection(pMtx, 1); MTXIdentity(mMtx); GXLoadPosMtxImm(mMtx, 0); @@ -141,6 +156,9 @@ void DEMOPrintf(s16 x, s16 y, s16 z, char * fmt, ...) { va_end(vlist); } +#undef LINE_OFFSET +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 6 : 0) + struct OSFontHeader * DEMOInitROMFont() { if (OSGetFontEncode() == 1) { FontData = OSAllocFromHeap(__OSCurrHeap, 0x120F00); @@ -148,10 +166,10 @@ struct OSFontHeader * DEMOInitROMFont() { FontData = OSAllocFromHeap(__OSCurrHeap, 0x20120); } if (!FontData) { - OSPanic(__FILE__, 0x19D, "Ins. memory to load ROM font."); + OSPanic(__FILE__, 0x19D+LINE_OFFSET, "Ins. memory to load ROM font."); } if (OSInitFont(FontData) == 0) { - OSPanic(__FILE__, 0x1A1, "ROM font is available in boot ROM ver 0.8 or later."); + OSPanic(__FILE__, 0x1A1+LINE_OFFSET, "ROM font is available in boot ROM ver 0.8 or later."); } FontSize = FontData->cellWidth * 0x10; FontSpace = -0x10; @@ -163,14 +181,36 @@ void DEMOSetROMFontSize(s16 size, s16 space) { FontSpace = space * 0x10; } +#if DOLPHIN_REVISION >= 45 +void DEMOGetROMFontSize(s16 *size, s16 *space) { + if (size) { + *size = FontSize / 16; + } + if (space) { + *space = FontSpace / 16; + } +} +#endif + static void DrawFontChar(int x, int y, int z, int xChar, int yChar) { s16 posLeft = x; +#if DOLPHIN_REVISION >= 45 + s16 posRight = posLeft + FontSize; + s16 posTop = y - (FontData->ascent * FontSize / FontData->cellWidth); + s16 posBottom = y + (FontData->descent * FontSize / FontData->cellWidth); +#else s16 posRight = posLeft + ((FontSize * FontData->cellWidth) / FontData->cellWidth); s16 posBottom = y; s16 posTop = y - ((FontData->cellHeight * ((FontData->cellHeight * FontSize) / FontData->cellWidth)) / FontData->cellHeight); +#endif s16 texLeft = xChar; +#if DOLPHIN_REVISION >= 45 + s16 texRight = xChar + FontData->cellWidth; + s16 texTop = yChar; +#else s16 texTop = yChar; s16 texRight = (xChar + FontData->cellWidth); +#endif s16 texBottom = (yChar + FontData->cellHeight); GXBegin(0x80, 0, 4); @@ -201,6 +241,9 @@ static void LoadSheet(void * image, enum _GXTexMapID texMapID) { } } +#undef LINE_OFFSET +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 28 : 0) + int DEMORFPuts(s16 x, s16 y, s16 z, char * string) { long cx; void * image; @@ -208,7 +251,7 @@ int DEMORFPuts(s16 x, s16 y, s16 z, char * string) { long yChar; long width; - ASSERTLINE(0x210, FontData); + ASSERTLINE(0x210+LINE_OFFSET, FontData); LastSheet = NULL; GXClearVtxDesc(); GXSetVtxDesc(9, 1); @@ -224,7 +267,11 @@ int DEMORFPuts(s16 x, s16 y, s16 z, char * string) { while(*string != 0) { if (*string == 0xA) { width = 0; - y += FontData->leading * 0x10; +#if DOLPHIN_REVISION >= 45 + y += FontData->leading * FontSize / FontData->cellWidth; +#else + y += FontData->leading * 16; +#endif string++; } else { string = OSGetFontTexture(string, &image, &xChar, &yChar, &cx); @@ -244,7 +291,7 @@ int DEMORFPutsEx(s16 x, s16 y, s16 z, char * string, s16 maxWidth, int length) { long width; char * end; - ASSERTLINE(0x23D, FontData); + ASSERTLINE(0x23D+LINE_OFFSET, FontData); LastSheet = NULL; GXClearVtxDesc(); GXSetVtxDesc(9, 1); @@ -262,13 +309,21 @@ int DEMORFPutsEx(s16 x, s16 y, s16 z, char * string, s16 maxWidth, int length) { while(*string && string < end) { if (*string == 0xA) { width = 0; - y += FontData->leading * 0x10; +#if DOLPHIN_REVISION >= 45 + y += FontData->leading * FontSize / FontData->cellWidth; +#else + y += FontData->leading * 16; +#endif string++; } else { string = OSGetFontTexture(string, &image, &xChar, &yChar, &cx); if (maxWidth < width + (FontSize * cx / FontData->cellWidth) + FontSpace) { width = 0; - y += FontData->leading * 0x10; +#if DOLPHIN_REVISION >= 45 + y += FontData->leading * FontSize / FontData->cellWidth; +#else + y += FontData->leading * 16; +#endif } LoadSheet(image, 0); DrawFontChar(x + width, y, z, xChar, yChar); @@ -294,7 +349,7 @@ char * DEMODumpROMFont(char * string) { int j; long width; - ASSERTLINE(0x295, FontData); + ASSERTLINE(0x295+LINE_OFFSET, FontData); if (OSGetFontEncode() == 1) { temp = (void*)((u32)FontData + 0xD3F00); @@ -313,15 +368,57 @@ char * DEMODumpROMFont(char * string) { return string; } +#undef LINE_OFFSET +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 29 : 0) + int DEMOGetRFTextWidth(char * string) { long cx; long width; - - ASSERTLINE(0x2C3, FontData); +#if DOLPHIN_REVISION >= 45 + long maxWidth; +#endif + + ASSERTLINE(0x2C3+LINE_OFFSET, FontData); +#if DOLPHIN_REVISION >= 45 + maxWidth = width = 0; +#else width = 0; +#endif while(*string != 0) { +#if DOLPHIN_REVISION >= 45 + if (*string == '\n') { + if (maxWidth < width) { + maxWidth = width; + } + width = 0; + } +#endif string = OSGetFontWidth(string, &cx); width = FontSpace + ((FontSize * cx) / FontData->cellWidth) + width; } +#if DOLPHIN_REVISION >= 45 + if (maxWidth < width) { + maxWidth = width; + } + return (maxWidth + 0xF) / 16; +#else return (width + 0xF) / 16; +#endif +} + +#if DOLPHIN_REVISION >= 45 +int DEMOGetRFTextHeight(char * string) { + long height; + + ASSERTLINE(0x304, FontData); + height = 1; + while (*string != 0) { + if (*string == '\n') { + height++; + } + string++; + } + height *= FontData->leading * FontSize / FontData->cellWidth; + return (height + 0xF) / 16; } +#endif diff --git a/src/demo/DEMOWin.c b/src/demo/DEMOWin.c index 6b3cb0b..fec3799 100644 --- a/src/demo/DEMOWin.c +++ b/src/demo/DEMOWin.c @@ -29,13 +29,15 @@ void DEMOWinInit() { GXSetCopyClear((GXColor){0, 0, 0, 0}, 0xFFFFFF); } +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 4 : 0) + struct STRUCT_DEMOWIN * DEMOWinCreateWindow(s32 x1, s32 y1, s32 x2, s32 y2, char * caption, u16 scroll, void * func) { struct STRUCT_DEMOWIN * handle; - ASSERTMSGLINE(0xB1, x1 < x2, "DEMOWIN: Illegal X coords for window\n"); - ASSERTMSGLINE(0xB2, y1 < y2, "DEMOWIN: Illegal y coords for window\n"); + ASSERTMSGLINE(0xB1+LINE_OFFSET, x1 < x2, "DEMOWIN: Illegal X coords for window\n"); + ASSERTMSGLINE(0xB2+LINE_OFFSET, y1 < y2, "DEMOWIN: Illegal y coords for window\n"); handle = (void*)OSAllocFromHeap(__OSCurrHeap, sizeof(struct STRUCT_DEMOWIN)); - ASSERTMSGLINE(0xB6, handle, "DEMOWIN: FAILED TO ALLOCATE WINDOW!\n"); + ASSERTMSGLINE(0xB6+LINE_OFFSET, handle, "DEMOWIN: FAILED TO ALLOCATE WINDOW!\n"); handle->x1 = x1; handle->y1 = y1; handle->x2 = x2; @@ -56,7 +58,7 @@ struct STRUCT_DEMOWIN * DEMOWinCreateWindow(s32 x1, s32 y1, s32 x2, s32 y2, char handle->flags = 0; handle->priority = 0; handle->buffer = (void*)OSAllocFromHeap(__OSCurrHeap, handle->total_lines * handle->char_width); - ASSERTMSGLINE(0xEE, handle->buffer, "DEMOWinCreateWindow(): Unable to allocation buffer!\n"); + ASSERTMSGLINE(0xEE+LINE_OFFSET, handle->buffer, "DEMOWinCreateWindow(): Unable to allocation buffer!\n"); memset(handle->buffer, ' ', handle->total_lines * handle->char_width); // set to all empty spaces DEMOWinSetWindowColor(handle, 3, 0, 0, 0, 0); handle->cursor_line = -1; @@ -68,7 +70,7 @@ struct STRUCT_DEMOWIN * DEMOWinCreateWindow(s32 x1, s32 y1, s32 x2, s32 y2, char void DEMOWinDestroyWindow(struct STRUCT_DEMOWIN * handle) { int old; - ASSERTMSGLINE(0x114, handle, "DEMOWinDestroyWindow(): NULL handle!\n"); + ASSERTMSGLINE(0x114+LINE_OFFSET, handle, "DEMOWinDestroyWindow(): NULL handle!\n"); old = OSDisableInterrupts(); __DEMOWin_delete_node(handle); OSFreeToHeap(__OSCurrHeap, handle->buffer); @@ -77,17 +79,17 @@ void DEMOWinDestroyWindow(struct STRUCT_DEMOWIN * handle) { } void DEMOWinOpenWindow(struct STRUCT_DEMOWIN * handle) { - ASSERTMSGLINE(0x136, handle, "DEMOWinOpenWindow(): NULL handle!\n"); + ASSERTMSGLINE(0x136+LINE_OFFSET, handle, "DEMOWinOpenWindow(): NULL handle!\n"); handle->flags |= DEMOWIN_FLAGS_OPENED; } void DEMOWinCloseWindow(struct STRUCT_DEMOWIN * handle) { - ASSERTMSGLINE(0x146, handle, "DEMOWinCloseWindow(): NULL handle!\n"); + ASSERTMSGLINE(0x146+LINE_OFFSET, handle, "DEMOWinCloseWindow(): NULL handle!\n"); handle->flags &= ~(DEMOWIN_FLAGS_OPENED); } void DEMOWinSetWindowColor(struct STRUCT_DEMOWIN * handle, enum DEMOWinItem item, u8 r, u8 g, u8 b, u8 a) { - ASSERTMSGLINE(0x158, handle, "DEMOWinSetWinColor(): NULL window handle\n"); + ASSERTMSGLINE(0x158+LINE_OFFSET, handle, "DEMOWinSetWinColor(): NULL window handle\n"); switch(item) { case DEMOWIN_ITEM_CAP: // set cap handle->cap.r = r; @@ -125,7 +127,7 @@ void DEMOWinSetWindowColor(struct STRUCT_DEMOWIN * handle, enum DEMOWinItem item handle->border.a = 255; return; default: - ASSERTMSGLINE(0x183, FALSE, "DEMOWinSetWinColor(): Unknown item\n"); + ASSERTMSGLINE(0x183+LINE_OFFSET, FALSE, "DEMOWinSetWinColor(): Unknown item\n"); return; } } @@ -196,8 +198,8 @@ void DEMOWinScrollWindow(struct STRUCT_DEMOWIN * handle, u32 dir) { u16 n; u16 v_start; - ASSERTMSGLINE(0x21B, handle, "DEMOWinScrollWindow(): NULL handle!\n"); - ASSERTMSGLINE(0x21C, handle->num_scroll_lines, "DEMOWinScrollWindow(): No scrollback buffer!\n"); + ASSERTMSGLINE(0x21B+LINE_OFFSET, handle, "DEMOWinScrollWindow(): NULL handle!\n"); + ASSERTMSGLINE(0x21C+LINE_OFFSET, handle->num_scroll_lines, "DEMOWinScrollWindow(): No scrollback buffer!\n"); switch(dir) { case 1: @@ -222,7 +224,7 @@ void DEMOWinScrollWindow(struct STRUCT_DEMOWIN * handle, u32 dir) { OSRestoreInterrupts(old); return; default: - ASSERTMSGLINE(0x23F, FALSE, "DEMOWinScrollWindow(): Unknown token\n"); + ASSERTMSGLINE(0x23F+LINE_OFFSET, FALSE, "DEMOWinScrollWindow(): Unknown token\n"); return; } } @@ -230,8 +232,8 @@ void DEMOWinScrollWindow(struct STRUCT_DEMOWIN * handle, u32 dir) { void DEMOWinBringToFront(struct STRUCT_DEMOWIN * handle) { struct STRUCT_DEMOWIN * ptr; - ASSERTMSGLINE(0x256, __first_node, "DEMOWinBringToFront(): Window list is empty!\n"); - ASSERTMSGLINE(0x257, handle, "DEMOWinBringToFront(): NULL handle!\n"); + ASSERTMSGLINE(0x256+LINE_OFFSET, __first_node, "DEMOWinBringToFront(): Window list is empty!\n"); + ASSERTMSGLINE(0x257+LINE_OFFSET, handle, "DEMOWinBringToFront(): NULL handle!\n"); if (handle->priority) { for(ptr = __first_node; ptr; ptr = ptr->next) { ptr->priority = 1; @@ -241,7 +243,7 @@ void DEMOWinBringToFront(struct STRUCT_DEMOWIN * handle) { } void DEMOWinSendToBack(struct STRUCT_DEMOWIN * handle) { - ASSERTMSGLINE(0x27A, handle, "DEMOWinSendToBack(): NULL handle!\n"); + ASSERTMSGLINE(0x27A+LINE_OFFSET, handle, "DEMOWinSendToBack(): NULL handle!\n"); handle->priority = 1; } @@ -251,7 +253,7 @@ void DEMOWinClearRow(struct STRUCT_DEMOWIN * handle, u16 row) { u16 i; int old; - ASSERTMSGLINE(0x292, handle, "DEMOWinClearRow(): NULL handle!\n"); + ASSERTMSGLINE(0x292+LINE_OFFSET, handle, "DEMOWinClearRow(): NULL handle!\n"); if (row < handle->char_height) { old = OSDisableInterrupts(); buffer_row = (((handle->curr_view_line + handle->total_lines) - (handle->char_height - 1)) % handle->total_lines); @@ -270,7 +272,7 @@ void DEMOWinClearWindow(struct STRUCT_DEMOWIN * handle) { u16 i; int old; - ASSERTMSGLINE(0x2C3, handle, "DEMOWinClearWindow(): NULL handle!\n"); + ASSERTMSGLINE(0x2C3+LINE_OFFSET, handle, "DEMOWinClearWindow(): NULL handle!\n"); old = OSDisableInterrupts(); buffer_row = ((handle->curr_view_line + handle->total_lines) - (handle->char_height - 1)) % handle->total_lines; @@ -285,7 +287,7 @@ void DEMOWinClearWindow(struct STRUCT_DEMOWIN * handle) { void DEMOWinClearBuffer(struct STRUCT_DEMOWIN * handle) { int old; - ASSERTMSGLINE(0x2E5, handle, "DEMOWinClearBuffer(): NULL handle!\n"); + ASSERTMSGLINE(0x2E5+LINE_OFFSET, handle, "DEMOWinClearBuffer(): NULL handle!\n"); old = OSDisableInterrupts(); memset(handle->buffer, ' ', handle->total_lines * handle->char_width); OSRestoreInterrupts(old); @@ -299,7 +301,7 @@ void DEMOWinRefresh() { unsigned short y; int old; - ASSERTMSGLINE(0x30D, __first_node, "DEMOWinRefresh(): Windowlist is empty!\n"); + ASSERTMSGLINE(0x30D+LINE_OFFSET, __first_node, "DEMOWinRefresh(): Windowlist is empty!\n"); for(ptr = __first_node; ptr; ptr = ptr->next) { if (ptr->flags & DEMOWIN_FLAGS_OPENED) { GXSetZMode(1, 3, 1); @@ -444,7 +446,7 @@ void DEMOWinRefresh() { static void __DEMOWin_add_node(struct STRUCT_DEMOWIN * handle) { - ASSERTMSGLINE(0x3FD, handle, "__add_node(): you're adding a NULL node!\n"); + ASSERTMSGLINE(0x3FD+LINE_OFFSET, handle, "__add_node(): you're adding a NULL node!\n"); // WHY. why it backwards. who writes like this? if (NULL == __last_node) { @@ -453,7 +455,7 @@ static void __DEMOWin_add_node(struct STRUCT_DEMOWIN * handle) { __first_node = handle; handle->next = 0; handle->prev = 0; - ASSERTMSGLINE(0x407, __first_node, " > __first_node: NULL HANDLE!\n"); + ASSERTMSGLINE(0x407+LINE_OFFSET, __first_node, " > __first_node: NULL HANDLE!\n"); } else { __last_node->next = handle; handle->next = 0; @@ -465,7 +467,7 @@ static void __DEMOWin_add_node(struct STRUCT_DEMOWIN * handle) { static void __DEMOWin_delete_node(struct STRUCT_DEMOWIN * handle) { static unsigned short old; - ASSERTMSGLINE(0x424, handle, "__delete_node(): you're deleting a NULL node!\n"); + ASSERTMSGLINE(0x424+LINE_OFFSET, handle, "__delete_node(): you're deleting a NULL node!\n"); if (__first_node == handle) { if (handle->next) { @@ -550,6 +552,9 @@ void DEMOWinDestroyMenuWindow(struct STRUCT_MENU * menu) { if (menu->handle) { DEMOWinCloseWindow(menu->handle); DEMOWinDestroyWindow(menu->handle); +#if DOLPHIN_REVISION >= 45 + menu->handle = NULL; +#endif } } @@ -811,10 +816,13 @@ void DEMOWinResetRepeat() { __DEMOWIN_PAD_repeat_rate = 2; } +#undef LINE_OFFSET +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 6 : 0) + struct STRUCT_LISTBOX * DEMOWinCreateListWindow(struct STRUCT_LISTBOX * list, unsigned short x, unsigned short y) { struct STRUCT_LISTBOX_ITEM * ptr; - ASSERTMSGLINE(0x72A, list, "DEMOWinCreateListWindow(): List is NULL!\n"); + ASSERTMSGLINE(0x72A+LINE_OFFSET, list, "DEMOWinCreateListWindow(): List is NULL!\n"); ptr = list->items; list->max_str_len = strlen(list->title); list->num_items = 0; @@ -842,6 +850,9 @@ void DEMOWinDestroyListWindow(struct STRUCT_LISTBOX * list) { if (list->handle) { DEMOWinCloseWindow(list->handle); DEMOWinDestroyWindow(list->handle); +#if DOLPHIN_REVISION >= 45 + list->handle = NULL; +#endif } } @@ -880,8 +891,11 @@ void DEMOWinListSetCursor(struct STRUCT_LISTBOX * list, int x) { list->cursor_state = x; } +#undef LINE_OFFSET +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 8 : 0) + long DEMOWinListScrollList(struct STRUCT_LISTBOX * list, unsigned long dir) { - ASSERTMSGLINE(0x7E2, list, "DEMOWinListScrollList(): NULL handle!\n"); + ASSERTMSGLINE(0x7E2+LINE_OFFSET, list, "DEMOWinListScrollList(): NULL handle!\n"); switch(dir) { case 1: if (list->display_pos) { @@ -897,7 +911,7 @@ long DEMOWinListScrollList(struct STRUCT_LISTBOX * list, unsigned long dir) { list->display_pos = 0; break; default: - ASSERTMSGLINE(0x7FB, FALSE, "DEMOWinListScrollList(): Invalid dimension!\n"); + ASSERTMSGLINE(0x7FB+LINE_OFFSET, FALSE, "DEMOWinListScrollList(): Invalid dimension!\n"); break; } if (list->curr_pos > (list->display_pos + list->num_display_items - 1)) { @@ -909,7 +923,7 @@ long DEMOWinListScrollList(struct STRUCT_LISTBOX * list, unsigned long dir) { } long DEMOWinListMoveCursor(struct STRUCT_LISTBOX * list, unsigned long dir) { - ASSERTMSGLINE(0x81E, list, "DEMOWinListScrollList(): NULL handle!\n"); + ASSERTMSGLINE(0x81E+LINE_OFFSET, list, "DEMOWinListScrollList(): NULL handle!\n"); switch(dir) { case 1: list->curr_pos = (list->curr_pos + list->num_items - 1) % list->num_items; @@ -918,7 +932,7 @@ long DEMOWinListMoveCursor(struct STRUCT_LISTBOX * list, unsigned long dir) { list->curr_pos = (list->curr_pos + 1) % list->num_items; break; default: - ASSERTMSGLINE(0x82B, FALSE, "DEMOWinListMoveCursor(): Invalid dimension!\n"); + ASSERTMSGLINE(0x82B+LINE_OFFSET, FALSE, "DEMOWinListMoveCursor(): Invalid dimension!\n"); break; } return list->curr_pos; diff --git a/src/dtk/dtk.c b/src/dtk/dtk.c index 13f738e..b8dc6bb 100644 --- a/src/dtk/dtk.c +++ b/src/dtk/dtk.c @@ -17,6 +17,7 @@ static volatile u8 __DTKVolumeR; static volatile u32 __DTKShutdownFlag; static volatile u32 __DTKTrackEnded; static DTKFlushCallback __DTKFlushCallback; +static BOOL __busy_for_ais_address; static DVDCommandBlock __block_for_run_callback; static DVDCommandBlock __block_for_prep_callback; @@ -44,9 +45,11 @@ static void __DTKStopAi(void) AISetStreamPlayState(0); } +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 3 : 0) + static void __DTKCheckUserCallback(struct DTKTrack *track, u32 event) { - ASSERTLINE(0x53, track); + ASSERTLINE(0x53+LINE_OFFSET, track); if (track && track->callback && (track->eventMask & event)) { track->callback(track->eventMask & event); } @@ -107,6 +110,9 @@ static void __DTKPrepareCurrentTrackPaused(void) static void __DTKCallbackForPlaylist(s32 result, DVDCommandBlock *block) { __DTKPosition = result; +#if DOLPHIN_REVISION >= 45 + __busy_for_ais_address = 0; +#endif if (__DTKTrackEnded) { __DTKTrackEnded = 0; __DTKCheckUserCallback(__DTKCurrentTrack, 16); @@ -154,6 +160,12 @@ static void __DTKCallbackForAIInterrupt(u32 count) { AISetStreamTrigger(count + __DTKInterruptFrequency); if (__DTKCurrentTrack) { +#if DOLPHIN_REVISION >= 45 + if (__busy_for_ais_address) { + return; + } + __busy_for_ais_address = TRUE; +#endif DVDGetStreamPlayAddrAsync(&__block_for_ais_isr, __DTKCallbackForPlaylist); } } 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/gx/GXAttr.c b/src/gx/GXAttr.c index 1cde475..6cf9d32 100644 --- a/src/gx/GXAttr.c +++ b/src/gx/GXAttr.c @@ -34,56 +34,86 @@ static void __GXXfVtxSpecs(void) nTex += GET_REG_FIELD(gx->vcdHi, 2, 14) ? 1 : 0; reg = (nCols) | (nNrm << 2) | (nTex << 4); GX_WRITE_XF_REG(8, reg); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 1; +#else gx->bpSent = 0; +#endif } +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 6 : 0) + static inline void SETVCDATTR(GXAttr Attr, GXAttrType Type) { switch (Attr) { - case GX_VA_PNMTXIDX: SET_REG_FIELD(0xA8, gx->vcdLo, 1, 0, Type); break; - case GX_VA_TEX0MTXIDX: SET_REG_FIELD(0xA9, gx->vcdLo, 1, 1, Type); break; - case GX_VA_TEX1MTXIDX: SET_REG_FIELD(0xAA, gx->vcdLo, 1, 2, Type); break; - case GX_VA_TEX2MTXIDX: SET_REG_FIELD(0xAB, gx->vcdLo, 1, 3, Type); break; - case GX_VA_TEX3MTXIDX: SET_REG_FIELD(0xAC, gx->vcdLo, 1, 4, Type); break; - case GX_VA_TEX4MTXIDX: SET_REG_FIELD(0xAD, gx->vcdLo, 1, 5, Type); break; - case GX_VA_TEX5MTXIDX: SET_REG_FIELD(0xAE, gx->vcdLo, 1, 6, Type); break; - case GX_VA_TEX6MTXIDX: SET_REG_FIELD(0xAf, gx->vcdLo, 1, 7, Type); break; - case GX_VA_TEX7MTXIDX: SET_REG_FIELD(0xB0, gx->vcdLo, 1, 8, Type); break; - case GX_VA_POS: SET_REG_FIELD(0xB1, gx->vcdLo, 2, 9, Type); break; + case GX_VA_PNMTXIDX: SET_REG_FIELD(0xA8+LINE_OFFSET, gx->vcdLo, 1, 0, Type); break; + case GX_VA_TEX0MTXIDX: SET_REG_FIELD(0xA9+LINE_OFFSET, gx->vcdLo, 1, 1, Type); break; + case GX_VA_TEX1MTXIDX: SET_REG_FIELD(0xAA+LINE_OFFSET, gx->vcdLo, 1, 2, Type); break; + case GX_VA_TEX2MTXIDX: SET_REG_FIELD(0xAB+LINE_OFFSET, gx->vcdLo, 1, 3, Type); break; + case GX_VA_TEX3MTXIDX: SET_REG_FIELD(0xAC+LINE_OFFSET, gx->vcdLo, 1, 4, Type); break; + case GX_VA_TEX4MTXIDX: SET_REG_FIELD(0xAD+LINE_OFFSET, gx->vcdLo, 1, 5, Type); break; + case GX_VA_TEX5MTXIDX: SET_REG_FIELD(0xAE+LINE_OFFSET, gx->vcdLo, 1, 6, Type); break; + case GX_VA_TEX6MTXIDX: SET_REG_FIELD(0xAF+LINE_OFFSET, gx->vcdLo, 1, 7, Type); break; + case GX_VA_TEX7MTXIDX: SET_REG_FIELD(0xB0+LINE_OFFSET, gx->vcdLo, 1, 8, Type); break; + case GX_VA_POS: SET_REG_FIELD(0xB1+LINE_OFFSET, gx->vcdLo, 2, 9, Type); break; case GX_VA_NRM: +#if DOLPHIN_REVISION >= 45 + if (Type != 0) { + gx->hasNrms = GX_TRUE; + gx->hasBiNrms = GX_FALSE; + gx->nrmType = Type; + } else { + gx->hasNrms = GX_FALSE; + } +#else gx->hasNrms = (Type != 0); if (Type != GX_NONE) { gx->nrmType = Type; } +#endif break; case GX_VA_NBT: +#if DOLPHIN_REVISION >= 45 + if (Type != 0) { + gx->hasBiNrms = GX_TRUE; + gx->hasNrms = GX_FALSE; + gx->nrmType = Type; + } else { + gx->hasBiNrms = GX_FALSE; + } +#else gx->hasBiNrms = (Type != 0); if (Type != GX_NONE) { gx->nrmType = Type; } +#endif break; - case GX_VA_CLR0: SET_REG_FIELD(0xBA, gx->vcdLo, 2, 13, Type); break; - case GX_VA_CLR1: SET_REG_FIELD(0xBB, gx->vcdLo, 2, 15, Type); break; - case GX_VA_TEX0: SET_REG_FIELD(0xBC, gx->vcdHi, 2, 0, Type); break; - case GX_VA_TEX1: SET_REG_FIELD(0xBD, gx->vcdHi, 2, 2, Type); break; - case GX_VA_TEX2: SET_REG_FIELD(0xBE, gx->vcdHi, 2, 4, Type); break; - case GX_VA_TEX3: SET_REG_FIELD(0xBF, gx->vcdHi, 2, 6, Type); break; - case GX_VA_TEX4: SET_REG_FIELD(0xC0, gx->vcdHi, 2, 8, Type); break; - case GX_VA_TEX5: SET_REG_FIELD(0xC1, gx->vcdHi, 2, 10, Type); break; - case GX_VA_TEX6: SET_REG_FIELD(0xC2, gx->vcdHi, 2, 12, Type); break; - case GX_VA_TEX7: SET_REG_FIELD(0xC3, gx->vcdHi, 2, 14, Type); break; + +#undef LINE_OFFSET +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 22 : 0) + + case GX_VA_CLR0: SET_REG_FIELD(0xBA+LINE_OFFSET, gx->vcdLo, 2, 13, Type); break; + case GX_VA_CLR1: SET_REG_FIELD(0xBB+LINE_OFFSET, gx->vcdLo, 2, 15, Type); break; + case GX_VA_TEX0: SET_REG_FIELD(0xBC+LINE_OFFSET, gx->vcdHi, 2, 0, Type); break; + case GX_VA_TEX1: SET_REG_FIELD(0xBD+LINE_OFFSET, gx->vcdHi, 2, 2, Type); break; + case GX_VA_TEX2: SET_REG_FIELD(0xBE+LINE_OFFSET, gx->vcdHi, 2, 4, Type); break; + case GX_VA_TEX3: SET_REG_FIELD(0xBF+LINE_OFFSET, gx->vcdHi, 2, 6, Type); break; + case GX_VA_TEX4: SET_REG_FIELD(0xC0+LINE_OFFSET, gx->vcdHi, 2, 8, Type); break; + case GX_VA_TEX5: SET_REG_FIELD(0xC1+LINE_OFFSET, gx->vcdHi, 2, 10, Type); break; + case GX_VA_TEX6: SET_REG_FIELD(0xC2+LINE_OFFSET, gx->vcdHi, 2, 12, Type); break; + case GX_VA_TEX7: SET_REG_FIELD(0xC3+LINE_OFFSET, gx->vcdHi, 2, 14, Type); break; } } void GXSetVtxDesc(GXAttr attr, GXAttrType type) { - CHECK_GXBEGIN(0xCC, "GXSetVtxDesc"); - CHECK_ATTRNAME(0xCF, attr); - CHECK_ATTRTYPE(0xD1, type); + CHECK_GXBEGIN(0xCC+LINE_OFFSET, "GXSetVtxDesc"); + CHECK_ATTRNAME(0xCF+LINE_OFFSET, attr); + CHECK_ATTRTYPE(0xD1+LINE_OFFSET, type); SETVCDATTR(attr, type); if (gx->hasNrms || gx->hasBiNrms) { - SET_REG_FIELD(0xD7, gx->vcdLo, 2, 11, gx->nrmType); + SET_REG_FIELD(0xD7+LINE_OFFSET, gx->vcdLo, 2, 11, gx->nrmType); } else { SET_REG_FIELD(0x00, gx->vcdLo, 2, 11, 0); } @@ -92,16 +122,16 @@ void GXSetVtxDesc(GXAttr attr, GXAttrType type) void GXSetVtxDescv(const GXVtxDescList *attrPtr) { - CHECK_GXBEGIN(0xF5, "GXSetVtxDescv"); - CHECK_ATTRPTR(0xF6, attrPtr); + CHECK_GXBEGIN(0xF5+LINE_OFFSET, "GXSetVtxDescv"); + CHECK_ATTRPTR(0xF6+LINE_OFFSET, attrPtr); while (attrPtr->attr != 0xFF) { - CHECK_ATTRNAME(0xFB, attrPtr->attr); - CHECK_ATTRTYPE(0xFE, attrPtr->type); + CHECK_ATTRNAME(0xFB+LINE_OFFSET, attrPtr->attr); + CHECK_ATTRTYPE(0xFE+LINE_OFFSET, attrPtr->type); SETVCDATTR(attrPtr->attr, attrPtr->type); attrPtr++; } if (gx->hasNrms || gx->hasBiNrms) { - SET_REG_FIELD(0x107, gx->vcdLo, 2, 11, gx->nrmType); + SET_REG_FIELD(0x107+LINE_OFFSET, gx->vcdLo, 2, 11, gx->nrmType); } else { SET_REG_FIELD(0x107, gx->vcdLo, 2, 11, 0); } @@ -154,8 +184,8 @@ void GXGetVtxDesc(GXAttr attr, GXAttrType *type) { u32 cpType; - CHECK_GXBEGIN(0x185, "GXGetVtxDesc"); - CHECK_ATTRNAME(0x187, attr); + CHECK_GXBEGIN(0x185+LINE_OFFSET, "GXGetVtxDesc"); + CHECK_ATTRNAME(0x187+LINE_OFFSET, attr); switch (attr) { case GX_VA_PNMTXIDX: cpType = GET_REG_FIELD(gx->vcdLo, 1, 0); break; @@ -189,8 +219,8 @@ void GXGetVtxDescv(GXVtxDescList *vcd) { GXAttr attr; - CHECK_GXBEGIN(0x1BA, "GXGetVtxDescv"); - CHECK_ATTRPTR(0x1BC, vcd); + CHECK_GXBEGIN(0x1BA+LINE_OFFSET, "GXGetVtxDescv"); + CHECK_ATTRPTR(0x1BC+LINE_OFFSET, vcd); for (attr = 0; attr < GX_VA_MAX_ATTR; attr++) { vcd[attr].attr = attr; GXGetVtxDesc(attr, &vcd[attr].type); @@ -200,7 +230,7 @@ void GXGetVtxDescv(GXVtxDescList *vcd) void GXClearVtxDesc(void) { - CHECK_GXBEGIN(0x1D3, "GXClearVtxDesc"); + CHECK_GXBEGIN(0x1D3+LINE_OFFSET, "GXClearVtxDesc"); gx->vcdLo = 0; SET_REG_FIELD(0x00, gx->vcdLo, 2, 9, 1); gx->vcdHi = 0; @@ -213,68 +243,68 @@ static inline void SETVAT(u32 *va, u32 *vb, u32 *vc, GXAttr attr, GXCompCnt cnt, { switch (attr) { case GX_VA_POS: - SET_REG_FIELD(511, *va, 1, 0, cnt); - SET_REG_FIELD(512, *va, 3, 1, type); - SET_REG_FIELD(513, *va, 5, 4, shft); + SET_REG_FIELD(511+LINE_OFFSET, *va, 1, 0, cnt); + SET_REG_FIELD(512+LINE_OFFSET, *va, 3, 1, type); + SET_REG_FIELD(513+LINE_OFFSET, *va, 5, 4, shft); break; case GX_VA_NRM: case GX_VA_NBT: - SET_REG_FIELD(521, *va, 3, 10, type); + SET_REG_FIELD(521+LINE_OFFSET, *va, 3, 10, type); if (cnt == GX_NRM_NBT3) { SET_REG_FIELD(0, *va, 1, 9, 1); SET_REG_FIELD(0, *va, 1, 31, 1); } else { - SET_REG_FIELD(527, *va, 1, 9, cnt); - SET_REG_FIELD(528, *va, 1, 31, 0); + SET_REG_FIELD(527+LINE_OFFSET, *va, 1, 9, cnt); + SET_REG_FIELD(528+LINE_OFFSET, *va, 1, 31, 0); } break; case GX_VA_CLR0: - SET_REG_FIELD(0x215, *va, 1, 13, cnt); - SET_REG_FIELD(0x216, *va, 3, 14, type); + SET_REG_FIELD(0x215+LINE_OFFSET, *va, 1, 13, cnt); + SET_REG_FIELD(0x216+LINE_OFFSET, *va, 3, 14, type); break; case GX_VA_CLR1: - SET_REG_FIELD(0x219, *va, 1, 0x11, cnt); - SET_REG_FIELD(0x21A, *va, 3, 18, type); + SET_REG_FIELD(0x219+LINE_OFFSET, *va, 1, 0x11, cnt); + SET_REG_FIELD(0x21A+LINE_OFFSET, *va, 3, 18, type); break; case GX_VA_TEX0: - SET_REG_FIELD(0x21D, *va, 1, 0x15, cnt); - SET_REG_FIELD(0x21E, *va, 3, 0x16, type); - SET_REG_FIELD(0x21F, *va, 5, 0x19, shft); + SET_REG_FIELD(0x21D+LINE_OFFSET, *va, 1, 0x15, cnt); + SET_REG_FIELD(0x21E+LINE_OFFSET, *va, 3, 0x16, type); + SET_REG_FIELD(0x21F+LINE_OFFSET, *va, 5, 0x19, shft); break; case GX_VA_TEX1: - SET_REG_FIELD(0x222, *vb, 1, 0, cnt); - SET_REG_FIELD(0x223, *vb, 3, 1, type); - SET_REG_FIELD(0x224, *vb, 5, 4, shft); + SET_REG_FIELD(0x222+LINE_OFFSET, *vb, 1, 0, cnt); + SET_REG_FIELD(0x223+LINE_OFFSET, *vb, 3, 1, type); + SET_REG_FIELD(0x224+LINE_OFFSET, *vb, 5, 4, shft); break; case GX_VA_TEX2: - SET_REG_FIELD(0x227, *vb, 1, 9, cnt); - SET_REG_FIELD(0x228, *vb, 3, 10, type); - SET_REG_FIELD(0x229, *vb, 5, 13, shft); + SET_REG_FIELD(0x227+LINE_OFFSET, *vb, 1, 9, cnt); + SET_REG_FIELD(0x228+LINE_OFFSET, *vb, 3, 10, type); + SET_REG_FIELD(0x229+LINE_OFFSET, *vb, 5, 13, shft); break; case GX_VA_TEX3: - SET_REG_FIELD(0x22C, *vb, 1, 18, cnt); - SET_REG_FIELD(0x22D, *vb, 3, 19, type); - SET_REG_FIELD(0x22E, *vb, 5, 22, shft); + SET_REG_FIELD(0x22C+LINE_OFFSET, *vb, 1, 18, cnt); + SET_REG_FIELD(0x22D+LINE_OFFSET, *vb, 3, 19, type); + SET_REG_FIELD(0x22E+LINE_OFFSET, *vb, 5, 22, shft); break; case GX_VA_TEX4: - SET_REG_FIELD(0x231, *vb, 1, 27, cnt); - SET_REG_FIELD(0x232, *vb, 3, 28, type); - SET_REG_FIELD(0x233, *vc, 5, 0, shft); + SET_REG_FIELD(0x231+LINE_OFFSET, *vb, 1, 27, cnt); + SET_REG_FIELD(0x232+LINE_OFFSET, *vb, 3, 28, type); + SET_REG_FIELD(0x233+LINE_OFFSET, *vc, 5, 0, shft); break; case GX_VA_TEX5: - SET_REG_FIELD(0x236, *vc, 1, 5, cnt); - SET_REG_FIELD(0x237, *vc, 3, 6, type); - SET_REG_FIELD(0x238, *vc, 5, 9, shft); + SET_REG_FIELD(0x236+LINE_OFFSET, *vc, 1, 5, cnt); + SET_REG_FIELD(0x237+LINE_OFFSET, *vc, 3, 6, type); + SET_REG_FIELD(0x238+LINE_OFFSET, *vc, 5, 9, shft); break; case GX_VA_TEX6: - SET_REG_FIELD(0x23B, *vc, 1, 14, cnt); - SET_REG_FIELD(0x23C, *vc, 3, 15, type); - SET_REG_FIELD(0x23D, *vc, 5, 18, shft); + SET_REG_FIELD(0x23B+LINE_OFFSET, *vc, 1, 14, cnt); + SET_REG_FIELD(0x23C+LINE_OFFSET, *vc, 3, 15, type); + SET_REG_FIELD(0x23D+LINE_OFFSET, *vc, 5, 18, shft); break; case GX_VA_TEX7: - SET_REG_FIELD(0x240, *vc, 1, 23, cnt); - SET_REG_FIELD(0x241, *vc, 3, 24, type); - SET_REG_FIELD(0x242, *vc, 5, 27, shft); + SET_REG_FIELD(0x240+LINE_OFFSET, *vc, 1, 23, cnt); + SET_REG_FIELD(0x241+LINE_OFFSET, *vc, 3, 24, type); + SET_REG_FIELD(0x242+LINE_OFFSET, *vc, 5, 27, shft); break; } } @@ -285,10 +315,10 @@ void GXSetVtxAttrFmt(GXVtxFmt vtxfmt, GXAttr attr, GXCompCnt cnt, GXCompType typ u32 *vb; u32 *vc; - CHECK_GXBEGIN(0x252, "GXSetVtxAttrFmt"); - CHECK_VTXFMT(0x253, vtxfmt); - CHECK_ATTRNAME2(0x255, attr); - CHECK_FRAC(0x256, frac); + CHECK_GXBEGIN(0x252+LINE_OFFSET, "GXSetVtxAttrFmt"); + CHECK_VTXFMT(0x253+LINE_OFFSET, vtxfmt); + CHECK_ATTRNAME2(0x255+LINE_OFFSET, attr); + CHECK_FRAC(0x256+LINE_OFFSET, frac); va = &gx->vatA[vtxfmt]; vb = &gx->vatB[vtxfmt]; vc = &gx->vatC[vtxfmt]; @@ -303,15 +333,15 @@ void GXSetVtxAttrFmtv(GXVtxFmt vtxfmt, const GXVtxAttrFmtList *list) u32 *vb; u32 *vc; - CHECK_GXBEGIN(0x27B, "GXSetVtxAttrFmtv"); - CHECK_LISTPTR(0x27C, list); - CHECK_VTXFMT(0x27D, vtxfmt); + CHECK_GXBEGIN(0x27B+LINE_OFFSET, "GXSetVtxAttrFmtv"); + CHECK_LISTPTR(0x27C+LINE_OFFSET, list); + CHECK_VTXFMT(0x27D+LINE_OFFSET, vtxfmt); va = &gx->vatA[vtxfmt]; vb = &gx->vatB[vtxfmt]; vc = &gx->vatC[vtxfmt]; while (list->attr != GX_VA_NULL) { - CHECK_ATTRNAME2(0x286, list->attr); - CHECK_FRAC(0x287, list->frac); + CHECK_ATTRNAME2(0x286+LINE_OFFSET, list->attr); + CHECK_FRAC(0x287+LINE_OFFSET, list->frac); SETVAT(va, vb, vc, list->attr, list->cnt, list->type, list->frac); list++; } @@ -339,8 +369,8 @@ void GXGetVtxAttrFmt(GXVtxFmt fmt, GXAttr attr, GXCompCnt *cnt, GXCompType *type u32 *vb; u32 *vc; - CHECK_GXBEGIN(0x2CF, "GXGetVtxAttrFmt"); - CHECK_VTXFMT(0x2D0, fmt); + CHECK_GXBEGIN(0x2CF+LINE_OFFSET, "GXGetVtxAttrFmt"); + CHECK_VTXFMT(0x2D0+LINE_OFFSET, fmt); va = &gx->vatA[fmt]; vb = &gx->vatB[fmt]; vc = &gx->vatC[fmt]; @@ -421,9 +451,9 @@ void GXGetVtxAttrFmtv(GXVtxFmt fmt, GXVtxAttrFmtList *vat) { GXAttr attr; - CHECK_GXBEGIN(0x330, "GXGetVtxAttrFmtv"); - CHECK_LISTPTR(0x331, vat); - CHECK_VTXFMT(0x332, fmt); + CHECK_GXBEGIN(0x330+LINE_OFFSET, "GXGetVtxAttrFmtv"); + CHECK_LISTPTR(0x331+LINE_OFFSET, vat); + CHECK_VTXFMT(0x332+LINE_OFFSET, fmt); for (attr = GX_VA_POS; attr < GX_VA_MAX_ATTR; attr++) { vat->attr = attr; GXGetVtxAttrFmt(fmt, attr, &vat->cnt, &vat->type, &vat->frac); @@ -439,11 +469,11 @@ void GXSetArray(GXAttr attr, const void *base_ptr, u8 stride) attr; // needed to match - CHECK_GXBEGIN(0x34F, "GXSetArray"); + CHECK_GXBEGIN(0x34F+LINE_OFFSET, "GXSetArray"); if (attr == GX_VA_NBT) { attr = GX_VA_NRM; } - CHECK_ATTRNAME3(0x352, attr); + CHECK_ATTRNAME3(0x352+LINE_OFFSET, attr); cpAttr = attr - GX_VA_POS; phyAddr = (u32)base_ptr & 0x3FFFFFFF; GX_WRITE_SOME_REG2(8, cpAttr | 0xA0, phyAddr, cpAttr - 12); @@ -452,7 +482,7 @@ void GXSetArray(GXAttr attr, const void *base_ptr, u8 stride) void GXInvalidateVtxCache(void) { - CHECK_GXBEGIN(0x368, "GXInvalidateVtxCache"); + CHECK_GXBEGIN(0x368+LINE_OFFSET, "GXInvalidateVtxCache"); GX_WRITE_U8(0x48); } @@ -464,8 +494,8 @@ void GXSetTexCoordGen2(GXTexCoordID dst_coord, GXTexGenType func, GXTexGenSrc sr u32 form; GXAttr mtxIdAttr; - CHECK_GXBEGIN(0x392, "GXSetTexCoordGen"); - ASSERTMSGLINE(0x393, dst_coord < 8, "GXSetTexCoordGen: Invalid coordinate Id"); + CHECK_GXBEGIN(0x392+LINE_OFFSET, "GXSetTexCoordGen"); + ASSERTMSGLINE(0x393+LINE_OFFSET, dst_coord < 8, "GXSetTexCoordGen: Invalid coordinate Id"); form = 0; row = 5; switch (src_param) { @@ -491,22 +521,22 @@ void GXSetTexCoordGen2(GXTexCoordID dst_coord, GXTexGenType func, GXTexGenSrc sr case GX_TG_TEXCOORD5: bumprow; break; case GX_TG_TEXCOORD6: bumprow; break; default: - ASSERTMSGLINE(0x3AF, 0, "GXSetTexCoordGen: Invalid source parameter"); + ASSERTMSGLINE(0x3AF+LINE_OFFSET, 0, "GXSetTexCoordGen: Invalid source parameter"); break; } switch (func) { case GX_TG_MTX2x4: - SET_REG_FIELD(0x3B8, reg, 1, 1, 0); - SET_REG_FIELD(0x3B9, reg, 1, 2, form); - SET_REG_FIELD(0x3BA, reg, 3, 4, 0); - SET_REG_FIELD(0x3BB, reg, 5, 7, row); + SET_REG_FIELD(0x3B8+LINE_OFFSET, reg, 1, 1, 0); + SET_REG_FIELD(0x3B9+LINE_OFFSET, reg, 1, 2, form); + SET_REG_FIELD(0x3BA+LINE_OFFSET, reg, 3, 4, 0); + SET_REG_FIELD(0x3BB+LINE_OFFSET, reg, 5, 7, row); break; case GX_TG_MTX3x4: - SET_REG_FIELD(0x3BF, reg, 1, 1, 1); - SET_REG_FIELD(0x3C0, reg, 1, 2, form); - SET_REG_FIELD(0x3C1, reg, 3, 4, 0); - SET_REG_FIELD(0x3C2, reg, 5, 7, row); + SET_REG_FIELD(0x3BF+LINE_OFFSET, reg, 1, 1, 1); + SET_REG_FIELD(0x3C0+LINE_OFFSET, reg, 1, 2, form); + SET_REG_FIELD(0x3C1+LINE_OFFSET, reg, 3, 4, 0); + SET_REG_FIELD(0x3C2+LINE_OFFSET, reg, 5, 7, row); break; case 2: case 3: @@ -516,17 +546,17 @@ void GXSetTexCoordGen2(GXTexCoordID dst_coord, GXTexGenType func, GXTexGenSrc sr case 7: case 8: case 9: - ASSERTMSGLINE(0x3CF, src_param >= 12 && src_param <= 18, "GXSetTexCoordGen: Bump source texture value is invalid"); - SET_REG_FIELD(0x3D0, reg, 1, 1, 0); - SET_REG_FIELD(0x3D1, reg, 1, 2, form); - SET_REG_FIELD(0x3D2, reg, 3, 4, 1); - SET_REG_FIELD(0x3D3, reg, 5, 7, row); - SET_REG_FIELD(0x3D4, reg, 3, 12, src_param - 12); - SET_REG_FIELD(0x3D5, reg, 3, 15, func - 2); + ASSERTMSGLINE(0x3CF+LINE_OFFSET, src_param >= 12 && src_param <= 18, "GXSetTexCoordGen: Bump source texture value is invalid"); + SET_REG_FIELD(0x3D0+LINE_OFFSET, reg, 1, 1, 0); + SET_REG_FIELD(0x3D1+LINE_OFFSET, reg, 1, 2, form); + SET_REG_FIELD(0x3D2+LINE_OFFSET, reg, 3, 4, 1); + SET_REG_FIELD(0x3D3+LINE_OFFSET, reg, 5, 7, row); + SET_REG_FIELD(0x3D4+LINE_OFFSET, reg, 3, 12, src_param - 12); + SET_REG_FIELD(0x3D5+LINE_OFFSET, reg, 3, 15, func - 2); break; case GX_TG_SRTG: - SET_REG_FIELD(0x3D9, reg, 1, 1, 0); - SET_REG_FIELD(0x3DA, reg, 1, 2, form); + SET_REG_FIELD(0x3D9+LINE_OFFSET, reg, 1, 1, 0); + SET_REG_FIELD(0x3DA+LINE_OFFSET, reg, 1, 2, form); if (src_param == GX_TG_COLOR0) { SET_REG_FIELD(0, reg, 3, 4, 2); } else { @@ -535,23 +565,23 @@ void GXSetTexCoordGen2(GXTexCoordID dst_coord, GXTexGenType func, GXTexGenSrc sr SET_REG_FIELD(0, reg, 5, 7, 2); break; default: - ASSERTMSGLINE(0x3E5, 0, "GXSetTexCoordGen: Invalid function"); + ASSERTMSGLINE(0x3E5+LINE_OFFSET, 0, "GXSetTexCoordGen: Invalid function"); break; } GX_WRITE_XF_REG(dst_coord + 0x40, reg); reg = 0; - SET_REG_FIELD(0x3F8, reg, 6, 0, pt_texmtx - 64); - SET_REG_FIELD(0x3F9, reg, 1, 8, normalize); + SET_REG_FIELD(0x3F8+LINE_OFFSET, reg, 6, 0, pt_texmtx - 64); + SET_REG_FIELD(0x3F9+LINE_OFFSET, reg, 1, 8, normalize); GX_WRITE_XF_REG(dst_coord + 0x50, reg); switch (dst_coord) { - case GX_TEXCOORD0: SET_REG_FIELD(0x402, gx->matIdxA, 6, 6, mtx); break; - case GX_TEXCOORD1: SET_REG_FIELD(0x403, gx->matIdxA, 6, 12, mtx); break; - case GX_TEXCOORD2: SET_REG_FIELD(0x404, gx->matIdxA, 6, 18, mtx); break; - case GX_TEXCOORD3: SET_REG_FIELD(0x405, gx->matIdxA, 6, 24, mtx); break; - case GX_TEXCOORD4: SET_REG_FIELD(0x406, gx->matIdxB, 6, 0, mtx); break; - case GX_TEXCOORD5: SET_REG_FIELD(0x407, gx->matIdxB, 6, 6, mtx); break; - case GX_TEXCOORD6: SET_REG_FIELD(0x408, gx->matIdxB, 6, 12, mtx); break; - default: SET_REG_FIELD(0x409, gx->matIdxB, 6, 18, mtx); break; + case GX_TEXCOORD0: SET_REG_FIELD(0x402+LINE_OFFSET, gx->matIdxA, 6, 6, mtx); break; + case GX_TEXCOORD1: SET_REG_FIELD(0x403+LINE_OFFSET, gx->matIdxA, 6, 12, mtx); break; + case GX_TEXCOORD2: SET_REG_FIELD(0x404+LINE_OFFSET, gx->matIdxA, 6, 18, mtx); break; + case GX_TEXCOORD3: SET_REG_FIELD(0x405+LINE_OFFSET, gx->matIdxA, 6, 24, mtx); break; + case GX_TEXCOORD4: SET_REG_FIELD(0x406+LINE_OFFSET, gx->matIdxB, 6, 0, mtx); break; + case GX_TEXCOORD5: SET_REG_FIELD(0x407+LINE_OFFSET, gx->matIdxB, 6, 6, mtx); break; + case GX_TEXCOORD6: SET_REG_FIELD(0x408+LINE_OFFSET, gx->matIdxB, 6, 12, mtx); break; + default: SET_REG_FIELD(0x409+LINE_OFFSET, gx->matIdxB, 6, 18, mtx); break; } mtxIdAttr = dst_coord + 1; __GXSetMatrixIndex(mtxIdAttr); @@ -559,8 +589,8 @@ void GXSetTexCoordGen2(GXTexCoordID dst_coord, GXTexGenType func, GXTexGenSrc sr void GXSetNumTexGens(u8 nTexGens) { - CHECK_GXBEGIN(0x41B, "GXSetNumTexGens"); - SET_REG_FIELD(0x41D, gx->genMode, 4, 0, nTexGens); + CHECK_GXBEGIN(0x41B+LINE_OFFSET, "GXSetNumTexGens"); + SET_REG_FIELD(0x41D+LINE_OFFSET, gx->genMode, 4, 0, nTexGens); GX_WRITE_XF_REG(0x3F, nTexGens); gx->dirtyState |= 4; } diff --git a/src/gx/GXBump.c b/src/gx/GXBump.c index 9144e49..e74d78e 100644 --- a/src/gx/GXBump.c +++ b/src/gx/GXBump.c @@ -36,7 +36,12 @@ void GXSetTevIndirect(GXTevStageID tev_stage, GXIndTexStageID ind_stage, GXIndTe SET_REG_FIELD(0x89, reg, 1, 20, add_prev); SET_REG_FIELD(0x8A, reg, 8, 24, tev_stage + 16); GX_WRITE_SOME_REG5(0x61, reg); + +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetIndTexMtx(GXIndTexMtxID mtx_id, f32 offset[2][3], s8 scale_exp) @@ -96,7 +101,11 @@ void GXSetIndTexMtx(GXIndTexMtxID mtx_id, f32 offset[2][3], s8 scale_exp) SET_REG_FIELD(0xD2, reg, 8, 24, id * 3 + 8); GX_WRITE_SOME_REG5(0x61, reg); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetIndTexCoordScale(GXIndTexStageID ind_state, GXIndTexScale scale_s, GXIndTexScale scale_t) @@ -132,7 +141,12 @@ void GXSetIndTexCoordScale(GXIndTexStageID ind_state, GXIndTexScale scale_s, GXI ASSERTMSGLINE(0x102, 0, "GXSetIndTexCoordScale: Invalid Indirect Stage Id"); break; } + +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetIndTexOrder(GXIndTexStageID ind_stage, GXTexCoordID tex_coord, GXTexMapID tex_map) @@ -165,7 +179,12 @@ void GXSetIndTexOrder(GXIndTexStageID ind_stage, GXTexCoordID tex_coord, GXTexMa } GX_WRITE_SOME_REG5(0x61, gx->iref); gx->dirtyState |= 3; + +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetNumIndStages(u8 nIndStages) @@ -327,12 +346,20 @@ void __GXUpdateBPMask(void) if ((u8)gx->bpMask != new_imask) { SET_REG_FIELD(0x26E, gx->bpMask, 8, 0, new_imask); GX_WRITE_SOME_REG5(0x61, gx->bpMask); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } } void __GXFlushTextureState(void) { GX_WRITE_SOME_REG5(0x61, gx->bpMask); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } diff --git a/src/gx/GXDisplayList.c b/src/gx/GXDisplayList.c index 41c1180..f0afd42 100644 --- a/src/gx/GXDisplayList.c +++ b/src/gx/GXDisplayList.c @@ -10,14 +10,16 @@ static struct __GXFifoObj DisplayListFifo; static volatile struct __GXFifoObj *OldCPUFifo; static struct __GXData_struct __savedGXdata; +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 3 : 0) + void GXBeginDisplayList(void *list, u32 size) { struct __GXFifoObj *CPUFifo = (struct __GXFifoObj *)GXGetCPUFifo(); - CHECK_GXBEGIN(0x7C, "GXBeginDisplayList"); - ASSERTMSGLINE(0x7D, !gx->inDispList, "GXBeginDisplayList: display list already in progress"); - ASSERTMSGLINE(0x7E, (size & 0x1F) == 0, "GXBeginDisplayList: size is not 32 byte aligned"); - ASSERTMSGLINE(0x7F, ((u32)list & 0x1F) == 0, "GXBeginDisplayList: list is not 32 byte aligned"); + CHECK_GXBEGIN(0x7C+LINE_OFFSET, "GXBeginDisplayList"); + ASSERTMSGLINE(0x7D+LINE_OFFSET, !gx->inDispList, "GXBeginDisplayList: display list already in progress"); + ASSERTMSGLINE(0x7E+LINE_OFFSET, (size & 0x1F) == 0, "GXBeginDisplayList: size is not 32 byte aligned"); + ASSERTMSGLINE(0x7F+LINE_OFFSET, ((u32)list & 0x1F) == 0, "GXBeginDisplayList: list is not 32 byte aligned"); if (gx->dirtyState != 0) { __GXSetDirtyState(); } @@ -46,15 +48,15 @@ unsigned long GXEndDisplayList(void) u8 unused[4]; // needed to match #endif - CHECK_GXBEGIN(0xB5, "GXEndDisplayList"); - ASSERTMSGLINE(0xB6, gx->inDispList == TRUE, "GXEndDisplayList: no display list in progress"); + CHECK_GXBEGIN(0xB5+LINE_OFFSET, "GXEndDisplayList"); + ASSERTMSGLINE(0xB6+LINE_OFFSET, gx->inDispList == TRUE, "GXEndDisplayList: no display list in progress"); if (gx->dirtyState != 0) { __GXSetDirtyState(); } reg = __piReg[5]; ov = (reg >> 26) & 1; __GXSaveCPUFifoAux(&DisplayListFifo); - ASSERTMSGLINE(0xC3, !ov, "GXEndDisplayList: display list commands overflowed buffer"); + ASSERTMSGLINE(0xC3+LINE_OFFSET, !ov, "GXEndDisplayList: display list commands overflowed buffer"); GXSetCPUFifo((GXFifoObj *)OldCPUFifo); if (gx->dlSaveContext != 0) { enabled = OSDisableInterrupts(); @@ -72,10 +74,10 @@ unsigned long GXEndDisplayList(void) void GXCallDisplayList(void *list, u32 nbytes) { - CHECK_GXBEGIN(0xEC, "GXCallDisplayList"); - ASSERTMSGLINE(0xED, !gx->inDispList, "GXCallDisplayList: display list already in progress"); - ASSERTMSGLINE(0xEE, (nbytes & 0x1F) == 0, "GXCallDisplayList: nbytes is not 32 byte aligned"); - ASSERTMSGLINE(0xEF, ((u32)list & 0x1F) == 0, "GXCallDisplayList: list is not 32 byte aligned"); + CHECK_GXBEGIN(0xEC+LINE_OFFSET, "GXCallDisplayList"); + ASSERTMSGLINE(0xED+LINE_OFFSET, !gx->inDispList, "GXCallDisplayList: display list already in progress"); + ASSERTMSGLINE(0xEE+LINE_OFFSET, (nbytes & 0x1F) == 0, "GXCallDisplayList: nbytes is not 32 byte aligned"); + ASSERTMSGLINE(0xEF+LINE_OFFSET, ((u32)list & 0x1F) == 0, "GXCallDisplayList: list is not 32 byte aligned"); if (gx->dirtyState != 0) { __GXSetDirtyState(); @@ -83,7 +85,11 @@ void GXCallDisplayList(void *list, u32 nbytes) #if DEBUG __GXShadowDispList(list, nbytes); #endif +#if DOLPHIN_REVISION >= 45 + if (*(u32 *)&gx->vNumNot == 0) { // checks both vNumNot and bpSentNot +#else if (*(u32 *)&gx->vNum != 0) { // checks both vNum and bpSent +#endif __GXSendFlushPrim(); } GX_WRITE_U8(0x40); diff --git a/src/gx/GXFifo.c b/src/gx/GXFifo.c index 7080283..cd1fa1d 100644 --- a/src/gx/GXFifo.c +++ b/src/gx/GXFifo.c @@ -29,6 +29,8 @@ static void __GXWriteFifoIntReset(u8 arg0, u8 arg1); static char __data_0[] = "[GXOverflowHandler]"; #endif +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 11 : 0) + static void GXOverflowHandler(s16 interrupt, OSContext *context) { #if DEBUG @@ -36,7 +38,7 @@ static void GXOverflowHandler(s16 interrupt, OSContext *context) OSReport(__data_0); } #endif - ASSERTLINE(0x15A, !GXOverflowSuspendInProgress); + ASSERTLINE(0x15A+LINE_OFFSET, !GXOverflowSuspendInProgress); __GXOverflowCount++; __GXWriteFifoIntEnable(0, 1); @@ -58,7 +60,7 @@ static void GXUnderflowHandler(s16 interrupt, OSContext *context) OSReport("[GXUnderflowHandler]"); } #endif - ASSERTLINE(0x184, GXOverflowSuspendInProgress); + ASSERTLINE(0x184+LINE_OFFSET, GXOverflowSuspendInProgress); OSResumeThread(__GXCurrentThread); GXOverflowSuspendInProgress = FALSE; @@ -99,12 +101,12 @@ void GXInitFifoBase(GXFifoObj *fifo, void *base, u32 size) { struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo; - ASSERTMSGLINE(0x1FF, realFifo != CPUFifo, "GXInitFifoBase: fifo is attached to CPU"); - ASSERTMSGLINE(0x201, realFifo != GPFifo, "GXInitFifoBase: fifo is attached to GP"); - ASSERTMSGLINE(0x203, ((u32)base & 0x1F) == 0, "GXInitFifoBase: base must be 32B aligned"); - ASSERTMSGLINE(0x205, base != NULL, "GXInitFifoBase: base pointer is NULL"); - ASSERTMSGLINE(0x207, (size & 0x1F) == 0, "GXInitFifoBase: size must be 32B aligned"); - ASSERTMSGLINE(0x209, size >= 0x10000, "GXInitFifoBase: fifo is not large enough"); + ASSERTMSGLINE(0x1FF+LINE_OFFSET, realFifo != CPUFifo, "GXInitFifoBase: fifo is attached to CPU"); + ASSERTMSGLINE(0x201+LINE_OFFSET, realFifo != GPFifo, "GXInitFifoBase: fifo is attached to GP"); + ASSERTMSGLINE(0x203+LINE_OFFSET, ((u32)base & 0x1F) == 0, "GXInitFifoBase: base must be 32B aligned"); + ASSERTMSGLINE(0x205+LINE_OFFSET, base != NULL, "GXInitFifoBase: base pointer is NULL"); + ASSERTMSGLINE(0x207+LINE_OFFSET, (size & 0x1F) == 0, "GXInitFifoBase: size must be 32B aligned"); + ASSERTMSGLINE(0x209+LINE_OFFSET, size >= 0x10000, "GXInitFifoBase: fifo is not large enough"); realFifo->base = base; realFifo->top = (u8 *)base + size - 4; @@ -119,12 +121,12 @@ void GXInitFifoPtrs(GXFifoObj *fifo, void *readPtr, void *writePtr) struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo; BOOL enabled; - ASSERTMSGLINE(0x231, realFifo != CPUFifo, "GXInitFifoPtrs: fifo is attached to CPU"); - ASSERTMSGLINE(0x233, realFifo != GPFifo, "GXInitFifoPtrs: fifo is attached to GP"); - ASSERTMSGLINE(0x235, ((u32)readPtr & 0x1F) == 0, "GXInitFifoPtrs: readPtr not 32B aligned"); - ASSERTMSGLINE(0x237, ((u32)writePtr & 0x1F) == 0, "GXInitFifoPtrs: writePtr not 32B aligned"); - ASSERTMSGLINE(0x23A, realFifo->base <= readPtr && readPtr < realFifo->top, "GXInitFifoPtrs: readPtr not in fifo range"); - ASSERTMSGLINE(0x23D, realFifo->base <= writePtr && writePtr < realFifo->top, "GXInitFifoPtrs: writePtr not in fifo range"); + ASSERTMSGLINE(0x231+LINE_OFFSET, realFifo != CPUFifo, "GXInitFifoPtrs: fifo is attached to CPU"); + ASSERTMSGLINE(0x233+LINE_OFFSET, realFifo != GPFifo, "GXInitFifoPtrs: fifo is attached to GP"); + ASSERTMSGLINE(0x235+LINE_OFFSET, ((u32)readPtr & 0x1F) == 0, "GXInitFifoPtrs: readPtr not 32B aligned"); + ASSERTMSGLINE(0x237+LINE_OFFSET, ((u32)writePtr & 0x1F) == 0, "GXInitFifoPtrs: writePtr not 32B aligned"); + ASSERTMSGLINE(0x23A+LINE_OFFSET, realFifo->base <= readPtr && readPtr < realFifo->top, "GXInitFifoPtrs: readPtr not in fifo range"); + ASSERTMSGLINE(0x23D+LINE_OFFSET, realFifo->base <= writePtr && writePtr < realFifo->top, "GXInitFifoPtrs: writePtr not in fifo range"); enabled = OSDisableInterrupts(); realFifo->rdPtr = readPtr; @@ -140,11 +142,11 @@ void GXInitFifoLimits(GXFifoObj *fifo, u32 hiWatermark, u32 loWatermark) { struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo; - ASSERTMSGLINE(0x262, realFifo != GPFifo, "GXInitFifoLimits: fifo is attached to GP"); - ASSERTMSGLINE(0x264, (hiWatermark & 0x1F) == 0, "GXInitFifoLimits: hiWatermark not 32B aligned"); - ASSERTMSGLINE(0x266, (loWatermark & 0x1F) == 0, "GXInitFifoLimits: loWatermark not 32B aligned"); - ASSERTMSGLINE(0x268, hiWatermark < realFifo->top - realFifo->base, "GXInitFifoLimits: hiWatermark too large"); - ASSERTMSGLINE(0x26A, loWatermark < hiWatermark, "GXInitFifoLimits: hiWatermark below lo watermark"); + ASSERTMSGLINE(0x262+LINE_OFFSET, realFifo != GPFifo, "GXInitFifoLimits: fifo is attached to GP"); + ASSERTMSGLINE(0x264+LINE_OFFSET, (hiWatermark & 0x1F) == 0, "GXInitFifoLimits: hiWatermark not 32B aligned"); + ASSERTMSGLINE(0x266+LINE_OFFSET, (loWatermark & 0x1F) == 0, "GXInitFifoLimits: loWatermark not 32B aligned"); + ASSERTMSGLINE(0x268+LINE_OFFSET, hiWatermark < realFifo->top - realFifo->base, "GXInitFifoLimits: hiWatermark too large"); + ASSERTMSGLINE(0x26A+LINE_OFFSET, loWatermark < hiWatermark, "GXInitFifoLimits: hiWatermark below lo watermark"); realFifo->hiWatermark = hiWatermark; realFifo->loWatermark = loWatermark; @@ -254,7 +256,7 @@ void GXSetGPFifo(GXFifoObj *fifo) void GXSaveCPUFifo(GXFifoObj *fifo) { struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo; - ASSERTMSGLINE(0x321, realFifo == CPUFifo, "GXSaveCPUFifo: fifo is not attached to CPU"); + ASSERTMSGLINE(0x321+LINE_OFFSET, realFifo == CPUFifo, "GXSaveCPUFifo: fifo is not attached to CPU"); __GXSaveCPUFifoAux(realFifo); } @@ -298,10 +300,10 @@ void GXSaveGPFifo(GXFifoObj *fifo) unsigned char readIdle; unsigned long temp; - ASSERTMSGLINE(0x36A, realFifo == GPFifo, "GXSaveGPFifo: fifo is not attached to GP"); + ASSERTMSGLINE(0x36A+LINE_OFFSET, realFifo == GPFifo, "GXSaveGPFifo: fifo is not attached to GP"); cpStatus = __cpReg[0]; readIdle = GET_REG_FIELD(cpStatus, 1, 2); - ASSERTMSGLINE(0x371, readIdle, "GXSaveGPFifo: GP is not idle"); + ASSERTMSGLINE(0x371+LINE_OFFSET, readIdle, "GXSaveGPFifo: GP is not idle"); SOME_MACRO1(realFifo); SOME_MACRO2(realFifo); @@ -344,7 +346,9 @@ void GXGetFifoPtrs(GXFifoObj *fifo, void **readPtr, void **writePtr) { struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo; +#if DOLPHIN_REVISION < 45 ASSERTMSGLINE(0x3F2, realFifo == CPUFifo || realFifo == GPFifo, "GXGetFifoPtrs: fifo is not CPU or GP fifo"); +#endif if (realFifo == CPUFifo) { realFifo->wrPtr = OSPhysicalToCached(__piReg[5] & 0xFBFFFFFF); } @@ -400,7 +404,9 @@ void GXEnableBreakPt(void *break_pt) BOOL enabled = OSDisableInterrupts(); __GXFifoReadDisable(); +#if DOLPHIN_REVISION < 45 ASSERTMSGLINE(0x44A, (u8 *)break_pt >= GPFifo->base && (u8 *)break_pt <= GPFifo->top, "GXEnableBreakPt: Break point value not in fifo range"); +#endif __cpReg[30] = (u32)break_pt; __cpReg[31] = ((u32)break_pt >> 16) & 0x3FFF; gx->cpEnable = (gx->cpEnable & 0xFFFFFFFD) | 2; @@ -428,6 +434,10 @@ void __GXFifoInit(void) __OSUnmaskInterrupts(0x4000); __GXCurrentThread = OSGetCurrentThread(); GXOverflowSuspendInProgress = FALSE; +#if DOLPHIN_REVISION >= 45 + CPUFifo = NULL; + GPFifo = NULL; +#endif } static void __GXFifoReadEnable(void) @@ -442,23 +452,26 @@ static void __GXFifoReadDisable(void) __cpReg[1] = gx->cpEnable; } +#undef LINE_OFFSET +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 18 : 0) + static void __GXFifoLink(u8 en) { - SET_REG_FIELD(0x4B0, gx->cpEnable, 1, 4, (en != 0) ? 1 : 0); + SET_REG_FIELD(0x4B0+LINE_OFFSET, gx->cpEnable, 1, 4, (en != 0) ? 1 : 0); __cpReg[1] = gx->cpEnable; } static void __GXWriteFifoIntEnable(u8 hiWatermarkEn, u8 loWatermarkEn) { - SET_REG_FIELD(0x4C6, gx->cpEnable, 1, 2, hiWatermarkEn); - SET_REG_FIELD(0x4C7, gx->cpEnable, 1, 3, loWatermarkEn); + SET_REG_FIELD(0x4C6+LINE_OFFSET, gx->cpEnable, 1, 2, hiWatermarkEn); + SET_REG_FIELD(0x4C7+LINE_OFFSET, gx->cpEnable, 1, 3, loWatermarkEn); __cpReg[1] = gx->cpEnable; } static void __GXWriteFifoIntReset(u8 hiWatermarkClr, u8 loWatermarkClr) { - SET_REG_FIELD(0x4DE, gx->cpClr, 1, 0, hiWatermarkClr); - SET_REG_FIELD(0x4DF, gx->cpClr, 1, 1, loWatermarkClr); + SET_REG_FIELD(0x4DE+LINE_OFFSET, gx->cpClr, 1, 0, hiWatermarkClr); + SET_REG_FIELD(0x4DF+LINE_OFFSET, gx->cpClr, 1, 1, loWatermarkClr); __cpReg[2] = gx->cpClr; } @@ -498,7 +511,7 @@ OSThread *GXSetCurrentGXThread(void) enabled = OSDisableInterrupts(); prev = __GXCurrentThread; - ASSERTMSGLINE(0x532, !GXOverflowSuspendInProgress, "GXSetCurrentGXThread: Two threads cannot generate GX commands at the same time!"); + ASSERTMSGLINE(0x532+LINE_OFFSET, !GXOverflowSuspendInProgress, "GXSetCurrentGXThread: Two threads cannot generate GX commands at the same time!"); __GXCurrentThread = OSGetCurrentThread(); OSRestoreInterrupts(enabled); return prev; diff --git a/src/gx/GXFrameBuf.c b/src/gx/GXFrameBuf.c index 491ae57..41eab5c 100644 --- a/src/gx/GXFrameBuf.c +++ b/src/gx/GXFrameBuf.c @@ -88,48 +88,50 @@ void GXAdjustForOverscan(GXRenderModeObj *rmin, GXRenderModeObj *rmout, u16 hor, rmout->viYOrigin = rmin->viYOrigin + ver; } +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 3 : 0) + void GXSetDispCopySrc(u16 left, u16 top, u16 wd, u16 ht) { - CHECK_GXBEGIN(0x3B9, "GXSetDispCopySrc"); + CHECK_GXBEGIN(0x3B9+LINE_OFFSET, "GXSetDispCopySrc"); gx->cpDispSrc = 0; - SET_REG_FIELD(0x3BC, gx->cpDispSrc, 10, 0, left); - SET_REG_FIELD(0x3BD, gx->cpDispSrc, 10, 10, top); - SET_REG_FIELD(0x3BE, gx->cpDispSrc, 8, 24, 0x49); + SET_REG_FIELD(0x3BC+LINE_OFFSET, gx->cpDispSrc, 10, 0, left); + SET_REG_FIELD(0x3BD+LINE_OFFSET, gx->cpDispSrc, 10, 10, top); + SET_REG_FIELD(0x3BE+LINE_OFFSET, gx->cpDispSrc, 8, 24, 0x49); gx->cpDispSize = 0; - SET_REG_FIELD(0x3C1, gx->cpDispSize, 10, 0, wd - 1); - SET_REG_FIELD(0x3C2, gx->cpDispSize, 10, 10, ht - 1); - SET_REG_FIELD(0x3C3, gx->cpDispSize, 8, 24, 0x4A); + SET_REG_FIELD(0x3C1+LINE_OFFSET, gx->cpDispSize, 10, 0, wd - 1); + SET_REG_FIELD(0x3C2+LINE_OFFSET, gx->cpDispSize, 10, 10, ht - 1); + SET_REG_FIELD(0x3C3+LINE_OFFSET, gx->cpDispSize, 8, 24, 0x4A); } void GXSetTexCopySrc(u16 left, u16 top, u16 wd, u16 ht) { - CHECK_GXBEGIN(0x3D5, "GXSetTexCopySrc"); + CHECK_GXBEGIN(0x3D5+LINE_OFFSET, "GXSetTexCopySrc"); gx->cpTexSrc = 0; - SET_REG_FIELD(0x3D8, gx->cpTexSrc, 10, 0, left); - SET_REG_FIELD(0x3D9, gx->cpTexSrc, 10, 10, top); - SET_REG_FIELD(0x3DA, gx->cpTexSrc, 8, 24, 0x49); + SET_REG_FIELD(0x3D8+LINE_OFFSET, gx->cpTexSrc, 10, 0, left); + SET_REG_FIELD(0x3D9+LINE_OFFSET, gx->cpTexSrc, 10, 10, top); + SET_REG_FIELD(0x3DA+LINE_OFFSET, gx->cpTexSrc, 8, 24, 0x49); gx->cpTexSize = 0; - SET_REG_FIELD(0x3DD, gx->cpTexSize, 10, 0, wd - 1); - SET_REG_FIELD(0x3DE, gx->cpTexSize, 10, 10, ht - 1); - SET_REG_FIELD(0x3DF, gx->cpTexSize, 8, 24, 0x4A); + SET_REG_FIELD(0x3DD+LINE_OFFSET, gx->cpTexSize, 10, 0, wd - 1); + SET_REG_FIELD(0x3DE+LINE_OFFSET, gx->cpTexSize, 10, 10, ht - 1); + SET_REG_FIELD(0x3DF+LINE_OFFSET, gx->cpTexSize, 8, 24, 0x4A); } void GXSetDispCopyDst(u16 wd, u16 ht) { u16 stride; - ASSERTMSGLINE(0x3F3, (wd & 0xF) == 0, "GXSetDispCopyDst: Width must be a multiple of 16"); - CHECK_GXBEGIN(0x3F4, "GXSetDispCopyDst"); + ASSERTMSGLINE(0x3F3+LINE_OFFSET, (wd & 0xF) == 0, "GXSetDispCopyDst: Width must be a multiple of 16"); + CHECK_GXBEGIN(0x3F4+LINE_OFFSET, "GXSetDispCopyDst"); stride = (int)wd * 2; gx->cpDispStride = 0; - SET_REG_FIELD(0x3FA, gx->cpDispStride, 10, 0, (stride >> 5) ); - SET_REG_FIELD(0x3FB, gx->cpDispStride, 8, 24, 0x4D); + SET_REG_FIELD(0x3FA+LINE_OFFSET, gx->cpDispStride, 10, 0, (stride >> 5) ); + SET_REG_FIELD(0x3FB+LINE_OFFSET, gx->cpDispStride, 8, 24, 0x4D); } void GXSetTexCopyDst(u16 wd, u16 ht, GXTexFmt fmt, GXBool mipmap) @@ -140,11 +142,11 @@ void GXSetTexCopyDst(u16 wd, u16 ht, GXTexFmt fmt, GXBool mipmap) u32 peTexFmt; u32 peTexFmtH; - CHECK_GXBEGIN(0x415, "GXSetTexCopyDst"); + CHECK_GXBEGIN(0x415+LINE_OFFSET, "GXSetTexCopyDst"); gx->cpTexZ = 0; peTexFmt = fmt & 0xF; - ASSERTMSGLINEV(0x434, peTexFmt < 13, "%s: invalid texture format", "GXSetTexCopyDst"); + ASSERTMSGLINEV(0x434+LINE_OFFSET, peTexFmt < 13, "%s: invalid texture format", "GXSetTexCopyDst"); if (fmt == GX_TF_Z16) { peTexFmt = 0xB; @@ -165,22 +167,22 @@ void GXSetTexCopyDst(u16 wd, u16 ht, GXTexFmt fmt, GXBool mipmap) gx->cpTexZ = (fmt & _GX_TF_ZTF) == _GX_TF_ZTF; peTexFmtH = (peTexFmt >> 3) & 1; !peTexFmt; - SET_REG_FIELD(0x44B, gx->cpTex, 1, 3, peTexFmtH); + SET_REG_FIELD(0x44B+LINE_OFFSET, gx->cpTex, 1, 3, peTexFmtH); peTexFmt = peTexFmt & 7; __GetImageTileCount(fmt, wd, ht, &rowTiles, &colTiles, &cmpTiles); gx->cpTexStride = 0; - SET_REG_FIELD(0x454, gx->cpTexStride, 10, 0, rowTiles * cmpTiles); - SET_REG_FIELD(0x455, gx->cpTexStride, 8, 24, 0x4D); - SET_REG_FIELD(0x456, gx->cpTex, 1, 9, mipmap); - SET_REG_FIELD(0x457, gx->cpTex, 3, 4, peTexFmt); + SET_REG_FIELD(0x454+LINE_OFFSET, gx->cpTexStride, 10, 0, rowTiles * cmpTiles); + SET_REG_FIELD(0x455+LINE_OFFSET, gx->cpTexStride, 8, 24, 0x4D); + SET_REG_FIELD(0x456+LINE_OFFSET, gx->cpTex, 1, 9, mipmap); + SET_REG_FIELD(0x457+LINE_OFFSET, gx->cpTex, 3, 4, peTexFmt); } void GXSetDispCopyFrame2Field(GXCopyMode mode) { - CHECK_GXBEGIN(0x468, "GXSetDispCopyFrame2Field"); - SET_REG_FIELD(0x469, gx->cpDisp, 2, 12, mode); - SET_REG_FIELD(0x46A, gx->cpTex, 2, 12, 0); + CHECK_GXBEGIN(0x468+LINE_OFFSET, "GXSetDispCopyFrame2Field"); + SET_REG_FIELD(0x469+LINE_OFFSET, gx->cpDisp, 2, 12, mode); + SET_REG_FIELD(0x46A+LINE_OFFSET, gx->cpTex, 2, 12, 0); } void GXSetCopyClamp(GXFBClamp clamp) @@ -188,16 +190,16 @@ void GXSetCopyClamp(GXFBClamp clamp) u8 clmpB; u8 clmpT; - CHECK_GXBEGIN(0x47D, "GXSetCopyClamp"); + CHECK_GXBEGIN(0x47D+LINE_OFFSET, "GXSetCopyClamp"); clmpT = (clamp & 1) == 1; clmpB = (clamp & 2) == 2; - SET_REG_FIELD(0x481, gx->cpDisp, 1, 0, clmpT); - SET_REG_FIELD(0x482, gx->cpDisp, 1, 1, clmpB); + SET_REG_FIELD(0x481+LINE_OFFSET, gx->cpDisp, 1, 0, clmpT); + SET_REG_FIELD(0x482+LINE_OFFSET, gx->cpDisp, 1, 1, clmpB); - SET_REG_FIELD(0x484, gx->cpTex, 1, 0, clmpT); - SET_REG_FIELD(0x485, gx->cpTex, 1, 1, clmpB); + SET_REG_FIELD(0x484+LINE_OFFSET, gx->cpTex, 1, 0, clmpT); + SET_REG_FIELD(0x485+LINE_OFFSET, gx->cpTex, 1, 1, clmpB); } u32 GXSetDispCopyYScale(f32 vscale) @@ -208,20 +210,24 @@ u32 GXSetDispCopyYScale(f32 vscale) u32 ht; u32 reg; - CHECK_GXBEGIN(0x49B, "GXSetDispCopyYScale"); + CHECK_GXBEGIN(0x49B+LINE_OFFSET, "GXSetDispCopyYScale"); - ASSERTMSGLINE(0x49D, vscale >= 1.0f, "GXSetDispCopyYScale: Vertical scale must be >= 1.0"); + ASSERTMSGLINE(0x49D+LINE_OFFSET, vscale >= 1.0f, "GXSetDispCopyYScale: Vertical scale must be >= 1.0"); iScale = (u32) (256.0f / vscale) & 0x1FF; fScale = 256.0f / (f32) iScale; enable = (iScale != 256); reg = 0; - SET_REG_FIELD(0x4A6, reg, 9, 0, iScale); - SET_REG_FIELD(0x4A7, reg, 8, 24, 0x4E); + SET_REG_FIELD(0x4A6+LINE_OFFSET, reg, 9, 0, iScale); + SET_REG_FIELD(0x4A7+LINE_OFFSET, reg, 8, 24, 0x4E); GX_WRITE_RAS_REG(reg); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; - SET_REG_FIELD(0x4AB, gx->cpDisp, 1, 10, enable); +#endif + SET_REG_FIELD(0x4AB+LINE_OFFSET, gx->cpDisp, 1, 10, enable); ht = GET_REG_FIELD(gx->cpDispSize, 10, 10) + 1; return ht * fScale; } @@ -230,26 +236,30 @@ void GXSetCopyClear(GXColor clear_clr, u32 clear_z) { u32 reg; - CHECK_GXBEGIN(0x4C4, "GXSetCopyClear"); - ASSERTMSGLINE(0x4C6, clear_z <= 0xFFFFFF, "GXSetCopyClear: Z clear value is out of range"); + CHECK_GXBEGIN(0x4C4+LINE_OFFSET, "GXSetCopyClear"); + ASSERTMSGLINE(0x4C6+LINE_OFFSET, clear_z <= 0xFFFFFF, "GXSetCopyClear: Z clear value is out of range"); reg = 0; - SET_REG_FIELD(0x4C9, reg, 8, 0, clear_clr.r); - SET_REG_FIELD(0x4CA, reg, 8, 8, clear_clr.a); - SET_REG_FIELD(0x4CB, reg, 8, 24, 0x4F); + SET_REG_FIELD(0x4C9+LINE_OFFSET, reg, 8, 0, clear_clr.r); + SET_REG_FIELD(0x4CA+LINE_OFFSET, reg, 8, 8, clear_clr.a); + SET_REG_FIELD(0x4CB+LINE_OFFSET, reg, 8, 24, 0x4F); GX_WRITE_RAS_REG(reg); reg = 0; - SET_REG_FIELD(0x4CF, reg, 8, 0, clear_clr.b); - SET_REG_FIELD(0x4D0, reg, 8, 8, clear_clr.g); - SET_REG_FIELD(0x4D1, reg, 8, 24, 0x50); + SET_REG_FIELD(0x4CF+LINE_OFFSET, reg, 8, 0, clear_clr.b); + SET_REG_FIELD(0x4D0+LINE_OFFSET, reg, 8, 8, clear_clr.g); + SET_REG_FIELD(0x4D1+LINE_OFFSET, reg, 8, 24, 0x50); GX_WRITE_RAS_REG(reg); reg = 0; - SET_REG_FIELD(0x4D5, reg, 24, 0, clear_z); - SET_REG_FIELD(0x4D6, reg, 8, 24, 0x51); + SET_REG_FIELD(0x4D5+LINE_OFFSET, reg, 24, 0, clear_z); + SET_REG_FIELD(0x4D6+LINE_OFFSET, reg, 8, 24, 0x51); GX_WRITE_RAS_REG(reg); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetCopyFilter(GXBool aa, const u8 sample_pattern[12][2], GXBool vf, const u8 vfilter[7]) { @@ -257,44 +267,44 @@ void GXSetCopyFilter(GXBool aa, const u8 sample_pattern[12][2], GXBool vf, const u32 coeff0; u32 coeff1; - CHECK_GXBEGIN(0x4F1, "GXSetCopyFilter"); + CHECK_GXBEGIN(0x4F1+LINE_OFFSET, "GXSetCopyFilter"); if (aa != 0) { msLoc[0] = 0; - SET_REG_FIELD(0x4F5, msLoc[0], 4, 0, sample_pattern[0][0]); - SET_REG_FIELD(0x4F6, msLoc[0], 4, 4, sample_pattern[0][1]); - SET_REG_FIELD(0x4F7, msLoc[0], 4, 8, sample_pattern[1][0]); - SET_REG_FIELD(0x4F8, msLoc[0], 4, 12, sample_pattern[1][1]); - SET_REG_FIELD(0x4F9, msLoc[0], 4, 16, sample_pattern[2][0]); - SET_REG_FIELD(0x4FA, msLoc[0], 4, 20, sample_pattern[2][1]); - SET_REG_FIELD(0x4FB, msLoc[0], 8, 24, 1); + SET_REG_FIELD(0x4F5+LINE_OFFSET, msLoc[0], 4, 0, sample_pattern[0][0]); + SET_REG_FIELD(0x4F6+LINE_OFFSET, msLoc[0], 4, 4, sample_pattern[0][1]); + SET_REG_FIELD(0x4F7+LINE_OFFSET, msLoc[0], 4, 8, sample_pattern[1][0]); + SET_REG_FIELD(0x4F8+LINE_OFFSET, msLoc[0], 4, 12, sample_pattern[1][1]); + SET_REG_FIELD(0x4F9+LINE_OFFSET, msLoc[0], 4, 16, sample_pattern[2][0]); + SET_REG_FIELD(0x4FA+LINE_OFFSET, msLoc[0], 4, 20, sample_pattern[2][1]); + SET_REG_FIELD(0x4FB+LINE_OFFSET, msLoc[0], 8, 24, 1); msLoc[1] = 0; - SET_REG_FIELD(0x4FE, msLoc[1], 4, 0, sample_pattern[3][0]); - SET_REG_FIELD(0x4FF, msLoc[1], 4, 4, sample_pattern[3][1]); - SET_REG_FIELD(0x500, msLoc[1], 4, 8, sample_pattern[4][0]); - SET_REG_FIELD(0x501, msLoc[1], 4, 12, sample_pattern[4][1]); - SET_REG_FIELD(0x502, msLoc[1], 4, 16, sample_pattern[5][0]); - SET_REG_FIELD(0x503, msLoc[1], 4, 20, sample_pattern[5][1]); - SET_REG_FIELD(0x504, msLoc[1], 8, 24, 2); + SET_REG_FIELD(0x4FE+LINE_OFFSET, msLoc[1], 4, 0, sample_pattern[3][0]); + SET_REG_FIELD(0x4FF+LINE_OFFSET, msLoc[1], 4, 4, sample_pattern[3][1]); + SET_REG_FIELD(0x500+LINE_OFFSET, msLoc[1], 4, 8, sample_pattern[4][0]); + SET_REG_FIELD(0x501+LINE_OFFSET, msLoc[1], 4, 12, sample_pattern[4][1]); + SET_REG_FIELD(0x502+LINE_OFFSET, msLoc[1], 4, 16, sample_pattern[5][0]); + SET_REG_FIELD(0x503+LINE_OFFSET, msLoc[1], 4, 20, sample_pattern[5][1]); + SET_REG_FIELD(0x504+LINE_OFFSET, msLoc[1], 8, 24, 2); msLoc[2] = 0; - SET_REG_FIELD(0x507, msLoc[2], 4, 0, sample_pattern[6][0]); - SET_REG_FIELD(0x508, msLoc[2], 4, 4, sample_pattern[6][1]); - SET_REG_FIELD(0x509, msLoc[2], 4, 8, sample_pattern[7][0]); - SET_REG_FIELD(0x50A, msLoc[2], 4, 12, sample_pattern[7][1]); - SET_REG_FIELD(0x50B, msLoc[2], 4, 16, sample_pattern[8][0]); - SET_REG_FIELD(0x50C, msLoc[2], 4, 20, sample_pattern[8][1]); - SET_REG_FIELD(0x50D, msLoc[2], 8, 24, 3); + SET_REG_FIELD(0x507+LINE_OFFSET, msLoc[2], 4, 0, sample_pattern[6][0]); + SET_REG_FIELD(0x508+LINE_OFFSET, msLoc[2], 4, 4, sample_pattern[6][1]); + SET_REG_FIELD(0x509+LINE_OFFSET, msLoc[2], 4, 8, sample_pattern[7][0]); + SET_REG_FIELD(0x50A+LINE_OFFSET, msLoc[2], 4, 12, sample_pattern[7][1]); + SET_REG_FIELD(0x50B+LINE_OFFSET, msLoc[2], 4, 16, sample_pattern[8][0]); + SET_REG_FIELD(0x50C+LINE_OFFSET, msLoc[2], 4, 20, sample_pattern[8][1]); + SET_REG_FIELD(0x50D+LINE_OFFSET, msLoc[2], 8, 24, 3); msLoc[3] = 0; - SET_REG_FIELD(0x510, msLoc[3], 4, 0, sample_pattern[9][0]); - SET_REG_FIELD(0x511, msLoc[3], 4, 4, sample_pattern[9][1]); - SET_REG_FIELD(0x512, msLoc[3], 4, 8, sample_pattern[10][0]); - SET_REG_FIELD(0x513, msLoc[3], 4, 12, sample_pattern[10][1]); - SET_REG_FIELD(0x514, msLoc[3], 4, 16, sample_pattern[11][0]); - SET_REG_FIELD(0x515, msLoc[3], 4, 20, sample_pattern[11][1]); - SET_REG_FIELD(0x516, msLoc[3], 8, 24, 4); + SET_REG_FIELD(0x510+LINE_OFFSET, msLoc[3], 4, 0, sample_pattern[9][0]); + SET_REG_FIELD(0x511+LINE_OFFSET, msLoc[3], 4, 4, sample_pattern[9][1]); + SET_REG_FIELD(0x512+LINE_OFFSET, msLoc[3], 4, 8, sample_pattern[10][0]); + SET_REG_FIELD(0x513+LINE_OFFSET, msLoc[3], 4, 12, sample_pattern[10][1]); + SET_REG_FIELD(0x514+LINE_OFFSET, msLoc[3], 4, 16, sample_pattern[11][0]); + SET_REG_FIELD(0x515+LINE_OFFSET, msLoc[3], 4, 20, sample_pattern[11][1]); + SET_REG_FIELD(0x516+LINE_OFFSET, msLoc[3], 8, 24, 4); } else { msLoc[0] = 0x01666666; msLoc[1] = 0x02666666; @@ -311,13 +321,13 @@ void GXSetCopyFilter(GXBool aa, const u8 sample_pattern[12][2], GXBool vf, const coeff1 = 0; SET_REG_FIELD(0, coeff1, 8, 24, 0x54); if (vf != 0) { - SET_REG_FIELD(0x52E, coeff0, 6, 0, vfilter[0]); - SET_REG_FIELD(0x52F, coeff0, 6, 6, vfilter[1]); - SET_REG_FIELD(0x530, coeff0, 6, 12, vfilter[2]); - SET_REG_FIELD(0x531, coeff0, 6, 18, vfilter[3]); - SET_REG_FIELD(0x532, coeff1, 6, 0, vfilter[4]); - SET_REG_FIELD(0x533, coeff1, 6, 6, vfilter[5]); - SET_REG_FIELD(0x534, coeff1, 6, 12, vfilter[6]); + SET_REG_FIELD(0x52E+LINE_OFFSET, coeff0, 6, 0, vfilter[0]); + SET_REG_FIELD(0x52F+LINE_OFFSET, coeff0, 6, 6, vfilter[1]); + SET_REG_FIELD(0x530+LINE_OFFSET, coeff0, 6, 12, vfilter[2]); + SET_REG_FIELD(0x531+LINE_OFFSET, coeff0, 6, 18, vfilter[3]); + SET_REG_FIELD(0x532+LINE_OFFSET, coeff1, 6, 0, vfilter[4]); + SET_REG_FIELD(0x533+LINE_OFFSET, coeff1, 6, 6, vfilter[5]); + SET_REG_FIELD(0x534+LINE_OFFSET, coeff1, 6, 12, vfilter[6]); } else { SET_REG_FIELD(0, coeff0, 6, 0, 0); SET_REG_FIELD(0, coeff0, 6, 6, 0); @@ -329,13 +339,17 @@ void GXSetCopyFilter(GXBool aa, const u8 sample_pattern[12][2], GXBool vf, const } GX_WRITE_RAS_REG(coeff0); GX_WRITE_RAS_REG(coeff1); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetDispCopyGamma(GXGamma gamma) { - CHECK_GXBEGIN(0x555, "GXSetDispCopyGamma"); - SET_REG_FIELD(0x556, gx->cpDisp, 2, 7, gamma); + CHECK_GXBEGIN(0x555+LINE_OFFSET, "GXSetDispCopyGamma"); + SET_REG_FIELD(0x556+LINE_OFFSET, gx->cpDisp, 2, 7, gamma); } #if DEBUG @@ -348,7 +362,7 @@ static void __GXVerifCopy(void *dest, u8 clear) u32 dx; u32 dy; - CHECK_GXBEGIN(0x56A, "GXCopyDisp"); + CHECK_GXBEGIN(0x56A+LINE_OFFSET, "GXCopyDisp"); clmpT = GET_REG_FIELD(gx->cpDisp, 1, 0); clmpB = (u32)GET_REG_FIELD(gx->cpDisp, 1, 1); @@ -357,22 +371,22 @@ static void __GXVerifCopy(void *dest, u8 clear) y0 = GET_REG_FIELD(gx->cpDispSrc, 10, 10); dy = GET_REG_FIELD(gx->cpDispSize, 10, 10) + 1; - ASSERTMSGLINE(0x574, clmpT || y0 != 0, "GXCopy: Have to set GX_CLAMP_TOP if source top == 0"); - ASSERTMSGLINE(0x576, clmpB || y0 + dy <= 528, "GXCopy: Have to set GX_CLAMP_BOTTOM if source bottom > 528"); - ASSERTMSGLINE(0x57B, (gx->peCtrl & 7) != 3 || clear == 0, "GXCopy: Can not do clear while pixel type is Z"); + ASSERTMSGLINE(0x574+LINE_OFFSET, clmpT || y0 != 0, "GXCopy: Have to set GX_CLAMP_TOP if source top == 0"); + ASSERTMSGLINE(0x576+LINE_OFFSET, clmpB || y0 + dy <= 528, "GXCopy: Have to set GX_CLAMP_BOTTOM if source bottom > 528"); + ASSERTMSGLINE(0x57B+LINE_OFFSET, (gx->peCtrl & 7) != 3 || clear == 0, "GXCopy: Can not do clear while pixel type is Z"); if ((u32) (gx->peCtrl & 7) == 5) { - ASSERTMSGLINE(0x581, clear == 0, "GXCopy: Can not clear YUV framebuffer"); - ASSERTMSGLINE(0x583, (x0 & 3) == 0, "GXCopy: Source x is not multiple of 4 for YUV copy"); - ASSERTMSGLINE(0x585, (y0 & 3) == 0, "GXCopy: Source y is not multiple of 4 for YUV copy"); - ASSERTMSGLINE(0x587, (dx & 3) == 0, "GXCopy: Source width is not multiple of 4 for YUV copy"); - ASSERTMSGLINE(0x589, (dy & 3) == 0, "GXCopy: Source height is not multiple of 4 for YUV copy"); + ASSERTMSGLINE(0x581+LINE_OFFSET, clear == 0, "GXCopy: Can not clear YUV framebuffer"); + ASSERTMSGLINE(0x583+LINE_OFFSET, (x0 & 3) == 0, "GXCopy: Source x is not multiple of 4 for YUV copy"); + ASSERTMSGLINE(0x585+LINE_OFFSET, (y0 & 3) == 0, "GXCopy: Source y is not multiple of 4 for YUV copy"); + ASSERTMSGLINE(0x587+LINE_OFFSET, (dx & 3) == 0, "GXCopy: Source width is not multiple of 4 for YUV copy"); + ASSERTMSGLINE(0x589+LINE_OFFSET, (dy & 3) == 0, "GXCopy: Source height is not multiple of 4 for YUV copy"); } else { - ASSERTMSGLINE(0x58D, (x0 & 1) == 0, "GXCopy: Source x is not multiple of 2 for RGB copy"); - ASSERTMSGLINE(0x58F, (y0 & 1) == 0, "GXCopy: Source y is not multiple of 2 for RGB copy"); - ASSERTMSGLINE(0x591, (dx & 1) == 0, "GXCopy: Source width is not multiple of 2 for RGB copy"); - ASSERTMSGLINE(0x593, (dy & 1) == 0, "GXCopy: Source height is not multiple of 2 for RGB copy"); + ASSERTMSGLINE(0x58D+LINE_OFFSET, (x0 & 1) == 0, "GXCopy: Source x is not multiple of 2 for RGB copy"); + ASSERTMSGLINE(0x58F+LINE_OFFSET, (y0 & 1) == 0, "GXCopy: Source y is not multiple of 2 for RGB copy"); + ASSERTMSGLINE(0x591+LINE_OFFSET, (dx & 1) == 0, "GXCopy: Source width is not multiple of 2 for RGB copy"); + ASSERTMSGLINE(0x593+LINE_OFFSET, (dy & 1) == 0, "GXCopy: Source height is not multiple of 2 for RGB copy"); } - ASSERTMSGLINE(0x597, ((u32)dest & 0x1F) == 0, "GXCopy: Display destination address not 32B aligned"); + ASSERTMSGLINE(0x597+LINE_OFFSET, ((u32)dest & 0x1F) == 0, "GXCopy: Display destination address not 32B aligned"); } #endif @@ -383,7 +397,7 @@ void GXCopyDisp(void *dest, GXBool clear) u32 phyAddr; u8 changePeCtrl; - CHECK_GXBEGIN(0x5B1, "GXCopyDisp"); + CHECK_GXBEGIN(0x5B1+LINE_OFFSET, "GXCopyDisp"); #if DEBUG __GXVerifCopy(dest, clear); @@ -413,13 +427,13 @@ void GXCopyDisp(void *dest, GXBool clear) phyAddr = (u32)dest & 0x3FFFFFFF; reg = 0; - SET_REG_FIELD(0x5D8, reg, 21, 0, phyAddr >> 5); - SET_REG_FIELD(0x5D9, reg, 8, 24, 0x4B); + SET_REG_FIELD(0x5D8+LINE_OFFSET, reg, 21, 0, phyAddr >> 5); + SET_REG_FIELD(0x5D9+LINE_OFFSET, reg, 8, 24, 0x4B); GX_WRITE_RAS_REG(reg); - SET_REG_FIELD(0x5DC, gx->cpDisp, 1, 11, clear); - SET_REG_FIELD(0x5DD, gx->cpDisp, 1, 14, 1); - SET_REG_FIELD(0x5DE, gx->cpDisp, 8, 24, 0x52); + SET_REG_FIELD(0x5DC+LINE_OFFSET, gx->cpDisp, 1, 11, clear); + SET_REG_FIELD(0x5DD+LINE_OFFSET, gx->cpDisp, 1, 14, 1); + SET_REG_FIELD(0x5DE+LINE_OFFSET, gx->cpDisp, 8, 24, 0x52); GX_WRITE_RAS_REG(gx->cpDisp); if (clear) { @@ -429,7 +443,11 @@ void GXCopyDisp(void *dest, GXBool clear) if (changePeCtrl) { GX_WRITE_RAS_REG(gx->peCtrl); } +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXCopyTex(void *dest, GXBool clear) @@ -439,7 +457,7 @@ void GXCopyTex(void *dest, GXBool clear) u32 phyAddr; u8 changePeCtrl; - CHECK_GXBEGIN(0x604, "GXCopyTex"); + CHECK_GXBEGIN(0x604+LINE_OFFSET, "GXCopyTex"); #if DEBUG __GXVerifCopy(dest, clear); @@ -474,13 +492,13 @@ void GXCopyTex(void *dest, GXBool clear) phyAddr = (u32)dest & 0x3FFFFFFF; reg = 0; - SET_REG_FIELD(0x635, reg, 21, 0, phyAddr >> 5); - SET_REG_FIELD(0x636, reg, 8, 24, 0x4B); + SET_REG_FIELD(0x635+LINE_OFFSET, reg, 21, 0, phyAddr >> 5); + SET_REG_FIELD(0x636+LINE_OFFSET, reg, 8, 24, 0x4B); GX_WRITE_RAS_REG(reg); - SET_REG_FIELD(0x639, gx->cpTex, 1, 11, clear); - SET_REG_FIELD(0x63A, gx->cpTex, 1, 14, 0); - SET_REG_FIELD(0x63B, gx->cpTex, 8, 24, 0x52); + SET_REG_FIELD(0x639+LINE_OFFSET, gx->cpTex, 1, 11, clear); + SET_REG_FIELD(0x63A+LINE_OFFSET, gx->cpTex, 1, 14, 0); + SET_REG_FIELD(0x63B+LINE_OFFSET, gx->cpTex, 8, 24, 0x52); GX_WRITE_RAS_REG(gx->cpTex); if (clear != 0) { @@ -490,24 +508,34 @@ void GXCopyTex(void *dest, GXBool clear) if (changePeCtrl) { GX_WRITE_RAS_REG(gx->peCtrl); } +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXClearBoundingBox(void) { u32 reg; - CHECK_GXBEGIN(0x65B, "GXClearBoundingBox"); + CHECK_GXBEGIN(0x65B+LINE_OFFSET, "GXClearBoundingBox"); reg = 0x550003FF; GX_WRITE_RAS_REG(reg); reg = 0x560003FF; GX_WRITE_RAS_REG(reg); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXReadBoundingBox(u16 *left, u16 *top, u16 *right, u16 *bottom) { - CHECK_GXBEGIN(0x671, "GXReadBoundingBox"); +#if DOLPHIN_REVISION < 45 + CHECK_GXBEGIN(0x671+LINE_OFFSET, "GXReadBoundingBox"); +#endif *left = __peReg[8]; *top = __peReg[10]; *right = __peReg[9]; diff --git a/src/gx/GXGeometry.c b/src/gx/GXGeometry.c index 9de9121..31780d4 100644 --- a/src/gx/GXGeometry.c +++ b/src/gx/GXGeometry.c @@ -25,10 +25,12 @@ void __GXSetDirtyState(void) gx->dirtyState = 0; } +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 3 : 0) + void GXBegin(GXPrimitive type, GXVtxFmt vtxfmt, u16 nverts) { - ASSERTMSGLINE(0x157, vtxfmt < 8, "GXBegin: Format Index is out of range"); - ASSERTMSGLINE(0x158, !__GXinBegin, "GXBegin: called inside another GXBegin/GXEnd"); + ASSERTMSGLINE(0x157+LINE_OFFSET, vtxfmt < 8, "GXBegin: Format Index is out of range"); + ASSERTMSGLINE(0x158+LINE_OFFSET, !__GXinBegin, "GXBegin: called inside another GXBegin/GXEnd"); if (gx->dirtyState != 0) { __GXSetDirtyState(); @@ -39,7 +41,11 @@ void GXBegin(GXPrimitive type, GXVtxFmt vtxfmt, u16 nverts) } __GXinBegin = 1; #endif +#if DOLPHIN_REVISION >= 45 + if (*(u32 *)&gx->vNumNot == 0) { // checks both vNumNot and bpSentNot +#else if (*(u32 *)&gx->vNum != 0) { // checks both vNum and bpSent +#endif __GXSendFlushPrim(); } GX_WRITE_U8(vtxfmt | type); @@ -56,21 +62,29 @@ void __GXSendFlushPrim(void) for (i = 0; i < numD; i += 4) { GX_WRITE_U32(0); } +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 1; +#else gx->bpSent = 0; +#endif } void GXSetLineWidth(u8 width, GXTexOffset texOffsets) { - CHECK_GXBEGIN(0x1A8, "GXSetLineWidth"); - SET_REG_FIELD(0x1A9, gx->lpSize, 8, 0, width); - SET_REG_FIELD(0x1AA, gx->lpSize, 3, 16, texOffsets); + CHECK_GXBEGIN(0x1A8+LINE_OFFSET, "GXSetLineWidth"); + SET_REG_FIELD(0x1A9+LINE_OFFSET, gx->lpSize, 8, 0, width); + SET_REG_FIELD(0x1AA+LINE_OFFSET, gx->lpSize, 3, 16, texOffsets); GX_WRITE_RAS_REG(gx->lpSize); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXGetLineWidth(u8 *width, GXTexOffset *texOffsets) { - ASSERTMSGLINE(0x1BF, width != NULL && texOffsets != NULL, "GXGet*: invalid null pointer"); + ASSERTMSGLINE(0x1BF+LINE_OFFSET, width != NULL && texOffsets != NULL, "GXGet*: invalid null pointer"); *width = GET_REG_FIELD(gx->lpSize, 8, 0); *texOffsets = GET_REG_FIELD(gx->lpSize, 3, 16); @@ -78,16 +92,20 @@ void GXGetLineWidth(u8 *width, GXTexOffset *texOffsets) void GXSetPointSize(u8 pointSize, GXTexOffset texOffsets) { - CHECK_GXBEGIN(0x1D4, "GXSetPointSize"); - SET_REG_FIELD(0x1D5, gx->lpSize, 8, 8, pointSize); - SET_REG_FIELD(0x1D6, gx->lpSize, 3, 19, texOffsets); + CHECK_GXBEGIN(0x1D4+LINE_OFFSET, "GXSetPointSize"); + SET_REG_FIELD(0x1D5+LINE_OFFSET, gx->lpSize, 8, 8, pointSize); + SET_REG_FIELD(0x1D6+LINE_OFFSET, gx->lpSize, 3, 19, texOffsets); GX_WRITE_RAS_REG(gx->lpSize); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXGetPointSize(u8 *pointSize, GXTexOffset *texOffsets) { - ASSERTMSGLINE(0x1EB, pointSize != NULL && texOffsets != NULL, "GXGet*: invalid null pointer"); + ASSERTMSGLINE(0x1EB+LINE_OFFSET, pointSize != NULL && texOffsets != NULL, "GXGet*: invalid null pointer"); *pointSize = (int)GET_REG_FIELD(gx->lpSize, 8, 8); *texOffsets = GET_REG_FIELD(gx->lpSize, 3, 19); @@ -95,27 +113,31 @@ void GXGetPointSize(u8 *pointSize, GXTexOffset *texOffsets) void GXEnableTexOffsets(GXTexCoordID coord, u8 line_enable, u8 point_enable) { - CHECK_GXBEGIN(0x201, "GXEnableTexOffsets"); + CHECK_GXBEGIN(0x201+LINE_OFFSET, "GXEnableTexOffsets"); - ASSERTMSGLINE(0x203, coord < 8, "GXEnableTexOffsets: Invalid coordinate Id"); + ASSERTMSGLINE(0x203+LINE_OFFSET, coord < 8, "GXEnableTexOffsets: Invalid coordinate Id"); - SET_REG_FIELD(0x205, gx->suTs0[coord], 1, 18, line_enable); - SET_REG_FIELD(0x206, gx->suTs0[coord], 1, 19, point_enable); + SET_REG_FIELD(0x205+LINE_OFFSET, gx->suTs0[coord], 1, 18, line_enable); + SET_REG_FIELD(0x206+LINE_OFFSET, gx->suTs0[coord], 1, 19, point_enable); GX_WRITE_RAS_REG(gx->suTs0[coord]); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetCullMode(GXCullMode mode) { GXCullMode hwMode; - CHECK_GXBEGIN(0x21D, "GXSetCullMode"); + CHECK_GXBEGIN(0x21D+LINE_OFFSET, "GXSetCullMode"); switch (mode) { case GX_CULL_FRONT: hwMode = GX_CULL_BACK; break; case GX_CULL_BACK: hwMode = GX_CULL_FRONT; break; default: hwMode = mode; break; } - SET_REG_FIELD(0x225, gx->genMode, 2, 14, hwMode); + SET_REG_FIELD(0x225+LINE_OFFSET, gx->genMode, 2, 14, hwMode); gx->dirtyState |= 4; } @@ -134,9 +156,9 @@ void GXSetCoPlanar(GXBool enable) { u32 reg; - CHECK_GXBEGIN(0x24A, "GXSetCoPlanar"); + CHECK_GXBEGIN(0x24A+LINE_OFFSET, "GXSetCoPlanar"); - SET_REG_FIELD(0x24C, gx->genMode, 1, 19, enable); + SET_REG_FIELD(0x24C+LINE_OFFSET, gx->genMode, 1, 19, enable); reg = 0xFE080000; GX_WRITE_RAS_REG(reg); GX_WRITE_RAS_REG(gx->genMode); @@ -145,5 +167,9 @@ void GXSetCoPlanar(GXBool enable) void __GXSetGenMode(void) { GX_WRITE_RAS_REG(gx->genMode); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } diff --git a/src/gx/GXInit.c b/src/gx/GXInit.c index ee600b4..5a1d603 100644 --- a/src/gx/GXInit.c +++ b/src/gx/GXInit.c @@ -19,6 +19,10 @@ u32 *__piReg; GXBool __GXinBegin; #endif +#if DOLPHIN_REVISION >= 45 +void __GXInitGX(void); +#endif + asm BOOL IsWriteGatherBufferEmpty(void) { sync @@ -71,13 +75,17 @@ static void __GXDefaultVerifyCallback(GXWarningLevel level, u32 id, char *msg) GXFifoObj FifoObj; +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 6 : 0) + GXFifoObj *GXInit(void *base, u32 size) { +#if DOLPHIN_REVISION < 45 GXRenderModeObj *rmode; f32 identity_mtx[3][4]; GXColor clear = {64, 64, 64, 255}; GXColor black = {0, 0, 0, 0}; GXColor white = {255, 255, 255, 255}; +#endif u32 i; u32 reg; u32 freqBase; @@ -111,18 +119,18 @@ GXFifoObj *GXInit(void *base, u32 size) gx->teva[i] = 0; gx->tref[i / 2] = 0; gx->texmapId[i] = GX_TEXMAP_NULL; - SET_REG_FIELD(0x2F2, gx->tevc[i], 8, 24, 0xC0 + i * 2); - SET_REG_FIELD(0x2F3, gx->teva[i], 8, 24, 0xC1 + i * 2); - SET_REG_FIELD(0x2F5, gx->tevKsel[i / 2], 8, 24, 0xF6 + i / 2); - SET_REG_FIELD(0x2F7, gx->tref[i / 2], 8, 24, 0x28 + i / 2); + SET_REG_FIELD(0x2F2+LINE_OFFSET, gx->tevc[i], 8, 24, 0xC0 + i * 2); + SET_REG_FIELD(0x2F3+LINE_OFFSET, gx->teva[i], 8, 24, 0xC1 + i * 2); + SET_REG_FIELD(0x2F5+LINE_OFFSET, gx->tevKsel[i / 2], 8, 24, 0xF6 + i / 2); + SET_REG_FIELD(0x2F7+LINE_OFFSET, gx->tref[i / 2], 8, 24, 0x28 + i / 2); } gx->iref = 0; SET_REG_FIELD(0, gx->iref, 8, 24, 0x27); for (i = 0; i < 8; ++i) { gx->suTs0[i] = 0; gx->suTs1[i] = 0; - SET_REG_FIELD(0x300, gx->suTs0[i], 8, 24, 0x30 + i * 2); - SET_REG_FIELD(0x301, gx->suTs1[i], 8, 24, 0x31 + i * 2); + SET_REG_FIELD(0x300+LINE_OFFSET, gx->suTs0[i], 8, 24, 0x30 + i * 2); + SET_REG_FIELD(0x301+LINE_OFFSET, gx->suTs1[i], 8, 24, 0x31 + i * 2); } SET_REG_FIELD(0, gx->suScis0, 8, 24, 0x20); SET_REG_FIELD(0, gx->suScis1, 8, 24, 0x21); @@ -190,6 +198,7 @@ GXFifoObj *GXInit(void *base, u32 size) SET_REG_FIELD(0, reg, 8, 24, 0x58); GX_WRITE_RAS_REG(reg); } +#if DOLPHIN_REVISION < 45 switch (VIGetTvFormat()) { case VI_NTSC: rmode = &GXNtsc480IntDf; break; case VI_PAL: rmode = &GXPal528IntDf; break; @@ -253,15 +262,37 @@ GXFifoObj *GXInit(void *base, u32 size) GXSetChanMatColor(GX_COLOR1A1, white); GXInvalidateTexAll(); gx->nextTexRgn = 0; +#endif for (i = 0; i < 8; i++) GXInitTexCacheRegion(&gx->TexRegions[i], 0, i * 0x8000, 0, 0x80000 + i * 0x8000, 0); +#if DOLPHIN_REVISION < 45 gx->nextTexRgnCI = 0; +#endif for (i = 0; i < 4; i++) GXInitTexCacheRegion(&gx->TexRegionsCI[i], 0, (i * 2 + 8) * 0x8000, 0, (i * 2 + 9) * 0x8000, 0); for (i = 0; i < 16; i++) GXInitTlutRegion(&gx->TlutRegions[i], 0xC0000 + i * 0x2000, 16); for (i = 0; i < 4; i++) GXInitTlutRegion(&gx->TlutRegions[i + 16], 0xE0000 + i * 0x8000, 64); +#if DOLPHIN_REVISION >= 45 + { + u32 reg; + + reg = 0; + __cpReg[3] = reg; + gx->perfSel = gx->perfSel & ~0xF0; + GX_WRITE_SOME_REG4(8, 0x20, gx->perfSel, -12); + reg = 0; + GX_WRITE_XF_REG(6, reg); + reg = 0x23000000; + GX_WRITE_RAS_REG(reg); + reg = 0x24000000; + GX_WRITE_RAS_REG(reg); + reg = 0x67000000; + GX_WRITE_RAS_REG(reg); + __GXSetTmemConfig(0); + } +#else GXSetTexRegionCallback(__GXDefaultTexRegionCallback); GXSetTlutRegionCallback(__GXDefaultTlutRegionCallback); GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); @@ -335,6 +366,161 @@ GXFifoObj *GXInit(void *base, u32 size) GXPokeAlphaRead(GX_READ_FF); GXPokeDstAlpha(GX_DISABLE, 0); GXPokeZMode(GX_TRUE, GX_ALWAYS, GX_TRUE); +#endif + +#if DOLPHIN_REVISION >= 45 + __GXInitGX(); +#endif return &FifoObj; } + +void __GXInitGX(void) +{ + struct _GXRenderModeObj * rmode; // r31 + f32 identity_mtx[3][4]; // r1+0x2C + GXColor clear = {64, 64, 64, 255}; + GXColor black = {0, 0, 0, 0}; + GXColor white = {255, 255, 255, 255}; + unsigned long i; // r30 + + switch (VIGetTvFormat()) { + case VI_NTSC: rmode = &GXNtsc480IntDf; break; + case VI_PAL: rmode = &GXPal528IntDf; break; + case VI_MPAL: rmode = &GXMpal480IntDf; break; + default: + ASSERTMSGLINE(0x3FE, 0, "GXInit: invalid TV format"); + rmode = &GXNtsc480IntDf; + break; + } + GXSetCopyClear(clear, 0xFFFFFF); + GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x3CU); + GXSetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX1, 0x3CU); + GXSetTexCoordGen(GX_TEXCOORD2, GX_TG_MTX2x4, GX_TG_TEX2, 0x3CU); + GXSetTexCoordGen(GX_TEXCOORD3, GX_TG_MTX2x4, GX_TG_TEX3, 0x3CU); + GXSetTexCoordGen(GX_TEXCOORD4, GX_TG_MTX2x4, GX_TG_TEX4, 0x3CU); + GXSetTexCoordGen(GX_TEXCOORD5, GX_TG_MTX2x4, GX_TG_TEX5, 0x3CU); + GXSetTexCoordGen(GX_TEXCOORD6, GX_TG_MTX2x4, GX_TG_TEX6, 0x3CU); + GXSetTexCoordGen(GX_TEXCOORD7, GX_TG_MTX2x4, GX_TG_TEX7, 0x3CU); + GXSetNumTexGens(1); + GXClearVtxDesc(); + GXInvalidateVtxCache(); + GXSetLineWidth(6, 0); + GXSetPointSize(6, 0); + GXEnableTexOffsets(0, 0, 0); + GXEnableTexOffsets(1, 0, 0); + GXEnableTexOffsets(2, 0, 0); + GXEnableTexOffsets(3, 0, 0); + GXEnableTexOffsets(4, 0, 0); + GXEnableTexOffsets(5, 0, 0); + GXEnableTexOffsets(6, 0, 0); + GXEnableTexOffsets(7, 0, 0); + identity_mtx[0][0] = 1.0f; + identity_mtx[0][1] = 0.0f; + identity_mtx[0][2] = 0.0f; + identity_mtx[0][3] = 0.0f; + identity_mtx[1][0] = 0.0f; + identity_mtx[1][1] = 1.0f; + identity_mtx[1][2] = 0.0f; + identity_mtx[1][3] = 0.0f; + identity_mtx[2][0] = 0.0f; + identity_mtx[2][1] = 0.0f; + identity_mtx[2][2] = 1.0f; + identity_mtx[2][3] = 0.0f; + GXLoadPosMtxImm(identity_mtx, GX_PNMTX0); + GXLoadNrmMtxImm(identity_mtx, GX_PNMTX0); + GXSetCurrentMtx(GX_PNMTX0); + GXLoadTexMtxImm(identity_mtx, GX_IDENTITY, GX_MTX3x4); + GXLoadTexMtxImm(identity_mtx, GX_PTIDENTITY, GX_MTX3x4); + GXSetViewport(0.0f, 0.0f, rmode->fbWidth, rmode->xfbHeight, 0.0f, 1.0f); + GXSetCoPlanar(GX_DISABLE); + GXSetCullMode(GX_CULL_BACK); + GXSetClipMode(GX_CLIP_ENABLE); + GXSetScissor(0, 0, rmode->fbWidth, rmode->efbHeight); + GXSetScissorBoxOffset(0, 0); + GXSetNumChans(0); + GXSetChanCtrl(GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE); + GXSetChanAmbColor(GX_COLOR0A0, black); + GXSetChanMatColor(GX_COLOR0A0, white); + GXSetChanCtrl(GX_COLOR1A1, GX_DISABLE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE); + GXSetChanAmbColor(GX_COLOR1A1, black); + GXSetChanMatColor(GX_COLOR1A1, white); + GXInvalidateTexAll(); + gx->nextTexRgn = 0; + gx->nextTexRgnCI = 0; + GXSetTexRegionCallback(__GXDefaultTexRegionCallback); + GXSetTlutRegionCallback(__GXDefaultTlutRegionCallback); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE2, GX_TEXCOORD2, GX_TEXMAP2, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE3, GX_TEXCOORD3, GX_TEXMAP3, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE4, GX_TEXCOORD4, GX_TEXMAP4, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE5, GX_TEXCOORD5, GX_TEXMAP5, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE6, GX_TEXCOORD6, GX_TEXMAP6, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE7, GX_TEXCOORD7, GX_TEXMAP7, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE8, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE9, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE10, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE11, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE12, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE13, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE14, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE15, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL); + + GXSetNumTevStages(1); + GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE); + GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0); + GXSetZTexture(GX_ZT_DISABLE, GX_TF_Z8, 0); + for (i = GX_TEVSTAGE0; i < GX_MAX_TEVSTAGE; i++) + { + GXSetTevKColorSel((GXTevStageID)i, GX_TEV_KCSEL_1_4); + GXSetTevKAlphaSel((GXTevStageID)i, GX_TEV_KASEL_1); + GXSetTevSwapMode((GXTevStageID)i, GX_TEV_SWAP0, GX_TEV_SWAP0); + } + GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA); + GXSetTevSwapModeTable(GX_TEV_SWAP1, GX_CH_RED, GX_CH_RED, GX_CH_RED, GX_CH_ALPHA); + GXSetTevSwapModeTable(GX_TEV_SWAP2, GX_CH_GREEN, GX_CH_GREEN, GX_CH_GREEN, GX_CH_ALPHA); + GXSetTevSwapModeTable(GX_TEV_SWAP3, GX_CH_BLUE, GX_CH_BLUE, GX_CH_BLUE, GX_CH_ALPHA); + + for (i = GX_TEVSTAGE0; i < GX_MAX_TEVSTAGE; i++) + GXSetTevDirect((GXTevStageID)i); + GXSetNumIndStages(0); + GXSetIndTexCoordScale(GX_INDTEXSTAGE0, GX_ITS_1, GX_ITS_1); + GXSetIndTexCoordScale(GX_INDTEXSTAGE1, GX_ITS_1, GX_ITS_1); + GXSetIndTexCoordScale(GX_INDTEXSTAGE2, GX_ITS_1, GX_ITS_1); + GXSetIndTexCoordScale(GX_INDTEXSTAGE3, GX_ITS_1, GX_ITS_1); + + GXSetFog(GX_FOG_NONE, 0.0f, 1.0f, 0.1f, 1.0f, black); + GXSetFogRangeAdj(GX_DISABLE, 0, 0); + GXSetBlendMode(GX_BM_NONE, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR); + GXSetColorUpdate(GX_ENABLE); + GXSetAlphaUpdate(GX_ENABLE); + GXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + GXSetZCompLoc(GX_TRUE); + GXSetDither(GX_ENABLE); + GXSetDstAlpha(GX_DISABLE, 0); + GXSetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR); + GXSetFieldMask(GX_ENABLE, GX_ENABLE); + GXSetFieldMode(rmode->field_rendering, + ((rmode->viHeight == 2 * rmode->xfbHeight) ? GX_ENABLE : GX_DISABLE)); + + GXSetDispCopySrc(0, 0, rmode->fbWidth, rmode->efbHeight); + GXSetDispCopyDst(rmode->fbWidth, rmode->efbHeight); + GXSetDispCopyYScale((f32)(rmode->xfbHeight) / (f32)(rmode->efbHeight)); + GXSetCopyClamp((GXFBClamp)(GX_CLAMP_TOP | GX_CLAMP_BOTTOM)); + GXSetCopyFilter(rmode->aa, rmode->sample_pattern, GX_TRUE, rmode->vfilter); + GXSetDispCopyGamma(GX_GM_1_0); + GXSetDispCopyFrame2Field(GX_COPY_PROGRESSIVE); + GXClearBoundingBox(); + + GXPokeColorUpdate(GX_TRUE); + GXPokeAlphaUpdate(GX_TRUE); + GXPokeDither(GX_FALSE); + GXPokeBlendMode(GX_BM_NONE, GX_BL_ZERO, GX_BL_ONE, GX_LO_SET); + GXPokeAlphaMode(GX_ALWAYS, 0); + GXPokeAlphaRead(GX_READ_FF); + GXPokeDstAlpha(GX_DISABLE, 0); + GXPokeZMode(GX_TRUE, GX_ALWAYS, GX_TRUE); + GXSetGPMetric(0x23, 0x16); + GXClearGPMetric(); +} diff --git a/src/gx/GXLight.c b/src/gx/GXLight.c index d46fde4..dfd96ac 100644 --- a/src/gx/GXLight.c +++ b/src/gx/GXLight.c @@ -364,7 +364,11 @@ void GXLoadLightObjImm(GXLightObj *lt_obj, GXLightID light) WRITE_SOME_LIGHT_REG2(obj->ldir[1], addr + 14); WRITE_SOME_LIGHT_REG2(obj->ldir[2], addr + 15); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 1; +#else gx->bpSent = 0; +#endif } void GXLoadLightObjIndx(u32 lt_obj_indx, GXLightID light) @@ -400,7 +404,12 @@ void GXLoadLightObjIndx(u32 lt_obj_indx, GXLightID light) #if DEBUG __GXShadowIndexState(7, reg); #endif + +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 1; +#else gx->bpSent = 0; +#endif } void GXSetChanAmbColor(GXChannelID chan, GXColor amb_color) @@ -458,7 +467,11 @@ void GXSetChanAmbColor(GXChannelID chan, GXColor amb_color) } GX_WRITE_XF_REG(colIdx + 10, reg); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 1; +#else gx->bpSent = 0; +#endif gx->ambColor[colIdx] = reg; } @@ -517,7 +530,11 @@ void GXSetChanMatColor(GXChannelID chan, GXColor mat_color) } GX_WRITE_XF_REG(colIdx + 12, reg); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 1; +#else gx->bpSent = 0; +#endif gx->matColor[colIdx] = reg; } @@ -565,7 +582,11 @@ void GXSetChanCtrl(GXChannelID chan, GXBool enable, GXColorSrc amb_src, SET_REG_FIELD(0x310, reg, 1, 10, (attn_fn != 0)); GX_WRITE_XF_REG(idx + 14, reg); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 1; +#else gx->bpSent = 0; +#endif if (chan == GX_COLOR0A0) { GX_WRITE_XF_REG(16, reg); } else if (chan == GX_COLOR1A1) { diff --git a/src/gx/GXMisc.c b/src/gx/GXMisc.c index 30fd00c..bcee2cb 100644 --- a/src/gx/GXMisc.c +++ b/src/gx/GXMisc.c @@ -11,17 +11,23 @@ static GXDrawDoneCallback DrawDoneCB; static u8 DrawDone; static OSThreadQueue FinishQueue; +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 14 : 0) + void GXSetMisc(GXMiscToken token, u32 val) { switch (token) { case GX_MT_XF_FLUSH: gx->vNum = val; +#if DOLPHIN_REVISION >= 45 + gx->vNumNot = !gx->vNum; + gx->bpSentNot = 1; +#endif if (gx->vNum != 0) { gx->dirtyState |= 8; } break; case GX_MT_DL_SAVE_CONTEXT: - ASSERTMSGLINE(0xC4, !gx->inDispList, "GXSetMisc: Cannot change DL context setting while making a display list"); + ASSERTMSGLINE(0xC4+LINE_OFFSET, !gx->inDispList, "GXSetMisc: Cannot change DL context setting while making a display list"); gx->dlSaveContext = (val > 0); break; case GX_MT_NULL: @@ -34,17 +40,31 @@ void GXSetMisc(GXMiscToken token, u32 val) } } +#undef LINE_OFFSET +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 13 : 0) + void GXFlush(void) { u32 i; - CHECK_GXBEGIN(0xF0, "GXFlush"); + CHECK_GXBEGIN(0xF0+LINE_OFFSET, "GXFlush"); if (gx->dirtyState) { __GXSetDirtyState(); } +#if DOLPHIN_REVISION >= 45 + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); + GX_WRITE_U32(0); +#else for (i = 32; i > 0; i--) { GX_WRITE_U8(0); } +#endif PPCSync(); } @@ -66,31 +86,52 @@ static inline void __GXAbortWait(u32 clocks) } while (time1 - time0 <= (clocks / 4)); } +#if DOLPHIN_REVISION >= 45 +void __GXAbort(void) +{ + __piReg[6] = 1; + __GXAbortWait(0xC8); + __piReg[6] = 0; + __GXAbortWait(0x14); +} +#endif + void GXAbortFrame(void) { +#if DOLPHIN_REVISION >= 45 + __GXAbort(); +#else __piReg[6] = 1; - __GXAbortWait(0xC8U); + __GXAbortWait(0xC8); __piReg[6] = 0; - __GXAbortWait(0x14U); + __GXAbortWait(0x14); +#endif __GXCleanGPFifo(); } +#undef LINE_OFFSET +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 25 : 0) + void GXSetDrawSync(u16 token) { BOOL enabled; u32 reg; - CHECK_GXBEGIN(0x162, "GXSetDrawSync"); + CHECK_GXBEGIN(0x162+LINE_OFFSET, "GXSetDrawSync"); enabled = OSDisableInterrupts(); reg = token | 0x48000000; GX_WRITE_RAS_REG(reg); - SET_REG_FIELD(0x16F, reg, 16, 0, token); - SET_REG_FIELD(0x170, reg, 8, 24, 0x47); + SET_REG_FIELD(0x16F+LINE_OFFSET, reg, 16, 0, token); + SET_REG_FIELD(0x170+LINE_OFFSET, reg, 8, 24, 0x47); GX_WRITE_RAS_REG(reg); GXFlush(); OSRestoreInterrupts(enabled); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } u16 GXReadDrawSync(void) @@ -104,7 +145,7 @@ void GXSetDrawDone(void) u32 reg; BOOL enabled; - CHECK_GXBEGIN(0x19C, "GXSetDrawDone"); + CHECK_GXBEGIN(0x19C+LINE_OFFSET, "GXSetDrawDone"); enabled = OSDisableInterrupts(); reg = 0x45000002; GX_WRITE_RAS_REG(reg); @@ -117,7 +158,7 @@ void GXWaitDrawDone(void) { BOOL enabled; - CHECK_GXBEGIN(0x1CA, "GXWaitDrawDone"); + CHECK_GXBEGIN(0x1CA+LINE_OFFSET, "GXWaitDrawDone"); enabled = OSDisableInterrupts(); while (!DrawDone) { @@ -128,34 +169,46 @@ void GXWaitDrawDone(void) void GXDrawDone(void) { - CHECK_GXBEGIN(0x1EA, "GXDrawDone"); + CHECK_GXBEGIN(0x1EA+LINE_OFFSET, "GXDrawDone"); GXSetDrawDone(); GXWaitDrawDone(); } void GXPixModeSync(void) { - CHECK_GXBEGIN(0x20D, "GXPixModeSync"); + CHECK_GXBEGIN(0x20D+LINE_OFFSET, "GXPixModeSync"); GX_WRITE_RAS_REG(gx->peCtrl); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXTexModeSync(void) { u32 reg; - CHECK_GXBEGIN(0x225, "GXTexModeSync"); + CHECK_GXBEGIN(0x225+LINE_OFFSET, "GXTexModeSync"); reg = 0x63000000; GX_WRITE_RAS_REG(reg); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } #if DEBUG void __GXBypass(u32 reg) { - CHECK_GXBEGIN(0x23B, "__GXBypass"); + CHECK_GXBEGIN(0x23B+LINE_OFFSET, "__GXBypass"); GX_WRITE_RAS_REG(reg); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } u16 __GXReadPEReg(u32 reg) @@ -168,87 +221,123 @@ void GXPokeAlphaMode(GXCompare func, u8 threshold) { u32 reg; +#if DOLPHIN_REVISION < 45 CHECK_GXBEGIN(0x25F, "GXPokeAlphaMode"); +#endif reg = (func << 8) | threshold; __peReg[3] = reg; } +#undef LINE_OFFSET +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 21 : 0) + void GXPokeAlphaRead(GXAlphaReadMode mode) { u32 reg; +#if DOLPHIN_REVISION < 45 CHECK_GXBEGIN(0x26A, "GXPokeAlphaRead"); +#endif reg = 0; - SET_REG_FIELD(0x26D, reg, 2, 0, mode); - SET_REG_FIELD(0x26E, reg, 1, 2, 1); + SET_REG_FIELD(0x26D+LINE_OFFSET, reg, 2, 0, mode); + SET_REG_FIELD(0x26E+LINE_OFFSET, reg, 1, 2, 1); __peReg[4] = reg; } +#undef LINE_OFFSET +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 19 : 0) + void GXPokeAlphaUpdate(GXBool update_enable) { u32 reg; +#if DOLPHIN_REVISION < 45 CHECK_GXBEGIN(0x277, "GXPokeAlphaUpdate"); +#endif reg = __peReg[1]; - SET_REG_FIELD(0x27A, reg, 1, 4, update_enable); + SET_REG_FIELD(0x27A+LINE_OFFSET, reg, 1, 4, update_enable); __peReg[1] = reg; } +#undef LINE_OFFSET +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 17 : 0) + void GXPokeBlendMode(GXBlendMode type, GXBlendFactor src_factor, GXBlendFactor dst_factor, GXLogicOp op) { u32 reg; +#if DOLPHIN_REVISION < 45 CHECK_GXBEGIN(0x284, "GXPokeBlendUpdate"); +#endif reg = __peReg[1]; - SET_REG_FIELD(0x28C, reg, 1, 0, (type == GX_BM_BLEND) || (type == GX_BM_SUBTRACT)); - SET_REG_FIELD(0x28D, reg, 1, 11, (type == GX_BM_SUBTRACT)); - SET_REG_FIELD(0x28F, reg, 1, 1, (type == GX_BM_LOGIC)); - SET_REG_FIELD(0x290, reg, 4, 12, op); - SET_REG_FIELD(0x291, reg, 3, 8, src_factor); - SET_REG_FIELD(0x292, reg, 3, 5, dst_factor); - SET_REG_FIELD(0x293, reg, 8, 24, 0x41); + SET_REG_FIELD(0x28C+LINE_OFFSET, reg, 1, 0, (type == GX_BM_BLEND) || (type == GX_BM_SUBTRACT)); + SET_REG_FIELD(0x28D+LINE_OFFSET, reg, 1, 11, (type == GX_BM_SUBTRACT)); + SET_REG_FIELD(0x28F+LINE_OFFSET, reg, 1, 1, (type == GX_BM_LOGIC)); + SET_REG_FIELD(0x290+LINE_OFFSET, reg, 4, 12, op); + SET_REG_FIELD(0x291+LINE_OFFSET, reg, 3, 8, src_factor); + SET_REG_FIELD(0x292+LINE_OFFSET, reg, 3, 5, dst_factor); + SET_REG_FIELD(0x293+LINE_OFFSET, reg, 8, 24, 0x41); __peReg[1] = reg; } +#undef LINE_OFFSET +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 15 : 0) + void GXPokeColorUpdate(GXBool update_enable) { u32 reg; +#if DOLPHIN_REVISION < 45 CHECK_GXBEGIN(0x29D, "GXPokeColorUpdate"); +#endif reg = __peReg[1]; - SET_REG_FIELD(0x2A0, reg, 1, 3, update_enable); + SET_REG_FIELD(0x2A0+LINE_OFFSET, reg, 1, 3, update_enable); __peReg[1] = reg; } +#undef LINE_OFFSET +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 13 : 0) + void GXPokeDstAlpha(GXBool enable, u8 alpha) { u32 reg = 0; +#if DOLPHIN_REVISION < 45 CHECK_GXBEGIN(0x2A9, "GXPokeDstAlpha"); - SET_REG_FIELD(0x2AB, reg, 8, 0, alpha); - SET_REG_FIELD(0x2AC, reg, 1, 8, enable); +#endif + SET_REG_FIELD(0x2AB+LINE_OFFSET, reg, 8, 0, alpha); + SET_REG_FIELD(0x2AC+LINE_OFFSET, reg, 1, 8, enable); __peReg[2] = reg; } +#undef LINE_OFFSET +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 11 : 0) + void GXPokeDither(GXBool dither) { u32 reg; +#if DOLPHIN_REVISION < 45 CHECK_GXBEGIN(0x2B5, "GXPokeDither"); +#endif reg = __peReg[1]; - SET_REG_FIELD(0x2B8, reg, 1, 2, dither); + SET_REG_FIELD(0x2B8+LINE_OFFSET, reg, 1, 2, dither); __peReg[1] = reg; } +#undef LINE_OFFSET +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 9 : 0) + void GXPokeZMode(GXBool compare_enable, GXCompare func, GXBool update_enable) { u32 reg = 0; +#if DOLPHIN_REVISION < 45 CHECK_GXBEGIN(0x2C1, "GXPokeZMode"); - - SET_REG_FIELD(0x2C3, reg, 1, 0, compare_enable); - SET_REG_FIELD(0x2C4, reg, 3, 1, func); - SET_REG_FIELD(0x2C5, reg, 1, 4, update_enable); +#endif + SET_REG_FIELD(0x2C3+LINE_OFFSET, reg, 1, 0, compare_enable); + SET_REG_FIELD(0x2C4+LINE_OFFSET, reg, 3, 1, func); + SET_REG_FIELD(0x2C5+LINE_OFFSET, reg, 1, 4, update_enable); __peReg[0] = reg; } @@ -256,9 +345,9 @@ void GXPeekARGB(u16 x, u16 y, u32 *color) { u32 addr = (u32)OSPhysicalToUncached(0x08000000); - SET_REG_FIELD(0x2DC, addr, 10, 2, x); - SET_REG_FIELD(0x2DD, addr, 10, 12, y); - SET_REG_FIELD(0x2DE, addr, 2, 22, 0); + SET_REG_FIELD(0x2DC+LINE_OFFSET, addr, 10, 2, x); + SET_REG_FIELD(0x2DD+LINE_OFFSET, addr, 10, 12, y); + SET_REG_FIELD(0x2DE+LINE_OFFSET, addr, 2, 22, 0); *color = *(u32 *)addr; } @@ -266,9 +355,9 @@ void GXPokeARGB(u16 x, u16 y, u32 color) { u32 addr = (u32)OSPhysicalToUncached(0x08000000); - SET_REG_FIELD(0x2E6, addr, 10, 2, x); - SET_REG_FIELD(0x2E7, addr, 10, 12, y); - SET_REG_FIELD(0x2E8, addr, 2, 22, 0); + SET_REG_FIELD(0x2E6+LINE_OFFSET, addr, 10, 2, x); + SET_REG_FIELD(0x2E7+LINE_OFFSET, addr, 10, 12, y); + SET_REG_FIELD(0x2E8+LINE_OFFSET, addr, 2, 22, 0); *(u32 *)addr = color; } @@ -276,9 +365,9 @@ void GXPeekZ(u16 x, u16 y, u32 *z) { u32 addr = (u32)OSPhysicalToUncached(0x08000000); - SET_REG_FIELD(0x2F0, addr, 10, 2, x); - SET_REG_FIELD(0x2F1, addr, 10, 12, y); - SET_REG_FIELD(0x2F2, addr, 2, 22, 1); + SET_REG_FIELD(0x2F0+LINE_OFFSET, addr, 10, 2, x); + SET_REG_FIELD(0x2F1+LINE_OFFSET, addr, 10, 12, y); + SET_REG_FIELD(0x2F2+LINE_OFFSET, addr, 2, 22, 1); *z = *(u32 *)addr; } @@ -286,9 +375,9 @@ void GXPokeZ(u16 x, u16 y, u32 z) { u32 addr = (u32)OSPhysicalToUncached(0x08000000); - SET_REG_FIELD(0x2FA, addr, 10, 2, x); - SET_REG_FIELD(0x2FB, addr, 10, 12, y); - SET_REG_FIELD(0x2FC, addr, 2, 22, 1); + SET_REG_FIELD(0x2FA+LINE_OFFSET, addr, 10, 2, x); + SET_REG_FIELD(0x2FB+LINE_OFFSET, addr, 10, 12, y); + SET_REG_FIELD(0x2FC+LINE_OFFSET, addr, 2, 22, 1); *(u32 *)addr = z; } @@ -429,7 +518,7 @@ u32 GXCompressZ16(u32 z24, GXZFmt16 zfmt) z16 = ((z24 >> shift) & 0xFFF & ~0xFFFFF000) | (exp << 12); break; default: - OSPanic(__FILE__, 0x3B0, "GXCompressZ16: Invalid Z format\n"); + OSPanic(__FILE__, 0x3B0+LINE_OFFSET, "GXCompressZ16: Invalid Z format\n"); break; } return z16; @@ -479,7 +568,7 @@ u32 GXDecompressZ16(u32 z16, GXZFmt16 zfmt) z24 = (cb1 | ((z16 & 0xFFF) << shift)) & 0xFFFFFF; break; default: - OSPanic(__FILE__, 0x3E2, "GXDecompressZ16: Invalid Z format\n"); + OSPanic(__FILE__, 0x3E2+LINE_OFFSET, "GXDecompressZ16: Invalid Z format\n"); break; } return z24; diff --git a/src/gx/GXPerf.c b/src/gx/GXPerf.c index 9cc7b04..b3b3521 100644 --- a/src/gx/GXPerf.c +++ b/src/gx/GXPerf.c @@ -4,11 +4,13 @@ #include "__gx.h" +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 3 : 0) + void GXSetGPMetric(GXPerf0 perf0, GXPerf1 perf1) { u32 reg; - CHECK_GXBEGIN(0x6A, "GXSetGPMetric"); + CHECK_GXBEGIN(0x6A+LINE_OFFSET, "GXSetGPMetric"); switch (gx->perf0) { case GX_PERF0_VERTICES: @@ -58,7 +60,7 @@ void GXSetGPMetric(GXPerf0 perf0, GXPerf1 perf1) case GX_PERF0_NONE: break; default: - ASSERTMSGLINE(0xA6, 0, "GXSetGPMetric: Invalid GXPerf0 metric name"); + ASSERTMSGLINE(0xA6+LINE_OFFSET, 0, "GXSetGPMetric: Invalid GXPerf0 metric name"); break; } @@ -97,7 +99,7 @@ void GXSetGPMetric(GXPerf0 perf0, GXPerf1 perf1) case GX_PERF1_NONE: break; default: - ASSERTMSGLINE(0xD8, 0, "GXSetGPMetric: Invalid GXPerf1 metric name"); + ASSERTMSGLINE(0xD8+LINE_OFFSET, 0, "GXSetGPMetric: Invalid GXPerf1 metric name"); break; } @@ -140,7 +142,7 @@ void GXSetGPMetric(GXPerf0 perf0, GXPerf1 perf1) case GX_PERF0_CLOCKS: reg = 0x21; GX_WRITE_XF_REG(6, reg); break; case GX_PERF0_NONE: break; default: - ASSERTMSGLINE(0x1DA, 0, "GXSetGPMetric: Invalid GXPerf0 metric name"); + ASSERTMSGLINE(0x1DA+LINE_OFFSET, 0, "GXSetGPMetric: Invalid GXPerf0 metric name"); break; } @@ -170,11 +172,15 @@ void GXSetGPMetric(GXPerf0 perf0, GXPerf1 perf1) case GX_PERF1_CLOCKS: reg = 0x67000021; GX_WRITE_RAS_REG(reg); break; case GX_PERF1_NONE: break; default: - ASSERTMSGLINE(0x26B, 0, "GXSetGPMetric: Invalid GXPerf1 metric name"); + ASSERTMSGLINE(0x26B+LINE_OFFSET, 0, "GXSetGPMetric: Invalid GXPerf1 metric name"); break; } +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXReadGPMetric(u32 *cnt0, u32 *cnt1) @@ -182,7 +188,7 @@ void GXReadGPMetric(u32 *cnt0, u32 *cnt1) u32 ctrl, ctrh; u32 cpCtr0, cpCtr1, cpCtr2, cpCtr3; - ASSERTMSGLINE(0x286, !gx->inDispList, "GXReadGPMetric: don't use in a display list"); + ASSERTMSGLINE(0x286+LINE_OFFSET, !gx->inDispList, "GXReadGPMetric: don't use in a display list"); ctrl = __cpReg[32]; ctrh = __cpReg[33]; cpCtr0 = (ctrh << 16) | ctrl; @@ -241,7 +247,7 @@ void GXReadGPMetric(u32 *cnt0, u32 *cnt1) *cnt0 = 0; break; default: - ASSERTMSGLINE(0x2CF, 0, "GXReadGPMetric: Invalid GXPerf0 metric name"); + ASSERTMSGLINE(0x2CF+LINE_OFFSET, 0, "GXReadGPMetric: Invalid GXPerf0 metric name"); *cnt0 = 0; break; } @@ -287,7 +293,7 @@ void GXReadGPMetric(u32 *cnt0, u32 *cnt1) *cnt1 = 0; break; default: - ASSERTMSGLINE(0x30A, 0, "GXReadGPMetric: Invalid GXPerf1 metric name"); + ASSERTMSGLINE(0x30A+LINE_OFFSET, 0, "GXReadGPMetric: Invalid GXPerf1 metric name"); *cnt1 = 0; break; } @@ -297,7 +303,7 @@ void GXClearGPMetric(void) { u32 reg; - ASSERTMSGLINE(0x322, !gx->inDispList, "GXClearGPMetric: don't use in a display list"); + ASSERTMSGLINE(0x322+LINE_OFFSET, !gx->inDispList, "GXClearGPMetric: don't use in a display list"); reg = 4; __cpReg[2] = reg; } @@ -322,7 +328,7 @@ void GXReadMemMetric(u32 *cp_req, u32 *tc_req, u32 *cpu_rd_req, u32 *cpu_wr_req, { u32 ctrl, ctrh; - ASSERTMSGLINE(0x380, !gx->inDispList, "GXReadMemMetric: don't use in a display list"); + ASSERTMSGLINE(0x380+LINE_OFFSET, !gx->inDispList, "GXReadMemMetric: don't use in a display list"); ctrl = __memReg[26]; ctrh = __memReg[25]; *cp_req = (ctrh << 16) | ctrl; @@ -357,7 +363,7 @@ void GXReadMemMetric(u32 *cp_req, u32 *tc_req, u32 *cpu_rd_req, u32 *cpu_wr_req, void GXClearMemMetric(void) { - ASSERTMSGLINE(0x3B9, !gx->inDispList, "GXClearMemMetric: don't use in a display list"); + ASSERTMSGLINE(0x3B9+LINE_OFFSET, !gx->inDispList, "GXClearMemMetric: don't use in a display list"); __memReg[25] = 0; __memReg[26] = 0; @@ -385,7 +391,7 @@ void GXReadPixMetric(u32 *top_pixels_in, u32 *top_pixels_out, u32 *bot_pixels_in { u32 ctrl, ctrh; - ASSERTMSGLINE(0x3F1, !gx->inDispList, "GXReadPixMetric: don't use in a display list"); + ASSERTMSGLINE(0x3F1+LINE_OFFSET, !gx->inDispList, "GXReadPixMetric: don't use in a display list"); ctrl = __peReg[12]; ctrh = __peReg[13]; *top_pixels_in = ((ctrh << 16) | ctrl) * 4; @@ -410,20 +416,24 @@ void GXClearPixMetric(void) { u32 reg; - CHECK_GXBEGIN(0x41D, "GXClearPixMetric"); + CHECK_GXBEGIN(0x41D+LINE_OFFSET, "GXClearPixMetric"); reg = 0x57000000; GX_WRITE_RAS_REG(reg); reg = 0x57000AAA; GX_WRITE_RAS_REG(reg); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetVCacheMetric(GXVCachePerf attr) { u32 reg; - SET_REG_FIELD(0x43C, gx->perfSel, 4, 0, attr); + SET_REG_FIELD(0x43C+LINE_OFFSET, gx->perfSel, 4, 0, attr); GX_WRITE_SOME_REG4(8, 0x20, gx->perfSel, -12); reg = 1; GX_WRITE_SOME_REG4(8, 0x10, reg, -12); @@ -452,13 +462,17 @@ void GXInitXfRasMetric(void) { u32 reg; - CHECK_GXBEGIN(0x489, "GXInitXfRasMetric"); + CHECK_GXBEGIN(0x489+LINE_OFFSET, "GXInitXfRasMetric"); reg = 0x2402C022; GX_WRITE_RAS_REG(reg); reg = 0x31000; GX_WRITE_XF_REG(6, reg); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 1; +#else gx->bpSent = 0; +#endif } void GXReadXfRasMetric(u32 *xf_wait_in, u32 *xf_wait_out, u32 *ras_busy, u32 *clocks) diff --git a/src/gx/GXPixel.c b/src/gx/GXPixel.c index 9fe787b..feac036 100644 --- a/src/gx/GXPixel.c +++ b/src/gx/GXPixel.c @@ -91,7 +91,11 @@ void GXSetFog(GXFogType type, f32 startz, f32 endz, f32 nearz, f32 farz, GXColor GX_WRITE_RAS_REG(fog2); GX_WRITE_RAS_REG(fog3); GX_WRITE_RAS_REG(fogclr); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXInitFogAdjTable(GXFogAdjTable *table, u16 width, f32 projmtx[4][4]) @@ -144,11 +148,20 @@ void GXSetFogRangeAdj(GXBool enable, u16 center, GXFogAdjTable *table) } } range_c = 0; + +#if DOLPHIN_REVISION >= 45 + SET_REG_FIELD(0x115, range_c, 10, 0, center + 342); +#else SET_REG_FIELD(0x115, range_c, 10, 0, center + 340); +#endif SET_REG_FIELD(0x116, range_c, 1, 10, enable); SET_REG_FIELD(0x117, range_c, 8, 24, 0xE8); GX_WRITE_RAS_REG(range_c); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetBlendMode(GXBlendMode type, GXBlendFactor src_factor, GXBlendFactor dst_factor, GXLogicOp op) @@ -163,7 +176,11 @@ void GXSetBlendMode(GXBlendMode type, GXBlendFactor src_factor, GXBlendFactor ds SET_REG_FIELD(0x13B, gx->cmode0, 3, 5, dst_factor); SET_REG_FIELD(0x13C, gx->cmode0, 8, 24, 0x41); GX_WRITE_RAS_REG(gx->cmode0); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetColorUpdate(GXBool update_enable) @@ -171,7 +188,11 @@ void GXSetColorUpdate(GXBool update_enable) CHECK_GXBEGIN(0x14F, "GXSetColorUpdate"); SET_REG_FIELD(0x150, gx->cmode0, 1, 3, update_enable); GX_WRITE_RAS_REG(gx->cmode0); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetAlphaUpdate(GXBool update_enable) @@ -179,7 +200,11 @@ void GXSetAlphaUpdate(GXBool update_enable) CHECK_GXBEGIN(0x158, "GXSetAlphaUpdate"); SET_REG_FIELD(0x159, gx->cmode0, 1, 4, update_enable); GX_WRITE_RAS_REG(gx->cmode0); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetZMode(GXBool compare_enable, GXCompare func, GXBool update_enable) @@ -189,7 +214,11 @@ void GXSetZMode(GXBool compare_enable, GXCompare func, GXBool update_enable) SET_REG_FIELD(0x172, gx->zmode, 3, 1, func); SET_REG_FIELD(0x173, gx->zmode, 1, 4, update_enable); GX_WRITE_RAS_REG(gx->zmode); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetZCompLoc(GXBool before_tex) @@ -197,7 +226,11 @@ void GXSetZCompLoc(GXBool before_tex) CHECK_GXBEGIN(0x17C, "GXSetZCompLoc"); SET_REG_FIELD(0x17D, gx->peCtrl, 1, 6, before_tex); GX_WRITE_RAS_REG(gx->peCtrl); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetPixelFmt(GXPixelFmt pix_fmt, GXZFmt16 z_fmt) @@ -225,7 +258,11 @@ void GXSetPixelFmt(GXPixelFmt pix_fmt, GXZFmt16 z_fmt) SET_REG_FIELD(0x1B9, gx->cmode1, 8, 24, 0x42); GX_WRITE_RAS_REG(gx->cmode1); } +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetDither(GXBool dither) @@ -233,7 +270,11 @@ void GXSetDither(GXBool dither) CHECK_GXBEGIN(0x1CD, "GXSetDither"); SET_REG_FIELD(0x1CE, gx->cmode0, 1, 2, dither); GX_WRITE_RAS_REG(gx->cmode0); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetDstAlpha(GXBool enable, u8 alpha) @@ -242,7 +283,11 @@ void GXSetDstAlpha(GXBool enable, u8 alpha) SET_REG_FIELD(0x1E2, gx->cmode1, 8, 0, alpha); SET_REG_FIELD(0x1E3, gx->cmode1, 1, 8, enable); GX_WRITE_RAS_REG(gx->cmode1); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetFieldMask(GXBool odd_mask, GXBool even_mask) @@ -255,7 +300,11 @@ void GXSetFieldMask(GXBool odd_mask, GXBool even_mask) SET_REG_FIELD(0x1FC, reg, 1, 1, odd_mask); SET_REG_FIELD(0x1FD, reg, 8, 24, 0x44); GX_WRITE_RAS_REG(reg); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetFieldMode(GXBool field_mode, GXBool half_aspect_ratio) diff --git a/src/gx/GXSave.c b/src/gx/GXSave.c index bcf0104..beaa604 100644 --- a/src/gx/GXSave.c +++ b/src/gx/GXSave.c @@ -76,11 +76,34 @@ static void __SaveCPRegs(u8 reg, u8 vatIdx, u32 data) } break; default: +#if DOLPHIN_REVISION >= 45 + if (__gxVerif->verifyLevel >= __gxvWarnLev[0x71]) { + __gxVerif->cb(__gxvWarnLev[0x71], 0x71, __gxvWarnings[0x71]); + } + OSReport("[Invalid CP Stream Register Address 0x%x\n]", reg); +#else OSReport("GX DisplayList: Invalid CP Stream Register Address 0x%x\n", reg); +#endif break; } } +static void __ReconstVtxStatus(u8 vatIdx) +{ + u32 vat; + + if (GET_REG_FIELD(gx->vcdLo, 2, 11)) { + vat = gx->vatA[vatIdx & 0xFF]; + if ((vat >> 9) & 1) { + gx->hasNrms = FALSE; + gx->hasBiNrms = TRUE; + } else { + gx->hasNrms = TRUE; + gx->hasBiNrms = FALSE; + } + } +} + static u32 vtxCompSize[5] = { 1, 1, 2, 2, 4 }; static int clrCompSize[6] = { 2, 3, 4, 2, 3, 4 }; @@ -124,6 +147,35 @@ static u32 GetAttrSize(u8 vatIdx, u32 attrIdx) } break; case 10: +#if DOLPHIN_REVISION >= 45 + vcd = gx->vcdLo; + vat = gx->vatA[vatIdx & 0xFF]; + switch (GET_REG_FIELD(vcd, 2, 11)) { + case 0: + return 0; + case 2: + if (GET_REG_FIELD(vat, 1, 9) && GET_REG_FIELD(vat, 1, 31)) { + nc = 3; + } else { + nc = 1; + } + return nc; + case 3: + if (GET_REG_FIELD(vat, 1, 9) && GET_REG_FIELD(vat, 1, 31)) { + nc = 6; + } else { + nc = 2; + } + return nc; + case 1: + if (GET_REG_FIELD(vat, 1, 9)) { + nc = 9; + } else { + nc = 3; + } + return nc * vtxCompSize[(vat >> 10) & 7]; + } +#else vcd = gx->vcdLo; vat = gx->vatA[vatIdx & 0xFF]; if ((vat >> 9) & 1) { @@ -141,6 +193,7 @@ static u32 GetAttrSize(u8 vatIdx, u32 attrIdx) case 1: return (((vat >> 9) & 1) + nc) * vtxCompSize[(vat >> 10) & 7]; } +#endif break; case 11: switch (GET_REG_FIELD(gx->vcdLo, 2, 13)) { @@ -314,6 +367,9 @@ void __GXShadowDispList(void *list, u32 nbytes) u32 i; u32 addr; u32 cnt; +#if DOLPHIN_REVISION >= 45 + u8 cpAddr; +#endif if (__gxVerif->verifyLevel == GX_WARN_NONE) { return; @@ -322,9 +378,12 @@ void __GXShadowDispList(void *list, u32 nbytes) dlist = list; dlistSize = nbytes; bytesRead = 0; +#if DOLPHIN_REVISION >= 45 + DPF("Displaylist IN\n"); +#endif while (dlistSize > bytesRead) { if (!__ReadMem(&cmd, 1)) { - return; + goto done; } cmdOp = (u32)GET_REG_FIELD((u32)cmd, 5, 3); vatIdx = cmd & 7; @@ -339,12 +398,21 @@ void __GXShadowDispList(void *list, u32 nbytes) case 21: case 22: case 23: +#if DOLPHIN_REVISION >= 45 + __ReconstVtxStatus(vatIdx); +#endif __GXVerifyState(vatIdx); __ParseVertexData(vatIdx); break; case 1: if (__ReadMem(®8, 1) && __ReadMem(&d32, 4)) { +#if DOLPHIN_REVISION >= 45 + vatIdx = reg8 & 0xF; + cpAddr = (int)((reg8 >> 4) & 0xF); + __SaveCPRegs(cpAddr, vatIdx, d32); +#else __SaveCPRegs(reg8, vatIdx, d32); +#endif } break; case 2: @@ -371,7 +439,13 @@ void __GXShadowDispList(void *list, u32 nbytes) } break; case 8: +#if DOLPHIN_REVISION >= 45 + if (__gxVerif->verifyLevel >= __gxvWarnLev[0x72]) { + __gxVerif->cb(__gxvWarnLev[0x72], 0x72, __gxvWarnings[0x72]); + } +#else OSReport("GX DisplayList: Nested Display Lists\n"); +#endif return; case 12: case 13: @@ -381,10 +455,22 @@ void __GXShadowDispList(void *list, u32 nbytes) } break; default: +#if DOLPHIN_REVISION >= 45 + if (__gxVerif->verifyLevel >= __gxvWarnLev[0x71]) { + __gxVerif->cb(__gxvWarnLev[0x71], 0x71, __gxvWarnings[0x71]); + } + OSReport("[Bad Display List Command: %d\n]", cmdOp); +#else OSReport("GX DisplayList: Bad Display List Command: %d\n", cmdOp); +#endif break; } } +done: + ; +#if DOLPHIN_REVISION >= 45 + DPF("Displaylist OUT\n"); +#endif } void __GXShadowIndexState(u32 idx_reg, u32 reg_data) @@ -405,7 +491,9 @@ void __GXShadowIndexState(u32 idx_reg, u32 reg_data) cnt = (reg_data >> 12) & 0xF; index = reg_data >> 16; memAddr = (u32 *)((u8 *)basePtr + (index * stride)); - +#if DOLPHIN_REVISION >= 45 + cnt++; +#endif while (cnt-- != 0) { data = *memAddr; VERIF_MTXLIGHT(addr, data); diff --git a/src/gx/GXTev.c b/src/gx/GXTev.c index 2d643be..d44e6ba 100644 --- a/src/gx/GXTev.c +++ b/src/gx/GXTev.c @@ -63,7 +63,11 @@ void GXSetTevColorIn(GXTevStageID stage, GXTevColorArg a, GXTevColorArg b, GXTev SET_REG_FIELD(0xF0, *pTevReg, 4, 0, d); GX_WRITE_RAS_REG(*pTevReg); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetTevAlphaIn(GXTevStageID stage, GXTevAlphaArg a, GXTevAlphaArg b, GXTevAlphaArg c, GXTevAlphaArg d) @@ -84,7 +88,11 @@ void GXSetTevAlphaIn(GXTevStageID stage, GXTevAlphaArg a, GXTevAlphaArg b, GXTev SET_REG_FIELD(0x113, *pTevReg, 3, 4, d); GX_WRITE_RAS_REG(*pTevReg); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetTevColorOp(GXTevStageID stage, GXTevOp op, GXTevBias bias, GXTevScale scale, GXBool clamp, GXTevRegID out_reg) @@ -107,7 +115,11 @@ void GXSetTevColorOp(GXTevStageID stage, GXTevOp op, GXTevBias bias, GXTevScale SET_REG_FIELD(0x141, *pTevReg, 2, 22, out_reg); GX_WRITE_RAS_REG(*pTevReg); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetTevAlphaOp(GXTevStageID stage, GXTevOp op, GXTevBias bias, GXTevScale scale, GXBool clamp, GXTevRegID out_reg) @@ -130,7 +142,11 @@ void GXSetTevAlphaOp(GXTevStageID stage, GXTevOp op, GXTevBias bias, GXTevScale SET_REG_FIELD(0x16D, *pTevReg, 2, 22, out_reg); GX_WRITE_RAS_REG(*pTevReg); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetTevColor(GXTevRegID id, GXColor color) @@ -154,7 +170,11 @@ void GXSetTevColor(GXTevRegID id, GXColor color) GX_WRITE_RAS_REG(regBG); GX_WRITE_RAS_REG(regBG); GX_WRITE_RAS_REG(regBG); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetTevColorS10(GXTevRegID id, GXColorS10 color) @@ -183,7 +203,11 @@ void GXSetTevColorS10(GXTevRegID id, GXColorS10 color) GX_WRITE_RAS_REG(regBG); GX_WRITE_RAS_REG(regBG); GX_WRITE_RAS_REG(regBG); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetTevKColor(GXTevKColorID id, GXColor color) @@ -207,7 +231,11 @@ void GXSetTevKColor(GXTevKColorID id, GXColor color) GX_WRITE_RAS_REG(regRA); GX_WRITE_RAS_REG(regBG); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetTevKColorSel(GXTevStageID stage, GXTevKColorSel sel) @@ -225,7 +253,11 @@ void GXSetTevKColorSel(GXTevStageID stage, GXTevKColorSel sel) } GX_WRITE_RAS_REG(*Kreg); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetTevKAlphaSel(GXTevStageID stage, GXTevKAlphaSel sel) @@ -243,7 +275,11 @@ void GXSetTevKAlphaSel(GXTevStageID stage, GXTevKAlphaSel sel) } GX_WRITE_RAS_REG(*Kreg); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetTevSwapMode(GXTevStageID stage, GXTevSwapSel ras_sel, GXTevSwapSel tex_sel) @@ -258,7 +294,11 @@ void GXSetTevSwapMode(GXTevStageID stage, GXTevSwapSel ras_sel, GXTevSwapSel tex SET_REG_FIELD(0x24F, *pTevReg, 2, 2, tex_sel); GX_WRITE_RAS_REG(*pTevReg); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetTevSwapModeTable(GXTevSwapSel table, GXTevColorChan red, GXTevColorChan green, GXTevColorChan blue, GXTevColorChan alpha) @@ -287,7 +327,11 @@ void GXSetTevSwapModeTable(GXTevSwapSel table, GXTevColorChan red, GXTevColorCha SET_REG_FIELD(0x278, *Kreg, 2, 2, alpha); GX_WRITE_RAS_REG(*Kreg); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetTevClampMode(void) @@ -309,7 +353,11 @@ void GXSetAlphaCompare(GXCompare comp0, u8 ref0, GXAlphaOp op, GXCompare comp1, SET_REG_FIELD(0x2B9, reg, 8, 24, 0xF3); GX_WRITE_RAS_REG(reg); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetZTexture(GXZTexOp op, GXTexFmt fmt, u32 bias) @@ -347,7 +395,11 @@ void GXSetZTexture(GXZTexOp op, GXTexFmt fmt, u32 bias) GX_WRITE_RAS_REG(zenv0); GX_WRITE_RAS_REG(zenv1); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetTevOrder(GXTevStageID stage, GXTexCoordID coord, GXTexMapID map, GXChannelID color) @@ -380,7 +432,11 @@ void GXSetTevOrder(GXTevStageID stage, GXTexCoordID coord, GXTexMapID map, GXCha } GX_WRITE_RAS_REG(*ptref); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif gx->dirtyState |= 1; } diff --git a/src/gx/GXTexture.c b/src/gx/GXTexture.c index f5ef9f6..7149b96 100644 --- a/src/gx/GXTexture.c +++ b/src/gx/GXTexture.c @@ -51,6 +51,8 @@ u8 GXTexTlutIds[8] = { 0x98, 0x99, 0x9A, 0x9B, 0xB8, 0xB9, 0xBA, 0xBB }; static u8 GX2HWFiltConv[6] = { 0x00, 0x04, 0x01, 0x05, 0x02, 0x06 }; static u8 HW2GXFiltConv[8] = { 0x00, 0x02, 0x04, 0x00, 0x01, 0x03, 0x05, 0x00 }; +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 19 : 0) + static void __GXGetTexTileShift(GXTexFmt fmt, u32 *rowTileS, u32 *colTileS) { switch (fmt) { @@ -92,7 +94,7 @@ static void __GXGetTexTileShift(GXTexFmt fmt, u32 *rowTileS, u32 *colTileS) break; default: *rowTileS = *colTileS = 0; - ASSERTMSGLINEV(0x184, 0, "%s: invalid texture format", "GX"); + ASSERTMSGLINEV(0x184+LINE_OFFSET, 0, "%s: invalid texture format", "GX"); break; } } @@ -107,8 +109,8 @@ u32 GXGetTexBufferSize(u16 width, u16 height, u32 format, u8 mipmap, u8 max_lod) u32 ny; u32 level; - ASSERTMSGLINEV(0x194, width <= 1024, "%s: width too large", "GXGetTexBufferSize"); - ASSERTMSGLINEV(0x195, height <= 1024, "%s: height too large", "GXGetTexBufferSize"); + ASSERTMSGLINEV(0x194+LINE_OFFSET, width <= 1024, "%s: width too large", "GXGetTexBufferSize"); + ASSERTMSGLINEV(0x195+LINE_OFFSET, height <= 1024, "%s: height too large", "GXGetTexBufferSize"); __GXGetTexTileShift(format, &tileShiftX, &tileShiftY); if (format == GX_TF_RGBA8 || format == GX_TF_Z24X8) { @@ -118,9 +120,9 @@ u32 GXGetTexBufferSize(u16 width, u16 height, u32 format, u8 mipmap, u8 max_lod) } if (mipmap == 1) { nx = 1 << (31 - __cntlzw(width)); - ASSERTMSGLINEV(0x1A7, width == nx, "%s: width must be a power of 2", "GXGetTexBufferSize"); + ASSERTMSGLINEV(0x1A7+LINE_OFFSET, width == nx, "%s: width must be a power of 2", "GXGetTexBufferSize"); ny = 1 << (31 - __cntlzw(height)); - ASSERTMSGLINEV(0x1AA, height == ny, "%s: height must be a power of 2", "GXGetTexBufferSize"); + ASSERTMSGLINEV(0x1AA+LINE_OFFSET, height == ny, "%s: height must be a power of 2", "GXGetTexBufferSize"); bufferSize = 0; for (level = 0; level < max_lod; level++) { @@ -168,46 +170,62 @@ void GXInitTexObj(GXTexObj *obj, void *image_ptr, u16 width, u16 height, GXTexFm u32 colC; __GXTexObjInt *t = (__GXTexObjInt *)obj; - ASSERTMSGLINE(0x1FD, obj, "Texture Object Pointer is null"); - CHECK_GXBEGIN(0x1FF, "GXInitTexObj"); - ASSERTMSGLINEV(0x200, width <= 1024, "%s: width too large", "GXInitTexObj"); - ASSERTMSGLINEV(0x201, height <= 1024, "%s: height too large", "GXInitTexObj"); - ASSERTMSGLINEV(0x203, !(format & 0x20), "%s: invalid texture format", "GXInitTexObj"); + ASSERTMSGLINE(0x1FD+LINE_OFFSET, obj, "Texture Object Pointer is null"); + CHECK_GXBEGIN(0x1FF+LINE_OFFSET, "GXInitTexObj"); + ASSERTMSGLINEV(0x200+LINE_OFFSET, width <= 1024, "%s: width too large", "GXInitTexObj"); + ASSERTMSGLINEV(0x201+LINE_OFFSET, height <= 1024, "%s: height too large", "GXInitTexObj"); + ASSERTMSGLINEV(0x203+LINE_OFFSET, !(format & 0x20), "%s: invalid texture format", "GXInitTexObj"); #if DEBUG if (wrap_s != GX_CLAMP || mipmap != 0) { u32 mask = 1 << (31 - __cntlzw(width)); - ASSERTMSGLINEV(0x20D, width == mask, "%s: width must be a power of 2", "GXInitTexObj"); + ASSERTMSGLINEV(0x20D+LINE_OFFSET, width == mask, "%s: width must be a power of 2", "GXInitTexObj"); } if (wrap_t != GX_CLAMP || mipmap != 0) { u32 mask = 1 << (31 - __cntlzw(height)); - ASSERTMSGLINEV(0x212, height == mask, "%s: height must be a power of 2", "GXInitTexObj"); + ASSERTMSGLINEV(0x212+LINE_OFFSET, height == mask, "%s: height must be a power of 2", "GXInitTexObj"); } #endif memset(t, 0, 0x20); - SET_REG_FIELD(0x220, t->mode0, 2, 0, wrap_s); - SET_REG_FIELD(0x221, t->mode0, 2, 2, wrap_t); - SET_REG_FIELD(0x222, t->mode0, 1, 4, 1); + SET_REG_FIELD(0x220+LINE_OFFSET, t->mode0, 2, 0, wrap_s); + SET_REG_FIELD(0x221+LINE_OFFSET, t->mode0, 2, 2, wrap_t); + SET_REG_FIELD(0x222+LINE_OFFSET, t->mode0, 1, 4, 1); if (mipmap != 0) { u8 lmax; t->flags |= 1; +#if DOLPHIN_REVISION >= 45 + if (format == 8 || format == 9 || format == 10) { + t->mode0 = (t->mode0 & 0xFFFFFF1F) | 0xA0; + } else { + t->mode0 = (t->mode0 & 0xFFFFFF1F) | 0xC0; + } +#else t->mode0 = (t->mode0 & 0xFFFFFF1F) | 0xC0; +#endif + +#undef LINE_OFFSET +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 31 : 0) + if (width > height) { maxLOD = 31 - __cntlzw(width); } else { maxLOD = 31 - __cntlzw(height); } lmax = 16.0f * maxLOD; - SET_REG_FIELD(0x234, t->mode1, 8, 8, lmax); + SET_REG_FIELD(0x234+LINE_OFFSET, t->mode1, 8, 8, lmax); } else { t->mode0 = (t->mode0 & 0xFFFFFF1F) | 0x80; } t->fmt = format; - SET_REG_FIELD(0x240, t->image0, 10, 0, width - 1); - SET_REG_FIELD(0x241, t->image0, 10, 10, height - 1); - SET_REG_FIELD(0x242, t->image0, 4, 20, format & 0xF); - ASSERTMSGLINEV(0x248, ((u32)image_ptr & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTexObj", "image"); + +#undef LINE_OFFSET +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 33 : 0) + + SET_REG_FIELD(0x240+LINE_OFFSET, t->image0, 10, 0, width - 1); + SET_REG_FIELD(0x241+LINE_OFFSET, t->image0, 10, 10, height - 1); + SET_REG_FIELD(0x242+LINE_OFFSET, t->image0, 4, 20, format & 0xF); + ASSERTMSGLINEV(0x248+LINE_OFFSET, ((u32)image_ptr & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTexObj", "image"); imageBase = (u32)((u32)image_ptr >> 5) & 0x01FFFFFF; - SET_REG_FIELD(0x24A, t->image3, 21, 0, imageBase); + SET_REG_FIELD(0x24A+LINE_OFFSET, t->image3, 21, 0, imageBase); switch (format & 0xF) { case 0: case 8: @@ -241,7 +259,7 @@ void GXInitTexObj(GXTexObj *obj, void *image_ptr, u16 width, u16 height, GXTexFm colT = 3; break; default: - ASSERTMSGLINEV(0x275, 0, "%s: invalid texture format", "GXPreLoadEntireTexture"); + ASSERTMSGLINEV(0x275+LINE_OFFSET, 0, "%s: invalid texture format", "GXPreLoadEntireTexture"); t->loadFmt = 2; rowT = 2; colT = 2; @@ -257,8 +275,8 @@ void GXInitTexObjCI(GXTexObj *obj, void *image_ptr, u16 width, u16 height, GXCIT { __GXTexObjInt *t = (__GXTexObjInt *)obj; - ASSERTMSGLINE(0x29B, obj, "Texture Object Pointer is null"); - CHECK_GXBEGIN(0x29D, "GXInitTexObjCI"); + ASSERTMSGLINE(0x29B+LINE_OFFSET, obj, "Texture Object Pointer is null"); + CHECK_GXBEGIN(0x29D+LINE_OFFSET, "GXInitTexObjCI"); GXInitTexObj(obj, image_ptr, width, height, format, wrap_s, wrap_t, mipmap); t->flags &= 0xFFFFFFFD; t->tlutName = tlut_name; @@ -271,8 +289,8 @@ void GXInitTexObjLOD(GXTexObj *obj, GXTexFilter min_filt, GXTexFilter mag_filt, u8 lmax; __GXTexObjInt *t = (__GXTexObjInt *)obj; - ASSERTMSGLINE(0x2C2, obj, "Texture Object Pointer is null"); - CHECK_GXBEGIN(0x2C4, "GXInitTexObjLOD"); + ASSERTMSGLINE(0x2C2+LINE_OFFSET, obj, "Texture Object Pointer is null"); + CHECK_GXBEGIN(0x2C4+LINE_OFFSET, "GXInitTexObjLOD"); if (lod_bias < -4.0f) { lod_bias = -4.0f; @@ -280,15 +298,15 @@ void GXInitTexObjLOD(GXTexObj *obj, GXTexFilter min_filt, GXTexFilter mag_filt, lod_bias = 3.99f; } lbias = 32.0f * lod_bias; - SET_REG_FIELD(0x2CE, t->mode0, 8, 9, lbias); - SET_REG_FIELD(0x2CF, t->mode0, 1, 4, (mag_filt == GX_LINEAR) ? 1 : 0); - ASSERTMSGLINE(0x2D1, (u32)min_filt <= 5, "GXInitTexObjLOD: invalid min_filt value"); - SET_REG_FIELD(0x2D2, t->mode0, 3, 5, GX2HWFiltConv[min_filt]); - SET_REG_FIELD(0x2D3, t->mode0, 1, 8, do_edge_lod ? 0 : 1); + SET_REG_FIELD(0x2CE+LINE_OFFSET, t->mode0, 8, 9, lbias); + SET_REG_FIELD(0x2CF+LINE_OFFSET, t->mode0, 1, 4, (mag_filt == GX_LINEAR) ? 1 : 0); + ASSERTMSGLINE(0x2D1+LINE_OFFSET, (u32)min_filt <= 5, "GXInitTexObjLOD: invalid min_filt value"); + SET_REG_FIELD(0x2D2+LINE_OFFSET, t->mode0, 3, 5, GX2HWFiltConv[min_filt]); + SET_REG_FIELD(0x2D3+LINE_OFFSET, t->mode0, 1, 8, do_edge_lod ? 0 : 1); t->mode0 &= 0xFFFDFFFF; t->mode0 &= 0xFFFBFFFF; - SET_REG_FIELD(0x2D6, t->mode0, 2, 19, max_aniso); - SET_REG_FIELD(0x2D7, t->mode0, 1, 21, bias_clamp); + SET_REG_FIELD(0x2D6+LINE_OFFSET, t->mode0, 2, 19, max_aniso); + SET_REG_FIELD(0x2D7+LINE_OFFSET, t->mode0, 1, 21, bias_clamp); if (min_lod < 0.0f) { min_lod = 0.0f; } else if (min_lod > 10.0f) { @@ -301,8 +319,8 @@ void GXInitTexObjLOD(GXTexObj *obj, GXTexFilter min_filt, GXTexFilter mag_filt, max_lod = 10.0f; } lmax = 16.0f * max_lod; - SET_REG_FIELD(0x2E5, t->mode1, 8, 0, lmin); - SET_REG_FIELD(0x2E6, t->mode1, 8, 8, lmax); + SET_REG_FIELD(0x2E5+LINE_OFFSET, t->mode1, 8, 0, lmin); + SET_REG_FIELD(0x2E6+LINE_OFFSET, t->mode1, 8, 8, lmax); } void GXInitTexObjData(GXTexObj *obj, void *image_ptr) @@ -310,29 +328,29 @@ void GXInitTexObjData(GXTexObj *obj, void *image_ptr) u32 imageBase; __GXTexObjInt *t = (__GXTexObjInt *)obj; - ASSERTMSGLINE(0x2F9, obj, "Texture Object Pointer is null"); - CHECK_GXBEGIN(0x2FB, "GXInitTexObjData"); - ASSERTMSGLINEV(0x2FE, ((u32)image_ptr & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTexObjData", "image"); + ASSERTMSGLINE(0x2F9+LINE_OFFSET, obj, "Texture Object Pointer is null"); + CHECK_GXBEGIN(0x2FB+LINE_OFFSET, "GXInitTexObjData"); + ASSERTMSGLINEV(0x2FE+LINE_OFFSET, ((u32)image_ptr & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTexObjData", "image"); imageBase = ((u32)image_ptr >> 5) & 0x01FFFFFF; - SET_REG_FIELD(0x301, t->image3, 21, 0, imageBase); + SET_REG_FIELD(0x301+LINE_OFFSET, t->image3, 21, 0, imageBase); } void GXInitTexObjWrapMode(GXTexObj *obj, GXTexWrapMode sm, GXTexWrapMode tm) { __GXTexObjInt *t = (__GXTexObjInt *)obj; - ASSERTMSGLINE(0x313, obj, "Texture Object Pointer is null"); - CHECK_GXBEGIN(0x315, "GXInitTexObjWrapMode"); - SET_REG_FIELD(0x317, t->mode0, 2, 0, sm); - SET_REG_FIELD(0x318, t->mode0, 2, 2, tm); + ASSERTMSGLINE(0x313+LINE_OFFSET, obj, "Texture Object Pointer is null"); + CHECK_GXBEGIN(0x315+LINE_OFFSET, "GXInitTexObjWrapMode"); + SET_REG_FIELD(0x317+LINE_OFFSET, t->mode0, 2, 0, sm); + SET_REG_FIELD(0x318+LINE_OFFSET, t->mode0, 2, 2, tm); } void GXInitTexObjTlut(GXTexObj *obj, u32 tlut_name) { __GXTexObjInt *t = (__GXTexObjInt *)obj; - ASSERTMSGLINE(0x329, obj, "Texture Object Pointer is null"); - CHECK_GXBEGIN(0x32B, "GXInitTexObjTlut"); + ASSERTMSGLINE(0x329+LINE_OFFSET, obj, "Texture Object Pointer is null"); + CHECK_GXBEGIN(0x32B+LINE_OFFSET, "GXInitTexObjTlut"); t->tlutName = tlut_name; } @@ -340,8 +358,8 @@ void GXInitTexObjUserData(GXTexObj *obj, void *user_data) { __GXTexObjInt *t = (__GXTexObjInt *)obj; - ASSERTMSGLINE(0x33E, obj, "Texture Object Pointer is null"); - CHECK_GXBEGIN(0x33F, "GXInitTexObjUserData"); + ASSERTMSGLINE(0x33E+LINE_OFFSET, obj, "Texture Object Pointer is null"); + CHECK_GXBEGIN(0x33F+LINE_OFFSET, "GXInitTexObjUserData"); t->userData = user_data; } @@ -349,7 +367,7 @@ void *GXGetTexObjUserData(const GXTexObj *obj) { const __GXTexObjInt *t = (const __GXTexObjInt *)obj; - ASSERTMSGLINE(0x345, obj, "Texture Object Pointer is null"); + ASSERTMSGLINE(0x345+LINE_OFFSET, obj, "Texture Object Pointer is null"); return t->userData; } @@ -357,7 +375,7 @@ void GXGetTexObjAll(const GXTexObj *obj, void **image_ptr, u16 *width, u16 *heig { const __GXTexObjInt *t = (const __GXTexObjInt *)obj; - ASSERTMSGLINE(0x359, obj, "Texture Object Pointer is null"); + ASSERTMSGLINE(0x359+LINE_OFFSET, obj, "Texture Object Pointer is null"); *image_ptr = (void *)(GET_REG_FIELD(t->image3, 21, 0) << 5); *width = (u32)GET_REG_FIELD(t->image0, 10, 0) + 1; *height = (u32)GET_REG_FIELD(t->image0, 10, 10) + 1; @@ -371,7 +389,7 @@ void *GXGetTexObjData(const GXTexObj *to) { const __GXTexObjInt *t = (const __GXTexObjInt *)to; - ASSERTMSGLINE(0x366, to, "Texture Object Pointer is null"); + ASSERTMSGLINE(0x366+LINE_OFFSET, to, "Texture Object Pointer is null"); return (void *)(GET_REG_FIELD(t->image3, 21, 0) << 5); } @@ -379,7 +397,7 @@ u16 GXGetTexObjWidth(const GXTexObj *to) { const __GXTexObjInt *t = (const __GXTexObjInt *)to; - ASSERTMSGLINE(0x36C, to, "Texture Object Pointer is null"); + ASSERTMSGLINE(0x36C+LINE_OFFSET, to, "Texture Object Pointer is null"); return (u32)GET_REG_FIELD(t->image0, 10, 0) + 1; } @@ -387,7 +405,7 @@ u16 GXGetTexObjHeight(const GXTexObj *to) { const __GXTexObjInt *t = (const __GXTexObjInt *)to; - ASSERTMSGLINE(0x372, to, "Texture Object Pointer is null"); + ASSERTMSGLINE(0x372+LINE_OFFSET, to, "Texture Object Pointer is null"); return (u32)GET_REG_FIELD(t->image0, 10, 10) + 1; } @@ -395,7 +413,7 @@ GXTexFmt GXGetTexObjFmt(const GXTexObj *to) { const __GXTexObjInt *t = (const __GXTexObjInt *)to; - ASSERTMSGLINE(0x378, to, "Texture Object Pointer is null"); + ASSERTMSGLINE(0x378+LINE_OFFSET, to, "Texture Object Pointer is null"); return t->fmt; } @@ -403,7 +421,7 @@ GXTexWrapMode GXGetTexObjWrapS(const GXTexObj *to) { const __GXTexObjInt *t = (const __GXTexObjInt *)to; - ASSERTMSGLINE(0x37E, to, "Texture Object Pointer is null"); + ASSERTMSGLINE(0x37E+LINE_OFFSET, to, "Texture Object Pointer is null"); return GET_REG_FIELD(t->mode0, 2, 0); } @@ -411,7 +429,7 @@ GXTexWrapMode GXGetTexObjWrapT(const GXTexObj *to) { const __GXTexObjInt *t = (const __GXTexObjInt *)to; - ASSERTMSGLINE(0x384, to, "Texture Object Pointer is null"); + ASSERTMSGLINE(0x384+LINE_OFFSET, to, "Texture Object Pointer is null"); return GET_REG_FIELD(t->mode0, 2, 2); } @@ -419,7 +437,7 @@ GXBool GXGetTexObjMipMap(const GXTexObj *to) { const __GXTexObjInt *t = (const __GXTexObjInt *)to; - ASSERTMSGLINE(0x38A, to, "Texture Object Pointer is null"); + ASSERTMSGLINE(0x38A+LINE_OFFSET, to, "Texture Object Pointer is null"); return (t->flags & 1) == 1; } @@ -428,7 +446,7 @@ void GXGetTexObjLODAll(const GXTexObj *tex_obj, GXTexFilter *min_filt, GXTexFilt s16 tmp; const __GXTexObjInt *t = (const __GXTexObjInt *)tex_obj; - ASSERTMSGLINE(0x3A0, tex_obj, "Texture Object Pointer is null"); + ASSERTMSGLINE(0x3A0+LINE_OFFSET, tex_obj, "Texture Object Pointer is null"); *min_filt = HW2GXFiltConv[GET_REG_FIELD(t->mode0, 3, 5)]; *mag_filt = GET_REG_FIELD(t->mode0, 1, 4); *min_lod = (u8)t->mode1 / 16.0f; @@ -447,7 +465,7 @@ GXTexFilter GXGetTexObjMinFilt(const GXTexObj *tex_obj) { const __GXTexObjInt *t = (const __GXTexObjInt *)tex_obj; - ASSERTMSGLINE(0x3B2, tex_obj, "Texture Object Pointer is null"); + ASSERTMSGLINE(0x3B2+LINE_OFFSET, tex_obj, "Texture Object Pointer is null"); return HW2GXFiltConv[GET_REG_FIELD(t->mode0, 3, 5)]; } @@ -455,7 +473,7 @@ GXTexFilter GXGetTexObjMagFilt(const GXTexObj *tex_obj) { const __GXTexObjInt *t = (const __GXTexObjInt *)tex_obj; - ASSERTMSGLINE(0x3B9, tex_obj, "Texture Object Pointer is null"); + ASSERTMSGLINE(0x3B9+LINE_OFFSET, tex_obj, "Texture Object Pointer is null"); return GET_REG_FIELD(t->mode0, 1, 4); } @@ -463,7 +481,7 @@ f32 GXGetTexObjMinLOD(const GXTexObj *tex_obj) { const __GXTexObjInt *t = (const __GXTexObjInt *)tex_obj; - ASSERTMSGLINE(0x3BF, tex_obj, "Texture Object Pointer is null"); + ASSERTMSGLINE(0x3BF+LINE_OFFSET, tex_obj, "Texture Object Pointer is null"); return (u32)GET_REG_FIELD(t->mode1, 8, 0) / 16.0f; } @@ -471,7 +489,7 @@ f32 GXGetTexObjMaxLOD(const GXTexObj *tex_obj) { const __GXTexObjInt *t = (const __GXTexObjInt *)tex_obj; - ASSERTMSGLINE(0x3C5, tex_obj, "Texture Object Pointer is null"); + ASSERTMSGLINE(0x3C5+LINE_OFFSET, tex_obj, "Texture Object Pointer is null"); return (u32)GET_REG_FIELD(t->mode1, 8, 8) / 16.0f; } @@ -480,7 +498,7 @@ f32 GXGetTexObjLODBias(const GXTexObj *tex_obj) s16 tmp; const __GXTexObjInt *t = (const __GXTexObjInt *)tex_obj; - ASSERTMSGLINE(0x3CC, tex_obj, "Texture Object Pointer is null"); + ASSERTMSGLINE(0x3CC+LINE_OFFSET, tex_obj, "Texture Object Pointer is null"); tmp = (s32)GET_REG_FIELD(t->mode0, 8, 9); if (tmp & 0x80) { tmp = -(tmp & 0x7F); @@ -492,7 +510,7 @@ GXBool GXGetTexObjBiasClamp(const GXTexObj *tex_obj) { const __GXTexObjInt *t = (const __GXTexObjInt *)tex_obj; - ASSERTMSGLINE(0x3D5, tex_obj, "Texture Object Pointer is null"); + ASSERTMSGLINE(0x3D5+LINE_OFFSET, tex_obj, "Texture Object Pointer is null"); return (u32)GET_REG_FIELD(t->mode0, 1, 21); } @@ -500,7 +518,7 @@ GXBool GXGetTexObjEdgeLOD(const GXTexObj *tex_obj) { const __GXTexObjInt *t = (const __GXTexObjInt *)tex_obj; - ASSERTMSGLINE(0x3DB, tex_obj, "Texture Object Pointer is null"); + ASSERTMSGLINE(0x3DB+LINE_OFFSET, tex_obj, "Texture Object Pointer is null"); return !GET_REG_FIELD(t->mode0, 1, 8); } @@ -508,7 +526,7 @@ GXAnisotropy GXGetTexObjMaxAniso(const GXTexObj *tex_obj) { const __GXTexObjInt *t = (const __GXTexObjInt *)tex_obj; - ASSERTMSGLINE(0x3E1, tex_obj, "Texture Object Pointer is null"); + ASSERTMSGLINE(0x3E1+LINE_OFFSET, tex_obj, "Texture Object Pointer is null"); return GET_REG_FIELD(t->mode0, 2, 19); } @@ -516,7 +534,7 @@ u32 GXGetTexObjTlut(const GXTexObj *tex_obj) { const __GXTexObjInt *t = (const __GXTexObjInt *)tex_obj; - ASSERTMSGLINE(0x3E7, tex_obj, "Texture Object Pointer is null"); + ASSERTMSGLINE(0x3E7+LINE_OFFSET, tex_obj, "Texture Object Pointer is null"); return t->tlutName; } @@ -526,17 +544,17 @@ void GXLoadTexObjPreLoaded(GXTexObj *obj, GXTexRegion *region, GXTexMapID id) __GXTexObjInt *t = (__GXTexObjInt *)obj; __GXTexRegionInt *r = (__GXTexRegionInt *)region; - ASSERTMSGLINE(0x3FE, obj, "Texture Object Pointer is null"); - ASSERTMSGLINE(0x3FE, region, "TexRegion Object Pointer is null"); - CHECK_GXBEGIN(0x400, "GXLoadTexObjPreLoaded"); - ASSERTMSGLINEV(0x401, id < 8, "%s: invalid texture map ID", "GXLoadTexObj"); + ASSERTMSGLINE(0x3FE+LINE_OFFSET, obj, "Texture Object Pointer is null"); + ASSERTMSGLINE(0x3FE+LINE_OFFSET, region, "TexRegion Object Pointer is null"); + CHECK_GXBEGIN(0x400+LINE_OFFSET, "GXLoadTexObjPreLoaded"); + ASSERTMSGLINEV(0x401+LINE_OFFSET, id < 8, "%s: invalid texture map ID", "GXLoadTexObj"); - SET_REG_FIELD(0x403, t->mode0, 8, 24, GXTexMode0Ids[id]); - SET_REG_FIELD(0x404, t->mode1, 8, 24, GXTexMode1Ids[id]); - SET_REG_FIELD(0x405, t->image0, 8, 24, GXTexImage0Ids[id]); - SET_REG_FIELD(0x406, r->image1, 8, 24, GXTexImage1Ids[id]); - SET_REG_FIELD(0x407, r->image2, 8, 24, GXTexImage2Ids[id]); - SET_REG_FIELD(0x408, t->image3, 8, 24, GXTexImage3Ids[id]); + SET_REG_FIELD(0x403+LINE_OFFSET, t->mode0, 8, 24, GXTexMode0Ids[id]); + SET_REG_FIELD(0x404+LINE_OFFSET, t->mode1, 8, 24, GXTexMode1Ids[id]); + SET_REG_FIELD(0x405+LINE_OFFSET, t->image0, 8, 24, GXTexImage0Ids[id]); + SET_REG_FIELD(0x406+LINE_OFFSET, r->image1, 8, 24, GXTexImage1Ids[id]); + SET_REG_FIELD(0x407+LINE_OFFSET, r->image2, 8, 24, GXTexImage2Ids[id]); + SET_REG_FIELD(0x408+LINE_OFFSET, t->image3, 8, 24, GXTexImage3Ids[id]); GX_WRITE_RAS_REG(t->mode0); GX_WRITE_RAS_REG(t->mode1); @@ -546,28 +564,32 @@ void GXLoadTexObjPreLoaded(GXTexObj *obj, GXTexRegion *region, GXTexMapID id) GX_WRITE_RAS_REG(t->image3); if (!(t->flags & 2)) { - ASSERTMSGLINEV(0x413, gx->tlutRegionCallback, "%s: Tex/Tlut Region Callback not set", "GXLoadTexObj/PreLoaded"); + ASSERTMSGLINEV(0x413+LINE_OFFSET, gx->tlutRegionCallback, "%s: Tex/Tlut Region Callback not set", "GXLoadTexObj/PreLoaded"); tlr = (__GXTlutRegionInt *)gx->tlutRegionCallback(t->tlutName); - ASSERTMSGLINEV(0x415, tlr, "%s: Tex/Tlut Region Callback returns NULL", "GXLoadTexObj/PreLoaded"); + ASSERTMSGLINEV(0x415+LINE_OFFSET, tlr, "%s: Tex/Tlut Region Callback returns NULL", "GXLoadTexObj/PreLoaded"); - SET_REG_FIELD(0x417, tlr->tlutObj.tlut, 8, 24, GXTexTlutIds[id]); + SET_REG_FIELD(0x417+LINE_OFFSET, tlr->tlutObj.tlut, 8, 24, GXTexTlutIds[id]); GX_WRITE_RAS_REG(tlr->tlutObj.tlut); } gx->tImage0[id] = t->image0; gx->tMode0[id] = t->mode0; gx->dirtyState |= 1; +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXLoadTexObj(GXTexObj *obj, GXTexMapID id) { GXTexRegion *r; - CHECK_GXBEGIN(0x432, "GXLoadTexObj"); - ASSERTMSGLINEV(0x433, id < 8, "%s: invalid texture map ID", "GXLoadTexObj"); - ASSERTMSGLINEV(0x438, gx->texRegionCallback, "%s: Tex/Tlut Region Callback not set", "GXLoadTexObj"); + CHECK_GXBEGIN(0x432+LINE_OFFSET, "GXLoadTexObj"); + ASSERTMSGLINEV(0x433+LINE_OFFSET, id < 8, "%s: invalid texture map ID", "GXLoadTexObj"); + ASSERTMSGLINEV(0x438+LINE_OFFSET, gx->texRegionCallback, "%s: Tex/Tlut Region Callback not set", "GXLoadTexObj"); r = gx->texRegionCallback(obj, id); - ASSERTMSGLINEV(0x43A, r, "%s: Tex/Tlut Region Callback returns NULL", "GXLoadTexObj"); + ASSERTMSGLINEV(0x43A+LINE_OFFSET, r, "%s: Tex/Tlut Region Callback returns NULL", "GXLoadTexObj"); GXLoadTexObjPreLoaded(obj, r, id); } @@ -575,14 +597,14 @@ void GXInitTlutObj(GXTlutObj *tlut_obj, void *lut, GXTlutFmt fmt, u16 n_entries) { __GXTlutObjInt *t = (__GXTlutObjInt *)tlut_obj; - ASSERTMSGLINE(0x452, tlut_obj, "TLut Object Pointer is null"); - CHECK_GXBEGIN(0x453, "GXInitTlutObj"); - ASSERTMSGLINEV(0x456, n_entries <= 0x4000, "%s: number of entries exceeds maximum", "GXInitTlutObj"); - ASSERTMSGLINEV(0x458, ((u32)lut & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTlutObj", "Tlut"); + ASSERTMSGLINE(0x452+LINE_OFFSET, tlut_obj, "TLut Object Pointer is null"); + CHECK_GXBEGIN(0x453+LINE_OFFSET, "GXInitTlutObj"); + ASSERTMSGLINEV(0x456+LINE_OFFSET, n_entries <= 0x4000, "%s: number of entries exceeds maximum", "GXInitTlutObj"); + ASSERTMSGLINEV(0x458+LINE_OFFSET, ((u32)lut & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTlutObj", "Tlut"); t->tlut = 0; - SET_REG_FIELD(0x45B, t->tlut, 2, 10, fmt); - SET_REG_FIELD(0x45C, t->loadTlut0, 21, 0, ((u32)lut & 0x3FFFFFFF) >> 5); - SET_REG_FIELD(0x45D, t->loadTlut0, 8, 24, 0x64); + SET_REG_FIELD(0x45B+LINE_OFFSET, t->tlut, 2, 10, fmt); + SET_REG_FIELD(0x45C+LINE_OFFSET, t->loadTlut0, 21, 0, ((u32)lut & 0x3FFFFFFF) >> 5); + SET_REG_FIELD(0x45D+LINE_OFFSET, t->loadTlut0, 8, 24, 0x64); t->numEntries = n_entries; } @@ -590,7 +612,7 @@ void GXGetTlutObjAll(const GXTlutObj *tlut_obj, void **data, GXTlutFmt *format, { const __GXTlutObjInt *t = (const __GXTlutObjInt *)tlut_obj; - ASSERTMSGLINE(0x472, tlut_obj, "TLut Object Pointer is null"); + ASSERTMSGLINE(0x472+LINE_OFFSET, tlut_obj, "TLut Object Pointer is null"); *data = (void *)(GET_REG_FIELD(t->loadTlut0, 21, 0) << 5); *format = GET_REG_FIELD(t->tlut, 2, 10); *numEntries = t->numEntries; @@ -600,7 +622,7 @@ void *GXGetTlutObjData(const GXTlutObj *tlut_obj) { const __GXTlutObjInt *t = (const __GXTlutObjInt *)tlut_obj; - ASSERTMSGLINE(0x47B, tlut_obj, "TLut Object Pointer is null"); + ASSERTMSGLINE(0x47B+LINE_OFFSET, tlut_obj, "TLut Object Pointer is null"); return (void *)(GET_REG_FIELD(t->loadTlut0, 21, 0) << 5); } @@ -608,7 +630,7 @@ GXTlutFmt GXGetTlutObjFmt(const GXTlutObj *tlut_obj) { const __GXTlutObjInt *t = (const __GXTlutObjInt *)tlut_obj; - ASSERTMSGLINE(0x482, tlut_obj, "TLut Object Pointer is null"); + ASSERTMSGLINE(0x482+LINE_OFFSET, tlut_obj, "TLut Object Pointer is null"); return GET_REG_FIELD(t->tlut, 2, 10); } @@ -616,7 +638,7 @@ u16 GXGetTlutObjNumEntries(const GXTlutObj *tlut_obj) { const __GXTlutObjInt *t = (const __GXTlutObjInt *)tlut_obj; - ASSERTMSGLINE(0x489, tlut_obj, "TLut Object Pointer is null"); + ASSERTMSGLINE(0x489+LINE_OFFSET, tlut_obj, "TLut Object Pointer is null"); return t->numEntries; } @@ -626,17 +648,17 @@ void GXLoadTlut(GXTlutObj *tlut_obj, u32 tlut_name) u32 tlut_offset; __GXTlutObjInt *t = (__GXTlutObjInt *)tlut_obj; - ASSERTMSGLINE(0x4A4, tlut_obj, "TLut Object Pointer is null"); - CHECK_GXBEGIN(0x4A6, "GXLoadTlut"); - ASSERTMSGLINEV(0x4A7, gx->tlutRegionCallback, "%s: Tex/Tlut Region Callback not set", "GXLoadTlut"); + ASSERTMSGLINE(0x4A4+LINE_OFFSET, tlut_obj, "TLut Object Pointer is null"); + CHECK_GXBEGIN(0x4A6+LINE_OFFSET, "GXLoadTlut"); + ASSERTMSGLINEV(0x4A7+LINE_OFFSET, gx->tlutRegionCallback, "%s: Tex/Tlut Region Callback not set", "GXLoadTlut"); r = (__GXTlutRegionInt *)gx->tlutRegionCallback(tlut_name); - ASSERTMSGLINEV(0x4A9, r, "%s: Tex/Tlut Region Callback returns NULL", "GXLoadTlut"); + ASSERTMSGLINEV(0x4A9+LINE_OFFSET, r, "%s: Tex/Tlut Region Callback returns NULL", "GXLoadTlut"); __GXFlushTextureState(); GX_WRITE_RAS_REG(t->loadTlut0); GX_WRITE_RAS_REG(r->loadTlut1); __GXFlushTextureState(); tlut_offset = r->loadTlut1 & 0x3FF; - SET_REG_FIELD(0x4B9, t->tlut, 10, 0, tlut_offset); + SET_REG_FIELD(0x4B9+LINE_OFFSET, t->tlut, 10, 0, tlut_offset); r->tlutObj = *t; } @@ -645,10 +667,10 @@ void GXInitTexCacheRegion(GXTexRegion *region, u8 is_32b_mipmap, u32 tmem_even, u32 WidthExp2; __GXTexRegionInt *t = (__GXTexRegionInt *)region; - ASSERTMSGLINE(0x4D8, region, "TexRegion Object Pointer is null"); - CHECK_GXBEGIN(0x4DA, "GXInitTexCacheRegion"); - ASSERTMSGLINEV(0x4DC, (tmem_even & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTexCacheRegion", "tmem even"); - ASSERTMSGLINEV(0x4DE, (tmem_odd & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTexCacheRegion", "tmem odd"); + ASSERTMSGLINE(0x4D8+LINE_OFFSET, region, "TexRegion Object Pointer is null"); + CHECK_GXBEGIN(0x4DA+LINE_OFFSET, "GXInitTexCacheRegion"); + ASSERTMSGLINEV(0x4DC+LINE_OFFSET, (tmem_even & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTexCacheRegion", "tmem even"); + ASSERTMSGLINEV(0x4DE+LINE_OFFSET, (tmem_odd & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTexCacheRegion", "tmem odd"); switch (size_even) { case GX_TEXCACHE_32K: WidthExp2 = 3; @@ -660,13 +682,13 @@ void GXInitTexCacheRegion(GXTexRegion *region, u8 is_32b_mipmap, u32 tmem_even, WidthExp2 = 5; break; default: - ASSERTMSGLINEV(0x4E6, 0, "%s: Invalid %s size", "GXInitTexCacheRegion", "tmem even"); + ASSERTMSGLINEV(0x4E6+LINE_OFFSET, 0, "%s: Invalid %s size", "GXInitTexCacheRegion", "tmem even"); break; } t->image1 = 0; - SET_REG_FIELD(0x4EB, t->image1, 15, 0, tmem_even >> 5); - SET_REG_FIELD(0x4EC, t->image1, 3, 15, WidthExp2); - SET_REG_FIELD(0x4ED, t->image1, 3, 18, WidthExp2); + SET_REG_FIELD(0x4EB+LINE_OFFSET, t->image1, 15, 0, tmem_even >> 5); + SET_REG_FIELD(0x4EC+LINE_OFFSET, t->image1, 3, 15, WidthExp2); + SET_REG_FIELD(0x4ED+LINE_OFFSET, t->image1, 3, 18, WidthExp2); t->image1 &= 0xFFDFFFFF; switch (size_odd) { case GX_TEXCACHE_32K: @@ -682,13 +704,13 @@ void GXInitTexCacheRegion(GXTexRegion *region, u8 is_32b_mipmap, u32 tmem_even, WidthExp2 = 0; break; default: - ASSERTMSGLINEV(0x4F6, 0, "%s: Invalid %s size", "GXInitTexCacheRegion", "tmem odd"); + ASSERTMSGLINEV(0x4F6+LINE_OFFSET, 0, "%s: Invalid %s size", "GXInitTexCacheRegion", "tmem odd"); break; } t->image2 = 0; - SET_REG_FIELD(0x4FB, t->image2, 15, 0, tmem_odd >> 5); - SET_REG_FIELD(0x4FC, t->image2, 3, 15, WidthExp2); - SET_REG_FIELD(0x4FD, t->image2, 3, 18, WidthExp2); + SET_REG_FIELD(0x4FB+LINE_OFFSET, t->image2, 15, 0, tmem_odd >> 5); + SET_REG_FIELD(0x4FC+LINE_OFFSET, t->image2, 3, 15, WidthExp2); + SET_REG_FIELD(0x4FD+LINE_OFFSET, t->image2, 3, 18, WidthExp2); t->is32bMipmap = is_32b_mipmap; t->isCached = 1; } @@ -697,21 +719,21 @@ void GXInitTexPreLoadRegion(GXTexRegion *region, u32 tmem_even, u32 size_even, u { __GXTexRegionInt *t = (__GXTexRegionInt *)region; - ASSERTMSGLINE(0x51A, region, "TexRegion Object Pointer is null"); - CHECK_GXBEGIN(0x51C, "GXInitTexPreLoadRegion"); - ASSERTMSGLINEV(0x51E, (tmem_even & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTexPreLoadRegion", "tmem even"); - ASSERTMSGLINEV(0x520, (tmem_odd & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTexPreLoadRegion", "tmem odd"); - ASSERTMSGLINEV(0x522, (size_even & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTexPreLoadRegion", "size even"); - ASSERTMSGLINEV(0x524, (size_odd & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTexPreLoadRegion", "size odd"); + ASSERTMSGLINE(0x51A+LINE_OFFSET, region, "TexRegion Object Pointer is null"); + CHECK_GXBEGIN(0x51C+LINE_OFFSET, "GXInitTexPreLoadRegion"); + ASSERTMSGLINEV(0x51E+LINE_OFFSET, (tmem_even & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTexPreLoadRegion", "tmem even"); + ASSERTMSGLINEV(0x520+LINE_OFFSET, (tmem_odd & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTexPreLoadRegion", "tmem odd"); + ASSERTMSGLINEV(0x522+LINE_OFFSET, (size_even & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTexPreLoadRegion", "size even"); + ASSERTMSGLINEV(0x524+LINE_OFFSET, (size_odd & 0x1F) == 0, "%s: %s pointer not aligned to 32B", "GXInitTexPreLoadRegion", "size odd"); t->image1 = 0; - SET_REG_FIELD(0x528, t->image1, 15, 0, tmem_even >> 5); + SET_REG_FIELD(0x528+LINE_OFFSET, t->image1, 15, 0, tmem_even >> 5); t->image1 &= 0xFFFC7FFF; t->image1 &= 0xFFE3FFFF; t->image1 = (t->image1 & 0xFFDFFFFF) | 0x200000; t->image2 = 0; - SET_REG_FIELD(0x52E, t->image2, 15, 0, tmem_odd >> 5); + SET_REG_FIELD(0x52E+LINE_OFFSET, t->image2, 15, 0, tmem_odd >> 5); t->image2 &= 0xFFFC7FFF; t->image2 &= 0xFFE3FFFF; t->is32bMipmap = 0; @@ -724,7 +746,7 @@ void GXGetTexRegionAll(const GXTexRegion *region, u8 *is_cached, u8 *is_32b_mipm { const __GXTexRegionInt *t = (const __GXTexRegionInt *)region; - ASSERTMSGLINE(0x54D, region, "TexRegion Object Pointer is null"); + ASSERTMSGLINE(0x54D+LINE_OFFSET, region, "TexRegion Object Pointer is null"); *tmem_even = GET_REG_FIELD(t->image1, 15, 0) << 5; *tmem_odd = GET_REG_FIELD(t->image2, 15, 0) << 5; if (t->isCached) { @@ -768,22 +790,22 @@ void GXInitTlutRegion(GXTlutRegion *region, u32 tmem_addr, GXTlutSize tlut_size) { __GXTlutRegionInt *t = (__GXTlutRegionInt *)region; - ASSERTMSGLINE(0x580, region, "TLutRegion Object Pointer is null"); - CHECK_GXBEGIN(0x582, "GXInitTlutRegion"); - ASSERTMSGLINEV(0x583, (tmem_addr & 0x1FF) == 0, "%s: tmem pointer is not aligned to 512B", "GXInitTlutRegion"); - ASSERTMSGLINEV(0x584, tlut_size <= 0x400, "%s: tlut size exceeds 16K", "GXInitTlutRegion"); + ASSERTMSGLINE(0x580+LINE_OFFSET, region, "TLutRegion Object Pointer is null"); + CHECK_GXBEGIN(0x582+LINE_OFFSET, "GXInitTlutRegion"); + ASSERTMSGLINEV(0x583+LINE_OFFSET, (tmem_addr & 0x1FF) == 0, "%s: tmem pointer is not aligned to 512B", "GXInitTlutRegion"); + ASSERTMSGLINEV(0x584+LINE_OFFSET, tlut_size <= 0x400, "%s: tlut size exceeds 16K", "GXInitTlutRegion"); t->loadTlut1 = 0; tmem_addr -= 0x80000; - SET_REG_FIELD(0x588, t->loadTlut1, 10, 0, tmem_addr >> 9); - SET_REG_FIELD(0x589, t->loadTlut1, 11, 10, tlut_size); - SET_REG_FIELD(0x58A, t->loadTlut1, 8, 24, 0x65); + SET_REG_FIELD(0x588+LINE_OFFSET, t->loadTlut1, 10, 0, tmem_addr >> 9); + SET_REG_FIELD(0x589+LINE_OFFSET, t->loadTlut1, 11, 10, tlut_size); + SET_REG_FIELD(0x58A+LINE_OFFSET, t->loadTlut1, 8, 24, 0x65); } void GXGetTlutRegionAll(const GXTlutRegion *region, u32 *tmem_addr, GXTlutSize *tlut_size) { const __GXTlutRegionInt *t = (const __GXTlutRegionInt *)region; - ASSERTMSGLINE(0x59E, region, "TLutRegion Object Pointer is null"); + ASSERTMSGLINE(0x59E+LINE_OFFSET, region, "TLutRegion Object Pointer is null"); *tmem_addr = (GET_REG_FIELD(t->loadTlut1, 10, 0) << 9) + 0x80000; *tlut_size = GET_REG_FIELD(t->loadTlut1, 11, 10); } @@ -799,8 +821,8 @@ void GXInvalidateTexRegion(GXTexRegion *region) u32 reg1; __GXTexRegionInt *r = (__GXTexRegionInt *)region; - ASSERTMSGLINE(0x5B5, region, "TexRegion Object Pointer is null"); - CHECK_GXBEGIN(0x5B7, "GXInvalidateTexRegion"); + ASSERTMSGLINE(0x5B5+LINE_OFFSET, region, "TexRegion Object Pointer is null"); + CHECK_GXBEGIN(0x5B7+LINE_OFFSET, "GXInvalidateTexRegion"); wle = GET_REG_FIELD(r->image1, 3, 15) - 1; hle = GET_REG_FIELD(r->image1, 3, 18) - 1; @@ -823,18 +845,18 @@ void GXInvalidateTexRegion(GXTexRegion *region) count = wlo + hlo - 2 + count; } reg0 = 0; - SET_REG_FIELD(0x5C8, reg0, 9, 0, GET_REG_FIELD(r->image1, 9, 6)); - SET_REG_FIELD(0x5C9, reg0, 4, 9, count); - SET_REG_FIELD(0x5CA, reg0, 8, 24, 0x66); + SET_REG_FIELD(0x5C8+LINE_OFFSET, reg0, 9, 0, GET_REG_FIELD(r->image1, 9, 6)); + SET_REG_FIELD(0x5C9+LINE_OFFSET, reg0, 4, 9, count); + SET_REG_FIELD(0x5CA+LINE_OFFSET, reg0, 8, 24, 0x66); if (wlo != 0) { count = wlo + hlo; if (r->is32bMipmap) { count = wle + hle - 2 + count; } reg1 = 0; - SET_REG_FIELD(0x5D4, reg1, 9, 0, GET_REG_FIELD(r->image2, 9, 6)); - SET_REG_FIELD(0x5D5, reg1, 4, 9, count); - SET_REG_FIELD(0x5D6, reg1, 8, 24, 0x66); + SET_REG_FIELD(0x5D4+LINE_OFFSET, reg1, 9, 0, GET_REG_FIELD(r->image2, 9, 6)); + SET_REG_FIELD(0x5D5+LINE_OFFSET, reg1, 4, 9, count); + SET_REG_FIELD(0x5D6+LINE_OFFSET, reg1, 8, 24, 0x66); } __GXFlushTextureState(); GX_WRITE_RAS_REG(reg0); @@ -851,7 +873,7 @@ void GXInvalidateTexAll(void) u32 reg0; u32 reg1; - CHECK_GXBEGIN(0x5E7, "GXInvalidateTexAll"); + CHECK_GXBEGIN(0x5E7+LINE_OFFSET, "GXInvalidateTexAll"); reg0 = 0x66001000; reg1 = 0x66001100; __GXFlushTextureState(); @@ -905,31 +927,31 @@ void GXPreLoadEntireTexture(GXTexObj *tex_obj, GXTexRegion *region) __GXTexObjInt *t = (__GXTexObjInt *)tex_obj; __GXTexRegionInt *r = (__GXTexRegionInt *)region; - ASSERTMSGLINE(0x628, tex_obj, "Texture Object Pointer is null"); - ASSERTMSGLINE(0x628, region, "TexRegion Object Pointer is null"); - CHECK_GXBEGIN(0x62A, "GXPreLoadEntireTexture"); + ASSERTMSGLINE(0x628+LINE_OFFSET, tex_obj, "Texture Object Pointer is null"); + ASSERTMSGLINE(0x628+LINE_OFFSET, region, "TexRegion Object Pointer is null"); + CHECK_GXBEGIN(0x62A+LINE_OFFSET, "GXPreLoadEntireTexture"); isMipMap = (t->flags & 1) == 1; is32bit = GET_REG_FIELD(t->image0, 4, 20) == 6; loadImage0 = 0; SET_REG_FIELD(0, loadImage0, 8, 24, 0x60); base = t->image3 & 0x1FFFFF; - SET_REG_FIELD(0x633, loadImage0, 21, 0, base); + SET_REG_FIELD(0x633+LINE_OFFSET, loadImage0, 21, 0, base); loadImage1 = 0; SET_REG_FIELD(0, loadImage1, 8, 24, 0x61); tmem1 = r->image1 & 0x7FFF; - SET_REG_FIELD(0x639, loadImage1, 15, 0, tmem1); + SET_REG_FIELD(0x639+LINE_OFFSET, loadImage1, 15, 0, tmem1); loadImage2 = 0; SET_REG_FIELD(0, loadImage2, 8, 24, 0x62); tmem2 = r->image2 & 0x7FFF; - SET_REG_FIELD(0x63F, loadImage2, 15, 0, tmem2); + SET_REG_FIELD(0x63F+LINE_OFFSET, loadImage2, 15, 0, tmem2); loadImage3 = 0; SET_REG_FIELD(0, loadImage3, 8, 24, 0x63); - SET_REG_FIELD(0x644, loadImage3, 15, 0, t->loadCnt); - SET_REG_FIELD(0x645, loadImage3, 2, 15, t->loadFmt); + SET_REG_FIELD(0x644+LINE_OFFSET, loadImage3, 15, 0, t->loadCnt); + SET_REG_FIELD(0x645+LINE_OFFSET, loadImage3, 2, 15, t->loadFmt); maxLevelIndex = 0; nTiles = t->loadCnt; if (isMipMap != 0) { @@ -969,20 +991,20 @@ void GXPreLoadEntireTexture(GXTexObj *tex_obj, GXTexRegion *region) if (is32bit) { totalOdd = isMipMap ? totalOdd : 0; totalEven = totalEven + totalOdd; - ASSERTMSGLINE(0x66E, totalEven <= r->sizeEven, "GXPreLoadEntireTexture: Even tmem size does not match the texture size"); - ASSERTMSGLINE(0x66F, totalEven <= r->sizeOdd, "GXPreLoadEntireTexture: Odd tmem size does not match the texture size"); + ASSERTMSGLINE(0x66E+LINE_OFFSET, totalEven <= r->sizeEven, "GXPreLoadEntireTexture: Even tmem size does not match the texture size"); + ASSERTMSGLINE(0x66F+LINE_OFFSET, totalEven <= r->sizeOdd, "GXPreLoadEntireTexture: Odd tmem size does not match the texture size"); } else if (isMipMap != 0) { if (r->sizeEven > r->sizeOdd) { - ASSERTMSGLINE(0x674, totalEven <= r->sizeEven, "GXPreLoadEntireTexture: Even tmem size does not match the texture size"); - ASSERTMSGLINE(0x675, totalOdd <= r->sizeOdd, "GXPreLoadEntireTexture: Odd tmem size does not match the texture size"); + ASSERTMSGLINE(0x674+LINE_OFFSET, totalEven <= r->sizeEven, "GXPreLoadEntireTexture: Even tmem size does not match the texture size"); + ASSERTMSGLINE(0x675+LINE_OFFSET, totalOdd <= r->sizeOdd, "GXPreLoadEntireTexture: Odd tmem size does not match the texture size"); } else { - ASSERTMSGLINE(0x678, totalEven <= r->sizeOdd, "GXPreLoadEntireTexture: Odd tmem size does not match the texture size"); - ASSERTMSGLINE(0x679, totalOdd <= r->sizeEven, "GXPreLoadEntireTexture: Even tmem size does not match the texture size"); + ASSERTMSGLINE(0x678+LINE_OFFSET, totalEven <= r->sizeOdd, "GXPreLoadEntireTexture: Odd tmem size does not match the texture size"); + ASSERTMSGLINE(0x679+LINE_OFFSET, totalOdd <= r->sizeEven, "GXPreLoadEntireTexture: Even tmem size does not match the texture size"); } } else if (r->sizeEven > r->sizeOdd) { - ASSERTMSGLINE(0x67E, totalEven <= r->sizeEven, "GXPreLoadEntireTexture: Even tmem size does not match the texture size"); + ASSERTMSGLINE(0x67E+LINE_OFFSET, totalEven <= r->sizeEven, "GXPreLoadEntireTexture: Even tmem size does not match the texture size"); } else { - ASSERTMSGLINE(0x680, totalOdd <= r->sizeOdd, "GXPreLoadEntireTexture: Odd tmem size does not match the texture size"); + ASSERTMSGLINE(0x680+LINE_OFFSET, totalOdd <= r->sizeOdd, "GXPreLoadEntireTexture: Odd tmem size does not match the texture size"); } #endif __GXFlushTextureState(); @@ -1010,10 +1032,10 @@ void GXPreLoadEntireTexture(GXTexObj *tex_obj, GXTexRegion *region) tmem2 = (i & 1) ? tmemGB : tmemAR; __GetImageTileCount(t->fmt, (u16) (wd >> (i + 1)), (u16) (ht >> (i + 1)), &rowTiles, &colTiles, &cmpTiles); nTiles = rowTiles * colTiles; - SET_REG_FIELD(0x6B1, loadImage0, 21, 0, base); - SET_REG_FIELD(0x6B2, loadImage1, 15, 0, tmem1); - SET_REG_FIELD(0x6B3, loadImage2, 15, 0, tmem2); - SET_REG_FIELD(0x6B4, loadImage3, 15, 0, nTiles); + SET_REG_FIELD(0x6B1+LINE_OFFSET, loadImage0, 21, 0, base); + SET_REG_FIELD(0x6B2+LINE_OFFSET, loadImage1, 15, 0, tmem1); + SET_REG_FIELD(0x6B3+LINE_OFFSET, loadImage2, 15, 0, tmem2); + SET_REG_FIELD(0x6B4+LINE_OFFSET, loadImage3, 15, 0, nTiles); GX_WRITE_RAS_REG(loadImage0); GX_WRITE_RAS_REG(loadImage1); GX_WRITE_RAS_REG(loadImage2); @@ -1029,41 +1051,53 @@ void GXPreLoadEntireTexture(GXTexObj *tex_obj, GXTexRegion *region) void GXSetTexCoordScaleManually(GXTexCoordID coord, u8 enable, u16 ss, u16 ts) { - CHECK_GXBEGIN(0x6D1, "GXSetTexCoordScaleManually"); - ASSERTMSGLINEV(0x6D3, coord < 8, "%s: bad texcoord specified", "GXSetTexCoordScaleManually"); + CHECK_GXBEGIN(0x6D1+LINE_OFFSET, "GXSetTexCoordScaleManually"); + ASSERTMSGLINEV(0x6D3+LINE_OFFSET, coord < 8, "%s: bad texcoord specified", "GXSetTexCoordScaleManually"); gx->tcsManEnab = (gx->tcsManEnab & ~(1 << coord)) | (enable << coord); if (enable != 0) { - SET_REG_FIELD(0x6D9, gx->suTs0[coord], 16, 0, (u16)(ss - 1)); - SET_REG_FIELD(0x6DA, gx->suTs1[coord], 16, 0, (u16)(ts - 1)); + SET_REG_FIELD(0x6D9+LINE_OFFSET, gx->suTs0[coord], 16, 0, (u16)(ss - 1)); + SET_REG_FIELD(0x6DA+LINE_OFFSET, gx->suTs1[coord], 16, 0, (u16)(ts - 1)); GX_WRITE_RAS_REG(gx->suTs0[coord]); GX_WRITE_RAS_REG(gx->suTs1[coord]); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } } void GXSetTexCoordCylWrap(GXTexCoordID coord, u8 s_enable, u8 t_enable) { - CHECK_GXBEGIN(0x6F3, "GXSetTexCoordCylWrap"); - ASSERTMSGLINEV(0x6F5, coord < 8, "%s: bad texcoord specified", "GXSetTexCoordCylWrap"); - SET_REG_FIELD(0x6F7, gx->suTs0[coord], 1, 17, s_enable); - SET_REG_FIELD(0x6F8, gx->suTs1[coord], 1, 17, t_enable); + CHECK_GXBEGIN(0x6F3+LINE_OFFSET, "GXSetTexCoordCylWrap"); + ASSERTMSGLINEV(0x6F5+LINE_OFFSET, coord < 8, "%s: bad texcoord specified", "GXSetTexCoordCylWrap"); + SET_REG_FIELD(0x6F7+LINE_OFFSET, gx->suTs0[coord], 1, 17, s_enable); + SET_REG_FIELD(0x6F8+LINE_OFFSET, gx->suTs1[coord], 1, 17, t_enable); if (gx->tcsManEnab & (1 << coord)) { GX_WRITE_RAS_REG(gx->suTs0[coord]); GX_WRITE_RAS_REG(gx->suTs1[coord]); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } } void GXSetTexCoordBias(GXTexCoordID coord, u8 s_enable, u8 t_enable) { - CHECK_GXBEGIN(0x712, "GXSetTexCoordBias"); - ASSERTMSGLINEV(0x714, coord < 8, "%s: bad texcoord specified", "GXSetTexCoordBias"); - SET_REG_FIELD(0x716, gx->suTs0[coord], 1, 16, s_enable); - SET_REG_FIELD(0x717, gx->suTs1[coord], 1, 16, t_enable); + CHECK_GXBEGIN(0x712+LINE_OFFSET, "GXSetTexCoordBias"); + ASSERTMSGLINEV(0x714+LINE_OFFSET, coord < 8, "%s: bad texcoord specified", "GXSetTexCoordBias"); + SET_REG_FIELD(0x716+LINE_OFFSET, gx->suTs0[coord], 1, 16, s_enable); + SET_REG_FIELD(0x717+LINE_OFFSET, gx->suTs1[coord], 1, 16, t_enable); if (gx->tcsManEnab & (1 << coord)) { GX_WRITE_RAS_REG(gx->suTs0[coord]); GX_WRITE_RAS_REG(gx->suTs1[coord]); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } } @@ -1076,15 +1110,19 @@ static void __SetSURegs(u32 tmap, u32 tcoord) w = GET_REG_FIELD(gx->tImage0[tmap], 10, 0); h = GET_REG_FIELD(gx->tImage0[tmap], 10, 10); - SET_REG_FIELD(0x735, gx->suTs0[tcoord], 16, 0, w); - SET_REG_FIELD(0x736, gx->suTs1[tcoord], 16, 0, h); + SET_REG_FIELD(0x735+LINE_OFFSET, gx->suTs0[tcoord], 16, 0, w); + SET_REG_FIELD(0x736+LINE_OFFSET, gx->suTs1[tcoord], 16, 0, h); s_bias = GET_REG_FIELD(gx->tMode0[tmap], 2, 0) == 1; t_bias = GET_REG_FIELD(gx->tMode0[tmap], 2, 2) == 1; - SET_REG_FIELD(0x73C, gx->suTs0[tcoord], 1, 16, s_bias); - SET_REG_FIELD(0x73D, gx->suTs1[tcoord], 1, 16, t_bias); + SET_REG_FIELD(0x73C+LINE_OFFSET, gx->suTs0[tcoord], 1, 16, s_bias); + SET_REG_FIELD(0x73D+LINE_OFFSET, gx->suTs1[tcoord], 1, 16, t_bias); GX_WRITE_RAS_REG(gx->suTs0[tcoord]); GX_WRITE_RAS_REG(gx->suTs1[tcoord]); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void __GXSetSUTexRegs(void) @@ -1145,3 +1183,96 @@ void __GXGetSUTexSize(GXTexCoordID coord, u16 *width, u16 *height) *width = (u16)gx->suTs0[coord] + 1; *height = (u16)gx->suTs1[coord] + 1; } + +#if DOLPHIN_REVISION >= 45 +void __GXSetTmemConfig(u32 config) { + switch (config) { + case 1: + GX_WRITE_RAS_REG(0x8C0D8000); + GX_WRITE_RAS_REG(0x900DC000); + GX_WRITE_RAS_REG(0x8D0D8800); + GX_WRITE_RAS_REG(0x910DC800); + GX_WRITE_RAS_REG(0x8E0D9000); + GX_WRITE_RAS_REG(0x920DD000); + GX_WRITE_RAS_REG(0x8F0D9800); + GX_WRITE_RAS_REG(0x930DD800); + GX_WRITE_RAS_REG(0xAC0DA000); + GX_WRITE_RAS_REG(0xB00DE000); + GX_WRITE_RAS_REG(0xAD0DA800); + GX_WRITE_RAS_REG(0xB10DE800); + GX_WRITE_RAS_REG(0xAE0DB000); + GX_WRITE_RAS_REG(0xB20DF000); + GX_WRITE_RAS_REG(0xAF0DB800); + GX_WRITE_RAS_REG(0xB30DF800); + break; + default: + case 0: + GX_WRITE_RAS_REG(0x8C0D8000); + GX_WRITE_RAS_REG(0x900DC000); + GX_WRITE_RAS_REG(0x8D0D8400); + GX_WRITE_RAS_REG(0x910DC400); + GX_WRITE_RAS_REG(0x8E0D8800); + GX_WRITE_RAS_REG(0x920DC800); + GX_WRITE_RAS_REG(0x8F0D8C00); + GX_WRITE_RAS_REG(0x930DCC00); + GX_WRITE_RAS_REG(0xAC0D9000); + GX_WRITE_RAS_REG(0xB00DD000); + GX_WRITE_RAS_REG(0xAD0D9400); + GX_WRITE_RAS_REG(0xB10DD400); + GX_WRITE_RAS_REG(0xAE0D9800); + GX_WRITE_RAS_REG(0xB20DD800); + GX_WRITE_RAS_REG(0xAF0D9C00); + GX_WRITE_RAS_REG(0xB30DDC00); + break; +/* + *(void *)0xCC008000 = 0x61; + *(void *)0xCC008000 = 0x8C0D8000; + __gxVerif->unkEF8 = 0x8C0D8000; + *(void *)0xCC008000 = 0x61; + *(void *)0xCC008000 = 0x900DC000; + __gxVerif->unkF08 = 0x900DC000; + *(void *)0xCC008000 = 0x61; + *(void *)0xCC008000 = 0x8D0D8800; + __gxVerif->unkEFC = 0x8D0D8800; + *(void *)0xCC008000 = 0x61; + *(void *)0xCC008000 = 0x910DC800; + __gxVerif->unkF0C = 0x910DC800; + *(void *)0xCC008000 = 0x61; + *(void *)0xCC008000 = 0x8E0D9000; + __gxVerif->unkF00 = 0x8E0D9000; + *(void *)0xCC008000 = 0x61; + *(void *)0xCC008000 = 0x920DD000; + __gxVerif->unkF10 = 0x920DD000; + *(void *)0xCC008000 = 0x61; + *(void *)0xCC008000 = 0x8F0D9800; + __gxVerif->unkF04 = 0x8F0D9800; + *(void *)0xCC008000 = 0x61; + *(void *)0xCC008000 = 0x930DD800; + __gxVerif->unkF14 = 0x930DD800; + *(void *)0xCC008000 = 0x61; + *(void *)0xCC008000 = 0xAC0DA000; + __gxVerif->unkF78 = 0xAC0DA000; + *(void *)0xCC008000 = 0x61; + *(void *)0xCC008000 = 0xB00DE000; + __gxVerif->unkF88 = 0xB00DE000; + *(void *)0xCC008000 = 0x61; + *(void *)0xCC008000 = 0xAD0DA800; + __gxVerif->unkF7C = 0xAD0DA800; + *(void *)0xCC008000 = 0x61; + *(void *)0xCC008000 = 0xB10DE800; + __gxVerif->unkF8C = 0xB10DE800; + *(void *)0xCC008000 = 0x61; + *(void *)0xCC008000 = 0xAE0DB000; + __gxVerif->unkF80 = 0xAE0DB000; + *(void *)0xCC008000 = 0x61; + *(void *)0xCC008000 = 0xB20DF000; + __gxVerif->unkF90 = 0xB20DF000; + *(void *)0xCC008000 = 0x61; + *(void *)0xCC008000 = 0xAF0DB800; + __gxVerif->unkF84 = 0xAF0DB800; + *(void *)0xCC008000 = 0x61; + *(void *)0xCC008000 = 0xB30DF800; + __gxVerif->unkF94 = 0xB30DF800;*/ + } +} +#endif diff --git a/src/gx/GXTransform.c b/src/gx/GXTransform.c index 3c8d2a4..549e759 100644 --- a/src/gx/GXTransform.c +++ b/src/gx/GXTransform.c @@ -63,7 +63,11 @@ void GXSetProjection(f32 mtx[4][4], GXProjectionType type) GX_WRITE_XF_REG_F(36, gx->projMtx[4]); GX_WRITE_XF_REG_F(37, gx->projMtx[5]); GX_WRITE_XF_REG_2(38, gx->projType); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 1; +#else gx->bpSent = 0; +#endif } void GXSetProjectionv(f32 *ptr) @@ -90,7 +94,11 @@ void GXSetProjectionv(f32 *ptr) GX_WRITE_XF_REG_F(36, gx->projMtx[4]); GX_WRITE_XF_REG_F(37, gx->projMtx[5]); GX_WRITE_XF_REG_2(38, gx->projType); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 1; +#else gx->bpSent = 0; +#endif } #define qr0 0 @@ -420,7 +428,11 @@ void GXSetViewportJitter(f32 left, f32 top, f32 wd, f32 ht, f32 nearz, f32 farz, GX_WRITE_XF_REG_F(29, ox); GX_WRITE_XF_REG_F(30, oy); GX_WRITE_XF_REG_F(31, oz); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 1; +#else gx->bpSent = 0; +#endif } void GXSetViewport(f32 left, f32 top, f32 wd, f32 ht, f32 nearz, f32 farz) @@ -440,6 +452,14 @@ void GXGetViewportv(f32 *vp) vp[5] = gx->vpFarz; } +#if DOLPHIN_REVISION >= 45 +#define SCISSOR_MAX 1706 +#define SCISSOR_WIDTH 342 +#else +#define SCISSOR_MAX 1708 +#define SCISSOR_WIDTH 340 +#endif + void GXSetScissor(u32 left, u32 top, u32 wd, u32 ht) { u32 tp; @@ -449,13 +469,14 @@ void GXSetScissor(u32 left, u32 top, u32 wd, u32 ht) CHECK_GXBEGIN(0x3B4, "GXSetScissor"); - ASSERTMSGLINE(0x3B5, left < 1708, "GXSetScissor: Left origin > 1708"); - ASSERTMSGLINE(0x3B6, top < 1708, "GXSetScissor: top origin > 1708"); - ASSERTMSGLINE(0x3B7, left + wd < 1708, "GXSetScissor: right edge > 1708"); - ASSERTMSGLINE(0x3B8, top + ht < 1708, "GXSetScissor: bottom edge > 1708"); + // BUG: message still says 1708, even when the max is 1706 + ASSERTMSGLINE(0x3B5, left < SCISSOR_MAX, "GXSetScissor: Left origin > 1708"); + ASSERTMSGLINE(0x3B6, top < SCISSOR_MAX, "GXSetScissor: top origin > 1708"); + ASSERTMSGLINE(0x3B7, left + wd < SCISSOR_MAX, "GXSetScissor: right edge > 1708"); + ASSERTMSGLINE(0x3B8, top + ht < SCISSOR_MAX, "GXSetScissor: bottom edge > 1708"); - tp = top + 340; - lf = left + 340; + tp = top + SCISSOR_WIDTH; + lf = left + SCISSOR_WIDTH; bm = tp + ht - 1; rt = lf + wd - 1; @@ -466,7 +487,11 @@ void GXSetScissor(u32 left, u32 top, u32 wd, u32 ht) GX_WRITE_RAS_REG(gx->suScis0); GX_WRITE_RAS_REG(gx->suScis1); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXGetScissor(u32 *left, u32 *top, u32 *wd, u32 *ht) @@ -483,8 +508,8 @@ void GXGetScissor(u32 *left, u32 *top, u32 *wd, u32 *ht) bm = gx->suScis1 & 0x7FF; rt = (gx->suScis1 & 0x7FF000) >> 12; - *left = lf - 340; - *top = tp - 340; + *left = lf - SCISSOR_WIDTH; + *top = tp - SCISSOR_WIDTH; *wd = rt - lf + 1; *ht = bm - tp + 1; } @@ -497,24 +522,32 @@ void GXSetScissorBoxOffset(s32 x_off, s32 y_off) CHECK_GXBEGIN(0x3FB, "GXSetScissorBoxOffset"); - ASSERTMSGLINE(0x3FE, (u32)(x_off + 340) < 2048, "GXSetScissorBoxOffset: x offset > 2048"); - ASSERTMSGLINE(0x400, (u32)(y_off + 340) < 2048, "GXSetScissorBoxOffset: y offset > 2048"); + ASSERTMSGLINE(0x3FE, (u32)(x_off + SCISSOR_WIDTH) < 2048, "GXSetScissorBoxOffset: x offset > 2048"); + ASSERTMSGLINE(0x400, (u32)(y_off + SCISSOR_WIDTH) < 2048, "GXSetScissorBoxOffset: y offset > 2048"); - hx = (u32)(x_off + 340) >> 1; - hy = (u32)(y_off + 340) >> 1; + hx = (u32)(x_off + SCISSOR_WIDTH) >> 1; + hy = (u32)(y_off + SCISSOR_WIDTH) >> 1; SET_REG_FIELD(0x405, reg, 10, 0, hx); SET_REG_FIELD(0x406, reg, 10, 10, hy); SET_REG_FIELD(0x407, reg, 8, 24, 0x59); GX_WRITE_RAS_REG(reg); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 0; +#else gx->bpSent = 1; +#endif } void GXSetClipMode(GXClipMode mode) { CHECK_GXBEGIN(0x41B, "GXSetClipMode"); GX_WRITE_XF_REG(5, mode); +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 1; +#else gx->bpSent = 0; +#endif } void __GXSetMatrixIndex(GXAttr matIdxAttr) @@ -526,5 +559,9 @@ void __GXSetMatrixIndex(GXAttr matIdxAttr) GX_WRITE_SOME_REG4(8, 0x40, gx->matIdxB, -12); GX_WRITE_XF_REG(25, gx->matIdxB); } +#if DOLPHIN_REVISION >= 45 + gx->bpSentNot = 1; +#else gx->bpSent = 0; +#endif } diff --git a/src/gx/GXVerifXF.c b/src/gx/GXVerifXF.c index 1fd625e..3368f9b 100644 --- a/src/gx/GXVerifXF.c +++ b/src/gx/GXVerifXF.c @@ -72,7 +72,11 @@ static void CountTextureTypes(void) } else if (texgen_type == 3) { numColor1Textures++; } else { +#if DOLPHIN_REVISION >= 45 + if (__gxVerif->verifyLevel >= __gxvWarnLev[GXWARN_INVALID_TG_TYPE]) { +#else if (__gxVerif->verifyLevel >= 1) { +#endif __GX_WARNF(GXWARN_INVALID_TG_TYPE, texgen_type, i); } } @@ -87,14 +91,22 @@ static void InitializeXFVerifyData(void) static void CheckDirty(u32 index, const char *name) { +#if DOLPHIN_REVISION >= 45 + if (!__gxVerif->xfRegsDirty[index - 0x1000] && __gxVerif->verifyLevel >= __gxvWarnLev[GXWARN_XF_CTRL_UNINIT]) { +#else if (__gxVerif->verifyLevel >= 1 && !__gxVerif->xfRegsDirty[index - 0x1000]) { +#endif __GX_WARNF(GXWARN_XF_CTRL_UNINIT, index, name); } } static void CheckClean(u32 index, const char *name) { +#if DOLPHIN_REVISION >= 45 + if (__gxVerif->xfRegsDirty[index - 0x1000] && __gxVerif->verifyLevel >= __gxvWarnLev[GXWARN_XF_CTRL_INIT]) { +#else if (__gxVerif->verifyLevel >= 1 && __gxVerif->xfRegsDirty[index - 0x1000]) { +#endif __GX_WARNF(GXWARN_XF_CTRL_INIT, index, name); } } @@ -104,14 +116,14 @@ static void CheckCTGColors(void) if (BYTE3(__gxVerif->xfRegs[9]) & 3) { if ((u32)(BYTE3(__gxVerif->xfRegs[9]) & 3) == 1) { if (numColorTextures != 0 && numColorTextures != 1) { - __GX_WARNF(GXWARN_INV_COLOR_TG_COMB, (u8)(BYTE3(__gxVerif->xfRegs[9]) & 3), numColorTextures); + __GX_WARNF_CHECKED(GXWARN_INV_COLOR_TG_COMB, (u8)(BYTE3(__gxVerif->xfRegs[9]) & 3), numColorTextures); } } else if ((u32)(BYTE3(__gxVerif->xfRegs[9]) & 3) == 2) { if (numColorTextures != 0 && numColorTextures != 2) { - __GX_WARNF(GXWARN_INV_COLOR_TG_COMB, (u8)(BYTE3(__gxVerif->xfRegs[9]) & 3), numColorTextures); + __GX_WARNF_CHECKED(GXWARN_INV_COLOR_TG_COMB, (u8)(BYTE3(__gxVerif->xfRegs[9]) & 3), numColorTextures); } } else { - __GX_WARNF(GXWARN_INV_NUM_COLORS, (u8)(BYTE3(__gxVerif->xfRegs[9]) & 3)); + __GX_WARNF_CHECKED(GXWARN_INV_NUM_COLORS, (u8)(BYTE3(__gxVerif->xfRegs[9]) & 3)); } } } @@ -152,52 +164,52 @@ static void CheckVertexPacket(void) u32 i; if (!__GXVertexPacketHas(GX_VA_POS)) { - __GX_WARN(GXWARN_VTX_NO_GEOM); + __GX_WARN_CHECKED(GXWARN_VTX_NO_GEOM); } if ((BYTE3(__gxVerif->xfRegs[8]) & 3) == 0) { if (__GXVertexPacketHas(GX_VA_CLR0) || __GXVertexPacketHas(GX_VA_CLR1)) { - __GX_WARN(GXWARN_CLR_XF0_CP1); + __GX_WARN_CHECKED(GXWARN_CLR_XF0_CP1); } } else if ((u32)(BYTE3(__gxVerif->xfRegs[8]) & 3) == 1) { if (!__GXVertexPacketHas(GX_VA_CLR0)) { - __GX_WARN(GXWARN_CLR_XF1_CP0); + __GX_WARN_CHECKED(GXWARN_CLR_XF1_CP0); } if (__GXVertexPacketHas(GX_VA_CLR1)) { - __GX_WARN(GXWARN_CLR_XF1_CP2); + __GX_WARN_CHECKED(GXWARN_CLR_XF1_CP2); } } else if ((u32)(BYTE3(__gxVerif->xfRegs[8]) & 3) == 2) { if (!__GXVertexPacketHas(GX_VA_CLR0)) { - __GX_WARN(GXWARN_CLR_XF2_CPN1); + __GX_WARN_CHECKED(GXWARN_CLR_XF2_CPN1); } if (!__GXVertexPacketHas(GX_VA_CLR1)) { - __GX_WARN(GXWARN_CLR_XF2_CPN2); + __GX_WARN_CHECKED(GXWARN_CLR_XF2_CPN2); } } else { - __GX_WARNF(GXWARN_INV_IVS_CLR, (u8)(BYTE3(__gxVerif->xfRegs[8]) & 3)); + __GX_WARNF_CHECKED(GXWARN_INV_IVS_CLR, (u8)(BYTE3(__gxVerif->xfRegs[8]) & 3)); } if (((BYTE3(__gxVerif->xfRegs[8]) >> 2) & 3) == 0) { if (__GXVertexPacketHas(GX_VA_NRM)) { - __GX_WARN(GXWARN_NRM_XF0_CP1); + __GX_WARN_CHECKED(GXWARN_NRM_XF0_CP1); } if (__GXVertexPacketHas(GX_VA_NBT)) { - __GX_WARN(GXWARN_NRM_XF0_CP3); + __GX_WARN_CHECKED(GXWARN_NRM_XF0_CP3); } } else if ((u32)((BYTE3(__gxVerif->xfRegs[8]) >> 2) & 3) == 1) { if (!__GXVertexPacketHas(GX_VA_NRM)) { - __GX_WARN(GXWARN_NRM_XF1_CP0); + __GX_WARN_CHECKED(GXWARN_NRM_XF1_CP0); } if (__GXVertexPacketHas(GX_VA_NBT)) { - __GX_WARN(GXWARN_NRM_XF1_CP3); + __GX_WARN_CHECKED(GXWARN_NRM_XF1_CP3); } } else if ((u32)((BYTE3(__gxVerif->xfRegs[8]) >> 2) & 3) == 2) { if (__GXVertexPacketHas(GX_VA_NRM)) { - __GX_WARN(GXWARN_NRM_XF3_CP1); + __GX_WARN_CHECKED(GXWARN_NRM_XF3_CP1); } if (!__GXVertexPacketHas(GX_VA_NBT)) { - __GX_WARN(GXWARN_NRM_XF3_CP0); + __GX_WARN_CHECKED(GXWARN_NRM_XF3_CP0); } } else { - __GX_WARNF(GXWARN_INV_IVS_NRM, (u8)((BYTE3(__gxVerif->xfRegs[8]) >> 2) & 3)); + __GX_WARNF_CHECKED(GXWARN_INV_IVS_NRM, (u8)((BYTE3(__gxVerif->xfRegs[8]) >> 2) & 3)); } numHostTextures = 0; for (i = 0; i <= 7; i++) { @@ -206,7 +218,7 @@ static void CheckVertexPacket(void) } } if (numHostTextures != (u32)((BYTE3(__gxVerif->xfRegs[8]) >> 4) & 0xF)) { - __GX_WARNF(GXWARN_TEX_XFN_CPM, (u8)((BYTE3(__gxVerif->xfRegs[8]) >> 4) & 0xF), numHostTextures); + __GX_WARNF_CHECKED(GXWARN_TEX_XFN_CPM, (u8)((BYTE3(__gxVerif->xfRegs[8]) >> 4) & 0xF), numHostTextures); } } @@ -218,26 +230,26 @@ static void CheckSourceRows(void) switch ((HIWORD(__gxVerif->xfRegs[i + 64]) >> 7) & 0x1F) { case 0: if (!__GXVertexPacketHas(GX_VA_POS)) { - __GX_WARNF(GXWARN_TEX_SRC_NPOS, i); + __GX_WARNF_CHECKED(GXWARN_TEX_SRC_NPOS, i); } break; case 1: if (!__GXVertexPacketHas(GX_VA_NRM) && !__GXVertexPacketHas(GX_VA_NBT)) { - __GX_WARNF(GXWARN_TEX_SRC_NNRM, i); + __GX_WARNF_CHECKED(GXWARN_TEX_SRC_NNRM, i); } break; case 2: if (!__GXVertexPacketHas(GX_VA_CLR0)) { - __GX_WARNF(GXWARN_TEX_SRC_NCLR0, i); + __GX_WARNF_CHECKED(GXWARN_TEX_SRC_NCLR0, i); } if (!__GXVertexPacketHas(GX_VA_CLR1)) { - __GX_WARNF(GXWARN_TEX_SRC_NCLR1, i); + __GX_WARNF_CHECKED(GXWARN_TEX_SRC_NCLR1, i); } break; case 3: case 4: if (!__GXVertexPacketHas(GX_VA_NBT)) { - __GX_WARNF(GXWARN_TEX_SRC_NNBT, i); + __GX_WARNF_CHECKED(GXWARN_TEX_SRC_NNBT, i); } break; case 5: @@ -249,11 +261,11 @@ static void CheckSourceRows(void) case 11: case 12: if (!__GXVertexPacketHas(TextureEnums[((HIWORD(__gxVerif->xfRegs[i + 64]) >> 7) & 0x1F) - 5])) { - __GX_WARNF(GXWARN_TEX_SRC_NTEX, i, ((HIWORD(__gxVerif->xfRegs[i + 64]) >> 7) & 0x1F) - 5); + __GX_WARNF_CHECKED(GXWARN_TEX_SRC_NTEX, i, ((HIWORD(__gxVerif->xfRegs[i + 64]) >> 7) & 0x1F) - 5); } break; default: - __GX_WARNF(GXWARN_INV_TEX_SRC, i, (u8)((HIWORD(__gxVerif->xfRegs[i + 64]) >> 7) & 0x1F)); + __GX_WARNF_CHECKED(GXWARN_INV_TEX_SRC, i, (u8)((HIWORD(__gxVerif->xfRegs[i + 64]) >> 7) & 0x1F)); break; } } @@ -278,7 +290,7 @@ static void CheckTextureOrder(void) done = 1; } else if ((u32)((BYTE3(__gxVerif->xfRegs[count + 64]) >> 4) & 7) != 1) { if (!((BYTE3(__gxVerif->xfRegs[count + 64]) >> 4) & 7)) { - __GX_WARN(GXWARN_INV_TG_ORDER); + __GX_WARN_CHECKED(GXWARN_INV_TG_ORDER); } done = 1; } else { @@ -291,7 +303,7 @@ static void CheckTextureOrder(void) if (count == __gxVerif->xfRegs[0x3F]) { done = 1; } else if (!((BYTE3(__gxVerif->xfRegs[count + 64]) >> 4) & 7) || (u32)((BYTE3(__gxVerif->xfRegs[count + 64]) >> 4) & 7) == 1) { - __GX_WARN(GXWARN_INV_TG_ORDER); + __GX_WARN_CHECKED(GXWARN_INV_TG_ORDER); done = 1; } else { count += 1; @@ -313,6 +325,15 @@ static void CheckRAM(u8 Normal, u32 StartingAddress, u32 Count, s32 WarnID, char } else { dirtyBit = __gxVerif->xfMtxDirty[i]; } +#if DOLPHIN_REVISION >= 45 + if (dirtyBit == 0 && printedPreamble == 0) { + if (__gxVerif->verifyLevel >= __gxvWarnLev[WarnID]) { + __gxVerif->cb(__gxvWarnLev[WarnID], WarnID, Str); + } + printedPreamble = 1; + WarnID; printedPreamble; // needed to match + } +#else if (dirtyBit == 0) { if (printedPreamble == 0) { __gxVerif->cb(1, WarnID, Str); @@ -320,6 +341,7 @@ static void CheckRAM(u8 Normal, u32 StartingAddress, u32 Count, s32 WarnID, char } __GX_WARNF(GXWARN_ADDR_UNINIT, i); } +#endif } } @@ -333,7 +355,7 @@ static void CheckBumpmapTextures(void) if (!__GXVertexPacketHas(GX_VA_PNMTXIDX)) { if ((u32)(BYTE3(__gxVerif->xfRegs[24]) & 0x3F) > 30) { - __GX_WARNF(0x50, (u8)(BYTE3(__gxVerif->xfRegs[24]) & 0x3F)); + __GX_WARNF_CHECKED(0x50, (u8)(BYTE3(__gxVerif->xfRegs[24]) & 0x3F)); } sprintf(Preamble, __gxvWarnings[0x6A], (u8)(BYTE3(__gxVerif->xfRegs[24]) & 0x3F)); CheckRAM(1, ((BYTE3(__gxVerif->xfRegs[24]) & 0x3F) * 3) + 0x400, 9U, 0x6A, Preamble); @@ -343,22 +365,38 @@ static void CheckBumpmapTextures(void) BumpMapSource = BYTE2(__gxVerif->xfRegs[numRegularTextures + i + 64]); BumpMapSource = (BumpMapSource >> 4) & 7; if ((BYTE3(__gxVerif->xfRegs[BumpMapSource + 64]) >> 4) & 7) { - __GX_WARNF(0x51, i, i + numRegularTextures, BumpMapSource); +#if DOLPHIN_REVISION >= 45 + __GX_WARNF_CHECKED(0x51, i + numRegularTextures, BumpMapSource); +#else + __GX_WARNF_CHECKED(0x51, i, i + numRegularTextures, BumpMapSource); +#endif } BumpMapLight = __gxVerif->xfRegs[numRegularTextures + i + 0x40]; BumpMapLight = (BumpMapLight >> 15) & 7; lightRAMOffset = (BumpMapLight * 0x10) + 0x60A; if (!__gxVerif->xfLightDirty[lightRAMOffset - 0x600 + 0]) { - __GX_WARNF(0x52, i, i + numRegularTextures, BumpMapLight, "X"); +#if DOLPHIN_REVISION >= 45 + __GX_WARNF_CHECKED(0x52, i + numRegularTextures, BumpMapLight, "X"); +#else + __GX_WARNF_CHECKED(0x52, i, i + numRegularTextures, BumpMapLight, "X"); +#endif } if (!__gxVerif->xfLightDirty[lightRAMOffset - 0x600 + 1]) { - __GX_WARNF(0x52, i, i + numRegularTextures, BumpMapLight, "Y"); +#if DOLPHIN_REVISION >= 45 + __GX_WARNF_CHECKED(0x52, i + numRegularTextures, BumpMapLight, "Y"); +#else + __GX_WARNF_CHECKED(0x52, i, i + numRegularTextures, BumpMapLight, "Y"); +#endif } if (!__gxVerif->xfLightDirty[lightRAMOffset - 0x600 + 2]) { - __GX_WARNF(0x52, i, i + numRegularTextures, BumpMapLight, "Z"); +#if DOLPHIN_REVISION >= 45 + __GX_WARNF_CHECKED(0x52, i + numRegularTextures, BumpMapLight, "Z"); +#else + __GX_WARNF_CHECKED(0x52, i, i + numRegularTextures, BumpMapLight, "Z"); +#endif } if (!__GXVertexPacketHas(GX_VA_NBT)) { - __GX_WARNF(0x53, i); + __GX_WARNF_CHECKED(0x53, i); } } @@ -426,10 +464,14 @@ static void CheckTextureTransformMatrices(void) MtxIndexInVertexPacket = __GXVertexPacketHas(GX_VA_TEX7MTXIDX); break; default: - __GX_WARNF(0x54, i); + __GX_WARNF_CHECKED(0x54, i); break; } +#if DOLPHIN_REVISION >= 45 + if (MtxIndexInVertexPacket == 0) { +#else if (MtxIndexInVertexPacket != 0) { +#endif sprintf(Preamble, __gxvWarnings[0x6B], i, i, Val); if (!((BYTE3(__gxVerif->xfRegs[i + 64]) >> 1) & 1)) { Size = 8; @@ -481,7 +523,9 @@ static void CheckInputForms(void) for (i = 0; i < numRegularTextures; i++) { switch ((HIWORD(__gxVerif->xfRegs[i + 64]) >> 7) & 0x1F) { +#if DOLPHIN_REVISION < 45 case 2: +#endif case 5: case 6: case 7: @@ -491,7 +535,7 @@ static void CheckInputForms(void) case 11: case 12: if ((BYTE3(__gxVerif->xfRegs[i + 64]) >> 2) & 1) { - __GX_WARNF(0x55, i, (u8)((HIWORD(__gxVerif->xfRegs[i + 64]) >> 7) & 0x1F)); + __GX_WARNF_CHECKED(0x55, i, (u8)((HIWORD(__gxVerif->xfRegs[i + 64]) >> 7) & 0x1F)); } } } @@ -508,10 +552,12 @@ static void CheckLight(u32 lightSource) for (i = 0; i < 13; i++) { if (!__gxVerif->xfLightDirty[lightRAMOffset + i - 0x600]) { if (!printedPreamble) { - __GX_WARNF(0x6C, lightSource); + __GX_WARNF_CHECKED(0x6C, lightSource); printedPreamble = 1; } +#if DOLPHIN_REVISION < 45 __GX_WARNF(0x70, lightRAMOffset + i, lightRegisterNames[i]); +#endif } } } @@ -525,16 +571,16 @@ static void CheckColor0(void) if ((u8)(BYTE3(__gxVerif->xfRegs[9]) & 3) || numColorTextures != 0) { if (!__gxVerif->xfRegsDirty[14]) { - __GX_WARNF(0x56, 0x100E, "Color 0 control register"); + __GX_WARNF_CHECKED(0x56, 0x100E, "Color 0 control register"); } if (!__gxVerif->xfRegsDirty[16]) { - __GX_WARNF(0x56, 0x1010, "Alpha 0 control register"); + __GX_WARNF_CHECKED(0x56, 0x1010, "Alpha 0 control register"); } if (!(BYTE3(__gxVerif->xfRegs[14]) & 1) && !__gxVerif->xfRegsDirty[12]) { - __GX_WARNF(0x57, 0, 0, 0x100C); + __GX_WARNF_CHECKED(0x57, 0, 0, 0x100C); } if (!((BYTE3(__gxVerif->xfRegs[14]) >> 6) & 1) && !__gxVerif->xfRegsDirty[10]) { - __GX_WARNF(0x58, 0, 0, 0x100A); + __GX_WARNF_CHECKED(0x58, 0, 0, 0x100A); } if ((u32)((BYTE3(__gxVerif->xfRegs[14]) >> 1) & 1) == 1 || (u32)((BYTE3(__gxVerif->xfRegs[16]) >> 1) & 1) == 1) { haveLight = 0; @@ -589,21 +635,21 @@ static void CheckColor0(void) } if (haveLight != 0) { if (!((BYTE2(__gxVerif->xfRegs[14]) >> 2) & 1) && ((HIWORD(__gxVerif->xfRegs[14]) >> 7) & 3)) { - __GX_WARNF(0x59, "COLOR0", "COLOR0"); + __GX_WARNF_CHECKED(0x59, "COLOR0", "COLOR0"); } if (!((BYTE2(__gxVerif->xfRegs[16]) >> 2) & 1) && ((HIWORD(__gxVerif->xfRegs[16]) >> 7) & 3)) { - __GX_WARNF(0x59, "ALPHA0", "ALPHA0"); + __GX_WARNF_CHECKED(0x59, "ALPHA0", "ALPHA0"); } if (((HIWORD(__gxVerif->xfRegs[14]) >> 7) & 3) || ((u8)((BYTE2(__gxVerif->xfRegs[14]) >> 1) & 1) && ((u32)((BYTE2(__gxVerif->xfRegs[14]) >> 2) & 1) == 1)) || ((HIWORD(__gxVerif->xfRegs[16]) >> 7) & 3) || ((u8)((BYTE2(__gxVerif->xfRegs[16]) >> 1) & 1) && ((u32)((BYTE2(__gxVerif->xfRegs[16]) >> 2) & 1) == 1))) { if ((__GXVertexPacketHas(GX_VA_NRM) == 0) && (__GXVertexPacketHas(GX_VA_NBT) == 0)) { - __GX_WARNF(0x5A, 0); + __GX_WARNF_CHECKED(0x5A, 0); } if (__GXVertexPacketHas(GX_VA_PNMTXIDX) == 0) { if ((u32)(BYTE3(__gxVerif->xfRegs[24]) & 0x3F) > 30) { - __GX_WARNF(0x5B, 0, (u8)(BYTE3(__gxVerif->xfRegs[24]) & 0x3F)); + __GX_WARNF_CHECKED(0x5B, 0, (u8)(BYTE3(__gxVerif->xfRegs[24]) & 0x3F)); } sprintf(Preamble, __gxvWarnings[0x6D], 0, (u8)(BYTE3(__gxVerif->xfRegs[24]) & 0x3F)); CheckRAM(1, ((BYTE3(__gxVerif->xfRegs[24]) & 0x3F) * 3) + 0x400, 9, 0x6D, Preamble); @@ -630,16 +676,16 @@ static void CheckColor1(void) if ((u32)(BYTE3(__gxVerif->xfRegs[9]) & 3) == 2 || usingColor1) { if (!__gxVerif->xfRegsDirty[15]) { - __GX_WARNF(0x56, 0x100F, "Color 1 control register"); + __GX_WARNF_CHECKED(0x56, 0x100F, "Color 1 control register"); } if (!__gxVerif->xfRegsDirty[17]) { - __GX_WARNF(0x56, 0x1011, "Alpha 1 control register"); + __GX_WARNF_CHECKED(0x56, 0x1011, "Alpha 1 control register"); } if (!(BYTE3(__gxVerif->xfRegs[15]) & 1) && !__gxVerif->xfRegsDirty[13]) { - __GX_WARNF(0x57, 1, 1, 0x100D); + __GX_WARNF_CHECKED(0x57, 1, 1, 0x100D); } if (!((BYTE3(__gxVerif->xfRegs[15]) >> 6) & 1) && !__gxVerif->xfRegsDirty[11]) { - __GX_WARNF(0x58, 1, 1, 0x100B); + __GX_WARNF_CHECKED(0x58, 1, 1, 0x100B); } if ((u32)((BYTE3(__gxVerif->xfRegs[15]) >> 1) & 1) == 1 || (u32)((BYTE3(__gxVerif->xfRegs[17]) >> 1) & 1) == 1) { haveLight = 0; @@ -694,21 +740,21 @@ static void CheckColor1(void) } if (haveLight != 0) { if (!((BYTE2(__gxVerif->xfRegs[15]) >> 2) & 1) && ((HIWORD(__gxVerif->xfRegs[15]) >> 7) & 3)) { - __GX_WARNF(0x59, "COLOR1", "COLOR1"); + __GX_WARNF_CHECKED(0x59, "COLOR1", "COLOR1"); } if (!((BYTE2(__gxVerif->xfRegs[17]) >> 2) & 1) && ((HIWORD(__gxVerif->xfRegs[17]) >> 7) & 3)) { - __GX_WARNF(0x59, "ALPHA1", "ALPHA1"); + __GX_WARNF_CHECKED(0x59, "ALPHA1", "ALPHA1"); } if (((HIWORD(__gxVerif->xfRegs[15]) >> 7) & 3) || ((u8)((BYTE2(__gxVerif->xfRegs[15]) >> 1) & 1) && ((u32)((BYTE2(__gxVerif->xfRegs[15]) >> 2) & 1) == 1)) || ((HIWORD(__gxVerif->xfRegs[17]) >> 7) & 3) || ((u8)((BYTE2(__gxVerif->xfRegs[17]) >> 1) & 1) && ((u32)((BYTE2(__gxVerif->xfRegs[17]) >> 2) & 1) == 1))) { if ((__GXVertexPacketHas(GX_VA_NRM) == 0) && (__GXVertexPacketHas(GX_VA_NBT) == 0)) { - __GX_WARNF(0x5A, 1); + __GX_WARNF_CHECKED(0x5A, 1); } if (__GXVertexPacketHas(GX_VA_PNMTXIDX) == 0) { if ((u32)(BYTE3(__gxVerif->xfRegs[24]) & 0x3F) > 30) { - __GX_WARNF(0x5B, 1, (u8)(BYTE3(__gxVerif->xfRegs[24]) & 0x3F)); + __GX_WARNF_CHECKED(0x5B, 1, (u8)(BYTE3(__gxVerif->xfRegs[24]) & 0x3F)); } sprintf(Preamble, __gxvWarnings[0x6D], 1, (u8)(BYTE3(__gxVerif->xfRegs[24]) & 0x3F)); CheckRAM(1, ((BYTE3(__gxVerif->xfRegs[24]) & 0x3F) * 3) + 0x400, 9, 0x6D, Preamble); @@ -751,19 +797,19 @@ static void CheckFloatingPointValue(u8 dirtyBit, u32 value, char *label) if (__gxVerif->verifyLevel >= 2) { if (mantissa == 0) { if (sign != 0) { - __GX_WARN2F(GX_WARN_MEDIUM, 0x5C, label, "-", *(u32 *)&valuef); + __GX_WARN2F_CHECKED(GX_WARN_MEDIUM, 0x5C, label, "-", *(u32 *)&valuef); } else { - __GX_WARN2F(GX_WARN_MEDIUM, 0x5C, label, "+", *(u32 *)&valuef); + __GX_WARN2F_CHECKED(GX_WARN_MEDIUM, 0x5C, label, "+", *(u32 *)&valuef); } } else { - __GX_WARN2F(GX_WARN_MEDIUM, 0x5D, label, *(u32 *)&valuef); + __GX_WARN2F_CHECKED(GX_WARN_MEDIUM, 0x5D, label, *(u32 *)&valuef); } } } else if (__gxVerif->verifyLevel >= 3) { if (exponent < 0x6BU) { - __GX_WARN2F(GX_WARN_ALL, 0x5E, label, valuef, *(u32 *)&valuef); + __GX_WARN2F_CHECKED(GX_WARN_ALL, 0x5E, label, valuef, *(u32 *)&valuef); } else if (exponent > 0x96U) { - __GX_WARN2F(GX_WARN_ALL, 0x5F, label, valuef, *(u32 *)&valuef); + __GX_WARN2F_CHECKED(GX_WARN_ALL, 0x5F, label, valuef, *(u32 *)&valuef); } } } @@ -865,7 +911,7 @@ static void CheckMatrixIndices(void) && numRegularTextures > 4 && __gxVerif->verifyLevel >= 1 && !__gxVerif->xfRegsDirty[0x19]) { - __GX_WARNF(0x60, numRegularTextures, 0x1019U); + __GX_WARNF_CHECKED(0x60, numRegularTextures, 0x1019U); } } @@ -892,6 +938,7 @@ static void CheckErrors(void) CheckDirty(0x1026U, "Projection matrix orthographic/perspective select"); CheckMatrixIndices(); if (__gxVerif->verifyLevel >= 1) { +#if DOLPHIN_REVISION < 45 if ((u32)((__gxVerif->rasRegs[0] & 0xFF000000) + 0x01000000) == 0U) { __GX_WARN(0x61); } @@ -901,24 +948,25 @@ static void CheckErrors(void) if ((u32)(BYTE3(__gxVerif->xfRegs[9]) & 3) != (u8)((__gxVerif->rasRegs[0] >> 4U) & 7)) { __GX_WARN(0x63); } +#endif CheckCTGColors(); if (__gxVerif->xfRegs[0x3F] > 8) { - __GX_WARNF(0x64, __gxVerif->xfRegs[0x3F], 8); + __GX_WARNF_CHECKED(0x64, __gxVerif->xfRegs[0x3F], 8); } if (numRegularTextures > 8) { - __GX_WARNF(0x65, numRegularTextures, 8); + __GX_WARNF_CHECKED(0x65, numRegularTextures, 8); } if (numBumpmapTextures > 3) { - __GX_WARNF(0x66, numBumpmapTextures, 3); + __GX_WARNF_CHECKED(0x66, numBumpmapTextures, 3); } if (numColorTextures > 2) { - __GX_WARNF(0x67, numColorTextures, 2); + __GX_WARNF_CHECKED(0x67, numColorTextures, 2); } if (numColor0Textures > 1) { - __GX_WARNF(0x69, 0); + __GX_WARNF_CHECKED(0x69, 0); } if (numColor1Textures > 1) { - __GX_WARNF(0x69, 1); + __GX_WARNF_CHECKED(0x69, 1); } CheckVertexPacket(); @@ -933,7 +981,7 @@ static void CheckErrors(void) } CheckTextureTransformMatrices(); if (numColorTextures != 0 && (u32)((BYTE3(__gxVerif->xfRegs[numRegularTextures + numBumpmapTextures + 64]) >> 4) & 7) != 2) {//((u32) (((u8) *(__gxVerif + (((numRegularTextures + (numBumpmapTextures + 0x40)) * 4) + 0xB)) >> 4U) & 7) != 2)) { - __GX_WARN(0x68U); + __GX_WARN_CHECKED(0x68U); } CheckColor0(); CheckColor1(); diff --git a/src/gx/__gx.h b/src/gx/__gx.h index 43e8ba1..b822d77 100644 --- a/src/gx/__gx.h +++ b/src/gx/__gx.h @@ -181,9 +181,16 @@ void __GXSetGenMode(void); struct __GXData_struct { // total size: 0x4F4 +#if DOLPHIN_REVISION >= 45 + unsigned short vNumNot; + unsigned short bpSentNot; + unsigned short vNum; + unsigned short vLim; +#else unsigned short vNum; // offset 0x0, size 0x2 unsigned short bpSent; // offset 0x2, size 0x2 unsigned long vLim; // offset 0x4, size 0x4 +#endif unsigned long cpEnable; // offset 0x8, size 0x4 unsigned long cpStatus; // offset 0xC, size 0x4 unsigned long cpClr; // offset 0x10, size 0x4 @@ -233,8 +240,8 @@ struct __GXData_struct { GXTexRegion * (* texRegionCallback)(GXTexObj *, GXTexMapID); // offset 0x410, size 0x4 GXTlutRegion * (* tlutRegionCallback)(unsigned long); // offset 0x414, size 0x4 GXAttrType nrmType; // offset 0x418, size 0x4 - unsigned char hasNrms; // offset 0x41C, size 0x1 - unsigned char hasBiNrms; // offset 0x41D, size 0x1 + GXBool hasNrms; // offset 0x41C, size 0x1 + GXBool hasBiNrms; // offset 0x41D, size 0x1 unsigned long projType; // offset 0x420, size 0x4 float projMtx[6]; // offset 0x424, size 0x18 float vpLeft; // offset 0x43C, size 0x4 @@ -288,6 +295,9 @@ void __GXSetRange(float nearz, float fgSideX); void __GetImageTileCount(GXTexFmt fmt, u16 wd, u16 ht, u32 *rowTiles, u32 *colTiles, u32 *cmpTiles); void __GXSetSUTexRegs(void); void __GXGetSUTexSize(GXTexCoordID coord, u16 *width, u16 *height); +#if DOLPHIN_REVISION >= 45 +void __GXSetTmemConfig(unsigned long config); +#endif /* GXTransform.c */ @@ -301,7 +311,7 @@ void __GXVerifyTEX(void); void __GXVerifyTEV(void); void __GXVerifyPE(void); -/* GXVerif.c */ +/* GXVerify.c */ typedef enum { GXWARN_INVALID_VTX_FMT = 0, @@ -420,13 +430,25 @@ typedef enum { GXWARN_MAX = 113, } GXWarnID; +#if DOLPHIN_REVISION >= 45 + +#define __GX_WARN(id) (__gxVerif->cb(__gxvWarnLev[(id)], (id), __gxvWarnings[(id)])) +#define __GX_WARNF(id, ...) \ +do { \ + sprintf(__gxvDummyStr, __gxvWarnings[(id)], __VA_ARGS__); \ + __gxVerif->cb(__gxvWarnLev[(id)], (id), __gxvDummyStr); \ +} while (0) +#define __GX_WARN2(level, id) (__gxVerif->cb(level, (id), __gxvWarnings[(id)])) +#define __GX_WARN2F(level, id, ...) __GX_WARNF(id, __VA_ARGS__) + +#else + #define __GX_WARN(id) (__gxVerif->cb(GX_WARN_SEVERE, (id), __gxvWarnings[(id)])) #define __GX_WARNF(id, ...) \ do { \ sprintf(__gxvDummyStr, __gxvWarnings[(id)], __VA_ARGS__); \ __gxVerif->cb(GX_WARN_SEVERE, (id), __gxvDummyStr); \ } while (0) - #define __GX_WARN2(level, id) (__gxVerif->cb(level, (id), __gxvWarnings[(id)])) #define __GX_WARN2F(level, id, ...) \ do { \ @@ -434,6 +456,41 @@ do { \ __gxVerif->cb(level, (id), __gxvDummyStr); \ } while (0) +#endif + +// On r45 and later, checks verify level before issuing warning +#if DOLPHIN_REVISION >= 45 +#define __GX_WARN_CHECKED(id) \ +do { \ + if (__gxVerif->verifyLevel >= __gxvWarnLev[(id)]) { \ + __GX_WARN(id); \ + } \ +} while (0) +#define __GX_WARNF_CHECKED(id, ...) \ +do { \ + if (__gxVerif->verifyLevel >= __gxvWarnLev[(id)]) { \ + __GX_WARNF(id, __VA_ARGS__); \ + } \ +} while (0) +#define __GX_WARN2_CHECKED(level, id) \ +do { \ + if (__gxVerif->verifyLevel >= __gxvWarnLev[(id)]) { \ + __GX_WARN2(level, id); \ + } \ +} while (0) +#define __GX_WARN2F_CHECKED(level, id, ...) \ +do { \ + if (__gxVerif->verifyLevel >= __gxvWarnLev[(id)]) { \ + __GX_WARN2F(level, id, __VA_ARGS__); \ + } \ +} while (0) +#else +#define __GX_WARN_CHECKED __GX_WARN +#define __GX_WARNF_CHECKED __GX_WARNF +#define __GX_WARN2_CHECKED __GX_WARN2 +#define __GX_WARN2F_CHECKED __GX_WARN2F +#endif + struct __GXVerifyData { // total size: 0x13F8 GXVerifyCallback cb; // offset 0x0, size 0x4 @@ -453,6 +510,9 @@ struct __GXVerifyData { extern struct __GXVerifyData *__gxVerif; extern char *__gxvWarnings[113]; +#if DOLPHIN_REVISION >= 45 +extern GXWarningLevel __gxvWarnLev[115]; +#endif extern char __gxvDummyStr[256]; void __GXVerifyGlobal(void); diff --git a/src/hio/hio.c b/src/hio/hio.c index f3ecf60..b9741ea 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; @@ -104,7 +106,20 @@ BOOL HIOInit(s32 chan, HIOCallback callback) u32 cmd; u32 id; +#if DOLPHIN_REVISION >= 45 + if (__OSGetDIConfig() == 0xFFu) { + Chan = -1; + return 0; + } +#endif + +#if DOLPHIN_REVISION >= 45 + if (Chan != -1) { + return 1; + } else { +#else if (Chan == -1) { +#endif Chan = chan; ExiCallback = callback; TxCallback = NULL; @@ -161,9 +176,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 +208,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; } @@ -206,15 +233,23 @@ BOOL HIOWriteMailbox(u32 word) return !err; } +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 13 : 0) + 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; } - ASSERTLINE(0x145, (addr % 4) == 0); +#endif + ASSERTLINE(0x145+LINE_OFFSET, (addr % 4) == 0); if (EXILock(Chan, 0, 0) == 0) { return 0; } @@ -238,10 +273,16 @@ 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; } - ASSERTLINE(0x167, (addr % 4) == 0); +#endif + ASSERTLINE(0x167+LINE_OFFSET, (addr % 4) == 0); if (EXILock(Chan, 0, 0) == 0) { return 0; } @@ -265,10 +306,14 @@ BOOL HIOReadAsync(u32 addr, void *buffer, s32 size, HIOCallback callback) int err; u32 cmd; +#if DOLPHIN_REVISION >= 45 + if (Chan == -1 || __OSGetDIConfig() == 0xFFu) { +#else if (Chan == -1) { +#endif return 0; } - ASSERTLINE(0x189, (addr % 4) == 0); + ASSERTLINE(0x189+LINE_OFFSET, (addr % 4) == 0); RxCallback = callback; if (EXILock(Chan, 0, 0) == 0) { return 0; @@ -290,10 +335,14 @@ BOOL HIOWriteAsync(u32 addr, void *buffer, s32 size, HIOCallback callback) int err; u32 cmd; +#if DOLPHIN_REVISION >= 45 + if (Chan == -1 || __OSGetDIConfig() == 0xFFu) { +#else if (Chan == -1) { +#endif return 0; } - ASSERTLINE(0x1AA, (addr % 4) == 0); + ASSERTLINE(0x1AA+LINE_OFFSET, (addr % 4) == 0); TxCallback = callback; if (EXILock(Chan, 0, 0) == 0) { return 0; @@ -315,7 +364,11 @@ BOOL HIOReadStatus(u32 *status) int err; u32 cmd; +#if DOLPHIN_REVISION >= 45 + if (Chan == -1 || __OSGetDIConfig() == 0xFFu) { +#else if (Chan == -1) { +#endif return 0; } if (EXILock(Chan, 0, 0) == 0) { diff --git a/src/os/OS.c b/src/os/OS.c index c25e1fb..a56844c 100644 --- a/src/os/OS.c +++ b/src/os/OS.c @@ -1,3 +1,4 @@ +#include // NULL must be defined as 0L in this file #include #include #include @@ -26,6 +27,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; @@ -52,6 +54,9 @@ static unsigned long * BI2DebugFlag; static double ZeroF; static int AreWeInitialized; static void (* * OSExceptionTable)(unsigned char, struct OSContext *); +#if DOLPHIN_REVISION >= 45 +OSTime __OSStartTime; +#endif // functions static asm void __OSInitFPRs(void); @@ -101,6 +106,15 @@ static asm void __OSInitFPRs(void) blr } +#if DOLPHIN_REVISION >= 45 +static void DisableWriteGatherPipe(void) +{ + u32 hid2 = PPCMfhid2(); + hid2 &= ~0x40000000; + PPCMthid2(hid2); +} +#endif + unsigned long OSGetConsoleType() { if ((!BootInfo) || (BootInfo->consoleType == 0)) { return OS_CONSOLE_ARTHUR; @@ -108,12 +122,68 @@ unsigned long OSGetConsoleType() { return BootInfo->consoleType; } +#if DOLPHIN_REVISION >= 45 +static void ClearArena(void) +{ + void *regionStart; + void *regionEnd; + + if (OSGetResetCode() != 0x80000000) { + memset(OSGetArenaLo(), 0, (u8 *)OSGetArenaHi() - (u8 *)OSGetArenaLo()); + return; + } + regionStart = *(void **)0x812FDFF0; + regionEnd = *(void **)0x812FDFEC; + if (regionStart == NULL) { + memset(OSGetArenaLo(), 0, (u8 *)OSGetArenaHi() - (u8 *)OSGetArenaLo()); + return; + } + ASSERTLINE(0x232, regionEnd != NULL); + if (OSGetArenaLo() >= regionStart) { + return; + } + if (OSGetArenaHi() <= regionStart) { + memset(OSGetArenaLo(), 0, (u8 *)OSGetArenaHi() - (u8 *)OSGetArenaLo()); + return; + } + memset(OSGetArenaLo(), 0, (u8 *)regionStart - (u8 *)OSGetArenaLo()); + if (OSGetArenaHi() > regionEnd) { + memset(regionEnd, 0, (u8 *)OSGetArenaHi() - (u8 *)regionEnd); + } +} +#endif + +#if DOLPHIN_REVISION == 45 +# define BUILD_DATE "Sep 8 2001" +# define BUILD_TIMESTAMP "01:29:38" +#elif 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) + +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 101 : 0) + void OSInit() { unsigned long consoleType; void * bi2StartAddr; if (AreWeInitialized == 0) { AreWeInitialized = 1; +#if DOLPHIN_REVISION >= 45 + __OSStartTime = __OSGetSystemTime(); +#endif OSDisableInterrupts(); BootInfo = (struct OSBootInfo_s *)OSPhysicalToCached(0); BI2DebugFlag = NULL; @@ -131,6 +201,9 @@ void OSInit() { OSSetArenaHi((!BootInfo->arenaHi) ? &__ArenaHi : BootInfo->arenaHi); OSExceptionInit(); __OSInitSystemCall(); +#if DOLPHIN_REVISION >= 45 + OSInitAlarm(); +#endif __OSModuleInit(); __OSInterruptInit(); __OSSetInterruptHandler(0x16, &__OSResetSWInterruptHandler); @@ -141,19 +214,21 @@ void OSInit() { __OSInitSram(); __OSThreadInit(); __OSInitAudioSystem(); - ASSERTLINE(0x252, BootInfo); // oh sure, assert NOW, you've already dereferenced it a bunch of times. +#if DOLPHIN_REVISION >= 45 + DisableWriteGatherPipe(); +#endif + ASSERTLINE(0x252+LINE_OFFSET, BootInfo); // oh sure, assert NOW, you've already dereferenced it a bunch of times. if ((BootInfo->consoleType & OS_CONSOLE_DEVELOPMENT) != 0) { BootInfo->consoleType = OS_CONSOLE_DEVHW1; } else { 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"); +#if DOLPHIN_REVISION >= 45 + __OSInitMemoryProtection(); #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 @@ -189,6 +264,9 @@ void OSInit() { if (BI2DebugFlag && ((*BI2DebugFlag) >= 2)) { EnableMetroTRKInterrupts(); } +#if DOLPHIN_REVISION >= 45 + ClearArena(); +#endif OSEnableInterrupts(); } } @@ -218,6 +296,9 @@ char * __OSExceptionNames[15] = { }; #endif +#undef LINE_OFFSET +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 109 : 0) + static void OSExceptionInit(void) { __OSException exception; void* destAddr; @@ -231,7 +312,7 @@ static void OSExceptionInit(void) { u8* handlerStart; u32 handlerSize; - ASSERTMSGLINE(0x2F1, ((u32)&__OSEVEnd - (u32)&__OSEVStart) <= 0x100, "OSExceptionInit(): too big exception vector code."); + ASSERTMSGLINE(0x2F1+LINE_OFFSET, ((u32)&__OSEVEnd - (u32)&__OSEVStart) <= 0x100, "OSExceptionInit(): too big exception vector code."); // Install the first level exception vector. opCodeAddr = (u32*)__OSEVSetNumber; @@ -329,7 +410,7 @@ entry __OSDBJUMPEND __OSExceptionHandler __OSSetExceptionHandler(__OSException exception, __OSExceptionHandler handler) { __OSExceptionHandler oldHandler; - ASSERTMSGLINE(0x37F, exception < __OS_EXCEPTION_MAX, "__OSSetExceptionHandler(): unknown exception."); + ASSERTMSGLINE(0x37F+LINE_OFFSET, exception < __OS_EXCEPTION_MAX, "__OSSetExceptionHandler(): unknown exception."); oldHandler = OSExceptionTable[exception]; OSExceptionTable[exception] = handler; @@ -337,7 +418,7 @@ __OSExceptionHandler __OSSetExceptionHandler(__OSException exception, __OSExcept } __OSExceptionHandler __OSGetExceptionHandler(__OSException exception) { - ASSERTMSGLINE(0x396, exception < __OS_EXCEPTION_MAX, "__OSGetExceptionHandler(): unknown exception."); + ASSERTMSGLINE(0x396+LINE_OFFSET, exception < __OS_EXCEPTION_MAX, "__OSGetExceptionHandler(): unknown exception."); return OSExceptionTable[exception]; } @@ -450,3 +531,13 @@ void __OSPSInit(void) } // clang-format on } + +#if DOLPHIN_REVISION >= 37 +u32 __OSGetDIConfig(void) { +#if DOLPHIN_REVISION >= 45 + return UNK_REG_CC006000[9] & 0xFF; +#else + return (u8)UNK_REG_CC006000[9]; +#endif +} +#endif diff --git a/src/os/OSAlarm.c b/src/os/OSAlarm.c index a7358eb..0e4ee01 100644 --- a/src/os/OSAlarm.c +++ b/src/os/OSAlarm.c @@ -20,22 +20,28 @@ static void DecrementerExceptionHandler(__OSException exception, OSContext* cont #define ASSERTREPORT(line, cond) \ if (!(cond)) { OSReport("OSCheckAlarmQueue: Failed " #cond " in %d", line); return 0; } +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 7 : 0) + BOOL OSCheckAlarmQueue(void) { struct OSAlarm * alarm; - ASSERTREPORT(0x70, AlarmQueue.head == NULL && AlarmQueue.tail == NULL || AlarmQueue.head != NULL && AlarmQueue.tail != NULL); - ASSERTREPORT(0x71, AlarmQueue.head == NULL || AlarmQueue.head->prev == NULL); - ASSERTREPORT(0x72, AlarmQueue.tail == NULL || AlarmQueue.tail->next == NULL); + ASSERTREPORT(0x70+LINE_OFFSET, AlarmQueue.head == NULL && AlarmQueue.tail == NULL || AlarmQueue.head != NULL && AlarmQueue.tail != NULL); + ASSERTREPORT(0x71+LINE_OFFSET, AlarmQueue.head == NULL || AlarmQueue.head->prev == NULL); + ASSERTREPORT(0x72+LINE_OFFSET, AlarmQueue.tail == NULL || AlarmQueue.tail->next == NULL); for(alarm = AlarmQueue.head; alarm; alarm = alarm->next) { - ASSERTREPORT(0x75, alarm->next == NULL || alarm->next->prev == alarm); - ASSERTREPORT(0x76, alarm->next != NULL || AlarmQueue.tail == alarm); + ASSERTREPORT(0x75+LINE_OFFSET, alarm->next == NULL || alarm->next->prev == alarm); + ASSERTREPORT(0x76+LINE_OFFSET, alarm->next != NULL || AlarmQueue.tail == alarm); } return TRUE; } static void SetTimer(struct OSAlarm * alarm) { +#if DOLPHIN_REVISION >= 45 + OSTime delta = alarm->fire - __OSGetSystemTime(); +#else OSTime delta = alarm->fire - OSGetTime(); +#endif if (delta < 0) { PPCMtdec(0); @@ -62,15 +68,19 @@ static void InsertAlarm(OSAlarm* alarm, OSTime fire, OSAlarmHandler handler) { OSAlarm* prev; if (0 < alarm->period) { +#if DOLPHIN_REVISION >= 45 + OSTime time = __OSGetSystemTime(); +#else OSTime time = OSGetTime(); - +#endif + fire = alarm->start; if (alarm->start < time) { fire += alarm->period * ((time - alarm->start) / alarm->period + 1); } } - ASSERTLINE(0xD6, alarm->handler == 0); + ASSERTLINE(0xD6+LINE_OFFSET, alarm->handler == 0); alarm->handler = handler; alarm->fire = fire; @@ -95,7 +105,7 @@ static void InsertAlarm(OSAlarm* alarm, OSTime fire, OSAlarmHandler handler) { return; } - ASSERTLINE(0xF3, next == 0); + ASSERTLINE(0xF3+LINE_OFFSET, next == 0); alarm->next = 0; prev = AlarmQueue.tail; @@ -112,35 +122,53 @@ static void InsertAlarm(OSAlarm* alarm, OSTime fire, OSAlarmHandler handler) { void OSSetAlarm(OSAlarm* alarm, OSTime tick, OSAlarmHandler handler) { BOOL enabled; - ASSERTMSGLINE(0x114, tick > 0, "OSSetAlarm(): tick was less than zero."); - ASSERTMSGLINE(0x115, handler, "OSSetAlarm(): null handler was specified."); + ASSERTMSGLINE(0x114+LINE_OFFSET, tick > 0, "OSSetAlarm(): tick was less than zero."); + ASSERTMSGLINE(0x115+LINE_OFFSET, handler, "OSSetAlarm(): null handler was specified."); enabled = OSDisableInterrupts(); alarm->period = 0; +#if DOLPHIN_REVISION >= 45 + InsertAlarm(alarm, __OSGetSystemTime() + tick, handler); +#else InsertAlarm(alarm, OSGetTime() + tick, handler); - ASSERTLINE(0x11C, OSCheckAlarmQueue()); +#endif + ASSERTLINE(0x11C+LINE_OFFSET, OSCheckAlarmQueue()); OSRestoreInterrupts(enabled); } +#undef LINE_OFFSET +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 9 : 0) + void OSSetAbsAlarm(struct OSAlarm * alarm, long long time, void (* handler)(struct OSAlarm *, struct OSContext *)) { int enabled; - ASSERTMSGLINE(0x130, handler, "OSSetAbsAlarm(): null handler was specified."); + ASSERTMSGLINE(0x130+LINE_OFFSET, handler, "OSSetAbsAlarm(): null handler was specified."); enabled = OSDisableInterrupts(); alarm->period = 0; +#if DOLPHIN_REVISION >= 45 + InsertAlarm(alarm, __OSTimeToSystemTime(time), handler); +#else InsertAlarm(alarm, time, handler); - ASSERTLINE(0x137, OSCheckAlarmQueue()); +#endif + ASSERTLINE(0x137+LINE_OFFSET, OSCheckAlarmQueue()); OSRestoreInterrupts(enabled); } +#undef LINE_OFFSET +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 11 : 0) + void OSSetPeriodicAlarm(OSAlarm* alarm, OSTime start, OSTime period, OSAlarmHandler handler) { BOOL enabled; - ASSERTMSGLINE(0x14D, period > 0, "OSSetPeriodicAlarm(): period was less than zero."); - ASSERTMSGLINE(0x14E, handler, "OSSetPeriodicAlarm(): null handler was specified."); + ASSERTMSGLINE(0x14D+LINE_OFFSET, period > 0, "OSSetPeriodicAlarm(): period was less than zero."); + ASSERTMSGLINE(0x14E+LINE_OFFSET, handler, "OSSetPeriodicAlarm(): null handler was specified."); enabled = OSDisableInterrupts(); alarm->period = period; +#if DOLPHIN_REVISION >= 45 + alarm->start = __OSTimeToSystemTime(start); +#else alarm->start = start; +#endif InsertAlarm(alarm, 0, handler); - ASSERTLINE(0x156, OSCheckAlarmQueue()); + ASSERTLINE(0x156+LINE_OFFSET, OSCheckAlarmQueue()); OSRestoreInterrupts(enabled); } @@ -170,18 +198,28 @@ void OSCancelAlarm(OSAlarm* alarm) { } } alarm->handler = 0; - ASSERTLINE(0x189, OSCheckAlarmQueue()); + ASSERTLINE(0x189+LINE_OFFSET, OSCheckAlarmQueue()); OSRestoreInterrupts(enabled); } +#undef LINE_OFFSET +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 12 : 0) + static void DecrementerExceptionCallback(register __OSException exception, register OSContext* context) { OSAlarm* alarm; OSAlarm* next; OSAlarmHandler handler; OSTime time; +#if DOLPHIN_REVISION >= 45 + OSContext exceptionContext; +#endif +#if DOLPHIN_REVISION >= 45 + time = __OSGetSystemTime(); +#else time = OSGetTime(); +#endif alarm = AlarmQueue.head; if (alarm == 0) { OSLoadContext(context); @@ -199,12 +237,12 @@ static void DecrementerExceptionCallback(register __OSException exception, } else { next->prev = 0; } - ASSERTLINE(0x1C2, OSCheckAlarmQueue()); + ASSERTLINE(0x1C2+LINE_OFFSET, OSCheckAlarmQueue()); handler = alarm->handler; alarm->handler = 0; if (0 < alarm->period) { InsertAlarm(alarm, 0, handler); - ASSERTLINE(0x1CC, OSCheckAlarmQueue()); + ASSERTLINE(0x1CC+LINE_OFFSET, OSCheckAlarmQueue()); } if (AlarmQueue.head) { @@ -212,7 +250,15 @@ static void DecrementerExceptionCallback(register __OSException exception, } OSDisableScheduler(); +#if DOLPHIN_REVISION >= 45 + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); +#endif handler(alarm, context); +#if DOLPHIN_REVISION >= 45 + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); +#endif OSEnableScheduler(); __OSReschedule(); OSLoadContext(context); diff --git a/src/os/OSAudioSystem.c b/src/os/OSAudioSystem.c index 6fdd1ff..ecc9054 100644 --- a/src/os/OSAudioSystem.c +++ b/src/os/OSAudioSystem.c @@ -18,18 +18,23 @@ static u8 DSPInitCode[128] = { #define __DSPWorkBuffer (void*)0x81000000 +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 7 : 0) + void __OSInitAudioSystem(void) { u8 errFlag; u16 reg16; u32 start_tick; +#if DOLPHIN_REVISION >= 45 + memcpy((u8 *)OSGetArenaHi() - 0x80, __DSPWorkBuffer, 0x80); +#endif memcpy(__DSPWorkBuffer, (void*)DSPInitCode, 128); DCFlushRange(__DSPWorkBuffer, 128); __DSPRegs[9] = 0x43; - ASSERTMSGLINE(0x67, !(__DSPRegs[5] & 0x200), "__OSInitAudioSystem(): ARAM DMA already in progress"); - ASSERTMSGLINE(0x6B, !(__DSPRegs[5] & 0x400), "__OSInitAudioSystem(): DSP DMA already in progress"); - ASSERTMSGLINE(0x6F, (__DSPRegs[5] & 0x004), "__OSInitAudioSystem(): DSP already working"); + ASSERTMSGLINE(0x67+LINE_OFFSET, !(__DSPRegs[5] & 0x200), "__OSInitAudioSystem(): ARAM DMA already in progress"); + ASSERTMSGLINE(0x6B+LINE_OFFSET, !(__DSPRegs[5] & 0x400), "__OSInitAudioSystem(): DSP DMA already in progress"); + ASSERTMSGLINE(0x6F+LINE_OFFSET, (__DSPRegs[5] & 0x004), "__OSInitAudioSystem(): DSP already working"); __DSPRegs[5] = 0x8AC; __DSPRegs[5] |= 1; while (__DSPRegs[5] & 1); @@ -70,7 +75,7 @@ void __OSInitAudioSystem(void) { } if(((u32)((reg16 << 16) | __DSPRegs[3]) + 0x7FAC0000U) != 0x4348) { - ASSERTMSGLINE(0xB7, 0, "__OSInitAudioSystem(): DSP returns invalid message"); + ASSERTMSGLINE(0xB7+LINE_OFFSET, 0, "__OSInitAudioSystem(): DSP returns invalid message"); } reg16 != 42069; @@ -78,6 +83,9 @@ void __OSInitAudioSystem(void) { __DSPRegs[5] = 0x8AC; __DSPRegs[5] |= 1; while (__DSPRegs[5] & 1); +#if DOLPHIN_REVISION >= 45 + memcpy(__DSPWorkBuffer, (u8 *)OSGetArenaHi() - 0x80, 0x80); +#endif } void __OSStopAudioSystem(void) { 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/OSError.c b/src/os/OSError.c index 59001fd..1468d91 100644 --- a/src/os/OSError.c +++ b/src/os/OSError.c @@ -5,7 +5,7 @@ // internal include #include "__os.h" -static OSErrorHandler OSErrorTable[15]; +static OSErrorHandler OSErrorTable[OS_ERROR_MAX]; void OSReport(char* msg, ...) { va_list marker; @@ -36,7 +36,12 @@ void OSPanic(char* file, int line, char* msg, ...) { OSErrorHandler OSSetErrorHandler(OSError error, OSErrorHandler handler) { OSErrorHandler oldHandler; +#if DOLPHIN_REVISION >= 45 + // Is __OS_EXCEPTION_MAX supposed to be different? + ASSERTMSGLINE(0x8F, error < __OS_EXCEPTION_MAX+1, "OSSetErrorHandler(): unknown error."); +#else ASSERTMSGLINE(0x8F, error < __OS_EXCEPTION_MAX, "OSSetErrorHandler(): unknown error."); +#endif oldHandler = OSErrorTable[error]; OSErrorTable[error] = handler; return oldHandler; 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..849f3ac 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/OSInterrupt.c b/src/os/OSInterrupt.c index 990adac..6c7c8d9 100644 --- a/src/os/OSInterrupt.c +++ b/src/os/OSInterrupt.c @@ -121,13 +121,15 @@ asm BOOL OSRestoreInterrupts(register BOOL level){ // clang-format on } +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 3 : 0) + __OSInterruptHandler __OSSetInterruptHandler(__OSInterrupt interrupt, __OSInterruptHandler handler) { __OSInterruptHandler oldHandler; - ASSERTMSGLINE(0x188, InterruptHandlerTable, "__OSSetInterruptHandler(): OSInit() must be called in advance."); - ASSERTMSGLINE(0x18A, interrupt < 0x20, "__OSSetInterruptHandler(): unknown interrupt."); + ASSERTMSGLINE(0x188+LINE_OFFSET, InterruptHandlerTable, "__OSSetInterruptHandler(): OSInit() must be called in advance."); + ASSERTMSGLINE(0x18A+LINE_OFFSET, interrupt < 0x20, "__OSSetInterruptHandler(): unknown interrupt."); oldHandler = InterruptHandlerTable[interrupt]; InterruptHandlerTable[interrupt] = handler; @@ -135,8 +137,8 @@ __OSInterruptHandler } __OSInterruptHandler __OSGetInterruptHandler(__OSInterrupt interrupt) { - ASSERTMSGLINE(0x19E, InterruptHandlerTable, "__OSGetInterruptHandler(): OSInit() must be called in advance."); - ASSERTMSGLINE(0x1A0, interrupt < 0x20, "__OSGetInterruptHandler(): unknown interrupt."); + ASSERTMSGLINE(0x19E+LINE_OFFSET, InterruptHandlerTable, "__OSGetInterruptHandler(): OSInit() must be called in advance."); + ASSERTMSGLINE(0x1A0+LINE_OFFSET, interrupt < 0x20, "__OSGetInterruptHandler(): unknown interrupt."); return InterruptHandlerTable[interrupt]; } @@ -168,6 +170,9 @@ static u32 SetInterruptMask(OSInterruptMask mask, OSInterruptMask current) { case __OS_INTERRUPT_MEM_1: case __OS_INTERRUPT_MEM_2: case __OS_INTERRUPT_MEM_3: +#if DOLPHIN_REVISION >= 45 + case __OS_INTERRUPT_MEM_ADDRESS: +#endif reg = 0; if (!(current & OS_INTERRUPTMASK_MEM_0)) reg |= 0x1; diff --git a/src/os/OSLink.c b/src/os/OSLink.c index 4dc1500..a36b330 100755 --- a/src/os/OSLink.c +++ b/src/os/OSLink.c @@ -38,10 +38,10 @@ #define R_PPC_PLTREL24 18 // low24* (L + A - P) >> 2 #define R_PPC_COPY 19 // none none #define R_PPC_GLOB_DAT 20 // word32 S + A -#define R_PPC_JMP_SLOT 21 // none +#define R_PPC_JMP_SLOT 21 // none #define R_PPC_RELATIVE 22 // word32 B + A -#define R_PPC_LOCAL24PC 23 // low24* +#define R_PPC_LOCAL24PC 23 // low24* #define R_PPC_UADDR32 24 // word32 S + A #define R_PPC_UADDR16 25 // half16* S + A @@ -68,14 +68,14 @@ #define R_PPC_EMB_SDAI16 106 // uhalf16 Y T #define R_PPC_EMB_SDA2I16 107 // uhalf16 Y U #define R_PPC_EMB_SDA2REL 108 // uhalf16 Y S + A - _SDA2_BASE_ -#define R_PPC_EMB_SDA21 109 // ulow21 N -#define R_PPC_EMB_MRKREF 110 // none N +#define R_PPC_EMB_SDA21 109 // ulow21 N +#define R_PPC_EMB_MRKREF 110 // none N #define R_PPC_EMB_RELSEC16 111 // uhalf16 Y V + A #define R_PPC_EMB_RELST_LO 112 // uhalf16 N #lo(W + A) #define R_PPC_EMB_RELST_HI 113 // uhalf16 N #hi(W + A) #define R_PPC_EMB_RELST_HA 114 // uhalf16 N #ha(W + A) -#define R_PPC_EMB_BIT_FLD 115 // uword32 Y -#define R_PPC_EMB_RELSDA 116 // uhalf16 Y +#define R_PPC_EMB_BIT_FLD 115 // uword32 Y +#define R_PPC_EMB_RELSDA 116 // uhalf16 Y OSModuleQueue __OSModuleInfoList : (OS_BASE_CACHED | 0x30C8); const void* __OSStringTable : (OS_BASE_CACHED | 0x30D0); @@ -217,10 +217,23 @@ BOOL OSLink(OSModuleInfo* newModule, void* bss) { OSModuleInfo* moduleInfo; OSImportInfo* imp; +#if DOLPHIN_REVISION >= 45 + ASSERTLINE(0xF1, newModule->version <= OS_MODULE_VERSION); +#else ASSERTLINE(0xEB, newModule->version == OS_MODULE_VERSION); +#endif moduleHeader = (OSModuleHeader*)newModule; +#if DOLPHIN_REVISION >= 45 + ASSERTLINE(0xF6, newModule->version < 2 || (u32) newModule % moduleHeader->align == 0); + ASSERTLINE(0xF7, newModule->version < 2 || (u32) bss % moduleHeader->bssAlign == 0); + if (newModule->version > 2 + || (newModule->version >= 2U && ((u32)newModule % moduleHeader->align != 0 || (u32)bss % moduleHeader->bssAlign != 0))) { + return 0; + } +#endif + ENQUEUE_INFO(&__OSModuleInfoList, newModule, link); memset(bss, 0, moduleHeader->bssSize); @@ -271,6 +284,8 @@ BOOL OSLink(OSModuleInfo* newModule, void* bss) { return TRUE; } +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 18 : 0) + static BOOL Undo(OSModuleHeader* newModule, OSModuleHeader* module) { OSModuleID idNew; OSImportInfo* imp; @@ -281,10 +296,10 @@ static BOOL Undo(OSModuleHeader* newModule, OSModuleHeader* module) { u32 offset; u32 x; - ASSERTLINE(0x147, newModule); + ASSERTLINE(0x147+LINE_OFFSET, newModule); idNew = newModule->info.id; - ASSERTLINE(0x149, idNew); - + ASSERTLINE(0x149+LINE_OFFSET, idNew); + for (imp = (OSImportInfo*)module->impOffset; imp < (OSImportInfo*)(module->impOffset + module->impSize); imp++) { if (imp->id == idNew) { @@ -358,7 +373,11 @@ BOOL OSUnlink(OSModuleInfo* oldModule) { OSModuleHeader* moduleHeader; OSModuleInfo* moduleInfo; - ASSERTLINE(0x1AA, oldModule->version == OS_MODULE_VERSION); +#if DOLPHIN_REVISION >= 45 + ASSERTLINE(0x1AA+LINE_OFFSET, oldModule->version <= OS_MODULE_VERSION); +#else + ASSERTLINE(0x1AA+LINE_OFFSET, oldModule->version == OS_MODULE_VERSION); +#endif moduleHeader = (OSModuleHeader*)oldModule; DEQUEUE_INFO(oldModule, &__OSModuleInfoList, link); diff --git a/src/os/OSMemory.c b/src/os/OSMemory.c index 884771a..c415047 100644 --- a/src/os/OSMemory.c +++ b/src/os/OSMemory.c @@ -1,6 +1,18 @@ #include #include #include +#include "__os.h" + +#if DOLPHIN_REVISION >= 45 +static BOOL OnReset(BOOL final); + +static OSResetFunctionInfo ResetFunctionInfo = { + OnReset, + 127, + NULL, + NULL +}; +#endif u32 OSGetPhysicalMemSize(void) { #if DEBUG @@ -12,6 +24,75 @@ u32 OSGetPhysicalMemSize(void) { #endif } +#if DOLPHIN_REVISION >= 45 // this got moved +u32 OSGetConsoleSimulatedMemSize(void) { +#if DEBUG + unsigned long * memSize = (unsigned long *)OSPhysicalToCached(0xF0); + + return *memSize; +#else + return __OSSimulatedMemSize; +#endif +} +#endif + +#if DOLPHIN_REVISION >= 45 +static BOOL OnReset(BOOL final) +{ + if (final) { + __MEMRegs[8] = 0xFF; + __OSMaskInterrupts(0xF0000000); + } + return TRUE; +} + +static void MEMIntrruptHandler(__OSInterrupt interrupt, OSContext *context) +{ + u32 addr; + u32 cause; + + cause = __MEMRegs[15]; + addr = ((__MEMRegs[18] << 16) & 0x3FF0000) | __MEMRegs[17]; + __MEMRegs[16] = 0; + __OSUnhandledException(15, context, cause, addr); +} + +#define OS_PROTECT_CONTROL_RDWR 3 + +void OSProtectRange(u32 chan, void *addr, u32 nBytes, u32 control) +{ + BOOL enabled; + u32 start; + u32 end; + u16 reg; + + ASSERTLINE(0xA0, chan < 4); + ASSERTLINE(0xA1, (control & ~(OS_PROTECT_CONTROL_RDWR)) == 0); + if (chan >= 4) { + return; + } + control &= 3; + end = (u32)addr + nBytes; + start = (u32)addr & ~0x3FF; + end = (end + 0x3FF) & ~0x3FF; + DCFlushRange((void *)start, end - start); + enabled = OSDisableInterrupts(); + __OSMaskInterrupts(OS_INTERRUPTMASK(chan)); + __MEMRegs[chan * 2 + 0] = start >> 10; + __MEMRegs[chan * 2 + 1] = end >> 10; + reg = __MEMRegs[8]; + reg &= ~(3 << (chan * 2)); + reg |= control << (chan * 2); + __MEMRegs[8] = reg; + if (control != 3) { + __OSUnmaskInterrupts(OS_INTERRUPTMASK(chan)); + } + OSRestoreInterrupts(enabled); + +} +#endif + +#if DOLPHIN_REVISION < 45 // this got moved u32 OSGetConsoleSimulatedMemSize(void) { #if DEBUG unsigned long * memSize = (unsigned long *)OSPhysicalToCached(0xF0); @@ -21,3 +102,37 @@ u32 OSGetConsoleSimulatedMemSize(void) { return __OSSimulatedMemSize; #endif } +#endif + +#if DOLPHIN_REVISION >= 45 +void __OSInitMemoryProtection(void) +{ + __MEMRegs[16] = 0; + __MEMRegs[8] = 0xFF; + __OSMaskInterrupts(0xF0000000); + __OSSetInterruptHandler(0, MEMIntrruptHandler); + __OSSetInterruptHandler(1, MEMIntrruptHandler); + __OSSetInterruptHandler(2, MEMIntrruptHandler); + __OSSetInterruptHandler(3, MEMIntrruptHandler); + __OSSetInterruptHandler(4, MEMIntrruptHandler); + OSRegisterResetFunction(&ResetFunctionInfo); + +#if DEBUG + if (OSGetConsoleSimulatedMemSize() < OSGetPhysicalMemSize() + && OSGetConsoleSimulatedMemSize() - 0x1800000 == 0) { + __MEMRegs[20] = 2; + } +#else +{ + u32 sim = OSGetConsoleSimulatedMemSize(); + u32 phys = OSGetPhysicalMemSize(); + u8 unused[20]; + if (sim < phys + && OSGetConsoleSimulatedMemSize() - 0x1800000 == 0) { + __MEMRegs[20] = 2; + } +} +#endif + __OSUnmaskInterrupts(0x8000000); +} +#endif diff --git a/src/os/OSReboot.c b/src/os/OSReboot.c new file mode 100644 index 0000000..774e854 --- /dev/null +++ b/src/os/OSReboot.c @@ -0,0 +1,146 @@ +#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" + +static struct { + char date[16]; + u32 entry; + u32 size; + u32 rebootSize; + u32 reserved2; +} Header; + +#if DOLPHIN_REVISION >= 45 +static void *SaveStart; +static void *SaveEnd; +#endif +static volatile BOOL Prepared; + +#pragma dont_inline on +static void Run(register void *entryPoint) +{ + entryPoint; // needed because the compiler is stupid + + OSDisableInterrupts(); + ICFlashInvalidate(); + asm { + sync + isync + mtlr entryPoint + blr + } +} +#pragma dont_inline reset + +#pragma peephole off + +static void ReadApploader(void *addr, long length, long offset) +{ + DVDCommandBlock block; + + while (!Prepared) { + } + DVDReadAbsAsyncForBS(&block, addr, length, offset + 0x2440, NULL); + while(1) + { + switch (block.state) { + case 0: + return; + case 1: + break; + 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; + default: + ASSERTLINE(0xB4, FALSE); + break; + } + } +} + +static void Callback(void) { + + Prepared = TRUE; +} + +void __OSReboot(unsigned long resetCode, int forceMenu) +{ + u32 offset; + u32 length; + OSContext exceptionContext; + +#if DOLPHIN_REVISION >= 45 && DEBUG + if (forceMenu == 1) { + OSReport("OSResetSystem(): You can't specify TRUE to forceMenu if you Restart. Ignored\n"); + } +#endif + + OSDisableInterrupts(); + UNK_817FFFFC = resetCode; + UNK_817FFFF8 = 0; + UNK_800030E2 = 1; +#if DOLPHIN_REVISION >= 45 + UNK_812FDFF0 = SaveStart; + UNK_812FDFEC = SaveEnd; +#endif + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + DVDInit(); +#if DOLPHIN_REVISION >= 45 + DVDSetAutoInvalidation(1); +#endif + __DVDPrepareResetAsync(Callback); + if (!DVDCheckDisk()) { + __OSDoHotReset(UNK_817FFFFC); + } + __OSMaskInterrupts(~0x1F); + __OSUnmaskInterrupts(0x400); + OSEnableInterrupts(); + ReadApploader(&Header, 32, 0); +#if DOLPHIN_REVISION >= 45 + ASSERTMSGLINE(0x101, Header.rebootSize != 0, "OSResetSystem(): old apploader"); +#endif + offset = Header.size + 32; + length = OSRoundUp32B(Header.rebootSize); + ReadApploader((void *)0x81300000, length, offset); + + ICInvalidateRange((void *)0x81300000, length); + Run((void *)0x81300000); +} + +#if DOLPHIN_REVISION >= 45 +void OSSetSaveRegion(void *start, void *end) +{ + ASSERTMSGLINE(0x112, (u32)start >= 0x80700000 || start == NULL, "OSSetSaveRegion(): start address should be NULL or higher than 0x80700000\n"); + ASSERTMSGLINE(0x113, 0x81200000 >= (u32)end || end == NULL, "OSSetSaveRegion(): end address should be NULL or lower than 0x81200000\n"); + ASSERTMSGLINE(0x114, !((start == NULL) ^ (end == NULL)), "OSSetSaveRegion(): if either start or end is NULL, both should be NULL\n"); + SaveStart = start; + SaveEnd = end; +} + +void OSGetSaveRegion(void **start, void **end) +{ + *start = SaveStart; + *end = SaveEnd; +} +#endif + +#endif // DOLPHIN_REVISION >= 37 diff --git a/src/os/OSReset.c b/src/os/OSReset.c index 25c9448..f8f8300 100644 --- a/src/os/OSReset.c +++ b/src/os/OSReset.c @@ -62,8 +62,10 @@ static struct OSResetFunctionQueue ResetFunctionQueue; static int CallResetFunctions(int final); static asm void Reset(unsigned long resetCode); +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 33 : 0) + void OSRegisterResetFunction(struct OSResetFunctionInfo * info) { - ASSERTLINE(0x76, info->func); + ASSERTLINE(0x76+LINE_OFFSET, info->func); ENQUEUE_INFO_PRIO(info, &ResetFunctionQueue); } @@ -72,7 +74,11 @@ void OSUnregisterResetFunction(struct OSResetFunctionInfo * info) { DEQUEUE_INFO(info, &ResetFunctionQueue); } +#if DOLPHIN_REVISION >= 45 +int __OSCallResetFunctions(int final) { +#else static int CallResetFunctions(int final) { +#endif struct OSResetFunctionInfo * info; int err = 0; @@ -127,6 +133,38 @@ static asm void Reset(unsigned long resetCode) { b L_000001A0 } +#if DOLPHIN_REVISION >= 37 +static void KillThreads(void) +{ + OSThread *thread; + OSThread *next; + + thread = UNK_800000DC; + while (thread) { + next = thread->linkActive.next; + switch (thread->state) { + case 1: + case 4: + OSCancelThread(thread); + break; + } + thread = next; + } +} +#endif + +#if DOLPHIN_REVISION >= 37 +void __OSDoHotReset(u32 resetCode) { + OSDisableInterrupts(); + __VIRegs[1] = 0; + ICFlashInvalidate(); + Reset(resetCode << 3); +} +#endif + +#undef LINE_OFFSET +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 69 : 0) + void OSResetSystem(int reset, unsigned long resetCode, int forceMenu) { int rc; int enabled; @@ -134,7 +172,11 @@ void OSResetSystem(int reset, unsigned long resetCode, int forceMenu) { OSDisableScheduler(); __OSStopAudioSystem(); +#if DOLPHIN_REVISION >= 45 + do {} while (__OSCallResetFunctions(0) == 0); +#else do {} while (CallResetFunctions(0) == 0); +#endif if ((reset != 0 && (forceMenu != 0))) { sram = __OSLockSram(); @@ -143,16 +185,43 @@ void OSResetSystem(int reset, unsigned long resetCode, int forceMenu) { do {} while(__OSSyncSram() == 0); } enabled = OSDisableInterrupts(); +#if DOLPHIN_REVISION >= 45 + rc = __OSCallResetFunctions(1); +#else rc = CallResetFunctions(1); - ASSERTLINE(0x117, rc); +#endif + ASSERTLINE(0x117+LINE_OFFSET, rc); +#if DOLPHIN_REVISION >= 45 + LCDisable(); +#endif +#if DOLPHIN_REVISION >= 37 + if (reset == 1) { + __OSDoHotReset(resetCode); + } else { + KillThreads(); + OSEnableScheduler(); + __OSReboot(resetCode, forceMenu); + } +#else if (reset != 0) { ICFlashInvalidate(); Reset(resetCode * 8); } +#endif OSRestoreInterrupts(enabled); OSEnableScheduler(); } unsigned long OSGetResetCode() { +#if DOLPHIN_REVISION >= 45 + u32 resetCode; + + if (UNK_800030E2 != 0) { + return 0x80000000; + } + resetCode = (__PIRegs[9] & 0xFFFFFFF8) / 8; + return resetCode; +#else return (__PIRegs[9] & 0xFFFFFFF8) / 8; +#endif } diff --git a/src/os/OSResetSW.c b/src/os/OSResetSW.c index 9bc6047..acea4cf 100644 --- a/src/os/OSResetSW.c +++ b/src/os/OSResetSW.c @@ -1,3 +1,6 @@ +#if DOLPHIN_REVISION >= 45 +#include +#endif #include #include @@ -5,11 +8,41 @@ 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)) { +#if DOLPHIN_REVISION >= 45 + LastState = Down = 1; +#else + Down = 1; + LastState = 1; +#endif + __OSMaskInterrupts(0x200); + if (ResetCallback != NULL) { + callback = ResetCallback; + ResetCallback = NULL; + callback(); + } + } + __PIRegs[0] = 2; +#else + Down = 1; __PIRegs[0] = 2; __OSMaskInterrupts(0x200); @@ -19,6 +52,7 @@ void __OSResetSWInterruptHandler(short exception, struct OSContext *context) { ResetCallback = NULL; callback(); } +#endif } OSResetCallback OSSetResetCallback(OSResetCallback callback) { @@ -39,7 +73,65 @@ OSResetCallback OSSetResetCallback(OSResetCallback callback) { return prevCallback; } +#if DOLPHIN_REVISION >= 45 +int OSGetResetButtonState(void) +{ + BOOL enabled; + int state; + u32 reg; + OSTime now; + OSTime fire; + + enabled = OSDisableInterrupts(); + now = __OSGetSystemTime(); + ASSERTLINE(0x97, 0 <= now); + ASSERTLINE(0x98, HoldUp == 0 || HoldUp < now); + ASSERTLINE(0x99, HoldDown == 0 || HoldDown < now); + reg = __PIRegs[0]; + if (!(reg & 0x10000)) { + if (Down == 0) { + Down = 1; + state = HoldUp ? 1 : 0; + HoldDown = now; + } + else { + state = (HoldUp || OSMicrosecondsToTicks(100) < (now - HoldDown)) ? 1 : 0; + } + } else if (Down) { + Down = 0; + state = LastState; + if (state != 0) { + HoldUp = now; + } else { + HoldUp = 0; + } + } else if (HoldUp && (now - HoldUp) < OSMillisecondsToTicks(40)) { + state = 1; + } else { + state = 0; + HoldUp = 0; + } + LastState = state; + if ((state == 0) && (UNK_800030E3 & 0x3F)) { + fire = (UNK_800030E3 & 0x3F) * 60; + fire = __OSStartTime + OSSecondsToTicks(fire); + if (fire < now) { + now -= fire; + now = OSTicksToSeconds(now) / 2; + if ((now & 1) == 0 || Down) { + state = 1; + } + } + } + OSRestoreInterrupts(enabled); + return state; +} +#endif + int OSGetResetSwitchState() { +#if DOLPHIN_REVISION >= 45 + return OSGetResetButtonState(); +#else int enabled; int state; unsigned long reg; @@ -47,6 +139,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 +180,23 @@ int OSGetResetSwitchState() { state = 0; Hold = 0; } +#endif OSRestoreInterrupts(enabled); return state; +#endif +} + +#if DOLPHIN_REVISION >= 45 +void __OSSetResetButtonTimer(u8 min) +{ + BOOL enabled; + + enabled = OSDisableInterrupts(); + if (min > 63) { + min = 63; + } + UNK_800030E3 &= 0xC0; + UNK_800030E3 |= min; + OSRestoreInterrupts(enabled); } +#endif diff --git a/src/os/OSRtc.c b/src/os/OSRtc.c index 708868c..c79bb9f 100644 --- a/src/os/OSRtc.c +++ b/src/os/OSRtc.c @@ -104,14 +104,16 @@ static int ReadSram(void * buffer) { return !err; } +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 9 : 0) + static void WriteSramCallback() { int unused; - ASSERTLINE(0xF0, !Scb.locked); + ASSERTLINE(0xF0+LINE_OFFSET, !Scb.locked); Scb.sync = WriteSram(&Scb.sram[Scb.offset], Scb.offset, 0x40 - Scb.offset); if (Scb.sync != 0) { Scb.offset = 0x40; } - ASSERTLINE(0xF6, Scb.sync); + ASSERTLINE(0xF6+LINE_OFFSET, Scb.sync); } static int WriteSram(void * buffer, unsigned long offset, unsigned long size) { @@ -139,7 +141,7 @@ static int WriteSram(void * buffer, unsigned long offset, unsigned long size) { void __OSInitSram() { Scb.locked = Scb.enabled = 0; Scb.sync = ReadSram(&Scb); - ASSERTLINE(0x12C, Scb.sync); + ASSERTLINE(0x12C+LINE_OFFSET, Scb.sync); Scb.offset = 0x40; } @@ -147,7 +149,7 @@ static void * LockSram(unsigned long offset) { int enabled; enabled = OSDisableInterrupts(); - ASSERTLINE(0x140, !Scb.locked); + ASSERTLINE(0x140+LINE_OFFSET, !Scb.locked); if (Scb.locked) { OSRestoreInterrupts(enabled); return NULL; @@ -168,10 +170,15 @@ struct OSSramEx * __OSLockSramEx(void) { static int UnlockSram(int commit, unsigned long offset) { unsigned short * p; - ASSERTLINE(0x162, Scb.locked); + ASSERTLINE(0x162+LINE_OFFSET, Scb.locked); 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; @@ -203,6 +210,9 @@ int __OSSyncSram() { return Scb.sync; } +#undef LINE_OFFSET +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 15 : 0) + int __OSCheckSram() { unsigned short * p; unsigned short checkSum; @@ -210,7 +220,7 @@ int __OSCheckSram() { struct OSSram * sram; int unused; - ASSERTLINE(0x1A9, Scb.locked); + ASSERTLINE(0x1A9+LINE_OFFSET, Scb.locked); checkSum = checkSumInv = 0; @@ -228,7 +238,7 @@ int __OSReadROM(void * buffer, long length, long offset) { int err; unsigned long cmd; - ASSERTLINE(0x1C8, length <= 1024); + ASSERTLINE(0x1C8+LINE_OFFSET, length <= 1024); DCInvalidateRange(buffer, length); if (EXILock(0, 1, NULL) == 0) { return 0; @@ -264,8 +274,8 @@ int __OSReadROMAsync(void * buffer, long length, long offset, void (* callback)( int err; unsigned long cmd; - ASSERTLINE(0x203, length <= 1024); - ASSERTLINE(0x204, callback); + ASSERTLINE(0x203+LINE_OFFSET, length <= 1024); + ASSERTLINE(0x204+LINE_OFFSET, callback); DCInvalidateRange(buffer, length); Scb.callback = callback; if (EXILock(0, 1, NULL) == 0) { @@ -295,7 +305,7 @@ void OSSetSoundMode(unsigned long mode) { struct OSSram * sram; int unused; - ASSERTLINE(0x22A, mode == OS_SOUND_MODE_MONO || mode == OS_SOUND_MODE_STEREO); + ASSERTLINE(0x22A+LINE_OFFSET, mode == OS_SOUND_MODE_MONO || mode == OS_SOUND_MODE_STEREO); mode *= 4; mode &= 4; sram = __OSLockSram(); @@ -308,21 +318,65 @@ void OSSetSoundMode(unsigned long mode) { __OSUnlockSram(1); } +#if DOLPHIN_REVISION >= 45 +u32 OSGetProgressiveMode(void) +{ + struct OSSram *sram; + u32 on; + + sram = __OSLockSram(); + on = (sram->flags & 0x80) ? 1 : 0; + __OSUnlockSram(0); + return on; +} + +void OSSetProgressiveMode(u32 on) +{ + struct OSSram *sram; + + ASSERTLINE(0x258, on == OS_PROGRESSIVE_MODE_OFF || on == OS_PROGRESSIVE_MODE_ON); + on <<= 7; + on &= 0x80; + sram = __OSLockSram(); + if (on == (sram->flags & 0x80)) { + __OSUnlockSram(0); + } else { + sram->flags &= ~0x80; + sram->flags |= on; + __OSUnlockSram(1); + } +} +#endif + unsigned long OSGetVideoMode() { struct OSSram * sram = __OSLockSram(); unsigned long mode = sram->flags & 3; __OSUnlockSram(0); +#if DOLPHIN_REVISION >= 45 + if (mode > 2) { + mode = 0; + } +#endif return mode; } +#undef LINE_OFFSET +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 51 : 0) + void OSSetVideoMode(unsigned long mode) { struct OSSram * sram; int unused; - ASSERTLINE(0x249, OS_VIDEO_MODE_NTSC <= mode && mode <= OS_VIDEO_MODE_MPAL); + ASSERTLINE(0x249+LINE_OFFSET, OS_VIDEO_MODE_NTSC <= mode && mode <= OS_VIDEO_MODE_MPAL); +#if DOLPHIN_REVISION >= 45 + if (mode > 2) { + mode = 0; + } +#else mode &= 3; +#endif sram = __OSLockSram(); if (mode == (sram->flags & 3)) { __OSUnlockSram(0); @@ -374,3 +428,29 @@ void __OSSetBootMode(unsigned char ntd) { sram->ntd |= ntd; __OSUnlockSram(1); } + +#if DOLPHIN_REVISION >= 45 +u16 OSGetWirelessID(s32 chan) +{ + struct OSSramEx *sram; + u16 id; + + sram = __OSLockSramEx(); + id = sram->wirelessPadID[chan]; + __OSUnlockSramEx(0); + return id; +} + +void OSSetWirelessID(s32 chan, u16 id) +{ + struct OSSramEx *sram; + + sram = __OSLockSramEx(); + if (sram->wirelessPadID[chan] != id) { + sram->wirelessPadID[chan] = id; + __OSUnlockSramEx(1); + } else { + __OSUnlockSramEx(0); + } +} +#endif diff --git a/src/os/OSSerial.c b/src/os/OSSerial.c index 60ae7d0..01178f1 100644 --- a/src/os/OSSerial.c +++ b/src/os/OSSerial.c @@ -1,5 +1,7 @@ #include #include +#include +#include "__os.h" static struct SIControl Si = { /* chan */ -1, @@ -9,19 +11,54 @@ static struct SIControl Si = { /* callback */ NULL }; +#define SI_MAX_TYPE 4 + static struct SIPacket Packet[4]; static struct OSAlarm Alarm[4]; +#if DOLPHIN_REVISION >= 45 +static u32 Type[4] = {8, 8, 8, 8}; // size: 0x10, address: 0x14 +static OSTime TypeTime[4]; // size: 0x20, address: 0x120 +static OSTime XferTime[4]; // size: 0x20, address: 0x140 +static void (*TypeCallback[4][4])(s32, u32); // size: 0x40, address: 0x160 +static void (*RDSTHandler[4])(s16, OSContext *); // size: 0x10, address: 0x1A0 +static int InputBufferValid[4]; // size: 0x10, address: 0x1B0 +static u32 InputBuffer[4][2]; // size: 0x20, address: 0x1C0 +u32 __PADFixBits; +long long SIDelay; +#endif static unsigned long CompleteTransfer(); static void SITransferNext(long chan); static void SIIntrruptHandler(short unused, struct OSContext * context); static int __SITransfer(long chan, void * output, unsigned long outputBytes, void * input, unsigned long inputBytes, void (* callback)(long, unsigned long, struct OSContext *)); static void AlarmHandler(struct OSAlarm * alarm, struct OSContext * context); +#if DOLPHIN_REVISION >= 45 +static void SIGetResponseRaw(s32 chan); +static void GetTypeCallback(s32 chan, u32 error); +unsigned long SIGetType(s32 chan); +#endif int SIBusy() { return (Si.chan != -1) ? 1 : 0; } +#if DOLPHIN_REVISION >= 45 +int SIIsChanBusy(s32 chan) +{ + return (Packet[chan].chan != -1 || Si.chan == chan); +} + +static void SIClearTCInterrupt(void) +{ + unsigned long reg; + + reg = __SIRegs[SI_COMCSR_IDX]; + reg |= SI_COMCSR_TCINT_MASK; + reg &= ~1; + __SIRegs[SI_COMCSR_IDX] = reg; +} +#endif + static unsigned long CompleteTransfer() { unsigned long sr; unsigned long i; @@ -30,15 +67,22 @@ static unsigned long CompleteTransfer() { unsigned long temp; sr = __SIRegs[SI_STATUS_IDX]; +#if DOLPHIN_REVISION >= 45 + SIClearTCInterrupt(); +#else __SIRegs[SI_COMCSR_IDX] = SI_COMCSR_TCINT_MASK; +#endif if (Si.chan != -1) { +#if DOLPHIN_REVISION >= 45 + XferTime[Si.chan] = __OSGetSystemTime(); +#endif input = Si.input; rLen = (Si.inputBytes / 4); for(i = 0; i < rLen; i++) { *((u32*)input)++ = __SIRegs[i+0x20]; } - + rLen = Si.inputBytes & 3; if (rLen != 0) { temp = __SIRegs[i + 32]; @@ -46,8 +90,23 @@ static unsigned long CompleteTransfer() { *(input++) = temp >> ((3 - i) * 8); } } - sr >>= ((3 - Si.chan) * 8); - sr &= 0xF; +#if DOLPHIN_REVISION >= 45 + if ((__SIRegs[13] & 0x20000000) != 0) { +#endif + sr >>= ((3 - Si.chan) * 8); + sr &= 0xF; +#if DOLPHIN_REVISION >= 45 + if ((sr & 8) != 0 && (Type[Si.chan] & 0x80) == 0) { + Type[Si.chan] = 8; + } + if (sr == 0) { + sr = 4; + } + } else { + TypeTime[Si.chan] = __OSGetSystemTime(); + sr = 0; + } +#endif Si.chan = -1; } @@ -64,7 +123,11 @@ static void SITransferNext(long chan) { packet = &Packet[chan]; if (packet->chan != -1) { +#if DOLPHIN_REVISION >= 45 + if (packet->fire <= __OSGetSystemTime()) { +#else if (packet->time <= OSGetTime()) { +#endif if (__SITransfer(packet->chan, packet->output, packet->outputBytes, packet->input, packet->inputBytes, packet->callback) != 0) { OSCancelAlarm(&Alarm[chan]); packet->chan = -1; @@ -75,6 +138,135 @@ static void SITransferNext(long chan) { } } +#if DOLPHIN_REVISION >= 45 +static void SIInterruptHandler(s16 interrupt, struct OSContext * context) +{ + OSTime t0; + u32 reg; + s32 chan; + u32 sr; + void (*callback)(s32, u32, OSContext *); + int i; + u32 mask; + static u32 cmdTypeAndStatus; + + t0 = __OSGetSystemTime(); + reg = __SIRegs[13]; + if ((reg & 0xC0000000) == 0xC0000000) { + ASSERTLINE(0X15A, Si.chan != CHAN_NONE); + chan = Si.chan; + sr = CompleteTransfer(); + callback = Si.callback; + Si.callback = NULL; + SITransferNext(chan); + if (callback) { + callback(chan, sr, context); + } + sr = __SIRegs[14]; + sr &= 0xF000000 >> (chan * 8); + __SIRegs[14] = sr; + if (Type[chan] == 0x80 && !SIIsChanBusy(chan)) { + SITransfer(chan, &cmdTypeAndStatus, 1, &Type[chan], 3, (void *)GetTypeCallback, (u32)OSMicrosecondsToTicks(65)); + } + } + if ((reg & 0x18000000) != 0x18000000) { + return; + } + mask = 0; + if ((Si.poll & 0x80) != 0) { + mask |= 0x20000000; + } + if ((Si.poll & 0x40) != 0) { + mask |= 0x200000; + } + if ((Si.poll & 0x20) != 0) { + mask |= 0x2000; + } + if ((Si.poll & 0x10) != 0) { + mask |= 0x20; + } + while ((__SIRegs[14] & mask) != mask && __OSGetSystemTime() - t0 < OSMicrosecondsToTicks(65)) { + } + SIDelay = __OSGetSystemTime() - t0; + for (i = 0; i < 4; i++) { + SIGetResponseRaw(i); + } + for (i = 0; i < 4; i++) { + if (RDSTHandler[i]) { + RDSTHandler[i](interrupt, context); + } + } +} + +static int SIEnablePollingInterrupt(BOOL enable) +{ + BOOL enabled; + int rc; + u32 reg; + + enabled = OSDisableInterrupts(); + reg = __SIRegs[13]; + rc = (reg & 0x8000000) ? 1 : 0; + if (enable) { + reg |= 0x8000000; + } else { + reg &= ~0x8000000; + } + reg &= ~0x80000001; + __SIRegs[13] = reg; + OSRestoreInterrupts(enabled); + return rc; +} + +int SIRegisterPollingHandler(void (*handler)(s16, OSContext *)) +{ + BOOL enabled; + int i; + + enabled = OSDisableInterrupts(); + for (i = 0; i < 4; i++) { + if (RDSTHandler[i] == handler) { + OSRestoreInterrupts(enabled); + return 1; + } + } + for (i = 0; i < 4; i++) { + if (!RDSTHandler[i]) { + RDSTHandler[i] = handler; + SIEnablePollingInterrupt(TRUE); + OSRestoreInterrupts(enabled); + return 1; + } + } + OSRestoreInterrupts(enabled); + return 0; +} + +int SIUnregisterPollingHandler(void (*handler)(signed short, struct OSContext *)) +{ + BOOL enabled; + int i; + + enabled = OSDisableInterrupts(); + for (i = 0; i < 4; i++) { + if (RDSTHandler[i] == handler) { + RDSTHandler[i] = NULL; + for (i = 0; i < 4; i++) { + if (RDSTHandler[i]) { + break; + } + } + if (i == 4) { + SIEnablePollingInterrupt(FALSE); + } + OSRestoreInterrupts(enabled); + return 1; + } + } + OSRestoreInterrupts(enabled); + return 0; +} +#else static void SIIntrruptHandler(short unused, struct OSContext * context) { long chan; unsigned long sr; @@ -91,16 +283,29 @@ static void SIIntrruptHandler(short unused, struct OSContext * context) { callback(chan, sr, context); } } +#endif void SIInit() { Packet[0].chan = Packet[1].chan = Packet[2].chan = Packet[3].chan = -1; __SIRegs[0x30/4] = 0; do {} while(__SIRegs[SI_COMCSR_IDX] & SI_COMCSR_TSTART_MASK); __SIRegs[SI_COMCSR_IDX] = SI_COMCSR_TCINT_MASK; +#if DOLPHIN_REVISION >= 45 + __OSSetInterruptHandler(0x14, SIInterruptHandler); +#else __OSSetInterruptHandler(0x14, SIIntrruptHandler); +#endif __OSUnmaskInterrupts(0x800); +#if DOLPHIN_REVISION >= 45 + SIGetType(0); + SIGetType(1); + SIGetType(2); + SIGetType(3); +#endif } +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 277 : 0) + static int __SITransfer(long chan, void * output, unsigned long outputBytes, void * input, unsigned long inputBytes, void (* callback)(long, unsigned long, struct OSContext *)) { int enabled; unsigned long rLen; @@ -124,20 +329,20 @@ static int __SITransfer(long chan, void * output, unsigned long outputBytes, voi } f; } comcsr; - ASSERTMSGLINE(0x12A, (chan >= 0) && (chan < 4), "SITransfer(): invalid channel."); - ASSERTMSGLINE(0x12C, (outputBytes != 0) && (outputBytes <= 128), "SITransfer(): output size is out of range (must be 1 to 128)."); - ASSERTMSGLINE(0x12E, (inputBytes != 0) && (inputBytes <= 128), "SITransfer(): input size is out of range (must be 1 to 128)."); + ASSERTMSGLINE(0x12A+LINE_OFFSET, (chan >= 0) && (chan < 4), "SITransfer(): invalid channel."); + ASSERTMSGLINE(0x12C+LINE_OFFSET, (outputBytes != 0) && (outputBytes <= 128), "SITransfer(): output size is out of range (must be 1 to 128)."); + ASSERTMSGLINE(0x12E+LINE_OFFSET, (inputBytes != 0) && (inputBytes <= 128), "SITransfer(): input size is out of range (must be 1 to 128)."); enabled = OSDisableInterrupts(); if (Si.chan != -1) { OSRestoreInterrupts(enabled); return 0; } - ASSERTLINE(0x138, (__SIRegs[SI_COMCSR_IDX] & (SI_COMCSR_TSTART_MASK | SI_COMCSR_TCINT_MASK)) == 0); + ASSERTLINE(0x138+LINE_OFFSET, (__SIRegs[SI_COMCSR_IDX] & (SI_COMCSR_TSTART_MASK | SI_COMCSR_TCINT_MASK)) == 0); sr = __SIRegs[SI_STATUS_IDX]; sr &= (0x0F000000 >> (chan * 8)); __SIRegs[SI_STATUS_IDX] = sr; - + Si.chan = chan; Si.callback = callback; Si.inputBytes = inputBytes; @@ -147,8 +352,12 @@ static int __SITransfer(long chan, void * output, unsigned long outputBytes, voi for (i = 0; i < rLen; i++) { __SIRegs[i+0x20] = ((u32*)output)[i]; } - + +#if DOLPHIN_REVISION >= 45 + comcsr.val = __SIRegs[13]; +#else comcsr.val = 0; +#endif comcsr.f.tcint = 1; comcsr.f.tcintmsk = callback ? 1 : 0; comcsr.f.outlngth = outputBytes == 0x80 ? 0 : outputBytes; @@ -175,16 +384,37 @@ unsigned long SISync() { } unsigned long SIGetStatus() { +#if DOLPHIN_REVISION >= 45 + BOOL enabled; + u32 sr; + int chan; + int chanShift; + + enabled = OSDisableInterrupts(); + sr = __SIRegs[SI_STATUS_IDX]; + for (chan = 0; chan < 4; chan++) { + chanShift = (3 - chan) * 8; + if ((sr & (8 << chanShift)) && !(Type[chan] & 0x80)) { + Type[chan] = 8; + } + } + OSRestoreInterrupts(enabled); + return sr; +#else return __SIRegs[SI_STATUS_IDX]; +#endif } +#undef LINE_OFFSET +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 295 : 0) + void SISetCommand(long chan, unsigned long command) { - ASSERTMSGLINE(0x197, (chan >= 0) && (chan < 4), "SISetCommand(): invalid channel."); + ASSERTMSGLINE(0x197+LINE_OFFSET, (chan >= 0) && (chan < 4), "SISetCommand(): invalid channel."); __SIRegs[chan * 3] = command; } unsigned long SIGetCommand(long chan) { - ASSERTMSGLINE(0x1A9, (chan >= 0) && (chan < 4), "SIGetCommand(): invalid channel."); + ASSERTMSGLINE(0x1A9+LINE_OFFSET, (chan >= 0) && (chan < 4), "SIGetCommand(): invalid channel."); return __SIRegs[chan * 3]; } @@ -196,9 +426,9 @@ unsigned long SISetXY(unsigned long x, unsigned long y) { unsigned long poll; int enabled; - ASSERTMSGLINE(0x1CA, x >= 8, "SISetXY(): x is out of range (8 <= x <= 255)."); - ASSERTMSGLINE(0x1CB, x <= 255, "SISetXY(): x is out of range (8 <= x <= 255)."); - ASSERTMSGLINE(0x1CC, y <= 255, "SISetXY(): y is out of range (0 <= y <= 255)."); + ASSERTMSGLINE(0x1CA+LINE_OFFSET, x >= 8, "SISetXY(): x is out of range (8 <= x <= 255)."); + ASSERTMSGLINE(0x1CB+LINE_OFFSET, x <= 255, "SISetXY(): x is out of range (8 <= x <= 255)."); + ASSERTMSGLINE(0x1CC+LINE_OFFSET, y <= 255, "SISetXY(): y is out of range (0 <= y <= 255)."); poll = x << 0x10; poll |= y << 8; @@ -214,39 +444,61 @@ unsigned long SIEnablePolling(unsigned long poll) { int enabled; unsigned long en; - ASSERTMSGLINE(0x1E8, !(poll & 0x0FFFFFFF), "SIEnablePolling(): invalid chan bit(s)."); + ASSERTMSGLINE(0x1E8+LINE_OFFSET, !(poll & 0x0FFFFFFF), "SIEnablePolling(): invalid chan bit(s)."); if (poll == 0) { return Si.poll; } - + enabled = OSDisableInterrupts(); +#if DOLPHIN_REVISION >= 37 + poll >>= 24; +#if DOLPHIN_REVISION >= 45 + en = poll & 0xF0; + ASSERTLINE(0x32E, en); + poll &= 0x03FFFFF0 | (en >> 4); +#else + Si.poll &= ~((poll >> 4) & 0xF); + poll &= 0x03FFFFF0 | ((poll >> 4) & 0xF); +#endif + 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 +#if DOLPHIN_REVISION >= 45 + Si.poll &= ~(en >> 4); +#endif Si.poll |= poll; poll = Si.poll; +#if DOLPHIN_REVISION >= 45 + SITransferCommands(); +#else __SIRegs[0x38/4] = 0x80000000; +#endif __SIRegs[0x30/4] = poll; OSRestoreInterrupts(enabled); return poll; } +#undef LINE_OFFSET +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 300 : 0) + unsigned long SIDisablePolling(unsigned long poll) { int enabled; - ASSERTMSGLINE(0x22D, !(poll & 0x0FFFFFFF), "SIDisablePolling(): invalid chan bit(s)."); + ASSERTMSGLINE(0x22D+LINE_OFFSET, !(poll & 0x0FFFFFFF), "SIDisablePolling(): invalid chan bit(s)."); if (poll == 0) { return Si.poll; } enabled = OSDisableInterrupts(); poll = poll >> 24; poll &= 0xF0; - ASSERTLINE(0x23A, poll); + ASSERTLINE(0x23A+LINE_OFFSET, poll); poll = Si.poll & ~poll; __SIRegs[0x30/4] = poll; Si.poll = poll; @@ -254,47 +506,124 @@ unsigned long SIDisablePolling(unsigned long poll) { return poll; } -void SIGetResponse(long chan, void * data) { - ASSERTMSGLINE(0x250, ((chan >= 0) && (chan < 4)), "SIGetResponse(): invalid channel."); +#if DOLPHIN_REVISION >= 45 +static void SIGetResponseRaw(s32 chan) +{ + u32 sr; + int chanShift; + + sr = SIGetStatus(); + chanShift = (3 - chan) * 8; + if (sr & (0x20 << chanShift)) { + InputBuffer[chan][0] = __SIRegs[1 + chan * 3]; + InputBuffer[chan][1] = __SIRegs[2 + chan * 3]; + InputBufferValid[chan] = TRUE; + } +} +#endif + +#undef LINE_OFFSET +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 328 : 0) + +#if DOLPHIN_REVISION >= 45 +int +#else +void +#endif +SIGetResponse(long chan, void * data) { +#if DOLPHIN_REVISION >= 45 + int rc; + BOOL enabled; +#endif + + ASSERTMSGLINE(0x250+LINE_OFFSET, ((chan >= 0) && (chan < 4)), "SIGetResponse(): invalid channel."); +#if DOLPHIN_REVISION >= 45 + enabled = OSDisableInterrupts(); + SIGetResponseRaw(chan); + rc = InputBufferValid[chan]; + InputBufferValid[chan] = FALSE; + if (rc) { + ((u32*)data)[0] = InputBuffer[chan][0]; + ((u32*)data)[1] = InputBuffer[chan][1]; + } + OSRestoreInterrupts(enabled); + return rc; +#else ((u32*)data)[0] = __SIRegs[chan * 3 + 1]; ((u32*)data)[1] = __SIRegs[chan * 3 + 2]; +#endif } +#undef LINE_OFFSET +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 337 : 0) + static void AlarmHandler(struct OSAlarm * alarm, struct OSContext * context) { long chan; struct SIPacket * packet; chan = alarm-Alarm; - ASSERTLINE(0x266, 0 <= chan && chan < SI_MAX_CHAN); + ASSERTLINE(0x266+LINE_OFFSET, 0 <= chan && chan < SI_MAX_CHAN); +#if DOLPHIN_REVISION >= 45 + packet = &Packet[chan]; + if (packet->chan != -1) { + ASSERTLINE(0x3BB, packet->fire <= __OSGetSystemTime()); // WTF? Dereferencing a NULL POINTER? + if (__SITransfer(packet->chan, packet->output, packet->outputBytes, packet->input, packet->inputBytes, packet->callback)) { + packet->chan = -1; + } + } +#else ASSERTLINE(0x267, packet->time <= OSGetTime()); // WTF? Dereferencing a NULL POINTER? packet = &Packet[chan]; if (packet->chan != -1 && __SITransfer(packet->chan, packet->output, packet->outputBytes, packet->input, packet->inputBytes, packet->callback)) { packet->chan = -1; } +#endif } -int SITransfer(long chan, void * output, unsigned long outputBytes, void * input, unsigned long inputBytes, +int SITransfer(long chan, void * output, unsigned long outputBytes, void * input, unsigned long inputBytes, void (* callback)(long, unsigned long, struct OSContext *), long long time) { int enabled; struct SIPacket * packet; long long now; +#if DOLPHIN_REVISION >= 45 + long long fire; +#endif packet = &Packet[chan]; enabled = OSDisableInterrupts(); +#if DOLPHIN_REVISION >= 45 + if (packet->chan != -1 || Si.chan == chan) { +#else if (packet->chan != -1) { +#endif OSRestoreInterrupts(enabled); return 0; } +#if DOLPHIN_REVISION >= 45 + now = __OSGetSystemTime(); + if (time == 0) { + fire = now; + } else { + fire = time + XferTime[chan]; + } +#else now = OSGetTime(); if (time == 0) { time = now; } +#endif +#if DOLPHIN_REVISION >= 45 + if (now < fire) { + time = fire - now; + OSSetAlarm(&Alarm[chan], time, AlarmHandler); +#else if (now < time) { OSSetAbsAlarm(&Alarm[chan], time, AlarmHandler); +#endif } else if (__SITransfer(chan, output, outputBytes, input, inputBytes, callback)) { OSRestoreInterrupts(enabled); return 1; @@ -305,7 +634,232 @@ int SITransfer(long chan, void * output, unsigned long outputBytes, void * input packet->input = input; packet->inputBytes = inputBytes; packet->callback = callback; +#if DOLPHIN_REVISION >= 45 + packet->fire = fire; +#else packet->time = time; +#endif OSRestoreInterrupts(enabled); return 1; } + +#if DOLPHIN_REVISION >= 45 +static void CallTypeAndStatusCallback(s32 chan, u32 type) +{ + void (*callback)(s32, u32); + int i; + + for (i = 0; i < 4; i++) { + callback = TypeCallback[chan][i]; + if (callback) { + TypeCallback[chan][i] = NULL; + callback(chan, type); + } + } +} + +static void GetTypeCallback(s32 chan, u32 error) +{ + u32 type; + u32 chanBit; + int fix; + u32 id; + static u32 cmdFixDevice[4]; + u8 unused[8]; + + ASSERTLINE(0x43E, 0 <= chan && chan < SI_MAX_CHAN); + ASSERTLINE(0x440, (Type[chan] & 0xff) == SI_ERROR_BUSY); + Type[chan] &= ~0x80; + Type[chan] |= error; + TypeTime[chan] = __OSGetSystemTime(); + type = Type[chan]; + chanBit = 0x80000000 >> chan; + fix = __PADFixBits & chanBit; + __PADFixBits &= ~chanBit; + if ((error & 0xF) || (type & 0x18000000) != 0x08000000 || !(type & 0x80000000) || (type & 0x4000000)) { + OSSetWirelessID(chan, 0); + CallTypeAndStatusCallback(chan, Type[chan]); + return; + } + id = (OSGetWirelessID(chan) << 8) & 0xFFFF00; + if (fix && (id & 0x100000)) { + cmdFixDevice[chan] = (id & 0xCFFF00) | 0x4E000000 | 0x100000; + Type[chan] = 0x80; + SITransfer(chan, &cmdFixDevice[chan], 3, &Type[chan], 3, (void *)GetTypeCallback, 0); + return; + } + if (type & 0x100000) { + if ((id & 0xCFFF00) != (type & 0xCFFF00)) { + if (!(id & 0x100000)) { + id = (type & 0xCFFF00); + id |= 0x100000; + OSSetWirelessID(chan, (id >> 8) & 0xFFFF); + } + cmdFixDevice[chan] = id | 0x4E000000; + Type[chan] = 0x80; + SITransfer(chan, &cmdFixDevice[chan], 3, &Type[chan], 3, (void *)GetTypeCallback, 0); + return; + } + } else if (type & 0x40000000) { + id = (type & 0xCFFF00); + id |= 0x100000; + OSSetWirelessID(chan, (id >> 8) & 0xFFFF); + cmdFixDevice[chan] = id | 0x4E000000; + Type[chan] = 0x80; + SITransfer(chan, &cmdFixDevice[chan], 3, &Type[chan], 3, (void *)GetTypeCallback, 0); + return; + } else { + OSSetWirelessID(chan, 0); + } + CallTypeAndStatusCallback(chan, Type[chan]); +} + +u32 SIGetType(s32 chan) +{ + BOOL enabled; + u32 type; + OSTime diff; + static u32 cmdTypeAndStatus; + + enabled = OSDisableInterrupts(); + ASSERTLINE(0x4A8, 0 <= chan && chan < SI_MAX_CHAN); + type = Type[chan]; + diff = __OSGetSystemTime() - TypeTime[chan]; + if (Si.poll & (0x80 >> chan)) { + if (type != 8) { + TypeTime[chan] = __OSGetSystemTime(); + OSRestoreInterrupts(enabled); + return type; + } + type = 0x80; + Type[chan] = type; + } else { + if (OSMillisecondsToTicks(50) >= diff && type != 8) { + OSRestoreInterrupts(enabled); + return type; + } + if (OSMillisecondsToTicks(75) >= diff) { + Type[chan] = 0x80; + } else { + type = 0x80; + Type[chan] = type; + } + } + TypeTime[chan] = __OSGetSystemTime(); + SITransfer(chan, &cmdTypeAndStatus, 1, &Type[chan], 3, (void *)GetTypeCallback, OSMicrosecondsToTicks(65)); + OSRestoreInterrupts(enabled); + Type;Type; // needed to match + return type; +} + +u32 SIGetTypeAsync(s32 chan, void (*callback)(s32, u32)) +{ + BOOL enabled; + u32 type; + int i; + + enabled = OSDisableInterrupts(); + type = SIGetType(chan); + if (Type[chan] & 0x80) { + for (i = 0; i < 4; i++) { + if (TypeCallback[chan][i] == callback) { + break; + } + if (!TypeCallback[chan][i]) { + TypeCallback[chan][i] = callback; + break; + } + } + ASSERTLINE(0x4F9, i < SI_MAX_TYPE); + } else { + callback(chan, type); + } + OSRestoreInterrupts(enabled); + return type; +} + +u32 SIDecodeType(u32 type) +{ + u32 error; + + error = type & 0xFF; + type &= 0xFFFFFF00; + if (error & 8) { + return 8; + } + if (error & 0x47) { + return 0x40; + } + if (error != 0) { + ASSERTLINE(0x528, error == SI_ERROR_BUSY); + return 0x80; + } + if (!(type & 0x18000000)) { + switch (type & 0xFFFF0000) { + case 0x40000: + case 0x20000: + case 0x10000: + case 0x5000000: + case 0x2000000: + return type & 0xFFFF0000; + default: + return 0x40; + } + } + if ((type & 0x18000000) != 0x08000000) { + return 0x40; + } + switch (type & 0xFFFF0000) { + case 0x9000000: + return type & 0xFFFF0000; + default: + if ((type & 0x80000000) && !(type & 0x04000000)) { + if ((type & 0x8B100000) == 0x8B100000) { + return 0x8B100000; + } + if (!(type & 0x02000000)) { + return 0x88000000; + } + } + if ((type & 0x09000000) == 0x09000000) { + return 0x09000000; + } + return 0x40; + } +} + +u32 SIProbe(s32 chan) +{ + return SIDecodeType(SIGetType(chan)); +} + +char *SIGetTypeString(u32 type) +{ + switch (SIDecodeType(type)) { + case 0x8: + return "No response"; + case 0x80: + return "Busy"; + case 0x5000000: + return "N64 controller"; + case 0x10000: + return "N64 microphone"; + case 0x20000: + return "N64 keyboard"; + case 0x2000000: + return "N64 mouse"; + case 0x40000: + return "GameBoy Advance"; + case 0x9000000: + return "Standard controller"; + case 0x88000000: + return "Wireless receiver"; + case 0x8B100000: + return "WaveBird controller"; + case 0x40: + default: + return "Unknown"; + } +} + +#endif 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/OSTime.c b/src/os/OSTime.c index 797fbae..4231342 100644 --- a/src/os/OSTime.c +++ b/src/os/OSTime.c @@ -74,6 +74,21 @@ long long __OSGetSystemTime() { return result; } +#if DOLPHIN_REVISION >= 45 +OSTime __OSTimeToSystemTime(OSTime time) +{ + BOOL enabled; + OSTime *timeAdjustAddr; + OSTime result; + + timeAdjustAddr = (OSTime *)0x800030D8; + enabled = OSDisableInterrupts(); + result = *timeAdjustAddr + time; + OSRestoreInterrupts(enabled); + return result; +} +#endif + asm void __OSSetTick(register unsigned long newTicks) { // clang-format off nofralloc @@ -92,9 +107,11 @@ static int GetYearDays(int year, int mon) { return md[mon]; } +#define LINE_OFFSET (DOLPHIN_REVISION >= 45 ? 26 : 0) + static int GetLeapDays(int year) { - ASSERTLINE(260, 0 <= year); - + ASSERTLINE(260+LINE_OFFSET, 0 <= year); + if (year < 1) { return 0; } @@ -107,7 +124,7 @@ static void GetDates(int days, OSCalendarTime* td) { int month; int * md; - ASSERTLINE(285, 0 <= days); + ASSERTLINE(285+LINE_OFFSET, 0 <= days); td->wday = (days + 6) % WEEK_DAY_MAX; @@ -133,29 +150,29 @@ void OSTicksToCalendarTime(long long ticks, OSCalendarTime* td) { int secs; long long d; - d = ticks % OS_SEC_TO_TICKS(1); + d = ticks % OS_SEC_TO_TICKS(1); if (d < 0) { d += OS_SEC_TO_TICKS(1); - ASSERTLINE(330, 0 <= d); + ASSERTLINE(330+LINE_OFFSET, 0 <= d); } td->usec = OS_TICKS_TO_USEC(d) % USEC_MAX; td->msec = OS_TICKS_TO_MSEC(d) % MSEC_MAX; - ASSERTLINE(334, 0 <= td->usec); - ASSERTLINE(335, 0 <= td->msec); + ASSERTLINE(334+LINE_OFFSET, 0 <= td->usec); + ASSERTLINE(335+LINE_OFFSET, 0 <= td->msec); ticks -= d; - ASSERTLINE(338, ticks % OSSecondsToTicks(1) == 0); - ASSERTLINE(342, 0 <= OSTicksToSeconds(ticks) / 86400 + BIAS && OSTicksToSeconds(ticks) / 86400 + BIAS <= INT_MAX); + ASSERTLINE(338+LINE_OFFSET, ticks % OSSecondsToTicks(1) == 0); + ASSERTLINE(342+LINE_OFFSET, 0 <= OSTicksToSeconds(ticks) / 86400 + BIAS && OSTicksToSeconds(ticks) / 86400 + BIAS <= INT_MAX); - days = (OS_TICKS_TO_SEC(ticks) / SECS_IN_DAY) + BIAS; + days = (OS_TICKS_TO_SEC(ticks) / SECS_IN_DAY) + BIAS; secs = OS_TICKS_TO_SEC(ticks) % SECS_IN_DAY; if (secs < 0) { days -= 1; secs += SECS_IN_DAY; - ASSERTLINE(349, 0 <= secs); + ASSERTLINE(349+LINE_OFFSET, 0 <= secs); } GetDates(days, td); @@ -178,8 +195,8 @@ OSTime OSCalendarTimeToTicks(OSCalendarTime* td) { ov_mon--; } - ASSERTLINE(0x182, (ov_mon <= 0 && 0 <= td->year + ov_mon) || (0 < ov_mon && td->year <= INT_MAX - ov_mon)); - + ASSERTLINE(0x182+LINE_OFFSET, (ov_mon <= 0 && 0 <= td->year + ov_mon) || (0 < ov_mon && td->year <= INT_MAX - ov_mon)); + year = td->year + ov_mon; // clang-format off diff --git a/src/os/OSUartExi.c b/src/os/OSUartExi.c index 88da718..34f4e83 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..852be93 100644 --- a/src/os/__os.h +++ b/src/os/__os.h @@ -3,11 +3,25 @@ #include +OSThread *UNK_800000DC : 0x800000DC; +extern u8 UNK_800030E2 : 0x800030E2; +extern u8 UNK_800030E3 : 0x800030E3; +extern void *UNK_812FDFEC : 0x812FDFEC; +extern void *UNK_812FDFF0 : 0x812FDFF0; +extern u32 UNK_817FFFF8 : 0x817FFFF8; +extern u32 UNK_817FFFFC : 0x817FFFFC; + // OS.c extern char * __OSExceptionNames[15]; // D ONLY +#if DOLPHIN_REVISION >= 45 +extern OSTime __OSStartTime; +#endif unsigned long __OSIsDebuggerPresent(void); void __OSPSInit(void); +#if DOLPHIN_REVISION >= 37 +u32 __OSGetDIConfig(void); +#endif // OSAlloc.c extern volatile int __OSCurrHeap; @@ -41,11 +55,24 @@ OSInterruptMask __OSUnmaskInterrupts(OSInterruptMask global); void __OSDispatchInterrupt(__OSException exception, OSContext* context); void __OSModuleInit(void); +// OSMemory.c +void __OSInitMemoryProtection(void); + // OSMutex.c 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); @@ -79,6 +106,9 @@ void __OSReschedule(void); // OSTime.c void __OSSetTime(long long time); long long __OSGetSystemTime(); +#if DOLPHIN_REVISION >= 45 +OSTime __OSTimeToSystemTime(OSTime); +#endif void __OSSetTick(register unsigned long newTicks); // ppc_eabi_init.c diff --git a/src/os/time.dolphin.c b/src/os/time.dolphin.c index 4921c2e..3a9384f 100644 --- a/src/os/time.dolphin.c +++ b/src/os/time.dolphin.c @@ -4,7 +4,11 @@ #include "__os.h" long long __get_clock(void) { +#if DOLPHIN_REVISION >= 45 + return __OSGetSystemTime(); +#else return -1; +#endif } unsigned long __get_time(void) { 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..b512965 100644 --- a/src/vi/vi.c +++ b/src/vi/vi.c @@ -69,7 +69,9 @@ typedef struct { } SomeVIStruct; static volatile u32 retraceCount; +#if DOLPHIN_REVISION < 45 static u32 changeMode; +#endif static volatile u32 flushFlag; static struct OSThreadQueue retraceQueue; static void (*PreCB)(u32); @@ -77,7 +79,13 @@ static void (*PostCB)(u32); static u32 encoderType; static s16 displayOffsetH; static s16 displayOffsetV; +#if DOLPHIN_REVISION >= 45 +static volatile u32 changeMode; +#endif static volatile u64 changed; +#if DOLPHIN_REVISION >= 45 +static volatile u32 shdwChangeMode; +#endif static u16 regs[59]; static volatile u64 shdwChanged; static u16 shdwRegs[59]; @@ -92,7 +100,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, @@ -139,18 +151,30 @@ static int VISetRegs(void) { s32 regIndex; - if (changeMode != 1 || getCurrentFieldEvenOdd() != 0) { + if ( +#if DOLPHIN_REVISION >= 45 + shdwChangeMode != 1 +#else + changeMode != 1 +#endif + || getCurrentFieldEvenOdd() != 0) { while (shdwChanged != 0) { regIndex = cntlzd(shdwChanged); __VIRegs[regIndex] = shdwRegs[regIndex]; shdwChanged &= ~((u64)1 << (63 - regIndex)); } +#if DOLPHIN_REVISION >= 45 + shdwChangeMode = 0; +#else changeMode = 0; +#endif return 1; } return 0; } +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 19 : 0) + static void __VIRetraceHandler(__OSInterrupt unused, OSContext *context) { OSContext exceptionContext; @@ -187,7 +211,7 @@ static void __VIRetraceHandler(__OSInterrupt unused, OSContext *context) return; } if (inter == 0) { - ASSERTLINE(0x2BA, FALSE); + ASSERTLINE(0x2BA+LINE_OFFSET, FALSE); } retraceCount += 1; OSClearContext(&exceptionContext); @@ -349,7 +373,7 @@ static void ImportAdjustingValues(void) { OSSram *sram = __OSLockSram(); - ASSERTLINE(0x3E2, sram); + ASSERTLINE(0x3E2+LINE_OFFSET, sram); displayOffsetH = sram->displayOffsetH; displayOffsetV = 0; __OSUnlockSram(0); @@ -369,6 +393,9 @@ void VIInit(void) changed = 0; shdwChanged = 0; changeMode = 0; +#if DOLPHIN_REVISION >= 45 + shdwChangeMode = 0; +#endif flushFlag = 0; __VIRegs[39] = taps[0] | ((taps[1] & 0x3F) << 10); __VIRegs[38] = (taps[1] >> 6) | (taps[2] << 4); @@ -626,9 +653,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; } @@ -644,6 +679,9 @@ static void setVerticalRegs(u16 dispPosY, u16 dispSizeY, u8 equ, u16 acv, u16 pr MARK_CHANGED(8); } +#undef LINE_OFFSET +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 28 : 0) + void VIConfigure(GXRenderModeObj *rm) { VITiming *tm; @@ -653,35 +691,50 @@ void VIConfigure(GXRenderModeObj *rm) u32 tvInBootrom; u32 tvInGame; - ASSERTMSGLINEV(0x601, (rm->viHeight & 1) == 0, + ASSERTMSGLINEV(0x601+LINE_OFFSET, (rm->viHeight & 1) == 0, "VIConfigure(): Odd number(%d) is specified to viHeight\n", rm->viHeight); if (rm->xFBmode == VI_XFBMODE_DF || rm->viTVmode == VI_TVMODE_NTSC_PROG) { - ASSERTMSGLINEV(0x607, rm->xfbHeight == rm->viHeight, + ASSERTMSGLINEV(0x607+LINE_OFFSET, rm->xfbHeight == rm->viHeight, "VIConfigure(): xfbHeight(%d) is not equal to viHeight(%d) when DF XFB mode or progressive mode is specified\n", rm->xfbHeight, rm->viHeight); } if (rm->xFBmode == VI_XFBMODE_SF && rm->viTVmode != VI_TVMODE_NTSC_PROG) { - ASSERTMSGLINEV(0x60E, rm->viHeight == rm->xfbHeight * 2, + ASSERTMSGLINEV(0x60E+LINE_OFFSET, rm->viHeight == rm->xfbHeight * 2, "VIConfigure(): xfbHeight(%d) is not as twice as viHeight(%d) when SF XFB mode is specified\n", rm->xfbHeight, rm->viHeight); } enabled = OSDisableInterrupts(); +#if DOLPHIN_REVISION < 45 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) { changeMode = 1; } HorVer.nonInter = newNonInter; } +#else + newNonInter = rm->viTVmode & 3; + if (HorVer.nonInter != newNonInter) { + changeMode = 1; + HorVer.nonInter = newNonInter; + } +#endif + +#undef LINE_OFFSET +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 21 : 0) tvInBootrom = VIGetTvFormat(); tvInGame = (u32)rm->viTVmode >> 2; - ASSERTMSGLINEV(0x635, tvInBootrom == tvInGame || (tvInBootrom == 2 && tvInGame == 0) || (tvInBootrom == 0 && tvInGame == 2), + ASSERTMSGLINEV(0x635+LINE_OFFSET, tvInBootrom == tvInGame || (tvInBootrom == 2 && tvInGame == 0) || (tvInBootrom == 0 && tvInGame == 2), "Doesn't match TV format: TV format in bootrom is %d but TV format specified in the game is %d (0:NTSC, 1:PAL, 2:MPAL)\n" /* BUG: forgot to pass in additional parameters! */); @@ -702,10 +755,10 @@ void VIConfigure(GXRenderModeObj *rm) tm = getTiming(rm->viTVmode); HorVer.timing = tm; AdjustPosition(tm->acv); - ASSERTMSGLINEV(0x654, rm->viXOrigin <= tm->hlw + 40 - tm->hbe640, + ASSERTMSGLINEV(0x654+LINE_OFFSET, rm->viXOrigin <= tm->hlw + 40 - tm->hbe640, "VIConfigure(): viXOrigin(%d) cannot be greater than %d in this TV mode\n", rm->viXOrigin, tm->hlw + 40 - tm->hbe640); - ASSERTMSGLINEV(0x659, rm->viXOrigin + rm->viWidth >= 0x2A8 - tm->hbs640, + ASSERTMSGLINEV(0x659+LINE_OFFSET, rm->viXOrigin + rm->viWidth >= 0x2A8 - tm->hbs640, "VIConfigure(): viXOrigin + viWidth (%d) cannot be less than %d in this TV mode\n", rm->viXOrigin + rm->viWidth, 0x2A8 - tm->hbs640); @@ -713,11 +766,37 @@ void VIConfigure(GXRenderModeObj *rm) HorVer.tv = 3; } setInterruptRegs(tm); + +#undef LINE_OFFSET +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 27 : 0) + reg = regs[1]; - SET_REG_FIELD(0x66A, reg, 1, 2, (HorVer.nonInter & 1)); - SET_REG_FIELD(0x66B, reg, 2, 8, HorVer.tv); +#if DOLPHIN_REVISION >= 37 + if (HorVer.nonInter == 2) { + SET_REG_FIELD(0x66A+LINE_OFFSET, reg, 1, 2, 1); + } else { + SET_REG_FIELD(0x66A+LINE_OFFSET, reg, 1, 2, (HorVer.nonInter & 1)); + } +#else + SET_REG_FIELD(0x66A+LINE_OFFSET, reg, 1, 2, (HorVer.nonInter & 1)); +#endif + +#undef LINE_OFFSET +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 28 : 0) + + SET_REG_FIELD(0x66B+LINE_OFFSET, reg, 2, 8, HorVer.tv); regs[1] = reg; MARK_CHANGED(1); +#if DOLPHIN_REVISION >= 37 + reg = regs[54]; +#if DOLPHIN_REVISION >= 45 + reg = (rm->viTVmode != 2) ? (reg & ~1) : ((reg & ~1) | 1); + regs[54] = reg; +#else + regs[54] = (rm->viTVmode != 2) ? (reg & ~1) : ((reg & ~1) | 1); +#endif + MARK_CHANGED(54); +#endif setScalingRegs(HorVer.PanSizeX, HorVer.DispSizeX, HorVer.threeD); setHorizontalRegs(tm, HorVer.AdjustedDispPosX, HorVer.DispSizeX); setBBIntervalRegs(tm); @@ -729,17 +808,20 @@ void VIConfigure(GXRenderModeObj *rm) OSRestoreInterrupts(enabled); } +#undef LINE_OFFSET +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 42 : 0) + void VIConfigurePan(u16 xOrg, u16 yOrg, u16 width, u16 height) { BOOL enabled; VITiming *tm; #if DEBUG - ASSERTMSGLINEV(0x69C, (xOrg & 1) == 0, + ASSERTMSGLINEV(0x69C+LINE_OFFSET, (xOrg & 1) == 0, "VIConfigurePan(): Odd number(%d) is specified to xOrg\n", xOrg); if (HorVer.FBMode == VI_XFBMODE_DF) { - ASSERTMSGLINEV(0x6A1, (height & 1) == 0, + ASSERTMSGLINEV(0x6A1+LINE_OFFSET, (height & 1) == 0, "VIConfigurePan(): Odd number(%d) is specified to height when DF XFB mode\n", height); } @@ -769,6 +851,10 @@ void VIFlush(void) s32 regIndex; enabled = OSDisableInterrupts(); +#if DOLPHIN_REVISION >= 45 + shdwChangeMode |= changeMode; + changeMode = 0; +#endif shdwChanged |= changed; while (changed != 0) { regIndex = cntlzd(changed); @@ -779,11 +865,14 @@ void VIFlush(void) OSRestoreInterrupts(enabled); } +#undef LINE_OFFSET +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 44 : 0) + void VISetNextFrameBuffer(void *fb) { BOOL enabled; - ASSERTMSGLINEV(0x6F7, ((u32)fb & 0x1F) == 0, + ASSERTMSGLINEV(0x6F7+LINE_OFFSET, ((u32)fb & 0x1F) == 0, "VISetNextFrameBuffer(): Frame buffer address(0x%08x) is not 32byte aligned\n", fb); enabled = OSDisableInterrupts(); @@ -797,7 +886,7 @@ void VISetNextRightFrameBuffer(void *fb) { BOOL enabled; - ASSERTMSGLINEV(0x71F, ((u32)fb & 0x1F) == 0, + ASSERTMSGLINEV(0x71F+LINE_OFFSET, ((u32)fb & 0x1F) == 0, "VISetNextFrameBuffer(): Frame buffer address(0x%08x) is not 32byte aligned\n", fb); enabled = OSDisableInterrupts(); @@ -827,7 +916,7 @@ void VISet3D(BOOL threeD) enabled = OSDisableInterrupts(); HorVer.threeD = threeD; reg = regs[1]; - SET_REG_FIELD(0x766, reg, 1, 3, HorVer.threeD); + SET_REG_FIELD(0x766+LINE_OFFSET, reg, 1, 3, HorVer.threeD); regs[1] = reg; MARK_CHANGED(1); setScalingRegs(HorVer.PanSizeX, HorVer.DispSizeX, HorVer.threeD); @@ -915,17 +1004,31 @@ u32 VIGetTvFormat(void) { u32 format = *(u32 *)OSPhysicalToCached(0xCC); - ASSERTMSGLINE(0x80D, format == 0 || format == 1 || format == 2, + ASSERTMSGLINE(0x80D+LINE_OFFSET, format == 0 || format == 1 || format == 2, "VIGetTvFormat(): Wrong format is stored in lo mem. Maybe lo mem is trashed"); return format; } +u32 VIGetDTVStatus() { + // Local variables + unsigned long dtvStatus; // r31 + BOOL enabled; // r30 + + enabled = OSDisableInterrupts(); + dtvStatus = __VIRegs[55] & 3; + OSRestoreInterrupts(enabled); + return dtvStatus & 1; +} + +#undef LINE_OFFSET +#define LINE_OFFSET ((DOLPHIN_REVISION >= 45) ? 66 : 0) + void __VISetAdjustingValues(s16 x, s16 y) { BOOL enabled; VITiming *tm; - ASSERTMSGLINE(0x822, (y & 1) == 0, "__VISetAdjustValues(): y offset should be an even number"); + ASSERTMSGLINE(0x822+LINE_OFFSET, (y & 1) == 0, "__VISetAdjustValues(): y offset should be an even number"); enabled = OSDisableInterrupts(); displayOffsetH = x; displayOffsetV = y;