Skip to content

Port project to 64 bit, MACOS and ARCH confirmed#33

Open
chasem-dev wants to merge 16 commits intoflyngmt:masterfrom
chasem-dev:master
Open

Port project to 64 bit, MACOS and ARCH confirmed#33
chasem-dev wants to merge 16 commits intoflyngmt:masterfrom
chasem-dev:master

Conversation

@chasem-dev
Copy link

Claude Code was heavily leveraged, I did test that things work on Windows for 64 bit, but I haven't tested the original 32 bit support that was functioning originally.

To be honest, I'll probably not do anything more with this project and or code, but I thought I'd submit a PR here to see if there's anything worth keeping.

Videos of it working on X. https://x.com/chasemdev/status/2034735172759826685?s=20

chasem-dev and others added 15 commits March 19, 2026 12:38
Port the 32-bit x86 PC build to 64-bit platforms. The game compiles, links,
and boots to the trademark screen on macOS Apple Silicon with GCC 15.

Type system:
- u32/s32/u64/s64 use stdint.h fixed-width types on PC (always 4/8 bytes)
- Compile-time static_assert validation for type sizes

Pointer safety (~120 casts across 83 files):
- PC port layer: GXTexObj rewritten as proper struct, texture/EFB cache
  uses uintptr_t, ARAM DMA uses uintptr_t for MRAM addresses
- Decomp code: JKRExpHeap, JKRHeap, JKRAram, JKRThread, JKRMemArchive,
  JKRCompArchive, JKRDvdRipper, and 8 JUtility files wrapped in
  #ifdef TARGET_PC using uintptr_t (preserves decomp matching in #else)
- emu64: segments[], DL_stack[] are uintptr_t; resolved_imgaddr field
  avoids 32-bit bitfield truncation for texture addresses
- jaudio_NES: OFS2RAM/BANK_ENTRY macros, PTconvert relocation, Nas_HeapInit
  alignment, audio command buffer (Acmd.w1), RSP simulator pointer recovery
- Header fixes: ARStartDMA, ARQPostRequest, AIInitDMA declarations match
  uintptr_t implementations; OSRoundUp32B/OSRoundDown32B use uintptr_t

seg2k0 64-bit:
- Simple threshold check (addresses > 0x0FFFFFFF are real PC pointers)
- Pointer recovery from truncated 32-bit GBI values using image/arena base
- Eliminates VirtualQuery dependency on 64-bit

Build system:
- Removed 32-bit enforcement; added macOS platform support
- GCC required on 64-bit (Clang rejects pointer truncation in GBI statics)
- macOS: GL_SILENCE_DEPRECATION, forward-compatible GL context, Cocoa/IOKit
  frameworks, dladdr-based image detection, no elf.h dependency
- Clang-incompatible flags guarded; decomp -Wno-return-type for Clang

Runtime fixes:
- operator new/delete uses malloc/free (prevents macOS framework corruption);
  operator delete checks arena range for JKR heap pointers
- Audio heap doubled (0x70000→0xE0000) for wider 64-bit structs
- Arena increased to 48MB on 64-bit; system heap overhead adjusted
- malloc.h→stdlib.h on macOS; errno field conflict; bcmp/bcopy builtins;
  CARD sub-header long/s32 conflicts; _mem.h memcpy builtin conflicts

Known limitations:
- Static GBI display lists with direct C pointers use 0 placeholder
  (_GBI_STATIC_PTR), recovered at runtime via seg2k0 pointer recovery
- Audio bank struct layout mismatch (PTconvert reads void* from 32-bit
  ROM fields) causes crash during bank loading after trademark screen
- Requires GCC (brew install gcc) on macOS; Clang 64-bit not supported
Fix crashes on macOS ARM64 / Linux x86_64 caused by 64-bit pointer
truncation throughout the codebase. The game now boots crash-free
through trademark init and into the main game loop.

