Modernize code

Can compile with arm-none-eabi-gcc 8.3.0
gbafix correctly handles ELF input
This commit is contained in:
PikalaxALT 2019-06-26 08:13:38 -04:00
parent 3f43523352
commit fb06e4a3c9
36 changed files with 3552 additions and 308 deletions

View File

@ -12,12 +12,10 @@ TITLE := POKEMON EMER
GAME_CODE := BPEE GAME_CODE := BPEE
MAKER_CODE := 01 MAKER_CODE := 01
REVISION := 0 REVISION := 0
MODERN ?= 0
SHELL := /bin/bash -o pipefail SHELL := /bin/bash -o pipefail
ROM := pokeemerald.gba
OBJ_DIR := build/emerald
ELF = $(ROM:.gba=.elf) ELF = $(ROM:.gba=.elf)
MAP = $(ROM:.gba=.map) MAP = $(ROM:.gba=.map)
@ -34,12 +32,21 @@ DATA_ASM_BUILDDIR = $(OBJ_DIR)/$(DATA_ASM_SUBDIR)
SONG_BUILDDIR = $(OBJ_DIR)/$(SONG_SUBDIR) SONG_BUILDDIR = $(OBJ_DIR)/$(SONG_SUBDIR)
MID_BUILDDIR = $(OBJ_DIR)/$(MID_SUBDIR) MID_BUILDDIR = $(OBJ_DIR)/$(MID_SUBDIR)
ASFLAGS := -mcpu=arm7tdmi ASFLAGS := -mcpu=arm7tdmi --defsym MODERN=$(MODERN)
ifeq ($(MODERN),0)
CC1 := tools/agbcc/bin/agbcc$(EXE) CC1 := tools/agbcc/bin/agbcc$(EXE)
override CFLAGS += -mthumb-interwork -Wimplicit -Wparentheses -Werror -O2 -fhex-asm override CFLAGS += -mthumb-interwork -Wimplicit -Wparentheses -Werror -O2 -fhex-asm
ROM := pokeemerald.gba
OBJ_DIR := build/emerald
else
CC1 := $(shell $(PREFIX)gcc --print-prog-name=cc1)
override CFLAGS += -mthumb -mthumb-interwork -O2 -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -quiet -fno-toplevel-reorder -Wno-aggressive-loop-optimizations
ROM := pokeemerald_modern.gba
OBJ_DIR := build/modern
endif
CPPFLAGS := -I tools/agbcc/include -I tools/agbcc -iquote include -Wno-trigraphs CPPFLAGS := -I tools/agbcc/include -I tools/agbcc -iquote include -Wno-trigraphs -DMODERN=$(MODERN)
LDFLAGS = -Map ../../$(MAP) LDFLAGS = -Map ../../$(MAP)
@ -109,7 +116,10 @@ clean: tidy
tidy: tidy:
rm -f $(ROM) $(ELF) $(MAP) rm -f $(ROM) $(ELF) $(MAP)
ifeq ($(MODERN),0)
@$(MAKE) tidy MODERN=1
rm -r build/* rm -r build/*
endif
include graphics_file_rules.mk include graphics_file_rules.mk
include map_data_rules.mk include map_data_rules.mk
@ -133,6 +143,7 @@ sound/direct_sound_samples/cry_%.bin: sound/direct_sound_samples/cry_%.aif ; $(A
sound/%.bin: sound/%.aif ; $(AIF) $< $@ sound/%.bin: sound/%.aif ; $(AIF) $< $@
ifeq ($(MODERN),0)
$(C_BUILDDIR)/libc.o: CC1 := tools/agbcc/bin/old_agbcc $(C_BUILDDIR)/libc.o: CC1 := tools/agbcc/bin/old_agbcc
$(C_BUILDDIR)/libc.o: CFLAGS := -O2 $(C_BUILDDIR)/libc.o: CFLAGS := -O2
@ -145,6 +156,7 @@ $(C_BUILDDIR)/agb_flash_mx.o: CFLAGS := -O -mthumb-interwork
$(C_BUILDDIR)/m4a.o: CC1 := tools/agbcc/bin/old_agbcc $(C_BUILDDIR)/m4a.o: CC1 := tools/agbcc/bin/old_agbcc
$(C_BUILDDIR)/record_mixing.o: CFLAGS += -ffreestanding $(C_BUILDDIR)/record_mixing.o: CFLAGS += -ffreestanding
endif
ifeq ($(NODEP),1) ifeq ($(NODEP),1)
$(C_BUILDDIR)/%.o: c_dep := $(C_BUILDDIR)/%.o: c_dep :=
@ -197,7 +209,9 @@ $(OBJ_DIR)/ld_script.ld: ld_script.txt $(OBJ_DIR)/sym_bss.ld $(OBJ_DIR)/sym_comm
$(ELF): $(OBJ_DIR)/ld_script.ld $(OBJS) $(ELF): $(OBJ_DIR)/ld_script.ld $(OBJS)
cd $(OBJ_DIR) && $(LD) $(LDFLAGS) -T ld_script.ld -o ../../$@ $(OBJS_REL) $(LIB) cd $(OBJ_DIR) && $(LD) $(LDFLAGS) -T ld_script.ld -o ../../$@ $(OBJS_REL) $(LIB)
$(FIX) $@ -p -t"$(TITLE)" -c$(GAME_CODE) -m$(MAKER_CODE) -r$(REVISION) --silent
$(ROM): $(ELF) $(ROM): $(ELF)
$(OBJCOPY) -O binary $< $@ $(OBJCOPY) -O binary --gap-fill 0xFF --pad-to 0x9000000 $< $@
$(FIX) $@ -p -t"$(TITLE)" -c$(GAME_CODE) -m$(MAKER_CODE) -r$(REVISION) --silent
modern: ; @$(MAKE) MODERN=1

View File

@ -6,9 +6,20 @@
#define TRUE 1 #define TRUE 1
#define FALSE 0 #define FALSE 0
#define BSS_DATA __attribute__((section(".bss")))
#if MODERN
#define IWRAM_DATA
#else
#define IWRAM_DATA __attribute__((section("iwram_data"))) #define IWRAM_DATA __attribute__((section("iwram_data")))
#endif
#define EWRAM_DATA __attribute__((section("ewram_data"))) #define EWRAM_DATA __attribute__((section("ewram_data")))
#if MODERN
#define NOINLINE __attribute__((noinline))
#else
#define NOINLINE
#endif
#define ALIGNED(n) __attribute__((aligned(n))) #define ALIGNED(n) __attribute__((aligned(n)))
#define SOUND_INFO_PTR (*(struct SoundInfo **)0x3007FF0) #define SOUND_INFO_PTR (*(struct SoundInfo **)0x3007FF0)

View File

@ -192,4 +192,29 @@
REG_IME = imeTemp; \ REG_IME = imeTemp; \
} \ } \
#if MODERN
#define FLOAT_UNS(x, bit) ({ \
s##bit sx = x; \
float fx = (float)sx; \
if (sx < 0) fx += (1 << (bit - 1)) * 2.0f; \
fx; \
})
#define DOUBLE_UNS(x, bit) ({ \
s##bit sx = x; \
double dx = (double)sx; \
if (sx < 0) dx += (1 << (bit - 1)) * 2.0; \
dx; \
})
#else
#define FLOAT_UNS(x, bit) ((float)(x))
#define DOUBLE_UNS(x, bit) ((double)(x))
#endif //MODERN
#define FLOAT_U8(x) FLOAT_UNS(x, 8)
#define FLOAT_U16(x) FLOAT_UNS(x, 16)
#define FLOAT_U32(x) FLOAT_UNS(x, 32)
#define DOUBLE_U8(x) DOUBLE_UNS(x, 8)
#define DOUBLE_U16(x) DOUBLE_UNS(x, 16)
#define DOUBLE_U32(x) DOUBLE_UNS(x, 32)
#endif // GUARD_GBA_MACRO_H #endif // GUARD_GBA_MACRO_H

View File

@ -62,6 +62,10 @@
#define min(a, b) ((a) < (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) >= (b) ? (a) : (b)) #define max(a, b) ((a) >= (b) ? (a) : (b))
#if MODERN
#define abs(x) (((x) < 0) ? -(x) : (x))
#endif
// Extracts the upper 16 bits of a 32-bit number // Extracts the upper 16 bits of a 32-bit number
#define HIHALF(n) (((n) & 0xFFFF0000) >> 16) #define HIHALF(n) (((n) & 0xFFFF0000) >> 16)

View File

@ -4005,9 +4005,6 @@ extern const u32 gBerryPalette_Starf[];
extern const u32 gBerryPic_Enigma[]; extern const u32 gBerryPic_Enigma[];
extern const u32 gBerryPalette_Enigma[]; extern const u32 gBerryPalette_Enigma[];
//credits
extern const u32 gCreditsCopyrightEnd_Gfx[];
//pokenav //pokenav
extern const u8 gPokenavConditionMarker_Gfx[]; extern const u8 gPokenavConditionMarker_Gfx[];
extern const u16 gPokenavConditionMarker_Pal[]; extern const u16 gPokenavConditionMarker_Pal[];

View File

@ -1,6 +1,8 @@
#ifndef GUARD_PLAYER_PC_H #ifndef GUARD_PLAYER_PC_H
#define GUARD_PLAYER_PC_H #define GUARD_PLAYER_PC_H
#include "menu.h"
// local task defines // local task defines
#define PAGE_INDEX data[0] #define PAGE_INDEX data[0]
#define ITEMS_ABOVE_TOP data[1] #define ITEMS_ABOVE_TOP data[1]

View File

@ -485,7 +485,6 @@ extern const u8 gText_CryOf[];
extern const u8 gText_SizeComparedTo[]; extern const u8 gText_SizeComparedTo[];
extern const u8 gText_PokedexRegistration[]; extern const u8 gText_PokedexRegistration[];
extern const u8 gText_UnkCtrlF908Clear01[]; extern const u8 gText_UnkCtrlF908Clear01[];
extern const u8 sText_TenDashes2[];
extern const u8 gText_5MarksPokemon[]; extern const u8 gText_5MarksPokemon[];
extern const u8 gText_UnkHeight[]; extern const u8 gText_UnkHeight[];
extern const u8 gText_UnkWeight[]; extern const u8 gText_UnkWeight[];

View File

@ -423,7 +423,9 @@ SECTIONS {
data/io_reg.o(.rodata); data/io_reg.o(.rodata);
src/string_util.o(.rodata); src/string_util.o(.rodata);
src/link.o(.rodata); src/link.o(.rodata);
src/link.o(.rodata.str1.4);
src/link_rfu.o(.rodata); src/link_rfu.o(.rodata);
src/link_rfu.o(.rodata.str1.4);
src/union_room.o(.rodata); src/union_room.o(.rodata);
src/mystery_gift.o(.rodata); src/mystery_gift.o(.rodata);
src/union_room_player_avatar.o(.rodata); src/union_room_player_avatar.o(.rodata);
@ -434,6 +436,7 @@ SECTIONS {
src/mevent_client.o(.rodata); src/mevent_client.o(.rodata);
src/mevent_scripts.o(.rodata); src/mevent_scripts.o(.rodata);
src/union_room_chat.o(.rodata); src/union_room_chat.o(.rodata);
src/berry_crush.o(.rodata);
data/berry_crush.o(.rodata); data/berry_crush.o(.rodata);
data/berry_powder.o(.rodata); data/berry_powder.o(.rodata);
src/dodrio_berry_picking.o(.rodata); src/dodrio_berry_picking.o(.rodata);
@ -442,6 +445,7 @@ SECTIONS {
data/pokemon_jump.o(.rodata); data/pokemon_jump.o(.rodata);
src/rtc.o(.rodata); src/rtc.o(.rodata);
src/main_menu.o(.rodata); src/main_menu.o(.rodata);
src/battle_controllers.o(.rodata);
src/rom_8034C54.o(.rodata); src/rom_8034C54.o(.rodata);
src/data.o(.rodata); src/data.o(.rodata);
src/battle_bg.o(.rodata); src/battle_bg.o(.rodata);
@ -451,6 +455,7 @@ SECTIONS {
src/battle_controller_player.o(.rodata); src/battle_controller_player.o(.rodata);
data/smokescreen.o(.rodata); data/smokescreen.o(.rodata);
src/battle_controller_opponent.o(.rodata); src/battle_controller_opponent.o(.rodata);
src/battle_ai_switch_items.o(.rodata);
src/battle_controller_link_opponent.o(.rodata); src/battle_controller_link_opponent.o(.rodata);
src/pokemon.o(.rodata); src/pokemon.o(.rodata);
src/trig.o(.rodata); src/trig.o(.rodata);
@ -473,6 +478,7 @@ SECTIONS {
src/event_object_movement.o(.rodata); src/event_object_movement.o(.rodata);
src/text_window.o(.rodata); src/text_window.o(.rodata);
src/scrcmd.o(.rodata); src/scrcmd.o(.rodata);
src/field_control_avatar.o(.rodata);
src/coord_event_weather.o(.rodata); src/coord_event_weather.o(.rodata);
src/field_tasks.o(.rodata); src/field_tasks.o(.rodata);
src/reset_rtc_screen.o(.rodata); src/reset_rtc_screen.o(.rodata);
@ -483,6 +489,7 @@ SECTIONS {
src/battle_anim.o(.rodata); src/battle_anim.o(.rodata);
src/battle_anim_mons.o(.rodata); src/battle_anim_mons.o(.rodata);
data/map_events.o(.rodata); data/map_events.o(.rodata);
src/reshow_battle_screen.o(.rodata);
src/battle_anim_status_effects.o(.rodata); src/battle_anim_status_effects.o(.rodata);
src/title_screen.o(.rodata); src/title_screen.o(.rodata);
src/field_weather.o(.rodata); src/field_weather.o(.rodata);
@ -493,6 +500,7 @@ SECTIONS {
src/trainer_see.o(.rodata); src/trainer_see.o(.rodata);
src/wild_encounter.o(.rodata); src/wild_encounter.o(.rodata);
src/field_effect.o(.rodata); src/field_effect.o(.rodata);
src/scanline_effect.o(.rodata);
src/option_menu.o(.rodata); src/option_menu.o(.rodata);
src/pokedex.o(.rodata); src/pokedex.o(.rodata);
src/trainer_card.o(.rodata); src/trainer_card.o(.rodata);
@ -515,12 +523,14 @@ SECTIONS {
src/record_mixing.o(.rodata); src/record_mixing.o(.rodata);
src/secret_base.o(.rodata); src/secret_base.o(.rodata);
src/tv.o(.rodata); src/tv.o(.rodata);
src/contest_link_80F57C4.o(.rodata);
data/contest_link_80F57C4.o(.rodata); data/contest_link_80F57C4.o(.rodata);
src/script_pokemon_util_80F87D8.o(.rodata); src/script_pokemon_util_80F87D8.o(.rodata);
src/pokemon_size_record.o(.rodata) src/pokemon_size_record.o(.rodata)
src/fldeff_misc.o(.rodata); src/fldeff_misc.o(.rodata);
src/field_special_scene.o(.rodata); src/field_special_scene.o(.rodata);
src/rotating_gate.o(.rodata); src/rotating_gate.o(.rodata);
src/contest_link_80FC4F4.o(.rodata);
src/item_use.o(.rodata); src/item_use.o(.rodata);
src/battle_anim_effects_1.o(.rodata); src/battle_anim_effects_1.o(.rodata);
src/battle_anim_effects_2.o(.rodata); src/battle_anim_effects_2.o(.rodata);
@ -549,6 +559,7 @@ SECTIONS {
src/menu_helpers.o(.rodata); src/menu_helpers.o(.rodata);
src/heal_location.o(.rodata); src/heal_location.o(.rodata);
src/region_map.o(.rodata); src/region_map.o(.rodata);
src/contest_painting_effects.o(.rodata);
data/contest_painting_effects.o(.rodata); data/contest_painting_effects.o(.rodata);
src/decoration.o(.rodata); src/decoration.o(.rodata);
src/slot_machine.o(.rodata); src/slot_machine.o(.rodata);
@ -575,6 +586,7 @@ SECTIONS {
src/save.o(.rodata); src/save.o(.rodata);
src/field_effect_helpers.o(.rodata); src/field_effect_helpers.o(.rodata);
src/contest_ai.o(.rodata); src/contest_ai.o(.rodata);
src/battle_anim_sound_tasks.o(.rodata);
src/battle_controller_safari.o(.rodata); src/battle_controller_safari.o(.rodata);
src/battle_anim_effects_3.o(.rodata); src/battle_anim_effects_3.o(.rodata);
src/move_relearner.o(.rodata); src/move_relearner.o(.rodata);
@ -617,6 +629,7 @@ SECTIONS {
src/battle_arena.o(.rodata); src/battle_arena.o(.rodata);
src/battle_factory.o(.rodata); src/battle_factory.o(.rodata);
src/battle_pike.o(.rodata); src/battle_pike.o(.rodata);
src/mossdeep_gym.o(.rodata);
data/mossdeep_gym.o(.rodata); data/mossdeep_gym.o(.rodata);
src/battle_pyramid.o(.rodata); src/battle_pyramid.o(.rodata);
src/item_menu.o(.rodata); src/item_menu.o(.rodata);
@ -626,6 +639,7 @@ SECTIONS {
src/party_menu.o(.rodata); src/party_menu.o(.rodata);
src/battle_tent.o(.rodata); src/battle_tent.o(.rodata);
src/unk_text_util_2.o(.rodata); src/unk_text_util_2.o(.rodata);
src/multiboot.o(.rodata);
src/unk_81BAD84.o(.rodata); src/unk_81BAD84.o(.rodata);
src/battle_controller_player_partner.o(.rodata); src/battle_controller_player_partner.o(.rodata);
src/mirage_tower.o(.rodata); src/mirage_tower.o(.rodata);
@ -638,11 +652,16 @@ SECTIONS {
src/pokenav_match_call_ui.o(.rodata); src/pokenav_match_call_ui.o(.rodata);
src/pokenav_unk_1.o(.rodata); src/pokenav_unk_1.o(.rodata);
data/pokenav.o(.rodata); data/pokenav.o(.rodata);
src/pokenav_unk_3.o(.rodata);
src/pokenav_unk_4.o(.rodata);
src/pokenav_unk_5.o(.rodata);
src/pokenav_unk_10.o(.rodata); src/pokenav_unk_10.o(.rodata);
src/pokenav_match_call_data.o(.rodata); src/pokenav_match_call_data.o(.rodata);
src/menu_specialized.o(.rodata); src/menu_specialized.o(.rodata);
src/ereader_helpers.o(.rodata);
data/ereader_helpers.o(.rodata); data/ereader_helpers.o(.rodata);
src/faraway_island.o(.rodata); src/faraway_island.o(.rodata);
src/ereader_screen.o(.rodata);
data/ereader_screen.o(.rodata); data/ereader_screen.o(.rodata);
src/trainer_hill.o(.rodata); src/trainer_hill.o(.rodata);
src/rayquaza_scene.o(.rodata); src/rayquaza_scene.o(.rodata);
@ -1195,6 +1214,7 @@ SECTIONS {
lib_rodata : lib_rodata :
SUBALIGN(4) SUBALIGN(4)
{ {
src/m4a.o(.rodata);
src/agb_flash.o(.rodata); src/agb_flash.o(.rodata);
src/agb_flash_1m.o(.rodata); src/agb_flash_1m.o(.rodata);
src/agb_flash_mx.o(.rodata); src/agb_flash_mx.o(.rodata);

View File

@ -5354,7 +5354,7 @@ void sub_8102EB0(struct Sprite* sprite)
if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_OPPONENT) if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_OPPONENT)
{ {
a = gBattleAnimArgs[1]; a = gBattleAnimArgs[1];
(u16)gBattleAnimArgs[1] = -a; *(u16 *)&gBattleAnimArgs[1] = -a;
} }
sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 2) + gBattleAnimArgs[1]; sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 2) + gBattleAnimArgs[1];

View File

@ -1024,13 +1024,13 @@ static const union AnimCmd gUnknown_0860D020[] =
static const union AnimCmd gUnknown_0860D028[] = static const union AnimCmd gUnknown_0860D028[] =
{ {
ANIMCMD_FRAME(18, 129, .vFlip = TRUE), ANIMCMD_FRAME(18, 1, .vFlip = TRUE),
ANIMCMD_END, ANIMCMD_END,
}; };
static const union AnimCmd gUnknown_0860D030[] = static const union AnimCmd gUnknown_0860D030[] =
{ {
ANIMCMD_FRAME(16, 65, .hFlip = TRUE), ANIMCMD_FRAME(16, 1, .hFlip = TRUE),
ANIMCMD_END, ANIMCMD_END,
}; };

View File

@ -914,7 +914,6 @@ void CopyBgTilemapBufferToVram(u8 bg)
void CopyToBgTilemapBufferRect(u8 bg, const void* src, u8 destX, u8 destY, u8 width, u8 height) void CopyToBgTilemapBufferRect(u8 bg, const void* src, u8 destX, u8 destY, u8 width, u8 height)
{ {
const void *srcCopy;
u16 destX16; u16 destX16;
u16 destY16; u16 destY16;
u16 mode; u16 mode;
@ -924,27 +923,31 @@ void CopyToBgTilemapBufferRect(u8 bg, const void* src, u8 destX, u8 destY, u8 wi
switch (GetBgType(bg)) switch (GetBgType(bg))
{ {
case 0: case 0:
srcCopy = src; {
const u16 * srcCopy = src;
for (destY16 = destY; destY16 < (destY + height); destY16++) for (destY16 = destY; destY16 < (destY + height); destY16++)
{ {
for (destX16 = destX; destX16 < (destX + width); destX16++) for (destX16 = destX; destX16 < (destX + width); destX16++)
{ {
((u16*)sGpuBgConfigs2[bg].tilemap)[((destY16 * 0x20) + destX16)] = *((u16*)srcCopy)++; ((u16*)sGpuBgConfigs2[bg].tilemap)[((destY16 * 0x20) + destX16)] = *srcCopy++;
} }
} }
break; break;
}
case 1: case 1:
srcCopy = src; {
const u8 * srcCopy = src;
mode = GetBgMetricAffineMode(bg, 0x1); mode = GetBgMetricAffineMode(bg, 0x1);
for (destY16 = destY; destY16 < (destY + height); destY16++) for (destY16 = destY; destY16 < (destY + height); destY16++)
{ {
for (destX16 = destX; destX16 < (destX + width); destX16++) for (destX16 = destX; destX16 < (destX + width); destX16++)
{ {
((u8*)sGpuBgConfigs2[bg].tilemap)[((destY16 * mode) + destX16)] = *((u8*)srcCopy)++; ((u8*)sGpuBgConfigs2[bg].tilemap)[((destY16 * mode) + destX16)] = *srcCopy++;
} }
} }
break; break;
} }
}
} }
} }

View File

@ -269,8 +269,6 @@ extern const u8 gText_Contest_Fear[];
extern const u8 gText_BDot[]; extern const u8 gText_BDot[];
extern const u8 gText_CDot[]; extern const u8 gText_CDot[];
extern const u8 *const gUnknown_08587E10[]; extern const u8 *const gUnknown_08587E10[];
extern const struct SpriteTemplate gSpriteTemplate_8587AD0;
extern const struct SpriteTemplate gSpriteTemplate_8587B18[];
extern void (*const gContestEffectFuncs[])(void); extern void (*const gContestEffectFuncs[])(void);
static const u8 gUnknown_08587A6C[] = static const u8 gUnknown_08587A6C[] =
@ -1268,7 +1266,7 @@ static void sub_80D8108(u8 taskId)
gTasks[taskId].data[0]++; gTasks[taskId].data[0]++;
break; break;
case 1: case 1:
(s16)gBattle_BG1_Y += 7; *(s16*)&gBattle_BG1_Y += 7;
if ((s16)gBattle_BG1_Y <= 160) if ((s16)gBattle_BG1_Y <= 160)
break; break;
gTasks[taskId].data[0]++; gTasks[taskId].data[0]++;

View File

@ -28,11 +28,11 @@ struct ContestWinner *gUnknown_030061C0;
u16 *gContestPaintingMonPalette; u16 *gContestPaintingMonPalette;
// IWRAM bss // IWRAM bss
IWRAM_DATA u8 gContestPaintingState; static u8 gContestPaintingState;
IWRAM_DATA u16 gContestPaintingMosaicVal; static u16 gContestPaintingMosaicVal;
IWRAM_DATA u16 gContestPaintingFadeCounter; static u16 gContestPaintingFadeCounter;
IWRAM_DATA bool8 gUnknown_030011F6; static bool8 gUnknown_030011F6;
IWRAM_DATA u8 gContestPaintingWindowId; static u8 gContestPaintingWindowId;
static void ShowContestPainting(void); static void ShowContestPainting(void);
static void HoldContestPainting(void); static void HoldContestPainting(void);

View File

@ -8,7 +8,7 @@
#define DMA_REQUEST_COPY16 3 #define DMA_REQUEST_COPY16 3
#define DMA_REQUEST_FILL16 4 #define DMA_REQUEST_FILL16 4
IWRAM_DATA struct BSS_DATA struct
{ {
const u8 *src; const u8 *src;
u8 *dest; u8 *dest;

View File

@ -145,7 +145,7 @@ EWRAM_DATA u16 * gUnknown_02022CE4[4] = {NULL};
EWRAM_DATA struct DodrioBerryPickingStruct_2022CF4 * gUnknown_02022CF4 = NULL; EWRAM_DATA struct DodrioBerryPickingStruct_2022CF4 * gUnknown_02022CF4 = NULL;
EWRAM_DATA struct DodrioBerryPickingSubstruct_0160 * gUnknown_02022CF8 = NULL; EWRAM_DATA struct DodrioBerryPickingSubstruct_0160 * gUnknown_02022CF8 = NULL;
IWRAM_DATA bool32 gUnknown_03000DB0; static bool32 gUnknown_03000DB0;
void sub_8024A1C(void); void sub_8024A1C(void);
void sub_8024A30(struct DodrioBerryPickingStruct *); void sub_8024A30(struct DodrioBerryPickingStruct *);

View File

@ -26,17 +26,17 @@ static void sub_81D414C(void);
static void sub_81D3F1C(u32, u32*, u32*); static void sub_81D3F1C(u32, u32*, u32*);
static void sub_81D3F68(void); static void sub_81D3F68(void);
IWRAM_DATA struct Unknown030012C8 gUnknown_030012C8; static struct Unknown030012C8 gUnknown_030012C8;
IWRAM_DATA u16 gUnknown_030012E0; static u16 gUnknown_030012E0;
IWRAM_DATA u16 gUnknown_030012E2; static u16 gUnknown_030012E2;
IWRAM_DATA u16 gUnknown_030012E4; static u16 gUnknown_030012E4;
IWRAM_DATA u16 gUnknown_030012E6; static u16 gUnknown_030012E6;
IWRAM_DATA u32 gUnknown_030012E8; static u32 gUnknown_030012E8;
IWRAM_DATA u16 gUnknown_030012EC; static u16 gUnknown_030012EC;
IWRAM_DATA u16 gUnknown_030012EE; static u16 gUnknown_030012EE;
IWRAM_DATA u16 gUnknown_030012F0; static u16 gUnknown_030012F0;
IWRAM_DATA u16 gUnknown_030012F2; static u16 gUnknown_030012F2;
IWRAM_DATA u16 gUnknown_030012F4; static u16 gUnknown_030012F4;
extern const u8 gUnknown_08625B6C[][0x148]; extern const u8 gUnknown_08625B6C[][0x148];

View File

@ -891,6 +891,7 @@ static void sub_81094D0(u8 taskId) // animate Move_ERUPTION?
break; break;
default: default:
break;
} }
} }

View File

@ -1148,7 +1148,8 @@ static void sub_8112B78(struct Sprite *sprite)
if (++coeffB > 16) if (++coeffB > 16)
coeffB = 16; coeffB = 16;
if (--(s16)coeffA < 0) --coeffA;
if ((s16)coeffA < 0)
coeffA = 0; coeffA = 0;
SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(coeffA, coeffB)); SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(coeffA, coeffB));

View File

@ -52,22 +52,21 @@ struct LinkTestBGInfo
// Static RAM declarations // Static RAM declarations
IWRAM_DATA struct BlockTransfer sBlockSend; static struct BlockTransfer sBlockSend;
IWRAM_DATA u32 link_c_unused_03000d1c; static struct BlockTransfer sBlockRecv[MAX_LINK_PLAYERS];
IWRAM_DATA struct BlockTransfer sBlockRecv[MAX_LINK_PLAYERS]; static u32 sBlockSendDelayCounter;
IWRAM_DATA u32 sBlockSendDelayCounter; static u32 gUnknown_03000D54;
IWRAM_DATA u32 gUnknown_03000D54; static u8 gUnknown_03000D58;
IWRAM_DATA u8 gUnknown_03000D58; static u32 sPlayerDataExchangeStatus;
IWRAM_DATA u32 sPlayerDataExchangeStatus; static u32 gUnknown_03000D60;
IWRAM_DATA u32 gUnknown_03000D60; static u8 sLinkTestLastBlockSendPos;
IWRAM_DATA u8 sLinkTestLastBlockSendPos; static u8 sLinkTestLastBlockRecvPos[MAX_LINK_PLAYERS];
ALIGNED() IWRAM_DATA u8 sLinkTestLastBlockRecvPos[MAX_LINK_PLAYERS]; static u8 sNumVBlanksWithoutSerialIntr;
IWRAM_DATA u8 sNumVBlanksWithoutSerialIntr; static bool8 sSendBufferEmpty;
IWRAM_DATA bool8 sSendBufferEmpty; static u16 sSendNonzeroCheck;
IWRAM_DATA u16 sSendNonzeroCheck; static u16 sRecvNonzeroCheck;
IWRAM_DATA u16 sRecvNonzeroCheck; static u8 sChecksumAvailable;
IWRAM_DATA u8 sChecksumAvailable; static u8 sHandshakePlayerCount;
IWRAM_DATA u8 sHandshakePlayerCount;
u16 gLinkPartnersHeldKeys[6]; u16 gLinkPartnersHeldKeys[6];
u32 gLinkDebugSeed; u32 gLinkDebugSeed;

View File

@ -24,10 +24,10 @@ extern u16 gHeldKeyCodeToSend;
struct UnkRfuStruct_1 gUnknown_03004140; struct UnkRfuStruct_1 gUnknown_03004140;
struct UnkRfuStruct_2 gUnknown_03005000; struct UnkRfuStruct_2 gUnknown_03005000;
IWRAM_DATA u8 gUnknown_03000D74; BSS_DATA u8 gUnknown_03000D74;
ALIGNED(4) IWRAM_DATA u8 gUnknown_03000D78[8]; ALIGNED(4) BSS_DATA u8 gUnknown_03000D78[8];
IWRAM_DATA u8 gUnknown_03000D80[16]; BSS_DATA u8 gUnknown_03000D80[16];
IWRAM_DATA u16 gUnknown_03000D90[8]; BSS_DATA u16 gUnknown_03000D90[8];
EWRAM_DATA u8 gWirelessStatusIndicatorSpriteId = 0; EWRAM_DATA u8 gWirelessStatusIndicatorSpriteId = 0;
EWRAM_DATA ALIGNED(4) struct UnkLinkRfuStruct_02022B14 gUnknown_02022B14 = {}; EWRAM_DATA ALIGNED(4) struct UnkLinkRfuStruct_02022B14 gUnknown_02022B14 = {};
@ -2021,6 +2021,8 @@ void sub_800DBF8(u8 *q1, u8 mode)
} }
} }
// File boundary here maybe?
void PkmnStrToASCII(u8 *q1, const u8 *q2) void PkmnStrToASCII(u8 *q1, const u8 *q2)
{ {
s32 i; s32 i;
@ -5191,4 +5193,3 @@ u32 GetRfuRecvQueueLength(void)
{ {
return gUnknown_03005000.unk_124.unk_8c2; return gUnknown_03005000.unk_124.unk_8c2;
} }

View File

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

View File

@ -85,7 +85,7 @@ void EnableVCountIntrAtLine150(void);
void AgbMain() void AgbMain()
{ {
RegisterRamReset(RESET_ALL); RegisterRamReset(MODERN ? RESET_ALL & ~RESET_IWRAM : RESET_ALL);
*(vu16 *)BG_PLTT = 0x7FFF; *(vu16 *)BG_PLTT = 0x7FFF;
InitGpuRegManager(); InitGpuRegManager();
REG_WAITCNT = WAITCNT_PREFETCH_ENABLE | WAITCNT_WS0_S_1 | WAITCNT_WS0_N_3; REG_WAITCNT = WAITCNT_PREFETCH_ENABLE | WAITCNT_WS0_S_1 | WAITCNT_WS0_N_3;

View File

@ -33,7 +33,7 @@ static void Task_BardSong(u8 taskId);
static void StorytellerSetup(void); static void StorytellerSetup(void);
static void Storyteller_ResetFlag(void); static void Storyteller_ResetFlag(void);
IWRAM_DATA u8 sSelectedStory; static u8 sSelectedStory;
struct BardSong gBardSong; struct BardSong gBardSong;

View File

@ -435,7 +435,7 @@ static int MultiBootHandShake(struct MultiBootParam *mp)
#undef must_data #undef must_data
} }
static void MultiBootWaitCycles(u32 cycles) static NOINLINE void MultiBootWaitCycles(u32 cycles)
{ {
asm("mov r2, pc"); asm("mov r2, pc");
asm("lsr r2, #24"); asm("lsr r2, #24");

View File

@ -97,7 +97,7 @@ static void FormatMonSizeRecord(u8 *string, u32 size)
{ {
#ifdef UNITS_IMPERIAL #ifdef UNITS_IMPERIAL
//Convert size from centimeters to inches //Convert size from centimeters to inches
size = (double)(size * 10) / (CM_PER_INCH * 10); size = DOUBLE_U32(size * 10) / (CM_PER_INCH * 10);
#endif #endif
string = ConvertIntToDecimalStringN(string, size / 10, 0, 8); string = ConvertIntToDecimalStringN(string, size / 10, 0, 8);

View File

@ -142,7 +142,7 @@ static const union AnimCmd sSpriteAnim_85104CC[] =
static const union AnimCmd sSpriteAnim_85104D4[] = static const union AnimCmd sSpriteAnim_85104D4[] =
{ {
ANIMCMD_FRAME(0, 158, .vFlip = TRUE), ANIMCMD_FRAME(0, 30, .vFlip = TRUE),
ANIMCMD_JUMP(0), ANIMCMD_JUMP(0),
}; };

View File

@ -3969,7 +3969,7 @@ static void sub_8144410(struct Sprite *sprite)
if (!sub_8143B48(sprite)) if (!sub_8143B48(sprite))
{ {
gUnknown_0203AB88->var90 = 0.0f; gUnknown_0203AB88->var90 = 0.0f;
gUnknown_0203AB88->var8C -= (float)(gUnknown_085B6348[gUnknown_0203AB88->var04_0].var03) gUnknown_0203AB88->var8C -= FLOAT_U8(gUnknown_085B6348[gUnknown_0203AB88->var04_0].var03)
/ (gUnknown_085B6348[gUnknown_0203AB88->var04_0].var04 + 1); / (gUnknown_085B6348[gUnknown_0203AB88->var04_0].var04 + 1);
sprite->data[1] = 4; sprite->data[1] = 4;
sprite->callback = sub_8144264; sprite->callback = sub_8144264;
@ -3994,8 +3994,8 @@ static void sub_8144514(struct Sprite *sprite)
if (gUnknown_0203AB88->var94 > 40.f) if (gUnknown_0203AB88->var94 > 40.f)
return; return;
gUnknown_0203AB88->var98 = -(4.0f / (float)gUnknown_0203AB88->var86); gUnknown_0203AB88->var98 = -(4.0f / FLOAT_U16(gUnknown_0203AB88->var86));
gUnknown_0203AB88->var90 = -(gUnknown_0203AB88->var8C / (float)gUnknown_0203AB88->var86); gUnknown_0203AB88->var90 = -(gUnknown_0203AB88->var8C / FLOAT_U16(gUnknown_0203AB88->var86));
sprite->animNum = 2; sprite->animNum = 2;
sprite->animBeginning = TRUE; sprite->animBeginning = TRUE;
sprite->animEnded = FALSE; sprite->animEnded = FALSE;
@ -4010,8 +4010,8 @@ static void sub_81445D8(struct Sprite *sprite)
return; return;
m4aSongNumStartOrChange(SE_TAMAKORO_E); m4aSongNumStartOrChange(SE_TAMAKORO_E);
gUnknown_0203AB88->var98 = -(20.0f / (float)gUnknown_0203AB88->var84); gUnknown_0203AB88->var98 = -(20.0f / FLOAT_U16(gUnknown_0203AB88->var84));
gUnknown_0203AB88->var90 = ((1.0f - gUnknown_0203AB88->var8C) / (float)gUnknown_0203AB88->var84); gUnknown_0203AB88->var90 = ((1.0f - gUnknown_0203AB88->var8C) / FLOAT_U16(gUnknown_0203AB88->var84));
sprite->animNum = 1; sprite->animNum = 1;
sprite->animBeginning = TRUE; sprite->animBeginning = TRUE;
sprite->animEnded = FALSE; sprite->animEnded = FALSE;

View File

@ -409,6 +409,7 @@ void UpdatePulseBlend(struct PulseBlend *pulseBlend)
} }
break; break;
case 2: // Flip back and forth case 2: // Flip back and forth
// This code is never reached
if (pulseBlendPalette->fadeDirection) if (pulseBlendPalette->fadeDirection)
pulseBlendPalette->blendCoeff = 0; pulseBlendPalette->blendCoeff = 0;
else else

View File

@ -626,7 +626,10 @@ static u16 CalculateChecksum(void *data, u16 size)
u32 checksum = 0; u32 checksum = 0;
for (i = 0; i < (size / 4); i++) for (i = 0; i < (size / 4); i++)
checksum += *((u32 *)data)++; {
checksum += *((u32 *)data);
data += sizeof(u32);
}
return ((checksum >> 16) + checksum); return ((checksum >> 16) + checksum);
} }

View File

@ -62,7 +62,7 @@ static EWRAM_DATA u16 sMovingNpcMapBank = 0;
static EWRAM_DATA u16 sMovingNpcMapId = 0; static EWRAM_DATA u16 sMovingNpcMapId = 0;
static EWRAM_DATA u16 sFieldEffectScriptId = 0; static EWRAM_DATA u16 sFieldEffectScriptId = 0;
IWRAM_DATA u8 gUnknown_03000F30; static u8 gUnknown_03000F30;
extern const SpecialFunc gSpecials[]; extern const SpecialFunc gSpecials[];
extern const u8 *gStdScripts[]; extern const u8 *gStdScripts[];

View File

@ -1017,8 +1017,8 @@ const u8 *const gUnknown_0858BBEC[] =
EWRAM_DATA u8 gUnknown_02039F90 = 0; EWRAM_DATA u8 gUnknown_02039F90 = 0;
IWRAM_DATA u8 gUnknown_03001124[7]; static u8 gUnknown_03001124[7];
IWRAM_DATA u32 filler_0300112c; static u32 filler_0300112c;
static void Task_HandleMultichoiceInput(u8); static void Task_HandleMultichoiceInput(u8);
static void Task_HandleYesNoInput(u8); static void Task_HandleYesNoInput(u8);

View File

@ -56,9 +56,9 @@ struct {
u16 move; u16 move;
} sTV_SecretBaseVisitMonsTemp[10]; } sTV_SecretBaseVisitMonsTemp[10];
IWRAM_DATA u8 sTVShowMixingNumPlayers; static u8 sTVShowMixingNumPlayers;
IWRAM_DATA u8 sTVShowNewsMixingNumPlayers; static u8 sTVShowNewsMixingNumPlayers;
IWRAM_DATA s8 sTVShowMixingCurSlot; static s8 sTVShowMixingCurSlot;
EWRAM_DATA u16 sPokemonAnglerSpecies = 0; EWRAM_DATA u16 sPokemonAnglerSpecies = 0;
EWRAM_DATA u16 sPokemonAnglerAttemptCounters = 0; EWRAM_DATA u16 sPokemonAnglerAttemptCounters = 0;
@ -70,9 +70,6 @@ EWRAM_DATA u8 sTVSecretBaseSecretsRandomValues[3] = {};
// Static ROM declarations // Static ROM declarations
extern const u8 *const sTVBravoTrainerTextGroup[];
extern const u8 *const sTVBravoTrainerBattleTowerTextGroup[];
void ClearPokemonNews(void); void ClearPokemonNews(void);
u8 GetTVChannelByShowType(u8 kind); u8 GetTVChannelByShowType(u8 kind);
u8 FindFirstActiveTVShowThatIsNotAMassOutbreak(void); u8 FindFirstActiveTVShowThatIsNotAMassOutbreak(void);

View File

@ -60,9 +60,9 @@ EWRAM_DATA u8 gUnknown_02022C3E = 0;
EWRAM_DATA struct TradeUnkStruct gUnknown_02022C40 = {}; EWRAM_DATA struct TradeUnkStruct gUnknown_02022C40 = {};
// IWRAM vars // IWRAM vars
IWRAM_DATA struct UnkStruct_Leader *gUnknown_03000DA0; static struct UnkStruct_Leader *gUnknown_03000DA0;
IWRAM_DATA struct UnkStruct_Group *gUnknown_03000DA4; static struct UnkStruct_Group *gUnknown_03000DA4;
IWRAM_DATA struct UnkStruct_URoom *gUnknown_03000DA8; static struct UnkStruct_URoom *gUnknown_03000DA8;
// this file's functions // this file's functions
void sub_80173E0(u8 windowId, u8 arg1, const u8 *str, u8 arg3, u8 arg4, u8 arg5); void sub_80173E0(u8 windowId, u8 arg1, const u8 *str, u8 arg3, u8 arg4, u8 arg5);

View File

@ -40,7 +40,7 @@ struct UnkStruct_2022C6C
s16 a0; s16 a0;
}; };
IWRAM_DATA struct UnkStruct_3000DAC * gUnknown_03000DAC; static struct UnkStruct_3000DAC * gUnknown_03000DAC;
EWRAM_DATA struct UnkStruct_2022C6C * gUnknown_02022C6C = NULL; EWRAM_DATA struct UnkStruct_2022C6C * gUnknown_02022C6C = NULL;

3147
tools/gbafix/elf.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,45 +1,45 @@
/* /*
"$Id: gbafix.c,v 1.2 2008-07-30 17:12:51 wntrmute Exp $" "$Id: gbafix.c,v 1.2 2008-07-30 17:12:51 wntrmute Exp $"
DevkitPro GBA ROM fix utility DevkitPro GBA ROM fix utility
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version. version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details. Library General Public License for more details.
You should have received a copy of the GNU Library General Public You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free Software License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA. USA.
Please report all bugs and problems through the bug tracker at Please report all bugs and problems through the bug tracker at
"http://sourceforge.net/tracker/?group_id=114505&atid=668551". "http://sourceforge.net/tracker/?group_id=114505&atid=668551".
"$Header: /lvm/shared/ds/ds/cvs/devkitpro-cvsbackup/tools/gba/gbatools/gbafix.c,v 1.2 2008-07-30 17:12:51 wntrmute Exp $" "$Header: /lvm/shared/ds/ds/cvs/devkitpro-cvsbackup/tools/gba/gbatools/gbafix.c,v 1.2 2008-07-30 17:12:51 wntrmute Exp $"
*/ */
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
// gbafix.c // gbafix.c
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
/* /*
Gameboy Advance ROM fixer (by Dark Fader / BlackThunder / WinterMute / Diegoisawesome) Gameboy Advance ROM fixer (by Dark Fader / BlackThunder / WinterMute / Diegoisawesome)
Validates header of GBA roms. Validates header of GBA roms.
History History
------- -------
v1.06 - added output silencing, (Diegoisawesome) v1.06 - added output silencing, (Diegoisawesome)
v1.05 - added debug offset argument, (Diegoisawesome) v1.05 - added debug offset argument, (Diegoisawesome)
v1.04 - converted to plain C, (WinterMute) v1.04 - converted to plain C, (WinterMute)
v1.03 - header.fixed, header.device_type v1.03 - header.fixed, header.device_type
v1.02 - redefined the options (rgbfix style), checksum=0 v1.02 - redefined the options (rgbfix style), checksum=0
v1.01 - fix in parameters v1.01 - fix in parameters
v1.00 - logo, complement v1.00 - logo, complement
*/ */
#pragma pack(1) #pragma pack(1)
@ -48,26 +48,27 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>
#include "elf.h"
#define VER "1.06" #define VER "1.06"
#define ARGV argv[arg] #define ARGV argv[arg]
#define VALUE (ARGV+2) #define VALUE (ARGV+2)
#define NUMBER strtoul(VALUE, NULL, 0) #define NUMBER strtoul(VALUE, NULL, 0)
typedef struct typedef struct
{ {
uint32_t start_code; // B instruction uint32_t start_code; // B instruction
uint8_t logo[0xA0-0x04]; // logo data uint8_t logo[0xA0-0x04]; // logo data
uint8_t title[0xC]; // game title name uint8_t title[0xC]; // game title name
uint32_t game_code; // uint32_t game_code; //
uint16_t maker_code; // uint16_t maker_code; //
uint8_t fixed; // 0x96 uint8_t fixed; // 0x96
uint8_t unit_code; // 0x00 uint8_t unit_code; // 0x00
uint8_t device_type; // 0x00 uint8_t device_type; // 0x00
uint8_t unused[7]; // uint8_t unused[7]; //
uint8_t game_version; // 0x00 uint8_t game_version; // 0x00
uint8_t complement; // 800000A0..800000BC uint8_t complement; // 800000A0..800000BC
uint16_t checksum; // 0x0000 uint16_t checksum; // 0x0000
} Header; } Header;
@ -77,55 +78,55 @@ unsigned short checksum_without_header = 0;
const Header good_header = const Header good_header =
{ {
// start_code // start_code
0xEA00002E, 0xEA00002E,
// logo // logo
{ 0x24,0xFF,0xAE,0x51,0x69,0x9A,0xA2,0x21,0x3D,0x84,0x82,0x0A,0x84,0xE4,0x09,0xAD, { 0x24,0xFF,0xAE,0x51,0x69,0x9A,0xA2,0x21,0x3D,0x84,0x82,0x0A,0x84,0xE4,0x09,0xAD,
0x11,0x24,0x8B,0x98,0xC0,0x81,0x7F,0x21,0xA3,0x52,0xBE,0x19,0x93,0x09,0xCE,0x20, 0x11,0x24,0x8B,0x98,0xC0,0x81,0x7F,0x21,0xA3,0x52,0xBE,0x19,0x93,0x09,0xCE,0x20,
0x10,0x46,0x4A,0x4A,0xF8,0x27,0x31,0xEC,0x58,0xC7,0xE8,0x33,0x82,0xE3,0xCE,0xBF, 0x10,0x46,0x4A,0x4A,0xF8,0x27,0x31,0xEC,0x58,0xC7,0xE8,0x33,0x82,0xE3,0xCE,0xBF,
0x85,0xF4,0xDF,0x94,0xCE,0x4B,0x09,0xC1,0x94,0x56,0x8A,0xC0,0x13,0x72,0xA7,0xFC, 0x85,0xF4,0xDF,0x94,0xCE,0x4B,0x09,0xC1,0x94,0x56,0x8A,0xC0,0x13,0x72,0xA7,0xFC,
0x9F,0x84,0x4D,0x73,0xA3,0xCA,0x9A,0x61,0x58,0x97,0xA3,0x27,0xFC,0x03,0x98,0x76, 0x9F,0x84,0x4D,0x73,0xA3,0xCA,0x9A,0x61,0x58,0x97,0xA3,0x27,0xFC,0x03,0x98,0x76,
0x23,0x1D,0xC7,0x61,0x03,0x04,0xAE,0x56,0xBF,0x38,0x84,0x00,0x40,0xA7,0x0E,0xFD, 0x23,0x1D,0xC7,0x61,0x03,0x04,0xAE,0x56,0xBF,0x38,0x84,0x00,0x40,0xA7,0x0E,0xFD,
0xFF,0x52,0xFE,0x03,0x6F,0x95,0x30,0xF1,0x97,0xFB,0xC0,0x85,0x60,0xD6,0x80,0x25, 0xFF,0x52,0xFE,0x03,0x6F,0x95,0x30,0xF1,0x97,0xFB,0xC0,0x85,0x60,0xD6,0x80,0x25,
0xA9,0x63,0xBE,0x03,0x01,0x4E,0x38,0xE2,0xF9,0xA2,0x34,0xFF,0xBB,0x3E,0x03,0x44, 0xA9,0x63,0xBE,0x03,0x01,0x4E,0x38,0xE2,0xF9,0xA2,0x34,0xFF,0xBB,0x3E,0x03,0x44,
0x78,0x00,0x90,0xCB,0x88,0x11,0x3A,0x94,0x65,0xC0,0x7C,0x63,0x87,0xF0,0x3C,0xAF, 0x78,0x00,0x90,0xCB,0x88,0x11,0x3A,0x94,0x65,0xC0,0x7C,0x63,0x87,0xF0,0x3C,0xAF,
0xD6,0x25,0xE4,0x8B,0x38,0x0A,0xAC,0x72,0x21,0xD4,0xF8,0x07 } , 0xD6,0x25,0xE4,0x8B,0x38,0x0A,0xAC,0x72,0x21,0xD4,0xF8,0x07 } ,
// title // title
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
// game code // game code
0x00000000, 0x00000000,
// maker code // maker code
0x3130, 0x3130,
// fixed // fixed
0x96, 0x96,
// unit_code // unit_code
0x00, 0x00,
// device type // device type
0x00, 0x00,
// unused // unused
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
// game version // game version
0x00, 0x00,
// complement // complement
0x00, 0x00,
// checksum // checksum
0x0000 0x0000
}; };
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
char HeaderComplement() char HeaderComplement()
/*--------------------------------------------------------------------------------- /*---------------------------------------------------------------------------------
Calculate Header complement check Calculate Header complement check
---------------------------------------------------------------------------------*/ ---------------------------------------------------------------------------------*/
{ {
int n; int n;
char c = 0; char c = 0;
char *p = (char *)&header + 0xA0; char *p = (char *)&header + 0xA0;
for (n=0; n<0xBD-0xA0; n++) for (n=0; n<0xBD-0xA0; n++)
{ {
c += *p++; c += *p++;
} }
return -(0x19+c); return -(0x19+c);
} }
@ -133,157 +134,176 @@ char HeaderComplement()
int main(int argc, char *argv[]) int main(int argc, char *argv[])
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
{ {
int arg; int arg;
char *argfile = 0; char *argfile = 0;
FILE *infile; FILE *infile;
int silent = 0; int silent = 0;
int size,bit; int size,bit;
// show syntax // show syntax
if (argc <= 1) if (argc <= 1)
{ {
printf("GBA ROM fixer v"VER" by Dark Fader / BlackThunder / WinterMute / Diegoisawesome \n"); printf("GBA ROM fixer v"VER" by Dark Fader / BlackThunder / WinterMute / Diegoisawesome \n");
printf("Syntax: gbafix <rom.gba> [-p] [-t[title]] [-c<game_code>] [-m<maker_code>] [-r<version>] [-d<debug>] [--silent]\n"); printf("Syntax: gbafix <rom.gba> [-p] [-t[title]] [-c<game_code>] [-m<maker_code>] [-r<version>] [-d<debug>] [--silent]\n");
printf("\n"); printf("\n");
printf("parameters:\n"); printf("parameters:\n");
printf(" -p Pad to next exact power of 2. No minimum size!\n"); printf(" -p Pad to next exact power of 2. No minimum size!\n");
printf(" -t[<title>] Patch title. Stripped filename if none given.\n"); printf(" -t[<title>] Patch title. Stripped filename if none given.\n");
printf(" -c<game_code> Patch game code (four characters)\n"); printf(" -c<game_code> Patch game code (four characters)\n");
printf(" -m<maker_code> Patch maker code (two characters)\n"); printf(" -m<maker_code> Patch maker code (two characters)\n");
printf(" -r<version> Patch game version (number)\n"); printf(" -r<version> Patch game version (number)\n");
printf(" -d<debug> Enable debugging handler and set debug entry point (0 or 1)\n"); printf(" -d<debug> Enable debugging handler and set debug entry point (0 or 1)\n");
printf(" --silent Silence non-error output\n"); printf(" --silent Silence non-error output\n");
return -1; return -1;
} }
// get filename // get filename
for (arg=1; arg<argc; arg++) for (arg=1; arg<argc; arg++)
{ {
if (ARGV[0] != '-') { argfile=ARGV; } if (ARGV[0] != '-') { argfile=ARGV; }
if (strncmp("--silent", &ARGV[0], 7) == 0) { silent = 1; } if (strncmp("--silent", &ARGV[0], 7) == 0) { silent = 1; }
} }
// check filename // check filename
if (!argfile) if (!argfile)
{ {
fprintf(stderr, "Filename needed!\n"); fprintf(stderr, "Filename needed!\n");
return -1; return -1;
} }
// read file // read file
infile = fopen(argfile, "r+b"); infile = fopen(argfile, "r+b");
if (!infile) { fprintf(stderr, "Error opening input file!\n"); return -1; } if (!infile) { fprintf(stderr, "Error opening input file!\n"); return -1; }
fseek(infile, 0, SEEK_SET); fseek(infile, 0, SEEK_SET);
fread(&header, sizeof(header), 1, infile); fread(&header, sizeof(header), 1, infile);
// fix some data // elf check
memcpy(header.logo, good_header.logo, sizeof(header.logo)); uint32_t sh_offset = 0;
memcpy(&header.fixed, &good_header.fixed, sizeof(header.fixed)); if (memcmp(&header, ELFMAG, 4) == 0) {
memcpy(&header.device_type, &good_header.device_type, sizeof(header.device_type)); Elf32_Ehdr *elfHeader = (Elf32_Ehdr *)&header;
fseek(infile, elfHeader->e_shoff, SEEK_SET);
int i;
for (i = 0; i < elfHeader->e_shnum; i++) {
Elf32_Shdr secHeader;
fread(&secHeader, sizeof(Elf32_Shdr), 1, infile);
if (secHeader.sh_type == SHT_PROGBITS && secHeader.sh_addr == elfHeader->e_entry) {
fseek(infile, secHeader.sh_offset, SEEK_SET);
sh_offset = secHeader.sh_offset;
break;
}
}
if (i == elfHeader->e_shnum) { fprintf(stderr, "Error finding entry point!\n"); return 1; }
fread(&header, sizeof(header), 1, infile);
}
// parse command line // fix some data
for (arg=1; arg<argc; arg++) memcpy(header.logo, good_header.logo, sizeof(header.logo));
{ memcpy(&header.fixed, &good_header.fixed, sizeof(header.fixed));
if ((ARGV[0] == '-')) memcpy(&header.device_type, &good_header.device_type, sizeof(header.device_type));
{
switch (ARGV[1])
{
case 'p': // pad
{
fseek(infile, 0, SEEK_END);
size = ftell(infile);
for (bit=31; bit>=0; bit--) if (size & (1<<bit)) break;
if (size != (1<<bit))
{
int todo = (1<<(bit+1)) - size;
while (todo--) fputc(0xFF, infile);
}
fseek(infile, 0, SEEK_SET);
break;
}
case 't': // title // parse command line
{ for (arg=1; arg<argc; arg++)
char title[256]; {
memset(title, 0, sizeof(title)); if ((ARGV[0] == '-'))
if (VALUE[0]) {
{ switch (ARGV[1])
strncpy(title, VALUE, sizeof(header.title)); {
} case 'p': // pad
else {
{ fseek(infile, 0, SEEK_END);
// use filename size = ftell(infile);
char s[256], *begin=s, *t; strcpy(s, argfile); for (bit=31; bit>=0; bit--) if (size & (1<<bit)) break;
t = strrchr(s, '\\'); if (t) begin = t+1; if (size != (1<<bit))
t = strrchr(s, '/'); if (t) begin = t+1; {
t = strrchr(s, '.'); if (t) *t = 0; int todo = (1<<(bit+1)) - size;
strncpy(title, begin, sizeof(header.title)); while (todo--) fputc(0xFF, infile);
if (!silent) printf("%s\n",begin); }
} fseek(infile, 0, SEEK_SET);
memcpy(header.title, title, sizeof(header.title)); // copy break;
break; }
}
case 'c': // game code case 't': // title
{ {
//if (!VALUE[0]) { fprintf(stderr, "Need value for %s\n", ARGV); break; } char title[256];
//header.game_code = NUMBER; memset(title, 0, sizeof(title));
header.game_code = VALUE[0] | VALUE[1]<<8 | VALUE[2]<<16 | VALUE[3]<<24; if (VALUE[0])
break; {
} strncpy(title, VALUE, sizeof(header.title));
}
else
{
// use filename
char s[256], *begin=s, *t; strcpy(s, argfile);
t = strrchr(s, '\\'); if (t) begin = t+1;
t = strrchr(s, '/'); if (t) begin = t+1;
t = strrchr(s, '.'); if (t) *t = 0;
strncpy(title, begin, sizeof(header.title));
if (!silent) printf("%s\n",begin);
}
memcpy(header.title, title, sizeof(header.title)); // copy
break;
}
case 'm': // maker code case 'c': // game code
{ {
//if (!VALUE[0]) { fprintf(stderr, "Need value for %s\n", ARGV); break; } //if (!VALUE[0]) { fprintf(stderr, "Need value for %s\n", ARGV); break; }
//header.maker_code = (unsigned short)NUMBER; //header.game_code = NUMBER;
header.maker_code = VALUE[0] | VALUE[1]<<8; header.game_code = VALUE[0] | VALUE[1]<<8 | VALUE[2]<<16 | VALUE[3]<<24;
break; break;
} }
case 'v': // ignored, compatability with other gbafix case 'm': // maker code
{ {
break; //if (!VALUE[0]) { fprintf(stderr, "Need value for %s\n", ARGV); break; }
} //header.maker_code = (unsigned short)NUMBER;
header.maker_code = VALUE[0] | VALUE[1]<<8;
break;
}
case 'r': // version case 'v': // ignored, compatability with other gbafix
{ {
if (!VALUE[0]) { fprintf(stderr, "Need value for %s\n", ARGV); break; } break;
header.game_version = (unsigned char)NUMBER; }
break;
}
case 'd': // debug case 'r': // version
{ {
if (!VALUE[0]) { fprintf(stderr, "Need value for %s\n", ARGV); break; } if (!VALUE[0]) { fprintf(stderr, "Need value for %s\n", ARGV); break; }
header.logo[0x9C-0x04] = 0xA5; // debug enable header.game_version = (unsigned char)NUMBER;
header.device_type = (unsigned char)((NUMBER & 1) << 7); // debug handler entry point break;
break; }
}
case '-': // long arguments
{
if (strncmp("silent", &ARGV[2], 6) == 0) { continue; }
break;
}
default:
{
printf("Invalid option: %s\n", ARGV);
}
}
}
}
// update complement check & total checksum case 'd': // debug
header.complement = 0; {
header.checksum = 0; // must be 0 if (!VALUE[0]) { fprintf(stderr, "Need value for %s\n", ARGV); break; }
header.complement = HeaderComplement(); header.logo[0x9C-0x04] = 0xA5; // debug enable
//header.checksum = checksum_without_header + HeaderChecksum(); header.device_type = (unsigned char)((NUMBER & 1) << 7); // debug handler entry point
break;
}
case '-': // long arguments
{
if (strncmp("silent", &ARGV[2], 6) == 0) { continue; }
break;
}
default:
{
printf("Invalid option: %s\n", ARGV);
}
}
}
}
fseek(infile, 0, SEEK_SET); // update complement check & total checksum
fwrite(&header, sizeof(header), 1, infile); header.complement = 0;
fclose(infile); header.checksum = 0; // must be 0
header.complement = HeaderComplement();
//header.checksum = checksum_without_header + HeaderChecksum();
if (!silent) printf("ROM fixed!\n"); fseek(infile, sh_offset, SEEK_SET);
fwrite(&header, sizeof(header), 1, infile);
fclose(infile);
return 0; if (!silent) printf("ROM fixed!\n");
return 0;
} }