Link in arq and most of dvd
This commit is contained in:
parent
92bc9d78fe
commit
53fba73d33
10 changed files with 1487 additions and 10 deletions
|
|
@ -3911,7 +3911,7 @@ lbl_8012E70A = .data:0x8012E70A; // type:object size:0xB data:string
|
|||
lbl_8012E715 = .data:0x8012E715; // type:object size:0x273
|
||||
lbl_8012E988 = .data:0x8012E988; // type:object size:0x12 data:string
|
||||
lbl_8012E99A = .data:0x8012E99A; // type:object size:0xD6
|
||||
HuSndGrpTbl = .data:0x8012EA70; // type:object size:0x5B0
|
||||
sndGrpTable = .data:0x8012EA70; // type:object size:0x5B0
|
||||
lbl_8012F020 = .data:0x8012F020; // type:object size:0x94
|
||||
lbl_8012F0B4 = .data:0x8012F0B4; // type:object size:0x11 data:string
|
||||
lbl_8012F0C5 = .data:0x8012F0C5; // type:object size:0x3A
|
||||
|
|
@ -5692,7 +5692,7 @@ shdwChanged = .sbss:0x801D4460; // type:object size:0x8 scope:local align:8 data
|
|||
CurrTiming = .sbss:0x801D4468; // type:object size:0x4 scope:local data:4byte
|
||||
CurrTvMode = .sbss:0x801D446C; // type:object size:0x4 scope:local data:4byte
|
||||
FBSet = .sbss:0x801D4470; // type:object size:0x4 scope:local data:4byte
|
||||
message$343 = .sbss:0x801D4474; // type:object size:0x4 scope:local data:4byte
|
||||
message$320 = .sbss:0x801D4474; // type:object size:0x4 scope:local data:4byte
|
||||
rmode = .sbss:0x801D4478; // type:object size:0x8 scope:local data:4byte
|
||||
fontShift = .sbss:0x801D4480; // type:object size:0x8 scope:local data:4byte
|
||||
DemoStat = .sbss:0x801D4488; // type:object size:0x4 scope:local data:4byte
|
||||
|
|
|
|||
14
configure.py
14
configure.py
|
|
@ -494,18 +494,18 @@ config.libs = [
|
|||
DolphinLib(
|
||||
"dvd",
|
||||
[
|
||||
Object(NonMatching, "dolphin/dvd/dvdlow.c"),
|
||||
Object(NonMatching, "dolphin/dvd/dvdfs.c"),
|
||||
Object(Matching, "dolphin/dvd/dvdlow.c"),
|
||||
Object(Matching, "dolphin/dvd/dvdfs.c"),
|
||||
Object(NonMatching, "dolphin/dvd/dvd.c"),
|
||||
Object(NonMatching, "dolphin/dvd/dvdqueue.c"),
|
||||
Object(NonMatching, "dolphin/dvd/dvderror.c"),
|
||||
Object(NonMatching, "dolphin/dvd/fstload.c"),
|
||||
Object(Matching, "dolphin/dvd/dvdqueue.c"),
|
||||
Object(Matching, "dolphin/dvd/dvderror.c"),
|
||||
Object(Matching, "dolphin/dvd/fstload.c"),
|
||||
],
|
||||
),
|
||||
DolphinLib(
|
||||
"vi",
|
||||
[
|
||||
Object(NonMatching, "dolphin/vi.c"),
|
||||
Object(Matching, "dolphin/vi.c"),
|
||||
],
|
||||
),
|
||||
DolphinLib(
|
||||
|
|
@ -534,7 +534,7 @@ config.libs = [
|
|||
"ar",
|
||||
[
|
||||
Object(NonMatching, "dolphin/ar/ar.c"),
|
||||
Object(NonMatching, "dolphin/ar/arq.c"),
|
||||
Object(Matching, "dolphin/ar/arq.c"),
|
||||
],
|
||||
),
|
||||
DolphinLib(
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include "dolphin/DVDPriv.h"
|
||||
#include "dolphin/types.h"
|
||||
|
||||
typedef struct OSBootInfo {
|
||||
typedef struct OSBootInfo_s {
|
||||
DVDDiskID DVDDiskID;
|
||||
u32 magic;
|
||||
u32 version;
|
||||
|
|
|
|||
251
src/dolphin/ar/ar.c
Normal file
251
src/dolphin/ar/ar.c
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
#include "dolphin/ar.h"
|
||||
|
||||
#include "dolphin/hw_regs.h"
|
||||
#include "dolphin/os.h"
|
||||
|
||||
static ARCallback __AR_Callback;
|
||||
static u32 __AR_Size;
|
||||
static u32 __AR_InternalSize;
|
||||
static u32 __AR_ExpansionSize;
|
||||
|
||||
static u32 __AR_StackPointer;
|
||||
static u32 __AR_FreeBlocks;
|
||||
static u32* __AR_BlockLength;
|
||||
|
||||
static volatile BOOL __AR_init_flag = FALSE;
|
||||
|
||||
static void __ARHandler(__OSInterrupt interrupt, OSContext* context);
|
||||
static void __ARChecksize(void);
|
||||
static void __ARClearArea(u32 start_addr, u32 length);
|
||||
|
||||
ARCallback ARRegisterDMACallback(ARCallback callback) {
|
||||
ARCallback oldCb;
|
||||
BOOL enabled;
|
||||
oldCb = __AR_Callback;
|
||||
enabled = OSDisableInterrupts();
|
||||
__AR_Callback = callback;
|
||||
OSRestoreInterrupts(enabled);
|
||||
return oldCb;
|
||||
}
|
||||
|
||||
u32 ARGetDMAStatus() {
|
||||
BOOL enabled;
|
||||
u32 val;
|
||||
enabled = OSDisableInterrupts();
|
||||
val = __DSPRegs[5] & 0x0200;
|
||||
OSRestoreInterrupts(enabled);
|
||||
return val;
|
||||
}
|
||||
|
||||
void ARStartDMA(u32 type, u32 mainmem_addr, u32 aram_addr, u32 length) {
|
||||
BOOL enabled;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
|
||||
__DSPRegs[16] = (u16)(__DSPRegs[16] & ~0x3ff) | (u16)(mainmem_addr >> 16);
|
||||
__DSPRegs[17] = (u16)(__DSPRegs[17] & ~0xffe0) | (u16)(mainmem_addr & 0xffff);
|
||||
__DSPRegs[18] = (u16)(__DSPRegs[18] & ~0x3ff) | (u16)(aram_addr >> 16);
|
||||
__DSPRegs[19] = (u16)(__DSPRegs[19] & ~0xffe0) | (u16)(aram_addr & 0xffff);
|
||||
__DSPRegs[20] = (u16)((__DSPRegs[20] & ~0x8000) | (type << 15));
|
||||
__DSPRegs[20] = (u16)(__DSPRegs[20] & ~0x3ff) | (u16)(length >> 16);
|
||||
__DSPRegs[21] = (u16)(__DSPRegs[21] & ~0xffe0) | (u16)(length & 0xffff);
|
||||
OSRestoreInterrupts(enabled);
|
||||
}
|
||||
|
||||
u32 ARAlloc(u32 length) {
|
||||
u32 tmp;
|
||||
BOOL enabled;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
tmp = __AR_StackPointer;
|
||||
__AR_StackPointer += length;
|
||||
*__AR_BlockLength = length;
|
||||
__AR_BlockLength++;
|
||||
__AR_FreeBlocks--;
|
||||
OSRestoreInterrupts(enabled);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
#if NONMATCHING
|
||||
u32 ARFree(u32* length) {
|
||||
BOOL old;
|
||||
|
||||
old = OSDisableInterrupts();
|
||||
|
||||
__AR_BlockLength--;
|
||||
|
||||
if (length) {
|
||||
*length = *__AR_BlockLength;
|
||||
}
|
||||
|
||||
__AR_StackPointer -= *__AR_BlockLength;
|
||||
|
||||
__AR_FreeBlocks++;
|
||||
|
||||
OSRestoreInterrupts(old);
|
||||
|
||||
return __AR_StackPointer;
|
||||
}
|
||||
#else
|
||||
/* clang-format off */
|
||||
#pragma push
|
||||
#pragma optimization_level 0
|
||||
#pragma optimizewithasm off
|
||||
asm u32 ARFree(u32* length) {
|
||||
nofralloc
|
||||
mflr r0
|
||||
stw r0, 4(r1)
|
||||
stwu r1, -0x18(r1)
|
||||
stw r31, 0x14(r1)
|
||||
mr r31, r3
|
||||
bl OSDisableInterrupts
|
||||
lwz r4, __AR_BlockLength
|
||||
cmplwi r31, 0
|
||||
addi r0, r4, -4
|
||||
stw r0, __AR_BlockLength
|
||||
beq lbl_8036DAB4
|
||||
lwz r4, __AR_BlockLength
|
||||
lwz r0, 0(r4)
|
||||
stw r0, 0(r31)
|
||||
lbl_8036DAB4:
|
||||
lwz r5, __AR_BlockLength
|
||||
lwz r4, __AR_FreeBlocks
|
||||
lwz r6, 0(r5)
|
||||
addi r0, r4, 1
|
||||
lwz r5, __AR_StackPointer
|
||||
stw r0, __AR_FreeBlocks
|
||||
subf r0, r6, r5
|
||||
stw r0, __AR_StackPointer
|
||||
bl OSRestoreInterrupts
|
||||
lwz r3, __AR_StackPointer
|
||||
lwz r0, 0x1c(r1)
|
||||
lwz r31, 0x14(r1)
|
||||
addi r1, r1, 0x18
|
||||
mtlr r0
|
||||
blr
|
||||
}
|
||||
#pragma pop
|
||||
/* clang-format on */
|
||||
#endif
|
||||
|
||||
BOOL ARCheckInit() { return __AR_init_flag; }
|
||||
|
||||
u32 ARInit(u32* stack_index_addr, u32 num_entries) {
|
||||
|
||||
BOOL old;
|
||||
u16 refresh;
|
||||
|
||||
if (__AR_init_flag == TRUE) {
|
||||
return 0x4000;
|
||||
}
|
||||
|
||||
old = OSDisableInterrupts();
|
||||
|
||||
__AR_Callback = NULL;
|
||||
|
||||
__OSSetInterruptHandler(__OS_INTERRUPT_DSP_ARAM, __ARHandler);
|
||||
__OSUnmaskInterrupts(OS_INTERRUPTMASK_DSP_ARAM);
|
||||
|
||||
__AR_StackPointer = 0x4000;
|
||||
__AR_FreeBlocks = num_entries;
|
||||
__AR_BlockLength = stack_index_addr;
|
||||
|
||||
refresh = (u16)(__DSPRegs[13] & 0x000000ff);
|
||||
|
||||
__DSPRegs[13] = (u16)((__DSPRegs[13] & ~0x000000ff) | (refresh & 0x000000ff));
|
||||
|
||||
__ARChecksize();
|
||||
|
||||
__AR_init_flag = TRUE;
|
||||
|
||||
OSRestoreInterrupts(old);
|
||||
|
||||
return __AR_StackPointer;
|
||||
}
|
||||
|
||||
u32 ARGetBaseAddress(void) { return 0x4000; }
|
||||
|
||||
void ARSetSize(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
u32 ARGetSize() { return __AR_Size; }
|
||||
|
||||
static void __ARHandler(__OSInterrupt interrupt, OSContext* context) {
|
||||
|
||||
OSContext exceptionContext;
|
||||
u16 tmp;
|
||||
|
||||
tmp = __DSPRegs[5];
|
||||
tmp = (u16)((tmp & ~0x00000088) | 0x20);
|
||||
__DSPRegs[5] = tmp;
|
||||
|
||||
OSClearContext(&exceptionContext);
|
||||
OSSetCurrentContext(&exceptionContext);
|
||||
|
||||
if (__AR_Callback) {
|
||||
(*__AR_Callback)();
|
||||
}
|
||||
|
||||
OSClearContext(&exceptionContext);
|
||||
OSSetCurrentContext(context);
|
||||
}
|
||||
|
||||
#define RoundUP32(x) (((u32)(x) + 32 - 1) & ~(32 - 1))
|
||||
|
||||
void __ARClearInterrupt(void) {
|
||||
|
||||
u16 tmp;
|
||||
tmp = __DSPRegs[5];
|
||||
tmp = (u16)((tmp & ~(0x00000080 | 0x00000008)) | 0x00000020);
|
||||
__DSPRegs[5] = tmp;
|
||||
}
|
||||
u16 __ARGetInterruptStatus(void) { return ((u16)(__DSPRegs[5] & 0x0200)); }
|
||||
|
||||
static void __ARWaitForDMA(void) {
|
||||
|
||||
while (__DSPRegs[5] & 0x0200) {
|
||||
}
|
||||
}
|
||||
|
||||
static void __ARWriteDMA(u32 mmem_addr, u32 aram_addr, u32 length) {
|
||||
|
||||
__DSPRegs[16] = (u16)((__DSPRegs[16] & ~0x03ff) | (u16)(mmem_addr >> 16));
|
||||
__DSPRegs[16 + 1] = (u16)((__DSPRegs[16 + 1] & ~0xffe0) | (u16)(mmem_addr & 0xffff));
|
||||
|
||||
__DSPRegs[18] = (u16)((__DSPRegs[18] & ~0x03ff) | (u16)(aram_addr >> 16));
|
||||
__DSPRegs[18 + 1] = (u16)((__DSPRegs[18 + 1] & ~0xffe0) | (u16)(aram_addr & 0xffff));
|
||||
|
||||
__DSPRegs[20] = (u16)(__DSPRegs[20] & ~0x8000);
|
||||
|
||||
__DSPRegs[20] = (u16)((__DSPRegs[20] & ~0x03ff) | (u16)(length >> 16));
|
||||
__DSPRegs[20 + 1] = (u16)((__DSPRegs[20 + 1] & ~0xffe0) | (u16)(length & 0xffff));
|
||||
|
||||
__ARWaitForDMA();
|
||||
|
||||
__ARClearInterrupt();
|
||||
}
|
||||
|
||||
static void __ARReadDMA(u32 mmem_addr, u32 aram_addr, u32 length) {
|
||||
|
||||
__DSPRegs[16] = (u16)((__DSPRegs[16] & ~0x03ff) | (u16)(mmem_addr >> 16));
|
||||
__DSPRegs[16 + 1] = (u16)((__DSPRegs[16 + 1] & ~0xffe0) | (u16)(mmem_addr & 0xffff));
|
||||
|
||||
__DSPRegs[18] = (u16)((__DSPRegs[18] & ~0x03ff) | (u16)(aram_addr >> 16));
|
||||
__DSPRegs[18 + 1] = (u16)((__DSPRegs[18 + 1] & ~0xffe0) | (u16)(aram_addr & 0xffff));
|
||||
|
||||
__DSPRegs[20] = (u16)(__DSPRegs[20] | 0x8000);
|
||||
|
||||
__DSPRegs[20] = (u16)((__DSPRegs[20] & ~0x03ff) | (u16)(length >> 16));
|
||||
__DSPRegs[20 + 1] = (u16)((__DSPRegs[20 + 1] & ~0xffe0) | (u16)(length & 0xffff));
|
||||
|
||||
__ARWaitForDMA();
|
||||
|
||||
__ARClearInterrupt();
|
||||
}
|
||||
|
||||
static void __ARChecksize(void) {
|
||||
//TODO: Implement for this SDK version
|
||||
}
|
||||
168
src/dolphin/ar/arq.c
Normal file
168
src/dolphin/ar/arq.c
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
#include "dolphin/arq.h"
|
||||
#include "dolphin/os.h"
|
||||
|
||||
static ARQRequest* __ARQRequestQueueHi;
|
||||
static ARQRequest* __ARQRequestTailHi;
|
||||
static ARQRequest* __ARQRequestQueueLo;
|
||||
static ARQRequest* __ARQRequestTailLo;
|
||||
static ARQRequest* __ARQRequestPendingHi;
|
||||
static ARQRequest* __ARQRequestPendingLo;
|
||||
static ARQCallback __ARQCallbackHi;
|
||||
static ARQCallback __ARQCallbackLo;
|
||||
static u32 __ARQChunkSize;
|
||||
|
||||
static volatile BOOL __ARQ_init_flag = FALSE;
|
||||
|
||||
void __ARQPopTaskQueueHi(void);
|
||||
void __ARQServiceQueueLo(void);
|
||||
void __ARQCallbackHack(void);
|
||||
void __ARQInterruptServiceRoutine(void);
|
||||
void __ARQInitTempQueue(void);
|
||||
void __ARQPushTempQueue(ARQRequest* task);
|
||||
|
||||
void __ARQPopTaskQueueHi(void) {
|
||||
|
||||
if (__ARQRequestQueueHi) {
|
||||
if (__ARQRequestQueueHi->type == ARQ_TYPE_MRAM_TO_ARAM) {
|
||||
ARStartDMA(__ARQRequestQueueHi->type, __ARQRequestQueueHi->source, __ARQRequestQueueHi->dest,
|
||||
__ARQRequestQueueHi->length);
|
||||
} else {
|
||||
ARStartDMA(__ARQRequestQueueHi->type, __ARQRequestQueueHi->dest, __ARQRequestQueueHi->source,
|
||||
__ARQRequestQueueHi->length);
|
||||
}
|
||||
|
||||
__ARQCallbackHi = __ARQRequestQueueHi->callback;
|
||||
|
||||
__ARQRequestPendingHi = __ARQRequestQueueHi;
|
||||
|
||||
__ARQRequestQueueHi = __ARQRequestQueueHi->next;
|
||||
}
|
||||
}
|
||||
|
||||
void __ARQServiceQueueLo(void) {
|
||||
|
||||
if ((__ARQRequestPendingLo == NULL) && (__ARQRequestQueueLo)) {
|
||||
__ARQRequestPendingLo = __ARQRequestQueueLo;
|
||||
|
||||
__ARQRequestQueueLo = __ARQRequestQueueLo->next;
|
||||
}
|
||||
|
||||
if (__ARQRequestPendingLo) {
|
||||
if (__ARQRequestPendingLo->length <= __ARQChunkSize) {
|
||||
if (__ARQRequestPendingLo->type == ARQ_TYPE_MRAM_TO_ARAM)
|
||||
ARStartDMA(__ARQRequestPendingLo->type, __ARQRequestPendingLo->source,
|
||||
__ARQRequestPendingLo->dest, __ARQRequestPendingLo->length);
|
||||
else
|
||||
ARStartDMA(__ARQRequestPendingLo->type, __ARQRequestPendingLo->dest,
|
||||
__ARQRequestPendingLo->source, __ARQRequestPendingLo->length);
|
||||
|
||||
__ARQCallbackLo = __ARQRequestPendingLo->callback;
|
||||
} else {
|
||||
if (__ARQRequestPendingLo->type == ARQ_TYPE_MRAM_TO_ARAM)
|
||||
ARStartDMA(__ARQRequestPendingLo->type, __ARQRequestPendingLo->source,
|
||||
__ARQRequestPendingLo->dest, __ARQChunkSize);
|
||||
else
|
||||
ARStartDMA(__ARQRequestPendingLo->type, __ARQRequestPendingLo->dest,
|
||||
__ARQRequestPendingLo->source, __ARQChunkSize);
|
||||
}
|
||||
|
||||
__ARQRequestPendingLo->length -= __ARQChunkSize;
|
||||
__ARQRequestPendingLo->source += __ARQChunkSize;
|
||||
__ARQRequestPendingLo->dest += __ARQChunkSize;
|
||||
}
|
||||
}
|
||||
void __ARQCallbackHack(void) { return; }
|
||||
|
||||
void __ARQInterruptServiceRoutine(void) {
|
||||
|
||||
if (__ARQCallbackHi) {
|
||||
(*__ARQCallbackHi)((u32)__ARQRequestPendingHi);
|
||||
__ARQRequestPendingHi = NULL;
|
||||
__ARQCallbackHi = NULL;
|
||||
}
|
||||
|
||||
else if (__ARQCallbackLo) {
|
||||
(*__ARQCallbackLo)((u32)__ARQRequestPendingLo);
|
||||
__ARQRequestPendingLo = NULL;
|
||||
__ARQCallbackLo = NULL;
|
||||
}
|
||||
|
||||
__ARQPopTaskQueueHi();
|
||||
|
||||
if (__ARQRequestPendingHi == NULL)
|
||||
__ARQServiceQueueLo();
|
||||
}
|
||||
|
||||
void ARQInit(void) {
|
||||
|
||||
if (TRUE == __ARQ_init_flag) {
|
||||
return;
|
||||
}
|
||||
|
||||
__ARQRequestQueueHi = __ARQRequestQueueLo = NULL;
|
||||
__ARQChunkSize = ARQ_CHUNK_SIZE_DEFAULT;
|
||||
ARRegisterDMACallback(&__ARQInterruptServiceRoutine);
|
||||
__ARQRequestPendingHi = NULL;
|
||||
__ARQRequestPendingLo = NULL;
|
||||
__ARQCallbackHi = NULL;
|
||||
__ARQCallbackLo = NULL;
|
||||
__ARQ_init_flag = TRUE;
|
||||
}
|
||||
|
||||
void ARQPostRequest(ARQRequest* request, u32 owner, u32 type, u32 priority, u32 source, u32 dest,
|
||||
u32 length, ARQCallback callback) {
|
||||
|
||||
BOOL enabled;
|
||||
|
||||
request->next = NULL;
|
||||
request->owner = owner;
|
||||
request->type = type;
|
||||
request->source = source;
|
||||
request->dest = dest;
|
||||
request->length = length;
|
||||
|
||||
if (callback) {
|
||||
request->callback = callback;
|
||||
} else {
|
||||
request->callback = (ARQCallback)&__ARQCallbackHack;
|
||||
}
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
|
||||
switch (priority) {
|
||||
case ARQ_PRIORITY_LOW:
|
||||
|
||||
if (__ARQRequestQueueLo) {
|
||||
__ARQRequestTailLo->next = request;
|
||||
} else {
|
||||
__ARQRequestQueueLo = request;
|
||||
}
|
||||
__ARQRequestTailLo = request;
|
||||
|
||||
break;
|
||||
|
||||
case ARQ_PRIORITY_HIGH:
|
||||
|
||||
if (__ARQRequestQueueHi) {
|
||||
__ARQRequestTailHi->next = request;
|
||||
} else {
|
||||
__ARQRequestQueueHi = request;
|
||||
}
|
||||
|
||||
__ARQRequestTailHi = request;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ((__ARQRequestPendingHi == NULL) && (__ARQRequestPendingLo == NULL)) {
|
||||
__ARQPopTaskQueueHi();
|
||||
|
||||
if (__ARQRequestPendingHi == NULL) {
|
||||
__ARQServiceQueueLo();
|
||||
}
|
||||
}
|
||||
|
||||
OSRestoreInterrupts(enabled);
|
||||
}
|
||||
|
||||
u32 ARQGetChunkSize(void) { return __ARQChunkSize; }
|
||||
56
src/dolphin/dvd/dvderror.c
Normal file
56
src/dolphin/dvd/dvderror.c
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
#include "dolphin/DVDPriv.h"
|
||||
#include "dolphin/OSRtcPriv.h"
|
||||
|
||||
static u32 ErrorTable[] = {
|
||||
0, 0x00023A00, 0x00062800, 0x00030200, 0x00031100, 0x00052000,
|
||||
0x00052001, 0x00052100, 0x00052400, 0x00052401, 0x00052402, 0x000B5A01,
|
||||
0x00056300, 0x00020401, 0x00020400, 0x00040800, 0x00100007, 0,
|
||||
};
|
||||
|
||||
static u8 ErrorCode2Num(u32 errorCode) {
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < sizeof(ErrorTable) / sizeof(ErrorTable[0]); i++) {
|
||||
if (ErrorTable[i] == errorCode) {
|
||||
return (u8)i;
|
||||
}
|
||||
}
|
||||
|
||||
if ((errorCode >= 0x00100000) && (errorCode <= 0x00100008)) {
|
||||
return 17;
|
||||
}
|
||||
|
||||
return 29;
|
||||
}
|
||||
|
||||
static u8 Convert(u32 error) {
|
||||
u32 statusCode;
|
||||
u32 errorCode;
|
||||
u8 errorNum;
|
||||
|
||||
if (error == 0x01234567)
|
||||
return 255;
|
||||
|
||||
if (error == 0x01234568)
|
||||
return 254;
|
||||
|
||||
statusCode = (error & 0xff000000) >> 24;
|
||||
errorCode = error & 0x00ffffff;
|
||||
|
||||
errorNum = ErrorCode2Num(errorCode);
|
||||
if (statusCode >= 6)
|
||||
statusCode = 6;
|
||||
|
||||
return (u8)(statusCode * 30 + errorNum);
|
||||
}
|
||||
|
||||
void __DVDStoreErrorCode(u32 error) {
|
||||
OSSramEx* sram;
|
||||
u8 num;
|
||||
|
||||
num = Convert(error);
|
||||
|
||||
sram = __OSLockSramEx();
|
||||
sram->dvdErrorCode = num;
|
||||
__OSUnlockSramEx(TRUE);
|
||||
}
|
||||
356
src/dolphin/dvd/dvdfs.c
Normal file
356
src/dolphin/dvd/dvdfs.c
Normal file
|
|
@ -0,0 +1,356 @@
|
|||
|
||||
#include "dolphin/DVDPriv.h"
|
||||
#include "dolphin/os.h"
|
||||
#include "dolphin/os/OSBootInfo.h"
|
||||
|
||||
typedef struct FSTEntry FSTEntry;
|
||||
|
||||
struct FSTEntry {
|
||||
unsigned int isDirAndStringOff;
|
||||
unsigned int parentOrPosition;
|
||||
unsigned int nextEntryOrLength;
|
||||
};
|
||||
|
||||
static OSBootInfo* BootInfo;
|
||||
static FSTEntry* FstStart;
|
||||
static char* FstStringStart;
|
||||
static u32 MaxEntryNum;
|
||||
static u32 currentDirectory = 0;
|
||||
OSThreadQueue __DVDThreadQueue;
|
||||
u32 __DVDLongFileNameFlag = 0;
|
||||
|
||||
static void cbForReadAsync(s32 result, DVDCommandBlock* block);
|
||||
static void cbForReadSync(s32 result, DVDCommandBlock* block);
|
||||
static void cbForSeekAsync(s32 result, DVDCommandBlock* block);
|
||||
static void cbForSeekSync(s32 result, DVDCommandBlock* block);
|
||||
static void cbForPrepareStreamAsync(s32 result, DVDCommandBlock* block);
|
||||
static void cbForPrepareStreamSync(s32 result, DVDCommandBlock* block);
|
||||
|
||||
void __DVDFSInit() {
|
||||
BootInfo = (OSBootInfo*)OSPhysicalToCached(0);
|
||||
FstStart = (FSTEntry*)BootInfo->FSTLocation;
|
||||
|
||||
if (FstStart) {
|
||||
MaxEntryNum = FstStart[0].nextEntryOrLength;
|
||||
FstStringStart = (char*)&(FstStart[MaxEntryNum]);
|
||||
}
|
||||
}
|
||||
|
||||
/* For convenience */
|
||||
#define entryIsDir(i) (((FstStart[i].isDirAndStringOff & 0xff000000) == 0) ? FALSE : TRUE)
|
||||
#define stringOff(i) (FstStart[i].isDirAndStringOff & ~0xff000000)
|
||||
#define parentDir(i) (FstStart[i].parentOrPosition)
|
||||
#define nextDir(i) (FstStart[i].nextEntryOrLength)
|
||||
#define filePosition(i) (FstStart[i].parentOrPosition)
|
||||
#define fileLength(i) (FstStart[i].nextEntryOrLength)
|
||||
|
||||
static BOOL isSame(const char* path, const char* string) {
|
||||
while (*string != '\0') {
|
||||
if (tolower(*path++) != tolower(*string++)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if ((*path == '/') || (*path == '\0')) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 DVDConvertPathToEntrynum(char* pathPtr) {
|
||||
const char* ptr;
|
||||
char* stringPtr;
|
||||
BOOL isDir;
|
||||
u32 length;
|
||||
u32 dirLookAt;
|
||||
u32 i;
|
||||
const char* origPathPtr = pathPtr;
|
||||
const char* extentionStart;
|
||||
BOOL illegal;
|
||||
BOOL extention;
|
||||
|
||||
dirLookAt = currentDirectory;
|
||||
|
||||
while (1) {
|
||||
|
||||
if (*pathPtr == '\0') {
|
||||
return (s32)dirLookAt;
|
||||
} else if (*pathPtr == '/') {
|
||||
dirLookAt = 0;
|
||||
pathPtr++;
|
||||
continue;
|
||||
} else if (*pathPtr == '.') {
|
||||
if (*(pathPtr + 1) == '.') {
|
||||
if (*(pathPtr + 2) == '/') {
|
||||
dirLookAt = parentDir(dirLookAt);
|
||||
pathPtr += 3;
|
||||
continue;
|
||||
} else if (*(pathPtr + 2) == '\0') {
|
||||
return (s32)parentDir(dirLookAt);
|
||||
}
|
||||
} else if (*(pathPtr + 1) == '/') {
|
||||
pathPtr += 2;
|
||||
continue;
|
||||
} else if (*(pathPtr + 1) == '\0') {
|
||||
return (s32)dirLookAt;
|
||||
}
|
||||
}
|
||||
|
||||
if (__DVDLongFileNameFlag == 0) {
|
||||
extention = FALSE;
|
||||
illegal = FALSE;
|
||||
|
||||
for (ptr = pathPtr; (*ptr != '\0') && (*ptr != '/'); ptr++) {
|
||||
if (*ptr == '.') {
|
||||
if ((ptr - pathPtr > 8) || (extention == TRUE)) {
|
||||
illegal = TRUE;
|
||||
break;
|
||||
}
|
||||
extention = TRUE;
|
||||
extentionStart = ptr + 1;
|
||||
|
||||
} else if (*ptr == ' ')
|
||||
illegal = TRUE;
|
||||
}
|
||||
|
||||
if ((extention == TRUE) && (ptr - extentionStart > 3))
|
||||
illegal = TRUE;
|
||||
|
||||
if (illegal)
|
||||
OSPanic(__FILE__, 376,
|
||||
"DVDConvertEntrynumToPath(possibly DVDOpen or DVDChangeDir or DVDOpenDir): "
|
||||
"specified directory or file (%s) doesn't match standard 8.3 format. This is a "
|
||||
"temporary restriction and will be removed soon\n",
|
||||
origPathPtr);
|
||||
} else {
|
||||
for (ptr = pathPtr; (*ptr != '\0') && (*ptr != '/'); ptr++)
|
||||
;
|
||||
}
|
||||
|
||||
isDir = (*ptr == '\0') ? FALSE : TRUE;
|
||||
length = (u32)(ptr - pathPtr);
|
||||
|
||||
ptr = pathPtr;
|
||||
|
||||
for (i = dirLookAt + 1; i < nextDir(dirLookAt); i = entryIsDir(i) ? nextDir(i) : (i + 1)) {
|
||||
if ((entryIsDir(i) == FALSE) && (isDir == TRUE)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
stringPtr = FstStringStart + stringOff(i);
|
||||
|
||||
if (isSame(ptr, stringPtr) == TRUE) {
|
||||
goto next_hier;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
next_hier:
|
||||
if (!isDir) {
|
||||
return (s32)i;
|
||||
}
|
||||
|
||||
dirLookAt = i;
|
||||
pathPtr += length + 1;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL DVDFastOpen(s32 entrynum, DVDFileInfo* fileInfo) {
|
||||
if ((entrynum < 0) || (entrynum >= MaxEntryNum) || entryIsDir(entrynum)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fileInfo->startAddr = filePosition(entrynum);
|
||||
fileInfo->length = fileLength(entrynum);
|
||||
fileInfo->callback = (DVDCallback)NULL;
|
||||
fileInfo->cb.state = DVD_STATE_END;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DVDOpen(char* fileName, DVDFileInfo* fileInfo) {
|
||||
s32 entry;
|
||||
char currentDir[128];
|
||||
|
||||
entry = DVDConvertPathToEntrynum(fileName);
|
||||
|
||||
if (0 > entry) {
|
||||
DVDGetCurrentDir(currentDir, 128);
|
||||
OSReport("Warning: DVDOpen(): file '%s' was not found under %s.\n", fileName, currentDir);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (entryIsDir(entry)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fileInfo->startAddr = filePosition(entry);
|
||||
fileInfo->length = fileLength(entry);
|
||||
fileInfo->callback = (DVDCallback)NULL;
|
||||
fileInfo->cb.state = DVD_STATE_END;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DVDClose(DVDFileInfo* fileInfo) {
|
||||
DVDCancel(&(fileInfo->cb));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static u32 myStrncpy(char* dest, char* src, u32 maxlen) {
|
||||
u32 i = maxlen;
|
||||
|
||||
while ((i > 0) && (*src != 0)) {
|
||||
*dest++ = *src++;
|
||||
i--;
|
||||
}
|
||||
|
||||
return (maxlen - i);
|
||||
}
|
||||
|
||||
static u32 entryToPath(u32 entry, char* path, u32 maxlen) {
|
||||
char* name;
|
||||
u32 loc;
|
||||
|
||||
if (entry == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
name = FstStringStart + stringOff(entry);
|
||||
|
||||
loc = entryToPath(parentDir(entry), path, maxlen);
|
||||
|
||||
if (loc == maxlen) {
|
||||
return loc;
|
||||
}
|
||||
|
||||
*(path + loc++) = '/';
|
||||
|
||||
loc += myStrncpy(path + loc, name, maxlen - loc);
|
||||
|
||||
return loc;
|
||||
}
|
||||
|
||||
static BOOL DVDConvertEntrynumToPath(s32 entrynum, char* path, u32 maxlen) {
|
||||
u32 loc;
|
||||
|
||||
loc = entryToPath((u32)entrynum, path, maxlen);
|
||||
|
||||
if (loc == maxlen) {
|
||||
path[maxlen - 1] = '\0';
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (entryIsDir(entrynum)) {
|
||||
if (loc == maxlen - 1) {
|
||||
path[loc] = '\0';
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
path[loc++] = '/';
|
||||
}
|
||||
|
||||
path[loc] = '\0';
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DVDGetCurrentDir(char* path, u32 maxlen) {
|
||||
return DVDConvertEntrynumToPath((s32)currentDirectory, path, maxlen);
|
||||
}
|
||||
|
||||
BOOL DVDChangeDir(char* dirName) {
|
||||
s32 entry;
|
||||
entry = DVDConvertPathToEntrynum(dirName);
|
||||
if ((entry < 0) || (entryIsDir(entry) == FALSE)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
currentDirectory = (u32)entry;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DVDReadAsyncPrio(DVDFileInfo* fileInfo, void* addr, s32 length, s32 offset,
|
||||
DVDCallback callback, s32 prio) {
|
||||
|
||||
if (!((0 <= offset) && (offset < fileInfo->length))) {
|
||||
OSPanic(__FILE__, 739, "DVDReadAsync(): specified area is out of the file ");
|
||||
}
|
||||
|
||||
if (!((0 <= offset + length) && (offset + length < fileInfo->length + DVD_MIN_TRANSFER_SIZE))) {
|
||||
OSPanic(__FILE__, 745, "DVDReadAsync(): specified area is out of the file ");
|
||||
}
|
||||
|
||||
fileInfo->callback = callback;
|
||||
DVDReadAbsAsyncPrio(&(fileInfo->cb), addr, length, (s32)(fileInfo->startAddr + offset),
|
||||
cbForReadAsync, prio);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#ifndef offsetof
|
||||
#define offsetof(type, memb) ((u32) & ((type*)0)->memb)
|
||||
#endif
|
||||
|
||||
static void cbForReadAsync(s32 result, DVDCommandBlock* block) {
|
||||
DVDFileInfo* fileInfo;
|
||||
|
||||
fileInfo = (DVDFileInfo*)((char*)block - offsetof(DVDFileInfo, cb));
|
||||
if (fileInfo->callback) {
|
||||
(fileInfo->callback)(result, fileInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/* This is based on the revolution SDK, these may not match in all cases I have also left the line numbers at 0 */
|
||||
BOOL DVDReadPrio(DVDFileInfo* fileInfo, void* addr, s32 length, s32 offset, s32 prio) {
|
||||
BOOL result;
|
||||
DVDCommandBlock* block;
|
||||
s32 state;
|
||||
BOOL enabled;
|
||||
s32 retVal;
|
||||
|
||||
if (!((0 <= offset) && (offset < fileInfo->length))) {
|
||||
OSPanic(__FILE__, 809, "DVDRead(): specified area is out of the file ");
|
||||
}
|
||||
|
||||
if (!((0 <= offset + length) && (offset + length < fileInfo->length + DVD_MIN_TRANSFER_SIZE))) {
|
||||
OSPanic(__FILE__, 815, "DVDRead(): specified area is out of the file ");
|
||||
}
|
||||
|
||||
block = &(fileInfo->cb);
|
||||
|
||||
result = DVDReadAbsAsyncPrio(block, addr, length, (s32)(fileInfo->startAddr + offset),
|
||||
cbForReadSync, prio);
|
||||
|
||||
if (result == FALSE) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
|
||||
while(1) {
|
||||
state = ((volatile DVDCommandBlock*)block)->state;
|
||||
|
||||
if (state == DVD_STATE_END) {
|
||||
retVal = (s32)block->transferredSize;
|
||||
break;
|
||||
}
|
||||
if (state == DVD_STATE_FATAL_ERROR) {
|
||||
retVal = DVD_RESULT_FATAL_ERROR;
|
||||
break;
|
||||
}
|
||||
if (state == DVD_STATE_CANCELED) {
|
||||
retVal = DVD_RESULT_CANCELED;
|
||||
break;
|
||||
}
|
||||
|
||||
OSSleepThread(&__DVDThreadQueue);
|
||||
}
|
||||
|
||||
OSRestoreInterrupts(enabled);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/* This is based on the revolution SDK, these may not match in all cases */
|
||||
static void cbForReadSync(s32 result, DVDCommandBlock* block) { OSWakeupThread(&__DVDThreadQueue); }
|
||||
436
src/dolphin/dvd/dvdlow.c
Normal file
436
src/dolphin/dvd/dvdlow.c
Normal file
|
|
@ -0,0 +1,436 @@
|
|||
#include "dolphin/DVDPriv.h"
|
||||
#include "dolphin/os.h"
|
||||
|
||||
extern DVDDiskID* DVDGetCurrentDiskID();
|
||||
|
||||
extern OSTime __OSGetSystemTime();
|
||||
|
||||
static BOOL FirstRead = TRUE;
|
||||
static volatile BOOL StopAtNextInt = FALSE;
|
||||
static u32 LastLength = 0;
|
||||
static DVDLowCallback Callback = NULL;
|
||||
static DVDLowCallback ResetCoverCallback = NULL;
|
||||
static volatile OSTime LastResetEnd = 0;
|
||||
static volatile u32 ResetOccurred = FALSE;
|
||||
static volatile BOOL WaitingCoverClose = FALSE;
|
||||
static BOOL Breaking = FALSE;
|
||||
static volatile u32 WorkAroundType = 0;
|
||||
static u32 WorkAroundSeekLocation = 0;
|
||||
static volatile OSTime LastReadFinished = 0;
|
||||
static OSTime LastReadIssued = 0;
|
||||
static volatile BOOL LastCommandWasRead = FALSE;
|
||||
static vu32 NextCommandNumber = 0;
|
||||
|
||||
typedef struct DVDBuffer {
|
||||
void* addr;
|
||||
u32 length;
|
||||
u32 offset;
|
||||
} DVDBuffer;
|
||||
|
||||
typedef struct DVDCommand {
|
||||
s32 cmd;
|
||||
void* addr;
|
||||
u32 length;
|
||||
u32 offset;
|
||||
DVDLowCallback callback;
|
||||
} DVDCommand;
|
||||
|
||||
static DVDCommand CommandList[3];
|
||||
static OSAlarm AlarmForWA;
|
||||
static OSAlarm AlarmForTimeout;
|
||||
static OSAlarm AlarmForBreak;
|
||||
static DVDBuffer Prev;
|
||||
static DVDBuffer Curr;
|
||||
|
||||
void __DVDInitWA() {
|
||||
NextCommandNumber = 0;
|
||||
CommandList[0].cmd = -1;
|
||||
__DVDLowSetWAType(0, 0);
|
||||
OSInitAlarm();
|
||||
}
|
||||
|
||||
static void Read(void* addr, u32 length, u32 offset, DVDLowCallback callback);
|
||||
|
||||
static BOOL ProcessNextCommand() {
|
||||
s32 n = NextCommandNumber;
|
||||
ASSERT(n < 3);
|
||||
|
||||
if (CommandList[n].cmd == 1) {
|
||||
++NextCommandNumber;
|
||||
Read(CommandList[n].addr, CommandList[n].length, CommandList[n].offset,
|
||||
CommandList[n].callback);
|
||||
return TRUE;
|
||||
} else if (CommandList[n].cmd == 2) {
|
||||
++NextCommandNumber;
|
||||
DVDLowSeek(CommandList[n].offset, CommandList[n].callback);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void __DVDInterruptHandler(__OSInterrupt interrupt, OSContext* context) {
|
||||
DVDLowCallback cb;
|
||||
OSContext exceptionContext;
|
||||
u32 cause = 0;
|
||||
u32 reg;
|
||||
u32 intr;
|
||||
u32 mask;
|
||||
|
||||
OSCancelAlarm(&AlarmForTimeout);
|
||||
|
||||
if (LastCommandWasRead) {
|
||||
LastReadFinished = __OSGetSystemTime();
|
||||
FirstRead = FALSE;
|
||||
Prev.addr = Curr.addr;
|
||||
Prev.length = Curr.length;
|
||||
Prev.offset = Curr.offset;
|
||||
if (StopAtNextInt == TRUE) {
|
||||
cause |= 8;
|
||||
}
|
||||
}
|
||||
|
||||
LastCommandWasRead = FALSE;
|
||||
StopAtNextInt = FALSE;
|
||||
reg = __DIRegs[0];
|
||||
mask = reg & 0x2a;
|
||||
intr = (reg & 0x54) & (mask << 1);
|
||||
|
||||
if (intr & 0x40) {
|
||||
cause |= 8;
|
||||
}
|
||||
|
||||
if (intr & 0x10) {
|
||||
cause |= 1;
|
||||
}
|
||||
|
||||
if (intr & 4) {
|
||||
cause |= 2;
|
||||
}
|
||||
|
||||
if (cause) {
|
||||
ResetOccurred = FALSE;
|
||||
|
||||
}
|
||||
|
||||
__DIRegs[0] = intr | mask;
|
||||
|
||||
if (ResetOccurred && (__OSGetSystemTime() - LastResetEnd) < OSMillisecondsToTicks(200)) {
|
||||
reg = __DIRegs[1];
|
||||
mask = reg & 0x2;
|
||||
intr = (reg & 4) & (mask << 1);
|
||||
if (intr & 4) {
|
||||
if (ResetCoverCallback) {
|
||||
ResetCoverCallback(4);
|
||||
}
|
||||
ResetCoverCallback = NULL;
|
||||
}
|
||||
|
||||
__DIRegs[1] = __DIRegs[1];
|
||||
} else if (WaitingCoverClose) {
|
||||
reg = __DIRegs[1];
|
||||
mask = reg & 2;
|
||||
intr = (reg & 4) & (mask << 1);
|
||||
|
||||
if (intr & 4) {
|
||||
cause |= 4;
|
||||
}
|
||||
|
||||
__DIRegs[1] = intr | mask;
|
||||
WaitingCoverClose = FALSE;
|
||||
} else {
|
||||
__DIRegs[1] = 0;
|
||||
}
|
||||
|
||||
if ((cause & 8) && !Breaking) {
|
||||
cause &= ~8;
|
||||
}
|
||||
|
||||
if ((cause & 1)) {
|
||||
if (ProcessNextCommand()) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
CommandList[0].cmd = -1;
|
||||
NextCommandNumber = 0;
|
||||
}
|
||||
|
||||
OSClearContext(&exceptionContext);
|
||||
OSSetCurrentContext(&exceptionContext);
|
||||
|
||||
if (cause) {
|
||||
cb = Callback;
|
||||
Callback = NULL;
|
||||
if (cb) {
|
||||
cb(cause);
|
||||
}
|
||||
|
||||
Breaking = FALSE;
|
||||
}
|
||||
|
||||
OSClearContext(&exceptionContext);
|
||||
OSSetCurrentContext(context);
|
||||
}
|
||||
|
||||
static void AlarmHandler(OSAlarm* alarm, OSContext* context) {
|
||||
BOOL error = ProcessNextCommand();
|
||||
ASSERTMSG(error != FALSE, "Failed assertion processed");
|
||||
}
|
||||
|
||||
static void AlarmHandlerForTimeout(OSAlarm* alarm, OSContext* context) {
|
||||
OSContext tmpContext;
|
||||
DVDLowCallback callback;
|
||||
__OSMaskInterrupts(0x400);
|
||||
OSClearContext(&tmpContext);
|
||||
OSSetCurrentContext(&tmpContext);
|
||||
callback = Callback;
|
||||
Callback = NULL;
|
||||
if (callback != NULL) {
|
||||
callback(0x10);
|
||||
}
|
||||
OSClearContext(&tmpContext);
|
||||
OSSetCurrentContext(context);
|
||||
}
|
||||
|
||||
static void SetTimeoutAlarm(OSTime timeout) {
|
||||
OSCreateAlarm(&AlarmForTimeout);
|
||||
OSSetAlarm(&AlarmForTimeout, timeout, AlarmHandlerForTimeout);
|
||||
}
|
||||
|
||||
static void Read(void* addr, u32 length, u32 offset, DVDLowCallback callback) {
|
||||
StopAtNextInt = FALSE;
|
||||
LastCommandWasRead = TRUE;
|
||||
Callback = callback;
|
||||
LastReadIssued = __OSGetSystemTime();
|
||||
|
||||
__DIRegs[2] = 0xa8000000;
|
||||
__DIRegs[3] = offset / 4;
|
||||
__DIRegs[4] = length;
|
||||
__DIRegs[5] = (u32)addr;
|
||||
__DIRegs[6] = length;
|
||||
LastLength = length;
|
||||
__DIRegs[7] = 3;
|
||||
|
||||
if (length > 0xa00000) {
|
||||
SetTimeoutAlarm(OSSecondsToTicks(20));
|
||||
} else {
|
||||
SetTimeoutAlarm(OSSecondsToTicks(10));
|
||||
}
|
||||
}
|
||||
|
||||
BOOL HitCache(DVDBuffer* cur, DVDBuffer* prev) {
|
||||
u32 uVar1 = (prev->offset + prev->length - 1) >> 15;
|
||||
u32 uVar2 = (cur->offset >> 15);
|
||||
u32 iVar3 = (DVDGetCurrentDiskID()->streaming ? TRUE : FALSE) ? 5 : 15;
|
||||
|
||||
if ((uVar2 > uVar1 - 2) || (uVar2 < uVar1 + iVar3 + 3)) {
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void DoJustRead(void* addr, u32 length, u32 offset, DVDLowCallback callback) {
|
||||
CommandList[0].cmd = -1;
|
||||
NextCommandNumber = 0;
|
||||
Read(addr, length, offset, callback);
|
||||
}
|
||||
|
||||
static void SeekTwiceBeforeRead(void* addr, u32 length, u32 offset, DVDLowCallback callback) {
|
||||
u32 newOffset = offset & ~0x7FFF;
|
||||
if (!newOffset) {
|
||||
newOffset = 0;
|
||||
} else {
|
||||
newOffset += WorkAroundSeekLocation;
|
||||
}
|
||||
CommandList[0].cmd = 2;
|
||||
CommandList[0].offset = newOffset;
|
||||
CommandList[0].callback = callback;
|
||||
CommandList[1].cmd = 1;
|
||||
CommandList[1].addr = addr;
|
||||
CommandList[1].length = length;
|
||||
CommandList[1].offset = offset;
|
||||
CommandList[1].callback = callback;
|
||||
CommandList[2].cmd = -1;
|
||||
NextCommandNumber = 0;
|
||||
DVDLowSeek(newOffset, callback);
|
||||
}
|
||||
|
||||
static void WaitBeforeRead(void* addr, u32 length, u32 offset, DVDLowCallback callback,
|
||||
OSTime timeout) {
|
||||
CommandList[0].cmd = 1;
|
||||
CommandList[0].addr = addr;
|
||||
CommandList[0].length = length;
|
||||
CommandList[0].offset = offset;
|
||||
CommandList[0].callback = callback;
|
||||
CommandList[1].cmd = -1;
|
||||
NextCommandNumber = 0;
|
||||
OSCreateAlarm(&AlarmForWA);
|
||||
OSSetAlarm(&AlarmForWA, timeout, AlarmHandler);
|
||||
}
|
||||
|
||||
|
||||
BOOL DVDLowRead(void* addr, u32 length, u32 offset, DVDLowCallback callback) {
|
||||
OSTime diff;
|
||||
u32 prev;
|
||||
|
||||
__DIRegs[6] = length;
|
||||
Curr.addr = addr;
|
||||
Curr.length = length;
|
||||
Curr.offset = offset;
|
||||
|
||||
if (WorkAroundType == 0) {
|
||||
DoJustRead(addr, length, offset, callback);
|
||||
} else if (WorkAroundType == 1) {
|
||||
if (FirstRead) {
|
||||
SeekTwiceBeforeRead(addr, length, offset, callback);
|
||||
} else {
|
||||
if (!HitCache(&Curr, &Prev)) {
|
||||
DoJustRead(addr, length, offset, callback);
|
||||
} else {
|
||||
prev = (Prev.offset + Prev.length - 1) >> 15;
|
||||
if (prev == Curr.offset >> 15 || prev + 1 == Curr.offset >> 15) {
|
||||
diff = __OSGetSystemTime() - LastReadFinished;
|
||||
if (OSMillisecondsToTicks(5) < diff) {
|
||||
DoJustRead(addr, length, offset, callback);
|
||||
} else {
|
||||
WaitBeforeRead(addr, length, offset, callback,
|
||||
OSMillisecondsToTicks(5) - diff + OSMicrosecondsToTicks(500));
|
||||
}
|
||||
} else {
|
||||
SeekTwiceBeforeRead(addr, length, offset, callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DVDLowSeek(u32 offset, DVDLowCallback callback) {
|
||||
ASSERTMSG(offset & 3, "DVDLowSeek(): offset must be a multiple of 4.");
|
||||
StopAtNextInt = FALSE;
|
||||
Callback = callback;
|
||||
__DIRegs[2] = 0xab000000;
|
||||
__DIRegs[3] = offset / 4;
|
||||
__DIRegs[7] = 1;
|
||||
SetTimeoutAlarm(OSSecondsToTicks(10));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DVDLowWaitCoverClose(DVDLowCallback callback) {
|
||||
Callback = callback;
|
||||
WaitingCoverClose = TRUE;
|
||||
StopAtNextInt = FALSE;
|
||||
__DIRegs[1] = 2;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DVDLowReadDiskID(DVDDiskID* diskID, DVDLowCallback callback) {
|
||||
StopAtNextInt = FALSE;
|
||||
Callback = callback;
|
||||
__DIRegs[2] = 0xa8000040;
|
||||
__DIRegs[3] = 0;
|
||||
__DIRegs[4] = sizeof(DVDDiskID);
|
||||
__DIRegs[5] = (u32)diskID;
|
||||
__DIRegs[6] = sizeof(DVDDiskID);
|
||||
__DIRegs[7] = 3;
|
||||
SetTimeoutAlarm(OSSecondsToTicks(10));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DVDLowStopMotor(DVDLowCallback callback) {
|
||||
StopAtNextInt = FALSE;
|
||||
Callback = callback;
|
||||
__DIRegs[2] = 0xe3000000;
|
||||
__DIRegs[7] = 1;
|
||||
SetTimeoutAlarm(OSSecondsToTicks(10));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DVDLowRequestError(DVDLowCallback callback) {
|
||||
StopAtNextInt = FALSE;
|
||||
Callback = callback;
|
||||
__DIRegs[2] = 0xe0000000;
|
||||
__DIRegs[7] = 1;
|
||||
SetTimeoutAlarm(OSSecondsToTicks(10));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DVDLowInquiry(DVDDriveInfo* info, DVDLowCallback callback) {
|
||||
StopAtNextInt = FALSE;
|
||||
Callback = callback;
|
||||
__DIRegs[2] = 0x12000000;
|
||||
__DIRegs[4] = sizeof(DVDDriveInfo);
|
||||
__DIRegs[5] = (u32)info;
|
||||
__DIRegs[6] = sizeof(DVDDriveInfo);
|
||||
__DIRegs[7] = 3;
|
||||
SetTimeoutAlarm(OSSecondsToTicks(10));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DVDLowAudioStream(u32 subcmd, u32 length, u32 offset, DVDLowCallback callback) {
|
||||
StopAtNextInt = FALSE;
|
||||
Callback = callback;
|
||||
__DIRegs[2] = subcmd | 0xe1000000;
|
||||
__DIRegs[3] = offset >> 2;
|
||||
__DIRegs[4] = length;
|
||||
__DIRegs[7] = 1;
|
||||
SetTimeoutAlarm(OSSecondsToTicks(10));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DVDLowRequestAudioStatus(u32 subcmd, DVDLowCallback callback) {
|
||||
StopAtNextInt = FALSE;
|
||||
Callback = callback;
|
||||
__DIRegs[2] = subcmd | 0xe2000000;
|
||||
__DIRegs[7] = 1;
|
||||
SetTimeoutAlarm(OSSecondsToTicks(10));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DVDLowAudioBufferConfig(BOOL enable, u32 size, DVDLowCallback callback) {
|
||||
StopAtNextInt = FALSE;
|
||||
Callback = callback;
|
||||
__DIRegs[2] = 0xe4000000 | (enable != 0 ? 0x10000 : 0) | size;
|
||||
__DIRegs[7] = 1;
|
||||
SetTimeoutAlarm(OSSecondsToTicks(10));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void DVDLowReset() {
|
||||
u32 reg;
|
||||
OSTime resetStart;
|
||||
|
||||
__DIRegs[1] = 2;
|
||||
reg = __PIRegs[9];
|
||||
__PIRegs[9] = (reg & ~4) | 1;
|
||||
|
||||
resetStart = __OSGetSystemTime();
|
||||
while ((__OSGetSystemTime() - resetStart) < OSMicrosecondsToTicks(12))
|
||||
;
|
||||
|
||||
__PIRegs[9] = reg | 5;
|
||||
ResetOccurred = TRUE;
|
||||
LastResetEnd = __OSGetSystemTime();
|
||||
}
|
||||
|
||||
BOOL DVDLowBreak() {
|
||||
StopAtNextInt = TRUE;
|
||||
Breaking = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DVDLowCallback DVDLowClearCallback() {
|
||||
DVDLowCallback old;
|
||||
__DIRegs[1] = 0;
|
||||
old = Callback;
|
||||
Callback = NULL;
|
||||
return old;
|
||||
}
|
||||
|
||||
void __DVDLowSetWAType(u32 type, u32 location) {
|
||||
BOOL enabled;
|
||||
enabled = OSDisableInterrupts();
|
||||
WorkAroundType = type;
|
||||
WorkAroundSeekLocation = location;
|
||||
OSRestoreInterrupts(enabled);
|
||||
}
|
||||
142
src/dolphin/dvd/dvdqueue.c
Normal file
142
src/dolphin/dvd/dvdqueue.c
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
#include "dolphin/DVDPriv.h"
|
||||
|
||||
#define MAX_QUEUES 4
|
||||
typedef struct {
|
||||
DVDCommandBlock* next;
|
||||
DVDCommandBlock* prev;
|
||||
} DVDQueue;
|
||||
|
||||
static DVDQueue WaitingQueue[MAX_QUEUES];
|
||||
|
||||
void __DVDClearWaitingQueue(void) {
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < MAX_QUEUES; i++) {
|
||||
DVDCommandBlock* q;
|
||||
|
||||
q = (DVDCommandBlock*)&(WaitingQueue[i]);
|
||||
q->next = q;
|
||||
q->prev = q;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL __DVDPushWaitingQueue(s32 prio, DVDCommandBlock* block) {
|
||||
BOOL enabled;
|
||||
DVDCommandBlock* q;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
|
||||
q = (DVDCommandBlock*)&(WaitingQueue[prio]);
|
||||
|
||||
q->prev->next = block;
|
||||
block->prev = q->prev;
|
||||
block->next = q;
|
||||
q->prev = block;
|
||||
|
||||
OSRestoreInterrupts(enabled);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static DVDCommandBlock* PopWaitingQueuePrio(s32 prio) {
|
||||
DVDCommandBlock* tmp;
|
||||
BOOL enabled;
|
||||
DVDCommandBlock* q;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
|
||||
q = (DVDCommandBlock*)&(WaitingQueue[prio]);
|
||||
|
||||
tmp = q->next;
|
||||
q->next = tmp->next;
|
||||
tmp->next->prev = q;
|
||||
|
||||
OSRestoreInterrupts(enabled);
|
||||
|
||||
tmp->next = (DVDCommandBlock*)NULL;
|
||||
tmp->prev = (DVDCommandBlock*)NULL;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
DVDCommandBlock* __DVDPopWaitingQueue(void) {
|
||||
u32 i;
|
||||
BOOL enabled;
|
||||
DVDCommandBlock* q;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
|
||||
for (i = 0; i < MAX_QUEUES; i++) {
|
||||
q = (DVDCommandBlock*)&(WaitingQueue[i]);
|
||||
if (q->next != q) {
|
||||
OSRestoreInterrupts(enabled);
|
||||
return PopWaitingQueuePrio((s32)i);
|
||||
}
|
||||
}
|
||||
|
||||
OSRestoreInterrupts(enabled);
|
||||
|
||||
return (DVDCommandBlock*)NULL;
|
||||
}
|
||||
|
||||
BOOL __DVDCheckWaitingQueue(void) {
|
||||
u32 i;
|
||||
BOOL enabled;
|
||||
DVDCommandBlock* q;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
|
||||
for (i = 0; i < MAX_QUEUES; i++) {
|
||||
q = (DVDCommandBlock*)&(WaitingQueue[i]);
|
||||
if (q->next != q) {
|
||||
OSRestoreInterrupts(enabled);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
OSRestoreInterrupts(enabled);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL __DVDDequeueWaitingQueue(DVDCommandBlock* block) {
|
||||
BOOL enabled;
|
||||
DVDCommandBlock* prev;
|
||||
DVDCommandBlock* next;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
|
||||
prev = block->prev;
|
||||
next = block->next;
|
||||
|
||||
if ((prev == (DVDCommandBlock*)NULL) || (next == (DVDCommandBlock*)NULL)) {
|
||||
OSRestoreInterrupts(enabled);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
prev->next = next;
|
||||
next->prev = prev;
|
||||
|
||||
OSRestoreInterrupts(enabled);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL __DVDIsBlockInWaitingQueue(DVDCommandBlock* block) {
|
||||
u32 i;
|
||||
DVDCommandBlock* start;
|
||||
DVDCommandBlock* q;
|
||||
|
||||
for (i = 0; i < MAX_QUEUES; i++) {
|
||||
start = (DVDCommandBlock*)&(WaitingQueue[i]);
|
||||
|
||||
if (start->next != start) {
|
||||
for (q = start->next; q != start; q = q->next) {
|
||||
if (q == block)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
68
src/dolphin/dvd/fstload.c
Normal file
68
src/dolphin/dvd/fstload.c
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
|
||||
#include <dolphin/DVDPriv.h>
|
||||
#include <dolphin/dvd.h>
|
||||
#include <dolphin/hw_regs.h>
|
||||
#include <dolphin/os.h>
|
||||
#include <dolphin/os/OSBootInfo.h>
|
||||
#include <string.h>
|
||||
|
||||
static s32 status = 0;
|
||||
|
||||
static u8 bb2Buf[OSRoundUp32B(sizeof(DVDBB2)) + 31];
|
||||
static DVDBB2* bb2 = 0;
|
||||
static DVDDiskID* idTmp = NULL;
|
||||
|
||||
static void cb(s32 result, DVDCommandBlock* block) {
|
||||
if (result > 0) {
|
||||
switch (status) {
|
||||
case 0:
|
||||
status = 1;
|
||||
DVDReadAbsAsyncForBS(block, bb2, OSRoundUp32B(sizeof(bb2)), 0x420, cb);
|
||||
break;
|
||||
case 1:
|
||||
status = 2;
|
||||
DVDReadAbsAsyncForBS(block, bb2->FSTAddress, OSRoundUp32B(bb2->FSTLength), bb2->FSTPosition,
|
||||
cb);
|
||||
}
|
||||
} else if (result == -1) {
|
||||
|
||||
} else if (result == -4) {
|
||||
status = 0;
|
||||
DVDReset();
|
||||
DVDReadDiskID(block, idTmp, cb);
|
||||
}
|
||||
}
|
||||
|
||||
void __fstLoad() {
|
||||
OSBootInfo* bootInfo;
|
||||
DVDDiskID* id;
|
||||
u8 idTmpBuf[sizeof(DVDDiskID) + 31];
|
||||
static DVDCommandBlock block;
|
||||
void* arenaHi;
|
||||
|
||||
arenaHi = OSGetArenaHi();
|
||||
bootInfo = (OSBootInfo*)OSPhysicalToCached(0);
|
||||
|
||||
idTmp = (DVDDiskID*)(OSRoundUp32B(idTmpBuf));
|
||||
bb2 = (DVDBB2*)(OSRoundUp32B(bb2Buf));
|
||||
|
||||
DVDReset();
|
||||
DVDReadDiskID(&block, idTmp, cb);
|
||||
while (DVDGetDriveStatus() != 0);
|
||||
|
||||
bootInfo->FSTLocation = bb2->FSTAddress;
|
||||
bootInfo->FSTMaxLength = bb2->FSTMaxLength;
|
||||
|
||||
id = &bootInfo->DVDDiskID;
|
||||
|
||||
memcpy(id, idTmp, sizeof(DVDDiskID));
|
||||
OSReport("\n");
|
||||
OSReport(" Game Name ... %c%c%c%c\n", id->gameName[0], id->gameName[1], id->gameName[2],
|
||||
id->gameName[3]);
|
||||
OSReport(" Company ..... %c%c\n", id->company[0], id->company[1]);
|
||||
OSReport(" Disk # ...... %d\n", id->diskNumber);
|
||||
OSReport(" Game ver .... %d\n", id->gameVersion);
|
||||
OSReport(" Streaming ... %s\n", (id->streaming == 0) ? "OFF" : "ON");
|
||||
OSReport("\n");
|
||||
OSSetArenaHi(bb2->FSTAddress);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue