From 7bf162955f421480459ef75ad29c5ee2f2e4e091 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Mon, 26 May 2025 13:36:54 +0200 Subject: [PATCH] modern working --- Makefile | 99 +++++++++---- include/gba/m4a_internal.h | 2 +- include/global.h | 12 ++ include/mini_printf.h | 42 ++++++ ld_script_modern.ld | 127 +++++++++++++++++ src/code_8069E0C.c | 2 +- src/code_8094F88.c | 4 +- src/code_80A26CC.c | 10 +- src/debug.c | 5 + src/ground_script.c | 19 ++- src/m4a.c | 2 +- src/mini_printf.c | 284 +++++++++++++++++++++++++++++++++++++ src/move_orb_effects_2.c | 4 +- src/text_4.c | 2 + src/wonder_mail_6.c | 2 +- 15 files changed, 566 insertions(+), 50 deletions(-) create mode 100644 include/mini_printf.h create mode 100644 ld_script_modern.ld create mode 100644 src/mini_printf.c diff --git a/Makefile b/Makefile index d6fd6a8d6..e776aef1f 100755 --- a/Makefile +++ b/Makefile @@ -25,6 +25,12 @@ export PATH := $(TOOLCHAIN)/bin:$(PATH) endif endif +# Builds the ROM using a modern compiler +MODERN ?= 0 +ifeq (modern,$(MAKECMDGOALS)) + MODERN := 1 +endif + PREFIX := arm-none-eabi- OBJCOPY := $(PREFIX)objcopy OBJDUMP := $(PREFIX)objdump @@ -32,7 +38,23 @@ AS := $(PREFIX)as CC := $(PREFIX)gcc AS := $(PREFIX)as LD := $(PREFIX)ld -CPP := $(CC) -E + +# use arm-none-eabi-cpp for macOS +# as macOS's default compiler is clang +# and clang's preprocessor will warn on \u +# when preprocessing asm files, expecting a unicode literal +# we can't unconditionally use arm-none-eabi-cpp +# as installations which install binutils-arm-none-eabi +# don't come with it +ifneq ($(MODERN),1) + ifeq ($(shell uname -s),Darwin) + CPP := $(PREFIX)cpp + else + CPP := $(CC) -E + endif +else + CPP := $(PREFIX)cpp +endif ifeq ($(OS),Windows_NT) EXE := .exe @@ -46,17 +68,10 @@ GAME_CODE := B24E MAKER_CODE := 01 REVISION := 0 -ifeq ($(OS),Windows_NT) -LIB := ../../tools/agbcc/lib/libc.a ../../tools/agbcc/lib/libgcc.a ../../libagbsyscall/libagbsyscall.a -else -LIB := -L ../../tools/agbcc/lib -lc -lgcc -L ../../libagbsyscall -lagbsyscall -endif - #### Tools #### SHELL := /bin/bash -o pipefail -CC1 := tools/agbcc/bin/agbcc SHA1SUM := sha1sum -c GBAGFX := tools/gbagfx/gbagfx GBAFIX := tools/gbafix/gbafix @@ -74,15 +89,38 @@ TOOLBASE = $(TOOLDIRS:tools/%=%) TOOLS = $(foreach tool,$(TOOLBASE),tools/$(tool)/$(tool)$(EXE)) -ASFLAGS := -mcpu=arm7tdmi +ASFLAGS := -mcpu=arm7tdmi --defsym MODERN=$(MODERN) -override CC1FLAGS += -mthumb-interwork -Wimplicit -Wparentheses -Wunused -Werror -O2 -fhex-asm -g -INCLUDE_PATHS := -I include -I tools/agbcc/include -CPPFLAGS := -iquote include -I tools/agbcc/include -nostdinc -undef +ifeq ($(MODERN),0) + CC1 := tools/agbcc/bin/agbcc + override CC1FLAGS += -mthumb-interwork -Wimplicit -Wparentheses -Wunused -Werror -O2 -fhex-asm -g + ifeq ($(OS),Windows_NT) + LIB := ../../tools/agbcc/lib/libc.a ../../tools/agbcc/lib/libgcc.a ../../libagbsyscall/libagbsyscall.a + else + LIB := -L ../../tools/agbcc/lib -lc -lgcc -L ../../libagbsyscall -lagbsyscall + endif + INCLUDE_PATHS := -I include -I tools/agbcc/include + CPPFLAGS := -iquote include -I tools/agbcc/include -nostdinc -undef +else + MODERNCC := $(PREFIX)gcc + PATH_MODERNCC := PATH="$(PATH)" $(MODERNCC) + CC1 := $(shell $(PATH_MODERNCC) --print-prog-name=cc1) -quiet + LIBPATH := -L "$(dir $(shell $(PATH_MODERNCC) -mthumb -print-file-name=libgcc.a))" -L "$(dir $(shell $(PATH_MODERNCC) -mthumb -print-file-name=libnosys.a))" -L "$(dir $(shell $(PATH_MODERNCC) -mthumb -print-file-name=libc.a))" + LIB := $(LIBPATH) -lc -lnosys -lgcc -L../../libagbsyscall -lagbsyscall + override CC1FLAGS += -mthumb -mthumb-interwork -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -Wimplicit -Wparentheses -Wunused -Werror -O2 -fno-toplevel-reorder + INCLUDE_DIRS := include + INCLUDE_CPP_ARGS := $(INCLUDE_DIRS:%=-iquote %) + INCLUDE_PATHS := $(INCLUDE_DIRS:%=-I %) + CPPFLAGS := $(INCLUDE_CPP_ARGS) -Wno-trigraphs -DMODERN=$(MODERN) +endif #### Files #### -BUILD_NAME = red +ifeq ($(MODERN),0) + BUILD_NAME = red +else + BUILD_NAME = red_modern +endif BUILD_DIR := build/pmd_$(BUILD_NAME) ROM := pmd_$(BUILD_NAME).gba @@ -104,30 +142,29 @@ DATA_ASM_BUILDDIR = $(BUILD_DIR)/$(DATA_ASM_SUBDIR) SONG_BUILDDIR = $(BUILD_DIR)/$(SONG_SUBDIR) MID_BUILDDIR = $(BUILD_DIR)/$(MID_SUBDIR) -C_SOURCES := $(wildcard src/*.c) +C_SRCS_IN := $(wildcard $(C_SUBDIR)/*.c $(C_SUBDIR)/*/*.c $(C_SUBDIR)/*/*/*.c) +C_SOURCES := $(foreach src,$(C_SRCS_IN),$(if $(findstring .inc.c,$(src)),,$(src))) ASM_SOURCES := $(wildcard asm/*.s data/*.s) C_ASM_SOURCES := $(wildcard src/*.s) SONG_SRCS := $(wildcard sound/songs/*.s) -C_OBJECTS := $(addprefix $(BUILD_DIR)/, $(C_SOURCES:%.c=%.o)) +C_OBJECTS := $(patsubst $(C_SUBDIR)/%.c,$(C_BUILDDIR)/%.o,$(C_SOURCES)) ASM_OBJECTS := $(addprefix $(BUILD_DIR)/, $(ASM_SOURCES:%.s=%.o)) C_ASM_OBJECTS := $(addprefix $(BUILD_DIR)/, $(C_ASM_SOURCES:%.s=%.o)) SONG_OBJS := $(addprefix $(BUILD_DIR)/, $(SONG_SRCS:%.s=%.o)) ALL_OBJECTS := $(C_OBJECTS) $(ASM_OBJECTS) $(C_ASM_OBJECTS) $(SONG_OBJS) +OBJS_REL := $(patsubst $(BUILD_DIR)/%,%,$(ALL_OBJECTS)) SUBDIRS := $(sort $(dir $(ALL_OBJECTS))) - -LD_SCRIPT := $(BUILD_DIR)/ld_script.ld - - # Special configurations required for lib files -$(C_BUILDDIR)/agb_flash.o : CC1FLAGS := -O -mthumb-interwork -$(C_BUILDDIR)/agb_flash_1m.o: CC1FLAGS := -O -mthumb-interwork -$(C_BUILDDIR)/agb_flash_mx.o: CC1FLAGS := -O -mthumb-interwork - -$(C_BUILDDIR)/m4a.o: CC1 := tools/agbcc/bin/old_agbcc +ifeq ($(MODERN),0) + $(C_BUILDDIR)/agb_flash.o : CC1FLAGS := -O -mthumb-interwork + $(C_BUILDDIR)/agb_flash_1m.o: CC1FLAGS := -O -mthumb-interwork + $(C_BUILDDIR)/agb_flash_mx.o: CC1FLAGS := -O -mthumb-interwork + $(C_BUILDDIR)/m4a.o: CC1 := tools/agbcc/bin/old_agbcc +endif #### Main Rules #### @@ -135,7 +172,10 @@ $(C_BUILDDIR)/m4a.o: CC1 := tools/agbcc/bin/old_agbcc ALL_BUILDS := red # Available targets -.PHONY: all clean compare tidy libagbsyscall tools clean-tools $(TOOLDIRS) +.PHONY: all modern clean compare tidy libagbsyscall tools clean-tools $(TOOLDIRS) + +# Pretend rules that are actually flags defer to `make all` +modern: all MAKEFLAGS += --no-print-directory @@ -268,13 +308,18 @@ $(BUILD_DIR)/sym_ewram_init.ld: sym_ewram_init.txt $(BUILD_DIR)/sym_iwram_init.ld: sym_iwram_init.txt $(RAMSCRGEN) iwram_init $< ENGLISH > $@ -LD_SCRIPT := ld_script.ld +ifeq ($(MODERN),0) + LD_SCRIPT := ld_script.ld +else + LD_SCRIPT := ld_script_modern.ld +endif + LD_SCRIPT_DEPS := $(BUILD_DIR)/sym_ewram.ld $(BUILD_DIR)/sym_iwram.ld $(BUILD_DIR)/sym_ewram_init.ld $(BUILD_DIR)/sym_iwram_init.ld # Elf from object files LDFLAGS = -Map ../../$(MAP) $(ELF): $(LD_SCRIPT) $(LD_SCRIPT_DEPS) $(ALL_OBJECTS) libagbsyscall - @cd $(BUILD_DIR) && $(LD) $(LDFLAGS) -T ../../$< --print-memory-usage -o ../../$@ $(LIB) | cat + @cd $(BUILD_DIR) && $(LD) $(LDFLAGS) -T ../../$< --print-memory-usage -o ../../$@ $(OBJS_REL) $(LIB) | cat @echo "cd $(BUILD_DIR) && $(LD) $(LDFLAGS) -T ../../$< --print-memory-usage -o ../../$@ | cat" $(GBAFIX) $@ -t"$(TITLE)" -c$(GAME_CODE) -m$(MAKER_CODE) -r$(REVISION) --silent diff --git a/include/gba/m4a_internal.h b/include/gba/m4a_internal.h index 39a7c2373..84e5826cd 100644 --- a/include/gba/m4a_internal.h +++ b/include/gba/m4a_internal.h @@ -400,7 +400,7 @@ extern const struct ToneData voicegroup_pokemon_cry; extern char gNumMusicPlayers[]; extern char gMaxLines[]; -#define NUM_MUSIC_PLAYERS ((u16)gNumMusicPlayers) +#define NUM_MUSIC_PLAYERS ((u16)((u32)gNumMusicPlayers)) #define MAX_LINES ((u32)gMaxLines) u32 umul3232H32(u32 multiplier, u32 multiplicand); diff --git a/include/global.h b/include/global.h index 837630cdc..8a74aad64 100644 --- a/include/global.h +++ b/include/global.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "config.h" // We need to define config before gba headers as print stuff needs the functions nulled before defines. #include "gba/gba.h" @@ -54,6 +55,17 @@ static inline bool8 AreStringsDifferent(const u8 *str1, const u8 *str2) return strcmp(str1, str2) != 0; } +#ifdef MODERN +#define BUGFIX +#define NONMATCHING + +#include "mini_printf.h" +void sprintfStatic(char *buffer, const char *text, ...); +// Use miniprintf instead of library printf functions +#define sprintf sprintfStatic +#define vsprintf mini_vsprintf +#endif // MODERN + // Sometimes incrementing and decrementing a variable changes how registers are allocated, which helps with matching functions. Functionality-wise this doesn't do anything. #ifdef NONMATCHING #define ASM_MATCH_TRICK(a) {;} diff --git a/include/mini_printf.h b/include/mini_printf.h new file mode 100644 index 000000000..87def992d --- /dev/null +++ b/include/mini_printf.h @@ -0,0 +1,42 @@ +/* + * The Minimal snprintf() implementation + * + * Copyright (c) 2013 Michal Ludvig + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the auhor nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Courtey of https://github.com/mludvig/mini-printf + * stripped to reduce file size for agb needs + */ + +#ifndef __MINI_PRINTF__ +#define __MINI_PRINTF__ + +s32 mini_vsprintf(char *buffer, const char *fmt, va_list va); +s32 mini_vsnprintf(char *buffer, u32 buffer_len, const char *fmt, va_list va); +s32 mini_vpprintf(void *buf, const char *fmt, va_list va); + +#endif diff --git a/ld_script_modern.ld b/ld_script_modern.ld new file mode 100644 index 000000000..adcfd4059 --- /dev/null +++ b/ld_script_modern.ld @@ -0,0 +1,127 @@ +ENTRY(Start) + +gNumMusicPlayers = 8; +gMaxLines = 0; + +MEMORY +{ + EWRAM (rwx) : ORIGIN = 0x2000000, LENGTH = 256K + IWRAM (rwx) : ORIGIN = 0x3000000, LENGTH = 32K + ROM (rx) : ORIGIN = 0x8000000, LENGTH = 32M +} + +SECTIONS { + + ewram 0x2000000 (NOLOAD) : + + ALIGN(4) + { + ewram_start = .; + + data/sound_data.o(.bss); + INCLUDE "sym_ewram.ld" + src/agb_flash.o(.bss); + *libgcc.a:fp-bit.o(.bss); + *libgcc.a:dp-bit.o(.bss); + *libc.a:syscalls.o(.bss); + . = ALIGN(16); + src/m4a.o(ewram_lib); + src/agb_flash.o(ewram_lib); + *libc.a:sbrkr.o(COMMON); + + ewram_end = .; + } > EWRAM + + iwram 0x3000000 (NOLOAD) : + ALIGN(4) + { + iwram_start = .; + INCLUDE "sym_iwram.ld" + iwram_end = .; + } > IWRAM + + /* BEGIN ROM DATA */ + . = 0x8000000; + + .text : + ALIGN(4) + { + asm/crt0.o(.text); + src/code_80001DC.o(.text); + asm/arm_func.o(.text); + src/main_loops.o(.text); + src/*.o(.text*); + asm/*.o(.text*); + *libagbsyscall.a:*.o(.text*); + *libgcc.a:*.o(.text*); + *libc.a:*.o(.text*); + *libnosys.a:*.o(.text*); + } > ROM =0 + + .rodata : + ALIGN(4) + { + src/*.o(.rodata*); + data/*.o(.rodata*); + . = ALIGN(4); + } > ROM =0 + + ewram_init : + ALIGN(4) + { + ewram_init_start = .; + + INCLUDE "sym_ewram_init.ld" + *libc.a:impure.o(.data); + *libc.a:locale.o(.data); + *libc.a:mallocr.o(.data); + + ewram_init_end = .; + . = 0x2724; /* This doesn't really do anything other than setting following 0x2724 bytes to 0 in rom */ + } > EWRAM AT>ROM + + EWRAM_INIT_ROM_START = LOADADDR(ewram_init); + + iwram_init : + ALIGN(4) + { + iwram_init_start = .; + + INCLUDE "sym_iwram_init.ld" + + iwram_init_end = .; + } > IWRAM AT>ROM + + IWRAM_INIT_ROM_START = LOADADDR(iwram_init); + + iwram_lib (NOLOAD) : + ALIGN(4) + { + end = .; /* This is needed for the libc.a function _sbrk */ + . = 0x2090; + gUnknown_3004000 = .; /* Used by sub_80001E0 */ + } > IWRAM + + sound_data : + ALIGN(4) + { + sound/songs/*.o(.rodata); + } > ROM =0 + + /* DWARF 2 sections */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + + /* Discard everything not specifically mentioned above. */ + /DISCARD/ : + { + *(*); + } +} diff --git a/src/code_8069E0C.c b/src/code_8069E0C.c index cd2d8c685..7464408da 100644 --- a/src/code_8069E0C.c +++ b/src/code_8069E0C.c @@ -699,7 +699,7 @@ void sub_806BB6C(Entity *entity, s32 _species) { s16 apparentSpeciesMatch; s32 apparentSpecies = (s16) (GetMonsterApparentID(NULL, species)); - EntityInfo *entInfo; + UNUSED EntityInfo *entInfo; entity->unk22 = 0; entInfo = GetEntInfo(entity); diff --git a/src/code_8094F88.c b/src/code_8094F88.c index 829c140e8..546506f03 100644 --- a/src/code_8094F88.c +++ b/src/code_8094F88.c @@ -59,7 +59,7 @@ unkStruct_203B48C *sub_8095110(void) void sub_8095118(void) { s32 index; - unkStruct_203B480 *unused; + UNUSED unkStruct_203B480 *unused; MemoryFill8(gUnknown_203B480, 0, 0x20 * sizeof(unkStruct_203B480)); MemoryFill8(gUnknown_203B484, 0, sizeof(unkStruct_203B484)); @@ -137,7 +137,7 @@ unkStruct_203B480 * GetMailatIndex(u8 index) void DeleteMailAtIndex(u8 index) { - unkStruct_203B480 *unused; + UNUSED unkStruct_203B480 *unused; MemoryFill8(&gUnknown_203B480[index], 0, sizeof(unkStruct_203B480)); unused = &gUnknown_203B480[index]; diff --git a/src/code_80A26CC.c b/src/code_80A26CC.c index 8425b167f..85d3c9bfd 100644 --- a/src/code_80A26CC.c +++ b/src/code_80A26CC.c @@ -127,14 +127,10 @@ s16 sub_80A2688(u8 r0) return -1; } -s16 sub_80A26B8(s16 r0) +s16 sub_80A26B8(s16 a0_) { - // Useless cast that forces correct ordering - s32 temp; - - temp = r0; - - return gUnknown_8116F9A[r0]; + s32 a0 = (s16) a0_; + return gUnknown_8116F9A[a0]; } s16 sub_80A26CC(s16 r0) diff --git a/src/debug.c b/src/debug.c index 0377a973d..d347bace2 100644 --- a/src/debug.c +++ b/src/debug.c @@ -47,7 +47,12 @@ ALIGNED(4) static const char debug_fill5[] = "pksdir0"; ALIGNED(4) static const char debug_fill6[] = "pksdir0"; ALIGNED(4) static const char debug_fill7[] = "pksdir0"; +// NORETURN attribute required for Modern +#ifdef MODERN +extern void Hang() NORETURN; +#else extern void Hang(); +#endif static void FatalErrorFormatMessage(const u8 *text, ...); static void FatalErrorHang(void) NORETURN; diff --git a/src/ground_script.c b/src/ground_script.c index 7b858a867..6e64035c5 100644 --- a/src/ground_script.c +++ b/src/ground_script.c @@ -134,7 +134,7 @@ bool8 sub_8098DCC(u32 speed); extern const PixelPos gUnknown_81164DC; extern u32 gUnknown_2039DA4; extern char *gUnknown_203B4B0; -extern char gUnknown_2039D98[10]; +extern char gUnknown_2039D98[]; void sub_8099220(void *param_1, s32 param_2); extern u32 gUnlockBranchLabels[]; s16 sub_8002694(u8 param_1); // value -> GroundEnter lookup @@ -710,7 +710,8 @@ s16 HandleAction(Action *action, DebugLocation *debug) case 0x69 ... 0x6f: { PixelPos pos, pos2; s32 res; - s32 dir, dirBefore; + s32 dir; + UNUSED s32 dirBefore; s8 dirS8; action->callbacks->getHitboxCenter(action->parentObject, &pos); pos2.x = action->scriptData.pos2.x - pos.x; @@ -766,7 +767,8 @@ s16 HandleAction(Action *action, DebugLocation *debug) case 0x83 ... 0x88: { if (action->scriptData.unk2A > 0) { PixelPos pos1, pos2, pos3; - s32 dir, dirBefore; + s32 dir; + UNUSED s32 dirBefore; s8 dirS8; action->callbacks->getHitboxCenter(action->parentObject, &pos1); @@ -833,7 +835,8 @@ s16 HandleAction(Action *action, DebugLocation *debug) } else { PixelPos pos1, pos2, pos3, pos4; - s32 tmp1, tmp2; + UNUSED s32 tmp1; + s32 tmp2; s8 dir; bool8 flag; cmd = *action->scriptData.curPtr; @@ -2310,17 +2313,19 @@ s32 ExecuteScriptCommand(Action *action) return 2; } case 0x73: case 0x79: case 0x7f: case 0x85: { - s32 cap1 = curCmd.arg1 * 2 - 1; - s32 cap2 = curCmd.arg2 * 2 - 1; - action->callbacks->getHitboxCenter(action->parentObject, &scriptData->pos1); // BUG: (or two): these lines use the wrong script command arguments to calculate the position offset // making the target position nonsense. But even if they were correct, // the way the cap is calculated would make the random offset biased off-center. // This doesn't affect the released version because these script commands are never used. #ifndef BUGFIX + s32 cap1 = curCmd.arg1 * 2 - 1; + s32 cap2 = curCmd.arg2 * 2 - 1; + + action->callbacks->getHitboxCenter(action->parentObject, &scriptData->pos1); scriptData->pos2.x = scriptData->pos1.x + ((OtherRandInt(cap1) - curCmd.argShort) << 8); scriptData->pos2.y = scriptData->pos1.y + ((OtherRandInt(cap2) - curCmd.arg1) << 8); #else + action->callbacks->getHitboxCenter(action->parentObject, &scriptData->pos1); scriptData->pos2.x = scriptData->pos1.x + ((OtherRandInt(curCmd.arg1 * 2 + 1) - curCmd.arg1) << 8); scriptData->pos2.y = scriptData->pos1.y + ((OtherRandInt(curCmd.arg2 * 2 + 1) - curCmd.arg2) << 8); #endif diff --git a/src/m4a.c b/src/m4a.c index a14060dae..bb4ca9337 100644 --- a/src/m4a.c +++ b/src/m4a.c @@ -1,4 +1,4 @@ -#include +#include "global.h" #include "gba/m4a_internal.h" extern const u8 gCgb3Vol[]; diff --git a/src/mini_printf.c b/src/mini_printf.c new file mode 100644 index 000000000..6e9801ab7 --- /dev/null +++ b/src/mini_printf.c @@ -0,0 +1,284 @@ +/* + * The Minimal snprintf() implementation + * + * Copyright (c) 2013,2014 Michal Ludvig + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the auhor nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * mini-printf courtesy of https://github.com/mludvig/mini-printf + * stripped to reduce file size for agb needs + */ + +#ifdef MODERN + +#include "global.h" +#include "mini_printf.h" + +struct mini_buff +{ + char *buffer, *pbuffer; + u32 buffer_len; +}; + +static s32 _putsAscii(char *s, s32 len, void *buf) +{ + char *p0; + s32 i; + struct mini_buff *b; + + if (!buf) + return len; + + b = buf; + p0 = b->buffer; + + /* Copy to buffer */ + for (i = 0; i < len; i++) + { + if(b->pbuffer == b->buffer + b->buffer_len - 1) + { + break; + } + *(b->pbuffer ++) = s[i]; + } + *(b->pbuffer) = 0; + return b->pbuffer - p0; +} + +static s32 mini_strlen(const char *s) +{ + s32 len = 0; + while (s[len] != '\0') len++; + return len; +} + +static s32 mini_itoa(s32 value, u32 radix, s32 uppercase, bool32 unsig, char *buffer) +{ + char *pbuffer = buffer; + s32 negative = 0; + s32 i, len; + + /* No support for unusual radixes. */ + if (radix > 16) + return 0; + + if (value < 0 && !unsig) + { + negative = 1; + value = -value; + } + + /* This builds the string back to front ... */ + do + { + s32 digit = value % radix; + *(pbuffer++) = (digit < 10 ? '0' + digit : (uppercase ? 'A' : 'a') + digit - 10); + value /= radix; + } while (value > 0); + + if (negative) + *(pbuffer++) = '-'; + + *(pbuffer) = '\0'; + + /* ... now we reverse it (could do it recursively but will + * conserve the stack space) */ + len = (pbuffer - buffer); + for (i = 0; i < len / 2; i++) + { + char j = buffer[i]; + buffer[i] = buffer[len-i-1]; + buffer[len-i-1] = j; + } + + return len; +} + +static s32 mini_pad(char *ptr, s32 len, char pad_char, s32 pad_to, char *buffer) +{ + s32 i; + bool32 overflow = FALSE; + char *pbuffer = buffer; + if(pad_to == 0) + pad_to = len; + if (len > pad_to) + { + len = pad_to; + overflow = TRUE; + } + for(i = pad_to - len; i > 0; i --) + { + *(pbuffer++) = pad_char; + } + for(i = len; i > 0; i --) + { + *(pbuffer++) = *(ptr++); + } + len = pbuffer - buffer; + if(overflow) + { + for (i = 0; i < 3 && pbuffer > buffer; i ++) + { + *(pbuffer-- - 1) = '*'; + } + } + return len; +} + +// Assumes the buffer is large enough to contain the formatted string. +s32 mini_vsprintf(char *buffer, const char *fmt, va_list va) +{ + mini_vsnprintf(buffer, 9999, fmt, va); +} + +s32 mini_vsnprintf(char *buffer, u32 buffer_len, const char *fmt, va_list va) +{ + struct mini_buff b; + s32 n; + b.buffer = buffer; + b.pbuffer = buffer; + b.buffer_len = buffer_len; + if (buffer_len == 0) + buffer = NULL; + n = mini_vpprintf((buffer != NULL) ? &b : NULL, fmt, va); + if (buffer == NULL) + return n; + return b.pbuffer - b.buffer; +} + +s32 mini_vpprintf(void *buf, const char *fmt, va_list va) +{ + char bf[24]; + char bf2[24]; + char ch; + s32 n; + n = 0; + while ((ch=*(fmt++))) + { + s32 len; + if (ch != '%') + { + len = 1; + len = _putsAscii(&ch, len, buf); + } + else + { + char pad_char = ' '; + s32 pad_to = 0; + char l = 0; + char *ptr; + + ch=*(fmt++); + + /* Zero padding requested */ + if (ch == '0') + pad_char = '0'; + while (ch >= '0' && ch <= '9') + { + pad_to = pad_to * 10 + (ch - '0'); + ch= *(fmt++); + } + if(pad_to > (s32) sizeof(bf)) + { + pad_to = sizeof(bf); + } + if (ch == 'l') + { + l = 1; + ch=*(fmt++); + } + + switch (ch) + { + case 0: + goto end; + case 'u': + case 'd': + if(l) + { + len = mini_itoa(va_arg(va, u32), 10, 0, (ch=='u'), bf2); + } + else + { + if(ch == 'u') + { + len = mini_itoa((u32) va_arg(va, u32), 10, 0, 1, bf2); + } + else + { + len = mini_itoa((s32) va_arg(va, s32), 10, 0, 0, bf2); + } + } + len = mini_pad(bf2, len, pad_char, pad_to, bf); + len = _putsAscii(bf, len, buf); + break; + + case 'x': + case 'X': + if(l) + { + len = mini_itoa(va_arg(va, u32), 16, (ch=='X'), 1, bf2); + } + else + { + len = mini_itoa((u32) va_arg(va, u32), 16, (ch=='X'), 1, bf2); + } + len = mini_pad(bf2, len, pad_char, pad_to, bf); + len = _putsAscii(bf, len, buf); + break; + + case 'c' : + ch = (char)(va_arg(va, s32)); + len = mini_pad(&ch, 1, pad_char, pad_to, bf); + len = _putsAscii(bf, len, buf); + break; + + case 's' : + ptr = va_arg(va, char*); + len = mini_strlen(ptr); + if (pad_to > 0) + { + len = mini_pad(ptr, len, pad_char, pad_to, bf); + len = _putsAscii(bf, len, buf); + } + else + { + len = _putsAscii(ptr, len, buf); + } + break; + default: + len = 1; + len = _putsAscii(&ch, len, buf); + break; + } + } + n = n + len; + } +end: + return n; +} + +#endif diff --git a/src/move_orb_effects_2.c b/src/move_orb_effects_2.c index 07c114419..0721272c9 100644 --- a/src/move_orb_effects_2.c +++ b/src/move_orb_effects_2.c @@ -1031,10 +1031,8 @@ void ExposeStatusTarget(Entity * pokemon, Entity * target, s16 param_3) void IdentityItemHolders(Entity *pokemon, Entity *target) { - EntityInfo *entityInfo; - if ((EntityIsValid(target)) && (!HasSafeguardStatus(pokemon, target, TRUE))) { - entityInfo = GetEntInfo(target); + UNUSED EntityInfo *entityInfo = GetEntInfo(target); if (!gDungeon->unk644.itemHoldersIdentified) { nullsub_89(target); gDungeon->unk644.itemHoldersIdentified = TRUE; diff --git a/src/text_4.c b/src/text_4.c index e5677a77a..e7d88e12e 100644 --- a/src/text_4.c +++ b/src/text_4.c @@ -259,5 +259,7 @@ IWRAM_INIT static void sub_8272A8C(Window *windows, s32 id) window->unk44 = 1; } +#ifndef NONMATCHING // Needed to match, because without it the alignment is different. IWRAM_INIT static UNUSED u8 sMatchAlignment = 0; +#endif // NONMATCHING diff --git a/src/wonder_mail_6.c b/src/wonder_mail_6.c index 6a365f34e..692a115a3 100644 --- a/src/wonder_mail_6.c +++ b/src/wonder_mail_6.c @@ -296,7 +296,7 @@ static void HandleWonderMail6DeleteMailMenu(u32 state) { s32 index; s32 menuAction; - unkStruct_203B480 *unused; + UNUSED unkStruct_203B480 *unused; menuAction = 0; sub_8030768(0);