summaryrefslogtreecommitdiff
path: root/src/JSystem
diff options
context:
space:
mode:
authorDylan Ascencio <empressglatia@gmail.com>2023-09-16 18:13:11 -0400
committerDylan Ascencio <empressglatia@gmail.com>2023-09-16 18:13:11 -0400
commite940e4f4e0961aaa01c687dbfd96fdb6dec02cfe (patch)
treed22f3e7228cf89ac7152517c98149b4778c6db04 /src/JSystem
parent331847e88ff809875cb2b643e8434a3a10b7446e (diff)
parentf0cc6a9bef1422bb5d63cfe452772a76499ea0fd (diff)
Merge remote-tracking branch 'upstream/main'
Diffstat (limited to 'src/JSystem')
-rw-r--r--src/JSystem/JKernel/JKRArchivePri.cpp219
-rw-r--r--src/JSystem/JKernel/JKRArchivePub.cpp341
-rw-r--r--src/JSystem/JKernel/JKRExpHeap.cpp952
-rw-r--r--src/JSystem/JKernel/JKRFileLoader.cpp145
-rw-r--r--src/JSystem/JKernel/JKRThread.cpp131
5 files changed, 1585 insertions, 203 deletions
diff --git a/src/JSystem/JKernel/JKRArchivePri.cpp b/src/JSystem/JKernel/JKRArchivePri.cpp
index 48f232b2..133fbb8c 100644
--- a/src/JSystem/JKernel/JKRArchivePri.cpp
+++ b/src/JSystem/JKernel/JKRArchivePri.cpp
@@ -3,85 +3,238 @@
// Translation Unit: JKRArchivePri.cpp
//
-#include "JSystem/JKernel/JKRArchivePri.h"
+#include "JSystem/JKernel/JKRArchive.h"
+#include "JSystem/JKernel/JKRHeap.h"
+#include "MSL_C/MSL_Common/Src/ctype.h"
+#include "MSL_C/string.h"
#include "dolphin/types.h"
+u32 JKRArchive::sCurrentDirID;
+
/* 802B8DFC-802B8E48 .text __ct__10JKRArchiveFv */
JKRArchive::JKRArchive() {
- /* Nonmatching */
+ mIsMounted = false;
+ mMountDirection = MOUNT_DIRECTION_HEAD;
}
/* 802B8E48-802B8EE8 .text __ct__10JKRArchiveFlQ210JKRArchive10EMountMode */
-JKRArchive::JKRArchive(long, JKRArchive::EMountMode) {
- /* Nonmatching */
+JKRArchive::JKRArchive(s32 entryNumber, JKRArchive::EMountMode mountMode) {
+ mIsMounted = false;
+ mMountMode = mountMode;
+ mMountCount = 1;
+ field_0x58 = 1;
+
+ mHeap = JKRHeap::findFromRoot(this);
+ if (mHeap == NULL) {
+ mHeap = JKRHeap::getCurrentHeap();
+ }
+
+ mEntryNum = entryNumber;
+ if (getCurrentVolume() == NULL) {
+ setCurrentVolume(this);
+ setCurrentDirID(0);
+ }
}
/* 802B8EE8-802B8F48 .text __dt__10JKRArchiveFv */
-JKRArchive::~JKRArchive() {
- /* Nonmatching */
-}
+JKRArchive::~JKRArchive() {}
/* 802B8F48-802B8F94 .text isSameName__10JKRArchiveCFRQ210JKRArchive8CArcNameUlUs */
-void JKRArchive::isSameName(JKRArchive::CArcName&, unsigned long, unsigned short) const {
- /* Nonmatching */
+bool JKRArchive::isSameName(JKRArchive::CArcName& name, u32 nameOffset, u16 nameHash) const {
+ u16 hash = name.getHash();
+ if (hash != nameHash)
+ return false;
+ return strcmp(mStringTable + nameOffset, name.getString()) == 0;
}
/* 802B8F94-802B8FD0 .text findResType__10JKRArchiveCFUl */
-void JKRArchive::findResType(unsigned long) const {
- /* Nonmatching */
+JKRArchive::SDIDirEntry* JKRArchive::findResType(u32 type) const {
+ SDIDirEntry* node = mNodes;
+ u32 count = 0;
+ while (count < mArcInfoBlock->num_nodes) {
+ if (node->type == type) {
+ return node;
+ }
+
+ node++;
+ count++;
+ }
+
+ return NULL;
}
/* 802B8FD0-802B90A8 .text findDirectory__10JKRArchiveCFPCcUl */
-void JKRArchive::findDirectory(const char*, unsigned long) const {
- /* Nonmatching */
+JKRArchive::SDIDirEntry* JKRArchive::findDirectory(const char* name, u32 directoryId) const {
+ if (name == NULL) {
+ return mNodes + directoryId;
+ }
+
+ CArcName arcName(&name, '/');
+ SDIDirEntry* dirEntry = mNodes + directoryId;
+ SDIFileEntry* fileEntry = mFiles + dirEntry->first_file_index;
+
+ for (int i = 0; i < dirEntry->num_entries; fileEntry++, i++) {
+ if (isSameName(arcName, fileEntry->getNameOffset(), fileEntry->name_hash)) {
+ if (fileEntry->isDirectory()) {
+ return findDirectory(name, fileEntry->data_offset);
+ }
+ break;
+ }
+ }
+
+ return NULL;
}
/* 802B90A8-802B9158 .text findTypeResource__10JKRArchiveCFUlPCc */
-void JKRArchive::findTypeResource(unsigned long, const char*) const {
- /* Nonmatching */
+JKRArchive::SDIFileEntry* JKRArchive::findTypeResource(u32 type, const char* name) const {
+ if (type) {
+ CArcName arcName(name);
+ SDIDirEntry* dirEntry = findResType(type);
+
+ if (dirEntry) {
+ SDIFileEntry* fileEntry = mFiles + dirEntry->first_file_index;
+ for (int i = 0; i < dirEntry->num_entries; fileEntry++, i++) {
+ if (isSameName(arcName, fileEntry->getNameOffset(), fileEntry->getNameHash())) {
+ return fileEntry;
+ }
+ }
+ }
+ }
+
+ return NULL;
}
/* 802B9158-802B9238 .text findFsResource__10JKRArchiveCFPCcUl */
-void JKRArchive::findFsResource(const char*, unsigned long) const {
- /* Nonmatching */
+JKRArchive::SDIFileEntry* JKRArchive::findFsResource(const char* name, u32 directoryId) const {
+ if (name) {
+ CArcName arcName(&name, '/');
+ SDIDirEntry* dirEntry = mNodes + directoryId;
+ SDIFileEntry* fileEntry = mFiles + dirEntry->first_file_index;
+
+ for (int i = 0; i < dirEntry->num_entries; fileEntry++, i++) {
+ if (isSameName(arcName, fileEntry->getNameOffset(), fileEntry->name_hash)) {
+ if (fileEntry->isDirectory()) {
+ return findFsResource(name, fileEntry->data_offset);
+ }
+
+ if (name == NULL) {
+ return fileEntry;
+ }
+
+ return NULL;
+ }
+ }
+ }
+
+ return NULL;
}
/* 802B9238-802B9260 .text findIdxResource__10JKRArchiveCFUl */
-void JKRArchive::findIdxResource(unsigned long) const {
- /* Nonmatching */
+JKRArchive::SDIFileEntry* JKRArchive::findIdxResource(u32 fileIndex) const {
+ if (fileIndex < mArcInfoBlock->num_file_entries) {
+ return mFiles + fileIndex;
+ }
+
+ return NULL;
}
/* 802B9260-802B92E8 .text findNameResource__10JKRArchiveCFPCc */
-void JKRArchive::findNameResource(const char*) const {
- /* Nonmatching */
+JKRArchive::SDIFileEntry* JKRArchive::findNameResource(const char* name) const {
+ SDIFileEntry* fileEntry = mFiles;
+
+ CArcName arcName(name);
+ for (int i = 0; i < mArcInfoBlock->num_file_entries; fileEntry++, i++) {
+ if (isSameName(arcName, fileEntry->getNameOffset(), fileEntry->getNameHash())) {
+ return fileEntry;
+ }
+ }
+
+ return NULL;
}
/* 802B92E8-802B9324 .text findPtrResource__10JKRArchiveCFPCv */
-void JKRArchive::findPtrResource(const void*) const {
- /* Nonmatching */
+JKRArchive::SDIFileEntry* JKRArchive::findPtrResource(const void* resource) const {
+ SDIFileEntry* fileEntry = mFiles;
+ for (int i = 0; i < mArcInfoBlock->num_file_entries; fileEntry++, i++) {
+ if (fileEntry->data == resource) {
+ return fileEntry;
+ }
+ }
+
+ return NULL;
}
/* 802B9324-802B93A4 .text findIdResource__10JKRArchiveCFUs */
-void JKRArchive::findIdResource(unsigned short) const {
- /* Nonmatching */
+JKRArchive::SDIFileEntry* JKRArchive::findIdResource(u16 id) const {
+ if (id != 0xFFFF) {
+ SDIFileEntry* fileEntry = mFiles + id;
+ if (fileEntry->file_id == id && fileEntry->isUnknownFlag1()) {
+ return fileEntry;
+ }
+
+ fileEntry = mFiles;
+ for (int i = 0; i < mArcInfoBlock->num_file_entries; fileEntry++, i++) {
+ if (fileEntry->file_id == id && fileEntry->isUnknownFlag1()) {
+ return fileEntry;
+ }
+ }
+ }
+
+ return NULL;
}
/* 802B93A4-802B9434 .text store__Q210JKRArchive8CArcNameFPCc */
-void JKRArchive::CArcName::store(const char*) {
- /* Nonmatching */
+void JKRArchive::CArcName::store(const char* name) {
+ mHash = 0;
+ s32 length = 0;
+ while (*name) {
+ s32 ch = tolower(*name);
+ mHash = ch + mHash * 3;
+ if (length < (s32)ARRAY_SIZE(mData)) {
+ mData[length++] = ch;
+ }
+ name++;
+ }
+
+ mLength = (u16)length;
+ mData[length] = 0;
}
/* 802B9434-802B94EC .text store__Q210JKRArchive8CArcNameFPCcc */
-void JKRArchive::CArcName::store(const char*, char) {
- /* Nonmatching */
+const char* JKRArchive::CArcName::store(const char* name, char endChar) {
+ mHash = 0;
+ s32 length = 0;
+ while (*name && *name != endChar) {
+ s32 lch = tolower((int)*name);
+ mHash = lch + mHash * 3;
+ if (length < (s32)ARRAY_SIZE(mData)) {
+ mData[length++] = lch;
+ }
+ name++;
+ }
+
+ mLength = (u16)length;
+ mData[length] = 0;
+
+ if (*name == 0)
+ return NULL;
+ return name + 1;
}
/* 802B94EC-802B9528 .text setExpandSize__10JKRArchiveFPQ210JKRArchive12SDIFileEntryUl */
-void JKRArchive::setExpandSize(JKRArchive::SDIFileEntry*, unsigned long) {
- /* Nonmatching */
+void JKRArchive::setExpandSize(SDIFileEntry* fileEntry, u32 expandSize) {
+ int index = fileEntry - mFiles;
+ if (!mExpandedSize || index >= mArcInfoBlock->num_file_entries)
+ return;
+
+ mExpandedSize[index] = expandSize;
}
/* 802B9528-802B9568 .text getExpandSize__10JKRArchiveCFPQ210JKRArchive12SDIFileEntry */
-void JKRArchive::getExpandSize(JKRArchive::SDIFileEntry*) const {
- /* Nonmatching */
+u32 JKRArchive::getExpandSize(SDIFileEntry* fileEntry) const {
+ int index = fileEntry - mFiles;
+ if (!mExpandedSize || index >= mArcInfoBlock->num_file_entries)
+ return 0;
+
+ return mExpandedSize[index];
}
diff --git a/src/JSystem/JKernel/JKRArchivePub.cpp b/src/JSystem/JKernel/JKRArchivePub.cpp
index edcaf067..f080e84a 100644
--- a/src/JSystem/JKernel/JKRArchivePub.cpp
+++ b/src/JSystem/JKernel/JKRArchivePub.cpp
@@ -3,115 +3,368 @@
// Translation Unit: JKRArchivePub.cpp
//
-#include "JSystem/JKernel/JKRArchivePub.h"
-#include "dolphin/types.h"
+#include "JSystem/JKernel/JKRArchive.h"
+#include "JSystem/JKernel/JKRAramArchive.h"
+#include "JSystem/JKernel/JKRCompArchive.h"
+#include "JSystem/JKernel/JKRDvdArchive.h"
+#include "JSystem/JKernel/JKRFileFinder.h"
+#include "JSystem/JKernel/JKRHeap.h"
+#include "JSystem/JKernel/JKRMemArchive.h"
+#include "JSystem/JUtility/JUTAssert.h"
+#include "dolphin/dvd/dvd.h"
/* 802B7FB4-802B8008 .text check_mount_already__10JKRArchiveFl */
-void JKRArchive::check_mount_already(long) {
- /* Nonmatching */
+JKRArchive* JKRArchive::check_mount_already(s32 entryNum) {
+ JSUList<JKRFileLoader>& volumeList = getVolumeList();
+ JSUListIterator<JKRFileLoader> iterator;
+ for (iterator = volumeList.getFirst(); iterator != volumeList.getEnd(); ++iterator) {
+ if (iterator->getVolumeType() == 'RARC') {
+ JKRArchive* archive = (JKRArchive*)iterator.getObject();
+ if (archive->mEntryNum == entryNum) {
+ archive->mMountCount++;
+ return archive;
+ }
+ }
+ }
+
+ return NULL;
}
/* 802B8008-802B8064 .text mount__10JKRArchiveFPCcQ210JKRArchive10EMountModeP7JKRHeapQ210JKRArchive15EMountDirection */
-void JKRArchive::mount(const char*, JKRArchive::EMountMode, JKRHeap*, JKRArchive::EMountDirection) {
- /* Nonmatching */
+JKRArchive* JKRArchive::mount(const char* path, JKRArchive::EMountMode mountMode, JKRHeap* heap, JKRArchive::EMountDirection mountDirection) {
+ s32 entryNum = DVDConvertPathToEntrynum(path);
+ if (entryNum < 0)
+ return NULL;
+
+ return mount(entryNum, mountMode, heap, mountDirection);
}
/* 802B8064-802B81D0 .text mount__10JKRArchiveFlQ210JKRArchive10EMountModeP7JKRHeapQ210JKRArchive15EMountDirection */
-void JKRArchive::mount(long, JKRArchive::EMountMode, JKRHeap*, JKRArchive::EMountDirection) {
- /* Nonmatching */
+JKRArchive* JKRArchive::mount(s32 entryNum, JKRArchive::EMountMode mountMode, JKRHeap* heap, JKRArchive::EMountDirection mountDirection) {
+ JKRArchive* archive = check_mount_already(entryNum);
+ if (archive != NULL) {
+ return archive;
+ } else {
+ int alignment;
+ if (mountDirection == JKRArchive::MOUNT_DIRECTION_HEAD) {
+ alignment = 4;
+ } else {
+ alignment = -4;
+ }
+
+ JKRArchive* archive;
+ switch (mountMode) {
+ case JKRArchive::MOUNT_MEM:
+ archive = new (heap, alignment) JKRMemArchive(entryNum, mountDirection);
+ break;
+ case JKRArchive::MOUNT_ARAM:
+ archive = new (heap, alignment) JKRAramArchive(entryNum, mountDirection);
+ break;
+ case JKRArchive::MOUNT_DVD:
+ archive = new (heap, alignment) JKRDvdArchive(entryNum, mountDirection);
+ break;
+ case JKRArchive::MOUNT_COMP:
+ archive = new (heap, alignment) JKRCompArchive(entryNum, mountDirection);
+ break;
+ }
+
+ if (archive && archive->getMountMode() == JKRArchive::UNKNOWN_MOUNT_MODE) {
+ delete archive;
+ archive = NULL;
+ }
+
+ return archive;
+ }
}
/* 802B81D0-802B8258 .text becomeCurrent__10JKRArchiveFPCc */
-void JKRArchive::becomeCurrent(const char*) {
- /* Nonmatching */
+bool JKRArchive::becomeCurrent(const char* path) {
+ SDIDirEntry* dirEntry;
+ if (*path == '/') {
+ path++;
+
+ if (*path == '\0')
+ path = NULL;
+ dirEntry = findDirectory(path, 0);
+ } else {
+ dirEntry = findDirectory(path, getCurrentDirID());
+ }
+
+ bool found = dirEntry != NULL;
+ if (found) {
+ setCurrentVolume(this);
+ setCurrentDirID(dirEntry - mNodes);
+ }
+
+ return found;
}
/* 802B8258-802B82D0 .text getDirEntry__10JKRArchiveCFPQ210JKRArchive9SDirEntryUl */
-void JKRArchive::getDirEntry(JKRArchive::SDirEntry*, unsigned long) const {
- /* Nonmatching */
+bool JKRArchive::getDirEntry(SDirEntry* dirEntry, u32 index) const {
+ SDIFileEntry* fileEntry = findIdxResource(index);
+ if (!fileEntry) {
+ return false;
+ }
+
+ dirEntry->flags = fileEntry->getFlags();
+ dirEntry->id = fileEntry->getFileID();
+ dirEntry->name = mStringTable + fileEntry->getNameOffset();
+ return true;
}
/* 802B82D0-802B8380 .text getGlbResource__10JKRArchiveFUlPCcP10JKRArchive */
-void JKRArchive::getGlbResource(unsigned long, const char*, JKRArchive*) {
- /* Nonmatching */
+void* JKRArchive::getGlbResource(u32 param_0, const char* path, JKRArchive* archive) {
+ void* resource = NULL;
+ if (archive) {
+ return archive->getResource(param_0, path);
+ }
+
+ JSUList<JKRFileLoader>& volumeList = getVolumeList();
+ JSUListIterator<JKRFileLoader> iterator;
+ for (iterator = volumeList.getFirst(); iterator != volumeList.getEnd(); ++iterator) {
+ if (iterator->getVolumeType() == 'RARC') {
+ resource = iterator->getResource(param_0, path);
+ if (resource)
+ break;
+ }
+ }
+
+ return resource;
}
/* 802B8380-802B8450 .text getResource__10JKRArchiveFPCc */
-void JKRArchive::getResource(const char*) {
- /* Nonmatching */
+void* JKRArchive::getResource(const char* path) {
+ JUT_ASSERT(285, isMounted());
+ SDIFileEntry* fileEntry;
+ if (*path == '/') {
+ fileEntry = findFsResource(path + 1, 0);
+ } else {
+ fileEntry = findFsResource(path, getCurrentDirID());
+ }
+
+ if (fileEntry) {
+ return fetchResource(fileEntry, NULL);
+ }
+
+ return NULL;
}
/* 802B8450-802B8528 .text getResource__10JKRArchiveFUlPCc */
-void JKRArchive::getResource(unsigned long, const char*) {
- /* Nonmatching */
+void* JKRArchive::getResource(u32 type, const char* path) {
+ JUT_ASSERT(332, isMounted());
+ SDIFileEntry* fileEntry;
+ if (type == 0 || type == '????') {
+ fileEntry = findNameResource(path);
+ } else {
+ fileEntry = findTypeResource(type, path);
+ }
+
+ if (fileEntry) {
+ return fetchResource(fileEntry, NULL);
+ }
+
+ return NULL;
}
/* 802B8528-802B85F0 .text readTypeResource__10JKRArchiveFPvUlUlPCcP10JKRArchive */
-void JKRArchive::readTypeResource(void*, unsigned long, unsigned long, const char*, JKRArchive*) {
+// missing instructions
+void JKRArchive::readTypeResource(void* buffer, u32 bufferSize, u32 type, const char* path, JKRArchive* archive) {
/* Nonmatching */
+ if (archive) {
+ archive->readResource(buffer, bufferSize, type, path);
+ return;
+ }
+ JSUListIterator<JKRFileLoader> iterator;
+ for (iterator = sVolumeList.getFirst(); iterator != sVolumeList.getEnd(); iterator++) {
+ if (iterator->getVolumeType() == 'RARC') {
+ u32 result = iterator->readResource(buffer, bufferSize, type, path);
+ if (result != 0) {
+ return;
+ }
+ }
+ }
}
/* 802B85F0-802B86DC .text readResource__10JKRArchiveFPvUlUlPCc */
-void JKRArchive::readResource(void*, unsigned long, unsigned long, const char*) {
- /* Nonmatching */
+u32 JKRArchive::readResource(void* buffer, u32 bufferSize, u32 type, const char* path) {
+ JUT_ASSERT(491, isMounted());
+ SDIFileEntry* fileEntry;
+ if (type == 0 || type == '????') {
+ fileEntry = findNameResource(path);
+ } else {
+ fileEntry = findTypeResource(type, path);
+ }
+
+ if (fileEntry) {
+ u32 resourceSize;
+ fetchResource(buffer, bufferSize, fileEntry, &resourceSize);
+ return resourceSize;
+ }
+
+ return 0;
}
/* 802B86DC-802B87C0 .text readResource__10JKRArchiveFPvUlPCc */
-void JKRArchive::readResource(void*, unsigned long, const char*) {
- /* Nonmatching */
+u32 JKRArchive::readResource(void* buffer, u32 bufferSize, const char* path) {
+ JUT_ASSERT(537, isMounted());
+ SDIFileEntry* fileEntry;
+ if (*path == '/') {
+ fileEntry = findFsResource(path + 1, 0);
+ } else {
+ fileEntry = findFsResource(path, getCurrentDirID());
+ }
+
+ if (fileEntry) {
+ u32 resourceSize;
+ fetchResource(buffer, bufferSize, fileEntry, &resourceSize);
+ return resourceSize;
+ }
+
+ return 0;
}
/* 802B87C0-802B8878 .text readIdxResource__10JKRArchiveFPvUlUl */
-void JKRArchive::readIdxResource(void*, unsigned long, unsigned long) {
- /* Nonmatching */
+u32 JKRArchive::readIdxResource(void* buffer, u32 bufferSize, u32 index) {
+ JUT_ASSERT(593, isMounted());
+ SDIFileEntry* fileEntry = findIdxResource(index);
+ if (fileEntry) {
+ u32 resourceSize;
+ fetchResource(buffer, bufferSize, fileEntry, &resourceSize);
+ return resourceSize;
+ }
+
+ return 0;
}
/* 802B8878-802B8930 .text readResource__10JKRArchiveFPvUlUs */
-void JKRArchive::readResource(void*, unsigned long, unsigned short) {
- /* Nonmatching */
+u32 JKRArchive::readResource(void* buffer, u32 bufferSize, u16 id) {
+ JUT_ASSERT(627, isMounted());
+ SDIFileEntry* fileEntry = findIdResource(id);
+ if (fileEntry) {
+ u32 resourceSize;
+ fetchResource(buffer, bufferSize, fileEntry, &resourceSize);
+ return resourceSize;
+ }
+
+ return 0;
}
/* 802B8930-802B89B8 .text removeResourceAll__10JKRArchiveFv */
void JKRArchive::removeResourceAll() {
- /* Nonmatching */
+ if (mArcInfoBlock && mMountMode != MOUNT_MEM) {
+ SDIFileEntry* fileEntry = mFiles;
+ for (int i = 0; i < mArcInfoBlock->num_file_entries; fileEntry++, i++) {
+ if (fileEntry->data) {
+ JKRFreeToHeap(mHeap, fileEntry->data);
+ fileEntry->data = NULL;
+ }
+ }
+ }
}
/* 802B89B8-802B8A54 .text removeResource__10JKRArchiveFPv */
-void JKRArchive::removeResource(void*) {
- /* Nonmatching */
+bool JKRArchive::removeResource(void* resource) {
+ JUT_ASSERT(687, resource != 0);
+ SDIFileEntry* fileEntry = findPtrResource(resource);
+ if (fileEntry == NULL)
+ return false;
+
+ fileEntry->data = NULL;
+ JKRFreeToHeap(mHeap, resource);
+ return true;
}
/* 802B8A54-802B8AE4 .text detachResource__10JKRArchiveFPv */
-void JKRArchive::detachResource(void*) {
- /* Nonmatching */
+bool JKRArchive::detachResource(void* resource) {
+ JUT_ASSERT(719, resource != 0);
+ SDIFileEntry* fileEntry = findPtrResource(resource);
+ if (fileEntry == NULL)
+ return false;
+
+ fileEntry->data = NULL;
+ return true;
}
/* 802B8AE4-802B8B6C .text getResSize__10JKRArchiveCFPCv */
-void JKRArchive::getResSize(const void*) const {
- /* Nonmatching */
+u32 JKRArchive::getResSize(const void* resource) const {
+ JUT_ASSERT(746, resource != 0);
+ SDIFileEntry* fileEntry = findPtrResource(resource);
+ if (fileEntry == NULL)
+ return -1;
+
+ return fileEntry->data_size;
}
/* 802B8B6C-802B8BF0 .text countResource__10JKRArchiveCFUl */
-void JKRArchive::countResource(unsigned long) const {
- /* Nonmatching */
+u32 JKRArchive::countResource(u32 type) const {
+ SDIDirEntry* dirEntry = findResType(type);
+ if (dirEntry) {
+ int count = 0;
+ for (int i = dirEntry->first_file_index; i < dirEntry->first_file_index + dirEntry->num_entries; i++) {
+ if (mFiles[i].isUnknownFlag1()) {
+ count++;
+ }
+ }
+ return count;
+ }
+ return 0;
}
/* 802B8BF0-802B8C50 .text countFile__10JKRArchiveCFPCc */
-void JKRArchive::countFile(const char*) const {
- /* Nonmatching */
+u32 JKRArchive::countFile(const char* path) const {
+ SDIDirEntry* dirEntry;
+ if (*path == '/') {
+ path++;
+
+ if (*path == '\0')
+ path = NULL;
+ dirEntry = findDirectory(path, 0);
+ } else {
+ dirEntry = findDirectory(path, sCurrentDirID);
+ }
+
+ if (dirEntry) {
+ return dirEntry->num_entries;
+ }
+
+ return 0;
}
/* 802B8C50-802B8CFC .text getFirstFile__10JKRArchiveCFPCc */
-void JKRArchive::getFirstFile(const char*) const {
- /* Nonmatching */
+JKRFileFinder* JKRArchive::getFirstFile(const char* path) const {
+ SDIDirEntry* dirEntry;
+ if (*path == '/') {
+ path++;
+
+ if (*path == '\0')
+ path = NULL;
+ dirEntry = findDirectory(path, 0);
+ } else {
+ dirEntry = findDirectory(path, sCurrentDirID);
+ }
+
+ if (dirEntry) {
+ return new (JKRHeap::sSystemHeap, 0) JKRArcFinder((JKRArchive*)this, dirEntry->first_file_index, dirEntry->num_entries);
+ }
+
+ return NULL;
}
/* 802B8CFC-802B8DC4 .text getFirstResource__10JKRArchiveCFUl */
-void JKRArchive::getFirstResource(unsigned long) const {
- /* Nonmatching */
+JKRArcFinder* JKRArchive::getFirstResource(u32 type) const {
+ SDIDirEntry* dirEntry = findResType(type);
+ if (dirEntry && (getFileAttribute(dirEntry->first_file_index) & 1)) {
+ return new (JKRHeap::sSystemHeap, 0) JKRArcFinder((JKRArchive*)this, dirEntry->first_file_index, countResource(type));
+ }
+ return new (JKRHeap::sSystemHeap, 0) JKRArcFinder((JKRArchive*)this, 0, 0);
}
/* 802B8DC4-802B8DFC .text getFileAttribute__10JKRArchiveCFUl */
-void JKRArchive::getFileAttribute(unsigned long) const {
- /* Nonmatching */
+u32 JKRArchive::getFileAttribute(u32 index) const {
+ SDIFileEntry* fileEntry = findIdxResource(index);
+ if (fileEntry) {
+ return fileEntry->getFlags();
+ }
+
+ return 0;
}
diff --git a/src/JSystem/JKernel/JKRExpHeap.cpp b/src/JSystem/JKernel/JKRExpHeap.cpp
index e09b0383..7cbc894e 100644
--- a/src/JSystem/JKernel/JKRExpHeap.cpp
+++ b/src/JSystem/JKernel/JKRExpHeap.cpp
@@ -4,209 +4,1001 @@
//
#include "JSystem/JKernel/JKRExpHeap.h"
+#include "JSystem/JSupport/JSupport.h"
+#include "JSystem/JUtility/JUTAssert.h"
+#include "JSystem/JUtility/JUTConsole.h"
+#include "JSystem/JUtility/JUTException.h"
+#include "dolphin/os/OS.h"
#include "dolphin/types.h"
/* 802B1558-802B15D0 .text createRoot__10JKRExpHeapFib */
-void JKRExpHeap::createRoot(int, bool) {
- /* Nonmatching */
+JKRExpHeap* JKRExpHeap::createRoot(int maxHeaps, bool errorFlag) {
+ JKRExpHeap* heap = NULL;
+ if (!sRootHeap) {
+ void* memory;
+ u32 memorySize;
+ initArena((char**)&memory, &memorySize, maxHeaps);
+ u8* start = (u8*)memory + OSRoundUp(sizeof(JKRExpHeap), 0x10);
+ u32 alignedSize = memorySize - OSRoundUp(sizeof(JKRExpHeap), 0x10);
+ heap = new (memory) JKRExpHeap(start, alignedSize, NULL, errorFlag);
+ sRootHeap = heap;
+ }
+ heap->field_0x6e = true;
+ return heap;
}
/* 802B15D0-802B16A4 .text create__10JKRExpHeapFUlP7JKRHeapb */
-void JKRExpHeap::create(unsigned long, JKRHeap*, bool) {
- /* Nonmatching */
+JKRExpHeap* JKRExpHeap::create(u32 size, JKRHeap* parent, bool errorFlag) {
+ if (!parent) {
+ parent = sRootHeap;
+ }
+
+ if (size == 0xffffffff) {
+ size = parent->getMaxAllocatableSize(0x10);
+ }
+
+ u32 alignedSize = OSRoundDown(size, 0x10);
+ u32 expHeapSize = OSRoundUp(sizeof(JKRExpHeap), 0x10);
+ if (alignedSize < 0xa0)
+ return NULL;
+
+ u8* memory = (u8*)JKRAllocFromHeap(parent, alignedSize, 0x10);
+ u8* dataPtr = (memory + expHeapSize);
+ if (!memory) {
+ return NULL;
+ }
+
+ JKRExpHeap* newHeap =
+ new (memory) JKRExpHeap(dataPtr, alignedSize - expHeapSize, parent, errorFlag);
+
+ if (newHeap == NULL) {
+ i_JKRFree(memory);
+ return NULL;
+ }
+
+ newHeap->field_0x6e = false;
+ return newHeap;
}
/* 802B16A4-802B1728 .text do_destroy__10JKRExpHeapFv */
void JKRExpHeap::do_destroy() {
- /* Nonmatching */
+ if (!field_0x6e) {
+ JKRHeap* heap = mChildTree.getParent()->getObject();
+ if (heap) {
+ this->~JKRExpHeap();
+ JKRHeap::free(this, heap);
+ }
+ } else {
+ this->~JKRExpHeap();
+ }
}
/* 802B1728-802B17B8 .text __ct__10JKRExpHeapFPvUlP7JKRHeapb */
-JKRExpHeap::JKRExpHeap(void*, unsigned long, JKRHeap*, bool) {
- /* Nonmatching */
+JKRExpHeap::JKRExpHeap(void* data, u32 size, JKRHeap* parent, bool errorFlag) : JKRHeap(data, size, parent, errorFlag) {
+ mAllocMode = 0;
+ mCurrentGroupId = 0xff;
+ mHeadFreeList = (CMemBlock*)data;
+ mTailFreeList = mHeadFreeList;
+ mHeadFreeList->initiate(NULL, NULL, size - sizeof(CMemBlock), 0, 0);
+ mHeadUsedList = NULL;
+ mTailUsedList = NULL;
}
/* 802B17B8-802B1820 .text __dt__10JKRExpHeapFv */
JKRExpHeap::~JKRExpHeap() {
- /* Nonmatching */
+ dispose();
}
/* 802B1820-802B192C .text do_alloc__10JKRExpHeapFUli */
-void JKRExpHeap::do_alloc(unsigned long, int) {
- /* Nonmatching */
-}
+void* JKRExpHeap::do_alloc(u32 size, int alignment) {
+ void* ptr;
+
+ lock();
+ if (size < 4) {
+ size = 4;
+ }
+
+ if (alignment >= 0) {
+ if (alignment <= 4) {
+ ptr = allocFromHead(size);
+ } else {
+ ptr = allocFromHead(size, alignment);
+ }
+ } else {
+ if (-alignment <= 4) {
+ ptr = allocFromTail(size);
+ } else {
+ ptr = allocFromTail(size, -alignment);
+ }
+ }
+
+ if (ptr == NULL) {
+ JUTWarningConsole_f(":::cannot alloc memory (0x%x byte).\n", size);
+ if (mErrorFlag == true) {
+ callErrorHandler(this, size, alignment);
+ }
+ }
+ unlock();
+
+ return ptr;
+}
+
+static u32 DBfoundSize;
+static u32 DBfoundOffset;
+static JKRExpHeap::CMemBlock* DBfoundBlock;
+static JKRExpHeap::CMemBlock* DBnewFreeBlock;
+static JKRExpHeap::CMemBlock* DBnewUsedBlock;
/* 802B192C-802B1B88 .text allocFromHead__10JKRExpHeapFUli */
-void JKRExpHeap::allocFromHead(unsigned long, int) {
- /* Nonmatching */
+// wrong register at end
+void* JKRExpHeap::allocFromHead(u32 size, int align) {
+ /* Nonmatching */
+ u32 foundOffset;
+ int foundSize;
+ CMemBlock* newFreeBlock;
+ CMemBlock* newUsedBlock;
+ CMemBlock* foundBlock;
+
+ size = ALIGN_NEXT(size, 4);
+ foundSize = -1;
+ foundOffset = 0;
+ foundBlock = NULL;
+
+ for (CMemBlock* block = mHeadFreeList; block; block = block->mNext) {
+ u32 offset =
+ ALIGN_PREV(align - 1 + (u32)block->getContent(), align) - (u32)block->getContent();
+ if (block->size < size + offset) {
+ continue;
+ }
+
+ if (foundSize <= (u32)block->size) {
+ continue;
+ }
+
+ foundSize = block->size;
+ foundBlock = block;
+ foundOffset = offset;
+ if (mAllocMode != 0) {
+ break;
+ }
+
+ u32 blockSize = block->size;
+ if (blockSize == size) {
+ break;
+ }
+ }
+
+ DBfoundSize = foundSize;
+ DBfoundOffset = foundOffset;
+ DBfoundBlock = foundBlock;
+
+ if (foundBlock) {
+ if (foundOffset >= sizeof(CMemBlock)) {
+ CMemBlock* prev = foundBlock->mPrev;
+ CMemBlock* next = foundBlock->mNext;
+ newUsedBlock = foundBlock->allocFore(foundOffset - sizeof(CMemBlock), 0, 0, 0, 0);
+
+ if (newUsedBlock) {
+ newFreeBlock = newUsedBlock->allocFore(size, mCurrentGroupId, 0, 0, 0);
+ } else {
+ newFreeBlock = NULL;
+ }
+
+ if (newFreeBlock) {
+ setFreeBlock(foundBlock, prev, newFreeBlock);
+ } else {
+ setFreeBlock(foundBlock, prev, next);
+ }
+
+ if (newFreeBlock) {
+ setFreeBlock(newFreeBlock, foundBlock, next);
+ }
+
+ appendUsedList(newUsedBlock);
+ DBnewFreeBlock = newFreeBlock;
+ DBnewUsedBlock = newUsedBlock;
+ return newUsedBlock->getContent();
+ } else {
+ if (foundOffset != 0) {
+ CMemBlock* prev = foundBlock->mPrev;
+ CMemBlock* next = foundBlock->mNext;
+ removeFreeBlock(foundBlock);
+ newUsedBlock = (CMemBlock*)((u32)foundBlock + foundOffset);
+ newUsedBlock->size = foundBlock->size - foundOffset;
+ newFreeBlock =
+ newUsedBlock->allocFore(size, mCurrentGroupId, (u8)foundOffset, 0, 0);
+ if (newFreeBlock) {
+ setFreeBlock(newFreeBlock, prev, next);
+ }
+ appendUsedList(newUsedBlock);
+ return newUsedBlock->getContent();
+ } else {
+ CMemBlock* prev = foundBlock->mPrev;
+ CMemBlock* next = foundBlock->mNext;
+ // Works but very fake match
+ /*size = (u32)foundBlock->allocFore(size, mCurrentGroupId, 0, 0, 0);
+ removeFreeBlock(foundBlock);
+ if (size) {
+ setFreeBlock((CMemBlock*)size, prev, next);
+ }*/
+ newFreeBlock = foundBlock->allocFore(size, mCurrentGroupId, 0, 0, 0);
+ removeFreeBlock(foundBlock);
+ if (newFreeBlock) {
+ setFreeBlock(newFreeBlock, prev, next);
+ }
+ appendUsedList(foundBlock);
+ return foundBlock->getContent();
+ }
+ }
+ }
+
+ return NULL;
}
/* 802B1B88-802B1C6C .text allocFromHead__10JKRExpHeapFUl */
-void JKRExpHeap::allocFromHead(unsigned long) {
- /* Nonmatching */
+void* JKRExpHeap::allocFromHead(u32 size) {
+ size = ALIGN_NEXT(size, 4);
+ s32 foundSize = -1;
+ CMemBlock* foundBlock = NULL;
+ for (CMemBlock* block = mHeadFreeList; block; block = block->getNextBlock()) {
+ if (block->getSize() < size) {
+ continue;
+ }
+
+ if (foundSize <= block->getSize()) {
+ continue;
+ }
+
+ foundSize = block->getSize();
+ foundBlock = block;
+ if (mAllocMode != 0) {
+ break;
+ }
+
+ if (foundSize == size) {
+ break;
+ }
+ }
+
+ if (foundBlock) {
+ CMemBlock* newblock = foundBlock->allocFore(size, mCurrentGroupId, 0, 0, 0);
+ if (newblock) {
+ setFreeBlock(newblock, foundBlock->getPrevBlock(), foundBlock->getNextBlock());
+ } else {
+ removeFreeBlock(foundBlock);
+ }
+ appendUsedList(foundBlock);
+ return foundBlock->getContent();
+ }
+ return NULL;
}
/* 802B1C6C-802B1DCC .text allocFromTail__10JKRExpHeapFUli */
-void JKRExpHeap::allocFromTail(unsigned long, int) {
- /* Nonmatching */
+void* JKRExpHeap::allocFromTail(u32 size, int align) {
+ u32 offset = 0;
+ CMemBlock* foundBlock = NULL;
+ CMemBlock* newBlock = NULL;
+ u32 usedSize;
+ u32 start;
+
+ for (CMemBlock* block = mTailFreeList; block; block = block->mPrev) {
+ start = ALIGN_PREV((u32)block->getContent() + block->size - size, align);
+ usedSize = (u32)block->getContent() + block->size - start;
+ if (block->size >= usedSize) {
+ foundBlock = block;
+ offset = block->size - usedSize;
+ newBlock = (CMemBlock*)start - 1;
+ break;
+ }
+ }
+
+ if (foundBlock != NULL) {
+ if (offset >= sizeof(CMemBlock)) {
+ newBlock->initiate(NULL, NULL, usedSize, mCurrentGroupId, -0x80);
+ foundBlock->size = foundBlock->size - usedSize - sizeof(CMemBlock);
+ appendUsedList(newBlock);
+ return newBlock->getContent();
+ } else {
+ if (offset != 0) {
+ removeFreeBlock(foundBlock);
+ newBlock->initiate(NULL, NULL, usedSize, mCurrentGroupId, offset | 0x80);
+ appendUsedList(newBlock);
+ return newBlock->getContent();
+ } else {
+ removeFreeBlock(foundBlock);
+ newBlock->initiate(NULL, NULL, usedSize, mCurrentGroupId, -0x80);
+ appendUsedList(newBlock);
+ return newBlock->getContent();
+ }
+ }
+ }
+
+ return NULL;
}
/* 802B1DCC-802B1EA4 .text allocFromTail__10JKRExpHeapFUl */
-void JKRExpHeap::allocFromTail(unsigned long) {
- /* Nonmatching */
+void* JKRExpHeap::allocFromTail(u32 size) {
+ u32 size2 = ALIGN_NEXT(size, 4);
+ CMemBlock* foundBlock = NULL;
+ for (CMemBlock* block = mTailFreeList; block; block = block->getPrevBlock()) {
+ if (block->getSize() >= size2) {
+ foundBlock = block;
+ break;
+ }
+ }
+
+ if (foundBlock != NULL) {
+ CMemBlock* usedBlock = foundBlock->allocBack(size2, 0, 0, mCurrentGroupId, 0);
+ CMemBlock* freeBlock;
+ if (usedBlock) {
+ freeBlock = foundBlock;
+ } else {
+ removeFreeBlock(foundBlock);
+ usedBlock = foundBlock;
+ freeBlock = NULL;
+ }
+
+ if (freeBlock) {
+ setFreeBlock(freeBlock, foundBlock->getPrevBlock(), foundBlock->getNextBlock());
+ }
+ appendUsedList(usedBlock);
+ return usedBlock->getContent();
+ }
+ return NULL;
}
/* 802B1EA4-802B1F44 .text do_free__10JKRExpHeapFPv */
-void JKRExpHeap::do_free(void*) {
- /* Nonmatching */
+void JKRExpHeap::do_free(void* ptr) {
+ lock();
+ if (getStartAddr() <= ptr && ptr <= getEndAddr()) {
+ CMemBlock* block = CMemBlock::getHeapBlock(ptr);
+ if (block) {
+ block->free(this);
+ }
+ } else {
+ JUT_WARN(888, "free: memblock %x not in heap %x", ptr, this);
+ }
+ unlock();
}
/* 802B1F44-802B1FC0 .text do_freeAll__10JKRExpHeapFv */
void JKRExpHeap::do_freeAll() {
- /* Nonmatching */
+ lock();
+ JKRHeap::callAllDisposer();
+ mHeadFreeList = (CMemBlock*)getStartAddr();
+ mTailFreeList = mHeadFreeList;
+ mHeadFreeList->initiate(NULL, NULL, getSize() - 0x10, 0, 0);
+ mHeadUsedList = NULL;
+ mTailUsedList = NULL;
+ unlock();
}
/* 802B1FC0-802B2048 .text do_freeTail__10JKRExpHeapFv */
void JKRExpHeap::do_freeTail() {
- /* Nonmatching */
+ lock();
+ for (CMemBlock* block = mHeadUsedList; block != NULL;) {
+ if ((block->mFlags & 0x80) != 0) {
+ dispose(block + 1, block->size);
+ CMemBlock* temp = block->mNext;
+ block->free(this);
+ block = temp;
+ } else {
+ block = block->mNext;
+ }
+ }
+ unlock();
}
/* 802B2048-802B2098 .text do_changeGroupID__10JKRExpHeapFUc */
-void JKRExpHeap::do_changeGroupID(unsigned char) {
- /* Nonmatching */
+s32 JKRExpHeap::do_changeGroupID(u8 groupId) {
+ lock();
+ u8 prev = mCurrentGroupId;
+ mCurrentGroupId = groupId;
+ unlock();
+ return prev;
}
/* 802B2098-802B2244 .text do_resize__10JKRExpHeapFPvUl */
-void JKRExpHeap::do_resize(void*, unsigned long) {
- /* Nonmatching */
+s32 JKRExpHeap::do_resize(void* ptr, u32 size) {
+ lock();
+ CMemBlock* block = CMemBlock::getHeapBlock(ptr);
+ if (block == NULL || ptr < mStart || mEnd < ptr) {
+ unlock();
+ return -1;
+ }
+
+ size = ALIGN_NEXT(size, 4);
+ if (size == block->size) {
+ unlock();
+ return size;
+ }
+
+ if (size > block->size) {
+ CMemBlock* foundBlock = NULL;
+ for (CMemBlock* freeBlock = mHeadFreeList; freeBlock; freeBlock = freeBlock->mNext) {
+ if (freeBlock == (CMemBlock*)((u32)(block + 1) + block->size)) {
+ foundBlock = freeBlock;
+ break;
+ }
+ }
+
+ if (foundBlock == NULL) {
+ unlock();
+ return -1;
+ }
+
+ if (size > block->size + sizeof(CMemBlock) + foundBlock->size) {
+ unlock();
+ return -1;
+ }
+
+ removeFreeBlock(foundBlock);
+ block->size += foundBlock->size + sizeof(CMemBlock);
+ if (block->size - size > sizeof(CMemBlock)) {
+ CMemBlock* newBlock = block->allocFore(size, block->mGroupId, block->mFlags, 0, 0);
+ if (newBlock) {
+ recycleFreeBlock(newBlock);
+ }
+ }
+ } else {
+ if (block->size - size > sizeof(CMemBlock)) {
+ CMemBlock* freeBlock = block->allocFore(size, block->mGroupId, block->mFlags, 0, 0);
+ if (freeBlock) {
+ recycleFreeBlock(freeBlock);
+ }
+ }
+ }
+
+ unlock();
+ return block->size;
}
/* 802B2244-802B22C4 .text do_getSize__10JKRExpHeapFPv */
-void JKRExpHeap::do_getSize(void*) {
- /* Nonmatching */
+s32 JKRExpHeap::do_getSize(void* ptr) {
+ lock();
+ CMemBlock* block = CMemBlock::getHeapBlock(ptr);
+ if (!block || ptr < getStartAddr() || getEndAddr() < ptr) {
+ unlock();
+ return -1;
+ }
+ unlock();
+ return block->getSize();
}
/* 802B22C4-802B2330 .text do_getFreeSize__10JKRExpHeapFv */
-void JKRExpHeap::do_getFreeSize() {
- /* Nonmatching */
+s32 JKRExpHeap::do_getFreeSize() {
+ lock();
+ s32 size = 0;
+ for (CMemBlock* block = mHeadFreeList; block; block = block->getNextBlock()) {
+ if (size < (s32)block->getSize()) {
+ size = block->getSize();
+ }
+ }
+ unlock();
+ return size;
}
/* 802B2330-802B23A4 .text do_getMaxFreeBlock__10JKRExpHeapFv */
-void JKRExpHeap::do_getMaxFreeBlock() {
- /* Nonmatching */
+void* JKRExpHeap::do_getMaxFreeBlock() {
+ lock();
+ s32 size = 0;
+ CMemBlock* res = NULL;
+ for (CMemBlock* block = mHeadFreeList; block; block = block->getNextBlock()) {
+ if (size < (s32)block->getSize()) {
+ size = block->getSize();
+ res = block;
+ }
+ }
+ unlock();
+ return res;
}
/* 802B23A4-802B2408 .text do_getTotalFreeSize__10JKRExpHeapFv */
-void JKRExpHeap::do_getTotalFreeSize() {
- /* Nonmatching */
+s32 JKRExpHeap::do_getTotalFreeSize() {
+ u32 size = 0;
+ lock();
+ for (CMemBlock* block = mHeadFreeList; block; block = block->getNextBlock()) {
+ size += block->getSize();
+ }
+ unlock();
+ return size;
}
/* 802B2408-802B2484 .text getUsedSize__10JKRExpHeapCFUc */
-void JKRExpHeap::getUsedSize(unsigned char) const {
- /* Nonmatching */
+s32 JKRExpHeap::getUsedSize(u8 groupId) const {
+ JKRExpHeap* this2 = const_cast<JKRExpHeap*>(this);
+ this2->lock();
+ u32 size = 0;
+
+ for (CMemBlock* block = mHeadUsedList; block; block = block->getNextBlock()) {
+ u8 blockGroupId = block->getGroupId();
+ if (blockGroupId == groupId) {
+ size += block->getSize() + sizeof(CMemBlock);
+ }
+ }
+
+ this2->unlock();
+ return size;
}
/* 802B2484-802B24EC .text getTotalUsedSize__10JKRExpHeapCFv */
-void JKRExpHeap::getTotalUsedSize() const {
- /* Nonmatching */
+s32 JKRExpHeap::getTotalUsedSize() const {
+ JKRExpHeap* this2 = const_cast<JKRExpHeap*>(this);
+ this2->lock();
+ u32 size = 0;
+
+ for (CMemBlock* block = mHeadUsedList; block; block = block->getNextBlock()) {
+ size += block->getSize() + sizeof(CMemBlock);
+ }
+
+ this2->unlock();
+ return size;
+}
+
+static void dummy1() {
+ OSReport("newSize > 0");
+ OSReport("Halt");
}
/* 802B24EC-802B2584 .text appendUsedList__10JKRExpHeapFPQ210JKRExpHeap9CMemBlock */
-void JKRExpHeap::appendUsedList(JKRExpHeap::CMemBlock*) {
- /* Nonmatching */
+void JKRExpHeap::appendUsedList(CMemBlock* newblock) {
+ if (!newblock) {
+ OSPanic(__FILE__, 1466, ":::ERROR! appendUsedList\n");
+ }
+
+ CMemBlock* block = mTailUsedList;
+ newblock->mMagic = 'HM';
+
+ if (block) {
+ block->mNext = newblock;
+ newblock->mPrev = block;
+ } else {
+ newblock->mPrev = NULL;
+ }
+
+ mTailUsedList = newblock;
+ if (!mHeadUsedList) {
+ mHeadUsedList = newblock;
+ }
+ newblock->mNext = NULL;
}
/* 802B2584-802B25D0 .text setFreeBlock__10JKRExpHeapFPQ210JKRExpHeap9CMemBlockPQ210JKRExpHeap9CMemBlockPQ210JKRExpHeap9CMemBlock */
-void JKRExpHeap::setFreeBlock(JKRExpHeap::CMemBlock*, JKRExpHeap::CMemBlock*, JKRExpHeap::CMemBlock*) {
- /* Nonmatching */
+void JKRExpHeap::setFreeBlock(CMemBlock* block, CMemBlock* prev, CMemBlock* next) {
+ if (prev == NULL) {
+ mHeadFreeList = block;
+ block->mPrev = NULL;
+ } else {
+ prev->mNext = block;
+ block->mPrev = prev;
+ }
+
+ if (next == NULL) {
+ mTailFreeList = block;
+ block->mNext = NULL;
+ } else {
+ next->mPrev = block;
+ block->mNext = next;
+ }
+
+ block->mMagic = 0;
}
/* 802B25D0-802B2604 .text removeFreeBlock__10JKRExpHeapFPQ210JKRExpHeap9CMemBlock */
-void JKRExpHeap::removeFreeBlock(JKRExpHeap::CMemBlock*) {
- /* Nonmatching */
+void JKRExpHeap::removeFreeBlock(CMemBlock* block) {
+ CMemBlock* prev = block->mPrev;
+ CMemBlock* next = block->mNext;
+
+ if (prev == NULL) {
+ mHeadFreeList = next;
+ } else {
+ prev->mNext = next;
+ }
+
+ if (next == NULL) {
+ mTailFreeList = prev;
+ } else {
+ next->mPrev = prev;
+ }
}
/* 802B2604-802B2638 .text removeUsedBlock__10JKRExpHeapFPQ210JKRExpHeap9CMemBlock */
-void JKRExpHeap::removeUsedBlock(JKRExpHeap::CMemBlock*) {
- /* Nonmatching */
+void JKRExpHeap::removeUsedBlock(CMemBlock* block) {
+ CMemBlock* prev = block->mPrev;
+ CMemBlock* next = block->mNext;
+
+ if (prev == NULL) {
+ mHeadUsedList = next;
+ } else {
+ prev->mNext = next;
+ }
+
+ if (next == NULL) {
+ mTailUsedList = prev;
+ } else {
+ next->mPrev = prev;
+ }
}
/* 802B2638-802B27D0 .text recycleFreeBlock__10JKRExpHeapFPQ210JKRExpHeap9CMemBlock */
-void JKRExpHeap::recycleFreeBlock(JKRExpHeap::CMemBlock*) {
- /* Nonmatching */
+void JKRExpHeap::recycleFreeBlock(CMemBlock* block) {
+ JKRExpHeap::CMemBlock* newBlock = block;
+ int size = block->size;
+ void* blockEnd = (u8*)block + size;
+ block->mMagic = 0;
+
+ if ((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->size = size;
+ }
+
+ if (!mHeadFreeList) {
+ newBlock->initiate(NULL, NULL, size, 0, 0);
+ mHeadFreeList = newBlock;
+ mTailFreeList = newBlock;
+ setFreeBlock(newBlock, NULL, NULL);
+ return;
+ }
+
+ if (mHeadFreeList >= blockEnd) {
+ newBlock->initiate(NULL, NULL, size, 0, 0);
+ setFreeBlock(newBlock, NULL, mHeadFreeList);
+ joinTwoBlocks(newBlock);
+ return;
+ }
+
+ if (mTailFreeList <= newBlock) {
+ newBlock->initiate(NULL, NULL, size, 0, 0);
+ setFreeBlock(newBlock, mTailFreeList, NULL);
+ joinTwoBlocks(newBlock->mPrev);
+ return;
+ }
+
+ for (CMemBlock* freeBlock = mHeadFreeList; 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;
+ }
}
/* 802B27D0-802B291C .text joinTwoBlocks__10JKRExpHeapFPQ210JKRExpHeap9CMemBlock */
-void JKRExpHeap::joinTwoBlocks(JKRExpHeap::CMemBlock*) {
- /* Nonmatching */
+// regalloc
+void JKRExpHeap::joinTwoBlocks(CMemBlock* block) {
+ /* Nonmatching */
+ u32 endAddr = (u32)(block + 1) + block->size;
+ CMemBlock* next = block->mNext;
+ u32 nextAddr = (u32)next - (next->mFlags & 0x7f);
+ if (endAddr > nextAddr) {
+ JUTWarningConsole_f(":::Heap may be broken. (block = %x)", block);
+ OSReport(":::block = %x\n", block);
+ OSReport(":::joinTwoBlocks [%x %x %x][%x %x %x]\n", block, block->mFlags, block->size, block->mNext, block->mNext->mFlags, block->mNext->size);
+ OSReport(":::: endAddr = %x\n", endAddr);
+ OSReport(":::: nextAddr = %x\n", nextAddr);
+ JKRGetCurrentHeap()->dump();
+ OSPanic(__FILE__, 1718, ":::: Bad Block\n");
+ }
+
+ if (endAddr == nextAddr) {
+ block->size = next->size + sizeof(CMemBlock) + next->getAlignment() + block->size;
+ setFreeBlock(block, block->mPrev, next->mNext);
+ }
}
/* 802B291C-802B2B44 .text check__10JKRExpHeapFv */
-void JKRExpHeap::check() {
- /* Nonmatching */
+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->mMagic), JSULoByte(block->mMagic));
+ }
+
+ 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->size + block->getAlignment();
+ }
+
+ for (CMemBlock* block = mHeadFreeList; block; block = block->mNext) {
+ totalBytes += block->size + 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->size + sizeof(CMemBlock) > (u32)block->mNext) {
+ ok = false;
+ JUTWarningConsole_f(":::addr %08x: bad block size (%08x)\n", block, block->size);
+ }
+ } else {
+ if (mTailFreeList != block) {
+ ok = false;
+ JUTWarningConsole_f(":::addr %08x: bad used list(REV) (%08x)\n", block,
+ mTailFreeList);
+ }
+ }
+ }
+
+ 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;
}
/* 802B2B44-802B2B48 .text do_freeFill__10JKRExpHeapFv */
-void JKRExpHeap::do_freeFill() {
- /* Nonmatching */
-}
+void JKRExpHeap::do_freeFill() {}
/* 802B2B48-802B2D5C .text dump__10JKRExpHeapFv */
-void JKRExpHeap::dump() {
- /* Nonmatching */
+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->size, block->mGroupId, block->getAlignment(), block->mPrev,
+ block->mNext);
+ usedBytes += sizeof(CMemBlock) + block->size + block->getAlignment();
+ usedCount++;
+ }
+
+ JUTReportConsole("(Free Blocks)\n");
+ if (!mHeadFreeList) {
+ JUTReportConsole(" NONE\n");
+ }
+
+ for (CMemBlock* block = mHeadFreeList; block; block = block->mNext) {
+ JUTReportConsole_f("%s %08x: %08x %3d %3d (%08x %08x)\n", " free", block->getContent(),
+ block->size, 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;
}
/* 802B2D5C-802B2F5C .text dump_sort_by_address__10JKRExpHeapFv */
-void JKRExpHeap::dump_sort_by_address() {
- /* Nonmatching */
+// regalloc, stack
+bool JKRExpHeap::dump_sort_by_address() {
+ /* Nonmatching */
+ lock();
+ bool result = check();
+ u32 usedBytes = 0;
+ u32 usedCount = 0;
+ u32 freeCount = 0;
+ JUTReportConsole(" attr address: size gid aln prev_ptr next_ptr\n");
+
+ CMemBlock* block;
+ for (CMemBlock* var1 = NULL; true; var1 = block) {
+ CMemBlock* block = (CMemBlock*)0xffffffff;
+ for (CMemBlock* iterBlock = mHeadFreeList; iterBlock; iterBlock = iterBlock->getNextBlock()) {
+ if (var1 < iterBlock && iterBlock < block) {
+ block = iterBlock;
+ }
+ }
+
+ for (CMemBlock* iterBlock = mHeadUsedList; iterBlock; iterBlock = iterBlock->getNextBlock()) {
+ if (var1 < iterBlock && iterBlock < block) {
+ block = iterBlock;
+ }
+ }
+
+ if (block == (CMemBlock*)0xffffffff) {
+ break;
+ }
+
+ if (block->mMagic == 0) {
+ JUTReportConsole_f("%s %08x: %08x %3d %3d (%08x %08x)\n", " free", block->getContent(), block->getSize(), block->getGroupId(), block->getAlignment(), block->getPrevBlock(), block->getNextBlock());
+ freeCount += 1;
+ continue;
+ }
+
+ 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->getSize(),
+ block->getGroupId(), offset, block->getPrevBlock(), block->getNextBlock());
+ usedBytes += sizeof(CMemBlock) + block->size + block->getAlignment();
+ usedCount++;
+ }
+
+ 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;
}
/* 802B2F5C-802B2F7C .text dump_sort__10JKRExpHeapFv */
-void JKRExpHeap::dump_sort() {
- /* Nonmatching */
+bool JKRExpHeap::dump_sort() {
+ return dump_sort_by_address();
}
/* 802B2F7C-802B2F9C .text initiate__Q210JKRExpHeap9CMemBlockFPQ210JKRExpHeap9CMemBlockPQ210JKRExpHeap9CMemBlockUlUcUc */
-void JKRExpHeap::CMemBlock::initiate(JKRExpHeap::CMemBlock*, JKRExpHeap::CMemBlock*, unsigned long, unsigned char, unsigned char) {
- /* Nonmatching */
+void JKRExpHeap::CMemBlock::initiate(CMemBlock* prev, CMemBlock* next, u32 size, u8 groupId, u8 alignment) {
+ mMagic = 'HM';
+ mFlags = alignment;
+ mGroupId = groupId;
+ this->size = size;
+ mPrev = prev;
+ mNext = next;
}
/* 802B2F9C-802B2FE0 .text allocFore__Q210JKRExpHeap9CMemBlockFUlUcUcUcUc */
-void JKRExpHeap::CMemBlock::allocFore(unsigned long, unsigned char, unsigned char, unsigned char, unsigned char) {
- /* Nonmatching */
+JKRExpHeap::CMemBlock* JKRExpHeap::CMemBlock::allocFore(u32 size, u8 groupId1, u8 alignment1, u8 groupId2, u8 alignment2) {
+ CMemBlock* block = NULL;
+ mGroupId = groupId1;
+ mFlags = alignment1;
+ if (getSize() >= size + sizeof(CMemBlock)) {
+ block = (CMemBlock*)(size + (u32)this);
+ block[1].mGroupId = groupId2;
+ block[1].mFlags = alignment2;
+ block[1].size = this->size - (size + sizeof(CMemBlock));
+ this->size = size;
+ block = block + 1;
+ }
+ return block;
}
/* 802B2FE0-802B3038 .text allocBack__Q210JKRExpHeap9CMemBlockFUlUcUcUcUc */
-void JKRExpHeap::CMemBlock::allocBack(unsigned long, unsigned char, unsigned char, unsigned char, unsigned char) {
- /* Nonmatching */
+JKRExpHeap::CMemBlock* JKRExpHeap::CMemBlock::allocBack(u32 size, u8 groupId1, u8 alignment1, u8 groupId2, u8 alignment2) {
+ CMemBlock* newblock = NULL;
+ if (getSize() >= size + sizeof(CMemBlock)) {
+ newblock = (CMemBlock*)((u32)this + getSize() - size);
+ newblock->mGroupId = groupId2;
+ newblock->mFlags = alignment2 | 0x80;
+ newblock->size = size;
+ mGroupId = groupId1;
+ mFlags = alignment1;
+ this->size -= size + sizeof(CMemBlock);
+ } else {
+ mGroupId = groupId2;
+ mFlags = 0x80;
+ }
+ return newblock;
}
/* 802B3038-802B3088 .text free__Q210JKRExpHeap9CMemBlockFP10JKRExpHeap */
-void JKRExpHeap::CMemBlock::free(JKRExpHeap*) {
- /* Nonmatching */
+int JKRExpHeap::CMemBlock::free(JKRExpHeap* heap) {
+ heap->removeUsedBlock(this);
+ heap->recycleFreeBlock(this);
+ return 0;
}
/* 802B3088-802B30A4 .text getHeapBlock__Q210JKRExpHeap9CMemBlockFPv */
-void JKRExpHeap::CMemBlock::getHeapBlock(void*) {
- /* Nonmatching */
+JKRExpHeap::CMemBlock* JKRExpHeap::CMemBlock::getHeapBlock(void* ptr) {
+ if (ptr) {
+ CMemBlock* block = (CMemBlock*)ptr - 1;
+ if (block->isValid()) {
+ return block;
+ }
+ }
+ return NULL;
+}
+
+static void dummy2() {
+ OSReport("+---------------JKRExpHeap\n");
+ OSReport("| Align Group size ( prev , next )\n");
+ OSReport("| ---- FreeFirst\n");
+ OSReport("| %08x ");
+ OSReport("%2x %3d %6x (%08x %08x)\n");
+ OSReport("| ---- FreeLast\n");
+ OSReport("| ---- UsedFirst\n");
+ OSReport("| ---- UsedLast\n");
+ OSReport("+---------------End\n");
}
/* 802B30A4-802B31D4 .text state_register__10JKRExpHeapCFPQ27JKRHeap6TStateUl */
-void JKRExpHeap::state_register(JKRHeap::TState*, unsigned long) const {
- /* Nonmatching */
+void JKRExpHeap::state_register(TState* p, u32 param_1) const {
+ JUT_ASSERT(2423, p != 0);
+ JUT_ASSERT(2424, p->getHeap() == this);
+ p->mId = param_1;
+ if (param_1 <= 0xff) {
+ p->mUsedSize = getUsedSize(param_1);
+ } else {
+ s32 freeSize = const_cast<JKRExpHeap*>(this)->getTotalFreeSize();
+ p->mUsedSize = getSize() - freeSize;
+ }
+
+ u32 checkCode = 0;
+ for (CMemBlock* block = mHeadUsedList; block; block = block->getNextBlock()) {
+ if (param_1 <= 0xff) {
+ u8 groupId = block->getGroupId();
+ if (groupId == param_1) {
+ checkCode += (u32)block * 3;
+ }
+ } else {
+ checkCode += (u32)block * 3;
+ }
+ }
+ p->mCheckCode = checkCode;
}
/* 802B31D4-802B327C .text state_compare__10JKRExpHeapCFRCQ27JKRHeap6TStateRCQ27JKRHeap6TState */
-void JKRExpHeap::state_compare(const JKRHeap::TState&, const JKRHeap::TState&) const {
- /* Nonmatching */
+bool JKRExpHeap::state_compare(const JKRHeap::TState& r1, const JKRHeap::TState& r2) const {
+ JUT_ASSERT(2471, r1.getHeap() == r2.getHeap());
+ bool result = true;
+ if (r1.mCheckCode != r2.mCheckCode) {
+ result = false;
+ }
+
+ if (r1.mUsedSize != r2.mUsedSize) {
+ result = false;
+ }
+
+ return result;
}
/* 802B327C-802B3288 .text getHeapType__10JKRExpHeapFv */
-void JKRExpHeap::getHeapType() {
- /* Nonmatching */
+u32 JKRExpHeap::getHeapType() {
+ return 'EXPH';
}
/* 802B3288-802B3290 .text do_getCurrentGroupId__10JKRExpHeapFv */
-void JKRExpHeap::do_getCurrentGroupId() {
- /* Nonmatching */
+u8 JKRExpHeap::do_getCurrentGroupId() {
+ return mCurrentGroupId;
}
diff --git a/src/JSystem/JKernel/JKRFileLoader.cpp b/src/JSystem/JKernel/JKRFileLoader.cpp
index a3d027f3..397d3e3f 100644
--- a/src/JSystem/JKernel/JKRFileLoader.cpp
+++ b/src/JSystem/JKernel/JKRFileLoader.cpp
@@ -4,54 +4,157 @@
//
#include "JSystem/JKernel/JKRFileLoader.h"
-#include "dolphin/types.h"
+#include "MSL_C/string.h"
+#include "MSL_C/MSL_Common/Src/ctype.h"
+#include "global.h"
+
+JKRFileLoader* JKRFileLoader::sCurrentVolume;
+JSUList<JKRFileLoader> JKRFileLoader::sVolumeList;
/* 802B6770-802B67C8 .text __ct__13JKRFileLoaderFv */
-JKRFileLoader::JKRFileLoader() {
- /* Nonmatching */
+JKRFileLoader::JKRFileLoader() : mFileLoaderLink(this) {
+ mVolumeName = NULL;
+ mVolumeType = 0;
+ mMountCount = 0;
}
/* 802B67C8-802B6854 .text __dt__13JKRFileLoaderFv */
JKRFileLoader::~JKRFileLoader() {
- /* Nonmatching */
+ if (getCurrentVolume() == this) {
+ setCurrentVolume(NULL);
+ }
}
/* 802B6854-802B68A4 .text unmount__13JKRFileLoaderFv */
void JKRFileLoader::unmount() {
- /* Nonmatching */
+ s32 count = mMountCount;
+ if (mMountCount != 0) {
+ count--;
+ mMountCount = count;
+ if (count == 0) {
+ delete this;
+ }
+ }
}
/* 802B68A4-802B68F0 .text getGlbResource__13JKRFileLoaderFPCc */
-void JKRFileLoader::getGlbResource(const char*) {
- /* Nonmatching */
+void* JKRFileLoader::getGlbResource(const char* name) {
+ const char* name_reference[1];
+ name_reference[0] = name;
+
+ JKRFileLoader* fileLoader = findVolume(name_reference);
+ void* resource;
+ if (fileLoader == NULL) {
+ resource = NULL;
+ } else {
+ resource = fileLoader->getResource(name_reference[0]);
+ }
+
+ return resource;
}
/* 802B68F0-802B6988 .text getGlbResource__13JKRFileLoaderFPCcP13JKRFileLoader */
-void JKRFileLoader::getGlbResource(const char*, JKRFileLoader*) {
- /* Nonmatching */
+void* JKRFileLoader::getGlbResource(const char* name, JKRFileLoader* fileLoader) {
+ void* resource = NULL;
+ if (fileLoader) {
+ return fileLoader->getResource(0, name);
+ }
+
+ JSUList<JKRFileLoader>& volumeList = getVolumeList();
+ JSUListIterator<JKRFileLoader> iterator;
+ for (iterator = volumeList.getFirst(); iterator != volumeList.getEnd(); ++iterator) {
+ resource = iterator->getResource(0, name);
+ if (resource)
+ break;
+ }
+ return resource;
}
/* 802B6988-802B6A20 .text removeResource__13JKRFileLoaderFPvP13JKRFileLoader */
-void JKRFileLoader::removeResource(void*, JKRFileLoader*) {
- /* Nonmatching */
+bool JKRFileLoader::removeResource(void* resource, JKRFileLoader* fileLoader) {
+ if (fileLoader) {
+ return fileLoader->removeResource(resource);
+ }
+
+ JSUList<JKRFileLoader>& volumeList = getVolumeList();
+ JSUListIterator<JKRFileLoader> iterator;
+ for (iterator = volumeList.getFirst(); iterator != volumeList.getEnd(); ++iterator) {
+ if (iterator->removeResource(resource)) {
+ return true;
+ }
+ }
+
+ return false;
}
/* 802B6A20-802B6AB8 .text detachResource__13JKRFileLoaderFPvP13JKRFileLoader */
-void JKRFileLoader::detachResource(void*, JKRFileLoader*) {
- /* Nonmatching */
+bool JKRFileLoader::detachResource(void* resource, JKRFileLoader* fileLoader) {
+ if (fileLoader) {
+ return fileLoader->detachResource(resource);
+ }
+
+ JSUList<JKRFileLoader>& volumeList = getVolumeList();
+ JSUListIterator<JKRFileLoader> iterator;
+ for (iterator = volumeList.getFirst(); iterator != volumeList.getEnd(); ++iterator) {
+ if (iterator->detachResource(resource)) {
+ return true;
+ }
+ }
+
+ return false;
}
/* 802B6AB8-802B6B44 .text findVolume__13JKRFileLoaderFPPCc */
-void JKRFileLoader::findVolume(const char**) {
- /* Nonmatching */
+JKRFileLoader* JKRFileLoader::findVolume(const char** volumeName) {
+ if (*volumeName[0] != '/') {
+ return getCurrentVolume();
+ }
+
+ char volumeNameBuffer[0x101];
+ *volumeName = fetchVolumeName(volumeNameBuffer, ARRAY_SIZE(volumeNameBuffer), *volumeName);
+
+ JSUList<JKRFileLoader>& volumeList = getVolumeList();
+ JSUListIterator<JKRFileLoader> iterator;
+ for (iterator = volumeList.getFirst(); iterator != volumeList.getEnd(); ++iterator) {
+ if (strcmp(volumeNameBuffer, iterator->mVolumeName) == 0) {
+ return iterator.getObject();
+ }
+ }
+
+ return NULL;
}
+static char rootPath[2] = "/";
+
/* 802B6B44-802B6C20 .text fetchVolumeName__13JKRFileLoaderFPclPCc */
-void JKRFileLoader::fetchVolumeName(char*, long, const char*) {
- /* Nonmatching */
-}
+const char* JKRFileLoader::fetchVolumeName(char* buffer, long bufferSize, const char* path) {
+ if (strcmp(path, "/") == 0) {
+ strcpy(buffer, rootPath);
+ return rootPath;
+ }
+
+ path++;
+ while (*path != 0 && *path != '/') {
+ if (1 < bufferSize) {
+ int lower_char;
+ int ch = (int)*path;
+ if (ch == -1) {
+ lower_char = -1;
+ } else {
+ lower_char = __lower_map[ch & 0xFF];
+ }
+
+ *buffer = lower_char;
+ buffer++;
+ bufferSize--;
+ }
+ path++;
+ }
+
+ *buffer = '\0';
+ if (*path == '\0') {
+ path = rootPath;
+ }
-/* 802B6C64-802B6CB8 .text __dt__24JSUList<13JKRFileLoader>Fv */
-JSUList<JKRFileLoader>::~JSUList() {
- /* Nonmatching */
+ return path;
}
diff --git a/src/JSystem/JKernel/JKRThread.cpp b/src/JSystem/JKernel/JKRThread.cpp
index cf539ab9..a8465bec 100644
--- a/src/JSystem/JKernel/JKRThread.cpp
+++ b/src/JSystem/JKernel/JKRThread.cpp
@@ -4,54 +4,135 @@
//
#include "JSystem/JKernel/JKRThread.h"
+#include "JSystem/JUtility/JUTAssert.h"
#include "dolphin/types.h"
+JSUList<JKRThread> JKRThread::sThreadList;
+JKRThreadSwitch* JKRThreadSwitch::sManager;
+OSThread* preEnd;
+JKRThreadSwitch_PreCallback JKRThreadSwitch::mUserPreCallback;
+JKRThreadSwitch_PostCallback JKRThreadSwitch::mUserPostCallback;
+
/* 802B3D1C-802B3E38 .text __ct__9JKRThreadFUlii */
-JKRThread::JKRThread(unsigned long, int, int) {
- /* Nonmatching */
+JKRThread::JKRThread(u32 stack_size, int message_count, int param_3) : mThreadListLink(this) {
+ mHeap = JKRHeap::findFromRoot(this);
+ if (mHeap == NULL) {
+ mHeap = JKRGetSystemHeap();
+ }
+
+ mStackSize = stack_size & 0xffffffe0;
+ mStackMemory = JKRAllocFromHeap(mHeap, mStackSize, 0x20);
+ mThreadRecord = (OSThread*)JKRAllocFromHeap(mHeap, sizeof(OSThread), 0x20);
+
+ void* stackBase = (void*)((int)mStackMemory + mStackSize);
+ OSCreateThread(mThreadRecord, start, this, stackBase, mStackSize, param_3, 1);
+
+ mMessageCount = message_count;
+ mMessages = (OSMessage*)JKRAllocFromHeap(mHeap, mMessageCount * sizeof(OSMessage), 0);
+
+ OSInitMessageQueue(&mMessageQueue, mMessages, mMessageCount);
+ getList().append(&mThreadListLink);
+
+ mCurrentHeap = NULL;
+ mCurrentHeapError = NULL;
}
/* 802B3E38-802B3EFC .text __ct__9JKRThreadFP8OSThreadi */
-JKRThread::JKRThread(OSThread*, int) {
- /* Nonmatching */
+JKRThread::JKRThread(OSThread* thread, int message_count) : mThreadListLink(this) {
+ mHeap = NULL;
+ mThreadRecord = thread;
+ mStackSize = (u32)thread->stack_end - (u32)thread->stack_base;
+ mStackMemory = thread->stack_base;
+
+ mMessageCount = message_count;
+ mMessages = (OSMessage*)JKRGetSystemHeap()->alloc(mMessageCount * sizeof(OSMessage), 4);
+
+ OSInitMessageQueue(&mMessageQueue, mMessages, mMessageCount);
+ getList().append(&mThreadListLink);
+
+ mCurrentHeap = NULL;
+ mCurrentHeapError = NULL;
}
/* 802B3EFC-802B3FD4 .text __dt__9JKRThreadFv */
JKRThread::~JKRThread() {
- /* Nonmatching */
+ getList().remove(&mThreadListLink);
+
+ if (mHeap) {
+ BOOL result = OSIsThreadTerminated(mThreadRecord);
+ if (result == FALSE) {
+ OSDetachThread(mThreadRecord);
+ OSCancelThread(mThreadRecord);
+ }
+ JKRFreeToHeap(mHeap, mStackMemory);
+ JKRFreeToHeap(mHeap, mThreadRecord);
+ }
+ i_JKRFree(mMessages);
}
/* 802B3FD4-802B4000 .text start__9JKRThreadFPv */
-void JKRThread::start(void*) {
- /* Nonmatching */
+void* JKRThread::start(void* param) {
+ JKRThread* thread = (JKRThread*)param;
+ return thread->run();
}
/* 802B4000-802B4050 .text __ct__15JKRThreadSwitchFP7JKRHeap */
-JKRThreadSwitch::JKRThreadSwitch(JKRHeap*) {
- /* Nonmatching */
+JKRThreadSwitch::JKRThreadSwitch(JKRHeap* param_0) {
+ mHeap = param_0;
+ OSSetSwitchThreadCallback(JKRThreadSwitch::callback);
+ mSetNextHeap = true;
}
/* 802B4050-802B40EC .text createManager__15JKRThreadSwitchFP7JKRHeap */
-void JKRThreadSwitch::createManager(JKRHeap*) {
- /* Nonmatching */
+JKRThreadSwitch* JKRThreadSwitch::createManager(JKRHeap* heap) {
+ JUT_ASSERT(184, sManager == 0);
+
+ if (!heap) {
+ heap = JKRGetCurrentHeap();
+ }
+
+ sManager = new (heap, 0) JKRThreadSwitch(heap);
+ return sManager;
}
/* 802B40EC-802B41DC .text callback__15JKRThreadSwitchFP8OSThreadP8OSThread */
-void JKRThreadSwitch::callback(OSThread*, OSThread*) {
- /* Nonmatching */
-}
+void JKRThreadSwitch::callback(OSThread* current, OSThread* next) {
+ if (mUserPreCallback) {
+ (*mUserPreCallback)(current, next);
+ }
-/* 802B41DC-802B41E4 .text run__9JKRThreadFv */
-void JKRThread::run() {
- /* Nonmatching */
-}
+ if (!current && !next) {
+ preEnd = current;
+ current = NULL;
+ }
-/* 802B41E4-802B422C .text __dt__15JKRThreadSwitchFv */
-JKRThreadSwitch::~JKRThreadSwitch() {
- /* Nonmatching */
-}
+ if (!current && !next) {
+ current = preEnd;
+ preEnd = NULL;
+ }
-/* 802B4270-802B42C4 .text __dt__19JSUList<9JKRThread>Fv */
-JSUList<JKRThread>::~JSUList() {
- /* Nonmatching */
+ JSUList<JKRThread>& threadList = JKRThread::getList();
+ JSUListIterator<JKRThread> iterator;
+ for (iterator = threadList.getFirst(); iterator != threadList.getEnd(); ++iterator) {
+ JKRThread* thread = iterator.getObject();
+
+ if (thread->getThreadRecord() == current) {
+ thread->setCurrentHeap(JKRHeap::getCurrentHeap());
+ }
+
+ if (thread->getThreadRecord() == next) {
+ if (sManager->mSetNextHeap) {
+ thread->getCurrentHeap()->becomeCurrentHeap();
+ }
+ }
+ }
+
+ if (mUserPostCallback) {
+ (*mUserPostCallback)(current, next);
+ }
}
+
+static void dummy() {
+ OSReport("Cannot create JKRTask Manager.");
+ OSReport("sManager != 0");
+} \ No newline at end of file