forked from Ports/goldeneye-pc-port
macos: native Apple Silicon (arm64) support — address model, boot chain, 21/21 levels
Adds native arm64 macOS support on top of #88's Intel macOS layer. The one structural change arm64 needs is an address model. The port realises the N64's 32-bit address space *as host addresses* — DRAM at 0x70000000, cart at 0x10000000, plus ~1700 linker-absolute symbols — which is only sound while host addresses fit in 32 bits. Native arm64 cannot map below 4 GiB (__PAGEZERO; a shrunken pagezero is SIGKILLed at exec; PIE is mandatory; MAP_32BIT fails). So the whole space is relocated to a fixed host base, PORT_ADDR_BASE (16 TiB), with portN64ToHost / portHostToN64 / PORT_N64PTR as the conversion chokepoints. PORT_ADDR_BASE is 0 on every other platform, so all of this is an identity there. That relocation then surfaces a class of latent 64-bit bugs that are invisible at base 0 — any place the decomp round-trips a pointer through a 32-bit integer. The src/ changes here are that class: pointer-width/layout only, no behaviour change, N64 branch textually unchanged, each documented in docs/dev/findings.md (D298/M2). Also: Mach-O absolute-symbol generation at the same base, #pragma weak -> symbol equates, __x86_64__ -> PLATFORM_64BIT, Darwin crash handler/ucontext, shm_open DRAM, the AppKit main-thread guard, and the sidecar generation that was the real boot blocker. Verified: 21/21 solo levels boot, render and run crash-free.
This commit is contained in:
1 parent
39d4f8d088
commit
d4cc71af0a
58 files changed
+1621
-329
No files matched your search
+18
-6
@@ -363,12 +363,22 @@ elseif(UNIX AND NOT APPLE)
|
||||
# This is the ELF analogue of the Windows build's fixed 0x140000000 base.
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-Ttext-segment=0x20000000")
|
||||
elseif(APPLE)
|
||||
# Mach-O executables normally reserve [0, 4 GiB) as __PAGEZERO. The port
|
||||
# needs fixed mappings at 0x10000000 (ROM), 0x70000000 (s32-safe DRAM), and
|
||||
# 0x80000000 (KSEG0 mirror), so retain null/low-pointer protection only up
|
||||
# while leaving ample space before the first required mapping.
|
||||
set(CMAKE_EXE_LINKER_FLAGS
|
||||
"${CMAKE_EXE_LINKER_FLAGS} -Wl,-pagezero_size,0x10000")
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm64|aarch64")
|
||||
# Apple Silicon: shrinking __PAGEZERO gets the process SIGKILLed at exec
|
||||
# and PIE is mandatory, so the fixed N64 mappings (0x10000000 / 0x70000000
|
||||
# / 0x80000000) are impossible. The whole N64 address space is instead
|
||||
# shifted to PORT_ADDR_BASE and reserved PROT_NONE by portAddrInit()
|
||||
# (port/include/port_addr.h, docs/dev/MACOS-ARM64-PLAN.md).
|
||||
set(PORT_ADDR_BASE 0x100000000000)
|
||||
else()
|
||||
# Intel: Mach-O normally reserves [0, 4 GiB) as __PAGEZERO. The port needs
|
||||
# fixed mappings at 0x10000000 (ROM), 0x70000000 (s32-safe DRAM), and
|
||||
# 0x80000000 (KSEG0 mirror), so retain null/low-pointer protection only up
|
||||
# while leaving ample space before the first required mapping.
|
||||
set(CMAKE_EXE_LINKER_FLAGS
|
||||
"${CMAKE_EXE_LINKER_FLAGS} -Wl,-pagezero_size,0x10000")
|
||||
set(PORT_ADDR_BASE 0x0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# port/shim first: PC-only shadow headers (bondtypes.h, bondconstants.h,
|
||||
@@ -475,6 +485,7 @@ if(APPLE)
|
||||
OUTPUT "${SRC_ROMASSETS}"
|
||||
COMMAND "${Python3_EXECUTABLE}"
|
||||
"${CMAKE_SOURCE_DIR}/scripts/gen_macho_syms.py"
|
||||
--base "${PORT_ADDR_BASE}"
|
||||
"${SRC_ROMASSETS_INPUT}" "${SRC_ROMASSETS}"
|
||||
DEPENDS "${SRC_ROMASSETS_INPUT}"
|
||||
"${CMAKE_SOURCE_DIR}/scripts/gen_macho_syms.py"
|
||||
@@ -483,6 +494,7 @@ if(APPLE)
|
||||
OUTPUT "${SRC_DRAM_SYMS}"
|
||||
COMMAND "${Python3_EXECUTABLE}"
|
||||
"${CMAKE_SOURCE_DIR}/scripts/gen_macho_syms.py"
|
||||
--base "${PORT_ADDR_BASE}"
|
||||
"${SRC_DRAM_SYMS_INPUT}" "${SRC_DRAM_SYMS}"
|
||||
DEPENDS "${SRC_DRAM_SYMS_INPUT}"
|
||||
"${CMAKE_SOURCE_DIR}/scripts/gen_macho_syms.py"
|
||||
|
||||
@@ -197,7 +197,7 @@
|
||||
// These are compile time extern constants (so not "really" const), but used the same
|
||||
// as the defines above, which is to index into ptr_animation_table.
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#if defined(PLATFORM_64BIT)
|
||||
/* D34 (docs/dev/findings.md): on N64 this segment links at VMA 0
|
||||
* (ge007.ld), so &ANIM_DATA_x is the record's offset within the
|
||||
* animation_data segment and game code re-bases it with
|
||||
@@ -572,7 +572,7 @@ extern s32 ANIM_DATA_credits_natalya_kissing;
|
||||
extern s32 ANIM_DATA_helicopter_cradle;
|
||||
extern s32 ANIM_DATA_plane_runway;
|
||||
extern s32 ANIM_DATA_helicopter_takeoff;
|
||||
#endif /* __x86_64__ (D34) */
|
||||
#endif /* PLATFORM_64BIT (D34) */
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,644 @@
|
||||
# macOS Apple Silicon (native arm64) port — implementation plan
|
||||
|
||||
Session 2026-09-18. Scope decision: **native arm64 only** (no Rosetta/x86_64
|
||||
build). Nothing in this plan has run yet; §1 is measured, §2 is design, §3 is
|
||||
the work. Companion: `LINUX-PORT.md` (same shape, earlier platform).
|
||||
|
||||
Execution model: research/design/integration items are run by the session
|
||||
model ("integrator"); items marked **mechanic** are self-contained briefs for
|
||||
the Sonnet-backed `.opencode/agents/mechanic.md` subagent. Every mechanic
|
||||
item lists files, recipe, budget, verify. Items in the same phase that touch
|
||||
disjoint files may run in parallel (dev-process.md §3).
|
||||
|
||||
---
|
||||
|
||||
## 0. Summary
|
||||
|
||||
The compiler is not the problem. Apple clang builds 235/237 C TUs of the
|
||||
existing tree with `-fms-extensions` (in place of GCC's `-fplan9-extensions`)
|
||||
plus small fixes. fast3d already selects a 4.1 Core GL context on macOS and
|
||||
uses no compat or >4.1 features.
|
||||
|
||||
**The blocker is the port's address model.** The port realises the N64's
|
||||
32-bit address space as *host* addresses: DRAM at `0x70000000` (+ KSEG0
|
||||
mirror at `0x80000000`), cart at `0x10000000`, and ~1700 linker-absolute
|
||||
symbols with those values; `osVirtualToPhysical` is a `u32` truncation and
|
||||
`u32 → pointer` is an identity cast. That works on Windows/Linux because the
|
||||
image and all mappings sit below 4 GiB. On native arm64 macOS **nothing can be
|
||||
mapped below 4 GiB**: `__PAGEZERO` covers it, `-pagezero_size` gets the
|
||||
process SIGKILLed, PIE is mandatory, and `MAP_32BIT` fails.
|
||||
|
||||
The fix (§2) is a **shifted window**: keep the N64 32-bit space intact but
|
||||
place it at a fixed host base `B` (`PORT_ADDR_BASE`), so every game-visible
|
||||
32-bit value is *identical* to today's Windows values and only the
|
||||
`u32 → host pointer` direction changes (add `B`). `B = 0` on Windows/Linux, so
|
||||
those builds are byte-for-byte unchanged. All conversions go through a
|
||||
port-owned chokepoint; the residue is a compiler-driven census of raw
|
||||
`u32 → pointer` casts in game code, each rewritten through a `PORT_*` macro
|
||||
(the sanctioned D3x ABI/layout class — no logic change).
|
||||
|
||||
Phases: **M0** compile+link on macOS → **M1** address model in `port/` →
|
||||
**M2** game-code cast census + rewrites → **M3** runtime bring-up (Cocoa
|
||||
threading, first frame, level sweep) → **M4** packaging/CI/docs.
|
||||
|
||||
---
|
||||
|
||||
## 0b. Base change (2026-09-18, later): rebased onto PR #88 + GCC
|
||||
|
||||
After M0/M1 were working on Apple clang, PR #88 ("Add native Intel macOS
|
||||
support", JunielKatarn) turned up: a single commit on this repo's exact base,
|
||||
targeting **Intel** macOS and explicitly leaving Apple Silicon unsupported. The
|
||||
arm64 work was rebased onto it rather than maintained in parallel. Branch:
|
||||
**`macos-arm64-gcc`** (the earlier clang branch `macos-arm64` is superseded).
|
||||
|
||||
**Adopted from #88 — this deletes the corresponding work in §3 M0:**
|
||||
- Homebrew GNU GCC (`gcc-16`) + libstdc++. Removes every clang workaround:
|
||||
no `-fms-extensions`/`-Wno-microsoft-anon-tag`, no libc++ wrapper header
|
||||
shims (the old D295), no `-D_FORTIFY_SOURCE=0`.
|
||||
- `scripts/gen_macho_syms.py` — build-tree Mach-O symbol generation; the
|
||||
committed `*.darwin.s` duplicates are gone.
|
||||
- `scripts/strip_weak_pragmas.py` + `port/src/macho_weak_aliases.s` — the
|
||||
`#pragma weak` handling, so **`src/` carries no macOS edit for it** (the old
|
||||
D294 in-source `#if defined(PORT) && defined(__APPLE__)` equates are gone).
|
||||
- POSIX `shm_open` DRAM backing, Darwin crash handling, and the AppKit
|
||||
main-thread event-pump guard in `gfx_sdl2.cpp` (that last one was §3 M3.1).
|
||||
|
||||
**Kept from this plan — the arm64 delta:**
|
||||
- §2's shifted-window address model (M1 / D298). `-pagezero_size 0x10000`,
|
||||
the core of #88's Intel approach, is fatal on arm64 (shrinking `__PAGEZERO`
|
||||
gets the process SIGKILLed), so CMake now sets it for x86_64 only and arm64
|
||||
uses `PORT_ADDR_BASE`.
|
||||
- D296 (`__x86_64__` → `PLATFORM_64BIT`). Without it #88's tree does not even
|
||||
*link* on arm64 — 23 undefined `_ANIM_DATA_*`.
|
||||
- `gen_macho_syms.py --base` (bakes `PORT_ADDR_BASE` into the absolute
|
||||
symbols; `--base 0` output is byte-identical to #88's transform).
|
||||
- arm64 crash registers (`__ss.__pc/__lr/__sp/__fp`) and
|
||||
`_dyld_get_image_header` / `_NSGetExecutablePath`.
|
||||
- All of M2 (the game-code re-basing sweep).
|
||||
|
||||
Mergeability consequence: the arm64 contribution is now a small additive delta
|
||||
on top of #88, and `src/` has no macOS-specific toolchain/alias edits.
|
||||
|
||||
## 1. Measured facts (this machine: macOS 26.3, arm64, Apple clang 21, SDL2 via `sdl2-compat` 2.32)
|
||||
|
||||
| # | Test | Result |
|
||||
|---|------|--------|
|
||||
| F1 | `mmap(MAP_FIXED)` at `0x10000000` / `0x70000000` / `0x80000000`, native arm64 | **ENOMEM** — first 4 GiB is `__PAGEZERO` |
|
||||
| F2 | Link with `-Wl,-pagezero_size,0x4000` (and 0x1000…0x90000000), native arm64 | links; **process SIGKILLed at exec (exit 137)** |
|
||||
| F3 | `-Wl,-no_pie`, `-Wl,-image_base` | ignored ("Linking with PIE"); image lands at `0x1_0000_0000 + slide`, slide observed `0x32_0000`–`0x4EF_8000` (varies per run) |
|
||||
| F4 | `mmap(MAP_32BIT)` | defined, **fails**; default thread stacks at `0x16b_xxxx_xxxx` |
|
||||
| F5 | Same code as x86_64 + `-pagezero_size 0x1000` under Rosetta | all fixed maps succeed (not our target; recorded for completeness) |
|
||||
| F6 | `mmap(MAP_FIXED)` at `B + n64addr` for `B ∈ {1,2,3,4} << 32` | all succeed — **but `MAP_FIXED` silently replaces existing mappings on macOS** (no `MAP_FIXED_NOREPLACE`), so success ≠ range was free. A 64 MiB `malloc` was observed at `0x4_8400_0000`. |
|
||||
| F7 | Non-clobbering 4 GiB `PROT_NONE` reservation via `mach_vm_map(VM_FLAGS_FIXED)` (no `OVERWRITE`) | `0x3<<32` free (this run); `0x2,0x4,0x8,0x10,0x20,0x40 <<32` **occupied** (libmalloc/VM regions, varies); **`0x100_0000_0000` (1 TiB), `0x400_0000_0000`, `0x1000_0000_0000` (16 TiB) reserved cleanly**, DRAM+cart carved inside OK |
|
||||
| F8 | Hinted `mmap` without `MAP_FIXED` | hint ignored (relocated to `0x70_0000_0000`) — cannot rely on hints; must reserve |
|
||||
| F9 | `shm_open`+`ftruncate`+2×`mmap(MAP_SHARED\|MAP_FIXED)` at `B+0x70000000` / `B+0x80000000` | works; alias verified (`memfd_create` replacement) |
|
||||
| F10 | `.set _cfb_16, 0x470000000` (64-bit-valued absolute symbol) referenced from C | links, `nm` type `A`, **no rebase fixups** (`dyld_info -fixups`) → ASLR-stable; clang emits GOT loads |
|
||||
| F11 | `-fplan9-extensions` | unknown argument (hard error). `-fms-extensions` accepts `inherits struct`; derived→base pointer passing becomes `-Wincompatible-pointer-types` (already demoted) |
|
||||
| F12 | `-fpermissive` (C), `-Og`, `-Wno-unused-but-set-variable`, `-fno-pie` | accepted (`-fpermissive` is a silent no-op in C) |
|
||||
| F13 | `-Wl,--disable-dynamicbase`, `-Wl,-Ttext-segment=` | ld64 unknown options (already not applied on APPLE) |
|
||||
| F14 | `.section .data` in both `.s` files | assembler error; `.data` works. `.global LameE` (88 `L*` names in `romassets_u.s`) → "non-local symbol required" until `_`-prefixed |
|
||||
| F15 | `#pragma weak X = Y` (sinf.c, cosf.c, objective_status.c, lv.c, spectrum.c) | Darwin emits a *local* alias: cross-TU users get undefined symbol; same-TU `extern` + use → "reference to X is ambiguous" (lv.c:603-606, spectrum.c:266) |
|
||||
| F16 | `-fsyntax-only` sweep, 237 C TUs, with `-fms-extensions -D_FORTIFY_SOURCE=0` + corrected host-header shim paths | **235/237 pass** (fails: lv.c, spectrum.c — F15). 4 fast3d `.cpp` TUs fail on libc++ header shadowing (`include/math.h`, `limits.h`, `assert.h` ahead of the SDK) |
|
||||
| F17 | `port/include/pc_protos.h:34` is gated on `__x86_64__` | on arm64 all ~400 D38 prototypes vanish → 45–63 implicit-declaration warnings per big TU (bg.c, chrai.c, propobj.c, front.c, boss.c) = silent pointer-return truncation. 23 game/asset sites use the same gate |
|
||||
| F18 | GL | fallback table lands on `{4,1,CORE}` on macOS; GLSL `#version 410 core`; VAO created for Core; no compat/>4.1 entry points. 2.1 compat is **not** enough (GLSL 1.30 min, FBO/blit/MSAA, `GL_DEPTH_CLAMP`) |
|
||||
|
||||
---
|
||||
|
||||
## 2. Design: the shifted-window address model
|
||||
|
||||
### 2.1 Invariant
|
||||
|
||||
Let `B = PORT_ADDR_BASE` (compile-time, per platform). Every host pointer that
|
||||
game code may truncate to 32 bits lives in the window `W = [B, B + 4 GiB)`,
|
||||
at host address `B + n64addr`. Therefore:
|
||||
|
||||
- `(u32)host_ptr` for any `host_ptr ∈ W` yields **exactly today's Windows
|
||||
value**. The pointer→u32 direction needs no game-code edits for in-window
|
||||
pointers.
|
||||
- `u32 → host pointer` becomes `B + u32`. This is the only direction that
|
||||
changes, and it is funnelled through one chokepoint.
|
||||
- On Windows/Linux `B = 0`: every chokepoint is an identity, behaviour and
|
||||
codegen are unchanged.
|
||||
|
||||
### 2.2 N64-space layout inside `W` (window offsets; unchanged from today)
|
||||
|
||||
| Range | Content | Host mapping |
|
||||
|---|---|---|
|
||||
| `[0x0000_0000, 0x1000_0000)` | segmented DL addresses (never host memory) | none (reserved `PROT_NONE`) |
|
||||
| `[0x1000_0000, 0x2000_0000)` | cart image + sidecars (`CART_BASE`) | `MAP_FIXED` carve (romdata.c) |
|
||||
| `[0x4000_0000, 0x7000_0000)` | **image-relative encoding** (§2.4) — virtual, never mapped | none |
|
||||
| `[0x7000_0000, +8 MiB)` | DRAM V1 | `shm_open` view 1 (dram.c) |
|
||||
| `[0x8000_0000, +8 MiB)` | DRAM V2 / KSEG0 mirror | `shm_open` view 2 |
|
||||
| `[0xA000_0000, 0xC000_0000)` | game-thread stacks, 8 MiB + guard page each (replaces `MAP_32BIT`) | `MAP_FIXED` carve (libultra.c) |
|
||||
| everything else | reserved, unmapped | `PROT_NONE` |
|
||||
|
||||
`B` proposal: **`0x1000_0000_0000` (16 TiB)** — reserved cleanly (F7), far
|
||||
above libmalloc's regions (`0x1..0x8 <<32`, observed) and the mmap hint region
|
||||
(`0x70_0000_0000`), below `fast3d_ptr_ok`'s `0x8000_0000_0000` bound. Fallback
|
||||
candidate `0x100_0000_0000`. Item **M1.1** confirms on a second machine and
|
||||
fixes the constant.
|
||||
|
||||
### 2.3 Startup contract
|
||||
|
||||
`portAddrInit()` is the **first thing in `main()`** (before SDL, before any
|
||||
large allocation): `mach_vm_map(task, &B, 4 GiB, VM_FLAGS_FIXED, PROT_NONE)`.
|
||||
Failure is fatal with a clear message — the same contract as the Windows
|
||||
build's `0x140000000` load-base check (`main.c:176`). Once reserved, carving
|
||||
sub-ranges with `MAP_FIXED` is safe (we own the range). No heap-copy
|
||||
fallbacks on macOS: `romdata` cart map failure is fatal, not degraded.
|
||||
|
||||
### 2.4 Chokepoint API — `port/include/port_addr.h` (new)
|
||||
|
||||
```c
|
||||
#define PORT_ADDR_BASE /* 0 on Windows/Linux; B on PLATFORM_MACOS && PLATFORM_ARM */
|
||||
/* u32 (N64/"physical") -> host pointer. */
|
||||
static inline void *portN64ToHost(u32 a) {
|
||||
if (a >= 0x40000000u && a < 0x70000000u) /* image-relative (D131 generalised) */
|
||||
return (void *)(portImageBase() + (a - 0x40000000u));
|
||||
return (void *)(PORT_ADDR_BASE + (uintptr_t)a);
|
||||
}
|
||||
/* host pointer -> u32. In-window: window offset. In-image: 0x40000000 + image offset. */
|
||||
static inline u32 portHostToN64(const void *p);
|
||||
/* Cast-site macro for game code (D3x class). Identity semantics at B == 0. */
|
||||
#define PORT_N64PTR(T, expr) ((T *)portN64ToHost((u32)(expr)))
|
||||
```
|
||||
|
||||
Rewired to it (all in `port/`): `osVirtualToPhysical`/`osPhysicalToVirtual`
|
||||
(`libultra.c:1442-1443`), `OS_K0_TO_PHYSICAL`/`OS_PHYSICAL_TO_K0`
|
||||
(`port/shim/PR/os.h:34,37` — subtract/add `B + 0x70000000`), `PHYS_TO_K0`
|
||||
(`port/shim/PR/R4300.h:25`, `port/shim/R4300.h:14`), fast3d `seg_addr`
|
||||
(`gfx_pc.cpp:2881-2935` — replace the `mod_hi` block with the image-relative
|
||||
rule; add `B` to the `< 0x800000` and pass-through returns), the fast3d
|
||||
range classifier (`gfx_pc.cpp:630-635` — compare `p - B`), `G_MW_SEGMENT`
|
||||
(`:2324-2327`) and `G_MW_NUMLIGHT` (`:2317`), mixer `osPhysicalToVirtual`
|
||||
users (`mixer.c:147,152,297`), `piServiceDma` (`libultra.c:1001`),
|
||||
`dramHostAddrValid` (`libultra.c:909-911`), `romdataIsCartAddr`
|
||||
(`romdata.c:441-451`), `n64stubs.c:94-107` (`0x70700000` literal).
|
||||
|
||||
**Why image-relative reproduces D131 exactly on Windows:** the image base is
|
||||
`0x1_4000_0000`, so `0x40000000 + (p - image_base) == (u32)p` — the current
|
||||
truncation result. On Linux (`-Ttext-segment=0x20000000`) `&sym` currently
|
||||
passes through `seg_addr` untouched; under the new rule it round-trips
|
||||
through `0x4xxxxxxx` to the same pointer. No behaviour change either way.
|
||||
|
||||
### 2.5 Absolute symbols
|
||||
|
||||
`dram_syms.s` (3 symbols) and `romassets_<region>.s` (1685 cart symbols) are
|
||||
generated with `B +` added on Darwin, Mach-O syntax (`.data`, `_` prefix).
|
||||
Verified viable by F10. The generator (`scripts/gen_romassets.py`) grows a
|
||||
`--darwin --base 0x...` mode; `B` is defined in exactly two places
|
||||
(`port_addr.h` and the CMake variable that feeds the generator) with a
|
||||
`_Static_assert`/CMake check that they agree.
|
||||
|
||||
### 2.6 The residue: raw casts in game code
|
||||
|
||||
Game code sites that turn a `u32` back into a pointer without going through a
|
||||
chokepoint are the only thing the model cannot fix by construction. Grep
|
||||
estimates (heuristic, noisy): 117 `(u32|s32)&sym` in 21 files, ~278
|
||||
`(T *)obj->field`-shaped casts, 7 `romptr_t`, 5 existing `PORT_PTRADD`. The
|
||||
authoritative census is the compiler (item **M2.1**): clang's
|
||||
`-Wint-to-pointer-cast`, `-Wpointer-to-int-cast` and `-Wint-conversion`
|
||||
(all warnings, none demoted to off) list every site precisely once M0 links.
|
||||
Each `u32 → pointer` site becomes `PORT_N64PTR(T, expr)`; each
|
||||
`&image_symbol → u32` site becomes `portHostToN64(&sym)`; in-window
|
||||
`ptr → u32` truncations are left alone. Every edit is identity at `B = 0`.
|
||||
|
||||
### 2.7 What this model deliberately does NOT do
|
||||
|
||||
- No PD-style relocatable/offset addressing rewrite of game structures.
|
||||
- No change to `Gwords {uintptr_t w0, w1}` (already 64-bit-safe).
|
||||
- No attempt to place the executable inside `W` (F3: not controllable).
|
||||
|
||||
---
|
||||
|
||||
## 3. Work items
|
||||
|
||||
Sizes: **S** ≤1 h, **M** 1–3 h, **L** half-day+. "mechanic" = Sonnet subagent
|
||||
with the brief below; "integrator" = session model. Budgets are per
|
||||
dev-process.md §1; on expiry: revert probes, leave the tree buildable, write up.
|
||||
|
||||
Common to every item — **READ FIRST:** this doc §2; `docs/porting-notes.md`
|
||||
(headers); `AGENTS.md` non-negotiables. **CONSTRAINTS:** no game-logic
|
||||
changes; `src/`/`assets/` edits only where an item lists them and only in the
|
||||
sanctioned mechanical classes; N64 build (`Makefile`, `tools/`, `rsp/`, `ld/`)
|
||||
untouched; new findings appended to `docs/dev/findings.md` §F/§H under the
|
||||
next free `Dxx` (last used at time of writing: D293) and indexed at the top of
|
||||
§F. **VERIFY** for build-affecting items always ends with
|
||||
`./build-pc.sh ntsc-final` (or the explicit target-only build the item names).
|
||||
|
||||
### Phase M0 — compile and link on macOS arm64 (no runtime expected)
|
||||
|
||||
Goal: `./build-pc.sh ntsc-final` produces `build-pc/ge007.*` on this Mac.
|
||||
`B` is still 0 in this phase (address model stubbed), so the binary will not
|
||||
boot; the milestone is a clean link + the M2 census becoming available.
|
||||
|
||||
| ID | Title | Who | Size | Deps | Files |
|
||||
|---|---|---|---|---|---|
|
||||
| M0.1 | CMake: Apple-clang toolchain path | mechanic | M | — | `CMakeLists.txt`, `cmake/*.cmake`, `build-pc.sh`, `docs/building.md` |
|
||||
| M0.2 | `__x86_64__` → `PLATFORM_64BIT` as the 64-bit-PC gate | mechanic | S | — | `port/include/pc_protos.h`, `port/include/platform.h`, + the 23 game/asset sites listed |
|
||||
| M0.3 | Darwin mode for generated assembly | mechanic | M | M0.1 | `scripts/gen_romassets.py`, `port/src/dram_syms.s` (→ generated), `CMakeLists.txt` (gen invocation) |
|
||||
| M0.4 | `#pragma weak X = Y` on Darwin | integrator → mechanic | S | — | `src/libultra/gu/sinf.c`, `cosf.c`, `src/game/objective_status.c`, `lv.c`, `spectrum.c`, `port/src/darwin_compat.c` (new) |
|
||||
| M0.5 | Header/libc clashes on Darwin | mechanic | M | M0.1 | `port/include/pc_protos.h`, `port/src/pc_netorder.c`, `port/shim/*`, `port/src/{romdata,romconvert,pccg,pcmodels,fs}.c`, `port/src/system.c` |
|
||||
| M0.6 | fast3d C++ TUs vs libc++ header shadowing | mechanic | M | M0.1 | `port/shim/` (new C++-route shims for `math.h`/`limits.h`/`assert.h`), `CMakeLists.txt` |
|
||||
| M0.7 | macOS branches: `crash.c`, `system.c` | mechanic | M | — | `port/src/crash.c`, `port/src/system.c` |
|
||||
| M0.8 | macOS stubs for `dram.c`/`romdata.c`/`libultra.c` low-stack (compile-only) | mechanic | S | — | `port/src/dram.c`, `port/src/romdata.c`, `port/src/libultra.c` |
|
||||
| M0.9 | Link-check + first `findings.md` batch | integrator | S | M0.1–M0.8 | `docs/dev/findings.md` |
|
||||
|
||||
**M0.1 — CMake: Apple-clang toolchain path.**
|
||||
Recipe: (a) detect clang (`CMAKE_C_COMPILER_ID STREQUAL "Clang"` or
|
||||
`AppleClang`) and in the `if(NOT MINGW)` block at `CMakeLists.txt:289-298`
|
||||
emit `-fms-extensions -Wno-microsoft-anon-tag` for clang instead of
|
||||
`-fplan9-extensions`; drop `-fpermissive` for clang; keep the GCC branch
|
||||
intact. (b) For clang add `-Wno-error=implicit-int
|
||||
-Wno-error=incompatible-function-pointer-types` next to the existing
|
||||
`-Wno-error=` set (`:273-277`); do **not** silence `-Wint-to-pointer-cast`,
|
||||
`-Wpointer-to-int-cast`, `-Wint-conversion` (they are the M2 census).
|
||||
(c) `add_definitions(-D_FORTIFY_SOURCE=0)` on APPLE (F16: the N64
|
||||
`sprintf` prototype vs `__builtin___sprintf_chk`). (d) Host-header shim
|
||||
derivation at `:165-205`: on APPLE derive from
|
||||
`execute_process(xcrun --show-sdk-path)` / `CMAKE_OSX_SYSROOT` →
|
||||
`${SDK}/usr/include/{string,sched,stdlib}.h` instead of
|
||||
`${_PORT_GCC_DIR}/../include`. (e) `:39-45`: set
|
||||
`CMAKE_OSX_DEPLOYMENT_TARGET 11.0` when `CMAKE_SYSTEM_PROCESSOR` is
|
||||
`arm64`/`aarch64` (currently keys off empty `CMAKE_OSX_ARCHITECTURES` →
|
||||
10.13). (f) `find_program(gcc)` at `:27-37` — prefer `clang` on APPLE and
|
||||
update the comment (it says clang rejects `inherits`; F11 shows it does not
|
||||
with `-fms-extensions`). (g) `build-pc.sh`: brew line already right; add a
|
||||
note that `zlib` is keg-only (CMake's `find_package(ZLIB)` finds the SDK
|
||||
zlib — verify, and if so say brew zlib is optional). Budget: 6 configure/build
|
||||
cycles. Verify: `cmake -S . -B build-pc -DROMID=ntsc-final` succeeds; `cmake
|
||||
--build build-pc --target ge007 -- -k 2>&1 | tee /tmp/m01.log`; report the
|
||||
distinct remaining error classes (expected: F14 asm, F15 pragma weak, F17
|
||||
implicit decls, libc++ shadowing, `memfd_create`, `crashDumpThreads`) — those
|
||||
belong to M0.2–M0.8, not this item.
|
||||
|
||||
**M0.2 — `__x86_64__` → `PLATFORM_64BIT`.** Sites (from
|
||||
`grep -rn __x86_64__ src assets include port`): `port/include/pc_protos.h:34`
|
||||
(the gate for the whole D38 header — critical, F17); `src/memp.c:66`;
|
||||
`src/music.c:55,688,711`; `src/game/objecthandler.c:7` (D40 — N64 branch
|
||||
overruns `.bss` by 12 KB on any 64-bit host); `src/game/initunk_005450.c:41`;
|
||||
`src/game/rsp.c:276`; `src/game/image_bank.c:170`;
|
||||
`assets/animationtable_data.h:200-575` (D34); `src/audi.c:10,666,734`;
|
||||
`src/libultra/audio/load.c:26,200,393,496`; `synthesizer.c:23,125`;
|
||||
`synsetfxmix.c:22`, `synsetpan.c:22`, `synsetvol.c:22`; `src/save.c:24`;
|
||||
`port/src/system.c:177` (keep — that one really is x86: `_mm_pause`). Recipe:
|
||||
replace `defined(__x86_64__)` with `defined(PLATFORM_64BIT)` at each listed
|
||||
site (spelling change only; every site is an existing, documented port-class
|
||||
edit); ensure `platform.h` is reachable from those TUs (it is included via
|
||||
`versioninfo.h`/`-include`? — check; if not, `pc_protos.h`-style
|
||||
`-include` or add `#include "platform.h"` to `port/shim/bondconstants.h`).
|
||||
`CMakeLists.txt:217-219` already defines `PLATFORM_64BIT=1` for aarch64 via
|
||||
`cmake/TargetArch.cmake`. Budget: 2 build cycles. Verify: `grep -rn
|
||||
__x86_64__ src assets include port` shows only `system.c:177`; build of
|
||||
`bg.c`, `chrai.c`, `propobj.c`, `front.c`, `boss.c` shows **0**
|
||||
`-Wimplicit-function-declaration` (was 45–63 each).
|
||||
|
||||
**M0.3 — Darwin mode for generated assembly.** Recipe: add
|
||||
`--darwin` (and `--base 0xHEX`, default 0) to `scripts/gen_romassets.py`:
|
||||
emit `.data` not `.section .data`; prefix every symbol with `_`; emit `.set
|
||||
_sym, (base + value)` — 64-bit values are fine (F10). Regenerate
|
||||
`port/src/romassets_u.s` (and `_e`/`_j` if the generator supports them — note
|
||||
they are currently absent, `CMakeLists.txt:417-420`). Convert
|
||||
`port/src/dram_syms.s` into generator output (or a tiny Darwin twin selected
|
||||
by CMake) with the same `--base`. Wire the CMake invocation (pass
|
||||
`PORT_ADDR_BASE` from a cache var; default 0 in M0). Keep ELF output
|
||||
byte-identical when `--darwin` is absent (diff the regenerated file against
|
||||
git). Budget: 4 cycles. Verify: `nm build-pc/CMakeFiles/.../romassets_u.s.o
|
||||
| head` shows `A`-type `_`-prefixed symbols; `nm ... | grep -c ' A '` = 1685;
|
||||
`dyld_info -fixups build-pc/ge007.* | grep -c romassets-symbol-name` = 0 once
|
||||
linked (M0.9).
|
||||
|
||||
**M0.4 — `#pragma weak X = Y` on Darwin.** Integrator first (30 min):
|
||||
read the five sites (`sinf.c:33-34`, `cosf.c:33-34`, `objective_status.c:162`
|
||||
+ consumer `chrai.c:41,2538`, `lv.c:208-216,603-606`, `spectrum.c:49-50,266`)
|
||||
and decide per site the minimal semantics-preserving form under
|
||||
`#if defined(PORT) && defined(__APPLE__)`: for `sinf`/`cosf` a strong
|
||||
definition in a **new port file** `port/src/darwin_compat.c`
|
||||
(`float sinf(float x){return __sinf(x);}` …) so the 25 game TUs keep binding
|
||||
to Rare's polynomial, not libSystem's (fidelity); for the three game-file
|
||||
aliases, a `PORT`-gated `#define X Y` or wrapper — record the choice as a
|
||||
`Dxx` (symbol-aliasing mechanism, ABI class). Then mechanic applies it.
|
||||
Budget: 3 cycles. Verify: `lv.c`, `spectrum.c` compile; link has no
|
||||
undefined `objectiveGetStatus_WEAK`; `nm build-pc/ge007.* | grep -E
|
||||
' T _(sinf|cosf)$'` shows both defined in the executable.
|
||||
|
||||
**M0.5 — Header/libc clashes.** Recipe: (a) `ntohl/ntohs`: on APPLE
|
||||
`<sys/_endian.h>` defines them as macros with `__uint32_t` prototypes;
|
||||
guard the K&R declarations in `pc_protos.h:54-60` and the definitions in
|
||||
`pc_netorder.c:24-32` with `#if !defined(__APPLE__)` (the game's own macros
|
||||
are already `#undef`'d in `port/shim/bondconstants.h:37-38`). (b) K&R
|
||||
redeclarations spelling `size_t` as `unsigned long long`
|
||||
(`romdata.c:25`, `romconvert.c:28`, `pccg.c:24`, `pcmodels.c:26`,
|
||||
`fs.c:18`) → `size_t` (identical on all shipping platforms; hard error the
|
||||
moment the SDK prototype is visible). (c) `system.c:26` `_POSIX_C_SOURCE
|
||||
199309L` hides `readlink` on Darwin → add `_DARWIN_C_SOURCE` on APPLE.
|
||||
(d) Anything else M0.1's log lists under this class. Budget: 3 cycles.
|
||||
Verify: the listed TUs compile warning-free for these classes.
|
||||
|
||||
**M0.6 — fast3d C++ vs libc++.** Recipe: the four `port/fast3d/*.cpp` TUs
|
||||
fail because `include/math.h`, `include/limits.h`, `include/assert.h`
|
||||
shadow the SDK ahead of libc++'s `<cmath>`/`<climits>`/`<cassert>` (F16).
|
||||
Add C++-routed shims in `port/shim/` following the existing pattern
|
||||
(`port/shim/stdlib.h:16-30`: `#ifdef __cplusplus` → host header by absolute
|
||||
SDK path via the CMake-generated `host*.h`, else N64 header). Alternative if
|
||||
that fights libc++: compile the four fast3d TUs with a private include order
|
||||
(`target_include_directories` on an OBJECT library, SDK first). Budget: 5
|
||||
cycles. Verify: all four `.cpp` TUs compile.
|
||||
|
||||
**M0.7 — macOS branches in `crash.c` and `system.c`.** Recipe (crash.c):
|
||||
change the `PLATFORM_LINUX` block guard (`:306-473`) to `PLATFORM_LINUX ||
|
||||
PLATFORM_MACOS`; replace the glibc `uc_mcontext.gregs[REG_*]` reads
|
||||
(`:344-358, 413-417`) with a `PLATFORM_MACOS && PLATFORM_ARM` variant
|
||||
reading `uc->uc_mcontext->__ss.__pc/__fp/__sp/__lr/__x[]`
|
||||
(`<mach/arm/_structs.h>`); keep `backtrace`/`backtrace_symbols`/`dladdr`;
|
||||
ensure `crashDumpThreads` is defined (it is referenced by
|
||||
`libultra.c:264`); note in the log that symbolication is
|
||||
`atos -o ge007 -l <slide>` and print `_dyld_get_image_vmaddr_slide(0)` at
|
||||
crash time. Recipe (system.c): `sysImageBase()` → `(uintptr_t)
|
||||
_dyld_get_image_header(0)` on APPLE; `sysGetExeDir()` → `_NSGetExecutablePath`
|
||||
+ `dirname` (or `SDL_GetBasePath`) instead of `"."`; `$S/` resolution at
|
||||
`:260` (`/proc/self/exe`) → same helper. Budget: 4 cycles. Verify: both TUs
|
||||
compile; `nm | grep crashDumpThreads` defined once.
|
||||
|
||||
**M0.8 — compile-only macOS stubs (address model lands in M1).** Recipe:
|
||||
`dram.c`: add a `PLATFORM_MACOS` branch that compiles (`shm_open` skeleton
|
||||
per F9, addresses still `0x70000000`/`0x80000000` — will fail at runtime,
|
||||
expected); `romdata.c`: `MAP_FIXED_NOREPLACE` path already `#ifdef`'d — no
|
||||
change unless the log says otherwise; `libultra.c:417-438`
|
||||
`portAllocLowStack`: compiles as-is (`MAP_32BIT` exists). Budget: 2 cycles.
|
||||
Verify: link completes.
|
||||
|
||||
**M0.9 — link-check + findings batch (integrator).** Run the AGENTS.md
|
||||
verification ritual (`/linkcheck`): undefined/duplicate symbols across the
|
||||
compiled set; record M0's findings as one `findings.md` batch (F11–F17 each
|
||||
get a `Dxx` row or are folded into one "macOS toolchain" row) and update
|
||||
`docs/building.md` "macOS: compiles, does not run yet (address model: M1)".
|
||||
|
||||
### Phase M1 — the address model in `port/`
|
||||
|
||||
Goal: the macOS binary boots to the first frame with `B ≠ 0`, with the
|
||||
game-code census still pending (expect crashes at un-rewritten cast sites —
|
||||
those are M2). All items here are `port/`-only.
|
||||
|
||||
| ID | Title | Who | Size | Deps | Files |
|
||||
|---|---|---|---|---|---|
|
||||
| M1.1 | Fix `B`; write `port_addr.h` + `portAddrInit()` | integrator | S | M0.9 | `port/include/port_addr.h` (new), `port/src/main.c`, `CMakeLists.txt` |
|
||||
| M1.2 | Rewire OS chokepoints | mechanic | M | M1.1 | `port/src/libultra.c`, `port/shim/PR/os.h`, `port/shim/PR/R4300.h`, `port/shim/R4300.h`, `port/src/n64stubs.c` |
|
||||
| M1.3 | DRAM double-map + cart map + stacks inside `W` | mechanic | M | M1.1 | `port/src/dram.c`, `port/src/romdata.c`, `port/src/libultra.c` (`portAllocLowStack`) |
|
||||
| M1.4 | fast3d `seg_addr` / classifier / moveword on `B` | mechanic | M | M1.1 | `port/fast3d/gfx_pc.cpp` |
|
||||
| M1.5 | Mixer + PI DMA + validity helpers on `B` | mechanic | S | M1.1 | `port/src/mixer.c`, `port/src/libultra.c` (`piServiceDma`, `dramHostAddrValid`), `port/src/romdata.c` (`romdataIsCartAddr`) |
|
||||
| M1.6 | Absolute symbols regenerated with `B` | mechanic | S | M0.3, M1.1 | generated `.s` via CMake var |
|
||||
| M1.7 | Boot attempt + triage | integrator | M | M1.2–M1.6 | — |
|
||||
|
||||
**M1.1 (integrator).** Confirm `B` on a second Mac if available (run the
|
||||
F7 probe: reserve 4 GiB `PROT_NONE` at candidates via `mach_vm_map
|
||||
VM_FLAGS_FIXED`); fix `PORT_ADDR_BASE = 0x1000_0000_0000` (fallback
|
||||
`0x100_0000_0000`). Write `port_addr.h` per §2.4 with `portImageBase()`
|
||||
(`_dyld_get_image_header(0)` on macOS; `sysImageBase()` elsewhere — on
|
||||
Windows this must equal `0x140000000` so the image-relative rule reproduces
|
||||
D131 exactly; assert it). `portAddrInit()` as §2.3, called first in
|
||||
`main()`; on non-macOS it is a no-op. Expose `PORT_ADDR_BASE` to CMake
|
||||
(`-DPORT_ADDR_BASE=` cache var, APPLE default the constant, else 0) so M1.6
|
||||
can feed the generator; add a `_Static_assert` tying the two.
|
||||
|
||||
**M1.2 (mechanic).** Recipe: `osVirtualToPhysical` → `portHostToN64`,
|
||||
`osPhysicalToVirtual` → `portN64ToHost` (`libultra.c:1442-1443`);
|
||||
`OS_K0_TO_PHYSICAL(x)` → `(u32)((uintptr_t)(x) - (PORT_ADDR_BASE +
|
||||
0x70000000))`, `OS_PHYSICAL_TO_K0(x)` → `portN64ToHost(x)`
|
||||
(`port/shim/PR/os.h:34,37`); `PHYS_TO_K0` likewise (`port/shim/PR/R4300.h:25`,
|
||||
`port/shim/R4300.h:14`); `n64stubs.c:94-107` `0x70700000` literal →
|
||||
`portN64ToHost(0x70700000)`. Budget: 3 cycles. Verify: Windows/Linux
|
||||
semantics unchanged is provable by inspection (`B = 0` ⇒ identity) — state
|
||||
it; macOS builds.
|
||||
|
||||
**M1.3 (mechanic).** Recipe: `dram.c` macOS branch: `shm_open` (unique
|
||||
name, `shm_unlink` immediately) + `ftruncate(8 MiB)` + two
|
||||
`mmap(MAP_SHARED|MAP_FIXED)` at `B+0x70000000` and `B+0x80000000` (F9); fatal
|
||||
on any failure (no fallback). `romdata.c`: on macOS `mmap(MAP_FIXED)` at
|
||||
`B+CART_BASE` (safe post-reservation), fatal on failure — do **not** take the
|
||||
heap-copy path on macOS (comment why: window invariant). `libultra.c`
|
||||
`portAllocLowStack`: macOS branch carves 8 MiB + 16 KiB guard per thread from
|
||||
`[B+0xA0000000, B+0xC0000000)` with a simple bump allocator + free list;
|
||||
`pthread_attr_setstack` as today. Budget: 4 cycles. Verify: a debug log line
|
||||
per mapping with the host address; run `build-pc/ge007 -level_09` far enough
|
||||
to see "DRAM V1 @0x1000_7000_0000 … cart @ … stacks @ …" (crash afterwards is
|
||||
expected in M1).
|
||||
|
||||
**M1.4 (mechanic).** Recipe (`gfx_pc.cpp`): `seg_addr` (`:2881-2935`) —
|
||||
the `w1 < 0x800000` branch returns `portN64ToHost(w1 + 0x80000000)`; the
|
||||
D131 `mod_hi` block is replaced by the image-relative rule (`0x40000000 ≤ w1
|
||||
< 0x70000000` → `portN64ToHost(w1)`); the final pass-through stays for
|
||||
full-width host pointers but a `w1 < 0x1_0000_0000` value there means
|
||||
"in-window N64 address" → `portN64ToHost`. `G_MW_SEGMENT` (`:2324-2327`)
|
||||
and `G_MW_NUMLIGHT` (`:2317`) same treatment. Range classifier
|
||||
(`:630-635`): compare `(uintptr_t)p - PORT_ADDR_BASE` against the cart and
|
||||
DRAM windows. `fast3d_ptr_ok`/`addr_bad` bounds: unchanged (16 TiB <
|
||||
128 TiB). Budget: 3 cycles. Verify: builds; on Windows semantics unchanged
|
||||
(identity) — state the argument per site.
|
||||
|
||||
**M1.5 (mechanic).** `mixer.c:147,152,297` already call
|
||||
`osPhysicalToVirtual` → covered by M1.2; check `mixer.h`'s `u32 dramAddr`
|
||||
ABI needs nothing. `piServiceDma` (`libultra.c:1001`): `memcpy` source from
|
||||
`portN64ToHost(srcPA)`. `dramHostAddrValid` (`:909-911`) and
|
||||
`romdataIsCartAddr` (`romdata.c:441-451`): ranges offset by `B`. Budget: 2
|
||||
cycles.
|
||||
|
||||
**M1.7 (integrator).** Boot `-level_09` (the standard sweep level); triage
|
||||
the first crash against the census (M2.1), which by now exists. Expect the
|
||||
first failures at `(T *)u32field` sites in game code.
|
||||
|
||||
### Phase M2 — game-code cast census and rewrites (the D3x class)
|
||||
|
||||
| ID | Title | Who | Size | Deps | Files |
|
||||
|---|---|---|---|---|---|
|
||||
| M2.1 | Compiler census | mechanic | S | M0.9 | none (report only) |
|
||||
| M2.2 | Classify census → work packets by file | integrator | M | M2.1 | `docs/dev/MACOS-ARM64-PLAN.md` (this doc, §3 table) |
|
||||
| M2.3a–n | Rewrite packets (one per file group, disjoint) | mechanic ×N (parallel) | S–M each | M2.2 | per packet |
|
||||
| M2.4 | Re-run census; assert zero unclassified | mechanic | S | M2.3 | — |
|
||||
|
||||
**M2.1 — census (mechanic).** Recipe: `cmake --build build-pc -- -k 2>&1 |
|
||||
tee /tmp/census.log`; extract `grep -E 'warning: .*\[-W(int-to-pointer-cast|
|
||||
pointer-to-int-cast|int-conversion)\]' /tmp/census.log | sort -u` into
|
||||
`/tmp/census.txt`; also grep `src/ assets/` for `(u32)&`, `(s32)&`,
|
||||
`romptr_t`, `PORT_PTRADD`; produce a table `file:line | direction (u32→ptr /
|
||||
ptr→u32 / implicit) | operand kind (field / &global / local / call result)`.
|
||||
No edits. Budget: 45 min.
|
||||
|
||||
**M2.2 — classify (integrator).** Per site decide: **(a)** `u32 → pointer`
|
||||
where the `u32` holds an N64 address (DRAM/cart/stack) →
|
||||
`PORT_N64PTR(T, expr)`; **(b)** `&global → u32` (image pointer) →
|
||||
`portHostToN64(&sym)` (identical value on Windows); **(c)** in-window
|
||||
`pointer → u32` truncation → leave; **(d)** ROM-serialized field (D3x) →
|
||||
already handled or `PORT_PTRADD`/`romptr_t` pattern; **(e)** genuine
|
||||
integer (not an address) → leave. Group (a)+(b) into packets by file so
|
||||
mechanics never collide (dev-process.md §3); each packet lists exact
|
||||
`file:line` sites and the replacement. Record the class counts in this doc.
|
||||
|
||||
**M2.3 packets (mechanic, parallel).** Per packet brief: FILES = the
|
||||
packet's files only; recipe = the per-site replacement table; every edit is
|
||||
one of the two macro forms — no other change; add a one-line `/* D3x/M2:
|
||||
window-model cast, identity at PORT_ADDR_BASE==0 */`-style comment only
|
||||
where the file has no adjacent D3x comment already. Budget: 2 cycles per
|
||||
packet. Verify: packet TUs compile; census diff shows the packet's sites
|
||||
gone; `./build-pc.sh ntsc-final` green.
|
||||
|
||||
### Phase M3 — runtime bring-up
|
||||
|
||||
| ID | Title | Who | Size | Deps | Files |
|
||||
|---|---|---|---|---|---|
|
||||
| M3.1 | Cocoa main-thread hygiene | mechanic | M | M0 | `port/fast3d/gfx_sdl2.cpp`, `port/src/video.c`, `port/src/input.c` |
|
||||
| M3.2 | Two Core-profile GL bugs + MSAA clamp | mechanic | S | M0 | `port/fast3d/gfx_opengl.cpp`, `port/src/video.c` |
|
||||
| M3.3 | First frame → intro → menu → `-level_09` | integrator | L | M1.7, M2.4, M3.1 | triage only |
|
||||
| M3.4 | arm64 float→int semantics check | integrator | M | M3.3 | `docs/dev/findings.md` |
|
||||
| M3.5 | Level sweep (21 levels, unattended window) | mechanic (runs) + integrator (triage) | L | M3.3 | `docs/dev/LEVEL-STATUS.md` |
|
||||
| M3.6 | Weak-memory-ordering audit of cross-thread flags | integrator | M | M3.3 | `port/src/video.c`, `optionsoverlay.c`, `libultra.c` |
|
||||
|
||||
**M3.1 (mechanic).** Recipe: remove the render-thread `SDL_PollEvent` pump
|
||||
(`gfx_sdl2.cpp:311-360`, called from `gfx_pc.cpp:3301`) — the host thread
|
||||
already pumps (`video.c:502-591`); route Alt+Enter through
|
||||
`videoRequestFullscreen` (`video.c:298-309`); replace the render-thread
|
||||
`exit(0)` calls (`gfx_sdl2.cpp:322/348/356`) with a quit request the host
|
||||
loop honours. Marshal `SDL_SetRelativeMouseMode`/`SDL_ShowCursor`
|
||||
(`input.c:1227,1256,1310,1313`, reached from render + game threads) onto the
|
||||
host thread via the existing `winReq*` queue. `SDL_GameControllerUpdate`
|
||||
(`input.c:622`, game thread) — move to the host pump, snapshot state under
|
||||
the existing lock. Budget: 5 cycles (Windows/Linux behaviour must be
|
||||
unchanged — this is a correctness fix everywhere). Verify: builds; on macOS
|
||||
no `NSInternalInconsistencyException`/main-thread assertions in the log once
|
||||
M3.3 boots.
|
||||
|
||||
**M3.2 (mechanic).** `gfx_opengl.cpp:1271` binds the vector *index* instead
|
||||
of `.fbo` (cf. correct `:1335`) — fix; `:1328` `glReadBuffer(GL_FRONT)` when
|
||||
`use_back=false` (`video.c:722`) is undefined on Cocoa → read the back buffer
|
||||
or the FBO; clamp `gfx_msaa_level` to `GL_MAX_SAMPLES` before `:1187/:1199`.
|
||||
Budget: 2 cycles.
|
||||
|
||||
**M3.4 (integrator).** arm64 `fcvtzs` **saturates** and yields 0 for NaN;
|
||||
x86 `cvttss2si` yields `0x80000000` for overflow and NaN; MIPS yields
|
||||
`0x7FFFFFFF`. Sites validated against x86 behaviour: `floorFloatToInt`
|
||||
(`src/game/math_floor.c:42`, 19 call sites), `FTOFIX32` in `guMtxF2L`
|
||||
(`include/PR/gu.h:38` — also `long` = 64-bit on LP64), D73/D155/D156 guards
|
||||
(`src/game/model.c`). Re-read each; where behaviour differs for
|
||||
out-of-range/NaN inputs, decide whether a port-side helper is needed to
|
||||
match the x86-validated behaviour (a `port/` change; no game-code edit).
|
||||
Record as a `Dxx`.
|
||||
|
||||
### Phase M4 — packaging, CI, docs
|
||||
|
||||
| ID | Title | Who | Size | Files |
|
||||
|---|---|---|---|---|
|
||||
| M4.1 | `.app` bundle target + `Info.plist` + `$S/` under `~/Library/Application Support/ge007` when bundled | mechanic | M | `CMakeLists.txt`, `port/src/system.c`, `port/src/romconvert.c` |
|
||||
| M4.2 | GitHub Actions `macos-14` (arm64) compile job (mirror of the Ubuntu job) | mechanic | S | `.github/workflows/ci.yml` |
|
||||
| M4.3 | `docs/building.md` macOS section; README "Status"; AGENTS.md build note (currently says MSYS2 only) | mechanic | S | docs |
|
||||
| M4.4 | Bundle script (`bundle-mac.sh`, mirrors `bundle-win.sh`; reuse `prepare-assets.py`) | mechanic | M | scripts |
|
||||
|
||||
---
|
||||
|
||||
## 4. Decisions needed from a human
|
||||
|
||||
1. **`B` value** — `0x1000_0000_0000` proposed (F7). Needs one more machine's
|
||||
probe before M1.1 fixes it. If no second Mac: accept the fatal-on-failure
|
||||
contract and revisit if a user report shows the range occupied.
|
||||
2. **`#pragma weak` handling (M0.4)** touches three game files with a
|
||||
`PORT`-gated alias/wrapper. Sanctioned as ABI/linker-mechanism class?
|
||||
(Recommendation: yes, documented as one `Dxx`.)
|
||||
3. **Heap-copy fallback on macOS = fatal** (§2.3). Confirms we never run
|
||||
degraded on macOS; a Mac that cannot reserve 4 GiB `PROT_NONE` at `B`
|
||||
cannot run the port. (Recommendation: yes; it costs nothing — `PROT_NONE`
|
||||
reservations are free.)
|
||||
4. **M3.1 changes Windows/Linux behaviour too** (removing the render-thread
|
||||
event pump). Recommendation: yes — it is an SDL-rules violation on every
|
||||
platform; verify Windows once after.
|
||||
|
||||
## 5. Risks (ranked)
|
||||
|
||||
1. **Census size (M2).** If the compiler census exceeds a few hundred
|
||||
`u32 → pointer` sites, M2 becomes the dominant cost. Mitigation: the
|
||||
rewrites are mechanical and file-partitioned; run 4–6 mechanics in parallel.
|
||||
2. **Game code keeping host pointers in `u32` fields *implicitly*** (no cast,
|
||||
`-Wint-conversion`): each is a latent truncation today too; the census
|
||||
catches them, but classification needs judgement (integrator time).
|
||||
3. **Pointers reaching game code from host allocations outside `W`** (e.g. a
|
||||
port-side `malloc` result handed into a game struct) — invisible to the
|
||||
census. Mitigation: M1.7/M3.3 triage; `dramHostAddrValid`-style debug
|
||||
assert in `portHostToN64` (env-gated) that logs any out-of-window,
|
||||
out-of-image pointer.
|
||||
4. **arm64 float→int and weak memory ordering** (M3.4, M3.6): subtle,
|
||||
non-crashing divergences; needs framediff against the Windows reference.
|
||||
5. **SDL2 on macOS is `sdl2-compat` over SDL3** (brew default): behaviour
|
||||
differences in relative mouse mode / HiDPI are possible; pin to real SDL2
|
||||
(`brew install sdl2` gives compat; real SDL2 is `sdl2@2`? — verify in M0.1).
|
||||
6. **`fast3d_ptr_ok` 47-bit bound** and any other `< 0x8000_0000_0000`
|
||||
checks are fine at 16 TiB but would not be at ≥128 TiB — do not raise `B`
|
||||
above that without checking.
|
||||
|
||||
## 6. Status
|
||||
|
||||
| Phase | State | Notes |
|
||||
|---|---|---|
|
||||
| Research | done | §1 F1–F18, measured 2026-09-18 |
|
||||
| M0 | **superseded by #88** | the clang build/toolchain work is replaced by PR #88's GCC-based macOS layer; only D296 + `gen_macho_syms --base` survive (§0b) |
|
||||
| M1 | **done** | shifted-window address model (D298); self-test ALL PASS on the #88 base |
|
||||
| M2 | **in progress** | game-code re-basing sweep; boot reaches the level stage load |
|
||||
| M3 | partly inherited | #88 supplies the AppKit main-thread guard; the two Core-profile GL fixes and the level sweep remain |
|
||||
| M4 | not started | packaging / CI / docs |
|
||||
|
||||
### Prerequisites to run (easy to miss)
|
||||
|
||||
Two things must be in `data/` before the binary will render anything, both
|
||||
documented in `docs/building.md`:
|
||||
|
||||
1. **The ROM** as `data/ge007.ntsc-final.z64` (SHA-1 `abe01e4a…`, matching the
|
||||
repo's `ge007.u.sha1`).
|
||||
2. **The PC asset sidecars** — `data/pcmodels-ntsc-final/` and
|
||||
`data/pccg-ntsc-final/`. These are ROM-derived and **gitignored**, so a
|
||||
fresh clone has empty directories and the game will look like it has an
|
||||
address bug when it is really serving raw big-endian ROM bytes (that is
|
||||
finding **D69** reproducing). Generate them once:
|
||||
|
||||
```sh
|
||||
python3 tools_pc/d43_emit.py ntsc-final # 512 model sidecars
|
||||
python3 tools_pc/d69_emit.py ntsc-final # 25 bg + 27 stan
|
||||
python3 tools_pc/d88_emit.py ntsc-final --regen # + 21 stage-setup
|
||||
```
|
||||
|
||||
This cost a detour during M2: the `bg.c` big-endian-header crash looked like
|
||||
an un-rebased pointer but was the missing sidecars. PR #88's author ran the
|
||||
same three passes before their 1,500-frame `-level_09` run.
|
||||
|
||||
### Where the boot is (2026-09-18, branch `macos-arm64-gcc`)
|
||||
|
||||
`./build-pc/ge007.aarch64 -level_09`, ROM `data/ge007.ntsc-final.z64`
|
||||
(SHA-1 `abe01e4a…`, matching the repo's `ge007.u.sha1`):
|
||||
|
||||
- ROM load, config, EEPROM, GL 4.1 core, audio, input, threads, VI, timers — OK
|
||||
- language banks, animation tables, `texReset`/`texLoad`, `gimgSync…` — OK
|
||||
- faults in `bg.c` `load_bg_file` (level geometry) — the next M2 site
|
||||
|
||||
M2 batches so far (all `#if defined(PORT)` and identity at
|
||||
`PORT_ADDR_BASE == 0`): the mempool boundary; `language.c` `g_LangBanks`;
|
||||
`initanitable.c` `expand_ani_table_entries`; `initactorpropstuff.c` anim
|
||||
groups / `ANIM_PTR`; `model.c` `bitDescriptors`/`bitStream`; `image_bank.c`
|
||||
`globalbank_rdram_offset` (structural, ~43 sites at once) + `texSetBitstring`;
|
||||
`image.c` `texLoadFromDisplayList`; `bg.c` `BG_SEG_TO_PTR`/`ptr_bg_data`
|
||||
(**under review** — the fold's value depends on the stack address, which
|
||||
differs between Windows and the macOS window, so it needs a careful look).
|
||||
|
||||
### The M2 census is a checklist, not a scoreboard
|
||||
|
||||
The clang census is ~474 game-code rows (`-Wint-conversion` 253,
|
||||
`-Wpointer-to-int-cast` 122, `-Wint-to-pointer-cast` 54,
|
||||
`-Wint-to-void-pointer-cast` 35, `-Wvoid-pointer-to-int-cast` 10). Re-basing
|
||||
edits *add* explicit `u32 → pointer` conversions, so the raw count can rise
|
||||
while progress is made, and one structural fix can clear dozens of rows. The
|
||||
honest progress metric is boot-path reach.
|
||||
|
||||
### Next
|
||||
|
||||
1. Finish the `bg.c` level-geometry re-basing (the current fault), then keep
|
||||
triaging `-level_09` until a frame renders.
|
||||
2. Refresh §1/§3 for the #88/GCC base (the M0 rows elsewhere in this doc are
|
||||
historical).
|
||||
3. M3: the two Core-profile GL bugs (`gfx_opengl.cpp:1271` binds the FBO
|
||||
index instead of `.fbo`; `glReadBuffer(GL_FRONT)`), the MSAA clamp, then
|
||||
the level sweep and the arm64 float→int / memory-ordering checks.
|
||||
+33
-25
@@ -27,6 +27,7 @@
|
||||
#include "gbiex.h" /* GE's G_TRI4 + PD extension opcodes (see header) */
|
||||
|
||||
#include "platform.h"
|
||||
#include "port_addr.h"
|
||||
|
||||
#include "gfx_pc.h"
|
||||
#include "gfx_cc.h"
|
||||
@@ -687,7 +688,9 @@ void gfx_texture_cache_delete_range(const uint8_t* start, const uint8_t* end) {
|
||||
// texels (0xED0F...) decode from the swapped pairs (0x4FCC/0xCC4F) as bright
|
||||
// green/pink — the garbled Rareware-logo pixels.
|
||||
static bool gfx_tex_source_is_c_array(const uint8_t* addr) {
|
||||
const uintptr_t a = (uintptr_t)addr;
|
||||
// Ranges are N64-space, so strip the window base first (identity at
|
||||
// PORT_ADDR_BASE==0, where the ranges are the raw addresses).
|
||||
const uintptr_t a = (uintptr_t)addr - (uintptr_t)PORT_ADDR_BASE;
|
||||
if (a >= 0x10000000u && a < 0x20000000u) return false; // cart map + sidecar
|
||||
if (a >= 0x70000000u && a < 0x90000000u) return false; // V1 dram + KSEG0 mirror
|
||||
return true; // exe image: C-compiled array
|
||||
@@ -3154,11 +3157,20 @@ static void gfx_sp_moveword(uint8_t index, uint16_t offset, uintptr_t data) {
|
||||
rsp.fog_mul = (int16_t)(data >> 16);
|
||||
rsp.fog_offset = (int16_t)data;
|
||||
break;
|
||||
case G_MW_SEGMENT:
|
||||
case G_MW_SEGMENT: {
|
||||
// GE registers segment bases as OS_K0_TO_PHYSICAL(ptr); store the
|
||||
// live host pointer so seg_addr() resolves seg+offset correctly.
|
||||
segmentPointers[(offset >> 2) & 0xff] = (data < 0x800000) ? (data + 0x80000000) : data;
|
||||
// Values that fit in 32 bits are N64-space (a small physical
|
||||
// offset, or a V1 address); full 64-bit values are already host
|
||||
// pointers. Identity at PORT_ADDR_BASE==0.
|
||||
uintptr_t v = (uintptr_t)data;
|
||||
if (v < 0x100000000ULL) {
|
||||
if (v < 0x800000) v += 0x80000000u;
|
||||
v = (uintptr_t)portN64ToHost((u32)v);
|
||||
}
|
||||
segmentPointers[(offset >> 2) & 0xff] = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3799,6 +3811,12 @@ static void gfx_sp_vertex_float(size_t n_vertices, size_t dest_index, const Port
|
||||
}
|
||||
|
||||
static inline void *seg_addr(uintptr_t w1) {
|
||||
// A full 64-bit host pointer (the gSP* macros pack full pointers into w1;
|
||||
// the window base makes every real host pointer >= 4 GiB) passes through
|
||||
// untouched. Only values that fit in 32 bits are N64-space addresses.
|
||||
if (w1 >= 0x100000000ULL) {
|
||||
return (void *)w1;
|
||||
}
|
||||
// GE model files reference GDLs (gSPDisplayList) and vertex arrays by raw
|
||||
// VMA 0x05xxxxxx WITHOUT the LSB set; segment 5 is set per-render to the
|
||||
// live host file base by the game's gSPSegment. Resolve it explicitly
|
||||
@@ -3828,30 +3846,20 @@ static inline void *seg_addr(uintptr_t w1) {
|
||||
return (void *)(segmentPointers[seg] + (w1 & 0x00FFFFFF));
|
||||
}
|
||||
}
|
||||
// GE passes OS_K0_TO_PHYSICAL(ptr) == ptr - 0x80000000 for RAM that lives
|
||||
// in the reserved N64-DRAM region (port/src/dram.c); map it back. The
|
||||
// region is 8 MB, so any offset below 0x800000 came from there.
|
||||
// GE passes OS_K0_TO_PHYSICAL(ptr) == ptr - V1 base for RAM that lives in
|
||||
// the reserved N64-DRAM region (port/src/dram.c); map it back into the V2
|
||||
// view. The region is 8 MB, so any offset below 0x800000 came from there.
|
||||
if (w1 < 0x800000) {
|
||||
return (void *)(w1 + 0x80000000);
|
||||
return portN64ToHost((u32)(w1 + 0x80000000));
|
||||
}
|
||||
// D131: a GBI DL built by game code can reference a COMPILED symbol via
|
||||
// osVirtualToPhysical() (a u32-returning shim), which truncates the
|
||||
// module's 0x1_00000000 high word. Seen in explosionRenderPropSmoke:
|
||||
// gSPMatrix(gdl++, osVirtualToPhysical((void*)&dword_CODE_bss_8007A100),
|
||||
// ..MODELVIEW) -> w1 == 0x40xxxxxx -> wild deref in gfx_sp_matrix. The
|
||||
// module is based at 0x140000000 (fixed, no ASLR), and nothing legit
|
||||
// reaches this fallthrough with a value in [0x40000000, DRAM_V1): DRAM
|
||||
// (>=0x70000000), KSEG0 (>=0x80000000), segmented addrs and sub-0x800000
|
||||
// physical offsets are all handled above. Restore the high word from
|
||||
// this TU's own load address.
|
||||
{
|
||||
static const uintptr_t mod_hi =
|
||||
((uintptr_t)(void *)&segmentPointers[0]) & 0xffffffff00000000ULL;
|
||||
if (mod_hi && w1 >= 0x40000000 && w1 < 0x70000000) {
|
||||
return (void *)(mod_hi | w1);
|
||||
}
|
||||
}
|
||||
return (void *)w1;
|
||||
// Everything else is a 32-bit N64-space address: DRAM V1 (0x70xxxxxx),
|
||||
// KSEG0 (0x80xxxxxx), cart (0x10xxxxxx), or the image-relative encoding
|
||||
// 0x40000000 + (ptr - image base) produced by osVirtualToPhysical() on a
|
||||
// pointer into the executable (D131). portN64ToHost applies the window
|
||||
// base and, for the image-relative range, the image base. On Windows the
|
||||
// image base is 0x140000000, so this reproduces the old mod_hi|w1 exactly;
|
||||
// at PORT_ADDR_BASE==0 the whole thing is the identity it was before.
|
||||
return portN64ToHost((u32)w1);
|
||||
}
|
||||
|
||||
uintptr_t clearMtx;
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
#undef strncpy
|
||||
#endif
|
||||
|
||||
#if defined(PORT) && defined(__x86_64__) && !defined(__cplusplus)
|
||||
#if defined(PORT) && defined(PLATFORM_64BIT) && !defined(__cplusplus)
|
||||
|
||||
#include <PR/ultratypes.h> /* u8..s32, f32, size_t (host on PC) */
|
||||
#include <PR/gbi.h> /* Gfx, Mtx, Vtx, Light (shimmed on PC) */
|
||||
@@ -493,5 +493,5 @@ Gfx * watchRenderControllerOpaque();
|
||||
u32 weaponLoadProjectileModels();
|
||||
void zbufSetBuffer();
|
||||
|
||||
#endif /* PORT && __x86_64__ && !__cplusplus */
|
||||
#endif /* PORT && PLATFORM_64BIT && !__cplusplus */
|
||||
#endif /* _PC_PROTOS_H_ */
|
||||
@@ -0,0 +1,105 @@
|
||||
#ifndef PORT_ADDR_H
|
||||
#define PORT_ADDR_H
|
||||
|
||||
/*
|
||||
* The N64 address-space window (M1 of the macOS port).
|
||||
*
|
||||
* The port realises the N64's 32-bit address space as a range of *host*
|
||||
* addresses, because the game stores addresses in 32-bit fields and 32-bit
|
||||
* arithmetic and expects `(u32)ptr` to round-trip:
|
||||
*
|
||||
* 0x00000000..0x0fffffff segmented DL addresses (never host memory)
|
||||
* 0x10000000..0x1fffffff cart image + sidecars (CART_BASE)
|
||||
* 0x40000000..0x6fffffff image-relative encoding (see below)
|
||||
* 0x70000000..0x707fffff DRAM V1 ("virtual", s32-safe; all RAM symbols)
|
||||
* 0x80000000..0x807fffff DRAM V2 (KSEG0 mirror of V1)
|
||||
* 0xa0000000..0xbfffffff game-thread stacks
|
||||
*
|
||||
* On Windows/Linux that range starts at host address 0, so `(u32)ptr ==
|
||||
* offset` and the pointer IS the N64 address. Native arm64 macOS cannot map
|
||||
* below 4 GiB (__PAGEZONE; see docs/dev/MACOS-ARM64-PLAN.md §1), so there the
|
||||
* whole range is shifted up by PORT_ADDR_BASE. Every game-visible 32-bit value
|
||||
* is then IDENTICAL to the Windows build; only the u32->host-pointer direction
|
||||
* adds the base. PORT_ADDR_BASE is 0 everywhere but macOS, so those builds are
|
||||
* unchanged.
|
||||
*
|
||||
* Image-relative encoding: pointers into the executable image cannot be
|
||||
* truncated into the window (the image is not inside it, and on arm64 it is
|
||||
* PIE with a per-run slide). They are encoded as 0x40000000 + (ptr - image
|
||||
* base). On Windows the image base is 0x140000000, so this equals the raw
|
||||
* `(u32)ptr` truncation the D131 fix relied on; on macOS it makes the round
|
||||
* trip explicit. Ported game code must use portN64ToHost/portHostToN64 (or
|
||||
* PORT_N64PTR) rather than a bare cast wherever a 32-bit field carries a
|
||||
* pointer that is not a plain N64 address.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "platform.h"
|
||||
|
||||
#if defined(PLATFORM_MACOS) && defined(PLATFORM_ARM)
|
||||
/* 16 TiB: reserved cleanly on Apple Silicon, far above libmalloc's regions and
|
||||
* the mmap hint area, and well below fast3d_ptr_ok()'s 128 TiB bound. The
|
||||
* committed port/src/*.darwin.s files are generated with the SAME base
|
||||
* (scripts/gen_romassets.py --darwin --base 0x100000000000); portAddrInit()
|
||||
* checks the two agree at startup. */
|
||||
#define PORT_ADDR_BASE 0x100000000000ULL
|
||||
#else
|
||||
#define PORT_ADDR_BASE 0x0ULL
|
||||
#endif
|
||||
|
||||
/* Size of the N64 address space. */
|
||||
#define PORT_ADDR_WINDOW (1ULL << 32)
|
||||
|
||||
/* Bound on the executable image's size, for classifying a host pointer as
|
||||
* image-relative. The binary is a few MB; 256 MiB is comfortably generous. */
|
||||
#define PORT_IMAGE_MAX (256u << 20)
|
||||
|
||||
/* Set by portAddrInit(): the executable's load address, and whether the image
|
||||
* lies outside the window (so a truncated pointer needs the 0x40000000
|
||||
* encoding). False on Linux, true on Windows and macOS. */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern uintptr_t g_portImageBase;
|
||||
extern int g_portUseImageRel;
|
||||
|
||||
/* Reserve the window (macOS only) and record the image base. Must run before
|
||||
* any of the port's fixed mappings and before large allocations. */
|
||||
void portAddrInit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* u32 N64/physical address -> live host pointer. */
|
||||
static inline void *portN64ToHost(uint32_t a)
|
||||
{
|
||||
if (g_portUseImageRel && a >= 0x40000000u && a < 0x70000000u) {
|
||||
return (void *)(g_portImageBase + (uintptr_t)(a - 0x40000000u));
|
||||
}
|
||||
return (void *)((uintptr_t)PORT_ADDR_BASE + (uintptr_t)a);
|
||||
}
|
||||
|
||||
/* Host pointer -> u32, the inverse of portN64ToHost for in-window and image
|
||||
* pointers. Out-of-range pointers fall back to raw truncation (the pre-M1
|
||||
* behaviour); they should not be stored in 32-bit fields. */
|
||||
static inline uint32_t portHostToN64(const void *p)
|
||||
{
|
||||
uintptr_t v = (uintptr_t)p;
|
||||
if (v - (uintptr_t)PORT_ADDR_BASE < (uintptr_t)PORT_ADDR_WINDOW) {
|
||||
return (uint32_t)(v - (uintptr_t)PORT_ADDR_BASE);
|
||||
}
|
||||
if (g_portUseImageRel && v >= g_portImageBase
|
||||
&& v - g_portImageBase < (uintptr_t)PORT_IMAGE_MAX) {
|
||||
return (uint32_t)(0x40000000u + (v - g_portImageBase));
|
||||
}
|
||||
return (uint32_t)v;
|
||||
}
|
||||
|
||||
/* Cast-site helper for game code (the D3x ABI/layout class): reads a 32-bit
|
||||
* address out of a field/expression and yields a typed pointer. Identity on
|
||||
* Windows/Linux (PORT_ADDR_BASE == 0). */
|
||||
#define PORT_N64PTR(T, expr) ((T *)portN64ToHost((uint32_t)(expr)))
|
||||
|
||||
#endif /* PORT_ADDR_H */
|
||||
+9
-1
@@ -41,11 +41,19 @@
|
||||
# pragma pop_macro("sprintf")
|
||||
# pragma pop_macro("errno")
|
||||
# endif
|
||||
# include "port_addr.h" /* PORT_ADDR_BASE for the V1-base subtractions */
|
||||
|
||||
# undef OS_K0_TO_PHYSICAL
|
||||
# define OS_K0_TO_PHYSICAL(x) ((u32)((char *)(x) - 0x70000000))
|
||||
/* Offset of a DRAM V1 pointer from the V1 base. On macOS the V1 base is
|
||||
* PORT_ADDR_BASE + 0x70000000, so the base must be subtracted too; the result
|
||||
* is a small (< 8 MB) offset that fits s32 and that fast3d's seg_addr()
|
||||
* re-bases into the V2/KSEG0 mirror. Identity behaviour at PORT_ADDR_BASE==0. */
|
||||
# define OS_K0_TO_PHYSICAL(x) ((u32)((uintptr_t)(x) - (PORT_ADDR_BASE + 0x70000000ULL)))
|
||||
|
||||
# undef OS_PHYSICAL_TO_K0
|
||||
/* Identity: callers pass either a live V1 pointer (which is preserved with
|
||||
* its full 64-bit value through the 64-bit GBI words) or a small physical
|
||||
* offset (which fast3d re-bases). Both are unaffected by the window base. */
|
||||
# define OS_PHYSICAL_TO_K0(x) ((void *)(x))
|
||||
|
||||
#else
|
||||
|
||||
@@ -318,6 +318,9 @@ static LONG __stdcall crashHandler(PEXCEPTION_POINTERS exinfo)
|
||||
#include <ctype.h>
|
||||
#include <dlfcn.h>
|
||||
#include <sys/fcntl.h>
|
||||
#if defined(PLATFORM_MACOS)
|
||||
#include <mach-o/dyld.h> /* _dyld_get_image_vmaddr_slide (for atos) */
|
||||
#endif
|
||||
|
||||
static struct sigaction prevSigAction;
|
||||
|
||||
@@ -363,6 +366,27 @@ static void crashStackTrace(char *msg, int sig, void *pc, ucontext_t *ucontext,
|
||||
(void *)ucontext->uc_mcontext.gregs[REG_RSP],
|
||||
(void *)ucontext->uc_mcontext.gregs[REG_RBP]);
|
||||
}
|
||||
#elif defined(PLATFORM_MACOS) && defined(PLATFORM_ARM)
|
||||
/* Darwin's uc_mcontext is a POINTER to __darwin_mcontext64; the arm64
|
||||
* thread state is __ss.__x[0..28], __fp, __lr, __sp, __pc. */
|
||||
if (ucontext) {
|
||||
CRASH_MSG("REGS: x0=%p x1=%p x2=%p x3=%p x4=%p x5=%p x6=%p x7=%p\n",
|
||||
(void *)(uintptr_t)ucontext->uc_mcontext->__ss.__x[0],
|
||||
(void *)(uintptr_t)ucontext->uc_mcontext->__ss.__x[1],
|
||||
(void *)(uintptr_t)ucontext->uc_mcontext->__ss.__x[2],
|
||||
(void *)(uintptr_t)ucontext->uc_mcontext->__ss.__x[3],
|
||||
(void *)(uintptr_t)ucontext->uc_mcontext->__ss.__x[4],
|
||||
(void *)(uintptr_t)ucontext->uc_mcontext->__ss.__x[5],
|
||||
(void *)(uintptr_t)ucontext->uc_mcontext->__ss.__x[6],
|
||||
(void *)(uintptr_t)ucontext->uc_mcontext->__ss.__x[7]);
|
||||
CRASH_MSG("Pc=%p Lr=%p Sp=%p Fp=%p\n",
|
||||
(void *)(uintptr_t)ucontext->uc_mcontext->__ss.__pc,
|
||||
(void *)(uintptr_t)ucontext->uc_mcontext->__ss.__lr,
|
||||
(void *)(uintptr_t)ucontext->uc_mcontext->__ss.__sp,
|
||||
(void *)(uintptr_t)ucontext->uc_mcontext->__ss.__fp);
|
||||
}
|
||||
CRASH_MSG("IMAGE SLIDE: 0x%lx\n",
|
||||
(unsigned long)(uintptr_t)_dyld_get_image_vmaddr_slide(0));
|
||||
#endif
|
||||
CRASH_MSG("PC: ");
|
||||
if (pc) {
|
||||
@@ -422,6 +446,8 @@ static void crashHandler(int sig, siginfo_t *siginfo, void *ctx)
|
||||
pc = (void *)ucontext->uc_mcontext.gregs[REG_RIP];
|
||||
#elif defined(PLATFORM_MACOS) && defined(PLATFORM_X86_64)
|
||||
pc = (void *)ucontext->uc_mcontext->__ss.__rip;
|
||||
#elif defined(PLATFORM_MACOS) && defined(PLATFORM_ARM)
|
||||
pc = (void *)(uintptr_t)ucontext->uc_mcontext->__ss.__pc;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -48,6 +48,7 @@
|
||||
|
||||
#include "platform.h"
|
||||
#include "system.h"
|
||||
#include "port_addr.h"
|
||||
|
||||
#if defined(PLATFORM_WINDOWS)
|
||||
#include <windows.h>
|
||||
@@ -60,8 +61,8 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#define DRAM_V1_BASE 0x70000000UL /* s32-safe "virtual" view */
|
||||
#define DRAM_K0_BASE 0x80000000UL /* KSEG0 mirror view */
|
||||
#define DRAM_V1_BASE (PORT_ADDR_BASE + 0x70000000ULL) /* s32-safe "virtual" view */
|
||||
#define DRAM_K0_BASE (PORT_ADDR_BASE + 0x80000000ULL) /* KSEG0 mirror view */
|
||||
#define DRAM_SIZE 0x00800000UL /* 8 MB */
|
||||
|
||||
void *dramReserve(void)
|
||||
|
||||
+44
-10
@@ -44,6 +44,7 @@
|
||||
|
||||
#include "platform.h"
|
||||
#include "system.h"
|
||||
#include "port_addr.h"
|
||||
#include "crash.h" /* D38: crashDumpThreads() */
|
||||
#include "video.h"
|
||||
#include "audio.h"
|
||||
@@ -418,13 +419,40 @@ void osCreateThread(OSThread *t, OSId id, void (*entry)(void *), void *arg,
|
||||
#if !defined(_WIN32)
|
||||
#include <sys/mman.h>
|
||||
/* The decomp aligns/compares stack-buffer pointers by truncating to u32
|
||||
* (e.g. `(u32)compbuffer` in image.c texLoad) — an N64 assumption. glibc
|
||||
* puts pthread stacks above 4 GiB, so those truncations corrupt. Force each
|
||||
* game-thread stack into the low 2 GiB with MAP_32BIT so every such idiom
|
||||
* works exactly as on the console. Windows pthread stacks are already low. */
|
||||
* (e.g. `(u32)compbuffer` in image.c texLoad) — an N64 assumption. Windows
|
||||
* pthread stacks are already low, so every such idiom works there.
|
||||
*
|
||||
* On macOS the whole N64 window is reserved PROT_NONE by portAddrInit, so each
|
||||
* game-thread stack is carved from the window's stack region
|
||||
* [PORT_ADDR_BASE + 0xA0000000, + 0xC0000000), leaving a PROT_NONE guard page
|
||||
* below it; the stack's host address then truncates to its N64 address exactly
|
||||
* as on Windows.
|
||||
*
|
||||
* On Linux (PORT_ADDR_BASE == 0) the window is not reserved, so keep the
|
||||
* original MAP_32BIT allocation: addresses below 2 GiB truncate identically. */
|
||||
#define PORT_STACK_REGION_OFF 0xA0000000ULL
|
||||
#define PORT_STACK_REGION_SIZE (512ULL << 20)
|
||||
#define PORT_STACK_GUARD 0x4000ULL
|
||||
|
||||
static uintptr_t s_stackNext = 0;
|
||||
|
||||
static void *portAllocLowStack(size_t sz)
|
||||
{
|
||||
#if defined(MAP_32BIT)
|
||||
#if PORT_ADDR_BASE != 0
|
||||
const uintptr_t region = (uintptr_t)PORT_ADDR_BASE + PORT_STACK_REGION_OFF;
|
||||
if (s_stackNext == 0)
|
||||
s_stackNext = region;
|
||||
const uintptr_t base = s_stackNext + PORT_STACK_GUARD;
|
||||
const uintptr_t end = base + sz;
|
||||
if (end > region + PORT_STACK_REGION_SIZE)
|
||||
return NULL;
|
||||
void *p = mmap((void *)base, sz, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
|
||||
if (p != (void *)base)
|
||||
return NULL;
|
||||
s_stackNext = end;
|
||||
return p;
|
||||
#elif defined(MAP_32BIT)
|
||||
void *p = mmap(NULL, sz, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT
|
||||
#if defined(MAP_STACK)
|
||||
@@ -433,8 +461,11 @@ static void *portAllocLowStack(size_t sz)
|
||||
, -1, 0);
|
||||
if (p != MAP_FAILED)
|
||||
return p;
|
||||
#endif
|
||||
return NULL;
|
||||
#else
|
||||
(void)sz;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -911,7 +942,10 @@ static int s_d61opened = 0;
|
||||
|
||||
static int dramHostAddrValid(uintptr_t addr, u32 size)
|
||||
{
|
||||
static const uintptr_t bases[2] = { 0x70000000UL, 0x80000000UL };
|
||||
static const uintptr_t bases[2] = {
|
||||
(uintptr_t)PORT_ADDR_BASE + 0x70000000UL,
|
||||
(uintptr_t)PORT_ADDR_BASE + 0x80000000UL,
|
||||
};
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (addr >= bases[i] && addr + size <= bases[i] + 0x00800000UL)
|
||||
return 1;
|
||||
@@ -1003,7 +1037,7 @@ static void piServiceDma(s32 direction, u32 srcPA, void *dstVA, u32 size)
|
||||
sysFatalError("D60: ROM-read target %p + 0x%X not host-mapped "
|
||||
"(src=0x%08X)", dstVA, size, srcPA);
|
||||
}
|
||||
memcpy(dstVA, (const void *)(uintptr_t)srcPA, size);
|
||||
memcpy(dstVA, portN64ToHost(srcPA), size);
|
||||
} else {
|
||||
/* OS_WRITE: the game never writes the cart (saves go to EEPROM via
|
||||
* osEeprom*, shimmed separately). Log and drop. */
|
||||
@@ -1542,8 +1576,8 @@ void osWritebackDCache(void *addr, int size) { (void)addr; (void)size; }
|
||||
void osWritebackDCacheAll(void) { }
|
||||
void osInvalICache(void *addr, int size) { (void)addr; (void)size; }
|
||||
void osInvalDCache(void *addr, int size) { (void)addr; (void)size; }
|
||||
u32 osVirtualToPhysical(void *va) { return (u32)(uintptr_t)va; }
|
||||
void *osPhysicalToVirtual(u32 pa) { return (void *)(uintptr_t)pa; }
|
||||
u32 osVirtualToPhysical(void *va) { return portHostToN64(va); }
|
||||
void *osPhysicalToVirtual(u32 pa) { return portN64ToHost(pa); }
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* Misc */
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "platform.h"
|
||||
#include "system.h"
|
||||
#include "port_addr.h"
|
||||
#include "config.h"
|
||||
#include "fs.h"
|
||||
#include "romdata.h"
|
||||
@@ -102,6 +103,12 @@ int main(int argc, char **argv)
|
||||
GE007_ROMID, GE007_VERSION_HASH, GE007_VERSION_CODENAME,
|
||||
GE007_ORIGIN_URL);
|
||||
|
||||
/* Reserve the N64 address-space window before anything else maps or
|
||||
* allocates (macOS: 4 GiB PROT_NONE; elsewhere a no-op). Must precede
|
||||
* crashInit so the reservation is in place for every later stage, and any
|
||||
* failure here is reported before SDL/GL are involved. */
|
||||
portAddrInit();
|
||||
|
||||
/* Crash handler first, so any failure below is debuggable. */
|
||||
crashInit();
|
||||
|
||||
|
||||
+9
-2
@@ -23,6 +23,7 @@
|
||||
#include <PR/ultratypes.h>
|
||||
#include <PR/os.h>
|
||||
#include <tlb_manage.h>
|
||||
#include "port_addr.h"
|
||||
|
||||
/* --- Segment start/end getters (normally linker-script symbols) --------- */
|
||||
/* On the PC the ROM is loaded by romdata.c; these are unused. Return 0. */
|
||||
@@ -102,8 +103,14 @@ u8 (*tlbmanageGetTlbAllocatedBlock(void))[TLB_BLOCK_SIZE]
|
||||
* lives up there, at 0x707FFD30). Reclaim ~4 MB of it for the mempool
|
||||
* area; the extra goes to MEMPOOL_STAGE (boss.c:218 gives STAGE
|
||||
* everything that isn't the fixed PERMANENT bank). Stays well clear of
|
||||
* animations_frame_buffer. */
|
||||
return (u8 (*)[TLB_BLOCK_SIZE])0x70700000;
|
||||
* animations_frame_buffer.
|
||||
*
|
||||
* D298 (macOS/arm64): the same reclaim is not quite enough there — the
|
||||
* first level load exhausts STAGE by ~0x30 bytes at a model rwdata alloc
|
||||
* (mempAllocBytesInBank spins). Push the ceiling to the last 0x10000
|
||||
* before animations_frame_buffer, adding ~960 KiB to STAGE. Same
|
||||
* reasoning as above; no game-logic change. */
|
||||
return (u8 (*)[TLB_BLOCK_SIZE])portN64ToHost(0x707F0000);
|
||||
}
|
||||
|
||||
/* --- K&R libc helpers (IDO provided these; MinGW's libc does not) -------- */
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* port_addr.c — the N64 address-space window (see port/include/port_addr.h).
|
||||
*
|
||||
* On macOS/arm64 the whole window is reserved PROT_NONE up front so that the
|
||||
* fixed-address carves (cart, DRAM V1/V2, game-thread stacks, in dram.c /
|
||||
* romdata.c / libultra.c) land inside a range the process already owns and
|
||||
* cannot collide with libmalloc or the dyld shared cache. Reserving is cheap:
|
||||
* PROT_NONE pages are not committed.
|
||||
*
|
||||
* On Windows/Linux PORT_ADDR_BASE is 0 and this is a no-op beyond recording
|
||||
* the image base.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "platform.h"
|
||||
#include "system.h"
|
||||
#include "port_addr.h"
|
||||
|
||||
#if defined(PLATFORM_MACOS) && defined(PLATFORM_ARM)
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_vm.h>
|
||||
#endif
|
||||
|
||||
uintptr_t g_portImageBase = 0;
|
||||
int g_portUseImageRel = 0;
|
||||
|
||||
/* Defined by port/src/dram_syms*.s; must equal PORT_ADDR_BASE + 0x70000000. */
|
||||
extern unsigned char cfb_16[];
|
||||
|
||||
/* ROM-free verification of the address model: window round-trips for each
|
||||
* region, the absolute-symbol base, and the image-relative encoding. Logs
|
||||
* PASS/FAIL for each so a run without a ROM still exercises the core. */
|
||||
static int portAddrCheck(const char *what, int ok)
|
||||
{
|
||||
sysLogPrintf(ok ? LOG_INFO : LOG_ERROR, "portAddr: %-26s %s",
|
||||
what, ok ? "PASS" : "FAIL");
|
||||
return ok;
|
||||
}
|
||||
|
||||
static void portAddrSelfTest(void)
|
||||
{
|
||||
const uintptr_t B = (uintptr_t)PORT_ADDR_BASE;
|
||||
int ok = 1;
|
||||
ok &= portAddrCheck("host->n64 DRAM V1",
|
||||
portHostToN64((void *)(B + 0x70001234u)) == 0x70001234u);
|
||||
ok &= portAddrCheck("n64->host DRAM V1",
|
||||
portN64ToHost(0x70001234u) == (void *)(B + 0x70001234u));
|
||||
ok &= portAddrCheck("host->n64 DRAM V2",
|
||||
portHostToN64((void *)(B + 0x80005678u)) == 0x80005678u);
|
||||
ok &= portAddrCheck("host->n64 cart",
|
||||
portHostToN64((void *)(B + 0x10456789u)) == 0x10456789u);
|
||||
ok &= portAddrCheck("n64->host cart",
|
||||
portN64ToHost(0x10456789u) == (void *)(B + 0x10456789u));
|
||||
ok &= portAddrCheck("cfb_16 at base+DRAM_V1",
|
||||
(uintptr_t)cfb_16 == B + 0x70000000u);
|
||||
if (g_portUseImageRel) {
|
||||
ok &= portAddrCheck("host->n64 image",
|
||||
portHostToN64((void *)(g_portImageBase + 0x1234u)) == 0x40001234u);
|
||||
ok &= portAddrCheck("n64->host image",
|
||||
portN64ToHost(0x40001234u) == (void *)(g_portImageBase + 0x1234u));
|
||||
}
|
||||
sysLogPrintf(ok ? LOG_INFO : LOG_ERROR, "portAddr: selftest %s",
|
||||
ok ? "ALL PASS" : "FAILURES");
|
||||
}
|
||||
|
||||
void portAddrInit(void)
|
||||
{
|
||||
g_portImageBase = sysImageBase();
|
||||
/* The image needs the 0x40000000 encoding iff it lies outside the window,
|
||||
* i.e. its address does not survive a u32 truncation. False on Linux
|
||||
* (image at 0x20000000, inside the window), true on Windows (0x140000000)
|
||||
* and macOS (0x1_00xxxxxx + slide). */
|
||||
g_portUseImageRel = (g_portImageBase >= (uintptr_t)PORT_ADDR_WINDOW) ? 1 : 0;
|
||||
|
||||
#if PORT_ADDR_BASE != 0
|
||||
{
|
||||
/* Non-clobbering: VM_FLAGS_FIXED without VM_FLAGS_OVERWRITE fails with
|
||||
* KERN_NO_SPACE if the range is already in use, rather than silently
|
||||
* replacing a live mapping (mmap MAP_FIXED on macOS does the latter). */
|
||||
mach_vm_address_t addr = (mach_vm_address_t)PORT_ADDR_BASE;
|
||||
kern_return_t kr = mach_vm_map(mach_task_self(), &addr,
|
||||
(mach_vm_size_t)PORT_ADDR_WINDOW, 0,
|
||||
VM_FLAGS_FIXED, MEMORY_OBJECT_NULL, 0, FALSE,
|
||||
VM_PROT_NONE, VM_PROT_ALL, VM_INHERIT_DEFAULT);
|
||||
if (kr != KERN_SUCCESS || addr != (mach_vm_address_t)PORT_ADDR_BASE) {
|
||||
sysFatalError("portAddr: cannot reserve the 4 GiB N64 window at "
|
||||
"0x%llx (%s). See docs/dev/MACOS-ARM64-PLAN.md sec 2.",
|
||||
(unsigned long long)PORT_ADDR_BASE, mach_error_string(kr));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The committed .darwin.s absolute symbols must have been generated with
|
||||
* the same --base; cfb_16 is a region-independent sentinel for that. */
|
||||
if ((uintptr_t)cfb_16 != (uintptr_t)PORT_ADDR_BASE + 0x70000000ULL) {
|
||||
sysFatalError("portAddr: dram_syms base mismatch (cfb_16=%p, expected 0x%llx). "
|
||||
"Regenerate with: scripts/gen_romassets.py <region> --darwin "
|
||||
"--base 0x%llx --rom-size <size> --out ... --dram-out ...",
|
||||
(void *)cfb_16,
|
||||
(unsigned long long)((uintptr_t)PORT_ADDR_BASE + 0x70000000ULL),
|
||||
(unsigned long long)PORT_ADDR_BASE);
|
||||
}
|
||||
|
||||
sysLogPrintf(LOG_INFO, "portAddr: window base=0x%llx image=0x%llx image_rel=%d",
|
||||
(unsigned long long)PORT_ADDR_BASE,
|
||||
(unsigned long long)g_portImageBase, g_portUseImageRel);
|
||||
|
||||
portAddrSelfTest();
|
||||
}
|
||||
+22
-12
@@ -45,6 +45,7 @@ extern int snprintf(char *str, size_t maxsize, const char *format, ...);
|
||||
#include "pcmodels.h"
|
||||
#include "pccg.h"
|
||||
#include "romconvert.h"
|
||||
#include "port_addr.h"
|
||||
|
||||
/* D50: struct font/fontchar layouts for the font-segment re-layout. Order
|
||||
* matters (see pcmodels.c): ultra64.h must finish before bondtypes.h. */
|
||||
@@ -60,7 +61,11 @@ extern int snprintf(char *str, size_t maxsize, const char *format, ...);
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#define CART_BASE 0x10000000u
|
||||
#define CART_BASE 0x10000000u /* N64 cart address */
|
||||
/* Host address the ROM is mapped at (PORT_ADDR_BASE + CART_BASE; identity on
|
||||
* Windows/Linux). Game-visible 32-bit cart values stay CART_BASE-based; this
|
||||
* is only for the mapping and the host-side pointers into it. */
|
||||
#define CART_HOST ((uintptr_t)portN64ToHost(CART_BASE))
|
||||
|
||||
static u8 *rom = NULL; /* heap copy (fallback path) */
|
||||
static u32 romSize = 0;
|
||||
@@ -240,15 +245,15 @@ static void romdataRaw16Walk(const u8 *ctl, u32 ctlSize, u8 *tbl, u32 tblSize,
|
||||
static int romdataFinishCartMap(const char *tok, u8 *img,
|
||||
u32 sideTotal, u32 cgTotal)
|
||||
{
|
||||
memcpy((void *)(uintptr_t)CART_BASE, img, romSize);
|
||||
memcpy((void *)CART_HOST, img, romSize);
|
||||
free(img);
|
||||
mappedAtCartBase = 1;
|
||||
sysLogPrintf(LOG_INFO, "romdataInit: %s (%u bytes) mapped at 0x%08X "
|
||||
"(cart base)%s%s", tok, romSize, CART_BASE,
|
||||
sideTotal ? ", + model sidecars" : "",
|
||||
cgTotal ? ", + bg/stan sidecars" : "");
|
||||
pcmodelsLoadSidecars(CART_BASE, romSize);
|
||||
pccgLoadSidecars(CART_BASE + romSize + pcmodelsTotalSize());
|
||||
pcmodelsLoadSidecars(CART_HOST, romSize);
|
||||
pccgLoadSidecars(CART_HOST + romSize + pcmodelsTotalSize());
|
||||
|
||||
/* D55: the RLE folder-menu background at `unknown2` has a big-endian w/h
|
||||
* header that rle_expand_8bit() reads little-endian; match the N64 .data
|
||||
@@ -374,9 +379,9 @@ int romdataInit(void)
|
||||
{
|
||||
u32 maplen = romSize + sideTotal + cgTotal;
|
||||
#if defined(PLATFORM_WINDOWS)
|
||||
void *at = VirtualAlloc((LPVOID)CART_BASE, maplen,
|
||||
void *at = VirtualAlloc((LPVOID)CART_HOST, maplen,
|
||||
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
||||
if (at == (void *)(uintptr_t)CART_BASE)
|
||||
if (at == (void *)CART_HOST)
|
||||
return romdataFinishCartMap(tok, img, sideTotal, cgTotal);
|
||||
if (at)
|
||||
VirtualFree(at, 0, MEM_RELEASE);
|
||||
@@ -387,8 +392,10 @@ int romdataInit(void)
|
||||
/* POSIX: anonymous fixed-address mmap. MAP_FIXED_NOREPLACE (Linux
|
||||
* 4.17+) fails instead of clobbering an existing mapping; where it
|
||||
* is unavailable the plain hint is advisory and the == check below
|
||||
* catches a relocated result. */
|
||||
* catches a relocated result. On macOS portAddrInit has already
|
||||
* reserved the whole window, so MAP_FIXED lands inside our range. */
|
||||
int flags = MAP_PRIVATE | MAP_ANONYMOUS;
|
||||
#ifndef PLATFORM_MACOS
|
||||
#ifdef MAP_FIXED_NOREPLACE
|
||||
flags |= MAP_FIXED_NOREPLACE;
|
||||
#elif defined(PLATFORM_MACOS)
|
||||
@@ -397,10 +404,13 @@ int romdataInit(void)
|
||||
* otherwise treats CART_BASE only as a hint, relocating it. */
|
||||
flags |= MAP_FIXED;
|
||||
#endif
|
||||
void *at = mmap((void *)(uintptr_t)CART_BASE, maplen,
|
||||
#else
|
||||
flags |= MAP_FIXED;
|
||||
#endif
|
||||
void *at = mmap((void *)CART_HOST, maplen,
|
||||
PROT_READ | PROT_WRITE, flags, -1, 0);
|
||||
int mapErrno = errno;
|
||||
if (at != MAP_FAILED && at == (void *)(uintptr_t)CART_BASE) {
|
||||
if (at != MAP_FAILED && at == (void *)CART_HOST) {
|
||||
mappedLen = maplen;
|
||||
return romdataFinishCartMap(tok, img, sideTotal, cgTotal);
|
||||
}
|
||||
@@ -425,9 +435,9 @@ void romdataDestroy(void)
|
||||
{
|
||||
if (mappedAtCartBase) {
|
||||
#if defined(PLATFORM_WINDOWS)
|
||||
VirtualFree((LPVOID)CART_BASE, 0, MEM_RELEASE);
|
||||
VirtualFree((LPVOID)CART_HOST, 0, MEM_RELEASE);
|
||||
#else
|
||||
munmap((void *)(uintptr_t)CART_BASE, (size_t)mappedLen);
|
||||
munmap((void *)CART_HOST, (size_t)mappedLen);
|
||||
mappedLen = 0;
|
||||
#endif
|
||||
mappedAtCartBase = 0;
|
||||
@@ -440,7 +450,7 @@ void romdataDestroy(void)
|
||||
const u8 *romdataGetRom(void)
|
||||
{
|
||||
if (mappedAtCartBase)
|
||||
return (const u8 *)(uintptr_t)CART_BASE;
|
||||
return (const u8 *)CART_HOST;
|
||||
return rom;
|
||||
}
|
||||
u32 romdataGetRomSize(void) { return romSize; }
|
||||
|
||||
+45
-10
@@ -27,6 +27,9 @@
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <sys/stat.h>
|
||||
#if defined(PLATFORM_MACOS)
|
||||
#include <mach-o/dyld.h> /* _dyld_get_image_header, _NSGetExecutablePath */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "system.h"
|
||||
@@ -59,12 +62,46 @@ uintptr_t sysImageBase(void)
|
||||
{
|
||||
#if defined(PLATFORM_WINDOWS)
|
||||
return (uintptr_t)GetModuleHandleW(NULL);
|
||||
#elif defined(PLATFORM_MACOS)
|
||||
/* The mach_header of the main image == its load address. Unlike Windows
|
||||
* there is no fixed base: arm64 is PIE-only (and `-image_base` is ignored),
|
||||
* so this is 0x1_0000_0000 + a per-run ASLR slide. M1's image-relative
|
||||
* address rule uses this; get the slide from _dyld_get_image_vmaddr_slide. */
|
||||
return (uintptr_t)_dyld_get_image_header(0);
|
||||
#else
|
||||
/* TODO: parse /proc/self/maps for the first executable mapping. */
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Fill `buf` with the directory containing the executable, or "" on failure.
|
||||
* Linux reads /proc/self/exe; macOS uses _NSGetExecutablePath (no /proc, and
|
||||
* _POSIX_C_SOURCE=199309L above hides readlink on Darwin). */
|
||||
static void getExeDir(char *buf, size_t buflen)
|
||||
{
|
||||
buf[0] = 0;
|
||||
#if defined(PLATFORM_MACOS)
|
||||
uint32_t n = (uint32_t)buflen;
|
||||
if (_NSGetExecutablePath(buf, &n) == 0) {
|
||||
char *slash = strrchr(buf, '/');
|
||||
if (slash) *slash = 0; else buf[0] = 0;
|
||||
} else {
|
||||
buf[0] = 0;
|
||||
}
|
||||
#elif defined(PLATFORM_LINUX)
|
||||
ssize_t n = readlink("/proc/self/exe", buf, buflen - 1);
|
||||
if (n > 0) {
|
||||
buf[n] = 0;
|
||||
char *slash = strrchr(buf, '/');
|
||||
if (slash) *slash = 0; else buf[0] = 0;
|
||||
} else {
|
||||
buf[0] = 0;
|
||||
}
|
||||
#else
|
||||
(void)buf; (void)buflen;
|
||||
#endif
|
||||
}
|
||||
|
||||
int64_t sysGetTime(void)
|
||||
{
|
||||
return (int64_t)time(NULL);
|
||||
@@ -201,6 +238,13 @@ const char *sysGetExeDir(void)
|
||||
*slash = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (exeDir[0] == '.' && exeDir[1] == 0) {
|
||||
char d[512];
|
||||
getExeDir(d, sizeof(d));
|
||||
if (d[0])
|
||||
snprintf(exeDir, sizeof(exeDir), "%s", d);
|
||||
}
|
||||
#endif
|
||||
return exeDir;
|
||||
}
|
||||
@@ -257,16 +301,7 @@ const char *sysResolvePath(const char *path)
|
||||
else {
|
||||
static char sexedir[1024] = "";
|
||||
if (!sexedir[0]) {
|
||||
ssize_t n = readlink("/proc/self/exe", sexedir, sizeof(sexedir) - 1);
|
||||
if (n > 0) {
|
||||
char *slash;
|
||||
sexedir[n] = 0;
|
||||
slash = strrchr(sexedir, '/');
|
||||
if (slash)
|
||||
*slash = 0;
|
||||
else
|
||||
sexedir[0] = 0;
|
||||
}
|
||||
getExeDir(sexedir, sizeof(sexedir));
|
||||
}
|
||||
if (sexedir[0])
|
||||
snprintf(out, sizeof(out), "%s/data/%s", sexedir, path + 3);
|
||||
|
||||
@@ -1,18 +1,33 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Convert ELF/PE GAS absolute symbols to Mach-O spelling."""
|
||||
"""Convert ELF/PE GAS absolute symbols to Mach-O spelling.
|
||||
|
||||
Darwin needs `.data` (not `.section .data`), `_`-prefixed symbol names, and
|
||||
`.globl` (not `.global`). The cross-platform source files in port/src/ are left
|
||||
untouched; the Mach-O spelling is generated into the build tree.
|
||||
|
||||
--base is the Apple Silicon extension: PORT_ADDR_BASE, the host address the
|
||||
whole N64 address space is shifted to (see port/include/port_addr.h). It is
|
||||
added to every absolute value, so `cfb_16` becomes PORT_ADDR_BASE + 0x70000000.
|
||||
With --base 0 (Intel) the output is byte-identical to the original transform.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import pathlib
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
def main() -> int:
|
||||
if len(sys.argv) != 3:
|
||||
print(f"usage: {sys.argv[0]} INPUT OUTPUT", file=sys.stderr)
|
||||
return 2
|
||||
ap = argparse.ArgumentParser(description=__doc__)
|
||||
ap.add_argument("input")
|
||||
ap.add_argument("output")
|
||||
ap.add_argument("--base", type=lambda s: int(s, 0), default=0,
|
||||
help="host address of the N64 address space "
|
||||
"(PORT_ADDR_BASE; default 0)")
|
||||
args = ap.parse_args()
|
||||
|
||||
source = pathlib.Path(sys.argv[1])
|
||||
output = pathlib.Path(sys.argv[2])
|
||||
source = pathlib.Path(args.input)
|
||||
output = pathlib.Path(args.output)
|
||||
lines = []
|
||||
|
||||
for line in source.read_text(encoding="utf-8").splitlines():
|
||||
@@ -25,11 +40,14 @@ def main() -> int:
|
||||
continue
|
||||
|
||||
match = re.match(
|
||||
r"^(\s*)\.set\s+([A-Za-z_]\w*)(\s*,.*)$", line
|
||||
r"^(\s*)\.set\s+([A-Za-z_]\w*)(\s*,\s*)(0[xX][0-9A-Fa-f]+|\d+)(.*)$",
|
||||
line,
|
||||
)
|
||||
if match:
|
||||
value = int(match.group(4), 0) + args.base
|
||||
lines.append(
|
||||
f"{match.group(1)}.set _{match.group(2)}{match.group(3)}"
|
||||
f"0x{value:X}{match.group(5)}"
|
||||
)
|
||||
continue
|
||||
|
||||
|
||||
+3
-3
@@ -7,7 +7,7 @@
|
||||
#include "speed_graph.h"
|
||||
#if defined(PORT)
|
||||
#include <string.h> /* PC port: memcpy for the CUSTOM_FX_PARAMS_N copy in audioInit (docs/dev/findings.md §11) */
|
||||
#if defined(__x86_64__)
|
||||
#if defined(PLATFORM_64BIT)
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef PORT
|
||||
@@ -666,7 +666,7 @@ s32 amDmaCallback(s32 addr, s32 len, void* state)
|
||||
/* mark it used */
|
||||
dmaPtr->lastFrame = (s32) g_AudioFrameCount;
|
||||
freeBuffer = (dmaPtr->ptr + addr) - dmaPtr->startAddr;
|
||||
#if defined(__x86_64__)
|
||||
#if defined(PLATFORM_64BIT)
|
||||
if (GE_ENVFLAG("GE_MIXERTRACE")) {
|
||||
static FILE *dtf2 = NULL;
|
||||
if (!dtf2) { dtf2 = fopen("mixertrace.log", "a"); if (dtf2) setvbuf(dtf2, NULL, _IONBF, 0); }
|
||||
@@ -734,7 +734,7 @@ s32 amDmaCallback(s32 addr, s32 len, void* state)
|
||||
dmaPtr->lastFrame = g_AudioFrameCount;
|
||||
|
||||
osPiStartDma(&g_DmaIOMessageBuffer[g_NextDMa++], OS_MESG_PRI_HIGH, OS_READ, (u32)addr, freeBuffer, AUDIO_DMA_MAX_BUFFER_LENGTH, &g_DmaMessageQueue);
|
||||
#if defined(__x86_64__)
|
||||
#if defined(PLATFORM_64BIT)
|
||||
if (GE_ENVFLAG("GE_MIXERTRACE")) {
|
||||
static FILE *dtf3 = NULL;
|
||||
if (!dtf3) { dtf3 = fopen("mixertrace.log", "a"); if (dtf3) setvbuf(dtf3, NULL, _IONBF, 0); }
|
||||
|
||||
+1
-1
@@ -833,7 +833,7 @@ void bossMainloop(void)
|
||||
}
|
||||
|
||||
rspReplyMsg = (s32)(&localGfxDoneMsg);
|
||||
rspGfxTaskStart(firstGdl, gdl, 0, (s32*)rspReplyMsg);
|
||||
rspGfxTaskStart(firstGdl, gdl, 0, PORT_N64PTR(s32, rspReplyMsg));
|
||||
|
||||
pendingGfx++;
|
||||
memaSingleDefragPass();
|
||||
|
||||
+23
-17
@@ -7,6 +7,12 @@
|
||||
#include <fr.h>
|
||||
#include <memp.h>
|
||||
#include "bg.h"
|
||||
#if defined(PORT)
|
||||
#include "port_addr.h"
|
||||
#else
|
||||
/* N64 build: the port address window is the identity (see port_addr.h). */
|
||||
#define PORT_N64PTR(T, x) ((T *)(x))
|
||||
#endif
|
||||
#include "bondview.h"
|
||||
#include "chr.h"
|
||||
#include "debug_camera.h"
|
||||
@@ -879,22 +885,22 @@ void load_bg_file(LEVEL_INDEX levelid)
|
||||
lightFixtureInitTables();
|
||||
|
||||
ptr_bg_data = (s32)header;
|
||||
obLoadBGFileBytesAtOffset(levelinfotable[levelentry_index].bg_seg_filename, (u8 *) ptr_bg_data, 0, 0x40);
|
||||
obLoadBGFileBytesAtOffset(levelinfotable[levelentry_index].bg_seg_filename, (u8 *)PORT_N64PTR(void, ptr_bg_data), 0, 0x40);
|
||||
|
||||
if (((levelid && ptr_bg_data) && levelentry_index));
|
||||
|
||||
ptr_bgdata_offsets = ptr_bg_data;
|
||||
ptr_bgdata_room_fileposition_list = (bg_room_data *) BG_SEG_TO_PTR(ptr_bg_data, ((s32 *)ptr_bg_data)[1]);
|
||||
ptr_bgdata_room_fileposition_list = (bg_room_data *) BG_SEG_TO_PTR(ptr_bg_data, ((s32 *)PORT_N64PTR(void, ptr_bg_data))[1]);
|
||||
|
||||
size = (((((u32) ptr_bgdata_room_fileposition_list[1].pPointTableBin) & 0x00ffffff) - 1) | 0xf) + 1;
|
||||
|
||||
ptr_bg_data = (s32) mempAllocBytesInBank(size, 4);
|
||||
obLoadBGFileBytesAtOffset(levelinfotable[levelentry_index].bg_seg_filename, (u8 *) ptr_bg_data, 0, size);
|
||||
obLoadBGFileBytesAtOffset(levelinfotable[levelentry_index].bg_seg_filename, (u8 *)PORT_N64PTR(void, ptr_bg_data), 0, size);
|
||||
|
||||
gptr_stan = (s32) _fileNameLoadToBank(levelinfotable[levelentry_index].bg_stan_filename, 2, 0, 4);
|
||||
|
||||
stanDetermineEOF((struct StanPrefixRecord *) gptr_stan, 0, (u8 *) gptr_stan);
|
||||
stanLoadFile((struct StanPrefixRecord *) gptr_stan);
|
||||
stanDetermineEOF((struct StanPrefixRecord *)PORT_N64PTR(void, gptr_stan), 0, (u8 *)PORT_N64PTR(void, gptr_stan));
|
||||
stanLoadFile((struct StanPrefixRecord *)PORT_N64PTR(void, gptr_stan));
|
||||
|
||||
sub_GAME_7F0B4810(levelinfotable[levelentry_index].levelscale);
|
||||
setLevelScale(levelinfotable[levelentry_index].levelscale);
|
||||
@@ -906,7 +912,7 @@ void load_bg_file(LEVEL_INDEX levelid)
|
||||
sub_GAME_7F08976C(mCurrentLevelVisibilityScale);
|
||||
matrix_4x4_7F058C4C(mCurrentLevelVisibilityScale);
|
||||
|
||||
data = (s32 *)ptr_bg_data;
|
||||
data = (s32 *)PORT_N64PTR(void, ptr_bg_data);
|
||||
dword_CODE_bss_8007BF98 = *data;
|
||||
dword_CODE_bss_8007FF88 = 1;
|
||||
|
||||
@@ -914,7 +920,7 @@ void load_bg_file(LEVEL_INDEX levelid)
|
||||
{
|
||||
dword_CODE_bss_8007FF88 = 2;
|
||||
ptr_bgdata_offsets = (s32)data;
|
||||
ptr_bgdata_room_fileposition_list = (bg_room_data *) BG_SEG_TO_PTR(data, ((s32 *)ptr_bgdata_offsets)[1]);
|
||||
ptr_bgdata_room_fileposition_list = (bg_room_data *) BG_SEG_TO_PTR(data, ((s32 *)PORT_N64PTR(void, ptr_bgdata_offsets))[1]);
|
||||
|
||||
// Keep this fake goto for matching.
|
||||
goto dummy_label_543534; dummy_label_543534: ;
|
||||
@@ -926,25 +932,25 @@ void load_bg_file(LEVEL_INDEX levelid)
|
||||
g_MaxNumRooms++;
|
||||
}
|
||||
|
||||
g_BgPortals = (bg_portal_data_entry *) BG_SEG_TO_PTR(data, ((s32 *)ptr_bgdata_offsets)[2]);
|
||||
g_BgPortals = (bg_portal_data_entry *) BG_SEG_TO_PTR(data, ((s32 *)PORT_N64PTR(void, ptr_bgdata_offsets))[2]);
|
||||
|
||||
if (1);
|
||||
|
||||
if (((s32 *)ptr_bgdata_offsets)[3] == 0)
|
||||
if (((s32 *)PORT_N64PTR(void, ptr_bgdata_offsets))[3] == 0)
|
||||
{
|
||||
dword_CODE_bss_8007FF90 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
dword_CODE_bss_8007FF90 = (s32 *) BG_SEG_TO_PTR(data, ((s32 *)ptr_bgdata_offsets)[3]);
|
||||
dword_CODE_bss_8007FF90 = (s32 *) BG_SEG_TO_PTR(data, ((s32 *)PORT_N64PTR(void, ptr_bgdata_offsets))[3]);
|
||||
|
||||
if (((s32 *)ptr_bgdata_offsets)[4] == 0)
|
||||
if (((s32 *)PORT_N64PTR(void, ptr_bgdata_offsets))[4] == 0)
|
||||
{
|
||||
dword_CODE_bss_8007FF94 = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
dword_CODE_bss_8007FF94 = (f32 *) BG_SEG_TO_PTR(data, ((s32 *)ptr_bgdata_offsets)[4]);
|
||||
dword_CODE_bss_8007FF94 = (f32 *) BG_SEG_TO_PTR(data, ((s32 *)PORT_N64PTR(void, ptr_bgdata_offsets))[4]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3149,7 +3155,7 @@ void bgBuildRoomVtxBounds(s32 roomID)
|
||||
numvertices = ((gdl[cmdindex].dma.par >> 4) & 0xf) + 1;
|
||||
#endif
|
||||
|
||||
vtx = (Vtx *)(SEGMENT_OFFSET(gdl[cmdindex].dma.addr) + (u32)vertices);
|
||||
vtx = (Vtx *)PORT_N64PTR(void, SEGMENT_OFFSET(gdl[cmdindex].dma.addr) + (u32)vertices);
|
||||
|
||||
#if defined(PORT)
|
||||
/* TEMP D69 safety net: the room primary/secondary DL binaries
|
||||
@@ -3573,7 +3579,7 @@ bool bgTestRayIntersectionInRoom(coord3d *from, coord3d *to, coord3d *dir, RoomV
|
||||
|
||||
if (bgTestRayIntersectsBbox(from, dir, (s32 *) (&bboxMin), (s32 *) (&bboxMax)))
|
||||
{
|
||||
if (intersectRayTriangle((Vertex *)((s32)vtxbase - (0 - (idx[0] << 4))), (Vertex *)((s32)vtxbase - (0 - (idx[1] << 4))), (Vertex *)((s32)vtxbase - (0 - (idx[2] << 4))), (coord3d *) (((roomnum * 24) + ((s32) ptr_bgdata_room_fileposition_list)) + 12), from, to, dir, &hitbuf))
|
||||
if (intersectRayTriangle((Vertex *)((s32)vtxbase - (0 - (idx[0] << 4))), (Vertex *)((s32)vtxbase - (0 - (idx[1] << 4))), (Vertex *)((s32)vtxbase - (0 - (idx[2] << 4))), (coord3d *) (((roomnum * 24) + ((uintptr_t) ptr_bgdata_room_fileposition_list)) + 12), from, to, dir, &hitbuf))
|
||||
{
|
||||
tcmd = gdl;
|
||||
dx = ((s32) hitbuf.hitpos.x) - ((s32) from->x);
|
||||
@@ -3758,7 +3764,7 @@ bool bgTestRayIntersectionInRoom(coord3d *from, coord3d *to, coord3d *dir, RoomV
|
||||
|
||||
if (bgTestRayIntersectsBbox(from, dir, (s32 *) (&bboxMin2), (s32 *) (&bboxMax2)))
|
||||
{
|
||||
if (intersectRayTriangle((Vertex *)((s32)vtxbase - (0 - (idx2[0] << 4))), (Vertex *)((s32)vtxbase - (0 - (idx2[1] << 4))), (Vertex *)((s32)vtxbase - (0 - (idx2[2] << 4))), (coord3d *) (((roomnum * 24) + ((s32) ptr_bgdata_room_fileposition_list)) + 12), from, to, dir, &hitbuf))
|
||||
if (intersectRayTriangle((Vertex *)((s32)vtxbase - (0 - (idx2[0] << 4))), (Vertex *)((s32)vtxbase - (0 - (idx2[1] << 4))), (Vertex *)((s32)vtxbase - (0 - (idx2[2] << 4))), (coord3d *) (((roomnum * 24) + ((uintptr_t) ptr_bgdata_room_fileposition_list)) + 12), from, to, dir, &hitbuf))
|
||||
{
|
||||
tcmd = gdl;
|
||||
dx = ((s32) hitbuf.hitpos.x) - ((s32) from->x);
|
||||
@@ -5241,7 +5247,7 @@ void bgRoomCalcBB(s32 room) // canonical name
|
||||
StanRoomBounds limits;
|
||||
u8 wasloaded;
|
||||
|
||||
roomdata = (bg_room_data *) ((s32) ptr_bgdata_room_fileposition_list + room * 24);
|
||||
roomdata = (bg_room_data *) ((uintptr_t) ptr_bgdata_room_fileposition_list + room * 24);
|
||||
|
||||
if (roomdata->pPointTableBin == NULL)
|
||||
{
|
||||
@@ -5274,7 +5280,7 @@ void bgRoomCalcBB(s32 room) // canonical name
|
||||
}
|
||||
|
||||
vertices = g_BgRoomInfo[room].vertices;
|
||||
roomdata = (bg_room_data *) ((s32) ptr_bgdata_room_fileposition_list + room * 24);
|
||||
roomdata = (bg_room_data *) ((uintptr_t) ptr_bgdata_room_fileposition_list + room * 24);
|
||||
|
||||
limits.minX = 0x7fff;
|
||||
limits.minY = 0x7fff;
|
||||
|
||||
@@ -20,7 +20,15 @@ struct levelentry
|
||||
// cannonical name
|
||||
#define PORTMAX 200
|
||||
|
||||
/* D298/M2: the sum is an N64/window offset, so re-base it into the DRAM
|
||||
* window before it becomes a pointer. Identity at PORT_ADDR_BASE == 0. */
|
||||
#if defined(PORT)
|
||||
#include "port_addr.h"
|
||||
#define BG_SEG_TO_PTR(base, off) \
|
||||
((void *) portN64ToHost((u32)(((u32)(base)) + (((u32)(off)) + 0xF1000000))))
|
||||
#else
|
||||
#define BG_SEG_TO_PTR(base, off) ((void *) (((u32) (base)) + (((u32) (off)) + 0xF1000000)))
|
||||
#endif
|
||||
|
||||
typedef struct RoomVtxBatchBounds {
|
||||
s16 gdlindex; // 0x00
|
||||
|
||||
+43
-16
@@ -1,4 +1,9 @@
|
||||
#include <ultra64.h>
|
||||
#if defined(PORT)
|
||||
#include "port_addr.h"
|
||||
#else
|
||||
#define PORT_N64PTR(T, x) ((T *)(x))
|
||||
#endif
|
||||
#ifdef PORT
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -93,8 +98,15 @@
|
||||
|
||||
|
||||
#if defined(VERSION_US)
|
||||
/* D298/M2: the font-table globals are s32 holding truncated pointers
|
||||
* (D88 class); re-base on use. Identity at PORT_ADDR_BASE == 0. */
|
||||
#if defined(PORT)
|
||||
#define BONDVIEW_2ND_FONTTABLE(_param) PORT_N64PTR(void, copy_2ndfonttable)
|
||||
#define BONDVIEW_1ST_FONTTABLE(_param) PORT_N64PTR(void, copy_1stfonttable)
|
||||
#else
|
||||
#define BONDVIEW_2ND_FONTTABLE(_param) copy_2ndfonttable
|
||||
#define BONDVIEW_1ST_FONTTABLE(_param) copy_1stfonttable
|
||||
#endif
|
||||
#elif defined(VERSION_JP) || defined(VERSION_EU)
|
||||
#define BONDVIEW_2ND_FONTTABLE(_param) dword_CODE_bss_jp80079CEC[_param]
|
||||
#define BONDVIEW_1ST_FONTTABLE(_param) dword_CODE_bss_jp80079Cd8[_param]
|
||||
@@ -723,7 +735,7 @@ void solo_char_load(void)
|
||||
pitemheader = NULL;
|
||||
}
|
||||
|
||||
something_with_generating_object(self, prop, item, 0, (WeaponObjRecord *)helddst, (ItemModelFileRecord *)pitemheader);
|
||||
something_with_generating_object(self, prop, item, 0, PORT_N64PTR(WeaponObjRecord, helddst), (ItemModelFileRecord *)pitemheader);
|
||||
}
|
||||
|
||||
chrlvMergeKneelToStand(self, 0.0f);
|
||||
@@ -981,7 +993,7 @@ void bondviewSetCameraMode(s32 arg0)
|
||||
solo_char_load();
|
||||
|
||||
// HACK: ptr_animation_table->data regalloc is backwards
|
||||
sp38 = (struct ModelAnimation *)((s32)stage_intro_anim_table[g_IntroAnimationIndex].anonymous_0 + (s32)&ptr_animation_table->data);
|
||||
sp38 = PORT_N64PTR(struct ModelAnimation, (s32)stage_intro_anim_table[g_IntroAnimationIndex].anonymous_0 + (s32)&ptr_animation_table->data);
|
||||
sp78 = stage_intro_anim_table[g_IntroAnimationIndex].anonymous_2;
|
||||
ftemp_1 = stage_intro_anim_table[g_IntroAnimationIndex].anonymous_1;
|
||||
ftemp_3 = stage_intro_anim_table[g_IntroAnimationIndex].anonymous_3;
|
||||
@@ -1226,7 +1238,15 @@ void bondviewCalcIntroSwirlCamera(s32 index, f32 time, coord3d *pos, coord3d *lo
|
||||
{
|
||||
struct SetupIntroSwirl *base;
|
||||
struct SetupIntroSwirl *loopbase;
|
||||
#if defined(PORT)
|
||||
/* D189/D298: written pointbuf[0..11] via `&pointbuf[i*3]` then dst[3..5]
|
||||
* (i = -1..2), but declared [10] -- a 2-float stack overrun that on arm64
|
||||
* corrupts the saved frame pointer (Fp=0x374d56eac1a00000 at the fault).
|
||||
* N64/MinGW absorb it; give it room on the port. */
|
||||
f32 pointbuf[12];
|
||||
#else
|
||||
f32 pointbuf[10];
|
||||
#endif
|
||||
struct SetupIntroSwirl *swirl;
|
||||
f32 frac;
|
||||
f32 *dst;
|
||||
@@ -1317,7 +1337,7 @@ void bondviewCalcIntroSwirlCamera(s32 index, f32 time, coord3d *pos, coord3d *lo
|
||||
lookat->y = g_CurrentPlayer->field_3C8;
|
||||
lookat->z = g_CurrentPlayer->field_3CC;
|
||||
|
||||
swirl = (void *)(((u32) g_IntroSwirl) + (u32) base);
|
||||
swirl = (void *)(((uintptr_t) g_IntroSwirl) + (uintptr_t) base); /* D298/M2: full-width */
|
||||
|
||||
if (!(swirl->bitflags & 4))
|
||||
{
|
||||
@@ -1371,13 +1391,13 @@ void bondviewFrozenCameraTick(u16 buttons, u16 oldbuttons, struct coord3d *pos,
|
||||
#if defined(VERSION_US)
|
||||
setFontTables(ptrFontZurichBoldChars, ptrFontZurichBold);
|
||||
#ifdef PORT
|
||||
hudmsgBottomShow((char *)(uintptr_t)ptr_random06cam_entry->lang1c.lang_ptr);
|
||||
hudmsgBottomShow(PORT_N64PTR(char, ptr_random06cam_entry->lang1c.lang_ptr));
|
||||
#else
|
||||
hudmsgBottomShow(ptr_random06cam_entry->lang1c.lang_ptr);
|
||||
#endif
|
||||
#else
|
||||
#ifdef PORT
|
||||
hudmsgBottomShow((char *)(uintptr_t)ptr_random06cam_entry->lang1c.lang_ptr, ptrFontZurichBoldChars, ptrFontZurichBold);
|
||||
hudmsgBottomShow(PORT_N64PTR(char, ptr_random06cam_entry->lang1c.lang_ptr), ptrFontZurichBoldChars, ptrFontZurichBold);
|
||||
#else
|
||||
hudmsgBottomShow(ptr_random06cam_entry->lang1c.lang_ptr, ptrFontZurichBoldChars, ptrFontZurichBold);
|
||||
#endif
|
||||
@@ -1390,13 +1410,13 @@ void bondviewFrozenCameraTick(u16 buttons, u16 oldbuttons, struct coord3d *pos,
|
||||
{
|
||||
#if defined(VERSION_US)
|
||||
#ifdef PORT
|
||||
hudmsgBottomShow((char *)(uintptr_t)ptr_random06cam_entry->lang20.lang_ptr);
|
||||
hudmsgBottomShow(PORT_N64PTR(char, ptr_random06cam_entry->lang20.lang_ptr));
|
||||
#else
|
||||
hudmsgBottomShow(ptr_random06cam_entry->lang20.lang_ptr);
|
||||
#endif
|
||||
#else
|
||||
#ifdef PORT
|
||||
hudmsgBottomShow((char *)(uintptr_t)ptr_random06cam_entry->lang20.lang_ptr, ptrFontZurichBoldChars, ptrFontZurichBold);
|
||||
hudmsgBottomShow(PORT_N64PTR(char, ptr_random06cam_entry->lang20.lang_ptr), ptrFontZurichBoldChars, ptrFontZurichBold);
|
||||
#else
|
||||
hudmsgBottomShow(ptr_random06cam_entry->lang20.lang_ptr, ptrFontZurichBoldChars, ptrFontZurichBold);
|
||||
#endif
|
||||
@@ -7975,6 +7995,7 @@ void bondviewFrozenMoveBond(s8 stick_x, s8 stick_y, u16 buttons, u16 oldbuttons)
|
||||
return;
|
||||
}
|
||||
|
||||
room_pointer_tile = (struct StandTile *)0;
|
||||
bondviewFrozenCameraTick(buttons, oldbuttons, &property_pos, &property_pos2, &property_offset, &room_pointer_tile, &stan_walk_start);
|
||||
currentPlayerSetCameraMode(1);
|
||||
bondviewSetCurrentPlayerPosition(&property_pos, &property_pos2, &property_offset, room_pointer_tile, &stan_walk_start);
|
||||
@@ -8445,12 +8466,12 @@ void bondviewUpdateCameraMatrices(coord3d* cam_pos, coord3d* cam_look_dir, coord
|
||||
clpos.x, clpos.y, clpos.z,
|
||||
cam_up->x, cam_up->y, cam_up->z);
|
||||
|
||||
matrix_4x4_set_lookat((Mtxf*) g_CurrentPlayer->field_64,
|
||||
matrix_4x4_set_lookat(PORT_N64PTR(Mtxf, g_CurrentPlayer->field_64),
|
||||
cam_pos->x, cam_pos->y, cam_pos->z,
|
||||
cam_look_dir->x, cam_look_dir->y, cam_look_dir->z,
|
||||
cam_up->x, cam_up->y, cam_up->z);
|
||||
|
||||
matrix_4x4_set_basis_and_position((Mtxf*) g_CurrentPlayer->field_68,
|
||||
matrix_4x4_set_basis_and_position(PORT_N64PTR(Mtxf, g_CurrentPlayer->field_68),
|
||||
cam_pos->x, cam_pos->y, cam_pos->z,
|
||||
cam_look_dir->x, cam_look_dir->y, cam_look_dir->z,
|
||||
cam_up->x, cam_up->y, cam_up->z);
|
||||
@@ -8481,13 +8502,13 @@ void bondviewUpdateCameraMatrices(coord3d* cam_pos, coord3d* cam_look_dir, coord
|
||||
scale = bgGetLevelVisibilityScale();
|
||||
|
||||
matrix_scalar_multiply(scale, spC4.m[0]);
|
||||
guMtxF2L((f32 (*)[4]) &spC4, (Mtx* ) g_CurrentPlayer->field_5C);
|
||||
sub_GAME_7F059334((s32* ) g_CurrentPlayer->field_5C, (s32* ) g_CurrentPlayer->field_60);
|
||||
guMtxF2L((f32 (*)[4]) &spC4, PORT_N64PTR(Mtx, g_CurrentPlayer->field_5C));
|
||||
sub_GAME_7F059334(PORT_N64PTR(s32, g_CurrentPlayer->field_5C), PORT_N64PTR(s32, g_CurrentPlayer->field_60));
|
||||
|
||||
currentPlayerSetMatrix10C8((Mtx* ) g_CurrentPlayer->field_5C);
|
||||
currentPlayerSetMatrix10C4((Mtx* ) g_CurrentPlayer->field_60);
|
||||
currentPlayerSetMatrix10CC((Mtxf* ) g_CurrentPlayer->field_64);
|
||||
currentPlayerSetViewToWorldMtxf((Mtxf* ) g_CurrentPlayer->field_68);
|
||||
currentPlayerSetMatrix10C8(PORT_N64PTR(Mtx, g_CurrentPlayer->field_5C));
|
||||
currentPlayerSetMatrix10C4(PORT_N64PTR(Mtx, g_CurrentPlayer->field_60));
|
||||
currentPlayerSetMatrix10CC(PORT_N64PTR(Mtxf, g_CurrentPlayer->field_64));
|
||||
currentPlayerSetViewToWorldMtxf(PORT_N64PTR(Mtxf, g_CurrentPlayer->field_68));
|
||||
|
||||
sub_GAME_7F078464((s32) lookat);
|
||||
bondviewUpdateFrustumPlanes();
|
||||
@@ -10380,7 +10401,13 @@ Gfx* hudmsgBottomRender(Gfx* arg0)
|
||||
}
|
||||
|
||||
view_vert = view_top - view_top_offset;
|
||||
#ifdef PORT
|
||||
/* D298/M2: the (s32) casts are an N64 match hack; on the port they
|
||||
* truncate stack pointers. Pass them at full width. */
|
||||
arg0 = draw_blackbox_to_screen(arg0, &view_left, &view_vert, &view_horiz, &view_top);
|
||||
#else
|
||||
arg0 = draw_blackbox_to_screen(arg0, (s32) &view_left, (s32) &view_vert, (s32) &view_horiz, (s32) &view_top);
|
||||
#endif
|
||||
arg0 = combiner_bayer_lod_perspective(textRenderOutlined(arg0, &view_left, &view_vert, stringbuffer_lowerleft[status_bar_text_buffer_index], BONDVIEW_2ND_FONTTABLE(status_bar_text_buffer_index), BONDVIEW_1ST_FONTTABLE(status_bar_text_buffer_index), -1, 0x646464FFU, (s16) (s32) viGetX(), (s16) viGetY(), 0, 0));
|
||||
}
|
||||
}
|
||||
@@ -11393,7 +11420,7 @@ void sub_GAME_7F08BEEC(Mtxf *matrices, s32 count)
|
||||
|
||||
for (i = 0, j = 0; i < count; i++, j += sizeof(Mtxf))
|
||||
{
|
||||
matrix_4x4_multiply_homogeneous(currentPlayerGetViewToWorldMtxf(), (Mtxf *)((u32)matrices + j), &sp40);
|
||||
matrix_4x4_multiply_homogeneous(currentPlayerGetViewToWorldMtxf(), (Mtxf *)((uintptr_t)matrices + j), &sp40); /* D298/M2 */
|
||||
|
||||
sp40.m[3][0] -= g_CurrentPlayer->current_model_pos.f[0];
|
||||
sp40.m[3][1] -= g_CurrentPlayer->current_model_pos.f[1];
|
||||
|
||||
+17
-11
@@ -1,4 +1,9 @@
|
||||
#include <ultra64.h>
|
||||
#if defined(PORT)
|
||||
#include "port_addr.h"
|
||||
#else
|
||||
#define PORT_N64PTR(T, x) ((T *)(x))
|
||||
#endif
|
||||
#ifdef PORT
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -189,7 +194,7 @@ void bondviewLoadSetupIntroSection(void)
|
||||
startpadcount++;
|
||||
}
|
||||
|
||||
intro_record = (struct SetupIntroEmpty*)((s32)intro_record + sizeof(struct SetupIntroSpawn));
|
||||
intro_record = (struct SetupIntroEmpty*)((uintptr_t)intro_record + sizeof(struct SetupIntroSpawn));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -226,7 +231,7 @@ void bondviewLoadSetupIntroSection(void)
|
||||
}
|
||||
}
|
||||
|
||||
intro_record = (struct SetupIntroEmpty*)((s32)intro_record + sizeof(struct SetupIntroItem));
|
||||
intro_record = (struct SetupIntroEmpty*)((uintptr_t)intro_record + sizeof(struct SetupIntroItem));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -237,7 +242,7 @@ void bondviewLoadSetupIntroSection(void)
|
||||
give_cur_player_ammo(((struct SetupIntroAmmo*)intro_record)->ammo_type, ((struct SetupIntroAmmo*)intro_record)->ammo_amount);
|
||||
}
|
||||
|
||||
intro_record = (struct SetupIntroEmpty*)((s32)intro_record + sizeof(struct SetupIntroAmmo));
|
||||
intro_record = (struct SetupIntroEmpty*)((uintptr_t)intro_record + sizeof(struct SetupIntroAmmo));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -256,7 +261,7 @@ void bondviewLoadSetupIntroSection(void)
|
||||
intro_swirl->unk14.fval = intro_swirl->unk14.ival / M_U16_MAX_VALUE_F;
|
||||
intro_swirl->unk18.fval = intro_swirl->unk18.ival / M_U16_MAX_VALUE_F;
|
||||
|
||||
intro_record = (struct SetupIntroEmpty*)((s32)intro_record + sizeof(struct SetupIntroSwirl));
|
||||
intro_record = (struct SetupIntroEmpty*)((uintptr_t)intro_record + sizeof(struct SetupIntroSwirl));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -264,7 +269,7 @@ void bondviewLoadSetupIntroSection(void)
|
||||
{
|
||||
g_IntroAnimationIndex = ((struct SetupIntroAnim*)intro_record)->intro_anim;
|
||||
|
||||
intro_record = (struct SetupIntroEmpty*)((s32)intro_record + sizeof(struct SetupIntroAnim));
|
||||
intro_record = (struct SetupIntroEmpty*)((uintptr_t)intro_record + sizeof(struct SetupIntroAnim));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -272,7 +277,7 @@ void bondviewLoadSetupIntroSection(void)
|
||||
{
|
||||
g_CurrentPlayer->bondtype = ((struct SetupIntroCuff*)intro_record)->bondtype;
|
||||
|
||||
intro_record = (struct SetupIntroEmpty*)((s32)intro_record + sizeof(struct SetupIntroCuff));
|
||||
intro_record = (struct SetupIntroEmpty*)((uintptr_t)intro_record + sizeof(struct SetupIntroCuff));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -311,7 +316,7 @@ void bondviewLoadSetupIntroSection(void)
|
||||
}
|
||||
}
|
||||
|
||||
intro_record = (struct SetupIntroEmpty*)((s32)intro_record + sizeof(struct SetupIntroCamera));
|
||||
intro_record = (struct SetupIntroEmpty*)((uintptr_t)intro_record + sizeof(struct SetupIntroCamera));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -333,7 +338,7 @@ void bondviewLoadSetupIntroSection(void)
|
||||
|
||||
if (watch_time_0);
|
||||
|
||||
intro_record = (struct SetupIntroEmpty*)((s32)intro_record + sizeof(struct SetupIntroWatch));
|
||||
intro_record = (struct SetupIntroEmpty*)((uintptr_t)intro_record + sizeof(struct SetupIntroWatch));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -351,7 +356,7 @@ void bondviewLoadSetupIntroSection(void)
|
||||
credits++;
|
||||
}
|
||||
|
||||
intro_record = (struct SetupIntroEmpty*)((s32)intro_record + sizeof(struct SetupIntroCredits));
|
||||
intro_record = (struct SetupIntroEmpty*)((uintptr_t)intro_record + sizeof(struct SetupIntroCredits));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -360,7 +365,7 @@ void bondviewLoadSetupIntroSection(void)
|
||||
#ifdef DEBUG
|
||||
ossyncprintf("unknown bondstart type %d!\n",intro_record->type);
|
||||
#endif
|
||||
intro_record = (struct SetupIntroEmpty*)((s32)intro_record + sizeof(struct SetupIntroEmpty));
|
||||
intro_record = (struct SetupIntroEmpty*)((uintptr_t)intro_record + sizeof(struct SetupIntroEmpty));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -389,7 +394,8 @@ void bondviewLoadSetupIntroSection(void)
|
||||
{
|
||||
rand_camera_index--;
|
||||
#ifdef PORT
|
||||
ptr_random06cam_entry = (struct SetupIntroCamera *)(uintptr_t)ptr_random06cam_entry->prev;
|
||||
/* D88/D298: prev is a u32 holding the truncated host pointer; re-base. */
|
||||
ptr_random06cam_entry = PORT_N64PTR(struct SetupIntroCamera, ptr_random06cam_entry->prev);
|
||||
#else
|
||||
ptr_random06cam_entry = ptr_random06cam_entry->prev;
|
||||
#endif
|
||||
|
||||
+16
-6
@@ -33,6 +33,16 @@
|
||||
#include "model.h"
|
||||
#include "tex.h"
|
||||
|
||||
/* D298/M2: animation_table_ptrs1/2 slots and vtxstore_allocate() results hold
|
||||
* N64/window addresses as s32; re-base where they become pointers. Identity at
|
||||
* PORT_ADDR_BASE == 0. */
|
||||
#if defined(PORT)
|
||||
#include "port_addr.h"
|
||||
#else
|
||||
/* N64 build: the port address window is the identity (see port_addr.h). */
|
||||
#define PORT_N64PTR(T, x) ((T *)(x))
|
||||
#endif
|
||||
|
||||
#ifdef PORT
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -69,7 +79,7 @@ static s32 d193aAnimIndex(void *anim) {
|
||||
s32 i;
|
||||
if (anim == NULL) return -1;
|
||||
for (i = 0; animation_table_ptrs1[i] != 0; i++) {
|
||||
if ((void *)(uintptr_t)(u32)animation_table_ptrs1[i] == anim) return i;
|
||||
if (PORT_N64PTR(void, animation_table_ptrs1[i]) == anim) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -2491,11 +2501,11 @@ s32 chrTick(PropRecord *prop)
|
||||
{
|
||||
if (D_8002C904)
|
||||
{
|
||||
if (((ModelAnimation *)animation_table_ptrs1[g_AnimationTablePointerCountRelated]) != ((ModelAnimation *)1))
|
||||
if (PORT_N64PTR(ModelAnimation, animation_table_ptrs1[g_AnimationTablePointerCountRelated]) != PORT_N64PTR(ModelAnimation, 1))
|
||||
{
|
||||
if (objecthandlerGetModelAnim(model) != ((ModelAnimation *)animation_table_ptrs1[g_AnimationTablePointerCountRelated]))
|
||||
if (objecthandlerGetModelAnim(model) != PORT_N64PTR(ModelAnimation, animation_table_ptrs1[g_AnimationTablePointerCountRelated]))
|
||||
{
|
||||
modelSetAnimation(model, (ModelAnimation *)animation_table_ptrs1[g_AnimationTablePointerCountRelated], 0, 0.0f, 0.5f, 0.0f);
|
||||
modelSetAnimation(model, PORT_N64PTR(ModelAnimation, animation_table_ptrs1[g_AnimationTablePointerCountRelated]), 0, 0.0f, 0.5f, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3581,7 +3591,7 @@ after_opcode:
|
||||
|
||||
if (((ModelRwData_DisplayList_CollisionRecord *) rwdata)->Vertices == ((ModelRoData_DisplayList_CollisionRecord *) node)->Vertices)
|
||||
{
|
||||
newvertices = (Vertex *) vtxstore_allocate(((ModelRoData_DisplayList_CollisionRecord *) node)->numVertices, 0xcccc, 0, 0);
|
||||
newvertices = PORT_N64PTR(Vertex, vtxstore_allocate(((ModelRoData_DisplayList_CollisionRecord *) node)->numVertices, 0xcccc, 0, 0));
|
||||
|
||||
if (newvertices != NULL)
|
||||
{
|
||||
@@ -3598,7 +3608,7 @@ after_opcode:
|
||||
|
||||
if ((relatedrwdata != NULL) && (relatedrwdata->Vertices == relatedrodata->Vertices))
|
||||
{
|
||||
newvertices = (Vertex *) vtxstore_allocate(relatedrodata->numVertices, 0xcccc, 0, 0);
|
||||
newvertices = PORT_N64PTR(Vertex, vtxstore_allocate(relatedrodata->numVertices, 0xcccc, 0, 0));
|
||||
|
||||
if (newvertices != NULL)
|
||||
{
|
||||
|
||||
+6
-1
@@ -1,4 +1,9 @@
|
||||
#include <ultra64.h>
|
||||
#if defined(PORT)
|
||||
#include "port_addr.h"
|
||||
#else
|
||||
#define PORT_N64PTR(T, x) ((T *)(x))
|
||||
#endif
|
||||
#include <bondtypes.h>
|
||||
#include "cheat.h"
|
||||
#include "chr.h"
|
||||
@@ -100,7 +105,7 @@ struct Model *makeonebody(s32 body, s32 head, struct ModelFileHeader *bodyHeader
|
||||
if ((headHeader != 0) && (c_item_entries[body].hasHead == 0))
|
||||
{
|
||||
bodyHeader->numRecords -= headHeader->numRecords;
|
||||
modelAttachHead(model, opcode, headHeader);
|
||||
modelAttachHead(model, PORT_N64PTR(ModelNode, opcode), headHeader);
|
||||
|
||||
if ((sunglasses == 0) && ((s32) headHeader->numSwitches > 0))
|
||||
{
|
||||
|
||||
+25
-13
@@ -45,6 +45,16 @@
|
||||
#define PUN_ATTACK_ITEM(punchr, field) ((s32)(punchr)->field.attack_item)
|
||||
#endif
|
||||
|
||||
/* D298/M2: `(s32)&ANIM_DATA_x + (s32)&ptr_animation_table->data` is an N64
|
||||
* address, and animation_table_ptrs1[] slots hold N64 addresses; re-base where
|
||||
* such a value becomes a pointer. Identity at PORT_ADDR_BASE == 0. */
|
||||
#if defined(PORT)
|
||||
#include "port_addr.h"
|
||||
#else
|
||||
/* N64 build: the port address window is the identity (see port_addr.h). */
|
||||
#define PORT_N64PTR(T, x) ((T *)(x))
|
||||
#endif
|
||||
|
||||
point2d D_800309F0 = {0, 0};
|
||||
|
||||
// forward declarations
|
||||
@@ -507,7 +517,7 @@ void chrlvKneelingAnimationRelated(ChrRecord *self)
|
||||
|
||||
if ((s32)objecthandlerGetModelAnim(self->model) == (s32)&ANIM_DATA_fire_kneel_forward_one_handed_weapon_slow + (s32)&ptr_animation_table->data)
|
||||
{
|
||||
modelSetAnimation(self->model, (struct ModelAnimation*)((s32)&ANIM_DATA_fire_kneel_forward_one_handed_weapon_slow + (s32)&ptr_animation_table->data), (s32) self->model->gunhand, 109.0f, chrlvGetGuard007SpeedRating(self, 0.5f, 0.8f), 16.0f);
|
||||
modelSetAnimation(self->model, PORT_N64PTR(struct ModelAnimation, (s32)&ANIM_DATA_fire_kneel_forward_one_handed_weapon_slow + (s32)&ptr_animation_table->data), (s32) self->model->gunhand, 109.0f, chrlvGetGuard007SpeedRating(self, 0.5f, 0.8f), 16.0f);
|
||||
modelSetAnimEndFrame(self->model, 140.0f);
|
||||
}
|
||||
else
|
||||
@@ -625,7 +635,7 @@ void chrlvPerformAnimationForActor(ChrRecord *self, s32 animID, s32 startframe,
|
||||
}
|
||||
#endif
|
||||
|
||||
modelSetAnimation(self->model, (void *)animation_table_ptrs1[animID], (bitfield & ANIM_MIRROR) != 0, startframef, phi_f0, (f32)interpol_time60);
|
||||
modelSetAnimation(self->model, PORT_N64PTR(void, animation_table_ptrs1[animID]), (bitfield & ANIM_MIRROR) != 0, startframef, phi_f0, (f32)interpol_time60);
|
||||
|
||||
if (endframe >= 0)
|
||||
{
|
||||
@@ -2822,7 +2832,7 @@ s32 chrlvExplosionDamage(ChrRecord *self, coord3d *arg1, f32 damage, s32 arg3)
|
||||
|
||||
modelSetAnimation(
|
||||
self_model,
|
||||
(struct ModelAnimation *) ((s32)sp38->anonymous_0 + (s32)&ptr_animation_table->data),
|
||||
PORT_N64PTR(struct ModelAnimation, (s32)sp38->anonymous_0 + (s32)&ptr_animation_table->data),
|
||||
sp38->anonymous_1,
|
||||
sp38->anonymous_3,
|
||||
sp38->anonymous_2,
|
||||
@@ -4986,7 +4996,9 @@ bool if_actor_able_set_on_path(ChrRecord *self, s32 pathid)
|
||||
{
|
||||
if (pathid && chrIsNotDeadOrShot(self))
|
||||
{
|
||||
set_actor_on_path(self, pathid);
|
||||
/* D298/M2: callers pass a window PathRecord* truncated through this
|
||||
* s32 param (chrai.c / aicommands.def); re-base on the read. */
|
||||
set_actor_on_path(self, PORT_N64PTR(struct patrol_path, pathid));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -5075,7 +5087,7 @@ void chrlvTickStand(ChrRecord *self)
|
||||
modelSetAnimation(
|
||||
self->model,
|
||||
// awkward fix: addu instruction is backwards
|
||||
(struct ModelAnimation *)((s32)&ANIM_DATA_walking_unarmed + (s32)&ptr_animation_table->data),
|
||||
PORT_N64PTR(struct ModelAnimation, (s32)&ANIM_DATA_walking_unarmed + (s32)&ptr_animation_table->data),
|
||||
i,
|
||||
0.0f,
|
||||
0.5f,
|
||||
@@ -5083,14 +5095,14 @@ void chrlvTickStand(ChrRecord *self)
|
||||
|
||||
modelSetAnimEndFrame(
|
||||
self->model,
|
||||
(((u16*)((s32)&ANIM_DATA_walking_unarmed + (s32)&ptr_animation_table->data))[2] - 1));
|
||||
(PORT_N64PTR(u16, (s32)&ANIM_DATA_walking_unarmed + (s32)&ptr_animation_table->data)[2] - 1));
|
||||
}
|
||||
else if ((right != NULL) || (left != NULL))
|
||||
{
|
||||
modelSetAnimation(
|
||||
self->model,
|
||||
// awkward fix: addu instruction is backwards
|
||||
(struct ModelAnimation *)((s32)&ANIM_DATA_walking + (s32)&ptr_animation_table->data),
|
||||
PORT_N64PTR(struct ModelAnimation, (s32)&ANIM_DATA_walking + (s32)&ptr_animation_table->data),
|
||||
left != NULL,
|
||||
0.0f,
|
||||
0.5f,
|
||||
@@ -5098,7 +5110,7 @@ void chrlvTickStand(ChrRecord *self)
|
||||
|
||||
modelSetAnimEndFrame(
|
||||
self->model,
|
||||
(((u16*)((s32)&ANIM_DATA_walking + (s32)&ptr_animation_table->data))[2] - 1));
|
||||
(PORT_N64PTR(u16, (s32)&ANIM_DATA_walking + (s32)&ptr_animation_table->data)[2] - 1));
|
||||
}
|
||||
}
|
||||
else if (self->act_stand.face_entitytype & 0x10)
|
||||
@@ -5450,13 +5462,13 @@ void chrlvTickDie(ChrRecord *self)
|
||||
{
|
||||
modelSetAnimation(
|
||||
model,
|
||||
(void*)((s32)&ANIM_DATA_jump_backwards + (s32)&ptr_animation_table->data),
|
||||
PORT_N64PTR(void, (s32)&ANIM_DATA_jump_backwards + (s32)&ptr_animation_table->data),
|
||||
objecthandlerGetModelGunhand(model) == 0,
|
||||
50.0f,
|
||||
0.3f,
|
||||
(((u16*)((s32)&ANIM_DATA_jump_backwards + (s32)&ptr_animation_table->data))[2] - 1.0f) - 50.0f);
|
||||
((PORT_N64PTR(u16, (s32)&ANIM_DATA_jump_backwards + (s32)&ptr_animation_table->data))[2] - 1.0f) - 50.0f);
|
||||
|
||||
modelSetAnimSpeed(model, 0.5f, (((u16*)((s32)&ANIM_DATA_jump_backwards + (s32)&ptr_animation_table->data))[2] - 1.0f) - 50.0f);
|
||||
modelSetAnimSpeed(model, 0.5f, ((PORT_N64PTR(u16, (s32)&ANIM_DATA_jump_backwards + (s32)&ptr_animation_table->data))[2] - 1.0f) - 50.0f);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -9160,8 +9172,8 @@ void chrlvTravelTick(ChrRecord *self, coord3d *arg1, StandTile *arg2, struct way
|
||||
|
||||
if ((phi_s3 == NULL) || ((self->hidden & CHRHIDDEN_OFFSCREEN_PATROL) != 0))
|
||||
{
|
||||
if ((objecthandlerGetModelAnim(self->model) == (struct ModelAnimation *)((s32)&ANIM_DATA_idle_unarmed + (s32)&ptr_animation_table->data))
|
||||
|| (objecthandlerGetModelAnim(self->model) == (struct ModelAnimation *)((s32)&ANIM_DATA_idle + (s32)&ptr_animation_table->data)))
|
||||
if ((objecthandlerGetModelAnim(self->model) == PORT_N64PTR(struct ModelAnimation, (s32)&ANIM_DATA_idle_unarmed + (s32)&ptr_animation_table->data))
|
||||
|| (objecthandlerGetModelAnim(self->model) == PORT_N64PTR(struct ModelAnimation, (s32)&ANIM_DATA_idle + (s32)&ptr_animation_table->data)))
|
||||
{
|
||||
if (self->actiontype == ACT_PATROL)
|
||||
{
|
||||
|
||||
+6
-1
@@ -33,6 +33,11 @@
|
||||
#include <random.h>
|
||||
#include <snd.h>
|
||||
#include <ultra64.h>
|
||||
#if defined(PORT)
|
||||
#include "port_addr.h"
|
||||
#else
|
||||
#define PORT_N64PTR(T, x) ((T *)(x))
|
||||
#endif
|
||||
#ifdef PORT
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
@@ -1192,7 +1197,7 @@ void ai(PropDefHeaderRecord *Entityp, PROP_TYPE EntityType)
|
||||
{
|
||||
zero = 0; // debug value maybe?
|
||||
/* D32/D33: table holds s32 offsets; cast at use site. */
|
||||
modelSetAnimation(AircraftEntityp->model, (ModelAnimation *)animation_table_ptrs2[anim_id], zero, startframe, 0.5f, (s32)ai->INTERPOL_TIME60);
|
||||
modelSetAnimation(AircraftEntityp->model, PORT_N64PTR(ModelAnimation, animation_table_ptrs2[anim_id]), zero, startframe, 0.5f, (s32)ai->INTERPOL_TIME60);
|
||||
if (endframe >= 0)
|
||||
{
|
||||
modelSetAnimEndFrame(AircraftEntityp->model, endframe);
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
#include <ultra64.h>
|
||||
#if defined(PORT)
|
||||
#include "port_addr.h"
|
||||
#else
|
||||
#define PORT_N64PTR(T, x) ((T *)(x))
|
||||
#endif
|
||||
#include <PR/os.h>
|
||||
#include <PR/gbi.h>
|
||||
#include <gbi_extension.h>
|
||||
@@ -1734,7 +1739,7 @@ Gfx *explosionRenderFlyingParticles(Gfx *gdl)
|
||||
for (i = 0; i < max_particles; i++)
|
||||
{
|
||||
// HACK: regalloc has instructions backwards.
|
||||
particles = (struct FlyingParticles *)(u32)g_FlyingParticlesBuffer + i;
|
||||
particles = (struct FlyingParticles *)PORT_N64PTR(void, g_FlyingParticlesBuffer) + i;
|
||||
|
||||
if (particles->unk00 > 0)
|
||||
{
|
||||
|
||||
+19
-15
@@ -51,6 +51,10 @@
|
||||
#include "model.h"
|
||||
#ifdef PORT
|
||||
#include "hudaspect.h" /* D335 front-end pillarbox under native widescreen */
|
||||
#include "port_addr.h"
|
||||
#else
|
||||
/* N64 build: the port address window is the identity (see port_addr.h). */
|
||||
#define PORT_N64PTR(T, x) ((T *)(x))
|
||||
#endif
|
||||
|
||||
|
||||
@@ -983,8 +987,8 @@ Gfx *frontPrintText(Gfx *gdl, s32 *x, s32 *y, s8 *text, s32 second_font_table, s
|
||||
x,
|
||||
y,
|
||||
text,
|
||||
second_font_table,
|
||||
first_font_table,
|
||||
PORT_N64PTR(struct fontchar, second_font_table),
|
||||
PORT_N64PTR(struct font, first_font_table),
|
||||
arg6,
|
||||
(textglowR.r << 0x18) | (textglowG.r << 0x10) | (textglowB.r << 8) | textglowA.r,
|
||||
view_x,
|
||||
@@ -999,8 +1003,8 @@ Gfx *frontPrintText(Gfx *gdl, s32 *x, s32 *y, s8 *text, s32 second_font_table, s
|
||||
x,
|
||||
y,
|
||||
text,
|
||||
second_font_table,
|
||||
first_font_table,
|
||||
PORT_N64PTR(struct fontchar, second_font_table),
|
||||
PORT_N64PTR(struct font, first_font_table),
|
||||
arg6,
|
||||
view_x,
|
||||
view_y,
|
||||
@@ -1526,7 +1530,7 @@ Gfx *display_aligned_white_text_to_screen(Gfx *dl, s32 arg1, s32 arg2, s32 halig
|
||||
x = arg1 - ((s32) (halign * sp48) / 2);
|
||||
y = arg2 - ((s32) (valign * sp4C) / 2);
|
||||
|
||||
return textRender(dl, &x, &y, text, arg6, arg7, -1, viGetX(), viGetY(), 0, 0);
|
||||
return textRender(dl, &x, &y, text, PORT_N64PTR(struct fontchar, arg6), PORT_N64PTR(struct font, arg7), -1, viGetX(), viGetY(), 0, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -2179,7 +2183,7 @@ void load_walletbond(void)
|
||||
b = (struct ModelNode *)mnode;
|
||||
srecord = b->Data;
|
||||
|
||||
arg0 = (s32)srecord->BaseAddr + ((s32)srecord->Primary & 0xffffff);
|
||||
arg0 = PORT_N64PTR(Gfx, (s32)srecord->BaseAddr + ((s32)srecord->Primary & 0xffffff));
|
||||
bgApplyDynamicCCRMLUT(arg0, NULL, CCRMLUT_WALLETBOND);
|
||||
}
|
||||
}
|
||||
@@ -7485,7 +7489,7 @@ Gfx *constructor_menu0D_missioncomplete(Gfx *DL)
|
||||
x = 0x37;
|
||||
y = 0xDC;
|
||||
DL = frontPrintText(DL, &x, &y, text, ptrFontZurichBoldChars, ptrFontZurichBold, 0xFF, viGetX(), viGetY(), 0, 0);
|
||||
strcpy(stagename, frontGetPlayersFavoriteWeaponInHand(0, 0));
|
||||
strcpy(stagename, PORT_N64PTR(char, frontGetPlayersFavoriteWeaponInHand(0, 0)));
|
||||
if ((array_favweapon[0][0] > 0) && (array_favweapon[0][1] == array_favweapon[0][0]))
|
||||
{
|
||||
temp = strlen(stagename)-1;
|
||||
@@ -7846,16 +7850,16 @@ Gfx *constructor_menu16_nocontrollers(Gfx *DL)
|
||||
if ((numContCon == 0) || (numContCon == 1) || (numContCon == 2) || (numContCon == 3)) {
|
||||
text = langGet(getStringID(LTITLE, TITLE_STR_118_NOCONT)); //NO CONTROLLER IN CONTROLLER SOCKET 1
|
||||
}
|
||||
textMeasure(&y2, &x2, text, ptrFontZurichBoldChars, ptrFontZurichBold, 0);
|
||||
textMeasure(&y2, &x2, PORT_N64PTR(char, text), ptrFontZurichBoldChars, ptrFontZurichBold, 0);
|
||||
x = 0xDC - (x2 >> 1);
|
||||
y = 0x99 - (y2 >> 1);
|
||||
#ifdef BUGFIX_R1
|
||||
if (j_text_trigger) {
|
||||
DL = textRenderOutlined(DL, &x, &y, text, ptrFontZurichBoldChars, ptrFontZurichBold, -1, 0x8000FF, viGetX(), viGetY(), 0, 0);
|
||||
DL = textRenderOutlined(DL, &x, &y, PORT_N64PTR(char, text), ptrFontZurichBoldChars, ptrFontZurichBold, -1, 0x8000FF, viGetX(), viGetY(), 0, 0);
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
DL = textRender(DL, &x, &y, text, ptrFontZurichBoldChars, ptrFontZurichBold, -1, viGetX(), viGetY(), 0, 0);
|
||||
DL = textRender(DL, &x, &y, PORT_N64PTR(char, text), ptrFontZurichBoldChars, ptrFontZurichBold, -1, viGetX(), viGetY(), 0, 0);
|
||||
#ifdef BUGFIX_R1
|
||||
}
|
||||
#endif
|
||||
@@ -7864,16 +7868,16 @@ Gfx *constructor_menu16_nocontrollers(Gfx *DL)
|
||||
if ((numContCon == 0) || (numContCon == 1) || (numContCon == 2) || (numContCon == 3)) {
|
||||
text = langGet(getStringID(LTITLE, TITLE_STR_119_ATTACHCONT)); //PLEASE POWER OFF AND ATTACH A CONTROLLER
|
||||
}
|
||||
textMeasure(&y2, &x2, text, ptrFontZurichBoldChars, ptrFontZurichBold, 0);
|
||||
textMeasure(&y2, &x2, PORT_N64PTR(char, text), ptrFontZurichBoldChars, ptrFontZurichBold, 0);
|
||||
x = 0xDC - (x2 >> 1);
|
||||
y = 0xB1 - (y2 >> 1);
|
||||
#ifdef BUGFIX_R1
|
||||
if (j_text_trigger) {
|
||||
DL = textRenderOutlined(DL, &x, &y, text, ptrFontZurichBoldChars, ptrFontZurichBold, -1, 0x8000FF, viGetX(), viGetY(), 0, 0);
|
||||
DL = textRenderOutlined(DL, &x, &y, PORT_N64PTR(char, text), ptrFontZurichBoldChars, ptrFontZurichBold, -1, 0x8000FF, viGetX(), viGetY(), 0, 0);
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
DL = textRender(DL, &x, &y, text, ptrFontZurichBoldChars, ptrFontZurichBold, -1, viGetX(), viGetY(), 0, 0);
|
||||
DL = textRender(DL, &x, &y, PORT_N64PTR(char, text), ptrFontZurichBoldChars, ptrFontZurichBold, -1, viGetX(), viGetY(), 0, 0);
|
||||
#ifdef BUGFIX_R1
|
||||
}
|
||||
#endif
|
||||
@@ -8098,7 +8102,7 @@ void init_menu18_displaycast(void)
|
||||
#else
|
||||
modelSetAnimPlaySpeed(cast_model, 0.5f, 0);
|
||||
#endif
|
||||
modelSetAnimation(cast_model, animation_table_ptrs1[intro_animation_table[randomly_selected_intro_animation].animID], flip, intro_animation_table[randomly_selected_intro_animation].startframeoffset, intro_animation_table[randomly_selected_intro_animation].playback_speed, 0.0f);
|
||||
modelSetAnimation(cast_model, PORT_N64PTR(ModelAnimation, animation_table_ptrs1[intro_animation_table[randomly_selected_intro_animation].animID]), flip, intro_animation_table[randomly_selected_intro_animation].startframeoffset, intro_animation_table[randomly_selected_intro_animation].playback_speed, 0.0f);
|
||||
|
||||
g_MenuTimer = 0;
|
||||
cast_camera_dist_start = ((((f32) ((u32) randomGetNext())) * (1.0f / U32_MAX)) * 80.0f) + 70.0f;
|
||||
@@ -8761,7 +8765,7 @@ void menu_init(void)
|
||||
{
|
||||
if (viGetFrameBuf2() == (cfb_16[1]))
|
||||
{
|
||||
viSetFrameBuf2(ptr_menu_videobuffer);
|
||||
viSetFrameBuf2(PORT_N64PTR(u8, ptr_menu_videobuffer));
|
||||
}
|
||||
|
||||
viSetAspect(MENU_INIT_ASPECT_440);
|
||||
|
||||
+12
-7
@@ -1,4 +1,9 @@
|
||||
#include <ultra64.h>
|
||||
#if defined(PORT)
|
||||
#include "port_addr.h"
|
||||
#else
|
||||
#define PORT_N64PTR(T, x) ((T *)(x))
|
||||
#endif
|
||||
#include "include/limits.h"
|
||||
#include <bondconstants.h>
|
||||
#include <bondtypes.h>
|
||||
@@ -6256,14 +6261,14 @@ Gfx *generate_ammo_total_microcode(Gfx *gdl)
|
||||
if (imageoffset_r != 0)
|
||||
{
|
||||
imageoffset_r += globalbank_rdram_offset;
|
||||
gdl = set_rgba_redirect_generate_microcode(gdl, (u8 *)imageoffset_r, (getPlayer_c_screenleft() + getPlayer_c_screenwidth()) - (f32)rightx, -1.0f,
|
||||
gdl = set_rgba_redirect_generate_microcode(gdl, PORT_N64PTR(u8, imageoffset_r), (getPlayer_c_screenleft() + getPlayer_c_screenwidth()) - (f32)rightx, -1.0f,
|
||||
#if defined(VERSION_EU)
|
||||
(viGetViewTop() + viGetViewHeight()) - 30, 0,
|
||||
#else
|
||||
(viGetViewTop() + viGetViewHeight()) - 20, 0,
|
||||
#endif
|
||||
ammo_related[ammotype].IconYOffset, 1);
|
||||
textwidth_r = ((u8 *)imageoffset_r)[4];
|
||||
textwidth_r = (PORT_N64PTR(u8, imageoffset_r))[4];
|
||||
}
|
||||
|
||||
gdl = microcode_constructor(gdl);
|
||||
@@ -6328,14 +6333,14 @@ Gfx *generate_ammo_total_microcode(Gfx *gdl)
|
||||
if (imageoffset_l != 0)
|
||||
{
|
||||
imageoffset_l += globalbank_rdram_offset;
|
||||
gdl = set_rgba_redirect_generate_microcode(gdl, (u8 *)imageoffset_l, getPlayer_c_screenleft() + (f32)leftx, -1.0f,
|
||||
gdl = set_rgba_redirect_generate_microcode(gdl, PORT_N64PTR(u8, imageoffset_l), getPlayer_c_screenleft() + (f32)leftx, -1.0f,
|
||||
#if defined(VERSION_EU)
|
||||
(viGetViewTop() + viGetViewHeight()) - 30, 1,
|
||||
#else
|
||||
(viGetViewTop() + viGetViewHeight()) - 20, 1,
|
||||
#endif
|
||||
ammo_related[ammotype].IconYOffset, 1);
|
||||
textwidth_l = ((u8 *)imageoffset_l)[4];
|
||||
textwidth_l = (PORT_N64PTR(u8, imageoffset_l))[4];
|
||||
}
|
||||
|
||||
gdl = microcode_constructor(gdl);
|
||||
@@ -6426,12 +6431,12 @@ Gfx *gunDrawWatchAmmoDisplay(Gfx *gdl)
|
||||
|
||||
// Draw the ammo icon
|
||||
#if defined(VERSION_EU)
|
||||
gdl = set_rgba_redirect_generate_microcode(gdl, (u8 *)imageoffset, 200.0f, 208.0f, (viGetViewTop() + viGetViewHeight()) - 30, 0, ammo_related[ammotype].IconYOffset, 1);
|
||||
gdl = set_rgba_redirect_generate_microcode(gdl, PORT_N64PTR(u8, imageoffset), 200.0f, 208.0f, (viGetViewTop() + viGetViewHeight()) - 30, 0, ammo_related[ammotype].IconYOffset, 1);
|
||||
#else
|
||||
gdl = set_rgba_redirect_generate_microcode(gdl, (u8 *)imageoffset, 200.0f, 180.0f, (viGetViewTop() + viGetViewHeight()) - 20, 0, ammo_related[ammotype].IconYOffset, 1);
|
||||
gdl = set_rgba_redirect_generate_microcode(gdl, PORT_N64PTR(u8, imageoffset), 200.0f, 180.0f, (viGetViewTop() + viGetViewHeight()) - 20, 0, ammo_related[ammotype].IconYOffset, 1);
|
||||
#endif
|
||||
|
||||
textwidth = ((u8 *)imageoffset)[4];
|
||||
textwidth = (PORT_N64PTR(u8, imageoffset))[4];
|
||||
}
|
||||
|
||||
gdl = microcode_constructor(gdl);
|
||||
|
||||
+2
-2
@@ -414,7 +414,7 @@ s32 texAlignIndices(u8 *src, s32 width, s32 height, s32 format, u8 *dst)
|
||||
src++;
|
||||
}
|
||||
|
||||
outptr = (u8 *)(((u32)outptr + 7) & ~7);
|
||||
outptr = (u8 *)(((uintptr_t)outptr + 7) & ~(uintptr_t)7);
|
||||
}
|
||||
|
||||
return outptr - dst;
|
||||
@@ -2462,7 +2462,7 @@ void texLoadFromDisplayList(Gfx *gdl, struct texpool *arg1)
|
||||
if (bytes[0] == G_SETTIMG && bytes[4] == 0xab && bytes[5] == 0xcd)
|
||||
#endif
|
||||
{
|
||||
texLoad((u32 *)((s32)bytes + 4), arg1);
|
||||
texLoad((u32 *)(bytes + 4), arg1);
|
||||
}
|
||||
|
||||
bytes += 8;
|
||||
|
||||
+27
-4
@@ -4,6 +4,10 @@
|
||||
#include "image_bank.h"
|
||||
#ifdef PORT
|
||||
#include <gimgfixup.h>
|
||||
#include "port_addr.h"
|
||||
#else
|
||||
/* N64 build: the port address window is the identity (see port_addr.h). */
|
||||
#define PORT_N64PTR(T, x) ((T *)(x))
|
||||
#endif
|
||||
|
||||
// bss
|
||||
@@ -16,7 +20,11 @@ s32 img_bitcount;
|
||||
//8008D0AC
|
||||
s32 dword_CODE_bss_8008D0AC;
|
||||
//8008D0B0;
|
||||
#if defined(PORT)
|
||||
uintptr_t globalbank_rdram_offset; /* D298/M2: host-based, see image_bank.h */
|
||||
#else
|
||||
s32 globalbank_rdram_offset;
|
||||
#endif
|
||||
//8008D0B4;
|
||||
s32 *pGlobalimagetable;
|
||||
//8008D0B8;
|
||||
@@ -89,7 +97,14 @@ extern u8* _GlobalimagetableSegmentRomStart;
|
||||
|
||||
|
||||
void texSetBitstring(s32 pos) {
|
||||
#if defined(PORT)
|
||||
/* D298/M2: callers pass a host pointer through this s32 parameter, which
|
||||
* truncates it. Because PORT_ADDR_BASE is 4 GiB-aligned the low 32 bits
|
||||
* are the N64/window offset, so re-base them. Identity at base 0. */
|
||||
img_curpos = (u8 *)portN64ToHost((u32)pos);
|
||||
#else
|
||||
img_curpos = pos;
|
||||
#endif
|
||||
img_curdatatable = 0;
|
||||
img_bitcount = 0;
|
||||
}
|
||||
@@ -167,7 +182,7 @@ extern Gfx* globalDL_0x900;
|
||||
extern Gfx* globalDL_0x9a8;
|
||||
extern Gfx* globalDL_0xa50;
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#if defined(PLATFORM_64BIT)
|
||||
/* D39 (docs/dev/findings.md): on N64 all 49 symbols above link inside the
|
||||
* Globalimagetable segment at physical 0x02xxxxxx (ge007.ld), so
|
||||
* `globalbank_rdram_offset + (u32)&sym` rebases each onto pGlobalimagetable.
|
||||
@@ -244,16 +259,24 @@ void texReset(void)
|
||||
pGlobalimagetable = mempAllocBytesInBank(size + 0x1000, MEMPOOL_STAGE);
|
||||
pGlobalimagetable = ((u32)pGlobalimagetable + 0xFFFU) & 0xFFFFF000;
|
||||
|
||||
romCopy(pGlobalimagetable, &_GlobalimagetableSegmentRomStart, size);
|
||||
romCopy(PORT_N64PTR(void, pGlobalimagetable), &_GlobalimagetableSegmentRomStart, size);
|
||||
|
||||
#ifdef PORT
|
||||
/* D68 (docs/dev/findings.md): the ROM copy is N64 big-endian; convert
|
||||
* the CPU-interpreted u32 fields (IMAGESEG Gfx w1 words and
|
||||
* sImageTableEntry.index) to host order before any code reads them. */
|
||||
gimgFixupGlobalimagetable((u8 *)pGlobalimagetable);
|
||||
gimgFixupGlobalimagetable((u8 *)PORT_N64PTR(void, pGlobalimagetable));
|
||||
#endif
|
||||
|
||||
#if defined(PORT)
|
||||
/* D298/M2: store a HOST-based offset. GIMG_OFF(sym) adds 0x02000000, so
|
||||
* `globalbank_rdram_offset + GIMG_OFF(sym)` is then a live host pointer.
|
||||
* `- 0x02000000` is the 64-bit equivalent of the original 32-bit
|
||||
* `+ 0xFE000000` wraparound (which relied on mod-2^32 cancellation). */
|
||||
globalbank_rdram_offset = (uintptr_t)portN64ToHost((u32)pGlobalimagetable) - 0x02000000UL;
|
||||
#else
|
||||
globalbank_rdram_offset = (u32)pGlobalimagetable + 0xFE000000;
|
||||
#endif
|
||||
genericimage = (void *) (globalbank_rdram_offset + GIMG_OFF(s_genericimage));
|
||||
impactimages = (void *) (globalbank_rdram_offset + GIMG_OFF(s_impactimages));
|
||||
explosion_smokeimages = (void *) (globalbank_rdram_offset + GIMG_OFF(s_explosion_smokeimages));
|
||||
@@ -321,6 +344,6 @@ void texReset(void)
|
||||
/* D68: explosion.c executes the compiled globalDL_0xNNN shadows via
|
||||
* g_ExplosionDisplayLists[]; copy the IMAGESEG words that texLoad()
|
||||
* patched in the ROM copy over into those arrays. */
|
||||
gimgSyncCompiledGlobalDLs((u8 *)pGlobalimagetable);
|
||||
gimgSyncCompiledGlobalDLs((u8 *)PORT_N64PTR(void, pGlobalimagetable));
|
||||
#endif
|
||||
}
|
||||
@@ -25,7 +25,14 @@ extern struct sImageTableEntry *flareimage5;
|
||||
extern u8* img_curpos;
|
||||
extern s32 img_bitcount;
|
||||
extern s32 *pGlobalimagetable;
|
||||
#if defined(PORT)
|
||||
/* D298/M2: holds a host-based RDRAM offset (pGlobalimagetable - 0x02000000)
|
||||
* so `globalbank_rdram_offset + GIMG_OFF(sym)` is a live host pointer in the
|
||||
* DRAM window. s32 on N64 (see image_bank.c). */
|
||||
extern uintptr_t globalbank_rdram_offset;
|
||||
#else
|
||||
extern s32 globalbank_rdram_offset;
|
||||
#endif
|
||||
|
||||
void texReset(void);
|
||||
u32 texReadBits(s32 bitCount);
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
#include <ultra64.h>
|
||||
#if defined(PORT)
|
||||
#include "port_addr.h"
|
||||
#else
|
||||
#define PORT_N64PTR(T, x) ((T *)(x))
|
||||
#endif
|
||||
#include <math.h>
|
||||
#include <bondtypes.h>
|
||||
#include "chr.h"
|
||||
@@ -166,7 +171,7 @@ void sets_a_bunch_of_BONDdata_values_to_default(void)
|
||||
{
|
||||
sub_GAME_7F0062C0(
|
||||
// match hack: addu address calculated backwards
|
||||
(void*)((s32)g_BondMoveAnimationSetup[i].anim_id + (s32)&ptr_animation_table->data),
|
||||
PORT_N64PTR(void, (s32)g_BondMoveAnimationSetup[i].anim_id + (s32)&ptr_animation_table->data),
|
||||
(s32)g_BondMoveAnimationSetup[i].loopframe,
|
||||
(s32)g_BondMoveAnimationSetup[i].endframe,
|
||||
&spD0);
|
||||
@@ -194,7 +199,7 @@ void sets_a_bunch_of_BONDdata_values_to_default(void)
|
||||
modelSetAnimation(
|
||||
&g_CurrentPlayer->model,
|
||||
// match hack: addu address calculated backwards
|
||||
(struct ModelAnimation *) ((s32)g_BondMoveAnimationSetup[g_CurrentPlayer->headanim].anim_id + (s32)&ptr_animation_table->data),
|
||||
(struct ModelAnimation *) PORT_N64PTR(void, (s32)g_BondMoveAnimationSetup[g_CurrentPlayer->headanim].anim_id + (s32)&ptr_animation_table->data),
|
||||
0,
|
||||
g_BondMoveAnimationSetup[g_CurrentPlayer->headanim].loopframe,
|
||||
0.5f,
|
||||
|
||||
@@ -6,6 +6,16 @@
|
||||
#include "math.h"
|
||||
#include "math_floor.h"
|
||||
|
||||
/* D298/M2: these tables store animation addresses as N64 values (s32/union
|
||||
* offset) that are then cast to pointers. Re-base when the pointer is formed;
|
||||
* identity at PORT_ADDR_BASE == 0. */
|
||||
#if defined(PORT)
|
||||
#include "port_addr.h"
|
||||
#define ANI_ADDR(x) ((void *)portN64ToHost((u32)(x)))
|
||||
#else
|
||||
#define ANI_ADDR(x) ((void *)(x))
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of currently allocated heads and bodies
|
||||
@@ -108,7 +118,7 @@ s32 initResolveAnimGroupTable(struct weapon_firing_animation_table *animconfig)
|
||||
|
||||
do
|
||||
{
|
||||
config->anim.anim = (struct ModelAnimation *)(((0, animoffset)) + ((s32)ptr_animation_table));
|
||||
config->anim.anim = (struct ModelAnimation *)ANI_ADDR(((0, animoffset)) + ((s32)ptr_animation_table));
|
||||
endframe = floorFloatToInt(config->unk04);
|
||||
angle16 = sub_GAME_7F0001F0(config->anim.anim, 0, endframe) & 0xffff;
|
||||
duration = config->unk04;
|
||||
@@ -186,7 +196,7 @@ s32 initResolveAnimTable(struct StruckAnim *entries)
|
||||
count++;
|
||||
entry++;
|
||||
ptr_animation_table_addr = (struct StruckAnim *)(&ptr_animation_table);
|
||||
entry[-1].struck_anim = (ModelAnimation *)((*((s32 *)entries)) + (0, address));
|
||||
entry[-1].struck_anim = (ModelAnimation *)ANI_ADDR((*((s32 *)entries)) + (0, address));
|
||||
}
|
||||
while (entry->struck_anim != 0);
|
||||
}
|
||||
@@ -196,7 +206,7 @@ s32 initResolveAnimTable(struct StruckAnim *entries)
|
||||
|
||||
|
||||
#define ANIM_PTR(anim) \
|
||||
((ModelAnimation *)((s32)&anim + ((s32)ptr_animation_table)))
|
||||
((ModelAnimation *)ANI_ADDR((s32)&anim + ((s32)ptr_animation_table)))
|
||||
|
||||
#define ANIM_FRAC(anim) \
|
||||
((((f32)sub_GAME_7F000290(ANIM_PTR(anim), 0, ANIM_PTR(anim)->unk04 - 1)) * 0.10000001f) / \
|
||||
|
||||
@@ -6,6 +6,12 @@
|
||||
|
||||
/* D33: ROM-file endianness fixup for the animation data segment (port layer). */
|
||||
#include "romdata.h"
|
||||
#if defined(PORT)
|
||||
#include "port_addr.h"
|
||||
#else
|
||||
/* N64 build: the port address window is the identity (see port_addr.h). */
|
||||
#define PORT_N64PTR(T, x) ((T *)(x))
|
||||
#endif
|
||||
|
||||
//bss
|
||||
|
||||
@@ -256,15 +262,15 @@ void expand_ani_table_entries(s32** arg0)
|
||||
while (*var_v0 != 0) {
|
||||
if (*var_v0 != 1) {
|
||||
*var_v0 = (s32)((s32)*var_v0 + (s32)(&ptr_animation_table->data));
|
||||
((struct anim_entry *)*var_v0)->unk08 += (s32)&ptr_animation_table->data;
|
||||
((struct anim_entry *)*var_v0)->unk10 += (s32)&ptr_animation_table->data;
|
||||
PORT_N64PTR(struct anim_entry, *var_v0)->unk08 += (s32)&ptr_animation_table->data;
|
||||
PORT_N64PTR(struct anim_entry, *var_v0)->unk10 += (s32)&ptr_animation_table->data;
|
||||
}
|
||||
var_v0++;
|
||||
}
|
||||
|
||||
for (var_v0 = (s32 *)arg0; *var_v0 != 0; var_v0++) {
|
||||
if (*var_v0 != 1) {
|
||||
*(s32 *)*var_v0 += (s32)&_animation_entriesSegmentRomStart;
|
||||
*PORT_N64PTR(s32, *var_v0) += (s32)&_animation_entriesSegmentRomStart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ void initModelHitEntryFreeList(void)
|
||||
entries[i].prev = &entries[i - 1];
|
||||
}
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#if defined(PLATFORM_64BIT)
|
||||
// D40: N64 g_ModelHitEntriesPenultimate labels entry 598 of the pool; on PC the
|
||||
// placeholder symbol is not emitted, so take the address directly.
|
||||
((ModelHitEntry *)g_ModelHitEntries)[MODELHITENTRIES_LEN - 1].prev = &entries[MODELHITENTRIES_LEN - 2];
|
||||
|
||||
+31
-14
@@ -11,6 +11,7 @@
|
||||
#ifdef PORT
|
||||
#include "envflag.h" /* cached getenv for hot-path probes */
|
||||
#endif
|
||||
#include "port_addr.h" /* D298/M2: DRAM window base */
|
||||
extern resource_lookup_data_entry resource_lookup_data_array[]; /* ob.c */
|
||||
|
||||
static void langFixupLoadedBank(char *name, void *p)
|
||||
@@ -21,6 +22,16 @@ static void langFixupLoadedBank(char *name, void *p)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* g_LangBanks[] holds N64 DRAM addresses as s32 (they must fit s32, see
|
||||
* memp.h / D298). Re-base only where a slot becomes a pointer; identity at
|
||||
* PORT_ADDR_BASE == 0, so Windows/Linux are unchanged. */
|
||||
#if defined(PORT)
|
||||
#include "port_addr.h"
|
||||
#else
|
||||
/* N64 build: the port address window is the identity (see port_addr.h). */
|
||||
#define PORT_N64PTR(T, x) ((T *)(x))
|
||||
#endif
|
||||
|
||||
// bss
|
||||
//CODE.bss:8008C640
|
||||
s32 g_LangBanks[45];
|
||||
@@ -267,13 +278,13 @@ void langInit(void) {
|
||||
g_LangBanks[LOPTIONS] = _fileNameLoadToBank(LnameX_lookuptable[LOPTIONS][j_text_trigger], FILELOADMETHOD_DEFAULT, 0x100, MEMPOOL_PERMANENT);
|
||||
g_LangBanks[LMISC] = _fileNameLoadToBank(LnameX_lookuptable[LMISC][j_text_trigger], FILELOADMETHOD_DEFAULT, 0x100, MEMPOOL_PERMANENT);
|
||||
#ifdef PORT
|
||||
langFixupLoadedBank(LnameX_lookuptable[LGUN][j_text_trigger], (void *)g_LangBanks[LGUN]);
|
||||
langFixupLoadedBank(LnameX_lookuptable[LTITLE][j_text_trigger], (void *)g_LangBanks[LTITLE]);
|
||||
langFixupLoadedBank(LnameX_lookuptable[LMPMENU][j_text_trigger], (void *)g_LangBanks[LMPMENU]);
|
||||
langFixupLoadedBank(LnameX_lookuptable[LPROPOBJ][j_text_trigger], (void *)g_LangBanks[LPROPOBJ]);
|
||||
langFixupLoadedBank(LnameX_lookuptable[LMPWEAPONS][j_text_trigger], (void *)g_LangBanks[LMPWEAPONS]);
|
||||
langFixupLoadedBank(LnameX_lookuptable[LOPTIONS][j_text_trigger], (void *)g_LangBanks[LOPTIONS]);
|
||||
langFixupLoadedBank(LnameX_lookuptable[LMISC][j_text_trigger], (void *)g_LangBanks[LMISC]);
|
||||
langFixupLoadedBank(LnameX_lookuptable[LGUN][j_text_trigger], PORT_N64PTR(void, g_LangBanks[LGUN]));
|
||||
langFixupLoadedBank(LnameX_lookuptable[LTITLE][j_text_trigger], PORT_N64PTR(void, g_LangBanks[LTITLE]));
|
||||
langFixupLoadedBank(LnameX_lookuptable[LMPMENU][j_text_trigger], PORT_N64PTR(void, g_LangBanks[LMPMENU]));
|
||||
langFixupLoadedBank(LnameX_lookuptable[LPROPOBJ][j_text_trigger], PORT_N64PTR(void, g_LangBanks[LPROPOBJ]));
|
||||
langFixupLoadedBank(LnameX_lookuptable[LMPWEAPONS][j_text_trigger], PORT_N64PTR(void, g_LangBanks[LMPWEAPONS]));
|
||||
langFixupLoadedBank(LnameX_lookuptable[LOPTIONS][j_text_trigger], PORT_N64PTR(void, g_LangBanks[LOPTIONS]));
|
||||
langFixupLoadedBank(LnameX_lookuptable[LMISC][j_text_trigger], PORT_N64PTR(void, g_LangBanks[LMISC]));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -381,7 +392,7 @@ void langLoadToAddr(u32 id)
|
||||
{
|
||||
g_LangBanks[id] = _fileNameLoadToBank(LnameX_lookuptable[id][j_text_trigger],1,0x100,MEMPOOL_STAGE);
|
||||
#ifdef PORT
|
||||
langFixupLoadedBank(LnameX_lookuptable[id][j_text_trigger], (void *)g_LangBanks[id]);
|
||||
langFixupLoadedBank(LnameX_lookuptable[id][j_text_trigger], PORT_N64PTR(void, g_LangBanks[id]));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -390,7 +401,7 @@ void langLoadToBank(int id,u8 *target,int size)
|
||||
{
|
||||
g_LangBanks[id] = _fileNameLoadToAddr(LnameX_lookuptable[id][j_text_trigger],1,target,size);
|
||||
#ifdef PORT
|
||||
langFixupLoadedBank(LnameX_lookuptable[id][j_text_trigger], (void *)g_LangBanks[id]);
|
||||
langFixupLoadedBank(LnameX_lookuptable[id][j_text_trigger], PORT_N64PTR(void, g_LangBanks[id]));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -417,16 +428,22 @@ u8 * langGet(s32 slotID)
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
u32 * textbank_ptr = g_LangBanks[slotID >> 10]; /* get the text file bank ID index the text ptr table */
|
||||
u32 * textbank_ptr = PORT_N64PTR(u32, g_LangBanks[slotID >> 10]); /* get the text file bank ID index the text ptr table */
|
||||
#ifdef PORT
|
||||
/* D129 cont.: g_LangBanks[] is s32 and only populated for banks the
|
||||
* current flow has loaded. A bare `-level_XX` boot that reaches the
|
||||
* cast/credits text path (Cuba, bondviewRenderCredits, D76) hits a bank
|
||||
* slot that was never filled -> stale/garbage non-NULL value -> fault on
|
||||
* the table read below. Reject anything that is not a plausible mapped
|
||||
* DRAM address. */
|
||||
if ((uintptr_t)textbank_ptr < 0x10000 || (uintptr_t)textbank_ptr >= 0x400000000ULL) {
|
||||
return NULL;
|
||||
* DRAM address. D298/M2: the DRAM window is shifted by PORT_ADDR_BASE on
|
||||
* macOS, so the bounds move with it (identity at PORT_ADDR_BASE == 0). */
|
||||
{
|
||||
uintptr_t t = (uintptr_t)textbank_ptr;
|
||||
uintptr_t lo = (uintptr_t)PORT_ADDR_BASE + 0x10000u;
|
||||
uintptr_t hi = (uintptr_t)PORT_ADDR_BASE + 0x400000000ULL;
|
||||
if (t < lo || t >= hi) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef PORT
|
||||
@@ -437,7 +454,7 @@ u8 * langGet(s32 slotID)
|
||||
d65first = 0;
|
||||
for (int b = 0; b < 45; b++)
|
||||
if (g_LangBanks[b])
|
||||
osSyncPrintf("D65 bank %d = %p\n", b, (void *)g_LangBanks[b]);
|
||||
osSyncPrintf("D65 bank %d = %p\n", b, PORT_N64PTR(void, g_LangBanks[b]));
|
||||
}
|
||||
if (!textbank_ptr)
|
||||
osSyncPrintf("D65 langGet slotID=0x%08x bank=%d ptr=NULL\n", (unsigned)slotID, slotID >> 10);
|
||||
|
||||
+43
-19
@@ -13,6 +13,16 @@
|
||||
#include "initunk_005520.h"
|
||||
#include "math_asinfacosf.h"
|
||||
#include "math_floor.h"
|
||||
|
||||
/* D298/M2: ModelAnimation.bitDescriptors/bitStream are u32 fields holding N64
|
||||
* addresses (D32: the blob base is added by expand_ani_table_entries). Re-base
|
||||
* where they become pointers; identity at PORT_ADDR_BASE == 0. */
|
||||
#if defined(PORT)
|
||||
#include "port_addr.h"
|
||||
#else
|
||||
/* N64 build: the port address window is the identity (see port_addr.h). */
|
||||
#define PORT_N64PTR(T, x) ((T *)(x))
|
||||
#endif
|
||||
#include "math_ceil.h"
|
||||
#include "math_unk_05A9E0.h"
|
||||
#include "objecthandler.h"
|
||||
@@ -78,6 +88,11 @@ Model *modelmgrInstantiateModel(ModelFileHeader *header)
|
||||
/* PC port (D53.2): this buffer is used as a struct Model via the
|
||||
* same type-pun as g_ModelSlots; on PC that struct is 0xE8 bytes,
|
||||
* not the N64 0x20 slot size. */
|
||||
{
|
||||
static int fb = 0;
|
||||
osSyncPrintf("modelmgr: STAGE model fallback #%d (numRecords=%d)\n",
|
||||
++fb, (int)header->numRecords);
|
||||
}
|
||||
model = mempAllocBytesInBank(sizeof(struct Model), MEMPOOL_STAGE);
|
||||
#else
|
||||
model = mempAllocBytesInBank(0x20, MEMPOOL_STAGE);
|
||||
@@ -1028,7 +1043,7 @@ u16 modelAnimReadRootMotionValue(ModelAnimation *anim, s32 fieldIndex, s32 extra
|
||||
u8 bitsThisRead;
|
||||
|
||||
result = 0;
|
||||
desc = (ModelAnimBitField *)anim->bitDescriptors + fieldIndex; // D32: u32 -> ptr
|
||||
desc = PORT_N64PTR(struct ModelAnimBitField, anim->bitDescriptors) + fieldIndex; // D32: u32 -> ptr (D298/M2 re-base)
|
||||
bitsRemaining = desc->bitCount;
|
||||
|
||||
if (bitsRemaining > 0)
|
||||
@@ -1036,7 +1051,7 @@ u16 modelAnimReadRootMotionValue(ModelAnimation *anim, s32 fieldIndex, s32 extra
|
||||
totalBitOffset = extraBitOffset + desc->bitOffset;
|
||||
byteIndex = totalBitOffset >> 3;
|
||||
totalBitOffset &= 7;
|
||||
byteptr = (u8 *)anim->bitStream + byteIndex; // D32: u32 -> ptr
|
||||
byteptr = PORT_N64PTR(u8, anim->bitStream) + byteIndex; // D32: u32 -> ptr (D298/M2 re-base)
|
||||
bitsThisRead = 8 - totalBitOffset;
|
||||
|
||||
if (bitsRemaining >= bitsThisRead)
|
||||
@@ -1713,24 +1728,24 @@ void process_02_position(ModelRenderData *arg0, Model *model, ModelNode *node)
|
||||
|
||||
rot1 = D_80036094;
|
||||
|
||||
sub_GAME_7F06DEC0(jointnum.v, model->gunhand, skeleton, model->anim, model->unk34, &rot1);
|
||||
sub_GAME_7F06DEC0(jointnum.v, model->gunhand, skeleton, model->anim, PORT_N64PTR(u8, model->unk34), &rot1);
|
||||
|
||||
if (model->unk2c != 0.0f)
|
||||
{
|
||||
rot2 = D_800360A0;
|
||||
sub_GAME_7F06DEC0(jointnum.v, model->gunhand, skeleton, model->anim, model->unk38, &rot2);
|
||||
sub_GAME_7F06DEC0(jointnum.v, model->gunhand, skeleton, model->anim, PORT_N64PTR(u8, model->unk38), &rot2);
|
||||
sub_GAME_7F06D160(&rot1, &rot2, model->unk2c);
|
||||
}
|
||||
|
||||
if (model->unk84 != 0.0f)
|
||||
{
|
||||
rot3 = D_800360AC;
|
||||
sub_GAME_7F06DEC0(jointnum.v, model->unk25, skeleton, model->anim2, model->unk64, &rot3);
|
||||
sub_GAME_7F06DEC0(jointnum.v, model->unk25, skeleton, model->anim2, PORT_N64PTR(u8, model->unk64), &rot3);
|
||||
|
||||
if (model->unk5c != 0.0f)
|
||||
{
|
||||
rot4 = D_800360B8;
|
||||
sub_GAME_7F06DEC0(jointnum.v, model->unk25, skeleton, model->anim2, model->unk68, &rot4);
|
||||
sub_GAME_7F06DEC0(jointnum.v, model->unk25, skeleton, model->anim2, PORT_N64PTR(u8, model->unk68), &rot4);
|
||||
sub_GAME_7F06D160(&rot3, &rot4, model->unk5c);
|
||||
}
|
||||
|
||||
@@ -6209,7 +6224,12 @@ s32 loadAnimationFrame(ModelAnimation* anim, s32 frame, ModelSkeleton* unused)
|
||||
s32 ret;
|
||||
s32 source;
|
||||
s32 frameSize;
|
||||
#if defined(PORT)
|
||||
/* D298/M2: keep the buffer address at full pointer width (D59 buffer). */
|
||||
uintptr_t dest;
|
||||
#else
|
||||
u32 dest;
|
||||
#endif
|
||||
u32 size;
|
||||
|
||||
ret = 0;
|
||||
@@ -6223,8 +6243,12 @@ s32 loadAnimationFrame(ModelAnimation* anim, s32 frame, ModelSkeleton* unused)
|
||||
else if (D_80036414 != NULL) // should never be NULL after initAnimationsBuffer is called
|
||||
{
|
||||
// Get dest from this D_80036414 which points to an array. Align to 16 bytes.
|
||||
#if defined(PORT)
|
||||
dest = ((uintptr_t)(D_80036414->animBufferPtr2 + 15) >> 4) * 16;
|
||||
#else
|
||||
dest = ((u32) (D_80036414->animBufferPtr2 + 15) >> 4) * 16;
|
||||
ret = dest;
|
||||
#endif
|
||||
ret = (s32)dest;
|
||||
|
||||
// Get source of this animation in ROM with the offset of the frame we'll load
|
||||
source = anim->address + (frame * frameSize);
|
||||
@@ -6239,14 +6263,14 @@ s32 loadAnimationFrame(ModelAnimation* anim, s32 frame, ModelSkeleton* unused)
|
||||
size = ((u32) (frameSize + 15) >> 4) * 16;
|
||||
|
||||
// This copies one animation frame from ROM to the destination in RAM
|
||||
romCopy((void* ) dest, (void* ) source, size);
|
||||
romCopy((void *)dest, (void *)source, size);
|
||||
|
||||
// Increment this which serves nothing
|
||||
D_80036414->uselessPointer += 1;
|
||||
|
||||
// Set this to point to the end of the copied frame
|
||||
// This allows to copy another frame after this one
|
||||
D_80036414->animBufferPtr2 = dest + size;
|
||||
D_80036414->animBufferPtr2 = (void *)(dest + size);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -6268,7 +6292,7 @@ void modelResetAnimationsScratchBuffer(void)
|
||||
|
||||
#define PROMOTE(var) \
|
||||
if (var) \
|
||||
var = (void *)((u32)var + diff)
|
||||
var = (void *)portN64ToHost((u32)var + diff)
|
||||
|
||||
#ifdef PORT
|
||||
/* PC port (D43/D45): Vertex.LinkedTo is a raw vma (u32), not a pointer —
|
||||
@@ -6320,7 +6344,7 @@ void modelPromoteNodeOffsetsToPointers(ModelNode *node, u32 vma, u32 fileramaddr
|
||||
{
|
||||
ModelRoData_DisplayListRecord* rodata = &node->Data->DisplayList;
|
||||
PROMOTE(rodata->Vertices);
|
||||
rodata->BaseAddr = (void *)fileramaddr;
|
||||
rodata->BaseAddr = PORT_N64PTR(void, fileramaddr);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -6338,7 +6362,7 @@ void modelPromoteNodeOffsetsToPointers(ModelNode *node, u32 vma, u32 fileramaddr
|
||||
PROMOTE(rodata->CollisionVertices[i].LinkedTo);
|
||||
#endif
|
||||
}
|
||||
rodata->BaseAddr = (void *)fileramaddr;
|
||||
rodata->BaseAddr = PORT_N64PTR(void, fileramaddr);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -6362,7 +6386,7 @@ void modelPromoteNodeOffsetsToPointers(ModelNode *node, u32 vma, u32 fileramaddr
|
||||
PROMOTE(rodata->Children[i].unk04);
|
||||
}
|
||||
|
||||
rodata->BaseAddr = (void *)fileramaddr;
|
||||
rodata->BaseAddr = PORT_N64PTR(void, fileramaddr);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -6381,14 +6405,14 @@ void modelPromoteNodeOffsetsToPointers(ModelNode *node, u32 vma, u32 fileramaddr
|
||||
PROMOTE(rodata->Children[i].unk04);
|
||||
}
|
||||
|
||||
rodata->BaseAddr = (void *)fileramaddr;
|
||||
rodata->BaseAddr = PORT_N64PTR(void, fileramaddr);
|
||||
break;
|
||||
}
|
||||
|
||||
case MODELNODE_OPCODE_OP06:
|
||||
{
|
||||
ModelRoData_Op06Record* rodata = &node->Data->Op06;
|
||||
rodata->BaseAddr = (void *)fileramaddr;
|
||||
rodata->BaseAddr = PORT_N64PTR(void, fileramaddr);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -6426,7 +6450,7 @@ void modelPromoteNodeOffsetsToPointers(ModelNode *node, u32 vma, u32 fileramaddr
|
||||
{
|
||||
ModelRoData_Op11Record* rodata = &node->Data->Op11;
|
||||
PROMOTE(rodata->unk0c[15]);
|
||||
rodata->BaseAddr = (void *)fileramaddr;
|
||||
rodata->BaseAddr = PORT_N64PTR(void, fileramaddr);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -6434,7 +6458,7 @@ void modelPromoteNodeOffsetsToPointers(ModelNode *node, u32 vma, u32 fileramaddr
|
||||
{
|
||||
ModelRoData_GunfireRecord* rodata = &node->Data->Gunfire;
|
||||
PROMOTE(rodata->Image);
|
||||
rodata->BaseAddr = (void *)fileramaddr;
|
||||
rodata->BaseAddr = PORT_N64PTR(void, fileramaddr);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -6443,7 +6467,7 @@ void modelPromoteNodeOffsetsToPointers(ModelNode *node, u32 vma, u32 fileramaddr
|
||||
ModelRoData_ShadowRecord* rodata = &node->Data->Shadow;
|
||||
PROMOTE(rodata->image);
|
||||
PROMOTE(rodata->Header);
|
||||
rodata->BaseAddr = (void *)fileramaddr;
|
||||
rodata->BaseAddr = PORT_N64PTR(void, fileramaddr);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -6451,7 +6475,7 @@ void modelPromoteNodeOffsetsToPointers(ModelNode *node, u32 vma, u32 fileramaddr
|
||||
{
|
||||
ModelRoData_DisplayListPrimaryRecord* rodata = &node->Data->DisplayListPrimary;
|
||||
PROMOTE(rodata->Vertices);
|
||||
rodata->BaseAddr = (void *)fileramaddr;
|
||||
rodata->BaseAddr = PORT_N64PTR(void, fileramaddr);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+11
-5
@@ -17,6 +17,12 @@
|
||||
#include "mp_music.h"
|
||||
#include "file.h"
|
||||
#include "assets/obseg/text/LmpmenuE.h"
|
||||
#if defined(PORT)
|
||||
#include "port_addr.h"
|
||||
#else
|
||||
/* N64 build: the port address window is the identity (see port_addr.h). */
|
||||
#define PORT_N64PTR(T, x) ((T *)(x))
|
||||
#endif
|
||||
|
||||
#ifdef REFRESH_PAL
|
||||
#define MPMENU_YOFF 8 /* PAL: every text row sits 8 pixels lower */
|
||||
@@ -1407,7 +1413,7 @@ Gfx *mp_watch_menu_display(Gfx *gdl)
|
||||
|
||||
// Must remain a comma expression for matching
|
||||
h2 = (s32) langGet(getStringID(LMPMENU, MPMENU_STR_1D_KILLS)), /* KILLS */
|
||||
sprintf(rankbuffer, ascii_pnum_KILLS, (char *) q, curplayernum + 1, (char *) h2); /* -> "P<n> KILLS" */
|
||||
sprintf(rankbuffer, ascii_pnum_KILLS, PORT_N64PTR(char, q), curplayernum + 1, PORT_N64PTR(char, h2)); /* -> "P<n> KILLS" */
|
||||
|
||||
textMeasure(&textheight, &textwidth, rankbuffer, ptrFontBankGothicChars, ptrFontBankGothic, 0);
|
||||
x = ((viGetViewLeft() + two_player_x_offset) - (textwidth >> 1)) + 80;
|
||||
@@ -1477,7 +1483,7 @@ Gfx *mp_watch_menu_display(Gfx *gdl)
|
||||
|
||||
// Must remain a comma expression for matching.
|
||||
h2 = (s32) langGet(getStringID(LMPMENU, MPMENU_STR_1E_LOSSES)), /* LOSSES */
|
||||
sprintf(rankbuffer, ascii_pnum_LOSSES, (char *) q, curplayernum + 1, (char *) h2); /* -> "P<n> LOSSES" */
|
||||
sprintf(rankbuffer, ascii_pnum_LOSSES, PORT_N64PTR(char, q), curplayernum + 1, PORT_N64PTR(char, h2)); /* -> "P<n> LOSSES" */
|
||||
|
||||
textMeasure(&textheight, &textwidth, rankbuffer, ptrFontBankGothicChars, ptrFontBankGothic, 0);
|
||||
x = ((viGetViewLeft() + two_player_x_offset) - (textwidth >> 1)) + 80;
|
||||
@@ -1593,7 +1599,7 @@ Gfx *mp_watch_menu_display(Gfx *gdl)
|
||||
y = (viGetViewTop() - (fav_textheight >> 1)) + (37 + MPMENU_YOFF);
|
||||
viewleft = viGetX(); h1 = viGetY();
|
||||
gdl = textRender(gdl, &x, &y, text, ptrFontBankGothicChars, ptrFontBankGothic, 0x00ff00b0, viewleft, h1, 0, 0);
|
||||
text = frontGetPlayersFavoriteWeaponInHand(curplayernum, 0);
|
||||
text = PORT_N64PTR(char, frontGetPlayersFavoriteWeaponInHand(curplayernum, 0));
|
||||
textMeasure(&fav_textheight, &fav_textwidth, text, ptrFontBankGothicChars, ptrFontBankGothic, 0);
|
||||
x = ((viGetViewLeft() + fav_x_offset) - (fav_textwidth >> 1)) + 80;
|
||||
x2 = viGetViewTop();
|
||||
@@ -1615,7 +1621,7 @@ Gfx *mp_watch_menu_display(Gfx *gdl)
|
||||
|
||||
if (g_CurrentPlayer->ptr_text_first_mp_award)
|
||||
{
|
||||
text = (char *) g_CurrentPlayer->ptr_text_first_mp_award;
|
||||
text = PORT_N64PTR(char, g_CurrentPlayer->ptr_text_first_mp_award);
|
||||
textMeasure(&fav_textheight, &fav_textwidth, text, ptrFontBankGothicChars, ptrFontBankGothic, 0);
|
||||
x = ((viGetViewLeft() + fav_x_offset) - (fav_textwidth >> 1)) + 80;
|
||||
y = (viGetViewTop() - (fav_textheight >> 1)) + (75 + MPMENU_YOFF);
|
||||
@@ -1626,7 +1632,7 @@ Gfx *mp_watch_menu_display(Gfx *gdl)
|
||||
|
||||
if (g_CurrentPlayer->ptr_text_second_mp_award)
|
||||
{
|
||||
text = (char *) g_CurrentPlayer->ptr_text_second_mp_award;
|
||||
text = PORT_N64PTR(char, g_CurrentPlayer->ptr_text_second_mp_award);
|
||||
textMeasure(&fav_textheight, &fav_textwidth, text, ptrFontBankGothicChars, ptrFontBankGothic, 0);
|
||||
x = ((viGetViewLeft() + fav_x_offset) - (fav_textwidth >> 1)) + 80;
|
||||
y = (viGetViewTop() - (fav_textheight >> 1)) + (88 + MPMENU_YOFF);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "model.h"
|
||||
|
||||
// bss
|
||||
#if defined(__x86_64__)
|
||||
#if defined(PLATFORM_64BIT)
|
||||
// D40: the N64 placeholder chain below (g_ModelHitEntries .. g_ModelHitEntriesPenultimate)
|
||||
// forms one contiguous 600 x 20-byte ModelHitEntry pool in CODE.bss. On x86-64
|
||||
// ModelHitEntry is 40 bytes (two pointer pairs), so initModelHitEntryFreeList()
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
#include <ultra64.h>
|
||||
#if defined(PORT)
|
||||
#include "port_addr.h"
|
||||
#else
|
||||
#define PORT_N64PTR(T, x) ((T *)(x))
|
||||
#endif
|
||||
#include "chrobjdata.h"
|
||||
#include "image.h"
|
||||
#include "math_asinfacosf.h"
|
||||
@@ -56,7 +61,7 @@ void sub_GAME_7F0762E0(ModelFileHeader *objheader, u8 *name, u8 *dst, struct tex
|
||||
|
||||
delta = ((s32) ((romremaining + filedata) - (s32) name)) - ((s32) (((u8 *) objheader->Switches) + (((u32) gdl) & 0x00ffffff)));
|
||||
|
||||
texCopyGdls((Gfx *) (((u8 *) objheader->Switches) + (((u32) gdl) & 0x00ffffff)), (Gfx *) ((romremaining + filedata) - (s32) name), (s32) name);
|
||||
texCopyGdls((Gfx *) (((u8 *) objheader->Switches) + (((u32) gdl) & 0x00ffffff)), PORT_N64PTR(Gfx, (romremaining + filedata) - (s32) name), (s32) name);
|
||||
|
||||
texLoadFromModelFileHeader(objheader, buffer);
|
||||
|
||||
@@ -86,7 +91,7 @@ void sub_GAME_7F0762E0(ModelFileHeader *objheader, u8 *name, u8 *dst, struct tex
|
||||
|
||||
name = (u8 *) (((s32) (((u8 *) objheader->Switches) + (replacementgdl & 0x00ffffff))) - filedata);
|
||||
|
||||
fileSetSize(filenum, (u8 *) filedata, (((s32) name + 0xf) & (~0xf)), dst == 0);
|
||||
fileSetSize(filenum, PORT_N64PTR(u8, filedata), (((s32) name + 0xf) & (~0xf)), dst == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+54
-48
@@ -17,6 +17,12 @@
|
||||
#include "glass.h"
|
||||
#include "frametiming.h"
|
||||
#include "assets/obseg/text/LoptionE.h"
|
||||
#if defined(PORT)
|
||||
#include "port_addr.h"
|
||||
#else
|
||||
/* N64 build: the port address window is the identity (see port_addr.h). */
|
||||
#define PORT_N64PTR(T, x) ((T *)(x))
|
||||
#endif
|
||||
|
||||
#define WATCH_BACKGROUND_VERTEX_COUNT 30
|
||||
|
||||
@@ -1937,30 +1943,30 @@ Gfx *draw_abort_cancel_confirm(Gfx *gdl)
|
||||
|
||||
if (watch_item_is_actively_selected != 0)
|
||||
{
|
||||
textMeasure(&sp60, &sp64, sp54, pFontChars, pFontFile, 0);
|
||||
textMeasure(&sp60, &sp64, PORT_N64PTR(char, sp54), PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), 0);
|
||||
|
||||
gdl = textRender(gdl, &sp7C, &sp70, sp54, pFontChars, pFontFile, 0xA0FFA0F0, sp64, sp60, 0, 0);
|
||||
gdl = textRender(gdl, &sp7C, &sp70, PORT_N64PTR(char, sp54), PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), 0xA0FFA0F0, sp64, sp60, 0, 0);
|
||||
|
||||
if (D_800409A4 != 0)
|
||||
{
|
||||
gdl = textRenderOutlined(gdl, &sp78, &sp6C, sp50, pFontChars, pFontFile, -1, 0x7000A0, viGetX(), viGetY(), 0, 0);
|
||||
gdl = textRender(gdl, &sp74, &sp68, sp4C, pFontChars, pFontFile, 0xFF00B0, viGetX(), viGetY(), 0, 0);
|
||||
gdl = textRenderOutlined(gdl, &sp78, &sp6C, PORT_N64PTR(char, sp50), PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), -1, 0x7000A0, viGetX(), viGetY(), 0, 0);
|
||||
gdl = textRender(gdl, &sp74, &sp68, PORT_N64PTR(char, sp4C), PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), 0xFF00B0, viGetX(), viGetY(), 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (D_800409A4 == 0)
|
||||
{
|
||||
gdl = textRender(gdl, &sp78, &sp6C, sp50, pFontChars, pFontFile, 0xFF00B0, viGetX(), viGetY(), 0, 0);
|
||||
gdl = textRenderOutlined(gdl, &sp74, &sp68, sp4C, pFontChars, pFontFile, -1, 0x7000A0, viGetX(), viGetY(), 0, 0);
|
||||
gdl = textRender(gdl, &sp78, &sp6C, PORT_N64PTR(char, sp50), PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), 0xFF00B0, viGetX(), viGetY(), 0, 0);
|
||||
gdl = textRenderOutlined(gdl, &sp74, &sp68, PORT_N64PTR(char, sp4C), PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), -1, 0x7000A0, viGetX(), viGetY(), 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
textMeasure(&sp60, &sp64, sp54, pFontChars, pFontFile, 0);
|
||||
gdl = textRender(gdl, &sp7C, &sp70, sp54, pFontChars, pFontFile, 0x800080, sp64, sp60, 0, 0);
|
||||
gdl = textRender(gdl, &sp78, &sp6C, sp50, pFontChars, pFontFile, 0x800080, viGetX(), viGetY(), 0, 0);
|
||||
gdl = textRender(gdl, &sp74, &sp68, sp4C, pFontChars, pFontFile, 0x800080, viGetX(), viGetY(), 0, 0);
|
||||
textMeasure(&sp60, &sp64, PORT_N64PTR(char, sp54), PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), 0);
|
||||
gdl = textRender(gdl, &sp7C, &sp70, PORT_N64PTR(char, sp54), PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), 0x800080, sp64, sp60, 0, 0);
|
||||
gdl = textRender(gdl, &sp78, &sp6C, PORT_N64PTR(char, sp50), PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), 0x800080, viGetX(), viGetY(), 0, 0);
|
||||
gdl = textRender(gdl, &sp74, &sp68, PORT_N64PTR(char, sp4C), PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), 0x800080, viGetX(), viGetY(), 0, 0);
|
||||
}
|
||||
|
||||
return gdl;
|
||||
@@ -1996,10 +2002,10 @@ Gfx *draw_text_mission_status(Gfx *gdl)
|
||||
}
|
||||
|
||||
gdl = microcode_constructor(gdl);
|
||||
textMeasure(&sp5C, &sp58, txtptr_1, pFontChars, pFontFile, 0);
|
||||
textMeasure(&sp5C, &sp58, PORT_N64PTR(char, txtptr_1), PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), 0);
|
||||
sp64 = 0x51;
|
||||
sp60 = YOFFSET_MISSIONSTATUS;
|
||||
gdl = textRender(gdl, &sp64, &sp60, txtptr_1, pFontChars, pFontFile, 0xFF00B0, sp58, sp5C, 0, 0);
|
||||
gdl = textRender(gdl, &sp64, &sp60, PORT_N64PTR(char, txtptr_1), PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), 0xFF00B0, sp58, sp5C, 0, 0);
|
||||
|
||||
if (j_text_trigger)
|
||||
{
|
||||
@@ -2012,8 +2018,8 @@ Gfx *draw_text_mission_status(Gfx *gdl)
|
||||
|
||||
sp64 = sp64 + sp58 + joffset + 4;
|
||||
sp60 = sp60 - sp5C;
|
||||
textMeasure(&sp5C, &sp58, txtptr_2, pFontChars, pFontFile, 0);
|
||||
gdl = textRender(gdl, &sp64, &sp60, txtptr_2, pFontChars, pFontFile, sp4C, sp58, sp5C, 0, 0);
|
||||
textMeasure(&sp5C, &sp58, PORT_N64PTR(char, txtptr_2), PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), 0);
|
||||
gdl = textRender(gdl, &sp64, &sp60, PORT_N64PTR(char, txtptr_2), PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), sp4C, sp58, sp5C, 0, 0);
|
||||
gdl = draw_abort_cancel_confirm(gdl);
|
||||
|
||||
return gdl;
|
||||
@@ -2053,8 +2059,8 @@ Gfx *draw_text_q_watch_v201_beta(Gfx *gdl)
|
||||
pFontFile = ptrFontBankGothic;
|
||||
pFontChars = ptrFontBankGothicChars;
|
||||
gdl = microcode_constructor(gdl);
|
||||
textMeasure(&sp48, &sp44, txtptr, pFontChars, pFontFile, 0);
|
||||
gdl = textRender(gdl, &sp50, &sp4C, txtptr, pFontChars, pFontFile, 0xFF00B0, sp44, sp48, 0, 0);
|
||||
textMeasure(&sp48, &sp44, PORT_N64PTR(char, txtptr), PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), 0);
|
||||
gdl = textRender(gdl, &sp50, &sp4C, PORT_N64PTR(char, txtptr), PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), 0xFF00B0, sp44, sp48, 0, 0);
|
||||
return gdl;
|
||||
}
|
||||
|
||||
@@ -2189,16 +2195,16 @@ Gfx* draw_current_hand_item_and_ammo(Gfx* gdl) {
|
||||
#else
|
||||
sp88 = 0xBC;
|
||||
#endif
|
||||
textMeasure(&sp84, &sp80, text, sp78, sp7C, 0);
|
||||
gdl = textRender(gdl, &sp8C, &sp88, text, sp78, sp7C, 0xFF00B0, sp80, sp84, 0, 0);
|
||||
textMeasure(&sp84, &sp80, text, PORT_N64PTR(struct fontchar, sp78), PORT_N64PTR(struct font, sp7C), 0);
|
||||
gdl = textRender(gdl, &sp8C, &sp88, text, PORT_N64PTR(struct fontchar, sp78), PORT_N64PTR(struct font, sp7C), 0xFF00B0, sp80, sp84, 0, 0);
|
||||
|
||||
#if defined(LEFTOVERDEBUG)
|
||||
sp88 = 0xAA;
|
||||
#else
|
||||
sp88 = 0xC6;
|
||||
#endif
|
||||
textMeasure(&sp84, &sp80, text2, sp78, sp7C, 0);
|
||||
gdl = textRender(gdl, &sp8C, &sp88, text2, sp78, sp7C, 0xFF00B0, sp80, sp84, 0, 0);
|
||||
textMeasure(&sp84, &sp80, text2, PORT_N64PTR(struct fontchar, sp78), PORT_N64PTR(struct font, sp7C), 0);
|
||||
gdl = textRender(gdl, &sp8C, &sp88, text2, PORT_N64PTR(struct fontchar, sp78), PORT_N64PTR(struct font, sp7C), 0xFF00B0, sp80, sp84, 0, 0);
|
||||
|
||||
return gdl;
|
||||
}
|
||||
@@ -2428,11 +2434,11 @@ Gfx *draw_watch_inventory_page(Gfx *gdl, Mtx *param_2)
|
||||
|
||||
gdl = microcode_constructor(gdl);
|
||||
|
||||
textMeasure(&textheight, &textwidth, string_builder_allocation, pFontChars2, pFontFile2, LINEHEIGHT());
|
||||
textMeasure(&textheight, &textwidth, string_builder_allocation, PORT_N64PTR(struct fontchar, pFontChars2), PORT_N64PTR(struct font, pFontFile2), LINEHEIGHT());
|
||||
|
||||
gdl = microcode_constructor_related_to_menus(gdl, 0x4E, WATCH_INV_BASE_Y(), textwidth + 0x4E, (LINEHEIGHT() * 5) + WATCH_INV_BASE_Y(), 0);
|
||||
|
||||
gdl = textRender(gdl, &x1, &y1, string_builder_allocation, pFontChars2, pFontFile2, 0xAA00B0, textwidth + 1, LINEHEIGHT() * 5, watch_inventory_text_y, LINEHEIGHT());
|
||||
gdl = textRender(gdl, &x1, &y1, string_builder_allocation, PORT_N64PTR(struct fontchar, pFontChars2), PORT_N64PTR(struct font, pFontFile2), 0xAA00B0, textwidth + 1, LINEHEIGHT() * 5, watch_inventory_text_y, LINEHEIGHT());
|
||||
|
||||
gdl = microcode_constructor_related_to_menus(gdl, 0x4B, temp_s0_3, textwidth + 0x52, (LINEHEIGHT() + temp_s0_3) - 2, 0x800050);
|
||||
|
||||
@@ -2454,22 +2460,22 @@ Gfx *draw_watch_inventory_page(Gfx *gdl, Mtx *param_2)
|
||||
|
||||
gdl = microcode_constructor(gdl);
|
||||
|
||||
textMeasure(&y2, &x2, formattedString, pFontChars, pFontFile, 0);
|
||||
textMeasure(&y2, &x2, formattedString, PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), 0);
|
||||
|
||||
if (watch_inventory_text_is_settled != 0)
|
||||
{
|
||||
textMeasure(&y2, &x2, invItemName, pFontChars, pFontFile, LINEHEIGHT());
|
||||
textMeasure(&y2, &x2, invItemName, PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), LINEHEIGHT());
|
||||
|
||||
x1 = 0x4E;
|
||||
y1 = (LINEHEIGHT() * 2) + WATCH_INV_BASE_Y();
|
||||
|
||||
if (D_800409C4 == 0)
|
||||
{
|
||||
gdl = textRender(gdl, &x1, &y1, invItemName, pFontChars, pFontFile, 0xA0FFA0F0, x2, 0x64, 0, LINEHEIGHT());
|
||||
gdl = textRender(gdl, &x1, &y1, invItemName, PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), 0xA0FFA0F0, x2, 0x64, 0, LINEHEIGHT());
|
||||
}
|
||||
else
|
||||
{
|
||||
gdl = textRenderOutlined(gdl, &x1, &y1, invItemName, pFontChars, pFontFile, -1, 0x7000A0, x2 + 1, 0x64, 0, LINEHEIGHT());
|
||||
gdl = textRenderOutlined(gdl, &x1, &y1, invItemName, PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), -1, 0x7000A0, x2 + 1, 0x64, 0, LINEHEIGHT());
|
||||
}
|
||||
|
||||
sub_GAME_7F0A8378();
|
||||
@@ -2521,7 +2527,7 @@ Gfx *unused_draw_watch_inventory_page(Gfx *gdl, Mtx *param_2) {
|
||||
game_options_inventory_navigation();
|
||||
gdl = microcode_constructor(gdl);
|
||||
|
||||
textMeasure(&sp58, &sp54, long_name, pFontChars, pFontFile, 0);
|
||||
textMeasure(&sp58, &sp54, long_name, PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), 0);
|
||||
|
||||
sp70 = ((s32) (0xAA - sp54) / 2) + 0x4B;
|
||||
temp_2 = sp70;
|
||||
@@ -2534,16 +2540,16 @@ Gfx *unused_draw_watch_inventory_page(Gfx *gdl, Mtx *param_2) {
|
||||
sub_GAME_7F0A8378();
|
||||
if (D_800409C4 == 0)
|
||||
{
|
||||
gdl = textRender(gdl, &sp70, &sp6C, long_name, pFontChars, pFontFile, 0xA0FFA0F0, sp54, 0x64, 0, 0);
|
||||
gdl = textRender(gdl, &sp70, &sp6C, long_name, PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), 0xA0FFA0F0, sp54, 0x64, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
gdl = textRenderOutlined(gdl, &sp70, &sp6C, long_name, pFontChars, pFontFile, -1, 0x7000A0, sp54 + 1, 0x64, 0, 0);
|
||||
gdl = textRenderOutlined(gdl, &sp70, &sp6C, long_name, PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), -1, 0x7000A0, sp54 + 1, 0x64, 0, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gdl = textRender(gdl, &sp70, &sp6C, long_name, pFontChars, pFontFile, 0xAA00B0, sp54, 0x64, 0, 0);
|
||||
gdl = textRender(gdl, &sp70, &sp6C, long_name, PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), 0xAA00B0, sp54, 0x64, 0, 0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3260,11 +3266,11 @@ Gfx *display_text_buttons_dual_control(Gfx *gdl)
|
||||
|
||||
if (joyGetButtons(PLAYER_1, Z_TRIG))
|
||||
{
|
||||
gdl = draw_options_labels(gdl, 0x5A, YOFFSET_5, textptr_aux, -1, 1, 0x7000A0, 0, 0, 0x3000B0, 0);
|
||||
gdl = draw_options_labels(gdl, 0x5A, YOFFSET_5, PORT_N64PTR(char, textptr_aux), -1, 1, 0x7000A0, 0, 0, 0x3000B0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
gdl = draw_options_labels(gdl, 0x5A, YOFFSET_5, textptr_aux, 0xAA00B0, 0, -1, 0, 0, 0x3000B0, 0);
|
||||
gdl = draw_options_labels(gdl, 0x5A, YOFFSET_5, PORT_N64PTR(char, textptr_aux), 0xAA00B0, 0, -1, 0, 0, 0x3000B0, 0);
|
||||
}
|
||||
|
||||
if ((g_CurrentPlayer->cur_player_control_type_0 == CONTROLLER_CONFIG_PLENTY) || (g_CurrentPlayer->cur_player_control_type_0 == CONTROLLER_CONFIG_DOMINO))
|
||||
@@ -3276,7 +3282,7 @@ Gfx *display_text_buttons_dual_control(Gfx *gdl)
|
||||
textptr_aux = langGet(getStringID(LOPTIONS, OPTION_STR_06_LOOK_LF)); //look
|
||||
}
|
||||
|
||||
gdl = draw_options_labels(gdl, 0x5A, YOFFSET_4, textptr_aux, 0xAA00B0, 0, -1, 0, 0, 0x3000B0, 0);
|
||||
gdl = draw_options_labels(gdl, 0x5A, YOFFSET_4, PORT_N64PTR(char, textptr_aux), 0xAA00B0, 0, -1, 0, 0, 0x3000B0, 0);
|
||||
|
||||
if (joyGetButtons(1, A_BUTTON))
|
||||
{
|
||||
@@ -3307,11 +3313,11 @@ Gfx *display_text_buttons_dual_control(Gfx *gdl)
|
||||
|
||||
if (joyGetButtons(1, Z_TRIG))
|
||||
{
|
||||
gdl = draw_options_labels(gdl, 0xE6, YOFFSET_5, textptr_aux, -1, 1, 0x7000A0, 0, 0, 0x3000B0, 1);
|
||||
gdl = draw_options_labels(gdl, 0xE6, YOFFSET_5, PORT_N64PTR(char, textptr_aux), -1, 1, 0x7000A0, 0, 0, 0x3000B0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
gdl = draw_options_labels(gdl, 0xE6, YOFFSET_5, textptr_aux, 0xAA00B0, 0, -1, 0, 0, 0x3000B0, 1);
|
||||
gdl = draw_options_labels(gdl, 0xE6, YOFFSET_5, PORT_N64PTR(char, textptr_aux), 0xAA00B0, 0, -1, 0, 0, 0x3000B0, 1);
|
||||
}
|
||||
|
||||
if ((g_CurrentPlayer->cur_player_control_type_0 == CONTROLLER_CONFIG_PLENTY) || (g_CurrentPlayer->cur_player_control_type_0 == CONTROLLER_CONFIG_DOMINO))
|
||||
@@ -3323,7 +3329,7 @@ Gfx *display_text_buttons_dual_control(Gfx *gdl)
|
||||
textptr_aux = langGet(getStringID(LOPTIONS, OPTION_STR_05_MOVE_LF)); //move
|
||||
}
|
||||
|
||||
gdl = draw_options_labels(gdl, 0xE6, YOFFSET_4, textptr_aux, 0xAA00B0, 0, -1, 0, 0, 0x3000B0, 1);
|
||||
gdl = draw_options_labels(gdl, 0xE6, YOFFSET_4, PORT_N64PTR(char, textptr_aux), 0xAA00B0, 0, -1, 0, 0, 0x3000B0, 1);
|
||||
return gdl;
|
||||
}
|
||||
|
||||
@@ -3554,14 +3560,14 @@ Gfx *draw_watch_control_options_page(Gfx *gdl, Mtx *param_2) {
|
||||
}
|
||||
}
|
||||
|
||||
textMeasure(&sp50, &sp54, textptr, pFontChars, pFontFile, 0);
|
||||
textMeasure(&sp50, &sp54, textptr, PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), 0);
|
||||
|
||||
if ((watch_item_is_actively_selected != 0) && (controller_options_index == CONTROLLER_OPTIONS_INDEX_STYLE))
|
||||
{
|
||||
gdl = textRenderOutlined(gdl, &sp5C, &sp58, textptr, pFontChars, pFontFile, phi_s1, 0x7000A0, sp54 + 1, sp50, 0, 0);
|
||||
gdl = textRenderOutlined(gdl, &sp5C, &sp58, textptr, PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), phi_s1, 0x7000A0, sp54 + 1, sp50, 0, 0);
|
||||
} else
|
||||
{
|
||||
gdl = textRender(gdl, &sp5C, &sp58, textptr, pFontChars, pFontFile, phi_s1, sp54, sp50, 0, 0);
|
||||
gdl = textRender(gdl, &sp5C, &sp58, textptr, PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), phi_s1, sp54, sp50, 0, 0);
|
||||
}
|
||||
|
||||
gdl = draw_controller_style_text(gdl);
|
||||
@@ -3585,14 +3591,14 @@ Gfx *draw_watch_control_options_page(Gfx *gdl, Mtx *param_2) {
|
||||
}
|
||||
}
|
||||
|
||||
textMeasure(&sp50, &sp54, textptr, pFontChars, pFontFile, 0);
|
||||
textMeasure(&sp50, &sp54, textptr, PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), 0);
|
||||
|
||||
if ((watch_item_is_actively_selected != 0) && (controller_options_index == CONTROLLER_OPTIONS_INDEX_INPUTS))
|
||||
{
|
||||
gdl = textRenderOutlined(gdl, &sp5C, &sp58, textptr, pFontChars, pFontFile, phi_s1, 0x7000A0, sp54 + 1, sp50, 0, 0);
|
||||
gdl = textRenderOutlined(gdl, &sp5C, &sp58, textptr, PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), phi_s1, 0x7000A0, sp54 + 1, sp50, 0, 0);
|
||||
} else
|
||||
{
|
||||
gdl = textRender(gdl, &sp5C, &sp58, textptr, pFontChars, pFontFile, phi_s1, sp54, sp50, 0, 0);
|
||||
gdl = textRender(gdl, &sp5C, &sp58, textptr, PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), phi_s1, sp54, sp50, 0, 0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3859,15 +3865,15 @@ Gfx *draw_watch_game_options_page(Gfx *gdl, Mtx *param_2) {
|
||||
}
|
||||
}
|
||||
|
||||
textMeasure(&sp48, &sp4C, textptr, pFontChars, pFontFile, 0);
|
||||
textMeasure(&sp48, &sp4C, textptr, PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), 0);
|
||||
|
||||
if ((watch_item_is_actively_selected != 0) && (game_options_index == 0))
|
||||
{
|
||||
gdl = textRenderOutlined(gdl, &sp54, &sp50, textptr, pFontChars, pFontFile, sp5C, 0x7000A0, sp4C + 1, sp48, 0, 0);
|
||||
gdl = textRenderOutlined(gdl, &sp54, &sp50, textptr, PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), sp5C, 0x7000A0, sp4C + 1, sp48, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
gdl = textRender(gdl, &sp54, &sp50, textptr, pFontChars, pFontFile, sp5C, sp4C, sp48, 0, 0);
|
||||
gdl = textRender(gdl, &sp54, &sp50, textptr, PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), sp5C, sp4C, sp48, 0, 0);
|
||||
}
|
||||
|
||||
sp5C = 0xFF00B0;
|
||||
@@ -3886,15 +3892,15 @@ Gfx *draw_watch_game_options_page(Gfx *gdl, Mtx *param_2) {
|
||||
}
|
||||
}
|
||||
|
||||
textMeasure(&sp48, &sp4C, textptr, pFontChars, pFontFile, 0);
|
||||
textMeasure(&sp48, &sp4C, textptr, PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), 0);
|
||||
|
||||
if ((watch_item_is_actively_selected != 0) && (game_options_index == 1))
|
||||
{
|
||||
gdl = textRenderOutlined(gdl, &sp54, &sp50, textptr, pFontChars, pFontFile, sp5C, 0x7000A0, sp4C + 1, sp48, 0, 0);
|
||||
gdl = textRenderOutlined(gdl, &sp54, &sp50, textptr, PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), sp5C, 0x7000A0, sp4C + 1, sp48, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
gdl = textRender(gdl, &sp54, &sp50, textptr, pFontChars, pFontFile, sp5C, sp4C, sp48, 0, 0);
|
||||
gdl = textRender(gdl, &sp54, &sp50, textptr, PORT_N64PTR(struct fontchar, pFontChars), PORT_N64PTR(struct font, pFontFile), sp5C, sp4C, sp48, 0, 0);
|
||||
}
|
||||
|
||||
gdl = draw_toggle_options(gdl);
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
#include <ultra64.h>
|
||||
#if defined(PORT)
|
||||
#include "port_addr.h"
|
||||
#else
|
||||
#define PORT_N64PTR(T, x) ((T *)(x))
|
||||
#endif
|
||||
#include <R4300.h>
|
||||
#include "tex.h"
|
||||
#include "image.h"
|
||||
@@ -364,7 +369,7 @@ void texSelect(Gfx **gdlptr, struct sImageTableEntry *tconfig, u32 arg2, s32 arg
|
||||
texLoad((s32 *)tconfig, NULL);
|
||||
}
|
||||
|
||||
aa = PHYS_TO_K0(tconfig->index);
|
||||
aa = PORT_N64PTR(u16, tconfig->index); /* D298/M2: index holds the pool address */
|
||||
tex = texFindInPool((aa)[-4], NULL);
|
||||
|
||||
if (tconfig->level == 0)
|
||||
|
||||
+20
-20
@@ -1324,19 +1324,19 @@ void proplvreset2(enum LEVELID stageId)
|
||||
* The setup file stores every internal reference as a byte offset from the start of the file,
|
||||
* so rebase them all onto the RAM copy at local_stage.
|
||||
*/
|
||||
g_CurrentSetup.pathwaypoints = (void *) (((u32) local_stage) + ((u32) local_stage->pathwaypoints));
|
||||
g_CurrentSetup.waypointgroups = (void *) (((u32) local_stage) + ((u32) local_stage->waypointgroups));
|
||||
g_CurrentSetup.intro = (void *) (((u32) local_stage) + ((u32) local_stage->intro));
|
||||
g_CurrentSetup.propDefs = (void *) (((u32) local_stage) + ((u32) local_stage->propDefs));
|
||||
g_CurrentSetup.patrolpaths = (void *) (((u32) local_stage) + ((u32) local_stage->patrolpaths));
|
||||
g_CurrentSetup.ailists = (void *) (((u32) local_stage) + ((u32) local_stage->ailists));
|
||||
g_CurrentSetup.pads = (void *) (((u32) local_stage) + ((u32) local_stage->pads));
|
||||
g_CurrentSetup.boundpads = (void *) (((u32) local_stage) + ((u32) local_stage->boundpads));
|
||||
g_CurrentSetup.pathwaypoints = (void *) (((uintptr_t) local_stage) + ((u32) local_stage->pathwaypoints));
|
||||
g_CurrentSetup.waypointgroups = (void *) (((uintptr_t) local_stage) + ((u32) local_stage->waypointgroups));
|
||||
g_CurrentSetup.intro = (void *) (((uintptr_t) local_stage) + ((u32) local_stage->intro));
|
||||
g_CurrentSetup.propDefs = (void *) (((uintptr_t) local_stage) + ((u32) local_stage->propDefs));
|
||||
g_CurrentSetup.patrolpaths = (void *) (((uintptr_t) local_stage) + ((u32) local_stage->patrolpaths));
|
||||
g_CurrentSetup.ailists = (void *) (((uintptr_t) local_stage) + ((u32) local_stage->ailists));
|
||||
g_CurrentSetup.pads = (void *) (((uintptr_t) local_stage) + ((u32) local_stage->pads));
|
||||
g_CurrentSetup.boundpads = (void *) (((uintptr_t) local_stage) + ((u32) local_stage->boundpads));
|
||||
|
||||
// Pad names and bound names are optional. An offset of 0 means absent.
|
||||
if (local_stage->padnames != 0)
|
||||
{
|
||||
g_CurrentSetup.padnames = (void *) (((u32) local_stage) + ((u32) local_stage->padnames));
|
||||
g_CurrentSetup.padnames = (void *) (((uintptr_t) local_stage) + ((u32) local_stage->padnames));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1345,7 +1345,7 @@ void proplvreset2(enum LEVELID stageId)
|
||||
|
||||
if (local_stage->boundpadnames != 0)
|
||||
{
|
||||
g_CurrentSetup.boundpadnames = (void *) (((u32) local_stage) + ((u32) local_stage->boundpadnames));
|
||||
g_CurrentSetup.boundpadnames = (void *) (((uintptr_t) local_stage) + ((u32) local_stage->boundpadnames));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1356,7 +1356,7 @@ void proplvreset2(enum LEVELID stageId)
|
||||
{
|
||||
for (i1 = 0; g_CurrentSetup.pathwaypoints[i1].padID >= 0; i1++)
|
||||
{
|
||||
g_CurrentSetup.pathwaypoints[i1].neighbours = (void *) (((u32) g_CurrentSetup.pathwaypoints[i1].neighbours) + ((u32) local_stage));
|
||||
g_CurrentSetup.pathwaypoints[i1].neighbours = (void *) (((u32) g_CurrentSetup.pathwaypoints[i1].neighbours) + ((uintptr_t) local_stage));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1364,8 +1364,8 @@ void proplvreset2(enum LEVELID stageId)
|
||||
{
|
||||
for (i2 = 0; g_CurrentSetup.waypointgroups[i2].neighbours; i2++)
|
||||
{
|
||||
g_CurrentSetup.waypointgroups[i2].neighbours = (void *) (((u32) g_CurrentSetup.waypointgroups[i2].neighbours) + ((u32) local_stage));
|
||||
g_CurrentSetup.waypointgroups[i2].waypoints = (void *) (((u32) g_CurrentSetup.waypointgroups[i2].waypoints) + ((u32) local_stage));
|
||||
g_CurrentSetup.waypointgroups[i2].neighbours = (void *) (((u32) g_CurrentSetup.waypointgroups[i2].neighbours) + ((uintptr_t) local_stage));
|
||||
g_CurrentSetup.waypointgroups[i2].waypoints = (void *) (((u32) g_CurrentSetup.waypointgroups[i2].waypoints) + ((uintptr_t) local_stage));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1376,7 +1376,7 @@ void proplvreset2(enum LEVELID stageId)
|
||||
{
|
||||
for (i3 = 0; g_CurrentSetup.ailists[i3].ailist != 0; i3++)
|
||||
{
|
||||
g_CurrentSetup.ailists[i3].ailist = (void *) (((u32) g_CurrentSetup.ailists[i3].ailist) + ((u32) local_stage));
|
||||
g_CurrentSetup.ailists[i3].ailist = (void *) (((u32) g_CurrentSetup.ailists[i3].ailist) + ((uintptr_t) local_stage));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1385,7 +1385,7 @@ void proplvreset2(enum LEVELID stageId)
|
||||
{
|
||||
for (i3 = 0; g_CurrentSetup.patrolpaths[i3].waypoints != NULL; i3++)
|
||||
{
|
||||
g_CurrentSetup.patrolpaths[i3].waypoints = (void *) (((u32) g_CurrentSetup.patrolpaths[i3].waypoints) + ((u32) local_stage));
|
||||
g_CurrentSetup.patrolpaths[i3].waypoints = (void *) (((u32) g_CurrentSetup.patrolpaths[i3].waypoints) + ((uintptr_t) local_stage));
|
||||
|
||||
for (i5 = 0; g_CurrentSetup.patrolpaths[i3].waypoints[i5] >= 0; i5++)
|
||||
{
|
||||
@@ -1405,7 +1405,7 @@ void proplvreset2(enum LEVELID stageId)
|
||||
|
||||
for (; pad->plink != NULL; pad++)
|
||||
{
|
||||
pad->plink = (void *) (((u32) local_stage) + ((u32) pad->plink));
|
||||
pad->plink = (void *) (((uintptr_t) local_stage) + ((u32) pad->plink));
|
||||
pad->pos.f[0] *= roompos_1;
|
||||
pad->pos.f[1] *= roompos_1;
|
||||
pad->pos.f[2] *= roompos_1;
|
||||
@@ -1460,9 +1460,9 @@ void proplvreset2(enum LEVELID stageId)
|
||||
/** Ugly matching hack.
|
||||
* TODO: investigate if there's a way to get rid of this.
|
||||
*/
|
||||
if ((((u32) local_stage) ^ 0) + ((u32)vol->plink));
|
||||
if ((((uintptr_t) local_stage) ^ 0) + ((u32)vol->plink));
|
||||
|
||||
vol->plink = (void *) (((u32) local_stage) + ((u32)vol->plink));
|
||||
vol->plink = (void *) (((uintptr_t) local_stage) + ((u32)vol->plink));
|
||||
vol->pos.f[0] *= roompos_2;
|
||||
vol->pos.f[1] *= roompos_2;
|
||||
vol->pos.f[2] *= roompos_2;
|
||||
@@ -1497,7 +1497,7 @@ void proplvreset2(enum LEVELID stageId)
|
||||
{
|
||||
for (i1 = 0; g_CurrentSetup.padnames[i1].p; i1++)
|
||||
{
|
||||
g_CurrentSetup.padnames[i1].p = (void *) (((u32) g_CurrentSetup.padnames[i1].p) + ((u32) local_stage));
|
||||
g_CurrentSetup.padnames[i1].p = (void *) (((u32) g_CurrentSetup.padnames[i1].p) + ((uintptr_t) local_stage));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1508,7 +1508,7 @@ void proplvreset2(enum LEVELID stageId)
|
||||
|
||||
for (i1 = 0; g_CurrentSetup.boundpadnames[i1].p; i1++)
|
||||
{
|
||||
g_CurrentSetup.boundpadnames[i1].p = (void *) (((u32) g_CurrentSetup.boundpadnames[i1].p) + ((u32) local_stage));
|
||||
g_CurrentSetup.boundpadnames[i1].p = (void *) (((u32) g_CurrentSetup.boundpadnames[i1].p) + ((uintptr_t) local_stage));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-1
@@ -7,6 +7,11 @@
|
||||
---------------------------------------------------------------------*/
|
||||
|
||||
#include <ultra64.h>
|
||||
#if defined(PORT)
|
||||
#include "port_addr.h"
|
||||
#else
|
||||
#define PORT_N64PTR(T, x) ((T *)(x))
|
||||
#endif
|
||||
#include <math.h>
|
||||
#ifdef PORT
|
||||
#include <stdio.h> /* D202/M-65 diag probe only (doorSndProbe); remove with it */
|
||||
@@ -5725,7 +5730,7 @@ s32 objTick(struct PropRecord *prop)
|
||||
#endif
|
||||
temp_s0_6 = render_pad2F4->model;
|
||||
|
||||
if (temp_s0_6->anim == (ModelAnimation *)animation_table_ptrs2[1]) /* D32/D33 */
|
||||
if (temp_s0_6->anim == PORT_N64PTR(ModelAnimation, animation_table_ptrs2[1])) /* D32/D33 */
|
||||
{
|
||||
modelSetAnimTranslationScale(temp_s0_6, 10.438f);
|
||||
setsubroty(render_pad2F4->model, M_PI_F);
|
||||
|
||||
+1
-1
@@ -273,7 +273,7 @@ void rspGfxTaskStart(Gfx *firstGdl, Gfx *gdl, s32 arg2, OSMesg rspReplyMsg)
|
||||
// Toggles the g_gfxTaskSettingsList to point to altnerate tasks.
|
||||
// Depends on first assignment taking place (g_gfxTaskSettingsList = g_gfxTaskSettings[0]).
|
||||
// Not a typo, but probably not best practice.
|
||||
#if defined(__x86_64__)
|
||||
#if defined(PLATFORM_64BIT)
|
||||
// D32-class: the XOR idiom below truncates exe pointers to u32 on x86-64 and
|
||||
// yields garbage; toggle explicitly (same semantics: list is always &[0] or &[1]).
|
||||
g_gfxTaskSettingsList = (g_gfxTaskSettingsList == &g_gfxTaskSettings[0]) ? &g_gfxTaskSettings[1] : &g_gfxTaskSettings[0];
|
||||
|
||||
+9
-3
@@ -2,6 +2,12 @@
|
||||
//#include <bondtypes.h>
|
||||
#include <deb.h>
|
||||
#include "stan.h"
|
||||
#if defined(PORT)
|
||||
#include "port_addr.h"
|
||||
#else
|
||||
/* N64 build: the port address window is the identity (see port_addr.h). */
|
||||
#define PORT_N64PTR(T, x) ((T *)(x))
|
||||
#endif
|
||||
#include "bg.h"
|
||||
#include "chrai.h"
|
||||
#include "chr.h"
|
||||
@@ -3239,7 +3245,7 @@ void stanDetermineEOF(struct StanPrefixRecord *file /* canonically r */, s32 ori
|
||||
assert(*r==0);
|
||||
#endif
|
||||
|
||||
standTileStart = (StandTile *)(((s32)file->ptr_firstroom + delta) - 0x80);
|
||||
standTileStart = PORT_N64PTR(StandTile, ((s32)file->ptr_firstroom + delta) - 0x80);
|
||||
ptr_firstroom_0 = (s32)file->ptr_firstroom + delta;
|
||||
|
||||
newBase = list_of_tilesizes;
|
||||
@@ -3249,7 +3255,7 @@ void stanDetermineEOF(struct StanPrefixRecord *file /* canonically r */, s32 ori
|
||||
{
|
||||
do
|
||||
{
|
||||
*roomPtr = (void *) ((s32) (*roomPtr) + delta);
|
||||
*roomPtr = PORT_N64PTR(void, (s32)(*roomPtr) + delta);
|
||||
roomPtr++;
|
||||
}
|
||||
while (*roomPtr != NULL);
|
||||
@@ -3266,7 +3272,7 @@ void stanDetermineEOF(struct StanPrefixRecord *file /* canonically r */, s32 ori
|
||||
// Fake but required for matching.
|
||||
if (tile->tail.half);
|
||||
|
||||
tile = (StandTile *)((s32)tile
|
||||
tile = PORT_N64PTR(StandTile, (s32)tile
|
||||
+ (tileSizes = newBase)[(tile->tail.half >> 0xc) & 0xf]);
|
||||
}
|
||||
while (*(s32 *) tile != 0);
|
||||
|
||||
+12
-8
@@ -28,6 +28,10 @@
|
||||
|
||||
#ifdef PORT
|
||||
#include <stdlib.h>
|
||||
#include "port_addr.h"
|
||||
#else
|
||||
/* N64 build: the port address window is the identity (see port_addr.h). */
|
||||
#define PORT_N64PTR(T, x) ((T *)(x))
|
||||
#endif
|
||||
|
||||
|
||||
@@ -221,7 +225,7 @@ Gfx *sub_GAME_7F007F30(Gfx *gdl, s32 count, Mtxf *matrix)
|
||||
|
||||
if (gunbarrelTimer == BOND_EYE_ANIM_START)
|
||||
{
|
||||
modelSetAnimation(chrModelInstance, (struct ModelAnimation *) ((s32) &ANIM_DATA_bond_eye_fire + (s32) &ptr_animation_table->data), 0, 2.0f, 0.910000026f, 16.0f);
|
||||
modelSetAnimation(chrModelInstance, PORT_N64PTR(struct ModelAnimation, (s32) &ANIM_DATA_bond_eye_fire + (s32) &ptr_animation_table->data), 0, 2.0f, 0.910000026f, 16.0f);
|
||||
}
|
||||
|
||||
if (gunbarrelTimer == BOND_EYE_ANIM_SPEEDUP)
|
||||
@@ -397,7 +401,7 @@ void setupRarewareLogoData(s32 address, s32 size) {
|
||||
D_8002A89C = -40.0f;
|
||||
intro_eye_counter = 0;
|
||||
virtualaddress = address;
|
||||
romCopy(virtualaddress, &_rarewarelogoSegmentRomStart, ALIGN64_V2((u32)&_rarewarelogoSegmentEnd - (u32)&_rarewarelogoSegmentStart));
|
||||
romCopy(PORT_N64PTR(void, virtualaddress), &_rarewarelogoSegmentRomStart, ALIGN64_V2((u32)&_rarewarelogoSegmentEnd - (u32)&_rarewarelogoSegmentStart));
|
||||
}
|
||||
|
||||
|
||||
@@ -416,7 +420,7 @@ Gfx *retrieve_display_rareware_logo(Gfx *gdl)
|
||||
#endif
|
||||
|
||||
D_8002A7D0 = (1 - D_8002A7D0);
|
||||
gSPSegment(gdl++, SPSEGMENT_GETITLE, osVirtualToPhysical(virtualaddress));
|
||||
gSPSegment(gdl++, SPSEGMENT_GETITLE, osVirtualToPhysical(PORT_N64PTR(void, virtualaddress)));
|
||||
if ((gunbarrel_mode == 0) || (gunbarrel_mode == 1)) {
|
||||
s32 var1;
|
||||
s32 var2;
|
||||
@@ -461,8 +465,8 @@ void sub_GAME_7F008DE4(u8 **addr, s32 *size) {
|
||||
*size -= 0x40400;
|
||||
*addr += 0x40400;
|
||||
dword_CODE_bss_80069588 = *addr;
|
||||
romCopy(dword_CODE_bss_80069588, (void *)(s32)&unknown2, ALIGN64_V2(((u32)&unknown2_end - (u32)&unknown2)));
|
||||
rle_expand_8bit(dword_CODE_bss_80069588, dword_CODE_bss_8006958C);
|
||||
romCopy(PORT_N64PTR(void, dword_CODE_bss_80069588), PORT_N64PTR(void, &unknown2), ALIGN64_V2(((u32)&unknown2_end - (u32)&unknown2)));
|
||||
rle_expand_8bit(PORT_N64PTR(u8, dword_CODE_bss_80069588), PORT_N64PTR(u8, dword_CODE_bss_8006958C));
|
||||
}
|
||||
|
||||
|
||||
@@ -487,7 +491,7 @@ void initializeGunBarrelIntro(u8 *gfxBuffer, s32 bufferSize)
|
||||
bufferSize -= 0x200;
|
||||
gfxBuffer += 0x200;
|
||||
|
||||
createGunbarrelRenderHole(barrelDisplayListPtr, 0x1E);
|
||||
createGunbarrelRenderHole(PORT_N64PTR(struct s_display_list_something, barrelDisplayListPtr), 0x1E);
|
||||
|
||||
gunbarrelgfxListPointer = (Gfx*)gfxBuffer;
|
||||
#ifdef PORT
|
||||
@@ -517,7 +521,7 @@ void initializeGunBarrelIntro(u8 *gfxBuffer, s32 bufferSize)
|
||||
* N64 K0 value from the physical offset; seg_addr() passes it through to
|
||||
* the KSEG0 mirror at 0x80000000 (segments 7/8 are never registered, so
|
||||
* the unmarked-segment path is skipped). */
|
||||
sub_GAME_7F01BFF8(gunbarrelgfxListPointer, (Vtx *)(OS_K0_TO_PHYSICAL((void *)barrelDisplayListPtr) | 0x80000000u), 0x1E);
|
||||
sub_GAME_7F01BFF8(gunbarrelgfxListPointer, (Vtx *)(OS_K0_TO_PHYSICAL((void *)portN64ToHost((u32)barrelDisplayListPtr)) | 0x80000000u), 0x1E);
|
||||
#else
|
||||
sub_GAME_7F01BFF8(gunbarrelgfxListPointer, barrelDisplayListPtr + 0x80000000, 0x1E);
|
||||
#endif
|
||||
@@ -559,7 +563,7 @@ void initializeGunBarrelIntro(u8 *gfxBuffer, s32 bufferSize)
|
||||
modelSetAnimPlaySpeed(chrModelInstance, S_7F008E80_ANIM_SPEED, 0.0f);
|
||||
#undef S_7F008E80_ANIM_SPEED
|
||||
|
||||
animation = (struct ModelAnimation*)((s32)ptr_animation_table + (s32)&ANIM_DATA_bond_eye_walk);
|
||||
animation = PORT_N64PTR(struct ModelAnimation, (s32)ptr_animation_table + (s32)&ANIM_DATA_bond_eye_walk);
|
||||
startframe = animation->unk04 - 0x44;
|
||||
while (startframe < 0)
|
||||
{
|
||||
|
||||
@@ -49,7 +49,7 @@ void alCSeqNew(ALCSeq *seq, u8 *ptr)
|
||||
{
|
||||
flagTmp = 1 << i;
|
||||
seq->validTracks |= flagTmp;
|
||||
seq->curLoc[i] = (u8*)((u32)ptr + tmpOff);
|
||||
seq->curLoc[i] = (u8*)((uintptr_t)ptr + tmpOff);
|
||||
seq->evtDeltaTicks[i] = __readVarLen(seq,i);
|
||||
/*__alCSeqGetTrackEvent(seq,i); prime the event buffers */
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "synthInternals.h"
|
||||
#include <os.h>
|
||||
#include <R4300.h>
|
||||
#if defined(__x86_64__)
|
||||
#if defined(PLATFORM_64BIT)
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "audiotrace.h" /* D202/M-70: serialized trace writer */
|
||||
@@ -200,7 +200,7 @@ Acmd *alAdpcmPull(void *filter, s16 *outp, s32 outCount, s32 sampleOffset, Acmd
|
||||
f->memin += ADPCMFBYTES*nframes;
|
||||
}
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#if defined(PLATFORM_64BIT)
|
||||
/* D202/M-65 diag (temporary): a wave with no ALADPCMloop must run out and
|
||||
* be zero-filled (nOver > 0) once memin passes base+len. If a voice keeps
|
||||
* decoding past that point, an unstopped voice stays audible forever
|
||||
@@ -393,7 +393,7 @@ alLoadParam(void *filter, s32 paramID, void *param)
|
||||
switch (paramID) {
|
||||
case (AL_FILTER_SET_WAVETABLE):
|
||||
a->table = (ALWaveTable *) param;
|
||||
#if defined(__x86_64__)
|
||||
#if defined(PLATFORM_64BIT)
|
||||
if (GE_ENVFLAG("GE_AUDIOTRACE")) {
|
||||
extern uint64_t sysGetMicroseconds(void); /* port/src/system.c */
|
||||
geTracePrintf("audiotrace_wire.log", "[WIRE] t=%llu filter=%p <- table=%p base=%p len=%d book=%p\n",
|
||||
@@ -496,7 +496,7 @@ Acmd *_decodeChunk(Acmd *ptr, ALLoadFilter *f, s32 tsam, s32 nbytes, s16 outp, s
|
||||
dramLoc;
|
||||
|
||||
if (nbytes > 0){
|
||||
#if defined(__x86_64__)
|
||||
#if defined(PLATFORM_64BIT)
|
||||
if (GE_ENVFLAG("GE_MIXERTRACE")) {
|
||||
static FILE *dtf = NULL;
|
||||
if (!dtf) { dtf = fopen("mixertrace.log", "a"); if (dtf) setvbuf(dtf, NULL, _IONBF, 0); }
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <libaudio.h>
|
||||
#include "synthInternals.h"
|
||||
#include <os.h>
|
||||
#if defined(__x86_64__)
|
||||
#if defined(PLATFORM_64BIT)
|
||||
#endif
|
||||
#include "include/assert.h"
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*====================================================================*/
|
||||
|
||||
#include "synthInternals.h"
|
||||
#if defined(__x86_64__)
|
||||
#if defined(PLATFORM_64BIT)
|
||||
#endif
|
||||
#include <os_internal.h>
|
||||
#include <ultraerror.h>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*====================================================================*/
|
||||
|
||||
#include "synthInternals.h"
|
||||
#if defined(__x86_64__)
|
||||
#if defined(PLATFORM_64BIT)
|
||||
#endif
|
||||
#include <os_internal.h>
|
||||
#include <ultraerror.h>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*====================================================================*/
|
||||
|
||||
#include "synthInternals.h"
|
||||
#if defined(__x86_64__)
|
||||
#if defined(PLATFORM_64BIT)
|
||||
#endif
|
||||
#include <os_internal.h>
|
||||
#include <ultraerror.h>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
#include "synthInternals.h"
|
||||
#include "include/assert.h"
|
||||
#if defined(__x86_64__)
|
||||
#if defined(PLATFORM_64BIT)
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
@@ -122,7 +122,7 @@ void alSynNew(ALSynth *drvr, ALSynConfig *c)
|
||||
|
||||
pv->channelKnob = (ALFilter *)&pv->envmixer;
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#if defined(PLATFORM_64BIT)
|
||||
/* D202/M-69 diag (temporary): GE_AUDIOTRACE=1 logs the full
|
||||
* PVoice -> decoder/resampler/env-state address map at synth init,
|
||||
* so offline voicedump slot addresses can be tied to WIRE filter
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
#include <ultra64.h>
|
||||
#if defined(PORT)
|
||||
#include "port_addr.h" /* D298/M2: memaAlloc returns a DRAM address */
|
||||
#endif
|
||||
#include "mema.h"
|
||||
#include "deb.h"
|
||||
|
||||
@@ -314,7 +317,13 @@ void *memaAlloc(u32 amount) {
|
||||
best->addr = 0;
|
||||
}
|
||||
|
||||
#if defined(PORT)
|
||||
/* D298/M2: best->addr is an N64 DRAM address; hand back a live pointer.
|
||||
* Identity at PORT_ADDR_BASE == 0. */
|
||||
return portN64ToHost((u32)addr);
|
||||
#else
|
||||
return (void*)addr;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Find the memaspace of the given address and reduce its size by the given
|
||||
|
||||
+39
-3
@@ -2,6 +2,9 @@
|
||||
#include <deb.h>
|
||||
#include "memp.h"
|
||||
#include "game/language.h"
|
||||
#if defined(PORT)
|
||||
#include "port_addr.h" /* portN64ToHost: DRAM window base (M2/D298) */
|
||||
#endif
|
||||
|
||||
/**
|
||||
* EU .data, offset from start of data_seg : 0x3640
|
||||
@@ -43,8 +46,18 @@ void mempCheckMemflagTokens(s32 poolAreaStart, s32 poolAreaSize)
|
||||
|
||||
//set pool 0 to what boss wants (room_model_buffer)
|
||||
//pool 0 = TotalPoolArea
|
||||
#if defined(PORT)
|
||||
/* D298/M2: the pool lives in the N64 DRAM window, which on macOS is
|
||||
* shifted up by PORT_ADDR_BASE. boss.c passes N64 addresses (the pool
|
||||
* must stay s32 for mempCheckMemflagTokens' arithmetic), so convert to
|
||||
* host pointers here — the MemoryPool fields are u8*. Identity at
|
||||
* PORT_ADDR_BASE == 0. The N64 build keeps the original line. */
|
||||
g_mempPools[MEMPOOL_TOTAL].start = (u8 *)portN64ToHost((u32)poolAreaStart);
|
||||
g_mempPools[MEMPOOL_TOTAL].end = g_mempPools[MEMPOOL_TOTAL].start + poolAreaSize;
|
||||
#else
|
||||
g_mempPools[MEMPOOL_TOTAL].start = poolAreaStart;
|
||||
g_mempPools[MEMPOOL_TOTAL].end = poolAreaStart + poolAreaSize;
|
||||
#endif
|
||||
|
||||
poolSizes = sdefaultmvals;
|
||||
|
||||
@@ -63,7 +76,7 @@ void mempCheckMemflagTokens(s32 poolAreaStart, s32 poolAreaSize)
|
||||
if (poolSizes.me == 0)
|
||||
{
|
||||
poolSizes.mf = 0;
|
||||
#if defined(__x86_64__)
|
||||
#if defined(PLATFORM_64BIT)
|
||||
/* D36 (PC port): the PERMANENT bank must also hold the enlarged
|
||||
* music heap (MUSIC_ALLOCATION_BYTES in src/music.c, 0x2E000 ->
|
||||
* 0x32000 on x86-64 due to libaudio pointer bloat). Grow the bank on
|
||||
@@ -91,7 +104,6 @@ void mempSetBankStarts(s32 poolSizes[MEMPOOL_COUNT+1])
|
||||
s32 bankstarts[MEMPOOL_COUNT] = {0};
|
||||
s32 mempLen;
|
||||
s32 mempRequested;
|
||||
s32 mempStart;
|
||||
|
||||
//set MF, ML, ME first
|
||||
i = 0;
|
||||
@@ -130,13 +142,27 @@ void mempSetBankStarts(s32 poolSizes[MEMPOOL_COUNT+1])
|
||||
// {0,0,0,0,poolAreaSize - 303104, poolAreaSize - 303104, poolAreaSize}
|
||||
|
||||
|
||||
mempStart = g_mempPools[MEMPOOL_TOTAL].start;
|
||||
#if defined(PORT)
|
||||
{
|
||||
uintptr_t mempStart = (uintptr_t)g_mempPools[MEMPOOL_TOTAL].start;
|
||||
#else
|
||||
{
|
||||
s32 mempStart = g_mempPools[MEMPOOL_TOTAL].start;
|
||||
#endif
|
||||
//for each bank 1-7, add new start position
|
||||
for (i = MEMPOOL_TOTAL; i < MEMPOOL_COUNT - 1; i++)
|
||||
{
|
||||
#if defined(PORT)
|
||||
/* D298/M2: pool fields are u8* host pointers in the DRAM window. */
|
||||
g_mempPools[i + 1].start = (u8 *)(mempStart + bankstarts[i]);
|
||||
g_mempPools[i + 1].pos = 0;
|
||||
g_mempPools[i + 1].end = (u8 *)(mempStart + bankstarts[i + 1]);
|
||||
#else
|
||||
g_mempPools[i + 1].start = bankstarts[i] + mempStart;
|
||||
g_mempPools[i + 1].pos = 0;
|
||||
g_mempPools[i + 1].end = bankstarts[i + 1] + mempStart;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/*
|
||||
rel-start size
|
||||
@@ -201,6 +227,12 @@ void *mempAllocBytesInBank(u32 bytes, u8 poolnum)
|
||||
|
||||
nulled_mempLoopAllMemBanks();
|
||||
|
||||
#if defined(PORT)
|
||||
osSyncPrintf("memp OOM: bank=%d bytes=0x%X left=0x%X pos=%p end=%p\n",
|
||||
(int)poolnum, (unsigned)bytes,
|
||||
(unsigned)(uintptr_t)(pool->end - pool->pos),
|
||||
(void *)pool->pos, (void *)pool->end);
|
||||
#endif
|
||||
while (1);
|
||||
}
|
||||
|
||||
@@ -237,6 +269,10 @@ MEMP_ADD_ENTRY_RESULT mempAddEntryOfSizeToBank(void *allocation, s32 newsize, u8
|
||||
|
||||
if (allocation != pool->prevpos)
|
||||
{
|
||||
#if defined(PORT)
|
||||
osSyncPrintf("mempAddEntry: NOT_LAST bank=%d alloc=%p prevpos=%p\n",
|
||||
(int)poolnum, allocation, (void *)pool->prevpos);
|
||||
#endif
|
||||
return MEMP_ADD_ENTRY_NOT_LAST_ALLOCATION;
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -52,7 +52,7 @@
|
||||
* allocated later from this heap need N64-equivalent headroom on top, so
|
||||
* budget 0x38000 (init headroom ~19 KiB). PC only.
|
||||
*/
|
||||
#if defined(__x86_64__)
|
||||
#if defined(PLATFORM_64BIT)
|
||||
#define MUSIC_ALLOCATION_BYTES 0x38000
|
||||
#else
|
||||
#define MUSIC_ALLOCATION_BYTES 0x2E000
|
||||
@@ -685,7 +685,7 @@ void musicSeqPlayerInit(void)
|
||||
{
|
||||
size = (u32)&_sfxtblSegmentRomStart - (u32)&_sfxctlSegmentRomStart;
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#if defined(PLATFORM_64BIT)
|
||||
// D37: the PC-native bank image is larger than the ROM segment
|
||||
// (4-byte packed offsets become 8-byte pointer slots); allocate the
|
||||
// re-laid-out size, copy only the ROM bytes, then convert.
|
||||
@@ -708,7 +708,7 @@ void musicSeqPlayerInit(void)
|
||||
{
|
||||
size = (u32)&_instrumentstblSegmentRomStart - (u32)&_instrumentsctlSegmentRomStart;
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#if defined(PLATFORM_64BIT)
|
||||
// D37: as above.
|
||||
{
|
||||
u32 romSize = size;
|
||||
@@ -876,7 +876,7 @@ void musicTrack1Play(s32 track)
|
||||
t3 = ALIGN16_a(g_musicTrackLength[g_musicXTrack1CurrentTrackNum]) + ALIGN16_a(NUM_MUSIC_TRACKS);
|
||||
trackSizeBytes = ALIGN16_a(g_musicTrackCompressedLength[g_musicXTrack1CurrentTrackNum]);
|
||||
thing.seqData = g_musicXTrack1SeqData;
|
||||
temp_a0 = (u8*)((t3 + (s32)thing.seqData) - trackSizeBytes);
|
||||
temp_a0 = (u8*)(((uintptr_t)thing.seqData + t3) - trackSizeBytes);
|
||||
|
||||
romCopy(temp_a0, romAddress, trackSizeBytes);
|
||||
decompressdata(temp_a0, thing.seqData, &hlist);
|
||||
@@ -1070,7 +1070,7 @@ void musicTrack2Play(s32 track)
|
||||
t3 = ALIGN16_a(g_musicTrackLength[g_musicXTrack2CurrentTrackNum]) + ALIGN16_a(NUM_MUSIC_TRACKS);
|
||||
trackSizeBytes = ALIGN16_a(g_musicTrackCompressedLength[g_musicXTrack2CurrentTrackNum]);
|
||||
thing.seqData = g_musicXTrack2SeqData;
|
||||
temp_a0 = (u8*)((t3 + (s32)thing.seqData) - trackSizeBytes);
|
||||
temp_a0 = (u8*)(((uintptr_t)thing.seqData + t3) - trackSizeBytes);
|
||||
|
||||
romCopy(temp_a0, romAddress, trackSizeBytes);
|
||||
decompressdata(temp_a0, thing.seqData, &hlist);
|
||||
@@ -1263,7 +1263,7 @@ void musicTrack3Play(s32 track)
|
||||
t3 = ALIGN16_a(g_musicTrackLength[g_musicXTrack3CurrentTrackNum]) + ALIGN16_a(NUM_MUSIC_TRACKS);
|
||||
trackSizeBytes = ALIGN16_a(g_musicTrackCompressedLength[g_musicXTrack3CurrentTrackNum]);
|
||||
thing.seqData = g_musicXTrack3SeqData;
|
||||
temp_a0 = (u8*)((t3 + (s32)thing.seqData) - trackSizeBytes);
|
||||
temp_a0 = (u8*)(((uintptr_t)thing.seqData + t3) - trackSizeBytes);
|
||||
|
||||
romCopy(temp_a0, romAddress, trackSizeBytes);
|
||||
decompressdata(temp_a0, thing.seqData, &hlist);
|
||||
|
||||
Reference in new issue
Block a user