Merge branch 'develop-rando' of garrettjoecox.github.com:HarbourMasters/Shipwright into develop-rando-changes

This commit is contained in:
Garrett Cox 2024-04-04 08:15:34 -05:00
commit 325035e473
33 changed files with 424 additions and 437 deletions

View File

@ -1 +1 @@
libusb-dev libusb-1.0-0-dev libsdl2-dev libsdl2-net-dev libpng-dev libglew-dev ninja-build
libusb-dev libusb-1.0-0-dev libsdl2-dev libsdl2-net-dev libpng-dev libglew-dev libzip-dev zipcmp zipmerge ziptool ninja-build

View File

@ -92,14 +92,19 @@ jobs:
if [ -d /opt/local/ ]; then
echo "MacPorts already installed"
else
wget https://github.com/macports/macports-base/releases/download/v2.7.2/MacPorts-2.7.2-12-Monterey.pkg
sudo installer -pkg ./MacPorts-2.7.2-12-Monterey.pkg -target /
wget https://github.com/macports/macports-base/releases/download/v2.9.1/MacPorts-2.9.1-12-Monterey.pkg
sudo installer -pkg ./MacPorts-2.9.1-12-Monterey.pkg -target /
fi
echo "/opt/local/bin:/opt/local/sbin" >> $GITHUB_PATH
- name: Update MacPorts
if: ${{ !vars.MAC_RUNNER }}
run: |
sudo port selfupdate
sudo port upgrade outdated
- name: Install dependencies
if: ${{ !vars.MAC_RUNNER }}
run: |
brew uninstall --ignore-dependencies libpng
brew uninstall --ignore-dependencies libpng libzip
sudo port install $(cat .github/workflows/macports-deps.txt)
brew install ninja
- name: Download soh.otr
@ -175,6 +180,21 @@ jobs:
make -j 10
sudo make install
sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/
- name: Install latest libzip
if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) }}
run: |
sudo apt-get remove libzip-dev zipcmp zipmerge ziptool
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
if [ ! -d "libzip-1.10.1" ]; then
wget https://libzip.org/download/libzip-1.10.1.tar.gz
tar -xzvf libzip-1.10.1.tar.gz
fi
cd libzip-1.10.1
mkdir build
cd build
cmake ..
make
sudo make install
- name: Install latest SDL_net
if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) || (matrix.os == 'ubuntu-22.04' && !vars.LINUX_PERFORMANCE_RUNNER) }}
run: |
@ -224,6 +244,14 @@ jobs:
sudo apt-get remove -y cmake
wget https://github.com/Kitware/CMake/releases/download/v3.28.3/cmake-3.28.3-linux-x86_64.sh -O /tmp/cmake.sh
sudo sh /tmp/cmake.sh --prefix=/usr/local/ --exclude-subdir
wget https://libzip.org/download/libzip-1.10.1.tar.gz
tar -xzvf libzip-1.10.1.tar.gz
cd libzip-1.10.1
mkdir build
cd build
cmake -H.. -B. -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake
make
make install
- name: Fix dubious ownership error
if: ${{ vars.LINUX_RUNNER }}
run: git config --global --add safe.directory '*'
@ -270,6 +298,14 @@ jobs:
sudo apt-get remove -y cmake
wget https://github.com/Kitware/CMake/releases/download/v3.28.3/cmake-3.28.3-linux-x86_64.sh -O /tmp/cmake.sh
sudo sh /tmp/cmake.sh --prefix=/usr/local/ --exclude-subdir
wget https://libzip.org/download/libzip-1.10.1.tar.gz
tar -xzvf libzip-1.10.1.tar.gz
cd libzip-1.10.1
mkdir build
cd build
cmake -H.. -B. -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/WiiU.cmake
make
make install
- uses: actions/checkout@v3
with:
submodules: true

View File

@ -1 +1 @@
libsdl2 +universal libsdl2_net +universal libpng +universal glew +universal
libsdl2 +universal libsdl2_net +universal libpng +universal glew +universal libzip +universal

View File

@ -23,31 +23,31 @@ jobs:
if: ${{ matrix.image == 'archlinux:base' }}
run: |
echo arch
echo pacman -S ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng sdl2_net boost
echo pacman -S ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng libzip sdl2_net boost
pacman -Syu --noconfirm
pacman -S --noconfirm ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng sdl2_net boost
pacman -S --noconfirm ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng libzip sdl2_net boost
- name: Install dependencies (dnf)
if: ${{ matrix.image == 'fedora:39' }}
run: |
echo fedora
echo dnf install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} git cmake ninja-build lsb_release SDL2-devel libpng-devel boost-devel
echo dnf install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools boost-devel
dnf -y upgrade
dnf -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} git cmake ninja-build lsb_release SDL2-devel libpng-devel boost-devel
dnf -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools boost-devel
- name: Install dependencies (apt)
if: ${{ matrix.image == 'ubuntu:mantic' || matrix.image == 'debian:bookworm' }}
run: |
echo debian based
echo apt-get install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libboost-dev libopengl-dev
echo apt-get install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool libboost-dev libopengl-dev
apt-get update
apt-get -y full-upgrade
apt-get -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libboost-dev libopengl-dev
apt-get -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool libboost-dev libopengl-dev
- name: Install dependencies (zypper)
if: ${{ matrix.image == 'opensuse/tumbleweed:latest' }}
run: |
echo openSUSE
echo zypper in ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} ${{ matrix.cc == 'clang' && 'libstdc++-devel' || '' }} git cmake ninja SDL2-devel libpng16-devel
echo zypper in ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} ${{ matrix.cc == 'clang' && 'libstdc++-devel' || '' }} git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools
zypper --non-interactive dup
zypper --non-interactive in ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} ${{ matrix.cc == 'clang' && 'libstdc++-devel' || '' }} git cmake ninja SDL2-devel libpng16-devel
zypper --non-interactive in ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} ${{ matrix.cc == 'clang' && 'libstdc++-devel' || '' }} git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools
- uses: actions/checkout@v3
with:
submodules: true

View File

@ -5,8 +5,8 @@ set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use")
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")
project(Ship VERSION 8.0.4 LANGUAGES C CXX)
set(PROJECT_BUILD_NAME "MacReady Echo" CACHE STRING "")
project(Ship VERSION 8.0.5 LANGUAGES C CXX)
set(PROJECT_BUILD_NAME "MacReady Foxtrot" CACHE STRING "")
set(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "")
set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT soh)
@ -20,7 +20,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
set(VCPKG_TARGET_TRIPLET x64-windows-static)
vcpkg_bootstrap()
vcpkg_install_packages(zlib bzip2 libpng sdl2 sdl2-net glew glfw3)
vcpkg_install_packages(zlib bzip2 libzip libpng sdl2 sdl2-net glew glfw3)
if (CMAKE_C_COMPILER_LAUNCHER MATCHES "ccache|sccache")
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT Embedded)

View File

