From e733023c12a71a138475c90d81143999243de68e Mon Sep 17 00:00:00 2001 From: orangepeelbeef <130179+orangepeelbeef@users.noreply.github.com> Date: Sat, 27 Dec 2025 02:33:14 -0800 Subject: [PATCH 1/5] new FSModTool build stuff * added missing folder to kf1.csv * added warning message and except path for MIMList that is not defined but present in kf1.csv * updated the github link to the correct fsmod committee url * add build steps to FSModTool.pro * completely redo the github actions to utilize the .pro file * set releases name/version based on git tag rather than just the build --- .github/workflows/main.yml | 345 +++++++++++-------------------------- FSModTool.pro | 61 ++++++- aboutdialog.ui | 2 +- core/kfmtcore.cpp | 19 +- filelists/kf1.csv | 1 + 5 files changed, 169 insertions(+), 259 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3a598f7..1f54288 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,258 +1,109 @@ -name: Build all projects +name: Build and Release on: push: - branches: [ master ] - paths-ignore: - - '**.md' - - '**.png' - - "**.txt" - pull_request: - branches: [ master ] + tags: + - 'r*' # Only triggers when you push a tag starting with 'r' (e.g. r140) -jobs: - linux-build: - runs-on: ubuntu-18.04 - - steps: - - name: Checkout repo - uses: actions/checkout@v2 - with: - submodules: 'recursive' - - - name: Install Qt - uses: jurplel/install-qt-action@v2 - - - name: Install libxcb stuff - run: | - sudo apt install -y libxcb* - - - name: Get linuxdeployqt - run: | - wget "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage" -P ~/ - chmod +x ~/linuxdeployqt-continuous-x86_64.AppImage - - - name: Build checksum_tool - run: | - cd Tools/checksum_tool - qmake - make -j2 - cd .. - - - name: Build KFModTool - continue-on-error: true - run: | - - cd Tools/KFModTool - qmake - make -j2 - cd .. - - - name: Build KFRandomizer - run: | - cd Tools/KFRandomizer - qmake - make -j2 - cd .. - - - name: Build tfile_tool - run: | - cd Tools/tfile_tool - qmake - make -j2 - cd .. - - - name: Deploy checksum_tool AppImage - run: | - cd Tools/checksum_tool - ~/linuxdeployqt-continuous-x86_64.AppImage checksum_tool -appimage - - - name: Upload checksum_tool build - uses: actions/upload-artifact@v2 - with: - name: checksum_tool Linux (64-bit) AppImage - path: Tools/checksum_tool/checksum_tool*.AppImage - - - name: Deploy KFModTool AppImage - run: | - cd Tools/KFModTool - ~/linuxdeployqt-continuous-x86_64.AppImage KFModTool -appimage - - - name: Upload KFModTool build - continue-on-error: true - uses: actions/upload-artifact@v2 - with: - name: KFModTool Linux (64-bit) AppImage - path: Tools/KFModTool/KFModTool*.AppImage - - - name: Deploy KFRandomizer AppImage - run: | - cd Tools/KFRandomizer - ~/linuxdeployqt-continuous-x86_64.AppImage KFRandomizer -appimage +permissions: + contents: write - - name: Upload KFRandomizer build - uses: actions/upload-artifact@v2 - with: - name: KFRandomizer Linux (64-bit) AppImage - path: Tools/KFRandomizer/KFRandomizer*.AppImage - - - name: Deploy tfile_tool AppImage - run: | - cd Tools/tfile_tool - ~/linuxdeployqt-continuous-x86_64.AppImage tfile_tool -appimage - - - name: Upload tfile_tool build - uses: actions/upload-artifact@v2 - with: - name: tfile_tool Linux (64-bit) AppImage - path: Tools/tfile_tool/tfile_tool*.AppImage +jobs: + build: + name: Build (${{ matrix.os }}) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - os: windows-latest + qt_arch: win64_mingw81 + - os: ubuntu-20.04 + qt_arch: gcc_64 + - os: macos-latest + qt_arch: clang_64 - windows-build: - runs-on: windows-latest - steps: - - name: Checkout repo - uses: actions/checkout@v2 - with: - submodules: 'recursive' - - - name: Install Qt - uses: jurplel/install-qt-action@v2 - with: - arch: win64_mingw81 - - - name: Build checksum_tool - run: | - cd Tools\checksum_tool - qmake - make -j2 - cd .. - - - name: Build KFModTool - continue-on-error: true - run: | - cd Tools\KFModTool - qmake - make -j2 - cd .. - - - name: Build KFRandomizer - run: | - cd Tools\KFRandomizer - qmake - make -j2 - cd .. - - - name: Build tfile_tool - run: | - cd Tools\tfile_tool - qmake - make -j2 - cd .. + - name: Checkout repository + uses: actions/checkout@v4 + with: + submodules: 'recursive' + + - name: Install Qt + uses: jurplel/install-qt-action@v3 + with: + version: '5.15.2' + arch: ${{ matrix.qt_arch }} + + - name: Set up MinGW (Windows) + if: runner.os == 'Windows' + uses: egor-tensin/setup-mingw@v2 + with: + platform: x64 + + - name: Build Project + shell: bash + run: | + mkdir build_assets + cd build_assets + qmake ../FSModTool.pro CONFIG+=release + if [ "$RUNNER_OS" == "Windows" ]; then + mingw32-make -j$(nproc) + else + make -j$(nproc) + fi + + - name: Package Windows (win64) + if: runner.os == 'Windows' + shell: bash + # github.ref_name will be "r140" + run: mv *_Release.zip FSModTool-${{ github.ref_name }}-windows-x86_64.zip + + - name: Package Linux (lin64 & AppImage) + if: runner.os == 'Linux' + shell: bash + run: | + sudo apt-get update && sudo apt-get install -y libxcb-util1 zip + zip -j FSModTool-${{ github.ref_name }}-linux-x86_64.zip build_assets/FSModTool + + wget -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage" + chmod a+x linuxdeployqt-continuous-x86_64.AppImage + echo -e "[Desktop Entry]\nType=Application\nName=FSModTool\nExec=FSModTool\nIcon=FSModTool\nCategories=Development;" > FSModTool.desktop + ./linuxdeployqt-continuous-x86_64.AppImage build_assets/FSModTool -appimage -unsupported-allow-new-glibc + + mv FSModTool-x86_64.AppImage FSModTool-linux-appimage.AppImage + zip FSModTool-${{ github.ref_name }}-linux-appimage.zip FSModTool-linux-appimage.AppImage + + - name: Package macOS (mac64) + if: runner.os == 'macOS' + shell: bash + run: | + macdeployqt build_assets/FSModTool.app + zip -r FSModTool-${{ github.ref_name }}-macos-x86_64.zip build_assets/FSModTool.app + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: assets-${{ matrix.os }} + path: FSModTool-*.zip - - name: Deploy checksum_tool - run : | - cd Tools\checksum_tool\release - windeployqt --compiler-runtime checksum_tool.exe - del *.o - del *.cpp - del *.h - cp $env:Qt5_Dir\bin\libgcc_s_seh-1.dll . - cp $env:Qt5_Dir\bin\libstdc++-6.dll . - cp $env:Qt5_Dir\bin\libwinpthread-1.dll . - cd .. - ren release checksum_tool - tar.exe -a -c -f "checksum_tool Windows (64-bit) build.zip" checksum_tool - - - name: Upload checksum_tool build - uses: actions/upload-artifact@v2 - with: - name: checksum_tool Windows (64-bit) build - path: 'Tools\checksum_tool\checksum_tool Windows (64-bit) build.zip' - - - name: Deploy KFModTool - continue-on-error: true - run : | - cd Tools\KFModTool\release - windeployqt --compiler-runtime KFModTool.exe - del *.o - del *.cpp - del *.h - cp $env:Qt5_Dir\bin\libgcc_s_seh-1.dll . - cp $env:Qt5_Dir\bin\libstdc++-6.dll . - cp $env:Qt5_Dir\bin\libwinpthread-1.dll . - cd .. - ren release KFModTool - tar.exe -a -c -f "KFModTool Windows (64-bit) build.zip" KFModTool - - - name: Upload KFModTool build - continue-on-error: true - uses: actions/upload-artifact@v2 - with: - name: KFModTool Windows (64-bit) build - path: 'Tools\KFModTool\KFModTool Windows (64-bit) build.zip' - - - name: Deploy KFRandomizer - run : | - cd Tools\KFRandomizer\release - windeployqt --compiler-runtime KFRandomizer.exe - del *.o - del *.cpp - del *.h - cp $env:Qt5_Dir\bin\libgcc_s_seh-1.dll . - cp $env:Qt5_Dir\bin\libstdc++-6.dll . - cp $env:Qt5_Dir\bin\libwinpthread-1.dll . - cd .. - ren release KFRandomizer - tar.exe -a -c -f "KFRandomizer Windows (64-bit) build.zip" KFRandomizer - - - name: Upload KFRandomizer build - uses: actions/upload-artifact@v2 - with: - name: KFRandomizer Windows (64-bit) build - path: 'Tools\KFRandomizer\KFRandomizer Windows (64-bit) build.zip' - - - name: Deploy tfile_tool - run : | - cd Tools\tfile_tool\release - windeployqt --compiler-runtime tfile_tool.exe - del *.o - del *.cpp - del *.h - cp $env:Qt5_Dir\bin\libgcc_s_seh-1.dll . - cp $env:Qt5_Dir\bin\libstdc++-6.dll . - cp $env:Qt5_Dir\bin\libwinpthread-1.dll . - cd .. - ren release tfile_tool - tar.exe -a -c -f "tfile_tool Windows (64-bit) build.zip" tfile_tool - cd ../.. - - - name: Upload tfile_tool build - uses: actions/upload-artifact@v2 - with: - name: tfile_tool Windows (64-bit) build - path: 'Tools\tfile_tool\tfile_tool Windows (64-bit) build.zip' - - # This is practically copied from DuckStation's GitHub Actions workflow. create-release: - needs: [linux-build, windows-build] + needs: [build] runs-on: ubuntu-latest - steps: - - name: "Download all artifacts" - uses: actions/download-artifact@v2 - - - name: "tree for debugging" - run: | - sudo apt install tree - tree - - - name: "Create release" - uses: "marvinpinto/action-automatic-releases@latest" - with: - repo_token: "${{ secrets.GITHUB_TOKEN }}" - automatic_release_tag: "r${{ github.run_number }}" - prerelease: false - title: "KingsFieldRE r${{ github.run_number }}" - files: | - */* + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: release_assets + merge-multiple: true + + - name: Create GitHub Release + uses: "marvinpinto/action-automatic-releases@latest" + with: + repo_token: "${{ secrets.GITHUB_TOKEN }}" + # Uses the actual tag name you pushed + automatic_release_tag: "${{ github.ref_name }}" + prerelease: false + title: "FSModTool ${{ github.ref_name }}" + files: | + release_assets/FSModTool-*.zip \ No newline at end of file diff --git a/FSModTool.pro b/FSModTool.pro index 85571a1..d6fe314 100644 --- a/FSModTool.pro +++ b/FSModTool.pro @@ -2,16 +2,19 @@ QT += 3danimation 3dcore 3dinput 3dlogic 3drender core gui widgets greaterThan(QT_MAJOR_VERSION, 4): QT += -# Use the GitHub Actions run ID -RUNID = $$(GITHUB_RUN_NUMBER) +# Identify the app version. +# Priority: GitHub Tag -> Local Git Branch-Hash -> Fallback +RUNID = $$(GITHUB_REF_NAME) -!isEmpty(RUNID) { - DEFINES += "RUNID=\\\"$$RUNID\\\"" -} isEmpty(RUNID) { - DEFINES += "RUNID=\\\"DEVELOPMENT\\\"" + GIT_BRANCH = $$system(git rev-parse --abbrev-ref HEAD) + GIT_HASH = $$system(git rev-parse --short HEAD) + !isEmpty(GIT_BRANCH):!isEmpty(GIT_HASH): RUNID = "$$GIT_BRANCH-$$GIT_HASH" } +isEmpty(RUNID): RUNID = DEVELOPMENT +DEFINES += "RUNID=\\\"$$RUNID\\\"" + # Set C++ to latest standard CONFIG += c++latest @@ -90,8 +93,6 @@ HEADERS += \ models/texturelistmodel.h \ models/tilecontentslistmodel.h \ models/vfxinstancetablemodel.h \ - platform/psx/sdk/fixedp.h \ - platform/psx/sdk/libgte.h \ types/kf1/levelcurveentry.h \ types/kf2/armourparams.h \ types/kf2/entity.h \ @@ -192,3 +193,47 @@ DISTFILES += \ litStatic.vert \ unlitSimple.frag \ unlitSimple.vert + +CONFIG(release, debug|release):win32 { + DIST_DIR = $$OUT_PWD/dist + PACKAGE_FILE = $$OUT_PWD/../$${TARGET}_Release.zip + EXE_NAME = $${TARGET}.exe + BUILD_PATH = $$OUT_PWD/release/$$EXE_NAME + DIST_PATH = $$DIST_DIR/$$EXE_NAME + + CLEAN_CMD = if exist $$shell_quote($$shell_path($$DIST_DIR)) rmdir /s /q $$shell_quote($$shell_path($$DIST_DIR)) + MKDIR_CMD = mkdir $$shell_quote($$shell_path($$DIST_DIR)) + COPY_CMD = copy /y $$shell_quote($$shell_path($$BUILD_PATH)) $$shell_quote($$shell_path($$DIST_PATH)) + DEPLOY_CMD = $$shell_quote($$shell_path($$[QT_INSTALL_BINS]/windeployqt.exe)) --compiler-runtime $$shell_quote($$shell_path($$DIST_PATH)) + ZIP_CMD = cd /d $$shell_quote($$shell_path($$DIST_DIR)) && tar -a -cf $$shell_quote($$shell_path($$PACKAGE_FILE)) * + + QMAKE_POST_LINK += $$CLEAN_CMD && $$MKDIR_CMD && $$COPY_CMD && $$DEPLOY_CMD && $$ZIP_CMD +} + +CONFIG(release, debug|release):macx { + DIST_DIR = $$OUT_PWD/dist + PACKAGE_FILE = $$OUT_PWD/../$${TARGET}_Release.zip + EXE_NAME = $${TARGET}.app + BUILD_PATH = $$OUT_PWD/$$EXE_NAME + DIST_PATH = $$DIST_DIR/$$EXE_NAME + + CLEAN_CMD = rm -rf $$shell_quote($$shell_path($$DIST_DIR)) + MKDIR_CMD = mkdir -p $$shell_quote($$shell_path($$DIST_DIR)) + COPY_CMD = cp -R $$shell_quote($$shell_path($$BUILD_PATH)) $$shell_quote($$shell_path($$DIST_PATH)) + DEPLOY_CMD = $$shell_quote($$shell_path($$[QT_INSTALL_BINS]/macdeployqt)) $$shell_quote($$shell_path($$DIST_PATH)) + ZIP_CMD = cd $$shell_quote($$shell_path($$DIST_DIR)) && zip -r -y $$shell_quote($$shell_path($$PACKAGE_FILE)) . + + QMAKE_POST_LINK += $$CLEAN_CMD && $$MKDIR_CMD && $$COPY_CMD && $$DEPLOY_CMD && $$ZIP_CMD +} + +CONFIG(release, debug|release):unix:!macx:!android { + DIST_DIR = $$OUT_PWD/dist + PACKAGE_FILE = $$OUT_PWD/../$${TARGET}_Release.tar.gz + + CLEAN_CMD = rm -rf $$shell_quote($$shell_path($$DIST_DIR)) + MKDIR_CMD = mkdir -p $$shell_quote($$shell_path($$DIST_DIR)) + COPY_CMD = cp $$shell_quote($$shell_path($$OUT_PWD/$$TARGET)) $$shell_quote($$shell_path($$DIST_DIR/)) + TAR_CMD = cd $$shell_quote($$shell_path($$DIST_DIR)) && tar -czf $$shell_quote($$shell_path($$PACKAGE_FILE)) * + + QMAKE_POST_LINK += $$CLEAN_CMD && $$MKDIR_CMD && $$COPY_CMD && $$TAR_CMD +} diff --git a/aboutdialog.ui b/aboutdialog.ui index 3a325de..65a472f 100644 --- a/aboutdialog.ui +++ b/aboutdialog.ui @@ -36,7 +36,7 @@ - <html><head/><body><p>A project of The FromSoft Modding Committee. Visit us on GitHub at: <a href="https://github.com/IvanDSM/KingsFieldRE"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/IvanDSM/KingsFieldRE</span></a>!</p></body></html> + <html><head/><body><p>A project of The FromSoft Modding Committee. Visit us on GitHub at: <a href="https://github.com/FromSoft-Modding-Committee-FSMC"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/FromSoft-Modding-Committee-FSMC</span></a>!</p></body></html> true diff --git a/core/kfmtcore.cpp b/core/kfmtcore.cpp index ce4cfad..6019250 100644 --- a/core/kfmtcore.cpp +++ b/core/kfmtcore.cpp @@ -136,9 +136,18 @@ KFMTFile::FileFormat KFMTCore::parseFileFormat(const QString& fileTypeStr) else if (fileTypeStr == QStringLiteral("MIX")) return KFMTFile::FileFormat::MIX; else if (fileTypeStr == QStringLiteral("Raw")) return KFMTFile::FileFormat::Raw; else if (fileTypeStr == QStringLiteral("T")) return KFMTFile::FileFormat::T; - - fsmt_assert(false, "KFMTCore::parseFileFormat: File had unknown file format."); -} + else if (fileTypeStr == QStringLiteral("MIMList")) + { + static bool warned = false; + if (!warned) { + KFMTError::warning(QStringLiteral("Support for type %1 is does not currently exist. ").arg(fileTypeStr)); + warned = true; + } + // Return Raw as a fallback so the app doesn't crash + return KFMTFile::FileFormat::Raw; + } + fsmt_assert((KFMTError::warning(QStringLiteral("KFMTCore::parseFileFormat: Unknown format '%1'").arg(fileTypeStr)), false), + "KFMTCore::parseFileFormat: File had unknown file format.");} void KFMTCore::loadFileList(const QString& fileList) { @@ -173,6 +182,10 @@ void KFMTCore::loadFileList(const QString& fileList) for (auto i = 0; i < path.size() - 1; i++) { parent = (*parent)[path[i]]; + if (parent == nullptr) + { + KFMTError::warning(QString("Failed to find parent for path: %1, looking for: %2").arg(line[0]).arg(path[i])); + } fsmt_assert(parent != nullptr, "KFMTCore::loadFileList: Couldn't find file parent!"); } } diff --git a/filelists/kf1.csv b/filelists/kf1.csv index 9534045..2835f01 100644 --- a/filelists/kf1.csv +++ b/filelists/kf1.csv @@ -1,6 +1,7 @@ FSMTFileList,v,0,1 FILES,,, Path,FileType,DataType,PrettyName +KF,Folder,Container, KF/B0,Folder,Container, KF/B0/END,Raw,MusicSequence,Epilogue KF/B0/ENDG,Raw,MusicSequence,Ending From 30f0b803b257116de9aad707cd13144dfe96e137 Mon Sep 17 00:00:00 2001 From: orangepeelbeef <130179+orangepeelbeef@users.noreply.github.com> Date: Sat, 27 Dec 2025 03:29:02 -0800 Subject: [PATCH 2/5] Update the workflow and make a beta release --- .github/workflows/main.yml | 61 ++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1f54288..ba5f80d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,9 +18,9 @@ jobs: include: - os: windows-latest qt_arch: win64_mingw81 - - os: ubuntu-20.04 + - os: ubuntu-22.04 qt_arch: gcc_64 - - os: macos-latest + - os: macos-15-intel qt_arch: clang_64 steps: @@ -32,23 +32,31 @@ jobs: - name: Install Qt uses: jurplel/install-qt-action@v3 with: + aqtversion: '==3.1.*' version: '5.15.2' + tools: ${{ runner.os == 'Windows' && 'tools_mingw81' || '' }} arch: ${{ matrix.qt_arch }} + modules: 'qtquick3d' - - name: Set up MinGW (Windows) + - name: Build Project (Windows) if: runner.os == 'Windows' - uses: egor-tensin/setup-mingw@v2 - with: - platform: x64 + shell: cmd + run: | + mkdir build_assets + cd build_assets + set PATH=%IQTA_TOOLS%/mingw810_64/bin;%PATH% + qmake ..\FSModTool.pro CONFIG+=release + mingw32-make -j2 - - name: Build Project + - name: Build Project (Unix) + if: runner.os != 'Windows' shell: bash run: | mkdir build_assets cd build_assets qmake ../FSModTool.pro CONFIG+=release - if [ "$RUNNER_OS" == "Windows" ]; then - mingw32-make -j$(nproc) + if [ "$RUNNER_OS" == "macOS" ]; then + make -j$(sysctl -n hw.ncpu) else make -j$(nproc) fi @@ -56,36 +64,40 @@ jobs: - name: Package Windows (win64) if: runner.os == 'Windows' shell: bash - # github.ref_name will be "r140" - run: mv *_Release.zip FSModTool-${{ github.ref_name }}-windows-x86_64.zip + run: mv FSModTool_Release.zip FSModTool-${{ github.ref_name }}-windows-x86_64.zip - name: Package Linux (lin64 & AppImage) if: runner.os == 'Linux' shell: bash + env: + APPIMAGE_EXTRACT_AND_RUN: 1 run: | - sudo apt-get update && sudo apt-get install -y libxcb-util1 zip - zip -j FSModTool-${{ github.ref_name }}-linux-x86_64.zip build_assets/FSModTool - + sudo apt-get update && sudo apt-get install -y libxcb-util1 zip imagemagick + mv FSModTool_Release.tar.gz FSModTool-${{ github.ref_name }}-linux-x86_64.tar.gz + #AppImage + convert KFModTool.ico[0] build_assets/FSModTool.png wget -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage" chmod a+x linuxdeployqt-continuous-x86_64.AppImage - echo -e "[Desktop Entry]\nType=Application\nName=FSModTool\nExec=FSModTool\nIcon=FSModTool\nCategories=Development;" > FSModTool.desktop - ./linuxdeployqt-continuous-x86_64.AppImage build_assets/FSModTool -appimage -unsupported-allow-new-glibc - - mv FSModTool-x86_64.AppImage FSModTool-linux-appimage.AppImage - zip FSModTool-${{ github.ref_name }}-linux-appimage.zip FSModTool-linux-appimage.AppImage + echo -e "[Desktop Entry]\nType=Application\nName=FSModTool\nExec=FSModTool\nIcon=FSModTool\nCategories=Development;" > build_assets/FSModTool.desktop + cd build_assets + export VERSION=${{ github.ref_name }} + ../linuxdeployqt-continuous-x86_64.AppImage FSModTool -appimage -unsupported-allow-new-glibc + cd .. + mv FSModTool-*-x86_64.AppImage FSModTool-${{ github.ref_name }}-x86_64.AppImage + zip FSModTool-${{ github.ref_name }}-x86_64-AppImage.zip FSModTool-${{ github.ref_name }}-x86_64.AppImage - name: Package macOS (mac64) if: runner.os == 'macOS' shell: bash - run: | - macdeployqt build_assets/FSModTool.app - zip -r FSModTool-${{ github.ref_name }}-macos-x86_64.zip build_assets/FSModTool.app + run: mv FSModTool_Release.zip FSModTool-${{ github.ref_name }}-macos-x86_64.zip - name: Upload Artifacts uses: actions/upload-artifact@v4 with: name: assets-${{ matrix.os }} - path: FSModTool-*.zip + path: | + FSModTool-*.zip + FSModTool-*.tar.gz create-release: needs: [build] @@ -101,9 +113,8 @@ jobs: uses: "marvinpinto/action-automatic-releases@latest" with: repo_token: "${{ secrets.GITHUB_TOKEN }}" - # Uses the actual tag name you pushed automatic_release_tag: "${{ github.ref_name }}" prerelease: false title: "FSModTool ${{ github.ref_name }}" files: | - release_assets/FSModTool-*.zip \ No newline at end of file + release_assets/FSModTool-* From a53bba146be493beaa2ff8b9b6914789b9903c09 Mon Sep 17 00:00:00 2001 From: orangepeelbeef <130179+orangepeelbeef@users.noreply.github.com> Date: Sat, 27 Dec 2025 05:09:43 -0800 Subject: [PATCH 3/5] change the datahandler declaration to build on later mac --- .github/workflows/main.yml | 8 +- datahandlers/model.h | 347 +++++++++++-------------------------- datahandlers/texturedb.h | 70 ++++---- 3 files changed, 134 insertions(+), 291 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ba5f80d..fb99254 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -64,7 +64,7 @@ jobs: - name: Package Windows (win64) if: runner.os == 'Windows' shell: bash - run: mv FSModTool_Release.zip FSModTool-${{ github.ref_name }}-windows-x86_64.zip + run: mv build_assets/FSModTool_Release.zip FSModTool-${{ github.ref_name }}-windows-x86_64.zip - name: Package Linux (lin64 & AppImage) if: runner.os == 'Linux' @@ -73,7 +73,7 @@ jobs: APPIMAGE_EXTRACT_AND_RUN: 1 run: | sudo apt-get update && sudo apt-get install -y libxcb-util1 zip imagemagick - mv FSModTool_Release.tar.gz FSModTool-${{ github.ref_name }}-linux-x86_64.tar.gz + mv build_assets/FSModTool_Release.tar.gz FSModTool-${{ github.ref_name }}-linux-x86_64.tar.gz #AppImage convert KFModTool.ico[0] build_assets/FSModTool.png wget -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage" @@ -83,13 +83,13 @@ jobs: export VERSION=${{ github.ref_name }} ../linuxdeployqt-continuous-x86_64.AppImage FSModTool -appimage -unsupported-allow-new-glibc cd .. - mv FSModTool-*-x86_64.AppImage FSModTool-${{ github.ref_name }}-x86_64.AppImage + mv build_assets/FSModTool-*-x86_64.AppImage FSModTool-${{ github.ref_name }}-x86_64.AppImage zip FSModTool-${{ github.ref_name }}-x86_64-AppImage.zip FSModTool-${{ github.ref_name }}-x86_64.AppImage - name: Package macOS (mac64) if: runner.os == 'macOS' shell: bash - run: mv FSModTool_Release.zip FSModTool-${{ github.ref_name }}-macos-x86_64.zip + run: mv build_assets/FSModTool_Release.zip FSModTool-${{ github.ref_name }}-macos-x86_64.zip - name: Upload Artifacts uses: actions/upload-artifact@v4 diff --git a/datahandlers/model.h b/datahandlers/model.h index e4614f5..1f9c4e1 100644 --- a/datahandlers/model.h +++ b/datahandlers/model.h @@ -6,46 +6,104 @@ #include #include #include +#include +#include -/*! - * \brief Class to represent a generic 3D model. - * This class is made to accomodate the three kinds of model King's Field uses: MO, RTMD and TMD. - * For MO files, each mesh in the animFrames vector represents a different frame of animation. The - * baseMesh variable is used as the standard mesh storage for RTMD and TMD files and for the base - * TMD mesh for MO files. - */ class Model : public KFMTDataHandler { public: - // Forward declarations for the internal structures + // 1. Define MOPacket first (needed by Vec3) + struct MOPacket + { + short x = 0; + short y = 0; + short z = 0; + MOPacket() = default; + MOPacket(short x_, short y_, short z_) : x(x_), y(y_), z(z_) {} + MOPacket(const MOPacket& other) : x(other.x), y(other.y), z(other.z) {} + }; + + // 2. Define Vec3 (needed by Mesh) + struct Vec3 + { + float x; + float y; + float z; + void applyPacket(const MOPacket& packet); + void readSVECTOR(QDataStream& in); + operator QVector3D() const { return {x, y, z}; } + }; - /*! - * \brief Structure for a XYZ vertex. - */ - struct Vec3; + // 3. Define Primitive (needed by Mesh) + struct Primitive + { + enum class PrimitiveFlag; + enum class PrimitiveMode; + + PrimitiveFlag flag; + PrimitiveMode mode; + uint8_t ilen; + uint8_t olen; + uint8_t r0 = 255, g0 = 255, b0 = 255; + uint8_t r1 = 255, g1 = 255, b1 = 255; + uint8_t r2 = 255, g2 = 255, b2 = 255; + uint8_t r3 = 255, g3 = 255, b3 = 255; + uint8_t alpha = 255; + uint8_t u0, v0, u1, v1, u2, v2, u3, v3; + uint16_t cba, tsb; + uint16_t vertex0, vertex1, vertex2, vertex3; + uint16_t normal0, normal1, normal2, normal3; + + QVector4D Colour0() const { return {r0 / 255.f, g0 / 255.f, b0 / 255.f, alpha / 255.f}; } + QVector4D Colour1() const { return {r1 / 255.f, g1 / 255.f, b1 / 255.f, alpha / 255.f}; } + QVector4D Colour2() const { return {r2 / 255.f, g2 / 255.f, b2 / 255.f, alpha / 255.f}; } + QVector4D Colour3() const { return {r3 / 255.f, g3 / 255.f, b3 / 255.f, alpha / 255.f}; } + + std::vector getAdaptedTexCoords() const; + bool isDoubleSided() const { return (static_cast(flag) >> 1) & 1; } + bool isGouraud() const { return ((static_cast(mode) >> 5) & 1) == 1; } + bool isGradation() const { return static_cast(flag) > 3; } + bool isLit() const { return (static_cast(flag) & 1) == 0; } + bool isQuad() const { + auto mode_ = static_cast(mode); + return (mode_ >> 5) && ((mode_ >> 3) & 1); + } + bool isSmooth() const { return (static_cast(mode) >> 4) & 1; } + bool isTextured() const { return (static_cast(mode) >> 2) & 1; } + bool isTriangle() const { + auto mode_ = static_cast(mode); + return (mode_ >> 5) && !((mode_ >> 3) & 1); + } - /*! - * \brief Structure for a TMD primitive. - */ - struct Primitive; + void readFrom(QDataStream& stream); + void readGradation(QDataStream& stream) { + if (isGradation()) { + stream >> r1 >> g1 >> b1; stream.skipRawData(1); + stream >> r2 >> g2 >> b2; stream.skipRawData(1); + if (isQuad()) { stream >> r3 >> g3 >> b3; stream.skipRawData(1); } + } + } + void readx20(QDataStream& stream); + void readx24(QDataStream& stream); + void readx25(QDataStream& stream); + void readx28(QDataStream& stream); + void readx2c(QDataStream& stream); + void readx30(QDataStream& stream); + void readx34(QDataStream& stream); + void readx38(QDataStream& stream); + void readx3c(QDataStream& stream); + }; - /*! - * \brief Mesh structure for storing vertex arrays. - */ + // 4. Define Mesh (Now it knows what Vec3 and Primitive are!) struct Mesh { std::vector vertices; std::vector normals; std::vector primitives; - bool visible = true; - Vec3& operator[](size_t vertex) { return vertices[vertex]; } }; - /*! - * \brief Header for MIM/MO files. - */ struct MIMOrMOHeader { uint32_t animationCount; @@ -54,27 +112,20 @@ class Model : public KFMTDataHandler uint32_t animationsOffset; }; - /*! - * \brief Structure for a MO-style animation. Contains an array of frame indexes. - */ - struct MOAnimation; - - /*! - * \brief Structure for a MO-style frame. - */ - struct MOFrame; + struct MOAnimation { std::vector frameIndexes; }; - /*! - * \brief Structure for a decoded MO morph target packet. - */ - struct MOPacket; + struct MOFrame + { + short Unknown00 = 0, Weight = 0, frameID = 0; + std::vector targets; + MOFrame(short u, short w, short f, short t) : Unknown00(u), Weight(w), frameID(f) { targets.resize(t); } + }; explicit Model(KFMTFile& modelFile); void saveChanges() override {} std::vector baseObjects; float scale = 1.0f; - std::vector animations; std::vector animFrames; std::vector morphTargets; @@ -88,221 +139,18 @@ class Model : public KFMTDataHandler Model::MIMOrMOHeader readMIMOrMOHeader(QDataStream& stream); }; -/*! - * \brief Operator for reading a primitive from a QDataStream. - * \param in QDataStream to read from. - * \param primitive Primitive to read into. - * \return The QDataStream after reading. - */ QDataStream& operator>>(QDataStream& in, Model::Primitive& primitive); -// Struct definitions - -struct Model::MOAnimation -{ - std::vector frameIndexes; -}; - -struct Model::MOFrame -{ - short Unknown00 = 0; - short Weight = 0; - short frameID = 0; - std::vector targets; - - MOFrame(short Unknown00_, short Weight_, short frameID_, short targetAmount) - : Unknown00(Unknown00_), Weight(Weight_), frameID(frameID_) - { - targets.resize(targetAmount); - } -}; - -struct Model::MOPacket -{ - short x = 0; - short y = 0; - short z = 0; - - MOPacket() = default; - MOPacket(short x_, short y_, short z_) : x(x_), y(y_), z(z_) {} - MOPacket(const MOPacket& other) : x(other.x), y(other.y), z(other.z) {} -}; - -struct Model::Primitive -{ - /*! - * \brief Enum with terribly long names for the primitive flags. - * Single/double faced only applies to polygon primitives. - */ - enum class PrimitiveFlag; - - /*! - * \brief Enum with terribly long names for the TMD primitive modes. - */ - enum class PrimitiveMode; - - PrimitiveFlag flag; - PrimitiveMode mode; - uint8_t ilen; - uint8_t olen; - // The following variables represent packet elements. Not all of them are present in all types, - // and the only reason all of them are declared here is to save time and not have to do some - // sketchy inheritance stuff that'd make the file 5x bigger. - uint8_t r0 = 255, g0 = 255, b0 = 255; - uint8_t r1 = 255, g1 = 255, b1 = 255; - uint8_t r2 = 255, g2 = 255, b2 = 255; - uint8_t r3 = 255, g3 = 255, b3 = 255; - uint8_t alpha = 255; - - uint8_t u0, v0; - uint8_t u1, v1; - uint8_t u2, v2; - uint8_t u3, v3; - - uint16_t cba; - uint16_t tsb; - - uint16_t vertex0, vertex1, vertex2, vertex3; - uint16_t normal0, normal1, normal2, normal3; - - /*! - * \brief Returns r0, g0 and b0 as a QVector4D - * \return QVector4D with colour - */ - QVector4D Colour0() const { return {r0 / 255.f, g0 / 255.f, b0 / 255.f, alpha / 255.f}; } - QVector4D Colour1() const { return {r1 / 255.f, g1 / 255.f, b1 / 255.f, alpha / 255.f}; } - QVector4D Colour2() const { return {r2 / 255.f, g2 / 255.f, b2 / 255.f, alpha / 255.f}; } - QVector4D Colour3() const { return {r3 / 255.f, g3 / 255.f, b3 / 255.f, alpha / 255.f}; } - - std::vector getAdaptedTexCoords() const; - - /*! - * \brief Checks if a primitive is double sided. - * \return Whether this is a double sided primitive. - */ - bool isDoubleSided() const - { - auto flag_ = static_cast(flag); - return (flag_ >> 1) & 1; - } - - /*! - * \brief Checks whether this is a Gouraud shaded primitive. - * \return Whether this is a Gouraud shaded primitive. - */ - bool isGouraud() const { return ((static_cast(mode) >> 5) & 1) == 1; } - - /*! - * \brief Checks whether this is a gradation primitive. - * \return Whether this is a gradation primitive. - */ - bool isGradation() const { return static_cast(flag) > 3; } - - /*! - * \brief Checks whether this is a lit primitive. - * \return Whether this is a lit primitive. - */ - bool isLit() const { return (static_cast(flag) & 1) == 0; } - - /*! - * \brief Checks whether this is a quadrilateral primitive. - * \return Whether this is a quadrilateral primitive. - */ - bool isQuad() const - { - auto mode_ = static_cast(mode); - return (mode_ >> 5) && ((mode_ >> 3) & 1); - } - - /*! - * \brief Checks whether this primitive is flat shaded. - * \return Whether this is a flat shade primitive. - */ - bool isSmooth() const - { - auto mode_ = static_cast(mode); - return (mode_ >> 4) & 1; - } - - /*! - * \brief Checks whether this primitive is textured. - * \return Whether this is a textured primitive. - */ - bool isTextured() const - { - auto mode_ = static_cast(mode); - return (mode_ >> 2) & 1; - } - - /*! - * \brief Checks whether this is a triangle primitive. - * \return Whether this is a triangle primitive. - */ - bool isTriangle() const - { - auto mode_ = static_cast(mode); - return (mode_ >> 5) && !((mode_ >> 3) & 1); - } - - void readFrom(QDataStream& stream); - // Helper method for reading gradation - void readGradation(QDataStream& stream) - { - if (isGradation()) - { - stream >> r1; - stream >> g1; - stream >> b1; - stream.skipRawData(1); - stream >> r2; - stream >> g2; - stream >> b2; - stream.skipRawData(1); - if (isQuad()) - { - stream >> r3; - stream >> g3; - stream >> b3; - stream.skipRawData(1); - } - } - } - // Primitive packet readers - void readx20(QDataStream& stream); - void readx24(QDataStream& stream); - void readx25(QDataStream& stream); - void readx28(QDataStream& stream); - void readx2c(QDataStream& stream); - void readx30(QDataStream& stream); - void readx34(QDataStream& stream); - void readx38(QDataStream& stream); - void readx3c(QDataStream& stream); -}; - -struct Model::Vec3 -{ - float x; - float y; - float z; - - void applyPacket(const MOPacket& packet); - void readSVECTOR(QDataStream& in); - - operator QVector3D() const { return {x, y, z}; } -}; - -// Enum definitions - enum class Model::Primitive::PrimitiveFlag { - SingleColorSingleFaceLightSourceNoCalc = 0b00000000, ///< 0x0 - SingleColorSingleFaceLightSourceCalc = 0b00000001, ///< 0x1 - SingleColorDoubleFaceLightSourceNoCalc = 0b00000010, ///< 0x2 - SingleColorDoubleFaceLightSourceCalc = 0b00000011, ///< 0x3 - GradationSingleFaceLightSourceNoCalc = 0b00000100, ///< 0x4 - GradationSingleFaceLightSourceCalc = 0b00000101, ///< 0x5 - GradationDoubleFaceLightSourceNoCalc = 0b00000110, ///< 0x6 - GradationDoubleFaceLightSourceCalc = 0b00000111 ///< 0x7 + SingleColorSingleFaceLightSourceNoCalc = 0b00000000, + SingleColorSingleFaceLightSourceCalc = 0b00000001, + SingleColorDoubleFaceLightSourceNoCalc = 0b00000010, + SingleColorDoubleFaceLightSourceCalc = 0b00000011, + GradationSingleFaceLightSourceNoCalc = 0b00000100, + GradationSingleFaceLightSourceCalc = 0b00000101, + GradationDoubleFaceLightSourceNoCalc = 0b00000110, + GradationDoubleFaceLightSourceCalc = 0b00000111 }; enum class Model::Primitive::PrimitiveMode @@ -352,4 +200,5 @@ enum class Model::Primitive::PrimitiveMode x7cSprite16x16Opaque = 0b01111100, x7eSprite16x16Translucent = 0b01111110 }; + #endif // MODEL_H diff --git a/datahandlers/texturedb.h b/datahandlers/texturedb.h index 53391aa..e96be6b 100644 --- a/datahandlers/texturedb.h +++ b/datahandlers/texturedb.h @@ -1,6 +1,5 @@ #ifndef TEXTUREDB_H #define TEXTUREDB_H - #include "datahandlers/kfmtdatahandler.h" #include #include @@ -13,11 +12,6 @@ class TextureDB : public KFMTDataHandler RTIM, TIM }; - - /*! - * \brief Structure for representing a single texture (CLUT + Pixel Data). - */ - struct Texture; enum class PixelMode { @@ -28,8 +22,36 @@ class TextureDB : public KFMTDataHandler Mixed = 4 }; - explicit TextureDB(KFMTFile& file_); + /*! + * \brief Structure for representing a single texture (CLUT + Pixel Data). + */ + struct Texture + { + // Info + PixelMode pMode; + bool cf = true; + QPoint framebufferCoordinate {0,0}; + + // CLUT Data + uint32_t clutSize; + uint16_t clutVramX; + uint16_t clutVramY; + uint16_t clutWidth; + uint16_t clutHeight; + QVector clutColorTable {}; + + // Pixel Data + uint32_t pxDataSize; + uint16_t pxVramX; + uint16_t pxVramY; + uint16_t pxWidth; + uint16_t pxHeight; + QImage image; + std::vector getCLUTEntries() const; + }; + + explicit TextureDB(KFMTFile& file_); QPoint getFramebufferCoordinate(size_t textureIndex); Texture &getTexture(size_t textureIndex); size_t getTextureCount() const { return textures.size(); } @@ -37,47 +59,19 @@ class TextureDB : public KFMTDataHandler void saveChanges() override; private: - void loadRTIM(); void loadTIM(); - + bool readCLUT(QDataStream &stream, Texture &targetTex); void readPixelData(QDataStream &stream, Texture &targetTex); - + void writeRTIM(); void writeTIM(); - + static void writeCLUT(QDataStream &stream, const Texture &targetTex, TexDBType type); static void writePixelData(QDataStream& stream, const Texture& targetTex, TexDBType type); - std::vector textures; TexDBType type; }; -struct TextureDB::Texture -{ - // Info - PixelMode pMode; - bool cf = true; - QPoint framebufferCoordinate {0,0}; - - // CLUT Data - uint32_t clutSize; - uint16_t clutVramX; - uint16_t clutVramY; - uint16_t clutWidth; - uint16_t clutHeight; - QVector clutColorTable {}; - - // Pixel Data - uint32_t pxDataSize; - uint16_t pxVramX; - uint16_t pxVramY; - uint16_t pxWidth; - uint16_t pxHeight; - QImage image; - - std::vector getCLUTEntries() const; -}; - #endif // TEXTUREDB_H From 96ca86df970a98b02964092ba751865d872d9503 Mon Sep 17 00:00:00 2001 From: orangepeelbeef <130179+orangepeelbeef@users.noreply.github.com> Date: Sat, 27 Dec 2025 05:23:26 -0800 Subject: [PATCH 4/5] QMAKE_POST_LINK had += for some reason --- .github/workflows/main.yml | 6 +++--- FSModTool.pro | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index fb99254..719e521 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -64,7 +64,7 @@ jobs: - name: Package Windows (win64) if: runner.os == 'Windows' shell: bash - run: mv build_assets/FSModTool_Release.zip FSModTool-${{ github.ref_name }}-windows-x86_64.zip + run: mv FSModTool_Release.zip FSModTool-${{ github.ref_name }}-windows-x86_64.zip - name: Package Linux (lin64 & AppImage) if: runner.os == 'Linux' @@ -73,7 +73,7 @@ jobs: APPIMAGE_EXTRACT_AND_RUN: 1 run: | sudo apt-get update && sudo apt-get install -y libxcb-util1 zip imagemagick - mv build_assets/FSModTool_Release.tar.gz FSModTool-${{ github.ref_name }}-linux-x86_64.tar.gz + mv FSModTool_Release.tar.gz FSModTool-${{ github.ref_name }}-linux-x86_64.tar.gz #AppImage convert KFModTool.ico[0] build_assets/FSModTool.png wget -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage" @@ -89,7 +89,7 @@ jobs: - name: Package macOS (mac64) if: runner.os == 'macOS' shell: bash - run: mv build_assets/FSModTool_Release.zip FSModTool-${{ github.ref_name }}-macos-x86_64.zip + run: mv FSModTool_Release.zip FSModTool-${{ github.ref_name }}-macos-x86_64.zip - name: Upload Artifacts uses: actions/upload-artifact@v4 diff --git a/FSModTool.pro b/FSModTool.pro index d6fe314..218e40a 100644 --- a/FSModTool.pro +++ b/FSModTool.pro @@ -207,7 +207,7 @@ CONFIG(release, debug|release):win32 { DEPLOY_CMD = $$shell_quote($$shell_path($$[QT_INSTALL_BINS]/windeployqt.exe)) --compiler-runtime $$shell_quote($$shell_path($$DIST_PATH)) ZIP_CMD = cd /d $$shell_quote($$shell_path($$DIST_DIR)) && tar -a -cf $$shell_quote($$shell_path($$PACKAGE_FILE)) * - QMAKE_POST_LINK += $$CLEAN_CMD && $$MKDIR_CMD && $$COPY_CMD && $$DEPLOY_CMD && $$ZIP_CMD + QMAKE_POST_LINK = $$CLEAN_CMD && $$MKDIR_CMD && $$COPY_CMD && $$DEPLOY_CMD && $$ZIP_CMD } CONFIG(release, debug|release):macx { @@ -223,7 +223,7 @@ CONFIG(release, debug|release):macx { DEPLOY_CMD = $$shell_quote($$shell_path($$[QT_INSTALL_BINS]/macdeployqt)) $$shell_quote($$shell_path($$DIST_PATH)) ZIP_CMD = cd $$shell_quote($$shell_path($$DIST_DIR)) && zip -r -y $$shell_quote($$shell_path($$PACKAGE_FILE)) . - QMAKE_POST_LINK += $$CLEAN_CMD && $$MKDIR_CMD && $$COPY_CMD && $$DEPLOY_CMD && $$ZIP_CMD + QMAKE_POST_LINK = $$CLEAN_CMD && $$MKDIR_CMD && $$COPY_CMD && $$DEPLOY_CMD && $$ZIP_CMD } CONFIG(release, debug|release):unix:!macx:!android { @@ -235,5 +235,5 @@ CONFIG(release, debug|release):unix:!macx:!android { COPY_CMD = cp $$shell_quote($$shell_path($$OUT_PWD/$$TARGET)) $$shell_quote($$shell_path($$DIST_DIR/)) TAR_CMD = cd $$shell_quote($$shell_path($$DIST_DIR)) && tar -czf $$shell_quote($$shell_path($$PACKAGE_FILE)) * - QMAKE_POST_LINK += $$CLEAN_CMD && $$MKDIR_CMD && $$COPY_CMD && $$TAR_CMD + QMAKE_POST_LINK = $$CLEAN_CMD && $$MKDIR_CMD && $$COPY_CMD && $$TAR_CMD } From 4c1c1d10c9ce3b31ad2893b84e3f7f9d8fd72de4 Mon Sep 17 00:00:00 2001 From: orangepeelbeef <130179+orangepeelbeef@users.noreply.github.com> Date: Sat, 27 Dec 2025 05:32:21 -0800 Subject: [PATCH 5/5] bump --- FSModTool.pro | 1 + 1 file changed, 1 insertion(+) diff --git a/FSModTool.pro b/FSModTool.pro index 218e40a..1cf469f 100644 --- a/FSModTool.pro +++ b/FSModTool.pro @@ -195,6 +195,7 @@ DISTFILES += \ unlitSimple.vert CONFIG(release, debug|release):win32 { + QMAKE_SH = DIST_DIR = $$OUT_PWD/dist PACKAGE_FILE = $$OUT_PWD/../$${TARGET}_Release.zip EXE_NAME = $${TARGET}.exe