modern working

This commit is contained in:
DizzyEggg 2025-05-26 13:36:54 +02:00
parent 552f8629b3
commit 7bf162955f
15 changed files with 566 additions and 50 deletions

View File

@ -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 ../../$@ <objs> <libs> | cat"
$(GBAFIX) $@ -t"$(TITLE)" -c$(GAME_CODE) -m$(MAKER_CODE) -r$(REVISION) --silent

View File

@ -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);

View File

@ -5,6 +5,7 @@
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#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) {;}

42
include/mini_printf.h Normal file
View File

@ -0,0 +1,42 @@
/*
* The Minimal snprintf() implementation
*
* Copyright (c) 2013 Michal Ludvig <michal@logix.cz>
* 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

127
ld_script_modern.ld Normal file
View File

@ -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/ :
{
*(*);
}
}

View File

@ -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);

View File

@ -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];

View File

@ -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)

View File

@ -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;

View File

@ -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

View File

@ -1,4 +1,4 @@
#include <string.h>
#include "global.h"
#include "gba/m4a_internal.h"
extern const u8 gCgb3Vol[];

284
src/mini_printf.c Normal file
View File

@ -0,0 +1,284 @@
/*
* The Minimal snprintf() implementation
*
* Copyright (c) 2013,2014 Michal Ludvig <michal@logix.cz>
* 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

View File

@ -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;

View File

@ -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

View File

@ -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);