Audio system (system.c):
- Define GC-compat structs (smzwavetable_gc, wtstr_gc, perctable_gc,
  voicetable_gc, percvoicetable_gc) that match the GC binary layout
  with u32 for pointer fields
- Add Nas_BankOfsToAddr_Inner_PC + __WaveTouch_PC to allocate native
  64-bit structs from GC ROM data during bank ctrl relocation
- Add safety guards: __Link_BankNum NULL check,
  __Nas_SzCacheCheck_Inner default case, __Load_Bank_BG range check

Pointer truncation (22 files):
- GRAPH_ALLOC macro: (int) -> (intptr_t) for pointer arithmetic
- TwoHeadArena: (u32) -> (uintptr_t) in allocator functions
- __osMalloc: (u32) -> (uintptr_t) in macros and pointer math
- ARQRequest struct: u32 source/dest -> uintptr_t on 64-bit
- ALIGN_NEXT((u32)ptr) -> (uintptr_t) across 12+ game files
- m_play.c / famicom_emu.c: THA_alloc u32 -> uintptr_t

GBI display list (emu64.c):
- Recover full 64-bit pointer via pc_gbi_recover_ptr when setting
  segment bases in dl_G_MOVEWORD

Build config:
- Add BUGFIXES define to fix original game buffer overflows that
  crash on modern platforms with fortified libc
On 64-bit, Gwords.w1 is now uintptr_t (8 bytes) instead of u32,
making sizeof(Gfx) = 16. This allows static display list initializers
to store full 64-bit pointers via _GBI_STATIC_PTR(s) = (uintptr_t)(s)
instead of the 0u placeholder that produced a black screen.

gbi.h:
- Gwords.w1: u32 -> uintptr_t on 64-bit
- _GBI_STATIC_PTR: 0u -> (uintptr_t)(s) on 64-bit
- _GBI_SET_W1 / _GBI_SET_W1_RAW: new macros for runtime w1 writes
- All g* runtime macros updated to use _GBI_SET_W1

emu64.c:
- EMU64_GFX_COMPACT_PTR: builds packed 8-byte {w0,(u32)w1} buffer
  for safe casting to union member structs (Gsettile, Gsetcolor, etc.)
  whose second u32 field would land in padding with 16-byte Gfx
- All command handlers read pointers from gfx.words.w1 (full width)
  instead of union views that truncate to u32
- seg2k0 already returns full 64-bit values directly (> 0xFFFFFFFF)

emu64.hpp: rdpHalf_1 widened to uintptr_t, segchk param widened

Result: ~1300 GBI commands/frame, 70-95 triangles, 60-98 GL draws.
Game renders title screen and character movement is visible.
SDIFileEntry had void* mData at offset 0x10, making sizeof() = 0x18
on 64-bit instead of the RARC binary layout's 0x14. This caused
fileEntry++ iteration to misalign, breaking archive file lookups
(most resources returned address 0 from JW_GetAramAddress).

Fix: replace void* mData with u32 mData_pad on TARGET_PC to keep
the binary-compatible 0x14 stride. Store actual mData pointers in a
parallel heap-allocated array (mFileEntryDataPtrs) accessed via
getFileEntryData()/setFileEntryData() methods.

Updated: JKRAramArchive, JKRDvdArchive, JKRMemArchive,
JKRCompArchive, JKRArchivePri, JKRArchivePub (all mData accesses).

pallet_boy.bin now resolves to valid ARAM address (0x8a4080).
Texture/color rendering still WIP — ARAM DMA reads return zeros,
suggesting the resource data within the archive wasn't decompressed
or the ARAM buffer contents at those offsets are empty.
Updated the DVDFileInfo and DVDCommandBlock structures to ensure correct field offsets on 64-bit systems. This includes replacing hardcoded offsets with offsetof() macros for better maintainability and accuracy. Adjusted memory initialization to use sizeof() for the structures instead of fixed sizes, enhancing compatibility across different architectures. Additionally, added a new fast-forward feature in the main PC application loop and included pixel color diagnostics for debugging purposes.
- game.c: use %p format for crash diagnostic pointer printing
- m_card.c: cast pointer arithmetic through uintptr_t instead of u32
- m_mail.c: fix mMl_strlen to use typed pointer instead of u32 cast
- m_font_main.c_inc: fix vertex alpha (255), cache char code to avoid
  re-dereferencing, clean up trailing whitespace
