diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 00000000..8425582b --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,124 @@ +name: Build + +on: + push: + workflow_dispatch: + +jobs: + build: + name: ${{ matrix.name }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - { name: "Windows-x86_64", os: windows-latest, msys2_sys: MINGW64, msys2_env: mingw-w64-x86_64 } + - { name: "Windows-i686", os: windows-latest, msys2_sys: MINGW32, msys2_env: mingw-w64-i686 } + - { name: "Linux-x86_64", os: ubuntu-latest, linux_arch: x86_64 } + - { name: "Linux-i686", os: ubuntu-latest, linux_arch: i686 } + - { name: "macOS-ARM64", os: macos-latest } + - { name: "macOS-x86_64", os: macos-latest, macos_arch: x86_64 } + + steps: + - uses: actions/checkout@v6 + + # ── Windows ────────────────────────────────────────────────────── + - uses: msys2/setup-msys2@v2 + if: runner.os == 'Windows' + with: + msystem: ${{ matrix.msys2_sys }} + update: true + install: >- + ${{ matrix.msys2_env }}-gcc + ${{ matrix.msys2_env }}-cmake + ${{ matrix.msys2_env }}-SDL2 + ${{ matrix.msys2_env }}-make + + - name: Build (Windows) + if: runner.os == 'Windows' + shell: msys2 {0} + run: | + cd pc && mkdir -p build && cd build + cmake .. -G "MinGW Makefiles" + mingw32-make -j$(nproc) + + # ── Linux ───────────────────────────────────────────────────────── + - name: Install deps (Linux x86_64) + if: runner.os == 'Linux' && matrix.linux_arch == 'x86_64' + run: | + sudo apt-get update + sudo apt-get install -y gcc g++ cmake libsdl2-dev libgl-dev + + - name: Install deps (Linux i686) + if: runner.os == 'Linux' && matrix.linux_arch == 'i686' + run: | + sudo dpkg --add-architecture i386 + sudo apt-get update + sudo apt-get install -y gcc-multilib g++-multilib cmake + # Install 32-bit libraries without dev packages to avoid glib conflicts + sudo apt-get install -y libsdl2-2.0-0:i386 libgl1:i386 libglx0:i386 libopengl0:i386 + # Install x86_64 dev packages (headers are arch-independent) + sudo apt-get install -y libsdl2-dev libgl-dev + + - name: Build (Linux x86_64) + if: runner.os == 'Linux' && matrix.linux_arch == 'x86_64' + run: | + cd pc && mkdir -p build && cd build + cmake .. + make -j$(nproc) + + - name: Build (Linux i686) + if: runner.os == 'Linux' && matrix.linux_arch == 'i686' + run: | + cd pc && mkdir -p build32 && cd build32 + cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-linux32.cmake + make -j$(nproc) + + # ── macOS ARM64 ─────────────────────────────────────────────────── + - name: Install deps (macOS ARM64) + if: runner.os == 'macOS' && matrix.macos_arch != 'x86_64' + run: | + brew install gcc sdl2 cmake + GCC_VERSION=$(ls "$(brew --prefix)/bin/gcc-"* | grep -Eo '[0-9]+$' | sort -rn | head -1) + echo "GCC_VERSION=$GCC_VERSION" >> $GITHUB_ENV + + - name: Build (macOS ARM64) + if: runner.os == 'macOS' && matrix.macos_arch != 'x86_64' + run: | + cd pc && mkdir -p build && cd build + cmake .. \ + -DCMAKE_C_COMPILER=gcc-${GCC_VERSION} \ + -DCMAKE_CXX_COMPILER=g++-${GCC_VERSION} + make -j$(sysctl -n hw.ncpu) + + # ── macOS x86_64 (via Rosetta 2 + x86_64 Homebrew) ─────────────── + - name: Install deps (macOS x86_64) + if: runner.os == 'macOS' && matrix.macos_arch == 'x86_64' + run: | + curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh -o /tmp/brew_install.sh + arch -x86_64 /bin/bash /tmp/brew_install.sh + arch -x86_64 /usr/local/bin/brew install gcc sdl2 cmake + GCC_VERSION=$(ls /usr/local/bin/gcc-* | grep -Eo '[0-9]+$' | sort -rn | head -1) + echo "GCC_VERSION=$GCC_VERSION" >> $GITHUB_ENV + + - name: Build (macOS x86_64) + if: runner.os == 'macOS' && matrix.macos_arch == 'x86_64' + run: | + cd pc && mkdir -p build && cd build + arch -x86_64 /usr/local/bin/cmake .. \ + -DCMAKE_C_COMPILER=/usr/local/bin/gcc-${GCC_VERSION} \ + -DCMAKE_CXX_COMPILER=/usr/local/bin/g++-${GCC_VERSION} + arch -x86_64 make -j$(sysctl -n hw.ncpu) + + # ── Artifacts ───────────────────────────────────────────────────── + - uses: actions/upload-artifact@v7 + if: runner.os == 'Windows' || (runner.os == 'Linux' && matrix.linux_arch == 'x86_64') || runner.os == 'macOS' + with: + name: AnimalCrossing-${{ matrix.name }} + path: pc/build/bin/ + + - uses: actions/upload-artifact@v7 + if: runner.os == 'Linux' && matrix.linux_arch == 'i686' + with: + name: AnimalCrossing-${{ matrix.name }} + path: pc/build32/bin/ diff --git a/.gitignore b/.gitignore index 8ce7bd42..63d33ec5 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ orig/*/* # Build files build/ build32/ +build64/ .ninja_* build.ninja diff --git a/README.md b/README.md index 9a024258..c99df3d2 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ A native PC port of Animal Crossing (GameCube) built on top of the [ac-decomp](https://github.com/ACreTeam/ac-decomp) decompilation project. -The game's original C code runs natively on x86, with a custom translation layer replacing the GameCube's GX graphics API with OpenGL 3.3. +The game's original C code runs natively on PC, with a custom translation layer replacing the GameCube's GX graphics API with OpenGL 3.3. This repository does not contain any game assets or assembly whatsoever. An existing copy of the game is required. @@ -24,40 +24,111 @@ Only needed if you want to modify the code. Otherwise, use the [pre-built releas ### Requirements -- **MSYS2** (https://www.msys2.org/) - **Animal Crossing (USA) disc image** (ISO, GCM, or CISO format) +- **CMake** 3.16+ +- **SDL2** development libraries +- **GCC** (required on 64-bit platforms; Clang is supported on 32-bit only) -### MSYS2 Packages +### Build Steps -Open **MSYS2 MINGW32** from your Start menu and install: +### Windows 32-bit (MSYS2) -```bash -pacman -S mingw-w64-i686-gcc mingw-w64-i686-cmake mingw-w64-i686-SDL2 mingw-w64-i686-make -``` +1. Install **MSYS2** (https://www.msys2.org/) -### Build Steps +2. Open **MSYS2 MINGW32** and install dependencies: + ```bash + pacman -S mingw-w64-i686-gcc mingw-w64-i686-cmake mingw-w64-i686-SDL2 mingw-w64-i686-make + ``` -1. Clone the repository: +3. Clone and build: ```bash git clone https://github.com/flyngmt/ACGC-PC-Port.git cd ACGC-PC-Port + ./build_pc.sh ``` -2. Build (from **MSYS2 MINGW32** shell): +4. Place your disc image in `pc/build32/bin/rom/` and run: ```bash - ./build_pc.sh + pc/build32/bin/AnimalCrossing.exe + ``` + +### Windows 64-bit (MSYS2) + +1. Install **MSYS2** (https://www.msys2.org/) + +2. Open **MSYS2 MINGW64** and install dependencies: + ```bash + pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake mingw-w64-x86_64-SDL2 mingw-w64-x86_64-make ``` -3. Place your disc image in the `rom/` folder: +3. Clone and build: + ```bash + git clone https://github.com/flyngmt/ACGC-PC-Port.git + cd ACGC-PC-Port/pc + mkdir build64 && cd build64 + cmake .. -G "MinGW Makefiles" + mingw32-make -j$(nproc) ``` - pc/build32/bin/rom/YourGame.ciso + +4. Place your disc image in `pc/build64/bin/rom/` and run: + ```bash + pc/build64/bin/AnimalCrossing.exe ``` -4. Run: +### macOS (Apple Silicon & Intel) + +1. Install dependencies: ```bash - pc/build32/bin/AnimalCrossing.exe + brew install gcc sdl2 cmake + ``` + +2. Clone and build: + ```bash + git clone https://github.com/flyngmt/ACGC-PC-Port.git + cd ACGC-PC-Port/pc + mkdir build && cd build + cmake .. -DCMAKE_C_COMPILER=gcc-15 -DCMAKE_CXX_COMPILER=g++-15 + make -j$(sysctl -n hw.ncpu) + ``` + > Adjust `gcc-15`/`g++-15` to match your installed GCC version (`ls /opt/homebrew/bin/gcc-*`). + +3. Place your disc image in `build/bin/rom/` and run: + ```bash + build/bin/AnimalCrossing + ``` + +### Linux (x86_64 / ARM64) + +1. Install dependencies: + ```bash + # Arch/CachyOS/Manjaro + sudo pacman -S gcc cmake sdl2 + + # Debian/Ubuntu + sudo apt install gcc g++ cmake libsdl2-dev + + # Fedora + sudo dnf install gcc gcc-c++ cmake SDL2-devel + ``` + +2. Clone and build: + ```bash + git clone https://github.com/flyngmt/ACGC-PC-Port.git + cd ACGC-PC-Port/pc + mkdir build && cd build + cmake .. + make -j$(nproc) ``` +3. Place your disc image in `build/bin/rom/` and run: + ```bash + build/bin/AnimalCrossing + ``` + +### Disc Image + +The game reads all assets directly from the disc image at startup. No extraction or preprocessing step is needed. Place your disc image (`.iso`, `.gcm`, or `.ciso`) in the `rom/` folder next to the executable — the file can be named anything. The game also checks the `orig/` folder and the current directory. + ## Controls Keyboard bindings are customizable via `keybindings.ini` (next to the executable). Mouse buttons (Mouse1/Mouse2/Mouse3) can also be assigned. @@ -92,7 +163,7 @@ SDL2 game controllers are supported with automatic hotplug detection. Button map ## Settings -Graphics settings are stored in `settings.ini` and can be edited manually or through the in-game options menu: +Graphics settings are stored in `settings.ini` (next to the executable) and can be edited manually or through the in-game options menu: - Resolution (up to 4K) - Fullscreen toggle @@ -102,7 +173,7 @@ Graphics settings are stored in `settings.ini` and can be edited manually or thr ## Texture Packs -Custom textures can be placed in `texture_pack/`. Dolphin-compatible format (XXHash64, DDS). +Custom textures can be placed in the `texture_pack/` folder next to the executable. Dolphin-compatible format (XXHash64, DDS). I highly recommend the following texture pack from the talented artists of Animal Crossing community. @@ -110,7 +181,7 @@ I highly recommend the following texture pack from the talented artists of Anima ## Save Data -Save files are stored in `save/` using the standard GCI format, compatible with Dolphin emulator saves. Place a Dolphin GCI export in the save directory to import an existing save. +Save files are stored in the `save/` folder next to the executable, using the standard GCI format. Compatible with Dolphin emulator saves — place a Dolphin GCI export in the save directory to import an existing save. ## Credits diff --git a/include/JSystem/JKernel/JKRAram.h b/include/JSystem/JKernel/JKRAram.h index 981bad61..792b98f8 100644 --- a/include/JSystem/JKernel/JKRAram.h +++ b/include/JSystem/JKernel/JKRAram.h @@ -105,7 +105,11 @@ class JKRAramHeap : public JKRDisposer { class JKRAram : public JKRThread { public: +#ifdef TARGET_PC + JKRAram(u32, u32, s32); +#else JKRAram(u32, u32, long); +#endif virtual ~JKRAram(); // _08 virtual void* run(); // _0C @@ -113,7 +117,11 @@ class JKRAram : public JKRThread { static bool checkOkAddress(u8* addr, u32 size, JKRAramBlock* block, u32 param_4); static void changeGroupIdIfNeed(u8* data, int groupId); +#ifdef TARGET_PC + static JKRAram* create(u32, u32, s32, s32, s32); +#else static JKRAram* create(u32, u32, long, long, long); +#endif static JKRAramBlock* mainRamToAram(u8*, u32, u32, JKRExpandSwitch, u32, JKRHeap*, int); static JKRAramBlock* mainRamToAram(u8*, JKRAramBlock* block, u32, JKRExpandSwitch, u32, JKRHeap*, int); static u8* aramToMainRam(u32, u8*, u32, JKRExpandSwitch, u32, JKRHeap*, int, u32*); @@ -167,7 +175,11 @@ class JKRAram : public JKRThread { class JKRAMCommand : public ARQRequest { public: +#ifdef TARGET_PC + typedef void (*AMCommandCallback)(uintptr_t); +#else typedef void (*AMCommandCallback)(u32); +#endif JKRAMCommand(); ~JKRAMCommand(); @@ -176,8 +188,13 @@ class JKRAMCommand : public ARQRequest { JSULink mLink30; s32 mDirection; u32 mLength; +#ifdef TARGET_PC + uintptr_t mSource; + uintptr_t mDestination; +#else u32 mSource; u32 mDestination; +#endif JKRAramBlock* mAramBlock; u8 _54[4]; AMCommandCallback mCallback; @@ -204,6 +221,17 @@ class JKRAramCommand { class JKRAramPiece { public: +#ifdef TARGET_PC + static JKRAMCommand* prepareCommand(int direction, uintptr_t source, uintptr_t destination, u32 length, JKRAramBlock* aramBlock, + JKRAMCommand::AMCommandCallback callback); + static void sendCommand(JKRAMCommand* cmd); + static JKRAMCommand* orderAsync(int direction, uintptr_t source, uintptr_t destination, u32 length, JKRAramBlock* aramBlock, + JKRAMCommand::AMCommandCallback callback); + static bool sync(JKRAMCommand* cmd, BOOL noBlock); + static bool orderSync(int direction, uintptr_t source, uintptr_t destination, u32 length, JKRAramBlock* aramBlock); + static void startDMA(JKRAMCommand* cmd); + static void doneDMA(uintptr_t arg); +#else static JKRAMCommand* prepareCommand(int direction, u32 source, u32 destination, u32 length, JKRAramBlock* aramBlock, JKRAMCommand::AMCommandCallback callback); static void sendCommand(JKRAMCommand* cmd); @@ -213,6 +241,7 @@ class JKRAramPiece { static bool orderSync(int direction, u32 source, u32 destination, u32 length, JKRAramBlock* aramBlock); static void startDMA(JKRAMCommand* cmd); static void doneDMA(u32 arg); +#endif static OSMutex mMutex; static JSUList sAramPieceCommandList; @@ -237,7 +266,11 @@ class JKRAramStreamCommand { JKRAramStreamCommand(); ECommandType type; // _00 +#ifdef TARGET_PC + uintptr_t mAddress; // _04 +#else u32 mAddress; // _04 +#endif u32 mSize; // _08 u32 _0C; // _0C JSUFileInputStream* mStream; // _10 @@ -255,7 +288,11 @@ class JKRAramStreamCommand { class JKRAramStream : public JKRThread { public: +#ifdef TARGET_PC + JKRAramStream(s32); +#else JKRAramStream(long); +#endif virtual ~JKRAramStream(); // _08 virtual void* run(); // _0C @@ -303,9 +340,15 @@ inline JKRAramStream* JKRCreateAramStreamManager(s32 priority) { return JKRAramStream::create(priority); } +#ifdef TARGET_PC +inline bool JKRAramPcs(int direction, uintptr_t source, uintptr_t destination, u32 length, JKRAramBlock* block) { + return JKRAramPiece::orderSync(direction, source, destination, length, block); +} +#else inline bool JKRAramPcs(int direction, u32 source, u32 destination, u32 length, JKRAramBlock* block) { return JKRAramPiece::orderSync(direction, source, destination, length, block); } +#endif inline void JKRAramPcs_SendCommand(JKRAMCommand* cmd) { JKRAramPiece::sendCommand(cmd); diff --git a/include/JSystem/JKernel/JKRArchive.h b/include/JSystem/JKernel/JKRArchive.h index fc080db2..d472a839 100644 --- a/include/JSystem/JKernel/JKRArchive.h +++ b/include/JSystem/JKernel/JKRArchive.h @@ -111,9 +111,39 @@ class JKRArchive : public JKRFileLoader { u32 mFlag; // _04 u32 mDataOffset; // _08 u32 mSize; // _0C +#ifdef TARGET_PC + /* On 64-bit, void* is 8 bytes which breaks the 0x14-byte RARC + * binary layout. Keep a u32 placeholder here to preserve stride. + * Actual mData pointers are stored in a parallel array via + * the accessor macros below. */ + u32 mData_pad; // _10 (placeholder, not used directly) +#else void* mData; // _10 +#endif }; +#ifdef TARGET_PC + /* On 64-bit, SDIFileEntry.mData is a u32 placeholder (not a real pointer) + * to keep the struct at 0x14 bytes matching the RARC binary layout. + * Store actual mData pointers in a parallel heap-allocated array. */ + void** mFileEntryDataPtrs; // allocated alongside mFileEntries + + void* getFileEntryData(SDIFileEntry* entry) const { + if (!mFileEntryDataPtrs || !mArcInfoBlock) return nullptr; + int idx = (int)(entry - mFileEntries); + if (idx >= 0 && (u32)idx < mArcInfoBlock->num_file_entries) return mFileEntryDataPtrs[idx]; + return nullptr; + } + void setFileEntryData(SDIFileEntry* entry, void* data) { + if (!mFileEntryDataPtrs || !mArcInfoBlock) return; + int idx = (int)(entry - mFileEntries); + if (idx >= 0 && (u32)idx < mArcInfoBlock->num_file_entries) mFileEntryDataPtrs[idx] = data; + } +#else + void* getFileEntryData(SDIFileEntry* entry) const { return entry->mData; } + void setFileEntryData(SDIFileEntry* entry, void* data) { entry->mData = data; } +#endif + struct SDirEntry { u8 mFlags; // _00 u8 _01; // _01 @@ -292,7 +322,11 @@ struct JKRCompArchive : public JKRArchive { // _00 = VTBL // _00-_5C = JKRArchive +#ifdef TARGET_PC + uintptr_t _60; // _60 +#else u32 _60; // _60 +#endif JKRAramBlock* mAramPart; // _64 u32 _68; // _68 JKRFile* mDvdFile; // _6C diff --git a/include/JSystem/JKernel/JKRDecomp.h b/include/JSystem/JKernel/JKRDecomp.h index 7ed5e688..8cc66b14 100644 --- a/include/JSystem/JKernel/JKRDecomp.h +++ b/include/JSystem/JKernel/JKRDecomp.h @@ -22,7 +22,11 @@ #define SZP_GETBACKOFS(buf) (((*((u8*)buf) & 0xF) << 8) | (*(((u8*)buf) + 1))) #define SZP_GETCOUNT(buf) (*((u16*)buf) >> 12) +#ifdef TARGET_PC +typedef void DecompCallback(uintptr_t); +#else typedef void DecompCallback(u32); +#endif class JKRDecompCommand { public: diff --git a/include/JSystem/JKernel/JKRDvdAramRipper.h b/include/JSystem/JKernel/JKRDvdAramRipper.h index 658dcc19..dd2585d4 100644 --- a/include/JSystem/JKernel/JKRDvdAramRipper.h +++ b/include/JSystem/JKernel/JKRDvdAramRipper.h @@ -9,7 +9,11 @@ #ifdef __cplusplus class JKRADCommand { public: +#ifdef TARGET_PC + typedef void (*LoadCallback)(uintptr_t); +#else typedef void (*LoadCallback)(u32); +#endif JKRADCommand(); ~JKRADCommand(); diff --git a/include/JSystem/JKernel/JKRFileLoader.h b/include/JSystem/JKernel/JKRFileLoader.h index 0d7ccd79..9eca475d 100644 --- a/include/JSystem/JKernel/JKRFileLoader.h +++ b/include/JSystem/JKernel/JKRFileLoader.h @@ -22,7 +22,11 @@ class JKRFileLoader : public JKRDisposer { virtual void removeResourceAll() = 0; // _24 virtual bool removeResource(void*) = 0; // _28 virtual bool detachResource(void*) = 0; // _2C +#ifdef TARGET_PC + virtual s32 getResSize(const void*) const = 0; // _30 +#else virtual long getResSize(const void*) const = 0; // _30 +#endif virtual u32 countFile(const char*) const = 0; // _34 virtual JKRFileFinder* getFirstFile(const char*) const = 0; // _38 diff --git a/include/JSystem/JKernel/JKRHeap.h b/include/JSystem/JKernel/JKRHeap.h index 69d5df7c..0a97a10d 100644 --- a/include/JSystem/JKernel/JKRHeap.h +++ b/include/JSystem/JKernel/JKRHeap.h @@ -134,7 +134,11 @@ class JKRHeap : public JKRDisposer { u32 getMaxAllocatableSize(int alignment); JKRHeap* find(void*) const; // 0x80084640 JKRHeap* findAllHeap(void*) const; // 0x8008492c +#ifdef TARGET_PC + void dispose_subroutine(uintptr_t begin, uintptr_t end); +#else void dispose_subroutine(u32 begin, u32 end); +#endif bool dispose(void*, u32); // 0x80084b9c void dispose(void*, void*); // 0x80084c2c void dispose(); // 0x80084cb8 @@ -314,7 +318,7 @@ void JKRDefaultMemoryErrorRoutine(void*, u32, int); void* operator new(size_t); void* operator new(size_t, s32); void* operator new(size_t, JKRHeap*, int); -inline void* operator new(size_t, void* buf) { +inline void* operator new(size_t sz, void* buf) { return buf; } // i believe this is actually part of MSL_C? diff --git a/include/JSystem/JUtility/JUTException.h b/include/JSystem/JUtility/JUTException.h index d596c79a..40b634e4 100644 --- a/include/JSystem/JUtility/JUTException.h +++ b/include/JSystem/JUtility/JUTException.h @@ -67,11 +67,20 @@ struct JUTException : public JKRThread { void printContext(u16, OSContext*, u32, u32); void createFB(); +#ifdef TARGET_PC + static void waitTime(s32); +#else static void waitTime(long); +#endif static JUTErrorHandler setPreUserCallback(JUTErrorHandler); static void appendMapFile(const char*); +#ifdef TARGET_PC + static bool queryMapAddress(char*, u32, s32, u32*, u32*, char*, u32, bool, bool); + static bool queryMapAddress_single(char*, u32, s32, u32*, u32*, char*, u32, bool, bool); +#else static bool queryMapAddress(char*, u32, long, u32*, u32*, char*, u32, bool, bool); static bool queryMapAddress_single(char*, u32, long, u32*, u32*, char*, u32, bool, bool); +#endif static JUTException* create(JUTDirectPrint*); static void createConsole(void* buffer, u32 bufferSize); diff --git a/include/JSystem/JUtility/JUTFont.h b/include/JSystem/JUtility/JUTFont.h index 65d45c58..6a9f5bdb 100644 --- a/include/JSystem/JUtility/JUTFont.h +++ b/include/JSystem/JUtility/JUTFont.h @@ -3,6 +3,9 @@ #include "types.h" #include "string.h" +#ifdef TARGET_PC +#include +#endif #include "dolphin/gx.h" #include "dolphin/os.h" #include "JSystem/JUtility/TColor.h" diff --git a/include/JSystem/JUtility/JUTVideo.h b/include/JSystem/JUtility/JUTVideo.h index e9d5f87d..0233b701 100644 --- a/include/JSystem/JUtility/JUTVideo.h +++ b/include/JSystem/JUtility/JUTVideo.h @@ -18,8 +18,13 @@ struct JUTVideo { static JUTVideo* createManager(const GXRenderModeObj*); static void destroyManager(); +#ifdef TARGET_PC + static void preRetraceProc(u32); + static void postRetraceProc(u32); +#else static void preRetraceProc(unsigned long); static void postRetraceProc(unsigned long); +#endif static void drawDoneCallback(); u32 getEfbHeight() const { diff --git a/include/MSL_C/ctype.h b/include/MSL_C/ctype.h index af1672ec..6f3bf2c6 100644 --- a/include/MSL_C/ctype.h +++ b/include/MSL_C/ctype.h @@ -1,8 +1,8 @@ -#ifndef _CTYPE_H -#define _CTYPE_H +#ifndef _MSL_C_CTYPE_H +#define _MSL_C_CTYPE_H #ifdef TARGET_PC -#include // Conflicts can happen otherwise in certain compiler versions +#include_next #else #include "MSL_C/locale.h" @@ -47,5 +47,6 @@ inline int _toupper(int c) { #ifdef __cplusplus } #endif + #endif /* !TARGET_PC */ -#endif /* _CTYPE_H */ +#endif /* _MSL_C_CTYPE_H */ diff --git a/include/PR/abi.h b/include/PR/abi.h index e1215260..1ee1013a 100644 --- a/include/PR/abi.h +++ b/include/PR/abi.h @@ -274,7 +274,7 @@ typedef short ENVMIX_STATE[40]; Acmd *_a = (Acmd *)pkt; \ \ _a->words.w0 = _SHIFTL(A_ADPCM, 24, 8) | _SHIFTL(f, 16, 8); \ - _a->words.w1 = (unsigned int)(s); \ + _a->words.w1 = (unsigned int)(uintptr_t)(s); \ } #define aPoleFilter(pkt, f, g, s) \ @@ -283,7 +283,7 @@ typedef short ENVMIX_STATE[40]; \ _a->words.w0 = (_SHIFTL(A_POLEF, 24, 8) | _SHIFTL(f, 16, 8) | \ _SHIFTL(g, 0, 16)); \ - _a->words.w1 = (unsigned int)(s); \ + _a->words.w1 = (unsigned int)(uintptr_t)(s); \ } #define aClearBuffer(pkt, d, c) \ @@ -291,7 +291,7 @@ typedef short ENVMIX_STATE[40]; Acmd *_a = (Acmd *)pkt; \ \ _a->words.w0 = _SHIFTL(A_CLEARBUFF, 24, 8) | _SHIFTL(d, 0, 24); \ - _a->words.w1 = (unsigned int)(c); \ + _a->words.w1 = (unsigned int)(uintptr_t)(c); \ } #define aEnvMixer(pkt, f, s) \ @@ -299,7 +299,7 @@ typedef short ENVMIX_STATE[40]; Acmd *_a = (Acmd *)pkt; \ \ _a->words.w0 = _SHIFTL(A_ENVMIXER, 24, 8) | _SHIFTL(f, 16, 8); \ - _a->words.w1 = (unsigned int)(s); \ + _a->words.w1 = (unsigned int)(uintptr_t)(s); \ } #define aInterleave(pkt, l, r) \ @@ -315,7 +315,7 @@ typedef short ENVMIX_STATE[40]; Acmd *_a = (Acmd *)pkt; \ \ _a->words.w0 = _SHIFTL(A_LOADBUFF, 24, 8); \ - _a->words.w1 = (unsigned int)(s); \ + _a->words.w1 = (unsigned int)(uintptr_t)(s); \ } #define aMix(pkt, f, g, i, o) \ @@ -333,7 +333,7 @@ typedef short ENVMIX_STATE[40]; \ _a->words.w0 = (_SHIFTL(A_PAN, 24, 8) | _SHIFTL(f, 16, 8) | \ _SHIFTL(d, 0, 16)); \ - _a->words.w1 = (unsigned int)(s); \ + _a->words.w1 = (unsigned int)(uintptr_t)(s); \ } #define aResample(pkt, f, p, s) \ @@ -342,7 +342,7 @@ typedef short ENVMIX_STATE[40]; \ _a->words.w0 = (_SHIFTL(A_RESAMPLE, 24, 8) | _SHIFTL(f, 16, 8) |\ _SHIFTL(p, 0, 16)); \ - _a->words.w1 = (unsigned int)(s); \ + _a->words.w1 = (unsigned int)(uintptr_t)(s); \ } #define aSaveBuffer(pkt, s) \ @@ -350,7 +350,7 @@ typedef short ENVMIX_STATE[40]; Acmd *_a = (Acmd *)pkt; \ \ _a->words.w0 = _SHIFTL(A_SAVEBUFF, 24, 8); \ - _a->words.w1 = (unsigned int)(s); \ + _a->words.w1 = (unsigned int)(uintptr_t)(s); \ } #define aSegment(pkt, s, b) \ @@ -383,7 +383,7 @@ typedef short ENVMIX_STATE[40]; { \ Acmd *_a = (Acmd *)pkt; \ _a->words.w0 = _SHIFTL(A_SETLOOP, 24, 8); \ - _a->words.w1 = (unsigned int)(a); \ + _a->words.w1 = (unsigned int)(uintptr_t)(a); \ } #define aDMEMMove(pkt, i, o, c) \ @@ -399,7 +399,7 @@ typedef short ENVMIX_STATE[40]; Acmd *_a = (Acmd *)pkt; \ \ _a->words.w0 = _SHIFTL(A_LOADADPCM, 24, 8) | _SHIFTL(c, 0, 24); \ - _a->words.w1 = (unsigned int) d; \ + _a->words.w1 = (unsigned int)(uintptr_t) d; \ } #endif /* _LANGUAGE_C */ diff --git a/include/PR/gbi.h b/include/PR/gbi.h index 612d4a4e..e7cba728 100644 --- a/include/PR/gbi.h +++ b/include/PR/gbi.h @@ -23,11 +23,30 @@ #include #ifdef TARGET_PC -/* GCC GNU extension: pointer-to-integer cast in static initializers. - Safe on 32-bit where sizeof(void*) == sizeof(unsigned int). */ +#include +/* On 64-bit PC, Gwords.w1 is uintptr_t so static initializers can store full + * 64-bit pointers directly. On 32-bit PC, w1 is u32 so we cast through + * uintptr_t to silence warnings. */ +#if UINTPTR_MAX > 0xFFFFFFFFu +#define _GBI_STATIC_PTR(s) (uintptr_t)(s) +#else #define _GBI_STATIC_PTR(s) (unsigned int)(uintptr_t)(s) +#endif + +/* Macro for runtime writes to Gwords.w1. + * On 64-bit, w1 is uintptr_t so we must not truncate pointers. + * On 32-bit, w1 is unsigned int. */ +#if UINTPTR_MAX > 0xFFFFFFFFu +#define _GBI_SET_W1(g, val) ((g)->words.w1 = (uintptr_t)(val)) +#define _GBI_SET_W1_RAW(g, val) ((g)->words.w1 = (uintptr_t)(val)) +#else +#define _GBI_SET_W1(g, val) ((g)->words.w1 = (unsigned int)(val)) +#define _GBI_SET_W1_RAW(g, val) ((g)->words.w1 = (unsigned int)(val)) +#endif #else #define _GBI_STATIC_PTR(s) (unsigned int)(s) +#define _GBI_SET_W1(g, val) ((g)->words.w1 = (unsigned int)(val)) +#define _GBI_SET_W1_RAW(g, val) ((g)->words.w1 = (unsigned int)(val)) #endif /* @@ -1140,12 +1159,12 @@ typedef struct { * First 8 words are integer portion of the 4x4 matrix * Last 8 words are the fraction portion of the 4x4 matrix */ -typedef long Mtx_t[4][4]; +typedef s32_compat Mtx_t[4][4]; typedef union { Mtx_t m; long long int force_structure_alignment; -} Mtx; +} Mtx ATTRIBUTE_ALIGN(8); /* * Viewport @@ -1190,7 +1209,7 @@ typedef struct { typedef union { Vp_t vp; long long int force_structure_alignment; -} Vp; +} Vp ATTRIBUTE_ALIGN(8); /* * MOVEMEM indices @@ -1370,12 +1389,12 @@ typedef struct { typedef union { Light_t l; long long int force_structure_alignment[2]; -} Light; +} Light ATTRIBUTE_ALIGN(8); typedef union { Ambient_t l; long long int force_structure_alignment[1]; -} Ambient; +} Ambient ATTRIBUTE_ALIGN(8); typedef struct { Ambient a; @@ -1428,8 +1447,8 @@ typedef struct { typedef union { Hilite_t h; - long int force_structure_alignment[4]; -} Hilite; + long long int force_structure_alignment[2]; +} Hilite ATTRIBUTE_ALIGN(8); #define gdSPDefLights0(ar,ag,ab) \ { {{ {ar,ag,ab},0,{ar,ag,ab},0}}, \ @@ -1693,7 +1712,7 @@ typedef struct { unsigned int prim_min_level:8; unsigned int pad:8; int cmd:8; - unsigned long color; + u32_compat color; } Gsetcolor; #else typedef struct { @@ -1701,7 +1720,7 @@ typedef struct { unsigned char pad; unsigned char prim_min_level; unsigned char prim_level; - unsigned long color; + u32_compat color; } Gsetcolor; #endif @@ -1840,23 +1859,35 @@ typedef struct { * Textured rectangles are 128 bits not 64 bits */ typedef struct { - unsigned long w0; - unsigned long w1; - unsigned long w2; - unsigned long w3; + u32_compat w0; + u32_compat w1; + u32_compat w2; + u32_compat w3; } TexRect; /* * Generic Gfx Packet + * + * On 64-bit PC, w1 is uintptr_t (8 bytes) so it can store full pointers. + * This makes sizeof(Gwords) == 16 (with 4 bytes of padding between w0 + * and w1 for alignment). Union member structs (Gdma, Gmoveword, etc.) + * are still 8 bytes and their second-word fields land in the padding + * area — so on 64-bit, always read w1 through words.w1, never through + * a union view's second field. */ typedef struct { unsigned int w0; +#if defined(TARGET_PC) && UINTPTR_MAX > 0xFFFFFFFFu + uintptr_t w1; /* Full pointer width on 64-bit PC */ +#else unsigned int w1; +#endif } Gwords; /* * This union is the fundamental type of the display list. - * It is, by law, exactly 64 bits in size. + * Originally 64 bits; on 64-bit PC it is 128 bits (16 bytes) because + * Gwords.w1 is uintptr_t to hold full 64-bit pointers. */ typedef union { Gwords words; @@ -1878,7 +1909,11 @@ typedef union { Gsettilesize settilesize; Gloadtlut loadtlut; long long int force_structure_alignment; -} Gfx; +} Gfx ATTRIBUTE_ALIGN(8); + +/* GBI_FIXUP_PTR is no longer needed — _GBI_STATIC_PTR now stores full pointers + * on 64-bit via uintptr_t w1. Kept as no-op for compatibility. */ +#define GBI_FIXUP_PTR(gfx_array, index, ptr) ((void)0) /* * Macros to assemble the graphics display list @@ -1892,7 +1927,7 @@ typedef union { Gfx *_g = (Gfx *)(pkt); \ \ _g->words.w0 = _SHIFTL((c), 24, 8) | _SHIFTL((l), 0, 24); \ - _g->words.w1 = (unsigned int)(s); \ + _GBI_SET_W1(_g, (s)); \ } #define gsDma0p(c, s, l) \ @@ -1906,7 +1941,7 @@ typedef union { \ _g->words.w0 = (_SHIFTL((c), 24, 8) | _SHIFTL((p), 16, 8) | \ _SHIFTL((l), 0, 16)); \ - _g->words.w1 = (unsigned int)(s); \ + _GBI_SET_W1(_g, (s)); \ } #define gsDma1p(c, s, l, p) \ @@ -1921,7 +1956,7 @@ typedef union { Gfx *_g = (Gfx *)(pkt); \ _g->words.w0 = (_SHIFTL((c),24,8)|_SHIFTL(((len)-1)/8,19,5)| \ _SHIFTL((ofs)/8,8,8)|_SHIFTL((idx),0,8)); \ - _g->words.w1 = (unsigned int)(adrs); \ + _GBI_SET_W1(_g, (adrs)); \ } #define gsDma2p(c, adrs, len, idx, ofs) \ {{ \ @@ -1958,7 +1993,7 @@ typedef union { Gfx *_g = (Gfx *)(pkt); \ _g->words.w0 = \ _SHIFTL(G_VTX,24,8)|_SHIFTL((n),12,8)|_SHIFTL((v0)+(n),1,7); \ - _g->words.w1 = (unsigned int)(v); \ + _GBI_SET_W1(_g, (v)); \ } # define gsSPVertex(v, n, v0) \ {{ \ @@ -2028,7 +2063,7 @@ typedef union { Gfx *_g = (Gfx *)(pkt); \ \ _g->words.w0 = _SHIFTL((c), 24, 8); \ - _g->words.w1 = (unsigned int)(p0); \ + _GBI_SET_W1(_g, (p0)); \ } #define gsImmp1(c, p0) \ @@ -2070,7 +2105,7 @@ typedef union { \ _g->words.w0 = (_SHIFTL((c), 24, 8) | _SHIFTL((p0), 8, 16) | \ _SHIFTL((p1), 0, 8)); \ - _g->words.w1 = (unsigned int) (dat); \ + _GBI_SET_W1(_g, (dat)); \ } #define gsImmp21(c, p0, p1, dat) \ @@ -2362,7 +2397,7 @@ typedef union { \ _g->words.w0 = _SHIFTL(G_CULLDL, 24, 8) | \ ((0x0f & (vstart))*40); \ - _g->words.w1 = (unsigned int)((0x0f & ((vend)+1))*40); \ + _GBI_SET_W1_RAW(_g, (0x0f & ((vend)+1))*40); \ } #define gsSPCullDisplayList(vstart,vend) \ @@ -2470,7 +2505,7 @@ typedef union { Gfx *_g = (Gfx *)(pkt); \ _g->words.w0 = (_SHIFTL(G_MODIFYVTX,24,8)| \ _SHIFTL((where),16,8)|_SHIFTL((vtx)*2,0,16)); \ - _g->words.w1 = (unsigned int)(val); \ + _GBI_SET_W1_RAW(_g, (val)); \ } # define gsSPModifyVertex(vtx, where, val) \ {{ \ @@ -2515,7 +2550,7 @@ typedef union { { \ Gfx *_g = (Gfx *)(pkt); \ _g->words.w0 = _SHIFTL(G_RDPHALF_1,24,8); \ - _g->words.w1 = (unsigned int)(dl); \ + _GBI_SET_W1(_g, (dl)); \ _g = (Gfx *)(pkt); \ _g->words.w0 = (_SHIFTL(G_BRANCH_Z,24,8)| \ _SHIFTL((vtx)*5,12,12)|_SHIFTL((vtx)*2,0,12)); \ @@ -2544,11 +2579,11 @@ typedef union { { \ Gfx *_g = (Gfx *)(pkt); \ _g->words.w0 = _SHIFTL(G_RDPHALF_1,24,8); \ - _g->words.w1 = (unsigned int)(dl); \ + _GBI_SET_W1(_g, (dl)); \ _g = (Gfx *)(pkt); \ _g->words.w0 = (_SHIFTL(G_BRANCH_Z,24,8)| \ _SHIFTL((vtx)*5,12,12)|_SHIFTL((vtx)*2,0,12)); \ - _g->words.w1 = (unsigned int)(zval); \ + _GBI_SET_W1_RAW(_g, (zval)); \ } #define gsSPBranchLessZraw(dl, vtx, zval) \ @@ -2567,11 +2602,11 @@ typedef union { { \ Gfx *_g = (Gfx *)(pkt); \ _g->words.w0 = _SHIFTL(G_RDPHALF_1,24,8); \ - _g->words.w1 = (unsigned int)(uc_dstart); \ + _GBI_SET_W1(_g, (uc_dstart)); \ _g = (Gfx *)(pkt); \ _g->words.w0 = (_SHIFTL(G_LOAD_UCODE,24,8)| \ _SHIFTL((int)(uc_dsize)-1,0,16)); \ - _g->words.w1 = (unsigned int)(uc_start); \ + _GBI_SET_W1(_g, (uc_start)); \ } #define gsSPLoadUcodeEx(uc_start, uc_dstart, uc_dsize) \ @@ -2603,7 +2638,7 @@ typedef union { Gfx *_g = (Gfx *)(pkt); \ _g->words.w0 = _SHIFTL(G_DMA_IO,24,8)|_SHIFTL((flag),23,1)| \ _SHIFTL((dmem)/8,13,10)|_SHIFTL((size)-1,0,12); \ - _g->words.w1 = (unsigned int)(dram); \ + _GBI_SET_W1(_g, (dram)); \ } #define gsSPDma_io(flag, dmem, dram, size) \ @@ -3033,7 +3068,7 @@ typedef union { Gfx *_g = (Gfx *)(pkt); \ \ _g->words.w0 = _SHIFTL(G_SETGEOMETRYMODE, 24, 8); \ - _g->words.w1 = (unsigned int)(word); \ + _GBI_SET_W1_RAW(_g, (word)); \ } #define gsSPSetGeometryMode(word) \ @@ -3046,7 +3081,7 @@ typedef union { Gfx *_g = (Gfx *)(pkt); \ \ _g->words.w0 = _SHIFTL(G_CLEARGEOMETRYMODE, 24, 8); \ - _g->words.w1 = (unsigned int)(word); \ + _GBI_SET_W1_RAW(_g, (word)); \ } #define gsSPClearGeometryMode(word) \ @@ -3061,7 +3096,7 @@ typedef union { Gfx *_g = (Gfx *)(pkt); \ _g->words.w0 = (_SHIFTL(cmd,24,8)|_SHIFTL(32-(sft)-(len),8,8)| \ _SHIFTL((len)-1,0,8)); \ - _g->words.w1 = (unsigned int)(data); \ + _GBI_SET_W1_RAW(_g, (data)); \ } #define gsSPSetOtherMode(cmd, sft, len, data) \ @@ -3076,7 +3111,7 @@ typedef union { \ _g->words.w0 = (_SHIFTL(cmd, 24, 8) | _SHIFTL(sft, 8, 8) | \ _SHIFTL(len, 0, 8)); \ - _g->words.w1 = (unsigned int)(data); \ + _GBI_SET_W1_RAW(_g, (data)); \ } #define gsSPSetOtherMode(cmd, sft, len, data) \ @@ -3183,14 +3218,14 @@ typedef union { \ _g->words.w0 = _SHIFTL(cmd, 24, 8) | _SHIFTL(fmt, 21, 3) | \ _SHIFTL(siz, 19, 2) | _SHIFTL((width)-1, 0, 12); \ - _g->words.w1 = (unsigned int)(i); \ + _GBI_SET_W1(_g, (i)); \ } #define gsSetImage(cmd, fmt, siz, width, i) \ {{ \ _SHIFTL(cmd, 24, 8) | _SHIFTL(fmt, 21, 3) | \ _SHIFTL(siz, 19, 2) | _SHIFTL((width)-1, 0, 12), \ - (unsigned int)(i) \ + _GBI_STATIC_PTR(i) \ }} #define gDPSetColorImage(pkt, f, s, w, i) gSetImage(pkt, G_SETCIMG, f, s, w, i) @@ -3216,7 +3251,7 @@ typedef union { Gfx *_g = (Gfx *)(pkt); \ \ _g->words.w0 = _SHIFTL(G_SETCOMBINE, 24, 8) | _SHIFTL(muxs0, 0, 24);\ - _g->words.w1 = (unsigned int)(muxs1); \ + _GBI_SET_W1_RAW(_g, (muxs1)); \ } #define gsDPSetCombine(muxs0, muxs1) \ @@ -3251,7 +3286,7 @@ typedef union { G_ACMUX_##Aa0, G_ACMUX_##Ac0) | \ GCCc1w0(G_CCMUX_##a1, G_CCMUX_##c1), \ 0, 24); \ - _g->words.w1 = (unsigned int)(GCCc0w1(G_CCMUX_##b0, \ + _GBI_SET_W1_RAW(_g, (GCCc0w1(G_CCMUX_##b0, \ G_CCMUX_##d0, \ G_ACMUX_##Ab0, \ G_ACMUX_##Ad0) | \ @@ -3260,7 +3295,7 @@ typedef union { G_ACMUX_##Ac1, \ G_CCMUX_##d1, \ G_ACMUX_##Ab1, \ - G_ACMUX_##Ad1)); \ + G_ACMUX_##Ad1))); \ } #define gsDPSetCombineLERP(a0, b0, c0, d0, Aa0, Ab0, Ac0, Ad0, \ @@ -3295,7 +3330,7 @@ typedef union { Gfx *_g = (Gfx *)(pkt); \ \ _g->words.w0 = _SHIFTL(c, 24, 8); \ - _g->words.w1 = (unsigned int)(d); \ + _GBI_SET_W1_RAW(_g, (d)); \ } #define gsDPSetColor(c, d) \ @@ -3387,7 +3422,7 @@ typedef union { Gfx *_g = (Gfx *)(pkt); \ \ _g->words.w0 = _SHIFTL(G_RDPSETOTHERMODE,24,8)|_SHIFTL(mode0,0,24);\ - _g->words.w1 = (unsigned int)(mode1); \ + _GBI_SET_W1_RAW(_g, (mode1)); \ } #define gsDPSetOtherMode(mode0, mode1) \ diff --git a/include/PR/gs2dex.h b/include/PR/gs2dex.h index ced46855..4b583787 100644 --- a/include/PR/gs2dex.h +++ b/include/PR/gs2dex.h @@ -108,7 +108,7 @@ typedef union { uObjBg_t b; uObjScaleBg_t s; long long int force_structure_alignment; -} uObjBg; +} uObjBg ATTRIBUTE_ALIGN(8); /*---------------------------------------------------------------------------* * 2D Objects @@ -136,7 +136,7 @@ typedef struct { typedef union { uObjSprite_t s; long long int force_structure_alignment; -} uObjSprite; +} uObjSprite ATTRIBUTE_ALIGN(8); /*---------------------------------------------------------------------------* * 2D Matrix @@ -151,7 +151,7 @@ typedef struct { typedef union { uObjMtx_t m; long long int force_structure_alignment; -} uObjMtx; +} uObjMtx ATTRIBUTE_ALIGN(8); typedef struct { s16 X, Y; /* s10.2 */ @@ -162,7 +162,7 @@ typedef struct { typedef union { uObjSubMtx_t m; long long int force_structure_alignment; -} uObjSubMtx; +} uObjSubMtx ATTRIBUTE_ALIGN(8); /*---------------------------------------------------------------------------* * Loading into TMEM @@ -218,7 +218,7 @@ typedef union { uObjTxtrTile_t tile; uObjTxtrTLUT_t tlut; long long int force_structure_alignment; -} uObjTxtr; +} uObjTxtr ATTRIBUTE_ALIGN(8); /*---------------------------------------------------------------------------* * Loading into TMEM & 2D Objects diff --git a/include/PR/ultratypes.h b/include/PR/ultratypes.h index 71ef4cb0..049e9deb 100644 --- a/include/PR/ultratypes.h +++ b/include/PR/ultratypes.h @@ -34,6 +34,33 @@ */ #if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS) || defined(TARGET_PC) +#ifdef TARGET_PC +/* On PC, types are already defined by types.h / dolphin/types.h via stdint.h. + * Only define them here if they haven't been defined yet. */ +#include +#include +#ifndef _DOLPHIN_TYPES_H_ +typedef unsigned char u8; +typedef unsigned short u16; +typedef uint32_t u32; +typedef uint64_t u64; +typedef signed char s8; +typedef short s16; +typedef int32_t s32; +typedef int64_t s64; +typedef volatile unsigned char vu8; +typedef volatile unsigned short vu16; +typedef volatile uint32_t vu32; +typedef volatile uint64_t vu64; +typedef volatile signed char vs8; +typedef volatile short vs16; +typedef volatile int32_t vs32; +typedef volatile int64_t vs64; +typedef float f32; +typedef double f64; +#endif /* _DOLPHIN_TYPES_H_ */ +#else +/* N64/GC original types */ typedef unsigned char u8; /* unsigned 8-bit */ typedef unsigned short u16; /* unsigned 16-bit */ typedef unsigned long u32; /* unsigned 32-bit */ @@ -56,10 +83,9 @@ typedef volatile long long vs64; /* signed 64-bit */ typedef float f32; /* single prec floating point */ typedef double f64; /* double prec floating point */ +#endif /* TARGET_PC */ -#ifdef TARGET_PC -#include -#else +#ifndef TARGET_PC #if !defined(_SIZE_T) && !defined(_SIZE_T_) && !defined(_SIZE_T_DEF) #define _SIZE_T #define _SIZE_T_DEF /* exeGCC size_t define label */ diff --git a/include/_mem.h b/include/_mem.h index f61c5b4b..fef694ad 100644 --- a/include/_mem.h +++ b/include/_mem.h @@ -1,6 +1,11 @@ #ifndef _MEM_H #define _MEM_H +#ifdef TARGET_PC +/* On PC, use system for memcpy/memset/memcmp */ +#include +#else + #include "stddef.h" #ifdef __cplusplus @@ -19,4 +24,5 @@ void __fill_mem(void * dst, int val, unsigned long n); #ifdef __cplusplus }; #endif +#endif /* TARGET_PC */ #endif \ No newline at end of file diff --git a/include/audio.h b/include/audio.h index 55affab7..c25340dc 100644 --- a/include/audio.h +++ b/include/audio.h @@ -78,7 +78,7 @@ extern u8 sAdo_MessageSpeedGet(); extern void sAdo_SysLevStop(u8 id); extern void sAdo_SysLevStart(u8 id); -extern void sAdo_OngenPos(u32 p1, u8 p2, const xyz_t* pos); +extern void sAdo_OngenPos(uintptr_t p1, u8 p2, const xyz_t* pos); extern void sAdo_OngenTrgStart(u16 id, const xyz_t* pos); extern void sAdo_SetOutMode(u8 mode); @@ -115,7 +115,7 @@ extern int sAdo_SubGameOK(); extern void sAdo_Tenki(u8 mode); extern void sAdos_KishaStatusTrg(u8 state); -extern void sAdos_KishaStatusLevel(f32 speed, u32 ongenNum1, f32 distance1, u16 angle1, u32 ongenNum2, +extern void sAdos_KishaStatusLevel(f32 speed, uintptr_t ongenNum1, f32 distance1, u16 angle1, uintptr_t ongenNum2, f32 distance2, u16 angle2); extern int sAdos_GetRadioCounter(Radio_c* radio); diff --git a/include/dolphin/ai.h b/include/dolphin/ai.h index 79bd974e..4976264b 100644 --- a/include/dolphin/ai.h +++ b/include/dolphin/ai.h @@ -17,7 +17,11 @@ typedef void (*AIDCallback)(); #define AI_SAMPLERATE_48KHZ 1 AIDCallback AIRegisterDMACallback(AIDCallback callback); +#ifdef TARGET_PC +void AIInitDMA(uintptr_t start_addr, u32 length); +#else void AIInitDMA(u32 start_addr, u32 length); +#endif BOOL AIGetDMAEnableFlag(void); void AIStartDMA(void); void AIStopDMA(void); diff --git a/include/dolphin/ar.h b/include/dolphin/ar.h index b73dffc7..8f849605 100644 --- a/include/dolphin/ar.h +++ b/include/dolphin/ar.h @@ -21,10 +21,15 @@ struct ARQRequest { u32 owner; // _04 u32 type; // _08 u32 priority; // _0C +#ifdef TARGET_PC + uintptr_t source; // _10 + uintptr_t dest; // _18 +#else u32 source; // _10 u32 dest; // _14 - u32 length; // _18 - ARQCallback callback; // _1C +#endif + u32 length; + ARQCallback callback; }; //////////////////////////////////////////// @@ -32,12 +37,20 @@ struct ARQRequest { /////////////// AR FUNCTIONS /////////////// // ARQ functions. void ARQInit(); +#ifdef TARGET_PC +void ARQPostRequest(void* req, u32 owner, u32 type, u32 prio, uintptr_t source, uintptr_t dest, u32 length, void* callback); +#else void ARQPostRequest(ARQRequest* task, u32 owner, u32 type, u32 priority, u32 source, u32 dest, u32 length, ARQCallback callback); +#endif // AR functions. ARQCallback ARRegisterDMACallback(ARQCallback callback); u32 ARGetDMAStatus(); +#ifdef TARGET_PC +void ARStartDMA(u32 type, uintptr_t mainmem_addr, u32 aram_addr, u32 length); +#else void ARStartDMA(u32 type, u32 mainmem_addr, u32 aram_addr, u32 length); +#endif u32 ARAlloc(u32 length); u32 ARInit(u32* stack_index_addr, u32 num_entries); u32 ARGetBaseAddress(); diff --git a/include/dolphin/card/CARDBios.h b/include/dolphin/card/CARDBios.h index e57bb87e..5a83536d 100644 --- a/include/dolphin/card/CARDBios.h +++ b/include/dolphin/card/CARDBios.h @@ -4,8 +4,10 @@ void CARDInit(void); s32 CARDGetResultCode(s32 chan); s32 CARDFreeBlocks(s32 chan, s32 *byteNotUsed, s32 *filesNotUsed); +#ifndef TARGET_PC long CARDGetEncoding(long chan, unsigned short * encode); long CARDGetMemSize(long chan, unsigned short * size); +#endif s32 CARDGetSectorSize(s32 chan, u32 *size); #endif // _DOLPHIN_CARDBIOS_H_ diff --git a/include/dolphin/card/CARDCheck.h b/include/dolphin/card/CARDCheck.h index bc0f8a00..277da2f2 100644 --- a/include/dolphin/card/CARDCheck.h +++ b/include/dolphin/card/CARDCheck.h @@ -2,6 +2,8 @@ #define _DOLPHIN_CARDCHECK_H_ s32 CARDCheckAsync(s32 chan, CARDCallback callback); +#ifndef TARGET_PC long CARDCheck(long chan); +#endif #endif // _DOLPHIN_CARDCHECK_H_ diff --git a/include/dolphin/card/CARDCreate.h b/include/dolphin/card/CARDCreate.h index 35a8206b..5bdd76eb 100644 --- a/include/dolphin/card/CARDCreate.h +++ b/include/dolphin/card/CARDCreate.h @@ -2,6 +2,8 @@ #define _DOLPHIN_CARDCREATE_H_ s32 CARDCreateAsync(s32 chan, const char* fileName, u32 size, CARDFileInfo* fileInfo, CARDCallback callback); +#ifndef TARGET_PC long CARDCreate(long chan, const char * fileName, unsigned long size, struct CARDFileInfo * fileInfo); +#endif #endif // _DOLPHIN_CARDCREATE_H_ diff --git a/include/dolphin/card/CARDDelete.h b/include/dolphin/card/CARDDelete.h index f967340b..574a96a7 100644 --- a/include/dolphin/card/CARDDelete.h +++ b/include/dolphin/card/CARDDelete.h @@ -2,7 +2,9 @@ #define _DOLPHIN_CARDDELETE_H_ s32 CARDFastDeleteAsync(s32 chan, s32 fileNo, CARDCallback callback); +#ifndef TARGET_PC long CARDFastDelete(long chan, long fileNo); +#endif s32 CARDDeleteAsync(s32 chan, const char *fileName, CARDCallback callback); s32 CARDDelete(s32 chan, const char *fileName); diff --git a/include/dolphin/card/CARDFormat.h b/include/dolphin/card/CARDFormat.h index e35fcf2e..2f153fd1 100644 --- a/include/dolphin/card/CARDFormat.h +++ b/include/dolphin/card/CARDFormat.h @@ -1,6 +1,8 @@ #ifndef _DOLPHIN_CARDFORMAT_H_ #define _DOLPHIN_CARDFORMAT_H_ +#ifndef TARGET_PC long CARDFormat(long chan); +#endif #endif // _DOLPHIN_CARDFORMAT_H_ diff --git a/include/dolphin/card/CARDMount.h b/include/dolphin/card/CARDMount.h index e87beb03..49de5745 100644 --- a/include/dolphin/card/CARDMount.h +++ b/include/dolphin/card/CARDMount.h @@ -1,7 +1,9 @@ #ifndef _DOLPHIN_CARDMOUNT_H_ #define _DOLPHIN_CARDMOUNT_H_ +#ifndef TARGET_PC int CARDProbe(long chan); +#endif s32 CARDProbeEx(s32 chan, s32 *memSize, s32 *sectorSize); s32 CARDMountAsync(s32 chan, void *workArea, CARDCallback detachCallback, CARDCallback attachCallback); s32 CARDMount(s32 chan, void *workArea, CARDCallback detachCallback); diff --git a/include/dolphin/card/CARDRdwr.h b/include/dolphin/card/CARDRdwr.h index 383cfadb..641fd995 100644 --- a/include/dolphin/card/CARDRdwr.h +++ b/include/dolphin/card/CARDRdwr.h @@ -1,6 +1,8 @@ #ifndef _DOLPHIN_CARDRDWR_H_ #define _DOLPHIN_CARDRDWR_H_ +#ifndef TARGET_PC long CARDGetXferredBytes(long chan); +#endif #endif // _DOLPHIN_CARDRDWR_H_ diff --git a/include/dolphin/card/CARDRead.h b/include/dolphin/card/CARDRead.h index ec250aa8..058677c2 100644 --- a/include/dolphin/card/CARDRead.h +++ b/include/dolphin/card/CARDRead.h @@ -2,7 +2,9 @@ #define _DOLPHIN_CARDREAD_H_ s32 CARDReadAsync(CARDFileInfo *fileInfo, void *buf, s32 length, s32 offset, CARDCallback callback); +#ifndef TARGET_PC long CARDRead(struct CARDFileInfo * fileInfo, void * buf, long length, long offset); +#endif s32 CARDCancel(CARDFileInfo *fileInfo); #endif // _DOLPHIN_CARDREAD_H_ diff --git a/include/dolphin/card/CARDStat.h b/include/dolphin/card/CARDStat.h index 546ac92f..8bb012d5 100644 --- a/include/dolphin/card/CARDStat.h +++ b/include/dolphin/card/CARDStat.h @@ -22,6 +22,8 @@ typedef struct CARDStat s32 CARDGetStatus(s32 chan, s32 fileNo, CARDStat *stat); s32 CARDSetStatusAsync(s32 chan, s32 fileNo, CARDStat *stat, CARDCallback callback); +#ifndef TARGET_PC long CARDSetStatus(long chan, long fileNo, struct CARDStat * stat); +#endif #endif // _DOLPHIN_CARDSTAT_H_ diff --git a/include/dolphin/card/CARDWrite.h b/include/dolphin/card/CARDWrite.h index 83fb625c..327a3471 100644 --- a/include/dolphin/card/CARDWrite.h +++ b/include/dolphin/card/CARDWrite.h @@ -1,7 +1,9 @@ #ifndef _DOLPHIN_CARDWRITE_H_ #define _DOLPHIN_CARDWRITE_H_ +#ifndef TARGET_PC long CARDWriteAsync(struct CARDFileInfo * fileInfo, const void * buf, long length, long offset, void (* callback)(long, long)); long CARDWrite(struct CARDFileInfo * fileInfo, const void * buf, long length, long offset); +#endif #endif // _DOLPHIN_CARDWRITE_H_ diff --git a/include/dolphin/os/OSUtil.h b/include/dolphin/os/OSUtil.h index 70f5071a..7257ed19 100644 --- a/include/dolphin/os/OSUtil.h +++ b/include/dolphin/os/OSUtil.h @@ -8,8 +8,13 @@ extern "C" { #endif +#ifdef TARGET_PC +#define OSRoundUp32B(x) (((uintptr_t)(x) + 0x1F) & ~((uintptr_t)0x1F)) +#define OSRoundDown32B(x) (((uintptr_t)(x)) & ~((uintptr_t)0x1F)) +#else #define OSRoundUp32B(x) (((u32)(x) + 0x1F) & ~(0x1F)) #define OSRoundDown32B(x) (((u32)(x)) & ~(0x1F)) +#endif #ifdef __cplusplus }; diff --git a/include/dolphin/types.h b/include/dolphin/types.h index 6a92bb32..a4b36934 100644 --- a/include/dolphin/types.h +++ b/include/dolphin/types.h @@ -5,10 +5,18 @@ typedef signed char s8; typedef unsigned char u8; typedef signed short int s16; typedef unsigned short int u16; +#ifdef TARGET_PC +#include +typedef int32_t s32; +typedef uint32_t u32; +typedef int64_t s64; +typedef uint64_t u64; +#else typedef signed long s32; typedef unsigned long u32; typedef signed long long int s64; typedef unsigned long long int u64; +#endif typedef float f32; typedef double f64; @@ -49,8 +57,12 @@ typedef int BOOL; #endif #endif +#ifndef INT_MIN #define INT_MIN -2147483648 +#endif +#ifndef INT_MAX #define INT_MAX 2147483647 +#endif #ifndef NULL #ifndef __cplusplus diff --git a/include/graph.h b/include/graph.h index 14cb1c1d..30aea19e 100644 --- a/include/graph.h +++ b/include/graph.h @@ -272,7 +272,7 @@ extern void graph_dt(GRAPH* graph); #define GRAPH_ALLOC(graph, size) \ ((void*)((graph)->polygon_opaque_thaga.tha.tail_p = \ - (char*)((int)(graph)->polygon_opaque_thaga.tha.tail_p - (int)(size)))) + (char*)((intptr_t)(graph)->polygon_opaque_thaga.tha.tail_p - (intptr_t)(size)))) #define GRAPH_ALLOC_TYPE(graph, type, num) (GRAPH_ALLOC(graph, sizeof(type) * (num))) #if VERSION != VER_GAFU01_00 diff --git a/include/jaudio_NES/audiocommon.h b/include/jaudio_NES/audiocommon.h index 46f27370..397d4b1b 100644 --- a/include/jaudio_NES/audiocommon.h +++ b/include/jaudio_NES/audiocommon.h @@ -97,7 +97,7 @@ extern "C" { Acmd *_a = (Acmd *)pkt; \ \ _a->words.w0 = _SHIFTL(A_CMD_LOADCACHE, 24, 8) | _SHIFTL((len) >> 4, 16, 8) | _SHIFTL(src, 0, 16); \ - _a->words.w1 = (u32)(dst); \ + _a->words.w1 = (u32)(uintptr_t)(dst); \ } #define aLoadBuffer2(pkt, dst, src, len) \ @@ -105,7 +105,7 @@ extern "C" { Acmd *_a = (Acmd *)pkt; \ \ _a->words.w0 = _SHIFTL(A_CMD_LOADBUFFER2, 24, 8) | _SHIFTL((len) >> 4, 16, 8) | _SHIFTL(src, 0, 16); \ - _a->words.w1 = (u32)(dst); \ + _a->words.w1 = (u32)(uintptr_t)(dst); \ } #define aSaveBuffer2(pkt, dst, src, len) \ @@ -113,7 +113,7 @@ extern "C" { Acmd *_a = (Acmd *)pkt; \ \ _a->words.w0 = _SHIFTL(A_CMD_SAVEBUFFER2, 24, 8) | _SHIFTL((len) >> 4, 16, 8) | _SHIFTL(src, 0, 16); \ - _a->words.w1 = (u32)(dst); \ + _a->words.w1 = (u32)(uintptr_t)(dst); \ } #define aInterleave2(pkt, o, l, r, c) \ @@ -969,8 +969,13 @@ typedef enum NASubtrack { #define NA_COMMAND_AUDIO_GROUP_SET_APPLY_SUBTRACK_MASK(group, mask) \ Nap_SetU16(NA_MAKE_COMMAND(AUDIOCMD_SET_GROUP_MASK, group, 0, 0), mask) +#ifdef TARGET_PC +#define NA_COMMAND_AUDIO_SUBTRACK_SET_FILTER(group, subtrack, filterCutoff, pFilter) \ + Nap_SetPtr(NA_MAKE_COMMAND(AUDIOCMD_OP_SUB_SET_FILTER, group, subtrack, filterCutoff), (void*)pFilter) +#else #define NA_COMMAND_AUDIO_SUBTRACK_SET_FILTER(group, subtrack, filterCutoff, pFilter) \ Nap_SetS32(NA_MAKE_COMMAND(AUDIOCMD_OP_SUB_SET_FILTER, group, subtrack, filterCutoff), (s32)pFilter) +#endif #ifdef __cplusplus } diff --git a/include/jaudio_NES/game64.h b/include/jaudio_NES/game64.h index 98f5ea14..f7e79d42 100644 --- a/include/jaudio_NES/game64.h +++ b/include/jaudio_NES/game64.h @@ -30,7 +30,7 @@ extern void Na_VoiceSe(u8, u8, u8, s16, u8, u8); extern void Na_MessageStatus(u8 messageStatus); extern void Na_MessageSpeed(u8 messageSpeed); extern u8 Na_MessageSpeedGet(); -extern void Na_OngenPos(u32 id, u8 index, u16 angle, f32 distance); +extern void Na_OngenPos(uintptr_t id, u8 index, u16 angle, f32 distance); extern void Na_OngenTrgStartSpeed(u16 num, u16 angle, f32 distance, f32 speed); extern void Na_OngenTrgStart(u16 a, u16 angle, f32 distance); extern void Na_SetOutMode(u8 outMode); @@ -48,7 +48,7 @@ extern u8 Na_CheckRestartReady(); extern void Na_Restart(); extern u8 Na_SubGameOK(); extern void Na_KishaStatusTrg(u8); -extern void Na_KishaStatusLevel(f32 speed, u32 ongenNum1, u16 angle1, f32 distance1, u32 ongenNum2, u16 angle2, +extern void Na_KishaStatusLevel(f32 speed, uintptr_t ongenNum1, u16 angle1, f32 distance1, uintptr_t ongenNum2, u16 angle2, f32 distance2); extern void Na_TTKK_ARM(u8); extern void Na_BgmMuteClear(); diff --git a/include/jaudio_NES/sub_sys.h b/include/jaudio_NES/sub_sys.h index ba3df5b4..44793d71 100644 --- a/include/jaudio_NES/sub_sys.h +++ b/include/jaudio_NES/sub_sys.h @@ -12,6 +12,9 @@ extern "C" { extern void Nap_AudioPortInit(void); extern void Nap_SetF32(u32 cmd, f32 param); extern void Nap_SetS32(u32 cmd, s32 param); +#ifdef TARGET_PC +extern void Nap_SetPtr(u32 cmd, void* ptr); +#endif extern void Nap_SetS8(u32 cmd, s8 param); extern void Nap_SetU16(u32 cmd, u16 param); extern s32 Nap_SendStart(void); diff --git a/include/libc/string.h b/include/libc/string.h index 06b1f6cb..31c3a8d9 100644 --- a/include/libc/string.h +++ b/include/libc/string.h @@ -1,5 +1,5 @@ -#ifndef _STRING_H_ -#define _STRING_H_ +#ifndef _LIBC_STRING_H_ +#define _LIBC_STRING_H_ #ifdef TARGET_PC #include_next diff --git a/include/libc64/math64.h b/include/libc64/math64.h index b43dd3d1..0d1340b5 100644 --- a/include/libc64/math64.h +++ b/include/libc64/math64.h @@ -28,7 +28,8 @@ f32 facos(f32); s16 sins(u16); s16 coss(u16); f32 fatan2(f32, f32); -f32 fsqrt(f32); +f32 game_fsqrt(f32); +#define fsqrt game_fsqrt f32 facos(f32); #endif diff --git a/include/libforest/emu64/emu64.hpp b/include/libforest/emu64/emu64.hpp index 70cc7e48..5ea98480 100644 --- a/include/libforest/emu64/emu64.hpp +++ b/include/libforest/emu64/emu64.hpp @@ -628,7 +628,7 @@ class emu64 : public emu64_print { void texture_gen(int tile); void texture_matrix(); void disp_matrix(MtxP mtx); - const char* segchk(u32 seg); + const char* segchk(uintptr_t seg); const char* combine_name(u32 param, u32 type); const char* combine_alpha(int param, int type); const char* combine_tev_color_name(u32 color_param); @@ -639,7 +639,11 @@ class emu64 : public emu64_print { void print_combine(u64 combine); void print_combine_tev(u64 combine_tev); void print_guMtxXFM1F_dol2(MtxP mtx, GXProjectionType type, float x, float y, float z); +#ifdef TARGET_PC + uintptr_t seg2k0(uintptr_t seg); +#else u32 seg2k0(u32 seg); +#endif void setup_texture_tile(int tile); void setup_1tri_2tri_1quad(unsigned int vtx_idx); void draw_1tri_2tri_1quad(unsigned int n_verts, ...); @@ -740,6 +744,18 @@ class emu64 : public emu64_print { /* 0x003C */ u32 cullDL_visible_obj_count; /* 0x0040 */ Gfx* gfx_p; /* 0x0048 */ Gfx gfx; +#if defined(TARGET_PC) && UINTPTR_MAX > 0xFFFFFFFFu + /* On 64-bit, Gfx is 16 bytes (padded uintptr_t w1), but union view structs + * expect an 8-byte layout. This compact copy packs {w0, (u32)w1} so that + * existing casts to Gsettile*, Gsetcolor*, etc. read the correct bitfields. */ + union { + struct { u32 w0; u32 w1; } words_compact; + /* Union views can be cast from &gfx_c */ + } gfx_c; +#define EMU64_GFX_COMPACT_PTR (&this->gfx_c) +#else +#define EMU64_GFX_COMPACT_PTR ((void*)&this->gfx) +#endif /* 0x0050 */ u8 gfx_cmd; /* 0x0054 */ void* work_ptr; /* 0x0058 */ int end_dl; @@ -747,8 +763,14 @@ class emu64 : public emu64_print { /* 0x0060 */ ucode_info* ucode_info_p; /* 0x0064 */ int ucode_type; // maybe? /* 0x0068 */ int _0068; /* ??? */ +#ifdef TARGET_PC + /* On PC, segments and DL_stack store full native pointers */ + /* 0x006C */ uintptr_t segments[EMU64_NUM_SEGMENTS]; + /* */ uintptr_t DL_stack[DL_MAX_STACK_LEVEL]; +#else /* 0x006C */ u32 segments[EMU64_NUM_SEGMENTS]; /* 0x00AC */ u32 DL_stack[DL_MAX_STACK_LEVEL]; +#endif /* 0x00F4 */ s8 DL_stack_level; /* 0x00F8 */ u32 othermode_high; /* 0x00FC */ u32 othermode_low; @@ -765,6 +787,11 @@ class emu64 : public emu64_print { /* 0x03F8 */ Gsettile_dolphin settile_dolphin_cmds[NUM_TILES]; /* 0x0438 */ Gsettilesize_Dolphin settilesize_dolphin_cmds[NUM_TILES]; /* 0x0478 */ Gsetimg_new now_setimg; +#ifdef TARGET_PC + /* Resolved image address — stores the full native pointer from seg2k0, + * avoiding truncation through the 32-bit imgaddr bitfield. */ + uintptr_t resolved_imgaddr; +#endif /* 0x0480 */ u8 tex_edge_alpha; /* 0x0484 */ union { @@ -809,7 +836,7 @@ class emu64 : public emu64_print { /* 0x09E8 */ GXProjectionType projection_type; /* 0x09EC */ GC_Mtx perspective_mtx; /* 0x0A1C */ u32 _0A1C; - /* 0x0A20 */ u32 rdpHalf_1; + /* 0x0A20 */ uintptr_t rdpHalf_1; /* 0x0A24 */ EmuLight lights[NUM_LIGHTS]; /* 0x0B64 */ u8 num_lights; /* 0x0B68 */ u32 lookatx_cnt; diff --git a/include/libforest/gbi_extensions.h b/include/libforest/gbi_extensions.h index 4ddcddb2..71fd27dc 100644 --- a/include/libforest/gbi_extensions.h +++ b/include/libforest/gbi_extensions.h @@ -11,7 +11,11 @@ extern "C" { #ifndef _GBI_STATIC_PTR #ifdef TARGET_PC +#if UINTPTR_MAX > 0xFFFFFFFFu +#define _GBI_STATIC_PTR(s) (uintptr_t)(s) +#else #define _GBI_STATIC_PTR(s) (unsigned int)(uintptr_t)(s) +#endif #else #define _GBI_STATIC_PTR(s) (unsigned int)(s) #endif @@ -1029,7 +1033,7 @@ typedef struct { do { \ Gfx* _g = (Gfx*)(pkt); \ _g->words.w0 = (u32)(_SHIFTL(cmd, 24, 8) | _SHIFTL(tag, 16, 8) | _SHIFTL(param, 0, 16)); \ - _g->words.w1 = (u32)(extra); \ + _GBI_SET_W1_RAW(_g, (extra)); \ } while(0) #define gsDPParam2(cmd, tag, param, extra) \ @@ -1078,7 +1082,7 @@ do { \ do { \ Gfx* _g = (Gfx*)(pkt); \ _g->words.w0 = _SHIFTL(G_LOADTLUT, 24, 8) | _SHIFTL(G_TLUT_DOLPHIN, 22, 2) | _SHIFTL(name, 16, 4) | _SHIFTL(unk, 14, 2) | _SHIFTL(count, 0, 14); \ - _g->words.w1 = (unsigned int)addr; \ + _GBI_SET_W1(_g, addr); \ } while (0) #define gsDPLoadTLUT_Dolphin(name, count, unk, addr) \ @@ -1104,7 +1108,7 @@ do { \ Gfx* _gfx = (Gfx*)(pkt); \ _gfx->words.w0 = _SHIFTL(G_SETTIMG, 24, 8) | _SHIFTL(fmt, 21, 3) | _SHIFTL(siz, 19, 2) | _SHIFTL(1, 18, 1) | \ _SHIFTL((h/4)-1, 10, 8) | _SHIFTL((w-1), 0, 10); \ - _gfx->words.w1 = (unsigned int)img; \ + _GBI_SET_W1(_gfx, img); \ }} #define gDPSetTile_Dolphin(pkt, d_fmt, tile, tlut_name, wrap_s, wrap_t, shift_s, shift_t) \ diff --git a/include/libultra/libultra.h b/include/libultra/libultra.h index 20df57f7..8af85673 100644 --- a/include/libultra/libultra.h +++ b/include/libultra/libultra.h @@ -22,9 +22,14 @@ extern "C" { typedef u64 Z_OSTime; +#if defined(__APPLE__) || defined(__linux__) +/* macOS and Linux (glibc 2.41+ / GCC 15+) provide bcmp/bcopy/bzero — don't redeclare */ +#include +#else int bcmp(void* v1, void* v2, u32 size); void bcopy(void* src, void* dst, size_t n); void bzero(void* ptr, size_t size); +#endif void osSyncPrintf(const char* fmt, ...); void osWritebackDCache(void* vaddr, u32 nbytes); u32 osGetCount(void); diff --git a/include/libultra/osContPad.h b/include/libultra/osContPad.h index 06abbdee..1bb051b9 100644 --- a/include/libultra/osContPad.h +++ b/include/libultra/osContPad.h @@ -50,7 +50,8 @@ extern "C" { #define CONT_ERR_VOICE_NO_RESPONSE 15 #ifdef TARGET_PC -/* 'errno' is a macro on PC (from ), rename the struct member */ +/* 'errno' is a macro on POSIX (from ). Permanently undefine it so + * the struct field named 'errno' works. Game code never uses C errno. */ #ifdef errno #undef errno #endif @@ -66,8 +67,6 @@ typedef struct { /* 0x03 */ s8 stick_y; /* 0x04 */ u8 errno; } OSContPad; -/* Restore errno macro */ -#include #else typedef struct { diff --git a/include/m_player.h b/include/m_player.h index 9447283f..a1adf860 100644 --- a/include/m_player.h +++ b/include/m_player.h @@ -888,7 +888,7 @@ typedef struct player_request_door_s { s16 angle_y; xyz_t player_pos; int type; - u32 label; + uintptr_t label; } mPlayer_request_door_c; typedef struct player_request_outdoor_s { @@ -898,7 +898,7 @@ typedef struct player_request_outdoor_s { typedef struct player_request_demo_wait_s { int umbrella_flag; - u32 label; + uintptr_t label; } mPlayer_request_demo_wait_c; typedef struct player_request_demo_walk_s { @@ -956,16 +956,16 @@ typedef struct player_request_shock_s { } mPlayer_request_shock_c; typedef struct player_request_push_snowball_s { - u32 label; + uintptr_t label; int wade_flag; } mPlayer_request_push_snowball_c; typedef struct player_request_stung_mosquito_s { - u32 label; + uintptr_t label; } mPlayer_request_stung_mosquito_c; typedef struct player_request_notice_mosquito_s { - u32 label; + uintptr_t label; } mPlayer_request_notice_mosquito_c; typedef struct player_request_switch_on_lighthouse_s { @@ -1019,7 +1019,7 @@ typedef struct player_request_wade_s { typedef struct player_request_wade_snowball_s { int dir; xyz_t snowball_dist; - u32 label; + uintptr_t label; } mPlayer_request_wade_snowball_c; typedef struct player_request_push_s { @@ -1515,7 +1515,7 @@ typedef struct player_main_wait_s { } mPlayer_main_wait_c; typedef struct player_main_door_s { - u32 label; + uintptr_t label; } mPlayer_main_door_c; typedef struct player_main_outdoor_s { @@ -1756,7 +1756,7 @@ typedef struct player_main_putin_item_s { typedef struct player_main_demo_wait_s { int effect_id; - u32 label; + uintptr_t label; } mPlayer_main_demo_wait_c; typedef struct player_main_release_creature_s { @@ -1888,7 +1888,7 @@ typedef struct player_main_change_netcloth_s { } mPlayer_main_change_cloth_c; typedef struct player_main_push_snowball_s { - u32 label; + uintptr_t label; } mPlayer_main_push_snowball_c; typedef struct player_main_complete_payment_s { @@ -1902,11 +1902,11 @@ typedef struct player_main_fail_emu_s { } mPlayer_main_fail_emu_c; typedef struct player_main_stung_mosquito_s { - u32 label; + uintptr_t label; } mPlayer_main_stung_mosquito_c; typedef struct player_main_notice_mosquito_s { - u32 label; + uintptr_t label; f32 timer; int msg_mode; } mPlayer_main_notice_mosquito_c; @@ -1924,7 +1924,7 @@ typedef struct player_main_wade_snowball_s { xyz_t end_pos; f32 timer; xyz_t snowball_dist; - u32 snowball_label; + uintptr_t snowball_label; } mPlayer_main_wade_snowball_c; typedef struct player_main_demo_geton_boat_wade_s { @@ -2131,15 +2131,15 @@ struct player_actor_s { /* 0x0E68 */ int umbrella_state; /* 0x0E6C */ s8 unable_hand_item_in_demo; /* 0x0E6D */ s8 able_hand_all_item_in_demo; - /* 0x0E70 */ u32 item_net_catch_label; + /* 0x0E70 */ uintptr_t item_net_catch_label; /* 0x0E74 */ s8 item_net_catch_type; /* 0x0E75 */ s8 item_net_has_catch; - /* 0x0E78 */ u32 item_net_catch_label_request_table[mPlayer_NET_CATCH_TABLE_COUNT]; + /* 0x0E78 */ uintptr_t item_net_catch_label_request_table[mPlayer_NET_CATCH_TABLE_COUNT]; /* 0x0E98 */ s8 item_net_catch_type_request_table[mPlayer_NET_CATCH_TABLE_COUNT]; /* 0x0EA0 */ xyz_t item_net_catch_pos_request_table[mPlayer_NET_CATCH_TABLE_COUNT]; /* 0x0F00 */ f32 item_net_catch_radius_request_table[mPlayer_NET_CATCH_TABLE_COUNT]; /* 0x0F20 */ int item_net_catch_request_use_count; - /* 0x0F24 */ u32 item_net_catch_label_request_force; + /* 0x0F24 */ uintptr_t item_net_catch_label_request_force; /* 0x0F28 */ s8 item_net_catch_type_request_force; /* 0x0F2C */ int item_net_catch_insect_idx; #if VERSION >= VER_GAFU01_00 @@ -2213,7 +2213,7 @@ struct player_actor_s { /* 0x121C */ u16 player_frame_counter; /* 0x121E */ s8 bee_chase_bgm_flag; /* 0x121F */ s8 status_for_bee; - /* 0x1220 */ u32 able_force_speak_label; + /* 0x1220 */ uintptr_t able_force_speak_label; /* 0x1224 */ int player_sunburn_rankup; /* 0x1228 */ int player_sunburn_rankdown; /* 0x122C */ s8 radio_exercise_command_ring_buffer[mPlayer_RADIO_EXERCISE_COMMAND_RING_BUFFER_SIZE]; @@ -2267,9 +2267,9 @@ struct player_actor_s { /* 0x12F8 */ int (*request_main_demo_get_golden_axe_wait_all_proc)(GAME*, int); /* 0x12FC */ int (*check_request_main_priority_proc)(GAME*, int); /* 0x1300 */ void* (*get_door_label_proc)(GAME*); - /* 0x1304 */ int (*Set_Item_net_catch_request_table_proc)(ACTOR*, GAME*, u32, s8, const xyz_t*, f32); + /* 0x1304 */ int (*Set_Item_net_catch_request_table_proc)(ACTOR*, GAME*, uintptr_t, s8, const xyz_t*, f32); /* 0x1308 */ f32 (*Get_Item_net_catch_swing_timer_proc)(ACTOR*, GAME*); - /* 0x130C */ int (*Set_Item_net_catch_request_force_proc)(ACTOR*, GAME*, u32, s8); + /* 0x130C */ int (*Set_Item_net_catch_request_force_proc)(ACTOR*, GAME*, uintptr_t, s8); /* 0x1310 */ void (*Set_force_position_angle_proc)(GAME*, const xyz_t*, const s_xyz*, u8); /* 0x1314 */ u8 (*Get_force_position_angle_proc)(GAME*, xyz_t*, s_xyz*); /* 0x1318 */ int (*Get_WadeEndPos_proc)(GAME*, xyz_t*); @@ -2279,8 +2279,8 @@ struct player_actor_s { /* 0x1328 */ int (*check_able_change_camera_normal_index_proc)(ACTOR*); /* 0x132C */ int (*Check_able_force_speak_label_proc)(GAME*, void*); /* 0x1330 */ int (*check_cancel_request_change_proc_index_proc)(int); - /* 0x1334 */ u32 (*Get_item_net_catch_label_proc)(ACTOR*); - /* 0x1338 */ int (*Change_item_net_catch_label_proc)(ACTOR*, u32, s8); + /* 0x1334 */ uintptr_t (*Get_item_net_catch_label_proc)(ACTOR*); + /* 0x1338 */ int (*Change_item_net_catch_label_proc)(ACTOR*, uintptr_t, s8); /* 0x133C */ int (*Check_StopNet_proc)(ACTOR*, xyz_t*); /* 0x1340 */ int (*Check_HitAxe_proc)(ACTOR*, xyz_t*); /* 0x1344 */ int (*Check_VibUnit_OneFrame_proc)(ACTOR*, const xyz_t*); diff --git a/include/m_player_lib.h b/include/m_player_lib.h index 0ad50ffe..e37ea8ec 100644 --- a/include/m_player_lib.h +++ b/include/m_player_lib.h @@ -137,8 +137,8 @@ extern int mPlib_check_player_warp_forEvent(void); extern int mPlib_Check_HitAxe(xyz_t* pos_p); extern int mPlib_Check_VibUnit_OneFrame(const xyz_t* pos_p); extern int mPlib_Check_StopNet(xyz_t* pos_p); -extern u32 mPlib_Get_item_net_catch_label(void); -extern int mPlib_Change_item_net_catch_label(u32 label, s8 type); +extern uintptr_t mPlib_Get_item_net_catch_label(void); +extern int mPlib_Change_item_net_catch_label(uintptr_t label, s8 type); extern int mPlib_Check_HitScoop(xyz_t* pos_p); extern int mPlib_Check_DigScoop(xyz_t* pos_p); extern int mPlib_Get_address_able_display(void); diff --git a/include/m_scene.h b/include/m_scene.h index 04b9accf..e0d92de8 100644 --- a/include/m_scene.h +++ b/include/m_scene.h @@ -165,6 +165,24 @@ typedef union scene_word_u { Scene_Word_Data_ArrangeFurniture_ct_c arrange_ftr_ct; } Scene_Word_u; +#ifdef TARGET_PC +/* On PC (especially 64-bit), use the properly-typed union members + * instead of casting pointers to u32 via the Misc_c layout */ +#define mSc_DATA_PLAYER(actor_data_p) \ + { .actor = { mSc_SCENE_DATA_TYPE_PLAYER_PTR, 1, actor_data_p } } + +#define mSc_DATA_CTRL_ACTORS(n_actors, ctrl_actor_list_p) \ + { .control_actor = { mSc_SCENE_DATA_TYPE_CTRL_ACTOR_PTR, n_actors, ctrl_actor_list_p } } + +#define mSc_DATA_ACTORS(n_actors, actor_data_p) \ + { .actor = { mSc_SCENE_DATA_TYPE_ACTOR_PTR, n_actors, actor_data_p } } + +#define mSc_DATA_OBJ_BANK(n_banks, bank_list_p) \ + { .object_bank = { mSc_SCENE_DATA_TYPE_OBJECT_EXCHANGE_BANK_PTR, n_banks, bank_list_p } } + +#define mSc_DATA_DOOR_DATA(n_doors, door_data_list_p) \ + { .door_data = { mSc_SCENE_DATA_TYPE_DOOR_DATA_PTR, n_doors, door_data_list_p } } +#else #define mSc_DATA_PLAYER(actor_data_p) \ { \ mSc_SCENE_DATA_TYPE_PLAYER_PTR, 1, 0, 0, (u32)actor_data_p, \ @@ -189,6 +207,7 @@ typedef union scene_word_u { { \ mSc_SCENE_DATA_TYPE_DOOR_DATA_PTR, n_doors, 0, 0, (u32)door_data_list_p, \ } +#endif #define mSc_DATA_FIELDCT(item_type, bg_num, bg_disp_size, room_type, draw_type) \ { \ diff --git a/include/sys_ucode.h b/include/sys_ucode.h index fb96791f..cd64ea11 100644 --- a/include/sys_ucode.h +++ b/include/sys_ucode.h @@ -21,16 +21,16 @@ typedef struct ucode_info_s { #define SP_UCODE_DATA_SIZE 0x800 -extern long long int gspF3DZEX2_NoN_PosLight_fifoDataStart[]; -extern long long int gspF3DZEX2_NoN_PosLight_fifoTextStart[]; +extern s64 gspF3DZEX2_NoN_PosLight_fifoDataStart[]; +extern s64 gspF3DZEX2_NoN_PosLight_fifoTextStart[]; -extern unsigned long long gspS2DEX2_fifoDataStart[]; -extern unsigned long long gspS2DEX2_fifoTextStart[]; +extern u64 gspS2DEX2_fifoDataStart[]; +extern u64 gspS2DEX2_fifoTextStart[]; -extern long long int* ucode_GetPolyTextStart(); -extern long long int* ucode_GetPolyDataStart(); -extern unsigned long long* ucode_GetSpriteTextStart(); -extern unsigned long long* ucode_GetSpriteDataStart(); +extern s64* ucode_GetPolyTextStart(); +extern s64* ucode_GetPolyDataStart(); +extern u64* ucode_GetSpriteTextStart(); +extern u64* ucode_GetSpriteDataStart(); #ifdef __cplusplus }; diff --git a/include/types.h b/include/types.h index 5ae5f9b9..cd834b83 100644 --- a/include/types.h +++ b/include/types.h @@ -5,9 +5,16 @@ /* On PC, we don't have MSL_C - use standard math */ #include #include +#ifdef __APPLE__ +#include /* alloca() on macOS */ +#else #include /* for alloca() */ -/* Metrowerks __alloca is a compiler built-in; map to standard alloca on PC */ +#endif +/* Metrowerks __alloca is a compiler built-in; map to standard alloca on PC. + * Skip on platforms where it's already a built-in or macro to avoid redefinition. */ +#ifndef __alloca #define __alloca alloca +#endif /* Metrowerks __declspec(section "...") is not supported by GCC. * GCC defines __declspec as a builtin keyword, so we must #undef it first. */ #undef __declspec @@ -19,6 +26,16 @@ #include #include "macros.h" +#ifndef ATTRIBUTE_ALIGN +#if defined(__MWERKS__) || defined(__GNUC__) +#define ATTRIBUTE_ALIGN(num) __attribute__((aligned(num))) +#elif defined(_MSC_VER) +#define ATTRIBUTE_ALIGN(num) +#else +#error unknown compiler +#endif +#endif + #define VER_GAFE01_00 0 #define VER_GAFU01_00 1 @@ -36,20 +53,29 @@ typedef signed char s8; typedef signed short s16; +#ifdef TARGET_PC +#include +typedef int32_t s32; +typedef uint32_t u32; +typedef int32_t s32_compat; +typedef uint32_t u32_compat; +typedef int64_t s64 ATTRIBUTE_ALIGN(8); +typedef uint64_t u64 ATTRIBUTE_ALIGN(8); +#include +#else typedef signed long s32; -typedef signed long long s64; -typedef unsigned char u8; -typedef unsigned short u16; typedef unsigned long u32; -#ifndef TARGET_PC +typedef signed long s32_compat; +typedef unsigned long u32_compat; #ifndef _SIZE_T_DEF #define _SIZE_T_DEF typedef unsigned long size_t; #endif -#else -#include -#endif +typedef signed long long s64; typedef unsigned long long u64; +#endif +typedef unsigned char u8; +typedef unsigned short u16; typedef unsigned int uint; typedef volatile u8 vu8; @@ -62,7 +88,11 @@ typedef volatile s32 vs32; typedef volatile s64 vs64; typedef float f32; +#ifdef TARGET_PC +typedef double f64 ATTRIBUTE_ALIGN(8); +#else typedef double f64; +#endif typedef volatile f32 vf32; typedef volatile f64 vf64; @@ -82,7 +112,7 @@ typedef u32 unknown; #define NULL 0 #endif #endif -#ifndef __cplusplus +#if !defined(__cplusplus) && !defined(nullptr) #define nullptr 0 #endif @@ -100,15 +130,6 @@ typedef u32 unknown; #define FLAG_ON(V, F) (((V) & (F)) == 0) #define FLAG_OFF(V, F) (((V) & (F)) != 0) -#ifndef ATTRIBUTE_ALIGN -#if defined(__MWERKS__) || defined(__GNUC__) -#define ATTRIBUTE_ALIGN(num) __attribute__((aligned(num))) -#elif defined(_MSC_VER) -#define ATTRIBUTE_ALIGN(num) -#else -#error unknown compiler -#endif -#endif #define BUTTON_NONE 0x0000 #define BUTTON_CRIGHT 0x0001 diff --git a/pc/CMakeLists.txt b/pc/CMakeLists.txt index c9062959..99cb92e1 100644 --- a/pc/CMakeLists.txt +++ b/pc/CMakeLists.txt @@ -13,15 +13,12 @@ set(CMAKE_CXX_STANDARD 17) option(PC_CONSOLE "Show console window (disables -mwindows, useful for debugging)" OFF) # ============================================================================= -# 32-bit enforcement (required: JSystem casts pointers to u32) +# Platform info # ============================================================================= if(CMAKE_SIZEOF_VOID_P EQUAL 8) - message(FATAL_ERROR - "This project MUST be built as 32-bit (pointer-to-u32 casts in JSystem).\n" - " Windows/MSYS2: Use the MINGW32 shell (not MINGW64)\n" - " Linux: Use a 32-bit toolchain, e.g.:\n" - " cmake .. -DCMAKE_C_COMPILER=i686-linux-gnu-gcc -DCMAKE_CXX_COMPILER=i686-linux-gnu-g++\n" - " OR: cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-linux32.cmake") + message(STATUS "Building as 64-bit (pointer size = 8 bytes)") +else() + message(STATUS "Building as 32-bit (pointer size = 4 bytes)") endif() # Allow mixed C/C++ linkage @@ -36,10 +33,14 @@ add_compile_definitions( VERSION=0 F3DEX_GBI_2 NDEBUG + BUGFIXES # Fix original game bugs (buffer overflows, etc.) that crash on modern platforms _LANGUAGE_C # Required for N64 GBI/ultratypes headers PC_ENHANCEMENTS # Optional visual improvements (MSAA, etc). Remove to get pure PC port. KEYBOARD_TYPING # Physical keyboard typing in text editor. Remove for platforms without keyboards. ) +if(APPLE) + add_compile_definitions(GL_SILENCE_DEPRECATION) +endif() # Common compiler flags (applied to all sources) if(MSVC) @@ -116,8 +117,9 @@ if(NOT SDL2_FOUND) if(NOT SDL2_FOUND) message(FATAL_ERROR "SDL2 not found!\n" - " Linux: sudo apt install libsdl2-dev:i386 (Debian/Ubuntu)\n" - " sudo dnf install SDL2-devel.i686 (Fedora)\n" + " macOS: brew install sdl2\n" + " Linux: sudo apt install libsdl2-dev (Debian/Ubuntu)\n" + " sudo dnf install SDL2-devel (Fedora)\n" " Windows/MSYS2: pacman -S mingw-w64-i686-SDL2\n" " Or download SDL2 development libraries to ${CMAKE_CURRENT_SOURCE_DIR}/lib/SDL2") endif() @@ -126,6 +128,11 @@ include_directories(${SDL2_INCLUDE_DIRS}) message(STATUS "SDL2 include: ${SDL2_INCLUDE_DIRS}") message(STATUS "SDL2 libraries: ${SDL2_LIBRARIES}") +# Fix SDL2 target for 32-bit Linux multilib builds +if(UNIX AND NOT APPLE AND CMAKE_SIZEOF_VOID_P EQUAL 4) + include(cmake/FixSDL2-i686.cmake) +endif() + # ============================================================================= # GLAD (OpenGL 3.3 loader - generated by glad2) # ============================================================================= @@ -313,15 +320,24 @@ set_source_files_properties( PROPERTIES LANGUAGE CXX ) -# jaudio_NES C files use nullptr: define it as NULL for C compilation on PC. -# Generator expression ensures this only applies to C files (C++ has nullptr natively). -add_compile_options($<$:-Dnullptr=NULL>) - # ============================================================================= # Per-source warning settings # ============================================================================= # Decomp code: suppress all warnings (fires heavily on decompiled code) -set(DECOMP_WARN_FLAGS "-w;-fpermissive") +# Clang treats some decomp patterns as errors even with -w: +# -Wno-return-type: missing return values in non-void functions +# -Wno-initializer-overrides: GBI macros use designated initializers with overlapping fields +set(DECOMP_WARN_FLAGS "-w;-fpermissive;-Wno-return-type;-Wno-error=return-type") +if(CMAKE_C_COMPILER_ID MATCHES "Clang") + list(APPEND DECOMP_WARN_FLAGS "-Wno-c99-designator" "-Wno-initializer-overrides") + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + message(FATAL_ERROR + "64-bit builds require GCC (Clang rejects pointer-to-u32 truncation in GBI static initializers).\n" + " macOS: brew install gcc && cmake .. -DCMAKE_C_COMPILER=gcc-15 -DCMAKE_CXX_COMPILER=g++-15\n" + " (adjust version number to match installed GCC, e.g. gcc-14/g++-14)\n" + " Linux: GCC is typically the default compiler.") + endif() +endif() set_source_files_properties(${GAME_C_SOURCES} ${GAME_CXX_SOURCES} PROPERTIES COMPILE_OPTIONS "${DECOMP_WARN_FLAGS}" ) @@ -333,7 +349,10 @@ set(PC_CXX_SOURCES ${PC_SOURCES}) list(FILTER PC_CXX_SOURCES INCLUDE REGEX "\\.cpp$") # Note: -Wno-comment/-Wno-unused-function/-Wno-builtin-declaration-mismatch suppress # warnings from decomp headers (types.h, gfxprint.h, OSRtc.h, libultra.h) that we can't modify. -set(PC_WARN_SUPPRESS "-Wno-unused-parameter;-Wno-sign-compare;-Wno-comment;-Wno-unused-function;-Wno-builtin-declaration-mismatch") +set(PC_WARN_SUPPRESS "-Wno-unused-parameter;-Wno-sign-compare;-Wno-comment;-Wno-unused-function") +if(NOT CMAKE_C_COMPILER_ID MATCHES "Clang") + list(APPEND PC_WARN_SUPPRESS "-Wno-builtin-declaration-mismatch") +endif() set_source_files_properties(${PC_C_SOURCES} PROPERTIES COMPILE_OPTIONS "-Wall;-Wextra;${PC_WARN_SUPPRESS}" ) @@ -368,6 +387,9 @@ endif() if(WIN32) target_link_libraries(ac_pc opengl32 winmm imm32 version setupapi) +elseif(APPLE) + find_package(OpenGL REQUIRED) + target_link_libraries(ac_pc OpenGL::GL "-framework Cocoa" "-framework IOKit" pthread m) else() find_package(OpenGL REQUIRED) target_link_libraries(ac_pc OpenGL::GL dl pthread m) diff --git a/pc/cmake/FixSDL2-i686.cmake b/pc/cmake/FixSDL2-i686.cmake new file mode 100644 index 00000000..5f341b5b --- /dev/null +++ b/pc/cmake/FixSDL2-i686.cmake @@ -0,0 +1,16 @@ +# Fix for i686 multilib - override SDL2::SDL2 target to use 32-bit library +message(STATUS "FixSDL2-i686: Checking for SDL2 target...") +if(TARGET SDL2::SDL2) + message(STATUS "Found SDL2::SDL2 target, overriding to use 32-bit library") + set_target_properties(SDL2::SDL2 PROPERTIES + IMPORTED_LOCATION /usr/lib/i386-linux-gnu/libSDL2-2.0.so.0 + INTERFACE_LINK_LIBRARIES "" + ) +else() + message(STATUS "SDL2::SDL2 target not found, creating it") + add_library(SDL2::SDL2 UNKNOWN IMPORTED) + set_target_properties(SDL2::SDL2 PROPERTIES + IMPORTED_LOCATION /usr/lib/i386-linux-gnu/libSDL2-2.0.so.0 + INTERFACE_INCLUDE_DIRECTORIES "/usr/include;/usr/include/SDL2" + ) +endif() diff --git a/pc/cmake/Toolchain-linux32.cmake b/pc/cmake/Toolchain-linux32.cmake index 863d06f3..6ebe0aeb 100644 --- a/pc/cmake/Toolchain-linux32.cmake +++ b/pc/cmake/Toolchain-linux32.cmake @@ -1,7 +1,38 @@ # CMake toolchain file for Linux i686 (32-bit) cross-compilation set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR i686) -set(CMAKE_C_COMPILER i686-linux-gnu-gcc) -set(CMAKE_CXX_COMPILER i686-linux-gnu-g++) -set(CMAKE_C_FLAGS "-m32" CACHE STRING "") -set(CMAKE_CXX_FLAGS "-m32" CACHE STRING "") + +# Use multilib gcc/g++ instead of cross-compiler +set(CMAKE_C_COMPILER gcc) +set(CMAKE_CXX_COMPILER g++) + +# Force 32-bit compilation. Enable SSE2 for floating point to ensure consistency +# with 64-bit and Windows builds, avoiding x87 excess precision issues that cause +# animation "twitching" and camera positioning bugs. +set(CMAKE_C_FLAGS "-m32 -msse2 -mfpmath=sse" CACHE STRING "") +set(CMAKE_CXX_FLAGS "-m32 -msse2 -mfpmath=sse" CACHE STRING "") +set(CMAKE_EXE_LINKER_FLAGS "-m32" CACHE STRING "") +set(CMAKE_SHARED_LINKER_FLAGS "-m32" CACHE STRING "") + +# Tell CMake to look for 32-bit libraries +set(CMAKE_LIBRARY_ARCHITECTURE i386-linux-gnu) +set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS FALSE) + +# Help CMake find 32-bit libraries +set(CMAKE_LIBRARY_PATH /usr/lib/i386-linux-gnu) +set(CMAKE_FIND_ROOT_PATH /usr/lib/i386-linux-gnu) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH) + +# Explicitly set library paths for 32-bit linking +# Use runtime libraries (.so.0) since i386 dev packages cause dependency conflicts +set(OPENGL_opengl_LIBRARY /usr/lib/i386-linux-gnu/libOpenGL.so.0 CACHE FILEPATH "") +set(OPENGL_glx_LIBRARY /usr/lib/i386-linux-gnu/libGLX.so.0 CACHE FILEPATH "") + +# SDL2 will be fixed by FixSDL2-i686.cmake after find_package() in CMakeLists.txt + +# Workaround: SDL2's multiarch wrapper includes which +# lives in /usr/include//SDL2/. Since we can't install libsdl2-dev:i386 +# (causes glib conflicts), we use the x86_64 headers which are arch-independent. +include_directories(BEFORE SYSTEM /usr/include/x86_64-linux-gnu) diff --git a/pc/include/pc_audio_ptr.h b/pc/include/pc_audio_ptr.h new file mode 100644 index 00000000..8388d0ab --- /dev/null +++ b/pc/include/pc_audio_ptr.h @@ -0,0 +1,40 @@ +/* pc_audio_ptr.h - 64-bit pointer recovery for audio DMA commands. + * Audio Acmd commands pack pointers into u32 w1 fields, truncating on 64-bit. + * Since all audio pointers come from a single contiguous region (the audio heap + * or related allocations), they share the same upper 32 bits. We store that + * prefix once and reconstruct full pointers in rspsim. */ +#ifndef PC_AUDIO_PTR_H +#define PC_AUDIO_PTR_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if UINTPTR_MAX > 0xFFFFFFFFu + +extern uintptr_t pc_audio_ptr_base; + +/* Call once with any audio heap pointer to capture the upper 32 bits */ +static inline void pc_audio_ptr_init(void* any_audio_ptr) { + pc_audio_ptr_base = (uintptr_t)any_audio_ptr & ~(uintptr_t)0xFFFFFFFF; +} + +/* Recover full pointer from truncated u32 in audio command */ +static inline void* pc_audio_recover_ptr(unsigned int truncated) { + if (truncated == 0) return (void*)0; + return (void*)(pc_audio_ptr_base | (uintptr_t)truncated); +} + +#else +/* 32-bit: no recovery needed */ +#define pc_audio_ptr_init(p) ((void)0) +#define pc_audio_recover_ptr(t) ((void*)(uintptr_t)(t)) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* PC_AUDIO_PTR_H */ diff --git a/pc/include/pc_gbi_ptr.h b/pc/include/pc_gbi_ptr.h new file mode 100644 index 00000000..6cc90d73 --- /dev/null +++ b/pc/include/pc_gbi_ptr.h @@ -0,0 +1,64 @@ +/* pc_gbi_ptr.h - 64-bit pointer recovery for GBI display list commands. + * GBI commands store addresses in 32-bit w1 fields. On 64-bit, pointers + * are truncated. This module recovers the full address from the truncated + * value using the executable/arena base addresses. */ +#ifndef PC_GBI_PTR_H +#define PC_GBI_PTR_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(TARGET_PC) && UINTPTR_MAX > 0xFFFFFFFFu + +/* Recover a full 64-bit pointer from a truncated 32-bit GBI w1 value. + * Strategy: all game pointers come from one of two regions: + * 1. Static data in the executable (__DATA segment) — share pc_image_base upper bits + * 2. Arena memory (mmap'd heap) — share arena_memory upper bits + * We check which region the low 32 bits fall into and reconstruct accordingly. */ +extern uintptr_t pc_image_base; +extern u8* arena_memory; + +static inline uintptr_t pc_gbi_recover_ptr(unsigned int truncated) { + if (truncated == 0) return 0; + + /* Check if it's an arena pointer (game heap allocations) */ + uintptr_t arena_base = (uintptr_t)arena_memory; + uintptr_t arena_lo32 = arena_base & 0xFFFFFFFF; + uintptr_t arena_hi32 = arena_base & ~(uintptr_t)0xFFFFFFFF; + uintptr_t arena_end_lo32 = (arena_base + 48u * 1024u * 1024u) & 0xFFFFFFFF; + + if (arena_lo32 <= arena_end_lo32) { + /* Arena doesn't wrap in low 32 bits */ + if (truncated >= arena_lo32 && truncated < arena_end_lo32) { + return arena_hi32 | (uintptr_t)truncated; + } + } + + /* Check if it's a static data pointer (executable image) */ + uintptr_t img_hi32 = pc_image_base & ~(uintptr_t)0xFFFFFFFF; + uintptr_t img_lo32 = pc_image_base & 0xFFFFFFFF; + if (truncated >= img_lo32) { + return img_hi32 | (uintptr_t)truncated; + } + + /* Unknown region — return as-is (may be a segment address or small offset) */ + return (uintptr_t)truncated; +} + +/* Truncate a pointer for storage in a GBI w1 field */ +#define GBI_PTR_TRUNC(p) ((unsigned int)(uintptr_t)(p)) + +#else +/* 32-bit: no recovery needed */ +#define pc_gbi_recover_ptr(t) ((uintptr_t)(t)) +#define GBI_PTR_TRUNC(p) ((unsigned int)(uintptr_t)(p)) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* PC_GBI_PTR_H */ diff --git a/pc/include/pc_gx_internal.h b/pc/include/pc_gx_internal.h index 4832d2e4..d9043bbd 100644 --- a/pc/include/pc_gx_internal.h +++ b/pc/include/pc_gx_internal.h @@ -273,8 +273,8 @@ void pc_gx_texture_cache_invalidate(void); #ifdef PC_ENHANCEMENTS /* EFB capture: store full-res GL texture from GXCopyTex, retrieve on texture load */ -void pc_gx_efb_capture_store(u32 dest_ptr, GLuint gl_tex); -GLuint pc_gx_efb_capture_find(u32 data_ptr); +void pc_gx_efb_capture_store(uintptr_t dest_ptr, GLuint gl_tex); +GLuint pc_gx_efb_capture_find(uintptr_t data_ptr); void pc_gx_efb_capture_cleanup(void); #endif diff --git a/pc/include/pc_platform.h b/pc/include/pc_platform.h index a102eddb..6ca84c99 100644 --- a/pc/include/pc_platform.h +++ b/pc/include/pc_platform.h @@ -2,11 +2,7 @@ #ifndef PC_PLATFORM_H #define PC_PLATFORM_H -/* 32-bit required: decomp code (JSystem, emu64) casts pointers to u32 */ #include -#if UINTPTR_MAX != 0xFFFFFFFFu -#error "This project must be compiled as 32-bit (pointer size != 4 bytes)" -#endif #define SDL_MAIN_HANDLED #include @@ -29,7 +25,12 @@ #define PC_SCREEN_HEIGHT PC_GC_HEIGHT #define PC_WINDOW_TITLE "Animal Crossing" +#if UINTPTR_MAX > 0xFFFFFFFFu +/* 64-bit: structs with pointer fields are larger, need more arena space */ +#define PC_MAIN_MEMORY_SIZE (48 * 1024 * 1024) +#else #define PC_MAIN_MEMORY_SIZE (24 * 1024 * 1024) +#endif #define PC_ARAM_SIZE (16 * 1024 * 1024) #define PC_FIFO_SIZE (256 * 1024) @@ -50,6 +51,11 @@ #include #undef near #undef far +#elif defined(__APPLE__) +#include +#include +#include +#include #else #include #include @@ -68,6 +74,7 @@ extern SDL_GLContext g_pc_gl_context; extern int g_pc_running; extern int g_pc_verbose; extern int g_pc_no_framelimit; +extern int g_pc_fast_forward; extern int g_pc_time_override; extern int g_pc_min_override; extern int g_pc_sec_override; @@ -96,12 +103,23 @@ int pc_platform_poll_events(void); /* --- Crash protection (VEH + setjmp/longjmp) --- */ void pc_crash_protection_init(void); void pc_crash_set_jmpbuf(jmp_buf* buf); /* NULL to disable */ -unsigned int pc_crash_get_addr(void); -unsigned int pc_crash_get_data_addr(void); +uintptr_t pc_crash_get_addr(void); +uintptr_t pc_crash_get_data_addr(void); /* EXE image range for seg2k0 pointer disambiguation (vs N64 segment addresses) */ -extern unsigned int pc_image_base; -extern unsigned int pc_image_end; +extern uintptr_t pc_image_base; +extern uintptr_t pc_image_end; + +/* Compile-time type validation */ +#ifdef __cplusplus +static_assert(sizeof(u32) == 4, "u32 must be 4 bytes"); +static_assert(sizeof(u16) == 2, "u16 must be 2 bytes"); +static_assert(sizeof(uintptr_t) == sizeof(void*), "uintptr_t must match pointer size"); +#else +_Static_assert(sizeof(u32) == 4, "u32 must be 4 bytes"); +_Static_assert(sizeof(u16) == 2, "u16 must be 2 bytes"); +_Static_assert(sizeof(uintptr_t) == sizeof(void*), "uintptr_t must match pointer size"); +#endif /* --- Model viewer --- */ extern int g_pc_model_viewer; diff --git a/pc/include/pc_types.h b/pc/include/pc_types.h index 35339193..f2cb26d7 100644 --- a/pc/include/pc_types.h +++ b/pc/include/pc_types.h @@ -6,16 +6,28 @@ * Included automatically via pc_platform.h. */ -typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned long u32; -typedef unsigned long long u64; -typedef signed char s8; -typedef signed short s16; -typedef signed long s32; -typedef signed long long s64; +#include + +#ifndef ATTRIBUTE_ALIGN +#if defined(__MWERKS__) || defined(__GNUC__) || defined(__clang__) +#define ATTRIBUTE_ALIGN(num) __attribute__((aligned(num))) +#elif defined(_MSC_VER) +#define ATTRIBUTE_ALIGN(num) __declspec(align(num)) +#else +#define ATTRIBUTE_ALIGN(num) +#endif +#endif + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64 ATTRIBUTE_ALIGN(8); +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64 ATTRIBUTE_ALIGN(8); typedef float f32; -typedef double f64; +typedef double f64 ATTRIBUTE_ALIGN(8); typedef int BOOL; #ifndef TRUE diff --git a/pc/src/pc_aram.c b/pc/src/pc_aram.c index b54a4c4c..237fb2da 100644 --- a/pc/src/pc_aram.c +++ b/pc/src/pc_aram.c @@ -38,27 +38,27 @@ void ARFree(u32* addr) { } /* type 0 = MRAM→ARAM, type 1 = ARAM→MRAM. params are always (type, mram, aram). */ -void ARStartDMA(u32 type, u32 mram_addr, u32 aram_addr, u32 length) { +void ARStartDMA(u32 type, uintptr_t mram_addr, u32 aram_addr, u32 length) { if (!aram_base) return; /* some code passes (aram_base + offset) instead of just the offset */ - u32 base = (u32)(uintptr_t)aram_base; + uintptr_t base = (uintptr_t)aram_base; if (aram_addr >= base && aram_addr < base + PC_ARAM_SIZE) { - aram_addr -= base; + aram_addr -= (u32)base; } if (length > PC_ARAM_SIZE || aram_addr > PC_ARAM_SIZE - length) { /* OOB read: zero-fill dest so caller doesn't get garbage (cap 1MB) */ if (type == 1 && mram_addr != 0 && length > 0 && length <= 0x100000) { - memset((void*)(uintptr_t)mram_addr, 0, length); + memset((void*)mram_addr, 0, length); } return; } if (type == 0) { - memcpy(aram_base + aram_addr, (void*)(uintptr_t)mram_addr, length); + memcpy(aram_base + aram_addr, (void*)mram_addr, length); } else { - memcpy((void*)(uintptr_t)mram_addr, aram_base + aram_addr, length); + memcpy((void*)mram_addr, aram_base + aram_addr, length); } } @@ -69,13 +69,13 @@ BOOL ARCheckInit(void) { return aram_base != NULL; } * ARQPostRequest's source/dest order differs from ARStartDMA's, so we remap. */ void ARQInit(void) {} void ARQPostRequest(void* req, u32 owner, u32 type, u32 prio, - u32 source, u32 dest, u32 length, void* callback) { + uintptr_t source, uintptr_t dest, u32 length, void* callback) { if (type == 0) { - ARStartDMA(type, source, dest, length); /* source=mram, dest=aram */ + ARStartDMA(type, source, (u32)dest, length); /* source=mram, dest=aram */ } else { - ARStartDMA(type, dest, source, length); /* source=aram, dest=mram — swapped */ + ARStartDMA(type, dest, (u32)source, length); /* source=aram, dest=mram — swapped */ } - if (callback) ((void (*)(u32))callback)((u32)(uintptr_t)req); + if (callback) ((void (*)(uintptr_t))callback)((uintptr_t)req); } void ARQFlushQueue(void) {} diff --git a/pc/src/pc_audio.c b/pc/src/pc_audio.c index 3fee16a6..4e30ef1f 100644 --- a/pc/src/pc_audio.c +++ b/pc/src/pc_audio.c @@ -9,8 +9,13 @@ * so OS preemption of the game thread doesn't cause audio dropouts. */ #include "pc_platform.h" +#include "pc_audio_ptr.h" #include "jaudio_NES/audiothread.h" +#if UINTPTR_MAX > 0xFFFFFFFFu +uintptr_t pc_audio_ptr_base = 0; +#endif + #define PC_AUDIO_SAMPLE_RATE 32000 /* lock-free SPSC ring buffer (producer=audio thread, consumer=SDL callback) */ @@ -113,8 +118,8 @@ void AIInit(u8* stack) { } } -void AIInitDMA(u32 addr, u32 size) { - s16* src = (s16*)(uintptr_t)addr; +void AIInitDMA(uintptr_t addr, u32 size) { + s16* src = (s16*)addr; u32 n_samples = size / sizeof(s16); n_samples &= ~1u; /* whole stereo frames */ diff --git a/pc/src/pc_dvd.c b/pc/src/pc_dvd.c index 1996c365..1e4c88c2 100644 --- a/pc/src/pc_dvd.c +++ b/pc/src/pc_dvd.c @@ -81,19 +81,51 @@ s32 DVDConvertPathToEntrynum(const char* path) { return idx; } -/* DVDFileInfo: 0x3C bytes. We store FILE* in the DVDCommandBlock area at offset 0x18. */ -/* For disc-image backed files, FILE* is set to sentinel DISC_SENTINEL, - * and the disc offset is stored in startAddr (0x30). */ +/* DVDFileInfo field access — compute offsets from struct layout so they work on 64-bit. + * On GC (32-bit), DVDCommandBlock has 4-byte pointers → DVDFileInfo is 0x3C bytes. + * On 64-bit, pointers are 8 bytes → DVDCommandBlock grows, shifting all fields. + * + * DVDCommandBlock layout (see dolphin/dvd.h): + * DVDCommandBlock* next, *prev; // 2 pointers + * u32 command, state, offset, length; // 4 × u32 + * void* addr; // 1 pointer ← we store FILE* here + * u32 currTransferSize, transferredSize; // 2 × u32 + * DVDDiskID* id; // 1 pointer + * DVDCBCallback callback; // 1 pointer (func ptr) + * void* userData; // 1 pointer + * + * DVDFileInfo = { DVDCommandBlock cb; u32 startAddr; u32 length; DVDCallback callback; } + */ +#include + +/* Mirror the struct layout locally to compute correct offsets without + * pulling in the full dolphin/dvd.h (which conflicts with our void* stubs). */ +typedef struct { + void* next; void* prev; /* 2 ptrs */ + u32 command; s32 state; + u32 offset_; u32 length_; + void* addr; /* FILE* stored here */ + u32 currTransferSize; u32 transferredSize; + void* id; void (*callback_)(s32, void*); void* userData; +} DVDCommandBlock_PC; + +typedef struct { + DVDCommandBlock_PC cb; + u32 startAddr; + u32 length; + void (*callback)(s32, void*); +} DVDFileInfo_PC; + #define DISC_SENTINEL ((FILE*)(uintptr_t)0xDEADC0DE) static FILE** dvd_fi_fp(void* fileInfo) { - return (FILE**)((u8*)fileInfo + 0x18); + return (FILE**)((u8*)fileInfo + offsetof(DVDFileInfo_PC, cb) + offsetof(DVDCommandBlock_PC, addr)); } static u32* dvd_fi_length(void* fileInfo) { - return (u32*)((u8*)fileInfo + 0x34); + return (u32*)((u8*)fileInfo + offsetof(DVDFileInfo_PC, length)); } static u32* dvd_fi_startAddr(void* fileInfo) { - return (u32*)((u8*)fileInfo + 0x30); + return (u32*)((u8*)fileInfo + offsetof(DVDFileInfo_PC, startAddr)); } BOOL DVDFastOpen(s32 entrynum, void* fileInfo) { @@ -107,7 +139,7 @@ BOOL DVDFastOpen(s32 entrynum, void* fileInfo) { if (pc_disc_is_open()) { u32 disc_off, disc_sz; if (pc_disc_find_file(path, &disc_off, &disc_sz)) { - memset(fileInfo, 0, 0x3C); + memset(fileInfo, 0, sizeof(DVDFileInfo_PC)); *dvd_fi_fp(fileInfo) = DISC_SENTINEL; *dvd_fi_startAddr(fileInfo) = disc_off; *dvd_fi_length(fileInfo) = disc_sz; @@ -137,7 +169,7 @@ BOOL DVDFastOpen(s32 entrynum, void* fileInfo) { len = (u32)ftell(fp); fseek(fp, 0, SEEK_SET); - memset(fileInfo, 0, 0x3C); + memset(fileInfo, 0, sizeof(DVDFileInfo_PC)); *dvd_fi_fp(fileInfo) = fp; *dvd_fi_startAddr(fileInfo) = 0; *dvd_fi_length(fileInfo) = len; diff --git a/pc/src/pc_gx.c b/pc/src/pc_gx.c index bce3ea9d..b065942f 100644 --- a/pc/src/pc_gx.c +++ b/pc/src/pc_gx.c @@ -39,12 +39,12 @@ static void pc_gx_update_aspect(void) { /* EFB capture: keep full-res GL textures from GXCopyTex instead of downsampling to 640x480 */ #define MAX_EFB_CAPTURES 4 static struct { - u32 dest_ptr; + uintptr_t dest_ptr; GLuint gl_tex; } s_efb_captures[MAX_EFB_CAPTURES]; static int s_efb_capture_count = 0; -void pc_gx_efb_capture_store(u32 dest_ptr, GLuint gl_tex) { +void pc_gx_efb_capture_store(uintptr_t dest_ptr, GLuint gl_tex) { for (int i = 0; i < s_efb_capture_count; i++) { if (s_efb_captures[i].dest_ptr == dest_ptr) { if (s_efb_captures[i].gl_tex) @@ -65,7 +65,7 @@ void pc_gx_efb_capture_store(u32 dest_ptr, GLuint gl_tex) { s_efb_capture_count++; } -GLuint pc_gx_efb_capture_find(u32 data_ptr) { +GLuint pc_gx_efb_capture_find(uintptr_t data_ptr) { for (int i = 0; i < s_efb_capture_count; i++) { if (s_efb_captures[i].dest_ptr == data_ptr) return s_efb_captures[i].gl_tex; @@ -1643,7 +1643,7 @@ static void pc_gx_copy_tex_execute(void* dest, GXBool clear) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - pc_gx_efb_capture_store((u32)(uintptr_t)dest, efb_tex); + pc_gx_efb_capture_store((uintptr_t)dest, efb_tex); glBindTexture(GL_TEXTURE_2D, 0); } #else diff --git a/pc/src/pc_gx_texture.c b/pc/src/pc_gx_texture.c index 4a34855f..7fcf75a3 100644 --- a/pc/src/pc_gx_texture.c +++ b/pc/src/pc_gx_texture.c @@ -20,12 +20,12 @@ u16 s_tlut_first_word[16]; #define TEX_CACHE_SIZE 2048 typedef struct { - u32 data_ptr; + uintptr_t data_ptr; u16 width; u16 height; u32 format; u32 tlut_name; /* TLUT slot for CI4/CI8, 0xFFFFFFFF for non-indexed */ - u32 tlut_ptr; + uintptr_t tlut_ptr; u32 tlut_hash; /* FNV-1a of TLUT data + metadata */ u32 data_hash; /* FNV-1a of first N bytes */ GLuint gl_tex; @@ -99,8 +99,8 @@ static int tex_cache_hits = 0; static int tex_cache_misses = 0; /* Linear scan. Fine for <=2048 entries at ~100% hit rate. */ -static TexCacheEntry* tex_cache_find(u32 data_ptr, int w, int h, u32 fmt, u32 tlut_name, - u32 tlut_ptr, u32 tlut_hash, u32 data_hash) { +static TexCacheEntry* tex_cache_find(uintptr_t data_ptr, int w, int h, u32 fmt, u32 tlut_name, + uintptr_t tlut_ptr, u32 tlut_hash, u32 data_hash) { for (int i = 0; i < tex_cache_count; i++) { TexCacheEntry* e = &tex_cache[i]; if (e->data_ptr == data_ptr && e->width == w && e->height == h && @@ -112,8 +112,8 @@ static TexCacheEntry* tex_cache_find(u32 data_ptr, int w, int h, u32 fmt, u32 tl return NULL; } -static TexCacheEntry* tex_cache_insert(u32 data_ptr, int w, int h, u32 fmt, u32 tlut_name, - u32 tlut_ptr, u32 tlut_hash, u32 data_hash, GLuint gl_tex) { +static TexCacheEntry* tex_cache_insert(uintptr_t data_ptr, int w, int h, u32 fmt, u32 tlut_name, + uintptr_t tlut_ptr, u32 tlut_hash, u32 data_hash, GLuint gl_tex) { if (tex_cache_count >= TEX_CACHE_SIZE) { /* evict oldest half */ int half = TEX_CACHE_SIZE / 2; @@ -170,78 +170,80 @@ void pc_gx_texture_shutdown(void) { /* --- texture object API --- */ -/* GXTexObj layout for PC: 22 u32s (88 bytes) */ -#define TEXOBJ_IMAGE_PTR 0 -#define TEXOBJ_WIDTH 1 -#define TEXOBJ_HEIGHT 2 -#define TEXOBJ_FORMAT 3 -#define TEXOBJ_WRAP_S 4 -#define TEXOBJ_WRAP_T 5 -#define TEXOBJ_MIPMAP 6 -#define TEXOBJ_MIN_FILTER 7 -#define TEXOBJ_MAG_FILTER 8 -#define TEXOBJ_MIN_LOD 9 -#define TEXOBJ_MAX_LOD 10 -#define TEXOBJ_LOD_BIAS 11 -#define TEXOBJ_BIAS_CLAMP 12 -#define TEXOBJ_EDGE_LOD 13 -#define TEXOBJ_MAX_ANISO 14 -#define TEXOBJ_GL_TEX 15 -#define TEXOBJ_CI_FORMAT 16 -#define TEXOBJ_TLUT_NAME 17 -#define TEXOBJ_SIZE 22 /* total u32 count */ - -/* GXTlutObj layout (4 u32s) */ -#define TLUTOBJ_DATA 0 -#define TLUTOBJ_FORMAT 1 -#define TLUTOBJ_N_ENTRIES 2 +/* PC-side texture object — replaces the u32[] array approach so pointers + * survive on both 32-bit and 64-bit platforms. */ +typedef struct { + void* image_ptr; + u32 width; + u32 height; + u32 format; + u32 wrap_s; + u32 wrap_t; + u32 mipmap; + u32 min_filter; + u32 mag_filter; + f32 min_lod; + f32 max_lod; + f32 lod_bias; + u32 bias_clamp; + u32 edge_lod; + u32 max_aniso; + GLuint gl_tex; + u32 ci_format; + u32 tlut_name; +} PCTexObj; + +typedef struct { + void* data; + u32 format; + u32 n_entries; +} PCTlutObj; void GXInitTexObj(void* obj, void* image_ptr, u16 width, u16 height, u32 format, u32 wrap_s, u32 wrap_t, u8 mipmap) { - u32* o = (u32*)obj; - memset(o, 0, TEXOBJ_SIZE * sizeof(u32)); - o[TEXOBJ_IMAGE_PTR] = (u32)(uintptr_t)image_ptr; - o[TEXOBJ_WIDTH] = width; - o[TEXOBJ_HEIGHT] = height; - o[TEXOBJ_FORMAT] = format; - o[TEXOBJ_WRAP_S] = wrap_s; - o[TEXOBJ_WRAP_T] = wrap_t; - o[TEXOBJ_MIPMAP] = mipmap; - o[TEXOBJ_MIN_FILTER] = 1; /* GX_LINEAR */ - o[TEXOBJ_MAG_FILTER] = 1; /* GX_LINEAR */ + PCTexObj* o = (PCTexObj*)obj; + memset(o, 0, sizeof(PCTexObj)); + o->image_ptr = image_ptr; + o->width = width; + o->height = height; + o->format = format; + o->wrap_s = wrap_s; + o->wrap_t = wrap_t; + o->mipmap = mipmap; + o->min_filter = 1; /* GX_LINEAR */ + o->mag_filter = 1; /* GX_LINEAR */ } void GXInitTexObjCI(void* obj, void* image_ptr, u16 width, u16 height, u32 format, u32 wrap_s, u32 wrap_t, u8 mipmap, u32 tlut_name) { GXInitTexObj(obj, image_ptr, width, height, format, wrap_s, wrap_t, mipmap); - u32* o = (u32*)obj; - o[TEXOBJ_CI_FORMAT] = format; - o[TEXOBJ_TLUT_NAME] = tlut_name; + PCTexObj* o = (PCTexObj*)obj; + o->ci_format = format; + o->tlut_name = tlut_name; } void GXInitTexObjData(void* obj, void* image_ptr) { - u32* o = (u32*)obj; - o[TEXOBJ_IMAGE_PTR] = (u32)(uintptr_t)image_ptr; + PCTexObj* o = (PCTexObj*)obj; + o->image_ptr = image_ptr; } void GXInitTexObjLOD(void* obj, u32 min_filt, u32 mag_filt, f32 min_lod, f32 max_lod, f32 lod_bias, GXBool bias_clamp, GXBool edge_lod, u32 max_aniso) { - u32* o = (u32*)obj; - o[TEXOBJ_MIN_FILTER] = min_filt; - o[TEXOBJ_MAG_FILTER] = mag_filt; - /* store floats as bits */ - memcpy(&o[TEXOBJ_MIN_LOD], &min_lod, sizeof(f32)); - memcpy(&o[TEXOBJ_MAX_LOD], &max_lod, sizeof(f32)); - memcpy(&o[TEXOBJ_LOD_BIAS], &lod_bias, sizeof(f32)); - o[TEXOBJ_BIAS_CLAMP] = bias_clamp; - o[TEXOBJ_EDGE_LOD] = edge_lod; - o[TEXOBJ_MAX_ANISO] = max_aniso; + PCTexObj* o = (PCTexObj*)obj; + o->min_filter = min_filt; + o->mag_filter = mag_filt; + o->min_lod = min_lod; + o->max_lod = max_lod; + o->lod_bias = lod_bias; + o->bias_clamp = bias_clamp; + o->edge_lod = edge_lod; + o->max_aniso = max_aniso; } void GXInitTexObjWrapMode(void* obj, u32 s, u32 t) { - u32* o = (u32*)obj; - o[TEXOBJ_WRAP_S] = s; - o[TEXOBJ_WRAP_T] = t; + PCTexObj* o = (PCTexObj*)obj; + o->wrap_s = s; + o->wrap_t = t; } /* --- GC texture format decoders (tile layout -> linear RGBA8) --- */ @@ -598,21 +600,49 @@ void GXLoadTexObj(void* obj, u32 id) { if (id >= 8 && id != 0xFF && id < 0x100) return; if (id >= 8) return; - u32* o = (u32*)obj; - void* image_ptr = (void*)(uintptr_t)o[TEXOBJ_IMAGE_PTR]; - int width = (int)o[TEXOBJ_WIDTH]; - int height = (int)o[TEXOBJ_HEIGHT]; - u32 format = o[TEXOBJ_FORMAT]; - u32 wrap_s = o[TEXOBJ_WRAP_S], wrap_t = o[TEXOBJ_WRAP_T]; - u32 tlut_key = (format == GX_TF_C4 || format == GX_TF_C8) ? o[TEXOBJ_TLUT_NAME] : 0xFFFFFFFF; - u32 tlut_ptr_key = 0; + PCTexObj* o = (PCTexObj*)obj; + +#ifdef TARGET_PC + { + static int tex_diag_frame = 0; + static int tex_diag_count = 0; + tex_diag_count++; + if (0 && tex_diag_frame < 3 && tex_diag_count <= 30) { /* disabled */ + fprintf(stderr, "[TEX] id=%d fmt=0x%x %dx%d ptr=%p tlut=%d", + id, o->format, o->width, o->height, o->image_ptr, o->tlut_name); + if (o->image_ptr) { + u8* d = (u8*)o->image_ptr; + fprintf(stderr, " data=[%02x%02x%02x%02x]", d[0], d[1], d[2], d[3]); + } + if ((o->format == 8 || o->format == 9) && o->tlut_name < 16) { + fprintf(stderr, " tlut_data=%p entries=%d is_be=%d", + g_gx.tlut[o->tlut_name].data, + g_gx.tlut[o->tlut_name].n_entries, + g_gx.tlut[o->tlut_name].is_be); + if (g_gx.tlut[o->tlut_name].data) { + u16* pal = (u16*)g_gx.tlut[o->tlut_name].data; + fprintf(stderr, " pal=[%04x %04x %04x %04x]", pal[0], pal[1], pal[2], pal[3]); + } + } + fprintf(stderr, "\n"); + } + if (tex_diag_count > 100) { tex_diag_count = 0; tex_diag_frame++; } + } +#endif + void* image_ptr = o->image_ptr; + int width = (int)o->width; + int height = (int)o->height; + u32 format = o->format; + u32 wrap_s = o->wrap_s, wrap_t = o->wrap_t; + u32 tlut_key = (format == GX_TF_C4 || format == GX_TF_C8) ? o->tlut_name : 0xFFFFFFFF; + uintptr_t tlut_ptr_key = 0; u32 tlut_hash_key = 0; - u32 filter_mode = o[TEXOBJ_MIN_FILTER]; + u32 filter_mode = o->min_filter; if (format == GX_TF_C4 || format == GX_TF_C8) { - int tlut_name = (int)o[TEXOBJ_TLUT_NAME]; + int tlut_name = (int)o->tlut_name; if (tlut_name >= 0 && tlut_name < 16 && g_gx.tlut[tlut_name].data) { - tlut_ptr_key = (u32)(uintptr_t)g_gx.tlut[tlut_name].data; + tlut_ptr_key = (uintptr_t)g_gx.tlut[tlut_name].data; tlut_hash_key = tlut_content_hash(g_gx.tlut[tlut_name].data, g_gx.tlut[tlut_name].format, g_gx.tlut[tlut_name].n_entries, @@ -623,13 +653,13 @@ void GXLoadTexObj(void* obj, u32 id) { #ifdef PC_ENHANCEMENTS /* EFB capture bypass: use full-res FBO texture instead of re-decoding */ { - GLuint efb_tex = pc_gx_efb_capture_find(o[TEXOBJ_IMAGE_PTR]); + GLuint efb_tex = pc_gx_efb_capture_find((uintptr_t)image_ptr); if (efb_tex) { glBindTexture(GL_TEXTURE_2D, efb_tex); GLenum gl_filter = filter_mode ? GL_LINEAR : GL_NEAREST; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter); - o[TEXOBJ_GL_TEX] = efb_tex; + o->gl_tex = efb_tex; g_gx.gl_textures[id] = efb_tex; g_gx.tex_obj_w[id] = width; g_gx.tex_obj_h[id] = height; @@ -644,7 +674,8 @@ void GXLoadTexObj(void* obj, u32 id) { u32 hash = tex_content_hash(image_ptr, width, height, format); /* cache lookup */ - TexCacheEntry* cached = tex_cache_find(o[TEXOBJ_IMAGE_PTR], width, height, format, tlut_key, + uintptr_t data_ptr_key = (uintptr_t)image_ptr; + TexCacheEntry* cached = tex_cache_find(data_ptr_key, width, height, format, tlut_key, tlut_ptr_key, tlut_hash_key, hash); if (cached) { tex_cache_hits++; @@ -669,7 +700,7 @@ void GXLoadTexObj(void* obj, u32 id) { cached->min_filter = filter_mode; } - o[TEXOBJ_GL_TEX] = tex; + o->gl_tex = tex; g_gx.gl_textures[id] = tex; g_gx.tex_obj_w[id] = width; g_gx.tex_obj_h[id] = height; @@ -687,7 +718,7 @@ void GXLoadTexObj(void* obj, u32 id) { int tp_tlut_entries = 0; int tp_tlut_is_be = 1; if ((format == GX_TF_C4 || format == GX_TF_C8)) { - int tlut_name = (int)o[TEXOBJ_TLUT_NAME]; + int tlut_name = (int)o->tlut_name; if (tlut_name >= 0 && tlut_name < 16 && g_gx.tlut[tlut_name].data) { tp_tlut = g_gx.tlut[tlut_name].data; tp_tlut_entries = g_gx.tlut[tlut_name].n_entries; @@ -709,14 +740,14 @@ void GXLoadTexObj(void* obj, u32 id) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, gl_ws); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gl_wt); - TexCacheEntry* entry = tex_cache_insert(o[TEXOBJ_IMAGE_PTR], width, height, format, + TexCacheEntry* entry = tex_cache_insert(data_ptr_key, width, height, format, tlut_key, tlut_ptr_key, tlut_hash_key, hash, hd_tex); entry->wrap_s = wrap_s; entry->wrap_t = wrap_t; entry->min_filter = filter_mode; entry->external = 1; - o[TEXOBJ_GL_TEX] = hd_tex; + o->gl_tex = hd_tex; g_gx.gl_textures[id] = hd_tex; g_gx.tex_obj_w[id] = width; g_gx.tex_obj_h[id] = height; @@ -735,7 +766,7 @@ void GXLoadTexObj(void* obj, u32 id) { if (rgba) { u8 palette[256][4]; if (format == GX_TF_C4 || format == GX_TF_C8) { - int tlut_name = (int)o[TEXOBJ_TLUT_NAME]; + int tlut_name = (int)o->tlut_name; if (tlut_name >= 0 && tlut_name < 16 && g_gx.tlut[tlut_name].data) { build_palette(g_gx.tlut[tlut_name].data, g_gx.tlut[tlut_name].format, @@ -779,13 +810,13 @@ void GXLoadTexObj(void* obj, u32 id) { } /* insert into cache */ - TexCacheEntry* entry = tex_cache_insert(o[TEXOBJ_IMAGE_PTR], width, height, format, tlut_key, + TexCacheEntry* entry = tex_cache_insert(data_ptr_key, width, height, format, tlut_key, tlut_ptr_key, tlut_hash_key, hash, tex); entry->wrap_s = wrap_s; entry->wrap_t = wrap_t; entry->min_filter = filter_mode; - o[TEXOBJ_GL_TEX] = tex; + o->gl_tex = tex; g_gx.gl_textures[id] = tex; g_gx.tex_obj_w[id] = width; g_gx.tex_obj_h[id] = height; @@ -815,21 +846,28 @@ void GXInvalidateTexRegion(void* region) { (void)region; } /* --- TLUT --- */ void GXInitTlutObj(void* obj, void* lut, u32 fmt, u16 n_entries) { - u32* o = (u32*)obj; - memset(o, 0, 4 * sizeof(u32)); - o[TLUTOBJ_DATA] = (u32)(uintptr_t)lut; - o[TLUTOBJ_FORMAT] = fmt; - o[TLUTOBJ_N_ENTRIES] = n_entries; + PCTlutObj* o = (PCTlutObj*)obj; + memset(o, 0, sizeof(PCTlutObj)); + o->data = lut; + o->format = fmt; + o->n_entries = n_entries; } void GXLoadTlut(void* obj, u32 idx) { pc_gx_flush_if_begin_complete(); if (idx >= 16) return; - u32* o = (u32*)obj; - g_gx.tlut[idx].data = (const void*)(uintptr_t)o[TLUTOBJ_DATA]; - g_gx.tlut[idx].format = (int)o[TLUTOBJ_FORMAT]; - g_gx.tlut[idx].n_entries = (int)o[TLUTOBJ_N_ENTRIES]; - g_gx.tlut[idx].is_be = 1; /* default to BE (ROM/JSystem data) */ + PCTlutObj* o = (PCTlutObj*)obj; + g_gx.tlut[idx].data = (const void*)o->data; + g_gx.tlut[idx].format = (int)o->format; + g_gx.tlut[idx].n_entries = (int)o->n_entries; + + /* Detect if the TLUT is in the executable (native) or ROM (BE) */ + uintptr_t addr = (uintptr_t)o->data; + if (addr >= pc_image_base && addr < pc_image_end) { + g_gx.tlut[idx].is_be = 0; + } else { + g_gx.tlut[idx].is_be = 1; + } } /* PC_GX_TLUT_MODE env var: "be" forces BE decode for diagnostics */ @@ -870,18 +908,18 @@ void GXInitTlutRegion(void* region, u32 tmem_addr, u32 tlut_size) { } /* --- accessors --- */ -GXBool GXGetTexObjMipMap(const void* obj) { return ((const u32*)obj)[TEXOBJ_MIPMAP] != 0; } -u32 GXGetTexObjFmt(const void* obj) { return ((const u32*)obj)[TEXOBJ_FORMAT]; } -u16 GXGetTexObjHeight(const void* obj) { return (u16)((const u32*)obj)[TEXOBJ_HEIGHT]; } -u16 GXGetTexObjWidth(const void* obj) { return (u16)((const u32*)obj)[TEXOBJ_WIDTH]; } -u32 GXGetTexObjWrapS(const void* obj) { return ((const u32*)obj)[TEXOBJ_WRAP_S]; } -u32 GXGetTexObjWrapT(const void* obj) { return ((const u32*)obj)[TEXOBJ_WRAP_T]; } -void* GXGetTexObjData(const void* obj) { return (void*)(uintptr_t)((const u32*)obj)[TEXOBJ_IMAGE_PTR]; } +GXBool GXGetTexObjMipMap(const void* obj) { return ((const PCTexObj*)obj)->mipmap != 0; } +u32 GXGetTexObjFmt(const void* obj) { return ((const PCTexObj*)obj)->format; } +u16 GXGetTexObjHeight(const void* obj) { return (u16)((const PCTexObj*)obj)->height; } +u16 GXGetTexObjWidth(const void* obj) { return (u16)((const PCTexObj*)obj)->width; } +u32 GXGetTexObjWrapS(const void* obj) { return ((const PCTexObj*)obj)->wrap_s; } +u32 GXGetTexObjWrapT(const void* obj) { return ((const PCTexObj*)obj)->wrap_t; } +void* GXGetTexObjData(const void* obj) { return ((const PCTexObj*)obj)->image_ptr; } void GXDestroyTexObj(void* obj) { - u32* o = (u32*)obj; + PCTexObj* o = (PCTexObj*)obj; /* don't delete GL texture here; cache eviction handles that */ - o[TEXOBJ_GL_TEX] = 0; + o->gl_tex = 0; } void GXDestroyTlutObj(void* obj) { (void)obj; } diff --git a/pc/src/pc_main.c b/pc/src/pc_main.c index 1374d0d8..c0a88ff5 100644 --- a/pc/src/pc_main.c +++ b/pc/src/pc_main.c @@ -1,4 +1,7 @@ /* pc_main.c - PC entry point: SDL2/GL init, crash protection, boot sequence */ +#ifndef _WIN32 +#define _GNU_SOURCE /* needed for dladdr */ +#endif #include "pc_platform.h" #include "pc_gx_internal.h" #include "pc_texture_pack.h" @@ -18,6 +21,7 @@ SDL_Window* g_pc_window = NULL; SDL_GLContext g_pc_gl_context = NULL; int g_pc_running = 1; int g_pc_no_framelimit = 0; +int g_pc_fast_forward = 0; int g_pc_verbose = 0; int g_pc_time_override = -1; /* -1=system clock, 0-23=override hour */ int g_pc_min_override = -1; /* -1=system clock, 0-59=override minute */ @@ -27,13 +31,13 @@ int g_pc_window_h = PC_SCREEN_HEIGHT; int g_pc_widescreen_stretch = 0; /* exe image range -- used by seg2k0 to distinguish pointers from segment addresses */ -unsigned int pc_image_base = 0; -unsigned int pc_image_end = 0; +uintptr_t pc_image_base = 0; +uintptr_t pc_image_end = 0; static jmp_buf* pc_active_jmpbuf = NULL; -static volatile unsigned int pc_last_crash_addr = 0; +static volatile uintptr_t pc_last_crash_addr = 0; -static volatile unsigned int pc_last_crash_data_addr = 0; +static volatile uintptr_t pc_last_crash_data_addr = 0; #ifdef _WIN32 /* longjmp from VEH is technically UB, but works on x86 MinGW (no SEH to corrupt). @@ -45,9 +49,9 @@ static LONG WINAPI pc_veh_handler(PEXCEPTION_POINTERS ep) { code == EXCEPTION_ILLEGAL_INSTRUCTION || code == EXCEPTION_INT_DIVIDE_BY_ZERO || code == EXCEPTION_PRIV_INSTRUCTION)) { - pc_last_crash_addr = (unsigned int)(uintptr_t)ep->ExceptionRecord->ExceptionAddress; + pc_last_crash_addr = (uintptr_t)ep->ExceptionRecord->ExceptionAddress; if (code == EXCEPTION_ACCESS_VIOLATION) - pc_last_crash_data_addr = (unsigned int)(uintptr_t)ep->ExceptionRecord->ExceptionInformation[1]; + pc_last_crash_data_addr = (uintptr_t)ep->ExceptionRecord->ExceptionInformation[1]; else pc_last_crash_data_addr = 0; jmp_buf* buf = pc_active_jmpbuf; @@ -61,9 +65,9 @@ static LONG WINAPI pc_veh_handler(PEXCEPTION_POINTERS ep) { static void pc_signal_handler(int sig, siginfo_t* info, void* ucontext) { (void)ucontext; if (pc_active_jmpbuf != NULL) { - pc_last_crash_addr = (unsigned int)(uintptr_t)info->si_addr; + pc_last_crash_addr = (uintptr_t)info->si_addr; pc_last_crash_data_addr = (sig == SIGSEGV) ? - (unsigned int)(uintptr_t)info->si_addr : 0; + (uintptr_t)info->si_addr : 0; jmp_buf* buf = pc_active_jmpbuf; pc_active_jmpbuf = NULL; longjmp(*buf, 1); @@ -73,7 +77,7 @@ static void pc_signal_handler(int sig, siginfo_t* info, void* ucontext) { } #endif -unsigned int pc_crash_get_data_addr(void) { +uintptr_t pc_crash_get_data_addr(void) { return pc_last_crash_data_addr; } @@ -99,14 +103,13 @@ void pc_crash_set_jmpbuf(jmp_buf* buf) { pc_active_jmpbuf = buf; } -unsigned int pc_crash_get_addr(void) { +uintptr_t pc_crash_get_addr(void) { return pc_last_crash_addr; } void pc_platform_init(void) { #ifdef _WIN32 SetProcessDPIAware(); - #endif if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER | SDL_INIT_AUDIO | SDL_INIT_TIMER) < 0) { fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError()); @@ -116,6 +119,11 @@ void pc_platform_init(void) { SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); +#ifdef __APPLE__ + /* macOS requires forward-compatible flag for Core Profile contexts */ + SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); +#endif + SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); #ifdef PC_ENHANCEMENTS @@ -162,6 +170,36 @@ void pc_platform_init(void) { exit(1); } + if (g_pc_verbose) { + const char* vendor = (const char*)glGetString(GL_VENDOR); + const char* renderer = (const char*)glGetString(GL_RENDERER); + const char* version = (const char*)glGetString(GL_VERSION); + const char* glsl = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION); + printf("[GL] Vendor: %s\n", vendor ? vendor : "Unknown"); + printf("[GL] Renderer: %s\n", renderer ? renderer : "Unknown"); + printf("[GL] Version: %s\n", version ? version : "Unknown"); + printf("[GL] GLSL: %s\n", glsl ? glsl : "Unknown"); + const char* sdl_driver = SDL_GetCurrentVideoDriver(); + printf("[SDL] Video Driver: %s\n", sdl_driver ? sdl_driver : "Unknown"); + } + +#ifndef _WIN32 + { + const char* renderer = (const char*)glGetString(GL_RENDERER); + if (renderer && (strstr(renderer, "llvmpipe") || strstr(renderer, "softpipe"))) { + const char* sdl_driver = SDL_GetCurrentVideoDriver(); + fprintf(stderr, "\n--- WARNING ---\n" + "Game is running on software renderer (llvmpipe/softpipe).\n" + "This likely means 32-bit graphics drivers are missing on your system.\n"); + if (sdl_driver && strcmp(sdl_driver, "wayland") == 0) { + fprintf(stderr, "On Wayland, ensure you have lib32-egl-wayland installed.\n" + "Alternatively, try running with: SDL_VIDEODRIVER=x11\n"); + } + fprintf(stderr, "----------------\n\n"); + } + } +#endif + SDL_GL_SetSwapInterval(g_pc_settings.vsync); pc_platform_update_window_size(); @@ -208,6 +246,30 @@ void pc_platform_update_window_size(void) { } void pc_platform_swap_buffers(void) { + /* One-time pixel color diagnostic */ + { + static int diag_frame = 0; + if (diag_frame >= 180 && diag_frame < 185) { + u8 px[4]; + int cx = g_pc_window_w / 2, cy = g_pc_window_h / 2; + /* Sample center, and 5 points around the character area */ + struct { int x, y; const char* label; } pts[] = { + {cx, cy, "center"}, + {cx, cy + 50, "char_body"}, + {cx - 30, cy + 30, "char_left"}, + {cx + 30, cy + 30, "char_right"}, + {cx, cy - 80, "above"}, + {50, 50, "top_left"}, + }; + fprintf(stderr, "[PIXEL] frame=%d:", diag_frame); + for (int i = 0; i < 6; i++) { + glReadPixels(pts[i].x, g_pc_window_h - pts[i].y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, px); + fprintf(stderr, " %s=(%d,%d,%d,%d)", pts[i].label, px[0], px[1], px[2], px[3]); + } + fprintf(stderr, "\n"); + } + diag_frame++; + } SDL_GL_SwapWindow(g_pc_window); } @@ -256,6 +318,10 @@ int pc_platform_poll_events(void) { g_pc_no_framelimit ^= 1; printf("[PC] Frame limiter %s\n", g_pc_no_framelimit ? "OFF" : "ON"); } + if (event.key.keysym.sym == SDLK_F4 && !event.key.repeat) { + g_pc_fast_forward ^= 1; + printf("[PC] Fast forward %s (2x)\n", g_pc_fast_forward ? "ON" : "OFF"); + } pc_typing_handle_event(&event); break; case SDL_TEXTINPUT: @@ -271,6 +337,34 @@ extern void ac_entry(void); extern int boot_main(int argc, const char** argv); int main(int argc, char* argv[]) { +#ifndef _WIN32 + /* prefer discrete GPU on Linux (NVIDIA PRIME and AMD) while respecting user overrides */ + setenv("__NV_PRIME_RENDER_OFFLOAD", "1", 0); + setenv("__GLX_VENDOR_LIBRARY_NAME", "nvidia", 0); + setenv("__VK_LAYER_NV_optimus", "NVIDIA_only", 0); + setenv("DRI_PRIME", "1", 0); + + const char* wayland_display = getenv("WAYLAND_DISPLAY"); + const char* x11_display = getenv("DISPLAY"); + +#if UINTPTR_MAX <= 0xFFFFFFFFu + /* On 32-bit Linux, Wayland/EGL often fails to load discrete drivers (lib32-nvidia-utils). + * We default to X11 (XWayland) for stability, but allow user override via SDL_VIDEODRIVER. */ + if (wayland_display != NULL && x11_display != NULL) { + setenv("SDL_VIDEODRIVER", "x11", 0); + } +#endif + + const char* sdl_vid_drv = getenv("SDL_VIDEODRIVER"); + if (sdl_vid_drv != NULL && strcmp(sdl_vid_drv, "x11") == 0) { + /* prefer GLX on X11 to prevent EGL fallback issues on some discrete drivers */ + setenv("SDL_VIDEO_GL_DRIVER", "libGL.so.1", 0); + } else if (sdl_vid_drv == NULL && x11_display != NULL && wayland_display == NULL) { + /* No driver set, and only X11 is available - safe to prefer GLX */ + setenv("SDL_VIDEO_GL_DRIVER", "libGL.so.1", 0); + } +#endif + for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { printf("Usage: AnimalCrossing [options]\n"); @@ -321,23 +415,48 @@ int main(int argc, char* argv[]) { HMODULE exe = GetModuleHandle(NULL); IMAGE_DOS_HEADER* dos = (IMAGE_DOS_HEADER*)exe; IMAGE_NT_HEADERS* nt = (IMAGE_NT_HEADERS*)((char*)exe + dos->e_lfanew); - pc_image_base = (unsigned int)(uintptr_t)exe; + pc_image_base = (uintptr_t)exe; pc_image_end = pc_image_base + nt->OptionalHeader.SizeOfImage; } +#elif defined(__APPLE__) + { + /* macOS: use dladdr — no ELF headers available */ + Dl_info dl; + if (dladdr((void*)main, &dl) && dl.dli_fbase) { + pc_image_base = (uintptr_t)dl.dli_fbase; + /* Estimate image end — on 64-bit, seg2k0 uses threshold check + * instead of image range, so this is defense-in-depth only. */ + pc_image_end = pc_image_base + 0x10000000; + } + } #else { Dl_info dl; if (dladdr((void*)main, &dl) && dl.dli_fbase) { - pc_image_base = (unsigned int)(uintptr_t)dl.dli_fbase; + pc_image_base = (uintptr_t)dl.dli_fbase; +#if UINTPTR_MAX > 0xFFFFFFFFu + /* 64-bit ELF */ + Elf64_Ehdr* ehdr = (Elf64_Ehdr*)dl.dli_fbase; + Elf64_Phdr* phdr = (Elf64_Phdr*)((char*)dl.dli_fbase + ehdr->e_phoff); + uintptr_t max_end = 0; + for (int i = 0; i < ehdr->e_phnum; i++) { + if (phdr[i].p_type == PT_LOAD) { + uintptr_t seg_end = phdr[i].p_vaddr + phdr[i].p_memsz; + if (seg_end > max_end) max_end = seg_end; + } + } +#else + /* 32-bit ELF */ Elf32_Ehdr* ehdr = (Elf32_Ehdr*)dl.dli_fbase; Elf32_Phdr* phdr = (Elf32_Phdr*)((char*)dl.dli_fbase + ehdr->e_phoff); - unsigned int max_end = 0; + uintptr_t max_end = 0; for (int i = 0; i < ehdr->e_phnum; i++) { if (phdr[i].p_type == PT_LOAD) { - unsigned int seg_end = phdr[i].p_vaddr + phdr[i].p_memsz; + uintptr_t seg_end = phdr[i].p_vaddr + phdr[i].p_memsz; if (seg_end > max_end) max_end = seg_end; } } +#endif /* ET_EXEC: p_vaddr is absolute. ET_DYN (PIE): relative to load address. */ if (ehdr->e_type == ET_DYN) { pc_image_end = pc_image_base + max_end; diff --git a/pc/src/pc_mtx.c b/pc/src/pc_mtx.c index 2b99f521..e29c2d16 100644 --- a/pc/src/pc_mtx.c +++ b/pc/src/pc_mtx.c @@ -8,13 +8,13 @@ typedef f32 (*MtxP)[4]; typedef struct { f32 x, y, z; } Vec; -typedef long long int Mtx_t[4][2]; +typedef s32 Mtx_t[4][4]; typedef union { Mtx_t m; - long long int forc_align; -} Mtx; + long long int force_structure_alignment; +} Mtx ATTRIBUTE_ALIGN(8); -#define FTOFIX32(x) (long)((x) * (float)0x00010000) +#define FTOFIX32(x) (s32)((x) * (float)0x00010000) /* --- Dolphin PS* matrix functions (3x4 row-major) --- */ @@ -287,18 +287,18 @@ void guMtxIdentF(float mf[4][4]) { void guMtxF2L(float mf[4][4], Mtx* m) { int i, j; - int e1, e2; - int *ai, *af; + s32 e1, e2; + s32 *ai, *af; - ai = (int*)&m->m[0][0]; - af = (int*)&m->m[2][0]; + ai = (s32*)&m->m[0][0]; + af = (s32*)&m->m[2][0]; for (i = 0; i < 4; i++) for (j = 0; j < 2; j++) { - e1 = FTOFIX32(mf[i][j*2]); - e2 = FTOFIX32(mf[i][j*2+1]); - *(ai++) = (e1 & 0xffff0000) | ((e2 >> 16) & 0xffff); - *(af++) = ((e1 << 16) & 0xffff0000) | (e2 & 0xffff); + e1 = FTOFIX32(mf[i][j * 2]); + e2 = FTOFIX32(mf[i][j * 2 + 1]); + *(ai++) = (e1 & 0xffff0000) | ((u32)e2 >> 16); + *(af++) = (e1 << 16) | (e2 & 0xffff); } } diff --git a/pc/src/pc_os.c b/pc/src/pc_os.c index 21c885cd..6d8bcd7e 100644 --- a/pc/src/pc_os.c +++ b/pc/src/pc_os.c @@ -4,7 +4,7 @@ #include /* --- Memory arena --- */ -static u8* arena_memory = NULL; +u8* arena_memory = NULL; static u8* arena_lo = NULL; static u8* arena_hi = NULL; @@ -238,7 +238,21 @@ void LCDisable(void) {} /* --- Init --- */ void OSInit(void) { if (!arena_memory) { - /* alloc arena at >=0x10000000 to avoid collision with N64 segment addresses */ + /* alloc arena — on 64-bit, any mmap/VirtualAlloc returns high addresses + * naturally (well above 0x0FFFFFFF), so no fixed-address loop needed. + * On 32-bit, alloc at >=0x10000000 to avoid collision with N64 segment addresses. */ +#if UINTPTR_MAX > 0xFFFFFFFFu + /* 64-bit: let OS choose address (will be above N64 segment range) */ +#ifdef _WIN32 + arena_memory = (u8*)VirtualAlloc(NULL, + PC_MAIN_MEMORY_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); +#else + arena_memory = (u8*)mmap(NULL, PC_MAIN_MEMORY_SIZE, + PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if (arena_memory == MAP_FAILED) arena_memory = NULL; +#endif +#else + /* 32-bit: try fixed addresses above N64 segment range */ { u32 base; for (base = 0x10000000; base <= 0x50000000; base += 0x01000000) { @@ -257,9 +271,10 @@ void OSInit(void) { if (arena_memory) break; } } +#endif if (!arena_memory) { - /* fallback (may cause seg2k0 issues) */ - fprintf(stderr, "[PC] WARNING: VirtualAlloc at high address failed, " + /* fallback (may cause seg2k0 issues on 32-bit) */ + fprintf(stderr, "[PC] WARNING: memory allocation at high address failed, " "falling back to malloc (seg2k0 may misfire)\n"); arena_memory = (u8*)malloc(PC_MAIN_MEMORY_SIZE); } @@ -365,8 +380,8 @@ int __osResetSwitchPressed = 0; /* --- Address translation (physical addr → arena_memory offset) --- */ void* OSPhysicalToCached(u32 paddr) { return (void*)(arena_memory + paddr); } void* OSPhysicalToUncached(u32 paddr) { return (void*)(arena_memory + paddr); } -u32 OSCachedToPhysical(void* caddr) { return (u32)((u8*)caddr - arena_memory); } -u32 OSUncachedToPhysical(void* ucaddr) { return (u32)((u8*)ucaddr - arena_memory); } +u32 OSCachedToPhysical(void* caddr) { return (u32)(uintptr_t)((u8*)caddr - arena_memory); } +u32 OSUncachedToPhysical(void* ucaddr) { return (u32)(uintptr_t)((u8*)ucaddr - arena_memory); } void* OSCachedToUncached(void* caddr) { return caddr; } void* OSUncachedToCached(void* ucaddr) { return ucaddr; } diff --git a/pc/src/pc_stubs_cpp.cpp b/pc/src/pc_stubs_cpp.cpp index b7897c1b..8f66f31b 100644 --- a/pc/src/pc_stubs_cpp.cpp +++ b/pc/src/pc_stubs_cpp.cpp @@ -17,7 +17,7 @@ int JSURandomOutputStream::getAvailable() const { } int JSURandomOutputStream::skip(s32 amount) { - int s = this->seekPos(amount, SEEK_CUR); + int s = this->seekPos(amount, (JSUStreamSeekFrom)SEEK_CUR); return s; } diff --git a/pc/src/pc_vi.c b/pc/src/pc_vi.c index ddfe78e0..f0ccb936 100644 --- a/pc/src/pc_vi.c +++ b/pc/src/pc_vi.c @@ -43,15 +43,15 @@ void VIWaitForRetrace(void) { Uint64 t_before_pace = SDL_GetPerformanceCounter(); if (!g_pc_no_framelimit) { - /* Timer-based pacing: sleep until 16ms per frame (~60 FPS). + /* Timer-based pacing: sleep until target frame time. * Audio production runs on a dedicated thread and is no longer * tied to game frame timing. */ + Uint64 target_us = g_pc_fast_forward ? 8333 : 16667; /* 2x = 120Hz, 1x = 60Hz */ if (frame_start_time) { Uint64 now = SDL_GetPerformanceCounter(); Uint64 elapsed_us = (now - frame_start_time) * 1000000 / perf_freq; - /* 16667us = 60.0 Hz (NTSC). Spin for sub-ms precision. */ - while (elapsed_us < 16667) { - Uint64 remain_us = 16667 - elapsed_us; + while (elapsed_us < target_us) { + Uint64 remain_us = target_us - elapsed_us; if (remain_us > 2000) { SDL_Delay(1); } @@ -81,8 +81,9 @@ void VIWaitForRetrace(void) { Uint64 now = SDL_GetPerformanceCounter(); double secs = (double)(now - fps_start) / (double)perf_freq; double fps = (double)fps_count / secs; - char title[64]; - snprintf(title, sizeof(title), "Animal Crossing - %.1f FPS", fps); + char title[80]; + snprintf(title, sizeof(title), "Animal Crossing - %.1f FPS%s", fps, + g_pc_fast_forward ? " [2x]" : ""); SDL_SetWindowTitle(g_pc_window, title); fps_start = now; fps_count = 0; diff --git a/src/TwoHeadArena.c b/src/TwoHeadArena.c index 5bc52d79..c03ca031 100644 --- a/src/TwoHeadArena.c +++ b/src/TwoHeadArena.c @@ -60,18 +60,19 @@ extern void* THA_alloc(TwoHeadArena* this, size_t siz) { */ extern void* THA_alloc16(TwoHeadArena* this, size_t siz) { - const int mask = ~(16 - 1); - this->tail_p = (char*)((((u32)this->tail_p & mask) - siz) & mask); + const uintptr_t mask = ~(uintptr_t)(16 - 1); + this->tail_p = (char*)((((uintptr_t)this->tail_p & mask) - siz) & mask); return this->tail_p; } extern void* THA_allocAlign(TwoHeadArena* this, size_t siz, int mask) { - this->tail_p = (char*)((((u32)this->tail_p & mask) - siz) & mask); + uintptr_t umask = (uintptr_t)(intptr_t)mask; /* sign-extend mask to pointer width */ + this->tail_p = (char*)((((uintptr_t)this->tail_p & umask) - siz) & umask); return this->tail_p; } extern int THA_getFreeBytesAlign(TwoHeadArena* this, int mask) { - return (int)this->tail_p - (mask & (int)(this->head_p + ~mask)); + return (int)((intptr_t)this->tail_p - ((intptr_t)mask & (intptr_t)(this->head_p + ~mask))); } extern int THA_getFreeBytes16(TwoHeadArena* this) { diff --git a/src/actor/ac_animal_logo.c b/src/actor/ac_animal_logo.c index 0a0edd35..62456e86 100644 --- a/src/actor/ac_animal_logo.c +++ b/src/actor/ac_animal_logo.c @@ -481,7 +481,7 @@ static void aAL_setupAction(ANIMAL_LOGO_ACTOR* actor, GAME* game, int action) { &aAL_back_fadein, &aAL_start_key_chk_start_wait, #ifdef PC_ENHANCEMENTS - &aAL_pc_game_start_wait, + (ANIMAL_LOGO_ACTION_PROC)&aAL_pc_game_start_wait, #else &aAL_game_start_wait, #endif diff --git a/src/actor/ac_ant.c b/src/actor/ac_ant.c index 16521ac2..19f9738d 100644 --- a/src/actor/ac_ant.c +++ b/src/actor/ac_ant.c @@ -59,18 +59,18 @@ static void aANT_wait(ANT_ACTOR* ant, GAME* game) { if (ant->below_fg_p == NULL || (*ant->below_fg_p != ITM_FOOD_CANDY && *ant->below_fg_p != ITM_KABU_SPOILED)) { aANT_setupAction(ant, aANT_ACT_DISAPPEAR); } else { - u32 catch_label = mPlib_Get_item_net_catch_label(); + uintptr_t catch_label = mPlib_Get_item_net_catch_label(); - if ((u32)ant == catch_label) { + if ((uintptr_t)ant == catch_label) { aANT_setupAction(ant, aANT_ACT_CAUGHT); } else { f32 catch_swing_timer = GET_PLAYER_ACTOR_NOW()->Get_Item_net_catch_swing_timer_proc(GET_PLAYER_ACTOR_NOW_ACTOR(), gamePT); xyz_t stop_net_pos; if ((catch_swing_timer > 0.0f || mPlib_Check_StopNet(&stop_net_pos)) && ant->actor_class.player_distance_xz < mFI_UNIT_BASE_SIZE_F) { - GET_PLAYER_ACTOR_NOW()->Set_Item_net_catch_request_force_proc(GET_PLAYER_ACTOR_NOW_ACTOR(), gamePT, (u32)ant, mPlayer_NET_CATCH_TYPE_ANT); + GET_PLAYER_ACTOR_NOW()->Set_Item_net_catch_request_force_proc(GET_PLAYER_ACTOR_NOW_ACTOR(), gamePT, (uintptr_t)ant, mPlayer_NET_CATCH_TYPE_ANT); } else { - GET_PLAYER_ACTOR_NOW()->Set_Item_net_catch_request_table_proc(GET_PLAYER_ACTOR_NOW_ACTOR(), gamePT, (u32)ant, mPlayer_NET_CATCH_TYPE_ANT, &ant->actor_class.world.position, 24.0f); + GET_PLAYER_ACTOR_NOW()->Set_Item_net_catch_request_table_proc(GET_PLAYER_ACTOR_NOW_ACTOR(), gamePT, (uintptr_t)ant, mPlayer_NET_CATCH_TYPE_ANT, &ant->actor_class.world.position, 24.0f); } } } @@ -86,7 +86,7 @@ static void aANT_caught(ANT_ACTOR* ant, GAME* game) { ant->insect_actor = CLIP(insect_clip)->make_insect_proc(&insect_init, aINS_MAKE_EXIST); if (ant->insect_actor != NULL) { - if (mPlib_Change_item_net_catch_label((u32)ant->insect_actor, mPlayer_NET_CATCH_TYPE_INSECT)) { + if (mPlib_Change_item_net_catch_label((uintptr_t)ant->insect_actor, mPlayer_NET_CATCH_TYPE_INSECT)) { aANT_setupAction(ant, aANT_ACT_DISAPPEAR); } } else { diff --git a/src/actor/ac_arrange_room.c b/src/actor/ac_arrange_room.c index c6b325ae..91bcb166 100644 --- a/src/actor/ac_arrange_room.c +++ b/src/actor/ac_arrange_room.c @@ -172,8 +172,8 @@ static void Arrange_Room_Actor_draw(ACTOR* actor, GAME* game) { aAR_DrawWall(&arrange_room->actor_class, &play->game); } -static void Arrange_Room_Actor_move() { - +static void Arrange_Room_Actor_move(ACTOR* actor, GAME* game) { + (void)actor; (void)game; } static void aAR_Redma() { diff --git a/src/actor/ac_bee.c b/src/actor/ac_bee.c index 332d1c03..e32b319c 100644 --- a/src/actor/ac_bee.c +++ b/src/actor/ac_bee.c @@ -165,7 +165,7 @@ static void aBEE_fly(ACTOR* actorx, GAME* game) { xyz_t pos; aBEE_calc_fly_angle(actorx); - if ((u32)bee == mPlib_Get_item_net_catch_label()) { + if ((uintptr_t)bee == mPlib_Get_item_net_catch_label()) { aBEE_setupAction(bee, aBEE_ACT_CAUGHT, game); } else if (actorx->shape_info.rotation.x <= DEG2SHORT_ANGLE2(22.5f)) { if (mPlib_check_player_actor_main_index_Pitfall(game)) { @@ -197,9 +197,9 @@ static void aBEE_fly(ACTOR* actorx, GAME* game) { swing_timer = GET_PLAYER_ACTOR_NOW()->Get_Item_net_catch_swing_timer_proc(GET_PLAYER_ACTOR_NOW_ACTOR(), gamePT); if ((swing_timer > 0.0f || mPlib_Check_StopNet(&pos)) && actorx->player_distance_xz < 40.0f) { - GET_PLAYER_ACTOR_NOW()->Set_Item_net_catch_request_force_proc(GET_PLAYER_ACTOR_NOW_ACTOR(), gamePT, (u32)actorx, TRUE); + GET_PLAYER_ACTOR_NOW()->Set_Item_net_catch_request_force_proc(GET_PLAYER_ACTOR_NOW_ACTOR(), gamePT, (uintptr_t)actorx, TRUE); } else { - GET_PLAYER_ACTOR_NOW()->Set_Item_net_catch_request_table_proc(GET_PLAYER_ACTOR_NOW_ACTOR(), gamePT, (u32)actorx, TRUE, &actorx->world.position, 24.0f); + GET_PLAYER_ACTOR_NOW()->Set_Item_net_catch_request_table_proc(GET_PLAYER_ACTOR_NOW_ACTOR(), gamePT, (uintptr_t)actorx, TRUE, &actorx->world.position, 24.0f); } } @@ -223,7 +223,7 @@ static void aBEE_caught(ACTOR* actorx, GAME* game) { } if (bee->insect_actor != NULL) { - if (mPlib_Change_item_net_catch_label((u32)bee->insect_actor, 0)) { + if (mPlib_Change_item_net_catch_label((uintptr_t)bee->insect_actor, 0)) { aBEE_setupAction(bee, aBEE_ACT_DISAPPEAR, game); return; } @@ -346,7 +346,7 @@ static void aBEE_setupAction(BEE_ACTOR* bee, int action, GAME* game) { static void aBEE_actor_move(ACTOR* actorx, GAME* game) { BEE_ACTOR* bee = (BEE_ACTOR*)actorx; - sAdo_OngenPos((u32)actorx, NA_SE_B0, &actorx->world.position); + sAdo_OngenPos((uintptr_t)actorx, NA_SE_B0, &actorx->world.position); if ((actorx->world.position.x < 0.0f && actorx->world.position.z < 0.0f)) { // empty block, maybe for debug? } else { diff --git a/src/actor/ac_birth_control.c b/src/actor/ac_birth_control.c index bf15e1c6..05a3f324 100644 --- a/src/actor/ac_birth_control.c +++ b/src/actor/ac_birth_control.c @@ -290,7 +290,6 @@ static void aBC_set_boat(BIRTH_CONTROL_ACTOR* birth_control, GAME_PLAY* play) { static void aBC_actor_move(ACTOR* actorx, GAME* game) { BIRTH_CONTROL_ACTOR* birth_control = (BIRTH_CONTROL_ACTOR*)actorx; GAME_PLAY* play = (GAME_PLAY*)game; - if (Common_Get(bg_item_type) == 0) { birth_control->setup_actor_flag |= mFI_ActorisBorn() == TRUE; aBC_set_boat(birth_control, play); @@ -299,7 +298,6 @@ static void aBC_actor_move(ACTOR* actorx, GAME* game) { if (mFI_ActorisBorn() == TRUE) { int bx = play->block_table.block_x; int bz = play->block_table.block_z; - birth_control->move_actor_data = mFI_MoveActorListDma(bx, bz); mNpc_AddActor_inBlock(birth_control->move_actor_data, bx, bz); diff --git a/src/actor/ac_fallSESW_move.c_inc b/src/actor/ac_fallSESW_move.c_inc index 5cfa0239..661eac14 100644 --- a/src/actor/ac_fallSESW_move.c_inc +++ b/src/actor/ac_fallSESW_move.c_inc @@ -5,5 +5,5 @@ void aFLEW_actor_move(ACTOR* actor, GAME*) { pos.y += 40.0f; - sAdo_OngenPos((u32)actor, 12, &pos); + sAdo_OngenPos((uintptr_t)actor, 12, &pos); } \ No newline at end of file diff --git a/src/actor/ac_fallS_move.c_inc b/src/actor/ac_fallS_move.c_inc index daadde13..41414256 100644 --- a/src/actor/ac_fallS_move.c_inc +++ b/src/actor/ac_fallS_move.c_inc @@ -5,5 +5,5 @@ void aFLS_actor_move(ACTOR* actor, GAME*) { pos.y += 40.0f; - sAdo_OngenPos((u32)actor, 12, &pos); + sAdo_OngenPos((uintptr_t)actor, 12, &pos); } diff --git a/src/actor/ac_field_draw.c b/src/actor/ac_field_draw.c index 9cb75edb..e13a055b 100644 --- a/src/actor/ac_field_draw.c +++ b/src/actor/ac_field_draw.c @@ -164,7 +164,7 @@ static int aFD_OperateWaterSound(xyz_t* center_pos, ACTOR* actorx, s16 ongen_typ aFD_ongen_info2_c* info = &ongen_info[i]; if (info->sound_source_no != -1) { - u32 ongen_id = (u32)actorx + (mFI_GetBlockXMax() * info->bz + info->bx) * mFM_SOUND_SOURCE_NUM + + uintptr_t ongen_id = (uintptr_t)actorx + (mFI_GetBlockXMax() * info->bz + info->bx) * mFM_SOUND_SOURCE_NUM + info->sound_source_no; mFM_bg_sound_source_c* source = mFI_GetSoundSourcePBlockNum(info->bx, info->bz); @@ -281,7 +281,7 @@ static void Bg_Draw_Actor_move(ACTOR* actorx, GAME* game) { frog_se_pos.y = 0.0f; frog_se_pos.z = mFI_UNIT_BASE_SIZE_F + (f32)pond_z * mFI_UNIT_BASE_SIZE_F; frog_se_pos.y = mCoBG_GetBgY_OnlyCenter_FromWpos(frog_se_pos, 0.0f); - sAdo_OngenPos((u32)&Bg_Draw_Actor_move, 0xA1, &frog_se_pos); + sAdo_OngenPos((uintptr_t)&Bg_Draw_Actor_move, 0xA1, &frog_se_pos); } /* Pond sound effect */ @@ -289,7 +289,7 @@ static void Bg_Draw_Actor_move(ACTOR* actorx, GAME* game) { pond_pos.y = 0.0f; pond_pos.z = mFI_UNIT_BASE_SIZE_F * 0.5f + (f32)pond_z * mFI_UNIT_BASE_SIZE_F; pond_pos.y = mCoBG_GetBgY_OnlyCenter_FromWpos(pond_pos, 0.0f); - sAdo_OngenPos((u32)&Bg_Draw_Actor_ct, 0x16, &pond_pos); + sAdo_OngenPos((uintptr_t)&Bg_Draw_Actor_ct, 0x16, &pond_pos); } } diff --git a/src/actor/ac_gyo_kaseki.c b/src/actor/ac_gyo_kaseki.c index c35ff71e..b1209654 100644 --- a/src/actor/ac_gyo_kaseki.c +++ b/src/actor/ac_gyo_kaseki.c @@ -620,7 +620,7 @@ static void aGKK_bite(ACTOR* actorx, GAME* game) { actorx->world.position.z = pos.z; aGKK_set_angle(actorx, uki->actor_class.world.angle.y); - sAdo_OngenPos((u32)actorx, NA_SE_24, &actorx->world.position); + sAdo_OngenPos((uintptr_t)actorx, NA_SE_24, &actorx->world.position); CLIP(gyo_clip)->hitcheck_gyoei_proc(&actorx->world.position, gyo->size_type); if (DECREMENT_TIMER(gyo->swork0) == 0) { diff --git a/src/actor/ac_gyo_test.c b/src/actor/ac_gyo_test.c index 33709d91..57f3aa89 100644 --- a/src/actor/ac_gyo_test.c +++ b/src/actor/ac_gyo_test.c @@ -633,11 +633,11 @@ static void aGTT_bite(ACTOR* actorx, GAME* game) { actorx->world.position.y = now_y; } - sAdo_OngenPos((u32)actorx, NA_SE_24, &actorx->world.position); + sAdo_OngenPos((uintptr_t)actorx, NA_SE_24, &actorx->world.position); } else { static f32 rr[] = { 6.0f, 7.0f, 8.0f, 8.0f, 9.0f, 10.0f, 15.0f, 15.0f }; xyz_t pos; - + pos = aGTT_pos_calc(uki->actor_class.world.position, game, uki->actor_class.world.angle.y, 8.0f, rr[gyo->size_type]); actorx->world.position.x = pos.x; actorx->world.position.z = pos.z; @@ -646,7 +646,7 @@ static void aGTT_bite(ACTOR* actorx, GAME* game) { } aGTT_set_angle(actorx, uki->actor_class.world.angle.y); - sAdo_OngenPos((u32)actorx, NA_SE_24, &actorx->world.position); + sAdo_OngenPos((uintptr_t)actorx, NA_SE_24, &actorx->world.position); CLIP(gyo_clip)->hitcheck_gyoei_proc(&actorx->world.position, gyo->size_type); if (DECREMENT_TIMER(gyo->swork0) == 0) { diff --git a/src/actor/ac_house.c b/src/actor/ac_house.c index 5ccc8c51..a8683cb1 100644 --- a/src/actor/ac_house.c +++ b/src/actor/ac_house.c @@ -34,12 +34,20 @@ enum { }; #define aHUS_GET_LOOKS(h) ((h)->arg0) +#ifdef TARGET_PC +#define aHUS_GET_ANIMAL_P(h) (Save_GetPointer(animals[(h)->arg2])) +#else #define aHUS_GET_ANIMAL_P(h) ((Animal_c*)(h)->arg1) +#endif #define aHUS_GET_ANIMAL_IDX(h) ((h)->arg2) #define aHUS_GET_LIGHT_PERCENT(h) ((h)->arg1_f) #define aHUS_SET_LOOKS(h, v) ((h)->arg0 = (v)) +#ifdef TARGET_PC +#define aHUS_SET_ANIMAL_P(h, v) +#else #define aHUS_SET_ANIMAL_P(h, v) ((h)->arg1 = (int)(v)) +#endif #define aHUS_SET_ANIMAL_IDX(h, v) ((h)->arg2 = (v)) #define aHUS_SET_LIGHT_PERCENT(h, v) ((h)->arg1_f = (v)) diff --git a/src/actor/ac_house_goki.c b/src/actor/ac_house_goki.c index f2bd46cc..3e9bbd52 100644 --- a/src/actor/ac_house_goki.c +++ b/src/actor/ac_house_goki.c @@ -255,7 +255,7 @@ static void aHG_away(ACTOR* actorx, GAME* game) { } } - sAdo_OngenPos((u32)goki, NA_SE_GOKI_MOVE, &actorx->world.position); + sAdo_OngenPos((uintptr_t)goki, NA_SE_GOKI_MOVE, &actorx->world.position); } } @@ -314,7 +314,7 @@ static void aHG_move(ACTOR* actorx, GAME* game) { if (goki->timer <= 0.0f) { aHG_decide_next_act_idx_wait_move(goki, game); } else { - sAdo_OngenPos((u32)goki, NA_SE_GOKI_MOVE, &actorx->world.position); + sAdo_OngenPos((uintptr_t)goki, NA_SE_GOKI_MOVE, &actorx->world.position); } } } diff --git a/src/actor/ac_ins_amenbo.c b/src/actor/ac_ins_amenbo.c index 32f48eb1..42b0c30d 100644 --- a/src/actor/ac_ins_amenbo.c +++ b/src/actor/ac_ins_amenbo.c @@ -81,7 +81,7 @@ static void aIAB_let_escape(ACTOR* actorx, GAME* game) { } actorx->gravity = grav; - sAdo_OngenPos((u32)actorx, NA_SE_25, &actorx->world.position); + sAdo_OngenPos((uintptr_t)actorx, NA_SE_25, &actorx->world.position); } static void aIAB_move(ACTOR* actorx, GAME* game) { @@ -203,9 +203,9 @@ static void aIAB_setupAction(aINS_INSECT_ACTOR* insect, int action, GAME* game) static void aIAB_actor_move(ACTOR* actorx, GAME* game) { aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actorx; - u32 label = mPlib_Get_item_net_catch_label(); + uintptr_t label = mPlib_Get_item_net_catch_label(); - if (label == (u32)actorx) { + if (label == (uintptr_t)actorx) { insect->alpha0 = 255; aIAB_setupAction(insect, aIAB_ACTION_LET_ESCAPE, game); } else if (insect->insect_flags.bit_3 == TRUE && insect->insect_flags.bit_2 == FALSE) { diff --git a/src/actor/ac_ins_batta.c b/src/actor/ac_ins_batta.c index fcba631b..c767d0ca 100644 --- a/src/actor/ac_ins_batta.c +++ b/src/actor/ac_ins_batta.c @@ -137,10 +137,10 @@ static int aIBT_check_ball(aINS_INSECT_ACTOR* insect) { static void aIBT_set_fly_se(aINS_INSECT_ACTOR* insect) { switch (insect->type) { case aINS_INSECT_TYPE_LONG_LOCUST: - sAdo_OngenPos((u32)insect, 0xA2, &insect->tools_actor.actor_class.world.position); + sAdo_OngenPos((uintptr_t)insect, 0xA2, &insect->tools_actor.actor_class.world.position); break; case aINS_INSECT_TYPE_MIGRATORY_LOCUST: - sAdo_OngenPos((u32)insect, 0xA3, &insect->tools_actor.actor_class.world.position); + sAdo_OngenPos((uintptr_t)insect, 0xA3, &insect->tools_actor.actor_class.world.position); break; } } @@ -151,8 +151,8 @@ static int aIBT_check_player_net_sub(xyz_t* net_pos, aINS_INSECT_ACTOR* insect) ret = FALSE; if (mPlib_Check_StopNet(net_pos) == TRUE) { - u32 label = mPlib_Get_item_net_catch_label(); - if (label == (u32)insect) { + uintptr_t label = mPlib_Get_item_net_catch_label(); + if (label == (uintptr_t)insect) { ret = TRUE; } } @@ -184,8 +184,8 @@ static int aIBT_check_player_net2(aINS_INSECT_ACTOR* insect) { ret = FALSE; if (mPlib_Check_StopNet(&pos) == TRUE) { - u32 label = mPlib_Get_item_net_catch_label(); - if (label == (u32)insect) { + uintptr_t label = mPlib_Get_item_net_catch_label(); + if (label == (uintptr_t)insect) { insect->s32_work1 = 1; } else { x = pos.x - insect->tools_actor.actor_class.world.position.x; @@ -423,7 +423,7 @@ static void aIBT_wait(ACTOR* actor, GAME* game) { aIBT_anime_proc(insect); } if (insect->s32_work1 == 0) { - sAdo_OngenPos((u32)insect, batta_sound_data[idx], &actor->world.position); + sAdo_OngenPos((uintptr_t)insect, batta_sound_data[idx], &actor->world.position); } } } @@ -567,9 +567,9 @@ void aIBT_actor_move(ACTOR* actor, GAME* game) { aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actor; GAME_PLAY* play = (GAME_PLAY*)game; - u32 label = mPlib_Get_item_net_catch_label(); + uintptr_t label = mPlib_Get_item_net_catch_label(); - if (label == (u32)actor) { + if (label == (uintptr_t)actor) { aIBT_setupAction(insect, aIBT_ACTION_LET_ESCAPE, game); } else { if (insect->insect_flags.bit_3 == TRUE && insect->insect_flags.bit_2 == FALSE) { diff --git a/src/actor/ac_ins_chou.c b/src/actor/ac_ins_chou.c index 2dd83490..b9b3ea65 100644 --- a/src/actor/ac_ins_chou.c +++ b/src/actor/ac_ins_chou.c @@ -286,8 +286,8 @@ static int aICH_check_player_net(aINS_INSECT_ACTOR* insect) { ret = FALSE; if (mPlib_Check_StopNet(&pos) == TRUE) { - u32 label = mPlib_Get_item_net_catch_label(); - if ((label != (u32)insect)) { + uintptr_t label = mPlib_Get_item_net_catch_label(); + if ((label != (uintptr_t)insect)) { xDiff = pos.x - insect->tools_actor.actor_class.world.position.x; zDiff = pos.z - insect->tools_actor.actor_class.world.position.z; @@ -618,9 +618,9 @@ static void aICH_actor_move(ACTOR* actor, GAME* game) { aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actor; GAME_PLAY* play = (GAME_PLAY*)game; - u32 label = mPlib_Get_item_net_catch_label(); + uintptr_t label = mPlib_Get_item_net_catch_label(); - if (label == (u32)actor) { + if (label == (uintptr_t)actor) { insect->alpha0 = 255; aICH_anime_proc(insect); aICH_setupAction(insect, aICH_ACTION_LET_ESCAPE, game); diff --git a/src/actor/ac_ins_dango.c b/src/actor/ac_ins_dango.c index b81cb8a7..466887f8 100644 --- a/src/actor/ac_ins_dango.c +++ b/src/actor/ac_ins_dango.c @@ -392,9 +392,9 @@ static void aIDG_actor_move(ACTOR* actor, GAME* game) { aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actor; GAME_PLAY* play = (GAME_PLAY*)game; - u32 label = mPlib_Get_item_net_catch_label(); + uintptr_t label = mPlib_Get_item_net_catch_label(); - if (label == (u32)actor) { + if (label == (uintptr_t)actor) { insect->alpha0 = 255; aIDG_setupAction(insect, aIDG_ACTION_LET_ESCAPE, game); } else { diff --git a/src/actor/ac_ins_goki.c b/src/actor/ac_ins_goki.c index 3e73789c..b4ec4344 100644 --- a/src/actor/ac_ins_goki.c +++ b/src/actor/ac_ins_goki.c @@ -42,8 +42,13 @@ enum { #define aIGK_TARGET_ANGLE(insect) ((insect)->s32_work0) #define aIGK_CHANGE_WAIT_TIMER(insect) ((insect)->s32_work1) #define aIGK_MOVE_TIMER(insect) ((insect)->s32_work2) +#ifdef TARGET_PC +#define aIGK_GET_ITEM_P(insect) (mFI_GetUnitFG(insect->tools_actor.actor_class.home.position)) +#define aIGK_SET_ITEM_P(insect, item_p) +#else #define aIGK_GET_ITEM_P(insect) ((insect)->s32_work3) #define aIGK_SET_ITEM_P(insect, item_p) ((insect)->s32_work3 = (int)item_p) +#endif static void aIGK_actor_move(ACTOR* actorx, GAME* game); static void aIGK_setupAction(aINS_INSECT_ACTOR* insect, int action, GAME* game); @@ -159,9 +164,9 @@ static int aIGK_check_player_net(aINS_INSECT_ACTOR* insect) { int res = FALSE; if (mPlib_Check_StopNet(&net_pos) == TRUE) { - u32 label = mPlib_Get_item_net_catch_label(); + uintptr_t label = mPlib_Get_item_net_catch_label(); - if (label != (u32)insect) { + if (label != (uintptr_t)insect) { f32 dX = net_pos.x - insect->tools_actor.actor_class.world.position.x; f32 dZ = net_pos.z - insect->tools_actor.actor_class.world.position.z; @@ -224,7 +229,7 @@ static void aIGK_avoid(ACTOR* actorx, GAME* game) { } actorx->gravity = grav; - sAdo_OngenPos((u32)actorx, NA_SE_26, &actorx->world.position); + sAdo_OngenPos((uintptr_t)actorx, NA_SE_26, &actorx->world.position); aIGK_anime_proc(insect); if (insect->bg_type == 0) { @@ -268,7 +273,7 @@ static void aIGK_move_on_flower(ACTOR* actorx, GAME* game) { aIGK_MOVE_TIMER(insect)--; if (aIGK_MOVE_TIMER(insect) <= 0) { - sAdo_OngenPos((u32)actorx, NA_SE_GOKI_MOVE, &actorx->world.position); + sAdo_OngenPos((uintptr_t)actorx, NA_SE_GOKI_MOVE, &actorx->world.position); insect->timer = (int)(2 * (90.0f + RANDOM_F(90.0f))); aIGK_setupAction(insect, aIGK_ACTION_WAIT_ON_FLOWER, game); } else { @@ -462,9 +467,9 @@ static void aIGK_setupAction(aINS_INSECT_ACTOR* insect, int action, GAME* game) static void aIGK_actor_move(ACTOR* actorx, GAME* game) { aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actorx; - u32 label = mPlib_Get_item_net_catch_label(); + uintptr_t label = mPlib_Get_item_net_catch_label(); - if (label == (u32)actorx) { + if (label == (uintptr_t)actorx) { aIGK_setupAction(insect, aIGK_ACTION_LET_ESCAPE, game); } else if (insect->insect_flags.bit_3 == TRUE && insect->insect_flags.bit_2 == FALSE) { aIGK_setupAction(insect, aIGK_ACTION_LET_ESCAPE, game); diff --git a/src/actor/ac_ins_hitodama.c b/src/actor/ac_ins_hitodama.c index f42bcd10..535e74dd 100644 --- a/src/actor/ac_ins_hitodama.c +++ b/src/actor/ac_ins_hitodama.c @@ -298,7 +298,7 @@ static void aIHD_actor_move(ACTOR* actorx, GAME* game) { } label = mPlib_Get_item_net_catch_label(); - if (label == (u32)actorx) { + if (label == (uintptr_t)actorx) { aIHD_setupAction(insect, aIHD_ACTION_LET_ESCAPE, game); } else { if (mEv_check_status(mEv_EVENT_GHOST, mEv_STATUS_RUN) == FALSE) { diff --git a/src/actor/ac_ins_ka.c b/src/actor/ac_ins_ka.c index 1f68413d..b588ebad 100644 --- a/src/actor/ac_ins_ka.c +++ b/src/actor/ac_ins_ka.c @@ -279,11 +279,11 @@ static void aIKA_actor_move(ACTOR* actorx, GAME* game) { } label = mPlib_Get_item_net_catch_label(); - if (label == (u32)actorx) { + if (label == (uintptr_t)actorx) { aIKA_setupAction(insect, aIKA_ACTION_LET_ESCAPE, game); } else { if (insect->action != aIKA_ACTION_ATTACK) { - sAdo_OngenPos((u32)actorx, NA_SE_KA_BUZZ, &actorx->world.position); + sAdo_OngenPos((uintptr_t)actorx, NA_SE_KA_BUZZ, &actorx->world.position); } if (insect->insect_flags.bit_3 == TRUE && insect->insect_flags.bit_2 == FALSE && diff --git a/src/actor/ac_ins_kabuto.c b/src/actor/ac_ins_kabuto.c index 7818c3b6..30401d1a 100644 --- a/src/actor/ac_ins_kabuto.c +++ b/src/actor/ac_ins_kabuto.c @@ -124,9 +124,9 @@ static int aIKB_check_player_net(ACTOR* actorx) { int res = FALSE; if (mPlib_Check_StopNet(&net_pos) == TRUE) { - u32 label = mPlib_Get_item_net_catch_label(); + uintptr_t label = mPlib_Get_item_net_catch_label(); - if (label != (u32)actorx) { + if (label != (uintptr_t)actorx) { f32 dX = net_pos.x - actorx->world.position.x; f32 dZ = net_pos.z - actorx->world.position.z; @@ -194,7 +194,7 @@ static void aIKB_avoid(ACTOR* actorx, GAME* game) { actorx->gravity = grav; - sAdo_OngenPos((u32)actorx, NA_SE_25, &actorx->world.position); + sAdo_OngenPos((uintptr_t)actorx, NA_SE_25, &actorx->world.position); if (insect->bg_type != 2) { int h_ut_x; @@ -289,9 +289,9 @@ static void aIKB_setupAction(aINS_INSECT_ACTOR* insect, int action, GAME* game) static void aIKB_actor_move(ACTOR* actorx, GAME* game) { aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actorx; - u32 label = mPlib_Get_item_net_catch_label(); + uintptr_t label = mPlib_Get_item_net_catch_label(); - if (label == (u32)actorx) { + if (label == (uintptr_t)actorx) { aIKB_setupAction(insect, aIKB_ACTION_LET_ESCAPE, game); } else if (insect->insect_flags.bit_3 == TRUE && insect->insect_flags.bit_2 == FALSE) { aIKB_setupAction(insect, aIKB_ACTION_LET_ESCAPE, game); diff --git a/src/actor/ac_ins_kera.c b/src/actor/ac_ins_kera.c index 791c4f5e..9139189b 100644 --- a/src/actor/ac_ins_kera.c +++ b/src/actor/ac_ins_kera.c @@ -248,7 +248,7 @@ static void aIKR_avoid(ACTOR* actorx, GAME* game) { } aIKR_calc_direction_angl(actorx); - sAdo_OngenPos((u32)actorx, NA_SE_MOLE_CRICKET_OUT, &actorx->world.position); + sAdo_OngenPos((uintptr_t)actorx, NA_SE_MOLE_CRICKET_OUT, &actorx->world.position); } } @@ -266,7 +266,7 @@ static void aIKR_let_escape(ACTOR* actorx, GAME* game) { aIKR_setupAction(insect, aIKR_ACT_DIVE, game); } else { aIKR_calc_direction_angl(actorx); - sAdo_OngenPos((u32)actorx, NA_SE_MOLE_CRICKET_OUT, &actorx->world.position); + sAdo_OngenPos((uintptr_t)actorx, NA_SE_MOLE_CRICKET_OUT, &actorx->world.position); } } @@ -286,7 +286,7 @@ static void aIKR_hide(ACTOR* actorx, GAME* game) { eEC_CLIP->effect_make_proc(eEC_EFFECT_DIG_MUD, actorx->world.position, 2, actorx->shape_info.rotation.y, game, RSV_NO, 0, 0x4000 | i); } } else { - sAdo_OngenPos((u32)actorx, NA_SE_MOLE_CRICKET_HIDE, &actorx->world.position); + sAdo_OngenPos((uintptr_t)actorx, NA_SE_MOLE_CRICKET_HIDE, &actorx->world.position); } } @@ -338,7 +338,7 @@ static void aIKR_dug(ACTOR* actorx, GAME* game) { } chase_angle(&actorx->shape_info.rotation.x, DEG2SHORT_ANGLE2(157.5f), 0x300); - sAdo_OngenPos((u32)actorx, NA_SE_MOLE_CRICKET_OUT, &actorx->world.position); + sAdo_OngenPos((uintptr_t)actorx, NA_SE_MOLE_CRICKET_OUT, &actorx->world.position); } /** @@ -498,9 +498,9 @@ static void aIKR_setupAction(aINS_INSECT_ACTOR* insect, int action, GAME* game) */ static void aIKR_actor_move(ACTOR* actorx, GAME* game) { aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actorx; - u32 catch_label = mPlib_Get_item_net_catch_label(); + uintptr_t catch_label = mPlib_Get_item_net_catch_label(); - if (catch_label == (u32)actorx) { + if (catch_label == (uintptr_t)actorx) { insect->alpha0 = 255; aIKR_setupAction(insect, aIKR_ACT_LET_ESCAPE, game); } else { diff --git a/src/actor/ac_ins_mino.c b/src/actor/ac_ins_mino.c index 08f2163e..eeeaf841 100644 --- a/src/actor/ac_ins_mino.c +++ b/src/actor/ac_ins_mino.c @@ -618,9 +618,9 @@ static void aIMN_setupAction(aINS_INSECT_ACTOR* insect, int action, GAME* game) */ static void aIMN_actor_move(ACTOR* actorx, GAME* game) { aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actorx; - u32 catch_label = mPlib_Get_item_net_catch_label(); + uintptr_t catch_label = mPlib_Get_item_net_catch_label(); - if (catch_label == (u32)actorx) { + if (catch_label == (uintptr_t)actorx) { insect->alpha0 = 255; insect->tools_actor.actor_class.shape_info.rotation.y = DEG2SHORT_ANGLE2(180.0f); aIMN_setupAction(insect, aIMN_ACT_LET_ESCAPE, game); diff --git a/src/actor/ac_ins_semi.c b/src/actor/ac_ins_semi.c index 52872213..a151080e 100644 --- a/src/actor/ac_ins_semi.c +++ b/src/actor/ac_ins_semi.c @@ -144,9 +144,9 @@ static int aISM_check_player_net(ACTOR* actorx) { int ret = FALSE; if (mPlib_Check_StopNet(&net_pos) == TRUE) { - u32 catch_label = mPlib_Get_item_net_catch_label(); + uintptr_t catch_label = mPlib_Get_item_net_catch_label(); - if (catch_label == (u32)actorx) { + if (catch_label == (uintptr_t)actorx) { aISM_IS_CAUGHT(insect) = TRUE; } else { f32 dx = net_pos.x - actorx->world.position.x; @@ -248,7 +248,7 @@ static void aISM_avoid(ACTOR* actorx, GAME* game) { } if (insect->type == aINS_INSECT_TYPE_BEE) { - sAdo_OngenPos((u32)actorx, NA_SE_26, &actorx->world.position); + sAdo_OngenPos((uintptr_t)actorx, NA_SE_26, &actorx->world.position); } } @@ -277,7 +277,7 @@ static void aISM_wait(ACTOR* actorx, GAME* game) { int semi_idx = insect->type - aINS_INSECT_TYPE_ROBUST_CICADA; insect->timer = 0; - sAdo_OngenPos((u32)actorx, semi_sound_data[semi_idx], &actorx->world.position); + sAdo_OngenPos((uintptr_t)actorx, semi_sound_data[semi_idx], &actorx->world.position); actorx->world.position.x = actorx->home.position.x + RANDOM_F(0.4f); } } else { @@ -376,9 +376,9 @@ static void aISM_setupAction(aINS_INSECT_ACTOR* insect, int action, GAME* game) */ static void aISM_actor_move(ACTOR* actorx, GAME* game) { aINS_INSECT_ACTOR* ins = (aINS_INSECT_ACTOR*)actorx; - u32 catch_label = (u32)mPlib_Get_item_net_catch_label(); + uintptr_t catch_label = mPlib_Get_item_net_catch_label(); - if (catch_label == (u32)ins) { + if (catch_label == (uintptr_t)ins) { aISM_setupAction(ins, aISM_ACT_LET_ESCAPE, game); } else if (ins->insect_flags.bit_3 == TRUE && ins->insect_flags.bit_2 == FALSE) { aISM_setupAction(ins, aISM_ACT_LET_ESCAPE, game); diff --git a/src/actor/ac_ins_tentou.c b/src/actor/ac_ins_tentou.c index 7db46477..8ac82412 100644 --- a/src/actor/ac_ins_tentou.c +++ b/src/actor/ac_ins_tentou.c @@ -133,9 +133,9 @@ static int aITT_check_player_net(ACTOR* actorx) { int ret = FALSE; if (mPlib_Check_StopNet(&net_pos) == TRUE) { - u32 catch_label = mPlib_Get_item_net_catch_label(); + uintptr_t catch_label = mPlib_Get_item_net_catch_label(); - if (catch_label != (u32)actorx) { + if (catch_label != (uintptr_t)actorx) { f32 dx = net_pos.x - actorx->world.position.x; f32 dz = net_pos.z - actorx->world.position.z; @@ -277,7 +277,7 @@ static void aITT_avoid(ACTOR* actorx, GAME* game) { case aINS_INSECT_TYPE_LADYBUG: case aINS_INSECT_TYPE_SPOTTED_LADYBUG: case aINS_INSECT_TYPE_MANTIS: - sAdo_OngenPos((u32)actorx, NA_SE_26, &actorx->world.position); + sAdo_OngenPos((uintptr_t)actorx, NA_SE_26, &actorx->world.position); break; } } @@ -495,9 +495,9 @@ static void aITT_setupAction(aINS_INSECT_ACTOR* insect, int action, GAME* game) */ static void aITT_actor_move(ACTOR* actorx, GAME* game) { aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actorx; - u32 catch_label = mPlib_Get_item_net_catch_label(); + uintptr_t catch_label = mPlib_Get_item_net_catch_label(); - if (catch_label == (u32)actorx) { + if (catch_label == (uintptr_t)actorx) { // @BUG - They forgot to make a separate case for the snail, // so it uses the ladybug/spotted ladybug/mantis let escape behavior. // This was fixed in the Australian release. diff --git a/src/actor/ac_ins_tonbo.c b/src/actor/ac_ins_tonbo.c index 4af61426..5153de06 100644 --- a/src/actor/ac_ins_tonbo.c +++ b/src/actor/ac_ins_tonbo.c @@ -831,9 +831,9 @@ static void aITB_setupAction(aINS_INSECT_ACTOR* insect, int action, GAME* game) */ static void aITB_actor_move(ACTOR* actorx, GAME* game) { aINS_INSECT_ACTOR* ins = (aINS_INSECT_ACTOR*)actorx; - u32 catch_label = (u32)mPlib_Get_item_net_catch_label(); + uintptr_t catch_label = mPlib_Get_item_net_catch_label(); - if (catch_label == (u32)ins) { + if (catch_label == (uintptr_t)ins) { ins->alpha0 = 255; aITB_setupAction(ins, aITB_ACT_LET_ESCAPE, game); } else if (ins->insect_flags.bit_3 == TRUE && ins->insect_flags.bit_2 == FALSE) { diff --git a/src/actor/ac_insect_move.c_inc b/src/actor/ac_insect_move.c_inc index 7ef958d7..75391627 100644 --- a/src/actor/ac_insect_move.c_inc +++ b/src/actor/ac_insect_move.c_inc @@ -337,7 +337,7 @@ static void aINS_set_catch_range(ACTOR* actorx) { if (!F32_IS_ZERO(catch_range)) { GET_PLAYER_ACTOR_NOW()->Set_Item_net_catch_request_table_proc( - (ACTOR*)GET_PLAYER_ACTOR_NOW(), gamePT, (u32)actorx, 0, &actorx->world.position, catch_range); + (ACTOR*)GET_PLAYER_ACTOR_NOW(), gamePT, (uintptr_t)actorx, 0, &actorx->world.position, catch_range); } } } diff --git a/src/actor/ac_intro_demo.c b/src/actor/ac_intro_demo.c index 394efd4f..ff1e9c28 100644 --- a/src/actor/ac_intro_demo.c +++ b/src/actor/ac_intro_demo.c @@ -63,20 +63,20 @@ static void aID_actor_ct(ACTOR* actorx, GAME* game) { if (mEv_CheckFirstIntro() == TRUE) { if (Common_Get(field_type) == mFI_FIELDTYPE_FG) { switch (mFI_GET_TYPE(Common_Get(last_field_id))) { - case mFI_FIELD_PLAYER0_ROOM: - intro_demo->_1A4 = TRUE; - intro_demo->next_action = aID_ACT_DECIDE_HOUSE; - aID_setupAction(intro_demo, play, aID_ACT_BIRTH_RCN_GUIDE); - mBGMPsComp_make_ps_demo(BGM_INTRO_RCN_GUIDE, 0x168); - break; - default: - aID_setupAction(intro_demo, play, 0); - break; + case mFI_FIELD_PLAYER0_ROOM: + intro_demo->_1A4 = TRUE; + intro_demo->next_action = aID_ACT_DECIDE_HOUSE; + aID_setupAction(intro_demo, play, aID_ACT_BIRTH_RCN_GUIDE); + mBGMPsComp_make_ps_demo(BGM_INTRO_RCN_GUIDE, 0x168); + break; + default: + aID_setupAction(intro_demo, play, 0); + break; + } + } else { + aID_setupAction(intro_demo, play, aID_ACT_IN_HOUSE); } } else { - aID_setupAction(intro_demo, play, aID_ACT_IN_HOUSE); - } - } else { aID_setupAction(intro_demo, play, aID_ACT_FIRST_JOB); } } diff --git a/src/actor/ac_kamakura_indoor.c b/src/actor/ac_kamakura_indoor.c index 97c6ac72..f0a92907 100644 --- a/src/actor/ac_kamakura_indoor.c +++ b/src/actor/ac_kamakura_indoor.c @@ -320,7 +320,7 @@ static void Kamakura_Indoor_Actor_move(ACTOR* actorx, GAME* game) { int i; s16 timer; - sAdo_OngenPos((u32)actorx, NA_SE_KOKORO_TOGURU, &k_indoor->mochi.pos); + sAdo_OngenPos((uintptr_t)actorx, NA_SE_KOKORO_TOGURU, &k_indoor->mochi.pos); if ((play->game_frame & 7) == 0) { xyz_t soba_yuge_pos = k_indoor->mochi.pos; diff --git a/src/actor/ac_koinobori_move.c_inc b/src/actor/ac_koinobori_move.c_inc index edb223b1..3ba00a61 100644 --- a/src/actor/ac_koinobori_move.c_inc +++ b/src/actor/ac_koinobori_move.c_inc @@ -18,7 +18,7 @@ static void aKOI_actor_move(ACTOR* actor, GAME* game) { cKF_SkeletonInfo_R_play(&koinobori->structure_class.keyframe); koinobori->structure_class.action_proc(&koinobori->structure_class, game_play); - sAdo_OngenPos((u32)actor, 0x35, &actor->world.position); + sAdo_OngenPos((uintptr_t)actor, 0x35, &actor->world.position); } static void aKOI_actor_init(ACTOR* actor, GAME* game) { diff --git a/src/actor/ac_misin.c b/src/actor/ac_misin.c index 0e2f727a..9cbf01d8 100644 --- a/src/actor/ac_misin.c +++ b/src/actor/ac_misin.c @@ -287,7 +287,7 @@ static void aMSN_MoveDustcloth(aMSN_DustCloth_c* dustcloth, GAME* game) { /* Play sewing SFX */ xyz_t pos = { 91.0f, 40.0f, 136.0f }; - sAdo_OngenPos((u32)&aMSN_MoveDustcloth, 0x48, &pos); + sAdo_OngenPos((uintptr_t)&aMSN_MoveDustcloth, 0x48, &pos); } } else if (dustcloth->frame >= 120) { f32 percent = get_percent(138, 120, dustcloth->frame); diff --git a/src/actor/ac_museum_insect_batta.c_inc b/src/actor/ac_museum_insect_batta.c_inc index a3dfac64..834c01f1 100644 --- a/src/actor/ac_museum_insect_batta.c_inc +++ b/src/actor/ac_museum_insect_batta.c_inc @@ -202,7 +202,7 @@ void minsect_batta_mv(MUSEUM_INSECT_PRIVATE_DATA* actor, GAME* game) { } } if (dist < 200.f) { - sAdo_OngenPos((u32)actor, batta_sound_data[id], &actor->_1C); + sAdo_OngenPos((uintptr_t)actor, batta_sound_data[id], &actor->_1C); } } else if (actor->_04 == minsect_batta_silent_process && actor->_8E == 0) { if (actor->_00 == 17) { @@ -212,7 +212,7 @@ void minsect_batta_mv(MUSEUM_INSECT_PRIVATE_DATA* actor, GAME* game) { } } if (dist < 200.f) { - sAdo_OngenPos((u32)actor, batta_sound_data[id], &actor->_1C); + sAdo_OngenPos((uintptr_t)actor, batta_sound_data[id], &actor->_1C); } } } diff --git a/src/actor/ac_museum_insect_goki.c_inc b/src/actor/ac_museum_insect_goki.c_inc index 8b1574d0..0067321f 100644 --- a/src/actor/ac_museum_insect_goki.c_inc +++ b/src/actor/ac_museum_insect_goki.c_inc @@ -152,7 +152,7 @@ void minsect_goki_mv(MUSEUM_INSECT_PRIVATE_DATA* actor, GAME* game) { if (actor->_40 > 0.f) { goki_wall_hit_angle_corect(actor, game); mID_insect_moveF(actor); - sAdo_OngenPos((u32)actor, 0xa8, &actor->_1C); + sAdo_OngenPos((uintptr_t)actor, 0xa8, &actor->_1C); if (actor->_6E-- < 0) { if (RANDOM_F(1.f) > 0.2f) { actor->_6E = (s16)RANDOM_F(420.f) + 180; diff --git a/src/actor/ac_museum_insect_ka.c_inc b/src/actor/ac_museum_insect_ka.c_inc index d4b93d87..51d1f66a 100644 --- a/src/actor/ac_museum_insect_ka.c_inc +++ b/src/actor/ac_museum_insect_ka.c_inc @@ -75,7 +75,7 @@ void minsect_ka_mv(MUSEUM_INSECT_PRIVATE_DATA* actor, GAME* game) { actor->_6E = (s16)RANDOM_F(1200.f) + 600; } if (dist < 300.f) { - sAdo_OngenPos((u32)actor, 0xcf, &actor->_1C); + sAdo_OngenPos((uintptr_t)actor, 0xcf, &actor->_1C); } mID_insect_moveF(actor); actor->_0C += actor->_10; diff --git a/src/actor/ac_museum_insect_okera.c_inc b/src/actor/ac_museum_insect_okera.c_inc index 0e549d0d..f400f93c 100644 --- a/src/actor/ac_museum_insect_okera.c_inc +++ b/src/actor/ac_museum_insect_okera.c_inc @@ -179,10 +179,10 @@ void minsect_okera_mv(MUSEUM_INSECT_PRIVATE_DATA* actor, GAME* game) { f32 dist = search_position_distance(&actor->_1C, &player->actor_class.world.position); actor->_04(actor, game); if (actor->_04 == okera_dig_wait_process && dist < 200.f) { - sAdo_OngenPos((u32)actor, 68, &actor->_1C); + sAdo_OngenPos((uintptr_t)actor, 68, &actor->_1C); } if (actor->_04 == okera_dig_up_process && dist < 200.f) { - sAdo_OngenPos((u32)actor, 69, &actor->_1C); + sAdo_OngenPos((uintptr_t)actor, 69, &actor->_1C); } //! NOTE: has to be written this way to match diff --git a/src/actor/ac_museum_insect_semi.c_inc b/src/actor/ac_museum_insect_semi.c_inc index 6b5a3dd9..1e15f213 100644 --- a/src/actor/ac_museum_insect_semi.c_inc +++ b/src/actor/ac_museum_insect_semi.c_inc @@ -82,7 +82,7 @@ void minsect_semi_mv(MUSEUM_INSECT_PRIVATE_DATA* actor, GAME* game) { static const u8 semi_sound_data[4] = { 0x9b, 0x9a, 0x98, 0x97 }; PLAYER_ACTOR* player = get_player_actor_withoutCheck((GAME_PLAY*)game); if (search_position_distance(&actor->_1C, &player->actor_class.world.position) < 200.f) { - sAdo_OngenPos((u32)actor, semi_sound_data[id], &actor->_1C); + sAdo_OngenPos((uintptr_t)actor, semi_sound_data[id], &actor->_1C); } if (actor->_70 <= 0) { actor->_70 = 7; diff --git a/src/actor/ac_my_house_move.c_inc b/src/actor/ac_my_house_move.c_inc index 6df9e894..3c7de04d 100644 --- a/src/actor/ac_my_house_move.c_inc +++ b/src/actor/ac_my_house_move.c_inc @@ -373,8 +373,9 @@ static void aMHS_wait(STRUCTURE_ACTOR* my_house, GAME_PLAY* play) { static void aMHS_open_door_wait(STRUCTURE_ACTOR* my_house, GAME_PLAY* play) { ACTOR* actorx = (ACTOR*)my_house; + ACTOR* door_label = (*GET_PLAYER_ACTOR_NOW()->get_door_label_proc)(gamePT); - if (actorx == (*GET_PLAYER_ACTOR_NOW()->get_door_label_proc)(gamePT)) { + if (actorx == door_label) { mBGMPsComp_make_ps_wipe(0x249); aMHS_setup_animation(my_house, 0.5f); aMHS_setup_action(my_house, aMHS_ACTION_OPEN_DOOR); diff --git a/src/actor/ac_my_room.c b/src/actor/ac_my_room.c index 0005cb69..d3d49597 100644 --- a/src/actor/ac_my_room.c +++ b/src/actor/ac_my_room.c @@ -2140,7 +2140,7 @@ static void aMR_CallSitDownOngenPosSE(const xyz_t* pos) { /* Check for massage chair */ switch (ftr_actor->name) { case FTR_KON_MASAJI: - sAdo_OngenPos((u32)ftr_actor, 39, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 39, &ftr_actor->position); break; } } diff --git a/src/actor/ac_shrine_move.c_inc b/src/actor/ac_shrine_move.c_inc index 51c7f41b..2e912769 100644 --- a/src/actor/ac_shrine_move.c_inc +++ b/src/actor/ac_shrine_move.c_inc @@ -372,7 +372,7 @@ static void aSHR_actor_move(ACTOR* actorx, GAME* game) { (*(aSHR_PROC)shrine->structure_class.action_proc)(shrine, play); aSHR_Present_move(&aSHR_present, shrine, play); - sAdo_OngenPos((u32)actorx, 0x5A, &actorx->world.position); + sAdo_OngenPos((uintptr_t)actorx, 0x5A, &actorx->world.position); } static void aSHR_actor_init(ACTOR* actorx, GAME* game) { diff --git a/src/actor/ac_snowman.c b/src/actor/ac_snowman.c index 15bfbd0a..3b40843c 100644 --- a/src/actor/ac_snowman.c +++ b/src/actor/ac_snowman.c @@ -997,7 +997,7 @@ static int aSMAN_process_player_push(ACTOR* actorx, GAME* game) { aSMAN_Make_Effect_Ground(actorx, game); if (actorx->speed > 1.0f) { - sAdo_OngenPos((u32)actorx, 52, &actorx->world.position); + sAdo_OngenPos((uintptr_t)actorx, 52, &actorx->world.position); } aSMAN_player_push_scroll_request(actorx, game); } diff --git a/src/actor/ac_train0.c b/src/actor/ac_train0.c index 1575a40d..f4db1123 100644 --- a/src/actor/ac_train0.c +++ b/src/actor/ac_train0.c @@ -52,10 +52,12 @@ static void aTR0_actor_dt(ACTOR* actor, GAME* game) { tr_home_pos = train0->actor_class.home.position; mFI_SetFG_common(EMPTY_NO, tr_home_pos, FALSE); - engineer_p = (ACTOR*)train0->arg3; - if (engineer_p != NULL) { - Actor_delete(engineer_p); - train0->arg3 = (int)NULL; + if (train0->arg3 != 0) { + engineer_p = Actor_info_fgName_search(&((GAME_PLAY*)game)->actor_info, SP_NPC_ENGINEER, ACTOR_PART_NPC); + if (engineer_p != NULL) { + Actor_delete(engineer_p); + } + train0->arg3 = 0; } cKF_SkeletonInfo_R_dt(&train0->keyframe); diff --git a/src/actor/ac_train0_move.c_inc b/src/actor/ac_train0_move.c_inc index c99ac36d..7dc59f8d 100644 --- a/src/actor/ac_train0_move.c_inc +++ b/src/actor/ac_train0_move.c_inc @@ -3,11 +3,11 @@ static void aTR0_ctrl_engineer(ACTOR* actor, GAME* game) { GAME_PLAY* play = (GAME_PLAY*)game; ACTOR* ac_p; - ac_p = (ACTOR*)train0->arg3; + ac_p = Actor_info_fgName_search(&play->actor_info, SP_NPC_ENGINEER, ACTOR_PART_NPC); if (ac_p == NULL) { if (CLIP(npc_clip)->setupActor_proc(play, SP_NPC_ENGINEER, -1, -1, -1, -1, -1, 0, 0) == TRUE) { - train0->arg3 = (int)Actor_info_fgName_search(&play->actor_info, SP_NPC_ENGINEER, ACTOR_PART_NPC); + train0->arg3 = TRUE; } } else { ac_p->world.position.x = -40.0f + train0->actor_class.world.position.x; @@ -157,7 +157,10 @@ static void aTR0_delcheck(ACTOR* actor, GAME* game) { if ((abs_x >= 2) || (z != play->block_table.block_z) || (train0->action == 0)) { if (train0->arg3 != 0) { - Actor_delete((ACTOR*)train0->arg3); + ACTOR* eng = Actor_info_fgName_search(&play->actor_info, SP_NPC_ENGINEER, ACTOR_PART_NPC); + if (eng != NULL) { + Actor_delete(eng); + } } Actor_delete(actor->child_actor); Actor_delete(actor); diff --git a/src/actor/npc/ac_countdown_npc1_talk.c_inc b/src/actor/npc/ac_countdown_npc1_talk.c_inc index d1fa6314..79b535aa 100644 --- a/src/actor/npc/ac_countdown_npc1_talk.c_inc +++ b/src/actor/npc/ac_countdown_npc1_talk.c_inc @@ -167,7 +167,7 @@ static void aCD1_clap(COUNTDOWN_NPC1_ACTOR* actor) { int idx = actor->npc_class.actor_class.npc_id - SP_NPC_EV_COUNTDOWN_1; aCD1_before_wait(actor); - sAdo_OngenPos((u32)actor, se_no[idx], &actor->npc_class.actor_class.world.position); + sAdo_OngenPos((uintptr_t)actor, se_no[idx], &actor->npc_class.actor_class.world.position); } static void aCD1_set_spd_info(COUNTDOWN_NPC1_ACTOR* actor, int action) { diff --git a/src/actor/npc/ac_hanabi_npc1_talk.c_inc b/src/actor/npc/ac_hanabi_npc1_talk.c_inc index a6302b4b..692ddf8e 100644 --- a/src/actor/npc/ac_hanabi_npc1_talk.c_inc +++ b/src/actor/npc/ac_hanabi_npc1_talk.c_inc @@ -48,7 +48,7 @@ static void aHN1_hurrahs(HANABI_NPC1_ACTOR* actor) { static void aHN1_clapping(HANABI_NPC1_ACTOR* actor) { aHN1_hurrahs(actor); - sAdo_OngenPos((u32)actor, actor->clap_se_no, &actor->npc_class.actor_class.world.position); + sAdo_OngenPos((uintptr_t)actor, actor->clap_se_no, &actor->npc_class.actor_class.world.position); } static void aHN1_setupAction(HANABI_NPC1_ACTOR* actor, int action) { diff --git a/src/actor/npc/ac_hanami_npc0_talk.c_inc b/src/actor/npc/ac_hanami_npc0_talk.c_inc index 419d1b24..1444089e 100644 --- a/src/actor/npc/ac_hanami_npc0_talk.c_inc +++ b/src/actor/npc/ac_hanami_npc0_talk.c_inc @@ -35,7 +35,7 @@ static void aHM0_merry(HANAMI_NPC0_ACTOR* actor) { } } - sAdo_OngenPos((u32)actor, actor->clap_se_no, &actor->npc_class.actor_class.world.position); + sAdo_OngenPos((uintptr_t)actor, actor->clap_se_no, &actor->npc_class.actor_class.world.position); } static void aHM0_drink(HANAMI_NPC0_ACTOR* actor) { diff --git a/src/actor/npc/ac_harvest_npc0.c_inc b/src/actor/npc/ac_harvest_npc0.c_inc index e6505ee6..44c6c0c7 100644 --- a/src/actor/npc/ac_harvest_npc0.c_inc +++ b/src/actor/npc/ac_harvest_npc0.c_inc @@ -36,7 +36,7 @@ static void aHT0_merry(NPC_HARVEST_NPC0_ACTOR* actor, GAME_PLAY* play) { actor->actor.draw.loop_flag--; } } - sAdo_OngenPos((u32)actor, actor->_9A8, &actor->actor.actor_class.world.position); + sAdo_OngenPos((uintptr_t)actor, actor->_9A8, &actor->actor.actor_class.world.position); } static void aHT0_drink(NPC_HARVEST_NPC0_ACTOR* actor, GAME_PLAY* play) { diff --git a/src/actor/npc/ac_npc_ctrl.c_inc b/src/actor/npc/ac_npc_ctrl.c_inc index 7ad2a76a..ce660abb 100644 --- a/src/actor/npc/ac_npc_ctrl.c_inc +++ b/src/actor/npc/ac_npc_ctrl.c_inc @@ -516,7 +516,7 @@ static int aNPC_setupActor_proc(GAME_PLAY* play, mActor_name_t name, s8 idx, int pos.y = mCoBG_GetBgY_OnlyCenter_FromWpos(pos, 0.0f); } - aNPC_setupActor_sub(play, idx, name, profile, &pos, mvlist_no, arg); + return aNPC_setupActor_sub(play, idx, name, profile, &pos, mvlist_no, arg); } #ifndef aNPC_NPC2 @@ -644,7 +644,11 @@ static ACTOR* aNPC_get_actor_area_proc(size_t size, const char* actor_name, int int* used = CLIP(npc_clip)->keep_actor_used; int i; +#ifdef TARGET_PC + if (size > 0xC00) { +#else if (size > 0x9D0) { +#endif return NULL; } @@ -694,7 +698,11 @@ static void aNPC_dma_draw_data_proc(aNPC_draw_data_c* draw_data_p, mActor_name_t #ifndef aNPC_NPC2 typedef struct { u64 align; +#ifdef TARGET_PC + u8 buf[0xC00]; /* 64-bit: NPC structs are larger due to pointer widening */ +#else u8 buf[0x9D0]; +#endif } aNPC_actor_class_overlay_c; typedef struct { @@ -729,7 +737,7 @@ static void aNPC_keep_actor_class(void) { int i; for (i = 0; i < 9; i++) { - *actor = (NPC_ACTOR*)ALIGN_NEXT((u32)aNPC_n_actor_cl_tbl[i].buf, 16); + *actor = (NPC_ACTOR*)ALIGN_NEXT((uintptr_t)aNPC_n_actor_cl_tbl[i].buf, 16); *used = FALSE; actor++; diff --git a/src/actor/npc/ac_tamaire_npc0_schedule.c_inc b/src/actor/npc/ac_tamaire_npc0_schedule.c_inc index 72b1cbb5..2972789d 100644 --- a/src/actor/npc/ac_tamaire_npc0_schedule.c_inc +++ b/src/actor/npc/ac_tamaire_npc0_schedule.c_inc @@ -55,7 +55,7 @@ static void aTMN0_timer_next(TAMAIRE_NPC0_ACTOR* actor, GAME_PLAY* play) { } if (actor->npc_class.draw.animation_id == aNPC_ANIM_CLAP1) { - sAdo_OngenPos((u32)actorx, NA_SE_2F, &actorx->world.position); + sAdo_OngenPos((uintptr_t)actorx, NA_SE_2F, &actorx->world.position); } } diff --git a/src/actor/npc/ac_tokyoso_npc1_schedule.c_inc b/src/actor/npc/ac_tokyoso_npc1_schedule.c_inc index 63daf5ee..919226bc 100644 --- a/src/actor/npc/ac_tokyoso_npc1_schedule.c_inc +++ b/src/actor/npc/ac_tokyoso_npc1_schedule.c_inc @@ -168,9 +168,9 @@ static void aTKN1_omedeto(TOKYOSO_NPC1_ACTOR* actor, GAME_PLAY* play) { } if (aTKC_NPCID2TEAM(actorx->npc_id) != 0) { - sAdo_OngenPos((u32)actorx, 0x2F, &actorx->world.position); + sAdo_OngenPos((uintptr_t)actorx, 0x2F, &actorx->world.position); } else { - sAdo_OngenPos((u32)actorx, 0x31, &actorx->world.position); + sAdo_OngenPos((uintptr_t)actorx, 0x31, &actorx->world.position); } } diff --git a/src/actor/npc/event/ac_ev_soncho2_think.c_inc b/src/actor/npc/event/ac_ev_soncho2_think.c_inc index 26b917cb..28504f60 100644 --- a/src/actor/npc/event/ac_ev_soncho2_think.c_inc +++ b/src/actor/npc/event/ac_ev_soncho2_think.c_inc @@ -117,7 +117,7 @@ static void aES2_tug_of_war(NPC_SONCHO2* soncho, GAME_PLAY* play) { aES2_setup_think_proc(soncho, play, soncho->think_idx); } if (soncho->npc_class.draw.animation_id == aNPC_ANIM_CLAP1) { - sAdo_OngenPos((u32)soncho, NA_SE_2F, &soncho->npc_class.actor_class.world.position); + sAdo_OngenPos((uintptr_t)soncho, NA_SE_2F, &soncho->npc_class.actor_class.world.position); } } diff --git a/src/audio.c b/src/audio.c index 457d8d19..68b4bbfa 100644 --- a/src/audio.c +++ b/src/audio.c @@ -122,7 +122,7 @@ extern void sAdo_SysLevStop(u8 id) { Na_SysLevStop(id); } -extern void sAdo_OngenPos(u32 p1, u8 p2, const xyz_t* pos) { +extern void sAdo_OngenPos(uintptr_t p1, u8 p2, const xyz_t* pos) { u16 scalc; f32 fcalc; @@ -254,7 +254,7 @@ extern void sAdos_KishaStatusTrg(u8 state) { Na_KishaStatusTrg(state); } -extern void sAdos_KishaStatusLevel(f32 speed, u32 ongenNum1, f32 distance1, u16 angle1, u32 ongenNum2, +extern void sAdos_KishaStatusLevel(f32 speed, uintptr_t ongenNum1, f32 distance1, u16 angle1, uintptr_t ongenNum2, f32 distance2, u16 angle2) { Na_KishaStatusLevel(speed, ongenNum1, angle1, distance1, ongenNum2, angle2, distance2); } diff --git a/src/bg_item/bg_item_common.c_inc b/src/bg_item/bg_item_common.c_inc index f7a8dff7..f0c9d296 100644 --- a/src/bg_item/bg_item_common.c_inc +++ b/src/bg_item/bg_item_common.c_inc @@ -517,7 +517,7 @@ static int bIT_actor_shin_effect_move(GAME* game, bg_item_shin_c* shin) { exit = TRUE; break; case 4: - sAdo_OngenPos((u32)shin, 0x2C, &shin->position); + sAdo_OngenPos((uintptr_t)shin, 0x2C, &shin->position); break; case 5: eEC_CLIP->effect_kill_proc(eEC_EFFECT_ANAHIKARI, (u16)i); diff --git a/src/data/model/ctl_sentaku.c b/src/data/model/ctl_sentaku.c index fd028951..a8b1b91f 100644 --- a/src/data/model/ctl_sentaku.c +++ b/src/data/model/ctl_sentaku.c @@ -24,7 +24,7 @@ Vtx ctl_sentaku_v[] = { Gfx ctl_sentaku_taguT_model[] = { gsDPPipeSync(), gsDPSetCombineLERP(PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, 0, 0, 0, TEXEL0, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, 0, 0, 0, TEXEL0), -gsSPDisplayList(anime_1_txt + 0x30), +gsSPDisplayList(anime_1_txt + 6 * sizeof(Gfx)), gsDPSetRenderMode(G_RM_XLU_SURF, G_RM_XLU_SURF2), gsDPSetTextureImage_Dolphin(G_IM_FMT_IA, G_IM_SIZ_8b, 32, 16, ctl_win_tagu3_tex), gsDPSetTile_Dolphin(G_DOLPHIN_TLUT_DEFAULT_MODE, 0, 0, GX_MIRROR, GX_MIRROR, 0, 0), diff --git a/src/data/model/ctl_win1.c b/src/data/model/ctl_win1.c index 5b52d9db..3247ea4d 100644 --- a/src/data/model/ctl_win1.c +++ b/src/data/model/ctl_win1.c @@ -428,7 +428,7 @@ gsSPEndDisplayList(), Gfx ctl_win1_ue2T_model[] = { gsDPPipeSync(), -gsSPDisplayList(anime_1_txt + 0x18), +gsSPDisplayList(anime_1_txt + 3 * sizeof(Gfx)), gsDPSetTextureImage_Dolphin(G_IM_FMT_IA, G_IM_SIZ_8b, 32, 32, ctl_win_aw7_tex), gsDPSetTile_Dolphin(G_DOLPHIN_TLUT_DEFAULT_MODE, 0, 0, GX_MIRROR, GX_MIRROR, 0, 0), gsSPVertex(&ctl_win1_v[8], 4, 0), @@ -481,7 +481,7 @@ gsSPEndDisplayList(), Gfx ctl_win1_nameT_model[] = { gsDPPipeSync(), -gsSPDisplayList(anime_1_txt + 0x30), +gsSPDisplayList(anime_1_txt + 6 * sizeof(Gfx)), gsDPSetTextureImage_Dolphin(G_IM_FMT_IA, G_IM_SIZ_8b, 64, 32, ctl_win_waku4_tex), gsDPSetTile_Dolphin(G_DOLPHIN_TLUT_DEFAULT_MODE, 0, 0, GX_MIRROR, GX_MIRROR, 0, 0), gsSPVertex(&ctl_win1_v[70], 4, 0), diff --git a/src/data/model/kan_waku.c b/src/data/model/kan_waku.c index c4e7408a..80c8656e 100644 --- a/src/data/model/kan_waku.c +++ b/src/data/model/kan_waku.c @@ -54,7 +54,7 @@ Vtx kan_waku_v[] = { #endif Gfx kan_waku_w1T_model[] = { - gsSPDisplayList(anime_4_txt + 0x58), + gsSPDisplayList(anime_4_txt + 11 * sizeof(Gfx)), gsDPSetTextureImage_Dolphin(G_IM_FMT_IA, G_IM_SIZ_8b, 64, 64, kan_win_waku1b_tex), gsDPSetTile_Dolphin(G_DOLPHIN_TLUT_DEFAULT_MODE, 0, 0, GX_MIRROR, GX_MIRROR, 0, 0), gsSPVertex(kan_waku_v, 8, 0), @@ -66,7 +66,7 @@ Gfx kan_waku_w1T_model[] = { }; Gfx kan_waku_w2T_model[] = { - gsSPDisplayList(anime_4_txt + 0x58), + gsSPDisplayList(anime_4_txt + 11 * sizeof(Gfx)), gsDPSetTextureImage_Dolphin(G_IM_FMT_IA, G_IM_SIZ_8b, 64, 64, kan_win_waku3_tex), gsDPSetTile_Dolphin(G_DOLPHIN_TLUT_DEFAULT_MODE, 0, 0, GX_MIRROR, GX_MIRROR, 0, 0), gsSPVertex(&kan_waku_v[8], 4, 0), @@ -75,7 +75,7 @@ Gfx kan_waku_w2T_model[] = { }; Gfx kan_waku_w3T_model[] = { - gsSPDisplayList(anime_4_txt + 0x58), + gsSPDisplayList(anime_4_txt + 11 * sizeof(Gfx)), gsDPSetTextureImage_Dolphin(G_IM_FMT_IA, G_IM_SIZ_8b, 64, 64, kan_win_waku4_tex), gsDPSetTile_Dolphin(G_DOLPHIN_TLUT_DEFAULT_MODE, 0, 0, GX_MIRROR, GX_MIRROR, 0, 0), gsSPVertex(&kan_waku_v[12], 4, 0), @@ -84,7 +84,7 @@ Gfx kan_waku_w3T_model[] = { }; Gfx kan_waku_w4T_model[] = { - gsSPDisplayList(anime_4_txt + 0x58), + gsSPDisplayList(anime_4_txt + 11 * sizeof(Gfx)), gsDPSetTextureImage_Dolphin(G_IM_FMT_IA, G_IM_SIZ_8b, 64, 64, kan_win_waku5_tex), gsDPSetTile_Dolphin(G_DOLPHIN_TLUT_DEFAULT_MODE, 0, 0, GX_MIRROR, GX_MIRROR, 0, 0), gsSPVertex(&kan_waku_v[16], 4, 0), diff --git a/src/data/model/kan_win.c b/src/data/model/kan_win.c index 82d04e54..b91bd51d 100644 --- a/src/data/model/kan_win.c +++ b/src/data/model/kan_win.c @@ -278,7 +278,7 @@ Vtx kan_win_v[] = { #endif Gfx kan_win_moji1_model[] = { - gsSPDisplayList(anime_4_txt + 0x48), + gsSPDisplayList(anime_4_txt + 9 * sizeof(Gfx)), gsDPSetTextureImage_Dolphin(G_IM_FMT_I, G_IM_SIZ_4b, 64, 16, kan_win_map_tex), gsDPSetTile_Dolphin(G_DOLPHIN_TLUT_DEFAULT_MODE, 0, 15, GX_CLAMP, GX_CLAMP, 0, 0), gsSPVertex(kan_win_v, 4, 0), @@ -287,7 +287,7 @@ Gfx kan_win_moji1_model[] = { }; Gfx kan_win_moji2_model[] = { - gsSPDisplayList(anime_4_txt + 0x70), + gsSPDisplayList(anime_4_txt + 14 * sizeof(Gfx)), gsDPSetTextureImage_Dolphin(G_IM_FMT_I, G_IM_SIZ_4b, 32, 16, kan_win_acre_tex), gsDPSetTile_Dolphin(G_DOLPHIN_TLUT_DEFAULT_MODE, 0, 15, GX_CLAMP, GX_CLAMP, 0, 0), gsSPVertex(&kan_win_v[4], 4, 0), @@ -321,7 +321,7 @@ Gfx kan_win_kiwakuT_model[] = { }; Gfx kan_win_futiT_model[] = { - gsSPDisplayList(anime_4_txt + 0x18), + gsSPDisplayList(anime_4_txt + 3 * sizeof(Gfx)), gsDPSetTextureImage_Dolphin(G_IM_FMT_IA, G_IM_SIZ_8b, 16, 16, kan_win_ga4_tex), gsDPSetTile_Dolphin(G_DOLPHIN_TLUT_DEFAULT_MODE, 0, 0, GX_CLAMP, GX_CLAMP, 0, 0), gsSPVertex(&kan_win_v[39], 16, 0), @@ -339,7 +339,7 @@ Gfx kan_win_futiT_model[] = { }; Gfx kan_win_futi2T_model[] = { - gsSPDisplayList(anime_4_txt + 0x30), + gsSPDisplayList(anime_4_txt + 6 * sizeof(Gfx)), gsDPSetTextureImage_Dolphin(G_IM_FMT_IA, G_IM_SIZ_8b, 16, 16, kan_win_ga4_tex), gsDPSetTile_Dolphin(G_DOLPHIN_TLUT_DEFAULT_MODE, 0, 0, GX_CLAMP, GX_CLAMP, 0, 0), gsSPVertex(&kan_win_v[55], 16, 0), @@ -357,7 +357,7 @@ Gfx kan_win_futi2T_model[] = { }; Gfx kan_win_wakuT_model[] = { - gsSPDisplayList(anime_4_txt + 0x58), + gsSPDisplayList(anime_4_txt + 11 * sizeof(Gfx)), gsDPSetTextureImage_Dolphin(G_IM_FMT_IA, G_IM_SIZ_8b, 64, 64, kan_win_waku2a_tex), gsDPSetTile_Dolphin(G_DOLPHIN_TLUT_DEFAULT_MODE, 0, 0, GX_MIRROR, GX_MIRROR, 0, 0), gsSPVertex(&kan_win_v[71], 4, 0), @@ -433,7 +433,7 @@ Gfx kan_win_tyou2T_model[] = { }; Gfx kan_win_sakiT_model[] = { - gsSPDisplayList(anime_4_txt + 0x58), + gsSPDisplayList(anime_4_txt + 11 * sizeof(Gfx)), gsDPSetTextureImage_Dolphin(G_IM_FMT_IA, G_IM_SIZ_8b, 32, 32, kan_win_saki_tex), gsDPSetTile_Dolphin(G_DOLPHIN_TLUT_DEFAULT_MODE, 0, 0, GX_MIRROR, GX_MIRROR, 0, 0), gsSPVertex(&kan_win_v[127], 4, 0), diff --git a/src/effect/ef_ase2.c b/src/effect/ef_ase2.c index c286c6ec..ccca1195 100644 --- a/src/effect/ef_ase2.c +++ b/src/effect/ef_ase2.c @@ -50,7 +50,7 @@ static void eAS2_ct(eEC_Effect_c* effect, GAME* game, void* ct_arg) { static void eAS2_mv(eEC_Effect_c* effect, GAME* game) { eEC_CLIP->set_continious_env_proc(effect, 26, 52); effect->effect_specific[0]++; - sAdo_OngenPos((u32)effect, 0x29, &effect->position); + sAdo_OngenPos((uintptr_t)effect, 0x29, &effect->position); } static void eAS2_dw(eEC_Effect_c* effect, GAME* game) { diff --git a/src/effect/ef_buruburu.c b/src/effect/ef_buruburu.c index 7290a8a9..aaa0dca8 100644 --- a/src/effect/ef_buruburu.c +++ b/src/effect/ef_buruburu.c @@ -50,7 +50,7 @@ static void eBR_ct(eEC_Effect_c* effect, GAME* game, void* ct_arg) { static void eBR_mv(eEC_Effect_c* effect, GAME* game) { eEC_CLIP->set_continious_env_proc(effect,8,8); - sAdo_OngenPos((u32) effect, 0x2D, &effect->position); + sAdo_OngenPos((uintptr_t) effect, 0x2D, &effect->position); } static void eBR_dw(eEC_Effect_c* effect, GAME* game) { diff --git a/src/effect/ef_kangaeru.c b/src/effect/ef_kangaeru.c index 11cbb29b..72530954 100644 --- a/src/effect/ef_kangaeru.c +++ b/src/effect/ef_kangaeru.c @@ -71,7 +71,7 @@ static void eKG_mv(eEC_Effect_c* effect, GAME* game) { if (effect->state == eEC_STATE_FINISHED) { effect->effect_specific[4] = (u8)eEC_CLIP->calc_adjust_proc(7 - effect->timer, 0, 6, 255.0f, 0.0f); } else { - sAdo_OngenPos((u32)effect, 0x58, &effect->position); + sAdo_OngenPos((uintptr_t)effect, 0x58, &effect->position); effect->effect_specific[4] = 255; } } diff --git a/src/effect/ef_lovelove.c b/src/effect/ef_lovelove.c index 53e9b6d9..1d16c253 100644 --- a/src/effect/ef_lovelove.c +++ b/src/effect/ef_lovelove.c @@ -33,7 +33,7 @@ static void eLove_mv(eEC_Effect_c* effect, GAME* game) { u16 name; eEC_CLIP->set_continious_env_proc(effect, 52, 102); - sAdo_OngenPos((u32)effect, 14, &effect->position); + sAdo_OngenPos((uintptr_t)effect, 14, &effect->position); if ((effect->timer & 7) == 0) { name = effect->item_name; diff --git a/src/effect/ef_naku.c b/src/effect/ef_naku.c index 76b4edc7..8507f483 100644 --- a/src/effect/ef_naku.c +++ b/src/effect/ef_naku.c @@ -51,7 +51,7 @@ static void eNaku_mv(eEC_Effect_c* effect, GAME* game) { effect->effect_specific[1]++; } - sAdo_OngenPos((u32)effect, 0x2E, &effect->position); + sAdo_OngenPos((uintptr_t)effect, 0x2E, &effect->position); } static void eNaku_dw(eEC_Effect_c* effect, GAME* game) { diff --git a/src/effect/ef_otikomi.c b/src/effect/ef_otikomi.c index d80939e5..b46d73a1 100644 --- a/src/effect/ef_otikomi.c +++ b/src/effect/ef_otikomi.c @@ -78,11 +78,11 @@ static void eOMN_dw(eEC_Effect_c* effect, GAME* game) { scale_y = eEC_CLIP->calc_adjust_proc(timer, 10, 21, 0.0f, 0.0135f); alpha = 255; alpha2 = 100; - sAdo_OngenPos((u32)effect, 0x59, &effect->position); + sAdo_OngenPos((uintptr_t)effect, 0x59, &effect->position); break; case eEC_STATE_CONTINUOUS: - sAdo_OngenPos((u32)effect, 0x59, &effect->position); + sAdo_OngenPos((uintptr_t)effect, 0x59, &effect->position); scale_m = 0.01f; alpha = 255; scale_y = 0.0135f; diff --git a/src/effect/ef_siawase_hikari.c b/src/effect/ef_siawase_hikari.c index 99f063da..f2b46e45 100644 --- a/src/effect/ef_siawase_hikari.c +++ b/src/effect/ef_siawase_hikari.c @@ -45,7 +45,7 @@ static void eSSHKR_ct(eEC_Effect_c* effect, GAME* game, void* ct_arg) { static void eSSHKR_mv(eEC_Effect_c* effect, GAME* game) { f32 scale; - sAdo_OngenPos((u32)effect, 14, &effect->position); + sAdo_OngenPos((uintptr_t)effect, 14, &effect->position); eEC_CLIP->set_continious_env_proc(effect, 22, 122); diff --git a/src/effect/ef_warau.c b/src/effect/ef_warau.c index f8023275..9f70854e 100644 --- a/src/effect/ef_warau.c +++ b/src/effect/ef_warau.c @@ -34,7 +34,7 @@ static void eWU_ct(eEC_Effect_c* effect, GAME* game, void* ct_arg) { } static void eWU_mv(eEC_Effect_c* effect, GAME* game) { - sAdo_OngenPos((u32)effect, 15, &effect->position); + sAdo_OngenPos((uintptr_t)effect, 15, &effect->position); eEC_CLIP->set_continious_env_proc(effect, 24, 24); } diff --git a/src/famicom_emu.c b/src/famicom_emu.c index c39a4ddb..dba8cdff 100644 --- a/src/famicom_emu.c +++ b/src/famicom_emu.c @@ -19,12 +19,12 @@ static u32 freeXfbSize = 0; static void my_alloc_init(GAME* game, void* start, size_t size) { u32 freebytes; - u32 alloc; - u32 aligned; - u32 tsize; + uintptr_t alloc; + uintptr_t aligned; + uintptr_t tsize; freebytes = game_getFreeBytes(game); - alloc = (u32)THA_alloc16(&game->tha, freebytes); + alloc = (uintptr_t)THA_alloc16(&game->tha, freebytes); aligned = ALIGN_NEXT(alloc, 16); tsize = aligned - alloc; diff --git a/src/furniture/ac_ike_island_hako01.c b/src/furniture/ac_ike_island_hako01.c index e9edf43f..eb3ad2d6 100644 --- a/src/furniture/ac_ike_island_hako01.c +++ b/src/furniture/ac_ike_island_hako01.c @@ -74,10 +74,10 @@ void fIIH_mv(FTR_ACTOR* ftr_actor, ACTOR* my_room_actor, GAME* game, u8* data) { if (aFTR_CAN_PLAY_SE(ftr_actor)) { if (ftr_actor->dynamic_work_s[0] != 0) { if (keyf->frame_control.current_frame > 25.0f) { - sAdo_OngenPos((u32)ftr_actor, 0x52, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 0x52, &ftr_actor->position); } } else if (keyf->frame_control.current_frame < 25.0f) { - sAdo_OngenPos((u32)ftr_actor, 0x52, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 0x52, &ftr_actor->position); } } } @@ -107,10 +107,10 @@ void fIIH_mv(FTR_ACTOR* ftr_actor, ACTOR* my_room_actor, GAME* game, u8* data) { if (aFTR_CAN_PLAY_SE(ftr_actor)) { if (ftr_actor->dynamic_work_s[0] != 0) { if (keyf->frame_control.current_frame > 25.0f) { - sAdo_OngenPos((u32)ftr_actor, 0x52, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 0x52, &ftr_actor->position); } } else if (keyf->frame_control.current_frame < 25.0f) { - sAdo_OngenPos((u32)ftr_actor, 0x52, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 0x52, &ftr_actor->position); } } if (cKF_SkeletonInfo_R_play(keyf) == cKF_STATE_STOPPED) { diff --git a/src/furniture/ac_ike_jny_syon01.c b/src/furniture/ac_ike_jny_syon01.c index 18960f65..fb06b9ce 100644 --- a/src/furniture/ac_ike_jny_syon01.c +++ b/src/furniture/ac_ike_jny_syon01.c @@ -31,7 +31,7 @@ static void fIJS_mv(FTR_ACTOR* ftr_actor, ACTOR* my_room_actor, GAME* game, u8* } if (ftr_actor->dynamic_work_s[0] == TRUE) { if (aFTR_CAN_PLAY_SE(ftr_actor)) { - sAdo_OngenPos((u32) ftr_actor, 0x4B, &ftr_actor->position); + sAdo_OngenPos((uintptr_t) ftr_actor, 0x4B, &ftr_actor->position); } } if (ftr_actor->dynamic_work_f[0] > alpha) { diff --git a/src/furniture/ac_ike_kama_danro01.c b/src/furniture/ac_ike_kama_danro01.c index 0b5d48ba..a13b6b49 100644 --- a/src/furniture/ac_ike_kama_danro01.c +++ b/src/furniture/ac_ike_kama_danro01.c @@ -7,7 +7,7 @@ extern Gfx int_ike_kama_danrofire_off_model[]; static void fIKD_mv(FTR_ACTOR* ftr_actor, ACTOR* my_room_actor, GAME* game, u8* data){ if(aFTR_CAN_PLAY_SE(ftr_actor)){ - sAdo_OngenPos((u32)ftr_actor, 0x46, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 0x46, &ftr_actor->position); } } static Gfx* fIKD_GetTwoTileGfx(int x0, int y0, int x1, int y1, GAME* game) { diff --git a/src/furniture/ac_ike_tent_fire01.c b/src/furniture/ac_ike_tent_fire01.c index 68ddc8da..7d35179b 100644 --- a/src/furniture/ac_ike_tent_fire01.c +++ b/src/furniture/ac_ike_tent_fire01.c @@ -17,7 +17,7 @@ static void fITF_mv(FTR_ACTOR* ftr_actor, ACTOR* my_room_actor, GAME* game, u8* keyframe->frame_control.speed = 0.5f; if (aFTR_CAN_PLAY_SE(ftr_actor)) { - sAdo_OngenPos((u32)ftr_actor, 0x5D, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 0x5D, &ftr_actor->position); } } diff --git a/src/furniture/ac_ike_tent_fire02.c b/src/furniture/ac_ike_tent_fire02.c index bfb826af..e1c84b35 100644 --- a/src/furniture/ac_ike_tent_fire02.c +++ b/src/furniture/ac_ike_tent_fire02.c @@ -18,7 +18,7 @@ static void fITF02_mv(FTR_ACTOR* ftr_actor, ACTOR* my_room_actor, GAME* game, u8 keyframe->frame_control.speed = 0.5f; if (aFTR_CAN_PLAY_SE(ftr_actor)) { - sAdo_OngenPos((u32)ftr_actor, 0x5C, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 0x5C, &ftr_actor->position); } } diff --git a/src/furniture/ac_iku_mario_star.c b/src/furniture/ac_iku_mario_star.c index 5e9afff7..292170bb 100644 --- a/src/furniture/ac_iku_mario_star.c +++ b/src/furniture/ac_iku_mario_star.c @@ -5,7 +5,7 @@ static void fIMS_ct(FTR_ACTOR* ftr_actor, u8* data) { static void fIMS_mv(FTR_ACTOR* ftr_actor, ACTOR* my_room_actor, GAME* game, u8* data) { if (aFTR_CAN_PLAY_SE(ftr_actor)) { if (ftr_actor->switch_bit == TRUE) { - sAdo_OngenPos((u32)ftr_actor, 0x5F, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 0x5F, &ftr_actor->position); mPlib_Set_change_color_request(); } diff --git a/src/furniture/ac_iku_turkey_TV.c b/src/furniture/ac_iku_turkey_TV.c index 8acd4366..af805454 100644 --- a/src/furniture/ac_iku_turkey_TV.c +++ b/src/furniture/ac_iku_turkey_TV.c @@ -5,7 +5,7 @@ static void fITT_ct(FTR_ACTOR* ftr_actor, u8* data) { static void fITT_mv(FTR_ACTOR* ftr_actor, ACTOR* my_room_actor, GAME* game, u8* data) { if (ftr_actor->switch_bit) { if (aFTR_CAN_PLAY_SE(ftr_actor)) { - sAdo_OngenPos((u32)ftr_actor, 0x5E, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 0x5E, &ftr_actor->position); } } diff --git a/src/furniture/ac_kon_snowtv.c b/src/furniture/ac_kon_snowtv.c index 76dc1ff4..9c52ff0b 100644 --- a/src/furniture/ac_kon_snowtv.c +++ b/src/furniture/ac_kon_snowtv.c @@ -35,7 +35,7 @@ static void fKST_mv(FTR_ACTOR* ftr_actor, ACTOR* my_room_actor, GAME* game, u8* if (ftr_actor->switch_bit != FALSE) { if (aFTR_CAN_PLAY_SE(ftr_actor)) { - sAdo_OngenPos((u32)ftr_actor, 0x2B, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 0x2B, &ftr_actor->position); } } @@ -133,7 +133,7 @@ static void aKonsnowtv_mv(FTR_ACTOR* ftr_actor, ACTOR* my_room_actor, GAME* game if (ftr_actor->switch_bit != FALSE) { if (aFTR_CAN_PLAY_SE(ftr_actor)) { - sAdo_OngenPos((u32)ftr_actor, 0x2B, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 0x2B, &ftr_actor->position); } ftr_actor->tex_animation.frame++; diff --git a/src/furniture/ac_nog_fan01.c b/src/furniture/ac_nog_fan01.c index 0de8a240..9c1edcb0 100644 --- a/src/furniture/ac_nog_fan01.c +++ b/src/furniture/ac_nog_fan01.c @@ -66,7 +66,7 @@ static void aNogFan_mv(FTR_ACTOR* ftr_actor, ACTOR* my_room_actor, GAME* game, u add_calc(&ftr_actor->dynamic_work_f[0], 0.5f, CALC_EASE(0.05f), 0.25f, 0.0005f); if (aFTR_CAN_PLAY_SE(ftr_actor)) { - sAdo_OngenPos((u32)ftr_actor, 1, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 1, &ftr_actor->position); } } else { add_calc(&ftr_actor->dynamic_work_f[0], 0.0f, CALC_EASE(0.05f), 0.25f, 0.0005f); diff --git a/src/furniture/ac_nog_nabe.c b/src/furniture/ac_nog_nabe.c index 80d8d3ca..bd08cac7 100644 --- a/src/furniture/ac_nog_nabe.c +++ b/src/furniture/ac_nog_nabe.c @@ -38,7 +38,7 @@ void fNNB_mv(FTR_ACTOR* ftr_actor, ACTOR* my_room_actor, GAME* game, u8* data) { if (ftr_actor->dynamic_work_s[0] == 1) { if (aFTR_CAN_PLAY_SE(ftr_actor)) { - sAdo_OngenPos((u32)ftr_actor, 0x50, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 0x50, &ftr_actor->position); if (ftr_actor->dynamic_work_s[2] < 0) { pos = ftr_actor->position; diff --git a/src/furniture/ac_nog_sprinkler.c b/src/furniture/ac_nog_sprinkler.c index ea3a9090..0c6b560d 100644 --- a/src/furniture/ac_nog_sprinkler.c +++ b/src/furniture/ac_nog_sprinkler.c @@ -27,7 +27,7 @@ static void fNS_mv(FTR_ACTOR* ftr_actor, ACTOR* my_room_actor, GAME* game, u8* d if (aFTR_CAN_PLAY_SE(ftr_actor)) { if (ftr_actor->dynamic_work_s[0] == TRUE) { - sAdo_OngenPos((u32)ftr_actor, 0x5B, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 0x5B, &ftr_actor->position); } } diff --git a/src/furniture/ac_sugi_barbecue.c b/src/furniture/ac_sugi_barbecue.c index 34a14ea2..39a32a78 100644 --- a/src/furniture/ac_sugi_barbecue.c +++ b/src/furniture/ac_sugi_barbecue.c @@ -7,7 +7,7 @@ static void gSBBQ_mv(FTR_ACTOR* ftr_actor, ACTOR* my_room_actor, GAME* game, u8* if (aFTR_CAN_PLAY_SE(ftr_actor)) { u32 ctr = play->game_frame; - sAdo_OngenPos((u32)ftr_actor, 0x55, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 0x55, &ftr_actor->position); if ((ctr & 15) == 0) { xyz_t pos = ftr_actor->position; diff --git a/src/furniture/ac_sugi_torch.c b/src/furniture/ac_sugi_torch.c index 82f55f84..e2e87a3f 100644 --- a/src/furniture/ac_sugi_torch.c +++ b/src/furniture/ac_sugi_torch.c @@ -16,7 +16,7 @@ static void fSGT_mv(FTR_ACTOR* ftr_actor, ACTOR* my_room_actor, GAME* game, u8* cKF_SkeletonInfo_R_play(keyframe); keyframe->frame_control.speed = 0.5f; - sAdo_OngenPos((u32)ftr_actor, 0x57, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 0x57, &ftr_actor->position); } extern Gfx sugi_fireto_model[]; diff --git a/src/furniture/ac_sum_fruittv01.c b/src/furniture/ac_sum_fruittv01.c index cc936533..4bb8af39 100644 --- a/src/furniture/ac_sum_fruittv01.c +++ b/src/furniture/ac_sum_fruittv01.c @@ -5,7 +5,7 @@ static void aSumFruittv01_ct(FTR_ACTOR* ftr_actor, u8* data) { static void aSumFruittv01_mv(FTR_ACTOR* ftr_actor, ACTOR* my_room_actor, GAME* game, u8* data) { if (ftr_actor->switch_bit) { if (aFTR_CAN_PLAY_SE(ftr_actor)) { - sAdo_OngenPos((u32)ftr_actor, 6, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 6, &ftr_actor->position); } ftr_actor->tex_animation.frame++; diff --git a/src/furniture/ac_sum_kisha.c b/src/furniture/ac_sum_kisha.c index 1c6cb08c..addbac30 100644 --- a/src/furniture/ac_sum_kisha.c +++ b/src/furniture/ac_sum_kisha.c @@ -46,7 +46,7 @@ static void aSumKisha_mv(FTR_ACTOR* ftr_actor, ACTOR* my_room_actor, GAME* game, add_calc(&ftr_actor->dynamic_work_f[0], 0.5f, 1.0f - sqrtf(0.95), 0.25f, 0.0005f); if (aFTR_CAN_PLAY_SE(ftr_actor)) { - sAdo_OngenPos((u32)ftr_actor, 3, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 3, &ftr_actor->position); } } else { diff --git a/src/furniture/ac_sum_slot.c b/src/furniture/ac_sum_slot.c index 1b822d8e..29477a37 100644 --- a/src/furniture/ac_sum_slot.c +++ b/src/furniture/ac_sum_slot.c @@ -25,7 +25,7 @@ static void aSumSlot_mv(FTR_ACTOR* ftr_actor, ACTOR* my_room_actor, GAME* game, } if (aFTR_CAN_PLAY_SE(ftr_actor)) { - sAdo_OngenPos((u32)ftr_actor, 2, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 2, &ftr_actor->position); } } else { ftr_actor->dynamic_work_s[0] = FALSE; diff --git a/src/furniture/ac_sum_tv01.c b/src/furniture/ac_sum_tv01.c index cdc750de..200cfedf 100644 --- a/src/furniture/ac_sum_tv01.c +++ b/src/furniture/ac_sum_tv01.c @@ -9,7 +9,7 @@ static void fST01_ct(FTR_ACTOR* ftr_actor, u8* data) { static void fST01_mv(FTR_ACTOR* ftr_actor, ACTOR* my_room_actor, GAME* game, u8* data) { if (ftr_actor->switch_bit) { if (aFTR_CAN_PLAY_SE(ftr_actor)) { - sAdo_OngenPos((u32)ftr_actor, 5, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 5, &ftr_actor->position); } } @@ -107,7 +107,7 @@ static void aSumTv01_ct(FTR_ACTOR* ftr_actor, u8* data) { static void aSumTv01_mv(FTR_ACTOR* ftr_actor, ACTOR* my_room_actor, GAME* game, u8* data) { if (ftr_actor->switch_bit) { if (aFTR_CAN_PLAY_SE(ftr_actor)) { - sAdo_OngenPos((u32)ftr_actor, 5, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 5, &ftr_actor->position); } ftr_actor->tex_animation.frame++; diff --git a/src/furniture/ac_sum_tv02.c b/src/furniture/ac_sum_tv02.c index c5a46663..93664971 100644 --- a/src/furniture/ac_sum_tv02.c +++ b/src/furniture/ac_sum_tv02.c @@ -9,7 +9,7 @@ static void fST02_ct(FTR_ACTOR* ftr_actor, u8* data) { static void fST02_mv(FTR_ACTOR* ftr_actor, ACTOR* my_room_actor, GAME* game, u8* data) { if (ftr_actor->switch_bit) { if (aFTR_CAN_PLAY_SE(ftr_actor)) { - sAdo_OngenPos((u32)ftr_actor, 4, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 4, &ftr_actor->position); } } @@ -99,7 +99,7 @@ static void fST02_ct(FTR_ACTOR* ftr_actor, u8* data) { static void fST02_mv(FTR_ACTOR* ftr_actor, ACTOR* my_room_actor, GAME* game, u8* data) { if (ftr_actor->switch_bit) { if (aFTR_CAN_PLAY_SE(ftr_actor)) { - sAdo_OngenPos((u32)ftr_actor, 4, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 4, &ftr_actor->position); } ftr_actor->tex_animation.frame++; diff --git a/src/furniture/ac_tak_ham1.c b/src/furniture/ac_tak_ham1.c index c0886ba1..fa9f8a2d 100644 --- a/src/furniture/ac_tak_ham1.c +++ b/src/furniture/ac_tak_ham1.c @@ -14,7 +14,7 @@ static void fTHM1_mv(FTR_ACTOR* ftr_actor, ACTOR* my_room_actor, GAME* game, u8* keyframe->frame_control.speed = 1.0f; cKF_SkeletonInfo_R_play(keyframe); - sAdo_OngenPos((u32)ftr_actor, 0x56, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 0x56, &ftr_actor->position); } extern u8 int_tak_ham1_a1_tex_txt[]; diff --git a/src/furniture/ac_tak_ice.c b/src/furniture/ac_tak_ice.c index e67d10ea..437614b0 100644 --- a/src/furniture/ac_tak_ice.c +++ b/src/furniture/ac_tak_ice.c @@ -48,7 +48,7 @@ static void fTIC_mv(FTR_ACTOR* ftr_actor, ACTOR* my_room_actor, GAME* game, u8* } if (ftr_actor->dynamic_work_f[0] >= 0.01f && ftr_actor->switch_bit == TRUE) { - sAdo_OngenPos((u32)ftr_actor, 0x51, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 0x51, &ftr_actor->position); } } } diff --git a/src/furniture/ac_tak_lion.c b/src/furniture/ac_tak_lion.c index 4596e0b7..b8a4a212 100644 --- a/src/furniture/ac_tak_lion.c +++ b/src/furniture/ac_tak_lion.c @@ -27,7 +27,7 @@ static void fTL_mv(FTR_ACTOR* ftr_actor, ACTOR* my_room_actor, GAME* game, u8* d if (ftr_actor->dynamic_work_s[0] == 1) { if (aFTR_CAN_PLAY_SE(ftr_actor)) { - sAdo_OngenPos((u32)ftr_actor, 0x4A, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 0x4A, &ftr_actor->position); } } diff --git a/src/furniture/ac_tak_stew.c b/src/furniture/ac_tak_stew.c index 74097d7a..23df89c8 100644 --- a/src/furniture/ac_tak_stew.c +++ b/src/furniture/ac_tak_stew.c @@ -8,7 +8,7 @@ static void fTSW_mv(FTR_ACTOR* ftr_actor, ACTOR* my_room_actor, GAME* game, u8* if (aFTR_CAN_PLAY_SE(ftr_actor)) { u32 frame = play->game_frame; - sAdo_OngenPos((u32)ftr_actor, 0x54, &ftr_actor->position); + sAdo_OngenPos((uintptr_t)ftr_actor, 0x54, &ftr_actor->position); if ((frame & 7) == 0) { xyz_t effect_pos = ftr_actor->position; diff --git a/src/game.c b/src/game.c index cd22e819..56638014 100644 --- a/src/game.c +++ b/src/game.c @@ -23,6 +23,11 @@ extern int g_pc_model_viewer; #include "GBA/gba.h" #include "m_vibctl.h" +/* On x86/x86_64, SDL2 pulls in , + * which defines errno as a function-like macro. This conflicts with the + * pad_t struct member named errno. Undefine it after all headers. */ +#undef errno + GAME* gamePT = NULL; static u16 last_button[MAXCONTROLLERS]; @@ -155,9 +160,9 @@ extern void game_main(GAME* this) { pc_crash_set_jmpbuf(&game_exec_jmpbuf); if (setjmp(game_exec_jmpbuf) != 0) { /* Recovered from crash in game exec */ - printf("[PC] CRASH in game exec! doing_point=%d specific=0x%02X addr=0x%08X data=0x%08X\n", + printf("[PC] CRASH in game exec! doing_point=%d specific=0x%02X addr=%p data=%p\n", this->doing_point, this->doing_point_specific, - pc_crash_get_addr(), pc_crash_get_data_addr()); + (void*)pc_crash_get_addr(), (void*)pc_crash_get_data_addr()); } else { this->exec(this); } diff --git a/src/game/m_actor.c b/src/game/m_actor.c index 8649cb9a..45e265f6 100644 --- a/src/game/m_actor.c +++ b/src/game/m_actor.c @@ -274,20 +274,21 @@ extern int Actor_draw_actor_no_culling_check(ACTOR* actor) { } extern int Actor_draw_actor_no_culling_check2(ACTOR* actor, xyz_t* camera_pos, f32 camera_w) { +#ifdef TARGET_PC + /* PC port: the GC projection matrix produced clip-space values in a range the + * original culling thresholds were tuned for. The PC/OpenGL projection produces + * values in a different range, causing false-negative culling. Disable software + * frustum culling on PC — the GPU clips out-of-frustum geometry anyway. + * TODO: properly recalibrate the clip-space thresholds for the PC projection. */ + (void)camera_pos; + (void)camera_w; + return TRUE; +#else int res = FALSE; if (-actor->cull_radius < camera_pos->z && camera_pos->z < actor->cull_distance + actor->cull_radius) { f32 m = camera_w < 1.0f ? 1.0f : 1.0f / camera_w; -#ifdef PC_ENHANCEMENTS - /* Widescreen hor+ widens the rendered frustum. The projection matrix - * used to compute camera_pos is the original 4:3 one, so the NDC X - * edge (1.0) is too narrow. Extend by the aspect ratio correction. */ - f32 x_edge = (f32)g_pc_window_w / (f32)g_pc_window_h - / ((f32)PC_GC_WIDTH / (f32)PC_GC_HEIGHT); - if (x_edge < 1.0f) x_edge = 1.0f; -#else f32 x_edge = 1.0f; -#endif int width_OK = (m * (fabsf(camera_pos->x) - actor->cull_width)) < x_edge; if (width_OK && @@ -297,6 +298,7 @@ extern int Actor_draw_actor_no_culling_check2(ACTOR* actor, xyz_t* camera_pos, f } return res; +#endif } static void Actor_cull_check(ACTOR* actor) { diff --git a/src/game/m_card.c b/src/game/m_card.c index b4d445ee..2353056b 100644 --- a/src/game/m_card.c +++ b/src/game/m_card.c @@ -625,7 +625,7 @@ static int mCD_write_comp_bg_read(mCD_bg_info_c* bg_info, s32 chan, s32* result, bg_info->length = mCD_MEMCARD_SECTORSIZE; } - bg_info->data = (void*)((u32)data + ofs); + bg_info->data = (void*)((uintptr_t)data + ofs); bzero(*read_p, mCD_MEMCARD_SECTORSIZE); *result = CARDReadAsync(&bg_info->fileInfo, *read_p, bg_info->length, bg_info->offset, NULL); if (*result == CARD_RESULT_READY) { @@ -666,7 +666,7 @@ static int mCD_write_comp_bg_write(mCD_bg_info_c* bg_info, s32 chan, s32* result } else { bg_info->length = mCD_MEMCARD_SECTORSIZE; } - bg_info->data = (void*)((u32)data + ofs); + bg_info->data = (void*)((uintptr_t)data + ofs); bzero(*read_p, mCD_MEMCARD_SECTORSIZE); *result = CARDReadAsync(&bg_info->fileInfo, *read_p, bg_info->length, bg_info->offset, NULL); @@ -825,7 +825,7 @@ static int mCD_read_fg(void* buf, const char* filename, s32 length, s32 offset, void* workArea; int res = mCD_RESULT_ERROR; - if (buf != NULL && IS_ALIGNED((u32)buf, 32)) { + if (buf != NULL && IS_ALIGNED((uintptr_t)buf, 32)) { int card_res = mCD_check_card(result, mCD_MEMCARD_SECTORSIZE, chan); if (card_res == mCD_RESULT_SUCCESS) { diff --git a/src/game/m_catalog_ovl.c b/src/game/m_catalog_ovl.c index 07cec004..778cb610 100644 --- a/src/game/m_catalog_ovl.c +++ b/src/game/m_catalog_ovl.c @@ -1417,7 +1417,7 @@ extern void mCL_catalog_ovl_construct(Submenu* submenu) { seg0_p += 0x2000; overlay->catalog_ovl->item_data[i].seg1 = - (u8*)ALIGN_NEXT((u32)overlay->catalog_ovl->item_data[i].segment_data, 32); + (u8*)ALIGN_NEXT((uintptr_t)overlay->catalog_ovl->item_data[i].segment_data, 32); } submenu->next_overlay_address = (char*)seg0_p; diff --git a/src/game/m_event.c b/src/game/m_event.c index 657072da..331d4f61 100644 --- a/src/game/m_event.c +++ b/src/game/m_event.c @@ -88,6 +88,7 @@ extern void mEv_ClearEventInfo() { Common_Get(event_flags[1]) = event_save->flags; Common_Get(event_common).fieldday_event_id = -1; Common_Get(event_common).fieldday_event_over_status = -1; + } extern void mEv_EventON(u32 event_kind) { diff --git a/src/game/m_field_make.c b/src/game/m_field_make.c index e5a067bc..3e04d2c9 100644 --- a/src/game/m_field_make.c +++ b/src/game/m_field_make.c @@ -867,8 +867,7 @@ static mFM_fdinfo_c* mFM_MakeField(u16 scene, u16 bg_max, u8 bg_num) { for (i = 0; i < field_info->bg_num; i++) { field_info->bg_display_list_p[i] = (u8*)zelda_malloc(field_info->bg_max); - field_info->bg_display_list_p[i] = (u8*)((u32)(field_info->bg_display_list_p[i]) + (16 - 1)); - field_info->bg_display_list_p[i] = (u8*)((u32)(field_info->bg_display_list_p[i]) & (~(16 - 1))); + field_info->bg_display_list_p[i] = (u8*)(((uintptr_t)(field_info->bg_display_list_p[i]) + (16 - 1)) & ~(uintptr_t)(16 - 1)); } mFM_set_pal_p(&field_info->field_palette); @@ -1477,10 +1476,10 @@ extern void mFM_InitFgCombiSaveData(GAME* game) { // Aus version added NULL check #if VERSION >= VER_GAFU01_00 if (gamealloc_data_p != NULL) { - fg_data_p = (mFM_fg_data_c*)(ALIGN_NEXT((u32)gamealloc_data_p, 32)); + fg_data_p = (mFM_fg_data_c*)(ALIGN_NEXT((uintptr_t)gamealloc_data_p, 32)); } #else - fg_data_p = (mFM_fg_data_c*)(ALIGN_NEXT((u32)gamealloc_data_p, 32)); + fg_data_p = (mFM_fg_data_c*)(ALIGN_NEXT((uintptr_t)gamealloc_data_p, 32)); #endif } else { fg_data_p = (mFM_fg_data_c*)zelda_malloc_align(fg_datasize_align, 32); @@ -1818,7 +1817,7 @@ extern void mFM_SetIslandNpcRoomData(GAME* game, int malloc_flag) { fgnpc_data_p = (mFM_fg_data_c*)zelda_malloc_align(fgnpc_size_align, 32); } else if (game != NULL) { gamealloc_data_p = gamealloc_malloc(gamealloc, fgnpc_size_align + 32); - fgnpc_data_p = (mFM_fg_data_c*)(ALIGN_NEXT((u32)gamealloc_data_p, 32)); + fgnpc_data_p = (mFM_fg_data_c*)(ALIGN_NEXT((uintptr_t)gamealloc_data_p, 32)); } else { fgnpc_data_p = (mFM_fg_data_c*)zelda_malloc_align(fgnpc_size_align, 32); } diff --git a/src/game/m_font_main.c_inc b/src/game/m_font_main.c_inc index 1bde1bf9..dc790b51 100644 --- a/src/game/m_font_main.c_inc +++ b/src/game/m_font_main.c_inc @@ -349,16 +349,16 @@ static void mFont_SetVertex_dol(Vtx* vtx, int x, int y, int s, int t) { vtx->v.ob[0] = x; vtx->v.ob[1] = y; vtx->v.ob[2] = 0; - + vtx->v.flag = 1; - + vtx->v.tc[0] = s; vtx->v.tc[1] = t; vtx->v.cn[0] = 0; vtx->v.cn[1] = 0; vtx->v.cn[2] = 0; - vtx->v.cn[3] = 0; + vtx->v.cn[3] = 255; } // TEMP @@ -515,7 +515,14 @@ static f32 mFont_SetLineStrings_AndSpace_new( gfx = NOW_FONT_DISP; } - flag = mFont_SENTENCE_FLAG_USE_POLY; + flag = 0; + /* On PC, the poly glyph path has rendering issues on POLY_OPA_DISP. + * Use poly mode only for FONT_DISP callers (NPC names, choices) where + * the window's modelview matrix is needed for correct positioning. + * POLY_OPA callers (editor keyboard) use rect mode with absolute coords. */ + if (mode == mFont_MODE_FONT) { + flag |= mFont_SENTENCE_FLAG_USE_POLY; + } if (flag_revert) { flag |= mFont_SENTENCE_FLAG_REVERT; } @@ -818,29 +825,35 @@ static void mFontChar_set( } static void mFontChar_gppDrawRect(mFontChar* this, GRAPH* graph, Gfx** gfx_pp) { - u32 ulx, uly, lrx, lry; + int ulx_i, uly_i, lrx_i, lry_i; int dsdx, dtdy; f32 t; f32 width; - + u8 c = *this->char_p; t = -this->ofs_y; - uly = (int)((t * this->scaled_size.y - t + this->position.y) * 4.0f); - + uly_i = (int)((t * this->scaled_size.y - t + this->position.y) * 4.0f); + t = mFont_TEX_CHAR_HEIGHT_F32 - this->ofs_y; - lry = (int)((t * this->scaled_size.y - t + this->position.y + mFont_TEX_CHAR_HEIGHT_F32) * 4.0f); - - ulx = (int)(this->position.x * 4.0f); - - width = (f32)mFont_GetCodeWidth(*this->char_p, this->flags & mFont_CHAR_FLAG_CUT) * this->scaled_size.x; - - lrx = (int)((width + this->position.x) * 4.0f); - + lry_i = (int)((t * this->scaled_size.y - t + this->position.y + mFont_TEX_CHAR_HEIGHT_F32) * 4.0f); + + ulx_i = (int)(this->position.x * 4.0f); + + width = (f32)mFont_GetCodeWidth(c, this->flags & mFont_CHAR_FLAG_CUT) * this->scaled_size.x; + + lrx_i = (int)((width + this->position.x) * 4.0f); + dsdx = (1024.0f * this->inv_scaled_size.x); /* 1 << 10 for correct s5.10 format? */ dtdy = (1024.0f * this->inv_scaled_size.y); /* 1 << 10 for correct s5.10 format? */ - + this->width = width; - - mFont_gppDrawCharRect(graph, gfx_pp, *this->char_p, ulx, uly, lrx, lry, dsdx, dtdy); + + /* Skip rendering if the rect is fully offscreen (negative coordinates + would wrap when stored in unsigned GBI bitfields, causing artifacts) */ + if (lrx_i <= 0 || lry_i <= 0) return; + if (ulx_i < 0) ulx_i = 0; + if (uly_i < 0) uly_i = 0; + + mFont_gppDrawCharRect(graph, gfx_pp, c, (u32)ulx_i, (u32)uly_i, (u32)lrx_i, (u32)lry_i, dsdx, dtdy); } static void mFontChar_gppDrawPoly(mFontChar* this, GRAPH* graph, Gfx** gfx_pp) { diff --git a/src/game/m_mail.c b/src/game/m_mail.c index defe8316..543258f9 100644 --- a/src/game/m_mail.c +++ b/src/game/m_mail.c @@ -16,13 +16,13 @@ static u8 footer[MAIL_FOOTER2_LEN]; static u8 header[MAIL_HEADER2_LEN]; extern int mMl_strlen(u8* str, int size, u8 end_char) { - u32 end_p = size + (u32)str; + u8* end_p = str + size; int i; end_p--; for (size; size != 0; size--) { - if (*(u8*)end_p != end_char) { + if (*end_p != end_char) { return size; } diff --git a/src/game/m_play.c b/src/game/m_play.c index 513746e4..5054e014 100644 --- a/src/game/m_play.c +++ b/src/game/m_play.c @@ -409,9 +409,9 @@ extern void play_init(GAME* game) { int type; fbdemo_fade* fade; int freebytes; - u32 alloc; - u32 aligned; - u32 size; + uintptr_t alloc; + uintptr_t aligned; + uintptr_t size; game_resize_hyral(game, -Game_play_HYRAL_SIZE); // reserve bytes from gamealloc Common_Set(rhythym_updated, 0); @@ -475,7 +475,7 @@ extern void play_init(GAME* game) { play->fade_color_value.rgba8888 = 0; freebytes = game_getFreeBytes(game); - alloc = (u32)THA_alloc16(&game->tha, freebytes); + alloc = (uintptr_t)THA_alloc16(&game->tha, freebytes); aligned = ALIGN_NEXT(alloc, 16); size = aligned - alloc; diff --git a/src/game/m_player.c b/src/game/m_player.c index 7e30669b..33bab4cb 100644 --- a/src/game/m_player.c +++ b/src/game/m_player.c @@ -255,9 +255,9 @@ static int Player_actor_request_main_demo_get_golden_item2_all(GAME*, int, int); static int Player_actor_request_main_demo_get_golden_axe_wait_all(GAME*, int); static int Player_actor_check_request_main_priority(GAME*, int); static void* Player_actor_get_door_label(GAME*); -static int Player_actor_Set_Item_net_catch_request_table(ACTOR*, GAME*, u32, s8, const xyz_t*, f32); +static int Player_actor_Set_Item_net_catch_request_table(ACTOR*, GAME*, uintptr_t, s8, const xyz_t*, f32); static f32 Player_actor_Get_Item_net_catch_swing_timer(ACTOR*, GAME*); -static int Player_actor_Set_Item_net_catch_request_force(ACTOR*, GAME*, u32, s8); +static int Player_actor_Set_Item_net_catch_request_force(ACTOR*, GAME*, uintptr_t, s8); static void Player_actor_Set_force_position_angle(GAME*, const xyz_t*, const s_xyz*, u8); static u8 Player_actor_Get_force_position_angle(GAME*, xyz_t*, s_xyz*); static int Player_actor_Get_WadeEndPos(GAME*, xyz_t*); @@ -267,8 +267,8 @@ static int Player_actor_able_submenu_request_main_index(GAME*); static int Player_actor_check_able_change_camera_normal_index(ACTOR*); static int Player_actor_Check_able_force_speak_label(GAME*, void*); static int Player_actor_check_cancel_request_change_proc_index(int); -static u32 Player_actor_Get_item_net_catch_label(ACTOR*); -static int Player_actor_Change_item_net_catch_label(ACTOR*, u32, s8); +static uintptr_t Player_actor_Get_item_net_catch_label(ACTOR*); +static int Player_actor_Change_item_net_catch_label(ACTOR*, uintptr_t, s8); static int Player_actor_Check_StopNet(ACTOR*, xyz_t*); static int Player_actor_Check_HitAxe(ACTOR*, xyz_t*); static int Player_actor_Check_VibUnit_OneFrame(ACTOR*, const xyz_t*); diff --git a/src/game/m_player_common.c_inc b/src/game/m_player_common.c_inc index 44376ded..65ebe0e2 100644 --- a/src/game/m_player_common.c_inc +++ b/src/game/m_player_common.c_inc @@ -2462,7 +2462,7 @@ static void Player_actor_Reset_Item_net_catch_request_table(ACTOR* actorx) { player->item_net_catch_label_request_force = 0; } -static int Player_actor_Set_Item_net_catch_request_table(ACTOR* actorx, GAME* game, u32 label, s8 type, +static int Player_actor_Set_Item_net_catch_request_table(ACTOR* actorx, GAME* game, uintptr_t label, s8 type, const xyz_t* pos_p, f32 radius) { PLAYER_ACTOR* player = (PLAYER_ACTOR*)actorx; @@ -2483,7 +2483,7 @@ static int Player_actor_Set_Item_net_catch_request_table(ACTOR* actorx, GAME* ga return FALSE; } -static int Player_actor_Set_Item_net_catch_request_force(ACTOR* actorx, GAME* game, u32 label, s8 type) { +static int Player_actor_Set_Item_net_catch_request_force(ACTOR* actorx, GAME* game, uintptr_t label, s8 type) { PLAYER_ACTOR* player = (PLAYER_ACTOR*)actorx; if (mPlib_get_player_actor_main_index(game) == mPlayer_INDEX_SWING_NET && @@ -4491,7 +4491,7 @@ static void Player_actor_cancel_request_change_proc_index_by_A_btn(ACTOR* actorx } } -static u32 Player_actor_Get_item_net_catch_label(ACTOR* actorx) { +static uintptr_t Player_actor_Get_item_net_catch_label(ACTOR* actorx) { PLAYER_ACTOR* player = (PLAYER_ACTOR*)actorx; switch (player->now_main_index) { @@ -4505,7 +4505,7 @@ static u32 Player_actor_Get_item_net_catch_label(ACTOR* actorx) { } } -static int Player_actor_Change_item_net_catch_label(ACTOR* actorx, u32 label, s8 insect_type) { +static int Player_actor_Change_item_net_catch_label(ACTOR* actorx, uintptr_t label, s8 insect_type) { PLAYER_ACTOR* player = (PLAYER_ACTOR*)actorx; aINS_INSECT_ACTOR* insect_actor = (aINS_INSECT_ACTOR*)label; @@ -7022,7 +7022,7 @@ static void Player_actor_Set_bgm_volume(ACTOR* actorx, int main_index) { static int Player_actor_Check_Label_main_push_snowball(GAME* game, void* label) { PLAYER_ACTOR* player = GET_PLAYER_ACTOR_GAME(game); - if (player->now_main_index == mPlayer_INDEX_PUSH_SNOWBALL && player->main_data.push_snowball.label == (u32)label) { + if (player->now_main_index == mPlayer_INDEX_PUSH_SNOWBALL && player->main_data.push_snowball.label == (uintptr_t)label) { return TRUE; } @@ -7033,7 +7033,7 @@ static int Player_actor_Check_Label_main_wade_snowball(GAME* game, void* label) PLAYER_ACTOR* player = GET_PLAYER_ACTOR_GAME(game); if (player->now_main_index == mPlayer_INDEX_WADE_SNOWBALL && - player->main_data.wade_snowball.snowball_label == (u32)label) { + player->main_data.wade_snowball.snowball_label == (uintptr_t)label) { return TRUE; } @@ -7772,13 +7772,13 @@ static int Player_actor_check_cancel_event_without_priority(GAME* game) { static int Player_actor_Check_able_force_speak_label(GAME* game, void* label) { PLAYER_ACTOR* player = GET_PLAYER_ACTOR_GAME(game); - u32 able_force_speak_label = (u32)player->able_force_speak_label; + uintptr_t able_force_speak_label = (uintptr_t)player->able_force_speak_label; if (able_force_speak_label == 0) { return TRUE; } - if (able_force_speak_label == (u32)label) { + if (able_force_speak_label == (uintptr_t)label) { return TRUE; } @@ -7818,17 +7818,17 @@ static int Player_actor_Check_stung_mosquito(GAME* game, void* label) { switch (main_index) { case mPlayer_INDEX_STUNG_MOSQUITO: { - u32 stung_label = GET_PLAYER_ACTOR_GAME(game)->requested_main_index_data.stung_mosquito.label; + uintptr_t stung_label = GET_PLAYER_ACTOR_GAME(game)->requested_main_index_data.stung_mosquito.label; - if (stung_label == (u32)label) { + if (stung_label == (uintptr_t)label) { return TRUE; } break; } case mPlayer_INDEX_NOTICE_MOSQUITO: { - u32 notice_label = GET_PLAYER_ACTOR_GAME(game)->requested_main_index_data.notice_mosquito.label; + uintptr_t notice_label = GET_PLAYER_ACTOR_GAME(game)->requested_main_index_data.notice_mosquito.label; - if (notice_label == (u32)label) { + if (notice_label == (uintptr_t)label) { return TRUE; } break; diff --git a/src/game/m_player_lib.c b/src/game/m_player_lib.c index 4386c49a..5ba95628 100644 --- a/src/game/m_player_lib.c +++ b/src/game/m_player_lib.c @@ -1039,7 +1039,7 @@ static int mPlib_Object_Exchange_keep_new(GAME_PLAY* play, s16 bank, u32 src, u3 } if (obj_ex->bank_idx < (mSc_OBJECT_BANK_NUM - 1)) { - obj_ex->next_bank_ram_address = (char*)ALIGN_NEXT((u32)obj_ex->next_bank_ram_address + size, 32); + obj_ex->next_bank_ram_address = (char*)ALIGN_NEXT((uintptr_t)obj_ex->next_bank_ram_address + size, 32); obj_ex->bank_idx++; } @@ -1072,7 +1072,7 @@ extern u32 mPlib_Get_PlayerTexRom_p(int idx) { org_idx = 0; } - return (u32)Now_Private->my_org[org_idx & 7].design.data; + return (uintptr_t)Now_Private->my_org[org_idx & 7].design.data; } } @@ -1102,7 +1102,7 @@ extern u32 mPlib_Get_PlayerPalletRom_p(int idx) { org_idx = 0; } - return (u32)mNW_PaletteIdx2Palette(Now_Private->my_org[org_idx & 7].palette); + return (uintptr_t)mNW_PaletteIdx2Palette(Now_Private->my_org[org_idx & 7].palette); } } @@ -1667,7 +1667,7 @@ extern void mPlib_request_main_demo_wait_from_submenu(ACTOR* speak_actor_p) { change_data_from_submenu_p->requested_index_pending = TRUE; req_demo_wait_p->umbrella_flag = FALSE; - req_demo_wait_p->label = (u32)speak_actor_p; + req_demo_wait_p->label = (uintptr_t)speak_actor_p; if (speak_actor_p != NULL) { mPlib_Set_able_force_speak_label(speak_actor_p); @@ -1692,7 +1692,7 @@ extern int mPlib_Check_able_force_speak_label(GAME* game, ACTOR* label) { extern void mPlib_Set_able_force_speak_label(ACTOR* label) { if (Common_Get(player_actor_exists)) { - GET_PLAYER_ACTOR_NOW()->able_force_speak_label = (u32)label; + GET_PLAYER_ACTOR_NOW()->able_force_speak_label = (uintptr_t)label; } } @@ -2617,7 +2617,7 @@ extern int mPlib_check_label_player_demo_wait(GAME* game, void* label) { if (mPlib_get_player_actor_main_index(game) == mPlayer_INDEX_DEMO_WAIT) { mPlayer_main_demo_wait_c* demo_wait_p = &GET_PLAYER_ACTOR_GAME(game)->main_data.demo_wait; - if (demo_wait_p->label == (u32)label) { + if (demo_wait_p->label == (uintptr_t)label) { return TRUE; } } @@ -2792,11 +2792,11 @@ extern int mPlib_Check_StopNet(xyz_t* pos_p) { return GET_PLAYER_ACTOR_NOW()->Check_StopNet_proc(GET_PLAYER_ACTOR_NOW_ACTOR(), pos_p); } -extern u32 mPlib_Get_item_net_catch_label(void) { +extern uintptr_t mPlib_Get_item_net_catch_label(void) { return GET_PLAYER_ACTOR_NOW()->Get_item_net_catch_label_proc(GET_PLAYER_ACTOR_NOW_ACTOR()); } -extern int mPlib_Change_item_net_catch_label(u32 label, s8 type) { +extern int mPlib_Change_item_net_catch_label(uintptr_t label, s8 type) { return GET_PLAYER_ACTOR_NOW()->Change_item_net_catch_label_proc(GET_PLAYER_ACTOR_NOW_ACTOR(), label, type); } diff --git a/src/game/m_player_main_demo_wait.c_inc b/src/game/m_player_main_demo_wait.c_inc index b71b5397..100c7574 100644 --- a/src/game/m_player_main_demo_wait.c_inc +++ b/src/game/m_player_main_demo_wait.c_inc @@ -4,7 +4,7 @@ static int Player_actor_request_main_demo_wait_all(GAME* game, int umbrella_flag mPlayer_request_demo_wait_c* req_demo_wait_p = &player->requested_main_index_data.demo_wait; req_demo_wait_p->umbrella_flag = umbrella_flag; - req_demo_wait_p->label = (u32)label; + req_demo_wait_p->label = (uintptr_t)label; Player_actor_request_main_index(game, mPlayer_INDEX_DEMO_WAIT, prio); return TRUE; } diff --git a/src/game/m_player_main_door.c_inc b/src/game/m_player_main_door.c_inc index 8221c6ea..bd2127e1 100644 --- a/src/game/m_player_main_door.c_inc +++ b/src/game/m_player_main_door.c_inc @@ -7,7 +7,7 @@ static int Player_actor_request_main_door(GAME* game, const xyz_t* pos, s16 angl player->requested_main_index_data.door.player_pos.y = player->actor_class.world.position.y; player->requested_main_index_data.door.angle_y = angle_y; player->requested_main_index_data.door.type = type; - player->requested_main_index_data.door.label = (u32)label; + player->requested_main_index_data.door.label = (uintptr_t)label; Player_actor_request_main_index(game, mPlayer_INDEX_DOOR, priority); diff --git a/src/game/m_player_main_notice_net.c_inc b/src/game/m_player_main_notice_net.c_inc index bfc0cf5b..a7bcc734 100644 --- a/src/game/m_player_main_notice_net.c_inc +++ b/src/game/m_player_main_notice_net.c_inc @@ -107,7 +107,7 @@ static void Player_actor_settle_main_Notice_net(ACTOR* actor, GAME* game) { } if (!main_notice->not_full_pocket) { - u32 label = player->item_net_catch_label; + uintptr_t label = player->item_net_catch_label; if (label != 0 && player->item_net_catch_type == 0) { ((aINS_INSECT_ACTOR*)label)->patience = 100.0f; @@ -250,7 +250,7 @@ static void Player_actor_request_proc_index_fromNotice_net(ACTOR* actor, GAME* g Player_actor_request_main_putaway_net(game, main_notice->exchange_flag, mPlayer_REQUEST_PRIORITY_28); } else if (msg_control == 0x53) { if (player->item_net_catch_type == 0) { - u32 label = player->item_net_catch_label; + uintptr_t label = player->item_net_catch_label; mPlayer_request_release_creature_u release_data; bzero(&release_data, sizeof(mPlayer_request_release_creature_u)); diff --git a/src/game/m_player_main_pull_net.c_inc b/src/game/m_player_main_pull_net.c_inc index 2eac9d8d..29acd61b 100644 --- a/src/game/m_player_main_pull_net.c_inc +++ b/src/game/m_player_main_pull_net.c_inc @@ -59,7 +59,7 @@ static void Player_actor_CorrectSomething_Pull_net(ACTOR* actor) { xyz_t* pos; if (player->keyframe0.frame_control.current_frame > 15.0f) { - u32 label = player->item_net_catch_label; + uintptr_t label = player->item_net_catch_label; if (label != 0 && player->item_net_catch_type == 0) { ((ACTOR*)label)->drawn = TRUE; @@ -105,7 +105,7 @@ static void Player_actor_Pull_net_demo_ct(ACTOR* actor) { PLAYER_ACTOR* player = (PLAYER_ACTOR*)actor; rgba_t color; mMsg_Window_c* win = mMsg_Get_base_window_p(); - u32 label = player->item_net_catch_label; + uintptr_t label = player->item_net_catch_label; s8 type = player->item_net_catch_type; int msg_no = 0xA2C; diff --git a/src/game/m_player_main_push_snowball.c_inc b/src/game/m_player_main_push_snowball.c_inc index 70428d67..5c2fdf72 100644 --- a/src/game/m_player_main_push_snowball.c_inc +++ b/src/game/m_player_main_push_snowball.c_inc @@ -11,13 +11,13 @@ static int Player_actor_request_main_push_snowball_all(GAME* game, void* label, mPlayer_main_wade_snowball_c* wade_snowball_p = &player->main_data.wade_snowball; /* When wading between acres, check the snowball label is the same as the one pushed */ - if (wade_snowball_p->snowball_label != (u32)label) { + if (wade_snowball_p->snowball_label != (uintptr_t)label) { return FALSE; } } if (Player_actor_check_request_main_able(game, mPlayer_INDEX_PUSH_SNOWBALL, prio)) { - req_push_snowball_p->label = (u32)label; + req_push_snowball_p->label = (uintptr_t)label; req_push_snowball_p->wade_flag = wade_flag; Player_actor_request_main_index(game, mPlayer_INDEX_PUSH_SNOWBALL, prio); diff --git a/src/game/m_player_main_putaway_net.c_inc b/src/game/m_player_main_putaway_net.c_inc index ac8f5dc7..54aff7ac 100644 --- a/src/game/m_player_main_putaway_net.c_inc +++ b/src/game/m_player_main_putaway_net.c_inc @@ -38,7 +38,7 @@ static int Player_actor_CulcAnimation_Putaway_net(ACTOR* actor, f32* frame_calc) static void Player_actor_CorrectSomething_Putaway_net(ACTOR* actor, GAME* game) { PLAYER_ACTOR* player = (PLAYER_ACTOR*)actor; - u32 label = player->item_net_catch_label; + uintptr_t label = player->item_net_catch_label; if (label != 0) { cKF_FrameControl_c* fc = &player->keyframe0.frame_control; diff --git a/src/game/m_player_main_stung_mosquito.c_inc b/src/game/m_player_main_stung_mosquito.c_inc index 7291ff87..567271f8 100644 --- a/src/game/m_player_main_stung_mosquito.c_inc +++ b/src/game/m_player_main_stung_mosquito.c_inc @@ -28,7 +28,7 @@ static int Player_actor_request_main_stung_mosquito_all(GAME* game, void* label, if (Player_actor_check_request_main_able(game, mPlayer_INDEX_STUNG_MOSQUITO, prio)) { mPlayer_request_stung_mosquito_c* req_stung_mosquito_p = &player->requested_main_index_data.stung_mosquito; - req_stung_mosquito_p->label = (u32)label; + req_stung_mosquito_p->label = (uintptr_t)label; Player_actor_request_main_index(game, mPlayer_INDEX_STUNG_MOSQUITO, prio); return TRUE; } diff --git a/src/game/m_player_main_swing_net.c_inc b/src/game/m_player_main_swing_net.c_inc index 2935f4af..4698d646 100644 --- a/src/game/m_player_main_swing_net.c_inc +++ b/src/game/m_player_main_swing_net.c_inc @@ -242,7 +242,7 @@ static int Player_actor_CatchSomethingCheck_common(ACTOR* actor, f32 frame) { mPlayer_main_swing_net_c* main_swing = &player->main_data.swing_net; u32 label; s8 type; - u32 pl_label = player->item_net_catch_label; + uintptr_t pl_label = player->item_net_catch_label; main_swing->swing_timer += 0.5f; @@ -281,7 +281,7 @@ static int Player_actor_CatchSomethingCheck_Swing_net(ACTOR* actor) { static void Player_actor_CorrectSomething_Swing_net(ACTOR* actor) { PLAYER_ACTOR* player = (PLAYER_ACTOR*)actor; xyz_t* pos = &player->net_pos; - u32 label = player->item_net_catch_label; + uintptr_t label = player->item_net_catch_label; if (label != 0 && player->item_net_catch_type == 0) { ((ACTOR*)label)->drawn = FALSE; diff --git a/src/game/m_player_sound.c_inc b/src/game/m_player_sound.c_inc index 96c9fddf..adbe8d0a 100644 --- a/src/game/m_player_sound.c_inc +++ b/src/game/m_player_sound.c_inc @@ -333,6 +333,6 @@ static void Player_actor_sound_move_temochi_kazaguruma(ACTOR* actor) { } if (speed != 0.0f) { sAdo_kazagurumaLevel(speed); - sAdo_OngenPos((u32)player, NA_SE_TEMOCHI_KAZAGURUMA, &actor->world.position); + sAdo_OngenPos((uintptr_t)player, NA_SE_TEMOCHI_KAZAGURUMA, &actor->world.position); } } diff --git a/src/game/m_scene.c b/src/game/m_scene.c index 916a3dd8..91748451 100644 --- a/src/game/m_scene.c +++ b/src/game/m_scene.c @@ -40,7 +40,7 @@ extern char* mSc_secure_exchange_keep_bank(Object_Exchange_c* exchange, s16 bank Object_Bank_c* bank = exchange->banks + exchange->bank_idx; if (exchange->bank_idx < mSc_OBJECT_BANK_NUM) { - area = (char*)ALIGN_NEXT((u32)exchange->next_bank_ram_address + size, 32); + area = (char*)ALIGN_NEXT((uintptr_t)exchange->next_bank_ram_address + size, 32); if (area >= exchange->max_ram_address) { area = NULL; @@ -111,10 +111,10 @@ extern void mSc_regist_initial_exchange_bank(GAME_PLAY* play) { u32 size; /* Split the remaining object exchange space into two equal portions */ - size = (u32)(play->object_exchange.max_ram_address - play->object_exchange.next_bank_ram_address) / 2; + size = (size_t)(play->object_exchange.max_ram_address - play->object_exchange.next_bank_ram_address) / 2; play->object_exchange.start_address_save[0] = play->object_exchange.next_bank_ram_address; play->object_exchange.end_address_save[0] = - (char*)ALIGN_NEXT((u32)play->object_exchange.next_bank_ram_address + size, 32); + (char*)ALIGN_NEXT((uintptr_t)play->object_exchange.next_bank_ram_address + size, 32); play->object_exchange.start_address_save[1] = play->object_exchange.end_address_save[0]; play->object_exchange.end_address_save[1] = play->object_exchange.max_ram_address; @@ -134,14 +134,14 @@ extern void mSc_regist_initial_exchange_bank(GAME_PLAY* play) { static void mSc_dmacopy_all_exchange_bank_sub(Object_Bank_c* bank, Object_Exchange_c* exchange, int idx) { if (idx >= exchange->exchange_id) { - char* area = (char*)ALIGN_NEXT((u32)exchange->next_bank_ram_address + bank->size, 32); + char* area = (char*)ALIGN_NEXT((uintptr_t)exchange->next_bank_ram_address + bank->size, 32); if (area >= exchange->max_ram_address) { exchange->selected_partition = (exchange->selected_partition + 1) % 2; exchange->next_bank_ram_address = exchange->start_address_save[exchange->selected_partition]; exchange->max_ram_address = exchange->end_address_save[exchange->selected_partition]; - area = (char*)ALIGN_NEXT((u32)exchange->next_bank_ram_address + bank->size, 32); + area = (char*)ALIGN_NEXT((uintptr_t)exchange->next_bank_ram_address + bank->size, 32); } bank->dma_start = exchange->next_bank_ram_address; diff --git a/src/game/m_scene_ftr.c b/src/game/m_scene_ftr.c index e0ab371f..5bf201ff 100644 --- a/src/game/m_scene_ftr.c +++ b/src/game/m_scene_ftr.c @@ -14,7 +14,7 @@ static void mScn_KeepMyRoomBankNew(Object_Exchange_c* exchange, s16 bank_id, siz bank->size = size; if (exchange->bank_idx < (mSc_OBJECT_BANK_NUM - 1)) { - exchange->next_bank_ram_address = (char*)ALIGN_NEXT((u32)exchange->next_bank_ram_address + size, 16); + exchange->next_bank_ram_address = (char*)ALIGN_NEXT((uintptr_t)exchange->next_bank_ram_address + size, 16); exchange->bank_idx++; } } diff --git a/src/game/m_submenu.c b/src/game/m_submenu.c index 429fa6f1..c1dc4a99 100644 --- a/src/game/m_submenu.c +++ b/src/game/m_submenu.c @@ -620,7 +620,7 @@ static char* mSM_Object_Exchange_keep_new(GAME_PLAY* play, s16 bank_id, size_t s bank->size = size; if (exchange->bank_idx < mSc_OBJECT_BANK_NUM - 1) { - exchange->next_bank_ram_address = (char*)ALIGN_NEXT((u32)(exchange->next_bank_ram_address + size), 16); + exchange->next_bank_ram_address = (char*)ALIGN_NEXT((uintptr_t)(exchange->next_bank_ram_address + size), 16); exchange->bank_idx++; } diff --git a/src/game/m_submenu_ovl.c b/src/game/m_submenu_ovl.c index 727b5c19..611e5708 100644 --- a/src/game/m_submenu_ovl.c +++ b/src/game/m_submenu_ovl.c @@ -1974,7 +1974,7 @@ static void mSM_ovl_prog_seg(Submenu* submenu, mSM_Ovl_dlftbl_c* dlftbl) { dlftbl->seg_start = NULL; dlftbl->seg_end = NULL; - submenu->next_overlay_address = (char*)ALIGN_NEXT((u32)dlftbl->seg_end - (u32)dlftbl->seg_start, 64); + submenu->next_overlay_address = (char*)ALIGN_NEXT((uintptr_t)dlftbl->seg_end - (uintptr_t)dlftbl->seg_start, 64); ct_proc = dlftbl->ct_proc; (*ct_proc)(submenu); dlftbl->ct_proc = ct_proc; diff --git a/src/game/m_train_control.c b/src/game/m_train_control.c index e80fe94a..526b127e 100644 --- a/src/game/m_train_control.c +++ b/src/game/m_train_control.c @@ -49,8 +49,8 @@ static void mTRC_KishaStatusLevel(GAME_PLAY* play, f32 speed, xyz_t pos) { xyz_t mic_pos; u16 unsigned_angle; u16 unsigned_angle2; - u32 ongen; - u32 ongen2; + uintptr_t ongen; + uintptr_t ongen2; mTRC_SetMicPos(play, &mic_pos); @@ -68,8 +68,8 @@ static void mTRC_KishaStatusLevel(GAME_PLAY* play, f32 speed, xyz_t pos) { distance2 = sqrtf(SQ(x) + SQ(y) + SQ(z)); unsigned_angle2 = (int)angle; - ongen = (u32)Common_GetPointer(train_coming_flag); - ongen2 = (u32)Common_GetPointer(train_exists_flag); + ongen = (uintptr_t)Common_GetPointer(train_coming_flag); + ongen2 = (uintptr_t)Common_GetPointer(train_exists_flag); sAdos_KishaStatusLevel(speed, ongen, distance, unsigned_angle, ongen2, distance2, unsigned_angle2); } @@ -438,6 +438,7 @@ static void mTRC_trainSet(GAME_PLAY* play) { /* spawn train actor since it doesn't exist */ train_actor = (ACTOR*)Common_Get(clip.structure_clip)->setup_actor_proc(&play->game, TRAIN0, -1, x, 740.0f); + fflush(stdout); /* for whatever reason, train actor didn't spawn, so exit */ if (train_actor == NULL) { diff --git a/src/graph.c b/src/graph.c index 9223fb35..3e46ca40 100644 --- a/src/graph.c +++ b/src/graph.c @@ -147,6 +147,7 @@ static void graph_task_set00(GRAPH* this) { #ifdef TARGET_PC { extern int pc_emu64_frame_cmds, pc_emu64_frame_tri_cmds, pc_emu64_frame_vtx_cmds; + extern int pc_emu64_frame_dl_cmds, pc_emu64_frame_crashes; extern int pc_gx_draw_call_count; PC_DIAG(5, "emu64 stats: cmds=%d tri=%d vtx=%d gl_draws=%d\n", pc_emu64_frame_cmds, pc_emu64_frame_tri_cmds, pc_emu64_frame_vtx_cmds, diff --git a/src/static/JSystem/JFramework/JFWDisplay.cpp b/src/static/JSystem/JFramework/JFWDisplay.cpp index c72fc0e4..41d39bb6 100644 --- a/src/static/JSystem/JFramework/JFWDisplay.cpp +++ b/src/static/JSystem/JFramework/JFWDisplay.cpp @@ -1,4 +1,7 @@ #include +#ifdef TARGET_PC +#include +#endif #include #include "_mem.h" #include "JSystem/J2D/J2DGrafContext.h" diff --git a/src/static/JSystem/JKernel/JKRAram.cpp b/src/static/JSystem/JKernel/JKRAram.cpp index 9f68c3a9..8122cd6b 100644 --- a/src/static/JSystem/JKernel/JKRAram.cpp +++ b/src/static/JSystem/JKernel/JKRAram.cpp @@ -85,7 +85,11 @@ void* JKRAram::run() { } bool JKRAram::checkOkAddress(u8* addr, u32 size, JKRAramBlock* block, u32 blockSize) { +#ifdef TARGET_PC + if (!IS_ALIGNED((uintptr_t)addr, 0x20) && !IS_ALIGNED(size, 0x20)) { +#else if (!IS_ALIGNED((u32)addr, 0x20) && !IS_ALIGNED(size, 0x20)) { +#endif JPANIC(225, ":::address not 32Byte aligned."); return false; } @@ -142,7 +146,11 @@ JKRAramBlock* JKRAram::mainRamToAram(u8* buf, u32 address, u32 alignedSize, JKRE block = nullptr; } else { JKRDecompress(buf, (u8*)allocatedMem, fileSize, 0); +#ifdef TARGET_PC + JKRAramPcs(0, (uintptr_t)allocatedMem, address, alignedSize, block); +#else JKRAramPcs(0, (u32)allocatedMem, address, alignedSize, block); +#endif JKRFreeToHeap(heap, allocatedMem); block = block == nullptr ? (JKRAramBlock*)-1 : block; } @@ -156,7 +164,11 @@ JKRAramBlock* JKRAram::mainRamToAram(u8* buf, u32 address, u32 alignedSize, JKRE address = block->getAddress(); } +#ifdef TARGET_PC + JKRAramPcs(0, (uintptr_t)buf, address, alignedSize, block); +#else JKRAramPcs(0, (u32)buf, address, alignedSize, block); +#endif block = block == nullptr ? (JKRAramBlock*)-1 : block; } return block; @@ -193,9 +205,15 @@ u8* JKRAram::aramToMainRam(u32 address, u8* buf, u32 srcSize, JKRExpandSwitch ex u32 expandSize; if (expandSwitch == EXPAND_SWITCH_DECOMPRESS) { u8 buffer[64]; +#ifdef TARGET_PC + u8* bufPtr = (u8*)ALIGN_NEXT((uintptr_t)buffer, 32); + JKRAramPcs(1, address, (uintptr_t)bufPtr, sizeof(buffer) / 2, + nullptr); // probably change sizeof(buffer) / 2 to 32 +#else u8* bufPtr = (u8*)ALIGN_NEXT((u32)buffer, 32); JKRAramPcs(1, address, (u32)bufPtr, sizeof(buffer) / 2, nullptr); // probably change sizeof(buffer) / 2 to 32 +#endif compression = JKRCheckCompressed(bufPtr); expandSize = JKRDecompExpandSize(bufPtr); } @@ -223,7 +241,11 @@ u8* JKRAram::aramToMainRam(u32 address, u8* buf, u32 srcSize, JKRExpandSwitch ex if (szpSpace == nullptr) { return nullptr; } else { +#ifdef TARGET_PC + JKRAramPcs(1, address, (uintptr_t)szpSpace, srcSize, nullptr); +#else JKRAramPcs(1, address, (u32)szpSpace, srcSize, nullptr); +#endif if (p5 != 0 && p5 < expandSize) expandSize = p5; @@ -250,7 +272,11 @@ u8* JKRAram::aramToMainRam(u32 address, u8* buf, u32 srcSize, JKRExpandSwitch ex return nullptr; } else { changeGroupIdIfNeed(buf, id); +#ifdef TARGET_PC + JKRAramPcs(1, address, (uintptr_t)buf, srcSize, nullptr); +#else JKRAramPcs(1, address, (u32)buf, srcSize, nullptr); +#endif if (pSize != nullptr) { *pSize = srcSize; } @@ -456,7 +482,11 @@ static u8* firstSrcData() { u32 maxSize = (szpEnd - szpBuf); u32 transSize = MIN(transLeft, maxSize); +#ifdef TARGET_PC + JKRAramPcs(1, srcAddress + srcOffset, (uintptr_t)buf, ALIGN_NEXT(transSize, 32), nullptr); +#else JKRAramPcs(1, srcAddress + srcOffset, (u32)buf, ALIGN_NEXT(transSize, 32), nullptr); +#endif srcOffset += transSize; transLeft -= transSize; @@ -466,19 +496,31 @@ static u8* firstSrcData() { u8* nextSrcData(u8* current) { u8* dest; +#ifdef TARGET_PC + u32 left = (uintptr_t)(szpEnd - current); +#else u32 left = (u32)(szpEnd - current); +#endif if (IS_NOT_ALIGNED(left, 0x20)) dest = szpBuf + 0x20 - (left & (0x20 - 1)); else dest = szpBuf; memcpy(dest, current, left); +#ifdef TARGET_PC + u32 transSize = (uintptr_t)(szpEnd - (dest + left)); +#else u32 transSize = (u32)(szpEnd - (dest + left)); +#endif if (transSize > transLeft) transSize = transLeft; JUT_ASSERT(transSize > 0); +#ifdef TARGET_PC + JKRAramPcs(1, (uintptr_t)(srcAddress + srcOffset), ((uintptr_t)dest + left), ALIGN_NEXT(transSize, 0x20), nullptr); +#else JKRAramPcs(1, (u32)(srcAddress + srcOffset), ((u32)dest + left), ALIGN_NEXT(transSize, 0x20), nullptr); +#endif srcOffset += transSize; transLeft -= transSize; diff --git a/src/static/JSystem/JKernel/JKRAramArchive.cpp b/src/static/JSystem/JKernel/JKRAramArchive.cpp index 33f07fed..b4252a21 100644 --- a/src/static/JSystem/JKernel/JKRAramArchive.cpp +++ b/src/static/JSystem/JKernel/JKRAramArchive.cpp @@ -10,6 +10,7 @@ #include "JSystem/JUtility/JUTAssertion.h" #ifdef TARGET_PC +#include #include "pc_bswap.h" #define bswap32 pc_bswap32 #define bswap16 pc_bswap16 @@ -35,8 +36,8 @@ JKRAramArchive::~JKRAramArchive() { if (mArcInfoBlock) { SDIFileEntry* fileEntries = mFileEntries; for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) { - if (fileEntries->mData != nullptr) { - JKRFreeToHeap(mHeap, fileEntries->mData); + if (getFileEntryData(fileEntries) != nullptr) { + JKRFreeToHeap(mHeap, getFileEntryData(fileEntries)); } fileEntries++; } @@ -44,6 +45,13 @@ JKRAramArchive::~JKRAramArchive() { mArcInfoBlock = nullptr; } +#ifdef TARGET_PC + if (mFileEntryDataPtrs) { + free(mFileEntryDataPtrs); + mFileEntryDataPtrs = nullptr; + } +#endif + if (mDvdFile) { delete mDvdFile; } @@ -102,8 +110,8 @@ void JKRAramArchive::unmountFixed() { if (mArcInfoBlock) { SDIFileEntry* fileEntries = mFileEntries; for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) { - if (fileEntries->mData != nullptr) { - JKRFreeToHeap(mHeap, fileEntries->mData); + if (getFileEntryData(fileEntries) != nullptr) { + JKRFreeToHeap(mHeap, getFileEntryData(fileEntries)); } fileEntries++; } @@ -111,6 +119,13 @@ void JKRAramArchive::unmountFixed() { mArcInfoBlock = nullptr; } +#ifdef TARGET_PC + if (mFileEntryDataPtrs) { + free(mFileEntryDataPtrs); + mFileEntryDataPtrs = nullptr; + } +#endif + if (mDvdFile) delete mDvdFile; @@ -125,12 +140,15 @@ void JKRAramArchive::unmountFixed() { CW_FORCE_STRINGS(JKRAramArchive_cpp, __FILE__, "isMounted()", "mMountCount == 1") #endif -bool JKRAramArchive::open(long entryNum) { +bool JKRAramArchive::open(s32 entryNum) { mArcInfoBlock = nullptr; mDirectories = nullptr; mFileEntries = nullptr; mStrTable = nullptr; mBlock = nullptr; +#ifdef TARGET_PC + mFileEntryDataPtrs = nullptr; +#endif mDvdFile = new (JKRGetSystemHeap(), mMountDirection == MOUNT_DIRECTION_HEAD ? 4 : -4) JKRDvdFile(entryNum); if (mDvdFile == nullptr) { @@ -206,6 +224,7 @@ bool JKRAramArchive::open(long entryNum) { mFileEntries[i].mSize = bswap32(mFileEntries[i].mSize); /* mData is a host pointer, don't swap */ } + mFileEntryDataPtrs = (void**)calloc(mArcInfoBlock->num_file_entries > 0 ? mArcInfoBlock->num_file_entries : 1, sizeof(void*)); #endif u32 aramSize = ALIGN_NEXT(mem->file_data_length, 32); @@ -240,7 +259,7 @@ void* JKRAramArchive::fetchResource(SDIFileEntry* fileEntry, u32* pSize) { u32 sizeRef; u8* data; - if (fileEntry->mData) { + if (getFileEntryData(fileEntry)) { if (pSize) *pSize = fileEntry->mSize; } else { @@ -250,10 +269,10 @@ void* JKRAramArchive::fetchResource(SDIFileEntry* fileEntry, u32* pSize) { fetchResource_subroutine(fileEntry->mDataOffset + addres, fileEntry->mSize, mHeap, compression, &data); if (pSize) *pSize = size; - fileEntry->mData = (void*)data; + setFileEntryData(fileEntry, (void*)data); } - return fileEntry->mData; + return getFileEntryData(fileEntry); } void* JKRAramArchive::fetchResource(void* data, u32 compressedSize, SDIFileEntry* fileEntry, u32* pSize, @@ -263,8 +282,8 @@ void* JKRAramArchive::fetchResource(void* data, u32 compressedSize, SDIFileEntry if (fileSize > compressedSize) { fileSize = compressedSize; } - if (fileEntry->mData) { - JKRHeap::copyMemory(data, fileEntry->mData, fileSize); + if (getFileEntryData(fileEntry)) { + JKRHeap::copyMemory(data, getFileEntryData(fileEntry), fileSize); } else { int compression = JKRConvertAttrToCompressionType(fileEntry->mFlag >> 0x18); if (expandSwitch != EXPAND_SWITCH_DECOMPRESS) diff --git a/src/static/JSystem/JKernel/JKRAramPiece.cpp b/src/static/JSystem/JKernel/JKRAramPiece.cpp index ad14c575..81bfd47c 100644 --- a/src/static/JSystem/JKernel/JKRAramPiece.cpp +++ b/src/static/JSystem/JKernel/JKRAramPiece.cpp @@ -12,8 +12,13 @@ JSUList JKRAramPiece::sAramPieceCommandList; OSMutex JKRAramPiece::mMutex; +#ifdef TARGET_PC +JKRAMCommand* JKRAramPiece::prepareCommand(int direction, uintptr_t source, uintptr_t destination, u32 length, + JKRAramBlock* aramBlock, JKRAMCommand::AMCommandCallback callback) { +#else JKRAMCommand* JKRAramPiece::prepareCommand(int direction, u32 source, u32 destination, u32 length, JKRAramBlock* aramBlock, JKRAMCommand::AMCommandCallback callback) { +#endif JKRAMCommand* cmd = new (JKRGetSystemHeap(), -4) JKRAMCommand(); cmd->mDirection = direction; cmd->mSource = source; @@ -29,8 +34,13 @@ void JKRAramPiece::sendCommand(JKRAMCommand* cmd) { JKRAramPiece::startDMA(cmd); } +#ifdef TARGET_PC +JKRAMCommand* JKRAramPiece::orderAsync(int direction, uintptr_t source, uintptr_t destination, u32 length, JKRAramBlock* aramBlock, + JKRAMCommand::AMCommandCallback callback) { +#else JKRAMCommand* JKRAramPiece::orderAsync(int direction, u32 source, u32 destination, u32 length, JKRAramBlock* aramBlock, JKRAMCommand::AMCommandCallback callback) { +#endif JKRAramPiece::lock(); if (!JKR_ISALIGNED32(source) || !JKR_ISALIGNED32(destination)) { @@ -81,7 +91,11 @@ bool JKRAramPiece::sync(JKRAMCommand* cmd, BOOL noBlock) { } } +#ifdef TARGET_PC +bool JKRAramPiece::orderSync(int direction, uintptr_t source, uintptr_t destination, u32 length, JKRAramBlock* aramBlock) { +#else bool JKRAramPiece::orderSync(int direction, u32 source, u32 destination, u32 length, JKRAramBlock* aramBlock) { +#endif JKRAramPiece::lock(); JKRAMCommand* cmd = JKRAramPiece::orderAsync(direction, source, destination, length, aramBlock, nullptr); @@ -102,7 +116,11 @@ void JKRAramPiece::startDMA(JKRAMCommand* cmd) { ARQPostRequest(cmd, 0, cmd->mDirection, 0, cmd->mSource, cmd->mDestination, cmd->mLength, JKRAramPiece::doneDMA); } +#ifdef TARGET_PC +void JKRAramPiece::doneDMA(uintptr_t param) { +#else void JKRAramPiece::doneDMA(u32 param) { +#endif JKRAMCommand* cmd = (JKRAMCommand*)param; if (cmd->mDirection == ARAM_DIR_ARAM_TO_MRAM) { DCInvalidateRange((u8*)cmd->mDestination, cmd->mLength); diff --git a/src/static/JSystem/JKernel/JKRAramStream.cpp b/src/static/JSystem/JKernel/JKRAramStream.cpp index 23f181d6..1a9b5019 100644 --- a/src/static/JSystem/JKernel/JKRAramStream.cpp +++ b/src/static/JSystem/JKernel/JKRAramStream.cpp @@ -56,7 +56,7 @@ s32 JKRAramStream::writeToAram(JKRAramStreamCommand* command) { u32 dstSize = command->mSize; u32 offset = command->mOffset; u32 writtenLength = 0; - u32 destination = command->mAddress; + u32 destination = (u32)command->mAddress; u8* buffer = command->mTransferBuffer; u32 bufferSize = command->mTransferBufferSize; JKRHeap* heap = command->mHeap; @@ -96,7 +96,11 @@ s32 JKRAramStream::writeToAram(JKRAramStreamCommand* command) { s32 readLength = command->mStream->read(buffer, length); +#ifdef TARGET_PC + JKRAramPcs(0, (uintptr_t)buffer, destination, length, nullptr); +#else JKRAramPcs(0, (u32)buffer, destination, length, nullptr); +#endif dstSize -= length; writtenLength += length; destination += length; @@ -122,7 +126,11 @@ JKRAramStreamCommand* JKRAramStream::write_StreamToAram_Async(JSUFileInputStream u32 offset) { JKRAramStreamCommand* command = new (JKRGetSystemHeap(), -4) JKRAramStreamCommand(); command->type = JKRAramStreamCommand::ECT_WRITE; +#ifdef TARGET_PC + command->mAddress = (uintptr_t)addr; +#else command->mAddress = (u32)addr; +#endif command->mSize = size; command->mStream = stream; command->_28 = stream->getAvailable(); @@ -199,7 +207,11 @@ void JKRAramStream::setTransBuffer(u8* buffer, u32 bufferSize, JKRHeap* heap) { transHeap = nullptr; if (buffer) { +#ifdef TARGET_PC + transBuffer = (u8*)ALIGN_NEXT((uintptr_t)buffer, 0x20); +#else transBuffer = (u8*)ALIGN_NEXT((u32)buffer, 0x20); +#endif } if (bufferSize) { diff --git a/src/static/JSystem/JKernel/JKRArchivePri.cpp b/src/static/JSystem/JKernel/JKRArchivePri.cpp index 591f1883..b674a727 100644 --- a/src/static/JSystem/JKernel/JKRArchivePri.cpp +++ b/src/static/JSystem/JKernel/JKRArchivePri.cpp @@ -10,6 +10,9 @@ u32 JKRArchive::sCurrentDirID; JKRArchive::JKRArchive() { mIsMounted = false; mMountDirection = MOUNT_DIRECTION_HEAD; +#ifdef TARGET_PC + mFileEntryDataPtrs = nullptr; +#endif } JKRArchive::JKRArchive(s32 entryNum, JKRArchive::EMountMode mountMode) : JKRFileLoader() { @@ -17,6 +20,9 @@ JKRArchive::JKRArchive(s32 entryNum, JKRArchive::EMountMode mountMode) : JKRFile mMountMode = mountMode; mMountCount = 1; _54 = 1; +#ifdef TARGET_PC + mFileEntryDataPtrs = nullptr; +#endif mHeap = JKRHeap::findFromRoot(this); if (!mHeap) { mHeap = JKRHeap::sCurrentHeap; @@ -130,7 +136,7 @@ JKRArchive::SDIFileEntry* JKRArchive::findNameResource(const char* name) const { JKRArchive::SDIFileEntry* JKRArchive::findPtrResource(const void* ptr) const { SDIFileEntry* entry = mFileEntries; for (u32 i = 0; i < mArcInfoBlock->num_file_entries; entry++, i++) { - if (entry->mData == ptr) { + if (getFileEntryData(entry) == ptr) { return entry; } } diff --git a/src/static/JSystem/JKernel/JKRArchivePub.cpp b/src/static/JSystem/JKernel/JKRArchivePub.cpp index d49287a2..5af20b9e 100644 --- a/src/static/JSystem/JKernel/JKRArchivePub.cpp +++ b/src/static/JSystem/JKernel/JKRArchivePub.cpp @@ -241,9 +241,9 @@ void JKRArchive::removeResourceAll() { if (mArcInfoBlock && mMountMode != MOUNT_MEM) { SDIFileEntry* entry = mFileEntries; for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) { - if (entry->mData) { - entry->mData = nullptr; - JKRFreeToHeap(mHeap, entry->mData); + if (getFileEntryData(entry)) { + setFileEntryData(entry, nullptr); + JKRFreeToHeap(mHeap, getFileEntryData(entry)); } } } @@ -255,7 +255,7 @@ bool JKRArchive::removeResource(void* resource) { if (entry == nullptr) { return false; } - entry->mData = nullptr; + setFileEntryData(entry, nullptr); JKRHeap::free(resource, mHeap); return true; } @@ -266,7 +266,7 @@ bool JKRArchive::detachResource(void* resource) { if (entry == nullptr) { return false; } - entry->mData = nullptr; + setFileEntryData(entry, nullptr); return true; } diff --git a/src/static/JSystem/JKernel/JKRCompArchive.cpp b/src/static/JSystem/JKernel/JKRCompArchive.cpp index a4331db4..e2f19d24 100644 --- a/src/static/JSystem/JKernel/JKRCompArchive.cpp +++ b/src/static/JSystem/JKernel/JKRCompArchive.cpp @@ -8,7 +8,11 @@ #include "JSystem/JSystem.h" #include "JSystem/JUtility/JUTAssertion.h" -JKRCompArchive::JKRCompArchive(long entryNum, EMountDirection mountDirection) : JKRArchive(entryNum, MOUNT_COMP) { +#ifdef TARGET_PC +#include +#endif + +JKRCompArchive::JKRCompArchive(s32 entryNum, EMountDirection mountDirection) : JKRArchive(entryNum, MOUNT_COMP) { mMountDirection = mountDirection; if (!open(entryNum)) { return; @@ -32,14 +36,22 @@ JKRCompArchive::~JKRCompArchive() { SDIFileEntry* fileEntries = mFileEntries; for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) { u32 flag = (fileEntries->mFlag >> 24); - if ((flag & 16) == 0 && fileEntries->mData) { - JKRFreeToHeap(mHeap, fileEntries->mData); + if ((flag & 16) == 0 && getFileEntryData(fileEntries)) { + JKRFreeToHeap(mHeap, getFileEntryData(fileEntries)); } fileEntries++; } JKRFreeToHeap(mHeap, mArcInfoBlock); mArcInfoBlock = nullptr; } + +#ifdef TARGET_PC + if (mFileEntryDataPtrs) { + free(mFileEntryDataPtrs); + mFileEntryDataPtrs = nullptr; + } +#endif + if (mAramPart) { delete mAramPart; } @@ -51,7 +63,7 @@ JKRCompArchive::~JKRCompArchive() { mIsMounted = false; } -bool JKRCompArchive::open(long entryNum) { +bool JKRCompArchive::open(s32 entryNum) { mArcInfoBlock = nullptr; _60 = 0; mAramPart = nullptr; @@ -62,6 +74,9 @@ bool JKRCompArchive::open(long entryNum) { mDirectories = nullptr; mFileEntries = nullptr; mStrTable = nullptr; +#ifdef TARGET_PC + mFileEntryDataPtrs = nullptr; +#endif mDvdFile = new (JKRGetSystemHeap(), 0) JKRDvdFile(entryNum); if (mDvdFile == nullptr) { @@ -95,7 +110,11 @@ bool JKRCompArchive::open(long entryNum) { JKRDvdToMainRam(entryNum, (u8*)mArcInfoBlock, EXPAND_SWITCH_DECOMPRESS, (u32)arcHeader->file_data_offset + mSizeOfMemPart, nullptr, JKRDvdRipper::ALLOC_DIR_TOP, 0x20, nullptr); +#ifdef TARGET_PC + _60 = (uintptr_t)mArcInfoBlock + arcHeader->file_data_offset; +#else _60 = (u32)mArcInfoBlock + arcHeader->file_data_offset; +#endif if (mSizeOfAramPart != 0) { mAramPart = JKRAllocFromAram(mSizeOfAramPart, JKRAramHeap::Head); @@ -108,9 +127,16 @@ bool JKRCompArchive::open(long entryNum) { arcHeader->header_length + arcHeader->file_data_offset + mSizeOfMemPart, 0); } +#ifdef TARGET_PC + mDirectories = (SDIDirEntry*)((uintptr_t)mArcInfoBlock + mArcInfoBlock->node_offset); + mFileEntries = (SDIFileEntry*)((uintptr_t)mArcInfoBlock + mArcInfoBlock->file_entry_offset); + mStrTable = (const char*)((uintptr_t)mArcInfoBlock + mArcInfoBlock->string_table_offset); + mFileEntryDataPtrs = (void**)calloc(mArcInfoBlock->num_file_entries > 0 ? mArcInfoBlock->num_file_entries : 1, sizeof(void*)); +#else mDirectories = (SDIDirEntry*)((u32)mArcInfoBlock + mArcInfoBlock->node_offset); mFileEntries = (SDIFileEntry*)((u32)mArcInfoBlock + mArcInfoBlock->file_entry_offset); mStrTable = (const char*)((u32)mArcInfoBlock + mArcInfoBlock->string_table_offset); +#endif _68 = arcHeader->header_length + arcHeader->file_data_offset; } break; @@ -144,7 +170,11 @@ bool JKRCompArchive::open(long entryNum) { // header JKRHeap::copyMemory((u8*)mArcInfoBlock, arcHeader + 1, (arcHeader->file_data_offset + mSizeOfMemPart)); +#ifdef TARGET_PC + _60 = (uintptr_t)mArcInfoBlock + arcHeader->file_data_offset; +#else _60 = (u32)mArcInfoBlock + arcHeader->file_data_offset; +#endif if (mSizeOfAramPart != 0) { mAramPart = JKRAllocFromAram(mSizeOfAramPart, JKRAramHeap::Head); if (mAramPart == nullptr) { @@ -159,9 +189,16 @@ bool JKRCompArchive::open(long entryNum) { } } } +#ifdef TARGET_PC + mDirectories = (SDIDirEntry*)((uintptr_t)mArcInfoBlock + mArcInfoBlock->node_offset); + mFileEntries = (SDIFileEntry*)((uintptr_t)mArcInfoBlock + mArcInfoBlock->file_entry_offset); + mStrTable = (const char*)((uintptr_t)mArcInfoBlock + mArcInfoBlock->string_table_offset); + mFileEntryDataPtrs = (void**)calloc(mArcInfoBlock->num_file_entries > 0 ? mArcInfoBlock->num_file_entries : 1, sizeof(void*)); +#else mDirectories = (SDIDirEntry*)((u32)mArcInfoBlock + mArcInfoBlock->node_offset); mFileEntries = (SDIFileEntry*)((u32)mArcInfoBlock + mArcInfoBlock->file_entry_offset); mStrTable = (const char*)((u32)mArcInfoBlock + mArcInfoBlock->string_table_offset); +#endif _68 = arcHeader->header_length + arcHeader->file_data_offset; break; } @@ -185,10 +222,10 @@ void* JKRCompArchive::fetchResource(SDIFileEntry* fileEntry, u32* pSize) { u32 ptrSize; - if (fileEntry->mData == nullptr) { + if (getFileEntryData(fileEntry) == nullptr) { u32 flag = fileEntry->mFlag >> 0x18; if (flag & 0x10) { - fileEntry->mData = (void*)(_60 + fileEntry->mDataOffset); + setFileEntryData(fileEntry, (void*)(_60 + fileEntry->mDataOffset)); if (pSize) *pSize = fileEntry->mSize; } else if (flag & 0x20) { @@ -202,7 +239,7 @@ void* JKRCompArchive::fetchResource(SDIFileEntry* fileEntry, u32* pSize) { if (pSize) *pSize = size; - fileEntry->mData = data; + setFileEntryData(fileEntry, data); } else if (flag & 0x40) { int compression = JKRConvertAttrToCompressionType(fileEntry->mFlag >> 0x18); @@ -214,12 +251,12 @@ void* JKRCompArchive::fetchResource(SDIFileEntry* fileEntry, u32* pSize) { if (pSize) *pSize = size; - fileEntry->mData = data; + setFileEntryData(fileEntry, data); } } else if (pSize) { *pSize = fileEntry->mSize; } - return fileEntry->mData; + return getFileEntryData(fileEntry); } void* JKRCompArchive::fetchResource(void* data, u32 compressedSize, SDIFileEntry* fileEntry, u32* pSize, @@ -233,12 +270,12 @@ void* JKRCompArchive::fetchResource(void* data, u32 compressedSize, SDIFileEntry if (size == 0) JPANIC(651, ":::bad resource size. size = 0\n"); - if (fileEntry->mData) { + if (getFileEntryData(fileEntry)) { if (size > (compressedSize & ~31)) { size = (compressedSize & ~31); } - JKRHeap::copyMemory(data, fileEntry->mData, size); + JKRHeap::copyMemory(data, getFileEntryData(fileEntry), size); expandSize = size; } else { u32 fileFlag = fileEntry->mFlag >> 0x18; @@ -285,12 +322,12 @@ void JKRCompArchive::removeResourceAll() { SDIFileEntry* fileEntry = mFileEntries; for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) { u32 flag = fileEntry->mFlag >> 0x18; - if (fileEntry->mData) { + if (getFileEntryData(fileEntry)) { if ((flag & 0x10) == 0) { - JKRFreeToHeap(mHeap, fileEntry->mData); + JKRFreeToHeap(mHeap, getFileEntryData(fileEntry)); } - fileEntry->mData = nullptr; + setFileEntryData(fileEntry, nullptr); } } } @@ -305,6 +342,6 @@ bool JKRCompArchive::removeResource(void* resource) { JKRFreeToHeap(mHeap, resource); } - fileEntry->mData = nullptr; + setFileEntryData(fileEntry, nullptr); return true; } diff --git a/src/static/JSystem/JKernel/JKRDecomp.cpp b/src/static/JSystem/JKernel/JKRDecomp.cpp index 72207a8c..af2711f9 100644 --- a/src/static/JSystem/JKernel/JKRDecomp.cpp +++ b/src/static/JSystem/JKernel/JKRDecomp.cpp @@ -50,7 +50,11 @@ void* JKRDecomp::run() { break; } +#ifdef TARGET_PC + cmd->mCallback((uintptr_t)cmd); +#else cmd->mCallback((u32)cmd); +#endif } if (cmd->pMesgQueue1C != nullptr) { diff --git a/src/static/JSystem/JKernel/JKRDvdAramRipper.cpp b/src/static/JSystem/JKernel/JKRDvdAramRipper.cpp index a317c32b..bd8db294 100644 --- a/src/static/JSystem/JKernel/JKRDvdAramRipper.cpp +++ b/src/static/JSystem/JKernel/JKRDvdAramRipper.cpp @@ -77,7 +77,11 @@ JKRADCommand* JKRDvdAramRipper::callCommand_Async(JKRADCommand* command) { fileSize = ALIGN_NEXT(fileSize, 0x20); if (command->mExpandSwitch == EXPAND_SWITCH_DECOMPRESS) { u8 buffer[0x40]; +#ifdef TARGET_PC + u8* bufPtr = (u8*)ALIGN_NEXT((uintptr_t)buffer, 0x20); +#else u8* bufPtr = (u8*)ALIGN_NEXT((u32)buffer, 0x20); +#endif while (true) { if (DVDReadPrio(dvdFile->getFileInfo(), bufPtr, 0x20, 0, 2) >= 0) { break; @@ -151,7 +155,11 @@ JKRADCommand* JKRDvdAramRipper::callCommand_Async(JKRADCommand* command) { if (!command->mCallBack) { sDvdAramAsyncList.append(&command->mLink); } else { +#ifdef TARGET_PC + command->mCallBack((uintptr_t)command); +#else command->mCallBack((u32)command); +#endif } } @@ -369,7 +377,11 @@ u8* nextSrcData(u8* src) { buf = szpBuf; memcpy(buf, src, limit); +#ifdef TARGET_PC + uintptr_t transSize = (uintptr_t)(szpEnd - (buf + limit)); +#else u32 transSize = (u32)(szpEnd - (buf + limit)); +#endif if (transSize > transLeft) transSize = transLeft; @@ -397,8 +409,13 @@ u32 dmaBufferFlush(u32 src) { if (dmaCurrent == dmaBuf) { return 0; } else { +#ifdef TARGET_PC + u32 length = ALIGN_NEXT((uintptr_t)(dmaCurrent - dmaBuf), 32); + JKRAramPiece::orderSync(0, (uintptr_t)dmaBuf, src, length, nullptr); +#else u32 length = ALIGN_NEXT((u32)(dmaCurrent - dmaBuf), 32); JKRAramPiece::orderSync(0, (u32)dmaBuf, src, length, nullptr); +#endif dmaCurrent = dmaBuf; return length; } diff --git a/src/static/JSystem/JKernel/JKRDvdArchive.cpp b/src/static/JSystem/JKernel/JKRDvdArchive.cpp index b825b394..fe74aac7 100644 --- a/src/static/JSystem/JKernel/JKRDvdArchive.cpp +++ b/src/static/JSystem/JKernel/JKRDvdArchive.cpp @@ -8,6 +8,10 @@ #include "JSystem/JSystem.h" #include "JSystem/JUtility/JUTAssertion.h" +#ifdef TARGET_PC +#include +#endif + JKRDvdArchive::JKRDvdArchive() : JKRArchive() { } @@ -28,14 +32,21 @@ JKRDvdArchive::~JKRDvdArchive() { if (mArcInfoBlock) { SDIFileEntry* fileEntries = mFileEntries; for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) { - if (fileEntries->mData != nullptr) { - JKRFreeToHeap(mHeap, fileEntries->mData); + if (getFileEntryData(fileEntries) != nullptr) { + JKRFreeToHeap(mHeap, getFileEntryData(fileEntries)); } fileEntries++; } JKRFreeToHeap(mHeap, mArcInfoBlock); } +#ifdef TARGET_PC + if (mFileEntryDataPtrs) { + free(mFileEntryDataPtrs); + mFileEntryDataPtrs = nullptr; + } +#endif + if (mDvdFile) { delete mDvdFile; } @@ -49,12 +60,15 @@ JKRDvdArchive::~JKRDvdArchive() { CW_FORCE_STRINGS(JKRDvdArchive_cpp, __FILE__, "isMounted()", "mMountCount == 1") #endif -bool JKRDvdArchive::open(long entryNum) { +bool JKRDvdArchive::open(s32 entryNum) { mArcInfoBlock = nullptr; _60 = 0; mDirectories = nullptr; mFileEntries = nullptr; mStrTable = nullptr; +#ifdef TARGET_PC + mFileEntryDataPtrs = nullptr; +#endif mDvdFile = new (JKRGetSystemHeap(), 0) JKRDvdFile(entryNum); if (mDvdFile == nullptr) { @@ -79,6 +93,9 @@ bool JKRDvdArchive::open(long entryNum) { mDirectories = (SDIDirEntry*)((u8*)mArcInfoBlock + mArcInfoBlock->node_offset); mFileEntries = (SDIFileEntry*)((u8*)mArcInfoBlock + mArcInfoBlock->file_entry_offset); mStrTable = (const char*)((u8*)mArcInfoBlock + mArcInfoBlock->string_table_offset); +#ifdef TARGET_PC + mFileEntryDataPtrs = (void**)calloc(mArcInfoBlock->num_file_entries > 0 ? mArcInfoBlock->num_file_entries : 1, sizeof(void*)); +#endif _60 = mem->mDataOffset + mem->mSize; // End of data offset? } } @@ -101,7 +118,7 @@ void* JKRDvdArchive::fetchResource(SDIFileEntry* fileEntry, u32* pSize) { u32 sizeRef; u8* data; - if (fileEntry->mData == nullptr) { + if (getFileEntryData(fileEntry) == nullptr) { int compression = JKRConvertAttrToCompressionType(fileEntry->mFlag >> 0x18); u32 size = fetchResource_subroutine(mEntryNum, _60 + fileEntry->mDataOffset, fileEntry->mSize, mHeap, (int)compression, mCompression, &data); @@ -109,12 +126,12 @@ void* JKRDvdArchive::fetchResource(SDIFileEntry* fileEntry, u32* pSize) { if (pSize) *pSize = size; - fileEntry->mData = data; + setFileEntryData(fileEntry, data); } else if (pSize) { *pSize = fileEntry->mSize; } - return fileEntry->mData; + return getFileEntryData(fileEntry); } void* JKRDvdArchive::fetchResource(void* data, u32 compressedSize, SDIFileEntry* fileEntry, u32* pSize, @@ -128,14 +145,14 @@ void* JKRDvdArchive::fetchResource(void* data, u32 compressedSize, SDIFileEntry* alignedSize = fileSize; } - if (fileEntry->mData == nullptr) { + if (getFileEntryData(fileEntry) == nullptr) { int compression = JKRConvertAttrToCompressionType(fileEntry->mFlag >> 0x18); if (expandSwitch != EXPAND_SWITCH_DECOMPRESS) compression = 0; alignedSize = fetchResource_subroutine(mEntryNum, _60 + fileEntry->mDataOffset, fileEntry->mSize, (u8*)data, fileSize, compression, mCompression); } else { - JKRHeap::copyMemory(data, fileEntry->mData, alignedSize); + JKRHeap::copyMemory(data, getFileEntryData(fileEntry), alignedSize); } if (pSize) { @@ -144,7 +161,7 @@ void* JKRDvdArchive::fetchResource(void* data, u32 compressedSize, SDIFileEntry* return data; } -u32 JKRDvdArchive::fetchResource_subroutine(long entryNum, u32 offset, u32 size, u8* data, u32 expandSize, +u32 JKRDvdArchive::fetchResource_subroutine(s32 entryNum, u32 offset, u32 size, u8* data, u32 expandSize, int fileCompression, int archiveCompression) { u32 prevAlignedSize, alignedSize; @@ -199,7 +216,7 @@ u32 JKRDvdArchive::fetchResource_subroutine(long entryNum, u32 offset, u32 size, return 0; } -u32 JKRDvdArchive::fetchResource_subroutine(long entryNum, u32 offset, u32 size, JKRHeap* heap, int fileCompression, +u32 JKRDvdArchive::fetchResource_subroutine(s32 entryNum, u32 offset, u32 size, JKRHeap* heap, int fileCompression, int archiveCompression, u8** pBuf) { u32 alignedSize = ALIGN_NEXT(size, 32); diff --git a/src/static/JSystem/JKernel/JKRDvdRipper.cpp b/src/static/JSystem/JKernel/JKRDvdRipper.cpp index 27de91b2..de21f938 100644 --- a/src/static/JSystem/JKernel/JKRDvdRipper.cpp +++ b/src/static/JSystem/JKernel/JKRDvdRipper.cpp @@ -48,7 +48,11 @@ void* JKRDvdRipper::loadToMainRAM(JKRDvdFile* file, u8* buf, JKRExpandSwitch exp if (expandSwitch == EXPAND_SWITCH_DECOMPRESS) { u8 buffer[64]; +#ifdef TARGET_PC + u8* aligned_buf = (u8*)ALIGN_NEXT((uintptr_t)buffer, 32); +#else u8* aligned_buf = (u8*)ALIGN_NEXT((u32)buffer, 32); +#endif while (true) { if (DVDReadPrio(file->getFileInfo(), aligned_buf, 32, 0, 2) >= 0) { break; @@ -105,7 +109,11 @@ void* JKRDvdRipper::loadToMainRAM(JKRDvdFile* file, u8* buf, JKRExpandSwitch exp if (offset != 0) { u8 buffer[64]; +#ifdef TARGET_PC + u8* aligned_buf = (u8*)ALIGN_NEXT((uintptr_t)buffer, 32); +#else u8* aligned_buf = (u8*)ALIGN_NEXT((u32)buffer, 32); +#endif while (true) { if (DVDReadPrio(file->getFileInfo(), aligned_buf, 32, offset, 2) >= 0) { break; diff --git a/src/static/JSystem/JKernel/JKRExpHeap.cpp b/src/static/JSystem/JKernel/JKRExpHeap.cpp index 90649bde..e1f3f283 100644 --- a/src/static/JSystem/JKernel/JKRExpHeap.cpp +++ b/src/static/JSystem/JKernel/JKRExpHeap.cpp @@ -74,7 +74,11 @@ JKRExpHeap* JKRExpHeap::create(void* ptr, u32 size, JKRHeap* parent, bool errorF return nullptr; void* dataPtr = (u8*)ptr + expHeapSize; +#ifdef TARGET_PC + u32 alignedSize = ALIGN_PREV((uintptr_t)ptr + size - (uintptr_t)dataPtr, 0x10); +#else u32 alignedSize = ALIGN_PREV((u32)ptr + size - (u32)dataPtr, 0x10); +#endif if (ptr) newHeap = new (ptr) JKRExpHeap(dataPtr, alignedSize, parent2, errorFlag); @@ -157,7 +161,11 @@ void* JKRExpHeap::allocFromHead(u32 size, int align) { CMemBlock* foundBlock = nullptr; for (CMemBlock* block = mHead; block; block = block->mNext) { +#ifdef TARGET_PC + u32 offset = ALIGN_PREV(align - 1 + (uintptr_t)block->getContent(), align) - (uintptr_t)block->getContent(); +#else u32 offset = ALIGN_PREV(align - 1 + (u32)block->getContent(), align) - (u32)block->getContent(); +#endif if (block->mAllocatedSpace < size + offset) { continue; } @@ -217,7 +225,11 @@ void* JKRExpHeap::allocFromHead(u32 size, int align) { CMemBlock* prev = foundBlock->mPrev; CMemBlock* next = foundBlock->mNext; removeFreeBlock(foundBlock); +#ifdef TARGET_PC + newUsedBlock = (CMemBlock*)((uintptr_t)foundBlock + foundOffset); +#else newUsedBlock = (CMemBlock*)((u32)foundBlock + foundOffset); +#endif newUsedBlock->mAllocatedSpace = foundBlock->mAllocatedSpace - foundOffset; newFreeBlock = newUsedBlock->allocFore(size, mCurrentGroupID, (u8)foundOffset, 0, 0); if (newFreeBlock) { @@ -295,12 +307,22 @@ void* JKRExpHeap::allocFromTail(u32 size, int align) { u32 offset = 0; CMemBlock* foundBlock = nullptr; CMemBlock* newBlock = nullptr; +#ifdef TARGET_PC + uintptr_t usedSize; + uintptr_t start; +#else u32 usedSize; u32 start; +#endif for (CMemBlock* block = mTail; block; block = block->mPrev) { +#ifdef TARGET_PC + start = ALIGN_PREV((uintptr_t)block->getContent() + block->mAllocatedSpace - size, align); + usedSize = (uintptr_t)block->getContent() + block->mAllocatedSpace - start; +#else start = ALIGN_PREV((u32)block->getContent() + block->mAllocatedSpace - size, align); usedSize = (u32)block->getContent() + block->mAllocatedSpace - start; +#endif if (block->mAllocatedSpace >= usedSize) { foundBlock = block; offset = block->mAllocatedSpace - usedSize; @@ -432,7 +454,11 @@ s32 JKRExpHeap::do_resize(void* ptr, u32 size) { if (size > block->mAllocatedSpace) { CMemBlock* foundBlock = nullptr; for (CMemBlock* freeBlock = mHead; freeBlock; freeBlock = freeBlock->mNext) { +#ifdef TARGET_PC + if (freeBlock == (CMemBlock*)((uintptr_t)(block + 1) + block->mAllocatedSpace)) { +#else if (freeBlock == (CMemBlock*)((u32)(block + 1) + block->mAllocatedSpace)) { +#endif foundBlock = freeBlock; break; } @@ -552,7 +578,11 @@ bool JKRExpHeap::check() { ok = false; JUTWarningConsole_f(":::addr %08x: bad previous pointer (%08x)\n", block->mNext, block->mNext->mPrev); } +#ifdef TARGET_PC + if ((uintptr_t)block + block->mAllocatedSpace + sizeof(CMemBlock) > (uintptr_t)block->mNext) { +#else if ((u32)block + block->mAllocatedSpace + sizeof(CMemBlock) > (u32)block->mNext) { +#endif ok = false; JUTWarningConsole_f(":::addr %08x: bad block size (%08x)\n", block, block->mAllocatedSpace); } @@ -699,9 +729,15 @@ void JKRExpHeap::joinTwoBlocks(CMemBlock* block) { // u32 nextAddr; // CMemBlock *next; +#ifdef TARGET_PC + uintptr_t endAddr = (uintptr_t)(block + 1) + block->mAllocatedSpace; + CMemBlock* next = block->mNext; + uintptr_t nextAddr = (uintptr_t)next - (next->mFlags & 0x7f); +#else u32 endAddr = (u32)(block + 1) + block->mAllocatedSpace; CMemBlock* next = block->mNext; u32 nextAddr = (u32)next - (next->mFlags & 0x7f); +#endif if (endAddr > nextAddr) { JUTWarningConsole_f(":::Heap may be broken. (block = %x)", block); JREPORTF(":::block = %x\n", block); @@ -837,7 +873,11 @@ JKRExpHeap::CMemBlock* JKRExpHeap::CMemBlock::allocFore(u32 size, u8 groupId1, u mGroupID = groupId1; mFlags = alignment1; if (mAllocatedSpace >= size + sizeof(CMemBlock)) { +#ifdef TARGET_PC + block = (CMemBlock*)(size + (uintptr_t)this); +#else block = (CMemBlock*)(size + (u32)this); +#endif block = block + 1; block->mGroupID = groupId2; block->mFlags = alignment2; @@ -847,7 +887,7 @@ JKRExpHeap::CMemBlock* JKRExpHeap::CMemBlock::allocFore(u32 size, u8 groupId1, u return block; } -JKRExpHeap::CMemBlock* JKRExpHeap::CMemBlock::allocBack(unsigned long size, unsigned char groupID, unsigned char p3, +JKRExpHeap::CMemBlock* JKRExpHeap::CMemBlock::allocBack(u32 size, unsigned char groupID, unsigned char p3, unsigned char allocGroupID, unsigned char p5) { CMemBlock* newBlock = nullptr; if (mAllocatedSpace >= size + sizeof(CMemBlock)) { @@ -893,10 +933,18 @@ void JKRExpHeap::state_register(JKRHeap::TState* p, u32 param_1) const { if (param_1 <= 0xff) { u8 groupId = block->mGroupID; if (groupId == param_1) { +#ifdef TARGET_PC + checkCode += (uintptr_t)block * 3; +#else checkCode += (u32)block * 3; +#endif } } else { +#ifdef TARGET_PC + checkCode += (uintptr_t)block * 3; +#else checkCode += (u32)block * 3; +#endif } } setState_u32CheckCode_(p, checkCode); diff --git a/src/static/JSystem/JKernel/JKRHeap.cpp b/src/static/JSystem/JKernel/JKRHeap.cpp index 068d7f0d..4c8c0ee5 100644 --- a/src/static/JSystem/JKernel/JKRHeap.cpp +++ b/src/static/JSystem/JKernel/JKRHeap.cpp @@ -70,7 +70,11 @@ bool JKRHeap::initArena(char** outUserRamStart, u32* outUserRamSize, int numHeap OSSetArenaLo(arenaHi); OSSetArenaHi(arenaHi); *outUserRamStart = (char*)arenaLo; +#ifdef TARGET_PC + *outUserRamSize = (u32)((uintptr_t)arenaHi - (uintptr_t)arenaLo); +#else *outUserRamSize = (u32)arenaHi - (u32)arenaLo; +#endif return true; } @@ -207,7 +211,11 @@ JKRHeap* JKRHeap::findAllHeap(void* memory) const { } // generates __as__25JSUTreeIterator<7JKRHeap>FP17JSUTree<7JKRHeap> and __ct__25JSUTreeIterator<7JKRHeap>Fv, remove this +#ifdef TARGET_PC +void JKRHeap::dispose_subroutine(uintptr_t begin, uintptr_t end) { +#else void JKRHeap::dispose_subroutine(u32 begin, u32 end) { +#endif JSUListIterator last_iterator; JSUListIterator next_iterator; JSUListIterator iterator; @@ -231,14 +239,23 @@ void JKRHeap::dispose_subroutine(u32 begin, u32 end) { } bool JKRHeap::dispose(void* memory, u32 size) { +#ifdef TARGET_PC + uintptr_t begin = (uintptr_t)memory; + uintptr_t end = (uintptr_t)memory + size; +#else u32 begin = (u32)memory; u32 end = (u32)memory + size; +#endif dispose_subroutine(begin, end); return false; } void JKRHeap::dispose(void* begin, void* end) { +#ifdef TARGET_PC + dispose_subroutine((uintptr_t)begin, (uintptr_t)end); +#else dispose_subroutine((u32)begin, (u32)end); +#endif } void JKRHeap::dispose() { @@ -296,43 +313,79 @@ bool JKRHeap::isSubHeap(JKRHeap* heap) const { return false; } +#ifdef TARGET_PC +/* On PC, the default operator new uses system malloc (not JKRHeap), because + * macOS/Linux frameworks also call global operator new and expect malloc memory. + * + * operator delete must handle BOTH malloc'd memory AND JKR heap memory (from + * objects allocated via `new (heap, alignment)` which uses JKRHeap::alloc). */ +extern u8* arena_memory; /* from pc_os.c */ + +static inline bool pc_is_arena_ptr(void* p) { + if (!arena_memory || !p) return false; + uintptr_t addr = (uintptr_t)p; + uintptr_t base = (uintptr_t)arena_memory; + /* 48MB arena on 64-bit, 24MB on 32-bit */ + return (addr >= base && addr < base + (48u * 1024u * 1024u)); +} + +void* operator new(u32 byteCount) { + return malloc(byteCount); +} +void* operator new(u32 byteCount, int alignment) { + return malloc(byteCount); +} +void* operator new[](u32 byteCount) { + return malloc(byteCount); +} +void* operator new[](u32 byteCount, int alignment) { + return malloc(byteCount); +} +void operator delete(void* memory) { + if (pc_is_arena_ptr(memory)) { JKRHeap::free(memory, nullptr); return; } + free(memory); +} +void operator delete[](void* memory) { + if (pc_is_arena_ptr(memory)) { JKRHeap::free(memory, nullptr); return; } + free(memory); +} +/* C++14 sized deallocation - GCC 15 generates calls to these by default. */ +void operator delete(void* memory, size_t) { + if (pc_is_arena_ptr(memory)) { JKRHeap::free(memory, nullptr); return; } + free(memory); +} +void operator delete[](void* memory, size_t) { + if (pc_is_arena_ptr(memory)) { JKRHeap::free(memory, nullptr); return; } + free(memory); +} +#else void* operator new(u32 byteCount) { return JKRHeap::alloc(byteCount, 4, nullptr); } void* operator new(u32 byteCount, int alignment) { return JKRHeap::alloc(byteCount, alignment, nullptr); } -void* operator new(u32 byteCount, JKRHeap* heap, int alignment) { - return JKRHeap::alloc(byteCount, alignment, heap); -} - void* operator new[](u32 byteCount) { return JKRHeap::alloc(byteCount, 4, nullptr); } void* operator new[](u32 byteCount, int alignment) { return JKRHeap::alloc(byteCount, alignment, nullptr); } -void* operator new[](u32 byteCount, JKRHeap* heap, int alignment) { - return JKRHeap::alloc(byteCount, alignment, heap); -} - -// this is not needed without the other pragma and asm bs void operator delete(void* memory) { JKRHeap::free(memory, nullptr); } void operator delete[](void* memory) { JKRHeap::free(memory, nullptr); } -#ifdef TARGET_PC -/* C++14 sized deallocation - GCC 15 generates calls to these by default. - Without these, sized delete falls through to CRT free() which crashes - on pointers from the JKR heap (inside the game's arena memory). */ -void operator delete(void* memory, size_t) { - JKRHeap::free(memory, nullptr); +#endif +void* operator new(u32 byteCount, JKRHeap* heap, int alignment) { + return JKRHeap::alloc(byteCount, alignment, heap); } -void operator delete[](void* memory, size_t) { - JKRHeap::free(memory, nullptr); +void* operator new[](u32 byteCount, JKRHeap* heap, int alignment) { + return JKRHeap::alloc(byteCount, alignment, heap); } +#ifdef TARGET_PC +/* already defined above with malloc fallback */ #endif /*JKRHeap::TState::TState(const JKRHeap::TState::TArgument &arg, const JKRHeap::TState::TLocation &location) diff --git a/src/static/JSystem/JKernel/JKRMemArchive.cpp b/src/static/JSystem/JKernel/JKRMemArchive.cpp index f9312a9d..97526169 100644 --- a/src/static/JSystem/JKernel/JKRMemArchive.cpp +++ b/src/static/JSystem/JKernel/JKRMemArchive.cpp @@ -7,6 +7,10 @@ #include "JSystem/JKernel/JKRDvdRipper.h" #include "JSystem/JUtility/JUTAssertion.h" +#ifdef TARGET_PC +#include +#endif + JKRMemArchive::JKRMemArchive() : JKRArchive() { } @@ -40,6 +44,13 @@ JKRMemArchive::~JKRMemArchive() { if (mIsOpen && mArcHeader) JKRFreeToHeap(mHeap, mArcHeader); +#ifdef TARGET_PC + if (mFileEntryDataPtrs) { + free(mFileEntryDataPtrs); + mFileEntryDataPtrs = nullptr; + } +#endif + sVolumeList.remove(&mFileLoaderLink); mIsMounted = false; } @@ -63,6 +74,9 @@ bool JKRMemArchive::open(s32 entryNum, JKRArchive::EMountDirection mountDirectio mStrTable = nullptr; mIsOpen = false; mMountDirection = mountDirection; +#ifdef TARGET_PC + mFileEntryDataPtrs = nullptr; +#endif if (mMountDirection == JKRArchive::MOUNT_DIRECTION_HEAD) { u32 loadedSize; @@ -84,7 +98,12 @@ bool JKRMemArchive::open(s32 entryNum, JKRArchive::EMountDirection mountDirectio mFileEntries = (SDIFileEntry*)((u8*)&mArcInfoBlock->num_nodes + mArcInfoBlock->file_entry_offset); mStrTable = (char*)((u8*)&mArcInfoBlock->num_nodes + mArcInfoBlock->string_table_offset); +#ifdef TARGET_PC + mArchiveData = (u8*)((uintptr_t)mArcHeader + mArcHeader->header_length + mArcHeader->file_data_offset); + mFileEntryDataPtrs = (void**)calloc(mArcInfoBlock->num_file_entries > 0 ? mArcInfoBlock->num_file_entries : 1, sizeof(void*)); +#else mArchiveData = (u8*)((u32)mArcHeader + mArcHeader->header_length + mArcHeader->file_data_offset); +#endif mIsOpen = true; } #if DEBUG @@ -103,7 +122,12 @@ bool JKRMemArchive::open(void* buffer, u32 bufferSize, JKRMemBreakFlag flag) { mDirectories = (SDIDirEntry*)((u8*)&mArcInfoBlock->num_nodes + mArcInfoBlock->node_offset); mFileEntries = (SDIFileEntry*)((u8*)&mArcInfoBlock->num_nodes + mArcInfoBlock->file_entry_offset); mStrTable = (char*)((u8*)&mArcInfoBlock->num_nodes + mArcInfoBlock->string_table_offset); +#ifdef TARGET_PC + mArchiveData = (u8*)(((uintptr_t)mArcHeader + mArcHeader->header_length) + mArcHeader->file_data_offset); + mFileEntryDataPtrs = (void**)calloc(mArcInfoBlock->num_file_entries > 0 ? mArcInfoBlock->num_file_entries : 1, sizeof(void*)); +#else mArchiveData = (u8*)(((u32)mArcHeader + mArcHeader->header_length) + mArcHeader->file_data_offset); +#endif mIsOpen = (flag == MBF_1) ? true : false; // mIsOpen might be u8 mHeap = JKRHeap::findFromRoot(buffer); mCompression = JKRCOMPRESSION_NONE; @@ -113,13 +137,13 @@ bool JKRMemArchive::open(void* buffer, u32 bufferSize, JKRMemBreakFlag flag) { void* JKRMemArchive::fetchResource(SDIFileEntry* fileEntry, u32* resourceSize) { JUT_ASSERT(isMounted()) - if (!fileEntry->mData) - fileEntry->mData = mArchiveData + fileEntry->mDataOffset; + if (!getFileEntryData(fileEntry)) + setFileEntryData(fileEntry, mArchiveData + fileEntry->mDataOffset); if (resourceSize) *resourceSize = fileEntry->mSize; - return fileEntry->mData; + return getFileEntryData(fileEntry); } void* JKRMemArchive::fetchResource(void* buffer, u32 bufferSize, SDIFileEntry* fileEntry, u32* resourceSize, @@ -132,8 +156,8 @@ void* JKRMemArchive::fetchResource(void* buffer, u32 bufferSize, SDIFileEntry* f srcLength = bufferSize; } - if (fileEntry->mData != nullptr) { - JKRHeap::copyMemory(buffer, fileEntry->mData, srcLength); + if (getFileEntryData(fileEntry) != nullptr) { + JKRHeap::copyMemory(buffer, getFileEntryData(fileEntry), srcLength); } else { int compression = JKRConvertAttrToCompressionType(fileEntry->getAttr()); if (expandSwitch != EXPAND_SWITCH_DECOMPRESS) @@ -162,8 +186,8 @@ void JKRMemArchive::removeResourceAll(void) { // first fileEntry will clear/remove the resource data. SDIFileEntry* fileEntry = mFileEntries; for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) { - if (fileEntry->mData) { - fileEntry->mData = nullptr; + if (getFileEntryData(fileEntry)) { + setFileEntryData(fileEntry, nullptr); } } } @@ -175,7 +199,7 @@ bool JKRMemArchive::removeResource(void* resource) { if (!fileEntry) return false; - fileEntry->mData = nullptr; + setFileEntryData(fileEntry, nullptr); return true; } diff --git a/src/static/JSystem/JKernel/JKRThread.cpp b/src/static/JSystem/JKernel/JKRThread.cpp index 27d3310a..fdf91495 100644 --- a/src/static/JSystem/JKernel/JKRThread.cpp +++ b/src/static/JSystem/JKernel/JKRThread.cpp @@ -14,8 +14,13 @@ JKRThread::JKRThread(u32 stackSize, int msgCount, int threadPrio) : mLink(this) this->mStackSize = JKR_ALIGN32(stackSize); this->mStackMemory = JKRHeap::alloc(this->mStackSize, 32, this->mHeap); this->mThreadRecord = (OSThread*)JKRHeap::alloc(sizeof(OSThread), 32, this->mHeap); +#ifdef TARGET_PC + OSCreateThread(this->mThreadRecord, &JKRThread::start, this, (void*)((uintptr_t)this->mStackMemory + this->mStackSize), + this->mStackSize, threadPrio, OS_THREAD_ATTR_DETACH); +#else OSCreateThread(this->mThreadRecord, &JKRThread::start, this, (void*)((u32)this->mStackMemory + this->mStackSize), this->mStackSize, threadPrio, OS_THREAD_ATTR_DETACH); +#endif this->mMesgCount = msgCount; this->mMesgBuffer = (OSMessage*)JKRHeap::alloc(mMesgCount * sizeof(OSMessage), 0, this->mHeap); OSInitMessageQueue(&this->mMesgQueue, this->mMesgBuffer, this->mMesgCount); @@ -25,7 +30,11 @@ JKRThread::JKRThread(u32 stackSize, int msgCount, int threadPrio) : mLink(this) JKRThread::JKRThread(OSThread* threadRecord, int msgCount) : mLink(this) { this->mHeap = nullptr; this->mThreadRecord = threadRecord; +#ifdef TARGET_PC + this->mStackSize = (uintptr_t)threadRecord->stackEnd - (uintptr_t)threadRecord->stackBase; +#else this->mStackSize = (u32)threadRecord->stackEnd - (u32)threadRecord->stackBase; +#endif this->mStackMemory = threadRecord->stackBase; this->mMesgCount = msgCount; this->mMesgBuffer = (OSMessage*)JKRHeap::sSystemHeap->alloc(mMesgCount * sizeof(OSMessage), 4); diff --git a/src/static/JSystem/JUtility/JUTConsole.cpp b/src/static/JSystem/JUtility/JUTConsole.cpp index 34fea4f2..314d5ede 100644 --- a/src/static/JSystem/JUtility/JUTConsole.cpp +++ b/src/static/JSystem/JUtility/JUTConsole.cpp @@ -32,7 +32,11 @@ JUTConsole* JUTConsole::create(uint param_0, uint maxLines, JKRHeap* pHeap) { JUTConsole* JUTConsole::create(uint param_0, void* buffer, u32 bufferSize) { JUTConsoleManager* const pManager = JUTConsoleManager::getManager(); JUT_ASSERT(pManager != 0); +#ifdef TARGET_PC + JUT_ASSERT(( (uintptr_t)buffer & 0x3 ) == 0); +#else JUT_ASSERT(( (u32)buffer & 0x3 ) == 0); +#endif u32 maxLines = getLineFromObjectSize(bufferSize, param_0); JUTConsole* newConsole = new (buffer) JUTConsole(param_0, maxLines, false); diff --git a/src/static/JSystem/JUtility/JUTDirectFile.cpp b/src/static/JSystem/JUtility/JUTDirectFile.cpp index 6466041a..cf1bcd61 100644 --- a/src/static/JSystem/JUtility/JUTDirectFile.cpp +++ b/src/static/JSystem/JUtility/JUTDirectFile.cpp @@ -27,7 +27,11 @@ JUTDirectFile::JUTDirectFile() { mLength = 0; mPos = 0; mToRead = 0; +#ifdef TARGET_PC + mSectorStart = (u8*)ALIGN_NEXT((uintptr_t)mBuffer, DVD_MIN_TRANSFER_SIZE); +#else mSectorStart = (u8*)ALIGN_NEXT((u32)mBuffer, DVD_MIN_TRANSFER_SIZE); +#endif mIsOpen = false; } diff --git a/src/static/JSystem/JUtility/JUTException.cpp b/src/static/JSystem/JUtility/JUTException.cpp index 50badb5f..3fc2beee 100644 --- a/src/static/JSystem/JUtility/JUTException.cpp +++ b/src/static/JSystem/JUtility/JUTException.cpp @@ -610,8 +610,13 @@ void JUTException::createFB() { u32 pixel_count = width * height; u32 size = pixel_count * 2; +#ifdef TARGET_PC + void* begin = (void*)ALIGN_PREV((uintptr_t)end - size, 32); + void* object = (void*)ALIGN_PREV((intptr_t)begin - sizeof(JUTExternalFB), 32); +#else void* begin = (void*)ALIGN_PREV((u32)end - size, 32); void* object = (void*)ALIGN_PREV((s32)begin - sizeof(JUTExternalFB), 32); +#endif JUTExternalFB* fb = new (object) JUTExternalFB(renderMode, GX_GM_1_7, begin, size); mDirectPrint->changeFrameBuffer(object); diff --git a/src/static/JSystem/JUtility/JUTGraphFifo.cpp b/src/static/JSystem/JUtility/JUTGraphFifo.cpp index c53fd938..2e931aa1 100644 --- a/src/static/JSystem/JUtility/JUTGraphFifo.cpp +++ b/src/static/JSystem/JUtility/JUTGraphFifo.cpp @@ -16,7 +16,11 @@ JUTGraphFifo::JUTGraphFifo(u32 size) { } else { /** TODO: Figure out what has sizeof 0xA0. */ mBase = JKRAllocFromSysHeap(mSize + 0xA0, 32); +#ifdef TARGET_PC + mBase = (void*)ALIGN_NEXT((uintptr_t)mBase, 32); +#else mBase = (void*)ALIGN_NEXT((u32)mBase, 32); +#endif mFifo = GXInit(mBase, mSize); sInitiated = true; sCurrentFifo = this; diff --git a/src/static/JSystem/JUtility/JUTProcBar.cpp b/src/static/JSystem/JUtility/JUTProcBar.cpp index fe20e2ff..88d268df 100644 --- a/src/static/JSystem/JUtility/JUTProcBar.cpp +++ b/src/static/JSystem/JUtility/JUTProcBar.cpp @@ -232,7 +232,11 @@ void JUTProcBar::drawProcessBar() { } int addrToXPos(void* param_0, int param_1) { +#ifdef TARGET_PC + return param_1 * (((uintptr_t)param_0 - 0x80000000) / (float)JKRHeap::getMemorySize()); +#else return param_1 * (((u32)param_0 - 0x80000000) / (float)JKRHeap::getMemorySize()); +#endif } int byteToXLen(int param_0, int param_1) { diff --git a/src/static/dolphin/ar/ar.c b/src/static/dolphin/ar/ar.c index ecafff65..568f70aa 100644 --- a/src/static/dolphin/ar/ar.c +++ b/src/static/dolphin/ar/ar.c @@ -226,9 +226,9 @@ static void __ARChecksize(void) __DSPRegs[DSP_ARAM_SIZE] = ((__DSPRegs[DSP_ARAM_SIZE] & 0xFFFFFFC0) | ARAM_mode) | 0x20; - test_data = (void*)ALIGN_NEXT((u32)test_data_pad, 0x20); - dummy_data = (void*)ALIGN_NEXT((u32)dummy_data_pad, 0x20); - buffer = (void*)ALIGN_NEXT((u32)buffer_pad, 0x20); + test_data = (void*)ALIGN_NEXT((uintptr_t)test_data_pad, 0x20); + dummy_data = (void*)ALIGN_NEXT((uintptr_t)dummy_data_pad, 0x20); + buffer = (void*)ALIGN_NEXT((uintptr_t)buffer_pad, 0x20); for (i = 0; i < 8; i++) { test_data[i] = 0xDEADBEEF; dummy_data[i] = 0xBAD0BAD0; diff --git a/src/static/dolphin/ar/arq.c b/src/static/dolphin/ar/arq.c index 6c521b29..a6e833f7 100644 --- a/src/static/dolphin/ar/arq.c +++ b/src/static/dolphin/ar/arq.c @@ -98,9 +98,15 @@ void ARQInit(void) } } +#ifdef TARGET_PC +void ARQPostRequest(struct ARQRequest* request, u32 owner, u32 type, + u32 priority, uintptr_t source, uintptr_t dest, u32 length, + ARQCallback callback) +#else void ARQPostRequest(struct ARQRequest* request, u32 owner, u32 type, u32 priority, u32 source, u32 dest, u32 length, ARQCallback callback) +#endif { int level; diff --git a/src/static/initial_menu.c b/src/static/initial_menu.c index 9e1305b2..b7611cad 100644 --- a/src/static/initial_menu.c +++ b/src/static/initial_menu.c @@ -433,7 +433,7 @@ extern void initial_menu_init() { } extern void initial_menu_cleanup() { - int msg; + OSMessage msg; if (Thread_p != NULL) { if (!osRecvMesg(&commandQ, (OSMessage*)&msg, OS_MESSAGE_NOBLOCK)) { diff --git a/src/static/jaudio_NES/game/game64.c_inc b/src/static/jaudio_NES/game/game64.c_inc index c376a41c..d5955500 100644 --- a/src/static/jaudio_NES/game/game64.c_inc +++ b/src/static/jaudio_NES/game/game64.c_inc @@ -584,7 +584,12 @@ f32 SOU_ONGEN_AREA1 = 540.f; f32 SOU_ONGEN_AREA2 = 533.f; f32 sou_md_bgm_boost_pasent = 1.f; +#if defined(TARGET_PC) && UINTPTR_MAX > 0xFFFFFFFFu +/* 64-bit: audio structs with pointer fields are larger, need more heap space */ +u8 audiomemory[0x120000] ATTRIBUTE_ALIGN(32); +#else u8 audiomemory[0x90000] ATTRIBUTE_ALIGN(32); +#endif s16* SOU_FIR_STATE; s16 SOU_FIR_STATE_COPY[12]; @@ -3056,7 +3061,7 @@ u8 Na_MessageSpeedGet() { return sou_message_speed; } -void Na_OngenPos(u32 id, u8 index, u16 angle, f32 distance) { +void Na_OngenPos(uintptr_t id, u8 index, u16 angle, f32 distance) { u8 pan = 0; u8 i = 0; u8 j = 0; @@ -3617,7 +3622,7 @@ extern void Na_KishaStatusTrg(u8 a) { } } -extern void Na_KishaStatusLevel(f32 speed, u32 ongenNum1, u16 angle1, f32 distance1, u32 ongenNum2, u16 angle2, +extern void Na_KishaStatusLevel(f32 speed, uintptr_t ongenNum1, u16 angle1, f32 distance1, uintptr_t ongenNum2, u16 angle2, f32 distance2) { f32 f30 = 0.f; f32 f29 = 0.f; diff --git a/src/static/jaudio_NES/game/melody.c b/src/static/jaudio_NES/game/melody.c index 5ecc883b..234be0e1 100644 --- a/src/static/jaudio_NES/game/melody.c +++ b/src/static/jaudio_NES/game/melody.c @@ -687,7 +687,11 @@ static void Na_MelodyStart(u16 voice, s16 subTrack, const u8* pData) { #endif } - Nap_SetS32(NA_MAKE_COMMAND(0x10, 0x00, subTrack, 0x00), (u64)pData); +#ifdef TARGET_PC + Nap_SetPtr(NA_MAKE_COMMAND(0x10, 0x00, subTrack, 0x00), pData); +#else + Nap_SetS32(NA_MAKE_COMMAND(0x10, 0x00, subTrack, 0x00), (u32)pData); +#endif Nap_SetS8(NA_MAKE_COMMAND(0x06, 0x00, subTrack, 0x02), voice); Nap_SetS8(NA_MAKE_COMMAND(0x06, 0x00, subTrack, 0x00), 0); } @@ -730,7 +734,11 @@ extern void Na_FurnitureInst(u32 id, u8 inst, u8* melody, u16 angle, f32 dist) { u8 pan = angle2pan(angle, dist); f32 vol = distance2vol(dist); - Nap_SetS32(NA_MAKE_COMMAND(0x10, 0x02, sub_track, 0x00), (u64)melody); +#ifdef TARGET_PC + Nap_SetPtr(NA_MAKE_COMMAND(0x10, 0x02, sub_track, 0x00), melody); +#else + Nap_SetS32(NA_MAKE_COMMAND(0x10, 0x02, sub_track, 0x00), (u32)melody); +#endif Nap_SetS8(NA_MAKE_COMMAND(0x06, 0x02, sub_track, 0x02), inst); Nap_SetS8(NA_MAKE_COMMAND(0x06, 0x02, sub_track, 0x00), 0); Nap_SetF32(NA_MAKE_COMMAND(0x01, 0x02, sub_track, 0x00), vol); diff --git a/src/static/jaudio_NES/game/rhythm.c b/src/static/jaudio_NES/game/rhythm.c index a6fadd23..d7eb8794 100644 --- a/src/static/jaudio_NES/game/rhythm.c +++ b/src/static/jaudio_NES/game/rhythm.c @@ -34,8 +34,13 @@ extern void Na_RhythmInit() { rhythm_buffer[i].current_subtrack = i; } +#ifdef TARGET_PC + Nap_SetPtr(NA_MAKE_COMMAND(228, 0, 0, 0), (void*)Na_GetRhythmSeNum); + Nap_SetPtr(NA_MAKE_COMMAND(228, 0, 0, 1), (void*)Na_RhythmGrpProcess); +#else Nap_SetS32(NA_MAKE_COMMAND(228, 0, 0, 0), (s32)Na_GetRhythmSeNum); Nap_SetS32(NA_MAKE_COMMAND(228, 0, 0, 1), (s32)Na_RhythmGrpProcess); +#endif } static NA_RHYTHM_BUFFER* rhythm_buffer_alloc() { diff --git a/src/static/jaudio_NES/internal/aictrl.c b/src/static/jaudio_NES/internal/aictrl.c index d674ed98..70ae7421 100644 --- a/src/static/jaudio_NES/internal/aictrl.c +++ b/src/static/jaudio_NES/internal/aictrl.c @@ -26,6 +26,15 @@ static u8 ext_mixmode = MixMode_Mono; extern void Jac_HeapSetup(void* pHeap, s32 size) { if (pHeap != nullptr) { +#ifdef TARGET_PC +#if UINTPTR_MAX > 0xFFFFFFFFu + /* Capture upper 32 bits of audio heap address for pointer recovery */ + { + extern uintptr_t pc_audio_ptr_base; + pc_audio_ptr_base = (uintptr_t)pHeap & ~(uintptr_t)0xFFFFFFFF; + } +#endif +#endif Nas_HeapInit(&audio_hp, (u8*)pHeap, size); audio_hp_exist = TRUE; } else { @@ -60,7 +69,11 @@ extern void Jac_Init(void) { } AIInit(nullptr); +#ifdef TARGET_PC + AIInitDMA((uintptr_t)dac[2], DAC_SIZE * 2); +#else AIInitDMA((u32)dac[2], DAC_SIZE * 2); +#endif } static void MixMonoTrack(s16* track, s32 nSamples, MixCallback callback) { @@ -282,7 +295,11 @@ extern void Jac_UpdateDAC(void) { } if (use_rsp_madep != nullptr) { +#ifdef TARGET_PC + AIInitDMA((uintptr_t)use_rsp_madep, DAC_SIZE * 2); +#else AIInitDMA((u32)use_rsp_madep, DAC_SIZE * 2); +#endif use_rsp_madep = nullptr; } else { UNIVERSAL_DACCOUNTER++; diff --git a/src/static/jaudio_NES/internal/aramcall.c b/src/static/jaudio_NES/internal/aramcall.c index 3d527488..ef689a44 100644 --- a/src/static/jaudio_NES/internal/aramcall.c +++ b/src/static/jaudio_NES/internal/aramcall.c @@ -103,7 +103,11 @@ void Init_AramMotherHeap(void) inited = TRUE; void* alloc = ARAllocFull(&outSize); +#ifdef TARGET_PC + Jac_InitMotherHeap(&aram_mother, (uintptr_t)alloc, outSize, 0); +#else Jac_InitMotherHeap(&aram_mother, (u32)alloc, outSize, 0); +#endif } } diff --git a/src/static/jaudio_NES/internal/audioconst.c b/src/static/jaudio_NES/internal/audioconst.c index 9da399e7..ad20a805 100644 --- a/src/static/jaudio_NES/internal/audioconst.c +++ b/src/static/jaudio_NES/internal/audioconst.c @@ -29,6 +29,13 @@ na_spec_config NA_SPEC_CONFIG[1] = { }; // clang-format on +#if defined(TARGET_PC) && UINTPTR_MAX > 0xFFFFFFFFu +/* 64-bit: audio structs with pointer fields are larger, need bigger heaps */ +ALGlobalsConst AGC = { + 0x18, 0x30, 0xE0000, 0x70000, 0x50000, +}; +#else ALGlobalsConst AGC = { 0x18, 0x30, 0x70000, 0x38000, 0x28000, }; +#endif diff --git a/src/static/jaudio_NES/internal/bankread.c b/src/static/jaudio_NES/internal/bankread.c index fd7dbedb..d5e79bfd 100644 --- a/src/static/jaudio_NES/internal/bankread.c +++ b/src/static/jaudio_NES/internal/bankread.c @@ -11,6 +11,23 @@ static Bank_* bankp[BANKP_SIZE]; * Address: 8000BE00 * Size: 000024 */ +#ifdef TARGET_PC +static void PTconvert(void** pointer, uintptr_t base_address) +{ + /* ROM data stores 32-bit offsets. On 64-bit, void* is 8 bytes but the + * serialized data has 4-byte values. Read as u32 offset, relocate. */ + u32 offset = *(u32*)pointer; + if (offset == 0) { + *pointer = NULL; + return; + } + if (offset >= (u32)base_address) { + *pointer = (void*)(uintptr_t)offset; + return; + } + *pointer = (void*)(base_address + offset); +} +#else static void PTconvert(void** pointer, u32 base_address) { if (*pointer >= (void*)base_address || *pointer == NULL) { @@ -18,6 +35,7 @@ static void PTconvert(void** pointer, u32 base_address) } *pointer = *(char**)pointer + base_address; } +#endif /* * --INFO-- @@ -27,7 +45,11 @@ static void PTconvert(void** pointer, u32 base_address) Bank_* Bank_Test(u8* ibnk_address) { u32 i, j, k; +#ifdef TARGET_PC + uintptr_t base_addr = (uintptr_t)ibnk_address; +#else u32 base_addr = (u32)ibnk_address; +#endif Bank_* startBank = (Bank_*)(ibnk_address + 0x20); if (startBank->mMagic != 'BANK') { return NULL; diff --git a/src/static/jaudio_NES/internal/driver.c b/src/static/jaudio_NES/internal/driver.c index 9cdc1aee..cc10cc0f 100644 --- a/src/static/jaudio_NES/internal/driver.c +++ b/src/static/jaudio_NES/internal/driver.c @@ -986,7 +986,11 @@ extern Acmd* Nas_SynthMain(s32 chan_id, commonch* common, driverch* driver, s16* return cmd; } else { // This medium is not in ram, so dma the requested sample into ram +#ifdef TARGET_PC + samplesToLoadAddr = (u8*)Nas_WaveDmaCallBack((uintptr_t)(tmpSamplesToLoadAddr), +#else samplesToLoadAddr = (u8*)Nas_WaveDmaCallBack((u32)(tmpSamplesToLoadAddr), +#endif sampleDataChunkSize, flags, &driver->sample_dma_idx, sample->medium); } @@ -1176,7 +1180,11 @@ extern Acmd* Nas_SynthMain(s32 chan_id, commonch* common, driverch* driver, s16* if (!STOP_VELOCONV) { // Load the velocity convolution table into DMEM_0x800 s32 vel_conv_idx = driver->vel_conv_table_idx; +#ifdef TARGET_PC + aLoadBuffer2(cmd++, VELOCONV_TABLE[vel_conv_idx], 0x800, sizeof(VELOCONV_TABLE[vel_conv_idx])); +#else aLoadBuffer2(cmd++, (u32)VELOCONV_TABLE[vel_conv_idx], 0x800, sizeof(VELOCONV_TABLE[vel_conv_idx])); +#endif aUnkCmd3(cmd++, DMEM_TEMP, 0x800, samples_per_update); } diff --git a/src/static/jaudio_NES/internal/dummyrom.c b/src/static/jaudio_NES/internal/dummyrom.c index 9a16c9d9..90922883 100644 --- a/src/static/jaudio_NES/internal/dummyrom.c +++ b/src/static/jaudio_NES/internal/dummyrom.c @@ -27,7 +27,11 @@ extern u32 GetNeosRomTop(void) { } extern u32 GetNeosRom_PreLoaded(void) { +#ifdef TARGET_PC + DVDT_DRAMtoARAM(0, (uintptr_t)init_load_addr, AUDIO_ARAM_TOP, init_load_size, nullptr, nullptr); +#else DVDT_DRAMtoARAM(0, (u32)init_load_addr, AUDIO_ARAM_TOP, init_load_size, nullptr, nullptr); +#endif return init_load_size; } @@ -45,9 +49,17 @@ extern BOOL ARAMStartDMAmesg(u32 dir, u32 dramAddr, u32 aramAddr, u32 size, s32 aramAddr += AUDIO_ARAM_TOP; if (dir == DUMMYROM_ARAM_TO_DRAM) { +#ifdef TARGET_PC + DVDT_ARAMtoDRAM((uintptr_t)mq, dramAddr, aramAddr, size, nullptr, &mesg_finishcall); +#else DVDT_ARAMtoDRAM((u32)mq, dramAddr, aramAddr, size, nullptr, &mesg_finishcall); +#endif } else { +#ifdef TARGET_PC + DVDT_DRAMtoARAM((uintptr_t)mq, dramAddr, aramAddr, size, nullptr, &mesg_finishcall); +#else DVDT_DRAMtoARAM((u32)mq, dramAddr, aramAddr, size, nullptr, &mesg_finishcall); +#endif } return FALSE; diff --git a/src/static/jaudio_NES/internal/dvdthread.c b/src/static/jaudio_NES/internal/dvdthread.c index 0e0a89e5..6fc69107 100644 --- a/src/static/jaudio_NES/internal/dvdthread.c +++ b/src/static/jaudio_NES/internal/dvdthread.c @@ -186,7 +186,7 @@ extern s32 DVDT_LoadtoARAM_Main(void* arg) { /* Copy to ARAM synchronously */ ARQPostRequest(nullptr, 0x12345678, ARQ_TYPE_MRAM_TO_ARAM, ARQ_PRIORITY_HIGH, - (u32)buf, call->dst, readSize, nullptr); + (uintptr_t)buf, call->dst, readSize, nullptr); call->dst += readSize; } @@ -212,7 +212,7 @@ extern s32 DVDT_LoadtoARAM(u32 owner, char* name, u32 dst, u32 src, u32 length, extern s32 DVDT_ARAMtoDRAM_Main(void* arg) { DVDCall* call = (DVDCall*)arg; - ARQPostRequest(nullptr, (u32)call, ARQ_TYPE_ARAM_TO_MRAM, ARQ_PRIORITY_HIGH, + ARQPostRequest(nullptr, (uintptr_t)call, ARQ_TYPE_ARAM_TO_MRAM, ARQ_PRIORITY_HIGH, call->src, call->dst, call->length, nullptr); __DoFinish(call, call->length); return 0; @@ -220,7 +220,7 @@ extern s32 DVDT_ARAMtoDRAM_Main(void* arg) { extern s32 DVDT_DRAMtoARAM_Main(void* arg) { DVDCall* call = (DVDCall*)arg; - ARQPostRequest(nullptr, (u32)call, ARQ_TYPE_MRAM_TO_ARAM, ARQ_PRIORITY_HIGH, + ARQPostRequest(nullptr, (uintptr_t)call, ARQ_TYPE_MRAM_TO_ARAM, ARQ_PRIORITY_HIGH, call->dst, call->src, call->length, nullptr); __DoFinish(call, call->length); return 0; diff --git a/src/static/jaudio_NES/internal/heapctrl.c b/src/static/jaudio_NES/internal/heapctrl.c index e0bd5185..369f0a53 100644 --- a/src/static/jaudio_NES/internal/heapctrl.c +++ b/src/static/jaudio_NES/internal/heapctrl.c @@ -42,9 +42,17 @@ static void ARAM_TO_ARAM_DMA(u32 src, u32 dst, u32 totalSize) while (totalSize != 0) { burstSize = totalSize >= DMABUFFER_SIZE ? DMABUFFER_SIZE : totalSize; +#ifdef TARGET_PC + ARQPostRequest(&request, (uintptr_t)&msgQueue, ARQ_TYPE_ARAM_TO_MRAM, ARQ_PRIORITY_LOW, src, (uintptr_t)dmabuffer, burstSize, &ARAMFinish); +#else ARQPostRequest(&request, (u32)&msgQueue, ARQ_TYPE_ARAM_TO_MRAM, ARQ_PRIORITY_LOW, src, (u32)dmabuffer, burstSize, &ARAMFinish); +#endif OSReceiveMessage(&msgQueue, NULL, OS_MESSAGE_BLOCK); +#ifdef TARGET_PC + ARQPostRequest(&request, (uintptr_t)&msgQueue, ARQ_TYPE_MRAM_TO_ARAM, ARQ_PRIORITY_LOW, (uintptr_t)dmabuffer, dst, burstSize, &ARAMFinish); +#else ARQPostRequest(&request, (u32)&msgQueue, ARQ_TYPE_MRAM_TO_ARAM, ARQ_PRIORITY_LOW, (u32)dmabuffer, dst, burstSize, &ARAMFinish); +#endif OSReceiveMessage(&msgQueue, NULL, OS_MESSAGE_BLOCK); totalSize -= burstSize; @@ -66,16 +74,28 @@ static void DRAM_TO_DRAM_DMA(u32 src, u32 dst, u32 totalSize) u32 dma_buffer_top; u32 burstSize; +#ifdef TARGET_PC + dma_buffer_top = (uintptr_t)JAC_ARAM_DMA_BUFFER_TOP; +#else dma_buffer_top = (u32)JAC_ARAM_DMA_BUFFER_TOP; +#endif OSInitMessageQueue(&msgQueue, &msg, 1); DCFlushRange((void*)src, totalSize); DCInvalidateRange((void*)dst, totalSize); while (totalSize != 0) { burstSize = totalSize >= DMABUFFER_SIZE ? DMABUFFER_SIZE : totalSize; +#ifdef TARGET_PC + ARQPostRequest(&request, (uintptr_t)&msgQueue, ARQ_TYPE_MRAM_TO_ARAM, ARQ_PRIORITY_LOW, src, dma_buffer_top, burstSize, &ARAMFinish); +#else ARQPostRequest(&request, (u32)&msgQueue, ARQ_TYPE_MRAM_TO_ARAM, ARQ_PRIORITY_LOW, src, dma_buffer_top, burstSize, &ARAMFinish); +#endif OSReceiveMessage(&msgQueue, NULL, OS_MESSAGE_BLOCK); +#ifdef TARGET_PC + ARQPostRequest(&request, (uintptr_t)&msgQueue, ARQ_TYPE_ARAM_TO_MRAM, ARQ_PRIORITY_LOW, dma_buffer_top, dst, burstSize, &ARAMFinish); +#else ARQPostRequest(&request, (u32)&msgQueue, ARQ_TYPE_ARAM_TO_MRAM, ARQ_PRIORITY_LOW, dma_buffer_top, dst, burstSize, &ARAMFinish); +#endif OSReceiveMessage(&msgQueue, NULL, OS_MESSAGE_BLOCK); totalSize -= burstSize; diff --git a/src/static/jaudio_NES/internal/ja_calc.c b/src/static/jaudio_NES/internal/ja_calc.c index f6873b3b..52a08041 100644 --- a/src/static/jaudio_NES/internal/ja_calc.c +++ b/src/static/jaudio_NES/internal/ja_calc.c @@ -1,6 +1,6 @@ #include "jaudio_NES/ja_calc.h" -#include "PowerPC_EABI_Support/msl/MSL_C/PPC_EABI/cmath_gcn.h" +#include "PowerPC_EABI_Support/Msl/MSL_C/PPC_EABI/cmath_gcn.h" // #include "std/Math.h" // #include "dolphin/math.h" // #include "stl/math.h" @@ -15,7 +15,7 @@ static f32 SINTABLE[SINTABLE_LENGTH]; */ f32 sqrtf2(f32 x) { - return std::sqrtf(x); + return sqrtf(x); } /* @@ -46,7 +46,7 @@ f32 atanf2(f32 x, f32 y) f32 sinf2(f32 x) { // @fabricated - return std::sinf(x); + return sinf(x); } /* @@ -57,7 +57,7 @@ f32 sinf2(f32 x) void Jac_InitSinTable() { for (u32 i = 0; i < SINTABLE_LENGTH; i++) { - SINTABLE[i] = std::sinf(i * HALF_PI / 256.0f); + SINTABLE[i] = sinf(i * HALF_PI / 256.0f); } } diff --git a/src/static/jaudio_NES/internal/memory.c b/src/static/jaudio_NES/internal/memory.c index fa122383..3f1a24e2 100644 --- a/src/static/jaudio_NES/internal/memory.c +++ b/src/static/jaudio_NES/internal/memory.c @@ -266,8 +266,13 @@ void Nas_HeapInit(ALHeap* heap, u8* p2, s32 p3) { heap->current = NULL; heap->last = NULL; } else { +#ifdef TARGET_PC + length = p3 - ((uintptr_t)p2 & 0x1F); + heap->base = (u8*)ALIGN_NEXT((uintptr_t)p2, 32); +#else length = p3 - ((u32)p2 & 0x1F); heap->base = (u8*)ALIGN_NEXT((u32)p2, 32); +#endif heap->current = heap->base; heap->length = length; heap->last = NULL; @@ -722,6 +727,8 @@ void* __Nas_SzCacheCheck_Inner(s32 tabletype, s32 audioCacheType, s32 id) { case WAVE_TABLE: { heap = &AG.wave_heap; } break; + default: + return NULL; } SZAuto* autoHeap = &heap->auto_heap; if (audioCacheType == 0) { @@ -1369,7 +1376,11 @@ void __RestoreAddr(Wavelookuptable* a, smzwavetable* b) { u8* o = a_sample + a->_08; if (b_sample >= a_sample && b_sample < o) { // fakematch? +#ifdef TARGET_PC + b->sample = (u8*)((uintptr_t)a->_04 + (b->sample - (uintptr_t)a->sample)); +#else b->sample = (u8*)((u32)a->_04 + (b->sample - (u32)a->sample)); +#endif if (EXGTYPE == 0) { b->medium = a->medium; } else { diff --git a/src/static/jaudio_NES/internal/rspsim.c b/src/static/jaudio_NES/internal/rspsim.c index b45ad24c..faa44029 100644 --- a/src/static/jaudio_NES/internal/rspsim.c +++ b/src/static/jaudio_NES/internal/rspsim.c @@ -3,6 +3,14 @@ #include #include "jaudio_NES/sample.h" #include "jaudio_NES/rate.h" + +#ifdef TARGET_PC +#include "pc_audio_ptr.h" +/* Recover full pointer from truncated u32 in audio command */ +#define CMDLO_PTR(cmdLo) pc_audio_recover_ptr(cmdLo) +#else +#define CMDLO_PTR(cmdLo) ((void*)(cmdLo)) +#endif #include "jaudio_NES/audiocommon.h" static u8 DMEM[0x1000] ATTRIBUTE_ALIGN(32); @@ -96,9 +104,9 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { switch (cmdHi >> 24) { case A_CMD_LOADCACHE: // A_LOADCACHE (special to GC?) - sp128 = (u8*)cmdLo; + sp128 = (u8*)CMDLO_PTR(cmdLo); sp12C = cmdHi & 0xFFFF; - DCTouchRange((void*)cmdLo, ((cmdHi >> 16) & 0xFF) * 16); + DCTouchRange(CMDLO_PTR(cmdLo), ((cmdHi >> 16) & 0xFF) * 16); break; case A_CMD_SPNOOP: // A_SPNOOP @@ -114,7 +122,7 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { Jac_bcopy(loop_point, &DMEM[DMEMOut], 16 * sizeof(s16)); } else { // copy from address in command - Jac_bcopy((void*)cmdLo, &DMEM[DMEMOut], 16 * sizeof(s16)); + Jac_bcopy(CMDLO_PTR(cmdLo), &DMEM[DMEMOut], 16 * sizeof(s16)); } s16* var_r17 = (s16*)&DMEM[(u16)(DMEMOut + 32)]; @@ -208,7 +216,7 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { *var_r17++ = sp9C[k]; } } - Jac_bcopy(var_r17 - 16, (void*)cmdLo, 16 * sizeof(s16)); + Jac_bcopy(var_r17 - 16, CMDLO_PTR(cmdLo), 16 * sizeof(s16)); break; } @@ -237,7 +245,7 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { Jac_bzero(spC, 8 * sizeof(s16)); var_r7 = 0; } else { - Jac_bcopy((void*)cmdLo, spC, 8 * sizeof(s16)); + Jac_bcopy(CMDLO_PTR(cmdLo), spC, 8 * sizeof(s16)); var_r7 = spC[4] & 0x7FFF; } var_r4 = (s16*)&DMEM[DMEMIn]; @@ -287,7 +295,7 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { *var_r6++ = var_r15; } spC[var_r8] = var_r7 & 0x7FFF; - Jac_bcopy(&spC[var_r8 - 4], (void*)cmdLo, 8 * sizeof(s16)); + Jac_bcopy(&spC[var_r8 - 4], CMDLO_PTR(cmdLo), 8 * sizeof(s16)); break; } @@ -338,7 +346,7 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { } case A_CMD_LOADADPCM: // A_LOADADPCM - Jac_bcopy((void*)cmdLo, ADPCM_BOOKBUF, cmdHi & 0xFFFF); + Jac_bcopy(CMDLO_PTR(cmdLo), ADPCM_BOOKBUF, cmdHi & 0xFFFF); ADPCM_BOOKBUF_SIZE = cmdHi & 0xFFFF; break; @@ -395,7 +403,7 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { break; case A_CMD_SETLOOP: // A_SETLOOP - loop_point = (void*)cmdLo; + loop_point = CMDLO_PTR(cmdLo); break; case A_CMD_UNK16: { // ??? @@ -428,13 +436,13 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { case A_CMD_LOADBUFFER2: { // A_LOADBUFF2 u16 size = ((cmdHi >> 16) & 0xFF) * 16; - Jac_bcopy((void*)cmdLo, (s16*)&DMEM[cmdHi & 0xFFFF], size); + Jac_bcopy(CMDLO_PTR(cmdLo), (s16*)&DMEM[cmdHi & 0xFFFF], size); break; } case A_CMD_SAVEBUFFER2: { // A_SAVEBUFF2 u16 size = ((cmdHi >> 16) & 0xFF) * 16; - Jac_bcopy(DMEM_OFS(cmdHi & 0xFFFF), (void*)cmdLo, size); + Jac_bcopy(DMEM_OFS(cmdHi & 0xFFFF), CMDLO_PTR(cmdLo), size); break; } @@ -584,7 +592,7 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { Jac_bcopy(loop_point, DMEM_OFS(DMEMOut), 16 * sizeof(s16)); } else { // copy from address in command - Jac_bcopy((void*)cmdLo, DMEM_OFS(DMEMOut), 16 * sizeof(s16)); + Jac_bcopy(CMDLO_PTR(cmdLo), DMEM_OFS(DMEMOut), 16 * sizeof(s16)); } u16 temp1 = DMEMOut + 32; @@ -598,7 +606,7 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { u16 temp2 = DMEMOut; temp2 += 32; - Jac_bcopy(&DMEM[temp2 - 32], (void*)cmdLo, 32); + Jac_bcopy(&DMEM[temp2 - 32], CMDLO_PTR(cmdLo), 32); break; } @@ -617,7 +625,7 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { flags = cmdHi >> 16; if (flags & 2) { - sp120 = (s16*)cmdLo; + sp120 = (s16*)CMDLO_PTR(cmdLo); sp124 = (cmdHi & 0xFFFF) >> 1; } else { var_r14_3 = (s16*)&DMEM[cmdHi & 0xFFFF]; @@ -626,7 +634,7 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { sp3C[j] = 0; } } else { - Jac_bcopy((void*)cmdLo, sp3C, 16 * sizeof(s16)); + Jac_bcopy(CMDLO_PTR(cmdLo), sp3C, 16 * sizeof(s16)); } for (j = 0; j < 8; j++) { sp1C[j] = sp120[j] >> 3; @@ -652,7 +660,7 @@ extern s32 RspStart(u32* pTaskCmds, s32 allTasks) { var_r8_3 = 0; } } - Jac_bcopy(sp3C, (void*)cmdLo, 16 * sizeof(s16)); + Jac_bcopy(sp3C, CMDLO_PTR(cmdLo), 16 * sizeof(s16)); } break; } diff --git a/src/static/jaudio_NES/internal/sub_sys.c b/src/static/jaudio_NES/internal/sub_sys.c index 38a1d40f..37577bd7 100644 --- a/src/static/jaudio_NES/internal/sub_sys.c +++ b/src/static/jaudio_NES/internal/sub_sys.c @@ -127,15 +127,15 @@ static void Nap_AudioSysProcess(AudioPort* port) { AG.main_group.subtracks[0]->changes.flags.volume = TRUE; break; case AUDIOCMD_SET_VFRAME_CALLBACK: - NA_VFRAME_CALLBACK = (VFRAME_CALLBACK)port->param.asU32; + NA_VFRAME_CALLBACK = (VFRAME_CALLBACK)port->param.asVoidPtr; break; case AUDIOCMD_SET_CALLBACK: if (port->command.arg2 == AUDIO_CALLBACK_SOUND) { - NA_SOUND_CALLBACK = (SOUND_CALLBACK)port->param.asU32; + NA_SOUND_CALLBACK = (SOUND_CALLBACK)port->param.asVoidPtr; } else if (port->command.arg2 == AUDIO_CALLBACK_DACOUT) { - NA_DACOUT_CALLBACK = (DACOUT_CALLBACK)port->param.asU32; + NA_DACOUT_CALLBACK = (DACOUT_CALLBACK)port->param.asVoidPtr; } else { - AG.seq_callbacks[port->command.arg2] = (SequenceCallback)port->param.asU32; + AG.seq_callbacks[port->command.arg2] = (SequenceCallback)port->param.asVoidPtr; } break; case AUDIOCMD_SET_PERC_BANK: @@ -214,6 +214,9 @@ static void Nap_PortSet(u32 data, s32* param_p) { AudioPort* port_p = &AG.audio_port_cmds[AG.thread_cmd_write_pos & 0xFF]; port_p->raw_cmd = data; +#ifdef TARGET_PC + port_p->param.asVoidPtr = NULL; /* Clear full pointer-width before writing 4-byte param */ +#endif port_p->param.asS32 = *param_p; AG.thread_cmd_write_pos++; @@ -230,6 +233,20 @@ extern void Nap_SetS32(u32 cmd, s32 param) { Nap_PortSet(cmd, (s32*)¶m); } +#ifdef TARGET_PC +extern void Nap_SetPtr(u32 cmd, void* ptr) { + AudioPort* port_p = &AG.audio_port_cmds[AG.thread_cmd_write_pos & 0xFF]; + + port_p->raw_cmd = cmd; + port_p->param.asVoidPtr = ptr; + + AG.thread_cmd_write_pos++; + if (AG.thread_cmd_write_pos == AG.thread_cmd_read_pos) { + AG.thread_cmd_write_pos--; + } +} +#endif + extern void Nap_SetS8(u32 cmd, s8 param) { u32 mod_param; #ifdef TARGET_PC diff --git a/src/static/jaudio_NES/internal/system.c b/src/static/jaudio_NES/internal/system.c index df1328e4..61e80d32 100644 --- a/src/static/jaudio_NES/internal/system.c +++ b/src/static/jaudio_NES/internal/system.c @@ -12,6 +12,8 @@ #include #ifdef TARGET_PC #include +#include +#include #endif #define MK_BGLOAD_MSG(retData, tableType, id, loadStatus) \ @@ -238,6 +240,414 @@ static void pc_swap_perc_ptr_array(u32* perc_tbl, s32 n_perc) { } static u32 pc_swap_bank_init_count = 0; + +/*=== GC-compatible struct layouts for 64-bit ROM data parsing === + * On GC, sizeof(void*)==4. These structs use u32 for pointer fields + * so they match the GC binary layout exactly (even on 64-bit). */ + +typedef struct { + u32 bitfield; /* 0x00 */ + u32 sample; /* 0x04 */ + u32 loop; /* 0x08 */ + u32 book; /* 0x0C */ +} smzwavetable_gc; + +typedef struct { + u32 wavetable; /* 0x00 */ + f32 tuning; /* 0x04 */ +} wtstr_gc; + +typedef struct { + u8 adsr_decay_idx; /* 0x00 */ + u8 pan; /* 0x01 */ + u8 is_relocated; /* 0x02 */ + u8 _pad; /* 0x03 */ + wtstr_gc tuned_sample; /* 0x04 */ + u32 envelope; /* 0x0C */ +} perctable_gc; + +typedef struct { + u8 is_relocated; /* 0x00 */ + u8 normal_range_low; /* 0x01 */ + u8 normal_range_high; /* 0x02 */ + u8 adsr_decay_idx; /* 0x03 */ + u32 envelope; /* 0x04 */ + wtstr_gc low_pitch_tuned_sample; /* 0x08 */ + wtstr_gc normal_pitch_tuned_sample; /* 0x10 */ + wtstr_gc high_pitch_tuned_sample; /* 0x18 */ +} voicetable_gc; + +typedef struct { + wtstr_gc tuned_sample; /* 0x00 */ +} percvoicetable_gc; + +/* --- GC-struct byte-swap helpers --- */ + +static void pc_swap_perctable_gc(perctable_gc* pt) { + swap32_inplace(&pt->tuned_sample.wavetable); + swap32_inplace(&pt->tuned_sample.tuning); + swap32_inplace(&pt->envelope); +} + +static void pc_swap_voicetable_gc(voicetable_gc* vt) { + swap32_inplace(&vt->envelope); + swap32_inplace(&vt->low_pitch_tuned_sample.wavetable); + swap32_inplace(&vt->low_pitch_tuned_sample.tuning); + swap32_inplace(&vt->normal_pitch_tuned_sample.wavetable); + swap32_inplace(&vt->normal_pitch_tuned_sample.tuning); + swap32_inplace(&vt->high_pitch_tuned_sample.wavetable); + swap32_inplace(&vt->high_pitch_tuned_sample.tuning); +} + +static void pc_swap_percvoicetable_gc(percvoicetable_gc* pvt) { + swap32_inplace(&pvt->tuned_sample.wavetable); + swap32_inplace(&pvt->tuned_sample.tuning); +} + +static void pc_swap_smzwavetable_gc(smzwavetable_gc* wt) { + swap32_inplace(&wt->bitfield); + swap32_inplace(&wt->sample); + swap32_inplace(&wt->loop); + swap32_inplace(&wt->book); +} + +/* --- Visited map for wavetable deduplication on 64-bit --- */ +#define PC_WT_VISITED_MAX 512 +static struct { void* gc_addr; smzwavetable* native; } pc_wt_visited[PC_WT_VISITED_MAX]; +static u32 pc_wt_visited_count = 0; + +static smzwavetable* pc_find_visited_wt(void* gc_addr) { + for (u32 i = 0; i < pc_wt_visited_count; i++) { + if (pc_wt_visited[i].gc_addr == gc_addr) return pc_wt_visited[i].native; + } + return NULL; +} + +static void pc_add_visited_wt(void* gc_addr, smzwavetable* native) { + if (pc_wt_visited_count < PC_WT_VISITED_MAX) { + pc_wt_visited[pc_wt_visited_count].gc_addr = gc_addr; + pc_wt_visited[pc_wt_visited_count].native = native; + pc_wt_visited_count++; + } +} + +/** + * 64-bit __WaveTouch replacement. + * Takes a native wtstr* whose wavetable field holds a u32 offset (zero-extended), + * reads the GC-layout smzwavetable_gc from ctrl_p, and creates a new native + * smzwavetable with properly widened pointer fields. + */ +static void __WaveTouch_PC(wtstr* wavetouch_str, uintptr_t ram_addr, WaveMedia* wave_media) { + u32 wt_ofs = (u32)(uintptr_t)wavetouch_str->wavetable; + smzwavetable_gc* gc_wt; + smzwavetable* native_wt; + u32 gc_bitfield; + u32 gc_is_relocated; + + if (wt_ofs == 0) return; + + /* Point to the GC wavetable data in the ctrl buffer */ + gc_wt = (smzwavetable_gc*)(ram_addr + (uintptr_t)wt_ofs); + + /* Check visited map first */ + native_wt = pc_find_visited_wt(gc_wt); + if (native_wt != NULL) { + wavetouch_str->wavetable = native_wt; + return; + } + + /* Check if already relocated (raw BE check before swap). + * Bitfield layout: [31]bit31 | [30:28]codec | [27:26]medium | [25]bit26 | [24]is_relocated | [23:0]size + * is_relocated is bit 24, NOT bit 25 (bit 25 is "bit26" flag). */ + gc_bitfield = gc_wt->bitfield; + { + u32 be_val = BSWAP32(gc_bitfield); + gc_is_relocated = (be_val >> 24) & 1; + } + /* Also check if it was already swapped and relocated (LE check) */ + if (!gc_is_relocated) { + gc_is_relocated = (gc_bitfield >> 24) & 1; + } + + if (gc_is_relocated) { + /* This shouldn't normally happen on first pass since we reset visited, + * but handle it gracefully */ + wavetouch_str->wavetable = NULL; + return; + } + + /* Byte-swap the GC wavetable fields */ + pc_swap_smzwavetable_gc(gc_wt); + + /* Allocate and fill the native smzwavetable */ + native_wt = (smzwavetable*)malloc(sizeof(smzwavetable)); + if (native_wt == NULL) return; + + /* Parse bitfield from the (now LE) gc_wt->bitfield: + * On LE after swap, the bits are in LE order. The original BE layout is: + * bit31(1) | codec(3) | medium(2) | bit26(1) | is_relocated(1) | size(24) + * After byte-swap to LE, the u32 value has the same numeric value as BE. + * We need to extract the same fields: + * size = bits[0:23], is_relocated = bit24, bit26 = bit25, medium = bits[26:27], + * codec = bits[28:30], bit31 = bit31 + * Wait, BE bit numbering: MSB=bit31. The BE layout is: + * [31] bit31 | [30:28] codec | [27:26] medium | [25] bit26 | [24] is_relocated | [23:0] size + * After swap to LE, the u32 value is the same numerical value. */ + { + u32 bf = gc_wt->bitfield; + native_wt->size = bf & 0xFFFFFF; + native_wt->is_relocated = (bf >> 24) & 1; + native_wt->bit26 = (bf >> 25) & 1; + native_wt->medium = (bf >> 26) & 3; + native_wt->codec = (bf >> 28) & 7; + native_wt->bit31 = (bf >> 31) & 1; + } + + /* Convert pointer fields (u32 offsets -> relocated pointers) */ + native_wt->sample = (u8*)(uintptr_t)gc_wt->sample; + native_wt->loop = (adpcmloop*)(uintptr_t)gc_wt->loop; + native_wt->book = (adpcmbook*)(uintptr_t)gc_wt->book; + + /* Mark GC data as relocated to prevent re-processing */ + gc_wt->bitfield |= (1 << 24); /* set is_relocated bit in LE layout */ + + /* Add to visited map */ + pc_add_visited_wt(gc_wt, native_wt); + + if (native_wt->size != 0) { + /* Relocate loop pointer */ + native_wt->loop = (adpcmloop*)(ram_addr + (uintptr_t)native_wt->loop); + pc_swap_adpcmloop(native_wt->loop); + + /* Relocate book pointer */ + native_wt->book = (adpcmbook*)(ram_addr + (uintptr_t)native_wt->book); + pc_swap_adpcmbook(native_wt->book); + + /* Relocate sample pointer based on medium */ + switch (native_wt->medium) { + case MEDIUM_RAM: + native_wt->sample = (u8*)((uintptr_t)native_wt->sample + (uintptr_t)wave_media->wave0_p); + native_wt->medium = wave_media->wave0_media; + break; + case MEDIUM_DISK: + native_wt->sample = (u8*)((uintptr_t)native_wt->sample + (uintptr_t)wave_media->wave1_p); + native_wt->medium = wave_media->wave1_media; + break; + case MEDIUM_CART: + case MEDIUM_DISK_DRIVE: + break; + } + + native_wt->is_relocated = TRUE; + if (native_wt->bit26 && native_wt->medium != MEDIUM_RAM && + AG.num_used_samples < ARRAY_COUNT(AG.used_samples)) { + AG.used_samples[AG.num_used_samples++] = native_wt; + } + } + + wavetouch_str->wavetable = native_wt; +} + +/** + * 64-bit replacement for Nas_BankOfsToAddr_Inner. + * Reads GC-layout structs from ctrl_p and creates new native structs with + * properly widened pointer fields. + */ +static void Nas_BankOfsToAddr_Inner_PC(s32 bank_id, u8* ctrl_p, WaveMedia* wave_media) { + s32 i; + s32 n_voice_inst = AG.voice_info[bank_id].num_instruments; + s32 n_perc_inst = AG.voice_info[bank_id].num_drums; + s32 n_sfx_inst = AG.voice_info[bank_id].num_sfx; + + /* Reset visited arrays */ + pc_wt_visited_count = 0; + pc_envdat_bank_visited_count = 0; + pc_book_visited_count = 0; + pc_loop_visited_count = 0; + + /* The offset table at the start of ctrl_p has already been byte-swapped + * by pc_swap_bank_ctrl_offsets (flat u32 array, no pointer issues). + * Entry[0] = perc base offset, Entry[1] = sfx base offset, + * Entry[2..] = instrument offsets. */ + + /* === Percussion === */ + { + u32 perc_base_ofs = ((u32*)ctrl_p)[0]; + if (perc_base_ofs != 0 && n_perc_inst != 0) { + u32* perc_gc_array = (u32*)(ctrl_p + perc_base_ofs); + + /* Byte-swap the percussion pointer array (u32 offsets) */ + pc_swap_perc_ptr_array(perc_gc_array, n_perc_inst); + + /* Allocate native pointer array */ + perctable** new_perc_array = (perctable**)calloc(n_perc_inst, sizeof(perctable*)); + + for (i = 0; i < n_perc_inst; i++) { + u32 perc_ofs = perc_gc_array[i]; + perctable_gc* gc; + perctable* native; + + if (perc_ofs == 0) continue; + + gc = (perctable_gc*)(ctrl_p + perc_ofs); + + /* Check if already relocated (shared percussion entries) */ + if (gc->is_relocated) { + /* Find the previously created native entry */ + s32 j; + for (j = 0; j < i; j++) { + if (new_perc_array[j] != NULL) { + perctable_gc* prev_gc = (perctable_gc*)(ctrl_p + perc_gc_array[j]); + if (prev_gc == gc) { + new_perc_array[i] = new_perc_array[j]; + break; + } + } + } + continue; + } + + /* Byte-swap GC struct fields */ + pc_swap_perctable_gc(gc); + + /* Allocate and populate native perctable */ + native = (perctable*)calloc(1, sizeof(perctable)); + native->adsr_decay_idx = gc->adsr_decay_idx; + native->pan = gc->pan; + native->is_relocated = FALSE; + native->tuned_sample.wavetable = (smzwavetable*)(uintptr_t)gc->tuned_sample.wavetable; + native->tuned_sample.tuning = gc->tuned_sample.tuning; + native->envelope = (envdat*)(uintptr_t)gc->envelope; + + /* Relocate wavetable via __WaveTouch_PC */ + __WaveTouch_PC(&native->tuned_sample, (uintptr_t)ctrl_p, wave_media); + + /* Relocate envelope */ + { + u32 env_ofs = (u32)(uintptr_t)native->envelope; + native->envelope = (envdat*)((uintptr_t)ctrl_p + (uintptr_t)env_ofs); + pc_swap_envdat(native->envelope); + } + + native->is_relocated = TRUE; + gc->is_relocated = TRUE; + new_perc_array[i] = native; + } + + AG.voice_info[bank_id].percussion = new_perc_array; + } else { + AG.voice_info[bank_id].percussion = NULL; + } + } + + /* === SFX (effects) === */ + { + u32 sfx_base_ofs = ((u32*)ctrl_p)[1]; + if (sfx_base_ofs != 0 && n_sfx_inst != 0) { + u8* sfx_gc_base = ctrl_p + sfx_base_ofs; + + /* Allocate contiguous native array */ + percvoicetable* new_sfx_array = (percvoicetable*)calloc(n_sfx_inst, sizeof(percvoicetable)); + + for (i = 0; i < n_sfx_inst; i++) { + percvoicetable_gc* gc = (percvoicetable_gc*)(sfx_gc_base + i * sizeof(percvoicetable_gc)); + + /* Byte-swap GC entry */ + pc_swap_percvoicetable_gc(gc); + + /* Copy to native */ + new_sfx_array[i].tuned_sample.wavetable = (smzwavetable*)(uintptr_t)gc->tuned_sample.wavetable; + new_sfx_array[i].tuned_sample.tuning = gc->tuned_sample.tuning; + + /* Relocate wavetable if non-null */ + if (gc->tuned_sample.wavetable != 0) { + __WaveTouch_PC(&new_sfx_array[i].tuned_sample, (uintptr_t)ctrl_p, wave_media); + } + } + + AG.voice_info[bank_id].effects = new_sfx_array; + } else { + AG.voice_info[bank_id].effects = NULL; + } + } + + /* === Instruments === */ + { + s32 n_voice = n_voice_inst; + if (n_voice > 126) n_voice = 126; + + /* Allocate native pointer array */ + voicetable** new_inst_array = (voicetable**)calloc(n_voice, sizeof(voicetable*)); + + for (i = 0; i < n_voice; i++) { + u32 inst_ofs = ((u32*)ctrl_p)[2 + i]; + voicetable_gc* gc; + voicetable* native; + + if (inst_ofs == 0) continue; + + gc = (voicetable_gc*)(ctrl_p + inst_ofs); + + /* Check if already relocated (shared instrument entries) */ + if (gc->is_relocated) { + /* Find the previously created native entry */ + s32 j; + for (j = 0; j < i; j++) { + if (new_inst_array[j] != NULL) { + u32 prev_ofs = ((u32*)ctrl_p)[2 + j]; + if (prev_ofs == inst_ofs) { + new_inst_array[i] = new_inst_array[j]; + break; + } + } + } + continue; + } + + /* Byte-swap GC struct fields */ + pc_swap_voicetable_gc(gc); + + /* Allocate and populate native voicetable */ + native = (voicetable*)calloc(1, sizeof(voicetable)); + native->is_relocated = FALSE; + native->normal_range_low = gc->normal_range_low; + native->normal_range_high = gc->normal_range_high; + native->adsr_decay_idx = gc->adsr_decay_idx; + native->envelope = (envdat*)(uintptr_t)gc->envelope; + + native->low_pitch_tuned_sample.wavetable = (smzwavetable*)(uintptr_t)gc->low_pitch_tuned_sample.wavetable; + native->low_pitch_tuned_sample.tuning = gc->low_pitch_tuned_sample.tuning; + + native->normal_pitch_tuned_sample.wavetable = (smzwavetable*)(uintptr_t)gc->normal_pitch_tuned_sample.wavetable; + native->normal_pitch_tuned_sample.tuning = gc->normal_pitch_tuned_sample.tuning; + + native->high_pitch_tuned_sample.wavetable = (smzwavetable*)(uintptr_t)gc->high_pitch_tuned_sample.wavetable; + native->high_pitch_tuned_sample.tuning = gc->high_pitch_tuned_sample.tuning; + + /* Relocate wavetables */ + if (native->normal_range_low != 0) { + __WaveTouch_PC(&native->low_pitch_tuned_sample, (uintptr_t)ctrl_p, wave_media); + } + __WaveTouch_PC(&native->normal_pitch_tuned_sample, (uintptr_t)ctrl_p, wave_media); + if (native->normal_range_high != 0x7F) { + __WaveTouch_PC(&native->high_pitch_tuned_sample, (uintptr_t)ctrl_p, wave_media); + } + + /* Relocate envelope */ + { + u32 env_ofs = (u32)(uintptr_t)native->envelope; + native->envelope = (envdat*)((uintptr_t)ctrl_p + (uintptr_t)env_ofs); + pc_swap_envdat(native->envelope); + } + + native->is_relocated = TRUE; + gc->is_relocated = TRUE; + new_inst_array[i] = native; + } + + AG.voice_info[bank_id].instruments = new_inst_array; + } +} #endif /* TARGET_PC */ static s32 Nas_GetSyncDummy(u8* param0, s32 param1); @@ -261,7 +671,11 @@ static s32 __Nas_StartSeq(s32 group_idx, s32 seq_id, s32 param); static u8* __Load_Bank(s32 table_type, s32 id, s32* did_alloc); static u32 __Load_Wave(s32 wave_id, u32* medium, s32 no_load); static void* __Check_Cache(s32 table_type, s32 id); +#ifdef TARGET_PC +static void __WaveTouch(wtstr* wavetouch_str, uintptr_t ram_addr, WaveMedia* wave_media); +#else static void __WaveTouch(wtstr* wavetouch_str, u32 ram_addr, WaveMedia* wave_media); +#endif static Bgload* Nas_BgCopyDisk(s32 dev_medium, u8* src, u8* dst, u32 size, s32 medium, s32 n_chunks, OSMesgQueue* mq, s32 msg); static Bgload* Nas_BgCopyReq(u8* src, u8* dst, u32 size, s32 medium, s32 n_chunks, OSMesgQueue* mq, s32 msg); @@ -570,7 +984,11 @@ void Nas_BankHeaderInit(ArcHeader* header, u8* data, u16 medium) { for (i = 0; i < header->numEntries; i++) { if (header->entries[i].size != 0 && header->entries[i].medium == MEDIUM_CART) { +#ifdef TARGET_PC + header->entries[i].addr += (uintptr_t)data; +#else header->entries[i].addr += (u32)data; +#endif } } } @@ -759,7 +1177,11 @@ void Nas_SetExtPointer(s32 table_type, s32 idx, s32 param_3, s32 data) { if (header->entries[idx].medium == MEDIUM_RAM_UNLOADED) { switch (param_3) { case EXT_TYPE_DATA: +#ifdef TARGET_PC + header->entries[idx].addr = (uintptr_t)data; +#else header->entries[idx].addr = (u32)data; +#endif break; case EXT_TYPE_SIZE: header->entries[idx].size = data; @@ -855,7 +1277,11 @@ static u32 __Load_Wave(s32 wave_id, u32* medium, s32 no_load) { } *medium = MEDIUM_RAM; +#ifdef TARGET_PC + return (uintptr_t)ram_p; +#else return (u32)ram_p; +#endif } if (header->entries[wave_id].cacheType == CACHE_LOAD_EITHER_NOSYNC || no_load == TRUE) { @@ -866,7 +1292,11 @@ static u32 __Load_Wave(s32 wave_id, u32* medium, s32 no_load) { ram_p = __Load_Bank(WAVE_TABLE, wave_id, &no_load); if (ram_p != NULL) { *medium = MEDIUM_RAM; +#ifdef TARGET_PC + return (uintptr_t)ram_p; +#else return (u32)ram_p; +#endif } *medium = header->entries[wave_id].medium; @@ -1023,6 +1453,20 @@ static u8* __Load_Bank(s32 table_type, s32 id, s32* did_alloc) { static s32 __Link_BankNum(s32 type, s32 id) { ArcHeader* header = __Get_ArcHeader(type); +#ifdef TARGET_PC + if (header == NULL) { + fprintf(stderr, "[__Link_BankNum] FATAL: NULL header for type=%d id=%d\n", type, id); + fflush(stderr); + return id; + } + if (id < 0 || id >= header->numEntries) { + fprintf(stderr, "[__Link_BankNum] WARN: id=%d out of range (numEntries=%d, type=%d)\n", + id, header->numEntries, type); + fflush(stderr); + return id; + } +#endif + if (header->entries[id].size == 0) { id = header->entries[id].addr; } @@ -1059,12 +1503,21 @@ static ArcHeader* __Get_ArcHeader(s32 table_type) { } } +#ifdef TARGET_PC +#define OFS2RAM(base, ofs) ((uintptr_t)(ofs) + (uintptr_t)base) +#define BANK_ENTRY(ctrl, idx) (((u32*)((uintptr_t)ctrl)) + idx) +#else #define OFS2RAM(base, ofs) ((u32)(ofs) + (u32)base) #define BANK_ENTRY(ctrl, idx) (((u32*)((u32)ctrl)) + idx) +#endif static void Nas_BankOfsToAddr_Inner(s32 bank_id, u8* ctrl_p, WaveMedia* wave_media) { u32 ofs; +#ifdef TARGET_PC + uintptr_t inst_ofs; +#else u32 inst_ofs; +#endif voicetable* inst; perctable* percvt; percvoicetable* sfx; @@ -1083,6 +1536,9 @@ static void Nas_BankOfsToAddr_Inner(s32 bank_id, u8* ctrl_p, WaveMedia* wave_med pc_swap_bank_ctrl_offsets(ctrl_p, n_ctrl_entries); pc_swap_bank_init_count++; } + /* On 64-bit, use the GC-layout-aware PC version that allocates new native structs */ + Nas_BankOfsToAddr_Inner_PC(bank_id, ctrl_p, wave_media); + return; #endif ofs = *BANK_ENTRY(ctrl_p, 0); @@ -1095,12 +1551,20 @@ static void Nas_BankOfsToAddr_Inner(s32 bank_id, u8* ctrl_p, WaveMedia* wave_med #endif for (i = 0; i < n_perc_inst; i++) { +#ifdef TARGET_PC + inst_ofs = (uintptr_t)((perctable**)*BANK_ENTRY(ctrl_p, 0))[i]; +#else inst_ofs = (u32)((perctable**)*BANK_ENTRY(ctrl_p, 0))[i]; +#endif if (inst_ofs == 0) { continue; // empty percussion/drum entry } +#ifdef TARGET_PC + inst_ofs += (uintptr_t)ctrl_p; // OFS2RAM(ctrl_p, ofs); +#else inst_ofs += (u32)ctrl_p; // OFS2RAM(ctrl_p, ofs); +#endif percvt = (perctable*)inst_ofs; ((perctable**)*BANK_ENTRY(ctrl_p, 0))[i] = percvt; @@ -1113,8 +1577,16 @@ static void Nas_BankOfsToAddr_Inner(s32 bank_id, u8* ctrl_p, WaveMedia* wave_med #ifdef TARGET_PC pc_swap_perctable(percvt); #endif +#ifdef TARGET_PC + __WaveTouch(&percvt->tuned_sample, (uintptr_t)ctrl_p, wave_media); +#else __WaveTouch(&percvt->tuned_sample, (u32)ctrl_p, wave_media); +#endif +#ifdef TARGET_PC + inst_ofs = (uintptr_t)percvt->envelope; +#else inst_ofs = (u32)percvt->envelope; +#endif percvt->envelope = (envdat*)OFS2RAM(ctrl_p, inst_ofs); #ifdef TARGET_PC pc_swap_envdat(percvt->envelope); @@ -1137,7 +1609,11 @@ static void Nas_BankOfsToAddr_Inner(s32 bank_id, u8* ctrl_p, WaveMedia* wave_med #endif for (i = 0; i < n_sfx_inst; i++) { +#ifdef TARGET_PC + inst_ofs = (uintptr_t)(((percvoicetable*)*BANK_ENTRY(ctrl_p, 1)) + i); +#else inst_ofs = (u32)(((percvoicetable*)*BANK_ENTRY(ctrl_p, 1)) + i); +#endif sfx = (percvoicetable*)inst_ofs; // check for null sfx or null sample wave table pointer @@ -1145,7 +1621,11 @@ static void Nas_BankOfsToAddr_Inner(s32 bank_id, u8* ctrl_p, WaveMedia* wave_med continue; } +#ifdef TARGET_PC + __WaveTouch(&sfx->tuned_sample, (uintptr_t)ctrl_p, wave_media); +#else __WaveTouch(&sfx->tuned_sample, (u32)ctrl_p, wave_media); +#endif } } @@ -1167,18 +1647,34 @@ static void Nas_BankOfsToAddr_Inner(s32 bank_id, u8* ctrl_p, WaveMedia* wave_med #endif // Optional low pitch sample if (inst->normal_range_low != 0) { +#ifdef TARGET_PC + __WaveTouch(&inst->low_pitch_tuned_sample, (uintptr_t)ctrl_p, wave_media); +#else __WaveTouch(&inst->low_pitch_tuned_sample, (u32)ctrl_p, wave_media); +#endif } // Standard sample, required by all instruments +#ifdef TARGET_PC + __WaveTouch(&inst->normal_pitch_tuned_sample, (uintptr_t)ctrl_p, wave_media); +#else __WaveTouch(&inst->normal_pitch_tuned_sample, (u32)ctrl_p, wave_media); +#endif // Optional high pitch sample if (inst->normal_range_high != 0x7F) { +#ifdef TARGET_PC + __WaveTouch(&inst->high_pitch_tuned_sample, (uintptr_t)ctrl_p, wave_media); +#else __WaveTouch(&inst->high_pitch_tuned_sample, (u32)ctrl_p, wave_media); +#endif } +#ifdef TARGET_PC + inst_ofs = (uintptr_t)inst->envelope; +#else inst_ofs = (u32)inst->envelope; +#endif inst->envelope = (envdat*)OFS2RAM(ctrl_p, inst_ofs); #ifdef TARGET_PC pc_swap_envdat(inst->envelope); @@ -1297,7 +1793,7 @@ static s32 Nas_StartDma(OSIoMesg* ioMsg, s32 priority, s32 direction, u32 device /* device_addr is an ARAM offset (relative to audiorom start). * GetNeosRomTop() gives the base ARAM address for audiorom data. */ u32 aram_offset = device_addr + GetNeosRomTop(); - ARStartDMA(1 /* ARAM→MRAM */, (u32)dram_addr, aram_offset, size); + ARStartDMA(1 /* ARAM→MRAM */, (uintptr_t)dram_addr, aram_offset, size); /* Send completion message so callers that do Z_osRecvMesg(BLOCK) unblock */ if (mq != NULL) { @@ -1357,9 +1853,16 @@ static u8* __Load_Bank_BG(s32 table_type, s32 id, s32 n_chunks, s32 ret_data, OS s32 loadStatus; s8 cachePolicy; s32 asyncLoadStatus; - s32 link_id = __Link_BankNum(table_type, id); + s32 link_id; voiceinfo* vinfo; +#ifdef TARGET_PC + if (table_type < 0 || table_type > WAVE_TABLE) { + return NULL; + } +#endif + link_id = __Link_BankNum(table_type, id); + switch (table_type) { case SEQUENCE_TABLE: if (AG.sequence_load_status[link_id] == LOAD_STATUS_IN_PROGRESS) { @@ -2024,7 +2527,11 @@ static void __Nas_BgDiskCopy(u8* src, u8* dst, u32 size, s32 param) { // nothing } +#ifdef TARGET_PC +static void __WaveTouch(wtstr* wavetouch_str, uintptr_t ram_addr, WaveMedia* wave_media) { +#else static void __WaveTouch(wtstr* wavetouch_str, u32 ram_addr, WaveMedia* wave_media) { +#endif smzwavetable* wavetable; void* reloc; @@ -2036,7 +2543,7 @@ static void __WaveTouch(wtstr* wavetouch_str, u32 ram_addr, WaveMedia* wave_medi * pointers are < OS_BASE_CACHED (0x80000000), so use a simpler check: * if the offset is small enough to be a valid offset, relocate it. */ { - u32 wt_ofs = (u32)wavetouch_str->wavetable; + uintptr_t wt_ofs = (uintptr_t)wavetouch_str->wavetable; if (wt_ofs != 0 && wt_ofs < 0x10000000) { /* Not yet relocated — relocate now */ reloc = (void*)(wt_ofs + ram_addr); @@ -2068,22 +2575,22 @@ static void __WaveTouch(wtstr* wavetouch_str, u32 ram_addr, WaveMedia* wave_medi pc_swap_smzwavetable(wavetable); if (wavetable->size != 0) { - reloc = (void*)((u32)wavetable->loop + ram_addr); + reloc = (void*)((uintptr_t)wavetable->loop + ram_addr); wavetable->loop = (adpcmloop*)reloc; pc_swap_adpcmloop(wavetable->loop); - reloc = (void*)((u32)wavetable->book + ram_addr); + reloc = (void*)((uintptr_t)wavetable->book + ram_addr); wavetable->book = (adpcmbook*)reloc; pc_swap_adpcmbook(wavetable->book); switch (wavetable->medium) { case MEDIUM_RAM: - reloc = (void*)((u32)wavetable->sample + (u32)wave_media->wave0_p); + reloc = (void*)((uintptr_t)wavetable->sample + (uintptr_t)wave_media->wave0_p); wavetable->sample = (u8*)reloc; wavetable->medium = wave_media->wave0_media; break; case MEDIUM_DISK: - reloc = (void*)((u32)wavetable->sample + (u32)wave_media->wave1_p); + reloc = (void*)((uintptr_t)wavetable->sample + (uintptr_t)wave_media->wave1_p); wavetable->sample = (u8*)reloc; wavetable->medium = wave_media->wave1_media; break; diff --git a/src/static/jaudio_NES/internal/waveread.c b/src/static/jaudio_NES/internal/waveread.c index d02e5bbe..ed3ba153 100644 --- a/src/static/jaudio_NES/internal/waveread.c +++ b/src/static/jaudio_NES/internal/waveread.c @@ -17,6 +17,25 @@ CtrlGroup_* CGRP_ARRAY[16]; * Size: 000038 */ +#ifdef TARGET_PC +static void PTconvert(void** pointer, uintptr_t base_address) +{ + /* ROM data stores 32-bit offsets. On 64-bit, void* is 8 bytes but the + * serialized data has 4-byte values. Read as u32 offset, relocate. */ + u32 offset = *(u32*)pointer; + if (offset == 0) { + *pointer = NULL; + return; + } + if (offset >= (u32)base_address) { + /* Already an absolute address (or larger than base) — leave as-is + * but widen to pointer */ + *pointer = (void*)(uintptr_t)offset; + return; + } + *pointer = (void*)(base_address + offset); +} +#else static void PTconvert(void** pointer, u32 base_address) { if (*pointer == NULL) { @@ -28,6 +47,7 @@ static void PTconvert(void** pointer, u32 base_address) } *pointer = *(char**)pointer + base_address; } +#endif /* * --INFO-- @@ -36,7 +56,11 @@ static void PTconvert(void** pointer, u32 base_address) */ CtrlGroup_* Wave_Test(u8* data) { +#ifdef TARGET_PC + uintptr_t base_addr = (uintptr_t)data; +#else u32 base_addr = (u32)data; +#endif CtrlGroup_* group; SCNE_* scene; Ctrl_* cst; @@ -47,10 +71,24 @@ CtrlGroup_* Wave_Test(u8* data) WaveArchiveBank_* arcBank; WaveArchive_* arc; +#ifdef TARGET_PC + /* ROM data has 32-bit pointer fields at fixed offsets regardless of + * native pointer size. Read as u32 offsets and relocate manually. */ + { + u32 arcBank_off = *(u32*)(data + 0x10); + u32 group_off = *(u32*)(data + 0x14); + arcBank = arcBank_off ? (WaveArchiveBank_*)(base_addr + arcBank_off) : NULL; + group = group_off ? (CtrlGroup_*)(base_addr + group_off) : NULL; + /* Write back relocated pointers for later use via struct fields */ + ((Wsys_*)data)->waveArcBank = arcBank; + ((Wsys_*)data)->ctrlGroup = group; + } +#else PTconvert((void**)&((Wsys_*)data)->waveArcBank, base_addr); PTconvert((void**)&((Wsys_*)data)->ctrlGroup, base_addr); arcBank = *(WaveArchiveBank_**)(data + 0x10); group = *(CtrlGroup_**)(data + 0x14); +#endif CGRP_ARRAY[0] = group; if (arcBank->magic != 'WINF') { diff --git a/src/static/jsyswrap.cpp b/src/static/jsyswrap.cpp index f65ed778..7f5a57c6 100644 --- a/src/static/jsyswrap.cpp +++ b/src/static/jsyswrap.cpp @@ -456,6 +456,17 @@ extern u32 JW_GetAramAddress(int res_no) { address = JC_JKRAramArchive_getAramAddress_byName(forest_arc_aram2_p, (u32)'DATA', aram_resName[res_no]); } +#ifdef TARGET_PC + { + static int aram_log = 0; + if (0 && aram_log < 40) { /* disabled */ + aram_log++; + fprintf(stderr, "[ARAM_ADDR] res_no=%d name=%s addr=0x%x\n", + res_no, (res_no >= 0 && res_no < RESOURCE_NUM) ? aram_resName[res_no] : "?", address); + } + } +#endif + return address; } @@ -490,7 +501,12 @@ extern void JW_Init() { void* arena_hi = OSGetArenaHi(); void* arena_lo = OSGetArenaLo(); +#ifdef TARGET_PC + /* Overhead is larger on 64-bit due to wider pointers in JKR heap structs */ + SystemHeapSize = (uintptr_t)arena_hi - (uintptr_t)arena_lo - 0x200; +#else SystemHeapSize = (u32)arena_hi - (u32)arena_lo - 0xD0; +#endif JC_JFWSystem_setMaxStdHeap(1); JC_JFWSystem_setSysHeapSize(SystemHeapSize); JC_JFWSystem_setFifoBufSize(0x10001); diff --git a/src/static/libc64/__osMalloc.c b/src/static/libc64/__osMalloc.c index 15af4ed6..97415027 100644 --- a/src/static/libc64/__osMalloc.c +++ b/src/static/libc64/__osMalloc.c @@ -6,11 +6,11 @@ #define OS_MALLOC_MAGIC (s16)'ss' // magic number for an OSMemBlock #define OS_MALLOC_BLOCK_OK(block) ((block) != NULL && (block)->magic == OS_MALLOC_MAGIC) // check if OSMemBlock structure is OK -#define OS_MALLOC_DATA2BLOCK(data) ((OSMemBlock*)((u32)(data) - sizeof(OSMemBlock))) // get memblock data pointer from OSMemBlock +#define OS_MALLOC_DATA2BLOCK(data) ((OSMemBlock*)((uintptr_t)(data) - sizeof(OSMemBlock))) // get memblock data pointer from OSMemBlock #define OS_MALLOC_BLOCK2DATA(block) ((u8*)(block) + sizeof(OSMemBlock)) // get OSMemBlock pointer from data // Gets the pointer to the next OSMemBlock immediately following this block in RAM, may or may not be a valid OSMemBlock -#define OS_MALLOC_NEXTMEMBLOCK(block) ((OSMemBlock*)((u32)(block) + sizeof(OSMemBlock) + (block)->size)) +#define OS_MALLOC_NEXTMEMBLOCK(block) ((OSMemBlock*)((uintptr_t)(block) + sizeof(OSMemBlock) + (block)->size)) int __osMalloc_FreeBlockTest_Enable = FALSE; @@ -89,8 +89,8 @@ extern void __osMallocAddBlock(OSArena* arena, u8* base, s32 size) { OSMemBlock* last; if (base != NULL) { - block = (OSMemBlock*)ALIGN_NEXT((u32)base, 32); - align_size = ALIGN_PREV(size - ((u32)block - (u32)base), 32); + block = (OSMemBlock*)ALIGN_NEXT((uintptr_t)base, 32); + align_size = ALIGN_PREV(size - ((uintptr_t)block - (uintptr_t)base), 32); if (align_size > (int)sizeof(OSMemBlock)) { memset(block, 0xAB, align_size); @@ -191,9 +191,9 @@ static void* __osMallocAlign_NoLock(OSArena* arena, u32 size, u32 align) { mask = align - 1; while (block != NULL) { if (block->free) { - remain = ((u32)block + sizeof(OSMemBlock)) & mask; + remain = ((uintptr_t)block +sizeof(OSMemBlock)) & mask; alignment_bytes = remain == 0 ? 0 : align - remain; - aligned_block = (OSMemBlock*)((u32)block + alignment_bytes); + aligned_block = (OSMemBlock*)((uintptr_t)block +alignment_bytes); if (block->size - alignment_bytes >= size) { if (arena->flags & OSArena_FLAG_FREE_BLOCK_TEST) { @@ -217,7 +217,7 @@ static void* __osMallocAlign_NoLock(OSArena* arena, u32 size, u32 align) { } if (block->size > full_size) { - new_next = (OSMemBlock*)((u32)block + full_size); + new_next = (OSMemBlock*)((uintptr_t)block +full_size); new_next->next = get_block_next(block); new_next->prev = block; new_next->size = block->size - full_size; @@ -284,7 +284,7 @@ extern void* __osMallocR(OSArena* arena, u32 size) { } if (block->size > full_size) { - next = (OSMemBlock*)((u32)block + block->size - size); + next = (OSMemBlock*)((uintptr_t)block +block->size - size); next->next = get_block_next(block); next->prev = block; next->size = size; @@ -419,7 +419,7 @@ extern void* __osRealloc(OSArena* arena, void* ptr, u32 size) { next = get_block_next(orig_block); need_size = size - orig_block->size; if (next == OS_MALLOC_NEXTMEMBLOCK(orig_block) && next->free && next->size >= need_size) { - OSMemBlock* new_next = (OSMemBlock*)((u32)next + need_size); + OSMemBlock* new_next = (OSMemBlock*)((uintptr_t)next + need_size); next->size -= need_size; temp = get_block_next(next); if (temp != NULL) { diff --git a/src/static/libc64/math64.c b/src/static/libc64/math64.c index ce72be2e..f8ab62ac 100644 --- a/src/static/libc64/math64.c +++ b/src/static/libc64/math64.c @@ -5,7 +5,7 @@ f32 fatan2(f32 x, f32 y) { return atan2(x, y); } -f32 fsqrt(f32 x) { +f32 game_fsqrt(f32 x) { return sqrtf(x); } diff --git a/src/static/libforest/emu64/emu64.c b/src/static/libforest/emu64/emu64.c index fbf340a1..c9ea1579 100644 --- a/src/static/libforest/emu64/emu64.c +++ b/src/static/libforest/emu64/emu64.c @@ -15,8 +15,41 @@ #ifdef TARGET_PC #include "pc_platform.h" +extern "C" void pc_gx_flush_if_begin_complete(void); static jmp_buf pc_dl_crash_jmpbuf; + +/* On 64-bit, Gwords.w1 is uintptr_t (at offset 8) while union member structs + * have their second u32 field at offset 4 (in the padding). So union views + * can't access w1 data. Use GFX_W1_U32 for reading w1 as u32, and + * GFX_COMPACT / GFX_COMPACT_P for building a temporary 8-byte buffer that + * can be cast to union view types (Gsettile, Gsetcolor, etc.). */ +#if UINTPTR_MAX > 0xFFFFFFFFu +#define GFX_W1_U32(gfx_ref) ((u32)(gfx_ref).words.w1) +/* Build a packed 8-byte {w0,w1} buffer from a widened Gfx, suitable for + * casting to any of the original 8-byte union member structs. */ +#define GFX_COMPACT(varname, gfx_ptr) \ + u32 varname[2]; \ + varname[0] = (gfx_ptr)->words.w0; \ + varname[1] = (u32)(gfx_ptr)->words.w1 +/* Same but from the this->gfx copy */ +#define GFX_COMPACT_SELF(varname) \ + u32 varname[2]; \ + varname[0] = this->gfx.words.w0; \ + varname[1] = (u32)this->gfx.words.w1 +#else +#define GFX_W1_U32(gfx_ref) ((gfx_ref).words.w1) +#define GFX_COMPACT(varname, gfx_ptr) \ + u32* varname = (u32*)(gfx_ptr) +#define GFX_COMPACT_SELF(varname) \ + u32* varname = (u32*)&this->gfx +#endif +#else +#define GFX_W1_U32(gfx_ref) ((gfx_ref).words.w1) +#define GFX_COMPACT(varname, gfx_ptr) \ + u32* varname = (u32*)(gfx_ptr) +#define GFX_COMPACT_SELF(varname) \ + u32* varname = (u32*)&this->gfx #endif // this pragma may be unnecessary @@ -405,7 +438,7 @@ static u32 texture_cache_get_heap_size(texture_cache_t* cache) { static void* texture_cache_alloc(texture_cache_t* cache, u32 size) { cache->last_alloc_start = cache->buffer_current; - cache->last_alloc_end = (u8*)ALIGN_NEXT((u32)cache->buffer_current + size, 32); + cache->last_alloc_end = (u8*)ALIGN_NEXT((uintptr_t)cache->buffer_current + size, 32); if (cache->buffer_pos < cache->last_alloc_end - cache->buffer_start) { cache->buffer_pos = cache->last_alloc_end - cache->buffer_start; @@ -3093,6 +3126,13 @@ void emu64::draw_rectangle(Gtexrect2* texrect) { s1 = (center + (s_end - this->settilesize_dolphin_cmds[tile].sl / 16.0f)) / (int)this->texture_info[tile].width; t1 = (center + (t_end - this->settilesize_dolphin_cmds[tile].tl / 16.0f)) / (int)this->texture_info[tile].height; + /* Save current projection — draw_rectangle overwrites it with its own + ortho, but subsequent polygon rendering (e.g. mFont text on the FONT + display list) needs the original projection to be restored. */ + Mtx44 saved_proj; + int saved_proj_type = this->projection_type; + bcopy(this->projection_mtx, saved_proj, sizeof(Mtx44)); + GXSetProjection(this->ortho_mtx, GX_ORTHOGRAPHIC); GXSetCurrentMtx(GX_PNMTX0); @@ -3148,6 +3188,12 @@ void emu64::draw_rectangle(Gtexrect2* texrect) { GXEnd(); } + /* Restore projection so subsequent polygon rendering uses the correct matrix */ + bcopy(saved_proj, this->projection_mtx, sizeof(Mtx44)); + this->projection_type = saved_proj_type; + GXSetProjection(this->projection_mtx, (GXProjectionType)this->projection_type); + this->dirty_flags[EMU64_DIRTY_FLAG_PROJECTION_MTX] = true; + this->rdp_pipe_sync_needed = true; } @@ -3165,6 +3211,16 @@ void emu64::dirty_check(int tile, int n_tiles, int do_texture_matrix) { EMU64_TIMED_SEGMENT_BEGIN(); EMU64_ASSERTLINE_DEBUG(this, 4826); +#ifdef TARGET_PC + /* Flush any pending GX batch BEFORE changing state. + * Without this, a pending batch (from the previous draw) gets flushed + * mid-dirty_check when the first GX state call triggers + * pc_gx_flush_if_begin_complete(). At that point, texture/combine/etc. + * may already be partially updated for the NEW draw, causing the previous + * batch to render with wrong textures. */ + pc_gx_flush_if_begin_complete(); +#endif + if (IS_DIRTY(EMU64_DIRTY_FLAG_PRIM_COLOR)) { EMU64_TIMED_SEGMENT_BEGIN(); CLEAR_DIRTY(EMU64_DIRTY_FLAG_PRIM_COLOR); @@ -3324,7 +3380,10 @@ void emu64::dirty_check(int tile, int n_tiles, int do_texture_matrix) { GXSetChanCtrl(GX_ALPHA0, GX_FALSE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE); } } else { - GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE); + /* When G_SHADE is off, N64 ignores vertex colors (shade defaults to white). + * Use GX_SRC_REG so the channel doesn't pull black vertex colors. */ + int mat_src = (this->geometry_mode & G_SHADE) ? GX_SRC_VTX : GX_SRC_REG; + GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_REG, mat_src, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE); } EMU64_TIMED_SEGMENT_END(dirty_light_time); @@ -3454,7 +3513,7 @@ void emu64::dl_G_DL(void) { static char s[256]; Gfx* gfx = this->gfx_p; - this->work_ptr = (void*)this->seg2k0(gfx->dma.addr); + this->work_ptr = (void*)this->seg2k0(gfx->words.w1); #ifdef TARGET_PC if (this->work_ptr == NULL) { return; @@ -3477,7 +3536,7 @@ void emu64::dl_G_DL(void) { case G_DL_PUSH: if (this->segment_set != false) { this->segment_set = false; - sprintf(s, "%s", this->segchk(gfx->dma.addr)); + sprintf(s, "%s", this->segchk(gfx->words.w1)); this->Printf0(VT_COL(RED, WHITE) "gsSPDisplayList(%s),\n" VT_RST, s); emu64::warningString[EMU64_WARN_IDX_DL] = s; emu64::warningTime[EMU64_WARN_IDX_DL] = EMU64_WARN_TIME; @@ -3485,16 +3544,16 @@ void emu64::dl_G_DL(void) { } if (this->DL_stack_level < DL_MAX_STACK_LEVEL) { - this->DL_stack[this->DL_stack_level++] = (u32)(this->gfx_p + 1); + this->DL_stack[this->DL_stack_level++] = (uintptr_t)(this->gfx_p + 1); } else { this->err_count++; this->Printf0("*** DL stack overflow ***\n"); } - this->gfx_p = (Gfx*)((int)this->work_ptr - sizeof(Gfx)); + this->gfx_p = (Gfx*)((uintptr_t)this->work_ptr - sizeof(Gfx)); break; case G_DL_NOPUSH: - this->gfx_p = (Gfx*)((u32)this->work_ptr - sizeof(Gfx)); + this->gfx_p = (Gfx*)((uintptr_t)this->work_ptr - sizeof(Gfx)); break; default: if (this->disable_polygons == false) { @@ -3509,7 +3568,18 @@ void emu64::dl_G_RDPHALF_1(void) { } void emu64::dl_G_TEXRECT() { +#if UINTPTR_MAX > 0xFFFFFFFFu + /* Gtexrect2 spans 3 Gfx commands (24 bytes in original 8-byte format). + * Build a compact buffer from the widened Gfx entries. */ + u32 _texrect_buf[6] = { + this->gfx_p[0].words.w0, (u32)this->gfx_p[0].words.w1, + this->gfx_p[1].words.w0, (u32)this->gfx_p[1].words.w1, + this->gfx_p[2].words.w0, (u32)this->gfx_p[2].words.w1 + }; + Gtexrect2* texrect_p = (Gtexrect2*)_texrect_buf; +#else Gtexrect2* texrect_p = (Gtexrect2*)this->gfx_p; +#endif #ifdef EMU64_DEBUG if (this->print_commands != false) { @@ -3571,7 +3641,7 @@ void emu64::dl_G_ENDDL() { } void emu64::dl_G_SETTILE() { - Gsettile* settile = (Gsettile*)this->gfx_p; + Gsettile* settile = (Gsettile*)EMU64_GFX_COMPACT_PTR; #ifdef EMU64_DEBUG if (this->print_commands != false) { @@ -3677,7 +3747,11 @@ void emu64::dl_G_SETTILE_DOLPHIN() { this->settilesize_dolphin_cmds[tile].isDolphin = 1; /* Set texture info for use in GC texture object initialization */ +#ifdef TARGET_PC + this->texture_info[tile].img_addr = (void*)this->resolved_imgaddr; +#else this->texture_info[tile].img_addr = (void*)this->now_setimg.setimg2.imgaddr; +#endif this->texture_info[tile].format = this->now_setimg.setimg2.fmt; this->texture_info[tile].size = this->now_setimg.setimg2.siz; this->texture_info[tile].width = EXPAND_WIDTH(this->now_setimg.setimg2.wd); @@ -3688,7 +3762,7 @@ void emu64::dl_G_SETTILE_DOLPHIN() { } void emu64::dl_G_LOADTILE() { - Gloadtile& loadtile = this->gfx_p->loadtile; + Gloadtile& loadtile = *(Gloadtile*)EMU64_GFX_COMPACT_PTR; #ifdef EMU64_DEBUG if (this->print_commands) { @@ -3702,7 +3776,11 @@ void emu64::dl_G_LOADTILE() { return; /* Determine tmem base address */ +#ifdef TARGET_PC + uintptr_t dram = this->resolved_imgaddr; +#else u32 dram = this->now_setimg.setimg2.imgaddr; +#endif dram += ((loadtile.tl / 4) * EXPAND_WIDTH(this->now_setimg.setimg2.wd) + (loadtile.sl / 4) << this->now_setimg.setimg2.siz) / 2; @@ -3729,8 +3807,12 @@ void emu64::dl_G_LOADTILE() { void emu64::dl_G_LOADBLOCK() { int tmem_idx; - Gloadblock* loadblock = (Gloadblock*)this->gfx_p; + Gloadblock* loadblock = (Gloadblock*)EMU64_GFX_COMPACT_PTR; +#ifdef TARGET_PC + uintptr_t addr; +#else u32 addr; +#endif int i; #ifdef EMU64_DEBUG @@ -3746,7 +3828,11 @@ void emu64::dl_G_LOADBLOCK() { return; /* Does not support LOAD commands */ tmem_idx = this->settile_cmds[loadblock->tile].tmem / 4; +#ifdef TARGET_PC + addr = this->resolved_imgaddr; +#else addr = this->now_setimg.setimg2.imgaddr; +#endif for (i = tmem_idx; i < tmem_idx + (loadblock->sh + 1) / 16; i++) { tmem_map[i].addr = (void*)addr; tmem_map[i].loadblock = *loadblock; @@ -3760,7 +3846,7 @@ void emu64::dl_G_LOADBLOCK() { } void emu64::dl_G_SETTILESIZE() { - Gsettilesize* settilesize = (Gsettilesize*)this->gfx_p; + Gsettilesize* settilesize = (Gsettilesize*)EMU64_GFX_COMPACT_PTR; u32 w0 = this->gfx.words.w0; u32 w1 = this->gfx.words.w1; int tile; @@ -3821,7 +3907,7 @@ extern "C" u16 s_tlut_first_word[16]; #endif void emu64::dl_G_LOADTLUT() { - Gloadtlut_dolphin* loadtlut_dol = (Gloadtlut_dolphin*)this->gfx_p; + Gloadtlut_dolphin* loadtlut_dol = (Gloadtlut_dolphin*)EMU64_GFX_COMPACT_PTR; u16 count; void* tlut_addr; u32 tlut_name; @@ -3830,13 +3916,14 @@ void emu64::dl_G_LOADTLUT() { EMU64_TIMED_SEGMENT_BEGIN(); if (loadtlut_dol->type == 2) { + uintptr_t tlut_w1 = this->gfx_p->words.w1; /* Full pointer from w1 */ EMU64_LOGF("gsDPLoadTLUT_Dolphin(%d, %d, %s),", loadtlut_dol->tlut_name, loadtlut_dol->count, - this->segchk(loadtlut_dol->tlut_addr)); + this->segchk(tlut_w1)); if (this->disable_polygons == false) { count = loadtlut_dol->count & 0x3FFF; tlut_name = loadtlut_dol->tlut_name; - tlut_addr = (void*)this->seg2k0(loadtlut_dol->tlut_addr); + tlut_addr = (void*)this->seg2k0(tlut_w1); if (tlut_addr == this->tlut_addresses[tlut_name]) { /* Translation: ### Same TLUT address */ @@ -3885,18 +3972,23 @@ void emu64::dl_G_LOADTLUT() { } } else { Gfx* loadtlut = this->gfx_p; + Gloadtlut* loadtlut_v = (Gloadtlut*)EMU64_GFX_COMPACT_PTR; - EMU64_LOGF("gsDPLoadTLUTCmd(%d,%d),", loadtlut->loadtlut.tile, (loadtlut->words.w1 >> 14) & 0x3FF); + EMU64_LOGF("gsDPLoadTLUTCmd(%d,%d),", loadtlut_v->tile, (loadtlut->words.w1 >> 14) & 0x3FF); - Gsettile* settile_p = &this->settile_cmds[loadtlut->loadtlut.tile]; + Gsettile* settile_p = &this->settile_cmds[loadtlut_v->tile]; if (this->disable_polygons == false) { u16 count = ((loadtlut->words.w1 >> 14) & 0x3FF) + 1; void* tlut; +#ifdef TARGET_PC + uintptr_t addr = this->resolved_imgaddr; +#else u32 addr = this->now_setimg.setimg2.imgaddr; +#endif u32 tlut_name = (settile_p->tmem / 16) & 0xF; - if (addr == (u32)this->tlut_addresses[tlut_name]) { + if (addr == (uintptr_t)this->tlut_addresses[tlut_name]) { /* Translation: ### Same TLUT address %08x %d */ EMU64_INFOF("### 同じTLUTアドレスです %08x %d\n", addr, tlut_name); #ifdef TARGET_PC @@ -3944,72 +4036,120 @@ void emu64::dl_G_LOADTLUT() { } void emu64::dl_G_SETCOMBINE_NOTEV() { +#if defined(TARGET_PC) && UINTPTR_MAX > 0xFFFFFFFFu + /* On 64-bit, reconstruct the packed 64-bit combine value from w0 and w1 */ + u64 combine_val = ((u64)this->gfx.words.w0) | ((u64)(u32)this->gfx.words.w1 << 32); + /* Fix cmd to G_SETCOMBINE */ + combine_val = (combine_val & ~((u64)0xFF << 24)) | ((u64)G_SETCOMBINE << 24); +#else u64* combine = (u64*)&this->gfx; +#endif s8 print_commands = this->print_commands; if (print_commands) { +#if defined(TARGET_PC) && UINTPTR_MAX > 0xFFFFFFFFu + this->print_combine(combine_val); +#else this->print_combine(*combine); +#endif } /* Update combiner settings only if it changed */ +#if defined(TARGET_PC) && UINTPTR_MAX > 0xFFFFFFFFu + if (*(u64*)&this->combine_gfx != combine_val) { + *(u64*)&this->combine_gfx = combine_val; + this->dirty_flags[EMU64_DIRTY_FLAG_COMBINE] = true; + } +#else ((Gsetcombine_new*)combine)->cmd = G_SETCOMBINE; if (*(u64*)&this->combine_gfx != *combine) { *(u64*)&this->combine_gfx = *combine; this->dirty_flags[EMU64_DIRTY_FLAG_COMBINE] = true; } +#endif } void emu64::dl_G_SETCOMBINE() { +#if defined(TARGET_PC) && UINTPTR_MAX > 0xFFFFFFFFu + u64 combine_val = ((u64)this->gfx.words.w0) | ((u64)(u32)this->gfx.words.w1 << 32); +#else u64* combine = (u64*)&this->gfx; +#endif s8 print_commands = this->print_commands; if (print_commands) { +#if defined(TARGET_PC) && UINTPTR_MAX > 0xFFFFFFFFu + this->print_combine(combine_val); +#else this->print_combine(*combine); +#endif } /* Update combiner settings only if it changed */ +#if defined(TARGET_PC) && UINTPTR_MAX > 0xFFFFFFFFu + if (*(u64*)&this->combine_gfx != combine_val) { + *(u64*)&this->combine_gfx = combine_val; + this->dirty_flags[EMU64_DIRTY_FLAG_COMBINE] = true; + } +#else if (*(u64*)&this->combine_gfx != *combine) { *(u64*)&this->combine_gfx = *combine; this->dirty_flags[EMU64_DIRTY_FLAG_COMBINE] = true; } +#endif /* N64 Combiner -> GC TEV */ - if (this->gfx_cmd != G_SETCOMBINE_NOTEV && aflags[AFLAGS_SKIP_COMBINE_TEV] == 0) { #ifdef TARGET_PC - /* On PC, convert the writable combine_gfx copy instead of the - read-only display list data. combine_tev() will then see - G_SETCOMBINE_TEV and use the proper TEV color/alpha inputs. */ - this->replace_combine_to_tev(&this->combine_gfx); + /* On PC, skip replace_combine_to_tev — the Gsetcombine_tev bitfield + layout is endian-dependent and produces garbled TEV inputs on LE. + Instead, combine() will use combine_auto/combine_manual which + translate N64 combine modes to GX TEV calls directly. */ #else + if (this->gfx_cmd != G_SETCOMBINE_NOTEV && aflags[AFLAGS_SKIP_COMBINE_TEV] == 0) { this->replace_combine_to_tev(this->gfx_p); -#endif } +#endif } void emu64::dl_G_SETCOMBINE_TEV() { +#if defined(TARGET_PC) && UINTPTR_MAX > 0xFFFFFFFFu + u64 combine_tev_val = ((u64)this->gfx.words.w0) | ((u64)(u32)this->gfx.words.w1 << 32); +#else u64* combine_tev = (u64*)&this->gfx; +#endif s8 print_commands = this->print_commands; if (print_commands) { +#if defined(TARGET_PC) && UINTPTR_MAX > 0xFFFFFFFFu + this->print_combine_tev(combine_tev_val); +#else this->print_combine_tev(*combine_tev); +#endif } /* Update combiner settings only if it changed */ +#if defined(TARGET_PC) && UINTPTR_MAX > 0xFFFFFFFFu + if (*(u64*)&this->combine_gfx != combine_tev_val) { + *(u64*)&this->combine_gfx = combine_tev_val; + this->dirty_flags[EMU64_DIRTY_FLAG_COMBINE] = true; + } +#else if (*(u64*)&this->combine_gfx != *combine_tev) { *(u64*)&this->combine_gfx = *combine_tev; this->dirty_flags[EMU64_DIRTY_FLAG_COMBINE] = true; } +#endif } void emu64::dl_G_SETOTHERMODE_H() { - Gsetothermode_dolphin* othermodeH = (Gsetothermode_dolphin*)&this->gfx.setothermodeH; + Gsetothermode_dolphin* othermodeH = (Gsetothermode_dolphin*)EMU64_GFX_COMPACT_PTR; u32 sft; u32 len; u32 data; len = othermodeH->len + 1; sft = (32 - othermodeH->sft) - len; - data = othermodeH->data; + data = GFX_W1_U32(this->gfx); if ((this->print_commands & EMU64_PRINTF2_FLAG) != 0) { for (int i = 0; i < ARRAY_COUNT(h_tbl); i++) { @@ -4043,9 +4183,9 @@ void emu64::dl_G_SETOTHERMODE_L() { u32 len; u32 data; - len = ((Gsetothermode_dolphin*)&this->gfx)->len + 1; - sft = (32 - ((Gsetothermode_dolphin*)&this->gfx)->sft) - len; - data = this->gfx.setothermodeL.data; + len = ((Gsetothermode_dolphin*)EMU64_GFX_COMPACT_PTR)->len + 1; + sft = (32 - ((Gsetothermode_dolphin*)EMU64_GFX_COMPACT_PTR)->sft) - len; + data = GFX_W1_U32(this->gfx); if ((this->print_commands & EMU64_PRINTF2_FLAG) != 0) { if ((int)sft == G_MDSFT_RENDERMODE) { @@ -4141,7 +4281,7 @@ void emu64::dl_G_RDPSETOTHERMODE() { void emu64::dl_G_SETSCISSOR() { u8 print_commands = this->print_commands; - Gscissor* scissor = (Gscissor*)this->gfx_p; + Gscissor* scissor = (Gscissor*)EMU64_GFX_COMPACT_PTR; #ifdef EMU64_DEBUG @@ -4182,7 +4322,7 @@ void emu64::dl_G_SETSCISSOR() { } void emu64::dl_G_FILLRECT() { - Gfillrect2* fillrect = (Gfillrect2*)this->gfx_p; + Gfillrect2* fillrect = (Gfillrect2*)EMU64_GFX_COMPACT_PTR; EMU64_LOGF("gsDPFillRectangle(%d, %d, %d, %d),", fillrect->x1, fillrect->y1, fillrect->x0, fillrect->y0); @@ -4225,18 +4365,18 @@ void emu64::dl_G_SETCIMG() { } this->Printf1("gsDPSetColorImage(G_IM_FMT_%s, G_IM_SIZ_%s, %d, %s),", s_fmt, s_siz, - EXPAND_WIDTH(this->gfx.setimg.wd), this->segchk(this->gfx.setimg.dram)); + EXPAND_WIDTH(this->gfx.setimg.wd), this->segchk(this->gfx.words.w1)); } } #endif } void emu64::dl_G_SETZIMG() { - EMU64_WARNF("gsDPSetDepthImage(%s),", this->segchk(this->gfx.setimg.dram)); + EMU64_WARNF("gsDPSetDepthImage(%s),", this->segchk(this->gfx.words.w1)); } void emu64::dl_G_SETTIMG() { - Gsetimg2* setimg2 = (Gsetimg2*)this->gfx_p; + Gsetimg2* setimg2 = (Gsetimg2*)EMU64_GFX_COMPACT_PTR; #ifdef EMU64_DEBUG if (this->print_commands & EMU64_PRINT_FLAG_ENABLE) { @@ -4272,7 +4412,7 @@ void emu64::dl_G_SETTIMG() { } this->Printf2("gsDPSetTextureImage(G_IM_FMT_%s, G_IM_SIZ_%s, %d, %s),", s_fmt, s_siz, - EXPAND_WIDTH(setimg->wd), this->segchk(setimg->dram)); + EXPAND_WIDTH(setimg->wd), this->segchk(this->gfx_p->words.w1)); } } else if (this->print_commands) { const char* s_siz; @@ -4290,58 +4430,66 @@ void emu64::dl_G_SETTIMG() { this->Printf2("gsDPSetTextureImage_Dolphin(G_IM_FMT_%s, G_IM_SIZ_%s, %d, %d, %s),", dolfmttbl2[setimg2->siz][setimg2->fmt], s_siz, EXPAND_WIDTH(setimg2->wd), - EXPAND_HEIGHT(setimg2->ht), this->segchk(setimg2->imgaddr)); + EXPAND_HEIGHT(setimg2->ht), this->segchk(this->gfx_p->words.w1)); } } #endif this->now_setimg.setimg2 = *setimg2; +#ifdef TARGET_PC + /* On 64-bit, the full pointer is in gfx_p->words.w1 (uintptr_t). + * The 32-bit imgaddr bitfield in Gsetimg2 would truncate it. */ + this->resolved_imgaddr = this->seg2k0(this->gfx_p->words.w1); + this->now_setimg.setimg2.imgaddr = (u32)this->resolved_imgaddr; +#else this->now_setimg.setimg2.imgaddr = (u32)this->seg2k0(setimg2->imgaddr); +#endif } void emu64::dl_G_SETENVCOLOR() { - EMU64_LOGF("gsDPSetEnvColor(%d, %d, %d, %d),", (this->gfx.setcolor.color >> 24) & 0xFF, - (this->gfx.setcolor.color >> 16) & 0xFF, (this->gfx.setcolor.color >> 8) & 0xFF, - (this->gfx.setcolor.color >> 0) & 0xFF); + EMU64_LOGF("gsDPSetEnvColor(%d, %d, %d, %d),", (GFX_W1_U32(this->gfx) >> 24) & 0xFF, + (GFX_W1_U32(this->gfx) >> 16) & 0xFF, (GFX_W1_U32(this->gfx) >> 8) & 0xFF, + (GFX_W1_U32(this->gfx) >> 0) & 0xFF); - if (this->environment_color.raw != this->gfx.setcolor.color) { - this->environment_color.raw = this->gfx.setcolor.color; + if (this->environment_color.raw != GFX_W1_U32(this->gfx)) { + this->environment_color.raw = GFX_W1_U32(this->gfx); this->dirty_flags[EMU64_DIRTY_FLAG_ENV_COLOR] = true; } } void emu64::dl_G_SETBLENDCOLOR() { - EMU64_LOGF("gsDPSetBlendColor(%d, %d, %d, %d),", (this->gfx.setcolor.color >> 24) & 0xFF, - (this->gfx.setcolor.color >> 16) & 0xFF, (this->gfx.setcolor.color >> 8) & 0xFF, - (this->gfx.setcolor.color >> 0) & 0xFF); + EMU64_LOGF("gsDPSetBlendColor(%d, %d, %d, %d),", (GFX_W1_U32(this->gfx) >> 24) & 0xFF, + (GFX_W1_U32(this->gfx) >> 16) & 0xFF, (GFX_W1_U32(this->gfx) >> 8) & 0xFF, + (GFX_W1_U32(this->gfx) >> 0) & 0xFF); - if (this->blend_color.raw != this->gfx.setcolor.color) { - this->blend_color.raw = this->gfx.setcolor.color; + if (this->blend_color.raw != GFX_W1_U32(this->gfx)) { + this->blend_color.raw = GFX_W1_U32(this->gfx); this->dirty_flags[EMU64_DIRTY_FLAG_BLEND_COLOR] = true; } } void emu64::dl_G_SETFOGCOLOR() { - EMU64_LOGF("gsDPSetFogColor(%d, %d, %d, %d),", (this->gfx.setcolor.color >> 24) & 0xFF, - (this->gfx.setcolor.color >> 16) & 0xFF, (this->gfx.setcolor.color >> 8) & 0xFF, - (this->gfx.setcolor.color >> 0) & 0xFF); + EMU64_LOGF("gsDPSetFogColor(%d, %d, %d, %d),", (GFX_W1_U32(this->gfx) >> 24) & 0xFF, + (GFX_W1_U32(this->gfx) >> 16) & 0xFF, (GFX_W1_U32(this->gfx) >> 8) & 0xFF, + (GFX_W1_U32(this->gfx) >> 0) & 0xFF); - if (this->fog_color.raw != this->gfx.setcolor.color) { - this->fog_color.raw = this->gfx.setcolor.color; + if (this->fog_color.raw != GFX_W1_U32(this->gfx)) { + this->fog_color.raw = GFX_W1_U32(this->gfx); this->dirty_flags[EMU64_DIRTY_FLAG_FOG] = true; } } void emu64::dl_G_SETFILLCOLOR() { - EMU64_LOGF("gsDPSetFillColor(0x%08x),", this->gfx.setcolor.color); + EMU64_LOGF("gsDPSetFillColor(0x%08x),", GFX_W1_U32(this->gfx)); - if (this->fill_color.raw != this->gfx.setcolor.color) { - this->fill_color.raw = this->gfx.setcolor.color; + if (this->fill_color.raw != GFX_W1_U32(this->gfx)) { + this->fill_color.raw = GFX_W1_U32(this->gfx); - u16* color = (u16*)&this->gfx.setcolor.color; - this->fill_tev_color.color.r = (*color >> 8) & 0xF8; - this->fill_tev_color.color.g = (*color >> 3) & 0xF8; - this->fill_tev_color.color.b = (*color << 2) & 0xF8; + u32 fill_w1 = GFX_W1_U32(this->gfx); + u16 fill_col = (u16)fill_w1; /* Low 16 bits on little-endian (same as *(u16*)&color) */ + this->fill_tev_color.color.r = (fill_col >> 8) & 0xF8; + this->fill_tev_color.color.g = (fill_col >> 3) & 0xF8; + this->fill_tev_color.color.b = (fill_col << 2) & 0xF8; this->dirty_flags[EMU64_DIRTY_FLAG_FILL_COLOR] = true; this->dirty_flags[EMU64_DIRTY_FLAG_FILL_TEV_COLOR] = true; @@ -4349,9 +4497,7 @@ void emu64::dl_G_SETFILLCOLOR() { } void emu64::dl_G_SETTEXEDGEALPHA(void) { - Gsettexedgealpha* gfx = (Gsettexedgealpha*)&this->gfx; - - this->tex_edge_alpha = gfx->tex_edge_alpha; + this->tex_edge_alpha = (u8)(GFX_W1_U32(this->gfx) & 0xFF); this->dirty_flags[EMU64_DIRTY_FLAG_OTHERMODE_LOW] = TRUE; } @@ -4363,12 +4509,12 @@ void emu64::dl_G_SETPRIMDEPTH() { void emu64::dl_G_SETPRIMCOLOR() { EMU64_LOGF("gsDPSetPrimColor(%d, %d, %d, %d, %d, %d),", this->gfx.setcolor.prim_min_level, - this->gfx.setcolor.prim_level, (this->gfx.setcolor.color >> 24) & 0xFF, - (this->gfx.setcolor.color >> 16) & 0xFF, (this->gfx.setcolor.color >> 8) & 0xFF, - (this->gfx.setcolor.color >> 0) & 0xFF); + this->gfx.setcolor.prim_level, (GFX_W1_U32(this->gfx) >> 24) & 0xFF, + (GFX_W1_U32(this->gfx) >> 16) & 0xFF, (GFX_W1_U32(this->gfx) >> 8) & 0xFF, + (GFX_W1_U32(this->gfx) >> 0) & 0xFF); - if (this->primitive_color.raw != this->gfx.setcolor.color) { - this->primitive_color.raw = this->gfx.setcolor.color; + if (this->primitive_color.raw != GFX_W1_U32(this->gfx)) { + this->primitive_color.raw = GFX_W1_U32(this->gfx); this->dirty_flags[EMU64_DIRTY_FLAG_PRIM_COLOR] = true; } @@ -4399,7 +4545,7 @@ void emu64::dl_G_RDPLOADSYNC() { } void emu64::dl_G_NOOP() { - Gnoop* noop = (Gnoop*)&this->gfx; + Gnoop* noop = (Gnoop*)EMU64_GFX_COMPACT_PTR; switch (noop->tag) { case G_TAG_NONE: @@ -4418,21 +4564,22 @@ void emu64::dl_G_NOOP() { if (this->gfx.words.w1 == 0) { EMU64_LOG("gsDPNoOp(),"); } else { - EMU64_LOGF("gsDPNoOpTag(%08x),", noop->param1); + EMU64_LOGF("gsDPNoOpTag(%08x),", (u32)this->gfx.words.w1); } break; case G_TAG_HERE: - EMU64_WARNF("gsDPNoOpHere([%s:%d]),", (char*)noop->param1, noop->param0); + EMU64_WARNF("gsDPNoOpHere([%s:%d]),", (char*)(uintptr_t)this->gfx.words.w1, noop->param0); break; case G_TAG_STRING: - EMU64_WARNF("gsDPNoOpString(%c%s%c, %d),", '"', (char*)noop->param1, '"', noop->param0); + EMU64_WARNF("gsDPNoOpString(%c%s%c, %d),", '"', (char*)(uintptr_t)this->gfx.words.w1, '"', noop->param0); break; case G_TAG_WORD: - EMU64_WARNF("gsDPNoOpWord(0x%08x, %d),", noop->param1, noop->param0); - break; - case G_TAG_FLOAT: - EMU64_WARNF("gsDPNoOpFloat(%8.3f, %d),", *(f32*)&noop->param1, noop->param0); + EMU64_WARNF("gsDPNoOpWord(0x%08x, %d),", (u32)this->gfx.words.w1, noop->param0); break; + case G_TAG_FLOAT: { + u32 float_bits = (u32)this->gfx.words.w1; + EMU64_WARNF("gsDPNoOpFloat(%8.3f, %d),", *(f32*)&float_bits, noop->param0); + } break; case G_TAG_INFO: if (noop->param0 == 0) { EMU64_WARN("gsDPNoOpQuiet(),"); @@ -4445,51 +4592,51 @@ void emu64::dl_G_NOOP() { case G_TAG_CALLBACK: /* They forgot to pass arguments here */ #ifdef EMU64_FIX_NOOP_CALLBACK_LOG - EMU64_WARNF("gsDPNoOpCallBack(%08x,%d),", noop->param1, noop->param0); + EMU64_WARNF("gsDPNoOpCallBack(%08x,%d),", (u32)this->gfx.words.w1, noop->param0); #else EMU64_WARN("gsDPNoOpCallBack(%08x,%d),"); #endif break; case G_TAG_OPENDISP: - EMU64_WARNF("gsDPNoOpOpenDisp([%s:%d]),", noop->param1, noop->param0); + EMU64_WARNF("gsDPNoOpOpenDisp([%s:%d]),", (char*)(uintptr_t)this->gfx.words.w1, noop->param0); break; case G_TAG_CLOSEDISP: - EMU64_WARNF("gsDPNoOpCloseDisp([%s:%d]),", noop->param1, noop->param0); + EMU64_WARNF("gsDPNoOpCloseDisp([%s:%d]),", (char*)(uintptr_t)this->gfx.words.w1, noop->param0); break; case G_TAG_FILL: EMU64_WARN("gsDPNoOpFill(), /* ### 何じゃコリャ */"); /* Rough translation: ### What the hell */ this->num_unknown_cmds++; break; default: - EMU64_WARNF("gsDPNoOpTag3(%02x, %08x, %04x),", tag, noop->param1, noop->param0); + EMU64_WARNF("gsDPNoOpTag3(%02x, %08x, %04x),", tag, (u32)this->gfx.words.w1, noop->param0); break; } } void emu64::dl_G_MTX() { if (this->print_commands & EMU64_PRINTF_ENABLED_FLAG) { - Gwords gfx_copy = this->gfx_p->words; - EMU64_LOGF("gsSPMatrix(%s, 0", this->segchk(gfx_copy.w1)); + uintptr_t mtx_w1 = this->gfx_p->words.w1; + EMU64_LOGF("gsSPMatrix(%s, 0", this->segchk(mtx_w1)); for (int i = 0; i < ARRAY_COUNT(gmtxtbl); i++) { - EMU64_LOGF("|%s", ((((Gmtx*)this->gfx_p)->type ^ G_MTX_PUSH) & gmtxtbl[i].mask) == 0 ? gmtxtbl[i].disabled + EMU64_LOGF("|%s", ((((Gmtx*)EMU64_GFX_COMPACT_PTR)->type ^ G_MTX_PUSH) & gmtxtbl[i].mask) == 0 ? gmtxtbl[i].disabled : gmtxtbl[i].enabled); } EMU64_LOG("),"); if ((this->print_commands & EMU64_PRINTF3_FLAG) != 0) { - EMU64_LOGF("%08x %08x %08x\n", gfx_copy.w1, this->seg2k0(gfx_copy.w1), this->seg2k0(gfx_copy.w1)); - this->disp_matrix((MtxP)this->seg2k0(gfx_copy.w1)); + EMU64_LOGF("%08x %08x %08x\n", (u32)mtx_w1, this->seg2k0(mtx_w1), this->seg2k0(mtx_w1)); + this->disp_matrix((MtxP)this->seg2k0(mtx_w1)); } } if (this->disable_polygons == false) { EMU64_TIMED_SEGMENT_BEGIN(); - Gmtx* mtx_gfx = (Gmtx*)this->gfx_p; + Gmtx* mtx_gfx = (Gmtx*)EMU64_GFX_COMPACT_PTR; Mtx_t* mtx = - (Mtx_t*)this->seg2k0(mtx_gfx->addr); /* Matrix is in N64 s16.16 format. (First 8 elements are s16 integer + (Mtx_t*)this->seg2k0(this->gfx_p->words.w1); /* Matrix is in N64 s16.16 format. (First 8 elements are s16 integer components, second 8 elements are s16 fractional components) */ #ifdef TARGET_PC if (mtx == NULL) { @@ -4521,7 +4668,21 @@ void emu64::dl_G_MTX() { if ((mtx_gfx->type & G_MTX_PROJECTION) != G_MTX_MODELVIEW) { /* Projection */ N64Mtx_to_DOLMtx((Mtx*)mtx, mtx44); if ((mtx_gfx->type & G_MTX_LOAD) != G_MTX_MUL) { - if ((u16)(*mtx)[1][3] == 0) { /* If the last entry is 0, this should be a perspective projection. + { +#ifdef TARGET_PC + /* Detect perspective vs orthographic from the converted float matrix. + For perspective: mtx44[2][3] is large (near*far term, typically hundreds). + For orthographic: mtx44[2][3] is 0 or very small (-(f+n)/(f-n), often 0 + for symmetric near/far). + The original (*mtx)[1][3] check fails on 64-bit because Mtx_t uses + `long` (8 bytes) so array indexing reads wrong offsets. + Also, N64Mtx_to_DOLMtx only converts 3 rows, so mtx44[3][3] is + uninitialized and can't be used. */ + int is_perspective = (fabsf(mtx44[2][3]) > 1.0f); +#else + int is_perspective = ((u16)(*mtx)[1][3] == 0); +#endif + if (is_perspective) { /* If the last entry is 0, this should be a perspective projection. Otherwise, it's likely an orthographic projection. */ this->near = mtx44[2][3] * ((mtx44[2][2] + 1.0f) / (mtx44[2][2] - 1.0f) - 1.0f) / 2.0f; this->far = this->near * ((mtx44[2][2] - 1.0f) / (mtx44[2][2] + 1.0f) + 1.0f); @@ -4555,6 +4716,7 @@ void emu64::dl_G_MTX() { MTXIdentity(this->position_mtx); this->dirty_flags[EMU64_DIRTY_FLAG_PROJECTION_MTX] = true; this->dirty_flags[EMU64_DIRTY_FLAG_FOG] = true; + } /* end perspective/ortho block */ } else { bcopy(mtx44, &this->position_mtx, sizeof(GC_Mtx)); /* Last row of Mtx44 is ignored */ } @@ -4616,7 +4778,7 @@ void emu64::dl_G_MTX() { void emu64::dl_G_VTX() { EMU64_TIMED_SEGMENT_BEGIN(); - Gvtx* vtx_gfx = (Gvtx*)&this->gfx; + Gvtx* vtx_gfx = (Gvtx*)EMU64_GFX_COMPACT_PTR; u32 n = vtx_gfx->n; /* number of vertices */ int vn = vtx_gfx->vn; u32 v0 = (vn >> 1) - n; /* first vertex to load */ @@ -4626,15 +4788,15 @@ void emu64::dl_G_VTX() { this->vtx_load_calls++; if ((this->print_commands & EMU64_PRINTF_ENABLED_FLAG)) { - EMU64_LOGF("gsSPVertex(%s, %d, %d),", this->segchk(this->gfx.dma.addr), n, v0); + EMU64_LOGF("gsSPVertex(%s, %d, %d),", this->segchk(this->gfx.words.w1), n, v0); if ((this->print_commands & EMU64_PRINTF3_FLAG) != 0) { - this->work_ptr = (void*)this->seg2k0(this->gfx.dma.addr); + this->work_ptr = (void*)this->seg2k0(this->gfx.words.w1); this->show_vtx((Vtx*)work_ptr, n, v0); } } if (this->disable_polygons == false) { - Vtx* vtx_p = (Vtx*)this->seg2k0(this->gfx.dma.addr); + Vtx* vtx_p = (Vtx*)this->seg2k0(this->gfx.words.w1); #ifdef TARGET_PC if (vtx_p == NULL) { EMU64_TIMED_SEGMENT_END(spvertex_time); @@ -4755,7 +4917,7 @@ void emu64::dl_G_MODIFYVTX() { } void emu64::dl_G_LINE3D() { - Gline3D_new* line = (Gline3D_new*)&this->gfx; + Gline3D_new* line = (Gline3D_new*)EMU64_GFX_COMPACT_PTR; if (line->wd == 0) { EMU64_LOGF("gsSPLine3D(%d, %d),", line->v0, line->v1); @@ -4768,7 +4930,7 @@ void emu64::dl_G_LINE3D() { } void emu64::dl_G_TRI1() { - Gtri1 tri_gfx = *(Gtri1*)this->gfx_p; + Gtri1 tri_gfx = *(Gtri1*)EMU64_GFX_COMPACT_PTR; u32 v0 = tri_gfx.v0 / 2; u32 v1 = tri_gfx.v1 / 2; u32 v2 = tri_gfx.v2 / 2; @@ -4808,6 +4970,7 @@ void emu64::dl_G_TRIN() { EMU64_TIMED_SEGMENT_BEGIN(); this->dirty_check(this->texture_gfx.tile, this->texture_gfx.level, TRUE); + this->setup_1tri_2tri_1quad(first_vtx); n_faces = ((first_cmd->words.w0 >> 17) & 0x7F) + 1; int n_verts = n_faces * 3; @@ -5069,7 +5232,7 @@ void emu64::dl_G_TRI2() { */ if (this->disable_polygons || aflags[AFLAGS_MAX_POLYGONS] || aflags[AFLAGS_WIREFRAME]) { - Gtri2 tris = *((Gtri2*)&this->gfx_p->words); + Gtri2 tris = *((Gtri2*)EMU64_GFX_COMPACT_PTR); v0 = tris.t0v0 / 2; v1 = tris.t0v1 / 2; @@ -5130,7 +5293,12 @@ void emu64::dl_G_TRI2() { } for (u32 i = 0; i < commands; i++) { +#if UINTPTR_MAX > 0xFFFFFFFFu + u32 _tri2_buf[2] = { this->gfx_p[i].words.w0, (u32)this->gfx_p[i].words.w1 }; + Gtri2 g = *(Gtri2*)_tri2_buf; +#else Gtri2 g = *(Gtri2*)&this->gfx_p[i].words; +#endif u32 v0 = g.t0v0 / 2; u32 v1 = g.t0v1 / 2; u32 v2 = g.t0v2 / 2; @@ -5160,7 +5328,7 @@ void emu64::dl_G_TRI2() { } void emu64::dl_G_QUAD() { - Gquad0 q = *(Gquad0*)&this->gfx_p->words; + Gquad0 q = *(Gquad0*)EMU64_GFX_COMPACT_PTR; u32 v0 = q.v0 / 2; u32 v1 = q.v1 / 2; u32 v2 = q.v2 / 2; @@ -5188,8 +5356,8 @@ void emu64::dl_G_CULLDL() { f32 ox; f32 oy; f32 oz; - u32 vstart = ((Gculldl*)&this->gfx)->vstart / 2; - u32 vend = ((Gculldl*)&this->gfx)->vend / 2; + u32 vstart = ((Gculldl*)EMU64_GFX_COMPACT_PTR)->vstart / 2; + u32 vend = ((Gculldl*)EMU64_GFX_COMPACT_PTR)->vend / 2; u32 mask; u32 i; Vertex* vtx; @@ -5320,7 +5488,7 @@ void emu64::dl_G_BRANCH_Z() { EMU64_WARNF("gsSPBranchLessZraw(%s, %d, 0x%08x),", this->segchk(this->rdpHalf_1), (this->gfx.words.w0 / 2) & 0x7FF, this->gfx.words.w1); - this->gfx_p = (Gfx*)((int)this->work_ptr - sizeof(Gfx)); + this->gfx_p = (Gfx*)((uintptr_t)this->work_ptr - sizeof(Gfx)); /* Translation: gsSPBranchLessZraw isn't implemented yet */ this->Printf0("gsSPBranchLessZrawはまだインプリメントされていません\n"); } @@ -5329,7 +5497,7 @@ void emu64::dl_G_BRANCH_Z() { #define TEXTURE_SCALE_CONV TEXTURE_SCALE * 65536.0f void emu64::dl_G_TEXTURE() { - Gtexture_internal* texture = (Gtexture_internal*)&this->gfx; + Gtexture_internal* texture = (Gtexture_internal*)EMU64_GFX_COMPACT_PTR; #ifdef EMU64_DEBUG if (this->print_commands != false) { @@ -5344,7 +5512,7 @@ void emu64::dl_G_TEXTURE() { #endif Gfx* t = (Gfx*)&this->texture_gfx; - if ((*(u64*)t) != (*(u64*)&this->gfx)) { + if ((*(u64*)t) != (*(u64*)texture)) { *(u64*)&this->texture_gfx = *(u64*)texture; this->dirty_flags[EMU64_DIRTY_FLAG_TEX] = true; @@ -5440,16 +5608,22 @@ void emu64::dl_G_MOVEWORD() { static char s1[20]; static char s2[64]; static char s3[64]; - Gmoveword* moveword = (Gmoveword*)this->gfx_p; + Gmoveword* moveword = (Gmoveword*)EMU64_GFX_COMPACT_PTR; + u32 mw_data = (u32)this->gfx_p->words.w1; /* Read data word from w1, not union view */ switch (moveword->index) { case G_MW_SEGMENT: { u32 segment = moveword->offset / 4; - EMU64_WARNF("gsSPSegmentA(%d, 0x%08x),", segment, moveword->data); #ifdef TARGET_PC - /* On PC, store address directly (no GC physical address mapping) */ - this->segments[segment] = moveword->data; + /* On 64-bit, w1 is uintptr_t and stores the full pointer directly. + * No need for pc_gbi_recover_ptr anymore. */ + { + uintptr_t seg_addr = this->gfx_p->words.w1; + EMU64_WARNF("gsSPSegmentA(%d, 0x%08x),", segment, (u32)seg_addr); + this->segments[segment] = seg_addr; + } #else + EMU64_WARNF("gsSPSegmentA(%d, 0x%08x),", segment, moveword->data); this->segments[segment] = (0x80000000 + (moveword->data & 0x0FFFFFFF)); if (segment >= EMU64_NUM_SEGMENTS || (moveword->data != 0 && (moveword->data < 0x80000000 || moveword->data > 0x83000000))) { @@ -5472,13 +5646,13 @@ void emu64::dl_G_MOVEWORD() { } break; case G_MW_CLIP: { - EMU64_LOGF("gsSPClipRatio(FRUSTRATIO_%d), ", moveword->data == 0 ? 0 : moveword->data); + EMU64_LOGF("gsSPClipRatio(FRUSTRATIO_%d), ", mw_data == 0 ? 0 : mw_data); this->gfx_p += 3; /* gsSPClipRatio generates four moveword instructions, so skip three. Emulator will skip last one. */ } break; case G_MW_NUMLIGHT: { - u32 num_lights = moveword->data / 24; + u32 num_lights = mw_data / 24; EMU64_LOGF("gsSPNumLights(%d), ", num_lights); if (this->num_lights != num_lights) { this->num_lights = num_lights; @@ -5492,24 +5666,30 @@ void emu64::dl_G_MOVEWORD() { /* Seems like the devs used the light table index as the enum number */ /* TODO: This could be correct. Investigate if they changed the light definitions. */ #ifdef EMU64_FIX_MOVEWORD_LIGHT_NUM_LOG - EMU64_LOGF("gsSPLightColor(LIGHT_%d, %08x), ", (moveword->offset / 0x18) + 1, moveword->data); + EMU64_LOGF("gsSPLightColor(LIGHT_%d, %08x), ", (moveword->offset / 0x18) + 1, mw_data); #else - EMU64_LOGF("gsSPLightColor(LIGHT_%d, %08x), ", light + 1, moveword->data); + EMU64_LOGF("gsSPLightColor(LIGHT_%d, %08x), ", light + 1, mw_data); #endif this->gfx_p++; /* gsSPLightColor generates two commands */ - GXColor* color = (GXColor*)&((Gmoveword*)&this->gfx)->data; - this->lights[light].color.rgba.r = color->r; - this->lights[light].color.rgba.g = color->g; - this->lights[light].color.rgba.b = color->b; + { + u32 color_val = GFX_W1_U32(this->gfx); + GXColor color_tmp; + color_tmp.r = (color_val >> 24) & 0xFF; + color_tmp.g = (color_val >> 16) & 0xFF; + color_tmp.b = (color_val >> 8) & 0xFF; + this->lights[light].color.rgba.r = color_tmp.r; + this->lights[light].color.rgba.g = color_tmp.g; + this->lights[light].color.rgba.b = color_tmp.b; + } this->dirty_flags[EMU64_DIRTY_FLAG_LIGHTS] = true; } break; case G_MW_FOG: { - s16 fm = (s16)(moveword->data >> 16); /* z multiplier */ - s16 fo = (s16)moveword->data; /* z offset */ + s16 fm = (s16)(mw_data >> 16); /* z multiplier */ + s16 fo = (s16)mw_data; /* z offset */ if (fm != 0) { int min = 500 - (fo * 500) / fm; EMU64_LOGF("gsSPFogFactor(%d, %d),", fm, fo); @@ -5524,11 +5704,11 @@ void emu64::dl_G_MOVEWORD() { } break; case G_MW_PERSPNORM: { - EMU64_LOGF("gsSPPerspNormalize(%d),", moveword->data); + EMU64_LOGF("gsSPPerspNormalize(%d),", mw_data); } break; default: { - EMU64_LOGF("gsMoveWd(%d, %d, %d), /* ### what */", moveword->index, moveword->offset, moveword->data); + EMU64_LOGF("gsMoveWd(%d, %d, %d), /* ### what */", moveword->index, moveword->offset, mw_data); this->num_unknown_cmds++; this->Printf0("未知の命令に出くわした\n"); /* Translation: Came across an unknown command */ @@ -5537,16 +5717,17 @@ void emu64::dl_G_MOVEWORD() { } void emu64::dl_G_MOVEMEM() { - Gmovemem* movemem = (Gmovemem*)this->gfx_p; + Gmovemem* movemem = (Gmovemem*)EMU64_GFX_COMPACT_PTR; + uintptr_t movemem_addr = this->gfx_p->words.w1; /* Full pointer from w1 */ u8 param = movemem->index; switch (movemem->index) { case G_MV_VIEWPORT: { - this->work_ptr = (void*)this->seg2k0(movemem->data); + this->work_ptr = (void*)this->seg2k0(movemem_addr); Vp_t* vp = (Vp_t*)this->work_ptr; #ifdef EMU64_DEBUG if (this->print_commands != false) { - EMU64_LOGF("gsSPViewport(%s),", this->segchk(movemem->data)); + EMU64_LOGF("gsSPViewport(%s),", this->segchk(movemem_addr)); EMU64_INFOF("\t# vscale=[%d %d %d %d], ", vp->vscale[0], vp->vscale[1], vp->vscale[2], vp->vscale[3]); EMU64_INFOF("vtrans=[%d %d %d %d] ", vp->vtrans[0], vp->vtrans[1], vp->vtrans[2], vp->vtrans[3]); } @@ -5578,7 +5759,7 @@ void emu64::dl_G_MOVEMEM() { } case G_MV_MATRIX: { - EMU64_LOGF("gsSPForceMatrix(%s),", this->segchk(movemem->data)); + EMU64_LOGF("gsSPForceMatrix(%s),", this->segchk(movemem_addr)); this->gfx_p++; /* Generates two commands */ this->Printf0("gsSPForceMatrixはサポートしてません\n"); /* Translation: gsSPForceMatrix isn't supported */ break; @@ -5587,8 +5768,8 @@ void emu64::dl_G_MOVEMEM() { case G_MV_LIGHT: { switch (movemem->offset * 8) { case G_MVO_LOOKATX: { - EMU64_LOGF("gsSPLookAtX(%s),", this->segchk(movemem->data)); - LookAt* la = (LookAt*)this->seg2k0(movemem->data); + EMU64_LOGF("gsSPLookAtX(%s),", this->segchk(movemem_addr)); + LookAt* la = (LookAt*)this->seg2k0(movemem_addr); EMU64_INFOF(" /* {%3d,%3d,%3d} */", la->l->l.dir[0], la->l->l.dir[1], la->l->l.dir[2]); this->lookAt.x.x = la->l->l.dir[0]; this->lookAt.x.y = la->l->l.dir[1]; @@ -5598,8 +5779,8 @@ void emu64::dl_G_MOVEMEM() { } case G_MVO_LOOKATY: { - EMU64_LOGF("gsSPLookAtY(%s),", this->segchk(movemem->data)); - LookAt* la = (LookAt*)this->seg2k0(movemem->data); + EMU64_LOGF("gsSPLookAtY(%s),", this->segchk(movemem_addr)); + LookAt* la = (LookAt*)this->seg2k0(movemem_addr); EMU64_INFOF(" /* {%3d,%3d,%3d} */", la->l->l.dir[0], la->l->l.dir[1], la->l->l.dir[2]); this->lookAt.y.x = la->l->l.dir[0]; this->lookAt.y.y = la->l->l.dir[1]; @@ -5609,11 +5790,11 @@ void emu64::dl_G_MOVEMEM() { } default: { - Light_new* light = (Light_new*)this->seg2k0(movemem->data); + Light_new* light = (Light_new*)this->seg2k0(movemem_addr); int idx = movemem->offset * 8 - 24; idx /= 24; /* Idx should be 1 - 8. There's more bithacks going on here, but I think it's compiler generated */ - EMU64_LOGF("gsSPLight(%s, %d),", this->segchk(movemem->data), idx); + EMU64_LOGF("gsSPLight(%s, %d),", this->segchk(movemem_addr), idx); EMU64_INFOF("no = %d color=[%3d %3d %3d],", idx, light->l.col[0], light->l.col[1], light->l.col[2]); /* Convert index to 0 based */ @@ -5667,7 +5848,7 @@ void emu64::dl_G_MOVEMEM() { default: { /* Invalid/Unknown MOVEMEM command */ - EMU64_WARNF("gsMoveMem(%s, %d, %d, %d), /* ### what? */", this->segchk(movemem->data), + EMU64_WARNF("gsMoveMem(%s, %d, %d, %d), /* ### what? */", this->segchk(movemem_addr), ((movemem->length >> 3) + 1) * 8, movemem->index, movemem->offset); this->num_unknown_cmds++; @@ -5682,7 +5863,7 @@ void emu64::dl_G_S2DEX() { } void emu64::dl_G_SPECIAL_1() { - Gspecial1* special = (Gspecial1*)&this->gfx; + Gspecial1* special = (Gspecial1*)EMU64_GFX_COMPACT_PTR; if (special->mode == G_SPECIAL_TA_MODE) { EMU64_LOGF("gsDPSetTextureAdjustMode(%s),", special->param0 == 0 ? "G_TA_N64" : "G_TA_DOLPHIN"); @@ -5803,6 +5984,10 @@ u32 emu64::emu64_taskstart_r(Gfx* dl_p) { this->cmds_processed++; EMU64_INFOF("%08x:", this->gfx_p); this->gfx = *this->gfx_p; +#if UINTPTR_MAX > 0xFFFFFFFFu + this->gfx_c.words_compact.w0 = this->gfx.words.w0; + this->gfx_c.words_compact.w1 = (u32)this->gfx.words.w1; +#endif this->gfx_cmd = this->gfx.dma.cmd; this->dl_history[this->dl_history_start++] = this->gfx_p; if (this->dl_history_start >= DL_HISTORY_COUNT) { diff --git a/src/static/libforest/emu64/emu64_print.cpp b/src/static/libforest/emu64/emu64_print.cpp index 0eb104e6..2ad1e754 100644 --- a/src/static/libforest/emu64/emu64_print.cpp +++ b/src/static/libforest/emu64/emu64_print.cpp @@ -54,21 +54,21 @@ void emu64::disp_matrix(MtxP mtx) { #pragma inline_depth(5) #pragma inline_max_size(1100) -const char* emu64::segchk(u32 segment) { +const char* emu64::segchk(uintptr_t segment) { static char str[64]; char buf[30]; const char str0[] = "anime_4_txt+%4u"; const char str1[] = "anime_6_model+sizeof(Mtx)*%2u"; - u32 partial_addr = seg2k0(segment); - u32 addr = convert_partial_address(partial_addr); + uintptr_t partial_addr = seg2k0(segment); + uintptr_t addr = convert_partial_address((u32)partial_addr); str[0] = '\0'; if (segment == partial_addr) { if (addr == partial_addr) { - snprintf(str, sizeof(str), "0x%08x", segment); + snprintf(str, sizeof(str), "0x%08x", (u32)segment); } else { - snprintf(str, sizeof(str), "0x%08x /* PADDR=0x%08x */", segment, addr); + snprintf(str, sizeof(str), "0x%08x /* PADDR=0x%08x */", (u32)segment, (u32)addr); } } else { const char* s; diff --git a/src/static/libforest/emu64/emu64_utility.c b/src/static/libforest/emu64/emu64_utility.c index a73bb755..8033f05b 100644 --- a/src/static/libforest/emu64/emu64_utility.c +++ b/src/static/libforest/emu64/emu64_utility.c @@ -6,47 +6,130 @@ #ifdef TARGET_PC /* Executable image range from pc_main.c — BSS/data can collide with N64 segments */ -extern "C" unsigned int pc_image_base; -extern "C" unsigned int pc_image_end; +extern "C" uintptr_t pc_image_base; +extern "C" uintptr_t pc_image_end; /* Arena range from pc_os.c — heap pointers in arena also bypass segment resolution */ extern "C" unsigned char* pc_arena_base; extern "C" unsigned char* pc_arena_end; -/* Page-granularity cache for VirtualQuery results. +#if UINTPTR_MAX > 0xFFFFFFFFu +#include "pc_gbi_ptr.h" + +/* === 64-bit seg2k0 === + * On 64-bit, real PC pointers are always above 0x0FFFFFFF. N64 segment + * addresses are always 0x03XXXXXX-0x0FXXXXXX. However, truncated 64-bit + * pointers (low 32 bits of a real pointer stored in a u32 Gfx field) can + * fall ANYWHERE in the 32-bit range, including the segment address range. + * + * Strategy: first try segment resolution. If the segment base is 0 (unused + * segment), try recovering the full pointer from the truncated value using + * the known image/arena base addresses. */ +uintptr_t emu64::seg2k0(uintptr_t segadr) { + /* Full 64-bit pointer — already resolved */ + if (segadr > 0xFFFFFFFFu) return segadr; + /* Zero — can't recover */ + if (segadr == 0) return 0; + + /* If the address is within the executable image, it's a native pointer */ + if (segadr >= pc_image_base && segadr < pc_image_end) { + return segadr; + } + + /* Check if address falls within the main memory arena (JKRHeap, Object_Exchange + banks, cloth data, etc.).*/ + if (pc_arena_base && segadr >= (uintptr_t)pc_arena_base && + segadr < (uintptr_t)pc_arena_end) { + return segadr; + } + + /* Try N64 segment resolution first (0x03-0x0F range) */ + if (segadr >= 0x03000000u && segadr <= 0x0FFFFFFFu) { + uintptr_t seg = (segadr >> 24) & 0xF; + uintptr_t offset = segadr & 0xFFFFFF; + if (this->segments[seg] != 0) { + this->resolved_addresses++; + return this->segments[seg] + offset; + } + /* Segment base is 0 — this might be a truncated PC pointer, + * not a real segment address. Fall through to recovery. */ + } + + /* Try to recover a full 64-bit pointer from the truncated 32-bit value */ + uintptr_t recovered = pc_gbi_recover_ptr((unsigned int)segadr); + if (recovered != segadr) { + /* Successfully recovered — this was a truncated pointer */ + return recovered; + } + + /* Unrecoverable — return as-is (may crash, handled by VEH/signal) */ + return segadr; +} +#else +/* === 32-bit seg2k0 === + * On 32-bit, PC pointers can collide with N64 segment addresses (both in + * 0x03-0x0F range). On Windows/Linux, use VirtualQuery/mincore + page cache to + * disambiguate. On other platforms, rely on segment table and image range. */ + +#if defined(_WIN32) || defined(__linux__) +#ifndef _WIN32 +#include +#include +#include +#endif + +/* Page-granularity cache for VirtualQuery/mincore results. * Avoids repeated syscalls for addresses in the same page. */ #define SEG2K0_PAGE_CACHE_SIZE 32 static struct { u32 page; u8 committed; } seg2k0_page_cache[SEG2K0_PAGE_CACHE_SIZE]; static int seg2k0_cache_next = 0; static int seg2k0_is_committed(u32 addr) { - u32 page = addr & ~0xFFF; - /* Check cache first */ + static long page_size = 0; + if (page_size == 0) { +#ifdef _WIN32 + page_size = 4096; +#else + page_size = sysconf(_SC_PAGESIZE); + if (page_size <= 0) page_size = 4096; +#endif + } + u32 page = addr & ~(u32)(page_size - 1); for (int i = 0; i < SEG2K0_PAGE_CACHE_SIZE; i++) { if (seg2k0_page_cache[i].page == page) { return seg2k0_page_cache[i].committed; } } - /* Cache miss — query the OS */ - MEMORY_BASIC_INFORMATION mbi; int committed = 0; - if (VirtualQuery((void*)addr, &mbi, sizeof(mbi)) > 0 && mbi.State == MEM_COMMIT) { +#ifdef _WIN32 + MEMORY_BASIC_INFORMATION mbi; + if (VirtualQuery((void*)(uintptr_t)addr, &mbi, sizeof(mbi)) > 0 && mbi.State == MEM_COMMIT) { committed = 1; } +#else + /* Linux: use mincore to check if the page is mapped. + * mincore(2) returns 0 on success, and sets vec[0] to indicate if the page is resident. + * If the address is not mapped, it returns -1 with errno=ENOMEM. */ + unsigned char vec[1]; + if (mincore((void*)(uintptr_t)page, (size_t)page_size, vec) == 0) { + committed = 1; + } else if (errno != ENOMEM) { + /* Other error (e.g. invalid pointer) — assume not committed */ + committed = 0; + } +#endif seg2k0_page_cache[seg2k0_cache_next].page = page; - seg2k0_page_cache[seg2k0_cache_next].committed = committed; + seg2k0_page_cache[seg2k0_cache_next].committed = (u8)committed; seg2k0_cache_next = (seg2k0_cache_next + 1) % SEG2K0_PAGE_CACHE_SIZE; - return committed; + return (int)committed; } +#endif /* _WIN32 || __linux__ */ -u32 emu64::seg2k0(u32 segadr) { - /* Addresses above the N64 segment range (upper nibble != 0) or below - the minimum segment address are definitely raw PC pointers. */ +uintptr_t emu64::seg2k0(uintptr_t segadr) { if ((segadr >> 28) != 0 || segadr < 0x03000000) { return segadr; } - /* Check if address falls within the executable image (BSS/data/code). */ if (segadr >= pc_image_base && segadr < pc_image_end) { return segadr; } @@ -65,16 +148,15 @@ u32 emu64::seg2k0(u32 segadr) { return segadr; } - /* On PC, raw heap/DLL pointers can fall in the 0x03000000-0x0FFFFFFF range, - colliding with N64 segmented addresses (seg<<24|offset). On GC, all real - pointers had bit 31 set (k0 space) so they bypassed segment resolution. + uintptr_t resolved = this->segments[seg] + offset; - Real N64 segment addresses come from GBI macros like SEGMENT_ADDR(seg, offset) +#if defined(_WIN32) || defined(__linux__) + /* Real N64 segment addresses come from GBI macros like SEGMENT_ADDR(seg, offset) and always have small offsets (textures, matrices that are never > 512KB). PC heap pointers that collide with the segment range have large "offsets" (the low 24 bits of an arbitrary address). Use this to discriminate: - large offset + committed raw address = heap pointer, not segment ref. - + large offset + committed raw address = heap pointer, not segment ref. + This might be the last memory fix needed. */ @@ -85,27 +167,21 @@ u32 emu64::seg2k0(u32 segadr) { } /* Normal segment resolution path */ - u32 resolved = (u32)this->segments[seg] + offset; - - if (seg2k0_is_committed(resolved)) { + if (seg2k0_is_committed((u32)resolved)) { /* Segment resolution gave a valid address — use it (normal path) */ this->resolved_addresses++; return resolved; } - /* Resolved address is invalid. Check if the raw address is valid memory. */ - if (seg2k0_is_committed(segadr)) { - /* Raw address IS valid — it's a direct PC pointer misidentified as - a segment reference. This happens when heap/stack/DLL pointers - fall in the 0x03-0x0F range. Return as-is. */ + if (seg2k0_is_committed((u32)segadr)) { return segadr; } +#endif /* _WIN32 || __linux__ */ - /* Neither resolved nor raw is committed. Fall through to segment resolution - (may crash, but the VEH crash recovery will handle it). */ this->resolved_addresses++; return resolved; } +#endif /* UINTPTR_MAX */ #else u32 emu64::seg2k0(u32 segadr) { u32 k0; diff --git a/src/system/sys_ucode.c b/src/system/sys_ucode.c index dbc2a994..713ebbc3 100644 --- a/src/system/sys_ucode.c +++ b/src/system/sys_ucode.c @@ -1,9 +1,9 @@ #include "sys_ucode.h" -long long int gspF3DZEX2_NoN_PosLight_fifoTextStart[1]; -long long int gspF3DZEX2_NoN_PosLight_fifoDataStart[1]; -unsigned long long gspS2DEX2_fifoTextStart[1]; -unsigned long long gspS2DEX2_fifoDataStart[1]; +s64 gspF3DZEX2_NoN_PosLight_fifoTextStart[1]; +s64 gspF3DZEX2_NoN_PosLight_fifoDataStart[1]; +u64 gspS2DEX2_fifoTextStart[1]; +u64 gspS2DEX2_fifoDataStart[1]; s64* poly_tbl[] = { gspF3DZEX2_NoN_PosLight_fifoTextStart, gspF3DZEX2_NoN_PosLight_fifoDataStart };