diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 267af1ce2a..4584db3385 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,8 +1,9 @@ -name: PR Builds x64 +name: Builds on: push: - branches: [ master ] + branches: + - master paths-ignore: - "**.md" - "**.ini" @@ -13,274 +14,211 @@ on: - "**.ini" jobs: -# windows64-netplay: -# env: -# DXSDK_DIR: "C:\\Program Files (x86)\\Microsoft DirectX SDK (June 2010)\\" -# name: "Windows Netplay" -# runs-on: windows-2019 -# steps: -# - name: "Remove Redistributable" -# shell: cmd -# run: | -# MsiExec.exe /passive /X{F0C3E5D1-1ADE-321E-8167-68EF0DE699A5} -# - name: "Setup MSBuild" -# uses: microsoft/setup-msbuild@v1 -# - name: "Install DirectX SDK" -# shell: powershell -# run: | -# choco install directx-sdk -# - name: "Checkout" -# uses: actions/checkout@v2.3.1 -# - name: 'Fetch Git Tags' -# if: success() -# shell: bash -# run: | -# git fetch --prune --unshallow -# echo ::set-env name=GIT_BRANCH::$(git rev-parse --abbrev-ref HEAD) -# echo ::set-env name=GIT_HASH::$(git rev-parse --short HEAD) -# echo ::set-env name=GIT_TAG::$(git describe --tags --abbrev=0) -# echo ::set-env name=CURR_DATE::$(date +%Y-%m-%d) -# - name: "Build Netplay Dolphin" -# shell: cmd -# run: | -# msbuild /p:Configuration=Release /p:Platform=x64 ${{ github.workspace }}\Source\Dolphin.sln -# - name: "Package Netplay" -# working-directory: ${{ github.workspace }} -# run: | -# $env:FILE_NAME="${{ env.CURR_DATE }}-${{ env.OBS_GIT_HASH }}-${{ env.OBS_GIT_TAG }}-win64-netplay.zip" -# mkdir artifact -# Xcopy /Y /E /I .\Data\Sys .\Binary\x64\Sys -# cd .\Binary\x64\ -# fsutil file createnew portable.txt 0 -# fsutil file createnew FIX-VCRUNTIME140-ERROR.txt 0 -# echo "Download and install this: https://aka.ms/vs/16/release/vc_redist.x64.exe" > .\FIX-VCRUNTIME140-ERROR.txt -# 7z a ${env:FILE_NAME} .\* -# move ${env:FILE_NAME} ..\..\artifact\ -# - name: "Publish" -# if: success() -# uses: actions/upload-artifact@v2-preview -# with: -# name: "windows64-netplay" -# path: "./artifact/" -# windows64-playback: -# env: -# DXSDK_DIR: "C:\\Program Files (x86)\\Microsoft DirectX SDK (June 2010)\\" -# name: "Windows Playback" -# runs-on: windows-2019 -# steps: -# - name: "Remove Redistributable" -# shell: cmd -# run: | -# MsiExec.exe /passive /X{F0C3E5D1-1ADE-321E-8167-68EF0DE699A5} -# - name: "Setup MSBuild" -# uses: microsoft/setup-msbuild@v1 -# - name: "Install DirectX SDK" -# shell: powershell -# run: | -# choco install directx-sdk -# - name: "Checkout" -# uses: actions/checkout@v2.3.1 -# - name: 'Fetch Git Tags' -# if: success() -# shell: bash -# run: | -# git fetch --prune --unshallow -# echo ::set-env name=GIT_BRANCH::$(git rev-parse --abbrev-ref HEAD) -# echo ::set-env name=GIT_HASH::$(git rev-parse --short HEAD) -# echo ::set-env name=GIT_TAG::$(git describe --tags --abbrev=0) -# echo ::set-env name=CURR_DATE::$(date +%Y-%m-%d) -# - name: "Build Playback Dolphin" -# shell: cmd -# run: | -# msbuild /p:Configuration=ReleasePlayback /p:Platform=x64 ${{ github.workspace }}\Source\Dolphin.sln -# - name: "Package Playback" -# if: success() -# working-directory: ${{ github.workspace }} -# run: | -# $env:FILE_NAME="${{ env.CURR_DATE }}-${{ env.OBS_GIT_HASH }}-${{ env.OBS_GIT_TAG }}-win64-playback.zip" -# mkdir artifact -# git clone https://github.com/project-slippi/slippi-desktop-app -# Xcopy /Y /E /I .\Data\Sys .\Binary\x64\Sys -# Xcopy /Y /E /I .\slippi-desktop-app\app\dolphin-dev\overwrite\Sys .\Binary\x64\Sys -# Xcopy /Y /E /I .\slippi-desktop-app\app\dolphin-dev\overwrite\User .\Binary\x64\User -# cd .\Binary\x64\ -# fsutil file createnew portable.txt 0 -# 7z a ${env:FILE_NAME} .\* -# move ${env:FILE_NAME} ..\..\artifact\ -# - name: "Publish" -# if: success() -# uses: actions/upload-artifact@v2-preview -# with: -# name: "windows64-playback" -# path: "./artifact/" - ubuntu64-netplay: - name: "Ubuntu Netplay" - runs-on: ubuntu-18.04 - steps: - - name: "Checkout" - uses: actions/checkout@v2 - - name: 'Fetch Git Tags' - if: success() - run: | - git fetch --prune --unshallow - echo "GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)" >> $GITHUB_ENV - echo "GIT_HASH=$(git rev-parse --short HEAD)" >> $GITHUB_ENV - echo "GIT_TAG=$(git describe --tags --abbrev=0)" >> $GITHUB_ENV - echo "CURR_DATE=$(date +%Y-%m-%d)" >> $GITHUB_ENV - - name: "Install prerequisites" - if: success() - shell: bash - run: | - sudo dpkg --add-architecture amd64 - sudo apt update - sudo apt install \ - cmake \ - pkg-config \ - git \ - wget \ - libao-dev \ - libasound2-dev \ - libavcodec-dev \ - libavformat-dev \ - libbluetooth-dev \ - libenet-dev \ - libgtk2.0-dev \ - liblzo2-dev \ - libminiupnpc-dev \ - libopenal-dev \ - libpulse-dev \ - libreadline-dev \ - libsfml-dev \ - libsoil-dev \ - libsoundtouch-dev \ - libswscale-dev \ - libusb-1.0-0-dev \ - libxext-dev \ - libxrandr-dev \ - portaudio19-dev \ - zlib1g-dev \ - libudev-dev \ - libevdev-dev \ - libmbedtls-dev \ - libcurl4-openssl-dev \ - libegl1-mesa-dev \ - libpng-dev \ - qtbase5-private-dev \ - libxxf86vm-dev \ - x11proto-xinerama-dev - - name: "Build Netplay Dolphin" - if: success() - working-directory: ${{ github.workspace }} - run: | - chmod +x ./build-linux.sh - ./build-linux.sh - - name: "Build Netplay AppImage" - if: success() - working-directory: ${{ github.workspace }} - run: | - chmod +x ./build-appimage.sh - ./build-appimage.sh - - name: "Package Netplay" - if: success() - working-directory: ${{ github.workspace }} - run: | - mkdir artifact - FILE_NAME=${{ env.CURR_DATE }}-${{ env.GIT_HASH }}-${{ env.GIT_TAG }}-linux-appimage-netplay.zip - zip -r "${FILE_NAME}" ./*.AppImage* - mv "${FILE_NAME}" ./artifact/ - - name: "Publish" - if: success() - uses: actions/upload-artifact@v2-preview - with: - name: "linux-netplay" - path: "./artifact/" - ubuntu64-playback: - name: "Ubuntu Playback" - runs-on: ubuntu-18.04 - steps: - - name: "Checkout" - uses: actions/checkout@v2 - - name: 'Fetch Git Tags' - if: success() - run: | - git fetch --prune --unshallow - echo "GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)" >> $GITHUB_ENV - echo "GIT_HASH=$(git rev-parse --short HEAD)" >> $GITHUB_ENV - echo "GIT_TAG=$(git describe --tags --abbrev=0)" >> $GITHUB_ENV - echo "CURR_DATE=$(date +%Y-%m-%d)" >> $GITHUB_ENV - - name: "Install prerequisites" - if: success() - shell: bash - run: | - sudo dpkg --add-architecture amd64 - sudo apt update - sudo apt install \ - cmake \ - pkg-config \ - git \ - wget \ - libao-dev \ - libasound2-dev \ - libavcodec-dev \ - libavformat-dev \ - libbluetooth-dev \ - libenet-dev \ - libgtk2.0-dev \ - liblzo2-dev \ - libminiupnpc-dev \ - libopenal-dev \ - libpulse-dev \ - libreadline-dev \ - libsfml-dev \ - libsoil-dev \ - libsoundtouch-dev \ - libswscale-dev \ - libusb-1.0-0-dev \ - libxext-dev \ - libxrandr-dev \ - portaudio19-dev \ - zlib1g-dev \ - libudev-dev \ - libevdev-dev \ - libmbedtls-dev \ - libcurl4-openssl-dev \ - libegl1-mesa-dev \ - libpng-dev \ - qtbase5-private-dev \ - libxxf86vm-dev \ - x11proto-xinerama-dev - - name: "Build Playback Dolphin" - if: success() - working-directory: ${{ github.workspace }} - run: | - chmod +x ./build-linux.sh - ./build-linux.sh playback - - name: "Build Playback AppImage" - if: success() - working-directory: ${{ github.workspace }} - run: | - chmod +x ./build-appimage.sh - ./build-appimage.sh playback - - name: "Package Playback" - if: success() - working-directory: ${{ github.workspace }} - run: | - mkdir artifact - FILE_NAME=${{ env.CURR_DATE }}-${{ env.GIT_HASH }}-${{ env.GIT_TAG }}-linux-appimage-playback.zip - zip -r "${FILE_NAME}" ./*.AppImage - mv "${FILE_NAME}" ./artifact/ - - name: "Publish" - if: success() - uses: actions/upload-artifact@v2-preview - with: - name: "linux-playback" - path: "./artifact/" - macOS64-netplay: - name: "macOS Netplay" + # windows: + # strategy: + # fail-fast: false + # matrix: + # build_type: [Netplay, Playback] + # include: + # - build_type: Netplay + # artifact_name: windows64-netplay + # build_config: -G "Ninja" -DCMAKE_BUILD_TYPE="Release" -DQt5_DIR:STRING="D:\a\dolphin\dolphin\Externals\Qt\Qt5.15.0\msvc2019_64\lib\cmake\Qt5" -DSLIPPI_PLAYBACK=false + # - build_type: Playback + # artifact_name: windows64-playback + # build_config: -G "Ninja" -DCMAKE_BUILD_TYPE="Release" -DQt5_DIR:STRING="D:\a\dolphin\dolphin\Externals\Qt\Qt5.15.0\msvc2019_64\lib\cmake\Qt5" + # env: + # DXSDK_DIR: "C:\\Program Files (x86)\\Microsoft DirectX SDK (June 2010)\\" + # name: "Windows ${{ matrix.build_type }}" + # runs-on: windows-2019 + # steps: + # - name: "Checkout" + # uses: actions/checkout@v2 + # with: + # submodules: recursive + # # - name: "Remove Redistributable" + # # shell: cmd + # # run: | + # # MsiExec.exe /passive /X{F0C3E5D1-1ADE-321E-8167-68EF0DE699A5} + # # MsiExec.exe /passive /X{1D8E6291-B0D5-35EC-8441-6616F567A0F7} + # # mkdir .\Tools\DX + # # - name: "Setup MSBuild" + # # uses: microsoft/setup-msbuild@v1 + # # - name: Cache DXSDK_Jun10.exe + # # uses: actions/cache@v2 + # # with: + # # path: ./Tools/DX/ + # # key: ${{ runner.os }} + # # - name: "Download DirectX SDK" + # # working-directory: ${{ github.workspace }} + # # shell: powershell + # # run: | + # # if (!(Test-Path ".\Tools\DX\DXSDK_Jun10.exe" -PathType Leaf)) { Invoke-WebRequest -Uri https://github.com/project-slippi/Ishiiruka/releases/download/v2.2.5/DXSDK_Jun10.exe -UseBasicParsing -OutFile ".\Tools\DX\DXSDK_Jun10.exe" } + # # - name: "Install DirectX SDK" + # # working-directory: ${{ github.workspace }} + # # shell: cmd + # # run: | + # # .\Tools\DX\DXSDK_Jun10.exe /U /F + # - name: 'Fetch Git Tags' + # shell: bash + # if: success() + # run: | + # git fetch --prune --unshallow + # echo "GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)" >> $GITHUB_ENV + # echo "GIT_HASH=$(git rev-parse --short HEAD)" >> $GITHUB_ENV + # echo "GIT_TAG=$(git describe --tags --abbrev=0)" >> $GITHUB_ENV + # echo "CURR_DATE=$(date +%Y-%m-%d)" >> $GITHUB_ENV + # - uses: seanmiddleditch/gha-setup-ninja@master + # - uses: egor-tensin/vs-shell@v2 + # - name: "Build ${{ matrix.build_type }} Dolphin" + # shell: cmd + # working-directory: ${{ github.workspace }} + # run: | + # mkdir build + # cd build + # dir ..\Externals\Qt\Qt5.15.0\msvc2019_64\lib\cmake\Qt5 + # cmake ${{ matrix.build_config }} .. + # ninja + # - name: "Package ${{ matrix.build_type }}" + # working-directory: ${{ github.workspace }} + # run: | + # Xcopy /Y /E /I .\Data\Sys .\Binary\x64\Sys + # cd .\Binary\x64\ + # fsutil file createnew FIX-VCRUNTIME140-ERROR.txt 0 + # echo "Download and install this: https://aka.ms/vs/16/release/vc_redist.x64.exe" > .\FIX-VCRUNTIME140-ERROR.txt + # - name: "Add Playback codes" + # working-directory: ${{ github.workspace }} + # if: matrix.build_type == 'Playback' + # run: | + # Xcopy /Y /E /I .\Data\Sys .\Binary\x64\Sys + # Xcopy /Y /E /I .\Data\PlaybackGeckoCodes\* .\Binary\x64\Sys\GameSettings\ + # - name: Package Artifact + # working-directory: ${{ github.workspace }} + # run: | + # $FILE_NAME="${{ env.CURR_DATE }}-${{ env.GIT_HASH }}-${{ env.GIT_TAG }}-${{ matrix.artifact_name }}.zip" + # mkdir artifact + # cd .\Binary\x64\ + # fsutil file createnew portable.txt 0 + # 7z a $FILE_NAME .\* + # move $FILE_NAME ..\..\artifact\ + # - name: "Publish" + # if: success() + # uses: actions/upload-artifact@v2-preview + # with: + # name: ${{ matrix.artifact_name }} + # path: "./artifact/" + linux: + strategy: + fail-fast: false + matrix: + build_type: [Netplay, Playback] + include: + - build_type: Netplay + artifact_name: linux-netplay + build_config: netplay + - build_type: Playback + artifact_name: linux-playback + build_config: playback + name: "Linux ${{ matrix.build_type }}" + runs-on: ubuntu-18.04 + steps: + - name: "Checkout" + uses: actions/checkout@v2 + with: + submodules: recursive + - name: 'Fetch Git Tags' + if: success() + run: | + git fetch --prune --unshallow + echo "GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)" >> $GITHUB_ENV + echo "GIT_HASH=$(git rev-parse --short HEAD)" >> $GITHUB_ENV + echo "GIT_TAG=$(git describe --tags --abbrev=0)" >> $GITHUB_ENV + echo "CURR_DATE=$(date +%Y-%m-%d)" >> $GITHUB_ENV + - name: "Install prerequisites" + if: success() + shell: bash + run: | + sudo dpkg --add-architecture amd64 + sudo apt update + sudo apt install \ + cmake \ + pkg-config \ + git \ + wget \ + libao-dev \ + libasound2-dev \ + libavcodec-dev \ + libavformat-dev \ + libbluetooth-dev \ + libenet-dev \ + libgtk2.0-dev \ + liblzo2-dev \ + libminiupnpc-dev \ + libopenal-dev \ + libpulse-dev \ + libreadline-dev \ + libsfml-dev \ + libsoil-dev \ + libsoundtouch-dev \ + libswscale-dev \ + libusb-1.0-0-dev \ + libwebkit2gtk-4.0-dev \ + libxext-dev \ + libxrandr-dev \ + portaudio19-dev \ + zlib1g-dev \ + libudev-dev \ + libevdev-dev \ + libmbedtls-dev \ + libcurl4-openssl-dev \ + libegl1-mesa-dev \ + libpng-dev \ + qtbase5-private-dev \ + libxxf86vm-dev \ + x11proto-xinerama-dev + - name: "Build ${{ matrix.build_type }} Dolphin" + if: success() + working-directory: ${{ github.workspace }} + run: | + chmod +x ./build-linux.sh && ./build-linux.sh ${{ matrix.build_config }} + - name: "Build ${{ matrix.build_type }} AppImage" + if: success() + working-directory: ${{ github.workspace }} + run: | + chmod +x ./build-appimage.sh && ./build-appimage.sh ${{ matrix.build_config }} + - name: "Package" + if: success() + working-directory: ${{ github.workspace }} + run: | + mkdir artifact + FILE_NAME=${{ env.CURR_DATE }}-${{ env.GIT_HASH }}-${{ env.GIT_TAG }}-${{ matrix.artifact_name }}.zip + chmod +x ./*.AppImage + zip -r "${FILE_NAME}" ./*.AppImage* + mv "${FILE_NAME}" ./artifact/ + - name: "Publish" + if: success() + uses: actions/upload-artifact@v2-preview + with: + name: ${{ matrix.artifact_name }} + path: "./artifact/" + macOS: + strategy: + fail-fast: false + matrix: + build_type: [Netplay, Playback] + include: + - build_type: Netplay + artifact_name: macOS-netplay + build_config: netplay + - build_type: Playback + artifact_name: macOS-playback + build_config: playback + name: "macOS ${{ matrix.build_type }}" runs-on: macos-10.15 steps: - name: "Checkout" uses: actions/checkout@v2 + with: + submodules: recursive - name: 'Fetch Git Tags' if: success() run: | @@ -302,7 +240,8 @@ jobs: if: success() shell: bash run: | - brew update + rm '/usr/local/bin/2to3' || true + echo "HOMEBREW_NO_AUTO_UPDATE=1" >> $GITHUB_ENV brew upgrade cmake brew install \ ffmpeg \ @@ -312,100 +251,26 @@ jobs: libao \ sound-touch \ hidapi \ - qt - - name: "Build Netplay" + qt@5 + - name: "Build ${{ matrix.build_type }} Dolphin" if: success() shell: bash working-directory: ${{ github.workspace }} run: | - mkdir build - cd build - export LIBRARY_PATH=/usr/lib/ - cmake -DSLIPPI_PLAYBACK=false -DQt5_DIR=$(brew --prefix qt)/lib/cmake/Qt5 -DENABLE_NOGUI=false .. - make -j7 - - name: "Package Netplay" + chmod +x ./build-mac.sh && ./build-mac.sh ${{ matrix.build_config }} + - name: Package ${{ matrix.build_type }} if: success() shell: bash working-directory: ${{ github.workspace }} run: | - FILE_NAME=${{ env.CURR_DATE }}-${{ env.GIT_HASH }}-${{ env.GIT_TAG }}-macOS-netplay.tar.gz - echo "::set-env name=FILE_NAME::${FILE_NAME}" - cp -Rf Data/Sys build/Binaries/Dolphin.app/Contents/Resources/ + FILE_NAME=${{ env.CURR_DATE }}-${{ env.GIT_HASH }}-${{ env.GIT_TAG }}-${{ matrix.artifact_name }}.tar.gz mkdir artifact cd ./build/Binaries/ - zip -r "${FILE_NAME}" Dolphin.app + zip -r "${FILE_NAME}" "Slippi_Dolphin.app" mv "${FILE_NAME}" ../../artifact/ - name: "Publish" if: success() uses: actions/upload-artifact@v2-preview with: - name: "macOS-netplay" - path: "./artifact/" - macOS64-playback: - name: "macOS Playback" - runs-on: macos-10.15 - steps: - - name: "Checkout" - uses: actions/checkout@v2 - - name: 'Fetch Git Tags' - if: success() - run: | - git fetch --prune --unshallow - echo "GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)" >> $GITHUB_ENV - echo "GIT_HASH=$(git rev-parse --short HEAD)" >> $GITHUB_ENV - echo "GIT_TAG=$(git describe --tags --abbrev=0)" >> $GITHUB_ENV - echo "CURR_DATE=$(date +%Y-%m-%d)" >> $GITHUB_ENV - - name: "Install 10.14 SDK" - if: success() - shell: bash - working-directory: ${{ github.workspace }} - run: | - wget https://github.com/phracker/MacOSX-SDKs/releases/download/10.15/MacOSX10.14.sdk.tar.xz - tar -xf MacOSX10.14.sdk.tar.xz - rm MacOSX10.14.sdk.tar.xz - sudo mv MacOSX10.14.sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ - - name: "Download and Install prerequisites" - if: success() - shell: bash - run: | - brew update - brew upgrade cmake - brew install \ - ffmpeg \ - libpng \ - libav \ - pkgconfig \ - libao \ - sound-touch \ - hidapi \ - qt - - name: "Build Playback" - if: success() - shell: bash - working-directory: ${{ github.workspace }} - run: | - mkdir build - export LD_LIBRARY_PATH=/usr/lib/ - cd build - cmake -DQt5_DIR=$(brew --prefix qt)/lib/cmake/Qt5 -DENABLE_NOGUI=false .. - make -j7 - - name: "Package Playback" - if: success() - shell: bash - working-directory: ${{ github.workspace }} - run: | - mkdir artifact - git clone https://github.com/project-slippi/slippi-desktop-app - cd ./build/Binaries/ - cp -Rf ../../Data/Sys ./Dolphin.app/Contents/Resources - cp -Rf ../../slippi-desktop-app/app/dolphin-dev/overwrite/Sys ./Dolphin.app/Contents/Resources - cp -Rf ../../slippi-desktop-app/app/dolphin-dev/overwrite/User ./Dolphin.app/Contents/Resources - FILE_NAME=${{ env.CURR_DATE }}-${{ env.GIT_HASH }}-${{ env.GIT_TAG }}-macOS-playback.zip - zip -r "${FILE_NAME}" Dolphin.app - mv "${FILE_NAME}" ../../artifact/ - - name: "Publish" - if: success() - uses: actions/upload-artifact@v2-preview - with: - name: "macOS-playback" + name: ${{ matrix.artifact_name }} path: "./artifact/" diff --git a/.gitignore b/.gitignore index f4847d2eb3..b92208f13b 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ Source/Core/Common/scmrev.h /obj/ # Ignore files output by Android cmake build /Source/Android/app/.cxx/ +# Ignore build output +/Source/out/** /libs/ # Ignore various files created by visual studio/msbuild *.ipch diff --git a/CMakeLists.txt b/CMakeLists.txt index c20217770a..634028b8a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -549,6 +549,7 @@ else() check_vendoring_approved(fmt) message(STATUS "Using static fmt from Externals") add_subdirectory(Externals/fmt EXCLUDE_FROM_ALL) + include_directories(Externals/fmt/include) endif() add_subdirectory(Externals/imgui) add_subdirectory(Externals/glslang) diff --git a/Data/PlaybackGeckoCodes/GALE01r2.ini b/Data/PlaybackGeckoCodes/GALE01r2.ini new file mode 100644 index 0000000000..367ac20bef --- /dev/null +++ b/Data/PlaybackGeckoCodes/GALE01r2.ini @@ -0,0 +1,1262 @@ +# GALE01 - Super Smash Bros. Melee NTSC-U 1.02 + +[Core] +CPUThread = False +GPUDeterminismMode = fake-completion +PollingMethod = OnSIRead +FastDiscSpeed = True + +[Gecko_Enabled] +$Required: General Codes +$Required: Slippi Playback +$Optional: Show Player Names + +[Gecko] +$Required: General Codes [Achilles, Dan Salvato, UnclePunch, tauKhan, Ptomerty, Cilan, Datel, Most] +0415EE98 38600001 #Unlock All Characters and Stages [Datel] +0415EDDC 38600001 +04164B14 38600001 +041648F4 38600001 +0415EE4C 38600001 +0415EE14 38600001 +0415D968 38600001 +0415D9D8 38600001 +0417229C 38600000 +041737B0 38600000 +04164658 38600001 +041644E8 38600001 +0430490C 38600063 +043044F0 38600001 +0415D94C 4E800020 #Disable Special Messages [Most] +0415D984 4E800020 #Disable Trophy Messages [Achilles] +C22FCCE8 00000013 #External/Extended Nametag Box/Extended Nametag Box.asm +3C608003 6063556C +7C6803A6 887F0000 +4E800021 5460063E +28000078 41820070 +3C608045 6063D84F +1C0001A4 7C630214 +38800000 8C030001 +2C000000 41820018 +38840001 2C000080 +41A0FFEC 8C030001 +4BFFFFE4 2C040005 +41800034 3C604080 +9061FFF0 C221FFF0 +3E404330 CA028C58 +9241FFEC 9081FFF0 +C9E1FFEC EDEF8028 +EDEF8824 807E0010 +D1E3002C 807E0010 +60000000 00000000 +C213C388 0000000A #Common/CostumeBoundCheck/PuffCostume.asm +83DC002C 887E000C +3D808003 618C2330 +7D8903A6 4E800421 +3D808016 618C9238 +7D8903A6 4E800421 +889E0619 7C041800 +40800008 48000014 +3D808013 618CC46C +7D8903A6 4E800420 +809C002C 00000000 +C216DED4 00000039 #Common/CostumeBoundCheck/main.asm +7C0802A6 90010004 +9421FF50 BE810008 +3BE00000 7FE3FB78 +3D808003 618C241C +7D8903A6 4E800421 +2C030003 41820060 +7FE3FB78 3D808003 +618C3198 7D8903A6 +4E800421 7C7E1B78 +7FE3FB78 3D808003 +618C2330 7D8903A6 +4E800421 3D808016 +618C9238 7D8903A6 +4E800421 7C1E1800 +4180001C 7FE3FB78 +38800000 3D808003 +618C3208 7D8903A6 +4E800421 3BFF0001 +2C1F0006 4180FF80 +3BE00000 7FE3FB78 +3D808003 618C241C +7D8903A6 4E800421 +2C030003 418200EC +7FE3FB78 3D808003 +618C2330 7D8903A6 +4E800421 7C7E1B78 +7FE3FB78 3D808003 +618C3198 7D8903A6 +4E800421 7C7D1B78 +7FE3FB78 3D808003 +618C3284 7D8903A6 +4E800421 7C7C1B78 +3B600000 7C1FD800 +4182008C 7F63DB78 +3D808003 618C241C +7D8903A6 4E800421 +2C030003 41820070 +7F63DB78 3D808003 +618C2330 7D8903A6 +4E800421 7C03F000 +40820054 7F63DB78 +3D808003 618C3198 +7D8903A6 4E800421 +7C03E800 40820038 +7F63DB78 3D808003 +618C3284 7D8903A6 +4E800421 7C03E000 +4082001C 38830001 +7F63DB78 3D808003 +618C32F4 7D8903A6 +4E800421 3B7B0001 +2C1B0006 4180FF68 +3BFF0001 2C1F0006 +4180FEF4 BA810008 +800100B4 382100B0 +7C0803A6 8001001C +60000000 00000000 + +$Required: Slippi Playback [Fizzi, UnclePunch, Achilles, tauKhan] +*Used to play back a .slp file +*Will play replay configured in playback.txt +C216E9E4 00000010 #Playback/Core/CleanDynamicGeckos.asm +3BC30000 7C0802A6 +90010004 9421FF50 +BE810008 83CDB64C +83BE0010 807D0000 +2C030000 41820044 +389D0008 80BD0004 +3D808000 618C31F4 +7D8903A6 4E800421 +807D0000 809D0004 +3D808032 618C8F50 +7D8903A6 4E800421 +807D0004 7FBD1A14 +3BBD0008 4BFFFFB8 +BA810008 800100B4 +382100B0 7C0803A6 +60000000 00000000 +C216D298 00000016 #Playback/Core/FetchGameFrame.asm +881F0008 2C000000 +408200A0 7C0802A6 +90010004 9421FF50 +BE810008 806DB64C +83630000 38600076 +987B0000 806DB654 +907B0001 7F63DB78 +38800005 38A00001 +3D808000 618C55F0 +7D8903A6 4E800421 +7F63DB78 3880018F +38A00000 3D808000 +618C55F0 7D8903A6 +4E800421 887B0000 +2C030000 40820024 +3D808034 618CF314 +7D8903A6 4E800421 +3C60804C 38000000 +98031F7B 4BFFFF90 +BA810008 800100B4 +382100B0 7C0803A6 +881F0008 00000000 +C206B0DC 00000046 #Playback/Core/RestoreGameFrame.asm +7C0802A6 90010004 +9421FF50 BE810008 +8BBF000C 7FA3EB78 +3D808003 618C1724 +7D8903A6 4E800421 +7C7C1B78 832DB64C +83790000 7FE3FB78 +3D808000 618C55F8 +7D8903A6 4E800421 +7C741B78 389B0007 +88BF000C 1CA50062 +7C842A14 1CB40031 +7F442A14 3C80804D +807A0000 90645F90 +807A0004 907F0620 +807A0008 907F0624 +807A000C 907F0638 +807A0010 907F063C +807A0014 907F0650 +807A0018 907F065C +8879056F 2C030000 +41820024 807A001C +907F00B0 807A0020 +907F00B4 807A0024 +907F002C 807A0028 +907F0010 3C608046 +6063B108 3C80804C +60841F78 88840001 +3884FFFF 2C040000 +40A00008 38840005 +1C840030 7C632214 +889F0618 1C84000C +7E832214 887A002C +98740002 8879056F +2C030000 4182004C +807A002D 2C03FFFF +41820040 90610040 +C0210040 C05F1830 +EC211028 C0429500 +FC011040 41820024 +7FE3FB78 C0210040 +C05F1830 EC211028 +3D808006 618CCC7C +7D8903A6 4E800421 +806DB654 2C03FF85 +408200AC 7FE3FB78 +38800000 C0228874 +3D808007 618C592C +7D8903A6 4E800421 +807F00B0 907F06F4 +907F070C 807F00B4 +907F06F8 907F0710 +807F00B8 907F06FC +907F0714 C03F00B4 +D03F2344 806DAE0C +907F0728 887F000C +889F221F 5484EFFE +38BF00B0 3D808003 +618C2828 7D8903A6 +4E800421 7FC3F378 +3D808007 618C61C8 +7D8903A6 4E800421 +807F0890 C0230040 +D023002C C0230044 +D0230030 3D808002 +618CF3AC 7D8903A6 +4E800421 BA810008 +800100B4 382100B0 +7C0803A6 881F2219 +60000000 00000000 +C216E74C 0000009E #Playback/Core/RestoreGameInfo.asm +7C0802A6 90010004 +9421FF50 BE810008 +386005EC 3D808037 +618CF1E4 7D8903A6 +4E800421 7C7C1B78 +938DB64C 388005EC +3D808000 618CC160 +7D8903A6 4E800421 +38600221 3D808037 +618CF1E4 7D8903A6 +4E800421 7C7E1B78 +93DC0000 38600040 +3D808037 618CF1E4 +7D8903A6 4E800421 +907C0004 38600075 +987E0000 387C001C +907E0001 38600553 +907E0005 38600000 +907E0009 7FC3F378 +3880000D 38A00001 +3D808000 618C55F0 +7D8903A6 4E800421 +7FC3F378 38800221 +38A00000 3D808000 +618C55F0 7D8903A6 +4E800421 887E0000 +2C030001 41820018 +3D808034 618CF314 +7D8903A6 4E800421 +4BFFFF8C 807E0001 +3C80804D 90645F90 +7FE3FB78 389E0005 +38A00138 3D808000 +618C31F4 7D8903A6 +4E800421 387F0040 +3880001C 3D808000 +618CC160 7D8903A6 +4E800421 3AE2F22C +3A82F230 3ABE013D +3AC00000 1C960008 +7C64A82E 7C76B9AE +38840004 7C64A82E +7C76A1AE 3AD60001 +2C160004 4180FFE0 +3A800000 3ABF0060 +1ED40024 7ED6AA14 +88760001 2C030000 +40820078 8876000A +2C030078 4182006C +7C771B78 3D808023 +618C7A04 7D8903A6 +4E800421 7EE3BB78 +3D808015 618CCC9C +7D8903A6 4E800421 +38630198 389E015D +1CB40010 7C842A14 +88A40000 2C050000 +40820010 38600078 +9876000A 4800001C +38A00010 3D808000 +618C31F4 7D8903A6 +4E800421 48000004 +3A940001 2C140004 +4180FF70 887E019D +9862F234 887E019E +9862F238 887E019F +9862F23C 887E01A0 +987C056F 387C0570 +389E01A1 38A0007C +3D808000 618C31F4 +7D8903A6 4E800421 +807E021D 3D808037 +618CF1E4 7D8903A6 +4E800421 7C7D1B78 +93BC0008 3860008A +987D0000 7FA3EB78 +38800001 38A00001 +3D808000 618C55F0 +7D8903A6 4E800421 +7FA3EB78 809E021D +38A00000 3D808000 +618C55F0 7D8903A6 +4E800421 38800004 +909C000C 7FA3EB78 +48000055 7C8802A6 +3D808000 618C55FC +7D8903A6 4E800421 +807C000C 3D808037 +618CF1E4 7D8903A6 +4E800421 907C0010 +907C0014 7FA3EB78 +48000041 7C8802A6 +3D808000 618C55FC +7D8903A6 4E800421 +4800013C 4E800021 +2C050000 41820018 +80CDB64C 8066000C +38630008 7C632A14 +9066000C 4E800020 +4E800021 2C050000 +41820108 7C0802A6 +90010004 9421FF50 +BE810008 7C9E2378 +7CBB2B78 80BE0000 +54A501FE 64BD8000 +834DB64C 833A0014 +2C030004 41820014 +2C030006 41820014 +2C0300C2 41820014 +3B9E0004 48000048 +3B9E0008 48000040 +389E0008 7C7D2050 +546301BA 64634800 +907A0018 3B9A0018 +807E0004 1C630008 +7C83F214 387D0004 +7C641850 546301BA +64634800 3863FFFC +90640004 93B90000 +93790004 38790008 +7FA4EB78 7F65DB78 +3D808000 618C31F4 +7D8903A6 4E800421 +3B390008 7F39DA14 +933A0014 7FA3EB78 +7F84E378 7F65DB78 +3D808000 618C31F4 +7D8903A6 4E800421 +7FA3EB78 7F64DB78 +3D808032 618C8F50 +7D8903A6 4E800421 +BA810008 800100B4 +382100B0 7C0803A6 +4E800020 38600000 +809C0014 90640000 +7FA3EB78 809E021D +3D808032 618C8F50 +7D8903A6 4E800421 +38600004 38800007 +38A00000 3D808039 +618C01F0 7D8903A6 +4E800421 48000021 +7C8802A6 38A00000 +3D808038 618CFD54 +7D8903A6 4E800421 +4800004C 4E800021 +7C0802A6 90010004 +9421FF50 BE810008 +806DB64C 83A30000 +887D0002 2C030000 +41820010 807D0003 +3C80804D 90645F90 +BA810008 800100B4 +382100B0 7C0803A6 +4E800020 BA810008 +800100B4 382100B0 +7C0803A6 3C608017 +60000000 00000000 +C216D304 00000009 #Playback/Core/RestoreLRAStart.asm +806DB64C 80630000 +88630000 2C030002 +4082002C 3860FFFF +38800007 3D808016 +618CCF4C 7D8903A6 +4E800421 3D808016 +618CD30C 7D8903A6 +4E800420 7FE3FB78 +60000000 00000000 +C216B9C0 00000012 #Playback/Core/RestoreStockSteal.asm +80ADB64C 80A50004 +38800089 98850000 +808DB654 90850001 +98650005 7CA32B78 +38800006 38A00001 +3D808000 618C55F0 +7D8903A6 4E800421 +806DB64C 80630004 +38800001 38A00000 +3D808000 618C55F0 +7D8903A6 4E800421 +806DB64C 80630004 +88630000 2C030000 +41820014 3D808016 +618CBA1C 7D8903A6 +4E800420 3D808016 +618CBAC8 7D8903A6 +4E800420 00000000 +C21A501C 0000002A #Playback/Core/FastForward/FastForward.asm +3C808048 88649D30 +2C03000E 40820040 +88649D33 2C030001 +40820034 38600001 +3D80801A 618C45E8 +7D8903A6 4E800421 +2C030002 41820018 +806DB64C 80630000 +88630000 2C030003 +41820024 38600001 +38800002 3D808002 +618C5064 7D8903A6 +4E800421 7C1AD800 +480000E0 806DB64C +80630000 88630001 +2C030001 4182001C +38600000 38800000 +3D808002 618C5064 +7D8903A6 4E800421 +4800000D 2C0300FF +480000A8 7C0802A6 +90010004 9421FF50 +BE810008 3D808003 +618C0A50 7D8903A6 +4E800421 3D808002 +618CA4AC 7D8903A6 +4E800421 3D808003 +618C0A50 7D8903A6 +4E800421 80630028 +3D808036 618C8458 +7D8903A6 4E800421 +806DC18C 82830020 +4800002C 82B4002C +8875221F 546006F7 +40820018 7E83A378 +3D808008 618C6A8C +7D8903A6 4E800421 +82940008 2C140000 +4082FFD4 BA810008 +800100B4 382100B0 +7C0803A6 4E800020 +60000000 00000000 +C2377544 00000002 #Playback/Core/FastForward/IncrementPadIndex.asm +40A2000C 38000001 +981E0003 00000000 +04376A88 881F0001 #Playback/Core/FastForward/PadAlwaysUseMasterIndex.asm +C21A45A0 00000007 #Playback/Core/Scene/Boot to Playback Scene.asm +48000019 7C6802A6 +3C80803D 6084ADA8 +90640004 4800001C +4E800021 38600003 +3C808047 60849D30 +98640003 4E800020 +3800000E 00000000 +C21A6348 000000AB #Playback/Core/Scene/SceneThink_Playback.asm +3C608047 60639D30 +88630000 2C03000E +4082053C 3860000D +3880000E 38A00000 +3D808039 618C01F0 +7D8903A6 4E800421 +48000021 7C8802A6 +38A00000 3D808038 +618CFD54 7D8903A6 +4E800421 480004F0 +4E800021 7C0802A6 +90010004 9421FF50 +BE810008 48000461 +7FC802A6 38600000 +3880FFFF 3D80803A +618C6754 7D8903A6 +4E800421 7C7C1B78 +38800001 989C0049 +38800000 989C004A +C03E0008 D03C0008 +C03E0010 D03C0024 +D03C0028 C03E0000 +C05E0004 7F83E378 +48000435 7C8802A6 +48000445 7CA802A6 +3D80803A 618C6B98 +7D8903A6 4E800421 +7C641B78 7F83E378 +C03E000C C05E000C +3D80803A 618C7548 +7D8903A6 4E800421 +C03E0014 C05E0018 +7F83E378 48000415 +7C8802A6 3D80803A +618C6B98 7D8903A6 +4E800421 7C641B78 +7F83E378 C03E000C +C05E000C 3D80803A +618C7548 7D8903A6 +4E800421 3C602ECC +606340FF 90610040 +7F83E378 38800001 +38A10040 3D80803A +618C74F0 7D8903A6 +4E800421 38600221 +3D808037 618CF1E4 +7D8903A6 4E800421 +7C7D1B78 3B600000 +3D808033 618CC898 +7D8903A6 4E800421 +3D808033 618CF270 +7D8903A6 4E800421 +38600000 3D808037 +618C5538 7D8903A6 +4E800421 8062F240 +2C030000 4082001C +38600000 7F84E378 +3D80803A 618C84BC +7D8903A6 4E800421 +38600000 3D808037 +618C61C0 7D8903A6 +4E800421 3D808034 +618CF314 7D8903A6 +4E800421 3B7B0001 +2C1B00F0 41800008 +3B600000 3860003C +7C7B1B96 480002F1 +7C8802A6 1C630004 +7CC32214 7F83E378 +38800000 480002C1 +7CA802A6 4CC63182 +3D80803A 618C70A0 +7D8903A6 4E800421 +38600088 987D0000 +7FA3EB78 38800001 +38A00001 3D808000 +618C55F0 7D8903A6 +4E800421 7FA3EB78 +38800001 38A00000 +3D808000 618C55F0 +7D8903A6 4E800421 +887D0000 2C030001 +4082FEF0 7F83E378 +3D80803A 618C5CC4 +7D8903A6 4E800421 +38600075 987D0000 +38600000 907D0001 +38600000 907D0005 +38600000 907D0009 +7FA3EB78 3880000D +38A00001 3D808000 +618C55F0 7D8903A6 +4E800421 7FA3EB78 +38800221 38A00000 +3D808000 618C55F0 +7D8903A6 4E800421 +887D0000 2C030001 +41820018 3D808034 +618CF314 7D8903A6 +4E800421 4BFFFF8C +3A9D0005 3C808043 +60842078 88740060 +90640014 88740063 +98640018 88740084 +9064001C 88740087 +98640020 887400A8 +90640024 887400AB +98640028 887400CC +9064002C 887400CF +98640030 A074000E +9064000C 3D808001 +618C8254 7D8903A6 +4E800421 386000C7 +3D808001 618C8C2C +7D8903A6 4E800421 +38600004 3D808001 +618C7700 7D8903A6 +4E800421 3860001C +3D808002 618C6F2C +7D8903A6 4E800421 +3D808021 618CB2D8 +7D8903A6 4E800421 +3AA00000 1C150024 +7E96A378 7ED60214 +3D808000 618C569C +7D8903A6 4E800421 +88960060 7C840774 +7C041800 41820028 +38600000 3D808000 +618C56A0 7D8903A6 +4E800421 3D808000 +618C56A8 7D8903A6 +4E800421 3AB50001 +2C150006 3AD60024 +4180FFB0 A074000E +3D808022 618C519C +7D8903A6 4E800421 +7C641B78 38600001 +3D808000 618C56A0 +7D8903A6 4E800421 +3D808000 618C56A8 +7D8903A6 4E800421 +3D808002 618C7168 +7D8903A6 4E800421 +8062F240 2C030000 +40820018 38600001 +3D808002 618C4030 +7D8903A6 4E800421 +3D808002 618C4F6C +7D8903A6 4E800421 +3D80801A 618C4B60 +7D8903A6 4E800421 +48000068 4E800021 +C33E0000 00000000 +00000000 3F800000 +3F19999A 43B70000 +43AF0000 432A0000 +00000000 4E800021 +57616974 696E6720 +666F7220 67616D65 +25730000 4E800021 +00000000 2E000000 +2E2E0000 2E2E2E00 +4E800021 736C6970 +70692E67 67000000 +BA810008 800100B4 +382100B0 7C0803A6 +4E800020 3D80801A +618C6368 7D8903A6 +4E800420 807F0000 +60000000 00000000 +041B16A8 801B09C0 #Playback/Core/Scene/Change Debug Result Screen MinorType to Debug Menu/ScenePrep_DebugResult = ScenePrep_DebugMenu.asm +043DDA9C 07000000 #Playback/Core/Scene/Change Debug Result Screen MinorType to Debug Menu/Swap MinorType.asm +C238D224 00000015 #Playback/Core/Sounds/AssignSoundInstanceId.asm +900DC0E8 3C608048 +80639D30 5463443E +2C03010E 40820090 +7C0802A6 90010004 +9421FF50 BE810008 +83EDB64C 3BDF001C +8B9E0000 3C608048 +80639D60 809F056B +7C032000 41810028 +3C608048 80639D60 +809F056B 7C632050 +38630001 8B9E0000 +7F83E051 40800008 +3B9C0007 1C7C00C2 +38DE0001 7CC61A14 +88660000 3863FFFF +1C630006 38A60001 +7CA51A14 807D000C +90650002 BA810008 +800100B4 382100B0 +7C0803A6 00000000 +C21A5014 00000032 #Playback/Core/Sounds/HandleFrameSoundLog.asm +41A20014 3D80801A +618C5024 7D8903A6 +4E800420 3C608048 +80639D30 5463443E +2C03010E 40820168 +7C0802A6 90010004 +9421FF50 BE810008 +3D808034 618C7364 +7D8903A6 4E800421 +7C7D1B78 83EDB64C +3BDF001C 8B9E0000 +3F008048 83189D60 +3B18FFFF 82FF056B +7C18B800 4181009C +7C78B850 38630001 +8B9E0000 7F83E051 +40800008 3B9C0007 +387E0001 1C9C00C2 +7F432214 3B200000 +48000060 38DA0000 +38E00000 48000028 +1C790006 7C651A14 +A0630001 1C870006 +7C862214 A0840001 +7C032000 41820030 +38E70001 88660000 +2C070003 4180FFD4 +1C790006 7C651A14 +80630003 3D808002 +618C36B8 7D8903A6 +4E800421 3B390001 +38BA0061 88650000 +7C191800 4180FF98 +387E0001 1C9C00C2 +7F432214 387A0061 +389A0000 38A00061 +3D808000 618C31F4 +7D8903A6 4E800421 +387A0000 38800061 +3D808000 618CC160 +7D8903A6 4E800421 +7C18B800 4081001C +931F056B 3B9C0001 +2C1C0007 41800008 +3B9CFFF9 9B9E0000 +7FA3EB78 3D808034 +618C738C 7D8903A6 +4E800421 BA810008 +800100B4 382100B0 +7C0803A6 00000000 +C2088224 0000001D #Playback/Core/Sounds/NoDestroyVoice.asm +3C608048 80639D30 +5463443E 2C03010E +408200CC 7C0802A6 +90010004 9421FF50 +BE810008 83EDB64C +3BBF001C 57DE043E +8B9D0000 3C608048 +80639D60 809F056B +7C032000 41810088 +3C608048 80639D60 +809F056B 7C632050 +38630001 8B9D0000 +7F83E051 40800008 +3B9C0007 1C7C00C2 +38DD0062 7CC61A14 +39000000 48000020 +1C680006 38A60001 +7CA51A14 A0650000 +7C1E1800 41820018 +39080001 88660000 +7C081800 4180FFDC +48000024 BA810008 +800100B4 382100B0 +7C0803A6 3D808008 +618C8244 7D8903A6 +4E800420 BA810008 +800100B4 382100B0 +7C0803A6 387F0000 +60000000 00000000 +C20882B0 0000001D #Playback/Core/Sounds/NoDestroyVoice2.asm +3C608048 80639D30 +5463443E 2C03010E +408200CC 7C0802A6 +90010004 9421FF50 +BE810008 83EDB64C +3BBF001C 57DE043E +8B9D0000 3C608048 +80639D60 809F056B +7C032000 41810088 +3C608048 80639D60 +809F056B 7C632050 +38630001 8B9D0000 +7F83E051 40800008 +3B9C0007 1C7C00C2 +38DD0062 7CC61A14 +39000000 48000020 +1C680006 38A60001 +7CA51A14 A0650000 +7C1E1800 41820018 +39080001 88660000 +7C081800 4180FFDC +48000024 BA810008 +800100B4 382100B0 +7C0803A6 3D808008 +618C82D0 7D8903A6 +4E800420 BA810008 +800100B4 382100B0 +7C0803A6 387F0000 +60000000 00000000 +C238D0B0 00000027 #Playback/Core/Sounds/PreventDuplicateSounds.asm +3C608048 80639D30 +5463443E 2C03010E +40820120 7C0802A6 +90010004 9421FF50 +BE810008 83EDB64C +3BDF001C 3BA00000 +3B400000 56FB043E +8B9E0000 3C608048 +80639D60 809F056B +7C032000 41810070 +3C608048 80639D60 +809F056B 7C632050 +38630001 8B9E0000 +7F83E051 40800008 +3B9C0007 1C7C00C2 +38DE0062 7CC61A14 +39000000 48000020 +1C680006 38A60001 +7CA51A14 A0650000 +7C1B1800 41820018 +39080001 88660000 +7C081800 4180FFDC +4800000C 83450002 +3BA00001 1C7C00C2 +38DE0001 7CC61A14 +88660000 2C030010 +40800024 1C630006 +38A60001 7CA51A14 +B3650000 93450002 +88660000 38630001 +98660000 2C1D0000 +41820028 7F43D378 +BA810008 800100B4 +382100B0 7C0803A6 +3D808038 618CD2A0 +7D8903A6 4E800420 +BA810008 800100B4 +382100B0 7C0803A6 +2C1A0000 00000000 +C200569C 00000002 #Common/GetFighterNum.asm +38600021 4E800020 +60000000 00000000 +C20055F8 0000000F #Common/GetIsFollower.asm +7C0802A6 90010004 +9421FF50 BE810008 +7C7E1B78 3BE00000 +887E221F 5460EFFF +41820038 887E000C +3D808003 618C2330 +7D8903A6 4E800421 +3C80803B 6084CDE0 +1C030003 7C640214 +88030002 2C000000 +40820008 3BE00001 +7FE3FB78 BA810008 +800100B4 382100B0 +7C0803A6 4E800020 +60000000 00000000 +C20056A0 00000007 #Common/GetSSMIndex.asm +2C030001 41820018 +3C60803B 6063B3C0 +1C840010 7C6320AE +48000018 3C60803B +6063B6B0 1C840003 +7C6320AE 48000004 +4E800020 00000000 +C216D294 00000006 #Common/IncrementFrameIndex.asm +987F0008 3C608048 +80639D58 2C030000 +40820010 3860FF85 +906DB654 48000010 +806DB654 38630001 +906DB654 00000000 +C20055F4 00000007 #Common/IntToFloat.asm +9421FF00 D0410008 +3C004330 C84298A8 +6C638000 900100F0 +906100F4 C82100F0 +EC211028 C0410008 +38210100 4E800020 +60000000 00000000 +C20056A4 00000022 #Common/LoadPremadeText.asm +7C0802A6 90010004 +9421FF50 BE810008 +7C7F1B78 7C9E2378 +3B800004 7F83E378 +3D808037 618CF1E4 +7D8903A6 4E800421 +7C7D1B78 7F84E378 +3D808000 618CC160 +7D8903A6 4E800421 +386000E1 48000055 +839D0000 7FA3EB78 +3D808037 618CF1B0 +7D8903A6 4E800421 +7F83E378 3D808037 +618CF1E4 7D8903A6 +4E800421 7C7D1B78 +386000E2 4800001D +7FA3EB78 BA810008 +800100B4 382100B0 +7C0803A6 4E800020 +7C0802A6 90010004 +9421FF50 BE810008 +987D0000 9BFD0001 +9BDD0002 7FA3EB78 +38800003 38A00001 +3D808000 618C55F0 +7D8903A6 4E800421 +7FA3EB78 7F84E378 +38A00000 3D808000 +618C55F0 7D8903A6 +4E800421 BA810008 +800100B4 382100B0 +7C0803A6 4E800020 +60000000 00000000 +C20055EC 00000008 #Common/MultiplyRWithF.asm +7C0802A6 90010004 +9421FF50 BE810008 +3D808000 618C55F4 +7D8903A6 4E800421 +EC2100B2 BA810008 +800100B4 382100B0 +7C0803A6 4E800020 +60000000 00000000 +C20056A8 00000005 #Common/RequestSSMLoad.asm +2C030037 41820018 +3D808043 618C37C4 +38800001 1C630004 +7C83612E 4E800020 +60000000 00000000 +C20056B4 00000059 #Common/SubtextFunctions.asm +2C050002 418201F8 +7C0802A6 90010004 +9421FF50 BE810008 +7C751B78 7C962378 +7CB82B78 7CD93378 +90E10038 9101003C +91210040 91410044 +91610048 9181004C +FEA00890 FEC01090 +FEE01890 FF202890 +FF403090 2C180001 +418000FC 39E00004 +FC20B090 FC40B890 +2C0F0001 41820020 +2C0F0002 41820020 +2C0F0003 41820020 +2C0F0004 41820020 +48000024 EC21D028 +4800001C EC21D02A +48000014 EC42D028 +4800000C EC42D02A +48000004 7EA3AB78 +80810038 3D80803A +618C6B98 7D8903A6 +4E800421 7C771B78 +7EA3AB78 7EE4BB78 +FC20A890 FC40A890 +3D80803A 618C7548 +7D8903A6 4E800421 +7F25CB78 2C0F0000 +40820008 7EC5B378 +7EA3AB78 7EE4BB78 +3D80803A 618C74F0 +7D8903A6 4E800421 +7EA3AB78 7EE4BB78 +80A10038 80C1003C +80E10040 81010044 +81210048 8141004C +3D80803A 618C70A0 +7D8903A6 4E800421 +2C0F0000 4182000C +39EFFFFF 4BFFFF14 +48000094 7EA3AB78 +80810038 FC20B090 +FC40B890 3D80803A +618C6B98 7D8903A6 +4E800421 7C771B78 +7EA3AB78 7EE4BB78 +FC20A890 FC40A890 +3D80803A 618C7548 +7D8903A6 4E800421 +7EA3AB78 7EE4BB78 +7EC5B378 3D80803A +618C74F0 7D8903A6 +4E800421 7EA3AB78 +7EE4BB78 80A10038 +80C1003C 80E10040 +81010044 81210048 +8141004C 3D80803A +618C70A0 7D8903A6 +4E800421 7EE3BB78 +BA810008 800100B4 +382100B0 7C0803A6 +4E800020 7C0802A6 +90010004 9421FF50 +BE810008 7C7D1B78 +7C9C2378 7CDB3378 +FEC00890 FEE01090 +FF001890 FEA02090 +4800008D 7F4802A6 +38600000 7F64DB78 +C01A0000 FC20B090 +FC40B890 FC60C090 +C09A0004 C0BA0008 +3D80803A 618C5ACC +7D8903A6 4E800421 +7C751B78 2C1C0000 +41820010 38600001 +986DAFEC 7F86E378 +7EA3AB78 7FA4EB78 +FC00A890 D0030024 +D0030028 3D80803A +618C6368 7D8903A6 +4E800421 7EA3AB78 +BA810008 800100B4 +382100B0 7C0803A6 +4E800020 4E800021 +41100000 44160000 +41A00000 00000000 +C21C154C 00000004 #Common/Initialize Stage Data/Init Stage Data.asm +38800204 3D808000 +618CC160 7D8903A6 +4E800421 281A0000 +60000000 00000000 +C2068EEC 00000006 #Common/Initialize Player Data/Init Player Data.asm +3BC30000 3C808045 +60848FD0 80840020 +3D808000 618CC160 +7D8903A6 4E800421 +7FC3F378 3C808046 +60000000 00000000 +C209E090 00000011 #Common/FastForward/DynamicsFix.asm +807E0000 80630028 +48000009 48000074 +7C0802A6 90010004 +9421FFE8 93E10014 +7C7F1B78 807F0014 +54600211 40820020 +54600673 41820018 +7FE3FB78 3D808037 +618C3078 7D8903A6 +4E800421 807F0010 +2C030000 41820008 +4BFFFFB9 807F0008 +2C030000 41820008 +4BFFFFA9 83E10014 +8001001C 38210018 +7C0803A6 4E800020 +BB010028 00000000 + +$Optional: Show Player Names [Fizzi, UnclePunch, Enzyme, jmlee337] +*Show players' Slippi Online display names as HUD elements when available +C216E9B4 0000009A #Playback/Show Player Names/InitInGame.asm +48000088 4E800021 +3EA8F5C3 000000FF +3F1EB852 3F466666 +C1C07AE1 3C6F34D7 +3F4CCCCD 41A51EB8 +00000000 3D75C28F +43160000 3F0A3D71 +00000000 4E800021 +7C0802A6 90010004 +9421FF50 BE810008 +7C7F1B78 880DB6CC +2C000001 41820018 +7FE3FB78 3D808039 +618C10D8 7D8903A6 +4E800421 BA810008 +800100B4 382100B0 +7C0803A6 4E800020 +7C0802A6 90010004 +9421FF50 BE810008 +3C60804D 60636D5C +80630000 3C80803F +608494D0 3D808038 +618C0358 7D8903A6 +4E800421 80630004 +80630000 3D808036 +618CA590 7D8903A6 +4E800421 7C7E1B78 +38600013 38800014 +38A00000 3D808039 +618C01F0 7D8903A6 +4E800421 7C7D1B78 +7FA3EB78 888DC1AB +7FC5F378 3D808039 +618C0A70 7D8903A6 +4E800421 7FA3EB78 +4BFFFF25 7C8802A6 +38A00008 3D808039 +618C075C 7D8903A6 +4E800421 3C600000 +60631000 907D0024 +38600002 7FA4EB78 +38A00009 38C0000D +38E00000 3900000C +39200050 39400008 +3D80803A 618C611C +7D8903A6 4E800421 +7C7F1B78 4BFFFE91 +7F8802A6 834DB64C +3A800000 3EA0804A +62B50FF0 7E83A378 +3D808003 618C241C +7D8903A6 4E800421 +2C030003 41820308 +387A0570 1C94001F +7F032214 7F03C378 +3D808032 618C5B04 +7D8903A6 4E800421 +2C040000 418202E0 +7E83A378 3D80802F +618C3424 7D8903A6 +4E800421 C0230000 +D0210070 38600002 +7FE4FB78 3D80803A +618C6754 7D8903A6 +4E800421 7C7D1B78 +38800001 989D0048 +989D004A 989D004C +989D0049 C03C0024 +D03D0024 D03D0028 +C0210070 C05C0018 +EC21102A D03D0000 +C03C001C D03D0004 +C03C0020 D03D0008 +C03C0028 D03D000C +D03D0010 4CC63242 +C03C0030 C05C0030 +7FA3EB78 7F04C378 +3D80803A 618C6B98 +7D8903A6 4E800421 +7FA3EB78 38800000 +C03C002C C05C002C +3D80803A 618C7548 +7D8903A6 4E800421 +3860000E 3880000F +38A00000 3D808039 +618C01F0 7D8903A6 +4E800421 7C771B78 +3C60804A 60631ED0 +80630000 3D808037 +618C0E44 7D8903A6 +4E800421 7C761B78 +7EE3BB78 888DC1A9 +7EC5B378 3D808039 +618C0A70 7D8903A6 +4E800421 7EE3BB78 +3C808039 60841070 +38A0000C 38C00000 +3D808039 618C069C +7D8903A6 4E800421 +7E83A378 3D80802F +618C3424 7D8903A6 +4E800421 C0230000 +C05C000C EC21102A +D0360038 C03C0010 +D036003C C03C0008 +D0360030 7EC3B378 +38810080 38A00001 +38C0FFFF 3D808001 +618C1E24 7D8903A6 +4E800421 80610080 +38800000 90830040 +80610080 80630018 +80830014 60840001 +90830014 80630004 +80830014 60840001 +90830014 80630004 +80630008 8063000C +C03C0000 D023000C +809C0004 90830004 +3B200000 807D005C +38800000 3D80803A +618C6FEC 7D8903A6 +4E800421 3943000F +3D808040 618CCB00 +887D004F 1C630004 +3C80804D 60841124 +7C63202E 81630004 +886A0000 2C03000B +41820064 2C030020 +4182001C 2C030040 +41820034 886A0000 +2C03000F 41820050 +48000044 886A0001 +1C630002 7C6360AE +38800014 7C632050 +7F391A14 394A0002 +4BFFFFB8 886A0001 +1C630002 7C6358AE +38800014 7C632050 +7F391A14 394A0002 +4BFFFF98 394A0001 +4BFFFF90 2C19003C +40800008 3B20003C +2C190090 40810008 +3B200090 3C004330 +C84298A8 6F238000 +90010080 90610084 +C8210080 EC211028 +C05C0014 EC2100B2 +D036002C 3A940001 +2C140006 4180FCD8 +BA810008 800100B4 +382100B0 7C0803A6 +8001001C 00000000 + +$Optional: Game Music OFF [UnclePunch] +*Keep checked if you want music OFF. Uncheck "Game Music ON". +04023FFC 38800000 + +$Optional: Widescreen 16:9 [Dan Salvato, mirrorbender, Achilles1515, UnclePunch] +*Set Aspect Ratio to "Force 16:9" in Graphics +043BB05C 3EB00000 #External/Widescreen/Fix Screen Flash.asm +C236A4A8 00000007 #External/Widescreen/Overwrite CObj Values.asm +38600001 986DAFE0 +C03F0034 4800001D +7C6802A6 C0430000 +C0630004 EC2100B2 +EC211824 48000010 +4E800021 43A00000 +435B0000 00000000 +044DDB58 3E4CCCCD #External/Widescreen/Adjust Offscreen Scissor/Adjust Bubble Zoom.asm +04086B24 60000000 #External/Widescreen/Adjust Offscreen Scissor/Draw High Poly Models.asm +04030C7C 38000064 #External/Widescreen/Adjust Offscreen Scissor/Left Camera Bound.asm +04030C88 3800021C #External/Widescreen/Adjust Offscreen Scissor/Right Camera Bound.asm +044DDB30 3F666666 #External/Widescreen/Adjust Offscreen Scissor/Fix Bubble Positions/Adjust Corner Value 1.asm +044DDB34 BF666666 #External/Widescreen/Adjust Offscreen Scissor/Fix Bubble Positions/Adjust Corner Value 2.asm +044DDB2C C3660000 #External/Widescreen/Adjust Offscreen Scissor/Fix Bubble Positions/Extend Negative Vertical Bound.asm +044DDB28 43660000 #External/Widescreen/Adjust Offscreen Scissor/Fix Bubble Positions/Extend Positive Vertical Bound.asm +044DDB4C 3D916873 #External/Widescreen/Adjust Offscreen Scissor/Fix Bubble Positions/Widen Bubble Region.asm +C22FCFC4 00000004 #External/Widescreen/Nametag Fixes/Adjust Nametag Background X Scale.asm +48000011 7C6802A6 +C0030000 4800000C +4E800021 40DC7AE1 +60000000 00000000 +044DDB84 3E89FEFA #External/Widescreen/Nametag Fixes/Adjust Nametag Text X Scale.asm + +$Optional: Disable Screen Shake [Achilles1515] +*Disables all screen shaking +04030E44 4E800020 #External/Disable Screen Shake/Disable Screen Shake.asm + +$Optional: Hide HUD [UnclePunch] +*Hides the timer and player percent HUD elements +0416E9A4 60000000 #External/Hide Timer and Player HUD/Hide Timer HUD.asm +0416BA80 48000014 #External/Hide Timer and Player HUD/Hide Percents/Skip Percent Anim During Stock Steal.asm +0416E9B0 60000000 #External/Hide Timer and Player HUD/Hide Percents/Skip Player HUD Creation.asm + +$Optional: Hide Waiting For Game [Nikki, UnclePunch] +*Hides the waiting for game text and slippi.gg text and disables the SFX played before a replay starts +*With this enabled, there will be no indication between matches that Melee is still running +044DEC20 00000001 #Playback/Hide Waiting For Game/Hide Waiting For Game.asm + +$Optional: Enable Develop Mode [UnclePunch] +*Turns develop (debug) mode on. Allows access to frame advance, hit/hurtbox display, and alternate camera angles +044D4A08 00000004 #External/Enable Develop Mode/Enable Develop Mode.asm +04089250 48000008 #External/Enable Develop Mode/Enable Stale Moves.asm + +$Optional: Lagless FoD [Achilles, Myougi, Dan Salvato] +*Disables particles and reflection on FoD to improve performance +C21CBB90 00000005 #Lagless FoD +9421FFF8 3CC0804A +80C6ED78 3CA00002 +60A5AE44 7CA53050 +88C50000 60C60004 +98C50000 00000000 +041CC8AC FC000028 +041CBE9C 60000000 +041CBEF0 60000000 +041CBF54 60000000 +04390838 60000000 +041CD250 60000000 +041CCDCC 480000B4 diff --git a/Data/PlaybackGeckoCodes/GALJ01r2.ini b/Data/PlaybackGeckoCodes/GALJ01r2.ini new file mode 100644 index 0000000000..2740d41047 --- /dev/null +++ b/Data/PlaybackGeckoCodes/GALJ01r2.ini @@ -0,0 +1,1262 @@ +# GALJ01 - Super Smash Bros. Melee NTSC-J 1.02 + +[Core] +CPUThread = False +GPUDeterminismMode = fake-completion +PollingMethod = OnSIRead +FastDiscSpeed = True + +[Gecko_Enabled] +$Required: General Codes +$Required: Slippi Playback +$Optional: Show Player Names + +[Gecko] +$Required: General Codes [Achilles, Dan Salvato, UnclePunch, tauKhan, Ptomerty, Cilan, Datel, Most] +0415EE98 38600001 #Unlock All Characters and Stages [Datel] +0415EDDC 38600001 +04164B14 38600001 +041648F4 38600001 +0415EE4C 38600001 +0415EE14 38600001 +0415D968 38600001 +0415D9D8 38600001 +0417229C 38600000 +041737B0 38600000 +04164658 38600001 +041644E8 38600001 +0430490C 38600063 +043044F0 38600001 +0415D94C 4E800020 #Disable Special Messages [Most] +0415D984 4E800020 #Disable Trophy Messages [Achilles] +C22FCCE8 00000013 #External/Extended Nametag Box/Extended Nametag Box.asm +3C608003 6063556C +7C6803A6 887F0000 +4E800021 5460063E +28000078 41820070 +3C608045 6063D84F +1C0001A4 7C630214 +38800000 8C030001 +2C000000 41820018 +38840001 2C000080 +41A0FFEC 8C030001 +4BFFFFE4 2C040005 +41800034 3C604080 +9061FFF0 C221FFF0 +3E404330 CA028C58 +9241FFEC 9081FFF0 +C9E1FFEC EDEF8028 +EDEF8824 807E0010 +D1E3002C 807E0010 +60000000 00000000 +C213C388 0000000A #Common/CostumeBoundCheck/PuffCostume.asm +83DC002C 887E000C +3D808003 618C2330 +7D8903A6 4E800421 +3D808016 618C9238 +7D8903A6 4E800421 +889E0619 7C041800 +40800008 48000014 +3D808013 618CC46C +7D8903A6 4E800420 +809C002C 00000000 +C216DED4 00000039 #Common/CostumeBoundCheck/main.asm +7C0802A6 90010004 +9421FF50 BE810008 +3BE00000 7FE3FB78 +3D808003 618C241C +7D8903A6 4E800421 +2C030003 41820060 +7FE3FB78 3D808003 +618C3198 7D8903A6 +4E800421 7C7E1B78 +7FE3FB78 3D808003 +618C2330 7D8903A6 +4E800421 3D808016 +618C9238 7D8903A6 +4E800421 7C1E1800 +4180001C 7FE3FB78 +38800000 3D808003 +618C3208 7D8903A6 +4E800421 3BFF0001 +2C1F0006 4180FF80 +3BE00000 7FE3FB78 +3D808003 618C241C +7D8903A6 4E800421 +2C030003 418200EC +7FE3FB78 3D808003 +618C2330 7D8903A6 +4E800421 7C7E1B78 +7FE3FB78 3D808003 +618C3198 7D8903A6 +4E800421 7C7D1B78 +7FE3FB78 3D808003 +618C3284 7D8903A6 +4E800421 7C7C1B78 +3B600000 7C1FD800 +4182008C 7F63DB78 +3D808003 618C241C +7D8903A6 4E800421 +2C030003 41820070 +7F63DB78 3D808003 +618C2330 7D8903A6 +4E800421 7C03F000 +40820054 7F63DB78 +3D808003 618C3198 +7D8903A6 4E800421 +7C03E800 40820038 +7F63DB78 3D808003 +618C3284 7D8903A6 +4E800421 7C03E000 +4082001C 38830001 +7F63DB78 3D808003 +618C32F4 7D8903A6 +4E800421 3B7B0001 +2C1B0006 4180FF68 +3BFF0001 2C1F0006 +4180FEF4 BA810008 +800100B4 382100B0 +7C0803A6 8001001C +60000000 00000000 + +$Required: Slippi Playback [Fizzi, UnclePunch, Achilles, tauKhan] +*Used to play back a .slp file +*Will play replay configured in playback.txt +C216E9E4 00000010 #Playback/Core/CleanDynamicGeckos.asm +3BC30000 7C0802A6 +90010004 9421FF50 +BE810008 83CDB64C +83BE0010 807D0000 +2C030000 41820044 +389D0008 80BD0004 +3D808000 618C31F4 +7D8903A6 4E800421 +807D0000 809D0004 +3D808032 618C8F50 +7D8903A6 4E800421 +807D0004 7FBD1A14 +3BBD0008 4BFFFFB8 +BA810008 800100B4 +382100B0 7C0803A6 +60000000 00000000 +C216D298 00000016 #Playback/Core/FetchGameFrame.asm +881F0008 2C000000 +408200A0 7C0802A6 +90010004 9421FF50 +BE810008 806DB64C +83630000 38600076 +987B0000 806DB654 +907B0001 7F63DB78 +38800005 38A00001 +3D808000 618C55F0 +7D8903A6 4E800421 +7F63DB78 3880018F +38A00000 3D808000 +618C55F0 7D8903A6 +4E800421 887B0000 +2C030000 40820024 +3D808034 618CF314 +7D8903A6 4E800421 +3C60804C 38000000 +98031F7B 4BFFFF90 +BA810008 800100B4 +382100B0 7C0803A6 +881F0008 00000000 +C206B0DC 00000046 #Playback/Core/RestoreGameFrame.asm +7C0802A6 90010004 +9421FF50 BE810008 +8BBF000C 7FA3EB78 +3D808003 618C1724 +7D8903A6 4E800421 +7C7C1B78 832DB64C +83790000 7FE3FB78 +3D808000 618C55F8 +7D8903A6 4E800421 +7C741B78 389B0007 +88BF000C 1CA50062 +7C842A14 1CB40031 +7F442A14 3C80804D +807A0000 90645F90 +807A0004 907F0620 +807A0008 907F0624 +807A000C 907F0638 +807A0010 907F063C +807A0014 907F0650 +807A0018 907F065C +8879056F 2C030000 +41820024 807A001C +907F00B0 807A0020 +907F00B4 807A0024 +907F002C 807A0028 +907F0010 3C608046 +6063B108 3C80804C +60841F78 88840001 +3884FFFF 2C040000 +40A00008 38840005 +1C840030 7C632214 +889F0618 1C84000C +7E832214 887A002C +98740002 8879056F +2C030000 4182004C +807A002D 2C03FFFF +41820040 90610040 +C0210040 C05F1830 +EC211028 C0429500 +FC011040 41820024 +7FE3FB78 C0210040 +C05F1830 EC211028 +3D808006 618CCC7C +7D8903A6 4E800421 +806DB654 2C03FF85 +408200AC 7FE3FB78 +38800000 C0228874 +3D808007 618C592C +7D8903A6 4E800421 +807F00B0 907F06F4 +907F070C 807F00B4 +907F06F8 907F0710 +807F00B8 907F06FC +907F0714 C03F00B4 +D03F2344 806DAE0C +907F0728 887F000C +889F221F 5484EFFE +38BF00B0 3D808003 +618C2828 7D8903A6 +4E800421 7FC3F378 +3D808007 618C61C8 +7D8903A6 4E800421 +807F0890 C0230040 +D023002C C0230044 +D0230030 3D808002 +618CF3AC 7D8903A6 +4E800421 BA810008 +800100B4 382100B0 +7C0803A6 881F2219 +60000000 00000000 +C216E74C 0000009E #Playback/Core/RestoreGameInfo.asm +7C0802A6 90010004 +9421FF50 BE810008 +386005EC 3D808037 +618CF1E4 7D8903A6 +4E800421 7C7C1B78 +938DB64C 388005EC +3D808000 618CC160 +7D8903A6 4E800421 +38600221 3D808037 +618CF1E4 7D8903A6 +4E800421 7C7E1B78 +93DC0000 38600040 +3D808037 618CF1E4 +7D8903A6 4E800421 +907C0004 38600075 +987E0000 387C001C +907E0001 38600553 +907E0005 38600000 +907E0009 7FC3F378 +3880000D 38A00001 +3D808000 618C55F0 +7D8903A6 4E800421 +7FC3F378 38800221 +38A00000 3D808000 +618C55F0 7D8903A6 +4E800421 887E0000 +2C030001 41820018 +3D808034 618CF314 +7D8903A6 4E800421 +4BFFFF8C 807E0001 +3C80804D 90645F90 +7FE3FB78 389E0005 +38A00138 3D808000 +618C31F4 7D8903A6 +4E800421 387F0040 +3880001C 3D808000 +618CC160 7D8903A6 +4E800421 3AE2F22C +3A82F230 3ABE013D +3AC00000 1C960008 +7C64A82E 7C76B9AE +38840004 7C64A82E +7C76A1AE 3AD60001 +2C160004 4180FFE0 +3A800000 3ABF0060 +1ED40024 7ED6AA14 +88760001 2C030000 +40820078 8876000A +2C030078 4182006C +7C771B78 3D808023 +618C7A04 7D8903A6 +4E800421 7EE3BB78 +3D808015 618CCC9C +7D8903A6 4E800421 +38630198 389E015D +1CB40010 7C842A14 +88A40000 2C050000 +40820010 38600078 +9876000A 4800001C +38A00010 3D808000 +618C31F4 7D8903A6 +4E800421 48000004 +3A940001 2C140004 +4180FF70 887E019D +9862F234 887E019E +9862F238 887E019F +9862F23C 887E01A0 +987C056F 387C0570 +389E01A1 38A0007C +3D808000 618C31F4 +7D8903A6 4E800421 +807E021D 3D808037 +618CF1E4 7D8903A6 +4E800421 7C7D1B78 +93BC0008 3860008A +987D0000 7FA3EB78 +38800001 38A00001 +3D808000 618C55F0 +7D8903A6 4E800421 +7FA3EB78 809E021D +38A00000 3D808000 +618C55F0 7D8903A6 +4E800421 38800004 +909C000C 7FA3EB78 +48000055 7C8802A6 +3D808000 618C55FC +7D8903A6 4E800421 +807C000C 3D808037 +618CF1E4 7D8903A6 +4E800421 907C0010 +907C0014 7FA3EB78 +48000041 7C8802A6 +3D808000 618C55FC +7D8903A6 4E800421 +4800013C 4E800021 +2C050000 41820018 +80CDB64C 8066000C +38630008 7C632A14 +9066000C 4E800020 +4E800021 2C050000 +41820108 7C0802A6 +90010004 9421FF50 +BE810008 7C9E2378 +7CBB2B78 80BE0000 +54A501FE 64BD8000 +834DB64C 833A0014 +2C030004 41820014 +2C030006 41820014 +2C0300C2 41820014 +3B9E0004 48000048 +3B9E0008 48000040 +389E0008 7C7D2050 +546301BA 64634800 +907A0018 3B9A0018 +807E0004 1C630008 +7C83F214 387D0004 +7C641850 546301BA +64634800 3863FFFC +90640004 93B90000 +93790004 38790008 +7FA4EB78 7F65DB78 +3D808000 618C31F4 +7D8903A6 4E800421 +3B390008 7F39DA14 +933A0014 7FA3EB78 +7F84E378 7F65DB78 +3D808000 618C31F4 +7D8903A6 4E800421 +7FA3EB78 7F64DB78 +3D808032 618C8F50 +7D8903A6 4E800421 +BA810008 800100B4 +382100B0 7C0803A6 +4E800020 38600000 +809C0014 90640000 +7FA3EB78 809E021D +3D808032 618C8F50 +7D8903A6 4E800421 +38600004 38800007 +38A00000 3D808039 +618C01F0 7D8903A6 +4E800421 48000021 +7C8802A6 38A00000 +3D808038 618CFD54 +7D8903A6 4E800421 +4800004C 4E800021 +7C0802A6 90010004 +9421FF50 BE810008 +806DB64C 83A30000 +887D0002 2C030000 +41820010 807D0003 +3C80804D 90645F90 +BA810008 800100B4 +382100B0 7C0803A6 +4E800020 BA810008 +800100B4 382100B0 +7C0803A6 3C608017 +60000000 00000000 +C216D304 00000009 #Playback/Core/RestoreLRAStart.asm +806DB64C 80630000 +88630000 2C030002 +4082002C 3860FFFF +38800007 3D808016 +618CCF4C 7D8903A6 +4E800421 3D808016 +618CD30C 7D8903A6 +4E800420 7FE3FB78 +60000000 00000000 +C216B9C0 00000012 #Playback/Core/RestoreStockSteal.asm +80ADB64C 80A50004 +38800089 98850000 +808DB654 90850001 +98650005 7CA32B78 +38800006 38A00001 +3D808000 618C55F0 +7D8903A6 4E800421 +806DB64C 80630004 +38800001 38A00000 +3D808000 618C55F0 +7D8903A6 4E800421 +806DB64C 80630004 +88630000 2C030000 +41820014 3D808016 +618CBA1C 7D8903A6 +4E800420 3D808016 +618CBAC8 7D8903A6 +4E800420 00000000 +C21A501C 0000002A #Playback/Core/FastForward/FastForward.asm +3C808048 88649D30 +2C03000E 40820040 +88649D33 2C030001 +40820034 38600001 +3D80801A 618C45E8 +7D8903A6 4E800421 +2C030002 41820018 +806DB64C 80630000 +88630000 2C030003 +41820024 38600001 +38800002 3D808002 +618C5064 7D8903A6 +4E800421 7C1AD800 +480000E0 806DB64C +80630000 88630001 +2C030001 4182001C +38600000 38800000 +3D808002 618C5064 +7D8903A6 4E800421 +4800000D 2C0300FF +480000A8 7C0802A6 +90010004 9421FF50 +BE810008 3D808003 +618C0A50 7D8903A6 +4E800421 3D808002 +618CA4AC 7D8903A6 +4E800421 3D808003 +618C0A50 7D8903A6 +4E800421 80630028 +3D808036 618C8458 +7D8903A6 4E800421 +806DC18C 82830020 +4800002C 82B4002C +8875221F 546006F7 +40820018 7E83A378 +3D808008 618C6A8C +7D8903A6 4E800421 +82940008 2C140000 +4082FFD4 BA810008 +800100B4 382100B0 +7C0803A6 4E800020 +60000000 00000000 +C2377544 00000002 #Playback/Core/FastForward/IncrementPadIndex.asm +40A2000C 38000001 +981E0003 00000000 +04376A88 881F0001 #Playback/Core/FastForward/PadAlwaysUseMasterIndex.asm +C21A45A0 00000007 #Playback/Core/Scene/Boot to Playback Scene.asm +48000019 7C6802A6 +3C80803D 6084ADA8 +90640004 4800001C +4E800021 38600003 +3C808047 60849D30 +98640003 4E800020 +3800000E 00000000 +C21A6348 000000AB #Playback/Core/Scene/SceneThink_Playback.asm +3C608047 60639D30 +88630000 2C03000E +4082053C 3860000D +3880000E 38A00000 +3D808039 618C01F0 +7D8903A6 4E800421 +48000021 7C8802A6 +38A00000 3D808038 +618CFD54 7D8903A6 +4E800421 480004F0 +4E800021 7C0802A6 +90010004 9421FF50 +BE810008 48000461 +7FC802A6 38600000 +3880FFFF 3D80803A +618C6754 7D8903A6 +4E800421 7C7C1B78 +38800001 989C0049 +38800000 989C004A +C03E0008 D03C0008 +C03E0010 D03C0024 +D03C0028 C03E0000 +C05E0004 7F83E378 +48000435 7C8802A6 +48000445 7CA802A6 +3D80803A 618C6B98 +7D8903A6 4E800421 +7C641B78 7F83E378 +C03E000C C05E000C +3D80803A 618C7548 +7D8903A6 4E800421 +C03E0014 C05E0018 +7F83E378 48000415 +7C8802A6 3D80803A +618C6B98 7D8903A6 +4E800421 7C641B78 +7F83E378 C03E000C +C05E000C 3D80803A +618C7548 7D8903A6 +4E800421 3C602ECC +606340FF 90610040 +7F83E378 38800001 +38A10040 3D80803A +618C74F0 7D8903A6 +4E800421 38600221 +3D808037 618CF1E4 +7D8903A6 4E800421 +7C7D1B78 3B600000 +3D808033 618CC898 +7D8903A6 4E800421 +3D808033 618CF270 +7D8903A6 4E800421 +38600000 3D808037 +618C5538 7D8903A6 +4E800421 8062F240 +2C030000 4082001C +38600000 7F84E378 +3D80803A 618C84BC +7D8903A6 4E800421 +38600000 3D808037 +618C61C0 7D8903A6 +4E800421 3D808034 +618CF314 7D8903A6 +4E800421 3B7B0001 +2C1B00F0 41800008 +3B600000 3860003C +7C7B1B96 480002F1 +7C8802A6 1C630004 +7CC32214 7F83E378 +38800000 480002C1 +7CA802A6 4CC63182 +3D80803A 618C70A0 +7D8903A6 4E800421 +38600088 987D0000 +7FA3EB78 38800001 +38A00001 3D808000 +618C55F0 7D8903A6 +4E800421 7FA3EB78 +38800001 38A00000 +3D808000 618C55F0 +7D8903A6 4E800421 +887D0000 2C030001 +4082FEF0 7F83E378 +3D80803A 618C5CC4 +7D8903A6 4E800421 +38600075 987D0000 +38600000 907D0001 +38600000 907D0005 +38600000 907D0009 +7FA3EB78 3880000D +38A00001 3D808000 +618C55F0 7D8903A6 +4E800421 7FA3EB78 +38800221 38A00000 +3D808000 618C55F0 +7D8903A6 4E800421 +887D0000 2C030001 +41820018 3D808034 +618CF314 7D8903A6 +4E800421 4BFFFF8C +3A9D0005 3C808043 +60842078 88740060 +90640014 88740063 +98640018 88740084 +9064001C 88740087 +98640020 887400A8 +90640024 887400AB +98640028 887400CC +9064002C 887400CF +98640030 A074000E +9064000C 3D808001 +618C8254 7D8903A6 +4E800421 386000C7 +3D808001 618C8C2C +7D8903A6 4E800421 +38600004 3D808001 +618C7700 7D8903A6 +4E800421 3860001C +3D808002 618C6F2C +7D8903A6 4E800421 +3D808021 618CB2D8 +7D8903A6 4E800421 +3AA00000 1C150024 +7E96A378 7ED60214 +3D808000 618C569C +7D8903A6 4E800421 +88960060 7C840774 +7C041800 41820028 +38600000 3D808000 +618C56A0 7D8903A6 +4E800421 3D808000 +618C56A8 7D8903A6 +4E800421 3AB50001 +2C150006 3AD60024 +4180FFB0 A074000E +3D808022 618C519C +7D8903A6 4E800421 +7C641B78 38600001 +3D808000 618C56A0 +7D8903A6 4E800421 +3D808000 618C56A8 +7D8903A6 4E800421 +3D808002 618C7168 +7D8903A6 4E800421 +8062F240 2C030000 +40820018 38600001 +3D808002 618C4030 +7D8903A6 4E800421 +3D808002 618C4F6C +7D8903A6 4E800421 +3D80801A 618C4B60 +7D8903A6 4E800421 +48000068 4E800021 +C33E0000 00000000 +00000000 3F800000 +3F19999A 43B70000 +43AF0000 432A0000 +00000000 4E800021 +57616974 696E6720 +666F7220 67616D65 +25730000 4E800021 +00000000 2E000000 +2E2E0000 2E2E2E00 +4E800021 736C6970 +70692E67 67000000 +BA810008 800100B4 +382100B0 7C0803A6 +4E800020 3D80801A +618C6368 7D8903A6 +4E800420 807F0000 +60000000 00000000 +041B16A8 801B09C0 #Playback/Core/Scene/Change Debug Result Screen MinorType to Debug Menu/ScenePrep_DebugResult = ScenePrep_DebugMenu.asm +043DDA9C 07000000 #Playback/Core/Scene/Change Debug Result Screen MinorType to Debug Menu/Swap MinorType.asm +C238D224 00000015 #Playback/Core/Sounds/AssignSoundInstanceId.asm +900DC0E8 3C608048 +80639D30 5463443E +2C03010E 40820090 +7C0802A6 90010004 +9421FF50 BE810008 +83EDB64C 3BDF001C +8B9E0000 3C608048 +80639D60 809F056B +7C032000 41810028 +3C608048 80639D60 +809F056B 7C632050 +38630001 8B9E0000 +7F83E051 40800008 +3B9C0007 1C7C00C2 +38DE0001 7CC61A14 +88660000 3863FFFF +1C630006 38A60001 +7CA51A14 807D000C +90650002 BA810008 +800100B4 382100B0 +7C0803A6 00000000 +C21A5014 00000032 #Playback/Core/Sounds/HandleFrameSoundLog.asm +41A20014 3D80801A +618C5024 7D8903A6 +4E800420 3C608048 +80639D30 5463443E +2C03010E 40820168 +7C0802A6 90010004 +9421FF50 BE810008 +3D808034 618C7364 +7D8903A6 4E800421 +7C7D1B78 83EDB64C +3BDF001C 8B9E0000 +3F008048 83189D60 +3B18FFFF 82FF056B +7C18B800 4181009C +7C78B850 38630001 +8B9E0000 7F83E051 +40800008 3B9C0007 +387E0001 1C9C00C2 +7F432214 3B200000 +48000060 38DA0000 +38E00000 48000028 +1C790006 7C651A14 +A0630001 1C870006 +7C862214 A0840001 +7C032000 41820030 +38E70001 88660000 +2C070003 4180FFD4 +1C790006 7C651A14 +80630003 3D808002 +618C36B8 7D8903A6 +4E800421 3B390001 +38BA0061 88650000 +7C191800 4180FF98 +387E0001 1C9C00C2 +7F432214 387A0061 +389A0000 38A00061 +3D808000 618C31F4 +7D8903A6 4E800421 +387A0000 38800061 +3D808000 618CC160 +7D8903A6 4E800421 +7C18B800 4081001C +931F056B 3B9C0001 +2C1C0007 41800008 +3B9CFFF9 9B9E0000 +7FA3EB78 3D808034 +618C738C 7D8903A6 +4E800421 BA810008 +800100B4 382100B0 +7C0803A6 00000000 +C2088224 0000001D #Playback/Core/Sounds/NoDestroyVoice.asm +3C608048 80639D30 +5463443E 2C03010E +408200CC 7C0802A6 +90010004 9421FF50 +BE810008 83EDB64C +3BBF001C 57DE043E +8B9D0000 3C608048 +80639D60 809F056B +7C032000 41810088 +3C608048 80639D60 +809F056B 7C632050 +38630001 8B9D0000 +7F83E051 40800008 +3B9C0007 1C7C00C2 +38DD0062 7CC61A14 +39000000 48000020 +1C680006 38A60001 +7CA51A14 A0650000 +7C1E1800 41820018 +39080001 88660000 +7C081800 4180FFDC +48000024 BA810008 +800100B4 382100B0 +7C0803A6 3D808008 +618C8244 7D8903A6 +4E800420 BA810008 +800100B4 382100B0 +7C0803A6 387F0000 +60000000 00000000 +C20882B0 0000001D #Playback/Core/Sounds/NoDestroyVoice2.asm +3C608048 80639D30 +5463443E 2C03010E +408200CC 7C0802A6 +90010004 9421FF50 +BE810008 83EDB64C +3BBF001C 57DE043E +8B9D0000 3C608048 +80639D60 809F056B +7C032000 41810088 +3C608048 80639D60 +809F056B 7C632050 +38630001 8B9D0000 +7F83E051 40800008 +3B9C0007 1C7C00C2 +38DD0062 7CC61A14 +39000000 48000020 +1C680006 38A60001 +7CA51A14 A0650000 +7C1E1800 41820018 +39080001 88660000 +7C081800 4180FFDC +48000024 BA810008 +800100B4 382100B0 +7C0803A6 3D808008 +618C82D0 7D8903A6 +4E800420 BA810008 +800100B4 382100B0 +7C0803A6 387F0000 +60000000 00000000 +C238D0B0 00000027 #Playback/Core/Sounds/PreventDuplicateSounds.asm +3C608048 80639D30 +5463443E 2C03010E +40820120 7C0802A6 +90010004 9421FF50 +BE810008 83EDB64C +3BDF001C 3BA00000 +3B400000 56FB043E +8B9E0000 3C608048 +80639D60 809F056B +7C032000 41810070 +3C608048 80639D60 +809F056B 7C632050 +38630001 8B9E0000 +7F83E051 40800008 +3B9C0007 1C7C00C2 +38DE0062 7CC61A14 +39000000 48000020 +1C680006 38A60001 +7CA51A14 A0650000 +7C1B1800 41820018 +39080001 88660000 +7C081800 4180FFDC +4800000C 83450002 +3BA00001 1C7C00C2 +38DE0001 7CC61A14 +88660000 2C030010 +40800024 1C630006 +38A60001 7CA51A14 +B3650000 93450002 +88660000 38630001 +98660000 2C1D0000 +41820028 7F43D378 +BA810008 800100B4 +382100B0 7C0803A6 +3D808038 618CD2A0 +7D8903A6 4E800420 +BA810008 800100B4 +382100B0 7C0803A6 +2C1A0000 00000000 +C200569C 00000002 #Common/GetFighterNum.asm +38600021 4E800020 +60000000 00000000 +C20055F8 0000000F #Common/GetIsFollower.asm +7C0802A6 90010004 +9421FF50 BE810008 +7C7E1B78 3BE00000 +887E221F 5460EFFF +41820038 887E000C +3D808003 618C2330 +7D8903A6 4E800421 +3C80803B 6084CDE0 +1C030003 7C640214 +88030002 2C000000 +40820008 3BE00001 +7FE3FB78 BA810008 +800100B4 382100B0 +7C0803A6 4E800020 +60000000 00000000 +C20056A0 00000007 #Common/GetSSMIndex.asm +2C030001 41820018 +3C60803B 6063B3C0 +1C840010 7C6320AE +48000018 3C60803B +6063B6B0 1C840003 +7C6320AE 48000004 +4E800020 00000000 +C216D294 00000006 #Common/IncrementFrameIndex.asm +987F0008 3C608048 +80639D58 2C030000 +40820010 3860FF85 +906DB654 48000010 +806DB654 38630001 +906DB654 00000000 +C20055F4 00000007 #Common/IntToFloat.asm +9421FF00 D0410008 +3C004330 C84298A8 +6C638000 900100F0 +906100F4 C82100F0 +EC211028 C0410008 +38210100 4E800020 +60000000 00000000 +C20056A4 00000022 #Common/LoadPremadeText.asm +7C0802A6 90010004 +9421FF50 BE810008 +7C7F1B78 7C9E2378 +3B800004 7F83E378 +3D808037 618CF1E4 +7D8903A6 4E800421 +7C7D1B78 7F84E378 +3D808000 618CC160 +7D8903A6 4E800421 +386000E1 48000055 +839D0000 7FA3EB78 +3D808037 618CF1B0 +7D8903A6 4E800421 +7F83E378 3D808037 +618CF1E4 7D8903A6 +4E800421 7C7D1B78 +386000E2 4800001D +7FA3EB78 BA810008 +800100B4 382100B0 +7C0803A6 4E800020 +7C0802A6 90010004 +9421FF50 BE810008 +987D0000 9BFD0001 +9BDD0002 7FA3EB78 +38800003 38A00001 +3D808000 618C55F0 +7D8903A6 4E800421 +7FA3EB78 7F84E378 +38A00000 3D808000 +618C55F0 7D8903A6 +4E800421 BA810008 +800100B4 382100B0 +7C0803A6 4E800020 +60000000 00000000 +C20055EC 00000008 #Common/MultiplyRWithF.asm +7C0802A6 90010004 +9421FF50 BE810008 +3D808000 618C55F4 +7D8903A6 4E800421 +EC2100B2 BA810008 +800100B4 382100B0 +7C0803A6 4E800020 +60000000 00000000 +C20056A8 00000005 #Common/RequestSSMLoad.asm +2C030037 41820018 +3D808043 618C37C4 +38800001 1C630004 +7C83612E 4E800020 +60000000 00000000 +C20056B4 00000059 #Common/SubtextFunctions.asm +2C050002 418201F8 +7C0802A6 90010004 +9421FF50 BE810008 +7C751B78 7C962378 +7CB82B78 7CD93378 +90E10038 9101003C +91210040 91410044 +91610048 9181004C +FEA00890 FEC01090 +FEE01890 FF202890 +FF403090 2C180001 +418000FC 39E00004 +FC20B090 FC40B890 +2C0F0001 41820020 +2C0F0002 41820020 +2C0F0003 41820020 +2C0F0004 41820020 +48000024 EC21D028 +4800001C EC21D02A +48000014 EC42D028 +4800000C EC42D02A +48000004 7EA3AB78 +80810038 3D80803A +618C6B98 7D8903A6 +4E800421 7C771B78 +7EA3AB78 7EE4BB78 +FC20A890 FC40A890 +3D80803A 618C7548 +7D8903A6 4E800421 +7F25CB78 2C0F0000 +40820008 7EC5B378 +7EA3AB78 7EE4BB78 +3D80803A 618C74F0 +7D8903A6 4E800421 +7EA3AB78 7EE4BB78 +80A10038 80C1003C +80E10040 81010044 +81210048 8141004C +3D80803A 618C70A0 +7D8903A6 4E800421 +2C0F0000 4182000C +39EFFFFF 4BFFFF14 +48000094 7EA3AB78 +80810038 FC20B090 +FC40B890 3D80803A +618C6B98 7D8903A6 +4E800421 7C771B78 +7EA3AB78 7EE4BB78 +FC20A890 FC40A890 +3D80803A 618C7548 +7D8903A6 4E800421 +7EA3AB78 7EE4BB78 +7EC5B378 3D80803A +618C74F0 7D8903A6 +4E800421 7EA3AB78 +7EE4BB78 80A10038 +80C1003C 80E10040 +81010044 81210048 +8141004C 3D80803A +618C70A0 7D8903A6 +4E800421 7EE3BB78 +BA810008 800100B4 +382100B0 7C0803A6 +4E800020 7C0802A6 +90010004 9421FF50 +BE810008 7C7D1B78 +7C9C2378 7CDB3378 +FEC00890 FEE01090 +FF001890 FEA02090 +4800008D 7F4802A6 +38600000 7F64DB78 +C01A0000 FC20B090 +FC40B890 FC60C090 +C09A0004 C0BA0008 +3D80803A 618C5ACC +7D8903A6 4E800421 +7C751B78 2C1C0000 +41820010 38600001 +986DAFEC 7F86E378 +7EA3AB78 7FA4EB78 +FC00A890 D0030024 +D0030028 3D80803A +618C6368 7D8903A6 +4E800421 7EA3AB78 +BA810008 800100B4 +382100B0 7C0803A6 +4E800020 4E800021 +41100000 44160000 +41A00000 00000000 +C21C154C 00000004 #Common/Initialize Stage Data/Init Stage Data.asm +38800204 3D808000 +618CC160 7D8903A6 +4E800421 281A0000 +60000000 00000000 +C2068EEC 00000006 #Common/Initialize Player Data/Init Player Data.asm +3BC30000 3C808045 +60848FD0 80840020 +3D808000 618CC160 +7D8903A6 4E800421 +7FC3F378 3C808046 +60000000 00000000 +C209E090 00000011 #Common/FastForward/DynamicsFix.asm +807E0000 80630028 +48000009 48000074 +7C0802A6 90010004 +9421FFE8 93E10014 +7C7F1B78 807F0014 +54600211 40820020 +54600673 41820018 +7FE3FB78 3D808037 +618C3078 7D8903A6 +4E800421 807F0010 +2C030000 41820008 +4BFFFFB9 807F0008 +2C030000 41820008 +4BFFFFA9 83E10014 +8001001C 38210018 +7C0803A6 4E800020 +BB010028 00000000 + +$Optional: Show Player Names [Fizzi, UnclePunch, Enzyme, jmlee337] +*Show players' Slippi Online display names as HUD elements when available +C216E9B4 0000009A #Playback/Show Player Names/InitInGame.asm +48000088 4E800021 +3EA8F5C3 000000FF +3F1EB852 3F466666 +C1C07AE1 3C6F34D7 +3F4CCCCD 41A51EB8 +00000000 3D75C28F +43160000 3F0A3D71 +00000000 4E800021 +7C0802A6 90010004 +9421FF50 BE810008 +7C7F1B78 880DB6CC +2C000001 41820018 +7FE3FB78 3D808039 +618C10D8 7D8903A6 +4E800421 BA810008 +800100B4 382100B0 +7C0803A6 4E800020 +7C0802A6 90010004 +9421FF50 BE810008 +3C60804D 60636D5C +80630000 3C80803F +608494D0 3D808038 +618C0358 7D8903A6 +4E800421 80630004 +80630000 3D808036 +618CA590 7D8903A6 +4E800421 7C7E1B78 +38600013 38800014 +38A00000 3D808039 +618C01F0 7D8903A6 +4E800421 7C7D1B78 +7FA3EB78 888DC1AB +7FC5F378 3D808039 +618C0A70 7D8903A6 +4E800421 7FA3EB78 +4BFFFF25 7C8802A6 +38A00008 3D808039 +618C075C 7D8903A6 +4E800421 3C600000 +60631000 907D0024 +38600002 7FA4EB78 +38A00009 38C0000D +38E00000 3900000C +39200050 39400008 +3D80803A 618C611C +7D8903A6 4E800421 +7C7F1B78 4BFFFE91 +7F8802A6 834DB64C +3A800000 3EA0804A +62B50FF0 7E83A378 +3D808003 618C241C +7D8903A6 4E800421 +2C030003 41820308 +387A0570 1C94001F +7F032214 7F03C378 +3D808032 618C5B04 +7D8903A6 4E800421 +2C040000 418202E0 +7E83A378 3D80802F +618C3424 7D8903A6 +4E800421 C0230000 +D0210070 38600002 +7FE4FB78 3D80803A +618C6754 7D8903A6 +4E800421 7C7D1B78 +38800001 989D0048 +989D004A 989D004C +989D0049 C03C0024 +D03D0024 D03D0028 +C0210070 C05C0018 +EC21102A D03D0000 +C03C001C D03D0004 +C03C0020 D03D0008 +C03C0028 D03D000C +D03D0010 4CC63242 +C03C0030 C05C0030 +7FA3EB78 7F04C378 +3D80803A 618C6B98 +7D8903A6 4E800421 +7FA3EB78 38800000 +C03C002C C05C002C +3D80803A 618C7548 +7D8903A6 4E800421 +3860000E 3880000F +38A00000 3D808039 +618C01F0 7D8903A6 +4E800421 7C771B78 +3C60804A 60631ED0 +80630000 3D808037 +618C0E44 7D8903A6 +4E800421 7C761B78 +7EE3BB78 888DC1A9 +7EC5B378 3D808039 +618C0A70 7D8903A6 +4E800421 7EE3BB78 +3C808039 60841070 +38A0000C 38C00000 +3D808039 618C069C +7D8903A6 4E800421 +7E83A378 3D80802F +618C3424 7D8903A6 +4E800421 C0230000 +C05C000C EC21102A +D0360038 C03C0010 +D036003C C03C0008 +D0360030 7EC3B378 +38810080 38A00001 +38C0FFFF 3D808001 +618C1E24 7D8903A6 +4E800421 80610080 +38800000 90830040 +80610080 80630018 +80830014 60840001 +90830014 80630004 +80830014 60840001 +90830014 80630004 +80630008 8063000C +C03C0000 D023000C +809C0004 90830004 +3B200000 807D005C +38800000 3D80803A +618C6FEC 7D8903A6 +4E800421 3943000F +3D808040 618CCB00 +887D004F 1C630004 +3C80804D 60841124 +7C63202E 81630004 +886A0000 2C03000B +41820064 2C030020 +4182001C 2C030040 +41820034 886A0000 +2C03000F 41820050 +48000044 886A0001 +1C630002 7C6360AE +38800014 7C632050 +7F391A14 394A0002 +4BFFFFB8 886A0001 +1C630002 7C6358AE +38800014 7C632050 +7F391A14 394A0002 +4BFFFF98 394A0001 +4BFFFF90 2C19003C +40800008 3B20003C +2C190090 40810008 +3B200090 3C004330 +C84298A8 6F238000 +90010080 90610084 +C8210080 EC211028 +C05C0014 EC2100B2 +D036002C 3A940001 +2C140006 4180FCD8 +BA810008 800100B4 +382100B0 7C0803A6 +8001001C 00000000 + +$Optional: Game Music OFF [UnclePunch] +*Keep checked if you want music OFF. Uncheck "Game Music ON". +04023FFC 38800000 + +$Optional: Widescreen 16:9 [Dan Salvato, mirrorbender, Achilles1515, UnclePunch] +*Set Aspect Ratio to "Force 16:9" in Graphics +043BB05C 3EB00000 #External/Widescreen/Fix Screen Flash.asm +C236A4A8 00000007 #External/Widescreen/Overwrite CObj Values.asm +38600001 986DAFE0 +C03F0034 4800001D +7C6802A6 C0430000 +C0630004 EC2100B2 +EC211824 48000010 +4E800021 43A00000 +435B0000 00000000 +044DDB58 3E4CCCCD #External/Widescreen/Adjust Offscreen Scissor/Adjust Bubble Zoom.asm +04086B24 60000000 #External/Widescreen/Adjust Offscreen Scissor/Draw High Poly Models.asm +04030C7C 38000064 #External/Widescreen/Adjust Offscreen Scissor/Left Camera Bound.asm +04030C88 3800021C #External/Widescreen/Adjust Offscreen Scissor/Right Camera Bound.asm +044DDB30 3F666666 #External/Widescreen/Adjust Offscreen Scissor/Fix Bubble Positions/Adjust Corner Value 1.asm +044DDB34 BF666666 #External/Widescreen/Adjust Offscreen Scissor/Fix Bubble Positions/Adjust Corner Value 2.asm +044DDB2C C3660000 #External/Widescreen/Adjust Offscreen Scissor/Fix Bubble Positions/Extend Negative Vertical Bound.asm +044DDB28 43660000 #External/Widescreen/Adjust Offscreen Scissor/Fix Bubble Positions/Extend Positive Vertical Bound.asm +044DDB4C 3D916873 #External/Widescreen/Adjust Offscreen Scissor/Fix Bubble Positions/Widen Bubble Region.asm +C22FCFC4 00000004 #External/Widescreen/Nametag Fixes/Adjust Nametag Background X Scale.asm +48000011 7C6802A6 +C0030000 4800000C +4E800021 40DC7AE1 +60000000 00000000 +044DDB84 3E89FEFA #External/Widescreen/Nametag Fixes/Adjust Nametag Text X Scale.asm + +$Optional: Disable Screen Shake [Achilles1515] +*Disables all screen shaking +04030E44 4E800020 #External/Disable Screen Shake/Disable Screen Shake.asm + +$Optional: Hide HUD [UnclePunch] +*Hides the timer and player percent HUD elements +0416E9A4 60000000 #External/Hide Timer and Player HUD/Hide Timer HUD.asm +0416BA80 48000014 #External/Hide Timer and Player HUD/Hide Percents/Skip Percent Anim During Stock Steal.asm +0416E9B0 60000000 #External/Hide Timer and Player HUD/Hide Percents/Skip Player HUD Creation.asm + +$Optional: Hide Waiting For Game [Nikki, UnclePunch] +*Hides the waiting for game text and slippi.gg text and disables the SFX played before a replay starts +*With this enabled, there will be no indication between matches that Melee is still running +044DEC20 00000001 #Playback/Hide Waiting For Game/Hide Waiting For Game.asm + +$Optional: Enable Develop Mode [UnclePunch] +*Turns develop (debug) mode on. Allows access to frame advance, hit/hurtbox display, and alternate camera angles +044D4A08 00000004 #External/Enable Develop Mode/Enable Develop Mode.asm +04089250 48000008 #External/Enable Develop Mode/Enable Stale Moves.asm + +$Optional: Lagless FoD [Achilles, Myougi, Dan Salvato] +*Disables particles and reflection on FoD to improve performance +C21CBB90 00000005 #Lagless FoD +9421FFF8 3CC0804A +80C6ED78 3CA00002 +60A5AE44 7CA53050 +88C50000 60C60004 +98C50000 00000000 +041CC8AC FC000028 +041CBE9C 60000000 +041CBEF0 60000000 +041CBF54 60000000 +04390838 60000000 +041CD250 60000000 +041CCDCC 480000B4 diff --git a/Data/linux-env.sh b/Data/linux-env.sh new file mode 100644 index 0000000000..b5aff092a2 --- /dev/null +++ b/Data/linux-env.sh @@ -0,0 +1,15 @@ +#!/bin/bash -e +# linux-env.sh + +# Add /usr/lib/ to LD_LIBRARY_PATH cause Ubuntu is dumb +export LD_LIBRARY_PATH="/usr/lib/:$LD_LIBRARY_PATH" + +if [[ $(env | grep -i wayland) ]]; then + # wxWidgets 3.14 is GTK3, which seemingly has an issue or two when + # running under Wayland. Explicitly setting this for Slippi avoids + # those issues. + export GDK_BACKEND=x11 + + # Disable Webkit compositing on Wayland cause it breaks stuff + export WEBKIT_DISABLE_COMPOSITING_MODE=1 +fi diff --git a/Data/slippi_dmg_background.png b/Data/slippi_dmg_background.png new file mode 100644 index 0000000000..fec520848e Binary files /dev/null and b/Data/slippi_dmg_background.png differ diff --git a/Data/slippi_dmg_icon.icns b/Data/slippi_dmg_icon.icns new file mode 100644 index 0000000000..4a17b18dec Binary files /dev/null and b/Data/slippi_dmg_icon.icns differ diff --git a/Externals/SlippiLib/SlippiGame.cpp b/Externals/SlippiLib/SlippiGame.cpp index 8655c16d5f..7892486653 100644 --- a/Externals/SlippiLib/SlippiGame.cpp +++ b/Externals/SlippiLib/SlippiGame.cpp @@ -1,17 +1,20 @@ -#include #include #include +#include #include "SlippiGame.h" -namespace Slippi { - +namespace Slippi +{ //********************************************************************** //* Event Handlers //********************************************************************** - //The read operators will read a value and increment the index so the next read will read in the correct location - uint8_t readByte(uint8_t* a, int& idx, uint32_t maxSize, uint8_t defaultValue) { - if (idx >= (int)maxSize) { + // The read operators will read a value and increment the index so the next read + // will read in the correct location + uint8_t readByte(uint8_t* a, int& idx, uint32_t maxSize, uint8_t defaultValue) + { + if (idx >= (int)maxSize) + { idx += 1; return defaultValue; } @@ -19,8 +22,10 @@ namespace Slippi { return a[idx++]; } - uint16_t readHalf(uint8_t* a, int& idx, uint32_t maxSize, uint16_t defaultValue) { - if (idx >= (int)maxSize) { + uint16_t readHalf(uint8_t* a, int& idx, uint32_t maxSize, uint16_t defaultValue) + { + if (idx >= (int)maxSize) + { idx += 2; return defaultValue; } @@ -30,8 +35,10 @@ namespace Slippi { return value; } - uint32_t readWord(uint8_t* a, int& idx, uint32_t maxSize, uint32_t defaultValue) { - if (idx >= (int)maxSize) { + uint32_t readWord(uint8_t* a, int& idx, uint32_t maxSize, uint32_t defaultValue) + { + if (idx >= (int)maxSize) + { idx += 4; return defaultValue; } @@ -41,21 +48,25 @@ namespace Slippi { return value; } - float readFloat(uint8_t* a, int& idx, uint32_t maxSize, float defaultValue) { + float readFloat(uint8_t* a, int& idx, uint32_t maxSize, float defaultValue) + { uint32_t bytes = readWord(a, idx, maxSize, *(uint32_t*)(&defaultValue)); return *(float*)(&bytes); } - void handleGameInit(Game* game, uint32_t maxSize) { + void handleGameInit(Game* game, uint32_t maxSize) + { int idx = 0; // Read version number - for (int i = 0; i < 4; i++) { + for (int i = 0; i < 4; i++) + { game->version[i] = readByte(data, idx, maxSize, 0); } // Read entire game info header - for (int i = 0; i < GAME_INFO_HEADER_SIZE; i++) { + for (int i = 0; i < GAME_INFO_HEADER_SIZE; i++) + { game->settings.header[i] = readWord(data, idx, maxSize, 0); } @@ -64,15 +75,18 @@ namespace Slippi { // Read UCF toggle bytes bool shouldRead = game->version[0] >= 1; - for (int i = 0; i < UCF_TOGGLE_SIZE; i++) { + for (int i = 0; i < UCF_TOGGLE_SIZE; i++) + { uint32_t value = shouldRead ? readWord(data, idx, maxSize, 0) : 0; game->settings.ucfToggles[i] = value; } // Read nametag for each player std::array, 4> playerNametags; - for (int i = 0; i < 4; i++) { - for (int j = 0; j < NAMETAG_SIZE; j++) { + for (int i = 0; i < 4; i++) + { + for (int j = 0; j < NAMETAG_SIZE; j++) + { playerNametags[i][j] = readHalf(data, idx, maxSize, 0); } } @@ -84,15 +98,18 @@ namespace Slippi { game->settings.isFrozenPS = readByte(data, idx, maxSize, 0); // Pull header data into struct - int player1Pos = 24; // This is the index of the first players character info + int player1Pos = 24; // This is the index of the first players character info std::array gameInfoHeader = game->settings.header; - for (int i = 0; i < 4; i++) { - // this is the position in the array that this player's character info is stored + for (int i = 0; i < 4; i++) + { + // this is the position in the array that this player's character info is + // stored int pos = player1Pos + (9 * i); uint32_t playerInfo = gameInfoHeader[pos]; uint8_t playerType = (playerInfo & 0x00FF0000) >> 16; - if (playerType == 0x3) { + if (playerType == 0x3) + { // Player type 3 is an empty slot continue; } @@ -106,7 +123,7 @@ namespace Slippi { p.characterColor = playerInfo & 0xFF; p.nametag = playerNametags[i]; - //Add player settings to result + // Add player settings to result game->settings.players[i] = p; } @@ -114,13 +131,15 @@ namespace Slippi { auto majorVersion = game->version[0]; auto minorVersion = game->version[1]; - if (majorVersion > 3 || (majorVersion == 3 && minorVersion >= 1)) { + if (majorVersion > 3 || (majorVersion == 3 && minorVersion >= 1)) + { // After version 3.1.0 we added a dynamic gecko loading process. These // are needed before starting the game. areSettingsLoaded will be set // to true when they are received game->areSettingsLoaded = false; } - else if (majorVersion > 1 || (majorVersion == 1 && minorVersion >= 6)) { + else if (majorVersion > 1 || (majorVersion == 1 && minorVersion >= 6)) + { // Indicate settings loaded immediately if after version 1.6.0 // Sheik game info was added in this version and so we no longer // need to wait @@ -128,7 +147,8 @@ namespace Slippi { } } - void handleGeckoList(Game* game, uint32_t maxSize) { + void handleGeckoList(Game* game, uint32_t maxSize) + { game->settings.geckoCodes.clear(); game->settings.geckoCodes.insert(game->settings.geckoCodes.end(), data, data + maxSize); @@ -136,10 +156,11 @@ namespace Slippi { game->areSettingsLoaded = true; } - void handleFrameStart(Game* game, uint32_t maxSize) { + void handleFrameStart(Game* game, uint32_t maxSize) + { int idx = 0; - //Check frame count + // Check frame count int32_t frameCount = readWord(data, idx, maxSize, 0); game->frameCount = frameCount; @@ -157,10 +178,11 @@ namespace Slippi { game->framesByIndex[frameCount] = frame; } - void handlePreFrameUpdate(Game* game, uint32_t maxSize) { + void handlePreFrameUpdate(Game* game, uint32_t maxSize) + { int idx = 0; - //Check frame count + // Check frame count int32_t frameCount = readWord(data, idx, maxSize, 0); game->frameCount = frameCount; @@ -168,7 +190,8 @@ namespace Slippi { FrameData* frame = frameUniquePtr.get(); bool isNewFrame = true; - if (game->framesByIndex.count(frameCount)) { + if (game->framesByIndex.count(frameCount)) + { // If this frame already exists, get the current frame frame = game->frames.back().get(); isNewFrame = false; @@ -181,16 +204,16 @@ namespace Slippi { uint8_t playerSlot = readByte(data, idx, maxSize, 0); uint8_t isFollower = readByte(data, idx, maxSize, 0); - //Load random seed for player frame update + // Load random seed for player frame update p.randomSeed = readWord(data, idx, maxSize, 0); - //Load player data + // Load player data p.animation = readHalf(data, idx, maxSize, 0); p.locationX = readFloat(data, idx, maxSize, 0); p.locationY = readFloat(data, idx, maxSize, 0); p.facingDirection = readFloat(data, idx, maxSize, 0); - //Controller information + // Controller information p.joystickX = readFloat(data, idx, maxSize, 0); p.joystickY = readFloat(data, idx, maxSize, 0); p.cstickX = readFloat(data, idx, maxSize, 0); @@ -198,12 +221,13 @@ namespace Slippi { p.trigger = readFloat(data, idx, maxSize, 0); p.buttons = readWord(data, idx, maxSize, 0); - //Raw controller information + // Raw controller information p.physicalButtons = readHalf(data, idx, maxSize, 0); p.lTrigger = readFloat(data, idx, maxSize, 0); p.rTrigger = readFloat(data, idx, maxSize, 0); - if (asmEvents[EVENT_PRE_FRAME_UPDATE] >= 59) { + if (asmEvents[EVENT_PRE_FRAME_UPDATE] >= 59) + { p.joystickXRaw = readByte(data, idx, maxSize, 0); } @@ -218,27 +242,31 @@ namespace Slippi { target->operator[](playerSlot) = p; // Add frame to game - if (isNewFrame) { + if (isNewFrame) + { frame->numSinceStart = game->frames.size(); game->frames.push_back(std::move(frameUniquePtr)); game->framesByIndex[frameCount] = frame; } } - void handlePostFrameUpdate(Game* game, uint32_t maxSize) { + void handlePostFrameUpdate(Game* game, uint32_t maxSize) + { int idx = 0; - //Check frame count + // Check frame count int32_t frameCount = readWord(data, idx, maxSize, 0); FrameData* frame; - if (game->framesByIndex.count(frameCount)) { + if (game->framesByIndex.count(frameCount)) + { // If this frame already exists, get the current frame frame = game->frames.back().get(); } - // As soon as a post frame update happens, we know we have received all the inputs - // This is used to determine if a frame is ready to be used for a replay (for mirroring) + // As soon as a post frame update happens, we know we have received all the + // inputs This is used to determine if a frame is ready to be used for a + // replay (for mirroring) frame->inputsFullyFetched = true; uint8_t playerSlot = readByte(data, idx, maxSize, 0); @@ -249,24 +277,24 @@ namespace Slippi { p->internalCharacterId = readByte(data, idx, maxSize, 0); // Check if a player started as sheik and update - if (frameCount == GAME_FIRST_FRAME && p->internalCharacterId == GAME_SHEIK_INTERNAL_ID) { + if (frameCount == GAME_FIRST_FRAME && p->internalCharacterId == GAME_SHEIK_INTERNAL_ID) + { game->settings.players[playerSlot].characterId = GAME_SHEIK_EXTERNAL_ID; } // Set settings loaded if this is the last character - if (frameCount == GAME_FIRST_FRAME) { + if (frameCount == GAME_FIRST_FRAME) + { uint8_t lastPlayerIndex = 0; - for (auto it = frame->players.begin(); it != frame->players.end(); ++it) { - if (it->first <= lastPlayerIndex) { + for (auto it = frame->players.begin(); it != frame->players.end(); ++it) + { + if (it->first <= lastPlayerIndex) + { continue; } lastPlayerIndex = it->first; } - - if (playerSlot >= lastPlayerIndex) { - game->areSettingsLoaded = true; - } } } @@ -279,34 +307,41 @@ namespace Slippi { game->lastFinalizedFrame = lastFinalizedFrame; } - void handleGameEnd(Game* game, uint32_t maxSize) { + void handleGameEnd(Game* game, uint32_t maxSize) + { int idx = 0; game->winCondition = readByte(data, idx, maxSize, 0); } // This function gets the position where the raw data starts - int getRawDataPosition(std::ifstream* f) { + int getRawDataPosition(std::ifstream* f) + { char buffer[2]; f->seekg(0, std::ios::beg); f->read(buffer, 2); - if (buffer[0] == 0x36) { + if (buffer[0] == 0x36) + { return 0; } - if (buffer[0] != '{') { + if (buffer[0] != '{') + { // TODO: Do something here to cause an error return 0; } // TODO: Read ubjson file to find the "raw" element and return the start of it - // TODO: For now since raw is the first element the data will always start at 15 + // TODO: For now since raw is the first element the data will always start at + // 15 return 15; } - uint32_t getRawDataLength(std::ifstream* f, int position, int fileSize) { - if (position == 0) { + uint32_t getRawDataLength(std::ifstream* f, int position, int fileSize) + { + if (position == 0) + { return fileSize; } @@ -319,23 +354,23 @@ namespace Slippi { return length; } - std::unordered_map getMessageSizes(std::ifstream* f, int position) { + std::unordered_map getMessageSizes(std::ifstream* f, int position) + { char buffer[2]; f->seekg(position, std::ios::beg); f->read(buffer, 2); - if (buffer[0] != EVENT_PAYLOAD_SIZES) { + if (buffer[0] != EVENT_PAYLOAD_SIZES) + { return {}; } int payloadLength = buffer[1]; - std::unordered_map messageSizes = { - { EVENT_PAYLOAD_SIZES, payloadLength } - }; - + std::unordered_map messageSizes = { {EVENT_PAYLOAD_SIZES, payloadLength} }; std::vector messageSizesBuffer(payloadLength - 1); f->read(&messageSizesBuffer[0], payloadLength - 1); - for (int i = 0; i < payloadLength - 1; i += 3) { + for (int i = 0; i < payloadLength - 1; i += 3) + { uint8_t command = messageSizesBuffer[i]; // Extract the bytes in u8s. Without this the chars don't or together well @@ -349,8 +384,10 @@ namespace Slippi { return messageSizes; } - void SlippiGame::processData() { - if (isProcessingComplete) { + void SlippiGame::processData() + { + if (isProcessingComplete) + { // If we have finished processing this file, return return; } @@ -358,17 +395,20 @@ namespace Slippi { // This function will process as much data as possible int startPos = (int)file->tellg(); file->seekg(startPos); - if (startPos == 0) { + if (startPos == 0) + { file->seekg(0, std::ios::end); int len = (int)file->tellg(); - if (len < 2) { + if (len < 2) + { // If we can't read message sizes payload size yet, return return; } int rawDataPos = getRawDataPosition(file.get()); int rawDataLen = len - rawDataPos; - if (rawDataLen < 2) { + if (rawDataLen < 2) + { // If we don't have enough raw data yet to read the replay file, return // Reset to begining so that the startPos condition will be hit again file->seekg(0); @@ -382,7 +422,8 @@ namespace Slippi { file->read(buffer, 2); file->seekg(startPos); auto messageSizesSize = (int)buffer[1]; - if (rawDataLen < messageSizesSize) { + if (rawDataLen < messageSizesSize) + { // If we haven't received the full payload sizes message, return // Reset to begining so that the startPos condition will be hit again file->seekg(0); @@ -397,10 +438,11 @@ namespace Slippi { int endPos = (int)file->tellg(); int sizeToRead = endPos - startPos; file->seekg(startPos); - //log << "Size to read: " << sizeToRead << "\n"; - //log << "Start Pos: " << startPos << "\n"; - //log << "End Pos: " << endPos << "\n\n"; - if (sizeToRead <= 0) { + // log << "Size to read: " << sizeToRead << "\n"; + // log << "Start Pos: " << startPos << "\n"; + // log << "End Pos: " << endPos << "\n\n"; + if (sizeToRead <= 0) + { return; } @@ -408,16 +450,18 @@ namespace Slippi { file->read(&newData[0], sizeToRead); int newDataPos = 0; - while (newDataPos < sizeToRead) { + while (newDataPos < sizeToRead) + { auto command = newData[newDataPos]; auto payloadSize = asmEvents[command]; - //char buff[100]; - //snprintf(buff, sizeof(buff), "%x", command); - //log << "Command: " << buff << " | Payload Size: " << payloadSize << "\n"; + // char buff[100]; + // snprintf(buff, sizeof(buff), "%x", command); + // log << "Command: " << buff << " | Payload Size: " << payloadSize << "\n"; auto remainingLen = sizeToRead - newDataPos; - if (remainingLen < ((int)payloadSize + 1)) { + if (remainingLen < ((int)payloadSize + 1)) + { // Here we don't have enough data to read the whole payload // Will be processed after getting more data (hopefully) file->seekg(-remainingLen, std::ios::cur); @@ -430,7 +474,8 @@ namespace Slippi { uint32_t outerPayloadSize = payloadSize; // Handle a split message, combining in until we possess the entire message - if (command == EVENT_SPLIT_MESSAGE) { + if (command == EVENT_SPLIT_MESSAGE) + { if (shouldResetSplitMessageBuf) { splitMessageBuf.clear(); @@ -452,7 +497,8 @@ namespace Slippi { } } - switch (command) { + switch (command) + { case EVENT_GAME_INIT: handleGameInit(game.get(), payloadSize); break; @@ -468,9 +514,6 @@ namespace Slippi { case EVENT_POST_FRAME_UPDATE: handlePostFrameUpdate(game.get(), payloadSize); break; - case EVENT_FRAME_END: - handleFrameEnd(game.get(), payloadSize); - break; case EVENT_GAME_END: handleGameEnd(game.get(), payloadSize); isProcessingComplete = true; @@ -480,7 +523,7 @@ namespace Slippi { // from processing the metadata as raw data. 0x55 is 'U' // which is the first character after the raw data in the // ubjson file format - //log.close(); + // log.close(); isProcessingComplete = true; file->seekg(-remainingLen, std::ios::cur); return; @@ -491,7 +534,8 @@ namespace Slippi { } } - std::unique_ptr SlippiGame::FromFile(std::string path) { + std::unique_ptr SlippiGame::FromFile(std::string path) + { auto result = std::make_unique(); result->game = std::make_unique(); result->path = path; @@ -504,35 +548,39 @@ namespace Slippi { result->file = std::make_unique(path, std::ios::in | std::ios::binary); #endif - //result->log.open("log.txt"); - if (!result->file->is_open()) { + // result->log.open("log.txt"); + if (!result->file->is_open()) + { return nullptr; } - //int fileLength = (int)file.tellg(); - //int rawDataPos = getRawDataPosition(&file); - //uint32_t rawDataLength = getRawDataLength(&file, rawDataPos, fileLength); - //asmEvents = getMessageSizes(&file, rawDataPos); + // int fileLength = (int)file.tellg(); + // int rawDataPos = getRawDataPosition(&file); + // uint32_t rawDataLength = getRawDataLength(&file, rawDataPos, fileLength); + // asmEvents = getMessageSizes(&file, rawDataPos); - //std::vector rawData(rawDataLength); - //file.seekg(rawDataPos, std::ios::beg); - //file.read(&rawData[0], rawDataLength); + // std::vector rawData(rawDataLength); + // file.seekg(rawDataPos, std::ios::beg); + // file.read(&rawData[0], rawDataLength); - //SlippiGame* result = processFile((uint8_t*)&rawData[0], rawDataLength); + // SlippiGame* result = processFile((uint8_t*)&rawData[0], rawDataLength); return std::move(result); } - bool SlippiGame::IsProcessingComplete() { + bool SlippiGame::IsProcessingComplete() + { return isProcessingComplete; } - bool SlippiGame::AreSettingsLoaded() { + bool SlippiGame::AreSettingsLoaded() + { processData(); return game->areSettingsLoaded; } - bool SlippiGame::DoesFrameExist(int32_t frame) { + bool SlippiGame::DoesFrameExist(int32_t frame) + { processData(); return (bool)game->framesByIndex.count(frame); } @@ -555,11 +603,12 @@ namespace Slippi { return game->framesByIndex.at(frame); } - FrameData* SlippiGame::GetFrameAt(uint32_t pos) { - if (pos >= game->frames.size()) { + FrameData* SlippiGame::GetFrameAt(uint32_t pos) + { + if (pos >= game->frames.size()) + { return nullptr; } - // Get the frame we want return game->frames[pos].get(); } @@ -574,7 +623,8 @@ namespace Slippi { return game->frameCount; } - GameSettings* SlippiGame::GetSettings() { + GameSettings* SlippiGame::GetSettings() + { processData(); return &game->settings; } @@ -586,4 +636,4 @@ namespace Slippi { uint8_t SlippiGame::GetGameEndMethod() { return game->winCondition; } -} +} // namespace Slippi diff --git a/Externals/SlippiLib/SlippiGame.h b/Externals/SlippiLib/SlippiGame.h index 1e05ea565b..03afd296be 100644 --- a/Externals/SlippiLib/SlippiGame.h +++ b/Externals/SlippiLib/SlippiGame.h @@ -1,12 +1,12 @@ #pragma once -#include #include -#include -#include -#include #include +#include #include +#include +#include +#include namespace Slippi { const uint8_t EVENT_SPLIT_MESSAGE = 0x10; diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceSlippi.cpp b/Source/Core/Core/HW/EXI/EXI_DeviceSlippi.cpp index 4bb56c0677..862ecb8114 100644 --- a/Source/Core/Core/HW/EXI/EXI_DeviceSlippi.cpp +++ b/Source/Core/Core/HW/EXI/EXI_DeviceSlippi.cpp @@ -2,10 +2,9 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. - -#include -#include // std::move #include +#include +#include // std::move #include "Common/CommonPaths.h" #include "Common/CommonTypes.h" @@ -17,17 +16,17 @@ #include "Common/Thread.h" #include "Common/Version.h" -#include "Core/Core.h" #include "Core/ConfigManager.h" +#include "Core/Core.h" #include "Core/CoreTiming.h" #include "Core/Debugger/Debugger_SymbolMap.h" -#include "Core/Host.h" #include "Core/HW/EXI/EXI_DeviceSlippi.h" #include "Core/HW/Memmap.h" #include "Core/HW/SystemTimers.h" +#include "Core/Host.h" #include "Core/NetPlayClient.h" -#include "Core/Slippi/SlippiReplayComm.h" #include "Core/Slippi/SlippiPlayback.h" +#include "Core/Slippi/SlippiReplayComm.h" #include "Core/State.h" #define FRAME_INTERVAL 900 @@ -44,12 +43,13 @@ extern bool g_needInputForFrame; bool isLocalConnected = false; #endif -namespace ExpansionInterface { - +namespace ExpansionInterface +{ static std::unordered_map slippi_names; static std::unordered_map slippi_connect_codes; -template bool isFutureReady(std::future& t) +template +bool isFutureReady(std::future& t) { return t.wait_for(std::chrono::seconds(0)) == std::future_status::ready; } @@ -59,7 +59,7 @@ std::vector uint16ToVector(u16 num) u8 byte0 = num >> 8; u8 byte1 = num & 0xFF; - return std::vector({ byte0, byte1 }); + return std::vector({byte0, byte1}); } std::vector uint32ToVector(u32 num) @@ -69,7 +69,7 @@ std::vector uint32ToVector(u32 num) u8 byte2 = (num & 0xFF00) >> 8; u8 byte3 = num & 0xFF; - return std::vector({ byte0, byte1, byte2, byte3 }); + return std::vector({byte0, byte1, byte2, byte3}); } std::vector int32ToVector(int32_t num) @@ -79,7 +79,7 @@ std::vector int32ToVector(int32_t num) u8 byte2 = (num & 0xFF00) >> 8; u8 byte3 = num & 0xFF; - return std::vector({ byte0, byte1, byte2, byte3 }); + return std::vector({byte0, byte1, byte2, byte3}); } void appendWordToBuffer(std::vector* buf, u32 word) @@ -97,6 +97,7 @@ void appendHalfToBuffer(std::vector* buf, u16 word) CEXISlippi::CEXISlippi() { INFO_LOG(SLIPPI, "EXI SLIPPI Constructor called."); + user = std::make_unique(); g_playbackStatus = std::make_unique(); matchmaking = std::make_unique(user.get()); @@ -120,60 +121,76 @@ CEXISlippi::CEXISlippi() // MnMaAll.usd std::string origStr; std::string modifiedStr; - File::ReadFileToString("C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\MainMenu\\MnMaAll.usd", origStr); - File::ReadFileToString("C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\MainMenu\\MnMaAll-new.usd", - modifiedStr); + File::ReadFileToString( + "C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\MainMenu\\MnMaAll.usd", origStr); + File::ReadFileToString( + "C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\MainMenu\\MnMaAll-new.usd", modifiedStr); std::vector orig(origStr.begin(), origStr.end()); std::vector modified(modifiedStr.begin(), modifiedStr.end()); auto diff = processDiff(orig, modified); - File::WriteStringToFile(diff, "C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\MainMenu\\MnMaAll.usd.diff"); + File::WriteStringToFile( + diff, "C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\MainMenu\\MnMaAll.usd.diff"); File::WriteStringToFile(diff, "C:\\Dolphin\\IshiiDev\\Sys\\GameFiles\\GALE01\\MnMaAll.usd.diff"); // MnExtAll.usd - File::ReadFileToString("C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\CSS\\MnExtAll.usd", origStr); - File::ReadFileToString("C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\CSS\\MnExtAll-new.usd", modifiedStr); + File::ReadFileToString("C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\CSS\\MnExtAll.usd", + origStr); + File::ReadFileToString( + "C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\CSS\\MnExtAll-new.usd", modifiedStr); orig = std::vector(origStr.begin(), origStr.end()); modified = std::vector(modifiedStr.begin(), modifiedStr.end()); diff = processDiff(orig, modified); - File::WriteStringToFile(diff, "C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\CSS\\MnExtAll.usd.diff"); + File::WriteStringToFile( + diff, "C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\CSS\\MnExtAll.usd.diff"); File::WriteStringToFile(diff, "C:\\Dolphin\\IshiiDev\\Sys\\GameFiles\\GALE01\\MnExtAll.usd.diff"); // SdMenu.usd - File::ReadFileToString("C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\MainMenu\\SdMenu.usd", origStr); - File::ReadFileToString("C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\MainMenu\\SdMenu-new.usd", modifiedStr); + File::ReadFileToString("C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\MainMenu\\SdMenu.usd", + origStr); + File::ReadFileToString( + "C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\MainMenu\\SdMenu-new.usd", modifiedStr); orig = std::vector(origStr.begin(), origStr.end()); modified = std::vector(modifiedStr.begin(), modifiedStr.end()); diff = processDiff(orig, modified); - File::WriteStringToFile(diff, "C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\MainMenu\\SdMenu.usd.diff"); + File::WriteStringToFile( + diff, "C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\MainMenu\\SdMenu.usd.diff"); File::WriteStringToFile(diff, "C:\\Dolphin\\IshiiDev\\Sys\\GameFiles\\GALE01\\SdMenu.usd.diff"); // Japanese Files // MnMaAll.dat - File::ReadFileToString("C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\MainMenu\\MnMaAll.dat", origStr); - File::ReadFileToString("C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\MainMenu\\MnMaAll-new.dat", - modifiedStr); + File::ReadFileToString( + "C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\MainMenu\\MnMaAll.dat", origStr); + File::ReadFileToString( + "C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\MainMenu\\MnMaAll-new.dat", modifiedStr); orig = std::vector(origStr.begin(), origStr.end()); modified = std::vector(modifiedStr.begin(), modifiedStr.end()); diff = processDiff(orig, modified); - File::WriteStringToFile(diff, "C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\MainMenu\\MnMaAll.dat.diff"); + File::WriteStringToFile( + diff, "C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\MainMenu\\MnMaAll.dat.diff"); File::WriteStringToFile(diff, "C:\\Dolphin\\IshiiDev\\Sys\\GameFiles\\GALE01\\MnMaAll.dat.diff"); // MnExtAll.dat - File::ReadFileToString("C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\CSS\\MnExtAll.dat", origStr); - File::ReadFileToString("C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\CSS\\MnExtAll-new.dat", modifiedStr); + File::ReadFileToString("C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\CSS\\MnExtAll.dat", + origStr); + File::ReadFileToString( + "C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\CSS\\MnExtAll-new.dat", modifiedStr); orig = std::vector(origStr.begin(), origStr.end()); modified = std::vector(modifiedStr.begin(), modifiedStr.end()); diff = processDiff(orig, modified); - File::WriteStringToFile(diff, "C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\CSS\\MnExtAll.dat.diff"); + File::WriteStringToFile( + diff, "C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\CSS\\MnExtAll.dat.diff"); File::WriteStringToFile(diff, "C:\\Dolphin\\IshiiDev\\Sys\\GameFiles\\GALE01\\MnExtAll.dat.diff"); // SdMenu.dat - File::ReadFileToString("C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\MainMenu\\SdMenu.dat", origStr); - File::ReadFileToString("C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\MainMenu\\SdMenu-new.dat", modifiedStr); + File::ReadFileToString("C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\MainMenu\\SdMenu.dat", + origStr); + File::ReadFileToString( + "C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\MainMenu\\SdMenu-new.dat", modifiedStr); orig = std::vector(origStr.begin(), origStr.end()); modified = std::vector(modifiedStr.begin(), modifiedStr.end()); diff = processDiff(orig, modified); - File::WriteStringToFile(diff, "C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\MainMenu\\SdMenu.dat.diff"); + File::WriteStringToFile( + diff, "C:\\Users\\Jas\\Documents\\Melee\\Textures\\Slippi\\MainMenu\\SdMenu.dat.diff"); File::WriteStringToFile(diff, "C:\\Dolphin\\IshiiDev\\Sys\\GameFiles\\GALE01\\SdMenu.dat.diff"); // TEMP - Restore orig @@ -260,7 +277,7 @@ std::unordered_map CEXISlippi::getNetplayNames() std::vector CEXISlippi::generateMetadata() { - std::vector metadata({ 'U', 8, 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '{' }); + std::vector metadata({'U', 8, 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '{'}); // TODO: Abstract out UBJSON functions to make this cleaner @@ -268,17 +285,18 @@ std::vector CEXISlippi::generateMetadata() u8 dateTimeStrLength = sizeof "2011-10-08T07:07:09Z"; std::vector dateTimeBuf(dateTimeStrLength); strftime(&dateTimeBuf[0], dateTimeStrLength, "%FT%TZ", gmtime(&gameStartTime)); - dateTimeBuf.pop_back(); // Removes the \0 from the back of string - metadata.insert(metadata.end(), { 'U', 7, 's', 't', 'a', 'r', 't', 'A', 't', 'S', 'U', (u8)dateTimeBuf.size() }); + dateTimeBuf.pop_back(); // Removes the \0 from the back of string + metadata.insert(metadata.end(), + {'U', 7, 's', 't', 'a', 'r', 't', 'A', 't', 'S', 'U', (u8)dateTimeBuf.size()}); metadata.insert(metadata.end(), dateTimeBuf.begin(), dateTimeBuf.end()); // Add game duration std::vector lastFrameToWrite = int32ToVector(lastFrame); - metadata.insert(metadata.end(), { 'U', 9, 'l', 'a', 's', 't', 'F', 'r', 'a', 'm', 'e', 'l' }); + metadata.insert(metadata.end(), {'U', 9, 'l', 'a', 's', 't', 'F', 'r', 'a', 'm', 'e', 'l'}); metadata.insert(metadata.end(), lastFrameToWrite.begin(), lastFrameToWrite.end()); // Add players elements to metadata, one per player index - metadata.insert(metadata.end(), { 'U', 7, 'p', 'l', 'a', 'y', 'e', 'r', 's', '{' }); + metadata.insert(metadata.end(), {'U', 7, 'p', 'l', 'a', 'y', 'e', 'r', 's', '{'}); auto playerNames = getNetplayNames(); @@ -294,13 +312,13 @@ std::vector CEXISlippi::generateMetadata() metadata.push_back('{'); // Add names element for this player - metadata.insert(metadata.end(), { 'U', 5, 'n', 'a', 'm', 'e', 's', '{' }); + metadata.insert(metadata.end(), {'U', 5, 'n', 'a', 'm', 'e', 's', '{'}); if (playerNames.count(playerIndex)) { auto playerName = playerNames[playerIndex]; // Add netplay element for this player name - metadata.insert(metadata.end(), { 'U', 7, 'n', 'e', 't', 'p', 'l', 'a', 'y', 'S', 'U' }); + metadata.insert(metadata.end(), {'U', 7, 'n', 'e', 't', 'p', 'l', 'a', 'y', 'S', 'U'}); metadata.push_back((u8)playerName.length()); metadata.insert(metadata.end(), playerName.begin(), playerName.end()); } @@ -309,15 +327,16 @@ std::vector CEXISlippi::generateMetadata() { auto connectCode = slippi_connect_codes[playerIndex]; // Add connection code element for this player name - metadata.insert(metadata.end(), { 'U', 4, 'c', 'o', 'd', 'e', 'S', 'U' }); + metadata.insert(metadata.end(), {'U', 4, 'c', 'o', 'd', 'e', 'S', 'U'}); metadata.push_back((u8)connectCode.length()); metadata.insert(metadata.end(), connectCode.begin(), connectCode.end()); } - metadata.push_back('}'); // close names + metadata.push_back('}'); // close names // Add character element for this player - metadata.insert(metadata.end(), { 'U', 10, 'c', 'h', 'a', 'r', 'a', 'c', 't', 'e', 'r', 's', '{' }); + metadata.insert(metadata.end(), + {'U', 10, 'c', 'h', 'a', 'r', 'a', 'c', 't', 'e', 'r', 's', '{'}); for (auto it2 = playerCharacterUsage.begin(); it2 != playerCharacterUsage.end(); ++it2) { metadata.push_back('U'); @@ -329,15 +348,15 @@ std::vector CEXISlippi::generateMetadata() std::vector frameCount = uint32ToVector(it2->second); metadata.insert(metadata.end(), frameCount.begin(), frameCount.end()); } - metadata.push_back('}'); // close characters + metadata.push_back('}'); // close characters - metadata.push_back('}'); // close player + metadata.push_back('}'); // close player } metadata.push_back('}'); // Indicate this was played on dolphin - metadata.insert(metadata.end(), - { 'U', 8, 'p', 'l', 'a', 'y', 'e', 'd', 'O', 'n', 'S', 'U', 7, 'd', 'o', 'l', 'p', 'h', 'i', 'n' }); + metadata.insert(metadata.end(), {'U', 8, 'p', 'l', 'a', 'y', 'e', 'd', 'O', 'n', + 'S', 'U', 7, 'd', 'o', 'l', 'p', 'h', 'i', 'n'}); metadata.push_back('}'); return metadata; @@ -410,7 +429,7 @@ void CEXISlippi::writeToFile(std::unique_ptr msg) // Start ubjson file and prepare the "raw" element that game // data output will be dumped into. The size of the raw output will // be initialized to 0 until all of the data has been received - std::vector headerBytes({ '{', 'U', 3, 'r', 'a', 'w', '[', '$', 'U', '#', 'l', 0, 0, 0, 0 }); + std::vector headerBytes({'{', 'U', 3, 'r', 'a', 'w', '[', '$', 'U', '#', 'l', 0, 0, 0, 0}); dataToWrite.insert(dataToWrite.end(), headerBytes.begin(), headerBytes.end()); // Used to keep track of how many bytes have been written to the file @@ -425,17 +444,17 @@ void CEXISlippi::writeToFile(std::unique_ptr msg) // Get display names and connection codes from slippi netplay client if (slippi_netplay) { - auto userInfo = user->GetUserInfo(); - auto oppInfo = matchmaking->GetOpponent(); + auto userInfo = user->GetUserInfo(); + auto oppInfo = matchmaking->GetOpponent(); - auto isDecider = slippi_netplay->IsDecider(); - int local_port = isDecider ? 0 : 1; - int remote_port = isDecider ? 1 : 0; + auto isDecider = slippi_netplay->IsDecider(); + int local_port = isDecider ? 0 : 1; + int remote_port = isDecider ? 1 : 0; - slippi_names[local_port] = userInfo.displayName; - slippi_connect_codes[local_port] = userInfo.connectCode; - slippi_names[remote_port] = oppInfo.displayName; - slippi_connect_codes[remote_port] = oppInfo.connectCode; + slippi_names[local_port] = userInfo.display_name; + slippi_connect_codes[local_port] = userInfo.connect_code; + slippi_names[remote_port] = oppInfo.display_name; + slippi_connect_codes[remote_port] = oppInfo.connect_code; } } @@ -541,11 +560,11 @@ void CEXISlippi::createNewFile() if (!m_file) { PanicAlertT("Could not create .slp replay file [%s].\n\n" - "The replay folder's path might be invalid, or you might " - "not have permission to write to it.\n\n" - "You can change the replay folder in Config > Slippi > " - "Slippi Replay Settings.", - filepath.c_str()); + "The replay folder's path might be invalid, or you might " + "not have permission to write to it.\n\n" + "You can change the replay folder in Config > Slippi > " + "Slippi Replay Settings.", + filepath.c_str()); } } @@ -595,13 +614,14 @@ void CEXISlippi::prepareGameInfo(u8* payload) // Prepare playback savestate payload playbackSavestatePayload.clear(); - appendWordToBuffer(&playbackSavestatePayload, 0); // This space will be used to set frame index + appendWordToBuffer(&playbackSavestatePayload, 0); // This space will be used to set frame index int bkpPos = 0; while ((*(u32*)(&payload[bkpPos * 8])) != 0) { bkpPos += 1; } - playbackSavestatePayload.insert(playbackSavestatePayload.end(), payload, payload + (bkpPos * 8 + 4)); + playbackSavestatePayload.insert(playbackSavestatePayload.end(), payload, + payload + (bkpPos * 8 + 4)); Slippi::GameSettings* settings = m_current_game->GetSettings(); @@ -622,7 +642,7 @@ void CEXISlippi::prepareGameInfo(u8* payload) // This is kinda dumb but we need to handle the case where a player transforms // into sheik/zelda immediately. This info is not stored in the game info header // and so let's overwrite those values - int player1Pos = 24; // This is the index of the first players character info + int player1Pos = 24; // This is the index of the first players character info std::array gameInfoHeader = settings->header; for (int i = 0; i < 4; i++) { @@ -725,7 +745,7 @@ void CEXISlippi::prepareGameInfo(u8* payload) // Initialize replay related threads if not viewing rollback versions of relays if (replayCommSettings.rollbackDisplayMethod == "off" && - (replayCommSettings.mode == "normal" || replayCommSettings.mode == "queue")) + (replayCommSettings.mode == "normal" || replayCommSettings.mode == "queue")) { g_playbackStatus->startThreads(); } @@ -736,289 +756,318 @@ void CEXISlippi::prepareGeckoList() // TODO: How do I move this somewhere else? // This contains all of the codes required to play legacy replays (UCF, PAL, Frz Stadium) static std::vector defaultCodeList = { - 0xC2, 0x0C, 0x9A, 0x44, 0x00, 0x00, 0x00, 0x2F, // #External/UCF + Arduino Toggle UI/UCF/UCF 0.74 - // Dashback - Check for Toggle.asm - 0xD0, 0x1F, 0x00, 0x2C, 0x88, 0x9F, 0x06, 0x18, 0x38, 0x62, 0xF2, 0x28, 0x7C, 0x63, 0x20, 0xAE, 0x2C, 0x03, - 0x00, 0x01, 0x41, 0x82, 0x00, 0x14, 0x38, 0x62, 0xF2, 0x2C, 0x7C, 0x63, 0x20, 0xAE, 0x2C, 0x03, 0x00, 0x01, - 0x40, 0x82, 0x01, 0x50, 0x7C, 0x08, 0x02, 0xA6, 0x90, 0x01, 0x00, 0x04, 0x94, 0x21, 0xFF, 0x50, 0xBE, 0x81, - 0x00, 0x08, 0x48, 0x00, 0x01, 0x21, 0x7F, 0xC8, 0x02, 0xA6, 0xC0, 0x3F, 0x08, 0x94, 0xC0, 0x5E, 0x00, 0x00, - 0xFC, 0x01, 0x10, 0x40, 0x40, 0x82, 0x01, 0x18, 0x80, 0x8D, 0xAE, 0xB4, 0xC0, 0x3F, 0x06, 0x20, 0xFC, 0x20, - 0x0A, 0x10, 0xC0, 0x44, 0x00, 0x3C, 0xFC, 0x01, 0x10, 0x40, 0x41, 0x80, 0x01, 0x00, 0x88, 0x7F, 0x06, 0x70, - 0x2C, 0x03, 0x00, 0x02, 0x40, 0x80, 0x00, 0xF4, 0x88, 0x7F, 0x22, 0x1F, 0x54, 0x60, 0x07, 0x39, 0x40, 0x82, - 0x00, 0xE8, 0x3C, 0x60, 0x80, 0x4C, 0x60, 0x63, 0x1F, 0x78, 0x8B, 0xA3, 0x00, 0x01, 0x38, 0x7D, 0xFF, 0xFE, - 0x88, 0x9F, 0x06, 0x18, 0x48, 0x00, 0x00, 0x8D, 0x7C, 0x7C, 0x1B, 0x78, 0x7F, 0xA3, 0xEB, 0x78, 0x88, 0x9F, - 0x06, 0x18, 0x48, 0x00, 0x00, 0x7D, 0x7C, 0x7C, 0x18, 0x50, 0x7C, 0x63, 0x19, 0xD6, 0x2C, 0x03, 0x15, 0xF9, - 0x40, 0x81, 0x00, 0xB0, 0x38, 0x00, 0x00, 0x01, 0x90, 0x1F, 0x23, 0x58, 0x90, 0x1F, 0x23, 0x40, 0x80, 0x9F, - 0x00, 0x04, 0x2C, 0x04, 0x00, 0x0A, 0x40, 0xA2, 0x00, 0x98, 0x88, 0x7F, 0x00, 0x0C, 0x38, 0x80, 0x00, 0x01, - 0x3D, 0x80, 0x80, 0x03, 0x61, 0x8C, 0x41, 0x8C, 0x7D, 0x89, 0x03, 0xA6, 0x4E, 0x80, 0x04, 0x21, 0x2C, 0x03, - 0x00, 0x00, 0x41, 0x82, 0x00, 0x78, 0x80, 0x83, 0x00, 0x2C, 0x80, 0x84, 0x1E, 0xCC, 0xC0, 0x3F, 0x00, 0x2C, - 0xD0, 0x24, 0x00, 0x18, 0xC0, 0x5E, 0x00, 0x04, 0xFC, 0x01, 0x10, 0x40, 0x41, 0x81, 0x00, 0x0C, 0x38, 0x60, - 0x00, 0x80, 0x48, 0x00, 0x00, 0x08, 0x38, 0x60, 0x00, 0x7F, 0x98, 0x64, 0x00, 0x06, 0x48, 0x00, 0x00, 0x48, - 0x7C, 0x85, 0x23, 0x78, 0x38, 0x63, 0xFF, 0xFF, 0x2C, 0x03, 0x00, 0x00, 0x40, 0x80, 0x00, 0x08, 0x38, 0x63, - 0x00, 0x05, 0x3C, 0x80, 0x80, 0x46, 0x60, 0x84, 0xB1, 0x08, 0x1C, 0x63, 0x00, 0x30, 0x7C, 0x84, 0x1A, 0x14, - 0x1C, 0x65, 0x00, 0x0C, 0x7C, 0x84, 0x1A, 0x14, 0x88, 0x64, 0x00, 0x02, 0x7C, 0x63, 0x07, 0x74, 0x4E, 0x80, - 0x00, 0x20, 0x4E, 0x80, 0x00, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBA, 0x81, 0x00, 0x08, - 0x80, 0x01, 0x00, 0xB4, 0x38, 0x21, 0x00, 0xB0, 0x7C, 0x08, 0x03, 0xA6, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x09, - 0x98, 0xA4, 0x00, 0x00, 0x00, 0x2B, // #External/UCF + Arduino Toggle UI/UCF/UCF - // 0.74 Shield Drop - Check for Toggle.asm - 0x7C, 0x08, 0x02, 0xA6, 0x90, 0x01, 0x00, 0x04, 0x94, 0x21, 0xFF, 0x50, 0xBE, 0x81, 0x00, 0x08, 0x7C, 0x7E, - 0x1B, 0x78, 0x83, 0xFE, 0x00, 0x2C, 0x48, 0x00, 0x01, 0x01, 0x7F, 0xA8, 0x02, 0xA6, 0x88, 0x9F, 0x06, 0x18, - 0x38, 0x62, 0xF2, 0x28, 0x7C, 0x63, 0x20, 0xAE, 0x2C, 0x03, 0x00, 0x01, 0x41, 0x82, 0x00, 0x14, 0x38, 0x62, - 0xF2, 0x30, 0x7C, 0x63, 0x20, 0xAE, 0x2C, 0x03, 0x00, 0x01, 0x40, 0x82, 0x00, 0xF8, 0xC0, 0x3F, 0x06, 0x3C, - 0x80, 0x6D, 0xAE, 0xB4, 0xC0, 0x03, 0x03, 0x14, 0xFC, 0x01, 0x00, 0x40, 0x40, 0x81, 0x00, 0xE4, 0xC0, 0x3F, - 0x06, 0x20, 0x48, 0x00, 0x00, 0x71, 0xD0, 0x21, 0x00, 0x90, 0xC0, 0x3F, 0x06, 0x24, 0x48, 0x00, 0x00, 0x65, - 0xC0, 0x41, 0x00, 0x90, 0xEC, 0x42, 0x00, 0xB2, 0xEC, 0x21, 0x00, 0x72, 0xEC, 0x21, 0x10, 0x2A, 0xC0, 0x5D, - 0x00, 0x0C, 0xFC, 0x01, 0x10, 0x40, 0x41, 0x80, 0x00, 0xB4, 0x88, 0x9F, 0x06, 0x70, 0x2C, 0x04, 0x00, 0x03, - 0x40, 0x81, 0x00, 0xA8, 0xC0, 0x1D, 0x00, 0x10, 0xC0, 0x3F, 0x06, 0x24, 0xFC, 0x00, 0x08, 0x40, 0x40, 0x80, - 0x00, 0x98, 0xBA, 0x81, 0x00, 0x08, 0x80, 0x01, 0x00, 0xB4, 0x38, 0x21, 0x00, 0xB0, 0x7C, 0x08, 0x03, 0xA6, - 0x80, 0x61, 0x00, 0x1C, 0x83, 0xE1, 0x00, 0x14, 0x38, 0x21, 0x00, 0x18, 0x38, 0x63, 0x00, 0x08, 0x7C, 0x68, - 0x03, 0xA6, 0x4E, 0x80, 0x00, 0x20, 0xFC, 0x00, 0x0A, 0x10, 0xC0, 0x3D, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x72, - 0xC0, 0x3D, 0x00, 0x04, 0xEC, 0x00, 0x08, 0x28, 0xFC, 0x00, 0x00, 0x1E, 0xD8, 0x01, 0x00, 0x80, 0x80, 0x61, - 0x00, 0x84, 0x38, 0x63, 0x00, 0x02, 0x3C, 0x00, 0x43, 0x30, 0xC8, 0x5D, 0x00, 0x14, 0x6C, 0x63, 0x80, 0x00, - 0x90, 0x01, 0x00, 0x80, 0x90, 0x61, 0x00, 0x84, 0xC8, 0x21, 0x00, 0x80, 0xEC, 0x01, 0x10, 0x28, 0xC0, 0x3D, - 0x00, 0x00, 0xEC, 0x20, 0x08, 0x24, 0x4E, 0x80, 0x00, 0x20, 0x4E, 0x80, 0x00, 0x21, 0x42, 0xA0, 0x00, 0x00, - 0x37, 0x27, 0x00, 0x00, 0x43, 0x30, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0xBF, 0x4C, 0xCC, 0xCD, 0x43, 0x30, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x7F, 0xC3, 0xF3, 0x78, 0x7F, 0xE4, 0xFB, 0x78, 0xBA, 0x81, 0x00, 0x08, - 0x80, 0x01, 0x00, 0xB4, 0x38, 0x21, 0x00, 0xB0, 0x7C, 0x08, 0x03, 0xA6, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xC2, 0x16, 0xE7, 0x50, 0x00, 0x00, 0x00, - 0x33, // #Common/StaticPatches/ToggledStaticOverwrites.asm - 0x88, 0x62, 0xF2, 0x34, 0x2C, 0x03, 0x00, 0x00, 0x41, 0x82, 0x00, 0x14, 0x48, 0x00, 0x00, 0x75, 0x7C, 0x68, - 0x02, 0xA6, 0x48, 0x00, 0x01, 0x3D, 0x48, 0x00, 0x00, 0x14, 0x48, 0x00, 0x00, 0x95, 0x7C, 0x68, 0x02, 0xA6, - 0x48, 0x00, 0x01, 0x2D, 0x48, 0x00, 0x00, 0x04, 0x88, 0x62, 0xF2, 0x38, 0x2C, 0x03, 0x00, 0x00, 0x41, 0x82, - 0x00, 0x14, 0x48, 0x00, 0x00, 0xB9, 0x7C, 0x68, 0x02, 0xA6, 0x48, 0x00, 0x01, 0x11, 0x48, 0x00, 0x00, 0x10, - 0x48, 0x00, 0x00, 0xC9, 0x7C, 0x68, 0x02, 0xA6, 0x48, 0x00, 0x01, 0x01, 0x88, 0x62, 0xF2, 0x3C, 0x2C, 0x03, - 0x00, 0x00, 0x41, 0x82, 0x00, 0x14, 0x48, 0x00, 0x00, 0xD1, 0x7C, 0x68, 0x02, 0xA6, 0x48, 0x00, 0x00, 0xE9, - 0x48, 0x00, 0x01, 0x04, 0x48, 0x00, 0x00, 0xD1, 0x7C, 0x68, 0x02, 0xA6, 0x48, 0x00, 0x00, 0xD9, 0x48, 0x00, - 0x00, 0xF4, 0x4E, 0x80, 0x00, 0x21, 0x80, 0x3C, 0xE4, 0xD4, 0x00, 0x24, 0x04, 0x64, 0x80, 0x07, 0x96, 0xE0, - 0x60, 0x00, 0x00, 0x00, 0x80, 0x2B, 0x7E, 0x54, 0x48, 0x00, 0x00, 0x88, 0x80, 0x2B, 0x80, 0x8C, 0x48, 0x00, - 0x00, 0x84, 0x80, 0x12, 0x39, 0xA8, 0x60, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x4E, 0x80, 0x00, 0x21, - 0x80, 0x3C, 0xE4, 0xD4, 0x00, 0x20, 0x00, 0x00, 0x80, 0x07, 0x96, 0xE0, 0x3A, 0x40, 0x00, 0x01, 0x80, 0x2B, - 0x7E, 0x54, 0x88, 0x7F, 0x22, 0x40, 0x80, 0x2B, 0x80, 0x8C, 0x2C, 0x03, 0x00, 0x02, 0x80, 0x10, 0xFC, 0x48, - 0x90, 0x05, 0x21, 0xDC, 0x80, 0x10, 0xFB, 0x68, 0x90, 0x05, 0x21, 0xDC, 0x80, 0x12, 0x39, 0xA8, 0x90, 0x1F, - 0x1A, 0x5C, 0xFF, 0xFF, 0xFF, 0xFF, 0x4E, 0x80, 0x00, 0x21, 0x80, 0x1D, 0x46, 0x10, 0x48, 0x00, 0x00, 0x4C, - 0x80, 0x1D, 0x47, 0x24, 0x48, 0x00, 0x00, 0x3C, 0x80, 0x1D, 0x46, 0x0C, 0x80, 0x9F, 0x00, 0xEC, 0xFF, 0xFF, - 0xFF, 0xFF, 0x4E, 0x80, 0x00, 0x21, 0x80, 0x1D, 0x46, 0x10, 0x38, 0x83, 0x7F, 0x9C, 0x80, 0x1D, 0x47, 0x24, - 0x88, 0x1B, 0x00, 0xC4, 0x80, 0x1D, 0x46, 0x0C, 0x3C, 0x60, 0x80, 0x3B, 0xFF, 0xFF, 0xFF, 0xFF, 0x4E, 0x80, - 0x00, 0x21, 0x80, 0x1D, 0x45, 0xFC, 0x48, 0x00, 0x09, 0xDC, 0xFF, 0xFF, 0xFF, 0xFF, 0x4E, 0x80, 0x00, 0x21, - 0x80, 0x1D, 0x45, 0xFC, 0x40, 0x80, 0x09, 0xDC, 0xFF, 0xFF, 0xFF, 0xFF, 0x38, 0xA3, 0xFF, 0xFC, 0x84, 0x65, - 0x00, 0x04, 0x2C, 0x03, 0xFF, 0xFF, 0x41, 0x82, 0x00, 0x10, 0x84, 0x85, 0x00, 0x04, 0x90, 0x83, 0x00, 0x00, - 0x4B, 0xFF, 0xFF, 0xEC, 0x4E, 0x80, 0x00, 0x20, 0x3C, 0x60, 0x80, 0x00, 0x3C, 0x80, 0x00, 0x3B, 0x60, 0x84, - 0x72, 0x2C, 0x3D, 0x80, 0x80, 0x32, 0x61, 0x8C, 0x8F, 0x50, 0x7D, 0x89, 0x03, 0xA6, 0x4E, 0x80, 0x04, 0x21, - 0x3C, 0x60, 0x80, 0x17, 0x3C, 0x80, 0x80, 0x17, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x1D, 0x14, 0xC8, 0x00, 0x00, - 0x00, 0x04, // #Common/Preload Stadium - // Transformations/Handlers/Init - // isLoaded Bool.asm - 0x88, 0x62, 0xF2, 0x38, 0x2C, 0x03, 0x00, 0x00, 0x41, 0x82, 0x00, 0x0C, 0x38, 0x60, 0x00, 0x00, 0x98, 0x7F, - 0x00, 0xF0, 0x3B, 0xA0, 0x00, 0x01, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x1D, 0x45, 0xEC, - 0x00, 0x00, 0x00, 0x1B, // #Common/Preload Stadium - // Transformations/Handlers/Load - // Transformation.asm - 0x88, 0x62, 0xF2, 0x38, 0x2C, 0x03, 0x00, 0x00, 0x41, 0x82, 0x00, 0xC4, 0x88, 0x7F, 0x00, 0xF0, 0x2C, 0x03, - 0x00, 0x00, 0x40, 0x82, 0x00, 0xB8, 0x38, 0x60, 0x00, 0x04, 0x3D, 0x80, 0x80, 0x38, 0x61, 0x8C, 0x05, 0x80, - 0x7D, 0x89, 0x03, 0xA6, 0x4E, 0x80, 0x04, 0x21, 0x54, 0x60, 0x10, 0x3A, 0xA8, 0x7F, 0x00, 0xE2, 0x3C, 0x80, - 0x80, 0x3B, 0x60, 0x84, 0x7F, 0x9C, 0x7C, 0x84, 0x00, 0x2E, 0x7C, 0x03, 0x20, 0x00, 0x41, 0x82, 0xFF, 0xD4, - 0x90, 0x9F, 0x00, 0xEC, 0x2C, 0x04, 0x00, 0x03, 0x40, 0x82, 0x00, 0x0C, 0x38, 0x80, 0x00, 0x00, 0x48, 0x00, - 0x00, 0x34, 0x2C, 0x04, 0x00, 0x04, 0x40, 0x82, 0x00, 0x0C, 0x38, 0x80, 0x00, 0x01, 0x48, 0x00, 0x00, 0x24, - 0x2C, 0x04, 0x00, 0x09, 0x40, 0x82, 0x00, 0x0C, 0x38, 0x80, 0x00, 0x02, 0x48, 0x00, 0x00, 0x14, 0x2C, 0x04, - 0x00, 0x06, 0x40, 0x82, 0x00, 0x00, 0x38, 0x80, 0x00, 0x03, 0x48, 0x00, 0x00, 0x04, 0x3C, 0x60, 0x80, 0x3E, - 0x60, 0x63, 0x12, 0x48, 0x54, 0x80, 0x10, 0x3A, 0x7C, 0x63, 0x02, 0x14, 0x80, 0x63, 0x03, 0xD8, 0x80, 0x9F, - 0x00, 0xCC, 0x38, 0xBF, 0x00, 0xC8, 0x3C, 0xC0, 0x80, 0x1D, 0x60, 0xC6, 0x42, 0x20, 0x38, 0xE0, 0x00, 0x00, - 0x3D, 0x80, 0x80, 0x01, 0x61, 0x8C, 0x65, 0x80, 0x7D, 0x89, 0x03, 0xA6, 0x4E, 0x80, 0x04, 0x21, 0x38, 0x60, - 0x00, 0x01, 0x98, 0x7F, 0x00, 0xF0, 0x80, 0x7F, 0x00, 0xD8, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xC2, 0x1D, 0x4F, 0x14, 0x00, 0x00, 0x00, 0x04, // #Common/Preload - // Stadium - // Transformations/Handlers/Reset - // isLoaded.asm - 0x88, 0x62, 0xF2, 0x38, 0x2C, 0x03, 0x00, 0x00, 0x41, 0x82, 0x00, 0x0C, 0x38, 0x60, 0x00, 0x00, 0x98, 0x7F, - 0x00, 0xF0, 0x80, 0x6D, 0xB2, 0xD8, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x06, 0x8F, 0x30, - 0x00, 0x00, 0x00, 0x9D, // #Common/PAL/Handlers/Character DAT - // Patcher.asm - 0x88, 0x62, 0xF2, 0x34, 0x2C, 0x03, 0x00, 0x00, 0x41, 0x82, 0x04, 0xD4, 0x7C, 0x08, 0x02, 0xA6, 0x90, 0x01, - 0x00, 0x04, 0x94, 0x21, 0xFF, 0x50, 0xBE, 0x81, 0x00, 0x08, 0x83, 0xFE, 0x01, 0x0C, 0x83, 0xFF, 0x00, 0x08, - 0x3B, 0xFF, 0xFF, 0xE0, 0x80, 0x7D, 0x00, 0x00, 0x2C, 0x03, 0x00, 0x1B, 0x40, 0x80, 0x04, 0x9C, 0x48, 0x00, - 0x00, 0x71, 0x48, 0x00, 0x00, 0xA9, 0x48, 0x00, 0x00, 0xB9, 0x48, 0x00, 0x01, 0x51, 0x48, 0x00, 0x01, 0x79, - 0x48, 0x00, 0x01, 0x79, 0x48, 0x00, 0x02, 0x29, 0x48, 0x00, 0x02, 0x39, 0x48, 0x00, 0x02, 0x81, 0x48, 0x00, - 0x02, 0xF9, 0x48, 0x00, 0x03, 0x11, 0x48, 0x00, 0x03, 0x11, 0x48, 0x00, 0x03, 0x11, 0x48, 0x00, 0x03, 0x11, - 0x48, 0x00, 0x03, 0x21, 0x48, 0x00, 0x03, 0x21, 0x48, 0x00, 0x03, 0x89, 0x48, 0x00, 0x03, 0x89, 0x48, 0x00, - 0x03, 0x91, 0x48, 0x00, 0x03, 0x91, 0x48, 0x00, 0x03, 0xA9, 0x48, 0x00, 0x03, 0xA9, 0x48, 0x00, 0x03, 0xB9, - 0x48, 0x00, 0x03, 0xB9, 0x48, 0x00, 0x03, 0xC9, 0x48, 0x00, 0x03, 0xC9, 0x48, 0x00, 0x03, 0xC9, 0x48, 0x00, - 0x04, 0x29, 0x7C, 0x88, 0x02, 0xA6, 0x1C, 0x63, 0x00, 0x04, 0x7C, 0x84, 0x1A, 0x14, 0x80, 0xA4, 0x00, 0x00, - 0x54, 0xA5, 0x01, 0xBA, 0x7C, 0xA4, 0x2A, 0x14, 0x80, 0x65, 0x00, 0x00, 0x80, 0x85, 0x00, 0x04, 0x2C, 0x03, - 0x00, 0xFF, 0x41, 0x82, 0x00, 0x14, 0x7C, 0x63, 0xFA, 0x14, 0x90, 0x83, 0x00, 0x00, 0x38, 0xA5, 0x00, 0x08, - 0x4B, 0xFF, 0xFF, 0xE4, 0x48, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x33, 0x44, 0x3F, 0x54, 0x7A, 0xE1, 0x00, 0x00, - 0x33, 0x60, 0x42, 0xC4, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x37, 0x9C, 0x42, 0x92, 0x00, 0x00, - 0x00, 0x00, 0x39, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x0C, 0x40, 0x86, 0x66, 0x66, 0x00, 0x00, - 0x39, 0x10, 0x3D, 0xEA, 0x0E, 0xA1, 0x00, 0x00, 0x39, 0x28, 0x41, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x04, - 0x2C, 0x01, 0x48, 0x0C, 0x00, 0x00, 0x47, 0x20, 0x1B, 0x96, 0x80, 0x13, 0x00, 0x00, 0x47, 0x34, 0x1B, 0x96, - 0x80, 0x13, 0x00, 0x00, 0x47, 0x3C, 0x04, 0x00, 0x00, 0x09, 0x00, 0x00, 0x4A, 0x40, 0x2C, 0x00, 0x68, 0x11, - 0x00, 0x00, 0x4A, 0x4C, 0x28, 0x1B, 0x00, 0x13, 0x00, 0x00, 0x4A, 0x50, 0x0D, 0x00, 0x01, 0x0B, 0x00, 0x00, - 0x4A, 0x54, 0x2C, 0x80, 0x68, 0x11, 0x00, 0x00, 0x4A, 0x60, 0x28, 0x1B, 0x00, 0x13, 0x00, 0x00, 0x4A, 0x64, - 0x0D, 0x00, 0x01, 0x0B, 0x00, 0x00, 0x4B, 0x24, 0x2C, 0x00, 0x68, 0x0D, 0x00, 0x00, 0x4B, 0x30, 0x0F, 0x10, - 0x40, 0x13, 0x00, 0x00, 0x4B, 0x38, 0x2C, 0x80, 0x38, 0x0D, 0x00, 0x00, 0x4B, 0x44, 0x0F, 0x10, 0x40, 0x13, - 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x38, 0x0C, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x4E, 0xF8, 0x2C, 0x00, - 0x38, 0x03, 0x00, 0x00, 0x4F, 0x08, 0x0F, 0x80, 0x00, 0x0B, 0x00, 0x00, 0x4F, 0x0C, 0x2C, 0x80, 0x20, 0x03, - 0x00, 0x00, 0x4F, 0x1C, 0x0F, 0x80, 0x00, 0x0B, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, - 0x4D, 0x10, 0x3F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x70, 0x42, 0x94, 0x00, 0x00, 0x00, 0x00, 0x4D, 0xD4, - 0x41, 0x90, 0x00, 0x00, 0x00, 0x00, 0x4D, 0xE0, 0x41, 0x90, 0x00, 0x00, 0x00, 0x00, 0x83, 0xAC, 0x2C, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x83, 0xB8, 0x34, 0x8C, 0x80, 0x11, 0x00, 0x00, 0x84, 0x00, 0x34, 0x8C, 0x80, 0x11, - 0x00, 0x00, 0x84, 0x30, 0x05, 0x00, 0x00, 0x8B, 0x00, 0x00, 0x84, 0x38, 0x04, 0x1A, 0x05, 0x00, 0x00, 0x00, - 0x84, 0x44, 0x05, 0x00, 0x00, 0x8B, 0x00, 0x00, 0x84, 0xDC, 0x05, 0x78, 0x05, 0x78, 0x00, 0x00, 0x85, 0xB8, - 0x10, 0x00, 0x01, 0x0B, 0x00, 0x00, 0x85, 0xC0, 0x03, 0xE8, 0x01, 0xF4, 0x00, 0x00, 0x85, 0xCC, 0x10, 0x00, - 0x01, 0x0B, 0x00, 0x00, 0x85, 0xD4, 0x03, 0x84, 0x03, 0xE8, 0x00, 0x00, 0x85, 0xE0, 0x10, 0x00, 0x01, 0x0B, - 0x00, 0x00, 0x88, 0x18, 0x0B, 0x00, 0x01, 0x0B, 0x00, 0x00, 0x88, 0x2C, 0x0B, 0x00, 0x01, 0x0B, 0x00, 0x00, - 0x88, 0xF8, 0x04, 0x1A, 0x0B, 0xB8, 0x00, 0x00, 0x89, 0x3C, 0x04, 0x1A, 0x0B, 0xB8, 0x00, 0x00, 0x89, 0x80, - 0x04, 0x1A, 0x0B, 0xB8, 0x00, 0x00, 0x89, 0xE0, 0x04, 0xFE, 0xF7, 0x04, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, - 0x36, 0xCC, 0x42, 0xEC, 0x00, 0x00, 0x00, 0x00, 0x37, 0xC4, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x34, 0x68, 0x3F, 0x66, 0x66, 0x66, 0x00, 0x00, 0x39, 0xD8, 0x44, 0x0C, 0x00, 0x00, 0x00, 0x00, - 0x3A, 0x44, 0xB4, 0x99, 0x00, 0x11, 0x00, 0x00, 0x3A, 0x48, 0x1B, 0x8C, 0x00, 0x8F, 0x00, 0x00, 0x3A, 0x58, - 0xB4, 0x99, 0x00, 0x11, 0x00, 0x00, 0x3A, 0x5C, 0x1B, 0x8C, 0x00, 0x8F, 0x00, 0x00, 0x3A, 0x6C, 0xB4, 0x99, - 0x00, 0x11, 0x00, 0x00, 0x3A, 0x70, 0x1B, 0x8C, 0x00, 0x8F, 0x00, 0x00, 0x3B, 0x30, 0x44, 0x0C, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x45, 0xC8, 0x2C, 0x01, 0x50, 0x10, 0x00, 0x00, 0x45, 0xD4, 0x2D, 0x19, - 0x80, 0x13, 0x00, 0x00, 0x45, 0xDC, 0x2C, 0x80, 0xB0, 0x10, 0x00, 0x00, 0x45, 0xE8, 0x2D, 0x19, 0x80, 0x13, - 0x00, 0x00, 0x49, 0xC4, 0x2C, 0x00, 0x68, 0x0A, 0x00, 0x00, 0x49, 0xD0, 0x28, 0x1B, 0x80, 0x13, 0x00, 0x00, - 0x49, 0xD8, 0x2C, 0x80, 0x78, 0x0A, 0x00, 0x00, 0x49, 0xE4, 0x28, 0x1B, 0x80, 0x13, 0x00, 0x00, 0x49, 0xF0, - 0x2C, 0x00, 0x68, 0x08, 0x00, 0x00, 0x49, 0xFC, 0x23, 0x1B, 0x80, 0x13, 0x00, 0x00, 0x4A, 0x04, 0x2C, 0x80, - 0x78, 0x08, 0x00, 0x00, 0x4A, 0x10, 0x23, 0x1B, 0x80, 0x13, 0x00, 0x00, 0x5C, 0x98, 0x1E, 0x0C, 0x80, 0x80, - 0x00, 0x00, 0x5C, 0xF4, 0xB4, 0x80, 0x0C, 0x90, 0x00, 0x00, 0x5D, 0x08, 0xB4, 0x80, 0x0C, 0x90, 0x00, 0x00, - 0x00, 0xFF, 0x00, 0x00, 0x3A, 0x1C, 0xB4, 0x94, 0x00, 0x13, 0x00, 0x00, 0x3A, 0x64, 0x2C, 0x00, 0x00, 0x15, - 0x00, 0x00, 0x3A, 0x70, 0xB4, 0x92, 0x80, 0x13, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, - 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x64, 0x7C, 0xB4, 0x9A, 0x40, 0x17, 0x00, 0x00, 0x64, 0x80, - 0x64, 0x00, 0x10, 0x97, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x33, 0xE4, 0x42, 0xDE, - 0x00, 0x00, 0x00, 0x00, 0x45, 0x28, 0x2C, 0x01, 0x30, 0x11, 0x00, 0x00, 0x45, 0x34, 0xB4, 0x98, 0x80, 0x13, - 0x00, 0x00, 0x45, 0x3C, 0x2C, 0x81, 0x30, 0x11, 0x00, 0x00, 0x45, 0x48, 0xB4, 0x98, 0x80, 0x13, 0x00, 0x00, - 0x45, 0x50, 0x2D, 0x00, 0x20, 0x11, 0x00, 0x00, 0x45, 0x5C, 0xB4, 0x98, 0x80, 0x13, 0x00, 0x00, 0x45, 0xF8, - 0x2C, 0x01, 0x30, 0x0F, 0x00, 0x00, 0x46, 0x08, 0x0F, 0x00, 0x01, 0x0B, 0x00, 0x00, 0x46, 0x0C, 0x2C, 0x81, - 0x28, 0x0F, 0x00, 0x00, 0x46, 0x1C, 0x0F, 0x00, 0x01, 0x0B, 0x00, 0x00, 0x4A, 0xEC, 0x2C, 0x00, 0x70, 0x03, - 0x00, 0x00, 0x4B, 0x00, 0x2C, 0x80, 0x38, 0x03, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, - 0x48, 0x5C, 0x2C, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x37, 0xB0, - 0x3F, 0x59, 0x99, 0x9A, 0x00, 0x00, 0x37, 0xCC, 0x42, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x55, 0x20, 0x87, 0x11, - 0x80, 0x13, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x3B, 0x8C, 0x44, 0x0C, 0x00, 0x00, - 0x00, 0x00, 0x3D, 0x0C, 0x44, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, - 0x50, 0xE4, 0xB4, 0x99, 0x00, 0x13, 0x00, 0x00, 0x50, 0xF8, 0xB4, 0x99, 0x00, 0x13, 0x00, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x4E, 0xB0, 0x02, 0xBC, 0xFF, 0x38, 0x00, 0x00, - 0x4E, 0xBC, 0x14, 0x00, 0x01, 0x23, 0x00, 0x00, 0x4E, 0xC4, 0x03, 0x84, 0x01, 0xF4, 0x00, 0x00, 0x4E, 0xD0, - 0x14, 0x00, 0x01, 0x23, 0x00, 0x00, 0x4E, 0xD8, 0x04, 0x4C, 0x04, 0xB0, 0x00, 0x00, 0x4E, 0xE4, 0x14, 0x00, - 0x01, 0x23, 0x00, 0x00, 0x50, 0x5C, 0x2C, 0x00, 0x68, 0x15, 0x00, 0x00, 0x50, 0x6C, 0x14, 0x08, 0x01, 0x23, - 0x00, 0x00, 0x50, 0x70, 0x2C, 0x80, 0x60, 0x15, 0x00, 0x00, 0x50, 0x80, 0x14, 0x08, 0x01, 0x23, 0x00, 0x00, - 0x50, 0x84, 0x2D, 0x00, 0x20, 0x15, 0x00, 0x00, 0x50, 0x94, 0x14, 0x08, 0x01, 0x23, 0x00, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0xFF, 0xBA, 0x81, 0x00, 0x08, 0x80, 0x01, 0x00, 0xB4, 0x38, 0x21, 0x00, 0xB0, 0x7C, 0x08, - 0x03, 0xA6, 0x3C, 0x60, 0x80, 0x3C, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x2F, 0x9A, 0x3C, - 0x00, 0x00, 0x00, 0x08, // #Common/PAL/Handlers/PAL Stock Icons.asm - 0x88, 0x62, 0xF2, 0x34, 0x2C, 0x03, 0x00, 0x00, 0x41, 0x82, 0x00, 0x30, 0x48, 0x00, 0x00, 0x21, 0x7C, 0x88, - 0x02, 0xA6, 0x80, 0x64, 0x00, 0x00, 0x90, 0x7D, 0x00, 0x2C, 0x90, 0x7D, 0x00, 0x30, 0x80, 0x64, 0x00, 0x04, - 0x90, 0x7D, 0x00, 0x3C, 0x48, 0x00, 0x00, 0x10, 0x4E, 0x80, 0x00, 0x21, 0x3F, 0x59, 0x99, 0x9A, 0xC1, 0xA8, - 0x00, 0x00, 0x80, 0x1D, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x10, 0xFC, 0x44, 0x00, 0x00, 0x00, - 0x04, // #Common/PAL/Handlers/DK - // Up B/Aerial Up B.asm - 0x88, 0x82, 0xF2, 0x34, 0x2C, 0x04, 0x00, 0x00, 0x41, 0x82, 0x00, 0x10, 0x3C, 0x00, 0x80, 0x11, 0x60, 0x00, - 0x00, 0x74, 0x48, 0x00, 0x00, 0x08, 0x38, 0x03, 0xD7, 0x74, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x10, 0xFB, 0x64, - 0x00, 0x00, 0x00, 0x04, // #Common/PAL/Handlers/DK Up B/Grounded - // Up B.asm - 0x88, 0x82, 0xF2, 0x34, 0x2C, 0x04, 0x00, 0x00, 0x41, 0x82, 0x00, 0x10, 0x3C, 0x00, 0x80, 0x11, 0x60, 0x00, - 0x00, 0x74, 0x48, 0x00, 0x00, 0x08, 0x38, 0x03, 0xD7, 0x74, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 // Termination sequence + 0xC2, 0x0C, 0x9A, 0x44, 0x00, 0x00, 0x00, 0x2F, // #External/UCF + Arduino Toggle UI/UCF/UCF + // 0.74 Dashback - Check for Toggle.asm + 0xD0, 0x1F, 0x00, 0x2C, 0x88, 0x9F, 0x06, 0x18, 0x38, 0x62, 0xF2, 0x28, 0x7C, 0x63, 0x20, + 0xAE, 0x2C, 0x03, 0x00, 0x01, 0x41, 0x82, 0x00, 0x14, 0x38, 0x62, 0xF2, 0x2C, 0x7C, 0x63, + 0x20, 0xAE, 0x2C, 0x03, 0x00, 0x01, 0x40, 0x82, 0x01, 0x50, 0x7C, 0x08, 0x02, 0xA6, 0x90, + 0x01, 0x00, 0x04, 0x94, 0x21, 0xFF, 0x50, 0xBE, 0x81, 0x00, 0x08, 0x48, 0x00, 0x01, 0x21, + 0x7F, 0xC8, 0x02, 0xA6, 0xC0, 0x3F, 0x08, 0x94, 0xC0, 0x5E, 0x00, 0x00, 0xFC, 0x01, 0x10, + 0x40, 0x40, 0x82, 0x01, 0x18, 0x80, 0x8D, 0xAE, 0xB4, 0xC0, 0x3F, 0x06, 0x20, 0xFC, 0x20, + 0x0A, 0x10, 0xC0, 0x44, 0x00, 0x3C, 0xFC, 0x01, 0x10, 0x40, 0x41, 0x80, 0x01, 0x00, 0x88, + 0x7F, 0x06, 0x70, 0x2C, 0x03, 0x00, 0x02, 0x40, 0x80, 0x00, 0xF4, 0x88, 0x7F, 0x22, 0x1F, + 0x54, 0x60, 0x07, 0x39, 0x40, 0x82, 0x00, 0xE8, 0x3C, 0x60, 0x80, 0x4C, 0x60, 0x63, 0x1F, + 0x78, 0x8B, 0xA3, 0x00, 0x01, 0x38, 0x7D, 0xFF, 0xFE, 0x88, 0x9F, 0x06, 0x18, 0x48, 0x00, + 0x00, 0x8D, 0x7C, 0x7C, 0x1B, 0x78, 0x7F, 0xA3, 0xEB, 0x78, 0x88, 0x9F, 0x06, 0x18, 0x48, + 0x00, 0x00, 0x7D, 0x7C, 0x7C, 0x18, 0x50, 0x7C, 0x63, 0x19, 0xD6, 0x2C, 0x03, 0x15, 0xF9, + 0x40, 0x81, 0x00, 0xB0, 0x38, 0x00, 0x00, 0x01, 0x90, 0x1F, 0x23, 0x58, 0x90, 0x1F, 0x23, + 0x40, 0x80, 0x9F, 0x00, 0x04, 0x2C, 0x04, 0x00, 0x0A, 0x40, 0xA2, 0x00, 0x98, 0x88, 0x7F, + 0x00, 0x0C, 0x38, 0x80, 0x00, 0x01, 0x3D, 0x80, 0x80, 0x03, 0x61, 0x8C, 0x41, 0x8C, 0x7D, + 0x89, 0x03, 0xA6, 0x4E, 0x80, 0x04, 0x21, 0x2C, 0x03, 0x00, 0x00, 0x41, 0x82, 0x00, 0x78, + 0x80, 0x83, 0x00, 0x2C, 0x80, 0x84, 0x1E, 0xCC, 0xC0, 0x3F, 0x00, 0x2C, 0xD0, 0x24, 0x00, + 0x18, 0xC0, 0x5E, 0x00, 0x04, 0xFC, 0x01, 0x10, 0x40, 0x41, 0x81, 0x00, 0x0C, 0x38, 0x60, + 0x00, 0x80, 0x48, 0x00, 0x00, 0x08, 0x38, 0x60, 0x00, 0x7F, 0x98, 0x64, 0x00, 0x06, 0x48, + 0x00, 0x00, 0x48, 0x7C, 0x85, 0x23, 0x78, 0x38, 0x63, 0xFF, 0xFF, 0x2C, 0x03, 0x00, 0x00, + 0x40, 0x80, 0x00, 0x08, 0x38, 0x63, 0x00, 0x05, 0x3C, 0x80, 0x80, 0x46, 0x60, 0x84, 0xB1, + 0x08, 0x1C, 0x63, 0x00, 0x30, 0x7C, 0x84, 0x1A, 0x14, 0x1C, 0x65, 0x00, 0x0C, 0x7C, 0x84, + 0x1A, 0x14, 0x88, 0x64, 0x00, 0x02, 0x7C, 0x63, 0x07, 0x74, 0x4E, 0x80, 0x00, 0x20, 0x4E, + 0x80, 0x00, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBA, 0x81, 0x00, 0x08, + 0x80, 0x01, 0x00, 0xB4, 0x38, 0x21, 0x00, 0xB0, 0x7C, 0x08, 0x03, 0xA6, 0x00, 0x00, 0x00, + 0x00, 0xC2, 0x09, 0x98, 0xA4, 0x00, 0x00, 0x00, + 0x2B, // #External/UCF + Arduino Toggle UI/UCF/UCF + // 0.74 Shield Drop - Check for Toggle.asm + 0x7C, 0x08, 0x02, 0xA6, 0x90, 0x01, 0x00, 0x04, 0x94, 0x21, 0xFF, 0x50, 0xBE, 0x81, 0x00, + 0x08, 0x7C, 0x7E, 0x1B, 0x78, 0x83, 0xFE, 0x00, 0x2C, 0x48, 0x00, 0x01, 0x01, 0x7F, 0xA8, + 0x02, 0xA6, 0x88, 0x9F, 0x06, 0x18, 0x38, 0x62, 0xF2, 0x28, 0x7C, 0x63, 0x20, 0xAE, 0x2C, + 0x03, 0x00, 0x01, 0x41, 0x82, 0x00, 0x14, 0x38, 0x62, 0xF2, 0x30, 0x7C, 0x63, 0x20, 0xAE, + 0x2C, 0x03, 0x00, 0x01, 0x40, 0x82, 0x00, 0xF8, 0xC0, 0x3F, 0x06, 0x3C, 0x80, 0x6D, 0xAE, + 0xB4, 0xC0, 0x03, 0x03, 0x14, 0xFC, 0x01, 0x00, 0x40, 0x40, 0x81, 0x00, 0xE4, 0xC0, 0x3F, + 0x06, 0x20, 0x48, 0x00, 0x00, 0x71, 0xD0, 0x21, 0x00, 0x90, 0xC0, 0x3F, 0x06, 0x24, 0x48, + 0x00, 0x00, 0x65, 0xC0, 0x41, 0x00, 0x90, 0xEC, 0x42, 0x00, 0xB2, 0xEC, 0x21, 0x00, 0x72, + 0xEC, 0x21, 0x10, 0x2A, 0xC0, 0x5D, 0x00, 0x0C, 0xFC, 0x01, 0x10, 0x40, 0x41, 0x80, 0x00, + 0xB4, 0x88, 0x9F, 0x06, 0x70, 0x2C, 0x04, 0x00, 0x03, 0x40, 0x81, 0x00, 0xA8, 0xC0, 0x1D, + 0x00, 0x10, 0xC0, 0x3F, 0x06, 0x24, 0xFC, 0x00, 0x08, 0x40, 0x40, 0x80, 0x00, 0x98, 0xBA, + 0x81, 0x00, 0x08, 0x80, 0x01, 0x00, 0xB4, 0x38, 0x21, 0x00, 0xB0, 0x7C, 0x08, 0x03, 0xA6, + 0x80, 0x61, 0x00, 0x1C, 0x83, 0xE1, 0x00, 0x14, 0x38, 0x21, 0x00, 0x18, 0x38, 0x63, 0x00, + 0x08, 0x7C, 0x68, 0x03, 0xA6, 0x4E, 0x80, 0x00, 0x20, 0xFC, 0x00, 0x0A, 0x10, 0xC0, 0x3D, + 0x00, 0x00, 0xEC, 0x00, 0x00, 0x72, 0xC0, 0x3D, 0x00, 0x04, 0xEC, 0x00, 0x08, 0x28, 0xFC, + 0x00, 0x00, 0x1E, 0xD8, 0x01, 0x00, 0x80, 0x80, 0x61, 0x00, 0x84, 0x38, 0x63, 0x00, 0x02, + 0x3C, 0x00, 0x43, 0x30, 0xC8, 0x5D, 0x00, 0x14, 0x6C, 0x63, 0x80, 0x00, 0x90, 0x01, 0x00, + 0x80, 0x90, 0x61, 0x00, 0x84, 0xC8, 0x21, 0x00, 0x80, 0xEC, 0x01, 0x10, 0x28, 0xC0, 0x3D, + 0x00, 0x00, 0xEC, 0x20, 0x08, 0x24, 0x4E, 0x80, 0x00, 0x20, 0x4E, 0x80, 0x00, 0x21, 0x42, + 0xA0, 0x00, 0x00, 0x37, 0x27, 0x00, 0x00, 0x43, 0x30, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, + 0xBF, 0x4C, 0xCC, 0xCD, 0x43, 0x30, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x7F, 0xC3, 0xF3, + 0x78, 0x7F, 0xE4, 0xFB, 0x78, 0xBA, 0x81, 0x00, 0x08, 0x80, 0x01, 0x00, 0xB4, 0x38, 0x21, + 0x00, 0xB0, 0x7C, 0x08, 0x03, 0xA6, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, + 0x16, 0xE7, 0x50, 0x00, 0x00, 0x00, + 0x33, // #Common/StaticPatches/ToggledStaticOverwrites.asm + 0x88, 0x62, 0xF2, 0x34, 0x2C, 0x03, 0x00, 0x00, 0x41, 0x82, 0x00, 0x14, 0x48, 0x00, 0x00, + 0x75, 0x7C, 0x68, 0x02, 0xA6, 0x48, 0x00, 0x01, 0x3D, 0x48, 0x00, 0x00, 0x14, 0x48, 0x00, + 0x00, 0x95, 0x7C, 0x68, 0x02, 0xA6, 0x48, 0x00, 0x01, 0x2D, 0x48, 0x00, 0x00, 0x04, 0x88, + 0x62, 0xF2, 0x38, 0x2C, 0x03, 0x00, 0x00, 0x41, 0x82, 0x00, 0x14, 0x48, 0x00, 0x00, 0xB9, + 0x7C, 0x68, 0x02, 0xA6, 0x48, 0x00, 0x01, 0x11, 0x48, 0x00, 0x00, 0x10, 0x48, 0x00, 0x00, + 0xC9, 0x7C, 0x68, 0x02, 0xA6, 0x48, 0x00, 0x01, 0x01, 0x88, 0x62, 0xF2, 0x3C, 0x2C, 0x03, + 0x00, 0x00, 0x41, 0x82, 0x00, 0x14, 0x48, 0x00, 0x00, 0xD1, 0x7C, 0x68, 0x02, 0xA6, 0x48, + 0x00, 0x00, 0xE9, 0x48, 0x00, 0x01, 0x04, 0x48, 0x00, 0x00, 0xD1, 0x7C, 0x68, 0x02, 0xA6, + 0x48, 0x00, 0x00, 0xD9, 0x48, 0x00, 0x00, 0xF4, 0x4E, 0x80, 0x00, 0x21, 0x80, 0x3C, 0xE4, + 0xD4, 0x00, 0x24, 0x04, 0x64, 0x80, 0x07, 0x96, 0xE0, 0x60, 0x00, 0x00, 0x00, 0x80, 0x2B, + 0x7E, 0x54, 0x48, 0x00, 0x00, 0x88, 0x80, 0x2B, 0x80, 0x8C, 0x48, 0x00, 0x00, 0x84, 0x80, + 0x12, 0x39, 0xA8, 0x60, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x4E, 0x80, 0x00, 0x21, + 0x80, 0x3C, 0xE4, 0xD4, 0x00, 0x20, 0x00, 0x00, 0x80, 0x07, 0x96, 0xE0, 0x3A, 0x40, 0x00, + 0x01, 0x80, 0x2B, 0x7E, 0x54, 0x88, 0x7F, 0x22, 0x40, 0x80, 0x2B, 0x80, 0x8C, 0x2C, 0x03, + 0x00, 0x02, 0x80, 0x10, 0xFC, 0x48, 0x90, 0x05, 0x21, 0xDC, 0x80, 0x10, 0xFB, 0x68, 0x90, + 0x05, 0x21, 0xDC, 0x80, 0x12, 0x39, 0xA8, 0x90, 0x1F, 0x1A, 0x5C, 0xFF, 0xFF, 0xFF, 0xFF, + 0x4E, 0x80, 0x00, 0x21, 0x80, 0x1D, 0x46, 0x10, 0x48, 0x00, 0x00, 0x4C, 0x80, 0x1D, 0x47, + 0x24, 0x48, 0x00, 0x00, 0x3C, 0x80, 0x1D, 0x46, 0x0C, 0x80, 0x9F, 0x00, 0xEC, 0xFF, 0xFF, + 0xFF, 0xFF, 0x4E, 0x80, 0x00, 0x21, 0x80, 0x1D, 0x46, 0x10, 0x38, 0x83, 0x7F, 0x9C, 0x80, + 0x1D, 0x47, 0x24, 0x88, 0x1B, 0x00, 0xC4, 0x80, 0x1D, 0x46, 0x0C, 0x3C, 0x60, 0x80, 0x3B, + 0xFF, 0xFF, 0xFF, 0xFF, 0x4E, 0x80, 0x00, 0x21, 0x80, 0x1D, 0x45, 0xFC, 0x48, 0x00, 0x09, + 0xDC, 0xFF, 0xFF, 0xFF, 0xFF, 0x4E, 0x80, 0x00, 0x21, 0x80, 0x1D, 0x45, 0xFC, 0x40, 0x80, + 0x09, 0xDC, 0xFF, 0xFF, 0xFF, 0xFF, 0x38, 0xA3, 0xFF, 0xFC, 0x84, 0x65, 0x00, 0x04, 0x2C, + 0x03, 0xFF, 0xFF, 0x41, 0x82, 0x00, 0x10, 0x84, 0x85, 0x00, 0x04, 0x90, 0x83, 0x00, 0x00, + 0x4B, 0xFF, 0xFF, 0xEC, 0x4E, 0x80, 0x00, 0x20, 0x3C, 0x60, 0x80, 0x00, 0x3C, 0x80, 0x00, + 0x3B, 0x60, 0x84, 0x72, 0x2C, 0x3D, 0x80, 0x80, 0x32, 0x61, 0x8C, 0x8F, 0x50, 0x7D, 0x89, + 0x03, 0xA6, 0x4E, 0x80, 0x04, 0x21, 0x3C, 0x60, 0x80, 0x17, 0x3C, 0x80, 0x80, 0x17, 0x00, + 0x00, 0x00, 0x00, 0xC2, 0x1D, 0x14, 0xC8, 0x00, 0x00, 0x00, + 0x04, // #Common/Preload Stadium + // Transformations/Handlers/Init + // isLoaded Bool.asm + 0x88, 0x62, 0xF2, 0x38, 0x2C, 0x03, 0x00, 0x00, 0x41, 0x82, 0x00, 0x0C, 0x38, 0x60, 0x00, + 0x00, 0x98, 0x7F, 0x00, 0xF0, 0x3B, 0xA0, 0x00, 0x01, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xC2, 0x1D, 0x45, 0xEC, 0x00, 0x00, 0x00, 0x1B, // #Common/Preload Stadium + // Transformations/Handlers/Load + // Transformation.asm + 0x88, 0x62, 0xF2, 0x38, 0x2C, 0x03, 0x00, 0x00, 0x41, 0x82, 0x00, 0xC4, 0x88, 0x7F, 0x00, + 0xF0, 0x2C, 0x03, 0x00, 0x00, 0x40, 0x82, 0x00, 0xB8, 0x38, 0x60, 0x00, 0x04, 0x3D, 0x80, + 0x80, 0x38, 0x61, 0x8C, 0x05, 0x80, 0x7D, 0x89, 0x03, 0xA6, 0x4E, 0x80, 0x04, 0x21, 0x54, + 0x60, 0x10, 0x3A, 0xA8, 0x7F, 0x00, 0xE2, 0x3C, 0x80, 0x80, 0x3B, 0x60, 0x84, 0x7F, 0x9C, + 0x7C, 0x84, 0x00, 0x2E, 0x7C, 0x03, 0x20, 0x00, 0x41, 0x82, 0xFF, 0xD4, 0x90, 0x9F, 0x00, + 0xEC, 0x2C, 0x04, 0x00, 0x03, 0x40, 0x82, 0x00, 0x0C, 0x38, 0x80, 0x00, 0x00, 0x48, 0x00, + 0x00, 0x34, 0x2C, 0x04, 0x00, 0x04, 0x40, 0x82, 0x00, 0x0C, 0x38, 0x80, 0x00, 0x01, 0x48, + 0x00, 0x00, 0x24, 0x2C, 0x04, 0x00, 0x09, 0x40, 0x82, 0x00, 0x0C, 0x38, 0x80, 0x00, 0x02, + 0x48, 0x00, 0x00, 0x14, 0x2C, 0x04, 0x00, 0x06, 0x40, 0x82, 0x00, 0x00, 0x38, 0x80, 0x00, + 0x03, 0x48, 0x00, 0x00, 0x04, 0x3C, 0x60, 0x80, 0x3E, 0x60, 0x63, 0x12, 0x48, 0x54, 0x80, + 0x10, 0x3A, 0x7C, 0x63, 0x02, 0x14, 0x80, 0x63, 0x03, 0xD8, 0x80, 0x9F, 0x00, 0xCC, 0x38, + 0xBF, 0x00, 0xC8, 0x3C, 0xC0, 0x80, 0x1D, 0x60, 0xC6, 0x42, 0x20, 0x38, 0xE0, 0x00, 0x00, + 0x3D, 0x80, 0x80, 0x01, 0x61, 0x8C, 0x65, 0x80, 0x7D, 0x89, 0x03, 0xA6, 0x4E, 0x80, 0x04, + 0x21, 0x38, 0x60, 0x00, 0x01, 0x98, 0x7F, 0x00, 0xF0, 0x80, 0x7F, 0x00, 0xD8, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x1D, 0x4F, 0x14, 0x00, 0x00, 0x00, + 0x04, // #Common/Preload + // Stadium + // Transformations/Handlers/Reset + // isLoaded.asm + 0x88, 0x62, 0xF2, 0x38, 0x2C, 0x03, 0x00, 0x00, 0x41, 0x82, 0x00, 0x0C, 0x38, 0x60, 0x00, + 0x00, 0x98, 0x7F, 0x00, 0xF0, 0x80, 0x6D, 0xB2, 0xD8, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xC2, 0x06, 0x8F, 0x30, 0x00, 0x00, 0x00, 0x9D, // #Common/PAL/Handlers/Character + // DAT Patcher.asm + 0x88, 0x62, 0xF2, 0x34, 0x2C, 0x03, 0x00, 0x00, 0x41, 0x82, 0x04, 0xD4, 0x7C, 0x08, 0x02, + 0xA6, 0x90, 0x01, 0x00, 0x04, 0x94, 0x21, 0xFF, 0x50, 0xBE, 0x81, 0x00, 0x08, 0x83, 0xFE, + 0x01, 0x0C, 0x83, 0xFF, 0x00, 0x08, 0x3B, 0xFF, 0xFF, 0xE0, 0x80, 0x7D, 0x00, 0x00, 0x2C, + 0x03, 0x00, 0x1B, 0x40, 0x80, 0x04, 0x9C, 0x48, 0x00, 0x00, 0x71, 0x48, 0x00, 0x00, 0xA9, + 0x48, 0x00, 0x00, 0xB9, 0x48, 0x00, 0x01, 0x51, 0x48, 0x00, 0x01, 0x79, 0x48, 0x00, 0x01, + 0x79, 0x48, 0x00, 0x02, 0x29, 0x48, 0x00, 0x02, 0x39, 0x48, 0x00, 0x02, 0x81, 0x48, 0x00, + 0x02, 0xF9, 0x48, 0x00, 0x03, 0x11, 0x48, 0x00, 0x03, 0x11, 0x48, 0x00, 0x03, 0x11, 0x48, + 0x00, 0x03, 0x11, 0x48, 0x00, 0x03, 0x21, 0x48, 0x00, 0x03, 0x21, 0x48, 0x00, 0x03, 0x89, + 0x48, 0x00, 0x03, 0x89, 0x48, 0x00, 0x03, 0x91, 0x48, 0x00, 0x03, 0x91, 0x48, 0x00, 0x03, + 0xA9, 0x48, 0x00, 0x03, 0xA9, 0x48, 0x00, 0x03, 0xB9, 0x48, 0x00, 0x03, 0xB9, 0x48, 0x00, + 0x03, 0xC9, 0x48, 0x00, 0x03, 0xC9, 0x48, 0x00, 0x03, 0xC9, 0x48, 0x00, 0x04, 0x29, 0x7C, + 0x88, 0x02, 0xA6, 0x1C, 0x63, 0x00, 0x04, 0x7C, 0x84, 0x1A, 0x14, 0x80, 0xA4, 0x00, 0x00, + 0x54, 0xA5, 0x01, 0xBA, 0x7C, 0xA4, 0x2A, 0x14, 0x80, 0x65, 0x00, 0x00, 0x80, 0x85, 0x00, + 0x04, 0x2C, 0x03, 0x00, 0xFF, 0x41, 0x82, 0x00, 0x14, 0x7C, 0x63, 0xFA, 0x14, 0x90, 0x83, + 0x00, 0x00, 0x38, 0xA5, 0x00, 0x08, 0x4B, 0xFF, 0xFF, 0xE4, 0x48, 0x00, 0x03, 0xF0, 0x00, + 0x00, 0x33, 0x44, 0x3F, 0x54, 0x7A, 0xE1, 0x00, 0x00, 0x33, 0x60, 0x42, 0xC4, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x37, 0x9C, 0x42, 0x92, 0x00, 0x00, 0x00, 0x00, 0x39, + 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x0C, 0x40, 0x86, 0x66, 0x66, 0x00, 0x00, + 0x39, 0x10, 0x3D, 0xEA, 0x0E, 0xA1, 0x00, 0x00, 0x39, 0x28, 0x41, 0xA0, 0x00, 0x00, 0x00, + 0x00, 0x3C, 0x04, 0x2C, 0x01, 0x48, 0x0C, 0x00, 0x00, 0x47, 0x20, 0x1B, 0x96, 0x80, 0x13, + 0x00, 0x00, 0x47, 0x34, 0x1B, 0x96, 0x80, 0x13, 0x00, 0x00, 0x47, 0x3C, 0x04, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x4A, 0x40, 0x2C, 0x00, 0x68, 0x11, 0x00, 0x00, 0x4A, 0x4C, 0x28, 0x1B, + 0x00, 0x13, 0x00, 0x00, 0x4A, 0x50, 0x0D, 0x00, 0x01, 0x0B, 0x00, 0x00, 0x4A, 0x54, 0x2C, + 0x80, 0x68, 0x11, 0x00, 0x00, 0x4A, 0x60, 0x28, 0x1B, 0x00, 0x13, 0x00, 0x00, 0x4A, 0x64, + 0x0D, 0x00, 0x01, 0x0B, 0x00, 0x00, 0x4B, 0x24, 0x2C, 0x00, 0x68, 0x0D, 0x00, 0x00, 0x4B, + 0x30, 0x0F, 0x10, 0x40, 0x13, 0x00, 0x00, 0x4B, 0x38, 0x2C, 0x80, 0x38, 0x0D, 0x00, 0x00, + 0x4B, 0x44, 0x0F, 0x10, 0x40, 0x13, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x38, 0x0C, 0x00, + 0x00, 0x00, 0x07, 0x00, 0x00, 0x4E, 0xF8, 0x2C, 0x00, 0x38, 0x03, 0x00, 0x00, 0x4F, 0x08, + 0x0F, 0x80, 0x00, 0x0B, 0x00, 0x00, 0x4F, 0x0C, 0x2C, 0x80, 0x20, 0x03, 0x00, 0x00, 0x4F, + 0x1C, 0x0F, 0x80, 0x00, 0x0B, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, + 0x4D, 0x10, 0x3F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x70, 0x42, 0x94, 0x00, 0x00, 0x00, + 0x00, 0x4D, 0xD4, 0x41, 0x90, 0x00, 0x00, 0x00, 0x00, 0x4D, 0xE0, 0x41, 0x90, 0x00, 0x00, + 0x00, 0x00, 0x83, 0xAC, 0x2C, 0x00, 0x00, 0x09, 0x00, 0x00, 0x83, 0xB8, 0x34, 0x8C, 0x80, + 0x11, 0x00, 0x00, 0x84, 0x00, 0x34, 0x8C, 0x80, 0x11, 0x00, 0x00, 0x84, 0x30, 0x05, 0x00, + 0x00, 0x8B, 0x00, 0x00, 0x84, 0x38, 0x04, 0x1A, 0x05, 0x00, 0x00, 0x00, 0x84, 0x44, 0x05, + 0x00, 0x00, 0x8B, 0x00, 0x00, 0x84, 0xDC, 0x05, 0x78, 0x05, 0x78, 0x00, 0x00, 0x85, 0xB8, + 0x10, 0x00, 0x01, 0x0B, 0x00, 0x00, 0x85, 0xC0, 0x03, 0xE8, 0x01, 0xF4, 0x00, 0x00, 0x85, + 0xCC, 0x10, 0x00, 0x01, 0x0B, 0x00, 0x00, 0x85, 0xD4, 0x03, 0x84, 0x03, 0xE8, 0x00, 0x00, + 0x85, 0xE0, 0x10, 0x00, 0x01, 0x0B, 0x00, 0x00, 0x88, 0x18, 0x0B, 0x00, 0x01, 0x0B, 0x00, + 0x00, 0x88, 0x2C, 0x0B, 0x00, 0x01, 0x0B, 0x00, 0x00, 0x88, 0xF8, 0x04, 0x1A, 0x0B, 0xB8, + 0x00, 0x00, 0x89, 0x3C, 0x04, 0x1A, 0x0B, 0xB8, 0x00, 0x00, 0x89, 0x80, 0x04, 0x1A, 0x0B, + 0xB8, 0x00, 0x00, 0x89, 0xE0, 0x04, 0xFE, 0xF7, 0x04, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, + 0x36, 0xCC, 0x42, 0xEC, 0x00, 0x00, 0x00, 0x00, 0x37, 0xC4, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0x00, 0x00, 0x34, 0x68, 0x3F, 0x66, 0x66, 0x66, 0x00, 0x00, 0x39, 0xD8, + 0x44, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x44, 0xB4, 0x99, 0x00, 0x11, 0x00, 0x00, 0x3A, + 0x48, 0x1B, 0x8C, 0x00, 0x8F, 0x00, 0x00, 0x3A, 0x58, 0xB4, 0x99, 0x00, 0x11, 0x00, 0x00, + 0x3A, 0x5C, 0x1B, 0x8C, 0x00, 0x8F, 0x00, 0x00, 0x3A, 0x6C, 0xB4, 0x99, 0x00, 0x11, 0x00, + 0x00, 0x3A, 0x70, 0x1B, 0x8C, 0x00, 0x8F, 0x00, 0x00, 0x3B, 0x30, 0x44, 0x0C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x45, 0xC8, 0x2C, 0x01, 0x50, 0x10, 0x00, 0x00, 0x45, + 0xD4, 0x2D, 0x19, 0x80, 0x13, 0x00, 0x00, 0x45, 0xDC, 0x2C, 0x80, 0xB0, 0x10, 0x00, 0x00, + 0x45, 0xE8, 0x2D, 0x19, 0x80, 0x13, 0x00, 0x00, 0x49, 0xC4, 0x2C, 0x00, 0x68, 0x0A, 0x00, + 0x00, 0x49, 0xD0, 0x28, 0x1B, 0x80, 0x13, 0x00, 0x00, 0x49, 0xD8, 0x2C, 0x80, 0x78, 0x0A, + 0x00, 0x00, 0x49, 0xE4, 0x28, 0x1B, 0x80, 0x13, 0x00, 0x00, 0x49, 0xF0, 0x2C, 0x00, 0x68, + 0x08, 0x00, 0x00, 0x49, 0xFC, 0x23, 0x1B, 0x80, 0x13, 0x00, 0x00, 0x4A, 0x04, 0x2C, 0x80, + 0x78, 0x08, 0x00, 0x00, 0x4A, 0x10, 0x23, 0x1B, 0x80, 0x13, 0x00, 0x00, 0x5C, 0x98, 0x1E, + 0x0C, 0x80, 0x80, 0x00, 0x00, 0x5C, 0xF4, 0xB4, 0x80, 0x0C, 0x90, 0x00, 0x00, 0x5D, 0x08, + 0xB4, 0x80, 0x0C, 0x90, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x3A, 0x1C, 0xB4, 0x94, 0x00, + 0x13, 0x00, 0x00, 0x3A, 0x64, 0x2C, 0x00, 0x00, 0x15, 0x00, 0x00, 0x3A, 0x70, 0xB4, 0x92, + 0x80, 0x13, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, + 0x00, 0x00, 0xFF, 0x00, 0x00, 0x64, 0x7C, 0xB4, 0x9A, 0x40, 0x17, 0x00, 0x00, 0x64, 0x80, + 0x64, 0x00, 0x10, 0x97, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x33, + 0xE4, 0x42, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x45, 0x28, 0x2C, 0x01, 0x30, 0x11, 0x00, 0x00, + 0x45, 0x34, 0xB4, 0x98, 0x80, 0x13, 0x00, 0x00, 0x45, 0x3C, 0x2C, 0x81, 0x30, 0x11, 0x00, + 0x00, 0x45, 0x48, 0xB4, 0x98, 0x80, 0x13, 0x00, 0x00, 0x45, 0x50, 0x2D, 0x00, 0x20, 0x11, + 0x00, 0x00, 0x45, 0x5C, 0xB4, 0x98, 0x80, 0x13, 0x00, 0x00, 0x45, 0xF8, 0x2C, 0x01, 0x30, + 0x0F, 0x00, 0x00, 0x46, 0x08, 0x0F, 0x00, 0x01, 0x0B, 0x00, 0x00, 0x46, 0x0C, 0x2C, 0x81, + 0x28, 0x0F, 0x00, 0x00, 0x46, 0x1C, 0x0F, 0x00, 0x01, 0x0B, 0x00, 0x00, 0x4A, 0xEC, 0x2C, + 0x00, 0x70, 0x03, 0x00, 0x00, 0x4B, 0x00, 0x2C, 0x80, 0x38, 0x03, 0x00, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x48, 0x5C, 0x2C, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x37, 0xB0, 0x3F, 0x59, 0x99, 0x9A, 0x00, 0x00, + 0x37, 0xCC, 0x42, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x55, 0x20, 0x87, 0x11, 0x80, 0x13, 0x00, + 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x3B, 0x8C, 0x44, 0x0C, 0x00, 0x00, + 0x00, 0x00, 0x3D, 0x0C, 0x44, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0x00, 0x50, 0xE4, 0xB4, 0x99, 0x00, 0x13, 0x00, 0x00, 0x50, 0xF8, 0xB4, 0x99, + 0x00, 0x13, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, + 0x00, 0x4E, 0xB0, 0x02, 0xBC, 0xFF, 0x38, 0x00, 0x00, 0x4E, 0xBC, 0x14, 0x00, 0x01, 0x23, + 0x00, 0x00, 0x4E, 0xC4, 0x03, 0x84, 0x01, 0xF4, 0x00, 0x00, 0x4E, 0xD0, 0x14, 0x00, 0x01, + 0x23, 0x00, 0x00, 0x4E, 0xD8, 0x04, 0x4C, 0x04, 0xB0, 0x00, 0x00, 0x4E, 0xE4, 0x14, 0x00, + 0x01, 0x23, 0x00, 0x00, 0x50, 0x5C, 0x2C, 0x00, 0x68, 0x15, 0x00, 0x00, 0x50, 0x6C, 0x14, + 0x08, 0x01, 0x23, 0x00, 0x00, 0x50, 0x70, 0x2C, 0x80, 0x60, 0x15, 0x00, 0x00, 0x50, 0x80, + 0x14, 0x08, 0x01, 0x23, 0x00, 0x00, 0x50, 0x84, 0x2D, 0x00, 0x20, 0x15, 0x00, 0x00, 0x50, + 0x94, 0x14, 0x08, 0x01, 0x23, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xBA, 0x81, + 0x00, 0x08, 0x80, 0x01, 0x00, 0xB4, 0x38, 0x21, 0x00, 0xB0, 0x7C, 0x08, 0x03, 0xA6, 0x3C, + 0x60, 0x80, 0x3C, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x2F, 0x9A, 0x3C, + 0x00, 0x00, 0x00, 0x08, // #Common/PAL/Handlers/PAL Stock Icons.asm + 0x88, 0x62, 0xF2, 0x34, 0x2C, 0x03, 0x00, 0x00, 0x41, 0x82, 0x00, 0x30, 0x48, 0x00, 0x00, + 0x21, 0x7C, 0x88, 0x02, 0xA6, 0x80, 0x64, 0x00, 0x00, 0x90, 0x7D, 0x00, 0x2C, 0x90, 0x7D, + 0x00, 0x30, 0x80, 0x64, 0x00, 0x04, 0x90, 0x7D, 0x00, 0x3C, 0x48, 0x00, 0x00, 0x10, 0x4E, + 0x80, 0x00, 0x21, 0x3F, 0x59, 0x99, 0x9A, 0xC1, 0xA8, 0x00, 0x00, 0x80, 0x1D, 0x00, 0x14, + 0x00, 0x00, 0x00, 0x00, 0xC2, 0x10, 0xFC, 0x44, 0x00, 0x00, 0x00, + 0x04, // #Common/PAL/Handlers/DK + // Up B/Aerial Up B.asm + 0x88, 0x82, 0xF2, 0x34, 0x2C, 0x04, 0x00, 0x00, 0x41, 0x82, 0x00, 0x10, 0x3C, 0x00, 0x80, + 0x11, 0x60, 0x00, 0x00, 0x74, 0x48, 0x00, 0x00, 0x08, 0x38, 0x03, 0xD7, 0x74, 0x00, 0x00, + 0x00, 0x00, 0xC2, 0x10, 0xFB, 0x64, 0x00, 0x00, 0x00, 0x04, // #Common/PAL/Handlers/DK Up + // B/Grounded Up B.asm + 0x88, 0x82, 0xF2, 0x34, 0x2C, 0x04, 0x00, 0x00, 0x41, 0x82, 0x00, 0x10, 0x3C, 0x00, 0x80, + 0x11, 0x60, 0x00, 0x00, 0x74, 0x48, 0x00, 0x00, 0x08, 0x38, 0x03, 0xD7, 0x74, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Termination sequence }; static std::unordered_map staticBlacklist = { - {0x8008d698, true}, // Recording/GetLCancelStatus/GetLCancelStatus.asm - {0x8006c324, true}, // Recording/GetLCancelStatus/ResetLCancelStatus.asm - {0x800679bc, true}, // Recording/ExtendPlayerBlock.asm - {0x802fef88, true}, // Recording/FlushFrameBuffer.asm - {0x80005604, true}, // Recording/IsVSMode.asm - {0x8016d30c, true}, // Recording/SendGameEnd.asm - {0x8016e74c, true}, // Recording/SendGameInfo.asm - {0x8006c5d8, true}, // Recording/SendGamePostFrame.asm - {0x8006b0dc, true}, // Recording/SendGamePreFrame.asm - {0x803219ec, true}, // 3.4.0: Recording/FlushFrameBuffer.asm (Have to keep old ones for backward compatibility) - {0x8006da34, true}, // 3.4.0: Recording/SendGamePostFrame.asm - {0x8016d884, true}, // 3.7.0: Recording/SendGameEnd.asm + {0x8008d698, true}, // Recording/GetLCancelStatus/GetLCancelStatus.asm + {0x8006c324, true}, // Recording/GetLCancelStatus/ResetLCancelStatus.asm + {0x800679bc, true}, // Recording/ExtendPlayerBlock.asm + {0x802fef88, true}, // Recording/FlushFrameBuffer.asm + {0x80005604, true}, // Recording/IsVSMode.asm + {0x8016d30c, true}, // Recording/SendGameEnd.asm + {0x8016e74c, true}, // Recording/SendGameInfo.asm + {0x8006c5d8, true}, // Recording/SendGamePostFrame.asm + {0x8006b0dc, true}, // Recording/SendGamePreFrame.asm + {0x803219ec, true}, // 3.4.0: Recording/FlushFrameBuffer.asm (Have to keep old ones for + // backward compatibility) + {0x8006da34, true}, // 3.4.0: Recording/SendGamePostFrame.asm + {0x8016d884, true}, // 3.7.0: Recording/SendGameEnd.asm - {0x8021aae4, true}, // Binary/FasterMeleeSettings/DisableFdTransitions.bin - {0x801cbb90, true}, // Binary/FasterMeleeSettings/LaglessFod.bin - {0x801CC8AC, true}, // Binary/FasterMeleeSettings/LaglessFod.bin - {0x801CBE9C, true}, // Binary/FasterMeleeSettings/LaglessFod.bin - {0x801CBEF0, true}, // Binary/FasterMeleeSettings/LaglessFod.bin - {0x801CBF54, true}, // Binary/FasterMeleeSettings/LaglessFod.bin - {0x80390838, true}, // Binary/FasterMeleeSettings/LaglessFod.bin - {0x801CD250, true}, // Binary/FasterMeleeSettings/LaglessFod.bin - {0x801CCDCC, true}, // Binary/FasterMeleeSettings/LaglessFod.bin - {0x801C26B0, true}, // Binary/FasterMeleeSettings/RandomStageMusic.bin - {0x803761ec, true}, // Binary/NormalLagReduction.bin - {0x800198a4, true}, // Binary/PerformanceLagReduction.bin - {0x80019620, true}, // Binary/PerformanceLagReduction.bin - {0x801A5054, true}, // Binary/PerformanceLagReduction.bin - {0x80397878, true}, // Binary/OsReportPrintOnCrash.bin - {0x801A4DA0, true}, // Binary/LagReduction/PD.bin - {0x801A4DB4, true}, // Binary/LagReduction/PD.bin - {0x80019860, true}, // Binary/LagReduction/PD.bin - {0x801A4C24, true}, // Binary/LagReduction/PD+VB.bin - {0x8001985C, true}, // Binary/LagReduction/PD+VB.bin - {0x80019860, true}, // Binary/LagReduction/PD+VB.bin - {0x80376200, true}, // Binary/LagReduction/PD+VB.bin - {0x801A5018, true}, // Binary/LagReduction/PD+VB.bin - {0x80218D68, true}, // Binary/LagReduction/PD+VB.bin - {0x8016E9AC, true}, // Binary/Force2PCenterHud.bin - {0x80030E44, true}, // Binary/DisableScreenShake.bin + {0x8021aae4, true}, // Binary/FasterMeleeSettings/DisableFdTransitions.bin + {0x801cbb90, true}, // Binary/FasterMeleeSettings/LaglessFod.bin + {0x801CC8AC, true}, // Binary/FasterMeleeSettings/LaglessFod.bin + {0x801CBE9C, true}, // Binary/FasterMeleeSettings/LaglessFod.bin + {0x801CBEF0, true}, // Binary/FasterMeleeSettings/LaglessFod.bin + {0x801CBF54, true}, // Binary/FasterMeleeSettings/LaglessFod.bin + {0x80390838, true}, // Binary/FasterMeleeSettings/LaglessFod.bin + {0x801CD250, true}, // Binary/FasterMeleeSettings/LaglessFod.bin + {0x801CCDCC, true}, // Binary/FasterMeleeSettings/LaglessFod.bin + {0x801C26B0, true}, // Binary/FasterMeleeSettings/RandomStageMusic.bin + {0x803761ec, true}, // Binary/NormalLagReduction.bin + {0x800198a4, true}, // Binary/PerformanceLagReduction.bin + {0x80019620, true}, // Binary/PerformanceLagReduction.bin + {0x801A5054, true}, // Binary/PerformanceLagReduction.bin + {0x80397878, true}, // Binary/OsReportPrintOnCrash.bin + {0x801A4DA0, true}, // Binary/LagReduction/PD.bin + {0x801A4DB4, true}, // Binary/LagReduction/PD.bin + {0x80019860, true}, // Binary/LagReduction/PD.bin + {0x801A4C24, true}, // Binary/LagReduction/PD+VB.bin + {0x8001985C, true}, // Binary/LagReduction/PD+VB.bin + {0x80019860, true}, // Binary/LagReduction/PD+VB.bin + {0x80376200, true}, // Binary/LagReduction/PD+VB.bin + {0x801A5018, true}, // Binary/LagReduction/PD+VB.bin + {0x80218D68, true}, // Binary/LagReduction/PD+VB.bin - {0x800055f0, true}, // Common/EXITransferBuffer.asm - {0x800055f8, true}, // Common/GetIsFollower.asm - {0x800055fc, true}, // Common/Gecko/ProcessCodeList.asm - {0x8016d294, true}, // Common/IncrementFrameIndex.asm + {0x800055f0, true}, // Common/EXITransferBuffer.asm + {0x800055f8, true}, // Common/GetIsFollower.asm + {0x800055fc, true}, // Common/Gecko/ProcessCodeList.asm + {0x8016d294, true}, // Common/IncrementFrameIndex.asm - {0x801a5b14, true}, // External/Salty Runback/Salty Runback.asm - {0x801a4570, true}, // External/LagReduction/ForceHD/480pDeflickerOff.asm - {0x802fccd8, true}, // External/Hide Nametag When Invisible/Hide Nametag When Invisible.asm + {0x801a5b14, true}, // External/Salty Runback/Salty Runback.asm + {0x801a4570, true}, // External/LagReduction/ForceHD/480pDeflickerOff.asm + {0x802fccd8, true}, // External/Hide Nametag When Invisible/Hide Nametag When Invisible.asm - {0x804ddb30, - true}, // External/Widescreen/Adjust Offscreen Scissor/Fix Bubble Positions/Adjust Corner Value 1.asm - {0x804ddb34, - true}, // External/Widescreen/Adjust Offscreen Scissor/Fix Bubble Positions/Adjust Corner Value 2.asm - {0x804ddb2c, true}, // External/Widescreen/Adjust Offscreen Scissor/Fix Bubble Positions/Extend Negative - // Vertical Bound.asm - {0x804ddb28, true}, // External/Widescreen/Adjust Offscreen Scissor/Fix Bubble Positions/Extend Positive - // Vertical Bound.asm - {0x804ddb4c, true}, // External/Widescreen/Adjust Offscreen Scissor/Fix Bubble Positions/Widen Bubble Region.asm - {0x804ddb58, true}, // External/Widescreen/Adjust Offscreen Scissor/Adjust Bubble Zoom.asm - {0x80086b24, true}, // External/Widescreen/Adjust Offscreen Scissor/Draw High Poly Models.asm - {0x80030C7C, true}, // External/Widescreen/Adjust Offscreen Scissor/Left Camera Bound.asm - {0x80030C88, true}, // External/Widescreen/Adjust Offscreen Scissor/Right Camera Bound.asm - {0x802fcfc4, true}, // External/Widescreen/Nametag Fixes/Adjust Nametag Background X Scale.asm - {0x804ddb84, true}, // External/Widescreen/Nametag Fixes/Adjust Nametag Text X Scale.asm - {0x803BB05C, true}, // External/Widescreen/Fix Screen Flash.asm - {0x8036A4A8, true}, // External/Widescreen/Overwrite CObj Values.asm - {0x800C0148, true}, // External/FlashRedFailedLCancel/ChangeColor.asm - {0x8008D690, true}, // External/FlashRedFailedLCancel/TriggerColor.asm + {0x804ddb30, true}, // External/Widescreen/Adjust Offscreen Scissor/Fix Bubble + // Positions/Adjust Corner Value 1.asm + {0x804ddb34, true}, // External/Widescreen/Adjust Offscreen Scissor/Fix Bubble + // Positions/Adjust Corner Value 2.asm + {0x804ddb2c, true}, // External/Widescreen/Adjust Offscreen Scissor/Fix Bubble + // Positions/Extend Negative Vertical Bound.asm + {0x804ddb28, true}, // External/Widescreen/Adjust Offscreen Scissor/Fix Bubble + // Positions/Extend Positive Vertical Bound.asm + {0x804ddb4c, true}, // External/Widescreen/Adjust Offscreen Scissor/Fix Bubble + // Positions/Widen Bubble Region.asm + {0x804ddb58, true}, // External/Widescreen/Adjust Offscreen Scissor/Adjust Bubble Zoom.asm + {0x80086b24, true}, // External/Widescreen/Adjust Offscreen Scissor/Draw High Poly Models.asm + {0x80030C7C, true}, // External/Widescreen/Adjust Offscreen Scissor/Left Camera Bound.asm + {0x80030C88, true}, // External/Widescreen/Adjust Offscreen Scissor/Right Camera Bound.asm + {0x802fcfc4, + true}, // External/Widescreen/Nametag Fixes/Adjust Nametag Background X Scale.asm + {0x804ddb84, true}, // External/Widescreen/Nametag Fixes/Adjust Nametag Text X Scale.asm + {0x803BB05C, true}, // External/Widescreen/Fix Screen Flash.asm + {0x8036A4A8, true}, // External/Widescreen/Overwrite CObj Values.asm + {0x800C0148, true}, // External/FlashRedFailedLCancel/ChangeColor.asm + {0x8008D690, true}, // External/FlashRedFailedLCancel/TriggerColor.asm - {0x801A4DB4, true}, // Online/Core/ForceEngineOnRollback.asm - {0x8016D310, true}, // Online/Core/HandleLRAS.asm - {0x8034DED8, true}, // Online/Core/HandleRumble.asm - {0x8016E748, true}, // Online/Core/InitOnlinePlay.asm - {0x8016e904, true}, // Online/Core/InitPause.asm - {0x801a5014, true}, // Online/Core/LoopEngineForRollback.asm - {0x801a4de4, true}, // Online/Core/StartEngineLoop.asm - {0x80376A28, true}, // Online/Core/TriggerSendInput.asm - {0x801a4cb4, true}, // Online/Core/EXIFileLoad/AllocBuffer.asm - {0x800163fc, true}, // Online/Core/EXIFileLoad/GetFileSize.asm - {0x800166b8, true}, // Online/Core/EXIFileLoad/TransferFile.asm - {0x80019260, true}, // Online/Core/Hacks/ForceNoDiskCrash.asm - {0x80376304, true}, // Online/Core/Hacks/ForceNoVideoAssert.asm - {0x80321d70, true}, // Online/Core/Hacks/PreventCharacterCrowdChants.asm - {0x80019608, true}, // Online/Core/Hacks/PreventPadAlarmDuringRollback.asm - {0x8038D224, true}, // Online/Core/Sound/AssignSoundInstanceId.asm - {0x80088224, true}, // Online/Core/Sound/NoDestroyVoice.asm - {0x800882B0, true}, // Online/Core/Sound/NoDestroyVoice2.asm - {0x8038D0B0, true}, // Online/Core/Sound/PreventDuplicateSounds.asm - {0x803775b8, true}, // Online/Logging/LogInputOnCopy.asm - {0x8016e9b4, true}, // Online/Menus/InGame/InitInGame.asm - {0x80185050, true}, // Online/Menus/VSScreen/HideStageDisplay/PreventEarlyR3Overwrite.asm - {0x80184b1c, true}, // Online/Menus/VSScreen/HideStageText/SkipStageNumberShow.asm - {0x801A45BC, true}, // Online/Slippi Online Scene/main.asm - {0x801a45b8, true}, // Online/Slippi Online Scene/main.asm (https://bit.ly/3kxohf4) - {0x801BFA20, true}, // Online/Slippi Online Scene/boot.asm - {0x800cc818, true}, // External/GreenDuringWait/fall.asm - {0x8008a478, true}, // External/GreenDuringWait/wait.asm - - {0x802f6690, true}, // HUD Transparency v1.1 + {0x8006A880, true}, // Online/Core/BrawlOffscreenDamage.asm + {0x801A4DB4, true}, // Online/Core/ForceEngineOnRollback.asm + {0x8016D310, true}, // Online/Core/HandleLRAS.asm + {0x8034DED8, true}, // Online/Core/HandleRumble.asm + {0x8016E748, true}, // Online/Core/InitOnlinePlay.asm + {0x8016e904, true}, // Online/Core/InitPause.asm + {0x801a5014, true}, // Online/Core/LoopEngineForRollback.asm + {0x801a4de4, true}, // Online/Core/StartEngineLoop.asm + {0x80376A28, true}, // Online/Core/TriggerSendInput.asm + {0x801a4cb4, true}, // Online/Core/EXIFileLoad/AllocBuffer.asm + {0x800163fc, true}, // Online/Core/EXIFileLoad/GetFileSize.asm + {0x800166b8, true}, // Online/Core/EXIFileLoad/TransferFile.asm + {0x80019260, true}, // Online/Core/Hacks/ForceNoDiskCrash.asm + {0x80376304, true}, // Online/Core/Hacks/ForceNoVideoAssert.asm + {0x80321d70, true}, // Online/Core/Hacks/PreventCharacterCrowdChants.asm + {0x80019608, true}, // Online/Core/Hacks/PreventPadAlarmDuringRollback.asm + {0x8038D224, true}, // Online/Core/Sound/AssignSoundInstanceId.asm + {0x80088224, true}, // Online/Core/Sound/NoDestroyVoice.asm + {0x800882B0, true}, // Online/Core/Sound/NoDestroyVoice2.asm + {0x8038D0B0, true}, // Online/Core/Sound/PreventDuplicateSounds.asm + {0x803775b8, true}, // Online/Logging/LogInputOnCopy.asm + {0x8016e9b4, true}, // Online/Menus/InGame/InitInGame.asm + {0x80185050, true}, // Online/Menus/VSScreen/HideStageDisplay/PreventEarlyR3Overwrite.asm + {0x80184b1c, true}, // Online/Menus/VSScreen/HideStageText/SkipStageNumberShow.asm + {0x801A45BC, true}, // Online/Slippi Online Scene/main.asm + {0x801BFA20, true}, // Online/Slippi Online Scene/boot.asm }; std::unordered_map blacklist; @@ -1030,8 +1079,8 @@ void CEXISlippi::prepareGeckoList() // Some codes should only be blacklisted when not displaying rollbacks, these are codes // that are required for things to not break when using Slippi savestates. Perhaps this // should be handled by actually applying these codes in the playback ASM instead? not sure - blacklist[0x8038add0] = true; // Online/Core/PreventFileAlarms/PreventMusicAlarm.asm - blacklist[0x80023FFC] = true; // Online/Core/PreventFileAlarms/MuteMusic.asm + blacklist[0x8038add0] = true; // Online/Core/PreventFileAlarms/PreventMusicAlarm.asm + blacklist[0x80023FFC] = true; // Online/Core/PreventFileAlarms/MuteMusic.asm } geckoList.clear(); @@ -1050,16 +1099,18 @@ void CEXISlippi::prepareGeckoList() while (idx < source.size()) { u8 codeType = source[idx] & 0xFE; - u32 address = source[idx] << 24 | source[idx + 1] << 16 | source[idx + 2] << 8 | source[idx + 3]; + u32 address = + source[idx] << 24 | source[idx + 1] << 16 | source[idx + 2] << 8 | source[idx + 3]; address = (address & 0x01FFFFFF) | 0x80000000; - u32 codeOffset = 8; // Default code offset. Most codes are this length + u32 codeOffset = 8; // Default code offset. Most codes are this length switch (codeType) { case 0xC0: case 0xC2: { - u32 lineCount = source[idx + 4] << 24 | source[idx + 5] << 16 | source[idx + 6] << 8 | source[idx + 7]; + u32 lineCount = + source[idx + 4] << 24 | source[idx + 5] << 16 | source[idx + 6] << 8 | source[idx + 7]; codeOffset = 8 + (lineCount * 8); break; } @@ -1068,8 +1119,10 @@ void CEXISlippi::prepareGeckoList() break; case 0x06: { - u32 byteLen = source[idx + 4] << 24 | source[idx + 5] << 16 | source[idx + 6] << 8 | source[idx + 7]; - codeOffset = 8 + ((byteLen + 7) & 0xFFFFFFF8); // Round up to next 8 bytes and add the first 8 bytes + u32 byteLen = + source[idx + 4] << 24 | source[idx + 5] << 16 | source[idx + 6] << 8 | source[idx + 7]; + codeOffset = + 8 + ((byteLen + 7) & 0xFFFFFFF8); // Round up to next 8 bytes and add the first 8 bytes break; } } @@ -1080,15 +1133,15 @@ void CEXISlippi::prepareGeckoList() if (blacklist.count(address)) continue; - INFO_LOG(SLIPPI, "Codetype [%x] Inserting section: %d - %d (%x, %d)", codeType, idx - codeOffset, idx, address, - codeOffset); + INFO_LOG(SLIPPI, "Codetype [%x] Inserting section: %d - %d (%x, %d)", codeType, + idx - codeOffset, idx, address, codeOffset); // If not blacklisted, add code to return vector geckoList.insert(geckoList.end(), source.begin() + (idx - codeOffset), source.begin() + idx); } // Add the termination sequence - geckoList.insert(geckoList.end(), { 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }); + geckoList.insert(geckoList.end(), {0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); } void CEXISlippi::prepareCharacterFrameData(Slippi::FrameData* frame, u8 port, u8 isFollower) @@ -1110,27 +1163,27 @@ void CEXISlippi::prepareCharacterFrameData(Slippi::FrameData* frame, u8 port, u8 // Get data for this player Slippi::PlayerFrameData data = source[port]; - // log << frameIndex << "\t" << port << "\t" << data.locationX << "\t" << data.locationY << "\t" << - // data.animation + // log << frameIndex << "\t" << port << "\t" << data.locationX << "\t" << data.locationY << "\t" + // << data.animation // << "\n"; - // WARN_LOG(EXPANSIONINTERFACE, "[Frame %d] [Player %d] Positions: %f | %f", frameIndex, port, data.locationX, - // data.locationY); + // WARN_LOG(EXPANSIONINTERFACE, "[Frame %d] [Player %d] Positions: %f | %f", frameIndex, port, + // data.locationX, data.locationY); // Add all of the inputs in order appendWordToBuffer(&m_read_queue, data.randomSeed); - appendWordToBuffer(&m_read_queue, *(u32*)& data.joystickX); - appendWordToBuffer(&m_read_queue, *(u32*)& data.joystickY); - appendWordToBuffer(&m_read_queue, *(u32*)& data.cstickX); - appendWordToBuffer(&m_read_queue, *(u32*)& data.cstickY); - appendWordToBuffer(&m_read_queue, *(u32*)& data.trigger); + appendWordToBuffer(&m_read_queue, *(u32*)&data.joystickX); + appendWordToBuffer(&m_read_queue, *(u32*)&data.joystickY); + appendWordToBuffer(&m_read_queue, *(u32*)&data.cstickX); + appendWordToBuffer(&m_read_queue, *(u32*)&data.cstickY); + appendWordToBuffer(&m_read_queue, *(u32*)&data.trigger); appendWordToBuffer(&m_read_queue, data.buttons); - appendWordToBuffer(&m_read_queue, *(u32*)& data.locationX); - appendWordToBuffer(&m_read_queue, *(u32*)& data.locationY); - appendWordToBuffer(&m_read_queue, *(u32*)& data.facingDirection); + appendWordToBuffer(&m_read_queue, *(u32*)&data.locationX); + appendWordToBuffer(&m_read_queue, *(u32*)&data.locationY); + appendWordToBuffer(&m_read_queue, *(u32*)&data.facingDirection); appendWordToBuffer(&m_read_queue, (u32)data.animation); m_read_queue.push_back(data.joystickXRaw); - appendWordToBuffer(&m_read_queue, *(u32*)& data.percent); + appendWordToBuffer(&m_read_queue, *(u32*)&data.percent); // NOTE TO DEV: If you add data here, make sure to increase the size above } @@ -1269,13 +1322,14 @@ void CEXISlippi::prepareFrameData(u8* payload) if (requestResultCode == FRAME_RESP_TERMINATE) { - ERROR_LOG(EXPANSIONINTERFACE, "Game should terminate on frame %d [%X]", frameIndex, frameIndex); + ERROR_LOG(EXPANSIONINTERFACE, "Game should terminate on frame %d [%X]", frameIndex, + frameIndex); } return; } - u8 rollbackCode = 0; // 0 = not rollback, 1 = rollback, perhaps other options in the future? + u8 rollbackCode = 0; // 0 = not rollback, 1 = rollback, perhaps other options in the future? // Increment frame index if greater if (frameIndex > g_playbackStatus->currentPlaybackFrame) @@ -1291,7 +1345,7 @@ void CEXISlippi::prepareFrameData(u8* payload) if (shouldFFW) { WARN_LOG(SLIPPI, "[Frame %d] FFW frame, behind by: %d frames.", frameIndex, - g_playbackStatus->lastFrame - frameIndex); + g_playbackStatus->lastFrame - frameIndex); g_playbackStatus->lastFFWFrame = frameIndex; } @@ -1332,7 +1386,7 @@ void CEXISlippi::prepareFrameData(u8* payload) // Add frame rng seed to be restored at priority 0 u8 rngResult = frame->randomSeedExists ? 1 : 0; m_read_queue.push_back(rngResult); - appendWordToBuffer(&m_read_queue, *(u32*)& frame->randomSeed); + appendWordToBuffer(&m_read_queue, *(u32*)&frame->randomSeed); // Add frame data for every character for (u8 port = 0; port < 4; port++) @@ -1413,7 +1467,8 @@ bool CEXISlippi::isDisconnected() return true; auto status = slippi_netplay->GetSlippiConnectStatus(); - return status != SlippiNetplayClient::SlippiConnectStatus::NET_CONNECT_STATUS_CONNECTED || isConnectionStalled; + return status != SlippiNetplayClient::SlippiConnectStatus::NET_CONNECT_STATUS_CONNECTED || + isConnectionStalled; } static int tempTestCount = 0; @@ -1425,7 +1480,7 @@ void CEXISlippi::handleOnlineInputs(u8* payload) if (isDisconnected()) { - m_read_queue.push_back(3); // Indicate we disconnected + m_read_queue.push_back(3); // Indicate we disconnected return; } @@ -1464,8 +1519,10 @@ void CEXISlippi::handleOnlineInputs(u8* payload) bool CEXISlippi::shouldSkipOnlineFrame(s32 frame) { auto status = slippi_netplay->GetSlippiConnectStatus(); - bool connectionFailed = status == SlippiNetplayClient::SlippiConnectStatus::NET_CONNECT_STATUS_FAILED; - bool connectionDisconnected = status == SlippiNetplayClient::SlippiConnectStatus::NET_CONNECT_STATUS_DISCONNECTED; + bool connectionFailed = + status == SlippiNetplayClient::SlippiConnectStatus::NET_CONNECT_STATUS_FAILED; + bool connectionDisconnected = + status == SlippiNetplayClient::SlippiConnectStatus::NET_CONNECT_STATUS_DISCONNECTED; if (connectionFailed || connectionDisconnected) { // If connection failed just continue the game @@ -1489,8 +1546,9 @@ bool CEXISlippi::shouldSkipOnlineFrame(s32 frame) isConnectionStalled = true; } - WARN_LOG(SLIPPI_ONLINE, "Halting for one frame due to rollback limit (frame: %d | latest: %d)...", frame, - latestRemoteFrame); + WARN_LOG(SLIPPI_ONLINE, + "Halting for one frame due to rollback limit (frame: %d | latest: %d)...", frame, + latestRemoteFrame); return true; } @@ -1498,10 +1556,10 @@ bool CEXISlippi::shouldSkipOnlineFrame(s32 frame) // Return true if we are over 60% of a frame ahead of our opponent. Currently limiting how // often this happens because I'm worried about jittery data causing a lot of unneccesary delays. - // Only skip once for a given frame because our time detection method doesn't take into consideration - // waiting for a frame. Also it's less jarring and it happens often enough that it will smoothly - // get to the right place - auto isTimeSyncFrame = frame % SLIPPI_ONLINE_LOCKSTEP_INTERVAL; // Only time sync every 30 frames + // Only skip once for a given frame because our time detection method doesn't take into + // consideration waiting for a frame. Also it's less jarring and it happens often enough that it + // will smoothly get to the right place + auto isTimeSyncFrame = frame % SLIPPI_ONLINE_LOCKSTEP_INTERVAL; // Only time sync every 30 frames if (isTimeSyncFrame == 0 && !isCurrentlySkipping) { auto offsetUs = slippi_netplay->CalcTimeOffsetUs(); @@ -1511,12 +1569,13 @@ bool CEXISlippi::shouldSkipOnlineFrame(s32 frame) { isCurrentlySkipping = true; - int maxSkipFrames = frame <= 120 ? 5 : 1; // On early frames, support skipping more frames + int maxSkipFrames = frame <= 120 ? 5 : 1; // On early frames, support skipping more frames framesToSkip = ((offsetUs - 10000) / 16683) + 1; - framesToSkip = framesToSkip > maxSkipFrames ? maxSkipFrames : framesToSkip; // Only skip 5 frames max + framesToSkip = + framesToSkip > maxSkipFrames ? maxSkipFrames : framesToSkip; // Only skip 5 frames max - WARN_LOG(SLIPPI_ONLINE, "Halting on frame %d due to time sync. Offset: %d us. Frames: %d...", frame, - offsetUs, framesToSkip); + WARN_LOG(SLIPPI_ONLINE, "Halting on frame %d due to time sync. Offset: %d us. Frames: %d...", + frame, offsetUs, framesToSkip); } } @@ -1551,15 +1610,16 @@ void CEXISlippi::prepareOpponentInputs(u8* payload) { m_read_queue.clear(); - u8 frameResult = 1; // Indicates to continue frame + u8 frameResult = 1; // Indicates to continue frame auto state = slippi_netplay->GetSlippiConnectStatus(); - if (state != SlippiNetplayClient::SlippiConnectStatus::NET_CONNECT_STATUS_CONNECTED || isConnectionStalled) + if (state != SlippiNetplayClient::SlippiConnectStatus::NET_CONNECT_STATUS_CONNECTED || + isConnectionStalled) { - frameResult = 3; // Indicates we have disconnected + frameResult = 3; // Indicates we have disconnected } - m_read_queue.push_back(frameResult); // Indicate a continue frame + m_read_queue.push_back(frameResult); // Indicate a continue frame int32_t frame = payload[0] << 24 | payload[1] << 16 | payload[2] << 8 | payload[3]; @@ -1571,7 +1631,7 @@ void CEXISlippi::prepareOpponentInputs(u8* payload) // add latest frame we are transfering to begining of return buf int32_t latestFrame = offset > 0 ? frame : result->latestFrame; - appendWordToBuffer(&m_read_queue, *(u32*)& latestFrame); + appendWordToBuffer(&m_read_queue, *(u32*)&latestFrame); // copy pad data over auto txStart = result->data.begin() + offset; @@ -1583,8 +1643,9 @@ void CEXISlippi::prepareOpponentInputs(u8* payload) m_read_queue.insert(m_read_queue.end(), tx.begin(), tx.end()); - // ERROR_LOG(SLIPPI_ONLINE, "EXI: [%d] %X %X %X %X %X %X %X %X", latestFrame, m_read_queue[5], m_read_queue[6], - // m_read_queue[7], m_read_queue[8], m_read_queue[9], m_read_queue[10], m_read_queue[11], m_read_queue[12]); + // ERROR_LOG(SLIPPI_ONLINE, "EXI: [%d] %X %X %X %X %X %X %X %X", latestFrame, m_read_queue[5], + // m_read_queue[6], m_read_queue[7], m_read_queue[8], m_read_queue[9], m_read_queue[10], + // m_read_queue[11], m_read_queue[12]); } void CEXISlippi::handleCaptureSavestate(u8* payload) @@ -1625,7 +1686,7 @@ void CEXISlippi::handleCaptureSavestate(u8* payload) u32 timeDiff = (u32)(Common::Timer::GetTimeUs() - startTime); INFO_LOG(SLIPPI_ONLINE, "SLIPPI ONLINE: Captured savestate for frame %d in: %f ms", frame, - ((double)timeDiff) / 1000); + ((double)timeDiff) / 1000); } void CEXISlippi::handleLoadSavestate(u8* payload) @@ -1649,7 +1710,8 @@ void CEXISlippi::handleLoadSavestate(u8* payload) int idx = 0; while (Common::swap32(preserveArr[idx]) != 0) { - SlippiSavestate::PreserveBlock p = { Common::swap32(preserveArr[idx]), Common::swap32(preserveArr[idx + 1]) }; + SlippiSavestate::PreserveBlock p = {Common::swap32(preserveArr[idx]), + Common::swap32(preserveArr[idx + 1])}; blocks.push_back(p); idx += 2; } @@ -1666,7 +1728,8 @@ void CEXISlippi::handleLoadSavestate(u8* payload) activeSavestates.clear(); u32 timeDiff = (u32)(Common::Timer::GetTimeUs() - startTime); - INFO_LOG(SLIPPI_ONLINE, "SLIPPI ONLINE: Loaded savestate for frame %d in: %f ms", frame, ((double)timeDiff) / 1000); + INFO_LOG(SLIPPI_ONLINE, "SLIPPI ONLINE: Loaded savestate for frame %d in: %f ms", frame, + ((double)timeDiff) / 1000); } void CEXISlippi::startFindMatch(u8* payload) @@ -1685,9 +1748,9 @@ void CEXISlippi::startFindMatch(u8* payload) // Store this search so we know what was queued for lastSearch = search; - // While we do have another condition that checks characters after being connected, it's nice to give - // someone an early error before they even queue so that they wont enter the queue and make someone - // else get force removed from queue and have to requeue + // While we do have another condition that checks characters after being connected, it's nice to + // give someone an early error before they even queue so that they wont enter the queue and make + // someone else get force removed from queue and have to requeue auto directMode = SlippiMatchmaking::OnlinePlayMode::DIRECT; if (search.mode != directMode && localSelections.characterId >= 26) { @@ -1712,34 +1775,38 @@ void CEXISlippi::startFindMatch(u8* payload) void CEXISlippi::prepareOnlineMatchState() { - // This match block is a VS match with P1 Red Falco vs P2 Red Bowser on Battlefield. The proper values will - // be overwritten + // This match block is a VS match with P1 Red Falco vs P2 Red Bowser on Battlefield. The proper + // values will be overwritten static std::vector onlineMatchBlock = { - 0x32, 0x01, 0x86, 0x4C, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x6E, 0x00, 0x1F, 0x00, 0x00, - 0x01, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x78, 0x00, - 0xC0, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, - 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x05, 0x00, 0x04, 0x01, 0x00, 0x01, 0x00, 0x00, 0x09, 0x00, 0x78, 0x00, - 0xC0, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, - 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x1A, 0x03, 0x04, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x09, 0x00, 0x78, 0x00, - 0x40, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, - 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x1A, 0x03, 0x04, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x09, 0x00, 0x78, 0x00, - 0x40, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, - 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x21, 0x03, 0x04, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x09, 0x00, 0x78, 0x00, - 0x40, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, - 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x21, 0x03, 0x04, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x09, 0x00, 0x78, 0x00, - 0x40, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, - 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, + 0x32, 0x01, 0x86, 0x4C, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x6E, 0x00, + 0x1F, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x3F, + 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, + 0x00, 0x78, 0x00, 0xC0, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x05, 0x00, 0x04, + 0x01, 0x00, 0x01, 0x00, 0x00, 0x09, 0x00, 0x78, 0x00, 0xC0, 0x00, 0x04, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, + 0x80, 0x00, 0x00, 0x1A, 0x03, 0x04, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x09, 0x00, 0x78, 0x00, + 0x40, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, + 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x1A, 0x03, 0x04, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x09, 0x00, 0x78, 0x00, 0x40, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, + 0x21, 0x03, 0x04, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x09, 0x00, 0x78, 0x00, 0x40, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, + 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x21, 0x03, 0x04, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x09, + 0x00, 0x78, 0x00, 0x40, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, }; m_read_queue.clear(); auto errorState = SlippiMatchmaking::ProcessState::ERROR_ENCOUNTERED; - SlippiMatchmaking::ProcessState mmState = !forcedError.empty() ? errorState : matchmaking->GetMatchmakeState(); + SlippiMatchmaking::ProcessState mmState = + !forcedError.empty() ? errorState : matchmaking->GetMatchmakeState(); #ifdef LOCAL_TESTING if (localSelections.isCharacterSelected || isLocalConnected) @@ -1749,7 +1816,7 @@ void CEXISlippi::prepareOnlineMatchState() } #endif - m_read_queue.push_back(mmState); // Matchmaking State + m_read_queue.push_back(mmState); // Matchmaking State u8 localPlayerReady = localSelections.isCharacterSelected; u8 remotePlayerReady = 0; @@ -1757,7 +1824,7 @@ void CEXISlippi::prepareOnlineMatchState() u8 remotePlayerIndex = 1; auto opponent = matchmaking->GetOpponent(); - std::string oppName = opponent.displayName; + std::string oppName = opponent.display_name; auto userInfo = user->GetUserInfo(); if (mmState == SlippiMatchmaking::ProcessState::CONNECTION_SUCCESS) @@ -1777,7 +1844,8 @@ void CEXISlippi::prepareOnlineMatchState() bool isConnected = true; #else auto status = slippi_netplay->GetSlippiConnectStatus(); - bool isConnected = status == SlippiNetplayClient::SlippiConnectStatus::NET_CONNECT_STATUS_CONNECTED; + bool isConnected = + status == SlippiNetplayClient::SlippiConnectStatus::NET_CONNECT_STATUS_CONNECTED; #endif if (isConnected) @@ -1808,10 +1876,10 @@ void CEXISlippi::prepareOnlineMatchState() slippi_netplay = nullptr; } - m_read_queue.push_back(localPlayerReady); // Local player ready - m_read_queue.push_back(remotePlayerReady); // Remote player ready - m_read_queue.push_back(localPlayerIndex); // Local player index - m_read_queue.push_back(remotePlayerIndex); // Remote player index + m_read_queue.push_back(localPlayerReady); // Local player ready + m_read_queue.push_back(remotePlayerReady); // Remote player ready + m_read_queue.push_back(localPlayerIndex); // Local player index + m_read_queue.push_back(remotePlayerIndex); // Remote player index u32 rngOffset = 0; std::string p1Name = ""; @@ -1855,8 +1923,8 @@ void CEXISlippi::prepareOnlineMatchState() onlineMatchBlock[0x63 + remotePlayerIndex * 0x24] = rps.characterColor; // Make one character lighter if same character, same color - bool isSheikVsZelda = - lps.characterId == 0x12 && rps.characterId == 0x13 || lps.characterId == 0x13 && rps.characterId == 0x12; + bool isSheikVsZelda = lps.characterId == 0x12 && rps.characterId == 0x13 || + lps.characterId == 0x13 && rps.characterId == 0x12; bool charMatch = lps.characterId == rps.characterId || isSheikVsZelda; bool colMatch = lps.characterColor == rps.characterColor; @@ -1877,20 +1945,21 @@ void CEXISlippi::prepareOnlineMatchState() // u32 *timer = (u32 *)&onlineMatchBlock[0x10]; //*timer = Common::swap32(seconds * 60); - u16* stage = (u16*)& onlineMatchBlock[0xE]; + u16* stage = (u16*)&onlineMatchBlock[0xE]; *stage = Common::swap16(stageId); // Set rng offset rngOffset = isDecider ? lps.rngOffset : rps.rngOffset; WARN_LOG(SLIPPI_ONLINE, "Rng Offset: 0x%x", rngOffset); - WARN_LOG(SLIPPI_ONLINE, "P1 Char: 0x%X, P2 Char: 0x%X", onlineMatchBlock[0x60], onlineMatchBlock[0x84]); + WARN_LOG(SLIPPI_ONLINE, "P1 Char: 0x%X, P2 Char: 0x%X", onlineMatchBlock[0x60], + onlineMatchBlock[0x84]); // Set player names - p1Name = isDecider ? userInfo.displayName : oppName; - p2Name = isDecider ? oppName : userInfo.displayName; + p1Name = isDecider ? userInfo.display_name : oppName; + p2Name = isDecider ? oppName : userInfo.display_name; // Turn pause on in direct, off in everything else - u8* gameBitField3 = (u8*)& onlineMatchBlock[2]; + u8* gameBitField3 = (u8*)&onlineMatchBlock[2]; *gameBitField3 = lastSearch.mode == directMode ? *gameBitField3 & 0xF7 : *gameBitField3 | 0x8; } @@ -1922,12 +1991,12 @@ u16 CEXISlippi::getRandomStage() static u16 selectedStage; static std::vector stages = { - 0x2, // FoD - 0x3, // Pokemon - 0x8, // Yoshi's Story - 0x1C, // Dream Land - 0x1F, // Battlefield - 0x20, // Final Destination + 0x2, // FoD + 0x3, // Pokemon + 0x8, // Yoshi's Story + 0x1C, // Dream Land + 0x1F, // Battlefield + 0x20, // Final Destination }; // Reset stage pool if it's empty @@ -1977,7 +2046,7 @@ void CEXISlippi::prepareFileLength(u8* payload) { m_read_queue.clear(); - std::string fileName((char*)& payload[0]); + std::string fileName((char*)&payload[0]); std::string contents; u32 size = gameFileLoader->LoadFile(fileName, contents); @@ -1992,7 +2061,7 @@ void CEXISlippi::prepareFileLoad(u8* payload) { m_read_queue.clear(); - std::string fileName((char*)& payload[0]); + std::string fileName((char*)&payload[0]); std::string contents; u32 size = gameFileLoader->LoadFile(fileName, contents); @@ -2009,12 +2078,12 @@ void CEXISlippi::logMessageFromGame(u8* payload) if (payload[0] == 0) { // The first byte indicates whether to log the time or not - GENERIC_LOG(Common::Log::SLIPPI, (Common::Log::LOG_LEVELS)payload[1], "%s", (char*)& payload[2]); + GENERIC_LOG(Common::Log::SLIPPI, (Common::Log::LOG_LEVELS)payload[1], "%s", (char*)&payload[2]); } else { - GENERIC_LOG(Common::Log::SLIPPI, (Common::Log::LOG_LEVELS)payload[1], "%s: %llu", (char*)& payload[2], - Common::Timer::GetTimeUs()); + GENERIC_LOG(Common::Log::SLIPPI, (Common::Log::LOG_LEVELS)payload[1], "%s: %llu", + (char*)&payload[2], Common::Timer::GetTimeUs()); } } @@ -2038,9 +2107,12 @@ void CEXISlippi::handleLogOutRequest() void CEXISlippi::handleUpdateAppRequest() { +#ifdef __APPLE__ + CriticalAlertT("Automatic updates are not available for macOS, please get the latest update from " + "slippi.gg/netplay."); +#else Host_LowerWindow(); user->UpdateApp(); -#ifdef _WIN32 Host_Exit(); #endif } @@ -2056,7 +2128,7 @@ void CEXISlippi::prepareOnlineStatus() if (isLoggedIn) { // Check if we have the latest version, and if not, indicate we need to update - version::Semver200_version latestVersion(userInfo.latestVersion); + version::Semver200_version latestVersion(userInfo.latest_version); version::Semver200_version currentVersion(Common::scm_slippi_semver_str); appState = latestVersion > currentVersion ? 2 : 1; @@ -2065,19 +2137,20 @@ void CEXISlippi::prepareOnlineStatus() m_read_queue.push_back(appState); // Write player name (31 bytes) - std::string playerName = ConvertStringForGame(userInfo.displayName, MAX_NAME_LENGTH); + std::string playerName = ConvertStringForGame(userInfo.display_name, MAX_NAME_LENGTH); m_read_queue.insert(m_read_queue.end(), playerName.begin(), playerName.end()); // Write connect code (10 bytes) - std::string connectCode = userInfo.connectCode; - char shiftJisHashtag[] = { '\x81', '\x94', '\x00' }; + std::string connectCode = userInfo.connect_code; + char shiftJisHashtag[] = {'\x81', '\x94', '\x00'}; connectCode.resize(CONNECT_CODE_LENGTH); connectCode = ReplaceAll(connectCode, "#", shiftJisHashtag); auto codeBuf = connectCode.c_str(); m_read_queue.insert(m_read_queue.end(), codeBuf, codeBuf + CONNECT_CODE_LENGTH + 2); } -void doConnectionCleanup(std::unique_ptr mm, std::unique_ptr nc) +void doConnectionCleanup(std::unique_ptr mm, + std::unique_ptr nc) { if (mm) mm.reset(); @@ -2142,7 +2215,7 @@ void CEXISlippi::DMAWrite(u32 _uAddr, u32 _uSize) u8 byte = memPtr[0]; if (byte == CMD_RECEIVE_COMMANDS) { - time(&gameStartTime); // Store game start time + time(&gameStartTime); // Store game start time u8 receiveCommandsLen = memPtr[1]; configureCommands(&memPtr[1], receiveCommandsLen); writeToFileAsync(&memPtr[0], receiveCommandsLen + 1, "create"); @@ -2158,9 +2231,10 @@ void CEXISlippi::DMAWrite(u32 _uAddr, u32 _uSize) g_needInputForFrame = true; } - INFO_LOG(EXPANSIONINTERFACE, "EXI SLIPPI DMAWrite: addr: 0x%08x size: %d, bufLoc:[%02x %02x %02x %02x %02x]", - _uAddr, _uSize, memPtr[bufLoc], memPtr[bufLoc + 1], memPtr[bufLoc + 2], memPtr[bufLoc + 3], - memPtr[bufLoc + 4]); + INFO_LOG(EXPANSIONINTERFACE, + "EXI SLIPPI DMAWrite: addr: 0x%08x size: %d, bufLoc:[%02x %02x %02x %02x %02x]", _uAddr, + _uSize, memPtr[bufLoc], memPtr[bufLoc + 1], memPtr[bufLoc + 2], memPtr[bufLoc + 3], + memPtr[bufLoc + 4]); while (bufLoc < _uSize) { @@ -2265,11 +2339,12 @@ void CEXISlippi::DMARead(u32 addr, u32 size) return; } - m_read_queue.resize(size, 0); // Resize response array to make sure it's all full/allocated + m_read_queue.resize(size, 0); // Resize response array to make sure it's all full/allocated auto queueAddr = &m_read_queue[0]; - INFO_LOG(EXPANSIONINTERFACE, "EXI SLIPPI DMARead: addr: 0x%08x size: %d, startResp: [%02x %02x %02x %02x %02x]", - addr, size, queueAddr[0], queueAddr[1], queueAddr[2], queueAddr[3], queueAddr[4]); + INFO_LOG(EXPANSIONINTERFACE, + "EXI SLIPPI DMARead: addr: 0x%08x size: %d, startResp: [%02x %02x %02x %02x %02x]", addr, + size, queueAddr[0], queueAddr[1], queueAddr[2], queueAddr[3], queueAddr[4]); // Copy buffer data to memory Memory::CopyToEmu(addr, queueAddr, size); @@ -2280,5 +2355,7 @@ bool CEXISlippi::IsPresent() const return true; } -void CEXISlippi::TransferByte(u8& byte) {} +void CEXISlippi::TransferByte(u8& byte) +{ } +} // namespace ExpansionInterface diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceSlippi.h b/Source/Core/Core/HW/EXI/EXI_DeviceSlippi.h index 554da5b7f7..19782513fd 100644 --- a/Source/Core/Core/HW/EXI/EXI_DeviceSlippi.h +++ b/Source/Core/Core/HW/EXI/EXI_DeviceSlippi.h @@ -7,9 +7,8 @@ #include #include "Common/CommonTypes.h" -#include "Common/FileUtil.h" #include "Common/File.h" -#include "EXI_Device.h" +#include "Common/FileUtil.h" #include "Core/Slippi/SlippiGameFileLoader.h" #include "Core/Slippi/SlippiMatchmaking.h" #include "Core/Slippi/SlippiNetplay.h" @@ -18,6 +17,7 @@ #include "Core/Slippi/SlippiSavestate.h" #include "Core/Slippi/SlippiSpectate.h" #include "Core/Slippi/SlippiUser.h" +#include "EXI_Device.h" #define ROLLBACK_MAX_FRAMES 7 #define MAX_NAME_LENGTH 15 @@ -25,67 +25,68 @@ namespace ExpansionInterface { - // Emulated Slippi device used to receive and respond to in-game messages - class CEXISlippi : public IEXIDevice +// Emulated Slippi device used to receive and respond to in-game messages +class CEXISlippi : public IEXIDevice +{ +public: + CEXISlippi(); + virtual ~CEXISlippi(); + + void DMAWrite(u32 _uAddr, u32 _uSize) override; + void DMARead(u32 addr, u32 size) override; + + bool IsPresent() const override; + +private: + enum { - public: - CEXISlippi(); - virtual ~CEXISlippi(); + CMD_UNKNOWN = 0x0, - void DMAWrite(u32 _uAddr, u32 _uSize) override; - void DMARead(u32 addr, u32 size) override; + // Recording + CMD_RECEIVE_COMMANDS = 0x35, + CMD_RECEIVE_GAME_INFO = 0x36, + CMD_RECEIVE_POST_FRAME_UPDATE = 0x38, + CMD_RECEIVE_GAME_END = 0x39, + CMD_FRAME_BOOKEND = 0x3C, + CMD_MENU_FRAME = 0x3E, - bool IsPresent() const override; + // Playback + CMD_PREPARE_REPLAY = 0x75, + CMD_READ_FRAME = 0x76, + CMD_GET_LOCATION = 0x77, + CMD_IS_FILE_READY = 0x88, + CMD_IS_STOCK_STEAL = 0x89, + CMD_GET_GECKO_CODES = 0x8A, - private: - enum - { - CMD_UNKNOWN = 0x0, + // Online + CMD_ONLINE_INPUTS = 0xB0, + CMD_CAPTURE_SAVESTATE = 0xB1, + CMD_LOAD_SAVESTATE = 0xB2, + CMD_GET_MATCH_STATE = 0xB3, + CMD_FIND_OPPONENT = 0xB4, + CMD_SET_MATCH_SELECTIONS = 0xB5, + CMD_OPEN_LOGIN = 0xB6, + CMD_LOGOUT = 0xB7, + CMD_UPDATE = 0xB8, + CMD_GET_ONLINE_STATUS = 0xB9, + CMD_CLEANUP_CONNECTION = 0xBA, + CMD_GET_NEW_SEED = 0xBC, - // Recording - CMD_RECEIVE_COMMANDS = 0x35, - CMD_RECEIVE_GAME_INFO = 0x36, - CMD_RECEIVE_POST_FRAME_UPDATE = 0x38, - CMD_RECEIVE_GAME_END = 0x39, - CMD_FRAME_BOOKEND = 0x3C, - CMD_MENU_FRAME = 0x3E, + // Misc + CMD_LOG_MESSAGE = 0xD0, + CMD_FILE_LENGTH = 0xD1, + CMD_FILE_LOAD = 0xD2, + }; - // Playback - CMD_PREPARE_REPLAY = 0x75, - CMD_READ_FRAME = 0x76, - CMD_GET_LOCATION = 0x77, - CMD_IS_FILE_READY = 0x88, - CMD_IS_STOCK_STEAL = 0x89, - CMD_GET_GECKO_CODES = 0x8A, + enum + { + FRAME_RESP_WAIT = 0, + FRAME_RESP_CONTINUE = 1, + FRAME_RESP_TERMINATE = 2, + FRAME_RESP_FASTFORWARD = 3, + }; - // Online - CMD_ONLINE_INPUTS = 0xB0, - CMD_CAPTURE_SAVESTATE = 0xB1, - CMD_LOAD_SAVESTATE = 0xB2, - CMD_GET_MATCH_STATE = 0xB3, - CMD_FIND_OPPONENT = 0xB4, - CMD_SET_MATCH_SELECTIONS = 0xB5, - CMD_OPEN_LOGIN = 0xB6, - CMD_LOGOUT = 0xB7, - CMD_UPDATE = 0xB8, - CMD_GET_ONLINE_STATUS = 0xB9, - CMD_CLEANUP_CONNECTION = 0xBA, - CMD_GET_NEW_SEED = 0xBC, - // Misc - CMD_LOG_MESSAGE = 0xD0, - CMD_FILE_LENGTH = 0xD1, - CMD_FILE_LOAD = 0xD2, - }; - - enum - { - FRAME_RESP_WAIT = 0, - FRAME_RESP_CONTINUE = 1, - FRAME_RESP_TERMINATE = 2, - FRAME_RESP_FASTFORWARD = 3, - }; - - std::unordered_map payloadSizes = { + std::unordered_map payloadSizes = { // The actual size of this command will be sent in one byte // after the command is received. The other receive command IDs // and sizes will be received immediately following @@ -113,117 +114,120 @@ namespace ExpansionInterface {CMD_GET_ONLINE_STATUS, 0}, {CMD_CLEANUP_CONNECTION, 0}, {CMD_GET_NEW_SEED, 0}, + // Misc - {CMD_LOG_MESSAGE, 0xFFFF}, // Variable size... will only work if by itself + {CMD_LOG_MESSAGE, 0xFFFF}, // Variable size... will only work if by itself {CMD_FILE_LENGTH, 0x40}, {CMD_FILE_LOAD, 0x40}, - }; - - struct WriteMessage - { - std::vector data; - std::string operation; - }; - - // .slp File creation stuff - u32 writtenByteCount = 0; - - // vars for metadata generation - time_t gameStartTime; - s32 lastFrame; - std::unordered_map> characterUsage; - - void updateMetadataFields(u8* payload, u32 length); - void configureCommands(u8* payload, u8 length); - void writeToFileAsync(u8* payload, u32 length, std::string fileOption); - void writeToFile(std::unique_ptr msg); - std::vector generateMetadata(); - void createNewFile(); - void closeFile(); - std::string generateFileName(); - bool checkFrameFullyFetched(s32 frameIndex); - - // std::ofstream log; - - File::IOFile m_file; - std::vector m_payload; - - // online play stuff - u16 getRandomStage(); - bool isDisconnected(); - void handleOnlineInputs(u8* payload); - void prepareOpponentInputs(u8* payload); - void handleSendInputs(u8* payload); - void handleCaptureSavestate(u8* payload); - void handleLoadSavestate(u8* payload); - void startFindMatch(u8* payload); - void prepareOnlineMatchState(); - void setMatchSelections(u8* payload); - bool shouldSkipOnlineFrame(s32 frame); - void handleLogInRequest(); - void handleLogOutRequest(); - void handleUpdateAppRequest(); - void prepareOnlineStatus(); - void handleConnectionCleanup(); - void prepareNewSeed(); - - // replay playback stuff - void prepareGameInfo(u8* payload); - void prepareGeckoList(); - void prepareCharacterFrameData(Slippi::FrameData* frame, u8 port, u8 isFollower); - void prepareFrameData(u8* payload); - void prepareIsStockSteal(u8* payload); - void prepareIsFileReady(); - - // misc stuff - void logMessageFromGame(u8* payload); - void prepareFileLength(u8* payload); - void prepareFileLoad(u8* payload); - - void FileWriteThread(void); - - std::queue> fileWriteQueue; - bool writeThreadRunning = false; - std::thread m_fileWriteThread; - - std::unordered_map getNetplayNames(); - - std::vector playbackSavestatePayload; - std::vector geckoList; - - u32 stallFrameCount = 0; - bool isConnectionStalled = false; - - std::vector m_read_queue; - std::unique_ptr m_current_game = nullptr; - SlippiMatchmaking::MatchSearchSettings lastSearch; - - std::vector stagePool; - - u32 frameSeqIdx = 0; - - bool isEnetInitialized = false; - - std::default_random_engine generator; - - std::string forcedError = ""; - - // Frame skipping variables - int framesToSkip = 0; - bool isCurrentlySkipping = false; - - protected: - void TransferByte(u8& byte) override; - - private: - SlippiPlayerSelections localSelections; - - std::unique_ptr user; - std::unique_ptr gameFileLoader; - std::unique_ptr slippi_netplay; - std::unique_ptr matchmaking; - - std::map> activeSavestates; - std::deque> availableSavestates; }; -} + + struct WriteMessage + { + std::vector data; + std::string operation; + }; + + // .slp File creation stuff + u32 writtenByteCount = 0; + + // vars for metadata generation + time_t gameStartTime; + s32 lastFrame; + std::unordered_map> characterUsage; + + void updateMetadataFields(u8* payload, u32 length); + void configureCommands(u8* payload, u8 length); + void writeToFileAsync(u8* payload, u32 length, std::string fileOption); + void writeToFile(std::unique_ptr msg); + std::vector generateMetadata(); + void createNewFile(); + void closeFile(); + std::string generateFileName(); + bool checkFrameFullyFetched(s32 frameIndex); + // bool shouldFFWFrame(s32 frameIndex); + + // std::ofstream log; + + File::IOFile m_file; + std::vector m_payload; + + // online play stuff + u16 getRandomStage(); + bool isDisconnected(); + void handleOnlineInputs(u8* payload); + void prepareOpponentInputs(u8* payload); + void handleSendInputs(u8* payload); + void handleCaptureSavestate(u8* payload); + void handleLoadSavestate(u8* payload); + void startFindMatch(u8* payload); + void prepareOnlineMatchState(); + void setMatchSelections(u8* payload); + bool shouldSkipOnlineFrame(s32 frame); + void handleLogInRequest(); + void handleLogOutRequest(); + void handleUpdateAppRequest(); + void prepareOnlineStatus(); + void handleConnectionCleanup(); + void prepareNewSeed(); + + // replay playback stuff + void prepareGameInfo(u8* payload); + void prepareGeckoList(); + void prepareCharacterFrameData(Slippi::FrameData* frame, u8 port, u8 isFollower); + void prepareFrameData(u8* payload); + void prepareIsStockSteal(u8* payload); + void prepareIsFileReady(); + + // misc stuff + void logMessageFromGame(u8* payload); + void prepareFileLength(u8* payload); + void prepareFileLoad(u8* payload); + + void FileWriteThread(void); + + std::queue> fileWriteQueue; + bool writeThreadRunning = false; + std::thread m_fileWriteThread; + + std::unordered_map getNetplayNames(); + + std::vector playbackSavestatePayload; + std::vector geckoList; + + u32 stallFrameCount = 0; + bool isConnectionStalled = false; + + std::vector m_read_queue; + std::unique_ptr m_current_game = nullptr; + SlippiSpectateServer* m_slippiserver = nullptr; + SlippiMatchmaking::MatchSearchSettings lastSearch; + + std::vector stagePool; + + u32 frameSeqIdx = 0; + + bool isEnetInitialized = false; + + std::default_random_engine generator; + + std::string forcedError = ""; + + // Frame skipping variables + int framesToSkip = 0; + bool isCurrentlySkipping = false; + +protected: + void TransferByte(u8& byte) override; + +private: + SlippiPlayerSelections localSelections; + + std::unique_ptr user; + std::unique_ptr gameFileLoader; + std::unique_ptr slippi_netplay; + std::unique_ptr matchmaking; + + std::map> activeSavestates; + std::deque> availableSavestates; +}; +} // namespace ExpansionInterface diff --git a/Source/Core/Core/Slippi/SlippiGameFileLoader.cpp b/Source/Core/Core/Slippi/SlippiGameFileLoader.cpp index e1ce3fc849..0e4bdd936a 100644 --- a/Source/Core/Core/Slippi/SlippiGameFileLoader.cpp +++ b/Source/Core/Core/Slippi/SlippiGameFileLoader.cpp @@ -1,18 +1,18 @@ #include "SlippiGameFileLoader.h" -#include "Common/Logging/Log.h" -#include "Common/FileUtil.h" #include "Common/File.h" -#include "Core/HW/DVD/DVDThread.h" +#include "Common/FileUtil.h" +#include "Common/Logging/Log.h" #include "Core/Boot/Boot.h" -#include "Core/Core.h" #include "Core/ConfigManager.h" +#include "Core/Core.h" +#include "Core/HW/DVD/DVDThread.h" std::string getFilePath(std::string fileName) { std::string dirPath = File::GetSysDirectory(); - std::string filePath = dirPath + "GameFiles/GALE01/" + fileName; // TODO: Handle other games? + std::string filePath = dirPath + "GameFiles/GALE01/" + fileName; // TODO: Handle other games? if (File::Exists(filePath)) { @@ -49,8 +49,10 @@ u32 SlippiGameFileLoader::LoadFile(std::string fileName, std::string& data) std::string fileContents; File::ReadFileToString(gameFilePath, fileContents); - // If the file was a diff file and the game is running, load the main file from ISO and apply patch - if (gameFilePath.substr(gameFilePath.length() - 5) == ".diff" && Core::GetState() == Core::State::Running) + // If the file was a diff file and the game is running, load the main file from ISO and apply + // patch + if (gameFilePath.substr(gameFilePath.length() - 5) == ".diff" && + Core::GetState() == Core::State::Running) { std::vector buf; INFO_LOG(SLIPPI, "Will process diff"); diff --git a/Source/Core/Core/Slippi/SlippiGameFileLoader.h b/Source/Core/Core/Slippi/SlippiGameFileLoader.h index 5bc5f25360..d066ab9236 100644 --- a/Source/Core/Core/Slippi/SlippiGameFileLoader.h +++ b/Source/Core/Core/Slippi/SlippiGameFileLoader.h @@ -1,10 +1,10 @@ #pragma once -#include "Common/CommonTypes.h" #include #include #include #include +#include "Common/CommonTypes.h" class SlippiGameFileLoader { diff --git a/Source/Core/Core/Slippi/SlippiMatchmaking.cpp b/Source/Core/Core/Slippi/SlippiMatchmaking.cpp index 9f9e093fe3..7b46235d77 100644 --- a/Source/Core/Core/Slippi/SlippiMatchmaking.cpp +++ b/Source/Core/Core/Slippi/SlippiMatchmaking.cpp @@ -1,11 +1,11 @@ #include "SlippiMatchmaking.h" +#include +#include #include "Common/Common.h" -#include "Common/Version.h" #include "Common/ENetUtil.h" #include "Common/Logging/Log.h" #include "Common/StringUtil.h" -#include -#include +#include "Common/Version.h" class MmMessageType { @@ -28,7 +28,8 @@ SlippiMatchmaking::SlippiMatchmaking(SlippiUser* user) m_client = nullptr; m_server = nullptr; - MM_HOST = Common::scm_slippi_semver_str.find("dev") == std::string::npos ? MM_HOST_PROD : MM_HOST_DEV; + MM_HOST = + Common::scm_slippi_semver_str.find("dev") == std::string::npos ? MM_HOST_PROD : MM_HOST_DEV; generator = std::default_random_engine(Common::Timer::GetTimeMs()); } @@ -116,7 +117,8 @@ int SlippiMatchmaking::receiveMessage(json& msg, int timeoutMs) case ENET_EVENT_TYPE_RECEIVE: { std::vector buf; - buf.insert(buf.end(), netEvent.packet->data, netEvent.packet->data + netEvent.packet->dataLength); + buf.insert(buf.end(), netEvent.packet->data, + netEvent.packet->data + netEvent.packet->dataLength); std::string str(buf.begin(), buf.end()); INFO_LOG(SLIPPI_ONLINE, "[Matchmaking] Received: %s", str.c_str()); @@ -286,13 +288,13 @@ void SlippiMatchmaking::startMatchmaking() std::vector connectCodeBuf; connectCodeBuf.insert(connectCodeBuf.end(), m_searchSettings.connectCode.begin(), - m_searchSettings.connectCode.end()); + m_searchSettings.connectCode.end()); // Send message to server to create ticket json request; request["type"] = MmMessageType::CREATE_TICKET; - request["user"] = { {"uid", userInfo.uid}, {"playKey", userInfo.playKey} }; - request["search"] = { {"mode", m_searchSettings.mode}, {"connectCode", connectCodeBuf} }; + request["user"] = {{"uid", userInfo.uid}, {"playKey", userInfo.play_key}}; + request["search"] = {{"mode", m_searchSettings.mode}, {"connectCode", connectCodeBuf}}; request["appVersion"] = Common::scm_slippi_semver_str; sendMessage(request); @@ -301,7 +303,8 @@ void SlippiMatchmaking::startMatchmaking() int rcvRes = receiveMessage(response, 5000); if (rcvRes != 0) { - ERROR_LOG(SLIPPI_ONLINE, "[Matchmaking] Did not receive response from server for create ticket"); + ERROR_LOG(SLIPPI_ONLINE, + "[Matchmaking] Did not receive response from server for create ticket"); m_state = ProcessState::ERROR_ENCOUNTERED; m_errorMsg = "Failed to join mm queue"; return; @@ -369,7 +372,8 @@ void SlippiMatchmaking::handleMatchmaking() if (latestVersion != "") { // Update file to get new version number when the mm server tells us our version is outdated - m_user->OverwriteLatestVersion(latestVersion); // Force latest version for people whose file updates dont work + m_user->OverwriteLatestVersion( + latestVersion); // Force latest version for people whose file updates dont work } ERROR_LOG(SLIPPI_ONLINE, "[Matchmaking] Received error from server for get ticket"); @@ -391,15 +395,16 @@ void SlippiMatchmaking::handleMatchmaking() if (oppUser.is_object()) { m_oppUser.uid = oppUser.value("uid", ""); - m_oppUser.displayName = oppUser.value("displayName", ""); - m_oppUser.connectCode = oppUser.value("connectCode", ""); + m_oppUser.display_name = oppUser.value("displayName", ""); + m_oppUser.connect_code = oppUser.value("connectCode", ""); } // Disconnect and destroy enet client to mm server terminateMmConnection(); m_state = ProcessState::OPPONENT_CONNECTING; - ERROR_LOG(SLIPPI_ONLINE, "[Matchmaking] Opponent found. isDecider: %s", m_isHost ? "true" : "false"); + ERROR_LOG(SLIPPI_ONLINE, "[Matchmaking] Opponent found. isDecider: %s", + m_isHost ? "true" : "false"); } void SlippiMatchmaking::handleConnecting() @@ -407,7 +412,8 @@ void SlippiMatchmaking::handleConnecting() std::vector ipParts = SplitString(m_oppIp, ':'); // Is host is now used to specify who the decider is - auto client = std::make_unique(ipParts[0], std::stoi(ipParts[1]), m_hostPort, m_isHost); + auto client = std::make_unique(ipParts[0], std::stoi(ipParts[1]), m_hostPort, + m_isHost); while (!m_netplayClient) { @@ -425,7 +431,8 @@ void SlippiMatchmaking::handleConnecting() } else if (status != SlippiNetplayClient::SlippiConnectStatus::NET_CONNECT_STATUS_CONNECTED) { - ERROR_LOG(SLIPPI_ONLINE, "[Matchmaking] Connection attempt failed, looking for someone else."); + ERROR_LOG(SLIPPI_ONLINE, + "[Matchmaking] Connection attempt failed, looking for someone else."); // Return to the start to get a new ticket to find someone else we can hopefully connect with m_netplayClient = nullptr; diff --git a/Source/Core/Core/Slippi/SlippiMatchmaking.h b/Source/Core/Core/Slippi/SlippiMatchmaking.h index af369f0fba..be4b042a51 100644 --- a/Source/Core/Core/Slippi/SlippiMatchmaking.h +++ b/Source/Core/Core/Slippi/SlippiMatchmaking.h @@ -6,9 +6,9 @@ #include "Core/Slippi/SlippiUser.h" #include +#include #include #include -#include #include using json = nlohmann::json; @@ -51,8 +51,8 @@ public: SlippiUser::UserInfo GetOpponent(); protected: - const std::string MM_HOST_DEV = "35.197.121.196"; // Dev host - const std::string MM_HOST_PROD = "35.247.98.48"; // Production host + const std::string MM_HOST_DEV = "35.197.121.196"; // Dev host + const std::string MM_HOST_PROD = "35.247.98.48"; // Production host const u16 MM_PORT = 43113; std::string MM_HOST = ""; diff --git a/Source/Core/Core/Slippi/SlippiNetplay.cpp b/Source/Core/Core/Slippi/SlippiNetplay.cpp index 64a5f9a0f9..a068ef976a 100644 --- a/Source/Core/Core/Slippi/SlippiNetplay.cpp +++ b/Source/Core/Core/Slippi/SlippiNetplay.cpp @@ -11,10 +11,10 @@ #include "Common/MD5.h" #include "Common/MsgHandler.h" #include "Common/Timer.h" -#include "Core/ConfigManager.h" -#include "Core/NetPlayProto.h" -#include "Core/Core.h" #include "Core/Config/NetplaySettings.h" +#include "Core/ConfigManager.h" +#include "Core/Core.h" +#include "Core/NetPlayProto.h" //#include "Core/HW/EXI_DeviceIPL.h" //#include "Core/HW/SI.h" //#include "Core/HW/SI_DeviceGCController.h" @@ -22,16 +22,16 @@ #include "Core/HW/WiimoteEmu/WiimoteEmu.h" #include "Core/HW/WiimoteReal/WiimoteReal.h" //#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_emu.h" -#include "Core/Movie.h" -#include "InputCommon/GCAdapter.h" -#include "VideoCommon/OnScreenDisplay.h" -#include "VideoCommon/VideoConfig.h" #include #include #include #include #include #include +#include "Core/Movie.h" +#include "InputCommon/GCAdapter.h" +#include "VideoCommon/OnScreenDisplay.h" +#include "VideoCommon/VideoConfig.h" static std::mutex pad_mutex; static std::mutex ack_mutex; @@ -62,25 +62,26 @@ SlippiNetplayClient::~SlippiNetplayClient() } // called from ---SLIPPI EXI--- thread -SlippiNetplayClient::SlippiNetplayClient(const std::string& address, const u16 remotePort, const u16 localPort, - bool isDecider) +SlippiNetplayClient::SlippiNetplayClient(const std::string& address, const u16 remotePort, + const u16 localPort, bool isDecider) #ifdef _WIN32 - : m_qos_handle(nullptr) - , m_qos_flow_id(0) + : m_qos_handle(nullptr), m_qos_flow_id(0) #endif { WARN_LOG(SLIPPI_ONLINE, "Initializing Slippi Netplay for port: %d, with host: %s", localPort, - isDecider ? "true" : "false"); + isDecider ? "true" : "false"); this->isDecider = isDecider; + // this->playerIdx = isDecider ? 0 : 1; // Local address ENetAddress* localAddr = nullptr; ENetAddress localAddrDef; - // It is important to be able to set the local port to listen on even in a client connection because - // not doing so will break hole punching, the host is expecting traffic to come from a specific ip/port - // and if the port does not match what it is expecting, it will not get through the NAT on some routers + // It is important to be able to set the local port to listen on even in a client connection + // because not doing so will break hole punching, the host is expecting traffic to come from a + // specific ip/port and if the port does not match what it is expecting, it will not get through + // the NAT on some routers if (localPort > 0) { INFO_LOG(SLIPPI_ONLINE, "Setting up local address"); @@ -91,7 +92,8 @@ SlippiNetplayClient::SlippiNetplayClient(const std::string& address, const u16 r localAddr = &localAddrDef; } - // TODO: Figure out how to use a local port when not hosting without accepting incoming connections + // TODO: Figure out how to use a local port when not hosting without accepting incoming + // connections m_client = enet_host_create(localAddr, 2, 3, 0, 0); if (m_client == nullptr) @@ -126,7 +128,8 @@ SlippiNetplayClient::SlippiNetplayClient(bool isDecider) unsigned int SlippiNetplayClient::OnData(sf::Packet& packet) { NetPlay::MessageId mid = 0; - if (!(packet >> mid)) { + if (!(packet >> mid)) + { ERROR_LOG(SLIPPI_ONLINE, "Received empty netplay packet"); return 0; } @@ -136,7 +139,8 @@ unsigned int SlippiNetplayClient::OnData(sf::Packet& packet) case NetPlay::NP_MSG_SLIPPI_PAD: { int32_t frame; - if (!(packet >> frame)) { + if (!(packet >> frame)) + { ERROR_LOG(SLIPPI_ONLINE, "Netplay packet too small to read frame count"); break; } @@ -151,8 +155,8 @@ unsigned int SlippiNetplayClient::OnData(sf::Packet& packet) auto timing = lastFrameTiming; if (!hasGameStarted) { - // Handle case where opponent starts sending inputs before our game has reached frame 1. This will - // continuously say frame 0 is now to prevent opp from getting too far ahead + // Handle case where opponent starts sending inputs before our game has reached frame 1. This + // will continuously say frame 0 is now to prevent opp from getting too far ahead timing.frame = 0; timing.timeUs = curTime; } @@ -161,8 +165,8 @@ unsigned int SlippiNetplayClient::OnData(sf::Packet& packet) s64 frameDiffOffsetUs = 16683 * (timing.frame - frame); s64 timeOffsetUs = opponentSendTimeUs - timing.timeUs + frameDiffOffsetUs; - INFO_LOG(SLIPPI_ONLINE, "[Offset] Opp Frame: %d, My Frame: %d. Time offset: %lld", frame, timing.frame, - timeOffsetUs); + INFO_LOG(SLIPPI_ONLINE, "[Offset] Opp Frame: %d, My Frame: %d. Time offset: %lld", frame, + timing.frame, timeOffsetUs); // Add this offset to circular buffer for use later if (frameOffsetData.buf.size() < SLIPPI_ONLINE_LOCKSTEP_INTERVAL) @@ -173,7 +177,7 @@ unsigned int SlippiNetplayClient::OnData(sf::Packet& packet) frameOffsetData.idx = (frameOffsetData.idx + 1) % SLIPPI_ONLINE_LOCKSTEP_INTERVAL; { - std::lock_guard lk(pad_mutex); // TODO: Is this the correct lock? + std::lock_guard lk(pad_mutex); // TODO: Is this the correct lock? auto packetData = (u8*)packet.getData(); @@ -183,19 +187,22 @@ unsigned int SlippiNetplayClient::OnData(sf::Packet& packet) int inputsToCopy = frame - headFrame; // Check that the packet actually contains the data it claims to - //if ((5 + inputsToCopy * SLIPPI_PAD_DATA_SIZE) > (int)packet.getDataSize()) - //{ - // ERROR_LOG(SLIPPI_ONLINE, "Netplay packet too small to read pad buffer"); - // break; - //} + if ((5 + inputsToCopy * SLIPPI_PAD_DATA_SIZE) > (int)packet.getDataSize()) + { + ERROR_LOG(SLIPPI_ONLINE, + "Netplay packet too small to read pad buffer. Size: %d, Inputs: %d, MinSize: %d", + (int)packet.getDataSize(), inputsToCopy, 5 + inputsToCopy * SLIPPI_PAD_DATA_SIZE); + break; + } for (int i = inputsToCopy - 1; i >= 0; i--) { - auto pad = std::make_unique(frame - i, &packetData[5 + i * SLIPPI_PAD_DATA_SIZE]); + auto pad = + std::make_unique(frame - i, &packetData[5 + i * SLIPPI_PAD_DATA_SIZE]); INFO_LOG(SLIPPI_ONLINE, "Rcv [%d] -> %02X %02X %02X %02X %02X %02X %02X %02X", pad->frame, - pad->padBuf[0], pad->padBuf[1], pad->padBuf[2], pad->padBuf[3], pad->padBuf[4], pad->padBuf[5], - pad->padBuf[6], pad->padBuf[7]); + pad->padBuf[0], pad->padBuf[1], pad->padBuf[2], pad->padBuf[3], pad->padBuf[4], + pad->padBuf[5], pad->padBuf[6], pad->padBuf[7]); remotePadQueue.push_front(std::move(pad)); } @@ -211,11 +218,12 @@ unsigned int SlippiNetplayClient::OnData(sf::Packet& packet) case NetPlay::NP_MSG_SLIPPI_PAD_ACK: { - std::lock_guard lk(ack_mutex); // Trying to fix rare crash on ackTimers.count + std::lock_guard lk(ack_mutex); // Trying to fix rare crash on ackTimers.count // Store last frame acked int32_t frame; - if (!(packet >> frame)) { + if (!(packet >> frame)) + { ERROR_LOG(SLIPPI_ONLINE, "Ack packet too small to read frame"); break; } @@ -240,8 +248,9 @@ unsigned int SlippiNetplayClient::OnData(sf::Packet& packet) pingUs = Common::Timer::GetTimeUs() - sendTime; if (g_ActiveConfig.bShowNetPlayPing && frame % SLIPPI_PING_DISPLAY_INTERVAL == 0) { - OSD::AddTypedMessage(OSD::MessageType::NetPlayPing, StringFromFormat("Ping: %u", pingUs / 1000), - OSD::Duration::NORMAL, OSD::Color::CYAN); + OSD::AddTypedMessage(OSD::MessageType::NetPlayPing, + StringFromFormat("Ping: %u", pingUs / 1000), OSD::Duration::NORMAL, + OSD::Color::CYAN); } } break; @@ -254,15 +263,18 @@ unsigned int SlippiNetplayClient::OnData(sf::Packet& packet) // This might be a good place to reset some logic? Game can't start until we receive this msg // so this should ensure that everything is initialized before the game starts - // TODO: This could cause issues in the case of a desync? If this is ever received mid-game, bad things - // TODO: will happen. Consider improving this hasGameStarted = false; + + // Reset remote pad queue such that next inputs that we get are not compared to inputs from last + // game + remotePadQueue.clear(); } break; case NetPlay::NP_MSG_SLIPPI_CONN_SELECTED: { - // Currently this is unused but the intent is to support two-way simultaneous connection attempts + // Currently this is unused but the intent is to support two-way simultaneous connection + // attempts isConnectionSelected = true; } break; @@ -283,7 +295,8 @@ void SlippiNetplayClient::writeToPacket(sf::Packet& packet, SlippiPlayerSelectio packet << s.rngOffset; } -std::unique_ptr SlippiNetplayClient::readSelectionsFromPacket(sf::Packet& packet) +std::unique_ptr +SlippiNetplayClient::readSelectionsFromPacket(sf::Packet& packet) { auto s = std::make_unique(); @@ -395,26 +408,27 @@ void SlippiNetplayClient::ThreadFunc() bool qos_success = false; #ifdef _WIN32 - QOS_VERSION ver = { 1, 0 }; + QOS_VERSION ver = {1, 0}; if (Config::Get(Config::NETPLAY_ENABLE_QOS) && QOSCreateHandle(&ver, &m_qos_handle)) { // from win32.c - struct sockaddr_in sin = { 0 }; + struct sockaddr_in sin = {0}; sin.sin_family = AF_INET; sin.sin_port = ENET_HOST_TO_NET_16(m_server->host->address.port); sin.sin_addr.s_addr = m_server->host->address.host; if (QOSAddSocketToFlow(m_qos_handle, m_server->host->socket, reinterpret_cast(&sin), - // this is 0x38 - QOSTrafficTypeControl, QOS_NON_ADAPTIVE_FLOW, &m_qos_flow_id)) + // this is 0x38 + QOSTrafficTypeControl, QOS_NON_ADAPTIVE_FLOW, &m_qos_flow_id)) { DWORD dscp = 0x2e; // this will fail if we're not admin // sets DSCP to the same as linux (0x2e) - QOSSetFlow(m_qos_handle, m_qos_flow_id, QOSSetOutgoingDSCPValue, sizeof(DWORD), &dscp, 0, nullptr); + QOSSetFlow(m_qos_handle, m_qos_flow_id, QOSSetOutgoingDSCPValue, sizeof(DWORD), &dscp, 0, + nullptr); qos_success = true; } @@ -431,7 +445,8 @@ void SlippiNetplayClient::ThreadFunc() // https://www.tucny.com/Home/dscp-tos // ef is better than cs7 int tos_val = 0xb8; - qos_success = setsockopt(m_server->host->socket, IPPROTO_IP, IP_TOS, &tos_val, sizeof(tos_val)) == 0; + qos_success = + setsockopt(m_server->host->socket, IPPROTO_IP, IP_TOS, &tos_val, sizeof(tos_val)) == 0; } #endif @@ -458,13 +473,13 @@ void SlippiNetplayClient::ThreadFunc() break; case ENET_EVENT_TYPE_DISCONNECT: ERROR_LOG(SLIPPI_ONLINE, "[Netplay] Disconnected Event detected: %s", - netEvent.peer == m_server ? "same client" : "diff client"); + netEvent.peer == m_server ? "same client" : "diff client"); // If the disconnect event doesn't come from the client we are actually listening to, // it can be safely ignored if (netEvent.peer == m_server) { - m_do_loop.Clear(); // Stop the loop, will trigger a disconnect + m_do_loop.Clear(); // Stop the loop, will trigger a disconnect } break; default: @@ -514,12 +529,7 @@ void SlippiNetplayClient::StartSlippiGame() localPadQueue.clear(); - remotePadQueue.clear(); - for (s32 i = 1; i <= 2; i++) - { - std::unique_ptr pad = std::make_unique(i); - remotePadQueue.push_front(std::move(pad)); - } + // Remote pad should have been cleared when receiving the match selections // Reset match info for next game matchInfo.Reset(); @@ -540,8 +550,10 @@ void SlippiNetplayClient::SendConnectionSelected() void SlippiNetplayClient::SendSlippiPad(std::unique_ptr pad) { auto status = slippiConnectStatus; - bool connectionFailed = status == SlippiNetplayClient::SlippiConnectStatus::NET_CONNECT_STATUS_FAILED; - bool connectionDisconnected = status == SlippiNetplayClient::SlippiConnectStatus::NET_CONNECT_STATUS_DISCONNECTED; + bool connectionFailed = + status == SlippiNetplayClient::SlippiConnectStatus::NET_CONNECT_STATUS_FAILED; + bool connectionDisconnected = + status == SlippiNetplayClient::SlippiConnectStatus::NET_CONNECT_STATUS_DISCONNECTED; if (connectionFailed || connectionDisconnected) { return; @@ -549,8 +561,9 @@ void SlippiNetplayClient::SendSlippiPad(std::unique_ptr pad) // if (pad && isDecider) //{ - // ERROR_LOG(SLIPPI_ONLINE, "[%d] %X %X %X %X %X %X %X %X", pad->frame, pad->padBuf[0], pad->padBuf[1], - // pad->padBuf[2], pad->padBuf[3], pad->padBuf[4], pad->padBuf[5], pad->padBuf[6], pad->padBuf[7]); + // ERROR_LOG(SLIPPI_ONLINE, "[%d] %X %X %X %X %X %X %X %X", pad->frame, pad->padBuf[0], + // pad->padBuf[1], pad->padBuf[2], pad->padBuf[3], pad->padBuf[4], pad->padBuf[5], + // pad->padBuf[6], pad->padBuf[7]); //} if (pad) @@ -577,13 +590,13 @@ void SlippiNetplayClient::SendSlippiPad(std::unique_ptr pad) *spac << static_cast(NetPlay::NP_MSG_SLIPPI_PAD); *spac << frame; - INFO_LOG(SLIPPI_ONLINE, "Sending a packet of inputs [%d]...", frame); + // INFO_LOG(SLIPPI_ONLINE, "Sending a packet of inputs [%d]...", frame); for (auto it = localPadQueue.begin(); it != localPadQueue.end(); ++it) { - INFO_LOG(SLIPPI_ONLINE, "Send [%d] -> %02X %02X %02X %02X %02X %02X %02X %02X", (*it)->frame, (*it)->padBuf[0], - (*it)->padBuf[1], (*it)->padBuf[2], (*it)->padBuf[3], (*it)->padBuf[4], (*it)->padBuf[5], - (*it)->padBuf[6], (*it)->padBuf[7]); - spac->append((*it)->padBuf, SLIPPI_PAD_DATA_SIZE); // only transfer 8 bytes per pad + /*INFO_LOG(SLIPPI_ONLINE, "Send [%d] -> %02X %02X %02X %02X %02X %02X %02X %02X", (*it)->frame, + (*it)->padBuf[0], (*it)->padBuf[1], (*it)->padBuf[2], (*it)->padBuf[3], + (*it)->padBuf[4], (*it)->padBuf[5], (*it)->padBuf[6], (*it)->padBuf[7]);*/ + spac->append((*it)->padBuf, SLIPPI_PAD_DATA_SIZE); // only transfer 8 bytes per pad } SendAsync(std::move(spac)); @@ -616,7 +629,7 @@ void SlippiNetplayClient::SetMatchSelections(SlippiPlayerSelections& s) std::unique_ptr SlippiNetplayClient::GetSlippiRemotePad(int32_t curFrame) { - std::lock_guard lk(pad_mutex); // TODO: Is this the correct lock? + std::lock_guard lk(pad_mutex); // TODO: Is this the correct lock? std::unique_ptr padOutput = std::make_unique(); @@ -662,7 +675,7 @@ u64 SlippiNetplayClient::GetSlippiPing() int32_t SlippiNetplayClient::GetSlippiLatestRemoteFrame() { - std::lock_guard lk(pad_mutex); // TODO: Is this the correct lock? + std::lock_guard lk(pad_mutex); // TODO: Is this the correct lock? if (remotePadQueue.empty()) { @@ -698,7 +711,7 @@ s32 SlippiNetplayClient::CalcTimeOffsetUs() int count = end - offset; if (count <= 0) { - return 0; // What do I return here? + return 0; // What do I return here? } return sum / count; diff --git a/Source/Core/Core/Slippi/SlippiNetplay.h b/Source/Core/Core/Slippi/SlippiNetplay.h index fabe2fbf75..fa5aaf9a87 100644 --- a/Source/Core/Core/Slippi/SlippiNetplay.h +++ b/Source/Core/Core/Slippi/SlippiNetplay.h @@ -4,6 +4,16 @@ #pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "Common/CommonTypes.h" #include "Common/Event.h" #include "Common/Timer.h" @@ -11,22 +21,13 @@ #include "Core/NetPlayProto.h" #include "Core/Slippi/SlippiPad.h" #include "InputCommon/GCPadStatus.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #ifdef _WIN32 #include #endif -#define SLIPPI_ONLINE_LOCKSTEP_INTERVAL 30 // Number of frames to wait before attempting to time-sync +#define SLIPPI_ONLINE_LOCKSTEP_INTERVAL \ + 30 // Number of frames to wait before attempting to time-sync #define SLIPPI_PING_DISPLAY_INTERVAL 60 struct SlippiRemotePadOutput @@ -97,8 +98,9 @@ public: void ThreadFunc(); void SendAsync(std::unique_ptr packet); - SlippiNetplayClient(bool isDecider); // Make a dummy client - SlippiNetplayClient(const std::string& address, const u16 remotePort, const u16 localPort, bool isDecider); + SlippiNetplayClient(bool isDecider); // Make a dummy client + SlippiNetplayClient(const std::string& address, const u16 remotePort, const u16 localPort, + bool isDecider); ~SlippiNetplayClient(); // Slippi Online @@ -140,8 +142,8 @@ protected: std::thread m_thread; std::string m_selected_game; - Common::Flag m_is_running{ false }; - Common::Flag m_do_loop{ true }; + Common::Flag m_is_running{false}; + Common::Flag m_do_loop{true}; unsigned int m_minimum_buffer_size = 6; @@ -167,8 +169,8 @@ protected: bool hasGameStarted = false; FrameTiming lastFrameTiming; u64 pingUs; - std::deque> localPadQueue; // most recent inputs at start of deque - std::deque> remotePadQueue; // most recent inputs at start of deque + std::deque> localPadQueue; // most recent inputs at start of deque + std::deque> remotePadQueue; // most recent inputs at start of deque std::queue ackTimers; SlippiConnectStatus slippiConnectStatus = SlippiConnectStatus::NET_CONNECT_STATUS_UNSET; SlippiMatchInfo matchInfo; diff --git a/Source/Core/Core/Slippi/SlippiPad.cpp b/Source/Core/Core/Slippi/SlippiPad.cpp index 96cdd86823..df0c329227 100644 --- a/Source/Core/Core/Slippi/SlippiPad.cpp +++ b/Source/Core/Core/Slippi/SlippiPad.cpp @@ -5,7 +5,7 @@ #include // TODO: Confirm the default and padding values are right -static u8 emptyPad[SLIPPI_PAD_FULL_SIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +static u8 emptyPad[SLIPPI_PAD_FULL_SIZE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; SlippiPad::SlippiPad(int32_t frame) { diff --git a/Source/Core/Core/Slippi/SlippiPad.h b/Source/Core/Core/Slippi/SlippiPad.h index 101c82e4d9..8b7d2171a8 100644 --- a/Source/Core/Core/Slippi/SlippiPad.h +++ b/Source/Core/Core/Slippi/SlippiPad.h @@ -15,4 +15,3 @@ public: int32_t frame; u8 padBuf[SLIPPI_PAD_FULL_SIZE]; }; - diff --git a/Source/Core/Core/Slippi/SlippiPlayback.cpp b/Source/Core/Core/Slippi/SlippiPlayback.cpp index 1f4c6ac84c..ed440b4aa6 100644 --- a/Source/Core/Core/Slippi/SlippiPlayback.cpp +++ b/Source/Core/Core/Slippi/SlippiPlayback.cpp @@ -86,8 +86,7 @@ void SlippiPlaybackStatus::prepareSlippiPlayback(s32& frameIndex) // TODO: figure out why sometimes playback frame increments past targetFrameNum if (inSlippiPlayback && frameIndex >= targetFrameNum) { - INFO_LOG(SLIPPI, "Reached frame %d. Target was %d. Unblocking", frameIndex, - targetFrameNum); + INFO_LOG(SLIPPI, "Reached frame %d. Target was %d. Unblocking", frameIndex, targetFrameNum); cv_waitingForTargetFrame.notify_one(); } } @@ -101,7 +100,7 @@ void SlippiPlaybackStatus::resetPlayback() if (m_savestateThread.joinable()) m_savestateThread.detach(); - condVar.notify_one(); // Will allow thread to kill itself + condVar.notify_one(); // Will allow thread to kill itself futureDiffs.clear(); futureDiffs.rehash(0); } @@ -122,7 +121,8 @@ void SlippiPlaybackStatus::processInitialState() // Doing it here to get it out of the way and prevent stutters later // Subsequent calls to SaveToBuffer for cState take ~1 frame State::SaveToBuffer(cState); - if (SConfig::GetInstance().m_slippiEnableSeek) { + if (SConfig::GetInstance().m_slippiEnableSeek) + { SConfig::GetInstance().bHideCursor = false; } }; @@ -138,7 +138,8 @@ void SlippiPlaybackStatus::SavestateThread() { // Wait to hit one of the intervals // Possible while rewinding that we hit this wait again. - while (shouldRunThreads && (currentPlaybackFrame - Slippi::PLAYBACK_FIRST_SAVE) % FRAME_INTERVAL != 0) + while (shouldRunThreads && + (currentPlaybackFrame - Slippi::PLAYBACK_FIRST_SAVE) % FRAME_INTERVAL != 0) condVar.wait(intervalLock); if (!shouldRunThreads) @@ -171,11 +172,13 @@ void SlippiPlaybackStatus::SavestateThread() void SlippiPlaybackStatus::seekToFrame() { - if (seekMtx.try_lock()) { + if (seekMtx.try_lock()) + { if (targetFrameNum < Slippi::PLAYBACK_FIRST_SAVE) targetFrameNum = Slippi::PLAYBACK_FIRST_SAVE; - if (targetFrameNum > lastFrame) { + if (targetFrameNum > lastFrame) + { targetFrameNum = lastFrame; } @@ -188,8 +191,10 @@ void SlippiPlaybackStatus::seekToFrame() if (prevState != Core::State::Paused) Core::SetState(Core::State::Paused); - s32 closestStateFrame = targetFrameNum - emod(targetFrameNum - Slippi::PLAYBACK_FIRST_SAVE, FRAME_INTERVAL); - bool isLoadingStateOptimal = targetFrameNum < currentPlaybackFrame || closestStateFrame > currentPlaybackFrame; + s32 closestStateFrame = + targetFrameNum - emod(targetFrameNum - Slippi::PLAYBACK_FIRST_SAVE, FRAME_INTERVAL); + bool isLoadingStateOptimal = + targetFrameNum < currentPlaybackFrame || closestStateFrame > currentPlaybackFrame; if (isLoadingStateOptimal) { @@ -208,7 +213,7 @@ void SlippiPlaybackStatus::seekToFrame() { s32 closestActualStateFrame = closestStateFrame - FRAME_INTERVAL; while (closestActualStateFrame > Slippi::PLAYBACK_FIRST_SAVE && - futureDiffs.count(closestActualStateFrame) == 0) + futureDiffs.count(closestActualStateFrame) == 0) closestActualStateFrame -= FRAME_INTERVAL; loadState(closestActualStateFrame); } @@ -216,10 +221,11 @@ void SlippiPlaybackStatus::seekToFrame() { s32 closestActualStateFrame = closestStateFrame - FRAME_INTERVAL; while (closestActualStateFrame > currentPlaybackFrame && - futureDiffs.count(closestActualStateFrame) == 0) + futureDiffs.count(closestActualStateFrame) == 0) closestActualStateFrame -= FRAME_INTERVAL; - // only load a savestate if we find one past our current frame since we are seeking forwards + // only load a savestate if we find one past our current frame since we are seeking + // forwards if (closestActualStateFrame > currentPlaybackFrame) loadState(closestActualStateFrame); } @@ -236,18 +242,22 @@ void SlippiPlaybackStatus::seekToFrame() setHardFFW(false); } - // We've reached the frame we want. Reset targetFrameNum and release mutex so another seek can be performed + // We've reached the frame we want. Reset targetFrameNum and release mutex so another seek can + // be performed g_playbackStatus->currentPlaybackFrame = targetFrameNum; targetFrameNum = INT_MAX; Core::SetState(prevState); seekMtx.unlock(); - } else { + } + else + { INFO_LOG(SLIPPI, "Already seeking. Ignoring this call"); } } // Set isHardFFW and update OC settings to speed up the FFW -void SlippiPlaybackStatus::setHardFFW(bool enable) { +void SlippiPlaybackStatus::setHardFFW(bool enable) +{ if (enable) { SConfig::GetInstance().m_OCEnable = true; @@ -262,7 +272,6 @@ void SlippiPlaybackStatus::setHardFFW(bool enable) { isHardFFW = enable; } - void SlippiPlaybackStatus::loadState(s32 closestStateFrame) { if (closestStateFrame == Slippi::PLAYBACK_FIRST_SAVE) @@ -270,7 +279,8 @@ void SlippiPlaybackStatus::loadState(s32 closestStateFrame) else { std::string stateString; - decoder.Decode((char*)iState.data(), iState.size(), futureDiffs[closestStateFrame].get(), &stateString); + decoder.Decode((char*)iState.data(), iState.size(), futureDiffs[closestStateFrame].get(), + &stateString); std::vector stateToLoad(stateString.begin(), stateString.end()); State::LoadFromBuffer(stateToLoad); } diff --git a/Source/Core/Core/Slippi/SlippiPlayback.h b/Source/Core/Core/Slippi/SlippiPlayback.h index dfb6fc3d72..8870076a60 100644 --- a/Source/Core/Core/Slippi/SlippiPlayback.h +++ b/Source/Core/Core/Slippi/SlippiPlayback.h @@ -5,12 +5,12 @@ #include #include +#include #include #include -#include -#include "Core/ConfigManager.h" #include "../../Common/CommonTypes.h" +#include "Core/ConfigManager.h" class SlippiPlaybackStatus { @@ -48,9 +48,9 @@ private: void updateWatchSettingsStartEnd(); std::unordered_map> - futureDiffs; // State diffs keyed by frameIndex, processed async - std::vector iState; // The initial state - std::vector cState; // The current (latest) state + futureDiffs; // State diffs keyed by frameIndex, processed async + std::vector iState; // The initial state + std::vector cState; // The current (latest) state open_vcdiff::VCDiffDecoder decoder; open_vcdiff::VCDiffEncoder* encoder = NULL; diff --git a/Source/Core/Core/Slippi/SlippiReplayComm.cpp b/Source/Core/Core/Slippi/SlippiReplayComm.cpp index 1549630838..6930abd687 100644 --- a/Source/Core/Core/Slippi/SlippiReplayComm.cpp +++ b/Source/Core/Core/Slippi/SlippiReplayComm.cpp @@ -1,6 +1,6 @@ +#include "SlippiReplayComm.h" #include #include -#include "SlippiReplayComm.h" #include "Common/CommonPaths.h" #include "Common/FileUtil.h" #include "Common/Logging/LogManager.h" @@ -18,7 +18,8 @@ static inline void ltrim(std::string& s) // trim from end (in place) static inline void rtrim(std::string& s) { - s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) { return !std::isspace(ch); }).base(), s.end()); + s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) { return !std::isspace(ch); }).base(), + s.end()); } // trim from both ends (in place) @@ -31,11 +32,13 @@ static inline void trim(std::string& s) SlippiReplayComm::SlippiReplayComm() { INFO_LOG(EXPANSIONINTERFACE, "SlippiReplayComm: Using playback config path: %s", - SConfig::GetInstance().m_strSlippiInput.c_str()); + SConfig::GetInstance().m_strSlippiInput.c_str()); configFilePath = SConfig::GetInstance().m_strSlippiInput.c_str(); } -SlippiReplayComm::~SlippiReplayComm() {} +SlippiReplayComm::~SlippiReplayComm() +{ +} SlippiReplayComm::CommSettings SlippiReplayComm::getSettings() { @@ -178,8 +181,8 @@ void SlippiReplayComm::loadFile() { WARN_LOG(EXPANSIONINTERFACE, "Comm file load error detected. Check file format"); - // Reset in the case of read error. this fixes a race condition where file mod time changes but - // the file is not readable yet? + // Reset in the case of read error. this fixes a race condition where file mod time changes + // but the file is not readable yet? configLastLoadModTime = 0; } diff --git a/Source/Core/Core/Slippi/SlippiReplayComm.h b/Source/Core/Core/Slippi/SlippiReplayComm.h index b4253e8952..fd9a54b81c 100644 --- a/Source/Core/Core/Slippi/SlippiReplayComm.h +++ b/Source/Core/Core/Slippi/SlippiReplayComm.h @@ -1,10 +1,10 @@ #pragma once +#include #include +#include #include #include -#include -#include #include @@ -32,8 +32,8 @@ public: int endFrame = INT_MAX; bool outputOverlayFiles; bool isRealTimeMode; - bool shouldResync; // If true, logic will attempt to resync games - std::string rollbackDisplayMethod; // off, normal, visible + bool shouldResync; // If true, logic will attempt to resync games + std::string rollbackDisplayMethod; // off, normal, visible std::string commandId; std::queue queue; } CommSettings; diff --git a/Source/Core/Core/Slippi/SlippiSavestate.cpp b/Source/Core/Core/Slippi/SlippiSavestate.cpp index 57d7a2bd72..66b02428f3 100644 --- a/Source/Core/Core/Slippi/SlippiSavestate.cpp +++ b/Source/Core/Core/Slippi/SlippiSavestate.cpp @@ -1,4 +1,5 @@ #include "SlippiSavestate.h" +#include #include "Common/CommonFuncs.h" #include "Common/MemoryUtil.h" #include "Core/HW/AudioInterface.h" @@ -11,7 +12,6 @@ #include "Core/HW/ProcessorInterface.h" #include "Core/HW/SI/SI.h" #include "Core/HW/VideoInterface.h" -#include SlippiSavestate::SlippiSavestate() { @@ -47,52 +47,52 @@ bool cmpFn(SlippiSavestate::PreserveBlock pb1, SlippiSavestate::PreserveBlock pb void SlippiSavestate::initBackupLocs() { static std::vector fullBackupRegions = { - {0x80005520, 0x80005940, nullptr}, // Data Sections 0 and 1 - {0x803b7240, 0x804DEC00, nullptr}, // Data Sections 2-7 and in between sections including BSS + {0x80005520, 0x80005940, nullptr}, // Data Sections 0 and 1 + {0x803b7240, 0x804DEC00, nullptr}, // Data Sections 2-7 and in between sections including BSS // Full Unknown Region: [804fec00 - 80BD5C40) // https://docs.google.com/spreadsheets/d/16ccNK_qGrtPfx4U25w7OWIDMZ-NxN1WNBmyQhaDxnEg/edit?usp=sharing - {0x8065c000, 0x8071b000, nullptr}, // Unknown Region Pt1 - {0x80bb0000, 0x811AD5A0, nullptr}, // Unknown Region Pt2, Heap [80bd5c40 - 811AD5A0) + {0x8065c000, 0x8071b000, nullptr}, // Unknown Region Pt1 + {0x80bb0000, 0x811AD5A0, nullptr}, // Unknown Region Pt2, Heap [80bd5c40 - 811AD5A0) }; static std::vector excludeSections = { - // Sound stuff - {0x804031A0, 0x24}, // [804031A0 - 804031C4) - {0x80407FB4, 0x34C}, // [80407FB4 - 80408300) - {0x80433C64, 0x1EE80}, // [80433C64 - 80452AE4) - {0x804A8D78, 0x17A68}, // [804A8D78 - 804C07E0) - {0x804C28E0, 0x399C}, // [804C28E0 - 804C627C) - {0x804D7474, 0x8}, // [804D7474 - 804D747C) - {0x804D74F0, 0x50}, // [804D74F0 - 804D7540) - {0x804D7548, 0x4}, // [804D7548 - 804D754C) - {0x804D7558, 0x24}, // [804D7558 - 804D757C) - {0x804D7580, 0xC}, // [804D7580 - 804D758C) - {0x804D759C, 0x4}, // [804D759C - 804D75A0) - {0x804D7720, 0x4}, // [804D7720 - 804D7724) - {0x804D7744, 0x4}, // [804D7744 - 804D7748) - {0x804D774C, 0x8}, // [804D774C - 804D7754) - {0x804D7758, 0x8}, // [804D7758 - 804D7760) - {0x804D7788, 0x10}, // [804D7788 - 804D7798) - {0x804D77C8, 0x4}, // [804D77C8 - 804D77CC) - {0x804D77D0, 0x4}, // [804D77D0 - 804D77D4) - {0x804D77E0, 0x4}, // [804D77E0 - 804D77E4) - {0x804DE358, 0x80}, // [804DE358 - 804DE3D8) - {0x804DE800, 0x70}, // [804DE800 - 804DE870) + // Sound stuff + {0x804031A0, 0x24}, // [804031A0 - 804031C4) + {0x80407FB4, 0x34C}, // [80407FB4 - 80408300) + {0x80433C64, 0x1EE80}, // [80433C64 - 80452AE4) + {0x804A8D78, 0x17A68}, // [804A8D78 - 804C07E0) + {0x804C28E0, 0x399C}, // [804C28E0 - 804C627C) + {0x804D7474, 0x8}, // [804D7474 - 804D747C) + {0x804D74F0, 0x50}, // [804D74F0 - 804D7540) + {0x804D7548, 0x4}, // [804D7548 - 804D754C) + {0x804D7558, 0x24}, // [804D7558 - 804D757C) + {0x804D7580, 0xC}, // [804D7580 - 804D758C) + {0x804D759C, 0x4}, // [804D759C - 804D75A0) + {0x804D7720, 0x4}, // [804D7720 - 804D7724) + {0x804D7744, 0x4}, // [804D7744 - 804D7748) + {0x804D774C, 0x8}, // [804D774C - 804D7754) + {0x804D7758, 0x8}, // [804D7758 - 804D7760) + {0x804D7788, 0x10}, // [804D7788 - 804D7798) + {0x804D77C8, 0x4}, // [804D77C8 - 804D77CC) + {0x804D77D0, 0x4}, // [804D77D0 - 804D77D4) + {0x804D77E0, 0x4}, // [804D77E0 - 804D77E4) + {0x804DE358, 0x80}, // [804DE358 - 804DE3D8) + {0x804DE800, 0x70}, // [804DE800 - 804DE870) - // The following need to be added to the ranges proper - {0x804d6030, 0x4}, // ??? - {0x804d603c, 0x4}, // ??? - {0x804d7218, 0x4}, // ??? - {0x804d7228, 0x8}, // ??? - {0x804d7740, 0x4}, // ??? - {0x804d7754, 0x4}, // ??? - {0x804d77bc, 0x4}, // ??? - {0x804de7f0, 0x10}, // ??? + // The following need to be added to the ranges proper + {0x804d6030, 0x4}, // ??? + {0x804d603c, 0x4}, // ??? + {0x804d7218, 0x4}, // ??? + {0x804d7228, 0x8}, // ??? + {0x804d7740, 0x4}, // ??? + {0x804d7754, 0x4}, // ??? + {0x804d77bc, 0x4}, // ??? + {0x804de7f0, 0x10}, // ??? - // Camera Blocks, Temporarily added here - //{0x80452c7c, 0x2B0}, // Cam Block 1, including gaps - //{0x806e516c, 0xA8}, // Cam Block 2, including gaps + // Camera Blocks, Temporarily added here + //{0x80452c7c, 0x2B0}, // Cam Block 1, including gaps + //{0x806e516c, 0xA8}, // Cam Block 2, including gaps }; static std::vector processedLocs = {}; @@ -146,7 +146,7 @@ void SlippiSavestate::initBackupLocs() // Add split section after exclusion if (backupLocs[idx].endAddress > ipb.address + ipb.length) { - ssBackupLoc newLoc = { ipb.address + ipb.length, backupLocs[idx].endAddress, nullptr }; + ssBackupLoc newLoc = {ipb.address + ipb.length, backupLocs[idx].endAddress, nullptr}; backupLocs.insert(backupLocs.begin() + idx + 1, newLoc); } diff --git a/Source/Core/Core/Slippi/SlippiSavestate.h b/Source/Core/Core/Slippi/SlippiSavestate.h index 284df2cf14..30001129ff 100644 --- a/Source/Core/Core/Slippi/SlippiSavestate.h +++ b/Source/Core/Core/Slippi/SlippiSavestate.h @@ -1,8 +1,8 @@ #pragma once +#include #include "Common/ChunkFile.h" #include "Common/CommonTypes.h" -#include class PointerWrap; @@ -14,7 +14,10 @@ public: u32 address; u32 length; - bool operator==(const PreserveBlock& p) const { return address == p.address && length == p.length; } + bool operator==(const PreserveBlock& p) const + { + return address == p.address && length == p.length; + } }; SlippiSavestate(); @@ -46,7 +49,7 @@ private: { std::size_t operator()(const PreserveBlock& node) const { - return node.address ^ node.length; // TODO: This is probably a bad hash + return node.address ^ node.length; // TODO: This is probably a bad hash } }; diff --git a/Source/Core/Core/Slippi/SlippiUser.cpp b/Source/Core/Core/Slippi/SlippiUser.cpp index 8030e4bbf2..873bf8b57c 100644 --- a/Source/Core/Core/Slippi/SlippiUser.cpp +++ b/Source/Core/Core/Slippi/SlippiUser.cpp @@ -33,7 +33,7 @@ static void system_hidden(const char* cmd) memset(&p_info, 0, sizeof(p_info)); s_info.cb = sizeof(s_info); - wchar_t utf16cmd[MAX_SYSTEM_PROGRAM] = { 0 }; + wchar_t utf16cmd[MAX_SYSTEM_PROGRAM] = {0}; MultiByteToWideChar(CP_UTF8, 0, cmd, -1, utf16cmd, MAX_SYSTEM_PROGRAM); if (CreateProcessW(NULL, utf16cmd, NULL, NULL, 0, CREATE_NO_WINDOW, NULL, NULL, &s_info, &p_info)) { @@ -76,8 +76,8 @@ SlippiUser::SlippiUser() curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 5000); // Set up HTTP Headers - m_curlHeaderList = curl_slist_append(m_curlHeaderList, "Content-Type: application/json"); - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, m_curlHeaderList); + m_curl_header_list = curl_slist_append(m_curl_header_list, "Content-Type: application/json"); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, m_curl_header_list); #ifdef _WIN32 // ALPN support is enabled by default but requires Windows >= 8.1. @@ -91,56 +91,58 @@ SlippiUser::SlippiUser() SlippiUser::~SlippiUser() { // Wait for thread to terminate - runThread = false; - if (fileListenThread.joinable()) - fileListenThread.join(); + m_run_thread = false; + if (m_file_listen_thread.joinable()) + m_file_listen_thread.join(); if (m_curl) { - curl_slist_free_all(m_curlHeaderList); + curl_slist_free_all(m_curl_header_list); curl_easy_cleanup(m_curl); } } bool SlippiUser::AttemptLogin() { - std::string userFilePath = getUserFilePath(); + std::string user_file_path = getUserFilePath(); - INFO_LOG(SLIPPI_ONLINE, "Looking for file at: %s", userFilePath.c_str()); + INFO_LOG(SLIPPI_ONLINE, "Looking for file at: %s", user_file_path.c_str()); { - std::string userFilePathTxt = - userFilePath + ".txt"; // Put the filename here in its own scope because we don't really need it elsewhere - if (File::Exists(userFilePathTxt)) + // Put the filename here in its own scope because we don't really need it elsewhere + std::string user_file_path_txt = user_file_path + ".txt"; + if (File::Exists(user_file_path_txt)) { // If both files exist we just log they exist and take no further action - if (File::Exists(userFilePath)) + if (File::Exists(user_file_path)) { - INFO_LOG(SLIPPI_ONLINE, - "Found both .json.txt and .json file for user data. Using .json and ignoring the .json.txt"); + INFO_LOG(SLIPPI_ONLINE, "Found both .json.txt and .json file for user data. Using .json " + "and ignoring the .json.txt"); } // If only the .txt file exists move the contents to a json file and log if it fails - else if (!File::Rename(userFilePathTxt, userFilePath)) + else if (!File::Rename(user_file_path_txt, user_file_path)) { - WARN_LOG(SLIPPI_ONLINE, "Could not move file %s to %s", userFilePathTxt.c_str(), userFilePath.c_str()); + WARN_LOG(SLIPPI_ONLINE, "Could not move file %s to %s", user_file_path_txt.c_str(), + user_file_path.c_str()); } } } // Get user file - std::string userFileContents; - File::ReadFileToString(userFilePath, userFileContents); + std::string user_file_contents; + File::ReadFileToString(user_file_path, user_file_contents); - userInfo = parseFile(userFileContents); + m_user_info = parseFile(user_file_contents); - isLoggedIn = !userInfo.uid.empty(); - if (isLoggedIn) + m_is_logged_in = !m_user_info.uid.empty(); + if (m_is_logged_in) { overwriteFromServer(); - WARN_LOG(SLIPPI_ONLINE, "Found user %s (%s)", userInfo.displayName.c_str(), userInfo.uid.c_str()); + WARN_LOG(SLIPPI_ONLINE, "Found user %s (%s)", m_user_info.display_name.c_str(), + m_user_info.uid.c_str()); } - return isLoggedIn; + return m_is_logged_in; } void SlippiUser::OpenLogInPage() @@ -149,27 +151,28 @@ void SlippiUser::OpenLogInPage() std::string path = getUserFilePath(); #ifdef _WIN32 - // On windows, sometimes the path can have backslashes and slashes mixed, convert all to backslashes + // On windows, sometimes the path can have backslashes and slashes mixed, convert all to + // backslashes path = ReplaceAll(path, "\\", "\\"); path = ReplaceAll(path, "/", "\\"); #endif #ifndef __APPLE__ - char* escapedPath = curl_easy_escape(nullptr, path.c_str(), (int)path.length()); - path = std::string(escapedPath); - curl_free(escapedPath); + char* escaped_path = curl_easy_escape(nullptr, path.c_str(), (int)path.length()); + path = std::string(escaped_path); + curl_free(escaped_path); #endif - std::string fullUrl = url + "?path=" + path; + std::string full_url = url + "?path=" + path; - INFO_LOG(SLIPPI_ONLINE, "[User] Login at path: %s", fullUrl.c_str()); + INFO_LOG(SLIPPI_ONLINE, "[User] Login at path: %s", full_url.c_str()); #ifdef _WIN32 - std::string command = "explorer \"" + fullUrl + "\""; + std::string command = "explorer \"" + full_url + "\""; #elif defined(__APPLE__) - std::string command = "open \"" + fullUrl + "\""; + std::string command = "open \"" + full_url + "\""; #else - std::string command = "xdg-open \"" + fullUrl + "\""; // Linux + std::string command = "xdg-open \"" + full_url + "\""; // Linux #endif RunSystemCommand(command); @@ -181,16 +184,21 @@ void SlippiUser::UpdateApp() auto isoPath = SConfig::GetInstance().m_strIsoPath; std::string path = File::GetExeDirectory() + "/dolphin-slippi-tools.exe"; - std::string echoMsg = "echo Starting update process. If nothing happen after a few " - "minutes, you may need to update manually from https://slippi.gg/netplay ..."; + std::string echo_msg = + "echo Starting update process. If nothing happen after a few " + "minutes, you may need to update manually from https://slippi.gg/netplay ..."; // std::string command = - // "start /b cmd /c " + echoMsg + " && \"" + path + "\" app-update -launch -iso \"" + isoPath + "\""; - std::string command = "start /b cmd /c " + echoMsg + " && \"" + path + "\" app-update -launch -iso \"" + isoPath + - "\" -version \"" + Common::scm_slippi_semver_str + "\""; + // "start /b cmd /c " + echo_msg + " && \"" + path + "\" app-update -launch -iso \"" + isoPath + // + + // "\""; + std::string command = "start /b cmd /c " + echo_msg + " && \"" + path + + "\" app-update -launch -iso \"" + isoPath + "\" -version \"" + + Common::scm_slippi_semver_str + "\""; WARN_LOG(SLIPPI, "Executing app update command: %s", command.c_str()); RunSystemCommand(command); #elif defined(__APPLE__) - CriticalAlertT("Automatic updates are not available for macOS; please get the latest update from slippi.gg/netplay."); + CriticalAlertT("Automatic updates are not available for macOS; please get the latest update from " + "slippi.gg/netplay."); #else const char* appimage_path = getenv("APPIMAGE"); const char* appmount_path = getenv("APPDIR"); @@ -204,55 +212,56 @@ void SlippiUser::UpdateApp() std::string command = mount_path + "/usr/bin/appimageupdatetool " + path; WARN_LOG(SLIPPI, "Executing app update command: %s", command.c_str()); RunSystemCommand(command); - CriticalAlertT("Restart Dolphin to finish the update. If there was an issue, please head over to the Slippi " - "Discord for support."); + CriticalAlertT( + "Restart Dolphin to finish the update. If there was an issue, please head over to the Slippi " + "Discord for support."); #endif } void SlippiUser::ListenForLogIn() { - if (runThread) + if (m_run_thread) return; - if (fileListenThread.joinable()) - fileListenThread.join(); + if (m_file_listen_thread.joinable()) + m_file_listen_thread.join(); - runThread = true; - fileListenThread = std::thread(&SlippiUser::FileListenThread, this); + m_run_thread = true; + m_file_listen_thread = std::thread(&SlippiUser::FileListenThread, this); } void SlippiUser::LogOut() { - runThread = false; + m_run_thread = false; deleteFile(); - UserInfo emptyUser; - isLoggedIn = false; - userInfo = emptyUser; + UserInfo empty_user; + m_is_logged_in = false; + m_user_info = empty_user; } void SlippiUser::OverwriteLatestVersion(std::string version) { - userInfo.latestVersion = version; + m_user_info.latest_version = version; } SlippiUser::UserInfo SlippiUser::GetUserInfo() { - return userInfo; + return m_user_info; } bool SlippiUser::IsLoggedIn() { - return isLoggedIn; + return m_is_logged_in; } void SlippiUser::FileListenThread() { - while (runThread) + while (m_run_thread) { if (AttemptLogin()) { - runThread = false; + m_run_thread = false; break; } @@ -266,13 +275,14 @@ void SlippiUser::FileListenThread() std::string SlippiUser::getUserFilePath() { #if defined(__APPLE__) - std::string userFilePath = File::GetBundleDirectory() + "/Contents/Resources" + DIR_SEP + "user.json"; + std::string user_file_path = + File::GetBundleDirectory() + "/Contents/Resources" + DIR_SEP + "user.json"; #elif defined(_WIN32) - std::string userFilePath = File::GetExeDirectory() + DIR_SEP + "user.json"; + std::string user_file_path = File::GetExeDirectory() + DIR_SEP + "user.json"; #else - std::string userFilePath = File::GetUserPath(F_USERJSON_IDX); + std::string user_file_path = File::GetUserPath(F_USERJSON_IDX); #endif - return userFilePath; + return user_file_path; } inline std::string readString(json obj, std::string key) @@ -286,30 +296,30 @@ inline std::string readString(json obj, std::string key) return obj[key]; } -SlippiUser::UserInfo SlippiUser::parseFile(std::string fileContents) +SlippiUser::UserInfo SlippiUser::parseFile(std::string file_contents) { UserInfo info; - info.fileContents = fileContents; + info.file_contents = file_contents; - auto res = json::parse(fileContents, nullptr, false); + auto res = json::parse(file_contents, nullptr, false); if (res.is_discarded() || !res.is_object()) { return info; } info.uid = readString(res, "uid"); - info.displayName = readString(res, "displayName"); - info.playKey = readString(res, "playKey"); - info.connectCode = readString(res, "connectCode"); - info.latestVersion = readString(res, "latestVersion"); + info.display_name = readString(res, "displayName"); + info.play_key = readString(res, "playKey"); + info.connect_code = readString(res, "connectCode"); + info.latest_version = readString(res, "latestVersion"); return info; } void SlippiUser::deleteFile() { - std::string userFilePath = getUserFilePath(); - File::Delete(userFilePath); + std::string user_file_path = getUserFilePath(); + File::Delete(user_file_path); } void SlippiUser::overwriteFromServer() @@ -319,7 +329,7 @@ void SlippiUser::overwriteFromServer() // Perform curl request std::string resp; - curl_easy_setopt(m_curl, CURLOPT_URL, (URL_START + "/" + userInfo.uid).c_str()); + curl_easy_setopt(m_curl, CURLOPT_URL, (URL_START + "/" + m_user_info.uid).c_str()); curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &resp); CURLcode res = curl_easy_perform(m_curl); @@ -329,17 +339,17 @@ void SlippiUser::overwriteFromServer() return; } - long responseCode; - curl_easy_getinfo(m_curl, CURLINFO_RESPONSE_CODE, &responseCode); - if (responseCode != 200) + long response_code; + curl_easy_getinfo(m_curl, CURLINFO_RESPONSE_CODE, &response_code); + if (response_code != 200) { - ERROR_LOG(SLIPPI, "[User] Server responded with non-success status: %d", responseCode); + ERROR_LOG(SLIPPI, "[User] Server responded with non-success status: %d", response_code); return; } - // Overwrite userInfo with data from server + // Overwrite user info with data from server auto r = json::parse(resp); - userInfo.connectCode = r.value("connectCode", userInfo.connectCode); - userInfo.latestVersion = r.value("latestVersion", userInfo.latestVersion); - userInfo.displayName = r.value("displayName", userInfo.displayName); + m_user_info.connect_code = r.value("connectCode", m_user_info.connect_code); + m_user_info.latest_version = r.value("latestVersion", m_user_info.latest_version); + m_user_info.display_name = r.value("displayName", m_user_info.display_name); } diff --git a/Source/Core/Core/Slippi/SlippiUser.h b/Source/Core/Core/Slippi/SlippiUser.h index f12b66f774..3b7166d567 100644 --- a/Source/Core/Core/Slippi/SlippiUser.h +++ b/Source/Core/Core/Slippi/SlippiUser.h @@ -1,12 +1,12 @@ #pragma once -#include "Common/CommonTypes.h" #include #include #include #include #include #include +#include "Common/CommonTypes.h" class SlippiUser { @@ -14,11 +14,11 @@ public: struct UserInfo { std::string uid = ""; - std::string playKey = ""; - std::string displayName = ""; - std::string connectCode = ""; - std::string latestVersion = ""; - std::string fileContents = ""; + std::string play_key = ""; + std::string display_name = ""; + std::string connect_code = ""; + std::string latest_version = ""; + std::string file_contents = ""; }; SlippiUser(); @@ -36,18 +36,18 @@ public: protected: std::string getUserFilePath(); - UserInfo parseFile(std::string fileContents); + UserInfo parseFile(std::string file_contents); void deleteFile(); void overwriteFromServer(); - UserInfo userInfo; - bool isLoggedIn = false; + UserInfo m_user_info; + bool m_is_logged_in = false; const std::string URL_START = "https://users-rest-dot-slippi.uc.r.appspot.com/user"; CURL* m_curl = nullptr; - struct curl_slist* m_curlHeaderList = nullptr; - std::vector receiveBuf; + struct curl_slist* m_curl_header_list = nullptr; + std::vector m_receive_buf; - std::thread fileListenThread; - std::atomic runThread; + std::thread m_file_listen_thread; + std::atomic m_run_thread; }; diff --git a/Source/Core/DolphinQt/CMakeLists.txt b/Source/Core/DolphinQt/CMakeLists.txt index 27b50b9922..bba23af4b8 100644 --- a/Source/Core/DolphinQt/CMakeLists.txt +++ b/Source/Core/DolphinQt/CMakeLists.txt @@ -438,13 +438,13 @@ endif() if(APPLE) include(BundleUtilities) - set(BUNDLE_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Dolphin.app) + set(BUNDLE_PATH "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Slippi_Dolphin.app") # Ask for an application bundle. set_target_properties(dolphin-emu PROPERTIES MACOSX_BUNDLE true MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in - OUTPUT_NAME Dolphin + OUTPUT_NAME "Slippi_Dolphin" ) # Copy qt.conf into the bundle diff --git a/Source/Core/DolphinQt/Info.plist.in b/Source/Core/DolphinQt/Info.plist.in index b5f3a3f44b..d926a47cc6 100644 --- a/Source/Core/DolphinQt/Info.plist.in +++ b/Source/Core/DolphinQt/Info.plist.in @@ -29,11 +29,15 @@ CFBundleExecutable - Dolphin + Slippi_Dolphin + CFBundleName + Slippi_Dolphin + CFBundleDisplayName + Slippi_Dolphin CFBundleIconFile Dolphin.icns CFBundleIdentifier - org.dolphin-emu.dolphin + com.project-slippi.dolphin CFBundleDevelopmentRegion English CFBundlePackageType diff --git a/Source/Core/DolphinQt/Settings/SlippiPane.cpp b/Source/Core/DolphinQt/Settings/SlippiPane.cpp index 5ae78ba8ef..4998841c28 100644 --- a/Source/Core/DolphinQt/Settings/SlippiPane.cpp +++ b/Source/Core/DolphinQt/Settings/SlippiPane.cpp @@ -94,22 +94,23 @@ void SlippiPane::CreateLayout() connect(delay_spin, qOverload(&QSpinBox::valueChanged), this, [](int delay) { SConfig::GetInstance().m_slippiOnlineDelay = delay; }); #else - //Playback Settings + // Playback Settings auto* playback_settings = new QGroupBox(tr("Playback Settings")); auto* playback_settings_layout = new QVBoxLayout(); playback_settings->setLayout(playback_settings_layout); layout->addWidget(playback_settings); auto* enable_playback_seek_checkbox = new QCheckBox(tr("Enable Seekbar")); - char seekbarTooltip[] = "

Enables video player style controls while watching Slippi replays. Uses more cpu resources and can be stuttery. " \ - "Space: Pause/Play " \ - "Left/Right: Jump 5 seconds back/forward" \ - "Shift + Left/Right: Jump 20 seconds back/forward" \ - "Period (while paused): Advance one frame"; + char seekbarTooltip[] = "

Enables video player style controls while " + "watching Slippi replays. Uses more cpu resources and can be stuttery. " + "Space: Pause/Play " + "Left/Right: Jump 5 seconds back/forward" + "Shift + Left/Right: Jump 20 seconds back/forward" + "Period (while paused): Advance one frame"; enable_playback_seek_checkbox->setToolTip(tr(seekbarTooltip)); playback_settings_layout->addWidget(enable_playback_seek_checkbox); enable_playback_seek_checkbox->setChecked(SConfig::GetInstance().m_slippiEnableSeek); connect(enable_playback_seek_checkbox, &QCheckBox::toggled, this, - [](bool checked) { SConfig::GetInstance().m_slippiEnableSeek = checked; }); + [](bool checked) { SConfig::GetInstance().m_slippiEnableSeek = checked; }); #endif } diff --git a/build-appimage.sh b/build-appimage.sh index fda23abc69..04aa7fa18f 100644 --- a/build-appimage.sh +++ b/build-appimage.sh @@ -1,7 +1,8 @@ #!/bin/bash -e -# build-online-appimage.sh +# build-appimage.sh ZSYNC_STRING="gh-releases-zsync|project-slippi|Ishiiruka|latest|Slippi_Online-x86_64.AppImage.zsync" +NETPLAY_APPIMAGE_STRING="Slippi_Online-x86_64.AppImage" PLAYBACK_APPIMAGE_STRING="Slippi_Playback-x86_64.AppImage" LINUXDEPLOY_PATH="https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous" @@ -16,28 +17,33 @@ UPDATETOOL_PATH="https://github.com/AppImage/AppImageUpdate/releases/download/co UPDATETOOL_FILE="appimageupdatetool-x86_64.AppImage" UPDATETOOL_URL="${UPDATETOOL_PATH}/${UPDATETOOL_FILE}" -DESKTOP_APP_URL="https://github.com/project-slippi/slippi-desktop-app" -DESKTOP_APP_SYS_PATH="./slippi-desktop-app/app/dolphin-dev/overwrite/Sys" +PLAYBACK_CODES_PATH="./Data/PlaybackGeckoCodes/" APPDIR_BIN="./AppDir/usr/bin" +APPDIR_HOOKS="./AppDir/apprun-hooks" # Grab various appimage binaries from GitHub if we don't have them if [ ! -e ./Tools/linuxdeploy ]; then wget ${LINUXDEPLOY_URL} -O ./Tools/linuxdeploy - chmod +x ./Tools/linuxdeploy fi if [ ! -e ./Tools/linuxdeploy-update-plugin ]; then wget ${UPDATEPLUG_URL} -O ./Tools/linuxdeploy-update-plugin - chmod +x ./Tools/linuxdeploy-update-plugin fi if [ ! -e ./Tools/appimageupdatetool ]; then - wget ${UPDATEPLUG_URL} -O ./Tools/appimageupdatetool - chmod +x ./Tools/appimageupdatetool + wget ${UPDATETOOL_URL} -O ./Tools/appimageupdatetool fi +chmod +x ./Tools/linuxdeploy +chmod +x ./Tools/linuxdeploy-update-plugin +chmod +x ./Tools/appimageupdatetool + # Delete the AppDir folder to prevent build issues rm -rf ./AppDir/ +# Add the linux-env script to the AppDir prior to running linuxdeploy +mkdir -p ${APPDIR_HOOKS} +cp Data/linux-env.sh ${APPDIR_HOOKS} + # Build the AppDir directory for this image mkdir -p AppDir ./Tools/linuxdeploy \ @@ -50,32 +56,29 @@ mkdir -p AppDir cp -r Data/Sys ${APPDIR_BIN} # Build type -if [ -z "$1" ] # Netplay +if [ "$1" == "playback" ] # Playback then - echo "Using Netplay build config" - + echo "Using Playback build config" + + rm -f ${PLAYBACK_APPIMAGE_STRING} + + # Update Sys dir with playback codes + echo "Copying Playback gecko codes" + rm -rf "${APPDIR_BIN}/Sys/GameSettings" # Delete netplay codes + cp -r "${PLAYBACK_CODES_PATH}/." "${APPDIR_BIN}/Sys/GameSettings/" + + OUTPUT="${PLAYBACK_APPIMAGE_STRING}" \ + ./Tools/linuxdeploy-update-plugin --appdir=./AppDir/ +else + echo "Using Netplay build config" + + # remove existing appimage just in case + rm -f ${NETPLAY_APPIMAGE_STRING} + # Package up the update tool within the AppImage cp ./Tools/appimageupdatetool ./AppDir/usr/bin/ # Bake an AppImage with the update metadata UPDATE_INFORMATION="${ZSYNC_STRING}" \ ./Tools/linuxdeploy-update-plugin --appdir=./AppDir/ -elif [ "$1" == "playback" ] # Playback - then - echo "Using Playback build config" - if [ -d "slippi-desktop-app" ] - then - pushd slippi-desktop-app - git checkout master - git pull --ff-only - popd - else - git clone ${DESKTOP_APP_URL} - fi - # Update Sys dir with playback codes - rm -rf "${APPDIR_BIN}/GameSettings" # Delete netplay codes - cp -r ${DESKTOP_APP_SYS_PATH} ${APPDIR_BIN} - - OUTPUT="${PLAYBACK_APPIMAGE_STRING}" \ - ./Tools/linuxdeploy-update-plugin --appdir=./AppDir/ fi diff --git a/build-linux.sh b/build-linux.sh index e076f9cada..a84dd609ab 100644 --- a/build-linux.sh +++ b/build-linux.sh @@ -3,15 +3,19 @@ CMAKE_FLAGS='-DLINUX_LOCAL_DEV=true' +PLAYBACK_CODES_PATH="./Data/PlaybackGeckoCodes/" + +DATA_SYS_PATH="./Data/Sys/" +BINARY_PATH="./build/Binaries/" + # Build type -if [ -z "$1" ] +if [ "$1" == "playback" ] then + echo "Using Playback build config" +else # TODO: move this around, playback should be the secondary build CMAKE_FLAGS+=" -DSLIPPI_PLAYBACK=false" echo "Using Netplay build config" -elif [ "$1" == "playback" ] - then - echo "Using Playback build config" fi # Move into the build directory, run CMake, and compile the project @@ -22,6 +26,15 @@ make -j$(nproc) popd # Copy the Sys folder in -cp -r -n Data/Sys/ build/Binaries/ +cp -r -n ${DATA_SYS_PATH} ${BINARY_PATH} touch ./build/Binaries/portable.txt + +# Copy playback specific codes if needed +if [ "$1" == "playback" ] + then + # Update Sys dir with playback codes + echo "Copying Playback gecko codes" + rm -rf "${BINARY_PATH}/Sys/GameSettings" # Delete netplay codes + cp -r "${PLAYBACK_CODES_PATH}/." "${BINARY_PATH}/Sys/GameSettings/" +fi \ No newline at end of file diff --git a/build-mac.sh b/build-mac.sh new file mode 100644 index 0000000000..7835be7701 --- /dev/null +++ b/build-mac.sh @@ -0,0 +1,49 @@ +#!/bin/bash -e +# build-mac.sh + +QT_BREW_PATH=$(brew --prefix qt@5) +CMAKE_FLAGS="-DQt5_DIR=${QT_BREW_PATH}/lib/cmake/Qt5 -DENABLE_NOGUI=false" + +PLAYBACK_CODES_PATH="./Data/PlaybackGeckoCodes/" + +DATA_SYS_PATH="./Data/Sys/" +BINARY_PATH="./build/Binaries/Slippi_Dolphin.app/Contents/Resources/" + +export LIBRARY_PATH=$LIBRARY_PATH:/usr/local/lib:/usr/lib/ + +# Build type +if [ "$1" == "playback" ] + then + echo "Using Playback build config" +else + echo "Using Netplay build config" + CMAKE_FLAGS+=" -DSLIPPI_PLAYBACK=false" +fi + +if [[ -z "${CERTIFICATE_MACOS_APPLICATION}" ]] + then + echo "Building without code signing" +else + echo "Building with code signing" + CMAKE_FLAGS+=' -DMACOS_CODE_SIGNING="ON"' +fi + +# Move into the build directory, run CMake, and compile the project +mkdir -p build +pushd build +cmake ${CMAKE_FLAGS} .. +make -j7 +popd + +# Copy the Sys folder in +echo "Copying Sys files into the bundle" +cp -Rfn "${DATA_SYS_PATH}" "${BINARY_PATH}" + +# Copy playback specific codes if needed +if [ "$1" == "playback" ] + then + # Update Sys dir with playback codes + echo "Copying playback gecko codes into the bundle" + rm -rf "${BINARY_PATH}/Sys/GameSettings" # Delete netplay codes + cp -r "${PLAYBACK_CODES_PATH}/." "${BINARY_PATH}/Sys/GameSettings/" +fi