Merge pull request #445 from dbalatoni13/main
Imported lots of dolphin library files
This commit is contained in:
commit
be6ea5de09
40 changed files with 7486 additions and 100 deletions
|
|
@ -4366,16 +4366,24 @@ lbl_8013C958 = .data:0x8013C958; // type:object size:0x29 scope:local data:strin
|
|||
lbl_8013C984 = .data:0x8013C984; // type:object size:0x29 scope:local data:string
|
||||
lbl_8013C9B0 = .data:0x8013C9B0; // type:object size:0x29 scope:local data:string
|
||||
DEMOFontBitmap = .data:0x8013C9E0; // type:object size:0xC00 align:32
|
||||
lbl_8013D5E0 = .data:0x8013D5E0; // type:object size:0xC data:string
|
||||
lbl_8013D5EC = .data:0x8013D5EC; // type:object size:0x28
|
||||
lbl_8013D5E0 = .data:0x8013D5E0; // type:object size:0xC scope:local data:string
|
||||
lbl_8013D5EC = .data:0x8013D5EC; // type:object size:0x28 scope:local data:string
|
||||
jumptable_8013D614 = .data:0x8013D614; // type:object size:0x28 scope:local
|
||||
jumptable_8013D698 = .data:0x8013D698; // type:object size:0x28 scope:local
|
||||
jumptable_8013D6C0 = .data:0x8013D6C0; // type:object size:0x28 scope:local
|
||||
jumptable_8013D6E8 = .data:0x8013D6E8; // type:object size:0x28 scope:local
|
||||
jumptable_8013D710 = .data:0x8013D710; // type:object size:0x28 scope:local
|
||||
ResetFunctionInfo = .data:0x8013D738; // type:object size:0x10
|
||||
lbl_8013D748 = .data:0x8013D748; // type:object size:0x38
|
||||
lbl_8013D780 = .data:0x8013D780; // type:object size:0x140
|
||||
lbl_8013D748 = .data:0x8013D748; // type:object size:0x20 scope:local data:string
|
||||
lbl_8013D768 = .data:0x8013D768; // type:object size:0xC scope:local data:string
|
||||
lbl_8013D774 = .data:0x8013D774; // type:object size:0xC scope:local data:string
|
||||
lbl_8013D780 = .data:0x8013D780; // type:object size:0x20 scope:local data:string
|
||||
lbl_8013D7A0 = .data:0x8013D7A0; // type:object size:0x30 scope:local data:string
|
||||
lbl_8013D7D0 = .data:0x8013D7D0; // type:object size:0x30 scope:local data:string
|
||||
lbl_8013D800 = .data:0x8013D800; // type:object size:0x30 scope:local data:string
|
||||
lbl_8013D830 = .data:0x8013D830; // type:object size:0x30 scope:local data:string
|
||||
lbl_8013D860 = .data:0x8013D860; // type:object size:0x30 scope:local data:string
|
||||
lbl_8013D890 = .data:0x8013D890; // type:object size:0x30 scope:local data:string
|
||||
jumptable_8013D8C0 = .data:0x8013D8C0; // type:object size:0x68 scope:local
|
||||
jumptable_8013D928 = .data:0x8013D928; // type:object size:0x44 scope:local
|
||||
jumptable_8013D96C = .data:0x8013D96C; // type:object size:0x1C scope:local
|
||||
|
|
@ -4400,6 +4408,17 @@ SectorSizeTable = .data:0x8013E060; // type:object size:0x20 scope:local
|
|||
LatencyTable = .data:0x8013E080; // type:object size:0x20 scope:local
|
||||
Si = .data:0x8013E0A0; // type:object size:0x14 scope:local data:4byte
|
||||
Type = .data:0x8013E0B4; // type:object size:0x10 scope:local
|
||||
@464 = .data:0x8013E0C4; // type:object size:0x9 scope:local data:string
|
||||
lbl_8013E0D0 = .data:0x8013E0D0; // type:object size:0xF scope:local data:string
|
||||
lbl_8013E0E0 = .data:0x8013E0E0; // type:object size:0xF scope:local data:string
|
||||
lbl_8013E0F0 = .data:0x8013E0F0; // type:object size:0xD scope:local data:string
|
||||
lbl_8013E100 = .data:0x8013E100; // type:object size:0xA scope:local data:string
|
||||
lbl_8013E10C = .data:0x8013E10C; // type:object size:0x10 scope:local data:string
|
||||
lbl_8013E11C = .data:0x8013E11C; // type:object size:0x14 scope:local data:string
|
||||
lbl_8013E130 = .data:0x8013E130; // type:object size:0x12 scope:local data:string
|
||||
lbl_8013E144 = .data:0x8013E144; // type:object size:0x14 scope:local data:string
|
||||
lbl_8013E158 = .data:0x8013E158; // type:object size:0x9 scope:local data:string
|
||||
lbl_8013E164 = .data:0x8013E164; // type:object size:0x9 scope:local data:string
|
||||
XYNTSC = .data:0x8013E170; // type:object size:0x30 scope:local
|
||||
XYPAL = .data:0x8013E1A0; // type:object size:0x30 scope:local
|
||||
__vt__Q23std9exception = .data:0x8013E208; // type:object size:0x10 scope:weak
|
||||
|
|
@ -4982,7 +5001,7 @@ autoInvalidation = .sdata:0x801D38F0; // type:object size:0x4 scope:local data:4
|
|||
@35 = .sdata:0x801D38F8; // type:object size:0x2 scope:local data:string
|
||||
@40 = .sdata:0x801D38FC; // type:object size:0x4 scope:local data:string
|
||||
@41 = .sdata:0x801D3900; // type:object size:0x3 scope:local data:string
|
||||
lbl_801D3908 = .sdata:0x801D3908; // type:object size:0x8 data:string
|
||||
lbl_801D3908 = .sdata:0x801D3908; // type:object size:0x8 scope:local data:string
|
||||
ClampRegion = .sdata:0x801D3910; // type:object size:0x8 scope:local data:byte
|
||||
ResettingChan = .sdata:0x801D3918; // type:object size:0x4 scope:local data:4byte
|
||||
XPatchBits = .sdata:0x801D391C; // type:object size:0x4 scope:local data:4byte
|
||||
|
|
@ -7307,13 +7326,13 @@ lbl_801D63A8 = .sdata2:0x801D63A8; // type:object size:0x4 data:float
|
|||
lbl_801D63AC = .sdata2:0x801D63AC; // type:object size:0x4 data:float
|
||||
lbl_801D63B0 = .sdata2:0x801D63B0; // type:object size:0x4 data:float
|
||||
lbl_801D63B4 = .sdata2:0x801D63B4; // type:object size:0x4 data:float
|
||||
lbl_801D63B8 = .sdata2:0x801D63B8; // type:object size:0x4 data:float
|
||||
lbl_801D63BC = .sdata2:0x801D63BC; // type:object size:0x4 data:float
|
||||
lbl_801D63C0 = .sdata2:0x801D63C0; // type:object size:0x8 data:double
|
||||
lbl_801D63C8 = .sdata2:0x801D63C8; // type:object size:0x8 data:double
|
||||
lbl_801D63D0 = .sdata2:0x801D63D0; // type:object size:0x8 data:float
|
||||
lbl_801D63D8 = .sdata2:0x801D63D8; // type:object size:0x4 data:float
|
||||
lbl_801D63E0 = .sdata2:0x801D63E0; // type:object size:0x8 data:double
|
||||
lbl_801D63B8 = .sdata2:0x801D63B8; // type:object size:0x4 scope:local data:float
|
||||
lbl_801D63BC = .sdata2:0x801D63BC; // type:object size:0x4 scope:local data:float
|
||||
lbl_801D63C0 = .sdata2:0x801D63C0; // type:object size:0x8 scope:local data:double
|
||||
lbl_801D63C8 = .sdata2:0x801D63C8; // type:object size:0x8 scope:local data:double
|
||||
lbl_801D63D0 = .sdata2:0x801D63D0; // type:object size:0x8 scope:local data:float
|
||||
lbl_801D63D8 = .sdata2:0x801D63D8; // type:object size:0x4 scope:local data:float
|
||||
lbl_801D63E0 = .sdata2:0x801D63E0; // type:object size:0x8 scope:local data:double
|
||||
lbl_801D63E8 = .sdata2:0x801D63E8; // type:object size:0x4 data:4byte
|
||||
lbl_801D63EC = .sdata2:0x801D63EC; // type:object size:0x4 data:4byte
|
||||
lbl_801D63F0 = .sdata2:0x801D63F0; // type:object size:0x4 data:4byte
|
||||
|
|
|
|||
20
configure.py
20
configure.py
|
|
@ -517,10 +517,10 @@ config.libs = [
|
|||
DolphinLib(
|
||||
"demo",
|
||||
[
|
||||
Object(NonMatching, "dolphin/demo/DEMOInit.c"),
|
||||
Object(NonMatching, "dolphin/demo/DEMOFont.c"),
|
||||
Object(Matching, "dolphin/demo/DEMOInit.c"),
|
||||
Object(Matching, "dolphin/demo/DEMOFont.c"),
|
||||
Object(NonMatching, "dolphin/demo/DEMOPuts.c"),
|
||||
Object(NonMatching, "dolphin/demo/DEMOStats.c"),
|
||||
Object(Matching, "dolphin/demo/DEMOStats.c"),
|
||||
],
|
||||
),
|
||||
DolphinLib(
|
||||
|
|
@ -546,9 +546,9 @@ config.libs = [
|
|||
DolphinLib(
|
||||
"dsp",
|
||||
[
|
||||
Object(NonMatching, "dolphin/dsp/dsp.c"),
|
||||
Object(NonMatching, "dolphin/dsp/dsp_debug.c"),
|
||||
Object(NonMatching, "dolphin/dsp/dsp_task.c"),
|
||||
Object(Matching, "dolphin/dsp/dsp.c"),
|
||||
Object(Matching, "dolphin/dsp/dsp_debug.c"),
|
||||
Object(Matching, "dolphin/dsp/dsp_task.c"),
|
||||
],
|
||||
),
|
||||
DolphinLib(
|
||||
|
|
@ -594,15 +594,15 @@ config.libs = [
|
|||
DolphinLib(
|
||||
"exi",
|
||||
[
|
||||
Object(NonMatching, "dolphin/exi/EXIBios.c"),
|
||||
Object(NonMatching, "dolphin/exi/EXIUart.c"),
|
||||
Object(Matching, "dolphin/exi/EXIBios.c"),
|
||||
Object(Matching, "dolphin/exi/EXIUart.c"),
|
||||
],
|
||||
),
|
||||
DolphinLib(
|
||||
"si",
|
||||
[
|
||||
Object(NonMatching, "dolphin/si/SIBios.c"),
|
||||
Object(NonMatching, "dolphin/si/SISamplingRate.c"),
|
||||
Object(Matching, "dolphin/si/SIBios.c"),
|
||||
Object(Matching, "dolphin/si/SISamplingRate.c"),
|
||||
],
|
||||
),
|
||||
DolphinLib(
|
||||
|
|
|
|||
|
|
@ -21,103 +21,149 @@ extern "C" {
|
|||
#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
|
||||
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;
|
||||
u32 iconAddr; // 0xffffffff if not used
|
||||
u16 iconFormat;
|
||||
u16 iconSpeed;
|
||||
|
||||
u8 permission;
|
||||
u8 copyTimes;
|
||||
u16 startBlock;
|
||||
u16 length;
|
||||
u8 _padding1[2];
|
||||
u8 permission;
|
||||
u8 copyTimes;
|
||||
u16 startBlock;
|
||||
u16 length;
|
||||
u8 _padding1[2];
|
||||
|
||||
u32 commentAddr; // 0xffffffff if not used
|
||||
u32 commentAddr; // 0xffffffff if not used
|
||||
} CARDDir;
|
||||
|
||||
typedef struct CARDDirCheck {
|
||||
u8 padding0[64 - 2 * 4];
|
||||
u16 padding1;
|
||||
s16 checkCode;
|
||||
u16 checkSum;
|
||||
u16 checkSumInv;
|
||||
u8 padding0[64 - 2 * 4];
|
||||
u16 padding1;
|
||||
s16 checkCode;
|
||||
u16 checkSum;
|
||||
u16 checkSumInv;
|
||||
} CARDDirCheck;
|
||||
|
||||
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* currentDir;
|
||||
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;
|
||||
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 *currentDir;
|
||||
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 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];
|
||||
u8 padding[512 - 32 - 5 * 2];
|
||||
|
||||
u16 checkSum;
|
||||
u16 checkSumInv;
|
||||
u16 checkSum;
|
||||
u16 checkSumInv;
|
||||
} CARDID;
|
||||
|
||||
void __CARDDefaultApiCallback(s32 chan, s32 result);
|
||||
s32 __CARDEraseSector(s32 chan, u32 addr, CARDCallback callback);
|
||||
s32 __CARDPutControlBlock(struct CARDControl *card, s32 result);
|
||||
void __CARDSyncCallback(s32 chan, s32 result);
|
||||
u16 *__CARDGetFatBlock(CARDControl *card);
|
||||
|
||||
#define CARDIsValidBlockNo(card, iBlock) \
|
||||
(CARD_NUM_SYSTEM_BLOCK <= (iBlock) && (iBlock) < (card)->cBlock)
|
||||
#define __CARDGetDirCheck(dir) ((CARDDirCheck*)&(dir)[CARD_MAX_FILE])
|
||||
/* CARDBios */
|
||||
void __CARDExtHandler(s32 chan, OSContext *context);
|
||||
void __CARDExiHandler(s32 chan, OSContext *context);
|
||||
void __CARDTxHandler(s32 chan, OSContext *context);
|
||||
void __CARDUnlockedHandler(s32 chan, OSContext *context);
|
||||
s32 __CARDEnableInterrupt(s32 chan, BOOL enable);
|
||||
s32 __CARDReadStatus(s32 chan, u8 *status);
|
||||
s32 __CARDReadVendorID(s32 chan, u16 *vendorId);
|
||||
s32 __CARDClearStatus(s32 chan);
|
||||
s32 __CARDStart(s32 chan, CARDCallback txCallback, CARDCallback exiCallback);
|
||||
s32 __CARDReadSegment(s32 chan, CARDCallback callback);
|
||||
s32 __CARDWritePage(s32 chan, CARDCallback callback);
|
||||
u16 __CARDGetFontEncode(void);
|
||||
void __CARDSetDiskID(const DVDDiskID *id);
|
||||
s32 __CARDGetControlBlock(s32 chan, struct CARDControl **pcard);
|
||||
s32 __CARDSync(s32 chan);
|
||||
|
||||
CARDDir* __CARDGetDirBlock(CARDControl* card);
|
||||
u16* __CARDGetFatBlock(CARDControl* card);
|
||||
s32 __CARDUpdateFatBlock(s32 chan, u16* fat, CARDCallback callback);
|
||||
void __CARDCheckSum(void* ptr, int length, u16* checkSum, u16* checkSumInv);
|
||||
u16 __CARDGetFontEncode();
|
||||
void __CARDExiHandler(s32 chan, OSContext* context);
|
||||
void __CARDExtHandler(s32 chan, OSContext* context);
|
||||
void __CARDUnlockedHandler(s32 chan, OSContext* context);
|
||||
s32 __CARDAccess(CARDControl* card, CARDDir* ent);
|
||||
BOOL __CARDIsWritable(CARDDir* ent);
|
||||
/* CARDBlock */
|
||||
s32 __CARDAllocBlock(s32 chan, u32 cBlock, CARDCallback callback);
|
||||
s32 __CARDFreeBlock(s32 chan, u16 nBlock, CARDCallback callback);
|
||||
s32 __CARDUpdateFatBlock(s32 chan, u16 *fat, CARDCallback callback);
|
||||
|
||||
/* CARDCheck */
|
||||
void __CARDCheckSum(void *ptr, int length, u16 *checksum, u16 *checksumInv);
|
||||
s32 __CARDVerify(CARDControl *card);
|
||||
|
||||
/* CARDDir */
|
||||
CARDDir *__CARDGetDirBlock(CARDControl *card);
|
||||
s32 __CARDUpdateDir(s32 chan, CARDCallback callback);
|
||||
|
||||
/* CARDFormat */
|
||||
s32 __CARDFormatRegionAsync(s32 chan, u16 encode, CARDCallback callback);
|
||||
|
||||
/* CARDMount */
|
||||
void __CARDMountCallback(s32 chan, s32 result);
|
||||
|
||||
/* CARDOpen */
|
||||
BOOL __CARDCompareFileName(CARDDir *ent, const char *fileName);
|
||||
s32 __CARDAccess(CARDControl *card, CARDDir *ent);
|
||||
BOOL __CARDIsPublic(CARDDir *ent);
|
||||
s32 __CARDIsReadable(CARDControl *card, CARDDir *ent);
|
||||
s32 __CARDGetFileNo(CARDControl *card, const char *fileName, s32 *pfileNo);
|
||||
BOOL __CARDIsOpened(CARDControl *card, s32 fileNo);
|
||||
|
||||
/* CARDRdwr */
|
||||
s32 __CARDRead(s32 chan, u32 addr, s32 length, void *dst, CARDCallback callback);
|
||||
s32 __CARDWrite(s32 chan, u32 addr, s32 length, void *dst, CARDCallback callback);
|
||||
|
||||
/* CARDRead */
|
||||
s32 __CARDSeek(CARDFileInfo *fileInfo, s32 length, s32 offset, CARDControl **pcard);
|
||||
|
||||
/* CARDUnlock */
|
||||
s32 __CARDUnlock(s32 chan, u8 flashID[12]);
|
||||
|
||||
#define CARDIsValidBlockNo(card, iBlock) (CARD_NUM_SYSTEM_BLOCK <= (iBlock) && (iBlock) < (card)->cBlock)
|
||||
#define __CARDGetDirCheck(dir) ((CARDDirCheck *)&(dir)[CARD_MAX_FILE])
|
||||
|
||||
#define TRUNC(n, a) (((u32)(n)) & ~((a)-1))
|
||||
#define OFFSET(n, a) (((u32)(n)) & ((a)-1))
|
||||
|
|
|
|||
72
include/dolphin/demo.h
Normal file
72
include/dolphin/demo.h
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
#ifndef _DOLPHIN_DEMO
|
||||
#define _DOLPHIN_DEMO
|
||||
|
||||
#include <dolphin/pad.h>
|
||||
#include <dolphin/gx.h>
|
||||
|
||||
struct STRUCT_MENU_ITEM {
|
||||
/* 0x00 */ char * name;
|
||||
/* 0x04 */ unsigned long flags;
|
||||
/* 0x08 */ void (* function)(struct STRUCT_MENU *, unsigned long, unsigned long *);
|
||||
/* 0x0C */ struct STRUCT_MENU * link;
|
||||
};
|
||||
|
||||
struct STRUCT_MENU {
|
||||
/* 0x00 */ char * title;
|
||||
/* 0x04 */ struct STRUCT_DEMOWIN * handle;
|
||||
/* 0x08 */ struct STRUCT_MENU_ITEM * items;
|
||||
/* 0x0C */ long max_display_items;
|
||||
/* 0x10 */ unsigned long flags;
|
||||
/* 0x14 */ void (* cb_open)(struct STRUCT_MENU *, unsigned long);
|
||||
/* 0x18 */ void (* cb_move)(struct STRUCT_MENU *, unsigned long);
|
||||
/* 0x1C */ void (* cb_select)(struct STRUCT_MENU *, unsigned long);
|
||||
/* 0x20 */ void (* cb_cancel)(struct STRUCT_MENU *, unsigned long);
|
||||
/* 0x24 */ long num_display_items;
|
||||
/* 0x28 */ long num_items;
|
||||
/* 0x2C */ unsigned long max_str_len;
|
||||
/* 0x30 */ long curr_pos;
|
||||
/* 0x34 */ long display_pos;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
/* 0x00 */ struct PADStatus pads[4];
|
||||
/* 0x30 */ unsigned long button[4];
|
||||
/* 0x40 */ unsigned long old_button[4];
|
||||
/* 0x50 */ unsigned long changed_button[4];
|
||||
/* 0x60 */ unsigned long repeat_button[4];
|
||||
/* 0x70 */ unsigned long repeat_ctr[4];
|
||||
} DEMOWinPadInfo;
|
||||
|
||||
struct STRUCT_LISTBOX_ITEM {
|
||||
/* 0x00 */ char * name; // offset 0x0, size 0x4
|
||||
/* 0x04 */ unsigned long flags; // offset 0x4, size 0x4
|
||||
};
|
||||
|
||||
struct STRUCT_LISTBOX {
|
||||
/* 0x00 */ char * title; // offset 0x0, size 0x4
|
||||
/* 0x04 */ struct STRUCT_DEMOWIN * handle; // offset 0x4, size 0x4
|
||||
/* 0x08 */ struct STRUCT_LISTBOX_ITEM * items; // offset 0x8, size 0x4
|
||||
/* 0x0C */ long max_display_items; // offset 0xC, size 0x4
|
||||
/* 0x10 */ unsigned long flags; // offset 0x10, size 0x4
|
||||
/* 0x14 */ long num_display_items; // offset 0x14, size 0x4
|
||||
/* 0x18 */ long num_items; // offset 0x18, size 0x4
|
||||
/* 0x1C */ unsigned long max_str_len; // offset 0x1C, size 0x4
|
||||
/* 0x20 */ long curr_pos; // offset 0x20, size 0x4
|
||||
/* 0x24 */ long display_pos; // offset 0x24, size 0x4
|
||||
/* 0x28 */ int cursor_state; // offset 0x28, size 0x4
|
||||
};
|
||||
|
||||
extern unsigned long DEMOFontBitmap[768];
|
||||
|
||||
#include <dolphin/demo/DEMOInit.h>
|
||||
#include <dolphin/demo/DEMOPad.h>
|
||||
#include <dolphin/demo/DEMOPuts.h>
|
||||
#include <dolphin/demo/DEMOStats.h>
|
||||
#include <dolphin/demo/DEMOWin.h>
|
||||
|
||||
// unsorted externs
|
||||
extern void DEMOPrintf(s16 x, s16 y, s16 priority, char *str, ...);
|
||||
|
||||
extern struct _GXRenderModeObj *DEMOGetRenderModeObj();
|
||||
|
||||
#endif
|
||||
21
include/dolphin/demo/DEMOInit.h
Normal file
21
include/dolphin/demo/DEMOInit.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef _DOLPHIN_DEMOINIT
|
||||
#define _DOLPHIN_DEMOINIT
|
||||
|
||||
#include <dolphin/gx.h>
|
||||
|
||||
extern void *DemoFrameBuffer1;
|
||||
extern void *DemoFrameBuffer2;
|
||||
extern void *DemoCurrentBuffer;
|
||||
|
||||
void DEMOInit(struct _GXRenderModeObj *mode);
|
||||
void DEMOBeforeRender();
|
||||
void DEMODoneRender();
|
||||
void DEMOSwapBuffers();
|
||||
void DEMOSetTevColorIn(enum _GXTevStageID stage, enum _GXTevColorArg a, enum _GXTevColorArg b, enum _GXTevColorArg c, enum _GXTevColorArg d);
|
||||
void DEMOSetTevOp(enum _GXTevStageID id, enum _GXTevMode mode);
|
||||
struct _GXRenderModeObj *DEMOGetRenderModeObj();
|
||||
u32 DEMOGetCurrentBuffer(void);
|
||||
void DEMOEnableBypassWorkaround(unsigned long timeoutFrames);
|
||||
void DEMOReInit(struct _GXRenderModeObj *mode);
|
||||
|
||||
#endif
|
||||
26
include/dolphin/demo/DEMOPad.h
Normal file
26
include/dolphin/demo/DEMOPad.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef _DOLPHIN_DEMOPAD
|
||||
#define _DOLPHIN_DEMOPAD
|
||||
|
||||
#include <dolphin/pad.h>
|
||||
|
||||
typedef struct {
|
||||
/* 0x00 */ struct PADStatus pst;
|
||||
/* 0x0C */ u16 buttonDown;
|
||||
/* 0x0E */ u16 buttonUp;
|
||||
/* 0x10 */ u16 dirs;
|
||||
/* 0x12 */ u16 dirsNew;
|
||||
/* 0x14 */ u16 dirsReleased;
|
||||
/* 0x16 */ s16 stickDeltaX;
|
||||
/* 0x18 */ s16 stickDeltaY;
|
||||
/* 0x1A */ s16 substickDeltaX;
|
||||
/* 0x1C */ s16 substickDeltaY;
|
||||
} DEMODMPad;
|
||||
|
||||
extern DEMODMPad DemoPad[4];
|
||||
|
||||
extern u32 DemoNumValidPads;
|
||||
|
||||
void DEMOPadRead();
|
||||
void DEMOPadInit();
|
||||
|
||||
#endif
|
||||
27
include/dolphin/demo/DEMOPuts.h
Normal file
27
include/dolphin/demo/DEMOPuts.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef _DOLPHIN_DEMOPUTS
|
||||
#define _DOLPHIN_DEMOPUTS
|
||||
|
||||
#include <dolphin/gx.h>
|
||||
|
||||
typedef enum {
|
||||
DMTF_POINTSAMPLE,
|
||||
DMTF_BILERP,
|
||||
} DMTexFlt;
|
||||
|
||||
typedef enum { DM_FT_OPQ, DM_FT_RVS, DM_FT_XLU } DMFontType;
|
||||
|
||||
void DEMOSetFontType(DMFontType attr);
|
||||
void DEMOLoadFont(enum _GXTexMapID texMap, enum _GXTexMtx texMtx, DMTexFlt texFlt);
|
||||
void DEMOSetupScrnSpc(long width, long height, float depth);
|
||||
void DEMOInitCaption(long font_type, long width, long height);
|
||||
void DEMOPuts(s16 x, s16 y, s16 z, char *string);
|
||||
void DEMOPrintf(s16 x, s16 y, s16 z, char *fmt, ...);
|
||||
struct OSFontHeader *DEMOInitROMFont();
|
||||
void DEMOSetROMFontSize(s16 size, s16 space);
|
||||
int DEMORFPuts(s16 x, s16 y, s16 z, char *string);
|
||||
int DEMORFPutsEx(s16 x, s16 y, s16 z, char *string, s16 maxWidth, int length);
|
||||
int DEMORFPrintf(s16 x, s16 y, s16 z, char *fmt, ...);
|
||||
char *DEMODumpROMFont(char *string);
|
||||
int DEMOGetRFTextWidth(char *string);
|
||||
|
||||
#endif
|
||||
38
include/dolphin/demo/DEMOStats.h
Normal file
38
include/dolphin/demo/DEMOStats.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
#ifndef _DOLPHIN_DEMOSTATS
|
||||
#define _DOLPHIN_DEMOSTATS
|
||||
|
||||
typedef enum DEMO_STAT_TYPE {
|
||||
DEMO_STAT_GP0 = 0,
|
||||
DEMO_STAT_GP1 = 1,
|
||||
DEMO_STAT_MEM = 2,
|
||||
DEMO_STAT_PIX = 3,
|
||||
DEMO_STAT_VC = 4,
|
||||
DEMO_STAT_FR = 5,
|
||||
DEMO_STAT_TBW = 6,
|
||||
DEMO_STAT_TBP = 7,
|
||||
DEMO_STAT_MYC = 8,
|
||||
DEMO_STAT_MYR = 9,
|
||||
} DEMO_STAT_TYPE;
|
||||
|
||||
typedef struct DemoStatData {
|
||||
char text[50];
|
||||
DEMO_STAT_TYPE stat_type;
|
||||
unsigned long stat;
|
||||
unsigned long count;
|
||||
} DemoStatData;
|
||||
|
||||
typedef enum {
|
||||
DEMO_STAT_TL = 0,
|
||||
DEMO_STAT_BL = 1,
|
||||
DEMO_STAT_TLD = 2,
|
||||
DEMO_STAT_BLD = 3,
|
||||
DEMO_STAT_IO = 4,
|
||||
} DEMO_STAT_DISP;
|
||||
|
||||
extern unsigned char DemoStatEnable;
|
||||
|
||||
void DEMOSetStats(DemoStatData * stat, unsigned long nstats, DEMO_STAT_DISP disp);
|
||||
void DEMOUpdateStats(unsigned char inc);
|
||||
void DEMOPrintStats(void);
|
||||
|
||||
#endif
|
||||
77
include/dolphin/demo/DEMOWin.h
Normal file
77
include/dolphin/demo/DEMOWin.h
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
#ifndef _DOLPHIN_DEMOWIN
|
||||
#define _DOLPHIN_DEMOWIN
|
||||
|
||||
#include <dolphin/demo.h>
|
||||
#include <dolphin/gx.h>
|
||||
|
||||
enum DEMOWinItem {
|
||||
DEMOWIN_ITEM_CAP,
|
||||
DEMOWIN_ITEM_BKGND,
|
||||
DEMOWIN_ITEM_BORDER,
|
||||
DEMOWIN_ITEM_DEFAULT
|
||||
};
|
||||
|
||||
// flags
|
||||
#define DEMOWIN_FLAGS_INIT (1 << 0)
|
||||
#define DEMOWIN_FLAGS_OPENED (1 << 1)
|
||||
|
||||
struct STRUCT_DEMOWIN {
|
||||
/* 0x00 */ long x1;
|
||||
/* 0x04 */ long y1;
|
||||
/* 0x08 */ long x2;
|
||||
/* 0x0C */ long y2;
|
||||
/* 0x10 */ unsigned long priority;
|
||||
/* 0x14 */ unsigned long flags;
|
||||
/* 0x18 */ unsigned short x_cal;
|
||||
/* 0x1A */ unsigned short y_cal;
|
||||
/* 0x1C */ unsigned short pixel_width;
|
||||
/* 0x1E */ unsigned short pixel_height;
|
||||
/* 0x20 */ unsigned short char_width;
|
||||
/* 0x22 */ unsigned short char_height;
|
||||
/* 0x24 */ unsigned short num_scroll_lines;
|
||||
/* 0x26 */ unsigned short total_lines;
|
||||
/* 0x28 */ unsigned short curr_output_line;
|
||||
/* 0x2A */ unsigned short curr_output_col;
|
||||
/* 0x2C */ unsigned short curr_view_line;
|
||||
/* 0x2E */ signed short cursor_line;
|
||||
/* 0x30 */ char * caption;
|
||||
/* 0x34 */ unsigned char * buffer;
|
||||
/* 0x38 */ GXColor bkgnd;
|
||||
/* 0x3C */ GXColor cap;
|
||||
/* 0x40 */ GXColor border;
|
||||
/* 0x44 */ void (* refresh)(struct STRUCT_DEMOWIN *);
|
||||
/* 0x48 */ struct STRUCT_DEMOWIN * next;
|
||||
/* 0x4C */ struct STRUCT_DEMOWIN * prev;
|
||||
/* 0x50 */ void * parent;
|
||||
};
|
||||
|
||||
// functions
|
||||
void DEMOWinInit();
|
||||
struct STRUCT_DEMOWIN * DEMOWinCreateWindow(s32 x1, s32 y1, s32 x2, s32 y2, char * caption, u16 scroll, void * func);
|
||||
void DEMOWinDestroyWindow(struct STRUCT_DEMOWIN * handle);
|
||||
void DEMOWinOpenWindow(struct STRUCT_DEMOWIN * handle);
|
||||
void DEMOWinCloseWindow(struct STRUCT_DEMOWIN * handle);
|
||||
void DEMOWinSetWindowColor(struct STRUCT_DEMOWIN * handle, enum DEMOWinItem item, u8 r, u8 g, u8 b, u8 a);
|
||||
void DEMOWinLogPrintf(struct STRUCT_DEMOWIN * handle, char * fmt, ...);
|
||||
void DEMOWinPrintfXY(struct STRUCT_DEMOWIN * handle, u16 col, u16 row, char * fmt, ...);
|
||||
void DEMOWinScrollWindow(struct STRUCT_DEMOWIN * handle, u32 dir);
|
||||
void DEMOWinBringToFront(struct STRUCT_DEMOWIN * handle);
|
||||
void DEMOWinSendToBack(struct STRUCT_DEMOWIN * handle);
|
||||
void DEMOWinClearRow(struct STRUCT_DEMOWIN * handle, u16 row);
|
||||
void DEMOWinClearWindow(struct STRUCT_DEMOWIN * handle);
|
||||
void DEMOWinClearBuffer(struct STRUCT_DEMOWIN * handle);
|
||||
void DEMOWinRefresh();
|
||||
struct STRUCT_MENU * DEMOWinCreateMenuWindow(struct STRUCT_MENU * menu, u16 x, u16 y);
|
||||
void DEMOWinDestroyMenuWindow(struct STRUCT_MENU * menu);
|
||||
u32 DEMOWinMenuChild(struct STRUCT_MENU * menu, int child_flag);
|
||||
void DEMOWinPadInit(DEMOWinPadInfo *p);
|
||||
void DEMOWinPadRead(DEMOWinPadInfo *p);
|
||||
void DEMOWinSetRepeat(unsigned long threshold, unsigned long rate);
|
||||
void DEMOWinResetRepeat();
|
||||
struct STRUCT_LISTBOX * DEMOWinCreateListWindow(struct STRUCT_LISTBOX * list, unsigned short x, unsigned short y);
|
||||
void DEMOWinDestroyListWindow(struct STRUCT_LISTBOX * list);
|
||||
void DEMOWinListSetCursor(struct STRUCT_LISTBOX * list, int x);
|
||||
long DEMOWinListScrollList(struct STRUCT_LISTBOX * list, unsigned long dir);
|
||||
long DEMOWinListMoveCursor(struct STRUCT_LISTBOX * list, unsigned long dir);
|
||||
|
||||
#endif
|
||||
11
include/dolphin/demoPriv.h
Normal file
11
include/dolphin/demoPriv.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef _DOLPHIN_DEMOPRIV
|
||||
#define _DOLPHIN_DEMOPRIV
|
||||
|
||||
#include <dolphin/demo.h>
|
||||
|
||||
extern struct STRUCT_DEMOWIN * __first_node;
|
||||
extern struct STRUCT_DEMOWIN * __last_node;
|
||||
extern struct STRUCT_DEMOWIN * __curr_node;
|
||||
extern struct _GXRenderModeObj * __rmp;
|
||||
|
||||
#endif
|
||||
|
|
@ -59,6 +59,7 @@ DSPTaskInfo* DSPAddTask(DSPTaskInfo* task);
|
|||
|
||||
void __DSP_exec_task(DSPTaskInfo* curr, DSPTaskInfo* next);
|
||||
void __DSP_boot_task(DSPTaskInfo* task);
|
||||
void __DSP_insert_task(DSPTaskInfo* task);
|
||||
void __DSP_remove_task(DSPTaskInfo* task);
|
||||
void __DSP_add_task(DSPTaskInfo* task);
|
||||
void __DSP_debug_printf(const char* fmt, ...);
|
||||
|
|
|
|||
27
include/dolphin/exi.h
Normal file
27
include/dolphin/exi.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef _DOLPHIN_EXI
|
||||
#define _DOLPHIN_EXI
|
||||
|
||||
#include <dolphin/os/OSContext.h>
|
||||
|
||||
typedef void (*EXICallback)(s32 chan, OSContext *context);
|
||||
|
||||
EXICallback EXISetExiCallback(s32 channel, EXICallback callback);
|
||||
|
||||
void EXIInit(void);
|
||||
BOOL EXILock(s32 channel, u32 device, EXICallback callback);
|
||||
BOOL EXIUnlock(s32 channel);
|
||||
BOOL EXISelect(s32 channel, u32 device, u32 frequency);
|
||||
BOOL EXIDeselect(s32 channel);
|
||||
BOOL EXIImm(s32 channel, void *buffer, s32 length, u32 type, EXICallback callback);
|
||||
BOOL EXIImmEx(s32 channel, void *buffer, s32 length, u32 type);
|
||||
BOOL EXIDma(s32 channel, void *buffer, s32 length, u32 type, EXICallback callback);
|
||||
BOOL EXISync(s32 channel);
|
||||
BOOL EXIProbe(s32 channel);
|
||||
s32 EXIProbeEx(s32 channel);
|
||||
BOOL EXIAttach(s32 channel, EXICallback callback);
|
||||
BOOL EXIDetach(s32 channel);
|
||||
u32 EXIGetState(s32 channel);
|
||||
s32 EXIGetID(s32 channel, u32 device, u32 *id);
|
||||
void EXIProbeReset(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -39,6 +39,7 @@ struct OSResetFunctionInfo {
|
|||
OSResetFunctionInfo* prev;
|
||||
};
|
||||
|
||||
void OSRegisterResetFunction(OSResetFunctionInfo *info);
|
||||
u32 OSGetResetCode(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
615
src/dolphin/card/CARDBios.c
Normal file
615
src/dolphin/card/CARDBios.c
Normal file
|
|
@ -0,0 +1,615 @@
|
|||
#include <dolphin/card.h>
|
||||
#include <dolphin/dsp.h>
|
||||
#include <dolphin/dvd.h>
|
||||
#include <dolphin/exi.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#include <dolphin/CARDPriv.h>
|
||||
|
||||
CARDControl __CARDBlock[2];
|
||||
DVDDiskID __CARDDiskNone;
|
||||
|
||||
static u16 __CARDEncode;
|
||||
|
||||
s32 __CARDReadStatus(s32 chan, u8 *status);
|
||||
s32 __CARDClearStatus(s32 chan);
|
||||
void __CARDSetDiskID(const DVDDiskID *id);
|
||||
static s32 Retry(s32 chan);
|
||||
|
||||
static BOOL OnReset(BOOL f);
|
||||
static OSResetFunctionInfo ResetFunctionInfo = { OnReset, 127 };
|
||||
|
||||
void __CARDDefaultApiCallback(s32 chan, s32 result) { }
|
||||
|
||||
void __CARDSyncCallback(s32 chan, s32 result)
|
||||
{
|
||||
OSWakeupThread(&__CARDBlock[chan].threadQueue);
|
||||
}
|
||||
|
||||
void __CARDExtHandler(s32 chan, OSContext *context)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __CARDExiHandler(s32 chan, OSContext *context)
|
||||
{
|
||||
CARDControl *card;
|
||||
CARDCallback callback;
|
||||
u8 status;
|
||||
s32 result;
|
||||
|
||||
card = &__CARDBlock[chan];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
error:
|
||||
EXIUnlock(chan);
|
||||
|
||||
fatal:
|
||||
callback = card->exiCallback;
|
||||
if (callback) {
|
||||
card->exiCallback = 0;
|
||||
callback(chan, result);
|
||||
}
|
||||
}
|
||||
|
||||
void __CARDTxHandler(s32 chan, OSContext *context)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void __CARDUnlockedHandler(s32 chan, OSContext *context)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
s32 CARDGetSectorSize(s32 chan, u32 *size)
|
||||
{
|
||||
struct CARDControl *card;
|
||||
long result;
|
||||
|
||||
result = __CARDGetControlBlock(chan, &card);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
*size = card->sectorSize;
|
||||
return __CARDPutControlBlock(card, 0);
|
||||
}
|
||||
|
||||
s32 __CARDSync(s32 chan)
|
||||
{
|
||||
CARDControl *block;
|
||||
s32 result;
|
||||
s32 enabled;
|
||||
|
||||
block = &__CARDBlock[chan];
|
||||
enabled = OSDisableInterrupts();
|
||||
while ((result = CARDGetResultCode(chan)) == -1) {
|
||||
OSSleepThread(&block->threadQueue);
|
||||
}
|
||||
OSRestoreInterrupts(enabled);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOL OnReset(BOOL f)
|
||||
{
|
||||
if (!f) {
|
||||
if (CARDUnmount(0) == CARD_RESULT_BUSY || CARDUnmount(1) == CARD_RESULT_BUSY) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
170
src/dolphin/card/CARDBlock.c
Normal file
170
src/dolphin/card/CARDBlock.c
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
#include <dolphin/card.h>
|
||||
#include <dolphin/dsp.h>
|
||||
#include <dolphin/dvd.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#include "string.h"
|
||||
|
||||
#include <dolphin/CARDPriv.h>
|
||||
|
||||
u16 *__CARDGetFatBlock(CARDControl *card)
|
||||
{
|
||||
return card->currentFat;
|
||||
}
|
||||
|
||||
static void WriteCallback(s32 chan, s32 result)
|
||||
{
|
||||
CARDControl *card;
|
||||
CARDCallback callback;
|
||||
u16 *fat;
|
||||
u16 *fatBack;
|
||||
|
||||
card = &__CARDBlock[chan];
|
||||
|
||||
if (result >= 0) {
|
||||
fat = (u16 *)((u8 *)card->workArea + 0x6000);
|
||||
fatBack = (u16 *)((u8 *)card->workArea + 0x8000);
|
||||
|
||||
if (card->currentFat == fat) {
|
||||
card->currentFat = fatBack;
|
||||
memcpy(fatBack, fat, 0x2000);
|
||||
}
|
||||
else {
|
||||
card->currentFat = fat;
|
||||
memcpy(fat, fatBack, 0x2000);
|
||||
}
|
||||
}
|
||||
|
||||
if (card->apiCallback == NULL) {
|
||||
__CARDPutControlBlock(card, result);
|
||||
}
|
||||
|
||||
callback = card->eraseCallback;
|
||||
if (callback) {
|
||||
card->eraseCallback = NULL;
|
||||
callback(chan, result);
|
||||
}
|
||||
}
|
||||
|
||||
static void EraseCallback(s32 chan, s32 result)
|
||||
{
|
||||
CARDControl *card;
|
||||
CARDCallback callback;
|
||||
u32 temp[2]; /* this compiler sucks */
|
||||
u16 *fat;
|
||||
u32 addr;
|
||||
|
||||
card = &__CARDBlock[chan];
|
||||
if (result < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
fat = __CARDGetFatBlock(card);
|
||||
addr = ((u32)fat - (u32)card->workArea) / CARD_SYSTEM_BLOCK_SIZE * card->sectorSize;
|
||||
result = __CARDWrite(chan, addr, CARD_SYSTEM_BLOCK_SIZE, fat, WriteCallback);
|
||||
if (result < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
if (card->apiCallback == NULL) {
|
||||
__CARDPutControlBlock(card, result);
|
||||
}
|
||||
callback = card->eraseCallback;
|
||||
if (callback) {
|
||||
card->eraseCallback = NULL;
|
||||
callback(chan, result);
|
||||
}
|
||||
}
|
||||
|
||||
s32 __CARDAllocBlock(s32 chan, u32 cBlock, CARDCallback callback)
|
||||
{
|
||||
CARDControl *card;
|
||||
u16 *fat;
|
||||
u16 iBlock;
|
||||
u16 startBlock;
|
||||
u16 prevBlock;
|
||||
u16 count;
|
||||
|
||||
card = &__CARDBlock[chan];
|
||||
if (!card->attached) {
|
||||
return CARD_RESULT_NOCARD;
|
||||
}
|
||||
|
||||
fat = __CARDGetFatBlock(card);
|
||||
if (fat[3] < cBlock) {
|
||||
return CARD_RESULT_INSSPACE;
|
||||
}
|
||||
|
||||
fat[3] -= cBlock;
|
||||
startBlock = 0xFFFF;
|
||||
iBlock = fat[4];
|
||||
count = 0;
|
||||
while (0 < cBlock) {
|
||||
if (card->cBlock - 5 < ++count) {
|
||||
return CARD_RESULT_BROKEN;
|
||||
}
|
||||
|
||||
iBlock++;
|
||||
if (!CARDIsValidBlockNo(card, iBlock)) {
|
||||
iBlock = 5;
|
||||
}
|
||||
|
||||
if (fat[iBlock] == 0x0000u) {
|
||||
if (startBlock == 0xFFFF) {
|
||||
startBlock = iBlock;
|
||||
}
|
||||
else {
|
||||
fat[prevBlock] = iBlock;
|
||||
}
|
||||
prevBlock = iBlock;
|
||||
fat[iBlock] = 0xFFFF;
|
||||
--cBlock;
|
||||
}
|
||||
}
|
||||
fat[4] = iBlock;
|
||||
card->startBlock = startBlock;
|
||||
|
||||
return __CARDUpdateFatBlock(chan, fat, callback);
|
||||
}
|
||||
|
||||
s32 __CARDFreeBlock(s32 chan, u16 nBlock, CARDCallback callback)
|
||||
{
|
||||
CARDControl *card;
|
||||
u16 *fat;
|
||||
u16 nextBlock;
|
||||
|
||||
card = card = &__CARDBlock[chan];
|
||||
if (!card->attached) {
|
||||
return CARD_RESULT_NOCARD;
|
||||
}
|
||||
|
||||
fat = __CARDGetFatBlock(card);
|
||||
while (nBlock != 0xFFFF) {
|
||||
if (!CARDIsValidBlockNo(card, nBlock)) {
|
||||
return CARD_RESULT_BROKEN;
|
||||
}
|
||||
|
||||
nextBlock = fat[nBlock];
|
||||
fat[nBlock] = 0;
|
||||
nBlock = nextBlock;
|
||||
++fat[3];
|
||||
}
|
||||
|
||||
return __CARDUpdateFatBlock(chan, fat, callback);
|
||||
}
|
||||
|
||||
s32 __CARDUpdateFatBlock(s32 chan, u16 *fat, CARDCallback callback)
|
||||
{
|
||||
CARDControl *card;
|
||||
|
||||
card = &__CARDBlock[chan];
|
||||
++fat[2];
|
||||
__CARDCheckSum(fat + 2, 0x1FFC, fat, fat + 1);
|
||||
DCStoreRange(fat, 0x2000);
|
||||
card->eraseCallback = callback;
|
||||
|
||||
return __CARDEraseSector(chan, (((u32)fat - (u32)card->workArea) / 8192u) * card->sectorSize, EraseCallback);
|
||||
}
|
||||
343
src/dolphin/card/CARDCheck.c
Normal file
343
src/dolphin/card/CARDCheck.c
Normal file
|
|
@ -0,0 +1,343 @@
|
|||
#include <dolphin/card.h>
|
||||
#include <dolphin/dsp.h>
|
||||
#include <dolphin/dvd.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#include <dolphin/CARDPriv.h>
|
||||
#include <dolphin/OSRtcPriv.h>
|
||||
|
||||
#include "string.h"
|
||||
|
||||
void __CARDCheckSum(void *ptr, int length, u16 *checksum, u16 *checksumInv)
|
||||
{
|
||||
u16 *p;
|
||||
int i;
|
||||
|
||||
length /= sizeof(u16);
|
||||
*checksum = *checksumInv = 0;
|
||||
for (i = 0, p = ptr; i < length; i++, p++) {
|
||||
*checksum += *p;
|
||||
*checksumInv += ~*p;
|
||||
}
|
||||
if (*checksum == 0xffff) {
|
||||
*checksum = 0;
|
||||
}
|
||||
if (*checksumInv == 0xffff) {
|
||||
*checksumInv = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static s32 VerifyID(CARDControl *card)
|
||||
{
|
||||
CARDID *id;
|
||||
u16 checksum;
|
||||
u16 checksumInv;
|
||||
OSSramEx *sramEx;
|
||||
OSTime rand;
|
||||
int i;
|
||||
|
||||
id = card->workArea;
|
||||
|
||||
if (id->deviceID != 0 || id->size != card->size)
|
||||
return CARD_RESULT_BROKEN;
|
||||
|
||||
__CARDCheckSum(id, sizeof(CARDID) - sizeof(u32), &checksum, &checksumInv);
|
||||
if (id->checkSum != checksum || id->checkSumInv != checksumInv)
|
||||
return CARD_RESULT_BROKEN;
|
||||
|
||||
if (id->encode != OSGetFontEncode())
|
||||
return CARD_RESULT_ENCODING;
|
||||
|
||||
rand = *(OSTime *)&id->serial[12];
|
||||
sramEx = __OSLockSramEx();
|
||||
for (i = 0; i < 12; i++) {
|
||||
rand = (rand * 1103515245 + 12345) >> 16;
|
||||
if (id->serial[i] != (u8)(sramEx->flashID[card - __CARDBlock][i] + rand)) {
|
||||
__OSUnlockSramEx(FALSE);
|
||||
return CARD_RESULT_BROKEN;
|
||||
}
|
||||
rand = ((rand * 1103515245 + 12345) >> 16) & 0x7FFF;
|
||||
}
|
||||
|
||||
__OSUnlockSramEx(FALSE);
|
||||
|
||||
return CARD_RESULT_READY;
|
||||
}
|
||||
|
||||
static s32 VerifyDir(CARDControl *card, int *outCurrent)
|
||||
{
|
||||
CARDDir *dir[2];
|
||||
CARDDirCheck *check[2];
|
||||
u16 checkSum;
|
||||
u16 checkSumInv;
|
||||
int i;
|
||||
int errors;
|
||||
int current;
|
||||
|
||||
current = errors = 0;
|
||||
for (i = 0; i < 2; i++) {
|
||||
dir[i] = (CARDDir *)((u8 *)card->workArea + (1 + i) * CARD_SYSTEM_BLOCK_SIZE);
|
||||
check[i] = __CARDGetDirCheck(dir[i]);
|
||||
__CARDCheckSum(dir[i], CARD_SYSTEM_BLOCK_SIZE - sizeof(u32), &checkSum, &checkSumInv);
|
||||
if (check[i]->checkSum != checkSum || check[i]->checkSumInv != checkSumInv) {
|
||||
++errors;
|
||||
current = i;
|
||||
card->currentDir = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 == errors) {
|
||||
if (card->currentDir == 0) {
|
||||
if ((check[0]->checkCode - check[1]->checkCode) < 0) {
|
||||
current = 0;
|
||||
}
|
||||
else {
|
||||
current = 1;
|
||||
}
|
||||
card->currentDir = dir[current];
|
||||
memcpy(dir[current], dir[current ^ 1], CARD_SYSTEM_BLOCK_SIZE);
|
||||
}
|
||||
else {
|
||||
current = (card->currentDir == dir[0]) ? 0 : 1;
|
||||
}
|
||||
}
|
||||
if (outCurrent) {
|
||||
*outCurrent = current;
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
static s32 VerifyFAT(CARDControl *card, int *outCurrent)
|
||||
{
|
||||
u16 *fat[2];
|
||||
u16 *fatp;
|
||||
u16 nBlock;
|
||||
u16 cFree;
|
||||
int i;
|
||||
u16 checkSum;
|
||||
u16 checkSumInv;
|
||||
int errors;
|
||||
int current;
|
||||
|
||||
current = errors = 0;
|
||||
for (i = 0; i < 2; i++) {
|
||||
fatp = fat[i] = (u16 *)((u8 *)card->workArea + (3 + i) * CARD_SYSTEM_BLOCK_SIZE);
|
||||
|
||||
__CARDCheckSum(&fatp[CARD_FAT_CHECKCODE], CARD_SYSTEM_BLOCK_SIZE - sizeof(u32), &checkSum, &checkSumInv);
|
||||
if (fatp[CARD_FAT_CHECKSUM] != checkSum || fatp[CARD_FAT_CHECKSUMINV] != checkSumInv) {
|
||||
++errors;
|
||||
current = i;
|
||||
card->currentFat = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
cFree = 0;
|
||||
for (nBlock = CARD_NUM_SYSTEM_BLOCK; nBlock < card->cBlock; nBlock++) {
|
||||
if (fatp[nBlock] == CARD_FAT_AVAIL) {
|
||||
cFree++;
|
||||
}
|
||||
}
|
||||
if (cFree != fatp[CARD_FAT_FREEBLOCKS]) {
|
||||
++errors;
|
||||
current = i;
|
||||
card->currentFat = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 == errors) {
|
||||
if (card->currentFat == 0) {
|
||||
if (((s16)fat[0][CARD_FAT_CHECKCODE] - (s16)fat[1][CARD_FAT_CHECKCODE]) < 0) {
|
||||
current = 0;
|
||||
}
|
||||
else {
|
||||
current = 1;
|
||||
}
|
||||
card->currentFat = fat[current];
|
||||
memcpy(fat[current], fat[current ^ 1], CARD_SYSTEM_BLOCK_SIZE);
|
||||
}
|
||||
else {
|
||||
current = (card->currentFat == fat[0]) ? 0 : 1;
|
||||
}
|
||||
}
|
||||
if (outCurrent) {
|
||||
*outCurrent = current;
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
s32 __CARDVerify(CARDControl *card)
|
||||
{
|
||||
s32 result;
|
||||
int errors;
|
||||
|
||||
result = VerifyID(card);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
errors = VerifyDir(card, NULL);
|
||||
errors += VerifyFAT(card, NULL);
|
||||
switch (errors) {
|
||||
case 0:
|
||||
return CARD_RESULT_READY;
|
||||
case 1:
|
||||
return CARD_RESULT_BROKEN;
|
||||
default:
|
||||
return CARD_RESULT_BROKEN;
|
||||
}
|
||||
}
|
||||
|
||||
s32 CARDCheckExAsync(s32 chan, s32 *xferBytes, CARDCallback callback)
|
||||
{
|
||||
CARDControl *card;
|
||||
CARDDir *dir[2];
|
||||
u16 *fat[2];
|
||||
u16 *map;
|
||||
s32 result;
|
||||
int errors;
|
||||
int currentFat;
|
||||
int currentDir;
|
||||
s32 fileNo;
|
||||
u16 iBlock;
|
||||
u16 cBlock;
|
||||
u16 cFree;
|
||||
BOOL updateFat = FALSE;
|
||||
BOOL updateDir = FALSE;
|
||||
BOOL updateOrphan = FALSE;
|
||||
|
||||
if (xferBytes) {
|
||||
*xferBytes = 0;
|
||||
}
|
||||
|
||||
result = __CARDGetControlBlock(chan, &card);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = VerifyID(card);
|
||||
if (result < 0) {
|
||||
return __CARDPutControlBlock(card, result);
|
||||
}
|
||||
|
||||
errors = VerifyDir(card, ¤tDir);
|
||||
errors += VerifyFAT(card, ¤tFat);
|
||||
if (1 < errors) {
|
||||
return __CARDPutControlBlock(card, CARD_RESULT_BROKEN);
|
||||
}
|
||||
|
||||
dir[0] = (CARDDir *)((u8 *)card->workArea + (1 + 0) * CARD_SYSTEM_BLOCK_SIZE);
|
||||
dir[1] = (CARDDir *)((u8 *)card->workArea + (1 + 1) * CARD_SYSTEM_BLOCK_SIZE);
|
||||
fat[0] = (u16 *)((u8 *)card->workArea + (3 + 0) * CARD_SYSTEM_BLOCK_SIZE);
|
||||
fat[1] = (u16 *)((u8 *)card->workArea + (3 + 1) * CARD_SYSTEM_BLOCK_SIZE);
|
||||
|
||||
switch (errors) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
if (!card->currentDir) {
|
||||
card->currentDir = dir[currentDir];
|
||||
memcpy(dir[currentDir], dir[currentDir ^ 1], CARD_SYSTEM_BLOCK_SIZE);
|
||||
updateDir = TRUE;
|
||||
}
|
||||
else {
|
||||
card->currentFat = fat[currentFat];
|
||||
memcpy(fat[currentFat], fat[currentFat ^ 1], CARD_SYSTEM_BLOCK_SIZE);
|
||||
updateFat = TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
map = fat[currentFat ^ 1];
|
||||
memset(map, 0, CARD_SYSTEM_BLOCK_SIZE);
|
||||
|
||||
for (fileNo = 0; fileNo < CARD_MAX_FILE; fileNo++) {
|
||||
CARDDir *ent;
|
||||
|
||||
ent = &card->currentDir[fileNo];
|
||||
if (ent->gameName[0] == 0xff) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (iBlock = ent->startBlock, cBlock = 0; iBlock != 0xFFFF && cBlock < ent->length; iBlock = card->currentFat[iBlock], ++cBlock) {
|
||||
if (!CARDIsValidBlockNo(card, iBlock) || 1 < ++map[iBlock]) {
|
||||
return __CARDPutControlBlock(card, CARD_RESULT_BROKEN);
|
||||
}
|
||||
}
|
||||
if (cBlock != ent->length || iBlock != 0xFFFF) {
|
||||
return __CARDPutControlBlock(card, CARD_RESULT_BROKEN);
|
||||
}
|
||||
}
|
||||
|
||||
cFree = 0;
|
||||
for (iBlock = CARD_NUM_SYSTEM_BLOCK; iBlock < card->cBlock; iBlock++) {
|
||||
u16 nextBlock;
|
||||
|
||||
nextBlock = card->currentFat[iBlock];
|
||||
if (map[iBlock] == 0) {
|
||||
if (nextBlock != CARD_FAT_AVAIL) {
|
||||
card->currentFat[iBlock] = CARD_FAT_AVAIL;
|
||||
updateOrphan = TRUE;
|
||||
}
|
||||
cFree++;
|
||||
}
|
||||
else if (!CARDIsValidBlockNo(card, nextBlock) && nextBlock != 0xFFFF) {
|
||||
return __CARDPutControlBlock(card, CARD_RESULT_BROKEN);
|
||||
}
|
||||
}
|
||||
if (cFree != card->currentFat[CARD_FAT_FREEBLOCKS]) {
|
||||
card->currentFat[CARD_FAT_FREEBLOCKS] = cFree;
|
||||
updateOrphan = TRUE;
|
||||
}
|
||||
if (updateOrphan) {
|
||||
__CARDCheckSum(&card->currentFat[CARD_FAT_CHECKCODE], CARD_SYSTEM_BLOCK_SIZE - sizeof(u32), &card->currentFat[CARD_FAT_CHECKSUM],
|
||||
&card->currentFat[CARD_FAT_CHECKSUMINV]);
|
||||
}
|
||||
|
||||
memcpy(fat[currentFat ^ 1], fat[currentFat], CARD_SYSTEM_BLOCK_SIZE);
|
||||
|
||||
if (updateDir) {
|
||||
if (xferBytes) {
|
||||
*xferBytes = CARD_SYSTEM_BLOCK_SIZE;
|
||||
}
|
||||
return __CARDUpdateDir(chan, callback);
|
||||
}
|
||||
|
||||
if (updateFat | updateOrphan) {
|
||||
if (xferBytes) {
|
||||
*xferBytes = CARD_SYSTEM_BLOCK_SIZE;
|
||||
}
|
||||
return __CARDUpdateFatBlock(chan, card->currentFat, callback);
|
||||
}
|
||||
|
||||
__CARDPutControlBlock(card, CARD_RESULT_READY);
|
||||
if (callback) {
|
||||
BOOL enabled = OSDisableInterrupts();
|
||||
callback(chan, CARD_RESULT_READY);
|
||||
OSRestoreInterrupts(enabled);
|
||||
}
|
||||
return CARD_RESULT_READY;
|
||||
}
|
||||
|
||||
s32 CARDCheckAsync(s32 chan, CARDCallback callback)
|
||||
{
|
||||
s32 xferBytes;
|
||||
|
||||
return CARDCheckExAsync(chan, &xferBytes, callback);
|
||||
}
|
||||
|
||||
s32 CARDCheck(s32 chan)
|
||||
{
|
||||
s32 xferBytes;
|
||||
|
||||
s32 result = CARDCheckExAsync(chan, &xferBytes, __CARDSyncCallback);
|
||||
if (result >= 0) {
|
||||
if (&xferBytes == NULL) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return __CARDSync(chan);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
126
src/dolphin/card/CARDCreate.c
Normal file
126
src/dolphin/card/CARDCreate.c
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
#include <dolphin/card.h>
|
||||
#include <dolphin/dsp.h>
|
||||
#include <dolphin/dvd.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#include <dolphin/CARDPriv.h>
|
||||
|
||||
static void CreateCallbackFat(s32 chan, s32 result)
|
||||
{
|
||||
CARDControl *card;
|
||||
CARDDir *dir;
|
||||
CARDDir *ent;
|
||||
CARDCallback callback;
|
||||
|
||||
card = &__CARDBlock[chan];
|
||||
callback = card->apiCallback;
|
||||
card->apiCallback = 0;
|
||||
if (result < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
dir = __CARDGetDirBlock(card);
|
||||
ent = &dir[card->freeNo];
|
||||
memcpy(ent->gameName, card->diskID->gameName, sizeof(ent->gameName));
|
||||
memcpy(ent->company, card->diskID->company, sizeof(ent->company));
|
||||
ent->permission = CARD_ATTR_PUBLIC;
|
||||
ent->copyTimes = 0;
|
||||
ent->startBlock = card->startBlock;
|
||||
|
||||
ent->bannerFormat = 0;
|
||||
ent->iconAddr = 0xffffffff;
|
||||
ent->iconFormat = 0;
|
||||
ent->iconSpeed = 0;
|
||||
ent->commentAddr = 0xffffffff;
|
||||
|
||||
CARDSetIconSpeed(ent, 0, CARD_STAT_SPEED_FAST);
|
||||
|
||||
card->fileInfo->offset = 0;
|
||||
card->fileInfo->iBlock = ent->startBlock;
|
||||
|
||||
ent->time = (u32)OSTicksToSeconds(OSGetTime());
|
||||
result = __CARDUpdateDir(chan, callback);
|
||||
if (result < 0) {
|
||||
goto error;
|
||||
}
|
||||
return;
|
||||
|
||||
error:
|
||||
__CARDPutControlBlock(card, result);
|
||||
if (callback) {
|
||||
callback(chan, result);
|
||||
}
|
||||
}
|
||||
|
||||
s32 CARDCreateAsync(s32 chan, const char *fileName, u32 size, CARDFileInfo *fileInfo, CARDCallback callback)
|
||||
{
|
||||
CARDControl *card;
|
||||
CARDDir *dir;
|
||||
CARDDir *ent;
|
||||
s32 result;
|
||||
u16 fileNo;
|
||||
u16 freeNo;
|
||||
u16 *fat;
|
||||
|
||||
if (strlen(fileName) > (u32)CARD_FILENAME_MAX) {
|
||||
return CARD_RESULT_NAMETOOLONG;
|
||||
}
|
||||
|
||||
result = __CARDGetControlBlock(chan, &card);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (size <= 0 || (size % card->sectorSize) != 0) {
|
||||
return CARD_RESULT_FATAL_ERROR;
|
||||
}
|
||||
|
||||
freeNo = (u16)-1;
|
||||
dir = __CARDGetDirBlock(card);
|
||||
for (fileNo = 0; fileNo < CARD_MAX_FILE; fileNo++) {
|
||||
ent = &dir[fileNo];
|
||||
if (ent->gameName[0] == 0xff) {
|
||||
if (freeNo == (u16)-1) {
|
||||
freeNo = fileNo;
|
||||
}
|
||||
}
|
||||
else if (memcmp(ent->gameName, card->diskID->gameName, sizeof(ent->gameName)) == 0
|
||||
&& memcmp(ent->company, card->diskID->company, sizeof(ent->company)) == 0 && __CARDCompareFileName(ent, fileName)) {
|
||||
return __CARDPutControlBlock(card, CARD_RESULT_EXIST);
|
||||
}
|
||||
}
|
||||
if (freeNo == (u16)-1) {
|
||||
return __CARDPutControlBlock(card, CARD_RESULT_NOENT);
|
||||
}
|
||||
|
||||
fat = __CARDGetFatBlock(card);
|
||||
if (card->sectorSize * fat[CARD_FAT_FREEBLOCKS] < size) {
|
||||
return __CARDPutControlBlock(card, CARD_RESULT_INSSPACE);
|
||||
}
|
||||
|
||||
card->apiCallback = callback ? callback : __CARDDefaultApiCallback;
|
||||
card->freeNo = freeNo;
|
||||
ent = &dir[freeNo];
|
||||
ent->length = (u16)(size / card->sectorSize);
|
||||
strcat(ent->fileName, fileName, CARD_FILENAME_MAX);
|
||||
|
||||
card->fileInfo = fileInfo;
|
||||
fileInfo->chan = chan;
|
||||
fileInfo->fileNo = freeNo;
|
||||
|
||||
result = __CARDAllocBlock(chan, size / card->sectorSize, CreateCallbackFat);
|
||||
if (result < 0) {
|
||||
return __CARDPutControlBlock(card, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 CARDCreate(s32 chan, const char *fileName, u32 size, CARDFileInfo *fileInfo)
|
||||
{
|
||||
s32 result = CARDCreateAsync(chan, fileName, size, fileInfo, __CARDSyncCallback);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return __CARDSync(chan);
|
||||
}
|
||||
111
src/dolphin/card/CARDDelete.c
Normal file
111
src/dolphin/card/CARDDelete.c
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
#include <dolphin/card.h>
|
||||
#include <dolphin/dsp.h>
|
||||
#include <dolphin/dvd.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#include "string.h"
|
||||
|
||||
#include <dolphin/CARDPriv.h>
|
||||
|
||||
static void DeleteCallback(s32 chan, s32 result)
|
||||
{
|
||||
CARDControl *card;
|
||||
CARDCallback callback;
|
||||
|
||||
card = &__CARDBlock[chan];
|
||||
callback = card->apiCallback;
|
||||
card->apiCallback = 0;
|
||||
|
||||
if (result < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
result = __CARDFreeBlock(chan, card->startBlock, callback);
|
||||
if (result < 0) {
|
||||
goto error;
|
||||
}
|
||||
return;
|
||||
|
||||
error:
|
||||
__CARDPutControlBlock(card, result);
|
||||
if (callback) {
|
||||
callback(chan, result);
|
||||
}
|
||||
}
|
||||
|
||||
s32 CARDFastDeleteAsync(s32 chan, s32 fileNo, CARDCallback callback)
|
||||
{
|
||||
CARDControl *card;
|
||||
CARDDir *dir;
|
||||
CARDDir *ent;
|
||||
s32 result;
|
||||
|
||||
if (fileNo < 0 || CARD_MAX_FILE <= fileNo) {
|
||||
return CARD_RESULT_FATAL_ERROR;
|
||||
}
|
||||
result = __CARDGetControlBlock(chan, &card);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
dir = __CARDGetDirBlock(card);
|
||||
ent = &dir[fileNo];
|
||||
result = __CARDAccess(card, ent);
|
||||
if (result < 0) {
|
||||
return __CARDPutControlBlock(card, result);
|
||||
}
|
||||
if (__CARDIsOpened(card, fileNo)) {
|
||||
return __CARDPutControlBlock(card, CARD_RESULT_BUSY);
|
||||
}
|
||||
card->startBlock = ent->startBlock;
|
||||
memset(ent, 0xff, sizeof(CARDDir));
|
||||
|
||||
card->apiCallback = callback ? callback : __CARDDefaultApiCallback;
|
||||
result = __CARDUpdateDir(chan, DeleteCallback);
|
||||
if (result < 0) {
|
||||
__CARDPutControlBlock(card, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 CARDDeleteAsync(s32 chan, const char *fileName, CARDCallback callback)
|
||||
{
|
||||
CARDControl *card;
|
||||
s32 fileNo;
|
||||
s32 result;
|
||||
CARDDir *dir;
|
||||
CARDDir *ent;
|
||||
|
||||
result = __CARDGetControlBlock(chan, &card);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
result = __CARDGetFileNo(card, fileName, &fileNo);
|
||||
if (result < 0) {
|
||||
return __CARDPutControlBlock(card, result);
|
||||
}
|
||||
if (__CARDIsOpened(card, fileNo)) {
|
||||
return __CARDPutControlBlock(card, CARD_RESULT_BUSY);
|
||||
}
|
||||
|
||||
dir = __CARDGetDirBlock(card);
|
||||
ent = &dir[fileNo];
|
||||
card->startBlock = ent->startBlock;
|
||||
memset(ent, 0xff, sizeof(CARDDir));
|
||||
|
||||
card->apiCallback = callback ? callback : __CARDDefaultApiCallback;
|
||||
result = __CARDUpdateDir(chan, DeleteCallback);
|
||||
if (result < 0) {
|
||||
__CARDPutControlBlock(card, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 CARDDelete(s32 chan, const char *fileName)
|
||||
{
|
||||
s32 result = CARDDeleteAsync(chan, fileName, __CARDSyncCallback);
|
||||
|
||||
if (result < 0)
|
||||
return result;
|
||||
return __CARDSync(chan);
|
||||
}
|
||||
101
src/dolphin/card/CARDDir.c
Normal file
101
src/dolphin/card/CARDDir.c
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
#include <dolphin/card.h>
|
||||
#include <dolphin/dsp.h>
|
||||
#include <dolphin/dvd.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#include "string.h"
|
||||
|
||||
#include <dolphin/CARDPriv.h>
|
||||
|
||||
CARDDir *__CARDGetDirBlock(CARDControl *card)
|
||||
{
|
||||
return card->currentDir;
|
||||
}
|
||||
|
||||
static void WriteCallback(s32 chan, s32 result)
|
||||
{
|
||||
CARDControl *card;
|
||||
CARDCallback callback;
|
||||
|
||||
card = &__CARDBlock[chan];
|
||||
if (0 <= result) {
|
||||
CARDDir *dir0 = (CARDDir *)((u8 *)card->workArea + 0x2000);
|
||||
CARDDir *dir1 = (CARDDir *)((u8 *)card->workArea + 0x4000);
|
||||
|
||||
if (card->currentDir == dir0) {
|
||||
card->currentDir = dir1;
|
||||
memcpy(dir1, dir0, 0x2000);
|
||||
}
|
||||
else {
|
||||
card->currentDir = dir0;
|
||||
memcpy(dir0, dir1, 0x2000);
|
||||
}
|
||||
}
|
||||
|
||||
error:
|
||||
if (card->apiCallback == 0) {
|
||||
__CARDPutControlBlock(card, result);
|
||||
}
|
||||
callback = card->eraseCallback;
|
||||
if (callback) {
|
||||
card->eraseCallback = 0;
|
||||
callback(chan, result);
|
||||
}
|
||||
}
|
||||
|
||||
static void EraseCallback(s32 chan, s32 result)
|
||||
{
|
||||
CARDControl *card;
|
||||
CARDCallback callback;
|
||||
CARDDir *dir;
|
||||
u32 tmp[2];
|
||||
u32 addr;
|
||||
|
||||
card = &__CARDBlock[chan];
|
||||
if (result < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
dir = __CARDGetDirBlock(card);
|
||||
addr = ((u32)dir - (u32)card->workArea) / 0x2000 * card->sectorSize;
|
||||
result = __CARDWrite(chan, addr, 0x2000, dir, WriteCallback);
|
||||
if (result < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
if (card->apiCallback == 0) {
|
||||
__CARDPutControlBlock(card, result);
|
||||
}
|
||||
callback = card->eraseCallback;
|
||||
if (callback) {
|
||||
card->eraseCallback = 0;
|
||||
callback(chan, result);
|
||||
}
|
||||
}
|
||||
|
||||
s32 __CARDUpdateDir(s32 chan, CARDCallback callback)
|
||||
{
|
||||
CARDControl *card;
|
||||
CARDDirCheck *check;
|
||||
u32 tmp[2];
|
||||
u32 addr;
|
||||
CARDDir *dir;
|
||||
|
||||
card = &__CARDBlock[chan];
|
||||
if (!card->attached) {
|
||||
return CARD_RESULT_NOCARD;
|
||||
}
|
||||
|
||||
dir = __CARDGetDirBlock(card);
|
||||
check = __CARDGetDirCheck(dir);
|
||||
++check->checkCode;
|
||||
__CARDCheckSum(dir, 0x2000 - sizeof(u32), &check->checkSum, &check->checkSumInv);
|
||||
DCStoreRange(dir, 0x2000);
|
||||
|
||||
card->eraseCallback = callback;
|
||||
addr = ((u32)dir - (u32)card->workArea) / 0x2000 * card->sectorSize;
|
||||
return __CARDEraseSector(chan, addr, EraseCallback);
|
||||
}
|
||||
141
src/dolphin/card/CARDFormat.c
Normal file
141
src/dolphin/card/CARDFormat.c
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
#include <dolphin/card.h>
|
||||
#include <dolphin/dsp.h>
|
||||
#include <dolphin/dvd.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#include <dolphin/CARDPriv.h>
|
||||
#include <dolphin/OSRtcPriv.h>
|
||||
#include <dolphin/hw_regs.h>
|
||||
#include <dolphin/vi.h>
|
||||
|
||||
#include "string.h"
|
||||
|
||||
static void FormatCallback(s32 chan, s32 result)
|
||||
{
|
||||
CARDControl *card;
|
||||
CARDCallback callback;
|
||||
|
||||
card = &__CARDBlock[chan];
|
||||
if (result < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
++card->formatStep;
|
||||
if (card->formatStep < CARD_NUM_SYSTEM_BLOCK) {
|
||||
result = __CARDEraseSector(chan, (u32)card->sectorSize * card->formatStep, FormatCallback);
|
||||
if (0 <= result) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (card->formatStep < 2 * CARD_NUM_SYSTEM_BLOCK) {
|
||||
int step = card->formatStep - CARD_NUM_SYSTEM_BLOCK;
|
||||
result = __CARDWrite(
|
||||
chan, (u32)card->sectorSize * step, CARD_SYSTEM_BLOCK_SIZE, (u8 *)card->workArea + (CARD_SYSTEM_BLOCK_SIZE * step), FormatCallback);
|
||||
if (result >= 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
card->currentDir = (CARDDir *)((u8 *)card->workArea + (1 + 0) * CARD_SYSTEM_BLOCK_SIZE);
|
||||
memcpy(card->currentDir, (u8 *)card->workArea + (1 + 1) * CARD_SYSTEM_BLOCK_SIZE, CARD_SYSTEM_BLOCK_SIZE);
|
||||
card->currentFat = (u16 *)((u8 *)card->workArea + (3 + 0) * CARD_SYSTEM_BLOCK_SIZE);
|
||||
memcpy(card->currentFat, (u8 *)card->workArea + (3 + 1) * CARD_SYSTEM_BLOCK_SIZE, CARD_SYSTEM_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
error:
|
||||
callback = card->apiCallback;
|
||||
card->apiCallback = 0;
|
||||
__CARDPutControlBlock(card, result);
|
||||
callback(chan, result);
|
||||
}
|
||||
|
||||
s32 __CARDFormatRegionAsync(s32 chan, u16 encode, CARDCallback callback)
|
||||
{
|
||||
CARDControl *card;
|
||||
CARDID *id;
|
||||
CARDDir *dir;
|
||||
u16 *fat;
|
||||
s16 i;
|
||||
s32 result;
|
||||
OSSram *sram;
|
||||
OSSramEx *sramEx;
|
||||
u16 viDTVStatus;
|
||||
OSTime time;
|
||||
OSTime rand;
|
||||
|
||||
result = __CARDGetControlBlock(chan, &card);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
id = (CARDID *)card->workArea;
|
||||
memset(id, 0xff, CARD_SYSTEM_BLOCK_SIZE);
|
||||
viDTVStatus = __VIRegs[55];
|
||||
|
||||
id->encode = encode;
|
||||
|
||||
sram = __OSLockSram();
|
||||
*(u32 *)&id->serial[20] = sram->counterBias;
|
||||
*(u32 *)&id->serial[24] = sram->language;
|
||||
__OSUnlockSram(FALSE);
|
||||
|
||||
rand = time = OSGetTime();
|
||||
|
||||
sramEx = __OSLockSramEx();
|
||||
for (i = 0; i < 12; i++) {
|
||||
rand = (rand * 1103515245 + 12345) >> 16;
|
||||
id->serial[i] = (u8)(sramEx->flashID[chan][i] + rand);
|
||||
rand = ((rand * 1103515245 + 12345) >> 16) & 0x7FFF;
|
||||
}
|
||||
__OSUnlockSramEx(FALSE);
|
||||
|
||||
*(u32 *)&id->serial[28] = viDTVStatus;
|
||||
*(OSTime *)&id->serial[12] = time;
|
||||
|
||||
id->deviceID = 0;
|
||||
id->size = card->size;
|
||||
__CARDCheckSum(id, sizeof(CARDID) - sizeof(u32), &id->checkSum, &id->checkSumInv);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
CARDDirCheck *check;
|
||||
|
||||
dir = (CARDDir *)((u8 *)card->workArea + (1 + i) * CARD_SYSTEM_BLOCK_SIZE);
|
||||
memset(dir, 0xff, CARD_SYSTEM_BLOCK_SIZE);
|
||||
check = __CARDGetDirCheck(dir);
|
||||
check->checkCode = i;
|
||||
__CARDCheckSum(dir, CARD_SYSTEM_BLOCK_SIZE - sizeof(u32), &check->checkSum, &check->checkSumInv);
|
||||
}
|
||||
for (i = 0; i < 2; i++) {
|
||||
fat = (u16 *)((u8 *)card->workArea + (3 + i) * CARD_SYSTEM_BLOCK_SIZE);
|
||||
memset(fat, 0x00, CARD_SYSTEM_BLOCK_SIZE);
|
||||
fat[CARD_FAT_CHECKCODE] = (u16)i;
|
||||
fat[CARD_FAT_FREEBLOCKS] = (u16)(card->cBlock - CARD_NUM_SYSTEM_BLOCK);
|
||||
fat[CARD_FAT_LASTSLOT] = CARD_NUM_SYSTEM_BLOCK - 1;
|
||||
__CARDCheckSum(&fat[CARD_FAT_CHECKCODE], CARD_SYSTEM_BLOCK_SIZE - sizeof(u32), &fat[CARD_FAT_CHECKSUM], &fat[CARD_FAT_CHECKSUMINV]);
|
||||
}
|
||||
|
||||
card->apiCallback = callback ? callback : __CARDDefaultApiCallback;
|
||||
DCStoreRange(card->workArea, CARD_WORKAREA_SIZE);
|
||||
|
||||
card->formatStep = 0;
|
||||
result = __CARDEraseSector(chan, (u32)card->sectorSize * card->formatStep, FormatCallback);
|
||||
if (result < 0) {
|
||||
__CARDPutControlBlock(card, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 CARDFormatAsync(s32 chan, CARDCallback callback)
|
||||
{
|
||||
return __CARDFormatRegionAsync(chan, __CARDGetFontEncode(), callback);
|
||||
}
|
||||
|
||||
s32 CARDFormat(s32 chan)
|
||||
{
|
||||
s32 result = __CARDFormatRegionAsync(chan, OSGetFontEncode(), __CARDSyncCallback);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return __CARDSync(chan);
|
||||
}
|
||||
396
src/dolphin/card/CARDMount.c
Normal file
396
src/dolphin/card/CARDMount.c
Normal file
|
|
@ -0,0 +1,396 @@
|
|||
#include <dolphin/card.h>
|
||||
#include <dolphin/dsp.h>
|
||||
#include <dolphin/dvd.h>
|
||||
#include <dolphin/exi.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#include <dolphin/CARDPriv.h>
|
||||
#include <dolphin/OSRtcPriv.h>
|
||||
|
||||
u8 GameChoice : (OS_BASE_CACHED | 0x000030E3);
|
||||
|
||||
static u32 SectorSizeTable[8] = {
|
||||
8 * 1024,
|
||||
16 * 1024,
|
||||
32 * 1024,
|
||||
64 * 1024,
|
||||
128 * 1024,
|
||||
256 * 1024,
|
||||
0,
|
||||
0,
|
||||
};
|
||||
|
||||
static u32 LatencyTable[8] = {
|
||||
4,
|
||||
8,
|
||||
16,
|
||||
32,
|
||||
64,
|
||||
128,
|
||||
256,
|
||||
512,
|
||||
};
|
||||
|
||||
void __CARDMountCallback(s32 chan, s32 result);
|
||||
static void DoUnmount(s32 chan, s32 result);
|
||||
|
||||
static BOOL IsCard(u32 id)
|
||||
{
|
||||
u32 size;
|
||||
s32 sectorSize;
|
||||
if (id & (0xFFFF0000) && (id != 0x80000004 || __CARDVendorID == 0xFFFF)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((id & 3) != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
size = id & 0xfc;
|
||||
switch (size) {
|
||||
case 4:
|
||||
case 8:
|
||||
case 16:
|
||||
case 32:
|
||||
case 64:
|
||||
case 128:
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
sectorSize = SectorSizeTable[(id & 0x00003800) >> 11];
|
||||
if (sectorSize == 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((size * 1024 * 1024 / 8) / sectorSize < 8) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
s32 CARDProbeEx(s32 chan, s32 *memSize, s32 *sectorSize)
|
||||
{
|
||||
u32 id;
|
||||
CARDControl *card;
|
||||
BOOL enabled;
|
||||
s32 result;
|
||||
int probe;
|
||||
|
||||
if (chan < 0 || 2 <= chan) {
|
||||
return CARD_RESULT_FATAL_ERROR;
|
||||
}
|
||||
|
||||
if (GameChoice & 0x80) {
|
||||
return CARD_RESULT_NOCARD;
|
||||
}
|
||||
|
||||
card = &__CARDBlock[chan];
|
||||
enabled = OSDisableInterrupts();
|
||||
|
||||
probe = EXIProbeEx(chan);
|
||||
if (probe == -1) {
|
||||
result = CARD_RESULT_NOCARD;
|
||||
}
|
||||
else if (probe == 0) {
|
||||
result = CARD_RESULT_BUSY;
|
||||
}
|
||||
else if (card->attached) {
|
||||
if (card->mountStep < 1) {
|
||||
result = CARD_RESULT_BUSY;
|
||||
}
|
||||
else {
|
||||
if (memSize) {
|
||||
*memSize = card->size;
|
||||
}
|
||||
if (sectorSize) {
|
||||
*sectorSize = card->sectorSize;
|
||||
}
|
||||
result = CARD_RESULT_READY;
|
||||
}
|
||||
}
|
||||
else if ((EXIGetState(chan) & 8)) {
|
||||
result = CARD_RESULT_WRONGDEVICE;
|
||||
}
|
||||
else if (!EXIGetID(chan, 0, &id)) {
|
||||
result = CARD_RESULT_BUSY;
|
||||
}
|
||||
else if (IsCard(id)) {
|
||||
if (memSize) {
|
||||
*memSize = (s32)(id & 0xfc);
|
||||
}
|
||||
if (sectorSize) {
|
||||
*sectorSize = SectorSizeTable[(id & 0x00003800) >> 11];
|
||||
}
|
||||
result = CARD_RESULT_READY;
|
||||
}
|
||||
else {
|
||||
result = CARD_RESULT_WRONGDEVICE;
|
||||
}
|
||||
|
||||
OSRestoreInterrupts(enabled);
|
||||
return result;
|
||||
}
|
||||
|
||||
static s32 DoMount(s32 chan)
|
||||
{
|
||||
CARDControl *card;
|
||||
u32 id;
|
||||
u8 status;
|
||||
s32 result;
|
||||
OSSramEx *sram;
|
||||
int i;
|
||||
u8 checkSum;
|
||||
int step;
|
||||
|
||||
card = &__CARDBlock[chan];
|
||||
|
||||
if (card->mountStep == 0) {
|
||||
if (EXIGetID(chan, 0, &id) == 0) {
|
||||
result = CARD_RESULT_NOCARD;
|
||||
}
|
||||
else if (IsCard(id)) {
|
||||
result = CARD_RESULT_READY;
|
||||
}
|
||||
else {
|
||||
result = CARD_RESULT_WRONGDEVICE;
|
||||
}
|
||||
if (result < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
card->cid = id;
|
||||
|
||||
card->size = (u16)(id & 0xFC);
|
||||
card->sectorSize = SectorSizeTable[(id & 0x00003800) >> 11];
|
||||
card->cBlock = (u16)((card->size * 1024 * 1024 / 8) / card->sectorSize);
|
||||
card->latency = LatencyTable[(id & 0x00000700) >> 8];
|
||||
|
||||
result = __CARDClearStatus(chan);
|
||||
if (result < 0) {
|
||||
goto error;
|
||||
}
|
||||
result = __CARDReadStatus(chan, &status);
|
||||
if (result < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!EXIProbe(chan)) {
|
||||
result = CARD_RESULT_NOCARD;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!(status & 0x40)) {
|
||||
result = __CARDUnlock(chan, card->id);
|
||||
if (result < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
checkSum = 0;
|
||||
sram = __OSLockSramEx();
|
||||
for (i = 0; i < 12; i++) {
|
||||
sram->flashID[chan][i] = card->id[i];
|
||||
checkSum += card->id[i];
|
||||
}
|
||||
sram->flashIDCheckSum[chan] = (u8)~checkSum;
|
||||
__OSUnlockSramEx(TRUE);
|
||||
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
card->mountStep = 1;
|
||||
|
||||
checkSum = 0;
|
||||
sram = __OSLockSramEx();
|
||||
for (i = 0; i < 12; i++) {
|
||||
checkSum += sram->flashID[chan][i];
|
||||
}
|
||||
__OSUnlockSramEx(FALSE);
|
||||
if (sram->flashIDCheckSum[chan] != (u8)~checkSum) {
|
||||
result = CARD_RESULT_IOERROR;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (card->mountStep == 1) {
|
||||
if (card->cid == 0x80000004) {
|
||||
u16 vendorID;
|
||||
|
||||
sram = __OSLockSramEx();
|
||||
vendorID = *(u16 *)sram->flashID[chan];
|
||||
__OSUnlockSramEx(FALSE);
|
||||
|
||||
if (__CARDVendorID == 0xffff || vendorID != __CARDVendorID) {
|
||||
result = CARD_RESULT_WRONGDEVICE;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
card->mountStep = 2;
|
||||
|
||||
result = __CARDEnableInterrupt(chan, TRUE);
|
||||
if (result < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
EXISetExiCallback(chan, __CARDExiHandler);
|
||||
EXIUnlock(chan);
|
||||
DCInvalidateRange(card->workArea, CARD_WORKAREA_SIZE);
|
||||
}
|
||||
|
||||
step = card->mountStep - 2;
|
||||
result = __CARDRead(
|
||||
chan, (u32)card->sectorSize * step, CARD_SYSTEM_BLOCK_SIZE, (u8 *)card->workArea + (CARD_SYSTEM_BLOCK_SIZE * step), __CARDMountCallback);
|
||||
if (result < 0) {
|
||||
__CARDPutControlBlock(card, result);
|
||||
}
|
||||
return result;
|
||||
|
||||
error:
|
||||
EXIUnlock(chan);
|
||||
DoUnmount(chan, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void __CARDMountCallback(s32 chan, s32 result)
|
||||
{
|
||||
CARDControl *card;
|
||||
CARDCallback callback;
|
||||
|
||||
card = &__CARDBlock[chan];
|
||||
|
||||
switch (result) {
|
||||
case CARD_RESULT_READY:
|
||||
if (++card->mountStep < CARD_MAX_MOUNT_STEP) {
|
||||
result = DoMount(chan);
|
||||
if (0 <= result) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = __CARDVerify(card);
|
||||
}
|
||||
break;
|
||||
case CARD_RESULT_UNLOCKED:
|
||||
card->unlockCallback = __CARDMountCallback;
|
||||
if (!EXILock(chan, 0, __CARDUnlockedHandler)) {
|
||||
return;
|
||||
}
|
||||
card->unlockCallback = 0;
|
||||
|
||||
result = DoMount(chan);
|
||||
if (0 <= result) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case CARD_RESULT_IOERROR:
|
||||
case CARD_RESULT_NOCARD:
|
||||
DoUnmount(chan, result);
|
||||
break;
|
||||
}
|
||||
|
||||
callback = card->apiCallback;
|
||||
card->apiCallback = 0;
|
||||
__CARDPutControlBlock(card, result);
|
||||
callback(chan, result);
|
||||
}
|
||||
|
||||
s32 CARDMountAsync(s32 chan, void *workArea, CARDCallback detachCallback, CARDCallback attachCallback)
|
||||
{
|
||||
CARDControl *card;
|
||||
BOOL enabled;
|
||||
|
||||
if (chan < 0 || 2 <= chan) {
|
||||
return CARD_RESULT_FATAL_ERROR;
|
||||
}
|
||||
if (GameChoice & 0x80) {
|
||||
return CARD_RESULT_NOCARD;
|
||||
}
|
||||
card = &__CARDBlock[chan];
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
if (card->result == CARD_RESULT_BUSY) {
|
||||
OSRestoreInterrupts(enabled);
|
||||
return CARD_RESULT_BUSY;
|
||||
}
|
||||
|
||||
if (!card->attached && (EXIGetState(chan) & 0x08)) {
|
||||
OSRestoreInterrupts(enabled);
|
||||
return CARD_RESULT_WRONGDEVICE;
|
||||
}
|
||||
|
||||
card->result = CARD_RESULT_BUSY;
|
||||
card->workArea = workArea;
|
||||
card->extCallback = detachCallback;
|
||||
card->apiCallback = attachCallback ? attachCallback : __CARDDefaultApiCallback;
|
||||
card->exiCallback = 0;
|
||||
|
||||
if (!card->attached && !EXIAttach(chan, __CARDExtHandler)) {
|
||||
card->result = CARD_RESULT_NOCARD;
|
||||
OSRestoreInterrupts(enabled);
|
||||
return CARD_RESULT_NOCARD;
|
||||
}
|
||||
|
||||
card->mountStep = 0;
|
||||
card->attached = TRUE;
|
||||
EXISetExiCallback(chan, 0);
|
||||
OSCancelAlarm(&card->alarm);
|
||||
|
||||
card->currentDir = 0;
|
||||
card->currentFat = 0;
|
||||
|
||||
OSRestoreInterrupts(enabled);
|
||||
|
||||
card->unlockCallback = __CARDMountCallback;
|
||||
if (!EXILock(chan, 0, __CARDUnlockedHandler)) {
|
||||
return CARD_RESULT_READY;
|
||||
}
|
||||
card->unlockCallback = 0;
|
||||
|
||||
return DoMount(chan);
|
||||
}
|
||||
|
||||
s32 CARDMount(s32 chan, void *workArea, CARDCallback attachCb)
|
||||
{
|
||||
s32 result = CARDMountAsync(chan, workArea, attachCb, __CARDSyncCallback);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return __CARDSync(chan);
|
||||
}
|
||||
|
||||
static void DoUnmount(s32 chan, s32 result)
|
||||
{
|
||||
CARDControl *card;
|
||||
BOOL enabled;
|
||||
|
||||
card = &__CARDBlock[chan];
|
||||
enabled = OSDisableInterrupts();
|
||||
if (card->attached) {
|
||||
EXISetExiCallback(chan, 0);
|
||||
EXIDetach(chan);
|
||||
OSCancelAlarm(&card->alarm);
|
||||
card->attached = FALSE;
|
||||
card->result = result;
|
||||
card->mountStep = 0;
|
||||
}
|
||||
OSRestoreInterrupts(enabled);
|
||||
}
|
||||
|
||||
s32 CARDUnmount(s32 chan)
|
||||
{
|
||||
CARDControl *card;
|
||||
s32 result;
|
||||
|
||||
result = __CARDGetControlBlock(chan, &card);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
DoUnmount(chan, CARD_RESULT_NOCARD);
|
||||
return CARD_RESULT_READY;
|
||||
}
|
||||
34
src/dolphin/card/CARDNet.c
Normal file
34
src/dolphin/card/CARDNet.c
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#include <dolphin/card.h>
|
||||
#include <dolphin/dsp.h>
|
||||
#include <dolphin/dvd.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#include <dolphin/CARDPriv.h>
|
||||
|
||||
u16 __CARDVendorID = 0xffff;
|
||||
|
||||
s32 CARDGetSerialNo(s32 chan, u64 *serialNo)
|
||||
{
|
||||
CARDControl *card;
|
||||
CARDID *id;
|
||||
int i;
|
||||
u64 code;
|
||||
s32 result;
|
||||
|
||||
if (!(0 <= chan && chan < 2)) {
|
||||
return CARD_RESULT_FATAL_ERROR;
|
||||
}
|
||||
|
||||
result = __CARDGetControlBlock(chan, &card);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
id = (CARDID *)card->workArea;
|
||||
for (code = 0, i = 0; i < sizeof(id->serial) / sizeof(u64); ++i) {
|
||||
code ^= *(u64 *)&id->serial[sizeof(u64) * i];
|
||||
}
|
||||
*serialNo = code;
|
||||
|
||||
return __CARDPutControlBlock(card, CARD_RESULT_READY);
|
||||
}
|
||||
134
src/dolphin/card/CARDOpen.c
Normal file
134
src/dolphin/card/CARDOpen.c
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
#include <dolphin/card.h>
|
||||
#include <dolphin/dsp.h>
|
||||
#include <dolphin/dvd.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#include <dolphin/CARDPriv.h>
|
||||
|
||||
BOOL __CARDCompareFileName(CARDDir *ent, const char *fileName)
|
||||
{
|
||||
char *entName;
|
||||
char c1;
|
||||
char c2;
|
||||
int n;
|
||||
|
||||
entName = (char *)ent->fileName;
|
||||
n = CARD_FILENAME_MAX;
|
||||
while (0 <= --n) {
|
||||
if ((c1 = *entName++) != (c2 = *fileName++)) {
|
||||
return FALSE;
|
||||
}
|
||||
else if (c2 == '\0') {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (*fileName == '\0') {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 __CARDAccess(CARDControl *card, CARDDir *ent)
|
||||
{
|
||||
if (ent->gameName[0] == 0xFF) {
|
||||
return CARD_RESULT_NOFILE;
|
||||
}
|
||||
|
||||
if (card->diskID == &__CARDDiskNone
|
||||
|| (memcmp(ent->gameName, card->diskID->gameName, 4) == 0 && memcmp(ent->company, card->diskID->company, 2) == 0)) {
|
||||
return CARD_RESULT_READY;
|
||||
}
|
||||
|
||||
return CARD_RESULT_NOPERM;
|
||||
}
|
||||
|
||||
BOOL __CARDIsPublic(CARDDir *ent)
|
||||
{
|
||||
if (ent->gameName[0] == 0xFF) {
|
||||
return CARD_RESULT_NOFILE;
|
||||
}
|
||||
|
||||
if ((ent->permission & CARD_ATTR_PUBLIC) != 0) {
|
||||
return CARD_RESULT_READY;
|
||||
}
|
||||
|
||||
return CARD_RESULT_NOPERM;
|
||||
}
|
||||
|
||||
s32 __CARDGetFileNo(CARDControl *card, const char *fileName, s32 *pfileNo)
|
||||
{
|
||||
CARDDir *dir;
|
||||
CARDDir *ent;
|
||||
s32 fileNo;
|
||||
s32 result;
|
||||
|
||||
if (!card->attached) {
|
||||
return CARD_RESULT_NOCARD;
|
||||
}
|
||||
|
||||
dir = __CARDGetDirBlock(card);
|
||||
for (fileNo = 0; fileNo < CARD_MAX_FILE; fileNo++) {
|
||||
ent = &dir[fileNo];
|
||||
result = __CARDAccess(card, ent);
|
||||
if (result < 0) {
|
||||
continue;
|
||||
}
|
||||
if (__CARDCompareFileName(ent, fileName)) {
|
||||
*pfileNo = fileNo;
|
||||
return CARD_RESULT_READY;
|
||||
}
|
||||
}
|
||||
|
||||
return CARD_RESULT_NOFILE;
|
||||
}
|
||||
|
||||
s32 CARDOpen(s32 chan, const char *fileName, CARDFileInfo *fileInfo)
|
||||
{
|
||||
CARDControl *card;
|
||||
CARDDir *dir;
|
||||
CARDDir *ent;
|
||||
s32 result;
|
||||
s32 fileNo;
|
||||
|
||||
fileInfo->chan = -1;
|
||||
result = __CARDGetControlBlock(chan, &card);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
result = __CARDGetFileNo(card, fileName, &fileNo);
|
||||
if (0 <= result) {
|
||||
dir = __CARDGetDirBlock(card);
|
||||
ent = &dir[fileNo];
|
||||
if (!CARDIsValidBlockNo(card, ent->startBlock)) {
|
||||
result = CARD_RESULT_BROKEN;
|
||||
}
|
||||
else {
|
||||
fileInfo->chan = chan;
|
||||
fileInfo->fileNo = fileNo;
|
||||
fileInfo->offset = 0;
|
||||
fileInfo->iBlock = ent->startBlock;
|
||||
}
|
||||
}
|
||||
return __CARDPutControlBlock(card, result);
|
||||
}
|
||||
|
||||
s32 CARDClose(CARDFileInfo *fileInfo)
|
||||
{
|
||||
CARDControl *card;
|
||||
s32 result;
|
||||
|
||||
result = __CARDGetControlBlock(fileInfo->chan, &card);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
fileInfo->chan = -1;
|
||||
return __CARDPutControlBlock(card, CARD_RESULT_READY);
|
||||
}
|
||||
|
||||
BOOL __CARDIsOpened(CARDControl *card, s32 fileNo)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
108
src/dolphin/card/CARDRdwr.c
Normal file
108
src/dolphin/card/CARDRdwr.c
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
#include <dolphin/card.h>
|
||||
#include <dolphin/dsp.h>
|
||||
#include <dolphin/dvd.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#include <dolphin/CARDPriv.h>
|
||||
|
||||
static void BlockReadCallback(s32 chan, s32 result)
|
||||
{
|
||||
CARDControl *card;
|
||||
CARDCallback callback;
|
||||
|
||||
card = &__CARDBlock[chan];
|
||||
if (result < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
card->xferred += CARD_SEG_SIZE;
|
||||
|
||||
card->addr += CARD_SEG_SIZE;
|
||||
(u8 *)card->buffer += CARD_SEG_SIZE;
|
||||
if (--card->repeat <= 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
result = __CARDReadSegment(chan, BlockReadCallback);
|
||||
if (result < 0) {
|
||||
goto error;
|
||||
}
|
||||
return;
|
||||
|
||||
error:
|
||||
if (card->apiCallback == 0) {
|
||||
__CARDPutControlBlock(card, result);
|
||||
}
|
||||
callback = card->xferCallback;
|
||||
if (callback) {
|
||||
card->xferCallback = 0;
|
||||
callback(chan, result);
|
||||
}
|
||||
}
|
||||
|
||||
s32 __CARDRead(s32 chan, u32 addr, s32 length, void *dst, CARDCallback callback)
|
||||
{
|
||||
CARDControl *card;
|
||||
card = &__CARDBlock[chan];
|
||||
if (!card->attached) {
|
||||
return CARD_RESULT_NOCARD;
|
||||
}
|
||||
|
||||
card->xferCallback = callback;
|
||||
card->repeat = (int)(length / CARD_SEG_SIZE);
|
||||
card->addr = addr;
|
||||
card->buffer = dst;
|
||||
|
||||
return __CARDReadSegment(chan, BlockReadCallback);
|
||||
}
|
||||
|
||||
static void BlockWriteCallback(s32 chan, s32 result)
|
||||
{
|
||||
CARDControl *card;
|
||||
CARDCallback callback;
|
||||
|
||||
card = &__CARDBlock[chan];
|
||||
if (result < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
card->xferred += CARD_PAGE_SIZE;
|
||||
|
||||
card->addr += CARD_PAGE_SIZE;
|
||||
(u8 *)card->buffer += CARD_PAGE_SIZE;
|
||||
if (--card->repeat <= 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
result = __CARDWritePage(chan, BlockWriteCallback);
|
||||
if (result < 0) {
|
||||
goto error;
|
||||
}
|
||||
return;
|
||||
|
||||
error:
|
||||
if (card->apiCallback == 0) {
|
||||
__CARDPutControlBlock(card, result);
|
||||
}
|
||||
callback = card->xferCallback;
|
||||
if (callback) {
|
||||
card->xferCallback = 0;
|
||||
callback(chan, result);
|
||||
}
|
||||
}
|
||||
|
||||
s32 __CARDWrite(s32 chan, u32 addr, s32 length, void *dst, CARDCallback callback)
|
||||
{
|
||||
CARDControl *card;
|
||||
card = &__CARDBlock[chan];
|
||||
if (!card->attached) {
|
||||
return CARD_RESULT_NOCARD;
|
||||
}
|
||||
|
||||
card->xferCallback = callback;
|
||||
card->repeat = (int)(length / CARD_PAGE_SIZE);
|
||||
card->addr = addr;
|
||||
card->buffer = dst;
|
||||
|
||||
return __CARDWritePage(chan, BlockWriteCallback);
|
||||
}
|
||||
149
src/dolphin/card/CARDRead.c
Normal file
149
src/dolphin/card/CARDRead.c
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
#include <dolphin/card.h>
|
||||
#include <dolphin/dsp.h>
|
||||
#include <dolphin/dvd.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#include <dolphin/CARDPriv.h>
|
||||
|
||||
s32 __CARDSeek(CARDFileInfo *fileInfo, s32 length, s32 offset, CARDControl **pcard)
|
||||
{
|
||||
CARDControl *card;
|
||||
CARDDir *dir;
|
||||
CARDDir *ent;
|
||||
s32 result;
|
||||
u16 *fat;
|
||||
|
||||
result = __CARDGetControlBlock(fileInfo->chan, &card);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!CARDIsValidBlockNo(card, fileInfo->iBlock) || card->cBlock * card->sectorSize <= fileInfo->offset) {
|
||||
return __CARDPutControlBlock(card, CARD_RESULT_FATAL_ERROR);
|
||||
}
|
||||
|
||||
dir = __CARDGetDirBlock(card);
|
||||
ent = &dir[fileInfo->fileNo];
|
||||
if (ent->length * card->sectorSize <= offset || ent->length * card->sectorSize < offset + length) {
|
||||
return __CARDPutControlBlock(card, CARD_RESULT_LIMIT);
|
||||
}
|
||||
|
||||
card->fileInfo = fileInfo;
|
||||
fileInfo->length = length;
|
||||
if (offset < fileInfo->offset) {
|
||||
fileInfo->offset = 0;
|
||||
fileInfo->iBlock = ent->startBlock;
|
||||
if (!CARDIsValidBlockNo(card, fileInfo->iBlock)) {
|
||||
return __CARDPutControlBlock(card, CARD_RESULT_BROKEN);
|
||||
}
|
||||
}
|
||||
fat = __CARDGetFatBlock(card);
|
||||
while (fileInfo->offset < TRUNC(offset, card->sectorSize)) {
|
||||
fileInfo->offset += card->sectorSize;
|
||||
fileInfo->iBlock = fat[fileInfo->iBlock];
|
||||
if (!CARDIsValidBlockNo(card, fileInfo->iBlock)) {
|
||||
return __CARDPutControlBlock(card, CARD_RESULT_BROKEN);
|
||||
}
|
||||
}
|
||||
|
||||
fileInfo->offset = offset;
|
||||
|
||||
*pcard = card;
|
||||
return CARD_RESULT_READY;
|
||||
}
|
||||
|
||||
static void ReadCallback(s32 chan, s32 result)
|
||||
{
|
||||
CARDControl *card;
|
||||
CARDCallback callback;
|
||||
u16 *fat;
|
||||
CARDFileInfo *fileInfo;
|
||||
s32 length;
|
||||
|
||||
card = &__CARDBlock[chan];
|
||||
if (result < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
fileInfo = card->fileInfo;
|
||||
if (fileInfo->length < 0) {
|
||||
result = CARD_RESULT_CANCELED;
|
||||
goto error;
|
||||
}
|
||||
|
||||
length = (s32)TRUNC(fileInfo->offset + card->sectorSize, card->sectorSize) - fileInfo->offset;
|
||||
fileInfo->length -= length;
|
||||
if (fileInfo->length <= 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
fat = __CARDGetFatBlock(card);
|
||||
fileInfo->offset += length;
|
||||
fileInfo->iBlock = fat[fileInfo->iBlock];
|
||||
if (!CARDIsValidBlockNo(card, fileInfo->iBlock)) {
|
||||
result = CARD_RESULT_BROKEN;
|
||||
goto error;
|
||||
}
|
||||
|
||||
result = __CARDRead(chan, card->sectorSize * (u32)fileInfo->iBlock, (fileInfo->length < card->sectorSize) ? fileInfo->length : card->sectorSize,
|
||||
card->buffer, ReadCallback);
|
||||
if (result < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
callback = card->apiCallback;
|
||||
card->apiCallback = 0;
|
||||
__CARDPutControlBlock(card, result);
|
||||
callback(chan, result);
|
||||
}
|
||||
|
||||
s32 CARDReadAsync(CARDFileInfo *fileInfo, void *buf, s32 length, s32 offset, CARDCallback callback)
|
||||
{
|
||||
CARDControl *card;
|
||||
s32 result;
|
||||
CARDDir *dir;
|
||||
CARDDir *ent;
|
||||
|
||||
if (OFFSET(offset, CARD_SEG_SIZE) != 0 || OFFSET(length, CARD_SEG_SIZE) != 0) {
|
||||
return CARD_RESULT_FATAL_ERROR;
|
||||
}
|
||||
result = __CARDSeek(fileInfo, length, offset, &card);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
dir = __CARDGetDirBlock(card);
|
||||
ent = &dir[fileInfo->fileNo];
|
||||
result = __CARDAccess(card, ent);
|
||||
if (result == CARD_RESULT_NOPERM) {
|
||||
result = __CARDIsPublic(ent);
|
||||
}
|
||||
|
||||
if (result < 0) {
|
||||
return __CARDPutControlBlock(card, result);
|
||||
}
|
||||
|
||||
DCInvalidateRange(buf, (u32)length);
|
||||
card->apiCallback = callback ? callback : __CARDDefaultApiCallback;
|
||||
|
||||
offset = (s32)OFFSET(fileInfo->offset, card->sectorSize);
|
||||
length = (length < card->sectorSize - offset) ? length : card->sectorSize - offset;
|
||||
result = __CARDRead(fileInfo->chan, card->sectorSize * (u32)fileInfo->iBlock + offset, length, buf, ReadCallback);
|
||||
if (result < 0) {
|
||||
__CARDPutControlBlock(card, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 CARDRead(CARDFileInfo *fileInfo, void *buf, s32 length, s32 offset)
|
||||
{
|
||||
s32 result = CARDReadAsync(fileInfo, buf, length, offset, __CARDSyncCallback);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return __CARDSync(fileInfo->chan);
|
||||
}
|
||||
70
src/dolphin/card/CARDRename.c
Normal file
70
src/dolphin/card/CARDRename.c
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
#include <dolphin/card.h>
|
||||
#include <dolphin/dsp.h>
|
||||
#include <dolphin/dvd.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#include <dolphin/CARDPriv.h>
|
||||
|
||||
s32 CARDRenameAsync(s32 chan, const char* old, const char* new, CARDCallback callback) {
|
||||
CARDControl* card;
|
||||
CARDDir* dir;
|
||||
CARDDir* ent;
|
||||
s32 result;
|
||||
int fileNo;
|
||||
int newNo;
|
||||
int oldNo;
|
||||
|
||||
if (*old == 0xff || *new == 0xff || *old == 0x00 || *new == 0x00) {
|
||||
return CARD_RESULT_FATAL_ERROR;
|
||||
}
|
||||
if (CARD_FILENAME_MAX < (u32)strlen(old) || CARD_FILENAME_MAX < (u32)strlen(new)) {
|
||||
return CARD_RESULT_NAMETOOLONG;
|
||||
}
|
||||
result = __CARDGetControlBlock(chan, &card);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
newNo = oldNo = -1;
|
||||
dir = __CARDGetDirBlock(card);
|
||||
for (fileNo = 0; fileNo < CARD_MAX_FILE; fileNo++) {
|
||||
ent = &dir[fileNo];
|
||||
if (ent->gameName[0] == 0xff) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (memcmp(ent->gameName, card->diskID->gameName, sizeof(ent->gameName)) != 0 ||
|
||||
memcmp(ent->company, card->diskID->company, sizeof(ent->company)) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (__CARDCompareFileName(ent, old)) {
|
||||
oldNo = fileNo;
|
||||
}
|
||||
if (__CARDCompareFileName(ent, new)) {
|
||||
newNo = fileNo;
|
||||
}
|
||||
}
|
||||
|
||||
if (oldNo == -1) {
|
||||
return __CARDPutControlBlock(card, CARD_RESULT_NOFILE);
|
||||
}
|
||||
if (newNo != -1) {
|
||||
return __CARDPutControlBlock(card, CARD_RESULT_EXIST);
|
||||
}
|
||||
|
||||
ent = &dir[oldNo];
|
||||
result = __CARDAccess(card, ent);
|
||||
if (result < 0) {
|
||||
return __CARDPutControlBlock(card, result);
|
||||
}
|
||||
|
||||
strncpy((char*)ent->fileName, new, CARD_FILENAME_MAX);
|
||||
|
||||
ent->time = (u32)OSTicksToSeconds(OSGetTime());
|
||||
result = __CARDUpdateDir(chan, callback);
|
||||
if (result < 0) {
|
||||
__CARDPutControlBlock(card, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
158
src/dolphin/card/CARDStat.c
Normal file
158
src/dolphin/card/CARDStat.c
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
#include <dolphin/card.h>
|
||||
#include <dolphin/dsp.h>
|
||||
#include <dolphin/dvd.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#include "string.h"
|
||||
|
||||
#include <dolphin/CARDPriv.h>
|
||||
|
||||
static void UpdateIconOffsets(CARDDir *ent, CARDStat *stat)
|
||||
{
|
||||
u32 offset;
|
||||
BOOL iconTlut;
|
||||
int i;
|
||||
|
||||
offset = ent->iconAddr;
|
||||
if (offset == 0xffffffff) {
|
||||
stat->bannerFormat = 0;
|
||||
stat->iconFormat = 0;
|
||||
stat->iconSpeed = 0;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
iconTlut = FALSE;
|
||||
switch (CARDGetBannerFormat(ent)) {
|
||||
case CARD_STAT_BANNER_C8:
|
||||
stat->offsetBanner = offset;
|
||||
offset += CARD_BANNER_WIDTH * CARD_BANNER_HEIGHT;
|
||||
stat->offsetBannerTlut = offset;
|
||||
offset += 2 * 256;
|
||||
break;
|
||||
case CARD_STAT_BANNER_RGB5A3:
|
||||
stat->offsetBanner = offset;
|
||||
offset += 2 * CARD_BANNER_WIDTH * CARD_BANNER_HEIGHT;
|
||||
stat->offsetBannerTlut = 0xffffffff;
|
||||
break;
|
||||
default:
|
||||
stat->offsetBanner = 0xffffffff;
|
||||
stat->offsetBannerTlut = 0xffffffff;
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < CARD_ICON_MAX; ++i) {
|
||||
switch (CARDGetIconFormat(ent, i)) {
|
||||
case CARD_STAT_ICON_C8:
|
||||
stat->offsetIcon[i] = offset;
|
||||
offset += CARD_ICON_WIDTH * CARD_ICON_HEIGHT;
|
||||
iconTlut = TRUE;
|
||||
break;
|
||||
case CARD_STAT_ICON_RGB5A3:
|
||||
stat->offsetIcon[i] = offset;
|
||||
offset += 2 * CARD_ICON_WIDTH * CARD_ICON_HEIGHT;
|
||||
break;
|
||||
default:
|
||||
stat->offsetIcon[i] = 0xffffffff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (iconTlut) {
|
||||
stat->offsetIconTlut = offset;
|
||||
offset += 2 * 256;
|
||||
}
|
||||
else {
|
||||
stat->offsetIconTlut = 0xffffffff;
|
||||
}
|
||||
stat->offsetData = offset;
|
||||
}
|
||||
|
||||
s32 CARDGetStatus(s32 chan, s32 fileNo, CARDStat *stat)
|
||||
{
|
||||
CARDControl *card;
|
||||
CARDDir *dir;
|
||||
CARDDir *ent;
|
||||
s32 result;
|
||||
|
||||
if (fileNo < 0 || CARD_MAX_FILE <= fileNo) {
|
||||
return CARD_RESULT_FATAL_ERROR;
|
||||
}
|
||||
result = __CARDGetControlBlock(chan, &card);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
dir = __CARDGetDirBlock(card);
|
||||
ent = &dir[fileNo];
|
||||
result = __CARDAccess(card, ent);
|
||||
if (result == CARD_RESULT_NOPERM) {
|
||||
result = __CARDIsPublic(ent);
|
||||
}
|
||||
|
||||
if (result >= 0) {
|
||||
memcpy(stat->gameName, ent->gameName, sizeof(stat->gameName));
|
||||
memcpy(stat->company, ent->company, sizeof(stat->company));
|
||||
stat->length = (u32)ent->length * card->sectorSize;
|
||||
memcpy(stat->fileName, ent->fileName, CARD_FILENAME_MAX);
|
||||
stat->time = ent->time;
|
||||
|
||||
stat->bannerFormat = ent->bannerFormat;
|
||||
stat->iconAddr = ent->iconAddr;
|
||||
stat->iconFormat = ent->iconFormat;
|
||||
stat->iconSpeed = ent->iconSpeed;
|
||||
stat->commentAddr = ent->commentAddr;
|
||||
|
||||
UpdateIconOffsets(ent, stat);
|
||||
}
|
||||
return __CARDPutControlBlock(card, result);
|
||||
}
|
||||
|
||||
s32 CARDSetStatusAsync(s32 chan, s32 fileNo, CARDStat *stat, CARDCallback callback)
|
||||
{
|
||||
CARDControl *card;
|
||||
CARDDir *dir;
|
||||
CARDDir *ent;
|
||||
s32 result;
|
||||
|
||||
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;
|
||||
}
|
||||
result = __CARDGetControlBlock(chan, &card);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
dir = __CARDGetDirBlock(card);
|
||||
ent = &dir[fileNo];
|
||||
result = __CARDAccess(card, ent);
|
||||
if (result < 0) {
|
||||
return __CARDPutControlBlock(card, result);
|
||||
}
|
||||
|
||||
ent->bannerFormat = stat->bannerFormat;
|
||||
ent->iconAddr = stat->iconAddr;
|
||||
ent->iconFormat = stat->iconFormat;
|
||||
ent->iconSpeed = stat->iconSpeed;
|
||||
ent->commentAddr = stat->commentAddr;
|
||||
UpdateIconOffsets(ent, stat);
|
||||
|
||||
if (ent->iconAddr == 0xffffffff) {
|
||||
CARDSetIconSpeed(ent, 0, CARD_STAT_SPEED_FAST);
|
||||
}
|
||||
|
||||
ent->time = (u32)OSTicksToSeconds(OSGetTime());
|
||||
result = __CARDUpdateDir(chan, callback);
|
||||
if (result < 0) {
|
||||
__CARDPutControlBlock(card, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 CARDSetStatus(s32 chan, s32 fileNo, CARDStat *stat)
|
||||
{
|
||||
s32 result = CARDSetStatusAsync(chan, fileNo, stat, __CARDSyncCallback);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return __CARDSync(chan);
|
||||
}
|
||||
406
src/dolphin/card/CARDUnlock.c
Normal file
406
src/dolphin/card/CARDUnlock.c
Normal file
|
|
@ -0,0 +1,406 @@
|
|||
#include <dolphin/card.h>
|
||||
#include <dolphin/dsp.h>
|
||||
#include <dolphin/dvd.h>
|
||||
#include <dolphin/exi.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#include "string.h"
|
||||
|
||||
#include <dolphin/CARDPriv.h>
|
||||
|
||||
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);
|
||||
}
|
||||
128
src/dolphin/card/CARDWrite.c
Normal file
128
src/dolphin/card/CARDWrite.c
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
#include <dolphin/card.h>
|
||||
#include <dolphin/dsp.h>
|
||||
#include <dolphin/dvd.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#include <dolphin/CARDPriv.h>
|
||||
|
||||
static void EraseCallback(s32 chan, s32 result);
|
||||
|
||||
static void WriteCallback(s32 chan, s32 result)
|
||||
{
|
||||
CARDControl *card;
|
||||
CARDCallback callback;
|
||||
u16 *fat;
|
||||
CARDDir *dir;
|
||||
CARDDir *ent;
|
||||
CARDFileInfo *fileInfo;
|
||||
|
||||
card = &__CARDBlock[chan];
|
||||
if (result < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
fileInfo = card->fileInfo;
|
||||
if (fileInfo->length < 0) {
|
||||
result = CARD_RESULT_CANCELED;
|
||||
goto error;
|
||||
}
|
||||
|
||||
fileInfo->length -= card->sectorSize;
|
||||
if (fileInfo->length <= 0) {
|
||||
dir = __CARDGetDirBlock(card);
|
||||
ent = &dir[fileInfo->fileNo];
|
||||
ent->time = (u32)OSTicksToSeconds(OSGetTime());
|
||||
callback = card->apiCallback;
|
||||
card->apiCallback = 0;
|
||||
result = __CARDUpdateDir(chan, callback);
|
||||
}
|
||||
else {
|
||||
fat = __CARDGetFatBlock(card);
|
||||
fileInfo->offset += card->sectorSize;
|
||||
fileInfo->iBlock = fat[fileInfo->iBlock];
|
||||
if (!CARDIsValidBlockNo(card, fileInfo->iBlock)) {
|
||||
result = CARD_RESULT_BROKEN;
|
||||
goto error;
|
||||
}
|
||||
result = __CARDEraseSector(chan, card->sectorSize * (u32)fileInfo->iBlock, EraseCallback);
|
||||
}
|
||||
|
||||
if (result < 0) {
|
||||
goto error;
|
||||
}
|
||||
return;
|
||||
|
||||
error:
|
||||
callback = card->apiCallback;
|
||||
card->apiCallback = 0;
|
||||
__CARDPutControlBlock(card, result);
|
||||
callback(chan, result);
|
||||
}
|
||||
|
||||
static void EraseCallback(s32 chan, s32 result)
|
||||
{
|
||||
CARDControl *card;
|
||||
CARDCallback callback;
|
||||
CARDFileInfo *fileInfo;
|
||||
|
||||
card = &__CARDBlock[chan];
|
||||
if (result < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
fileInfo = card->fileInfo;
|
||||
result = __CARDWrite(chan, card->sectorSize * (u32)fileInfo->iBlock, card->sectorSize, card->buffer, WriteCallback);
|
||||
if (result < 0) {
|
||||
goto error;
|
||||
}
|
||||
return;
|
||||
|
||||
error:
|
||||
callback = card->apiCallback;
|
||||
card->apiCallback = 0;
|
||||
__CARDPutControlBlock(card, result);
|
||||
callback(chan, result);
|
||||
}
|
||||
|
||||
s32 CARDWriteAsync(CARDFileInfo *fileInfo, const void *buf, s32 length, s32 offset, CARDCallback callback)
|
||||
{
|
||||
CARDControl *card;
|
||||
s32 result;
|
||||
CARDDir *dir;
|
||||
CARDDir *ent;
|
||||
|
||||
result = __CARDSeek(fileInfo, length, offset, &card);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (OFFSET(offset, card->sectorSize) != 0 || OFFSET(length, card->sectorSize) != 0) {
|
||||
return __CARDPutControlBlock(card, CARD_RESULT_FATAL_ERROR);
|
||||
}
|
||||
|
||||
dir = __CARDGetDirBlock(card);
|
||||
ent = &dir[fileInfo->fileNo];
|
||||
result = __CARDAccess(card, ent);
|
||||
if (result < 0) {
|
||||
return __CARDPutControlBlock(card, result);
|
||||
}
|
||||
|
||||
DCStoreRange((void *)buf, (u32)length);
|
||||
card->apiCallback = callback ? callback : __CARDDefaultApiCallback;
|
||||
card->buffer = (void *)buf;
|
||||
result = __CARDEraseSector(fileInfo->chan, card->sectorSize * (u32)fileInfo->iBlock, EraseCallback);
|
||||
if (result < 0) {
|
||||
__CARDPutControlBlock(card, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 CARDWrite(CARDFileInfo *fileInfo, const void *buf, s32 length, s32 offset)
|
||||
{
|
||||
s32 result = CARDWriteAsync(fileInfo, buf, length, offset, __CARDSyncCallback);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return __CARDSync(fileInfo->chan);
|
||||
}
|
||||
773
src/dolphin/demo/DEMOFont.c
Normal file
773
src/dolphin/demo/DEMOFont.c
Normal file
|
|
@ -0,0 +1,773 @@
|
|||
#include <dolphin.h>
|
||||
#include <dolphin/demo.h>
|
||||
|
||||
unsigned long DEMOFontBitmap[768] ATTRIBUTE_ALIGN(32) = {
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x000FF000,
|
||||
0x000FF000,
|
||||
0x000FF000,
|
||||
0x000FF000,
|
||||
0x000FF000,
|
||||
0x00000000,
|
||||
0x000FF000,
|
||||
0x00000000,
|
||||
0x00F00F00,
|
||||
0x00F00F00,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00F00F00,
|
||||
0x00F00F00,
|
||||
0x0FFFFFF0,
|
||||
0x00F00F00,
|
||||
0x0FFFFFF0,
|
||||
0x00F00F00,
|
||||
0x00F00F00,
|
||||
0x00000000,
|
||||
0x0000F000,
|
||||
0x00FFFFF0,
|
||||
0x0F00F000,
|
||||
0x00FFFF00,
|
||||
0x0000F0F0,
|
||||
0x0FFFFF00,
|
||||
0x0000F000,
|
||||
0x00000000,
|
||||
0x0FF000F0,
|
||||
0x0FF00F00,
|
||||
0x0000F000,
|
||||
0x000F0000,
|
||||
0x00F00FF0,
|
||||
0x0F000FF0,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x000F0000,
|
||||
0x00F0F000,
|
||||
0x00F0F000,
|
||||
0x00FF0000,
|
||||
0x0F000FF0,
|
||||
0x0F0000F0,
|
||||
0x00FFFF00,
|
||||
0x00000000,
|
||||
0x000FF000,
|
||||
0x000FF000,
|
||||
0x0000F000,
|
||||
0x000F0000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x0000F000,
|
||||
0x000F0000,
|
||||
0x00F00000,
|
||||
0x00F00000,
|
||||
0x00F00000,
|
||||
0x000F0000,
|
||||
0x0000F000,
|
||||
0x00000000,
|
||||
0x000F0000,
|
||||
0x0000F000,
|
||||
0x00000F00,
|
||||
0x00000F00,
|
||||
0x00000F00,
|
||||
0x0000F000,
|
||||
0x000F0000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00F000F0,
|
||||
0x000F0F00,
|
||||
0x00FFFFF0,
|
||||
0x000F0F00,
|
||||
0x00F000F0,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x00FFFFF0,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x000FF000,
|
||||
0x000FF000,
|
||||
0x0000F000,
|
||||
0x000F0000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00FFFFF0,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x000FF000,
|
||||
0x000FF000,
|
||||
0x00000000,
|
||||
0x000000F0,
|
||||
0x00000F00,
|
||||
0x0000F000,
|
||||
0x000F0000,
|
||||
0x00F00000,
|
||||
0x0F000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x000FF000,
|
||||
0x00F00F00,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x00F00F00,
|
||||
0x000FF000,
|
||||
0x00000000,
|
||||
0x0000F000,
|
||||
0x000FF000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x000FFF00,
|
||||
0x00000000,
|
||||
0x00FFFF00,
|
||||
0x0F0000F0,
|
||||
0x000000F0,
|
||||
0x00000F00,
|
||||
0x0000F000,
|
||||
0x000F0000,
|
||||
0x0FFFFFF0,
|
||||
0x00000000,
|
||||
0x00FFFF00,
|
||||
0x0F0000F0,
|
||||
0x000000F0,
|
||||
0x0000FF00,
|
||||
0x000000F0,
|
||||
0x0F0000F0,
|
||||
0x00FFFF00,
|
||||
0x00000000,
|
||||
0x00000F00,
|
||||
0x0000FF00,
|
||||
0x000F0F00,
|
||||
0x00F00F00,
|
||||
0x0FFFFFF0,
|
||||
0x00000F00,
|
||||
0x00000F00,
|
||||
0x00000000,
|
||||
0x0FFFFFF0,
|
||||
0x0F000000,
|
||||
0x0F000000,
|
||||
0x0FFFFF00,
|
||||
0x000000F0,
|
||||
0x0F0000F0,
|
||||
0x00FFFF00,
|
||||
0x00000000,
|
||||
0x000FFF00,
|
||||
0x00F00000,
|
||||
0x0F000000,
|
||||
0x0FFFFF00,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x00FFFF00,
|
||||
0x00000000,
|
||||
0x0FFFFFF0,
|
||||
0x0F0000F0,
|
||||
0x00000F00,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x00000000,
|
||||
0x00FFFF00,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x00FFFF00,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x00FFFF00,
|
||||
0x00000000,
|
||||
0x00FFFF00,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x00FFFFF0,
|
||||
0x000000F0,
|
||||
0x000000F0,
|
||||
0x00FFFF00,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x000FF000,
|
||||
0x000FF000,
|
||||
0x00000000,
|
||||
0x000FF000,
|
||||
0x000FF000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x000FF000,
|
||||
0x000FF000,
|
||||
0x00000000,
|
||||
0x000FF000,
|
||||
0x000FF000,
|
||||
0x0000F000,
|
||||
0x000F0000,
|
||||
0x00000000,
|
||||
0x00000F00,
|
||||
0x0000F000,
|
||||
0x000F0000,
|
||||
0x00F00000,
|
||||
0x000F0000,
|
||||
0x0000F000,
|
||||
0x00000F00,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x0FFFFFF0,
|
||||
0x00000000,
|
||||
0x0FFFFFF0,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00F00000,
|
||||
0x000F0000,
|
||||
0x0000F000,
|
||||
0x00000F00,
|
||||
0x0000F000,
|
||||
0x000F0000,
|
||||
0x00F00000,
|
||||
0x00000000,
|
||||
0x00FFFF00,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x0000FF00,
|
||||
0x000FF000,
|
||||
0x00000000,
|
||||
0x000FF000,
|
||||
0x00000000,
|
||||
0x00FFFF00,
|
||||
0x0F0000F0,
|
||||
0x0F000FF0,
|
||||
0x0F00F0F0,
|
||||
0x0F00FFF0,
|
||||
0x0F000000,
|
||||
0x00FFFFF0,
|
||||
0x00000000,
|
||||
0x000FF000,
|
||||
0x00F00F00,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x0FFFFFF0,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x00000000,
|
||||
0x0FFFFF00,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x0FFFFF00,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x0FFFFF00,
|
||||
0x00000000,
|
||||
0x000FFF00,
|
||||
0x00F000F0,
|
||||
0x0F000000,
|
||||
0x0F000000,
|
||||
0x0F000000,
|
||||
0x00F000F0,
|
||||
0x000FFF00,
|
||||
0x00000000,
|
||||
0x0FFFF000,
|
||||
0x0F000F00,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x0F000F00,
|
||||
0x0FFFF000,
|
||||
0x00000000,
|
||||
0x0FFFFFF0,
|
||||
0x0F000000,
|
||||
0x0F000000,
|
||||
0x0FFFFF00,
|
||||
0x0F000000,
|
||||
0x0F000000,
|
||||
0x0FFFFFF0,
|
||||
0x00000000,
|
||||
0x0FFFFFF0,
|
||||
0x0F000000,
|
||||
0x0F000000,
|
||||
0x0FFFFF00,
|
||||
0x0F000000,
|
||||
0x0F000000,
|
||||
0x0F000000,
|
||||
0x00000000,
|
||||
0x000FFF00,
|
||||
0x00F00000,
|
||||
0x0F000000,
|
||||
0x0F00FFF0,
|
||||
0x0F0000F0,
|
||||
0x00F000F0,
|
||||
0x000FFF00,
|
||||
0x00000000,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x0FFFFFF0,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x00000000,
|
||||
0x000FFF00,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x000FFF00,
|
||||
0x00000000,
|
||||
0x0000FFF0,
|
||||
0x00000F00,
|
||||
0x00000F00,
|
||||
0x00000F00,
|
||||
0x00000F00,
|
||||
0x0F000F00,
|
||||
0x00FFF000,
|
||||
0x00000000,
|
||||
0x0F0000F0,
|
||||
0x0F000F00,
|
||||
0x0F00F000,
|
||||
0x0FFF0000,
|
||||
0x0F00F000,
|
||||
0x0F000F00,
|
||||
0x0F0000F0,
|
||||
0x00000000,
|
||||
0x0F000000,
|
||||
0x0F000000,
|
||||
0x0F000000,
|
||||
0x0F000000,
|
||||
0x0F000000,
|
||||
0x0F000000,
|
||||
0x0FFFFFF0,
|
||||
0x00000000,
|
||||
0x0F00000F,
|
||||
0x0FF000FF,
|
||||
0x0F0F0F0F,
|
||||
0x0F00F00F,
|
||||
0x0F00F00F,
|
||||
0x0F00000F,
|
||||
0x0F00000F,
|
||||
0x00000000,
|
||||
0x0F0000F0,
|
||||
0x0FF000F0,
|
||||
0x0F0F00F0,
|
||||
0x0F00F0F0,
|
||||
0x0F00F0F0,
|
||||
0x0F000FF0,
|
||||
0x0F0000F0,
|
||||
0x00000000,
|
||||
0x00FFFF00,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x00FFFF00,
|
||||
0x00000000,
|
||||
0x0FFFFF00,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x0FFFFF00,
|
||||
0x0F000000,
|
||||
0x0F000000,
|
||||
0x0F000000,
|
||||
0x00000000,
|
||||
0x00FFFF00,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x0F00F0F0,
|
||||
0x0F000F00,
|
||||
0x00FFF0F0,
|
||||
0x00000000,
|
||||
0x0FFFFF00,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x0FFFFF00,
|
||||
0x0F00F000,
|
||||
0x0F000F00,
|
||||
0x0F0000F0,
|
||||
0x00000000,
|
||||
0x00FFFF00,
|
||||
0x0F0000F0,
|
||||
0x0F000000,
|
||||
0x00FFFF00,
|
||||
0x000000F0,
|
||||
0x0F0000F0,
|
||||
0x00FFFF00,
|
||||
0x00000000,
|
||||
0x0FFFFFFF,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x00000000,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x00FFFF00,
|
||||
0x00000000,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x00F00F00,
|
||||
0x00F00F00,
|
||||
0x000FF000,
|
||||
0x00000000,
|
||||
0x0F00000F,
|
||||
0x0F00000F,
|
||||
0x0F00000F,
|
||||
0x0F00F00F,
|
||||
0x0F00F00F,
|
||||
0x0F00F00F,
|
||||
0x00FF0FF0,
|
||||
0x00000000,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x00F00F00,
|
||||
0x000FF000,
|
||||
0x00F00F00,
|
||||
0x0F0000F0,
|
||||
0x0F0000F0,
|
||||
0x00000000,
|
||||
0x0F00000F,
|
||||
0x00F000F0,
|
||||
0x000F0F00,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x00000000,
|
||||
0x0FFFFFF0,
|
||||
0x000000F0,
|
||||
0x00000F00,
|
||||
0x000FF000,
|
||||
0x00F00000,
|
||||
0x0F000000,
|
||||
0x0FFFFFF0,
|
||||
0x00000000,
|
||||
0x000FFF00,
|
||||
0x000F0000,
|
||||
0x000F0000,
|
||||
0x000F0000,
|
||||
0x000F0000,
|
||||
0x000F0000,
|
||||
0x000FFF00,
|
||||
0x00000000,
|
||||
0x0F000000,
|
||||
0x00F00000,
|
||||
0x000F0000,
|
||||
0x0000F000,
|
||||
0x00000F00,
|
||||
0x000000F0,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00FFF000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x00FFF000,
|
||||
0x00000000,
|
||||
0x000FF000,
|
||||
0x00F00F00,
|
||||
0x0F0000F0,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x0FFFFFF0,
|
||||
0x00000000,
|
||||
0x000FF000,
|
||||
0x000FF000,
|
||||
0x000F0000,
|
||||
0x0000F000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00FFFF00,
|
||||
0x0F000F00,
|
||||
0x0F000F00,
|
||||
0x0F000F00,
|
||||
0x00FFFFF0,
|
||||
0x00000000,
|
||||
0x00F00000,
|
||||
0x00F00000,
|
||||
0x00F00000,
|
||||
0x00FFFF00,
|
||||
0x00F000F0,
|
||||
0x00F000F0,
|
||||
0x00FFFF00,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00FFFF00,
|
||||
0x0F000000,
|
||||
0x0F000000,
|
||||
0x0F000000,
|
||||
0x00FFFF00,
|
||||
0x00000000,
|
||||
0x000000F0,
|
||||
0x000000F0,
|
||||
0x000000F0,
|
||||
0x000FFFF0,
|
||||
0x00F000F0,
|
||||
0x00F000F0,
|
||||
0x000FFFF0,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00FFFF00,
|
||||
0x0F0000F0,
|
||||
0x0FFFFFF0,
|
||||
0x0F000000,
|
||||
0x00FFFF00,
|
||||
0x00000000,
|
||||
0x0000FF00,
|
||||
0x000F0000,
|
||||
0x000F0000,
|
||||
0x0FFFFF00,
|
||||
0x000F0000,
|
||||
0x000F0000,
|
||||
0x000F0000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x000FFFF0,
|
||||
0x00F000F0,
|
||||
0x00F000F0,
|
||||
0x000FFFF0,
|
||||
0x000000F0,
|
||||
0x000FFF00,
|
||||
0x00000000,
|
||||
0x00F00000,
|
||||
0x00F00000,
|
||||
0x00F00000,
|
||||
0x00F0FF00,
|
||||
0x00FF00F0,
|
||||
0x00F000F0,
|
||||
0x00F000F0,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x0000F000,
|
||||
0x00000000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x00000000,
|
||||
0x00000F00,
|
||||
0x00000000,
|
||||
0x00000F00,
|
||||
0x00000F00,
|
||||
0x00000F00,
|
||||
0x00F00F00,
|
||||
0x000FF000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00F00000,
|
||||
0x00F00000,
|
||||
0x00F00F00,
|
||||
0x00F0F000,
|
||||
0x00FFF000,
|
||||
0x00F00F00,
|
||||
0x00000000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x00000F00,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00F0FF00,
|
||||
0x0F0F00F0,
|
||||
0x0F0F00F0,
|
||||
0x0F0F00F0,
|
||||
0x0F0F00F0,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00F0FF00,
|
||||
0x00FF00F0,
|
||||
0x00F000F0,
|
||||
0x00F000F0,
|
||||
0x00F000F0,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x000FFF00,
|
||||
0x00F000F0,
|
||||
0x00F000F0,
|
||||
0x00F000F0,
|
||||
0x000FFF00,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00FFF000,
|
||||
0x00F00F00,
|
||||
0x00F00F00,
|
||||
0x00FFF000,
|
||||
0x00F00000,
|
||||
0x00F00000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x000FFF00,
|
||||
0x00F00F00,
|
||||
0x00F00F00,
|
||||
0x000FFF00,
|
||||
0x00000F00,
|
||||
0x00000FF0,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00F0FFF0,
|
||||
0x00FF0000,
|
||||
0x00F00000,
|
||||
0x00F00000,
|
||||
0x00F00000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x000FFFF0,
|
||||
0x00F00000,
|
||||
0x000FFF00,
|
||||
0x000000F0,
|
||||
0x00FFFF00,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x0000F000,
|
||||
0x00FFFFF0,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x00000FF0,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00F000F0,
|
||||
0x00F000F0,
|
||||
0x00F000F0,
|
||||
0x00F000F0,
|
||||
0x000FFFF0,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00F000F0,
|
||||
0x00F000F0,
|
||||
0x00F000F0,
|
||||
0x000F0F00,
|
||||
0x0000F000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x0F0000F0,
|
||||
0x0F00F0F0,
|
||||
0x0F00F0F0,
|
||||
0x0F00F0F0,
|
||||
0x00FF0F00,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00F000F0,
|
||||
0x000F0F00,
|
||||
0x0000F000,
|
||||
0x000F0F00,
|
||||
0x00F000F0,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x0F000F00,
|
||||
0x0F000F00,
|
||||
0x00F00F00,
|
||||
0x000FFF00,
|
||||
0x00000F00,
|
||||
0x00FFF000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00FFFFF0,
|
||||
0x00000F00,
|
||||
0x0000F000,
|
||||
0x000F0000,
|
||||
0x00FFFFF0,
|
||||
0x00000000,
|
||||
0x00000F00,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x00FF0000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x00000F00,
|
||||
0x00000000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x00000000,
|
||||
0x000F0000,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x00000FF0,
|
||||
0x0000F000,
|
||||
0x0000F000,
|
||||
0x000F0000,
|
||||
0x00000000,
|
||||
0x00FF00FF,
|
||||
0x0F00FF00,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00FF0000,
|
||||
0x0FF00000,
|
||||
0xFFFFFFFF,
|
||||
0xFFFFF000,
|
||||
0xFFFFF000,
|
||||
0xFFF00000,
|
||||
0x00000000
|
||||
};
|
||||
251
src/dolphin/demo/DEMOInit.c
Normal file
251
src/dolphin/demo/DEMOInit.c
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
#include <dolphin.h>
|
||||
#include <dolphin/demo.h>
|
||||
#include <dolphin/gx.h>
|
||||
#include <dolphin/pad.h>
|
||||
#include <dolphin/vi.h>
|
||||
#include "game/init.h"
|
||||
|
||||
#include <dolphin/demoPriv.h>
|
||||
|
||||
extern unsigned char DemoStatEnable; // size: 0x1, address: 0x0
|
||||
|
||||
// .bss
|
||||
static struct _GXRenderModeObj rmodeobj; // size: 0x3C, address: 0x0
|
||||
|
||||
// .sdata
|
||||
static unsigned char DemoFirstFrame = 1; // size: 0x1, address: 0x0
|
||||
|
||||
// .sbss
|
||||
static void *DefaultFifo = NULL; // size: 0x4, address: 0x0
|
||||
static GXFifoObj *DefaultFifoObj = NULL; // size: 0x4, address: 0x4
|
||||
static struct _GXRenderModeObj *rmode; // size: 0x4, address: 0x8
|
||||
static int BypassWorkaround; // size: 0x4, address: 0xC
|
||||
static unsigned long FrameCount; // size: 0x4, address: 0x10
|
||||
static unsigned long FrameMissThreshold; // size: 0x4, address: 0x14
|
||||
|
||||
// functions
|
||||
static void __DEMOInitRenderMode(struct _GXRenderModeObj *mode);
|
||||
static void __DEMOInitMem();
|
||||
static void __DEMOInitGX();
|
||||
static void __DEMOInitVI();
|
||||
static void __DEMOInitForEmu();
|
||||
static void __BypassRetraceCallback();
|
||||
static void LoadMemInfo();
|
||||
|
||||
void DEMOInit(struct _GXRenderModeObj *mode)
|
||||
{
|
||||
OSInit();
|
||||
DVDInit();
|
||||
VIInit();
|
||||
DEMOPadInit();
|
||||
__DEMOInitRenderMode(mode);
|
||||
__DEMOInitMem();
|
||||
VIConfigure(rmode);
|
||||
DefaultFifo = OSAllocFromHeap(__OSCurrHeap, 0x40000);
|
||||
DefaultFifoObj = GXInit(DefaultFifo, 0x40000);
|
||||
__DEMOInitGX();
|
||||
__DEMOInitVI();
|
||||
}
|
||||
|
||||
static void __DEMOInitRenderMode(struct _GXRenderModeObj *mode)
|
||||
{
|
||||
if (mode != NULL) {
|
||||
rmode = mode;
|
||||
return;
|
||||
}
|
||||
switch (VIGetTvFormat()) {
|
||||
case VI_NTSC:
|
||||
rmode = &GXNtsc480IntDf;
|
||||
break;
|
||||
case VI_PAL:
|
||||
rmode = &GXPal528IntDf;
|
||||
break;
|
||||
case VI_MPAL:
|
||||
rmode = &GXMpal480IntDf;
|
||||
break;
|
||||
default:
|
||||
OSPanic(__FILE__, 0x1A6, "DEMOInit: invalid TV format\n");
|
||||
break;
|
||||
}
|
||||
GXAdjustForOverscan(rmode, &rmodeobj, 0, 0x10);
|
||||
rmode = &rmodeobj;
|
||||
}
|
||||
|
||||
static void __DEMOInitMem()
|
||||
{
|
||||
void *arenaLo = OSGetArenaLo();
|
||||
void *arenaHi = OSGetArenaHi();
|
||||
unsigned long fbSize = ((u16)(rmode->fbWidth + 15) & 0xFFF0) * rmode->xfbHeight * 2;
|
||||
|
||||
DemoFrameBuffer1 = (void *)(((u32)arenaLo + 0x1F) & 0xFFFFFFE0);
|
||||
DemoFrameBuffer2 = (void *)(((u32)DemoFrameBuffer1 + fbSize + 0x1F) & 0xFFFFFFE0);
|
||||
DemoCurrentBuffer = DemoFrameBuffer2;
|
||||
arenaLo = (void *)(((u32)DemoFrameBuffer2 + fbSize + 0x1F) & 0xFFFFFFE0);
|
||||
OSSetArenaLo(arenaLo);
|
||||
if (((OSGetConsoleType() + 0xF0000000) == 4U) && ((OSGetPhysicalMemSize() + 0xFFC00000) != 0U)
|
||||
&& (OSGetConsoleSimulatedMemSize() < 0x01800000U)) {
|
||||
LoadMemInfo();
|
||||
return;
|
||||
}
|
||||
arenaLo = OSGetArenaLo();
|
||||
arenaHi = OSGetArenaHi();
|
||||
arenaLo = OSInitAlloc(arenaLo, arenaHi, 1);
|
||||
OSSetArenaLo(arenaLo);
|
||||
arenaLo = (void *)(((u32)arenaLo + 0x1F) & 0xFFFFFFE0);
|
||||
arenaHi = (void *)((u32)arenaHi & 0xFFFFFFE0);
|
||||
OSSetCurrentHeap(OSCreateHeap((void *)(((u32)arenaLo)), arenaHi));
|
||||
OSSetArenaLo((arenaLo = arenaHi));
|
||||
}
|
||||
|
||||
static void __DEMOInitGX()
|
||||
{
|
||||
GXSetViewport(0.0f, 0.0f, rmode->fbWidth, rmode->xfbHeight, 0.0f, 1.0f);
|
||||
GXSetScissor(0, 0, rmode->fbWidth, rmode->efbHeight);
|
||||
GXSetDispCopySrc(0, 0, rmode->fbWidth, rmode->efbHeight);
|
||||
GXSetDispCopyDst(rmode->fbWidth, rmode->xfbHeight);
|
||||
GXSetDispCopyYScale(((f32)rmode->xfbHeight / (f32)rmode->efbHeight));
|
||||
GXSetCopyFilter(rmode->aa, rmode->sample_pattern, 1, rmode->vfilter);
|
||||
if (rmode->aa != 0) {
|
||||
GXSetPixelFmt(2, 0);
|
||||
}
|
||||
else {
|
||||
GXSetPixelFmt(0, 0);
|
||||
}
|
||||
GXCopyDisp(DemoCurrentBuffer, 1);
|
||||
GXSetDispCopyGamma(0);
|
||||
}
|
||||
|
||||
static void __DEMOInitVI()
|
||||
{
|
||||
unsigned long nin;
|
||||
|
||||
VISetNextFrameBuffer(DemoFrameBuffer1);
|
||||
DemoCurrentBuffer = DemoFrameBuffer2;
|
||||
VIFlush();
|
||||
VIWaitForRetrace();
|
||||
nin = rmode->viTVmode & 1;
|
||||
if (nin != 0) {
|
||||
VIWaitForRetrace();
|
||||
}
|
||||
}
|
||||
|
||||
static void __DEMOInitForEmu() { }
|
||||
|
||||
void DEMOBeforeRender()
|
||||
{
|
||||
if (BypassWorkaround != 0) {
|
||||
GXSetDrawSync(0xFEEB);
|
||||
}
|
||||
if (rmode->field_rendering != 0) {
|
||||
GXSetViewportJitter(0.0f, 0.0f, rmode->fbWidth, rmode->xfbHeight, 0.0f, 1.0f, VIGetNextField());
|
||||
}
|
||||
else {
|
||||
GXSetViewport(0.0f, 0.0f, rmode->fbWidth, rmode->xfbHeight, 0.0f, 1.0f);
|
||||
}
|
||||
GXInvalidateVtxCache();
|
||||
GXInvalidateTexAll();
|
||||
}
|
||||
|
||||
void DEMOSwapBuffers()
|
||||
{
|
||||
VISetNextFrameBuffer(DemoCurrentBuffer);
|
||||
if (DemoFirstFrame != 0) {
|
||||
VISetBlack(0);
|
||||
DemoFirstFrame = 0;
|
||||
}
|
||||
VIFlush();
|
||||
VIWaitForRetrace();
|
||||
if ((u32)DemoCurrentBuffer == (u32)DemoFrameBuffer1) {
|
||||
DemoCurrentBuffer = DemoFrameBuffer2;
|
||||
return;
|
||||
}
|
||||
DemoCurrentBuffer = DemoFrameBuffer1;
|
||||
}
|
||||
|
||||
struct _GXRenderModeObj *DEMOGetRenderModeObj()
|
||||
{
|
||||
return rmode;
|
||||
}
|
||||
|
||||
u32 DEMOGetCurrentBuffer(void)
|
||||
{
|
||||
return (u32)DemoCurrentBuffer;
|
||||
}
|
||||
|
||||
void DEMOEnableBypassWorkaround(unsigned long timeoutFrames)
|
||||
{
|
||||
BypassWorkaround = 1;
|
||||
FrameMissThreshold = timeoutFrames;
|
||||
VISetPreRetraceCallback(__BypassRetraceCallback);
|
||||
}
|
||||
|
||||
static void __BypassRetraceCallback()
|
||||
{
|
||||
FrameCount += 1;
|
||||
}
|
||||
|
||||
static void LoadMemInfo()
|
||||
{
|
||||
void *arenaHiOld;
|
||||
void *arenaLo;
|
||||
void *arenaHi;
|
||||
void *simMemEnd;
|
||||
struct DVDFileInfo fileInfo;
|
||||
unsigned long length;
|
||||
unsigned long transferLength;
|
||||
long offset;
|
||||
unsigned long i;
|
||||
unsigned long indexMax;
|
||||
char *buf[63];
|
||||
struct {
|
||||
void *start;
|
||||
void *end;
|
||||
} *memEntry;
|
||||
|
||||
OSReport("\nNow, try to find memory info file...\n\n");
|
||||
if (!DVDOpen("/meminfo.bin", &fileInfo)) {
|
||||
OSReport("\nCan't find memory info file. Use /XXX toolname/ to maximize available\n");
|
||||
OSReport("memory space. For now, we only use the first %dMB.\n", OSGetConsoleSimulatedMemSize() >> 0x14);
|
||||
arenaLo = OSGetArenaLo();
|
||||
arenaHi = OSGetArenaHi();
|
||||
arenaLo = OSInitAlloc(arenaLo, arenaHi, 1);
|
||||
OSSetArenaLo(arenaLo);
|
||||
arenaLo = (void *)(((u32)arenaLo + 0x1F) & 0xFFFFFFE0);
|
||||
arenaHi = (void *)((u32)arenaHi & 0xFFFFFFE0);
|
||||
OSSetCurrentHeap(OSCreateHeap((void *)(((u32)arenaLo)), arenaHi));
|
||||
OSSetArenaLo((arenaLo = arenaHi));
|
||||
return;
|
||||
}
|
||||
memEntry = (void *)((u32)buf + 0x1F & 0xFFFFFFE0);
|
||||
arenaHiOld = OSGetArenaHi();
|
||||
simMemEnd = OSPhysicalToCached(OSGetConsoleSimulatedMemSize());
|
||||
OSSetArenaHi(OSPhysicalToCached(OSGetPhysicalMemSize()));
|
||||
arenaLo = OSGetArenaLo();
|
||||
arenaHi = OSGetArenaHi();
|
||||
arenaLo = OSInitAlloc(arenaLo, arenaHi, 1);
|
||||
OSSetArenaLo(arenaLo);
|
||||
arenaLo = (void *)(((u32)arenaLo + 0x1F) & 0xFFFFFFE0);
|
||||
arenaHi = (void *)((u32)arenaHi & 0xFFFFFFE0);
|
||||
OSSetCurrentHeap(OSCreateHeap((void *)(arenaLo), arenaHi));
|
||||
OSSetArenaLo((arenaLo = arenaHi));
|
||||
OSAllocFixed(&arenaHiOld, &simMemEnd);
|
||||
length = fileInfo.length;
|
||||
offset = 0;
|
||||
while (length) {
|
||||
OSReport("loop\n");
|
||||
transferLength = (length < 0x20) ? length : 0x20;
|
||||
if (DVDReadPrio(&fileInfo, memEntry, (transferLength + 0x1F) & 0xFFFFFFE0, offset, 2) < 0) {
|
||||
OSPanic(__FILE__, 0x49F, "An error occurred when issuing read to /meminfo.bin\n");
|
||||
}
|
||||
indexMax = (transferLength / 8);
|
||||
for (i = 0; i < indexMax; i++) {
|
||||
OSReport("start: 0x%08x, end: 0x%08x\n", memEntry[i].start, memEntry[i].end);
|
||||
OSAllocFixed(&memEntry[i].start, &memEntry[i].end);
|
||||
OSReport("Removed 0x%08x - 0x%08x from the current heap\n", memEntry[i].start, (char *)memEntry[i].end - 1);
|
||||
}
|
||||
length -= transferLength;
|
||||
offset += transferLength;
|
||||
}
|
||||
DVDClose(&fileInfo);
|
||||
OSDumpHeap(__OSCurrHeap);
|
||||
}
|
||||
146
src/dolphin/demo/DEMOPuts.c
Normal file
146
src/dolphin/demo/DEMOPuts.c
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
#include "stdarg.h"
|
||||
#include "stdio.h"
|
||||
#include <dolphin.h>
|
||||
#include <dolphin/demo.h>
|
||||
#include <dolphin/gx.h>
|
||||
#include <dolphin/mtx.h>
|
||||
|
||||
#include <dolphin/demoPriv.h>
|
||||
|
||||
extern unsigned long DEMOFontBitmap[]; // size: 0x0, address: 0x0
|
||||
|
||||
// .bss
|
||||
static struct _GXTexObj fontTexObj; // size: 0x20, address: 0x0
|
||||
|
||||
// .sbss
|
||||
static long fontShift; // size: 0x4, address: 0x0
|
||||
|
||||
// functions
|
||||
static void DrawFontChar(int x, int y, int z, int xChar, int yChar);
|
||||
static void LoadSheet(void *image, enum _GXTexMapID texMapID);
|
||||
|
||||
void DEMOSetFontType(DMFontType attr)
|
||||
{
|
||||
switch (attr) {
|
||||
case DM_FT_RVS:
|
||||
GXSetBlendMode(2, 0, 0, 0xC);
|
||||
break;
|
||||
case DM_FT_XLU:
|
||||
GXSetBlendMode(1, 1, 1, 0);
|
||||
break;
|
||||
case DM_FT_OPQ:
|
||||
default:
|
||||
GXSetBlendMode(1, 1, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DEMOLoadFont(enum _GXTexMapID texMap, enum _GXTexMtx texMtx, DMTexFlt texFlt)
|
||||
{
|
||||
// float fontTMtx[3][4];
|
||||
// unsigned short width;
|
||||
// unsigned short height;
|
||||
|
||||
// width = 64;
|
||||
// height = 0x1800 / width;
|
||||
// GXInitTexObj(&fontTexObj, (void *)DEMOFontBitmap, width, (u16)height, 0, 0, 0, 0);
|
||||
// if (texFlt == 0) {
|
||||
// GXInitTexObjLOD(&fontTexObj, 0, 0, 0, 0, 0, 0.0f, 0.0f, 0.0f);
|
||||
// fontShift = 0;
|
||||
// }
|
||||
// GXLoadTexObj(&fontTexObj, texMap);
|
||||
// MTXScale(fontTMtx, 1.0f / (width - fontShift), 1.0f / ((u16)height - !fontShift), 1.0f);
|
||||
// GXLoadTexMtxImm(fontTMtx, texMtx, 1);
|
||||
// GXSetNumTexGens(1);
|
||||
// GXSetTexCoordGen(0, 1, 4, texMtx);
|
||||
}
|
||||
|
||||
void DEMOSetupScrnSpc(long width, long height, float depth)
|
||||
{
|
||||
float pMtx[4][4];
|
||||
float mMtx[3][4];
|
||||
|
||||
MTXOrtho(pMtx, 0.0f, height, 0.0f, width, 0.0f, -depth);
|
||||
GXSetProjection(pMtx, 1);
|
||||
MTXIdentity(mMtx);
|
||||
GXLoadPosMtxImm(mMtx, 0);
|
||||
GXSetCurrentMtx(0);
|
||||
}
|
||||
|
||||
void DEMOInitCaption(long font_type, long width, long height)
|
||||
{
|
||||
DEMOSetupScrnSpc(width, height, 100.0f);
|
||||
GXSetZMode(1, 7, 1);
|
||||
GXSetNumChans(0);
|
||||
GXSetNumTevStages(1);
|
||||
GXSetTevOp(0, 3);
|
||||
GXSetTevOrder(0, 0, 0, 0xFF);
|
||||
DEMOLoadFont(0, 0x1E, 0);
|
||||
DEMOSetFontType(font_type);
|
||||
}
|
||||
|
||||
void DEMOPuts(s16 x, s16 y, s16 z, char *string)
|
||||
{
|
||||
char *str;
|
||||
long s;
|
||||
long t;
|
||||
long c;
|
||||
long w;
|
||||
long len;
|
||||
long i;
|
||||
|
||||
str = string;
|
||||
GXClearVtxDesc();
|
||||
GXSetVtxDesc(9, 1);
|
||||
GXSetVtxDesc(0xD, 1);
|
||||
GXSetVtxAttrFmt(0, 9, 1, 3, 0);
|
||||
GXSetVtxAttrFmt(0, 0xD, 1, 3, 1);
|
||||
|
||||
// calc len
|
||||
len = 0;
|
||||
while (1) {
|
||||
c = *(str++);
|
||||
if ((c >= 0x20) && (c <= 0x7F)) {
|
||||
len++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
GXBegin(0x80, 0, len * 4);
|
||||
for (i = 0; i < len; i++) {
|
||||
w = string[i] - 0x20;
|
||||
s = fontShift + ((w % 8) * 0x10);
|
||||
t = fontShift + ((w / 8) * 0x10);
|
||||
GXPosition3s16(x + (i * 8), y, z);
|
||||
GXTexCoord2s16(s, t);
|
||||
GXPosition3s16(x + (i * 8) + 8, y, z);
|
||||
GXTexCoord2s16(s + 0x10, t);
|
||||
GXPosition3s16(x + (i * 8) + 8, y + 8, z);
|
||||
GXTexCoord2s16(s + 0x10, t + 0x10);
|
||||
GXPosition3s16(x + (i * 8), y + 8, z);
|
||||
GXTexCoord2s16(s, t + 0x10);
|
||||
}
|
||||
GXEnd();
|
||||
len = 0;
|
||||
}
|
||||
|
||||
string = str;
|
||||
if (c == 0xA) {
|
||||
y += 0x8;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DEMOPrintf(s16 x, s16 y, s16 z, char *fmt, ...)
|
||||
{
|
||||
va_list vlist;
|
||||
char buf[256];
|
||||
|
||||
va_start(vlist, fmt);
|
||||
vsprintf(buf, fmt, vlist);
|
||||
DEMOPuts(x, y, z, buf);
|
||||
va_end(vlist);
|
||||
}
|
||||
424
src/dolphin/demo/DEMOStats.c
Normal file
424
src/dolphin/demo/DEMOStats.c
Normal file
|
|
@ -0,0 +1,424 @@
|
|||
#include "dolphin/gx/GXPerf.h"
|
||||
#include "string.h"
|
||||
#include <dolphin.h>
|
||||
#include <dolphin/demo.h>
|
||||
#include <dolphin/gx.h>
|
||||
|
||||
#include <dolphin/demoPriv.h>
|
||||
|
||||
unsigned char DemoStatEnable = 0;
|
||||
static DemoStatData *DemoStat;
|
||||
static unsigned long DemoStatIndx;
|
||||
static unsigned long DemoStatMaxIndx;
|
||||
static unsigned long DemoStatClocks;
|
||||
static unsigned long DemoStatDisp;
|
||||
static unsigned long DemoStatStrLen;
|
||||
static unsigned long topPixIn;
|
||||
static unsigned long topPixOut;
|
||||
static unsigned long botPixIn;
|
||||
static unsigned long botPixOut;
|
||||
static unsigned long clrPixIn;
|
||||
static unsigned long copyClks;
|
||||
static unsigned long vcCheck;
|
||||
static unsigned long vcMiss;
|
||||
static unsigned long vcStall;
|
||||
static unsigned long cpReq;
|
||||
static unsigned long tcReq;
|
||||
static unsigned long cpuRdReq;
|
||||
static unsigned long cpuWrReq;
|
||||
static unsigned long dspReq;
|
||||
static unsigned long ioReq;
|
||||
static unsigned long viReq;
|
||||
static unsigned long peReq;
|
||||
static unsigned long rfReq;
|
||||
static unsigned long fiReq;
|
||||
|
||||
// functions
|
||||
static void DEMOWriteStats(unsigned char update);
|
||||
static void DEMOWriteStats(unsigned char update);
|
||||
|
||||
void DEMOSetStats(DemoStatData *stat, unsigned long nstats, DEMO_STAT_DISP disp)
|
||||
{
|
||||
if (!stat || nstats == 0) {
|
||||
DemoStatEnable = FALSE;
|
||||
}
|
||||
else {
|
||||
DemoStatEnable = TRUE;
|
||||
DemoStat = stat;
|
||||
DemoStatIndx = 0;
|
||||
DemoStatMaxIndx = nstats;
|
||||
DemoStatDisp = disp;
|
||||
DemoStatStrLen = strlen(DemoStat->text);
|
||||
}
|
||||
}
|
||||
|
||||
static void DEMOWriteStats(unsigned char update)
|
||||
{
|
||||
unsigned long cnt0;
|
||||
unsigned long cnt1;
|
||||
unsigned long cnt2;
|
||||
unsigned long cnt3;
|
||||
unsigned long cnt4;
|
||||
unsigned long cnt5;
|
||||
unsigned long cnt6;
|
||||
unsigned long cnt7;
|
||||
unsigned long cnt8;
|
||||
unsigned long cnt9;
|
||||
|
||||
switch (DemoStat[DemoStatIndx].stat_type) {
|
||||
case DEMO_STAT_GP0:
|
||||
if (update) {
|
||||
cnt0 = GXReadGP0Metric();
|
||||
DemoStat[DemoStatIndx].count = cnt0;
|
||||
GXSetGPMetric(GX_PERF0_NONE, GX_PERF1_NONE);
|
||||
break;
|
||||
}
|
||||
GXSetGPMetric(DemoStat[DemoStatIndx].stat, GX_PERF1_NONE);
|
||||
GXClearGPMetric();
|
||||
break;
|
||||
case DEMO_STAT_GP1:
|
||||
if (update) {
|
||||
cnt0 = GXReadGP1Metric();
|
||||
DemoStat[DemoStatIndx].count = cnt0;
|
||||
GXSetGPMetric(GX_PERF0_NONE, GX_PERF1_NONE);
|
||||
break;
|
||||
}
|
||||
GXSetGPMetric(GX_PERF0_NONE, DemoStat[DemoStatIndx].stat);
|
||||
GXClearGPMetric();
|
||||
break;
|
||||
case DEMO_STAT_MEM:
|
||||
if (update) {
|
||||
GXReadMemMetric(&cnt0, &cnt1, &cnt2, &cnt3, &cnt4, &cnt5, &cnt6, &cnt7, &cnt8, &cnt9);
|
||||
cpReq = cnt0;
|
||||
tcReq = cnt1;
|
||||
cpuRdReq = cnt2;
|
||||
cpuWrReq = cnt3;
|
||||
dspReq = cnt4;
|
||||
ioReq = cnt5;
|
||||
viReq = cnt6;
|
||||
peReq = cnt7;
|
||||
rfReq = cnt8;
|
||||
fiReq = cnt9;
|
||||
break;
|
||||
}
|
||||
GXClearMemMetric();
|
||||
break;
|
||||
case DEMO_STAT_PIX:
|
||||
if (update) {
|
||||
GXReadPixMetric(&cnt0, &cnt1, &cnt2, &cnt3, &cnt4, &cnt5);
|
||||
topPixIn = cnt0;
|
||||
topPixOut = cnt1;
|
||||
botPixIn = cnt2;
|
||||
botPixOut = cnt3;
|
||||
clrPixIn = cnt4;
|
||||
copyClks = cnt5;
|
||||
break;
|
||||
}
|
||||
GXClearPixMetric();
|
||||
break;
|
||||
case DEMO_STAT_VC:
|
||||
if (update) {
|
||||
GXReadVCacheMetric(&cnt0, &cnt1, &cnt2);
|
||||
vcCheck = cnt0;
|
||||
vcMiss = cnt1;
|
||||
vcStall = cnt2;
|
||||
break;
|
||||
}
|
||||
GXSetVCacheMetric(GX_VC_POS);
|
||||
GXClearVCacheMetric();
|
||||
break;
|
||||
case DEMO_STAT_FR:
|
||||
if (update) {
|
||||
GXReadPixMetric(&cnt0, &cnt1, &cnt2, &cnt3, &cnt4, &cnt5);
|
||||
topPixIn = cnt0;
|
||||
topPixOut = cnt1;
|
||||
botPixIn = cnt2;
|
||||
botPixOut = cnt3;
|
||||
clrPixIn = cnt4;
|
||||
copyClks = cnt5;
|
||||
DemoStatClocks = GXReadGP0Metric();
|
||||
GXSetGPMetric(GX_PERF0_NONE, GX_PERF1_NONE);
|
||||
break;
|
||||
}
|
||||
GXClearPixMetric();
|
||||
GXSetGPMetric(GX_PERF0_CLOCKS, GX_PERF1_NONE);
|
||||
GXClearGPMetric();
|
||||
break;
|
||||
case DEMO_STAT_TBW:
|
||||
case DEMO_STAT_TBP:
|
||||
GXClearPixMetric();
|
||||
if (update) {
|
||||
GXReadPixMetric(&cnt0, &cnt1, &cnt2, &cnt3, &cnt4, &cnt5);
|
||||
topPixIn = cnt0;
|
||||
topPixOut = cnt1;
|
||||
botPixIn = cnt2;
|
||||
botPixOut = cnt3;
|
||||
clrPixIn = cnt4;
|
||||
copyClks = cnt5;
|
||||
DemoStatClocks = GXReadGP0Metric(cnt4, cnt3, cnt2, cnt1, cnt0);
|
||||
GXReadMemMetric(&cnt0, &cnt1, &cnt2, &cnt3, &cnt4, &cnt5, &cnt6, &cnt7, &cnt8, &cnt9);
|
||||
tcReq = cnt1;
|
||||
GXSetGPMetric(GX_PERF0_NONE, GX_PERF1_NONE);
|
||||
break;
|
||||
}
|
||||
GXClearMemMetric();
|
||||
GXSetGPMetric(GX_PERF0_CLOCKS, GX_PERF1_NONE);
|
||||
GXClearGPMetric();
|
||||
break;
|
||||
case DEMO_STAT_MYC:
|
||||
case DEMO_STAT_MYR:
|
||||
break;
|
||||
default:
|
||||
OSPanic("DEMOStats.c", 0x127, "DEMOSetStats: Unknown demo stat type\n");
|
||||
}
|
||||
}
|
||||
|
||||
void DEMOUpdateStats(unsigned char inc)
|
||||
{
|
||||
DEMOWriteStats(inc);
|
||||
if (inc) {
|
||||
DemoStatIndx = DemoStatIndx + 1;
|
||||
if (DemoStatIndx == DemoStatMaxIndx) {
|
||||
DemoStatIndx = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DEMOPrintStats(void)
|
||||
{
|
||||
GXRenderModeObj *rmode;
|
||||
unsigned long i;
|
||||
signed short text_x;
|
||||
signed short text_y;
|
||||
signed short text_yinc;
|
||||
unsigned short wd;
|
||||
unsigned short ht;
|
||||
float rate;
|
||||
|
||||
if (DemoStatDisp == DEMO_STAT_IO) {
|
||||
for (i = 0; i < DemoStatMaxIndx; i++) {
|
||||
switch (DemoStat[i].stat_type) {
|
||||
case DEMO_STAT_PIX:
|
||||
switch (DemoStat[i].stat) {
|
||||
case 0:
|
||||
OSReport("%s: %8d\n", DemoStat[i].text, topPixIn);
|
||||
break;
|
||||
case 1:
|
||||
OSReport("%s: %8d\n", DemoStat[i].text, topPixOut);
|
||||
break;
|
||||
case 2:
|
||||
OSReport("%s: %8d\n", DemoStat[i].text, botPixIn);
|
||||
break;
|
||||
case 3:
|
||||
OSReport("%s: %8d\n", DemoStat[i].text, botPixOut);
|
||||
break;
|
||||
case 4:
|
||||
OSReport("%s: %8d\n", DemoStat[i].text, clrPixIn);
|
||||
break;
|
||||
case 5:
|
||||
OSReport("%s: %8d\n", DemoStat[i].text, copyClks);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case DEMO_STAT_FR:
|
||||
rate = 162.0F * (topPixIn + botPixIn) / (float)(DemoStatClocks - copyClks);
|
||||
OSReport("%s: %8.2f\n", DemoStat[i].text, rate);
|
||||
break;
|
||||
case DEMO_STAT_TBW:
|
||||
rate = 162.0F * (tcReq << 5) / (float)(DemoStatClocks - copyClks);
|
||||
OSReport("%s: %8.2f\n", DemoStat[i].text, rate);
|
||||
break;
|
||||
case DEMO_STAT_TBP:
|
||||
rate = (tcReq << 5) / (float)(topPixIn + botPixIn);
|
||||
OSReport("%s: %8.2f\n", DemoStat[i].text, rate);
|
||||
break;
|
||||
case DEMO_STAT_VC:
|
||||
switch (DemoStat[i].stat) {
|
||||
case 0:
|
||||
OSReport("%s: %8d\n", DemoStat[i].text, vcCheck);
|
||||
break;
|
||||
case 1:
|
||||
OSReport("%s: %8d\n", DemoStat[i].text, vcMiss);
|
||||
break;
|
||||
case 2:
|
||||
OSReport("%s: %8d\n", DemoStat[i].text, vcStall);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case DEMO_STAT_MYR:
|
||||
rate = DemoStat[i].stat / (float)DemoStat[i].count;
|
||||
OSReport("%s: %8.2f\n", DemoStat[i].text, rate);
|
||||
break;
|
||||
case DEMO_STAT_MEM:
|
||||
switch (DemoStat[i].stat) {
|
||||
case 0:
|
||||
OSReport("%s: %8d\n", DemoStat[i].text, cpReq);
|
||||
break;
|
||||
case 1:
|
||||
OSReport("%s: %8d\n", DemoStat[i].text, tcReq);
|
||||
break;
|
||||
case 2:
|
||||
OSReport("%s: %8d\n", DemoStat[i].text, cpuRdReq);
|
||||
break;
|
||||
case 3:
|
||||
OSReport("%s: %8d\n", DemoStat[i].text, cpuWrReq);
|
||||
break;
|
||||
case 4:
|
||||
OSReport("%s: %8d\n", DemoStat[i].text, dspReq);
|
||||
break;
|
||||
case 5:
|
||||
OSReport("%s: %8d\n", DemoStat[i].text, ioReq);
|
||||
break;
|
||||
case 6:
|
||||
OSReport("%s: %8d\n", DemoStat[i].text, viReq);
|
||||
break;
|
||||
case 7:
|
||||
OSReport("%s: %8d\n", DemoStat[i].text, peReq);
|
||||
break;
|
||||
case 8:
|
||||
OSReport("%s: %8d\n", DemoStat[i].text, rfReq);
|
||||
break;
|
||||
case 9:
|
||||
OSReport("%s: %8d\n", DemoStat[i].text, fiReq);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
OSReport("%s: %8d\n", DemoStat[i].text, DemoStat[i].count);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
rmode = DEMOGetRenderModeObj();
|
||||
switch (DemoStatDisp) {
|
||||
case DEMO_STAT_TL:
|
||||
text_x = 0x10;
|
||||
text_y = 0x10;
|
||||
text_yinc = 0xA;
|
||||
wd = rmode->fbWidth;
|
||||
ht = rmode->xfbHeight;
|
||||
break;
|
||||
case DEMO_STAT_BL:
|
||||
text_x = 0x10;
|
||||
text_y = rmode->xfbHeight - 0x18;
|
||||
text_yinc = -0xA;
|
||||
wd = rmode->fbWidth;
|
||||
ht = rmode->xfbHeight;
|
||||
break;
|
||||
case DEMO_STAT_TLD:
|
||||
text_x = 8;
|
||||
text_y = 8;
|
||||
text_yinc = 9;
|
||||
wd = rmode->fbWidth / 2;
|
||||
ht = rmode->xfbHeight / 2;
|
||||
break;
|
||||
case DEMO_STAT_BLD:
|
||||
text_x = 8;
|
||||
text_y = (rmode->xfbHeight - 0x18) / 2;
|
||||
text_yinc = -9;
|
||||
wd = rmode->fbWidth / 2;
|
||||
ht = rmode->xfbHeight / 2;
|
||||
break;
|
||||
}
|
||||
DEMOInitCaption(0, wd, ht);
|
||||
for (i = 0; i < DemoStatMaxIndx; i++) {
|
||||
switch (DemoStat[i].stat_type) {
|
||||
case DEMO_STAT_PIX:
|
||||
switch (DemoStat[i].stat) {
|
||||
case 0:
|
||||
DEMOPrintf(text_x, text_y, 0, "%s: %8d\n", DemoStat[i].text, topPixIn);
|
||||
break;
|
||||
case 1:
|
||||
DEMOPrintf(text_x, text_y, 0, "%s: %8d\n", DemoStat[i].text, topPixOut);
|
||||
break;
|
||||
case 2:
|
||||
DEMOPrintf(text_x, text_y, 0, "%s: %8d\n", DemoStat[i].text, botPixIn);
|
||||
break;
|
||||
case 3:
|
||||
DEMOPrintf(text_x, text_y, 0, "%s: %8d\n", DemoStat[i].text, botPixOut);
|
||||
break;
|
||||
case 4:
|
||||
DEMOPrintf(text_x, text_y, 0, "%s: %8d\n", DemoStat[i].text, clrPixIn);
|
||||
break;
|
||||
case 5:
|
||||
DEMOPrintf(text_x, text_y, 0, "%s: %8d\n", DemoStat[i].text, copyClks);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case DEMO_STAT_FR:
|
||||
rate = 162.0F * (topPixIn + botPixIn) / (float)(DemoStatClocks - copyClks);
|
||||
DEMOPrintf(text_x, text_y, 0, "%s: %8.2f\n", DemoStat[i].text, rate);
|
||||
break;
|
||||
case DEMO_STAT_TBW:
|
||||
rate = 162.0F * (tcReq << 5) / (float)(DemoStatClocks - copyClks);
|
||||
DEMOPrintf(text_x, text_y, 0, "%s: %8.2f\n", DemoStat[i].text, rate);
|
||||
break;
|
||||
case DEMO_STAT_TBP:
|
||||
rate = (tcReq << 5) / (float)(topPixIn - botPixIn);
|
||||
DEMOPrintf(text_x, text_y, 0, "%s: %8.3f\n", DemoStat[i].text, rate);
|
||||
break;
|
||||
case DEMO_STAT_VC:
|
||||
switch (DemoStat[i].stat) {
|
||||
case 0:
|
||||
DEMOPrintf(text_x, text_y, 0, "%s: %8d\n", DemoStat[i].text, vcCheck);
|
||||
break;
|
||||
case 1:
|
||||
DEMOPrintf(text_x, text_y, 0, "%s: %8d\n", DemoStat[i].text, vcMiss);
|
||||
break;
|
||||
case 2:
|
||||
DEMOPrintf(text_x, text_y, 0, "%s: %8d\n", DemoStat[i].text, vcStall);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case DEMO_STAT_MEM:
|
||||
switch (DemoStat[i].stat) {
|
||||
case 0:
|
||||
DEMOPrintf(text_x, text_y, 0, "%s: %8d\n", DemoStat[i].text, cpReq);
|
||||
break;
|
||||
case 1:
|
||||
DEMOPrintf(text_x, text_y, 0, "%s: %8d\n", DemoStat[i].text, tcReq);
|
||||
break;
|
||||
case 2:
|
||||
DEMOPrintf(text_x, text_y, 0, "%s: %8d\n", DemoStat[i].text, cpuRdReq);
|
||||
break;
|
||||
case 3:
|
||||
DEMOPrintf(text_x, text_y, 0, "%s: %8d\n", DemoStat[i].text, cpuWrReq);
|
||||
break;
|
||||
case 4:
|
||||
DEMOPrintf(text_x, text_y, 0, "%s: %8d\n", DemoStat[i].text, dspReq);
|
||||
break;
|
||||
case 5:
|
||||
DEMOPrintf(text_x, text_y, 0, "%s: %8d\n", DemoStat[i].text, ioReq);
|
||||
break;
|
||||
case 6:
|
||||
DEMOPrintf(text_x, text_y, 0, "%s: %8d\n", DemoStat[i].text, viReq);
|
||||
break;
|
||||
case 7:
|
||||
DEMOPrintf(text_x, text_y, 0, "%s: %8d\n", DemoStat[i].text, peReq);
|
||||
break;
|
||||
case 8:
|
||||
DEMOPrintf(text_x, text_y, 0, "%s: %8d\n", DemoStat[i].text, rfReq);
|
||||
break;
|
||||
case 9:
|
||||
DEMOPrintf(text_x, text_y, 0, "%s: %8d\n", DemoStat[i].text, fiReq);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case DEMO_STAT_GP0:
|
||||
case DEMO_STAT_GP1:
|
||||
case DEMO_STAT_MYC:
|
||||
DEMOPrintf(text_x, text_y, 0, "%s: %8d", DemoStat[i].text, DemoStat[i].count);
|
||||
break;
|
||||
case DEMO_STAT_MYR:
|
||||
rate = DemoStat[i].stat / (float)DemoStat[i].count;
|
||||
DEMOPrintf(text_x, text_y, 0, "%s: %8.3f", DemoStat[i].text, rate);
|
||||
break;
|
||||
default:
|
||||
OSReport("Undefined stat type %d in DEMOPrintStats()\n", DemoStat[i].stat_type);
|
||||
break;
|
||||
}
|
||||
text_y += text_yinc;
|
||||
}
|
||||
}
|
||||
}
|
||||
99
src/dolphin/dsp/dsp.c
Normal file
99
src/dolphin/dsp/dsp.c
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
#include "dolphin/dsp.h"
|
||||
#include "dolphin/os.h"
|
||||
|
||||
#include "dolphin/hw_regs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static s32 __DSP_init_flag = 0;
|
||||
extern DSPTaskInfo* __DSP_tmp_task;
|
||||
extern DSPTaskInfo* __DSP_last_task;
|
||||
extern DSPTaskInfo* __DSP_first_task;
|
||||
extern DSPTaskInfo* __DSP_curr_task;
|
||||
|
||||
extern void __DSPHandler(__OSInterrupt, OSContext*);
|
||||
extern void __DSP_debug_printf(const char* fmt, ...);
|
||||
extern void __DSP_boot_task(DSPTaskInfo* task);
|
||||
|
||||
u32 DSPCheckMailToDSP(void) { return (__DSPRegs[0] >> 0xF) & 1; }
|
||||
|
||||
u32 DSPCheckMailFromDSP(void) { return (__DSPRegs[2] >> 0xF) & 1; }
|
||||
|
||||
u32 DSPReadMailFromDSP() {
|
||||
u16 reg1;
|
||||
u16 reg2;
|
||||
reg1 = __DSPRegs[2];
|
||||
reg2 = __DSPRegs[3];
|
||||
return reg1 << 16 | reg2;
|
||||
}
|
||||
|
||||
void DSPSendMailToDSP(u32 mail) {
|
||||
__DSPRegs[0] = mail >> 16;
|
||||
__DSPRegs[1] = mail;
|
||||
}
|
||||
|
||||
void DSPInit(void) {
|
||||
u32 oldInt;
|
||||
u16 reg;
|
||||
__DSP_debug_printf("DSPInit(): Build Date: %s %s\n", "Dec 17 2001", "18:25:00");
|
||||
|
||||
if (__DSP_init_flag == 1) {
|
||||
return;
|
||||
}
|
||||
oldInt = OSDisableInterrupts();
|
||||
__OSSetInterruptHandler(7, __DSPHandler);
|
||||
__OSUnmaskInterrupts(0x1000000);
|
||||
reg = __DSPRegs[5];
|
||||
reg = (reg & ~0xA8) | 0x800;
|
||||
__DSPRegs[5] = reg;
|
||||
reg = __DSPRegs[5];
|
||||
reg = reg & ~0xAC;
|
||||
__DSPRegs[5] = reg;
|
||||
__DSP_tmp_task = 0;
|
||||
__DSP_curr_task = 0;
|
||||
__DSP_last_task = 0;
|
||||
__DSP_first_task = 0;
|
||||
__DSP_init_flag = 1;
|
||||
OSRestoreInterrupts(oldInt);
|
||||
}
|
||||
|
||||
void DSPReset(void) {
|
||||
u16 reg;
|
||||
u32 oldInt;
|
||||
oldInt = OSDisableInterrupts();
|
||||
reg = __DSPRegs[5];
|
||||
__DSPRegs[5] = (reg & ~0xA8) | 0x801;
|
||||
__DSP_init_flag = 0;
|
||||
OSRestoreInterrupts(oldInt);
|
||||
}
|
||||
|
||||
void DSPHalt(void) {
|
||||
u16 reg;
|
||||
u32 oldInt;
|
||||
oldInt = OSDisableInterrupts();
|
||||
reg = __DSPRegs[5];
|
||||
__DSPRegs[5] = (reg & ~0xA8) | 4;
|
||||
OSRestoreInterrupts(oldInt);
|
||||
}
|
||||
|
||||
u32 DSPGetDMAStatus(void) { return __DSPRegs[5] & 0x200; }
|
||||
|
||||
DSPTaskInfo* DSPAddTask(DSPTaskInfo* task) {
|
||||
u32 oldInt;
|
||||
oldInt = OSDisableInterrupts();
|
||||
__DSP_insert_task(task);
|
||||
task->state = 0;
|
||||
task->flags = 1;
|
||||
OSRestoreInterrupts(oldInt);
|
||||
if (task == __DSP_first_task) {
|
||||
__DSP_boot_task(task);
|
||||
}
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
5
src/dolphin/dsp/dsp_debug.c
Normal file
5
src/dolphin/dsp/dsp_debug.c
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
#include "types.h"
|
||||
|
||||
void __DSP_debug_printf(const char* fmt, ...) {
|
||||
// UNUSED(fmt);
|
||||
}
|
||||
389
src/dolphin/dsp/dsp_task.c
Normal file
389
src/dolphin/dsp/dsp_task.c
Normal file
|
|
@ -0,0 +1,389 @@
|
|||
#include "dolphin/dsp.h"
|
||||
#include "dolphin/hw_regs.h"
|
||||
|
||||
DSPTaskInfo *__DSP_curr_task;
|
||||
DSPTaskInfo *__DSP_first_task;
|
||||
DSPTaskInfo *__DSP_last_task;
|
||||
DSPTaskInfo *__DSP_tmp_task;
|
||||
DSPTaskInfo *__DSP_rude_task;
|
||||
|
||||
BOOL __DSP_rude_task_pending;
|
||||
|
||||
void __DSPHandler(__OSInterrupt, OSContext *context)
|
||||
{
|
||||
DSPTaskInfo *tmp_task;
|
||||
OSContext exceptionContext;
|
||||
u16 tmp;
|
||||
u32 mail;
|
||||
|
||||
tmp = __DSPRegs[5];
|
||||
tmp = (u16)(tmp & ~0x28) | 0x80;
|
||||
__DSPRegs[5] = tmp;
|
||||
|
||||
OSClearContext(&exceptionContext);
|
||||
OSSetCurrentContext(&exceptionContext);
|
||||
|
||||
while (!DSPCheckMailFromDSP())
|
||||
;
|
||||
mail = DSPReadMailFromDSP();
|
||||
|
||||
if ((__DSP_curr_task->flags & DSP_TASK_FLAG_CANCEL) && (mail == 0xDCD10002)) {
|
||||
mail = 0xDCD10003;
|
||||
}
|
||||
|
||||
switch (mail) {
|
||||
case 0xDCD10000:
|
||||
__DSP_curr_task->state = DSP_TASK_STATE_RUN;
|
||||
|
||||
if (__DSP_curr_task->init_cb) {
|
||||
(*(__DSP_curr_task->init_cb))((void *)(__DSP_curr_task));
|
||||
}
|
||||
break;
|
||||
case 0xDCD10001:
|
||||
__DSP_curr_task->state = DSP_TASK_STATE_RUN;
|
||||
if (__DSP_curr_task->res_cb) {
|
||||
(*(__DSP_curr_task->res_cb))((void *)(__DSP_curr_task));
|
||||
}
|
||||
break;
|
||||
case 0xDCD10002:
|
||||
if (__DSP_rude_task_pending) {
|
||||
|
||||
if (__DSP_curr_task == __DSP_rude_task) {
|
||||
DSPSendMailToDSP(0xCDD10003);
|
||||
while (DSPCheckMailToDSP()) { }
|
||||
|
||||
__DSP_rude_task = NULL;
|
||||
__DSP_rude_task_pending = FALSE;
|
||||
|
||||
if (__DSP_curr_task->res_cb) {
|
||||
(*(__DSP_curr_task->res_cb))((void *)(__DSP_curr_task));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else {
|
||||
DSPSendMailToDSP(0xCDD10001);
|
||||
while (DSPCheckMailToDSP())
|
||||
;
|
||||
__DSP_exec_task(__DSP_curr_task, __DSP_rude_task);
|
||||
|
||||
__DSP_curr_task->state = DSP_TASK_STATE_YIELD;
|
||||
__DSP_curr_task = __DSP_rude_task;
|
||||
|
||||
__DSP_rude_task = NULL;
|
||||
__DSP_rude_task_pending = FALSE;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (__DSP_curr_task->next == NULL) {
|
||||
|
||||
if (__DSP_curr_task == __DSP_first_task) {
|
||||
|
||||
DSPSendMailToDSP(0xCDD10003);
|
||||
while (DSPCheckMailToDSP())
|
||||
;
|
||||
|
||||
if (__DSP_curr_task->res_cb) {
|
||||
(*(__DSP_curr_task->res_cb))((void *)(__DSP_curr_task));
|
||||
}
|
||||
}
|
||||
else {
|
||||
DSPSendMailToDSP(0xCDD10001);
|
||||
while (DSPCheckMailToDSP()) { }
|
||||
|
||||
__DSP_exec_task(__DSP_curr_task, __DSP_first_task);
|
||||
|
||||
__DSP_curr_task->state = DSP_TASK_STATE_YIELD;
|
||||
__DSP_curr_task = __DSP_first_task;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
DSPSendMailToDSP(0xCDD10001);
|
||||
while (DSPCheckMailToDSP()) { }
|
||||
|
||||
__DSP_exec_task(__DSP_curr_task, __DSP_curr_task->next);
|
||||
|
||||
__DSP_curr_task->state = DSP_TASK_STATE_YIELD;
|
||||
__DSP_curr_task = __DSP_curr_task->next;
|
||||
}
|
||||
break;
|
||||
case 0xDCD10003:
|
||||
if (__DSP_rude_task_pending) {
|
||||
|
||||
if (__DSP_curr_task->done_cb) {
|
||||
(*(__DSP_curr_task->done_cb))((void *)(__DSP_curr_task));
|
||||
}
|
||||
|
||||
DSPSendMailToDSP(0xCDD10001);
|
||||
while (DSPCheckMailToDSP())
|
||||
;
|
||||
|
||||
__DSP_exec_task(NULL, __DSP_rude_task);
|
||||
|
||||
__DSP_remove_task(__DSP_curr_task);
|
||||
__DSP_curr_task = __DSP_rude_task;
|
||||
|
||||
__DSP_rude_task = NULL;
|
||||
__DSP_rude_task_pending = FALSE;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (__DSP_curr_task->next == NULL) {
|
||||
|
||||
if (__DSP_curr_task == __DSP_first_task) {
|
||||
|
||||
if (__DSP_curr_task->done_cb) {
|
||||
(*(__DSP_curr_task->done_cb))((void *)(__DSP_curr_task));
|
||||
}
|
||||
|
||||
DSPSendMailToDSP(0xCDD10002);
|
||||
while (DSPCheckMailToDSP())
|
||||
;
|
||||
|
||||
__DSP_curr_task->state = DSP_TASK_STATE_DONE;
|
||||
|
||||
__DSP_remove_task(__DSP_curr_task);
|
||||
}
|
||||
else {
|
||||
|
||||
if (__DSP_curr_task->done_cb) {
|
||||
(*(__DSP_curr_task->done_cb))((void *)(__DSP_curr_task));
|
||||
}
|
||||
|
||||
DSPSendMailToDSP(0xCDD10001);
|
||||
while (DSPCheckMailToDSP())
|
||||
;
|
||||
|
||||
__DSP_curr_task->state = DSP_TASK_STATE_DONE;
|
||||
__DSP_exec_task(NULL, __DSP_first_task);
|
||||
|
||||
__DSP_curr_task = __DSP_first_task;
|
||||
__DSP_remove_task(__DSP_last_task);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (__DSP_curr_task->done_cb) {
|
||||
(*(__DSP_curr_task->done_cb))((void *)(__DSP_curr_task));
|
||||
}
|
||||
DSPSendMailToDSP(0xCDD10001);
|
||||
while (DSPCheckMailToDSP())
|
||||
;
|
||||
|
||||
__DSP_curr_task->state = DSP_TASK_STATE_DONE;
|
||||
__DSP_exec_task(NULL, __DSP_curr_task->next);
|
||||
|
||||
__DSP_curr_task = __DSP_curr_task->next;
|
||||
__DSP_remove_task(__DSP_curr_task->prev);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xDCD10004:
|
||||
|
||||
if (__DSP_curr_task->req_cb) {
|
||||
(*(__DSP_curr_task->req_cb))((void *)(__DSP_curr_task));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
OSClearContext(&exceptionContext);
|
||||
OSSetCurrentContext(context);
|
||||
}
|
||||
|
||||
void __DSP_exec_task(DSPTaskInfo *curr, DSPTaskInfo *next)
|
||||
{
|
||||
if (curr) {
|
||||
DSPSendMailToDSP((u32)(curr->dram_mmem_addr));
|
||||
while (DSPCheckMailToDSP())
|
||||
;
|
||||
DSPSendMailToDSP((u32)(curr->dram_length));
|
||||
while (DSPCheckMailToDSP())
|
||||
;
|
||||
DSPSendMailToDSP((u32)(curr->dram_addr));
|
||||
while (DSPCheckMailToDSP())
|
||||
;
|
||||
}
|
||||
else {
|
||||
|
||||
DSPSendMailToDSP((u32)(0));
|
||||
while (DSPCheckMailToDSP())
|
||||
;
|
||||
DSPSendMailToDSP((u32)(0));
|
||||
while (DSPCheckMailToDSP())
|
||||
;
|
||||
DSPSendMailToDSP((u32)(0));
|
||||
while (DSPCheckMailToDSP())
|
||||
;
|
||||
}
|
||||
|
||||
DSPSendMailToDSP((u32)(next->iram_mmem_addr));
|
||||
while (DSPCheckMailToDSP())
|
||||
;
|
||||
DSPSendMailToDSP((u32)(next->iram_length));
|
||||
while (DSPCheckMailToDSP())
|
||||
;
|
||||
DSPSendMailToDSP((u32)(next->iram_addr));
|
||||
while (DSPCheckMailToDSP())
|
||||
;
|
||||
|
||||
if (DSP_TASK_STATE_INIT == next->state) {
|
||||
DSPSendMailToDSP((u32)(next->dsp_init_vector));
|
||||
while (DSPCheckMailToDSP())
|
||||
;
|
||||
DSPSendMailToDSP((u32)(0));
|
||||
while (DSPCheckMailToDSP())
|
||||
;
|
||||
DSPSendMailToDSP((u32)(0));
|
||||
while (DSPCheckMailToDSP())
|
||||
;
|
||||
DSPSendMailToDSP((u32)(0));
|
||||
while (DSPCheckMailToDSP())
|
||||
;
|
||||
}
|
||||
else {
|
||||
DSPSendMailToDSP((u32)(next->dsp_resume_vector));
|
||||
while (DSPCheckMailToDSP())
|
||||
;
|
||||
DSPSendMailToDSP((u32)(next->dram_mmem_addr));
|
||||
while (DSPCheckMailToDSP())
|
||||
;
|
||||
|
||||
DSPSendMailToDSP((u32)(next->dram_length));
|
||||
while (DSPCheckMailToDSP())
|
||||
;
|
||||
|
||||
DSPSendMailToDSP((u32)(next->dram_addr));
|
||||
while (DSPCheckMailToDSP())
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
#define MSG_BASE 0x80F30000
|
||||
void __DSP_boot_task(DSPTaskInfo *task)
|
||||
{
|
||||
|
||||
volatile u32 mail;
|
||||
|
||||
while (!DSPCheckMailFromDSP())
|
||||
;
|
||||
|
||||
mail = DSPReadMailFromDSP();
|
||||
|
||||
DSPSendMailToDSP(MSG_BASE | 0xA001);
|
||||
while (DSPCheckMailToDSP()) { }
|
||||
DSPSendMailToDSP((u32)(task->iram_mmem_addr));
|
||||
while (DSPCheckMailToDSP()) { }
|
||||
|
||||
DSPSendMailToDSP(MSG_BASE | 0xC002);
|
||||
while (DSPCheckMailToDSP()) { }
|
||||
DSPSendMailToDSP((u32)(task->iram_addr & 0xffff));
|
||||
while (DSPCheckMailToDSP()) { }
|
||||
|
||||
DSPSendMailToDSP(MSG_BASE | 0xA002);
|
||||
while (DSPCheckMailToDSP()) { }
|
||||
DSPSendMailToDSP(task->iram_length);
|
||||
while (DSPCheckMailToDSP()) { }
|
||||
|
||||
DSPSendMailToDSP(MSG_BASE | 0xB002);
|
||||
while (DSPCheckMailToDSP()) { }
|
||||
DSPSendMailToDSP(0x00000000);
|
||||
while (DSPCheckMailToDSP()) { }
|
||||
|
||||
DSPSendMailToDSP(MSG_BASE | 0xD001);
|
||||
while (DSPCheckMailToDSP()) { }
|
||||
DSPSendMailToDSP((u32)(0xffff & task->dsp_init_vector));
|
||||
while (DSPCheckMailToDSP()) { }
|
||||
|
||||
__DSP_debug_printf("DSP is booting task: 0x%08X\n", task);
|
||||
__DSP_debug_printf("__DSP_boot_task() : IRAM MMEM ADDR: 0x%08X\n", (u32)(task->iram_mmem_addr));
|
||||
__DSP_debug_printf("__DSP_boot_task() : IRAM DSP ADDR : 0x%08X\n", (u32)(task->iram_addr));
|
||||
__DSP_debug_printf("__DSP_boot_task() : IRAM LENGTH : 0x%08X\n", (u32)(task->iram_length));
|
||||
__DSP_debug_printf("__DSP_boot_task() : DRAM MMEM ADDR: 0x%08X\n", (u32)(task->dram_length));
|
||||
__DSP_debug_printf("__DSP_boot_task() : Start Vector : 0x%08X\n", (u32)(task->dsp_init_vector));
|
||||
}
|
||||
|
||||
void __DSP_insert_task(DSPTaskInfo *task)
|
||||
{
|
||||
|
||||
DSPTaskInfo *temp;
|
||||
|
||||
if (__DSP_first_task == NULL) {
|
||||
__DSP_first_task = __DSP_last_task = __DSP_curr_task = task;
|
||||
task->next = task->prev = NULL;
|
||||
}
|
||||
else {
|
||||
temp = __DSP_first_task;
|
||||
|
||||
while (temp) {
|
||||
if (task->priority < temp->priority) {
|
||||
task->prev = temp->prev;
|
||||
temp->prev = task;
|
||||
task->next = temp;
|
||||
if (task->prev == NULL) {
|
||||
__DSP_first_task = task;
|
||||
}
|
||||
else {
|
||||
(task->prev)->next = task;
|
||||
}
|
||||
break;
|
||||
}
|
||||
temp = temp->next;
|
||||
}
|
||||
|
||||
if (temp == NULL) {
|
||||
__DSP_last_task->next = task;
|
||||
task->next = NULL;
|
||||
task->prev = __DSP_last_task;
|
||||
__DSP_last_task = task;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __DSP_add_task(DSPTaskInfo *task)
|
||||
{
|
||||
if (__DSP_last_task == NULL) {
|
||||
__DSP_first_task = __DSP_last_task = __DSP_curr_task = task;
|
||||
task->next = task->prev = NULL;
|
||||
}
|
||||
else {
|
||||
__DSP_last_task->next = task;
|
||||
task->next = NULL;
|
||||
task->prev = __DSP_last_task;
|
||||
__DSP_last_task = task;
|
||||
}
|
||||
|
||||
task->state = DSP_TASK_STATE_INIT;
|
||||
|
||||
__DSP_debug_printf("__DSP_add_task() : Added task : 0x%08X\n", task);
|
||||
}
|
||||
|
||||
void __DSP_remove_task(DSPTaskInfo *task)
|
||||
{
|
||||
|
||||
task->flags = DSP_TASK_FLAG_CLEARALL;
|
||||
task->state = DSP_TASK_STATE_DONE;
|
||||
|
||||
if (__DSP_first_task == task) {
|
||||
if (task->next) {
|
||||
__DSP_first_task = (task->next);
|
||||
task->next->prev = NULL;
|
||||
}
|
||||
else {
|
||||
__DSP_first_task = __DSP_last_task = __DSP_curr_task = NULL;
|
||||
}
|
||||
}
|
||||
else if (__DSP_last_task == task) {
|
||||
__DSP_last_task = (task->prev);
|
||||
task->prev->next = NULL;
|
||||
__DSP_curr_task = __DSP_first_task;
|
||||
}
|
||||
else {
|
||||
__DSP_curr_task = task->next;
|
||||
task->prev->next = task->next;
|
||||
task->next->prev = task->prev;
|
||||
}
|
||||
}
|
||||
686
src/dolphin/exi/EXIBios.c
Normal file
686
src/dolphin/exi/EXIBios.c
Normal file
|
|
@ -0,0 +1,686 @@
|
|||
#include <dolphin/exi.h>
|
||||
#include <dolphin/hw_regs.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#define MAX_DEV 3
|
||||
#define MAX_CHAN 3
|
||||
|
||||
#define REG_MAX 5
|
||||
#define REG(chan, idx) (__EXIRegs[((chan)*REG_MAX) + (idx)])
|
||||
|
||||
#define STATE_IDLE 0x00
|
||||
#define STATE_DMA 0x01
|
||||
#define STATE_IMM 0x02
|
||||
#define STATE_BUSY (STATE_DMA | STATE_IMM)
|
||||
#define STATE_SELECTED 0x04
|
||||
#define STATE_ATTACHED 0x08
|
||||
#define STATE_LOCKED 0x10
|
||||
|
||||
#define EXI_0CR(tstart, dma, rw, tlen) ((((u32)(tstart)) << 0) | (((u32)(dma)) << 1) | (((u32)(rw)) << 2) | (((u32)(tlen)) << 4))
|
||||
|
||||
#define CPR_CS(x) ((1u << (x)) << 7)
|
||||
#define CPR_CLK(x) ((x) << 4)
|
||||
|
||||
static BOOL __EXIProbe(s32 chan);
|
||||
|
||||
typedef struct EXIControl {
|
||||
EXICallback exiCallback;
|
||||
EXICallback tcCallback;
|
||||
EXICallback extCallback;
|
||||
vu32 state;
|
||||
int immLen;
|
||||
u8 *immBuf;
|
||||
u32 dev;
|
||||
u32 id;
|
||||
s32 idTime;
|
||||
int items;
|
||||
struct {
|
||||
u32 dev;
|
||||
EXICallback callback;
|
||||
} queue[MAX_DEV];
|
||||
} EXIControl;
|
||||
|
||||
static EXIControl Ecb[MAX_CHAN];
|
||||
|
||||
s32 __EXIProbeStartTime[2] : (OS_BASE_CACHED | 0x30C0);
|
||||
|
||||
static void SetExiInterruptMask(s32 chan, EXIControl *exi)
|
||||
{
|
||||
EXIControl *exi2;
|
||||
|
||||
exi2 = &Ecb[2];
|
||||
switch (chan) {
|
||||
case 0:
|
||||
if ((exi->exiCallback == 0 && exi2->exiCallback == 0) || (exi->state & STATE_LOCKED)) {
|
||||
__OSMaskInterrupts(OS_INTERRUPTMASK_EXI_0_EXI | OS_INTERRUPTMASK_EXI_2_EXI);
|
||||
}
|
||||
else {
|
||||
__OSUnmaskInterrupts(OS_INTERRUPTMASK_EXI_0_EXI | OS_INTERRUPTMASK_EXI_2_EXI);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (exi->exiCallback == 0 || (exi->state & STATE_LOCKED)) {
|
||||
__OSMaskInterrupts(OS_INTERRUPTMASK_EXI_1_EXI);
|
||||
}
|
||||
else {
|
||||
__OSUnmaskInterrupts(OS_INTERRUPTMASK_EXI_1_EXI);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (__OSGetInterruptHandler(__OS_INTERRUPT_PI_DEBUG) == 0 || (exi->state & STATE_LOCKED)) {
|
||||
__OSMaskInterrupts(OS_INTERRUPTMASK_PI_DEBUG);
|
||||
}
|
||||
else {
|
||||
__OSUnmaskInterrupts(OS_INTERRUPTMASK_PI_DEBUG);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void CompleteTransfer(s32 chan)
|
||||
{
|
||||
EXIControl *exi = &Ecb[chan];
|
||||
u8 *buf;
|
||||
u32 data;
|
||||
int i;
|
||||
int len;
|
||||
|
||||
if (exi->state & STATE_BUSY) {
|
||||
if ((exi->state & STATE_IMM) && (len = exi->immLen)) {
|
||||
buf = exi->immBuf;
|
||||
data = REG(chan, 4);
|
||||
for (i = 0; i < len; i++) {
|
||||
*buf++ = (u8)((data >> ((3 - i) * 8)) & 0xff);
|
||||
}
|
||||
}
|
||||
exi->state &= ~STATE_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL EXIImm(s32 chan, void *buf, s32 len, u32 type, EXICallback callback)
|
||||
{
|
||||
EXIControl *exi = &Ecb[chan];
|
||||
BOOL enabled;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
if ((exi->state & STATE_BUSY) || !(exi->state & STATE_SELECTED)) {
|
||||
OSRestoreInterrupts(enabled);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
exi->tcCallback = callback;
|
||||
if (exi->tcCallback) {
|
||||
EXIClearInterrupts(chan, FALSE, TRUE, FALSE);
|
||||
__OSUnmaskInterrupts(OS_INTERRUPTMASK_EXI_0_TC >> (3 * chan));
|
||||
}
|
||||
|
||||
exi->state |= STATE_IMM;
|
||||
|
||||
if (type != EXI_READ) {
|
||||
u32 data;
|
||||
int i;
|
||||
|
||||
data = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
data |= ((u8 *)buf)[i] << ((3 - i) * 8);
|
||||
}
|
||||
REG(chan, 4) = data;
|
||||
}
|
||||
|
||||
exi->immBuf = buf;
|
||||
exi->immLen = (type != EXI_WRITE) ? len : 0;
|
||||
|
||||
REG(chan, 3) = EXI_0CR(1, 0, type, len - 1);
|
||||
|
||||
OSRestoreInterrupts(enabled);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL EXIImmEx(s32 chan, void *buf, s32 len, u32 mode)
|
||||
{
|
||||
s32 xLen;
|
||||
|
||||
while (len) {
|
||||
xLen = (len < 4) ? len : 4;
|
||||
if (!EXIImm(chan, buf, xLen, mode, NULL)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!EXISync(chan)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
(u8 *)buf += xLen;
|
||||
len -= xLen;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL EXIDma(s32 chan, void *buf, s32 len, u32 type, EXICallback callback)
|
||||
{
|
||||
EXIControl *exi = &Ecb[chan];
|
||||
BOOL enabled;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
if ((exi->state & STATE_BUSY) || !(exi->state & STATE_SELECTED)) {
|
||||
OSRestoreInterrupts(enabled);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
exi->tcCallback = callback;
|
||||
if (exi->tcCallback) {
|
||||
EXIClearInterrupts(chan, FALSE, TRUE, FALSE);
|
||||
__OSUnmaskInterrupts(OS_INTERRUPTMASK_EXI_0_TC >> (3 * chan));
|
||||
}
|
||||
|
||||
exi->state |= STATE_DMA;
|
||||
|
||||
REG(chan, 1) = (u32)buf & 0x3ffffe0;
|
||||
REG(chan, 2) = (u32)len;
|
||||
REG(chan, 3) = EXI_0CR(1, 1, type, 0);
|
||||
|
||||
OSRestoreInterrupts(enabled);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
extern u32 __OSGetDIConfig(void);
|
||||
|
||||
vu16 __OSDeviceCode : (OS_BASE_CACHED | 0x30E6);
|
||||
|
||||
BOOL EXISync(s32 chan)
|
||||
{
|
||||
EXIControl *exi = &Ecb[chan];
|
||||
BOOL rc = FALSE;
|
||||
BOOL enabled;
|
||||
|
||||
while (exi->state & STATE_SELECTED) {
|
||||
if (((REG(chan, 3) & 1) >> 0) == 0) {
|
||||
enabled = OSDisableInterrupts();
|
||||
if (exi->state & STATE_SELECTED) {
|
||||
CompleteTransfer(chan);
|
||||
if (__OSGetDIConfig() != 0xff || exi->immLen != 4 || (REG(chan, 0) & 0x00000070) != (EXI_FREQ_1M << 4)
|
||||
|| (REG(chan, 4) != EXI_USB_ADAPTER && REG(chan, 4) != EXI_IS_VIEWER && REG(chan, 4) != 0x04220001) || __OSDeviceCode == 0x8200) {
|
||||
rc = TRUE;
|
||||
}
|
||||
}
|
||||
OSRestoreInterrupts(enabled);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
u32 EXIClearInterrupts(s32 chan, BOOL exi, BOOL tc, BOOL ext)
|
||||
{
|
||||
u32 cpr;
|
||||
u32 prev;
|
||||
|
||||
prev = cpr = REG(chan, 0);
|
||||
cpr &= 0x7f5;
|
||||
if (exi)
|
||||
cpr |= 2;
|
||||
if (tc)
|
||||
cpr |= 8;
|
||||
if (ext)
|
||||
cpr |= 0x800;
|
||||
REG(chan, 0) = cpr;
|
||||
return prev;
|
||||
}
|
||||
|
||||
EXICallback EXISetExiCallback(s32 chan, EXICallback exiCallback)
|
||||
{
|
||||
EXIControl *exi = &Ecb[chan];
|
||||
EXICallback prev;
|
||||
BOOL enabled;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
prev = exi->exiCallback;
|
||||
exi->exiCallback = exiCallback;
|
||||
|
||||
if (chan != 2) {
|
||||
SetExiInterruptMask(chan, exi);
|
||||
}
|
||||
else {
|
||||
SetExiInterruptMask(0, &Ecb[0]);
|
||||
}
|
||||
|
||||
OSRestoreInterrupts(enabled);
|
||||
return prev;
|
||||
}
|
||||
|
||||
void EXIProbeReset(void)
|
||||
{
|
||||
__EXIProbeStartTime[0] = __EXIProbeStartTime[1] = 0;
|
||||
Ecb[0].idTime = Ecb[1].idTime = 0;
|
||||
__EXIProbe(0);
|
||||
__EXIProbe(1);
|
||||
}
|
||||
|
||||
static BOOL __EXIProbe(s32 chan)
|
||||
{
|
||||
EXIControl *exi = &Ecb[chan];
|
||||
BOOL enabled;
|
||||
BOOL rc;
|
||||
u32 cpr;
|
||||
s32 t;
|
||||
|
||||
if (chan == 2) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
rc = TRUE;
|
||||
enabled = OSDisableInterrupts();
|
||||
cpr = REG(chan, 0);
|
||||
if (!(exi->state & EXI_STATE_ATTACHED)) {
|
||||
if (cpr & 0x00000800) {
|
||||
EXIClearInterrupts(chan, FALSE, FALSE, TRUE);
|
||||
__EXIProbeStartTime[chan] = exi->idTime = 0;
|
||||
}
|
||||
|
||||
if (cpr & 0x00001000) {
|
||||
t = (s32)(OSTicksToMilliseconds(OSGetTime()) / 100) + 1;
|
||||
if (__EXIProbeStartTime[chan] == 0) {
|
||||
__EXIProbeStartTime[chan] = t;
|
||||
}
|
||||
if (t - __EXIProbeStartTime[chan] < 300 / 100) {
|
||||
rc = FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
__EXIProbeStartTime[chan] = exi->idTime = 0;
|
||||
rc = FALSE;
|
||||
}
|
||||
}
|
||||
else if (!(cpr & 0x00001000) || (cpr & 0x00000800)) {
|
||||
__EXIProbeStartTime[chan] = exi->idTime = 0;
|
||||
rc = FALSE;
|
||||
}
|
||||
OSRestoreInterrupts(enabled);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
BOOL EXIProbe(s32 chan)
|
||||
{
|
||||
EXIControl *exi = &Ecb[chan];
|
||||
BOOL rc;
|
||||
u32 id;
|
||||
|
||||
rc = __EXIProbe(chan);
|
||||
if (rc && exi->idTime == 0) {
|
||||
rc = EXIGetID(chan, 0, &id) ? TRUE : FALSE;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
s32 EXIProbeEx(s32 chan)
|
||||
{
|
||||
if (EXIProbe(chan)) {
|
||||
return 1;
|
||||
}
|
||||
else if (__EXIProbeStartTime[chan] != 0) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL __EXIAttach(s32 chan, EXICallback extCallback)
|
||||
{
|
||||
EXIControl *exi = &Ecb[chan];
|
||||
BOOL enabled;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
if ((exi->state & EXI_STATE_ATTACHED) || __EXIProbe(chan) == FALSE) {
|
||||
OSRestoreInterrupts(enabled);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
EXIClearInterrupts(chan, TRUE, FALSE, FALSE);
|
||||
|
||||
exi->extCallback = extCallback;
|
||||
__OSUnmaskInterrupts(OS_INTERRUPTMASK_EXI_0_EXT >> (3 * chan));
|
||||
exi->state |= STATE_ATTACHED;
|
||||
OSRestoreInterrupts(enabled);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL EXIAttach(s32 chan, EXICallback extCallback)
|
||||
{
|
||||
EXIControl *exi = &Ecb[chan];
|
||||
BOOL enabled;
|
||||
BOOL rc;
|
||||
|
||||
EXIProbe(chan);
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
if (exi->idTime == 0) {
|
||||
OSRestoreInterrupts(enabled);
|
||||
return FALSE;
|
||||
}
|
||||
rc = __EXIAttach(chan, extCallback);
|
||||
OSRestoreInterrupts(enabled);
|
||||
return rc;
|
||||
}
|
||||
|
||||
BOOL EXIDetach(s32 chan)
|
||||
{
|
||||
EXIControl *exi = &Ecb[chan];
|
||||
BOOL enabled;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
if (!(exi->state & STATE_ATTACHED)) {
|
||||
OSRestoreInterrupts(enabled);
|
||||
return TRUE;
|
||||
}
|
||||
if ((exi->state & STATE_LOCKED) && exi->dev == 0) {
|
||||
OSRestoreInterrupts(enabled);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
exi->state &= ~STATE_ATTACHED;
|
||||
__OSMaskInterrupts((OS_INTERRUPTMASK_EXI_0_EXT | OS_INTERRUPTMASK_EXI_0_EXI) >> (3 * chan));
|
||||
OSRestoreInterrupts(enabled);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL EXISelect(s32 chan, u32 dev, u32 freq)
|
||||
{
|
||||
EXIControl *exi = &Ecb[chan];
|
||||
u32 cpr;
|
||||
BOOL enabled;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
if ((exi->state & STATE_SELECTED)
|
||||
|| chan != 2 && (dev == 0 && !(exi->state & STATE_ATTACHED) && !__EXIProbe(chan) || !(exi->state & STATE_LOCKED) || (exi->dev != dev))) {
|
||||
OSRestoreInterrupts(enabled);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
exi->state |= STATE_SELECTED;
|
||||
cpr = REG(chan, 0);
|
||||
cpr &= 0x405;
|
||||
cpr |= CPR_CS(dev) | CPR_CLK(freq);
|
||||
REG(chan, 0) = cpr;
|
||||
|
||||
if (exi->state & STATE_ATTACHED) {
|
||||
switch (chan) {
|
||||
case 0:
|
||||
__OSMaskInterrupts(OS_INTERRUPTMASK_EXI_0_EXT);
|
||||
break;
|
||||
case 1:
|
||||
__OSMaskInterrupts(OS_INTERRUPTMASK_EXI_1_EXT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
OSRestoreInterrupts(enabled);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL EXIDeselect(s32 chan)
|
||||
{
|
||||
EXIControl *exi = &Ecb[chan];
|
||||
u32 cpr;
|
||||
BOOL enabled;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
if (!(exi->state & STATE_SELECTED)) {
|
||||
OSRestoreInterrupts(enabled);
|
||||
return FALSE;
|
||||
}
|
||||
exi->state &= ~STATE_SELECTED;
|
||||
cpr = REG(chan, 0);
|
||||
REG(chan, 0) = cpr & 0x405;
|
||||
|
||||
if (exi->state & STATE_ATTACHED) {
|
||||
switch (chan) {
|
||||
case 0:
|
||||
__OSUnmaskInterrupts(OS_INTERRUPTMASK_EXI_0_EXT);
|
||||
break;
|
||||
case 1:
|
||||
__OSUnmaskInterrupts(OS_INTERRUPTMASK_EXI_1_EXT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
OSRestoreInterrupts(enabled);
|
||||
|
||||
if (chan != 2 && (cpr & CPR_CS(0))) {
|
||||
return __EXIProbe(chan) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void EXIIntrruptHandler(__OSInterrupt interrupt, OSContext *context)
|
||||
{
|
||||
s32 chan;
|
||||
EXIControl *exi;
|
||||
EXICallback callback;
|
||||
|
||||
chan = (interrupt - __OS_INTERRUPT_EXI_0_EXI) / 3;
|
||||
exi = &Ecb[chan];
|
||||
EXIClearInterrupts(chan, TRUE, FALSE, FALSE);
|
||||
callback = exi->exiCallback;
|
||||
if (callback) {
|
||||
OSContext exceptionContext;
|
||||
|
||||
OSClearContext(&exceptionContext);
|
||||
OSSetCurrentContext(&exceptionContext);
|
||||
|
||||
callback(chan, context);
|
||||
|
||||
OSClearContext(&exceptionContext);
|
||||
OSSetCurrentContext(context);
|
||||
}
|
||||
}
|
||||
|
||||
static void TCIntrruptHandler(__OSInterrupt interrupt, OSContext *context)
|
||||
{
|
||||
OSContext exceptionContext;
|
||||
s32 chan;
|
||||
EXIControl *exi;
|
||||
EXICallback callback;
|
||||
|
||||
chan = (interrupt - __OS_INTERRUPT_EXI_0_TC) / 3;
|
||||
exi = &Ecb[chan];
|
||||
__OSMaskInterrupts(OS_INTERRUPTMASK(interrupt));
|
||||
EXIClearInterrupts(chan, FALSE, TRUE, FALSE);
|
||||
callback = exi->tcCallback;
|
||||
if (callback) {
|
||||
exi->tcCallback = 0;
|
||||
CompleteTransfer(chan);
|
||||
|
||||
OSClearContext(&exceptionContext);
|
||||
OSSetCurrentContext(&exceptionContext);
|
||||
|
||||
callback(chan, context);
|
||||
|
||||
OSClearContext(&exceptionContext);
|
||||
OSSetCurrentContext(context);
|
||||
}
|
||||
}
|
||||
|
||||
static void EXTIntrruptHandler(__OSInterrupt interrupt, OSContext *context)
|
||||
{
|
||||
s32 chan;
|
||||
EXIControl *exi;
|
||||
EXICallback callback;
|
||||
|
||||
chan = (interrupt - __OS_INTERRUPT_EXI_0_EXT) / 3;
|
||||
__OSMaskInterrupts((OS_INTERRUPTMASK_EXI_0_EXT | OS_INTERRUPTMASK_EXI_0_EXI) >> (3 * chan));
|
||||
exi = &Ecb[chan];
|
||||
callback = exi->extCallback;
|
||||
exi->state &= ~STATE_ATTACHED;
|
||||
if (callback) {
|
||||
OSContext exceptionContext;
|
||||
|
||||
OSClearContext(&exceptionContext);
|
||||
OSSetCurrentContext(&exceptionContext);
|
||||
|
||||
exi->extCallback = 0;
|
||||
callback(chan, context);
|
||||
|
||||
OSClearContext(&exceptionContext);
|
||||
OSSetCurrentContext(context);
|
||||
}
|
||||
}
|
||||
|
||||
void EXIInit(void)
|
||||
{
|
||||
__OSMaskInterrupts(OS_INTERRUPTMASK_EXI_0_EXI | OS_INTERRUPTMASK_EXI_0_TC | OS_INTERRUPTMASK_EXI_0_EXT | OS_INTERRUPTMASK_EXI_1_EXI
|
||||
| OS_INTERRUPTMASK_EXI_1_TC | OS_INTERRUPTMASK_EXI_1_EXT | OS_INTERRUPTMASK_EXI_2_EXI | OS_INTERRUPTMASK_EXI_2_TC);
|
||||
|
||||
REG(0, 0) = 0;
|
||||
REG(1, 0) = 0;
|
||||
REG(2, 0) = 0;
|
||||
|
||||
REG(0, 0) = 0x00002000;
|
||||
|
||||
__OSSetInterruptHandler(__OS_INTERRUPT_EXI_0_EXI, EXIIntrruptHandler);
|
||||
__OSSetInterruptHandler(__OS_INTERRUPT_EXI_0_TC, TCIntrruptHandler);
|
||||
__OSSetInterruptHandler(__OS_INTERRUPT_EXI_0_EXT, EXTIntrruptHandler);
|
||||
__OSSetInterruptHandler(__OS_INTERRUPT_EXI_1_EXI, EXIIntrruptHandler);
|
||||
__OSSetInterruptHandler(__OS_INTERRUPT_EXI_1_TC, TCIntrruptHandler);
|
||||
__OSSetInterruptHandler(__OS_INTERRUPT_EXI_1_EXT, EXTIntrruptHandler);
|
||||
__OSSetInterruptHandler(__OS_INTERRUPT_EXI_2_EXI, EXIIntrruptHandler);
|
||||
__OSSetInterruptHandler(__OS_INTERRUPT_EXI_2_TC, TCIntrruptHandler);
|
||||
|
||||
if ((OSGetConsoleType() & 0x10000000) != 0) {
|
||||
__EXIProbeStartTime[0] = __EXIProbeStartTime[1] = 0;
|
||||
Ecb[0].idTime = Ecb[1].idTime = 0;
|
||||
__EXIProbe(0);
|
||||
__EXIProbe(1);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL EXILock(s32 chan, u32 dev, EXICallback unlockedCallback)
|
||||
{
|
||||
EXIControl *exi = &Ecb[chan];
|
||||
BOOL enabled;
|
||||
int i;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
if (exi->state & STATE_LOCKED) {
|
||||
if (unlockedCallback) {
|
||||
for (i = 0; i < exi->items; i++) {
|
||||
if (exi->queue[i].dev == dev) {
|
||||
OSRestoreInterrupts(enabled);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
exi->queue[exi->items].callback = unlockedCallback;
|
||||
exi->queue[exi->items].dev = dev;
|
||||
exi->items++;
|
||||
}
|
||||
OSRestoreInterrupts(enabled);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
exi->state |= STATE_LOCKED;
|
||||
exi->dev = dev;
|
||||
SetExiInterruptMask(chan, exi);
|
||||
|
||||
OSRestoreInterrupts(enabled);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL EXIUnlock(s32 chan)
|
||||
{
|
||||
EXIControl *exi = &Ecb[chan];
|
||||
BOOL enabled;
|
||||
EXICallback unlockedCallback;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
if (!(exi->state & STATE_LOCKED)) {
|
||||
OSRestoreInterrupts(enabled);
|
||||
return FALSE;
|
||||
}
|
||||
exi->state &= ~STATE_LOCKED;
|
||||
SetExiInterruptMask(chan, exi);
|
||||
|
||||
if (0 < exi->items) {
|
||||
unlockedCallback = exi->queue[0].callback;
|
||||
if (0 < --exi->items) {
|
||||
memmove(&exi->queue[0], &exi->queue[1], sizeof(exi->queue[0]) * exi->items);
|
||||
}
|
||||
unlockedCallback(chan, 0);
|
||||
}
|
||||
|
||||
OSRestoreInterrupts(enabled);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
u32 EXIGetState(s32 chan)
|
||||
{
|
||||
EXIControl *exi = &Ecb[chan];
|
||||
|
||||
return (u32)exi->state;
|
||||
}
|
||||
|
||||
static void UnlockedHandler(s32 chan, OSContext *context)
|
||||
{
|
||||
u32 id;
|
||||
|
||||
EXIGetID(chan, 0, &id);
|
||||
}
|
||||
|
||||
s32 EXIGetID(s32 chan, u32 dev, u32 *id)
|
||||
{
|
||||
EXIControl *exi = &Ecb[chan];
|
||||
BOOL err;
|
||||
u32 cmd;
|
||||
s32 startTime;
|
||||
BOOL enabled;
|
||||
|
||||
if (chan < 2 && dev == 0) {
|
||||
if (!__EXIProbe(chan)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (exi->idTime == __EXIProbeStartTime[chan]) {
|
||||
*id = exi->id;
|
||||
return exi->idTime;
|
||||
}
|
||||
|
||||
if (!__EXIAttach(chan, NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
startTime = __EXIProbeStartTime[chan];
|
||||
}
|
||||
|
||||
err = !EXILock(chan, dev, (chan < 2 && dev == 0) ? UnlockedHandler : NULL);
|
||||
if (!err) {
|
||||
err = !EXISelect(chan, dev, EXI_FREQ_1M);
|
||||
if (!err) {
|
||||
cmd = 0;
|
||||
err |= !EXIImm(chan, &cmd, 2, EXI_WRITE, NULL);
|
||||
err |= !EXISync(chan);
|
||||
err |= !EXIImm(chan, id, 4, EXI_READ, NULL);
|
||||
err |= !EXISync(chan);
|
||||
err |= !EXIDeselect(chan);
|
||||
}
|
||||
EXIUnlock(chan);
|
||||
}
|
||||
|
||||
if (chan < 2 && dev == 0) {
|
||||
EXIDetach(chan);
|
||||
enabled = OSDisableInterrupts();
|
||||
err |= (startTime != __EXIProbeStartTime[chan]);
|
||||
if (!err) {
|
||||
exi->id = *id;
|
||||
exi->idTime = startTime;
|
||||
}
|
||||
OSRestoreInterrupts(enabled);
|
||||
|
||||
return err ? 0 : exi->idTime;
|
||||
}
|
||||
|
||||
return err ? 0 : !0;
|
||||
}
|
||||
184
src/dolphin/exi/EXIUart.c
Normal file
184
src/dolphin/exi/EXIUart.c
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
#include <dolphin/os.h>
|
||||
#include <dolphin/exi.h>
|
||||
|
||||
#define EXI_TX 0x800400u
|
||||
#define EXI_MAGIC 0xa5ff005a
|
||||
|
||||
static s32 Chan;
|
||||
static u32 Dev;
|
||||
static u32 Enabled = 0;
|
||||
static u32 BarnacleEnabled = 0;
|
||||
|
||||
static BOOL ProbeBarnacle(s32 chan, u32 dev, u32 *revision)
|
||||
{
|
||||
BOOL err;
|
||||
u32 cmd;
|
||||
|
||||
if (chan != 2 && dev == 0 && !EXIAttach(chan, NULL)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
err = !EXILock(chan, dev, NULL);
|
||||
if (!err) {
|
||||
err = !EXISelect(chan, dev, EXI_FREQ_1M);
|
||||
if (!err) {
|
||||
cmd = 0x20011300;
|
||||
err = FALSE;
|
||||
err |= !EXIImm(chan, &cmd, 4, EXI_WRITE, NULL);
|
||||
err |= !EXISync(chan);
|
||||
err |= !EXIImm(chan, revision, 4, EXI_READ, NULL);
|
||||
err |= !EXISync(chan);
|
||||
err |= !EXIDeselect(chan);
|
||||
}
|
||||
EXIUnlock(chan);
|
||||
}
|
||||
|
||||
if (chan != 2 && dev == 0) {
|
||||
EXIDetach(chan);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return (*revision != 0xFFFFFFFF) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
void __OSEnableBarnacle(s32 chan, u32 dev)
|
||||
{
|
||||
u32 id;
|
||||
|
||||
if (EXIGetID(chan, dev, &id)) {
|
||||
switch (id) {
|
||||
case 0xffffffff:
|
||||
case EXI_MEMORY_CARD_59:
|
||||
case EXI_MEMORY_CARD_123:
|
||||
case EXI_MEMORY_CARD_251:
|
||||
case EXI_MEMORY_CARD_507:
|
||||
case EXI_USB_ADAPTER:
|
||||
case EXI_NPDP_GDEV:
|
||||
case EXI_MODEM:
|
||||
case EXI_MARLIN:
|
||||
case 0x04220000:
|
||||
case 0x04020100:
|
||||
case 0x04020200:
|
||||
case 0x04020300:
|
||||
case 0x04040404:
|
||||
case 0x04060000:
|
||||
case 0x04120000:
|
||||
case 0x04130000:
|
||||
case 0x80000000 | EXI_MEMORY_CARD_59:
|
||||
case 0x80000000 | EXI_MEMORY_CARD_123:
|
||||
case 0x80000000 | EXI_MEMORY_CARD_251:
|
||||
case 0x80000000 | EXI_MEMORY_CARD_507:
|
||||
break;
|
||||
default:
|
||||
if (ProbeBarnacle(chan, dev, &id)) {
|
||||
Chan = chan;
|
||||
Dev = dev;
|
||||
Enabled = BarnacleEnabled = EXI_MAGIC;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u32 InitializeUART(u32 baudRate)
|
||||
{
|
||||
if (BarnacleEnabled == EXI_MAGIC) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(OSGetConsoleType() & OS_CONSOLE_DEVELOPMENT)) {
|
||||
Enabled = 0;
|
||||
return 2;
|
||||
}
|
||||
else {
|
||||
Chan = 0;
|
||||
Dev = 1;
|
||||
Enabled = EXI_MAGIC;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
u32 ReadUARTN(void *bytes, unsigned long length)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
static int QueueLength(void)
|
||||
{
|
||||
u32 cmd;
|
||||
|
||||
if (!EXISelect(Chan, Dev, EXI_FREQ_8M))
|
||||
return -1;
|
||||
|
||||
cmd = EXI_TX << 6;
|
||||
EXIImm(Chan, &cmd, 4, EXI_WRITE, NULL);
|
||||
EXISync(Chan);
|
||||
|
||||
EXIImm(Chan, &cmd, 1, EXI_READ, NULL);
|
||||
EXISync(Chan);
|
||||
EXIDeselect(Chan);
|
||||
|
||||
return 16 - (int)((cmd >> 24) & 0xff);
|
||||
}
|
||||
|
||||
u32 WriteUARTN(const void *buf, unsigned long len)
|
||||
{
|
||||
u32 cmd;
|
||||
int qLen;
|
||||
long xLen;
|
||||
char *ptr;
|
||||
BOOL locked;
|
||||
u32 error;
|
||||
|
||||
if (Enabled != EXI_MAGIC)
|
||||
return 2;
|
||||
|
||||
locked = EXILock(Chan, Dev, 0);
|
||||
if (!locked) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (ptr = (char *)buf; ptr - buf < len; ptr++) {
|
||||
if (*ptr == '\n')
|
||||
*ptr = '\r';
|
||||
}
|
||||
|
||||
error = 0;
|
||||
cmd = (EXI_TX | 0x2000000) << 6;
|
||||
while (len) {
|
||||
qLen = QueueLength();
|
||||
if (qLen < 0) {
|
||||
error = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
if (qLen < 12 && qLen < len)
|
||||
continue;
|
||||
|
||||
if (!EXISelect(Chan, Dev, EXI_FREQ_8M)) {
|
||||
error = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
EXIImm(Chan, &cmd, 4, EXI_WRITE, NULL);
|
||||
EXISync(Chan);
|
||||
|
||||
while (qLen && len) {
|
||||
if (qLen < 4 && qLen < len)
|
||||
break;
|
||||
xLen = (len < 4) ? (long)len : 4;
|
||||
EXIImm(Chan, (void *)buf, xLen, EXI_WRITE, NULL);
|
||||
(u8 *)buf += xLen;
|
||||
len -= xLen;
|
||||
qLen -= xLen;
|
||||
EXISync(Chan);
|
||||
}
|
||||
EXIDeselect(Chan);
|
||||
}
|
||||
|
||||
EXIUnlock(Chan);
|
||||
return error;
|
||||
}
|
||||
817
src/dolphin/si/SIBios.c
Normal file
817
src/dolphin/si/SIBios.c
Normal file
|
|
@ -0,0 +1,817 @@
|
|||
#include <dolphin/OSRtcPriv.h>
|
||||
#include <dolphin/hw_regs.h>
|
||||
#include <dolphin/os.h>
|
||||
#include <dolphin/sipriv.h>
|
||||
|
||||
|
||||
extern OSTime __OSGetSystemTime();
|
||||
|
||||
typedef struct SIControl {
|
||||
s32 chan;
|
||||
u32 poll;
|
||||
u32 inputBytes;
|
||||
void *input;
|
||||
SICallback callback;
|
||||
} SIControl;
|
||||
|
||||
static SIControl Si = {
|
||||
-1,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
typedef struct SIComm_s {
|
||||
u32 tcint : 1;
|
||||
u32 tcintmsk : 1;
|
||||
u32 comerr : 1;
|
||||
u32 rdstint : 1;
|
||||
u32 rdstintmsk : 1;
|
||||
u32 pad0 : 4;
|
||||
u32 outlngth : 7;
|
||||
u32 pad1 : 1;
|
||||
u32 inlngth : 7;
|
||||
u32 pad2 : 5;
|
||||
u32 channel : 2;
|
||||
u32 tstart : 1;
|
||||
} SIComm_s;
|
||||
|
||||
typedef union SIComm_u {
|
||||
u32 val;
|
||||
SIComm_s f;
|
||||
} SIComm_u;
|
||||
|
||||
static SIPacket Packet[SI_MAX_CHAN];
|
||||
static OSAlarm Alarm[SI_MAX_CHAN];
|
||||
static u32 Type[SI_MAX_CHAN] = {
|
||||
SI_ERROR_NO_RESPONSE,
|
||||
SI_ERROR_NO_RESPONSE,
|
||||
SI_ERROR_NO_RESPONSE,
|
||||
SI_ERROR_NO_RESPONSE,
|
||||
};
|
||||
|
||||
static OSTime TypeTime[SI_MAX_CHAN];
|
||||
static OSTime XferTime[SI_MAX_CHAN];
|
||||
|
||||
static SITypeAndStatusCallback TypeCallback[SI_MAX_CHAN][4];
|
||||
static __OSInterruptHandler RDSTHandler[4];
|
||||
|
||||
u32 __PADFixBits;
|
||||
|
||||
static BOOL __SITransfer(s32 chan, void *output, u32 outputBytes, void *input, u32 inputBytes, SICallback callback);
|
||||
|
||||
static BOOL InputBufferValid[SI_MAX_CHAN];
|
||||
static u32 InputBuffer[SI_MAX_CHAN][2];
|
||||
static vu32 InputBufferVcount[SI_MAX_CHAN];
|
||||
|
||||
static BOOL SIGetResponseRaw(s32 chan);
|
||||
static void GetTypeCallback(s32 chan, u32 error, OSContext *context);
|
||||
|
||||
BOOL SIBusy()
|
||||
{
|
||||
return Si.chan != -1 ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
BOOL SIIsChanBusy(s32 chan)
|
||||
{
|
||||
return (Packet[chan].chan != -1 || Si.chan == chan);
|
||||
}
|
||||
|
||||
static void SIClearTCInterrupt()
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
reg = __SIRegs[13];
|
||||
reg |= 0x80000000;
|
||||
reg &= ~0x00000001;
|
||||
__SIRegs[13] = reg;
|
||||
}
|
||||
|
||||
static u32 CompleteTransfer()
|
||||
{
|
||||
u32 sr;
|
||||
u32 i;
|
||||
u32 rLen;
|
||||
u8 *input;
|
||||
|
||||
sr = __SIRegs[14];
|
||||
|
||||
SIClearTCInterrupt();
|
||||
|
||||
if (Si.chan != -1) {
|
||||
XferTime[Si.chan] = __OSGetSystemTime();
|
||||
|
||||
input = Si.input;
|
||||
|
||||
rLen = Si.inputBytes / 4;
|
||||
for (i = 0; i < rLen; i++) {
|
||||
*(u32 *)input = __SIRegs[32 + i];
|
||||
input += 4;
|
||||
}
|
||||
|
||||
rLen = Si.inputBytes & 3;
|
||||
if (rLen) {
|
||||
u32 temp = __SIRegs[32 + i];
|
||||
for (i = 0; i < rLen; i++) {
|
||||
*input++ = (u8)((temp >> ((3 - i) * 8)) & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
if (__SIRegs[13] & 0x20000000) {
|
||||
sr >>= 8 * (3 - Si.chan);
|
||||
sr &= 0xf;
|
||||
|
||||
if ((sr & SI_ERROR_NO_RESPONSE) && !(Type[Si.chan] & SI_ERROR_BUSY)) {
|
||||
Type[Si.chan] = SI_ERROR_NO_RESPONSE;
|
||||
}
|
||||
if (sr == 0) {
|
||||
sr = SI_ERROR_COLLISION;
|
||||
}
|
||||
}
|
||||
else {
|
||||
TypeTime[Si.chan] = __OSGetSystemTime();
|
||||
sr = 0;
|
||||
}
|
||||
|
||||
Si.chan = -1;
|
||||
}
|
||||
return sr;
|
||||
}
|
||||
|
||||
static void SITransferNext(s32 chan)
|
||||
{
|
||||
int i;
|
||||
SIPacket *packet;
|
||||
|
||||
for (i = 0; i < SI_MAX_CHAN; ++i) {
|
||||
++chan;
|
||||
chan %= SI_MAX_CHAN;
|
||||
packet = &Packet[chan];
|
||||
if (packet->chan != -1 && packet->fire <= __OSGetSystemTime()) {
|
||||
if (__SITransfer(packet->chan, packet->output, packet->outputBytes, packet->input, packet->inputBytes, packet->callback)) {
|
||||
OSCancelAlarm(&Alarm[chan]);
|
||||
packet->chan = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SIInterruptHandler(__OSInterrupt interrupt, OSContext *context)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
reg = __SIRegs[13];
|
||||
|
||||
if ((reg & 0xc0000000) == 0xc0000000) {
|
||||
s32 chan;
|
||||
u32 sr;
|
||||
SICallback callback;
|
||||
|
||||
chan = Si.chan;
|
||||
sr = CompleteTransfer();
|
||||
callback = Si.callback;
|
||||
Si.callback = 0;
|
||||
|
||||
SITransferNext(chan);
|
||||
|
||||
if (callback) {
|
||||
callback(chan, sr, context);
|
||||
}
|
||||
|
||||
sr = __SIRegs[14];
|
||||
sr &= 0xf000000 >> (8 * chan);
|
||||
__SIRegs[14] = sr;
|
||||
|
||||
if (Type[chan] == SI_ERROR_BUSY && !SIIsChanBusy(chan)) {
|
||||
static u32 cmdTypeAndStatus = 0 << 24;
|
||||
SITransfer(chan, &cmdTypeAndStatus, 1, &Type[chan], 3, GetTypeCallback, OSMicrosecondsToTicks(65));
|
||||
}
|
||||
}
|
||||
|
||||
if ((reg & 0x18000000) == 0x18000000) {
|
||||
|
||||
int i;
|
||||
u32 vcount;
|
||||
u32 x;
|
||||
|
||||
vcount = VIGetCurrentLine() + 1;
|
||||
x = (Si.poll & 0x03ff0000) >> 16;
|
||||
|
||||
for (i = 0; i < SI_MAX_CHAN; ++i) {
|
||||
if (SIGetResponseRaw(i)) {
|
||||
InputBufferVcount[i] = vcount;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < SI_MAX_CHAN; ++i) {
|
||||
if (!(Si.poll & (SI_CHAN0_BIT >> (31 - 7 + i)))) {
|
||||
continue;
|
||||
}
|
||||
if (InputBufferVcount[i] == 0 || InputBufferVcount[i] + (x / 2) < vcount) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < SI_MAX_CHAN; ++i) {
|
||||
InputBufferVcount[i] = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
if (RDSTHandler[i]) {
|
||||
RDSTHandler[i](interrupt, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL SIEnablePollingInterrupt(BOOL enable)
|
||||
{
|
||||
BOOL enabled;
|
||||
BOOL rc;
|
||||
u32 reg;
|
||||
int i;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
reg = __SIRegs[13];
|
||||
rc = (reg & 0x08000000) ? TRUE : FALSE;
|
||||
if (enable) {
|
||||
reg |= 0x08000000;
|
||||
for (i = 0; i < SI_MAX_CHAN; ++i) {
|
||||
InputBufferVcount[i] = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
reg &= ~0x08000000;
|
||||
}
|
||||
reg &= ~0x80000001;
|
||||
__SIRegs[13] = reg;
|
||||
OSRestoreInterrupts(enabled);
|
||||
return rc;
|
||||
}
|
||||
|
||||
BOOL SIRegisterPollingHandler(__OSInterruptHandler handler)
|
||||
{
|
||||
BOOL enabled;
|
||||
int i;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
for (i = 0; i < 4; ++i) {
|
||||
if (RDSTHandler[i] == handler) {
|
||||
OSRestoreInterrupts(enabled);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 4; ++i) {
|
||||
if (RDSTHandler[i] == 0) {
|
||||
RDSTHandler[i] = handler;
|
||||
SIEnablePollingInterrupt(TRUE);
|
||||
OSRestoreInterrupts(enabled);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
OSRestoreInterrupts(enabled);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL SIUnregisterPollingHandler(__OSInterruptHandler handler)
|
||||
{
|
||||
BOOL enabled;
|
||||
int i;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
for (i = 0; i < 4; ++i) {
|
||||
if (RDSTHandler[i] == handler) {
|
||||
RDSTHandler[i] = 0;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
if (RDSTHandler[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == 4) {
|
||||
SIEnablePollingInterrupt(FALSE);
|
||||
}
|
||||
OSRestoreInterrupts(enabled);
|
||||
return TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
OSRestoreInterrupts(enabled);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void SIInit(void)
|
||||
{
|
||||
Packet[0].chan = Packet[1].chan = Packet[2].chan = Packet[3].chan = -1;
|
||||
|
||||
Si.poll = 0;
|
||||
SISetSamplingRate(0);
|
||||
|
||||
while (__SIRegs[13] & 1)
|
||||
;
|
||||
|
||||
__SIRegs[13] = 0x80000000;
|
||||
|
||||
__OSSetInterruptHandler(__OS_INTERRUPT_PI_SI, SIInterruptHandler);
|
||||
__OSUnmaskInterrupts(OS_INTERRUPTMASK_PI_SI);
|
||||
|
||||
SIGetType(0);
|
||||
SIGetType(1);
|
||||
SIGetType(2);
|
||||
SIGetType(3);
|
||||
}
|
||||
|
||||
#define ROUND(n, a) (((u32)(n) + (a)-1) & ~((a)-1))
|
||||
|
||||
static BOOL __SITransfer(s32 chan, void *output, u32 outputBytes, void *input, u32 inputBytes, SICallback callback)
|
||||
{
|
||||
BOOL enabled;
|
||||
u32 rLen;
|
||||
u32 i;
|
||||
u32 sr;
|
||||
SIComm_u comcsr;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
if (Si.chan != -1) {
|
||||
OSRestoreInterrupts(enabled);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
sr = __SIRegs[14];
|
||||
sr &= (0xf000000) >> (8 * chan);
|
||||
__SIRegs[14] = sr;
|
||||
|
||||
Si.chan = chan;
|
||||
Si.callback = callback;
|
||||
Si.inputBytes = inputBytes;
|
||||
Si.input = input;
|
||||
|
||||
rLen = ROUND(outputBytes, 4) / 4;
|
||||
for (i = 0; i < rLen; i++) {
|
||||
__SIRegs[32 + i] = ((u32 *)output)[i];
|
||||
}
|
||||
|
||||
comcsr.val = __SIRegs[13];
|
||||
comcsr.f.tcint = 1;
|
||||
comcsr.f.tcintmsk = callback ? 1 : 0;
|
||||
comcsr.f.outlngth = (outputBytes == SI_MAX_COMCSR_OUTLNGTH) ? 0 : outputBytes;
|
||||
comcsr.f.inlngth = (inputBytes == SI_MAX_COMCSR_INLNGTH) ? 0 : inputBytes;
|
||||
comcsr.f.channel = chan;
|
||||
comcsr.f.tstart = 1;
|
||||
__SIRegs[13] = comcsr.val;
|
||||
|
||||
OSRestoreInterrupts(enabled);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
u32 SISync(void)
|
||||
{
|
||||
BOOL enabled;
|
||||
u32 sr;
|
||||
|
||||
while (__SIRegs[13] & 1)
|
||||
;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
sr = CompleteTransfer();
|
||||
|
||||
SITransferNext(SI_MAX_CHAN);
|
||||
|
||||
OSRestoreInterrupts(enabled);
|
||||
|
||||
return sr;
|
||||
}
|
||||
|
||||
u32 SIGetStatus(s32 chan)
|
||||
{
|
||||
BOOL enabled;
|
||||
u32 sr;
|
||||
int chanShift;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
sr = __SIRegs[14];
|
||||
chanShift = 8 * (SI_MAX_CHAN - 1 - chan);
|
||||
sr >>= chanShift;
|
||||
if (sr & SI_ERROR_NO_RESPONSE) {
|
||||
if (!(Type[chan] & SI_ERROR_BUSY)) {
|
||||
Type[chan] = SI_ERROR_NO_RESPONSE;
|
||||
}
|
||||
}
|
||||
OSRestoreInterrupts(enabled);
|
||||
return sr;
|
||||
}
|
||||
|
||||
void SISetCommand(s32 chan, u32 command)
|
||||
{
|
||||
__SIRegs[3 * chan] = command;
|
||||
}
|
||||
|
||||
u32 SIGetCommand(s32 chan)
|
||||
{
|
||||
return __SIRegs[3 * chan];
|
||||
}
|
||||
|
||||
void SITransferCommands(void)
|
||||
{
|
||||
__SIRegs[14] = 0x80000000;
|
||||
}
|
||||
|
||||
u32 SISetXY(u32 x, u32 y)
|
||||
{
|
||||
u32 poll;
|
||||
BOOL enabled;
|
||||
|
||||
poll = x << 16;
|
||||
poll |= y << 8;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
Si.poll &= ~(0x03ff0000 | 0x0000ff00);
|
||||
Si.poll |= poll;
|
||||
poll = Si.poll;
|
||||
__SIRegs[12] = poll;
|
||||
OSRestoreInterrupts(enabled);
|
||||
return poll;
|
||||
}
|
||||
|
||||
u32 SIEnablePolling(u32 poll)
|
||||
{
|
||||
BOOL enabled;
|
||||
u32 en;
|
||||
|
||||
if (poll == 0) {
|
||||
return Si.poll;
|
||||
}
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
|
||||
poll >>= (31 - 7);
|
||||
en = poll & 0xf0;
|
||||
|
||||
poll &= (en >> 4) | 0x03fffff0;
|
||||
|
||||
poll &= ~0x03ffff00;
|
||||
|
||||
Si.poll &= ~(en >> 4);
|
||||
|
||||
Si.poll |= poll;
|
||||
|
||||
poll = Si.poll;
|
||||
|
||||
SITransferCommands();
|
||||
|
||||
__SIRegs[12] = poll;
|
||||
|
||||
OSRestoreInterrupts(enabled);
|
||||
|
||||
return poll;
|
||||
}
|
||||
|
||||
u32 SIDisablePolling(u32 poll)
|
||||
{
|
||||
BOOL enabled;
|
||||
|
||||
if (poll == 0) {
|
||||
return Si.poll;
|
||||
}
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
|
||||
poll >>= (31 - 7);
|
||||
poll &= 0xf0;
|
||||
|
||||
poll = Si.poll & ~poll;
|
||||
|
||||
__SIRegs[12] = poll;
|
||||
Si.poll = poll;
|
||||
|
||||
OSRestoreInterrupts(enabled);
|
||||
return poll;
|
||||
}
|
||||
|
||||
static BOOL SIGetResponseRaw(s32 chan)
|
||||
{
|
||||
u32 sr;
|
||||
|
||||
sr = SIGetStatus(chan);
|
||||
if (sr & SI_ERROR_RDST) {
|
||||
InputBuffer[chan][0] = __SIRegs[3 * chan + 1];
|
||||
InputBuffer[chan][1] = __SIRegs[3 * chan + 2];
|
||||
InputBufferValid[chan] = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL SIGetResponse(s32 chan, void *data)
|
||||
{
|
||||
BOOL rc;
|
||||
BOOL enabled;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static void AlarmHandler(OSAlarm *alarm, OSContext *context)
|
||||
{
|
||||
#pragma unused(context)
|
||||
s32 chan;
|
||||
SIPacket *packet;
|
||||
|
||||
chan = alarm - Alarm;
|
||||
packet = &Packet[chan];
|
||||
if (packet->chan != -1) {
|
||||
if (__SITransfer(packet->chan, packet->output, packet->outputBytes, packet->input, packet->inputBytes, packet->callback)) {
|
||||
packet->chan = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL SITransfer(s32 chan, void *output, u32 outputBytes, void *input, u32 inputBytes, SICallback callback, OSTime delay)
|
||||
{
|
||||
BOOL enabled;
|
||||
SIPacket *packet = &Packet[chan];
|
||||
OSTime now;
|
||||
OSTime fire;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
if (packet->chan != -1 || Si.chan == chan) {
|
||||
OSRestoreInterrupts(enabled);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
now = __OSGetSystemTime();
|
||||
if (delay == 0) {
|
||||
fire = now;
|
||||
}
|
||||
else {
|
||||
fire = XferTime[chan] + delay;
|
||||
}
|
||||
if (now < fire) {
|
||||
delay = fire - now;
|
||||
OSSetAlarm(&Alarm[chan], delay, AlarmHandler);
|
||||
}
|
||||
else if (__SITransfer(chan, output, outputBytes, input, inputBytes, callback)) {
|
||||
OSRestoreInterrupts(enabled);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
packet->chan = chan;
|
||||
packet->output = output;
|
||||
packet->outputBytes = outputBytes;
|
||||
packet->input = input;
|
||||
packet->inputBytes = inputBytes;
|
||||
packet->callback = callback;
|
||||
packet->fire = fire;
|
||||
|
||||
OSRestoreInterrupts(enabled);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void CallTypeAndStatusCallback(s32 chan, u32 type)
|
||||
{
|
||||
SITypeAndStatusCallback callback;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
callback = TypeCallback[chan][i];
|
||||
if (callback) {
|
||||
TypeCallback[chan][i] = 0;
|
||||
callback(chan, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void GetTypeCallback(s32 chan, u32 error, OSContext *context)
|
||||
{
|
||||
static u32 cmdFixDevice[SI_MAX_CHAN];
|
||||
u32 type;
|
||||
u32 chanBit;
|
||||
BOOL fix;
|
||||
u32 id;
|
||||
|
||||
Type[chan] &= ~SI_ERROR_BUSY;
|
||||
Type[chan] |= error;
|
||||
TypeTime[chan] = __OSGetSystemTime();
|
||||
|
||||
type = Type[chan];
|
||||
|
||||
chanBit = SI_CHAN0_BIT >> chan;
|
||||
fix = (BOOL)(__PADFixBits & chanBit);
|
||||
__PADFixBits &= ~chanBit;
|
||||
|
||||
if ((error & (SI_ERROR_UNDER_RUN | SI_ERROR_OVER_RUN | SI_ERROR_NO_RESPONSE | SI_ERROR_COLLISION)) || (type & SI_TYPE_MASK) != SI_TYPE_DOLPHIN
|
||||
|| !(type & SI_GC_WIRELESS) || (type & SI_WIRELESS_IR)) {
|
||||
OSSetWirelessID(chan, 0);
|
||||
CallTypeAndStatusCallback(chan, Type[chan]);
|
||||
return;
|
||||
}
|
||||
|
||||
id = (u32)(OSGetWirelessID(chan) << 8);
|
||||
|
||||
if (fix && (id & SI_WIRELESS_FIX_ID)) {
|
||||
cmdFixDevice[chan] = 0x4Eu << 24 | (id & SI_WIRELESS_TYPE_ID) | SI_WIRELESS_FIX_ID;
|
||||
Type[chan] = SI_ERROR_BUSY;
|
||||
SITransfer(chan, &cmdFixDevice[chan], 3, &Type[chan], 3, GetTypeCallback, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (type & SI_WIRELESS_FIX_ID) {
|
||||
if ((id & SI_WIRELESS_TYPE_ID) != (type & SI_WIRELESS_TYPE_ID)) {
|
||||
if (!(id & SI_WIRELESS_FIX_ID)) {
|
||||
id = type & SI_WIRELESS_TYPE_ID;
|
||||
id |= SI_WIRELESS_FIX_ID;
|
||||
OSSetWirelessID(chan, (u16)((id >> 8) & 0xffff));
|
||||
}
|
||||
|
||||
cmdFixDevice[chan] = 0x4E << 24 | id;
|
||||
Type[chan] = SI_ERROR_BUSY;
|
||||
SITransfer(chan, &cmdFixDevice[chan], 3, &Type[chan], 3, GetTypeCallback, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (type & SI_WIRELESS_RECEIVED) {
|
||||
id = type & SI_WIRELESS_TYPE_ID;
|
||||
id |= SI_WIRELESS_FIX_ID;
|
||||
|
||||
OSSetWirelessID(chan, (u16)((id >> 8) & 0xffff));
|
||||
|
||||
cmdFixDevice[chan] = 0x4E << 24 | id;
|
||||
Type[chan] = SI_ERROR_BUSY;
|
||||
SITransfer(chan, &cmdFixDevice[chan], 3, &Type[chan], 3, GetTypeCallback, 0);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
OSSetWirelessID(chan, 0);
|
||||
}
|
||||
|
||||
CallTypeAndStatusCallback(chan, Type[chan]);
|
||||
}
|
||||
|
||||
u32 SIGetType(s32 chan)
|
||||
{
|
||||
static u32 cmdTypeAndStatus;
|
||||
BOOL enabled;
|
||||
u32 type;
|
||||
OSTime diff;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
|
||||
type = Type[chan];
|
||||
diff = __OSGetSystemTime() - TypeTime[chan];
|
||||
if (Si.poll & (0x80 >> chan)) {
|
||||
if (type != SI_ERROR_NO_RESPONSE) {
|
||||
TypeTime[chan] = __OSGetSystemTime();
|
||||
OSRestoreInterrupts(enabled);
|
||||
return type;
|
||||
}
|
||||
else {
|
||||
type = Type[chan] = SI_ERROR_BUSY;
|
||||
}
|
||||
}
|
||||
else if (diff <= OSMillisecondsToTicks(50) && type != SI_ERROR_NO_RESPONSE) {
|
||||
OSRestoreInterrupts(enabled);
|
||||
return type;
|
||||
}
|
||||
else if (diff <= OSMillisecondsToTicks(75)) {
|
||||
Type[chan] = SI_ERROR_BUSY;
|
||||
}
|
||||
else {
|
||||
type = Type[chan] = SI_ERROR_BUSY;
|
||||
}
|
||||
TypeTime[chan] = __OSGetSystemTime();
|
||||
|
||||
SITransfer(chan, &cmdTypeAndStatus, 1, &Type[chan], 3, GetTypeCallback, OSMicrosecondsToTicks(65));
|
||||
|
||||
OSRestoreInterrupts(enabled);
|
||||
return type;
|
||||
}
|
||||
|
||||
u32 SIGetTypeAsync(s32 chan, SITypeAndStatusCallback callback)
|
||||
{
|
||||
BOOL enabled;
|
||||
u32 type;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
type = SIGetType(chan);
|
||||
if (Type[chan] & SI_ERROR_BUSY) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
if (TypeCallback[chan][i] == callback) {
|
||||
break;
|
||||
}
|
||||
if (TypeCallback[chan][i] == 0) {
|
||||
TypeCallback[chan][i] = callback;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
callback(chan, type);
|
||||
}
|
||||
OSRestoreInterrupts(enabled);
|
||||
return type;
|
||||
}
|
||||
|
||||
u32 SIDecodeType(u32 type)
|
||||
{
|
||||
u32 error;
|
||||
|
||||
error = type & 0xff;
|
||||
type &= ~0xff;
|
||||
|
||||
if (error & SI_ERROR_NO_RESPONSE) {
|
||||
return SI_ERROR_NO_RESPONSE;
|
||||
}
|
||||
if (error & (SI_ERROR_UNDER_RUN | SI_ERROR_OVER_RUN | SI_ERROR_COLLISION | SI_ERROR_UNKNOWN)) {
|
||||
return SI_ERROR_UNKNOWN;
|
||||
}
|
||||
if (error) {
|
||||
return SI_ERROR_BUSY;
|
||||
}
|
||||
|
||||
if ((type & SI_TYPE_MASK) == SI_TYPE_N64) {
|
||||
switch (type & 0xffff0000) {
|
||||
case SI_N64_CONTROLLER:
|
||||
case SI_N64_MIC:
|
||||
case SI_N64_KEYBOARD:
|
||||
case SI_N64_MOUSE:
|
||||
case SI_GBA:
|
||||
return type & 0xffff0000;
|
||||
break;
|
||||
}
|
||||
return SI_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
if ((type & SI_TYPE_MASK) != SI_TYPE_GC) {
|
||||
|
||||
return SI_ERROR_UNKNOWN;
|
||||
}
|
||||
switch (type & 0xffff0000) {
|
||||
case SI_GC_CONTROLLER:
|
||||
case SI_GC_STEERING:
|
||||
return type & 0xffff0000;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((type & 0xffe00000) == SI_GC_KEYBOARD) {
|
||||
return SI_GC_KEYBOARD;
|
||||
}
|
||||
|
||||
if ((type & SI_GC_WIRELESS) && !(type & SI_WIRELESS_IR)) {
|
||||
if ((type & SI_GC_WAVEBIRD) == SI_GC_WAVEBIRD) {
|
||||
return SI_GC_WAVEBIRD;
|
||||
}
|
||||
else if (!(type & SI_WIRELESS_STATE)) {
|
||||
return SI_GC_RECEIVER;
|
||||
}
|
||||
}
|
||||
|
||||
if ((type & SI_GC_CONTROLLER) == SI_GC_CONTROLLER) {
|
||||
return SI_GC_CONTROLLER;
|
||||
}
|
||||
return SI_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
u32 SIProbe(s32 chan)
|
||||
{
|
||||
return SIDecodeType(SIGetType(chan));
|
||||
}
|
||||
|
||||
char *SIGetTypeString(u32 type)
|
||||
{
|
||||
switch (SIDecodeType(type)) {
|
||||
case SI_ERROR_NO_RESPONSE:
|
||||
return "No response";
|
||||
case SI_N64_CONTROLLER:
|
||||
return "N64 controller";
|
||||
case SI_N64_MIC:
|
||||
return "N64 microphone";
|
||||
case SI_N64_KEYBOARD:
|
||||
return "N64 keyboard";
|
||||
case SI_N64_MOUSE:
|
||||
return "N64 mouse";
|
||||
case SI_GBA:
|
||||
return "GameBoy Advance";
|
||||
case SI_GC_CONTROLLER:
|
||||
return "Standard controller";
|
||||
case SI_GC_RECEIVER:
|
||||
return "Wireless receiver";
|
||||
case SI_GC_WAVEBIRD:
|
||||
return "WaveBird controller";
|
||||
case SI_GC_KEYBOARD:
|
||||
return "Keyboard";
|
||||
case SI_GC_STEERING:
|
||||
return "Steering";
|
||||
}
|
||||
}
|
||||
56
src/dolphin/si/SISamplingRate.c
Normal file
56
src/dolphin/si/SISamplingRate.c
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
#include "dolphin/sipriv.h"
|
||||
#include "dolphin/vi.h"
|
||||
#include "dolphin/hw_regs.h"
|
||||
|
||||
#pragma dont_inline on
|
||||
static u32 SamplingRate;
|
||||
|
||||
typedef struct XY {
|
||||
u16 line;
|
||||
u8 count;
|
||||
} XY;
|
||||
|
||||
static XY XYNTSC[12] = {
|
||||
{263 - 17, 2}, {15, 18}, {30, 9}, {44, 6}, {52, 5}, {65, 4},
|
||||
{87, 3}, {87, 3}, {87, 3}, {131, 2}, {131, 2}, {131, 2},
|
||||
};
|
||||
|
||||
static XY XYPAL[12] = {
|
||||
{313 - 17, 2}, {15, 21}, {29, 11}, {45, 7}, {52, 6}, {63, 5},
|
||||
{78, 4}, {104, 3}, {104, 3}, {104, 3}, {104, 3}, {156, 2},
|
||||
};
|
||||
|
||||
void SISetSamplingRate(u32 msec) {
|
||||
XY* xy;
|
||||
BOOL enabled;
|
||||
|
||||
if (msec > 11) {
|
||||
msec = 11;
|
||||
}
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
|
||||
SamplingRate = msec;
|
||||
|
||||
switch (VIGetTvFormat()) {
|
||||
case VI_NTSC:
|
||||
case VI_MPAL:
|
||||
case VI_EURGB60:
|
||||
xy = XYNTSC;
|
||||
break;
|
||||
case VI_PAL:
|
||||
xy = XYPAL;
|
||||
break;
|
||||
default:
|
||||
OSReport("SISetSamplingRate: unknown TV format. Use default.");
|
||||
msec = 0;
|
||||
xy = XYNTSC;
|
||||
break;
|
||||
}
|
||||
|
||||
SISetXY((__VIRegs[54] & 1 ? 2u : 1u) * xy[msec].line, xy[msec].count);
|
||||
OSRestoreInterrupts(enabled);
|
||||
}
|
||||
|
||||
void SIRefreshSamplingRate() { SISetSamplingRate(SamplingRate); }
|
||||
#pragma dont_inline reset
|
||||
Loading…
Add table
Add a link
Reference in a new issue