diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..c5098e0 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +# EditorConfig is awesome: https://EditorConfig.org + +root = true + +[*] +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..a863d88 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,34 @@ +--- +name: Bug report 🐞 +about: Create a report to help us improve. If you come here from a 7th Heaven crash, DO NOT open an issue, as it will be closed IMMEDIATELY. Consider opening a discussion thread instead! +title: "[ GAME ] ISSUE" +labels: bug +assignees: "" +--- + +**PLEASE NOTE:** If you come here to report a crash while you were using 7th Heaven, please do on their relative support channels. NO SUPPORT will be provided, and your issue will be close immediately. + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: + +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**GPU (please complete the following information):** + +- Brand [e.g. Nvidia] +- Driver Version [e.g. 27.21.14.5730] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..927fac0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,17 @@ +--- +name: Feature Request 💡 +about: Suggest a new idea for the project. +labels: enhancement +--- + +## Summary + +Brief explanation of the feature. + +### Basic example + +If the proposal involves a new or changed API, include a basic code example. Omit this section if it's not applicable. + +### Motivation + +Why are we doing this? What use cases does it support? What is the expected outcome? diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..28ca26b --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,12 @@ +## Summary + +Brief explanation of the pull request. + +### Motivation + +Why are you doing this? What use cases does it support? What is the expected outcome? + +### ACKs + +- [ ] I have updated the [Changelog.md](https://github.com/julianxhokaxhiu/CTNx/blob/master/Changelog.md) file +- [ ] I did test my code on the game diff --git a/.github/workflows/alert.ps1 b/.github/workflows/alert.ps1 new file mode 100644 index 0000000..2e12fdd --- /dev/null +++ b/.github/workflows/alert.ps1 @@ -0,0 +1,44 @@ +#*****************************************************************************# +# Copyright (C) 2024 Julian Xhokaxhiu # +# # +# This file is part of CTNx # +# # +# CTNx is free software: you can redistribute it and\or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License # +# # +# CTNx is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +#*****************************************************************************# + +# $downloadUrl = "https://github.com/julianxhokaxhiu/CTNx/releases/latest" + +# if ($env:_IS_BUILD_CANARY -eq "true") { +# $downloadUrl = "https://github.com/julianxhokaxhiu/CTNx/releases/tag/canary" +# } + +# # Initial template from https://discohook.org/ +# $discordPost = @" +# { +# "username": "CTNx", +# "avatar_url": "https://github.com/julianxhokaxhiu/CTNx/raw/master/.logo/logo_whitebg.png", +# "content": "Release **${env:_RELEASE_VERSION}** has just been published!\n\nDownload Url: ${downloadUrl}\n\nIf you find something broken or unexpected, feel free to check existing ones first here https://github.com/julianxhokaxhiu/CTNx/issues.\nIf non existing, then report your issue here https://github.com/julianxhokaxhiu/CTNx/issues/new.\n\nThank you for using CTNx!", +# "embeds": [ +# { +# "title": "How to install", +# "description": "Feel free to follow instructions at this link, depending on which version of the game you own: https://github.com/julianxhokaxhiu/CTNx/blob/master/docs/how_to_install.md", +# "color": 7506394 +# }, +# { +# "title": "CTNx is FOSS Software!", +# "description": "CTNx is released under GPLv3 license. More info here: https://github.com/julianxhokaxhiu/CTNx#license", +# "color": 15746887 +# } +# ] +# } +# "@ + +# Invoke-RestMethod -Uri $env:_MAP_CTNx_QHIMM_CT -ContentType "application/json" -Method Post -Body $discordPost +# Invoke-RestMethod -Uri $env:_MAP_CTNx_TSUNAMODS_CT -ContentType "application/json" -Method Post -Body $discordPost diff --git a/.github/workflows/build.ps1 b/.github/workflows/build.ps1 new file mode 100644 index 0000000..eb02a1b --- /dev/null +++ b/.github/workflows/build.ps1 @@ -0,0 +1,103 @@ +#*****************************************************************************# +# Copyright (C) 2024 Julian Xhokaxhiu # +# # +# This file is part of CTNx # +# # +# CTNx is free software: you can redistribute it and\or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License # +# # +# CTNx is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +#*****************************************************************************# + +Set-StrictMode -Version Latest + +if ($env:_BUILD_BRANCH -eq "refs/heads/master" -Or $env:_BUILD_BRANCH -eq "refs/tags/canary") +{ + $env:_IS_BUILD_CANARY = "true" + $env:_IS_GITHUB_RELEASE = "true" +} +elseif ($env:_BUILD_BRANCH -like "refs/tags/*") +{ + $env:_CHANGELOG_VERSION = $env:_BUILD_VERSION.Substring(0,$env:_BUILD_VERSION.LastIndexOf('.')).Replace('.','') + $env:_BUILD_VERSION = $env:_BUILD_VERSION.Substring(0,$env:_BUILD_VERSION.LastIndexOf('.')) + ".0" + $env:_IS_GITHUB_RELEASE = "true" +} +$env:_RELEASE_VERSION = "v${env:_BUILD_VERSION}" + +$vcpkgRoot = "C:\vcpkg" +$vcpkgBaseline = [string](jq --arg baseline "builtin-baseline" -r '.[$baseline]' vcpkg.json) +$vcpkgOriginUrl = &"git" -C $vcpkgRoot remote get-url origin +$vcpkgBranchName = &"git" -C $vcpkgRoot branch --show-current + +$releasePath = [string](jq -r '.configurePresets[0].binaryDir' CMakePresets.json).Replace('${sourceDir}/', '') + +Write-Output "--------------------------------------------------" +Write-Output "BUILD CONFIGURATION: $env:_RELEASE_CONFIGURATION" +Write-Output "RELEASE VERSION: $env:_RELEASE_VERSION" +Write-Output "VCPKG ORIGIN: $vcpkgOriginUrl" +Write-Output "VCPKG BRANCH: $vcpkgBranchName" +Write-Output "VCPKG BASELINE: $vcpkgBaseline" +Write-Output "--------------------------------------------------" + +Write-Output "_BUILD_VERSION=${env:_BUILD_VERSION}" >> ${env:GITHUB_ENV} +Write-Output "_RELEASE_VERSION=${env:_RELEASE_VERSION}" >> ${env:GITHUB_ENV} +Write-Output "_IS_BUILD_CANARY=${env:_IS_BUILD_CANARY}" >> ${env:GITHUB_ENV} +Write-Output "_IS_GITHUB_RELEASE=${env:_IS_GITHUB_RELEASE}" >> ${env:GITHUB_ENV} +Write-Output "_CHANGELOG_VERSION=${env:_CHANGELOG_VERSION}" >> ${env:GITHUB_ENV} + +# Install CMake +Write-Output "Installing cmake v${env:_WINGET_CMAKE}..." +winget install Kitware.CMake --version ${env:_WINGET_CMAKE} --silent --uninstall-previous --accept-source-agreements --accept-package-agreements --disable-interactivity --force | out-null +cmake --version + +# Install Powershell +Write-Output "Installing powershell v${env:_WINGET_POWERSHELL}..." +winget install Microsoft.PowerShell --version ${env:_WINGET_POWERSHELL} --silent --uninstall-previous --accept-source-agreements --accept-package-agreements --disable-interactivity --force | out-null +pwsh --version + +# Install Visual Studio Enterprise +Write-Output "Installing VisualStudio 2022 Enterprise v${env:_WINGET_VS2022}..." +winget install Microsoft.VisualStudio.2022.Enterprise --version ${env:_WINGET_VS2022} --silent --accept-source-agreements --accept-package-agreements --disable-interactivity --force | out-null + +# Load vcvarsall environment for x86 +$vcvarspath = &"${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -prerelease -latest -property InstallationPath +cmd.exe /c "call `"$vcvarspath\VC\Auxiliary\Build\vcvarsall.bat`" x86 && set > %temp%\vcvars.txt" +Get-Content "$env:temp\vcvars.txt" | Foreach-Object { + if ($_ -match "^(.*?)=(.*)$") { + Set-Content "env:\$($matches[1])" $matches[2] + } +} + +# Unset VCPKG_ROOT if set +[Environment]::SetEnvironmentVariable('VCPKG_ROOT','') + +# Add Github Packages registry +nuget sources add -Name github -Source "https://nuget.pkg.github.com/julianxhokaxhiu/index.json" -Username ${env:GITHUB_REPOSITORY_OWNER} -Password ${env:GITHUB_PACKAGES_PAT} -StorePasswordInClearText +nuget setApiKey ${env:GITHUB_PACKAGES_PAT} -Source "https://nuget.pkg.github.com/julianxhokaxhiu/index.json" +nuget sources list + +# Vcpkg setup +git -C $vcpkgRoot pull --all +git -C $vcpkgRoot checkout $vcpkgBaseline +git -C $vcpkgRoot clean -fxd + +cmd.exe /c "call $vcpkgRoot\bootstrap-vcpkg.bat" + +vcpkg integrate install + +# Start the build +cmake --preset "${env:_RELEASE_CONFIGURATION}" -D_DLL_VERSION="$env:_BUILD_VERSION" +cmake --build --preset "${env:_RELEASE_CONFIGURATION}" + +# Start the packaging +mkdir .dist\pkg\CTNx | Out-Null +Copy-Item -R "$releasePath\bin\*" .dist\pkg\CTNx +Move-Item .dist\pkg\CTNx\CTNx.dll .dist\pkg\CTNx\version.dll + +7z a ".\.dist\${env:_RELEASE_NAME}-${env:_RELEASE_VERSION}.zip" ".\.dist\pkg\CTNx\*" + +Remove-Item -Recurse -Force .dist\pkg diff --git a/.github/workflows/main-0.0.1.yml b/.github/workflows/main-0.0.1.yml new file mode 100644 index 0000000..1278cda --- /dev/null +++ b/.github/workflows/main-0.0.1.yml @@ -0,0 +1,124 @@ +name: CTNx + +run-name: 0.0.1.${{ github.run_number }} + +on: + workflow_dispatch: + push: + branches: + - master + tags: + - "*" + pull_request: + branches: + - master + +env: + _IS_BUILD_CANARY: false + _IS_GITHUB_RELEASE: false + _RELEASE_NAME: CTNx + _RELEASE_VERSION: v0 + _RELEASE_CONFIGURATION: Release + _BUILD_BRANCH: "${{ github.ref }}" + _CHANGELOG_VERSION: "0" + # GIT: Fix reporting from stderr to stdout + GIT_REDIRECT_STDERR: 2>&1 + # Tools versions + _WINGET_CMAKE: 3.30.3 + _WINGET_POWERSHELL: 7.4.5 + _WINGET_VS2022: 17.11.1 + +jobs: + CTNx: + runs-on: windows-latest + timeout-minutes: 1440 + strategy: + max-parallel: 1 + steps: + - name: Set Git Config + run: | + git config --global core.autocrlf false + git config --global core.filemode false + git config --global core.longpaths true + - name: Checkout + uses: actions/checkout@v4.1.0 + - name: Install WinGet + uses: Cyberboss/install-winget@v1 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Build + run: ".github/workflows/build.ps1" + shell: pwsh + env: + _BUILD_VERSION: "0.0.1.${{ github.run_number }}" + GITHUB_PACKAGES_PAT: ${{ secrets.GITHUB_TOKEN }} + - name: Publish PR artifacts + if: env._IS_GITHUB_RELEASE == 'false' && success() + uses: actions/upload-artifact@v4.0.0 + with: + name: "${{ env._RELEASE_NAME }}-${{ env._RELEASE_VERSION }}" + path: ".dist/*.zip" + - name: VirusTotal Scan + id: vt-scan + if: env._IS_GITHUB_RELEASE == 'true' && success() + uses: crazy-max/ghaction-virustotal@v4 + with: + vt_api_key: ${{ secrets._VT_API_KEY }} + files: ".dist/*.zip" + - name: Parse VirusTotal Results + id: vt-res + if: env._IS_GITHUB_RELEASE == 'true' && success() + uses: actions/github-script@v7 + with: + result-encoding: string + script: | + let ret = `${{ steps.vt-scan.outputs.analysis }}`; + + ret = '- ' + ret + .replaceAll('.dist/','') + .replaceAll('=h', ': h') + .replaceAll(',', "\n- "); + + console.log('Results:'); + console.log(ret); + + return ret; + - name: Publish Canary release + uses: ncipollo/release-action@v1 + if: env._IS_GITHUB_RELEASE == 'true' && env._IS_BUILD_CANARY == 'true' && success() + with: + artifacts: ".dist/*.zip" + allowUpdates: true + generateReleaseNotes: true + prerelease: true + removeArtifacts: true + tag: canary + name: "${{ env._RELEASE_NAME }}-${{ env._RELEASE_VERSION }}" + body: | + See https://github.com/julianxhokaxhiu/CTNx/blob/master/Changelog.md#next + + This is a canary build. Please be aware it may be prone to crashing and is NOT tested by anyone. Use this build AT YOUR OWN RISK! + + 🛡️ **VirusTotal analysis:** + ${{ steps.vt-res.outputs.result }} + - name: Publish Stable release + uses: ncipollo/release-action@v1 + if: env._IS_GITHUB_RELEASE == 'true' && env._IS_BUILD_CANARY == 'false' && success() + with: + artifacts: ".dist/*.zip" + generateReleaseNotes: true + makeLatest: true + removeArtifacts: true + name: "${{ env._RELEASE_NAME }}-${{ env._RELEASE_VERSION }}" + body: | + See https://github.com/julianxhokaxhiu/CTNx/blob/master/Changelog.md#${{ env._CHANGELOG_VERSION }} + + 🛡️ **VirusTotal analysis:** + ${{ steps.vt-res.outputs.result }} + - name: Send alerts + if: env._IS_GITHUB_RELEASE == 'true' && success() + env: + _MAP_CTNx_TSUNAMODS_CT: "${{ secrets._CTNx_TSUNAMODS_CT }}" + _MAP_CTNx_QHIMM_CT: "${{ secrets._CTNx_QHIMM_CT }}" + run: ".github/workflows/alert.ps1" + shell: pwsh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2f7325e --- /dev/null +++ b/.gitignore @@ -0,0 +1,400 @@ +## C++ Ignore file + +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*[.json, .xml, .info] + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +## Custom section + +# Build directory +.build + +# Clion +cmake-build*/ + +# vcpkg +!make.exe +vcpkg_installed/ diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..6a41f9a --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,10 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ +# we don't use this file for this project. +/deployment.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..ab8afec --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +SUPERBUILD \ No newline at end of file diff --git a/.idea/CTNx.iml b/.idea/CTNx.iml new file mode 100644 index 0000000..f08604b --- /dev/null +++ b/.idea/CTNx.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..79b3c94 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..d963afe --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.logo/logo_nobg.png b/.logo/logo_nobg.png new file mode 100644 index 0000000..cd29b77 Binary files /dev/null and b/.logo/logo_nobg.png differ diff --git a/.logo/logo_whitebg.png b/.logo/logo_whitebg.png new file mode 100644 index 0000000..cd29b77 Binary files /dev/null and b/.logo/logo_whitebg.png differ diff --git a/.vcpkg/ports/bgfx/FindBGFX.cmake.in b/.vcpkg/ports/bgfx/FindBGFX.cmake.in new file mode 100644 index 0000000..915543b --- /dev/null +++ b/.vcpkg/ports/bgfx/FindBGFX.cmake.in @@ -0,0 +1,119 @@ +# Distributed under the OSI-approved BSD 3-Clause License. +# +#.rst: +# FindBGFX +# -------- +# +# Find the BGFX libraries +# +# Result Variables +# ^^^^^^^^^^^^^^^^ +# +# The following variables will be defined: +# +# ``BGFX_FOUND`` +# True if BGFX found on the local system +# +# ``BGFX_INCLUDE_DIRS`` +# Location of BGFX header files +# +# ``BGFX_LIBRARY_DIRS`` +# Location of BGFX libraries +# +# ``BGFX_LIBRARIES`` +# List of the BGFX libraries found +# +# + +include(FindPackageHandleStandardArgs) +include(SelectLibraryConfigurations) +include(CMakeFindDependencyMacro) + +if(NOT BGFX_FOUND) + +# Compute the installation path relative to this file. +get_filename_component(SEARCH_PATH "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(SEARCH_PATH "${SEARCH_PATH}" PATH) +get_filename_component(SEARCH_PATH "${SEARCH_PATH}" PATH) +if(SEARCH_PATH STREQUAL "/") + set(SEARCH_PATH "") +endif() + +set(BGFX_VERSION "@BGFX_VERSION@") + +function(append_dependencies out) + cmake_parse_arguments(PARSE_ARGV 1 "arg" "DEBUG" "NAMES" "") + if(${arg_DEBUG}) + set(config DEBUG) + set(path "${CURRENT_INSTALLED_DIR}/debug/lib/") + else() + set(config RELEASE) + set(path "${CURRENT_INSTALLED_DIR}/lib/") + endif() + foreach(lib_name ${arg_NAMES}) + if("${lib_name}" STREQUAL "-pthread") + list(APPEND ${out} "-pthread") + elseif("${lib_name}" STREQUAL "-pthreads") + list(APPEND ${out} "-pthreads") + elseif("${lib_name}" STREQUAL "gcc") + list(APPEND ${out} "-lgcc") + elseif("${lib_name}" STREQUAL "gcc_s") + list(APPEND ${out} "-lgcc_s") + elseif("${lib_name}" STREQUAL "stdc++") + list(APPEND ${out} "-lstdc++") + else() + # first look in ${path} specifically to ensure we find the right release/debug variant + find_library(BGFX_DEPENDENCY_${lib_name}_${config} NAMES "${lib_name}" PATHS "${path}" NO_DEFAULT_PATH) + # if not found there, must be a system dependency, so look elsewhere + find_library(BGFX_DEPENDENCY_${lib_name}_${config} NAMES "${lib_name}" REQUIRED) + list(APPEND ${out} "${BGFX_DEPENDENCY_${lib_name}_${config}}") + endif() + endforeach() + set("${out}" "${${out}}" PARENT_SCOPE) +endfunction() + +macro(BGFX_FIND libname shortname headername) + if(NOT BGFX_${libname}_INCLUDE_DIRS) + find_path(BGFX_${libname}_INCLUDE_DIRS NAMES ${headername} PATHS ${SEARCH_PATH}/include NO_DEFAULT_PATH) + endif() + if(NOT BGFX_${libname}_LIBRARY) + find_library(BGFX_${libname}_LIBRARY_RELEASE NAMES ${shortname}Release PATHS ${SEARCH_PATH}/lib/ NO_DEFAULT_PATH) + find_library(BGFX_${libname}_LIBRARY_DEBUG NAMES ${shortname}Debug PATHS ${SEARCH_PATH}/debug/lib/ NO_DEFAULT_PATH) + get_filename_component(BGFX_${libname}_LIBRARY_RELEASE_DIR ${BGFX_${libname}_LIBRARY_RELEASE} DIRECTORY) + get_filename_component(BGFX_${libname}_LIBRARY_DEBUG_DIR ${BGFX_${libname}_LIBRARY_DEBUG} DIRECTORY) + select_library_configurations(BGFX_${libname}) + set(BGFX_${libname}_LIBRARY ${BGFX_${libname}_LIBRARY} CACHE STRING "") + endif() + if (BGFX_${libname}_LIBRARY AND BGFX_${libname}_INCLUDE_DIRS) + set(BGFX_${libname}_FOUND TRUE BOOL) + list(APPEND BGFX_INCLUDE_DIRS ${BGFX_${libname}_INCLUDE_DIRS}) + list(APPEND BGFX_LIBRARIES ${BGFX_${libname}_LIBRARY}) + list(APPEND BGFX_LIBRARY_DIRS ${BGFX_${libname}_LIBRARY_RELEASE_DIR} ${BGFX_${libname}_LIBRARY_DEBUG_DIR}) + endif() +endmacro(BGFX_FIND) + +BGFX_FIND(bgfx bgfx bgfx/bgfx.h) + +if (BGFX_bgfx_FOUND) + list(REMOVE_DUPLICATES BGFX_INCLUDE_DIRS) + list(REMOVE_DUPLICATES BGFX_LIBRARY_DIRS) + set(BGFX_bgfx_VERSION "@BGFX_VERSION@" CACHE STRING "") + + append_dependencies(BGFX_DEPS_LIBRARY_RELEASE NAMES "@BGFX_DEPENDENCIES_RELEASE@") + append_dependencies(BGFX_DEPS_LIBRARY_DEBUG NAMES "@BGFX_DEPENDENCIES_DEBUG@" DEBUG) + if(BGFX_DEPS_LIBRARY_RELEASE OR BGFX_DEPS_LIBRARY_DEBUG) + select_library_configurations(BGFX_DEPS) + list(APPEND BGFX_LIBRARIES ${BGFX_DEPS_LIBRARY}) + endif() + + set(BGFX_LIBRARY ${BGFX_LIBRARIES}) + + set(BGFX_FOUND TRUE CACHE BOOL "") + set(BGFX_LIBRARIES ${BGFX_LIBRARIES} CACHE STRING "") + set(BGFX_INCLUDE_DIRS ${BGFX_INCLUDE_DIRS} CACHE STRING "") + set(BGFX_LIBRARY_DIRS ${BGFX_LIBRARY_DIRS} CACHE STRING "") +endif() + +find_package_handle_standard_args(BGFX REQUIRED_VARS BGFX_LIBRARIES BGFX_LIBRARY_DIRS BGFX_INCLUDE_DIRS) + +endif() diff --git a/.vcpkg/ports/bgfx/portfile.cmake b/.vcpkg/ports/bgfx/portfile.cmake new file mode 100644 index 0000000..3e43595 --- /dev/null +++ b/.vcpkg/ports/bgfx/portfile.cmake @@ -0,0 +1,161 @@ +# For a list of common variables see https://github.com/microsoft/vcpkg/blob/master/docs/maintainers/vcpkg_common_definitions.md + +# Download source packages +# (bgfx requires bx and bimg source for building) + +vcpkg_from_github(OUT_SOURCE_PATH BX_SOURCE_DIR + REPO "julianxhokaxhiu/bx" + HEAD_REF master + REF ba882e5864c94dcacf6ba623b8e71249a88448c6 + SHA512 1d23a85520dcb1676799623d71a591a093d197f159791a544b6a8571c7fed1a1735545a5aab7679437daa4fa6d51ccdae59f3ea1cf8471296a0eebb93de5953e +) + +vcpkg_from_github(OUT_SOURCE_PATH BIMG_SOURCE_DIR + REPO "julianxhokaxhiu/bimg" + HEAD_REF master + REF aaf9125234e657393f504404a279289669d89fcb + SHA512 f7437227b84b3bcdc603d7ebe0831091a273061b7cd85b8b68c1ca4f94d6e5a9150e1386608e5d4a6304aad828b1f8439ac09316133a55d5545eeb3d24d3bc98 +) + +vcpkg_from_github(OUT_SOURCE_PATH SOURCE_DIR + REPO "julianxhokaxhiu/bgfx" + HEAD_REF master + REF 7c58f2aa1e4af85c69d818cb166bd8a4e39361a5 + SHA512 7887d21987d940be40fcce7508e81cde6b83f2316dfbfe4546c951bb014e9071b02199d87b7ec21f08f1888efb133ea1fe0adcc1e4ba91d6dac80fc90be184a5 +) + +# Move bx source inside bgfx source tree +set(BX_DIR ${SOURCE_DIR}/.bx) +file(RENAME ${BX_SOURCE_DIR} "${BX_DIR}") +set(ENV{BX_DIR} ${BX_DIR}) + +# Move bimg source inside bgfx source tree +set(BIMG_DIR ${SOURCE_DIR}/.bimg) +file(RENAME ${BIMG_SOURCE_DIR} "${BIMG_DIR}") +set(ENV{BIMG_DIR} ${BIMG_DIR}) + +# Set custom BGFX configuration +set(ENV{BGFX_CONFIG} "DEBUG=1:PREFER_DISCRETE_GPU=0:DYNAMIC_INDEX_BUFFER_SIZE=10485760:DYNAMIC_VERTEX_BUFFER_SIZE=31457280:MAX_RECT_CACHE=8192") + +# Set up GENie (custom project generator) +set(GENIE_OPTIONS --with-tools) + +if(VCPKG_CRT_LINKAGE STREQUAL dynamic) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --with-dynamic-runtime) +endif() +if(VCPKG_LIBRARY_LINKAGE STREQUAL "dynamic") + set(GENIE_OPTIONS ${GENIE_OPTIONS} --with-shared-lib) +endif() + +if(VCPKG_TARGET_ARCHITECTURE STREQUAL x86) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --platform=x32) +elseif(VCPKG_TARGET_ARCHITECTURE STREQUAL x64) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --platform=x64) +elseif(VCPKG_TARGET_ARCHITECTURE STREQUAL arm OR VCPKG_TARGET_ARCHITECTURE STREQUAL arm64) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --platform=ARM) +else() + message(WARNING "Architecture may be not supported: ${VCPKG_TARGET_ARCHITECTURE}") + set(GENIE_OPTIONS ${GENIE_OPTIONS} --platform=${VCPKG_TARGET_ARCHITECTURE}) +endif() + +if(TARGET_TRIPLET MATCHES osx) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --os=macosx) +elseif(TARGET_TRIPLET MATCHES linux) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --os=linux) +elseif(TARGET_TRIPLET MATCHES windows) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --os=windows) +elseif(TARGET_TRIPLET MATCHES uwp) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --vs=winstore100) +endif() + +# GENie does not allow cmake+msvc, so we use msbuild in windows +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + if(VCPKG_PLATFORM_TOOLSET STREQUAL "v140") + set(GENIE_ACTION vs2015) + elseif(VCPKG_PLATFORM_TOOLSET STREQUAL "v141") + set(GENIE_ACTION vs2017) + elseif(VCPKG_PLATFORM_TOOLSET STREQUAL "v142") + set(GENIE_ACTION vs2019) + elseif(VCPKG_PLATFORM_TOOLSET STREQUAL "v143") + set(GENIE_ACTION vs2022) + else() + message(FATAL_ERROR "Unsupported Visual Studio toolset: ${VCPKG_PLATFORM_TOOLSET}") + endif() + set(PROJ_FOLDER ${GENIE_ACTION}) + if(TARGET_TRIPLET MATCHES uwp) + set(PROJ_FOLDER ${PROJ_FOLDER}-winstore100) + endif() +else() + set(GENIE_ACTION cmake) + set(PROJ_FOLDER ${GENIE_ACTION}) +endif() + +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + set(GENIE "${BX_DIR}/tools/bin/windows/genie.exe") +elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") + set(GENIE "${BX_DIR}/tools/bin/darwin/genie") +elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") + set(GENIE "${BX_DIR}/tools/bin/linux/genie") +else() + message(FATAL_ERROR "Unsupported host platform: ${CMAKE_HOST_SYSTEM_NAME}") +endif() + +# Run GENie + +vcpkg_execute_required_process( + COMMAND ${GENIE} ${GENIE_OPTIONS} ${GENIE_ACTION} + WORKING_DIRECTORY "${SOURCE_DIR}" + LOGNAME "genie-${TARGET_TRIPLET}" +) + +if(GENIE_ACTION STREQUAL cmake) + if(VCPKG_LIBRARY_LINKAGE STREQUAL "dynamic") + set(PROJ bgfx-shared-lib) + else() + set(PROJ bgfx) + endif() + vcpkg_configure_cmake( + SOURCE_PATH "${SOURCE_DIR}/.build/projects/${PROJ_FOLDER}" + PREFER_NINJA + OPTIONS_RELEASE -DCMAKE_BUILD_TYPE=Release + OPTIONS_DEBUG -DCMAKE_BUILD_TYPE=Debug + ) + vcpkg_install_cmake(TARGET ${PROJ}/all) + file(INSTALL "${SOURCE_DIR}/include/bgfx" DESTINATION "${CURRENT_PACKAGES_DIR}/include") + file(GLOB instfiles + "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-rel/${PROJ}/*.a" + "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-rel/${PROJ}/*.so" + ) + file(INSTALL ${instfiles} DESTINATION "${CURRENT_PACKAGES_DIR}/lib") + file(GLOB instfiles + "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-dbg/${PROJ}/*.a" + "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-dbg/${PROJ}/*.so" + ) + file(INSTALL ${instfiles} DESTINATION "${CURRENT_PACKAGES_DIR}/debug/lib") + file(INSTALL "${SOURCE_DIR}/LICENSE" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME "copyright") +else() + vcpkg_install_msbuild( + SOURCE_PATH "${SOURCE_DIR}" + PROJECT_SUBPATH ".build/projects/${PROJ_FOLDER}/bgfx.sln" + LICENSE_SUBPATH "LICENSE" + INCLUDES_SUBPATH "include" + ) + # Install shader include file + file(INSTALL "${SOURCE_DIR}/src/bgfx_shader.sh" DESTINATION "${CURRENT_PACKAGES_DIR}/include/bgfx" ) + # Remove redundant files + foreach(a bx bimg bimg_decode bimg_encode) + foreach(b Debug Release) + foreach(c lib pdb) + if(b STREQUAL Debug) + file(REMOVE "${CURRENT_PACKAGES_DIR}/debug/lib/${a}${b}.${c}") + else() + file(REMOVE "${CURRENT_PACKAGES_DIR}/lib/${a}${b}.${c}") + endif() + endforeach() + endforeach() + endforeach() +endif() + +file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}") +configure_file(${CMAKE_CURRENT_LIST_DIR}/FindBGFX.cmake.in ${CURRENT_PACKAGES_DIR}/share/${PORT}/FindBGFX.cmake @ONLY) +file(COPY ${CMAKE_CURRENT_LIST_DIR}/vcpkg-cmake-wrapper.cmake DESTINATION ${CURRENT_PACKAGES_DIR}/share/${PORT}) diff --git a/.vcpkg/ports/bgfx/usage b/.vcpkg/ports/bgfx/usage new file mode 100644 index 0000000..f26c831 --- /dev/null +++ b/.vcpkg/ports/bgfx/usage @@ -0,0 +1,6 @@ +To use bgfx add the following to your CMake project: + + find_package(BGFX REQUIRED) + target_include_directories(main PRIVATE ${BGFX_INCLUDE_DIRS}) + target_link_directories(main PRIVATE ${BGFX_LIBRARY_DIRS}) + target_link_libraries(main PRIVATE ${BGFX_LIBRARIES}) diff --git a/.vcpkg/ports/bgfx/vcpkg-cmake-wrapper.cmake b/.vcpkg/ports/bgfx/vcpkg-cmake-wrapper.cmake new file mode 100644 index 0000000..f57692d --- /dev/null +++ b/.vcpkg/ports/bgfx/vcpkg-cmake-wrapper.cmake @@ -0,0 +1,8 @@ +set(BGFX_PREV_MODULE_PATH ${CMAKE_MODULE_PATH}) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) + +cmake_policy(SET CMP0012 NEW) + +_find_package(${ARGS}) + +set(CMAKE_MODULE_PATH ${BGFX_PREV_MODULE_PATH}) diff --git a/.vcpkg/ports/bgfx/vcpkg.json b/.vcpkg/ports/bgfx/vcpkg.json new file mode 100644 index 0000000..6e4a5c9 --- /dev/null +++ b/.vcpkg/ports/bgfx/vcpkg.json @@ -0,0 +1,10 @@ +{ + "name": "bgfx", + "version": "1.0.0", + "description": "Cross-platform, graphics API agnostic, Bring Your Own Engine/Framework style rendering library.", + "homepage": "https://github.com/bkaradzic/bgfx", + "dependencies": [ + "bx", + "bimg" + ] +} \ No newline at end of file diff --git a/.vcpkg/ports/bimg/FindBIMG.cmake.in b/.vcpkg/ports/bimg/FindBIMG.cmake.in new file mode 100644 index 0000000..e4e988f --- /dev/null +++ b/.vcpkg/ports/bimg/FindBIMG.cmake.in @@ -0,0 +1,121 @@ +# Distributed under the OSI-approved BSD 3-Clause License. +# +#.rst: +# FindBIMG +# -------- +# +# Find the BIMG libraries +# +# Result Variables +# ^^^^^^^^^^^^^^^^ +# +# The following variables will be defined: +# +# ``BIMG_FOUND`` +# True if BIMG found on the local system +# +# ``BIMG_INCLUDE_DIRS`` +# Location of BIMG header files +# +# ``BIMG_LIBRARY_DIRS`` +# Location of BIMG libraries +# +# ``BIMG_LIBRARIES`` +# List of the BIMG libraries found +# +# + +include(FindPackageHandleStandardArgs) +include(SelectLibraryConfigurations) +include(CMakeFindDependencyMacro) + +if(NOT BIMG_FOUND) + +# Compute the installation path relative to this file. +get_filename_component(SEARCH_PATH "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(SEARCH_PATH "${SEARCH_PATH}" PATH) +get_filename_component(SEARCH_PATH "${SEARCH_PATH}" PATH) +if(SEARCH_PATH STREQUAL "/") + set(SEARCH_PATH "") +endif() + +set(BIMG_VERSION "@BIMG_VERSION@") + +function(append_dependencies out) + cmake_parse_arguments(PARSE_ARGV 1 "arg" "DEBUG" "NAMES" "") + if(${arg_DEBUG}) + set(config DEBUG) + set(path "${CURRENT_INSTALLED_DIR}/debug/lib/") + else() + set(config RELEASE) + set(path "${CURRENT_INSTALLED_DIR}/lib/") + endif() + foreach(lib_name ${arg_NAMES}) + if("${lib_name}" STREQUAL "-pthread") + list(APPEND ${out} "-pthread") + elseif("${lib_name}" STREQUAL "-pthreads") + list(APPEND ${out} "-pthreads") + elseif("${lib_name}" STREQUAL "gcc") + list(APPEND ${out} "-lgcc") + elseif("${lib_name}" STREQUAL "gcc_s") + list(APPEND ${out} "-lgcc_s") + elseif("${lib_name}" STREQUAL "stdc++") + list(APPEND ${out} "-lstdc++") + else() + # first look in ${path} specifically to ensure we find the right release/debug variant + find_library(BIMG_DEPENDENCY_${lib_name}_${config} NAMES "${lib_name}" PATHS "${path}" NO_DEFAULT_PATH) + # if not found there, must be a system dependency, so look elsewhere + find_library(BIMG_DEPENDENCY_${lib_name}_${config} NAMES "${lib_name}" REQUIRED) + list(APPEND ${out} "${BIMG_DEPENDENCY_${lib_name}_${config}}") + endif() + endforeach() + set("${out}" "${${out}}" PARENT_SCOPE) +endfunction() + +macro(BIMG_FIND libname shortname headername) + if(NOT BIMG_${libname}_INCLUDE_DIRS) + find_path(BIMG_${libname}_INCLUDE_DIRS NAMES ${headername} PATHS ${SEARCH_PATH}/include NO_DEFAULT_PATH) + endif() + if(NOT BIMG_${libname}_LIBRARY) + find_library(BIMG_${libname}_LIBRARY_RELEASE NAMES ${shortname}Release PATHS ${SEARCH_PATH}/lib/ NO_DEFAULT_PATH) + find_library(BIMG_${libname}_LIBRARY_DEBUG NAMES ${shortname}Debug PATHS ${SEARCH_PATH}/debug/lib/ NO_DEFAULT_PATH) + get_filename_component(BIMG_${libname}_LIBRARY_RELEASE_DIR ${BIMG_${libname}_LIBRARY_RELEASE} DIRECTORY) + get_filename_component(BIMG_${libname}_LIBRARY_DEBUG_DIR ${BIMG_${libname}_LIBRARY_DEBUG} DIRECTORY) + select_library_configurations(BIMG_${libname}) + set(BIMG_${libname}_LIBRARY ${BIMG_${libname}_LIBRARY} CACHE STRING "") + endif() + if (BIMG_${libname}_LIBRARY AND BIMG_${libname}_INCLUDE_DIRS) + set(BIMG_${libname}_FOUND TRUE BOOL) + list(APPEND BIMG_INCLUDE_DIRS ${BIMG_${libname}_INCLUDE_DIRS}) + list(APPEND BIMG_LIBRARIES ${BIMG_${libname}_LIBRARY}) + list(APPEND BIMG_LIBRARY_DIRS ${BIMG_${libname}_LIBRARY_RELEASE_DIR} ${BIMG_${libname}_LIBRARY_DEBUG_DIR}) + endif() +endmacro(BIMG_FIND) + +BIMG_FIND(bimg bimg bimg/bimg.h) +BIMG_FIND(bimg_decode bimg_decode bimg/decode.h) +BIMG_FIND(bimg_encode bimg_encode bimg/encode.h) + +if (BIMG_bimg_FOUND) + list(REMOVE_DUPLICATES BIMG_INCLUDE_DIRS) + list(REMOVE_DUPLICATES BIMG_LIBRARY_DIRS) + set(BIMG_bimg_VERSION "@BIMG_VERSION@" CACHE STRING "") + + append_dependencies(BIMG_DEPS_LIBRARY_RELEASE NAMES "@BIMG_DEPENDENCIES_RELEASE@") + append_dependencies(BIMG_DEPS_LIBRARY_DEBUG NAMES "@BIMG_DEPENDENCIES_DEBUG@" DEBUG) + if(BIMG_DEPS_LIBRARY_RELEASE OR BIMG_DEPS_LIBRARY_DEBUG) + select_library_configurations(BIMG_DEPS) + list(APPEND BIMG_LIBRARIES ${BIMG_DEPS_LIBRARY}) + endif() + + set(BIMG_LIBRARY ${BIMG_LIBRARIES}) + + set(BIMG_FOUND TRUE CACHE BOOL "") + set(BIMG_LIBRARIES ${BIMG_LIBRARIES} CACHE STRING "") + set(BIMG_INCLUDE_DIRS ${BIMG_INCLUDE_DIRS} CACHE STRING "") + set(BIMG_LIBRARY_DIRS ${BIMG_LIBRARY_DIRS} CACHE STRING "") +endif() + +find_package_handle_standard_args(BIMG REQUIRED_VARS BIMG_LIBRARIES BIMG_LIBRARY_DIRS BIMG_INCLUDE_DIRS) + +endif() diff --git a/.vcpkg/ports/bimg/portfile.cmake b/.vcpkg/ports/bimg/portfile.cmake new file mode 100644 index 0000000..5f4cf9a --- /dev/null +++ b/.vcpkg/ports/bimg/portfile.cmake @@ -0,0 +1,153 @@ +# For a list of common variables see https://github.com/microsoft/vcpkg/blob/master/docs/maintainers/vcpkg_common_definitions.md + +# Download source packages +# (bimg requires bx source for building) + +vcpkg_from_github(OUT_SOURCE_PATH BX_SOURCE_DIR + REPO "julianxhokaxhiu/bx" + HEAD_REF master + REF ba882e5864c94dcacf6ba623b8e71249a88448c6 + SHA512 1d23a85520dcb1676799623d71a591a093d197f159791a544b6a8571c7fed1a1735545a5aab7679437daa4fa6d51ccdae59f3ea1cf8471296a0eebb93de5953e +) + +vcpkg_from_github(OUT_SOURCE_PATH SOURCE_DIR + REPO "julianxhokaxhiu/bimg" + HEAD_REF master + REF aaf9125234e657393f504404a279289669d89fcb + SHA512 f7437227b84b3bcdc603d7ebe0831091a273061b7cd85b8b68c1ca4f94d6e5a9150e1386608e5d4a6304aad828b1f8439ac09316133a55d5545eeb3d24d3bc98 +) + +# Move bx source inside bgfx source tree +set(BX_DIR ${SOURCE_DIR}/.bx) +file(RENAME ${BX_SOURCE_DIR} "${BX_DIR}") +set(ENV{BX_DIR} ${BX_DIR}) + +# Set up GENie (custom project generator) + +if(VCPKG_CRT_LINKAGE STREQUAL dynamic) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --with-dynamic-runtime) +endif() +if(VCPKG_LIBRARY_LINKAGE STREQUAL dynamic) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --with-shared-lib) +endif() + +if(VCPKG_TARGET_ARCHITECTURE STREQUAL x86) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --platform=x32) +elseif(VCPKG_TARGET_ARCHITECTURE STREQUAL x64) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --platform=x64) +elseif(VCPKG_TARGET_ARCHITECTURE STREQUAL arm OR VCPKG_TARGET_ARCHITECTURE STREQUAL arm64) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --platform=ARM) +else() + message(WARNING "Architecture may be not supported: ${VCPKG_TARGET_ARCHITECTURE}") + set(GENIE_OPTIONS ${GENIE_OPTIONS} --platform=${VCPKG_TARGET_ARCHITECTURE}) +endif() + +if(TARGET_TRIPLET MATCHES osx) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --os=macosx) +elseif(TARGET_TRIPLET MATCHES linux) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --os=linux) +elseif(TARGET_TRIPLET MATCHES windows) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --os=windows) +elseif(TARGET_TRIPLET MATCHES uwp) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --vs=winstore100) +endif() + +# GENie does not allow cmake+msvc, so we use msbuild in windows +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + if(VCPKG_PLATFORM_TOOLSET STREQUAL "v140") + set(GENIE_ACTION vs2015) + elseif(VCPKG_PLATFORM_TOOLSET STREQUAL "v141") + set(GENIE_ACTION vs2017) + elseif(VCPKG_PLATFORM_TOOLSET STREQUAL "v142") + set(GENIE_ACTION vs2019) + elseif(VCPKG_PLATFORM_TOOLSET STREQUAL "v143") + set(GENIE_ACTION vs2022) + else() + message(FATAL_ERROR "Unsupported Visual Studio toolset: ${VCPKG_PLATFORM_TOOLSET}") + endif() + set(PROJ_FOLDER ${GENIE_ACTION}) + if(TARGET_TRIPLET MATCHES uwp) + set(PROJ_FOLDER ${PROJ_FOLDER}-winstore100) + endif() +else() + set(GENIE_ACTION cmake) + set(PROJ_FOLDER ${GENIE_ACTION}) +endif() + +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + set(GENIE "${BX_DIR}/tools/bin/windows/genie.exe") +elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") + set(GENIE "${BX_DIR}/tools/bin/darwin/genie") +elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") + set(GENIE "${BX_DIR}/tools/bin/linux/genie") +else() + message(FATAL_ERROR "Unsupported host platform: ${CMAKE_HOST_SYSTEM_NAME}") +endif() + +# Run GENie + +vcpkg_execute_required_process( + COMMAND ${GENIE} ${GENIE_OPTIONS} ${GENIE_ACTION} + WORKING_DIRECTORY "${SOURCE_DIR}" + LOGNAME "genie-${TARGET_TRIPLET}" +) + +if(GENIE_ACTION STREQUAL cmake) + # Run CMake + vcpkg_configure_cmake( + SOURCE_PATH "${SOURCE_DIR}/.build/projects/${PROJ_FOLDER}" + PREFER_NINJA + OPTIONS_RELEASE -DCMAKE_BUILD_TYPE=Release + OPTIONS_DEBUG -DCMAKE_BUILD_TYPE=Debug + ) + vcpkg_install_cmake(TARGET bimg/all) + vcpkg_install_cmake(TARGET bimg_encode/all) + vcpkg_install_cmake(TARGET bimg_decode/all) + # GENie does not generate an install target, so we install explicitly + file(INSTALL "${SOURCE_DIR}/include/bimg" DESTINATION "${CURRENT_PACKAGES_DIR}/include") + file(GLOB instfiles + "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-rel/bimg/*.a" + "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-rel/bimg/*.so" + "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-rel/bimg_encode/*.a" + "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-rel/bimg_encode/*.so" + "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-rel/bimg_decode/*.a" + "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-rel/bimg_decode/*.so" + ) + file(INSTALL ${instfiles} DESTINATION "${CURRENT_PACKAGES_DIR}/lib") + file(GLOB instfiles + "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-dbg/bimg/*.a" + "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-dbg/bimg/*.so" + "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-dbg/bimg_encode/*.a" + "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-dbg/bimg_encode/*.so" + "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-dbg/bimg_decode/*.a" + "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-dbg/bimg_decode/*.so" + ) + file(INSTALL ${instfiles} DESTINATION "${CURRENT_PACKAGES_DIR}/debug/lib") + file(INSTALL "${SOURCE_DIR}/LICENSE" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright) +else() + # Run MSBuild for all 3 targets + foreach(PROJ bimg bimg_decode bimg_encode) + vcpkg_install_msbuild( + SOURCE_PATH "${SOURCE_DIR}" + PROJECT_SUBPATH ".build/projects/${PROJ_FOLDER}/${PROJ}.vcxproj" + LICENSE_SUBPATH "LICENSE" + INCLUDES_SUBPATH "include" + ) + endforeach() + # Remove redundant files + foreach(a bx) + foreach(b Debug Release) + foreach(c lib pdb) + if(b STREQUAL Debug) + file(REMOVE "${CURRENT_PACKAGES_DIR}/debug/lib/${a}${b}.${c}") + else() + file(REMOVE "${CURRENT_PACKAGES_DIR}/lib/${a}${b}.${c}") + endif() + endforeach() + endforeach() + endforeach() +endif() + +file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}") +configure_file(${CMAKE_CURRENT_LIST_DIR}/FindBIMG.cmake.in ${CURRENT_PACKAGES_DIR}/share/${PORT}/FindBIMG.cmake @ONLY) +file(COPY ${CMAKE_CURRENT_LIST_DIR}/vcpkg-cmake-wrapper.cmake DESTINATION ${CURRENT_PACKAGES_DIR}/share/${PORT}) diff --git a/.vcpkg/ports/bimg/usage b/.vcpkg/ports/bimg/usage new file mode 100644 index 0000000..d06d845 --- /dev/null +++ b/.vcpkg/ports/bimg/usage @@ -0,0 +1,6 @@ +To use bimg add the following to your CMake project: + + find_package(BIMG REQUIRED) + target_include_directories(main PRIVATE ${BIMG_INCLUDE_DIRS}) + target_link_directories(main PRIVATE ${BIMG_LIBRARY_DIRS}) + target_link_libraries(main PRIVATE ${BIMG_LIBRARIES}) diff --git a/.vcpkg/ports/bimg/vcpkg-cmake-wrapper.cmake b/.vcpkg/ports/bimg/vcpkg-cmake-wrapper.cmake new file mode 100644 index 0000000..0e0dff6 --- /dev/null +++ b/.vcpkg/ports/bimg/vcpkg-cmake-wrapper.cmake @@ -0,0 +1,8 @@ +set(BIMG_PREV_MODULE_PATH ${CMAKE_MODULE_PATH}) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) + +cmake_policy(SET CMP0012 NEW) + +_find_package(${ARGS}) + +set(CMAKE_MODULE_PATH ${BIMG_PREV_MODULE_PATH}) diff --git a/.vcpkg/ports/bimg/vcpkg.json b/.vcpkg/ports/bimg/vcpkg.json new file mode 100644 index 0000000..aea873e --- /dev/null +++ b/.vcpkg/ports/bimg/vcpkg.json @@ -0,0 +1,9 @@ +{ + "name": "bimg", + "version": "1.0.0", + "description": "Image library", + "homepage": "https://github.com/bkaradzic/bimg", + "dependencies": [ + "bx" + ] +} \ No newline at end of file diff --git a/.vcpkg/ports/bx/FindBX.cmake.in b/.vcpkg/ports/bx/FindBX.cmake.in new file mode 100644 index 0000000..111d5ba --- /dev/null +++ b/.vcpkg/ports/bx/FindBX.cmake.in @@ -0,0 +1,120 @@ +# Distributed under the OSI-approved BSD 3-Clause License. +# +#.rst: +# FindBX +# -------- +# +# Find the BX libraries +# +# Result Variables +# ^^^^^^^^^^^^^^^^ +# +# The following variables will be defined: +# +# ``BX_FOUND`` +# True if BX found on the local system +# +# ``BX_INCLUDE_DIRS`` +# Location of BX header files +# +# ``BX_LIBRARY_DIRS`` +# Location of BX libraries +# +# ``BX_LIBRARIES`` +# List of the BX libraries found +# +# + +include(FindPackageHandleStandardArgs) +include(SelectLibraryConfigurations) +include(CMakeFindDependencyMacro) + +if(NOT BX_FOUND) + +# Compute the installation path relative to this file. +get_filename_component(SEARCH_PATH "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(SEARCH_PATH "${SEARCH_PATH}" PATH) +get_filename_component(SEARCH_PATH "${SEARCH_PATH}" PATH) +if(SEARCH_PATH STREQUAL "/") + set(SEARCH_PATH "") +endif() + +set(BX_VERSION "@BX_VERSION@") + +function(append_dependencies out) + cmake_parse_arguments(PARSE_ARGV 1 "arg" "DEBUG" "NAMES" "") + if(${arg_DEBUG}) + set(config DEBUG) + set(path "${CURRENT_INSTALLED_DIR}/debug/lib/") + else() + set(config RELEASE) + set(path "${CURRENT_INSTALLED_DIR}/lib/") + endif() + foreach(lib_name ${arg_NAMES}) + if("${lib_name}" STREQUAL "-pthread") + list(APPEND ${out} "-pthread") + elseif("${lib_name}" STREQUAL "-pthreads") + list(APPEND ${out} "-pthreads") + elseif("${lib_name}" STREQUAL "gcc") + list(APPEND ${out} "-lgcc") + elseif("${lib_name}" STREQUAL "gcc_s") + list(APPEND ${out} "-lgcc_s") + elseif("${lib_name}" STREQUAL "stdc++") + list(APPEND ${out} "-lstdc++") + else() + # first look in ${path} specifically to ensure we find the right release/debug variant + find_library(BX_DEPENDENCY_${lib_name}_${config} NAMES "${lib_name}" PATHS "${path}" NO_DEFAULT_PATH) + # if not found there, must be a system dependency, so look elsewhere + find_library(BX_DEPENDENCY_${lib_name}_${config} NAMES "${lib_name}" REQUIRED) + list(APPEND ${out} "${BX_DEPENDENCY_${lib_name}_${config}}") + endif() + endforeach() + set("${out}" "${${out}}" PARENT_SCOPE) +endfunction() + +macro(BX_FIND libname shortname headername) + if(NOT BX_${libname}_INCLUDE_DIRS) + find_path(BX_${libname}_INCLUDE_DIRS NAMES ${headername} PATHS ${SEARCH_PATH}/include NO_DEFAULT_PATH) + endif() + if(NOT BX_${libname}_LIBRARY) + find_library(BX_${libname}_LIBRARY_RELEASE NAMES ${shortname}Release PATHS ${SEARCH_PATH}/lib/ NO_DEFAULT_PATH) + find_library(BX_${libname}_LIBRARY_DEBUG NAMES ${shortname}Debug PATHS ${SEARCH_PATH}/debug/lib/ NO_DEFAULT_PATH) + get_filename_component(BX_${libname}_LIBRARY_RELEASE_DIR ${BX_${libname}_LIBRARY_RELEASE} DIRECTORY) + get_filename_component(BX_${libname}_LIBRARY_DEBUG_DIR ${BX_${libname}_LIBRARY_DEBUG} DIRECTORY) + select_library_configurations(BX_${libname}) + set(BX_${libname}_LIBRARY ${BX_${libname}_LIBRARY} CACHE STRING "") + endif() + if (BX_${libname}_LIBRARY AND BX_${libname}_INCLUDE_DIRS) + set(BX_${libname}_FOUND TRUE BOOL) + list(APPEND BX_INCLUDE_DIRS ${BX_${libname}_INCLUDE_DIRS}) + list(APPEND BX_LIBRARIES ${BX_${libname}_LIBRARY}) + list(APPEND BX_LIBRARY_DIRS ${BX_${libname}_LIBRARY_RELEASE_DIR} ${BX_${libname}_LIBRARY_DEBUG_DIR}) + endif() +endmacro(BX_FIND) + +BX_FIND(bx bx bx/bx.h) + +if (BX_bx_FOUND) + list(APPEND BX_INCLUDE_DIRS "${SEARCH_PATH}/include/compat/msvc") + list(REMOVE_DUPLICATES BX_INCLUDE_DIRS) + list(REMOVE_DUPLICATES BX_LIBRARY_DIRS) + set(BX_bx_VERSION "@BX_VERSION@" CACHE STRING "") + + append_dependencies(BX_DEPS_LIBRARY_RELEASE NAMES "@BX_DEPENDENCIES_RELEASE@") + append_dependencies(BX_DEPS_LIBRARY_DEBUG NAMES "@BX_DEPENDENCIES_DEBUG@" DEBUG) + if(BX_DEPS_LIBRARY_RELEASE OR BX_DEPS_LIBRARY_DEBUG) + select_library_configurations(BX_DEPS) + list(APPEND BX_LIBRARIES ${BX_DEPS_LIBRARY}) + endif() + + set(BX_LIBRARY ${BX_LIBRARIES}) + + set(BX_FOUND TRUE CACHE BOOL "") + set(BX_LIBRARIES ${BX_LIBRARIES} CACHE STRING "") + set(BX_INCLUDE_DIRS ${BX_INCLUDE_DIRS} CACHE STRING "") + set(BX_LIBRARY_DIRS ${BX_LIBRARY_DIRS} CACHE STRING "") +endif() + +find_package_handle_standard_args(BX REQUIRED_VARS BX_LIBRARIES BX_LIBRARY_DIRS BX_INCLUDE_DIRS) + +endif() diff --git a/.vcpkg/ports/bx/portfile.cmake b/.vcpkg/ports/bx/portfile.cmake new file mode 100644 index 0000000..1f2bd0a --- /dev/null +++ b/.vcpkg/ports/bx/portfile.cmake @@ -0,0 +1,117 @@ +# For a list of common variables see https://github.com/microsoft/vcpkg/blob/master/docs/maintainers/vcpkg_common_definitions.md + +vcpkg_check_linkage(ONLY_STATIC_LIBRARY) + +# Download source + +vcpkg_from_github(OUT_SOURCE_PATH SOURCE_DIR + REPO "julianxhokaxhiu/bx" + HEAD_REF master + REF ba882e5864c94dcacf6ba623b8e71249a88448c6 + SHA512 1d23a85520dcb1676799623d71a591a093d197f159791a544b6a8571c7fed1a1735545a5aab7679437daa4fa6d51ccdae59f3ea1cf8471296a0eebb93de5953e +) + +# Set up GENie (custom project generator) + +if(VCPKG_CRT_LINKAGE STREQUAL dynamic) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --with-dynamic-runtime) +endif() + +if(VCPKG_TARGET_ARCHITECTURE STREQUAL x86) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --platform=x32) +elseif(VCPKG_TARGET_ARCHITECTURE STREQUAL x64) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --platform=x64) +elseif(VCPKG_TARGET_ARCHITECTURE STREQUAL arm OR VCPKG_TARGET_ARCHITECTURE STREQUAL arm64) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --platform=ARM) +else() + message(WARNING "Architecture may be not supported: ${VCPKG_TARGET_ARCHITECTURE}") + set(GENIE_OPTIONS ${GENIE_OPTIONS} --platform=${VCPKG_TARGET_ARCHITECTURE}) +endif() + +if(TARGET_TRIPLET MATCHES osx) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --os=macosx) +elseif(TARGET_TRIPLET MATCHES linux) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --os=linux) +elseif(TARGET_TRIPLET MATCHES windows) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --os=windows) +elseif(TARGET_TRIPLET MATCHES uwp) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --vs=winstore100) +endif() + +# GENie does not allow cmake+msvc, so we use msbuild in windows +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + if(VCPKG_PLATFORM_TOOLSET STREQUAL "v140") + set(GENIE_ACTION vs2015) + elseif(VCPKG_PLATFORM_TOOLSET STREQUAL "v141") + set(GENIE_ACTION vs2017) + elseif(VCPKG_PLATFORM_TOOLSET STREQUAL "v142") + set(GENIE_ACTION vs2019) + elseif(VCPKG_PLATFORM_TOOLSET STREQUAL "v143") + set(GENIE_ACTION vs2022) + else() + message(FATAL_ERROR "Unsupported Visual Studio toolset: ${VCPKG_PLATFORM_TOOLSET}") + endif() + set(PROJ_FOLDER ${GENIE_ACTION}) + if(TARGET_TRIPLET MATCHES uwp) + set(PROJ_FOLDER ${PROJ_FOLDER}-winstore100) + endif() +else() + set(GENIE_ACTION cmake) + set(PROJ_FOLDER ${GENIE_ACTION}) +endif() + +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + set(GENIE "${SOURCE_DIR}/tools/bin/windows/genie.exe") +elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") + set(GENIE "${SOURCE_DIR}/tools/bin/darwin/genie") +elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") + set(GENIE "${SOURCE_DIR}/tools/bin/linux/genie") +else() + message(FATAL_ERROR "Unsupported host platform: ${CMAKE_HOST_SYSTEM_NAME}") +endif() + +# Run GENie + +vcpkg_execute_required_process( + COMMAND ${GENIE} ${GENIE_OPTIONS} ${GENIE_ACTION} + WORKING_DIRECTORY "${SOURCE_DIR}" + LOGNAME "genie-${TARGET_TRIPLET}" +) + +if(GENIE_ACTION STREQUAL cmake) + # Run CMake + vcpkg_configure_cmake( + SOURCE_PATH "${SOURCE_DIR}/.build/projects/${PROJ_FOLDER}" + PREFER_NINJA + OPTIONS_RELEASE -DCMAKE_BUILD_TYPE=Release + OPTIONS_DEBUG -DCMAKE_BUILD_TYPE=Debug + ) + vcpkg_install_cmake(TARGET bx/all) + # GENie does not generate an install target, so we install explicitly + file(INSTALL + "${SOURCE_DIR}/include/bx" + "${SOURCE_DIR}/include/compat" + "${SOURCE_DIR}/include/tinystl" + DESTINATION "${CURRENT_PACKAGES_DIR}/include") + file(GLOB instfiles + "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-rel/bx/*.a" + ) + file(INSTALL ${instfiles} DESTINATION "${CURRENT_PACKAGES_DIR}/lib") + file(GLOB instfiles + "${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-dbg/bx/*.a" + ) + file(INSTALL ${instfiles} DESTINATION "${CURRENT_PACKAGES_DIR}/debug/lib") + file(INSTALL "${SOURCE_DIR}/LICENSE" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright) +else() + # Run MSBuild + vcpkg_install_msbuild( + SOURCE_PATH "${SOURCE_DIR}" + PROJECT_SUBPATH ".build/projects/${PROJ_FOLDER}/bx.vcxproj" + LICENSE_SUBPATH "LICENSE" + INCLUDES_SUBPATH "include" + ) +endif() + +file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}") +configure_file(${CMAKE_CURRENT_LIST_DIR}/FindBX.cmake.in ${CURRENT_PACKAGES_DIR}/share/${PORT}/FindBX.cmake @ONLY) +file(COPY ${CMAKE_CURRENT_LIST_DIR}/vcpkg-cmake-wrapper.cmake DESTINATION ${CURRENT_PACKAGES_DIR}/share/${PORT}) diff --git a/.vcpkg/ports/bx/usage b/.vcpkg/ports/bx/usage new file mode 100644 index 0000000..1d30018 --- /dev/null +++ b/.vcpkg/ports/bx/usage @@ -0,0 +1,6 @@ +To use bx add the following to your CMake project: + + find_package(BX REQUIRED) + target_include_directories(main PRIVATE ${BX_INCLUDE_DIRS}) + target_link_directories(main PRIVATE ${BX_LIBRARY_DIRS}) + target_link_libraries(main PRIVATE ${BX_LIBRARIES}) diff --git a/.vcpkg/ports/bx/vcpkg-cmake-wrapper.cmake b/.vcpkg/ports/bx/vcpkg-cmake-wrapper.cmake new file mode 100644 index 0000000..e6dca77 --- /dev/null +++ b/.vcpkg/ports/bx/vcpkg-cmake-wrapper.cmake @@ -0,0 +1,8 @@ +set(BX_PREV_MODULE_PATH ${CMAKE_MODULE_PATH}) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) + +cmake_policy(SET CMP0012 NEW) + +_find_package(${ARGS}) + +set(CMAKE_MODULE_PATH ${BX_PREV_MODULE_PATH}) diff --git a/.vcpkg/ports/bx/vcpkg.json b/.vcpkg/ports/bx/vcpkg.json new file mode 100644 index 0000000..2e0838d --- /dev/null +++ b/.vcpkg/ports/bx/vcpkg.json @@ -0,0 +1,6 @@ +{ + "name": "bx", + "version": "1.0.0", + "description": "Base library used across multiple projects", + "homepage": "https://github.com/bkaradzic/bx" +} \ No newline at end of file diff --git a/.vcpkg/ports/hwinfo/hwinfoConfig.cmake.in b/.vcpkg/ports/hwinfo/hwinfoConfig.cmake.in new file mode 100644 index 0000000..20e07be --- /dev/null +++ b/.vcpkg/ports/hwinfo/hwinfoConfig.cmake.in @@ -0,0 +1,32 @@ +include(FindPackageHandleStandardArgs) + +if (NOT HWINFO_FOUND) + find_library( + HWINFO_LIBRARY + hwinfo + PATH_SUFFIXES + lib + vendor/lib + ) + + find_path( + HWINFO_INCLUDE_DIR + hwinfo + PATH_SUFFIXES + include + vendor/include + ) + + add_library(HWINFO::HWINFO STATIC IMPORTED) + + set_target_properties( + HWINFO::HWINFO + PROPERTIES + IMPORTED_LOCATION + "${HWINFO_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES + "${HWINFO_INCLUDE_DIR}" + ) + + find_package_handle_standard_args(HWINFO DEFAULT_MSG HWINFO_LIBRARY HWINFO_INCLUDE_DIR) +endif() \ No newline at end of file diff --git a/.vcpkg/ports/hwinfo/portfile.cmake b/.vcpkg/ports/hwinfo/portfile.cmake new file mode 100644 index 0000000..1679aad --- /dev/null +++ b/.vcpkg/ports/hwinfo/portfile.cmake @@ -0,0 +1,25 @@ +vcpkg_check_linkage(ONLY_STATIC_LIBRARY) + +vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_PATH + REPO lfreist/hwinfo + REF 3d234f4799f9eb7651f9853bd3fd17456b191a58 + SHA512 f109449ffb678810383ee5f39d6ba098b96779ace538f0301833c5b2f168a119ca325a47df2353a783b1cdb47e0c282b18bb578587dd79568e7defe115b27350 +) + +vcpkg_cmake_configure( + SOURCE_PATH "${SOURCE_PATH}" + OPTIONS + -DNO_OCL=TRUE # disable OpenCL usage + MAYBE_UNUSED_VARIABLES + NO_OCL +) +vcpkg_cmake_install() + +file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include") +file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}") + +vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE") + +# Copy cmake configuration files +configure_file(${CMAKE_CURRENT_LIST_DIR}/hwinfoConfig.cmake.in ${CURRENT_PACKAGES_DIR}/share/${PORT}/hwinfoConfig.cmake @ONLY) diff --git a/.vcpkg/ports/hwinfo/usage b/.vcpkg/ports/hwinfo/usage new file mode 100644 index 0000000..f1c6a32 --- /dev/null +++ b/.vcpkg/ports/hwinfo/usage @@ -0,0 +1,4 @@ +To use HWINFO add the following to your CMake project: + + find_package(HWINFO REQUIRED) + target_link_libraries(main PRIVATE HWINFO::HWINFO) diff --git a/.vcpkg/ports/hwinfo/vcpkg.json b/.vcpkg/ports/hwinfo/vcpkg.json new file mode 100644 index 0000000..38336fc --- /dev/null +++ b/.vcpkg/ports/hwinfo/vcpkg.json @@ -0,0 +1,18 @@ +{ + "name": "hwinfo", + "version": "1.0.0", + "description": "cross platform C++ library for hardware information (CPU, RAM, GPU, ...)", + "homepage": "https://github.com/lfreist/hwinfo", + "license": "MIT", + "supports": "(windows | linux) & !uwp", + "dependencies": [ + { + "name": "vcpkg-cmake", + "host": true + }, + { + "name": "vcpkg-cmake-config", + "host": true + } + ] +} diff --git a/.vcpkg/ports/libcocos2d/ccstring.patch b/.vcpkg/ports/libcocos2d/ccstring.patch new file mode 100644 index 0000000..d24476a --- /dev/null +++ b/.vcpkg/ports/libcocos2d/ccstring.patch @@ -0,0 +1,18 @@ +diff --git a/cocos/deprecated/CCString.h b/cocos/deprecated/CCString.h +index 9c4981cfa0..e1d326dfd5 100644 +--- a/cocos/deprecated/CCString.h ++++ b/cocos/deprecated/CCString.h +@@ -200,13 +200,6 @@ public: + std::string _string; + }; + +-struct StringCompare : public std::binary_function<__String *, __String *, bool> { +- public: +- bool operator() (__String * a, __String * b) const { +- return strcmp(a->getCString(), b->getCString()) < 0; +- } +-}; +- + #define StringMake(str) String::create(str) + #define ccs StringMake + diff --git a/.vcpkg/ports/libcocos2d/glfw.patch b/.vcpkg/ports/libcocos2d/glfw.patch new file mode 100644 index 0000000..548a028 --- /dev/null +++ b/.vcpkg/ports/libcocos2d/glfw.patch @@ -0,0 +1,31 @@ +diff --git a/cocos/platform/desktop/CCGLViewImpl-desktop.h b/cocos/platform/desktop/CCGLViewImpl-desktop.h +index 1f92acecd5..53cee41d17 100644 +--- a/cocos/platform/desktop/CCGLViewImpl-desktop.h ++++ b/cocos/platform/desktop/CCGLViewImpl-desktop.h +@@ -29,7 +29,7 @@ THE SOFTWARE. + #include "base/CCRef.h" + #include "platform/CCCommon.h" + #include "platform/CCGLView.h" +-#include "glfw3.h" ++#include + + #if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) + #ifndef GLFW_EXPOSE_NATIVE_WIN32 +@@ -38,7 +38,7 @@ THE SOFTWARE. + #ifndef GLFW_EXPOSE_NATIVE_WGL + #define GLFW_EXPOSE_NATIVE_WGL + #endif +-#include "glfw3native.h" ++#include + #endif /* (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) */ + + #if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) +@@ -48,7 +48,7 @@ THE SOFTWARE. + #ifndef GLFW_EXPOSE_NATIVE_COCOA + #define GLFW_EXPOSE_NATIVE_COCOA + #endif +-#include "glfw3native.h" ++#include + #endif // #if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) + + NS_CC_BEGIN diff --git a/.vcpkg/ports/libcocos2d/libcocos2d.lib b/.vcpkg/ports/libcocos2d/libcocos2d.lib new file mode 100644 index 0000000..b4f2fe1 Binary files /dev/null and b/.vcpkg/ports/libcocos2d/libcocos2d.lib differ diff --git a/.vcpkg/ports/libcocos2d/libcocos2dConfig.cmake.in b/.vcpkg/ports/libcocos2d/libcocos2dConfig.cmake.in new file mode 100644 index 0000000..05f8933 --- /dev/null +++ b/.vcpkg/ports/libcocos2d/libcocos2dConfig.cmake.in @@ -0,0 +1,32 @@ +include(FindPackageHandleStandardArgs) + +if (NOT LIBCOCOS2D_FOUND) + find_library( + LIBCOCOS2D_LIBRARY + libcocos2d + PATH_SUFFIXES + lib + vendor/lib + ) + + find_path( + LIBCOCOS2D_INCLUDE_DIR + cocos + PATH_SUFFIXES + include + vendor/include + ) + + add_library(LIBCOCOS2D::LIBCOCOS2D STATIC IMPORTED) + + set_target_properties( + LIBCOCOS2D::LIBCOCOS2D + PROPERTIES + IMPORTED_LOCATION + "${LIBCOCOS2D_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES + "${LIBCOCOS2D_INCLUDE_DIR}" + ) + + find_package_handle_standard_args(LIBCOCOS2D DEFAULT_MSG LIBCOCOS2D_LIBRARY LIBCOCOS2D_INCLUDE_DIR) +endif() diff --git a/.vcpkg/ports/libcocos2d/portfile.cmake b/.vcpkg/ports/libcocos2d/portfile.cmake new file mode 100644 index 0000000..662d98a --- /dev/null +++ b/.vcpkg/ports/libcocos2d/portfile.cmake @@ -0,0 +1,22 @@ +vcpkg_check_linkage(ONLY_STATIC_LIBRARY) + +vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_PATH + REPO cocos2d/cocos2d-x + REF cocos2d-x-3.14.1 + SHA512 48d12a48b5c880aa1cccafa64353f025b32235be5d15d73861f6e825a5305946e039a1585883f7ca5336a59c966cb8daf61012ed0c99810a5fe3ae8aa98f80a3 + PATCHES + ccstring.patch + glfw.patch + win32.patch +) + +file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}") +file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/${PORT}.lib" DESTINATION "${CURRENT_PACKAGES_DIR}/lib") + +file(INSTALL "${SOURCE_PATH}/cocos" DESTINATION "${CURRENT_PACKAGES_DIR}/include" FILES_MATCHING PATTERN "*.h") +file(INSTALL "${SOURCE_PATH}/cocos" DESTINATION "${CURRENT_PACKAGES_DIR}/include" FILES_MATCHING PATTERN "*.inl") +vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/licenses/LICENSE_cocos2d-x.txt") + +# Copy cmake configuration files +configure_file(${CMAKE_CURRENT_LIST_DIR}/libcocos2dConfig.cmake.in ${CURRENT_PACKAGES_DIR}/share/${PORT}/libcocos2dConfig.cmake @ONLY) diff --git a/.vcpkg/ports/libcocos2d/usage b/.vcpkg/ports/libcocos2d/usage new file mode 100644 index 0000000..e09fc8d --- /dev/null +++ b/.vcpkg/ports/libcocos2d/usage @@ -0,0 +1,4 @@ +To use COCOS2D add the following to your CMake project: + + find_package(COCOS2D REQUIRED) + target_link_libraries(main PRIVATE COCOS2D::COCOS2D) diff --git a/.vcpkg/ports/libcocos2d/vcpkg.json b/.vcpkg/ports/libcocos2d/vcpkg.json new file mode 100644 index 0000000..ad11630 --- /dev/null +++ b/.vcpkg/ports/libcocos2d/vcpkg.json @@ -0,0 +1,12 @@ +{ + "name": "libcocos2d", + "version": "3.14.1", + "description": "Cocos2d-x is a suite of open-source, cross-platform, game-development tools utilized by millions of developers across the globe", + "homepage": "https://github.com/cocos2d/cocos2d-x", + "license": "MIT", + "supports": "(windows) & !uwp", + "dependencies": [ + "glew", + "glfw3" + ] +} diff --git a/.vcpkg/ports/libcocos2d/win32.patch b/.vcpkg/ports/libcocos2d/win32.patch new file mode 100644 index 0000000..7325d24 --- /dev/null +++ b/.vcpkg/ports/libcocos2d/win32.patch @@ -0,0 +1,25 @@ +diff --git a/cocos/platform/win32/CCPlatformDefine-win32.h b/cocos/platform/win32/CCPlatformDefine-win32.h +index 88d04b5442..a532025774 100644 +--- a/cocos/platform/win32/CCPlatformDefine-win32.h ++++ b/cocos/platform/win32/CCPlatformDefine-win32.h +@@ -60,20 +60,6 @@ THE SOFTWARE. + #endif + #endif + +-#if _MSC_VER > 1800 +-#pragma comment(lib,"libpng-2015.lib") +-#pragma comment(lib,"libjpeg-2015.lib") +-#pragma comment(lib,"libtiff-2015.lib") +-#pragma comment(lib,"glfw3-2015.lib") +-#pragma comment(lib,"libchipmunk-2015.lib") +-#else +-#pragma comment(lib,"libpng.lib") +-#pragma comment(lib,"libjpeg.lib") +-#pragma comment(lib,"libtiff.lib") +-#pragma comment(lib,"glfw3.lib") +-#pragma comment(lib,"libchipmunk.lib") +-#endif +- + #endif //s CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 + + #endif /* __CCPLATFORMDEFINE_H__*/ diff --git a/.vcpkg/ports/openpsf/FindOPENPSF.cmake.in b/.vcpkg/ports/openpsf/FindOPENPSF.cmake.in new file mode 100644 index 0000000..d2c79ea --- /dev/null +++ b/.vcpkg/ports/openpsf/FindOPENPSF.cmake.in @@ -0,0 +1,121 @@ +# Distributed under the OSI-approved BSD 3-Clause License. +# +#.rst: +# FindOPENPSF +# -------- +# +# Find the OPENPSF libraries +# +# Result Variables +# ^^^^^^^^^^^^^^^^ +# +# The following variables will be defined: +# +# ``OPENPSF_FOUND`` +# True if OPENPSF found on the local system +# +# ``OPENPSF_INCLUDE_DIRS`` +# Location of OPENPSF header files +# +# ``OPENPSF_LIBRARY_DIRS`` +# Location of OPENPSF libraries +# +# ``OPENPSF_LIBRARIES`` +# List of the OPENPSF libraries found +# +# + +include(FindPackageHandleStandardArgs) +include(SelectLibraryConfigurations) +include(CMakeFindDependencyMacro) + +if(NOT OPENPSF_FOUND) + +# Compute the installation path relative to this file. +get_filename_component(SEARCH_PATH "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(SEARCH_PATH "${SEARCH_PATH}" PATH) +get_filename_component(SEARCH_PATH "${SEARCH_PATH}" PATH) +if(SEARCH_PATH STREQUAL "/") + set(SEARCH_PATH "") +endif() + +set(OPENPSF_VERSION "@OPENPSF_VERSION@") + +function(append_dependencies out) + cmake_parse_arguments(PARSE_ARGV 1 "arg" "DEBUG" "NAMES" "") + if(${arg_DEBUG}) + set(config DEBUG) + set(path "${CURRENT_INSTALLED_DIR}/debug/lib/") + else() + set(config RELEASE) + set(path "${CURRENT_INSTALLED_DIR}/lib/") + endif() + foreach(lib_name ${arg_NAMES}) + if("${lib_name}" STREQUAL "-pthread") + list(APPEND ${out} "-pthread") + elseif("${lib_name}" STREQUAL "-pthreads") + list(APPEND ${out} "-pthreads") + elseif("${lib_name}" STREQUAL "gcc") + list(APPEND ${out} "-lgcc") + elseif("${lib_name}" STREQUAL "gcc_s") + list(APPEND ${out} "-lgcc_s") + elseif("${lib_name}" STREQUAL "stdc++") + list(APPEND ${out} "-lstdc++") + else() + # first look in ${path} specifically to ensure we find the right release/debug variant + find_library(OPENPSF_DEPENDENCY_${lib_name}_${config} NAMES "${lib_name}" PATHS "${path}" NO_DEFAULT_PATH) + # if not found there, must be a system dependency, so look elsewhere + find_library(OPENPSF_DEPENDENCY_${lib_name}_${config} NAMES "${lib_name}" REQUIRED) + list(APPEND ${out} "${OPENPSF_DEPENDENCY_${lib_name}_${config}}") + endif() + endforeach() + set("${out}" "${${out}}" PARENT_SCOPE) +endfunction() + +macro(OPENPSF_FIND libname shortname headername) + if(NOT OPENPSF_${libname}_INCLUDE_DIRS) + find_path(OPENPSF_${libname}_INCLUDE_DIRS NAMES ${headername} PATHS ${SEARCH_PATH}/include NO_DEFAULT_PATH) + endif() + if(NOT OPENPSF_${libname}_LIBRARY) + find_library(OPENPSF_${libname}_LIBRARY_RELEASE NAMES ${shortname} PATHS ${SEARCH_PATH}/lib/ NO_DEFAULT_PATH) + find_library(OPENPSF_${libname}_LIBRARY_DEBUG NAMES ${shortname} PATHS ${SEARCH_PATH}/debug/lib/ NO_DEFAULT_PATH) + get_filename_component(OPENPSF_${libname}_LIBRARY_RELEASE_DIR ${OPENPSF_${libname}_LIBRARY_RELEASE} DIRECTORY) + get_filename_component(OPENPSF_${libname}_LIBRARY_DEBUG_DIR ${OPENPSF_${libname}_LIBRARY_DEBUG} DIRECTORY) + select_library_configurations(OPENPSF_${libname}) + set(OPENPSF_${libname}_LIBRARY ${OPENPSF_${libname}_LIBRARY} CACHE STRING "") + endif() + if (OPENPSF_${libname}_LIBRARY AND OPENPSF_${libname}_INCLUDE_DIRS) + set(OPENPSF_${libname}_FOUND TRUE BOOL) + list(APPEND OPENPSF_INCLUDE_DIRS ${OPENPSF_${libname}_INCLUDE_DIRS}) + list(APPEND OPENPSF_LIBRARIES ${OPENPSF_${libname}_LIBRARY}) + list(APPEND OPENPSF_LIBRARY_DIRS ${OPENPSF_${libname}_LIBRARY_RELEASE_DIR} ${OPENPSF_${libname}_LIBRARY_DEBUG_DIR}) + endif() +endmacro(OPENPSF_FIND) + +OPENPSF_FIND(PSXCore PSXCore highly_experimental/bios.h) +OPENPSF_FIND(psflib psflib psflib/psflib.h) +OPENPSF_FIND(openpsf openpsf openpsf/openpsf.h) + +if (OPENPSF_openpsf_FOUND) + list(REMOVE_DUPLICATES OPENPSF_INCLUDE_DIRS) + list(REMOVE_DUPLICATES OPENPSF_LIBRARY_DIRS) + set(OPENPSF_openpsf_VERSION "@OPENPSF_VERSION@" CACHE STRING "") + + append_dependencies(OPENPSF_DEPS_LIBRARY_RELEASE NAMES "@OPENPSF_DEPENDENCIES_RELEASE@") + append_dependencies(OPENPSF_DEPS_LIBRARY_DEBUG NAMES "@OPENPSF_DEPENDENCIES_DEBUG@" DEBUG) + if(OPENPSF_DEPS_LIBRARY_RELEASE OR OPENPSF_DEPS_LIBRARY_DEBUG) + select_library_configurations(OPENPSF_DEPS) + list(APPEND OPENPSF_LIBRARIES ${OPENPSF_DEPS_LIBRARY}) + endif() + + set(OPENPSF_LIBRARY ${OPENPSF_LIBRARIES}) + + set(OPENPSF_FOUND TRUE CACHE BOOL "") + set(OPENPSF_LIBRARIES ${OPENPSF_LIBRARIES} CACHE STRING "") + set(OPENPSF_INCLUDE_DIRS ${OPENPSF_INCLUDE_DIRS} CACHE STRING "") + set(OPENPSF_LIBRARY_DIRS ${OPENPSF_LIBRARY_DIRS} CACHE STRING "") +endif() + +find_package_handle_standard_args(OPENPSF REQUIRED_VARS OPENPSF_LIBRARIES OPENPSF_LIBRARY_DIRS OPENPSF_INCLUDE_DIRS) + +endif() diff --git a/.vcpkg/ports/openpsf/portfile.cmake b/.vcpkg/ports/openpsf/portfile.cmake new file mode 100644 index 0000000..45930d3 --- /dev/null +++ b/.vcpkg/ports/openpsf/portfile.cmake @@ -0,0 +1,51 @@ +# For a list of common variables see https://github.com/microsoft/vcpkg/blob/master/docs/maintainers/vcpkg_common_definitions.md + +# Checkout dependencies + +vcpkg_from_github( + OUT_SOURCE_PATH HE_SOURCE_DIR + REPO "julianxhokaxhiu/highly_experimental" + HEAD_REF master + REF 3600726c94b685a007ef9b6be2b31c29fbad08e9 + SHA512 c2a2504379b8e407d005dae8c28616f694892228ff25f0e39262bb4a0fe3f689552b6b93788f7d175338b2034b45b3059cd6050b7335d3c5ef83d6cf861dc2ba +) + +vcpkg_from_github( + OUT_SOURCE_PATH PSFLIB_SOURCE_DIR + REPO "julianxhokaxhiu/psflib" + HEAD_REF master + REF 93d14f05f5943ca5437378a731be60f8525366be + SHA512 a63ae8bfa3ea0b45fe957eebb5a0d0c4cb829e05c6255525a88a019c13f4bf1900234d0894be2bf75f5ecfd8f1783b188576a534f1e192e4cfc01aed9e041b86 +) + +# Checkout this project + +vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_DIR + REPO "julianxhokaxhiu/openpsf" + HEAD_REF master + REF 9b832c44ab57084f5e96aa6b78eb3a68e77e0cd9 + SHA512 77fe1bd888cd434f2fe61af972b6d406341b30571e4d6db5b3ad413de156c4e8b29068a9826c093b707bbd0e7cf12e658d515ee4cb02c98fb2e2a7e905ae8bc8 +) + +# Move dependencies inside the project directory +file(RENAME ${HE_SOURCE_DIR} "${SOURCE_DIR}/highly_experimental") +file(RENAME ${PSFLIB_SOURCE_DIR} "${SOURCE_DIR}/psflib") + +# Run MSBuild + +vcpkg_install_msbuild( + SOURCE_PATH "${SOURCE_DIR}" + PROJECT_SUBPATH "openpsf.sln" + LICENSE_SUBPATH "LICENSE" + INCLUDES_SUBPATH "include" + USE_VCPKG_INTEGRATION +) + +# Copy dependencies headers +file(INSTALL "${SOURCE_DIR}/highly_experimental/include/highly_experimental" DESTINATION "${CURRENT_PACKAGES_DIR}/include") +file(INSTALL "${SOURCE_DIR}/psflib/include/psflib" DESTINATION "${CURRENT_PACKAGES_DIR}/include") + +# Copy cmake configuration files +configure_file(${CMAKE_CURRENT_LIST_DIR}/FindOPENPSF.cmake.in ${CURRENT_PACKAGES_DIR}/share/${PORT}/FindOPENPSF.cmake @ONLY) +file(COPY ${CMAKE_CURRENT_LIST_DIR}/vcpkg-cmake-wrapper.cmake DESTINATION ${CURRENT_PACKAGES_DIR}/share/${PORT}) diff --git a/.vcpkg/ports/openpsf/usage b/.vcpkg/ports/openpsf/usage new file mode 100644 index 0000000..e1c63b7 --- /dev/null +++ b/.vcpkg/ports/openpsf/usage @@ -0,0 +1,6 @@ +To use openpsf add the following to your CMake project: + + find_package(OPENPSF REQUIRED) + target_include_directories(main PRIVATE ${OPENPSF_INCLUDE_DIRS}) + target_link_directories(main PRIVATE ${OPENPSF_LIBRARY_DIRS}) + target_link_libraries(main PRIVATE ${OPENPSF_LIBRARIES}) diff --git a/.vcpkg/ports/openpsf/vcpkg-cmake-wrapper.cmake b/.vcpkg/ports/openpsf/vcpkg-cmake-wrapper.cmake new file mode 100644 index 0000000..c871cf7 --- /dev/null +++ b/.vcpkg/ports/openpsf/vcpkg-cmake-wrapper.cmake @@ -0,0 +1,8 @@ +set(OPENPSF_PREV_MODULE_PATH ${CMAKE_MODULE_PATH}) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) + +cmake_policy(SET CMP0012 NEW) + +_find_package(${ARGS}) + +set(CMAKE_MODULE_PATH ${OPENPSF_PREV_MODULE_PATH}) diff --git a/.vcpkg/ports/openpsf/vcpkg.json b/.vcpkg/ports/openpsf/vcpkg.json new file mode 100644 index 0000000..8c13e3f --- /dev/null +++ b/.vcpkg/ports/openpsf/vcpkg.json @@ -0,0 +1,9 @@ +{ + "name": "openpsf", + "version": "1.3.0", + "description": "Tiny lib to stream PSF files (PlayStation Midi)", + "homepage": "https://github.com/myst6re/openpsf", + "dependencies": [ + "zlib" + ] +} \ No newline at end of file diff --git a/.vcpkg/ports/soloud/FindSOLOUD.cmake.in b/.vcpkg/ports/soloud/FindSOLOUD.cmake.in new file mode 100644 index 0000000..2b4da22 --- /dev/null +++ b/.vcpkg/ports/soloud/FindSOLOUD.cmake.in @@ -0,0 +1,125 @@ +# Distributed under the OSI-approved BSD 3-Clause License. +# +#.rst: +# FindSOLOUD +# -------- +# +# Find the SOLOUD libraries +# +# Result Variables +# ^^^^^^^^^^^^^^^^ +# +# The following variables will be defined: +# +# ``SOLOUD_FOUND`` +# True if SOLOUD found on the local system +# +# ``SOLOUD_INCLUDE_DIRS`` +# Location of SOLOUD header files +# +# ``SOLOUD_LIBRARY_DIRS`` +# Location of SOLOUD libraries +# +# ``SOLOUD_LIBRARIES`` +# List of the SOLOUD libraries found +# +# + +include(FindPackageHandleStandardArgs) +include(SelectLibraryConfigurations) +include(CMakeFindDependencyMacro) + +if(NOT SOLOUD_FOUND) + +# Compute the installation path relative to this file. +get_filename_component(SEARCH_PATH "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(SEARCH_PATH "${SEARCH_PATH}" PATH) +get_filename_component(SEARCH_PATH "${SEARCH_PATH}" PATH) +if(SEARCH_PATH STREQUAL "/") + set(SEARCH_PATH "") +endif() + +# Compute target architecture +set(architecture x86) +if (CMAKE_GENERATOR_PLATFORM MATCHES Win64) + set(architecture x64) +endif() + +set(SOLOUD_VERSION "@SOLOUD_VERSION@") + +function(append_dependencies out) + cmake_parse_arguments(PARSE_ARGV 1 "arg" "DEBUG" "NAMES" "") + if(${arg_DEBUG}) + set(config DEBUG) + set(path "${CURRENT_INSTALLED_DIR}/debug/lib/") + else() + set(config RELEASE) + set(path "${CURRENT_INSTALLED_DIR}/lib/") + endif() + foreach(lib_name ${arg_NAMES}) + if("${lib_name}" STREQUAL "-pthread") + list(APPEND ${out} "-pthread") + elseif("${lib_name}" STREQUAL "-pthreads") + list(APPEND ${out} "-pthreads") + elseif("${lib_name}" STREQUAL "gcc") + list(APPEND ${out} "-lgcc") + elseif("${lib_name}" STREQUAL "gcc_s") + list(APPEND ${out} "-lgcc_s") + elseif("${lib_name}" STREQUAL "stdc++") + list(APPEND ${out} "-lstdc++") + else() + # first look in ${path} specifically to ensure we find the right release/debug variant + find_library(SOLOUD_DEPENDENCY_${lib_name}_${config} NAMES "${lib_name}" PATHS "${path}" NO_DEFAULT_PATH) + # if not found there, must be a system dependency, so look elsewhere + find_library(SOLOUD_DEPENDENCY_${lib_name}_${config} NAMES "${lib_name}" REQUIRED) + list(APPEND ${out} "${SOLOUD_DEPENDENCY_${lib_name}_${config}}") + endif() + endforeach() + set("${out}" "${${out}}" PARENT_SCOPE) +endfunction() + +macro(SOLOUD_FIND libname shortname headername) + if(NOT SOLOUD_${libname}_INCLUDE_DIRS) + find_path(SOLOUD_${libname}_INCLUDE_DIRS NAMES ${headername} PATHS ${SEARCH_PATH}/include NO_DEFAULT_PATH) + endif() + if(NOT SOLOUD_${libname}_LIBRARY) + find_library(SOLOUD_${libname}_LIBRARY_RELEASE NAMES ${shortname}_${architecture} PATHS ${SEARCH_PATH}/lib/ NO_DEFAULT_PATH) + find_library(SOLOUD_${libname}_LIBRARY_DEBUG NAMES ${shortname}_${architecture}_d PATHS ${SEARCH_PATH}/debug/lib/ NO_DEFAULT_PATH) + get_filename_component(SOLOUD_${libname}_LIBRARY_RELEASE_DIR ${SOLOUD_${libname}_LIBRARY_RELEASE} DIRECTORY) + get_filename_component(SOLOUD_${libname}_LIBRARY_DEBUG_DIR ${SOLOUD_${libname}_LIBRARY_DEBUG} DIRECTORY) + select_library_configurations(SOLOUD_${libname}) + set(SOLOUD_${libname}_LIBRARY ${SOLOUD_${libname}_LIBRARY} CACHE STRING "") + endif() + if (SOLOUD_${libname}_LIBRARY AND SOLOUD_${libname}_INCLUDE_DIRS) + set(SOLOUD_${libname}_FOUND TRUE BOOL) + list(APPEND SOLOUD_INCLUDE_DIRS ${SOLOUD_${libname}_INCLUDE_DIRS}) + list(APPEND SOLOUD_LIBRARIES ${SOLOUD_${libname}_LIBRARY}) + list(APPEND SOLOUD_LIBRARY_DIRS ${SOLOUD_${libname}_LIBRARY_RELEASE_DIR} ${SOLOUD_${libname}_LIBRARY_DEBUG_DIR}) + endif() +endmacro(SOLOUD_FIND) + +SOLOUD_FIND(soloud soloud_static soloud.h) + +if (SOLOUD_soloud_FOUND) + list(REMOVE_DUPLICATES SOLOUD_INCLUDE_DIRS) + list(REMOVE_DUPLICATES SOLOUD_LIBRARY_DIRS) + set(SOLOUD_soloud_VERSION "@SOLOUD_VERSION@" CACHE STRING "") + + append_dependencies(SOLOUD_DEPS_LIBRARY_RELEASE NAMES "@SOLOUD_DEPENDENCIES_RELEASE@") + append_dependencies(SOLOUD_DEPS_LIBRARY_DEBUG NAMES "@SOLOUD_DEPENDENCIES_DEBUG@" DEBUG) + if(SOLOUD_DEPS_LIBRARY_RELEASE OR SOLOUD_DEPS_LIBRARY_DEBUG) + select_library_configurations(SOLOUD_DEPS) + list(APPEND SOLOUD_LIBRARIES ${SOLOUD_DEPS_LIBRARY}) + endif() + + set(SOLOUD_LIBRARY ${SOLOUD_LIBRARIES}) + + set(SOLOUD_FOUND TRUE CACHE BOOL "") + set(SOLOUD_LIBRARIES ${SOLOUD_LIBRARIES} CACHE STRING "") + set(SOLOUD_INCLUDE_DIRS ${SOLOUD_INCLUDE_DIRS} CACHE STRING "") + set(SOLOUD_LIBRARY_DIRS ${SOLOUD_LIBRARY_DIRS} CACHE STRING "") +endif() + +find_package_handle_standard_args(SOLOUD REQUIRED_VARS SOLOUD_LIBRARIES SOLOUD_LIBRARY_DIRS SOLOUD_INCLUDE_DIRS) + +endif() diff --git a/.vcpkg/ports/soloud/portfile.cmake b/.vcpkg/ports/soloud/portfile.cmake new file mode 100644 index 0000000..fe57549 --- /dev/null +++ b/.vcpkg/ports/soloud/portfile.cmake @@ -0,0 +1,94 @@ +# For a list of common variables see https://github.com/microsoft/vcpkg/blob/master/docs/maintainers/vcpkg_common_definitions.md + +# Download source packages + +vcpkg_from_github(OUT_SOURCE_PATH SOURCE_DIR + REPO "julianxhokaxhiu/soloud" + HEAD_REF master + REF a95f563abfbf3f45f83927a322f5113ba99559bb + SHA512 05d6869de77c1bf578619c6c4a6523cd7afc1e2eeaa22934f32de0c7bff372dd5acde1b87a8cc50a2b8be37ac5a672060de5f5fc98e519b2f40736cbaa9868be +) + +# Set up GENie (custom project generator) + +set(SOLOUD_PROJNAME Static) +set(GENIE_OPTIONS --with-miniaudio-only) + +if(VCPKG_CRT_LINKAGE STREQUAL dynamic) + set(SOLOUD_PROJNAME Dynamic) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --with-dynamic-runtime) +endif() +if(VCPKG_LIBRARY_LINKAGE STREQUAL dynamic) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --with-shared-lib) +endif() + +if(VCPKG_TARGET_ARCHITECTURE STREQUAL x86) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --platform=x32) +elseif(VCPKG_TARGET_ARCHITECTURE STREQUAL x64) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --platform=x64) +elseif(VCPKG_TARGET_ARCHITECTURE STREQUAL arm OR VCPKG_TARGET_ARCHITECTURE STREQUAL arm64) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --platform=ARM) +else() + message(WARNING "Architecture may be not supported: ${VCPKG_TARGET_ARCHITECTURE}") + set(GENIE_OPTIONS ${GENIE_OPTIONS} --platform=${VCPKG_TARGET_ARCHITECTURE}) +endif() + +if(TARGET_TRIPLET MATCHES osx) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --os=macosx) +elseif(TARGET_TRIPLET MATCHES linux) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --os=linux) +elseif(TARGET_TRIPLET MATCHES windows) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --os=windows) +elseif(TARGET_TRIPLET MATCHES uwp) + set(GENIE_OPTIONS ${GENIE_OPTIONS} --vs=winstore100) +endif() + +# GENie does not allow cmake+msvc, so we use msbuild in windows +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + if(VCPKG_PLATFORM_TOOLSET STREQUAL "v140") + set(GENIE_ACTION vs2015) + elseif(VCPKG_PLATFORM_TOOLSET STREQUAL "v141") + set(GENIE_ACTION vs2017) + elseif(VCPKG_PLATFORM_TOOLSET STREQUAL "v142") + set(GENIE_ACTION vs2019) + elseif(VCPKG_PLATFORM_TOOLSET STREQUAL "v143") + set(GENIE_ACTION vs2022) + else() + message(FATAL_ERROR "Unsupported Visual Studio toolset: ${VCPKG_PLATFORM_TOOLSET}") + endif() + set(PROJ_FOLDER ${GENIE_ACTION}) + if(TARGET_TRIPLET MATCHES uwp) + set(PROJ_FOLDER ${PROJ_FOLDER}-winstore100) + endif() +else() + set(GENIE_ACTION cmake) + set(PROJ_FOLDER ${GENIE_ACTION}) +endif() + +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + set(GENIE "${CURRENT_INSTALLED_DIR}/tools/bx/genie.exe") +else() + message(FATAL_ERROR "Unsupported host platform: ${CMAKE_HOST_SYSTEM_NAME}") +endif() + +# Run GENie + +vcpkg_execute_required_process( + COMMAND ${GENIE} ${GENIE_OPTIONS} ${GENIE_ACTION} + WORKING_DIRECTORY "${SOURCE_DIR}/build" + LOGNAME "genie-${TARGET_TRIPLET}" +) + +# Run MSBuild + +vcpkg_install_msbuild( + SOURCE_PATH "${SOURCE_DIR}" + PROJECT_SUBPATH "build/${GENIE_ACTION}/SoLoud${SOLOUD_PROJNAME}.vcxproj" + LICENSE_SUBPATH "LICENSE" + INCLUDES_SUBPATH "include" + ALLOW_ROOT_INCLUDES +) + +# Copy cmake configuration files +configure_file(${CMAKE_CURRENT_LIST_DIR}/FindSOLOUD.cmake.in ${CURRENT_PACKAGES_DIR}/share/${PORT}/FindSOLOUD.cmake @ONLY) +file(COPY ${CMAKE_CURRENT_LIST_DIR}/vcpkg-cmake-wrapper.cmake DESTINATION ${CURRENT_PACKAGES_DIR}/share/${PORT}) diff --git a/.vcpkg/ports/soloud/usage b/.vcpkg/ports/soloud/usage new file mode 100644 index 0000000..86f7a45 --- /dev/null +++ b/.vcpkg/ports/soloud/usage @@ -0,0 +1,6 @@ +To use soloud add the following to your CMake project: + + find_package(SOLOUD REQUIRED) + target_include_directories(main PRIVATE ${SOLOUD_INCLUDE_DIRS}) + target_link_directories(main PRIVATE ${SOLOUD_LIBRARY_DIRS}) + target_link_libraries(main PRIVATE ${SOLOUD_LIBRARIES}) diff --git a/.vcpkg/ports/soloud/vcpkg-cmake-wrapper.cmake b/.vcpkg/ports/soloud/vcpkg-cmake-wrapper.cmake new file mode 100644 index 0000000..888c683 --- /dev/null +++ b/.vcpkg/ports/soloud/vcpkg-cmake-wrapper.cmake @@ -0,0 +1,8 @@ +set(SOLOUD_PREV_MODULE_PATH ${CMAKE_MODULE_PATH}) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) + +cmake_policy(SET CMP0012 NEW) + +_find_package(${ARGS}) + +set(CMAKE_MODULE_PATH ${SOLOUD_PREV_MODULE_PATH}) diff --git a/.vcpkg/ports/soloud/vcpkg.json b/.vcpkg/ports/soloud/vcpkg.json new file mode 100644 index 0000000..a8be192 --- /dev/null +++ b/.vcpkg/ports/soloud/vcpkg.json @@ -0,0 +1,9 @@ +{ + "name": "soloud", + "version": "1.0.0", + "description": "Free, easy, portable audio engine for games", + "homepage": "https://github.com/julianxhokaxhiu/soloud", + "dependencies": [ + "bx" + ] +} \ No newline at end of file diff --git a/.vcpkg/ports/stackwalker/FindSTACKWALKER.cmake.in b/.vcpkg/ports/stackwalker/FindSTACKWALKER.cmake.in new file mode 100644 index 0000000..fdbf81f --- /dev/null +++ b/.vcpkg/ports/stackwalker/FindSTACKWALKER.cmake.in @@ -0,0 +1,119 @@ +# Distributed under the OSI-approved BSD 3-Clause License. +# +#.rst: +# FindSTACKWALKER +# -------- +# +# Find the STACKWALKER libraries +# +# Result Variables +# ^^^^^^^^^^^^^^^^ +# +# The following variables will be defined: +# +# ``STACKWALKER_FOUND`` +# True if STACKWALKER found on the local system +# +# ``STACKWALKER_INCLUDE_DIRS`` +# Location of STACKWALKER header files +# +# ``STACKWALKER_LIBRARY_DIRS`` +# Location of STACKWALKER libraries +# +# ``STACKWALKER_LIBRARIES`` +# List of the STACKWALKER libraries found +# +# + +include(FindPackageHandleStandardArgs) +include(SelectLibraryConfigurations) +include(CMakeFindDependencyMacro) + +if(NOT STACKWALKER_FOUND) + +# Compute the installation path relative to this file. +get_filename_component(SEARCH_PATH "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(SEARCH_PATH "${SEARCH_PATH}" PATH) +get_filename_component(SEARCH_PATH "${SEARCH_PATH}" PATH) +if(SEARCH_PATH STREQUAL "/") + set(SEARCH_PATH "") +endif() + +set(STACKWALKER_VERSION "@STACKWALKER_VERSION@") + +function(append_dependencies out) + cmake_parse_arguments(PARSE_ARGV 1 "arg" "DEBUG" "NAMES" "") + if(${arg_DEBUG}) + set(config DEBUG) + set(path "${CURRENT_INSTALLED_DIR}/debug/lib/") + else() + set(config RELEASE) + set(path "${CURRENT_INSTALLED_DIR}/lib/") + endif() + foreach(lib_name ${arg_NAMES}) + if("${lib_name}" STREQUAL "-pthread") + list(APPEND ${out} "-pthread") + elseif("${lib_name}" STREQUAL "-pthreads") + list(APPEND ${out} "-pthreads") + elseif("${lib_name}" STREQUAL "gcc") + list(APPEND ${out} "-lgcc") + elseif("${lib_name}" STREQUAL "gcc_s") + list(APPEND ${out} "-lgcc_s") + elseif("${lib_name}" STREQUAL "stdc++") + list(APPEND ${out} "-lstdc++") + else() + # first look in ${path} specifically to ensure we find the right release/debug variant + find_library(STACKWALKER_DEPENDENCY_${lib_name}_${config} NAMES "${lib_name}" PATHS "${path}" NO_DEFAULT_PATH) + # if not found there, must be a system dependency, so look elsewhere + find_library(STACKWALKER_DEPENDENCY_${lib_name}_${config} NAMES "${lib_name}" REQUIRED) + list(APPEND ${out} "${STACKWALKER_DEPENDENCY_${lib_name}_${config}}") + endif() + endforeach() + set("${out}" "${${out}}" PARENT_SCOPE) +endfunction() + +macro(STACKWALKER_FIND libname shortname headername) + if(NOT STACKWALKER_${libname}_INCLUDE_DIRS) + find_path(STACKWALKER_${libname}_INCLUDE_DIRS NAMES ${headername} PATHS ${SEARCH_PATH}/include NO_DEFAULT_PATH) + endif() + if(NOT STACKWALKER_${libname}_LIBRARY) + find_library(STACKWALKER_${libname}_LIBRARY_RELEASE NAMES ${shortname} PATHS ${SEARCH_PATH}/lib/ NO_DEFAULT_PATH) + find_library(STACKWALKER_${libname}_LIBRARY_DEBUG NAMES ${shortname} PATHS ${SEARCH_PATH}/debug/lib/ NO_DEFAULT_PATH) + get_filename_component(STACKWALKER_${libname}_LIBRARY_RELEASE_DIR ${STACKWALKER_${libname}_LIBRARY_RELEASE} DIRECTORY) + get_filename_component(STACKWALKER_${libname}_LIBRARY_DEBUG_DIR ${STACKWALKER_${libname}_LIBRARY_DEBUG} DIRECTORY) + select_library_configurations(STACKWALKER_${libname}) + set(STACKWALKER_${libname}_LIBRARY ${STACKWALKER_${libname}_LIBRARY} CACHE STRING "") + endif() + if (STACKWALKER_${libname}_LIBRARY AND STACKWALKER_${libname}_INCLUDE_DIRS) + set(STACKWALKER_${libname}_FOUND TRUE BOOL) + list(APPEND STACKWALKER_INCLUDE_DIRS ${STACKWALKER_${libname}_INCLUDE_DIRS}) + list(APPEND STACKWALKER_LIBRARIES ${STACKWALKER_${libname}_LIBRARY}) + list(APPEND STACKWALKER_LIBRARY_DIRS ${STACKWALKER_${libname}_LIBRARY_RELEASE_DIR} ${STACKWALKER_${libname}_LIBRARY_DEBUG_DIR}) + endif() +endmacro(STACKWALKER_FIND) + +STACKWALKER_FIND(stackwalker StackWalker StackWalker.h) + +if (STACKWALKER_stackwalker_FOUND) + list(REMOVE_DUPLICATES STACKWALKER_INCLUDE_DIRS) + list(REMOVE_DUPLICATES STACKWALKER_LIBRARY_DIRS) + set(STACKWALKER_stackwalker_VERSION "@STACKWALKER_VERSION@" CACHE STRING "") + + append_dependencies(STACKWALKER_DEPS_LIBRARY_RELEASE NAMES "@STACKWALKER_DEPENDENCIES_RELEASE@") + append_dependencies(STACKWALKER_DEPS_LIBRARY_DEBUG NAMES "@STACKWALKER_DEPENDENCIES_DEBUG@" DEBUG) + if(STACKWALKER_DEPS_LIBRARY_RELEASE OR STACKWALKER_DEPS_LIBRARY_DEBUG) + select_library_configurations(STACKWALKER_DEPS) + list(APPEND STACKWALKER_LIBRARIES ${STACKWALKER_DEPS_LIBRARY}) + endif() + + set(STACKWALKER_LIBRARY ${STACKWALKER_LIBRARIES}) + + set(STACKWALKER_FOUND TRUE CACHE BOOL "") + set(STACKWALKER_LIBRARIES ${STACKWALKER_LIBRARIES} CACHE STRING "") + set(STACKWALKER_INCLUDE_DIRS ${STACKWALKER_INCLUDE_DIRS} CACHE STRING "") + set(STACKWALKER_LIBRARY_DIRS ${STACKWALKER_LIBRARY_DIRS} CACHE STRING "") +endif() + +find_package_handle_standard_args(STACKWALKER REQUIRED_VARS STACKWALKER_LIBRARIES STACKWALKER_LIBRARY_DIRS STACKWALKER_INCLUDE_DIRS) + +endif() diff --git a/.vcpkg/ports/stackwalker/portfile.cmake b/.vcpkg/ports/stackwalker/portfile.cmake new file mode 100644 index 0000000..c2f7b6c --- /dev/null +++ b/.vcpkg/ports/stackwalker/portfile.cmake @@ -0,0 +1,29 @@ +# For a list of common variables see https://github.com/microsoft/vcpkg/blob/master/docs/maintainers/vcpkg_common_definitions.md + +# Download source packages +# (bgfx requires bx and bimg source for building) + +vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_PATH + REPO "JochenKalmbach/StackWalker" + HEAD_REF master + REF 5b0df7a4db8896f6b6dc45d36e383c52577e3c6b + SHA512 4a338e886c09f4350eaf46be6c4ca04b3be5e7b7909241047a72f2972af7bc7ad750272204d96869763ba251ca5cd5f4212c65628e35b18217970ae059545382 +) + +vcpkg_configure_cmake( + SOURCE_PATH ${SOURCE_PATH} + PREFER_NINJA +) + +vcpkg_install_cmake() + +vcpkg_copy_pdbs() + +file(INSTALL ${SOURCE_PATH}/LICENSE DESTINATION ${CURRENT_PACKAGES_DIR}/share/${PORT} RENAME copyright) + +file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include") + +# Copy cmake configuration files +configure_file(${CMAKE_CURRENT_LIST_DIR}/FindSTACKWALKER.cmake.in ${CURRENT_PACKAGES_DIR}/share/${PORT}/FindSTACKWALKER.cmake @ONLY) +file(COPY ${CMAKE_CURRENT_LIST_DIR}/vcpkg-cmake-wrapper.cmake DESTINATION ${CURRENT_PACKAGES_DIR}/share/${PORT}) diff --git a/.vcpkg/ports/stackwalker/usage b/.vcpkg/ports/stackwalker/usage new file mode 100644 index 0000000..009e150 --- /dev/null +++ b/.vcpkg/ports/stackwalker/usage @@ -0,0 +1,6 @@ +To use stackwalker add the following to your CMake project: + + find_package(STACKWALKER REQUIRED) + target_include_directories(main PRIVATE ${STACKWALKER_INCLUDE_DIRS}) + target_link_directories(main PRIVATE ${STACKWALKER_LIBRARY_DIRS}) + target_link_libraries(main PRIVATE ${STACKWALKER_LIBRARIES}) diff --git a/.vcpkg/ports/stackwalker/vcpkg-cmake-wrapper.cmake b/.vcpkg/ports/stackwalker/vcpkg-cmake-wrapper.cmake new file mode 100644 index 0000000..024e373 --- /dev/null +++ b/.vcpkg/ports/stackwalker/vcpkg-cmake-wrapper.cmake @@ -0,0 +1,8 @@ +set(STACKWALKER_PREV_MODULE_PATH ${CMAKE_MODULE_PATH}) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) + +cmake_policy(SET CMP0012 NEW) + +_find_package(${ARGS}) + +set(CMAKE_MODULE_PATH ${STACKWALKER_PREV_MODULE_PATH}) diff --git a/.vcpkg/ports/stackwalker/vcpkg.json b/.vcpkg/ports/stackwalker/vcpkg.json new file mode 100644 index 0000000..d779cef --- /dev/null +++ b/.vcpkg/ports/stackwalker/vcpkg.json @@ -0,0 +1,6 @@ +{ + "name": "stackwalker", + "version": "1.2.1", + "description": "Walking the callstack in windows applications", + "homepage": "https://github.com/JochenKalmbach/StackWalker" +} \ No newline at end of file diff --git a/.vcpkg/ports/steamworkssdk/STEAMWORKSSDKConfig.cmake.in b/.vcpkg/ports/steamworkssdk/STEAMWORKSSDKConfig.cmake.in new file mode 100644 index 0000000..2c43220 --- /dev/null +++ b/.vcpkg/ports/steamworkssdk/STEAMWORKSSDKConfig.cmake.in @@ -0,0 +1,32 @@ +include(FindPackageHandleStandardArgs) + +if (NOT STEAMWORKSSDK_FOUND) + find_library( + STEAMWORKSSDK_LIBRARY + steam_api + PATH_SUFFIXES + lib + vendor/lib + ) + + find_path( + STEAMWORKSSDK_INCLUDE_DIR + steamworkssdk + PATH_SUFFIXES + include + vendor/include + ) + + add_library(STEAMWORKSSDK::STEAMWORKSSDK STATIC IMPORTED) + + set_target_properties( + STEAMWORKSSDK::STEAMWORKSSDK + PROPERTIES + IMPORTED_LOCATION + "${STEAMWORKSSDK_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES + "${STEAMWORKSSDK_INCLUDE_DIR}" + ) + + find_package_handle_standard_args(STEAMWORKSSDK DEFAULT_MSG STEAMWORKSSDK_LIBRARY STEAMWORKSSDK_INCLUDE_DIR) +endif() \ No newline at end of file diff --git a/.vcpkg/ports/steamworkssdk/portfile.cmake b/.vcpkg/ports/steamworkssdk/portfile.cmake new file mode 100644 index 0000000..c23852d --- /dev/null +++ b/.vcpkg/ports/steamworkssdk/portfile.cmake @@ -0,0 +1,33 @@ +# For a list of common variables see https://github.com/microsoft/vcpkg/blob/master/docs/maintainers/vcpkg_common_definitions.md + +# Download source packages + +set(VCPKG_POLICY_EMPTY_PACKAGE enabled) + +vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_PATH + REPO "julianxhokaxhiu/SteamworksSDKCI" + HEAD_REF master + REF d320d9566179684d4fc597e151f50ad0beaaa4d0 + SHA512 dc7d4ee95353737fa38b68204755ec3b0a7a2216cc60af6da20b491ba729b2a8003a6511b34690cb254a0db91c79b8df588a40e7e75aed9d00d10c35eb221583 +) + +file(TO_NATIVE_PATH "${CURRENT_PACKAGES_DIR}/include/steamworkssdk" INCLUDE_PATH) +file(TO_NATIVE_PATH "${CURRENT_PACKAGES_DIR}/tools/steamworkssdk" TOOLS_PATH) + +file(MAKE_DIRECTORY + "${INCLUDE_PATH}" +) + +file(GLOB + HEADER_FILES + "${SOURCE_PATH}/steamworks_sdk/public/steam/*.h" +) + +file(COPY ${SOURCE_PATH}/steamworks_sdk/redistributable_bin/steam_api.lib DESTINATION ${CURRENT_PACKAGES_DIR}/lib) +file(COPY ${SOURCE_PATH}/steamworks_sdk/redistributable_bin/steam_api.lib DESTINATION ${CURRENT_PACKAGES_DIR}/debug/lib) +file(COPY ${SOURCE_PATH}/steamworks_sdk/redistributable_bin/steam_api.dll DESTINATION ${TOOLS_PATH}) +file(COPY ${HEADER_FILES} DESTINATION ${INCLUDE_PATH}) + +# Copy cmake configuration files +configure_file(${CMAKE_CURRENT_LIST_DIR}/STEAMWORKSSDKConfig.cmake.in ${CURRENT_PACKAGES_DIR}/share/${PORT}/STEAMWORKSSDKConfig.cmake @ONLY) diff --git a/.vcpkg/ports/steamworkssdk/usage b/.vcpkg/ports/steamworkssdk/usage new file mode 100644 index 0000000..b74c169 --- /dev/null +++ b/.vcpkg/ports/steamworkssdk/usage @@ -0,0 +1,4 @@ +To use STEAMWORKSSDK add the following to your CMake project: + + find_package(STEAMWORKSSDK REQUIRED) + target_link_libraries(main PRIVATE STEAMWORKSSDK::STEAMWORKSSDK) diff --git a/.vcpkg/ports/steamworkssdk/vcpkg.json b/.vcpkg/ports/steamworkssdk/vcpkg.json new file mode 100644 index 0000000..747f3f2 --- /dev/null +++ b/.vcpkg/ports/steamworkssdk/vcpkg.json @@ -0,0 +1,6 @@ +{ + "name": "steamworkssdk", + "version": "1.23.0", + "description": "CI builds of Steamworks SDK for CMake build systems", + "homepage": "https://github.com/julianxhokaxhiu/SteamworksSDKCI" +} \ No newline at end of file diff --git a/.vcpkg/ports/tomlplusplus/portfile.cmake b/.vcpkg/ports/tomlplusplus/portfile.cmake new file mode 100644 index 0000000..36e6d05 --- /dev/null +++ b/.vcpkg/ports/tomlplusplus/portfile.cmake @@ -0,0 +1,20 @@ +vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_PATH + REPO marzer/tomlplusplus + REF v3.4.0 + SHA512 c227fc8147c9459b29ad24002aaf6ab2c42fac22ea04c1c52b283a0172581ccd4527b33c1931e0ef0d1db6b6a53f9e9882c6d4231c7f3494cf070d0220741aa5 + HEAD_REF master +) + +vcpkg_configure_cmake( + SOURCE_PATH ${SOURCE_PATH} + PREFER_NINJA +) + +vcpkg_install_cmake() +vcpkg_cmake_config_fixup(CONFIG_PATH lib/cmake/tomlplusplus) +vcpkg_fixup_pkgconfig() + +file(INSTALL "${SOURCE_PATH}/LICENSE" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright) +file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug") +file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/lib") diff --git a/.vcpkg/ports/tomlplusplus/vcpkg.json b/.vcpkg/ports/tomlplusplus/vcpkg.json new file mode 100644 index 0000000..77b675b --- /dev/null +++ b/.vcpkg/ports/tomlplusplus/vcpkg.json @@ -0,0 +1,18 @@ +{ + "name": "tomlplusplus", + "version": "3.4.0", + "description": "Header-only TOML config file parser and serializer for modern C++.", + "homepage": "https://marzer.github.io/tomlplusplus/", + "license": "MIT", + "supports": "!uwp", + "dependencies": [ + { + "name": "vcpkg-cmake-config", + "host": true + }, + { + "name": "vcpkg-tool-meson", + "host": true + } + ] +} diff --git a/.vcpkg/ports/vgmstream/FindVGMSTREAM.cmake.in b/.vcpkg/ports/vgmstream/FindVGMSTREAM.cmake.in new file mode 100644 index 0000000..6542b4d --- /dev/null +++ b/.vcpkg/ports/vgmstream/FindVGMSTREAM.cmake.in @@ -0,0 +1,120 @@ +# Distributed under the OSI-approved BSD 3-Clause License. +# +#.rst: +# FindVGMSTREAM +# -------- +# +# Find the VGMSTREAM libraries +# +# Result Variables +# ^^^^^^^^^^^^^^^^ +# +# The following variables will be defined: +# +# ``VGMSTREAM_FOUND`` +# True if VGMSTREAM found on the local system +# +# ``VGMSTREAM_INCLUDE_DIRS`` +# Location of VGMSTREAM header files +# +# ``VGMSTREAM_LIBRARY_DIRS`` +# Location of VGMSTREAM libraries +# +# ``VGMSTREAM_LIBRARIES`` +# List of the VGMSTREAM libraries found +# +# + +include(FindPackageHandleStandardArgs) +include(SelectLibraryConfigurations) +include(CMakeFindDependencyMacro) + +if(NOT VGMSTREAM_FOUND) + +# Compute the installation path relative to this file. +get_filename_component(SEARCH_PATH "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(SEARCH_PATH "${SEARCH_PATH}" PATH) +get_filename_component(SEARCH_PATH "${SEARCH_PATH}" PATH) +if(SEARCH_PATH STREQUAL "/") + set(SEARCH_PATH "") +endif() + +set(VGMSTREAM_VERSION "@VGMSTREAM_VERSION@") + +function(append_dependencies out) + cmake_parse_arguments(PARSE_ARGV 1 "arg" "DEBUG" "NAMES" "") + if(${arg_DEBUG}) + set(config DEBUG) + set(path "${CURRENT_INSTALLED_DIR}/debug/lib/") + else() + set(config RELEASE) + set(path "${CURRENT_INSTALLED_DIR}/lib/") + endif() + foreach(lib_name ${arg_NAMES}) + if("${lib_name}" STREQUAL "-pthread") + list(APPEND ${out} "-pthread") + elseif("${lib_name}" STREQUAL "-pthreads") + list(APPEND ${out} "-pthreads") + elseif("${lib_name}" STREQUAL "gcc") + list(APPEND ${out} "-lgcc") + elseif("${lib_name}" STREQUAL "gcc_s") + list(APPEND ${out} "-lgcc_s") + elseif("${lib_name}" STREQUAL "stdc++") + list(APPEND ${out} "-lstdc++") + else() + # first look in ${path} specifically to ensure we find the right release/debug variant + find_library(VGMSTREAM_DEPENDENCY_${lib_name}_${config} NAMES "${lib_name}" PATHS "${path}" NO_DEFAULT_PATH) + # if not found there, must be a system dependency, so look elsewhere + find_library(VGMSTREAM_DEPENDENCY_${lib_name}_${config} NAMES "${lib_name}" REQUIRED) + list(APPEND ${out} "${VGMSTREAM_DEPENDENCY_${lib_name}_${config}}") + endif() + endforeach() + set("${out}" "${${out}}" PARENT_SCOPE) +endfunction() + +macro(VGMSTREAM_FIND libname shortname headername) + if(NOT VGMSTREAM_${libname}_INCLUDE_DIRS) + find_path(VGMSTREAM_${libname}_INCLUDE_DIRS NAMES ${headername} PATHS ${SEARCH_PATH}/include NO_DEFAULT_PATH) + endif() + if(NOT VGMSTREAM_${libname}_LIBRARY) + find_library(VGMSTREAM_${libname}_LIBRARY_RELEASE NAMES ${shortname} PATHS ${SEARCH_PATH}/lib/ NO_DEFAULT_PATH) + find_library(VGMSTREAM_${libname}_LIBRARY_DEBUG NAMES ${shortname} PATHS ${SEARCH_PATH}/debug/lib/ NO_DEFAULT_PATH) + get_filename_component(VGMSTREAM_${libname}_LIBRARY_RELEASE_DIR ${VGMSTREAM_${libname}_LIBRARY_RELEASE} DIRECTORY) + get_filename_component(VGMSTREAM_${libname}_LIBRARY_DEBUG_DIR ${VGMSTREAM_${libname}_LIBRARY_DEBUG} DIRECTORY) + select_library_configurations(VGMSTREAM_${libname}) + set(VGMSTREAM_${libname}_LIBRARY ${VGMSTREAM_${libname}_LIBRARY} CACHE STRING "") + endif() + if (VGMSTREAM_${libname}_LIBRARY AND VGMSTREAM_${libname}_INCLUDE_DIRS) + set(VGMSTREAM_${libname}_FOUND TRUE BOOL) + list(APPEND VGMSTREAM_INCLUDE_DIRS ${VGMSTREAM_${libname}_INCLUDE_DIRS}) + list(APPEND VGMSTREAM_LIBRARIES ${VGMSTREAM_${libname}_LIBRARY}) + list(APPEND VGMSTREAM_LIBRARY_DIRS ${VGMSTREAM_${libname}_LIBRARY_RELEASE_DIR} ${VGMSTREAM_${libname}_LIBRARY_DEBUG_DIR}) + endif() +endmacro(VGMSTREAM_FIND) + +VGMSTREAM_FIND(vgmstream libvgmstream libvgmstream/vgmstream.h) + +if (VGMSTREAM_vgmstream_FOUND) + list(APPEND VGMSTREAM_INCLUDE_DIRS "${SEARCH_PATH}/include/libvgmstream") + list(REMOVE_DUPLICATES VGMSTREAM_INCLUDE_DIRS) + list(REMOVE_DUPLICATES VGMSTREAM_LIBRARY_DIRS) + set(VGMSTREAM_vgmstream_VERSION "@VGMSTREAM_VERSION@" CACHE STRING "") + + append_dependencies(VGMSTREAM_DEPS_LIBRARY_RELEASE NAMES "@VGMSTREAM_DEPENDENCIES_RELEASE@") + append_dependencies(VGMSTREAM_DEPS_LIBRARY_DEBUG NAMES "@VGMSTREAM_DEPENDENCIES_DEBUG@" DEBUG) + if(VGMSTREAM_DEPS_LIBRARY_RELEASE OR VGMSTREAM_DEPS_LIBRARY_DEBUG) + select_library_configurations(VGMSTREAM_DEPS) + list(APPEND VGMSTREAM_LIBRARIES ${VGMSTREAM_DEPS_LIBRARY}) + endif() + + set(VGMSTREAM_LIBRARY ${VGMSTREAM_LIBRARIES}) + + set(VGMSTREAM_FOUND TRUE CACHE BOOL "") + set(VGMSTREAM_LIBRARIES ${VGMSTREAM_LIBRARIES} CACHE STRING "") + set(VGMSTREAM_INCLUDE_DIRS ${VGMSTREAM_INCLUDE_DIRS} CACHE STRING "") + set(VGMSTREAM_LIBRARY_DIRS ${VGMSTREAM_LIBRARY_DIRS} CACHE STRING "") +endif() + +find_package_handle_standard_args(VGMSTREAM REQUIRED_VARS VGMSTREAM_LIBRARIES VGMSTREAM_LIBRARY_DIRS VGMSTREAM_INCLUDE_DIRS) + +endif() diff --git a/.vcpkg/ports/vgmstream/cmake.patch b/.vcpkg/ports/vgmstream/cmake.patch new file mode 100644 index 0000000..fb3ab69 --- /dev/null +++ b/.vcpkg/ports/vgmstream/cmake.patch @@ -0,0 +1,68 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index f34fe127..539deb44 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1,4 +1,5 @@ + cmake_minimum_required(VERSION 3.6) ++cmake_policy(SET CMP0091 NEW) + project(vgmstream NONE) + + if(CMAKE_SYSTEM_NAME MATCHES Darwin) +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 3e707614..f653a75e 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -90,3 +90,30 @@ if(NOT EMSCRIPTEN) + set_target_properties(libvgmstream_shared PROPERTIES LINK_FLAGS_RELEASE -s) + endif() + endif() ++ ++if(MSVC) ++ target_compile_definitions(libvgmstream PRIVATE "USE_ALLOCA") ++ target_compile_options(libvgmstream PRIVATE /DVGM_DEBUG_OUTPUT) ++endif() ++ ++# Install library ++install(TARGETS libvgmstream ++ RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" ++ ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" ++ LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" ++) ++ ++if(NOT SKIP_INSTALL_HEADERS) ++ # Install headers ++ install( FILES ${CMAKE_CURRENT_SOURCE_DIR}/vgmstream.h DESTINATION include/libvgmstream ) ++ install( FILES ${CMAKE_CURRENT_SOURCE_DIR}/vgmstream_types.h DESTINATION include/libvgmstream ) ++ install( FILES ${CMAKE_CURRENT_SOURCE_DIR}/base/plugins.h DESTINATION include/libvgmstream ) ++ install( FILES ${CMAKE_CURRENT_SOURCE_DIR}/util.h DESTINATION include/libvgmstream ) ++ install( FILES ${CMAKE_CURRENT_SOURCE_DIR}/util/log.h DESTINATION include/libvgmstream/util ) ++ install( FILES ${CMAKE_CURRENT_SOURCE_DIR}/util/reader_get.h DESTINATION include/libvgmstream/util ) ++ install( FILES ${CMAKE_CURRENT_SOURCE_DIR}/util/reader_put.h DESTINATION include/libvgmstream/util ) ++ install( FILES ${CMAKE_CURRENT_SOURCE_DIR}/util/vgmstream_limits.h DESTINATION include/libvgmstream/util ) ++ install( FILES ${CMAKE_CURRENT_SOURCE_DIR}/streamtypes.h DESTINATION include/libvgmstream ) ++ install( FILES ${CMAKE_CURRENT_SOURCE_DIR}/streamfile.h DESTINATION include/libvgmstream ) ++ install( FILES ${CMAKE_CURRENT_SOURCE_DIR}/coding/g72x_state.h DESTINATION include/libvgmstream/coding ) ++endif() +diff --git a/src/base/streamfile_stdio.c b/src/base/streamfile_stdio.c +index 948f5ffc..a3dc25b0 100644 +--- a/src/base/streamfile_stdio.c ++++ b/src/base/streamfile_stdio.c +@@ -264,7 +264,10 @@ static STREAMFILE* open_stdio_streamfile_buffer_by_file(FILE* infile, const char + + this_sf->name_len = strlen(filename); + if (this_sf->name_len >= sizeof(this_sf->name)) ++ { ++ vgm_logi("STREAMFILE: filename length is longer than sizeof(this_sf->name).\n"); + goto fail; ++ } + memcpy(this_sf->name, filename, this_sf->name_len); + this_sf->name[this_sf->name_len] = '\0'; + +@@ -304,6 +307,7 @@ static STREAMFILE* open_stdio_streamfile_buffer_by_file(FILE* infile, const char + return &this_sf->vt; + + fail: ++ vgm_logi("STREAMFILE: could not allocate stream because of memory exhaustion.\n"); + free(buf); + free(this_sf); + return NULL; diff --git a/.vcpkg/ports/vgmstream/portfile.cmake b/.vcpkg/ports/vgmstream/portfile.cmake new file mode 100644 index 0000000..bef6e01 --- /dev/null +++ b/.vcpkg/ports/vgmstream/portfile.cmake @@ -0,0 +1,63 @@ +# For a list of common variables see https://github.com/microsoft/vcpkg/blob/master/docs/maintainers/vcpkg_common_definitions.md + +# Download source packages +# (bgfx requires bx and bimg source for building) + +vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_PATH + REPO "vgmstream/vgmstream" + HEAD_REF master + REF e79e0bad3fe32ded496220385debc83cc8c4fb03 + SHA512 0482623a77a03262a65023a5e5f8436c508bf5e127d9580642a8e67fc3b2a95182066ffe857253914c231273028755296de9e711bd3db784536c32e4a2fa443d + PATCHES cmake.patch +) + +SET(USE_FFMPEG OFF) +SET(USE_MPEG OFF) +SET(USE_VORBIS OFF) + +if("ffmpeg" IN_LIST FEATURES) + SET(USE_FFMPEG ON) +endif() + +if("mpg123" IN_LIST FEATURES) + SET(USE_MPEG ON) +endif() + +if("vorbis" IN_LIST FEATURES) + SET(USE_VORBIS ON) +endif() + +vcpkg_configure_cmake( + SOURCE_PATH ${SOURCE_PATH} + OPTIONS + -DUSE_ATRAC9=OFF + -DUSE_CELT=OFF + -DUSE_FFMPEG=${USE_FFMPEG} + -DAVCODEC_VERSION=57 + -DAVUTIL_VERSION=55 + -DAVFORMAT_VERSION=57 + -DSWRESAMPLE_VERSION=2 + -DUSE_G719=OFF + -DUSE_G7221=ON + -DUSE_MPEG=${USE_MPEG} + -DUSE_VORBIS=${USE_VORBIS} + -DBUILD_AUDACIOUS=OFF + -DBUILD_CLI=OFF + -DBUILD_FB2K=OFF + -DBUILD_XMPLAY=OFF + -DBUILD_WINAMP=OFF + OPTIONS_DEBUG + -DSKIP_INSTALL_HEADERS=ON +) + +vcpkg_install_cmake() + +vcpkg_copy_pdbs() + +file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}") +file(INSTALL ${SOURCE_PATH}/COPYING DESTINATION ${CURRENT_PACKAGES_DIR}/share/${PORT} RENAME copyright) + +# Copy cmake configuration files +configure_file(${CMAKE_CURRENT_LIST_DIR}/FindVGMSTREAM.cmake.in ${CURRENT_PACKAGES_DIR}/share/${PORT}/FindVGMSTREAM.cmake @ONLY) +file(COPY ${CMAKE_CURRENT_LIST_DIR}/vcpkg-cmake-wrapper.cmake DESTINATION ${CURRENT_PACKAGES_DIR}/share/${PORT}) diff --git a/.vcpkg/ports/vgmstream/usage b/.vcpkg/ports/vgmstream/usage new file mode 100644 index 0000000..f5decb1 --- /dev/null +++ b/.vcpkg/ports/vgmstream/usage @@ -0,0 +1,6 @@ +To use vgmstream add the following to your CMake project: + + find_package(VGMSTREAM REQUIRED) + target_include_directories(main PRIVATE ${VGMSTREAM_INCLUDE_DIRS}) + target_link_directories(main PRIVATE ${VGMSTREAM_LIBRARY_DIRS}) + target_link_libraries(main PRIVATE ${VGMSTREAM_LIBRARIES}) diff --git a/.vcpkg/ports/vgmstream/vcpkg-cmake-wrapper.cmake b/.vcpkg/ports/vgmstream/vcpkg-cmake-wrapper.cmake new file mode 100644 index 0000000..3548a5c --- /dev/null +++ b/.vcpkg/ports/vgmstream/vcpkg-cmake-wrapper.cmake @@ -0,0 +1,8 @@ +set(VGMSTREAM_PREV_MODULE_PATH ${CMAKE_MODULE_PATH}) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) + +cmake_policy(SET CMP0012 NEW) + +_find_package(${ARGS}) + +set(CMAKE_MODULE_PATH ${VGMSTREAM_PREV_MODULE_PATH}) diff --git a/.vcpkg/ports/vgmstream/vcpkg.json b/.vcpkg/ports/vgmstream/vcpkg.json new file mode 100644 index 0000000..1d14db0 --- /dev/null +++ b/.vcpkg/ports/vgmstream/vcpkg.json @@ -0,0 +1,38 @@ +{ + "name": "vgmstream", + "version": "1.0.0", + "description": "A library for playback of various streamed audio formats used in video games.", + "homepage": "https://github.com/vgmstream/vgmstream", + "default-features": [ + "ffmpeg", + "mpg123", + "vorbis" + ], + "features": { + "ffmpeg": { + "description": "Use ffmpeg to decode audio files", + "dependencies": [ + { + "name": "ffmpeg", + "default-features": false, + "features": [ + "avresample", + "gpl" + ] + } + ] + }, + "mpg123": { + "description": "Use mpg123 to decode MPEG audio files", + "dependencies": [ + "mpg123" + ] + }, + "vorbis": { + "description": "Use libvorbis to decode OGG audio files", + "dependencies": [ + "libvorbis" + ] + } + } +} \ No newline at end of file diff --git a/.vcpkg/versions/b-/bgfx.json b/.vcpkg/versions/b-/bgfx.json new file mode 100644 index 0000000..9934860 --- /dev/null +++ b/.vcpkg/versions/b-/bgfx.json @@ -0,0 +1,8 @@ +{ + "versions": [ + { + "version": "1.0.0", + "path": "$/ports/bgfx" + } + ] +} \ No newline at end of file diff --git a/.vcpkg/versions/b-/bimg.json b/.vcpkg/versions/b-/bimg.json new file mode 100644 index 0000000..cd6bc01 --- /dev/null +++ b/.vcpkg/versions/b-/bimg.json @@ -0,0 +1,8 @@ +{ + "versions": [ + { + "version": "1.0.0", + "path": "$/ports/bimg" + } + ] +} \ No newline at end of file diff --git a/.vcpkg/versions/b-/bx.json b/.vcpkg/versions/b-/bx.json new file mode 100644 index 0000000..5bb4e7b --- /dev/null +++ b/.vcpkg/versions/b-/bx.json @@ -0,0 +1,8 @@ +{ + "versions": [ + { + "version": "1.0.0", + "path": "$/ports/bx" + } + ] +} \ No newline at end of file diff --git a/.vcpkg/versions/baseline.json b/.vcpkg/versions/baseline.json new file mode 100644 index 0000000..1c273bb --- /dev/null +++ b/.vcpkg/versions/baseline.json @@ -0,0 +1,48 @@ +{ + "default": { + "bx": { + "baseline": "1.0.0", + "port-version": 0 + }, + "bimg": { + "baseline": "1.0.0", + "port-version": 0 + }, + "bgfx": { + "baseline": "1.0.0", + "port-version": 0 + }, + "soloud": { + "baseline": "1.0.0", + "port-version": 0 + }, + "stackwalker": { + "baseline": "1.2.1", + "port-version": 0 + }, + "vgmstream": { + "baseline": "1.0.0", + "port-version": 0 + }, + "openpsf": { + "baseline": "1.3.0", + "port-version": 0 + }, + "steamworkssdk": { + "baseline": "1.23.0", + "port-version": 0 + }, + "tomlplusplus": { + "baseline": "3.4.0", + "port-version": 0 + }, + "hwinfo": { + "baseline": "1.0.0", + "port-version": 0 + }, + "libcocos2d": { + "baseline": "3.14.1", + "port-version": 0 + } + } +} diff --git a/.vcpkg/versions/h-/hwinfo.json b/.vcpkg/versions/h-/hwinfo.json new file mode 100644 index 0000000..e15b237 --- /dev/null +++ b/.vcpkg/versions/h-/hwinfo.json @@ -0,0 +1,8 @@ +{ + "versions": [ + { + "version": "1.0.0", + "path": "$/ports/hwinfo" + } + ] +} \ No newline at end of file diff --git a/.vcpkg/versions/l-/libcocos2d.json b/.vcpkg/versions/l-/libcocos2d.json new file mode 100644 index 0000000..1e471a3 --- /dev/null +++ b/.vcpkg/versions/l-/libcocos2d.json @@ -0,0 +1,8 @@ +{ + "versions": [ + { + "version": "3.14.1", + "path": "$/ports/libcocos2d" + } + ] +} diff --git a/.vcpkg/versions/o-/openpsf.json b/.vcpkg/versions/o-/openpsf.json new file mode 100644 index 0000000..723efc5 --- /dev/null +++ b/.vcpkg/versions/o-/openpsf.json @@ -0,0 +1,8 @@ +{ + "versions": [ + { + "version": "1.3.0", + "path": "$/ports/openpsf" + } + ] +} \ No newline at end of file diff --git a/.vcpkg/versions/s-/soloud.json b/.vcpkg/versions/s-/soloud.json new file mode 100644 index 0000000..6e275ce --- /dev/null +++ b/.vcpkg/versions/s-/soloud.json @@ -0,0 +1,8 @@ +{ + "versions": [ + { + "version": "1.0.0", + "path": "$/ports/soloud" + } + ] +} \ No newline at end of file diff --git a/.vcpkg/versions/s-/stackwalker.json b/.vcpkg/versions/s-/stackwalker.json new file mode 100644 index 0000000..d15d252 --- /dev/null +++ b/.vcpkg/versions/s-/stackwalker.json @@ -0,0 +1,8 @@ +{ + "versions": [ + { + "version": "1.2.1", + "path": "$/ports/stackwalker" + } + ] +} \ No newline at end of file diff --git a/.vcpkg/versions/s-/steamworkssdk.json b/.vcpkg/versions/s-/steamworkssdk.json new file mode 100644 index 0000000..2f81845 --- /dev/null +++ b/.vcpkg/versions/s-/steamworkssdk.json @@ -0,0 +1,8 @@ +{ + "versions": [ + { + "version": "1.23.0", + "path": "$/ports/steamworkssdk" + } + ] +} \ No newline at end of file diff --git a/.vcpkg/versions/t-/tomlplusplus.json b/.vcpkg/versions/t-/tomlplusplus.json new file mode 100644 index 0000000..26a4bce --- /dev/null +++ b/.vcpkg/versions/t-/tomlplusplus.json @@ -0,0 +1,8 @@ +{ + "versions": [ + { + "version": "3.4.0", + "path": "$/ports/tomlplusplus" + } + ] +} \ No newline at end of file diff --git a/.vcpkg/versions/v-/vgmstream.json b/.vcpkg/versions/v-/vgmstream.json new file mode 100644 index 0000000..753cfcb --- /dev/null +++ b/.vcpkg/versions/v-/vgmstream.json @@ -0,0 +1,8 @@ +{ + "versions": [ + { + "version": "1.0.0", + "path": "$/ports/vgmstream" + } + ] +} \ No newline at end of file diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..6c996ad --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,23 @@ +{ + "configurations": [ + { + "name": "Win32", + "includePath": [ + "${default}", + "${workspaceFolder}/**" + ], + "defines": [ + "_DEBUG", + "UNICODE", + "_UNICODE" + ], + "cStandard": "c11", + "cppStandard": "c++20", + "browse": { + "limitSymbolsToIncludedHeaders": true + }, + "configurationProvider": "ms-vscode.cmake-tools" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..b1eb34c --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + "configurations": [ + { + "name": "Run CT", + "type": "cppvsdbg", + "request": "launch", + "program": "C:\\Program Files (x86)\\Steam\\steamapps\\common\\Chrono Trigger\\Chrono Trigger.exe", + "cwd": "C:\\Program Files (x86)\\Steam\\steamapps\\common\\Chrono Trigger" + }, + { + "name": "Attach Process", + "type": "cppvsdbg", + "request": "attach", + "processId":"${command:pickProcess}" + } + ] +} \ No newline at end of file diff --git a/.vsconfig b/.vsconfig new file mode 100644 index 0000000..e380d65 --- /dev/null +++ b/.vsconfig @@ -0,0 +1,56 @@ +{ + "version": "1.0", + "components": [ + "Microsoft.VisualStudio.Component.CoreEditor", + "Microsoft.VisualStudio.Workload.CoreEditor", + "Microsoft.Net.Component.4.8.SDK", + "Microsoft.Net.Component.4.7.2.TargetingPack", + "Microsoft.Net.ComponentGroup.DevelopmentPrerequisites", + "Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions", + "Microsoft.VisualStudio.Component.Roslyn.Compiler", + "Microsoft.Component.MSBuild", + "Microsoft.VisualStudio.Component.Roslyn.LanguageServices", + "Microsoft.VisualStudio.Component.TextTemplating", + "Microsoft.VisualStudio.Component.NuGet", + "Microsoft.VisualStudio.Component.SQL.CLR", + "Microsoft.Component.ClickOnce", + "Microsoft.VisualStudio.Component.ManagedDesktop.Core", + "Microsoft.NetCore.Component.Runtime.6.0", + "Microsoft.NetCore.Component.SDK", + "Microsoft.VisualStudio.Component.FSharp", + "Microsoft.ComponentGroup.ClickOnce.Publish", + "Microsoft.NetCore.Component.DevelopmentTools", + "Microsoft.Net.Component.4.8.TargetingPack", + "Microsoft.Net.ComponentGroup.4.8.DeveloperTools", + "Microsoft.VisualStudio.Component.DiagnosticTools", + "Microsoft.VisualStudio.Component.EntityFramework", + "Microsoft.VisualStudio.Component.Debugger.JustInTime", + "Microsoft.VisualStudio.Component.IntelliCode", + "Microsoft.Net.Component.4.6.2.TargetingPack", + "Microsoft.Net.Component.4.7.TargetingPack", + "Microsoft.Net.Component.4.7.1.TargetingPack", + "Microsoft.VisualStudio.Component.VC.CoreIde", + "Microsoft.VisualStudio.Component.Windows10SDK", + "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", + "Microsoft.VisualStudio.Component.Graphics.Tools", + "Microsoft.VisualStudio.Component.VC.DiagnosticTools", + "Microsoft.VisualStudio.Component.Windows10SDK.19041", + "Microsoft.VisualStudio.Component.ManagedDesktop.Prerequisites", + "Microsoft.ComponentGroup.Blend", + "Microsoft.VisualStudio.ComponentGroup.MSIX.Packaging", + "Microsoft.VisualStudio.Workload.ManagedDesktop", + "Microsoft.VisualStudio.Component.VC.Redist.14.Latest", + "Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core", + "Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions.CMake", + "Microsoft.VisualStudio.Component.VC.CMake.Project", + "Microsoft.VisualStudio.Component.VC.ATL", + "Microsoft.VisualStudio.Component.VC.TestAdapterForBoostTest", + "Microsoft.VisualStudio.Component.VC.TestAdapterForGoogleTest", + "Microsoft.VisualStudio.Component.VC.ASAN", + "Microsoft.VisualStudio.Component.Windows10SDK.20348", + "Microsoft.VisualStudio.Workload.NativeDesktop", + "Microsoft.Net.ComponentGroup.TargetingPacks.Common", + "Microsoft.Net.Component.4.6.TargetingPack", + "Microsoft.Net.Component.4.6.1.TargetingPack" + ] +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..d74c9ad --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,242 @@ +#*****************************************************************************# +# Copyright (C) 2024 Julian Xhokaxhiu # +# # +# This file is part of CTNx # +# # +# CTNx is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License # +# # +# CTNx is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +#*****************************************************************************# + +cmake_minimum_required(VERSION 3.25) +cmake_policy(SET CMP0091 NEW) + +if(NOT DEFINED CMAKE_BUILD_TYPE) + message(FATAL_ERROR "CMAKE_BUILD_TYPE must be set to continue building with cmake. \nExample: Add -DCMAKE_BUILD_TYPE=Release to your cmake command line.") +endif() +if (NOT DEFINED _DLL_VERSION OR NOT _DLL_VERSION) + message(FATAL_ERROR "_DLL_VERSION must be set to continue building with cmake. \nExample: Add -D_DLL_VERSION=devel to your cmake command line.") +endif () + +set(VCPKG_INSTALL_OPTIONS "--clean-after-build" "--x-use-aria2") + +set(CMAKE_SHARED_LINKER_FLAGS + "${CMAKE_SHARED_LINKER_FLAGS} /NODEFAULTLIB:MSVCRT /NODEFAULTLIB:MSVCRTD /DEBUG:FULL /FORCE:MULTIPLE /IGNORE:4006,4075,4099,4217" +) + +if(CMAKE_BUILD_TYPE MATCHES Debug) + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDebug") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /NODEFAULTLIB:LIBCMT") +else() + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /NODEFAULTLIB:LIBCMTD") +endif() + +project(CTNx) + +find_package(FFMPEG REQUIRED) +find_package(MPG123 REQUIRED) +find_package(Vorbis CONFIG REQUIRED) +find_package(VGMSTREAM REQUIRED) +find_package(STACKWALKER REQUIRED) +find_package(mimalloc CONFIG REQUIRED) +find_package(SOLOUD REQUIRED) +find_package(tomlplusplus CONFIG REQUIRED) +find_package(CMakeRC CONFIG REQUIRED) +find_package(HWINFO REQUIRED) +find_package(plog CONFIG REQUIRED) +find_package(LIBCOCOS2D REQUIRED) +find_package(glfw3 REQUIRED) + +find_path(DETOURS_INCLUDE_DIRS "detours/detours.h") +find_library(DETOURS_LIBRARY detours REQUIRED) + +set(RELEASE_NAME "CTNx") + +if(_DLL_VERSION STREQUAL "devel" OR _DLL_VERSION MATCHES "-") + set(_DLL_RCVERSION "0,0,0,0") + set(_DLL_RCSTRVERSION "0.0.0.0") + set(PATCH_COLLECT_DUPLICATES 1) +else() + string(REPLACE "." "," _DLL_RCVERSION ${_DLL_VERSION}) + set(_DLL_RCSTRVERSION ${_DLL_VERSION}) +endif() + +# Include all the source code files +file(GLOB_RECURSE source_files "${CMAKE_SOURCE_DIR}/src/*.cpp") + +configure_file(misc/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc @ONLY) + +cmrc_add_resource_library( + ${RELEASE_NAME}-resources + ALIAS ${RELEASE_NAME}::rc + NAMESPACE ${RELEASE_NAME} + ${CMAKE_CURRENT_SOURCE_DIR}/.logo/logo_nobg.png +) + +add_library(${RELEASE_NAME} SHARED ${source_files} ${CMAKE_CURRENT_BINARY_DIR}/version.rc) +target_include_directories( + ${RELEASE_NAME} + PRIVATE "${CMAKE_SOURCE_DIR}/src" + PRIVATE ${FFMPEG_INCLUDE_DIRS} + PRIVATE ${SOLOUD_INCLUDE_DIRS} + PRIVATE ${STACKWALKER_INCLUDE_DIRS} + PRIVATE ${VGMSTREAM_INCLUDE_DIRS} + PRIVATE ${DETOURS_INCLUDE_DIRS} + PRIVATE ${LIBCOCOS2D_INCLUDE_DIR} +) +target_link_directories( + ${RELEASE_NAME} + PRIVATE ${FFMPEG_LIBRARY_DIRS} +) +target_link_libraries( + ${RELEASE_NAME} + ${RELEASE_NAME}::rc + dbghelp + shlwapi + psapi + dwmapi + winmm + strmiids + mimalloc-static + tomlplusplus::tomlplusplus + Vorbis::vorbisfile + Vorbis::vorbis + MPG123::libmpg123 + HWINFO::HWINFO + plog::plog + LIBCOCOS2D::LIBCOCOS2D + glfw3 + ${FFMPEG_LIBRARIES} + ${SOLOUD_LIBRARIES} + ${STACKWALKER_LIBRARIES} + ${VGMSTREAM_LIBRARIES} + ${DETOURS_LIBRARY} +) +target_compile_options( + ${RELEASE_NAME} + PRIVATE /D_CRT_SECURE_NO_WARNINGS + PRIVATE /DNOMINMAX + PRIVATE /DWIN32_LEAN_AND_MEAN + PRIVATE /Zc:strictStrings- + PRIVATE /Zc:__cplusplus + PRIVATE /Zc:preprocessor + PRIVATE /Qpar + PRIVATE /MP + # App Defines + PRIVATE /DAPP_CONFIG_FILE="${RELEASE_NAME}.toml" + PRIVATE /DAPP_RELEASE_NAME="${RELEASE_NAME}" + PRIVATE /DAPP_RELEASE_VERSION="${_DLL_RCSTRVERSION}" +) +if(PATCH_COLLECT_DUPLICATES) + target_compile_definitions(${RELEASE_NAME} + PRIVATE PATCH_COLLECT_DUPLICATES + ) +endif() +target_compile_features(${RELEASE_NAME} + PRIVATE cxx_std_20 +) +target_link_options(${RELEASE_NAME} PRIVATE /PDBALTPATH:${RELEASE_NAME}.pdb) + +# List .gitkeep files to remove them on INSTALL +FILE(GLOB_RECURSE HEXT_GIT_KEEP_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/misc/ ${CMAKE_CURRENT_SOURCE_DIR}/misc/hext/**/.gitkeep) +LIST(TRANSFORM HEXT_GIT_KEEP_FILES PREPEND ${CMAKE_BINARY_DIR}/bin/) + +# INSTALL +add_custom_command( + TARGET ${RELEASE_NAME} + POST_BUILD + COMMAND echo Preparing ${RELEASE_NAME} ${_DLL_VERSION} release... + # ensure bin directory exists + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/bin + # License + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/COPYING.TXT + ${CMAKE_BINARY_DIR}/bin + # .dll + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${RELEASE_NAME}.dll + ${CMAKE_BINARY_DIR}/bin + # .pdb + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${RELEASE_NAME}.pdb + ${CMAKE_BINARY_DIR}/bin + # .toml + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/misc/${RELEASE_NAME}.toml + ${CMAKE_BINARY_DIR}/bin + # hext + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_SOURCE_DIR}/misc/hext + ${CMAKE_BINARY_DIR}/bin/hext + COMMAND ${CMAKE_COMMAND} -E rm ${HEXT_GIT_KEEP_FILES} + + # ambient .toml + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/misc/${RELEASE_NAME}.ambient.toml + ${CMAKE_BINARY_DIR}/bin/ambient/config.toml + + # Voice .toml + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/misc/${RELEASE_NAME}.voice.toml + ${CMAKE_BINARY_DIR}/bin/voice/config.toml +) + +# CPU INFO +add_custom_command( + TARGET ${RELEASE_NAME} + PRE_BUILD + # Get CPU info + COMMAND + ${CMAKE_BINARY_DIR}/vcpkg_installed/x86-windows-static/tools/cpuinfo/cpu-info + # Get CPU ISA supported instructions + COMMAND + ${CMAKE_BINARY_DIR}/vcpkg_installed/x86-windows-static/tools/cpuinfo/isa-info +) + +# Copy CTNx release to Chrono Trigger game path if installed +execute_process( + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/utils/FindSteamGamePath 613830 + OUTPUT_VARIABLE CT_GAME_PATH + OUTPUT_STRIP_TRAILING_WHITESPACE +) +if(NOT "${CT_GAME_PATH}" STREQUAL "") + cmake_path(CONVERT "${CT_GAME_PATH}" TO_CMAKE_PATH_LIST CT_GAME_PATH) + # Ensure CTNx.toml exists so the copy on build does not error on fresh installs + if(NOT EXISTS "${CT_GAME_PATH}/CTNx.toml") + # Copy file if it doesn't exist + file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/misc/CTNx.toml" DESTINATION "${CT_GAME_PATH}/") + endif() + add_custom_command( + TARGET ${RELEASE_NAME} + POST_BUILD + COMMAND echo Copying ${RELEASE_NAME} ${_DLL_VERSION} release to ${CT_GAME_PATH}... + # Preserve the current CTNx.toml + COMMAND ${CMAKE_COMMAND} -E rename + ${CT_GAME_PATH}/CTNx.toml + ${CT_GAME_PATH}/CTNx.toml.bak + # Copy all dist files + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_BINARY_DIR}/bin + ${CT_GAME_PATH} + # Delete previous version.dll + COMMAND ${CMAKE_COMMAND} -E remove + ${CT_GAME_PATH}/version.dll + # Rename CTNx.dll to version.dll + COMMAND ${CMAKE_COMMAND} -E rename + ${CT_GAME_PATH}/CTNx.dll + ${CT_GAME_PATH}/version.dll + # Delete the new copied CTNx.toml + COMMAND ${CMAKE_COMMAND} -E remove + ${CT_GAME_PATH}/CTNx.toml + # Bring back the existing CTNx.toml + COMMAND ${CMAKE_COMMAND} -E rename + ${CT_GAME_PATH}/CTNx.toml.bak + ${CT_GAME_PATH}/CTNx.toml + ) +endif() diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..5bbff1a --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,95 @@ +{ + "version": 6, + "cmakeMinimumRequired": { + "major": 3, + "minor": 25, + "patch": 0 + }, + "configurePresets": [ + { + "name": "base", + "hidden": true, + "generator": "Visual Studio 17 2022", + "architecture": { + "value": "win32", + "strategy": "set" + }, + "toolset": { + "value": "host=x86", + "strategy": "set" + }, + "environment": { + "NUGET_CLI_LANGUAGE": "en-us", + "VCPKG_ROOT": "C:/vcpkg", + "VCPKG_BINARY_SOURCES": "clear;nuget,github,readwrite;default,readwrite" + }, + "binaryDir": "${sourceDir}/.build", + "toolchainFile": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake", + "cacheVariables": { + "_DLL_VERSION": "devel", + "CMAKE_C_COMPILER": "cl", + "VCPKG_TARGET_TRIPLET": "x86-windows-static" + } + }, + { + "name": "Release", + "inherits": "base", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + } + }, + { + "name": "RelWithDebInfo", + "inherits": "base", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo" + } + }, + { + "name": "Debug", + "inherits": "base", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug" + } + }, + { + "name": "MinSizeRel", + "inherits": "base", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "MinSizeRel" + } + } + ], + "buildPresets": [ + { + "name": "Release", + "displayName": "Default", + "configurePreset": "Release", + "configuration": "Release" + }, + { + "name": "RelWithDebInfo", + "displayName": "Default", + "configurePreset": "RelWithDebInfo", + "configuration": "RelWithDebInfo" + }, + { + "name": "Debug", + "displayName": "Default", + "configurePreset": "Debug", + "configuration": "Debug" + }, + { + "name": "MinSizeRel", + "displayName": "Default", + "configurePreset": "MinSizeRel", + "configuration": "MinSizeRel" + } + ], + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "hostOS": "Windows", + "intelliSenseMode": "windows-msvc-x64" + } + } +} \ No newline at end of file diff --git a/COPYING.txt b/COPYING.txt new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/COPYING.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/Changelog.md b/Changelog.md new file mode 100644 index 0000000..1415101 --- /dev/null +++ b/Changelog.md @@ -0,0 +1,3 @@ +# Next + +- Full commit list since last stable release: https://github.com/julianxhokaxhiu/CTNx/compare/0.0.1...master diff --git a/README.md b/README.md new file mode 100644 index 0000000..67f9c70 --- /dev/null +++ b/README.md @@ -0,0 +1,181 @@ +![License](https://img.shields.io/github/license/julianxhokaxhiu/CTNx) ![Overall Downloads](https://img.shields.io/github/downloads/julianxhokaxhiu/CTNx/total?label=Overall%20Downloads) ![Latest Stable Downloads](https://img.shields.io/github/downloads/julianxhokaxhiu/CTNx/latest/total?label=Latest%20Stable%20Downloads&sort=semver) ![Latest Canary Downloads](https://img.shields.io/github/downloads/julianxhokaxhiu/CTNx/canary/total?label=Latest%20Canary%20Downloads) ![GitHub Actions Workflow Status](https://github.com/julianxhokaxhiu/CTNx/actions/workflows/main-0.0.1.yml/badge.svg?branch=master) + +
+ +
Temporary logo until final one is ready. Made with DALL-E 3 +
+ +# CTNx + +Next generation modding platform for Chrono Trigger ( native Steam 2018 release support! ) + +## Introduction + +CTNx is a new modding platform for Chrono Trigger. Inspired by [FFNx](https://github.com/julianxhokaxhiu/FFNx) aims at bringing the same set of functionalities in time. + +CTNx today in a nutshell: + +- Uses an easy, drag-n-drop installation experience, see [How to Install](docs/how_to_install.md) + +## The Team + +CTNx is developed by a core team, currently composed of: + +- [Julian Xhokaxhiu](https://github.com/julianxhokaxhiu) (TrueOdin, 🇪🇸 Spain) + +We are always open for contributions via PRs, and in case you want to join the core team, feel free to approach us on Discord and we will evaluate on a case-by-case basis. + +## Features + +### As a user + +- [/LARGEADDRESSAWARE](https://docs.microsoft.com/en-us/cpp/build/reference/largeaddressaware-handle-large-addresses?view=vs-2019) support. Up to 3.5GB of RAM available for mods (this requires the [4GB Patch](https://ntcore.com/?page_id=371) in your Chrono Trigger.exe). +- Native speedhack support (coming soon) +- Ambient effects layer (coming soon) +- Voice acting layer. + +### As a modder + +- Support for [Hext](https://forums.qhimm.com/index.php?topic=13574.0) patching files inside of the [hext_patching_path](misc/CTNx.toml#L113) + +## Documentation + +For a more in-depth documentation feel free to visit the [docs/](docs/) folder. + +## Tech Stack + +If you're curious to know, CTNx makes use of: + +- C++ code base +- Latest MSVC available on [Visual Studio 2022 Community Edition](https://visualstudio.microsoft.com/vs/features/cplusplus/) +- [vcpkg](https://vcpkg.io/) (dependency manager) +- [CMake](https://cmake.org/) (make files) +- [FFMpeg](https://www.ffmpeg.org/) with H/W accelleration support +- [VGMStream](https://github.com/losnoco/vgmstream) using FFMpeg as backend (with loop support!) +- [tomlplusplus](https://github.com/marzer/tomlplusplus) (configuration management) +- [StackWalker](https://github.com/JochenKalmbach/StackWalker) (log file stack traces) +- [SoLoud](https://github.com/jarikomppa/soloud) (audio engine used to playback audio, music or voice files) +- [mimalloc](https://github.com/microsoft/mimalloc) (a compact general purpose allocator with excellent performance) +- [plog](https://github.com/SergiusTheBest/plog) (logging library) +- [Detours](https://github.com/microsoft/Detours) (function replacement library) +- [Cocos2d-x](https://github.com/cocos2d/cocos2d-x) (game framework) + +## How to build + +Available build profiles: + +- x86-Release (default, the same used to release artifacts in this Github page) +- x86-RelWithDebInfo (used while developing to better debug some issues) +- x86-MinSizeRel +- x86-Debug (prefer it if you want to use a debugger attached to the game) + +Once the project is built you can find the output in this path: `.build/bin` + +### Preparation + +> **Please note:** +> +> CTNx uses vcpkg as a package manager to resolve dependencies. Failing to follow these steps will result in build errors. + +0. Clone the [vcpkg](https://vcpkg.io) project in the root folder of your `C:` drive (`git clone https://github.com/Microsoft/vcpkg.git`) +1. Go inside the `C:\vcpkg` folder and double click `bootstrap-vcpkg.bat` +2. Open a `cmd` window in `C:\vcpkg` and run the following command: `vcpkg integrate install` + +### NuGet + +> **Please note:** +> +> This step will speed up your compilation times by avoiding the vcpkg dependencies rebuild. + +0. Make sure you have [NuGet CLI installed](https://learn.microsoft.com/en-us/nuget/install-nuget-client-tools?tabs=windows#install-nugetexe). +1. [Create a Personal Access token ( classic )](https://github.com/settings/tokens/new) with the `write:packages` permission. +2. Open a `cmd` window and run the following commands ( replace `YOUR_GITHUB_USERNAME` and `YOUR_GITHUB_PAT` accordingly ): +```pwsh +$ nuget sources add -Name github -Source "https://nuget.pkg.github.com/tsunamods-codes/index.json" -Username YOUR_GITHUB_USERNAME -Password YOUR_GITHUB_PAT -StorePasswordInClearText +$ nuget setApiKey YOUR_GITHUB_PAT -Source "https://nuget.pkg.github.com/tsunamods-codes/index.json" +``` + +### Visual Studio + +> **Please note:** +> +> By default Visual Studio will pick the **x86-Release** build configuration, but you can choose any other profile available. + +0. Download the the latest [Visual Studio Community](https://visualstudio.microsoft.com/vs/community/) installer +1. Run the installer and import this [.vsconfig](.vsconfig) file in the installer to pick the components required to build this project +2. Make sure you select the English Language pack in the language list before clicking Install +3. Once installed, open this repository **as a folder** in Visual Studio +4. Choose as preset in the status bar the one you desire +5. Click the `Build` button + +### Visual Studio Code + +0. **REQUIRED!** Follow up the steps to install Visual Studio, which will also install the MSVC toolchain +1. Download and install the latest [Visual Studio Code](https://code.visualstudio.com/) release +2. Install the following extensions: + - https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools + - https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools +3. Open this repository as a folder in Visual Studio Code +4. Choose as preset in the status bar the one you desire +5. Click the button on the status bar `Build` + +### Neovim with clangd (optional) + +0. **REQUIRED!** Follow up the steps to install Visual Studio, which will also install the MSVC toolchain +1. **REQUIRED!** Have [Neovim](https://neovim.io/) installed with [clangd](https://clangd.llvm.org/) as LSP +2. Install the extension `Clang Power Tools` in [Visual Studio Community](https://visualstudio.microsoft.com/vs/community/) +3. Open the solution `CTNx.sln` under the `.build` directory with **Visual Studio Community** (**sln** file is generated by the build process) +4. Right-click on **CTNx** solution (under the **Solution Explorer**) then click on **Clang Power Tools** -> **Export Compilation Database** +5. Copy the `compile_commands.json` generated file into the root of the repository +6. Open **Neovim** and enjoy! + +To build from the terminal (example with *RelWithDebInfo*): +- For dependency use: `cmake --preset RelWithDebInfo` +- For building the project: `cmake --build --preset RelWithDebInfo` + +**NOTICE**: For the dependency step, make sure that PATH variable does not contain any UNIX command tools since vcpkg build process is based on UNIX tools. +Also on terminal it might not auto detect the kernel32_lib, so pass it with `-DCMAKE_LIBRARY_PATH=%kernel32_lib%` +(e.g. `cmake --preset RelWithDebInfo -DCMAKE_LIBRARY_PATH="C:\Program Files (x86)\Windows Kits\10\Lib\10.0.22621.0\um\x86"`) + +## Auto-Formatting + +### CMake Files + +0. **REQUIRED!** Install [Python](https://www.python.org/) +1. Install [cmake-format](https://github.com/cheshirekow/cmake_format#installation) and make sure the binary is available in your PATH environment variable +2. **OPTIONAL!** Integrate it [in your own IDE](https://github.com/cheshirekow/cmake_format#integrations) (eg. for Visual Studio Code use [the relative extension](https://marketplace.visualstudio.com/items?itemName=cheshirekow.cmake-format)) + +## Support + +CTNx offers multiple support channels, pick the one you prefer + +### Discord + +- Tsunamods CTNx: https://discord.gg/Urq67Uz (remember to hit the relative reaction!) + +### Github + +- Issues: https://github.com/julianxhokaxhiu/CTNx/issues + +## Credits + +This project could have not been a reality if those people would have not worked on Chrono Trigger with their deep passion and knowledge. +CTNx makes use also of their work, and I will never be enough grateful to those people. The order is purely Alphabetical. + +These people are: + +- [Biggs McWedge ](https://github.com/TheRealBiggs) + - for various discoveries in the game engine code + - for the initial voice acting implementation and research +- [Maciej Trębacz ](https://github.com/maciej-trebacz) + - for various discoveries in the game engine code + +## License + +CTNx is released under GPLv3 license. You can get a copy of the license here: [COPYING.txt](COPYING.txt) + +If you paid for CTNx, remember to ask for a refund from the person who sold you a copy. Also make sure you get a copy of the source code (if it was provided as binary only). + +If the person who gave you this copy refuses to give you the source code, report it here: https://www.gnu.org/licenses/gpl-violation.html + +All rights belong to their respective owners. diff --git a/cmake-format.yaml b/cmake-format.yaml new file mode 100644 index 0000000..f6c4b8c --- /dev/null +++ b/cmake-format.yaml @@ -0,0 +1,9 @@ +# cmake-format yaml configuration file + +format: + dangle_align: prefix + fractional_tab_policy: use-space + line_width: 150 + +markup: + enable_markup: false diff --git a/docs/faq.md b/docs/faq.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/how_to_install.md b/docs/how_to_install.md new file mode 100644 index 0000000..2dbdc53 --- /dev/null +++ b/docs/how_to_install.md @@ -0,0 +1,22 @@ +# How-to: Install + +Independently of the way you decide to install CTNx, in order to use it you MUST have a legal copy of the game. Support will NOT be provided if the game will NOT be detected as genuine. + +## Canary vs Stable + +CTNx comes in two flavors, resembling the Google Chrome release names. Unlike this one though, we don't need all the others. + +- **Stable:** this is a fully tested, and hopefully, bug free release. + > It is commonly accepted for long gameplay sessions and generic users. If in doubt, use this one first. +- **Canary:** this is like a nightly release, but untested. Feel free to use it at your own risk. + > This is what users need to try before reporting any issue encountered in this channel, or if you want to try the latest development updates going on in CTNx. + +## Standalone + +#### [2018 Steam Release](https://store.steampowered.com/app/613830/CHRONO_TRIGGER/) + +0. Install the game using the Steam Client +1. Open the installation directory of the game ( see [How to access game files](https://steamcommunity.com/sharedfiles/filedetails/?id=760447682) ) +2. Download the latest `CTNx` release here: https://github.com/julianxhokaxhiu/CTNx/releases +3. Extract the ZIP content next to your `Chrono Trigger.exe` file +4. Enjoy! diff --git a/docs/readme.md b/docs/readme.md new file mode 100644 index 0000000..096ee20 --- /dev/null +++ b/docs/readme.md @@ -0,0 +1,9 @@ +# CTNx documentation + +Welcome to the CTNx documentation! + +## Common + +- [How To Install](how_to_install.md) +- [FAQ - Frequently Asked Questions](faq.md) +- [Built-In Shortcuts](shortcuts.md) diff --git a/docs/shortcuts.md b/docs/shortcuts.md new file mode 100644 index 0000000..36b29c6 --- /dev/null +++ b/docs/shortcuts.md @@ -0,0 +1,23 @@ +# Shortcuts + +CTNx comes with various built-in shortcuts which would allow you to boost or enjoy your gameplay experience. + +### Speedhack + +This cheat will allow you to boost the gameplay timing up to 8x ( by default, [you can configure this](<(https://github.com/julianxhokaxhiu/CTNx/blob/master/misc/CTNx.toml#L200)>) up to your pleasure ). + +Shortcuts: + +- Keyboard Shortcut: `CTRL + Arrow Up/Down` + +You can toggle the speedhack (enable/disable) when you want by using these Shortcuts: + +- Keyboard Shortcut: `CTRL + Arrow Left/Right` + +### Voice Auto-Text + +This cheat will allow you to toggle the voice auto text feature while playing the game. By pressing the key combination you will be able to toggle the auto advance of text boxes as voice line finishes to play. + +Shortcuts: + +- Keyboard Shortcut: `CTRL + T` diff --git a/misc/CTNx.ambient.toml b/misc/CTNx.ambient.toml new file mode 100644 index 0000000..31d8110 --- /dev/null +++ b/misc/CTNx.ambient.toml @@ -0,0 +1,38 @@ +# CTNx Audio Engine config file - Ambient layer + +### HOW TO: ################################################################### +# Sections may be commented by default with an initial # character. +# Remove the initial # character to set the entire sections block and its flags +# ----------------------------------------------------------------------------- +# Syntax: +# [ID] +# flag = value +# another_flag = value +############################################################################### + +### SUPPORTED FLAGS: ########################################################## +# shuffle: Shuffle an SFX ID with one of the given IDs in the array. IDs MUST +# be numbers ONLY and MUST NOT contain any special character like - or _. +# This flag MUST NOT be used in pair with 'sequential'. +# ----------------------------------------------------------------------------- +# sequential: Sequentially playback an SFX ID with the ones provided in the +# array. IDs MUST be numbers ONLY and MUST NOT contain any special character +# like - or _. This flag MUST NOT be used in pair with 'shuffle'. +# ----------------------------------------------------------------------------- +# fade_in: Fade in the track on play. The value MUST be a floating point +# number and if 0.0 ( default ) then the track will NOT fade. +# ----------------------------------------------------------------------------- +# fade_out: Fade out the track on stop. The value MUST be a floating point +# number and if 0.0 ( default ) then the track will NOT fade. +# ----------------------------------------------------------------------------- +# volume: Allow volume to be adjusted for a specific track. +############################################################################### + +# Example +# ----------------------------------------------------------------------------- +#[field_123] +#shuffle = [ "field_121", "field_122", "field_124" ] +#sequential = [ "field_121", "field_122", "field_124" ] +#fade_in = 0.0 +#fade_out = 0.0 +#volume = 50 diff --git a/misc/CTNx.toml b/misc/CTNx.toml new file mode 100644 index 0000000..677fd40 --- /dev/null +++ b/misc/CTNx.toml @@ -0,0 +1,122 @@ +# CTNx config file + +######################### +# Audio Player Options +######################### + +#[NUMBER OF CHANNELS] +# This flag will set the number of channels you want to use. +# You can force a Stereo output ( 2.0 ) on a 7.1 system for example, by setting this flag to 2. +# The number MUST always be EVEN ( eg. 2, 4, 6, 8). If you have 5.1 set, then use 6 ( 5+1 ). If you have 7.1 set, then use 8 ( 7+1 ). +# NOTE: 0 = Autodetect. It will use the number of channels set in your audio card and/or inherited through audio software enhancements suites. +# WARNING: This flag WILL impact the OVERALL external audio layer ( Music, SFX, Voice, Ambient, etc.)! +external_audio_number_of_channels = 2 + +#[SAMPLE RATE] +# This flag will set the sample rate you want to use. +# The number MUST be one of the known sample rates values ( 44100, 48000, etc. ) +# NOTE: 0 = Autodetect. It will use the sample rate set in your audio card and/or inherited through audio software enhancements suites. +# WARNING: This flag WILL impact the OVERALL external audio layer ( Music, SFX, Voice, Ambient, etc.)! +external_audio_sample_rate = 44100 + +#[EXTERNAL VOICE PATH] +# Path of the external voice files +#~~~~~~~~~~~~~~~~~~~~~~~~~~~ +external_voice_path = "voice" + +#[EXTERNAL VOICE EXTENSION] +# The type of file to search for. By default is ogg. +# You can use a list to specify multiple extensions, ordered by priority. +# Example: ["ogg", "flac"] +# Supported extensions: +# - https://github.com/losnoco/vgmstream#supported-file-types +#~~~~~~~~~~~~~~~~~~~~~~~~~~~ +external_voice_ext = "ogg" + +#[EXTERNAL VOICE VOLUME] +# This setting will allow you to configure the volume of the Voice layer. +# Possible values: 0..100 +# If -1, the volume will be set to 100% +external_voice_volume = -1 + +#[ENABLE VOICE MUSIC FADE] +# This flag will enable the music volume fade out and fade in, when a voice acting is being played back. +# Please note this flag will take effect ONLY when "use_external_music" is enabled. +#~~~~~~~~~~~~~~~~~~~~~~~~~~~ +enable_voice_music_fade = false + +#[EXTERNAL VOICE MUSIC FADE VOLUME] +# This flag will set to how much the volume will be lowered down when a voice acting is going to be played back. When the voice file will be finished, the music volume will be then restored to its previous value. +# Range: 0-100 ( Min = 0, Max = 100) +#~~~~~~~~~~~~~~~~~~~~~~~~~~~ +external_voice_music_fade_volume = 25 + +#[ENABLE VOICE AUTO TEXT] +# This will allow you to enable or disable the Voice Auto-Text feature. When enabled the game will automatically close the dialogue as soon as the voice acting is finished for that line. +enable_voice_auto_text = true + +#[EXTERNAL AMBIENT PATH] +# Path of the external ambient files +#~~~~~~~~~~~~~~~~~~~~~~~~~~~ +external_ambient_path = "ambient" + +#[EXTERNAL AMBIENT EXTENSION] +# The type of file to search for. By default is ogg. +# You can use a list to specify multiple extensions, ordered by priority. +# Example: ["ogg", "flac"] +# Supported extensions: +# - https://github.com/losnoco/vgmstream#supported-file-types +#~~~~~~~~~~~~~~~~~~~~~~~~~~~ +external_ambient_ext = "ogg" + +#[EXTERNAL AMBIENT VOLUME] +# This setting will allow you to configure the volume of the Ambient layer. +# Possible values: 0..100 +# If -1, the volume will be set to 100% +external_ambient_volume = -1 + +######################## +## MODDER OPTIONS +######################## + +# This path is where the Hext patching layer will look for txt files. +# The path will ALWAYS have appended the game language. +# The resulting path will then be "/en", if you run for eg. the English language +#~~~~~~~~~~~~~~~~~~~~~~~~~~~ +hext_patching_path = "hext" + +#[SPEEDHACK] +# Set the step when increasing the speedhack speed +#~~~~~~~~~~~~~~~~~~~~~~~~~~ +speedhack_step = 0.5 + +# Set the limit of the speedhack multiplier +#~~~~~~~~~~~~~~~~~~~~~~~~~~ +speedhack_max = 8.0 +speedhack_min = 1.0 + +########################## +# DEBUGGING OPTIONS +# These options are mostly useful for developers or people reporting crashes. +# Please do enable them only when required. +########################## + +# Show game debug logs +#~~~~~~~~~~~~~~~~~~~~~~~~~~~ +show_applog = true + +# trace_all - Dump in the logs whatever APIs is being called from the Engine in CTNx. Overrides all the others below. +#~~~~~~~~~~~~~~~~~~~~~~~~~~~ +trace_all = false + +# trace_voice - Dump in the logs only APIs that has to do with voice playback +#~~~~~~~~~~~~~~~~~~~~~~~~~~~ +trace_voice = false + +# trace_ambient - Dump in the logs only APIs that has to do with ambient playback +#~~~~~~~~~~~~~~~~~~~~~~~~~~~ +trace_ambient = false + +# Creates a full crashdump file if the game crashes. Useful to be analyzed with WinDbg when reporting issues. +#~~~~~~~~~~~~~~~~~~~~~~~~~~~ +create_crash_dump = false diff --git a/misc/CTNx.voice.toml b/misc/CTNx.voice.toml new file mode 100644 index 0000000..473fb0a --- /dev/null +++ b/misc/CTNx.voice.toml @@ -0,0 +1,32 @@ +# CTNx Audio Engine config file - Voice layer + +### HOW TO: ################################################################### +# Sections may be commented by default with an initial # character. +# Remove the initial # character to set the entire sections block and its flags +# ----------------------------------------------------------------------------- +# Syntax: +# [FIELDNAME] +# flag = value +# another_flag = value +# ----------------------------------------------------------------------------- +# where: +# - FIELDNAME: the current field name, for eg. 'field_123' +############################################################################### + +### SUPPORTED FLAGS: ########################################################## +# volume: Allow volume to be adjusted for a specific track. +# ----------------------------------------------------------------------------- +# shuffle: Shuffle a voice track with any of the given one in the array. Each +# item MUST be a string. This flag MUST NOT be used in pair with 'sequential'. +# ----------------------------------------------------------------------------- +# sequential: Sequentially playback a voice track with the ones provided in the +# array. Each item MUST be a string. This flag MUST NOT be used in pair with +# 'shuffle'. +############################################################################### + +# This entry will set the volume to 50% +# ----------------------------------------------------------------------------- +#[field_123] +#volume = 50 +#shuffle = [ "foo", "bar" ] +#sequential = [ "foo", "bar" ] diff --git a/misc/hext/de/.gitkeep b/misc/hext/de/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/misc/hext/en/.gitkeep b/misc/hext/en/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/misc/hext/es/.gitkeep b/misc/hext/es/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/misc/hext/fr/.gitkeep b/misc/hext/fr/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/misc/hext/it/.gitkeep b/misc/hext/it/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/misc/hext/ja/.gitkeep b/misc/hext/ja/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/misc/hext/ko/.gitkeep b/misc/hext/ko/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/misc/hext/zh-hans/.gitkeep b/misc/hext/zh-hans/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/misc/hext/zh-hant/.gitkeep b/misc/hext/zh-hant/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/misc/version.rc.in b/misc/version.rc.in new file mode 100644 index 0000000..49a05ba --- /dev/null +++ b/misc/version.rc.in @@ -0,0 +1,64 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#include + +#define VER_FILEVERSION @_DLL_RCVERSION@ +#define VER_FILEVERSION_STR "@_DLL_RCSTRVERSION@\0" + +#define VER_PRODUCTVERSION @_DLL_RCVERSION@ +#define VER_PRODUCTVERSION_STR "@_DLL_RCSTRVERSION@\0" + +#define VER_INTERNALNAME "@RELEASE_NAME@" +#define VER_PRODUCTNAME "@RELEASE_NAME@" +#define VER_ORIGINALFILENAME "@RELEASE_NAME@.dll" + +VS_VERSION_INFO VERSIONINFO +FILEVERSION VER_FILEVERSION +PRODUCTVERSION VER_PRODUCTVERSION +FILEOS VOS__WINDOWS32 +FILETYPE VFT_DLL +FILESUBTYPE VFT2_UNKNOWN +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "CompanyName", "Tsunamods" + VALUE "FileDescription", "Next generation modding platform for Chrono Trigger ( native Steam 2018 release support! )" + VALUE "FileVersion", VER_FILEVERSION_STR + VALUE "InternalName", VER_INTERNALNAME + VALUE "LegalCopyright", "GPLv3" + VALUE "LegalTrademarks1", "" + VALUE "LegalTrademarks2", "" + VALUE "OriginalFilename", VER_ORIGINALFILENAME + VALUE "ProductName", VER_PRODUCTNAME + VALUE "ProductVersion", VER_PRODUCTVERSION_STR + END + END + + BLOCK "VarFileInfo" + BEGIN + /* The following line should only be modified for localized versions. */ + /* It consists of any number of WORD,WORD pairs, with each pair */ + /* describing a language,codepage combination supported by the file. */ + /* */ + /* For example, a file might have values "0x409,1252" indicating that it */ + /* supports English language (0x409) in the Windows ANSI codepage (1252). */ + + VALUE "Translation", 0x409, 1252 + + END +END diff --git a/src/audio.cpp b/src/audio.cpp new file mode 100644 index 0000000..9a177f2 --- /dev/null +++ b/src/audio.cpp @@ -0,0 +1,493 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#include "audio.h" +#include "utils.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#include + +#if defined(__cplusplus) +} +#endif + +NxAudioEngine nxAudioEngine; + +// PRIVATE + +void NxAudioEngine::loadConfig() +{ + char _fullpath[MAX_PATH]; + + for (int idx = NxAudioEngineLayer::NXAUDIOENGINE_VOICE; idx <= NxAudioEngineLayer::NXAUDIOENGINE_AMBIENT; idx++) + { + NxAudioEngineLayer type = NxAudioEngineLayer(idx); + + switch (type) + { + case NxAudioEngineLayer::NXAUDIOENGINE_VOICE: + sprintf(_fullpath, "%s/%s/config.toml", basedir, external_voice_path.c_str()); + if (trace_all || trace_voice) PLOGD.printf("NxAudioEngine::%s: %s\n", __func__, _fullpath); + break; + case NxAudioEngineLayer::NXAUDIOENGINE_AMBIENT: + sprintf(_fullpath, "%s/%s/config.toml", basedir, external_ambient_path.c_str()); + if (trace_all || trace_ambient) PLOGD.printf("NxAudioEngine::%s: %s\n", __func__, _fullpath); + break; + } + + try + { + nxAudioEngineConfig[type] = toml::parse_file(_fullpath); + } + catch (const toml::parse_error &err) + { + PLOGW.printf("Parse error while opening the file %s. Will continue with the default settings.\n", _fullpath); + PLOGW.printf("%s (Line %u Column %u)\n", err.what(), err.source().begin.line, err.source().begin.column); + + nxAudioEngineConfig[type] = toml::parse(""); + } + } +} + +bool NxAudioEngine::getFilenameFullPath(char *_out, const char* _key, NxAudioEngineLayer _type) +{ + std::vector extensions; + + switch(_type) + { + case NxAudioEngineLayer::NXAUDIOENGINE_VOICE: + extensions = external_voice_ext; + break; + case NxAudioEngineLayer::NXAUDIOENGINE_AMBIENT: + extensions = external_ambient_ext; + break; + } + + for (const std::string &extension: extensions) { + switch (_type) + { + case NxAudioEngineLayer::NXAUDIOENGINE_VOICE: + sprintf(_out, "%s/%s/%s.%s", basedir, external_voice_path.c_str(), _key, extension.c_str()); + break; + case NxAudioEngineLayer::NXAUDIOENGINE_AMBIENT: + sprintf(_out, "%s/%s/%s.%s", basedir, external_ambient_path.c_str(), _key, extension.c_str()); + break; + } + + if (fileExists(_out)) { + return true; + } + } + + return false; +} + +bool NxAudioEngine::fileExists(const char* filename) +{ + bool ret = ::fileExists(filename); + + if (!ret && (trace_all || trace_voice || trace_ambient)) + PLOGW.printf("NxAudioEngine::%s: Could not find file %s\n", __func__, filename); + + return ret; +} + +// PUBLIC + +bool NxAudioEngine::init() +{ + if (_engine.init(SoLoud::Soloud::CLIP_ROUNDOFF, SoLoud::Soloud::AUTO, external_audio_sample_rate, SoLoud::Soloud::AUTO, external_audio_number_of_channels) == 0) + { + _engineInitialized = true; + + PLOGI.printf("NxAudioEngine initialized: channels=%u,sample_rate=%u\n", _engine.getBackendChannels(), _engine.getBackendSamplerate()); + + // 100 -> LOG_LEVEL_ALL: https://github.com/vgmstream/vgmstream/blob/4cda04d02595b381dc8cf98ec39e771c80987d18/src/util/log.c#L20 + if (trace_all || trace_ambient || trace_voice) vgm_log_set_callback(NULL, 100, 0, NxAudioEngineVgmstreamCallback); + + loadConfig(); + + return true; + } + + return false; +} + +void NxAudioEngine::flush() +{ + _engine.stopAll(); + + for (int slot = 0; slot < _voiceMaxSlots; slot++) + { + _currentVoice[slot] = NxAudioEngineVoice(); + } + + _currentAmbient = NxAudioEngineAmbient(); +} + +void NxAudioEngine::cleanup() +{ + _engine.deinit(); +} + +// Voice +bool NxAudioEngine::canPlayVoice(const char* name) +{ + char filename[MAX_PATH]; + + return getFilenameFullPath(filename, name, NxAudioEngineLayer::NXAUDIOENGINE_VOICE); +} + +bool NxAudioEngine::playVoice(const char* name, int slot, float volume) +{ + char filename[MAX_PATH]; + + bool exists = false; + + _currentVoice[slot].volume = volume * getVoiceMasterVolume(); + + std::string _name(name); + // TOML doesn't like the / char as key, replace it with - ( one of the valid accepted chars ) + replaceAll(_name, '/', '-'); + + auto node = nxAudioEngineConfig[NxAudioEngineLayer::NXAUDIOENGINE_VOICE][_name]; + if (node) + { + // Set volume for the current track + toml::node *trackVolume = node["volume"].as_integer(); + if (trackVolume) + { + _currentVoice[slot].volume = (trackVolume->value_or(100) / 100.0f) * getVoiceMasterVolume(); + } + + // Shuffle Voice playback, if any entry found for the current id + toml::array *shuffleNames = node["shuffle"].as_array(); + if (shuffleNames && !shuffleNames->empty() && shuffleNames->is_homogeneous(toml::node_type::string)) + { + auto _newName = shuffleNames->get(getRandomInt(0, shuffleNames->size() - 1)); + + exists = getFilenameFullPath(filename, _newName->value_or(name), NxAudioEngineLayer::NXAUDIOENGINE_VOICE); + } + + // Sequentially playback new voice items, if any entry found for the current id + toml::array *sequentialNames = node["sequential"].as_array(); + if (sequentialNames && !sequentialNames->empty() && sequentialNames->is_homogeneous(toml::node_type::string)) + { + if (_voiceSequentialIndexes.find(name) == _voiceSequentialIndexes.end() || _voiceSequentialIndexes[name] >= sequentialNames->size()) + _voiceSequentialIndexes[name] = 0; + + auto _newName = sequentialNames->get(_voiceSequentialIndexes[name]); + + _voiceSequentialIndexes[name]++; + + exists = getFilenameFullPath(filename, _newName->value_or(name), NxAudioEngineLayer::NXAUDIOENGINE_VOICE); + } + } + + // If none of the previous configurations worked, load the default one as last tentative + if (!exists) { + exists = getFilenameFullPath(filename, name, NxAudioEngineLayer::NXAUDIOENGINE_VOICE); + } + + if (trace_all || trace_voice) PLOGD.printf("NxAudioEngine::%s: slot[%d] %s exists=%d\n", __func__, slot, filename, exists); + + if (exists) + { + // Stop any previously playing voice + if (_engine.isValidVoiceHandle(_currentVoice[slot].handle)) + { + _engine.stop(_currentVoice[slot].handle); + + delete _currentVoice[slot].stream; + + _currentVoice[slot].handle = NXAUDIOENGINE_INVALID_HANDLE; + } + + _currentVoice[slot].stream = new SoLoud::VGMStream(); + + SoLoud::result res = _currentVoice[slot].stream->load(filename); + if (res != SoLoud::SO_NO_ERROR) { + PLOGE.printf("NxAudioEngine::%s: Cannot load %s with vgmstream ( SoLoud error: %u )\n", __func__, filename, res); + delete _currentVoice[slot].stream; + return false; + } + + _currentVoice[slot].handle = _engine.play(*_currentVoice[slot].stream, _currentVoice[slot].volume); + + return _engine.isValidVoiceHandle(_currentVoice[slot].handle); + } + else + return false; +} + +void NxAudioEngine::stopVoice(int slot, double time) +{ + SoLoud::handle handle = _currentVoice[slot].handle; + + if (trace_all || trace_voice) PLOGD.printf("NxAudioEngine::%s: slot=%d time=%lf handle=%X\n", __func__, slot, time, handle); + + if (!_engine.isValidVoiceHandle(handle)) + { + return; + } + + if (time > 0.0) + { + _engine.fadeVolume(handle, 0, time); + _engine.scheduleStop(handle, time); + } + else + { + _engine.stop(handle); + } +} + +void NxAudioEngine::pauseVoice(int slot, double time) +{ + if (time > 0.0) + { + _engine.fadeVolume(_currentVoice[slot].handle, 0, time); + _engine.schedulePause(_currentVoice[slot].handle, time); + } + else + { + _engine.setPause(_currentVoice[slot].handle, true); + } +} + +void NxAudioEngine::resumeVoice(int slot, double time) +{ + if (time > 0.0) + { + _engine.setPause(_currentVoice[slot].handle, false); + _engine.fadeVolume(_currentVoice[slot].handle, _currentVoice[slot].volume, time); + } + else + { + _engine.setVolume(_currentVoice[slot].handle, _currentVoice[slot].volume); + _engine.setPause(_currentVoice[slot].handle, false); + } +} + +bool NxAudioEngine::isVoicePlaying(int slot) +{ + return _engine.isValidVoiceHandle(_currentVoice[slot].handle) && !_engine.getPause(_currentVoice[slot].handle); +} + +void NxAudioEngine::setVoiceMaxSlots(int slot) +{ + _voiceMaxSlots = slot; +} + +float NxAudioEngine::getVoiceMasterVolume() +{ + return _voiceMasterVolume < 0.0f ? 1.0f : _voiceMasterVolume; +} + +void NxAudioEngine::setVoiceMasterVolume(float volume, double time) +{ + _voiceMasterVolume = volume; +} + +// Ambient +bool NxAudioEngine::canPlayAmbient(const char* name) +{ + char filename[MAX_PATH]; + + return getFilenameFullPath(filename, name, NxAudioEngineLayer::NXAUDIOENGINE_AMBIENT); +} + +bool NxAudioEngine::playAmbient(const char* name, float volume, double time) +{ + char filename[MAX_PATH]; + bool exists = false; + + // Reset state + _currentAmbient.fade_in = 0.0f; + _currentAmbient.fade_out = 0.0f; + _currentAmbient.volume = volume * getAmbientMasterVolume(); + + auto node = nxAudioEngineConfig[NxAudioEngineLayer::NXAUDIOENGINE_AMBIENT][name]; + if (node) + { + // Shuffle Ambient playback, if any entry found for the current id + toml::array *shuffleIds = node["shuffle"].as_array(); + if (shuffleIds && !shuffleIds->empty() && shuffleIds->is_homogeneous(toml::node_type::string)) + { + auto _newName = shuffleIds->get(getRandomInt(0, shuffleIds->size() - 1)); + + exists = getFilenameFullPath(filename, _newName->value_or(""), NxAudioEngineLayer::NXAUDIOENGINE_AMBIENT); + } + + // Sequentially playback new Ambient ids, if any entry found for the current id + toml::array *sequentialIds = node["sequential"].as_array(); + if (sequentialIds && !sequentialIds->empty() && sequentialIds->is_homogeneous(toml::node_type::string)) + { + // If the key doesn't exist already, add it + if (_ambientSequentialIndexes.count(name) == 0) _ambientSequentialIndexes[name] = NULL; + + if (_ambientSequentialIndexes.find(name) == _ambientSequentialIndexes.end() || _ambientSequentialIndexes[name] >= sequentialIds->size()) + _ambientSequentialIndexes[name] = 0; + + auto _newName = sequentialIds->get(_ambientSequentialIndexes[name]); + + _ambientSequentialIndexes[name]++; + + exists = getFilenameFullPath(filename, _newName->value_or(""), NxAudioEngineLayer::NXAUDIOENGINE_AMBIENT); + } + + // Fade In time for this track, if configured + toml::node *fadeInTime = node["fade_in"].as_floating_point(); + if (fadeInTime) + { + _currentAmbient.fade_in = fadeInTime->value_or(0.0f); + + time = _currentAmbient.fade_in; + } + + // Fade Out time for this track, if configured + toml::node *fadeOutTime = node["fade_out"].as_floating_point(); + if (fadeOutTime) + { + _currentAmbient.fade_out = fadeOutTime->value_or(0.0f); + } + + // Set volume for the current ambient + toml::node *ambientVolume = node["volume"].as_integer(); + if (ambientVolume) + { + _currentAmbient.volume = (ambientVolume->value_or(100) / 100.0f) * getAmbientMasterVolume(); + } + } + + // If none of the previous configurations worked, load the default one as last tentative + if (!exists) { + exists = getFilenameFullPath(filename, name, NxAudioEngineLayer::NXAUDIOENGINE_AMBIENT); + } + + if (trace_all || trace_ambient) PLOGD.printf("NxAudioEngine::%s: %s exists=%d handle=%X\n", __func__, filename, exists, _currentAmbient.handle); + + if (exists) + { + // Stop any previously playing ambient + if (_engine.isValidVoiceHandle(_currentAmbient.handle)) + { + _engine.stop(_currentAmbient.handle); + + delete _currentAmbient.stream; + + _currentAmbient.handle = NXAUDIOENGINE_INVALID_HANDLE; + } + + _currentAmbient.stream = new SoLoud::VGMStream(); + + SoLoud::result res = _currentAmbient.stream->load(filename); + if (res != SoLoud::SO_NO_ERROR) { + PLOGE.printf("NxAudioEngine::%s: Cannot load %s with vgmstream ( SoLoud error: %u )\n", __func__, filename, res); + delete _currentAmbient.stream; + return false; + } + + _currentAmbient.handle = _engine.play(*_currentAmbient.stream, time > 0.0f ? 0.0f : _currentAmbient.volume, 0.0f, time > 0.0f); + + if (time > 0.0f) resumeAmbient(time); + + return _engine.isValidVoiceHandle(_currentAmbient.handle); + } + else + return false; +} + +void NxAudioEngine::stopAmbient(double time) +{ + if (_currentAmbient.fade_out > 0.0f) + { + time = _currentAmbient.fade_out; + + if (trace_all || trace_ambient) PLOGD.printf("NxAudioEngine::%s: time=%f ( overridden through config.toml )\n", __func__, time); + } + else if (trace_all || trace_ambient) PLOGD.printf("NxAudioEngine::%s: time=%f\n", __func__, time); + + if (time > 0.0) + { + _engine.fadeVolume(_currentAmbient.handle, 0, time); + _engine.scheduleStop(_currentAmbient.handle, time); + } + else + { + _engine.stop(_currentAmbient.handle); + } +} + +void NxAudioEngine::pauseAmbient(double time) +{ + if (_currentAmbient.fade_out > 0.0f) + { + time = _currentAmbient.fade_out; + + if (trace_all || trace_ambient) PLOGD.printf("NxAudioEngine::%s: time=%f ( overridden through config.toml )\n", __func__, time); + } + else if (trace_all || trace_ambient) PLOGD.printf("NxAudioEngine::%s: time=%f\n", __func__, time); + + if (time > 0.0) + { + _engine.fadeVolume(_currentAmbient.handle, 0, time); + _engine.schedulePause(_currentAmbient.handle, time); + } + else + { + _engine.setPause(_currentAmbient.handle, true); + } +} + +void NxAudioEngine::resumeAmbient(double time) +{ + if (_currentAmbient.fade_in > 0.0f) + { + time = _currentAmbient.fade_in; + + if (trace_all || trace_ambient) PLOGD.printf("NxAudioEngine::%s: time=%f ( overridden through config.toml )\n", __func__, time); + } + else if (trace_all || trace_ambient) PLOGD.printf("NxAudioEngine::%s: time=%f\n", __func__, time); + + if (time > 0.0) + { + _engine.setPause(_currentAmbient.handle, false); + _engine.fadeVolume(_currentAmbient.handle, _currentAmbient.volume, time); + } + else + { + _engine.setVolume(_currentAmbient.handle, _currentAmbient.volume); + _engine.setPause(_currentAmbient.handle, false); + } +} + +bool NxAudioEngine::isAmbientPlaying() +{ + return _engine.isValidVoiceHandle(_currentAmbient.handle) && !_engine.getPause(_currentAmbient.handle); +} + +float NxAudioEngine::getAmbientMasterVolume() +{ + return _ambientMasterVolume < 0.0f ? 1.0f : _ambientMasterVolume; +} + +void NxAudioEngine::setAmbientMasterVolume(float volume, double time) +{ + _ambientMasterVolume = volume; +} diff --git a/src/audio.h b/src/audio.h new file mode 100644 index 0000000..2650e15 --- /dev/null +++ b/src/audio.h @@ -0,0 +1,122 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#pragma once + +#include +#include +#include +#include +#include +#include "audio/vgmstream/vgmstream.h" +#include "globals.h" + +#define NXAUDIOENGINE_INVALID_HANDLE 0xfffff000 + +static void NxAudioEngineVgmstreamCallback(int level, const char* str) +{ + PLOGI.printf("VGMStream [L%d]: %s\n", level, str); +} + +class NxAudioEngine +{ +public: + struct NxAudioEngineVoice + { + NxAudioEngineVoice() : + handle(NXAUDIOENGINE_INVALID_HANDLE), + stream(nullptr), + volume(1.0f) {} + SoLoud::handle handle; + SoLoud::VGMStream* stream; + float volume; + }; + + struct NxAudioEngineAmbient + { + NxAudioEngineAmbient() : + handle(NXAUDIOENGINE_INVALID_HANDLE), + stream(nullptr), + volume(1.0f), + fade_in(0.0f), + fade_out(0.0f) {} + SoLoud::handle handle; + SoLoud::VGMStream* stream; + float volume; + double fade_in; + double fade_out; + }; + +private: + enum NxAudioEngineLayer + { + NXAUDIOENGINE_VOICE, + NXAUDIOENGINE_AMBIENT + }; + + bool _engineInitialized = false; + SoLoud::Soloud _engine; + + // VOICE + short _voiceMaxSlots = 0; + float _voiceMasterVolume = -1.0f; + std::map _currentVoice; + std::map _voiceSequentialIndexes; + + // AMBIENT + float _ambientMasterVolume = -1.0f; + std::map _ambientSequentialIndexes; + NxAudioEngineAmbient _currentAmbient; + + // MISC + // Returns false if the file does not exist + bool getFilenameFullPath(char *_out, const char* _key, NxAudioEngineLayer _type); + + bool fileExists(const char* filename); + + // CFG + std::unordered_map nxAudioEngineConfig; + + void loadConfig(); + +public: + + bool init(); + void flush(); + void cleanup(); + + // Voice + bool canPlayVoice(const char* name); + bool playVoice(const char* name, int slot = 0, float volume = 1.0f); + void stopVoice(int slot = 0, double time = 0); + void pauseVoice(int slot = 0, double time = 0); + void resumeVoice(int slot = 0, double time = 0); + bool isVoicePlaying(int slot = 0); + void setVoiceMaxSlots(int slot); + float getVoiceMasterVolume(); + void setVoiceMasterVolume(float volume, double time = 0); + + // Ambient + bool canPlayAmbient(const char* name); + bool playAmbient(const char* name, float volume = 1.0f, double time = 0); + void stopAmbient(double time = 0); + void pauseAmbient(double time = 0); + void resumeAmbient(double time = 0); + bool isAmbientPlaying(); + float getAmbientMasterVolume(); + void setAmbientMasterVolume(float volume, double time = 0); +}; + +extern NxAudioEngine nxAudioEngine; diff --git a/src/audio/vgmstream/vgmstream.cpp b/src/audio/vgmstream/vgmstream.cpp new file mode 100644 index 0000000..1d5601b --- /dev/null +++ b/src/audio/vgmstream/vgmstream.cpp @@ -0,0 +1,163 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#include "vgmstream.h" +#include "../../utils.h" + +namespace SoLoud +{ + VGMStreamInstance::VGMStreamInstance(VGMStream* aParent) + { + mParent = aParent; + mStreamBuffer = new sample_t[SAMPLE_GRANULARITY * aParent->mChannels]; + + rewind(); + } + + VGMStreamInstance::~VGMStreamInstance() + { + delete[] mStreamBuffer; + } + + unsigned int VGMStreamInstance::getAudio(float* aBuffer, unsigned int aSamplesToRead, unsigned int aBufferSize) + { + memset(mStreamBuffer, 0, sizeof(sample_t) * SAMPLE_GRANULARITY * mChannels); + int sample_count = render_vgmstream(mStreamBuffer, aSamplesToRead, mParent->mStream); + + for (int j = 0; j < sample_count; j++) + { + for (unsigned int k = 0; k < mChannels; k++) + { + aBuffer[k * aSamplesToRead + j] = mStreamBuffer[(j * mChannels) + k] / (float)INT16_MAX; + } + } + + mOffset += sample_count; + + // If the song is looping, recalculate the offset correctly + if (mFlags & AudioSourceInstance::LOOPING) { + if (mOffset >= mParent->mStream->loop_end_sample) + { + mOffset = mOffset - mParent->mSampleCount + mParent->mStream->loop_start_sample; + } + } + + return sample_count; + } + + result VGMStreamInstance::rewind() + { + reset_vgmstream(mParent->mStream); + + mOffset = 0; + mStreamPosition = 0.0f; + return SO_NO_ERROR; + } + + result VGMStreamInstance::seek(double aSeconds, float* mScratch, unsigned int mScratchSize) + { + mOffset = int(floor(mSamplerate * aSeconds)); + + seek_vgmstream(mParent->mStream, mOffset); + + mStreamPosition = aSeconds; + return SO_NO_ERROR; + } + + bool VGMStreamInstance::hasEnded() + { + if (!(mFlags & AudioSourceInstance::LOOPING) && mOffset >= mParent->mSampleCount) + { + return 1; + } + return 0; + } + + VGMStream::VGMStream() + { + mSampleCount = 0; + } + + VGMStream::~VGMStream() + { + stop(); + + close_vgmstream(mStream); + } + + VGMSTREAM* VGMStream::init_vgmstream_with_extension(const char* aFilename, const char* ext) + { + STREAMFILE* streamFile = open_stdio_streamfile(aFilename); + if (streamFile == nullptr) { + return nullptr; + } + // Force extension + streamFile = open_fakename_streamfile_f(streamFile, nullptr, ext); + if (streamFile == nullptr) { + return nullptr; + } + VGMSTREAM* stream = init_vgmstream_from_STREAMFILE(streamFile); + close_streamfile(streamFile); + return stream; + } + + result VGMStream::load(const char* aFilename, const char* ext) + { + mBaseSamplerate = 0; + + if (aFilename == 0) + return INVALID_PARAMETER; + + if (! fileExists(aFilename)) + return FILE_NOT_FOUND; + + stop(); + + if (ext && ext[0] != '\0') { + mStream = init_vgmstream_with_extension(aFilename, ext); + } + else { + mStream = init_vgmstream(aFilename); + } + + if (mStream == nullptr) { + return FILE_LOAD_FAILED; + } + + mBaseSamplerate = (float)mStream->sample_rate; + mSampleCount = (unsigned int)mStream->num_samples; + mChannels = mStream->channels; + + // Autodetect looping from the file itself and just inform SoLoud about it + if (mStream->loop_flag) setLooping(true); + // If the file has no loop tags, but the users wants to loop, force a basic start to end loop + else if (mFlags & AudioSourceInstance::LOOPING) vgmstream_force_loop(mStream, true, 0, mStream->num_samples); + + return SO_NO_ERROR; + } + + AudioSourceInstance* VGMStream::createInstance() + { + return new VGMStreamInstance(this); + } + + double VGMStream::getLength() + { + if (mBaseSamplerate == 0) + return 0; + + return mSampleCount / mBaseSamplerate; + } +}; diff --git a/src/audio/vgmstream/vgmstream.h b/src/audio/vgmstream/vgmstream.h new file mode 100644 index 0000000..444cabc --- /dev/null +++ b/src/audio/vgmstream/vgmstream.h @@ -0,0 +1,62 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#pragma once + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +#include + +#if defined(__cplusplus) +} +#endif + +namespace SoLoud +{ + class VGMStream : public AudioSource + { + static VGMSTREAM* init_vgmstream_with_extension(const char* aFilename, const char* ext); + public: + VGMSTREAM* mStream; + unsigned int mSampleCount; + + sample_t* mData; + + VGMStream(); + virtual ~VGMStream(); + result load(const char* aFilename, const char* ext = nullptr); + + virtual AudioSourceInstance* createInstance(); + time getLength(); + }; + + class VGMStreamInstance : public AudioSourceInstance + { + sample_t* mStreamBuffer; + VGMStream* mParent; + unsigned int mOffset; + public: + VGMStreamInstance(VGMStream* aParent); + virtual ~VGMStreamInstance(); + virtual unsigned int getAudio(float* aBuffer, unsigned int aSamplesToRead, unsigned int aBufferSize); + virtual result rewind(); + virtual result seek(double aSeconds, float *mScratch, unsigned int mScratchSize); + virtual bool hasEnded(); + }; +}; diff --git a/src/cfg.cpp b/src/cfg.cpp new file mode 100644 index 0000000..04365c5 --- /dev/null +++ b/src/cfg.cpp @@ -0,0 +1,177 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#include + +#include "cfg.h" +#include "globals.h" + +#define CTNx_CFG_FILE "CTNx.toml" + +// configuration variables with their default values +std::string external_voice_path; +std::vector external_voice_ext; +std::string external_ambient_path; +std::vector external_ambient_ext; +bool enable_voice_music_fade; +long external_voice_music_fade_volume; +bool enable_voice_auto_text; +bool show_applog; +bool trace_all; +bool trace_voice; +bool trace_ambient; +bool create_crash_dump; +std::string hext_patching_path; +double speedhack_step; +double speedhack_max; +double speedhack_min; +long external_audio_number_of_channels; +long external_audio_sample_rate; +long external_voice_volume; +long external_ambient_volume; + +std::vector get_string_or_array_of_strings(const toml::node_view &node) +{ + if (node.is_array()) { + toml::array* a = node.as_array(); + if (a && a->is_homogeneous(toml::node_type::string)) { + std::vector ret; + ret.reserve(a->size()); + for (toml::node &elem: *a) { + ret.push_back(elem.value_or("")); + } + return ret; + } + } + + return std::vector(1, node.value_or("")); +} + +void read_cfg() +{ + toml::parse_result config; + + try + { + config = toml::parse_file(CTNx_CFG_FILE); + } + catch (const toml::parse_error &err) + { + PLOGW.printf("Parse error while opening the file " CTNx_CFG_FILE ". Will continue with the default settings.\n"); + PLOGW.printf("%s (Line %u Column %u)\n", err.what(), err.source().begin.line, err.source().begin.column); + + char tmp[1024]{0}; + sprintf(tmp, "%s (Line %u Column %u)\n\nWill continue with safe default settings.", err.what(), err.source().begin.line, err.source().begin.column); + MessageBoxA(NULL, tmp, "Configuration issue detected!", MB_ICONWARNING | MB_OK); + + config = toml::parse(""); + } + + // Read config values + external_voice_path = config["external_voice_path"].value_or(""); + external_voice_ext = get_string_or_array_of_strings(config["external_voice_ext"]); + enable_voice_music_fade = config["enable_voice_music_fade"].value_or(false); + external_voice_music_fade_volume = config["external_voice_music_fade_volume"].value_or(25); + enable_voice_auto_text = config["enable_voice_auto_text"].value_or(true); + external_ambient_path = config["external_ambient_path"].value_or(""); + external_ambient_ext = get_string_or_array_of_strings(config["external_ambient_ext"]); + show_applog = config["show_applog"].value_or(true); + trace_all = config["trace_all"].value_or(false); + trace_voice = config["trace_voice"].value_or(false); + trace_ambient = config["trace_ambient"].value_or(false); + create_crash_dump = config["create_crash_dump"].value_or(false); + hext_patching_path = config["hext_patching_path"].value_or(""); + speedhack_step = config["speedhack_step"].value_or(0.5); + speedhack_max = config["speedhack_max"].value_or(8.0); + speedhack_min = config["speedhack_min"].value_or(1.0); + external_audio_number_of_channels = config["external_audio_number_of_channels"].value_or(2); + external_audio_sample_rate = config["external_audio_sample_rate"].value_or(44100); + external_voice_volume = config["external_voice_volume"].value_or(-1); + external_ambient_volume = config["external_ambient_volume"].value_or(-1); + + // Normalize voice music fade volume + if (external_voice_music_fade_volume < 0) external_voice_music_fade_volume = 0; + if (external_voice_music_fade_volume > 100) external_voice_music_fade_volume = 100; + + // ############# + // SAFE DEFAULTS + // ############# + + if (hext_patching_path.empty()) + { + hext_patching_path = "hext"; + } + + switch(*game_externals.language_id) + { + case GAME_LANGUAGE_JA: + hext_patching_path += "/ja"; + break; + case GAME_LANGUAGE_EN: + hext_patching_path += "/en"; + break; + case GAME_LANGUAGE_DE: + hext_patching_path += "/de"; + break; + case GAME_LANGUAGE_IT: + hext_patching_path += "/it"; + break; + case GAME_LANGUAGE_FR: + hext_patching_path += "/fr"; + break; + case GAME_LANGUAGE_ZH_HANS: + hext_patching_path += "/zh-hans"; + break; + case GAME_LANGUAGE_ZH_HANT: + hext_patching_path += "/zh-hant"; + break; + case GAME_LANGUAGE_KO: + hext_patching_path += "/ko"; + break; + } + + // EXTERNAL VOICE PATH + if (external_voice_path.empty()) + external_voice_path = "voice"; + + // EXTERNAL VOICE EXTENSION + if (external_voice_ext.empty() || external_voice_ext.front().empty()) + external_voice_ext = std::vector(1, "ogg"); + + // EXTERNAL AMBIENT PATH + if (external_ambient_path.empty()) + external_ambient_path = "ambient"; + + // EXTERNAL AMBIENT EXTENSION + if (external_ambient_ext.empty() || external_ambient_ext.front().empty()) + external_ambient_ext = std::vector(1, "ogg"); + + // AUDIO NUMBER OF CHANNELS + if (external_audio_number_of_channels < 0) + external_audio_number_of_channels = 0; + else if (external_audio_number_of_channels % 2 != 0) + // Round to the previous even number + external_audio_number_of_channels--; + + // AUDIO SAMPLE RATE + if (external_audio_sample_rate < 0) + external_audio_sample_rate = 0; + + // VOLUME + if (external_voice_volume < 0) external_voice_volume = 0; + if (external_ambient_volume < 0) external_ambient_volume = 0; + if (external_voice_volume > 100) external_voice_volume = 100; + if (external_ambient_volume > 100) external_ambient_volume = 100; +} diff --git a/src/cfg.h b/src/cfg.h new file mode 100644 index 0000000..f46d422 --- /dev/null +++ b/src/cfg.h @@ -0,0 +1,59 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#pragma once + +#include +#include + +#define RENDERER_BACKEND_AUTO 0 +#define RENDERER_BACKEND_OPENGL 1 +// Slot 2 used to be used for DIRECT3D9 but is not more officially supported by bgfx. +// Preserve the slot numbers as they are to ensure compatibility with existing installations and tooling. +#define RENDERER_BACKEND_DIRECT3D11 3 +#define RENDERER_BACKEND_DIRECT3D12 4 +#define RENDERER_BACKEND_VULKAN 5 + +#define FPS_LIMITER_ORIGINAL 0 +#define FPS_LIMITER_DEFAULT 1 +#define FPS_LIMITER_30FPS 2 +#define FPS_LIMITER_60FPS 3 + +#define GAME_LIGHTING_ORIGINAL 0 +#define GAME_LIGHTING_PER_VERTEX 1 +#define GAME_LIGHTING_PER_PIXEL 2 + +extern std::string external_voice_path; +extern std::vector external_voice_ext; +extern std::string external_ambient_path; +extern std::vector external_ambient_ext; +extern bool enable_voice_music_fade; +extern long external_voice_music_fade_volume; +extern bool enable_voice_auto_text; +extern bool show_applog; +extern bool trace_all; +extern bool trace_voice; +extern bool trace_ambient; +extern bool create_crash_dump; +extern std::string hext_patching_path; +extern double speedhack_step; +extern double speedhack_max; +extern double speedhack_min; +extern long external_audio_number_of_channels; +extern long external_audio_sample_rate; +extern long external_voice_volume; +extern long external_ambient_volume; + +void read_cfg(); diff --git a/src/cocos2d.cpp b/src/cocos2d.cpp new file mode 100644 index 0000000..4e387a4 --- /dev/null +++ b/src/cocos2d.cpp @@ -0,0 +1,27 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#include "cocos2d.h" + +void show_popup_msg(std::string& text) +{ + auto currentScene = Director::getInstance()->getRunningScene(); + + if (currentScene) + { + auto textLayer = CTNxStatusLayer::create(text); + currentScene->addChild(textLayer, 1); + } +} diff --git a/src/cocos2d.h b/src/cocos2d.h new file mode 100644 index 0000000..4cb8d18 --- /dev/null +++ b/src/cocos2d.h @@ -0,0 +1,51 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#pragma once + +#include "globals.h" +class CTNxStatusLayer : public Layer { +public: + CTNxStatusLayer(const std::string& text) { + auto label = Label::createWithSystemFont(text, "Arial", 12); + + // Cyan color (R=0, G=255, B=255, A=255) + label->setTextColor(Color4B(0, 255, 255, 255)); + // Set label position at the bottom-left corner of the screen + label->setAnchorPoint(Vec2(0, 0)); + label->setPosition(Vec2(10, 10)); + + // Add the label to the layer + this->addChild(label, 1); + + // Make the layer disappear after 1 second + auto delay = DelayTime::create(1.0f); + auto remove = RemoveSelf::create(); + auto sequence = Sequence::create(delay, remove, nullptr); + this->runAction(sequence); + } + + static CTNxStatusLayer* create(const std::string& text) { + CTNxStatusLayer* ret = new CTNxStatusLayer(text); + if (ret) { + ret->autorelease(); + return ret; + } + CC_SAFE_DELETE(ret); + return nullptr; + } +}; + +void show_popup_msg(std::string& text); diff --git a/src/crashdump.cpp b/src/crashdump.cpp new file mode 100644 index 0000000..e732240 --- /dev/null +++ b/src/crashdump.cpp @@ -0,0 +1,95 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#include "crashdump.h" + +#include +#include "audio.h" + +LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS *ep) +{ + static uint32_t had_exception = false; + char filePath[260]{ 0 }; + + // give up if we crash again inside the exception handler (this function) + if(had_exception) + { + PLOGV.printf("ExceptionHandler: crash while running another ExceptionHandler. Exiting.\n"); + SetUnhandledExceptionFilter(0); + return EXCEPTION_CONTINUE_EXECUTION; + } + + PLOGD.printf("*** Exception 0x%x, address 0x%x ***\n", ep->ExceptionRecord->ExceptionCode, ep->ExceptionRecord->ExceptionAddress); + CTNxStackWalker sw; + sw.ShowCallstack( + GetCurrentThread(), + ep->ContextRecord + ); + + had_exception = true; + + // show cursor in case it was hidden + while (ShowCursor(true) < 0); + + if (create_crash_dump) + { + PathAppendA(filePath, "crash.dmp"); + + HANDLE file = CreateFile(filePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + HANDLE proc = GetCurrentProcess(); + DWORD procid = GetCurrentProcessId(); + MINIDUMP_EXCEPTION_INFORMATION mdei; + + CONTEXT c; + HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, GetCurrentThreadId());; + memset(&c, 0, sizeof(c)); + c.ContextFlags = CONTEXT_FULL; + GetThreadContext(hThread, &c); + + mdei.ThreadId = GetCurrentThreadId(); + mdei.ExceptionPointers = ep; + mdei.ExceptionPointers->ContextRecord = &c; + mdei.ClientPointers = true; + + if (!MiniDumpWriteDump( + proc, + procid, + file, + (MINIDUMP_TYPE)(MiniDumpWithFullMemory | + MiniDumpWithFullMemoryInfo | + MiniDumpWithHandleData | + MiniDumpWithUnloadedModules | + MiniDumpWithThreadInfo), + &mdei, NULL, NULL)) { + wchar_t buf[256]; + + FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError(), MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), + buf, (sizeof(buf) / sizeof(wchar_t)), NULL); + + PLOGD.printf("MiniDumpWriteDump failed with error: %ls\n", buf); + } + } + + PLOGE.printf("Unhandled Exception. See dumped information above.\n"); + + MessageBoxA(NULL, "Feel free to visit this link to know about further next steps you can take: https://github.com/julianxhokaxhiu/CTNx/blob/master/docs/faq.md", "Game crashed :(", MB_ICONERROR | MB_OK); + + on_game_close(); + + // let OS handle the crash + SetUnhandledExceptionFilter(0); + return EXCEPTION_CONTINUE_EXECUTION; +} diff --git a/src/crashdump.h b/src/crashdump.h new file mode 100644 index 0000000..707b718 --- /dev/null +++ b/src/crashdump.h @@ -0,0 +1,68 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#pragma once + +#include +#include +#include "globals.h" + +#define STACK_MAX_NAME_LENGTH 256 + +class CTNxStackWalker : public StackWalker +{ +public: + CTNxStackWalker(bool muted = false) : StackWalker(), _baseAddress(0), _size(0), _muted(muted) {} + DWORD64 getBaseAddress() const { + return _baseAddress; + } + DWORD getSize() const { + return _size; + } +protected: + virtual void OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, + DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, + ULONGLONG fileVersion + ) + { + if (_baseAddress == 0 && _size == 0) + { + _baseAddress = baseAddr; + _size = size; + } + StackWalker::OnLoadModule( + img, mod, baseAddr, size, result, symType, pdbName, fileVersion + ); + } + + virtual void OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr) + { + // Silence is golden. + } + + virtual void OnOutput(LPCSTR szText) + { + if (! _muted) + { + PLOGD.printf(szText); + } + } +private: + DWORD64 _baseAddress; + DWORD _size; + bool _muted; +}; + +LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS *ep); diff --git a/src/dllmain.cpp b/src/dllmain.cpp new file mode 100644 index 0000000..bd4ced2 --- /dev/null +++ b/src/dllmain.cpp @@ -0,0 +1,158 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#include "audio.h" +#include "crashdump.h" +#include "exports.h" +#include "hext.h" +#include "game.h" +#include "gamehacks.h" +#include "utils.h" +#include "voice.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void on_game_hook() +{ + // install crash handler + SetUnhandledExceptionFilter(ExceptionHandler); + + CTNx_log_current_pc_specs(); + + QueryPerformanceFrequency(&system_frequency); + + // Disable vsync + glfwSwapInterval(0); + + // start hooking + game_hook_init(); + voice_init(); + + // gamehacks + gamehacks.init(); + + // apply hext patching + hextPatcher.applyAll(); +} + +void on_game_close() +{ + voice_term(); + game_hook_term(); + + // Cleanup the audio device + nxAudioEngine.cleanup(); +} + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + if (DetourIsHelperProcess()) return TRUE; + + if (fdwReason == DLL_PROCESS_ATTACH) + { + // Push the limit of how many files we can open at the same time to the maximum available on Windows + // See https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/setmaxstdio?view=msvc-160#remarks + _setmaxstdio(8192); + + SetProcessDPIAware(); + + GetCurrentDirectoryA(BASEDIR_LENGTH, basedir); + + // Setup logging layer + remove(APP_RELEASE_NAME ".log"); + plog::init(plog::verbose, APP_RELEASE_NAME ".log"); + + // prevent screensavers + SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED | ES_SYSTEM_REQUIRED); + + PLOGI.printf("CTNx driver version " APP_RELEASE_VERSION "\n"); + + // init game data + game_externals.baseAddress = GetModuleHandle(nullptr); + game_externals.libcocosAddress = GetModuleHandle("libcocos2d"); + game_data_init(); + + // print detected language + switch(*game_externals.language_id) + { + case GAME_LANGUAGE_JA: + PLOGI.printf("Detected language: ja\n"); + break; + case GAME_LANGUAGE_EN: + PLOGI.printf("Detected language: en\n"); + break; + case GAME_LANGUAGE_DE: + PLOGI.printf("Detected language: de\n"); + break; + case GAME_LANGUAGE_IT: + PLOGI.printf("Detected language: it\n"); + break; + case GAME_LANGUAGE_FR: + PLOGI.printf("Detected language: fr\n"); + break; + case GAME_LANGUAGE_ZH_HANS: + PLOGI.printf("Detected language: zh-hans\n"); + break; + case GAME_LANGUAGE_ZH_HANT: + PLOGI.printf("Detected language: zh-hant\n"); + break; + case GAME_LANGUAGE_KO: + PLOGI.printf("Detected language: ko\n"); + break; + } + + read_cfg(); + + // Hook WinMain and allow us to run some custom init code before the game starts + static decltype(game_externals.WinMain) detour = [](HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) -> int + { + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + // ------------------------------------ + DetourDetach((void**)&game_externals.WinMain, detour); + // ------------------------------------ + DetourTransactionCommit(); + + on_game_hook(); + + // continue execution + return game_externals.WinMain(hInstance, hPrevInstance, lpCmdLine, nShowCmd); + }; + + DisableThreadLibraryCalls(hinstDLL); + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + // ------------------------------------ + DetourAttach((void**)&game_externals.WinMain, detour); + // ------------------------------------ + DetourTransactionCommit(); + } + else if (fdwReason == DLL_PROCESS_DETACH) + { + on_game_close(); + } + + return TRUE; +} diff --git a/src/exports.h b/src/exports.h new file mode 100644 index 0000000..26ff524 --- /dev/null +++ b/src/exports.h @@ -0,0 +1,34 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#pragma once + +#pragma comment(linker, "/export:GetFileVersionInfoA=C:\\Windows\\System32\\version.GetFileVersionInfoA,@1") +#pragma comment(linker, "/export:GetFileVersionInfoByHandle=C:\\Windows\\System32\\version.GetFileVersionInfoByHandle,@2") +#pragma comment(linker, "/export:GetFileVersionInfoExA=C:\\Windows\\System32\\version.GetFileVersionInfoExA,@3") +#pragma comment(linker, "/export:GetFileVersionInfoExW=C:\\Windows\\System32\\version.GetFileVersionInfoExW,@4") +#pragma comment(linker, "/export:GetFileVersionInfoSizeA=C:\\Windows\\System32\\version.GetFileVersionInfoSizeA,@5") +#pragma comment(linker, "/export:GetFileVersionInfoSizeExA=C:\\Windows\\System32\\version.GetFileVersionInfoSizeExA,@6") +#pragma comment(linker, "/export:GetFileVersionInfoSizeExW=C:\\Windows\\System32\\version.GetFileVersionInfoSizeExW,@7") +#pragma comment(linker, "/export:GetFileVersionInfoSizeW=C:\\Windows\\System32\\version.GetFileVersionInfoSizeW,@8") +#pragma comment(linker, "/export:GetFileVersionInfoW=C:\\Windows\\System32\\version.GetFileVersionInfoW,@9") +#pragma comment(linker, "/export:VerFindFileA=C:\\Windows\\System32\\version.VerFindFileA,@10") +#pragma comment(linker, "/export:VerFindFileW=C:\\Windows\\System32\\version.VerFindFileW,@11") +#pragma comment(linker, "/export:VerInstallFileA=C:\\Windows\\System32\\version.VerInstallFileA,@12") +#pragma comment(linker, "/export:VerInstallFileW=C:\\Windows\\System32\\version.VerInstallFileW,@13") +#pragma comment(linker, "/export:VerLanguageNameA=C:\\Windows\\System32\\version.VerLanguageNameA,@14") +#pragma comment(linker, "/export:VerLanguageNameW=C:\\Windows\\System32\\version.VerLanguageNameW,@15") +#pragma comment(linker, "/export:VerQueryValueA=C:\\Windows\\System32\\version.VerQueryValueA,@16") +#pragma comment(linker, "/export:VerQueryValueW=C:\\Windows\\System32\\version.VerQueryValueW,@17") diff --git a/src/game.cpp b/src/game.cpp new file mode 100644 index 0000000..2c1841a --- /dev/null +++ b/src/game.cpp @@ -0,0 +1,82 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#include "globals.h" +#include "game.h" +#include "cocos2d.h" +#include "gamehacks.h" +#include "log.h" + +struct game_externals game_externals; + +uint32_t calc_game_address_offset(uint32_t offset) +{ + return uint32_t(game_externals.baseAddress) + offset; +} + +uint32_t calc_libcocos2d_address_offset(uint32_t offset) +{ + return uint32_t(game_externals.libcocosAddress) + offset; +} + +void game_data_init() +{ + game_externals.WinMain = (decltype(game_externals.WinMain))(calc_game_address_offset(0x2D8830)); + game_externals.WindowProc = (decltype(game_externals.WindowProc))(calc_libcocos2d_address_offset(0x000C2170)); + + game_externals.Frequency = (decltype(game_externals.PerformanceCount))(calc_game_address_offset(0x41A388)); + game_externals.PerformanceCount = (decltype(game_externals.PerformanceCount))(calc_game_address_offset(0x41A390)); + game_externals.get_time_sub_30FFA0 = (decltype(game_externals.get_time_sub_30FFA0))(calc_game_address_offset(0x30FFA0)); + game_externals.get_time_sub_30FFF0 = (decltype(game_externals.get_time_sub_30FFF0))(calc_game_address_offset(0x30FFF0)); + + game_externals.get_game_string = (decltype(game_externals.get_game_string))(calc_game_address_offset(0x1B9060)); + game_externals.sub_1B92D0 = (decltype(game_externals.sub_1B92D0))(calc_game_address_offset(0x1B92D0)); + game_externals.sub_msgwindow_nextpage = (decltype(game_externals.sub_msgwindow_nextpage))(calc_game_address_offset(0x195E30)); + game_externals.sub_195C70 = (decltype(game_externals.sub_195C70))(calc_game_address_offset(0x195C70)); + game_externals.language_id = (decltype(game_externals.language_id))(calc_game_address_offset(0x3FA168)); + + game_externals.log_line_sub_6F2690 = (decltype(game_externals.log_line_sub_6F2690))(calc_game_address_offset(0x2F2690)); +} + +LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + gamehacks.processKeyboardInput(uMsg, wParam, lParam); + + Director::getInstance()->setDisplayStats(true); + + return game_externals.WindowProc(hwnd, uMsg, wParam, lParam); +} + +void game_hook_init() +{ + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + // ------------------------------------ + DetourAttach((void**)&game_externals.WindowProc, WindowProc); + if (show_applog) DetourAttach((void**)&game_externals.log_line_sub_6F2690, external_debug_print); + // ------------------------------------ + DetourTransactionCommit(); +} + +void game_hook_term() +{ + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + // ------------------------------------ + DetourDetach((void**)&game_externals.WindowProc, WindowProc); + if (show_applog) DetourDetach((void**)&game_externals.log_line_sub_6F2690, external_debug_print); + // ------------------------------------ + DetourTransactionCommit(); +} diff --git a/src/game.h b/src/game.h new file mode 100644 index 0000000..d8d43a5 --- /dev/null +++ b/src/game.h @@ -0,0 +1,99 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#pragma once + +#include +#include + +#define GAME_LANGUAGE_JA 0 +#define GAME_LANGUAGE_EN 1 +#define GAME_LANGUAGE_DE 2 +#define GAME_LANGUAGE_IT 3 +#define GAME_LANGUAGE_ES 4 +#define GAME_LANGUAGE_FR 5 +#define GAME_LANGUAGE_ZH_HANS 6 +#define GAME_LANGUAGE_ZH_HANT 7 +#define GAME_LANGUAGE_KO 8 + +struct MsgWindow { + BYTE gap0[0x2C0]; + int currentLineNoMaybe; + int pageStartLineNoMaybe; +}; + +struct field_object { + DWORD dword0; + DWORD dword4; + DWORD dword8; + DWORD dwordC; + DWORD dword10; + DWORD dword14; + DWORD dword18; + DWORD dword1C; + BYTE byte20; + BYTE gap0[6375]; + std::string defaultCharacterNames[7]; + BYTE gap1[62932]; + BYTE byte10F84; + BYTE gap2[1]; + WORD word10F86; + BYTE gap3[72]; + DWORD dword10FD0; + BYTE gap4[56]; + DWORD dword1100C; + BYTE gap5[56]; + DWORD dword11048; + BYTE gap6[100]; + DWORD dword110B0; + BYTE gap7[4108]; + int currentFieldId; + BYTE gap8[4488]; + int activePartyMemberIds[3]; + int inactivePartyMemberIds[4]; + BYTE gap9[20]; + DWORD dword1327C; + BYTE gapA[728]; + DWORD dword13558; + BYTE gap[38828]; +}; + +struct game_externals +{ + // Core exe address + HMODULE baseAddress; + HMODULE libcocosAddress; + // Game WinMain + int (WINAPI *WinMain)(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd); + LRESULT (CALLBACK *WindowProc)(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + // Game Functions + LONGLONG (*get_time_sub_30FFA0)(); + LONGLONG (*get_time_sub_30FFF0)(); + std::string* (__thiscall *get_game_string)(void*, void*, int, int); + std::string* (__thiscall *sub_1B92D0)(void*, void*, int, int); + void (__thiscall *sub_msgwindow_nextpage)(MsgWindow*); + void (__thiscall *sub_195C70)(MsgWindow*, int); + int (*log_line_sub_6F2690)(int, char*, ...); + // Game Data + LARGE_INTEGER* PerformanceCount; + LARGE_INTEGER* Frequency; + field_object* field_object; + DWORD* language_id; +}; + +uint32_t calc_game_address_offset(uint32_t offset); +void game_data_init(); +void game_hook_init(); +void game_hook_term(); diff --git a/src/gamehacks.cpp b/src/gamehacks.cpp new file mode 100644 index 0000000..75b48b6 --- /dev/null +++ b/src/gamehacks.cpp @@ -0,0 +1,139 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#include +#include "gamehacks.h" +#include "audio.h" +#include "cocos2d.h" + +GameHacks gamehacks; + +// PRIVATE + +void GameHacks::toggleSpeedhack() +{ + speedhack_enabled = !speedhack_enabled; + + std::string text = std::format("Current Speedhack: {}", speedhack_enabled ? "ENABLED" : "DISABLED"); + show_popup_msg(text); + + Director::getInstance()->setAnimationInterval(1.0f / (60.0f * gamehacks.getCurrentSpeedhack())); + + holdInput(); +} + +void GameHacks::resetSpeedhack() +{ + speedhack_current_speed = speedhack_min; +} + +void GameHacks::increaseSpeedhack() +{ + speedhack_enabled = true; + + if ((speedhack_current_speed + speedhack_step) <= speedhack_max) speedhack_current_speed += speedhack_step; + + std::string text = std::format("Current Speedhack: {:.2f}x", speedhack_current_speed); + show_popup_msg(text); + + Director::getInstance()->setAnimationInterval(1.0f / (60.0f * gamehacks.getCurrentSpeedhack())); + + holdInput(); +} + +void GameHacks::decreaseSpeedhack() +{ + speedhack_enabled = true; + + if ((speedhack_current_speed - speedhack_step) >= speedhack_min) speedhack_current_speed -= speedhack_step; + + std::string text = std::format("Current Speedhack: {:.2f}x", speedhack_current_speed); + show_popup_msg(text); + + Director::getInstance()->setAnimationInterval(1.0f / (60.0f * gamehacks.getCurrentSpeedhack())); + + holdInput(); +} + +void GameHacks::toggleAutoText() +{ + enable_voice_auto_text = !enable_voice_auto_text; + + std::string text = std::format("Voice auto text mode: {}", enable_voice_auto_text ? "ENABLED" : "DISABLED"); + show_popup_msg(text); + + holdInput(); +} + +// PUBLIC + +void GameHacks::init() +{ + resetSpeedhack(); + + if (speedhack_current_speed > 1.0) speedhack_enabled = true; +} + +void GameHacks::processKeyboardInput(UINT msg, WPARAM wParam, LPARAM lParam) +{ + isKeyboardShortcutMode = false; + switch (msg) + { + case WM_KEYDOWN: + if ((::GetKeyState(VK_CONTROL) & 0x8000) != 0) + { + isKeyboardShortcutMode = true; + switch (wParam) + { + case 'T': + toggleAutoText(); + break; + case VK_UP: + increaseSpeedhack(); + break; + case VK_DOWN: + decreaseSpeedhack(); + break; + case VK_LEFT: + case VK_RIGHT: + toggleSpeedhack(); + break; + } + } + break; + } +} + +double GameHacks::getCurrentSpeedhack() +{ + return speedhack_enabled ? speedhack_current_speed : 1.0; +} + +void GameHacks::holdInput() +{ + if(!enable_hold_input) return; + hold_input_for_frames = 30; // ~1 sec + enable_hold_input = false; +} + +void GameHacks::drawnInput() +{ + if (hold_input_for_frames > 0) hold_input_for_frames--; +} + +bool GameHacks::canInputBeProcessed() +{ + return !isGamepadShortcutMode && !isKeyboardShortcutMode; +} diff --git a/src/gamehacks.h b/src/gamehacks.h new file mode 100644 index 0000000..906f80f --- /dev/null +++ b/src/gamehacks.h @@ -0,0 +1,61 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#pragma once + +#include +#include + +class GameHacks +{ +private: + uint16_t hold_input_for_frames = 0; + bool enable_hold_input = true; + + bool speedhack_enabled; + double speedhack_current_speed; + + // SPEEDHACK + void toggleSpeedhack(); + void resetSpeedhack(); + void increaseSpeedhack(); + void decreaseSpeedhack(); + + // INPUT VALIDATION + void holdInput(); + void drawnInput(); + + // VOICE AUTO TEXT + void toggleAutoText(); + +public: + void init(); + + // GLOBALS + void processKeyboardInput(UINT msg, WPARAM wParam, LPARAM lParam); + void processGamepadInput(); + + // SPEEDHACK + double getCurrentSpeedhack(); + + // INPUT VALIDATION + bool canInputBeProcessed(); + +private: + bool isKeyboardShortcutMode = false; + bool isGamepadShortcutMode = false; +}; + +extern GameHacks gamehacks; diff --git a/src/globals.cpp b/src/globals.cpp new file mode 100644 index 0000000..9c72971 --- /dev/null +++ b/src/globals.cpp @@ -0,0 +1,93 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#include +#include +#include "globals.h" +#include "crashdump.h" +#include "wine.h" + +// install directory for the current game +char basedir[BASEDIR_LENGTH]; + +uint32_t noop() { return 0; } + +void ffmpeg_log_callback(void* ptr, int level, const char* fmt, va_list vl) +{ + char msg[4 * 1024]; // 4K + static int print_prefix = 1; + + av_log_format_line(ptr, level, fmt, vl, msg, sizeof(msg), &print_prefix); + + switch (level) { + case AV_LOG_VERBOSE: + case AV_LOG_DEBUG: if (trace_all) PLOGD.printf(msg); break; + case AV_LOG_INFO: + case AV_LOG_WARNING: if (trace_all) PLOGI.printf(msg); break; + case AV_LOG_ERROR: + case AV_LOG_FATAL: + case AV_LOG_PANIC: PLOGE.printf(msg); break; + } + + if (level <= AV_LOG_ERROR) { + CTNxStackWalker sw; + sw.ShowCallstack(); + } +} + +void CTNx_log_current_pc_specs() +{ + // Start report of PC specs + PLOGI.printf("--- PC SPECS ---\n"); + + // CPU + auto cpus = hwinfo::getAllCPUs(); + for (const auto& cpu : cpus) { + PLOGI.printf(" CPU: %s\n", cpu.modelName().c_str()); + } + + // GPU + auto gpus = hwinfo::getAllGPUs(); + uint16_t gpuidx = 0; + for (auto& gpu : gpus) { + uint16_t vendorId = std::stoi(gpu.vendor_id(), 0, 16), deviceId = std::stoi(gpu.device_id(), 0, 16); + PLOGI.printf(" GPU #%u: %s (%dMB) - Driver: %s\n", gpuidx, gpu.name().c_str(), (int)(gpu.memory_Bytes() / 1024.0 / 1024.0), gpu.driverVersion().c_str()); + gpuidx++; + } + + // RAM + hwinfo::Memory memory; + PLOGI.printf(" RAM: %dMB/%dMB (Free: %dMB)\n", (int)((memory.total_Bytes() - memory.free_Bytes()) / 1024.0 / 1024.0), (int)(memory.total_Bytes() / 1024.0 / 1024.0), (int)(memory.free_Bytes() / 1024.0 / 1024.0)); + + // OS + hwinfo::OS os; + PLOGI.printf(" OS: %s %s (build %s)\n", os.name().c_str(), (os.is32bit() ? "32 bit" : "64 bit"), os.version().c_str()); + + // WINE+PROTON + const char* env_wineloader = std::getenv("WINELOADER"); + if (env_wineloader != NULL) // Are we running under Wine/Proton? + { + PLOGI.printf(" WINE: v%s\n", GetWineVersion()); + + const std::regex proton_regex("([Pp]roton[\\s\\-\\w.()]+)"); + std::smatch base_match; + std::string s_wineloader = std::string(env_wineloader); + if (std::regex_search(s_wineloader, base_match, proton_regex)) + PLOGI.printf("PROTON: %s\n", base_match[1].str().c_str()); + } + + // End report of PC specs + PLOGI.printf("----------------\n"); +} diff --git a/src/globals.h b/src/globals.h new file mode 100644 index 0000000..6cc5b83 --- /dev/null +++ b/src/globals.h @@ -0,0 +1,57 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#pragma once + +#include +USING_NS_CC; + +#include +#include + +#include + +#include +#include +#include "plog.formatter.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#include +#include +#include +#include +#include + +#if defined(__cplusplus) +} +#endif + +#include "cfg.h" +#include "game.h" + +#define BASEDIR_LENGTH 512 +extern char basedir[BASEDIR_LENGTH]; + +extern HMODULE game_baseAddress; +extern struct game_externals game_externals; +LARGE_INTEGER system_frequency; + +uint32_t noop(); +void on_game_close(); +void ffmpeg_log_callback(void* ptr, int level, const char* fmt, va_list vl); +void CTNx_log_current_pc_specs(); diff --git a/src/hext.cpp b/src/hext.cpp new file mode 100644 index 0000000..2a23f15 --- /dev/null +++ b/src/hext.cpp @@ -0,0 +1,315 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#include +#include +#include "hext.h" +#include "globals.h" +#include "patch.h" +#include "utils.h" + +Hext hextPatcher; + +// PRIVATE + +int Hext::getAddress(std::string token) +{ + int ret; + + std::vector sparts = split(token, "[+-]+"); + std::vector iparts; + + if (ends_with(sparts[0], "^")) + { + std::stringstream ss; + int *ptr = (int*)(std::stoi(sparts[0].substr(0, sparts[0].length() - 1), nullptr, 16) + inGlobalOffset); + ss << std::hex << *ptr; + sparts[0] = ss.str(); + } + + for (auto &part : sparts) + { + iparts.push_back( + std::stoi(part, nullptr, 16) + ); + } + + ret = iparts[0]; + + if (contains(token, "+")) + { + ret += iparts[1]; + } + else if (contains(token, "-")) + { + ret -= iparts[1]; + } + + return ret + inGlobalOffset; +} + +std::vector Hext::getBytes(std::string token) +{ + std::vector ret; + + if (contains(token, ":")) + { + std::vector parts = split(token, "[:]+"); + int count = std::stoi(parts[1], nullptr, 0); + while (count > 0) + { + ret.push_back(std::stoi(parts[0], nullptr, 16)); + count--; + } + } + else + { + std::vector bytes = split(token, "[\\s,\\t]+"); + + for (auto byte : bytes) + { + ret.push_back(std::stoi(byte, nullptr, 16)); + } + } + + return ret; +} + +bool Hext::hasCheckpoint(std::string token) +{ + if (starts_with(token, "!")) + { + return true; + } + + return false; +} + +bool Hext::parseCheckpoint(std::string token, std::string checkpoint) +{ + if (starts_with(token, "!")) + { + if (contains(token, checkpoint)) + { + return true; + } + } + + return false; +} + +bool Hext::parseCommands(std::string token) +{ + if (starts_with(token, "<<")) + { + replaceOnce(token, "<<", ""); + + trim(token); + + PLOGD.printf("%s\n", token.data()); + + return true; + } + + return false; +} + +bool Hext::parseComment(std::string token) +{ + if (isMultilineComment) + { + if (ends_with(token, "}}")) isMultilineComment = false; + return true; + } + + if (starts_with(token, "{{")) + { + isMultilineComment = true; + return true; + } + + if (starts_with(token, "#")) return true; + if (starts_with(token, "{")) return true; + if (starts_with(token, ".")) return true; + + return false; +} + +bool Hext::parseGlobalOffset(std::string token) +{ + if (starts_with(token, "+")) + { + inGlobalOffset = std::stoi(token.substr(1), nullptr, 16); + + return true; + } + else if (starts_with(token, "-")) + { + inGlobalOffset = -std::stoi(token.substr(1), nullptr, 16); + + return true; + } + + return false; +} + +bool Hext::parseMemoryPermission(std::string token) +{ + if (contains(token, ":")) + { + DWORD dummy; + + std::vector parts = split(token, "[:]+"); + int addr = getAddress(parts[0]); + int length = std::stoi(parts[1], nullptr, 16); + + VirtualProtect((LPVOID)addr, length, PAGE_EXECUTE_READWRITE, &dummy); + + return true; + } + + return false; +} + +bool Hext::parseMemoryPatch(std::string token) +{ + if (contains(token, "=")) + { + DWORD dummy; + + std::vector parts = split(token, "[=]+"); + int addr = getAddress(parts[0]); + std::vector bytes = getBytes(parts[1]); + + memcpy_code(addr, bytes.data(), bytes.size()); + + return true; + } + + return false; +} + +// PUBLIC + +void Hext::apply(std::string filename) +{ + std::string line; + std::ifstream ifs(filename); + + while (std::getline(ifs, line)) + { + if (line.empty()) continue; + + // Check if delayed, if so it should not be applied + if (hasCheckpoint(line)) { + ifs.close(); + return; + } + + // Check if is a comment + if (parseComment(line)) continue; + + // Check if is a command + if (parseCommands(line)) continue; + + // Check if is a global offset + if (parseGlobalOffset(line)) continue; + + // Check if is a memory permission range + if (parseMemoryPermission(line)) continue; + + // Check if is a memory patch instruction + if (parseMemoryPatch(line)) continue; + } + + ifs.close(); + + PLOGD.printf("Applied Hext patch: %s\n", filename.c_str()); +} + +void Hext::applyDelayed(std::string filename, std::string checkpoint) +{ + std::string line; + std::ifstream ifs(filename); + + bool matchCheckpoint = false; + + while (std::getline(ifs, line)) + { + if (line.empty()) continue; + + // Check if is a comment + if (parseComment(line)) continue; + + // Check if is a delayed patch. + if (parseCheckpoint(line, checkpoint)) { + matchCheckpoint = true; + + continue; + } + + if (matchCheckpoint) + { + // Check if is a command + if (parseCommands(line)) continue; + + // Check if is a global offset + if (parseGlobalOffset(line)) continue; + + // Check if is a memory permission range + if (parseMemoryPermission(line)) continue; + + // Check if is a memory patch instruction + if (parseMemoryPatch(line)) continue; + } + else + { + break; + } + } + + ifs.close(); + + if (matchCheckpoint) PLOGD.printf("Applied delayed Hext patch: %s\n", filename.c_str()); +} + +void Hext::applyAll(std::string checkpoint) +{ + if (fileExists(hext_patching_path.c_str())) + { + if (!checkpoint.empty()) + { + for (const auto& entry : std::filesystem::directory_iterator(hext_patching_path)) + { + if (entry.is_regular_file()) { + applyDelayed(entry.path().string(), checkpoint); + } + + inGlobalOffset = 0; + } + } + else + { + for (const auto& entry : std::filesystem::directory_iterator(hext_patching_path)) + { + if (entry.is_regular_file()) { + apply(entry.path().string()); + } + + inGlobalOffset = 0; + } + } + } +} diff --git a/src/hext.h b/src/hext.h new file mode 100644 index 0000000..f6f6a7f --- /dev/null +++ b/src/hext.h @@ -0,0 +1,52 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +/* + HEXT Specification by DLPB + + See https://forums.qhimm.com/index.php?topic=13574.0 + + This implementation may differ from the original specification as new required functionalities will be implemented, + in order to ease modders life. +*/ + +#pragma once + +#include +#include + +class Hext { +private: + int inGlobalOffset; + bool isMultilineComment = false; + + int getAddress(std::string token); + std::vector getBytes(std::string token); + + bool hasCheckpoint(std::string token); + bool parseCheckpoint(std::string token, std::string checkpoint); + bool parseCommands(std::string token); + bool parseComment(std::string token); + bool parseGlobalOffset(std::string token); + bool parseMemoryPermission(std::string token); + bool parseMemoryPatch(std::string token); + +public: + void apply(std::string filename); + void applyDelayed(std::string filename, std::string checkpoint); + void applyAll(std::string checkpoint = std::string()); +}; + +extern Hext hextPatcher; diff --git a/src/log.cpp b/src/log.cpp new file mode 100644 index 0000000..b00f53f --- /dev/null +++ b/src/log.cpp @@ -0,0 +1,26 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#include "globals.h" +#include "log.h" + +void external_debug_print(int unk, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + PLOGD.printf(fmt, args); + va_end(args); +} diff --git a/src/log.h b/src/log.h new file mode 100644 index 0000000..70ac3ef --- /dev/null +++ b/src/log.h @@ -0,0 +1,18 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#pragma once + +void external_debug_print(int unk, const char *fmt, ...); diff --git a/src/patch.cpp b/src/patch.cpp new file mode 100644 index 0000000..71e2ef1 --- /dev/null +++ b/src/patch.cpp @@ -0,0 +1,157 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#include "patch.h" + +#include +#include + +#include "crashdump.h" + +uint8_t check_is_call(const char *name, uint32_t base, uint32_t offset, uint16_t instruction) +{ + if ((instruction & 0xFF) != 0xE8 && (instruction & 0xFF) != 0xE9 && instruction != 0x15FF) + { + // Warning to diagnose errors faster + PLOGW.printf("%s: Unrecognized call/jmp instruction at 0x%X + 0x%X (0x%X): 0x%X\n", name, base, offset, base + offset, instruction); + } + + return instruction == 0x15FF ? 2 : 1; +} + +uint32_t get_relative_call(uint32_t base, uint32_t offset) +{ + uint16_t instruction = *((uint16_t *)(base + offset)); + + uint8_t size = check_is_call(__func__, base, offset, instruction); + + uint32_t ret = base + *((uint32_t *)(base + offset + size)) + offset + 4 + size; + + return ret; +} + +uint32_t get_absolute_value(uint32_t base, uint32_t offset) +{ + return *((uint32_t *)(base + offset)); +} + +void patch_code_byte(uint32_t offset, unsigned char r) +{ + DWORD dummy; + + VirtualProtect((void *)offset, sizeof(r), PAGE_EXECUTE_READWRITE, &dummy); + + *(unsigned char *)offset = r; +} + +void patch_code_char(uint32_t offset, char r) +{ + DWORD dummy; + + VirtualProtect((void *)offset, sizeof(r), PAGE_EXECUTE_READWRITE, &dummy); + + *(char *)offset = r; +} + +void patch_code_word(uint32_t offset, WORD r) +{ + DWORD dummy; + + VirtualProtect((void *)offset, sizeof(r), PAGE_EXECUTE_READWRITE, &dummy); + + *(WORD *)offset = r; +} + +void patch_code_short(uint32_t offset, short r) +{ + DWORD dummy; + + VirtualProtect((void *)offset, sizeof(r), PAGE_EXECUTE_READWRITE, &dummy); + + *(short *)offset = r; +} + +void patch_code_dword(uint32_t offset, DWORD r) +{ + DWORD dummy; + + VirtualProtect((void*)offset, sizeof(r), PAGE_EXECUTE_READWRITE, &dummy); + + *(DWORD*)offset = r; +} + +void patch_code_int(uint32_t offset, int r) +{ + DWORD dummy; + + VirtualProtect((void*)offset, sizeof(r), PAGE_EXECUTE_READWRITE, &dummy); + + *(int*)offset = r; +} + +void patch_code_uint(uint32_t offset, uint32_t r) +{ + DWORD dummy; + + VirtualProtect((void *)offset, sizeof(r), PAGE_EXECUTE_READWRITE, &dummy); + + *(uint32_t *)offset = r; +} + +void patch_code_float(uint32_t offset, float r) +{ + DWORD dummy; + + VirtualProtect((void *)offset, sizeof(r), PAGE_EXECUTE_READWRITE, &dummy); + + *(float *)offset = r; +} + +void patch_code_double(uint32_t offset, double r) +{ + DWORD dummy; + + VirtualProtect((void *)offset, sizeof(r), PAGE_EXECUTE_READWRITE, &dummy); + + *(double *)offset = r; +} + +void memcpy_code(uint32_t offset, void *data, uint32_t size) +{ + DWORD dummy; + + VirtualProtect((void *)offset, size, PAGE_EXECUTE_READWRITE, &dummy); + + memcpy((void *)offset, data, size); +} + +void memset_code(uint32_t offset, uint32_t val, uint32_t size) +{ + DWORD dummy; + + VirtualProtect((void *)offset, size, PAGE_EXECUTE_READWRITE, &dummy); + + memset((void *)offset, val, size); +} + +// From https://stackoverflow.com/a/21636483 +void* member_func_to_ptr(char i, ...) +{ + va_list v; + va_start(v,i); + void* ret = va_arg(v, void*); + va_end(v); + return ret; +} diff --git a/src/patch.h b/src/patch.h new file mode 100644 index 0000000..13b9b1f --- /dev/null +++ b/src/patch.h @@ -0,0 +1,60 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#pragma once + +#include +#include + +uint32_t get_relative_call(uint32_t base, uint32_t offset); +uint32_t get_absolute_value(uint32_t base, uint32_t offset); +void patch_code_char(uint32_t offset, char r); +void patch_code_byte(uint32_t offset, unsigned char r); +void patch_code_word(uint32_t offset, WORD r); +void patch_code_short(uint32_t offset, short r); +void patch_code_dword(uint32_t offset, DWORD r); +void patch_code_int(uint32_t offset, int r); +void patch_code_uint(uint32_t offset, uint32_t r); +void patch_code_float(uint32_t offset, float r); +void patch_code_double(uint32_t offset, double r); + +template +void patch_multiply_code(uint32_t offset, int multiplier) +{ + DWORD dummy; + + VirtualProtect((void *)offset, sizeof(T), PAGE_EXECUTE_READWRITE, &dummy); + + *(T *)offset = (*(T *)offset) * (T)multiplier; + + // TODO Add assertion +} + +template +void patch_divide_code(uint32_t offset, int multiplier) +{ + DWORD dummy; + + VirtualProtect((void *)offset, sizeof(T), PAGE_EXECUTE_READWRITE, &dummy); + + *(T *)offset = (*(T *)offset) / (T)multiplier; + + // TODO Add assertion +} + +void memcpy_code(uint32_t offset, void *data, uint32_t size); +void memset_code(uint32_t offset, uint32_t val, uint32_t size); + +void* member_func_to_ptr(char i, ...); diff --git a/src/plog.formatter.h b/src/plog.formatter.h new file mode 100644 index 0000000..5f8e32b --- /dev/null +++ b/src/plog.formatter.h @@ -0,0 +1,45 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#pragma once +#include +#include +#include + +namespace plog +{ + class CTNxFormatter + { + public: + static util::nstring header() + { + return util::nstring(); + } + + static util::nstring format(const Record& record) + { + tm t; + util::localtime_s(&t, &record.getTime().time); + + util::nostringstream ss; + ss << t.tm_year + 1900 << "-" << std::setfill(PLOG_NSTR('0')) << std::setw(2) << t.tm_mon + 1 << PLOG_NSTR("-") << std::setfill(PLOG_NSTR('0')) << std::setw(2) << t.tm_mday << PLOG_NSTR(" "); + ss << std::setfill(PLOG_NSTR('0')) << std::setw(2) << t.tm_hour << PLOG_NSTR(":") << std::setfill(PLOG_NSTR('0')) << std::setw(2) << t.tm_min << PLOG_NSTR(":") << std::setfill(PLOG_NSTR('0')) << std::setw(2) << t.tm_sec << PLOG_NSTR(".") << std::setfill(PLOG_NSTR('0')) << std::setw(3) << static_cast (record.getTime().millitm) << PLOG_NSTR(" "); + ss << std::setfill(PLOG_NSTR(' ')) << std::setw(5) << std::left << severityToString(record.getSeverity()) << PLOG_NSTR(" "); + ss << record.getMessage(); + + return ss.str(); + } + }; +} diff --git a/src/utils.cpp b/src/utils.cpp new file mode 100644 index 0000000..ce1237c --- /dev/null +++ b/src/utils.cpp @@ -0,0 +1,36 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ +#include "utils.h" + +#include "globals.h" + +#include +#include + +bool fileExists(const char *filename) +{ + struct stat dummy; + + // Use stat to keep compatibility with 7th Heaven + return stat(filename, &dummy) == 0; +} + +bool dirExists(const char *dirname) +{ + struct stat dummy; + + // Use stat to keep compatibility with 7th Heaven + return stat(dirname, &dummy) == 0; +} diff --git a/src/utils.h b/src/utils.h new file mode 100644 index 0000000..26a31c6 --- /dev/null +++ b/src/utils.h @@ -0,0 +1,135 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#pragma once + +#include +#include +#include +#include +#include + +// Get the size of a vector in bytes +template +size_t vectorSizeOf(const typename std::vector& vec) +{ + return sizeof(T) * vec.size(); +} + +// trim from start (in place) +inline void ltrim(std::string& s) { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) { + return !std::isspace(ch); + })); +} + +// trim from end (in place) +inline void rtrim(std::string& s) { + s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) { + return !std::isspace(ch); + }).base(), s.end()); +} + +// trim from both ends (in place) +inline void trim(std::string& s) { + ltrim(s); + rtrim(s); +} + +inline bool contains(std::string const& value, std::string const& token) +{ + return value.find(token) != std::string::npos; +} + +inline std::vector split(const std::string& string, const std::string& regex) +{ + std::vector result; + std::string safeString(string); + + trim(safeString); + + const std::regex rgx(regex); + std::sregex_token_iterator iter(safeString.begin(), safeString.end(), rgx, -1); + + for (std::sregex_token_iterator end; iter != end; ++iter) + { + result.push_back(iter->str()); + } + + return result; +} + +inline bool starts_with(std::string const& value, std::string const& starting) +{ + if (starting.size() > value.size()) return false; + return value.rfind(starting, 0) == 0; +} + +inline bool ends_with(std::string const& value, std::string const& ending) +{ + if (ending.size() > value.size()) return false; + return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); +} + +inline bool replaceOnce(std::string& str, const std::string& from, const std::string& to) +{ + size_t start_pos = str.find(from); + + if (start_pos == std::string::npos) + return false; + + str.replace(start_pos, from.length(), to); + + return true; +} + +inline void replaceAll(std::string& str, const char from, const char to) +{ + std::replace(str.begin(), str.end(), from, to); +} + +// Based on https://stackoverflow.com/a/13446015 +inline int getRandomInt(int min, int max) +{ + std::random_device rd; + std::mt19937::result_type seed = rd() ^ ( + (std::mt19937::result_type) + std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch() + ).count() + + (std::mt19937::result_type) + std::chrono::duration_cast( + std::chrono::high_resolution_clock::now().time_since_epoch() + ).count() + ); + + std::mt19937 gen(seed); + std::uniform_int_distribution distrib(min, max); + + return distrib(gen); +} + +inline std::chrono::time_point highResolutionNow() +{ + return std::chrono::high_resolution_clock::now(); +} + +inline long double elapsedMicroseconds(std::chrono::time_point startTime) +{ + return std::chrono::duration(highResolutionNow() - startTime).count(); +} + +bool fileExists(const char *filename); +bool dirExists(const char *dirname); diff --git a/src/voice.cpp b/src/voice.cpp new file mode 100644 index 0000000..18b104e --- /dev/null +++ b/src/voice.cpp @@ -0,0 +1,130 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#include "voice.h" + +#include "audio.h" +#include "game.h" +#include "patch.h" +#include "utils.h" + +#include +#include + +//============================================================================= + +int currentTxtFileId = -1; +int currenttxtDialogID = -1; +uint8_t currentPage = 0; + +int fieldId; +std::string* fieldName = new std::string(); + +bool play_voice(const char* field_name, uint32_t window_id, uint32_t dialog_id, uint8_t page_count) +{ + char name[MAX_PATH]; + + char page = 'a' + page_count; + if (page > 'z') page = 'z'; + + sprintf(name, "%s/w%u_%u%c", field_name, window_id, dialog_id, page); + + if (!nxAudioEngine.canPlayVoice(name)) + sprintf(name, "%s/%u%c", field_name, dialog_id, page); + + if (!nxAudioEngine.canPlayVoice(name) && page_count == 0) + { + sprintf(name, "%s/w%u_%u", field_name, window_id, dialog_id); + + if (!nxAudioEngine.canPlayVoice(name)) + sprintf(name, "%s/%u", field_name, dialog_id); + } + + return nxAudioEngine.playVoice(name, window_id); +} + +std::string* __fastcall sub_1B92D0(void* _this, void* _, void* a2, int txtFileId, int txtDialogID) { + if (txtFileId < 27 || txtFileId > 59) + return game_externals.sub_1B92D0(_this, a2, txtFileId, txtDialogID); + + currentTxtFileId = txtFileId; + currenttxtDialogID = txtDialogID; + + // Get current Field ID + game_externals.field_object = *(field_object**)calc_game_address_offset(0x41B4C4); + fieldId = game_externals.field_object->currentFieldId-1; + game_externals.get_game_string(_this, fieldName, 11, fieldId); + *fieldName = split(*fieldName, ",")[0]; + replaceOnce(*fieldName, "MSG_DEBUG_", ""); + + play_voice(fieldName->c_str(), 0, currenttxtDialogID, currentPage); + + return game_externals.sub_1B92D0(_this, a2, txtFileId, txtDialogID);; +} + +void __fastcall sub_next_page(MsgWindow* _this) { + if (_this->currentLineNoMaybe == 0 || currentTxtFileId == -1 || currenttxtDialogID == -1) + { + game_externals.sub_msgwindow_nextpage(_this); + + return; + } + + currentPage++; + + play_voice(fieldName->c_str(), 0, currenttxtDialogID, currentPage); + + game_externals.sub_msgwindow_nextpage(_this); +} + +// Called by CT when dialogue window closed +void __fastcall sub_195C70(MsgWindow* _this, void* _, int lineCount) { + currentTxtFileId = -1; + currenttxtDialogID = -1; + currentPage = 0; + + nxAudioEngine.stopVoice(); + + game_externals.sub_195C70(_this, lineCount); +} + +void voice_init() +{ + // Prepare up to 1 voice slots + nxAudioEngine.setVoiceMaxSlots(1); + + // Hook voice functions + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + // ------------------------------------ + DetourAttach((void**)&game_externals.sub_1B92D0, sub_1B92D0); + DetourAttach((void**)&game_externals.sub_msgwindow_nextpage, sub_next_page); + DetourAttach((void**)&game_externals.sub_195C70, sub_195C70); + // ------------------------------------ + DetourTransactionCommit(); +} + +void voice_term() +{ + // Hook voice functions + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + // ------------------------------------ + DetourDetach((void**)&game_externals.sub_1B92D0, sub_1B92D0); + DetourDetach((void**)&game_externals.sub_msgwindow_nextpage, sub_next_page); + DetourDetach((void**)&game_externals.sub_195C70, sub_195C70); + // ------------------------------------ + DetourTransactionCommit(); +} diff --git a/src/voice.h b/src/voice.h new file mode 100644 index 0000000..6a787d4 --- /dev/null +++ b/src/voice.h @@ -0,0 +1,37 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#pragma once + +static const char* KEY_PREFIXES[] = { + "CMES0", "CMES1", "CMES2", "CMES3", "CMES4", "CMES5", + "KMES0", "KMES1", "KMES2", + "MESI0", + "MESK0", "MESK1", "MESK2", "MESK3", "MESK4", + "MESS0", + "MEST0", "MEST1", "MEST2", "MEST3", "MEST4", "MEST5", + "MSG01", "MSG02", "MSG03", "MSG04", + "EXMS0", "EXMS1", "EXMS2", "EXMS3", + "QUES0", + "STAF", + "COMU0", +}; + +static const char* CHARACTER_NAMES[] = { + "crono", "marle", "lucca", "robo", "frog", "ayla", "magus" +}; + +void voice_init(); +void voice_term(); diff --git a/src/wine.h b/src/wine.h new file mode 100644 index 0000000..5ca2b5e --- /dev/null +++ b/src/wine.h @@ -0,0 +1,34 @@ +/****************************************************************************/ +// Copyright (C) 2024 Julian Xhokaxhiu // +// // +// This file is part of CTNx // +// // +// CTNx is free software: you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation, either version 3 of the License // +// // +// CTNx is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +/****************************************************************************/ + +#pragma once + +typedef const char* (*WineVersionFunction)(); +inline const char* GetWineVersion() { + HMODULE hModule = LoadLibraryA("ntdll.dll"); + if (!hModule) { + return "Wine is not detected."; + } + + WineVersionFunction wine_get_version = (WineVersionFunction)GetProcAddress(hModule, "wine_get_version"); + if (!wine_get_version) { + FreeLibrary(hModule); + return "Wine is not detected."; + } + + const char* version = wine_get_version(); + FreeLibrary(hModule); + return version; +} diff --git a/utils/FindSteamGamePath.exe b/utils/FindSteamGamePath.exe new file mode 100644 index 0000000..714a88c Binary files /dev/null and b/utils/FindSteamGamePath.exe differ diff --git a/vcpkg-configuration.json b/vcpkg-configuration.json new file mode 100644 index 0000000..e27127c --- /dev/null +++ b/vcpkg-configuration.json @@ -0,0 +1,17 @@ +{ + "registries": [ + { + "kind": "filesystem", + "path": ".vcpkg", + "packages": [ + "bx", + "hwinfo", + "libcocos2d", + "soloud", + "stackwalker", + "tomlplusplus", + "vgmstream" + ] + } + ] +} diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 0000000..143a1d3 --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,122 @@ +{ + "name": "ctnx", + "version": "0.0.1", + "builtin-baseline": "1de2026f28ead93ff1773e6e680387643e914ea1", + "dependencies": [ + { + "name": "ffmpeg", + "default-features": false, + "features": [ + "avcodec", + "avdevice", + "avfilter", + "avformat", + "avresample", + "postproc", + "swresample", + "swscale", + "amf", + "nvcodec", + "opencl", + "qsv", + "gpl", + "version3", + "dav1d", + "opus", + "speex", + "theora", + "vorbis", + "vpx", + "x264", + "x265" + ], + "platform": "windows" + }, + { + "name": "mimalloc", + "default-features": false, + "features": [ + "override", + "secure" + ] + }, + "soloud", + "stackwalker", + "tomlplusplus", + "vgmstream", + { + "name": "cpuinfo", + "default-features": false, + "features": [ + "tools" + ] + }, + "cmakerc", + "hwinfo", + "plog", + "detours", + "libcocos2d" + ], + "overrides": [ + { + "name": "ffmpeg", + "version": "6.1.1", + "port-version": 10 + }, + { + "name": "mimalloc", + "version": "2.1.2", + "port-version": 3 + }, + { + "name": "soloud", + "version": "1.0.0", + "port-version": 0 + }, + { + "name": "stackwalker", + "version": "1.2.1", + "port-version": 0 + }, + { + "name": "tomlplusplus", + "version": "3.4.0", + "port-version": 0 + }, + { + "name": "vgmstream", + "version": "1.0.0", + "port-version": 0 + }, + { + "name": "cpuinfo", + "version": "2022-07-19", + "port-version": 3 + }, + { + "name": "cmakerc", + "version": "2023-07-24", + "port-version": 0 + }, + { + "name": "hwinfo", + "version": "1.0.0", + "port-version": 0 + }, + { + "name": "plog", + "version": "1.1.10", + "port-version": 0 + }, + { + "name": "detours", + "version": "4.0.1", + "port-version": 8 + }, + { + "name": "libcocos2d", + "version": "3.14.1", + "port-version": 0 + } + ] +}