diff --git a/configure.py b/configure.py index a5da38af6..48c0d4934 100644 --- a/configure.py +++ b/configure.py @@ -758,17 +758,17 @@ config.libs = [ Object(Matching, "JSystem/JKernel/JKRHeap.cpp"), Object(NonMatching, "JSystem/JKernel/JKRStdHeap.cpp"), Object(NonMatching, "JSystem/JKernel/JKRExpHeap.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRSolidHeap.cpp"), + Object(Matching, "JSystem/JKernel/JKRSolidHeap.cpp"), Object(Matching, "JSystem/JKernel/JKRDisposer.cpp"), Object(Matching, "JSystem/JKernel/JKRThread.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRAram.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRAramHeap.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRAramBlock.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRAramPiece.cpp"), + Object(Matching, "JSystem/JKernel/JKRAram.cpp"), + Object(Matching, "JSystem/JKernel/JKRAramHeap.cpp"), + Object(Matching, "JSystem/JKernel/JKRAramBlock.cpp"), + Object(Matching, "JSystem/JKernel/JKRAramPiece.cpp"), Object(NonMatching, "JSystem/JKernel/JKRAramStream.cpp"), Object(Matching, "JSystem/JKernel/JKRFileLoader.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRFileFinder.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRFileCache.cpp"), + Object(Matching, "JSystem/JKernel/JKRFileFinder.cpp"), + Object(Matching, "JSystem/JKernel/JKRFileCache.cpp"), Object(NonMatching, "JSystem/JKernel/JKRArchivePub.cpp"), Object(NonMatching, "JSystem/JKernel/JKRArchivePri.cpp"), Object(Matching, "JSystem/JKernel/JKRMemArchive.cpp"), @@ -777,7 +777,7 @@ config.libs = [ Object(Matching, "JSystem/JKernel/JKRCompArchive.cpp"), Object(Matching, "JSystem/JKernel/JKRFile.cpp"), Object(NonMatching, "JSystem/JKernel/JKRDvdFile.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRDvdRipper.cpp"), + Object(Matching, "JSystem/JKernel/JKRDvdRipper.cpp"), Object(NonMatching, "JSystem/JKernel/JKRDvdAramRipper.cpp"), Object(NonMatching, "JSystem/JKernel/JKRDecomp.cpp"), ], diff --git a/include/JSystem/JKernel/JKRAram.h b/include/JSystem/JKernel/JKRAram.h index 07f6bb231..e66c696a6 100644 --- a/include/JSystem/JKernel/JKRAram.h +++ b/include/JSystem/JKernel/JKRAram.h @@ -34,10 +34,12 @@ public: public: static JKRAram* create(u32, u32, long, long, long); - static void checkOkAddress(u8*, u32, JKRAramBlock*, u32); + static bool checkOkAddress(u8*, u32, JKRAramBlock*, u32); static void changeGroupIdIfNeed(u8*, int); static JKRAramBlock* mainRamToAram(u8*, u32, u32, JKRExpandSwitch, u32, JKRHeap*, int); + static JKRAramBlock* mainRamToAram(u8*, JKRAramBlock*, u32, JKRExpandSwitch, u32, JKRHeap*, int); static u8* aramToMainRam(u32, u8*, u32, JKRExpandSwitch, u32, JKRHeap*, int, u32*); + static u8* aramToMainRam(JKRAramBlock*, u8*, u32, u32, JKRExpandSwitch, u32, JKRHeap*, int, u32*); static void dump(void); static JKRAram* getManager() { return sAramObject; } diff --git a/include/JSystem/JKernel/JKRAramBlock.h b/include/JSystem/JKernel/JKRAramBlock.h index 15058145b..630547f07 100644 --- a/include/JSystem/JKernel/JKRAramBlock.h +++ b/include/JSystem/JKernel/JKRAramBlock.h @@ -29,7 +29,7 @@ public: /* 0x18 */ u32 mSize; /* 0x1C */ u32 mFreeSize; /* 0x20 */ u8 mGroupId; - /* 0x21 */ u8 mIsTempMemory; + /* 0x21 */ bool mIsTempMemory; /* 0x22 */ u8 padding[2]; }; diff --git a/include/JSystem/JKernel/JKRAramStream.h b/include/JSystem/JKernel/JKRAramStream.h index cc42bd609..cdbfbd5ca 100644 --- a/include/JSystem/JKernel/JKRAramStream.h +++ b/include/JSystem/JKernel/JKRAramStream.h @@ -22,22 +22,21 @@ public: /* 0x0C */ u32 field_0x0c; /* 0x10 */ JSUFileInputStream* mStream; /* 0x14 */ u32 mOffset; - /* 0x18 */ u32* mReturnSize; - /* 0x1C */ u8* mTransferBuffer; - /* 0x20 */ u32 mTransferBufferSize; - /* 0x24 */ JKRHeap* mHeap; - /* 0x28 */ bool mAllocatedTransferBuffer; - /* 0x29 */ u8 padding_0x29[3]; - /* 0x2C */ u32 field_0x2c; - /* 0x30 */ OSMessageQueue mMessageQueue; - /* 0x50 */ OSMessage mMessage; - /* 0x54 */ u32 field_0x54; - /* 0x58 */ u32 field_0x58; + /* 0x18 */ u8* mTransferBuffer; + /* 0x1C */ u32 mTransferBufferSize; + /* 0x20 */ JKRHeap* mHeap; + /* 0x24 */ bool mAllocatedTransferBuffer; + /* 0x25 */ u8 padding_0x29[3]; + /* 0x28 */ u32 field_0x2c; + /* 0x2C */ OSMessageQueue mMessageQueue; + /* 0x4C */ OSMessage mMessage; + /* 0x50 */ u32 field_0x54; + /* 0x54 */ u32 field_0x58; }; class JKRAramStream : public JKRThread { private: - JKRAramStream(long); + JKRAramStream(s32); virtual ~JKRAramStream(); /* vt[03] */ void* run(void); /* override */ @@ -47,7 +46,7 @@ public: static s32 readFromAram(void); static s32 writeToAram(JKRAramStreamCommand*); - static JKRAramStreamCommand* write_StreamToAram_Async(JSUFileInputStream*, u32, u32, u32, u32*); + static JKRAramStreamCommand* write_StreamToAram_Async(JSUFileInputStream*, u32, u32, u32); static JKRAramStreamCommand* sync(JKRAramStreamCommand*, BOOL); static void setTransBuffer(u8*, u32, JKRHeap*); @@ -65,4 +64,8 @@ inline JKRAramStream* JKRCreateAramStreamManager(long priority) { return JKRAramStream::create(priority); } +inline JKRAramStreamCommand* JKRStreamToAram_Async(JSUFileInputStream *stream, u32 addr, u32 size, u32 offset, void (*callback)(u32)) { + return JKRAramStream::write_StreamToAram_Async(stream, addr, size, offset); +} + #endif /* JKRARAMSTREAM_H */ diff --git a/include/JSystem/JKernel/JKRArchive.h b/include/JSystem/JKernel/JKRArchive.h index 8ef03c411..ca184c2e7 100644 --- a/include/JSystem/JKernel/JKRArchive.h +++ b/include/JSystem/JKernel/JKRArchive.h @@ -41,10 +41,6 @@ inline u16 read_big_endian_u16(void* ptr) { return ((u16)uptr[0] << 8) | ((u16)uptr[1]); } -inline u32 JKRDecompExpandSize(u8* pBuf) { - return (pBuf[4] << 0x18) | (pBuf[5] << 0x10) | (pBuf[6] << 8) | pBuf[7]; -} - extern u32 sCurrentDirID__10JKRArchive; // JKRArchive::sCurrentDirID class JKRArchive : public JKRFileLoader { diff --git a/include/JSystem/JKernel/JKRDecomp.h b/include/JSystem/JKernel/JKRDecomp.h index 539695d2a..e7ef48c68 100644 --- a/include/JSystem/JKernel/JKRDecomp.h +++ b/include/JSystem/JKernel/JKRDecomp.h @@ -62,11 +62,12 @@ inline JKRDecomp* JKRCreateDecompManager(long priority) { return JKRDecomp::create(priority); } -inline JKRCompression JKRCheckCompressed_noASR(u8 *pBuf) { - JKRCompression compression = JKRDecomp::checkCompressed(pBuf); - if (compression == COMPRESSION_ASR) // ternary i had before was either incorrect, or was not a ternary at all - compression = COMPRESSION_NONE; - return compression; +inline JKRCompression JKRCheckCompressed(u8 *pBuf) { + return JKRDecomp::checkCompressed(pBuf); +} + +inline u32 JKRDecompExpandSize(u8* pBuf) { + return (pBuf[4] << 0x18) | (pBuf[5] << 0x10) | (pBuf[6] << 8) | pBuf[7]; } #endif /* JKRDECOMP_H */ diff --git a/include/JSystem/JKernel/JKRDvdAramRipper.h b/include/JSystem/JKernel/JKRDvdAramRipper.h index 3561a7e99..6c3ba1de7 100644 --- a/include/JSystem/JKernel/JKRDvdAramRipper.h +++ b/include/JSystem/JKernel/JKRDvdAramRipper.h @@ -13,23 +13,22 @@ public: ~JKRADCommand(); /* 0x00 */ JSULink mLink; - /* 0x10 */ int field_0x10; - /* 0x14 */ int field_0x14; - /* 0x18 */ int field_0x18; - /* 0x1C */ int field_0x1c; - /* 0x20 */ int field_0x20; - /* 0x24 */ int field_0x24; - /* 0x28 */ JKRDvdFile* mDvdFile; - /* 0x2C */ u32 field_0x2c; - /* 0x30 */ JKRAramBlock* mBlock; + /* 0x10 */ JKRDvdFile* mDvdFile; + /* 0x14 */ u32 mOffset; + /* 0x18 */ u32 field_0x18; + /* 0x1C */ u32 mAddress; + /* 0x20 */ JKRAramBlock* mBlock; + /* 0x24 */ JKRExpandSwitch mExpandSwitch; + /* 0x28 */ int field_0x28; + /* 0x2C */ int field_0x2c; + /* 0x30 */ int field_0x30; /* 0x34 */ int field_0x34; - /* 0x38 */ void (*field_0x38)(u32); - /* 0x3C */ u32 field_0x3c; - /* 0x40 */ u32 field_0x40; - /* 0x44 */ u32* field_0x44; - /* 0x48 */ int field_0x48; - /* 0x4C */ u8 field_0x4c; - /* 0x50 */ JKRAramStreamCommand* mStreamCommand; + /* 0x38 */ int field_0x38; + /* 0x3C */ int field_0x3c; + /* 0x40 */ void (*mCallback)(u32); + /* 0x44 */ int field_0x44; + /* 0x48 */ bool field_0x48; + /* 0x4C */ JKRAramStreamCommand* mStreamCommand; }; class JKRDvdFile; @@ -42,11 +41,12 @@ public: static JKRADCommand* callCommand_Async(JKRADCommand*); static bool syncAram(JKRADCommand*, int); + static u32 getSzpBufferSize() { return sSzpBufferSize; } static void setSzpBufferSize(u32 size) { sSzpBufferSize = size; } - // TODO: fix type - static u8 sDvdAramAsyncList[12]; + static JSUList sDvdAramAsyncList; static u32 sSzpBufferSize; + static bool errorRetry; }; inline JKRAramBlock *JKRDvdToAram(s32 entrynum, u32 p2, JKRExpandSwitch expSwitch, u32 p4, u32 p5) { diff --git a/include/JSystem/JKernel/JKRDvdFile.h b/include/JSystem/JKernel/JKRDvdFile.h index 9fe03fda6..1ea018241 100644 --- a/include/JSystem/JKernel/JKRDvdFile.h +++ b/include/JSystem/JKernel/JKRDvdFile.h @@ -30,7 +30,7 @@ public: /* vt[04] */ virtual void close(void); /* override */ /* vt[05] */ virtual s32 readData(void*, s32, s32); /* override */ /* vt[06] */ virtual s32 writeData(const void*, s32, s32); /* override */ - /* vt[07] */ virtual s32 getFileSize(void) const; /* override */ + /* vt[07] */ virtual s32 getFileSize(void) const { return mFileInfo.length; } /* override */ /* vt[08] */ virtual bool open(s32); // private: diff --git a/include/JSystem/JKernel/JKRDvdRipper.h b/include/JSystem/JKernel/JKRDvdRipper.h index 139b8a7fd..7534f9ee9 100644 --- a/include/JSystem/JKernel/JKRDvdRipper.h +++ b/include/JSystem/JKernel/JKRDvdRipper.h @@ -26,6 +26,7 @@ class JKRDvdRipper { public: static JSUList sDvdAsyncList; static u32 sSzpBufferSize; + static bool errorRetry; enum EAllocDirection { UNKNOWN_EALLOC_DIRECTION = 0, @@ -42,7 +43,7 @@ public: static void* loadToMainRAM(JKRDvdFile*, u8*, JKRExpandSwitch, u32, JKRHeap*, EAllocDirection, u32, int*); - static u8 isErrorRetry(void); + static bool isErrorRetry(void) { return errorRetry; } inline static u32 getSzpBufferSize() { return sSzpBufferSize; } }; diff --git a/include/JSystem/JKernel/JKRFileCache.h b/include/JSystem/JKernel/JKRFileCache.h index b4b9830bc..892f1670b 100644 --- a/include/JSystem/JKernel/JKRFileCache.h +++ b/include/JSystem/JKernel/JKRFileCache.h @@ -41,10 +41,10 @@ public: /* vt[12] */ virtual u32 getResSize(const void*) const; /* override */ /* vt[13] */ virtual u32 countFile(const char*) const; /* override */ /* vt[14] */ virtual JKRFileFinder* getFirstFile(const char*) const; /* override */ - /* vt[15] */ virtual void* getFsResource(const char*); - /* vt[16] */ virtual void* getNameResource(u32, const char*); - /* vt[17] */ virtual u32 readFsResource(void*, u32, const char*); - /* vt[18] */ virtual u32 readNameResource(void*, u32, u32, const char*); + /* vt[15] */ virtual void* getFsResource(const char* path) { return getResource(path); } + /* vt[16] */ virtual void* getNameResource(u32 type, const char* path) { return getResource(type, path); } + /* vt[17] */ virtual u32 readFsResource(void* dst, u32 dstLength, const char* path) { return readResource(dst, dstLength, path); } + /* vt[18] */ virtual u32 readNameResource(void* dst, u32 dstLength, u32 type, const char* path) { return readResource(dst, dstLength, type, path); } private: /* 0x00 */ // vtable diff --git a/include/JSystem/JKernel/JKRFileFinder.h b/include/JSystem/JKernel/JKRFileFinder.h index d41709086..fece8bb2b 100644 --- a/include/JSystem/JKernel/JKRFileFinder.h +++ b/include/JSystem/JKernel/JKRFileFinder.h @@ -16,7 +16,7 @@ public: mIsAvailable = false; mIsFileOrDirectory = false; } - inline virtual ~JKRFileFinder(); + inline virtual ~JKRFileFinder() {}; bool isAvailable() const { return mIsAvailable; } bool isFile() const { return mIsFileOrDirectory; } @@ -37,7 +37,7 @@ class JKRArchive; class JKRArcFinder : public JKRFileFinder { public: JKRArcFinder(JKRArchive*, s32, s32); - inline virtual ~JKRArcFinder(); + inline virtual ~JKRArcFinder() {}; public: /* vt[3] */ virtual bool findNextFile(void); /* override */ diff --git a/include/JSystem/JKernel/JKRSolidHeap.h b/include/JSystem/JKernel/JKRSolidHeap.h index 83a6e918a..79beebb2a 100644 --- a/include/JSystem/JKernel/JKRSolidHeap.h +++ b/include/JSystem/JKernel/JKRSolidHeap.h @@ -23,8 +23,8 @@ protected: static s32 getUsedSize(JKRSolidHeap* heap) { return heap->mSize - heap->getTotalFreeSize(); } public: - /* vt[04] */ virtual u32 getHeapType(void); /* override */ - /* vt[05] */ virtual bool check(void); /* override */ + /* vt[04] */ virtual u32 getHeapType(void) { return 'SLID'; } /* override */ + /* vt[05] */ virtual bool check(void); /* override */ /* vt[07] */ virtual bool dump(void); /* override */ /* vt[08] */ virtual void do_destroy(void); /* override */ @@ -35,11 +35,11 @@ public: /* vt[13] */ virtual void do_freeFill(void); /* override */ /* vt[14] */ virtual s32 do_resize(void*, u32); /* override */ /* vt[15] */ virtual s32 do_getSize(void*); /* override */ - /* vt[16] */ virtual s32 do_getFreeSize(void); /* override */ - /* vt[17] */ virtual void* do_getMaxFreeBlock(void); /* override */ - /* vt[18] */ virtual s32 do_getTotalFreeSize(void); /* override */ + /* vt[16] */ virtual s32 do_getFreeSize(void) { return mFreeSize;} /* override */ + /* vt[17] */ virtual void* do_getMaxFreeBlock(void) { return mSolidHead; } /* override */ + /* vt[18] */ virtual s32 do_getTotalFreeSize(void) { return getFreeSize(); } /* override */ - /* vt[21] */ virtual u32 state_register(JKRHeap::TState*, u32) const; /* override */ + /* vt[21] */ virtual void state_register(JKRHeap::TState*, u32) const; /* override */ /* vt[22] */ virtual bool state_compare(JKRHeap::TState const&, JKRHeap::TState const&) const; /* override */ diff --git a/include/JSystem/JKernel/JKRStdHeap.h b/include/JSystem/JKernel/JKRStdHeap.h new file mode 100644 index 000000000..c52c875bb --- /dev/null +++ b/include/JSystem/JKernel/JKRStdHeap.h @@ -0,0 +1,34 @@ +#ifndef JKRSTDHEAP_H +#define JKRSTDHEAP_H + +#include "JSystem/JKernel/JKRHeap.h" +#include "dolphin/os/OSAlloc.h" + +class JKRStdHeap : public JKRHeap { + static JKRStdHeap* create(u32, JKRHeap*, bool); + void do_destroy(); + JKRStdHeap(void*, u32, JKRHeap*, bool); + ~JKRStdHeap(); + void* do_alloc(u32, int); + void do_free(void*); + void do_freeAll(); + void do_freeTail(); + s32 do_resize(void*, u32); + s32 do_getFreeSize(); + void* do_getMaxFreeBlock(); + void state_register(JKRHeap::TState*, u32) const; + bool state_compare(const JKRHeap::TState&, const JKRHeap::TState&) const; + void do_freeFill(); + u32 getHeapType() { return 'STDH'; } + bool check() { return OSCheckHeap(mHeapHandle) != -1; } + bool dump() { + OSDumpHeap(mHeapHandle); + return OSCheckHeap(mHeapHandle) != -1; + } + s32 do_getSize(void* ptr) { return OSReferentSize(ptr); }; + s32 do_getTotalFreeSize() { return getFreeSize(); }; + + OSHeapHandle mHeapHandle; +}; + +#endif /* JKRSTDHEAP_H */ \ No newline at end of file diff --git a/include/dolphin/ar/ar.h b/include/dolphin/ar/ar.h new file mode 100644 index 000000000..c04e41f1d --- /dev/null +++ b/include/dolphin/ar/ar.h @@ -0,0 +1,23 @@ +#ifndef AR_H +#define AR_H + +#include "dolphin/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*ARCallback)(void); + +ARCallback ARRegisterDMACallback(ARCallback callback); +u32 ARGetDMAStatus(void); +void ARStartDMA(u32 type, u32 mainmem_addr, u32 aram_addr, u32 length); +u32 ARInit(u32* stack_index_addr, u32 num_entries); +u32 ARAlloc(u32 length); +u32 ARGetSize(void); + +#ifdef __cplusplus +}; +#endif + +#endif /* AR_H */ diff --git a/include/dolphin/ar/arq.h b/include/dolphin/ar/arq.h new file mode 100644 index 000000000..083c118a4 --- /dev/null +++ b/include/dolphin/ar/arq.h @@ -0,0 +1,43 @@ +#ifndef ARQ_H +#define ARQ_H + +#include "dolphin/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ARQ_CHUNK_SIZE_DEFAULT 4096 + +typedef void (*ARQCallback)(u32 request_address); + +typedef enum _ARamType { + ARAM_DIR_MRAM_TO_ARAM, + ARAM_DIR_ARAM_TO_MRAM, +} ARamType; + +typedef enum _ArqPriotity { + ARQ_PRIORITY_LOW, + ARQ_PRIORITY_HIGH, +} ArqPriotity; + +typedef struct ARQRequest { + struct ARQRequest* next; + u32 owner; + u32 type; + u32 priority; + u32 source; + u32 destination; + u32 length; + ARQCallback callback; +} ARQRequest; + +void ARQInit(void); +void ARQPostRequest(ARQRequest* task, u32 owner, u32 type, u32 priority, u32 source, + u32 destination, u32 length, ARQCallback callback); + +#ifdef __cplusplus +}; +#endif + +#endif /* ARQ_H */ diff --git a/include/dolphin/os/OSAlloc.h b/include/dolphin/os/OSAlloc.h index ffb5e0c9c..31a69d317 100644 --- a/include/dolphin/os/OSAlloc.h +++ b/include/dolphin/os/OSAlloc.h @@ -22,7 +22,7 @@ typedef struct OSHeapCell { /* 0x14 */ char field_0x14[0x20 - 0x14]; } OSHeapCell; -typedef u32 OSHeapHandle; +typedef s32 OSHeapHandle; extern volatile s32 __OSCurrHeap; @@ -36,10 +36,15 @@ extern volatile s32 __OSCurrHeap; #define OSRoundDownPtr(x, align) ((void*)(((u32)(x)) & (~((align)-1)))) static OSHeapCell* DLInsert(OSHeapCell* list, OSHeapCell* child); +void* OSAllocFromHeap(OSHeapHandle handle, u32 size); void OSFreeToHeap(OSHeapHandle handle, void* ptr); s32 OSSetCurrentHeap(OSHeapHandle handle); void* OSInitAlloc(void* lo, void* hi, s32 maxHeaps); OSHeapHandle OSCreateHeap(void* start, void* end); +void OSDestroyHeap(OSHeapHandle handle); +s32 OSCheckHeap(OSHeapHandle handle); +s32 OSReferentSize(void* ptr); +void OSDumpHeap(OSHeapHandle handle); #ifdef __cplusplus }; diff --git a/src/JSystem/JKernel/JKRAram.cpp b/src/JSystem/JKernel/JKRAram.cpp index aac4abb77..e20e34068 100644 --- a/src/JSystem/JKernel/JKRAram.cpp +++ b/src/JSystem/JKernel/JKRAram.cpp @@ -4,79 +4,553 @@ // #include "JSystem/JKernel/JKRAram.h" -#include "dolphin/types.h" +#include "JSystem/JKernel/JKRAramPiece.h" +#include "JSystem/JKernel/JKRAramStream.h" +#include "JSystem/JKernel/JKRDecomp.h" +#include "JSystem/JKernel/JKRExpHeap.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "JSystem/JUtility/JUTException.h" +#include "MSL_C/string.h" +#include "dolphin/ar/ar.h" +#include "dolphin/ar/arq.h" +#include "dolphin/os/OS.h" +#include "global.h" + +static int JKRDecompressFromAramToMainRam(u32, void*, u32, u32, u32); +static int decompSZS_subroutine(u8*, u8*); +static u8* firstSrcData(); +static u8* nextSrcData(u8*); + +JKRAram* JKRAram::sAramObject; /* 802B42C4-802B4360 .text create__7JKRAramFUlUllll */ -void JKRAram::create(unsigned long, unsigned long, long, long, long) { - /* Nonmatching */ +JKRAram* JKRAram::create(u32 aram_audio_buffer_size, u32 aram_audio_graph_size, long stream_priority, long decomp_priority, long piece_priority) { + if (!sAramObject) { + sAramObject = new (JKRHeap::getSystemHeap(), 0) + JKRAram(aram_audio_buffer_size, aram_audio_graph_size, piece_priority); + } + + JKRCreateAramStreamManager(stream_priority); + JKRCreateDecompManager(decomp_priority); + sAramObject->resume(); + return sAramObject; } +OSMessage JKRAram::sMessageBuffer[4] = { NULL, NULL, NULL, NULL }; +OSMessageQueue JKRAram::sMessageQueue = {0}; + /* 802B4360-802B44D8 .text __ct__7JKRAramFUlUll */ -JKRAram::JKRAram(unsigned long, unsigned long, long) { - /* Nonmatching */ +JKRAram::JKRAram(u32 audio_buffer_size, u32 audio_graph_size, long priority) : JKRThread(0x4000, 0x10, priority) { + u32 aramBase = ARInit(mStackArray, ARRAY_SIZE(mStackArray)); + ARQInit(); + + u32 aramSize = ARGetSize(); + OSReport("ARAM size = %08x\n", aramSize); + + mAudioMemorySize = audio_buffer_size; + if (audio_graph_size == 0xFFFFFFFF) { + mGraphMemorySize = (aramSize - audio_buffer_size) - aramBase; + mAramMemorySize = 0; + } else { + mGraphMemorySize = audio_graph_size; + mAramMemorySize = (aramSize - (audio_buffer_size + audio_graph_size)) - aramBase; + } + + mAudioMemoryPtr = ARAlloc(mAudioMemorySize); + mGraphMemoryPtr = ARAlloc(mGraphMemorySize); + + if (mAramMemorySize) { + mAramMemoryPtr = ARAlloc(mAramMemorySize); + } else { + mAramMemoryPtr = NULL; + } + OSReport("ARAM audio area %08x: %08x\n", mAudioMemoryPtr, mAudioMemorySize); + OSReport("ARAM graph area %08x: %08x\n", mGraphMemoryPtr, mGraphMemorySize); + OSReport("ARAM user area %08x: %08x\n", mAramMemoryPtr, mAramMemorySize); + + mAramHeap = new (JKRHeap::getSystemHeap(), 0) JKRAramHeap(mGraphMemoryPtr, mGraphMemorySize); } /* 802B44D8-802B4568 .text __dt__7JKRAramFv */ JKRAram::~JKRAram() { - /* Nonmatching */ + sAramObject = NULL; + if (mAramHeap) { + delete mAramHeap; + } } /* 802B4568-802B45D4 .text run__7JKRAramFv */ -void JKRAram::run() { - /* Nonmatching */ +void* JKRAram::run() { + int result; + JKRAMCommand* command; + JKRAramPiece::Message* message; + OSInitMessageQueue(&sMessageQueue, sMessageBuffer, 4); + do { + OSReceiveMessage(&sMessageQueue, (OSMessage*)&message, OS_MESSAGE_BLOCK); + result = message->field_0x00; + command = message->command; + delete message; + + switch (result) { + case 1: + JKRAramPiece::startDMA(command); + break; + } + } while (true); } /* 802B45D4-802B4664 .text checkOkAddress__7JKRAramFPUcUlP12JKRAramBlockUl */ -void JKRAram::checkOkAddress(unsigned char*, unsigned long, JKRAramBlock*, unsigned long) { - /* Nonmatching */ +bool JKRAram::checkOkAddress(u8* addr, u32 size, JKRAramBlock* block, u32 param_4) { + if (!IS_ALIGNED((u32)addr, 0x20) && !IS_ALIGNED(size, 0x20)) { + OSPanic(__FILE__, 226, ":::address not 32Byte aligned."); + return false; + } + + if (block && !IS_ALIGNED((u32)block->getAddress() + param_4, 0x20)) { + OSPanic(__FILE__, 235, ":::address not 32Byte aligned."); + return false; + } + return true; } /* 802B4664-802B46C0 .text changeGroupIdIfNeed__7JKRAramFPUci */ -void JKRAram::changeGroupIdIfNeed(unsigned char*, int) { - /* Nonmatching */ +void JKRAram::changeGroupIdIfNeed(u8* data, int groupId) { + if (groupId < 0) { + return; + } + JKRHeap* currentHeap = JKRHeap::getCurrentHeap(); + if (currentHeap->getHeapType() == 'EXPH') { + JKRExpHeap::CMemBlock* block = JKRExpHeap::CMemBlock::getBlock(data); + block->newGroupId(groupId); + } } /* 802B46C0-802B490C .text mainRamToAram__7JKRAramFPUcUlUl15JKRExpandSwitchUlP7JKRHeapi */ -void JKRAram::mainRamToAram(unsigned char*, unsigned long, unsigned long, JKRExpandSwitch, unsigned long, JKRHeap*, int) { - /* Nonmatching */ +JKRAramBlock* JKRAram::mainRamToAram(u8 *buf, u32 bufSize, u32 alignedSize, JKRExpandSwitch expandSwitch, u32 fileSize, JKRHeap* heap, int id) { + JKRAramBlock *block = NULL; + checkOkAddress(buf, bufSize, NULL, 0); + if (expandSwitch == EXPAND_SWITCH_UNKNOWN1) { + expandSwitch = (JKRCheckCompressed(buf) == COMPRESSION_NONE) ? EXPAND_SWITCH_UNKNOWN0 : EXPAND_SWITCH_UNKNOWN1; + } + if (expandSwitch == EXPAND_SWITCH_UNKNOWN1) { + u32 expandSize = JKRCheckCompressed(buf) != COMPRESSION_NONE ? JKRDecompExpandSize(buf) : 0; + if (fileSize == 0 || fileSize > expandSize) { + fileSize = expandSize; + } + if (bufSize == 0) { + JKRAramBlock* allocatedBlock = (JKRAramBlock*)JKRAllocFromAram(fileSize, JKRAramHeap::HEAD); + block = (JKRAramBlock*)allocatedBlock; + if (allocatedBlock == NULL) + return NULL; + + allocatedBlock->newGroupID(decideAramGroupId(id)); + bufSize = allocatedBlock->getAddress(); + } + if (alignedSize == 0 || alignedSize > expandSize) + alignedSize = expandSize; + + if (fileSize > alignedSize) + fileSize = alignedSize; + + void *allocatedMem = JKRAllocFromHeap(heap, fileSize, -32); + if (allocatedMem == NULL) { + if (block != NULL) { + JKRFreeToAram(block); + } + block = NULL; + } + else { + JKRDecompress(buf, (u8 *)allocatedMem, fileSize, 0); + JKRAramPcs(0, (u32)allocatedMem, bufSize, alignedSize, block); + JKRFreeToHeap(heap, allocatedMem); + block = block == NULL ? (JKRAramBlock *)-1 : block; + } + } + else { + if (bufSize == 0) { + + JKRAramBlock* allocatedBlock = (JKRAramBlock*)JKRAllocFromAram(alignedSize, JKRAramHeap::HEAD); + block = allocatedBlock; + block->newGroupID(decideAramGroupId(id)); + if (block == NULL) + return NULL; + + bufSize = allocatedBlock->getAddress(); + } + + JKRAramPcs(0, (u32)buf, bufSize, alignedSize, block); + block = block == NULL ? (JKRAramBlock *)-1 : block; + } + return block; } /* 802B490C-802B49DC .text mainRamToAram__7JKRAramFPUcP12JKRAramBlockUl15JKRExpandSwitchUlP7JKRHeapi */ -void JKRAram::mainRamToAram(unsigned char*, JKRAramBlock*, unsigned long, JKRExpandSwitch, unsigned long, JKRHeap*, int) { +JKRAramBlock* JKRAram::mainRamToAram(u8 *buf, JKRAramBlock* block, u32 alignedSize, JKRExpandSwitch expandSwitch, u32 fileSize, JKRHeap* heap, int id) { /* Nonmatching */ + checkOkAddress(buf, 0, block, 0); + if (!block) { + return mainRamToAram(buf, u32(0), alignedSize, expandSwitch, fileSize, heap, id); + } + u32 blockSize = block->mSize; + if (expandSwitch == 1) { + fileSize = fileSize >= blockSize ? blockSize : fileSize; + } + return mainRamToAram(buf, block->mAddress, alignedSize > blockSize ? blockSize : alignedSize, expandSwitch, fileSize, heap, id); } /* 802B49DC-802B4C54 .text aramToMainRam__7JKRAramFUlPUcUl15JKRExpandSwitchUlP7JKRHeapiPUl */ -void JKRAram::aramToMainRam(unsigned long, unsigned char*, unsigned long, JKRExpandSwitch, unsigned long, JKRHeap*, int, unsigned long*) { - /* Nonmatching */ +u8* JKRAram::aramToMainRam(u32 address, u8 *buf, u32 p3, JKRExpandSwitch expandSwitch, u32 p5, JKRHeap* heap, int id, u32 *pSize) { + JKRCompression compression = COMPRESSION_NONE; + if (pSize != NULL) + *pSize = 0; + + checkOkAddress(buf, address, NULL, 0); + + u32 expandSize; + if (expandSwitch == EXPAND_SWITCH_UNKNOWN1) { + u8 buffer[64]; + u8 *bufPtr = (u8 *)ALIGN_NEXT((u32)buffer, 32); + JKRAramPcs(1, address, (u32)bufPtr, sizeof(buffer) / 2, NULL); // probably change sizeof(buffer) / 2 to 32 + compression = JKRCheckCompressed(bufPtr); + expandSize = JKRDecompExpandSize(bufPtr); + } + + if (compression == COMPRESSION_YAZ0) { // SZS + if (p5 != 0 && p5 < expandSize) + expandSize = p5; + + if (buf == NULL) + buf = (u8 *)JKRAllocFromHeap(heap, expandSize, 32); + if (buf == NULL) + return NULL; + else { + changeGroupIdIfNeed(buf, id); + JKRDecompressFromAramToMainRam(address, buf, p3, expandSize, 0); + if (pSize != NULL) { + *pSize = expandSize; + } + return buf; + } + } + else if (compression == COMPRESSION_YAY0) { // SZP + u8 *szpSpace = (u8 *)JKRAllocFromHeap(heap, p3, -32); + if (szpSpace == NULL) { + return NULL; + } + else { + JKRAramPcs(1, address, (u32)szpSpace, p3, NULL); + if (p5 != 0 && p5 < expandSize) + expandSize = p5; + + u8* rv; + if (buf == NULL) { + rv = (u8 *)JKRAllocFromHeap(heap, expandSize, 32); + } else { + rv = buf; + } + + if (rv == NULL) { + i_JKRFree(szpSpace); + return NULL; + } + else { + changeGroupIdIfNeed(rv, id); + JKRDecompress(szpSpace, rv, expandSize, 0); + JKRFreeToHeap(heap, szpSpace); + if (pSize != NULL) { + *pSize = expandSize; + } + return rv; + } + } + } + else { // Not compressed or ASR + if (buf == NULL) + buf = (u8 *)JKRAllocFromHeap(heap, p3, 32); + if (buf == NULL) { + return NULL; + } + else { + changeGroupIdIfNeed(buf, id); + JKRAramPcs(1, address, (u32)buf, p3, NULL); + if (pSize != NULL) { + *pSize = p3; + } + return buf; + } + } } /* 802B4C54-802B4D4C .text aramToMainRam__7JKRAramFP12JKRAramBlockPUcUlUl15JKRExpandSwitchUlP7JKRHeapiPUl */ -void JKRAram::aramToMainRam(JKRAramBlock*, unsigned char*, unsigned long, unsigned long, JKRExpandSwitch, unsigned long, JKRHeap*, int, unsigned long*) { +u8* JKRAram::aramToMainRam(JKRAramBlock* block, u8 *buf, u32 p3, u32 p4, JKRExpandSwitch expandSwitch, u32 p6, JKRHeap* heap, int id, u32 *pSize) { /* Nonmatching */ + if (pSize) { + *pSize = 0; + } + checkOkAddress(buf, 0, block, p4); + if (!block) { +#if VERSION == VERSION_JPN + OSPanic(__FILE__, 690, ":::Bad Aram Block specified.\n"); +#else + OSPanic(__FILE__, 683, ":::Bad Aram Block specified.\n"); +#endif + } + if (p4 >= block->mSize) { + return NULL; + } + p3 = p3 == 0 ? block->mSize : p3; + if (p4 + p3 > block->mSize) { + p3 = block->mSize - p4; + } + return aramToMainRam(p4 + block->mAddress, buf, p3, expandSwitch, p6, heap, id, pSize); } +static void dummy() { + OSReport("---------------- BAD SYNC. you'd set callback, but now call sync.\n"); +} +JSUList JKRAram::sAramCommandList; +static OSMutex decompMutex; +u32 JKRAram::sSzpBufferSize = 0x00000400; +static u8* szpBuf; +static u8* szpEnd; +static u8* refBuf; +static u8* refEnd; +static u8* refCurrent; +static u32 srcOffset; +static u32 transLeft; +static u8* srcLimit; +static u32 srcAddress; +static u32 fileOffset; +static u32 readCount; +static u32 maxDest; +static bool sIsInitMutex; + /* 802B4D4C-802B4F20 .text JKRDecompressFromAramToMainRam__FUlPvUlUlUl */ -void JKRDecompressFromAramToMainRam(unsigned long, void*, unsigned long, unsigned long, unsigned long) { - /* Nonmatching */ +static int JKRDecompressFromAramToMainRam(u32 src, void* dst, u32 srcLength, u32 dstLength, u32 offset) { + BOOL interrupts = OSDisableInterrupts(); + if (sIsInitMutex == false) { + OSInitMutex(&decompMutex); + sIsInitMutex = true; + } + OSRestoreInterrupts(interrupts); + OSLockMutex(&decompMutex); + + u32 szsBufferSize = JKRAram::getSzpBufferSize(); + szpBuf = (u8 *)JKRAllocFromSysHeap(szsBufferSize, 32); +#if VERSION == VERSION_JPN + JUT_ASSERT(1091, szpBuf != 0); +#else + JUT_ASSERT(1077, szpBuf != 0); +#endif + + szpEnd = szpBuf + szsBufferSize; + if (offset != 0) { + refBuf = (u8 *)JKRAllocFromSysHeap(0x1120, 0); +#if VERSION == VERSION_JPN + JUT_ASSERT(1100, refBuf != 0); +#else + JUT_ASSERT(1086, refBuf != 0); +#endif + refEnd = refBuf + 0x1120; + refCurrent = refBuf; + } + else { + refBuf = NULL; + } + srcAddress = src; + srcOffset = 0; + transLeft = (srcLength != 0) ? srcLength : -1; + fileOffset = offset; + readCount = 0; + maxDest = dstLength; + + u8* data = firstSrcData(); + u32 decompressedSize = ((u32*)data)[1]; + decompSZS_subroutine(data, (u8 *)dst); + i_JKRFree(szpBuf); + if (refBuf) { + i_JKRFree(refBuf); + } + + DCStoreRangeNoSync(dst, decompressedSize); + OSUnlockMutex(&decompMutex); + + return 0; } /* 802B4F20-802B51A4 .text decompSZS_subroutine__FPUcPUc */ -void decompSZS_subroutine(unsigned char*, unsigned char*) { - /* Nonmatching */ +static int decompSZS_subroutine(u8 *src, u8 *dest) { + u8 *endPtr; + s32 validBitCount = 0; + s32 currCodeByte = 0; + u32 ts = 0; + + if (src[0] != 'Y' || src[1] != 'a' || src[2] != 'z' || src[3] != '0') { + return -1; + } + + SYaz0Header *header = (SYaz0Header *)src; + endPtr = dest + (header->length - fileOffset); + if (endPtr > dest + maxDest) { + endPtr = dest + maxDest; + } + + src += 0x10; + do { + if (validBitCount == 0) { + if ((src > srcLimit) && transLeft) { + src = nextSrcData(src); + } + currCodeByte = *src; + validBitCount = 8; + src++; + } + if (currCodeByte & 0x80) { + if (fileOffset != 0) { + if (readCount >= fileOffset) { + *dest = *src; + dest++; + ts++; + if (dest == endPtr) + { + break; + } + } + *(refCurrent++) = *src; + if (refCurrent == refEnd) { + refCurrent = refBuf; + } + src++; + } + else { + *dest = *src; + dest++; + src++; + ts++; + if (dest == endPtr) { + break; + } + } + readCount++; + } + else { + u32 dist = ((src[0] & 0x0f) << 8) | src[1]; + s32 numBytes = src[0] >> 4; + src += 2; + u8 *copySource; + if (fileOffset != 0) { + copySource = refCurrent - dist - 1; + if (copySource < refBuf) { + copySource += refEnd - refBuf; + } + } + else { + copySource = dest - dist - 1; + } + if (numBytes == 0) { + numBytes = *src + 0x12; + src += 1; + } + else { + numBytes += 2; + } + if (fileOffset != 0) { + do { + if (readCount >= fileOffset) { + *dest = *copySource; + dest++; + ts++; + if (dest == endPtr) { + break; + } + } + *(refCurrent++) = *copySource; + if (refCurrent == refEnd) { + refCurrent = refBuf; + } + copySource++; + if (copySource == refEnd) { + copySource = refBuf; + } + readCount++; + numBytes--; + } while (numBytes != 0); + } + else { + do { + *dest = *copySource; + dest++; + ts++; + if (dest == endPtr) { + break; + } + readCount++; + numBytes--; + copySource++; + } while (numBytes != 0); + } + } + currCodeByte <<= 1; + validBitCount--; + } while (dest < endPtr); + return 0; } /* 802B51A4-802B5248 .text firstSrcData__Fv */ -void firstSrcData() { - /* Nonmatching */ +static u8* firstSrcData() { + srcLimit = szpEnd - 0x19; + u8* buffer = szpBuf; + + u32 length; + u32 size = szpEnd - szpBuf; + if (transLeft < size) { + length = transLeft; + } else { + length = size; + } + + u32 src = (u32)(srcAddress + srcOffset); + u32 dst = (u32)buffer; + u32 alignedLength = ALIGN_NEXT(length, 0x20); + JKRAramPcs(1, src, dst, alignedLength, NULL); + + srcOffset += length; + transLeft -= length; + if (!transLeft) { + srcLimit = buffer + length; + } + + return buffer; } /* 802B5248-802B5350 .text nextSrcData__FPUc */ -void nextSrcData(unsigned char*) { - /* Nonmatching */ -} +static u8* nextSrcData(u8* current) { + u8 *dest; + u32 left = (u32)(szpEnd - current); + if (IS_NOT_ALIGNED(left, 0x20)) { + dest = szpBuf + 0x20 - (left & (0x20 - 1)); + } else { + dest = szpBuf; + } -/* 802B5394-802B53E8 .text __dt__23JSUList<12JKRAMCommand>Fv */ -JSUList::~JSUList() { - /* Nonmatching */ + memcpy(dest, current, left); + u32 transSize = (u32)(szpEnd - (dest + left)); + if (transSize > transLeft) { + transSize = transLeft; + } +#if VERSION == VERSION_JPN + JUT_ASSERT(1376, transSize > 0) +#else + JUT_ASSERT(1361, transSize > 0) +#endif + + JKRAramPcs(1, (u32)(srcAddress + srcOffset), ((u32)dest + left), ALIGN_NEXT(transSize, 0x20), + NULL); + srcOffset += transSize; + transLeft -= transSize; + + if (transLeft == 0) + srcLimit = (dest + left) + transSize; + + return dest; } diff --git a/src/JSystem/JKernel/JKRAramArchive.cpp b/src/JSystem/JKernel/JKRAramArchive.cpp index 314591d4e..08230cabb 100644 --- a/src/JSystem/JKernel/JKRAramArchive.cpp +++ b/src/JSystem/JKernel/JKRAramArchive.cpp @@ -7,6 +7,7 @@ #include "JSystem/JKernel/JKRAram.h" #include "JSystem/JKernel/JKRAramBlock.h" #include "JSystem/JKernel/JKRAramHeap.h" +#include "JSystem/JKernel/JKRDecomp.h" #include "JSystem/JKernel/JKRDvdFile.h" #include "JSystem/JKernel/JKRDvdRipper.h" #include "JSystem/JKernel/JKRDvdAramRipper.h" diff --git a/src/JSystem/JKernel/JKRAramBlock.cpp b/src/JSystem/JKernel/JKRAramBlock.cpp index 931d4d6e7..a5866ac90 100644 --- a/src/JSystem/JKernel/JKRAramBlock.cpp +++ b/src/JSystem/JKernel/JKRAramBlock.cpp @@ -4,24 +4,64 @@ // #include "JSystem/JKernel/JKRAramBlock.h" +#include "JSystem/JKernel/JKRAramHeap.h" +#include "JSystem/JKernel/JKRHeap.h" #include "dolphin/types.h" /* 802B59A4-802B5A18 .text __ct__12JKRAramBlockFUlUlUlUcb */ -JKRAramBlock::JKRAramBlock(unsigned long, unsigned long, unsigned long, unsigned char, bool) { - /* Nonmatching */ +JKRAramBlock::JKRAramBlock(u32 address, u32 size, u32 freeSize, u8 groupId, bool isTempMemory) : mBlockLink(this) { + mAddress = address; + mSize = size; + mFreeSize = freeSize; + mGroupId = groupId; + mIsTempMemory = isTempMemory; } /* 802B5A18-802B5AD4 .text __dt__12JKRAramBlockFv */ JKRAramBlock::~JKRAramBlock() { - /* Nonmatching */ + JSUList* list = mBlockLink.getSupervisor(); + JSULink* prev = mBlockLink.getPrev(); + + if (prev) { + JKRAramBlock* block = prev->getObject(); + block->mFreeSize = mSize + mFreeSize + block->mFreeSize; + list->remove(&mBlockLink); + } else { + mFreeSize = mFreeSize + mSize; + mSize = 0; + } } /* 802B5AD4-802B5B70 .text allocHead__12JKRAramBlockFUlUcP11JKRAramHeap */ -void JKRAramBlock::allocHead(unsigned long, unsigned char, JKRAramHeap*) { - /* Nonmatching */ +JKRAramBlock* JKRAramBlock::allocHead(u32 size, u8 groupId, JKRAramHeap* aramHeap) { + u32 address = mAddress; + u32 usedSize = mSize; + u32 nextAddress = address + usedSize; + u32 freeSize = mFreeSize; + u32 nextFreeSize = freeSize - size; + + JKRAramBlock* block = new (aramHeap->getMgrHeap(), 0) JKRAramBlock(nextAddress, size, nextFreeSize, groupId, false); + + mFreeSize = 0; + JSULink* next = mBlockLink.getNext(); + JSUList* list = mBlockLink.getSupervisor(); + list->insert(next, &block->mBlockLink); + return block; } /* 802B5B70-802B5C14 .text allocTail__12JKRAramBlockFUlUcP11JKRAramHeap */ -void JKRAramBlock::allocTail(unsigned long, unsigned char, JKRAramHeap*) { - /* Nonmatching */ +JKRAramBlock* JKRAramBlock::allocTail(u32 size, u8 groupId, JKRAramHeap* aramHeap) { + u32 freeSize = mFreeSize; + u32 address = mAddress; + u32 usedSize = mSize; + u32 endAddress = address + usedSize + freeSize; + u32 tailAddress = endAddress - size; + + JKRAramBlock* block = new (aramHeap->getMgrHeap(), 0) JKRAramBlock(tailAddress, size, 0, groupId, true); + + mFreeSize -= size; + JSULink* next = mBlockLink.getNext(); + JSUList* list = mBlockLink.getSupervisor(); + list->insert(next, &block->mBlockLink); + return block; } diff --git a/src/JSystem/JKernel/JKRAramHeap.cpp b/src/JSystem/JKernel/JKRAramHeap.cpp index 78b974efc..ab2488349 100644 --- a/src/JSystem/JKernel/JKRAramHeap.cpp +++ b/src/JSystem/JKernel/JKRAramHeap.cpp @@ -4,49 +4,152 @@ // #include "JSystem/JKernel/JKRAramHeap.h" -#include "dolphin/types.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "dolphin/os/OS.h" +#include "global.h" + +JSUList JKRAramHeap::sAramList; /* 802B53E8-802B54B8 .text __ct__11JKRAramHeapFUlUl */ -JKRAramHeap::JKRAramHeap(unsigned long, unsigned long) { - /* Nonmatching */ +JKRAramHeap::JKRAramHeap(u32 startAddress, u32 size) { + OSInitMutex(&mMutex); + + mHeap = JKRHeap::findFromRoot(this); + mSize = ALIGN_PREV(size, 0x20); + mHeadAddress = ALIGN_NEXT(startAddress, 0x20); + mTailAddress = mHeadAddress + mSize; + mGroupId = -1; + + JKRAramBlock* block = new (mHeap, 0) JKRAramBlock(mHeadAddress, 0, mSize, -1, false); + sAramList.append(&block->mBlockLink); } /* 802B54B8-802B5560 .text __dt__11JKRAramHeapFv */ JKRAramHeap::~JKRAramHeap() { - /* Nonmatching */ + JSUListIterator iterator(sAramList.getFirst()); + while (iterator != sAramList.getEnd()) { + delete (iterator++).getObject(); + } } /* 802B5560-802B55D8 .text alloc__11JKRAramHeapFUlQ211JKRAramHeap10EAllocMode */ -void JKRAramHeap::alloc(unsigned long, JKRAramHeap::EAllocMode) { - /* Nonmatching */ +JKRAramBlock* JKRAramHeap::alloc(u32 size, JKRAramHeap::EAllocMode allocationMode) { + lock(); + + JKRAramBlock* block; + if (allocationMode == JKRAramHeap::HEAD) { + block = allocFromHead(size); + } else { + block = allocFromTail(size); + } + + unlock(); + return block; } /* 802B55D8-802B5660 .text allocFromHead__11JKRAramHeapFUl */ -void JKRAramHeap::allocFromHead(unsigned long) { - /* Nonmatching */ +JKRAramBlock* JKRAramHeap::allocFromHead(u32 size) { + u32 alignedSize = ALIGN_NEXT(size, 0x20); + u32 bestFreeSize = UINT32_MAX; + JKRAramBlock* bestBlock = NULL; + + JSUList* list = &sAramList; + for (JSUListIterator iterator = list; iterator != list->getEnd(); ++iterator) { + JKRAramBlock* block = iterator.getObject(); + if (block->mFreeSize < alignedSize) + continue; + if (bestFreeSize <= block->mFreeSize) + continue; + + bestFreeSize = block->mFreeSize; + bestBlock = block; + + if (block->mFreeSize == alignedSize) { + break; + } + } + + if (bestBlock) { + return bestBlock->allocHead(alignedSize, mGroupId, this); + } + + return NULL; } /* 802B5660-802B56D8 .text allocFromTail__11JKRAramHeapFUl */ -void JKRAramHeap::allocFromTail(unsigned long) { - /* Nonmatching */ +JKRAramBlock* JKRAramHeap::allocFromTail(u32 size) { + u32 alignedSize = ALIGN_NEXT(size, 0x20); + JKRAramBlock* tailBlock = NULL; + + JSUList* list = &sAramList; + JSUListIterator iterator = list->getLast(); + for (; iterator != list->getEnd(); --iterator) { + JKRAramBlock* block = iterator.getObject(); + if (block->mFreeSize >= alignedSize) { + tailBlock = block; + break; + } + } + + if (tailBlock) { + return tailBlock->allocTail(alignedSize, mGroupId, this); + } + + return NULL; } /* 802B56D8-802B5750 .text getFreeSize__11JKRAramHeapFv */ -void JKRAramHeap::getFreeSize() { - /* Nonmatching */ +u32 JKRAramHeap::getFreeSize() { + u32 maxFreeSize = 0; + + lock(); + + JSUList* list = &sAramList; + JSUListIterator iterator = list; + for (; iterator != list->getEnd(); ++iterator) { + if (iterator->mFreeSize > maxFreeSize) { + maxFreeSize = iterator->mFreeSize; + } + } + + unlock(); + return maxFreeSize; } /* 802B5750-802B57BC .text getTotalFreeSize__11JKRAramHeapFv */ -void JKRAramHeap::getTotalFreeSize() { - /* Nonmatching */ +u32 JKRAramHeap::getTotalFreeSize() { + u32 totalFreeSize = 0; + + lock(); + + JSUList* list = &sAramList; + JSUListIterator iterator = list; + for (; iterator != list->getEnd(); ++iterator) { + totalFreeSize += iterator->mFreeSize; + } + + unlock(); + return totalFreeSize; } /* 802B57BC-802B590C .text dump__11JKRAramHeapFv */ void JKRAramHeap::dump() { - /* Nonmatching */ -} + lock(); -/* 802B5950-802B59A4 .text __dt__23JSUList<12JKRAramBlock>Fv */ -JSUList::~JSUList() { - /* Nonmatching */ + OSReport("\nJKRAramHeap dump\n"); + OSReport(" attr address: size gid\n"); + u32 bytesUsed = 0; + for (JSUListIterator iterator = sAramList.getFirst() ; iterator != sAramList.getEnd(); ++iterator) { + if (iterator->mSize) { + const char* type; + OSReport("%s %08x: %08x %3d\n", iterator->isTempMemory() ? " temp" : "alloc", iterator->mAddress, iterator->mSize, iterator->mGroupId); + } + if (iterator->mFreeSize) { + OSReport(" free %08x: %08x 0\n", iterator->mAddress + iterator->mSize, iterator->mFreeSize); + } + bytesUsed += iterator->mSize; + } + OSReport("%d / %d bytes (%6.2f%%) used\n", bytesUsed, mSize, (f32)bytesUsed / (f32)mSize * 100.0f); + + unlock(); } diff --git a/src/JSystem/JKernel/JKRAramPiece.cpp b/src/JSystem/JKernel/JKRAramPiece.cpp index d591be0a5..308825166 100644 --- a/src/JSystem/JKernel/JKRAramPiece.cpp +++ b/src/JSystem/JKernel/JKRAramPiece.cpp @@ -4,49 +4,150 @@ // #include "JSystem/JKernel/JKRAramPiece.h" -#include "dolphin/types.h" +#include "JSystem/JKernel/JKRAram.h" +#include "JSystem/JKernel/JKRDecomp.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "dolphin/os/OS.h" /* 802B5C14-802B5C94 .text prepareCommand__12JKRAramPieceFiUlUlUlP12JKRAramBlockPFUl_v */ -void JKRAramPiece::prepareCommand(int, unsigned long, unsigned long, unsigned long, JKRAramBlock*, void (*)(unsigned long)) { - /* Nonmatching */ +JKRAMCommand* JKRAramPiece::prepareCommand(int direction, u32 src, u32 dst, u32 length, JKRAramBlock* block, JKRAMCommand::AsyncCallback callback) { + JKRAMCommand* command = new (JKRHeap::getSystemHeap(), -4) JKRAMCommand(); + command->mTransferDirection = direction; + command->mSrc = src; + command->mDst = dst; + command->mAramBlock = block; + command->mDataLength = length; + command->mCallback = callback; + return command; } /* 802B5C94-802B5CB4 .text sendCommand__12JKRAramPieceFP12JKRAMCommand */ -void JKRAramPiece::sendCommand(JKRAMCommand*) { - /* Nonmatching */ +void JKRAramPiece::sendCommand(JKRAMCommand* command) { + startDMA(command); } +JSUList JKRAramPiece::sAramPieceCommandList; +OSMutex JKRAramPiece::mMutex; + /* 802B5CB4-802B5E0C .text orderAsync__12JKRAramPieceFiUlUlUlP12JKRAramBlockPFUl_v */ -void JKRAramPiece::orderAsync(int, unsigned long, unsigned long, unsigned long, JKRAramBlock*, void (*)(unsigned long)) { - /* Nonmatching */ +JKRAMCommand* JKRAramPiece::orderAsync(int direction, u32 source, u32 destination, u32 length, JKRAramBlock* block, JKRAMCommand::AsyncCallback callback) { + lock(); + if ((source & 0x1f) != 0 || (destination & 0x1f) != 0) { + OSReport("direction = %x\n", direction); + OSReport("source = %x\n", source); + OSReport("destination = %x\n", destination); + OSReport("length = %x\n", length); + OSPanic(__FILE__, 102, "Abort."); + } + + Message* message = new (JKRHeap::getSystemHeap(), -4) Message(); + JKRAMCommand* command = + JKRAramPiece::prepareCommand(direction, source, destination, length, block, callback); + message->field_0x00 = 1; + message->command = command; + + OSSendMessage(&JKRAram::sMessageQueue, message, OS_MESSAGE_BLOCK); + if (command->mCallback != NULL) { + sAramPieceCommandList.append(&command->mPieceLink); + } + + unlock(); + return command; } /* 802B5E0C-802B5ED4 .text sync__12JKRAramPieceFP12JKRAMCommandi */ -void JKRAramPiece::sync(JKRAMCommand*, int) { - /* Nonmatching */ +BOOL JKRAramPiece::sync(JKRAMCommand* command, int is_non_blocking) { + OSMessage message; + + lock(); + if (is_non_blocking == 0) { + OSReceiveMessage(&command->mMessageQueue, &message, OS_MESSAGE_BLOCK); + sAramPieceCommandList.remove(&command->mPieceLink); + unlock(); + return TRUE; + } + + BOOL result = OSReceiveMessage(&command->mMessageQueue, &message, OS_MESSAGE_NOBLOCK); + if (!result) { + unlock(); + return FALSE; + } + + sAramPieceCommandList.remove(&command->mPieceLink); + unlock(); + return TRUE; } /* 802B5ED4-802B5F68 .text orderSync__12JKRAramPieceFiUlUlUlP12JKRAramBlock */ -void JKRAramPiece::orderSync(int, unsigned long, unsigned long, unsigned long, JKRAramBlock*) { - /* Nonmatching */ +BOOL JKRAramPiece::orderSync(int direction, u32 source, u32 destination, u32 length, JKRAramBlock* block) { + lock(); + + JKRAMCommand* command = + JKRAramPiece::orderAsync(direction, source, destination, length, block, NULL); + BOOL result = JKRAramPiece::sync(command, 0); + delete command; + + unlock(); + return result; } /* 802B5F68-802B5FE0 .text startDMA__12JKRAramPieceFP12JKRAMCommand */ -void JKRAramPiece::startDMA(JKRAMCommand*) { - /* Nonmatching */ +void JKRAramPiece::startDMA(JKRAMCommand* command) { + if (command->mTransferDirection == 1) { + DCInvalidateRange((void*)command->mDst, command->mDataLength); + } else { + DCStoreRange((void*)command->mSrc, command->mDataLength); + } + + ARQPostRequest(&command->mRequest, 0, command->mTransferDirection, 0, command->mSrc, + command->mDst, command->mDataLength, JKRAramPiece::doneDMA); } /* 802B5FE0-802B6088 .text doneDMA__12JKRAramPieceFUl */ -void JKRAramPiece::doneDMA(unsigned long) { - /* Nonmatching */ +void JKRAramPiece::doneDMA(u32 requestAddress) { + JKRAMCommand* command = (JKRAMCommand*)requestAddress; + + if (command->mTransferDirection == 1) { + DCInvalidateRange((void*)command->mDst, command->mDataLength); + } + + if (command->field_0x60 != 0) { + if (command->field_0x60 == 2) { + JKRDecomp::sendCommand(command->mDecompCommand); + } + return; + } + + if (command->mCallback) { + (*command->mCallback)(requestAddress); + } else if (command->field_0x5C) { + OSSendMessage(command->field_0x5C, command, OS_MESSAGE_NOBLOCK); + } else { + OSSendMessage(&command->mMessageQueue, command, OS_MESSAGE_NOBLOCK); + } } /* 802B6088-802B60F8 .text __ct__12JKRAMCommandFv */ -JKRAMCommand::JKRAMCommand() { - /* Nonmatching */ +JKRAMCommand::JKRAMCommand() : mPieceLink(this), field_0x30(this) { + OSInitMessageQueue(&mMessageQueue, &mMessage, OS_MESSAGE_BLOCK); + mCallback = NULL; + field_0x5C = NULL; + field_0x60 = 0; + field_0x8C = NULL; + field_0x90 = NULL; + field_0x94 = NULL; } /* 802B60F8-802B61A0 .text __dt__12JKRAMCommandFv */ JKRAMCommand::~JKRAMCommand() { - /* Nonmatching */ + if (field_0x8C) { + delete field_0x8C; + } + if (field_0x90) { + delete field_0x90; + } + + if (field_0x94) { + JKRHeap::free(field_0x94, NULL); + } } diff --git a/src/JSystem/JKernel/JKRAramStream.cpp b/src/JSystem/JKernel/JKRAramStream.cpp index 4bcf69054..5ca40cc8e 100644 --- a/src/JSystem/JKernel/JKRAramStream.cpp +++ b/src/JSystem/JKernel/JKRAramStream.cpp @@ -4,59 +4,200 @@ // #include "JSystem/JKernel/JKRAramStream.h" -#include "dolphin/types.h" +#include "JSystem/JKernel/JKRAramPiece.h" +#include "JSystem/JSupport/JSUFileStream.h" +#include "dolphin/os/OS.h" +#include "global.h" + +JKRAramStream* JKRAramStream::sAramStreamObject; /* 802B61E4-802B6254 .text create__13JKRAramStreamFl */ -void JKRAramStream::create(long) { - /* Nonmatching */ +JKRAramStream* JKRAramStream::create(s32 priority) { + if (!sAramStreamObject) { + sAramStreamObject = new (JKRGetSystemHeap(), 0) JKRAramStream(priority); + setTransBuffer(NULL, 0, NULL); + } + + return sAramStreamObject; } +void* JKRAramStream::sMessageBuffer[4] = { NULL, NULL, NULL, NULL }; +OSMessageQueue JKRAramStream::sMessageQueue = {0}; + /* 802B6254-802B62A4 .text __ct__13JKRAramStreamFl */ -JKRAramStream::JKRAramStream(long) { - /* Nonmatching */ +JKRAramStream::JKRAramStream(s32 priority) : JKRThread (0x4000, 0x10, priority) { + resume(); } /* 802B62A4-802B6304 .text __dt__13JKRAramStreamFv */ -JKRAramStream::~JKRAramStream() { - /* Nonmatching */ -} +JKRAramStream::~JKRAramStream() {} /* 802B6304-802B6374 .text run__13JKRAramStreamFv */ -void JKRAramStream::run() { - /* Nonmatching */ +void* JKRAramStream::run() { + OSInitMessageQueue(&sMessageQueue, sMessageBuffer, ARRAY_SIZE(sMessageBuffer)); + + for (;;) { + OSMessage message; + OSReceiveMessage(&sMessageQueue, &message, OS_MESSAGE_BLOCK); + JKRAramStreamCommand* command = (JKRAramStreamCommand*)message; + + switch (command->mType) { + case JKRAramStreamCommand::READ: + readFromAram(); + break; + case JKRAramStreamCommand::WRITE: + writeToAram(command); + break; + } + } } /* 802B6374-802B637C .text readFromAram__13JKRAramStreamFv */ -void JKRAramStream::readFromAram() { - /* Nonmatching */ +s32 JKRAramStream::readFromAram() { + return 1; } /* 802B637C-802B6568 .text writeToAram__13JKRAramStreamFP20JKRAramStreamCommand */ -void JKRAramStream::writeToAram(JKRAramStreamCommand*) { - /* Nonmatching */ +s32 JKRAramStream::writeToAram(JKRAramStreamCommand* command) { + u32 dstSize = command->mSize; + u32 offset = command->mOffset; + u32 writtenLength = 0; + u32 destination = command->mAddress; + u8* buffer = command->mTransferBuffer; + u32 bufferSize = command->mTransferBufferSize; + JKRHeap* heap = command->mHeap; + + if (buffer) { + bufferSize = (bufferSize) ? bufferSize : 0x400; + + command->mTransferBufferSize = bufferSize; + command->mAllocatedTransferBuffer = false; + } else { + bufferSize = (bufferSize) ? bufferSize : 0x400; + + if (heap) { + buffer = (u8*)JKRAllocFromHeap(heap, bufferSize, -0x20); + command->mTransferBuffer = buffer; + } else { + buffer = (u8*)JKRAllocFromHeap(NULL, bufferSize, -0x20); + command->mTransferBuffer = buffer; + } + + command->mTransferBufferSize = bufferSize; + command->mAllocatedTransferBuffer = true; + } + + if (!buffer) { + if (!heap) { + JKRGetCurrentHeap()->dump(); + } else { + heap->dump(); + } + + OSReport(":::Cannot alloc memory [%s][%d]\n", __FILE__, 168); + OSPanic(__FILE__, 169, "abort\n"); + } + + if (buffer) { + command->mStream->seek(offset, JSUStreamSeekFrom_SET); + while (dstSize != 0) { + u32 length = (dstSize > bufferSize) ? bufferSize : dstSize; + + s32 readLength = command->mStream->read(buffer, length); + if (readLength == 0) { + writtenLength = 0; + break; + } + + JKRAramPcs(0, (u32)buffer, destination, length, NULL); + dstSize -= length; + writtenLength += length; + destination += length; + } + + if (command->mAllocatedTransferBuffer) { + i_JKRFree(buffer); + command->mAllocatedTransferBuffer = false; + } + } + + OSSendMessage(&command->mMessageQueue, (OSMessage)writtenLength, OS_MESSAGE_NOBLOCK); + return writtenLength; } +u8* JKRAramStream::transBuffer; +u32 JKRAramStream::transSize; +JKRHeap* JKRAramStream::transHeap; + /* 802B6568-802B6624 .text write_StreamToAram_Async__13JKRAramStreamFP18JSUFileInputStreamUlUlUl */ -void JKRAramStream::write_StreamToAram_Async(JSUFileInputStream*, unsigned long, unsigned long, unsigned long) { - /* Nonmatching */ +JKRAramStreamCommand* JKRAramStream::write_StreamToAram_Async(JSUFileInputStream* stream, u32 addr, u32 size, u32 offset) { + JKRAramStreamCommand* command = new (JKRGetSystemHeap(), -4) JKRAramStreamCommand(); + command->mType = JKRAramStreamCommand::WRITE; + command->mAddress = addr; + command->mSize = size; + command->mStream = stream; + command->field_0x2c = 0; + command->mOffset = offset; + command->mTransferBuffer = transBuffer; + command->mHeap = transHeap; + command->mTransferBufferSize = transSize; + + OSInitMessageQueue(&command->mMessageQueue, &command->mMessage, 1); + OSSendMessage(&sMessageQueue, command, OS_MESSAGE_BLOCK); + return command; } /* 802B6624-802B66B8 .text sync__13JKRAramStreamFP20JKRAramStreamCommandi */ -void JKRAramStream::sync(JKRAramStreamCommand*, int) { - /* Nonmatching */ +JKRAramStreamCommand* JKRAramStream::sync(JKRAramStreamCommand* command, int isNonBlocking) { + OSMessage message; + if (isNonBlocking == 0) { + OSReceiveMessage(&command->mMessageQueue, &message, OS_MESSAGE_BLOCK); + if (message == NULL) { + command = NULL; + return command; + } else { + return command; + } + } else { + BOOL receiveResult = + OSReceiveMessage(&command->mMessageQueue, &message, OS_MESSAGE_NOBLOCK); + if (receiveResult == FALSE) { + command = NULL; + return command; + } else if (message == NULL) { + command = NULL; + return command; + } else { + return command; + } + } } /* 802B66B8-802B6708 .text setTransBuffer__13JKRAramStreamFPUcUlP7JKRHeap */ -void JKRAramStream::setTransBuffer(unsigned char*, unsigned long, JKRHeap*) { - /* Nonmatching */ +void JKRAramStream::setTransBuffer(u8* buffer, u32 bufferSize, JKRHeap* heap) { + transBuffer = NULL; + transSize = 0x400; + transHeap = NULL; + + if (buffer) { + transBuffer = (u8*)ALIGN_NEXT((u32)buffer, 0x20); + } + + if (bufferSize) { + transSize = ALIGN_PREV(bufferSize, 0x20); + } + + if (heap && !buffer) { + transHeap = heap; + } } /* 802B6708-802B6714 .text __ct__20JKRAramStreamCommandFv */ JKRAramStreamCommand::JKRAramStreamCommand() { - /* Nonmatching */ + mAllocatedTransferBuffer = false; } /* 802B6714-802B6770 .text getAvailable__20JSURandomInputStreamCFv */ -void JSURandomInputStream::getAvailable() const { - /* Nonmatching */ +s32 JSURandomInputStream::getAvailable() const { + return getLength() - getPosition(); } diff --git a/src/JSystem/JKernel/JKRDvdAramRipper.cpp b/src/JSystem/JKernel/JKRDvdAramRipper.cpp index 0d2b2612c..9a6dfafef 100644 --- a/src/JSystem/JKernel/JKRDvdAramRipper.cpp +++ b/src/JSystem/JKernel/JKRDvdAramRipper.cpp @@ -4,74 +4,420 @@ // #include "JSystem/JKernel/JKRDvdAramRipper.h" -#include "dolphin/types.h" +#include "JSystem/JKernel/JKRAram.h" +#include "JSystem/JKernel/JKRAramPiece.h" +#include "JSystem/JKernel/JKRAramStream.h" +#include "JSystem/JKernel/JKRDecomp.h" +#include "JSystem/JKernel/JKRDvdFile.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "JSystem/JSupport/JSUFileStream.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "MSL_C/string.h" +#include "dolphin/os/OSCache.h" +#include "dolphin/os/OSInterrupt.h" +#include "dolphin/vi/vi.h" +#include "global.h" + +static int JKRDecompressFromDVDToAram(JKRDvdFile*, u32, u32, u32, u32, u32); +static int decompSZS_subroutine(u8*, u32); +static u8* firstSrcData(); +static u8* nextSrcData(u8*); +static u32 dmaBufferFlush(u32); /* 802BDA14-802BDAB0 .text loadToAram__16JKRDvdAramRipperFlUl15JKRExpandSwitchUlUl */ -void JKRDvdAramRipper::loadToAram(long, unsigned long, JKRExpandSwitch, unsigned long, unsigned long) { - /* Nonmatching */ +JKRAramBlock* JKRDvdAramRipper::loadToAram(s32 entryNumber, u32 address, JKRExpandSwitch expandSwitch, u32 param_3, u32 param_4) { + JKRDvdFile dvdFile; + if (!dvdFile.open(entryNumber)) { + return NULL; + } else { + return loadToAram(&dvdFile, address, expandSwitch, param_3, param_4); + } } /* 802BDAB0-802BDB50 .text loadToAram__16JKRDvdAramRipperFP10JKRDvdFileUl15JKRExpandSwitchUlUl */ -void JKRDvdAramRipper::loadToAram(JKRDvdFile*, unsigned long, JKRExpandSwitch, unsigned long, unsigned long) { - /* Nonmatching */ +JKRAramBlock* JKRDvdAramRipper::loadToAram(JKRDvdFile* dvdFile, u32 address, JKRExpandSwitch expandSwitch, u32 param_3, u32 param_4) { + JKRADCommand* command = loadToAram_Async(dvdFile, address, expandSwitch, NULL, param_3, param_4); + syncAram(command, 0); + + if (command->field_0x44 < 0) { + delete command; + return NULL; + } + + if (address) { + delete command; + return (JKRAramBlock*)-1; + } + + JKRAramBlock* result = command->mBlock; + delete command; + return result; } +bool JKRDvdAramRipper::errorRetry = true; + /* 802BDB50-802BDBFC .text loadToAram_Async__16JKRDvdAramRipperFP10JKRDvdFileUl15JKRExpandSwitchPFUl_vUlUl */ -void JKRDvdAramRipper::loadToAram_Async(JKRDvdFile*, unsigned long, JKRExpandSwitch, void (*)(unsigned long), unsigned long, unsigned long) { - /* Nonmatching */ +JKRADCommand* JKRDvdAramRipper::loadToAram_Async(JKRDvdFile* dvdFile, u32 address, JKRExpandSwitch expandSwitch, void (*callback)(u32), u32 param_4, u32 param_5) { + JKRADCommand* command = new (JKRGetSystemHeap(), -4) JKRADCommand(); + command->mDvdFile = dvdFile; + command->mAddress = address; + command->mBlock = NULL; + command->mExpandSwitch = expandSwitch; + command->mCallback = callback; + command->mOffset = param_4; + command->field_0x18 = param_5; + + if (!callCommand_Async(command)) { + delete command; + return NULL; + } + + return command; } +JSUList JKRDvdAramRipper::sDvdAramAsyncList; + /* 802BDBFC-802BDF34 .text callCommand_Async__16JKRDvdAramRipperFP12JKRADCommand */ -void JKRDvdAramRipper::callCommand_Async(JKRADCommand*) { +JKRADCommand* JKRDvdAramRipper::callCommand_Async(JKRADCommand* command) { /* Nonmatching */ -} + s32 compression; + s32 uncompressedSize; + bool bVar1 = true; + JKRDvdFile* dvdFile = command->mDvdFile; + compression = 0; + OSLockMutex(&dvdFile->mMutex2); -/* 802BDF34-802BDFA4 .text __dt__18JSUFileInputStreamFv */ -JSUFileInputStream::~JSUFileInputStream() { - /* Nonmatching */ + if (dvdFile->field_0x50) { + bVar1 = false; + } else { + dvdFile->field_0x50 = OSGetCurrentThread(); + JSUFileInputStream* stream = new (JKRGetSystemHeap(), -4) JSUFileInputStream(dvdFile); + dvdFile->mFileStream = stream; + u32 fileSize = dvdFile->getFileSize(); + if (command->field_0x18 && fileSize > command->field_0x18) { + fileSize = command->field_0x18; + } + fileSize = ALIGN_NEXT(fileSize, 0x20); + if (command->mExpandSwitch == 1) { + u8 buffer[0x40]; + u8* bufPtr = (u8*)ALIGN_NEXT((u32)&buffer, 0x20); + while (true) { + if (DVDReadPrio(dvdFile->getFileInfo(), bufPtr, 0x20, 0, 2) >= 0) { + break; + } + + if (errorRetry == 0) { + delete stream; + return NULL; + } + + VIWaitForRetrace(); + } + DCInvalidateRange(bufPtr, 0x20); + + compression = JKRCheckCompressed(bufPtr); + uncompressedSize = JKRDecompExpandSize(bufPtr); + if (command->field_0x18 && command->field_0x18 > uncompressedSize) { + uncompressedSize = command->field_0x18; + } + } + + if (compression == 0) { + command->mExpandSwitch = EXPAND_SWITCH_UNKNOWN0; + } + + if (command->mExpandSwitch == EXPAND_SWITCH_UNKNOWN1) { + if (command->mAddress == 0 && command->mBlock == NULL) { + command->mBlock = + JKRAram::getAramHeap()->alloc(uncompressedSize, JKRAramHeap::HEAD); + if (command->mBlock) { + command->mAddress = command->mBlock->mAddress; + } + dvdFile->mBlock = command->mBlock; + } + + if (command->mBlock) { + command->mAddress = command->mBlock->mAddress; + } + + if (command->mAddress == 0) { + dvdFile->field_0x50 = NULL; + return NULL; + } + } else { + if (command->mAddress == 0 && !command->mBlock) { + command->mBlock = JKRAram::getAramHeap()->alloc(fileSize, JKRAramHeap::HEAD); + } + + if (command->mBlock) { + command->mAddress = command->mBlock->mAddress; + } + + if (command->mAddress == 0) { + dvdFile->field_0x50 = NULL; + return NULL; + } + } + + if (compression == 0) { + command->mStreamCommand = JKRStreamToAram_Async(stream, command->mAddress, fileSize - command->mOffset, command->mOffset, NULL); + } else if (compression == 1) { + command->mStreamCommand = JKRStreamToAram_Async(stream, command->mAddress, fileSize - command->mOffset, command->mOffset, NULL); + } else if (compression == 2) { + command->mStreamCommand = NULL; + JKRDecompressFromDVDToAram(command->mDvdFile, command->mAddress, fileSize, uncompressedSize, command->mOffset, 0); + } + + if (!command->mCallback) { + (*((JSUList*)&sDvdAramAsyncList)).append(&command->mLink); + } else { + command->mCallback((u32)command); + } + } + + OSUnlockMutex(&dvdFile->mMutex2); + return bVar1 == true ? command : NULL; } /* 802BDFA4-802BE078 .text syncAram__16JKRDvdAramRipperFP12JKRADCommandi */ -void JKRDvdAramRipper::syncAram(JKRADCommand*, int) { - /* Nonmatching */ +bool JKRDvdAramRipper::syncAram(JKRADCommand* command, int param_1) { + JKRDvdFile* dvdFile = command->mDvdFile; + OSLockMutex(&dvdFile->mMutex2); + + if (command->mStreamCommand) { + JKRAramStreamCommand* var1 = JKRAramStream::sync(command->mStreamCommand, param_1); + command->field_0x44 = -(var1 == NULL); + + if (param_1 != 0 && var1 == NULL) { + OSUnlockMutex(&dvdFile->mMutex2); + return false; + } + } + + (*((JSUList*)&sDvdAramAsyncList)).remove(&command->mLink); + if (command->mStreamCommand) { + delete command->mStreamCommand; + } + + delete dvdFile->mFileStream; + dvdFile->field_0x50 = NULL; + OSUnlockMutex(&dvdFile->mMutex2); + return true; } /* 802BE078-802BE0B8 .text __ct__12JKRADCommandFv */ -JKRADCommand::JKRADCommand() { - /* Nonmatching */ +JKRADCommand::JKRADCommand() : mLink(this) { + field_0x44 = 0; + field_0x48 = false; } /* 802BE0B8-802BE144 .text __dt__12JKRADCommandFv */ JKRADCommand::~JKRADCommand() { - /* Nonmatching */ + if (field_0x48 == true) { + delete mDvdFile; + } } +static OSMutex decompMutex; +u32 JKRDvdAramRipper::sSzpBufferSize = 0x00000400; +static u8* szpBuf; +static u8* szpEnd; +static u8* refBuf; +static u8* refEnd; +static u8* refCurrent; +static u8* dmaBuf; +static u8* dmaEnd; +static u8* dmaCurrent; +static u32 srcOffset; +static u32 transLeft; +static u8* srcLimit; +static JKRDvdFile* srcFile; +static u32 fileOffset; +static int readCount; +static u32 maxDest; +static bool isInitMutex; + /* 802BE144-802BE34C .text JKRDecompressFromDVDToAram__FP10JKRDvdFileUlUlUlUlUl */ -void JKRDecompressFromDVDToAram(JKRDvdFile*, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) { - /* Nonmatching */ +static int JKRDecompressFromDVDToAram(JKRDvdFile* dvdFile, u32 param_1, u32 fileSize, u32 uncompressedSize, u32 param_4, u32 param_5) { + BOOL level = OSDisableInterrupts(); + if (!isInitMutex) { + OSInitMutex(&decompMutex); + isInitMutex = true; + } + + OSRestoreInterrupts(level); + OSLockMutex(&decompMutex); + u32 bufferSize = JKRDvdAramRipper::getSzpBufferSize(); + szpBuf = (u8*)JKRAllocFromSysHeap(bufferSize, 0x20); + JUT_ASSERT(693, szpBuf != 0); + szpEnd = szpBuf + bufferSize; + refBuf = (u8*)JKRAllocFromSysHeap(0x1120, 0); + JUT_ASSERT(701, refBuf != 0); + refEnd = refBuf + 0x1120; + refCurrent = refBuf; + dmaBuf = (u8*)JKRAllocFromSysHeap(0x100, 0x20); + JUT_ASSERT(710, dmaBuf != 0); + dmaEnd = dmaBuf + 0x100; + dmaCurrent = dmaBuf; + srcFile = dvdFile; + srcOffset = param_5; + transLeft = fileSize - param_5; + fileOffset = param_4; + readCount = 0; + maxDest = uncompressedSize; + u8* first = firstSrcData(); + int result = first ? decompSZS_subroutine(first, param_1) : -1; + JKRHeap::free(szpBuf, 0); + JKRHeap::free(refBuf, 0); + JKRHeap::free(dmaBuf, 0); + OSUnlockMutex(&decompMutex); + return result; } /* 802BE34C-802BE5C0 .text decompSZS_subroutine__FPUcUl */ -void decompSZS_subroutine(unsigned char*, unsigned long) { - /* Nonmatching */ +static int decompSZS_subroutine(u8* src, u32 dest) { + u32 endAddr; + s32 validBitCount = 0; + u32 currCodeByte = 0; + u32 startDest = dest; + + if (src[0] != 'Y' || src[1] != 'a' || src[2] != 'z' || src[3] != '0') { + return -1; + } + + SYaz0Header* header = (SYaz0Header*)src; + endAddr = dest + (header->length - fileOffset); + if (endAddr > dest + maxDest) { + endAddr = dest + maxDest; + } + + src += 0x10; + do { + if (validBitCount == 0) { + if ((src > srcLimit) && transLeft) { + src = nextSrcData(src); + } + currCodeByte = *src; + validBitCount = 8; + src++; + } + if (currCodeByte & 0x80) { + if (readCount >= fileOffset) { + *(dmaCurrent++) = *src; + dest++; + if (dmaCurrent == dmaEnd) { + startDest += dmaBufferFlush(startDest); + } + if (dest == endAddr) { + break; + } + } + *(refCurrent++) = *src; + if (refCurrent == refEnd) { + refCurrent = refBuf; + } + readCount++; + src++; + } else { + u32 dist = ((src[0] & 0x0f) << 8) | src[1]; + s32 numBytes = src[0] >> 4; + src += 2; + u8* copySource = refCurrent - dist - 1; + if (copySource < refBuf) { + copySource += refEnd - refBuf; + } + if (numBytes == 0) { + numBytes = *src + 0x12; + src += 1; + } else { + numBytes += 2; + } + do { + if (readCount >= fileOffset) { + *(dmaCurrent++) = *copySource; + dest++; + if (dmaCurrent == dmaEnd) { + startDest += dmaBufferFlush(startDest); + } + if (dest == endAddr) { + break; + } + } + *(refCurrent++) = *copySource; + if (refCurrent == refEnd) { + refCurrent = refBuf; + } + copySource++; + if (copySource == refEnd) { + copySource = refBuf; + } + readCount++; + numBytes--; + } while (numBytes != 0); + } + currCodeByte <<= 1; + validBitCount--; + } while (dest < endAddr); + dmaBufferFlush(startDest); + return 0; } /* 802BE5C0-802BE674 .text firstSrcData__Fv */ -void firstSrcData() { - /* Nonmatching */ +static u8* firstSrcData() { + srcLimit = szpEnd - 0x19; + u8* buffer = szpBuf; + u32 bufSize = szpEnd - buffer; + u32 length = transLeft < bufSize ? transLeft : bufSize; + while (true) { + int result = DVDReadPrio(&srcFile->mFileInfo, buffer, length, 0, 2); + if (result >= 0) { + break; + } + if (JKRDvdAramRipper::errorRetry == 0) { + return NULL; + } + VIWaitForRetrace(); + } + srcOffset += length; + transLeft -= length; + return buffer; } /* 802BE674-802BE790 .text nextSrcData__FPUc */ -void nextSrcData(unsigned char*) { - /* Nonmatching */ +static u8* nextSrcData(u8* src) { + u32 size = szpEnd - src; + u8* dest = IS_NOT_ALIGNED(size, 0x20) ? szpBuf + 0x20 - (size & (0x20 - 1)) : szpBuf; + memcpy(dest, src, size); + u32 transSize = szpEnd - (dest + size); + if (transSize > transLeft) { + transSize = transLeft; + } + JUT_ASSERT(966, transSize > 0); + while (true) { + s32 result = DVDReadPrio(&srcFile->mFileInfo, dest + size, transSize, srcOffset, 2); + if (result >= 0) { + break; + } + if (JKRDvdAramRipper::errorRetry == 0) { + return NULL; + } + VIWaitForRetrace(); + } + srcOffset += transSize; + transLeft -= transSize; + if (transLeft == 0) { + srcLimit = dest + size + transSize; + } + return dest; } /* 802BE790-802BE7F8 .text dmaBufferFlush__FUl */ -void dmaBufferFlush(unsigned long) { - /* Nonmatching */ -} - -/* 802BE83C-802BE890 .text __dt__23JSUList<12JKRADCommand>Fv */ -JSUList::~JSUList() { - /* Nonmatching */ +static u32 dmaBufferFlush(u32 param_1) { + if (dmaCurrent == dmaBuf) { + return 0; + } + u32 size = ALIGN_NEXT(dmaCurrent - dmaBuf, 0x20); + JKRAramPiece::orderSync(0, (u32)dmaBuf, param_1, size, NULL); + dmaCurrent = dmaBuf; + return size; } diff --git a/src/JSystem/JKernel/JKRDvdArchive.cpp b/src/JSystem/JKernel/JKRDvdArchive.cpp index 7ec088dba..23b5ef693 100644 --- a/src/JSystem/JKernel/JKRDvdArchive.cpp +++ b/src/JSystem/JKernel/JKRDvdArchive.cpp @@ -4,6 +4,7 @@ // #include "JSystem/JKernel/JKRDvdArchive.h" +#include "JSystem/JKernel/JKRDecomp.h" #include "JSystem/JKernel/JKRDvdFile.h" #include "JSystem/JKernel/JKRDvdRipper.h" #include "JSystem/JKernel/JKRHeap.h" diff --git a/src/JSystem/JKernel/JKRDvdFile.cpp b/src/JSystem/JKernel/JKRDvdFile.cpp index 3cdc52ce2..dc4898e6b 100644 --- a/src/JSystem/JKernel/JKRDvdFile.cpp +++ b/src/JSystem/JKernel/JKRDvdFile.cpp @@ -4,74 +4,145 @@ // #include "JSystem/JKernel/JKRDvdFile.h" +#include "JSystem/JUtility/JUTAssert.h" #include "dolphin/types.h" +JSUList JKRDvdFile::sDvdList; + /* 802BC6B4-802BC728 .text __ct__10JKRDvdFileFv */ -JKRDvdFile::JKRDvdFile() { - /* Nonmatching */ +JKRDvdFile::JKRDvdFile() : mDvdLink(this) { + initiate(); } /* 802BC728-802BC7D0 .text __ct__10JKRDvdFileFPCc */ -JKRDvdFile::JKRDvdFile(const char*) { - /* Nonmatching */ +JKRDvdFile::JKRDvdFile(const char* name) : mDvdLink(this) { + initiate(); + bool result = open(name); + mIsAvailable = result; + // weird code. doesn't match without this, maybe remains from assert or something? + if (mIsAvailable) { + return; + } else { + return; + } } /* 802BC7D0-802BC878 .text __ct__10JKRDvdFileFl */ -JKRDvdFile::JKRDvdFile(long) { - /* Nonmatching */ +JKRDvdFile::JKRDvdFile(s32 entryNum) : mDvdLink(this) { + initiate(); + bool result = open(entryNum); + mIsAvailable = result; + // weird code. doesn't match without this, maybe remains from assert or something? + if (mIsAvailable) { + return; + } else { + return; + } } /* 802BC878-802BC914 .text __dt__10JKRDvdFileFv */ JKRDvdFile::~JKRDvdFile() { - /* Nonmatching */ + close(); } /* 802BC914-802BC980 .text initiate__10JKRDvdFileFv */ void JKRDvdFile::initiate() { - /* Nonmatching */ + mDvdFile = this; + OSInitMutex(&mMutex1); + OSInitMutex(&mMutex2); + OSInitMessageQueue(&mMessageQueue2, &mMessage2, 1); + OSInitMessageQueue(&mMessageQueue1, &mMessage1, 1); + mOSThread = NULL; + field_0x50 = 0; + field_0x58 = 0; } /* 802BC980-802BC9F4 .text open__10JKRDvdFileFPCc */ -void JKRDvdFile::open(const char*) { - /* Nonmatching */ +bool JKRDvdFile::open(const char* name) { + if (!mIsAvailable) { + mIsAvailable = DVDOpen(name, &mFileInfo); + if (mIsAvailable) { + getDvdList().append(&mDvdLink); + getStatus(); + } + } + return mIsAvailable; } /* 802BC9F4-802BCA68 .text open__10JKRDvdFileFl */ -void JKRDvdFile::open(long) { - /* Nonmatching */ +bool JKRDvdFile::open(s32 entryNum) { + if (!mIsAvailable) { + mIsAvailable = DVDFastOpen(entryNum, &mFileInfo); + if (mIsAvailable) { + getDvdList().append(&mDvdLink); + getStatus(); + } + } + return mIsAvailable; } /* 802BCA68-802BCAE0 .text close__10JKRDvdFileFv */ void JKRDvdFile::close() { - /* Nonmatching */ + if (mIsAvailable) { + s32 result = DVDClose(&mFileInfo); + if (result != 0) { + mIsAvailable = false; + getDvdList().remove(&mDvdLink); + } else { + OSPanic(__FILE__, 212, "cannot close DVD file\n"); + } + } } /* 802BCAE0-802BCBCC .text readData__10JKRDvdFileFPvll */ -void JKRDvdFile::readData(void*, long, long) { - /* Nonmatching */ +s32 JKRDvdFile::readData(void* param_1, s32 length, s32 param_3) { + /* clang-format off */ + JUT_ASSERT(236, ( length & 0x1f ) == 0); + /* clang-format on */ + + OSLockMutex(&mMutex1); + if (mOSThread) { + OSUnlockMutex(&mMutex1); + return -1; + } + + mOSThread = OSGetCurrentThread(); + + s32 result = -1; + s32 readAsyncResult = + DVDReadAsyncPrio(&mFileInfo, param_1, length, param_3, JKRDvdFile::doneProcess, 2); + if (readAsyncResult) { + result = sync(); + } + + mOSThread = NULL; + OSUnlockMutex(&mMutex1); + + return result; } /* 802BCBCC-802BCC24 .text writeData__10JKRDvdFileFPCvll */ -void JKRDvdFile::writeData(const void*, long, long) { - /* Nonmatching */ +s32 JKRDvdFile::writeData(const void* param_0, s32 length, s32 param_2) { + /* clang-format off */ + JUT_ASSERT(340, ( length & 0x1f ) == 0); + /* clang-format on */ + + return -1; } /* 802BCC24-802BCC78 .text sync__10JKRDvdFileFv */ -void JKRDvdFile::sync() { - /* Nonmatching */ +s32 JKRDvdFile::sync() { + OSMessage message; + OSLockMutex(&mMutex1); + OSReceiveMessage(&mMessageQueue2, &message, 1); + mOSThread = NULL; + OSUnlockMutex(&mMutex1); + return (int)message; } /* 802BCC78-802BCCAC .text doneProcess__10JKRDvdFileFlP11DVDFileInfo */ -void JKRDvdFile::doneProcess(long, DVDFileInfo*) { - /* Nonmatching */ -} - -/* 802BCCAC-802BCCB4 .text getFileSize__10JKRDvdFileCFv */ -void JKRDvdFile::getFileSize() const { - /* Nonmatching */ -} - -/* 802BCCF8-802BCD4C .text __dt__21JSUList<10JKRDvdFile>Fv */ -JSUList::~JSUList() { - /* Nonmatching */ +void JKRDvdFile::doneProcess(s32 id, DVDFileInfo* fileInfo) { + // fileInfo->field_0x3c looks like some kind of user pointer? + JKRDvdFile* dvdFile = *(JKRDvdFile**)((u8*)fileInfo + 0x3c); + OSSendMessage(&dvdFile->mMessageQueue2, (OSMessage)id, OS_MESSAGE_NOBLOCK); } diff --git a/src/JSystem/JKernel/JKRDvdRipper.cpp b/src/JSystem/JKernel/JKRDvdRipper.cpp index 7e2787b49..289feb668 100644 --- a/src/JSystem/JKernel/JKRDvdRipper.cpp +++ b/src/JSystem/JKernel/JKRDvdRipper.cpp @@ -4,49 +4,448 @@ // #include "JSystem/JKernel/JKRDvdRipper.h" -#include "dolphin/types.h" +#include "JSystem/JKernel/JKRDecomp.h" +#include "JSystem/JKernel/JKRDvdFile.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "MSL_C/string.h" +#include "dolphin/os/OS.h" +#include "dolphin/vi/vi.h" +#include "global.h" + +static int JKRDecompressFromDVD(JKRDvdFile*, void*, u32, u32, u32, u32); +static int decompSZS_subroutine(u8*, u8*); +static u8* firstSrcData(); +static u8* nextSrcData(u8*); /* 802BCD4C-802BCE00 .text loadToMainRAM__12JKRDvdRipperFPCcPUc15JKRExpandSwitchUlP7JKRHeapQ212JKRDvdRipper15EAllocDirectionUlPi */ -void JKRDvdRipper::loadToMainRAM(const char*, unsigned char*, JKRExpandSwitch, unsigned long, JKRHeap*, JKRDvdRipper::EAllocDirection, unsigned long, int*) { - /* Nonmatching */ +void* JKRDvdRipper::loadToMainRAM(const char* name, u8* dst, JKRExpandSwitch expandSwitch, u32 dstLength, JKRHeap* heap, EAllocDirection allocDirection, u32 offset, int* pCompression) { + JKRDvdFile file; + if (!file.open(name)) { + return NULL; + } + return loadToMainRAM(&file, dst, expandSwitch, dstLength, heap, allocDirection, offset, pCompression); } /* 802BCE00-802BCEB4 .text loadToMainRAM__12JKRDvdRipperFlPUc15JKRExpandSwitchUlP7JKRHeapQ212JKRDvdRipper15EAllocDirectionUlPi */ -void JKRDvdRipper::loadToMainRAM(long, unsigned char*, JKRExpandSwitch, unsigned long, JKRHeap*, JKRDvdRipper::EAllocDirection, unsigned long, int*) { - /* Nonmatching */ +void* JKRDvdRipper::loadToMainRAM(s32 entryNumber, u8* dst, JKRExpandSwitch expandSwitch, u32 dstLength, JKRHeap* heap, EAllocDirection allocDirection, u32 offset, int* pCompression) { + JKRDvdFile file; + if (!file.open(entryNumber)) { + return NULL; + } + return loadToMainRAM(&file, dst, expandSwitch, dstLength, heap, allocDirection, offset, pCompression); } +bool JKRDvdRipper::errorRetry = true; + /* 802BCEB4-802BD324 .text loadToMainRAM__12JKRDvdRipperFP10JKRDvdFilePUc15JKRExpandSwitchUlP7JKRHeapQ212JKRDvdRipper15EAllocDirectionUlPi */ -void JKRDvdRipper::loadToMainRAM(JKRDvdFile*, unsigned char*, JKRExpandSwitch, unsigned long, JKRHeap*, JKRDvdRipper::EAllocDirection, unsigned long, int*) { - /* Nonmatching */ +void* JKRDvdRipper::loadToMainRAM(JKRDvdFile* dvdFile, u8* dst, JKRExpandSwitch expandSwitch, u32 dstLength, JKRHeap* heap, EAllocDirection allocDirection, u32 offset, int* pCompression) { + s32 fileSizeAligned; + bool hasAllocated = false; + JKRCompression compression = COMPRESSION_NONE; + u32 expandSize; + u8 *mem = NULL; + + fileSizeAligned = ALIGN_NEXT(dvdFile->getFileSize(), 32); + if (expandSwitch == EXPAND_SWITCH_UNKNOWN1) { + u8 buffer[0x40]; + u8 *bufPtr = (u8 *)ALIGN_NEXT((u32)buffer, 32); + while (true) { + int readBytes = DVDReadPrio(dvdFile->getFileInfo(), bufPtr, 0x20, 0, 2); + if (readBytes >= 0) { + break; + } + + if (readBytes == -3 || !isErrorRetry()) { + return NULL; + } + + VIWaitForRetrace(); + } + DCInvalidateRange(bufPtr, 0x20); + + compression = JKRCheckCompressed(bufPtr); + expandSize = JKRDecompExpandSize(bufPtr); + } + + if (pCompression) { + *pCompression = (int)compression; + } + + if (expandSwitch == EXPAND_SWITCH_UNKNOWN1 && compression != COMPRESSION_NONE) { + if (dstLength != 0 && expandSize > dstLength) { + expandSize = dstLength; + } + if (dst == NULL) { + dst = (u8 *)JKRAllocFromHeap(heap, expandSize, allocDirection == ALLOC_DIRECTION_FORWARD ? 32 : -32); + hasAllocated = true; + } + if (dst == NULL) { + return NULL; + } + if (compression == COMPRESSION_YAY0) { + mem = (u8 *)JKRAllocFromHeap((heap), fileSizeAligned, 32); + if (mem == NULL) { + if (hasAllocated == true) { + i_JKRFree(dst); + return NULL; + } + } + } + } else { + if (dst == NULL) { + dst = (u8 *)JKRAllocFromHeap(heap, fileSizeAligned - offset, allocDirection == ALLOC_DIRECTION_FORWARD ? 32 : -32); + hasAllocated = true; + } + if (dst == NULL) { + return NULL; + } + } + if (compression == COMPRESSION_NONE) { + JKRCompression compression2 = COMPRESSION_NONE; // maybe for a sub archive? + + if (offset != 0) { + u8 buffer[0x40]; + u8 *bufPtr = (u8 *)ALIGN_NEXT((u32)buffer, 32); + while (true) { + int readBytes = DVDReadPrio(dvdFile->getFileInfo(), bufPtr, 32, (s32)offset, 2); + if (readBytes >= 0) { + break; + } + + if (readBytes == -3 || !isErrorRetry()) { + if (hasAllocated == true) { + i_JKRFree(dst); + } + return NULL; + } + VIWaitForRetrace(); + } + DCInvalidateRange(bufPtr, 32); + + compression2 = JKRCheckCompressed(bufPtr); + } + if ((compression2 == COMPRESSION_NONE || expandSwitch == EXPAND_SWITCH_UNKNOWN2) || expandSwitch == EXPAND_SWITCH_UNKNOWN0) { + s32 size = fileSizeAligned - offset; + if (dstLength != 0 && dstLength < size) + size = dstLength; // probably a ternary + while (true) { + int readBytes = DVDReadPrio(dvdFile->getFileInfo(), dst, size, (s32)offset, 2); + if (readBytes >= 0) { + break; + } + + if (readBytes == -3 || !isErrorRetry()) { + if (hasAllocated == true) { + i_JKRFree(dst); + } + return NULL; + } + VIWaitForRetrace(); + } + + return dst; + } + else if (compression2 == COMPRESSION_YAZ0) { + JKRDecompressFromDVD(dvdFile, dst, fileSizeAligned, dstLength, 0, offset); + } else { +#if VERSION == VERSION_JPN + OSPanic(__FILE__, 337, "Sorry, not prepared for SZP resource\n"); +#else + OSPanic(__FILE__, 314, "Sorry, not prepared for SZP resource\n"); +#endif + } + return dst; + } + else if (compression == COMPRESSION_YAY0) + { + // SZP decompression + // s32 readoffset = startOffset; + if (offset != 0) { +#if VERSION == VERSION_JPN + OSPanic(__FILE__, 347, ":::Not support SZP with offset read"); +#else + OSPanic(__FILE__, 324, ":::Not support SZP with offset read"); +#endif + } + while (true) { + int readBytes = DVDReadPrio(dvdFile->getFileInfo(), mem, fileSizeAligned, 0, 2); + if (readBytes >= 0) + break; + + if (readBytes == -3 || !isErrorRetry()) { + if (hasAllocated == true) + i_JKRFree(dst); + + i_JKRFree(mem); + return NULL; + } + VIWaitForRetrace(); + } + JKRDecompress(mem, dst, expandSize, offset); + i_JKRFree(mem); + return dst; + } else if (compression == COMPRESSION_YAZ0) { + if (JKRDecompressFromDVD(dvdFile, dst, fileSizeAligned, expandSize, offset, 0) != 0u) + { + if (hasAllocated) + i_JKRFree(dst); + dst = NULL; + } + return dst; + } + else if (hasAllocated) + { + i_JKRFree(dst); + dst = NULL; + } + return NULL; } +JSUList JKRDvdRipper::sDvdAsyncList; +static OSMutex decompMutex; +u32 JKRDvdRipper::sSzpBufferSize = 0x00000400; +static u8* szpBuf; +static u8* szpEnd; +static u8* refBuf; +static u8* refEnd; +static u8* refCurrent; +static u32 srcOffset; +static u32 transLeft; +static u8* srcLimit; +static JKRDvdFile* srcFile; +static u32 fileOffset; +static u32 readCount; +static u32 maxDest; +static bool isInitMutex; + /* 802BD324-802BD4F0 .text JKRDecompressFromDVD__FP10JKRDvdFilePvUlUlUlUl */ -void JKRDecompressFromDVD(JKRDvdFile*, void*, unsigned long, unsigned long, unsigned long, unsigned long) { - /* Nonmatching */ +static int JKRDecompressFromDVD(JKRDvdFile* dvdFile, void* dst, u32 fileSize, u32 inMaxDest, u32 inFileOffset, u32 inSrcOffset) { + BOOL interrupts = OSDisableInterrupts(); + if (isInitMutex == false) { + OSInitMutex(&decompMutex); + isInitMutex = true; + } + OSRestoreInterrupts(interrupts); + OSLockMutex(&decompMutex); + int bufSize = JKRDvdRipper::getSzpBufferSize(); + szpBuf = (u8 *)JKRAllocFromSysHeap(bufSize, -0x20); +#if VERSION == VERSION_JPN + JUT_ASSERT(913, szpBuf != 0); +#else + JUT_ASSERT(884, szpBuf != 0); +#endif + + szpEnd = szpBuf + bufSize; + if (inFileOffset != 0) { + refBuf = (u8 *)JKRAllocFromSysHeap(0x1120, -4); +#if VERSION == VERSION_JPN + JUT_ASSERT(922, refBuf != 0); +#else + JUT_ASSERT(893, refBuf != 0); +#endif + refEnd = refBuf + 0x1120; + refCurrent = refBuf; + } else { + refBuf = NULL; + } + srcFile = dvdFile; + srcOffset = inSrcOffset; + transLeft = fileSize - inSrcOffset; + fileOffset = inFileOffset; + readCount = 0; + maxDest = inMaxDest; + u8 *data = firstSrcData(); + u32 result = (data != NULL) ? decompSZS_subroutine(data, (u8 *)dst) : -1; // figure out correct datatypes + u32 decompressedSize = ((u32*)data)[1]; + i_JKRFree(szpBuf); + if (refBuf) { + i_JKRFree(refBuf); + } + DCStoreRangeNoSync(dst, decompressedSize); + OSUnlockMutex(&decompMutex); + return result; } /* 802BD4F0-802BD784 .text decompSZS_subroutine__FPUcPUc */ -void decompSZS_subroutine(unsigned char*, unsigned char*) { - /* Nonmatching */ +static int decompSZS_subroutine(u8* src, u8* dest) { + u8 *endPtr; + s32 validBitCount = 0; + s32 currCodeByte = 0; + u32 ts = 0; + + if (src[0] != 'Y' || src[1] != 'a' || src[2] != 'z' || src[3] != '0') { + return -1; + } + + SYaz0Header *header = (SYaz0Header *)src; + endPtr = dest + (header->length - fileOffset); + if (endPtr > dest + maxDest) { + endPtr = dest + maxDest; + } + + src += 0x10; + do { + if (validBitCount == 0) { + if ((src > srcLimit) && transLeft) { + src = nextSrcData(src); + if (!src) { + return -1; + } + } + currCodeByte = *src; + validBitCount = 8; + src++; + } + if (currCodeByte & 0x80) { + if (fileOffset != 0) { + if (readCount >= fileOffset) { + *dest = *src; + dest++; + ts++; + if (dest == endPtr) { + break; + } + } + *(refCurrent++) = *src; + if (refCurrent == refEnd) { + refCurrent = refBuf; + } + src++; + } else { + *dest = *src; + dest++; + src++; + ts++; + if (dest == endPtr) { + break; + } + } + readCount++; + } else { + u32 dist = ((src[0] & 0x0f) << 8) | src[1]; + s32 numBytes = src[0] >> 4; + src += 2; + u8 *copySource; + if (fileOffset != 0) { + copySource = refCurrent - dist - 1; + if (copySource < refBuf) { + copySource += refEnd - refBuf; + } + } else { + copySource = dest - dist - 1; + } + if (numBytes == 0) { + numBytes = *src + 0x12; + src += 1; + } else { + numBytes += 2; + } + if (fileOffset != 0) { + do { + if (readCount >= fileOffset) { + *dest = *copySource; + dest++; + ts++; + if (dest == endPtr) { + break; + } + } + *(refCurrent++) = *copySource; + if (refCurrent == refEnd) { + refCurrent = refBuf; + } + copySource++; + if (copySource == refEnd) { + copySource = refBuf; + } + readCount++; + numBytes--; + } while (numBytes != 0); + } else { + do { + *dest = *copySource; + dest++; + ts++; + if (dest == endPtr) { + break; + } + readCount++; + numBytes--; + copySource++; + } while (numBytes != 0); + } + } + currCodeByte <<= 1; + validBitCount--; + } while (dest < endPtr); + return 0; } /* 802BD784-802BD84C .text firstSrcData__Fv */ -void firstSrcData() { - /* Nonmatching */ +static u8* firstSrcData() { + srcLimit = szpEnd - 0x19; + u8* buffer = szpBuf; + u32 bufSize = szpEnd - buffer; + u32 length = transLeft < bufSize ? transLeft : bufSize; + + while (true) { + int result = DVDReadPrio(srcFile->getFileInfo(), buffer, length, srcOffset, 2); + if (result >= 0) { + break; + } + + if (result == -3 || !JKRDvdRipper::isErrorRetry()) { + return NULL; + } + VIWaitForRetrace(); + } + + srcOffset += length; + transLeft -= length; + if (transLeft == 0) { + srcLimit = buffer + length; + } + return buffer; } /* 802BD84C-802BD974 .text nextSrcData__FPUc */ -void nextSrcData(unsigned char*) { - /* Nonmatching */ -} +static u8* nextSrcData(u8* src) { + u32 limit = szpEnd - src; + u8 *buf; + if (IS_NOT_ALIGNED(limit, 0x20)) { + buf = szpBuf + 0x20 - (limit & (0x20 - 1)); + } else { + buf = szpBuf; + } -/* 802BD974-802BD97C .text isErrorRetry__12JKRDvdRipperFv */ -void JKRDvdRipper::isErrorRetry() { - /* Nonmatching */ -} + memcpy(buf, src, limit); + u32 transSize = (u32)(szpEnd - (buf + limit)); + if (transSize > transLeft) { + transSize = transLeft; + } +#if VERSION == VERSION_JPN + JUT_ASSERT(1228, transSize > 0); +#else + JUT_ASSERT(1176, transSize > 0); +#endif -/* 802BD9C0-802BDA14 .text __dt__23JSUList<12JKRDMCommand>Fv */ -JSUList::~JSUList() { - /* Nonmatching */ + while (true) { + s32 result = DVDReadPrio(srcFile->getFileInfo(), (buf + limit), transSize, srcOffset, 2); + if (result >= 0) { + break; + } + // bug: supposed to call isErrorRetry, but didn't + if (result == -3 || !JKRDvdRipper::isErrorRetry) { + return NULL; + } + + VIWaitForRetrace(); + } + srcOffset += transSize; + transLeft -= transSize; + if (transLeft == 0) { + srcLimit = transSize + (buf + limit); + } + + return buf; } diff --git a/src/JSystem/JKernel/JKRFileCache.cpp b/src/JSystem/JKernel/JKRFileCache.cpp index 26190b9d3..89f60a249 100644 --- a/src/JSystem/JKernel/JKRFileCache.cpp +++ b/src/JSystem/JKernel/JKRFileCache.cpp @@ -4,124 +4,399 @@ // #include "JSystem/JKernel/JKRFileCache.h" -#include "dolphin/types.h" +#include "JSystem/JKernel/JKRDvdFile.h" +#include "JSystem/JKernel/JKRFileFinder.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "MSL_C/MSL_Common/Src/ctype.h" +#include "MSL_C/string.h" +#include "global.h" /* 802B6FEC-802B70EC .text mount__12JKRFileCacheFPCcP7JKRHeapPCc */ -void JKRFileCache::mount(const char*, JKRHeap*, const char*) { - /* Nonmatching */ +JKRFileCache* JKRFileCache::mount(const char* path, JKRHeap* heap, const char* param_3) { + if (!path || *path != '/') { + return NULL; + } + + u32 pathLength = strlen(path); + if (pathLength != 1 && path[pathLength - 1] == '/') { + return NULL; + } + + JSUList& volumeList = getVolumeList(); + JSUListIterator iterator; + for (iterator = volumeList.getFirst(); iterator != volumeList.getEnd(); ++iterator) { + if (iterator->getVolumeType() == 'CASH') { + JKRFileCache* fileCache = (JKRFileCache*)iterator.getObject(); + if (fileCache->mRootPath) { + if (strcmp(fileCache->mRootPath, path) == 0) { + fileCache->mMountCount++; + return fileCache; + } + } + } + } + + return new (heap, 0) JKRFileCache(path, param_3); } /* 802B70EC-802B72A8 .text __ct__12JKRFileCacheFPCcPCc */ -JKRFileCache::JKRFileCache(const char*, const char*) { - /* Nonmatching */ +JKRFileCache::JKRFileCache(const char* path, const char* volume) { + mParentHeap = JKRHeap::findFromRoot(this); + mMountCount = 1; + mVolumeType = 'CASH'; + + u32 pathLength = strlen(path); + mRootPath = (char*)JKRAllocFromHeap(mParentHeap, pathLength + 1, 1); + mCurrentPath = (char*)JKRAllocFromSysHeap(pathLength + 2, 1); + strcpy(mRootPath, path); + strcpy(mCurrentPath, path); + + if (path[1] != '\0') { + convStrLower(mRootPath); + convStrLower(mCurrentPath); + strcat(mCurrentPath, "/"); + + const char* volumePath = volume; + if (!volume) { + volumePath = strrchr(mRootPath, '/'); + volumePath++; + } + + u32 volumeLength = strlen(volumePath) + 1; + mVolumePath = (char*)JKRAllocFromSysHeap(volumeLength, 0); + strcpy(mVolumePath, volumePath); + convStrLower(mVolumePath); + mVolumeName = mVolumePath; + } else { + const char* volumePath = volume; + if (!volume) { + volumePath = "dvd"; + } + + u32 volumeLength = strlen(volumePath) + 1; + mVolumePath = (char*)JKRAllocFromSysHeap(volumeLength, 0); + strcpy(mVolumePath, volumePath); + convStrLower(mVolumePath); + mVolumeName = mVolumePath; + } + + getVolumeList().prepend(&mFileLoaderLink); + mIsMounted = true; } /* 802B72A8-802B737C .text __dt__12JKRFileCacheFv */ JKRFileCache::~JKRFileCache() { - /* Nonmatching */ + removeResourceAll(); + if (mRootPath) + JKRFreeToHeap(mParentHeap, mRootPath); + if (mCurrentPath) + JKRFreeToSysHeap(mCurrentPath); + if (mVolumePath) + JKRFreeToSysHeap(mVolumePath); + + getVolumeList().remove(&mFileLoaderLink); } /* 802B737C-802B7410 .text becomeCurrent__12JKRFileCacheFPCc */ -void JKRFileCache::becomeCurrent(const char*) { - /* Nonmatching */ +bool JKRFileCache::becomeCurrent(const char* path) { + char* dvdPathName = getDvdPathName(path); + + bool result = DVDChangeDir(dvdPathName); + if (result) { + sCurrentVolume = this; + JKRHeap::sSystemHeap->free(mCurrentPath); + mCurrentPath = dvdPathName; + if (mCurrentPath[1] != '\0') { + strcat(mCurrentPath, "/"); + } + } else { + JKRHeap::sSystemHeap->free(dvdPathName); + } + + return result; } /* 802B7410-802B7564 .text getResource__12JKRFileCacheFPCc */ -void JKRFileCache::getResource(const char*) { - /* Nonmatching */ +void* JKRFileCache::getResource(const char* path) { + JUT_ASSERT(237, isMounted()); + + void* buffer = NULL; + char* name = getDvdPathName(path); + + JKRDvdFile dvdFile(name); + if (dvdFile.isAvailable()) { + CCacheBlock* cacheBlock = findCacheBlock(dvdFile.getFileID()); + if (!cacheBlock) { + u32 fileSize = dvdFile.getFileInfo()->length; + u32 alignedSize = ALIGN_NEXT(fileSize, 0x20); + buffer = JKRAllocFromHeap(mParentHeap, alignedSize, 0x20); + if (buffer) { + dvdFile.read(buffer, alignedSize, 0); + + cacheBlock = new (JKRHeap::getSystemHeap(), 0) + CCacheBlock(dvdFile.getFileID(), dvdFile.getFileInfo()->length, buffer); + mCacheBlockList.append(&cacheBlock->mCacheBlockLink); + } + } else { + cacheBlock->mReferenceCount++; + buffer = cacheBlock->mMemoryPtr; + } + } + + JKRFreeToSysHeap(name); + return buffer; } /* 802B7564-802B7630 .text getResource__12JKRFileCacheFUlPCc */ -void JKRFileCache::getResource(unsigned long, const char*) { - /* Nonmatching */ +void* JKRFileCache::getResource(unsigned long, const char* path) { + JUT_ASSERT(303, isMounted()); + + char finalPath[256]; + u32 rootLength = strlen(mRootPath); + char* filePath = finalPath + rootLength; + strcpy(finalPath, mRootPath); + + bool found = findFile(finalPath, path); + if (found) { + return getResource(filePath); + } + + return NULL; } /* 802B7630-802B7754 .text readResource__12JKRFileCacheFPvUlPCc */ -void JKRFileCache::readResource(void*, unsigned long, const char*) { - /* Nonmatching */ +u32 JKRFileCache::readResource(void* dst, u32 dstLength, const char* path) { + JUT_ASSERT(344, isMounted()); + + char* name = getDvdPathName(path); + JKRDvdFile dvdFile(name); + + u32 resourceSize = 0; + + while (true) { + if (!dvdFile.isAvailable()) { + break; + } + u32 fileSize = dvdFile.getFileInfo()->length; + resourceSize = ALIGN_NEXT(fileSize, 0x20); + dstLength = ALIGN_PREV(dstLength, 0x20); + if (resourceSize > dstLength) { + resourceSize = dstLength; + } + + CCacheBlock* cacheBlock = findCacheBlock(dvdFile.getFileID()); + if (!cacheBlock) { + dvdFile.read(dst, resourceSize, 0); + } else { + memcpy(dst, cacheBlock->mMemoryPtr, resourceSize); + } + } + + JKRFreeToSysHeap(name); + return resourceSize; } /* 802B7754-802B7830 .text readResource__12JKRFileCacheFPvUlUlPCc */ -void JKRFileCache::readResource(void*, unsigned long, unsigned long, const char*) { - /* Nonmatching */ +u32 JKRFileCache::readResource(void* dst, u32 dstLength, u32, const char* path) { + JUT_ASSERT(412, isMounted()); + + char finalPath[256]; + u32 rootLength = strlen(mRootPath); + char* filePath = finalPath + rootLength; + strcpy(finalPath, mRootPath); + + bool found = findFile(finalPath, path); + if (found) + return readResource(dst, dstLength, filePath); + + return NULL; } /* 802B7830-802B7904 .text removeResourceAll__12JKRFileCacheFv */ void JKRFileCache::removeResourceAll() { - /* Nonmatching */ + JUT_ASSERT(441, isMounted()); + + JSUListIterator iterator; + iterator = mCacheBlockList.getFirst(); + while (iterator != mCacheBlockList.getEnd()) { + JKRFreeToHeap(mParentHeap, iterator->mMemoryPtr); + mCacheBlockList.remove(&iterator.getObject()->mCacheBlockLink); + CCacheBlock* cacheBlock = (iterator++).getObject(); + delete cacheBlock; + } } /* 802B7904-802B79E4 .text removeResource__12JKRFileCacheFPv */ -void JKRFileCache::removeResource(void*) { - /* Nonmatching */ +bool JKRFileCache::removeResource(void* resource) { + JUT_ASSERT(463, isMounted()); + + CCacheBlock* cacheBlock = findCacheBlock(resource); + if (!cacheBlock) + return false; + + u32 referenceCount = cacheBlock->mReferenceCount - 1; + cacheBlock->mReferenceCount = referenceCount; + if (referenceCount == 0) { + JKRFreeToHeap(mParentHeap, resource); + mCacheBlockList.remove(&cacheBlock->mCacheBlockLink); + delete cacheBlock; + } + + return true; } /* 802B79E4-802B7AA8 .text detachResource__12JKRFileCacheFPv */ -void JKRFileCache::detachResource(void*) { - /* Nonmatching */ +bool JKRFileCache::detachResource(void* resource) { + JUT_ASSERT(490, isMounted()); + + CCacheBlock* cacheBlock = findCacheBlock(resource); + if (!cacheBlock) + return false; + + mCacheBlockList.remove(&cacheBlock->mCacheBlockLink); + delete cacheBlock; + return true; } /* 802B7AA8-802B7ADC .text getResSize__12JKRFileCacheCFPCv */ -void JKRFileCache::getResSize(const void*) const { - /* Nonmatching */ +u32 JKRFileCache::getResSize(const void* resource) const { + CCacheBlock* cacheBlock = findCacheBlock(resource); + if (cacheBlock == NULL) { + return -1; + } else { + return cacheBlock->mFileSize; + } } /* 802B7ADC-802B7B58 .text countFile__12JKRFileCacheCFPCc */ -void JKRFileCache::countFile(const char*) const { - /* Nonmatching */ +u32 JKRFileCache::countFile(const char* path) const { + DVDDirectory dir; + DVDDirectoryEntry dirEntry; + + u32 count = 0; + char* name = getDvdPathName(path); + BOOL result = DVDOpenDir(name, &dir); + if (result != 0) { + while (result = DVDReadDir(&dir, &dirEntry), result != FALSE) { + count = count + 1; + } + + DVDCloseDir(&dir); + } + + JKRFreeToSysHeap(name); + return count; } /* 802B7B58-802B7BF4 .text getFirstFile__12JKRFileCacheCFPCc */ -void JKRFileCache::getFirstFile(const char*) const { - /* Nonmatching */ +JKRFileFinder* JKRFileCache::getFirstFile(const char* path) const { + char* name = getDvdPathName(path); + JKRHeap* systemHeap = JKRHeap::getSystemHeap(); + JKRDvdFinder* finder = new (systemHeap, 0) JKRDvdFinder(name); + JKRFreeToSysHeap(name); + + if (finder->isAvailable() != true) { + delete finder; + return NULL; + } + + return finder; } /* 802B7BF4-802B7C20 .text findCacheBlock__12JKRFileCacheCFPCv */ -void JKRFileCache::findCacheBlock(const void*) const { - /* Nonmatching */ +JKRFileCache::CCacheBlock* JKRFileCache::findCacheBlock(const void* resource) const { + JSUListIterator iterator; + for (iterator = mCacheBlockList.getFirst(); iterator != mCacheBlockList.getEnd(); ++iterator) { + if (iterator->mMemoryPtr == resource) { + return iterator.getObject(); + } + } + + return NULL; } /* 802B7C20-802B7C4C .text findCacheBlock__12JKRFileCacheCFUl */ -void JKRFileCache::findCacheBlock(unsigned long) const { - /* Nonmatching */ +JKRFileCache::CCacheBlock* JKRFileCache::findCacheBlock(u32 fileID) const { + JSUListIterator iterator; + for (iterator = mCacheBlockList.getFirst(); iterator != mCacheBlockList.getEnd(); ++iterator) { + if (iterator->mFileId == fileID) { + return iterator.getObject(); + } + } + + return NULL; } /* 802B7C4C-802B7D58 .text findFile__12JKRFileCacheCFPcPCc */ -void JKRFileCache::findFile(char*, const char*) const { - /* Nonmatching */ +bool JKRFileCache::findFile(char* path, const char* fileName) const { + DVDDirectory dir; + DVDDirectoryEntry dirEntry; + + bool result = false; + u32 pathLength = strlen(path); + if (DVDOpenDir(path, &dir)) { + while (DVDReadDir(&dir, &dirEntry)) { + if (dirEntry.is_directory) { + char* endOfPath = path + pathLength; + *endOfPath = '/'; + strcpy(path + pathLength + 1, dirEntry.name); + result = findFile(path, fileName); + if (result) + break; + *endOfPath = '\0'; + } else { + result = (strcmp(fileName, dirEntry.name) == 0); + if (result) { + strcat(path, "/"); + strcat(path, fileName); + break; + } + } + } + + DVDCloseDir(&dir); + } + + return result; } /* 802B7D58-802B7E60 .text getDvdPathName__12JKRFileCacheCFPCc */ -void JKRFileCache::getDvdPathName(const char*) const { - /* Nonmatching */ +char* JKRFileCache::getDvdPathName(const char* path) const { + char* newPath; + if (path[0] == '/') { + u32 length = strlen(mRootPath) + strlen(path) + 2; + newPath = (char*)JKRAllocFromSysHeap(length, 1); + strcpy(newPath, mRootPath); + if (path[1]) { + if (mRootPath[1] == 0) { + strcat(newPath, path + 1); + } else { + strcat(newPath, path); + } + } + } else { + u32 length = strlen(mCurrentPath) + strlen(path) + 2; + newPath = (char*)JKRAllocFromSysHeap(length, 1); + strcpy(newPath, mCurrentPath); + strcat(newPath, path); + } + + convStrLower(newPath); + return newPath; } /* 802B7E60-802B7EA8 .text convStrLower__12JKRFileCacheCFPc */ -void JKRFileCache::convStrLower(char*) const { - /* Nonmatching */ +void JKRFileCache::convStrLower(char* buffer) const { + while (*buffer) { + *buffer++ = tolower(*buffer); + } } /* 802B7EA8-802B7F04 .text __ct__Q212JKRFileCache11CCacheBlockFUlUlPCv */ -JKRFileCache::CCacheBlock::CCacheBlock(unsigned long, unsigned long, const void*) { - /* Nonmatching */ -} - -/* 802B7F04-802B7F30 .text getFsResource__12JKRFileCacheFPCc */ -void JKRFileCache::getFsResource(const char*) { - /* Nonmatching */ -} - -/* 802B7F30-802B7F5C .text getNameResource__12JKRFileCacheFUlPCc */ -void JKRFileCache::getNameResource(unsigned long, const char*) { - /* Nonmatching */ -} - -/* 802B7F5C-802B7F88 .text readFsResource__12JKRFileCacheFPvUlPCc */ -void JKRFileCache::readFsResource(void*, unsigned long, const char*) { - /* Nonmatching */ -} - -/* 802B7F88-802B7FB4 .text readNameResource__12JKRFileCacheFPvUlUlPCc */ -void JKRFileCache::readNameResource(void*, unsigned long, unsigned long, const char*) { - /* Nonmatching */ +JKRFileCache::CCacheBlock::CCacheBlock(u32 fileId, u32 fileSize, const void* resource) : mCacheBlockLink(this) { + mReferenceCount = 1; + mFileId = fileId; + mFileSize = fileSize; + mMemoryPtr = (void*)resource; // todo: don't cast away const } diff --git a/src/JSystem/JKernel/JKRFileFinder.cpp b/src/JSystem/JKernel/JKRFileFinder.cpp index 6c709bcf4..2e18ebc44 100644 --- a/src/JSystem/JKernel/JKRFileFinder.cpp +++ b/src/JSystem/JKernel/JKRFileFinder.cpp @@ -4,34 +4,73 @@ // #include "JSystem/JKernel/JKRFileFinder.h" +#include "JSystem/JKernel/JKRArchive.h" #include "dolphin/types.h" /* 802B6CB8-802B6D44 .text __ct__12JKRArcFinderFP10JKRArchivell */ -JKRArcFinder::JKRArcFinder(JKRArchive*, long, long) { - /* Nonmatching */ +JKRArcFinder::JKRArcFinder(JKRArchive* archive, s32 startIndex, s32 numEntries) { + mArchive = archive; + mIsAvailable = numEntries > 0; + mStartIndex = startIndex; + mEndIndex = startIndex + numEntries - 1; + mNextIndex = mStartIndex; + findNextFile(); } /* 802B6D44-802B6DF0 .text findNextFile__12JKRArcFinderFv */ -void JKRArcFinder::findNextFile() { - /* Nonmatching */ +bool JKRArcFinder::findNextFile() { + JKRArchive::SDirEntry entry; + + if (mIsAvailable) { + mIsAvailable = !(mNextIndex > mEndIndex); + if (mIsAvailable) { + mIsAvailable = mArchive->getDirEntry(&entry, mNextIndex); + mEntryName = entry.name; + mEntryFileIndex = mNextIndex; + mEntryId = entry.id; + mEntryTypeFlags = entry.flags; + mIsFileOrDirectory = (mEntryTypeFlags >> 1) & 1; + mNextIndex++; + } + } + return mIsAvailable; } /* 802B6DF0-802B6E74 .text __ct__12JKRDvdFinderFPCc */ -JKRDvdFinder::JKRDvdFinder(const char*) { - /* Nonmatching */ +JKRDvdFinder::JKRDvdFinder(const char* directory) { + mDvdIsOpen = DVDOpenDir(directory, &mDvdDirectory); + mIsAvailable = mDvdIsOpen; + findNextFile(); } /* 802B6E74-802B6EF4 .text __dt__12JKRDvdFinderFv */ JKRDvdFinder::~JKRDvdFinder() { - /* Nonmatching */ + if (mDvdIsOpen) { + DVDCloseDir(&mDvdDirectory); + } } /* 802B6EF4-802B6F90 .text findNextFile__12JKRDvdFinderFv */ -void JKRDvdFinder::findNextFile() { - /* Nonmatching */ -} +bool JKRDvdFinder::findNextFile() { + if (mIsAvailable) { + DVDDirectoryEntry directoryEntry; + mIsAvailable = DVDReadDir(&mDvdDirectory, &directoryEntry); -/* 802B6F90-802B6FEC .text __dt__12JKRArcFinderFv */ -JKRArcFinder::~JKRArcFinder() { - /* Nonmatching */ + if (mIsAvailable) { + mIsFileOrDirectory = directoryEntry.is_directory != 0; + mEntryName = directoryEntry.name; + mEntryFileIndex = directoryEntry.entry_number; + mEntryId = 0; + + // only matches with enum + // TODO: placeholder + enum EntryTypeFlags { + EntryTypeFlags1 = 1, + EntryTypeFlags2 = 2, + }; + mEntryTypeFlags = mIsFileOrDirectory ? EntryTypeFlags2 : EntryTypeFlags1; + } + } + + return mIsAvailable; } diff --git a/src/JSystem/JKernel/JKRSolidHeap.cpp b/src/JSystem/JKernel/JKRSolidHeap.cpp index 4027b9bbd..428043dbe 100644 --- a/src/JSystem/JKernel/JKRSolidHeap.cpp +++ b/src/JSystem/JKernel/JKRSolidHeap.cpp @@ -4,114 +4,269 @@ // #include "JSystem/JKernel/JKRSolidHeap.h" -#include "dolphin/types.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "JSystem/JUtility/JUTConsole.h" +#include "global.h" /* 802B3290-802B333C .text create__12JKRSolidHeapFUlP7JKRHeapb */ -void JKRSolidHeap::create(unsigned long, JKRHeap*, bool) { - /* Nonmatching */ +JKRSolidHeap* JKRSolidHeap::create(u32 size, JKRHeap* heap, bool useErrorHandler) { + if (!heap) { + heap = getRootHeap(); + } + + if (size == 0xffffffff) { + size = heap->getMaxAllocatableSize(0x10); + } + + u32 alignedSize = ALIGN_PREV(size, 0x10); + u32 solidHeapSize = ALIGN_NEXT(sizeof(JKRSolidHeap), 0x10); + if (alignedSize < solidHeapSize) + return NULL; + + JKRSolidHeap* solidHeap = (JKRSolidHeap*)JKRAllocFromHeap(heap, alignedSize, 0x10); + void* dataPtr = (u8*)solidHeap + solidHeapSize; + if (!solidHeap) + return NULL; + + solidHeap = + new (solidHeap) JKRSolidHeap(dataPtr, alignedSize - solidHeapSize, heap, useErrorHandler); + return solidHeap; } /* 802B333C-802B339C .text do_destroy__12JKRSolidHeapFv */ void JKRSolidHeap::do_destroy() { - /* Nonmatching */ + JKRHeap* parent = getParent(); + if (parent) { + this->~JKRSolidHeap(); + JKRFreeToHeap(parent, this); + } } /* 802B339C-802B33F8 .text __ct__12JKRSolidHeapFPvUlP7JKRHeapb */ -JKRSolidHeap::JKRSolidHeap(void*, unsigned long, JKRHeap*, bool) { - /* Nonmatching */ +JKRSolidHeap::JKRSolidHeap(void* start, u32 size, JKRHeap* parent, bool useErrorHandler) : JKRHeap(start, size, parent, useErrorHandler) { + mFreeSize = mSize; + mSolidHead = (u8*)mStart; + mSolidTail = (u8*)mEnd; + field_0x78 = NULL; } /* 802B33F8-802B3460 .text __dt__12JKRSolidHeapFv */ JKRSolidHeap::~JKRSolidHeap() { - /* Nonmatching */ + dispose(); } /* 802B3460-802B351C .text adjustSize__12JKRSolidHeapFv */ -void JKRSolidHeap::adjustSize() { - /* Nonmatching */ +s32 JKRSolidHeap::adjustSize() { + JKRHeap* parent = getParent(); + if (parent) { + lock(); + u32 thisSize = (u32)mStart - (u32)this; + u32 newSize = ALIGN_NEXT(mSolidHead - mStart, 0x20); + if (parent->resize(this, thisSize + newSize) != -1) { + mFreeSize = 0; + mSize = newSize; + mEnd = mStart + mSize; + mSolidHead = mEnd; + mSolidTail = mEnd; + } + + unlock(); + + return thisSize + newSize; + } + + return -1; } /* 802B351C-802B35C4 .text do_alloc__12JKRSolidHeapFUli */ -void JKRSolidHeap::do_alloc(unsigned long, int) { - /* Nonmatching */ +void* JKRSolidHeap::do_alloc(u32 size, int alignment) { + lock(); + + if (size < 4) { + size = 4; + } + + void* ptr; + if (alignment >= 0) { + ptr = allocFromHead(size, alignment < 4 ? 4 : alignment); + } else { + if (-alignment < 4) { + alignment = 4; + } else { + alignment = -alignment; + } + + ptr = allocFromTail(size, alignment); + } + + unlock(); + return ptr; } /* 802B35C4-802B368C .text allocFromHead__12JKRSolidHeapFUli */ -void JKRSolidHeap::allocFromHead(unsigned long, int) { - /* Nonmatching */ +void* JKRSolidHeap::allocFromHead(u32 size, int alignment) { + size = ALIGN_NEXT(size, 0x4); + void* ptr = NULL; + u32 alignedStart = (alignment - 1 + (u32)mSolidHead) & ~(alignment - 1); + u32 offset = alignedStart - (u32)mSolidHead; + u32 totalSize = size + offset; + if (totalSize <= mFreeSize) { + ptr = (void*)alignedStart; + mSolidHead += totalSize; + mFreeSize -= totalSize; + } else { + JUTWarningConsole_f("allocFromHead: cannot alloc memory (0x%x byte).\n", totalSize); + if (getErrorFlag() == true) { + callErrorHandler(this, size, alignment); + } + } + + return ptr; } /* 802B368C-802B3750 .text allocFromTail__12JKRSolidHeapFUli */ -void JKRSolidHeap::allocFromTail(unsigned long, int) { - /* Nonmatching */ +void* JKRSolidHeap::allocFromTail(u32 size, int alignment) { + size = ALIGN_NEXT(size, 4); + void* ptr = NULL; + u32 alignedStart = ALIGN_PREV((u32)mSolidTail - size, alignment); + u32 totalSize = (u32)mSolidTail - (u32)alignedStart; + if (totalSize <= mFreeSize) { + ptr = (void*)alignedStart; + mSolidTail -= totalSize; + mFreeSize -= totalSize; + } else { + JUTWarningConsole_f("allocFromTail: cannot alloc memory (0x%x byte).\n", totalSize); + if (getErrorFlag() == true) { + callErrorHandler(this, size, alignment); + } + } + return ptr; } /* 802B3750-802B3780 .text do_free__12JKRSolidHeapFPv */ -void JKRSolidHeap::do_free(void*) { - /* Nonmatching */ +void JKRSolidHeap::do_free(void* ptr) { + JUTWarningConsole_f("free: cannot free memory block (%08x)\n", ptr); } /* 802B3780-802B37E0 .text do_freeAll__12JKRSolidHeapFv */ void JKRSolidHeap::do_freeAll() { - /* Nonmatching */ + lock(); + + this->JKRHeap::callAllDisposer(); + mFreeSize = mSize; + mSolidHead = (u8*)mStart; + mSolidTail = (u8*)mEnd; + field_0x78 = NULL; + + unlock(); } /* 802B37E0-802B386C .text do_freeTail__12JKRSolidHeapFv */ void JKRSolidHeap::do_freeTail() { - /* Nonmatching */ + lock(); + + if (mSolidTail != mEnd) { + dispose(mSolidTail, mEnd); + } + + this->mFreeSize = ((u32)mEnd - (u32)mSolidTail + mFreeSize); + this->mSolidTail = mEnd; + + JKRSolidHeap::Unknown* unknown = field_0x78; + while (unknown) { + unknown->field_0xc = mEnd; + unknown = unknown->mNext; + } + + unlock(); } /* 802B386C-802B38A0 .text do_resize__12JKRSolidHeapFPvUl */ -void JKRSolidHeap::do_resize(void*, unsigned long) { - /* Nonmatching */ +s32 JKRSolidHeap::do_resize(void* ptr, u32 newSize) { + JUTWarningConsole_f("resize: cannot resize memory block (%08x: %d)\n", ptr, newSize); + return -1; } /* 802B38A0-802B38D4 .text do_getSize__12JKRSolidHeapFPv */ -void JKRSolidHeap::do_getSize(void*) { - /* Nonmatching */ +s32 JKRSolidHeap::do_getSize(void* ptr) { + JUTWarningConsole_f("getSize: cannot get memory block size (%08x)\n", ptr); + return -1; } /* 802B38D4-802B3964 .text check__12JKRSolidHeapFv */ -void JKRSolidHeap::check() { - /* Nonmatching */ +bool JKRSolidHeap::check() { + lock(); + + bool result = true; + u32 calculatedSize = + ((u32)mSolidHead - (u32)mStart) + mFreeSize + ((u32)mEnd - (u32)mSolidTail); + u32 availableSize = mSize; + if (calculatedSize != availableSize) { + result = false; + JUTWarningConsole_f("check: bad total memory block size (%08X, %08X)\n", availableSize, + calculatedSize); + } + + unlock(); + return result; } /* 802B3964-802B3968 .text do_freeFill__12JKRSolidHeapFv */ -void JKRSolidHeap::do_freeFill() { - /* Nonmatching */ -} +void JKRSolidHeap::do_freeFill() {} /* 802B3968-802B3A68 .text dump__12JKRSolidHeapFv */ -void JKRSolidHeap::dump() { - /* Nonmatching */ +bool JKRSolidHeap::dump() { + bool result = check(); + + lock(); + u32 headSize = ((u32)mSolidHead - (u32)mStart); + u32 tailSize = ((u32)mEnd - (u32)mSolidTail); + s32 htSize = headSize + tailSize; + JUTReportConsole_f("head %08x: %08x\n", mStart, headSize); + JUTReportConsole_f("tail %08x: %08x\n", mSolidTail, ((u32)mEnd - (u32)mSolidTail)); + + u32 totalSize = mSize; + float percentage = (float)htSize / (float)totalSize * 100.0f; + JUTReportConsole_f("%d / %d bytes (%6.2f%%) used\n", htSize, totalSize, percentage); + unlock(); + + return result; } /* 802B3A68-802B3B4C .text state_register__12JKRSolidHeapCFPQ27JKRHeap6TStateUl */ -void JKRSolidHeap::state_register(JKRHeap::TState*, unsigned long) const { - /* Nonmatching */ +void JKRSolidHeap::state_register(JKRHeap::TState* p, u32 id) const { +#if VERSION == VERSION_JPN + JUT_ASSERT(610, p != 0); + JUT_ASSERT(611, p->getHeap() == this); +#else + JUT_ASSERT(607, p != 0); + JUT_ASSERT(608, p->getHeap() == this); +#endif + + getState_(p); + setState_u32ID_(p, id); + setState_uUsedSize_(p, getUsedSize((JKRSolidHeap*)this)); + u32 r29 = (u32)mSolidHead; + r29 += (u32)mSolidTail * 3; + setState_u32CheckCode_(p, r29); } /* 802B3B4C-802B3BF4 .text state_compare__12JKRSolidHeapCFRCQ27JKRHeap6TStateRCQ27JKRHeap6TState */ -void JKRSolidHeap::state_compare(const JKRHeap::TState&, const JKRHeap::TState&) const { - /* Nonmatching */ -} +bool JKRSolidHeap::state_compare(const JKRHeap::TState& r1, const JKRHeap::TState& r2) const { +#if VERSION == VERSION_JPN + JUT_ASSERT(638, r1.getHeap() == r2.getHeap()); +#else + JUT_ASSERT(635, r1.getHeap() == r2.getHeap()); +#endif -/* 802B3BF4-802B3C00 .text getHeapType__12JKRSolidHeapFv */ -void JKRSolidHeap::getHeapType() { - /* Nonmatching */ -} + bool result = true; + if (r1.getCheckCode() != r2.getCheckCode()) { + result = false; + } -/* 802B3C00-802B3C08 .text do_getFreeSize__12JKRSolidHeapFv */ -void JKRSolidHeap::do_getFreeSize() { - /* Nonmatching */ -} + if (r1.getUsedSize() != r2.getUsedSize()) { + result = false; + } -/* 802B3C08-802B3C10 .text do_getMaxFreeBlock__12JKRSolidHeapFv */ -void JKRSolidHeap::do_getMaxFreeBlock() { - /* Nonmatching */ -} - -/* 802B3C10-802B3C30 .text do_getTotalFreeSize__12JKRSolidHeapFv */ -void JKRSolidHeap::do_getTotalFreeSize() { - /* Nonmatching */ + return result; } diff --git a/src/JSystem/JKernel/JKRStdHeap.cpp b/src/JSystem/JKernel/JKRStdHeap.cpp index c3f1f3735..015167447 100644 --- a/src/JSystem/JKernel/JKRStdHeap.cpp +++ b/src/JSystem/JKernel/JKRStdHeap.cpp @@ -4,99 +4,147 @@ // #include "JSystem/JKernel/JKRStdHeap.h" -#include "dolphin/types.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "JSystem/JUtility/JUTConsole.h" +#include "global.h" /* 802B0F34-802B0FE0 .text create__10JKRStdHeapFUlP7JKRHeapb */ -void JKRStdHeap::create(unsigned long, JKRHeap*, bool) { +JKRStdHeap* JKRStdHeap::create(u32 size, JKRHeap* parent, bool errorFlag) { /* Nonmatching */ + if (!parent) { + parent = sRootHeap; + } + if (size == -1) { + size = parent->getMaxAllocatableSize(0x20); + } + + u32 alignedSize = ALIGN_PREV(size, 0x20); + if (alignedSize < 0xC0) { + return NULL; + } + u8* memory = (u8*)JKRAllocFromHeap(parent, alignedSize, 0x20); + u32 stdHeapSize = ALIGN_NEXT(sizeof(JKRStdHeap), 0x20); + if (!memory) { + return NULL; + } + u8* dataPtr = (memory + stdHeapSize); + JKRStdHeap* newHeap = new(memory) JKRStdHeap(dataPtr, alignedSize - stdHeapSize, parent, errorFlag); + return newHeap; } /* 802B0FE0-802B1040 .text do_destroy__10JKRStdHeapFv */ void JKRStdHeap::do_destroy() { - /* Nonmatching */ + JKRHeap* heap = mChildTree.getParent()->getObject(); + if (heap) { + this->~JKRStdHeap(); + free(this, heap); + } } /* 802B1040-802B108C .text __ct__10JKRStdHeapFPvUlP7JKRHeapb */ -JKRStdHeap::JKRStdHeap(void*, unsigned long, JKRHeap*, bool) { - /* Nonmatching */ +JKRStdHeap::JKRStdHeap(void* data, u32 size, JKRHeap* parent, bool errorFlag) : JKRHeap(data, size, parent, errorFlag) { + mHeapHandle = OSCreateHeap(mStart, mEnd); } /* 802B108C-802B1104 .text __dt__10JKRStdHeapFv */ JKRStdHeap::~JKRStdHeap() { - /* Nonmatching */ + dispose(); + if (mHeapHandle != -1) { + OSDestroyHeap(mHeapHandle); + } +} + +static void dummy() { + OSReport("JKRStdHeap.cpp"); + OSReport("allocFixed from %x to %x in heap %x"); + OSReport("allocFixed: cannot alloc memory (from %x to %x).\n"); } /* 802B1104-802B11A4 .text do_alloc__10JKRStdHeapFUli */ -void JKRStdHeap::do_alloc(unsigned long, int) { +void* JKRStdHeap::do_alloc(u32 size, int alignment) { + if (mHeapHandle == -1) { + return NULL; + } + void* ptr = OSAllocFromHeap(mHeapHandle, size); + if (!ptr) { + JUTWarningConsole_f("alloc: cannot alloc memory (0x%x byte).\n", size); + if (mErrorFlag == true && mErrorHandler) { + mErrorHandler(this, size, alignment); + } + } + return ptr; /* Nonmatching */ } /* 802B11A4-802B1228 .text do_free__10JKRStdHeapFPv */ -void JKRStdHeap::do_free(void*) { +void JKRStdHeap::do_free(void* ptr) { + if (mHeapHandle != -1) { + if (mStart <= ptr && ptr <= mEnd) { + OSFreeToHeap(mHeapHandle, ptr); + } else { + JUT_WARN(279, "free: memblock %x not in heap %x", ptr, this); + } + } /* Nonmatching */ } /* 802B1228-802B1278 .text do_freeAll__10JKRStdHeapFv */ void JKRStdHeap::do_freeAll() { /* Nonmatching */ + if (mHeapHandle == -1) { + return; + } + JKRHeap::callAllDisposer(); + OSDestroyHeap(mHeapHandle); + mHeapHandle = OSCreateHeap(mStart, mEnd); } /* 802B1278-802B12A4 .text do_freeTail__10JKRStdHeapFv */ void JKRStdHeap::do_freeTail() { - /* Nonmatching */ + JUTWarningConsole("freeTail: freeTail() is not work\n"); } /* 802B12A4-802B12D8 .text do_resize__10JKRStdHeapFPvUl */ -void JKRStdHeap::do_resize(void*, unsigned long) { - /* Nonmatching */ +s32 JKRStdHeap::do_resize(void*, u32) { + JUTWarningConsole_f("resize: cannot resize memory block (%08x: %d)\n"); + return -1; } /* 802B12D8-802B1308 .text do_getFreeSize__10JKRStdHeapFv */ -void JKRStdHeap::do_getFreeSize() { - /* Nonmatching */ +s32 JKRStdHeap::do_getFreeSize() { + JUTWarningConsole("getFreeSize: cannot get free size\n"); + return -1; } /* 802B1308-802B1338 .text do_getMaxFreeBlock__10JKRStdHeapFv */ -void JKRStdHeap::do_getMaxFreeBlock() { - /* Nonmatching */ +void* JKRStdHeap::do_getMaxFreeBlock() { + JUTWarningConsole("getFreeSize: cannot get free block"); + return NULL; } /* 802B1338-802B13F0 .text state_register__10JKRStdHeapCFPQ27JKRHeap6TStateUl */ -void JKRStdHeap::state_register(JKRHeap::TState*, unsigned long) const { - /* Nonmatching */ +void JKRStdHeap::state_register(JKRHeap::TState* p, u32 id) const { + JUT_ASSERT(370, p != 0); + JUT_ASSERT(371, p->getHeap() == this); + setState_u32ID_(p, id); + setState_uUsedSize_(p, 0); + setState_u32CheckCode_(p, 0); } /* 802B13F0-802B1490 .text state_compare__10JKRStdHeapCFRCQ27JKRHeap6TStateRCQ27JKRHeap6TState */ -void JKRStdHeap::state_compare(const JKRHeap::TState&, const JKRHeap::TState&) const { - /* Nonmatching */ +bool JKRStdHeap::state_compare(const JKRHeap::TState& r1, const JKRHeap::TState& r2) const { + JUT_ASSERT(394, r1.getHeap() == r2.getHeap()); + bool result = true; + if (r1.mCheckCode != r2.mCheckCode) { + result = false; + } + + if (r1.mUsedSize != r2.mUsedSize) { + result = false; + } + + return result; } /* 802B1490-802B1494 .text do_freeFill__10JKRStdHeapFv */ -void JKRStdHeap::do_freeFill() { - /* Nonmatching */ -} - -/* 802B1494-802B14A0 .text getHeapType__10JKRStdHeapFv */ -void JKRStdHeap::getHeapType() { - /* Nonmatching */ -} - -/* 802B14A0-802B14D0 .text check__10JKRStdHeapFv */ -void JKRStdHeap::check() { - /* Nonmatching */ -} - -/* 802B14D0-802B1514 .text dump__10JKRStdHeapFv */ -void JKRStdHeap::dump() { - /* Nonmatching */ -} - -/* 802B1514-802B1538 .text do_getSize__10JKRStdHeapFPv */ -void JKRStdHeap::do_getSize(void*) { - /* Nonmatching */ -} - -/* 802B1538-802B1558 .text do_getTotalFreeSize__10JKRStdHeapFv */ -void JKRStdHeap::do_getTotalFreeSize() { - /* Nonmatching */ -} +void JKRStdHeap::do_freeFill() {}