@ -88,34 +88,34 @@ cd "build/x64"
#### Debian/Ubuntu
```sh
# using gcc
apt-get install gcc g++ git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libboost-dev libopengl-dev
apt-get install gcc g++ git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool libboost-dev libopengl-dev
# or using clang
apt-get install clang git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libboost-dev libopengl-dev
apt-get install clang git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool libboost-dev libopengl-dev
```
#### Arch
```sh
# using gcc
pacman -S gcc git cmake ninja lsb-release sdl2 libpng sdl2_net boost
pacman -S gcc git cmake ninja lsb-release sdl2 libpng libzip sdl2_net boost
# or using clang
pacman -S clang git cmake ninja lsb-release sdl2 libpng sdl2_net boost
pacman -S clang git cmake ninja lsb-release sdl2 libpng libzip sdl2_net boost
```
#### Fedora
```sh
# using gcc
dnf install gcc gcc-c++ git cmake ninja-build lsb_release SDL2-devel libpng-devel boost-devel
dnf install gcc gcc-c++ git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools boost-devel
# or using clang
dnf install clang git cmake ninja-build lsb_release SDL2-devel libpng-devel boost-devel
dnf install clang git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools boost-devel
```
#### openSUSE
```sh
# using gcc
zypper in gcc gcc-c++ git cmake ninja SDL2-devel libpng16-devel boost
zypper in gcc gcc-c++ git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools
# or using clang
zypper in clang libstdc++-devel git cmake ninja SDL2-devel libpng16-devel boost
zypper in clang libstdc++-devel git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools
```
### Build
@ -123,34 +123,27 @@ zypper in clang libstdc++-devel git cmake ninja SDL2-devel libpng16-devel boost
_Note: If you're using Visual Studio Code, the [CMake Tools plugin](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools) makes it very easy to just press run and debug._
```bash
# Clone the repo
# Clone the repo and enter the directory
git clone https://github.com/HarbourMasters/Shipwright.git
cd Shipwright
# Clone the submodules
git submodule update --init
# Copy the baserom to the OTRExporter folder
cp <path to your ROM> OTRExporter
# Generate Ninja project
cmake -H. -Bbuild-cmake -GNinja # -DCMAKE_BUILD_TYPE:STRING=Release (if you're packaging) -DPython3_EXECUTABLE=$(which python3) (if you are using non-standard Python installations such as PyEnv)
# Extract assets & generate OTR (run this anytime you need to regenerate OTR)
cmake --build build-cmake --target ExtractAssets
# Generate soh.otr
cmake --build build-cmake --target GenerateSohOtr
# Compile the project
cmake --build build-cmake # --config Release (if you're packaging)
# Now you can run the executable in ./build-cmake/soh/soh.elf
# To develop the project open the repository in VSCode (or your preferred editor)
# If you need to clean the project you can run
cmake --build build-cmake --target clean
# If you need to regenerate the asset headers to check them into source
cmake --build build-cmake --target ExtractAssetHeaders
# If you need a newer soh.otr only
cmake --build build-cmake --target GenerateSohOtr
```
### Generating a distributable
### Generate a distributable
After compiling the project you can generate a distributable by running of the following:
```bash
# Go to build folder
@ -161,6 +154,20 @@ cpack -G ZIP
cpack -G External (creates appimage)
```
### Additional CMake Targets
#### Clean
```bash
# If you need to clean the project you can run
cmake --build build-cmake --target clean
```
#### Regenerate Asset Headers
```bash
# If you need to regenerate the asset headers to check them into source
cp <path to your ROM> OTRExporter
cmake --build build-cmake --target ExtractAssetHeaders
```
## macOS
Requires Xcode (or xcode-tools) && `sdl2, libpng, glew, ninja, cmake` (can be installed via homebrew, macports, etc)

@ -1 +1 @@
Subproject commit a516b66ce0c89fe4e33c55b1fbfbde845d0bf129
Subproject commit c3a699403793c9ac97733179fe078d2e2f271ee1

View File