- emu64.c: fix G_TEXTURE dirty check to compare against incoming
  texture command rather than self
Halves the frame pacing target from 16667µs to 8333µs when active,
doubling the game loop rate. Audio is unaffected (decoupled thread).
Window title shows [2x] indicator when enabled.
…flush

- m_font_main.c_inc: Route FONT_DISP callers (NPC names, choices) through
  poly path for correct matrix-transformed positioning. Route POLY_OPA
  callers (editor keyboard) through rect path with absolute screen coords,
  working around a poly rendering issue on the POLY_OPA display list.

- emu64.c dirty_check: Flush pending GX batch at the start of dirty_check
  before any state changes. Fixes texture binding race where a previous
  batch would be flushed mid-dirty_check with partially-updated state
  (wrong texture bound at draw time).

- emu64.c dirty_check lighting: Use GX_SRC_REG instead of GX_SRC_VTX for
  channel material source when G_SHADE is off. Matches N64 behavior where
  vertex colors are ignored when shade is disabled.

- emu64.c: Add extern declaration for pc_gx_flush_if_begin_complete.
The original GameCube code stored pointers in u32 fields and used (u32)
casts on pointer values. On the 64-bit PC port, this truncates addresses
causing silent failures — most visibly, the house door entry during the
intro sequence would permanently black-screen because the player's door
label (an actor pointer) was truncated and never matched.

Changes:
- Widen u32 label/pointer fields to uintptr_t in m_player.h (door, demo
  wait, net catch, snowball, mosquito, force speak labels)
- Fix (u32)pointer casts to (uintptr_t) across ~90 source files including
  all insect actors, fishing actors, furniture, effects, NPCs, and the
  player state machine
- Update function signatures for sAdo_OngenPos, Na_OngenPos,
  sAdos_KishaStatusLevel, mPlib_Get/Change_item_net_catch_label, and
  related function pointer typedefs to use uintptr_t
- Add GitHub Actions release workflow for macOS, Windows, and Linux builds
@chasem-dev chasem-dev changed the title Port project to 64 bit and MACOS Port project to 64 bit, MACOS and ARCH confirmed Mar 20, 2026
@chasem-dev
Copy link
Author

Someone else added ARCH support, I'd really like someone to confirm that Windows 32 bit still compile and works correctly, btw Windows 64 bit seemed to work as well 🤔

@chasem-dev chasem-dev mentioned this pull request Mar 20, 2026
@Lyraedan
Copy link

A fellow person named Dia had Linux up and running pretty well. I'm curious however if the 64 bit stuff here means this will compile using MSYS2 MINGW64?

@chasem-dev
Copy link
Author

A fellow person named Dia had Linux up and running pretty well. I'm curious however if the 64 bit stuff here means this will compile using MSYS2 MINGW64?

I used MSYS2 MINGW64 to compile and run it on my own windows machine

@flyngmt
Copy link
Owner

flyngmt commented Mar 20, 2026

Thanks for your work, but this is a very huge PR that could affect things that aren't instantly obvious. Assume that it will take a while until I start working on merging it. I'll be currently focused on fixing the bugs that I know to exist in 32 bit version.

@Lyraedan
Copy link

Lyraedan commented Mar 20, 2026

A fellow person named Dia had Linux up and running pretty well. I'm curious however if the 64 bit stuff here means this will compile using MSYS2 MINGW64?

I used MSYS2 MINGW64 to compile and run it on my own windows machine

