diff --git a/Makefile b/Makefile index 7be7a2a3..b5dc444a 100644 --- a/Makefile +++ b/Makefile @@ -125,8 +125,6 @@ ifeq ($(VERBOSE),0) ASFLAGS += -W endif -$(INIT_O_FILES): MWCC_VERSION := 1.2.5 -$(INIT_O_FILES): CFLAGS := $(CFLAGS_BASE) $(METROTRK_FILES): MWCC_VERSION := 1.2.5 $(METROTRK_FILES): CFLAGS := $(CFLAGS_BASE) $(BASE_FILES): MWCC_VERSION := 1.2.5 @@ -135,6 +133,8 @@ $(AI_FILES): MWCC_VERSION := 1.2.5 $(AI_FILES): CFLAGS := $(CFLAGS_BASE) $(OS_FILES): MWCC_VERSION := 1.2.5 $(OS_FILES): CFLAGS := $(CFLAGS_BASE) +$(CARD_FILES): MWCC_VERSION := 1.2.5 +$(CARD_FILES): CFLAGS := $(CFLAGS_BASE) $(DSP_FILES): MWCC_VERSION := 1.2.5 $(DSP_FILES): CFLAGS := $(CFLAGS_BASE) $(MUSYX_FILES): CFLAGS := $(CFLAGS_MUSYX) diff --git a/asm/Dolphin/card/CARDBios.s b/asm/Dolphin/card/CARDBios.s index 5e1c5345..b4d35095 100644 --- a/asm/Dolphin/card/CARDBios.s +++ b/asm/Dolphin/card/CARDBios.s @@ -5,15 +5,17 @@ .global __CARDBlock __CARDBlock: .skip 0x220 +.global __CARDDiskNone +__CARDDiskNone: + .skip 0x20 .section .data, "wa" .balign 8 -lbl_803F6C90: +__CARDVersionStr: .asciz "<< Dolphin SDK - CARD\trelease build: Sep 5 2002 05:35:20 (0x2301) >>" .balign 4 -.global lbl_803F6CD8 -lbl_803F6CD8: +ResetFunctionInfo: .4byte OnReset .4byte 0x0000007f @@ -22,9 +24,9 @@ lbl_803F6CD8: .section .sdata, "wa" .balign 8 -.global lbl_805A8BF0 -lbl_805A8BF0: - .4byte lbl_803F6C90 +.global __CARDVersion +__CARDVersion: + .4byte __CARDVersionStr .skip 4 .section .sbss, "wa" @@ -1080,7 +1082,7 @@ CARDInit: lbl_803B8CEC: /* 803B8CEC 003B5C4C 4B FC 82 59 */ bl OSGetFontEncode /* 803B8CF0 003B5C50 B0 6D B0 08 */ sth r3, __CARDEncode@sda21(r13) -/* 803B8CF4 003B5C54 80 6D A0 30 */ lwz r3, lbl_805A8BF0@sda21(r13) +/* 803B8CF4 003B5C54 80 6D A0 30 */ lwz r3, __CARDVersion@sda21(r13) /* 803B8CF8 003B5C58 4B FC 53 41 */ bl OSRegisterVersion /* 803B8CFC 003B5C5C 4B FB 6D 09 */ bl DSPInit /* 803B8D00 003B5C60 4B FC 53 65 */ bl OSInitAlarm @@ -1098,8 +1100,8 @@ lbl_803B8D0C: /* 803B8D2C 003B5C8C 41 80 FF E0 */ blt lbl_803B8D0C /* 803B8D30 003B5C90 3C 60 80 00 */ lis r3, 0x8000 /* 803B8D34 003B5C94 48 00 00 35 */ bl __CARDSetDiskID -/* 803B8D38 003B5C98 3C 60 80 3F */ lis r3, lbl_803F6CD8@ha -/* 803B8D3C 003B5C9C 38 63 6C D8 */ addi r3, r3, lbl_803F6CD8@l +/* 803B8D38 003B5C98 3C 60 80 3F */ lis r3, ResetFunctionInfo@ha +/* 803B8D3C 003B5C9C 38 63 6C D8 */ addi r3, r3, ResetFunctionInfo@l /* 803B8D40 003B5CA0 4B FC A2 ED */ bl OSRegisterResetFunction lbl_803B8D44: /* 803B8D44 003B5CA4 80 01 00 1C */ lwz r0, 0x1c(r1) diff --git a/asm/Dolphin/card/CARDOpen.s b/asm/Dolphin/card/CARDOpen.s index 8e8d8405..8487c731 100644 --- a/asm/Dolphin/card/CARDOpen.s +++ b/asm/Dolphin/card/CARDOpen.s @@ -1,10 +1,5 @@ .include "macros.inc" -.section .bss -.balign 8 -lbl_80569C78: - .skip 0x20 - .section .text, "ax" .global __CARDCompareFileName @@ -55,9 +50,9 @@ __CARDAccess: /* 803BCDFC 003B9D5C 38 60 FF FC */ li r3, -4 /* 803BCE00 003B9D60 48 00 00 54 */ b lbl_803BCE54 lbl_803BCE04: -/* 803BCE04 003B9D64 3C 60 80 57 */ lis r3, lbl_80569C78@ha +/* 803BCE04 003B9D64 3C 60 80 57 */ lis r3, __CARDDiskNone@ha /* 803BCE08 003B9D68 80 9E 01 0C */ lwz r4, 0x10c(r30) -/* 803BCE0C 003B9D6C 38 03 9C 78 */ addi r0, r3, lbl_80569C78@l +/* 803BCE0C 003B9D6C 38 03 9C 78 */ addi r0, r3, __CARDDiskNone@l /* 803BCE10 003B9D70 7C 04 00 40 */ cmplw r4, r0 /* 803BCE14 003B9D74 41 82 00 34 */ beq lbl_803BCE48 /* 803BCE18 003B9D78 38 7F 00 00 */ addi r3, r31, 0 @@ -119,9 +114,9 @@ sub_803bce9c: lbl_803BCECC: /* 803BCECC 003B9E2C 7F 63 DB 78 */ mr r3, r27 /* 803BCED0 003B9E30 4B FF DA A1 */ bl __CARDGetDirBlock -/* 803BCED4 003B9E34 3C 80 80 57 */ lis r4, lbl_80569C78@ha +/* 803BCED4 003B9E34 3C 80 80 57 */ lis r4, __CARDDiskNone@ha /* 803BCED8 003B9E38 3B E3 00 00 */ addi r31, r3, 0 -/* 803BCEDC 003B9E3C 3B 44 9C 78 */ addi r26, r4, lbl_80569C78@l +/* 803BCEDC 003B9E3C 3B 44 9C 78 */ addi r26, r4, __CARDDiskNone@l /* 803BCEE0 003B9E40 3B C0 00 00 */ li r30, 0 lbl_803BCEE4: /* 803BCEE4 003B9E44 88 1F 00 00 */ lbz r0, 0(r31) @@ -228,9 +223,9 @@ lbl_803BD024: lbl_803BD03C: /* 803BD03C 003B9F9C 7F E3 FB 78 */ mr r3, r31 /* 803BD040 003B9FA0 4B FF D9 31 */ bl __CARDGetDirBlock -/* 803BD044 003B9FA4 3C 80 80 57 */ lis r4, lbl_80569C78@ha +/* 803BD044 003B9FA4 3C 80 80 57 */ lis r4, __CARDDiskNone@ha /* 803BD048 003B9FA8 3A E3 00 00 */ addi r23, r3, 0 -/* 803BD04C 003B9FAC 3B 44 9C 78 */ addi r26, r4, lbl_80569C78@l +/* 803BD04C 003B9FAC 3B 44 9C 78 */ addi r26, r4, __CARDDiskNone@l /* 803BD050 003B9FB0 3B 20 00 00 */ li r25, 0 lbl_803BD054: /* 803BD054 003B9FB4 88 17 00 00 */ lbz r0, 0(r23) diff --git a/asm/Dolphin/card/CARDUnlock.s b/asm/Dolphin/card/CARDUnlock.s index c82528ae..99a2cb41 100644 --- a/asm/Dolphin/card/CARDUnlock.s +++ b/asm/Dolphin/card/CARDUnlock.s @@ -3,8 +3,8 @@ .section .data, "wa" .balign 8 -.global lbl_803F6D00 -lbl_803F6D00: +.global CardData +CardData: # ROM: 0x3F3D00 .4byte 0 .4byte 0 @@ -98,13 +98,13 @@ lbl_803F6D00: .section .sdata, "wa" .balign 8 -.global lbl_805A8BF8 -lbl_805A8BF8: +next: .4byte 1 .skip 4 .section .text, "ax" +.global bitrev bitrev: /* 803B908C 003B5FEC 38 00 00 08 */ li r0, 8 /* 803B9090 003B5FF0 7C 09 03 A6 */ mtctr r0 @@ -311,14 +311,14 @@ DummyLen: /* 803B9354 003B62B4 93 A1 00 1C */ stw r29, 0x1c(r1) /* 803B9358 003B62B8 3B A0 00 00 */ li r29, 0 /* 803B935C 003B62BC 4B FC C0 65 */ bl OSGetTick -/* 803B9360 003B62C0 90 6D A0 38 */ stw r3, lbl_805A8BF8@sda21(r13) +/* 803B9360 003B62C0 90 6D A0 38 */ stw r3, next@sda21(r13) /* 803B9364 003B62C4 3C 60 41 C6 */ lis r3, 0x41C64E6D@ha /* 803B9368 003B62C8 3B E3 4E 6D */ addi r31, r3, 0x41C64E6D@l -/* 803B936C 003B62CC 80 0D A0 38 */ lwz r0, lbl_805A8BF8@sda21(r13) +/* 803B936C 003B62CC 80 0D A0 38 */ lwz r0, next@sda21(r13) /* 803B9370 003B62D0 7C 60 F9 D6 */ mullw r3, r0, r31 /* 803B9374 003B62D4 38 03 30 39 */ addi r0, r3, 0x3039 -/* 803B9378 003B62D8 90 0D A0 38 */ stw r0, lbl_805A8BF8@sda21(r13) -/* 803B937C 003B62DC 80 0D A0 38 */ lwz r0, lbl_805A8BF8@sda21(r13) +/* 803B9378 003B62D8 90 0D A0 38 */ stw r0, next@sda21(r13) +/* 803B937C 003B62DC 80 0D A0 38 */ lwz r0, next@sda21(r13) /* 803B9380 003B62E0 54 03 86 FE */ rlwinm r3, r0, 0x10, 0x1b, 0x1f /* 803B9384 003B62E4 38 63 00 01 */ addi r3, r3, 1 /* 803B9388 003B62E8 48 00 00 40 */ b lbl_803B93C8 @@ -330,13 +330,13 @@ lbl_803B938C: /* 803B939C 003B62FC 40 81 00 08 */ ble lbl_803B93A4 /* 803B93A0 003B6300 3B C0 00 01 */ li r30, 1 lbl_803B93A4: -/* 803B93A4 003B6304 90 0D A0 38 */ stw r0, lbl_805A8BF8@sda21(r13) +/* 803B93A4 003B6304 90 0D A0 38 */ stw r0, next@sda21(r13) /* 803B93A8 003B6308 3B BD 00 01 */ addi r29, r29, 1 -/* 803B93AC 003B630C 80 0D A0 38 */ lwz r0, lbl_805A8BF8@sda21(r13) +/* 803B93AC 003B630C 80 0D A0 38 */ lwz r0, next@sda21(r13) /* 803B93B0 003B6310 7C 60 F9 D6 */ mullw r3, r0, r31 /* 803B93B4 003B6314 38 03 30 39 */ addi r0, r3, 0x3039 -/* 803B93B8 003B6318 90 0D A0 38 */ stw r0, lbl_805A8BF8@sda21(r13) -/* 803B93BC 003B631C 80 0D A0 38 */ lwz r0, lbl_805A8BF8@sda21(r13) +/* 803B93B8 003B6318 90 0D A0 38 */ stw r0, next@sda21(r13) +/* 803B93BC 003B631C 80 0D A0 38 */ lwz r0, next@sda21(r13) /* 803B93C0 003B6320 54 03 86 FE */ rlwinm r3, r0, 0x10, 0x1b, 0x1f /* 803B93C4 003B6324 38 63 00 01 */ addi r3, r3, 1 lbl_803B93C8: @@ -376,16 +376,16 @@ __CARDUnlock: /* 803B9438 003B6398 3B A3 00 00 */ addi r29, r3, 0 /* 803B943C 003B639C 3A DC 00 20 */ addi r22, r28, 0x20 /* 803B9440 003B63A0 4B FC BF 81 */ bl OSGetTick -/* 803B9444 003B63A4 90 6D A0 38 */ stw r3, lbl_805A8BF8@sda21(r13) +/* 803B9444 003B63A4 90 6D A0 38 */ stw r3, next@sda21(r13) /* 803B9448 003B63A8 3C 60 41 C6 */ lis r3, 0x41C64E6D@ha /* 803B944C 003B63AC 3C A0 7F ED */ lis r5, 0x7FEC8000@ha -/* 803B9450 003B63B0 80 8D A0 38 */ lwz r4, lbl_805A8BF8@sda21(r13) +/* 803B9450 003B63B0 80 8D A0 38 */ lwz r4, next@sda21(r13) /* 803B9454 003B63B4 38 03 4E 6D */ addi r0, r3, 0x41C64E6D@l /* 803B9458 003B63B8 3B 25 80 00 */ addi r25, r5, 0x7FEC8000@l /* 803B945C 003B63BC 7C 64 01 D6 */ mullw r3, r4, r0 /* 803B9460 003B63C0 38 03 30 39 */ addi r0, r3, 0x3039 -/* 803B9464 003B63C4 90 0D A0 38 */ stw r0, lbl_805A8BF8@sda21(r13) -/* 803B9468 003B63C8 80 0D A0 38 */ lwz r0, lbl_805A8BF8@sda21(r13) +/* 803B9464 003B63C4 90 0D A0 38 */ stw r0, next@sda21(r13) +/* 803B9468 003B63C8 80 0D A0 38 */ lwz r0, next@sda21(r13) /* 803B946C 003B63CC 54 00 84 7E */ rlwinm r0, r0, 0x10, 0x11, 0x1f /* 803B9470 003B63D0 7F 39 03 78 */ or r25, r25, r0 /* 803B9474 003B63D4 57 39 00 26 */ rlwinm r25, r25, 0, 0, 0x13 @@ -1073,9 +1073,9 @@ lbl_803B9E78: /* 803B9ED8 003B6E38 38 80 00 10 */ li r4, 0x10 /* 803B9EDC 003B6E3C 4B FC 4B D5 */ bl DCFlushRange /* 803B9EE0 003B6E40 38 00 00 FF */ li r0, 0xff -/* 803B9EE4 003B6E44 3C 60 80 3F */ lis r3, lbl_803F6D00@ha +/* 803B9EE4 003B6E44 3C 60 80 3F */ lis r3, CardData@ha /* 803B9EE8 003B6E48 90 1E 00 04 */ stw r0, 4(r30) -/* 803B9EEC 003B6E4C 38 63 6D 00 */ addi r3, r3, lbl_803F6D00@l +/* 803B9EEC 003B6E4C 38 63 6D 00 */ addi r3, r3, CardData@l /* 803B9EF0 003B6E50 3C 03 80 00 */ addis r0, r3, 0x8000 /* 803B9EF4 003B6E54 90 1E 00 0C */ stw r0, 0xc(r30) /* 803B9EF8 003B6E58 38 00 01 60 */ li r0, 0x160 diff --git a/include/dolphin/CARDPriv.h b/include/dolphin/CARDPriv.h new file mode 100644 index 00000000..afad3a5b --- /dev/null +++ b/include/dolphin/CARDPriv.h @@ -0,0 +1,104 @@ +#ifndef __CARDPRIV_H__ +#define __CARDPRIV_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define CARD_FAT_CHECKSUM 0x0000u +#define CARD_FAT_CHECKSUMINV 0x0001u +#define CARD_FAT_CHECKCODE 0x0002u +#define CARD_FAT_FREEBLOCKS 0x0003u +#define CARD_FAT_LASTSLOT 0x0004u + +#define CARD_NUM_SYSTEM_BLOCK 5 +#define CARD_SYSTEM_BLOCK_SIZE (8 * 1024u) + +#define CARD_MAX_MOUNT_STEP (CARD_NUM_SYSTEM_BLOCK + 2) + +typedef struct CARDDir +{ + u8 gameName[4]; + u8 company[2]; + u8 _padding0; + u8 bannerFormat; + u8 fileName[CARD_FILENAME_MAX]; + u32 time; // seconds since 01/01/2000 midnight + + u32 iconAddr; // 0xffffffff if not used + u16 iconFormat; + u16 iconSpeed; + + u8 permission; + u8 copyTimes; + u16 startBlock; + u16 length; + u8 _padding1[2]; + + u32 commentAddr; // 0xffffffff if not used +} CARDDir; + +typedef struct CARDControl { + BOOL attached; + s32 result; + u16 size; + u16 pageSize; + s32 sectorSize; + u16 cBlock; + u16 vendorID; + s32 latency; + u8 id[12]; + int mountStep; + int formatStep; + u32 scramble; + DSPTaskInfo task; + void* workArea; + CARDDir* dir; + u16* currentFat; + OSThreadQueue threadQueue; + u8 cmd[9]; + s32 cmdlen; + vu32 mode; + int retry; + int repeat; + u32 addr; + void* buffer; + s32 xferred; + u16 freeNo; + u16 startBlock; + CARDFileInfo* fileInfo; + CARDCallback extCallback; + CARDCallback txCallback; + CARDCallback exiCallback; + CARDCallback apiCallback; + CARDCallback xferCallback; + CARDCallback eraseCallback; + CARDCallback unlockCallback; + OSAlarm alarm; + u32 cid; + const DVDDiskID* diskID; +} CARDControl; + +typedef struct CARDID { + u8 serial[32]; // flashID[12] + timebase[8] + counterBias[4] + language[4] + XXX[4] + u16 deviceID; + u16 size; + u16 encode; // character set -- 0: S-JIS, 1: ANSI + + u8 padding[512 - 32 - 5 * 2]; + + u16 checkSum; + u16 checkSumInv; +} CARDID; + +CARDDir* __CARDGetDirBlock( CARDControl* card ); +u16* __CARDGetFatBlock ( CARDControl* card ); + + +extern CARDControl __CARDBlock[2]; +extern DVDDiskID __CARDDiskNone; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/dolphin/dsp.h b/include/dolphin/dsp.h index ce7b8355..564a93a9 100644 --- a/include/dolphin/dsp.h +++ b/include/dolphin/dsp.h @@ -2,6 +2,7 @@ #define __DSP_H__ #include "types.h" +#include #ifdef __cplusplus extern "C" { diff --git a/include/dolphin/dvd.h b/include/dolphin/dvd.h new file mode 100644 index 00000000..eaba3235 --- /dev/null +++ b/include/dolphin/dvd.h @@ -0,0 +1,24 @@ +#ifndef __DVD_H__ +#define __DVD_H__ + +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct DVDDiskID { + char gameName[4]; + char company[2]; + u8 diskNumber; + u8 gameVersion; + u8 streaming; + u8 streamingBufSize; // 0 = default + u8 padding[22]; // 0's are stored +} DVDDiskID; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/dolphin/os.h b/include/dolphin/os.h index 3382981c..86704bf9 100644 --- a/include/dolphin/os.h +++ b/include/dolphin/os.h @@ -8,15 +8,15 @@ extern "C" { #endif // TODO OSInerrupt.h -typedef s16 __OSInterrupt; +typedef s16 __OSInterrupt; // Upper words of the masks, since UIMM is only 16 bits -#define OS_CACHED_REGION_PREFIX 0x8000 -#define OS_UNCACHED_REGION_PREFIX 0xC000 -#define OS_PHYSICAL_MASK 0x3FFF +#define OS_CACHED_REGION_PREFIX 0x8000 +#define OS_UNCACHED_REGION_PREFIX 0xC000 +#define OS_PHYSICAL_MASK 0x3FFF -#define OS_BASE_CACHED (OS_CACHED_REGION_PREFIX << 16) -#define OS_BASE_UNCACHED (OS_UNCACHED_REGION_PREFIX << 16) +#define OS_BASE_CACHED (OS_CACHED_REGION_PREFIX << 16) +#define OS_BASE_UNCACHED (OS_UNCACHED_REGION_PREFIX << 16) #ifdef __MWERKS__ #define AT_ADDRESS(xyz) : (xyz) @@ -25,48 +25,32 @@ typedef s16 __OSInterrupt; #endif typedef s64 OSTime; typedef u32 OSTick; -u32 __OSBusClock AT_ADDRESS(OS_BASE_CACHED | 0x00F8); // sync with OSLoMem.h -u32 __OSCoreClock AT_ADDRESS(OS_BASE_CACHED | 0x00FC); // sync with OSLoMem.h -#define OS_BUS_CLOCK __OSBusClock -#define OS_CORE_CLOCK __OSCoreClock -#define OS_TIMER_CLOCK (OS_BUS_CLOCK/4) +u32 __OSBusClock AT_ADDRESS(OS_BASE_CACHED | 0x00F8); // sync with OSLoMem.h +u32 __OSCoreClock AT_ADDRESS(OS_BASE_CACHED | 0x00FC); // sync with OSLoMem.h +#define OS_BUS_CLOCK __OSBusClock +#define OS_CORE_CLOCK __OSCoreClock +#define OS_TIMER_CLOCK (OS_BUS_CLOCK / 4) -#define OSTicksToCycles( ticks ) (((ticks) * ((OS_CORE_CLOCK * 2) / OS_TIMER_CLOCK)) / 2) -#define OSTicksToSeconds( ticks ) ((ticks) / OS_TIMER_CLOCK) -#define OSTicksToMilliseconds( ticks ) ((ticks) / (OS_TIMER_CLOCK / 1000)) -#define OSTicksToMicroseconds( ticks ) (((ticks) * 8) / (OS_TIMER_CLOCK / 125000)) -#define OSTicksToNanoseconds( ticks ) (((ticks) * 8000) / (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 OSPhysicalToCached(paddr) ((void*) ((u32)(paddr) + OS_BASE_CACHED)) +#define OSPhysicalToUncached(paddr) ((void*) ((u32)(paddr) + OS_BASE_UNCACHED)) +#define OSCachedToPhysical(caddr) ((u32) ((u8*)(caddr) - OS_BASE_CACHED)) +#define OSUncachedToPhysical(ucaddr) ((u32) ((u8*)(ucaddr)- OS_BASE_UNCACHED)) +#define OSCachedToUncached(caddr) ((void*) ((u8*)(caddr) + (OS_BASE_UNCACHED - OS_BASE_CACHED))) +#define OSUncachedToCached(ucaddr) ((void*) ((u8*)(ucaddr)- (OS_BASE_UNCACHED - OS_BASE_CACHED))) -#define OSDiffTick(tick1, tick0) ((s32) (tick1) - (s32) (tick0)) +#define OSTicksToCycles(ticks) (((ticks) * ((OS_CORE_CLOCK * 2) / OS_TIMER_CLOCK)) / 2) +#define OSTicksToSeconds(ticks) ((ticks) / OS_TIMER_CLOCK) +#define OSTicksToMilliseconds(ticks) ((ticks) / (OS_TIMER_CLOCK / 1000)) +#define OSTicksToMicroseconds(ticks) (((ticks)*8) / (OS_TIMER_CLOCK / 125000)) +#define OSTicksToNanoseconds(ticks) (((ticks)*8000) / (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 OSDiffTick(tick1, tick0) ((s32)(tick1) - (s32)(tick0)) -typedef struct OSContext { - u32 gpr[32]; - u32 cr; - u32 lr; - u32 ctr; - u32 xer; - - f64 fpr[32]; - - u32 fpscr_pad; - u32 fpscr; - - u32 srr0; - u32 srr1; - - u16 mode; - u16 state; - - u32 gqr[8]; - u32 psf_pad; - f64 psf[32]; - -} OSContext; +#define OSRoundUp32B(v) (((u32)(v + 31) & ~31)) OSTime OSGetTime(); @@ -74,4 +58,10 @@ OSTime OSGetTime(); } #endif +#include +#include +#include +#include +#include +#include #endif diff --git a/include/dolphin/os/OSAlarm.h b/include/dolphin/os/OSAlarm.h new file mode 100644 index 00000000..e3ae9cd4 --- /dev/null +++ b/include/dolphin/os/OSAlarm.h @@ -0,0 +1,29 @@ +#ifndef __OSALARM_H__ +#define __OSALARM_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct OSAlarm OSAlarm; +typedef void (*OSAlarmHandler)(OSAlarm* alarm, OSContext* context); + +struct OSAlarm { + OSAlarmHandler handler; + u32 tag; + OSTime fire; + OSAlarm* prev; + OSAlarm* next; + OSTime period; + OSTime start; +}; + +void OSSetAlarm(OSAlarm* alarm, OSTime tick, OSAlarmHandler handler); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/dolphin/OSCache.h b/include/dolphin/os/OSCache.h similarity index 100% rename from include/dolphin/OSCache.h rename to include/dolphin/os/OSCache.h diff --git a/include/dolphin/os/OSContext.h b/include/dolphin/os/OSContext.h new file mode 100644 index 00000000..8f7e46e4 --- /dev/null +++ b/include/dolphin/os/OSContext.h @@ -0,0 +1,40 @@ +#ifndef __OSCONTEXT_H__ +#define __OSCONTEXT_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct OSContext { + u32 gpr[32]; + u32 cr; + u32 lr; + u32 ctr; + u32 xer; + + f64 fpr[32]; + + u32 fpscr_pad; + u32 fpscr; + + u32 srr0; + u32 srr1; + + u16 mode; + u16 state; + + u32 gqr[8]; + u32 psf_pad; + f64 psf[32]; + +} OSContext; + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/dolphin/os/OSFont.h b/include/dolphin/os/OSFont.h new file mode 100644 index 00000000..cb62d0a9 --- /dev/null +++ b/include/dolphin/os/OSFont.h @@ -0,0 +1,17 @@ +#ifndef __OSFONT_H__ +#define __OSFONT_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +u16 OSGetFontEncode(void); +u16 OSSetFontEncode(u16 encode); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/dolphin/os/OSReset.h b/include/dolphin/os/OSReset.h new file mode 100644 index 00000000..65898d69 --- /dev/null +++ b/include/dolphin/os/OSReset.h @@ -0,0 +1,28 @@ +#ifndef __OSRESET_H__ +#define __OSRESET_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef BOOL (* OSResetFunction )(BOOL final); +typedef struct OSResetFunctionInfo OSResetFunctionInfo; + +struct OSResetFunctionInfo +{ + // public + OSResetFunction func; + u32 priority; + + // private + OSResetFunctionInfo* next; + OSResetFunctionInfo* prev; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/dolphin/os/OSThread.h b/include/dolphin/os/OSThread.h new file mode 100644 index 00000000..387d822a --- /dev/null +++ b/include/dolphin/os/OSThread.h @@ -0,0 +1,69 @@ +#ifndef __OSTHREAD_H__ +#define __OSTHREAD_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define OS_THREAD_SPECIFIC_MAX 2 + +typedef struct OSThread OSThread; +typedef struct OSThreadQueue OSThreadQueue; +typedef struct OSThreadLink OSThreadLink; +typedef s32 OSPriority; // 0 highest, 31 lowest + +typedef struct OSMutex OSMutex; +typedef struct OSMutexQueue OSMutexQueue; +typedef struct OSMutexLink OSMutexLink; +typedef struct OSCond OSCond; + +typedef void (*OSIdleFunction)(void* param); +typedef void (*OSSwitchThreadCallback)(OSThread* from, OSThread* to); + +struct OSThreadQueue { + OSThread* head; + OSThread* tail; +}; + +struct OSThreadLink { + OSThread* next; + OSThread* prev; +}; + +struct OSMutexQueue { + OSMutex* head; + OSMutex* tail; +}; + +struct OSMutexLink { + OSMutex* next; + OSMutex* prev; +}; + +struct OSThread { + OSContext context; + u16 state; + u16 attr; + s32 suspend; + OSPriority priority; + OSPriority base; + void* val; + OSThreadQueue* queue; + OSThreadLink link; + OSThreadQueue queueJoin; + OSMutex* mutex; + OSMutexQueue queueMutex; + OSThreadLink linkActive; + u8* stackBase; + u32* stackEnd; + s32 error; + void* specific[OS_THREAD_SPECIFIC_MAX]; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/obj_files.mk b/obj_files.mk index f2fbd6b6..1abaa5ad 100644 --- a/obj_files.mk +++ b/obj_files.mk @@ -816,7 +816,7 @@ DTK_FILES :=\ CARD_FILES :=\ $(BUILD_DIR)/asm/Dolphin/card/CARDBios.o\ - $(BUILD_DIR)/asm/Dolphin/card/CARDUnlock.o\ + $(BUILD_DIR)/src/Dolphin/card/CARDUnlock.ep.o\ $(BUILD_DIR)/asm/Dolphin/card/CARDRdwr.o\ $(BUILD_DIR)/asm/Dolphin/card/CARDBlock.o\ $(BUILD_DIR)/asm/Dolphin/card/CARDDir.o\ diff --git a/src/Dolphin/card/CARDBios.c b/src/Dolphin/card/CARDBios.c index a826649b..897cdc56 100644 --- a/src/Dolphin/card/CARDBios.c +++ b/src/Dolphin/card/CARDBios.c @@ -1,103 +1,549 @@ +#include +#include +#include +#include + +#include + +const char* __CARDVersion = "<< Dolphin SDK - CARD\trelease build: Sep 5 2002 05:35:20 (0x2301) >>"; + CARDControl __CARDBlock[2]; DVDDiskID __CARDDiskNone; -void __CARDDefaultApiCallback(s32 chan, s32 result) { -} +static u16 __CARDEncode; + +s32 __CARDReadStatus(s32 chan, u8* status); +s32 __CARDClearStatus(s32 chan); +void __CARDSetDiskID(const DVDDiskID* id); +static s32 Retry(s32 chan); + +BOOL OnReset(BOOL final); +static OSResetFunctionInfo ResetFunctionInfo = {OnReset, 127}; + +void __CARDDefaultApiCallback(s32 chan, s32 result) {} void __CARDExtHandler(s32 chan, OSContext* context) { - CARDControl* card; - CARDCallback callback; + CARDControl* card; + CARDCallback callback; - card = &__CARDBlock[chan]; - if (card->attached) { - card->attached = FALSE; - EXISetExiCallback(chan, 0); - OSCancelAlarm(&card->alarm); - callback = card->exiCallback; - - if (callback) { - card->exiCallback = 0; - callback(chan, CARD_RESULT_NOCARD); - } - - if (card->result != CARD_RESULT_BUSY) { - card->result = CARD_RESULT_NOCARD; - } - - callback = card->extCallback; - if (callback && CARD_MAX_MOUNT_STEP <= card->mountStep) { - card->extCallback = 0; - callback(chan, CARD_RESULT_NOCARD); - } + card = &__CARDBlock[chan]; + if (card->attached) { + card->attached = FALSE; + EXISetExiCallback(chan, 0); + OSCancelAlarm(&card->alarm); + callback = card->exiCallback; + + if (callback) { + card->exiCallback = 0; + callback(chan, CARD_RESULT_NOCARD); } + + if (card->result != CARD_RESULT_BUSY) { + card->result = CARD_RESULT_NOCARD; + } + + callback = card->extCallback; + if (callback && CARD_MAX_MOUNT_STEP <= card->mountStep) { + card->extCallback = 0; + callback(chan, CARD_RESULT_NOCARD); + } + } } void __CARDExiHandler(s32 chan, OSContext* context) { - CARDControl* card; - CARDCallback callback; - u8 status; - s32 result; + CARDControl* card; + CARDCallback callback; + u8 status; + s32 result; - card = &__CARDBlock[chan]; + card = &__CARDBlock[chan]; - OSCancelAlarm(&card->alarm); + OSCancelAlarm(&card->alarm); - if (!card->attached) { - return; - } - - if (!EXILock(chan, 0, 0)) { - result = CARD_RESULT_FATAL_ERROR; - goto fatal; - } - - if ((result = __CARDReadStatus(chan, &status)) < 0 || (result = __CARDClearStatus(chan)) < 0) { - goto error; - } - - if ((result = (status & 0x18) ? CARD_RESULT_IOERROR : CARD_RESULT_READY) == CARD_RESULT_IOERROR && --card->retry > 0) { - result = Retry(chan); - if (result >= 0) { - return; - } - goto fatal; + if (!card->attached) { + return; + } + + if (!EXILock(chan, 0, 0)) { + result = CARD_RESULT_FATAL_ERROR; + goto fatal; + } + + if ((result = __CARDReadStatus(chan, &status)) < 0 || (result = __CARDClearStatus(chan)) < 0) { + goto error; + } + + if ((result = (status & 0x18) ? CARD_RESULT_IOERROR : CARD_RESULT_READY) == CARD_RESULT_IOERROR && --card->retry > 0) { + result = Retry(chan); + if (result >= 0) { + return; } + goto fatal; + } error: - EXIUnlock(chan); + EXIUnlock(chan); fatal: - callback = card->exiCallback; - if (callback) { - card->exiCallback = 0; - callback(chan, result); - } + callback = card->exiCallback; + if (callback) { + card->exiCallback = 0; + callback(chan, result); + } } void __CARDTxHandler(s32 chan, OSContext* context) { - CARDControl* card; - CARDCallback callback; - BOOL err; + CARDControl* card; + CARDCallback callback; + BOOL err; - card = &__CARDBlock[chan]; - err = !EXIDeselect(chan); - EXIUnlock(chan); - callback = card->txCallback; - if (callback) { - card->txCallback = 0; - callback(chan, (!err && EXIProbe(chan)) ? CARD_RESULT_READY : CARD_RESULT_NOCARD); - } + card = &__CARDBlock[chan]; + err = !EXIDeselect(chan); + EXIUnlock(chan); + callback = card->txCallback; + if (callback) { + card->txCallback = 0; + callback(chan, (!err && EXIProbe(chan)) ? CARD_RESULT_READY : CARD_RESULT_NOCARD); + } } void __CARDUnlockedHandler(s32 chan, OSContext* context) { - CARDControl* card; - CARDCallback callback; + CARDControl* card; + CARDCallback callback; - card = &__CARDBlock[chan]; - callback = card->unlockCallback; - if (callback) { - card->unlockCallback = 0; - callback(chan, EXIProbe(chan) ? CARD_RESULT_UNLOCKED : CARD_RESULT_NOCARD); - } + card = &__CARDBlock[chan]; + callback = card->unlockCallback; + if (callback) { + card->unlockCallback = 0; + callback(chan, EXIProbe(chan) ? CARD_RESULT_UNLOCKED : CARD_RESULT_NOCARD); + } } +s32 __CARDEnableInterrupt(s32 chan, BOOL enable) { + BOOL err; + u32 cmd; + + if (!EXISelect(chan, 0, 4)) { + return CARD_RESULT_NOCARD; + } + + cmd = enable ? 0x81010000 : 0x81000000; + err = FALSE; + err |= !EXIImm(chan, &cmd, 2, 1, NULL); + err |= !EXISync(chan); + err |= !EXIDeselect(chan); + return err ? CARD_RESULT_NOCARD : CARD_RESULT_READY; +} + +s32 __CARDReadStatus(s32 chan, u8* status) { + BOOL err; + u32 cmd; + + if (!EXISelect(chan, 0, 4)) { + return CARD_RESULT_NOCARD; + } + + cmd = 0x83000000; + err = FALSE; + err |= !EXIImm(chan, &cmd, 2, 1, NULL); + err |= !EXISync(chan); + err |= !EXIImm(chan, status, 1, 0, NULL); + err |= !EXISync(chan); + err |= !EXIDeselect(chan); + return err ? CARD_RESULT_NOCARD : CARD_RESULT_READY; +} + +s32 __CARDClearStatus(s32 chan) { + BOOL err; + u32 cmd; + + if (!EXISelect(chan, 0, 4)) { + return CARD_RESULT_NOCARD; + } + + cmd = 0x89000000; + err = FALSE; + err |= !EXIImm(chan, &cmd, 1, 1, 0); + err |= !EXISync(chan); + err |= !EXIDeselect(chan); + + return err ? CARD_RESULT_NOCARD : CARD_RESULT_READY; +} + +static void TimeoutHandler(OSAlarm* alarm, OSContext* context) { + s32 chan; + CARDControl* card; + CARDCallback callback; + for (chan = 0; chan < 2; ++chan) { + card = &__CARDBlock[chan]; + if (alarm == &card->alarm) { + break; + } + } + + if (!card->attached) { + return; + } + + EXISetExiCallback(chan, NULL); + callback = card->exiCallback; + if (callback) { + card->exiCallback = 0; + callback(chan, CARD_RESULT_IOERROR); + } +} + +static void SetupTimeoutAlarm(CARDControl* card) { + OSCancelAlarm(&card->alarm); + switch (card->cmd[0]) { + case 0xF2: + OSSetAlarm(&card->alarm, OSMillisecondsToTicks(100), TimeoutHandler); + break; + case 0xF3: + break; + case 0xF4: + case 0xF1: + OSSetAlarm(&card->alarm, OSSecondsToTicks((OSTime)2) * (card->sectorSize / 0x2000), TimeoutHandler); + break; + } +} + +static s32 Retry(s32 chan) { + CARDControl* card; + card = &__CARDBlock[chan]; + + if (!EXISelect(chan, 0, 4)) { + EXIUnlock(chan); + return CARD_RESULT_NOCARD; + } + + SetupTimeoutAlarm(card); + + if (!EXIImmEx(chan, card->cmd, card->cmdlen, 1)) { + EXIDeselect(chan); + EXIUnlock(chan); + return CARD_RESULT_NOCARD; + } + + if (card->cmd[0] == 0x52 && !EXIImmEx(chan, (u8*)card->workArea + sizeof(CARDID), card->latency, 1)) { + EXIDeselect(chan); + EXIUnlock(chan); + return CARD_RESULT_NOCARD; + } + + if (card->mode == 0xffffffff) { + EXIDeselect(chan); + EXIUnlock(chan); + return CARD_RESULT_READY; + } + + if (!EXIDma(chan, card->buffer, (s32)((card->cmd[0] == 0x52) ? 512 : 128), card->mode, __CARDTxHandler)) { + EXIDeselect(chan); + EXIUnlock(chan); + return CARD_RESULT_NOCARD; + } + + return CARD_RESULT_READY; +} + +static void UnlockedCallback(s32 chan, s32 result) { + CARDCallback callback; + CARDControl* card; + + card = &__CARDBlock[chan]; + if (result >= 0) { + card->unlockCallback = UnlockedCallback; + if (!EXILock(chan, 0, __CARDUnlockedHandler)) { + result = CARD_RESULT_READY; + } else { + card->unlockCallback = 0; + result = Retry(chan); + } + } + + if (result < 0) { + switch (card->cmd[0]) { + case 0x52: + callback = card->txCallback; + if (callback) { + card->txCallback = 0; + callback(chan, result); + } + + break; + case 0xF2: + case 0xF4: + case 0xF1: + callback = card->exiCallback; + if (callback) { + card->exiCallback = 0; + callback(chan, result); + } + break; + } + } +} + +static s32 __CARDStart(s32 chan, CARDCallback txCallback, CARDCallback exiCallback) { + BOOL enabled; + CARDControl* card; + s32 result; + + enabled = OSDisableInterrupts(); + + card = &__CARDBlock[chan]; + if (!card->attached) { + result = CARD_RESULT_NOCARD; + } else { + + if (txCallback) { + card->txCallback = txCallback; + } + if (exiCallback) { + card->exiCallback = exiCallback; + } + card->unlockCallback = UnlockedCallback; + if (!EXILock(chan, 0, __CARDUnlockedHandler)) { + result = CARD_RESULT_BUSY; + } else { + card->unlockCallback = 0; + + if (!EXISelect(chan, 0, 4)) { + EXIUnlock(chan); + result = CARD_RESULT_NOCARD; + } else { + SetupTimeoutAlarm(card); + result = CARD_RESULT_READY; + } + } + } + + OSRestoreInterrupts(enabled); + return result; +} + +#define AD1(x) ((u8)(((x) >> 17) & 0x7f)) +#define AD1EX(x) ((u8)(AD1(x) | 0x80)); +#define AD2(x) ((u8)(((x) >> 9) & 0xff)) +#define AD3(x) ((u8)(((x) >> 7) & 0x03)) +#define BA(x) ((u8)((x)&0x7f)) + +s32 __CARDReadSegment(s32 chan, CARDCallback callback) { + CARDControl* card; + s32 result; + + card = &__CARDBlock[chan]; + card->cmd[0] = 0x52; + card->cmd[1] = AD1(card->addr); + card->cmd[2] = AD2(card->addr); + card->cmd[3] = AD3(card->addr); + card->cmd[4] = BA(card->addr); + card->cmdlen = 5; + card->mode = 0; + card->retry = 0; + + result = __CARDStart(chan, callback, 0); + if (result == CARD_RESULT_BUSY) { + result = CARD_RESULT_READY; + } else if (result >= 0) { + 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 = 0; + EXIDeselect(chan); + EXIUnlock(chan); + result = CARD_RESULT_NOCARD; + } else { + result = CARD_RESULT_READY; + } + } + return result; +} + +s32 __CARDWritePage(s32 chan, CARDCallback callback) { + CARDControl* card; + s32 result; + + card = &__CARDBlock[chan]; + card->cmd[0] = 0xF2; + card->cmd[1] = AD1(card->addr); + card->cmd[2] = AD2(card->addr); + card->cmd[3] = AD3(card->addr); + card->cmd[4] = BA(card->addr); + card->cmdlen = 5; + card->mode = 1; + card->retry = 3; + + result = __CARDStart(chan, 0, callback); + if (result == CARD_RESULT_BUSY) { + result = CARD_RESULT_READY; + } else if (result >= 0) { + if (!EXIImmEx(chan, card->cmd, card->cmdlen, 1) || !EXIDma(chan, card->buffer, 128, card->mode, __CARDTxHandler)) { + card->exiCallback = 0; + EXIDeselect(chan); + EXIUnlock(chan); + result = CARD_RESULT_NOCARD; + } else { + result = CARD_RESULT_READY; + } + } + return result; +} + +/* TODO: Needs frank fix for disconnected stack epilogue */ +s32 __CARDEraseSector(s32 chan, u32 addr, CARDCallback callback) { + CARDControl* card; + s32 result; + + card = &__CARDBlock[chan]; + card->cmd[0] = 0xF1; + card->cmd[1] = AD1(addr); + card->cmd[2] = AD2(addr); + card->cmdlen = 3; + card->mode = -1; + card->retry = 3; + + result = __CARDStart(chan, 0, callback); + + if (result == CARD_RESULT_BUSY) { + result = CARD_RESULT_READY; + } else if (result >= 0) { + if (!EXIImmEx(chan, card->cmd, card->cmdlen, 1)) { + card->exiCallback = NULL; + result = CARD_RESULT_NOCARD; + } else { + result = CARD_RESULT_READY; + } + + EXIDeselect(chan); + EXIUnlock(chan); + } + return result; +} + +void CARDInit(void) { + int chan; + + if (__CARDBlock[0].diskID && __CARDBlock[1].diskID) { + return; + } + + __CARDEncode = OSGetFontEncode(); + + OSRegisterVersion(__CARDVersion); + + DSPInit(); + OSInitAlarm(); + + for (chan = 0; chan < 2; ++chan) { + CARDControl* card = &__CARDBlock[chan]; + + card->result = CARD_RESULT_NOCARD; + OSInitThreadQueue(&card->threadQueue); + OSCreateAlarm(&card->alarm); + } + __CARDSetDiskID((DVDDiskID*)OSPhysicalToCached(0x0)); + + OSRegisterResetFunction(&ResetFunctionInfo); +} + +u16 __CARDGetFontEncode(s32 chan) { return __CARDEncode; } + +void __CARDSetDiskID(const DVDDiskID* id) { + __CARDBlock[0].diskID = id ? id : &__CARDDiskNone; + __CARDBlock[1].diskID = id ? id : &__CARDDiskNone; +} + +s32 __CARDGetControlBlock(s32 chan, CARDControl** pcard) { + BOOL enabled; + s32 result; + CARDControl* card; + + card = &__CARDBlock[chan]; + if (chan < 0 || chan >= 2 || card->diskID == NULL) { + return CARD_RESULT_FATAL_ERROR; + } + + enabled = OSDisableInterrupts(); + if (!card->attached) { + result = CARD_RESULT_NOCARD; + } else if (card->result == CARD_RESULT_BUSY) { + result = CARD_RESULT_BUSY; + } else { + card->result = CARD_RESULT_BUSY; + result = CARD_RESULT_READY; + card->apiCallback = 0; + *pcard = card; + } + OSRestoreInterrupts(enabled); + return result; +} + +/* TODO: Needs frank fix for disconnected stack epilogue */ +s32 __CARDPutControlBlock(CARDControl* card, s32 result) { + BOOL enabled; + + enabled = OSDisableInterrupts(); + if (card->attached) { + card->result = result; + } else if (card->result == CARD_RESULT_BUSY) { + card->result = result; + } + OSRestoreInterrupts(enabled); + return result; +} + +s32 CARDGetResultCode(s32 chan) { + CARDControl* card; + if (chan < 0 || chan >= 2) { + return CARD_RESULT_FATAL_ERROR; + } + card = &__CARDBlock[chan]; + return card->result; +} + +s32 CARDFreeBlocks(s32 chan, s32* byteNotUsed, s32* filesNotUsed) { + CARDControl* card; + s32 result; + u16* fat; + CARDDir* dir; + CARDDir* ent; + u16 fileNo; + + result = __CARDGetControlBlock(chan, &card); + if (result < 0) { + return result; + } + + fat = __CARDGetFatBlock(card); + dir = __CARDGetDirBlock(card); + if (fat == 0 || dir == 0) { + return __CARDPutControlBlock(card, CARD_RESULT_BROKEN); + } + + if (byteNotUsed) { + *byteNotUsed = (s32)(card->sectorSize * fat[CARD_FAT_FREEBLOCKS]); + } + + if (filesNotUsed) { + *filesNotUsed = 0; + for (fileNo = 0; fileNo < CARD_MAX_FILE; fileNo++) { + ent = &dir[fileNo]; + if (ent->fileName[0] == 0xff) { + ++*filesNotUsed; + } + } + } + + return __CARDPutControlBlock(card, CARD_RESULT_READY); +} + +static BOOL OnReset(BOOL final) { + if (!final) { + if (CARDUnmount(0) == CARD_RESULT_BUSY || CARDUnmount(1) == CARD_RESULT_BUSY) { + return FALSE; + } + } + + return TRUE; +} diff --git a/src/Dolphin/card/CARDUnlock.c b/src/Dolphin/card/CARDUnlock.c new file mode 100644 index 00000000..d56801f1 --- /dev/null +++ b/src/Dolphin/card/CARDUnlock.c @@ -0,0 +1,390 @@ +#include +#include +#include +#include + +#include + +static void InitCallback(void* task); +static void DoneCallback(void* task); + +static u8 CardData[] ATTRIBUTE_ALIGN(32) = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x02, 0xFF, 0x00, 0x21, 0x13, 0x06, 0x12, 0x03, 0x12, 0x04, 0x13, 0x05, 0x00, 0x92, 0x00, 0xFF, + 0x00, 0x88, 0xFF, 0xFF, 0x00, 0x89, 0xFF, 0xFF, 0x00, 0x8A, 0xFF, 0xFF, 0x00, 0x8B, 0xFF, 0xFF, 0x8F, 0x00, 0x02, 0xBF, 0x00, 0x88, + 0x16, 0xFC, 0xDC, 0xD1, 0x16, 0xFD, 0x00, 0x00, 0x16, 0xFB, 0x00, 0x01, 0x02, 0xBF, 0x00, 0x8E, 0x25, 0xFF, 0x03, 0x80, 0xFF, 0x00, + 0x02, 0x94, 0x00, 0x27, 0x02, 0xBF, 0x00, 0x8E, 0x1F, 0xDF, 0x24, 0xFF, 0x02, 0x40, 0x0F, 0xFF, 0x00, 0x98, 0x04, 0x00, 0x00, 0x9A, + 0x00, 0x10, 0x00, 0x99, 0x00, 0x00, 0x8E, 0x00, 0x02, 0xBF, 0x00, 0x94, 0x02, 0xBF, 0x86, 0x44, 0x02, 0xBF, 0x00, 0x88, 0x16, 0xFC, + 0xDC, 0xD1, 0x16, 0xFD, 0x00, 0x03, 0x16, 0xFB, 0x00, 0x01, 0x8F, 0x00, 0x02, 0xBF, 0x00, 0x8E, 0x03, 0x80, 0xCD, 0xD1, 0x02, 0x94, + 0x00, 0x48, 0x27, 0xFF, 0x03, 0x80, 0x00, 0x01, 0x02, 0x95, 0x00, 0x5A, 0x03, 0x80, 0x00, 0x02, 0x02, 0x95, 0x80, 0x00, 0x02, 0x9F, + 0x00, 0x48, 0x00, 0x21, 0x8E, 0x00, 0x02, 0xBF, 0x00, 0x8E, 0x25, 0xFF, 0x02, 0xBF, 0x00, 0x8E, 0x25, 0xFF, 0x02, 0xBF, 0x00, 0x8E, + 0x25, 0xFF, 0x02, 0xBF, 0x00, 0x8E, 0x00, 0xC5, 0xFF, 0xFF, 0x03, 0x40, 0x0F, 0xFF, 0x1C, 0x9F, 0x02, 0xBF, 0x00, 0x8E, 0x00, 0xC7, + 0xFF, 0xFF, 0x02, 0xBF, 0x00, 0x8E, 0x00, 0xC6, 0xFF, 0xFF, 0x02, 0xBF, 0x00, 0x8E, 0x00, 0xC0, 0xFF, 0xFF, 0x02, 0xBF, 0x00, 0x8E, + 0x20, 0xFF, 0x03, 0x40, 0x0F, 0xFF, 0x1F, 0x5F, 0x02, 0xBF, 0x00, 0x8E, 0x21, 0xFF, 0x02, 0xBF, 0x00, 0x8E, 0x23, 0xFF, 0x12, 0x05, + 0x12, 0x06, 0x02, 0x9F, 0x80, 0xB5, 0x00, 0x21, 0x27, 0xFC, 0x03, 0xC0, 0x80, 0x00, 0x02, 0x9D, 0x00, 0x88, 0x02, 0xDF, 0x27, 0xFE, + 0x03, 0xC0, 0x80, 0x00, 0x02, 0x9C, 0x00, 0x8E, 0x02, 0xDF, 0x2E, 0xCE, 0x2C, 0xCF, 0x00, 0xF8, 0xFF, 0xCD, 0x00, 0xF9, 0xFF, 0xC9, + 0x00, 0xFA, 0xFF, 0xCB, 0x26, 0xC9, 0x02, 0xC0, 0x00, 0x04, 0x02, 0x9D, 0x00, 0x9C, 0x02, 0xDF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +typedef struct DecodeParameters { + u8* inputAddr; + u32 inputLength; + u32 aramAddr; + u8* outputAddr; +} DecodeParameters; + +static unsigned long int next = 1; + +static int CARDRand(void) { + next = next * 1103515245 + 12345; + return (int)((unsigned int)(next / 65536) % 32768); +} + +static void CARDSrand(unsigned int seed) { next = seed; } + +static u32 GetInitVal(void) { + u32 tmp; + u32 tick; + + tick = OSGetTick(); + CARDSrand(tick); + tmp = 0x7fec8000; + tmp |= CARDRand(); + tmp &= 0xfffff000; + return tmp; +} + +static u32 exnor_1st(u32 data, u32 rshift) { + u32 wk; + u32 w; + u32 i; + + w = data; + for (i = 0; i < rshift; i++) { + wk = ~(w ^ (w >> 7) ^ (w >> 15) ^ (w >> 23)); + w = (w >> 1) | ((wk << 30) & 0x40000000); + } + return w; +} + +static u32 exnor(u32 data, u32 lshift) { + u32 wk; + u32 w; + u32 i; + + w = data; + for (i = 0; i < lshift; i++) { + // 1bit Left Shift + wk = ~(w ^ (w << 7) ^ (w << 15) ^ (w << 23)); + w = (w << 1) | ((wk >> 30) & 0x00000002); + // printf("i=%d, w=%8x\n", i, w); + } + return w; +} + +static u32 bitrev(u32 data) { + u32 wk; + u32 i; + u32 k = 0; + u32 j = 1; + + wk = 0; + for (i = 0; i < 32; i++) { + if (i > 15) { + if (i == 31) { + wk |= (((data & (0x01 << 31)) >> 31) & 0x01); + } else { + wk |= ((data & (0x01 << i)) >> j); + j += 2; + } + } else { + wk |= ((data & (0x01 << i)) << (31 - i - k)); + k++; + } + } + return wk; +} + +#define SEC_AD1(x) ((u8)(((x) >> 29) & 0x03)) +#define SEC_AD2(x) ((u8)(((x) >> 21) & 0xff)) +#define SEC_AD3(x) ((u8)(((x) >> 19) & 0x03)) +#define SEC_BA(x) ((u8)(((x) >> 12) & 0x7f)) + +static s32 ReadArrayUnlock(s32 chan, u32 data, void* rbuf, s32 rlen, s32 mode) { + CARDControl* card; + BOOL err; + u8 cmd[5]; + + card = &__CARDBlock[chan]; + if (!EXISelect(chan, 0, 4)) { + return CARD_RESULT_NOCARD; + } + + data &= 0xfffff000; + memset(cmd, 0, 5); + cmd[0] = 0x52; + if (mode == 0) { + cmd[1] = SEC_AD1(data); + cmd[2] = SEC_AD2(data); + cmd[3] = SEC_AD3(data); + cmd[4] = SEC_BA(data); + } else { + cmd[1] = (u8)((data & 0xff000000) >> 24); + cmd[2] = (u8)((data & 0x00ff0000) >> 16); + } + + err = FALSE; + err |= !EXIImmEx(chan, cmd, 5, 1); + err |= !EXIImmEx(chan, (u8*)card->workArea + (u32)sizeof(CARDID), card->latency, 1); + err |= !EXIImmEx(chan, rbuf, rlen, 0); + err |= !EXIDeselect(chan); + + return err ? CARD_RESULT_NOCARD : CARD_RESULT_READY; +} + +// Calculate Dummy Read Length, 4-32Bytes +static s32 DummyLen(void) { + u32 tick; + u32 wk; + s32 tmp; + u32 max; + + wk = 1; + max = 0; + tick = OSGetTick(); + CARDSrand(tick); + + tmp = CARDRand(); + tmp &= 0x0000001f; + tmp += 1; + while ((tmp < 4) && (max < 10)) { + tick = OSGetTick(); + tmp = (s32)(tick << wk); + wk++; + if (wk > 16) { + wk = 1; + } + CARDSrand((u32)tmp); + tmp = CARDRand(); + tmp &= 0x0000001f; + tmp += 1; + max++; + } + if (tmp < 4) { + tmp = 4; + } + + return tmp; +} + +s32 __CARDUnlock(s32 chan, u8 flashID[12]) { + u32 init_val; + u32 data; + + s32 dummy; + s32 rlen; + u32 rshift; + + u8 fsts; + u32 wk, wk1; + u32 Ans1 = 0; + u32 Ans2 = 0; + u32* dp; + u8 rbuf[64]; + u32 para1A = 0; + u32 para1B = 0; + u32 para2A = 0; + u32 para2B = 0; + + CARDControl* card; + DSPTaskInfo* task; + DecodeParameters* param; + u8* input; + u8* output; + + card = &__CARDBlock[chan]; + task = &card->task; + param = (DecodeParameters*)card->workArea; + input = (u8*)((u8*)param + sizeof(DecodeParameters)); + input = (u8*)OSRoundUp32B(input); + output = input + 32; + + fsts = 0; + init_val = GetInitVal(); + + dummy = DummyLen(); + rlen = dummy; + if (ReadArrayUnlock(chan, init_val, rbuf, rlen, 0) < 0) { + return CARD_RESULT_NOCARD; + } + + rshift = (u32)(dummy * 8 + 1); + wk = exnor_1st(init_val, rshift); + wk1 = ~(wk ^ (wk >> 7) ^ (wk >> 15) ^ (wk >> 23)); + card->scramble = (wk | ((wk1 << 31) & 0x80000000)); + card->scramble = bitrev(card->scramble); + dummy = DummyLen(); + rlen = 20 + dummy; + data = 0; + if (ReadArrayUnlock(chan, data, rbuf, rlen, 1) < 0) { + return CARD_RESULT_NOCARD; + } + dp = (u32*)rbuf; + para1A = *dp++; + para1B = *dp++; + Ans1 = *dp++; + para2A = *dp++; + para2B = *dp++; + para1A = (para1A ^ card->scramble); + rshift = 32; + wk = exnor(card->scramble, rshift); + wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23)); + card->scramble = (wk | ((wk1 >> 31) & 0x00000001)); + para1B = (para1B ^ card->scramble); + rshift = 32; + wk = exnor(card->scramble, rshift); + wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23)); + card->scramble = (wk | ((wk1 >> 31) & 0x00000001)); + Ans1 ^= card->scramble; + rshift = 32; + wk = exnor(card->scramble, rshift); + wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23)); + card->scramble = (wk | ((wk1 >> 31) & 0x00000001)); + para2A = (para2A ^ card->scramble); + rshift = 32; + wk = exnor(card->scramble, rshift); + wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23)); + card->scramble = (wk | ((wk1 >> 31) & 0x00000001)); + para2B = (para2B ^ card->scramble); + rshift = (u32)(dummy * 8); + wk = exnor(card->scramble, rshift); + wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23)); + card->scramble = (wk | ((wk1 >> 31) & 0x00000001)); + rshift = 32 + 1; + wk = exnor(card->scramble, rshift); + wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23)); + card->scramble = (wk | ((wk1 >> 31) & 0x00000001)); + + *(u32*)&input[0] = para2A; + *(u32*)&input[4] = para2B; + + param->inputAddr = input; + param->inputLength = 8; + param->outputAddr = output; + param->aramAddr = 0; + + DCFlushRange(input, 8); + DCInvalidateRange(output, 4); + DCFlushRange(param, sizeof(DecodeParameters)); + + task->priority = 255; + task->iram_mmem_addr = (u16*)OSPhysicalToCached(CardData); + task->iram_length = 0x160; + task->iram_addr = 0; + task->dsp_init_vector = 0x10; + task->init_cb = InitCallback; + task->res_cb = NULL; + task->done_cb = DoneCallback; + task->req_cb = NULL; + DSPAddTask(task); + + dp = (u32*)flashID; + *dp++ = para1A; + *dp++ = para1B; + *dp = Ans1; + + return CARD_RESULT_READY; +} + +static void InitCallback(void* _task) { + s32 chan; + CARDControl* card; + DSPTaskInfo* task; + DecodeParameters* param; + + task = _task; + for (chan = 0; chan < 2; ++chan) { + card = &__CARDBlock[chan]; + if ((DSPTaskInfo*)&card->task == task) { + break; + } + } + param = (DecodeParameters*)card->workArea; + + DSPSendMailToDSP(0xff000000); + while (DSPCheckMailToDSP()) + ; + + DSPSendMailToDSP((u32)param); + while (DSPCheckMailToDSP()) + ; +} + +static void DoneCallback(void* _task) { + u8 rbuf[64]; + u32 data; + s32 dummy; + s32 rlen; + u32 rshift; + + u8 unk; + u32 wk, wk1; + u32 Ans2; + + s32 chan; + CARDControl* card; + s32 result; + DSPTaskInfo* task; + DecodeParameters* param; + + u8* input; + u8* output; + task = _task; + for (chan = 0; chan < 2; ++chan) { + card = &__CARDBlock[chan]; + if ((DSPTaskInfo*)&card->task == task) { + break; + } + } + + param = (DecodeParameters*)card->workArea; + input = (u8*)((u8*)param + sizeof(DecodeParameters)); + input = (u8*)OSRoundUp32B(input); + output = input + 32; + + Ans2 = *(u32*)output; + dummy = DummyLen(); + rlen = dummy; + data = ((Ans2 ^ card->scramble) & 0xffff0000); + if (ReadArrayUnlock(chan, data, rbuf, rlen, 1) < 0) { + EXIUnlock(chan); + __CARDMountCallback(chan, CARD_RESULT_NOCARD); + return; + } + + rshift = (u32)((dummy + 4 + card->latency) * 8 + 1); + wk = exnor(card->scramble, rshift); + wk1 = ~(wk ^ (wk << 7) ^ (wk << 15) ^ (wk << 23)); + card->scramble = (wk | ((wk1 >> 31) & 0x00000001)); + + dummy = DummyLen(); + rlen = dummy; + data = (((Ans2 << 16) ^ card->scramble) & 0xffff0000); + if (ReadArrayUnlock(chan, data, rbuf, rlen, 1) < 0) { + EXIUnlock(chan); + __CARDMountCallback(chan, CARD_RESULT_NOCARD); + return; + } + result = __CARDReadStatus(chan, &unk); + if (!EXIProbe(chan)) { + EXIUnlock(chan); + __CARDMountCallback(chan, CARD_RESULT_NOCARD); + return; + } + if (result == CARD_RESULT_READY && !(unk & 0x40)) { + EXIUnlock(chan); + result = CARD_RESULT_IOERROR; + } + __CARDMountCallback(chan, result); +}