From 80ef14e4801738e65e497010635a311123d64a9d Mon Sep 17 00:00:00 2001 From: Cuyler36 Date: Tue, 7 Nov 2023 23:34:10 -0500 Subject: [PATCH] Add & Link JKernel (#142) * match and link JKRAram.cpp * match and link JKRExpHeap * match and link JKRAramStream.cpp * match and link JKRFileLoader.cpp * match and link JKRFileFinder.cpp * JKernel Dump * match and link JKRAramArchive.cpp * match and link JKRDvdArchive.cpp * match and link JKRCompArchive.cpp * match but not link JKRDvdAramRipper * small refactors * match and link JKRThread.cpp * fix and link JKRDvdAramStream.cpp * Formatting fixes --------- Co-authored-by: SwareJonge --- config/dol_slices.yml | 74 +- include/JSystem/JKernel/JKRAram.h | 208 +++- include/JSystem/JKernel/JKRArchive.h | 342 +++++ include/JSystem/JKernel/JKRDecomp.h | 13 + include/JSystem/JKernel/JKRDisposer.h | 4 +- include/JSystem/JKernel/JKRDvdAramRipper.h | 62 + include/JSystem/JKernel/JKRDvdFile.h | 31 +- include/JSystem/JKernel/JKRDvdRipper.h | 16 +- include/JSystem/JKernel/JKREnum.h | 12 +- include/JSystem/JKernel/JKRExpHeap.h | 107 ++ include/JSystem/JKernel/JKRFile.h | 5 +- include/JSystem/JKernel/JKRFileFinder.h | 78 ++ include/JSystem/JKernel/JKRFileLoader.h | 62 + include/JSystem/JKernel/JKRHeap.h | 187 +-- include/JSystem/JKernel/JKRThread.h | 122 +- include/JSystem/JSupport.h | 9 + include/JSystem/JSupport/JSUFileInputStream.h | 1 - include/JSystem/JUtility/JUTConsole.h | 28 + include/MSL_C/ctype.h | 34 + include/MSL_C/ctype_api.h | 35 + include/MSL_C/locale.h | 130 ++ include/MSL_C/rand.h | 4 +- include/types.h | 5 + src/JSystem/JKernel/JKRAram.cpp | 509 ++++++++ src/JSystem/JKernel/JKRAramArchive.cpp | 311 +++++ src/JSystem/JKernel/JKRAramBlock.cpp | 23 +- src/JSystem/JKernel/JKRAramHeap.cpp | 37 +- src/JSystem/JKernel/JKRAramPiece.cpp | 42 +- src/JSystem/JKernel/JKRAramStream.cpp | 215 +++- src/JSystem/JKernel/JKRArchivePri.cpp | 242 ++++ src/JSystem/JKernel/JKRArchivePub.cpp | 340 +++++ src/JSystem/JKernel/JKRCompArchive.cpp | 342 +++++ src/JSystem/JKernel/JKRDecomp.cpp | 306 +++-- src/JSystem/JKernel/JKRDisposer.cpp | 1 + src/JSystem/JKernel/JKRDvdAramRipper.cpp | 402 ++++++ src/JSystem/JKernel/JKRDvdArchive.cpp | 321 +++++ src/JSystem/JKernel/JKRDvdFile.cpp | 44 +- src/JSystem/JKernel/JKRDvdRipper.cpp | 262 ++-- src/JSystem/JKernel/JKRExpHeap.cpp | 1099 +++++++++++++++++ src/JSystem/JKernel/JKRFile.cpp | 6 +- src/JSystem/JKernel/JKRFileFinder.cpp | 63 + src/JSystem/JKernel/JKRFileLoader.cpp | 165 +++ src/JSystem/JKernel/JKRHeap.cpp | 146 +-- src/JSystem/JKernel/JKRMemArchive.cpp | 247 ++++ src/JSystem/JKernel/JKRThread.cpp | 83 +- src/JSystem/JKernel/JKRThread2.cpp | 3 - src/ctors.s | 1 + 47 files changed, 6183 insertions(+), 596 deletions(-) create mode 100644 include/JSystem/JKernel/JKRArchive.h create mode 100644 include/JSystem/JKernel/JKRDvdAramRipper.h create mode 100644 include/JSystem/JKernel/JKRExpHeap.h create mode 100644 include/JSystem/JKernel/JKRFileFinder.h create mode 100644 include/JSystem/JKernel/JKRFileLoader.h create mode 100644 include/JSystem/JSupport.h create mode 100644 include/JSystem/JUtility/JUTConsole.h create mode 100644 include/MSL_C/ctype.h create mode 100644 include/MSL_C/ctype_api.h create mode 100644 include/MSL_C/locale.h create mode 100644 src/JSystem/JKernel/JKRAram.cpp create mode 100644 src/JSystem/JKernel/JKRAramArchive.cpp create mode 100644 src/JSystem/JKernel/JKRArchivePri.cpp create mode 100644 src/JSystem/JKernel/JKRArchivePub.cpp create mode 100644 src/JSystem/JKernel/JKRCompArchive.cpp create mode 100644 src/JSystem/JKernel/JKRDvdAramRipper.cpp create mode 100644 src/JSystem/JKernel/JKRDvdArchive.cpp create mode 100644 src/JSystem/JKernel/JKRExpHeap.cpp create mode 100644 src/JSystem/JKernel/JKRFileFinder.cpp create mode 100644 src/JSystem/JKernel/JKRFileLoader.cpp create mode 100644 src/JSystem/JKernel/JKRMemArchive.cpp delete mode 100644 src/JSystem/JKernel/JKRThread2.cpp create mode 100644 src/ctors.s diff --git a/config/dol_slices.yml b/config/dol_slices.yml index be72edd8..8b2b2730 100644 --- a/config/dol_slices.yml +++ b/config/dol_slices.yml @@ -1,3 +1,5 @@ +ctors.s: + .ctors: [0x800a97b4, 0x800a97c0] # remove trailing 0s from ctor area #dolphin/os/__start.c: # .init: [0x80003100, 0x80003354] dolphin/__ppc_eabi_init.cpp: @@ -114,18 +116,29 @@ JSystem/JKernel/JKRHeap.cpp: .data: [0x800ddf20, 0x800ddf98] .sdata: [0x80217e58, 0x80217e80] .sbss: [0x802186d8, 0x80218700] +JSystem/JKernel/JKRExpHeap.cpp: + .text: [0x80064028, 0x80065aa0] + .data: [0x800ddf98, 0x800de3a8] + .sdata: [0x80217e80, 0x80217ec0] + .sbss: [0x80218700, 0x80218720] + .sdata2: [0x80219278, 0x80219288] JSystem/JKernel/JKRDisposer.cpp: .text: [0x80065aa0, 0x80065b8c] .data: [0x800de3a8, 0x800de3c0] .sdata: [0x80217ec0, 0x80217ec8] -#JSystem/JKernel/JKRThread.cpp: # JKRThread linkage disabled until we can resolve the order of RTTI strings in .data -# .text: [0x80065b8c, 0x80065ef0] -# .ctors: [0x800a978c, 0x800a9790] -# .data: [0x800de3c0, 0x800de3f8] -# .bss: [0x80207008, 0x80207020] -# .sdata: [0x80217ec8, 0x80217ed8] -JSystem/JKernel/JKRThread2.cpp: # This exists to fix ordering. It is a hack. AC was likely compiled with CW GC 1.3. - .text: [0x80065ef0, 0x80065ef8] +JSystem/JKernel/JKRThread.cpp: + .text: [0x80065b8c, 0x80065ef0] + .ctors: [0x800a978c, 0x800a9790] + .data: [0x800de3c0, 0x800de3f8] + .bss: [0x80207008, 0x80207020] + .sdata: [0x80217ec8, 0x80217ed8] +JSystem/JKernel/JKRAram.cpp: + .text: [0x80065ef8, 0x80066e84] + .ctors: [0x800a9790, 0x800a9794] + .data: [0x800de3f8, 0x800de4c0] + .bss: [0x80207020, 0x80207038] + .sdata: [0x80217ed8, 0x80217ef8] + .sbss: [0x80218720, 0x80218758] JSystem/JKernel/JKRAramHeap.cpp: .text: [0x80066e84, 0x80067258] .ctors: [0x800a9794, 0x800a9798] @@ -142,6 +155,45 @@ JSystem/JKernel/JKRAramPiece.cpp: .data: [0x800de510, 0x800de568] .bss: [0x80207050, 0x80207080] .sdata: [0x80217f10, 0x80217f18] +JSystem/JKernel/JKRAramStream.cpp: + .text: [0x80067a88, 0x80067ff4] + .data: [0x800de568, 0x800de608] + .sdata: [0x80217f18, 0x80217f38] + .sbss: [0x80218758, 0x80218768] +JSystem/JKernel/JKRFileLoader.cpp: + .text: [0x80067ff4, 0x800685b0] + .ctors: [0x800a979c, 0x800a97a0] + .data: [0x800de608, 0x800de670] + .bss: [0x80207080, 0x80207098] + .sdata: [0x80217f38, 0x80217f50] + .sbss: [0x80218768, 0x80218770] +JSystem/JKernel/JKRFileFinder.cpp: + .text: [0x800685b0, 0x80068744] + .data: [0x800de670, 0x800de6b0] + .sdata: [0x80217f50, 0x80217f60] +JSystem/JKernel/JKRArchivePub.cpp: + .text: [0x80068744, 0x80068ed0] + .data: [0x800de6b0, 0x800de740] + .sdata: [0x80217f60, 0x80217f78] +JSystem/JKernel/JKRArchivePri.cpp: + .text: [0x80068ed0, 0x80069530] + .sbss: [0x80218770, 0x80218778] +JSystem/JKernel/JKRMemArchive.cpp: + .text: [0x80069530, 0x80069a28] + .data: [0x800de740, 0x800de828] + .sdata: [0x80217f78, 0x80217f98] +JSystem/JKernel/JKRAramArchive.cpp: + .text: [0x80069a28, 0x8006a4fc] + .data: [0x800de828, 0x800de938] + .sdata: [0x80217f98, 0x80217fc8] +JSystem/JKernel/JKRDvdArchive.cpp: + .text: [0x8006a4fc, 0x8006add0] + .data: [0x800de938, 0x800dea70] + .sdata: [0x80217fc8, 0x80217fe8] +JSystem/JKernel/JKRCompArchive.cpp: + .text: [0x8006add0, 0x8006b8a4] + .data: [0x800dea70, 0x800deba8] + .sdata: [0x80217fe8, 0x80218008] JSystem/JKernel/JKRDvdFile.cpp: .text: [0x8006b8a4, 0x8006be0c] .ctors: [0x800a97a0, 0x800a97a4] @@ -155,6 +207,12 @@ JSystem/JKernel/JKRDvdRipper.cpp: .bss: [0x802070b0, 0x802070c8] .sdata: [0x80218028, 0x80218030] .sbss: [0x80218778, 0x802187a8] +JSystem/JKernel/JKRDvdAramRipper.cpp: + .text: [0x8006c8fc, 0x8006d608] + .ctors: [0x800a97a8, 0x800a97ac] + .bss: [0x802070c8, 0x802070e0] + .sdata: [0x80218030, 0x80218038] + .sbss: [0x802187a8, 0x802187e8] JSystem/JKernel/JKRDecomp.cpp: .text: [0x8006d608, 0x8006dd58] .data: [0x800dec90, 0x800ded18] diff --git a/include/JSystem/JKernel/JKRAram.h b/include/JSystem/JKernel/JKRAram.h index d6e0cbd6..9fbda659 100644 --- a/include/JSystem/JKernel/JKRAram.h +++ b/include/JSystem/JKernel/JKRAram.h @@ -5,9 +5,11 @@ #include "dolphin/ar.h" #include "dolphin/os/OSMessage.h" #include "JSystem/JKernel/JKRDisposer.h" +#include "JSystem/JKernel/JKREnum.h" #include "JSystem/JKernel/JKRHeap.h" #include "JSystem/JKernel/JKRThread.h" #include "JSystem/JSupport/JSUList.h" +#include "JSystem/JSupport/JSUStream.h" #define ARAM_GROUP_ID_ALL 0 #define ARAM_GROUP_ID_DEFAULT 0xFF @@ -22,7 +24,9 @@ class JKRAramHeap; class JKRDecompCommand; class JKRAMCommand; -class JKRAramBlock { +class JKRAramBlock +{ +public: JKRAramBlock(u32 address, u32 size, u32 freeSize, u8 groupID, bool tempMemory); virtual ~JKRAramBlock(); @@ -46,33 +50,11 @@ class JKRAramBlock { friend class JKRAramHeap; }; -class JKRAram : public JKRThread { +class JKRAramHeap : public JKRDisposer +{ public: - JKRAram(u32, u32, s32); - - virtual ~JKRAram(); - virtual void* run(); - - static JKRAram* sAramObject; - static const OSMessageQueue sMessageQueue; - static JSUList sAramCommandList; - static u32 sSZSBufferSize; - static OSMessage sMessageBuffer[ARAM_MESGBUF_COUNT]; - -private: - u32 mAudioMemoryPtr; - u32 mAudioMemorySize; - u32 mGraphMemoryPtr; - u32 mGraphMemorySize; - u32 mAramMemoryPtr; - u32 mAramMemorySize; - JKRAramHeap* mAramHeap; - u32 mBlockLength; - u8 _9C[4]; -}; - -class JKRAramHeap : public JKRDisposer { - enum EAllocMode { + enum EAllocMode + { Head = 0, Tail = 1 }; @@ -108,7 +90,77 @@ class JKRAramHeap : public JKRDisposer { friend class JKRAramBlock; }; -class JKRAMCommand : public ARQRequest { +class JKRAram : public JKRThread +{ +public: + JKRAram(u32, u32, long); + + virtual ~JKRAram(); // _08 + virtual void* run(); // _0C + + static bool checkOkAddress(u8* addr, u32 size, JKRAramBlock* block, u32 param_4); + static void changeGroupIdIfNeed(u8* data, int groupId); + + static JKRAram* create(u32, u32, long, long, long); + static JKRAramBlock* mainRamToAram(u8*, u32, u32, JKRExpandSwitch, u32, JKRHeap*, int); + static JKRAramBlock* mainRamToAram(u8*, JKRAramBlock* block, 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*); + + void aramSync(JKRAMCommand*, int); + + u32 getAudioMemory() const + { + return mAudioMemoryPtr; + } + + u32 getAudioMemSize() const + { + return mAudioMemorySize; + } + + static u32 getSZSBufferSize() + { + return sSZSBufferSize; + } + + static JKRAramHeap* getAramHeap() + { + return sAramObject->mAramHeap; + } + + static JKRAram* getManager() + { + return sAramObject; + } + + static u8 decideAramGroupId(int id) + { + if (id < 0) + return getAramHeap()->getCurrentGroupID(); + else + return id; + } + + static u32 sSZSBufferSize; + + static JKRAram* sAramObject; + static OSMessage sMessageBuffer[4]; + static OSMessageQueue sMessageQueue; + static JSUList sAramCommandList; + + u32 mAudioMemoryPtr; // _7C + u32 mAudioMemorySize; // _80 + u32 mGraphMemoryPtr; // _84 + u32 mGraphMemorySize; // _88 + u32 mUserMemoryPtr; // _8C + u32 mUserMemorySize; // _90 + JKRAramHeap* mAramHeap; // _94 + u32 mStackArray[3]; // _98 +}; + +class JKRAMCommand : public ARQRequest +{ public: typedef void (*AMCommandCallback)(u32); @@ -134,9 +186,11 @@ public: void* _94; }; -class JKRAramCommand { +class JKRAramCommand +{ public: - inline void setting(BOOL active, void* arg) { + inline void setting(BOOL active, void* arg) + { this->mActive = active; this->mArg = arg; } @@ -145,7 +199,8 @@ public: void* mArg; }; -class JKRAramPiece { +class JKRAramPiece +{ public: static JKRAMCommand* prepareCommand(int direction, u32 source, u32 destination, u32 length, JKRAramBlock* aramBlock, JKRAMCommand::AMCommandCallback callback); static void sendCommand(JKRAMCommand* cmd); @@ -163,12 +218,97 @@ private: static void unlock() { OSUnlockMutex(&mMutex); } }; -inline bool JKRAramPcs(int direction, u32 source, u32 destination, u32 length, JKRAramBlock* block) { +class JKRAramStreamCommand +{ +public: + enum ECommandType + { + ECT_UNK = 0, + ECT_READ = 1, + ECT_WRITE = 2, + }; + + JKRAramStreamCommand(); + + ECommandType type; // _00 + u32 mAddress; // _04 + u32 mSize; // _08 + u32 _0C; // _0C + JSUFileInputStream* mStream; // _10 + u32 mOffset; // _14 + u8* mTransferBuffer; // _18 + u32 mTransferBufferSize; // _1C + JKRHeap* mHeap; // _20 + bool mAllocatedTransferBuffer; // _24 + u32 _28; // _28 + OSMessageQueue mMessageQueue; // _2C + void* mMessage; // _4C + u32 _50; // _50 + u32 _54; // _54 +}; + +class JKRAramStream : public JKRThread +{ +public: + JKRAramStream(long); + + virtual ~JKRAramStream(); // _08 + virtual void* run(); // _0C + + static JKRAramStream* create(s32); + + static u32 readFromAram(); + static s32 writeToAram(JKRAramStreamCommand*); + static JKRAramStreamCommand* write_StreamToAram_Async(JSUFileInputStream*, JKRAramBlock*, u32, u32); + static JKRAramStreamCommand* write_StreamToAram_Async(JSUFileInputStream*, u32, u32, u32); + static JKRAramStreamCommand* sync(JKRAramStreamCommand*, BOOL); + static void setTransBuffer(u8*, u32, JKRHeap*); + + static JKRAramStream* sAramStreamObject; + static OSMessage sMessageBuffer[4]; + static OSMessageQueue sMessageQueue; + + static u8* transBuffer; + static JKRHeap* transHeap; + static u32 transSize; + + // _00 = VTBL + // _00-_7C = JKRThread +}; + +inline JKRAramBlock* JKRAllocFromAram(u32 size, JKRAramHeap::EAllocMode allocMode) +{ + return JKRAram::getAramHeap()->alloc(size, allocMode); +} + +inline void JKRFreeToAram(JKRAramBlock* block) +{ + JKRAram::getAramHeap()->free(block); +} + +inline u8* JKRAramToMainRam(u32 address, u8* buf, u32 bufSize, JKRExpandSwitch expandSwitch, u32 p5, JKRHeap* heap, int id, u32* pSize) +{ + JKRAram::aramToMainRam(address, buf, bufSize, expandSwitch, p5, heap, id, pSize); +} + +inline JKRAramBlock* JKRMainRamToAram(u8* buf, u32 bufSize, u32 alignedSize, JKRExpandSwitch expandSwitch, u32 fileSize, JKRHeap* heap, int id, u32) +{ + return JKRAram::mainRamToAram(buf, bufSize, alignedSize, expandSwitch, fileSize, heap, id); +} + +inline JKRAramStream* JKRCreateAramStreamManager(s32 priority) +{ + return JKRAramStream::create(priority); +} + +inline bool JKRAramPcs(int direction, u32 source, u32 destination, u32 length, JKRAramBlock* block) +{ return JKRAramPiece::orderSync(direction, source, destination, length, block); } -inline void JKRAramPcs_SendCommand(JKRAMCommand* cmd) { +inline void JKRAramPcs_SendCommand(JKRAMCommand* cmd) +{ JKRAramPiece::sendCommand(cmd); } -#endif \ No newline at end of file +#endif diff --git a/include/JSystem/JKernel/JKRArchive.h b/include/JSystem/JKernel/JKRArchive.h new file mode 100644 index 00000000..652c4f68 --- /dev/null +++ b/include/JSystem/JKernel/JKRArchive.h @@ -0,0 +1,342 @@ +#ifndef JKRARCHIVE_H_ +#define JKRARCHIVE_H_ + +#include "JSystem/JKernel/JKRDvdFile.h" +#include "JSystem/JKernel/JKRFileLoader.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "types.h" + +// NOTE: Vtable offsets are off + +#define JKRARCHIVE_ATTR_COMPRESSION 0x04 +#define JKRARCHIVE_ATTR_YAY0 0x80 + +inline u32 read_big_endian_u32(void* ptr) +{ + u8* uptr = (u8*)ptr; + return ((u32)uptr[0] << 0x18) | ((u32)uptr[1] << 0x10) | ((u32)uptr[2] << 8) | (u32)uptr[3]; +} + +class JKRArchive : public JKRFileLoader +{ +public: + enum EMountMode + { + UNKNOWN_MOUNT_MODE = 0, + MOUNT_MEM = 1, + MOUNT_ARAM = 2, + MOUNT_DVD = 3, + MOUNT_COMP = 4, + }; + + enum EMountDirection + { + UNKNOWN_MOUNT_DIRECTION = 0, + MOUNT_DIRECTION_HEAD = 1, + MOUNT_DIRECTION_TAIL = 2, + }; + + class CArcName + { + public: + CArcName(const char** p1, char p2) { p1[0] = store(p1[0], p2); } + + const char* getString() const { return mString; } + u16 getHash() const { return mHash; } + void store(const char*); + const char* store(const char*, char); + + // Unused/inlined: + CArcName() {} + CArcName(const char* data) { store(data); } + + u16 mHash; // _00 + u16 _02; // _02 + char mString[256]; // _04 + u8 _104[4]; // _104, unknown, used to fix stack size + }; + + struct SDIFileEntry + { + u16 getNameHash() const { return mHash; } + u32 getNameOffset() const { return mFlag & 0xFFFFFF; } + u32 getFlags() const { return mFlag >> 24; } + u32 getAttr() const { return getFlags(); } + u32 getSize() { return mSize; } + u16 getFileID() const { return mFileID; } + bool isDirectory() const { return (getFlags() & 0x02) != 0; } + bool isCompressed() const { return (getFlags() & 0x04) != 0; } + u8 getCompressFlag() const { return (getFlags() & 0x04); } // apparently both necessary? + bool isYAZ0Compressed() const { return (getFlags() & 0x80) != 0; } + + bool getFlag01() const { return (getFlags() & 0x01) != 0; } + bool getFlag04() { return mFlag >> 0x18 & 0x04; } + bool getFlag10() { return mFlag >> 0x18 & 0x10; } + bool getFlag80() { return mFlag >> 0x18 & 0x80; } + + u16 mFileID; // _00 + u16 mHash; // _02 + u32 mFlag; // _04 + u32 mDataOffset; // _08 + u32 mSize; // _0C + void* mData; // _10 + }; + + struct SDirEntry + { + u8 mFlags; // _00 + u8 _01; // _01 + u16 mID; // _02 + char* mName; // _04 + }; + + struct SDIDirEntry + { + u32 mType; // _00 + u32 mOffset; // _04 + u16 _08; // _08 + u16 mNum; // _0A + u32 mFirstIdx; // _0C + }; + + // NB: Fabricated name + struct SArcDataInfo + { + u32 num_nodes; // _00 + u32 node_offset; // _04 + u32 num_file_entries; // _08 + u32 file_entry_offset; // _0C + u32 string_table_length; // _10 + u32 string_table_offset; // _14 + u16 nextFreeFileID; // _18 + bool isSyncIDs; // _1A + u8 _1B[5]; // _1B, unknown + }; + + // NB: Fabricated name - need to check size + struct SArcHeader + { + u32 signature; // _00 + u32 file_length; // _04 + u32 header_length; // _08 + u32 file_data_offset; // _0C + u32 file_data_length; // _10 + u32 _14; // _14 + u32 _18; // _18 + u32 _1C; // _1C + }; + + JKRArchive(s32, EMountMode); + + virtual ~JKRArchive(); // _08 + virtual bool becomeCurrent(const char*); // _10 + virtual void* getResource(const char* path); // _14 + virtual void* getResource(u32 type, const char* name); // _18 + virtual size_t readResource(void* resourceBuffer, u32 bufferSize, const char* path, JKRExpandSwitch expandSwitch); // _1C + virtual size_t readResource(void* resourceBuffer, u32 bufferSize, u32 type, const char* name); // _20 + virtual void removeResourceAll(); // _24 + virtual bool removeResource(void*); // _28 + virtual bool detachResource(void*); // _2C + virtual s32 getResSize(const void*) const; // _30 + virtual u32 countFile(const char*) const; // _34 + virtual JKRFileFinder* getFirstFile(const char*) const; // _38 + virtual void* fetchResource(SDIFileEntry* entry, u32* outSize) = 0; // _40 + virtual void* fetchResource(void* resourceBuffer, u32 bufferSize, SDIFileEntry* entry, u32* resSize, JKRExpandSwitch expandSwitch) = 0; // _44 + + SDIDirEntry* findDirectory(const char*, u32) const; + SDIFileEntry* findFsResource(const char*, u32) const; + SDIFileEntry* findIdResource(u16) const; + SDIFileEntry* findIdxResource(u32) const; + SDIFileEntry* findNameResource(const char*) const; + SDIFileEntry* findPtrResource(const void*) const; + SDIFileEntry* findTypeResource(u32, const char*) const; + bool isSameName(CArcName&, u32, u16) const; + + bool getDirEntry(SDirEntry*, u32) const; + void* getIdxResource(u32 index); + size_t readResource(void* resourceBuffer, u32 bufferSize, u16 id); + + static JKRArchive* mount(char const*, EMountMode, JKRHeap*, EMountDirection); + static JKRArchive* mount(void*, JKRHeap*, EMountDirection); + static JKRArchive* mount(s32, EMountMode, JKRHeap*, EMountDirection); + static void* getGlbResource(u32 type, const char* name, JKRArchive* archive); + + // Unused/inlined: + JKRArchive(); + JKRArchive(const char* p1, EMountMode mountMode); + static JKRArchive* check_mount_already(s32); + static JKRArchive* check_mount_already(s32, JKRHeap*); + SDIDirEntry* findResType(u32) const; + SDIFileEntry* findTypeResource(u32, u32) const; + + static int convertAttrToCompressionType(int attr) + { + int compression; + if (FLAG_ON(attr, JKRARCHIVE_ATTR_COMPRESSION)) + compression = JKRCOMPRESSION_NONE; + else if (!FLAG_ON(attr, JKRARCHIVE_ATTR_YAY0)) + compression = JKRCOMPRESSION_YAZ0; + else + compression = JKRCOMPRESSION_YAY0; + + return compression; + } + + u32 getMountMode() const { return mMountMode; } + u32 countFile() const { return mArcInfoBlock->num_file_entries; } + int countDirectory() const { return mArcInfoBlock->num_nodes; } + static u32 getCurrentDirID() { return sCurrentDirID; } + static void setCurrentDirID(u32 dirID) { sCurrentDirID = dirID; } + + static u32 sCurrentDirID; + +protected: + // _00 = VTBL + // _00-_38 = JKRFileLoader + JKRHeap* mHeap; // _38 + u8 mMountMode; // _3C + s32 mEntryNum; // _40 + SArcDataInfo* mArcInfoBlock; // _44 + SDIDirEntry* mDirectories; // _48 + SDIFileEntry* mFileEntries; // _4C + const char* mStrTable; // _50 + int _54; // _54 + int mCompression; // _58 + EMountDirection mMountDirection; // _5C +}; + +enum JKRMemBreakFlag +{ + MBF_0 = 0, + MBF_1 = 1 +}; + +class JKRAramArchive : public JKRArchive +{ +public: + JKRAramArchive(); + JKRAramArchive(s32, EMountDirection); + + virtual ~JKRAramArchive(); // _08 + virtual void* fetchResource(SDIFileEntry*, u32*); // _40 + virtual void* fetchResource(void*, u32, SDIFileEntry*, u32*, JKRExpandSwitch expandSwitch); // _44 + + bool open(s32); + u32 getAramAddress_Entry(SDIFileEntry* fileEntry); + u32 getAramAddress(u32, const char* file); + static u32 fetchResource_subroutine(u32, u32, u8*, u32, int); + static u32 fetchResource_subroutine(u32, u32, JKRHeap*, int, u8**); + + void fixedInit(s32 entryNum, EMountDirection direction); + bool mountFixed(s32 entryNum, EMountDirection direction); + bool mountFixed(const char* path, EMountDirection direction); + void unmountFixed(); + + // _00 = VTBL + // _00-_60 = JKRArchive + JKRAramBlock* mBlock; // _60 + JKRFile* mDvdFile; // _64 +}; + +struct JKRCompArchive : public JKRArchive +{ + JKRCompArchive(s32, EMountDirection); + + virtual ~JKRCompArchive(); // _08 + virtual void removeResourceAll(); // _24 + virtual bool removeResource(void*); // _28 + virtual void* fetchResource(SDIFileEntry* entry, u32* outSize); // _40 + virtual void* fetchResource(void* resourceBuffer, u32 bufferSize, SDIFileEntry* entry, u32* resSize, JKRExpandSwitch expandSwitch); // _44 + + bool open(s32); + + // Unused/inlined: + void fixedInit(s32); + void mountFixed(s32); + void mountFixed(const char*); + void unmountFixed(); + + // _00 = VTBL + // _00-_5C = JKRArchive + u32 _60; // _60 + JKRAramBlock* mAramPart; // _64 + u32 _68; // _68 + JKRFile* mDvdFile; // _6C + u32 mSizeOfMemPart; // _70 + u32 mSizeOfAramPart; // _74 + u32 _78; // _78 +}; + +struct JKRDvdArchive : public JKRArchive +{ + JKRDvdArchive(); + JKRDvdArchive(s32, JKRArchive::EMountDirection); + + virtual ~JKRDvdArchive(); // _00 + virtual void* fetchResource(SDIFileEntry* entry, u32* outSize); // _38 + virtual void* fetchResource(void* resourceBuffer, u32 bufferSize, SDIFileEntry* entry, u32* resSize, JKRExpandSwitch expandSwitch); // _3C + + bool open(s32); + static u32 fetchResource_subroutine(s32, u32, u32, u8*, u32, int, int); + static u32 fetchResource_subroutine(s32, u32, u32, JKRHeap*, int, int, u8**); + + // Unused/inlined: + unknown fixedInit(s32, EMountDirection); + unknown mountFixed(s32, EMountDirection); + unknown mountFixed(const char*, EMountDirection); + unknown unmountFixed(); + + // _00 = VTBL + // _00-_5C = JKRArchive + int _60; // _60 + JKRFile* mDvdFile; // _64 +}; + +struct JKRMemArchive : public JKRArchive +{ + JKRMemArchive(); // unused/inlined + JKRMemArchive(s32, EMountDirection); + JKRMemArchive(void*, u32, JKRMemBreakFlag); + JKRMemArchive(const char*, EMountDirection); // unused/inlined + + virtual ~JKRMemArchive(); // _08 + virtual void removeResourceAll(); // _24 + virtual bool removeResource(void*); // _28 + virtual void* fetchResource(SDIFileEntry* entry, u32* outSize); // _40 + virtual void* fetchResource(void* resourceBuffer, u32 bufferSize, SDIFileEntry* entry, u32* resSize, JKRExpandSwitch expandSwitch); // _44 + + bool open(s32, EMountDirection); + bool open(void*, u32, JKRMemBreakFlag); + static u32 fetchResource_subroutine(u8*, u32, u8*, u32, int); + + // Unused/inlined: + void fixedInit(s32); + void mountFixed(s32, EMountDirection); + void mountFixed(const char*, EMountDirection); + void mountFixed(void*, JKRMemBreakFlag); + void unmountFixed(); + void open(const char*, EMountDirection); + + // _00 = VTBL + // _00-_60 = JKRArchive + SArcHeader* mArcHeader; // _60 + u8* mArchiveData; // _64 + bool mIsOpen; // _68 +}; + +inline int JKRConvertAttrToCompressionType(int attr) +{ + return JKRArchive::convertAttrToCompressionType(attr); +} + +inline JKRArchive* JKRMountArchive(const char* path, JKRArchive::EMountMode mountMode, JKRHeap* heap, JKRArchive::EMountDirection mountDirection) +{ + return JKRArchive::mount(path, mountMode, heap, mountDirection); +} + +inline JKRArchive* JKRMountArchive(void* inBuf, JKRHeap* heap, JKRArchive::EMountDirection mountDirection) +{ + return JKRArchive::mount(inBuf, heap, mountDirection); +} + +#endif diff --git a/include/JSystem/JKernel/JKRDecomp.h b/include/JSystem/JKernel/JKRDecomp.h index 0cc094ff..fa792bde 100644 --- a/include/JSystem/JKernel/JKRDecomp.h +++ b/include/JSystem/JKernel/JKRDecomp.h @@ -3,6 +3,7 @@ #include "types.h" #include "dolphin/os/OSMessage.h" +#include "JSystem/JKernel/JKRDvdFile.h" #include "JSystem/JKernel/JKRThread.h" #include "JSystem/JKernel/JKRAram.h" @@ -78,6 +79,14 @@ inline JKRDecomp* JKRCreateDecompManager(s32 priority) { return JKRDecomp::create(priority); } +inline int JKRCheckCompressed_noASR(u8* pBuf) +{ + int compression = JKRDecomp::checkCompressed(pBuf); + if (compression == JKRCOMPRESSION_ASR) + compression = JKRCOMPRESSION_NONE; + return compression; +} + inline JKRDecomp::CompressionMode JKRCheckCompressed(u8* buf) { return JKRDecomp::checkCompressed(buf); } @@ -90,4 +99,8 @@ inline void JKRDecompress(u8* src, u8* dst, u32 srcLength, u32 skipCount) { JKRDecomp::orderSync(src, dst, srcLength, skipCount); } +int JKRDecompressFromDVD(JKRDvdFile* srcFile, void* buf, u32 size, u32 maxDest, u32 fileOffset, u32 srcOffset); +int JKRDecompressFromDVDToAram(JKRDvdFile* srcFile, u32 address, u32 fileSize, u32 maxDest, u32 fileOffset, u32 srcOffset); +int JKRDecompressFromAramToMainRam(u32 srcAddress, void* dst, u32 fileSize, u32 maxDest, u32 fileOffset); + #endif diff --git a/include/JSystem/JKernel/JKRDisposer.h b/include/JSystem/JKernel/JKRDisposer.h index 9a4ced98..7d53aac6 100644 --- a/include/JSystem/JKernel/JKRDisposer.h +++ b/include/JSystem/JKernel/JKRDisposer.h @@ -14,8 +14,8 @@ public: virtual ~JKRDisposer(); public: - JKRHeap *mRootHeap; // _4 + JKRHeap* mRootHeap; // _4 JSULink mPointerLinks; // _8 }; -#endif \ No newline at end of file +#endif diff --git a/include/JSystem/JKernel/JKRDvdAramRipper.h b/include/JSystem/JKernel/JKRDvdAramRipper.h new file mode 100644 index 00000000..a535c84a --- /dev/null +++ b/include/JSystem/JKernel/JKRDvdAramRipper.h @@ -0,0 +1,62 @@ +#ifndef JKRDVDARAMRIPPER_H +#define JKRDVDARAMRIPPER_H + +#include "JSystem/JKernel/JKRAram.h" +#include "JSystem/JKernel/JKRDvdFile.h" +#include "JSystem/JSupport/JSUList.h" +#include "types.h" + +class JKRADCommand +{ +public: + typedef void (*LoadCallback)(u32); + JKRADCommand(); + ~JKRADCommand(); + + // Fields might need more swapping + JSULink mLink; + JKRDvdFile* mDvdFile; // _28 + u32 _14; // _14 + u32 _18; // _18, probably size + u32 _1C; // _1C + JKRAramBlock* mBlock; // _20 + JKRExpandSwitch mExpandSwitch; // _24 + u8 _28[0x10]; // _28 - unknown/padding + u32* _3C; // _3C + s32 _40; // _40 + LoadCallback mCallBack; // _40 + u8 _44; // _44 + JKRAramStreamCommand* mStreamCommand; // _48 +}; + +class JKRDvdAramRipper +{ +public: + static JKRAramBlock* loadToAram(char const*, u32, JKRExpandSwitch, u32, u32); + static JKRAramBlock* loadToAram(s32, u32, JKRExpandSwitch, u32, u32); + static JKRAramBlock* loadToAram(JKRDvdFile*, u32, JKRExpandSwitch, u32, u32); + static JKRADCommand* loadToAram_Async(JKRDvdFile*, u32, JKRExpandSwitch, JKRADCommand::LoadCallback, u32, u32); + static JKRADCommand* callCommand_Async(JKRADCommand*); + static bool syncAram(JKRADCommand*, int); + + // unused/inlined: + static JKRADCommand* loadToAram_Async(const char*, u32, JKRExpandSwitch, JKRADCommand::LoadCallback, u32, u32); + static JKRADCommand* loadToAram_Async(s32, u32, JKRExpandSwitch, JKRADCommand::LoadCallback, u32, u32); + static void syncAramAll(int); + static void countLeftSync(); + static void afterAramAsync(JKRADCommand*); + + static int getSZSBufferSize() { return sSZSBufferSize; } + static bool isErrorRetry() { return errorRetry; } + + static bool errorRetry; + static int sSZSBufferSize; + static JSUList sDvdAramAsyncList; +}; + +inline JKRAramBlock* JKRDvdToAram(s32 entrynum, u32 p2, JKRExpandSwitch expSwitch, u32 p4, u32 p5) +{ + return JKRDvdAramRipper::loadToAram(entrynum, p2, expSwitch, p4, p5); +} + +#endif diff --git a/include/JSystem/JKernel/JKRDvdFile.h b/include/JSystem/JKernel/JKRDvdFile.h index 8a975353..9db570e5 100644 --- a/include/JSystem/JKernel/JKRDvdFile.h +++ b/include/JSystem/JKernel/JKRDvdFile.h @@ -1,6 +1,7 @@ #ifndef JKRDVDFILE_H #define JKRDVDFILE_H +#include "JSystem/JKernel/JKRAram.h" #include "JSystem/JKernel/JKRFile.h" #include "JSystem/JSupport/JSUStream.h" @@ -30,22 +31,22 @@ public: } inline int readDataAsync(void* addr, s32 length, s32 offset) { - OSLockMutex(&this->mMutex1); + OSLockMutex(&this->mDvdMutex); s32 retAddr; - if (this->mThread2 != nullptr) { - OSUnlockMutex(&this->mMutex1); + if (this->mDvdThread != nullptr) { + OSUnlockMutex(&this->mDvdMutex); retAddr = -1; } else { - this->mThread2 = OSGetCurrentThread(); + this->mDvdThread = OSGetCurrentThread(); retAddr = -1; if (DVDReadAsync(&this->mDvdFileInfo, addr, length, offset, JKRDvdFile::doneProcess)) { retAddr = this->sync(); } - this->mThread2 = nullptr; - OSUnlockMutex(&this->mMutex1); + this->mDvdThread = nullptr; + OSUnlockMutex(&this->mDvdMutex); } return retAddr; @@ -60,20 +61,20 @@ public: static JSUList sDvdList; -protected: - OSMutex mMutex1; - OSMutex mMutex2; +public: + OSMutex mDvdMutex; + OSMutex mAramMutex; JKRAramBlock* mAramBlock; - OSThread* mThread1; + OSThread* mAramThread; JSUFileInputStream* mInputStream; u32 _58; JKRDvdFileInfo mDvdFileInfo; - OSMessageQueue mMessageQueue1; - OSMessage mMsg1; - OSMessageQueue mMessageQueue2; - OSMessage mMsg2; + OSMessageQueue mAramMessageQueue; + OSMessage mAramMessage; + OSMessageQueue mDvdMessageQueue; + OSMessage mDvdMessage; JSULink mLink; - OSThread* mThread2; + OSThread* mDvdThread; }; #endif diff --git a/include/JSystem/JKernel/JKRDvdRipper.h b/include/JSystem/JKernel/JKRDvdRipper.h index 65f8231d..4bd0453d 100644 --- a/include/JSystem/JKernel/JKRDvdRipper.h +++ b/include/JSystem/JKernel/JKRDvdRipper.h @@ -7,12 +7,18 @@ #define SZP_BUFFERSIZE 1024 #define REF_BUFFERSIZE 0x1120 +#define DMA_BUFFERSIZE 0x100 struct SZPHeader { u32 magic; u32 decompSize; }; +struct SYaz0Header { + u32 signature; + u32 length; +}; + class JKRDMCommand { JKRDMCommand(); ~JKRDMCommand(); @@ -37,6 +43,14 @@ public: static bool errorRetry; }; -static int JKRDecompressFromDVD(JKRDvdFile* srcFile, void* buf, u32 size, u32 maxDest, u32 fileOffset, u32 srcOffset); +inline void* JKRDvdToMainRam(long entryNum, u8* dst, JKRExpandSwitch expandSwitch, u32 fileSize, JKRHeap* heap, JKRDvdRipper::EAllocDirection allocDirection, u32 startOffset, int* pCompression) +{ + return JKRDvdRipper::loadToMainRAM(entryNum, dst, expandSwitch, fileSize, heap, allocDirection, startOffset, pCompression); +} + +inline void* JKRDvdToMainRam(const char* path, u8* dst, JKRExpandSwitch expandSwitch, u32 fileSize, JKRHeap* heap, JKRDvdRipper::EAllocDirection allocDirection, u32 startOffset, int* pCompression) +{ + return JKRDvdRipper::loadToMainRAM(path, dst, expandSwitch, fileSize, heap, allocDirection, startOffset, pCompression); +} #endif diff --git a/include/JSystem/JKernel/JKREnum.h b/include/JSystem/JKernel/JKREnum.h index 8652231b..361d0c66 100644 --- a/include/JSystem/JKernel/JKREnum.h +++ b/include/JSystem/JKernel/JKREnum.h @@ -7,10 +7,16 @@ extern "C" { #endif -typedef enum JKRExpandSwitch { - EXPAND_SWITCH_DEFAULT, /* Do nothing? treated same as 2 */ +#define JKRCOMPRESSION_NONE 0 +#define JKRCOMPRESSION_YAY0 1 +#define JKRCOMPRESSION_YAZ0 2 +#define JKRCOMPRESSION_ASR 3 + +typedef enum JKRExpandSwitch +{ + EXPAND_SWITCH_DEFAULT, /* Do nothing? treated same as 2 */ EXPAND_SWITCH_DECOMPRESS, /* Check for compression and decompress */ - EXPAND_SWITCH_NONE /* Do nothing */ + EXPAND_SWITCH_NONE /* Do nothing */ } JKRExpandSwitch; #ifdef __cplusplus diff --git a/include/JSystem/JKernel/JKRExpHeap.h b/include/JSystem/JKernel/JKRExpHeap.h new file mode 100644 index 00000000..d9c8c548 --- /dev/null +++ b/include/JSystem/JKernel/JKRExpHeap.h @@ -0,0 +1,107 @@ +#ifndef JKREXPHEAP_H +#define JKREXPHEAP_H + +#include "JSystem/JKernel/JKRHeap.h" +#include "types.h" + +class JKRExpHeap : public JKRHeap +{ +public: + class CMemBlock + { + public: + CMemBlock* allocBack(u32, u8, u8, u8, u8); + CMemBlock* allocFore(u32, u8, u8, u8, u8); + void* free(JKRExpHeap*); + static CMemBlock* getHeapBlock(void*); + void initiate(CMemBlock*, CMemBlock*, u32, u8, u8); + + void newGroupId(u8 groupId) { mGroupID = groupId; } + bool isValid() const { return mUsageHeader == 'HM'; } + bool _isTempMemBlock() const { return (mFlags & 0x80) ? true : false; } + int getAlignment() const { return mFlags & 0x7f; } + void* getContent() const { return (void*)(this + 1); } + CMemBlock* getPrevBlock() const { return mPrev; } + CMemBlock* getNextBlock() const { return mNext; } + u32 getSize() const { return mAllocatedSpace; } + u8 getGroupId() const { return mGroupID; } + static CMemBlock* getBlock(void* data) { return (CMemBlock*)((u32)data + -0x10); } + + u16 mUsageHeader; // _00 + u8 mFlags; // _02, a|bbbbbbb = a=temp, b=aln + u8 mGroupID; // _03 + int mAllocatedSpace; // _04 + CMemBlock* mPrev; // _08 + CMemBlock* mNext; // _0C + }; + + JKRExpHeap(void*, u32, JKRHeap*, bool); + + virtual ~JKRExpHeap(); // _08 + virtual void* do_alloc(u32, int); // _10 + virtual void do_free(void*); // _14 + virtual void do_freeTail(); // _18 + virtual void do_freeAll(); // _1C + virtual s32 do_resize(void*, u32); // _20 + virtual s32 do_getSize(void*); // _24 + virtual s32 do_getFreeSize(); // _28 + virtual s32 do_getTotalFreeSize(); // _2C + virtual bool check(); // _34 + virtual bool dump_sort(); // _38 + virtual bool dump(); // _3C + virtual s32 do_changeGroupID(u8); // _40 + virtual void state_register(TState*, u32) const; // _48 + virtual bool state_compare(const TState&, const TState&) const; // _4C + + virtual u8 do_getCurrentGroupId() { return mCurrentGroupID; } // _44 (weak) + virtual u32 getHeapType() { return 'EXPH'; } // _30 (weak) + + void* allocFromHead(u32, int); + void* allocFromHead(u32); + void* allocFromTail(u32, int); + void* allocFromTail(u32); + void appendUsedList(CMemBlock*); + static JKRExpHeap* create(u32, JKRHeap*, bool); + static JKRExpHeap* create(void*, u32, JKRHeap*, bool); + static JKRExpHeap* createRoot(int, bool); + int freeGroup(u8 groupID); + void joinTwoBlocks(CMemBlock*); + void recycleFreeBlock(CMemBlock*); + void removeFreeBlock(CMemBlock*); + void setFreeBlock(CMemBlock*, CMemBlock*, CMemBlock*); + + // unused/inlined: + void removeUsedBlock(CMemBlock*); + bool isEmpty(); + s32 getUsedSize(u8 groupId) const; + + CMemBlock* getHeadUsedList() const { return mHeadUsedList; } + void setAllocationMode(EAllocMode mode) { mCurrentAllocMode = mode; } + + static s32 getUsedSize_(JKRExpHeap* expHeap) + { + // s32 totalFreeSize = expHeap->getTotalFreeSize(); + return expHeap->mSize - expHeap->getTotalFreeSize(); + } + static u32 getState_(TState* state) { return getState_buf_(state); } // might instead be a pointer to a next state? + +private: + // _00 = VTBL + // _00-_6C = JKRHeap + u8 mCurrentAllocMode; // _6C + u8 mCurrentGroupID; // _6D + u8 _6E; // _6E + void* _70; // _70 + u32 _74; // _74 + CMemBlock* mHead; // _78, free list + CMemBlock* mTail; // _7C, free list + CMemBlock* mHeadUsedList; // _80 + CMemBlock* mTailUsedList; // _84 +}; + +inline JKRExpHeap* JKRCreateExpHeap(u32 size, JKRHeap* parent, bool errorFlag) +{ + return JKRExpHeap::create(size, parent, errorFlag); +} + +#endif /* JKREXPHEAP_H */ diff --git a/include/JSystem/JKernel/JKRFile.h b/include/JSystem/JKernel/JKRFile.h index 2a209850..8da98098 100644 --- a/include/JSystem/JKernel/JKRFile.h +++ b/include/JSystem/JKernel/JKRFile.h @@ -5,7 +5,6 @@ #include "dolphin/dvd.h" #include "dolphin/os.h" #include "JSystem/JSupport/JSUList.h" -#include "JSystem/JKernel/JKRAram.h" #include "JSystem/JKernel/JKRDisposer.h" #include "JSystem/JKernel/JKRMacro.h" @@ -14,8 +13,8 @@ public: inline JKRFile() : JKRDisposer() , mFileOpen(false) - { - } + { + } virtual ~JKRFile() { } virtual bool open(const char* path) = 0; diff --git a/include/JSystem/JKernel/JKRFileFinder.h b/include/JSystem/JKernel/JKRFileFinder.h new file mode 100644 index 00000000..f0bcfdca --- /dev/null +++ b/include/JSystem/JKernel/JKRFileFinder.h @@ -0,0 +1,78 @@ +#ifndef _JKRFILEFINDER_H +#define _JKRFILEFINDER_H + +#include +#include +#include "types.h" + +class JKRArchive; + +struct JKRFileFinderBase +{ + char* mFileName; // _00 + int mFileIndex; // _04 + u16 mFileID; // _08 + u16 mFileTypeFlags; // _0A +}; + +class JKRFileFinder +{ +public: + JKRFileFinder() + : mIsAvailable(false), mIsFileOrDir(false) + { + } + + JKRFileFinderBase mBase; + + virtual ~JKRFileFinder() {} // _08 (weak) + virtual bool findNextFile() = 0; // _0C + + bool isAvailable() const + { + return mIsAvailable; + } + + // _00 = VTBL + + bool mIsAvailable; // _10 + bool mIsFileOrDir; // _11 +}; + +class JKRArcFinder : public JKRFileFinder +{ +public: + JKRArcFinder(JKRArchive*, long, long); + + virtual ~JKRArcFinder() {} // _08 (weak) + virtual bool findNextFile(); // _0C + + // _00 = VTBL + // _00-_14 = JKRFileFinder + JKRArchive* mArchive; // _14 + long mStartIndex; // _18 + long mEndIndex; // _1C + long mNextIndex; // _20 +}; + +class JKRDvdFinder : public JKRFileFinder +{ +public: + JKRDvdFinder(const char*); + + virtual ~JKRDvdFinder() // _08 (weak) + { + if (mIsDvdOpen) + { + DVDCloseDir(&mDir); + } + } + virtual bool findNextFile(); // _0C + + // _00 = VTBL + // _00-_14 = JKRFileFinder + DVDDir mDir; // _14 + bool mIsDvdOpen; // _20 +}; + +#endif diff --git a/include/JSystem/JKernel/JKRFileLoader.h b/include/JSystem/JKernel/JKRFileLoader.h new file mode 100644 index 00000000..33646664 --- /dev/null +++ b/include/JSystem/JKernel/JKRFileLoader.h @@ -0,0 +1,62 @@ +#ifndef JKRFILELOADER_H_ +#define JKRFILELOADER_H_ + +#include "JSystem/JKernel/JKREnum.h" +#include "JSystem/JKernel/JKRDisposer.h" +#include "JSystem/JSupport/JSUList.h" + +class JKRFileFinder; +class JKRFileLoader : public JKRDisposer +{ +public: + JKRFileLoader(); + + virtual ~JKRFileLoader(); // _08 + virtual void unmount(); // _0C + virtual bool becomeCurrent(const char*) = 0; // _10 + virtual void* getResource(const char* path) = 0; // _14 + virtual void* getResource(u32 type, const char* name) = 0; // _18 + virtual size_t readResource(void* resourceBuffer, u32 bufferSize, const char* path, JKRExpandSwitch expandSwitch) = 0; // _1C + virtual size_t readResource(void* resourceBuffer, u32 bufferSize, u32 type, const char* name) = 0; // _20 + virtual void removeResourceAll() = 0; // _24 + virtual bool removeResource(void*) = 0; // _28 + virtual bool detachResource(void*) = 0; // _2C + virtual long getResSize(const void*) const = 0; // _30 + virtual u32 countFile(const char*) const = 0; // _34 + virtual JKRFileFinder* getFirstFile(const char*) const = 0; // _38 + + bool isMounted() const { return mIsMounted; } + u32 getVolumeType() const { return mVolumeType; } + + static void changeDirectory(const char* dir); + + static void* getGlbResource(const char*); + static void* getGlbResource(const char*, JKRFileLoader* fileLoader); + static size_t readGlbResource(void* resourceBuffer, u32 bufferSize, const char* path, JKRExpandSwitch expandSwitch); + + static bool removeResource(void* resourceBuffer, JKRFileLoader* fileLoader); + static bool detachResource(void* resourceBuffer, JKRFileLoader* fileLoader); + + static JKRFileLoader* findVolume(const char**); + static JKRFileFinder* findFirstFile(const char*); + static const char* fetchVolumeName(char*, long, const char*); + + static JKRFileLoader* getCurrentVolume() { return sCurrentVolume; } + static void setCurrentVolume(JKRFileLoader* fileLoader) { sCurrentVolume = fileLoader; } + static JSUList& getVolumeList() { return sVolumeList; } + + static JKRFileLoader* sCurrentVolume; + static JSUList sVolumeList; + +protected: + /* 0x00 */ // vtable + /* 0x04 */ // JKRDisposer + JSULink mFileLoaderLink; // 0x18 + const char* mVolumeName; // 0x28 + u32 mVolumeType; // 0x2C + bool mIsMounted; // 0x30 + u8 field_0x31[3]; // 0x31 + u32 mMountCount; // 0x34 +}; + +#endif diff --git a/include/JSystem/JKernel/JKRHeap.h b/include/JSystem/JKernel/JKRHeap.h index e779757b..dbfd6255 100644 --- a/include/JSystem/JKernel/JKRHeap.h +++ b/include/JSystem/JKernel/JKRHeap.h @@ -6,7 +6,7 @@ #include "types.h" -typedef void JKRHeapErrorHandler(void *, u32, int); +typedef void JKRHeapErrorHandler(void*, u32, int); class JKRHeap : public JKRDisposer { @@ -24,29 +24,29 @@ public: { } - void *_00; // _00 + void* _00; // _00 int _04; // _04 }; struct TArgument { - TArgument(const JKRHeap *heap, u32 p2, bool p3) + TArgument(const JKRHeap* heap, u32 p2, bool p3) : mHeap((heap) ? heap : JKRHeap::sCurrentHeap), mId(p2), mIsCompareOnDestructed(p3) { } - const JKRHeap *mHeap; // _00 + const JKRHeap* mHeap; // _00 u32 mId; // _04 bool mIsCompareOnDestructed; // _08 }; - TState(const JKRHeap *heap, u32 id, bool isCompareOnDestructed) + TState(const JKRHeap* heap, u32 id, bool isCompareOnDestructed) : mUsedSize(0), mCheckCode(0), mArgument(heap, id, isCompareOnDestructed) { mArgument.mHeap->state_register(this, mArgument.mId); } - TState(JKRHeap *heap) + TState(JKRHeap* heap) : mUsedSize(0), mCheckCode(0), mArgument(heap, 0xFFFFFFFF, true) { } @@ -57,13 +57,13 @@ public: bool isCompareOnDestructed() const { return mArgument.mIsCompareOnDestructed; }; u32 getUsedSize() const { return mUsedSize; } u32 getCheckCode() const { return mCheckCode; } - const JKRHeap *getHeap() const { return mArgument.mHeap; } + const JKRHeap* getHeap() const { return mArgument.mHeap; } u32 getId() const { return mArgument.mId; } // unused/inlined: - TState(const JKRHeap::TState::TArgument &arg, const JKRHeap::TState::TLocation &location); - TState(const JKRHeap::TState &other, bool p2); - TState(const JKRHeap::TState &other, const JKRHeap::TState::TLocation &location, bool p3); + TState(const JKRHeap::TState::TArgument& arg, const JKRHeap::TState::TLocation& location); + TState(const JKRHeap::TState& other, bool p2); + TState(const JKRHeap::TState& other, const JKRHeap::TState::TLocation& location, bool p3); static bool bVerbose_; @@ -76,19 +76,19 @@ public: }; public: - JKRHeap(void *, u32, JKRHeap *, bool); + JKRHeap(void*, u32, JKRHeap*, bool); bool setErrorFlag(bool errorFlag); - bool isSubHeap(JKRHeap *heap) const; + bool isSubHeap(JKRHeap* heap) const; virtual ~JKRHeap(); virtual void callAllDisposer(); - virtual void *do_alloc(u32, int) = 0; - virtual void do_free(void *) = 0; + virtual void* do_alloc(u32, int) = 0; + virtual void do_free(void*) = 0; virtual void do_freeAll() = 0; virtual void do_freeTail() = 0; - virtual s32 do_resize(void *, u32) = 0; - virtual s32 do_getSize(void *) = 0; + virtual s32 do_resize(void*, u32) = 0; + virtual s32 do_getSize(void*) = 0; virtual s32 do_getFreeSize() = 0; virtual s32 do_getTotalFreeSize() = 0; virtual u32 getHeapType() = 0; @@ -97,54 +97,54 @@ public: virtual bool dump() = 0; virtual s32 do_changeGroupID(u8 newGroupID) { return 0; } virtual u8 do_getCurrentGroupId() { return 0; } - virtual void state_register(JKRHeap::TState *, u32) const; - virtual bool state_compare(JKRHeap::TState const &, JKRHeap::TState const &) const; - virtual void state_dump(JKRHeap::TState const &) const; + virtual void state_register(JKRHeap::TState*, u32) const; + virtual bool state_compare(JKRHeap::TState const&, JKRHeap::TState const&) const; + virtual void state_dump(JKRHeap::TState const&) const; - JKRHeap *becomeSystemHeap(); - JKRHeap *becomeCurrentHeap(); + JKRHeap* becomeSystemHeap(); + JKRHeap* becomeCurrentHeap(); void destroy(); - void *alloc(u32, int); - void free(void *); + void* alloc(u32, int); + void free(void*); void freeAll(); void freeTail(); void fillFreeArea(); - void resize(void *, u32); - static s32 getSize(void *, JKRHeap*); + void resize(void*, u32); + static s32 getSize(void*, JKRHeap*); // ... more functions - s32 getSize(void *ptr); + s32 getSize(void* ptr); s32 getFreeSize(); - void *getMaxFreeBlock(); + void* getMaxFreeBlock(); s32 getTotalFreeSize(); u8 getCurrentGroupId(); s32 changeGroupID(u8 newGroupId); u32 getMaxAllocatableSize(int alignment); - JKRHeap *find(void *) const; // 0x80084640 - JKRHeap *findAllHeap(void *) const; // 0x8008492c + JKRHeap* find(void*) const; // 0x80084640 + JKRHeap* findAllHeap(void*) const; // 0x8008492c void dispose_subroutine(u32 begin, u32 end); - bool dispose(void *, u32); // 0x80084b9c - void dispose(void *, void *); // 0x80084c2c + bool dispose(void*, u32); // 0x80084b9c + void dispose(void*, void*); // 0x80084c2c void dispose(); // 0x80084cb8 - void appendDisposer(JKRDisposer *disposer) + void appendDisposer(JKRDisposer* disposer) { mDisposerList.append(&disposer->mPointerLinks); } - void removeDisposer(JKRDisposer *disposer) + void removeDisposer(JKRDisposer* disposer) { mDisposerList.remove(&disposer->mPointerLinks); } void setDebugFill(bool debugFill) { mDebugFill = debugFill; } bool getDebugFill() const { return mDebugFill; } - void *getStartAddr() const { return (void *)mStart; } - void *getEndAddr() const { return (void *)mEnd; } + void* getStartAddr() const { return (void*)mStart; } + void* getEndAddr() const { return (void*)mEnd; } u32 getHeapSize() const { return mSize; } bool getErrorFlag() const { return mErrorFlag; } - void callErrorHandler(JKRHeap *heap, u32 size, int alignment) + void callErrorHandler(JKRHeap* heap, u32 size, int alignment) { if (mErrorHandler) { @@ -152,34 +152,59 @@ public: } } + // TState related + static u32 getState_buf_(TState* state) { return state->mBuf; } // might instead be a pointer to a next state? + static void setState_u32ID_(TState* state, u32 id) + { + state->mArgument.mId = id; + } + static void setState_uUsedSize_(TState* state, u32 usedSize) + { + state->mUsedSize = usedSize; + } + static void setState_u32CheckCode_(TState* state, u32 checkCode) { state->mCheckCode = checkCode; } + + void lock() const { OSLockMutex(const_cast(&mMutex)); } + void unlock() const { OSUnlockMutex(const_cast(&mMutex)); } + + JKRHeap* getParent() + { + return mChildTree.getParent()->getObject(); + } + + const JSUTree& getHeapTree() + { + return mChildTree; + } + // Unused - void checkMemoryFilled(u8 *, u32 size, u8); + void checkMemoryFilled(u8*, u32 size, u8); - static void destroy(JKRHeap *heap); // fabricated - static bool initArena(char **, u32 *, int); - static void *alloc(u32, int, JKRHeap *); - static void copyMemory(void *, void *, u32); - static void free(void *, JKRHeap *); - static void state_dumpDifference(const TState &, const TState &); - static JKRHeap *findFromRoot(void *); - static JKRHeapErrorHandler *setErrorHandler(JKRHeapErrorHandler *); + static void destroy(JKRHeap* heap); // fabricated + static bool initArena(char**, u32*, int); + static void* alloc(u32, int, JKRHeap*); + static void copyMemory(void*, void*, u32); + static void free(void*, JKRHeap*); + static void state_dumpDifference(const TState&, const TState&); + static JKRHeap* findFromRoot(void*); + static JKRHeapErrorHandler* setErrorHandler(JKRHeapErrorHandler*); - static void *getCodeStart() + static void* getCodeStart() { return mCodeStart; } - static void *getCodeEnd() + static void* getCodeEnd() { return mCodeEnd; } - static void *getUserRamStart() + static void* getUserRamStart() { return mUserRamStart; } - static void *getUserRamEnd() + static void* getUserRamEnd() { return mUserRamEnd; } @@ -189,42 +214,42 @@ public: return mMemorySize; } - static JKRHeap *getCurrentHeap() + static JKRHeap* getCurrentHeap() { return sCurrentHeap; } - static JKRHeap *getRootHeap() + static JKRHeap* getRootHeap() { return sRootHeap; } - static JKRHeap *getSystemHeap() + static JKRHeap* getSystemHeap() { return sSystemHeap; } - static void *mCodeStart; - static void *mCodeEnd; - static void *mUserRamStart; - static void *mUserRamEnd; + static void* mCodeStart; + static void* mCodeEnd; + static void* mUserRamStart; + static void* mUserRamEnd; static u32 mMemorySize; - static JKRHeap *sSystemHeap; - static JKRHeap *sCurrentHeap; - static JKRHeap *sRootHeap; + static JKRHeap* sSystemHeap; + static JKRHeap* sCurrentHeap; + static JKRHeap* sRootHeap; static bool sDefaultFillFlag; static bool sDefaultFillCheckFlag; - static JKRHeapErrorHandler *mErrorHandler; + static JKRHeapErrorHandler* mErrorHandler; protected: /* 0x00 */ // vtable /* 0x04 */ // JKRDisposer /* 0x18 */ OSMutex mMutex; - /* 0x30 */ void *mStart; - /* 0x34 */ void *mEnd; + /* 0x30 */ void* mStart; + /* 0x34 */ void* mEnd; /* 0x38 */ u32 mSize; /* 0x3C */ bool mDebugFill; /* 0x3D */ bool mCheckMemoryFilled; @@ -237,52 +262,58 @@ protected: /* 0x6A */ u8 padding_0x6a[2]; }; -inline JKRHeap *JKRGetCurrentHeap() +inline JKRHeap* JKRGetCurrentHeap() { return JKRHeap::getCurrentHeap(); } -inline JKRHeap *JKRGetSystemHeap() +inline JKRHeap* JKRGetSystemHeap() { return JKRHeap::getSystemHeap(); } -inline JKRHeap *JKRGetRootHeap() +inline JKRHeap* JKRGetRootHeap() { return JKRHeap::getRootHeap(); } -inline void *JKRAllocFromSysHeap(u32 size, int alignment) +inline void* JKRAllocFromSysHeap(u32 size, int alignment) { return JKRHeap::getSystemHeap()->alloc(size, alignment); } -inline void *JKRAllocFromHeap(JKRHeap *heap, u32 size, int alignment) +inline void* JKRAllocFromHeap(JKRHeap* heap, u32 size, int alignment) { return JKRHeap::alloc(size, alignment, heap); } -inline void JKRFree(void *pBuf) +inline void JKRFree(void* pBuf) { JKRHeap::free(pBuf, nullptr); } -inline void JKRFreeToSysHeap(void *buf) +inline void JKRFreeToHeap(JKRHeap* heap, void* ptr) +{ + JKRHeap::free(ptr, heap); +} + +inline void JKRFreeToSysHeap(void* buf) { JKRHeap::getSystemHeap()->free(buf); } -void JKRDefaultMemoryErrorRoutine(void *, u32, int); +void JKRDefaultMemoryErrorRoutine(void*, u32, int); -void *operator new(size_t); -void *operator new(size_t, s32); -void *operator new(size_t, JKRHeap *, int); +void* operator new(size_t); +void* operator new(size_t, s32); +void* operator new(size_t, JKRHeap*, int); +inline void* operator new(size_t, void* buf) { return buf; } // i believe this is actually part of MSL_C? -void *operator new[](size_t); -void *operator new[](size_t, s32); -void *operator new[](size_t, JKRHeap *, int); +void* operator new[](size_t); +void* operator new[](size_t, s32); +void* operator new[](size_t, JKRHeap*, int); -void operator delete(void *); -void operator delete[](void *); +void operator delete(void*); +void operator delete[](void*); #endif // !JKRHEAP_H diff --git a/include/JSystem/JKernel/JKRThread.h b/include/JSystem/JKernel/JKRThread.h index b897af7b..5266be9e 100644 --- a/include/JSystem/JKernel/JKRThread.h +++ b/include/JSystem/JKernel/JKRThread.h @@ -6,16 +6,62 @@ #include "dolphin/os/OSThread.h" #include "dolphin/os/OSTime.h" #include "JSystem/JSupport/JSUList.h" +#include "JSystem/JUtility/JUTConsole.h" #include "JSystem/JKernel/JKRHeap.h" #include "JSystem/JKernel/JKRDisposer.h" +struct JKRThread; + +struct JKRThreadName_ +{ + s32 id; + char* name; +}; + +typedef void (*JKRThreadSwitch_PreCallback)(OSThread* current, OSThread* next); +typedef void (*JKRThreadSwitch_PostCallback)(OSThread* current, OSThread* next); + +class JKRThreadSwitch +{ +public: + JKRThreadSwitch(JKRHeap*); + virtual void draw(JKRThreadName_* param_1, JUTConsole* param_2); + virtual void draw(JKRThreadName_* param_1); + virtual ~JKRThreadSwitch(); + + static JKRThreadSwitch* createManager(JKRHeap* heap); + + JKRThread* enter(JKRThread* param_1, int param_2); + static void callback(OSThread* param_1, OSThread* param_2); + + static u32 getTotalCount() { return sTotalCount; } + +private: + static JKRThreadSwitch* sManager; + static u32 sTotalCount; + static u64 sTotalStart; + static JKRThreadSwitch_PreCallback mUserPreCallback; + static JKRThreadSwitch_PostCallback mUserPostCallback; + +private: + JKRHeap* mHeap; // _04 + bool mSetNextHeap; // _08 + u8 _09[3]; // _09, padding? + u32 _0C; // _0C + u32 _10; // _10 + u8 _14[4]; // _14 - unknown/padding + s64 _18; // _18 + JUTConsole* mConsole; // _20 + JKRThreadName_* mThreadName; // _24 +}; + class JKRThread : public JKRDisposer { public: JKRThread(u32 stackSize, int msgCount, int threadPrio); JKRThread(OSThread* osThread, int msgCount); virtual ~JKRThread(); - __declspec(weak) virtual void* run(); + virtual void* run() { return nullptr; } static void* start(void* param); static JSUList* getList() { return &JKRThread::sThreadList; } @@ -55,4 +101,78 @@ protected: u32 mStackSize; }; +// Unused class, function definitions from Sunshine and MKDD +class JKRTask : public JKRThread +{ + typedef void (*RequestCallback)(void*); + + /** + * @fabricated + * @size{0xC} + */ + struct Request + { + RequestCallback mCb; + void* mArg; + void* mMsg; + }; + + JKRTask(); // unused/inlined + + virtual ~JKRTask(); // _08 + virtual void* run(); // _0C + + bool request(RequestCallback, void*, void*); + + static JKRTask* create(); + + // unused/inlined: + Request* searchBlank(); + void requestJam(RequestCallback, void*, void*); + void cancelAll(); + void createTaskEndMessageQueue(int, JKRHeap*); + void destroyTaskEndMessageQueue(); + void waitQueueMessageBlock(OSMessageQueue*, int*); + void waitQueueMessage(OSMessageQueue*, int*); + + OSMessage waitMessageBlock() + { + OSMessage msg; + OSReceiveMessage(&mMesgQueue, &msg, OS_MESSAGE_BLOCK); + return msg; + } + + void destroy(); + + // Unused + static OSMessage* sEndMesgBuffer; + static u32 sEndMesgBufSize; + + // u32 _78; // _78 + //JSULink mTaskLink; // _7C, this didn't exist yet + Request* mRequest; // _8C - ptr to request array + u32 mRequestCnt; // _90 - amount of requests + OSMessageQueue* mTaskMsgQueue; // _94 + + static JSUList sTaskList; + static u8 sEndMesgQueue[32]; // Unused +}; + +/** @unused */ +struct JKRIdleThread : public JKRThread +{ + virtual ~JKRIdleThread() {}; // _08 + virtual void* run() // _0C + { + while (true) + { + } + }; + virtual void destroy() {} // 0x10 + + static void create(JKRHeap*, int, u32); + + static JKRIdleThread* sThread; +}; + #endif diff --git a/include/JSystem/JSupport.h b/include/JSystem/JSupport.h new file mode 100644 index 00000000..1d973537 --- /dev/null +++ b/include/JSystem/JSupport.h @@ -0,0 +1,9 @@ +#ifndef JSYSTEM_JSUPPORT_H +#define JSYSTEM_JSUPPORT_H + +#include "types.h" + +inline u8 JSULoByte(u16 in) { return in & 0xff; } +inline u8 JSUHiByte(u16 in) { return in >> 8; } + +#endif \ No newline at end of file diff --git a/include/JSystem/JSupport/JSUFileInputStream.h b/include/JSystem/JSupport/JSUFileInputStream.h index 74c810f0..8fc085e5 100644 --- a/include/JSystem/JSupport/JSUFileInputStream.h +++ b/include/JSystem/JSupport/JSUFileInputStream.h @@ -9,7 +9,6 @@ class JSUFileInputStream : public JSURandomInputStream { public: JSUFileInputStream(JKRFile* file); - virtual ~JSUFileInputStream() { } virtual int readData(void* buf, s32 len); virtual int getLength() const { return ((JKRFile*)this->mObject)->getFileSize(); } virtual int getPosition() const { return this->mPosition; } diff --git a/include/JSystem/JUtility/JUTConsole.h b/include/JSystem/JUtility/JUTConsole.h new file mode 100644 index 00000000..5cfc5a04 --- /dev/null +++ b/include/JSystem/JUtility/JUTConsole.h @@ -0,0 +1,28 @@ +#ifndef _JSYSTEM_JUT_JUTCONSOLE_H +#define _JSYSTEM_JUT_JUTCONSOLE_H + +#include "va_args.h" + +class JUTConsole; // TODO + +#ifdef __cplusplus +extern "C" +{ +#endif +void JUTConsole_print_f_va_(JUTConsole*, const char*, va_list); + +JUTConsole* JUTGetReportConsole(); +void JUTSetReportConsole(JUTConsole*); +JUTConsole* JUTGetWarningConsole(); +void JUTSetWarningConsole(JUTConsole*); +void JUTReportConsole(const char*); +void JUTReportConsole_f(const char*, ...); +void JUTReportConsole_f_va(const char*, va_list); +void JUTWarningConsole(const char*); +void JUTWarningConsole_f(const char*, ...); +void JUTWarningConsole_f_va(const char*, va_list); +#ifdef __cplusplus +}; +#endif // ifdef __cplusplus + +#endif diff --git a/include/MSL_C/ctype.h b/include/MSL_C/ctype.h new file mode 100644 index 00000000..fdf79242 --- /dev/null +++ b/include/MSL_C/ctype.h @@ -0,0 +1,34 @@ +#ifndef _CTYPE_H +#define _CTYPE_H + +#include "types.h" +#include "MSL_C/locale.h" +#include "MSL_C/ctype_api.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + __declspec(weak) int isalpha(int __c); + __declspec(weak) int isdigit(int __c); + __declspec(weak) int isspace(int __c); + __declspec(weak) int isupper(int __c); + __declspec(weak) int isxdigit(int __c); + + __declspec(weak) int tolower(int __c); + __declspec(weak) int toupper(int __c); + + // added underscore to avoid naming conflicts + inline int _isalpha(int c) { return (int)(__ctype_map[(u8)c] & __letter); } + inline int _isdigit(int c) { return (int)(__ctype_map[(u8)c] & __digit); } + inline int _isspace(int c) { return (int)(__ctype_map[(u8)c] & __whitespace); } + inline int _isupper(int c) { return (int)(__ctype_map[(u8)c] & __upper_case); } + inline int _isxdigit(int c) { return (int)(__ctype_map[(u8)c] & __hex_digit); } + inline int _tolower(int c) { return (c == -1 ? -1 : (int)__lower_map[(u8)c]); } + inline int _toupper(int c) { return (c == -1 ? -1 : (int)__upper_map[(u8)c]); } + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/MSL_C/ctype_api.h b/include/MSL_C/ctype_api.h new file mode 100644 index 00000000..ba4ffbfb --- /dev/null +++ b/include/MSL_C/ctype_api.h @@ -0,0 +1,35 @@ +#ifndef _MSL_CTYPE_API_H +#define _MSL_CTYPE_API_H + +#include "types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif // ifdef __cplusplus + + extern unsigned char __ctype_map[256]; + extern unsigned char __lower_map[256]; + extern unsigned char __upper_map[256]; + +#define __control_char 0x01 +#define __motion_char 0x02 +#define __space_char 0x04 +#define __punctuation 0x08 +#define __digit 0x10 +#define __hex_digit 0x20 +#define __lower_case 0x40 +#define __upper_case 0x80 + +#define __letter (__lower_case | __upper_case) +#define __alphanumeric (__letter | __digit) +#define __graphic (__alphanumeric | __punctuation) +#define __printable (__graphic | __space_char) +#define __whitespace (__motion_char | __space_char) +#define __control (__motion_char | __control_char) + +#ifdef __cplusplus +}; +#endif // ifdef __cplusplus + +#endif diff --git a/include/MSL_C/locale.h b/include/MSL_C/locale.h new file mode 100644 index 00000000..f9cdf079 --- /dev/null +++ b/include/MSL_C/locale.h @@ -0,0 +1,130 @@ +#ifndef _LOCALE_H +#define _LOCALE_H + +#include "types.h" +//#include "stdlib.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + typedef int (*__decode_mbyte)(wchar_t *, const char *, size_t); + typedef int (*__encode_mbyte)(char *, wchar_t); + + struct lconv + { + char *decimal_point; + char *thousands_sep; + char *grouping; + char *mon_decimal_point; + char *mon_thousands_sep; + char *mon_grouping; + char *positive_sign; + char *negative_sign; + char *currency_symbol; + char frac_digits; + char p_cs_precedes; + char n_cs_precedes; + char p_sep_by_space; + char n_sep_by_space; + char p_sign_posn; + char n_sign_posn; + char *int_curr_symbol; + char int_frac_digits; + char int_p_cs_precedes; + char int_n_cs_precedes; + char int_p_sep_by_space; + char int_n_sep_by_space; + char int_p_sign_posn; + char int_n_sign_posn; + }; + + struct _loc_mon_cmpt + { + char CmptName[8]; + char *mon_decimal_point; + char *mon_thousands_sep; + char *mon_grouping; + char *positive_sign; + char *negative_sign; + char *currency_symbol; + char frac_digits; + char p_cs_precedes; + char n_cs_precedes; + char p_sep_by_space; + char n_sep_by_space; + char p_sign_posn; + char n_sign_posn; + char *int_curr_symbol; + char int_frac_digits; + char int_p_cs_precedes; + char int_n_cs_precedes; + char int_p_sep_by_space; + char int_n_sep_by_space; + char int_p_sign_posn; + char int_n_sign_posn; + }; + + struct _loc_num_cmpt + { + char CmptName[8]; + char *decimal_point; + char *thousands_sep; + char *grouping; + }; + + struct _loc_time_cmpt + { + char CmptName[8]; + char *am_pm; + char *DateTime_Format; + char *Twelve_hr_format; + char *Date_Format; + char *Time_Format; + char *Day_Names; + char *MonthNames; + char *TimeZone; + }; + + struct _loc_coll_cmpt + { + char CmptName[8]; + int char_start_value; + int char_coll_tab_size; + short char_spec_accents; + unsigned short *char_coll_table_ptr; + unsigned short *wchar_coll_seq_ptr; + }; + + struct _loc_ctype_cmpt + { + char CmptName[8]; + const unsigned short *ctype_map_ptr; + const unsigned char *upper_map_ptr; + const unsigned char *lower_map_ptr; + const unsigned short *wctype_map_ptr; + const wchar_t *wupper_map_ptr; + const wchar_t *wlower_map_ptr; + __decode_mbyte decode_mb; + __encode_mbyte encode_wc; + }; + + struct __locale + { + struct __locale *next_locale; + char locale_name[48]; + struct _loc_coll_cmpt *coll_cmpt_ptr; + struct _loc_ctype_cmpt *ctype_cmpt_ptr; + struct _loc_mon_cmpt *mon_cmpt_ptr; + struct _loc_num_cmpt *num_cmpt_ptr; + struct _loc_time_cmpt *time_cmpt_ptr; + }; + + extern struct __locale _current_locale; + extern struct lconv __lconv; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/MSL_C/rand.h b/include/MSL_C/rand.h index 205616fe..eccef3bf 100644 --- a/include/MSL_C/rand.h +++ b/include/MSL_C/rand.h @@ -2,7 +2,7 @@ #define RAND_H #include "types.h" -void srand (u32 seeed); +void srand(u32 seed); int rand(void); -#endif \ No newline at end of file +#endif diff --git a/include/types.h b/include/types.h index 01bcac30..763e946d 100644 --- a/include/types.h +++ b/include/types.h @@ -48,6 +48,11 @@ typedef u32 unknown; #define ALIGN_PREV(u, align) (u & (~(align-1))) #define ALIGN_NEXT(u, align) ((u + (align-1)) & (~(align-1))) +#define IS_ALIGNED(X, N) (((X) & ((N)-1)) == 0) +#define IS_NOT_ALIGNED(X, N) (((X) & ((N)-1)) != 0) + +#define FLAG_ON(V, F) (((V) & (F)) == 0) +#define FLAG_OFF(V, F) (((V) & (F)) != 0) #ifndef ATTRIBUTE_ALIGN #if defined(__MWERKS__) || defined(__GNUC__) diff --git a/src/JSystem/JKernel/JKRAram.cpp b/src/JSystem/JKernel/JKRAram.cpp new file mode 100644 index 00000000..898f43bd --- /dev/null +++ b/src/JSystem/JKernel/JKRAram.cpp @@ -0,0 +1,509 @@ +#include +#include + +#include "JSystem/JKernel/JKRDecomp.h" +#include "JSystem/JKernel/JKRDvdRipper.h" +#include "JSystem/JKernel/JKRExpHeap.h" +#include "JSystem/JSystem.h" +#include "_mem.h" + +JSUList JKRAram::sAramCommandList; +JKRAram* JKRAram::sAramObject; +u32 JKRAram::sSZSBufferSize = 0x400; + +JKRAram* JKRAram::create(u32 aram_audio_buffer_size, u32 aram_audio_graph_size, + s32 streamPriority, s32 decomp_priority, + s32 piece_priority) { + if (!sAramObject) { + sAramObject = new (JKRGetSystemHeap(), 0) + JKRAram(aram_audio_buffer_size, aram_audio_graph_size, piece_priority); + } + + JKRCreateAramStreamManager(streamPriority); + JKRCreateDecompManager(decomp_priority); + sAramObject->resume(); + return sAramObject; +} + +OSMessage JKRAram::sMessageBuffer[4] = { + nullptr, + nullptr, + nullptr, + nullptr, +}; + +OSMessageQueue JKRAram::sMessageQueue = { 0 }; + +JKRAram::JKRAram(u32 bufSize, u32 graphSize, s32 priority) + : JKRThread(0x4000, 0x10, priority) { + u32 aramBase = ARInit(mStackArray, ARRAY_COUNT(mStackArray)); + ARQInit(); + + u32 aramSize = ARGetSize(); + mAudioMemorySize = bufSize; + if (graphSize == 0xffffffff) { + mGraphMemorySize = aramSize - bufSize - aramBase; + mUserMemorySize = 0; + } + else { + mGraphMemorySize = graphSize; + mUserMemorySize = (aramSize - (bufSize + graphSize) - aramBase); + } + + mAudioMemoryPtr = ARAlloc(mAudioMemorySize); + mGraphMemoryPtr = ARAlloc(mGraphMemorySize); + + if (mUserMemorySize != 0) { // ternary? + mUserMemoryPtr = ARAlloc(mUserMemorySize); + } + else { + mUserMemoryPtr = nullptr; + } + + mAramHeap = new (JKRHeap::getSystemHeap(), 0) + JKRAramHeap(mGraphMemoryPtr, mGraphMemorySize); +} + +JKRAram::~JKRAram() { + sAramObject = nullptr; + if (mAramHeap) delete mAramHeap; +} + +void* JKRAram::run() { + int result; + JKRAMCommand* command; + JKRAramCommand* message; + OSInitMessageQueue(&sMessageQueue, sMessageBuffer, 4); + do { + OSReceiveMessage(&sMessageQueue, (OSMessage*)&message, OS_MESSAGE_BLOCK); + result = message->mActive; + command = (JKRAMCommand*)message->mArg; + delete message; + + switch (result) { + case 1: + JKRAramPiece::startDMA(command); + break; + } + } while (true); +} + +bool JKRAram::checkOkAddress(u8* addr, u32 size, JKRAramBlock* block, + u32 blockSize) { + if (!IS_ALIGNED((u32)addr, 0x20) && !IS_ALIGNED(size, 0x20)) { + JPANIC(225, ":::address not 32Byte aligned."); + return false; + } + + if (block) { + if (!IS_ALIGNED(block->getAddress() + blockSize, 0x20)) { + JPANIC(234, ":::address not 32Byte aligned."); + return false; + } + } + return true; +} + +void JKRAram::changeGroupIdIfNeed(u8* data, int groupId) { + JKRHeap* currentHeap = JKRGetCurrentHeap(); + if (currentHeap->getHeapType() == 'EXPH' && groupId >= 0) { + JKRExpHeap::CMemBlock* block = (JKRExpHeap::CMemBlock*)(data + -0x10); + block->newGroupId(groupId); + } +} + +JKRAramBlock* JKRAram::mainRamToAram(u8* buf, u32 address, u32 alignedSize, + JKRExpandSwitch expandSwitch, u32 fileSize, + JKRHeap* heap, int id) { + JKRAramBlock* block = nullptr; + checkOkAddress(buf, address, nullptr, 0); + if (expandSwitch == EXPAND_SWITCH_DECOMPRESS) { + expandSwitch = (JKRCheckCompressed(buf) == JKRCOMPRESSION_NONE) + ? EXPAND_SWITCH_DEFAULT + : EXPAND_SWITCH_DECOMPRESS; + } + if (expandSwitch == EXPAND_SWITCH_DECOMPRESS) { + u32 expandSize = JKRCheckCompressed(buf) != JKRCOMPRESSION_NONE + ? JKRDecompExpandSize(buf) + : 0; + if (fileSize == 0 || fileSize > expandSize) { + fileSize = expandSize; + } + if (address == 0) { + block = JKRAllocFromAram(fileSize, JKRAramHeap::Head); + if (block == nullptr) return nullptr; + + block->newGroupID(decideAramGroupId(id)); + address = block->getAddress(); + } + if (alignedSize == 0 || alignedSize > expandSize) alignedSize = expandSize; + + if (fileSize > alignedSize) fileSize = alignedSize; + + void* allocatedMem = JKRAllocFromHeap(heap, fileSize, -32); + if (allocatedMem == nullptr) { + if (block != nullptr) { + delete block; + } + block = nullptr; + } + else { + JKRDecompress(buf, (u8*)allocatedMem, fileSize, 0); + JKRAramPcs(0, (u32)allocatedMem, address, alignedSize, block); + JKRFreeToHeap(heap, allocatedMem); + block = block == nullptr ? (JKRAramBlock*)-1 : block; + } + } + else { + if (address == 0) { + block = JKRAllocFromAram(alignedSize, JKRAramHeap::Head); + block->newGroupID(decideAramGroupId(id)); + if (block == nullptr) return nullptr; + + address = block->getAddress(); + } + + JKRAramPcs(0, (u32)buf, address, alignedSize, block); + block = block == nullptr ? (JKRAramBlock*)-1 : block; + } + return block; +} + +JKRAramBlock* JKRAram::mainRamToAram(u8* buf, JKRAramBlock* block, + u32 alignedSize, + JKRExpandSwitch expandSwitch, u32 fileSize, + JKRHeap* heap, int id) { + checkOkAddress(buf, 0, block, 0); + + if (block == nullptr) { + return mainRamToAram(buf, (u32)0, alignedSize, expandSwitch, fileSize, heap, + id); + } + + u32 blockSize = block->getSize(); + + if (expandSwitch == EXPAND_SWITCH_DECOMPRESS) { + fileSize = fileSize >= blockSize ? blockSize : fileSize; + } + + alignedSize = alignedSize > blockSize ? blockSize : alignedSize; + + return mainRamToAram(buf, block->getAddress(), alignedSize, expandSwitch, + fileSize, heap, id); +} + +// TODO: figure out name of parameter 5 +u8* JKRAram::aramToMainRam(u32 address, u8* buf, u32 srcSize, + JKRExpandSwitch expandSwitch, u32 p5, JKRHeap* heap, + int id, u32* pSize) { + int compression = JKRCOMPRESSION_NONE; + if (pSize) *pSize = 0; + + checkOkAddress(buf, address, nullptr, 0); + + u32 expandSize; + if (expandSwitch == EXPAND_SWITCH_DECOMPRESS) { + u8 buffer[64]; + u8* bufPtr = (u8*)ALIGN_NEXT((u32)buffer, 32); + JKRAramPcs(1, address, (u32)bufPtr, sizeof(buffer) / 2, + nullptr); // probably change sizeof(buffer) / 2 to 32 + compression = JKRCheckCompressed(bufPtr); + expandSize = JKRDecompExpandSize(bufPtr); + } + + if (compression == JKRCOMPRESSION_YAZ0) // SZS + { + if (p5 != 0 && p5 < expandSize) expandSize = p5; + + if (buf == nullptr) buf = (u8*)JKRAllocFromHeap(heap, expandSize, 32); + if (buf == nullptr) + return nullptr; + else { + changeGroupIdIfNeed(buf, id); + JKRDecompressFromAramToMainRam(address, buf, srcSize, expandSize, 0); + if (pSize) { + *pSize = expandSize; + } + return buf; + } + } + else if (compression == JKRCOMPRESSION_YAY0) // SZP + { + u8* szpSpace = (u8*)JKRAllocFromHeap(heap, srcSize, -32); + if (szpSpace == nullptr) { + return nullptr; + } + else { + JKRAramPcs(1, address, (u32)szpSpace, srcSize, nullptr); + if (p5 != 0 && p5 < expandSize) expandSize = p5; + + u8* szpBuffer = + buf == nullptr ? (u8*)JKRAllocFromHeap(heap, expandSize, 32) : buf; + + if (szpBuffer == nullptr) { + JKRFree(szpSpace); + return nullptr; + } + else { + changeGroupIdIfNeed(szpBuffer, id); + JKRDecompress(szpSpace, szpBuffer, expandSize, 0); + JKRFreeToHeap(heap, szpSpace); + if (pSize) { + *pSize = expandSize; + } + return szpBuffer; + } + } + } + else // Not compressed or ASR + { + if (buf == nullptr) buf = (u8*)JKRAllocFromHeap(heap, srcSize, 32); + if (buf == nullptr) { + return nullptr; + } + else { + changeGroupIdIfNeed(buf, id); + JKRAramPcs(1, address, (u32)buf, srcSize, nullptr); + if (pSize != nullptr) { + *pSize = srcSize; + } + return buf; + } + } +} + +// TODO: figure out what p6 does +u8* JKRAram::aramToMainRam(JKRAramBlock* block, u8* buf, u32 bufSize, + u32 alignedBlockSize, JKRExpandSwitch expandSwitch, + u32 p6, JKRHeap* heap, int id, u32* pSize) { + int compression = JKRCOMPRESSION_NONE; + if (pSize) *pSize = 0; + + checkOkAddress(buf, 0, block, alignedBlockSize); + + if (block == nullptr) { + JPANIC(667, ":::Bad Aram Block specified.\n"); + } + + u32 freeSize = block->getSize(); + + if (alignedBlockSize >= freeSize) return nullptr; + + bufSize = bufSize == 0 ? freeSize : bufSize; + + if (alignedBlockSize + bufSize > freeSize) { + bufSize = freeSize - alignedBlockSize; + } + + return aramToMainRam(alignedBlockSize + block->getAddress(), buf, bufSize, + expandSwitch, p6, heap, id, pSize); +} + +static OSMutex decompMutex; + +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 isInitMutex; +static u32* tsPtr; +static u32 tsArea; + +static u8* firstSrcData(); +static u8* nextSrcData(u8* current); +static int decompSZS_subroutine(u8* src, u8* dest); + +void JKRAram::aramSync(JKRAMCommand*, int) { + // JUT_REPORT_MSG("bad aramSync\n"); +} + +int JKRDecompressFromAramToMainRam(u32 src, void* dst, u32 srcLength, + u32 dstLength, u32 offset) { + szpBuf = (u8*)JKRAllocFromSysHeap(SZP_BUFFERSIZE, 32); + + // JUT_ASSERT(szpBuf != 0); + + szpEnd = szpBuf + SZP_BUFFERSIZE; + if (offset != 0) { + refBuf = (u8*)JKRAllocFromSysHeap(0x1120, 0); + // JUT_ASSERT(refBuf != 0); + refEnd = refBuf + 0x1120; + refCurrent = refBuf; + } + else { + refBuf = nullptr; + } + + srcAddress = src; + srcOffset = 0; + transLeft = (srcLength != 0) ? srcLength : -1; + fileOffset = offset; + readCount = 0; + maxDest = dstLength; + + decompSZS_subroutine(firstSrcData(), (u8*)dst); + JKRFree(szpBuf); + + if (refBuf) { + JKRFree(refBuf); + } + + return 0; +} + +int decompSZS_subroutine(u8* src, u8* dest) { + u8* endPtr; + s32 validBitCount = 0; + s32 currCodeByte = 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++; + if (dest == endPtr) { + break; + } + } + *(refCurrent++) = *src; + if (refCurrent == refEnd) { + refCurrent = refBuf; + } + src++; + } + else { + *dest = *src; + dest++; + src++; + if (dest == endPtr) { + break; + } + } + readCount++; + } + else { + u32 dist = src[1] | (src[0] & 0x0f) << 8; + 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++; + 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++; + if (dest == endPtr) { + break; + } + readCount++; + numBytes--; + copySource++; + } while (numBytes != 0); + } + } + currCodeByte <<= 1; + validBitCount--; + } while (dest < endPtr); + return 0; +} + +static u8* firstSrcData() { + srcLimit = szpEnd - 0x19; + u8* buf = szpBuf; + u32 maxSize = (szpEnd - szpBuf); + u32 transSize = MIN(transLeft, maxSize); + + JKRAramPcs(1, srcAddress + srcOffset, (u32)buf, ALIGN_NEXT(transSize, 32), + nullptr); + + srcOffset += transSize; + transLeft -= transSize; + + return buf; +} + +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; + + memcpy(dest, current, left); + u32 transSize = (u32)(szpEnd - (dest + left)); + if (transSize > transLeft) transSize = transLeft; + // JUT_ASSERT(transSize > 0); + + JKRAramPcs(1, (u32)(srcAddress + srcOffset), ((u32)dest + left), + ALIGN_NEXT(transSize, 0x20), nullptr); + 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 new file mode 100644 index 00000000..f28a2917 --- /dev/null +++ b/src/JSystem/JKernel/JKRAramArchive.cpp @@ -0,0 +1,311 @@ +#include +#include + +#include "JSystem/JKernel/JKRAram.h" +#include "JSystem/JKernel/JKRArchive.h" +#include "JSystem/JKernel/JKRDecomp.h" +#include "JSystem/JKernel/JKRDvdAramRipper.h" +#include "JSystem/JKernel/JKRDvdRipper.h" +#include "JSystem/JSystem.h" +#include "JSystem/JUtility/JUTAssertion.h" + +JKRAramArchive::JKRAramArchive() : JKRArchive() {} + +JKRAramArchive::JKRAramArchive(s32 entryNum, EMountDirection mountDirection) + : JKRArchive(entryNum, MOUNT_ARAM) { + mMountDirection = mountDirection; + if (!open(entryNum)) { + return; + } + else { + mVolumeType = 'RARC'; + mVolumeName = &mStrTable[mDirectories->mOffset]; + sVolumeList.prepend(&mFileLoaderLink); + mIsMounted = true; + } +} + +JKRAramArchive::~JKRAramArchive() { + if (mIsMounted == true) { + if (mArcInfoBlock) { + SDIFileEntry* fileEntries = mFileEntries; + for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) { + if (fileEntries->mData != nullptr) { + JKRFreeToHeap(mHeap, fileEntries->mData); + } + fileEntries++; + } + JKRFreeToHeap(mHeap, mArcInfoBlock); + mArcInfoBlock = nullptr; + } + + if (mDvdFile) { + delete mDvdFile; + } + if (mBlock) { + delete mBlock; + } + + sVolumeList.remove(&mFileLoaderLink); + mIsMounted = false; + } +} + +void JKRAramArchive::fixedInit(s32 entryNum, EMountDirection direction) { + mIsMounted = false; + mMountDirection = direction; + mMountMode = 2; + mMountCount = 1; + _54 = 2; + mHeap = JKRGetCurrentHeap(); + mEntryNum = entryNum; + + if (sCurrentVolume) return; + sCurrentVolume = this; + sCurrentDirID = 0; +} + +bool JKRAramArchive::mountFixed(s32 entryNum, EMountDirection direction) { + if (entryNum < 0) return false; + + if (check_mount_already(entryNum)) return false; + + fixedInit(entryNum, direction); + if (open(entryNum) == false) { + return false; + } + + mVolumeType = 'RARC'; + mVolumeName = &mStrTable[mDirectories->mOffset]; + sVolumeList.prepend(&mFileLoaderLink); + mIsMounted = true; + return true; +} + +bool JKRAramArchive::mountFixed(const char* path, EMountDirection direction) { + s32 entrynum = DVDConvertPathToEntrynum((char*)path); + return mountFixed(entrynum, direction); +} + +void JKRAramArchive::unmountFixed() { + if (sCurrentVolume == this) sCurrentVolume = nullptr; + + if (mArcInfoBlock) { + SDIFileEntry* fileEntries = mFileEntries; + for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) { + if (fileEntries->mData != nullptr) { + JKRFreeToHeap(mHeap, fileEntries->mData); + } + fileEntries++; + } + JKRFreeToHeap(mHeap, mArcInfoBlock); + mArcInfoBlock = nullptr; + } + + if (mDvdFile) delete mDvdFile; + + if (mBlock) delete mBlock; + + sVolumeList.remove(&mFileLoaderLink); + mIsMounted = false; +} + +#ifdef DEBUG +CW_FORCE_STRINGS(JKRAramArchive_cpp, __FILE__, "isMounted()", + "mMountCount == 1") +#endif + + bool JKRAramArchive::open(long entryNum) { + mArcInfoBlock = nullptr; + mDirectories = nullptr; + mFileEntries = nullptr; + mStrTable = nullptr; + mBlock = nullptr; + + mDvdFile = + new (JKRGetSystemHeap(), mMountDirection == MOUNT_DIRECTION_HEAD ? 4 : -4) + JKRDvdFile(entryNum); + if (mDvdFile == nullptr) { + mMountMode = 0; + return 0; + } + + // NOTE: a different struct is used here for sure, unfortunately i can't get + // any hits on this address, so gonna leave it like this for now + SArcHeader* mem = (SArcHeader*)JKRAllocFromSysHeap(32, -32); + if (mem == nullptr) { + mMountMode = 0; + } + else { + JKRDvdToMainRam(entryNum, (u8*)mem, EXPAND_SWITCH_DECOMPRESS, 32, nullptr, + JKRDvdRipper::ALLOC_DIR_TOP, 0, &mCompression); + int alignment = mMountDirection == MOUNT_DIRECTION_HEAD ? 32 : -32; + u32 alignedSize = ALIGN_NEXT(mem->file_data_offset, 32); + mArcInfoBlock = + (SArcDataInfo*)JKRAllocFromHeap(mHeap, alignedSize, alignment); + if (mArcInfoBlock == nullptr) { + mMountMode = 0; + } + else { + JKRDvdToMainRam(entryNum, (u8*)mArcInfoBlock, EXPAND_SWITCH_DECOMPRESS, + alignedSize, nullptr, JKRDvdRipper::ALLOC_DIR_TOP, 32, + nullptr); + + mDirectories = + (SDIDirEntry*)((u8*)mArcInfoBlock + mArcInfoBlock->node_offset); + mFileEntries = (SDIFileEntry*)((u8*)mArcInfoBlock + + mArcInfoBlock->file_entry_offset); + mStrTable = (const char*)((u8*)mArcInfoBlock + + mArcInfoBlock->string_table_offset); + + u32 aramSize = ALIGN_NEXT(mem->file_data_length, 32); + mBlock = + JKRAllocFromAram(aramSize, mMountDirection == MOUNT_DIRECTION_HEAD + ? JKRAramHeap::Head + : JKRAramHeap::Tail); + if (mBlock == nullptr) { + mMountMode = 0; + } + else { + JKRDvdToAram(entryNum, mBlock->getAddress(), EXPAND_SWITCH_DECOMPRESS, + mem->header_length + mem->file_data_offset, 0); + } + } + } +cleanup: + if (mem != nullptr) { + JKRFreeToSysHeap(mem); + } + if (mMountMode == 0) { + JREPORTF(":::[%s: %d] Cannot alloc memory\n", __FILE__, + 415); // TODO: macro + } + return mMountMode != 0; +} + +void* JKRAramArchive::fetchResource(SDIFileEntry* fileEntry, u32* pSize) { + JUT_ASSERT(isMounted()); + + u32 sizeRef; + u8* data; + + if (fileEntry->mData) { + if (pSize) *pSize = fileEntry->mSize; + } + else { + u32 addres = mBlock->getAddress(); + int compression = JKRConvertAttrToCompressionType(fileEntry->mFlag >> 0x18); + u32 size = + fetchResource_subroutine(fileEntry->mDataOffset + addres, + fileEntry->mSize, mHeap, compression, &data); + if (pSize) *pSize = size; + fileEntry->mData = (void*)data; + } + + return fileEntry->mData; +} + +void* JKRAramArchive::fetchResource(void* data, u32 compressedSize, + SDIFileEntry* fileEntry, u32* pSize, + JKRExpandSwitch expandSwitch) { + JUT_ASSERT(isMounted()); + u32 fileSize = fileEntry->mSize; + if (fileSize > compressedSize) { + fileSize = compressedSize; + } + if (fileEntry->mData) { + JKRHeap::copyMemory(data, fileEntry->mData, fileSize); + } + else { + int compression = JKRConvertAttrToCompressionType(fileEntry->mFlag >> 0x18); + if (expandSwitch != EXPAND_SWITCH_DECOMPRESS) compression = 0; + + fileSize = fetchResource_subroutine( + fileEntry->mDataOffset + mBlock->getAddress(), fileSize, (u8*)data, + compressedSize, compression); + } + + if (pSize != nullptr) { + *pSize = fileSize; + } + return data; +} + +u32 JKRAramArchive::getAramAddress_Entry(SDIFileEntry* fileEntry) { + JUT_ASSERT(isMounted()); + + if (fileEntry == nullptr) { + return 0; + } + return fileEntry->mDataOffset + mBlock->getAddress(); +} + +u32 JKRAramArchive::getAramAddress(u32 type, const char* file) { + SDIFileEntry* entry = findTypeResource(type, file); + return getAramAddress_Entry(entry); +} + +u32 JKRAramArchive::fetchResource_subroutine(u32 srcAram, u32 size, u8* data, + u32 expandSize, int compression) { + JUT_ASSERT((srcAram & 0x1f) == 0); + + u32 sizeRef; + + u32 alignedSize = ALIGN_NEXT(size, 32); + u32 prevAlignedSize = ALIGN_PREV(expandSize, 32); + switch (compression) { + case JKRCOMPRESSION_NONE: + if (alignedSize > prevAlignedSize) { + alignedSize = prevAlignedSize; + } + JKRAramToMainRam(srcAram, data, alignedSize, EXPAND_SWITCH_DEFAULT, + prevAlignedSize, nullptr, -1, &sizeRef); + return sizeRef; + case JKRCOMPRESSION_YAY0: + case JKRCOMPRESSION_YAZ0: + JKRAramToMainRam(srcAram, data, alignedSize, EXPAND_SWITCH_DECOMPRESS, + prevAlignedSize, nullptr, -1, &sizeRef); + return sizeRef; + default: + JPANIC(550, ":::??? bad sequence\n"); + return 0; + } +} + +u32 JKRAramArchive::fetchResource_subroutine(u32 srcAram, u32 size, + JKRHeap* heap, int compression, + u8** pBuf) { + u32 resSize; + u32 alignedSize = ALIGN_NEXT(size, 32); + + u8* buffer; + switch (compression) { + case JKRCOMPRESSION_NONE: + buffer = (u8*)JKRAllocFromHeap(heap, alignedSize, 32); + JUT_ASSERT(buffer != 0); + + JKRAramToMainRam(srcAram, buffer, alignedSize, EXPAND_SWITCH_DEFAULT, + alignedSize, nullptr, -1, nullptr); + *pBuf = buffer; + + return size; + case JKRCOMPRESSION_YAY0: + case JKRCOMPRESSION_YAZ0: + u8* header = (u8*)JKRAllocFromHeap(heap, 0x20, 0x20); + JKRAramToMainRam(srcAram, header, 0x20, EXPAND_SWITCH_DEFAULT, 0, nullptr, + -1, nullptr); + u32 expandSize = JKRDecompExpandSize(header); + JKRFreeToHeap(heap, header); + expandSize = ALIGN_NEXT(expandSize, 32); + buffer = (u8*)JKRAllocFromHeap(heap, expandSize, 0x20); + JUT_ASSERT(buffer); + + JKRAramToMainRam(srcAram, buffer, alignedSize, EXPAND_SWITCH_DECOMPRESS, + expandSize, heap, -1, &resSize); + *pBuf = buffer; + return resSize; + default: + JPANIC(605, ":::??? bad sequence\n"); + return 0; + } +} diff --git a/src/JSystem/JKernel/JKRAramBlock.cpp b/src/JSystem/JKernel/JKRAramBlock.cpp index 903f1da1..b035869d 100644 --- a/src/JSystem/JKernel/JKRAramBlock.cpp +++ b/src/JSystem/JKernel/JKRAramBlock.cpp @@ -1,14 +1,13 @@ #include "JSystem/JKernel/JKRAram.h" -JKRAramBlock::JKRAramBlock(u32 address, u32 size, u32 freeSize, u8 groupID, bool tempMemory) - : mLink(this) - , mAddress(address) - , mSize(size) - , mFreeSize(freeSize) - , mGroupID(groupID) - , mIsTempMemory(tempMemory) - { - } +JKRAramBlock::JKRAramBlock(u32 address, u32 size, u32 freeSize, u8 groupID, + bool tempMemory) + : mLink(this), + mAddress(address), + mSize(size), + mFreeSize(freeSize), + mGroupID(groupID), + mIsTempMemory(tempMemory) {} JKRAramBlock::~JKRAramBlock() { JSULink* prev = this->mLink.getPrev(); @@ -28,7 +27,8 @@ JKRAramBlock* JKRAramBlock::allocHead(u32 size, u8 groupID, JKRAramHeap* heap) { u32 address = this->mAddress + this->mSize; u32 freeSize = this->mFreeSize - size; - JKRAramBlock* block = new(heap->mHeap, nullptr) JKRAramBlock(address, size, freeSize, groupID, false); + JKRAramBlock* block = new (heap->mHeap, nullptr) + JKRAramBlock(address, size, freeSize, groupID, false); this->mFreeSize = 0; this->mLink.mPtrList->insert(this->mLink.mNext, &block->mLink); return block; @@ -37,7 +37,8 @@ JKRAramBlock* JKRAramBlock::allocHead(u32 size, u8 groupID, JKRAramHeap* heap) { JKRAramBlock* JKRAramBlock::allocTail(u32 size, u8 groupID, JKRAramHeap* heap) { u32 address = this->mAddress + this->mSize + this->mFreeSize - size; - JKRAramBlock* block = new(heap->mHeap, nullptr) JKRAramBlock(address, size, 0, groupID, true); + JKRAramBlock* block = + new (heap->mHeap, nullptr) JKRAramBlock(address, size, 0, groupID, true); this->mFreeSize -= size; this->mLink.mPtrList->insert(this->mLink.mNext, &block->mLink); return block; diff --git a/src/JSystem/JKernel/JKRAramHeap.cpp b/src/JSystem/JKernel/JKRAramHeap.cpp index e0ca7e8f..85fe39cf 100644 --- a/src/JSystem/JKernel/JKRAramHeap.cpp +++ b/src/JSystem/JKernel/JKRAramHeap.cpp @@ -12,13 +12,13 @@ JKRAramHeap::JKRAramHeap(u32 baseAddress, u32 size) : JKRDisposer() { this->mTailAddress = this->mHeadAddress + this->mSize; this->mGroupID = 0xFF; JKRAramBlock* block = new (this->mHeap, nullptr) - JKRAramBlock(this->mHeadAddress, 0, this->mSize, 0xFF, false); + JKRAramBlock(this->mHeadAddress, 0, this->mSize, 0xFF, false); sAramList.append(&block->mLink); } JKRAramHeap::~JKRAramHeap() { for (JSUListIterator it = sAramList.getFirst(); - it != sAramList.getEnd();) { + it != sAramList.getEnd();) { delete (it++).getObject(); } } @@ -29,7 +29,8 @@ JKRAramBlock* JKRAramHeap::alloc(u32 size, JKRAramHeap::EAllocMode mode) { if (mode == Head) { block = this->allocFromHead(size); - } else { + } + else { block = this->allocFromTail(size); } @@ -37,10 +38,9 @@ JKRAramBlock* JKRAramHeap::alloc(u32 size, JKRAramHeap::EAllocMode mode) { return block; } -/* Code retrieved from Twilight Princess Debug version & matched. Unused in AC. */ -void JKRAramHeap::free(JKRAramBlock* block) { - delete block; -} +/* Code retrieved from Twilight Princess Debug version & matched. Unused in AC. + */ +void JKRAramHeap::free(JKRAramBlock* block) { delete block; } JKRAramBlock* JKRAramHeap::allocFromHead(u32 size) { size = ALIGN_NEXT(size, 32); @@ -48,7 +48,7 @@ JKRAramBlock* JKRAramHeap::allocFromHead(u32 size) { JKRAramBlock* block = nullptr; for (JSUListIterator it = sAramList.getFirst(); - it != sAramList.getEnd(); it++) { + it != sAramList.getEnd(); it++) { JKRAramBlock* n_block = it.getObject(); if (n_block->mFreeSize >= size && min_size > n_block->mFreeSize) { min_size = n_block->mFreeSize; @@ -71,7 +71,7 @@ JKRAramBlock* JKRAramHeap::allocFromTail(u32 size) { size = ALIGN_NEXT(size, 32); for (JSUListIterator it = sAramList.getLast(); - it != sAramList.getEnd(); it--) { + it != sAramList.getEnd(); it--) { JKRAramBlock* n_block = it.getObject(); if (n_block->mFreeSize >= size) { @@ -96,23 +96,23 @@ void JKRAramHeap::dump() { JREPORT(" attr address: size gid\n"); for (JSUListIterator listItr = sAramList.getFirst(); - listItr != sAramList.getEnd(); listItr++) { + listItr != sAramList.getEnd(); listItr++) { if (listItr->mSize != 0) { JREPORTF("%s %08x: %08x %3d\n", - listItr->isTempMemory() ? " temp" : "alloc", listItr->mAddress, - listItr->mSize, listItr->mGroupID); + listItr->isTempMemory() ? " temp" : "alloc", listItr->mAddress, + listItr->mSize, listItr->mGroupID); } if (listItr->mFreeSize != 0) { JREPORTF(" free %08x: %08x 0\n", listItr->mAddress + listItr->mSize, - listItr->mFreeSize); + listItr->mFreeSize); } total_used += listItr->mSize; } JREPORTF("%d / %d bytes (%6.2f%%) used\n", total_used, this->mSize, - (f32)total_used / (f32)this->mSize); + (f32)total_used / (f32)this->mSize); this->unlock(); } @@ -122,7 +122,8 @@ u32 JKRAramHeap::getFreeSize() { u32 max_free = 0; this->lock(); - for (JSUListIterator it = sAramList.getFirst(); it != sAramList.getEnd(); it++) { + for (JSUListIterator it = sAramList.getFirst(); + it != sAramList.getEnd(); it++) { if (it->mFreeSize > max_free) { max_free = it->mFreeSize; } @@ -137,7 +138,8 @@ u32 JKRAramHeap::getTotalFreeSize() { u32 total_free = 0; this->lock(); - for (JSUListIterator it = sAramList.getFirst(); it != sAramList.getEnd(); it++) { + for (JSUListIterator it = sAramList.getFirst(); + it != sAramList.getEnd(); it++) { total_free += it->mFreeSize; } @@ -154,7 +156,8 @@ u32 JKRAramHeap::getUsedSize(u8 groupID) { total_used = this->mSize - this->getTotalFreeSize(); } else { - for (JSUListIterator it = sAramList.getFirst(); it != sAramList.getEnd(); it++) { + for (JSUListIterator it = sAramList.getFirst(); + it != sAramList.getEnd(); it++) { if (groupID == it->mGroupID) { total_used += it->mSize; } diff --git a/src/JSystem/JKernel/JKRAramPiece.cpp b/src/JSystem/JKernel/JKRAramPiece.cpp index 01f155ca..31acd78b 100644 --- a/src/JSystem/JKernel/JKRAramPiece.cpp +++ b/src/JSystem/JKernel/JKRAramPiece.cpp @@ -1,19 +1,20 @@ -#include "types.h" +#include "JSystem/JKernel/JKRAram.h" +#include "JSystem/JKernel/JKRDecomp.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "JSystem/JKernel/JKRMacro.h" +#include "JSystem/JSystem.h" #include "dolphin/ar.h" +#include "dolphin/os.h" /* TODO: OSReport lives in libforest in AC */ #include "dolphin/os/OSCache.h" #include "dolphin/os/OSMessage.h" -#include "dolphin/os.h" /* TODO: OSReport lives in libforest in AC */ -#include "JSystem/JKernel/JKRMacro.h" -#include "JSystem/JKernel/JKRHeap.h" -#include "JSystem/JKernel/JKRDecomp.h" -#include "JSystem/JSystem.h" - -#include "JSystem/JKernel/JKRAram.h" +#include "types.h" JSUList JKRAramPiece::sAramPieceCommandList; OSMutex JKRAramPiece::mMutex; -JKRAMCommand* JKRAramPiece::prepareCommand(int direction, u32 source, u32 destination, u32 length, JKRAramBlock* aramBlock, JKRAMCommand::AMCommandCallback callback) { +JKRAMCommand* JKRAramPiece::prepareCommand( + int direction, u32 source, u32 destination, u32 length, + JKRAramBlock* aramBlock, JKRAMCommand::AMCommandCallback callback) { JKRAMCommand* cmd = new (JKRGetSystemHeap(), -4) JKRAMCommand(); cmd->mDirection = direction; cmd->mSource = source; @@ -29,7 +30,9 @@ void JKRAramPiece::sendCommand(JKRAMCommand* cmd) { JKRAramPiece::startDMA(cmd); } -JKRAMCommand* JKRAramPiece::orderAsync(int direction, u32 source, u32 destination, u32 length, JKRAramBlock* aramBlock, JKRAMCommand::AMCommandCallback callback) { +JKRAMCommand* JKRAramPiece::orderAsync( + int direction, u32 source, u32 destination, u32 length, + JKRAramBlock* aramBlock, JKRAMCommand::AMCommandCallback callback) { JKRAramPiece::lock(); if (!JKR_ISALIGNED32(source) || !JKR_ISALIGNED32(destination)) { @@ -41,9 +44,11 @@ JKRAMCommand* JKRAramPiece::orderAsync(int direction, u32 source, u32 destinatio } JKRAramCommand* aramCmd = new (JKRGetSystemHeap(), -4) JKRAramCommand(); - JKRAMCommand* cmd = JKRAramPiece::prepareCommand(direction, source, destination, length, aramBlock, callback); + JKRAMCommand* cmd = JKRAramPiece::prepareCommand( + direction, source, destination, length, aramBlock, callback); aramCmd->setting(TRUE, cmd); - OSSendMessage((OSMessageQueue*)&JKRAram::sMessageQueue, (OSMessage)aramCmd, OS_MESSAGE_BLOCK); + OSSendMessage((OSMessageQueue*)&JKRAram::sMessageQueue, (OSMessage)aramCmd, + OS_MESSAGE_BLOCK); if (cmd->mCallback != nullptr) { JKRAramPiece::sAramPieceCommandList.append(&cmd->mAramPieceCommandLink); } @@ -76,11 +81,12 @@ bool JKRAramPiece::sync(JKRAMCommand* cmd, BOOL noBlock) { } } - -bool JKRAramPiece::orderSync(int direction, u32 source, u32 destination, u32 length, JKRAramBlock* aramBlock) { +bool JKRAramPiece::orderSync(int direction, u32 source, u32 destination, + u32 length, JKRAramBlock* aramBlock) { JKRAramPiece::lock(); - JKRAMCommand* cmd = JKRAramPiece::orderAsync(direction, source, destination, length, aramBlock, nullptr); + JKRAMCommand* cmd = JKRAramPiece::orderAsync(direction, source, destination, + length, aramBlock, nullptr); bool res = JKRAramPiece::sync(cmd, FALSE); delete cmd; @@ -96,7 +102,8 @@ void JKRAramPiece::startDMA(JKRAMCommand* cmd) { DCStoreRange((u8*)cmd->mSource, cmd->mLength); } - ARQPostRequest(cmd, 0, cmd->mDirection, 0, cmd->mSource, cmd->mDestination, cmd->mLength, JKRAramPiece::doneDMA); + ARQPostRequest(cmd, 0, cmd->mDirection, 0, cmd->mSource, cmd->mDestination, + cmd->mLength, JKRAramPiece::doneDMA); } void JKRAramPiece::doneDMA(u32 param) { @@ -115,7 +122,8 @@ void JKRAramPiece::doneDMA(u32 param) { } else { if (cmd->mCompletedMesgQueue != nullptr) { - OSSendMessage(cmd->mCompletedMesgQueue, (OSMessage)cmd, OS_MESSAGE_NOBLOCK); + OSSendMessage(cmd->mCompletedMesgQueue, (OSMessage)cmd, + OS_MESSAGE_NOBLOCK); } else { OSSendMessage(&cmd->mMesgQueue, (OSMessage)cmd, OS_MESSAGE_NOBLOCK); diff --git a/src/JSystem/JKernel/JKRAramStream.cpp b/src/JSystem/JKernel/JKRAramStream.cpp index d4df110a..77a4295e 100644 --- a/src/JSystem/JKernel/JKRAramStream.cpp +++ b/src/JSystem/JKernel/JKRAramStream.cpp @@ -1,4 +1,215 @@ -#include "JKRAram.h" -#include "JSUStream.h" +#include +#include "JSystem/JKernel/JKRAram.h" +#include "JSystem/JSupport/JSUStream.h" +#include "JSystem/JSystem.h" +#include "JSystem/JUtility/JUTAssertion.h" +#include "types.h" +// From Pikmin Repo + +OSMessage JKRAramStream::sMessageBuffer[4] = { 0 }; +OSMessageQueue JKRAramStream::sMessageQueue = { 0 }; + +JKRAramStream* JKRAramStream::sAramStreamObject = nullptr; +u8* JKRAramStream::transBuffer = nullptr; +u32 JKRAramStream::transSize = nullptr; +JKRHeap* JKRAramStream::transHeap = nullptr; + +JKRAramStream* JKRAramStream::create(s32 param) { + if (JKRAramStream::sAramStreamObject == nullptr) { + JKRAramStream::sAramStreamObject = + new (JKRGetSystemHeap(), 0) JKRAramStream(param); + setTransBuffer(nullptr, 0, nullptr); + } + return JKRAramStream::sAramStreamObject; +} + +JKRAramStream::JKRAramStream(s32 priority) : JKRThread(0x4000, 0x10, priority) { + OSResumeThread(mThreadRecord); +} + +JKRAramStream::~JKRAramStream() {}; + +void* JKRAramStream::run() { + OSMessage result; + OSInitMessageQueue( + &JKRAramStream::sMessageQueue, JKRAramStream::sMessageBuffer, + ARRAY_COUNT(sMessageBuffer)); // jank cast to void** to satisfy prototype + while (true) { + OSReceiveMessage(&JKRAramStream::sMessageQueue, &result, OS_MESSAGE_BLOCK); + JKRAramStreamCommand* command = static_cast(result); + switch (command->type) { + case JKRAramStreamCommand::ECT_READ: + readFromAram(); + break; + case JKRAramStreamCommand::ECT_WRITE: + writeToAram(command); + break; + } + } +} + +u32 JKRAramStream::readFromAram() { + return 1; +} // probably a define evaluating to 1 + +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 == nullptr) ? 0x8000 : bufferSize; + + command->mTransferBufferSize = bufferSize; + command->mAllocatedTransferBuffer = false; + } + else { + bufferSize = (bufferSize == nullptr) ? 0x8000 : bufferSize; + + if (heap) { + buffer = (u8*)JKRAllocFromHeap(heap, bufferSize, -0x20); + command->mTransferBuffer = buffer; + } + else { + buffer = (u8*)JKRAllocFromHeap(nullptr, bufferSize, -0x20); + command->mTransferBuffer = buffer; + } + + command->mTransferBufferSize = bufferSize; + command->mAllocatedTransferBuffer = true; + } + + if (!buffer) { + if (!heap) { + JKRGetCurrentHeap()->dump(); + } + else { + heap->dump(); + } + JPANIC(169, "abort\n"); + } + + if (buffer) { + command->mStream->seek(offset, SEEK_SET); + while (dstSize != 0) { + u32 length = (dstSize > bufferSize) ? bufferSize : dstSize; + + s32 readLength = command->mStream->read(buffer, length); + + JKRAramPcs(0, (u32)buffer, destination, length, nullptr); + dstSize -= length; + writtenLength += length; + destination += length; + } + + if (command->mAllocatedTransferBuffer) { + JKRFree(buffer); + command->mAllocatedTransferBuffer = false; + } + } + + OSSendMessage(&command->mMessageQueue, (OSMessage)writtenLength, + OS_MESSAGE_NOBLOCK); + return writtenLength; +}; + +/* + * Unused function, made-up contents. Do not take this seriously! + * While the function exists in the map, this is almost certainly incorrect. + * Should exist to generate JSURandomInputStream::getAvailable() const + * afterwards. + */ +JKRAramStreamCommand* JKRAramStream::write_StreamToAram_Async( + JSUFileInputStream* stream, JKRAramBlock* addr, u32 size, u32 offset) { + JKRAramStreamCommand* command = + new (JKRGetSystemHeap(), -4) JKRAramStreamCommand(); + command->type = JKRAramStreamCommand::ECT_WRITE; + command->mAddress = (u32)addr; + command->mSize = size; + command->mStream = stream; + command->_28 = stream->getAvailable(); + 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; +} + +JKRAramStreamCommand* JKRAramStream::write_StreamToAram_Async( + JSUFileInputStream* stream, u32 addr, u32 size, u32 offset) { + JKRAramStreamCommand* command = + new (JKRGetSystemHeap(), -4) JKRAramStreamCommand(); + command->type = JKRAramStreamCommand::ECT_WRITE; + command->mAddress = addr; + command->mSize = size; + command->mStream = stream; + command->_28 = 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; +} + +JKRAramStreamCommand* JKRAramStream::sync(JKRAramStreamCommand* command, + BOOL isNonBlocking) { + OSMessage msg; + if (isNonBlocking == FALSE) { + OSReceiveMessage(&command->mMessageQueue, &msg, OS_MESSAGE_BLOCK); + if (msg == nullptr) { + command = nullptr; + return command; + } + else { + return command; + } + } + else { + BOOL receiveResult = + OSReceiveMessage(&command->mMessageQueue, &msg, OS_MESSAGE_NOBLOCK); + if (receiveResult == FALSE) { + command = nullptr; + return command; + } + else if (msg == nullptr) { + command = nullptr; + return command; + } + else { + return command; + } + } +} + +void JKRAramStream::setTransBuffer(u8* buffer, u32 bufferSize, JKRHeap* heap) { + transBuffer = nullptr; + transSize = 0x8000; + transHeap = nullptr; + + if (buffer) { + transBuffer = (u8*)ALIGN_NEXT((u32)buffer, 0x20); + } + + if (bufferSize) { + transSize = ALIGN_PREV(bufferSize, 0x20); + } + + if (heap && !buffer) { + transHeap = heap; + } +} + +JKRAramStreamCommand::JKRAramStreamCommand() { + mAllocatedTransferBuffer = false; +} diff --git a/src/JSystem/JKernel/JKRArchivePri.cpp b/src/JSystem/JKernel/JKRArchivePri.cpp new file mode 100644 index 00000000..547d1eb1 --- /dev/null +++ b/src/JSystem/JKernel/JKRArchivePri.cpp @@ -0,0 +1,242 @@ +#include +#include + +#include "JSystem/JKernel/JKRArchive.h" +#include "JSystem/JKernel/JKRFileLoader.h" +#include "types.h" + +u32 JKRArchive::sCurrentDirID; + +JKRArchive::JKRArchive() +{ + mIsMounted = false; + mMountDirection = MOUNT_DIRECTION_HEAD; +} + +JKRArchive::JKRArchive(s32 entryNum, JKRArchive::EMountMode mountMode) + : JKRFileLoader() +{ + mIsMounted = false; + mMountMode = mountMode; + mMountCount = 1; + _54 = 1; + mHeap = JKRHeap::findFromRoot(this); + if (!mHeap) + { + mHeap = JKRHeap::sCurrentHeap; + } + mEntryNum = entryNum; + if (sCurrentVolume == nullptr) + { + sCurrentDirID = 0; + sCurrentVolume = this; + } +} + +JKRArchive::JKRArchive(const char* p1, JKRArchive::EMountMode mountMode) +{ + // UNUSED FUNCTION +} + +JKRArchive::~JKRArchive() {} + +bool JKRArchive::isSameName(JKRArchive::CArcName& archiveName, + u32 nameTableOffset, u16 hash) const +{ + u16 arcHash = archiveName.getHash(); + if (arcHash != hash) + return false; + + return strcmp(&mStrTable[nameTableOffset], archiveName.getString()) == 0; +} + +JKRArchive::SDIDirEntry* JKRArchive::findResType(u32 type) const +{ + SDIDirEntry* dirEntry = mDirectories; + for (u32 i = 0; i < mArcInfoBlock->num_nodes; i++, dirEntry++) + { + if (dirEntry->mType == type) + { + return dirEntry; + } + } + return nullptr; +} + +JKRArchive::SDIDirEntry* JKRArchive::findDirectory(const char* path, + u32 index) const +{ + if (path == nullptr) + { + return &mDirectories[index]; + } + + CArcName arcName(&path, '/'); + SDIDirEntry* dirEntry = &mDirectories[index]; + SDIFileEntry* entry = &mFileEntries[dirEntry->mFirstIdx]; + + for (int i = 0; i < dirEntry->mNum; entry++, i++) + { + if (isSameName(arcName, entry->mFlag & 0xFFFFFF, entry->mHash)) + { + if ((entry->mFlag >> 24) & 0x02) + { + return findDirectory(path, entry->mDataOffset); + } + break; + } + } + + return nullptr; +} + +JKRArchive::SDIFileEntry* JKRArchive::findTypeResource(u32 type, + const char* name) const +{ + if (type != 0) + { + CArcName arcName; + arcName.store(name); + SDIDirEntry* dirEntry = findResType(type); + if (dirEntry != nullptr) + { + SDIFileEntry* fileEntry = mFileEntries + dirEntry->mFirstIdx; + for (int i = 0; i < dirEntry->mNum; fileEntry++, i++) + { + if (isSameName(arcName, fileEntry->mFlag & 0xFFFFFF, + fileEntry->mHash)) + { + return fileEntry; + } + } + } + } + return nullptr; +} + +JKRArchive::SDIFileEntry* JKRArchive::findFsResource(const char* path, + u32 index) const +{ + if (path) + { + CArcName arcName(&path, '/'); + SDIDirEntry* dirEntry = &mDirectories[index]; + SDIFileEntry* entry = &mFileEntries[dirEntry->mFirstIdx]; + for (int i = 0; i < dirEntry->mNum; entry++, i++) + { + if (isSameName(arcName, entry->mFlag & 0xFFFFFF, entry->mHash)) + { + if (((entry->mFlag >> 0x18) & 2)) + { + return findFsResource(path, entry->mDataOffset); + } + if (path == 0) + { + return entry; + } + return nullptr; + } + } + } + return nullptr; +} + +JKRArchive::SDIFileEntry* JKRArchive::findIdxResource(u32 idx) const +{ + if (idx < mArcInfoBlock->num_file_entries) + { + return mFileEntries + idx; + } + return nullptr; +} + +JKRArchive::SDIFileEntry* JKRArchive::findNameResource(const char* name) const +{ + SDIFileEntry* fileEntry = mFileEntries; + + CArcName arcName(name); + for (int i = 0; i < mArcInfoBlock->num_file_entries; fileEntry++, i++) + { + if (isSameName(arcName, fileEntry->mFlag & 0xFFFFFF, fileEntry->mHash)) + { + return fileEntry; + } + } + + return nullptr; +} + +JKRArchive::SDIFileEntry* JKRArchive::findPtrResource(const void* ptr) const +{ + SDIFileEntry* entry = mFileEntries; + for (u32 i = 0; i < mArcInfoBlock->num_file_entries; entry++, i++) + { + if (entry->mData == ptr) + { + return entry; + } + } + return nullptr; +} + +JKRArchive::SDIFileEntry* JKRArchive::findIdResource(u16 id) const +{ + SDIFileEntry* entry; + if (id != 0xFFFF) + { + entry = &mFileEntries[id]; + if (entry->mFileID == id && (entry->getFlag01())) + { + return entry; + } + + entry = mFileEntries; + for (int i = 0; i < mArcInfoBlock->num_file_entries; entry++, i++) + { + if (entry->mFileID == id && (entry->getFlag01())) + { + return entry; + } + } + } + return nullptr; +} + +void JKRArchive::CArcName::store(const char* name) +{ + mHash = 0; + int count = 0; + while (*name) + { + int lower = tolower(*name); + mHash = lower + mHash * 3; + if (count < 0x100) + { + mString[count++] = lower; + } + name++; + } + _02 = count; + mString[count] = '\0'; +} + +const char* JKRArchive::CArcName::store(const char* name, char endChar) +{ + mHash = 0; + int count = 0; + for (; *name && *name != endChar; name++) + { + int lower = tolower(*name); + mHash = lower + mHash * 3; + if (count < 0x100) + { + mString[count++] = lower; + } + } + _02 = count; + mString[count] = '\0'; + + if (*name == 0) + return nullptr; + return name + 1; +} diff --git a/src/JSystem/JKernel/JKRArchivePub.cpp b/src/JSystem/JKernel/JKRArchivePub.cpp new file mode 100644 index 00000000..e7d41f92 --- /dev/null +++ b/src/JSystem/JKernel/JKRArchivePub.cpp @@ -0,0 +1,340 @@ +#include + +#include "JSystem/JKernel/JKRAram.h" +#include "JSystem/JKernel/JKRArchive.h" +#include "JSystem/JKernel/JKRDisposer.h" +#include "JSystem/JKernel/JKRFileFinder.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "JSystem/JUtility/JUTAssertion.h" +#include "types.h" + +// TODO: this file should emit a vtable but it doesn't, luckily JKRArchivePri +// does that and it doesn't cause any issues + +JKRArchive* JKRArchive::check_mount_already(s32 entryNum, JKRHeap* pHeap) { + // UNUSED FUNCTION + JKRHeap* heap = pHeap; + if (heap == nullptr) { + heap = JKRGetCurrentHeap(); + } + + JSUList& volumeList = JKRArchive::sVolumeList; + JSUListIterator iterator; + for (iterator = volumeList.getFirst(); iterator != volumeList.getEnd(); + ++iterator) { + if (iterator->getVolumeType() == 'RARC') { + JKRArchive* archive = + (JKRArchive*) + iterator.getObject(); // in TP debug it calls operator-> ? + if (archive->mEntryNum == entryNum && archive->mHeap == heap) { + archive->mMountCount++; + return archive; + } + } + } + return nullptr; +} + +JKRArchive* JKRArchive::check_mount_already(s32 entryNum) { + JSUList& volumeList = JKRArchive::sVolumeList; + JSUListIterator iterator; + for (iterator = volumeList.getFirst(); iterator != volumeList.getEnd(); + ++iterator) { + if (iterator->getVolumeType() == 'RARC') { + JKRArchive* archive = + (JKRArchive*) + iterator.getObject(); // in TP debug it calls operator-> ? + if (archive->mEntryNum == entryNum) { + archive->mMountCount++; + return archive; + } + } + } + return nullptr; +} + +JKRArchive* JKRArchive::mount(const char* path, EMountMode mode, JKRHeap* heap, + EMountDirection direction) { + int entryNum = DVDConvertPathToEntrynum((char*)path); + if (entryNum < 0) return nullptr; + + JKRArchive* mountedArchive = check_mount_already(entryNum); + if (mountedArchive != nullptr) { + return mountedArchive; + } + + int alignment = (direction == MOUNT_DIRECTION_HEAD) ? 4 : -4; + JKRArchive* archive; + switch (mode) { + case MOUNT_MEM: + if (entryNum == -1) + archive = nullptr; + else + archive = new (heap, alignment) JKRMemArchive(entryNum, direction); + break; + case MOUNT_ARAM: + archive = new (heap, alignment) JKRAramArchive(entryNum, direction); + break; + case MOUNT_DVD: + archive = new (heap, alignment) JKRDvdArchive(entryNum, direction); + break; + case MOUNT_COMP: + archive = new (heap, alignment) JKRCompArchive(entryNum, direction); + break; + } + if (archive != nullptr && archive->getMountMode() == UNKNOWN_MOUNT_MODE) { + delete archive; + archive = nullptr; + } + return archive; +} + +JKRArchive* JKRArchive::mount(void* p1, JKRHeap* heap, + EMountDirection mountDirection) { + JKRArchive* archive = check_mount_already((s32)p1, heap); + if (archive != nullptr) { + return archive; + } + return new (heap, (mountDirection == MOUNT_DIRECTION_HEAD) ? 4 : -4) + JKRMemArchive(p1, 0xFFFF, MBF_0); +} + +JKRArchive* JKRArchive::mount(s32 entryNum, EMountMode mountMode, JKRHeap* heap, + EMountDirection mountDirection) { + JKRArchive* archive = check_mount_already(entryNum, heap); + if (archive) { + return archive; + } + else { + int i = (mountDirection == MOUNT_DIRECTION_HEAD) ? 4 : -4; + JKRArchive* archive; + switch (mountMode) { + case MOUNT_MEM: + archive = new (heap, i) JKRMemArchive(entryNum, mountDirection); + break; + case MOUNT_ARAM: + archive = new (heap, i) JKRAramArchive(entryNum, mountDirection); + break; + case MOUNT_DVD: + archive = new (heap, i) JKRDvdArchive(entryNum, mountDirection); + break; + case MOUNT_COMP: + archive = new (heap, i) JKRCompArchive(entryNum, mountDirection); + break; + } + if (archive != nullptr && archive->getMountMode() == UNKNOWN_MOUNT_MODE) { + delete archive; + archive = nullptr; + } + return archive; + } +} + +bool JKRArchive::becomeCurrent(const char* path) { + SDIDirEntry* entry; + if (*path == '/') { + const char* directoryName = path + 1; + if (*directoryName == '\0') { + directoryName = nullptr; + } + entry = findDirectory(directoryName, 0); + } + else { + entry = findDirectory(path, sCurrentDirID); + } + bool result = (entry != nullptr); + if (result) { + sCurrentVolume = this; + sCurrentDirID = (entry - mDirectories); + } + return result; +} + +bool JKRArchive::getDirEntry(JKRArchive::SDirEntry* dirEntry, u32 p2) const { + SDIFileEntry* fileEntry = findIdxResource(p2); + if (!fileEntry) { + return false; + } + + dirEntry->mFlags = fileEntry->mFlag >> 0x18; + dirEntry->mID = fileEntry->mFileID; + dirEntry->mName = (char*)mStrTable + (fileEntry->mFlag & 0xFFFFFF); + return true; +} + +void* JKRArchive::getGlbResource(u32 type, const char* name, + JKRArchive* archive) { + void* resource = nullptr; + if (archive) { + return archive->getResource(type, name); + } + for (JSULink* link = sVolumeList.getFirst(); link != nullptr; + link = link->getNext()) { + if (link->getObject()->getVolumeType() == 'RARC' && + (resource = link->getObject()->getResource(type, name))) { + break; + } + } + return resource; +} + +void* JKRArchive::getResource(const char* path) { + JUT_ASSERT(isMounted()); + SDIFileEntry* fileEntry; + if (*path == '/') { + fileEntry = findFsResource(path + 1, 0); + } + else { + fileEntry = findFsResource(path, sCurrentDirID); + } + return (fileEntry != nullptr) ? (void*)fetchResource(fileEntry, nullptr) + : nullptr; +} + +void* JKRArchive::getResource(u32 type, const char* name) { + JUT_ASSERT(isMounted()); + SDIFileEntry* fileEntry; + if (type == 0 || type == '????') { + fileEntry = findNameResource(name); + } + else { + fileEntry = findTypeResource(type, name); + } + return (fileEntry != nullptr) ? (void*)fetchResource(fileEntry, nullptr) + : nullptr; +} + +void* JKRArchive::getIdxResource(u32 index) { + SDIFileEntry* fileEntry = findIdxResource(index); + return (fileEntry != nullptr) ? (void*)fetchResource(fileEntry, nullptr) + : nullptr; +} + +size_t JKRArchive::readResource(void* resourceBuffer, u32 bufferSize, u32 type, + const char* name) { + JUT_ASSERT(isMounted()); + SDIFileEntry* fileEntry; + if (type == 0 || type == '????') { + fileEntry = findNameResource(name); + } + else { + fileEntry = findTypeResource(type, name); + } + if (fileEntry) { + u32 resourceSize; + fetchResource(resourceBuffer, bufferSize, fileEntry, &resourceSize, + EXPAND_SWITCH_DECOMPRESS); + return resourceSize; + } + return 0; +} + +// Returns the size of the resource at the given path, or 0 if not found. +size_t JKRArchive::readResource(void* resourceBuffer, u32 bufferSize, + const char* path, + JKRExpandSwitch expandSwitch) { + JUT_ASSERT(isMounted()); + SDIFileEntry* fileEntry; + if (*path == '/') { + fileEntry = findFsResource(path + 1, 0); + } + else { + fileEntry = findFsResource(path, sCurrentDirID); + } + if (fileEntry) { + u32 resourceSize; + fetchResource(resourceBuffer, bufferSize, fileEntry, &resourceSize, + expandSwitch); + return resourceSize; + } + return 0; +} + +// Returns the size of the resource with the given ID, or 0 if not found. +size_t JKRArchive::readResource(void* resourceBuffer, u32 bufferSize, u16 id) { + JUT_ASSERT(isMounted()); + SDIFileEntry* fileEntry = findIdResource(id); + if (fileEntry) { + u32 resSize; + fetchResource(resourceBuffer, bufferSize, fileEntry, &resSize, + EXPAND_SWITCH_DEFAULT); + return resSize; + } + return 0; +} + +// This function is currently full off bugs, it doesn't increase the pointer to +// the file entries, and sets the pointer of mData to null before it's sent to +// free +void JKRArchive::removeResourceAll() { + if (mArcInfoBlock && mMountMode != MOUNT_MEM) { + SDIFileEntry* entry = mFileEntries; + for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) { + if (entry->mData) { + entry->mData = nullptr; + JKRFreeToHeap(mHeap, entry->mData); + } + } + } +} + +bool JKRArchive::removeResource(void* resource) { + JUT_ASSERT(resource != 0); + SDIFileEntry* entry = findPtrResource(resource); + if (entry == nullptr) { + return false; + } + entry->mData = nullptr; + JKRHeap::free(resource, mHeap); + return true; +} + +bool JKRArchive::detachResource(void* resource) { + JUT_ASSERT(resource != 0); + SDIFileEntry* entry = findPtrResource(resource); + if (entry == nullptr) { + return false; + } + entry->mData = nullptr; + return true; +} + +s32 JKRArchive::getResSize(const void* resource) const { + JUT_ASSERT(resource != 0); + SDIFileEntry* entry = findPtrResource(resource); + return (entry == nullptr) ? -1 : entry->getSize(); +} + +u32 JKRArchive::countFile(const char* path) const { + SDIDirEntry* dirEntry; + if (*path == '/') { + const char* pathPtr = path + 1; + if (*pathPtr == '\0') { + pathPtr = nullptr; + } + dirEntry = findDirectory(pathPtr, 0); + } + else { + dirEntry = findDirectory(path, sCurrentDirID); + } + return (dirEntry) ? dirEntry->mNum : 0; +} + +JKRFileFinder* JKRArchive::getFirstFile(const char* path) const { + SDIDirEntry* dirEntry; + if (*path == '/') { + const char* pathPtr = path + 1; + if (*pathPtr == '\0') { + pathPtr = nullptr; + } + dirEntry = findDirectory(pathPtr, 0); + } + else { + dirEntry = findDirectory(path, sCurrentDirID); + } + if (dirEntry) { + return new (JKRGetSystemHeap(), 0) JKRArcFinder( + const_cast(this), dirEntry->mFirstIdx, dirEntry->mNum); + } + return nullptr; +} diff --git a/src/JSystem/JKernel/JKRCompArchive.cpp b/src/JSystem/JKernel/JKRCompArchive.cpp new file mode 100644 index 00000000..11e8c342 --- /dev/null +++ b/src/JSystem/JKernel/JKRCompArchive.cpp @@ -0,0 +1,342 @@ +#include +#include + +#include "JSystem/JKernel/JKRArchive.h" +#include "JSystem/JKernel/JKRDecomp.h" +#include "JSystem/JKernel/JKRDvdAramRipper.h" +#include "JSystem/JKernel/JKRDvdRipper.h" +#include "JSystem/JSystem.h" +#include "JSystem/JUtility/JUTAssertion.h" + +JKRCompArchive::JKRCompArchive(long entryNum, EMountDirection mountDirection) + : JKRArchive(entryNum, MOUNT_COMP) { + mMountDirection = mountDirection; + if (!open(entryNum)) { + return; + } + else { + mVolumeType = 'RARC'; + mVolumeName = &mStrTable[mDirectories->mOffset]; + sVolumeList.prepend(&mFileLoaderLink); + mIsMounted = true; + } +} + +#ifdef DEBUG +void stringGen() { + JUT_PANIC("isMounted()"); + JUT_PANIC("mMountCount == 1"); +} +#endif + +JKRCompArchive::~JKRCompArchive() { + if (mArcInfoBlock) { + SDIFileEntry* fileEntries = mFileEntries; + for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) { + u32 flag = (fileEntries->mFlag >> 24); + if ((flag & 16) == 0 && fileEntries->mData) { + JKRFreeToHeap(mHeap, fileEntries->mData); + } + fileEntries++; + } + JKRFreeToHeap(mHeap, mArcInfoBlock); + mArcInfoBlock = nullptr; + } + if (mAramPart) { + delete mAramPart; + } + if (mDvdFile) { + delete mDvdFile; + } + + sVolumeList.remove(&mFileLoaderLink); + mIsMounted = false; +} + +bool JKRCompArchive::open(long entryNum) { + mArcInfoBlock = nullptr; + _60 = 0; + mAramPart = nullptr; + _68 = 0; + mSizeOfMemPart = 0; + mSizeOfAramPart = 0; + _78 = 0; + mDirectories = nullptr; + mFileEntries = nullptr; + mStrTable = nullptr; + + mDvdFile = new (JKRGetSystemHeap(), 0) JKRDvdFile(entryNum); + if (mDvdFile == nullptr) { + mMountMode = 0; + return 0; + } + SArcHeader* arcHeader = (SArcHeader*)JKRAllocFromSysHeap( + sizeof(SArcHeader), -32); // NOTE: unconfirmed if this struct is used + if (arcHeader == nullptr) { + mMountMode = 0; + } + else { + int alignment; + + JKRDvdToMainRam(entryNum, (u8*)arcHeader, EXPAND_SWITCH_DECOMPRESS, 32, + nullptr, JKRDvdRipper::ALLOC_DIR_TOP, 0, &mCompression); + + mSizeOfMemPart = arcHeader->_14; + mSizeOfAramPart = arcHeader->_18; + JUT_ASSERT((mSizeOfMemPart & 0x1f) == 0); + JUT_ASSERT((mSizeOfAramPart & 0x1f) == 0); + + switch (mCompression) { + case JKRCOMPRESSION_NONE: + case JKRCOMPRESSION_YAZ0: + alignment = mMountDirection == 1 ? 32 : -32; + mArcInfoBlock = (SArcDataInfo*)JKRAllocFromHeap( + mHeap, arcHeader->file_data_offset + mSizeOfMemPart, alignment); + if (mArcInfoBlock == nullptr) { + mMountMode = 0; + } + else { + JKRDvdToMainRam(entryNum, (u8*)mArcInfoBlock, + EXPAND_SWITCH_DECOMPRESS, + (u32)arcHeader->file_data_offset + mSizeOfMemPart, + nullptr, JKRDvdRipper::ALLOC_DIR_TOP, 0x20, nullptr); + _60 = (u32)mArcInfoBlock + arcHeader->file_data_offset; + + if (mSizeOfAramPart != 0) { + mAramPart = JKRAllocFromAram(mSizeOfAramPart, JKRAramHeap::Head); + if (mAramPart == nullptr) { + mMountMode = 0; + break; + } + + JKRDvdToAram(entryNum, mAramPart->getAddress(), + EXPAND_SWITCH_DECOMPRESS, + arcHeader->header_length + + arcHeader->file_data_offset + mSizeOfMemPart, + 0); + } + + mDirectories = + (SDIDirEntry*)((u32)mArcInfoBlock + mArcInfoBlock->node_offset); + mFileEntries = (SDIFileEntry*)((u32)mArcInfoBlock + + mArcInfoBlock->file_entry_offset); + mStrTable = (const char*)((u32)mArcInfoBlock + + mArcInfoBlock->string_table_offset); + _68 = arcHeader->header_length + arcHeader->file_data_offset; + } + break; + + case JKRCOMPRESSION_YAY0: + u32 alignedSize = ALIGN_NEXT(mDvdFile->getFileSize(), 32); + alignment = ((mMountDirection == 1) ? 32 : -32); + u8* buf = (u8*)JKRAllocFromSysHeap(alignedSize, -alignment); + + if (buf == nullptr) { + mMountMode = 0; + } + else { + JKRDvdToMainRam(entryNum, buf, EXPAND_SWITCH_NONE, alignedSize, + nullptr, JKRDvdRipper::ALLOC_DIR_TOP, 0, nullptr); + u32 expandSize = ALIGN_NEXT(JKRDecompExpandSize(buf), 32); + u8* mem = (u8*)JKRAllocFromHeap(mHeap, expandSize, -alignment); + + if (mem == nullptr) { + mMountMode = 0; + } + else { + arcHeader = (SArcHeader*)mem; + JKRDecompress((u8*)buf, (u8*)mem, expandSize, 0); + JKRFreeToSysHeap(buf); + + mArcInfoBlock = (SArcDataInfo*)JKRAllocFromHeap( + mHeap, arcHeader->file_data_offset + mSizeOfMemPart, alignment); + if (mArcInfoBlock == nullptr) { + mMountMode = 0; + } + else { + // arcHeader + 1 should lead to 0x20, which is the data after the + // header + JKRHeap::copyMemory( + (u8*)mArcInfoBlock, arcHeader + 1, + (arcHeader->file_data_offset + mSizeOfMemPart)); + _60 = (u32)mArcInfoBlock + arcHeader->file_data_offset; + if (mSizeOfAramPart != 0) { + mAramPart = + JKRAllocFromAram(mSizeOfAramPart, JKRAramHeap::Head); + if (mAramPart == nullptr) { + mMountMode = 0; + } + else { + JKRMainRamToAram( + (u8*)mem + arcHeader->header_length + + arcHeader->file_data_offset + mSizeOfMemPart, + mAramPart->getAddress(), mSizeOfAramPart, + EXPAND_SWITCH_DEFAULT, 0, nullptr, -1, nullptr); + } + } + } + } + } + mDirectories = + (SDIDirEntry*)((u32)mArcInfoBlock + mArcInfoBlock->node_offset); + mFileEntries = (SDIFileEntry*)((u32)mArcInfoBlock + + mArcInfoBlock->file_entry_offset); + mStrTable = (const char*)((u32)mArcInfoBlock + + mArcInfoBlock->string_table_offset); + _68 = arcHeader->header_length + arcHeader->file_data_offset; + break; + } + } + + if (arcHeader) { + JKRFreeToHeap(mHeap, arcHeader); + } + if (mMountMode == 0) { + JREPORTF(0, ":::[%s: %d] Cannot alloc memory in mounting CompArchive\n", + __FILE__, 567); // Macro? + if (mDvdFile) { + delete mDvdFile; + mDvdFile = nullptr; + } + } + return mMountMode != 0; +} + +void* JKRCompArchive::fetchResource(SDIFileEntry* fileEntry, u32* pSize) { + JUT_ASSERT(isMounted()); + + u32 ptrSize; + + if (fileEntry->mData == nullptr) { + u32 flag = fileEntry->mFlag >> 0x18; + if (flag & 0x10) { + fileEntry->mData = (void*)(_60 + fileEntry->mDataOffset); + if (pSize) *pSize = fileEntry->mSize; + } + else if (flag & 0x20) { + u32 address = mAramPart->getAddress(); + int compression = + JKRConvertAttrToCompressionType(fileEntry->mFlag >> 0x18); + + u8* data; + u32 size = JKRAramArchive::fetchResource_subroutine( + fileEntry->mDataOffset + address - mSizeOfMemPart, fileEntry->mSize, + mHeap, compression, &data); + + if (pSize) *pSize = size; + + fileEntry->mData = data; + + } + else if (flag & 0x40) { + int compression = + JKRConvertAttrToCompressionType(fileEntry->mFlag >> 0x18); + + u8* data; + u32 size = JKRDvdArchive::fetchResource_subroutine( + mEntryNum, _68 + fileEntry->mDataOffset, fileEntry->mSize, mHeap, + compression, mCompression, &data); + + if (pSize) *pSize = size; + + fileEntry->mData = data; + } + } + else if (pSize) { + *pSize = fileEntry->mSize; + } + return fileEntry->mData; +} + +void* JKRCompArchive::fetchResource(void* data, u32 compressedSize, + SDIFileEntry* fileEntry, u32* pSize, + JKRExpandSwitch expandSwitch) { +// u32 size = 0; + JUT_ASSERT(isMounted()); + + u32 size = ALIGN_NEXT(fileEntry->mSize, 32); + u32 expandSize = 0; + + if (size == 0) JPANIC(651, ":::bad resource size. size = 0\n"); + + if (fileEntry->mData) { + if (size > (compressedSize & ~31)) { + size = (compressedSize & ~31); + } + + JKRHeap::copyMemory(data, fileEntry->mData, size); + expandSize = size; + } + else { + u32 fileFlag = fileEntry->mFlag >> 0x18; + int compression = JKRConvertAttrToCompressionType(fileFlag); + if (expandSwitch != EXPAND_SWITCH_DECOMPRESS) compression = 0; + + if (fileFlag & 0x10) { + if (size > (compressedSize & ~31)) { + size = (compressedSize & ~31); + } + + if (FLAG_ON(fileFlag, 4)) { + JKRHeap::copyMemory(data, (void*)(_60 + fileEntry->mDataOffset), size); + } + else { + u8* header = (u8*)(_60 + fileEntry->mDataOffset); + expandSize = JKRDecompExpandSize(header); + expandSize = + (expandSize > compressedSize) ? compressedSize : expandSize; + JKRDecompress(header, (u8*)data, expandSize, 0); + } + + expandSize = JKRMemArchive::fetchResource_subroutine( + (u8*)(_60 + fileEntry->mDataOffset), size, (u8*)data, + compressedSize, compression); + } + else if (fileFlag & 0x20) { + expandSize = JKRAramArchive::fetchResource_subroutine( + fileEntry->mDataOffset + mAramPart->getAddress() - mSizeOfMemPart, + size, (u8*)data, compressedSize, compression); + } + else if (fileFlag & 0x40) { + expandSize = JKRDvdArchive::fetchResource_subroutine( + mEntryNum, _68 + fileEntry->mDataOffset, size, (u8*)data, + compressedSize, compression, mCompression); + } + else { + JPANIC(731, ":::CompArchive: bad mode."); + } + } + + if (pSize) { + *pSize = expandSize; + } + return data; +} + +void JKRCompArchive::removeResourceAll() { + if (mArcInfoBlock && mMountMode != MOUNT_MEM) { + SDIFileEntry* fileEntry = mFileEntries; + for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) { + u32 flag = fileEntry->mFlag >> 0x18; + if (fileEntry->mData) { + if ((flag & 0x10) == 0) { + JKRFreeToHeap(mHeap, fileEntry->mData); + } + + fileEntry->mData = nullptr; + } + } + } +} + +bool JKRCompArchive::removeResource(void* resource) { + SDIFileEntry* fileEntry = findPtrResource(resource); + if (!fileEntry) return false; + + if (((fileEntry->mFlag >> 0x18) & 0x10) == 0) { + JKRFreeToHeap(mHeap, resource); + } + + fileEntry->mData = nullptr; + return true; +} diff --git a/src/JSystem/JKernel/JKRDecomp.cpp b/src/JSystem/JKernel/JKRDecomp.cpp index 7a6436fa..9f645815 100644 --- a/src/JSystem/JKernel/JKRDecomp.cpp +++ b/src/JSystem/JKernel/JKRDecomp.cpp @@ -1,40 +1,45 @@ -#include "types.h" -#include "dolphin/os/OSMessage.h" -#include "JSystem/JSystem.h" -#include "JSystem/JKernel/JKRHeap.h" -#include "JSystem/JKernel/JKRAram.h" - #include "JSystem/JKernel/JKRDecomp.h" +#include "JSystem/JKernel/JKRAram.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "JSystem/JSystem.h" +#include "dolphin/os/OSMessage.h" +#include "types.h" + OSMessage JKRDecomp::sMessageBuffer[JKRDECOMP_MSG_BUF_COUNT] = { 0 }; OSMessageQueue JKRDecomp::sMessageQueue = { 0 }; JKRDecomp* JKRDecomp::sDecompObject; JKRDecomp* JKRDecomp::create(s32 decompPriority) { if (JKRDecomp::sDecompObject == nullptr) { - JKRDecomp::sDecompObject = new(JKRGetSystemHeap(), 0) JKRDecomp(decompPriority); + JKRDecomp::sDecompObject = + new (JKRGetSystemHeap(), 0) JKRDecomp(decompPriority); } return JKRDecomp::sDecompObject; } -JKRDecomp::JKRDecomp(s32 priority) : JKRThread(JKRDECOMP_STACK_SIZE, JKRDECOMP_THREAD_MSG_BUF_COUNT, priority) { +JKRDecomp::JKRDecomp(s32 priority) + : JKRThread(JKRDECOMP_STACK_SIZE, JKRDECOMP_THREAD_MSG_BUF_COUNT, + priority) { OSResumeThread(this->mThreadRecord); } -JKRDecomp::~JKRDecomp() { } +JKRDecomp::~JKRDecomp() {} void* JKRDecomp::run() { OSMessage recMesg; JKRDecompCommand* cmd; - OSInitMessageQueue(&JKRDecomp::sMessageQueue, JKRDecomp::sMessageBuffer, JKRDECOMP_MSG_BUF_COUNT); + OSInitMessageQueue(&JKRDecomp::sMessageQueue, JKRDecomp::sMessageBuffer, + JKRDECOMP_MSG_BUF_COUNT); while (true) { while (true) { while (true) { OSReceiveMessage(&JKRDecomp::sMessageQueue, &recMesg, OS_MESSAGE_BLOCK); cmd = static_cast(recMesg); - JKRDecomp::decode(cmd->mSrcBuffer, cmd->mDstBuffer, cmd->mSrcLength, cmd->mSkipCount); + JKRDecomp::decode(cmd->mSrcBuffer, cmd->mDstBuffer, cmd->mSrcLength, + cmd->mSkipCount); if (cmd->transferType == JKRDecompCommand::MRAM) { break; @@ -61,9 +66,11 @@ void* JKRDecomp::run() { } } -JKRDecompCommand* JKRDecomp::prepareCommand(u8* srcBuffer, u8* dstBuffer, u32 srcLength, u32 skipCount, DecompCallback* callback) { - JKRDecompCommand* cmd = new(JKRGetSystemHeap(), -4) JKRDecompCommand(); - +JKRDecompCommand* JKRDecomp::prepareCommand(u8* srcBuffer, u8* dstBuffer, + u32 srcLength, u32 skipCount, + DecompCallback* callback) { + JKRDecompCommand* cmd = new (JKRGetSystemHeap(), -4) JKRDecompCommand(); + cmd->mSrcBuffer = srcBuffer; cmd->mDstBuffer = dstBuffer; cmd->mSrcLength = srcLength; @@ -74,7 +81,8 @@ JKRDecompCommand* JKRDecomp::prepareCommand(u8* srcBuffer, u8* dstBuffer, u32 sr } BOOL JKRDecomp::sendCommand(JKRDecompCommand* cmd) { - BOOL res = OSSendMessage(&JKRDecomp::sMessageQueue, (OSMessage)cmd, OS_MESSAGE_BLOCK); + BOOL res = OSSendMessage(&JKRDecomp::sMessageQueue, (OSMessage)cmd, + OS_MESSAGE_BLOCK); #ifdef JSYSTEM_DEBUG if (res == FALSE) { @@ -85,8 +93,11 @@ BOOL JKRDecomp::sendCommand(JKRDecompCommand* cmd) { return res; } -JKRDecompCommand* JKRDecomp::orderAsync(u8* srcBuffer, u8* dstBuffer, u32 srcLength, u32 skipCount, DecompCallback* callback) { - JKRDecompCommand* cmd = JKRDecomp::prepareCommand(srcBuffer, dstBuffer, srcLength, skipCount, callback); +JKRDecompCommand* JKRDecomp::orderAsync(u8* srcBuffer, u8* dstBuffer, + u32 srcLength, u32 skipCount, + DecompCallback* callback) { + JKRDecompCommand* cmd = JKRDecomp::prepareCommand( + srcBuffer, dstBuffer, srcLength, skipCount, callback); JKRDecomp::sendCommand(cmd); return cmd; } @@ -99,18 +110,22 @@ bool JKRDecomp::sync(JKRDecompCommand* cmd, BOOL noBlock) { return true; } else { - return OSReceiveMessage(&cmd->mMesgQueue, &msg, OS_MESSAGE_NOBLOCK) != FALSE; + return OSReceiveMessage(&cmd->mMesgQueue, &msg, OS_MESSAGE_NOBLOCK) != + FALSE; } } -bool JKRDecomp::orderSync(u8* srcBuffer, u8* dstBuffer, u32 srcLength, u32 skipCount) { - JKRDecompCommand* cmd = JKRDecomp::orderAsync(srcBuffer, dstBuffer, srcLength, skipCount, nullptr); +bool JKRDecomp::orderSync(u8* srcBuffer, u8* dstBuffer, u32 srcLength, + u32 skipCount) { + JKRDecompCommand* cmd = JKRDecomp::orderAsync(srcBuffer, dstBuffer, srcLength, + skipCount, nullptr); bool res = JKRDecomp::sync(cmd, FALSE); delete cmd; return res; } -void JKRDecomp::decode(u8* srcBuffer, u8* dstBuffer, u32 srcLength, u32 skipCount) { +void JKRDecomp::decode(u8* srcBuffer, u8* dstBuffer, u32 srcLength, + u32 skipCount) { CompressionMode mode = JKRDecomp::checkCompressed(srcBuffer); if (mode == SZP) { JKRDecomp::decodeSZP(srcBuffer, dstBuffer, srcLength, skipCount); @@ -120,154 +135,135 @@ void JKRDecomp::decode(u8* srcBuffer, u8* dstBuffer, u32 srcLength, u32 skipCoun } } -void JKRDecomp::decodeSZP(u8 *src, u8 *dst, u32 srcLength, u32 skipCount) -{ - int srcChunkOffset; - int count; - int dstOffset; - u32 length; - int linkInfo; - int offset; - int i; +void JKRDecomp::decodeSZP(u8* src, u8* dst, u32 srcLength, u32 skipCount) { + int srcChunkOffset; + int count; + int dstOffset; + u32 length; + int linkInfo; + int offset; + int i; - int decodedSize = JKRDECOMP_READU32BE(src, 4); - int linkTableOffset = JKRDECOMP_READU32BE(src, 8); - int srcDataOffset = JKRDECOMP_READU32BE(src, 12); + int decodedSize = JKRDECOMP_READU32BE(src, 4); + int linkTableOffset = JKRDECOMP_READU32BE(src, 8); + int srcDataOffset = JKRDECOMP_READU32BE(src, 12); - dstOffset = 0; - u32 counter = 0; // curently counter gets assembled before the READ_U32 operations - srcChunkOffset = 16; + dstOffset = 0; + u32 counter = + 0; // curently counter gets assembled before the READ_U32 operations + srcChunkOffset = 16; - u32 chunkBits; - if (srcLength == 0) - return; - if (skipCount > decodedSize) - return; + u32 chunkBits; + if (srcLength == 0) return; + if (skipCount > decodedSize) return; - length = srcLength; - do - { - if (counter == 0) - { - chunkBits = JKRDECOMP_READU32BE(src, srcChunkOffset); - srcChunkOffset += sizeof(u32); - counter = sizeof(u32) * 8; - } + length = srcLength; + do { + if (counter == 0) { + chunkBits = JKRDECOMP_READU32BE(src, srcChunkOffset); + srcChunkOffset += sizeof(u32); + counter = sizeof(u32) * 8; + } - if (chunkBits & 0x80000000) - { - if (skipCount == 0) - { - dst[dstOffset] = src[srcDataOffset]; - length--; - if (length == 0) - return; - } - else - { - skipCount--; - } - dstOffset++; - srcDataOffset++; + if (chunkBits & 0x80000000) { + if (skipCount == 0) { + dst[dstOffset] = src[srcDataOffset]; + length--; + if (length == 0) return; + } + else { + skipCount--; + } + dstOffset++; + srcDataOffset++; + } + else { + linkInfo = src[linkTableOffset] << 8 | src[linkTableOffset + 1]; + linkTableOffset += sizeof(u16); + + offset = dstOffset - (linkInfo & 0xFFF); + count = (linkInfo >> 12); + if (count == 0) { + count = (u32)src[srcDataOffset++] + 0x12; + } + else + count += 2; + + if ((int)count > decodedSize - dstOffset) count = decodedSize - dstOffset; + + for (i = 0; i < (int)count; i++, dstOffset++, offset++) { + if (skipCount == 0) { + dst[dstOffset] = dst[offset - 1]; + length--; + if (length == 0) return; } else - { - linkInfo = src[linkTableOffset] << 8 | src[linkTableOffset + 1]; - linkTableOffset += sizeof(u16); + skipCount--; + } + } - offset = dstOffset - (linkInfo & 0xFFF); - count = (linkInfo >> 12); - if (count == 0) - { - count = (u32)src[srcDataOffset++] + 0x12; - } - else - count += 2; - - if ((int)count > decodedSize - dstOffset) - count = decodedSize - dstOffset; - - for (i = 0; i < (int)count; i++, dstOffset++, offset++) - { - if (skipCount == 0) - { - dst[dstOffset] = dst[offset - 1]; - length--; - if (length == 0) - return; - } - else - skipCount--; - } - } - - chunkBits <<= 1; - counter--; - } while (dstOffset < decodedSize); + chunkBits <<= 1; + counter--; + } while (dstOffset < decodedSize); } -void JKRDecomp::decodeSZS(u8 *src_buffer, u8 *dst_buffer, u32 srcSize, u32 skipCount) { +void JKRDecomp::decodeSZS(u8* src_buffer, u8* dst_buffer, u32 srcSize, + u32 skipCount) { + u8* decompEnd = dst_buffer + *(u32*)(src_buffer + 4) - skipCount; + u8* copyStart; + s32 copyByteCount; + s32 chunkBitsLeft = 0; + s32 chunkBits; - u8 *decompEnd = dst_buffer + *(u32 *)(src_buffer + 4) - skipCount; - u8 *copyStart; - s32 copyByteCount; - s32 chunkBitsLeft = 0; - s32 chunkBits; + if (srcSize == 0) return; + if (skipCount > *(u32*)src_buffer) return; - if (srcSize == 0) - return; - if (skipCount > *(u32 *)src_buffer) - return; - - u8 *curSrcPos = src_buffer + 0x10; - do { - if (chunkBitsLeft == 0) { - chunkBits = *curSrcPos++; - chunkBitsLeft = 8; - } - if ((chunkBits & 0x80) != 0) { - if (skipCount == 0) - { - *dst_buffer = *curSrcPos; - srcSize--; - dst_buffer++; - if (srcSize == 0) - return; - } - else { - skipCount--; - } - curSrcPos++; + u8* curSrcPos = src_buffer + 0x10; + do { + if (chunkBitsLeft == 0) { + chunkBits = *curSrcPos++; + chunkBitsLeft = 8; + } + if ((chunkBits & 0x80) != 0) { + if (skipCount == 0) { + *dst_buffer = *curSrcPos; + srcSize--; + dst_buffer++; + if (srcSize == 0) return; + } + else { + skipCount--; + } + curSrcPos++; + } + else { + u8 curVal = *curSrcPos; + copyStart = dst_buffer - (curSrcPos[1] | (curVal & 0xF) << 8); + curSrcPos += 2; + if (curVal >> 4 == 0) { + copyByteCount = *curSrcPos + 0x12; + curSrcPos++; + } + else { + copyByteCount = (curVal >> 4) + 2; + } + do { + if (skipCount == 0) { + *dst_buffer = *(copyStart - 1); + srcSize--; + dst_buffer++; + if (srcSize == 0) return; } else { - u8 curVal = *curSrcPos; - copyStart = dst_buffer - (curSrcPos[1] | (curVal & 0xF) << 8); - curSrcPos += 2; - if (curVal >> 4 == 0) { - copyByteCount = *curSrcPos + 0x12; - curSrcPos++; - } - else { - copyByteCount = (curVal >> 4) + 2; - } - do { - if (skipCount == 0) { - *dst_buffer = *(copyStart - 1); - srcSize--; - dst_buffer++; - if (srcSize == 0) - return; - } - else { - skipCount--; - } - copyByteCount--; - copyStart++; - } while (copyByteCount != 0); + skipCount--; } - chunkBits <<= 1; - chunkBitsLeft--; - } while (dst_buffer != decompEnd); + copyByteCount--; + copyStart++; + } while (copyByteCount != 0); + } + chunkBits <<= 1; + chunkBitsLeft--; + } while (dst_buffer != decompEnd); } JKRDecomp::CompressionMode JKRDecomp::checkCompressed(u8* buf) { @@ -292,4 +288,4 @@ JKRDecompCommand::JKRDecompCommand() { this->transferType = MRAM; } -JKRDecompCommand::~JKRDecompCommand() { } +JKRDecompCommand::~JKRDecompCommand() {} diff --git a/src/JSystem/JKernel/JKRDisposer.cpp b/src/JSystem/JKernel/JKRDisposer.cpp index 4ecb428a..970a1167 100644 --- a/src/JSystem/JKernel/JKRDisposer.cpp +++ b/src/JSystem/JKernel/JKRDisposer.cpp @@ -1,4 +1,5 @@ #include "JSystem/JKernel/JKRDisposer.h" + #include "JSystem/JKernel/JKRHeap.h" JKRDisposer::JKRDisposer() : mPointerLinks(this) { diff --git a/src/JSystem/JKernel/JKRDvdAramRipper.cpp b/src/JSystem/JKernel/JKRDvdAramRipper.cpp new file mode 100644 index 00000000..acb8d6e6 --- /dev/null +++ b/src/JSystem/JKernel/JKRDvdAramRipper.cpp @@ -0,0 +1,402 @@ +#include "JSystem/JKernel/JKRDvdAramRipper.h" + +#include <_mem.h> +#include +#include + +#include "JSystem/JKernel/JKRDecomp.h" +#include "JSystem/JKernel/JKRDvdFile.h" +#include "JSystem/JKernel/JKRDvdRipper.h" +#include "JSystem/JUtility/JUTAssertion.h" + +JSUList JKRDvdAramRipper::sDvdAramAsyncList; + +bool JKRDvdAramRipper::errorRetry = true; +int JKRDvdAramRipper::sSZSBufferSize = 0x400; + +JKRAramBlock* JKRDvdAramRipper::loadToAram(s32 entrynum, u32 p2, + JKRExpandSwitch expSwitch, u32 p6, + u32 p7) { + JKRDvdFile dvdFile; + if (!dvdFile.open(entrynum)) + return nullptr; + else + return loadToAram(&dvdFile, p2, expSwitch, p6, p7); +} + +JKRAramBlock* JKRDvdAramRipper::loadToAram(JKRDvdFile* dvdFile, u32 p1, + JKRExpandSwitch p2, u32 p3, u32 p4) { + JKRADCommand* command = loadToAram_Async(dvdFile, p1, p2, nullptr, p3, p4); + syncAram(command, 0); + + if (p1) { + delete command; + return (JKRAramBlock*)-1; + } + + JKRAramBlock* result = command->mBlock; + delete command; + return result; +} + +JKRADCommand* JKRDvdAramRipper::loadToAram_Async(JKRDvdFile* dvdFile, u32 p1, + JKRExpandSwitch expSwitch, + JKRADCommand::LoadCallback cb, + u32 p4, u32 p5) { + JKRADCommand* command = new (JKRGetSystemHeap(), -4) JKRADCommand(); + command->mDvdFile = dvdFile; + command->_1C = p1; + command->mBlock = nullptr; + command->mExpandSwitch = expSwitch; + command->mCallBack = cb; + + command->_14 = p4; + command->_18 = p5; + + if (!callCommand_Async(command)) { + delete command; + return nullptr; + } + + return command; +} + +JKRADCommand* JKRDvdAramRipper::callCommand_Async(JKRADCommand* command) { + bool isCmdTrdNull = true; + JKRDvdFile* dvdFile = command->mDvdFile; + int compression = JKRCOMPRESSION_NONE; + OSLockMutex(&dvdFile->mAramMutex); + + s32 uncompressedSize; + + if (dvdFile->mAramThread) { + isCmdTrdNull = false; + } + else { + dvdFile->mAramThread = OSGetCurrentThread(); + JSUFileInputStream* stream = + new (JKRGetSystemHeap(), -4) JSUFileInputStream(dvdFile); + dvdFile->mInputStream = stream; + u32 fileSize = dvdFile->getFileSize(); + if (command->_18 && fileSize > command->_18) { + fileSize = command->_18; + } + fileSize = ALIGN_NEXT(fileSize, 0x20); + if (command->mExpandSwitch == EXPAND_SWITCH_DECOMPRESS) { + 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 == false) { + delete stream; + return nullptr; + } + + VIWaitForRetrace(); + } + + compression = JKRCheckCompressed(bufPtr); + u32 expSize = JKRDecompExpandSize(bufPtr); + uncompressedSize = expSize; + + if ((command->_18 != 0) && expSize > command->_18) { + uncompressedSize = command->_18; + } + } + + if (compression == JKRCOMPRESSION_NONE) { + command->mExpandSwitch = EXPAND_SWITCH_DEFAULT; + } + + if (command->mExpandSwitch == EXPAND_SWITCH_DECOMPRESS) { + if (command->_1C == 0 && command->mBlock == nullptr) { + command->mBlock = + JKRAram::getAramHeap()->alloc(uncompressedSize, JKRAramHeap::Head); + if (command->mBlock) { + command->_1C = command->mBlock->mAddress; + } + dvdFile->mAramBlock = command->mBlock; + } + + if (command->mBlock) { + command->_1C = command->mBlock->mAddress; + } + + if (command->_1C == 0) { + dvdFile->mAramThread = nullptr; + return nullptr; + } + } + else { + if (command->_1C == 0 && !command->mBlock) { + command->mBlock = + JKRAram::getAramHeap()->alloc(fileSize, JKRAramHeap::Head); + } + + if (command->mBlock) { + command->_1C = command->mBlock->mAddress; + } + + if (command->_1C == 0) { + dvdFile->mAramThread = nullptr; + return nullptr; + } + } + + if (compression == 0) { + command->mStreamCommand = JKRAramStream::write_StreamToAram_Async( + stream, command->_1C, fileSize - command->_14, command->_14); + } + else if (compression == JKRCOMPRESSION_YAY0) { + command->mStreamCommand = JKRAramStream::write_StreamToAram_Async( + stream, command->_1C, fileSize - command->_14, command->_14); + } + else if (compression == JKRCOMPRESSION_YAZ0) { + command->mStreamCommand = nullptr; + JKRDecompressFromDVDToAram(command->mDvdFile, command->_1C, fileSize, + uncompressedSize, command->_14, 0); + } + + if (!command->mCallBack) { + sDvdAramAsyncList.append(&command->mLink); + } + else { + command->mCallBack((u32)command); + } + } + + OSUnlockMutex(&dvdFile->mAramMutex); + return isCmdTrdNull == true ? command : nullptr; +} + +bool JKRDvdAramRipper::syncAram(JKRADCommand* command, int p1) { + JKRDvdFile* dvdFile = command->mDvdFile; + OSLockMutex(&dvdFile->mAramMutex); + + if (command->mStreamCommand) { + JKRAramStreamCommand* var1 = + JKRAramStream::sync(command->mStreamCommand, p1); + + if (p1 != 0 && var1 == nullptr) { + OSUnlockMutex(&dvdFile->mAramMutex); + return false; + } + } + + sDvdAramAsyncList.remove(&command->mLink); + if (command->mStreamCommand) { + delete command->mStreamCommand; + } + + delete dvdFile->mInputStream; + dvdFile->mAramThread = nullptr; + OSUnlockMutex(&dvdFile->mAramMutex); + return true; +} + +JKRADCommand::JKRADCommand() : mLink(this) { _44 = 0; } + +JKRADCommand::~JKRADCommand() { + if (_44 == 1) delete mDvdFile; +} + +static OSMutex decompMutex; +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; +static u32* tsPtr; +static u32 tsArea; + +static int decompSZS_subroutine(u8*, u32); +static u8* firstSrcData(); +static u8* nextSrcData(u8*); +static u32 dmaBufferFlush(u32); + +int JKRDecompressFromDVDToAram(JKRDvdFile* dvdFile, u32 address, u32 fileSize, + u32 _maxDest, u32 _fileOffset, u32 _srcOffset) { + int result = 0; + szpBuf = (u8*)JKRAllocFromSysHeap(SZP_BUFFERSIZE, 32); + JUT_ASSERT(szpBuf != 0); + szpEnd = szpBuf + SZP_BUFFERSIZE; + + refBuf = (u8*)JKRAllocFromSysHeap(REF_BUFFERSIZE, 0); + JUT_ASSERT(refBuf != 0); + refEnd = refBuf + REF_BUFFERSIZE; + refCurrent = refBuf; + + dmaBuf = (u8*)JKRAllocFromSysHeap(DMA_BUFFERSIZE, 32); + JUT_ASSERT(dmaBuf != 0); + dmaEnd = dmaBuf + DMA_BUFFERSIZE; + dmaCurrent = dmaBuf; + + srcFile = dvdFile; + srcOffset = _srcOffset; + transLeft = fileSize - _srcOffset; + fileOffset = _fileOffset; + readCount = 0; + maxDest = _maxDest; + + u8* first = firstSrcData(); + if (first) result = decompSZS_subroutine(first, address); + + JKRFree(szpBuf); + JKRFree(refBuf); + JKRFree(dmaBuf); + + return result; +} + +int decompSZS_subroutine(u8* src, u32 dmaAddr) { + u32 endPtr; + u8* copySource; + s32 validBitCount = 0; + s32 currCodeByte = 0; + s32 numBytes; + + u32 dmaStart = dmaAddr; + + if (src[0] != 'Y' || src[1] != 'a' || src[2] != 'z' || src[3] != '0') + return -1; + + SYaz0Header* header = (SYaz0Header*)src; + endPtr = dmaAddr + (header->length - fileOffset); + if (endPtr > dmaAddr + maxDest) endPtr = dmaAddr + maxDest; + + src += 0x10; + + do { + if (validBitCount == 0) { + if ((src > srcLimit) && transLeft) src = nextSrcData(src); + + currCodeByte = *src++; + validBitCount = 8; + } + if (currCodeByte & 0x80) { + if (readCount >= fileOffset) { + dmaAddr++; + *dmaCurrent++ = *src; + if (dmaCurrent == dmaEnd) dmaStart += dmaBufferFlush(dmaStart); + + if (dmaAddr == endPtr) break; + } + *(refCurrent++) = *src; + if (refCurrent == refEnd) refCurrent = refBuf; + + src++; + + readCount++; + } + else { + int t0 = src[0]; + int t1 = src[1]; + copySource = refCurrent - (t1 | (t0 & 0x0f) << 8) - 1; + numBytes = t0 >> 4; + src += 2; + if (copySource < refBuf) copySource = copySource + (refEnd - refBuf); + + if (numBytes == 0) + numBytes = *src++ + 0x12; + else + numBytes += 2; + + do { + if (readCount >= fileOffset) { + dmaAddr++; + *(dmaCurrent++) = *copySource; + if (dmaCurrent == dmaEnd) dmaStart += dmaBufferFlush(dmaStart); + + if (dmaAddr == endPtr) break; + } + *(refCurrent++) = *copySource; + if (refCurrent == refEnd) refCurrent = refBuf; + + copySource++; + + if (copySource == refEnd) copySource = refBuf; + + readCount++; + numBytes--; + } while (numBytes != 0); + } + currCodeByte <<= 1; + validBitCount--; + } while (dmaAddr < endPtr); + + dmaBufferFlush(dmaStart); + + return 0; +} + +u8* firstSrcData() { + srcLimit = szpEnd - 0x19; + u8* buf = szpBuf; + u32 max = (szpEnd - szpBuf); + u32 transSize = MIN(transLeft, max); + + while (true) { + if (0 <= DVDReadPrio(srcFile->getFileInfo(), buf, transSize, 0, 2)) break; + if (!JKRDvdAramRipper::isErrorRetry()) return nullptr; + VIWaitForRetrace(); + } + srcOffset += transSize; + transLeft -= transSize; + return buf; +} + +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; + + memcpy(buf, src, limit); + u32 transSize = (u32)(szpEnd - (buf + limit)); + if (transSize > transLeft) transSize = transLeft; + + JUT_ASSERT(transSize > 0); + while (true) { + int result = DVDReadPrio(srcFile->getFileInfo(), (buf + limit), transSize, + srcOffset, 2); + if (result >= 0) break; + + if (!JKRDvdAramRipper::isErrorRetry()) return nullptr; + + VIWaitForRetrace(); + } + + srcOffset += transSize; + transLeft -= transSize; + if (transLeft == 0) srcLimit = transSize + (buf + limit); + + return buf; +} + +u32 dmaBufferFlush(u32 src) { + if (dmaCurrent == dmaBuf) { + return 0; + } + else { + u32 length = ALIGN_NEXT((u32)(dmaCurrent - dmaBuf), 32); + JKRAramPiece::orderSync(0, (u32)dmaBuf, src, length, nullptr); + dmaCurrent = dmaBuf; + return length; + } +} diff --git a/src/JSystem/JKernel/JKRDvdArchive.cpp b/src/JSystem/JKernel/JKRDvdArchive.cpp new file mode 100644 index 00000000..ed23f8a4 --- /dev/null +++ b/src/JSystem/JKernel/JKRDvdArchive.cpp @@ -0,0 +1,321 @@ +#include +#include + +#include "JSystem/JKernel/JKRArchive.h" +#include "JSystem/JKernel/JKRDecomp.h" +#include "JSystem/JKernel/JKRDvdAramRipper.h" +#include "JSystem/JKernel/JKRDvdRipper.h" +#include "JSystem/JSystem.h" +#include "JSystem/JUtility/JUTAssertion.h" + +JKRDvdArchive::JKRDvdArchive() : JKRArchive() {} + +JKRDvdArchive::JKRDvdArchive(s32 entryNum, EMountDirection mountDirection) + : JKRArchive(entryNum, MOUNT_DVD) +{ + mMountDirection = mountDirection; + if (!open(entryNum)) + { + return; + } + else + { + mVolumeType = 'RARC'; + mVolumeName = &mStrTable[mDirectories->mOffset]; + sVolumeList.prepend(&mFileLoaderLink); + mIsMounted = true; + } +} + +JKRDvdArchive::~JKRDvdArchive() +{ + if (mIsMounted == true) + { + if (mArcInfoBlock) + { + SDIFileEntry* fileEntries = mFileEntries; + for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) + { + if (fileEntries->mData != nullptr) + { + JKRFreeToHeap(mHeap, fileEntries->mData); + } + fileEntries++; + } + JKRFreeToHeap(mHeap, mArcInfoBlock); + } + + if (mDvdFile) + { + delete mDvdFile; + } + + sVolumeList.remove(&mFileLoaderLink); + mIsMounted = false; + } +} + +#ifdef DEBUG +CW_FORCE_STRINGS(JKRDvdArchive_cpp, __FILE__, "isMounted()", "mMountCount == 1") +#endif + +bool JKRDvdArchive::open(long entryNum) +{ + mArcInfoBlock = nullptr; + _60 = 0; + mDirectories = nullptr; + mFileEntries = nullptr; + mStrTable = nullptr; + + mDvdFile = new (JKRGetSystemHeap(), 0) JKRDvdFile(entryNum); + if (mDvdFile == nullptr) + { + mMountMode = 0; + return 0; + } + SDIFileEntry* mem = (SDIFileEntry*)JKRAllocFromSysHeap( + 32, 32); // NOTE: unconfirmed if this struct was used here + if (mem == nullptr) + { + mMountMode = 0; + } + else + { + JKRDvdToMainRam(entryNum, (u8*)mem, EXPAND_SWITCH_DECOMPRESS, 32, nullptr, + JKRDvdRipper::ALLOC_DIR_TOP, 0, &mCompression); + int alignment = mMountDirection == MOUNT_DIRECTION_HEAD ? 32 : -32; + + mArcInfoBlock = + (SArcDataInfo*)JKRAllocFromHeap(mHeap, mem->mSize, alignment); + if (mArcInfoBlock == nullptr) + { + mMountMode = 0; + } + else + { + JKRDvdToMainRam(entryNum, (u8*)mArcInfoBlock, EXPAND_SWITCH_DECOMPRESS, + mem->mSize, nullptr, JKRDvdRipper::ALLOC_DIR_TOP, 32, + nullptr); + + mDirectories = + (SDIDirEntry*)((u8*)mArcInfoBlock + mArcInfoBlock->node_offset); + mFileEntries = (SDIFileEntry*)((u8*)mArcInfoBlock + + mArcInfoBlock->file_entry_offset); + mStrTable = (const char*)((u8*)mArcInfoBlock + + mArcInfoBlock->string_table_offset); + _60 = mem->mDataOffset + mem->mSize; // End of data offset? + } + } +cleanup: + if (mem != nullptr) + { + JKRFreeToSysHeap(mem); + } + if (mMountMode == 0) + { + JREPORTF(":::Cannot alloc memory [%s][%d]\n", __FILE__, 397); // Macro? + if (mDvdFile != nullptr) + { + delete mDvdFile; + } + } + return mMountMode != 0; +} + +void* JKRDvdArchive::fetchResource(SDIFileEntry* fileEntry, u32* pSize) +{ + JUT_ASSERT(isMounted()); + + u32 sizeRef; + u8* data; + + if (fileEntry->mData == nullptr) + { + int compression = JKRConvertAttrToCompressionType(fileEntry->mFlag >> 0x18); + u32 size = fetchResource_subroutine(mEntryNum, _60 + fileEntry->mDataOffset, + fileEntry->mSize, mHeap, + (int)compression, mCompression, &data); + + if (pSize) + *pSize = size; + + fileEntry->mData = data; + } + else if (pSize) + { + *pSize = fileEntry->mSize; + } + + return fileEntry->mData; +} + +void* JKRDvdArchive::fetchResource(void* data, u32 compressedSize, + SDIFileEntry* fileEntry, u32* pSize, + JKRExpandSwitch expandSwitch) +{ + JUT_ASSERT(isMounted()); + + u32 fileSize = compressedSize & -32; + u32 alignedSize = ALIGN_NEXT(fileEntry->mSize, 32); + + if (alignedSize > fileSize) + { + alignedSize = fileSize; + } + + if (fileEntry->mData == nullptr) + { + int compression = JKRConvertAttrToCompressionType(fileEntry->mFlag >> 0x18); + if (expandSwitch != EXPAND_SWITCH_DECOMPRESS) + compression = 0; + alignedSize = fetchResource_subroutine( + mEntryNum, _60 + fileEntry->mDataOffset, fileEntry->mSize, (u8*)data, + fileSize, compression, mCompression); + } + else + { + JKRHeap::copyMemory(data, fileEntry->mData, alignedSize); + } + + if (pSize) + { + *pSize = alignedSize; + } + return data; +} + +u32 JKRDvdArchive::fetchResource_subroutine(long entryNum, u32 offset, u32 size, + u8* data, u32 expandSize, + int fileCompression, + int archiveCompression) +{ + u32 prevAlignedSize, alignedSize; + + alignedSize = ALIGN_NEXT(size, 32); + prevAlignedSize = ALIGN_PREV(expandSize, 32); + switch (archiveCompression) + { + case JKRCOMPRESSION_NONE: + { + switch (fileCompression) + { + case JKRCOMPRESSION_NONE: + + if (alignedSize > prevAlignedSize) + { + alignedSize = prevAlignedSize; + } + JKRDvdRipper::loadToMainRAM( + entryNum, data, EXPAND_SWITCH_DEFAULT, alignedSize, nullptr, + JKRDvdRipper::ALLOC_DIR_TOP, offset, nullptr); + return alignedSize; + + case JKRCOMPRESSION_YAY0: + case JKRCOMPRESSION_YAZ0: + u8* header = (u8*)JKRAllocFromSysHeap(0x20, 0x20); + JKRDvdRipper::loadToMainRAM( + entryNum, header, EXPAND_SWITCH_NONE, 0x20, nullptr, + JKRDvdRipper::ALLOC_DIR_TOP, offset, nullptr); + u32 expandFileSize = JKRDecompExpandSize(header); + JKRFreeToSysHeap(header); + alignedSize = ALIGN_NEXT(expandFileSize, 32); + if (alignedSize > prevAlignedSize) + { + alignedSize = prevAlignedSize; + } + JKRDvdRipper::loadToMainRAM( + entryNum, data, EXPAND_SWITCH_DECOMPRESS, alignedSize, nullptr, + JKRDvdRipper::ALLOC_DIR_TOP, offset, nullptr); + return expandFileSize; + } + } + case JKRCOMPRESSION_YAZ0: + { + if (size > prevAlignedSize) + { + size = prevAlignedSize; + } + JKRDvdRipper::loadToMainRAM(entryNum, data, EXPAND_SWITCH_DECOMPRESS, + size, nullptr, JKRDvdRipper::ALLOC_DIR_TOP, + offset, nullptr); + return size; + } + + case JKRCOMPRESSION_YAY0: + { + JPANIC(537, "Sorry, not prepared for SZP archive.\n"); + return 0; + } + + default: + { + JPANIC(546, ":::??? bad sequence\n"); + } + } + return 0; +} + +u32 JKRDvdArchive::fetchResource_subroutine(long entryNum, u32 offset, u32 size, + JKRHeap* heap, int fileCompression, + int archiveCompression, u8** pBuf) +{ + u32 alignedSize = ALIGN_NEXT(size, 32); + + u8* buffer; + switch (archiveCompression) + { + case JKRCOMPRESSION_NONE: + { + switch (fileCompression) + { + case JKRCOMPRESSION_NONE: + buffer = (u8*)JKRAllocFromHeap(heap, alignedSize, 32); + JUT_ASSERT(buffer != 0); + + JKRDvdToMainRam(entryNum, buffer, EXPAND_SWITCH_DEFAULT, alignedSize, + nullptr, JKRDvdRipper::ALLOC_DIR_TOP, offset, + nullptr); + *pBuf = buffer; + return alignedSize; + + case JKRCOMPRESSION_YAY0: + case JKRCOMPRESSION_YAZ0: + u8* header = (u8*)JKRAllocFromHeap(heap, 0x20, 0x20); + JKRDvdToMainRam(entryNum, header, EXPAND_SWITCH_NONE, 0x20, nullptr, + JKRDvdRipper::ALLOC_DIR_TOP, offset, nullptr); + + alignedSize = JKRDecompExpandSize(header); + JKRFreeToHeap(heap, header); + buffer = (u8*)JKRAllocFromHeap(heap, alignedSize, 0x20); + JUT_ASSERT(buffer); + + JKRDvdToMainRam(entryNum, buffer, EXPAND_SWITCH_DECOMPRESS, + alignedSize, nullptr, JKRDvdRipper::ALLOC_DIR_TOP, + offset, nullptr); + *pBuf = buffer; + return alignedSize; + } + } + case JKRCOMPRESSION_YAZ0: + { + buffer = (u8*)JKRAllocFromHeap(heap, alignedSize, 32); + JUT_ASSERT(buffer); + JKRDvdToMainRam(entryNum, buffer, EXPAND_SWITCH_DECOMPRESS, size, nullptr, + JKRDvdRipper::ALLOC_DIR_TOP, offset, nullptr); + *pBuf = buffer; + return alignedSize; + } + + case JKRCOMPRESSION_YAY0: + { + JPANIC(612, "Sorry, not prepared for SZP archive.\n"); + return 0; + } + + default: + { + JPANIC(617, ":::??? bad sequence\n"); + } + } + return 0; +} diff --git a/src/JSystem/JKernel/JKRDvdFile.cpp b/src/JSystem/JKernel/JKRDvdFile.cpp index 7b004571..bfa4372e 100644 --- a/src/JSystem/JKernel/JKRDvdFile.cpp +++ b/src/JSystem/JKernel/JKRDvdFile.cpp @@ -29,12 +29,12 @@ void JKRDvdFile::initiate() { /* Reference to self. Used to retrieve reference in the DVDReadAsync * DVDCallback func. */ this->mDvdFileInfo.mFile = this; - OSInitMutex(&this->mMutex1); - OSInitMutex(&this->mMutex2); - OSInitMessageQueue(&this->mMessageQueue2, &this->mMsg2, 1); - OSInitMessageQueue(&this->mMessageQueue1, &this->mMsg1, 1); - this->mThread2 = nullptr; - this->mThread1 = nullptr; + OSInitMutex(&this->mDvdMutex); + OSInitMutex(&this->mAramMutex); + OSInitMessageQueue(&this->mDvdMessageQueue, &this->mDvdMessage, 1); + OSInitMessageQueue(&this->mAramMessageQueue, &this->mAramMessage, 1); + this->mDvdThread = nullptr; + this->mAramThread = nullptr; this->_58 = 0; } @@ -68,29 +68,31 @@ bool JKRDvdFile::close() { if (DVDClose(&this->mDvdFileInfo)) { this->mFileOpen = false; return sDvdList.remove(&this->mLink); - } else { + } + else { OSErrorLine(212, "cannot close DVD file\n"); /* JKRDvdFile.cpp line 212 */ } } } int JKRDvdFile::readData(void* data, s32 length, s32 ofs) { - OSLockMutex(&this->mMutex1); + OSLockMutex(&this->mDvdMutex); s32 retAddr; - if (this->mThread2 != nullptr) { - OSUnlockMutex(&this->mMutex1); + if (this->mDvdThread != nullptr) { + OSUnlockMutex(&this->mDvdMutex); return -1; - } else { - this->mThread2 = OSGetCurrentThread(); + } + else { + this->mDvdThread = OSGetCurrentThread(); retAddr = -1; if (DVDReadAsync(&this->mDvdFileInfo, data, length, ofs, - JKRDvdFile::doneProcess)) { + JKRDvdFile::doneProcess)) { retAddr = this->sync(); } - this->mThread2 = nullptr; - OSUnlockMutex(&this->mMutex1); + this->mDvdThread = nullptr; + OSUnlockMutex(&this->mDvdMutex); } return retAddr; @@ -101,14 +103,14 @@ int JKRDvdFile::writeData(const void* data, s32 length, s32 ofs) { return -1; } s32 JKRDvdFile::sync() { OSMessage m; - OSLockMutex(&this->mMutex1); - OSReceiveMessage(&this->mMessageQueue2, &m, OS_MESSAGE_BLOCK); - this->mThread2 = nullptr; - OSUnlockMutex(&this->mMutex1); + OSLockMutex(&this->mDvdMutex); + OSReceiveMessage(&this->mDvdMessageQueue, &m, OS_MESSAGE_BLOCK); + this->mDvdThread = nullptr; + OSUnlockMutex(&this->mDvdMutex); return (s32)m; } void JKRDvdFile::doneProcess(s32 result, DVDFileInfo* info) { - OSSendMessage(&static_cast(info)->mFile->mMessageQueue2, - (OSMessage)result, OS_MESSAGE_NOBLOCK); + OSSendMessage(&static_cast(info)->mFile->mDvdMessageQueue, + (OSMessage)result, OS_MESSAGE_NOBLOCK); } diff --git a/src/JSystem/JKernel/JKRDvdRipper.cpp b/src/JSystem/JKernel/JKRDvdRipper.cpp index d17dbf47..5a698305 100644 --- a/src/JSystem/JKernel/JKRDvdRipper.cpp +++ b/src/JSystem/JKernel/JKRDvdRipper.cpp @@ -17,7 +17,7 @@ static u8* nextSrcData(u8* nowData); void* JKRDvdRipper::loadToMainRAM(const char* file, u8* buf, JKRExpandSwitch expandSwitch, u32 maxDest, JKRHeap* heap, EAllocDirection allocDir, u32 offset, int* compressMode) { JKRDvdFile dvdFile; - + if (!dvdFile.open(file)) { return nullptr; } @@ -28,7 +28,7 @@ void* JKRDvdRipper::loadToMainRAM(const char* file, u8* buf, JKRExpandSwitch exp void* JKRDvdRipper::loadToMainRAM(s32 entrynum, u8* buf, JKRExpandSwitch expandSwitch, u32 maxDest, JKRHeap* heap, EAllocDirection allocDir, u32 offset, int* compressMode) { JKRDvdFile dvdFile; - + if (!dvdFile.open(entrynum)) { return nullptr; } @@ -108,9 +108,9 @@ void* JKRDvdRipper::loadToMainRAM(JKRDvdFile* file, u8* buf, JKRExpandSwitch exp u8* aligned_buf = (u8*)ALIGN_NEXT((u32)buffer, 32); while (true) { if (DVDReadPrio(file->getFileInfo(), aligned_buf, 32, offset, 2) >= 0) { - break; + break; } - + if (JKRDvdRipper::errorRetry == false) { return nullptr; } @@ -155,7 +155,7 @@ void* JKRDvdRipper::loadToMainRAM(JKRDvdFile* file, u8* buf, JKRExpandSwitch exp } /* Looks like a bug here */ - #ifndef FIXES +#ifndef FIXES if (DVDReadPrio(file->getFileInfo(), mem, fileSize, 0, 2) < 0) { if (JKRDvdRipper::errorRetry == false) { VIWaitForRetrace(); @@ -169,7 +169,7 @@ void* JKRDvdRipper::loadToMainRAM(JKRDvdFile* file, u8* buf, JKRExpandSwitch exp JKRFree(mem); return buf; } - #else +#else while (DVDReadPrio(file->getFileInfo(), mem, fileSize, 0, 2) < 0) { if (JKRDvdRipper::errorRetry == false) { if (allocated) { @@ -179,13 +179,13 @@ void* JKRDvdRipper::loadToMainRAM(JKRDvdFile* file, u8* buf, JKRExpandSwitch exp JKRFree(mem); return nullptr; } - + VIWaitForRetrace(); } JKRDecompress(mem, buf, finalSize, 0); JKRFree(mem); - #endif +#endif } else if (fileCompressMode == JKRDecomp::SZS) { JKRDecompressFromDVD(file, buf, fileSize, finalSize, offset, 0); @@ -215,12 +215,12 @@ static u32 fileOffset; static u32 readCount; static u32 maxDest; -static int JKRDecompressFromDVD(JKRDvdFile* _srcFile, void* buf, u32 size, u32 _maxDest, u32 _fileOffset, u32 _srcOffset) { +int JKRDecompressFromDVD(JKRDvdFile* _srcFile, void* buf, u32 size, u32 _maxDest, u32 _fileOffset, u32 _srcOffset) { int res = 0; szpBuf = (u8*)JKRAllocFromSysHeap(SZP_BUFFERSIZE, -32); szpEnd = szpBuf + SZP_BUFFERSIZE; - + if (_fileOffset != 0) { refBuf = (u8*)JKRAllocFromSysHeap(REF_BUFFERSIZE, -4); refEnd = refBuf + REF_BUFFERSIZE; @@ -252,148 +252,148 @@ static int JKRDecompressFromDVD(JKRDvdFile* _srcFile, void* buf, u32 size, u32 _ } static int decompSZS_subroutine(u8* src, u8* dest) { - u8 *endPtr; + u8* endPtr; s32 validBitCount = 0; s32 currCodeByte = 0; u32 ts = 0; if ((s32)src[0] != 'Y' || (s32)src[1] != 'a' || (s32)src[2] != 'z' || (s32)src[3] != '0') { - return -1; + return -1; } - SZPHeader *header = (SZPHeader *)src; + SZPHeader* header = (SZPHeader*)src; endPtr = dest + (header->decompSize - fileOffset); if (endPtr > dest + maxDest) { - endPtr = dest + maxDest; + endPtr = dest + maxDest; } src += 0x10; do { - if (validBitCount == 0) + if (validBitCount == 0) + { + if ((src > srcLimit) && transLeft) { - if ((src > srcLimit) && transLeft) - { - src = nextSrcData(src); - if (!src) - { - return -1; - } - } - currCodeByte = *src; - validBitCount = 8; - src++; + src = nextSrcData(src); + if (!src) + { + return -1; + } } - if (currCodeByte & 0x80) + currCodeByte = *src; + validBitCount = 8; + src++; + } + if (currCodeByte & 0x80) + { + if (fileOffset != 0) { - if (fileOffset != 0) + if (readCount >= fileOffset) + { + *dest = *src; + dest++; + ts++; + if (dest == endPtr) { - if (readCount >= fileOffset) - { - *dest = *src; - dest++; - ts++; - if (dest == endPtr) - { - break; - } - } - *(refCurrent++) = *src; - if (refCurrent == refEnd) - { - refCurrent = refBuf; - } - src++; + break; } - else - { - *dest = *src; - dest++; - src++; - ts++; - if (dest == endPtr) - { - break; - } - } - readCount++; + } + *(refCurrent++) = *src; + if (refCurrent == refEnd) + { + refCurrent = refBuf; + } + src++; } else { - u32 dist = src[1] | (src[0] & 0x0f) << 8; - 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); - } + *dest = *src; + dest++; + src++; + ts++; + if (dest == endPtr) + { + break; + } } - currCodeByte <<= 1; - validBitCount--; + readCount++; + } + else + { + u32 dist = src[1] | (src[0] & 0x0f) << 8; + 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; @@ -442,16 +442,16 @@ static u8* nextSrcData(u8* nowData) { break; } // Oopsies, forgot to call the function - #ifndef FIXES +#ifndef FIXES if (JKRDvdRipper::isErrorRetry == false) { return nullptr; } - #else +#else if (JKRDvdRipper::isErrorRetry() == false) { return nullptr; } - #endif - +#endif + VIWaitForRetrace(); } diff --git a/src/JSystem/JKernel/JKRExpHeap.cpp b/src/JSystem/JKernel/JKRExpHeap.cpp new file mode 100644 index 00000000..2efb3740 --- /dev/null +++ b/src/JSystem/JKernel/JKRExpHeap.cpp @@ -0,0 +1,1099 @@ +#include "JSystem/JSystem.h" +#include "JSystem/JSupport.h" +#include "JSystem/JUtility/JUTAssertion.h" +#include "JSystem/JUtility/JUTConsole.h" +#include "JSystem/JKernel/JKRExpHeap.h" + +static u32 whatdo; +static u32 whatdo2; +static u32 DBfoundSize; +static u32 DBfoundOffset; +static JKRExpHeap::CMemBlock* DBfoundBlock; +static JKRExpHeap::CMemBlock* DBnewFreeBlock; +static JKRExpHeap::CMemBlock* DBnewUsedBlock; + +JKRExpHeap* JKRExpHeap::createRoot(int maxHeaps, bool errorFlag) +{ + JKRExpHeap* heap = nullptr; + if (!sRootHeap) + { + void* memory; + u32 memorySize; + initArena((char**)&memory, &memorySize, maxHeaps); + u8* start = (u8*)memory + ALIGN_NEXT(sizeof(JKRExpHeap), 0x10); + u32 alignedSize = memorySize - ALIGN_NEXT(sizeof(JKRExpHeap), 0x10); + heap = new (memory) JKRExpHeap(start, alignedSize, nullptr, errorFlag); + sRootHeap = heap; + } + heap->_6E = true; + return heap; +} + +JKRExpHeap* JKRExpHeap::create(u32 size, JKRHeap* parent, bool errorFlag) +{ + JKRExpHeap* newHeap; + if (!parent) + { + parent = sRootHeap; + } + + u32 alignedSize = ALIGN_PREV(size, 0x10); + s32 expHeapSize = ALIGN_NEXT(sizeof(JKRExpHeap), 0x10); + if (alignedSize < 0x90) + return nullptr; + + u8* memory = (u8*)JKRAllocFromHeap(parent, alignedSize, 0x10); + u8* dataPtr = memory + expHeapSize; + if (!memory) + { + return nullptr; + } + if ((int)(alignedSize - expHeapSize) < 0x10) { + JKRFree(memory); + return nullptr; + } + + newHeap = new (memory) JKRExpHeap(dataPtr, alignedSize - expHeapSize, parent, errorFlag); + if (newHeap == nullptr) + { + JKRFree(memory); + return nullptr; + }; + newHeap->_6E = false; + return newHeap; +} + +JKRExpHeap* JKRExpHeap::create(void* ptr, u32 size, JKRHeap* parent, bool errorFlag) +{ + JKRHeap* parent2; + if (parent == nullptr) + { + parent2 = sRootHeap->find(ptr); + if (!parent2) + return nullptr; + } + else + { + parent2 = parent; + } + + JKRExpHeap* newHeap = nullptr; + u32 expHeapSize = ALIGN_NEXT(sizeof(JKRExpHeap), 0x10); + + if (size < expHeapSize) + return nullptr; + + void* dataPtr = (u8*)ptr + expHeapSize; + u32 alignedSize = ALIGN_PREV((u32)ptr + size - (u32)dataPtr, 0x10); + + if (ptr) + newHeap = new (ptr) JKRExpHeap(dataPtr, alignedSize, parent2, errorFlag); + + newHeap->_6E = true; + newHeap->_70 = ptr; + newHeap->_74 = size; + return newHeap; +} + +JKRExpHeap::JKRExpHeap(void* p1, u32 p2, JKRHeap* p3, bool p4) + : JKRHeap(p1, p2, p3, p4) +{ + mCurrentAllocMode = 0; + mCurrentGroupID = 0xFF; + mHead = static_cast(p1); + mTail = mHead; + mHead->initiate(nullptr, nullptr, p2 - 0x10, 0, 0); + mHeadUsedList = nullptr; + mTailUsedList = nullptr; +} + +JKRExpHeap::~JKRExpHeap() { dispose(); } + +s32 JKRExpHeap::do_changeGroupID(unsigned char groupID) +{ + lock(); + u8 oldGroupID = mCurrentGroupID; + mCurrentGroupID = groupID; + unlock(); + return oldGroupID; +} + +void* JKRExpHeap::do_alloc(u32 size, int alignment) +{ + lock(); + if (size < 4) { + + size = 4; + } + whatdo2 = 0; + whatdo = 0; + + void* ptr; + if (alignment >= 0) + { + + if (alignment <= 4) { + whatdo = 1; + ptr = allocFromHead(size); + } + + else { + whatdo = 2; + ptr = allocFromHead(size, alignment); + } + } + else + { + if (-alignment <= 4) { + whatdo = 3; + ptr = allocFromTail(size); + } + else { + whatdo = 4; + ptr = allocFromTail(size, -alignment); + } + + } + if (ptr == nullptr) + { + JUTWarningConsole_f(":::cannot alloc memory (0x%x byte).\n", size); + if (mErrorFlag == true) + callErrorHandler(this, size, alignment); + } + unlock(); + + return ptr; +} + +void* JKRExpHeap::allocFromHead(u32 size, int align) +{ + CMemBlock* newFreeBlock; + CMemBlock* newUsedBlock; + + size = ALIGN_NEXT(size, 4); + int foundSize = -1; + u32 foundOffset = 0; + CMemBlock* foundBlock = nullptr; + + for (CMemBlock* block = mHead; block; block = block->mNext) + { + u32 offset = ALIGN_PREV(align - 1 + (u32)block->getContent(), align) - (u32)block->getContent(); + if (block->mAllocatedSpace < size + offset) + { + continue; + } + if (foundSize <= (u32)block->mAllocatedSpace) + { + continue; + } + foundSize = block->mAllocatedSpace; + foundBlock = block; + foundOffset = offset; + if (mCurrentAllocMode != 0) + { + break; + } + u32 blockSize = block->mAllocatedSpace; + if (blockSize == size) + { + break; + } + } + + DBfoundSize = foundSize; + DBfoundOffset = foundOffset; + DBfoundBlock = foundBlock; + + if (foundBlock) + { + if (foundOffset >= sizeof(CMemBlock)) + { + whatdo2++; + CMemBlock* prev = foundBlock->mPrev; + CMemBlock* next = foundBlock->mNext; + newUsedBlock = foundBlock->allocFore(foundOffset - sizeof(CMemBlock), 0, 0, 0, 0); + + if (newUsedBlock) + { + whatdo2 += 2; + newFreeBlock = newUsedBlock->allocFore(size, mCurrentGroupID, 0, 0, 0); + } + else + { + newFreeBlock = nullptr; + } + if (newFreeBlock) + { + setFreeBlock(foundBlock, prev, newFreeBlock); + } + else + { + setFreeBlock(foundBlock, prev, next); + } + if (newFreeBlock) + { + whatdo2 += 4; + setFreeBlock(newFreeBlock, foundBlock, next); + } + + appendUsedList(newUsedBlock); + whatdo2 += 0x8; + + DBnewFreeBlock = newFreeBlock; + DBnewUsedBlock = newUsedBlock; + + return newUsedBlock->getContent(); + } + + if (foundOffset != 0) + { + whatdo2 += 0x10; + CMemBlock* prev = foundBlock->mPrev; + CMemBlock* next = foundBlock->mNext; + removeFreeBlock(foundBlock); + newUsedBlock = (CMemBlock*)((u32)foundBlock + foundOffset); + newUsedBlock->mAllocatedSpace = foundBlock->mAllocatedSpace - foundOffset; + newFreeBlock = newUsedBlock->allocFore(size, mCurrentGroupID, (u8)foundOffset, 0, 0); + if (newFreeBlock) + { + whatdo2 += 0x20; + setFreeBlock(newFreeBlock, prev, next); + } + appendUsedList(newUsedBlock); + whatdo2 += 0x40; + return newUsedBlock->getContent(); + } + else + { + whatdo2 += 0x80; + CMemBlock* prev = foundBlock->mPrev; + CMemBlock* next = foundBlock->mNext; + newFreeBlock = foundBlock->allocFore(size, mCurrentGroupID, 0, 0, 0); + removeFreeBlock(foundBlock); + if (newFreeBlock) + { + whatdo2 += 0x100; + setFreeBlock(newFreeBlock, prev, next); + } + appendUsedList(foundBlock); + whatdo2 += 0x200; + return foundBlock->getContent(); + } + } + + whatdo2 += 0x400; + return nullptr; +} + +void* JKRExpHeap::allocFromHead(u32 size) +{ + size = ALIGN_NEXT(size, 4); + int foundSize = -1; + CMemBlock* foundBlock = nullptr; + + for (CMemBlock* block = mHead; block; block = block->mNext) + { + if (block->mAllocatedSpace < size) + { + continue; + } + if (foundSize <= (u32)block->mAllocatedSpace) + { // TODO: figure out if mAllocatedSpace is u32 or not + + continue; + } + foundSize = block->mAllocatedSpace; + foundBlock = block; + if (mCurrentAllocMode != 0) + { + + break; + } + if (foundSize == size) + { + + break; + } + } + whatdo2++; + if (foundBlock) + { + CMemBlock* newblock = foundBlock->allocFore(size, mCurrentGroupID, 0, 0, 0); + whatdo2 += 2; + if (newblock) + { + whatdo2 += 4; + setFreeBlock(newblock, foundBlock->mPrev, foundBlock->mNext); + } + else + { + whatdo2 += 8; + removeFreeBlock(foundBlock); + } + + appendUsedList(foundBlock); + whatdo2 += 0x10; + return foundBlock->getContent(); + } + whatdo2 += 0x20; + return nullptr; +} + +void* JKRExpHeap::allocFromTail(u32 size, int align) +{ + u32 offset = 0; + CMemBlock* foundBlock = nullptr; + CMemBlock* newBlock = nullptr; + u32 usedSize; + u32 start; + + for (CMemBlock* block = mTail; block; block = block->mPrev) + { + start = ALIGN_PREV((u32)block->getContent() + block->mAllocatedSpace - size, align); + usedSize = (u32)block->getContent() + block->mAllocatedSpace - start; + if (block->mAllocatedSpace >= usedSize) + { + foundBlock = block; + offset = block->mAllocatedSpace - usedSize; + newBlock = (CMemBlock*)start - 1; + break; + } + } + if (foundBlock != nullptr) + { + if (offset >= sizeof(CMemBlock)) + { + newBlock->initiate(nullptr, nullptr, usedSize, mCurrentGroupID, -0x80); + foundBlock->mAllocatedSpace = foundBlock->mAllocatedSpace - usedSize - sizeof(CMemBlock); + appendUsedList(newBlock); + return newBlock->getContent(); + } + else + { + if (offset != 0) + { + removeFreeBlock(foundBlock); + newBlock->initiate(nullptr, nullptr, usedSize, mCurrentGroupID, offset | 0x80); + appendUsedList(newBlock); + return newBlock->getContent(); + } + else + { + removeFreeBlock(foundBlock); + newBlock->initiate(nullptr, nullptr, usedSize, mCurrentGroupID, -0x80); + appendUsedList(newBlock); + return newBlock->getContent(); + } + } + } + return nullptr; +} + +void* JKRExpHeap::allocFromTail(u32 size) +{ + u32 size2 = ALIGN_NEXT(size, 4); + CMemBlock* foundBlock = nullptr; + for (CMemBlock* block = mTail; block; block = block->mPrev) + { + if (block->mAllocatedSpace >= size2) + { + foundBlock = block; + break; + } + } + if (foundBlock != nullptr) + { + CMemBlock* usedBlock = foundBlock->allocBack(size2, 0, 0, mCurrentGroupID, 0); + CMemBlock* freeBlock; + if (usedBlock) + { + freeBlock = foundBlock; + } + else + { + removeFreeBlock(foundBlock); + usedBlock = foundBlock; + freeBlock = nullptr; + } + if (freeBlock) + { + setFreeBlock(freeBlock, foundBlock->mPrev, foundBlock->mNext); + } + appendUsedList(usedBlock); + return usedBlock->getContent(); + } + return nullptr; +} + +void JKRExpHeap::do_free(void* memblock) +{ + lock(); + if (mStart <= memblock && memblock <= mEnd) + { + CMemBlock* block = CMemBlock::getHeapBlock(memblock); + if (block != nullptr) + { + block->free(this); + } + } + else + { + JUT_WARNING_F("free: memblock %x not in heap %x", memblock, this); + } + unlock(); +} + +int JKRExpHeap::freeGroup(u8 groupID) +{ + lock(); + CMemBlock* block = mHeadUsedList; + int count = 0; + while (block != nullptr) + { + if (block->mGroupID == groupID) + { + dispose(block + 1, block->mAllocatedSpace); + CMemBlock* temp = block->mNext; + block->free(this); + count++; + block = temp; + } + else + { + block = block->mNext; + } + } + unlock(); + return count; +} + +void JKRExpHeap::do_freeAll() +{ + lock(); + JKRHeap::callAllDisposer(); + mHead = (CMemBlock*)mStart; + mTail = mHead; + mHead->initiate(nullptr, nullptr, mSize - sizeof(CMemBlock), 0, 0); + mHeadUsedList = nullptr; + mTailUsedList = nullptr; + unlock(); +} + +void JKRExpHeap::do_freeTail() +{ + lock(); + for (CMemBlock* block = mHeadUsedList; block != nullptr;) + { + if ((block->mFlags & 0x80) != 0) + { + dispose(block + 1, block->mAllocatedSpace); + CMemBlock* temp = block->mNext; + block->free(this); + block = temp; + } + else + { + block = block->mNext; + } + } + unlock(); +} + +s32 JKRExpHeap::do_resize(void* ptr, u32 size) +{ + lock(); + CMemBlock* block = CMemBlock::getHeapBlock(ptr); + if (block == nullptr || ptr < mStart || mEnd < ptr) + { + unlock(); + return -1; + } + size = ALIGN_NEXT(size, 4); + if (size == block->mAllocatedSpace) + { + unlock(); + return size; + } + if (size > block->mAllocatedSpace) + { + CMemBlock* foundBlock = nullptr; + for (CMemBlock* freeBlock = mHead; freeBlock; freeBlock = freeBlock->mNext) + { + if (freeBlock == (CMemBlock*)((u32)(block + 1) + block->mAllocatedSpace)) + { + foundBlock = freeBlock; + break; + } + } + if (foundBlock == nullptr) + { + unlock(); + return -1; + } + if (size > block->mAllocatedSpace + sizeof(CMemBlock) + foundBlock->mAllocatedSpace) + { + unlock(); + return -1; + } + removeFreeBlock(foundBlock); + block->mAllocatedSpace += foundBlock->mAllocatedSpace + sizeof(CMemBlock); + if (block->mAllocatedSpace - size > sizeof(CMemBlock)) + { + CMemBlock* newBlock = block->allocFore(size, block->mGroupID, block->mFlags, 0, 0); + if (newBlock) + { + recycleFreeBlock(newBlock); + } + } + } + else + { + if (block->mAllocatedSpace - size > sizeof(CMemBlock)) + { + CMemBlock* freeBlock = block->allocFore(size, block->mGroupID, block->mFlags, 0, 0); + if (freeBlock) + { + recycleFreeBlock(freeBlock); + } + } + } + unlock(); + return block->mAllocatedSpace; +} + +s32 JKRExpHeap::do_getSize(void* ptr) +{ + lock(); + CMemBlock* block = CMemBlock::getHeapBlock(ptr); + if (block == nullptr || ptr < mStart || mEnd < ptr) + { + unlock(); + return -1; + } + unlock(); + return block->mAllocatedSpace; +} + +s32 JKRExpHeap::do_getFreeSize() +{ + lock(); + int maxFreeSize = 0; + for (CMemBlock* block = mHead; block != nullptr; block = block->mNext) + { + if (maxFreeSize < block->mAllocatedSpace) + maxFreeSize = block->mAllocatedSpace; + } + unlock(); + return maxFreeSize; +} + +s32 JKRExpHeap::do_getTotalFreeSize() +{ + int freeSize = 0; + lock(); + for (CMemBlock* block = mHead; block != nullptr; block = block->mNext) + { + freeSize += block->mAllocatedSpace; + } + unlock(); + return freeSize; +} + +s32 JKRExpHeap::getUsedSize(u8 groupId) const +{ + JKRExpHeap* this2 = const_cast(this); + this2->lock(); + u32 size = 0; + for (CMemBlock* block = mHeadUsedList; block; block = block->mNext) + { + u8 blockGroupId = block->mGroupID; + if (blockGroupId == groupId) + { + size += block->mAllocatedSpace + sizeof(CMemBlock); + } + } + this2->unlock(); + return size; +} + +bool JKRExpHeap::isEmpty() +{ + u32 newSize; + JUT_ASSERT(1269, newSize > 0); + return true; +} + +bool JKRExpHeap::check() +{ + lock(); + int totalBytes = 0; + bool ok = true; + for (CMemBlock* block = mHeadUsedList; block; block = block->mNext) + { + if (!block->isValid()) + { + ok = false; + JUTWarningConsole_f(":::addr %08x: bad heap signature. (%c%c)\n", block, JSUHiByte(block->mUsageHeader), + JSULoByte(block->mUsageHeader)); + } + if (block->mNext) + { + if (!block->mNext->isValid()) + { + ok = false; + JUTWarningConsole_f(":::addr %08x: bad next pointer (%08x)\nabort\n", block, block->mNext); + break; + } + if (block->mNext->mPrev != block) + { + ok = false; + JUTWarningConsole_f(":::addr %08x: bad previous pointer (%08x)\n", block->mNext, block->mNext->mPrev); + } + } + else + { + if (mTailUsedList != block) + { + ok = false; + JUTWarningConsole_f(":::addr %08x: bad used list(REV) (%08x)\n", block, mTailUsedList); + } + } + totalBytes += sizeof(CMemBlock) + block->mAllocatedSpace + block->getAlignment(); + } + for (CMemBlock* block = mHead; block; block = block->mNext) + { + totalBytes += block->mAllocatedSpace + sizeof(CMemBlock); + if (block->mNext) + { + if (block->mNext->mPrev != block) + { + ok = false; + JUTWarningConsole_f(":::addr %08x: bad previous pointer (%08x)\n", block->mNext, block->mNext->mPrev); + } + if ((u32)block + block->mAllocatedSpace + sizeof(CMemBlock) > (u32)block->mNext) + { + ok = false; + JUTWarningConsole_f(":::addr %08x: bad block size (%08x)\n", block, block->mAllocatedSpace); + } + } + else + { + if (mTail != block) + { + ok = false; + JUTWarningConsole_f(":::addr %08x: bad used list(REV) (%08x)\n", block, mTail); + } + } + } + if (totalBytes != mSize) + { + ok = false; + JUTWarningConsole_f(":::bad total memory block size (%08X, %08X)\n", mSize, totalBytes); + } + + if (!ok) + { + JUTWarningConsole(":::there is some error in this heap!\n"); + } + + unlock(); + return ok; +} + +void JKRExpHeap::appendUsedList(JKRExpHeap::CMemBlock* blockToAppend) +{ + if (!blockToAppend) + { + JPANIC(1543, ":::ERROR! appendUsedList\n"); + } + CMemBlock* block = mTailUsedList; + CMemBlock* tail = mTailUsedList; + blockToAppend->mUsageHeader = 'HM'; + if (tail) + { + tail->mNext = blockToAppend; + blockToAppend->mPrev = tail; + } + else + { + blockToAppend->mPrev = nullptr; + } + mTailUsedList = blockToAppend; + if (!mHeadUsedList) + { + mHeadUsedList = blockToAppend; + } + blockToAppend->mNext = nullptr; +} + +void JKRExpHeap::setFreeBlock(JKRExpHeap::CMemBlock* p1, JKRExpHeap::CMemBlock* p2, JKRExpHeap::CMemBlock* p3) +{ + if (p2 == nullptr) + { + mHead = p1; + p1->mPrev = nullptr; + } + else + { + p2->mNext = p1; + p1->mPrev = p2; + } + if (p3 == nullptr) + { + mTail = p1; + p1->mNext = nullptr; + } + else + { + p3->mPrev = p1; + p1->mNext = p3; + } + p1->mUsageHeader = 0; +} + +void JKRExpHeap::removeFreeBlock(JKRExpHeap::CMemBlock* blockToRemove) +{ + CMemBlock* prev = blockToRemove->mPrev; + CMemBlock* next = blockToRemove->mNext; + if (prev == nullptr) + mHead = next; + else + prev->mNext = next; + if (next == nullptr) + mTail = prev; + else + next->mPrev = prev; +} + +void JKRExpHeap::removeUsedBlock(JKRExpHeap::CMemBlock* blockToRemove) +{ + // UNUSED FUNCTION + CMemBlock* prev = blockToRemove->mPrev; + CMemBlock* next = blockToRemove->mNext; + if (prev == nullptr) + mHeadUsedList = next; + else + prev->mNext = next; + if (next == nullptr) + mTailUsedList = prev; + else + next->mPrev = prev; +} + +void JKRExpHeap::recycleFreeBlock(JKRExpHeap::CMemBlock* block) +{ + JKRExpHeap::CMemBlock* newBlock = block; + int size = block->mAllocatedSpace; + void* blockEnd = (u8*)block + size; + block->mUsageHeader = 0; + // int offset = block->mFlags & 0x7f; + + if ((u32)(block->mFlags & 0x7f) != 0) + { + newBlock = (CMemBlock*)((u8*)block - (block->mFlags & 0x7f)); + size += (block->mFlags & 0x7f); + blockEnd = (u8*)newBlock + size; + newBlock->mGroupID = 0; + newBlock->mFlags = 0; + newBlock->mAllocatedSpace = size; + } + + if (!mHead) + { + newBlock->initiate(nullptr, nullptr, size, 0, 0); + mHead = newBlock; + mTail = newBlock; + setFreeBlock(newBlock, nullptr, nullptr); + return; + } + if (mHead >= blockEnd) + { + newBlock->initiate(nullptr, nullptr, size, 0, 0); + setFreeBlock(newBlock, nullptr, mHead); + joinTwoBlocks(newBlock); + return; + } + if (mTail <= newBlock) + { + newBlock->initiate(nullptr, nullptr, size, 0, 0); + setFreeBlock(newBlock, mTail, nullptr); + joinTwoBlocks(newBlock->mPrev); + return; + } + for (CMemBlock* freeBlock = mHead; freeBlock; freeBlock = freeBlock->mNext) + { + if (freeBlock >= newBlock || newBlock >= freeBlock->mNext) + { + continue; + } + newBlock->mNext = freeBlock->mNext; + newBlock->mPrev = freeBlock; + freeBlock->mNext = newBlock; + newBlock->mNext->mPrev = newBlock; + newBlock->mGroupID = 0; + joinTwoBlocks(newBlock); + joinTwoBlocks(freeBlock); + return; + } +} + +// This functions doesn't match for the debug build, however functionality wise it's the same +// https://decomp.me/scratch/UOwNi +void JKRExpHeap::joinTwoBlocks(CMemBlock* block) +{ + // for some reason this gets rid of regswaps for the debug version, however is most likely incorrect + // u32 endAddr; + // u32 nextAddr; + // CMemBlock *next; + + u32 endAddr = (u32)(block + 1) + block->mAllocatedSpace; + CMemBlock* next = block->mNext; + u32 nextAddr = (u32)next - (next->mFlags & 0x7f); + if (endAddr > nextAddr) + { + JUTWarningConsole_f(":::Heap may be broken. (block = %x)", block); + JREPORTF(":::block = %x\n", block); + JREPORTF(":::joinTwoBlocks [%x %x %x][%x %x %x]\n", block, block->mFlags, block->mAllocatedSpace, block->mNext, block->mNext->mFlags, block->mNext->mAllocatedSpace); + JREPORTF(":::: endAddr = %x\n", endAddr); + JREPORTF(":::: nextAddr = %x\n", nextAddr); + JKRGetCurrentHeap()->dump(); + JPANIC(1824, ":::: Bad Block\n"); + } + if (endAddr == nextAddr) + { + block->mAllocatedSpace = next->mAllocatedSpace + sizeof(CMemBlock) + (next->mFlags & 0x7f) + block->mAllocatedSpace; + setFreeBlock(block, block->mPrev, next->mNext); + } +} + +bool JKRExpHeap::dump() +{ + lock(); + bool result = check(); + u32 usedBytes = 0; + u32 usedCount = 0; + u32 freeCount = 0; + JUTReportConsole(" attr address: size gid aln prev_ptr next_ptr\n"); + JUTReportConsole("(Used Blocks)\n"); + if (!mHeadUsedList) + { + JUTReportConsole(" NONE\n"); + } + for (CMemBlock* block = mHeadUsedList; block; block = block->mNext) + { + if (!block->isValid()) + { + JUTReportConsole_f("xxxxx %08x: -------- --- --- (-------- --------)\nabort\n", block); + break; + } + + JUTReportConsole_f("%s %08x: %08x %3d %3d (%08x %08x)\n", block->_isTempMemBlock() ? " temp" : "alloc", block->getContent(), + block->mAllocatedSpace, block->mGroupID, block->getAlignment(), block->mPrev, block->mNext); + usedBytes += sizeof(CMemBlock) + block->mAllocatedSpace + block->getAlignment(); + usedCount++; + } + JUTReportConsole("(Free Blocks)\n"); + if (!mHead) + { + JUTReportConsole(" NONE\n"); + } + for (CMemBlock* block = mHead; block; block = block->mNext) + { + JUTReportConsole_f("%s %08x: %08x %3d %3d (%08x %08x)\n", " free", block->getContent(), block->mAllocatedSpace, block->mGroupID, + block->getAlignment(), block->mPrev, block->mNext); + freeCount++; + } + float percent = ((float)usedBytes / (float)mSize) * 100.0f; + JUTReportConsole_f("%d / %d bytes (%6.2f%%) used (U:%d F:%d)\n", usedBytes, mSize, percent, usedCount, freeCount); + unlock(); + return result; +} + +bool JKRExpHeap::dump_sort() +{ + lock(); + bool result = check(); + u32 usedBytes = 0; + u32 usedCount = 0; + u32 freeCount = 0; + JUTReportConsole(" attr address: size gid aln prev_ptr next_ptr\n"); + JUTReportConsole("(Used Blocks)\n"); + if (mHeadUsedList == nullptr) + { + JUTReportConsole(" NONE\n"); + } + else + { + CMemBlock* var1 = nullptr; + while (true) + { + CMemBlock* block = (CMemBlock*)0xffffffff; + for (CMemBlock* iterBlock = mHeadUsedList; iterBlock; iterBlock = iterBlock->mNext) + { + if (var1 < iterBlock && iterBlock < block) + { + block = iterBlock; + } + } + if (block == (CMemBlock*)0xffffffff) + { + break; + } + if (!block->isValid()) + { + JUTReportConsole_f("xxxxx %08x: -------- --- --- (-------- --------)\nabort\n"); + break; + } + int offset = block->getAlignment(); + void* content = block->getContent(); + const char* type = block->_isTempMemBlock() ? " temp" : "alloc"; + JUTReportConsole_f("%s %08x: %08x %3d %3d (%08x %08x)\n", type, content, block->mAllocatedSpace, block->mGroupID, offset, + block->mPrev, block->mNext); + usedBytes += sizeof(CMemBlock) + block->mAllocatedSpace + block->getAlignment(); + usedCount++; + var1 = block; + } + } + JUTReportConsole("(Free Blocks)\n"); + if (mHead == nullptr) + { + JUTReportConsole(" NONE\n"); + } + for (CMemBlock* block = mHead; block; block = block->mNext) + { + JUTReportConsole_f("%s %08x: %08x %3d %3d (%08x %08x)\n", " free", block->getContent(), block->mAllocatedSpace, block->mGroupID, + block->getAlignment(), block->mPrev, block->mNext); + freeCount++; + } + float percent = ((float)usedBytes / (float)mSize) * 100.0f; + JUTReportConsole_f("%d / %d bytes (%6.2f%%) used (U:%d F:%d)\n", usedBytes, mSize, percent, usedCount, freeCount); + unlock(); + return result; +} + +// these didn't get deadstripped, workaround to generate it +static void genData() +{ + JUTWarningConsole_f("+---------------JKRExpHeap\n"); + JUTWarningConsole_f("| Align Group size ( prev , next )\n"); + JUTWarningConsole_f("| ---- FreeFirst\n"); + JUTWarningConsole_f("| %08x "); + JUTWarningConsole_f("%2x %3d %6x (%08x %08x)\n"); + JUTWarningConsole_f("| ---- FreeLast\n"); + JUTWarningConsole_f("| ---- UsedFirst\n"); + JUTWarningConsole_f("| ---- UsedLast\n"); + JUTWarningConsole_f("+---------------End\n"); +} + +void JKRExpHeap::CMemBlock::initiate(JKRExpHeap::CMemBlock* prev, JKRExpHeap::CMemBlock* next, u32 size, u8 groupID, u8 alignment) +{ + mUsageHeader = 'HM'; + mFlags = alignment; + mGroupID = groupID; + mAllocatedSpace = size; + mPrev = prev; + mNext = next; +} + +JKRExpHeap::CMemBlock* JKRExpHeap::CMemBlock::allocFore(u32 size, u8 groupId1, u8 alignment1, u8 groupId2, u8 alignment2) +{ + CMemBlock* block = nullptr; + mGroupID = groupId1; + mFlags = alignment1; + if (mAllocatedSpace >= size + sizeof(CMemBlock)) + { + block = (CMemBlock*)(size + (u32)this); + block = block + 1; + block->mGroupID = groupId2; + block->mFlags = alignment2; + block->mAllocatedSpace = mAllocatedSpace - (size + sizeof(CMemBlock)); + mAllocatedSpace = size; + } + return block; +} + +JKRExpHeap::CMemBlock* JKRExpHeap::CMemBlock::allocBack(unsigned long size, unsigned char groupID, unsigned char p3, + unsigned char allocGroupID, unsigned char p5) +{ + CMemBlock* newBlock = nullptr; + if (mAllocatedSpace >= size + sizeof(CMemBlock)) + { + newBlock = reinterpret_cast(mAllocatedSpace + reinterpret_cast(this) - size); + newBlock->mGroupID = allocGroupID; + newBlock->mFlags = p5 | 0x80; + newBlock->mAllocatedSpace = size; + mGroupID = groupID; + mFlags = p3; + mAllocatedSpace -= (size + sizeof(CMemBlock)); + } + else + { + mGroupID = allocGroupID; + mFlags = 0x80; + } + return newBlock; +} + +void* JKRExpHeap::CMemBlock::free(JKRExpHeap* heap) +{ + heap->removeUsedBlock(this); + heap->recycleFreeBlock(this); + return nullptr; +} + +JKRExpHeap::CMemBlock* JKRExpHeap::CMemBlock::getHeapBlock(void* mem) +{ + if (mem != nullptr && (static_cast(mem) - 1)->mUsageHeader == 0x484D) + { + return static_cast(mem) - 1; + } + return nullptr; +} + +void JKRExpHeap::state_register(JKRHeap::TState* p, u32 param_1) const +{ + JUT_ASSERT(p != 0); + JUT_ASSERT(p->getHeap() == this); + getState_(p); // not needed, however TP debug has it + setState_u32ID_(p, param_1); + if (param_1 <= 0xff) + { + setState_uUsedSize_(p, getUsedSize(param_1)); + } + else + { + setState_uUsedSize_(p, getUsedSize_((JKRExpHeap*)this)); + } + u32 checkCode = 0; + for (CMemBlock* block = mHeadUsedList; block; block = block->mNext) + { + if (param_1 <= 0xff) + { + u8 groupId = block->mGroupID; + if (groupId == param_1) + { + checkCode += (u32)block * 3; + } + } + else + { + checkCode += (u32)block * 3; + } + } + setState_u32CheckCode_(p, checkCode); +} + +bool JKRExpHeap::state_compare(const JKRHeap::TState& r1, const JKRHeap::TState& r2) const +{ + JUT_ASSERT(r1.getHeap() == r2.getHeap()); + bool result = true; + if (r1.mCheckCode != r2.mCheckCode) + { + result = false; + } + if (r1.mUsedSize != r2.mUsedSize) + { + result = false; + } + return result; +} diff --git a/src/JSystem/JKernel/JKRFile.cpp b/src/JSystem/JKernel/JKRFile.cpp index 894cdbfa..cb06f045 100644 --- a/src/JSystem/JKernel/JKRFile.cpp +++ b/src/JSystem/JKernel/JKRFile.cpp @@ -27,17 +27,17 @@ * Nonmatched function. Unused in Animal Crossing. */ void JKRFile::read(void* data, s32 length, s32 ofs) { - #ifdef JSYSTEM_DEBUG +#ifdef JSYSTEM_DEBUG if (!JKR_ISALIGNED(length, 32)) { JUTAssertion::showAssert(JUTAssertion::getSDevice(), __FILE__, __LINE__, "( length & 0x1f ) == 0"); } - #endif +#endif while (true) { if (this->readData(data, length, ofs) == length) { return; } - + VIWaitForRetrace(); } } diff --git a/src/JSystem/JKernel/JKRFileFinder.cpp b/src/JSystem/JKernel/JKRFileFinder.cpp new file mode 100644 index 00000000..e9a23781 --- /dev/null +++ b/src/JSystem/JKernel/JKRFileFinder.cpp @@ -0,0 +1,63 @@ +#include +#include "JSystem/JKernel/JKRFileFinder.h" +#include "JSystem/JKernel/JKRArchive.h" + +JKRArcFinder::JKRArcFinder(JKRArchive* archive, long startindex, long entries) : JKRFileFinder() +{ + mArchive = archive; + + mIsAvailable = entries > 0; + mStartIndex = startindex; + mEndIndex = startindex + entries - 1; + mNextIndex = mStartIndex; + + findNextFile(); +} + +bool JKRArcFinder::findNextFile() +{ + if (mIsAvailable) + { + mIsAvailable = (mNextIndex <= mEndIndex); + if (mIsAvailable) + { + JKRArchive::SDirEntry dirEntry; + mIsAvailable = mArchive->getDirEntry(&dirEntry, mNextIndex); + mBase.mFileName = dirEntry.mName; + mBase.mFileIndex = mNextIndex; + mBase.mFileID = dirEntry.mID; + mBase.mFileTypeFlags = dirEntry.mFlags; + mIsFileOrDir = FLAG_OFF(mBase.mFileTypeFlags, 2); + mNextIndex++; + } + } + return mIsAvailable; +} + +// UNUSED +JKRDvdFinder::JKRDvdFinder(const char* path) : JKRFileFinder() +{ + mIsDvdOpen = DVDOpenDir(const_cast(path), &mDir); + mIsAvailable = mIsDvdOpen; + findNextFile(); +} + +// UNUSED, not sure if it matches +bool JKRDvdFinder::findNextFile() +{ + if (mIsAvailable) + { + DVDDirEntry entry; + mIsAvailable = DVDReadDir(&mDir, &entry); + if (mIsAvailable) + { + mIsFileOrDir = (bool)entry.isDir; + mBase.mFileName = entry.name; + mBase.mFileIndex = entry.entryNum; + mBase.mFileID = 0; + + mBase.mFileTypeFlags = mIsFileOrDir ? 2 : 1; + } + } + return mIsAvailable; +} diff --git a/src/JSystem/JKernel/JKRFileLoader.cpp b/src/JSystem/JKernel/JKRFileLoader.cpp new file mode 100644 index 00000000..1eca1511 --- /dev/null +++ b/src/JSystem/JKernel/JKRFileLoader.cpp @@ -0,0 +1,165 @@ +#include +#include +#include "JSystem/JKernel/JKRFileLoader.h" + +JSUList JKRFileLoader::sVolumeList; +JKRFileLoader* JKRFileLoader::sCurrentVolume; + +JKRFileLoader::JKRFileLoader() : JKRDisposer(), mFileLoaderLink(this) +{ + mVolumeName = nullptr; + mVolumeType = 0; + mMountCount = 0; +} + +JKRFileLoader::~JKRFileLoader() +{ + if (sCurrentVolume == this) + sCurrentVolume = nullptr; +} + +void JKRFileLoader::unmount() +{ + if (mMountCount != 0) + { + if (--mMountCount == 0) + delete this; + } +} + +void JKRFileLoader::changeDirectory(const char* dir) +{ + JKRFileLoader* vol = findVolume(&dir); + if (vol) + vol->becomeCurrent(dir); +} + +void* JKRFileLoader::getGlbResource(const char* path) +{ + const char* components[2]; + components[0] = path; + JKRFileLoader* loader = findVolume(components); + return (loader == nullptr) ? nullptr : loader->getResource(components[0]); +} + +void* JKRFileLoader::getGlbResource(const char* name, JKRFileLoader* fileLoader) +{ + void* resource = nullptr; + if (fileLoader) + { + return fileLoader->getResource(0, name); + } + + JSUList& volumeList = getVolumeList(); + JSUListIterator iterator; + for (iterator = volumeList.getFirst(); iterator != volumeList.getEnd(); ++iterator) + { + resource = iterator->getResource(0, name); + if (resource) + break; + } + return resource; +} + +size_t JKRFileLoader::readGlbResource(void* resBuf, u32 bufSize, const char* volumeName, JKRExpandSwitch expandSwitch) +{ + JKRFileLoader* vol = findVolume(&volumeName); + + return vol == nullptr ? 0 : vol->readResource(resBuf, bufSize, volumeName, expandSwitch); +} + +bool JKRFileLoader::removeResource(void* resourceBuffer, JKRFileLoader* fileLoader) +{ + if (fileLoader) + { + return fileLoader->removeResource(resourceBuffer); + } + + JSUList& volumeList = getVolumeList(); + JSUListIterator iterator; + for (iterator = volumeList.getFirst(); iterator != volumeList.getEnd(); ++iterator) + { + if (iterator->removeResource(resourceBuffer)) + return true; + } + + return false; +} + +bool JKRFileLoader::detachResource(void* resourceBuffer, JKRFileLoader* fileLoader) +{ + if (fileLoader) + { + return fileLoader->detachResource(resourceBuffer); + } + + JSUList& volumeList = getVolumeList(); + JSUListIterator iterator; + for (iterator = volumeList.getFirst(); iterator != volumeList.getEnd(); ++iterator) + { + if (iterator->detachResource(resourceBuffer)) + return true; + } + + return false; +} + +JKRFileLoader* JKRFileLoader::findVolume(const char** volumeName) +{ + if (*volumeName[0] != '/') + { + return sCurrentVolume; + } + + char volumeNameBuffer[0x101]; + *volumeName = fetchVolumeName(volumeNameBuffer, ARRAY_COUNT(volumeNameBuffer), *volumeName); + + JSUList& volumeList = sVolumeList; + JSUListIterator iterator; + for (iterator = volumeList.getFirst(); iterator != volumeList.getEnd(); ++iterator) + { + if (strcmp(volumeNameBuffer, iterator->mVolumeName) == 0) + return iterator.getObject(); + } + return nullptr; +} + +JKRFileFinder* JKRFileLoader::findFirstFile(const char* volumeName) +{ + JKRFileFinder* ret = nullptr; + + JKRFileLoader* vol = findVolume(&volumeName); + if (vol) + ret = vol->getFirstFile(volumeName); + + return ret; +} + +const char* JKRFileLoader::fetchVolumeName(char* buffer, long bufferSize, const char* path) +{ + static char rootPath[] = "/"; + if (strcmp(path, "/") == 0) + { + strcpy(buffer, rootPath); + return rootPath; + } + else + { + path++; + while (*path != 0 && *path != '/') + { + if (1 < bufferSize) + { + *buffer = _tolower(*path); + buffer++; + bufferSize--; + } + path++; + } + buffer[0] = '\0'; + if (path[0] == '\0') + path = rootPath; + } + + return path; +} diff --git a/src/JSystem/JKernel/JKRHeap.cpp b/src/JSystem/JKernel/JKRHeap.cpp index 4a9c67e6..264d1b76 100644 --- a/src/JSystem/JKernel/JKRHeap.cpp +++ b/src/JSystem/JKernel/JKRHeap.cpp @@ -7,26 +7,26 @@ #include "dolphin/os/OSUtil.h" #include "dolphin/os/OSAddress.h" -JKRHeap *JKRHeap::sSystemHeap; -JKRHeap *JKRHeap::sCurrentHeap; -JKRHeap *JKRHeap::sRootHeap; -JKRHeapErrorHandler *JKRHeap::mErrorHandler; -void *JKRHeap::mCodeStart; -void *JKRHeap::mCodeEnd; -void *JKRHeap::mUserRamStart; -void *JKRHeap::mUserRamEnd; +JKRHeap* JKRHeap::sSystemHeap; +JKRHeap* JKRHeap::sCurrentHeap; +JKRHeap* JKRHeap::sRootHeap; +JKRHeapErrorHandler* JKRHeap::mErrorHandler; +void* JKRHeap::mCodeStart; +void* JKRHeap::mCodeEnd; +void* JKRHeap::mUserRamStart; +void* JKRHeap::mUserRamEnd; u32 JKRHeap::mMemorySize; bool JKRHeap::sDefaultFillFlag = true; -JKRHeap::JKRHeap(void *data, u32 size, JKRHeap *heap, bool errorFlag) : JKRDisposer(), - mChildTree(this), - mDisposerList() +JKRHeap::JKRHeap(void* data, u32 size, JKRHeap* heap, bool errorFlag) : JKRDisposer(), +mChildTree(this), +mDisposerList() { OSInitMutex(&mMutex); mSize = size; - mStart = (u8 *)data; - mEnd = ((u8 *)data + size); + mStart = (u8*)data; + mEnd = ((u8*)data + size); if (heap == nullptr) { becomeSystemHeap(); @@ -50,7 +50,7 @@ JKRHeap::JKRHeap(void *data, u32 size, JKRHeap *heap, bool errorFlag) : JKRDispo JKRHeap::~JKRHeap() { mChildTree.getParent()->removeChild(&mChildTree); - JSUTree *nextRootHeap = sRootHeap->mChildTree.getFirstChild(); + JSUTree* nextRootHeap = sRootHeap->mChildTree.getFirstChild(); if (sCurrentHeap == this) sCurrentHeap = !nextRootHeap ? sRootHeap : nextRootHeap->getObject(); @@ -58,53 +58,53 @@ JKRHeap::~JKRHeap() sSystemHeap = !nextRootHeap ? sRootHeap : nextRootHeap->getObject(); } -bool JKRHeap::initArena(char **outUserRamStart, u32 *outUserRamSize, int numHeaps) +bool JKRHeap::initArena(char** outUserRamStart, u32* outUserRamSize, int numHeaps) { - void *arenaLo = OSGetArenaLo(); - void *arenaHi = OSGetArenaHi(); + void* arenaLo = OSGetArenaLo(); + void* arenaHi = OSGetArenaHi(); if (arenaLo == arenaHi) { return false; } - void *arenaStart = OSInitAlloc(arenaLo, arenaHi, numHeaps); - arenaHi = (u8 *)OSRoundDown32B(arenaHi); - arenaLo = (u8 *)OSRoundUp32B(arenaStart); - u8 *start = (u8 *)OSPhysicalToCached(0); - mCodeStart = (u8 *)start; - mCodeEnd = (u8 *)arenaLo; - mUserRamStart = (u8 *)arenaLo; - mUserRamEnd = (u8 *)arenaHi; - mMemorySize = *(u32 *)((start + 0x28)); + void* arenaStart = OSInitAlloc(arenaLo, arenaHi, numHeaps); + arenaHi = (u8*)OSRoundDown32B(arenaHi); + arenaLo = (u8*)OSRoundUp32B(arenaStart); + u8* start = (u8*)OSPhysicalToCached(0); + mCodeStart = (u8*)start; + mCodeEnd = (u8*)arenaLo; + mUserRamStart = (u8*)arenaLo; + mUserRamEnd = (u8*)arenaHi; + mMemorySize = *(u32*)((start + 0x28)); OSSetArenaLo(arenaHi); OSSetArenaHi(arenaHi); - *outUserRamStart = (char *)arenaLo; + *outUserRamStart = (char*)arenaLo; *outUserRamSize = (u32)arenaHi - (u32)arenaLo; return true; } -JKRHeap *JKRHeap::becomeSystemHeap() +JKRHeap* JKRHeap::becomeSystemHeap() { - JKRHeap *old = sSystemHeap; + JKRHeap* old = sSystemHeap; sSystemHeap = this; return old; } -JKRHeap *JKRHeap::becomeCurrentHeap() +JKRHeap* JKRHeap::becomeCurrentHeap() { - JKRHeap *old = sCurrentHeap; + JKRHeap* old = sCurrentHeap; sCurrentHeap = this; return old; } -void JKRHeap::destroy(JKRHeap *heap) +void JKRHeap::destroy(JKRHeap* heap) { JUT_ASSERT(200, heap != 0); heap->destroy(); } -void *JKRHeap::alloc(u32 byteCount, int padding, JKRHeap *heap) +void* JKRHeap::alloc(u32 byteCount, int padding, JKRHeap* heap) { - void *memory = nullptr; + void* memory = nullptr; if (heap) { memory = heap->do_alloc(byteCount, padding); @@ -116,13 +116,13 @@ void *JKRHeap::alloc(u32 byteCount, int padding, JKRHeap *heap) return memory; } -void *JKRHeap::alloc(u32 byteCount, int padding) +void* JKRHeap::alloc(u32 byteCount, int padding) { JUT_WARNING_F(317, !mInitFlag, "alloc %x byte in heap %x", byteCount, this); return do_alloc(byteCount, padding); } -void JKRHeap::free(void *memory, JKRHeap *heap) +void JKRHeap::free(void* memory, JKRHeap* heap) { if ((heap) || (heap = findFromRoot(memory), heap)) { @@ -130,7 +130,7 @@ void JKRHeap::free(void *memory, JKRHeap *heap) } } -void JKRHeap::free(void *memory) +void JKRHeap::free(void* memory) { JUT_WARNING_F(365, !mInitFlag, "free %x in heap %x", memory, this); do_free(memory); @@ -157,13 +157,13 @@ void JKRHeap::freeTail() do_freeTail(); } -void JKRHeap::resize(void *memoryBlock, u32 newSize) +void JKRHeap::resize(void* memoryBlock, u32 newSize) { JUT_WARNING_F(491, !mInitFlag, "resize block %x into %x in heap %x", memoryBlock, newSize, this); do_resize(memoryBlock, newSize); } -s32 JKRHeap::getSize(void *memoryBlock, JKRHeap *heap) +s32 JKRHeap::getSize(void* memoryBlock, JKRHeap* heap) { if (heap == nullptr && (heap = findFromRoot(memoryBlock), heap == nullptr)) { @@ -173,7 +173,7 @@ s32 JKRHeap::getSize(void *memoryBlock, JKRHeap *heap) return heap->getSize(memoryBlock); } -s32 JKRHeap::getSize(void *memoryBlock) { return do_getSize(memoryBlock); } +s32 JKRHeap::getSize(void* memoryBlock) { return do_getSize(memoryBlock); } s32 JKRHeap::getFreeSize() { return do_getFreeSize(); } s32 JKRHeap::getTotalFreeSize() { return do_getTotalFreeSize(); } @@ -185,7 +185,7 @@ s32 JKRHeap::changeGroupID(u8 newGroupID) u8 JKRHeap::getCurrentGroupId() { return do_getCurrentGroupId(); } -JKRHeap *JKRHeap::findFromRoot(void *ptr) +JKRHeap* JKRHeap::findFromRoot(void* ptr) { if (sRootHeap != nullptr) return sRootHeap->find(ptr); @@ -193,7 +193,7 @@ JKRHeap *JKRHeap::findFromRoot(void *ptr) return nullptr; } -JKRHeap *JKRHeap::find(void *memory) const +JKRHeap* JKRHeap::find(void* memory) const { if ((mStart <= memory) && (memory <= mEnd)) { @@ -201,25 +201,25 @@ JKRHeap *JKRHeap::find(void *memory) const { for (JSUTreeIterator iterator(mChildTree.getFirstChild()); iterator != mChildTree.getEndChild(); ++iterator) { - JKRHeap *result = iterator->find(memory); + JKRHeap* result = iterator->find(memory); if (result) { return result; } } } - return const_cast(this); + return const_cast(this); } return nullptr; } -JKRHeap *JKRHeap::findAllHeap(void *memory) const +JKRHeap* JKRHeap::findAllHeap(void* memory) const { if (mChildTree.getNumChildren() != 0) { for (JSUTreeIterator iterator(mChildTree.getFirstChild()); iterator != mChildTree.getEndChild(); ++iterator) { - JKRHeap *result = iterator->findAllHeap(memory); + JKRHeap* result = iterator->findAllHeap(memory); if (result) { return result; @@ -229,7 +229,7 @@ JKRHeap *JKRHeap::findAllHeap(void *memory) const if (mStart <= memory && memory < mEnd) { - return const_cast(this); + return const_cast(this); } return nullptr; @@ -242,11 +242,11 @@ void JKRHeap::dispose_subroutine(u32 begin, u32 end) JSUListIterator next_iterator; JSUListIterator iterator; for (iterator = mDisposerList.getFirst(); iterator != mDisposerList.getEnd(); - iterator = next_iterator) + iterator = next_iterator) { - JKRDisposer *disposer = iterator.getObject(); + JKRDisposer* disposer = iterator.getObject(); - if ((void *)begin <= disposer && disposer < (void *)end) + if ((void*)begin <= disposer && disposer < (void*)end) { disposer->~JKRDisposer(); if (last_iterator == nullptr) @@ -268,7 +268,7 @@ void JKRHeap::dispose_subroutine(u32 begin, u32 end) } } -bool JKRHeap::dispose(void *memory, u32 size) +bool JKRHeap::dispose(void* memory, u32 size) { u32 begin = (u32)memory; u32 end = (u32)memory + size; @@ -276,7 +276,7 @@ bool JKRHeap::dispose(void *memory, u32 size) return false; } -void JKRHeap::dispose(void *begin, void *end) +void JKRHeap::dispose(void* begin, void* end) { dispose_subroutine((u32)begin, (u32)end); } @@ -290,12 +290,12 @@ void JKRHeap::dispose() } } -void JKRHeap::copyMemory(void *dst, void *src, u32 size) +void JKRHeap::copyMemory(void* dst, void* src, u32 size) { u32 count = (size + 3) / 4; - u32 *dst_32 = (u32 *)dst; - u32 *src_32 = (u32 *)src; + u32* dst_32 = (u32*)dst; + u32* src_32 = (u32*)src; while (count > 0) { *dst_32 = *src_32; @@ -305,15 +305,15 @@ void JKRHeap::copyMemory(void *dst, void *src, u32 size) } } -void JKRDefaultMemoryErrorRoutine(void *heap, u32 size, int alignment) +void JKRDefaultMemoryErrorRoutine(void* heap, u32 size, int alignment) { // OSReport("Error: Cannot allocate memory %d(0x%x)byte in %d byte alignment from %08x\n", size, size, alignment, heap); OSErrorLine(710, "abort\n"); } -JKRHeapErrorHandler *JKRHeap::setErrorHandler(JKRHeapErrorHandler *newHandler) +JKRHeapErrorHandler* JKRHeap::setErrorHandler(JKRHeapErrorHandler* newHandler) { - JKRHeapErrorHandler *oldHandler = mErrorHandler; + JKRHeapErrorHandler* oldHandler = mErrorHandler; if (!newHandler) { newHandler = JKRDefaultMemoryErrorRoutine; @@ -322,7 +322,7 @@ JKRHeapErrorHandler *JKRHeap::setErrorHandler(JKRHeapErrorHandler *newHandler) return oldHandler; } -bool JKRHeap::isSubHeap(JKRHeap *heap) const +bool JKRHeap::isSubHeap(JKRHeap* heap) const { if (!heap) return false; @@ -347,35 +347,35 @@ bool JKRHeap::isSubHeap(JKRHeap *heap) const return false; } -void *operator new(u32 byteCount) +void* operator new(u32 byteCount) { return JKRHeap::alloc(byteCount, 4, nullptr); } -void *operator new(u32 byteCount, int alignment) +void* operator new(u32 byteCount, int alignment) { return JKRHeap::alloc(byteCount, alignment, nullptr); } -void *operator new(u32 byteCount, JKRHeap *heap, int alignment) +void* operator new(u32 byteCount, JKRHeap* heap, int alignment) { return JKRHeap::alloc(byteCount, alignment, heap); } -void *operator new[](u32 byteCount) +void* operator new[](u32 byteCount) { return JKRHeap::alloc(byteCount, 4, nullptr); } -void *operator new[](u32 byteCount, int alignment) +void* operator new[](u32 byteCount, int alignment) { return JKRHeap::alloc(byteCount, alignment, nullptr); } -void *operator new[](u32 byteCount, JKRHeap *heap, int alignment) +void* operator new[](u32 byteCount, JKRHeap* heap, int alignment) { return JKRHeap::alloc(byteCount, alignment, heap); } -// this is not needed without the other pragma and asm bs -void operator delete(void *memory) { JKRHeap::free(memory, nullptr); } -void operator delete[](void *memory) { JKRHeap::free(memory, nullptr); } + // this is not needed without the other pragma and asm bs +void operator delete(void* memory) { JKRHeap::free(memory, nullptr); } +void operator delete[](void* memory) { JKRHeap::free(memory, nullptr); } /*JKRHeap::TState::TState(const JKRHeap::TState::TArgument &arg, const JKRHeap::TState::TLocation &location) { @@ -392,25 +392,25 @@ JKRHeap::TState::TState(const JKRHeap::TState &other, const JKRHeap::TState::TLo // UNUSED FUNCTION }*/ -JKRHeap::TState::~TState() + JKRHeap::TState::~TState() { // Unused, however might need it } -void JKRHeap::state_register(JKRHeap::TState *p, u32) const +void JKRHeap::state_register(JKRHeap::TState* p, u32) const { JUT_ASSERT(1132, p != 0); JUT_ASSERT(1133, p->getHeap() == this); } -bool JKRHeap::state_compare(const JKRHeap::TState &r1, const JKRHeap::TState &r2) const +bool JKRHeap::state_compare(const JKRHeap::TState& r1, const JKRHeap::TState& r2) const { JUT_ASSERT(1141, r1.getHeap() == r2.getHeap()); return (r1.getCheckCode() == r2.getCheckCode()); } // fabricated, but probably matches(except for line numbers) -void JKRHeap::state_dumpDifference(const JKRHeap::TState &r1, const JKRHeap::TState &r2) +void JKRHeap::state_dumpDifference(const JKRHeap::TState& r1, const JKRHeap::TState& r2) { JUT_LOG_F(1157, "heap : %p / %p", r1.getHeap(), r2.getHeap()); JUT_LOG_F(1158, "check-code : 0x%08x / 0x%08x", r1.getCheckCode(), r2.getCheckCode()); @@ -418,7 +418,7 @@ void JKRHeap::state_dumpDifference(const JKRHeap::TState &r1, const JKRHeap::TSt JUT_LOG_F(1160, "used size : %10u / %10u", r1.getUsedSize(), r2.getUsedSize()); } -void JKRHeap::state_dump(const TState &state) const +void JKRHeap::state_dump(const TState& state) const { JUT_LOG_F(1165, "check-code : 0x%08x", state.getCheckCode()); JUT_LOG_F(1166, "id : 0x%08x", state.getId()); diff --git a/src/JSystem/JKernel/JKRMemArchive.cpp b/src/JSystem/JKernel/JKRMemArchive.cpp new file mode 100644 index 00000000..b98d7801 --- /dev/null +++ b/src/JSystem/JKernel/JKRMemArchive.cpp @@ -0,0 +1,247 @@ +#include +#include + +#include "JSystem/JSystem.h" +#include "JSystem/JKernel/JKRArchive.h" +#include "JSystem/JKernel/JKRDecomp.h" +#include "JSystem/JKernel/JKRDvdRipper.h" +#include "JSystem/JUtility/JUTAssertion.h" + +JKRMemArchive::JKRMemArchive() : JKRArchive() {} + +JKRMemArchive::JKRMemArchive(s32 entryNum, EMountDirection mountDirection) : JKRArchive(entryNum, MOUNT_MEM) +{ + mIsMounted = false; + mMountDirection = mountDirection; + if (!open(entryNum, mMountDirection)) + { + return; + } + else + { + mVolumeType = 'RARC'; + mVolumeName = &mStrTable[mDirectories->mOffset]; + sVolumeList.prepend(&mFileLoaderLink); + mIsMounted = true; + } +} + +JKRMemArchive::JKRMemArchive(void* mem, u32 size, JKRMemBreakFlag breakFlag) : JKRArchive((s32)mem, MOUNT_MEM) +{ + mIsMounted = false; + if (!open(mem, size, breakFlag)) + { + return; + } + else + { + mVolumeType = 'RARC'; + mVolumeName = &mStrTable[mDirectories->mOffset]; + sVolumeList.prepend(&mFileLoaderLink); + mIsMounted = true; + } +} + +JKRMemArchive::~JKRMemArchive() +{ + if (mIsMounted == true) + { + if (mIsOpen && mArcHeader) + JKRFreeToHeap(mHeap, mArcHeader); + + sVolumeList.remove(&mFileLoaderLink); + mIsMounted = false; + } +} + +#ifdef DEBUG // function is needed to generate certain strings first, however this is not what the original function looks like +void JKRMemArchive::fixedInit(s32) +{ + JUT_ASSERT(isMounted()); + JUT_PANIC("mMountCount == 1"); // some member is called mMountCount, if there's a game with this assert, fix + JUT_ASSERT(mArcHeader->signature == 'RARC'); +} +#endif + +bool JKRMemArchive::open(s32 entryNum, JKRArchive::EMountDirection mountDirection) +{ + mArcHeader = nullptr; + mArcInfoBlock = nullptr; + mArchiveData = nullptr; + mDirectories = nullptr; + mFileEntries = nullptr; + mStrTable = nullptr; + mIsOpen = false; + mMountDirection = mountDirection; + + if (mMountDirection == JKRArchive::MOUNT_DIRECTION_HEAD) + { + u32 loadedSize; + mArcHeader = (SArcHeader*)JKRDvdRipper::loadToMainRAM( + entryNum, nullptr, EXPAND_SWITCH_DECOMPRESS, 0, mHeap, JKRDvdRipper::ALLOC_DIR_TOP, + 0, (int*)&mCompression); + + } + else + { + u32 loadedSize; + mArcHeader = (SArcHeader*)JKRDvdRipper::loadToMainRAM( + entryNum, nullptr, EXPAND_SWITCH_DECOMPRESS, 0, mHeap, + JKRDvdRipper::ALLOC_DIR_BOTTOM, 0, (int*)&mCompression); + } + + if (!mArcHeader) + { + mMountMode = UNKNOWN_MOUNT_MODE; + } + else + { + JUT_ASSERT(mArcHeader->signature == 'RARC'); + mArcInfoBlock = (SArcDataInfo*)((u8*)mArcHeader + mArcHeader->header_length); + mDirectories = (SDIDirEntry*)((u8*)&mArcInfoBlock->num_nodes + mArcInfoBlock->node_offset); + mFileEntries = (SDIFileEntry*)((u8*)&mArcInfoBlock->num_nodes + mArcInfoBlock->file_entry_offset); + mStrTable = (char*)((u8*)&mArcInfoBlock->num_nodes + mArcInfoBlock->string_table_offset); + + mArchiveData = + (u8*)((u32)mArcHeader + mArcHeader->header_length + mArcHeader->file_data_offset); + mIsOpen = true; + } +#if DEBUG + // OS Assert? + if (mMountMode == UNKNOWN_MOUNT_MODE) + { + OSReport(":::Cannot alloc memory [%s][%d]\n", __FILE__, 460); + } +#endif + return (mMountMode == UNKNOWN_MOUNT_MODE) ? false : true; +} + +bool JKRMemArchive::open(void* buffer, u32 bufferSize, JKRMemBreakFlag flag) +{ + mArcHeader = (SArcHeader*)buffer; + JUT_ASSERT(mArcHeader->signature == 'RARC'); + mArcInfoBlock = (SArcDataInfo*)((u8*)mArcHeader + mArcHeader->header_length); + mDirectories = (SDIDirEntry*)((u8*)&mArcInfoBlock->num_nodes + mArcInfoBlock->node_offset); + mFileEntries = (SDIFileEntry*)((u8*)&mArcInfoBlock->num_nodes + mArcInfoBlock->file_entry_offset); + mStrTable = (char*)((u8*)&mArcInfoBlock->num_nodes + mArcInfoBlock->string_table_offset); + mArchiveData = (u8*)(((u32)mArcHeader + mArcHeader->header_length) + mArcHeader->file_data_offset); + mIsOpen = (flag == MBF_1) ? true : false; // mIsOpen might be u8 + mHeap = JKRHeap::findFromRoot(buffer); + mCompression = JKRCOMPRESSION_NONE; + return true; +} + +void* JKRMemArchive::fetchResource(SDIFileEntry* fileEntry, u32* resourceSize) +{ + JUT_ASSERT(isMounted()) + + if (!fileEntry->mData) + fileEntry->mData = mArchiveData + fileEntry->mDataOffset; + + if (resourceSize) + *resourceSize = fileEntry->mSize; + + return fileEntry->mData; +} + +void* JKRMemArchive::fetchResource(void* buffer, u32 bufferSize, SDIFileEntry* fileEntry, + u32* resourceSize, JKRExpandSwitch expandSwitch) +{ + JUT_ASSERT(isMounted()) + + bufferSize = (bufferSize & -32); + u32 srcLength = ALIGN_NEXT(fileEntry->mSize, 32); + if (srcLength > bufferSize) + { + srcLength = bufferSize; + } + + if (fileEntry->mData != nullptr) + { + JKRHeap::copyMemory(buffer, fileEntry->mData, srcLength); + } + else + { + int compression = JKRConvertAttrToCompressionType(fileEntry->getAttr()); + if (expandSwitch != EXPAND_SWITCH_DECOMPRESS) + compression = JKRCOMPRESSION_NONE; + + void* data = mArchiveData + fileEntry->mDataOffset; + srcLength = + fetchResource_subroutine((u8*)data, srcLength, (u8*)buffer, bufferSize, compression); + } + + if (resourceSize) + { + *resourceSize = srcLength; + } + + return buffer; +} + +void JKRMemArchive::removeResourceAll(void) +{ + JUT_ASSERT(isMounted()); + + if (mArcInfoBlock == nullptr) + return; + if (mMountMode == MOUNT_MEM) + return; + + // !@bug: looping over file entries without incrementing the fileEntry pointer. Thus, only the + // first fileEntry will clear/remove the resource data. + SDIFileEntry* fileEntry = mFileEntries; + for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) + { + if (fileEntry->mData) + { + fileEntry->mData = nullptr; + } + } +} + +bool JKRMemArchive::removeResource(void* resource) +{ + JUT_ASSERT(isMounted()); + + SDIFileEntry* fileEntry = findPtrResource(resource); + if (!fileEntry) + return false; + + fileEntry->mData = nullptr; + return true; +} + +u32 JKRMemArchive::fetchResource_subroutine(u8* src, u32 srcLength, u8* dst, u32 dstLength, int compression) +{ + u32 alignedDst = dstLength & -32; + u32 alignedSrc = ALIGN_NEXT(srcLength, 32); + switch (compression) + { + case JKRCOMPRESSION_NONE: + if (alignedSrc > alignedDst) + alignedSrc = alignedDst; + + JKRHeap::copyMemory(dst, src, alignedSrc); + return alignedSrc; + + case JKRCOMPRESSION_YAY0: + case JKRCOMPRESSION_YAZ0: + u32 expandSize = JKRDecompExpandSize(src); + + if (expandSize > alignedDst) { + expandSize = alignedDst; + } + + JKRDecompress(src, dst, expandSize, 0); + return expandSize; + + default: + { + JPANIC(709, ":::??? bad sequence\n"); + return 0; + } + } + + return alignedSrc; +} diff --git a/src/JSystem/JKernel/JKRThread.cpp b/src/JSystem/JKernel/JKRThread.cpp index 22d056bc..0006186e 100644 --- a/src/JSystem/JKernel/JKRThread.cpp +++ b/src/JSystem/JKernel/JKRThread.cpp @@ -1,13 +1,12 @@ -#include "JSystem/JKernel/JKRThread.h" -#include "JSystem/JSupport/JSUList.h" -#include "JSystem/JKernel/JKRHeap.h" #include "JSystem/JKernel/JKRMacro.h" +#include "JSystem/JKernel/JKRThread.h" +#include "JSystem/JKernel/JKRHeap.h" JSUList JKRThread::sThreadList; JKRThread::JKRThread(u32 stackSize, int msgCount, int threadPrio) - : JKRDisposer(), mLink(this) { + : mLink(this) { this->mHeap = JKRHeap::findFromRoot(this); if (this->mHeap == nullptr) { this->mHeap = JKRHeap::sSystemHeap; @@ -16,26 +15,26 @@ JKRThread::JKRThread(u32 stackSize, int msgCount, int threadPrio) this->mStackSize = JKR_ALIGN32(stackSize); this->mStackMemory = JKRHeap::alloc(this->mStackSize, 32, this->mHeap); this->mThreadRecord = - (OSThread *)JKRHeap::alloc(sizeof(OSThread), 32, this->mHeap); + (OSThread*)JKRHeap::alloc(sizeof(OSThread), 32, this->mHeap); OSCreateThread(this->mThreadRecord, &JKRThread::start, this, - (void *)((u32)this->mStackMemory + this->mStackSize), - this->mStackSize, threadPrio, OS_THREAD_ATTR_DETACH); + (void*)((u32)this->mStackMemory + this->mStackSize), + this->mStackSize, threadPrio, OS_THREAD_ATTR_DETACH); this->mMesgCount = msgCount; - this->mMesgBuffer = (OSMessage *)JKRHeap::alloc( - mMesgCount * sizeof(OSMessage), 0, this->mHeap); + this->mMesgBuffer = (OSMessage*)JKRHeap::alloc( + mMesgCount * sizeof(OSMessage), 0, this->mHeap); OSInitMessageQueue(&this->mMesgQueue, this->mMesgBuffer, this->mMesgCount); JKRThread::sThreadList.append(&this->mLink); } -JKRThread::JKRThread(OSThread *threadRecord, int msgCount) - : JKRDisposer(), mLink(this) { +JKRThread::JKRThread(OSThread* threadRecord, int msgCount) + : mLink(this) { this->mHeap = nullptr; this->mThreadRecord = threadRecord; this->mStackSize = (u32)threadRecord->stackEnd - (u32)threadRecord->stackBase; this->mStackMemory = threadRecord->stackBase; this->mMesgCount = msgCount; - this->mMesgBuffer = (OSMessage *)JKRHeap::sSystemHeap->alloc( - mMesgCount * sizeof(OSMessage), 4); + this->mMesgBuffer = (OSMessage*)JKRHeap::sSystemHeap->alloc( + mMesgCount * sizeof(OSMessage), 4); OSInitMessageQueue(&this->mMesgQueue, this->mMesgBuffer, this->mMesgCount); JKRThread::sThreadList.append(&this->mLink); } @@ -56,6 +55,60 @@ JKRThread::~JKRThread() { JKRHeap::free(this->mMesgBuffer, nullptr); } -void *JKRThread::start(void *thread) { - return static_cast(thread)->run(); +void* JKRThread::start(void* thread) { + return static_cast(thread)->run(); +} + +// UNUSED FUNCTIONS, REQUIRED FOR RTTI +JKRTask::JKRTask() : JKRThread(0x4000, 4, 31) +{ + +} + +JKRTask::~JKRTask() { } + +JKRTask* JKRTask::create() +{ + return new JKRTask(); +} + +void JKRTask::destroy() { + delete this; +} + +void* JKRTask::run() +{ + Request* req; + //OSInitFastCast(); + while (true) + { + req = (Request*)waitMessageBlock(); + if (req->mCb) + { + req->mCb(req->mArg); + if (mTaskMsgQueue) + { + OSSendMessage(mTaskMsgQueue, req->mMsg, OS_MESSAGE_NOBLOCK); + } + } + req->mCb = nullptr; + } +} + +bool JKRTask::request(RequestCallback callback, void* arg, void* msg) +{ + Request* req = searchBlank(); + if (req == nullptr) + { + return false; + } + req->mCb = callback; + req->mArg = arg; + req->mMsg = msg; + bool sendResult = OSSendMessage(&mMesgQueue, req, OS_MESSAGE_NOBLOCK); + if (!sendResult) + { + req->mCb = nullptr; + } + return sendResult; } diff --git a/src/JSystem/JKernel/JKRThread2.cpp b/src/JSystem/JKernel/JKRThread2.cpp deleted file mode 100644 index 7568e7a9..00000000 --- a/src/JSystem/JKernel/JKRThread2.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "JSystem/JKernel/JKRThread.h" - -__declspec(weak) void* JKRThread::run() { return nullptr; } diff --git a/src/ctors.s b/src/ctors.s new file mode 100644 index 00000000..415a9375 --- /dev/null +++ b/src/ctors.s @@ -0,0 +1 @@ +# there totally is code in this file, needed to bypass a bug caused by trim_ctors \ No newline at end of file