@ -7,68 +7,6 @@ export RESPATH="${SNAME%/MacOS*}/Resources"
export LIBPATH="${SNAME%/MacOS*}/Frameworks"
export DYLD_FALLBACK_LIBRARY_PATH="$LIBPATH"
remap_hashes ()
{
# Remap v64 and n64 hashes to their z64 hash equivalent
# ZAPD will handle converting the data into z64 format
case "$ROMHASH" in
a9059b56e761c9034fbe02fe4c24985aaa835dac) # v64
ROMHASH=cee6bc3c2a634b41728f2af8da54d9bf8cc14099
;;
24708102dc504d3f375a37f4ae4e149c167dc515) # n64
ROMHASH=cee6bc3c2a634b41728f2af8da54d9bf8cc14099
;;
580dd0bd1b6d2c51cc20a764eece84dba558964c) # v64
ROMHASH=0227d7c0074f2d0ac935631990da8ec5914597b4
;;
d6342c59007e57c1194661ec6880b2f078403f4e) # n64
ROMHASH=0227d7c0074f2d0ac935631990da8ec5914597b4
;;
d0bdc2eb320668b4ba6893b9aefe4040a73123ff) # v64
ROMHASH=328a1f1beba30ce5e178f031662019eb32c5f3b5
;;
4946ab250f6ac9b32d76b21f309ebb8ebc8103d2) # n64
ROMHASH=328a1f1beba30ce5e178f031662019eb32c5f3b5
;;
663c34f1b2c05a09e5beffe4d0dcd440f7d49dc7) # v64
ROMHASH=cfbb98d392e4a9d39da8285d10cbef3974c2f012
;;
24c73d378b0620a380ce5ef9f2b186c6c157a68b) # n64
ROMHASH=cfbb98d392e4a9d39da8285d10cbef3974c2f012
;;
8ebf2e29313f44f2d49e5b4191971d09919e8e48) # v64
ROMHASH=f46239439f59a2a594ef83cf68ef65043b1bffe2
;;
4264bf7b875737b8fae77d52322a5099d051fc11) # n64
ROMHASH=f46239439f59a2a594ef83cf68ef65043b1bffe2
;;
973bc6fe56010a8d646166a1182a81b4f13b8cf9) # v64
ROMHASH=50bebedad9e0f10746a52b07239e47fa6c284d03
;;
d327752c46edc70ff3668b9514083dbbee08927c) # v64
ROMHASH=50bebedad9e0f10746a52b07239e47fa6c284d03
;;
ecdeb1747560834e079c22243febea7f6f26ba3b) # v64
ROMHASH=079b855b943d6ad8bd1eb026c0ed169ecbdac7da
;;
f19f8662ec7abee29484a272a6fda53e39efe0f1) # n64
ROMHASH=079b855b943d6ad8bd1eb026c0ed169ecbdac7da
;;
ab519ce04a33818ce2c39b3c514a751d807a494a) # v64
ROMHASH=cfecfdc58d650e71a200c81f033de4e6d617a9f6
;;
c19a34f7646305e1755249fca2071e178bd7cd00) # n64
ROMHASH=cfecfdc58d650e71a200c81f033de4e6d617a9f6
;;
25e8ae79ea0839ca5c984473f7460d8040c36f9c) # v64
ROMHASH=517bd9714c73cb96c21e7c2ef640d7b55186102f
;;
166c02770d67fcc3954c443eb400a6a3573d3fc0) # n64
ROMHASH=517bd9714c73cb96c21e7c2ef640d7b55186102f
;;
esac
}
if [ ! -e "$SHIP_HOME" ]; then mkdir "$SHIP_HOME"; fi
if [ ! -e "$SHIP_HOME"/mods ]; then
@ -76,178 +14,6 @@ if [ ! -e "$SHIP_HOME"/mods ]; then
touch "$SHIP_HOME"/mods/custom_otr_files_go_here.txt
fi
# If either OTR doesn't exist kick off the OTR gen process
if [ ! -e "$SHIP_HOME"/oot.otr ] || [ ! -e "$SHIP_HOME"/oot-mq.otr ]; then
# If no ROMs exist kick off the file selection prompts
while [ ! -e "$SHIP_HOME"/*.*64 ] && [ ! -e "$SHIP_HOME"/oot*.otr ]; do
SHOULD_PROMPT_FOR_ROM=1
while [ $SHOULD_PROMPT_FOR_ROM -eq 1 ]; do
SHOULD_PROMPT_FOR_ROM=0
# Use osascript to prompt the user to chose a file
DROPROM=`osascript <<-EOF
set romFile to choose file of type {"b64","n64","v64","z64"} with prompt "Please select your ROM:"
return POSIX path of romFile
EOF`
# If no rom was selected, the user cancelled, so exit
if [[ -z $DROPROM ]] && [[ -z "$UPLOAD_ANOTHER_RESULT" ]]; then
echo "No ROM selected. Exiting..."
exit 1
elif [[ -z $DROPROM ]]; then
break;
fi
# If an invalid rom was selected, let the user know and ask to try again
ROMHASH="$(shasum "$DROPROM" | awk '{ print $1 }')"
remap_hashes
case "$ROMHASH" in
cee6bc3c2a634b41728f2af8da54d9bf8cc14099)
ROM_TYPE=0;;
0227d7c0074f2d0ac935631990da8ec5914597b4)
ROM_TYPE=0;;
328a1f1beba30ce5e178f031662019eb32c5f3b5)
ROM_TYPE=0;;
cfbb98d392e4a9d39da8285d10cbef3974c2f012)
ROM_TYPE=0;;
f46239439f59a2a594ef83cf68ef65043b1bffe2)
ROM_TYPE=1;;
50bebedad9e0f10746a52b07239e47fa6c284d03)
ROM_TYPE=1;;
079b855b943d6ad8bd1eb026c0ed169ecbdac7da)
ROM_TYPE=1;;
cfecfdc58d650e71a200c81f033de4e6d617a9f6)
ROM_TYPE=1;;
517bd9714c73cb96c21e7c2ef640d7b55186102f)
ROM_TYPE=1;;
*)
TRY_AGAIN_RESULT=`osascript <<-EOF
set alertText to "Incompatible ROM hash"
set alertMessage to "Incompatible ROM provided, would you like to try again?"
return display alert alertText \
message alertMessage \
as critical \
buttons {"Cancel", "Try Again"}
EOF`
if [[ "$TRY_AGAIN_RESULT" == "button returned:Try Again" ]]; then
SHOULD_PROMPT_FOR_ROM=1
continue;
else
echo "No ROM selected. Exiting..."
exit 1
fi
esac
cp "$DROPROM" "$SHIP_HOME"
# Ask user if they would also like to select the other variant (MQ/Vanilla)
if [ $ROM_TYPE -eq 0 ] && [[ -z "$UPLOAD_ANOTHER_RESULT" ]]; then
UPLOAD_ANOTHER_RESULT=`osascript <<-EOF
set alertText to "Success"
set alertMessage to "Would you also like to provide a Master Quest ROM?"
return display alert alertText \
message alertMessage \
buttons {"No", "Yes"}
EOF`
elif [[ -z "$UPLOAD_ANOTHER_RESULT" ]]; then
UPLOAD_ANOTHER_RESULT=`osascript <<-EOF
set alertText to "Success"
set alertMessage to "Would you also like to provide a Vanilla (Non Master Quest) ROM?"
return display alert alertText \
message alertMessage \
buttons {"No", "Yes"}
EOF`
fi
if [[ "$UPLOAD_ANOTHER_RESULT" == "button returned:Yes" ]]; then
UPLOAD_ANOTHER_RESULT="button returned:No"
SHOULD_PROMPT_FOR_ROM=1
continue;
fi
break
done
done
# At this point we should now have 1 or more valid roms in $SHIP_HOME directory
# Prepare tmp dir
for ROMPATH in "$SHIP_HOME"/*.*64
do
ASSETDIR="$(mktemp -d /tmp/assets-XXXXX)"
export ASSETDIR
cp -r "$RESPATH/assets" "$ASSETDIR"
mkdir -p "$ASSETDIR"/tmp
cp "$ROMPATH" "$ASSETDIR"/tmp/rom.z64
cd "$ASSETDIR" || return
# If an invalid rom was detected, let the user know
ROMHASH="$(shasum "$ASSETDIR"/tmp/rom.z64 | awk '{ print $1 }')"
remap_hashes
case "$ROMHASH" in
cee6bc3c2a634b41728f2af8da54d9bf8cc14099)
ROM=GC_NMQ_D
OTRNAME="oot.otr";;
0227d7c0074f2d0ac935631990da8ec5914597b4)
ROM=GC_NMQ_PAL_F
OTRNAME="oot.otr";;
328a1f1beba30ce5e178f031662019eb32c5f3b5)
ROM=N64_PAL_10
OTRNAME="oot.otr";;
cfbb98d392e4a9d39da8285d10cbef3974c2f012)
ROM=N64_PAL_11
OTRNAME="oot.otr";;
f46239439f59a2a594ef83cf68ef65043b1bffe2)
ROM=GC_MQ_PAL_F
OTRNAME="oot-mq.otr";;
50bebedad9e0f10746a52b07239e47fa6c284d03)
ROM=GC_MQ_D
OTRNAME="oot-mq.otr";;
079b855b943d6ad8bd1eb026c0ed169ecbdac7da)
ROM=GC_MQ_D
OTRNAME="oot-mq.otr";;
cfecfdc58d650e71a200c81f033de4e6d617a9f6)
ROM=GC_MQ_D
OTRNAME="oot-mq.otr";;
517bd9714c73cb96c21e7c2ef640d7b55186102f)
ROM=GC_MQ_D
OTRNAME="oot-mq.otr";;
*)
osascript -e 'display notification "One or more invalid ROM provided" with title "Ship Of Harkinian"'
rm -r "$ASSETDIR"
cd "$SNAME"
continue;
esac
# Only generate OTR if we don't have on of this type yet
if [ -e "$SHIP_HOME"/"$OTRNAME" ]; then
rm -r "$ASSETDIR"
cd "$SNAME"
continue;
fi
osascript -e 'display notification "Generating OTR..." with title "Ship Of Harkinian"'
assets/extractor/ZAPD.out ed -i assets/extractor/xmls/"${ROM}" -b tmp/rom.z64 -fl assets/extractor/filelists -o placeholder -osf placeholder -gsf 1 -rconf assets/extractor/Config_"${ROM}".xml -se OTR --portVer "@CMAKE_PROJECT_VERSION@"
if [ -e "$ASSETDIR"/oot.otr ]; then
osascript -e 'display notification "OTR successfully generated" with title "Ship Of Harkinian"'
cp "$ASSETDIR"/oot.otr "$SHIP_HOME"/"$OTRNAME"
rm -r "$ASSETDIR"
cd "$SNAME"
fi
done
if [ ! -e "$SHIP_HOME"/oot*.otr ]; then
osascript -e 'display notification "OTR failed to generate" with title "Ship Of Harkinian"'
exit 1;
fi
fi
cd "$SNAME"
"$RESPATH"/soh-macos
exit

View File

@ -893,7 +893,7 @@ static void RandomizeDungeonItems() {
std::vector<RandomizerGet> overworldItems;
for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) {
if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON)) {
if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON)) {
auto dungeonKeys = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i){return (i == dungeon->GetSmallKey()) || (i == dungeon->GetKeyRing());});
AddElementsToPool(anyDungeonItems, dungeonKeys);
} else if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD)) {

View File

@ -1377,7 +1377,7 @@ void DrawLocation(RandomizerCheck rc) {
: CVarGetColor("gCheckTrackerSeenMainColor", Color_Main_Default);
extraColor = CVarGetColor("gCheckTrackerSeenExtraColor", Color_Seen_Extra_Default);
} else if (status == RCSHOW_SCUMMED) {
if (!showHidden && CVarGetInteger("gCheckTrackerKnownHide", 0)) {
if (!showHidden && CVarGetInteger("gCheckTrackerScummedHide", 0)) {
return;
}
mainColor =

View File

@ -396,6 +396,11 @@ void Entrance_SetSavewarpEntrance(void) {
gSaveContext.entranceIndex = ENTR_THIEVES_HIDEOUT_0; // Gerudo Fortress -> Thieve's Hideout spawn 0
} else if (scene == SCENE_LINKS_HOUSE) {
gSaveContext.entranceIndex = Entrance_OverrideNextIndex(ENTR_LINKS_HOUSE_0);
} else if (CVarGetInteger("gRememberSaveLocation", 0) && scene != SCENE_FAIRYS_FOUNTAIN && scene != SCENE_GROTTOS &&
gSaveContext.entranceIndex != ENTR_LOAD_OPENING) {
// Use the saved entrance value with remember save location, except when in grottos/fairy fountains or if
// the entrance index is -1 (new save)
return;
} else if (LINK_IS_CHILD) {
gSaveContext.entranceIndex = Entrance_OverrideNextIndex(ENTR_LINKS_HOUSE_0); // Child Overworld Spawn
} else {

View File

@ -0,0 +1,16 @@
#include "SpeechLogger.h"
#include <libultraship/libultraship.h>
SpeechLogger::SpeechLogger() {
}
void SpeechLogger::Speak(const char* text, const char* language) {
lusprintf(__FILE__, __LINE__, 2, "Spoken Text (%s): %s", language, text);
}
bool SpeechLogger::DoInit() {
return true;
}
void SpeechLogger::DoUninitialize() {
}

View File

@ -0,0 +1,17 @@
#ifndef SOHSpeechLogger_h
#define SOHSpeechLogger_h
#include "SpeechSynthesizer.h"
class SpeechLogger : public SpeechSynthesizer {
public:
SpeechLogger();
void Speak(const char* text, const char* language);
protected:
bool DoInit(void);
void DoUninitialize(void);
};
#endif

View File

@ -36,3 +36,5 @@ class SpeechSynthesizer {
#elif defined(__APPLE__)
#include "DarwinSpeechSynthesizer.h"
#endif
#include "SpeechLogger.h"

View File

@ -11,6 +11,8 @@
#include "message_data_static.h"
#include "overlays/gamestates/ovl_file_choose/file_choose.h"
#include "soh/Enhancements/boss-rush/BossRush.h"
#include "soh/resource/type/SohResourceType.h"
#include "soh/resource/type/RawJson.h"
extern "C" {
extern MapData* gMapData;
@ -1037,25 +1039,22 @@ void InitTTSBank() {
break;
}
auto sceneFile = LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->LoadFileRaw("accessibility/texts/scenes" + languageSuffix);
if (sceneFile != nullptr) {
sceneMap = nlohmann::json::parse(*sceneFile->Buffer.get(), nullptr, true, true);
}
auto initData = std::make_shared<LUS::ResourceInitData>();
initData->Format = RESOURCE_FORMAT_BINARY;
initData->Type = static_cast<uint32_t>(SOH::ResourceType::SOH_RawJson);
initData->ResourceVersion = 0;
auto miscFile = LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->LoadFileRaw("accessibility/texts/misc" + languageSuffix);
if (miscFile != nullptr) {
miscMap = nlohmann::json::parse(*miscFile->Buffer.get(), nullptr, true, true);
}
sceneMap = std::static_pointer_cast<SOH::RawJson>(
LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/scenes" + languageSuffix, true, initData))->Data;
auto kaleidoFile = LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->LoadFileRaw("accessibility/texts/kaleidoscope" + languageSuffix);
if (kaleidoFile != nullptr) {
kaleidoMap = nlohmann::json::parse(*kaleidoFile->Buffer.get(), nullptr, true, true);
}
miscMap = std::static_pointer_cast<SOH::RawJson>(
LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/misc" + languageSuffix, true, initData))->Data;
auto fileChooseFile = LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->LoadFileRaw("accessibility/texts/filechoose" + languageSuffix);
if (fileChooseFile != nullptr) {
fileChooseMap = nlohmann::json::parse(*fileChooseFile->Buffer.get(), nullptr, true, true);
}
kaleidoMap = std::static_pointer_cast<SOH::RawJson>(
LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/kaleidoscope" + languageSuffix, true, initData))->Data;
fileChooseMap = std::static_pointer_cast<SOH::RawJson>(
LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/filechoose" + languageSuffix, true, initData))->Data;
}
void RegisterOnSetGameLanguageHook() {

View File

@ -14,8 +14,6 @@ void OTRGetPixelDepthPrepare(float x, float y);
uint16_t OTRGetPixelDepth(float x, float y);
int32_t OTRGetLastScancode();
void ResourceMgr_LoadDirectory(const char* resName);
void ResourceMgr_LoadFile(const char* resName);
char* ResourceMgr_LoadFileFromDisk(const char* filePath);
uint16_t ResourceMgr_LoadTexWidthByName(char* texPath);
uint16_t ResourceMgr_LoadTexHeightByName(char* texPath);
size_t ResourceGetTexSizeByName(const char* name);

View File

@ -120,6 +120,7 @@ GameInteractorSail* GameInteractorSail::Instance;
#include "soh/resource/importer/SkeletonLimbFactory.h"
#include "soh/resource/importer/TextFactory.h"
#include "soh/resource/importer/BackgroundFactory.h"
#include "soh/resource/importer/RawJsonFactory.h"
#include "soh/config/ConfigUpdaters.h"
@ -271,7 +272,10 @@ OTRGlobals::OTRGlobals() {
if (patchesPath.length() > 0 && std::filesystem::exists(patchesPath)) {
if (std::filesystem::is_directory(patchesPath)) {
for (const auto& p : std::filesystem::recursive_directory_iterator(patchesPath, std::filesystem::directory_options::follow_directory_symlink)) {
if (StringHelper::IEquals(p.path().extension().string(), ".otr")) {
if (StringHelper::IEquals(p.path().extension().string(), ".otr") ||
StringHelper::IEquals(p.path().extension().string(), ".mpq") ||
StringHelper::IEquals(p.path().extension().string(), ".o2r") ||
StringHelper::IEquals(p.path().extension().string(), ".zip")) {
patchOTRs.push_back(p.path().generic_string());
}
}
@ -308,6 +312,7 @@ OTRGlobals::OTRGlobals() {
context = LUS::Context::CreateUninitializedInstance("Ship of Harkinian", appShortName, "shipofharkinian.json");
context->InitLogging();
context->InitGfxDebugger();
context->InitConfiguration();
context->InitConsoleVariables();
@ -344,6 +349,7 @@ OTRGlobals::OTRGlobals() {
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryAudioSoundFontV2>(), RESOURCE_FORMAT_BINARY, "AudioSoundFont", static_cast<uint32_t>(SOH::ResourceType::SOH_AudioSoundFont), 2);
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryAudioSequenceV2>(), RESOURCE_FORMAT_BINARY, "AudioSequence", static_cast<uint32_t>(SOH::ResourceType::SOH_AudioSequence), 2);
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryBackgroundV0>(), RESOURCE_FORMAT_BINARY, "Background", static_cast<uint32_t>(SOH::ResourceType::SOH_Background), 0);
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryRawJsonV0>(), RESOURCE_FORMAT_BINARY, "RawJson", static_cast<uint32_t>(SOH::ResourceType::SOH_RawJson), 0);
gSaveStateMgr = std::make_shared<SaveStateMgr>();
gRandoContext = Rando::Context::CreateInstance();
@ -876,8 +882,8 @@ OTRVersion ReadPortVersionFromOTR(std::string otrPath) {
// Use a temporary archive instance to load the otr and read the version file
auto archive = LUS::OtrArchive(otrPath);
if (archive.LoadRaw()) {
auto t = archive.LoadFileRaw("portVersion");
if (archive.Open()) {
auto t = archive.LoadFile("portVersion", std::make_shared<LUS::ResourceInitData>());
if (t != nullptr && t->IsLoaded) {
auto stream = std::make_shared<LUS::MemoryStream>(t->Buffer->data(), t->Buffer->size());
auto reader = std::make_shared<LUS::BinaryReader>(stream);
@ -887,7 +893,7 @@ OTRVersion ReadPortVersionFromOTR(std::string otrPath) {
version.minor = reader->ReadUInt16();
version.patch = reader->ReadUInt16();
}
archive.UnloadRaw();
archive.Close();
}
return version;
@ -1116,6 +1122,9 @@ extern "C" void InitOTR() {
#elif defined(_WIN32)
SpeechSynthesizer::Instance = new SAPISpeechSynthesizer();
SpeechSynthesizer::Instance->Init();
#else
SpeechSynthesizer::Instance = new SpeechLogger();
SpeechSynthesizer::Instance->Init();
#endif
#ifdef ENABLE_REMOTE_CONTROL
@ -1589,10 +1598,6 @@ extern "C" void ResourceMgr_UnloadOriginalWhenAltExists(const char* resName) {
}
}
extern "C" void ResourceMgr_LoadFile(const char* resName) {
LUS::Context::GetInstance()->GetResourceManager()->LoadResource(resName);
}
std::shared_ptr<LUS::IResource> GetResourceByNameHandlingMQ(const char* path) {
std::string Path = path;
if (ResourceMgr_IsGameMasterQuest()) {
@ -1614,20 +1619,6 @@ extern "C" char* GetResourceDataByNameHandlingMQ(const char* path) {
return (char*)res->GetRawPointer();
}
extern "C" char* ResourceMgr_LoadFileFromDisk(const char* filePath) {
FILE* file = fopen(filePath, "r");
fseek(file, 0, SEEK_END);
int fSize = ftell(file);
fseek(file, 0, SEEK_SET);
char* data = (char*)malloc(fSize);
fread(data, 1, fSize, file);
fclose(file);
return data;
}
extern "C" uint8_t ResourceMgr_TexIsRaw(const char* texPath) {
auto res = std::static_pointer_cast<LUS::Texture>(GetResourceByNameHandlingMQ(texPath));
return res->Flags & TEX_FLAG_LOAD_AS_RAW;

View File

@ -97,8 +97,6 @@ uint8_t ResourceMgr_FileExists(const char* resName);
uint8_t ResourceMgr_FileAltExists(const char* resName);
void ResourceMgr_UnloadOriginalWhenAltExists(const char* resName);
char* GetResourceDataByNameHandlingMQ(const char* path);
void ResourceMgr_LoadFile(const char* resName);
char* ResourceMgr_LoadFileFromDisk(const char* filePath);
uint8_t ResourceMgr_TexIsRaw(const char* texPath);
uint8_t ResourceMgr_ResourceIsBackground(char* texPath);
char* ResourceMgr_LoadJPEG(char* data, size_t dataSize);

View File

@ -13,6 +13,7 @@
#include <variables.h>
#include "soh/Enhancements/boss-rush/BossRush.h"
#include <libultraship/libultraship.h>
#include "SohGui.hpp"
#define NOGDI // avoid various windows defines that conflict with things in z64.h
#include <spdlog/spdlog.h>
@ -1185,51 +1186,67 @@ void SaveManager::SaveGlobal() {
void SaveManager::LoadFile(int fileNum) {
SPDLOG_INFO("Load File - fileNum: {}", fileNum);
assert(std::filesystem::exists(GetFileName(fileNum)));
std::filesystem::path fileName = GetFileName(fileNum);
assert(std::filesystem::exists(fileName));
InitFile(false);
std::ifstream input(GetFileName(fileNum));
std::ifstream input(fileName);
saveBlock = nlohmann::json::object();
input >> saveBlock;
if (!saveBlock.contains("version")) {
SPDLOG_ERROR("Save at " + GetFileName(fileNum).string() + " contains no version");
assert(false);
}
switch (saveBlock["version"].get<int>()) {
case 1:
for (auto& block : saveBlock["sections"].items()) {
int sectionVersion = block.value()["version"];
std::string sectionName = block.key();
if (!sectionLoadHandlers.contains(sectionName)) {
// Unloadable sections aren't necessarily errors, they are probably mods that were unloaded
// TODO report in a more noticeable manner
SPDLOG_WARN("Save " + GetFileName(fileNum).string() + " contains unloadable section " + sectionName);
continue;
}
SectionLoadHandler& handler = sectionLoadHandlers[sectionName];
if (!handler.contains(sectionVersion)) {
// A section that has a loader without a handler for the specific version means that the user has a mod
// at an earlier version than the save has. In this case, the user probably wants to load the save.
// Report the error so that the user can rectify the error.
// TODO report in a more noticeable manner
SPDLOG_ERROR("Save " + GetFileName(fileNum).string() + " contains section " + sectionName +
" with an unloadable version " + std::to_string(sectionVersion));
assert(false);
continue;
}
currentJsonContext = &block.value()["data"];
handler[sectionVersion]();
}
break;
default:
SPDLOG_ERROR("Unrecognized save version " + std::to_string(saveBlock["version"].get<int>()) + " in " +
GetFileName(fileNum).string());
try {
saveBlock = nlohmann::json::object();
input >> saveBlock;
if (!saveBlock.contains("version")) {
SPDLOG_ERROR("Save at " + fileName.string() + " contains no version");
assert(false);
break;
}
switch (saveBlock["version"].get<int>()) {
case 1:
for (auto& block : saveBlock["sections"].items()) {
int sectionVersion = block.value()["version"];
std::string sectionName = block.key();
if (!sectionLoadHandlers.contains(sectionName)) {
// Unloadable sections aren't necessarily errors, they are probably mods that were unloaded
// TODO report in a more noticeable manner
SPDLOG_WARN("Save " + GetFileName(fileNum).string() + " contains unloadable section " +
sectionName);
continue;
}
SectionLoadHandler& handler = sectionLoadHandlers[sectionName];
if (!handler.contains(sectionVersion)) {
// A section that has a loader without a handler for the specific version means that the user
// has a mod at an earlier version than the save has. In this case, the user probably wants to
// load the save. Report the error so that the user can rectify the error.
// TODO report in a more noticeable manner
SPDLOG_ERROR("Save " + GetFileName(fileNum).string() + " contains section " + sectionName +
" with an unloadable version " + std::to_string(sectionVersion));
assert(false);
continue;
}
currentJsonContext = &block.value()["data"];
handler[sectionVersion]();
}
break;
default:
SPDLOG_ERROR("Unrecognized save version " + std::to_string(saveBlock["version"].get<int>()) + " in " +
GetFileName(fileNum).string());
assert(false);
break;
}
InitMeta(fileNum);
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnLoadFile>(fileNum);
} catch (const std::exception& e) {
input.close();
std::filesystem::path newFile(LUS::Context::GetPathRelativeToAppDirectory("Save") + ("/file" + std::to_string(fileNum + 1) + "-" + std::to_string(GetUnixTimestamp()) + ".bak"));
#if defined(__SWITCH__) || defined(__WIIU__)
copy_file(fileName.c_str(), newFile.c_str());
#else
std::filesystem::copy_file(fileName, newFile);
#endif
std::filesystem::remove(fileName);
SohGui::RegisterPopup("Error loading save file", "A problem occurred loading the save in slot " + std::to_string(fileNum + 1) + ".\nSave file corruption is suspected.\n" +
"The file has been renamed to prevent further issues.");
}
InitMeta(fileNum);
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnLoadFile>(fileNum);
}
void SaveManager::ThreadPoolWait() {

View File

@ -133,8 +133,8 @@ namespace SohGui {
std::shared_ptr<ItemTrackerSettingsWindow> mItemTrackerSettingsWindow;
std::shared_ptr<ItemTrackerWindow> mItemTrackerWindow;
std::shared_ptr<RandomizerSettingsWindow> mRandomizerSettingsWindow;
std::shared_ptr<AdvancedResolutionSettings::AdvancedResolutionSettingsWindow> mAdvancedResolutionSettingsWindow;
std::shared_ptr<SohModalWindow> mModalWindow;
void SetupGuiElements() {
auto gui = LUS::Context::GetInstance()->GetWindow()->GetGui();
@ -201,9 +201,13 @@ namespace SohGui {
gui->AddGuiWindow(mRandomizerSettingsWindow);
mAdvancedResolutionSettingsWindow = std::make_shared<AdvancedResolutionSettings::AdvancedResolutionSettingsWindow>("gAdvancedResolutionEditorEnabled", "Advanced Resolution Settings");
gui->AddGuiWindow(mAdvancedResolutionSettingsWindow);
mModalWindow = std::make_shared<SohModalWindow>("gOpenWindows.modalWindowEnabled", "Modal Window");
gui->AddGuiWindow(mModalWindow);
mModalWindow->Show();
}
void Destroy() {
mModalWindow = nullptr;
mAdvancedResolutionSettingsWindow = nullptr;
mRandomizerSettingsWindow = nullptr;
mItemTrackerWindow = nullptr;
@ -227,4 +231,8 @@ namespace SohGui {
mInputViewer = nullptr;
mInputViewerSettings = nullptr;
}
void RegisterPopup(std::string title, std::string message, std::string button1, std::string button2, std::function<void()> button1callback, std::function<void()> button2callback) {
mModalWindow->RegisterPopup(title, message, button1, button2, button1callback, button2callback);
}
}

View File

@ -23,6 +23,7 @@
#include "Enhancements/randomizer/randomizer_entrance_tracker.h"
#include "Enhancements/randomizer/randomizer_item_tracker.h"
#include "Enhancements/randomizer/randomizer_settings_window.h"
#include "SohModals.h"
#ifdef __cplusplus
extern "C" {
@ -38,6 +39,7 @@ namespace SohGui {
void SetupGuiElements();
void Draw();
void Destroy();
void RegisterPopup(std::string title, std::string message, std::string button1 = "OK", std::string button2 = "", std::function<void()> button1callback = nullptr, std::function<void()> button2callback = nullptr);
}
#endif /* SohGui_hpp */

View File

@ -688,7 +688,7 @@ void DrawEnhancementsMenu() {
UIWidgets::Tooltip("Allows you to change the number of days it takes for Biggoron to forge the Biggoron Sword");
UIWidgets::PaddedEnhancementCheckbox("Remember Save Location", "gRememberSaveLocation", false, false);
UIWidgets::Tooltip("When loading a save, places Link at the last entrance he went through.\n"
"This doesn't work if the save was made in a grotto.");
"This doesn't work if the save was made in grottos/fairy fountains or dungeons.");
UIWidgets::PaddedEnhancementCheckbox("No Forced Navi", "gNoForcedNavi", true, false);
UIWidgets::Tooltip("Prevent forced Navi conversations");
UIWidgets::PaddedEnhancementCheckbox("Navi Timer Resets", "gEnhancements.ResetNaviTimer", true, false);

54
soh/soh/SohModals.cpp Normal file
View File

@ -0,0 +1,54 @@
#include "SohModals.h"
#include "ImGui/imgui.h"
#include <vector>
#include <string>
#include <libultraship/bridge.h>
#include <libultraship/libultraship.h>
#include "UIWidgets.hpp"
#include "OTRGlobals.h"
#include "z64.h"
extern "C" PlayState* gPlayState;
struct SohModal {
std::string title_;
std::string message_;
std::string button1_;
std::string button2_;
std::function<void()> button1callback_;
std::function<void()> button2callback_;
};
std::vector<SohModal> modals;
void SohModalWindow::DrawElement() {
if (modals.size() > 0) {
SohModal curModal = modals.at(0);
if (!ImGui::IsPopupOpen(curModal.title_.c_str())) {
ImGui::OpenPopup(curModal.title_.c_str());
}
if (ImGui::BeginPopupModal(curModal.title_.c_str(), NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings)) {
ImGui::Text(curModal.message_.c_str());
if (ImGui::Button(curModal.button1_.c_str())) {
if (curModal.button1callback_ != nullptr) {
curModal.button1callback_();
}
ImGui::CloseCurrentPopup();
modals.erase(modals.begin());
}
ImGui::SameLine();
if (curModal.button2_ != "") {
if (ImGui::Button(curModal.button2_.c_str())) {
if (curModal.button2callback_ != nullptr) {
curModal.button2callback_();
}
ImGui::CloseCurrentPopup();
modals.erase(modals.begin());
}
}
}
ImGui::EndPopup();
}
}
void SohModalWindow::RegisterPopup(std::string title, std::string message, std::string button1, std::string button2, std::function<void()> button1callback, std::function<void()> button2callback) {
modals.push_back({ title, message, button1, button2, button1callback, button2callback });
}

15
soh/soh/SohModals.h Normal file
View File

@ -0,0 +1,15 @@
#pragma once
#include <libultraship/libultraship.h>
#include "window/gui/GuiMenuBar.h"
#include "window/gui/GuiElement.h"
class SohModalWindow : public LUS::GuiWindow {
public:
using LUS::GuiWindow::GuiWindow;
void InitElement() override {};
void DrawElement() override;
void UpdateElement() override {};
void RegisterPopup(std::string title, std::string message, std::string button1 = "OK", std::string button2 = "", std::function<void()> button1callback = nullptr, std::function<void()> button2callback = nullptr);
};

View File

@ -0,0 +1,19 @@
#include "soh/resource/importer/RawJsonFactory.h"
#include "soh/resource/type/RawJson.h"
#include "spdlog/spdlog.h"
namespace SOH {
std::shared_ptr<LUS::IResource> ResourceFactoryBinaryRawJsonV0::ReadResource(std::shared_ptr<LUS::File> file) {
if (!FileHasValidFormatAndReader(file)) {
return nullptr;
}
auto rawJson = std::make_shared<RawJson>(file->InitData);
auto reader = std::get<std::shared_ptr<LUS::BinaryReader>>(file->Reader);
rawJson->DataSize = file->Buffer->size();
rawJson->Data = nlohmann::json::parse(reader->ReadCString(), nullptr, true, true);
return rawJson;
}
} // namespace SOH

View File

@ -0,0 +1,11 @@
#pragma once
#include "resource/Resource.h"
#include "resource/ResourceFactoryBinary.h"
namespace SOH {
class ResourceFactoryBinaryRawJsonV0 : public LUS::ResourceFactoryBinary {
public:
std::shared_ptr<LUS::IResource> ReadResource(std::shared_ptr<LUS::File> file) override;
};
}; // namespace SOH

View File

@ -0,0 +1,14 @@
#include "RawJson.h"
namespace SOH {
RawJson::RawJson() : Resource(std::shared_ptr<LUS::ResourceInitData>()) {
}
void* RawJson::GetPointer() {
return &Data;
}
size_t RawJson::GetPointerSize() {
return DataSize * sizeof(char);
}
} // namespace SOH

View File

@ -0,0 +1,20 @@
#pragma once
#include "resource/Resource.h"
#include <nlohmann/json.hpp>
namespace SOH {
class RawJson : public LUS::Resource<void> {
public:
using Resource::Resource;
RawJson();
void* GetPointer() override;
size_t GetPointerSize() override;
nlohmann::json Data;
size_t DataSize;
};
}; // namespace SOH

View File

@ -17,5 +17,6 @@ enum class ResourceType {
SOH_AudioSequence = 0x4F534551, // OSEQ
SOH_Background = 0x4F424749, // OBGI
SOH_SceneCommand = 0x4F52434D, // ORCM
SOH_RawJson = 0x4A534F4E, // JSON
};
} // namespace SOH

