diff --git a/configure.py b/configure.py index adf1d07b5..35921b930 100644 --- a/configure.py +++ b/configure.py @@ -768,7 +768,7 @@ config.libs = [ Object(NonMatching, "JSystem/JKernel/JKRAramStream.cpp"), Object(Matching, "JSystem/JKernel/JKRFileLoader.cpp"), Object(Matching, "JSystem/JKernel/JKRFileFinder.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRFileCache.cpp"), + Object(Matching, "JSystem/JKernel/JKRFileCache.cpp"), Object(NonMatching, "JSystem/JKernel/JKRArchivePub.cpp"), Object(NonMatching, "JSystem/JKernel/JKRArchivePri.cpp"), Object(Matching, "JSystem/JKernel/JKRMemArchive.cpp"), diff --git a/include/JSystem/JKernel/JKRFileCache.h b/include/JSystem/JKernel/JKRFileCache.h index b4b9830bc..892f1670b 100644 --- a/include/JSystem/JKernel/JKRFileCache.h +++ b/include/JSystem/JKernel/JKRFileCache.h @@ -41,10 +41,10 @@ public: /* vt[12] */ virtual u32 getResSize(const void*) const; /* override */ /* vt[13] */ virtual u32 countFile(const char*) const; /* override */ /* vt[14] */ virtual JKRFileFinder* getFirstFile(const char*) const; /* override */ - /* vt[15] */ virtual void* getFsResource(const char*); - /* vt[16] */ virtual void* getNameResource(u32, const char*); - /* vt[17] */ virtual u32 readFsResource(void*, u32, const char*); - /* vt[18] */ virtual u32 readNameResource(void*, u32, u32, const char*); + /* vt[15] */ virtual void* getFsResource(const char* path) { return getResource(path); } + /* vt[16] */ virtual void* getNameResource(u32 type, const char* path) { return getResource(type, path); } + /* vt[17] */ virtual u32 readFsResource(void* dst, u32 dstLength, const char* path) { return readResource(dst, dstLength, path); } + /* vt[18] */ virtual u32 readNameResource(void* dst, u32 dstLength, u32 type, const char* path) { return readResource(dst, dstLength, type, path); } private: /* 0x00 */ // vtable diff --git a/src/JSystem/JKernel/JKRFileCache.cpp b/src/JSystem/JKernel/JKRFileCache.cpp index 26190b9d3..89f60a249 100644 --- a/src/JSystem/JKernel/JKRFileCache.cpp +++ b/src/JSystem/JKernel/JKRFileCache.cpp @@ -4,124 +4,399 @@ // #include "JSystem/JKernel/JKRFileCache.h" -#include "dolphin/types.h" +#include "JSystem/JKernel/JKRDvdFile.h" +#include "JSystem/JKernel/JKRFileFinder.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "MSL_C/MSL_Common/Src/ctype.h" +#include "MSL_C/string.h" +#include "global.h" /* 802B6FEC-802B70EC .text mount__12JKRFileCacheFPCcP7JKRHeapPCc */ -void JKRFileCache::mount(const char*, JKRHeap*, const char*) { - /* Nonmatching */ +JKRFileCache* JKRFileCache::mount(const char* path, JKRHeap* heap, const char* param_3) { + if (!path || *path != '/') { + return NULL; + } + + u32 pathLength = strlen(path); + if (pathLength != 1 && path[pathLength - 1] == '/') { + return NULL; + } + + JSUList& volumeList = getVolumeList(); + JSUListIterator iterator; + for (iterator = volumeList.getFirst(); iterator != volumeList.getEnd(); ++iterator) { + if (iterator->getVolumeType() == 'CASH') { + JKRFileCache* fileCache = (JKRFileCache*)iterator.getObject(); + if (fileCache->mRootPath) { + if (strcmp(fileCache->mRootPath, path) == 0) { + fileCache->mMountCount++; + return fileCache; + } + } + } + } + + return new (heap, 0) JKRFileCache(path, param_3); } /* 802B70EC-802B72A8 .text __ct__12JKRFileCacheFPCcPCc */ -JKRFileCache::JKRFileCache(const char*, const char*) { - /* Nonmatching */ +JKRFileCache::JKRFileCache(const char* path, const char* volume) { + mParentHeap = JKRHeap::findFromRoot(this); + mMountCount = 1; + mVolumeType = 'CASH'; + + u32 pathLength = strlen(path); + mRootPath = (char*)JKRAllocFromHeap(mParentHeap, pathLength + 1, 1); + mCurrentPath = (char*)JKRAllocFromSysHeap(pathLength + 2, 1); + strcpy(mRootPath, path); + strcpy(mCurrentPath, path); + + if (path[1] != '\0') { + convStrLower(mRootPath); + convStrLower(mCurrentPath); + strcat(mCurrentPath, "/"); + + const char* volumePath = volume; + if (!volume) { + volumePath = strrchr(mRootPath, '/'); + volumePath++; + } + + u32 volumeLength = strlen(volumePath) + 1; + mVolumePath = (char*)JKRAllocFromSysHeap(volumeLength, 0); + strcpy(mVolumePath, volumePath); + convStrLower(mVolumePath); + mVolumeName = mVolumePath; + } else { + const char* volumePath = volume; + if (!volume) { + volumePath = "dvd"; + } + + u32 volumeLength = strlen(volumePath) + 1; + mVolumePath = (char*)JKRAllocFromSysHeap(volumeLength, 0); + strcpy(mVolumePath, volumePath); + convStrLower(mVolumePath); + mVolumeName = mVolumePath; + } + + getVolumeList().prepend(&mFileLoaderLink); + mIsMounted = true; } /* 802B72A8-802B737C .text __dt__12JKRFileCacheFv */ JKRFileCache::~JKRFileCache() { - /* Nonmatching */ + removeResourceAll(); + if (mRootPath) + JKRFreeToHeap(mParentHeap, mRootPath); + if (mCurrentPath) + JKRFreeToSysHeap(mCurrentPath); + if (mVolumePath) + JKRFreeToSysHeap(mVolumePath); + + getVolumeList().remove(&mFileLoaderLink); } /* 802B737C-802B7410 .text becomeCurrent__12JKRFileCacheFPCc */ -void JKRFileCache::becomeCurrent(const char*) { - /* Nonmatching */ +bool JKRFileCache::becomeCurrent(const char* path) { + char* dvdPathName = getDvdPathName(path); + + bool result = DVDChangeDir(dvdPathName); + if (result) { + sCurrentVolume = this; + JKRHeap::sSystemHeap->free(mCurrentPath); + mCurrentPath = dvdPathName; + if (mCurrentPath[1] != '\0') { + strcat(mCurrentPath, "/"); + } + } else { + JKRHeap::sSystemHeap->free(dvdPathName); + } + + return result; } /* 802B7410-802B7564 .text getResource__12JKRFileCacheFPCc */ -void JKRFileCache::getResource(const char*) { - /* Nonmatching */ +void* JKRFileCache::getResource(const char* path) { + JUT_ASSERT(237, isMounted()); + + void* buffer = NULL; + char* name = getDvdPathName(path); + + JKRDvdFile dvdFile(name); + if (dvdFile.isAvailable()) { + CCacheBlock* cacheBlock = findCacheBlock(dvdFile.getFileID()); + if (!cacheBlock) { + u32 fileSize = dvdFile.getFileInfo()->length; + u32 alignedSize = ALIGN_NEXT(fileSize, 0x20); + buffer = JKRAllocFromHeap(mParentHeap, alignedSize, 0x20); + if (buffer) { + dvdFile.read(buffer, alignedSize, 0); + + cacheBlock = new (JKRHeap::getSystemHeap(), 0) + CCacheBlock(dvdFile.getFileID(), dvdFile.getFileInfo()->length, buffer); + mCacheBlockList.append(&cacheBlock->mCacheBlockLink); + } + } else { + cacheBlock->mReferenceCount++; + buffer = cacheBlock->mMemoryPtr; + } + } + + JKRFreeToSysHeap(name); + return buffer; } /* 802B7564-802B7630 .text getResource__12JKRFileCacheFUlPCc */ -void JKRFileCache::getResource(unsigned long, const char*) { - /* Nonmatching */ +void* JKRFileCache::getResource(unsigned long, const char* path) { + JUT_ASSERT(303, isMounted()); + + char finalPath[256]; + u32 rootLength = strlen(mRootPath); + char* filePath = finalPath + rootLength; + strcpy(finalPath, mRootPath); + + bool found = findFile(finalPath, path); + if (found) { + return getResource(filePath); + } + + return NULL; } /* 802B7630-802B7754 .text readResource__12JKRFileCacheFPvUlPCc */ -void JKRFileCache::readResource(void*, unsigned long, const char*) { - /* Nonmatching */ +u32 JKRFileCache::readResource(void* dst, u32 dstLength, const char* path) { + JUT_ASSERT(344, isMounted()); + + char* name = getDvdPathName(path); + JKRDvdFile dvdFile(name); + + u32 resourceSize = 0; + + while (true) { + if (!dvdFile.isAvailable()) { + break; + } + u32 fileSize = dvdFile.getFileInfo()->length; + resourceSize = ALIGN_NEXT(fileSize, 0x20); + dstLength = ALIGN_PREV(dstLength, 0x20); + if (resourceSize > dstLength) { + resourceSize = dstLength; + } + + CCacheBlock* cacheBlock = findCacheBlock(dvdFile.getFileID()); + if (!cacheBlock) { + dvdFile.read(dst, resourceSize, 0); + } else { + memcpy(dst, cacheBlock->mMemoryPtr, resourceSize); + } + } + + JKRFreeToSysHeap(name); + return resourceSize; } /* 802B7754-802B7830 .text readResource__12JKRFileCacheFPvUlUlPCc */ -void JKRFileCache::readResource(void*, unsigned long, unsigned long, const char*) { - /* Nonmatching */ +u32 JKRFileCache::readResource(void* dst, u32 dstLength, u32, const char* path) { + JUT_ASSERT(412, isMounted()); + + char finalPath[256]; + u32 rootLength = strlen(mRootPath); + char* filePath = finalPath + rootLength; + strcpy(finalPath, mRootPath); + + bool found = findFile(finalPath, path); + if (found) + return readResource(dst, dstLength, filePath); + + return NULL; } /* 802B7830-802B7904 .text removeResourceAll__12JKRFileCacheFv */ void JKRFileCache::removeResourceAll() { - /* Nonmatching */ + JUT_ASSERT(441, isMounted()); + + JSUListIterator iterator; + iterator = mCacheBlockList.getFirst(); + while (iterator != mCacheBlockList.getEnd()) { + JKRFreeToHeap(mParentHeap, iterator->mMemoryPtr); + mCacheBlockList.remove(&iterator.getObject()->mCacheBlockLink); + CCacheBlock* cacheBlock = (iterator++).getObject(); + delete cacheBlock; + } } /* 802B7904-802B79E4 .text removeResource__12JKRFileCacheFPv */ -void JKRFileCache::removeResource(void*) { - /* Nonmatching */ +bool JKRFileCache::removeResource(void* resource) { + JUT_ASSERT(463, isMounted()); + + CCacheBlock* cacheBlock = findCacheBlock(resource); + if (!cacheBlock) + return false; + + u32 referenceCount = cacheBlock->mReferenceCount - 1; + cacheBlock->mReferenceCount = referenceCount; + if (referenceCount == 0) { + JKRFreeToHeap(mParentHeap, resource); + mCacheBlockList.remove(&cacheBlock->mCacheBlockLink); + delete cacheBlock; + } + + return true; } /* 802B79E4-802B7AA8 .text detachResource__12JKRFileCacheFPv */ -void JKRFileCache::detachResource(void*) { - /* Nonmatching */ +bool JKRFileCache::detachResource(void* resource) { + JUT_ASSERT(490, isMounted()); + + CCacheBlock* cacheBlock = findCacheBlock(resource); + if (!cacheBlock) + return false; + + mCacheBlockList.remove(&cacheBlock->mCacheBlockLink); + delete cacheBlock; + return true; } /* 802B7AA8-802B7ADC .text getResSize__12JKRFileCacheCFPCv */ -void JKRFileCache::getResSize(const void*) const { - /* Nonmatching */ +u32 JKRFileCache::getResSize(const void* resource) const { + CCacheBlock* cacheBlock = findCacheBlock(resource); + if (cacheBlock == NULL) { + return -1; + } else { + return cacheBlock->mFileSize; + } } /* 802B7ADC-802B7B58 .text countFile__12JKRFileCacheCFPCc */ -void JKRFileCache::countFile(const char*) const { - /* Nonmatching */ +u32 JKRFileCache::countFile(const char* path) const { + DVDDirectory dir; + DVDDirectoryEntry dirEntry; + + u32 count = 0; + char* name = getDvdPathName(path); + BOOL result = DVDOpenDir(name, &dir); + if (result != 0) { + while (result = DVDReadDir(&dir, &dirEntry), result != FALSE) { + count = count + 1; + } + + DVDCloseDir(&dir); + } + + JKRFreeToSysHeap(name); + return count; } /* 802B7B58-802B7BF4 .text getFirstFile__12JKRFileCacheCFPCc */ -void JKRFileCache::getFirstFile(const char*) const { - /* Nonmatching */ +JKRFileFinder* JKRFileCache::getFirstFile(const char* path) const { + char* name = getDvdPathName(path); + JKRHeap* systemHeap = JKRHeap::getSystemHeap(); + JKRDvdFinder* finder = new (systemHeap, 0) JKRDvdFinder(name); + JKRFreeToSysHeap(name); + + if (finder->isAvailable() != true) { + delete finder; + return NULL; + } + + return finder; } /* 802B7BF4-802B7C20 .text findCacheBlock__12JKRFileCacheCFPCv */ -void JKRFileCache::findCacheBlock(const void*) const { - /* Nonmatching */ +JKRFileCache::CCacheBlock* JKRFileCache::findCacheBlock(const void* resource) const { + JSUListIterator iterator; + for (iterator = mCacheBlockList.getFirst(); iterator != mCacheBlockList.getEnd(); ++iterator) { + if (iterator->mMemoryPtr == resource) { + return iterator.getObject(); + } + } + + return NULL; } /* 802B7C20-802B7C4C .text findCacheBlock__12JKRFileCacheCFUl */ -void JKRFileCache::findCacheBlock(unsigned long) const { - /* Nonmatching */ +JKRFileCache::CCacheBlock* JKRFileCache::findCacheBlock(u32 fileID) const { + JSUListIterator iterator; + for (iterator = mCacheBlockList.getFirst(); iterator != mCacheBlockList.getEnd(); ++iterator) { + if (iterator->mFileId == fileID) { + return iterator.getObject(); + } + } + + return NULL; } /* 802B7C4C-802B7D58 .text findFile__12JKRFileCacheCFPcPCc */ -void JKRFileCache::findFile(char*, const char*) const { - /* Nonmatching */ +bool JKRFileCache::findFile(char* path, const char* fileName) const { + DVDDirectory dir; + DVDDirectoryEntry dirEntry; + + bool result = false; + u32 pathLength = strlen(path); + if (DVDOpenDir(path, &dir)) { + while (DVDReadDir(&dir, &dirEntry)) { + if (dirEntry.is_directory) { + char* endOfPath = path + pathLength; + *endOfPath = '/'; + strcpy(path + pathLength + 1, dirEntry.name); + result = findFile(path, fileName); + if (result) + break; + *endOfPath = '\0'; + } else { + result = (strcmp(fileName, dirEntry.name) == 0); + if (result) { + strcat(path, "/"); + strcat(path, fileName); + break; + } + } + } + + DVDCloseDir(&dir); + } + + return result; } /* 802B7D58-802B7E60 .text getDvdPathName__12JKRFileCacheCFPCc */ -void JKRFileCache::getDvdPathName(const char*) const { - /* Nonmatching */ +char* JKRFileCache::getDvdPathName(const char* path) const { + char* newPath; + if (path[0] == '/') { + u32 length = strlen(mRootPath) + strlen(path) + 2; + newPath = (char*)JKRAllocFromSysHeap(length, 1); + strcpy(newPath, mRootPath); + if (path[1]) { + if (mRootPath[1] == 0) { + strcat(newPath, path + 1); + } else { + strcat(newPath, path); + } + } + } else { + u32 length = strlen(mCurrentPath) + strlen(path) + 2; + newPath = (char*)JKRAllocFromSysHeap(length, 1); + strcpy(newPath, mCurrentPath); + strcat(newPath, path); + } + + convStrLower(newPath); + return newPath; } /* 802B7E60-802B7EA8 .text convStrLower__12JKRFileCacheCFPc */ -void JKRFileCache::convStrLower(char*) const { - /* Nonmatching */ +void JKRFileCache::convStrLower(char* buffer) const { + while (*buffer) { + *buffer++ = tolower(*buffer); + } } /* 802B7EA8-802B7F04 .text __ct__Q212JKRFileCache11CCacheBlockFUlUlPCv */ -JKRFileCache::CCacheBlock::CCacheBlock(unsigned long, unsigned long, const void*) { - /* Nonmatching */ -} - -/* 802B7F04-802B7F30 .text getFsResource__12JKRFileCacheFPCc */ -void JKRFileCache::getFsResource(const char*) { - /* Nonmatching */ -} - -/* 802B7F30-802B7F5C .text getNameResource__12JKRFileCacheFUlPCc */ -void JKRFileCache::getNameResource(unsigned long, const char*) { - /* Nonmatching */ -} - -/* 802B7F5C-802B7F88 .text readFsResource__12JKRFileCacheFPvUlPCc */ -void JKRFileCache::readFsResource(void*, unsigned long, const char*) { - /* Nonmatching */ -} - -/* 802B7F88-802B7FB4 .text readNameResource__12JKRFileCacheFPvUlUlPCc */ -void JKRFileCache::readNameResource(void*, unsigned long, unsigned long, const char*) { - /* Nonmatching */ +JKRFileCache::CCacheBlock::CCacheBlock(u32 fileId, u32 fileSize, const void* resource) : mCacheBlockLink(this) { + mReferenceCount = 1; + mFileId = fileId; + mFileSize = fileSize; + mMemoryPtr = (void*)resource; // todo: don't cast away const }