diff --git a/.gitignore b/.gitignore index fafae443d..03468a05c 100644 --- a/.gitignore +++ b/.gitignore @@ -279,7 +279,7 @@ ClientBin/ *.publishsettings orleans.codegen.cs -# Including strong name files can present a security risk +# Including strong name files can present a security risk # (https://github.com/github/gitignore/pull/2483#issue-259490424) #*.snk @@ -375,7 +375,7 @@ __pycache__/ # OpenCover UI analysis results OpenCover/ -# Azure Stream Analytics local run output +# Azure Stream Analytics local run output ASALocalRun/ # MSBuild Binary and Structured Log @@ -384,7 +384,7 @@ ASALocalRun/ # NVidia Nsight GPU debugger configuration file *.nvuser -# MFractors (Xamarin productivity tool) working folder +# MFractors (Xamarin productivity tool) working folder .mfractor/ *.out @@ -395,6 +395,7 @@ ExporterTest/ExporterTest.a ZAPDUtils/ZAPDUtils.a .vscode/ build/ +external/ ZAPDUtils/build/ ZAPD/BuildInfo.h diff --git a/BUILDING.md b/BUILDING.md index 82c26bff4..d37d7c0d6 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -1,5 +1,7 @@ # Building Ship of Harkinian +## Windows + 1. Install [Python](https://www.python.org/ftp/python/3.10.2/python-3.10.2-amd64.exe) 2. Install [Visual Studio 2022 Community Edition](https://visualstudio.microsoft.com/vs/community/) 2b. In the Visual Studio Installer, install `MSVC v142 - VS 2019 C++`. @@ -7,7 +9,7 @@ 5. Place one or more [compatible](#compatible-roms) roms in the `OTRExporter` directory with namings of your choice. 6. Run `OTRExporter/OTRExporter.sln`. 7. Switch the solution to `Release x64`. - 8. Build the solution. + 8. Build the solution. 9. Launching `OTRExporter/extract_assets.py` will generate an `oot.otr` archive file in `OTRExporter/oot.otr`. 10. Run `soh/soh.sln` 11. Switch the solution to `Release x86`. @@ -15,7 +17,36 @@ 13. Copy the `OTRExporter/oot.otr` archive file to `soh/Release`. 14. Launch `soh.exe`. -## Compatible Roms +## Linux + +```bash +# Clone the repo +git clone git@github.com:HarbourMasters/ShipWright.git +cd ShipWright +# Copy the baserom to the OTRExporter folder +cp OTRExporter +# Build the docker image +sudo docker build . -t soh +# Run the docker image with the working directory mounted to /soh +sudo docker run --rm -it -v $(pwd):/soh soh /bin/bash +``` +Inside the Docker container: +```bash +# Clone and build StormLib +git clone https://github.com/ladislav-zezula/StormLib external/StormLib +cmake -B external/StormLib/build -S external/StormLib +cmake --build external/StormLib/build +cp external/StormLib/build/libstorm.a external +cp /usr/local/lib/libGLEW.a external + +cd soh +# Extract the assets/Compile the exporter/Run the exporter +make setup -j$(nproc) +# Compile the code +make -j $(nproc) +``` + +# Compatible Roms ``` OOT_PAL_GC checksum 0x09465AC3 OOT_PAL_GC_DBG1 checksum 0x871E1C92 (debug non-master quest) diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..e981cf573 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,38 @@ + + +FROM ubuntu:21.04 as build + +ENV LANG C.UTF-8 +ARG DEBIAN_FRONTEND=noninteractive + +RUN dpkg --add-architecture i386 && \ + apt-get update && \ + apt-get upgrade -y && \ + apt-get install -y \ + binutils:i386 \ + gcc-10:i386 \ + g++-10:i386 \ + python3.10 \ + python \ + make \ + cmake \ + git \ + lld \ + libsdl2-dev:i386 \ + zlib1g-dev:i386 \ + libbz2-dev:i386 \ + libpng-dev:i386 \ + libgles2-mesa-dev && \ + ln -sf /usr/bin/python3.10 /usr/bin/python3 && \ + ln -s /usr/bin/gcc-10 /usr/bin/gcc && \ + ln -s /usr/bin/gcc-10 /usr/bin/cc && \ + ln -s /usr/bin/g++-10 /usr/bin/g++ && \ + ln -s /usr/bin/g++-10 /usr/bin/c++ + +RUN git clone https://github.com/Perlmint/glew-cmake.git && \ + cmake glew-cmake && \ + make -j$(nproc) && \ + make install ARCH64=false + +RUN mkdir /soh +WORKDIR /soh diff --git a/Jenkinsfile b/Jenkinsfile index fa68703b2..7f1132bae 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,29 +1,26 @@ pipeline { - - environment { - MSBUILD='C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\Msbuild\\Current\\Bin\\msbuild.exe' - CONFIG='Release' - OTRPLATFORM='x64' - PLATFORM='x86' - ZIP='C:\\Program Files\\7-Zip\\7z.exe' - PYTHON='C:\\Users\\jenkins\\AppData\\Local\\Programs\\Python\\Python310\\python.exe' - TOOLSET='v142' - EMAILTO='' - } - - agent { - label 'SoH-Builders' - } - + agent none + options { timestamps() - timeout(time: 15, unit: 'MINUTES') skipDefaultCheckout(true) } - + stages { - - stage ('Checkout') { + stage ('Build Windows') { + environment { + MSBUILD='C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\Msbuild\\Current\\Bin\\msbuild.exe' + CONFIG='Release' + OTRPLATFORM='x64' + PLATFORM='x86' + ZIP='C:\\Program Files\\7-Zip\\7z.exe' + PYTHON='C:\\Users\\jenkins\\AppData\\Local\\Programs\\Python\\Python310\\python.exe' + CMAKE='C:\\Program Files\\CMake\\bin\\cmake.exe' + TOOLSET='v142' + } + agent { + label "SoH-Builders" + } steps { checkout([ $class: 'GitSCM', @@ -32,68 +29,89 @@ pipeline { extensions: scm.extensions, userRemoteConfigs: scm.userRemoteConfigs ]) + + catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') { + bat """ + + "${env.MSBUILD}" ".\\OTRExporter\\OTRExporter.sln" -t:build -p:Configuration=${env.CONFIG};Platform=${env.OTRPLATFORM};PlatformToolset=${env.TOOLSET};RestorePackagesConfig=true /restore /nodeReuse:false /m + + xcopy "..\\..\\ZELOOTD.z64" "OTRExporter\\" + + cd "OTRExporter" + "${env.PYTHON}" ".\\extract_assets.py" + cd "..\\" + + "${env.MSBUILD}" ".\\soh\\soh.sln" -t:build -p:Configuration=${env.CONFIG};Platform=${env.PLATFORM};PlatformToolset=${env.TOOLSET} /nodeReuse:false /m + + cd OTRGui + mkdir build + cd build + + "${env.CMAKE}" .. + "${env.CMAKE}" --build . --config Release + + cd "..\\..\\" + + move "soh\\Release\\soh.exe" ".\\" + move "OTRGui\\build\\assets" ".\\" + move ".\\OTRExporter\\x64\\Release\\ZAPD.exe" ".\\assets\\extractor\\" + move ".\\OTRGui\\build\\Release\\OTRGui.exe" ".\\" + rename README.md readme.txt + + "${env.ZIP}" a soh.7z soh.exe OTRGui.exe assets readme.txt + + """ + archiveArtifacts artifacts: 'soh.7z', followSymlinks: false, onlyIfSuccessful: true + } + } + post { + always { + step([$class: 'WsCleanup']) // Clean workspace + } } } - - stage ('Build OTRExporter') { + stage ('Build Linux') { + agent { + label "SoH-Linux-Builders" + } steps { - bat """ - - "${env.MSBUILD}" ".\\OTRExporter\\OTRExporter.sln" -t:restore,build -p:Configuration=${env.CONFIG};Platform=${env.OTRPLATFORM};PlatformToolset=${env.TOOLSET};RestorePackagesConfig=true /nodeReuse:false - - """ + checkout([ + $class: 'GitSCM', + branches: scm.branches, + doGenerateSubmoduleConfigurations: scm.doGenerateSubmoduleConfigurations, + extensions: scm.extensions, + userRemoteConfigs: scm.userRemoteConfigs + ]) + catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') { + sh ''' + + cp ../../ZELOOTD.z64 OTRExporter/baserom_non_mq.z64 + docker build . -t soh + docker run --name sohcont -dit --rm -v $(pwd):/soh soh /bin/bash + cp ../../buildsoh.bash soh + docker exec sohcont soh/buildsoh.bash + + mkdir build + mv soh/soh.elf build/ + mv OTRGui/build/OTRGui build/ + mv OTRGui/build/assets build/ + mv ZAPDTR/ZAPD.out build/assets/extractor/ + mv README.md build/readme.txt + cd build + + 7z a soh-linux.7z soh.elf OTRGui assets readme.txt + mv soh-linux.7z ../ + + ''' + } + sh 'sudo docker container stop sohcont' + archiveArtifacts artifacts: 'soh-linux.7z', followSymlinks: false, onlyIfSuccessful: true } - } - - stage ('Extract assets') { - steps { - bat """ - - xcopy "..\\..\\ZELOOTD.z64" "OTRExporter\\" - - cd "OTRExporter" - "${env.PYTHON}" ".\\extract_assets.py" - cd "${env.WORKSPACE}" - - """ + post { + always { + step([$class: 'WsCleanup']) // Clean workspace + } } } - - stage ('Build SoH') { - steps { - bat """ - - "${env.MSBUILD}" ".\\soh\\soh.sln" -t:build -p:Configuration=${env.CONFIG};Platform=${env.PLATFORM};PlatformToolset=${env.TOOLSET} /nodeReuse:false - - """ - } - } - - stage ('Archive artifacts') { - steps { - bat """ - - "${env.ZIP}" a "soh.zip" ".\\soh\\Release\\soh.exe" - - """ - - archiveArtifacts allowEmptyArchive: false, - artifacts: 'soh.zip', - caseSensitive: true, - defaultExcludes: true, - fingerprint: false, - onlyIfSuccessful: true - } - } - } - - post { - always { - step([$class: 'Mailer', - notifyEveryUnstableBuild: true, - recipients: "${env.EMAILTO}", - sendToIndividuals: false]) - step([$class: 'WsCleanup']) // Clean workspace - } } } diff --git a/OTRExporter/OTRExporter/AnimationExporter.cpp b/OTRExporter/OTRExporter/AnimationExporter.cpp index 4f031b8a8..74fa8a7e6 100644 --- a/OTRExporter/OTRExporter/AnimationExporter.cpp +++ b/OTRExporter/OTRExporter/AnimationExporter.cpp @@ -49,12 +49,12 @@ void OTRExporter_Animation::Save(ZResource* res, const fs::path& outPath, Binary writer->Write((uint32_t)normalAnim->rotationValues.size()); - for (int i = 0; i < normalAnim->rotationValues.size(); i++) + for (size_t i = 0; i < normalAnim->rotationValues.size(); i++) writer->Write(normalAnim->rotationValues[i]); writer->Write((uint32_t)normalAnim->rotationIndices.size()); - for (int i = 0; i < normalAnim->rotationIndices.size(); i++) + for (size_t i = 0; i < normalAnim->rotationIndices.size(); i++) { writer->Write(normalAnim->rotationIndices[i].x); writer->Write(normalAnim->rotationIndices[i].y); diff --git a/OTRExporter/OTRExporter/ArrayExporter.cpp b/OTRExporter/OTRExporter/ArrayExporter.cpp index 2ddfd7b10..f83bfd87d 100644 --- a/OTRExporter/OTRExporter/ArrayExporter.cpp +++ b/OTRExporter/OTRExporter/ArrayExporter.cpp @@ -10,7 +10,7 @@ void OTRExporter_Array::Save(ZResource* res, const fs::path& outPath, BinaryWrit writer->Write((uint32_t)arr->resList[0]->GetResourceType()); writer->Write((uint32_t)arr->arrayCnt); - for (int i = 0; i < arr->arrayCnt; i++) + for (size_t i = 0; i < arr->arrayCnt; i++) { if (arr->resList[i]->GetResourceType() == ZResourceType::Vertex) { @@ -32,7 +32,7 @@ void OTRExporter_Array::Save(ZResource* res, const fs::path& outPath, BinaryWrit writer->Write((uint32_t)vec->scalarType); writer->Write((uint32_t)vec->dimensions); - for (int k = 0; k < vec->dimensions; k++) + for (size_t k = 0; k < vec->dimensions; k++) { // OTRTODO: Duplicate code here. Cleanup at a later date... switch (vec->scalarType) @@ -62,6 +62,8 @@ void OTRExporter_Array::Save(ZResource* res, const fs::path& outPath, BinaryWrit writer->Write(vec->scalars[k].scalarData.u64); break; // OTRTODO: ADD OTHER TYPES + default: + break; } } } @@ -98,6 +100,8 @@ void OTRExporter_Array::Save(ZResource* res, const fs::path& outPath, BinaryWrit writer->Write(scal->scalarData.u64); break; // OTRTODO: ADD OTHER TYPES + default: + break; } } } diff --git a/OTRExporter/OTRExporter/CutsceneExporter.cpp b/OTRExporter/OTRExporter/CutsceneExporter.cpp index 7cbf7f175..b52d73d8b 100644 --- a/OTRExporter/OTRExporter/CutsceneExporter.cpp +++ b/OTRExporter/OTRExporter/CutsceneExporter.cpp @@ -29,7 +29,7 @@ void OTRExporter_Cutscene::Save(ZResource* res, const fs::path& outPath, BinaryW for (auto& e : ((CutsceneCommandSetCameraPos*)cs->commands[i])->entries) { writer->Write(CMD_BBH(e->continueFlag, e->cameraRoll, e->nextPointFrame)); - writer->Write(CMD_F(e->viewAngle)); + writer->Write(e->viewAngle); writer->Write(CMD_HH(e->posX, e->posY)); writer->Write(CMD_HH(e->posZ, e->unused)); } @@ -46,7 +46,7 @@ void OTRExporter_Cutscene::Save(ZResource* res, const fs::path& outPath, BinaryW for (auto& e : ((CutsceneCommandSetCameraPos*)cs->commands[i])->entries) { writer->Write(CMD_BBH(e->continueFlag, e->cameraRoll, e->nextPointFrame)); - writer->Write(CMD_F(e->viewAngle)); + writer->Write(e->viewAngle); writer->Write(CMD_HH(e->posX, e->posY)); writer->Write(CMD_HH(e->posZ, e->unused)); } @@ -105,7 +105,7 @@ void OTRExporter_Cutscene::Save(ZResource* res, const fs::path& outPath, BinaryW for (auto& e : ((CutsceneCommandSetCameraPos*)cs->commands[i])->entries) { writer->Write(CMD_BBH(e->continueFlag, e->cameraRoll, e->nextPointFrame)); - writer->Write(CMD_F(e->viewAngle)); + writer->Write(e->viewAngle); writer->Write(CMD_HH(e->posX, e->posY)); writer->Write(CMD_HH(e->posZ, e->unused)); } @@ -122,7 +122,7 @@ void OTRExporter_Cutscene::Save(ZResource* res, const fs::path& outPath, BinaryW for (auto& e : ((CutsceneCommandSetCameraPos*)cs->commands[i])->entries) { writer->Write(CMD_BBH(e->continueFlag, e->cameraRoll, e->nextPointFrame)); - writer->Write(CMD_F(e->viewAngle)); + writer->Write(e->viewAngle); writer->Write(CMD_HH(e->posX, e->posY)); writer->Write(CMD_HH(e->posZ, e->unused)); } diff --git a/OTRExporter/OTRExporter/DisplayListExporter.cpp b/OTRExporter/OTRExporter/DisplayListExporter.cpp index 1fe7cb44a..d03a06333 100644 --- a/OTRExporter/OTRExporter/DisplayListExporter.cpp +++ b/OTRExporter/OTRExporter/DisplayListExporter.cpp @@ -29,20 +29,6 @@ Ab1, Ad1)) \ } -typedef int32_t Mtx_t[4][4]; - -typedef union Mtx -{ - //_Alignas(8) - Mtx_t m; - int32_t l[16]; - struct - { - int16_t i[16]; - uint16_t f[16]; - }; -} Mtx; - #define gsSPBranchLessZraw2(dl, vtx, zval) \ { _SHIFTL(G_BRANCH_Z,24,8)|_SHIFTL((vtx)*5,12,12)|_SHIFTL((vtx)*2,0,12),\ (unsigned int)(zval), } @@ -71,7 +57,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina // DEBUG: Write in a marker Declaration* dbgDecl = dList->parent->GetDeclaration(dList->GetRawDataIndex()); - std::string dbgName = StringHelper::Sprintf("%s\\%s", GetParentFolderName(res).c_str(), dbgDecl->varName.c_str()); + std::string dbgName = StringHelper::Sprintf("%s/%s", GetParentFolderName(res).c_str(), dbgDecl->varName.c_str()); uint64_t hash = CRC64(dbgName.c_str()); writer->Write((uint32_t)(G_MARKER << 24)); writer->Write((uint32_t)0xBEEFBEEF); @@ -81,7 +67,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina auto dlStart = std::chrono::steady_clock::now(); //for (auto data : dList->instructions) - for (int dataIdx = 0; dataIdx < dList->instructions.size(); dataIdx++) + for (size_t dataIdx = 0; dataIdx < dList->instructions.size(); dataIdx++) { auto data = dList->instructions[dataIdx]; uint32_t word0 = 0; @@ -216,7 +202,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina pp ^= G_MTX_PUSH; - mm = (mm & 0x0FFFFFFF) + 0xF0000000; + mm = (mm & 0x0FFFFFFF) + 1; Gfx value = gsSPMatrix(mm, pp); word0 = value.words.w0; @@ -243,7 +229,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina if (mtxDecl != nullptr) { - std::string vName = StringHelper::Sprintf("%s\\%s", (GetParentFolderName(res).c_str()), mtxDecl->varName.c_str()); + std::string vName = StringHelper::Sprintf("%s/%s", (GetParentFolderName(res).c_str()), mtxDecl->varName.c_str()); uint64_t hash = CRC64(vName.c_str()); @@ -347,7 +333,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina if (dListDecl != nullptr) { - std::string vName = StringHelper::Sprintf("%s\\%s", (GetParentFolderName(res).c_str()), dListDecl->varName.c_str()); + std::string vName = StringHelper::Sprintf("%s/%s", (GetParentFolderName(res).c_str()), dListDecl->varName.c_str()); uint64_t hash = CRC64(vName.c_str()); @@ -370,7 +356,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina //std::string fName = StringHelper::Sprintf("%s\\%s", GetParentFolderName(res).c_str(), dListDecl2->varName.c_str()); std::string fName = OTRExporter_DisplayList::GetPathToRes(res, dListDecl2->varName.c_str()); - if (files.find(fName) == files.end() && !File::Exists("Extract\\" + fName)) + if (files.find(fName) == files.end() && !File::Exists("Extract/" + fName)) { MemoryStream* dlStream = new MemoryStream(); BinaryWriter dlWriter = BinaryWriter(dlStream); @@ -383,7 +369,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina #endif if (Globals::Instance->fileMode != ZFileMode::ExtractDirectory) - File::WriteAllBytes("Extract\\" + fName, dlStream->ToVector()); + File::WriteAllBytes("Extract/" + fName, dlStream->ToVector()); else files[fName] = dlStream->ToVector(); @@ -411,7 +397,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina Gfx value; - u32 dListVal = (data & 0x0FFFFFFF) + 0xF0000000; + u32 dListVal = (data & 0x0FFFFFFF) + 1; if (pp != 0) value = gsSPBranchList(dListVal); @@ -444,7 +430,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina if (dListDecl != nullptr) { - std::string vName = StringHelper::Sprintf("%s\\%s", (GetParentFolderName(res).c_str()), dListDecl->varName.c_str()); + std::string vName = StringHelper::Sprintf("%s/%s", (GetParentFolderName(res).c_str()), dListDecl->varName.c_str()); uint64_t hash = CRC64(vName.c_str()); @@ -467,7 +453,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina //std::string fName = StringHelper::Sprintf("%s\\%s", GetParentFolderName(res).c_str(), dListDecl2->varName.c_str()); std::string fName = OTRExporter_DisplayList::GetPathToRes(res, dListDecl2->varName.c_str()); - if (files.find(fName) == files.end() && !File::Exists("Extract\\" + fName)) + if (files.find(fName) == files.end() && !File::Exists("Extract/" + fName)) { MemoryStream* dlStream = new MemoryStream(); BinaryWriter dlWriter = BinaryWriter(dlStream); @@ -475,7 +461,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina Save(dList->otherDLists[i], outPath, &dlWriter); if (Globals::Instance->fileMode != ZFileMode::ExtractDirectory) - File::WriteAllBytes("Extract\\" + fName, dlStream->ToVector()); + File::WriteAllBytes("Extract/" + fName, dlStream->ToVector()); else files[fName] = dlStream->ToVector(); } @@ -533,7 +519,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina int32_t bb = ((data & 0x0000FF0000000000ULL) >> 40) / 2; int32_t cc = ((data & 0x000000FF00000000ULL) >> 32) / 2; int32_t dd = ((data & 0x000000000000FFULL)) / 2; - + Gfx test = gsSP1Quadrangle(aa, bb, cc, dd, 0); word0 = test.words.w0; word1 = test.words.w1; @@ -689,7 +675,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina uint32_t fmt = (__ & 0xE0) >> 5; uint32_t siz = (__ & 0x18) >> 3; - Gfx value = gsDPSetTextureImage(fmt, siz, www + 1, (seg & 0x0FFFFFFF) + 0xF0000000); + Gfx value = gsDPSetTextureImage(fmt, siz, www + 1, (seg & 0x0FFFFFFF) + 1); word0 = value.words.w0; word1 = value.words.w1; @@ -721,7 +707,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina ZFile* assocFile = Globals::Instance->GetSegment(GETSEGNUM(seg), res->parent->workerID); std::string assocFileName = assocFile->GetName(); std::string fName = ""; - + if (GETSEGNUM(seg) == SEGMENT_SCENE || GETSEGNUM(seg) == SEGMENT_ROOM) fName = GetPathToRes(res, texName.c_str()); else @@ -753,7 +739,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina Gfx value = gsSPVertex(data & 0xFFFFFFFF, nn, ((aa >> 1) - nn)); word0 = value.words.w0; - word1 = value.words.w1 | 0xF0000000; + word1 = value.words.w1 | 1; } else { @@ -790,7 +776,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina word0 = hash >> 32; word1 = hash & 0xFFFFFFFF; - if (files.find(fName) == files.end() && !File::Exists("Extract\\" + fName)) + if (files.find(fName) == files.end() && !File::Exists("Extract/" + fName)) { // Write vertices to file MemoryStream* vtxStream = new MemoryStream(); @@ -800,7 +786,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina auto split = StringHelper::Split(vtxDecl->text, "\n"); - for (int i = 0; i < split.size(); i++) + for (size_t i = 0; i < split.size(); i++) { std::string line = split[i]; @@ -842,7 +828,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina } if (Globals::Instance->fileMode != ZFileMode::ExtractDirectory) - File::WriteAllBytes("Extract\\" + fName, vtxStream->ToVector()); + File::WriteAllBytes("Extract/" + fName, vtxStream->ToVector()); else files[fName] = vtxStream->ToVector(); @@ -858,7 +844,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina } break; } - + writer->Write(word0); writer->Write(word1); } @@ -872,7 +858,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina std::string OTRExporter_DisplayList::GetPathToRes(ZResource* res, std::string varName) { std::string prefix = GetPrefix(res); - std::string fName = StringHelper::Sprintf("%s\\%s", GetParentFolderName(res).c_str(), varName.c_str()); + std::string fName = StringHelper::Sprintf("%s/%s", GetParentFolderName(res).c_str(), varName.c_str()); return fName; } @@ -886,7 +872,7 @@ std::string OTRExporter_DisplayList::GetParentFolderName(ZResource* res) { auto split = StringHelper::Split(oName, "_"); oName = ""; - for (int i = 0; i < split.size() - 1; i++) + for (size_t i = 0; i < split.size() - 1; i++) oName += split[i] + "_"; oName += "scene"; @@ -897,7 +883,7 @@ std::string OTRExporter_DisplayList::GetParentFolderName(ZResource* res) } if (prefix != "") - oName = prefix + "\\" + oName; + oName = prefix + "/" + oName; return oName; } diff --git a/OTRExporter/OTRExporter/Main.cpp b/OTRExporter/OTRExporter/Main.cpp index a58f94ae3..2ed9cb427 100644 --- a/OTRExporter/OTRExporter/Main.cpp +++ b/OTRExporter/OTRExporter/Main.cpp @@ -52,7 +52,7 @@ static void ExporterParseFileMode(const std::string& buildMode, ZFileMode& fileM for (auto item : lst) { auto fileData = File::ReadAllBytes(item); - otrArchive->AddFile(StringHelper::Split(item, "Extract\\")[1], (uintptr_t)fileData.data(), fileData.size()); + otrArchive->AddFile(StringHelper::Split(item, "Extract/")[1], (uintptr_t)fileData.data(), fileData.size()); } } } @@ -76,7 +76,7 @@ static void ExporterProgramEnd() for (auto item : lst) { auto fileData = File::ReadAllBytes(item); - otrArchive->AddFile(StringHelper::Split(item, "Extract\\")[1], (uintptr_t)fileData.data(), fileData.size()); + otrArchive->AddFile(StringHelper::Split(item, "Extract/")[1], (uintptr_t)fileData.data(), fileData.size()); } otrArchive->AddFile("Audiobank", (uintptr_t)Globals::Instance->GetBaseromFile("Audiobank").data(), Globals::Instance->GetBaseromFile("Audiobank").size()); @@ -117,7 +117,7 @@ static void ExporterFileBegin(ZFile* file) static void ExporterFileEnd(ZFile* file) { - int bp = 0; + // delete fileWriter; } static void ExporterResourceEnd(ZResource* res, BinaryWriter& writer) @@ -140,7 +140,7 @@ static void ExporterResourceEnd(ZResource* res, BinaryWriter& writer) { auto split = StringHelper::Split(oName, "_"); oName = ""; - for (int i = 0; i < split.size() - 1; i++) + for (size_t i = 0; i < split.size() - 1; i++) oName += split[i] + "_"; oName += "scene"; @@ -153,14 +153,14 @@ static void ExporterResourceEnd(ZResource* res, BinaryWriter& writer) std::string fName = ""; if (prefix != "") - fName = StringHelper::Sprintf("%s\\%s\\%s", prefix.c_str(), oName.c_str(), rName.c_str()); + fName = StringHelper::Sprintf("%s/%s/%s", prefix.c_str(), oName.c_str(), rName.c_str()); else - fName = StringHelper::Sprintf("%s\\%s", oName.c_str(), rName.c_str()); + fName = StringHelper::Sprintf("%s/%s", oName.c_str(), rName.c_str()); if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory) files[fName] = strem->ToVector(); else - File::WriteAllBytes("Extract\\" + fName, strem->ToVector()); + File::WriteAllBytes("Extract/" + fName, strem->ToVector()); } auto end = std::chrono::steady_clock::now(); diff --git a/OTRExporter/OTRExporter/Makefile b/OTRExporter/OTRExporter/Makefile index 1c4e61bf2..954b183a3 100644 --- a/OTRExporter/OTRExporter/Makefile +++ b/OTRExporter/OTRExporter/Makefile @@ -39,13 +39,13 @@ D_FILES := $(O_FILES:%.o=%.d) LIB := OTRExporter.a INC_DIRS := $(addprefix -I, \ - ../../ZAPD/ZAPD \ - ../../ZAPD/lib/tinyxml2 \ - ../../ZAPD/lib/libgfxd \ - ../../ZAPD/ZAPDUtils \ - ../../OtrLib/otrlib \ - ../../OtrLib/otrlib/Lib/spdlog/include \ - ../../OtrLib/otrlib/Lib/Fast3D/U64 \ + ../../ZAPDTR/ZAPD \ + ../../ZAPDTR/lib/tinyxml2 \ + ../../ZAPDTR/lib/libgfxd \ + ../../ZAPDTR/ZAPDUtils \ + ../../libultraship/libultraship \ + ../../libultraship/libultraship/Lib/spdlog/include \ + ../../libultraship/libultraship/Lib/Fast3D/U64 \ ) # create build directories diff --git a/OTRExporter/OTRExporter/PathExporter.cpp b/OTRExporter/OTRExporter/PathExporter.cpp index de15789ab..75f6b723f 100644 --- a/OTRExporter/OTRExporter/PathExporter.cpp +++ b/OTRExporter/OTRExporter/PathExporter.cpp @@ -9,11 +9,11 @@ void OTRExporter_Path::Save(ZResource* res, const fs::path& outPath, BinaryWrite writer->Write((uint32_t)path->pathways.size()); - for (int k = 0; k < path->pathways.size(); k++) + for (size_t k = 0; k < path->pathways.size(); k++) { writer->Write((uint32_t)path->pathways[k].points.size()); - for (int i = 0; i < path->pathways[k].points.size(); i++) + for (size_t i = 0; i < path->pathways[k].points.size(); i++) { writer->Write(path->pathways[k].points[i].scalars[0].scalarData.s16); writer->Write(path->pathways[k].points[i].scalars[1].scalarData.s16); diff --git a/OTRExporter/OTRExporter/RoomExporter.cpp b/OTRExporter/OTRExporter/RoomExporter.cpp index 5b7ce4323..9a5704bbc 100644 --- a/OTRExporter/OTRExporter/RoomExporter.cpp +++ b/OTRExporter/OTRExporter/RoomExporter.cpp @@ -46,7 +46,7 @@ void OTRExporter_Room::Save(ZResource* res, const fs::path& outPath, BinaryWrite for (size_t i = 0; i < room->commands.size(); i++) { ZRoomCommand* cmd = room->commands[i]; - + writer->Write((uint32_t)cmd->cmdID); switch (cmd->cmdID) @@ -172,7 +172,7 @@ void OTRExporter_Room::Save(ZResource* res, const fs::path& outPath, BinaryWrite writer->Write((uint32_t)cmdCsCam->points.size()); - for (int i = 0; i < cmdCsCam->points.size(); i++) + for (size_t i = 0; i < cmdCsCam->points.size(); i++) { writer->Write(cmdCsCam->points[i].scalars[0].scalarData.s16); writer->Write(cmdCsCam->points[i].scalars[1].scalarData.s16); @@ -183,7 +183,7 @@ void OTRExporter_Room::Save(ZResource* res, const fs::path& outPath, BinaryWrite case RoomCommand::SetMesh: { SetMesh* cmdMesh = (SetMesh*)cmd; - + writer->Write((uint8_t)cmdMesh->data); // 0x01 writer->Write(cmdMesh->meshHeaderType); @@ -207,12 +207,12 @@ void OTRExporter_Room::Save(ZResource* res, const fs::path& outPath, BinaryWrite Declaration* dListDeclXlu = poly->parent->GetDeclaration(GETSEGOFFSET(test->xlu)); if (test->opa != 0) - writer->Write(StringHelper::Sprintf("%s\\%s", OTRExporter_DisplayList::GetParentFolderName(res).c_str(), dListDeclOpa->varName.c_str())); + writer->Write(StringHelper::Sprintf("%s/%s", OTRExporter_DisplayList::GetParentFolderName(res).c_str(), dListDeclOpa->varName.c_str())); else writer->Write(""); - + if (test->xlu != 0) - writer->Write(StringHelper::Sprintf("%s\\%s", OTRExporter_DisplayList::GetParentFolderName(res).c_str(), dListDeclXlu->varName.c_str())); + writer->Write(StringHelper::Sprintf("%s/%s", OTRExporter_DisplayList::GetParentFolderName(res).c_str(), dListDeclXlu->varName.c_str())); else writer->Write(""); @@ -228,7 +228,7 @@ void OTRExporter_Room::Save(ZResource* res, const fs::path& outPath, BinaryWrite Declaration* bgDecl = poly->parent->GetDeclarationRanged(GETSEGOFFSET(poly->multiList[i].source)); writer->Write(OTRExporter_DisplayList::GetPathToRes(poly->multiList[i].sourceBackground, bgDecl->varName)); - + writer->Write(poly->multiList[i].unk_0C); writer->Write(poly->multiList[i].tlut); writer->Write(poly->multiList[i].width); @@ -338,7 +338,7 @@ void OTRExporter_Room::Save(ZResource* res, const fs::path& outPath, BinaryWrite for (size_t i = 0;i < cmdRoom->romfile->numRooms; i++) { - //std::string roomName = StringHelper::Sprintf("%s\\%s_room_%i", (StringHelper::Split(room->GetName(), "_")[0] + "_scene").c_str(), StringHelper::Split(room->GetName(), "_scene")[0].c_str(), i); + //std::string roomName = StringHelper::Sprintf("%s/%s_room_%i", (StringHelper::Split(room->GetName(), "_")[0] + "_scene").c_str(), StringHelper::Split(room->GetName(), "_scene")[0].c_str(), i); std::string roomName = OTRExporter_DisplayList::GetPathToRes(room, StringHelper::Sprintf("%s_room_%i", StringHelper::Split(room->GetName(), "_scene")[0].c_str(), i)); writer->Write(roomName); writer->Write(cmdRoom->romfile->rooms[i].virtualAddressStart); @@ -383,7 +383,7 @@ void OTRExporter_Room::Save(ZResource* res, const fs::path& outPath, BinaryWrite uint32_t baseStreamEnd = writer->GetStream().get()->GetLength(); writer->Write((uint32_t)cmdStartPos->actors.size()); // 0x01 - + for (const ActorSpawnEntry& entry : cmdStartPos->actors) { writer->Write(entry.actorNum); @@ -441,7 +441,7 @@ void OTRExporter_Room::Save(ZResource* res, const fs::path& outPath, BinaryWrite case RoomCommand::SetCutscenes: { SetCutscenes* cmdSetCutscenes = (SetCutscenes*)cmd; - + std::string listName; Globals::Instance->GetSegmentedPtrName(cmdSetCutscenes->cmdArg2, room->parent, "CutsceneData", listName, res->parent->workerID); std::string fName = OTRExporter_DisplayList::GetPathToRes(room, listName); @@ -452,9 +452,9 @@ void OTRExporter_Room::Save(ZResource* res, const fs::path& outPath, BinaryWrite BinaryWriter csWriter = BinaryWriter(csStream); OTRExporter_Cutscene cs; cs.Save(cmdSetCutscenes->cutscenes[0], "", &csWriter); - + if (Globals::Instance->fileMode != ZFileMode::ExtractDirectory) - File::WriteAllBytes("Extract\\" + fName, csStream->ToVector()); + File::WriteAllBytes("Extract/" + fName, csStream->ToVector()); else files[fName] = csStream->ToVector(); @@ -468,7 +468,7 @@ void OTRExporter_Room::Save(ZResource* res, const fs::path& outPath, BinaryWrite writer->Write((uint32_t)cmdSetPathways->pathwayList.pathways.size()); - for (int i = 0; i < cmdSetPathways->pathwayList.pathways.size(); i++) + for (size_t i = 0; i < cmdSetPathways->pathwayList.pathways.size(); i++) { Declaration* decl = room->parent->GetDeclaration(GETSEGOFFSET(cmdSetPathways->pathwayList.pathways[i].listSegmentAddress)); //std::string path = StringHelper::Sprintf("%s\\%s", OTRExporter_DisplayList::GetParentFolderName(res).c_str(), decl->varName.c_str()); @@ -481,7 +481,7 @@ void OTRExporter_Room::Save(ZResource* res, const fs::path& outPath, BinaryWrite pathExp.Save(&cmdSetPathways->pathwayList, outPath, &pathWriter); if (Globals::Instance->fileMode != ZFileMode::ExtractDirectory) - File::WriteAllBytes("Extract\\" + path, pathStream->ToVector()); + File::WriteAllBytes("Extract/" + path, pathStream->ToVector()); else files[path] = pathStream->ToVector(); @@ -514,12 +514,12 @@ void OTRExporter_Room::WritePolyDList(BinaryWriter* writer, ZRoom* room, Polygon writer->Write(dlist->unk_06); [[fallthrough]]; default: - //writer->Write(StringHelper::Sprintf("%s\\%s", OTRExporter_DisplayList::GetParentFolderName(res).c_str(), dListDeclOpa->varName.c_str())); + //writer->Write(StringHelper::Sprintf("%s/%s", OTRExporter_DisplayList::GetParentFolderName(res).c_str(), dListDeclOpa->varName.c_str())); if (dlist->opaDList != nullptr) { auto opaDecl = room->parent->GetDeclaration(GETSEGOFFSET(dlist->opaDList->GetRawDataIndex())); - writer->Write(StringHelper::Sprintf("%s\\%s", OTRExporter_DisplayList::GetParentFolderName(room).c_str(), opaDecl->varName.c_str())); + writer->Write(StringHelper::Sprintf("%s/%s", OTRExporter_DisplayList::GetParentFolderName(room).c_str(), opaDecl->varName.c_str())); } else writer->Write(""); @@ -527,7 +527,7 @@ void OTRExporter_Room::WritePolyDList(BinaryWriter* writer, ZRoom* room, Polygon if (dlist->xluDList != nullptr) { auto xluDecl = room->parent->GetDeclaration(GETSEGOFFSET(dlist->xluDList->GetRawDataIndex())); - writer->Write(StringHelper::Sprintf("%s\\%s", OTRExporter_DisplayList::GetParentFolderName(room).c_str(), xluDecl->varName.c_str())); + writer->Write(StringHelper::Sprintf("%s/%s", OTRExporter_DisplayList::GetParentFolderName(room).c_str(), xluDecl->varName.c_str())); } else writer->Write(""); diff --git a/OTRExporter/OTRExporter/TextExporter.cpp b/OTRExporter/OTRExporter/TextExporter.cpp index 19bc0ced1..5819b9b33 100644 --- a/OTRExporter/OTRExporter/TextExporter.cpp +++ b/OTRExporter/OTRExporter/TextExporter.cpp @@ -8,8 +8,8 @@ void OTRExporter_Text::Save(ZResource* res, const fs::path& outPath, BinaryWrite WriteHeader(txt, outPath, writer, Ship::ResourceType::Text); writer->Write((uint32_t)txt->messages.size()); - - for (int i = 0; i < txt->messages.size(); i++) + + for (size_t i = 0; i < txt->messages.size(); i++) { writer->Write(txt->messages[i].id); writer->Write(txt->messages[i].textboxType); diff --git a/OTRExporter/OTRExporter/VersionInfo.cpp b/OTRExporter/OTRExporter/VersionInfo.cpp index 9b684d22b..0a2004673 100644 --- a/OTRExporter/OTRExporter/VersionInfo.cpp +++ b/OTRExporter/OTRExporter/VersionInfo.cpp @@ -5,21 +5,23 @@ std::map resourceVersions; void InitVersionInfo() { - resourceVersions[Ship::ResourceType::Animation] = 0; - resourceVersions[Ship::ResourceType::Model] = 0; - resourceVersions[Ship::ResourceType::Texture] = 0; - resourceVersions[Ship::ResourceType::Material] = 0; - resourceVersions[Ship::ResourceType::PlayerAnimation] = 0; - resourceVersions[Ship::ResourceType::DisplayList] = 0; - resourceVersions[Ship::ResourceType::Room] = 0; - resourceVersions[Ship::ResourceType::CollisionHeader] = 0; - resourceVersions[Ship::ResourceType::Skeleton] = 0; - resourceVersions[Ship::ResourceType::SkeletonLimb] = 0; - resourceVersions[Ship::ResourceType::Matrix] = 0; - resourceVersions[Ship::ResourceType::Path] = 0; - resourceVersions[Ship::ResourceType::Vertex] = 0; - resourceVersions[Ship::ResourceType::Cutscene] = 0; - resourceVersions[Ship::ResourceType::Array] = 0; - resourceVersions[Ship::ResourceType::Text] = 0; - resourceVersions[Ship::ResourceType::Blob] = 0; + resourceVersions = { + { Ship::ResourceType::Animation, 0 }, + { Ship::ResourceType::Model, 0 }, + { Ship::ResourceType::Texture, 0 }, + { Ship::ResourceType::Material, 0 }, + { Ship::ResourceType::PlayerAnimation, 0 }, + { Ship::ResourceType::DisplayList, 0 }, + { Ship::ResourceType::Room, 0 }, + { Ship::ResourceType::CollisionHeader, 0 }, + { Ship::ResourceType::Skeleton, 0 }, + { Ship::ResourceType::SkeletonLimb, 0 }, + { Ship::ResourceType::Matrix, 0 }, + { Ship::ResourceType::Path, 0 }, + { Ship::ResourceType::Vertex, 0 }, + { Ship::ResourceType::Cutscene, 0 }, + { Ship::ResourceType::Array, 0 }, + { Ship::ResourceType::Text, 0 }, + { Ship::ResourceType::Blob, 0 }, + }; } \ No newline at end of file diff --git a/OTRExporter/assets/ship_of_harkinian/fonts/Fipps-Regular.otf b/OTRExporter/assets/ship_of_harkinian/fonts/Fipps-Regular.otf new file mode 100644 index 000000000..9334dad59 Binary files /dev/null and b/OTRExporter/assets/ship_of_harkinian/fonts/Fipps-Regular.otf differ diff --git a/OTRExporter/assets/ship_of_harkinian/fonts/PressStart2P-Regular.ttf b/OTRExporter/assets/ship_of_harkinian/fonts/PressStart2P-Regular.ttf new file mode 100644 index 000000000..2442affbf Binary files /dev/null and b/OTRExporter/assets/ship_of_harkinian/fonts/PressStart2P-Regular.ttf differ diff --git a/OTRExporter/extract_assets.py b/OTRExporter/extract_assets.py index e33b65f0e..67b4ca6e4 100755 --- a/OTRExporter/extract_assets.py +++ b/OTRExporter/extract_assets.py @@ -1,51 +1,15 @@ #!/usr/bin/env python3 -# How to use: -# Place a rom in this directory then run the script. -# If you are using multiple roms, the script will let you choose one. -# To choose with a commandline argument: -# Python3 extract_assets.py -# Invalid input results in the first rom being selected - -import json, os, signal, time, sys, shutil, glob -from multiprocessing import Pool, cpu_count, Event, Manager, ProcessError -from enum import Enum +import os, sys, shutil import shutil - -romVer = "..\\soh\\baserom_non_mq.z64" -roms = []; -checksums = ["", "", ""]; - -class Checksums(Enum): - OOT_NTSC_10 = "EC7011B7" - OOT_NTSC_11 = "D43DA81F" - OOT_NTSC_12 = "693BA2AE" - OOT_PAL_10 = "B044B569" - OOT_PAL_11 = "B2055FBD" - OOT_NTSC_JP_GC_CE = "F7F52DB8" - OOT_NTSC_JP_GC = "F611F4BA" - OOT_NTSC_US_GC = "F3DD35BA" - OOT_PAL_GC = "09465AC3" - OOT_NTSC_JP_MQ = "F43B45BA" - OOT_NTSC_US_MQ = "F034001A" - OOT_PAL_MQ = "1D4136F3" - OOT_PAL_GC_DBG1 = "871E1C92" - OOT_PAL_GC_DBG2 = "87121EFE" - OOT_PAL_GC_MQ_DBG = "917D18F6" - OOT_IQUE_TW = "3D81FB3E" - OOT_IQUE_CN = "B1E1E07B" - OOT_UNKNOWN = "FFFFFFFF" - -CompatibleChecksums = [ - Checksums.OOT_PAL_GC, - Checksums.OOT_PAL_GC_DBG1 -] +from rom_info import Z64Rom +import rom_chooser def BuildOTR(xmlPath, rom): shutil.copytree("assets", "Extract/assets") - execStr = "x64\\Release\\ZAPD.exe" if sys.platform == "win32" else "../ZAPD/ZAPD.out" - execStr += " ed -i %s -b %s -fl CFG\\filelists -o placeholder -osf placeholder -gsf 1 -rconf CFG/Config.xml -se OTR" % (xmlPath, rom) + execStr = "x64\\Release\\ZAPD.exe" if sys.platform == "win32" else "../ZAPDTR/ZAPD.out" + execStr += " ed -i %s -b %s -fl CFG/filelists -o placeholder -osf placeholder -gsf 1 -rconf CFG/Config.xml -se OTR" % (xmlPath, rom) print(execStr) exitValue = os.system(execStr) @@ -55,95 +19,14 @@ def BuildOTR(xmlPath, rom): print("Aborting...", file=os.sys.stderr) print("\n") -def checkChecksum(rom): - r = open(rom, "rb") - r.seek(16) - bytes = r.read(4).hex().upper() - r.close() - - for checksum in Checksums: - if (checksum.value == bytes): - - for compat in CompatibleChecksums: - if (checksum.name == compat.name): - print("Compatible rom found!") - return checksum - print("Valid oot rom found. However, not compatible with SoH.") - print("Compatible roms:") - for compat in CompatibleChecksums: - print(compat.name+" | 0x"+compat.value) - sys.exit(1) - - print("Wrong rom! No valid checksum found") - sys.exit(1) - def main(): - - romToUse = ""; - - for file in glob.glob("*.z64"): - roms.append(file) - - if not (roms): - print("Error: No roms located, place one in the OTRExporter directory", file=os.sys.stderr) - sys.exit(1) - - if (len(roms) > 1): - - # If commandline args exist - if (len(sys.argv) > 1): - try: - if ((int(sys.argv[1]) - 1) < 1): - romToUse = roms[0] - - elif ((int(sys.argv[1]) - 1) > len(roms)): - romToUse = roms[len(roms) - 1] - - else: - romToUse = roms[int(sys.argv[1]) - 1] - except: - romToUse = roms[0] - - # No commandline args, select rom using user input - else: - - print(str(len(roms))+" roms found, please select one by pressing 1-"+str(len(roms))) - - count = 1 - for list in range(len(roms)): - print(str(count)+". "+roms[list]) - count += 1 - - while(1): - try: - selection = int(input()) - except: - print("Bad input. Try again with the number keys.") - continue - - if (selection < 1 or selection > len(roms)): - print("Bad input. Try again.") - continue - - else: break - - romToUse = roms[selection - 1] - - else: - romToUse = roms[0] - - match checkChecksum(romToUse): - case Checksums.OOT_PAL_GC: - xmlVer = "GC_NMQ_PAL_F" - case Checksums.OOT_PAL_GC_DBG1: - xmlVer = "GC_NMQ_D" - case _: # default case - xmlVer = "GC_MQ_D" + rom_path = rom_chooser.chooseROM() + rom = Z64Rom(rom_path) if (os.path.exists("Extract")): shutil.rmtree("Extract") - - BuildOTR("..\\soh\\assets\\xml\\" + xmlVer + "\\", romToUse) + + BuildOTR("../soh/assets/xml/" + rom.version.xml_ver + "/", rom_path) if __name__ == "__main__": main() diff --git a/OTRExporter/extract_assets_old.py b/OTRExporter/extract_assets_old.py deleted file mode 100644 index 2922bbf06..000000000 --- a/OTRExporter/extract_assets_old.py +++ /dev/null @@ -1,125 +0,0 @@ -#!/usr/bin/env python3 - -import argparse, json, os, signal, time, sys, shutil -from multiprocessing import Pool, cpu_count, Event, Manager, ProcessError -import shutil - -def SignalHandler(sig, frame): - print(f'Signal {sig} received. Aborting...') - mainAbort.set() - # Don't exit immediately to update the extracted assets file. - -def BuildOTR(): - shutil.copyfile("baserom/Audiobank", "Extract/Audiobank") - shutil.copyfile("baserom/Audioseq", "Extract/Audioseq") - shutil.copyfile("baserom/Audiotable", "Extract/Audiotable") - - shutil.copytree("assets", "Extract/assets") - - execStr = "x64\\Release\\ZAPD.exe" if sys.platform == "win32" else "../ZAPD/ZAPD.out" - - execStr += " botr -se OTR" - - print(execStr) - exitValue = os.system(execStr) - if exitValue != 0: - print("\n") - print("Error when building the OTR file...", file=os.sys.stderr) - print("Aborting...", file=os.sys.stderr) - print("\n") - -def ExtractFile(xmlPath, outputPath, outputSourcePath): - execStr = "x64\\Release\\ZAPD.exe" if sys.platform == "win32" else "../ZAPD/ZAPD.out" - execStr += " e -eh -i %s -b baserom/ -o %s -osf %s -gsf 1 -rconf CFG/Config.xml -se OTR" % (xmlPath, outputPath, outputSourcePath) - - if "overlays" in xmlPath: - execStr += " --static" - - print(execStr) - exitValue = os.system(execStr) - #exitValue = 0 - if exitValue != 0: - print("\n") - print("Error when extracting from file " + xmlPath, file=os.sys.stderr) - print("Aborting...", file=os.sys.stderr) - print("\n") - -def ExtractFunc(fullPath): - *pathList, xmlName = fullPath.split(os.sep) - objectName = os.path.splitext(xmlName)[0] - - outPath = os.path.join("..\\soh\\assets\\", *pathList[5:], objectName) - os.makedirs(outPath, exist_ok=True) - outSourcePath = outPath - - ExtractFile(fullPath, outPath, outSourcePath) - -def initializeWorker(abort, test): - global globalAbort - globalAbort = abort - - -def main(): - parser = argparse.ArgumentParser(description="baserom asset extractor") - parser.add_argument("-s", "--single", help="asset path relative to assets/, e.g. objects/gameplay_keep") - parser.add_argument("-f", "--force", help="Force the extraction of every xml instead of checking the touched ones.", action="store_true") - parser.add_argument("-u", "--unaccounted", help="Enables ZAPD unaccounted detector warning system.", action="store_true") - parser.add_argument("-v", "--version", help="Sets game version.") - args = parser.parse_args() - - global mainAbort - mainAbort = Event() - manager = Manager() - signal.signal(signal.SIGINT, SignalHandler) - - extractedAssetsTracker = manager.dict() - - xmlVer = "GC_NMQ_D" - - if (args.version == "gc_pal_nmpq"): - xmlVer = "GC_NMQ_PAL_F" - elif (args.version == "dbg_mq"): - xmlVer = "GC_MQ_D" - - asset_path = args.single - if asset_path is not None: - fullPath = os.path.join("..\\soh\\assets", "xml", asset_path + ".xml") - if not os.path.exists(fullPath): - print(f"Error. File {fullPath} doesn't exists.", file=os.sys.stderr) - exit(1) - - ExtractFunc(fullPath) - else: - extract_text_path = "assets/text/message_data.h" - if os.path.isfile(extract_text_path): - extract_text_path = None - extract_staff_text_path = "assets/text/message_data_staff.h" - if os.path.isfile(extract_staff_text_path): - extract_staff_text_path = None - - xmlFiles = [] - for currentPath, _, files in os.walk(os.path.join("..\\soh\\assets\\xml\\", xmlVer)): - for file in files: - fullPath = os.path.join(currentPath, file) - if file.endswith(".xml"): - xmlFiles.append(fullPath) - - try: - numCores = 2 - print("Extracting assets with " + str(numCores) + " CPU cores.") - with Pool(numCores, initializer=initializeWorker, initargs=(mainAbort, 0)) as p: - p.map(ExtractFunc, xmlFiles) - except Exception as e: - print("Warning: Multiprocessing exception ocurred.", file=os.sys.stderr) - print("Disabling mutliprocessing.", file=os.sys.stderr) - - initializeWorker(mainAbort, 0) - for singlePath in xmlFiles: - ExtractFunc(singlePath) - - - BuildOTR() - shutil.rmtree("Extract") - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/OTRExporter/extract_baserom.py b/OTRExporter/extract_baserom.py new file mode 100644 index 000000000..f387df57a --- /dev/null +++ b/OTRExporter/extract_baserom.py @@ -0,0 +1,53 @@ +#!/usr/bin/python3 + +import os +import sys +import struct +from multiprocessing import Pool, cpu_count +from rom_info import Z64Rom +import rom_chooser + + +rom = None + +def initialize_worker(input_rom): + global rom + rom = input_rom + +def ExtractFunc(i): + + dma_file = rom.getDmaEntryByIndex(i) + dma_data = rom.readDmaEntry(dma_file) + + filename = '../soh/baserom/' + rom.version.file_table[i] + print('extracting ' + filename + " (0x%08X, 0x%08X)" % (dma_file.virtStart, dma_file.virtEnd)) + + try: + with open(filename, 'wb') as f: + f.write(dma_data) + except IOError: + print('failed to write file ' + filename) + + # TODO: handle this better + if dma_file.compressed: + os.system('tools/yaz0 -d ' + filename + ' ' + filename) + +##################################################################### + +def main(): + try: + os.mkdir('../soh/baserom') + except: + pass + + rom_path = rom_chooser.chooseROM() + input_rom = Z64Rom(rom_path) + + # extract files + num_cores = cpu_count() + print("Extracting baserom with " + str(num_cores) + " CPU cores.") + with Pool(num_cores, initialize_worker, (input_rom,)) as p: + p.map(ExtractFunc, range(len(input_rom.version.file_table))) + +if __name__ == "__main__": + main() diff --git a/OTRExporter/extract_baserom_debug.py b/OTRExporter/extract_baserom_debug.py deleted file mode 100644 index a3eb83a8f..000000000 --- a/OTRExporter/extract_baserom_debug.py +++ /dev/null @@ -1,1608 +0,0 @@ -#!/usr/bin/python3 - -import os -import sys -import struct -from multiprocessing import Pool, cpu_count - - -ROM_FILE_NAME = 'baserom_non_mq.z64' -FILE_TABLE_OFFSET = 0x12F70 - -FILE_NAMES = [ - 'makerom', - 'boot', - 'dmadata', - 'Audiobank', - 'Audioseq', - 'Audiotable', - 'link_animetion', - 'icon_item_static', - 'icon_item_24_static', - 'icon_item_field_static', - 'icon_item_dungeon_static', - 'icon_item_gameover_static', - 'icon_item_nes_static', - 'icon_item_ger_static', - 'icon_item_fra_static', - 'item_name_static', - 'map_name_static', - 'do_action_static', - 'message_static', - 'message_texture_static', - 'nes_font_static', - 'nes_message_data_static', - 'ger_message_data_static', - 'fra_message_data_static', - 'staff_message_data_static', - 'map_grand_static', - 'map_i_static', - 'map_48x85_static', - 'code', - 'ovl_title', - 'ovl_select', - 'ovl_opening', - 'ovl_file_choose', - 'ovl_kaleido_scope', - 'ovl_player_actor', - 'ovl_map_mark_data', - 'ovl_En_Test', - 'ovl_Arms_Hook', - 'ovl_Arrow_Fire', - 'ovl_Arrow_Ice', - 'ovl_Arrow_Light', - 'ovl_Bg_Bdan_Objects', - 'ovl_Bg_Bdan_Switch', - 'ovl_Bg_Bom_Guard', - 'ovl_Bg_Bombwall', - 'ovl_Bg_Bowl_Wall', - 'ovl_Bg_Breakwall', - 'ovl_Bg_Ddan_Jd', - 'ovl_Bg_Ddan_Kd', - 'ovl_Bg_Dodoago', - 'ovl_Bg_Dy_Yoseizo', - 'ovl_Bg_Ganon_Otyuka', - 'ovl_Bg_Gate_Shutter', - 'ovl_Bg_Gjyo_Bridge', - 'ovl_Bg_Gnd_Darkmeiro', - 'ovl_Bg_Gnd_Firemeiro', - 'ovl_Bg_Gnd_Iceblock', - 'ovl_Bg_Gnd_Nisekabe', - 'ovl_Bg_Gnd_Soulmeiro', - 'ovl_Bg_Haka', - 'ovl_Bg_Haka_Gate', - 'ovl_Bg_Haka_Huta', - 'ovl_Bg_Haka_Megane', - 'ovl_Bg_Haka_MeganeBG', - 'ovl_Bg_Haka_Sgami', - 'ovl_Bg_Haka_Ship', - 'ovl_Bg_Haka_Trap', - 'ovl_Bg_Haka_Tubo', - 'ovl_Bg_Haka_Water', - 'ovl_Bg_Haka_Zou', - 'ovl_Bg_Heavy_Block', - 'ovl_Bg_Hidan_Curtain', - 'ovl_Bg_Hidan_Dalm', - 'ovl_Bg_Hidan_Firewall', - 'ovl_Bg_Hidan_Fslift', - 'ovl_Bg_Hidan_Fwbig', - 'ovl_Bg_Hidan_Hamstep', - 'ovl_Bg_Hidan_Hrock', - 'ovl_Bg_Hidan_Kousi', - 'ovl_Bg_Hidan_Kowarerukabe', - 'ovl_Bg_Hidan_Rock', - 'ovl_Bg_Hidan_Rsekizou', - 'ovl_Bg_Hidan_Sekizou', - 'ovl_Bg_Hidan_Sima', - 'ovl_Bg_Hidan_Syoku', - 'ovl_Bg_Ice_Objects', - 'ovl_Bg_Ice_Shelter', - 'ovl_Bg_Ice_Shutter', - 'ovl_Bg_Ice_Turara', - 'ovl_Bg_Ingate', - 'ovl_Bg_Jya_1flift', - 'ovl_Bg_Jya_Amishutter', - 'ovl_Bg_Jya_Bigmirror', - 'ovl_Bg_Jya_Block', - 'ovl_Bg_Jya_Bombchuiwa', - 'ovl_Bg_Jya_Bombiwa', - 'ovl_Bg_Jya_Cobra', - 'ovl_Bg_Jya_Goroiwa', - 'ovl_Bg_Jya_Haheniron', - 'ovl_Bg_Jya_Ironobj', - 'ovl_Bg_Jya_Kanaami', - 'ovl_Bg_Jya_Lift', - 'ovl_Bg_Jya_Megami', - 'ovl_Bg_Jya_Zurerukabe', - 'ovl_Bg_Menkuri_Eye', - 'ovl_Bg_Menkuri_Kaiten', - 'ovl_Bg_Menkuri_Nisekabe', - 'ovl_Bg_Mizu_Bwall', - 'ovl_Bg_Mizu_Movebg', - 'ovl_Bg_Mizu_Shutter', - 'ovl_Bg_Mizu_Uzu', - 'ovl_Bg_Mizu_Water', - 'ovl_Bg_Mjin', - 'ovl_Bg_Mori_Bigst', - 'ovl_Bg_Mori_Elevator', - 'ovl_Bg_Mori_Hashigo', - 'ovl_Bg_Mori_Hashira4', - 'ovl_Bg_Mori_Hineri', - 'ovl_Bg_Mori_Idomizu', - 'ovl_Bg_Mori_Kaitenkabe', - 'ovl_Bg_Mori_Rakkatenjo', - 'ovl_Bg_Po_Event', - 'ovl_Bg_Po_Syokudai', - 'ovl_Bg_Pushbox', - 'ovl_Bg_Relay_Objects', - 'ovl_Bg_Spot00_Break', - 'ovl_Bg_Spot00_Hanebasi', - 'ovl_Bg_Spot01_Fusya', - 'ovl_Bg_Spot01_Idohashira', - 'ovl_Bg_Spot01_Idomizu', - 'ovl_Bg_Spot01_Idosoko', - 'ovl_Bg_Spot01_Objects2', - 'ovl_Bg_Spot02_Objects', - 'ovl_Bg_Spot03_Taki', - 'ovl_Bg_Spot05_Soko', - 'ovl_Bg_Spot06_Objects', - 'ovl_Bg_Spot07_Taki', - 'ovl_Bg_Spot08_Bakudankabe', - 'ovl_Bg_Spot08_Iceblock', - 'ovl_Bg_Spot09_Obj', - 'ovl_Bg_Spot11_Bakudankabe', - 'ovl_Bg_Spot11_Oasis', - 'ovl_Bg_Spot12_Gate', - 'ovl_Bg_Spot12_Saku', - 'ovl_Bg_Spot15_Rrbox', - 'ovl_Bg_Spot15_Saku', - 'ovl_Bg_Spot16_Bombstone', - 'ovl_Bg_Spot16_Doughnut', - 'ovl_Bg_Spot17_Bakudankabe', - 'ovl_Bg_Spot17_Funen', - 'ovl_Bg_Spot18_Basket', - 'ovl_Bg_Spot18_Futa', - 'ovl_Bg_Spot18_Obj', - 'ovl_Bg_Spot18_Shutter', - 'ovl_Bg_Sst_Floor', - 'ovl_Bg_Toki_Hikari', - 'ovl_Bg_Toki_Swd', - 'ovl_Bg_Treemouth', - 'ovl_Bg_Umajump', - 'ovl_Bg_Vb_Sima', - 'ovl_Bg_Ydan_Hasi', - 'ovl_Bg_Ydan_Maruta', - 'ovl_Bg_Ydan_Sp', - 'ovl_Bg_Zg', - 'ovl_Boss_Dodongo', - 'ovl_Boss_Fd', - 'ovl_Boss_Fd2', - 'ovl_Boss_Ganon', - 'ovl_Boss_Ganon2', - 'ovl_Boss_Ganondrof', - 'ovl_Boss_Goma', - 'ovl_Boss_Mo', - 'ovl_Boss_Sst', - 'ovl_Boss_Tw', - 'ovl_Boss_Va', - 'ovl_Demo_6K', - 'ovl_Demo_Du', - 'ovl_Demo_Ec', - 'ovl_Demo_Effect', - 'ovl_Demo_Ext', - 'ovl_Demo_Geff', - 'ovl_Demo_Gj', - 'ovl_Demo_Go', - 'ovl_Demo_Gt', - 'ovl_Demo_Ik', - 'ovl_Demo_Im', - 'ovl_Demo_Kankyo', - 'ovl_Demo_Kekkai', - 'ovl_Demo_Sa', - 'ovl_Demo_Shd', - 'ovl_Demo_Tre_Lgt', - 'ovl_Door_Ana', - 'ovl_Door_Gerudo', - 'ovl_Door_Killer', - 'ovl_Door_Shutter', - 'ovl_Door_Toki', - 'ovl_Door_Warp1', - 'ovl_Efc_Erupc', - 'ovl_Eff_Dust', - 'ovl_Effect_Ss_Blast', - 'ovl_Effect_Ss_Bomb', - 'ovl_Effect_Ss_Bomb2', - 'ovl_Effect_Ss_Bubble', - 'ovl_Effect_Ss_D_Fire', - 'ovl_Effect_Ss_Dead_Db', - 'ovl_Effect_Ss_Dead_Dd', - 'ovl_Effect_Ss_Dead_Ds', - 'ovl_Effect_Ss_Dead_Sound', - 'ovl_Effect_Ss_Dt_Bubble', - 'ovl_Effect_Ss_Dust', - 'ovl_Effect_Ss_En_Fire', - 'ovl_Effect_Ss_En_Ice', - 'ovl_Effect_Ss_Extra', - 'ovl_Effect_Ss_Fcircle', - 'ovl_Effect_Ss_Fhg_Flash', - 'ovl_Effect_Ss_Fire_Tail', - 'ovl_Effect_Ss_G_Fire', - 'ovl_Effect_Ss_G_Magma', - 'ovl_Effect_Ss_G_Magma2', - 'ovl_Effect_Ss_G_Ripple', - 'ovl_Effect_Ss_G_Spk', - 'ovl_Effect_Ss_G_Splash', - 'ovl_Effect_Ss_Hahen', - 'ovl_Effect_Ss_HitMark', - 'ovl_Effect_Ss_Ice_Piece', - 'ovl_Effect_Ss_Ice_Smoke', - 'ovl_Effect_Ss_K_Fire', - 'ovl_Effect_Ss_Kakera', - 'ovl_Effect_Ss_KiraKira', - 'ovl_Effect_Ss_Lightning', - 'ovl_Effect_Ss_Sibuki', - 'ovl_Effect_Ss_Sibuki2', - 'ovl_Effect_Ss_Solder_Srch_Ball', - 'ovl_Effect_Ss_Stick', - 'ovl_Effect_Ss_Stone1', - 'ovl_Elf_Msg', - 'ovl_Elf_Msg2', - 'ovl_En_Am', - 'ovl_En_Ani', - 'ovl_En_Anubice', - 'ovl_En_Anubice_Fire', - 'ovl_En_Anubice_Tag', - 'ovl_En_Arow_Trap', - 'ovl_En_Arrow', - 'ovl_En_Attack_Niw', - 'ovl_En_Ba', - 'ovl_En_Bb', - 'ovl_En_Bdfire', - 'ovl_En_Bigokuta', - 'ovl_En_Bili', - 'ovl_En_Bird', - 'ovl_En_Blkobj', - 'ovl_En_Bom', - 'ovl_En_Bom_Bowl_Man', - 'ovl_En_Bom_Bowl_Pit', - 'ovl_En_Bom_Chu', - 'ovl_En_Bombf', - 'ovl_En_Boom', - 'ovl_En_Box', - 'ovl_En_Brob', - 'ovl_En_Bubble', - 'ovl_En_Butte', - 'ovl_En_Bw', - 'ovl_En_Bx', - 'ovl_En_Changer', - 'ovl_En_Clear_Tag', - 'ovl_En_Cow', - 'ovl_En_Crow', - 'ovl_En_Cs', - 'ovl_En_Daiku', - 'ovl_En_Daiku_Kakariko', - 'ovl_En_Dekubaba', - 'ovl_En_Dekunuts', - 'ovl_En_Dh', - 'ovl_En_Dha', - 'ovl_En_Diving_Game', - 'ovl_En_Dns', - 'ovl_En_Dnt_Demo', - 'ovl_En_Dnt_Jiji', - 'ovl_En_Dnt_Nomal', - 'ovl_En_Dodojr', - 'ovl_En_Dodongo', - 'ovl_En_Dog', - 'ovl_En_Door', - 'ovl_En_Ds', - 'ovl_En_Du', - 'ovl_En_Dy_Extra', - 'ovl_En_Eg', - 'ovl_En_Eiyer', - 'ovl_En_Elf', - 'ovl_En_Encount1', - 'ovl_En_Encount2', - 'ovl_En_Ex_Item', - 'ovl_En_Ex_Ruppy', - 'ovl_En_Fd', - 'ovl_En_Fd_Fire', - 'ovl_En_Fhg_Fire', - 'ovl_En_Fire_Rock', - 'ovl_En_Firefly', - 'ovl_En_Fish', - 'ovl_En_Floormas', - 'ovl_En_Fr', - 'ovl_En_Fu', - 'ovl_En_Fw', - 'ovl_En_Fz', - 'ovl_En_G_Switch', - 'ovl_En_Ganon_Mant', - 'ovl_En_Ganon_Organ', - 'ovl_En_Gb', - 'ovl_En_Ge1', - 'ovl_En_Ge2', - 'ovl_En_Ge3', - 'ovl_En_GeldB', - 'ovl_En_GirlA', - 'ovl_En_Gm', - 'ovl_En_Go', - 'ovl_En_Go2', - 'ovl_En_Goma', - 'ovl_En_Goroiwa', - 'ovl_En_Gs', - 'ovl_En_Guest', - 'ovl_En_Hata', - 'ovl_En_Heishi1', - 'ovl_En_Heishi2', - 'ovl_En_Heishi3', - 'ovl_En_Heishi4', - 'ovl_En_Hintnuts', - 'ovl_En_Holl', - 'ovl_En_Honotrap', - 'ovl_En_Horse', - 'ovl_En_Horse_Game_Check', - 'ovl_En_Horse_Ganon', - 'ovl_En_Horse_Link_Child', - 'ovl_En_Horse_Normal', - 'ovl_En_Horse_Zelda', - 'ovl_En_Hs', - 'ovl_En_Hs2', - 'ovl_En_Hy', - 'ovl_En_Ice_Hono', - 'ovl_En_Ik', - 'ovl_En_In', - 'ovl_En_Insect', - 'ovl_En_Ishi', - 'ovl_En_It', - 'ovl_En_Jj', - 'ovl_En_Js', - 'ovl_En_Jsjutan', - 'ovl_En_Kakasi', - 'ovl_En_Kakasi2', - 'ovl_En_Kakasi3', - 'ovl_En_Kanban', - 'ovl_En_Karebaba', - 'ovl_En_Ko', - 'ovl_En_Kusa', - 'ovl_En_Kz', - 'ovl_En_Light', - 'ovl_En_Lightbox', - 'ovl_En_M_Fire1', - 'ovl_En_M_Thunder', - 'ovl_En_Ma1', - 'ovl_En_Ma2', - 'ovl_En_Ma3', - 'ovl_En_Mag', - 'ovl_En_Mb', - 'ovl_En_Md', - 'ovl_En_Mk', - 'ovl_En_Mm', - 'ovl_En_Mm2', - 'ovl_En_Ms', - 'ovl_En_Mu', - 'ovl_En_Nb', - 'ovl_En_Niw', - 'ovl_En_Niw_Girl', - 'ovl_En_Niw_Lady', - 'ovl_En_Nutsball', - 'ovl_En_Nwc', - 'ovl_En_Ny', - 'ovl_En_OE2', - 'ovl_En_Okarina_Effect', - 'ovl_En_Okarina_Tag', - 'ovl_En_Okuta', - 'ovl_En_Ossan', - 'ovl_En_Owl', - 'ovl_En_Part', - 'ovl_En_Peehat', - 'ovl_En_Po_Desert', - 'ovl_En_Po_Field', - 'ovl_En_Po_Relay', - 'ovl_En_Po_Sisters', - 'ovl_En_Poh', - 'ovl_En_Pu_box', - 'ovl_En_Rd', - 'ovl_En_Reeba', - 'ovl_En_River_Sound', - 'ovl_En_Rl', - 'ovl_En_Rr', - 'ovl_En_Ru1', - 'ovl_En_Ru2', - 'ovl_En_Sa', - 'ovl_En_Sb', - 'ovl_En_Scene_Change', - 'ovl_En_Sda', - 'ovl_En_Shopnuts', - 'ovl_En_Si', - 'ovl_En_Siofuki', - 'ovl_En_Skb', - 'ovl_En_Skj', - 'ovl_En_Skjneedle', - 'ovl_En_Ssh', - 'ovl_En_St', - 'ovl_En_Sth', - 'ovl_En_Stream', - 'ovl_En_Sw', - 'ovl_En_Syateki_Itm', - 'ovl_En_Syateki_Man', - 'ovl_En_Syateki_Niw', - 'ovl_En_Ta', - 'ovl_En_Takara_Man', - 'ovl_En_Tana', - 'ovl_En_Tg', - 'ovl_En_Tite', - 'ovl_En_Tk', - 'ovl_En_Torch', - 'ovl_En_Torch2', - 'ovl_En_Toryo', - 'ovl_En_Tp', - 'ovl_En_Tr', - 'ovl_En_Trap', - 'ovl_En_Tubo_Trap', - 'ovl_En_Vali', - 'ovl_En_Vase', - 'ovl_En_Vb_Ball', - 'ovl_En_Viewer', - 'ovl_En_Vm', - 'ovl_En_Wall_Tubo', - 'ovl_En_Wallmas', - 'ovl_En_Weather_Tag', - 'ovl_En_Weiyer', - 'ovl_En_Wf', - 'ovl_En_Wonder_Item', - 'ovl_En_Wonder_Talk', - 'ovl_En_Wonder_Talk2', - 'ovl_En_Wood02', - 'ovl_En_Xc', - 'ovl_En_Yabusame_Mark', - 'ovl_En_Yukabyun', - 'ovl_En_Zf', - 'ovl_En_Zl1', - 'ovl_En_Zl2', - 'ovl_En_Zl3', - 'ovl_En_Zl4', - 'ovl_En_Zo', - 'ovl_En_fHG', - 'ovl_End_Title', - 'ovl_Fishing', - 'ovl_Item_B_Heart', - 'ovl_Item_Etcetera', - 'ovl_Item_Inbox', - 'ovl_Item_Ocarina', - 'ovl_Item_Shield', - 'ovl_Magic_Dark', - 'ovl_Magic_Fire', - 'ovl_Magic_Wind', - 'ovl_Mir_Ray', - 'ovl_Obj_Bean', - 'ovl_Obj_Blockstop', - 'ovl_Obj_Bombiwa', - 'ovl_Obj_Comb', - 'ovl_Obj_Dekujr', - 'ovl_Obj_Elevator', - 'ovl_Obj_Hamishi', - 'ovl_Obj_Hana', - 'ovl_Obj_Hsblock', - 'ovl_Obj_Ice_Poly', - 'ovl_Obj_Kibako', - 'ovl_Obj_Kibako2', - 'ovl_Obj_Lift', - 'ovl_Obj_Lightswitch', - 'ovl_Obj_Makekinsuta', - 'ovl_Obj_Makeoshihiki', - 'ovl_Obj_Mure', - 'ovl_Obj_Mure2', - 'ovl_Obj_Mure3', - 'ovl_Obj_Oshihiki', - 'ovl_Obj_Roomtimer', - 'ovl_Obj_Switch', - 'ovl_Obj_Syokudai', - 'ovl_Obj_Timeblock', - 'ovl_Obj_Tsubo', - 'ovl_Obj_Warp2block', - 'ovl_Object_Kankyo', - 'ovl_Oceff_Spot', - 'ovl_Oceff_Storm', - 'ovl_Oceff_Wipe', - 'ovl_Oceff_Wipe2', - 'ovl_Oceff_Wipe3', - 'ovl_Oceff_Wipe4', - 'ovl_Shot_Sun', - 'gameplay_keep', - 'gameplay_field_keep', - 'gameplay_dangeon_keep', - 'gameplay_object_exchange_static', - 'object_link_boy', - 'object_link_child', - 'object_box', - 'object_human', - 'object_okuta', - 'object_poh', - 'object_wallmaster', - 'object_dy_obj', - 'object_firefly', - 'object_dodongo', - 'object_fire', - 'object_niw', - 'object_tite', - 'object_reeba', - 'object_peehat', - 'object_kingdodongo', - 'object_horse', - 'object_zf', - 'object_goma', - 'object_zl1', - 'object_gol', - 'object_bubble', - 'object_dodojr', - 'object_torch2', - 'object_bl', - 'object_tp', - 'object_oA1', - 'object_st', - 'object_bw', - 'object_ei', - 'object_horse_normal', - 'object_oB1', - 'object_o_anime', - 'object_spot04_objects', - 'object_ddan_objects', - 'object_hidan_objects', - 'object_horse_ganon', - 'object_oA2', - 'object_spot00_objects', - 'object_mb', - 'object_bombf', - 'object_sk2', - 'object_oE1', - 'object_oE_anime', - 'object_oE2', - 'object_ydan_objects', - 'object_gnd', - 'object_am', - 'object_dekubaba', - 'object_oA3', - 'object_oA4', - 'object_oA5', - 'object_oA6', - 'object_oA7', - 'object_jj', - 'object_oA8', - 'object_oA9', - 'object_oB2', - 'object_oB3', - 'object_oB4', - 'object_horse_zelda', - 'object_opening_demo1', - 'object_warp1', - 'object_b_heart', - 'object_dekunuts', - 'object_oE3', - 'object_oE4', - 'object_menkuri_objects', - 'object_oE5', - 'object_oE6', - 'object_oE7', - 'object_oE8', - 'object_oE9', - 'object_oE10', - 'object_oE11', - 'object_oE12', - 'object_vali', - 'object_oA10', - 'object_oA11', - 'object_mizu_objects', - 'object_fhg', - 'object_ossan', - 'object_mori_hineri1', - 'object_Bb', - 'object_toki_objects', - 'object_yukabyun', - 'object_zl2', - 'object_mjin', - 'object_mjin_flash', - 'object_mjin_dark', - 'object_mjin_flame', - 'object_mjin_ice', - 'object_mjin_soul', - 'object_mjin_wind', - 'object_mjin_oka', - 'object_haka_objects', - 'object_spot06_objects', - 'object_ice_objects', - 'object_relay_objects', - 'object_mori_hineri1a', - 'object_mori_hineri2', - 'object_mori_hineri2a', - 'object_mori_objects', - 'object_mori_tex', - 'object_spot08_obj', - 'object_warp2', - 'object_hata', - 'object_bird', - 'object_wood02', - 'object_lightbox', - 'object_pu_box', - 'object_trap', - 'object_vase', - 'object_im', - 'object_ta', - 'object_tk', - 'object_xc', - 'object_vm', - 'object_bv', - 'object_hakach_objects', - 'object_efc_crystal_light', - 'object_efc_fire_ball', - 'object_efc_flash', - 'object_efc_lgt_shower', - 'object_efc_star_field', - 'object_god_lgt', - 'object_light_ring', - 'object_triforce_spot', - 'object_medal', - 'object_bdan_objects', - 'object_sd', - 'object_rd', - 'object_po_sisters', - 'object_heavy_object', - 'object_gndd', - 'object_fd', - 'object_du', - 'object_fw', - 'object_horse_link_child', - 'object_spot02_objects', - 'object_haka', - 'object_ru1', - 'object_syokudai', - 'object_fd2', - 'object_dh', - 'object_rl', - 'object_efc_tw', - 'object_demo_tre_lgt', - 'object_gi_key', - 'object_mir_ray', - 'object_brob', - 'object_gi_jewel', - 'object_spot09_obj', - 'object_spot18_obj', - 'object_bdoor', - 'object_spot17_obj', - 'object_shop_dungen', - 'object_nb', - 'object_mo', - 'object_sb', - 'object_gi_melody', - 'object_gi_heart', - 'object_gi_compass', - 'object_gi_bosskey', - 'object_gi_medal', - 'object_gi_nuts', - 'object_sa', - 'object_gi_hearts', - 'object_gi_arrowcase', - 'object_gi_bombpouch', - 'object_in', - 'object_tr', - 'object_spot16_obj', - 'object_oE1s', - 'object_oE4s', - 'object_os_anime', - 'object_gi_bottle', - 'object_gi_stick', - 'object_gi_map', - 'object_oF1d_map', - 'object_ru2', - 'object_gi_shield_1', - 'object_dekujr', - 'object_gi_magicpot', - 'object_gi_bomb_1', - 'object_oF1s', - 'object_ma2', - 'object_gi_purse', - 'object_hni', - 'object_tw', - 'object_rr', - 'object_bxa', - 'object_anubice', - 'object_gi_gerudo', - 'object_gi_arrow', - 'object_gi_bomb_2', - 'object_gi_egg', - 'object_gi_scale', - 'object_gi_shield_2', - 'object_gi_hookshot', - 'object_gi_ocarina', - 'object_gi_milk', - 'object_ma1', - 'object_ganon', - 'object_sst', - 'object_ny', - 'object_fr', - 'object_gi_pachinko', - 'object_gi_boomerang', - 'object_gi_bow', - 'object_gi_glasses', - 'object_gi_liquid', - 'object_ani', - 'object_demo_6k', - 'object_gi_shield_3', - 'object_gi_letter', - 'object_spot15_obj', - 'object_jya_obj', - 'object_gi_clothes', - 'object_gi_bean', - 'object_gi_fish', - 'object_gi_saw', - 'object_gi_hammer', - 'object_gi_grass', - 'object_gi_longsword', - 'object_spot01_objects', - 'object_md', - 'object_km1', - 'object_kw1', - 'object_zo', - 'object_kz', - 'object_umajump', - 'object_masterkokiri', - 'object_masterkokirihead', - 'object_mastergolon', - 'object_masterzoora', - 'object_aob', - 'object_ik', - 'object_ahg', - 'object_cne', - 'object_gi_niwatori', - 'object_skj', - 'object_gi_bottle_letter', - 'object_bji', - 'object_bba', - 'object_gi_ocarina_0', - 'object_ds', - 'object_ane', - 'object_boj', - 'object_spot03_object', - 'object_spot07_object', - 'object_fz', - 'object_bob', - 'object_ge1', - 'object_yabusame_point', - 'object_gi_boots_2', - 'object_gi_seed', - 'object_gnd_magic', - 'object_d_elevator', - 'object_d_hsblock', - 'object_d_lift', - 'object_mamenoki', - 'object_goroiwa', - 'object_toryo', - 'object_daiku', - 'object_nwc', - 'object_blkobj', - 'object_gm', - 'object_ms', - 'object_hs', - 'object_ingate', - 'object_lightswitch', - 'object_kusa', - 'object_tsubo', - 'object_gi_gloves', - 'object_gi_coin', - 'object_kanban', - 'object_gjyo_objects', - 'object_owl', - 'object_mk', - 'object_fu', - 'object_gi_ki_tan_mask', - 'object_gi_redead_mask', - 'object_gi_skj_mask', - 'object_gi_rabit_mask', - 'object_gi_truth_mask', - 'object_ganon_objects', - 'object_siofuki', - 'object_stream', - 'object_mm', - 'object_fa', - 'object_os', - 'object_gi_eye_lotion', - 'object_gi_powder', - 'object_gi_mushroom', - 'object_gi_ticketstone', - 'object_gi_brokensword', - 'object_js', - 'object_cs', - 'object_gi_prescription', - 'object_gi_bracelet', - 'object_gi_soldout', - 'object_gi_frog', - 'object_mag', - 'object_door_gerudo', - 'object_gt', - 'object_efc_erupc', - 'object_zl2_anime1', - 'object_zl2_anime2', - 'object_gi_golonmask', - 'object_gi_zoramask', - 'object_gi_gerudomask', - 'object_ganon2', - 'object_ka', - 'object_ts', - 'object_zg', - 'object_gi_hoverboots', - 'object_gi_m_arrow', - 'object_ds2', - 'object_ec', - 'object_fish', - 'object_gi_sutaru', - 'object_gi_goddess', - 'object_ssh', - 'object_bigokuta', - 'object_bg', - 'object_spot05_objects', - 'object_spot12_obj', - 'object_bombiwa', - 'object_hintnuts', - 'object_rs', - 'object_spot00_break', - 'object_gla', - 'object_shopnuts', - 'object_geldb', - 'object_gr', - 'object_dog', - 'object_jya_iron', - 'object_jya_door', - 'object_spot01_objects2', - 'object_spot11_obj', - 'object_kibako2', - 'object_dns', - 'object_dnk', - 'object_gi_fire', - 'object_gi_insect', - 'object_gi_butterfly', - 'object_gi_ghost', - 'object_gi_soul', - 'object_bowl', - 'object_po_field', - 'object_demo_kekkai', - 'object_efc_doughnut', - 'object_gi_dekupouch', - 'object_ganon_anime1', - 'object_ganon_anime2', - 'object_ganon_anime3', - 'object_gi_rupy', - 'object_spot01_matoya', - 'object_spot01_matoyab', - 'object_po_composer', - 'object_mu', - 'object_wf', - 'object_skb', - 'object_gj', - 'object_geff', - 'object_haka_door', - 'object_gs', - 'object_ps', - 'object_bwall', - 'object_crow', - 'object_cow', - 'object_cob', - 'object_gi_sword_1', - 'object_door_killer', - 'object_ouke_haka', - 'object_timeblock', - 'object_zl4', - 'g_pn_01', - 'g_pn_02', - 'g_pn_03', - 'g_pn_04', - 'g_pn_05', - 'g_pn_06', - 'g_pn_07', - 'g_pn_08', - 'g_pn_09', - 'g_pn_10', - 'g_pn_11', - 'g_pn_12', - 'g_pn_13', - 'g_pn_14', - 'g_pn_15', - 'g_pn_16', - 'g_pn_17', - 'g_pn_18', - 'g_pn_19', - 'g_pn_20', - 'g_pn_21', - 'g_pn_22', - 'g_pn_23', - 'g_pn_24', - 'g_pn_25', - 'g_pn_26', - 'g_pn_27', - 'g_pn_28', - 'g_pn_29', - 'g_pn_30', - 'g_pn_31', - 'g_pn_32', - 'g_pn_33', - 'g_pn_34', - 'g_pn_35', - 'g_pn_36', - 'g_pn_37', - 'g_pn_38', - 'g_pn_39', - 'g_pn_40', - 'g_pn_41', - 'g_pn_42', - 'g_pn_43', - 'g_pn_44', - 'g_pn_45', - 'g_pn_46', - 'g_pn_47', - 'g_pn_48', - 'g_pn_49', - 'g_pn_50', - 'g_pn_51', - 'g_pn_52', - 'g_pn_53', - 'g_pn_54', - 'g_pn_55', - 'g_pn_56', - 'g_pn_57', - 'z_select_static', - 'nintendo_rogo_static', - 'title_static', - 'parameter_static', - 'vr_fine0_static', - 'vr_fine0_pal_static', - 'vr_fine1_static', - 'vr_fine1_pal_static', - 'vr_fine2_static', - 'vr_fine2_pal_static', - 'vr_fine3_static', - 'vr_fine3_pal_static', - 'vr_cloud0_static', - 'vr_cloud0_pal_static', - 'vr_cloud1_static', - 'vr_cloud1_pal_static', - 'vr_cloud2_static', - 'vr_cloud2_pal_static', - 'vr_cloud3_static', - 'vr_cloud3_pal_static', - 'vr_holy0_static', - 'vr_holy0_pal_static', - 'vr_holy1_static', - 'vr_holy1_pal_static', - 'vr_MDVR_static', - 'vr_MDVR_pal_static', - 'vr_MNVR_static', - 'vr_MNVR_pal_static', - 'vr_RUVR_static', - 'vr_RUVR_pal_static', - 'vr_LHVR_static', - 'vr_LHVR_pal_static', - 'vr_KHVR_static', - 'vr_KHVR_pal_static', - 'vr_K3VR_static', - 'vr_K3VR_pal_static', - 'vr_K4VR_static', - 'vr_K4VR_pal_static', - 'vr_K5VR_static', - 'vr_K5VR_pal_static', - 'vr_SP1a_static', - 'vr_SP1a_pal_static', - 'vr_MLVR_static', - 'vr_MLVR_pal_static', - 'vr_KKRVR_static', - 'vr_KKRVR_pal_static', - 'vr_KR3VR_static', - 'vr_KR3VR_pal_static', - 'vr_IPVR_static', - 'vr_IPVR_pal_static', - 'vr_KSVR_static', - 'vr_KSVR_pal_static', - 'vr_GLVR_static', - 'vr_GLVR_pal_static', - 'vr_ZRVR_static', - 'vr_ZRVR_pal_static', - 'vr_DGVR_static', - 'vr_DGVR_pal_static', - 'vr_ALVR_static', - 'vr_ALVR_pal_static', - 'vr_NSVR_static', - 'vr_NSVR_pal_static', - 'vr_LBVR_static', - 'vr_LBVR_pal_static', - 'vr_TTVR_static', - 'vr_TTVR_pal_static', - 'vr_FCVR_static', - 'vr_FCVR_pal_static', - 'elf_message_field', - 'elf_message_ydan', - 'syotes_scene', - 'syotes_room_0', - 'syotes2_scene', - 'syotes2_room_0', - 'depth_test_scene', - 'depth_test_room_0', - 'spot00_scene', - 'spot00_room_0', - 'spot01_scene', - 'spot01_room_0', - 'spot02_scene', - 'spot02_room_0', - 'spot02_room_1', - 'spot03_scene', - 'spot03_room_0', - 'spot03_room_1', - 'spot04_scene', - 'spot04_room_0', - 'spot04_room_1', - 'spot04_room_2', - 'spot05_scene', - 'spot05_room_0', - 'spot06_scene', - 'spot06_room_0', - 'spot07_scene', - 'spot07_room_0', - 'spot07_room_1', - 'spot08_scene', - 'spot08_room_0', - 'spot09_scene', - 'spot09_room_0', - 'spot10_scene', - 'spot10_room_0', - 'spot10_room_1', - 'spot10_room_2', - 'spot10_room_3', - 'spot10_room_4', - 'spot10_room_5', - 'spot10_room_6', - 'spot10_room_7', - 'spot10_room_8', - 'spot10_room_9', - 'spot11_scene', - 'spot11_room_0', - 'spot12_scene', - 'spot12_room_0', - 'spot12_room_1', - 'spot13_scene', - 'spot13_room_0', - 'spot13_room_1', - 'spot15_scene', - 'spot15_room_0', - 'spot16_scene', - 'spot16_room_0', - 'spot17_scene', - 'spot17_room_0', - 'spot17_room_1', - 'spot18_scene', - 'spot18_room_0', - 'spot18_room_1', - 'spot18_room_2', - 'spot18_room_3', - 'ydan_scene', - 'ydan_room_0', - 'ydan_room_1', - 'ydan_room_2', - 'ydan_room_3', - 'ydan_room_4', - 'ydan_room_5', - 'ydan_room_6', - 'ydan_room_7', - 'ydan_room_8', - 'ydan_room_9', - 'ydan_room_10', - 'ydan_room_11', - 'ddan_scene', - 'ddan_room_0', - 'ddan_room_1', - 'ddan_room_2', - 'ddan_room_3', - 'ddan_room_4', - 'ddan_room_5', - 'ddan_room_6', - 'ddan_room_7', - 'ddan_room_8', - 'ddan_room_9', - 'ddan_room_10', - 'ddan_room_11', - 'ddan_room_12', - 'ddan_room_13', - 'ddan_room_14', - 'ddan_room_15', - 'ddan_room_16', - 'bdan_scene', - 'bdan_room_0', - 'bdan_room_1', - 'bdan_room_2', - 'bdan_room_3', - 'bdan_room_4', - 'bdan_room_5', - 'bdan_room_6', - 'bdan_room_7', - 'bdan_room_8', - 'bdan_room_9', - 'bdan_room_10', - 'bdan_room_11', - 'bdan_room_12', - 'bdan_room_13', - 'bdan_room_14', - 'bdan_room_15', - 'Bmori1_scene', - 'Bmori1_room_0', - 'Bmori1_room_1', - 'Bmori1_room_2', - 'Bmori1_room_3', - 'Bmori1_room_4', - 'Bmori1_room_5', - 'Bmori1_room_6', - 'Bmori1_room_7', - 'Bmori1_room_8', - 'Bmori1_room_9', - 'Bmori1_room_10', - 'Bmori1_room_11', - 'Bmori1_room_12', - 'Bmori1_room_13', - 'Bmori1_room_14', - 'Bmori1_room_15', - 'Bmori1_room_16', - 'Bmori1_room_17', - 'Bmori1_room_18', - 'Bmori1_room_19', - 'Bmori1_room_20', - 'Bmori1_room_21', - 'Bmori1_room_22', - 'HIDAN_scene', - 'HIDAN_room_0', - 'HIDAN_room_1', - 'HIDAN_room_2', - 'HIDAN_room_3', - 'HIDAN_room_4', - 'HIDAN_room_5', - 'HIDAN_room_6', - 'HIDAN_room_7', - 'HIDAN_room_8', - 'HIDAN_room_9', - 'HIDAN_room_10', - 'HIDAN_room_11', - 'HIDAN_room_12', - 'HIDAN_room_13', - 'HIDAN_room_14', - 'HIDAN_room_15', - 'HIDAN_room_16', - 'HIDAN_room_17', - 'HIDAN_room_18', - 'HIDAN_room_19', - 'HIDAN_room_20', - 'HIDAN_room_21', - 'HIDAN_room_22', - 'HIDAN_room_23', - 'HIDAN_room_24', - 'HIDAN_room_25', - 'HIDAN_room_26', - 'MIZUsin_scene', - 'MIZUsin_room_0', - 'MIZUsin_room_1', - 'MIZUsin_room_2', - 'MIZUsin_room_3', - 'MIZUsin_room_4', - 'MIZUsin_room_5', - 'MIZUsin_room_6', - 'MIZUsin_room_7', - 'MIZUsin_room_8', - 'MIZUsin_room_9', - 'MIZUsin_room_10', - 'MIZUsin_room_11', - 'MIZUsin_room_12', - 'MIZUsin_room_13', - 'MIZUsin_room_14', - 'MIZUsin_room_15', - 'MIZUsin_room_16', - 'MIZUsin_room_17', - 'MIZUsin_room_18', - 'MIZUsin_room_19', - 'MIZUsin_room_20', - 'MIZUsin_room_21', - 'MIZUsin_room_22', - 'jyasinzou_scene', - 'jyasinzou_room_0', - 'jyasinzou_room_1', - 'jyasinzou_room_2', - 'jyasinzou_room_3', - 'jyasinzou_room_4', - 'jyasinzou_room_5', - 'jyasinzou_room_6', - 'jyasinzou_room_7', - 'jyasinzou_room_8', - 'jyasinzou_room_9', - 'jyasinzou_room_10', - 'jyasinzou_room_11', - 'jyasinzou_room_12', - 'jyasinzou_room_13', - 'jyasinzou_room_14', - 'jyasinzou_room_15', - 'jyasinzou_room_16', - 'jyasinzou_room_17', - 'jyasinzou_room_18', - 'jyasinzou_room_19', - 'jyasinzou_room_20', - 'jyasinzou_room_21', - 'jyasinzou_room_22', - 'jyasinzou_room_23', - 'jyasinzou_room_24', - 'jyasinzou_room_25', - 'jyasinzou_room_26', - 'jyasinzou_room_27', - 'jyasinzou_room_28', - 'HAKAdan_scene', - 'HAKAdan_room_0', - 'HAKAdan_room_1', - 'HAKAdan_room_2', - 'HAKAdan_room_3', - 'HAKAdan_room_4', - 'HAKAdan_room_5', - 'HAKAdan_room_6', - 'HAKAdan_room_7', - 'HAKAdan_room_8', - 'HAKAdan_room_9', - 'HAKAdan_room_10', - 'HAKAdan_room_11', - 'HAKAdan_room_12', - 'HAKAdan_room_13', - 'HAKAdan_room_14', - 'HAKAdan_room_15', - 'HAKAdan_room_16', - 'HAKAdan_room_17', - 'HAKAdan_room_18', - 'HAKAdan_room_19', - 'HAKAdan_room_20', - 'HAKAdan_room_21', - 'HAKAdan_room_22', - 'HAKAdanCH_scene', - 'HAKAdanCH_room_0', - 'HAKAdanCH_room_1', - 'HAKAdanCH_room_2', - 'HAKAdanCH_room_3', - 'HAKAdanCH_room_4', - 'HAKAdanCH_room_5', - 'HAKAdanCH_room_6', - 'ice_doukutu_scene', - 'ice_doukutu_room_0', - 'ice_doukutu_room_1', - 'ice_doukutu_room_2', - 'ice_doukutu_room_3', - 'ice_doukutu_room_4', - 'ice_doukutu_room_5', - 'ice_doukutu_room_6', - 'ice_doukutu_room_7', - 'ice_doukutu_room_8', - 'ice_doukutu_room_9', - 'ice_doukutu_room_10', - 'ice_doukutu_room_11', - 'men_scene', - 'men_room_0', - 'men_room_1', - 'men_room_2', - 'men_room_3', - 'men_room_4', - 'men_room_5', - 'men_room_6', - 'men_room_7', - 'men_room_8', - 'men_room_9', - 'men_room_10', - 'ganontika_scene', - 'ganontika_room_0', - 'ganontika_room_1', - 'ganontika_room_2', - 'ganontika_room_3', - 'ganontika_room_4', - 'ganontika_room_5', - 'ganontika_room_6', - 'ganontika_room_7', - 'ganontika_room_8', - 'ganontika_room_9', - 'ganontika_room_10', - 'ganontika_room_11', - 'ganontika_room_12', - 'ganontika_room_13', - 'ganontika_room_14', - 'ganontika_room_15', - 'ganontika_room_16', - 'ganontika_room_17', - 'ganontika_room_18', - 'ganontika_room_19', - 'market_day_scene', - 'market_day_room_0', - 'market_night_scene', - 'market_night_room_0', - 'testroom_scene', - 'testroom_room_0', - 'testroom_room_1', - 'testroom_room_2', - 'testroom_room_3', - 'testroom_room_4', - 'kenjyanoma_scene', - 'kenjyanoma_room_0', - 'tokinoma_scene', - 'tokinoma_room_0', - 'tokinoma_room_1', - 'sutaru_scene', - 'sutaru_room_0', - 'link_home_scene', - 'link_home_room_0', - 'kokiri_shop_scene', - 'kokiri_shop_room_0', - 'kokiri_home_scene', - 'kokiri_home_room_0', - 'kakusiana_scene', - 'kakusiana_room_0', - 'kakusiana_room_1', - 'kakusiana_room_2', - 'kakusiana_room_3', - 'kakusiana_room_4', - 'kakusiana_room_5', - 'kakusiana_room_6', - 'kakusiana_room_7', - 'kakusiana_room_8', - 'kakusiana_room_9', - 'kakusiana_room_10', - 'kakusiana_room_11', - 'kakusiana_room_12', - 'kakusiana_room_13', - 'entra_scene', - 'entra_room_0', - 'moribossroom_scene', - 'moribossroom_room_0', - 'moribossroom_room_1', - 'syatekijyou_scene', - 'syatekijyou_room_0', - 'shop1_scene', - 'shop1_room_0', - 'hairal_niwa_scene', - 'hairal_niwa_room_0', - 'ganon_tou_scene', - 'ganon_tou_room_0', - 'sasatest_scene', - 'sasatest_room_0', - 'market_alley_scene', - 'market_alley_room_0', - 'spot20_scene', - 'spot20_room_0', - 'market_ruins_scene', - 'market_ruins_room_0', - 'entra_n_scene', - 'entra_n_room_0', - 'enrui_scene', - 'enrui_room_0', - 'market_alley_n_scene', - 'market_alley_n_room_0', - 'hiral_demo_scene', - 'hiral_demo_room_0', - 'kokiri_home3_scene', - 'kokiri_home3_room_0', - 'malon_stable_scene', - 'malon_stable_room_0', - 'kakariko_scene', - 'kakariko_room_0', - 'bdan_boss_scene', - 'bdan_boss_room_0', - 'bdan_boss_room_1', - 'FIRE_bs_scene', - 'FIRE_bs_room_0', - 'FIRE_bs_room_1', - 'hut_scene', - 'hut_room_0', - 'daiyousei_izumi_scene', - 'daiyousei_izumi_room_0', - 'hakaana_scene', - 'hakaana_room_0', - 'yousei_izumi_tate_scene', - 'yousei_izumi_tate_room_0', - 'yousei_izumi_yoko_scene', - 'yousei_izumi_yoko_room_0', - 'golon_scene', - 'golon_room_0', - 'zoora_scene', - 'zoora_room_0', - 'drag_scene', - 'drag_room_0', - 'alley_shop_scene', - 'alley_shop_room_0', - 'night_shop_scene', - 'night_shop_room_0', - 'impa_scene', - 'impa_room_0', - 'labo_scene', - 'labo_room_0', - 'tent_scene', - 'tent_room_0', - 'nakaniwa_scene', - 'nakaniwa_room_0', - 'ddan_boss_scene', - 'ddan_boss_room_0', - 'ddan_boss_room_1', - 'ydan_boss_scene', - 'ydan_boss_room_0', - 'ydan_boss_room_1', - 'HAKAdan_bs_scene', - 'HAKAdan_bs_room_0', - 'HAKAdan_bs_room_1', - 'MIZUsin_bs_scene', - 'MIZUsin_bs_room_0', - 'MIZUsin_bs_room_1', - 'ganon_scene', - 'ganon_room_0', - 'ganon_room_1', - 'ganon_room_2', - 'ganon_room_3', - 'ganon_room_4', - 'ganon_room_5', - 'ganon_room_6', - 'ganon_room_7', - 'ganon_room_8', - 'ganon_room_9', - 'ganon_boss_scene', - 'ganon_boss_room_0', - 'jyasinboss_scene', - 'jyasinboss_room_0', - 'jyasinboss_room_1', - 'jyasinboss_room_2', - 'jyasinboss_room_3', - 'kokiri_home4_scene', - 'kokiri_home4_room_0', - 'kokiri_home5_scene', - 'kokiri_home5_room_0', - 'ganon_final_scene', - 'ganon_final_room_0', - 'kakariko3_scene', - 'kakariko3_room_0', - 'hairal_niwa2_scene', - 'hairal_niwa2_room_0', - 'hakasitarelay_scene', - 'hakasitarelay_room_0', - 'hakasitarelay_room_1', - 'hakasitarelay_room_2', - 'hakasitarelay_room_3', - 'hakasitarelay_room_4', - 'hakasitarelay_room_5', - 'hakasitarelay_room_6', - 'shrine_scene', - 'shrine_room_0', - 'turibori_scene', - 'turibori_room_0', - 'shrine_n_scene', - 'shrine_n_room_0', - 'shrine_r_scene', - 'shrine_r_room_0', - 'hakaana2_scene', - 'hakaana2_room_0', - 'gerudoway_scene', - 'gerudoway_room_0', - 'gerudoway_room_1', - 'gerudoway_room_2', - 'gerudoway_room_3', - 'gerudoway_room_4', - 'gerudoway_room_5', - 'hairal_niwa_n_scene', - 'hairal_niwa_n_room_0', - 'bowling_scene', - 'bowling_room_0', - 'hakaana_ouke_scene', - 'hakaana_ouke_room_0', - 'hakaana_ouke_room_1', - 'hakaana_ouke_room_2', - 'hylia_labo_scene', - 'hylia_labo_room_0', - 'souko_scene', - 'souko_room_0', - 'souko_room_1', - 'souko_room_2', - 'miharigoya_scene', - 'miharigoya_room_0', - 'mahouya_scene', - 'mahouya_room_0', - 'takaraya_scene', - 'takaraya_room_0', - 'takaraya_room_1', - 'takaraya_room_2', - 'takaraya_room_3', - 'takaraya_room_4', - 'takaraya_room_5', - 'takaraya_room_6', - 'ganon_sonogo_scene', - 'ganon_sonogo_room_0', - 'ganon_sonogo_room_1', - 'ganon_sonogo_room_2', - 'ganon_sonogo_room_3', - 'ganon_sonogo_room_4', - 'ganon_demo_scene', - 'ganon_demo_room_0', - 'besitu_scene', - 'besitu_room_0', - 'face_shop_scene', - 'face_shop_room_0', - 'kinsuta_scene', - 'kinsuta_room_0', - 'ganontikasonogo_scene', - 'ganontikasonogo_room_0', - 'ganontikasonogo_room_1', - 'test01_scene', - 'test01_room_0', - 'bump_texture_static', - 'anime_model_1_static', - 'anime_model_2_static', - 'anime_model_3_static', - 'anime_model_4_static', - 'anime_model_5_static', - 'anime_model_6_static', - 'anime_texture_1_static', - 'anime_texture_2_static', - 'anime_texture_3_static', - 'anime_texture_4_static', - 'anime_texture_5_static', - 'anime_texture_6_static', - 'softsprite_matrix_static', -] - -romData = None - - -def initialize_worker(rom_data): - global romData - romData = rom_data - -def read_uint32_be(offset): - return struct.unpack('>I', romData[offset:offset+4])[0] - -def write_output_file(name, offset, size): - try: - with open(name, 'wb') as f: - f.write(romData[offset:offset+size]) - except IOError: - print('failed to write file ' + name) - -def ExtractFunc(i): - filename = 'baserom/' + FILE_NAMES[i] - entryOffset = FILE_TABLE_OFFSET + 16 * i - - virtStart = read_uint32_be(entryOffset + 0) - virtEnd = read_uint32_be(entryOffset + 4) - physStart = read_uint32_be(entryOffset + 8) - physEnd = read_uint32_be(entryOffset + 12) - - if physEnd == 0: # uncompressed - compressed = False - size = virtEnd - virtStart - else: # compressed - compressed = True - size = physEnd - physStart - - print('extracting ' + filename + " (0x%08X, 0x%08X)" % (virtStart, virtEnd)) - write_output_file(filename, physStart, size) - if compressed: - os.system('tools/yaz0 -d ' + filename + ' ' + filename) - -##################################################################### - -def main(): - try: - os.mkdir('baserom') - except: - pass - - # read baserom data - try: - with open(ROM_FILE_NAME, 'rb') as f: - rom_data = f.read() - except IOError: - print('failed to read ' + ROM_FILE_NAME) - sys.exit(1) - - # extract files - num_cores = cpu_count() - print("Extracting baserom with " + str(num_cores) + " CPU cores.") - with Pool(num_cores, initialize_worker, (rom_data,)) as p: - p.map(ExtractFunc, range(len(FILE_NAMES))) - -if __name__ == "__main__": - main() diff --git a/OTRExporter/extract_baserom_gc.py b/OTRExporter/extract_baserom_gc.py deleted file mode 100644 index 0bc324f81..000000000 --- a/OTRExporter/extract_baserom_gc.py +++ /dev/null @@ -1,1586 +0,0 @@ -#!/usr/bin/python3 - -import os -import sys -import struct -from multiprocessing import Pool, cpu_count - - -ROM_FILE_NAME = 'zlp_f.n64' -FILE_TABLE_OFFSET = 0x7170 - -FILE_NAMES = [ - 'makerom', - 'boot', - 'dmadata', - 'Audiobank', - 'Audioseq', - 'Audiotable', - 'link_animetion', - 'icon_item_static', - 'icon_item_24_static', - 'icon_item_field_static', - 'icon_item_dungeon_static', - 'icon_item_gameover_static', - 'icon_item_nes_static', - 'icon_item_ger_static', - 'icon_item_fra_static', - 'item_name_static', - 'map_name_static', - 'do_action_static', - 'message_static', - 'message_texture_static', - 'nes_font_static', - 'nes_message_data_static', - 'ger_message_data_static', - 'fra_message_data_static', - 'staff_message_data_static', - 'map_grand_static', - 'map_48x85_static', - 'map_i_static', - 'code', - 'ovl_title', - 'ovl_select', - 'ovl_opening', - 'ovl_file_choose', - 'ovl_kaleido_scope', - 'ovl_player_actor', - 'ovl_map_mark_data', - 'ovl_En_Test', - 'ovl_Arms_Hook', - 'ovl_Arrow_Fire', - 'ovl_Arrow_Ice', - 'ovl_Arrow_Light', - 'ovl_Bg_Bdan_Objects', - 'ovl_Bg_Bdan_Switch', - 'ovl_Bg_Bom_Guard', - 'ovl_Bg_Bombwall', - 'ovl_Bg_Bowl_Wall', - 'ovl_Bg_Breakwall', - 'ovl_Bg_Ddan_Jd', - 'ovl_Bg_Ddan_Kd', - 'ovl_Bg_Dodoago', - 'ovl_Bg_Dy_Yoseizo', - 'ovl_Bg_Ganon_Otyuka', - 'ovl_Bg_Gate_Shutter', - 'ovl_Bg_Gjyo_Bridge', - 'ovl_Bg_Gnd_Darkmeiro', - 'ovl_Bg_Gnd_Firemeiro', - 'ovl_Bg_Gnd_Iceblock', - 'ovl_Bg_Gnd_Nisekabe', - 'ovl_Bg_Gnd_Soulmeiro', - 'ovl_Bg_Haka', - 'ovl_Bg_Haka_Gate', - 'ovl_Bg_Haka_Huta', - 'ovl_Bg_Haka_Megane', - 'ovl_Bg_Haka_MeganeBG', - 'ovl_Bg_Haka_Sgami', - 'ovl_Bg_Haka_Ship', - 'ovl_Bg_Haka_Trap', - 'ovl_Bg_Haka_Tubo', - 'ovl_Bg_Haka_Water', - 'ovl_Bg_Haka_Zou', - 'ovl_Bg_Heavy_Block', - 'ovl_Bg_Hidan_Curtain', - 'ovl_Bg_Hidan_Dalm', - 'ovl_Bg_Hidan_Firewall', - 'ovl_Bg_Hidan_Fslift', - 'ovl_Bg_Hidan_Fwbig', - 'ovl_Bg_Hidan_Hamstep', - 'ovl_Bg_Hidan_Hrock', - 'ovl_Bg_Hidan_Kousi', - 'ovl_Bg_Hidan_Kowarerukabe', - 'ovl_Bg_Hidan_Rock', - 'ovl_Bg_Hidan_Rsekizou', - 'ovl_Bg_Hidan_Sekizou', - 'ovl_Bg_Hidan_Sima', - 'ovl_Bg_Hidan_Syoku', - 'ovl_Bg_Ice_Objects', - 'ovl_Bg_Ice_Shelter', - 'ovl_Bg_Ice_Shutter', - 'ovl_Bg_Ice_Turara', - 'ovl_Bg_Ingate', - 'ovl_Bg_Jya_1flift', - 'ovl_Bg_Jya_Amishutter', - 'ovl_Bg_Jya_Bigmirror', - 'ovl_Bg_Jya_Block', - 'ovl_Bg_Jya_Bombchuiwa', - 'ovl_Bg_Jya_Bombiwa', - 'ovl_Bg_Jya_Cobra', - 'ovl_Bg_Jya_Goroiwa', - 'ovl_Bg_Jya_Haheniron', - 'ovl_Bg_Jya_Ironobj', - 'ovl_Bg_Jya_Kanaami', - 'ovl_Bg_Jya_Lift', - 'ovl_Bg_Jya_Megami', - 'ovl_Bg_Jya_Zurerukabe', - 'ovl_Bg_Menkuri_Eye', - 'ovl_Bg_Menkuri_Kaiten', - 'ovl_Bg_Menkuri_Nisekabe', - 'ovl_Bg_Mizu_Bwall', - 'ovl_Bg_Mizu_Movebg', - 'ovl_Bg_Mizu_Shutter', - 'ovl_Bg_Mizu_Uzu', - 'ovl_Bg_Mizu_Water', - 'ovl_Bg_Mjin', - 'ovl_Bg_Mori_Bigst', - 'ovl_Bg_Mori_Elevator', - 'ovl_Bg_Mori_Hashigo', - 'ovl_Bg_Mori_Hashira4', - 'ovl_Bg_Mori_Hineri', - 'ovl_Bg_Mori_Idomizu', - 'ovl_Bg_Mori_Kaitenkabe', - 'ovl_Bg_Mori_Rakkatenjo', - 'ovl_Bg_Po_Event', - 'ovl_Bg_Po_Syokudai', - 'ovl_Bg_Pushbox', - 'ovl_Bg_Relay_Objects', - 'ovl_Bg_Spot00_Break', - 'ovl_Bg_Spot00_Hanebasi', - 'ovl_Bg_Spot01_Fusya', - 'ovl_Bg_Spot01_Idohashira', - 'ovl_Bg_Spot01_Idomizu', - 'ovl_Bg_Spot01_Idosoko', - 'ovl_Bg_Spot01_Objects2', - 'ovl_Bg_Spot02_Objects', - 'ovl_Bg_Spot03_Taki', - 'ovl_Bg_Spot05_Soko', - 'ovl_Bg_Spot06_Objects', - 'ovl_Bg_Spot07_Taki', - 'ovl_Bg_Spot08_Bakudankabe', - 'ovl_Bg_Spot08_Iceblock', - 'ovl_Bg_Spot09_Obj', - 'ovl_Bg_Spot11_Bakudankabe', - 'ovl_Bg_Spot11_Oasis', - 'ovl_Bg_Spot12_Gate', - 'ovl_Bg_Spot12_Saku', - 'ovl_Bg_Spot15_Rrbox', - 'ovl_Bg_Spot15_Saku', - 'ovl_Bg_Spot16_Bombstone', - 'ovl_Bg_Spot16_Doughnut', - 'ovl_Bg_Spot17_Bakudankabe', - 'ovl_Bg_Spot17_Funen', - 'ovl_Bg_Spot18_Basket', - 'ovl_Bg_Spot18_Futa', - 'ovl_Bg_Spot18_Obj', - 'ovl_Bg_Spot18_Shutter', - 'ovl_Bg_Sst_Floor', - 'ovl_Bg_Toki_Hikari', - 'ovl_Bg_Toki_Swd', - 'ovl_Bg_Treemouth', - 'ovl_Bg_Umajump', - 'ovl_Bg_Vb_Sima', - 'ovl_Bg_Ydan_Hasi', - 'ovl_Bg_Ydan_Maruta', - 'ovl_Bg_Ydan_Sp', - 'ovl_Bg_Zg', - 'ovl_Boss_Dodongo', - 'ovl_Boss_Fd', - 'ovl_Boss_Fd2', - 'ovl_Boss_Ganon', - 'ovl_Boss_Ganon2', - 'ovl_Boss_Ganondrof', - 'ovl_Boss_Goma', - 'ovl_Boss_Mo', - 'ovl_Boss_Sst', - 'ovl_Boss_Tw', - 'ovl_Boss_Va', - 'ovl_Demo_6K', - 'ovl_Demo_Du', - 'ovl_Demo_Ec', - 'ovl_Demo_Effect', - 'ovl_Demo_Ext', - 'ovl_Demo_Geff', - 'ovl_Demo_Gj', - 'ovl_Demo_Go', - 'ovl_Demo_Gt', - 'ovl_Demo_Ik', - 'ovl_Demo_Im', - 'ovl_Demo_Kankyo', - 'ovl_Demo_Kekkai', - 'ovl_Demo_Sa', - 'ovl_Demo_Shd', - 'ovl_Demo_Tre_Lgt', - 'ovl_Door_Ana', - 'ovl_Door_Gerudo', - 'ovl_Door_Killer', - 'ovl_Door_Shutter', - 'ovl_Door_Toki', - 'ovl_Door_Warp1', - 'ovl_Efc_Erupc', - 'ovl_Eff_Dust', - 'ovl_Effect_Ss_Blast', - 'ovl_Effect_Ss_Bomb', - 'ovl_Effect_Ss_Bomb2', - 'ovl_Effect_Ss_Bubble', - 'ovl_Effect_Ss_D_Fire', - 'ovl_Effect_Ss_Dead_Db', - 'ovl_Effect_Ss_Dead_Dd', - 'ovl_Effect_Ss_Dead_Ds', - 'ovl_Effect_Ss_Dead_Sound', - 'ovl_Effect_Ss_Dt_Bubble', - 'ovl_Effect_Ss_Dust', - 'ovl_Effect_Ss_En_Fire', - 'ovl_Effect_Ss_En_Ice', - 'ovl_Effect_Ss_Extra', - 'ovl_Effect_Ss_Fcircle', - 'ovl_Effect_Ss_Fhg_Flash', - 'ovl_Effect_Ss_Fire_Tail', - 'ovl_Effect_Ss_G_Fire', - 'ovl_Effect_Ss_G_Magma', - 'ovl_Effect_Ss_G_Magma2', - 'ovl_Effect_Ss_G_Ripple', - 'ovl_Effect_Ss_G_Spk', - 'ovl_Effect_Ss_G_Splash', - 'ovl_Effect_Ss_Hahen', - 'ovl_Effect_Ss_HitMark', - 'ovl_Effect_Ss_Ice_Piece', - 'ovl_Effect_Ss_Ice_Smoke', - 'ovl_Effect_Ss_K_Fire', - 'ovl_Effect_Ss_Kakera', - 'ovl_Effect_Ss_KiraKira', - 'ovl_Effect_Ss_Lightning', - 'ovl_Effect_Ss_Sibuki', - 'ovl_Effect_Ss_Sibuki2', - 'ovl_Effect_Ss_Solder_Srch_Ball', - 'ovl_Effect_Ss_Stick', - 'ovl_Effect_Ss_Stone1', - 'ovl_Elf_Msg', - 'ovl_Elf_Msg2', - 'ovl_En_Am', - 'ovl_En_Ani', - 'ovl_En_Anubice', - 'ovl_En_Anubice_Fire', - 'ovl_En_Anubice_Tag', - 'ovl_En_Arow_Trap', - 'ovl_En_Arrow', - 'ovl_En_Attack_Niw', - 'ovl_En_Ba', - 'ovl_En_Bb', - 'ovl_En_Bdfire', - 'ovl_En_Bigokuta', - 'ovl_En_Bili', - 'ovl_En_Bird', - 'ovl_En_Blkobj', - 'ovl_En_Bom', - 'ovl_En_Bom_Bowl_Man', - 'ovl_En_Bom_Bowl_Pit', - 'ovl_En_Bom_Chu', - 'ovl_En_Bombf', - 'ovl_En_Boom', - 'ovl_En_Box', - 'ovl_En_Brob', - 'ovl_En_Bubble', - 'ovl_En_Butte', - 'ovl_En_Bw', - 'ovl_En_Bx', - 'ovl_En_Changer', - 'ovl_En_Clear_Tag', - 'ovl_En_Cow', - 'ovl_En_Crow', - 'ovl_En_Cs', - 'ovl_En_Daiku', - 'ovl_En_Daiku_Kakariko', - 'ovl_En_Dekubaba', - 'ovl_En_Dekunuts', - 'ovl_En_Dh', - 'ovl_En_Dha', - 'ovl_En_Diving_Game', - 'ovl_En_Dns', - 'ovl_En_Dnt_Demo', - 'ovl_En_Dnt_Jiji', - 'ovl_En_Dnt_Nomal', - 'ovl_En_Dodojr', - 'ovl_En_Dodongo', - 'ovl_En_Dog', - 'ovl_En_Door', - 'ovl_En_Ds', - 'ovl_En_Du', - 'ovl_En_Dy_Extra', - 'ovl_En_Eg', - 'ovl_En_Eiyer', - 'ovl_En_Elf', - 'ovl_En_Encount1', - 'ovl_En_Encount2', - 'ovl_En_Ex_Item', - 'ovl_En_Ex_Ruppy', - 'ovl_En_Fd', - 'ovl_En_Fd_Fire', - 'ovl_En_Fhg_Fire', - 'ovl_En_Fire_Rock', - 'ovl_En_Firefly', - 'ovl_En_Fish', - 'ovl_En_Floormas', - 'ovl_En_Fr', - 'ovl_En_Fu', - 'ovl_En_Fw', - 'ovl_En_Fz', - 'ovl_En_G_Switch', - 'ovl_En_Ganon_Mant', - 'ovl_En_Ganon_Organ', - 'ovl_En_Gb', - 'ovl_En_Ge1', - 'ovl_En_Ge2', - 'ovl_En_Ge3', - 'ovl_En_GeldB', - 'ovl_En_GirlA', - 'ovl_En_Gm', - 'ovl_En_Go', - 'ovl_En_Go2', - 'ovl_En_Goma', - 'ovl_En_Goroiwa', - 'ovl_En_Gs', - 'ovl_En_Guest', - 'ovl_En_Hata', - 'ovl_En_Heishi1', - 'ovl_En_Heishi2', - 'ovl_En_Heishi3', - 'ovl_En_Heishi4', - 'ovl_En_Hintnuts', - 'ovl_En_Holl', - 'ovl_En_Honotrap', - 'ovl_En_Horse', - 'ovl_En_Horse_Game_Check', - 'ovl_En_Horse_Ganon', - 'ovl_En_Horse_Link_Child', - 'ovl_En_Horse_Normal', - 'ovl_En_Horse_Zelda', - 'ovl_En_Hs', - 'ovl_En_Hs2', - 'ovl_En_Hy', - 'ovl_En_Ice_Hono', - 'ovl_En_Ik', - 'ovl_En_In', - 'ovl_En_Insect', - 'ovl_En_Ishi', - 'ovl_En_It', - 'ovl_En_Jj', - 'ovl_En_Js', - 'ovl_En_Jsjutan', - 'ovl_En_Kakasi', - 'ovl_En_Kakasi2', - 'ovl_En_Kakasi3', - 'ovl_En_Kanban', - 'ovl_En_Karebaba', - 'ovl_En_Ko', - 'ovl_En_Kusa', - 'ovl_En_Kz', - 'ovl_En_Light', - 'ovl_En_Lightbox', - 'ovl_En_M_Fire1', - 'ovl_En_M_Thunder', - 'ovl_En_Ma1', - 'ovl_En_Ma2', - 'ovl_En_Ma3', - 'ovl_En_Mag', - 'ovl_En_Mb', - 'ovl_En_Md', - 'ovl_En_Mk', - 'ovl_En_Mm', - 'ovl_En_Mm2', - 'ovl_En_Ms', - 'ovl_En_Mu', - 'ovl_En_Nb', - 'ovl_En_Niw', - 'ovl_En_Niw_Girl', - 'ovl_En_Niw_Lady', - 'ovl_En_Nutsball', - 'ovl_En_Nwc', - 'ovl_En_Ny', - 'ovl_En_OE2', - 'ovl_En_Okarina_Effect', - 'ovl_En_Okarina_Tag', - 'ovl_En_Okuta', - 'ovl_En_Ossan', - 'ovl_En_Owl', - 'ovl_En_Part', - 'ovl_En_Peehat', - 'ovl_En_Po_Desert', - 'ovl_En_Po_Field', - 'ovl_En_Po_Relay', - 'ovl_En_Po_Sisters', - 'ovl_En_Poh', - 'ovl_En_Pu_box', - 'ovl_En_Rd', - 'ovl_En_Reeba', - 'ovl_En_River_Sound', - 'ovl_En_Rl', - 'ovl_En_Rr', - 'ovl_En_Ru1', - 'ovl_En_Ru2', - 'ovl_En_Sa', - 'ovl_En_Sb', - 'ovl_En_Scene_Change', - 'ovl_En_Sda', - 'ovl_En_Shopnuts', - 'ovl_En_Si', - 'ovl_En_Siofuki', - 'ovl_En_Skb', - 'ovl_En_Skj', - 'ovl_En_Skjneedle', - 'ovl_En_Ssh', - 'ovl_En_St', - 'ovl_En_Sth', - 'ovl_En_Stream', - 'ovl_En_Sw', - 'ovl_En_Syateki_Itm', - 'ovl_En_Syateki_Man', - 'ovl_En_Syateki_Niw', - 'ovl_En_Ta', - 'ovl_En_Takara_Man', - 'ovl_En_Tana', - 'ovl_En_Tg', - 'ovl_En_Tite', - 'ovl_En_Tk', - 'ovl_En_Torch', - 'ovl_En_Torch2', - 'ovl_En_Toryo', - 'ovl_En_Tp', - 'ovl_En_Tr', - 'ovl_En_Trap', - 'ovl_En_Tubo_Trap', - 'ovl_En_Vali', - 'ovl_En_Vase', - 'ovl_En_Vb_Ball', - 'ovl_En_Viewer', - 'ovl_En_Vm', - 'ovl_En_Wall_Tubo', - 'ovl_En_Wallmas', - 'ovl_En_Weather_Tag', - 'ovl_En_Weiyer', - 'ovl_En_Wf', - 'ovl_En_Wonder_Item', - 'ovl_En_Wonder_Talk', - 'ovl_En_Wonder_Talk2', - 'ovl_En_Wood02', - 'ovl_En_Xc', - 'ovl_En_Yabusame_Mark', - 'ovl_En_Yukabyun', - 'ovl_En_Zf', - 'ovl_En_Zl1', - 'ovl_En_Zl2', - 'ovl_En_Zl3', - 'ovl_En_Zl4', - 'ovl_En_Zo', - 'ovl_En_fHG', - 'ovl_End_Title', - 'ovl_Fishing', - 'ovl_Item_B_Heart', - 'ovl_Item_Etcetera', - 'ovl_Item_Inbox', - 'ovl_Item_Ocarina', - 'ovl_Item_Shield', - 'ovl_Magic_Dark', - 'ovl_Magic_Fire', - 'ovl_Magic_Wind', - 'ovl_Mir_Ray', - 'ovl_Obj_Bean', - 'ovl_Obj_Blockstop', - 'ovl_Obj_Bombiwa', - 'ovl_Obj_Comb', - 'ovl_Obj_Dekujr', - 'ovl_Obj_Elevator', - 'ovl_Obj_Hamishi', - 'ovl_Obj_Hana', - 'ovl_Obj_Hsblock', - 'ovl_Obj_Ice_Poly', - 'ovl_Obj_Kibako', - 'ovl_Obj_Kibako2', - 'ovl_Obj_Lift', - 'ovl_Obj_Lightswitch', - 'ovl_Obj_Makekinsuta', - 'ovl_Obj_Makeoshihiki', - 'ovl_Obj_Mure', - 'ovl_Obj_Mure2', - 'ovl_Obj_Mure3', - 'ovl_Obj_Oshihiki', - 'ovl_Obj_Roomtimer', - 'ovl_Obj_Switch', - 'ovl_Obj_Syokudai', - 'ovl_Obj_Timeblock', - 'ovl_Obj_Tsubo', - 'ovl_Obj_Warp2block', - 'ovl_Object_Kankyo', - 'ovl_Oceff_Spot', - 'ovl_Oceff_Storm', - 'ovl_Oceff_Wipe', - 'ovl_Oceff_Wipe2', - 'ovl_Oceff_Wipe3', - 'ovl_Oceff_Wipe4', - 'ovl_Shot_Sun', - 'gameplay_keep', - 'gameplay_field_keep', - 'gameplay_dangeon_keep', - 'gameplay_object_exchange_static', - 'object_link_boy', - 'object_link_child', - 'object_box', - 'object_human', - 'object_okuta', - 'object_poh', - 'object_wallmaster', - 'object_dy_obj', - 'object_firefly', - 'object_dodongo', - 'object_fire', - 'object_niw', - 'object_tite', - 'object_reeba', - 'object_peehat', - 'object_kingdodongo', - 'object_horse', - 'object_zf', - 'object_goma', - 'object_zl1', - 'object_gol', - 'object_bubble', - 'object_dodojr', - 'object_torch2', - 'object_bl', - 'object_tp', - 'object_oA1', - 'object_st', - 'object_bw', - 'object_ei', - 'object_horse_normal', - 'object_oB1', - 'object_o_anime', - 'object_spot04_objects', - 'object_ddan_objects', - 'object_hidan_objects', - 'object_horse_ganon', - 'object_oA2', - 'object_spot00_objects', - 'object_mb', - 'object_bombf', - 'object_sk2', - 'object_oE1', - 'object_oE_anime', - 'object_oE2', - 'object_ydan_objects', - 'object_gnd', - 'object_am', - 'object_dekubaba', - 'object_oA3', - 'object_oA4', - 'object_oA5', - 'object_oA6', - 'object_oA7', - 'object_jj', - 'object_oA8', - 'object_oA9', - 'object_oB2', - 'object_oB3', - 'object_oB4', - 'object_horse_zelda', - 'object_opening_demo1', - 'object_warp1', - 'object_b_heart', - 'object_dekunuts', - 'object_oE3', - 'object_oE4', - 'object_menkuri_objects', - 'object_oE5', - 'object_oE6', - 'object_oE7', - 'object_oE8', - 'object_oE9', - 'object_oE10', - 'object_oE11', - 'object_oE12', - 'object_vali', - 'object_oA10', - 'object_oA11', - 'object_mizu_objects', - 'object_fhg', - 'object_ossan', - 'object_mori_hineri1', - 'object_Bb', - 'object_toki_objects', - 'object_yukabyun', - 'object_zl2', - 'object_mjin', - 'object_mjin_flash', - 'object_mjin_dark', - 'object_mjin_flame', - 'object_mjin_ice', - 'object_mjin_soul', - 'object_mjin_wind', - 'object_mjin_oka', - 'object_haka_objects', - 'object_spot06_objects', - 'object_ice_objects', - 'object_relay_objects', - 'object_mori_hineri1a', - 'object_mori_hineri2', - 'object_mori_hineri2a', - 'object_mori_objects', - 'object_mori_tex', - 'object_spot08_obj', - 'object_warp2', - 'object_hata', - 'object_bird', - 'object_wood02', - 'object_lightbox', - 'object_pu_box', - 'object_trap', - 'object_vase', - 'object_im', - 'object_ta', - 'object_tk', - 'object_xc', - 'object_vm', - 'object_bv', - 'object_hakach_objects', - 'object_efc_crystal_light', - 'object_efc_fire_ball', - 'object_efc_flash', - 'object_efc_lgt_shower', - 'object_efc_star_field', - 'object_god_lgt', - 'object_light_ring', - 'object_triforce_spot', - 'object_medal', - 'object_bdan_objects', - 'object_sd', - 'object_rd', - 'object_po_sisters', - 'object_heavy_object', - 'object_gndd', - 'object_fd', - 'object_du', - 'object_fw', - 'object_horse_link_child', - 'object_spot02_objects', - 'object_haka', - 'object_ru1', - 'object_syokudai', - 'object_fd2', - 'object_dh', - 'object_rl', - 'object_efc_tw', - 'object_demo_tre_lgt', - 'object_gi_key', - 'object_mir_ray', - 'object_brob', - 'object_gi_jewel', - 'object_spot09_obj', - 'object_spot18_obj', - 'object_bdoor', - 'object_spot17_obj', - 'object_shop_dungen', - 'object_nb', - 'object_mo', - 'object_sb', - 'object_gi_melody', - 'object_gi_heart', - 'object_gi_compass', - 'object_gi_bosskey', - 'object_gi_medal', - 'object_gi_nuts', - 'object_sa', - 'object_gi_hearts', - 'object_gi_arrowcase', - 'object_gi_bombpouch', - 'object_in', - 'object_tr', - 'object_spot16_obj', - 'object_oE1s', - 'object_oE4s', - 'object_os_anime', - 'object_gi_bottle', - 'object_gi_stick', - 'object_gi_map', - 'object_oF1d_map', - 'object_ru2', - 'object_gi_shield_1', - 'object_dekujr', - 'object_gi_magicpot', - 'object_gi_bomb_1', - 'object_oF1s', - 'object_ma2', - 'object_gi_purse', - 'object_hni', - 'object_tw', - 'object_rr', - 'object_bxa', - 'object_anubice', - 'object_gi_gerudo', - 'object_gi_arrow', - 'object_gi_bomb_2', - 'object_gi_egg', - 'object_gi_scale', - 'object_gi_shield_2', - 'object_gi_hookshot', - 'object_gi_ocarina', - 'object_gi_milk', - 'object_ma1', - 'object_ganon', - 'object_sst', - 'object_ny', - 'object_fr', - 'object_gi_pachinko', - 'object_gi_boomerang', - 'object_gi_bow', - 'object_gi_glasses', - 'object_gi_liquid', - 'object_ani', - 'object_demo_6k', - 'object_gi_shield_3', - 'object_gi_letter', - 'object_spot15_obj', - 'object_jya_obj', - 'object_gi_clothes', - 'object_gi_bean', - 'object_gi_fish', - 'object_gi_saw', - 'object_gi_hammer', - 'object_gi_grass', - 'object_gi_longsword', - 'object_spot01_objects', - 'object_md', - 'object_km1', - 'object_kw1', - 'object_zo', - 'object_kz', - 'object_umajump', - 'object_masterkokiri', - 'object_masterkokirihead', - 'object_mastergolon', - 'object_masterzoora', - 'object_aob', - 'object_ik', - 'object_ahg', - 'object_cne', - 'object_gi_niwatori', - 'object_skj', - 'object_gi_bottle_letter', - 'object_bji', - 'object_bba', - 'object_gi_ocarina_0', - 'object_ds', - 'object_ane', - 'object_boj', - 'object_spot03_object', - 'object_spot07_object', - 'object_fz', - 'object_bob', - 'object_ge1', - 'object_yabusame_point', - 'object_gi_boots_2', - 'object_gi_seed', - 'object_gnd_magic', - 'object_d_elevator', - 'object_d_hsblock', - 'object_d_lift', - 'object_mamenoki', - 'object_goroiwa', - 'object_toryo', - 'object_daiku', - 'object_nwc', - 'object_blkobj', - 'object_gm', - 'object_ms', - 'object_hs', - 'object_ingate', - 'object_lightswitch', - 'object_kusa', - 'object_tsubo', - 'object_gi_gloves', - 'object_gi_coin', - 'object_kanban', - 'object_gjyo_objects', - 'object_owl', - 'object_mk', - 'object_fu', - 'object_gi_ki_tan_mask', - 'object_gi_redead_mask', - 'object_gi_skj_mask', - 'object_gi_rabit_mask', - 'object_gi_truth_mask', - 'object_ganon_objects', - 'object_siofuki', - 'object_stream', - 'object_mm', - 'object_fa', - 'object_os', - 'object_gi_eye_lotion', - 'object_gi_powder', - 'object_gi_mushroom', - 'object_gi_ticketstone', - 'object_gi_brokensword', - 'object_js', - 'object_cs', - 'object_gi_prescription', - 'object_gi_bracelet', - 'object_gi_soldout', - 'object_gi_frog', - 'object_mag', - 'object_door_gerudo', - 'object_gt', - 'object_efc_erupc', - 'object_zl2_anime1', - 'object_zl2_anime2', - 'object_gi_golonmask', - 'object_gi_zoramask', - 'object_gi_gerudomask', - 'object_ganon2', - 'object_ka', - 'object_ts', - 'object_zg', - 'object_gi_hoverboots', - 'object_gi_m_arrow', - 'object_ds2', - 'object_ec', - 'object_fish', - 'object_gi_sutaru', - 'object_gi_goddess', - 'object_ssh', - 'object_bigokuta', - 'object_bg', - 'object_spot05_objects', - 'object_spot12_obj', - 'object_bombiwa', - 'object_hintnuts', - 'object_rs', - 'object_spot00_break', - 'object_gla', - 'object_shopnuts', - 'object_geldb', - 'object_gr', - 'object_dog', - 'object_jya_iron', - 'object_jya_door', - 'object_spot01_objects2', - 'object_spot11_obj', - 'object_kibako2', - 'object_dns', - 'object_dnk', - 'object_gi_fire', - 'object_gi_insect', - 'object_gi_butterfly', - 'object_gi_ghost', - 'object_gi_soul', - 'object_bowl', - 'object_po_field', - 'object_demo_kekkai', - 'object_efc_doughnut', - 'object_gi_dekupouch', - 'object_ganon_anime1', - 'object_ganon_anime2', - 'object_ganon_anime3', - 'object_gi_rupy', - 'object_spot01_matoya', - 'object_spot01_matoyab', - 'object_po_composer', - 'object_mu', - 'object_wf', - 'object_skb', - 'object_gj', - 'object_geff', - 'object_haka_door', - 'object_gs', - 'object_ps', - 'object_bwall', - 'object_crow', - 'object_cow', - 'object_cob', - 'object_gi_sword_1', - 'object_door_killer', - 'object_ouke_haka', - 'object_timeblock', - 'object_zl4', - 'g_pn_01', - 'g_pn_02', - 'g_pn_03', - 'g_pn_04', - 'g_pn_05', - 'g_pn_06', - 'g_pn_07', - 'g_pn_08', - 'g_pn_09', - 'g_pn_10', - 'g_pn_11', - 'g_pn_12', - 'g_pn_13', - 'g_pn_14', - 'g_pn_15', - 'g_pn_16', - 'g_pn_17', - 'g_pn_18', - 'g_pn_19', - 'g_pn_20', - 'g_pn_21', - 'g_pn_22', - 'g_pn_23', - 'g_pn_24', - 'g_pn_25', - 'g_pn_26', - 'g_pn_27', - 'g_pn_28', - 'g_pn_29', - 'g_pn_30', - 'g_pn_31', - 'g_pn_32', - 'g_pn_33', - 'g_pn_34', - 'g_pn_35', - 'g_pn_36', - 'g_pn_37', - 'g_pn_38', - 'g_pn_39', - 'g_pn_40', - 'g_pn_41', - 'g_pn_42', - 'g_pn_43', - 'g_pn_44', - 'g_pn_45', - 'g_pn_46', - 'g_pn_47', - 'g_pn_48', - 'g_pn_49', - 'g_pn_50', - 'g_pn_51', - 'g_pn_52', - 'g_pn_53', - 'g_pn_54', - 'g_pn_55', - 'g_pn_56', - 'g_pn_57', - 'z_select_static', - 'nintendo_rogo_static', - 'title_static', - 'parameter_static', - 'vr_fine0_static', - 'vr_fine0_pal_static', - 'vr_fine1_static', - 'vr_fine1_pal_static', - 'vr_fine2_static', - 'vr_fine2_pal_static', - 'vr_fine3_static', - 'vr_fine3_pal_static', - 'vr_cloud0_static', - 'vr_cloud0_pal_static', - 'vr_cloud1_static', - 'vr_cloud1_pal_static', - 'vr_cloud2_static', - 'vr_cloud2_pal_static', - 'vr_cloud3_static', - 'vr_cloud3_pal_static', - 'vr_holy0_static', - 'vr_holy0_pal_static', - 'vr_holy1_static', - 'vr_holy1_pal_static', - 'vr_MDVR_static', - 'vr_MDVR_pal_static', - 'vr_MNVR_static', - 'vr_MNVR_pal_static', - 'vr_RUVR_static', - 'vr_RUVR_pal_static', - 'vr_LHVR_static', - 'vr_LHVR_pal_static', - 'vr_KHVR_static', - 'vr_KHVR_pal_static', - 'vr_K3VR_static', - 'vr_K3VR_pal_static', - 'vr_K4VR_static', - 'vr_K4VR_pal_static', - 'vr_K5VR_static', - 'vr_K5VR_pal_static', - 'vr_SP1a_static', - 'vr_SP1a_pal_static', - 'vr_MLVR_static', - 'vr_MLVR_pal_static', - 'vr_KKRVR_static', - 'vr_KKRVR_pal_static', - 'vr_KR3VR_static', - 'vr_KR3VR_pal_static', - 'vr_IPVR_static', - 'vr_IPVR_pal_static', - 'vr_KSVR_static', - 'vr_KSVR_pal_static', - 'vr_GLVR_static', - 'vr_GLVR_pal_static', - 'vr_ZRVR_static', - 'vr_ZRVR_pal_static', - 'vr_DGVR_static', - 'vr_DGVR_pal_static', - 'vr_ALVR_static', - 'vr_ALVR_pal_static', - 'vr_NSVR_static', - 'vr_NSVR_pal_static', - 'vr_LBVR_static', - 'vr_LBVR_pal_static', - 'vr_TTVR_static', - 'vr_TTVR_pal_static', - 'vr_FCVR_static', - 'vr_FCVR_pal_static', - 'elf_message_field', - 'elf_message_ydan', - 'ydan_scene', -'ydan_room_0', -'ydan_room_1', -'ydan_room_2', -'ydan_room_3', -'ydan_room_4', -'ydan_room_5', -'ydan_room_6', -'ydan_room_7', -'ydan_room_8', -'ydan_room_9', -'ydan_room_10', -'ydan_room_11', -'ddan_scene', -'ddan_room_0', -'ddan_room_1', -'ddan_room_2', -'ddan_room_3', -'ddan_room_4', -'ddan_room_5', -'ddan_room_6', -'ddan_room_7', -'ddan_room_8', -'ddan_room_9', -'ddan_room_10', -'ddan_room_11', -'ddan_room_12', -'ddan_room_13', -'ddan_room_14', -'ddan_room_15', -'ddan_room_16', -'bdan_scene', -'bdan_room_0', -'bdan_room_1', -'bdan_room_2', -'bdan_room_3', -'bdan_room_4', -'bdan_room_5', -'bdan_room_6', -'bdan_room_7', -'bdan_room_8', -'bdan_room_9', -'bdan_room_10', -'bdan_room_11', -'bdan_room_12', -'bdan_room_13', -'bdan_room_14', -'bdan_room_15', -'Bmori1_scene', -'Bmori1_room_0', -'Bmori1_room_1', -'Bmori1_room_2', -'Bmori1_room_3', -'Bmori1_room_4', -'Bmori1_room_5', -'Bmori1_room_6', -'Bmori1_room_7', -'Bmori1_room_8', -'Bmori1_room_9', -'Bmori1_room_10', -'Bmori1_room_11', -'Bmori1_room_12', -'Bmori1_room_13', -'Bmori1_room_14', -'Bmori1_room_15', -'Bmori1_room_16', -'Bmori1_room_17', -'Bmori1_room_18', -'Bmori1_room_19', -'Bmori1_room_20', -'Bmori1_room_21', -'Bmori1_room_22', -'HIDAN_scene', -'HIDAN_room_0', -'HIDAN_room_1', -'HIDAN_room_2', -'HIDAN_room_3', -'HIDAN_room_4', -'HIDAN_room_5', -'HIDAN_room_6', -'HIDAN_room_7', -'HIDAN_room_8', -'HIDAN_room_9', -'HIDAN_room_10', -'HIDAN_room_11', -'HIDAN_room_12', -'HIDAN_room_13', -'HIDAN_room_14', -'HIDAN_room_15', -'HIDAN_room_16', -'HIDAN_room_17', -'HIDAN_room_18', -'HIDAN_room_19', -'HIDAN_room_20', -'HIDAN_room_21', -'HIDAN_room_22', -'HIDAN_room_23', -'HIDAN_room_24', -'HIDAN_room_25', -'HIDAN_room_26', -'MIZUsin_scene', -'MIZUsin_room_0', -'MIZUsin_room_1', -'MIZUsin_room_2', -'MIZUsin_room_3', -'MIZUsin_room_4', -'MIZUsin_room_5', -'MIZUsin_room_6', -'MIZUsin_room_7', -'MIZUsin_room_8', -'MIZUsin_room_9', -'MIZUsin_room_10', -'MIZUsin_room_11', -'MIZUsin_room_12', -'MIZUsin_room_13', -'MIZUsin_room_14', -'MIZUsin_room_15', -'MIZUsin_room_16', -'MIZUsin_room_17', -'MIZUsin_room_18', -'MIZUsin_room_19', -'MIZUsin_room_20', -'MIZUsin_room_21', -'MIZUsin_room_22', -'jyasinzou_scene', -'jyasinzou_room_0', -'jyasinzou_room_1', -'jyasinzou_room_2', -'jyasinzou_room_3', -'jyasinzou_room_4', -'jyasinzou_room_5', -'jyasinzou_room_6', -'jyasinzou_room_7', -'jyasinzou_room_8', -'jyasinzou_room_9', -'jyasinzou_room_10', -'jyasinzou_room_11', -'jyasinzou_room_12', -'jyasinzou_room_13', -'jyasinzou_room_14', -'jyasinzou_room_15', -'jyasinzou_room_16', -'jyasinzou_room_17', -'jyasinzou_room_18', -'jyasinzou_room_19', -'jyasinzou_room_20', -'jyasinzou_room_21', -'jyasinzou_room_22', -'jyasinzou_room_23', -'jyasinzou_room_24', -'jyasinzou_room_25', -'jyasinzou_room_26', -'jyasinzou_room_27', -'jyasinzou_room_28', -'HAKAdan_scene', -'HAKAdan_room_0', -'HAKAdan_room_1', -'HAKAdan_room_2', -'HAKAdan_room_3', -'HAKAdan_room_4', -'HAKAdan_room_5', -'HAKAdan_room_6', -'HAKAdan_room_7', -'HAKAdan_room_8', -'HAKAdan_room_9', -'HAKAdan_room_10', -'HAKAdan_room_11', -'HAKAdan_room_12', -'HAKAdan_room_13', -'HAKAdan_room_14', -'HAKAdan_room_15', -'HAKAdan_room_16', -'HAKAdan_room_17', -'HAKAdan_room_18', -'HAKAdan_room_19', -'HAKAdan_room_20', -'HAKAdan_room_21', -'HAKAdan_room_22', -'HAKAdanCH_scene', -'HAKAdanCH_room_0', -'HAKAdanCH_room_1', -'HAKAdanCH_room_2', -'HAKAdanCH_room_3', -'HAKAdanCH_room_4', -'HAKAdanCH_room_5', -'HAKAdanCH_room_6', -'ice_doukutu_scene', -'ice_doukutu_room_0', -'ice_doukutu_room_1', -'ice_doukutu_room_2', -'ice_doukutu_room_3', -'ice_doukutu_room_4', -'ice_doukutu_room_5', -'ice_doukutu_room_6', -'ice_doukutu_room_7', -'ice_doukutu_room_8', -'ice_doukutu_room_9', -'ice_doukutu_room_10', -'ice_doukutu_room_11', -'men_scene', -'men_room_0', -'men_room_1', -'men_room_2', -'men_room_3', -'men_room_4', -'men_room_5', -'men_room_6', -'men_room_7', -'men_room_8', -'men_room_9', -'men_room_10', -'ganontika_scene', -'ganontika_room_0', -'ganontika_room_1', -'ganontika_room_2', -'ganontika_room_3', -'ganontika_room_4', -'ganontika_room_5', -'ganontika_room_6', -'ganontika_room_7', -'ganontika_room_8', -'ganontika_room_9', -'ganontika_room_10', -'ganontika_room_11', -'ganontika_room_12', -'ganontika_room_13', -'ganontika_room_14', -'ganontika_room_15', -'ganontika_room_16', -'ganontika_room_17', -'ganontika_room_18', -'ganontika_room_19', -'spot00_scene', -'spot00_room_0', -'spot01_scene', -'spot01_room_0', -'spot02_scene', -'spot02_room_0', -'spot02_room_1', -'spot03_scene', -'spot03_room_0', -'spot03_room_1', -'spot04_scene', -'spot04_room_0', -'spot04_room_1', -'spot04_room_2', -'spot05_scene', -'spot05_room_0', -'spot06_scene', -'spot06_room_0', -'spot07_scene', -'spot07_room_0', -'spot07_room_1', -'spot08_scene', -'spot08_room_0', -'spot09_scene', -'spot09_room_0', -'spot10_scene', -'spot10_room_0', -'spot10_room_1', -'spot10_room_2', -'spot10_room_3', -'spot10_room_4', -'spot10_room_5', -'spot10_room_6', -'spot10_room_7', -'spot10_room_8', -'spot10_room_9', -'spot11_scene', -'spot11_room_0', -'spot12_scene', -'spot12_room_0', -'spot12_room_1', -'spot13_scene', -'spot13_room_0', -'spot13_room_1', -'spot15_scene', -'spot15_room_0', -'spot16_scene', -'spot16_room_0', -'spot17_scene', -'spot17_room_0', -'spot17_room_1', -'spot18_scene', -'spot18_room_0', -'spot18_room_1', -'spot18_room_2', -'spot18_room_3', -'market_day_scene', -'market_day_room_0', -'market_night_scene', -'market_night_room_0', -'kenjyanoma_scene', -'kenjyanoma_room_0', -'tokinoma_scene', -'tokinoma_room_0', -'tokinoma_room_1', -'link_home_scene', -'link_home_room_0', -'kokiri_shop_scene', -'kokiri_shop_room_0', -'kokiri_home_scene', -'kokiri_home_room_0', -'kakusiana_scene', -'kakusiana_room_0', -'kakusiana_room_1', -'kakusiana_room_2', -'kakusiana_room_3', -'kakusiana_room_4', -'kakusiana_room_5', -'kakusiana_room_6', -'kakusiana_room_7', -'kakusiana_room_8', -'kakusiana_room_9', -'kakusiana_room_10', -'kakusiana_room_11', -'kakusiana_room_12', -'kakusiana_room_13', -'entra_scene', -'entra_room_0', -'moribossroom_scene', -'moribossroom_room_0', -'moribossroom_room_1', -'syatekijyou_scene', -'syatekijyou_room_0', -'shop1_scene', -'shop1_room_0', -'hairal_niwa_scene', -'hairal_niwa_room_0', -'ganon_tou_scene', -'ganon_tou_room_0', -'market_alley_scene', -'market_alley_room_0', -'spot20_scene', -'spot20_room_0', -'market_ruins_scene', -'market_ruins_room_0', -'entra_n_scene', -'entra_n_room_0', -'enrui_scene', -'enrui_room_0', -'market_alley_n_scene', -'market_alley_n_room_0', -'hiral_demo_scene', -'hiral_demo_room_0', -'kokiri_home3_scene', -'kokiri_home3_room_0', -'malon_stable_scene', -'malon_stable_room_0', -'kakariko_scene', -'kakariko_room_0', -'bdan_boss_scene', -'bdan_boss_room_0', -'bdan_boss_room_1', -'FIRE_bs_scene', -'FIRE_bs_room_0', -'FIRE_bs_room_1', -'hut_scene', -'hut_room_0', -'daiyousei_izumi_scene', -'daiyousei_izumi_room_0', -'hakaana_scene', -'hakaana_room_0', -'yousei_izumi_tate_scene', -'yousei_izumi_tate_room_0', -'yousei_izumi_yoko_scene', -'yousei_izumi_yoko_room_0', -'golon_scene', -'golon_room_0', -'zoora_scene', -'zoora_room_0', -'drag_scene', -'drag_room_0', -'alley_shop_scene', -'alley_shop_room_0', -'night_shop_scene', -'night_shop_room_0', -'impa_scene', -'impa_room_0', -'labo_scene', -'labo_room_0', -'tent_scene', -'tent_room_0', -'nakaniwa_scene', -'nakaniwa_room_0', -'ddan_boss_scene', -'ddan_boss_room_0', -'ddan_boss_room_1', -'ydan_boss_scene', -'ydan_boss_room_0', -'ydan_boss_room_1', -'HAKAdan_bs_scene', -'HAKAdan_bs_room_0', -'HAKAdan_bs_room_1', -'MIZUsin_bs_scene', -'MIZUsin_bs_room_0', -'MIZUsin_bs_room_1', -'ganon_scene', -'ganon_room_0', -'ganon_room_1', -'ganon_room_2', -'ganon_room_3', -'ganon_room_4', -'ganon_room_5', -'ganon_room_6', -'ganon_room_7', -'ganon_room_8', -'ganon_room_9', -'ganon_boss_scene', -'ganon_boss_room_0', -'jyasinboss_scene', -'jyasinboss_room_0', -'jyasinboss_room_1', -'jyasinboss_room_2', -'jyasinboss_room_3', -'kokiri_home4_scene', -'kokiri_home4_room_0', -'kokiri_home5_scene', -'kokiri_home5_room_0', -'ganon_final_scene', -'ganon_final_room_0', -'kakariko3_scene', -'kakariko3_room_0', -'hakasitarelay_scene', -'hakasitarelay_room_0', -'hakasitarelay_room_1', -'hakasitarelay_room_2', -'hakasitarelay_room_3', -'hakasitarelay_room_4', -'hakasitarelay_room_5', -'hakasitarelay_room_6', -'shrine_scene', -'shrine_room_0', -'turibori_scene', -'turibori_room_0', -'shrine_n_scene', -'shrine_n_room_0', -'shrine_r_scene', -'shrine_r_room_0', -'hakaana2_scene', -'hakaana2_room_0', -'gerudoway_scene', -'gerudoway_room_0', -'gerudoway_room_1', -'gerudoway_room_2', -'gerudoway_room_3', -'gerudoway_room_4', -'gerudoway_room_5', -'hairal_niwa_n_scene', -'hairal_niwa_n_room_0', -'bowling_scene', -'bowling_room_0', -'hakaana_ouke_scene', -'hakaana_ouke_room_0', -'hakaana_ouke_room_1', -'hakaana_ouke_room_2', -'hylia_labo_scene', -'hylia_labo_room_0', -'souko_scene', -'souko_room_0', -'souko_room_1', -'souko_room_2', -'miharigoya_scene', -'miharigoya_room_0', -'mahouya_scene', -'mahouya_room_0', -'takaraya_scene', -'takaraya_room_0', -'takaraya_room_1', -'takaraya_room_2', -'takaraya_room_3', -'takaraya_room_4', -'takaraya_room_5', -'takaraya_room_6', -'ganon_sonogo_scene', -'ganon_sonogo_room_0', -'ganon_sonogo_room_1', -'ganon_sonogo_room_2', -'ganon_sonogo_room_3', -'ganon_sonogo_room_4', -'ganon_demo_scene', -'ganon_demo_room_0', -'face_shop_scene', -'face_shop_room_0', -'kinsuta_scene', -'kinsuta_room_0', -'ganontikasonogo_scene', -'ganontikasonogo_room_0', -'ganontikasonogo_room_1', - 'bump_texture_static', - 'anime_model_1_static', - 'anime_model_2_static', - 'anime_model_3_static', - 'anime_model_4_static', - 'anime_model_5_static', - 'anime_model_6_static', - 'anime_texture_1_static', - 'anime_texture_2_static', - 'anime_texture_3_static', - 'anime_texture_4_static', - 'anime_texture_5_static', - 'anime_texture_6_static', - 'softsprite_matrix_static', -] - -romData = None - - -def initialize_worker(rom_data): - global romData - romData = rom_data - -def read_uint32_be(offset): - return struct.unpack('>I', romData[offset:offset+4])[0] - -def write_output_file(name, offset, size): - try: - with open(name, 'wb') as f: - f.write(romData[offset:offset+size]) - except IOError: - print('failed to write file ' + name) - -def ExtractFunc(i): - filename = 'baserom/' + FILE_NAMES[i] - entryOffset = FILE_TABLE_OFFSET + 16 * i - - virtStart = read_uint32_be(entryOffset + 0) - virtEnd = read_uint32_be(entryOffset + 4) - physStart = read_uint32_be(entryOffset + 8) - physEnd = read_uint32_be(entryOffset + 12) - - if physEnd == 0: # uncompressed - compressed = False - size = virtEnd - virtStart - else: # compressed - compressed = True - size = physEnd - physStart - - print('extracting ' + filename + " (0x%08X, 0x%08X)" % (virtStart, virtEnd)) - write_output_file(filename, physStart, size) - if compressed: - os.system('tools/yaz0 -d ' + filename + ' ' + filename) - -##################################################################### - -def main(): - try: - os.mkdir('baserom') - except: - pass - - # read baserom data - try: - with open(ROM_FILE_NAME, 'rb') as f: - rom_data = f.read() - except IOError: - print('failed to read ' + ROM_FILE_NAME) - sys.exit(1) - - # extract files - num_cores = cpu_count() - print("Extracting baserom with " + str(num_cores) + " CPU cores.") - with Pool(num_cores, initialize_worker, (rom_data,)) as p: - p.map(ExtractFunc, range(len(FILE_NAMES))) - -if __name__ == "__main__": - main() diff --git a/OTRExporter/rom_chooser.py b/OTRExporter/rom_chooser.py new file mode 100644 index 000000000..5c5f875d0 --- /dev/null +++ b/OTRExporter/rom_chooser.py @@ -0,0 +1,37 @@ +import os, sys, glob + +from rom_info import Z64Rom + +def chooseROM(): + roms = [] + + for file in glob.glob("*.z64"): + if Z64Rom.isValidRom(file): + roms.append(file) + + if not (roms): + print("Error: No roms located, place one in the OTRExporter directory", file=os.sys.stderr) + sys.exit(1) + + if (len(roms) == 1): + return roms[0] + + print(str(len(roms))+ " roms found, please select one by pressing 1-"+str(len(roms))) + + for i in range(len(roms)): + print(str(i+1)+ ". " + roms[i]) + + while(1): + try: + selection = int(input()) + except: + print("Bad input. Try again with the number keys.") + continue + + if (selection < 1 or selection > len(roms)): + print("Bad input. Try again.") + continue + + else: break + + return roms[selection - 1] diff --git a/OTRExporter/rom_info.py b/OTRExporter/rom_info.py new file mode 100644 index 000000000..3edc8b0f9 --- /dev/null +++ b/OTRExporter/rom_info.py @@ -0,0 +1,87 @@ +from enum import Enum +from tabnanny import check +import struct + +class Checksums(Enum): + OOT_NTSC_10 = "EC7011B7" + OOT_NTSC_11 = "D43DA81F" + OOT_NTSC_12 = "693BA2AE" + OOT_PAL_10 = "B044B569" + OOT_PAL_11 = "B2055FBD" + OOT_NTSC_JP_GC_CE = "F7F52DB8" + OOT_NTSC_JP_GC = "F611F4BA" + OOT_NTSC_US_GC = "F3DD35BA" + OOT_PAL_GC = "09465AC3" + OOT_NTSC_JP_MQ = "F43B45BA" + OOT_NTSC_US_MQ = "F034001A" + OOT_PAL_MQ = "1D4136F3" + OOT_PAL_GC_DBG1 = "871E1C92" + OOT_PAL_GC_DBG2 = "87121EFE" + OOT_PAL_GC_MQ_DBG = "917D18F6" + OOT_IQUE_TW = "3D81FB3E" + OOT_IQUE_CN = "B1E1E07B" + OOT_UNKNOWN = "FFFFFFFF" + + @classmethod + def has_value(self, value): + return value in self._value2member_map_ + +class RomVersion: + def __init__(self, file_table_path, file_table_off, xml_ver): + self.file_table_off = file_table_off + self.xml_ver = xml_ver + with open(file_table_path, 'r') as f: + self.file_table = [line.strip('\n') for line in f] + +ROM_INFO_TABLE = dict() +ROM_INFO_TABLE[Checksums.OOT_PAL_GC] = RomVersion("CFG/filelists/gamecube_pal.txt", 0x7170, "GC_NMQ_PAL_F") +ROM_INFO_TABLE[Checksums.OOT_PAL_GC_DBG1] = RomVersion("CFG/filelists/dbg.txt", 0x12F70, "GC_NMQ_D") + +class RomDmaEntry: + def __init__(self, rom, i): + + off = rom.version.file_table_off + 16 * i + + (self.virtStart, \ + self.virtEnd, \ + self.physStart, \ + self.physEnd) = struct.unpack('>IIII', rom.rom_data[off:off+4*4]) + + self.compressed = self.physEnd != 0 + self.size = self.physEnd - self.physStart \ + if self.compressed \ + else self.virtEnd - self.virtStart + self.name = rom.version.file_table[i] + + +class Z64Rom: + def __init__(self, file_path): + self.file_path = file_path + with open(file_path, 'rb') as f: + self.rom_data = f.read() + + self.is_valid = len(self.rom_data) > 20 * 1024 * 1024 + + if not self.is_valid: + return + + # get checkum + checksum_str = self.rom_data[16:16+4].hex().upper() + self.checksum = Checksums(checksum_str) if Checksums.has_value(checksum_str) else Checksums.OOT_UNKNOWN + + if self.checksum == Checksums.OOT_UNKNOWN: + self.is_valid = False + return + + # get rom version + self.version = ROM_INFO_TABLE[self.checksum] + + def getDmaEntryByIndex(self, i): + return RomDmaEntry(self, i) + + def readDmaEntry(self, entry): + return self.rom_data[entry.physStart:entry.physStart + entry.size] + + @staticmethod + def isValidRom(rom_path): + return Z64Rom(rom_path).is_valid diff --git a/OTRGui/src/game/game.cpp b/OTRGui/src/game/game.cpp index 88bd7201f..e995b339c 100644 --- a/OTRGui/src/game/game.cpp +++ b/OTRGui/src/game/game.cpp @@ -67,13 +67,13 @@ void OTRGame::init(){ mat.shader = shader; } - if(fs::exists("soh.exe") && !fs::exists("oot.otr")) { + if((fs::exists("soh.exe") || fs::exists("soh.elf")) && !fs::exists("oot.otr")) { hide_second_btn = true; sohFolder = "."; } } -void ExtractRom() +void ExtractRom() { WriteResult result; @@ -220,4 +220,4 @@ void setCurrentStep(const std::string& step) { void OTRGame::exit(){ -} \ No newline at end of file +} diff --git a/README.md b/README.md index 1cbe0cd3f..3ce3fb21b 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ If you still cannot get the tool to work, join our [Discord Server](https://disc ### Running The Ship of Harkinian -Launch the game. If the window immediately closes, or if there are visual artifacts, you may have selected the wrong rom in the OTRGui tool. +Launch the game. If the window immediately closes, or if there are visual artifacts, you may have selected the wrong rom in the OTRGui tool. Currently, DirectX 11 and OpenGL is supported. Change the renderer by opening the `shipofharkinian.ini` configuration file in notepad and add `sdl` to `gfx backend` for OpenGL or leave blank for DirectX. diff --git a/ZAPDTR/ExporterTest/CollisionExporter.cpp b/ZAPDTR/ExporterTest/CollisionExporter.cpp index e00f5c1b0..4ab8a62cd 100644 --- a/ZAPDTR/ExporterTest/CollisionExporter.cpp +++ b/ZAPDTR/ExporterTest/CollisionExporter.cpp @@ -1,6 +1,6 @@ #include "CollisionExporter.h" -void ExporterExample_Collision::Save(ZResource* res, [[maybe_unused]] fs::path outPath, +void ExporterExample_Collision::Save(ZResource* res, [[maybe_unused]] const fs::path& outPath, BinaryWriter* writer) { ZCollisionHeader* col = (ZCollisionHeader*)res; diff --git a/ZAPDTR/ExporterTest/CollisionExporter.h b/ZAPDTR/ExporterTest/CollisionExporter.h index 5f48e6557..1dc50634e 100644 --- a/ZAPDTR/ExporterTest/CollisionExporter.h +++ b/ZAPDTR/ExporterTest/CollisionExporter.h @@ -6,5 +6,5 @@ class ExporterExample_Collision : public ZResourceExporter { public: - void Save(ZResource* res, fs::path outPath, BinaryWriter* writer) override; + void Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) override; }; \ No newline at end of file diff --git a/ZAPDTR/ExporterTest/RoomExporter.cpp b/ZAPDTR/ExporterTest/RoomExporter.cpp index 6c5552d8f..bc7ef3727 100644 --- a/ZAPDTR/ExporterTest/RoomExporter.cpp +++ b/ZAPDTR/ExporterTest/RoomExporter.cpp @@ -20,7 +20,7 @@ #include "ZRoom/Commands/SetTimeSettings.h" #include "ZRoom/Commands/SetWind.h" -void ExporterExample_Room::Save(ZResource* res, fs::path outPath, BinaryWriter* writer) +void ExporterExample_Room::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) { ZRoom* room = dynamic_cast(res); diff --git a/ZAPDTR/ExporterTest/RoomExporter.h b/ZAPDTR/ExporterTest/RoomExporter.h index ee531dc87..d8f7eae01 100644 --- a/ZAPDTR/ExporterTest/RoomExporter.h +++ b/ZAPDTR/ExporterTest/RoomExporter.h @@ -6,5 +6,5 @@ class ExporterExample_Room : public ZResourceExporter { public: - void Save(ZResource* res, fs::path outPath, BinaryWriter* writer) override; + void Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) override; }; \ No newline at end of file diff --git a/ZAPDTR/ExporterTest/TextureExporter.cpp b/ZAPDTR/ExporterTest/TextureExporter.cpp index 6488bed3a..58d0964d3 100644 --- a/ZAPDTR/ExporterTest/TextureExporter.cpp +++ b/ZAPDTR/ExporterTest/TextureExporter.cpp @@ -1,7 +1,7 @@ #include "TextureExporter.h" #include "../ZAPD/ZFile.h" -void ExporterExample_Texture::Save(ZResource* res, [[maybe_unused]] fs::path outPath, +void ExporterExample_Texture::Save(ZResource* res, [[maybe_unused]] const fs::path& outPath, BinaryWriter* writer) { ZTexture* tex = (ZTexture*)res; diff --git a/ZAPDTR/ExporterTest/TextureExporter.h b/ZAPDTR/ExporterTest/TextureExporter.h index 41c4e79be..f3922cac1 100644 --- a/ZAPDTR/ExporterTest/TextureExporter.h +++ b/ZAPDTR/ExporterTest/TextureExporter.h @@ -7,5 +7,5 @@ class ExporterExample_Texture : public ZResourceExporter { public: - void Save(ZResource* res, fs::path outPath, BinaryWriter* writer) override; + void Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) override; }; \ No newline at end of file diff --git a/ZAPDTR/Makefile b/ZAPDTR/Makefile index 2b47a8039..13f0dce20 100644 --- a/ZAPDTR/Makefile +++ b/ZAPDTR/Makefile @@ -44,7 +44,8 @@ ifneq ($(DEPRECATION_ON),0) endif # CXXFLAGS += -DTEXTURE_DEBUG -LDFLAGS := -lm -ldl -lpng +LDFLAGS := -lm -ldl -lpng \ + -L../external -L../libultraship -lz -lbz2 -pthread -lpulse -lultraship -lstorm -lSDL2 -lGLEW -lGL -lX11 # Use LLD if available. Set LLD=0 to not use it ifeq ($(shell command -v ld.lld >/dev/null 2>&1; echo $$?),0) @@ -59,9 +60,9 @@ UNAME := $(shell uname) UNAMEM := $(shell uname -m) ifneq ($(UNAME), Darwin) LDFLAGS += -Wl,-export-dynamic -lstdc++fs - EXPORTERS := -Wl,--whole-archive ExporterTest/ExporterTest.a -Wl,--no-whole-archive + EXPORTERS := -Wl,--whole-archive ../OTRExporter/OTRExporter/OTRExporter.a -Wl,--no-whole-archive else - EXPORTERS := -Wl,-force_load ExporterTest/ExporterTest.a + EXPORTERS := -Wl,-force_load ../OTRExporter/OTRExporter/OTRExporter.a ifeq ($(UNAMEM),arm64) ifeq ($(shell brew list libpng > /dev/null 2>&1; echo $$?),0) LDFLAGS += -L $(shell brew --prefix)/lib diff --git a/ZAPDTR/ZAPD/Main.cpp b/ZAPDTR/ZAPD/Main.cpp index dd53b9c67..65a65fea6 100644 --- a/ZAPDTR/ZAPD/Main.cpp +++ b/ZAPDTR/ZAPD/Main.cpp @@ -10,7 +10,7 @@ #include "ZFile.h" #include "ZTexture.h" -#if !defined(_MSC_VER) && !defined(__CYGWIN__) +#ifdef __linux__ #include #include #include @@ -28,6 +28,31 @@ //extern const char gBuildHash[]; const char gBuildHash[] = ""; +// LINUX_TODO: remove, those are because of soh <-> lus dependency problems +float divisor_num = 0.0f; + +extern "C" void Audio_SetGameVolume(int player_id, float volume) +{ + +} + + +extern "C" int ResourceMgr_OTRSigCheck(char* imgData) +{ + +} + +void DebugConsole_SaveCVars() +{ + +} + +void DebugConsole_LoadCVars() +{ + +} + + bool Parse(const fs::path& xmlFilePath, const fs::path& basePath, const fs::path& outPath, ZFileMode fileMode, int workerID); @@ -38,7 +63,7 @@ int ExtractFunc(int workerID, int fileListSize, std::string fileListItem, ZFileM volatile int numWorkersLeft = 0; -#if !defined(_MSC_VER) && !defined(__CYGWIN__) +#ifdef __linux__ #define ARRAY_COUNT(arr) (sizeof(arr) / sizeof(arr[0])) void ErrorHandler(int sig) { @@ -196,7 +221,7 @@ int main(int argc, char* argv[]) } else if (arg == "-eh") // Enable Error Handler { - #if !defined(_MSC_VER) && !defined(__CYGWIN__) +#ifdef __linux__ signal(SIGSEGV, ErrorHandler); signal(SIGABRT, ErrorHandler); #else @@ -302,7 +327,7 @@ int main(int argc, char* argv[]) ctpl::thread_pool pool(num_threads / 2); bool parseSuccessful; - + auto start = std::chrono::steady_clock::now(); int fileListSize = fileList.size(); Globals::Instance->singleThreaded = false; @@ -453,6 +478,7 @@ int ExtractFunc(int workerID, int fileListSize, std::string fileListItem, ZFileM numWorkersLeft--; } + return 0; } bool Parse(const fs::path& xmlFilePath, const fs::path& basePath, const fs::path& outPath, diff --git a/ZAPDTR/ZAPD/OutputFormatter.cpp b/ZAPDTR/ZAPD/OutputFormatter.cpp index 7fac434b2..362ef98fc 100644 --- a/ZAPDTR/ZAPD/OutputFormatter.cpp +++ b/ZAPDTR/ZAPD/OutputFormatter.cpp @@ -96,7 +96,7 @@ int OutputFormatter::Write(const std::string& buf) return Write(buf.data(), buf.size()); } -__declspec(thread) OutputFormatter* OutputFormatter::Instance; +thread_local OutputFormatter* OutputFormatter::Instance; int OutputFormatter::WriteStatic(const char* buf, int count) { diff --git a/ZAPDTR/ZAPD/OutputFormatter.h b/ZAPDTR/ZAPD/OutputFormatter.h index f008df2cb..03abfdb96 100644 --- a/ZAPDTR/ZAPD/OutputFormatter.h +++ b/ZAPDTR/ZAPD/OutputFormatter.h @@ -25,7 +25,7 @@ private: void Flush(); - static __declspec(thread) OutputFormatter* Instance; + static thread_local OutputFormatter* Instance; static int WriteStatic(const char* buf, int count); public: diff --git a/ZAPDTR/ZAPD/ZDisplayList.cpp b/ZAPDTR/ZAPD/ZDisplayList.cpp index 93269b65e..406245b33 100644 --- a/ZAPDTR/ZAPD/ZDisplayList.cpp +++ b/ZAPDTR/ZAPD/ZDisplayList.cpp @@ -15,6 +15,124 @@ #include "WarningHandler.h" #include "gfxd.h" + +#define G_MDSFT_ALPHACOMPARE 0 +#define G_MDSFT_ZSRCSEL 2 +#define G_MDSFT_RENDERMODE 3 +#define G_MDSFT_BLENDER 16 + +#define G_RM_FOG_SHADE_A 0xC8000000 +#define G_RM_FOG_PRIM_A 0xC4000000 +#define G_RM_PASS 0x0C080000 +#define G_RM_AA_ZB_OPA_SURF 0x442078 +#define G_RM_AA_ZB_OPA_SURF2 0x112078 +#define G_RM_AA_ZB_XLU_SURF 0x4049D8 +#define G_RM_AA_ZB_XLU_SURF2 0x1049D8 +#define G_RM_AA_ZB_OPA_DECAL 0x442D58 +#define G_RM_AA_ZB_OPA_DECAL2 0x112D58 +#define G_RM_AA_ZB_XLU_DECAL 0x404DD8 +#define G_RM_AA_ZB_XLU_DECAL2 0x104DD8 +#define G_RM_AA_ZB_OPA_INTER 0x442478 +#define G_RM_AA_ZB_OPA_INTER2 0x112478 +#define G_RM_AA_ZB_XLU_INTER 0x4045D8 +#define G_RM_AA_ZB_XLU_INTER2 0x1045D8 +#define G_RM_AA_ZB_XLU_LINE 0x407858 +#define G_RM_AA_ZB_XLU_LINE2 0x107858 +#define G_RM_AA_ZB_DEC_LINE 0x407F58 +#define G_RM_AA_ZB_DEC_LINE2 0x107F58 +#define G_RM_AA_ZB_TEX_EDGE 0x443078 +#define G_RM_AA_ZB_TEX_EDGE2 0x113078 +#define G_RM_AA_ZB_TEX_INTER 0x443478 +#define G_RM_AA_ZB_TEX_INTER2 0x113478 +#define G_RM_AA_ZB_SUB_SURF 0x442878 +#define G_RM_AA_ZB_SUB_SURF2 0x112278 +#define G_RM_AA_ZB_PCL_SURF 0x40007B +#define G_RM_AA_ZB_PCL_SURF2 0x10007B +#define G_RM_AA_ZB_OPA_TERR 0x402078 +#define G_RM_AA_ZB_OPA_TERR2 0x102078 +#define G_RM_AA_ZB_TEX_TERR 0x403078 +#define G_RM_AA_ZB_TEX_TERR2 0x103078 +#define G_RM_AA_ZB_SUB_TERR 0x402278 +#define G_RM_AA_ZB_SUB_TERR2 0x102278 +#define G_RM_RA_ZB_OPA_SURF 0x442038 +#define G_RM_RA_ZB_OPA_SURF2 0x112038 +#define G_RM_RA_ZB_OPA_DECAL 0x442D18 +#define G_RM_RA_ZB_OPA_DECAL2 0x112D18 +#define G_RM_RA_ZB_OPA_INTER 0x442438 +#define G_RM_RA_ZB_OPA_INTER2 0x112438 +#define G_RM_AA_OPA_SURF 0x442048 +#define G_RM_AA_OPA_SURF2 0x112048 +#define G_RM_AA_XLU_SURF 0x4041C8 +#define G_RM_AA_XLU_SURF2 0x1041C8 +#define G_RM_AA_XLU_LINE 0x407048 +#define G_RM_AA_XLU_LINE2 0x107048 +#define G_RM_AA_DEC_LINE 0x407248 +#define G_RM_AA_DEC_LINE2 0x107248 +#define G_RM_AA_TEX_EDGE 0x443048 +#define G_RM_AA_TEX_EDGE2 0x113048 +#define G_RM_AA_SUB_SURF 0x442248 +#define G_RM_AA_SUB_SURF2 0x112248 +#define G_RM_AA_PCL_SURF 0x40004B +#define G_RM_AA_PCL_SURF2 0x10004B +#define G_RM_AA_OPA_TERR 0x402048 +#define G_RM_AA_OPA_TERR2 0x102048 +#define G_RM_AA_TEX_TERR 0x403048 +#define G_RM_AA_TEX_TERR2 0x103048 +#define G_RM_AA_SUB_TERR 0x402248 +#define G_RM_AA_SUB_TERR2 0x102248 +#define G_RM_RA_OPA_SURF 0x442008 +#define G_RM_RA_OPA_SURF2 0x112008 +#define G_RM_ZB_OPA_SURF 0x442230 +#define G_RM_ZB_OPA_SURF2 0x112230 +#define G_RM_ZB_XLU_SURF 0x404A50 +#define G_RM_ZB_XLU_SURF2 0x104A50 +#define G_RM_ZB_OPA_DECAL 0x442E10 +#define G_RM_ZB_OPA_DECAL2 0x112E10 +#define G_RM_ZB_XLU_DECAL 0x404E50 +#define G_RM_ZB_XLU_DECAL2 0x104E50 +#define G_RM_ZB_CLD_SURF 0x404B50 +#define G_RM_ZB_CLD_SURF2 0x104B50 +#define G_RM_ZB_OVL_SURF 0x404F50 +#define G_RM_ZB_OVL_SURF2 0x104F50 +#define G_RM_ZB_PCL_SURF 0x0C080233 +#define G_RM_ZB_PCL_SURF2 0x03020233 +#define G_RM_OPA_SURF 0x0C084000 +#define G_RM_OPA_SURF2 0x03024000 +#define G_RM_XLU_SURF 0x00404200 +#define G_RM_XLU_SURF2 0x00104240 +#define G_RM_CLD_SURF 0x00404340 +#define G_RM_CLD_SURF2 0x00104340 +#define G_RM_TEX_EDGE 0x0C087008 +#define G_RM_TEX_EDGE2 0x03027008 +#define G_RM_PCL_SURF 0x0C084203 +#define G_RM_PCL_SURF2 0x03024203 +#define G_RM_ADD 0x04484340 +#define G_RM_ADD2 0x01124340 +#define G_RM_NOOP 0x00000000 +#define G_RM_NOOP2 0x00000000 +#define G_RM_VISCVG 0x0C844040 +#define G_RM_VISCVG2 0x03214040 +#define G_RM_OPA_CI 0x0C080000 +#define G_RM_OPA_CI2 0x03020000 + +#define AA_EN 0x8 +#define Z_CMP 0x10 +#define Z_UPD 0x20 +#define IM_RD 0x40 +#define CLR_ON_CVG 0x80 +#define CVG_DST_CLAMP 0 +#define CVG_DST_WRAP 0x100 +#define CVG_DST_FULL 0x200 +#define CVG_DST_SAVE 0x300 +#define ZMODE_OPA 0 +#define ZMODE_INTER 0x400 +#define ZMODE_XLU 0x800 +#define ZMODE_DEC 0xc00 +#define CVG_X_ALPHA 0x1000 +#define ALPHA_CVG_SEL 0x2000 +#define FORCE_BL 0x4000 +#define TEX_EDGE 0x0000 + REGISTER_ZFILENODE(DList, ZDisplayList); ZDisplayList::ZDisplayList(ZFile* nParent) : ZResource(nParent) diff --git a/ZAPDTR/ZAPD/ZDisplayList.h b/ZAPDTR/ZAPD/ZDisplayList.h index 96808315d..f3828cc79 100644 --- a/ZAPDTR/ZAPD/ZDisplayList.h +++ b/ZAPDTR/ZAPD/ZDisplayList.h @@ -166,122 +166,6 @@ enum class OoTSegments FrameBuffer = 16, }; -#define G_MDSFT_ALPHACOMPARE 0 -#define G_MDSFT_ZSRCSEL 2 -#define G_MDSFT_RENDERMODE 3 -#define G_MDSFT_BLENDER 16 - -#define G_RM_FOG_SHADE_A 0xC8000000 -#define G_RM_FOG_PRIM_A 0xC4000000 -#define G_RM_PASS 0x0C080000 -#define G_RM_AA_ZB_OPA_SURF 0x442078 -#define G_RM_AA_ZB_OPA_SURF2 0x112078 -#define G_RM_AA_ZB_XLU_SURF 0x4049D8 -#define G_RM_AA_ZB_XLU_SURF2 0x1049D8 -#define G_RM_AA_ZB_OPA_DECAL 0x442D58 -#define G_RM_AA_ZB_OPA_DECAL2 0x112D58 -#define G_RM_AA_ZB_XLU_DECAL 0x404DD8 -#define G_RM_AA_ZB_XLU_DECAL2 0x104DD8 -#define G_RM_AA_ZB_OPA_INTER 0x442478 -#define G_RM_AA_ZB_OPA_INTER2 0x112478 -#define G_RM_AA_ZB_XLU_INTER 0x4045D8 -#define G_RM_AA_ZB_XLU_INTER2 0x1045D8 -#define G_RM_AA_ZB_XLU_LINE 0x407858 -#define G_RM_AA_ZB_XLU_LINE2 0x107858 -#define G_RM_AA_ZB_DEC_LINE 0x407F58 -#define G_RM_AA_ZB_DEC_LINE2 0x107F58 -#define G_RM_AA_ZB_TEX_EDGE 0x443078 -#define G_RM_AA_ZB_TEX_EDGE2 0x113078 -#define G_RM_AA_ZB_TEX_INTER 0x443478 -#define G_RM_AA_ZB_TEX_INTER2 0x113478 -#define G_RM_AA_ZB_SUB_SURF 0x442878 -#define G_RM_AA_ZB_SUB_SURF2 0x112278 -#define G_RM_AA_ZB_PCL_SURF 0x40007B -#define G_RM_AA_ZB_PCL_SURF2 0x10007B -#define G_RM_AA_ZB_OPA_TERR 0x402078 -#define G_RM_AA_ZB_OPA_TERR2 0x102078 -#define G_RM_AA_ZB_TEX_TERR 0x403078 -#define G_RM_AA_ZB_TEX_TERR2 0x103078 -#define G_RM_AA_ZB_SUB_TERR 0x402278 -#define G_RM_AA_ZB_SUB_TERR2 0x102278 -#define G_RM_RA_ZB_OPA_SURF 0x442038 -#define G_RM_RA_ZB_OPA_SURF2 0x112038 -#define G_RM_RA_ZB_OPA_DECAL 0x442D18 -#define G_RM_RA_ZB_OPA_DECAL2 0x112D18 -#define G_RM_RA_ZB_OPA_INTER 0x442438 -#define G_RM_RA_ZB_OPA_INTER2 0x112438 -#define G_RM_AA_OPA_SURF 0x442048 -#define G_RM_AA_OPA_SURF2 0x112048 -#define G_RM_AA_XLU_SURF 0x4041C8 -#define G_RM_AA_XLU_SURF2 0x1041C8 -#define G_RM_AA_XLU_LINE 0x407048 -#define G_RM_AA_XLU_LINE2 0x107048 -#define G_RM_AA_DEC_LINE 0x407248 -#define G_RM_AA_DEC_LINE2 0x107248 -#define G_RM_AA_TEX_EDGE 0x443048 -#define G_RM_AA_TEX_EDGE2 0x113048 -#define G_RM_AA_SUB_SURF 0x442248 -#define G_RM_AA_SUB_SURF2 0x112248 -#define G_RM_AA_PCL_SURF 0x40004B -#define G_RM_AA_PCL_SURF2 0x10004B -#define G_RM_AA_OPA_TERR 0x402048 -#define G_RM_AA_OPA_TERR2 0x102048 -#define G_RM_AA_TEX_TERR 0x403048 -#define G_RM_AA_TEX_TERR2 0x103048 -#define G_RM_AA_SUB_TERR 0x402248 -#define G_RM_AA_SUB_TERR2 0x102248 -#define G_RM_RA_OPA_SURF 0x442008 -#define G_RM_RA_OPA_SURF2 0x112008 -#define G_RM_ZB_OPA_SURF 0x442230 -#define G_RM_ZB_OPA_SURF2 0x112230 -#define G_RM_ZB_XLU_SURF 0x404A50 -#define G_RM_ZB_XLU_SURF2 0x104A50 -#define G_RM_ZB_OPA_DECAL 0x442E10 -#define G_RM_ZB_OPA_DECAL2 0x112E10 -#define G_RM_ZB_XLU_DECAL 0x404E50 -#define G_RM_ZB_XLU_DECAL2 0x104E50 -#define G_RM_ZB_CLD_SURF 0x404B50 -#define G_RM_ZB_CLD_SURF2 0x104B50 -#define G_RM_ZB_OVL_SURF 0x404F50 -#define G_RM_ZB_OVL_SURF2 0x104F50 -#define G_RM_ZB_PCL_SURF 0x0C080233 -#define G_RM_ZB_PCL_SURF2 0x03020233 -#define G_RM_OPA_SURF 0x0C084000 -#define G_RM_OPA_SURF2 0x03024000 -#define G_RM_XLU_SURF 0x00404200 -#define G_RM_XLU_SURF2 0x00104240 -#define G_RM_CLD_SURF 0x00404340 -#define G_RM_CLD_SURF2 0x00104340 -#define G_RM_TEX_EDGE 0x0C087008 -#define G_RM_TEX_EDGE2 0x03027008 -#define G_RM_PCL_SURF 0x0C084203 -#define G_RM_PCL_SURF2 0x03024203 -#define G_RM_ADD 0x04484340 -#define G_RM_ADD2 0x01124340 -#define G_RM_NOOP 0x00000000 -#define G_RM_NOOP2 0x00000000 -#define G_RM_VISCVG 0x0C844040 -#define G_RM_VISCVG2 0x03214040 -#define G_RM_OPA_CI 0x0C080000 -#define G_RM_OPA_CI2 0x03020000 - -#define AA_EN 0x8 -#define Z_CMP 0x10 -#define Z_UPD 0x20 -#define IM_RD 0x40 -#define CLR_ON_CVG 0x80 -#define CVG_DST_CLAMP 0 -#define CVG_DST_WRAP 0x100 -#define CVG_DST_FULL 0x200 -#define CVG_DST_SAVE 0x300 -#define ZMODE_OPA 0 -#define ZMODE_INTER 0x400 -#define ZMODE_XLU 0x800 -#define ZMODE_DEC 0xc00 -#define CVG_X_ALPHA 0x1000 -#define ALPHA_CVG_SEL 0x2000 -#define FORCE_BL 0x4000 -#define TEX_EDGE 0x0000 class ZDisplayList : public ZResource { diff --git a/ZAPDTR/ZAPD/ZLimb.h b/ZAPDTR/ZAPD/ZLimb.h index 53a414329..5de5276e9 100644 --- a/ZAPDTR/ZAPD/ZLimb.h +++ b/ZAPDTR/ZAPD/ZLimb.h @@ -25,19 +25,19 @@ public: ZLimbSkinType skinSegmentType = ZLimbSkinType::SkinType_0; // Skin only segptr_t skinSegment = 0; // Skin only - Struct_800A5E28 segmentStruct; // Skin only + Struct_800A5E28 segmentStruct = {0}; // Skin only // Legacy only - float legTransX, legTransY, legTransZ; // Vec3f - uint16_t rotX, rotY, rotZ; // Vec3s - segptr_t childPtr; // LegacyLimb* - segptr_t siblingPtr; // LegacyLimb* + float legTransX = 0, legTransY = 0, legTransZ = 0; // Vec3f + uint16_t rotX = 0, rotY = 0, rotZ = 0; // Vec3s + segptr_t childPtr = 0; // LegacyLimb* + segptr_t siblingPtr = 0; // LegacyLimb* segptr_t dListPtr = 0; segptr_t dList2Ptr = 0; // LOD and Curve Only - int16_t transX, transY, transZ; - uint8_t childIndex, siblingIndex; + int16_t transX = 0, transY = 0, transZ = 0; + uint8_t childIndex = 0, siblingIndex = 0; ZLimb(ZFile* nParent); diff --git a/ZAPDTR/ZAPDUtils/Utils/BitConverter.h b/ZAPDTR/ZAPDUtils/Utils/BitConverter.h index e672b97c2..708d4b537 100644 --- a/ZAPDTR/ZAPDUtils/Utils/BitConverter.h +++ b/ZAPDTR/ZAPDUtils/Utils/BitConverter.h @@ -3,6 +3,7 @@ #include #include #include +#include class BitConverter { diff --git a/ZAPDTR/ZAPDUtils/Utils/Directory.h b/ZAPDTR/ZAPDUtils/Utils/Directory.h index b1ce49699..1ced139be 100644 --- a/ZAPDTR/ZAPDUtils/Utils/Directory.h +++ b/ZAPDTR/ZAPDUtils/Utils/Directory.h @@ -52,7 +52,7 @@ public: for (auto& p : fs::recursive_directory_iterator(dir)) { if (!p.is_directory()) - lst.push_back(p.path().string()); + lst.push_back(p.path().generic_string()); } } diff --git a/ZAPDTR/ZAPDUtils/Utils/StringHelper.cpp b/ZAPDTR/ZAPDUtils/Utils/StringHelper.cpp index e2b646fd9..070fffa63 100644 --- a/ZAPDTR/ZAPDUtils/Utils/StringHelper.cpp +++ b/ZAPDTR/ZAPDUtils/Utils/StringHelper.cpp @@ -3,6 +3,10 @@ #pragma optimize("2", on) #define _CRT_SECURE_NO_WARNINGS +#ifndef _MSC_VER +#define vsprintf_s vsprintf +#endif + std::vector StringHelper::Split(std::string s, const std::string& delimiter) { std::vector result; @@ -44,7 +48,7 @@ std::string StringHelper::Replace(std::string str, const std::string& from, while (start_pos != std::string::npos) { - str.replace(start_pos, from.length(), to); + str.replace(start_pos, from.length(), to); start_pos = str.find(from); } diff --git a/libultraship/.gitignore b/libultraship/.gitignore index da0a72409..1cf3c3325 100644 --- a/libultraship/.gitignore +++ b/libultraship/.gitignore @@ -353,4 +353,6 @@ MigrationBackup/ .ionide/ !libultraship/Lib/** -libultraship/DebugObj/* \ No newline at end of file +libultraship/DebugObj/* +build/ +libultraship.a \ No newline at end of file diff --git a/libultraship/Makefile b/libultraship/Makefile index d7aafd65f..d6789db0b 100644 --- a/libultraship/Makefile +++ b/libultraship/Makefile @@ -1,15 +1,78 @@ # Only used for standalone compilation, usually inherits these from the main makefile -CXXFLAGS ?= -Wall -Wextra -O2 -g -std=c++17 + +CXX := g++ +CC := gcc +AR := ar +FORMAT := clang-format-11 + +ASAN ?= 0 +DEBUG ?= 1 +OPTFLAGS ?= -O0 +LTO ?= 0 + +WARN := -Wall -Wextra -Werror \ + -Wno-unused-variable \ + -Wno-unused-parameter \ + -Wno-unused-function \ + -Wno-parentheses \ + -Wno-narrowing \ + -Wno-missing-field-initializers + +CXXFLAGS := $(WARN) -std=c++20 -D_GNU_SOURCE -DENABLE_OPENGL -DSPDLOG_ACTIVE_LEVEL=0 -m32 +CFLAGS := $(WARN) -std=c99 -D_GNU_SOURCE -DENABLE_OPENGL -DSPDLOG_ACTIVE_LEVEL=0 -m32 +CPPFLAGS := -MMD + +ifneq ($(DEBUG),0) + CXXFLAGS += -g -D_DEBUG + CFLAGS += -g -D_DEBUG +endif + +ifneq ($(ASAN),0) + CXXFLAGS += -fsanitize=address + CFLAGS += -fsanitize=address +endif + +ifneq ($(LTO),0) + CXXFLAGS += -flto + CFLAGS += -flto +endif SRC_DIRS := $(shell find -type d -not -path "*build*") -CPP_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.cpp)) -H_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.h)) -O_FILES := $(foreach f,$(CPP_FILES:.cpp=.o),build/$f) -LIB := otrlib.a +CXX_FILES := \ + $(shell find libultraship/Factories -name *.cpp) \ + $(shell find libultraship/Lib/Fast3D -name *.cpp) \ + $(shell find libultraship -maxdepth 1 -name *.cpp) \ + $(shell find libultraship/Lib/ImGui -maxdepth 1 -name *.cpp) \ + libultraship/Lib/ImGui/backends/imgui_impl_opengl3.cpp \ + libultraship/Lib/ImGui/backends/imgui_impl_sdl.cpp \ + libultraship/Lib/StrHash64.cpp \ + libultraship/Lib/tinyxml2/tinyxml2.cpp + +C_FILES := \ + libultraship/mixer.c \ + libultraship/Lib/stb/stb_impl.c + +FMT_FILES := $(shell find libultraship/ -type f \( -name *.cpp -o -name *.h \) -a -not -path "libultraship/Lib/*") + +O_FILES := \ + $(CXX_FILES:%.cpp=build/%.o) \ + $(C_FILES:%.c=build/%.o) + +D_FILES := $(O_FILES:%.o=%.d) + +LIB := libultraship.a + +INC_DIRS := $(addprefix -I, \ + ../ZAPDTR/ZAPDUtils \ + libultraship/Lib/Fast3D/U64 \ + libultraship/Lib/spdlog \ + libultraship/Lib/spdlog/include \ + libultraship \ +) # create build directories -$(shell mkdir -p $(foreach dir,$(SRC_DIRS),build/$(dir))) +$(shell mkdir -p $(SRC_DIRS:%=build/%)) all: $(LIB) @@ -17,12 +80,17 @@ clean: rm -rf build $(LIB) format: - clang-format-11 -i $(CPP_FILES) $(H_FILES) + $(FORMAT) -i $(FMT_FILES) .PHONY: all clean format build/%.o: %.cpp - $(CXX) $(CXXFLAGS) $(OPTFLAGS) -I ./ -I ../ZAPD/ZAPD -I ../ZAPD/ZAPDUtils -I ../../ZAPD/lib/tinyxml2 -I otrlib/Lib/spdlog/include -c $(OUTPUT_OPTION) $< + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPTFLAGS) $(INC_DIRS) -c $< -o $@ + +build/%.o: %.c + $(CC) $(CFLAGS) $(CPPFLAGS) $(OPTFLAGS) $(INC_DIRS) -c $< -o $@ $(LIB): $(O_FILES) $(AR) rcs $@ $^ + +-include $(D_FILES) \ No newline at end of file diff --git a/libultraship/libultraship/Animation.cpp b/libultraship/libultraship/Animation.cpp index be2decad3..f9a6e2ee8 100644 --- a/libultraship/libultraship/Animation.cpp +++ b/libultraship/libultraship/Animation.cpp @@ -21,7 +21,7 @@ void Ship::AnimationV0::ParseFileBinary(BinaryReader* reader, Resource* res) uint32_t rotIndCnt = reader->ReadUInt32(); anim->rotationIndices.reserve(rotIndCnt); - for (int i = 0; i < rotIndCnt; i++) + for (size_t i = 0; i < rotIndCnt; i++) { uint16_t x = reader->ReadUInt16(); uint16_t y = reader->ReadUInt16(); diff --git a/libultraship/libultraship/Archive.cpp b/libultraship/libultraship/Archive.cpp index 41c6649f8..1e8f8d597 100644 --- a/libultraship/libultraship/Archive.cpp +++ b/libultraship/libultraship/Archive.cpp @@ -7,7 +7,7 @@ #include namespace Ship { - Archive::Archive(const std::string& MainPath, bool enableWriting) : Archive(MainPath, "", enableWriting) + Archive::Archive(const std::string& MainPath, bool enableWriting) : Archive(MainPath, "", enableWriting) { mainMPQ = nullptr; } @@ -28,7 +28,7 @@ namespace Ship { std::shared_ptr Archive::CreateArchive(const std::string& archivePath, int fileCapacity) { - Archive* archive = new Archive(archivePath, true); + auto archive = std::make_shared(archivePath, true); TCHAR* t_filename = new TCHAR[archivePath.size() + 1]; t_filename[archivePath.size()] = 0; @@ -37,10 +37,15 @@ namespace Ship { bool success = SFileCreateArchive(t_filename, MPQ_CREATE_LISTFILE | MPQ_CREATE_ATTRIBUTES | MPQ_CREATE_ARCHIVE_V2, fileCapacity, &archive->mainMPQ); int error = GetLastError(); - if (success) { + delete[] t_filename; + + if (success) + { archive->mpqHandles[archivePath] = archive->mainMPQ; - return std::make_shared(*archive); - } else { + return archive; + } + else + { SPDLOG_ERROR("({}) We tried to create an archive, but it has fallen and cannot get up."); return nullptr; } @@ -49,11 +54,16 @@ namespace Ship { std::shared_ptr Archive::LoadFile(const std::string& filePath, bool includeParent, std::shared_ptr FileToLoad) { HANDLE fileHandle = NULL; + if (FileToLoad == nullptr) { + FileToLoad = std::make_shared(); + FileToLoad->path = filePath; + } + if (!SFileOpenFileEx(mainMPQ, filePath.c_str(), 0, &fileHandle)) { SPDLOG_ERROR("({}) Failed to open file {} from mpq archive {}", GetLastError(), filePath.c_str(), MainPath.c_str()); std::unique_lock Lock(FileToLoad->FileLoadMutex); FileToLoad->bHasLoadError = true; - return nullptr; + return FileToLoad; } DWORD dwFileSize = SFileGetFileSize(fileHandle, 0); @@ -67,18 +77,13 @@ namespace Ship { } std::unique_lock Lock(FileToLoad->FileLoadMutex); FileToLoad->bHasLoadError = true; - return nullptr; + return FileToLoad; } if (!SFileCloseFile(fileHandle)) { SPDLOG_ERROR("({}) Failed to close file {} from mpq archive {}", GetLastError(), filePath.c_str(), MainPath.c_str()); } - if (FileToLoad == nullptr) { - FileToLoad = std::make_shared(); - FileToLoad->path = filePath; - } - std::unique_lock Lock(FileToLoad->FileLoadMutex); FileToLoad->parent = includeParent ? shared_from_this() : nullptr; FileToLoad->buffer = fileData; @@ -92,6 +97,11 @@ namespace Ship { HANDLE fileHandle = NULL; HANDLE mpqHandle = NULL; + if (FileToLoad == nullptr) { + FileToLoad = std::make_shared(); + FileToLoad->path = filePath; + } + for(auto [path, handle] : mpqHandles) { if (SFileOpenFileEx(mpqHandle, filePath.c_str(), 0, &fileHandle)) { std::unique_lock Lock(FileToLoad->FileLoadMutex); @@ -116,18 +126,13 @@ namespace Ship { } std::unique_lock Lock(FileToLoad->FileLoadMutex); FileToLoad->bHasLoadError = true; - return nullptr; + return FileToLoad; } if (!SFileCloseFile(fileHandle)) { SPDLOG_ERROR("({}) Failed to close file {} from mpq archive {}", GetLastError(), filePath.c_str(), MainPath.c_str()); } - if (FileToLoad == nullptr) { - FileToLoad = std::make_shared(); - FileToLoad->path = filePath; - } - std::unique_lock Lock(FileToLoad->FileLoadMutex); FileToLoad->parent = includeParent ? shared_from_this() : nullptr; FileToLoad->buffer = fileData; @@ -139,13 +144,16 @@ namespace Ship { bool Archive::AddFile(const std::string& path, uintptr_t fileData, DWORD dwFileSize) { HANDLE hFile; - +#ifdef _WIN32 SYSTEMTIME sysTime; GetSystemTime(&sysTime); FILETIME t; SystemTimeToFileTime(&sysTime, &t); ULONGLONG stupidHack = static_cast(t.dwHighDateTime) << (sizeof(t.dwHighDateTime) * 8) | t.dwLowDateTime; - +#else + time_t stupidHack; + time(&stupidHack); +#endif if (!SFileCreateFile(mainMPQ, path.c_str(), stupidHack, dwFileSize, 0, MPQ_FILE_COMPRESS, &hFile)) { SPDLOG_ERROR("({}) Failed to create file of {} bytes {} in archive {}", GetLastError(), dwFileSize, path.c_str(), MainPath.c_str()); return false; @@ -181,7 +189,7 @@ namespace Ship { SPDLOG_ERROR("({}) Failed to remove file {} in archive {}", GetLastError(), path.c_str(), MainPath.c_str()); return false; } - + return true; } @@ -201,7 +209,7 @@ namespace Ship { SFILE_FIND_DATA findContext; HANDLE hFind; - + hFind = SFileFindFirstFile(mainMPQ, searchMask.c_str(), &findContext, nullptr); //if (hFind && GetLastError() != ERROR_NO_MORE_FILES) { if (hFind != nullptr) { @@ -245,7 +253,7 @@ namespace Ship { auto start = std::chrono::steady_clock::now(); auto lst = ListFiles(filename); - + for (const auto& item : lst) { if (item.cFileName == filename) { result = true; @@ -267,7 +275,7 @@ namespace Ship { return LoadMainMPQ(enableWriting, genCRCMap) && LoadPatchMPQs(); } - bool Archive::Unload() + bool Archive::Unload() { bool success = true; for (const auto& mpqHandle : mpqHandles) { @@ -302,11 +310,16 @@ namespace Ship { bool Archive::LoadMainMPQ(bool enableWriting, bool genCRCMap) { HANDLE mpqHandle = NULL; +#ifdef _WIN32 + std::wstring wfullPath = std::filesystem::absolute(MainPath).wstring(); +#endif std::string fullPath = std::filesystem::absolute(MainPath).string(); - std::wstring wFileName = std::filesystem::absolute(MainPath).wstring(); - - if (!SFileOpenArchive(wFileName.c_str(), 0, enableWriting ? 0 : MPQ_OPEN_READ_ONLY, &mpqHandle)) { +#ifdef _WIN32 + if (!SFileOpenArchive(wfullPath.c_str(), 0, enableWriting ? 0 : MPQ_OPEN_READ_ONLY, &mpqHandle)) { +#else + if (!SFileOpenArchive(fullPath.c_str(), 0, enableWriting ? 0 : MPQ_OPEN_READ_ONLY, &mpqHandle)) { +#endif SPDLOG_ERROR("({}) Failed to open main mpq file {}.", GetLastError(), fullPath.c_str()); return false; } @@ -340,12 +353,19 @@ namespace Ship { std::wstring wPath = std::filesystem::absolute(path).wstring(); +#ifdef _WIN32 if (!SFileOpenArchive(wPath.c_str(), 0, MPQ_OPEN_READ_ONLY, &patchHandle)) { +#else + if (!SFileOpenArchive(fullPath.c_str(), 0, MPQ_OPEN_READ_ONLY, &patchHandle)) { +#endif SPDLOG_ERROR("({}) Failed to open patch mpq file {} while applying to {}.", GetLastError(), path.c_str(), MainPath.c_str()); return false; } - +#ifdef _WIN32 if (!SFileOpenPatchArchive(mainMPQ, wPath.c_str(), "", 0)) { +#else + if (!SFileOpenPatchArchive(mainMPQ, fullPath.c_str(), "", 0)) { +#endif SPDLOG_ERROR("({}) Failed to apply patch mpq file {} to main mpq {}.", GetLastError(), path.c_str(), MainPath.c_str()); return false; } diff --git a/libultraship/libultraship/Array.cpp b/libultraship/libultraship/Array.cpp index f256903bf..fdd522c11 100644 --- a/libultraship/libultraship/Array.cpp +++ b/libultraship/libultraship/Array.cpp @@ -51,6 +51,8 @@ namespace Ship data.u16 = reader->ReadUInt16(); break; // OTRTODO: IMPLEMENT OTHER TYPES! + default: + break; } arr->scalars.push_back(data); diff --git a/libultraship/libultraship/ConfigFile.h b/libultraship/libultraship/ConfigFile.h index dcf2a0e4a..17e3720f8 100644 --- a/libultraship/libultraship/ConfigFile.h +++ b/libultraship/libultraship/ConfigFile.h @@ -29,9 +29,9 @@ namespace Ship { bool CreateDefaultConfig(); private: - mINI::INIFile File; mINI::INIStructure Val; std::weak_ptr Context; std::string Path; + mINI::INIFile File; }; } diff --git a/libultraship/libultraship/Cvar.cpp b/libultraship/libultraship/Cvar.cpp index 91788fd48..891ee73af 100644 --- a/libultraship/libultraship/Cvar.cpp +++ b/libultraship/libultraship/Cvar.cpp @@ -1,23 +1,22 @@ -#include "cvar.h" +#include "Cvar.h" #include #include +#include +#include +#include #include -std::map cvars; - -CVar* CVar_GetVar(const char* name) { - std::string key(name); - return cvars.contains(key) ? cvars[key] : nullptr; -} +std::map, std::less<>> cvars; extern "C" CVar* CVar_Get(const char* name) { - return CVar_GetVar(name); + auto it = cvars.find(name); + return (it != cvars.end()) ? it->second.get() : nullptr; } extern "C" s32 CVar_GetS32(const char* name, s32 defaultValue) { CVar* cvar = CVar_Get(name); - if (cvar != nullptr) { + if (cvar) { if (cvar->type == CVAR_TYPE_S32) return cvar->value.valueS32; } @@ -28,7 +27,7 @@ extern "C" s32 CVar_GetS32(const char* name, s32 defaultValue) { extern "C" float CVar_GetFloat(const char* name, float defaultValue) { CVar* cvar = CVar_Get(name); - if (cvar != nullptr) { + if (cvar) { if (cvar->type == CVAR_TYPE_FLOAT) return cvar->value.valueFloat; } @@ -36,10 +35,10 @@ extern "C" float CVar_GetFloat(const char* name, float defaultValue) { return defaultValue; } -extern "C" char* CVar_GetString(const char* name, char* defaultValue) { +extern "C" const char* CVar_GetString(const char* name, const char* defaultValue) { CVar* cvar = CVar_Get(name); - if (cvar != nullptr) { + if (cvar) { if (cvar->type == CVAR_TYPE_STRING) return cvar->value.valueStr; } @@ -48,53 +47,43 @@ extern "C" char* CVar_GetString(const char* name, char* defaultValue) { } extern "C" void CVar_SetS32(const char* name, s32 value) { - CVar* cvar = CVar_Get(name); + auto& cvar = cvars[name]; if (!cvar) { - cvar = new CVar; - cvars[std::string(name)] = cvar; + cvar = std::make_unique(); } cvar->type = CVAR_TYPE_S32; cvar->value.valueS32 = value; } void CVar_SetFloat(const char* name, float value) { - CVar* cvar = CVar_Get(name); + auto& cvar = cvars[name]; if (!cvar) { - cvar = new CVar; - cvars[std::string(name)] = cvar; + cvar = std::make_unique(); } cvar->type = CVAR_TYPE_FLOAT; cvar->value.valueFloat = value; } -void CVar_SetString(const char* name, char* value) { - CVar* cvar = CVar_Get(name); +void CVar_SetString(const char* name, const char* value) { + auto& cvar = cvars[name]; if (!cvar) { - cvar = new CVar; - cvars[std::string(name)] = cvar; + cvar = std::make_unique(); } cvar->type = CVAR_TYPE_STRING; cvar->value.valueStr = value; } - extern "C" void CVar_RegisterS32(const char* name, s32 defaultValue) { - CVar* cvar = CVar_Get(name); - - if (cvar == nullptr) + if (!CVar_Get(name)) CVar_SetS32(name, defaultValue); } extern "C" void CVar_RegisterFloat(const char* name, float defaultValue) { - CVar* cvar = CVar_Get(name); - - if (cvar == nullptr) + if (!CVar_Get(name)) CVar_SetFloat(name, defaultValue); } -extern "C" void CVar_RegisterString(const char* name, char* defaultValue) { - CVar* cvar = CVar_Get(name); - - if (cvar == nullptr) +extern "C" void CVar_RegisterString(const char* name, const char* defaultValue) { + if (!CVar_Get(name)) CVar_SetString(name, defaultValue); } diff --git a/libultraship/libultraship/Cvar.h b/libultraship/libultraship/Cvar.h index a85bb8fd3..e16f4469f 100644 --- a/libultraship/libultraship/Cvar.h +++ b/libultraship/libultraship/Cvar.h @@ -6,13 +6,13 @@ typedef enum CVarType { CVAR_TYPE_S32, CVAR_TYPE_FLOAT, CVAR_TYPE_STRING } CVarType; typedef struct CVar { - char* name; + const char* name; CVarType type; union { s32 valueS32; float valueFloat; - char* valueStr; + const char* valueStr; } value; } CVar; @@ -22,16 +22,15 @@ extern "C" #endif //#include - CVar* CVar_Get(const char* name); s32 CVar_GetS32(const char* name, s32 defaultValue); float CVar_GetFloat(const char* name, float defaultValue); -char* CVar_GetString(const char* name, char* defaultValue); +const char* CVar_GetString(const char* name, const char* defaultValue); void CVar_SetS32(const char* name, s32 value); void CVar_RegisterS32(const char* name, s32 defaultValue); void CVar_RegisterFloat(const char* name, float defaultValue); -void CVar_RegisterString(const char* name, char* defaultValue); +void CVar_RegisterString(const char* name, const char* defaultValue); #ifdef __cplusplus }; @@ -40,10 +39,11 @@ void CVar_RegisterString(const char* name, char* defaultValue); #ifdef __cplusplus #include #include +#include +#include -extern std::map cvars; -CVar* CVar_GetVar(const char* name); +extern std::map, std::less<>> cvars; void CVar_SetFloat(const char* name, float value); -void CVar_SetString(const char* name, char* value); +void CVar_SetString(const char* name, const char* value); #endif #endif diff --git a/libultraship/libultraship/Factories/OTRResourceLoader.cpp b/libultraship/libultraship/Factories/OTRResourceLoader.cpp deleted file mode 100644 index 125e0d9ec..000000000 --- a/libultraship/libultraship/Factories/OTRResourceLoader.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "OTRResourceLoader.h" -#include "OTRMaterialFactory.h" -#include "OTRSceneFactory.h" -#include "OTRCollisionHeaderFactory.h" -#include "OTRDisplayListFactory.h" -#include "OTRPlayerAnimationFactory.h" -#include "OTRSkeletonFactory.h" -#include "OTRSkeletonLimbFactory.h" -#include "OTRAnimationFactory.h" -#include "OTRVtxFactory.h" -#include "OTRCutsceneFactory.h" -#include "OTRArrayFactory.h" -#include "OTRPathFactory.h" - -namespace OtrLib -{ - OTRResource* OTRResourceLoader::LoadResource(BinaryReader* reader) - { - Endianess endianess = (Endianess)reader->ReadByte(); - - // TODO: Setup the binaryreader to use the resource's endianess - - ResourceType resourceType = (ResourceType)reader->ReadUInt32(); - OTRResource* result = nullptr; - - switch (resourceType) - { - case ResourceType::OTRMaterial: - result = OTRMaterialFactory::ReadMaterial(reader); - break; - case ResourceType::OTRRoom: - result = OTRSceneFactory::ReadScene(reader); - break; - case ResourceType::OTRCollisionHeader: - result = OTRCollisionHeaderFactory::ReadCollisionHeader(reader); - break; - case ResourceType::OTRDisplayList: - result = OTRDisplayListFactory::ReadDisplayList(reader); - break; - case ResourceType::OTRPlayerAnimation: - result = OTRPlayerAnimationFactory::ReadPlayerAnimation(reader); - break; - case ResourceType::OTRSkeleton: - result = OTRSkeletonFactory::ReadSkeleton(reader); - break; - case ResourceType::OTRSkeletonLimb: - result = OTRSkeletonLimbFactory::ReadSkeletonLimb(reader); - break; - case ResourceType::OTRVtx: - result = OTRVtxFactory::ReadVtx(reader); - break; - case ResourceType::OTRAnimation: - result = OTRAnimationFactory::ReadAnimation(reader); - break; - case ResourceType::OTRCutscene: - result = OTRCutsceneFactory::ReadCutscene(reader); - break; - case ResourceType::OTRArray: - result = OTRArrayFactory::ReadArray(reader); - break; - case ResourceType::OTRPath: - result = OTRPathFactory::ReadPath(reader); - break; - default: - // RESOURCE TYPE NOT SUPPORTED - break; - } - - return result; - } -} \ No newline at end of file diff --git a/libultraship/libultraship/GameOverlay.cpp b/libultraship/libultraship/GameOverlay.cpp new file mode 100644 index 000000000..bf9ca9a71 --- /dev/null +++ b/libultraship/libultraship/GameOverlay.cpp @@ -0,0 +1,186 @@ +#include "GameOverlay.h" + +#include "Cvar.h" +#include "File.h" +#include "Archive.h" +#include "ResourceMgr.h" +#include "SohConsole.h" +#include "SohImGuiImpl.h" +#include "TextureMod.h" +#include "Lib/ImGui/imgui_internal.h" + +void Ship::GameOverlay::LoadFont(const std::string& name, const std::string& path, float fontSize) { + ImGuiIO& io = ImGui::GetIO(); + std::shared_ptr base = GlobalCtx2::GetInstance()->GetResourceManager()->GetArchive(); + std::shared_ptr font = std::make_shared(); + base->LoadFile(path, false, font); + if (font->bIsLoaded) { + char* font_data = new char[font->dwBufferSize]; + memcpy(font_data, font->buffer.get(), font->dwBufferSize); + Fonts[name] = io.Fonts->AddFontFromMemoryTTF(font_data, font->dwBufferSize, fontSize); + } +} + +void Ship::GameOverlay::TextDraw(float x, float y, bool shadow, const char* fmt, ...) { + char buf[1024]; + va_list args; + va_start(args, fmt); + vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args); + buf[IM_ARRAYSIZE(buf) - 1] = 0; + va_end(args); + + ImGui::PushFont(Fonts[this->CurrentFont]); + if (shadow) { + ImGui::SetCursorPos(ImVec2(x + 1, y + 1)); + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(.0f, .0f, .0f, 255)); + ImGui::Text(buf, args); + } + ImGui::PopStyleColor(); + ImGui::SetCursorPos(ImVec2(x, y)); + ImGui::Text(buf, args); + ImGui::PopFont(); +} + +float Ship::GameOverlay::GetScreenWidth() { + const ImGuiViewport* viewport = ImGui::GetMainViewport(); + return viewport->Size.x; +} + +float Ship::GameOverlay::GetScreenHeight() { + const ImGuiViewport* viewport = ImGui::GetMainViewport(); + return viewport->Size.y; +} + +float Ship::GameOverlay::GetStringWidth(const char* text) { + return CalculateTextSize(text).x; +} + +ImVec2 Ship::GameOverlay::CalculateTextSize(const char* text, const char* text_end, bool hide_text_after_double_hash, float wrap_width) { + ImGuiContext& g = *GImGui; + + const char* text_display_end; + if (hide_text_after_double_hash) + text_display_end = ImGui::FindRenderedTextEnd(text, text_end); // Hide anything after a '##' string + else + text_display_end = text_end; + + GameOverlay* overlay = SohImGui::overlay; + + ImFont* font = overlay->CurrentFont == "Default" ? g.Font : overlay->Fonts[overlay->CurrentFont]; + const float font_size = font->FontSize; + if (text == text_display_end) + return ImVec2(0.0f, font_size); + ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL); + + // Round + // FIXME: This has been here since Dec 2015 (7b0bf230) but down the line we want this out. + // FIXME: Investigate using ceilf or e.g. + // - https://git.musl-libc.org/cgit/musl/tree/src/math/ceilf.c + // - https://embarkstudios.github.io/rust-gpu/api/src/libm/math/ceilf.rs.html + text_size.x = IM_FLOOR(text_size.x + 0.99999f); + + return text_size; +} + +void Ship::GameOverlay::Init() { + this->LoadFont("Press Start 2P", "assets/ship_of_harkinian/fonts/PressStart2P-Regular.ttf", 12.0f); + this->LoadFont("Fipps", "assets/ship_of_harkinian/fonts/Fipps-Regular.otf", 32.0f); + const std::string DefaultFont = this->Fonts.begin()->first; + if(!this->Fonts.empty()) { + const std::string font = CVar_GetString("gOverlayFont", ImStrdup(DefaultFont.c_str())); + for (auto& [name, _] : this->Fonts) { + if (font.starts_with(name)) { + this->CurrentFont = name; + break; + } + this->CurrentFont = DefaultFont; + } + } + SohImGui::console->Commands["overlay"] = { OverlayCommand, "Draw an overlay using a cvar value" }; +} + +void Ship::GameOverlay::DrawSettings() { + ImGui::Text("Overlays Text Font"); + if (ImGui::BeginCombo("##TextFont", this->CurrentFont.c_str())) { + for (auto& [name, font] : this->Fonts) { + if (ImGui::Selectable(name.c_str(), name == this->CurrentFont)) { + this->CurrentFont = name; + CVar_SetString("gOverlayFont", ImStrdup(name.c_str())); + SohImGui::needs_save = true; + } + + } + ImGui::EndCombo(); + } +} + + +void Ship::GameOverlay::Draw() { + const ImGuiViewport* viewport = ImGui::GetMainViewport(); + + ImGui::SetNextWindowPos(viewport->Pos, ImGuiCond_Always); + ImGui::SetNextWindowSize(viewport->Size, ImGuiCond_Always); + ImGui::Begin("SoHOverlay", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBackground | + ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoInputs); + + float textY = 50; + for (auto &[key, overlay] : this->RegisteredOverlays) { + + if (overlay.type == OverlayType::TEXT) { + const char* text = ImStrdup(key.c_str()); + const CVar* var = CVar_Get(text); + + switch (var->type) { + case CVAR_TYPE_FLOAT: + this->TextDraw(30, textY, true, "%s %.2f", text, var->value.valueFloat); + break; + case CVAR_TYPE_S32: + this->TextDraw(30, textY, true, "%s %d", text, var->value.valueS32); + break; + case CVAR_TYPE_STRING: + this->TextDraw(30, textY, true, "%s %s", text, var->value.valueStr); + break; + } + + free((void*) text); + textY += 30; + } + } + + ImGui::End(); +} + + +bool Ship::OverlayCommand(const std::vector& args) { + if (args.size() < 3) { + return CMD_FAILED; + } + + if (CVar_Get(args[2].c_str()) != nullptr) { + const char* key = args[2].c_str(); + GameOverlay* overlay = SohImGui::overlay; + if (args[1] == "add") { + if (!overlay->RegisteredOverlays.contains(args[2])) { + overlay->RegisteredOverlays[args[2]] = { + OverlayType::TEXT, + key + }; + INFO("Added overlay: %s ", key); + } else { + ERROR("Overlay already exists: %s", key); + } + } + else if (args[1] == "remove") { + if (overlay->RegisteredOverlays.contains(args[2])) { + overlay->RegisteredOverlays.erase(args[2]); + INFO("Removed overlay: %s ", key); + } else { + ERROR("Overlay not found: %s ", key); + } + } + } else { + ERROR("CVar %s does not exist", args[2].c_str()); + } + + return CMD_SUCCESS; +} diff --git a/libultraship/libultraship/GameOverlay.h b/libultraship/libultraship/GameOverlay.h new file mode 100644 index 000000000..c53503a52 --- /dev/null +++ b/libultraship/libultraship/GameOverlay.h @@ -0,0 +1,38 @@ +#pragma once +#include +#include + +#include "Lib/ImGui/imgui.h" +#include +#include + +enum class OverlayType { + TEXT, IMAGE +}; + +struct Overlay { + OverlayType type; + const char* value; +}; + +namespace Ship { + class GameOverlay { + public: + std::unordered_map RegisteredOverlays; + std::unordered_map Fonts; + std::string CurrentFont = "Default"; + void Init(); + void Draw(); + void DrawSettings(); + static float GetScreenWidth(); + static float GetScreenHeight(); + static float GetStringWidth(const char* text); + static ImVec2 CalculateTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f); + private: + void TextDraw(float x, float y, bool shadow, const char* text, ...); + void LoadFont(const std::string& name, const std::string& path, float fontSize); + }; + + static bool OverlayCommand(const std::vector& args); +} + diff --git a/libultraship/libultraship/GameSettings.cpp b/libultraship/libultraship/GameSettings.cpp index c2d876ab0..0cd9aa2f4 100644 --- a/libultraship/libultraship/GameSettings.cpp +++ b/libultraship/libultraship/GameSettings.cpp @@ -1,22 +1,22 @@ #include "GameSettings.h" // Audio +#include +#include #include #include #include -#include #include "ConfigFile.h" #include "Cvar.h" #include "GlobalCtx2.h" #include "SohImGuiImpl.h" -#include "stox.h" #include "../../soh/include/z64audio.h" -#include #include "SohHooks.h" #include "../../soh/soh/Enhancements/debugconsole.h" #include "Window.h" +#include "Lib/Fast3D/gfx_rendering_api.h" #define ABS(var) var < 0 ? -(var) : var @@ -25,14 +25,6 @@ using namespace Ship; namespace Game { bool DeSyncAudio = false; - SoHConfigType Settings; - const std::string ConfSection = DEBUG_SECTION; - const std::string AudioSection = AUDIO_SECTION; - const std::string ControllerSection = CONTROLLER_SECTION; - const std::string EnhancementSection = ENHANCEMENTS_SECTION; - const std::string CosmeticsSection = COSMETICS_SECTION; - const std::string CheatSection = CHEATS_SECTION; - const std::string LanguagesSection = LANGUAGES_SECTION; void UpdateAudio() { Audio_SetGameVolume(SEQ_BGM_MAIN, CVar_GetFloat("gMainMusicVolume", 1)); @@ -41,18 +33,6 @@ namespace Game { Audio_SetGameVolume(SEQ_SFX, CVar_GetFloat("gFanfareVolume", 1)); } - void LoadSettings() { - const std::shared_ptr pConf = GlobalCtx2::GetInstance()->GetConfig(); - ConfigFile& Conf = *pConf; - - // Debug - SohImGui::console->opened = stob(Conf[ConfSection]["console"]); - Settings.debug.menu_bar = stob(Conf[ConfSection]["menu_bar"]); - Settings.debug.soh = stob(Conf[ConfSection]["soh_debug"]); - - UpdateAudio(); - } - void LoadPadSettings() { const std::shared_ptr pConf = GlobalCtx2::GetInstance()->GetConfig(); ConfigFile& Conf = *pConf; @@ -65,16 +45,11 @@ namespace Game { } } + void LoadSettings() { + DebugConsole_LoadCVars(); + } + void SaveSettings() { - const std::shared_ptr pConf = GlobalCtx2::GetInstance()->GetConfig(); - ConfigFile& Conf = *pConf; - - // Debug - Conf[ConfSection]["console"] = std::to_string(SohImGui::console->opened); - Conf[ConfSection]["menu_bar"] = std::to_string(Settings.debug.menu_bar); - Conf[ConfSection]["soh_debug"] = std::to_string(Settings.debug.soh); - - Conf.Save(); DebugConsole_SaveCVars(); } @@ -82,6 +57,11 @@ namespace Game { ModInternal::registerHookListener({ AUDIO_INIT, [](HookEvent ev) { UpdateAudio(); }}); + ModInternal::registerHookListener({ GFX_INIT, [](HookEvent ev) { + gfx_get_current_rendering_api()->set_texture_filter((FilteringMode) CVar_GetS32("gTextureFilter", THREE_POINT)); + SohImGui::console->opened = CVar_GetS32("gConsoleEnabled", 0); + UpdateAudio(); + }}); } void SetSeqPlayerVolume(SeqPlayers playerId, float volume) { diff --git a/libultraship/libultraship/GameSettings.h b/libultraship/libultraship/GameSettings.h index 9d4e3e776..0a9aa0ee6 100644 --- a/libultraship/libultraship/GameSettings.h +++ b/libultraship/libultraship/GameSettings.h @@ -1,19 +1,5 @@ #pragma once -struct SoHConfigType { - // Debug - struct { - bool soh = false; - bool menu_bar = false; - bool soh_sink = true; - } debug; - - // Graphics - struct { - bool show = false; - } graphics; -}; - enum SeqPlayers { /* 0 */ SEQ_BGM_MAIN, /* 1 */ SEQ_FANFARE, @@ -22,16 +8,7 @@ enum SeqPlayers { /* 4 */ SEQ_MAX }; -#define DEBUG_SECTION "DEBUG SETTINGS" -#define AUDIO_SECTION "AUDIO SETTINGS" -#define CONTROLLER_SECTION "CONTROLLER SECTION" -#define ENHANCEMENTS_SECTION "ENHANCEMENT SETTINGS" -#define COSMETICS_SECTION "COSMETIC SETTINGS" -#define CHEATS_SECTION "CHEATS SETTINGS" -#define LANGUAGES_SECTION "LANGUAGES SETTINGS" - namespace Game { - extern SoHConfigType Settings; void InitSettings(); void LoadSettings(); void LoadPadSettings(); diff --git a/libultraship/libultraship/GlobalCtx2.cpp b/libultraship/libultraship/GlobalCtx2.cpp index dd8125bcc..5ce59f5ab 100644 --- a/libultraship/libultraship/GlobalCtx2.cpp +++ b/libultraship/libultraship/GlobalCtx2.cpp @@ -30,7 +30,7 @@ namespace Ship { } GlobalCtx2::GlobalCtx2(const std::string& Name) : Name(Name), MainPath(""), PatchesPath("") { - + } GlobalCtx2::~GlobalCtx2() { @@ -54,7 +54,11 @@ namespace Ship { if (!ResMan->DidLoadSuccessfully()) { +#ifdef _WIN32 MessageBox(NULL, L"Main OTR file not found!", L"Uh oh", MB_OK); +#else + SPDLOG_ERROR("Main OTR file not found!"); +#endif exit(1); } INSTANCE = new ModManager(ResMan); diff --git a/libultraship/libultraship/Lib/Fast3D/U64/PR/ultra64/gbi.h b/libultraship/libultraship/Lib/Fast3D/U64/PR/ultra64/gbi.h index dedc97939..a9e4f035e 100644 --- a/libultraship/libultraship/Lib/Fast3D/U64/PR/ultra64/gbi.h +++ b/libultraship/libultraship/Lib/Fast3D/U64/PR/ultra64/gbi.h @@ -1004,7 +1004,7 @@ #define G_DL_PUSH 0x00 #define G_DL_NOPUSH 0x01 -#if _MSC_VER +#if defined(_MSC_VER) || defined(__GNUC__) #define _LANGUAGE_C #endif @@ -3132,7 +3132,7 @@ _DW({ \ #endif */ -#ifdef _MSC_VER +#if defined(_MSC_VER) #define CALL_2(A,B) A B #define CALL_3(A,B,C) A B C @@ -3143,12 +3143,12 @@ _DW({ \ #define gsDPSetCombineMode(a, b) gsDPSetCombineLERP(a, b) #endif -#if _MSC_VER +#if defined(_MSC_VER) || defined(__GNUC__) #define CALL_2(A,B) A B #define CALL_3(A,B,C) A B C -#define gsDPSetCombineMode(a, b) CALL_2(gsDPSetCombineLERP, (a, b)) - //#define gsDPSetCombineMode(a, b) _SHIFTL(0, 24, 8), 0 +// #define gsDPSetCombineMode(a, b) CALL_2(gsDPSetCombineLERP, (a, b)) +// #define gsDPSetCombineMode(a, b) _SHIFTL(0, 24, 8), 0 #else #define gsDPSetCombineMode(a, b) gsDPSetCombineLERP(a, b) #endif diff --git a/libultraship/libultraship/Lib/Fast3D/U64/PR/ultra64/mbi.h b/libultraship/libultraship/Lib/Fast3D/U64/PR/ultra64/mbi.h index fd6042ff5..988c309df 100644 --- a/libultraship/libultraship/Lib/Fast3D/U64/PR/ultra64/mbi.h +++ b/libultraship/libultraship/Lib/Fast3D/U64/PR/ultra64/mbi.h @@ -33,6 +33,7 @@ #define G_OFF (0) #include +#include "types.h" #include "gbi.h" #include "abi.h" diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_direct3d11.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_direct3d11.cpp index cea82e09e..4664a0faa 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_direct3d11.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_direct3d11.cpp @@ -15,11 +15,9 @@ #ifndef _LANGUAGE_C #define _LANGUAGE_C #endif -#include +#include "PR/ultra64/gbi.h" -#include "gfx_cc.h" #include "gfx_window_manager_api.h" -#include "gfx_rendering_api.h" #include "gfx_direct3d_common.h" #define DECLARE_GFX_DXGI_FUNCTIONS @@ -28,7 +26,9 @@ #include "gfx_screen_config.h" #include "../../SohImGuiImpl.h" -#define THREE_POINT_FILTERING 0 +#include "gfx_cc.h" +#include "gfx_rendering_api.h" +#include "gfx_pc.h" #define DEBUG_D3D 0 using namespace Microsoft::WRL; // For ComPtr @@ -135,6 +135,7 @@ static struct { //uint32_t current_width, current_height; uint32_t render_target_height; int current_framebuffer; + FilteringMode current_filter_mode = NONE; int8_t depth_test; int8_t depth_mask; @@ -157,7 +158,7 @@ static LARGE_INTEGER last_time, accumulated_time, frequency; int gfx_d3d11_create_framebuffer(void); -void create_depth_stencil_objects(uint32_t width, uint32_t height, uint32_t msaa_count, ID3D11DepthStencilView **view, ID3D11ShaderResourceView **srv) { +static void create_depth_stencil_objects(uint32_t width, uint32_t height, uint32_t msaa_count, ID3D11DepthStencilView **view, ID3D11ShaderResourceView **srv) { D3D11_TEXTURE2D_DESC texture_desc; texture_desc.Width = width; texture_desc.Height = height; @@ -397,7 +398,7 @@ static struct ShaderProgram *gfx_d3d11_create_and_load_new_shader(uint64_t shade char buf[4096]; size_t len, num_floats; - gfx_direct3d_common_build_shader(buf, len, num_floats, cc_features, false, THREE_POINT_FILTERING); + gfx_direct3d_common_build_shader(buf, len, num_floats, cc_features, false, d3d.current_filter_mode == THREE_POINT); ComPtr vs, ps; ComPtr error_blob; @@ -564,11 +565,8 @@ static void gfx_d3d11_set_sampler_parameters(int tile, bool linear_filter, uint3 D3D11_SAMPLER_DESC sampler_desc; ZeroMemory(&sampler_desc, sizeof(D3D11_SAMPLER_DESC)); -#if THREE_POINT_FILTERING - sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; -#else - sampler_desc.Filter = linear_filter ? D3D11_FILTER_MIN_MAG_MIP_LINEAR : D3D11_FILTER_MIN_MAG_MIP_POINT; -#endif + sampler_desc.Filter = linear_filter && d3d.current_filter_mode == LINEAR ? D3D11_FILTER_MIN_MAG_MIP_LINEAR : D3D11_FILTER_MIN_MAG_MIP_POINT; + sampler_desc.AddressU = gfx_cm_to_d3d11(cms); sampler_desc.AddressV = gfx_cm_to_d3d11(cmt); sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; @@ -672,12 +670,12 @@ static void gfx_d3d11_draw_triangles(float buf_vbo[], size_t buf_vbo_len, size_t d3d.last_resource_views[i] = d3d.textures[d3d.current_texture_ids[i]].resource_view.Get(); d3d.context->PSSetShaderResources(i, 1, d3d.textures[d3d.current_texture_ids[i]].resource_view.GetAddressOf()); -#if THREE_POINT_FILTERING - d3d.per_draw_cb_data.textures[i].width = d3d.textures[d3d.current_texture_ids[i]].width; - d3d.per_draw_cb_data.textures[i].height = d3d.textures[d3d.current_texture_ids[i]].height; - d3d.per_draw_cb_data.textures[i].linear_filtering = d3d.textures[d3d.current_texture_ids[i]].linear_filtering; - textures_changed = true; -#endif + if (d3d.current_filter_mode == THREE_POINT) { + d3d.per_draw_cb_data.textures[i].width = d3d.textures[d3d.current_texture_ids[i]].width; + d3d.per_draw_cb_data.textures[i].height = d3d.textures[d3d.current_texture_ids[i]].height; + d3d.per_draw_cb_data.textures[i].linear_filtering = d3d.textures[d3d.current_texture_ids[i]].linear_filtering; + textures_changed = true; + } if (d3d.last_sampler_states[i].Get() != d3d.textures[d3d.current_texture_ids[i]].sampler_state.Get()) { d3d.last_sampler_states[i] = d3d.textures[d3d.current_texture_ids[i]].sampler_state.Get(); @@ -880,6 +878,15 @@ void gfx_d3d11_select_texture_fb(int fbID) { gfx_d3d11_select_texture(tile, d3d.framebuffers[fbID].texture_id); } +void gfx_d3d11_set_texture_filter(FilteringMode mode) { + d3d.current_filter_mode = mode; + gfx_texture_cache_clear(); +} + +FilteringMode gfx_d3d11_get_texture_filter(void) { + return d3d.current_filter_mode; +} + std::map, uint16_t> gfx_d3d11_get_pixel_depth(int fb_id, const std::set>& coordinates) { Framebuffer& fb = d3d.framebuffers[fb_id]; TextureData& td = d3d.textures[fb.texture_id]; @@ -985,8 +992,8 @@ std::map, uint16_t> gfx_d3d11_get_pixel_depth(int fb_id, } // namespace -ImTextureID SohImGui::GetTextureByID(int id) { - return impl.backend == Backend::DX11 ? d3d.textures[id].resource_view.Get() : reinterpret_cast(id); +ImTextureID gfx_d3d11_get_texture_by_id(int id) { + return d3d.textures[id].resource_view.Get(); } struct GfxRenderingAPI gfx_direct3d11_api = { @@ -1019,7 +1026,9 @@ struct GfxRenderingAPI gfx_direct3d11_api = { gfx_d3d11_get_pixel_depth, gfx_d3d11_get_framebuffer_texture_id, gfx_d3d11_select_texture_fb, - gfx_d3d11_delete_texture + gfx_d3d11_delete_texture, + gfx_d3d11_set_texture_filter, + gfx_d3d11_get_texture_filter }; #endif diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_glx.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_glx.cpp index 66bb5c182..d450558b2 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_glx.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_glx.cpp @@ -150,29 +150,29 @@ static struct { Display *dpy; Window root; Window win; - + Atom atom_wm_state; Atom atom_wm_state_fullscreen; Atom atom_wm_delete_window; - + bool is_fullscreen; void (*on_fullscreen_changed)(bool is_now_fullscreen); - + int keymap[256]; bool (*on_key_down)(int scancode); bool (*on_key_up)(int scancode); void (*on_all_keys_up)(void); - + PFNGLXGETSYNCVALUESOMLPROC glXGetSyncValuesOML; PFNGLXSWAPBUFFERSMSCOMLPROC glXSwapBuffersMscOML; PFNGLXWAITFORSBCOMLPROC glXWaitForSbcOML; - + PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT; PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI; - + PFNGLXGETVIDEOSYNCSGIPROC glXGetVideoSyncSGI; PFNGLXWAITVIDEOSYNCSGIPROC glXWaitVideoSyncSGI; - + bool has_oml_sync_control; uint64_t ust0; int64_t last_msc; @@ -181,7 +181,7 @@ static struct { uint64_t last_ust; int64_t target_msc; bool dropped_frame; - + bool has_sgi_video_sync; uint64_t last_sync_counter; int64_t this_msc; @@ -220,7 +220,7 @@ static int64_t glXGetVideoSyncSGI_wrapper(void) { static void init_keymap(void) { XkbDescPtr desc = XkbGetMap(glx.dpy, 0, XkbUseCoreKbd); XkbGetNames(glx.dpy, XkbKeyNamesMask, desc); - + for (int i = desc->min_key_code; i <= desc->max_key_code && i < 256; i++) { char name[XkbKeyNameLength + 1]; memcpy(name, desc->names->keys[i].name, XkbKeyNameLength); @@ -232,7 +232,7 @@ static void init_keymap(void) { } } } - + XkbFreeNames(desc, XkbKeyNamesMask, True); XkbFreeKeyboard(desc, 0, True); } @@ -265,7 +265,7 @@ static void gfx_glx_set_fullscreen_state(bool on, bool call_callback) { return; } glx.is_fullscreen = on; - + XEvent xev; xev.xany.type = ClientMessage; xev.xclient.message_type = glx.atom_wm_state; @@ -276,8 +276,8 @@ static void gfx_glx_set_fullscreen_state(bool on, bool call_callback) { xev.xclient.data.l[2] = 0; xev.xclient.data.l[3] = 0; XSendEvent(glx.dpy, glx.root, 0, SubstructureNotifyMask | SubstructureRedirectMask, &xev); - gfx_glx_ShowHideMouse(on); - + gfx_glx_show_cursor(on); + if (glx.on_fullscreen_changed != NULL && call_callback) { glx.on_fullscreen_changed(on); } @@ -303,7 +303,7 @@ static void gfx_glx_init(const char *game_name, bool start_in_fullscreen) { // which means that glXSwapBuffers should be non-blocking, // if we are sure to wait at least one vsync interval between calls. setenv("__GL_MaxFramesAllowed", "2", true); - + glx.dpy = XOpenDisplay(NULL); if (glx.dpy == NULL) { fprintf(stderr, "Cannot connect to X server\n"); @@ -311,7 +311,7 @@ static void gfx_glx_init(const char *game_name, bool start_in_fullscreen) { } int screen = DefaultScreen(glx.dpy); glx.root = RootWindow(glx.dpy, screen); - + GLint att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None }; XVisualInfo *vi = glXChooseVisual(glx.dpy, 0, att); if (vi == NULL) { @@ -323,7 +323,7 @@ static void gfx_glx_init(const char *game_name, bool start_in_fullscreen) { swa.colormap = cmap; swa.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | FocusChangeMask; glx.win = XCreateWindow(glx.dpy, glx.root, 0, 0, DESIRED_SCREEN_WIDTH, DESIRED_SCREEN_HEIGHT, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask, &swa); - + glx.atom_wm_state = XInternAtom(glx.dpy, "_NET_WM_STATE", False); glx.atom_wm_state_fullscreen = XInternAtom(glx.dpy, "_NET_WM_STATE_FULLSCREEN", False); glx.atom_wm_delete_window = XInternAtom(glx.dpy, "WM_DELETE_WINDOW", False); @@ -340,11 +340,11 @@ static void gfx_glx_init(const char *game_name, bool start_in_fullscreen) { XStoreName(glx.dpy, glx.win, title); GLXContext glc = glXCreateContext(glx.dpy, vi, NULL, GL_TRUE); glXMakeCurrent(glx.dpy, glx.win, glc); - + init_keymap(); - + const char *extensions = glXQueryExtensionsString(glx.dpy, screen); - + if (gfx_glx_check_extension(extensions, "GLX_OML_sync_control")) { glx.glXGetSyncValuesOML = (PFNGLXGETSYNCVALUESOMLPROC)glXGetProcAddressARB((const GLubyte *)"glXGetSyncValuesOML"); glx.glXSwapBuffersMscOML = (PFNGLXSWAPBUFFERSMSCOMLPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapBuffersMscOML"); @@ -360,7 +360,7 @@ static void gfx_glx_init(const char *game_name, bool start_in_fullscreen) { glx.glXGetVideoSyncSGI = (PFNGLXGETVIDEOSYNCSGIPROC)glXGetProcAddressARB((const GLubyte *)"glXGetVideoSyncSGI"); glx.glXWaitVideoSyncSGI = (PFNGLXWAITVIDEOSYNCSGIPROC)glXGetProcAddressARB((const GLubyte *)"glXWaitVideoSyncSGI"); } - + int64_t ust, msc, sbc; if (glx.glXGetSyncValuesOML != NULL && glx.glXGetSyncValuesOML(glx.dpy, glx.win, &ust, &msc, &sbc)) { glx.has_oml_sync_control = true; @@ -439,7 +439,7 @@ static void gfx_glx_handle_events(void) { } } } - if (xev.type == ClientMessage && xev.xclient.data.l[0] == glx.atom_wm_delete_window) { + if (xev.type == ClientMessage && (Atom)xev.xclient.data.l[0] == glx.atom_wm_delete_window) { exit(0); } } @@ -451,19 +451,19 @@ static bool gfx_glx_start_frame(void) { static void gfx_glx_swap_buffers_begin(void) { glx.wanted_ust += FRAME_INTERVAL_US_NUMERATOR; // advance 1/30 seconds on JP/US or 1/25 seconds on EU - + if (!glx.has_oml_sync_control && !glx.has_sgi_video_sync) { glFlush(); - + uint64_t target = glx.wanted_ust / FRAME_INTERVAL_US_DENOMINATOR; uint64_t now; while (target > (now = (uint64_t)get_time() - glx.ust0)) { - struct timespec ts = {(target - now) / 1000000, ((target - now) % 1000000) * 1000}; + struct timespec ts = {(time_t)((target - now) / 1000000), (time_t)(((target - now) % 1000000) * 1000)}; if (nanosleep(&ts, NULL) == 0) { break; } } - + if (target + 2 * FRAME_INTERVAL_US_NUMERATOR / FRAME_INTERVAL_US_DENOMINATOR < now) { if (target + 32 * FRAME_INTERVAL_US_NUMERATOR / FRAME_INTERVAL_US_DENOMINATOR >= now) { printf("Dropping frame\n"); @@ -476,10 +476,10 @@ static void gfx_glx_swap_buffers_begin(void) { } glXSwapBuffers(glx.dpy, glx.win); glx.dropped_frame = false; - + return; } - + double vsyncs_to_wait = (int64_t)(glx.wanted_ust / FRAME_INTERVAL_US_DENOMINATOR - glx.last_ust) / (double)glx.vsync_interval; if (vsyncs_to_wait <= 0) { printf("Dropping frame\n"); @@ -519,17 +519,17 @@ static void gfx_glx_swap_buffers_begin(void) { vsyncs_to_wait = 2; } glx.target_msc = glx.last_msc + vsyncs_to_wait; - + if (glx.has_oml_sync_control) { glx.glXSwapBuffersMscOML(glx.dpy, glx.win, glx.target_msc, 0, 0); } else if (glx.has_sgi_video_sync) { glFlush(); // Try to submit pending work. Don't use glFinish since that busy loops on NVIDIA proprietary driver. - + //uint64_t counter0; uint64_t counter1, counter2; - + //uint64_t before_wait = get_time(); - + counter1 = glXGetVideoSyncSGI_wrapper(); //counter0 = counter1; //int waits = 0; @@ -537,17 +537,17 @@ static void gfx_glx_swap_buffers_begin(void) { counter1 = glXWaitVideoSyncSGI_wrapper(); //++waits; } - + //uint64_t before = get_time(); glXSwapBuffers(glx.dpy, glx.win); - - + + counter2 = glXGetVideoSyncSGI_wrapper(); while (counter2 < (uint64_t)glx.target_msc) { counter2 = glXWaitVideoSyncSGI_wrapper(); } uint64_t after = get_time(); - + //printf("%.3f %.3f %.3f\t%.3f\t%u %d %.2f %u %d\n", before_wait * 0.000060, before * 0.000060, after * 0.000060, (after - before) * 0.000060, counter0, counter2 - counter0, vsyncs_to_wait, (unsigned int)glx.target_msc, waits); glx.this_msc = counter2; glx.this_ust = after; @@ -558,7 +558,7 @@ static void gfx_glx_swap_buffers_end(void) { if (glx.dropped_frame || (!glx.has_oml_sync_control && !glx.has_sgi_video_sync)) { return; } - + int64_t ust, msc, sbc; if (glx.has_oml_sync_control) { if (!glx.glXWaitForSbcOML(glx.dpy, glx.win, 0, &ust, &msc, &sbc)) { @@ -600,6 +600,10 @@ static double gfx_glx_get_time(void) { return 0.0; } +static void gfx_glx_set_frame_divisor(int divisor) { + // TODO +} + struct GfxWindowManagerAPI gfx_glx = { gfx_glx_init, gfx_glx_set_keyboard_callbacks, @@ -612,7 +616,8 @@ struct GfxWindowManagerAPI gfx_glx = { gfx_glx_start_frame, gfx_glx_swap_buffers_begin, gfx_glx_swap_buffers_end, - gfx_glx_get_time + gfx_glx_get_time, + gfx_glx_set_frame_divisor, }; #endif diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_glx.h b/libultraship/libultraship/Lib/Fast3D/gfx_glx.h index fe78db948..1ca410901 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_glx.h +++ b/libultraship/libultraship/Lib/Fast3D/gfx_glx.h @@ -3,6 +3,6 @@ #include "gfx_window_manager_api.h" -struct GfxWindowManagerAPI gfx_glx; +extern struct GfxWindowManagerAPI gfx_glx; #endif diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_opengl.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_opengl.cpp index 6c5f47577..b2db3186a 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_opengl.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_opengl.cpp @@ -29,8 +29,9 @@ #include "SDL_opengl.h" #else #include +#include #define GL_GLEXT_PROTOTYPES 1 -#include +// #include #endif #include "gfx_cc.h" @@ -73,6 +74,7 @@ static uint32_t frame_count; static vector framebuffers; static size_t current_framebuffer; static float current_noise_scale; +static FilteringMode current_filter_mode = THREE_POINT; GLuint pixel_depth_rb, pixel_depth_fb; size_t pixel_depth_rb_size; @@ -177,6 +179,7 @@ static const char *shader_item_to_str(uint32_t item, bool with_alpha, bool only_ return "texel.a"; } } + return ""; } static void append_formula(char *buf, size_t *len, uint8_t c[2][4], bool do_single, bool do_multiply, bool do_mix, bool with_alpha, bool only_alpha, bool opt_alpha) { @@ -211,7 +214,7 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad gfx_cc_get_features(shader_id0, shader_id1, &cc_features); char vs_buf[1024]; - char fs_buf[1024]; + char fs_buf[3000]; size_t vs_len = 0; size_t fs_len = 0; size_t num_floats = 4; @@ -312,21 +315,42 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad append_line(fs_buf, &fs_len, "}"); } + if (current_filter_mode == THREE_POINT) { + append_line(fs_buf, &fs_len, "#define TEX_OFFSET(off) texture2D(tex, texCoord - (off)/texSize)"); + append_line(fs_buf, &fs_len, "vec4 filter3point(in sampler2D tex, in vec2 texCoord, in vec2 texSize) {"); + append_line(fs_buf, &fs_len, " vec2 offset = fract(texCoord*texSize - vec2(0.5));"); + append_line(fs_buf, &fs_len, " offset -= step(1.0, offset.x + offset.y);"); + append_line(fs_buf, &fs_len, " vec4 c0 = TEX_OFFSET(offset);"); + append_line(fs_buf, &fs_len, " vec4 c1 = TEX_OFFSET(vec2(offset.x - sign(offset.x), offset.y));"); + append_line(fs_buf, &fs_len, " vec4 c2 = TEX_OFFSET(vec2(offset.x, offset.y - sign(offset.y)));"); + append_line(fs_buf, &fs_len, " return c0 + abs(offset.x)*(c1-c0) + abs(offset.y)*(c2-c0);"); + append_line(fs_buf, &fs_len, "}"); + append_line(fs_buf, &fs_len, "vec4 hookTexture2D(in sampler2D tex, in vec2 uv, in vec2 texSize) {"); + append_line(fs_buf, &fs_len, " return filter3point(tex, uv, texSize);"); + append_line(fs_buf, &fs_len, "}"); + } else { + append_line(fs_buf, &fs_len, "vec4 hookTexture2D(in sampler2D tex, in vec2 uv, in vec2 texSize) {"); + append_line(fs_buf, &fs_len, " return texture2D(tex, uv);"); + append_line(fs_buf, &fs_len, "}"); + } + append_line(fs_buf, &fs_len, "void main() {"); for (int i = 0; i < 2; i++) { if (cc_features.used_textures[i]) { bool s = cc_features.clamp[i][0], t = cc_features.clamp[i][1]; + + fs_len += sprintf(fs_buf + fs_len, "vec2 texSize%d = textureSize(uTex%d, 0);\n", i, i); + if (!s && !t) { - fs_len += sprintf(fs_buf + fs_len, "vec4 texVal%d = texture2D(uTex%d, vTexCoord%d);\n", i, i, i); + fs_len += sprintf(fs_buf + fs_len, "vec4 texVal%d = hookTexture2D(uTex%d, vTexCoord%d, texSize%d);\n", i, i, i, i); } else { - fs_len += sprintf(fs_buf + fs_len, "vec2 texSize%d = textureSize(uTex%d, 0);\n", i, i); if (s && t) { - fs_len += sprintf(fs_buf + fs_len, "vec4 texVal%d = texture2D(uTex%d, clamp(vTexCoord%d, 0.5 / texSize%d, vec2(vTexClampS%d, vTexClampT%d)));\n", i, i, i, i, i, i); + fs_len += sprintf(fs_buf + fs_len, "vec4 texVal%d = hookTexture2D(uTex%d, clamp(vTexCoord%d, 0.5 / texSize%d, vec2(vTexClampS%d, vTexClampT%d)), texSize%d);\n", i, i, i, i, i, i, i); } else if (s) { - fs_len += sprintf(fs_buf + fs_len, "vec4 texVal%d = texture2D(uTex%d, vec2(clamp(vTexCoord%d.s, 0.5 / texSize%d.s, vTexClampS%d), vTexCoord%d.t));\n", i, i, i, i, i, i); + fs_len += sprintf(fs_buf + fs_len, "vec4 texVal%d = hookTexture2D(uTex%d, vec2(clamp(vTexCoord%d.s, 0.5 / texSize%d.s, vTexClampS%d), vTexCoord%d.t), texSize%d);\n", i, i, i, i, i, i, i); } else { - fs_len += sprintf(fs_buf + fs_len, "vec4 texVal%d = texture2D(uTex%d, vec2(vTexCoord%d.s, clamp(vTexCoord%d.t, 0.5 / texSize%d.t, vTexClampT%d)));\n", i, i, i, i, i, i); + fs_len += sprintf(fs_buf + fs_len, "vec4 texVal%d = hookTexture2D(uTex%d, vec2(vTexCoord%d.s, clamp(vTexCoord%d.t, 0.5 / texSize%d.t, vTexClampT%d)), texSize%d);\n", i, i, i, i, i, i, i); } } } @@ -422,9 +446,9 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad GLint max_length = 0; glGetShaderiv(fragment_shader, GL_INFO_LOG_LENGTH, &max_length); char error_log[1024]; - //fprintf(stderr, "Fragment shader compilation failed\n"); + fprintf(stderr, "Fragment shader compilation failed\n"); glGetShaderInfoLog(fragment_shader, max_length, &max_length, &error_log[0]); - //fprintf(stderr, "%s\n", &error_log[0]); + fprintf(stderr, "%s\n", &error_log[0]); abort(); } @@ -549,12 +573,14 @@ static uint32_t gfx_cm_to_opengl(uint32_t val) { case G_TX_NOMIRROR | G_TX_WRAP: return GL_REPEAT; } + return 0; } static void gfx_opengl_set_sampler_parameters(int tile, bool linear_filter, uint32_t cms, uint32_t cmt) { + const GLint filter = linear_filter && current_filter_mode == LINEAR ? GL_LINEAR : GL_NEAREST; glActiveTexture(GL_TEXTURE0 + tile); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, linear_filter ? GL_LINEAR : GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linear_filter ? GL_LINEAR : GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, gfx_cm_to_opengl(cms)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gfx_cm_to_opengl(cmt)); } @@ -823,6 +849,15 @@ static std::map, uint16_t> gfx_opengl_get_pixel_depth(in return res; } +void gfx_opengl_set_texture_filter(FilteringMode mode) { + current_filter_mode = mode; + gfx_texture_cache_clear(); +} + +FilteringMode gfx_opengl_get_texture_filter(void) { + return current_filter_mode; +} + struct GfxRenderingAPI gfx_opengl_api = { gfx_opengl_get_clip_parameters, gfx_opengl_unload_shader, @@ -853,7 +888,9 @@ struct GfxRenderingAPI gfx_opengl_api = { gfx_opengl_get_pixel_depth, gfx_opengl_get_framebuffer_texture_id, gfx_opengl_select_texture_fb, - gfx_opengl_delete_texture + gfx_opengl_delete_texture, + gfx_opengl_set_texture_filter, + gfx_opengl_get_texture_filter }; #endif diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp index 1d03befe6..da39c0a4d 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #ifndef _LANGUAGE_C #define _LANGUAGE_C @@ -30,6 +31,8 @@ #include "../StrHash64.h" #include "../../SohImGuiImpl.h" #include "../../Environment.h" +#include "../../GameVersions.h" +#include "../../ResourceMgr.h" // OTRTODO: fix header files for these extern "C" { @@ -45,6 +48,8 @@ extern "C" { using namespace std; +#define SEG_ADDR(seg, addr) (addr | (seg << 24) | 1) + #define SUPPORT_CHECK(x) assert(x) // SCALE_M_N: upscale/downscale M-bit integer to N-bit @@ -209,7 +214,7 @@ static map framebuffers; static set> get_pixel_depth_pending; static map, uint16_t> get_pixel_depth_cached; -#ifdef _MSC_VER +#ifdef _WIN32 // TODO: Properly implement for MSVC static unsigned long get_time(void) { @@ -447,15 +452,15 @@ static void gfx_generate_cc(struct ColorCombiner *comb, uint64_t cc_id) { val = SHADER_COMBINED; break; } - // fallthrough for G_ACMUX_LOD_FRACTION c[i][1][j] = G_CCMUX_LOD_FRACTION; + [[fallthrough]]; // for G_ACMUX_LOD_FRACTION case G_ACMUX_1: //case G_ACMUX_PRIM_LOD_FRAC: same numerical value if (j != 2) { val = SHADER_1; break; } - // fallthrough for G_ACMUX_PRIM_LOD_FRAC + [[fallthrough]]; // for G_ACMUX_PRIM_LOD_FRAC case G_ACMUX_PRIMITIVE: case G_ACMUX_SHADE: case G_ACMUX_ENVIRONMENT: @@ -564,7 +569,7 @@ static void gfx_texture_cache_delete(const uint8_t* orig_addr) if (it->first.texture_addr == orig_addr) { gfx_texture_cache.lru.erase(*(list::iterator*)&it->second.lru_location); gfx_texture_cache.free_texture_ids.push_back(it->second.texture_id); - gfx_texture_cache.map.erase(it); + gfx_texture_cache.map.erase(it->first); again = true; break; } @@ -1692,7 +1697,7 @@ static void gfx_dp_load_block(uint8_t tile, uint32_t uls, uint32_t ult, uint32_t SUPPORT_CHECK(ult == 0); // The lrs field rather seems to be number of pixels to load - uint32_t word_size_shift; + uint32_t word_size_shift = 0; switch (rdp.texture_to_load.siz) { case G_IM_SIZ_4b: word_size_shift = 0; // Or -1? It's unused in SM64 anyway. @@ -1720,7 +1725,7 @@ static void gfx_dp_load_block(uint8_t tile, uint32_t uls, uint32_t ult, uint32_t static void gfx_dp_load_tile(uint8_t tile, uint32_t uls, uint32_t ult, uint32_t lrs, uint32_t lrt) { SUPPORT_CHECK(tile == G_TX_LOADTILE); - uint32_t word_size_shift; + uint32_t word_size_shift = 0; switch (rdp.texture_to_load.siz) { case G_IM_SIZ_4b: word_size_shift = 0; @@ -2060,12 +2065,11 @@ static void gfx_s2dex_bg_copy(const uObjBg* bg) { static inline void* seg_addr(uintptr_t w1) { // Segmented? - if (w1 >= 0xF0000000) + if (w1 & 1) { uint32_t segNum = (w1 >> 24); - segNum -= 0xF0; - uint32_t offset = w1 & 0x00FFFFFF; + uint32_t offset = w1 & 0x00FFFFFE; //offset = 0; // Cursed Malon bug if (segmentPointers[segNum] != 0) @@ -2082,7 +2086,7 @@ static inline void* seg_addr(uintptr_t w1) #define C0(pos, width) ((cmd->words.w0 >> (pos)) & ((1U << width) - 1)) #define C1(pos, width) ((cmd->words.w1 >> (pos)) & ((1U << width) - 1)) -int dListBP; +unsigned int dListBP; int matrixBP; uintptr_t clearMtx; @@ -2149,8 +2153,16 @@ static void gfx_run_dl(Gfx* cmd) { uintptr_t mtxAddr = cmd->words.w1; // OTRTODO: Temp way of dealing with gMtxClear. Need something more elegant in the future... - if (mtxAddr == 0xF012DB20 || mtxAddr == 0xF012DB40) - mtxAddr = clearMtx; + uint32_t gameVersion = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->GetGameVersion(); + if (gameVersion == OOT_PAL_GC) { + if (mtxAddr == SEG_ADDR(0, 0x0FBC20)) { + mtxAddr = clearMtx; + } + } else { + if (mtxAddr == SEG_ADDR(0, 0x12DB20) || mtxAddr == SEG_ADDR(0, 0x12DB40)) { + mtxAddr = clearMtx; + } + } #ifdef F3DEX_GBI_2 gfx_sp_matrix(C0(0, 8) ^ G_MTX_PUSH, (const int32_t *) seg_addr(mtxAddr)); @@ -2250,7 +2262,7 @@ static void gfx_run_dl(Gfx* cmd) { cmd--; - if (ourHash != -1) + if (ourHash != (uint64_t)-1) ResourceMgr_RegisterResourcePatch(ourHash, cmd - dListStart, cmd->words.w1); cmd->words.w1 = (uintptr_t)vtx; @@ -2368,7 +2380,7 @@ static void gfx_run_dl(Gfx* cmd) { case G_QUAD: { int bp = 0; - // fallthrough + [[fallthrough]]; } #endif #if defined(F3DEX_GBI) || defined(F3DLP_GBI) @@ -2398,11 +2410,11 @@ static void gfx_run_dl(Gfx* cmd) { char* imgData = (char*)i; - if ((i & 0xF0000000) != 0xF0000000) + if ((i & 1) != 1) if (ResourceMgr_OTRSigCheck(imgData) == 1) i = (uintptr_t)ResourceMgr_LoadTexByName(imgData); - gfx_dp_set_texture_image(C0(21, 3), C0(19, 2), C0(0, 10), (void*) i, imgData); + gfx_dp_set_texture_image(C0(21, 3), C0(19, 2), C0(0, 10), (void*) i, imgData); break; } case G_SETTIMG_OTR: @@ -2419,7 +2431,7 @@ static void gfx_run_dl(Gfx* cmd) { char* tex = NULL; #endif - if (addr != NULL) + if (addr != 0) { tex = (char*)addr; } @@ -2433,7 +2445,7 @@ static void gfx_run_dl(Gfx* cmd) { uintptr_t oldData = cmd->words.w1; cmd->words.w1 = (uintptr_t)tex; - if (ourHash != -1) + if (ourHash != (uint64_t)-1) ResourceMgr_RegisterResourcePatch(ourHash, cmd - dListStart, oldData); cmd++; @@ -2648,7 +2660,7 @@ void gfx_init(struct GfxWindowManagerAPI *wapi, struct GfxRenderingAPI *rapi, co game_framebuffer_msaa_resolved = gfx_rapi->create_framebuffer(); for (int i = 0; i < 16; i++) - segmentPointers[i] = NULL; + segmentPointers[i] = 0; // Used in the 120 star TAS static uint32_t precomp_shaders[] = { diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_pc.h b/libultraship/libultraship/Lib/Fast3D/gfx_pc.h index d682991d9..d9cd9be8d 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_pc.h +++ b/libultraship/libultraship/Lib/Fast3D/gfx_pc.h @@ -4,12 +4,14 @@ #include #include #include +#include struct GfxRenderingAPI; struct GfxWindowManagerAPI; struct XYWidthHeight { - int16_t x, y, width, height; + int16_t x, y; + uint32_t width, height; }; struct GfxDimensions { @@ -25,7 +27,7 @@ struct TextureCacheKey { uint8_t palette_index; bool operator==(const TextureCacheKey&) const noexcept = default; - + struct Hasher { size_t operator()(const TextureCacheKey& key) const noexcept { uintptr_t addr = (uintptr_t)key.texture_addr; diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_rendering_api.h b/libultraship/libultraship/Lib/Fast3D/gfx_rendering_api.h index 84247fe60..6318be492 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_rendering_api.h +++ b/libultraship/libultraship/Lib/Fast3D/gfx_rendering_api.h @@ -15,6 +15,12 @@ struct GfxClipParameters { bool invert_y; }; +enum FilteringMode { + THREE_POINT, + LINEAR, + NONE +}; + struct GfxRenderingAPI { struct GfxClipParameters (*get_clip_parameters)(void); void (*unload_shader)(struct ShaderProgram *old_prg); @@ -46,6 +52,8 @@ struct GfxRenderingAPI { void *(*get_framebuffer_texture_id)(int fb_id); void (*select_texture_fb)(int fb_id); void (*delete_texture)(uint32_t texID); + void (*set_texture_filter)(FilteringMode mode); + FilteringMode(*get_texture_filter)(void); }; #endif diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp index ffc46f369..e80097c81 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp @@ -1,6 +1,6 @@ #include -#if !defined(__linux__) && defined(ENABLE_OPENGL) +#if defined(ENABLE_OPENGL) #ifdef __MINGW32__ #define FOR_WINDOWS 1 @@ -23,7 +23,9 @@ #include "gfx_window_manager_api.h" #include "gfx_screen_config.h" +#ifdef _WIN32 #include +#endif #include #define GFX_API_NAME "SDL2 - OpenGL" @@ -41,7 +43,7 @@ static bool (*on_key_up_callback)(int scancode); static void (*on_all_keys_up_callback)(void); const SDL_Scancode windows_scancode_table[] = -{ +{ /* 0 1 2 3 4 5 6 7 */ /* 8 9 A B C D E F */ SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_ESCAPE, SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_3, SDL_SCANCODE_4, SDL_SCANCODE_5, SDL_SCANCODE_6, /* 0 */ @@ -117,7 +119,9 @@ static void set_fullscreen(bool on, bool call_callback) { } static uint64_t previous_time; +#ifndef __linux__ static HANDLE timer; +#endif static int frameDivisor = 1; @@ -131,7 +135,9 @@ static void gfx_sdl_init(const char *game_name, bool start_in_fullscreen) { SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); +#ifndef __linux timer = CreateWaitableTimer(nullptr, false, nullptr); +#endif //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); @@ -188,7 +194,7 @@ static void gfx_sdl_set_keyboard_callbacks(bool (*on_key_down)(int scancode), bo } static void gfx_sdl_main_loop(void (*run_one_game_iter)(void)) { - while (1) + while (1) { run_one_game_iter(); } diff --git a/libultraship/libultraship/Lib/StrHash64.h b/libultraship/libultraship/Lib/StrHash64.h index 35401bbf8..d8cc8ff62 100644 --- a/libultraship/libultraship/Lib/StrHash64.h +++ b/libultraship/libultraship/Lib/StrHash64.h @@ -86,14 +86,8 @@ #include -#define u8 uint8_t -#define u16 uint16_t -#define u32 uint32_t -#define u64 uint64_t -#define unint uint32_t - #define INITIAL_CRC64 0xffffffffffffffffULL -extern uint64_t update_crc64(const void* buf, unint len, u64 crc); -extern u64 crc64(const void* buf, unint len); -extern u64 CRC64(const char* t); \ No newline at end of file +extern uint64_t update_crc64(const void* buf, uint32_t len, uint64_t crc); +extern uint64_t crc64(const void* buf, uint32_t len); +extern uint64_t CRC64(const char* t); \ No newline at end of file diff --git a/libultraship/libultraship/Lib/spdlog/include/spdlog/sinks/sohconsole_sink.h b/libultraship/libultraship/Lib/spdlog/include/spdlog/sinks/sohconsole_sink.h index 08729f4dc..4fa03b5e0 100644 --- a/libultraship/libultraship/Lib/spdlog/include/spdlog/sinks/sohconsole_sink.h +++ b/libultraship/libultraship/Lib/spdlog/include/spdlog/sinks/sohconsole_sink.h @@ -10,6 +10,7 @@ #include #include "SohImGuiImpl.h" #include "GameSettings.h" +#include "Cvar.h" #include #include #include @@ -45,8 +46,8 @@ protected: } formatted.push_back('\0'); const char *msg_output = formatted.data(); - if (Game::Settings.debug.soh_sink && SohImGui::console->opened) - SohImGui::console->Append("SoH Logging", priority, msg_output); + if (CVar_GetS32("gSinkEnabled", 0) && SohImGui::console->opened) + SohImGui::console->Append("SoH Logging", priority, "%s", msg_output); } void flush_() override {} @@ -66,6 +67,8 @@ private: return Priority::ERROR_LVL; case spdlog::level::critical: return Priority::ERROR_LVL; + default: + break; } return Priority::LOG_LVL; } diff --git a/libultraship/libultraship/Model.cpp b/libultraship/libultraship/Model.cpp index 27220e3bc..9e37de177 100644 --- a/libultraship/libultraship/Model.cpp +++ b/libultraship/libultraship/Model.cpp @@ -39,7 +39,7 @@ namespace Ship Vertex* vtxData = new Vertex[numVerts]; uint32_t* indicesData = new uint32_t[numPolys]; - if (vertices != NULL) + if (vertices != 0) { reader->Seek(headerStart + vertices, SeekOffsetType::Start); @@ -47,7 +47,7 @@ namespace Ship vtxData[i].pos = reader->ReadVec3f(); } - if (normals != NULL) + if (normals != 0) { reader->Seek(headerStart + normals, SeekOffsetType::Start); @@ -55,7 +55,7 @@ namespace Ship vtxData[i].normal = reader->ReadVec3f(); } - if (vertexColors != NULL) + if (vertexColors != 0) { reader->Seek(headerStart + vertexColors, SeekOffsetType::Start); @@ -63,7 +63,7 @@ namespace Ship vtxData[i].color = reader->ReadColor3b(); } - if (uvCoords != NULL) + if (uvCoords != 0) { reader->Seek(headerStart + uvCoords, SeekOffsetType::Start); @@ -71,7 +71,7 @@ namespace Ship vtxData[i].uv = reader->ReadVec2f(); } - if (boneWeights != NULL) + if (boneWeights != 0) { reader->Seek(headerStart + boneWeights, SeekOffsetType::Start); @@ -81,7 +81,7 @@ namespace Ship mdl->boneWeights[i] = reader->ReadVec2f(); } - if (faces != NULL) + if (faces != 0) { reader->Seek(headerStart + faces, SeekOffsetType::Start); reader->Read((char*)indicesData, numPolys * sizeof(uint32_t)); diff --git a/libultraship/libultraship/PulseAudioPlayer.cpp b/libultraship/libultraship/PulseAudioPlayer.cpp new file mode 100644 index 000000000..955b225d1 --- /dev/null +++ b/libultraship/libultraship/PulseAudioPlayer.cpp @@ -0,0 +1,173 @@ +#if defined(__linux__) || defined(__BSD__) + +#include "PulseAudioPlayer.h" +#include + +namespace Ship +{ + static void pas_context_state_cb(pa_context *c, void *userdata) { + switch (pa_context_get_state(c)) { + case PA_CONTEXT_READY: + case PA_CONTEXT_TERMINATED: + case PA_CONTEXT_FAILED: + *(bool*)userdata = true; + break; + default: + break; + } + } + + static void pas_stream_state_cb(pa_stream *s, void *userdata) { + switch (pa_stream_get_state(s)) { + case PA_STREAM_READY: + case PA_STREAM_FAILED: + case PA_STREAM_TERMINATED: + *(bool*)userdata = true; + break; + default: + break; + } + } + + static void pas_stream_write_cb(pa_stream* s, size_t length, void* userdata) { + } + + static void pas_update_complete(pa_stream* stream, int success, void* userdata) { + *(bool*)userdata = true; + } + + static void pas_write_complete(void* userdata) { + *(bool*)userdata = true; + } + + bool PulseAudioPlayer::Init() + { + bool done = false; + const pa_buffer_attr* applied_attr = nullptr; + + // Create mainloop + m_MainLoop = pa_mainloop_new(); + if (m_MainLoop == NULL) { + return false; + } + + // Create context and connect + m_Context = pa_context_new(pa_mainloop_get_api(m_MainLoop), "Ocarina of Time"); + if (m_Context == NULL) { + goto fail; + } + + pa_context_set_state_callback(m_Context, pas_context_state_cb, &done); + + if (pa_context_connect(m_Context, NULL, PA_CONTEXT_NOFLAGS, NULL) < 0) { + goto fail; + } + + while (!done) { + pa_mainloop_iterate(m_MainLoop, true, NULL); + } + pa_context_set_state_callback(m_Context, NULL, NULL); + if (pa_context_get_state(m_Context) != PA_CONTEXT_READY) { + goto fail; + } + + // Create stream + pa_sample_spec ss; + ss.format = PA_SAMPLE_S16LE; + ss.rate = 32000; + ss.channels = 2; + + pa_buffer_attr attr; + attr.maxlength = (1600 + 544 + 528 + 1600) * 4; + attr.tlength = (528*2 + 544) * 4; + attr.prebuf = 1500 * 4; + attr.minreq = 161 * 4; + attr.fragsize = (uint32_t)-1; + + m_Stream = pa_stream_new(m_Context, "zelda", &ss, NULL); + if (m_Stream == NULL) { + goto fail; + } + + done = false; + pa_stream_set_state_callback(m_Stream, pas_stream_state_cb, &done); + pa_stream_set_write_callback(m_Stream, pas_stream_write_cb, NULL); + if (pa_stream_connect_playback(m_Stream, NULL, &attr, PA_STREAM_ADJUST_LATENCY, NULL, NULL) < 0) { + goto fail; + } + + while (!done) { + pa_mainloop_iterate(m_MainLoop, true, NULL); + } + pa_stream_set_state_callback(m_Stream, NULL, NULL); + if (pa_stream_get_state(m_Stream) != PA_STREAM_READY) { + goto fail; + } + + applied_attr = pa_stream_get_buffer_attr(m_Stream); + SPDLOG_TRACE("maxlength: {}\ntlength: {}\nprebuf: {}\nminreq: {}\nfragsize: {}\n", + applied_attr->maxlength, applied_attr->tlength, applied_attr->prebuf, applied_attr->minreq, applied_attr->fragsize); + m_Attr = *applied_attr; + + return true; + + fail: + if (m_Stream != NULL) { + pa_stream_unref(m_Stream); + m_Stream = NULL; + } + if (m_Context != NULL) { + pa_context_disconnect(m_Context); + pa_context_unref(m_Context); + m_Context = NULL; + } + if (m_MainLoop != NULL) { + pa_mainloop_free(m_MainLoop); + m_MainLoop = NULL; + } + return false; + } + + int PulseAudioPlayer::Buffered() + { + if (m_Stream == NULL) { + return 0; + } + + bool done = false; + pa_stream_update_timing_info(m_Stream, pas_update_complete, &done); + while (!done) { + pa_mainloop_iterate(m_MainLoop, true, NULL); + } + + const pa_timing_info *info = pa_stream_get_timing_info(m_Stream); + if (info == NULL) { + SPDLOG_ERROR("pa_stream_get_timing_info failed, state is %d\n", pa_stream_get_state(m_Stream)); + } + return (info->write_index - info->read_index) / 4; + } + + int PulseAudioPlayer::GetDesiredBuffered() + { + // return 1100; + return 1680; + } + + void PulseAudioPlayer::Play(const uint8_t* buff, uint32_t len) + { + size_t ws = m_Attr.maxlength - Buffered() * 4; + if (ws < len) { + len = ws; + } + if (pa_stream_write_ext_free(m_Stream, buff, len, pas_write_complete, &m_WriteComplete, 0LL, PA_SEEK_RELATIVE) < 0) { + SPDLOG_ERROR("pa_stream_write failed"); + return; + } + while (!m_WriteComplete) { + pa_mainloop_iterate(m_MainLoop, true, NULL); + } + m_WriteComplete = false; + } +} + +#endif \ No newline at end of file diff --git a/libultraship/libultraship/PulseAudioPlayer.h b/libultraship/libultraship/PulseAudioPlayer.h new file mode 100644 index 000000000..7bc72b097 --- /dev/null +++ b/libultraship/libultraship/PulseAudioPlayer.h @@ -0,0 +1,26 @@ +#pragma once + +#if defined(__linux__) || defined(__BSD__) + +#include "AudioPlayer.h" +#include + +namespace Ship { + class PulseAudioPlayer : public AudioPlayer { + public: + PulseAudioPlayer() {} + + bool Init() override; + int Buffered() override; + int GetDesiredBuffered() override; + void Play(const uint8_t* buff, uint32_t len) override; + + private: + pa_context* m_Context = nullptr; + pa_stream* m_Stream = nullptr; + pa_mainloop* m_MainLoop = nullptr; + bool m_WriteComplete = false; + pa_buffer_attr m_Attr = {0}; + }; +} +#endif diff --git a/libultraship/libultraship/Resource.cpp b/libultraship/libultraship/Resource.cpp index 5bdfc5efd..04fc2bfbb 100644 --- a/libultraship/libultraship/Resource.cpp +++ b/libultraship/libultraship/Resource.cpp @@ -2,8 +2,8 @@ #include "DisplayList.h" #include "ResourceMgr.h" #include "Utils/BinaryReader.h" -#include "lib/tinyxml2/tinyxml2.h" -#include "lib/Fast3D/U64/PR/ultra64/gbi.h" +#include "Lib/tinyxml2/tinyxml2.h" +#include "Lib/Fast3D/U64/PR/ultra64/gbi.h" namespace Ship { @@ -25,7 +25,7 @@ namespace Ship void ResourceFile::WriteFileBinary(BinaryWriter* writer, Resource* res) { - + } void ResourceFile::WriteFileXML(tinyxml2::XMLElement* writer, Resource* res) @@ -35,17 +35,17 @@ namespace Ship Resource::~Resource() { - free(cachedGameAsset); + free(cachedGameAsset); cachedGameAsset = nullptr; - for (int i = 0; i < patches.size(); i++) + for (size_t i = 0; i < patches.size(); i++) { std::string hashStr = resMgr->HashToString(patches[i].crc); auto resShared = resMgr->GetCachedFile(hashStr); if (resShared != nullptr) { auto res = (Ship::DisplayList*)resShared.get(); - + Gfx* gfx = (Gfx*)&res->instructions[patches[i].index]; gfx->words.w1 = patches[i].origData; } diff --git a/libultraship/libultraship/Resource.h b/libultraship/libultraship/Resource.h index 1df5c5ed7..ae8dc6ce5 100644 --- a/libultraship/libultraship/Resource.h +++ b/libultraship/libultraship/Resource.h @@ -6,7 +6,7 @@ #include "GlobalCtx2.h" #include "StrHash.h" #include "File.h" -#include "lib/tinyxml2/tinyxml2.h" +#include "Lib/tinyxml2/tinyxml2.h" namespace Ship { @@ -101,10 +101,10 @@ namespace Ship class ResourcePromise { public: - std::shared_ptr Resource; - std::shared_ptr File; - std::condition_variable ResourceLoadNotifier; - std::mutex ResourceLoadMutex; + std::shared_ptr resource; + std::shared_ptr file; + std::condition_variable resourceLoadNotifier; + std::mutex resourceLoadMutex; bool bHasResourceLoaded = false; }; } \ No newline at end of file diff --git a/libultraship/libultraship/ResourceMgr.cpp b/libultraship/libultraship/ResourceMgr.cpp index b4d7b76a8..de0296d12 100644 --- a/libultraship/libultraship/ResourceMgr.cpp +++ b/libultraship/libultraship/ResourceMgr.cpp @@ -43,7 +43,7 @@ namespace Ship { const std::lock_guard ResLock(ResourceLoadMutex); bIsRunning = false; } - + FileLoadNotifier.notify_all(); ResourceLoadNotifier.notify_all(); FileLoadThread->join(); @@ -89,7 +89,7 @@ namespace Ship { OTR->LoadFile(ToLoad->path, true, ToLoad); //Lock.lock(); - + if (!ToLoad->bHasLoadError) FileCache[ToLoad->path] = ToLoad->bIsLoaded && !ToLoad->bHasLoadError ? ToLoad : nullptr; @@ -124,15 +124,15 @@ namespace Ship { // Wait for the underlying File to complete loading { - std::unique_lock FileLock(ToLoad->File->FileLoadMutex); - while (!ToLoad->File->bIsLoaded && !ToLoad->File->bHasLoadError) { - ToLoad->File->FileLoadNotifier.wait(FileLock); + std::unique_lock FileLock(ToLoad->file->FileLoadMutex); + while (!ToLoad->file->bIsLoaded && !ToLoad->file->bHasLoadError) { + ToLoad->file->FileLoadNotifier.wait(FileLock); } } - if (!ToLoad->File->bHasLoadError) + if (!ToLoad->file->bHasLoadError) { - auto UnmanagedRes = ResourceLoader::LoadResource(ToLoad->File); + auto UnmanagedRes = ResourceLoader::LoadResource(ToLoad->file); if (UnmanagedRes != nullptr) { @@ -140,13 +140,13 @@ namespace Ship { auto Res = std::shared_ptr(UnmanagedRes); if (Res != nullptr) { - std::unique_lock Lock(ToLoad->ResourceLoadMutex); + std::unique_lock Lock(ToLoad->resourceLoadMutex); ToLoad->bHasResourceLoaded = true; - ToLoad->Resource = Res; + ToLoad->resource = Res; ResourceCache[Res->file->path] = Res; - SPDLOG_DEBUG("Loaded Resource {} on ResourceMgr thread", ToLoad->File->path); + SPDLOG_DEBUG("Loaded Resource {} on ResourceMgr thread", ToLoad->file->path); // Disabled for now because it can cause random crashes //FileCache[Res->File->path] = nullptr; @@ -155,9 +155,9 @@ namespace Ship { } else { ToLoad->bHasResourceLoaded = false; - ToLoad->Resource = nullptr; + ToLoad->resource = nullptr; - SPDLOG_ERROR("Resource load FAILED {} on ResourceMgr thread", ToLoad->File->path); + SPDLOG_ERROR("Resource load FAILED {} on ResourceMgr thread", ToLoad->file->path); } //ResLock.lock(); @@ -167,10 +167,10 @@ namespace Ship { else { ToLoad->bHasResourceLoaded = false; - ToLoad->Resource = nullptr; + ToLoad->resource = nullptr; } - ToLoad->ResourceLoadNotifier.notify_all(); + ToLoad->resourceLoadNotifier.notify_all(); } SPDLOG_INFO("Resource Manager LoadResourceThread ended"); @@ -232,17 +232,17 @@ namespace Ship { if (!Promise->bHasResourceLoaded) { - std::unique_lock Lock(Promise->ResourceLoadMutex); + std::unique_lock Lock(Promise->resourceLoadMutex); while (!Promise->bHasResourceLoaded) { - Promise->ResourceLoadNotifier.wait(Lock); + Promise->resourceLoadNotifier.wait(Lock); } } - return Promise->Resource; + return Promise->resource; } std::shared_ptr ResourceMgr::LoadResourceAsync(std::string FilePath) { - StringHelper::ReplaceOriginal(FilePath, "/", "\\"); + StringHelper::ReplaceOriginal(FilePath, "\\", "/"); if (StringHelper::StartsWith(FilePath, "__OTR__")) FilePath = StringHelper::Split(FilePath, "__OTR__")[1]; @@ -257,9 +257,9 @@ namespace Ship { } std::shared_ptr FileData = LoadFile(FilePath); - Promise->File = FileData; + Promise->file = FileData; - if (Promise->File->bHasLoadError) + if (Promise->file->bHasLoadError) { Promise->bHasResourceLoaded = true; } @@ -271,7 +271,7 @@ namespace Ship { } } else { Promise->bHasResourceLoaded = true; - Promise->Resource = resCacheFind->second; + Promise->resource = resCacheFind->second; } return Promise; @@ -295,37 +295,37 @@ namespace Ship { auto PromiseList = CacheDirectoryAsync(SearchMask); auto LoadedList = std::make_shared>>(); - for (int32_t i = 0; i < PromiseList->size(); i++) { + for (size_t i = 0; i < PromiseList->size(); i++) { auto Promise = PromiseList->at(i); - std::unique_lock Lock(Promise->ResourceLoadMutex); + std::unique_lock Lock(Promise->resourceLoadMutex); while (!Promise->bHasResourceLoaded) { - Promise->ResourceLoadNotifier.wait(Lock); + Promise->resourceLoadNotifier.wait(Lock); } - LoadedList->push_back(Promise->Resource); + LoadedList->push_back(Promise->resource); } return LoadedList; } - std::shared_ptr>> ResourceMgr::DirtyDirectory(std::string SearchMask) + std::shared_ptr>> ResourceMgr::DirtyDirectory(std::string SearchMask) { auto PromiseList = CacheDirectoryAsync(SearchMask); auto LoadedList = std::make_shared>>(); - for (int32_t i = 0; i < PromiseList->size(); i++) { + for (size_t i = 0; i < PromiseList->size(); i++) { auto Promise = PromiseList->at(i); - std::unique_lock Lock(Promise->ResourceLoadMutex); + std::unique_lock Lock(Promise->resourceLoadMutex); while (!Promise->bHasResourceLoaded) { - Promise->ResourceLoadNotifier.wait(Lock); + Promise->resourceLoadNotifier.wait(Lock); } - if (Promise->Resource != nullptr) - Promise->Resource->isDirty = true; + if (Promise->resource != nullptr) + Promise->resource->isDirty = true; - LoadedList->push_back(Promise->Resource); + LoadedList->push_back(Promise->resource); } return LoadedList; diff --git a/libultraship/libultraship/ResourceMgr.h b/libultraship/libultraship/ResourceMgr.h index 5eae61abe..28e77e537 100644 --- a/libultraship/libultraship/ResourceMgr.h +++ b/libultraship/libultraship/ResourceMgr.h @@ -28,7 +28,7 @@ namespace Ship std::string HashToString(uint64_t Hash); void InvalidateResourceCache(); - + uint32_t GetGameVersion(); void SetGameVersion(uint32_t newGameVersion); std::shared_ptr LoadFileAsync(std::string FilePath); @@ -48,6 +48,7 @@ namespace Ship private: std::weak_ptr Context; + volatile bool bIsRunning; std::map> FileCache; std::map> ResourceCache; std::queue> FileLoadQueue; @@ -59,7 +60,6 @@ namespace Ship std::mutex ResourceLoadMutex; std::condition_variable FileLoadNotifier; std::condition_variable ResourceLoadNotifier; - volatile bool bIsRunning; uint32_t gameVersion; }; } \ No newline at end of file diff --git a/libultraship/libultraship/SDLController.cpp b/libultraship/libultraship/SDLController.cpp index 50bc5eabb..ab2c48b30 100644 --- a/libultraship/libultraship/SDLController.cpp +++ b/libultraship/libultraship/SDLController.cpp @@ -61,17 +61,17 @@ namespace Ship { if (Conf[ConfSection]["GUID"].compare("") == 0 || Conf[ConfSection]["GUID"].compare(INVALID_SDL_CONTROLLER_GUID) == 0 || Conf[ConfSection]["GUID"].compare(NewGuid) == 0) { auto NewCont = SDL_GameControllerOpen(i); - if (SDL_GameControllerHasSensor(NewCont, SDL_SENSOR_GYRO)) - { - SDL_GameControllerSetSensorEnabled(NewCont, SDL_SENSOR_GYRO, SDL_TRUE); - } - // We failed to load the controller. Go to next. if (NewCont == nullptr) { SPDLOG_ERROR("SDL Controller failed to open: ({})", SDL_GetError()); continue; } + if (SDL_GameControllerHasSensor(NewCont, SDL_SENSOR_GYRO)) + { + SDL_GameControllerSetSensorEnabled(NewCont, SDL_SENSOR_GYRO, SDL_TRUE); + } + guid = NewGuid; Cont = NewCont; @@ -101,7 +101,7 @@ namespace Ship { } bool SDLController::Close() { - if (SDL_GameControllerHasRumble(Cont)) { + if (CanRumble()) { SDL_GameControllerRumble(Cont, 0, 0, 0); } if (Cont != nullptr) { @@ -190,7 +190,7 @@ namespace Ship { if (SDL_GameControllerHasSensor(Cont, SDL_SENSOR_GYRO)) { size_t contNumber = GetControllerNumber(); - + float gyroData[3]; SDL_GameControllerGetSensorData(Cont, SDL_SENSOR_GYRO, gyroData, 3); @@ -347,7 +347,7 @@ namespace Ship { void SDLController::WriteToSource(ControllerCallback* controller) { - if (SDL_GameControllerHasRumble(Cont)) { + if (CanRumble()) { if (controller->rumble > 0) { float rumble_strength = CVar_GetFloat(StringHelper::Sprintf("gCont%i_RumbleStrength", GetControllerNumber()).c_str(), 1.0f); SDL_GameControllerRumble(Cont, 0xFFFF * rumble_strength, 0xFFFF * rumble_strength, 0); diff --git a/libultraship/libultraship/SDLController.h b/libultraship/libultraship/SDLController.h index 138466a89..fbffa478f 100644 --- a/libultraship/libultraship/SDLController.h +++ b/libultraship/libultraship/SDLController.h @@ -13,7 +13,12 @@ namespace Ship { void ReadFromSource(); void WriteToSource(ControllerCallback* controller); bool Connected() const { return Cont != nullptr; } - bool CanRumble() const { return SDL_GameControllerHasRumble(Cont); } + bool CanRumble() const { +#if SDL_COMPILEDVERSION >= SDL_VERSIONNUM(2,0,18) + return SDL_GameControllerHasRumble(Cont); +#endif + return true; + } std::string GetGuid() { return guid; }; @@ -30,8 +35,8 @@ namespace Ship { static bool IsGuidInUse(const std::string& guid); private: - std::string guid; SDL_GameController* Cont; + std::string guid; std::map ThresholdMapping; void LoadAxisThresholds(); diff --git a/libultraship/libultraship/Scene.cpp b/libultraship/libultraship/Scene.cpp index 9468e3a59..17d2b6976 100644 --- a/libultraship/libultraship/Scene.cpp +++ b/libultraship/libultraship/Scene.cpp @@ -137,8 +137,8 @@ namespace Ship y = 0; z = 0; unk_06 = 0; - opa; - xlu; + // opa; + // xlu; } SetMesh::SetMesh(BinaryReader* reader) : SceneCommand(reader) @@ -398,18 +398,18 @@ namespace Ship LightInfo light = LightInfo(); light.type = reader->ReadUByte(); - + light.x = reader->ReadInt16(); - light.y = reader->ReadInt16(); + light.y = reader->ReadInt16(); light.z = reader->ReadInt16(); light.r = reader->ReadUByte(); light.g = reader->ReadUByte(); light.b = reader->ReadUByte(); - + light.drawGlow = reader->ReadUByte(); light.radius = reader->ReadInt16(); - + lights.push_back(light); } } diff --git a/libultraship/libultraship/SkeletonLimb.cpp b/libultraship/libultraship/SkeletonLimb.cpp index 5020fe8f5..75fd46780 100644 --- a/libultraship/libultraship/SkeletonLimb.cpp +++ b/libultraship/libultraship/SkeletonLimb.cpp @@ -15,7 +15,7 @@ namespace Ship limb->skinVtxCnt = reader->ReadUInt16(); uint32_t skinCnt = reader->ReadUInt32(); - for (int i = 0; i < skinCnt; i++) + for (size_t i = 0; i < skinCnt; i++) { Struct_800A598C struc; diff --git a/libultraship/libultraship/SohConsole.cpp b/libultraship/libultraship/SohConsole.cpp index 618cd1e1d..29e8a5daa 100644 --- a/libultraship/libultraship/SohConsole.cpp +++ b/libultraship/libultraship/SohConsole.cpp @@ -16,7 +16,7 @@ std::map BindingToggle; static bool HelpCommand(const std::vector&) { INFO("SoH Commands:"); for(const auto& cmd : SohImGui::console->Commands) { - INFO((" - " + cmd.first).c_str()); + INFO("%s", (" - " + cmd.first).c_str()); } return CMD_SUCCESS; } @@ -35,7 +35,7 @@ std::string toLowerCase(std::string in) { static bool BindCommand(const std::vector& args) { if(args.size() > 2) { const ImGuiIO* io = &ImGui::GetIO();; - for (int k = 0; k < std::size(io->KeysData); k++) { + for (size_t k = 0; k < std::size(io->KeysData); k++) { std::string key(ImGui::GetKeyName(k)); if(toLowerCase(args[1]) == toLowerCase(key)) { @@ -55,7 +55,7 @@ static bool BindCommand(const std::vector& args) { static bool BindToggleCommand(const std::vector& args) { if (args.size() > 2) { const ImGuiIO* io = &ImGui::GetIO();; - for (int k = 0; k < std::size(io->KeysData); k++) { + for (size_t k = 0; k < std::size(io->KeysData); k++) { std::string key(ImGui::GetKeyName(k)); if (toLowerCase(args[1]) == toLowerCase(key)) { @@ -92,7 +92,7 @@ void Console::Update() { } for (auto [key, var] : BindingToggle) { if (ImGui::IsKeyPressed(key)) { - CVar* cvar = CVar_GetVar(var.c_str()); + CVar* cvar = CVar_Get(var.c_str()); Dispatch("set " + var + " " + std::to_string(cvar == nullptr ? 0 : !static_cast(cvar->value.valueS32))); } } @@ -106,7 +106,7 @@ void Console::Draw() { if (!this->opened) return; ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver); - ImGui::Begin("Console", &this->opened); + ImGui::Begin("Console", nullptr); const ImVec2 pos = ImGui::GetWindowPos(); const ImVec2 size = ImGui::GetWindowSize(); @@ -177,8 +177,10 @@ void Console::Draw() { for (const auto& filter : priority_filters) { const bool is_selected = (filter == std::string(this->level_filter)); if (ImGui::Selectable(filter.c_str(), is_selected)) + { this->level_filter = filter; if (is_selected) ImGui::SetItemDefaultFocus(); + } } ImGui::EndCombo(); } @@ -194,7 +196,7 @@ void Console::Draw() { if (ImGui::BeginTable("History", 1)) { if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_DownArrow))) - if (this->selectedId < this->Log.size() - 1) ++this->selectedId; + if (this->selectedId < (int)this->Log.size() - 1) ++this->selectedId; if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_UpArrow))) if (this->selectedId > 0) --this->selectedId; @@ -226,7 +228,7 @@ void Console::Draw() { ImGui::EndChild(); // Renders input textfield - constexpr ImGuiInputTextFlags flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackEdit | + constexpr ImGuiInputTextFlags flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackEdit | ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory; ImGui::PushItemWidth(-1); if(ImGui::InputTextWithHint("CMDInput", ">", this->InputBuffer, MAX_BUFFER_SIZE, flags, &Console::CallbackStub, this)) { @@ -317,7 +319,7 @@ int Console::CallbackStub(ImGuiInputTextCallbackData* data) { return 0; } -void Console::Append(const std::string& channel, Priority priority, const char* fmt, ...) IM_FMTARGS(4) { +void Console::Append(const std::string& channel, Priority priority, const char* fmt, ...) { char buf[1024]; va_list args; va_start(args, fmt); diff --git a/libultraship/libultraship/SohConsole.h b/libultraship/libultraship/SohConsole.h index 57ad182f8..bfbffd0b9 100644 --- a/libultraship/libultraship/SohConsole.h +++ b/libultraship/libultraship/SohConsole.h @@ -7,10 +7,10 @@ #include "Lib/ImGui/imgui.h" -#define LOG(msg, ...) SohImGui::console->Append("Main", Priority::LOG_LVL, msg, __VA_ARGS__) -#define INFO(msg, ...) SohImGui::console->Append("Main", Priority::INFO_LVL, msg, __VA_ARGS__) -#define WARNING(msg, ...) SohImGui::console->Append("Main", Priority::WARNING_LVL, msg, __VA_ARGS__) -#define ERROR(msg, ...) SohImGui::console->Append("Main", Priority::ERROR_LVL, msg, __VA_ARGS__) +#define LOG(msg, ...) SohImGui::console->Append("Main", Priority::LOG_LVL, msg, ##__VA_ARGS__) +#define INFO(msg, ...) SohImGui::console->Append("Main", Priority::INFO_LVL, msg, ##__VA_ARGS__) +#define WARNING(msg, ...) SohImGui::console->Append("Main", Priority::WARNING_LVL, msg, ##__VA_ARGS__) +#define ERROR(msg, ...) SohImGui::console->Append("Main", Priority::ERROR_LVL, msg, ##__VA_ARGS__) #define CMD_SUCCESS true #define CMD_FAILED false #define MAX_BUFFER_SIZE 255 @@ -75,7 +75,7 @@ public: void Init(); void Update(); void Draw(); - void Append(const std::string& channel, Priority priority, const char* fmt, ...); + void Append(const std::string& channel, Priority priority, const char* fmt, ...) IM_FMTARGS(4); void Dispatch(const std::string& line); static int CallbackStub(ImGuiInputTextCallbackData* data); }; \ No newline at end of file diff --git a/libultraship/libultraship/SohHooks.cpp b/libultraship/libultraship/SohHooks.cpp index d40ab87e2..7ede525d7 100644 --- a/libultraship/libultraship/SohHooks.cpp +++ b/libultraship/libultraship/SohHooks.cpp @@ -24,7 +24,7 @@ namespace ModInternal { bool handleHook(std::shared_ptr call) { std::string hookName = std::string(call->name); - for (int l = 0; l < listeners[hookName].size(); l++) { + for (size_t l = 0; l < listeners[hookName].size(); l++) { (listeners[hookName][l])(call); } return call->cancelled; diff --git a/libultraship/libultraship/SohHooks.h b/libultraship/libultraship/SohHooks.h index 111f789d0..9a41eeb0e 100644 --- a/libultraship/libultraship/SohHooks.h +++ b/libultraship/libultraship/SohHooks.h @@ -47,6 +47,7 @@ struct HookParameter { #include #include #include +#include struct HookCall { std::string name; diff --git a/libultraship/libultraship/SohImGuiImpl.cpp b/libultraship/libultraship/SohImGuiImpl.cpp index af5066159..9adbdd820 100644 --- a/libultraship/libultraship/SohImGuiImpl.cpp +++ b/libultraship/libultraship/SohImGuiImpl.cpp @@ -18,6 +18,7 @@ #include "TextureMod.h" #include "Window.h" #include "Cvar.h" +#include "GameOverlay.h" #include "Texture.h" #include "../Fast3D/gfx_pc.h" #include "Lib/stb/stb_image.h" @@ -43,6 +44,11 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPAR using namespace Ship; bool oldCursorState = true; +#define EXPERIMENTAL() \ + ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 50, 50, 255)); \ + ImGui::Text("Experimental"); \ + ImGui::PopStyleColor(); \ + ImGui::Separator(); #define TOGGLE_BTN ImGuiKey_F1 #define HOOK(b) if(b) needs_save = true; OSContPad* pads; @@ -54,8 +60,10 @@ namespace SohImGui { WindowImpl impl; ImGuiIO* io; Console* console = new Console; + GameOverlay* overlay = new GameOverlay; bool p_open = false; bool needs_save = false; + std::vector CustomTexts; int SelectedLanguage = CVar_GetS32("gLanguages", 0); //Default Language to 0=English 1=German 2=French float kokiri_col[3] = { 0.118f, 0.41f, 0.106f }; float goron_col[3] = { 0.392f, 0.078f, 0.0f }; @@ -73,6 +81,12 @@ namespace SohImGui { float navi_prop_i_col[3] = { 0.0f, 0.0f, 0.0f }; float navi_prop_o_col[3] = { 0.0f, 0.0f, 0.0f }; + const char* filters[3] = { + "Three-Point", + "Linear", + "None" + }; + std::map> windowCategories; std::map customWindows; @@ -81,11 +95,15 @@ namespace SohImGui { case Backend::SDL: ImGui_ImplSDL2_InitForOpenGL(static_cast(impl.sdl.window), impl.sdl.context); break; +#if defined(ENABLE_DX11) || defined(ENABLE_DX12) case Backend::DX11: ImGui_ImplWin32_Init(impl.dx11.window); break; +#endif + default: + break; } - + // OTRTODO: This gameplay specific stuff should not be in libultraship. This needs to be moved to soh and use sTunicColors kokiri_col[0] = 30 / 255.0f; kokiri_col[1] = 105 / 255.0f; @@ -94,7 +112,7 @@ namespace SohImGui { goron_col[0] = 100 / 255.0f; goron_col[1] = 20 / 255.0f; goron_col[2] = 0; - + zora_col[0] = 0; zora_col[1] = 60 / 255.0f; zora_col[2] = 100 / 255.0f; @@ -137,9 +155,14 @@ namespace SohImGui { case Backend::SDL: ImGui_ImplOpenGL3_Init("#version 120"); break; + +#if defined(ENABLE_DX11) || defined(ENABLE_DX12) case Backend::DX11: ImGui_ImplDX11_Init(static_cast(impl.dx11.device), static_cast(impl.dx11.device_context)); break; +#endif + default: + break; } } @@ -148,9 +171,13 @@ namespace SohImGui { case Backend::SDL: ImGui_ImplSDL2_ProcessEvent(static_cast(event.sdl.event)); break; +#if defined(ENABLE_DX11) || defined(ENABLE_DX12) case Backend::DX11: ImGui_ImplWin32_WndProcHandler(static_cast(event.win32.handle), event.win32.msg, event.win32.wparam, event.win32.lparam); break; +#endif + default: + break; } } @@ -159,9 +186,13 @@ namespace SohImGui { case Backend::SDL: ImGui_ImplSDL2_NewFrame(static_cast(impl.sdl.window)); break; +#if defined(ENABLE_DX11) || defined(ENABLE_DX12) case Backend::DX11: ImGui_ImplWin32_NewFrame(); break; +#endif + default: + break; } } @@ -170,9 +201,13 @@ namespace SohImGui { case Backend::SDL: ImGui_ImplOpenGL3_NewFrame(); break; +#if defined(ENABLE_DX11) || defined(ENABLE_DX12) case Backend::DX11: ImGui_ImplDX11_NewFrame(); break; +#endif + default: + break; } } @@ -181,9 +216,13 @@ namespace SohImGui { case Backend::SDL: ImGui_ImplOpenGL3_RenderDrawData(data); break; +#if defined(ENABLE_DX11) || defined(ENABLE_DX12) case Backend::DX11: ImGui_ImplDX11_RenderDrawData(data); break; +#endif + default: + break; } } @@ -191,17 +230,18 @@ namespace SohImGui { switch (impl.backend) { case Backend::DX11: return true; + default: + return false; } - return false; } - void SohImGui::ShowCursor(bool hide, Dialogues d) { + void ShowCursor(bool hide, Dialogues d) { if (d == Dialogues::dLoadSettings) { GlobalCtx2::GetInstance()->GetWindow()->ShowCursor(hide); return; } - if (d == Dialogues::dConsole && Game::Settings.debug.menu_bar) { + if (d == Dialogues::dConsole && CVar_GetS32("gOpenMenuBar", 0)) { return; } if (!GlobalCtx2::GetInstance()->GetWindow()->IsFullscreen()) { @@ -280,23 +320,26 @@ namespace SohImGui { } void Init(WindowImpl window_impl) { - impl = window_impl; Game::LoadSettings(); + impl = window_impl; ImGuiContext* ctx = ImGui::CreateContext(); ImGui::SetCurrentContext(ctx); io = &ImGui::GetIO(); io->ConfigFlags |= ImGuiConfigFlags_DockingEnable; + io->Fonts->AddFontDefault(); + if (UseViewports()) { io->ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; } console->Init(); + overlay->Init(); ImGuiWMInit(); ImGuiBackendInit(); ModInternal::registerHookListener({ GFX_INIT, [](const HookEvent ev) { if (GlobalCtx2::GetInstance()->GetWindow()->IsFullscreen()) - ShowCursor(Game::Settings.debug.menu_bar, Dialogues::dLoadSettings); + ShowCursor(CVar_GetS32("gOpenMenuBar", 0), Dialogues::dLoadSettings); LoadTexture("Game_Icon", "assets/ship_of_harkinian/icons/gSohIcon.png"); LoadTexture("A-Btn", "assets/ship_of_harkinian/buttons/ABtn.png"); @@ -320,7 +363,7 @@ namespace SohImGui { ModInternal::registerHookListener({ CONTROLLER_READ, [](const HookEvent ev) { pads = static_cast(ev->baseArgs["cont_pad"]); - } }); + }}); Game::InitSettings(); } @@ -334,7 +377,7 @@ namespace SohImGui { #define BindButton(btn, status) ImGui::Image(GetTextureByID(DefaultAssets[btn]->textureId), ImVec2(16.0f * scale, 16.0f * scale), ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, (status) ? 255 : 0)); - void BindAudioSlider(const char* name, const char* key, float defaultValue, SeqPlayers playerId) + void BindAudioSlider(const char* name, const char* key, float defaultValue, SeqPlayers playerId) { float value = CVar_GetFloat(key, defaultValue); @@ -380,7 +423,7 @@ namespace SohImGui { ImGui::Text(text.c_str(), val); - if (ImGui::SliderInt(id.c_str(), &val, min, max, format.c_str())) + if (ImGui::SliderInt(id.c_str(), &val, min, max, format.c_str())) { CVar_SetS32(cvarName.c_str(), val); needs_save = true; @@ -443,7 +486,7 @@ namespace SohImGui { colors[2] = b / 255.0f; { - if (ImGui::ColorEdit3(text.c_str(), colors)) + if (ImGui::ColorEdit3(text.c_str(), colors)) { CVar_SetS32((cvarName + "_Red").c_str(), (int)(colors[0] * 255)); CVar_SetS32((cvarName + "_Green").c_str(), (int)(colors[1] * 255)); @@ -453,7 +496,7 @@ namespace SohImGui { } } - void DrawMainMenuAndCalculateGameSize() { + void DrawMainMenuAndCalculateGameSize() { console->Update(); ImGuiBackendNewFrame(); ImGuiWMNewFrame(); @@ -463,7 +506,7 @@ namespace SohImGui { ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoResize; - if (Game::Settings.debug.menu_bar) window_flags |= ImGuiWindowFlags_MenuBar; + if (CVar_GetS32("gOpenMenuBar", 0)) window_flags |= ImGuiWindowFlags_MenuBar; const ImGuiViewport* viewport = ImGui::GetMainViewport(); ImGui::SetNextWindowPos(viewport->WorkPos); @@ -491,10 +534,11 @@ namespace SohImGui { ImGui::DockSpace(dockId, ImVec2(0.0f, 0.0f), ImGuiDockNodeFlags_None); if (ImGui::IsKeyPressed(TOGGLE_BTN)) { - Game::Settings.debug.menu_bar = !Game::Settings.debug.menu_bar; + bool menu_bar = CVar_GetS32("gOpenMenuBar", 0); + CVar_SetS32("gOpenMenuBar", !menu_bar); needs_save = true; - GlobalCtx2::GetInstance()->GetWindow()->dwMenubar = Game::Settings.debug.menu_bar; - ShowCursor(Game::Settings.debug.menu_bar, Dialogues::dMenubar); + GlobalCtx2::GetInstance()->GetWindow()->dwMenubar = menu_bar; + ShowCursor(menu_bar, Dialogues::dMenubar); } if (ImGui::BeginMenuBar()) { @@ -563,9 +607,42 @@ namespace SohImGui { ImGui::EndMenu(); } + if (ImGui::BeginMenu("Graphics")) + { + EnhancementSliderInt("Internal Resolution: %dx", "##IMul", "gInternalResolution", 1, 8, ""); + gfx_current_dimensions.internal_mul = CVar_GetS32("gInternalResolution", 1); + EnhancementSliderInt("MSAA: %d", "##IMSAA", "gMSAAValue", 1, 8, ""); + gfx_msaa_level = CVar_GetS32("gMSAAValue", 1); + + EXPERIMENTAL(); + ImGui::Text("Texture Filter (Needs reload)"); + GfxRenderingAPI* gapi = gfx_get_current_rendering_api(); + if (ImGui::BeginCombo("##filters", filters[gapi->get_texture_filter()])) { + for (int fId = 0; fId <= FilteringMode::NONE; fId++) { + if (ImGui::Selectable(filters[fId], fId == gapi->get_texture_filter())) { + INFO("New Filter: %s", filters[fId]); + gapi->set_texture_filter((FilteringMode)fId); + + CVar_SetS32("gTextureFilter", (int) fId); + needs_save = true; + } + + } + ImGui::EndCombo(); + } + overlay->DrawSettings(); + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Languages")) { + EnhancementRadioButton("English", "gLanguages", 0); + EnhancementRadioButton("German", "gLanguages", 1); + EnhancementRadioButton("French", "gLanguages", 2); + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("Enhancements")) { - ImGui::Text("Gameplay"); ImGui::Separator(); @@ -583,62 +660,22 @@ namespace SohImGui { EnhancementCheckbox("N64 Mode", "gN64Mode"); EnhancementCheckbox("Animated Link in Pause Menu", "gPauseLiveLink"); - EnhancementCheckbox("Disable LOD", "gDisableLOD"); EnhancementCheckbox("Enable 3D Dropped items", "gNewDrops"); EnhancementCheckbox("Dynamic Wallet Icon", "gDynamicWalletIcon"); EnhancementCheckbox("Always show dungeon entrances", "gAlwaysShowDungeonMinimapIcon"); - - if (ImGui::BeginMenu("Fixes")) { - EnhancementCheckbox("Fix L&R Pause menu", "gUniformLR"); - EnhancementCheckbox("Fix Dungeon entrances", "gFixDungeonMinimapIcon"); - ImGui::EndMenu(); - } - ImGui::EndMenu(); - } - if (ImGui::BeginMenu("Developer Tools")) - { - HOOK(ImGui::MenuItem("Stats", nullptr, &Game::Settings.debug.soh)); - HOOK(ImGui::MenuItem("Console", nullptr, &console->opened)); - - ImGui::Text("Debug"); + ImGui::Text("Fixes"); ImGui::Separator(); + EnhancementCheckbox("Fix L&R Pause menu", "gUniformLR"); + EnhancementCheckbox("Fix Dungeon entrances", "gFixDungeonMinimapIcon"); - EnhancementCheckbox("Debug Mode", "gDebugEnabled"); + EXPERIMENTAL(); + + EnhancementCheckbox("Disable LOD", "gDisableLOD"); ImGui::EndMenu(); } - if (ImGui::BeginMenu("Graphics")) - { - HOOK(ImGui::MenuItem("Anti-aliasing", nullptr, &Game::Settings.graphics.show)); - ImGui::EndMenu(); - } - - if (ImGui::BeginMenu("Cheats")) - { - if (ImGui::BeginMenu("Infinite...")) { - EnhancementCheckbox("Money", "gInfiniteMoney"); - EnhancementCheckbox("Health", "gInfiniteHealth"); - EnhancementCheckbox("Ammo", "gInfiniteAmmo"); - EnhancementCheckbox("Magic", "gInfiniteMagic"); - EnhancementCheckbox("Nayru's Love", "gInfiniteNayru"); - - ImGui::EndMenu(); - } - - EnhancementCheckbox("No Clip", "gNoClip"); - EnhancementCheckbox("Climb Everything", "gClimbEverything"); - EnhancementCheckbox("Moon Jump on L", "gMoonJumpOnL"); - EnhancementCheckbox("Super Tunic", "gSuperTunic"); - EnhancementCheckbox("Easy ISG", "gEzISG"); - EnhancementCheckbox("Unrestricted Items", "gNoRestrictItems"); - EnhancementCheckbox("Freeze Time", "gFreezeTime"); - - ImGui::EndMenu(); - - } - if (ImGui::BeginMenu("Cosmetics")) { ImGui::Text("Tunics"); @@ -663,24 +700,48 @@ namespace SohImGui { ImGui::EndMenu(); } - if (CVar_GetS32("gLanguages", 0) == 0) { - SelectedLanguage = 0; - } else if (CVar_GetS32("gLanguages", 0) == 1) { - SelectedLanguage = 1; - } else if (CVar_GetS32("gLanguages", 0) == 2) { - SelectedLanguage = 2; + if (ImGui::BeginMenu("Cheats")) + { + if (ImGui::BeginMenu("Infinite...")) { + EnhancementCheckbox("Money", "gInfiniteMoney"); + EnhancementCheckbox("Health", "gInfiniteHealth"); + EnhancementCheckbox("Ammo", "gInfiniteAmmo"); + EnhancementCheckbox("Magic", "gInfiniteMagic"); + EnhancementCheckbox("Nayru's Love", "gInfiniteNayru"); + + ImGui::EndMenu(); + } + + EnhancementCheckbox("No Clip", "gNoClip"); + EnhancementCheckbox("Climb Everything", "gClimbEverything"); + EnhancementCheckbox("Moon Jump on L", "gMoonJumpOnL"); + EnhancementCheckbox("Super Tunic", "gSuperTunic"); + EnhancementCheckbox("Easy ISG", "gEzISG"); + EnhancementCheckbox("Unrestricted Items", "gNoRestrictItems"); + EnhancementCheckbox("Freeze Time", "gFreezeTime"); + + ImGui::EndMenu(); } - if (ImGui::BeginMenu("Languages")) { - EnhancementRadioButton("English", "gLanguages", 0); - EnhancementRadioButton("German", "gLanguages", 1); - EnhancementRadioButton("French", "gLanguages", 2); + + if (ImGui::BeginMenu("Developer Tools")) + { + EnhancementCheckbox("Stats", "gStatsEnabled"); + EnhancementCheckbox("Console", "gConsoleEnabled"); + console->opened = CVar_GetS32("gConsoleEnabled", 0); + EnhancementCheckbox("OoT Debug Mode", "gDebugEnabled"); + ImGui::EndMenu(); } for (const auto& category : windowCategories) { if (ImGui::BeginMenu(category.first.c_str())) { for (const std::string& name : category.second) { - HOOK(ImGui::MenuItem(name.c_str(), nullptr, &customWindows[name].enabled)); + std::string varName(name); + varName.erase(std::ranges::remove_if(varName, isspace).begin(), varName.end()); + std::string toggleName = "g" + varName + "Enabled"; + + EnhancementCheckbox(name, toggleName); + customWindows[name].enabled = CVar_GetS32(toggleName.c_str(), 0); } ImGui::EndMenu(); } @@ -691,28 +752,21 @@ namespace SohImGui { ImGui::End(); - if (Game::Settings.debug.soh) { + if (CVar_GetS32("gStatsEnabled", 0)) { const float framerate = ImGui::GetIO().Framerate; ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0)); ImGui::Begin("Debug Stats", nullptr, ImGuiWindowFlags_None); +#ifdef _WIN32 ImGui::Text("Platform: Windows"); +#else + ImGui::Text("Platform: Linux"); +#endif ImGui::Text("Status: %.3f ms/frame (%.1f FPS)", 1000.0f / framerate, framerate); ImGui::End(); ImGui::PopStyleColor(); } - if (Game::Settings.graphics.show) { - ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0)); - ImGui::Begin("Anti-aliasing settings", nullptr, ImGuiWindowFlags_None); - ImGui::Text("Internal Resolution:"); - ImGui::SliderInt("Mul", reinterpret_cast(&gfx_current_dimensions.internal_mul), 1, 8); - ImGui::Text("MSAA:"); - ImGui::SliderInt("MSAA", reinterpret_cast(&gfx_msaa_level), 1, 8); - ImGui::End(); - ImGui::PopStyleColor(); - } - console->Draw(); for (auto& windowIter : customWindows) { @@ -753,6 +807,8 @@ namespace SohImGui { pos = ImVec2(size.x / 2 - sw / 2, 0); size = ImVec2(sw, size.y); } + + overlay->Draw(); } void DrawFramebufferAndGameInput() { @@ -862,4 +918,16 @@ namespace SohImGui { ImTextureID GetTextureByName(const std::string& name) { return GetTextureByID(DefaultAssets[name]->textureId); } + + ImTextureID GetTextureByID(int id) { +#ifdef ENABLE_DX11 + if (impl.backend == Backend::DX11) + { + ImTextureID gfx_d3d11_get_texture_by_id(int id); + return gfx_d3d11_get_texture_by_id(id); + } +#else + return reinterpret_cast(id); +#endif + } } diff --git a/libultraship/libultraship/SohImGuiImpl.h b/libultraship/libultraship/SohImGuiImpl.h index c4fe3f825..dd0ec9fd3 100644 --- a/libultraship/libultraship/SohImGuiImpl.h +++ b/libultraship/libultraship/SohImGuiImpl.h @@ -1,5 +1,6 @@ #pragma once +#include "GameOverlay.h" #include "Lib/ImGui/imgui.h" #include "SohConsole.h" @@ -58,6 +59,8 @@ namespace SohImGui { } CustomWindow; extern Console* console; + extern Ship::GameOverlay* overlay; + extern bool needs_save; void Init(WindowImpl window_impl); void Update(EventImpl event); diff --git a/libultraship/libultraship/Utils.cpp b/libultraship/libultraship/Utils.cpp index e36ba29f5..d54952c77 100644 --- a/libultraship/libultraship/Utils.cpp +++ b/libultraship/libultraship/Utils.cpp @@ -1,9 +1,14 @@ #include "Utils.h" +#include + +#ifdef _MSC_VER +#define strdup _strdup +#endif namespace Utils { std::vector SplitText(const std::string text, char separator = ' ', bool keep_quotes = false) { std::vector args; - char* input = _strdup(text.c_str()); + char* input = strdup(text.c_str()); const size_t length = strlen(input); bool inQuotes = false; diff --git a/libultraship/libultraship/WasapiAudioPlayer.cpp b/libultraship/libultraship/WasapiAudioPlayer.cpp index 26e4504d3..30cb10905 100644 --- a/libultraship/libultraship/WasapiAudioPlayer.cpp +++ b/libultraship/libultraship/WasapiAudioPlayer.cpp @@ -1,3 +1,4 @@ +#ifdef _WIN32 #include "WasapiAudioPlayer.h" #include "spdlog/spdlog.h" @@ -169,4 +170,5 @@ namespace Ship { } return S_OK; } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/libultraship/libultraship/WasapiAudioPlayer.h b/libultraship/libultraship/WasapiAudioPlayer.h index 5067d01a2..dac7dd7a7 100644 --- a/libultraship/libultraship/WasapiAudioPlayer.h +++ b/libultraship/libultraship/WasapiAudioPlayer.h @@ -1,4 +1,7 @@ #pragma once + +#ifdef _WIN32 + #include "AudioPlayer.h" #include #include @@ -39,3 +42,4 @@ namespace Ship { bool started; }; } +#endif diff --git a/libultraship/libultraship/Window.cpp b/libultraship/libultraship/Window.cpp index 0feb7229f..e7c221e41 100644 --- a/libultraship/libultraship/Window.cpp +++ b/libultraship/libultraship/Window.cpp @@ -12,6 +12,8 @@ #include "Matrix.h" #include "AudioPlayer.h" #include "WasapiAudioPlayer.h" +#include "PulseAudioPlayer.h" +#include "SDLAudioPlayer.h" #include "Lib/Fast3D/gfx_pc.h" #include "Lib/Fast3D/gfx_sdl.h" #include "Lib/Fast3D/gfx_opengl.h" @@ -48,7 +50,7 @@ extern "C" { } // TODO: This for loop is debug. Burn it with fire. - for (size_t i = 0; i < SDL_NumJoysticks(); i++) { + for (int i = 0; i < SDL_NumJoysticks(); i++) { if (SDL_IsGameController(i)) { // Get the GUID from SDL char buf[33]; @@ -207,7 +209,7 @@ extern "C" { return (char*)res->imageData; } - void ResourceMgr_WriteTexS16ByName(char* texPath, int index, s16 value) { + void ResourceMgr_WriteTexS16ByName(char* texPath, size_t index, s16 value) { const auto res = static_cast(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(texPath).get()); if (res != nullptr) @@ -237,7 +239,7 @@ extern "C" { } } -extern "C" GfxWindowManagerAPI gfx_sdl; +extern GfxWindowManagerAPI gfx_sdl; void SetWindowManager(GfxWindowManagerAPI** WmApi, GfxRenderingAPI** RenderingApi, const std::string& gfx_backend); namespace Ship { @@ -397,6 +399,12 @@ namespace Ship { } void Window::SetAudioPlayer() { +#ifdef _WIN32 APlayer = std::make_shared(); +#elif defined(__linux) + APlayer = std::make_shared(); +#else + APlayer = std::make_shared(); +#endif } } diff --git a/libultraship/libultraship/WindowShim.cpp b/libultraship/libultraship/WindowShim.cpp index 96b636aff..4469c5c29 100644 --- a/libultraship/libultraship/WindowShim.cpp +++ b/libultraship/libultraship/WindowShim.cpp @@ -23,7 +23,9 @@ void SetWindowManager(struct GfxWindowManagerAPI** WmApi, struct GfxRenderingAPI #ifdef ENABLE_OPENGL *RenderingApi = &gfx_opengl_api; #if defined(__linux__) - *WmApi = &gfx_glx; + // LINUX_TODO: + // *WmApi = &gfx_glx; + *WmApi = &gfx_sdl; #else *WmApi = &gfx_sdl; #endif diff --git a/libultraship/libultraship/libultraship.vcxproj b/libultraship/libultraship/libultraship.vcxproj index 3bf81a67d..b3448e7b0 100644 --- a/libultraship/libultraship/libultraship.vcxproj +++ b/libultraship/libultraship/libultraship.vcxproj @@ -256,6 +256,7 @@ + @@ -343,6 +344,7 @@ + diff --git a/libultraship/libultraship/libultraship.vcxproj.filters b/libultraship/libultraship/libultraship.vcxproj.filters index 5079d826e..8ac4f0afb 100644 --- a/libultraship/libultraship/libultraship.vcxproj.filters +++ b/libultraship/libultraship/libultraship.vcxproj.filters @@ -88,6 +88,9 @@ {bd6557f1-9480-413b-b0cd-843f8efc1939} + + {3285ab8a-06d8-4dac-9af9-efb2a9723ab1} + @@ -339,6 +342,9 @@ Source Files\CustomImpl + + Source Files\CustomImpl\Overlay + @@ -629,5 +635,8 @@ Source Files\Resources + + Source Files\CustomImpl\Overlay + \ No newline at end of file diff --git a/libultraship/libultraship/mixer.c b/libultraship/libultraship/mixer.c index b81eb915a..302a54ef4 100644 --- a/libultraship/libultraship/mixer.c +++ b/libultraship/libultraship/mixer.c @@ -449,13 +449,16 @@ void aFilterImpl(uint8_t flags, uint16_t count_or_buf, int16_t *state_or_filter) int16_t *buf = BUF_S16(count_or_buf); if (flags == A_INIT) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmemset-elt-size" memset(tmp, 0, 8 * sizeof(int16_t)); +#pragma GCC diagnostic pop memset(tmp2, 0, 8 * sizeof(int16_t)); } else { memcpy(tmp, state_or_filter, 8 * sizeof(int16_t)); memcpy(tmp2, state_or_filter + 8, 8 * sizeof(int16_t)); } - + for (int i = 0; i < 8; i++) { rspa.filter[i] = (tmp2[i] + rspa.filter[i]) / 2; } diff --git a/libultraship/libultraship/stox.cpp b/libultraship/libultraship/stox.cpp index 75fcdfbf0..fa2dff974 100644 --- a/libultraship/libultraship/stox.cpp +++ b/libultraship/libultraship/stox.cpp @@ -1,3 +1,4 @@ +#include #include "stox.h" #include "spdlog/spdlog.h" diff --git a/soh/.gitignore b/soh/.gitignore index fafae443d..5920cfba7 100644 --- a/soh/.gitignore +++ b/soh/.gitignore @@ -25,6 +25,10 @@ docs/doxygen/ *.map *.dump out.txt +shipofharkinian.ini +imgui.ini +oot.otr +oot_save.sav # Tool artifacts tools/mipspro7.2_compiler/ @@ -279,7 +283,7 @@ ClientBin/ *.publishsettings orleans.codegen.cs -# Including strong name files can present a security risk +# Including strong name files can present a security risk # (https://github.com/github/gitignore/pull/2483#issue-259490424) #*.snk @@ -375,7 +379,7 @@ __pycache__/ # OpenCover UI analysis results OpenCover/ -# Azure Stream Analytics local run output +# Azure Stream Analytics local run output ASALocalRun/ # MSBuild Binary and Structured Log @@ -384,7 +388,7 @@ ASALocalRun/ # NVidia Nsight GPU debugger configuration file *.nvuser -# MFractors (Xamarin productivity tool) working folder +# MFractors (Xamarin productivity tool) working folder .mfractor/ *.out @@ -397,6 +401,7 @@ ZAPDUtils/ZAPDUtils.a build/ ZAPDUtils/build/ ZAPD/BuildInfo.h +cvars.cfg DebugObj/* ReleaseObj/* \ No newline at end of file diff --git a/soh/Makefile b/soh/Makefile new file mode 100644 index 000000000..be46f55e7 --- /dev/null +++ b/soh/Makefile @@ -0,0 +1,158 @@ +CXX := g++ +CC := gcc +LD := lld +AR := ar +FORMAT := clang-format-11 +ZAPD := ../ZAPDTR/ZAPD.out + +LIBULTRASHIP := ../libultraship/libultraship.a +ZAPDUTILS := ../ZAPDTR/ZAPDUtils/ZAPDUtils.a + +ASAN ?= 0 +DEBUG ?= 1 +OPTFLAGS ?= -O0 +LTO ?= 0 + +WARN := \ + -Wno-return-type \ + -funsigned-char \ + -m32 -mhard-float -fno-stack-protector -fno-common -fno-zero-initialized-in-bss -fno-strict-aliasing -fno-inline-functions -fno-inline-small-functions -fno-toplevel-reorder -ffreestanding -fwrapv \ + +CXXFLAGS := $(WARN) -std=c++20 -D_GNU_SOURCE -fpermissive -no-pie -nostdlib -march=i386 +CFLAGS := $(WARN) -std=c99 -D_GNU_SOURCE -no-pie -nostdlib -march=i386 +LDFLAGS := -m32 +CPPFLAGS := -MMD + +ifneq ($(DEBUG),0) + CXXFLAGS += -g + CFLAGS += -g +endif + +ifneq ($(ASAN),0) + CXXFLAGS += -fsanitize=address + LDFLAGS += -fsanitize=address +endif + +ifneq ($(LTO),0) + CXXFLAGS += -flto + LDFLAGS += -flto +endif + +TARGET := soh.elf + +INC_DIRS := $(addprefix -I, \ + . \ + assets \ + build \ + include \ + src \ + ../ZAPDTR/ZAPDUtils \ + ../libultraship/libultraship \ + ../libultraship/libultraship/Lib/spdlog/include \ + ../libultraship/libultraship/Lib/Fast3D/U64 \ + ../libultraship/libultraship/Lib/Fast3D/U64/PR \ +) + +LDDIRS := $(addprefix -L, \ + ../external \ + ../libultraship/ \ +) + +LDLIBS := \ + $(ZAPDUTILS) \ + $(addprefix -l, \ + X11 \ + dl \ + bz2 \ + z \ + pthread \ + atomic \ + SDL2 \ + GL \ + GLEW \ + storm \ + pulse\ + ultraship \ +) \ + +ASSET_BIN_DIRS := $(shell find assets/* -type d -not -path "assets/xml*") +ASSET_FILES_XML := $(foreach dir,$(ASSET_BIN_DIRS),$(wildcard $(dir)/*.xml)) +ASSET_FILES_BIN := $(foreach dir,$(ASSET_BIN_DIRS),$(wildcard $(dir)/*.bin)) +ASSET_FILES_OUT := $(foreach f,$(ASSET_FILES_XML:.xml=.c),$f) \ + $(foreach f,$(ASSET_FILES_BIN:.bin=.bin.inc.c),build/$f) + +TEXTURE_FILES_PNG := $(foreach dir,$(ASSET_BIN_DIRS),$(wildcard $(dir)/*.png)) +TEXTURE_FILES_JPG := $(foreach dir,$(ASSET_BIN_DIRS),$(wildcard $(dir)/*.jpg)) +TEXTURE_FILES_OUT := $(foreach f,$(TEXTURE_FILES_PNG:.png=.inc.c),build/$f) \ + $(foreach f,$(TEXTURE_FILES_JPG:.jpg=.jpg.inc.c),build/$f) \ + +CXX_FILES := \ + $(shell find soh -type f -name *.cpp) + +C_FILES := \ + $(shell find soh -type f -name *.c) \ + $(shell find src/boot -type f -name *.c) \ + $(shell find src/buffers -type f -name *.c) \ + $(shell find src/code -type f -name *.c) \ + $(shell find src/overlays -type f -name *.c) \ + src/libultra/gu/coss.c \ + src/libultra/gu/guLookAt.c \ + src/libultra/gu/guLookAtHilite.c \ + src/libultra/gu/guPerspectiveF.c \ + src/libultra/gu/guPosition.c \ + src/libultra/gu/guS2DInitBg.c \ + src/libultra/gu/ortho.c \ + src/libultra/gu/rotate.c \ + src/libultra/gu/sins.c \ + src/libultra/gu/sintable.c \ + src/libultra/libc/sprintf.c + +O_FILES := \ + $(C_FILES:%.c=build/%.o) \ + $(CXX_FILES:%.cpp=build/%.o) +D_FILES := $(O_FILES:%.o=%.d) + +# create build directory +SRC_DIRS := $(shell find . -type d -a -not -path "*build*") +$(shell mkdir -p $(SRC_DIRS:%=build/%)) + +all: + $(MAKE) -C ../libultraship + $(MAKE) $(TARGET) + +setup: + cd ../OTRExporter && python3 extract_baserom.py + $(MAKE) mpq + +mpq: + $(MAKE) -C ../libultraship + $(MAKE) -C ../OTRExporter/OTRExporter + $(MAKE) -C ../ZAPDTR + rm -rf ../OTRExporter/oot.otr + cd ../OTRExporter && python3 extract_assets.py + cp ../OTRExporter/oot.otr . + +distclean: clean + $(RM) -r baserom/ + $(MAKE) clean -C ../libultraship + $(MAKE) clean -C ../OTRExporter/OTRExporter + $(MAKE) clean -C ../ZAPDTR + +clean: + rm -rf build $(TARGET) + +.PHONY: all clean distclean setup mpq + +build/%.o: %.cpp + $(CXX) -c $(CXXFLAGS) $(CPPFLAGS) $(OPTFLAGS) $(INC_DIRS) $< -o $@ + +build/%.o: %.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $(OPTFLAGS) $(INC_DIRS) $< -o $@ + +# make soh depend on libultraship +$(TARGET): $(LIBULTRASHIP) + +$(TARGET): $(O_FILES) + $(CXX) $^ -o $@ $(LDFLAGS) -fuse-ld=$(LD) $(LDDIRS) $(LDLIBS) + +-include $(D_FILES) \ No newline at end of file diff --git a/soh/include/alloca.h b/soh/include/alloca.h index 9c6a0ab94..10025b7f7 100644 --- a/soh/include/alloca.h +++ b/soh/include/alloca.h @@ -1,7 +1,7 @@ #ifndef ALLOCA_H #define ALLOCA_H -void* alloca(u32); +// void* alloca(u32); //#define alloca __builtin_alloca #define alloca malloc diff --git a/soh/include/functions.h b/soh/include/functions.h index 7d368edb6..4cbc285a3 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -14,7 +14,7 @@ extern "C" #if defined(INCLUDE_GAME_PRINTF) && !defined(NDEBUG) #define osSyncPrintf(fmt, ...) lusprintf(__FILE__, __LINE__, 0, fmt, __VA_ARGS__) #else -#define osSyncPrintf(fmt, ...) osSyncPrintfUnused(fmt, __VA_ARGS__) +#define osSyncPrintf(fmt, ...) osSyncPrintfUnused(fmt, ##__VA_ARGS__) #endif f32 fabsf(f32 f); diff --git a/soh/include/global.h b/soh/include/global.h index 4845728dd..2e4808fe0 100644 --- a/soh/include/global.h +++ b/soh/include/global.h @@ -4,8 +4,8 @@ #include "functions.h" #include "variables.h" #include "macros.h" -#include "soh\OTRGlobals.h" -#include "soh\Enhancements\gameconsole.h" +#include "soh/OTRGlobals.h" +#include "soh/Enhancements/gameconsole.h" #include "Cvar.h" diff --git a/soh/include/macros.h b/soh/include/macros.h index c57effe02..a621a65f8 100644 --- a/soh/include/macros.h +++ b/soh/include/macros.h @@ -205,6 +205,14 @@ extern GraphicsContext* __gfxCtx; #define ALIGNED8 #endif -#define SEG_ADDR(seg, addr) (addr | (seg << 24) | 0xF0000000) +#define SEG_ADDR(seg, addr) (addr | (seg << 24) | 1) + +#ifdef _MSC_VER +#define BOMSWAP16 _byteswap_ushort +#define BOMSWAP32 _byteswap_ulong +#else +#define BOMSWAP16 __builtin_bswap16 +#define BOMSWAP32 __builtin_bswap32 +#endif #endif diff --git a/soh/include/ultra64.h b/soh/include/ultra64.h index 65ef6d147..c2e0e9b29 100644 --- a/soh/include/ultra64.h +++ b/soh/include/ultra64.h @@ -1,6 +1,9 @@ #ifndef ULTRA64_H #define ULTRA64_H +#include +#include +#include #include "ultra64/types.h" #include "unk.h" diff --git a/soh/soh.vcxproj b/soh/soh.vcxproj index 2bd4380b9..418fdd057 100644 --- a/soh/soh.vcxproj +++ b/soh/soh.vcxproj @@ -278,6 +278,7 @@ + diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp index ff69830e7..189230798 100644 --- a/soh/soh/Enhancements/debugconsole.cpp +++ b/soh/soh/Enhancements/debugconsole.cpp @@ -7,6 +7,8 @@ #define PATH_HACK #include #include + +#include "Lib/ImGui/imgui_internal.h" #undef PATH_HACK #undef Path @@ -18,7 +20,7 @@ extern "C" { extern GlobalContext* gGlobalCtx; } -#include "cvar.h" +#include "Cvar.h" #define CMD_REGISTER SohImGui::BindCmd @@ -122,7 +124,7 @@ static bool RuppeHandler(const std::vector& args) { try { rupeeAmount = std::stoi(args[1]); } - catch (std::invalid_argument const& ex) { + catch (std::invalid_argument const& ex) { ERROR("[SOH] Rupee count must be an integer."); return CMD_FAILED; } @@ -168,13 +170,13 @@ static bool ResetHandler(std::vector args) { ERROR("GlobalCtx == nullptr"); return CMD_FAILED; } - + SET_NEXT_GAMESTATE(&gGlobalCtx->state, TitleSetup_Init, GameState); gGlobalCtx->state.running = false; return CMD_SUCCESS; } -const static std::map ammoItems{ +const static std::map ammoItems{ { "sticks", ITEM_STICK }, { "deku_sticks", ITEM_STICK }, { "nuts", ITEM_NUT }, { "deku_nuts", ITEM_NUT }, { "bombs", ITEM_BOMB }, { "arrows", ITEM_BOW }, @@ -194,7 +196,7 @@ static bool AmmoHandler(const std::vector& args) { try { count = std::stoi(args[2]); - } catch (std::invalid_argument const& ex) { + } catch (std::invalid_argument const& ex) { ERROR("Ammo count must be an integer"); return CMD_FAILED; } @@ -203,7 +205,7 @@ static bool AmmoHandler(const std::vector& args) { ERROR("Ammo count must be positive"); return CMD_FAILED; } - + const auto& it = ammoItems.find(args[1]); if (it == ammoItems.end()) { @@ -213,7 +215,7 @@ static bool AmmoHandler(const std::vector& args) { // I dont think you can do OOB with just this AMMO(it->second) = count; - + //To use a change by uncomment this //Inventory_ChangeAmmo(it->second, count); } @@ -236,7 +238,7 @@ static bool BottleHandler(const std::vector& args) { unsigned int slot; try { slot = std::stoi(args[2]); - } catch (std::invalid_argument const& ex) { + } catch (std::invalid_argument const& ex) { ERROR("[SOH] Bottle slot must be an integer."); return CMD_FAILED; } @@ -275,7 +277,7 @@ static bool ItemHandler(const std::vector& args) { return CMD_FAILED; } - gSaveContext.inventory.items[std::stoi(args[1])] = std::stoi(args[2]); + gSaveContext.inventory.items[std::stoi(args[1])] = std::stoi(args[2]); return CMD_SUCCESS; } @@ -334,7 +336,7 @@ static bool SetCVarHandler(const std::vector& args) { int vType = CheckVarType(args[2]); if (vType == VARTYPE_STRING) - CVar_SetString(args[1].c_str(), (char*)args[2].c_str()); + CVar_SetString(args[1].c_str(), args[2].c_str()); else if (vType == VARTYPE_FLOAT) CVar_SetFloat(args[1].c_str(), std::stof(args[2])); else @@ -351,7 +353,7 @@ static bool GetCVarHandler(const std::vector& args) { if (args.size() < 2) return CMD_FAILED; - CVar* cvar = CVar_GetVar(args[1].c_str()); + CVar* cvar = CVar_Get(args[1].c_str()); if (cvar != nullptr) { @@ -414,8 +416,11 @@ void DebugConsole_Init(void) { { { "slot", ArgumentType::NUMBER }, { "item id", ArgumentType::NUMBER } } }); CMD_REGISTER("entrance", { EntranceHandler, "Sends player to the entered entrance (hex)", { { "entrance", ArgumentType::NUMBER } } }); +} - DebugConsole_LoadCVars(); +template bool is_number(const std::string& s) { + Numeric n; + return ((std::istringstream(s) >> n >> std::ws).eof()); } void DebugConsole_LoadCVars() @@ -424,7 +429,20 @@ void DebugConsole_LoadCVars() const auto lines = File::ReadAllLines("cvars.cfg"); for (const std::string& line : lines) { - SohImGui::console->Dispatch(line); + std::vector cfg = StringHelper::Split(line, " = "); + if (line.empty()) continue; + if (cfg.size() < 2) continue; + if (cfg[1].find("\"") != std::string::npos) { + std::string value(cfg[1]); + value.erase(std::ranges::remove(value, '\"').begin(), value.end()); + CVar_SetString(cfg[0].c_str(), ImStrdup(value.c_str())); + } + if (is_number(cfg[1])) { + CVar_SetFloat(cfg[0].c_str(), std::stof(cfg[1])); + } + if (is_number(cfg[1])) { + CVar_SetS32(cfg[0].c_str(), std::stoi(cfg[1])); + } } } } @@ -435,11 +453,11 @@ void DebugConsole_SaveCVars() for (const auto &cvar : cvars) { if (cvar.second->type == CVAR_TYPE_STRING) - output += StringHelper::Sprintf("set %s %s\n", cvar.first.c_str(), cvar.second->value.valueStr); + output += StringHelper::Sprintf("%s = \"%s\"\n", cvar.first.c_str(), cvar.second->value.valueStr); else if (cvar.second->type == CVAR_TYPE_S32) - output += StringHelper::Sprintf("set %s %i\n", cvar.first.c_str(), cvar.second->value.valueS32); + output += StringHelper::Sprintf("%s = %i\n", cvar.first.c_str(), cvar.second->value.valueS32); else if (cvar.second->type == CVAR_TYPE_FLOAT) - output += StringHelper::Sprintf("set %s %f\n", cvar.first.c_str(), cvar.second->value.valueFloat); + output += StringHelper::Sprintf("%s = %f\n", cvar.first.c_str(), cvar.second->value.valueFloat); } File::WriteAllText("cvars.cfg", output); diff --git a/soh/soh/Enhancements/debugger/colViewer.cpp b/soh/soh/Enhancements/debugger/colViewer.cpp index ad9d341d4..bbf791f67 100644 --- a/soh/soh/Enhancements/debugger/colViewer.cpp +++ b/soh/soh/Enhancements/debugger/colViewer.cpp @@ -4,6 +4,7 @@ #include #include +#include extern "C" { #include @@ -322,7 +323,7 @@ void CreateSphereData() { } void InitColViewer() { - SohImGui::AddWindow("Debug", "Collision Viewer", DrawColViewerWindow); + SohImGui::AddWindow("Developer Tools", "Collision Viewer", DrawColViewerWindow); CreateCylinderData(); CreateSphereData(); diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp index e2ed02705..800f8d5b2 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp @@ -251,15 +251,31 @@ void DrawGroupWithBorder(T&& drawFunc) { ImGui::EndGroup(); } +char z2ASCII(int code) { + int ret; + if (code < 10) { //Digits + ret = code + 0x30; + } else if (code >= 10 && code < 36) { //Uppercase letters + ret = code + 0x37; + } else if (code >= 36 && code < 62) { //Lowercase letters + ret = code + 0x3D; + } else if (code == 62) { //Space + ret = code - 0x1E; + } else if (code == 63 || code == 64) { // _ and . + ret = code - 0x12; + } else { + ret = code; + } + return char(ret); + +} + void DrawInfoTab() { - // TODO This is the bare minimum to get the player name showing - // There will need to be more effort to get it robust and editable + // TODO Needs a better method for name changing but for now this will work. std::string name; + ImU16 one = 1; for (int i = 0; i < 8; i++) { - char letter = gSaveContext.playerName[i] + 0x3D; - if (letter == '{') { - letter = '\0'; - } + char letter = z2ASCII(gSaveContext.playerName[i]); name += letter; } name += '\0'; @@ -268,6 +284,14 @@ void DrawInfoTab() { ImGui::Text("Name: %s", name.c_str()); InsertHelpHoverText("Player Name"); + std::string nameID; + for (int i = 0; i < 8; i++) { + nameID = z2ASCII(i); + if (i % 4 != 0) { + ImGui::SameLine(); + } + ImGui::InputScalar(nameID.c_str(), ImGuiDataType_U8, &gSaveContext.playerName[i], &one, NULL); + } // Use an intermediary to keep the health from updating (and potentially killing the player) // until it is done being edited @@ -377,21 +401,101 @@ void DrawInfoTab() { ImGui::InputScalar("Bgs Day Count", ImGuiDataType_S32, &gSaveContext.bgsDayCount); InsertHelpHoverText("Total number of days elapsed since giving Biggoron the claim check"); - // TODO Changing Link's age is more involved than just setting gSaveContext.linkAge - // It might not fit here and instead should be only changable when changing scenes - /* - if (ImGui::BeginCombo("Link Age", LINK_IS_ADULT ? "Adult" : "Child")) { - if (ImGui::Selectable("Adult")) { - gSaveContext.linkAge = 0; + ImGui::InputScalar("Entrance Index", ImGuiDataType_S32, &gSaveContext.entranceIndex); + InsertHelpHoverText("From which entrance did Link arrive?"); + + ImGui::InputScalar("Cutscene Index", ImGuiDataType_S32, &gSaveContext.cutsceneIndex); + InsertHelpHoverText("Which cutscene is this?"); + + ImGui::InputScalar("Navi Timer", ImGuiDataType_U16, &gSaveContext.naviTimer); + InsertHelpHoverText("Navi wants to talk at 600 units, decides not to at 3000."); + + ImGui::InputScalar("Timer 1 State", ImGuiDataType_S16, &gSaveContext.timer1State); + InsertHelpHoverText("Heat timer, race timer, etc. Has white font"); + + ImGui::InputScalar("Timer 1 Value", ImGuiDataType_S16, &gSaveContext.timer1Value, &one, NULL); + InsertHelpHoverText("Time, in seconds"); + + ImGui::InputScalar("Timer 2 State", ImGuiDataType_S16, &gSaveContext.timer2State); + InsertHelpHoverText("Trade timer, Ganon collapse timer, etc. Has yellow font"); + + ImGui::InputScalar("Timer 2 Value", ImGuiDataType_S16, &gSaveContext.timer2Value, &one, NULL); + InsertHelpHoverText("Time, in seconds"); + + const char* audioName; + switch (gSaveContext.audioSetting) { + case 0: + audioName = "Stereo"; + break; + case 1: + audioName = "Mono"; + break; + case 2: + audioName = "Headset"; + break; + case 3: + audioName = "Surround"; + break; + default: + audioName = "?"; + } + if (ImGui::BeginCombo("Audio", audioName)) { + if (ImGui::Selectable("Stereo")) { + gSaveContext.audioSetting = 0; } - if (ImGui::Selectable("Child")) { - gSaveContext.linkAge = 1; + if (ImGui::Selectable("Mono")) { + gSaveContext.audioSetting = 1; + } + if (ImGui::Selectable("Headset")) { + gSaveContext.audioSetting = 2; + } + if (ImGui::Selectable("Surround")) { + gSaveContext.audioSetting = 3; } ImGui::EndCombo(); } - */ + InsertHelpHoverText("Sound setting"); + + bool n64DDFlag = gSaveContext.n64ddFlag != 0; + if (ImGui::Checkbox("64 DD file?", &n64DDFlag)) { + gSaveContext.n64ddFlag = n64DDFlag; + } + InsertHelpHoverText("WARNING! If you save, your file may be locked! Use caution!"); + + if (ImGui::BeginCombo("Z Target Mode", gSaveContext.zTargetSetting ? "Hold" : "Switch")) { + if (ImGui::Selectable("Switch")) { + gSaveContext.zTargetSetting = 0; + } + if (ImGui::Selectable("Hold")) { + gSaveContext.zTargetSetting = 1; + } + ImGui::EndCombo(); + } + InsertHelpHoverText("Z-Targeting behavior"); + + ImGui::PushItemWidth(ImGui::GetFontSize() * 10); + static std::array minigameHS = { "Horseback Archery", + "Big Poe Points", + "Fishing", + "Malon's Obstacle Course", + "Running Man Race", + "?", + "Dampe's Race" }; + + if (ImGui::TreeNode("Minigames")) { + for (int i = 0; i < 7; i++) { + if (i == 5) { //HS_UNK_05 is unused + continue; + } + std::string minigameLbl = minigameHS[i]; + ImGui::InputScalar(minigameLbl.c_str(), ImGuiDataType_S32, &gSaveContext.highScores[i], &one, NULL); + } + + ImGui::TreePop(); + } + ImGui::PopItemWidth(); } @@ -505,7 +609,7 @@ void DrawInventoryTab() { } // Draw a flag bitfield as an grid of checkboxes -void DrawFlagArray(const std::string& name, uint32_t& flags) { +void DrawFlagArray32(const std::string& name, uint32_t& flags) { ImGui::PushID(name.c_str()); for (int32_t flagIndex = 0; flagIndex < 32; flagIndex++) { if ((flagIndex % 8) != 0) { @@ -526,6 +630,25 @@ void DrawFlagArray(const std::string& name, uint32_t& flags) { ImGui::PopID(); } +void DrawFlagArray16(const std::string& name, uint16_t& flags) { + ImGui::PushID(name.c_str()); + for (int32_t flagIndex = 15; flagIndex >= 0; flagIndex--) { + ImGui::SameLine(); + ImGui::PushID(flagIndex); + uint32_t bitMask = 1 << flagIndex; + bool flag = (flags & bitMask) != 0; + if (ImGui::Checkbox("##check", &flag)) { + if (flag) { + flags |= bitMask; + } else { + flags &= ~bitMask; + } + } + ImGui::PopID(); + } + ImGui::PopID(); +} + void DrawFlagsTab() { if (ImGui::TreeNode("Current Scene")) { if (gGlobalCtx != nullptr) { @@ -534,7 +657,7 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Switch"); InsertHelpHoverText("Permanently-saved switch flags"); - DrawFlagArray("Switch", act->flags.swch); + DrawFlagArray32("Switch", act->flags.swch); }); ImGui::SameLine(); @@ -542,13 +665,13 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Temp Switch"); InsertHelpHoverText("Temporary switch flags. Unset on scene transitions"); - DrawFlagArray("Temp Switch", act->flags.tempSwch); + DrawFlagArray32("Temp Switch", act->flags.tempSwch); }); DrawGroupWithBorder([&]() { ImGui::Text("Clear"); InsertHelpHoverText("Permanently-saved room-clear flags"); - DrawFlagArray("Clear", act->flags.clear); + DrawFlagArray32("Clear", act->flags.clear); }); ImGui::SameLine(); @@ -556,13 +679,13 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Temp Clear"); InsertHelpHoverText("Temporary room-clear flags. Unset on scene transitions"); - DrawFlagArray("Temp Clear", act->flags.tempClear); + DrawFlagArray32("Temp Clear", act->flags.tempClear); }); DrawGroupWithBorder([&]() { ImGui::Text("Collect"); InsertHelpHoverText("Permanently-saved collect flags"); - DrawFlagArray("Collect", act->flags.collect); + DrawFlagArray32("Collect", act->flags.collect); }); ImGui::SameLine(); @@ -570,13 +693,13 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Temp Collect"); InsertHelpHoverText("Temporary collect flags. Unset on scene transitions"); - DrawFlagArray("Temp Collect", act->flags.tempCollect); + DrawFlagArray32("Temp Collect", act->flags.tempCollect); }); DrawGroupWithBorder([&]() { ImGui::Text("Chest"); InsertHelpHoverText("Permanently-saved chest flags"); - DrawFlagArray("Chest", act->flags.chest); + DrawFlagArray32("Chest", act->flags.chest); }); ImGui::SameLine(); @@ -633,7 +756,7 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Switch"); InsertHelpHoverText("Switch flags"); - DrawFlagArray("Switch", gSaveContext.sceneFlags[selectedSceneFlagMap].swch); + DrawFlagArray32("Switch", gSaveContext.sceneFlags[selectedSceneFlagMap].swch); }); ImGui::SameLine(); @@ -641,13 +764,13 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Clear"); InsertHelpHoverText("Room-clear flags"); - DrawFlagArray("Clear", gSaveContext.sceneFlags[selectedSceneFlagMap].clear); + DrawFlagArray32("Clear", gSaveContext.sceneFlags[selectedSceneFlagMap].clear); }); DrawGroupWithBorder([&]() { ImGui::Text("Collect"); InsertHelpHoverText("Collect flags"); - DrawFlagArray("Collect", gSaveContext.sceneFlags[selectedSceneFlagMap].collect); + DrawFlagArray32("Collect", gSaveContext.sceneFlags[selectedSceneFlagMap].collect); }); ImGui::SameLine(); @@ -655,13 +778,13 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Chest"); InsertHelpHoverText("Chest flags"); - DrawFlagArray("Chest", gSaveContext.sceneFlags[selectedSceneFlagMap].chest); + DrawFlagArray32("Chest", gSaveContext.sceneFlags[selectedSceneFlagMap].chest); }); DrawGroupWithBorder([&]() { ImGui::Text("Rooms"); InsertHelpHoverText("Flags for visted rooms"); - DrawFlagArray("Rooms", gSaveContext.sceneFlags[selectedSceneFlagMap].rooms); + DrawFlagArray32("Rooms", gSaveContext.sceneFlags[selectedSceneFlagMap].rooms); }); ImGui::SameLine(); @@ -669,7 +792,7 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Floors"); InsertHelpHoverText("Flags for visted floors"); - DrawFlagArray("Floors", gSaveContext.sceneFlags[selectedSceneFlagMap].floors); + DrawFlagArray32("Floors", gSaveContext.sceneFlags[selectedSceneFlagMap].floors); }); ImGui::TreePop(); @@ -730,6 +853,124 @@ void DrawFlagsTab() { gSaveContext.inventory.gsTokens = gsCount; } }); + + if (ImGui::TreeNode("Event Check Inf Flags")) { + DrawGroupWithBorder([&]() { + ImGui::Text("0"); + InsertHelpHoverText("Mostly Kokiri Forest related"); + DrawFlagArray16("eci0", gSaveContext.eventChkInf[0]); + }); + + DrawGroupWithBorder([&]() { + ImGui::Text("1"); + InsertHelpHoverText("Mostly Lon Lon Ranch related"); + DrawFlagArray16("eci1", gSaveContext.eventChkInf[1]); + }); + + DrawGroupWithBorder([&]() { + ImGui::Text("2"); + InsertHelpHoverText("Dodongo Related?"); + DrawFlagArray16("eci2", gSaveContext.eventChkInf[2]); + }); + + DrawGroupWithBorder([&]() { + ImGui::Text("3"); + InsertHelpHoverText("Mostly Zora related"); + DrawFlagArray16("eci3", gSaveContext.eventChkInf[3]); + }); + + DrawGroupWithBorder([&]() { + ImGui::Text("4"); + InsertHelpHoverText("Random"); + DrawFlagArray16("eci4", gSaveContext.eventChkInf[4]); + }); + + DrawGroupWithBorder([&]() { + ImGui::Text("5"); + InsertHelpHoverText("Mostly song learning related"); + DrawFlagArray16("eci5", gSaveContext.eventChkInf[5]); + }); + + DrawGroupWithBorder([&]() { + ImGui::Text("6"); + InsertHelpHoverText("Random"); + DrawFlagArray16("eci6", gSaveContext.eventChkInf[6]); + }); + + DrawGroupWithBorder([&]() { + ImGui::Text("7"); + InsertHelpHoverText("Boss Battle related"); + DrawFlagArray16("eci7", gSaveContext.eventChkInf[7]); + }); + + DrawGroupWithBorder([&]() { + ImGui::Text("8"); + InsertHelpHoverText("Mask related?"); + DrawFlagArray16("eci8", gSaveContext.eventChkInf[8]); + }); + + DrawGroupWithBorder([&]() { + ImGui::Text("9"); + InsertHelpHoverText("Mostly carpenter related"); + DrawFlagArray16("eci9", gSaveContext.eventChkInf[9]); + }); + + DrawGroupWithBorder([&]() { + ImGui::Text("A"); + InsertHelpHoverText("First-time overworld entrance cs related"); + DrawFlagArray16("eci1", gSaveContext.eventChkInf[10]); + }); + + DrawGroupWithBorder([&]() { + ImGui::Text("B"); + InsertHelpHoverText("First-time dungeon entrance cs/trial cs related"); + DrawFlagArray16("eci11", gSaveContext.eventChkInf[11]); + }); + + DrawGroupWithBorder([&]() { + ImGui::Text("C"); + InsertHelpHoverText("Random"); + DrawFlagArray16("eci12", gSaveContext.eventChkInf[12]); + }); + + DrawGroupWithBorder([&]() { + ImGui::Text("D"); + InsertHelpHoverText("Frog songs/GS rewards"); + DrawFlagArray16("eci13", gSaveContext.eventChkInf[13]); + }); + + ImGui::TreePop(); + } + if (ImGui::TreeNode("Inf Table Flags")) { + for (int i = 0; i < 30; i++) { + std::string it_id = "it" + std::to_string(i); + DrawGroupWithBorder([&]() { + ImGui::Text("%2d", i); + DrawFlagArray16(it_id, gSaveContext.infTable[i]); + }); + } + ImGui::TreePop(); + } + if (ImGui::TreeNode("Item Get Inf Flags")) { + for (int i = 0; i < 4; i++) { + std::string igi_id = "igi" + std::to_string(i); + DrawGroupWithBorder([&]() { + ImGui::Text("%d", i); + DrawFlagArray16(igi_id, gSaveContext.itemGetInf[i]); + }); + } + ImGui::TreePop(); + } + if (ImGui::TreeNode("Event Inf Flags")) { + for (int i = 0; i < 4; i++) { + std::string ei_id = "ei" + std::to_string(i); + DrawGroupWithBorder([&]() { + ImGui::Text("%d", i); + DrawFlagArray16(ei_id, gSaveContext.eventInf[i]); + }); + } + ImGui::TreePop(); + } } // Draws a combo that lets you choose and upgrade value from a drop-down of text values @@ -1057,6 +1298,242 @@ void DrawQuestStatusTab() { ImGui::PopItemWidth(); } +void DrawPlayerTab() { + if (gGlobalCtx != nullptr) { + Player* player = GET_PLAYER(gGlobalCtx); + const char* curSword; + const char* curShield; + const char* curTunic; + const char* curBoots; + + switch (player->currentSwordItem) { + case ITEM_SWORD_KOKIRI: + curSword = "Kokiri Sword"; + break; + case ITEM_SWORD_MASTER: + curSword = "Master Sword"; + break; + case ITEM_SWORD_BGS: + curSword = "Biggoron's Sword"; + break; + case ITEM_NONE: + curSword = "None"; + break; + default: + curSword = "None"; + break; + } + + switch (player->currentShield) { + case PLAYER_SHIELD_NONE: + curShield = "None"; + break; + case PLAYER_SHIELD_DEKU: + curShield = "Deku Shield"; + break; + case PLAYER_SHIELD_HYLIAN: + curShield = "Hylian Shield"; + break; + case PLAYER_SHIELD_MIRROR: + curShield = "Mirror Shield"; + break; + default: + break; + } + + switch (player->currentTunic) { + case PLAYER_TUNIC_KOKIRI: + curTunic = "Kokiri Tunic"; + break; + case PLAYER_TUNIC_GORON: + curTunic = "Goron Tunic"; + break; + case PLAYER_TUNIC_ZORA: + curTunic = "Zora Tunic"; + break; + default: + break; + } + + switch (player->currentBoots) { + case PLAYER_BOOTS_KOKIRI: + curBoots = "Kokiri Boots"; + break; + case PLAYER_BOOTS_IRON: + curBoots = "Iron Boots"; + break; + case PLAYER_BOOTS_HOVER: + curBoots = "Hover Boots"; + break; + default: + break; + } + + ImGui::PushItemWidth(ImGui::GetFontSize() * 6); + DrawGroupWithBorder([&]() { + ImGui::Text("Link's Position"); + ImGui::InputScalar("X Pos", ImGuiDataType_Float, &player->actor.world.pos.x); + ImGui::SameLine(); + ImGui::InputScalar("Y Pos", ImGuiDataType_Float, &player->actor.world.pos.y); + ImGui::SameLine(); + ImGui::InputScalar("Z Pos", ImGuiDataType_Float, &player->actor.world.pos.z); + }); + + DrawGroupWithBorder([&]() { + ImGui::Text("Link's Rotation"); + InsertHelpHoverText("For Link's rotation in relation to the world"); + ImGui::InputScalar("X Rot", ImGuiDataType_S16, &player->actor.world.rot.x); + ImGui::SameLine(); + ImGui::InputScalar("Y Rot", ImGuiDataType_S16, &player->actor.world.rot.y); + ImGui::SameLine(); + ImGui::InputScalar("Z Rot", ImGuiDataType_S16, &player->actor.world.rot.z); + }); + + DrawGroupWithBorder([&]() { + ImGui::Text("Link's Model Rotation"); + InsertHelpHoverText("For Link's actual model"); + ImGui::InputScalar("X ModRot", ImGuiDataType_S16, &player->actor.shape.rot.x); + ImGui::SameLine(); + ImGui::InputScalar("Y ModRot", ImGuiDataType_S16, &player->actor.shape.rot.y); + ImGui::SameLine(); + ImGui::InputScalar("Z ModRot", ImGuiDataType_S16, &player->actor.shape.rot.z); + }); + + ImGui::InputScalar("Linear Velocity", ImGuiDataType_Float, &player->linearVelocity); + InsertHelpHoverText("Link's speed along the XZ plane"); + + ImGui::InputScalar("Y Velocity", ImGuiDataType_Float, &player->actor.velocity.y); + InsertHelpHoverText("Link's speed along the Y plane. Caps at -20"); + + ImGui::InputScalar("Wall Height", ImGuiDataType_Float, &player->wallHeight); + InsertHelpHoverText("\"height used to determine whether link can climb or grab a ledge at the top\""); + + ImGui::InputScalar("Invincibility Timer", ImGuiDataType_S8, &player->invincibilityTimer); + InsertHelpHoverText("Can't take damage while this is nonzero"); + + ImGui::InputScalar("Gravity", ImGuiDataType_Float, &player->actor.gravity); + InsertHelpHoverText("Rate at which Link falls. Default -4.0f"); + + if (ImGui::BeginCombo("Link Age on Load", gGlobalCtx->linkAgeOnLoad == 0 ? "Adult" : "Child")) { + if (ImGui::Selectable("Adult")) { + gGlobalCtx->linkAgeOnLoad = 0; + } + if (ImGui::Selectable("Child")) { + gGlobalCtx->linkAgeOnLoad = 1; + } + ImGui::EndCombo(); + } + + InsertHelpHoverText("This will change Link's age when you load a map"); + + ImGui::Separator(); + + ImGui::Text("Link's Current Equipment"); + ImGui::PushItemWidth(ImGui::GetFontSize() * 15); + if (ImGui::BeginCombo("Sword", curSword)) { + if (ImGui::Selectable("None")) { + player->currentSwordItem = ITEM_NONE; + gSaveContext.equips.buttonItems[0] = ITEM_NONE; + Inventory_ChangeEquipment(EQUIP_SWORD, PLAYER_SWORD_NONE); + } + if (ImGui::Selectable("Kokiri Sword")) { + player->currentSwordItem = ITEM_SWORD_KOKIRI; + gSaveContext.equips.buttonItems[0] = ITEM_SWORD_KOKIRI; + Inventory_ChangeEquipment(EQUIP_SWORD, PLAYER_SWORD_KOKIRI); + } + if (ImGui::Selectable("Master Sword")) { + player->currentSwordItem = ITEM_SWORD_MASTER; + gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER; + Inventory_ChangeEquipment(EQUIP_SWORD, PLAYER_SWORD_MASTER); + } + if (ImGui::Selectable("Biggoron's Sword")) { + if (gSaveContext.bgsFlag) { + if (gSaveContext.swordHealth < 8) { + gSaveContext.swordHealth = 8; + } + player->currentSwordItem = ITEM_SWORD_BGS; + gSaveContext.equips.buttonItems[0] = ITEM_SWORD_BGS; + } else { + if (gSaveContext.swordHealth < 8) { + gSaveContext.swordHealth = 8; + } + player->currentSwordItem = ITEM_SWORD_BGS; + gSaveContext.equips.buttonItems[0] = ITEM_SWORD_KNIFE; + } + + Inventory_ChangeEquipment(EQUIP_SWORD, PLAYER_SWORD_BGS); + } + ImGui::EndCombo(); + + } + if (ImGui::BeginCombo("Shield", curShield)) { + if (ImGui::Selectable("None")) { + player->currentShield = PLAYER_SHIELD_NONE; + Inventory_ChangeEquipment(EQUIP_SHIELD, PLAYER_SHIELD_NONE); + } + if (ImGui::Selectable("Deku Shield")) { + player->currentShield = PLAYER_SHIELD_DEKU; + Inventory_ChangeEquipment(EQUIP_SHIELD, PLAYER_SHIELD_DEKU); + } + if (ImGui::Selectable("Hylian Shield")) { + player->currentShield = PLAYER_SHIELD_HYLIAN; + Inventory_ChangeEquipment(EQUIP_SHIELD, PLAYER_SHIELD_HYLIAN); + } + if (ImGui::Selectable("Mirror Shield")) { + player->currentShield = PLAYER_SHIELD_MIRROR; + Inventory_ChangeEquipment(EQUIP_SHIELD, PLAYER_SHIELD_MIRROR); + } + ImGui::EndCombo(); + } + + if (ImGui::BeginCombo("Tunic", curTunic)) { + if (ImGui::Selectable("Kokiri Tunic")) { + player->currentTunic = PLAYER_TUNIC_KOKIRI; + Inventory_ChangeEquipment(EQUIP_TUNIC, PLAYER_TUNIC_KOKIRI + 1); + } + if (ImGui::Selectable("Goron Tunic")) { + player->currentTunic = PLAYER_TUNIC_GORON; + Inventory_ChangeEquipment(EQUIP_TUNIC, PLAYER_TUNIC_GORON + 1); + } + if (ImGui::Selectable("Zora Tunic")) { + player->currentTunic = PLAYER_TUNIC_ZORA; + Inventory_ChangeEquipment(EQUIP_TUNIC, PLAYER_TUNIC_ZORA + 1); + } + ImGui::EndCombo(); + } + + if (ImGui::BeginCombo("Boots", curBoots)) { + if (ImGui::Selectable("Kokiri Boots")) { + player->currentBoots = PLAYER_BOOTS_KOKIRI; + Inventory_ChangeEquipment(EQUIP_BOOTS, PLAYER_BOOTS_KOKIRI + 1); + } + if (ImGui::Selectable("Iron Boots")) { + player->currentBoots = PLAYER_BOOTS_IRON; + Inventory_ChangeEquipment(EQUIP_BOOTS, PLAYER_BOOTS_IRON + 1); + } + if (ImGui::Selectable("Hover Boots")) { + player->currentBoots = PLAYER_BOOTS_HOVER; + Inventory_ChangeEquipment(EQUIP_BOOTS, PLAYER_BOOTS_HOVER + 1); + } + ImGui::EndCombo(); + } + + ImU16 one = 1; + ImGui::PushItemWidth(ImGui::GetFontSize() * 6); + DrawGroupWithBorder([&]() { + ImGui::Text("Current C Equips"); + ImGui::InputScalar("C Left", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[1], &one, NULL); + ImGui::SameLine(); + ImGui::InputScalar("C Down", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[2], &one, NULL); + ImGui::SameLine(); + ImGui::InputScalar("C Right", ImGuiDataType_U8, &gSaveContext.equips.buttonItems[3], &one, NULL); + }); + + } else { + ImGui::Text("Global Context needed for player info!"); + } +} + void DrawSaveEditor(bool& open) { if (!open) { return; @@ -1094,6 +1571,11 @@ void DrawSaveEditor(bool& open) { ImGui::EndTabItem(); } + if (ImGui::BeginTabItem("Player")) { + DrawPlayerTab(); + ImGui::EndTabItem(); + } + ImGui::EndTabBar(); } @@ -1101,7 +1583,7 @@ void DrawSaveEditor(bool& open) { } void InitSaveEditor() { - SohImGui::AddWindow("Debug", "Save Editor", DrawSaveEditor); + SohImGui::AddWindow("Developer Tools", "Save Editor", DrawSaveEditor); // Load item icons into ImGui for (const auto& entry : itemMapping) { diff --git a/soh/soh/Enhancements/gameconsole.h b/soh/soh/Enhancements/gameconsole.h index d7052fce3..33301afe6 100644 --- a/soh/soh/Enhancements/gameconsole.h +++ b/soh/soh/Enhancements/gameconsole.h @@ -3,7 +3,7 @@ #include #include -#include "cvar.h" +#include "Cvar.h" #define MAX_CVARS 2048 diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index aad82be29..f7ff39cdc 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -11,10 +11,14 @@ #include "Window.h" #include "z64animation.h" #include "z64bgcheck.h" -#include "../soh/enhancements/gameconsole.h" +#include "Enhancements/gameconsole.h" #include #include +#ifdef _WIN32 #include +#else +#include +#endif #include #include #include @@ -22,10 +26,11 @@ #include #include "Lib/stb/stb_image.h" #include "AudioPlayer.h" -#include "../soh/Enhancements/debugconsole.h" -#include "../soh/Enhancements/debugger/debugger.h" +#include "Enhancements/debugconsole.h" +#include "Enhancements/debugger/debugger.h" #include "Utils/BitConverter.h" #include "variables.h" +#include "macros.h" #include OTRGlobals* OTRGlobals::Instance; @@ -59,7 +64,7 @@ extern "C" void InitOTR() { OTRGlobals::Instance = new OTRGlobals(); auto t = OTRGlobals::Instance->context->GetResourceManager()->LoadFile("version"); - if (!t->bHasLoadError) + if (!t->bHasLoadError) { //uint32_t gameVersion = BitConverter::ToUInt32BE((uint8_t*)t->buffer.get(), 0); uint32_t gameVersion = *((uint32_t*)t->buffer.get()); @@ -72,6 +77,7 @@ extern "C" void InitOTR() { Debug_Init(); } +#ifdef _WIN32 extern "C" uint64_t GetFrequency() { LARGE_INTEGER nFreq; @@ -86,6 +92,21 @@ extern "C" uint64_t GetPerfCounter() { return ticks.QuadPart; } +#else +extern "C" uint64_t GetFrequency() { + return 1000; // sec -> ms +} + +extern "C" uint64_t GetPerfCounter() { + struct timespec monotime; + clock_gettime(CLOCK_MONOTONIC, &monotime); + + uint64_t remainingMs = (monotime.tv_nsec / 1000000); + + // in milliseconds + return monotime.tv_sec * 1000 + remainingMs; +} +#endif // C->C++ Bridge extern "C" void Graph_ProcessFrame(void (*run_one_game_iter)(void)) { @@ -185,7 +206,7 @@ extern "C" void OTRResetScancode() OTRGlobals::Instance->context->GetWindow()->lastScancode = -1; } -extern "C" uint32_t ResourceMgr_GetGameVersion() +extern "C" uint32_t ResourceMgr_GetGameVersion() { return OTRGlobals::Instance->context->GetResourceManager()->GetGameVersion(); } @@ -309,7 +330,7 @@ extern "C" char* ResourceMgr_LoadArrayByNameAsVec3s(const char* path) { if (res->cachedGameAsset != nullptr) return (char*)res->cachedGameAsset; - else + else { Vec3s* data = (Vec3s*)malloc(sizeof(Vec3s) * res->scalars.size()); @@ -429,7 +450,7 @@ extern "C" int ResourceMgr_OTRSigCheck(char* imgData) { uintptr_t i = (uintptr_t)(imgData); - if (i == 0xD9000000 || i == 0xE7000000 || (i & 0xF0000000) == 0xF0000000) + if (i == 0xD9000000 || i == 0xE7000000 || (i & 1) == 1) return 0; if ((i & 0xFF000000) != 0xAB000000 && (i & 0xFF000000) != 0xCD000000 && i != 0) { @@ -823,24 +844,24 @@ extern "C" int16_t OTRGetRectDimensionFromRightEdge(float v) { } extern "C" void bswapSoundFontSound(SoundFontSound* swappable) { - swappable->sample = (SoundFontSample*)_byteswap_ulong((u32)swappable->sample); - swappable->tuningAsU32 = _byteswap_ulong((u32)swappable->tuningAsU32); + swappable->sample = (SoundFontSample*)BOMSWAP32((u32)swappable->sample); + swappable->tuningAsU32 = BOMSWAP32((u32)swappable->tuningAsU32); } extern "C" void bswapDrum(Drum* swappable) { bswapSoundFontSound(&swappable->sound); - swappable->envelope = (AdsrEnvelope*)_byteswap_ulong((u32)swappable->envelope); + swappable->envelope = (AdsrEnvelope*)BOMSWAP32((u32)swappable->envelope); } extern "C" void bswapInstrument(Instrument* swappable) { - swappable->envelope = (AdsrEnvelope*)_byteswap_ulong((u32)swappable->envelope); + swappable->envelope = (AdsrEnvelope*)BOMSWAP32((u32)swappable->envelope); bswapSoundFontSound(&swappable->lowNotesSound); bswapSoundFontSound(&swappable->normalNotesSound); bswapSoundFontSound(&swappable->highNotesSound); } extern "C" void bswapSoundFontSample(SoundFontSample* swappable) { - u32 origBitfield = _byteswap_ulong(swappable->asU32); + u32 origBitfield = BOMSWAP32(swappable->asU32); swappable->codec = (origBitfield >> 28) & 0x0F; swappable->medium = (origBitfield >> 24) & 0x03; @@ -848,29 +869,29 @@ extern "C" void bswapSoundFontSample(SoundFontSample* swappable) { swappable->unk_bit25 = (origBitfield >> 21) & 0x01; swappable->size = (origBitfield) & 0x00FFFFFF; - swappable->sampleAddr = (u8*)_byteswap_ulong((u32)swappable->sampleAddr); - swappable->loop = (AdpcmLoop*)_byteswap_ulong((u32)swappable->loop); - swappable->book = (AdpcmBook*)_byteswap_ulong((u32)swappable->book); + swappable->sampleAddr = (u8*)BOMSWAP32((u32)swappable->sampleAddr); + swappable->loop = (AdpcmLoop*)BOMSWAP32((u32)swappable->loop); + swappable->book = (AdpcmBook*)BOMSWAP32((u32)swappable->book); } extern "C" void bswapAdpcmLoop(AdpcmLoop* swappable) { - swappable->start = (u32)_byteswap_ulong((u32)swappable->start); - swappable->end = (u32)_byteswap_ulong((u32)swappable->end); - swappable->count = (u32)_byteswap_ulong((u32)swappable->count); + swappable->start = (u32)BOMSWAP32((u32)swappable->start); + swappable->end = (u32)BOMSWAP32((u32)swappable->end); + swappable->count = (u32)BOMSWAP32((u32)swappable->count); if (swappable->count != 0) { for (int i = 0; i < 16; i++) { - swappable->state[i] = (s16)_byteswap_ushort(swappable->state[i]); + swappable->state[i] = (s16)BOMSWAP16(swappable->state[i]); } } } extern "C" void bswapAdpcmBook(AdpcmBook* swappable) { - swappable->order = (u32)_byteswap_ulong((u32)swappable->order); - swappable->npredictors = (u32)_byteswap_ulong((u32)swappable->npredictors); + swappable->order = (u32)BOMSWAP32((u32)swappable->order); + swappable->npredictors = (u32)BOMSWAP32((u32)swappable->npredictors); for (int i = 0; i < swappable->npredictors * swappable->order * sizeof(s16) * 4; i++) - swappable->book[i] = (s16)_byteswap_ushort(swappable->book[i]); + swappable->book[i] = (s16)BOMSWAP16(swappable->book[i]); } extern "C" bool AudioPlayer_Init(void) { @@ -900,7 +921,7 @@ extern "C" void AudioPlayer_Play(const uint8_t* buf, uint32_t len) { } extern "C" int Controller_ShouldRumble(size_t i) { - for (const auto& controller : Ship::Window::Controllers.at(i)) + for (const auto& controller : Ship::Window::Controllers.at(i)) { float rumble_strength = CVar_GetFloat(StringHelper::Sprintf("gCont%i_RumbleStrength", i).c_str(), 1.0f); diff --git a/soh/soh/stubs.c b/soh/soh/stubs.c index c47c1fa5d..98f3b4823 100644 --- a/soh/soh/stubs.c +++ b/soh/soh/stubs.c @@ -12,12 +12,12 @@ OSViMode osViModeNtscLan1; OSViMode osViModeMpalLan1; OSViMode osViModeFpalLan1; OSViMode osViModePalLan1; -AudioContext gAudioContext; -unk_D_8016E750 D_8016E750[4]; +// AudioContext gAudioContext; +// unk_D_8016E750 D_8016E750[4]; u8 gLetterTLUT[4][32]; u8 gFontFF[999]; DmaEntry gDmaDataTable[0x60C]; -u8 D_80133418; +// u8 D_80133418; u16 gAudioSEFlagSwapSource[64]; u16 gAudioSEFlagSwapTarget[64]; u8 gAudioSEFlagSwapMode[64]; diff --git a/soh/soh/z_play_otr.cpp b/soh/soh/z_play_otr.cpp index c84e37482..3e2a990d7 100644 --- a/soh/soh/z_play_otr.cpp +++ b/soh/soh/z_play_otr.cpp @@ -12,7 +12,7 @@ void OTRGameplay_InitScene(GlobalContext* globalCtx, s32 spawn); s32 OTRScene_ExecuteCommands(GlobalContext* globalCtx, Ship::Scene* sceneCmd); //Ship::OTRResource* OTRGameplay_LoadFile(GlobalContext* globalCtx, RomFile* file) { -Ship::Resource* OTRGameplay_LoadFile(GlobalContext* globalCtx, const char* fileName) +Ship::Resource* OTRGameplay_LoadFile(GlobalContext* globalCtx, const char* fileName) { auto res = OTRGlobals::Instance->context->GetResourceManager()->LoadResource(fileName); return res.get(); @@ -28,7 +28,7 @@ extern "C" void OTRGameplay_SpawnScene(GlobalContext* globalCtx, s32 sceneNum, s //osSyncPrintf("\nSCENE SIZE %fK\n", (scene->sceneFile.vromEnd - scene->sceneFile.vromStart) / 1024.0f); - std::string scenePath = StringHelper::Sprintf("scenes\\%s\\%s", scene->sceneFile.fileName, scene->sceneFile.fileName); + std::string scenePath = StringHelper::Sprintf("scenes/%s/%s", scene->sceneFile.fileName, scene->sceneFile.fileName); globalCtx->sceneSegment = (Ship::Scene*)OTRGameplay_LoadFile(globalCtx, scenePath.c_str()); @@ -47,7 +47,7 @@ extern "C" void OTRGameplay_SpawnScene(GlobalContext* globalCtx, s32 sceneNum, s //gSegments[2] = VIRTUAL_TO_PHYSICAL(globalCtx->sceneSegment); OTRGameplay_InitScene(globalCtx, spawn); - + osSyncPrintf("ROOM SIZE=%fK\n", func_80096FE8(globalCtx, &globalCtx->roomCtx) / 1024.0f); } @@ -72,7 +72,7 @@ void OTRGameplay_InitScene(GlobalContext* globalCtx, s32 spawn) { ->GetResourceManager() ->LoadResource("object_link_child\\object_link_childVtx_01FE08") .get()); - + auto data2 = ResourceMgr_LoadVtxByCRC(0x68d4ea06044e228f);*/ volatile int a = 0; diff --git a/soh/soh/z_scene_otr.cpp b/soh/soh/z_scene_otr.cpp index f63df81e4..123f9c636 100644 --- a/soh/soh/z_scene_otr.cpp +++ b/soh/soh/z_scene_otr.cpp @@ -72,7 +72,7 @@ bool func_800985DC(GlobalContext* globalCtx, Ship::SceneCommand* cmd) { else { ActorEntry* entries = (ActorEntry*)malloc(cmdActor->entries.size() * sizeof(ActorEntry)); - + for (int i = 0; i < cmdActor->entries.size(); i++) { entries[i].id = cmdActor->entries[i].actorNum; @@ -241,7 +241,7 @@ bool func_800987F8(GlobalContext* globalCtx, Ship::SceneCommand* cmd) globalCtx->setupEntranceList[i].room = otrEntrance->entrances[i].roomToLoad; globalCtx->setupEntranceList[i].spawn = otrEntrance->entrances[i].startPositionIndex; } - + otrEntrance->cachedGameData = globalCtx->setupEntranceList; } @@ -252,11 +252,11 @@ bool func_800987F8(GlobalContext* globalCtx, Ship::SceneCommand* cmd) bool func_8009883C(GlobalContext* globalCtx, Ship::SceneCommand* cmd) { Ship::SetSpecialObjects* otrSpecial = (Ship::SetSpecialObjects*)cmd; - + if (otrSpecial->globalObject != 0) globalCtx->objectCtx.subKeepIndex = Object_Spawn(&globalCtx->objectCtx, otrSpecial->globalObject); - if (otrSpecial->elfMessage != 0) + if (otrSpecial->elfMessage != 0) { auto res = (Ship::Blob*)OTRGameplay_LoadFile(globalCtx, sNaviMsgFiles[otrSpecial->elfMessage - 1].fileName); globalCtx->cUpElfMsgs = (ElfMessage*)res->data.data(); @@ -436,7 +436,7 @@ extern "C" void* func_800982FC(ObjectContext * objectCtx, s32 bankIndex, s16 obj bool func_8009899C(GlobalContext* globalCtx, Ship::SceneCommand* cmd) { Ship::SetObjectList* cmdObj = (Ship::SetObjectList*)cmd; - + s32 i; s32 j; s32 k; @@ -743,7 +743,7 @@ bool func_8009918C(GlobalContext* globalCtx, Ship::SceneCommand* cmd) } // Scene Command 0x18: Alternate Headers -bool func_800991A0(GlobalContext* globalCtx, Ship::SceneCommand* cmd) +bool func_800991A0(GlobalContext* globalCtx, Ship::SceneCommand* cmd) { Ship::SetAlternateHeaders* cmdHeaders = (Ship::SetAlternateHeaders*)cmd; @@ -754,7 +754,7 @@ bool func_800991A0(GlobalContext* globalCtx, Ship::SceneCommand* cmd) //osSyncPrintf("\n[ZU]sceneset time =[%X]", ((void)0, gSaveContext.cutsceneIndex)); //osSyncPrintf("\n[ZU]sceneset counter=[%X]", ((void)0, gSaveContext.sceneSetupIndex)); - if (gSaveContext.sceneSetupIndex != 0) + if (gSaveContext.sceneSetupIndex != 0) { std::string desiredHeader = cmdHeaders->headers[gSaveContext.sceneSetupIndex - 1]; Ship::Scene* headerData = nullptr; @@ -798,7 +798,7 @@ bool func_800991A0(GlobalContext* globalCtx, Ship::SceneCommand* cmd) } // Scene Command 0x17: Cutscene Data -bool func_8009934C(GlobalContext* globalCtx, Ship::SceneCommand* cmd) +bool func_8009934C(GlobalContext* globalCtx, Ship::SceneCommand* cmd) { Ship::SetCutscenes* cmdCS = (Ship::SetCutscenes*)cmd; @@ -810,7 +810,7 @@ bool func_8009934C(GlobalContext* globalCtx, Ship::SceneCommand* cmd) } // Scene Command 0x19: Misc. Settings (Camera & World Map Area) -bool func_800993C0(GlobalContext* globalCtx, Ship::SceneCommand* cmd) +bool func_800993C0(GlobalContext* globalCtx, Ship::SceneCommand* cmd) { Ship::SetCameraSettings* cmdCam = (Ship::SetCameraSettings*)cmd; diff --git a/soh/src/code/audio_effects.c b/soh/src/code/audio_effects.c index 4813d1c63..d5aa3644f 100644 --- a/soh/src/code/audio_effects.c +++ b/soh/src/code/audio_effects.c @@ -246,7 +246,7 @@ f32 Audio_AdsrUpdate(AdsrState* adsr) { retry: case ADSR_STATE_LOOP: - adsr->delay = (s16)_byteswap_ushort(adsr->envelope[adsr->envIndex].delay); + adsr->delay = (s16)BOMSWAP16(adsr->envelope[adsr->envIndex].delay); switch (adsr->delay) { case ADSR_DISABLE: adsr->action.s.state = ADSR_STATE_DISABLED; @@ -255,7 +255,7 @@ f32 Audio_AdsrUpdate(AdsrState* adsr) { adsr->action.s.state = ADSR_STATE_HANG; break; case ADSR_GOTO: - adsr->envIndex = (s16)_byteswap_ushort(adsr->envelope[adsr->envIndex].arg); + adsr->envIndex = (s16)BOMSWAP16(adsr->envelope[adsr->envIndex].arg); goto retry; case ADSR_RESTART: adsr->action.s.state = ADSR_STATE_INITIAL; @@ -266,7 +266,7 @@ f32 Audio_AdsrUpdate(AdsrState* adsr) { if (adsr->delay == 0) { adsr->delay = 1; } - adsr->target = (s16)_byteswap_ushort(adsr->envelope[adsr->envIndex].arg) / 32767.0f; + adsr->target = (s16)BOMSWAP16(adsr->envelope[adsr->envIndex].arg) / 32767.0f; adsr->target = adsr->target * adsr->target; adsr->velocity = (adsr->target - adsr->current) / adsr->delay; adsr->action.s.state = ADSR_STATE_FADE; diff --git a/soh/src/code/audio_load.c b/soh/src/code/audio_load.c index ec8b7be86..7af9037a6 100644 --- a/soh/src/code/audio_load.c +++ b/soh/src/code/audio_load.c @@ -1058,7 +1058,7 @@ void AudioLoad_InitSwapFontSampleHeaders(SoundFontSample* sample, uintptr_t romA size_t maxSoundFontSize = 0x3AA0; // soundFont 0 is the largest size at 0x3AA0 AdpcmLoop* loop; AdpcmBook* book; - + if (((uintptr_t)sample->loop > maxSoundFontSize) || ((uintptr_t)sample->book > maxSoundFontSize) ) { bswapSoundFontSample(sample); @@ -1093,7 +1093,7 @@ void AudioLoad_InitSwapFont(void) { SoundFontSound* sfxList; SoundFontSound* sfx; Instrument** instList; - Instrument* inst; + Instrument* inst; // Only up to (numFonts - 1) as final font has garbage data to prevent corruption and is never used for (fontId = 0; fontId < (numFonts - 1); fontId++) { @@ -1110,12 +1110,12 @@ void AudioLoad_InitSwapFont(void) { numInstruments = font->numInstruments; // drums - ptrs[0] = (void*)_byteswap_ulong((uintptr_t)ptrs[0]); + ptrs[0] = (void*)BOMSWAP32((uintptr_t)ptrs[0]); if ((ptrs[0] != NULL) && (numDrums != 0)) { drumList = (Drum**)BASE_ROM_OFFSET(ptrs[0]); for (i = 0; i < numDrums; i++) { - drumList[i] = (Drum*)_byteswap_ulong((uintptr_t)drumList[i]); + drumList[i] = (Drum*)BOMSWAP32((uintptr_t)drumList[i]); if (drumList[i] != NULL) { drum = (Drum*)BASE_ROM_OFFSET(drumList[i]); @@ -1128,7 +1128,7 @@ void AudioLoad_InitSwapFont(void) { } // sfxs - ptrs[1] = (void*)_byteswap_ulong((u32)ptrs[1]); + ptrs[1] = (void*)BOMSWAP32((u32)ptrs[1]); if ((ptrs[1] != NULL) && (numSfxs != 0)) { sfxList = (SoundFontSound*)BASE_ROM_OFFSET(ptrs[1]); @@ -1151,7 +1151,7 @@ void AudioLoad_InitSwapFont(void) { instList = (Instrument**)(&ptrs[2]); for (i = 0; i < numInstruments; i++) { - instList[i] = (Instrument*)_byteswap_ulong((uintptr_t)instList[i]); + instList[i] = (Instrument*)BOMSWAP32((uintptr_t)instList[i]); if (instList[i] != NULL) { inst = BASE_ROM_OFFSET(instList[i]); @@ -1159,15 +1159,15 @@ void AudioLoad_InitSwapFont(void) { if (inst->normalRangeLo != 0) { sample = (SoundFontSample*)BASE_ROM_OFFSET(inst->lowNotesSound.sample); - AudioLoad_InitSwapFontSampleHeaders(sample, romAddr); + AudioLoad_InitSwapFontSampleHeaders(sample, romAddr); } sample = (SoundFontSample*)BASE_ROM_OFFSET(inst->normalNotesSound.sample); - AudioLoad_InitSwapFontSampleHeaders(sample, romAddr); - + AudioLoad_InitSwapFontSampleHeaders(sample, romAddr); + if (inst->normalRangeHi != 0x7F) { sample = (SoundFontSample*)BASE_ROM_OFFSET(inst->highNotesSound.sample); - AudioLoad_InitSwapFontSampleHeaders(sample, romAddr); + AudioLoad_InitSwapFontSampleHeaders(sample, romAddr); } } } diff --git a/soh/src/code/audio_seqplayer.c b/soh/src/code/audio_seqplayer.c index 03e8842e3..3dd7b811e 100644 --- a/soh/src/code/audio_seqplayer.c +++ b/soh/src/code/audio_seqplayer.c @@ -1323,14 +1323,14 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) { case 0xB2: offset = (u16)parameters[0]; // OTRTODO: Byteswap added for quick audio - channel->unk_22 = _byteswap_ushort(*(u16*)(seqPlayer->seqData + (uintptr_t)(offset + scriptState->value * 2))); + channel->unk_22 = BOMSWAP16(*(u16*)(seqPlayer->seqData + (uintptr_t)(offset + scriptState->value * 2))); break; case 0xB4: channel->dynTable = (void*)&seqPlayer->seqData[channel->unk_22]; break; case 0xB5: // OTRTODO: Byteswap added for quick audio - channel->unk_22 = _byteswap_ushort(((u16*)(channel->dynTable))[scriptState->value]); + channel->unk_22 = BOMSWAP16(((u16*)(channel->dynTable))[scriptState->value]); break; case 0xB6: scriptState->value = (*channel->dynTable)[0][scriptState->value]; diff --git a/soh/src/code/audio_synthesis.c b/soh/src/code/audio_synthesis.c index e71c6b441..037bd2ec3 100644 --- a/soh/src/code/audio_synthesis.c +++ b/soh/src/code/audio_synthesis.c @@ -1162,7 +1162,7 @@ Acmd* AudioSynth_LoadWaveSamples(Acmd* cmd, NoteSubEu* noteSubEu, NoteSynthesisS if (temp_v0 < nSamplesToLoad) { repeats = ((nSamplesToLoad - temp_v0 + 0x3F) / 0x40); if (repeats != 0) { - aDuplicate(cmd++, repeats, DMEM_UNCOMPRESSED_NOTE, DMEM_UNCOMPRESSED_NOTE + 0x80, 0x80); + aDuplicate(cmd++, repeats, DMEM_UNCOMPRESSED_NOTE, DMEM_UNCOMPRESSED_NOTE + 0x80); } } synthState->samplePosInt = samplePosInt; @@ -1225,6 +1225,6 @@ Acmd* AudioSynth_NoteApplyHeadsetPanEffects(Acmd* cmd, NoteSubEu* noteSubEu, Not aSaveBuffer(cmd++, DMEM_NOTE_PAN_TEMP + bufLen, &synthState->synthesisBuffers->panResampleState[0x8], ALIGN16(panShift)); } - aAddMixer(cmd++, ALIGN64(bufLen), DMEM_NOTE_PAN_TEMP, dest, 0x7FFF); + aAddMixer(cmd++, ALIGN64(bufLen), DMEM_NOTE_PAN_TEMP, dest); return cmd; } diff --git a/soh/src/code/padmgr.c b/soh/src/code/padmgr.c index 08c89869f..b467f5ee6 100644 --- a/soh/src/code/padmgr.c +++ b/soh/src/code/padmgr.c @@ -3,7 +3,9 @@ //#include +#ifdef _MSC_VER extern void* __cdecl memset(_Out_writes_bytes_all_(_Size) void* _Dst, _In_ int _Val, _In_ size_t _Size); +#endif s32 D_8012D280 = 1; diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index 9a56000ec..a9f50f687 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -7,13 +7,13 @@ #include "objects/gameplay_dangeon_keep/gameplay_dangeon_keep.h" #include "objects/object_bdoor/object_bdoor.h" -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__GNUC__) #include #include #include #endif -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__GNUC__) #include "textures/place_title_cards/g_pn_49.h" #include "textures/place_title_cards/g_pn_01.h" #include "textures/place_title_cards/g_pn_02.h" @@ -765,7 +765,7 @@ void TitleCard_InitBossName(GlobalContext* globalCtx, TitleCardContext* titleCtx titleCtx->texture = texture; titleCtx->isBossCard = true; - titleCtx->hasTranslation = hasTranslation; + titleCtx->hasTranslation = hasTranslation; titleCtx->x = x; titleCtx->y = y; titleCtx->width = width; @@ -774,7 +774,7 @@ void TitleCard_InitBossName(GlobalContext* globalCtx, TitleCardContext* titleCtx titleCtx->delayTimer = 0; } -void TitleCard_InitPlaceName(GlobalContext* globalCtx, TitleCardContext* titleCtx, char* texture, s32 x, s32 y, +void TitleCard_InitPlaceName(GlobalContext* globalCtx, TitleCardContext* titleCtx, void* texture, s32 x, s32 y, s32 width, s32 height, s32 delay) { SceneTableEntry* loadedScene = globalCtx->loadedScene; @@ -4272,8 +4272,6 @@ s32 func_80035124(Actor* actor, GlobalContext* globalCtx) { return ret; } -#include "z_cheap_proc.c" - u8 func_800353E8(GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); diff --git a/soh/src/code/z_bgcheck.c b/soh/src/code/z_bgcheck.c index 9ce139eed..811b0bea1 100644 --- a/soh/src/code/z_bgcheck.c +++ b/soh/src/code/z_bgcheck.c @@ -4031,7 +4031,7 @@ s32 func_80041E4C(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId) { /** * unused */ -u32 func_80041E80(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId) { +s32 func_80041E80(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId) { return SurfaceType_GetData(colCtx, poly, bgId, 0) >> 26 & 0xF; } diff --git a/soh/src/code/z_camera.c b/soh/src/code/z_camera.c index 7302f9b21..94faf8124 100644 --- a/soh/src/code/z_camera.c +++ b/soh/src/code/z_camera.c @@ -26,7 +26,7 @@ s32 Camera_CheckWater(Camera* camera); #define FLG_ADJSLOPE (1 << 0) #define FLG_OFFGROUND (1 << 7) -#include "z_camera_data.c" +#include "z_camera_data.inc" /*===============================================================*/ diff --git a/soh/src/code/z_camera_data.c b/soh/src/code/z_camera_data.inc similarity index 100% rename from soh/src/code/z_camera_data.c rename to soh/src/code/z_camera_data.inc diff --git a/soh/src/code/z_demo.c b/soh/src/code/z_demo.c index d0145fb43..f6bb7d572 100644 --- a/soh/src/code/z_demo.c +++ b/soh/src/code/z_demo.c @@ -2105,7 +2105,7 @@ void Cutscene_HandleConditionalTriggers(GlobalContext* globalCtx) { } void Cutscene_SetSegment(GlobalContext* globalCtx, void* segment) { - if (SEGMENT_NUMBER(segment) != 0) + if (SEGMENT_NUMBER(segment) != 0) { globalCtx->csCtx.segment = SEGMENTED_TO_VIRTUAL(segment); } else { diff --git a/soh/src/code/z_fbdemo_circle.c b/soh/src/code/z_fbdemo_circle.c index a6a46a0e4..5c8f688fa 100644 --- a/soh/src/code/z_fbdemo_circle.c +++ b/soh/src/code/z_fbdemo_circle.c @@ -19,9 +19,9 @@ Gfx __sCircleDList[] = { G_AC_NONE | G_ZS_PIXEL | G_RM_XLU_SURF | G_RM_XLU_SURF2), // 4 gsDPSetCombineMode(G_CC_BLENDPEDECALA, G_CC_BLENDPEDECALA), // 5 gsSPTexture(0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON), // 6 - gsDPLoadTextureBlock(0xF8000000, G_IM_FMT_I, G_IM_SIZ_8b, 16, 64, 0, G_TX_NOMIRROR | G_TX_WRAP, // 7 + gsDPLoadTextureBlock(SEG_ADDR(8, 0), G_IM_FMT_I, G_IM_SIZ_8b, 16, 64, 0, G_TX_NOMIRROR | G_TX_WRAP, // 7 G_TX_NOMIRROR | G_TX_CLAMP, 4, 6, G_TX_NOLOD, G_TX_NOLOD), - gsSPDisplayList(0xF9000000), // 8 + gsSPDisplayList(SEG_ADDR(9, 0)), // 8 gsSPVertex(sCircleWipeVtx, 32, 0), // 9 gsSP2Triangles(0, 1, 2, 0, 1, 3, 4, 0), // 10 gsSP2Triangles(3, 5, 6, 0, 5, 7, 8, 0), // 11 diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c index 7f3507abd..355d323e0 100644 --- a/soh/src/code/z_player_lib.c +++ b/soh/src/code/z_player_lib.c @@ -654,7 +654,7 @@ u8 sEyeMouthIndexes[][2] = { * from adult Link's object are used here. */ -#if defined(MODDING) || (_MSC_VER) +#if defined(MODDING) || defined(_MSC_VER) || defined(__GNUC__) //TODO: Formatting void* sEyeTextures[2][8] = { { gLinkAdultEyesOpenTex, gLinkAdultEyesHalfTex, gLinkAdultEyesClosedfTex, gLinkAdultEyesRollLeftTex, @@ -670,7 +670,7 @@ void* sEyeTextures[] = { }; #endif -#if defined(modding) || defined(_MSC_VER) +#if defined(MODDING) || defined(_MSC_VER) || defined(__GNUC__) void* sMouthTextures[2][4] = { { gLinkAdultMouth1Tex, @@ -726,7 +726,7 @@ void func_8008F470(GlobalContext* globalCtx, void** skeleton, Vec3s* jointTable, if (eyeIndex > 7) eyeIndex = 7; -#if defined(MODDING) || (_MSC_VER) +#if defined(MODDING) || defined(_MSC_VER) || defined(__GNUC__) gSPSegment(POLY_OPA_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(sEyeTextures[gSaveContext.linkAge][eyeIndex])); #else gSPSegment(POLY_OPA_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(sEyeTextures[eyeIndex])); @@ -738,31 +738,29 @@ void func_8008F470(GlobalContext* globalCtx, void** skeleton, Vec3s* jointTable, if (mouthIndex > 3) mouthIndex = 3; -#if defined(MODDING) || (_MSC_VER) +#if defined(MODDING) || defined(_MSC_VER) || defined(__GNUC__) gSPSegment(POLY_OPA_DISP++, 0x09, SEGMENTED_TO_VIRTUAL(sMouthTextures[gSaveContext.linkAge][mouthIndex])); #else gSPSegment(POLY_OPA_DISP++, 0x09, SEGMENTED_TO_VIRTUAL(sMouthTextures[eyeIndex])); #endif + Color_RGB8 sTemp; + color = &sTemp; if (tunic == PLAYER_TUNIC_KOKIRI) { - Color_RGB8 sTemp = { CVar_GetS32("gTunic_Kokiri_Red", sTunicColors[PLAYER_TUNIC_KOKIRI].r), - CVar_GetS32("gTunic_Kokiri_Green", sTunicColors[PLAYER_TUNIC_KOKIRI].g), - CVar_GetS32("gTunic_Kokiri_Blue", sTunicColors[PLAYER_TUNIC_KOKIRI].b) }; - color = &sTemp; + color->r = CVar_GetS32("gTunic_Kokiri_Red", sTunicColors[PLAYER_TUNIC_KOKIRI].r); + color->g = CVar_GetS32("gTunic_Kokiri_Green", sTunicColors[PLAYER_TUNIC_KOKIRI].g); + color->b = CVar_GetS32("gTunic_Kokiri_Blue", sTunicColors[PLAYER_TUNIC_KOKIRI].b); } else if (tunic == PLAYER_TUNIC_GORON) { - Color_RGB8 sTemp = { CVar_GetS32("gTunic_Goron_Red", sTunicColors[PLAYER_TUNIC_GORON].r), - CVar_GetS32("gTunic_Goron_Green", sTunicColors[PLAYER_TUNIC_GORON].g), - CVar_GetS32("gTunic_Goron_Blue", sTunicColors[PLAYER_TUNIC_GORON].b) }; - color = &sTemp; + color->r = CVar_GetS32("gTunic_Goron_Red", sTunicColors[PLAYER_TUNIC_GORON].r); + color->g = CVar_GetS32("gTunic_Goron_Green", sTunicColors[PLAYER_TUNIC_GORON].g); + color->b = CVar_GetS32("gTunic_Goron_Blue", sTunicColors[PLAYER_TUNIC_GORON].b); } else if (tunic == PLAYER_TUNIC_ZORA) { - Color_RGB8 sTemp = { CVar_GetS32("gTunic_Zora_Red", sTunicColors[PLAYER_TUNIC_ZORA].r), - CVar_GetS32("gTunic_Zora_Green", sTunicColors[PLAYER_TUNIC_ZORA].g), - CVar_GetS32("gTunic_Zora_Blue", sTunicColors[PLAYER_TUNIC_ZORA].b) }; - color = &sTemp; + color->r = CVar_GetS32("gTunic_Zora_Red", sTunicColors[PLAYER_TUNIC_ZORA].r); + color->g = CVar_GetS32("gTunic_Zora_Green", sTunicColors[PLAYER_TUNIC_ZORA].g); + color->b = CVar_GetS32("gTunic_Zora_Blue", sTunicColors[PLAYER_TUNIC_ZORA].b); } else { - Color_RGB8 sTemp = { CVar_GetS32("gTunic_Kokiri_Red", sTunicColors[PLAYER_TUNIC_KOKIRI].r), - CVar_GetS32("gTunic_Kokiri_Green", sTunicColors[PLAYER_TUNIC_KOKIRI].g), - CVar_GetS32("gTunic_Kokiri_Blue", sTunicColors[PLAYER_TUNIC_KOKIRI].b) }; - color = &sTemp; + color->r = CVar_GetS32("gTunic_Kokiri_Red", sTunicColors[PLAYER_TUNIC_KOKIRI].r); + color->g = CVar_GetS32("gTunic_Kokiri_Green", sTunicColors[PLAYER_TUNIC_KOKIRI].g); + color->b = CVar_GetS32("gTunic_Kokiri_Blue", sTunicColors[PLAYER_TUNIC_KOKIRI].b); } gDPSetEnvColor(POLY_OPA_DISP++, color->r, color->g, color->b, 0); diff --git a/soh/src/code/z_skelanime.c b/soh/src/code/z_skelanime.c index 2c03390e9..6dbfac7ef 100644 --- a/soh/src/code/z_skelanime.c +++ b/soh/src/code/z_skelanime.c @@ -863,7 +863,7 @@ void AnimationContext_SetLoadFrame(GlobalContext* globalCtx, LinkAnimationHeader char animPath[2048]; - sprintf(animPath, "misc\\link_animetion\\gPlayerAnimData_%06X", (((uintptr_t)linkAnimHeader->segment - 0x07000000))); + sprintf(animPath, "misc/link_animetion/gPlayerAnimData_%06X", (((uintptr_t)linkAnimHeader->segment - 0x07000000))); //printf("Streaming %s, seg = %08X\n", animPath, linkAnimHeader->segment); @@ -877,7 +877,7 @@ void AnimationContext_SetLoadFrame(GlobalContext* globalCtx, LinkAnimationHeader { ramPtr[i] = i * 7; }*/ - + //DmaMgr_SendRequest2(&entry->data.load.req, ram, //LINK_ANIMATION_OFFSET(linkAnimHeader->segment, ((sizeof(Vec3s) * limbCount + 2) * frame)), diff --git a/soh/src/code/z_vismono.c b/soh/src/code/z_vismono.c index 82acc9a17..2af876ad6 100644 --- a/soh/src/code/z_vismono.c +++ b/soh/src/code/z_vismono.c @@ -42,7 +42,7 @@ Gfx* VisMono_DrawTexture(VisMono* this, Gfx* gfx) s32 y; s32 height = 3; //u16* tex = D_0F000000; - u16* tex = 0xFF000000; + u16* tex = SEG_ADDR(0xF, 0); gDPPipeSync(gfx++); gDPSetOtherMode(gfx++, diff --git a/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c b/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c index 94ea16422..227e0d6f0 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c +++ b/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c @@ -210,7 +210,7 @@ static Vec3f sAudioVec = { 0.0f, 0.0f, 50.0f }; // OTRTODO: This code appears to cause the game to gradually crash... // Might be an OoB write. For now it's disabled. -void BossGanondrof_ClearPixels8x8(s16* texture, u8* mask, s16 index) +void BossGanondrof_ClearPixels8x8(s16* texture, u8* mask, s16 index) { //texture = ResourceMgr_LoadTexByName(texture); if (mask[index]) { @@ -248,18 +248,18 @@ void BossGanondrof_ClearPixels32x16(s16* texture, u8* mask, s16 index) { } } -void BossGanondrof_ClearPixels16x32(s16* texture, u8* mask, s16 index) { +void BossGanondrof_ClearPixels16x32(s16* texture, u8* mask, s16 index) { //texture = ResourceMgr_LoadTexByName(texture); if (mask[index]) { s16 i = ((index & 0xF) * 2) + ((index & 0xF0) * 2); - + ResourceMgr_WriteTexS16ByName(texture, i + 1, 0); ResourceMgr_WriteTexS16ByName(texture, i, 0); //texture[i + 1] = 0; //texture[i] = 0; } - + } void BossGanondrof_ClearPixels(u8* mask, s16 index) { diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c index dc48b277d..570eedd1f 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c +++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c @@ -1505,9 +1505,9 @@ void FileChoose_LoadGame(GameState* thisx) { (gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KNIFE)) { gSaveContext.equips.buttonItems[0] = ITEM_NONE; - swordEquipMask = _byteswap_ushort(gEquipMasks[EQUIP_SWORD]) & gSaveContext.equips.equipment; + swordEquipMask = BOMSWAP16(gEquipMasks[EQUIP_SWORD]) & gSaveContext.equips.equipment; gSaveContext.equips.equipment &= gEquipNegMasks[EQUIP_SWORD]; - gSaveContext.inventory.equipment ^= (gBitFlags[swordEquipMask - 1] << _byteswap_ushort(gEquipShifts[EQUIP_SWORD])); + gSaveContext.inventory.equipment ^= (gBitFlags[swordEquipMask - 1] << BOMSWAP16(gEquipShifts[EQUIP_SWORD])); } } } diff --git a/soh/src/overlays/gamestates/ovl_select/z_select.c b/soh/src/overlays/gamestates/ovl_select/z_select.c index 98aaa4a63..c4a467d63 100644 --- a/soh/src/overlays/gamestates/ovl_select/z_select.c +++ b/soh/src/overlays/gamestates/ovl_select/z_select.c @@ -624,10 +624,10 @@ void Select_Init(GameState* thisx) { this->pageDownIndex = dREG(82); } R_UPDATE_RATE = 1; - #ifndef _MSC_VER +#if !defined(_MSC_VER) && !defined(__GNUC__) this->staticSegment = GameState_Alloc(&this->state, size, "../z_select.c", 1114); DmaMgr_SendRequest1(this->staticSegment, _z_select_staticSegmentRomStart, size, "../z_select.c", 1115); - #endif +#endif gSaveContext.cutsceneIndex = 0x8000; gSaveContext.linkAge = 1; } diff --git a/soh/src/overlays/gamestates/ovl_title/z_title.c b/soh/src/overlays/gamestates/ovl_title/z_title.c index 380720dd1..18996f15e 100644 --- a/soh/src/overlays/gamestates/ovl_title/z_title.c +++ b/soh/src/overlays/gamestates/ovl_title/z_title.c @@ -34,7 +34,7 @@ void Title_PrintBuildInfo(Gfx** gfxp) { #ifdef _MSC_VER GfxPrint_Printf(&printer, "MSVC SHIP"); #else - GfxPrint_Printf(printer, "GCC SHIP"); + GfxPrint_Printf(&printer, "GCC SHIP"); #endif GfxPrint_SetPos(&printer, 5, 4); diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c index 5b90725e1..27575c3b6 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c @@ -119,7 +119,7 @@ void KaleidoScope_DrawPlayerWork(GlobalContext* globalCtx) { func_8009214C(globalCtx, pauseCtx->playerSegment, &pauseCtx->playerSkelAnime, &pos, &rot, scale, CUR_EQUIP_VALUE(EQUIP_SWORD), CUR_EQUIP_VALUE(EQUIP_TUNIC) - 1, CUR_EQUIP_VALUE(EQUIP_SHIELD), CUR_EQUIP_VALUE(EQUIP_BOOTS) - 1); - gsSPResetFB(globalCtx->state.gfxCtx->polyOpa.p++, fbTest); + gsSPResetFB(globalCtx->state.gfxCtx->polyOpa.p++); } void KaleidoScope_DrawEquipment(GlobalContext* globalCtx) { diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c index bd5277286..f0b59fa4b 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c @@ -17,6 +17,14 @@ void KaleidoScope_DrawDungeonMap(GlobalContext* globalCtx, GraphicsContext* gfxC gPauseDekuTitleENGTex, gPauseDodongoTitleENGTex, gPauseJabuTitleENGTex, gPauseForestTitleENGTex, gPauseFireTitleENGTex, gPauseWaterTitleENGTex, gPauseSpiritTitleENGTex, gPauseShadowTitleENGTex, gPauseBotWTitleENGTex, gPauseIceCavernTitleENGTex, + + gPauseDekuTitleGERTex, gPauseDodongoTitleGERTex, gPauseJabuTitleGERTex, gPauseForestTitleGERTex, + gPauseFireTitleGERTex, gPauseWaterTitleGERTex, gPauseSpiritTitleGERTex, gPauseShadowTitleGERTex, + gPauseBotWTitleGERTex, gPauseIceCavernTitleGERTex, + + gPauseDekuTitleFRATex, gPauseDodongoTitleFRATex, gPauseJabuTitleFRATex, gPauseForestTitleFRATex, + gPauseFireTitleFRATex, gPauseWaterTitleFRATex, gPauseSpiritTitleFRATex, gPauseShadowTitleFRATex, + gPauseBotWTitleFRATex, gPauseIceCavernTitleFRATex, }; static void* floorIconTexs[] = { gDungeonMapBlankFloorButtonTex, gDungeonMap8FButtonTex, gDungeonMap7FButtonTex, gDungeonMap6FButtonTex, @@ -216,7 +224,7 @@ void KaleidoScope_DrawDungeonMap(GlobalContext* globalCtx, GraphicsContext* gfxC gSPVertex(POLY_KAL_DISP++, &pauseCtx->mapPageVtx[68], 16, 0); - gDPLoadTextureBlock(POLY_KAL_DISP++, dungeonTitleTexs[gSaveContext.mapIndex], G_IM_FMT_IA, G_IM_SIZ_8b, 96, 16, 0, + gDPLoadTextureBlock(POLY_KAL_DISP++, dungeonTitleTexs[gSaveContext.mapIndex+(10*gSaveContext.language)], G_IM_FMT_IA, G_IM_SIZ_8b, 96, 16, 0, G_TX_WRAP | G_TX_NOMIRROR, G_TX_WRAP | G_TX_NOMIRROR, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c index 8732093ca..df6520ebf 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c @@ -3179,9 +3179,9 @@ void KaleidoScope_Update(GlobalContext* globalCtx) if (gSaveContext.language == LANGUAGE_ENG) { memcpy(pauseCtx->nameSegment + 0x400, ResourceMgr_LoadTexByName(mapNameTextures[36 + gSaveContext.worldMapArea]), 0xA00); } else if (gSaveContext.language == LANGUAGE_GER) { - memcpy(pauseCtx->nameSegment + 0x400, ResourceMgr_LoadTexByName(mapNameTextures[59 + gSaveContext.worldMapArea]), 0xA00); + memcpy(pauseCtx->nameSegment + 0x400, ResourceMgr_LoadTexByName(mapNameTextures[58 + gSaveContext.worldMapArea]), 0xA00); } else { - memcpy(pauseCtx->nameSegment + 0x400, ResourceMgr_LoadTexByName(mapNameTextures[81 + gSaveContext.worldMapArea]), 0xA00); + memcpy(pauseCtx->nameSegment + 0x400, ResourceMgr_LoadTexByName(mapNameTextures[80 + gSaveContext.worldMapArea]), 0xA00); } } // OTRTODO - player on pause diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_lmap_mark_data.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_lmap_mark_data.c index df96fc876..64275108b 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_lmap_mark_data.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_lmap_mark_data.c @@ -15,6 +15,522 @@ static const Vtx sMarkChestVtx[] = { }; PauseMapMarksData gPauseMapMarkDataTable[] = { + // Deku Tree map 3F + { + { PAUSE_MAP_MARK_CHEST, + 23, //unk + sMarkChestVtx, + 4, //unk + 2, //Number of icons to show. + { //ID, X, Y + { 2, 40.0f, -33.0f }, + { 6, 49.0f, -42.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Deku Tree map 2F + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 2, + { + { 1, 48.0f, -63.0f }, + { 5, 52.0f, -68.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Deku Tree map 1F + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 1, + { + { 3, 84.0f, -39.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Deku Tree map B1 + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 1, + { + { 4, 77.0f, -26.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Deku Tree map B2 + { + { PAUSE_MAP_MARK_BOSS, + 23, + sMarkBossVtx, + 4, + 1, + { + { -1, 55.0f, 0.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Dodongo's Cavern map 2F + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 3, + { + { 10, 25.0f, -41.0f }, + { 4, 53.0f, -47.0f }, + { 6, 58.0f, -59.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Dodongo's Cavern map 1F + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 2, + { + { 5, 13.0f, -60.0f }, + { 8, 20.0f, -49.0f }, + } }, + { PAUSE_MAP_MARK_BOSS, + 23, + sMarkBossVtx, + 4, + 1, + { + { -1, 23.0f, -25.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Jabu-Jabu's Belly map 1F + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 3, + { + { 1, 67.0f, -13.0f }, + { 2, 28.0f, -13.0f }, + { 4, 38.0f, 0.0f }, + } }, + { PAUSE_MAP_MARK_BOSS, + 23, + sMarkBossVtx, + 4, + 1, + { + { -1, 65.0f, -37.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Jabu-Jabu's Belly map B1 + { + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Forest Temple map 2F + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 4, + { + { 0, 49.0f, -3.0f }, + { 2, 12.0f, -26.0f }, + { 5, 74.0f, -13.0f }, + { 7, 82.0f, -22.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Forest Temple map 1F + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 4, + { + { 0, 49.0f, -3.0f }, + { 2, 12.0f, -26.0f }, + { 5, 74.0f, -13.0f }, + { 7, 82.0f, -22.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Forest Temple map B1 + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 1, + { + { 9, 31.0f, -29.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Forest Temple map B2 + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 1, + { + { 11, 40.0f, -41.0f }, + } }, + { PAUSE_MAP_MARK_BOSS, + 23, + sMarkBossVtx, + 4, + 1, + { + { -1, 50.0f, -11.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Fire Temple map 5F + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 2, + { + { 5, 22.0f, -41.0f }, + { 13, 74.0f, -29.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Fire Temple map 4F + { + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Fire Temple map 3F + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 3, + { + { 3, 76.0f, -48.0f }, + { 6, 72.0f, -50.0f }, + { 7, 44.0f, -17.0f }, + { 8, 63.0f, -12.0f }, + { 9, 30.0f, -34.0f }, + { 10, 61.0f, -31.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Fire Temple map 2F + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 1, + { + { 11, 78.0f, -34.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Fire Temple map 1F + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 5, + { + { 0, 48.0f, -17.0f }, + { 1, 35.0f, -45.0f }, + { 2, 67.0f, -58.0f }, + { 4, 74.0f, -15.0f }, + { 12, 47.0f, -27.0f }, + } }, + { PAUSE_MAP_MARK_BOSS, + 23, + sMarkBossVtx, + 4, + 1, + { + { -1, 26.0f, -34.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Water Temple map 3F + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 3, + { + { 2, 88.0f, -60.0f }, + { 7, 23.0f, -2.0f }, + { 9, 84.0f, -45.0f }, + } }, + { PAUSE_MAP_MARK_BOSS, + 23, + sMarkBossVtx, + 4, + 1, + { + { -1, 62.0f, -23.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Water Temple map 2F + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 2, + { + { 0, 86.0f, -60.0f }, + { 8, 76.0f, -72.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Water Temple map 1F + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 4, + { + { 1, 88.0f, -60.0f }, + { 3, 42.0f, -21.0f }, + { 5, 47.0f, -15.0f }, + { 10, 33.0f, -31.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Water Temple map B1 + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 1, + { + { 6, 77.0f, -66.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Spirit Temple map 4F + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 2, + { + { 10, 59.0f, -9.0f }, + { 18, 32.0f, -20.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Spirit Temple map 3F + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 5, + { + { 1, 20.0f, -43.0f }, + { 5, 83.0f, -26.0f }, + { 15, 57.0f, -14.0f }, + { 20, 81.0f, -55.0f }, + { 21, 87.0f, -55.0f }, + } }, + { PAUSE_MAP_MARK_BOSS, + 23, + sMarkBossVtx, + 4, + 1, + { + { -1, 47.0f, 0.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Spirit Temple map 2F + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 6, + { + { 2, 41.0f, -16.0f }, + { 3, 47.0f, -17.0f }, + { 6, 27.0f, -16.0f }, + { 12, 29.0f, -20.0f }, + { 13, 70.0f, -22.0f }, + { 14, 70.0f, -25.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Spirit Temple map 1F + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 4, + { + { 0, 38.0f, -17.0f }, + { 4, 55.0f, -14.0f }, + { 8, 15.0f, -14.0f }, + { 7, 78.0f, -3.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Shadow Temple map B1 + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 2, + { + { 1, 41.0f, -17.0f }, + { 7, 27.0f, -24.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Shadow Temple map B2 + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 2, + { + { 2, 81.0f, -20.0f }, + { 3, 74.0f, -37.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Shadow Temple map B3 + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 2, + { + { 12, 96.0f, -51.0f }, + { 22, 96.0f, -55.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Shadow Temple map B4 + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 10, + { + { 4, 43.0f, -66.0f }, + { 5, 37.0f, -66.0f }, + { 6, 33.0f, -72.0f }, + { 8, 85.0f, -18.0f }, + { 9, 61.0f, -42.0f }, + { 10, 15.0f, -4.0f }, + { 11, 25.0f, -4.0f }, + { 13, 19.0f, -29.0f }, + { 21, 92.0f, -29.0f }, + { 20, 87.0f, -20.0f }, + } }, + { PAUSE_MAP_MARK_BOSS, + 23, + sMarkBossVtx, + 4, + 1, + { + { -1, 31.0f, -45.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Bottom of the Well map B1 + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 9, + { + { 1, 51.0f, -24.0f }, + { 3, 84.0f, -38.0f }, + { 4, 31.0f, -2.0f }, + { 5, 67.0f, -27.0f }, + { 8, 46.0f, -27.0f }, + { 10, 82.0f, -12.0f }, + { 12, 80.0f, -16.0f }, + { 14, 62.0f, -24.0f }, + { 20, 89.0f, -38.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Bottom of the Well map B2 + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 3, + { + { 2, 54.0f, -27.0f }, + { 9, 28.0f, -17.0f }, + { 16, 56.0f, -38.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Bottom of the Well map B3 + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 1, + { + { 7, 71.0f, -33.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, + // Ice Cavern map 1F + { + { PAUSE_MAP_MARK_CHEST, + 23, + sMarkChestVtx, + 4, + 3, + { + { 0, 66.0f, -2.0f }, + { 1, 77.0f, -46.0f }, + { 2, 27.0f, -45.0f }, + } }, + { PAUSE_MAP_MARK_NONE, 0, NULL, 0, 0, { 0 } }, + }, +}; +PauseMapMarksData gPauseMapMarkDataTableMasterQuest[] = { // Deku Tree map 0 { { PAUSE_MAP_MARK_CHEST,