Merge pull request #445 from dbalatoni13/main

Imported lots of dolphin library files
This commit is contained in:
Liam Coleman 2024-11-11 21:04:51 -06:00 committed by GitHub
commit be6ea5de09
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
40 changed files with 7486 additions and 100 deletions

View file

@ -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

View file

@ -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(

View file

@ -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
View 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

View 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

View 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

View 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

View 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

View 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

View 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

View file

@ -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
View 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

View file

@ -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
View 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;
}

View 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);
}

View 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, &currentDir);
errors += VerifyFAT(card, &currentFat);
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;
}

View 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);
}

View 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
View 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);
}

View 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);
}

View 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;
}

View 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
View 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
View 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
View 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);
}

View 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
View 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);
}

View 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);
}

View 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
View 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
View 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
View 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);
}

View 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
View 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

View 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
View 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
View 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
View 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
View 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";
}
}

View 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