forked from Ports/goldeneye-pc-port
linux-runtime: BUNKER1 boots + renders on Linux
First runtime bring-up on Linux (Ubuntu, gcc-14). -level_09 now renders past frame 1200 crash-free with a clean shutdown, matching Windows. - port/src/romdata.c: no-PIE loads the image at 0x400000, so the D34 'clear low 32 bits of a symbol address' gives 0 -> false 'image base not 4GiB-aligned' abort. The ANIM_DATA_* lvalues are only ever address-taken (never dereferenced), so fall back to a fixed 4GiB-aligned sentinel (0x100000000) for g_pc_animdata_base. - port/src/main.c: the 'image must load at 0x140000000' assertion is PE-specific (.refptr base relocations); ELF no-PIE resolves dram_syms.s absolute symbols literally regardless of load address. Guard it to PLATFORM_WINDOWS. - port/src/libultra.c: mmap game-thread stacks with MAP_32BIT so they sit in the low 2GiB. The decomp truncates stack-buffer pointers to u32 (e.g. in texLoad); glibc pthread stacks live above 4GiB and those truncations corrupt. One fix covers the whole idiom class. Windows pthread stacks are already low. - src/game/image.c: belt-and-braces #ifdef PORT -- align compbuffer at uintptr_t width (identical result on N64). - CMakeLists.txt: drop the -Ttext-segment experiment (needs -mcmodel=large; breaks R_X86_64_32 relocs) -- comment only. Windows: build 240/241, -level_09 crash-free past frame 1440.
This commit is contained in:
1 parent
875b3c7653
commit
fe3d543647
5 files changed
+53
-4
No files matched your search
@@ -283,6 +283,10 @@ elseif(UNIX AND NOT APPLE)
|
||||
# and link no-PIE so the image keeps its preferred load address.
|
||||
add_compile_options(-fno-pie)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -no-pie")
|
||||
# (No -Ttext-segment: pushing the image above 4GiB needs -mcmodel=large and
|
||||
# breaks the R_X86_64_32 relocs. romdataInit handles the low no-PIE base
|
||||
# 0x400000 by using a fixed 4GiB-aligned g_pc_animdata_base sentinel — the
|
||||
# ANIM_DATA_* lvalues are only ever address-taken, never dereferenced.)
|
||||
endif()
|
||||
|
||||
# port/shim first: PC-only shadow headers (bondtypes.h, bondconstants.h,
|
||||
|
||||
@@ -334,6 +334,29 @@ void osCreateThread(OSThread *t, OSId id, void (*entry)(void *), void *arg,
|
||||
t->state = OS_STATE_STOPPED;
|
||||
}
|
||||
|
||||
#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. */
|
||||
static void *portAllocLowStack(size_t sz)
|
||||
{
|
||||
#if defined(MAP_32BIT)
|
||||
void *p = mmap(NULL, sz, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT
|
||||
#if defined(MAP_STACK)
|
||||
| MAP_STACK
|
||||
#endif
|
||||
, -1, 0);
|
||||
if (p != MAP_FAILED)
|
||||
return p;
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
void osStartThread(OSThread *t)
|
||||
{
|
||||
PortThread *pt = portFind(t);
|
||||
@@ -344,7 +367,15 @@ void osStartThread(OSThread *t)
|
||||
pthread_attr_t attr;
|
||||
int rc;
|
||||
pthread_attr_init(&attr);
|
||||
#if !defined(_WIN32)
|
||||
void *lowStack = portAllocLowStack(PORT_THREAD_STACK);
|
||||
if (lowStack)
|
||||
pthread_attr_setstack(&attr, lowStack, PORT_THREAD_STACK);
|
||||
else
|
||||
pthread_attr_setstacksize(&attr, PORT_THREAD_STACK);
|
||||
#else
|
||||
pthread_attr_setstacksize(&attr, PORT_THREAD_STACK);
|
||||
#endif
|
||||
rc = pthread_create(&pt->th, &attr, portThreadWrapper, pt);
|
||||
pthread_attr_destroy(&attr);
|
||||
if (rc != 0) {
|
||||
|
||||
@@ -115,6 +115,7 @@ int main(int argc, char **argv)
|
||||
* loader loads at 0x140000000 and those relocations are no-ops; if we
|
||||
* ever got relocated, every such slot would be silently corrupted.
|
||||
* Fail loudly instead. */
|
||||
#if defined(PLATFORM_WINDOWS)
|
||||
if (sysImageBase() != 0x140000000ul) {
|
||||
sysLogPrintf(LOG_ERROR,
|
||||
"image loaded at %p, expected preferred base 0x140000000; "
|
||||
@@ -122,6 +123,11 @@ int main(int argc, char **argv)
|
||||
(void *)sysImageBase());
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
/* Linux/ELF no-PIE: dram_syms.s absolute symbols resolve to their literal
|
||||
* values independent of the image base (no .refptr indirection), so the
|
||||
* load address is not constrained. sysImageBase() is a stub here anyway. */
|
||||
#endif
|
||||
|
||||
/* 2b. Reserve the N64-DRAM region: s32-safe view @ 0x70000000 (cfb_16,
|
||||
* mempools) + KSEG0 mirror @ 0x80000000 (see port/src/dram.c). */
|
||||
|
||||
+5
-4
@@ -157,10 +157,11 @@ int romdataInit(void)
|
||||
uintptr_t p = (uintptr_t)&probe;
|
||||
uintptr_t hi = p & ~(uintptr_t)0xFFFFFFFFu;
|
||||
if (hi == 0) {
|
||||
sysLogPrintf(LOG_ERROR, "romdataInit: image base 0x%llX is not "
|
||||
"4GiB-aligned; ANIM_DATA_* offsets would be wrong",
|
||||
(unsigned long long)p);
|
||||
return -1;
|
||||
/* Low image base (Linux no-PIE loads at 0x400000). The ANIM_DATA_*
|
||||
* lvalues are only ever address-taken — `(s32)&ANIM_DATA_x` yields
|
||||
* the offset, never a dereference — so g_pc_animdata_base just has
|
||||
* to be some 4GiB-aligned address whose low 32 bits are zero. */
|
||||
hi = (uintptr_t)0x100000000ull;
|
||||
}
|
||||
g_pc_animdata_base = (u8 *)hi;
|
||||
}
|
||||
|
||||
@@ -2435,7 +2435,14 @@ void texLoad(s32 *updateword, struct texpool *pool)
|
||||
|
||||
if (tex == NULL)
|
||||
{
|
||||
#ifdef PORT
|
||||
/* compbuffer is a stack array; (u32) truncates the 64-bit host stack
|
||||
* address (glibc pthread stacks live above 4GiB). Align at full
|
||||
* pointer width -- same result on N64, correct on the port. */
|
||||
alignedcompbuffer = (u8 *) (((uintptr_t)compbuffer + 0xF) & ~(uintptr_t)0xF);
|
||||
#else
|
||||
alignedcompbuffer = (u8 *) (((u32)compbuffer + 0xF) >> 4 << 4);
|
||||
#endif
|
||||
|
||||
if (alignedcompbuffer);
|
||||
if (tex);
|
||||
|
||||
Reference in new issue
Block a user