View File

@ -39,17 +39,6 @@ extern "C" s32 Object_Spawn(ObjectContext* objectCtx, s16 objectId);
extern "C" RomFile sNaviMsgFiles[];
s32 OTRScene_ExecuteCommands(PlayState* play, SOH::Scene* scene);
std::shared_ptr<LUS::File> ResourceMgr_LoadFile(const char* path) {
std::string Path = path;
if (IsGameMasterQuest()) {
size_t pos = 0;
if ((pos = Path.find("/nonmq/", 0)) != std::string::npos) {
Path.replace(pos, 7, "/mq/");
}
}
return LUS::Context::GetInstance()->GetResourceManager()->LoadFile(Path.c_str());
}
// Forward Declaration of function declared in OTRGlobals.cpp
std::shared_ptr<LUS::IResource> GetResourceByNameHandlingMQ(const char* path);

View File

@ -8,6 +8,7 @@
#include "textures/message_static/message_static.h"
#include "textures/message_texture_static/message_texture_static.h"
#include "soh/Enhancements/cosmetics/cosmeticsTypes.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/OTRGlobals.h"
@ -3087,7 +3088,9 @@ void Message_Draw(PlayState* play) {
POLY_OPA_DISP = plusOne;
}
plusOne = Graph_GfxPlusOne(polyOpaP = POLY_OPA_DISP);
gSPDisplayList(OVERLAY_DISP++, plusOne);
if (!GameInteractor_NoUIActive()) {
gSPDisplayList(OVERLAY_DISP++, plusOne);
}
Message_DrawMain(play, &plusOne);
gSPEndDisplayList(plusOne++);
Graph_BranchDlist(polyOpaP, plusOne);