I try compiling it with MSYS2 MINGW64 and it says

"Error: Must run from MSYS2 MINGW32 shell (not MINGW64 or MSYS)
Open 'MSYS2 MINGW32' from your Start menu, then run this script again."

@chasem-dev
Copy link
Author

chasem-dev commented Mar 21, 2026

A fellow person named Dia had Linux up and running pretty well. I'm curious however if the 64 bit stuff here means this will compile using MSYS2 MINGW64?

I used MSYS2 MINGW64 to compile and run it on my own windows machine

I try compiling it with MSYS2 MINGW64 and it says

"Error: Must run from MSYS2 MINGW32 shell (not MINGW64 or MSYS) Open 'MSYS2 MINGW32' from your Start menu, then run this script again."

@Lyraedan

Just pushed up a README adjustment with 64 bit instructions, don't let mingw32-make trip you up, it's still 64 bit.

Windows 64-bit (MSYS2)

  1. Install MSYS2 (https://www.msys2.org/)

  2. Open MSYS2 MINGW64 and install dependencies:

    pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake mingw-w64-x86_64-SDL2 mingw-w64-x86_64-make
  3. Clone and build:

    git clone https://github.com/chasem-dev/ACGC-PC-Port.git
    cd ACGC-PC-Port/pc
    mkdir build64 && cd build64
    cmake .. -G "MinGW Makefiles"
    mingw32-make -j$(nproc)
  4. Place your disc image in pc/build64/bin/rom/ and run:

    pc/build64/bin/AnimalCrossing.exe

@Lyraedan
Copy link

Lyraedan commented Mar 21, 2026

Thank youuuuuuuuu <3

Out of curiosity, I don't seem to have the CMakeLists.txt and cmake is complaining

@chasem-dev
Copy link
Author

Thank youuuuuuuuu <3

Out of curiosity, I don't seem to have the CMakeLists.txt and cmake is complaining

It's in the fork's PR and the main repo 🤔

pc/CMakeLists.txt

@chasem-dev
Copy link
Author

@Project516 Have you tried my fork? I think it will work

@Project516
Copy link

@Project516 Have you tried my fork? I think it will work

yeah it works

@chasem-dev
Copy link
Author

@Project516 Have you tried my fork? I think it will work

yeah it works

Which distro? Ubuntu? 👀

@chasem-dev chasem-dev closed this Mar 21, 2026
@chasem-dev chasem-dev reopened this Mar 21, 2026
@Project516
Copy link

@Project516 Have you tried my fork? I think it will work

yeah it works

Which distro? Ubuntu? 👀

fedora

@Lyraedan
Copy link

Update. I have it building now. I wasn't in /pc whoops

@birabittoh
Copy link

So we have confirmations for 64bit Windows, Fedora, Arch/CachyOS and Mac OS, right?

@chasem-dev
Copy link
Author

That seems accurate, I think more people have tried it in the bug issue thats open, but never shared their OS.

Copy link

@Project516 Project516 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some suggestions for the README

@@ -24,40 +24,111 @@ Only needed if you want to modify the code. Otherwise, use the [pre-built releas

### Requirements

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dependencies are declared per architecture in the later steps

```
> 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:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Windows instructions give full path from project root

make -j$(nproc)
```

3. Place your disc image in `build/bin/rom/` and run:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Windows instructions give full path from project root

@birabittoh
Copy link

My own fork has essentially reached feature parity with the 32bit version and it should also work on Mac OS and Linux.

https://nightly.link/birabittoh/ACGC-PC-Port/workflows/build.yaml/master?preview

Can anyone test it on Linux i686 or Mac OS?
I'm interested in knowing:

  • does the pc menu work? Can you see "Start Game" and "Options"?
  • does the town map look right?
  • are there any artifacts while opening the map screen?
  • does the game crash when you enter a house?

Thank you for your cooperation.

@Project516 Project516 mentioned this pull request Mar 26, 2026
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants