diff --git a/Makefile b/Makefile index 88b5b7d99c..ab7d47a896 100644 --- a/Makefile +++ b/Makefile @@ -108,11 +108,16 @@ ELF2ROM := tools/elf2rom ZAPD := tools/ZAPD/ZAPD.out FADO := tools/fado/fado.elf -OPTFLAGS := -O2 +ifeq ($(COMPILER),gcc) + OPTFLAGS := -Os -ffast-math -fno-unsafe-math-optimizations +else + OPTFLAGS := -O2 +endif + ASFLAGS := -march=vr4300 -32 -Iinclude ifeq ($(COMPILER),gcc) - CFLAGS += -G 0 -nostdinc $(INC) -DNON_MATCHING=1 -DAVOID_UB=1 -march=vr4300 -mfix4300 -mabi=32 -mdivide-breaks -fno-common -fno-zero-initialized-in-bss -mno-abicalls -fno-toplevel-reorder -ffreestanding $(CHECK_WARNINGS) -g -mno-explicit-relocs -mno-split-addresses -funsigned-char + CFLAGS += -G 0 -nostdinc $(INC) -DAVOID_UB -march=vr4300 -mfix4300 -mabi=32 -mno-abicalls -mdivide-breaks -fno-zero-initialized-in-bss -fno-toplevel-reorder -ffreestanding -fno-common -fno-merge-constants -mno-explicit-relocs -mno-split-addresses $(CHECK_WARNINGS) -funsigned-char MIPS_VERSION := -mips3 else # we support Microsoft extensions such as anonymous structs, which the compiler does support but warns for their usage. Surpress the warnings with -woff. @@ -207,6 +212,7 @@ build/src/overlays/%.o: CC := python3 tools/asm_processor/build.py $(CC) -- $(AS build/assets/%.o: CC := python3 tools/asm_processor/build.py $(CC) -- $(AS) $(ASFLAGS) -- else +build/src/libultra/libc/ll.o: OPTFLAGS := -Ofast build/src/%.o: CC := $(CC) -fexec-charset=euc-jp endif diff --git a/asm/llmuldiv_gcc.s b/asm/llmuldiv_gcc.s deleted file mode 100644 index d0a4de7139..0000000000 --- a/asm/llmuldiv_gcc.s +++ /dev/null @@ -1,103 +0,0 @@ -.include "macro.inc" - -# assembler directives -.set noat # allow manual use of $at -.set noreorder # don't insert nops after branches -.set gp=64 # allow use of 64-bit general purpose registers - -.section .text - -.balign 16 - -/* Copied from Super Mario 64 decomp project */ - -/* -------------------------------------------------------------------------------------- */ -/* need to asm these functions because lib32gcc-7-dev-mips-cross does not exist so we */ -/* cannot naturally link a libgcc variant for this target given this architecture and */ -/* compiler. Until we have a good workaround with a gcc target that doesn't involve */ -/* assuming a 32-bit to 64-bit change, we have to encode these functions as raw assembly */ -/* for it to compile. */ -/* -------------------------------------------------------------------------------------- */ - -/* TODO: Is there a non-insane way to fix this hack that doesn't involve the user compiling */ -/* a library themselves? */ -glabel __umoddi3 - sw $a0, ($sp) - sw $a1, 4($sp) - sw $a2, 8($sp) - sw $a3, 0xc($sp) - ld $t7, 8($sp) - ld $t6, ($sp) - ddivu $zero, $t6, $t7 - bnez $t7, .L80324144 - nop - break 7 -.L80324144: - mfhi $v0 - dsll32 $v1, $v0, 0 - dsra32 $v1, $v1, 0 - jr $ra - dsra32 $v0, $v0, 0 - -glabel __udivdi3 - sw $a0, ($sp) - sw $a1, 4($sp) - sw $a2, 8($sp) - sw $a3, 0xc($sp) - ld $t7, 8($sp) - ld $t6, ($sp) - ddivu $zero, $t6, $t7 - bnez $t7, .L80324180 - nop - break 7 -.L80324180: - mflo $v0 - dsll32 $v1, $v0, 0 - dsra32 $v1, $v1, 0 - jr $ra - dsra32 $v0, $v0, 0 - -glabel __moddi3 - sw $a0, ($sp) - sw $a1, 4($sp) - sw $a2, 8($sp) - sw $a3, 0xc($sp) - ld $t7, 8($sp) - ld $t6, ($sp) - ddivu $zero, $t6, $t7 - bnez $t7, .L803241E8 - nop - break 7 -.L803241E8: - mfhi $v0 - dsll32 $v1, $v0, 0 - dsra32 $v1, $v1, 0 - jr $ra - dsra32 $v0, $v0, 0 - -glabel __divdi3 - sw $a0, ($sp) - sw $a1, 4($sp) - sw $a2, 8($sp) - sw $a3, 0xc($sp) - ld $t7, 8($sp) - ld $t6, ($sp) - ddiv $zero, $t6, $t7 - nop - bnez $t7, .L80324228 - nop - break 7 -.L80324228: - daddiu $at, $zero, -1 - bne $t7, $at, .L80324244 - daddiu $at, $zero, 1 - dsll32 $at, $at, 0x1f - bne $t6, $at, .L80324244 - nop - break 6 -.L80324244: - mflo $v0 - dsll32 $v1, $v0, 0 - dsra32 $v1, $v1, 0 - jr $ra - dsra32 $v0, $v0, 0 diff --git a/include/functions.h b/include/functions.h index 07f4fa9aec..d604da5e78 100644 --- a/include/functions.h +++ b/include/functions.h @@ -8,6 +8,7 @@ f32 fabsf(f32 f); #define fabsf __builtin_fabsf f32 __floatundisf(u32 c); f64 __floatundidf(u32 c); +f32 __powisf2(f32 a, s32 b); unsigned long __udivdi3(unsigned long a, unsigned long b); #else #pragma intrinsic(fabsf) diff --git a/spec b/spec index 4aab92b311..41f40039c2 100644 --- a/spec +++ b/spec @@ -110,7 +110,6 @@ beginseg include "build/asm/__osSetWatchLo.o" include "build/data/rsp_boot.text.o" #ifdef COMPILER_GCC - include "build/asm/llmuldiv_gcc.o" include "build/src/boot/missing_gcc_functions.o" #endif endseg diff --git a/src/boot/boot_main.c b/src/boot/boot_main.c index 7a3350efe8..89e09a184a 100644 --- a/src/boot/boot_main.c +++ b/src/boot/boot_main.c @@ -24,7 +24,6 @@ void bootproc(void) { Locale_Init(); StackCheck_Init(&sIdleThreadInfo, sIdleThreadStack, STACK_TOP(sIdleThreadStack), 0, 256, "idle"); - osCreateThread(&sIdleThread, 1, Idle_ThreadEntry, NULL, STACK_TOP(sIdleThreadStack), - Z_PRIORITY_MAIN); + osCreateThread(&sIdleThread, 1, Idle_ThreadEntry, NULL, STACK_TOP(sIdleThreadStack), Z_PRIORITY_MAIN); osStartThread(&sIdleThread); } diff --git a/src/boot/missing_gcc_functions.c b/src/boot/missing_gcc_functions.c index 628b59e685..393fb16f1c 100644 --- a/src/boot/missing_gcc_functions.c +++ b/src/boot/missing_gcc_functions.c @@ -1,12 +1,19 @@ +/* --------------------------------------------------------------------------------*/ +/* Depending on the toolchain used, an appropriate precompiled libgcc library */ +/* may not exist and cannot be linked against. Until we have a better work around, */ +/* necessary gcc functions are hosted here in order to properly compile. */ +/* --------------------------------------------------------------------------------*/ + +#ifdef __GNUC__ + #include "global.h" -// Define functions needed for the GCC build here. - // Self-hosted memcmp. -int memcmp(void *s1, const void *s2, size_t n) { - u8 *m1 = (u8 *)s1; - u8 *m2 = (u8 *)s2; - int i; +int memcmp(void* s1, const void* s2, size_t n) { + u8* m1 = (u8*)s1; + u8* m2 = (u8*)s2; + u32 i; + for (i = 0; i < n; i++) { if (m1[i] < m2[i]) { return -1; @@ -14,29 +21,36 @@ int memcmp(void *s1, const void *s2, size_t n) { return 1; } } + return 0; } -void *memset(void *str, int c, size_t n) { - u8 *m1 = (u8 *)str; - int i; - for(i = 0; i < n; i++) { +void* memset(void* str, s32 c, size_t n) { + u8* m1 = (u8*)str; + u32 i; + + for (i = 0; i < n; i++) { m1[i] = c; } + return str; } // These functions convert c to an unsigned integer, rounding toward zero. Negative values // all become zero. u32 __fixunssfdi(f32 a) { - if (a < 0.0f) + if (a < 0.0f) { a = 0.0f; + } + return (u32)a; } u32 __fixunsdfdi(f64 a) { - if (a < 0.0) + if (a < 0.0) { a = 0.0; + } + return (u32)a; } @@ -60,9 +74,141 @@ f64 __floatdidf(s32 c) { // These functions convert c, an unsigned integer, to floating point. f32 __floatundisf(u32 c) { - return (f32)c; + return (f32)c; } f64 __floatundidf(u32 c) { return (f64)c; } + +f32 __powisf2(f32 a, s32 b) { + const s32 recip = b < 0; + f32 r = 1; + + while (1) { + if (b & 1) { + r *= a; + } + + b /= 2; + + if (b == 0) { + break; + } + + a *= a; + } + return recip ? 1 / r : r; +} + +__asm__(" \n\ + .set push \n\ + .set noat \n\ + .set noreorder \n\ + .set gp=64 \n\ + \n\ +.global __umoddi3 \n\ +__umoddi3: \n\ + .type __umoddi3, @function \n\ + .ent __umoddi3 \n\ + sw $a0, ($sp) \n\ + sw $a1, 4($sp) \n\ + sw $a2, 8($sp) \n\ + sw $a3, 0xc($sp) \n\ + ld $t7, 8($sp) \n\ + ld $t6, ($sp) \n\ + ddivu $zero, $t6, $t7 \n\ + bnez $t7, 1f \n\ + nop \n\ + break 7 \n\ +1: \n\ + mfhi $v0 \n\ + dsll32 $v1, $v0, 0 \n\ + dsra32 $v1, $v1, 0 \n\ + jr $ra \n\ + dsra32 $v0, $v0, 0 \n\ + .end __umoddi3 \n\ + .size __umoddi3, . - __umoddi3 \n\ + \n\ +.global __udivdi3 \n\ +__udivdi3: \n\ + .type __udivdi3, @function \n\ + .ent __udivdi3 \n\ + sw $a0, ($sp) \n\ + sw $a1, 4($sp) \n\ + sw $a2, 8($sp) \n\ + sw $a3, 0xc($sp) \n\ + ld $t7, 8($sp) \n\ + ld $t6, ($sp) \n\ + ddivu $zero, $t6, $t7 \n\ + bnez $t7, 1f \n\ + nop \n\ + break 7 \n\ +1: \n\ + mflo $v0 \n\ + dsll32 $v1, $v0, 0 \n\ + dsra32 $v1, $v1, 0 \n\ + jr $ra \n\ + dsra32 $v0, $v0, 0 \n\ + .end __udivdi3 \n\ + .size __udivdi3, . - __udivdi3 \n\ + \n\ +.global __moddi3 \n\ +__moddi3: \n\ + .type __moddi3, @function \n\ + .ent __moddi3 \n\ + sw $a0, ($sp) \n\ + sw $a1, 4($sp) \n\ + sw $a2, 8($sp) \n\ + sw $a3, 0xc($sp) \n\ + ld $t7, 8($sp) \n\ + ld $t6, ($sp) \n\ + ddivu $zero, $t6, $t7 \n\ + bnez $t7, 1f \n\ + nop \n\ + break 7 \n\ +1: \n\ + mfhi $v0 \n\ + dsll32 $v1, $v0, 0 \n\ + dsra32 $v1, $v1, 0 \n\ + jr $ra \n\ + dsra32 $v0, $v0, 0 \n\ + .end __moddi3 \n\ + .size __moddi3, . - __moddi3 \n\ + \n\ +.global __divdi3 \n\ +__divdi3: \n\ + .type __divdi3, @function \n\ + .ent __divdi3 \n\ + sw $a0, ($sp) \n\ + sw $a1, 4($sp) \n\ + sw $a2, 8($sp) \n\ + sw $a3, 0xc($sp) \n\ + ld $t7, 8($sp) \n\ + ld $t6, ($sp) \n\ + ddiv $zero, $t6, $t7 \n\ + nop \n\ + bnez $t7, 1f \n\ + nop \n\ + break 7 \n\ +1: \n\ + daddiu $at, $zero, -1 \n\ + bne $t7, $at, 2f \n\ + daddiu $at, $zero, 1 \n\ + dsll32 $at, $at, 0x1f \n\ + bne $t6, $at, 2f \n\ + nop \n\ + break 6 \n\ +2: \n\ + mflo $v0 \n\ + dsll32 $v1, $v0, 0 \n\ + dsra32 $v1, $v1, 0 \n\ + jr $ra \n\ + dsra32 $v0, $v0, 0 \n\ + .end __divdi3 \n\ + .size __divdi3, . - __divdi3 \n\ + \n\ + .set pop \n\ + \n"); + +#endif diff --git a/src/boot/z_std_dma.c b/src/boot/z_std_dma.c index 6a9d546ce8..7b9300e7d7 100644 --- a/src/boot/z_std_dma.c +++ b/src/boot/z_std_dma.c @@ -210,6 +210,9 @@ const char* DmaMgr_GetFileNameImpl(u32 vrom) { } //! @bug Since there is no return, in case the file isn't found, the return value will be a pointer to the end // of gDmaDataTable +#ifdef AVOID_UB + return (const char*)iter; +#endif } const char* DmaMgr_GetFileName(u32 vrom) { diff --git a/src/code/fault.c b/src/code/fault.c index 4e1087524e..d1cd9627ae 100644 --- a/src/code/fault.c +++ b/src/code/fault.c @@ -1265,8 +1265,7 @@ void Fault_Init(void) { gFaultMgr.faultHandlerEnabled = true; osCreateMesgQueue(&sFaultInstance->queue, &sFaultInstance->msg, 1); StackCheck_Init(&sFaultThreadInfo, &sFaultStack, STACK_TOP(sFaultStack), 0, 0x100, "fault"); - osCreateThread(&sFaultInstance->thread, 2, Fault_ThreadEntry, 0, STACK_TOP(sFaultStack), - OS_PRIORITY_APPMAX); + osCreateThread(&sFaultInstance->thread, 2, Fault_ThreadEntry, 0, STACK_TOP(sFaultStack), OS_PRIORITY_APPMAX); osStartThread(&sFaultInstance->thread); } diff --git a/src/code/z_actor.c b/src/code/z_actor.c index e3df1542cb..112ff7db85 100644 --- a/src/code/z_actor.c +++ b/src/code/z_actor.c @@ -470,7 +470,8 @@ void func_8002C7BC(TargetContext* targetCtx, Player* player, Actor* actorArg, Gl if ((actorArg != NULL) && (targetCtx->unk_4B == 0)) { Actor_ProjectPos(globalCtx, &actorArg->focus.pos, &projectedFocusPos, &cappedInvWDest); - if (((projectedFocusPos.z <= 0.0f) || (1.0f <= fabsf(projectedFocusPos.x * cappedInvWDest))) || (1.0f <= fabsf(projectedFocusPos.y * cappedInvWDest))) { + if (((projectedFocusPos.z <= 0.0f) || (1.0f <= fabsf(projectedFocusPos.x * cappedInvWDest))) || + (1.0f <= fabsf(projectedFocusPos.y * cappedInvWDest))) { actorArg = NULL; } } @@ -728,23 +729,23 @@ void TitleCard_Draw(GlobalContext* globalCtx, TitleCardContext* titleCtx) { gDPSetPrimColor(OVERLAY_DISP++, 0, 0, (u8)titleCtx->intensity, (u8)titleCtx->intensity, (u8)titleCtx->intensity, (u8)titleCtx->alpha); - gDPLoadTextureBlock(OVERLAY_DISP++, (s32)titleCtx->texture + textureLanguageOffset, G_IM_FMT_IA, G_IM_SIZ_8b, width, height, 0, - G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, - G_TX_NOLOD); + gDPLoadTextureBlock(OVERLAY_DISP++, (s32)titleCtx->texture + textureLanguageOffset, G_IM_FMT_IA, G_IM_SIZ_8b, + width, height, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, + G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); - gSPTextureRectangle(OVERLAY_DISP++, titleX, titleY, ((doubleWidth * 2) + titleX) - 4, titleY + (height * 4) - 1, G_TX_RENDERTILE, - 0, 0, 1 << 10, 1 << 10); + gSPTextureRectangle(OVERLAY_DISP++, titleX, titleY, ((doubleWidth * 2) + titleX) - 4, titleY + (height * 4) - 1, + G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); height = titleCtx->height - height; // If texture is bigger than 0x1000, display the rest if (height > 0) { - gDPLoadTextureBlock(OVERLAY_DISP++, (s32)titleCtx->texture + textureLanguageOffset + 0x1000, G_IM_FMT_IA, G_IM_SIZ_8b, width, - height, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, - G_TX_NOLOD, G_TX_NOLOD); + gDPLoadTextureBlock(OVERLAY_DISP++, (s32)titleCtx->texture + textureLanguageOffset + 0x1000, G_IM_FMT_IA, + G_IM_SIZ_8b, width, height, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, + G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); - gSPTextureRectangle(OVERLAY_DISP++, titleX, titleSecondY, ((doubleWidth * 2) + titleX) - 4, titleSecondY + (height * 4) - 1, - G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); + gSPTextureRectangle(OVERLAY_DISP++, titleX, titleSecondY, ((doubleWidth * 2) + titleX) - 4, + titleSecondY + (height * 4) - 1, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); } CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_actor.c", 2880); diff --git a/src/code/z_lifemeter.c b/src/code/z_lifemeter.c index fed721d81e..115baadcee 100644 --- a/src/code/z_lifemeter.c +++ b/src/code/z_lifemeter.c @@ -452,8 +452,10 @@ void HealthMeter_Draw(GlobalContext* globalCtx) { heartTexCoordPerPixel *= 1 << 10; halfHeartLength = 8.0f; halfHeartLength *= 0.68f; - gSPTextureRectangle(OVERLAY_DISP++, (s32)((heartCenterX - halfHeartLength) * 4), (s32)((heartCenterY - halfHeartLength) * 4), - (s32)((heartCenterX + halfHeartLength) * 4), (s32)((heartCenterY + halfHeartLength) * 4), G_TX_RENDERTILE, 0, 0, + gSPTextureRectangle(OVERLAY_DISP++, (s32)((heartCenterX - halfHeartLength) * 4), + (s32)((heartCenterY - halfHeartLength) * 4), + (s32)((heartCenterX + halfHeartLength) * 4), + (s32)((heartCenterY + halfHeartLength) * 4), G_TX_RENDERTILE, 0, 0, (s32)heartTexCoordPerPixel, (s32)heartTexCoordPerPixel); } else { if ((ddHeartCountMinusOne < 0) || (heartIndex > ddHeartCountMinusOne)) { @@ -474,8 +476,9 @@ void HealthMeter_Draw(GlobalContext* globalCtx) { { Mtx* matrix = Graph_Alloc(gfxCtx, sizeof(Mtx)); - Matrix_SetTranslateScaleMtx2(matrix, 1.0f - (0.32f * beatingHeartPulsingSize), 1.0f - (0.32f * beatingHeartPulsingSize), 1.0f - (0.32f * beatingHeartPulsingSize), - -130.0f + offsetX, 94.5f - offsetY, 0.0f); + Matrix_SetTranslateScaleMtx2( + matrix, 1.0f - (0.32f * beatingHeartPulsingSize), 1.0f - (0.32f * beatingHeartPulsingSize), + 1.0f - (0.32f * beatingHeartPulsingSize), -130.0f + offsetX, 94.5f - offsetY, 0.0f); gSPMatrix(OVERLAY_DISP++, matrix, G_MTX_MODELVIEW | G_MTX_LOAD); gSPVertex(OVERLAY_DISP++, beatingHeartVtx, 4, 0); gSP1Quadrangle(OVERLAY_DISP++, 0, 2, 3, 1, 0); diff --git a/src/code/z_map_mark.c b/src/code/z_map_mark.c index a096a9b566..8718b8de4b 100644 --- a/src/code/z_map_mark.c +++ b/src/code/z_map_mark.c @@ -63,10 +63,10 @@ void MapMark_Init(GlobalContext* globalCtx) { Overlay_Load(overlay->vromStart, overlay->vromEnd, overlay->vramStart, overlay->vramEnd, overlay->loadedRamAddr); sLoadedMarkDataTable = gMapMarkDataTable; - sLoadedMarkDataTable = (void*)(u32)((overlay->vramTable != NULL) - ? (void*)((u32)overlay->vramTable - - (s32)((u32)overlay->vramStart - (u32)overlay->loadedRamAddr)) - : NULL); + sLoadedMarkDataTable = (void*)(u32)( + (overlay->vramTable != NULL) + ? (void*)((u32)overlay->vramTable - (s32)((u32)overlay->vramStart - (u32)overlay->loadedRamAddr)) + : NULL); } void MapMark_ClearPointers(GlobalContext* globalCtx) { diff --git a/src/code/z_player_lib.c b/src/code/z_player_lib.c index 094c72faec..961c000e67 100644 --- a/src/code/z_player_lib.c +++ b/src/code/z_player_lib.c @@ -712,21 +712,21 @@ void func_8008F470(GlobalContext* globalCtx, void** skeleton, Vec3s* jointTable, eyeIndex = sEyeMouthIndexes[face][0]; } - #ifdef AVOID_UB +#ifdef AVOID_UB gSPSegment(POLY_OPA_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(sEyeTextures[gSaveContext.linkAge][eyeIndex])); - #else +#else gSPSegment(POLY_OPA_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(sEyeTextures[eyeIndex])); - #endif +#endif if (mouthIndex < 0) { mouthIndex = sEyeMouthIndexes[face][1]; } - #ifdef AVOID_UB +#ifdef AVOID_UB gSPSegment(POLY_OPA_DISP++, 0x09, SEGMENTED_TO_VIRTUAL(sMouthTextures[gSaveContext.linkAge][mouthIndex])); - #else +#else gSPSegment(POLY_OPA_DISP++, 0x09, SEGMENTED_TO_VIRTUAL(sMouthTextures[mouthIndex])); - #endif +#endif color = &sTunicColors[tunic]; gDPSetEnvColor(POLY_OPA_DISP++, color->r, color->g, color->b, 0); diff --git a/src/overlays/actors/ovl_En_Heishi2/z_en_heishi2.c b/src/overlays/actors/ovl_En_Heishi2/z_en_heishi2.c index aa0514d5d5..a4fd4db5c3 100644 --- a/src/overlays/actors/ovl_En_Heishi2/z_en_heishi2.c +++ b/src/overlays/actors/ovl_En_Heishi2/z_en_heishi2.c @@ -155,7 +155,8 @@ void EnHeishi2_Init(Actor* thisx, GlobalContext* globalCtx) { // "Identification Completed!" osSyncPrintf(VT_FGCOL(YELLOW) " ☆☆☆☆☆ 識別完了! ☆☆☆☆☆ %d\n" VT_RST, this->type); // "Message completed!" - osSyncPrintf(VT_FGCOL(MAGENTA) " ☆☆☆☆☆ メッセージ完了! ☆☆☆☆☆ %x\n\n" VT_RST, (this->actor.params >> 8) & 0xF); + osSyncPrintf(VT_FGCOL(MAGENTA) " ☆☆☆☆☆ メッセージ完了! ☆☆☆☆☆ %x\n\n" VT_RST, + (this->actor.params >> 8) & 0xF); } } diff --git a/src/overlays/actors/ovl_En_Sth/z_en_sth.c b/src/overlays/actors/ovl_En_Sth/z_en_sth.c index 7f0242f229..f59de90536 100644 --- a/src/overlays/actors/ovl_En_Sth/z_en_sth.c +++ b/src/overlays/actors/ovl_En_Sth/z_en_sth.c @@ -61,12 +61,8 @@ static s16 sObjectIds[6] = { }; static FlexSkeletonHeader* sSkeletons[6] = { - &object_ahg_Skel_0000F0, - &object_boj_Skel_0000F0, - &object_boj_Skel_0000F0, - &object_boj_Skel_0000F0, - &object_boj_Skel_0000F0, - &object_boj_Skel_0000F0, + &object_ahg_Skel_0000F0, &object_boj_Skel_0000F0, &object_boj_Skel_0000F0, + &object_boj_Skel_0000F0, &object_boj_Skel_0000F0, &object_boj_Skel_0000F0, }; static AnimationHeader* sAnimations[6] = { diff --git a/src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.c b/src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.c index adf159d81c..8f2716344c 100644 --- a/src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.c +++ b/src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.c @@ -186,7 +186,8 @@ void func_80B3A3D4(EnWonderTalk2* this, GlobalContext* globalCtx) { if ((this->switchFlag >= 0) && (this->talkMode != 4)) { Flags_SetSwitch(globalCtx, this->switchFlag); // "(Forced) I saved it! All of it!" - osSyncPrintf(VT_FGCOL(MAGENTA) "☆☆☆☆☆ (強制)セーブしたよ!おもいっきり! %x\n" VT_RST, this->switchFlag); + osSyncPrintf(VT_FGCOL(MAGENTA) "☆☆☆☆☆ (強制)セーブしたよ!おもいっきり! %x\n" VT_RST, + this->switchFlag); } if (this->talkMode == 4) { diff --git a/src/overlays/actors/ovl_En_Zf/z_en_zf.c b/src/overlays/actors/ovl_En_Zf/z_en_zf.c index a8d90a4a80..fa2962b9f3 100644 --- a/src/overlays/actors/ovl_En_Zf/z_en_zf.c +++ b/src/overlays/actors/ovl_En_Zf/z_en_zf.c @@ -452,9 +452,15 @@ s16 EnZf_FindNextPlatformAwayFromPlayer(Vec3f* pos, s16 curPlatform, s16 arg2, G } } - // These functions have no side effects, so these two calls do nothing + //! @bug `altNextPlatform` can be -1 in certain conditions and cause an out of bounds access. + //! Under normal conditions, this doesn't cause problems because the data before `sPlatformPositions` + //! is section padding between .text and .data, so 0 gets read as a float. + //! Other compilers can shift things and result in a crash. Defining `AVOID_UB` will remove these function calls + //! entirely as they are dead code and do not have any effect. +#ifndef AVOID_UB Math_Vec3f_DistXYZ(&player->actor.world.pos, &sPlatformPositions[nextPlatform]); Math_Vec3f_DistXYZ(&player->actor.world.pos, &sPlatformPositions[altNextPlatform]); +#endif if (altNextPlatform > 0) { s16 nextPlatformToPlayerYaw = diff --git a/src/overlays/actors/ovl_Obj_Oshihiki/z_obj_oshihiki.c b/src/overlays/actors/ovl_Obj_Oshihiki/z_obj_oshihiki.c index 55a519643e..f615a12e9d 100644 --- a/src/overlays/actors/ovl_Obj_Oshihiki/z_obj_oshihiki.c +++ b/src/overlays/actors/ovl_Obj_Oshihiki/z_obj_oshihiki.c @@ -344,8 +344,8 @@ s16 ObjOshihiki_GetHighestFloor(ObjOshihiki* this) { for (i = 1; i < ARRAY_COUNT(this->floorHeights); i++) { if (this->floorHeights[i] > this->floorHeights[highestFloor]) { highestFloor = i; - } else if ((this->floorBgIds[i] == BGCHECK_SCENE) && - ((this->floorHeights[i] - this->floorHeights[highestFloor]) > -0.001f)) { + } else if ((this->floorBgIds[i] == BGCHECK_SCENE) && + ((this->floorHeights[i] - this->floorHeights[highestFloor]) > -0.001f)) { highestFloor = i; } } diff --git a/tools/mkldscript.c b/tools/mkldscript.c index 2239e864e2..4246740dfe 100644 --- a/tools/mkldscript.c +++ b/tools/mkldscript.c @@ -17,7 +17,8 @@ static void write_ld_script(FILE *fout) int i; int j; - fputs("SECTIONS {\n" + fputs("OUTPUT_ARCH (mips)\n\n" + "SECTIONS {\n" " _RomSize = 0;\n" " _RomStart = _RomSize;\n\n", fout); @@ -62,6 +63,7 @@ static void write_ld_script(FILE *fout) fprintf(fout, " %s (.text)\n", seg->includes[j].fpath); if (seg->includes[j].linkerPadding != 0) fprintf(fout, " . += 0x%X;\n", seg->includes[j].linkerPadding); + fprintf(fout, " . = ALIGN(0x10);\n"); } fprintf(fout, " _%sSegmentTextEnd = .;\n", seg->name); @@ -73,7 +75,8 @@ static void write_ld_script(FILE *fout) for (j = 0; j < seg->includesCount; j++) { if (!seg->includes[j].dataWithRodata) - fprintf(fout, " %s (.data)\n", seg->includes[j].fpath); + fprintf(fout, " %s (.data)\n" + " . = ALIGN(0x10);\n", seg->includes[j].fpath); } /* @@ -88,14 +91,17 @@ static void write_ld_script(FILE *fout) fprintf(fout, " _%sSegmentDataEnd = .;\n", seg->name); fprintf(fout, " _%sSegmentDataSize = ABSOLUTE( _%sSegmentDataEnd - _%sSegmentDataStart );\n", seg->name, seg->name, seg->name); - + fprintf(fout, " _%sSegmentRoDataStart = .;\n", seg->name); for (j = 0; j < seg->includesCount; j++) { if (seg->includes[j].dataWithRodata) - fprintf(fout, " %s (.data)\n", seg->includes[j].fpath); - fprintf(fout, " %s (.rodata)\n", seg->includes[j].fpath); + fprintf(fout, " %s (.data)\n" + " . = ALIGN(0x10);\n", seg->includes[j].fpath); + + fprintf(fout, " %s (.rodata)\n" + " . = ALIGN(0x10);\n", seg->includes[j].fpath); // Compilers other than IDO, such as GCC, produce different sections such as // the ones named directly below. These sections do not contain values that // need relocating, but we need to ensure that the base .rodata section @@ -104,13 +110,14 @@ static void write_ld_script(FILE *fout) // the beginning of the entire rodata area in order to remain consistent. // Inconsistencies will lead to various .rodata reloc crashes as a result of // either missing relocs or wrong relocs. - fprintf(fout, " %s (.rodata.str1.4)\n", seg->includes[j].fpath); - fprintf(fout, " %s (.rodata.cst4)\n", seg->includes[j].fpath); - fprintf(fout, " %s (.rodata.cst8)\n", seg->includes[j].fpath); + fprintf(fout, " %s (.rodata.str1.4)\n" + " . = ALIGN(0x10);\n", seg->includes[j].fpath); + fprintf(fout, " %s (.rodata.cst4)\n" + " . = ALIGN(0x10);\n", seg->includes[j].fpath); + fprintf(fout, " %s (.rodata.cst8)\n" + " . = ALIGN(0x10);\n", seg->includes[j].fpath); } - //fprintf(fout, " . = ALIGN(0x10);\n"); - fprintf(fout, " _%sSegmentRoDataEnd = .;\n", seg->name); fprintf(fout, " _%sSegmentRoDataSize = ABSOLUTE( _%sSegmentRoDataEnd - _%sSegmentRoDataStart );\n", seg->name, seg->name, seg->name); @@ -118,9 +125,8 @@ static void write_ld_script(FILE *fout) fprintf(fout, " _%sSegmentSDataStart = .;\n", seg->name); for (j = 0; j < seg->includesCount; j++) - fprintf(fout, " %s (.sdata)\n", seg->includes[j].fpath); - - fprintf(fout, " . = ALIGN(0x10);\n"); + fprintf(fout, " %s (.sdata)\n" + " . = ALIGN(0x10);\n", seg->includes[j].fpath); fprintf(fout, " _%sSegmentSDataEnd = .;\n", seg->name); @@ -129,23 +135,22 @@ static void write_ld_script(FILE *fout) for (j = 0; j < seg->includesCount; j++) fprintf(fout, " %s (.ovl)\n", seg->includes[j].fpath); - fprintf(fout, " . = ALIGN(0x10);\n"); - fprintf(fout, " _%sSegmentOvlEnd = .;\n", seg->name); if (seg->fields & (1 << STMT_increment)) fprintf(fout, " . += 0x%08X;\n", seg->increment); + // fprintf(fout, " . = ALIGN(0x%X);\n", seg->align); fputs(" }\n", fout); - //fprintf(fout, " _RomSize += ( _%sSegmentDataEnd - _%sSegmentTextStart );\n", seg->name, seg->name); + fprintf(fout, " _RomSize += ( _%sSegmentOvlEnd - _%sSegmentTextStart );\n", seg->name, seg->name); fprintf(fout, " _%sSegmentRomEndTemp = _RomSize;\n" "_%sSegmentRomEnd = _%sSegmentRomEndTemp;\n\n", seg->name, seg->name, seg->name); - // algn end of ROM segment + // align end of ROM segment if (seg->fields & (1 << STMT_romalign)) fprintf(fout, " _RomSize = (_RomSize + %i) & ~ %i;\n", seg->romalign - 1, seg->romalign - 1); @@ -156,16 +161,26 @@ static void write_ld_script(FILE *fout) " . = ALIGN(0x10);\n" " _%sSegmentBssStart = .;\n", seg->name, seg->name, seg->name, seg->name); + if (seg->fields & (1 << STMT_align)) fprintf(fout, " . = ALIGN(0x%X);\n", seg->align); + for (j = 0; j < seg->includesCount; j++) - fprintf(fout, " %s (.sbss)\n", seg->includes[j].fpath); + fprintf(fout, " %s (.sbss)\n" + " . = ALIGN(0x10);\n", seg->includes[j].fpath); + for (j = 0; j < seg->includesCount; j++) - fprintf(fout, " %s (.scommon)\n", seg->includes[j].fpath); + fprintf(fout, " %s (.scommon)\n" + " . = ALIGN(0x10);\n", seg->includes[j].fpath); + for (j = 0; j < seg->includesCount; j++) - fprintf(fout, " %s (.bss)\n", seg->includes[j].fpath); + fprintf(fout, " %s (.bss)\n" + " . = ALIGN(0x10);\n", seg->includes[j].fpath); + for (j = 0; j < seg->includesCount; j++) - fprintf(fout, " %s (COMMON)\n", seg->includes[j].fpath); + fprintf(fout, " %s (COMMON)\n" + " . = ALIGN(0x10);\n", seg->includes[j].fpath); + fprintf(fout, " . = ALIGN(0x10);\n" " _%sSegmentBssEnd = .;\n" " _%sSegmentEnd = .;\n" @@ -193,13 +208,55 @@ static void write_ld_script(FILE *fout) //fprintf(fout, "\n }\n"); } + fputs(" _RomEnd = _RomSize;\n\n", fout); - fputs(" _RomEnd = _RomSize;\n}\n", fout); + // Debugging sections + fputs( + // mdebug debug sections + " .mdebug : { *(.mdebug) }" "\n" + " .mdebug.abi32 : { *(.mdebug.abi32) }" "\n" + // DWARF debug sections + // Symbols in the DWARF debugging sections are relative to the beginning of the section so we begin them at 0. + // DWARF 1 + " .debug 0 : { *(.debug) }" "\n" + " .line 0 : { *(.line) }" "\n" + // GNU DWARF 1 extensions + " .debug_srcinfo 0 : { *(.debug_srcinfo) }" "\n" + " .debug_sfnames 0 : { *(.debug_sfnames) }" "\n" + // DWARF 1.1 and DWARF 2 + " .debug_aranges 0 : { *(.debug_aranges) }" "\n" + " .debug_pubnames 0 : { *(.debug_pubnames) }" "\n" + // DWARF 2 + " .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }" "\n" + " .debug_abbrev 0 : { *(.debug_abbrev) }" "\n" + " .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) }" "\n" + " .debug_frame 0 : { *(.debug_frame) }" "\n" + " .debug_str 0 : { *(.debug_str) }" "\n" + " .debug_loc 0 : { *(.debug_loc) }" "\n" + " .debug_macinfo 0 : { *(.debug_macinfo) }" "\n" + // SGI/MIPS DWARF 2 extensions + " .debug_weaknames 0 : { *(.debug_weaknames) }" "\n" + " .debug_funcnames 0 : { *(.debug_funcnames) }" "\n" + " .debug_typenames 0 : { *(.debug_typenames) }" "\n" + " .debug_varnames 0 : { *(.debug_varnames) }" "\n" + // DWARF 3 + " .debug_pubtypes 0 : { *(.debug_pubtypes) }" "\n" + " .debug_ranges 0 : { *(.debug_ranges) }" "\n" + // DWARF Extension + " .debug_macro 0 : { *(.debug_macro) }" "\n" + " .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }" "\n", fout); + + // Discard all other sections not mentioned above + fputs(" /DISCARD/ :" "\n" + " {" "\n" + " *(*);" "\n" + " }" "\n", fout); + fputs("}\n", fout); } static void usage(const char *execname) { - fprintf(stderr, "Nintendo 64 linker script generation tool v0.02\n" + fprintf(stderr, "Nintendo 64 linker script generation tool v0.03\n" "usage: %s SPEC_FILE LD_SCRIPT\n" "SPEC_FILE file describing the organization of object files into segments\n" "LD_SCRIPT filename of output linker script\n",