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