View File

@ -74,65 +74,68 @@ void Sram_OpenSave() {
Save_LoadFile();
if (!CVarGetInteger("gRememberSaveLocation", 0) || gSaveContext.savedSceneNum == SCENE_FAIRYS_FOUNTAIN ||
gSaveContext.savedSceneNum == SCENE_GROTTOS) {
switch (gSaveContext.savedSceneNum) {
case SCENE_DEKU_TREE:
case SCENE_DODONGOS_CAVERN:
case SCENE_JABU_JABU:
case SCENE_FOREST_TEMPLE:
case SCENE_FIRE_TEMPLE:
case SCENE_WATER_TEMPLE:
case SCENE_SPIRIT_TEMPLE:
case SCENE_SHADOW_TEMPLE:
case SCENE_BOTTOM_OF_THE_WELL:
case SCENE_ICE_CAVERN:
case SCENE_GANONS_TOWER:
case SCENE_GERUDO_TRAINING_GROUND:
case SCENE_THIEVES_HIDEOUT:
case SCENE_INSIDE_GANONS_CASTLE:
gSaveContext.entranceIndex = sDungeonEntrances[gSaveContext.savedSceneNum];
break;
case SCENE_DEKU_TREE_BOSS:
gSaveContext.entranceIndex = ENTR_DEKU_TREE_0;
break;
case SCENE_DODONGOS_CAVERN_BOSS:
gSaveContext.entranceIndex = ENTR_DODONGOS_CAVERN_0;
break;
case SCENE_JABU_JABU_BOSS:
gSaveContext.entranceIndex = ENTR_JABU_JABU_0;
break;
case SCENE_FOREST_TEMPLE_BOSS:
gSaveContext.entranceIndex = ENTR_FOREST_TEMPLE_0;
break;
case SCENE_FIRE_TEMPLE_BOSS:
gSaveContext.entranceIndex = ENTR_FIRE_TEMPLE_0;
break;
case SCENE_WATER_TEMPLE_BOSS:
gSaveContext.entranceIndex = ENTR_WATER_TEMPLE_0;
break;
case SCENE_SPIRIT_TEMPLE_BOSS:
gSaveContext.entranceIndex = ENTR_SPIRIT_TEMPLE_0;
break;
case SCENE_SHADOW_TEMPLE_BOSS:
gSaveContext.entranceIndex = ENTR_SHADOW_TEMPLE_0;
break;
case SCENE_GANONS_TOWER_COLLAPSE_INTERIOR:
case SCENE_INSIDE_GANONS_CASTLE_COLLAPSE:
case SCENE_GANONDORF_BOSS:
case SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR:
case SCENE_GANON_BOSS:
gSaveContext.entranceIndex = ENTR_GANONS_TOWER_0;
break;
switch (gSaveContext.savedSceneNum) {
case SCENE_DEKU_TREE:
case SCENE_DODONGOS_CAVERN:
case SCENE_JABU_JABU:
case SCENE_FOREST_TEMPLE:
case SCENE_FIRE_TEMPLE:
case SCENE_WATER_TEMPLE:
case SCENE_SPIRIT_TEMPLE:
case SCENE_SHADOW_TEMPLE:
case SCENE_BOTTOM_OF_THE_WELL:
case SCENE_ICE_CAVERN:
case SCENE_GANONS_TOWER:
case SCENE_GERUDO_TRAINING_GROUND:
case SCENE_THIEVES_HIDEOUT:
case SCENE_INSIDE_GANONS_CASTLE:
gSaveContext.entranceIndex = sDungeonEntrances[gSaveContext.savedSceneNum];
break;
case SCENE_DEKU_TREE_BOSS:
gSaveContext.entranceIndex = ENTR_DEKU_TREE_0;
break;
case SCENE_DODONGOS_CAVERN_BOSS:
gSaveContext.entranceIndex = ENTR_DODONGOS_CAVERN_0;
break;
case SCENE_JABU_JABU_BOSS:
gSaveContext.entranceIndex = ENTR_JABU_JABU_0;
break;
case SCENE_FOREST_TEMPLE_BOSS:
gSaveContext.entranceIndex = ENTR_FOREST_TEMPLE_0;
break;
case SCENE_FIRE_TEMPLE_BOSS:
gSaveContext.entranceIndex = ENTR_FIRE_TEMPLE_0;
break;
case SCENE_WATER_TEMPLE_BOSS:
gSaveContext.entranceIndex = ENTR_WATER_TEMPLE_0;
break;
case SCENE_SPIRIT_TEMPLE_BOSS:
gSaveContext.entranceIndex = ENTR_SPIRIT_TEMPLE_0;
break;
case SCENE_SHADOW_TEMPLE_BOSS:
gSaveContext.entranceIndex = ENTR_SHADOW_TEMPLE_0;
break;
case SCENE_GANONS_TOWER_COLLAPSE_INTERIOR:
case SCENE_INSIDE_GANONS_CASTLE_COLLAPSE:
case SCENE_GANONDORF_BOSS:
case SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR:
case SCENE_GANON_BOSS:
gSaveContext.entranceIndex = ENTR_GANONS_TOWER_0;
break;
default:
if (gSaveContext.savedSceneNum != SCENE_LINKS_HOUSE) {
gSaveContext.entranceIndex = (LINK_AGE_IN_YEARS == YEARS_CHILD) ? ENTR_LINKS_HOUSE_0 : ENTR_TEMPLE_OF_TIME_7;
} else {
gSaveContext.entranceIndex = ENTR_LINKS_HOUSE_0;
}
default:
// Use the saved entrance value with remember save location, except when in grottos/fairy fountains
if (CVarGetInteger("gRememberSaveLocation", 0) && gSaveContext.savedSceneNum != SCENE_FAIRYS_FOUNTAIN &&
gSaveContext.savedSceneNum != SCENE_GROTTOS) {
break;
}
}
if (gSaveContext.savedSceneNum != SCENE_LINKS_HOUSE) {
gSaveContext.entranceIndex = (LINK_AGE_IN_YEARS == YEARS_CHILD) ? ENTR_LINKS_HOUSE_0 : ENTR_TEMPLE_OF_TIME_7;
} else {
gSaveContext.entranceIndex = ENTR_LINKS_HOUSE_0;
}
break;
}
osSyncPrintf("scene_no = %d\n", gSaveContext.entranceIndex);

View File

@ -3065,11 +3065,7 @@ void FileChoose_LoadGame(GameState* thisx) {
Entrance_Init();
// Handle randomized spawn positions after the save context has been setup from load
// When remeber save location is on, set save warp if the save was in an a grotto, or
// the entrance index is -1 from shuffle overwarld spawn
if (Randomizer_GetSettingValue(RSK_SHUFFLE_ENTRANCES) && ((!CVarGetInteger("gRememberSaveLocation", 0) ||
gSaveContext.savedSceneNum == SCENE_FAIRYS_FOUNTAIN || gSaveContext.savedSceneNum == SCENE_GROTTOS) ||
(CVarGetInteger("gRememberSaveLocation", 0) && Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_SPAWNS) && gSaveContext.entranceIndex == ENTR_LOAD_OPENING))) {
if (Randomizer_GetSettingValue(RSK_SHUFFLE_ENTRANCES)) {
Entrance_SetSavewarpEntrance();
}
}