From 00df1bf797ec763593b392a98d58ea3576230193 Mon Sep 17 00:00:00 2001 From: scnorton Date: Sun, 21 Jan 2018 12:51:52 -0500 Subject: Use standard flags to link libc, libgcc --- Makefile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 6d5d120..e568dcf 100755 --- a/Makefile +++ b/Makefile @@ -11,8 +11,7 @@ LD := $(DEVKITARM)/bin/arm-none-eabi-ld OBJCOPY := $(DEVKITARM)/bin/arm-none-eabi-objcopy -LIBGCC := tools/agbcc/lib/libgcc.a -LIBC := tools/agbcc/lib/libc.a +LIB := -L tools/agbcc/lib -lc -lgcc MD5 := md5sum -c @@ -93,7 +92,7 @@ ld_script.ld: ld_script.txt sym_ewram.ld sym_ewram2.ld sym_iwram.ld sed -f ld_script.sed ld_script.txt >ld_script.ld pmd_red.elf: ld_script.ld $(OBJS) $(LIBC) - $(LD) -T ld_script.ld -Map pmd_red.map -o $@ $(OBJS) $(LIBC) $(LIBGCC) + $(LD) -T ld_script.ld -Map pmd_red.map -o $@ $(OBJS) $(LIB) pmd_red.gba: pmd_red.elf $(OBJCOPY) -O binary --gap-fill 0xFF --pad-to 0xA000000 $< $@ -- cgit v1.2.3 From 2695f8d39a2ecef149ca864934ed0fd49bbd7ff6 Mon Sep 17 00:00:00 2001 From: scnorton Date: Sun, 21 Jan 2018 14:57:28 -0500 Subject: Include in global.h and add dependency scanning --- Makefile | 14 +++++++++++--- include/global.h | 14 ++------------ 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index e568dcf..c91a4e2 100755 --- a/Makefile +++ b/Makefile @@ -41,6 +41,14 @@ ASM_OBJS := $(ASM_SRCS:%.s=%.o) DATA_ASM_SRCS := $(wildcard data/*.s) DATA_ASM_OBJS := $(DATA_ASM_SRCS:%.s=%.o) +# Disable dependency scanning when NODEP is used for quick building +ifeq ($(NODEP),) + src/%.o: C_DEP = $(shell $(SCANINC) -I include src/$(*F).c) + asm/%.o: ASM_DEP = $(shell $(SCANINC) asm/$(*F).s) + data/%.o: ASM_DEP = $(shell $(SCANINC) data/$(*F).s) +endif + + OBJS := $(C_OBJS) $(ASM_OBJS) $(DATA_ASM_OBJS) all: pmd_red.gba @@ -67,16 +75,16 @@ src/agb_flash.o: CFLAGS := -O -mthumb-interwork src/agb_flash_1m.o: CFLAGS := -O -mthumb-interwork src/agb_flash_mx.o: CFLAGS := -O -mthumb-interwork -$(C_OBJS): %.o : %.c +$(C_OBJS): %.o : %.c $$(C_DEP) @$(CPP) $(CPPFLAGS) $< -o $*.i @$(CC1) $(CFLAGS) $*.i -o $*.s @printf ".text\n\t.align\t2, 0\n" >> $*.s $(AS) $(ASFLAGS) -o $@ $*.s -$(ASM_OBJS): %.o: %.s +$(ASM_OBJS): %.o: %.s $$(ASM_DEP) $(AS) $(ASFLAGS) -o $@ $< -$(DATA_ASM_OBJS): %.o: %.s +$(DATA_ASM_OBJS): %.o: %.s $$(ASM_DEP) $(AS) $(ASFLAGS) -o $@ $< sym_ewram.ld: sym_ewram.txt diff --git a/include/global.h b/include/global.h index 75592d5..66c1b6d 100644 --- a/include/global.h +++ b/include/global.h @@ -1,10 +1,11 @@ #ifndef GUARD_GLOBAL_H #define GUARD_GLOBAL_H +#include #include "gba/gba.h" // IDE support -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__CYGWIN__) #define _(x) x #define __(x) x #define INCBIN_U8 {0} @@ -13,9 +14,6 @@ #define INCBIN_S8 {0} #define INCBIN_S16 {0} #define INCBIN_S32 {0} -void * memcpy (void *, const void *, size_t); -void * memset (void *, int, size_t); -int strcmp (const char *, const char *); #endif // Prevent cross-jump optimization. @@ -26,14 +24,6 @@ int strcmp (const char *, const char *); #define asm_unified(x) asm(".syntax unified\n" x "\n.syntax divided\n") -#define nonmatching(fndec, x) {\ -__attribute__((naked))\ -fndec\ -{\ - asm_unified(x);\ -}\ -} - #define ARRAY_COUNT(array) (sizeof(array) / sizeof((array)[0])) #endif // GUARD_GLOBAL_H -- cgit v1.2.3 From 91c6c244007944ffcd5da2e42b1a5221b0ce2074 Mon Sep 17 00:00:00 2001 From: scnorton Date: Sun, 21 Jan 2018 16:51:04 -0500 Subject: sub_8006218 --- asm/text.s | 134 ------------------------------------------------- include/code_800558C.h | 6 +++ include/file_system.h | 34 +++++++++++++ ld_script.txt | 1 + src/file_system.c | 32 ++---------- src/text.c | 75 +++++++++++++++++++++++++++ 6 files changed, 120 insertions(+), 162 deletions(-) create mode 100644 include/code_800558C.h create mode 100644 include/file_system.h create mode 100644 src/text.c diff --git a/asm/text.s b/asm/text.s index a8e6dc5..f1235bb 100644 --- a/asm/text.s +++ b/asm/text.s @@ -5,140 +5,6 @@ .text - thumb_func_start sub_8006218 -sub_8006218: - push {r4-r7,lr} - mov r7, r10 - mov r6, r9 - mov r5, r8 - push {r5-r7} - ldr r1, _080062F4 - movs r0, 0 - str r0, [r1] - ldr r0, _080062F8 - ldr r5, _080062FC - adds r1, r5, 0 - bl OpenFileAndGetFileDataPtr - ldr r4, _08006300 - str r0, [r4] - ldr r0, _08006304 - adds r1, r5, 0 - bl OpenFileAndGetFileDataPtr - str r0, [r4, 0x4] - ldr r2, _08006308 - ldr r1, [r4] - ldr r1, [r1, 0x4] - str r1, [r2] - ldr r0, [r0, 0x4] - str r0, [r2, 0x4] - ldr r1, _0800630C - movs r0, 0xB - str r0, [r1] - movs r0, 0xC - str r0, [r1, 0x4] - ldr r0, _08006310 - movs r4, 0 - movs r3, 0 - adds r2, r0, 0 - adds r2, 0x46 - adds r0, 0x4 - movs r1, 0x3 -_08006264: - strh r3, [r0] - strh r3, [r0, 0x4] - strb r4, [r2] - adds r2, 0x48 - adds r0, 0x48 - subs r1, 0x1 - cmp r1, 0 - bge _08006264 - ldr r1, _08006314 - movs r0, 0 - strh r0, [r1] - movs r3, 0 - ldr r0, _08006318 - mov r9, r0 - ldr r1, _0800631C - mov r10, r1 - ldr r7, _08006320 - ldr r2, _08006324 - mov r8, r2 - movs r0, 0x80 - lsls r0, 4 - adds r6, r7, r0 - ldr r4, _08006328 - movs r5, 0 - mov r12, r6 -_08006296: - lsls r0, r3, 6 - adds r2, r0, r7 - mov r1, r8 - strh r1, [r2] - adds r1, r0, r6 - strh r4, [r1] - adds r3, 0x1 - add r0, r12 - adds r0, 0x2 - adds r2, 0x2 - movs r1, 0x1E -_080062AC: - strh r5, [r2] - strh r4, [r0] - adds r0, 0x2 - adds r2, 0x2 - subs r1, 0x1 - cmp r1, 0 - bge _080062AC - cmp r3, 0x13 - ble _08006296 - movs r1, 0 - movs r0, 0x1 - mov r2, r9 - strb r0, [r2] - ldr r0, _0800632C - mov r2, r10 - str r0, [r2] - ldr r0, _08006330 - str r1, [r0] - ldr r2, _08006334 - strb r1, [r2] - movs r0, 0x1 - ldr r1, _08006338 - str r0, [r1] - movs r0, 0x14 - ldr r2, _0800633C - str r0, [r2] - movs r0, 0 - bl xxx_update_some_bg_tiles - pop {r3-r5} - mov r8, r3 - mov r9, r4 - mov r10, r5 - pop {r4-r7} - pop {r0} - bx r0 - .align 2, 0 -_080062F4: .4byte gUnknown_20274AC -_080062F8: .4byte gUnknown_80B87B4 -_080062FC: .4byte gUnknown_8300500 -_08006300: .4byte gUnknown_202AFB4 -_08006304: .4byte gUnknown_80B87BC -_08006308: .4byte gUnknown_2027490 -_0800630C: .4byte gUnknown_202B028 -_08006310: .4byte gUnknown_2027370 -_08006314: .4byte gUnknown_2027498 -_08006318: .4byte gUnknown_202B034 -_0800631C: .4byte gUnknown_202B030 -_08006320: .4byte gUnknown_202B038 -_08006324: .4byte 0x0000f279 -_08006328: .4byte 0x0000f27a -_0800632C: .4byte 0x88888888 -_08006330: .4byte gUnknown_203B078 -_08006334: .4byte gUnknown_20274A5 -_08006338: .4byte gUnknown_202B020 -_0800633C: .4byte gUnknown_202B024 - thumb_func_end sub_8006218 - thumb_func_start xxx_update_some_bg_tiles xxx_update_some_bg_tiles: push {r4,r5,lr} diff --git a/include/code_800558C.h b/include/code_800558C.h new file mode 100644 index 0000000..be974cc --- /dev/null +++ b/include/code_800558C.h @@ -0,0 +1,6 @@ +#ifndef GUARD_code_800558C_H +#define GUARD_code_800558C_H + +extern u32 gUnknown_203B078; + +#endif //GUARD_code_800558C_H diff --git a/include/file_system.h b/include/file_system.h new file mode 100644 index 0000000..360f7ac --- /dev/null +++ b/include/file_system.h @@ -0,0 +1,34 @@ +#ifndef GUARD_FILE_SYSTEM_H +#define GUARD_FILE_SYSTEM_H + +struct File +{ + char *name; + u8 *data; +}; + +struct OpenedFile +{ + struct File *file; + u8 *data; +}; + +struct FileArchive +{ + char magic[8]; + s32 count; + struct File *entries; +}; + +struct SiroArchive +{ + u32 magic; + u8 *data; +}; + +struct OpenedFile *OpenFile(const char *filename, const struct FileArchive *arc); +u8 *GetFileDataPtr(struct OpenedFile *openedFile, int unused); +struct OpenedFile *OpenFileAndGetFileDataPtr(const char *filename, const struct FileArchive *arc); +struct OpenedFile *Call_OpenFileAndGetFileDataPtr(const char *filename, const struct FileArchive *arc); + +#endif //GUARD_FILE_SYSTEM_H diff --git a/ld_script.txt b/ld_script.txt index e3a6af7..f3ecc12 100755 --- a/ld_script.txt +++ b/ld_script.txt @@ -58,6 +58,7 @@ SECTIONS { asm/sprite.o(.text); asm/code_800558C.o(.text); src/random.o(.text); + src/text.o(.text); asm/text.o(.text); asm/code_8009804.o(.text); src/file_system.o(.text); diff --git a/src/file_system.c b/src/file_system.c index 296478d..0d8de10 100644 --- a/src/file_system.c +++ b/src/file_system.c @@ -1,29 +1,5 @@ #include "global.h" - -struct File -{ - char *name; - u8 *data; -}; - -struct OpenedFile -{ - struct File *file; - u8 *data; -}; - -struct FileArchive -{ - char magic[8]; - s32 count; - struct File *entries; -}; - -struct SiroArchive -{ - u32 magic; - u8 *data; -}; +#include "file_system.h" extern struct OpenedFile gUnknown_202D2A8[]; @@ -56,7 +32,7 @@ u32 sub_800A8F8(u32 value) return oldValue; } -struct OpenedFile *OpenFile(char *filename, struct FileArchive *arc) +struct OpenedFile *OpenFile(const char *filename, const struct FileArchive *arc) { char buffer[0x12C]; s32 left, right; @@ -138,7 +114,7 @@ u8 *GetFileDataPtr(struct OpenedFile *openedFile, int unused) return GetSiroPtr(openedFile); } -struct OpenedFile *OpenFileAndGetFileDataPtr(char *filename, struct FileArchive *arc) +struct OpenedFile *OpenFileAndGetFileDataPtr(const char *filename, const struct FileArchive *arc) { struct OpenedFile *openedFile = OpenFile(filename, arc); if (openedFile) @@ -146,7 +122,7 @@ struct OpenedFile *OpenFileAndGetFileDataPtr(char *filename, struct FileArchive return openedFile; } -struct OpenedFile *Call_OpenFileAndGetFileDataPtr(char *filename, struct FileArchive *arc) +struct OpenedFile *Call_OpenFileAndGetFileDataPtr(const char *filename, const struct FileArchive *arc) { return OpenFileAndGetFileDataPtr(filename, arc); } diff --git a/src/text.c b/src/text.c new file mode 100644 index 0000000..929d8b1 --- /dev/null +++ b/src/text.c @@ -0,0 +1,75 @@ +// ------------------------ +// TEXT.C +// Decompiled by PikalaxALT +// ------------------------ + +#include "global.h" +#include "file_system.h" +#include "code_800558C.h" + +struct UnkTextStruct1 { + u8 fill00[4]; + u16 unk04; + u8 fill06[2]; + u16 unk08; + u8 fill04[0x3c]; + u8 unk46; +}; + +EWRAM_DATA struct UnkTextStruct1 gUnknown_2027370[4]; +EWRAM_DATA u8 *gUnknown_2027490[2]; +EWRAM_DATA u16 gUnknown_2027498; +EWRAM_DATA u8 gUnknown_20274A5; +EWRAM_DATA u32 gUnknown_20274AC; +EWRAM_DATA struct OpenedFile *gUnknown_202AFB4[2]; +EWRAM_DATA u32 gUnknown_202B020; +EWRAM_DATA u32 gUnknown_202B024; +EWRAM_DATA u32 gUnknown_202B028[2]; +EWRAM_DATA u32 gUnknown_202B030; +EWRAM_DATA u8 gUnknown_202B034; +EWRAM_DATA u16 gUnknown_202B038[2][32][32]; + +void xxx_update_some_bg_tiles(int a0); + +extern const char gUnknown_80B87B4[]; +extern const char gUnknown_80B87BC[]; +extern const struct FileArchive gUnknown_8300500; + +void sub_8006218(void) +{ + int i; + int j; + int k; + + gUnknown_20274AC = 0; + gUnknown_202AFB4[0] = OpenFileAndGetFileDataPtr(gUnknown_80B87B4, &gUnknown_8300500); + gUnknown_202AFB4[1] = OpenFileAndGetFileDataPtr(gUnknown_80B87BC, &gUnknown_8300500); + gUnknown_2027490[0] = gUnknown_202AFB4[0]->data; + gUnknown_2027490[1] = gUnknown_202AFB4[1]->data; + gUnknown_202B028[0] = 11; + gUnknown_202B028[1] = 12; + for (k = 0; k < 4; k++) + { + gUnknown_2027370[k].unk04 = 0; + gUnknown_2027370[k].unk08 = 0; + gUnknown_2027370[k].unk46 = 0; + } + gUnknown_2027498 = 0; + for (i = 0; i < 20; i++) + { + gUnknown_202B038[0][i][0] = 0xf279; + gUnknown_202B038[1][i][0] = 0xf27a; + for (j = 1; j < 32; j++) + { + gUnknown_202B038[0][i][j] = 0; + gUnknown_202B038[1][i][j] = 0xf27a; + } + } + gUnknown_202B034 = 1; + gUnknown_202B030 = 0x88888888; + gUnknown_203B078 = 0; + gUnknown_20274A5 = 0; + gUnknown_202B020 = 1; + gUnknown_202B024 = 20; + xxx_update_some_bg_tiles(0); +} -- cgit v1.2.3 From 8bff04787167a733caa74c0b22dcd332b391f54d Mon Sep 17 00:00:00 2001 From: scnorton Date: Sun, 21 Jan 2018 17:12:02 -0500 Subject: through sub_80063D8 --- asm/text.s | 123 ------------------------------------------------- include/code_800B540.h | 6 +++ src/text.c | 72 ++++++++++++++++++++++++++++- 3 files changed, 77 insertions(+), 124 deletions(-) create mode 100644 include/code_800B540.h diff --git a/asm/text.s b/asm/text.s index f1235bb..d914098 100644 --- a/asm/text.s +++ b/asm/text.s @@ -5,129 +5,6 @@ .text - thumb_func_start xxx_update_some_bg_tiles -xxx_update_some_bg_tiles: - push {r4,r5,lr} - adds r1, r0, 0 - ldr r0, _08006360 - ldr r5, [r0] - ldr r4, _08006364 - str r1, [r0] - cmp r1, 0 - beq _08006354 - cmp r1, 0x2 - bne _0800636C -_08006354: - movs r0, 0x2 - bl sub_800CDA8 - ldr r2, _08006368 - b _08006374 - .align 2, 0 -_08006360: .4byte gUnknown_20274B0 -_08006364: .4byte 0x06004f40 -_08006368: .4byte gUnknown_80B87C4 -_0800636C: - movs r0, 0x1 - bl sub_800CDA8 - ldr r2, _080063A4 -_08006374: - ldr r1, _080063A8 - ldr r0, _080063AC - str r0, [r1] - ldm r2!, {r0} - stm r4!, {r0} - ldm r2!, {r0} - stm r4!, {r0} - ldm r2!, {r0} - stm r4!, {r0} - ldm r2!, {r0} - stm r4!, {r0} - ldm r2!, {r0} - stm r4!, {r0} - ldm r2!, {r0} - stm r4!, {r0} - ldm r2!, {r0} - stm r4!, {r0} - ldr r0, [r2] - str r0, [r4] - adds r0, r5, 0 - pop {r4,r5} - pop {r1} - bx r1 - .align 2, 0 -_080063A4: .4byte gUnknown_80B87E4 -_080063A8: .4byte gUnknown_202B030 -_080063AC: .4byte 0x88888888 - thumb_func_end xxx_update_some_bg_tiles - - thumb_func_start sub_80063B0 -sub_80063B0: - ldr r0, _080063B8 - ldr r0, [r0] - bx lr - .align 2, 0 -_080063B8: .4byte gUnknown_20274B0 - thumb_func_end sub_80063B0 - - thumb_func_start sub_80063BC -sub_80063BC: - ldr r1, _080063C8 - ldrb r2, [r1] - strb r0, [r1] - adds r0, r2, 0 - bx lr - .align 2, 0 -_080063C8: .4byte gUnknown_202B034 - thumb_func_end sub_80063BC - - thumb_func_start sub_80063CC -sub_80063CC: - ldr r1, _080063D4 - str r0, [r1] - bx lr - .align 2, 0 -_080063D4: .4byte gUnknown_20274AC - thumb_func_end sub_80063CC - - thumb_func_start sub_80063D8 -sub_80063D8: - push {lr} - adds r1, r0, 0 - cmp r1, 0 - bne _080063F0 - ldr r0, _080063E8 - ldr r0, [r0] - ldr r2, _080063EC - b _08006410 - .align 2, 0 -_080063E8: .4byte gUnknown_20274B0 -_080063EC: .4byte 0x88888888 -_080063F0: - movs r0, 0xF - ands r0, r1 - lsls r2, r0, 4 - orrs r2, r0 - lsls r1, r0, 8 - orrs r2, r1 - lsls r1, r0, 12 - orrs r2, r1 - lsls r1, r0, 16 - orrs r2, r1 - lsls r1, r0, 20 - orrs r2, r1 - lsls r1, r0, 24 - orrs r2, r1 - lsls r0, 28 - orrs r2, r0 -_08006410: - ldr r0, _08006418 - str r2, [r0] - pop {r0} - bx r0 - .align 2, 0 -_08006418: .4byte gUnknown_202B030 - thumb_func_end sub_80063D8 - thumb_func_start sub_800641C sub_800641C: push {lr} diff --git a/include/code_800B540.h b/include/code_800B540.h new file mode 100644 index 0000000..050998e --- /dev/null +++ b/include/code_800B540.h @@ -0,0 +1,6 @@ +#ifndef GUARD_code_800B540_H +#define GUARD_code_800B540_H + +void sub_800CDA8(int a0); + +#endif //GUARD_code_800B540_H diff --git a/src/text.c b/src/text.c index 929d8b1..3d60416 100644 --- a/src/text.c +++ b/src/text.c @@ -6,6 +6,7 @@ #include "global.h" #include "file_system.h" #include "code_800558C.h" +#include "code_800B540.h" struct UnkTextStruct1 { u8 fill00[4]; @@ -21,6 +22,7 @@ EWRAM_DATA u8 *gUnknown_2027490[2]; EWRAM_DATA u16 gUnknown_2027498; EWRAM_DATA u8 gUnknown_20274A5; EWRAM_DATA u32 gUnknown_20274AC; +EWRAM_DATA vu32 gUnknown_20274B0; EWRAM_DATA struct OpenedFile *gUnknown_202AFB4[2]; EWRAM_DATA u32 gUnknown_202B020; EWRAM_DATA u32 gUnknown_202B024; @@ -29,11 +31,13 @@ EWRAM_DATA u32 gUnknown_202B030; EWRAM_DATA u8 gUnknown_202B034; EWRAM_DATA u16 gUnknown_202B038[2][32][32]; -void xxx_update_some_bg_tiles(int a0); +u32 xxx_update_some_bg_tiles(u32 a0); extern const char gUnknown_80B87B4[]; extern const char gUnknown_80B87BC[]; extern const struct FileArchive gUnknown_8300500; +extern const u32 gUnknown_80B87C4[8]; +extern const u32 gUnknown_80B87E4[8]; void sub_8006218(void) { @@ -73,3 +77,69 @@ void sub_8006218(void) gUnknown_202B024 = 20; xxx_update_some_bg_tiles(0); } + +u32 xxx_update_some_bg_tiles(u32 a0) +{ + u32 r5 = gUnknown_20274B0; + u32 *r4 = (u32 *)(VRAM + 0x4f40); + const u32 *r2; + gUnknown_20274B0 = a0; + if (a0 == 0 || a0 == 2) + { + sub_800CDA8(2); + r2 = gUnknown_80B87C4; + } + else + { + sub_800CDA8(1); + r2 = gUnknown_80B87E4; + } + gUnknown_202B030 = 0x88888888; + *r4++ = *r2++; + *r4++ = *r2++; + *r4++ = *r2++; + *r4++ = *r2++; + *r4++ = *r2++; + *r4++ = *r2++; + *r4++ = *r2++; + *r4++ = *r2++; + return r5; +} + +u32 sub_80063B0(void) +{ + return gUnknown_20274B0; +} + +u8 sub_80063BC(u8 a0) +{ + u8 retval = gUnknown_202B034; + gUnknown_202B034 = a0; + return retval; +} + +void sub_80063CC(u32 a0) +{ + gUnknown_20274AC = a0; +} + +void sub_80063D8(int a0) +{ + u32 retval; + if (a0 == 0) + { + gUnknown_20274B0; + retval = 0x88888888; + } + else + { + retval = (a0 & 0xf) | ((a0 & 0xf) << 4); + retval |= ((a0 & 0xf) << 8); + retval |= ((a0 & 0xf) << 12); + retval |= ((a0 & 0xf) << 16); + retval |= ((a0 & 0xf) << 20); + retval |= ((a0 & 0xf) << 24); + retval |= ((a0 & 0xf) << 28); + } + gUnknown_202B030 = retval; +} -- cgit v1.2.3 From 192ee78bb96bae8dc8316cdd9edf2112ad2d1777 Mon Sep 17 00:00:00 2001 From: scnorton Date: Sun, 21 Jan 2018 17:48:35 -0500 Subject: through sub_8006438 --- asm/text.s | 123 ------------------------------------------------- include/code_800558C.h | 2 +- src/text.c | 64 ++++++++++++++++++++++++- 3 files changed, 63 insertions(+), 126 deletions(-) diff --git a/asm/text.s b/asm/text.s index d914098..98b8797 100644 --- a/asm/text.s +++ b/asm/text.s @@ -5,129 +5,6 @@ .text - thumb_func_start sub_800641C -sub_800641C: - push {lr} - sub sp, 0x4 - lsls r1, 24 - lsrs r1, 24 - lsls r2, 24 - lsrs r2, 24 - movs r3, 0 - str r3, [sp] - mov r3, sp - bl sub_8006438 - add sp, 0x4 - pop {r0} - bx r0 - thumb_func_end sub_800641C - - thumb_func_start sub_8006438 -sub_8006438: - push {r4-r7,lr} - mov r7, r10 - mov r6, r9 - mov r5, r8 - push {r5-r7} - sub sp, 0x1C - adds r4, r0, 0 - mov r8, r3 - lsls r1, 24 - lsrs r1, 24 - mov r10, r1 - lsls r2, 24 - lsrs r2, 24 - movs r0, 0x2 - mov r9, r0 - cmp r4, 0 - bne _0800645C - ldr r4, _080064F0 -_0800645C: - cmp r2, 0 - beq _08006464 - bl sub_8009388 -_08006464: - bl sub_800898C - movs r6, 0 - adds r5, r4, 0 - adds r5, 0xC - ldr r1, _080064F4 - str r1, [sp, 0x18] -_08006472: - ldr r0, [sp, 0x18] - adds r1, r4, 0 - ldm r1!, {r2,r3,r7} - stm r0!, {r2,r3,r7} - ldm r1!, {r2,r3,r7} - stm r0!, {r2,r3,r7} - movs r1, 0 - ldrsh r0, [r5, r1] - cmp r0, 0 - beq _080064C4 - ldr r1, _080064F8 - lsls r0, r6, 2 - adds r0, r1 - ldr r0, [r0] - str r0, [sp] - str r4, [sp, 0x4] - mov r2, r10 - str r2, [sp, 0x8] - mov r3, r9 - str r3, [sp, 0xC] - mov r7, r8 - str r7, [sp, 0x10] - movs r0, 0 - str r0, [sp, 0x14] - ldr r0, _080064FC - movs r1, 0xC0 - lsls r1, 19 - ldr r2, _08006500 - ldr r3, _08006504 - bl sub_8006554 - adds r0, r4, 0 - mov r1, r8 - bl sub_80089AC - movs r0, 0 - ldrsh r1, [r5, r0] - movs r2, 0x4 - ldrsh r0, [r5, r2] - muls r0, r1 - add r9, r0 -_080064C4: - adds r5, 0x18 - adds r4, 0x18 - ldr r3, [sp, 0x18] - adds r3, 0x18 - str r3, [sp, 0x18] - adds r6, 0x1 - cmp r6, 0x3 - ble _08006472 - ldr r2, _08006508 - ldr r0, _0800650C - ldr r1, _08006510 - str r0, [r2] - movs r0, 0x1 - strb r0, [r1] - add sp, 0x1C - pop {r3-r5} - mov r8, r3 - mov r9, r4 - mov r10, r5 - pop {r4-r7} - pop {r0} - bx r0 - .align 2, 0 -_080064F0: .4byte gUnknown_80B857C -_080064F4: .4byte gUnknown_202AFC0 -_080064F8: .4byte gUnknown_80B8804 -_080064FC: .4byte gUnknown_2027370 -_08006500: .4byte gUnknown_20274B4 -_08006504: .4byte gUnknown_202B038 -_08006508: .4byte gUnknown_203B078 -_0800650C: .4byte gUnknown_3000E94 -_08006510: .4byte gUnknown_20274A5 - thumb_func_end sub_8006438 - thumb_func_start nullsub_152 nullsub_152: bx lr diff --git a/include/code_800558C.h b/include/code_800558C.h index be974cc..e1b3432 100644 --- a/include/code_800558C.h +++ b/include/code_800558C.h @@ -1,6 +1,6 @@ #ifndef GUARD_code_800558C_H #define GUARD_code_800558C_H -extern u32 gUnknown_203B078; +extern void *gUnknown_203B078; #endif //GUARD_code_800558C_H diff --git a/src/text.c b/src/text.c index 3d60416..8c6725d 100644 --- a/src/text.c +++ b/src/text.c @@ -17,13 +17,25 @@ struct UnkTextStruct1 { u8 unk46; }; +struct UnkTextStruct2 { + u8 fill00[0x0c]; + s16 unk0c; + u8 fill0e[2]; + s16 unk10; + u8 fill12[0x06]; +}; + +extern char gUnknown_3000E94[]; + EWRAM_DATA struct UnkTextStruct1 gUnknown_2027370[4]; EWRAM_DATA u8 *gUnknown_2027490[2]; EWRAM_DATA u16 gUnknown_2027498; EWRAM_DATA u8 gUnknown_20274A5; EWRAM_DATA u32 gUnknown_20274AC; EWRAM_DATA vu32 gUnknown_20274B0; -EWRAM_DATA struct OpenedFile *gUnknown_202AFB4[2]; +EWRAM_DATA u8 gUnknown_20274B4[0x3b00]; +EWRAM_DATA struct OpenedFile *gUnknown_202AFB4[3]; +EWRAM_DATA struct UnkTextStruct2 gUnknown_202AFC0[4]; EWRAM_DATA u32 gUnknown_202B020; EWRAM_DATA u32 gUnknown_202B024; EWRAM_DATA u32 gUnknown_202B028[2]; @@ -32,12 +44,19 @@ EWRAM_DATA u8 gUnknown_202B034; EWRAM_DATA u16 gUnknown_202B038[2][32][32]; u32 xxx_update_some_bg_tiles(u32 a0); +void sub_8006438(const struct UnkTextStruct2 *a0, u8 a1, u8 a2, u32 *a3); +void sub_8006554(void *a0, void *a1, void *a2, void *a3, u32 a4, const struct UnkTextStruct2 *a5, u8 a6, u32 a7, u32 *a8, u32 a9); +void sub_800898C(void); +void sub_80089AC(const struct UnkTextStruct2 *a0, void *a1); +void sub_8009388(void); +extern const struct UnkTextStruct2 gUnknown_80B857C[4]; extern const char gUnknown_80B87B4[]; extern const char gUnknown_80B87BC[]; extern const struct FileArchive gUnknown_8300500; extern const u32 gUnknown_80B87C4[8]; extern const u32 gUnknown_80B87E4[8]; +extern const u32 gUnknown_80B8804[4]; void sub_8006218(void) { @@ -71,7 +90,7 @@ void sub_8006218(void) } gUnknown_202B034 = 1; gUnknown_202B030 = 0x88888888; - gUnknown_203B078 = 0; + gUnknown_203B078 = NULL; gUnknown_20274A5 = 0; gUnknown_202B020 = 1; gUnknown_202B024 = 20; @@ -143,3 +162,44 @@ void sub_80063D8(int a0) } gUnknown_202B030 = retval; } + +void sub_800641C(void *a0, u8 a1, u8 a2) +{ + u32 r3 = 0; + sub_8006438(a0, a1, a2, &r3); +} + +void sub_8006438(const struct UnkTextStruct2 *a0, u8 a1, u8 a2, u32 *a3) +{ + int i; + u32 r9 = 2; + + if (a0 == NULL) + a0 = gUnknown_80B857C; + if (a2) + sub_8009388(); + sub_800898C(); + for (i = 0; i < 4; i++) + { + gUnknown_202AFC0[i] = a0[i]; + if (a0[i].unk0c) + { + sub_8006554(gUnknown_2027370, (void *)VRAM, gUnknown_20274B4, gUnknown_202B038, gUnknown_80B8804[i], a0 + i, a1, r9, a3, 0); + sub_80089AC(a0 + i, a3); + r9 += a0[i].unk0c * a0[i].unk10; + } + } +#ifdef NONMATCHING + gUnknown_203B078 = gUnknown_3000E94; + gUnknown_20274A5 = 1; +#else + asm(".syntax unified\n" + "\tldr r2, =gUnknown_203B078\n" + "\tldr r0, =gUnknown_3000E94\n" + "\tldr r1, =gUnknown_20274A5\n" + "\tstr r0, [r2]\n" + "\tmovs r0, 0x1\n" + "\tstrb r0, [r1]\n" + ".syntax divided"); +#endif +} -- cgit v1.2.3 From 0429b2e5bb2a2c4467518bf921bd900927e84205 Mon Sep 17 00:00:00 2001 From: PikalaxALT Date: Sun, 21 Jan 2018 20:26:38 -0500 Subject: Fix Windows --- Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c91a4e2..b2f476a 100755 --- a/Makefile +++ b/Makefile @@ -11,7 +11,11 @@ LD := $(DEVKITARM)/bin/arm-none-eabi-ld OBJCOPY := $(DEVKITARM)/bin/arm-none-eabi-objcopy -LIB := -L tools/agbcc/lib -lc -lgcc +ifeq ($(OS),Windows_NT) + LIB := tools/agbcc/lib/libc.a tools/agbcc/lib/libgcc.a +else + LIB := -L tools/agbcc/lib -lc -lgcc +endif MD5 := md5sum -c -- cgit v1.2.3 From b1c96eaac6ab14ae272d3a56447ca9101bafc0f2 Mon Sep 17 00:00:00 2001 From: fl4shk Date: Fri, 16 Nov 2018 19:10:13 -0500 Subject: build_tools.sh --- build_tools.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100755 build_tools.sh diff --git a/build_tools.sh b/build_tools.sh new file mode 100755 index 0000000..d9eebf0 --- /dev/null +++ b/build_tools.sh @@ -0,0 +1,10 @@ +#!/bin/sh +make -C tools/gbagfx CXX=${1:-g++} +make -C tools/scaninc CXX=${1:-g++} +make -C tools/preproc CXX=${1:-g++} +make -C tools/bin2c CXX=${1:-g++} +make -C tools/rsfont CXX=${1:-g++} +make -C tools/aif2pcm CXX=${1:-g++} +make -C tools/ramscrgen CXX=${1:-g++} +make -C tools/gbafix CXX=${1:-g++} +make -C tools/mid2agb CXX=${1:-g++} -- cgit v1.2.3 From 9e5147a9adf9dc0aba908f38637cd0b4da2cbbcc Mon Sep 17 00:00:00 2001 From: nullableVoidPtr <30564701+nullableVoidPtr@users.noreply.github.com> Date: Tue, 16 Oct 2018 17:11:54 +0800 Subject: Makefile overhaul Addition of a build directory, and more flexible to allow for possible blue build. --- INSTALL.md | 6 +- Makefile | 160 ++++--- README.md | 6 +- asmdiff.sh | 7 + ld_script.sed | 14 - ld_script.txt | 6 +- red.sha1 | 1 + rom.md5 | 1 - sym_ewram.txt | 1406 ++++++++++++++++++++++++++++---------------------------- sym_ewram2.txt | 872 +++++++++++++++++------------------ sym_iwram.txt | 102 ++-- 11 files changed, 1294 insertions(+), 1287 deletions(-) create mode 100644 asmdiff.sh delete mode 100644 ld_script.sed create mode 100644 red.sha1 delete mode 100644 rom.md5 diff --git a/INSTALL.md b/INSTALL.md index b2440d2..b114971 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -10,7 +10,7 @@ Then get the compiler from https://github.com/pret/agbcc and run the following c install.sh PATH_OF_PMD-RED_DIRECTORY ${DEVKITARM}/bin/arm-none-eabi/ranlib PATH_OF_PMD-RED_DIRECTORY/tools/agbcc/lib/libgcc.a lib/libc.a -Then in the pokeruby directory, build the tools. +Then in the pmd-red directory, build the tools. build_tools.sh @@ -22,6 +22,6 @@ Finally, build the rom. Install [**devkitARM**](http://devkitpro.org/wiki/Getting_Started/devkitARM). -Then get the compiled tools from https://github.com/pret/pokeruby-tools. Copy the `tools/` folder over the `tools/` folder in your pokeruby directory. +Then get the compiled tools from https://github.com/pret/pokeruby-tools. Copy the `tools/` folder over the `tools/` folder in your pmd-red directory. -You can then build pokeruby using `make` in the MSYS environment provided with devkitARM. +You can then build pmd-red using `make` in the MSYS environment provided with devkitARM. diff --git a/Makefile b/Makefile index 6d5d120..0b86d1d 100755 --- a/Makefile +++ b/Makefile @@ -1,99 +1,115 @@ -AS := $(DEVKITARM)/bin/arm-none-eabi-as -ASFLAGS := -mcpu=arm7tdmi - -CC1 := tools/agbcc/bin/agbcc -override CFLAGS += -mthumb-interwork -Wimplicit -Wparentheses -Wunused -Werror -O2 -fhex-asm - -CPP := $(DEVKITARM)/bin/arm-none-eabi-cpp -CPPFLAGS := -I tools/agbcc/include -iquote include -nostdinc -undef - -LD := $(DEVKITARM)/bin/arm-none-eabi-ld +include $(DEVKITARM)/base_tools + +ifeq ($(OS),Windows_NT) +EXE := .exe +else +EXE := +endif + + +#### Tools #### + +SHELL := /bin/bash -o pipefail +AS := $(PREFIX)as +CC1 := tools/agbcc/bin/agbcc +CPP := $(PREFIX)cpp +LD := $(PREFIX)ld +OBJCOPY := $(PREFIX)objcopy +SHA1SUM := sha1sum -c +GBAGFX := tools/gbagfx/gbagfx +AIF2PCM := tools/aif2pcm/aif2pcm +MID2AGB := tools/mid2agb/mid2agb +PREPROC := tools/preproc/preproc +SCANINC := tools/scaninc/scaninc +RAMSCRGEN := tools/ramscrgen/ramscrgen -OBJCOPY := $(DEVKITARM)/bin/arm-none-eabi-objcopy +ASFLAGS := -mcpu=arm7tdmi +override CC1FLAGS += -mthumb-interwork -Wimplicit -Wparentheses -Wunused -Werror -O2 -fhex-asm +CPPFLAGS := -I tools/agbcc/include -iquote include -nostdinc -undef -LIBGCC := tools/agbcc/lib/libgcc.a -LIBC := tools/agbcc/lib/libc.a +#### Files #### -MD5 := md5sum -c +BUILD_NAME = red -GFX := tools/gbagfx/gbagfx -AIF := tools/aif2pcm/aif2pcm -MID := tools/mid2agb/mid2agb -SCANINC := tools/scaninc/scaninc -PREPROC := tools/preproc/preproc -RAMSCRGEN := tools/ramscrgen/ramscrgen +ROM := pmd_$(BUILD_NAME).gba +MAP := $(ROM:%.gba=%.map) -# Clear the default suffixes. -.SUFFIXES: +BUILD_DIR := build/pmd_$(BUILD_NAME) -# Secondary expansion is required for dependency variables in object rules. -.SECONDEXPANSION: +C_SOURCES := $(wildcard src/*.c) +ASM_SOURCES := $(wildcard asm/*.s data/*.s) -.PRECIOUS: %.1bpp %.4bpp %.8bpp %.gbapal %.lz %.rl %.pcm %.bin +C_OBJECTS := $(addprefix $(BUILD_DIR)/, $(C_SOURCES:%.c=%.o)) +ASM_OBJECTS := $(addprefix $(BUILD_DIR)/, $(ASM_SOURCES:%.s=%.o)) +ALL_OBJECTS := $(C_OBJECTS) $(ASM_OBJECTS) -.PHONY: all clean tidy +SUBDIRS := $(sort $(dir $(ALL_OBJECTS))) -C_SRCS := $(wildcard src/*.c) -C_OBJS := $(C_SRCS:%.c=%.o) +LIBC := tools/agbcc/lib/libc.a +LIBGCC := tools/agbcc/lib/libgcc.a -ASM_SRCS := $(wildcard asm/*.s) -ASM_OBJS := $(ASM_SRCS:%.s=%.o) +LD_SCRIPT := $(BUILD_DIR)/ld_script.ld -DATA_ASM_SRCS := $(wildcard data/*.s) -DATA_ASM_OBJS := $(DATA_ASM_SRCS:%.s=%.o) +# Special configurations required for lib files +%/src/agb_flash.o : CC1FLAGS := -O -mthumb-interwork +%/src/agb_flash_1m.o: CC1FLAGS := -O -mthumb-interwork +%/src/agb_flash_mx.o: CC1FLAGS := -O -mthumb-interwork -OBJS := $(C_OBJS) $(ASM_OBJS) $(DATA_ASM_OBJS) +#### Main Rules #### -all: pmd_red.gba +ALL_BUILDS := red -# For contributors to make sure a change didn't affect the contents of the ROM. +# Available targets +.PHONY: all clean tidy -compare: all - @$(MD5) rom.md5 +MAKEFLAGS += --no-print-directory +# Secondary expansion is required for dependency variables in object rules. +.SECONDEXPANSION: +# Clear the default suffixes +.SUFFIXES: +# Don't delete intermediate files +.SECONDARY: +# Delete files that weren't built properly +.DELETE_ON_ERROR: -clean: tidy +.PRECIOUS: %.1bpp %.4bpp %.8bpp %.gbapal %.lz %.rl %.pcm %.bin -tidy: - rm -f pmd_red.gba pmd_red.elf pmd_red.map - rm -f $(ASM_OBJS) - rm -f $(DATA_ASM_OBJS) - rm -f $(C_OBJS) - rm -f $(ASM_OBJS) - rm -f $(DATA_ASM_OBJS) - rm -f $(C_SRCS:%.c=%.i) - rm -f $(C_SRCS:%.c=%.s) - rm -f *.ld -src/agb_flash.o: CFLAGS := -O -mthumb-interwork -src/agb_flash_1m.o: CFLAGS := -O -mthumb-interwork -src/agb_flash_mx.o: CFLAGS := -O -mthumb-interwork +# Create build subdirectories -$(C_OBJS): %.o : %.c - @$(CPP) $(CPPFLAGS) $< -o $*.i - @$(CC1) $(CFLAGS) $*.i -o $*.s - @printf ".text\n\t.align\t2, 0\n" >> $*.s - $(AS) $(ASFLAGS) -o $@ $*.s +$(shell mkdir -p $(SUBDIRS)) -$(ASM_OBJS): %.o: %.s - $(AS) $(ASFLAGS) -o $@ $< +all: $(ROM) +ifeq ($(COMPARE),1) + @$(SHA1SUM) $(BUILD_NAME).sha1 +endif -$(DATA_ASM_OBJS): %.o: %.s - $(AS) $(ASFLAGS) -o $@ $< +clean: tidy + $(RM) $(ALL_OBJECTS) +tidy: + $(RM) $(ALL_BUILDS:%=pmd_%{.gba,.elf,.map}) + $(RM) -r build -sym_ewram.ld: sym_ewram.txt - $(RAMSCRGEN) ewram_data sym_ewram.txt ENGLISH >$@ +$(ROM): %.gba: %.elf + $(OBJCOPY) -O binary --gap-fill 0xFF --pad-to 0xA000000 $< $@ -sym_ewram2.ld: sym_ewram2.txt - $(RAMSCRGEN) ewram_data sym_ewram2.txt ENGLISH >$@ +%.elf: $(LD_SCRIPT) $(ALL_OBJECTS) $(LIBC) + cd $(BUILD_DIR) && $(LD) -T ld_script.ld -Map ../../$(MAP) -o ../../$@ ../../$(LIBC) ../../$(LIBGCC) -sym_iwram.ld: sym_iwram.txt - $(RAMSCRGEN) iwram_data sym_iwram.txt ENGLISH >$@ +$(LD_SCRIPT): ld_script.txt $(BUILD_DIR)/sym_ewram.ld $(BUILD_DIR)/sym_ewram2.ld $(BUILD_DIR)/sym_iwram.ld + cd $(BUILD_DIR) && sed -e "s#tools/#../../tools/#g" ../../ld_script.txt >ld_script.ld +$(BUILD_DIR)/sym_%.ld: sym_%.txt + $(CPP) -P $(CPPFLAGS) $< | sed -e "s#tools/#../../tools/#g" > $@ -ld_script.ld: ld_script.txt sym_ewram.ld sym_ewram2.ld sym_iwram.ld - sed -f ld_script.sed ld_script.txt >ld_script.ld +$(C_OBJECTS): $(BUILD_DIR)/%.o: %.c + @$(CPP) $(CPPFLAGS) $< -o $(BUILD_DIR)/$*.i + echo $(CC1) $(CC1FLAGS) $(BUILD_DIR)/$*.i -o $(BUILD_DIR)/$*.s + @$(CC1) $(CC1FLAGS) $(BUILD_DIR)/$*.i -o $(BUILD_DIR)/$*.s + @printf ".text\n\t.align\t2, 0\n" >> $(BUILD_DIR)/$*.s + $(AS) $(ASFLAGS) -o $@ $(BUILD_DIR)/$*.s -pmd_red.elf: ld_script.ld $(OBJS) $(LIBC) - $(LD) -T ld_script.ld -Map pmd_red.map -o $@ $(OBJS) $(LIBC) $(LIBGCC) +$(BUILD_DIR)/data/%.o: data/%.s + $(AS) $(ASFLAGS) $< -o $@ -pmd_red.gba: pmd_red.elf - $(OBJCOPY) -O binary --gap-fill 0xFF --pad-to 0xA000000 $< $@ +$(BUILD_DIR)/%.o: %.s + $(AS) $(ASFLAGS) $< -o $@ \ No newline at end of file diff --git a/README.md b/README.md index 4a5419d..070612d 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# Pokémon Mystery Dungeon: Red Rescue Team [![Build Status][travis-badge]][travis] +# Pokémon Mystery Dungeon: Red Rescue Team This is a disassembly of Pokémon Mystery Dungeon: Red Rescue Team. It builds the following rom: -* pmd_red.gba `md5: 2100cf6f17e12cd34f1513647dfa506b` +* pmd_red.gba `sha1: 9f4cfc5b5f4859d17169a485462e977c7aac2b89` To set up the repository, see [INSTALL.md](INSTALL.md). @@ -33,5 +33,3 @@ To set up the repository, see [INSTALL.md](INSTALL.md). [pokeemerald]: https://github.com/pret/pokeemerald [Discord]: https://discord.gg/6EuWgX9 [irc]: https://kiwiirc.com/client/irc.freenode.net/?#pret -[travis]: https://travis-ci.org/pret/pokeruby -[travis-badge]: https://travis-ci.org/pret/pokeruby.svg?branch=master diff --git a/asmdiff.sh b/asmdiff.sh new file mode 100644 index 0000000..a4afe79 --- /dev/null +++ b/asmdiff.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +OBJDUMP="$DEVKITARM/bin/arm-none-eabi-objdump -D -bbinary -marmv4t -Mforce-thumb" +OPTIONS="--start-address=$(($1)) --stop-address=$(($1 + $2))" +$OBJDUMP $OPTIONS baserom.gba > baserom.dump +$OBJDUMP $OPTIONS pmd_red.gba > pmd_red.dump +diff -u baserom.dump pmd_red.dump | less \ No newline at end of file diff --git a/ld_script.sed b/ld_script.sed deleted file mode 100644 index 65e2610..0000000 --- a/ld_script.sed +++ /dev/null @@ -1,14 +0,0 @@ -// { - r sym_ewram.ld - d -} - -// { - r sym_ewram2.ld - d -} - -// { - r sym_iwram.ld - d -} diff --git a/ld_script.txt b/ld_script.txt index e3a6af7..3bc7a22 100755 --- a/ld_script.txt +++ b/ld_script.txt @@ -7,7 +7,7 @@ SECTIONS { ALIGN(4) { ewram_start = .; - + INCLUDE "sym_ewram.ld" . = ALIGN(4); src/agb_flash.o(.bss); . = ALIGN(4); @@ -17,7 +17,7 @@ SECTIONS { . = ALIGN(4); tools/agbcc/lib/libc.a:syscalls.o(.bss); . = ALIGN(16); - + INCLUDE "sym_ewram2.ld" . = ALIGN(4); tools/agbcc/lib/libc.a:impure.o(.data); . = ALIGN(4); @@ -35,7 +35,7 @@ SECTIONS { ALIGN(4) { iwram_start = .; - + INCLUDE "sym_iwram.ld" . = 0x8000; } diff --git a/red.sha1 b/red.sha1 new file mode 100644 index 0000000..aefd29a --- /dev/null +++ b/red.sha1 @@ -0,0 +1 @@ +9f4cfc5b5f4859d17169a485462e977c7aac2b89 pmd_red.gba \ No newline at end of file diff --git a/rom.md5 b/rom.md5 deleted file mode 100644 index f228854..0000000 --- a/rom.md5 +++ /dev/null @@ -1 +0,0 @@ -2100cf6f17e12cd34f1513647dfa506b pmd_red.gba diff --git a/sym_ewram.txt b/sym_ewram.txt index ebfde64..f235a49 100644 --- a/sym_ewram.txt +++ b/sym_ewram.txt @@ -1,1054 +1,1054 @@ - .space 0x8F0 + . += 0x8F0; -gUnknown_20008F0: @ 20008F0 - .space 0x80 +gUnknown_20008F0 = .; /* 20008F0 */ + . += 0x80; -gUnknown_2000970: @ 2000970 - .space 0xC0 +gUnknown_2000970 = .; /* 2000970 */ + . += 0xC0; -gUnknown_2000A30: @ 2000A30 - .space 0x50 +gUnknown_2000A30 = .; /* 2000A30 */ + . += 0x50; -gUnknown_2000A80: @ 2000A80 - .space 0x8 +gUnknown_2000A80 = .; /* 2000A80 */ + . += 0x8; -gUnknown_2000A88: @ 2000A88 - .space 0x400 +gUnknown_2000A88 = .; /* 2000A88 */ + . += 0x400; -gUnknown_2000E88: @ 2000E88 - .space 0x20 +gUnknown_2000E88 = .; /* 2000E88 */ + . += 0x20; -gUnknown_2000EA8: @ 2000EA8 - .space 0x8 +gUnknown_2000EA8 = .; /* 2000EA8 */ + . += 0x8; -gUnknown_2000EB0: @ 2000EB0 - .space 0x20 +gUnknown_2000EB0 = .; /* 2000EB0 */ + . += 0x20; -gUnknown_2000ED0: @ 2000ED0 - .space 0x300 +gUnknown_2000ED0 = .; /* 2000ED0 */ + . += 0x300; -gUnknown_20011D0: @ 20011D0 - .space 0x24000 +gUnknown_20011D0 = .; /* 20011D0 */ + . += 0x24000; -gUnknown_20251D0: @ 20251D0 - .space 0x20 +gUnknown_20251D0 = .; /* 20251D0 */ + . += 0x20; -gUnknown_20251F0: @ 20251F0 - .space 0x400 +gUnknown_20251F0 = .; /* 20251F0 */ + . += 0x400; -gUnknown_20255F0: @ 20255F0 - .space 0x10 +gUnknown_20255F0 = .; /* 20255F0 */ + . += 0x10; -gUnknown_2025600: @ 2025600 - .space 0x2C +gUnknown_2025600 = .; /* 2025600 */ + . += 0x2C; -gUnknown_202562C: @ 202562C - .space 0xC +gUnknown_202562C = .; /* 202562C */ + . += 0xC; -gUnknown_2025638: @ 2025638 - .space 0x10 +gUnknown_2025638 = .; /* 2025638 */ + . += 0x10; -gUnknown_2025648: @ 2025648 - .space 0x10 +gUnknown_2025648 = .; /* 2025648 */ + . += 0x10; -gUnknown_2025658: @ 2025658 - .space 0x10 +gUnknown_2025658 = .; /* 2025658 */ + . += 0x10; -gUnknown_2025668: @ 2025668 - .space 0x8 +gUnknown_2025668 = .; /* 2025668 */ + . += 0x8; -gUnknown_2025670: @ 2025670 - .space 0x2 +gUnknown_2025670 = .; /* 2025670 */ + . += 0x2; -gUnknown_2025672: @ 2025672 - .space 0x10 +gUnknown_2025672 = .; /* 2025672 */ + . += 0x10; -gUnknown_2025682: @ 2025682 - .space 0x12 +gUnknown_2025682 = .; /* 2025682 */ + . += 0x12; -gUnknown_2025694: @ 2025694 - .space 0x4 +gUnknown_2025694 = .; /* 2025694 */ + . += 0x4; -gUnknown_2025698: @ 2025698 - .space 0x8 +gUnknown_2025698 = .; /* 2025698 */ + . += 0x8; -gUnknown_20256A0: @ 20256A0 - .space 0x808 +gUnknown_20256A0 = .; /* 20256A0 */ + . += 0x808; -gUnknown_2025EA8: @ 2025EA8 - .space 0x400 +gUnknown_2025EA8 = .; /* 2025EA8 */ + . += 0x400; -gUnknown_20262A8: @ 20262A8 - .space 0x400 +gUnknown_20262A8 = .; /* 20262A8 */ + . += 0x400; -gUnknown_20266A8: @ 20266A8 - .space 0x8 +gUnknown_20266A8 = .; /* 20266A8 */ + . += 0x8; -gUnknown_20266B0: @ 20266B0 - .space 0x780 +gUnknown_20266B0 = .; /* 20266B0 */ + . += 0x780; -gUnknown_2026E30: @ 2026E30 - .space 0x8 +gUnknown_2026E30 = .; /* 2026E30 */ + . += 0x8; -gUnknown_2026E38: @ 2026E38 - .space 0x4 +gUnknown_2026E38 = .; /* 2026E38 */ + . += 0x4; -gUnknown_2026E3C: @ 2026E3C - .space 0x4 +gUnknown_2026E3C = .; /* 2026E3C */ + . += 0x4; -gUnknown_2026E40: @ 2026E40 - .space 0x4 +gUnknown_2026E40 = .; /* 2026E40 */ + . += 0x4; -gUnknown_2026E44: @ 2026E44 - .space 0x4 +gUnknown_2026E44 = .; /* 2026E44 */ + . += 0x4; -gUnknown_2026E48: @ 2026E48 - .space 0x4 +gUnknown_2026E48 = .; /* 2026E48 */ + . += 0x4; -gUnknown_2026E4C: @ 2026E4C - .space 0x2 +gUnknown_2026E4C = .; /* 2026E4C */ + . += 0x2; -gUnknown_2026E4E: @ 2026E4E - .space 0x2 +gUnknown_2026E4E = .; /* 2026E4E */ + . += 0x2; -gUnknown_2026E50: @ 2026E50 - .space 0x4 +gUnknown_2026E50 = .; /* 2026E50 */ + . += 0x4; -gUnknown_2026E54: @ 2026E54 - .space 0x4 +gUnknown_2026E54 = .; /* 2026E54 */ + . += 0x4; -gUnknown_2026E58: @ 2026E58 - .space 0x8 +gUnknown_2026E58 = .; /* 2026E58 */ + . += 0x8; -gUnknown_2026E60: @ 2026E60 - .space 0x288 +gUnknown_2026E60 = .; /* 2026E60 */ + . += 0x288; -gUnknown_20270E8: @ 20270E8 - .space 0x288 +gUnknown_20270E8 = .; /* 20270E8 */ + . += 0x288; -gUnknown_2027370: @ 2027370 - .space 0x48 +gUnknown_2027370 = .; /* 2027370 */ + . += 0x48; -gUnknown_20273B8: @ 20273B8 - .space 0xD8 +gUnknown_20273B8 = .; /* 20273B8 */ + . += 0xD8; -gUnknown_2027490: @ 2027490 - .space 0x8 +gUnknown_2027490 = .; /* 2027490 */ + . += 0x8; -gUnknown_2027498: @ 2027498 - .space 0x2 +gUnknown_2027498 = .; /* 2027498 */ + . += 0x2; -gUnknown_202749A: @ 202749A - .space 0xB +gUnknown_202749A = .; /* 202749A */ + . += 0xB; -gUnknown_20274A5: @ 20274A5 - .space 0x1 +gUnknown_20274A5 = .; /* 20274A5 */ + . += 0x1; -gUnknown_20274A6: @ 20274A6 - .space 0x6 +gUnknown_20274A6 = .; /* 20274A6 */ + . += 0x6; -gUnknown_20274AC: @ 20274AC - .space 0x4 +gUnknown_20274AC = .; /* 20274AC */ + . += 0x4; -gUnknown_20274B0: @ 20274B0 - .space 0x4 +gUnknown_20274B0 = .; /* 20274B0 */ + . += 0x4; -gUnknown_20274B4: @ 20274B4 - .space 0x3B00 +gUnknown_20274B4 = .; /* 20274B4 */ + . += 0x3B00; -gUnknown_202AFB4: @ 202AFB4 - .space 0xC +gUnknown_202AFB4 = .; /* 202AFB4 */ + . += 0xC; -gUnknown_202AFC0: @ 202AFC0 - .space 0x60 +gUnknown_202AFC0 = .; /* 202AFC0 */ + . += 0x60; -gUnknown_202B020: @ 202B020 - .space 0x4 +gUnknown_202B020 = .; /* 202B020 */ + . += 0x4; -gUnknown_202B024: @ 202B024 - .space 0x4 +gUnknown_202B024 = .; /* 202B024 */ + . += 0x4; -gUnknown_202B028: @ 202B028 - .space 0x8 +gUnknown_202B028 = .; /* 202B028 */ + . += 0x8; -gUnknown_202B030: @ 202B030 - .space 0x4 +gUnknown_202B030 = .; /* 202B030 */ + . += 0x4; -gUnknown_202B034: @ 202B034 - .space 0x4 +gUnknown_202B034 = .; /* 202B034 */ + . += 0x4; -gUnknown_202B038: @ 202B038 - .space 0x2 +gUnknown_202B038 = .; /* 202B038 */ + . += 0x2; -gUnknown_202B03A: @ 202B03A - .space 0x7FE +gUnknown_202B03A = .; /* 202B03A */ + . += 0x7FE; -gUnknown_202B838: @ 202B838 - .space 0x800 +gUnknown_202B838 = .; /* 202B838 */ + . += 0x800; -gUnknown_202C038: @ 202C038 - .space 0x800 +gUnknown_202C038 = .; /* 202C038 */ + . += 0x800; -gUnknown_202C838: @ 202C838 - .space 0x720 +gUnknown_202C838 = .; /* 202C838 */ + . += 0x720; -gUnknown_202CF58: @ 202CF58 - .space 0xE0 +gUnknown_202CF58 = .; /* 202CF58 */ + . += 0xE0; -gUnknown_202D038: @ 202D038 - .space 0x4 +gUnknown_202D038 = .; /* 202D038 */ + . += 0x4; -gUnknown_202D03C: @ 202D03C - .space 0x1C +gUnknown_202D03C = .; /* 202D03C */ + . += 0x1C; -gUnknown_202D058: @ 202D058 - .space 0x10 +gUnknown_202D058 = .; /* 202D058 */ + . += 0x10; -gUnknown_202D068: @ 202D068 - .space 0x4 +gUnknown_202D068 = .; /* 202D068 */ + . += 0x4; -gUnknown_202D06C: @ 202D06C - .space 0xC +gUnknown_202D06C = .; /* 202D06C */ + . += 0xC; -gUnknown_202D078: @ 202D078 - .space 0x20 +gUnknown_202D078 = .; /* 202D078 */ + . += 0x20; -gUnknown_202D098: @ 202D098 - .space 0x120 +gUnknown_202D098 = .; /* 202D098 */ + . += 0x120; -gUnknown_202D1B8: @ 202D1B8 - .space 0x40 +gUnknown_202D1B8 = .; /* 202D1B8 */ + . += 0x40; -gUnknown_202D1F8: @ 202D1F8 - .space 0x40 +gUnknown_202D1F8 = .; /* 202D1F8 */ + . += 0x40; -gUnknown_202D238: @ 202D238 - .space 0x4 +gUnknown_202D238 = .; /* 202D238 */ + . += 0x4; -gUnknown_202D23C: @ 202D23C - .space 0x4 +gUnknown_202D23C = .; /* 202D23C */ + . += 0x4; -gUnknown_202D240: @ 202D240 - .space 0x60 +gUnknown_202D240 = .; /* 202D240 */ + . += 0x60; -gUnknown_202D2A0: @ 202D2A0 - .space 0x4 +gUnknown_202D2A0 = .; /* 202D2A0 */ + . += 0x4; -gUnknown_202D2A4: @ 202D2A4 - .space 0x4 +gUnknown_202D2A4 = .; /* 202D2A4 */ + . += 0x4; -gUnknown_202D2A8: @ 202D2A8 - .space 0x110 +gUnknown_202D2A8 = .; /* 202D2A8 */ + . += 0x110; -gUnknown_202D3B8: @ 202D3B8 - .space 0xF0 +gUnknown_202D3B8 = .; /* 202D3B8 */ + . += 0xF0; -gUnknown_202D4A8: @ 202D4A8 - .space 0x4 +gUnknown_202D4A8 = .; /* 202D4A8 */ + . += 0x4; -gUnknown_202D4AC: @ 202D4AC - .space 0x4 +gUnknown_202D4AC = .; /* 202D4AC */ + . += 0x4; -gUnknown_202D4B0: @ 202D4B0 - .space 0x4 +gUnknown_202D4B0 = .; /* 202D4B0 */ + . += 0x4; -gUnknown_202D4B4: @ 202D4B4 - .space 0x4 +gUnknown_202D4B4 = .; /* 202D4B4 */ + . += 0x4; -gUnknown_202D4B8: @ 202D4B8 - .space 0x120 +gUnknown_202D4B8 = .; /* 202D4B8 */ + . += 0x120; -gIntrTable: @ 202D5D8 - .space 0x18 +gIntrTable = .; /* 202D5D8 */ + . += 0x18; -gUnknown_202D5F0: @ 202D5F0 - .space 0x18 +gUnknown_202D5F0 = .; /* 202D5F0 */ + . += 0x18; -gUnknown_202D608: @ 202D608 - .space 0x40 +gUnknown_202D608 = .; /* 202D608 */ + . += 0x40; -gUnknown_202D648: @ 202D648 - .space 0x40 +gUnknown_202D648 = .; /* 202D648 */ + . += 0x40; -gUnknown_202D688: @ 202D688 - .space 0x2 +gUnknown_202D688 = .; /* 202D688 */ + . += 0x2; -gUnknown_202D68A: @ 202D68A - .space 0x2 +gUnknown_202D68A = .; /* 202D68A */ + . += 0x2; -gUnknown_202D68C: @ 202D68C - .space 0x2 +gUnknown_202D68C = .; /* 202D68C */ + . += 0x2; -gUnknown_202D68E: @ 202D68E - .space 0x2 +gUnknown_202D68E = .; /* 202D68E */ + . += 0x2; -gUnknown_202D690: @ 202D690 - .space 0x2 +gUnknown_202D690 = .; /* 202D690 */ + . += 0x2; -gUnknown_202D692: @ 202D692 - .space 0x2 +gUnknown_202D692 = .; /* 202D692 */ + . += 0x2; -gUnknown_202D694: @ 202D694 - .space 0x4 +gUnknown_202D694 = .; /* 202D694 */ + . += 0x4; -gUnknown_202D698: @ 202D698 - .space 0x8 +gUnknown_202D698 = .; /* 202D698 */ + . += 0x8; -gUnknown_202D6A0: @ 202D6A0 - .space 0x8 +gUnknown_202D6A0 = .; /* 202D6A0 */ + . += 0x8; -gUnknown_202D6A8: @ 202D6A8 - .space 0x8 +gUnknown_202D6A8 = .; /* 202D6A8 */ + . += 0x8; -gUnknown_202D6B0: @ 202D6B0 - .space 0x8 +gUnknown_202D6B0 = .; /* 202D6B0 */ + . += 0x8; -gUnknown_202D6B8: @ 202D6B8 - .space 0x1 +gUnknown_202D6B8 = .; /* 202D6B8 */ + . += 0x1; -gUnknown_202D6B9: @ 202D6B9 - .space 0x141 +gUnknown_202D6B9 = .; /* 202D6B9 */ + . += 0x141; -gUnknown_202D7FA: @ 202D7FA - .space 0x2 +gUnknown_202D7FA = .; /* 202D7FA */ + . += 0x2; -gUnknown_202D7FC: @ 202D7FC - .space 0x2 +gUnknown_202D7FC = .; /* 202D7FC */ + . += 0x2; -gUnknown_202D7FE: @ 202D7FE - .space 0x2 +gUnknown_202D7FE = .; /* 202D7FE */ + . += 0x2; -gUnknown_202D800: @ 202D800 - .space 0x8 +gUnknown_202D800 = .; /* 202D800 */ + . += 0x8; -gUnknown_202D808: @ 202D808 - .space 0x108 +gUnknown_202D808 = .; /* 202D808 */ + . += 0x108; -gUnknown_202D910: @ 202D910 - .space 0x4 +gUnknown_202D910 = .; /* 202D910 */ + . += 0x4; -gUnknown_202D914: @ 202D914 - .space 0x20C +gUnknown_202D914 = .; /* 202D914 */ + . += 0x20C; -gUnknown_202DB20: @ 202DB20 - .space 0x10 +gUnknown_202DB20 = .; /* 202DB20 */ + . += 0x10; -gUnknown_202DB30: @ 202DB30 - .space 0x20 +gUnknown_202DB30 = .; /* 202DB30 */ + . += 0x20; -gUnknown_202DB50: @ 202DB50 - .space 0x8 +gUnknown_202DB50 = .; /* 202DB50 */ + . += 0x8; -gUnknown_202DB58: @ 202DB58 - .space 0x8 +gUnknown_202DB58 = .; /* 202DB58 */ + . += 0x8; -gUnknown_202DB60: @ 202DB60 - .space 0x8 +gUnknown_202DB60 = .; /* 202DB60 */ + . += 0x8; -gUnknown_202DB68: @ 202DB68 - .space 0x4 +gUnknown_202DB68 = .; /* 202DB68 */ + . += 0x4; -gUnknown_202DB6C: @ 202DB6C - .space 0x4 +gUnknown_202DB6C = .; /* 202DB6C */ + . += 0x4; -gUnknown_202DB70: @ 202DB70 - .space 0x4 +gUnknown_202DB70 = .; /* 202DB70 */ + . += 0x4; -gUnknown_202DB74: @ 202DB74 - .space 0x4 +gUnknown_202DB74 = .; /* 202DB74 */ + . += 0x4; -gUnknown_202DB78: @ 202DB78 - .space 0x40 +gUnknown_202DB78 = .; /* 202DB78 */ + . += 0x40; -gUnknown_202DBB8: @ 202DBB8 - .space 0x140 +gUnknown_202DBB8 = .; /* 202DBB8 */ + . += 0x140; -gUnknown_202DCF8: @ 202DCF8 - .space 0x120 +gUnknown_202DCF8 = .; /* 202DCF8 */ + . += 0x120; -gUnknown_202DE18: @ 202DE18 - .space 0x1 +gUnknown_202DE18 = .; /* 202DE18 */ + . += 0x1; -gUnknown_202DE19: @ 202DE19 - .space 0x3 +gUnknown_202DE19 = .; /* 202DE19 */ + . += 0x3; -gUnknown_202DE1C: @ 202DE1C - .space 0x4 +gUnknown_202DE1C = .; /* 202DE1C */ + . += 0x4; -gUnknown_202DE20: @ 202DE20 - .space 0x2 +gUnknown_202DE20 = .; /* 202DE20 */ + . += 0x2; -gUnknown_202DE22: @ 202DE22 - .space 0x2 +gUnknown_202DE22 = .; /* 202DE22 */ + . += 0x2; -gUnknown_202DE24: @ 202DE24 - .space 0x4 +gUnknown_202DE24 = .; /* 202DE24 */ + . += 0x4; -gUnknown_202DE28: @ 202DE28 - .space 0x8 +gUnknown_202DE28 = .; /* 202DE28 */ + . += 0x8; -gUnknown_202DE30: @ 202DE30 - .space 0x28 +gUnknown_202DE30 = .; /* 202DE30 */ + . += 0x28; -gUnknown_202DE58: @ 202DE58 - .space 0x50 +gUnknown_202DE58 = .; /* 202DE58 */ + . += 0x50; -gUnknown_202DEA8: @ 202DEA8 - .space 0xF0 +gUnknown_202DEA8 = .; /* 202DEA8 */ + . += 0xF0; -gUnknown_202DF98: @ 202DF98 - .space 0x50 +gUnknown_202DF98 = .; /* 202DF98 */ + . += 0x50; -gUnknown_202DFE8: @ 202DFE8 - .space 0x50 +gUnknown_202DFE8 = .; /* 202DFE8 */ + . += 0x50; -gUnknown_202E038: @ 202E038 - .space 0x50 +gUnknown_202E038 = .; /* 202E038 */ + . += 0x50; -gUnknown_202E088: @ 202E088 - .space 0xA0 +gUnknown_202E088 = .; /* 202E088 */ + . += 0xA0; -gUnknown_202E128: @ 202E128 - .space 0xA0 +gUnknown_202E128 = .; /* 202E128 */ + . += 0xA0; -gUnknown_202E1C8: @ 202E1C8 - .space 0x50 +gUnknown_202E1C8 = .; /* 202E1C8 */ + . += 0x50; -gUnknown_202E218: @ 202E218 - .space 0xA0 +gUnknown_202E218 = .; /* 202E218 */ + . += 0xA0; -gUnknown_202E2B8: @ 202E2B8 - .space 0x320 +gUnknown_202E2B8 = .; /* 202E2B8 */ + . += 0x320; -gUnknown_202E5D8: @ 202E5D8 - .space 0x50 +gUnknown_202E5D8 = .; /* 202E5D8 */ + . += 0x50; -gUnknown_202E628: @ 202E628 - .space 0xB8 +gUnknown_202E628 = .; /* 202E628 */ + . += 0xB8; -gUnknown_202E6E0: @ 202E6E0 - .space 0x8 +gUnknown_202E6E0 = .; /* 202E6E0 */ + . += 0x8; -gUnknown_202E6E8: @ 202E6E8 - .space 0x50 +gUnknown_202E6E8 = .; /* 202E6E8 */ + . += 0x50; -gUnknown_202E738: @ 202E738 - .space 0x4 +gUnknown_202E738 = .; /* 202E738 */ + . += 0x4; -gUnknown_202E73C: @ 202E73C - .space 0x4 +gUnknown_202E73C = .; /* 202E73C */ + . += 0x4; -gUnknown_202E740: @ 202E740 - .space 0x4 +gUnknown_202E740 = .; /* 202E740 */ + . += 0x4; -gUnknown_202E744: @ 202E744 - .space 0x4 +gUnknown_202E744 = .; /* 202E744 */ + . += 0x4; -gUnknown_202E748: @ 202E748 - .space 0x34 +gUnknown_202E748 = .; /* 202E748 */ + . += 0x34; -gUnknown_202E77C: @ 202E77C - .space 0x4 +gUnknown_202E77C = .; /* 202E77C */ + . += 0x4; -gUnknown_202E780: @ 202E780 - .space 0x4 +gUnknown_202E780 = .; /* 202E780 */ + . += 0x4; -gUnknown_202E784: @ 202E784 - .space 0x4 +gUnknown_202E784 = .; /* 202E784 */ + . += 0x4; -gUnknown_202E788: @ 202E788 - .space 0x4 +gUnknown_202E788 = .; /* 202E788 */ + . += 0x4; -gUnknown_202E78C: @ 202E78C - .space 0x4 +gUnknown_202E78C = .; /* 202E78C */ + . += 0x4; -gUnknown_202E790: @ 202E790 - .space 0x1 +gUnknown_202E790 = .; /* 202E790 */ + . += 0x1; -gUnknown_202E791: @ 202E791 - .space 0x3 +gUnknown_202E791 = .; /* 202E791 */ + . += 0x3; -gUnknown_202E794: @ 202E794 - .space 0x4 +gUnknown_202E794 = .; /* 202E794 */ + . += 0x4; -gUnknown_202E798: @ 202E798 - .space 0x3E8 +gUnknown_202E798 = .; /* 202E798 */ + . += 0x3E8; -gUnknown_202EB80: @ 202EB80 - .space 0x40 +gUnknown_202EB80 = .; /* 202EB80 */ + . += 0x40; -gUnknown_202EBC0: @ 202EBC0 - .space 0x50 +gUnknown_202EBC0 = .; /* 202EBC0 */ + . += 0x50; -gUnknown_202EC10: @ 202EC10 - .space 0x4 +gUnknown_202EC10 = .; /* 202EC10 */ + . += 0x4; -gUnknown_202EC14: @ 202EC14 - .space 0x4 +gUnknown_202EC14 = .; /* 202EC14 */ + . += 0x4; -gUnknown_202EC18: @ 202EC18 - .space 0x4 +gUnknown_202EC18 = .; /* 202EC18 */ + . += 0x4; -gUnknown_202EC1C: @ 202EC1C - .space 0x4 +gUnknown_202EC1C = .; /* 202EC1C */ + . += 0x4; -gUnknown_202EC20: @ 202EC20 - .space 0x8 +gUnknown_202EC20 = .; /* 202EC20 */ + . += 0x8; -gUnknown_202EC28: @ 202EC28 - .space 0x10 +gUnknown_202EC28 = .; /* 202EC28 */ + . += 0x10; -gUnknown_202EC38: @ 202EC38 - .space 0x8 +gUnknown_202EC38 = .; /* 202EC38 */ + . += 0x8; -gUnknown_202EC40: @ 202EC40 - .space 0x8 +gUnknown_202EC40 = .; /* 202EC40 */ + . += 0x8; -gUnknown_202EC48: @ 202EC48 - .space 0x4 +gUnknown_202EC48 = .; /* 202EC48 */ + . += 0x4; -gUnknown_202EC4C: @ 202EC4C - .space 0x4 +gUnknown_202EC4C = .; /* 202EC4C */ + . += 0x4; -gUnknown_202EC50: @ 202EC50 - .space 0x38 +gUnknown_202EC50 = .; /* 202EC50 */ + . += 0x38; -gUnknown_202EC88: @ 202EC88 - .space 0x4 +gUnknown_202EC88 = .; /* 202EC88 */ + . += 0x4; -gUnknown_202EC8C: @ 202EC8C - .space 0x4 +gUnknown_202EC8C = .; /* 202EC8C */ + . += 0x4; -gUnknown_202EC90: @ 202EC90 - .space 0x4 +gUnknown_202EC90 = .; /* 202EC90 */ + . += 0x4; -gUnknown_202EC94: @ 202EC94 - .space 0x4 +gUnknown_202EC94 = .; /* 202EC94 */ + . += 0x4; -gUnknown_202EC98: @ 202EC98 - .space 0x4 +gUnknown_202EC98 = .; /* 202EC98 */ + . += 0x4; -gUnknown_202EC9C: @ 202EC9C - .space 0x4 +gUnknown_202EC9C = .; /* 202EC9C */ + . += 0x4; -gUnknown_202ECA0: @ 202ECA0 - .space 0x4 +gUnknown_202ECA0 = .; /* 202ECA0 */ + . += 0x4; -gUnknown_202ECA4: @ 202ECA4 - .space 0x84 +gUnknown_202ECA4 = .; /* 202ECA4 */ + . += 0x84; -gUnknown_202ED28: @ 202ED28 - .space 0x8 +gUnknown_202ED28 = .; /* 202ED28 */ + . += 0x8; -gUnknown_202ED30: @ 202ED30 - .space 0x88 +gUnknown_202ED30 = .; /* 202ED30 */ + . += 0x88; -gUnknown_202EDB8: @ 202EDB8 - .space 0x8 +gUnknown_202EDB8 = .; /* 202EDB8 */ + . += 0x8; -gUnknown_202EDC0: @ 202EDC0 - .space 0x8 +gUnknown_202EDC0 = .; /* 202EDC0 */ + . += 0x8; -gUnknown_202EDC8: @ 202EDC8 - .space 0x4 +gUnknown_202EDC8 = .; /* 202EDC8 */ + . += 0x4; -gUnknown_202EDCC: @ 202EDCC - .space 0x4 +gUnknown_202EDCC = .; /* 202EDCC */ + . += 0x4; -gUnknown_202EDD0: @ 202EDD0 - .space 0x4 +gUnknown_202EDD0 = .; /* 202EDD0 */ + . += 0x4; -gUnknown_202EDD4: @ 202EDD4 - .space 0x4 +gUnknown_202EDD4 = .; /* 202EDD4 */ + . += 0x4; -gUnknown_202EDD8: @ 202EDD8 - .space 0x4 +gUnknown_202EDD8 = .; /* 202EDD8 */ + . += 0x4; -gUnknown_202EDDC: @ 202EDDC - .space 0xC +gUnknown_202EDDC = .; /* 202EDDC */ + . += 0xC; -gUnknown_202EDE8: @ 202EDE8 - .space 0x14 +gUnknown_202EDE8 = .; /* 202EDE8 */ + . += 0x14; -gUnknown_202EDFC: @ 202EDFC - .space 0x4 +gUnknown_202EDFC = .; /* 202EDFC */ + . += 0x4; -gUnknown_202EE00: @ 202EE00 - .space 0x1 +gUnknown_202EE00 = .; /* 202EE00 */ + . += 0x1; -gUnknown_202EE01: @ 202EE01 - .space 0x1 +gUnknown_202EE01 = .; /* 202EE01 */ + . += 0x1; -gUnknown_202EE02: @ 202EE02 - .space 0x2 +gUnknown_202EE02 = .; /* 202EE02 */ + . += 0x2; -gUnknown_202EE04: @ 202EE04 - .space 0x4 +gUnknown_202EE04 = .; /* 202EE04 */ + . += 0x4; -gUnknown_202EE08: @ 202EE08 - .space 0x4 +gUnknown_202EE08 = .; /* 202EE08 */ + . += 0x4; -gUnknown_202EE0C: @ 202EE0C - .space 0x4 +gUnknown_202EE0C = .; /* 202EE0C */ + . += 0x4; -gUnknown_202EE10: @ 202EE10 - .space 0x28 +gUnknown_202EE10 = .; /* 202EE10 */ + . += 0x28; -gUnknown_202EE38: @ 202EE38 - .space 0x1 +gUnknown_202EE38 = .; /* 202EE38 */ + . += 0x1; -gUnknown_202EE39: @ 202EE39 - .space 0x1 +gUnknown_202EE39 = .; /* 202EE39 */ + . += 0x1; -gUnknown_202EE3A: @ 202EE3A - .space 0xA +gUnknown_202EE3A = .; /* 202EE3A */ + . += 0xA; -gUnknown_202EE44: @ 202EE44 - .space 0x28 +gUnknown_202EE44 = .; /* 202EE44 */ + . += 0x28; -gUnknown_202EE6C: @ 202EE6C - .space 0x4 +gUnknown_202EE6C = .; /* 202EE6C */ + . += 0x4; -gUnknown_202EE70: @ 202EE70 - .space 0x6 +gUnknown_202EE70 = .; /* 202EE70 */ + . += 0x6; -gUnknown_202EE76: @ 202EE76 - .space 0x12 +gUnknown_202EE76 = .; /* 202EE76 */ + . += 0x12; -gUnknown_202EE88: @ 202EE88 - .space 0x4 +gUnknown_202EE88 = .; /* 202EE88 */ + . += 0x4; -gUnknown_202EE8C: @ 202EE8C - .space 0x300 +gUnknown_202EE8C = .; /* 202EE8C */ + . += 0x300; -gUnknown_202F18C: @ 202F18C - .space 0x4 +gUnknown_202F18C = .; /* 202F18C */ + . += 0x4; -gUnknown_202F190: @ 202F190 - .space 0x18 +gUnknown_202F190 = .; /* 202F190 */ + . += 0x18; -gUnknown_202F1A8: @ 202F1A8 - .space 0x1 +gUnknown_202F1A8 = .; /* 202F1A8 */ + . += 0x1; -gUnknown_202F1A9: @ 202F1A9 - .space 0x1 +gUnknown_202F1A9 = .; /* 202F1A9 */ + . += 0x1; -gUnknown_202F1AA: @ 202F1AA - .space 0x1 +gUnknown_202F1AA = .; /* 202F1AA */ + . += 0x1; -gUnknown_202F1AB: @ 202F1AB - .space 0x1 +gUnknown_202F1AB = .; /* 202F1AB */ + . += 0x1; -gUnknown_202F1AC: @ 202F1AC - .space 0x1 +gUnknown_202F1AC = .; /* 202F1AC */ + . += 0x1; -gUnknown_202F1AD: @ 202F1AD - .space 0x1 +gUnknown_202F1AD = .; /* 202F1AD */ + . += 0x1; -gUnknown_202F1AE: @ 202F1AE - .space 0x2 +gUnknown_202F1AE = .; /* 202F1AE */ + . += 0x2; -gUnknown_202F1B0: @ 202F1B0 - .space 0x2 +gUnknown_202F1B0 = .; /* 202F1B0 */ + . += 0x2; -gUnknown_202F1B2: @ 202F1B2 - .space 0x2 +gUnknown_202F1B2 = .; /* 202F1B2 */ + . += 0x2; -gUnknown_202F1B4: @ 202F1B4 - .space 0x4 +gUnknown_202F1B4 = .; /* 202F1B4 */ + . += 0x4; -gUnknown_202F1B8: @ 202F1B8 - .space 0x10 +gUnknown_202F1B8 = .; /* 202F1B8 */ + . += 0x10; -gUnknown_202F1C8: @ 202F1C8 - .space 0x4 +gUnknown_202F1C8 = .; /* 202F1C8 */ + . += 0x4; -gUnknown_202F1CC: @ 202F1CC - .space 0x4 +gUnknown_202F1CC = .; /* 202F1CC */ + . += 0x4; -gUnknown_202F1D0: @ 202F1D0 - .space 0x4 +gUnknown_202F1D0 = .; /* 202F1D0 */ + . += 0x4; -gUnknown_202F1D4: @ 202F1D4 - .space 0x4 +gUnknown_202F1D4 = .; /* 202F1D4 */ + . += 0x4; -gUnknown_202F1D8: @ 202F1D8 - .space 0x4 +gUnknown_202F1D8 = .; /* 202F1D8 */ + . += 0x4; -gUnknown_202F1DC: @ 202F1DC - .space 0x4 +gUnknown_202F1DC = .; /* 202F1DC */ + . += 0x4; -gUnknown_202F1E0: @ 202F1E0 - .space 0x1 +gUnknown_202F1E0 = .; /* 202F1E0 */ + . += 0x1; -gUnknown_202F1E1: @ 202F1E1 - .space 0x7 +gUnknown_202F1E1 = .; /* 202F1E1 */ + . += 0x7; -gUnknown_202F1E8: @ 202F1E8 - .space 0x8 +gUnknown_202F1E8 = .; /* 202F1E8 */ + . += 0x8; -gUnknown_202F1F0: @ 202F1F0 - .space 0x8 +gUnknown_202F1F0 = .; /* 202F1F0 */ + . += 0x8; -gUnknown_202F1F8: @ 202F1F8 - .space 0x4 +gUnknown_202F1F8 = .; /* 202F1F8 */ + . += 0x4; -gUnknown_202F1FC: @ 202F1FC - .space 0x4 +gUnknown_202F1FC = .; /* 202F1FC */ + . += 0x4; -gUnknown_202F200: @ 202F200 - .space 0x8 +gUnknown_202F200 = .; /* 202F200 */ + . += 0x8; -gUnknown_202F208: @ 202F208 - .space 0x4 +gUnknown_202F208 = .; /* 202F208 */ + . += 0x4; -gUnknown_202F20C: @ 202F20C - .space 0x4 +gUnknown_202F20C = .; /* 202F20C */ + . += 0x4; -gUnknown_202F210: @ 202F210 - .space 0x4 +gUnknown_202F210 = .; /* 202F210 */ + . += 0x4; -gUnknown_202F214: @ 202F214 - .space 0x4 +gUnknown_202F214 = .; /* 202F214 */ + . += 0x4; -gUnknown_202F218: @ 202F218 - .space 0x1 +gUnknown_202F218 = .; /* 202F218 */ + . += 0x1; -gUnknown_202F219: @ 202F219 - .space 0x1 +gUnknown_202F219 = .; /* 202F219 */ + . += 0x1; -gUnknown_202F21A: @ 202F21A - .space 0x2 +gUnknown_202F21A = .; /* 202F21A */ + . += 0x2; -gUnknown_202F21C: @ 202F21C - .space 0x4 +gUnknown_202F21C = .; /* 202F21C */ + . += 0x4; -gUnknown_202F220: @ 202F220 - .space 0x1 +gUnknown_202F220 = .; /* 202F220 */ + . += 0x1; -gUnknown_202F221: @ 202F221 - .space 0x1 +gUnknown_202F221 = .; /* 202F221 */ + . += 0x1; -gUnknown_202F222: @ 202F222 - .space 0x2 +gUnknown_202F222 = .; /* 202F222 */ + . += 0x2; -gUnknown_202F224: @ 202F224 - .space 0x4 +gUnknown_202F224 = .; /* 202F224 */ + . += 0x4; -gUnknown_202F228: @ 202F228 - .space 0x4 +gUnknown_202F228 = .; /* 202F228 */ + . += 0x4; -gUnknown_202F22C: @ 202F22C - .space 0x1 +gUnknown_202F22C = .; /* 202F22C */ + . += 0x1; -gUnknown_202F22D: @ 202F22D - .space 0x1 +gUnknown_202F22D = .; /* 202F22D */ + . += 0x1; -gUnknown_202F22E: @ 202F22E - .space 0x2 +gUnknown_202F22E = .; /* 202F22E */ + . += 0x2; -gUnknown_202F230: @ 202F230 - .space 0x1 +gUnknown_202F230 = .; /* 202F230 */ + . += 0x1; -gUnknown_202F231: @ 202F231 - .space 0x7 +gUnknown_202F231 = .; /* 202F231 */ + . += 0x7; -gUnknown_202F238: @ 202F238 - .space 0x8 +gUnknown_202F238 = .; /* 202F238 */ + . += 0x8; -gUnknown_202F240: @ 202F240 - .space 0x8 +gUnknown_202F240 = .; /* 202F240 */ + . += 0x8; -gUnknown_202F248: @ 202F248 - .space 0x10 +gUnknown_202F248 = .; /* 202F248 */ + . += 0x10; -gUnknown_202F258: @ 202F258 - .space 0x8 +gUnknown_202F258 = .; /* 202F258 */ + . += 0x8; -gUnknown_202F260: @ 202F260 - .space 0x8 +gUnknown_202F260 = .; /* 202F260 */ + . += 0x8; -gUnknown_202F268: @ 202F268 - .space 0x8 +gUnknown_202F268 = .; /* 202F268 */ + . += 0x8; -gUnknown_202F270: @ 202F270 - .space 0x8 +gUnknown_202F270 = .; /* 202F270 */ + . += 0x8; -gUnknown_202F278: @ 202F278 - .space 0x60 +gUnknown_202F278 = .; /* 202F278 */ + . += 0x60; -gUnknown_202F2D8: @ 202F2D8 - .space 0x8 +gUnknown_202F2D8 = .; /* 202F2D8 */ + . += 0x8; -gUnknown_202F2E0: @ 202F2E0 - .space 0x8 +gUnknown_202F2E0 = .; /* 202F2E0 */ + . += 0x8; -gUnknown_202F2E8: @ 202F2E8 - .space 0x10 +gUnknown_202F2E8 = .; /* 202F2E8 */ + . += 0x10; -gUnknown_202F2F8: @ 202F2F8 - .space 0x4 +gUnknown_202F2F8 = .; /* 202F2F8 */ + . += 0x4; -gUnknown_202F2FC: @ 202F2FC - .space 0x4 +gUnknown_202F2FC = .; /* 202F2FC */ + . += 0x4; -gUnknown_202F300: @ 202F300 - .space 0x8 +gUnknown_202F300 = .; /* 202F300 */ + . += 0x8; -gUnknown_202F308: @ 202F308 - .space 0x4 +gUnknown_202F308 = .; /* 202F308 */ + . += 0x4; -gUnknown_202F30C: @ 202F30C - .space 0x4 +gUnknown_202F30C = .; /* 202F30C */ + . += 0x4; -gUnknown_202F310: @ 202F310 - .space 0x4 +gUnknown_202F310 = .; /* 202F310 */ + . += 0x4; -gUnknown_202F314: @ 202F314 - .space 0x8 +gUnknown_202F314 = .; /* 202F314 */ + . += 0x8; -gUnknown_202F31C: @ 202F31C - .space 0x8 +gUnknown_202F31C = .; /* 202F31C */ + . += 0x8; -gUnknown_202F324: @ 202F324 - .space 0x8 +gUnknown_202F324 = .; /* 202F324 */ + . += 0x8; -gUnknown_202F32C: @ 202F32C - .space 0x1 +gUnknown_202F32C = .; /* 202F32C */ + . += 0x1; -gUnknown_202F32D: @ 202F32D - .space 0x3 +gUnknown_202F32D = .; /* 202F32D */ + . += 0x3; -gUnknown_202F330: @ 202F330 - .space 0x20 +gUnknown_202F330 = .; /* 202F330 */ + . += 0x20; -gUnknown_202F350: @ 202F350 - .space 0x8 +gUnknown_202F350 = .; /* 202F350 */ + . += 0x8; -gUnknown_202F358: @ 202F358 - .space 0x20 +gUnknown_202F358 = .; /* 202F358 */ + . += 0x20; -gUnknown_202F378: @ 202F378 - .space 0x8 +gUnknown_202F378 = .; /* 202F378 */ + . += 0x8; -gUnknown_202F380: @ 202F380 - .space 0x8 +gUnknown_202F380 = .; /* 202F380 */ + . += 0x8; -gUnknown_202F388: @ 202F388 - .space 0x8 +gUnknown_202F388 = .; /* 202F388 */ + . += 0x8; -gUnknown_202F390: @ 202F390 - .space 0x20 +gUnknown_202F390 = .; /* 202F390 */ + . += 0x20; -gUnknown_202F3B0: @ 202F3B0 - .space 0x20 +gUnknown_202F3B0 = .; /* 202F3B0 */ + . += 0x20; -gUnknown_202F3D0: @ 202F3D0 - .space 0x8 +gUnknown_202F3D0 = .; /* 202F3D0 */ + . += 0x8; -gUnknown_202F3D8: @ 202F3D8 - .space 0x8 +gUnknown_202F3D8 = .; /* 202F3D8 */ + . += 0x8; -gUnknown_202F3E0: @ 202F3E0 - .space 0x4 +gUnknown_202F3E0 = .; /* 202F3E0 */ + . += 0x4; -gUnknown_202F3E4: @ 202F3E4 - .space 0x4 +gUnknown_202F3E4 = .; /* 202F3E4 */ + . += 0x4; -gUnknown_202F3E8: @ 202F3E8 - .space 0x18 +gUnknown_202F3E8 = .; /* 202F3E8 */ + . += 0x18; -gUnknown_202F400: @ 202F400 - .space 0x90E8 +gUnknown_202F400 = .; /* 202F400 */ + . += 0x90E8; -gUnknown_20384E8: @ 20384E8 - .space 0x8 +gUnknown_20384E8 = .; /* 20384E8 */ + . += 0x8; -gUnknown_20384F0: @ 20384F0 - .space 0x4B0 +gUnknown_20384F0 = .; /* 20384F0 */ + . += 0x4B0; -gUnknown_20389A0: @ 20389A0 - .space 0x4 +gUnknown_20389A0 = .; /* 20389A0 */ + . += 0x4; -gUnknown_20389A4: @ 20389A4 - .space 0x4 +gUnknown_20389A4 = .; /* 20389A4 */ + . += 0x4; -gUnknown_20389A8: @ 20389A8 - .space 0x268 +gUnknown_20389A8 = .; /* 20389A8 */ + . += 0x268; -gUnknown_2038C10: @ 2038C10 - .space 0x18 +gUnknown_2038C10 = .; /* 2038C10 */ + . += 0x18; -gUnknown_2038C28: @ 2038C28 - .space 0x3C +gUnknown_2038C28 = .; /* 2038C28 */ + . += 0x3C; -gUnknown_2038C64: @ 2038C64 - .space 0x4 +gUnknown_2038C64 = .; /* 2038C64 */ + . += 0x4; -gUnknown_2038C68: @ 2038C68 - .space 0x4 +gUnknown_2038C68 = .; /* 2038C68 */ + . += 0x4; -gUnknown_2038C6C: @ 2038C6C - .space 0x4 +gUnknown_2038C6C = .; /* 2038C6C */ + . += 0x4; -gUnknown_2038C70: @ 2038C70 - .space 0x10 +gUnknown_2038C70 = .; /* 2038C70 */ + . += 0x10; -gUnknown_2038C80: @ 2038C80 - .space 0x8 +gUnknown_2038C80 = .; /* 2038C80 */ + . += 0x8; -gUnknown_2038C88: @ 2038C88 - .space 0x600 +gUnknown_2038C88 = .; /* 2038C88 */ + . += 0x600; -gUnknown_2039288: @ 2039288 - .space 0x60 +gUnknown_2039288 = .; /* 2039288 */ + . += 0x60; -gUnknown_20392E8: @ 20392E8 - .space 0xD8 +gUnknown_20392E8 = .; /* 20392E8 */ + . += 0xD8; -gUnknown_20393C0: @ 20393C0 - .space 0x88 +gUnknown_20393C0 = .; /* 20393C0 */ + . += 0x88; -gUnknown_2039448: @ 2039448 - .space 0x330 +gUnknown_2039448 = .; /* 2039448 */ + . += 0x330; -gUnknown_2039778: @ 2039778 - .space 0xC8 +gUnknown_2039778 = .; /* 2039778 */ + . += 0xC8; -gUnknown_2039840: @ 2039840 - .space 0x68 +gUnknown_2039840 = .; /* 2039840 */ + . += 0x68; -gUnknown_20398A8: @ 20398A8 - .space 0x4 +gUnknown_20398A8 = .; /* 20398A8 */ + . += 0x4; -gUnknown_20398AC: @ 20398AC - .space 0x4 +gUnknown_20398AC = .; /* 20398AC */ + . += 0x4; -gUnknown_20398B0: @ 20398B0 - .space 0x4 +gUnknown_20398B0 = .; /* 20398B0 */ + . += 0x4; -gUnknown_20398B4: @ 20398B4 - .space 0x4 +gUnknown_20398B4 = .; /* 20398B4 */ + . += 0x4; -gUnknown_20398B8: @ 20398B8 - .space 0x1 +gUnknown_20398B8 = .; /* 20398B8 */ + . += 0x1; -gUnknown_20398B9: @ 20398B9 - .space 0x1 +gUnknown_20398B9 = .; /* 20398B9 */ + . += 0x1; -gUnknown_20398BA: @ 20398BA - .space 0x2 +gUnknown_20398BA = .; /* 20398BA */ + . += 0x2; -gUnknown_20398BC: @ 20398BC - .space 0x2 +gUnknown_20398BC = .; /* 20398BC */ + . += 0x2; -gUnknown_20398BE: @ 20398BE - .space 0x2 +gUnknown_20398BE = .; /* 20398BE */ + . += 0x2; -gUnknown_20398C0: @ 20398C0 - .space 0x4 +gUnknown_20398C0 = .; /* 20398C0 */ + . += 0x4; -gUnknown_20398C4: @ 20398C4 - .space 0x4 +gUnknown_20398C4 = .; /* 20398C4 */ + . += 0x4; -gUnknown_20398C8: @ 20398C8 - .space 0x10 +gUnknown_20398C8 = .; /* 20398C8 */ + . += 0x10; -gUnknown_20398D8: @ 20398D8 - .space 0x78 +gUnknown_20398D8 = .; /* 20398D8 */ + . += 0x78; -gUnknown_2039950: @ 2039950 - .space 0x8 +gUnknown_2039950 = .; /* 2039950 */ + . += 0x8; -gUnknown_2039958: @ 2039958 - .space 0x10 +gUnknown_2039958 = .; /* 2039958 */ + . += 0x10; -gUnknown_2039968: @ 2039968 - .space 0x10 +gUnknown_2039968 = .; /* 2039968 */ + . += 0x10; -gUnknown_2039978: @ 2039978 - .space 0x8 +gUnknown_2039978 = .; /* 2039978 */ + . += 0x8; -gUnknown_2039980: @ 2039980 - .space 0x10 +gUnknown_2039980 = .; /* 2039980 */ + . += 0x10; -gUnknown_2039990: @ 2039990 - .space 0x2 +gUnknown_2039990 = .; /* 2039990 */ + . += 0x2; -gUnknown_2039992: @ 2039992 - .space 0x6 +gUnknown_2039992 = .; /* 2039992 */ + . += 0x6; -gUnknown_2039998: @ 2039998 - .space 0x44 +gUnknown_2039998 = .; /* 2039998 */ + . += 0x44; -gUnknown_20399DC: @ 20399DC - .space 0x2 +gUnknown_20399DC = .; /* 20399DC */ + . += 0x2; -gUnknown_20399DE: @ 20399DE - .space 0x2 +gUnknown_20399DE = .; /* 20399DE */ + . += 0x2; -gUnknown_20399E0: @ 20399E0 - .space 0x8 +gUnknown_20399E0 = .; /* 20399E0 */ + . += 0x8; -gUnknown_20399E8: @ 20399E8 - .space 0x14 +gUnknown_20399E8 = .; /* 20399E8 */ + . += 0x14; -gUnknown_20399FC: @ 20399FC - .space 0x34 +gUnknown_20399FC = .; /* 20399FC */ + . += 0x34; -gUnknown_2039A30: @ 2039A30 - .space 0x2 +gUnknown_2039A30 = .; /* 2039A30 */ + . += 0x2; -gUnknown_2039A32: @ 2039A32 - .space 0x2 +gUnknown_2039A32 = .; /* 2039A32 */ + . += 0x2; -gUnknown_2039A34: @ 2039A34 - .space 0x2 +gUnknown_2039A34 = .; /* 2039A34 */ + . += 0x2; -gUnknown_2039A36: @ 2039A36 - .space 0x2 +gUnknown_2039A36 = .; /* 2039A36 */ + . += 0x2; -gUnknown_2039A38: @ 2039A38 - .space 0x88 +gUnknown_2039A38 = .; /* 2039A38 */ + . += 0x88; -gUnknown_2039AC0: @ 2039AC0 - .space 0x88 +gUnknown_2039AC0 = .; /* 2039AC0 */ + . += 0x88; -gUnknown_2039B48: @ 2039B48 - .space 0x208 +gUnknown_2039B48 = .; /* 2039B48 */ + . += 0x208; -gUnknown_2039D50: @ 2039D50 - .space 0x48 +gUnknown_2039D50 = .; /* 2039D50 */ + . += 0x48; -gUnknown_2039D98: @ 2039D98 - .space 0xC +gUnknown_2039D98 = .; /* 2039D98 */ + . += 0xC; -gUnknown_2039DA4: @ 2039DA4 - .space 0x4 +gUnknown_2039DA4 = .; /* 2039DA4 */ + . += 0x4; -gUnknown_2039DA8: @ 2039DA8 - .space 0x8 +gUnknown_2039DA8 = .; /* 2039DA8 */ + . += 0x8; -gUnknown_2039DB0: @ 2039DB0 - .space 0x10 +gUnknown_2039DB0 = .; /* 2039DB0 */ + . += 0x10; -gUnknown_2039DC0: @ 2039DC0 - .space 0xC +gUnknown_2039DC0 = .; /* 2039DC0 */ + . += 0xC; -gUnknown_2039DCC: @ 2039DCC - .space 0x2 +gUnknown_2039DCC = .; /* 2039DCC */ + . += 0x2; -gUnknown_2039DCE: @ 2039DCE - .space 0x2 +gUnknown_2039DCE = .; /* 2039DCE */ + . += 0x2; -gUnknown_2039DD0: @ 2039DD0 - .space 0x4 +gUnknown_2039DD0 = .; /* 2039DD0 */ + . += 0x4; -gUnknown_2039DD4: @ 2039DD4 - .space 0x4 +gUnknown_2039DD4 = .; /* 2039DD4 */ + . += 0x4; -gUnknown_2039DD8: @ 2039DD8 - .space 0x8 +gUnknown_2039DD8 = .; /* 2039DD8 */ + . += 0x8; -gUnknown_2039DE0: @ 2039DE0 - .space 0x4 +gUnknown_2039DE0 = .; /* 2039DE0 */ + . += 0x4; diff --git a/sym_ewram2.txt b/sym_ewram2.txt index ad9521d..5df20ac 100644 --- a/sym_ewram2.txt +++ b/sym_ewram2.txt @@ -1,654 +1,654 @@ - .align 2 + . = ALIGN(2); -gUnknown_2039ED0: @ 2039ED0 - .space 0xFB0 +gUnknown_2039ED0 = .; /* 2039ED0 */ + . += 0xFB0; -gUnknown_203AE80: @ 203AE80 - .space 0x4 +gUnknown_203AE80 = .; /* 203AE80 */ + . += 0x4; -gUnknown_203AE84: @ 203AE84 - .space 0x84 +gUnknown_203AE84 = .; /* 203AE84 */ + . += 0x84; -gUnknown_203AF08: @ 203AF08 - .space 0x4 +gUnknown_203AF08 = .; /* 203AF08 */ + . += 0x4; -gUnknown_203AF0C: @ 203AF0C - .space 0x4 +gUnknown_203AF0C = .; /* 203AF0C */ + . += 0x4; -gUnknown_203AF10: @ 203AF10 - .space 0x100 +gUnknown_203AF10 = .; /* 203AF10 */ + . += 0x100; -gFlashTimeoutFlag: @ 203B010 - .space 0x4 +gFlashTimeoutFlag = .; /* 203B010 */ + . += 0x4; -PollFlashStatus: @ 203B014 - .space 0x4 +PollFlashStatus = .; /* 203B014 */ + . += 0x4; -WaitForFlashWrite: @ 203B018 - .space 0x4 +WaitForFlashWrite = .; /* 203B018 */ + . += 0x4; -ProgramFlashSector: @ 203B01C - .space 0x4 +ProgramFlashSector = .; /* 203B01C */ + . += 0x4; -gFlash: @ 203B020 - .space 0x4 +gFlash = .; /* 203B020 */ + . += 0x4; -gFlashNumRemainingBytes: @ 203B024 - .space 0x4 +gFlashNumRemainingBytes = .; /* 203B024 */ + . += 0x4; -EraseFlashChip: @ 203B028 - .space 0x4 +EraseFlashChip = .; /* 203B028 */ + . += 0x4; -EraseFlashSector: @ 203B02C - .space 0x4 +EraseFlashSector = .; /* 203B02C */ + . += 0x4; -gFlashMaxTime: @ 203B030 - .space 0x4 +gFlashMaxTime = .; /* 203B030 */ + . += 0x4; -errno: @ 203B034 - .space 0x4 +errno = .; /* 203B034 */ + . += 0x4; -alt_203B038: +alt_203B038 = .; -gUnknown_203B038: @ 203B038 - .space 0x4 +gUnknown_203B038 = .; /* 203B038 */ + . += 0x4; -gUnknown_203B03C: @ 203B03C - .space 0x4 +gUnknown_203B03C = .; /* 203B03C */ + . += 0x4; -gUnknown_203B040: @ 203B040 - .space 0x30 +gUnknown_203B040 = .; /* 203B040 */ + . += 0x30; -gOtherRngState: @ 203B070 - .space 0x4 +gOtherRngState = .; /* 203B070 */ + . += 0x4; -gUnknown_203B074: @ 203B074 - .space 0x4 +gUnknown_203B074 = .; /* 203B074 */ + . += 0x4; -gUnknown_203B078: @ 203B078 - .space 0x4 +gUnknown_203B078 = .; /* 203B078 */ + . += 0x4; -gRngState: @ 203B07C - .space 0x4 +gRngState = .; /* 203B07C */ + . += 0x4; -gUnknown_203B080: @ 203B080 - .space 0x4 +gUnknown_203B080 = .; /* 203B080 */ + . += 0x4; -gUnknown_203B084: @ 203B084 - .space 0x4 +gUnknown_203B084 = .; /* 203B084 */ + . += 0x4; -gUnknown_203B088: @ 203B088 - .space 0x4 +gUnknown_203B088 = .; /* 203B088 */ + . += 0x4; -gUnknown_203B08C: @ 203B08C - .space 0x4 +gUnknown_203B08C = .; /* 203B08C */ + . += 0x4; -gUnknown_203B090: @ 203B090 - .space 0x4 +gUnknown_203B090 = .; /* 203B090 */ + . += 0x4; -gUnknown_203B094: @ 203B094 - .space 0x4 +gUnknown_203B094 = .; /* 203B094 */ + . += 0x4; -gUnknown_203B098: @ 203B098 - .space 0x1 +gUnknown_203B098 = .; /* 203B098 */ + . += 0x1; -gUnknown_203B099: @ 203B099 - .space 0x1 +gUnknown_203B099 = .; /* 203B099 */ + . += 0x1; -gUnknown_203B09A: @ 203B09A - .space 0x1 +gUnknown_203B09A = .; /* 203B09A */ + . += 0x1; -gUnknown_203B09B: @ 203B09B - .space 0x1 +gUnknown_203B09B = .; /* 203B09B */ + . += 0x1; -gUnknown_203B09C: @ 203B09C - .space 0x4 +gUnknown_203B09C = .; /* 203B09C */ + . += 0x4; -gUnknown_203B0A0: @ 203B0A0 - .space 0x4 +gUnknown_203B0A0 = .; /* 203B0A0 */ + . += 0x4; -gUnknown_203B0A4: @ 203B0A4 - .space 0x4 +gUnknown_203B0A4 = .; /* 203B0A4 */ + . += 0x4; -gUnknown_203B0A8: @ 203B0A8 - .space 0x2 +gUnknown_203B0A8 = .; /* 203B0A8 */ + . += 0x2; -gUnknown_203B0AA: @ 203B0AA - .space 0x2 +gUnknown_203B0AA = .; /* 203B0AA */ + . += 0x2; -gUnknown_203B0AC: @ 203B0AC - .space 0x2 +gUnknown_203B0AC = .; /* 203B0AC */ + . += 0x2; -gUnknown_203B0AE: @ 203B0AE - .space 0x2 +gUnknown_203B0AE = .; /* 203B0AE */ + . += 0x2; -gUnknown_203B0B0: @ 203B0B0 - .space 0x2 +gUnknown_203B0B0 = .; /* 203B0B0 */ + . += 0x2; -gUnknown_203B0B2: @ 203B0B2 - .space 0x2 +gUnknown_203B0B2 = .; /* 203B0B2 */ + . += 0x2; -gFlashEnabled: @ 203B0B4 - .space 0x4 +gFlashEnabled = .; /* 203B0B4 */ + . += 0x4; -gUnknown_203B0B8: @ 203B0B8 - .space 0x4 +gUnknown_203B0B8 = .; /* 203B0B8 */ + . += 0x4; -gUnknown_203B0BC: @ 203B0BC - .space 0x2 +gUnknown_203B0BC = .; /* 203B0BC */ + . += 0x2; -gUnknown_203B0BE: @ 203B0BE - .space 0xE +gUnknown_203B0BE = .; /* 203B0BE */ + . += 0xE; -gUnknown_203B0CC: @ 203B0CC - .space 0x4 +gUnknown_203B0CC = .; /* 203B0CC */ + . += 0x4; -gUnknown_203B0D0: @ 203B0D0 - .space 0x4 +gUnknown_203B0D0 = .; /* 203B0D0 */ + . += 0x4; -gUnknown_203B0D4: @ 203B0D4 - .space 0x4 +gUnknown_203B0D4 = .; /* 203B0D4 */ + . += 0x4; -gUnknown_203B0D8: @ 203B0D8 - .space 0x4 +gUnknown_203B0D8 = .; /* 203B0D8 */ + . += 0x4; -gUnknown_203B0DC: @ 203B0DC - .space 0x8 +gUnknown_203B0DC = .; /* 203B0DC */ + . += 0x8; -gUnknown_203B0E4: @ 203B0E4 - .space 0x4 +gUnknown_203B0E4 = .; /* 203B0E4 */ + . += 0x4; -gUnknown_203B0E8: @ 203B0E8 - .space 0x4 +gUnknown_203B0E8 = .; /* 203B0E8 */ + . += 0x4; -gUnknown_203B0EC: @ 203B0EC - .space 0x60 +gUnknown_203B0EC = .; /* 203B0EC */ + . += 0x60; -gUnknown_203B14C: @ 203B14C - .space 0x4 +gUnknown_203B14C = .; /* 203B14C */ + . += 0x4; -gUnknown_203B150: @ 203B150 - .space 0x2C +gUnknown_203B150 = .; /* 203B150 */ + . += 0x2C; -gUnknown_203B17C: @ 203B17C - .space 0x4 +gUnknown_203B17C = .; /* 203B17C */ + . += 0x4; -gUnknown_203B180: @ 203B180 - .space 0x4 +gUnknown_203B180 = .; /* 203B180 */ + . += 0x4; -gUnknown_203B184: @ 203B184 - .space 0x4 +gUnknown_203B184 = .; /* 203B184 */ + . += 0x4; -gUnknown_203B188: @ 203B188 - .space 0x4 +gUnknown_203B188 = .; /* 203B188 */ + . += 0x4; -gUnknown_203B18C: @ 203B18C - .space 0x4 +gUnknown_203B18C = .; /* 203B18C */ + . += 0x4; -gUnknown_203B190: @ 203B190 - .space 0x4 +gUnknown_203B190 = .; /* 203B190 */ + . += 0x4; -gUnknown_203B194: @ 203B194 - .space 0x4 +gUnknown_203B194 = .; /* 203B194 */ + . += 0x4; -gUnknown_203B198: @ 203B198 - .space 0x60 +gUnknown_203B198 = .; /* 203B198 */ + . += 0x60; -gUnknown_203B1F8: @ 203B1F8 - .space 0x4 +gUnknown_203B1F8 = .; /* 203B1F8 */ + . += 0x4; -gUnknown_203B1FC: @ 203B1FC - .space 0x4 +gUnknown_203B1FC = .; /* 203B1FC */ + . += 0x4; -gUnknown_203B200: @ 203B200 - .space 0x4 +gUnknown_203B200 = .; /* 203B200 */ + . += 0x4; -gUnknown_203B204: @ 203B204 - .space 0x4 +gUnknown_203B204 = .; /* 203B204 */ + . += 0x4; -gUnknown_203B208: @ 203B208 - .space 0x4 +gUnknown_203B208 = .; /* 203B208 */ + . += 0x4; -gUnknown_203B20C: @ 203B20C - .space 0x4 +gUnknown_203B20C = .; /* 203B20C */ + . += 0x4; -gUnknown_203B210: @ 203B210 - .space 0x4 +gUnknown_203B210 = .; /* 203B210 */ + . += 0x4; -gUnknown_203B214: @ 203B214 - .space 0x4 +gUnknown_203B214 = .; /* 203B214 */ + . += 0x4; -gUnknown_203B218: @ 203B218 - .space 0x4 +gUnknown_203B218 = .; /* 203B218 */ + . += 0x4; -gUnknown_203B21C: @ 203B21C - .space 0x4 +gUnknown_203B21C = .; /* 203B21C */ + . += 0x4; -gUnknown_203B220: @ 203B220 - .space 0x4 +gUnknown_203B220 = .; /* 203B220 */ + . += 0x4; -gUnknown_203B224: @ 203B224 - .space 0x4 +gUnknown_203B224 = .; /* 203B224 */ + . += 0x4; -gUnknown_203B228: @ 203B228 - .space 0x2 +gUnknown_203B228 = .; /* 203B228 */ + . += 0x2; -gUnknown_203B22A: @ 203B22A - .space 0x2 +gUnknown_203B22A = .; /* 203B22A */ + . += 0x2; -gUnknown_203B22C: @ 203B22C - .space 0x4 +gUnknown_203B22C = .; /* 203B22C */ + . += 0x4; -gUnknown_203B230: @ 203B230 - .space 0x4 +gUnknown_203B230 = .; /* 203B230 */ + . += 0x4; -gUnknown_203B234: @ 203B234 - .space 0x4 +gUnknown_203B234 = .; /* 203B234 */ + . += 0x4; -gUnknown_203B238: @ 203B238 - .space 0x4 +gUnknown_203B238 = .; /* 203B238 */ + . += 0x4; -gUnknown_203B23C: @ 203B23C - .space 0x4 +gUnknown_203B23C = .; /* 203B23C */ + . += 0x4; -gUnknown_203B240: @ 203B240 - .space 0x4 +gUnknown_203B240 = .; /* 203B240 */ + . += 0x4; -gUnknown_203B244: @ 203B244 - .space 0x4 +gUnknown_203B244 = .; /* 203B244 */ + . += 0x4; -gUnknown_203B248: @ 203B248 - .space 0x4 +gUnknown_203B248 = .; /* 203B248 */ + . += 0x4; -gUnknown_203B24C: @ 203B24C - .space 0x2 +gUnknown_203B24C = .; /* 203B24C */ + . += 0x2; -gUnknown_203B24E: @ 203B24E - .space 0x2 +gUnknown_203B24E = .; /* 203B24E */ + . += 0x2; -gUnknown_203B250: @ 203B250 - .space 0x4 +gUnknown_203B250 = .; /* 203B250 */ + . += 0x4; -gUnknown_203B254: @ 203B254 - .space 0x4 +gUnknown_203B254 = .; /* 203B254 */ + . += 0x4; -gUnknown_203B258: @ 203B258 - .space 0x4 +gUnknown_203B258 = .; /* 203B258 */ + . += 0x4; -gUnknown_203B25C: @ 203B25C - .space 0x4 +gUnknown_203B25C = .; /* 203B25C */ + . += 0x4; -gUnknown_203B260: @ 203B260 - .space 0x4 +gUnknown_203B260 = .; /* 203B260 */ + . += 0x4; -gUnknown_203B264: @ 203B264 - .space 0x4 +gUnknown_203B264 = .; /* 203B264 */ + . += 0x4; -gUnknown_203B268: @ 203B268 - .space 0x4 +gUnknown_203B268 = .; /* 203B268 */ + . += 0x4; -gUnknown_203B26C: @ 203B26C - .space 0x4 +gUnknown_203B26C = .; /* 203B26C */ + . += 0x4; -gUnknown_203B270: @ 203B270 - .space 0x4 +gUnknown_203B270 = .; /* 203B270 */ + . += 0x4; -gUnknown_203B274: @ 203B274 - .space 0x4 +gUnknown_203B274 = .; /* 203B274 */ + . += 0x4; -gUnknown_203B278: @ 203B278 - .space 0x4 +gUnknown_203B278 = .; /* 203B278 */ + . += 0x4; -gUnknown_203B27C: @ 203B27C - .space 0x4 +gUnknown_203B27C = .; /* 203B27C */ + . += 0x4; -gUnknown_203B280: @ 203B280 - .space 0x4 +gUnknown_203B280 = .; /* 203B280 */ + . += 0x4; -gUnknown_203B284: @ 203B284 - .space 0x4 +gUnknown_203B284 = .; /* 203B284 */ + . += 0x4; -gUnknown_203B288: @ 203B288 - .space 0x2 +gUnknown_203B288 = .; /* 203B288 */ + . += 0x2; -gUnknown_203B28A: @ 203B28A - .space 0x2 +gUnknown_203B28A = .; /* 203B28A */ + . += 0x2; -gUnknown_203B28C: @ 203B28C - .space 0x4 +gUnknown_203B28C = .; /* 203B28C */ + . += 0x4; -gUnknown_203B290: @ 203B290 - .space 0x4 +gUnknown_203B290 = .; /* 203B290 */ + . += 0x4; -gUnknown_203B294: @ 203B294 - .space 0x4 +gUnknown_203B294 = .; /* 203B294 */ + . += 0x4; -gUnknown_203B298: @ 203B298 - .space 0x4 +gUnknown_203B298 = .; /* 203B298 */ + . += 0x4; -gUnknown_203B29C: @ 203B29C - .space 0x2 +gUnknown_203B29C = .; /* 203B29C */ + . += 0x2; -gUnknown_203B29E: @ 203B29E - .space 0x2 +gUnknown_203B29E = .; /* 203B29E */ + . += 0x2; -gUnknown_203B2A0: @ 203B2A0 - .space 0x4 +gUnknown_203B2A0 = .; /* 203B2A0 */ + . += 0x4; -gUnknown_203B2A4: @ 203B2A4 - .space 0x4 +gUnknown_203B2A4 = .; /* 203B2A4 */ + . += 0x4; -gUnknown_203B2A8: @ 203B2A8 - .space 0x2 +gUnknown_203B2A8 = .; /* 203B2A8 */ + . += 0x2; -gUnknown_203B2AA: @ 203B2AA - .space 0x2 +gUnknown_203B2AA = .; /* 203B2AA */ + . += 0x2; -gUnknown_203B2AC: @ 203B2AC - .space 0x4 +gUnknown_203B2AC = .; /* 203B2AC */ + . += 0x4; -gUnknown_203B2B0: @ 203B2B0 - .space 0x4 +gUnknown_203B2B0 = .; /* 203B2B0 */ + . += 0x4; -gUnknown_203B2B4: @ 203B2B4 - .space 0x4 +gUnknown_203B2B4 = .; /* 203B2B4 */ + . += 0x4; -gUnknown_203B2B8: @ 203B2B8 - .space 0x4 +gUnknown_203B2B8 = .; /* 203B2B8 */ + . += 0x4; -gUnknown_203B2BC: @ 203B2BC - .space 0x4 +gUnknown_203B2BC = .; /* 203B2BC */ + . += 0x4; -gUnknown_203B2C0: @ 203B2C0 - .space 0x4 +gUnknown_203B2C0 = .; /* 203B2C0 */ + . += 0x4; -gUnknown_203B2C4: @ 203B2C4 - .space 0x4 +gUnknown_203B2C4 = .; /* 203B2C4 */ + . += 0x4; -gUnknown_203B2C8: @ 203B2C8 - .space 0x4 +gUnknown_203B2C8 = .; /* 203B2C8 */ + . += 0x4; -gUnknown_203B2CC: @ 203B2CC - .space 0x4 +gUnknown_203B2CC = .; /* 203B2CC */ + . += 0x4; -gUnknown_203B2D0: @ 203B2D0 - .space 0x2 +gUnknown_203B2D0 = .; /* 203B2D0 */ + . += 0x2; -gUnknown_203B2D2: @ 203B2D2 - .space 0x2 +gUnknown_203B2D2 = .; /* 203B2D2 */ + . += 0x2; -gUnknown_203B2D4: @ 203B2D4 - .space 0x4 +gUnknown_203B2D4 = .; /* 203B2D4 */ + . += 0x4; -gUnknown_203B2D8: @ 203B2D8 - .space 0x4 +gUnknown_203B2D8 = .; /* 203B2D8 */ + . += 0x4; -gUnknown_203B2DC: @ 203B2DC - .space 0x4 +gUnknown_203B2DC = .; /* 203B2DC */ + . += 0x4; -gUnknown_203B2E0: @ 203B2E0 - .space 0x4 +gUnknown_203B2E0 = .; /* 203B2E0 */ + . += 0x4; -gUnknown_203B2E4: @ 203B2E4 - .space 0x4 +gUnknown_203B2E4 = .; /* 203B2E4 */ + . += 0x4; -gUnknown_203B2E8: @ 203B2E8 - .space 0x4 +gUnknown_203B2E8 = .; /* 203B2E8 */ + . += 0x4; -gUnknown_203B2EC: @ 203B2EC - .space 0x4 +gUnknown_203B2EC = .; /* 203B2EC */ + . += 0x4; -gUnknown_203B2F0: @ 203B2F0 - .space 0x4 +gUnknown_203B2F0 = .; /* 203B2F0 */ + . += 0x4; -gUnknown_203B2F4: @ 203B2F4 - .space 0x4 +gUnknown_203B2F4 = .; /* 203B2F4 */ + . += 0x4; -gUnknown_203B2F8: @ 203B2F8 - .space 0x4 +gUnknown_203B2F8 = .; /* 203B2F8 */ + . += 0x4; -gUnknown_203B2FC: @ 203B2FC - .space 0x4 +gUnknown_203B2FC = .; /* 203B2FC */ + . += 0x4; -gUnknown_203B300: @ 203B300 - .space 0x4 +gUnknown_203B300 = .; /* 203B300 */ + . += 0x4; -gUnknown_203B304: @ 203B304 - .space 0x4 +gUnknown_203B304 = .; /* 203B304 */ + . += 0x4; -gUnknown_203B308: @ 203B308 - .space 0x4 +gUnknown_203B308 = .; /* 203B308 */ + . += 0x4; -gUnknown_203B30C: @ 203B30C - .space 0x4 +gUnknown_203B30C = .; /* 203B30C */ + . += 0x4; -gUnknown_203B310: @ 203B310 - .space 0x4 +gUnknown_203B310 = .; /* 203B310 */ + . += 0x4; -gUnknown_203B314: @ 203B314 - .space 0x4 +gUnknown_203B314 = .; /* 203B314 */ + . += 0x4; -gUnknown_203B318: @ 203B318 - .space 0x4 +gUnknown_203B318 = .; /* 203B318 */ + . += 0x4; -gUnknown_203B31C: @ 203B31C - .space 0x4 +gUnknown_203B31C = .; /* 203B31C */ + . += 0x4; -gUnknown_203B320: @ 203B320 - .space 0x4 +gUnknown_203B320 = .; /* 203B320 */ + . += 0x4; -gUnknown_203B324: @ 203B324 - .space 0x4 +gUnknown_203B324 = .; /* 203B324 */ + . += 0x4; -gUnknown_203B328: @ 203B328 - .space 0x4 +gUnknown_203B328 = .; /* 203B328 */ + . += 0x4; -gUnknown_203B32C: @ 203B32C - .space 0x4 +gUnknown_203B32C = .; /* 203B32C */ + . += 0x4; -gUnknown_203B330: @ 203B330 - .space 0x4 +gUnknown_203B330 = .; /* 203B330 */ + . += 0x4; -gUnknown_203B334: @ 203B334 - .space 0x4 +gUnknown_203B334 = .; /* 203B334 */ + . += 0x4; -gUnknown_203B338: @ 203B338 - .space 0x4 +gUnknown_203B338 = .; /* 203B338 */ + . += 0x4; -gUnknown_203B33C: @ 203B33C - .space 0x4 +gUnknown_203B33C = .; /* 203B33C */ + . += 0x4; -gUnknown_203B340: @ 203B340 - .space 0x4 +gUnknown_203B340 = .; /* 203B340 */ + . += 0x4; -gUnknown_203B344: @ 203B344 - .space 0x4 +gUnknown_203B344 = .; /* 203B344 */ + . += 0x4; -gUnknown_203B348: @ 203B348 - .space 0x4 +gUnknown_203B348 = .; /* 203B348 */ + . += 0x4; -gUnknown_203B34C: @ 203B34C - .space 0x4 +gUnknown_203B34C = .; /* 203B34C */ + . += 0x4; -gUnknown_203B350: @ 203B350 - .space 0x4 +gUnknown_203B350 = .; /* 203B350 */ + . += 0x4; -gUnknown_203B354: @ 203B354 - .space 0x4 +gUnknown_203B354 = .; /* 203B354 */ + . += 0x4; -gUnknown_203B358: @ 203B358 - .space 0x4 +gUnknown_203B358 = .; /* 203B358 */ + . += 0x4; -gUnknown_203B35C: @ 203B35C - .space 0x4 +gUnknown_203B35C = .; /* 203B35C */ + . += 0x4; -gUnknown_203B360: @ 203B360 - .space 0x4 +gUnknown_203B360 = .; /* 203B360 */ + . += 0x4; -gUnknown_203B364: @ 203B364 - .space 0x4 +gUnknown_203B364 = .; /* 203B364 */ + . += 0x4; -gUnknown_203B368: @ 203B368 - .space 0x4 +gUnknown_203B368 = .; /* 203B368 */ + . += 0x4; -gUnknown_203B36C: @ 203B36C - .space 0x4 +gUnknown_203B36C = .; /* 203B36C */ + . += 0x4; -gUnknown_203B370: @ 203B370 - .space 0x4 +gUnknown_203B370 = .; /* 203B370 */ + . += 0x4; -gUnknown_203B374: @ 203B374 - .space 0x4 +gUnknown_203B374 = .; /* 203B374 */ + . += 0x4; -gUnknown_203B378: @ 203B378 - .space 0x10 +gUnknown_203B378 = .; /* 203B378 */ + . += 0x10; -gUnknown_203B388: @ 203B388 - .space 0x30 +gUnknown_203B388 = .; /* 203B388 */ + . += 0x30; -gUnknown_203B3B8: @ 203B3B8 - .space 0x30 +gUnknown_203B3B8 = .; /* 203B3B8 */ + . += 0x30; -gUnknown_203B3E8: @ 203B3E8 - .space 0x4 +gUnknown_203B3E8 = .; /* 203B3E8 */ + . += 0x4; -gUnknown_203B3EC: @ 203B3EC - .space 0x4 +gUnknown_203B3EC = .; /* 203B3EC */ + . += 0x4; -gUnknown_203B3F0: @ 203B3F0 - .space 0x4 +gUnknown_203B3F0 = .; /* 203B3F0 */ + . += 0x4; -gUnknown_203B3F4: @ 203B3F4 - .space 0x4 +gUnknown_203B3F4 = .; /* 203B3F4 */ + . += 0x4; -gUnknown_203B3F8: @ 203B3F8 - .space 0x4 +gUnknown_203B3F8 = .; /* 203B3F8 */ + . += 0x4; -gUnknown_203B3FC: @ 203B3FC - .space 0x4 +gUnknown_203B3FC = .; /* 203B3FC */ + . += 0x4; -gUnknown_203B400: @ 203B400 - .space 0x4 +gUnknown_203B400 = .; /* 203B400 */ + . += 0x4; -gUnknown_203B404: @ 203B404 - .space 0x4 +gUnknown_203B404 = .; /* 203B404 */ + . += 0x4; -gUnknown_203B408: @ 203B408 - .space 0x4 +gUnknown_203B408 = .; /* 203B408 */ + . += 0x4; -gUnknown_203B40C: @ 203B40C - .space 0x1 +gUnknown_203B40C = .; /* 203B40C */ + . += 0x1; -gUnknown_203B40D: @ 203B40D - .space 0x3 +gUnknown_203B40D = .; /* 203B40D */ + . += 0x3; -gUnknown_203B410: @ 203B410 - .space 0x4 +gUnknown_203B410 = .; /* 203B410 */ + . += 0x4; -gUnknown_203B414: @ 203B414 - .space 0x4 +gUnknown_203B414 = .; /* 203B414 */ + . += 0x4; -gUnknown_203B418: @ 203B418 - .space 0x4 +gUnknown_203B418 = .; /* 203B418 */ + . += 0x4; -gUnknown_203B41C: @ 203B41C - .space 0x4 +gUnknown_203B41C = .; /* 203B41C */ + . += 0x4; -gUnknown_203B420: @ 203B420 - .space 0x8 +gUnknown_203B420 = .; /* 203B420 */ + . += 0x8; -gUnknown_203B428: @ 203B428 - .space 0x8 +gUnknown_203B428 = .; /* 203B428 */ + . += 0x8; -gUnknown_203B430: @ 203B430 - .space 0x4 +gUnknown_203B430 = .; /* 203B430 */ + . += 0x4; -gUnknown_203B434: @ 203B434 - .space 0x4 +gUnknown_203B434 = .; /* 203B434 */ + . += 0x4; -gUnknown_203B438: @ 203B438 - .space 0x4 +gUnknown_203B438 = .; /* 203B438 */ + . += 0x4; -gUnknown_203B43C: @ 203B43C - .space 0x4 +gUnknown_203B43C = .; /* 203B43C */ + . += 0x4; -gUnknown_203B440: @ 203B440 - .space 0x4 +gUnknown_203B440 = .; /* 203B440 */ + . += 0x4; -gUnknown_203B444: @ 203B444 - .space 0xC +gUnknown_203B444 = .; /* 203B444 */ + . += 0xC; -gUnknown_203B450: @ 203B450 - .space 0x4 +gUnknown_203B450 = .; /* 203B450 */ + . += 0x4; -gUnknown_203B454: @ 203B454 - .space 0x4 +gUnknown_203B454 = .; /* 203B454 */ + . += 0x4; -gUnknown_203B458: @ 203B458 - .space 0x4 +gUnknown_203B458 = .; /* 203B458 */ + . += 0x4; -gUnknown_203B45C: @ 203B45C - .space 0x4 +gUnknown_203B45C = .; /* 203B45C */ + . += 0x4; -gUnknown_203B460: @ 203B460 - .space 0x4 +gUnknown_203B460 = .; /* 203B460 */ + . += 0x4; -gUnknown_203B464: @ 203B464 - .space 0x4 +gUnknown_203B464 = .; /* 203B464 */ + . += 0x4; -gUnknown_203B468: @ 203B468 - .space 0x4 +gUnknown_203B468 = .; /* 203B468 */ + . += 0x4; -gUnknown_203B46C: @ 203B46C - .space 0x4 +gUnknown_203B46C = .; /* 203B46C */ + . += 0x4; -gUnknown_203B470: @ 203B470 - .space 0x4 +gUnknown_203B470 = .; /* 203B470 */ + . += 0x4; -gUnknown_203B474: @ 203B474 - .space 0x8 +gUnknown_203B474 = .; /* 203B474 */ + . += 0x8; -gUnknown_203B47C: @ 203B47C - .space 0x4 +gUnknown_203B47C = .; /* 203B47C */ + . += 0x4; -gUnknown_203B480: @ 203B480 - .space 0x4 +gUnknown_203B480 = .; /* 203B480 */ + . += 0x4; -gUnknown_203B484: @ 203B484 - .space 0x4 +gUnknown_203B484 = .; /* 203B484 */ + . += 0x4; -gUnknown_203B488: @ 203B488 - .space 0x4 +gUnknown_203B488 = .; /* 203B488 */ + . += 0x4; -gUnknown_203B48C: @ 203B48C - .space 0x4 +gUnknown_203B48C = .; /* 203B48C */ + . += 0x4; -gUnknown_203B490: @ 203B490 - .space 0x4 +gUnknown_203B490 = .; /* 203B490 */ + . += 0x4; -gUnknown_203B494: @ 203B494 - .space 0x4 +gUnknown_203B494 = .; /* 203B494 */ + . += 0x4; -gUnknown_203B498: @ 203B498 - .space 0x4 +gUnknown_203B498 = .; /* 203B498 */ + . += 0x4; -gUnknown_203B49C: @ 203B49C - .space 0x1 +gUnknown_203B49C = .; /* 203B49C */ + . += 0x1; -gUnknown_203B49D: @ 203B49D - .space 0x3 +gUnknown_203B49D = .; /* 203B49D */ + . += 0x3; -gUnknown_203B4A0: @ 203B4A0 - .space 0xC +gUnknown_203B4A0 = .; /* 203B4A0 */ + . += 0xC; -gUnknown_203B4AC: @ 203B4AC - .space 0x4 +gUnknown_203B4AC = .; /* 203B4AC */ + . += 0x4; -gUnknown_203B4B0: @ 203B4B0 - .space 0x4 +gUnknown_203B4B0 = .; /* 203B4B0 */ + . += 0x4; -gUnknown_203B4B4: @ 203B4B4 - .space 0x4 +gUnknown_203B4B4 = .; /* 203B4B4 */ + . += 0x4; -gUnknown_203B4B8: @ 203B4B8 - .space 0x4 +gUnknown_203B4B8 = .; /* 203B4B8 */ + . += 0x4; diff --git a/sym_iwram.txt b/sym_iwram.txt index 918f767..4eafdc5 100644 --- a/sym_iwram.txt +++ b/sym_iwram.txt @@ -1,77 +1,77 @@ -SoundMainRAM_Buffer: @ 3000000 - .space 0x400 +SoundMainRAM_Buffer = .; /* 3000000 */ + . += 0x400; -gUnknown_3000400: @ 3000400 - .space 0x800 +gUnknown_3000400 = .; /* 3000400 */ + . += 0x800; -gUnknown_3000C00: @ 3000C00 - .space 0x294 +gUnknown_3000C00 = .; /* 3000C00 */ + . += 0x294; -gUnknown_3000E94: @ 3000E94 - .space 0x144 +gUnknown_3000E94 = .; /* 3000E94 */ + . += 0x144; -gUnknown_3000FD8: @ 3000FD8 - .space 0x10 +gUnknown_3000FD8 = .; /* 3000FD8 */ + . += 0x10; -gUnknown_3000FE8: @ 3000FE8 - .space 0x30 +gUnknown_3000FE8 = .; /* 3000FE8 */ + . += 0x30; -gUnknown_3001018: @ 3001018 - .space 0x180 +gUnknown_3001018 = .; /* 3001018 */ + . += 0x180; -gUnknown_3001198: @ 3001198 - .space 0x9C0 +gUnknown_3001198 = .; /* 3001198 */ + . += 0x9C0; -alt_3001B58: +alt_3001B58 = .; -unk_code_ram: @ 3001B58 +unk_code_ram = .; /* 3001B58 */ -gUnknown_3001B58: @ 3001B58 - .space 0x2 +gUnknown_3001B58 = .; /* 3001B58 */ + . += 0x2; -gUnknown_3001B5A: @ 3001B5A - .space 0x2 +gUnknown_3001B5A = .; /* 3001B5A */ + . += 0x2; -gUnknown_3001B5C: @ 3001B5C - .space 0x4 +gUnknown_3001B5C = .; /* 3001B5C */ + . += 0x4; -gUnknown_3001B60: @ 3001B60 - .space 0x4 +gUnknown_3001B60 = .; /* 3001B60 */ + . += 0x4; -gUnknown_3001B64: @ 3001B64 - .space 0x4 +gUnknown_3001B64 = .; /* 3001B64 */ + . += 0x4; -gUnknown_3001B68: @ 3001B68 - .space 0x4 +gUnknown_3001B68 = .; /* 3001B68 */ + . += 0x4; -gUnknown_3001B6C: @ 3001B6C - .space 0x4 +gUnknown_3001B6C = .; /* 3001B6C */ + . += 0x4; -gUnknown_3001B70: @ 3001B70 - .space 0x4 +gUnknown_3001B70 = .; /* 3001B70 */ + . += 0x4; -gUnknown_3001B74: @ 3001B74 - .space 0x4 +gUnknown_3001B74 = .; /* 3001B74 */ + . += 0x4; -gUnknown_3001B78: @ 3001B78 - .space 0x4 +gUnknown_3001B78 = .; /* 3001B78 */ + . += 0x4; -gUnknown_3001B7C: @ 3001B7C - .space 0x4 +gUnknown_3001B7C = .; /* 3001B7C */ + . += 0x4; -gUnknown_3001B80: @ 3001B80 - .space 0x4 +gUnknown_3001B80 = .; /* 3001B80 */ + . += 0x4; -gUnknown_3001B84: @ 3001B84 - .space 0x4 +gUnknown_3001B84 = .; /* 3001B84 */ + . += 0x4; -gUnknown_3001B88: @ 3001B88 - .space 0x4 +gUnknown_3001B88 = .; /* 3001B88 */ + . += 0x4; -gUnknown_3001B8C: @ 3001B8C - .space 0x4 +gUnknown_3001B8C = .; /* 3001B8C */ + . += 0x4; -gUnknown_3001B90: @ 3001B90 - .space 0x2470 +gUnknown_3001B90 = .; /* 3001B90 */ + . += 0x2470; -gUnknown_3004000: @ 3004000 +gUnknown_3004000 = .; /* 3004000 */ \ No newline at end of file -- cgit v1.2.3 From 961ab7ccaf4d175189cd42fcddca1336f3d91bad Mon Sep 17 00:00:00 2001 From: nullableVoidPtr <30564701+nullableVoidPtr@users.noreply.github.com> Date: Wed, 17 Oct 2018 11:28:27 +0800 Subject: Fix makefile and decompile some functions. Partial memory.c, save.c and bg_palette_buffer.c decompilation, along with some asm/ cleanup. --- Makefile | 1 - asm/bg_palette_buffer.s | 133 ++------------------------ asm/input.s | 94 ++++++++----------- asm/memory.s | 242 ++++++++---------------------------------------- asm/save.s | 68 -------------- ld_script.txt | 3 + src/bg_palette_buffer.c | 102 ++++++++++++++++++++ src/memory.c | 85 +++++++++++++++++ src/save.c | 45 +++++++++ sym_ewram.txt | 11 ++- 10 files changed, 326 insertions(+), 458 deletions(-) create mode 100644 src/bg_palette_buffer.c create mode 100644 src/memory.c create mode 100644 src/save.c diff --git a/Makefile b/Makefile index 0b86d1d..92e1edd 100755 --- a/Makefile +++ b/Makefile @@ -103,7 +103,6 @@ $(BUILD_DIR)/sym_%.ld: sym_%.txt $(C_OBJECTS): $(BUILD_DIR)/%.o: %.c @$(CPP) $(CPPFLAGS) $< -o $(BUILD_DIR)/$*.i - echo $(CC1) $(CC1FLAGS) $(BUILD_DIR)/$*.i -o $(BUILD_DIR)/$*.s @$(CC1) $(CC1FLAGS) $(BUILD_DIR)/$*.i -o $(BUILD_DIR)/$*.s @printf ".text\n\t.align\t2, 0\n" >> $(BUILD_DIR)/$*.s $(AS) $(ASFLAGS) -o $@ $(BUILD_DIR)/$*.s diff --git a/asm/bg_palette_buffer.s b/asm/bg_palette_buffer.s index 9b42ee5..9cafb43 100644 --- a/asm/bg_palette_buffer.s +++ b/asm/bg_palette_buffer.s @@ -9,7 +9,7 @@ InitBGPaletteBuffer: push {lr} movs r2, 0 - ldr r1, _0800465C + ldr r1, =gBGPaletteBuffer movs r0, 0x80 lsls r0, 2 _0800463E: @@ -18,7 +18,7 @@ _0800463E: subs r0, 0x1 cmp r0, 0 bne _0800463E - ldr r1, _08004660 + ldr r1, =gBGPaletteUsed movs r2, 0x1 adds r0, r1, 0 adds r0, 0x1F @@ -30,8 +30,7 @@ _08004650: pop {r0} bx r0 .align 2, 0 -_0800465C: .4byte gUnknown_20251F0 -_08004660: .4byte gUnknown_20251D0 + .pool thumb_func_end InitBGPaletteBuffer thumb_func_start SetBGPaletteBufferColorRGB @@ -47,7 +46,7 @@ _08004670: ble _08004676 movs r2, 0x1F _08004676: - ldr r1, _080046CC + ldr r1, =gBGPaletteUsed adds r0, r4, 0 cmp r4, 0 bge _08004680 @@ -59,7 +58,7 @@ _08004680: strb r1, [r0] cmp r3, 0 bne _080046D4 - ldr r0, _080046D0 + ldr r0, =gBGPaletteBuffer lsls r1, r4, 1 adds r6, r1, r0 ldrb r0, [r5, 0x2] @@ -94,10 +93,9 @@ _080046C0: strh r1, [r6] b _08004722 .align 2, 0 -_080046CC: .4byte gUnknown_20251D0 -_080046D0: .4byte gUnknown_20251F0 + .pool _080046D4: - ldr r1, _08004728 + ldr r1, =gBGPaletteBuffer lsls r0, r4, 1 adds r7, r0, r1 ldrb r0, [r5, 0x2] @@ -144,120 +142,7 @@ _08004722: pop {r0} bx r0 .align 2, 0 -_08004728: .4byte gUnknown_20251F0 + .pool thumb_func_end SetBGPaletteBufferColorRGB - thumb_func_start SetBGPaletteBufferColorArray -SetBGPaletteBufferColorArray: - push {lr} - adds r2, r0, 0 - adds r3, r1, 0 - ldr r1, _08004764 - cmp r2, 0 - bge _0800473A - adds r0, 0xF -_0800473A: - asrs r0, 4 - adds r0, r1 - movs r1, 0x1 - strb r1, [r0] - ldr r0, _08004768 - lsls r2, 1 - adds r2, r0 - ldrb r1, [r3, 0x2] - lsrs r1, 3 - lsls r1, 10 - ldrb r0, [r3, 0x1] - lsrs r0, 3 - lsls r0, 5 - orrs r1, r0 - ldrb r0, [r3] - lsrs r0, 3 - orrs r0, r1 - strh r0, [r2] - pop {r0} - bx r0 - .align 2, 0 -_08004764: .4byte gUnknown_20251D0 -_08004768: .4byte gUnknown_20251F0 - thumb_func_end SetBGPaletteBufferColorArray - - thumb_func_start SetBGPaletteBufferColor -SetBGPaletteBufferColor: - push {lr} - adds r2, r0, 0 - adds r3, r1, 0 - ldr r1, _08004790 - cmp r2, 0 - bge _0800477A - adds r0, 0xF -_0800477A: - asrs r0, 4 - adds r0, r1 - movs r1, 0x1 - strb r1, [r0] - ldr r1, _08004794 - lsls r0, r2, 1 - adds r0, r1 - ldrh r1, [r3] - strh r1, [r0] - pop {r0} - bx r0 - .align 2, 0 -_08004790: .4byte gUnknown_20251D0 -_08004794: .4byte gUnknown_20251F0 - thumb_func_end SetBGPaletteBufferColor - - thumb_func_start nullsub_4 -nullsub_4: - bx lr - thumb_func_end nullsub_4 - - thumb_func_start nullsub_5 -nullsub_5: - bx lr - thumb_func_end nullsub_5 - - thumb_func_start nullsub_143 -nullsub_143: - bx lr - thumb_func_end nullsub_143 - - thumb_func_start TransferBGPaletteBuffer -TransferBGPaletteBuffer: - push {r4-r6,lr} - movs r6, 0 - movs r4, 0 - movs r5, 0xA0 - lsls r5, 19 -_080047AE: - ldr r0, _080047DC - adds r1, r6, r0 - ldrb r0, [r1] - cmp r0, 0 - beq _080047CA - movs r0, 0 - strb r0, [r1] - lsls r1, r4, 1 - ldr r0, _080047E0 - adds r1, r0 - adds r0, r5, 0 - movs r2, 0x20 - bl CpuCopy -_080047CA: - adds r6, 0x1 - adds r5, 0x20 - adds r4, 0x10 - ldr r0, _080047E4 - cmp r4, r0 - ble _080047AE - pop {r4-r6} - pop {r0} - bx r0 - .align 2, 0 -_080047DC: .4byte gUnknown_20251D0 -_080047E0: .4byte gUnknown_20251F0 -_080047E4: .4byte 0x000001ff - thumb_func_end TransferBGPaletteBuffer - - .align 2, 0 @ Don't pad with nop. +.align 2, 0 @ Don't pad with nop. \ No newline at end of file diff --git a/asm/input.s b/asm/input.s index 7516a30..d439867 100644 --- a/asm/input.s +++ b/asm/input.s @@ -7,24 +7,24 @@ thumb_func_start InitInput InitInput: - ldr r0, _08004840 + ldr r0, =gUnknown_20255F0 movs r3, 0 movs r2, 0 strh r2, [r0] strh r2, [r0, 0x2] strh r2, [r0, 0x4] strh r2, [r0, 0x6] - ldr r0, _08004844 + ldr r0, =gUnknown_2025638 strh r2, [r0] strh r2, [r0, 0x2] strh r2, [r0, 0x4] strh r2, [r0, 0x6] - ldr r1, _08004848 - ldr r0, _0800484C + ldr r1, =gUnknown_202562C + ldr r0, =0x4a14c1 str r0, [r1] - ldr r0, _08004850 + ldr r0, =gUnknown_2025600 str r2, [r0, 0x20] - ldr r1, _08004854 + ldr r1, =0xffff strh r1, [r0] movs r1, 0x1 negs r1, r1 @@ -46,25 +46,19 @@ InitInput: strb r3, [r1] adds r0, 0x29 strb r3, [r0] - ldr r0, _08004858 + ldr r0, =gUnknown_2025668 strh r2, [r0] strh r2, [r0, 0x2] bx lr .align 2, 0 -_08004840: .4byte gUnknown_20255F0 -_08004844: .4byte gUnknown_2025638 -_08004848: .4byte gUnknown_202562C -_0800484C: .4byte 0x004a14c1 -_08004850: .4byte gUnknown_2025600 -_08004854: .4byte 0x0000ffff -_08004858: .4byte gUnknown_2025668 + .pool thumb_func_end InitInput thumb_func_start sub_800485C sub_800485C: push {r4,r5,lr} - ldr r2, _080048A8 - ldr r1, _080048AC + ldr r2, =gUnknown_2025638 + ldr r1, =gUnknown_20255F0 adds r0, r2, 0 ldm r0!, {r3-r5} stm r1!, {r3-r5} @@ -76,8 +70,8 @@ sub_800485C: strh r0, [r2, 0x2] strh r0, [r2, 0x4] strh r0, [r2, 0x6] - ldr r0, _080048B0 - ldr r1, _080048B4 + ldr r0, =gUnknown_2025600 + ldr r1, =0xffff strh r1, [r0] movs r1, 0x1 negs r1, r1 @@ -101,10 +95,7 @@ sub_800485C: pop {r0} bx r0 .align 2, 0 -_080048A8: .4byte gUnknown_2025638 -_080048AC: .4byte gUnknown_20255F0 -_080048B0: .4byte gUnknown_2025600 -_080048B4: .4byte 0x0000ffff + .pool thumb_func_end sub_800485C thumb_func_start sub_80048B8 @@ -145,49 +136,44 @@ sub_80048CC: thumb_func_start sub_80048D0 sub_80048D0: - ldr r1, _080048E8 + ldr r1, =gUnknown_20255F0 movs r0, 0 strh r0, [r1, 0x4] - ldr r1, _080048EC + ldr r1, =gUnknown_2025648 str r0, [r1, 0xC] strh r0, [r1, 0x8] - ldr r1, _080048F0 - ldr r0, _080048F4 + ldr r1, =gUnknown_2025668 + ldr r0, =0x3e7 strh r0, [r1] strh r0, [r1, 0x2] bx lr .align 2, 0 -_080048E8: .4byte gUnknown_20255F0 -_080048EC: .4byte gUnknown_2025648 -_080048F0: .4byte gUnknown_2025668 -_080048F4: .4byte 0x000003e7 + .pool thumb_func_end sub_80048D0 thumb_func_start sub_80048F8 sub_80048F8: - ldr r0, _08004908 + ldr r0, =gUnknown_20255F0 movs r1, 0 strh r1, [r0, 0x2] - ldr r0, _0800490C + ldr r0, =gUnknown_2025638 strh r1, [r0, 0x2] - ldr r0, _08004910 + ldr r0, =gUnknown_2025648 strh r1, [r0, 0x2] bx lr .align 2, 0 -_08004908: .4byte gUnknown_20255F0 -_0800490C: .4byte gUnknown_2025638 -_08004910: .4byte gUnknown_2025648 + .pool thumb_func_end sub_80048F8 thumb_func_start sub_8004914 sub_8004914: - ldr r0, _0800494C + ldr r0, =gUnknown_2025600 movs r1, 0x5 str r1, [r0, 0x20] movs r2, 0 movs r1, 0 strh r1, [r0, 0x24] - ldr r1, _08004950 + ldr r1, =0xffff strh r1, [r0] movs r1, 0x1 negs r1, r1 @@ -209,15 +195,14 @@ sub_8004914: strb r2, [r0] bx lr .align 2, 0 -_0800494C: .4byte gUnknown_2025600 -_08004950: .4byte 0x0000ffff + .pool thumb_func_end sub_8004914 thumb_func_start UpdateInput UpdateInput: push {r4-r6,lr} - ldr r4, _08004998 - ldr r5, _0800499C + ldr r4, =gUnknown_2025658 + ldr r5, =gUnknown_2025648 adds r1, r4, 0 adds r0, r5, 0 ldm r0!, {r2,r3,r6} @@ -249,8 +234,7 @@ UpdateInput: str r0, [r5, 0xC] b _080049AC .align 2, 0 -_08004998: .4byte gUnknown_2025658 -_0800499C: .4byte gUnknown_2025648 + .pool _080049A0: strh r2, [r5, 0x8] movs r0, 0x1 @@ -260,7 +244,7 @@ _080049A8: str r0, [r5, 0xC] strh r0, [r5, 0x8] _080049AC: - ldr r0, _080049C4 + ldr r0, =gUnknown_2025648 ldr r2, [r0, 0xC] adds r3, r0, 0 cmp r2, 0x1 @@ -273,7 +257,7 @@ _080049AC: strh r1, [r3, 0x4] b _080049E0 .align 2, 0 -_080049C4: .4byte gUnknown_2025648 + .pool _080049C8: cmp r2, 0x30 bne _080049DC @@ -300,7 +284,7 @@ _080049E0: lsrs r2, r0, 16 cmp r2, 0 beq _08004A0C - ldr r0, _08004A08 + ldr r0, =gUnknown_2025668 ldrh r2, [r0] movs r4, 0 ldrsh r1, [r0, r4] @@ -311,9 +295,9 @@ _080049E0: strh r0, [r4] b _08004A20 .align 2, 0 -_08004A08: .4byte gUnknown_2025668 + .pool _08004A0C: - ldr r1, _08004A44 + ldr r1, =gUnknown_2025668 ldrh r0, [r1] subs r0, 0x2 lsls r0, 16 @@ -343,7 +327,7 @@ _08004A20: strh r0, [r4, 0x2] b _08004A5E .align 2, 0 -_08004A44: .4byte gUnknown_2025668 + .pool _08004A48: ldrh r0, [r4, 0x2] subs r0, 0x2 @@ -358,7 +342,7 @@ _08004A48: _08004A5C: strh r2, [r4, 0x2] _08004A5E: - ldr r2, _08004A94 + ldr r2, =gUnknown_2025638 ldrh r0, [r2] ldrh r1, [r3] orrs r0, r1 @@ -375,9 +359,9 @@ _08004A5E: ldrh r1, [r3, 0x6] orrs r0, r1 strh r0, [r2, 0x6] - ldr r2, _08004A98 + ldr r2, =gUnknown_202562C ldrh r0, [r3] - ldr r1, _08004A9C + ldr r1, =0x054a1c41 orrs r0, r1 ldr r1, [r2] muls r0, r1 @@ -386,9 +370,7 @@ _08004A5E: pop {r0} bx r0 .align 2, 0 -_08004A94: .4byte gUnknown_2025638 -_08004A98: .4byte gUnknown_202562C -_08004A9C: .4byte 0x054a1c41 + .pool thumb_func_end UpdateInput .align 2, 0 @ Don't pad with nop. diff --git a/asm/memory.s b/asm/memory.s index e364f1b..418056c 100644 --- a/asm/memory.s +++ b/asm/memory.s @@ -4,177 +4,21 @@ .syntax unified .text - - thumb_func_start InitHeap -InitHeap: - push {lr} - bl InitHeapInternal - pop {r0} - bx r0 - thumb_func_end InitHeap - - thumb_func_start MemoryClear8 -MemoryClear8: - push {lr} - cmp r1, 0 - ble _08002EAA - movs r2, 0 -_08002EA0: - subs r1, 0x1 - strb r2, [r0] - adds r0, 0x1 - cmp r1, 0 - bgt _08002EA0 -_08002EAA: - pop {r0} - bx r0 - thumb_func_end MemoryClear8 - - thumb_func_start MemoryClear16 -MemoryClear16: - push {lr} - cmp r1, 0 - ble _08002EC2 - movs r2, 0 -_08002EB8: - subs r1, 0x2 - strh r2, [r0] - adds r0, 0x2 - cmp r1, 0 - bgt _08002EB8 -_08002EC2: - pop {r0} - bx r0 - thumb_func_end MemoryClear16 - - thumb_func_start MemoryClear32 -MemoryClear32: - push {lr} - bl CpuClear - pop {r0} - bx r0 - thumb_func_end MemoryClear32 - - thumb_func_start MemoryFill8 -MemoryFill8: - push {lr} - lsls r1, 24 - lsrs r1, 24 - cmp r2, 0 - ble _08002EE8 -_08002EDE: - subs r2, 0x1 - strb r1, [r0] - adds r0, 0x1 - cmp r2, 0 - bgt _08002EDE -_08002EE8: - pop {r0} - bx r0 - thumb_func_end MemoryFill8 - - thumb_func_start MemoryFill16 -MemoryFill16: - push {lr} - lsls r1, 16 - lsrs r1, 16 - cmp r2, 0 - ble _08002F00 -_08002EF6: - subs r2, 0x2 - strh r1, [r0] - adds r0, 0x2 - cmp r2, 0 - bgt _08002EF6 -_08002F00: - pop {r0} - bx r0 - thumb_func_end MemoryFill16 - - thumb_func_start MemoryFill32 -MemoryFill32: - push {lr} - cmp r2, 0 - ble _08002F12 -_08002F0A: - subs r2, 0x4 - stm r0!, {r1} - cmp r2, 0 - bgt _08002F0A -_08002F12: - pop {r0} - bx r0 - thumb_func_end MemoryFill32 - - thumb_func_start MemoryCopy8 -MemoryCopy8: - push {lr} - adds r3, r0, 0 - cmp r2, 0 - ble _08002F2E -_08002F20: - subs r2, 0x1 - ldrb r0, [r1] - strb r0, [r3] - adds r1, 0x1 - adds r3, 0x1 - cmp r2, 0 - bgt _08002F20 -_08002F2E: - pop {r0} - bx r0 - thumb_func_end MemoryCopy8 - - thumb_func_start MemoryCopy16 -MemoryCopy16: - push {lr} - adds r3, r0, 0 - cmp r2, 0 - ble _08002F4A -_08002F3C: - subs r2, 0x2 - ldrh r0, [r1] - strh r0, [r3] - adds r1, 0x2 - adds r3, 0x2 - cmp r2, 0 - bgt _08002F3C -_08002F4A: - pop {r0} - bx r0 - thumb_func_end MemoryCopy16 - - thumb_func_start MemoryCopy32 -MemoryCopy32: - push {lr} - adds r3, r0, 0 - cmp r2, 0 - ble _08002F62 -_08002F58: - subs r2, 0x4 - ldm r1!, {r0} - stm r3!, {r0} - cmp r2, 0 - bgt _08002F58 -_08002F62: - pop {r0} - bx r0 - thumb_func_end MemoryCopy32 - + thumb_func_start InitHeapInternal InitHeapInternal: push {lr} sub sp, 0x8 - ldr r0, _08002F90 + ldr r0, =gHeap str r0, [sp] movs r0, 0x90 lsls r0, 10 str r0, [sp, 0x4] - ldr r1, _08002F94 + ldr r1, =gUnknown_2000EA8 movs r0, 0 str r0, [r1] - ldr r0, _08002F98 - ldr r2, _08002F9C + ldr r0, =gUnknown_2000EB0 + ldr r2, =gHeapHeader mov r1, sp movs r3, 0x20 bl DoInitHeap @@ -182,10 +26,7 @@ InitHeapInternal: pop {r0} bx r0 .align 2, 0 -_08002F90: .4byte gUnknown_20011D0 -_08002F94: .4byte gUnknown_2000EA8 -_08002F98: .4byte gUnknown_2000EB0 -_08002F9C: .4byte gUnknown_2000ED0 + .pool thumb_func_end InitHeapInternal thumb_func_start DoInitHeap @@ -201,8 +42,8 @@ DoInitHeap: mov r5, r9 ands r5, r4 mov r9, r5 - ldr r6, _08002FFC - ldr r4, _08003000 + ldr r6, =gUnknown_2000E88 + ldr r4, =gUnknown_2000EA8 mov r8, r4 ldr r5, [r4] lsls r4, r5, 2 @@ -237,8 +78,7 @@ DoInitHeap: pop {r0} bx r0 .align 2, 0 -_08002FFC: .4byte gUnknown_2000E88 -_08003000: .4byte gUnknown_2000EA8 + .pool thumb_func_end DoInitHeap thumb_func_start InitSubHeap @@ -361,7 +201,7 @@ _080030C2: _080030CC: movs r7, 0x1 negs r7, r7 - ldr r1, _08003100 + ldr r1, =0x24001 movs r4, 0 ldr r3, [r5, 0x8] ldr r2, [r5, 0xC] @@ -389,7 +229,7 @@ _080030FC: adds r0, r7, 0 b _08003108 .align 2, 0 -_08003100: .4byte 0x00024001 + .pool _08003104: movs r0, 0x1 negs r0, r0 @@ -454,7 +294,7 @@ _0800315E: _08003168: movs r7, 0x1 negs r7, r7 - ldr r6, _080031A4 + ldr r6, =0x24001 ldr r0, [r4, 0xC] subs r3, r0, 0x1 lsls r0, r3, 1 @@ -486,7 +326,7 @@ _080031A0: adds r0, r7, 0 b _080031AC .align 2, 0 -_080031A4: .4byte 0x00024001 + .pool _080031A8: movs r0, 0x1 negs r0, r0 @@ -561,13 +401,12 @@ _08003222: str r2, [r1, 0xC] cmp r2, r8 ble _08003240 - ldr r0, _08003238 - ldr r1, _0800323C + ldr r0, =gUnknown_80B7EB8 + ldr r1, =gUnknown_80B7EC4 mov r3, r8 bl FatalError .align 2, 0 -_08003238: .4byte gUnknown_80B7EB8 -_0800323C: .4byte gUnknown_80B7EC4 + .pool _08003240: ldr r0, [sp, 0xC] add r0, r9 @@ -671,13 +510,12 @@ _080032F6: str r2, [r7, 0xC] cmp r2, r8 ble _08003314 - ldr r0, _0800330C - ldr r1, _08003310 + ldr r0, =gUnknown_80B7EFC + ldr r1, =gUnknown_80B7EC4 mov r3, r8 bl FatalError .align 2, 0 -_0800330C: .4byte gUnknown_80B7EFC -_08003310: .4byte gUnknown_80B7EC4 + .pool _08003314: ldr r0, [r4, 0x10] ldr r1, [sp, 0x10] @@ -717,7 +555,7 @@ _LocateSet: adds r6, r2, 0 cmp r5, 0 bne _0800335C - ldr r5, _08003390 + ldr r5, =gUnknown_2000EB0 _0800335C: asrs r4, r6, 8 movs r0, 0x1 @@ -743,7 +581,7 @@ _0800335C: ldr r0, [r0, 0xC] b _080033CC .align 2, 0 -_08003390: .4byte gUnknown_2000EB0 + .pool _08003394: adds r0, r5, 0 adds r1, r4, 0 @@ -760,16 +598,15 @@ _08003394: ldr r0, [r0, 0xC] b _080033CC _080033B4: - ldr r0, _080033C4 - ldr r1, _080033C8 + ldr r0, =gUnknown_80B7F14 + ldr r1, =gUnknown_80B7F20 str r4, [sp] str r6, [sp, 0x4] adds r2, r5, 0 adds r3, r7, 0 bl FatalError .align 2, 0 -_080033C4: .4byte gUnknown_80B7F14 -_080033C8: .4byte gUnknown_80B7F20 + .pool _080033CC: add sp, 0x8 pop {r4-r7} @@ -782,25 +619,25 @@ MemoryAlloc: push {lr} adds r3, r0, 0 adds r2, r1, 0 - ldr r0, _080033E8 + ldr r0, =gUnknown_2000EB0 adds r1, r3, 0 bl DoAlloc pop {r1} bx r1 .align 2, 0 -_080033E8: .4byte gUnknown_2000EB0 + .pool thumb_func_end MemoryAlloc thumb_func_start MemoryFree MemoryFree: push {lr} adds r1, r0, 0 - ldr r0, _080033FC + ldr r0, =gUnknown_2000EB0 bl DoFree pop {r0} bx r0 .align 2, 0 -_080033FC: .4byte gUnknown_2000EB0 + .pool thumb_func_end MemoryFree thumb_func_start MemoryLocate_LocalCreate @@ -813,7 +650,7 @@ MemoryLocate_LocalCreate: adds r6, r3, 0 cmp r4, 0 bne _08003412 - ldr r4, _0800342C + ldr r4, =gUnknown_2000EB0 _08003412: adds r0, r4, 0 movs r1, 0x9 @@ -822,14 +659,12 @@ _08003412: adds r1, r0, 0 cmp r1, 0 bge _08003438 - ldr r0, _08003430 - ldr r1, _08003434 + ldr r0, =gUnknown_80B7F88 + ldr r1, =gUnknown_80B7F94 adds r2, r5, 0 bl FatalError .align 2, 0 -_0800342C: .4byte gUnknown_2000EB0 -_08003430: .4byte gUnknown_80B7F88 -_08003434: .4byte gUnknown_80B7F94 + .pool _08003438: str r6, [sp] adds r0, r4, 0 @@ -893,11 +728,11 @@ _080034A2: movs r0, 0 mov r12, r0 movs r3, 0 - ldr r6, _080034E0 + ldr r6, =gUnknown_2000EA8 ldr r0, [r6] cmp r12, r0 bge _080034F2 - ldr r5, _080034E4 + ldr r5, =gUnknown_2000E88 adds r1, r6, 0 adds r7, r5, 0 movs r2, 0 @@ -911,7 +746,7 @@ _080034BC: str r0, [r1] cmp r3, r0 bge _080034F8 - ldr r1, _080034E0 + ldr r1, =gUnknown_2000EA8 adds r2, r7 _080034D2: ldr r0, [r2, 0x4] @@ -922,8 +757,7 @@ _080034D2: blt _080034D2 b _080034F8 .align 2, 0 -_080034E0: .4byte gUnknown_2000EA8 -_080034E4: .4byte gUnknown_2000E88 + .pool _080034E8: adds r2, 0x4 adds r3, 0x1 @@ -966,7 +800,7 @@ DoFree: adds r4, r0, 0 cmp r4, 0 bne _0800352E - ldr r4, _080035D4 + ldr r4, =gUnknown_2000EB0 _0800352E: cmp r1, 0 beq _080035E4 @@ -1056,7 +890,7 @@ _080035BA: blt _080035BA b _080035E4 .align 2, 0 -_080035D4: .4byte gUnknown_2000EB0 + .pool _080035D8: movs r0, 0x1 add r8, r0 diff --git a/asm/save.s b/asm/save.s index f88c219..b4e748f 100644 --- a/asm/save.s +++ b/asm/save.s @@ -5,74 +5,6 @@ .text - thumb_func_start sub_8011C1C -sub_8011C1C: - ldr r0, _08011C24 - ldr r0, [r0] - bx lr - .align 2, 0 -_08011C24: .4byte gUnknown_203B17C - thumb_func_end sub_8011C1C - - thumb_func_start sub_8011C28 -sub_8011C28: - ldr r1, _08011C30 - str r0, [r1] - bx lr - .align 2, 0 -_08011C30: .4byte gUnknown_203B17C - thumb_func_end sub_8011C28 - - thumb_func_start sub_8011C34 -sub_8011C34: - ldr r0, _08011C3C - ldr r0, [r0] - bx lr - .align 2, 0 -_08011C3C: .4byte gUnknown_202DE28 - thumb_func_end sub_8011C34 - - thumb_func_start sub_8011C40 -sub_8011C40: - ldr r1, _08011C48 - str r0, [r1] - bx lr - .align 2, 0 -_08011C48: .4byte gUnknown_202DE28 - thumb_func_end sub_8011C40 - - thumb_func_start sub_8011C4C -sub_8011C4C: - ldr r0, _08011C54 - ldr r0, [r0] - bx lr - .align 2, 0 -_08011C54: .4byte gUnknown_203B180 - thumb_func_end sub_8011C4C - - thumb_func_start sub_8011C58 -sub_8011C58: - push {r4,lr} - adds r4, r0, 0 - movs r2, 0 - lsrs r1, 2 - cmp r1, 0x1 - ble _08011C72 - adds r3, r4, 0x4 - subs r1, 0x1 -_08011C68: - ldm r3!, {r0} - adds r2, r0 - subs r1, 0x1 - cmp r1, 0 - bne _08011C68 -_08011C72: - str r2, [r4] - pop {r4} - pop {r0} - bx r0 - thumb_func_end sub_8011C58 - thumb_func_start sub_8011C7C sub_8011C7C: push {r4,lr} diff --git a/ld_script.txt b/ld_script.txt index 3bc7a22..d1bbded 100755 --- a/ld_script.txt +++ b/ld_script.txt @@ -48,11 +48,13 @@ SECTIONS { asm/code.o(.text); asm/event_flag.o(.text); asm/code_8002774.o(.text); + src/memory.o(.text); asm/memory.o(.text); asm/code_80035F0.o(.text); src/other_random.o(.text); src/util.o(.text); asm/bg_palette_buffer.o(.text); + src/bg_palette_buffer.o(.text); asm/input.o(.text); asm/code_8004AA0.o(.text); asm/sprite.o(.text); @@ -66,6 +68,7 @@ SECTIONS { asm/code_800B540.o(.text); src/flash.o(.text); asm/code_800D090.o(.text); + src/save.o(.text); asm/save.o(.text); asm/code_8012A18.o(.text); asm/m4a.o(.text); diff --git a/src/bg_palette_buffer.c b/src/bg_palette_buffer.c new file mode 100644 index 0000000..5e078a0 --- /dev/null +++ b/src/bg_palette_buffer.c @@ -0,0 +1,102 @@ +#include "global.h" + +extern u16 gBGPaletteBuffer[512]; +extern bool8 gBGPaletteUsed[32]; + +extern void CpuCopy(void* src, void* dest, u32 size); + +/* +void InitBGPaletteBuffer(void) +{ + u16 color = 0; + u16* ptr; + u32 i; + bool8 paletteUsed; + + u8* p; + + ptr = gUnknown_20251F0; + + i = 0x80; + i <<= 2; + + do { + *ptr++ = color; + i--; + } while (i); + + paletteUsed = TRUE; + + p = gUnknown_20251D0; + p += 31; + + do + *p-- = paletteUsed; + while ((s32) p >= (s32) &gUnknown_20251D0); +} +void SetBGPaletteBufferColorRGB(s32 index, u8 *RGBArray, s32 a3, u8 *a4) +{ + if (a3 < 0) { + a3 = 0; + } + if (a3 > 31) { + a3 = 31; + } + gBGPaletteUsed[index / 16] = 1; + if (!a4) { + gBGPaletteBuffer[index] = ((RGBArray[2] * a3 / 256 & 0x1F) << 10) | ((RGBArray[1] * a3 / 256 & 0x1F) << 5) | (RGBArray[0] * a3 / 256 & 0x1F); + } + else + { + gBGPaletteBuffer[index] = ((a4[4 * RGBArray[2] + 2] * a3 / 256 & 0x1F) << 10) | ((a4[4 * RGBArray[1] + 1] * a3 / 256 & 0x1F) << 5) | (a4[4 * RGBArray[0]] * a3 / 256 & 0x1F); + } +} +*/ + +void SetBGPaletteBufferColorArray(s32 index, u8 *colorArray) +{ + gBGPaletteUsed[index / 16] = TRUE; + gBGPaletteBuffer[index] = (colorArray[2] >> 3) << 10 | (colorArray[1] >> 3) << 5 | colorArray[0] >> 3; +} + +void SetBGPaletteBufferColor(s32 index, u16 *color) +{ + gBGPaletteUsed[index / 16] = TRUE; + gBGPaletteBuffer[index] = *color; +} + +void nullsub_4() +{ + +} +void nullsub_5(void) +{ + +} +void nullsub_143(void) +{ + +} + +void TransferBGPaletteBuffer(void) +{ + u32 i; + s32 paletteBufferIndex; + u16 *dest; + + i = 0; + paletteBufferIndex = 0; + dest = (u16 *)PLTT; + do + { + if (gBGPaletteUsed[i]) + { + gBGPaletteUsed[i] = 0; + CpuCopy(dest, &gBGPaletteBuffer[paletteBufferIndex], sizeof(u16) * 16); + } + ++i; + dest += 16; + paletteBufferIndex += 16; + } + while ( paletteBufferIndex < 512 ); +} \ No newline at end of file diff --git a/src/memory.c b/src/memory.c new file mode 100644 index 0000000..1ccbe54 --- /dev/null +++ b/src/memory.c @@ -0,0 +1,85 @@ +#include "global.h" + +extern void InitHeapInternal(void); +extern void CpuClear(u32 *dest, s32 size); + +void InitHeap(void) +{ + InitHeapInternal(); +} + +void MemoryClear8(u8 *dest, s32 size) +{ + while (size > 0) + { + size -= 1; + *dest++ = 0; + } +} + +void MemoryClear16(u16 *dest, s32 size) +{ + while (size > 0) + { + size -= 2; + *dest++ = 0; + } +} +void MemoryClear32(u32 *dest, s32 size) +{ + CpuClear(dest, size); +} + +void MemoryFill8(u8 *dest, u8 value, s32 size) +{ + while (size > 0) + { + size -= 1; + *dest++ = value; + } +} + +void MemoryFill16(u16 *dest, u16 value, s32 size) +{ + while (size > 0) + { + size -= 2; + *dest++ = value; + } +} + +void MemoryFill32(u32 *dest, u32 value, s32 size) +{ + while (size > 0) + { + size -= 4; + *dest++ = value; + } +} + +void MemoryCopy8(u8 *dest, u8 *src, s32 size) +{ + while (size > 0) + { + size -= 1; + *dest++ = *src++; + } +} + +void MemoryCopy16(u16 *dest, u16 *src, s32 size) +{ + while (size > 0) + { + size -= 2; + *dest++ = *src++; + } +} + +void MemoryCopy32(u32 *dest, u32 *src, s32 size) +{ + while (size > 0) + { + size -= 4; + *dest++ = *src++; + } +} \ No newline at end of file diff --git a/src/save.c b/src/save.c new file mode 100644 index 0000000..575d4f1 --- /dev/null +++ b/src/save.c @@ -0,0 +1,45 @@ +#include "global.h" + +extern u32 gUnknown_203B17C; +extern u32 gUnknown_203B180; +extern u32 gUnknown_202DE28; + +u32 sub_8011C1C(void) +{ + return gUnknown_203B17C; +} + +void sub_8011C28(u32 in) +{ + gUnknown_203B17C = in; +} + +u32 sub_8011C34(void) +{ + return gUnknown_202DE28; +} + +void sub_8011C40(u32 in) +{ + gUnknown_202DE28 = in; +} + +u32 sub_8011C4C(void) +{ + return gUnknown_203B180; +} + +void sub_8011C58(u32 *out, u32 len) +{ + u32 sum = 0; + s32 i = len / 4; + if (i > 1) + { + u32 *ptr = &out[1]; + --i; + do + sum += *ptr++; + while (--i); + } + *out = sum; +} \ No newline at end of file diff --git a/sym_ewram.txt b/sym_ewram.txt index f235a49..fb753c9 100644 --- a/sym_ewram.txt +++ b/sym_ewram.txt @@ -24,16 +24,16 @@ gUnknown_2000EA8 = .; /* 2000EA8 */ gUnknown_2000EB0 = .; /* 2000EB0 */ . += 0x20; -gUnknown_2000ED0 = .; /* 2000ED0 */ +gHeapHeader = .; /* 2000ED0 */ . += 0x300; -gUnknown_20011D0 = .; /* 20011D0 */ +gHeap = .; /* 20011D0 */ . += 0x24000; -gUnknown_20251D0 = .; /* 20251D0 */ +gBGPaletteUsed = .; /* 20251D0 */ . += 0x20; -gUnknown_20251F0 = .; /* 20251F0 */ +gBGPaletteBuffer = .; /* 20251F0 */ . += 0x400; gUnknown_20255F0 = .; /* 20255F0 */ @@ -385,7 +385,8 @@ gUnknown_202DE24 = .; /* 202DE24 */ . += 0x4; gUnknown_202DE28 = .; /* 202DE28 */ - . += 0x8; + . += 0x4; + . = ALIGN(16); gUnknown_202DE30 = .; /* 202DE30 */ . += 0x28; -- cgit v1.2.3 From f4ef62bb4134498a4b4a9c4d61b99bda24c98680 Mon Sep 17 00:00:00 2001 From: nullableVoidPtr <30564701+nullableVoidPtr@users.noreply.github.com> Date: Sun, 18 Nov 2018 16:23:57 +0800 Subject: Renamed primary heap variables and partial cleanup m4a.s --- INSTALL.md | 2 + Makefile | 12 ++- asm/code_8012A18.s | 244 ++++++++++++++++++++++---------------------- asm/m4a.s | 216 ++++++++++++++++++++------------------- asm/memory.s | 121 ++-------------------- asm/rom_header.inc | 33 ++---- asm/save.s | 92 ++++------------- asm/sprite.s | 11 -- asm/text.s | 2 +- constants/m4a_constants.inc | 199 ++++++++++++++++++++++++++++++++++++ include/gba/defines.h | 4 +- include/memory.h | 56 ++++++++++ ld_script.txt | 2 + src/bg_palette_buffer.c | 15 +-- src/file_system.c | 34 +++--- src/flash.c | 3 +- src/memory.c | 62 ++++++++++- src/save.c | 33 ++++-- src/save1.c | 13 +++ src/sprite.c | 10 ++ sym_ewram.txt | 49 ++++----- sym_ewram2.txt | 2 +- 22 files changed, 702 insertions(+), 513 deletions(-) create mode 100644 constants/m4a_constants.inc create mode 100644 include/memory.h create mode 100644 src/save1.c create mode 100644 src/sprite.c diff --git a/INSTALL.md b/INSTALL.md index b114971..de8142d 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,3 +1,5 @@ +First, you must put a Pokémon Mystery Dungeon Red Rescue Team 1.0 (US) ROM in the root directory of the repository and name it `baserom.gba`. It should have a SHA1 checksum of `9f4cfc5b5f4859d17169a485462e977c7aac2b89`. Then, follow the OS-specific instructions below. + # Linux Install [**devkitARM**](http://devkitpro.org/wiki/Getting_Started/devkitARM). diff --git a/Makefile b/Makefile index 92e1edd..59e6caf 100755 --- a/Makefile +++ b/Makefile @@ -6,6 +6,10 @@ else EXE := endif +TITLE := POKE DUNGEON +GAME_CODE := B24E +MAKER_CODE := 01 +REVISION := 0 #### Tools #### @@ -17,6 +21,7 @@ LD := $(PREFIX)ld OBJCOPY := $(PREFIX)objcopy SHA1SUM := sha1sum -c GBAGFX := tools/gbagfx/gbagfx +GBAFIX := tools/gbafix/gbafix AIF2PCM := tools/aif2pcm/aif2pcm MID2AGB := tools/mid2agb/mid2agb PREPROC := tools/preproc/preproc @@ -51,9 +56,9 @@ LIBGCC := tools/agbcc/lib/libgcc.a LD_SCRIPT := $(BUILD_DIR)/ld_script.ld # Special configurations required for lib files -%/src/agb_flash.o : CC1FLAGS := -O -mthumb-interwork -%/src/agb_flash_1m.o: CC1FLAGS := -O -mthumb-interwork -%/src/agb_flash_mx.o: CC1FLAGS := -O -mthumb-interwork +$(BUILD_DIR)/src/agb_flash.o : CC1FLAGS := -O -mthumb-interwork +$(BUILD_DIR)/src/agb_flash_1m.o: CC1FLAGS := -O -mthumb-interwork +$(BUILD_DIR)/src/agb_flash_mx.o: CC1FLAGS := -O -mthumb-interwork #### Main Rules #### @@ -92,6 +97,7 @@ tidy: $(ROM): %.gba: %.elf $(OBJCOPY) -O binary --gap-fill 0xFF --pad-to 0xA000000 $< $@ + $(GBAFIX) $@ -p -t"$(TITLE)" -c$(GAME_CODE) -m$(MAKER_CODE) -r$(REVISION) --silent %.elf: $(LD_SCRIPT) $(ALL_OBJECTS) $(LIBC) cd $(BUILD_DIR) && $(LD) -T ld_script.ld -Map ../../$(MAP) -o ../../$@ ../../$(LIBC) ../../$(LIBGCC) diff --git a/asm/code_8012A18.s b/asm/code_8012A18.s index bf8e220..b1327f4 100644 --- a/asm/code_8012A18.s +++ b/asm/code_8012A18.s @@ -4698,7 +4698,7 @@ _08014E10: adds r4, r1, r0 b _08014F0C .align 2, 0 -_08014E20: .4byte gUnknown_202D3B8 +_08014E20: .4byte gFileCache + 0x110 _08014E24: adds r5, 0x1 movs r0, 0 @@ -86812,10 +86812,10 @@ _0803DB54: .align 2, 0 _0803DB84: .4byte gUnknown_80F60F8 _0803DB88: .4byte gUnknown_83B0000 -_0803DB8C: .4byte gUnknown_202EC88 +_0803DB8C: .4byte gDungeonNameBannerPalette _0803DB90: .4byte gUnknown_80F6100 -_0803DB94: .4byte gUnknown_202EC8C -_0803DB98: .4byte gUnknown_202EC90 +_0803DB94: .4byte gDungeonNameBannerFontFile +_0803DB98: .4byte gDungeonNameBannerFontFile + 4 _0803DB9C: .4byte 0x06000140 _0803DBA0: .4byte gUnknown_203B418 _0803DBA4: .4byte 0x00000645 @@ -86862,7 +86862,7 @@ _0803DBEA: .align 2, 0 _0803DC08: .4byte gUnknown_80F6118 _0803DC0C: .4byte gUnknown_20274A5 -_0803DC10: .4byte gUnknown_202EC8C +_0803DC10: .4byte gDungeonNameBannerFontFile thumb_func_end ShowDungeonNameBanner thumb_func_start sub_803DC14 @@ -87273,7 +87273,7 @@ sub_803DEC8: adds r1, r5, r0 b _0803DF56 .align 2, 0 -_0803DEFC: .4byte gUnknown_202EC8C +_0803DEFC: .4byte gDungeonNameBannerFontFile _0803DF00: .4byte 0xffff0800 _0803DF04: .4byte 0x000007fe _0803DF08: @@ -87287,7 +87287,7 @@ _0803DF08: adds r0, r2, r0 b _0803DF3A .align 2, 0 -_0803DF1C: .4byte gUnknown_202EC90 +_0803DF1C: .4byte gDungeonNameBannerFontFile + 4 _0803DF20: lsls r0, r1, 3 adds r0, r5 @@ -88555,7 +88555,7 @@ _0803E9B4: .4byte 0x00018215 _0803E9B8: .4byte 0x0001c06c _0803E9BC: .4byte gUnknown_202EE8C _0803E9C0: .4byte gUnknown_202ECA4 -_0803E9C4: .4byte gUnknown_202EC88 +_0803E9C4: .4byte gDungeonNameBannerPalette _0803E9C8: .4byte gUnknown_202D058 _0803E9CC: .4byte 0x000181e4 thumb_func_end sub_803E874 @@ -99078,7 +99078,7 @@ _08043984: .4byte 0xff00ffff _08043988: .4byte gUnknown_202EDC8 _0804398C: .4byte gUnknown_81006A4 _08043990: .4byte 0x00000222 -_08043994: .4byte gUnknown_202EC88 +_08043994: .4byte gDungeonNameBannerPalette _08043998: .4byte gUnknown_203B40C _0804399C: .4byte gUnknown_203B41C _080439A0: @@ -104471,7 +104471,7 @@ sub_8046298: ldrb r0, [r0, 0xD] bx lr .align 2, 0 -_080462A8: .4byte gUnknown_20389A4 +_080462A8: .4byte gItemParametersFile + 4 thumb_func_end sub_8046298 thumb_func_start sub_80462AC @@ -245668,8 +245668,8 @@ _0808CDE4: .4byte gUnknown_203B45C _0808CDE8: .4byte gUnknown_202F400 _0808CDEC: .4byte gUnknown_81075F4 _0808CDF0: .4byte gUnknown_8300500 -_0808CDF4: .4byte gUnknown_202F3E4 -_0808CDF8: .4byte gUnknown_202F3E0 +_0808CDF4: .4byte gMonsterParametersFile +_0808CDF8: .4byte gMonsterParameters _0808CDFC: .4byte gUnknown_20384E8 thumb_func_end LoadMonsterParameters @@ -245907,7 +245907,7 @@ _0808CFB8: pop {r0} bx r0 .align 2, 0 -_0808CFC8: .4byte gUnknown_202F3E0 +_0808CFC8: .4byte gMonsterParameters _0808CFCC: .4byte gUnknown_203B45C thumb_func_end sub_808CE74 @@ -246197,7 +246197,7 @@ sub_808D1DC: bne _0808D238 b _0808D268 .align 2, 0 -_0808D204: .4byte gUnknown_202F3E0 +_0808D204: .4byte gMonsterParameters _0808D208: .4byte gUnknown_203B468 _0808D20C: ldr r0, [r7] @@ -246278,7 +246278,7 @@ sub_808D278: bne _0808D2AA b _0808D2DA .align 2, 0 -_0808D29C: .4byte gUnknown_202F3E0 +_0808D29C: .4byte gMonsterParameters _0808D2A0: .4byte gUnknown_203B468 _0808D2A4: ldr r0, [r7] @@ -247194,7 +247194,7 @@ sub_808D8BC: pop {r0} bx r0 .align 2, 0 -_0808D8DC: .4byte gUnknown_202F3E0 +_0808D8DC: .4byte gMonsterParameters thumb_func_end sub_808D8BC thumb_func_start sub_808D8E0 @@ -247216,7 +247216,7 @@ sub_808D8E0: bx r0 .align 2, 0 _0808D900: .4byte gUnknown_8107600 -_0808D904: .4byte gUnknown_202F3E0 +_0808D904: .4byte gMonsterParameters thumb_func_end sub_808D8E0 thumb_func_start sub_808D908 @@ -247238,7 +247238,7 @@ sub_808D908: bx r0 .align 2, 0 _0808D928: .4byte gUnknown_8107608 -_0808D92C: .4byte gUnknown_202F3E0 +_0808D92C: .4byte gMonsterParameters thumb_func_end sub_808D908 thumb_func_start sub_808D930 @@ -247287,7 +247287,7 @@ _0808D986: bx r0 .align 2, 0 _0808D98C: .4byte gUnknown_8107638 -_0808D990: .4byte gUnknown_202F3E0 +_0808D990: .4byte gMonsterParameters thumb_func_end sub_808D930 thumb_func_start sub_808D994 @@ -247303,7 +247303,7 @@ sub_808D994: ldr r0, [r1] bx lr .align 2, 0 -_0808D9A8: .4byte gUnknown_202F3E0 +_0808D9A8: .4byte gMonsterParameters thumb_func_end sub_808D994 thumb_func_start sub_808D9AC @@ -247468,7 +247468,7 @@ sub_808DAB4: ldr r0, [r1, 0x4] bx lr .align 2, 0 -_0808DAC8: .4byte gUnknown_202F3E0 +_0808DAC8: .4byte gMonsterParameters thumb_func_end sub_808DAB4 thumb_func_start sub_808DACC @@ -247484,7 +247484,7 @@ sub_808DACC: ldrb r0, [r1, 0x9] bx lr .align 2, 0 -_0808DAE0: .4byte gUnknown_202F3E0 +_0808DAE0: .4byte gMonsterParameters thumb_func_end sub_808DACC thumb_func_start sub_808DAE4 @@ -247500,7 +247500,7 @@ sub_808DAE4: ldrb r0, [r1, 0x19] bx lr .align 2, 0 -_0808DAF8: .4byte gUnknown_202F3E0 +_0808DAF8: .4byte gMonsterParameters thumb_func_end sub_808DAE4 thumb_func_start sub_808DAFC @@ -247516,7 +247516,7 @@ sub_808DAFC: ldr r0, [r1, 0xC] bx lr .align 2, 0 -_0808DB10: .4byte gUnknown_202F3E0 +_0808DB10: .4byte gMonsterParameters thumb_func_end sub_808DAFC thumb_func_start sub_808DB14 @@ -247532,7 +247532,7 @@ sub_808DB14: ldrb r0, [r1, 0x15] bx lr .align 2, 0 -_0808DB28: .4byte gUnknown_202F3E0 +_0808DB28: .4byte gMonsterParameters thumb_func_end sub_808DB14 thumb_func_start sub_808DB2C @@ -247550,7 +247550,7 @@ sub_808DB2C: lsrs r0, 24 bx lr .align 2, 0 -_0808DB44: .4byte gUnknown_202F3E0 +_0808DB44: .4byte gMonsterParameters thumb_func_end sub_808DB2C thumb_func_start sub_808DB48 @@ -247566,7 +247566,7 @@ sub_808DB48: ldrb r0, [r1, 0x1C] bx lr .align 2, 0 -_0808DB5C: .4byte gUnknown_202F3E0 +_0808DB5C: .4byte gMonsterParameters thumb_func_end sub_808DB48 thumb_func_start sub_808DB60 @@ -247582,7 +247582,7 @@ sub_808DB60: ldrb r0, [r1, 0x1D] bx lr .align 2, 0 -_0808DB74: .4byte gUnknown_202F3E0 +_0808DB74: .4byte gMonsterParameters thumb_func_end sub_808DB60 thumb_func_start sub_808DB78 @@ -247598,7 +247598,7 @@ sub_808DB78: ldrh r0, [r1, 0x2C] bx lr .align 2, 0 -_0808DB8C: .4byte gUnknown_202F3E0 +_0808DB8C: .4byte gMonsterParameters thumb_func_end sub_808DB78 thumb_func_start sub_808DB90 @@ -247614,7 +247614,7 @@ sub_808DB90: ldrh r0, [r1, 0x2E] bx lr .align 2, 0 -_0808DBA4: .4byte gUnknown_202F3E0 +_0808DBA4: .4byte gMonsterParameters thumb_func_end sub_808DB90 thumb_func_start sub_808DBA8 @@ -247630,7 +247630,7 @@ sub_808DBA8: ldrb r0, [r1, 0x16] bx lr .align 2, 0 -_0808DBBC: .4byte gUnknown_202F3E0 +_0808DBBC: .4byte gMonsterParameters thumb_func_end sub_808DBA8 thumb_func_start sub_808DBC0 @@ -247646,7 +247646,7 @@ sub_808DBC0: ldrh r0, [r1, 0x1E] bx lr .align 2, 0 -_0808DBD4: .4byte gUnknown_202F3E0 +_0808DBD4: .4byte gMonsterParameters thumb_func_end sub_808DBC0 thumb_func_start sub_808DBD8 @@ -247663,7 +247663,7 @@ sub_808DBD8: ldrb r0, [r1] bx lr .align 2, 0 -_0808DBF0: .4byte gUnknown_202F3E0 +_0808DBF0: .4byte gMonsterParameters thumb_func_end sub_808DBD8 thumb_func_start sub_808DBF4 @@ -247679,7 +247679,7 @@ sub_808DBF4: ldrb r0, [r1, 0x12] bx lr .align 2, 0 -_0808DC08: .4byte gUnknown_202F3E0 +_0808DC08: .4byte gMonsterParameters thumb_func_end sub_808DBF4 thumb_func_start sub_808DC0C @@ -247696,7 +247696,7 @@ sub_808DC0C: ldrsh r0, [r1, r2] bx lr .align 2, 0 -_0808DC24: .4byte gUnknown_202F3E0 +_0808DC24: .4byte gMonsterParameters thumb_func_end sub_808DC0C thumb_func_start sub_808DC28 @@ -247715,7 +247715,7 @@ sub_808DC28: ldrh r0, [r2] bx lr .align 2, 0 -_0808DC44: .4byte gUnknown_202F3E0 +_0808DC44: .4byte gMonsterParameters thumb_func_end sub_808DC28 thumb_func_start sub_808DC48 @@ -247734,7 +247734,7 @@ sub_808DC48: ldrh r0, [r2] bx lr .align 2, 0 -_0808DC64: .4byte gUnknown_202F3E0 +_0808DC64: .4byte gMonsterParameters thumb_func_end sub_808DC48 thumb_func_start sub_808DC68 @@ -247752,7 +247752,7 @@ sub_808DC68: ldrb r0, [r2] bx lr .align 2, 0 -_0808DC80: .4byte gUnknown_202F3E0 +_0808DC80: .4byte gMonsterParameters thumb_func_end sub_808DC68 thumb_func_start sub_808DC84 @@ -247770,7 +247770,7 @@ sub_808DC84: ldrb r0, [r2] bx lr .align 2, 0 -_0808DC9C: .4byte gUnknown_202F3E0 +_0808DC9C: .4byte gMonsterParameters thumb_func_end sub_808DC84 thumb_func_start sub_808DCA0 @@ -247790,7 +247790,7 @@ sub_808DCA0: ldrsh r0, [r2, r1] bx lr .align 2, 0 -_0808DCBC: .4byte gUnknown_202F3E0 +_0808DCBC: .4byte gMonsterParameters thumb_func_end sub_808DCA0 thumb_func_start sub_808DCC0 @@ -247808,7 +247808,7 @@ sub_808DCC0: ldrsh r0, [r1, r2] bx lr .align 2, 0 -_0808DCD8: .4byte gUnknown_202F3E0 +_0808DCD8: .4byte gMonsterParameters thumb_func_end sub_808DCC0 thumb_func_start sub_808DCDC @@ -247828,7 +247828,7 @@ sub_808DCDC: ldrsh r0, [r2, r1] bx lr .align 2, 0 -_0808DCF8: .4byte gUnknown_202F3E0 +_0808DCF8: .4byte gMonsterParameters thumb_func_end sub_808DCDC thumb_func_start sub_808DCFC @@ -247845,7 +247845,7 @@ sub_808DCFC: ldrsh r0, [r1, r2] bx lr .align 2, 0 -_0808DD14: .4byte gUnknown_202F3E0 +_0808DD14: .4byte gMonsterParameters thumb_func_end sub_808DCFC thumb_func_start sub_808DD18 @@ -247871,7 +247871,7 @@ sub_808DD18: pop {r1} bx r1 .align 2, 0 -_0808DD44: .4byte gUnknown_202F3E0 +_0808DD44: .4byte gMonsterParameters thumb_func_end sub_808DD18 thumb_func_start sub_808DD48 @@ -247890,7 +247890,7 @@ sub_808DD48: str r3, [r1, 0x4] bx lr .align 2, 0 -_0808DD64: .4byte gUnknown_202F3E0 +_0808DD64: .4byte gMonsterParameters thumb_func_end sub_808DD48 thumb_func_start sub_808DD68 @@ -247909,7 +247909,7 @@ sub_808DD68: ldrb r0, [r0, 0x8] b _0808DD8A .align 2, 0 -_0808DD84: .4byte gUnknown_202F3E0 +_0808DD84: .4byte gMonsterParameters _0808DD88: movs r0, 0xA _0808DD8A: @@ -247940,7 +247940,7 @@ sub_808DD90: bl OpenFile b _0808DDCA .align 2, 0 -_0808DDBC: .4byte gUnknown_202F3E0 +_0808DDBC: .4byte gMonsterParameters _0808DDC0: .4byte gUnknown_8107684 _0808DDC4: .4byte gUnknown_8510000 _0808DDC8: @@ -247974,7 +247974,7 @@ sub_808DDD0: bl OpenFileAndGetFileDataPtr b _0808DE0A .align 2, 0 -_0808DDFC: .4byte gUnknown_202F3E0 +_0808DDFC: .4byte gMonsterParameters _0808DE00: .4byte gUnknown_8107684 _0808DE04: .4byte gUnknown_8510000 _0808DE08: @@ -248001,7 +248001,7 @@ sub_808DE10: ands r0, r1 bx lr .align 2, 0 -_0808DE2C: .4byte gUnknown_202F3E0 +_0808DE2C: .4byte gMonsterParameters thumb_func_end sub_808DE10 thumb_func_start sub_808DE30 @@ -253777,8 +253777,8 @@ _080909B8: .4byte gUnknown_203B460 _080909BC: .4byte gUnknown_20389A8 _080909C0: .4byte gUnknown_8109764 _080909C4: .4byte gUnknown_8300500 -_080909C8: .4byte gUnknown_20389A0 -_080909CC: .4byte gUnknown_20389A4 +_080909C8: .4byte gItemParametersFile +_080909CC: .4byte gItemParametersFile + 4 thumb_func_end sub_8090998 thumb_func_start sub_80909D0 @@ -254085,7 +254085,7 @@ sub_8090BD0: ldrb r0, [r0, 0xC] bx lr .align 2, 0 -_08090BE0: .4byte gUnknown_20389A4 +_08090BE0: .4byte gItemParametersFile + 4 thumb_func_end sub_8090BD0 thumb_func_start sub_8090BE4 @@ -254112,7 +254112,7 @@ _08090BF6: ldr r0, [r0, 0x4] b _08090C24 .align 2, 0 -_08090C10: .4byte gUnknown_20389A4 +_08090C10: .4byte gItemParametersFile + 4 _08090C14: ldrb r0, [r4, 0x2] ldr r1, _08090C2C @@ -254127,7 +254127,7 @@ _08090C24: pop {r1} bx r1 .align 2, 0 -_08090C2C: .4byte gUnknown_20389A4 +_08090C2C: .4byte gItemParametersFile + 4 thumb_func_end sub_8090BE4 thumb_func_start sub_8090C30 @@ -254154,7 +254154,7 @@ _08090C42: ldr r0, [r0, 0x8] b _08090C70 .align 2, 0 -_08090C5C: .4byte gUnknown_20389A4 +_08090C5C: .4byte gItemParametersFile + 4 _08090C60: ldrb r0, [r4, 0x2] ldr r1, _08090C78 @@ -254169,7 +254169,7 @@ _08090C70: pop {r1} bx r1 .align 2, 0 -_08090C78: .4byte gUnknown_20389A4 +_08090C78: .4byte gItemParametersFile + 4 thumb_func_end sub_8090C30 thumb_func_start sub_8090C7C @@ -254197,7 +254197,7 @@ _08090C90: ldr r0, [r0, 0x4] b _08090CC0 .align 2, 0 -_08090CAC: .4byte gUnknown_20389A4 +_08090CAC: .4byte gItemParametersFile + 4 _08090CB0: ldrb r0, [r4, 0x2] ldr r1, _08090CC8 @@ -254212,7 +254212,7 @@ _08090CC0: pop {r1} bx r1 .align 2, 0 -_08090CC8: .4byte gUnknown_20389A4 +_08090CC8: .4byte gItemParametersFile + 4 thumb_func_end sub_8090C7C thumb_func_start sub_8090CCC @@ -254240,7 +254240,7 @@ _08090CE0: ldr r0, [r0, 0x8] b _08090D10 .align 2, 0 -_08090CFC: .4byte gUnknown_20389A4 +_08090CFC: .4byte gItemParametersFile + 4 _08090D00: ldrb r0, [r4, 0x2] ldr r1, _08090D18 @@ -254255,7 +254255,7 @@ _08090D10: pop {r1} bx r1 .align 2, 0 -_08090D18: .4byte gUnknown_20389A4 +_08090D18: .4byte gItemParametersFile + 4 thumb_func_end sub_8090CCC thumb_func_start sub_8090D1C @@ -254268,7 +254268,7 @@ sub_8090D1C: ldr r0, [r0, 0x4] bx lr .align 2, 0 -_08090D2C: .4byte gUnknown_20389A4 +_08090D2C: .4byte gItemParametersFile + 4 thumb_func_end sub_8090D1C thumb_func_start sub_8090D30 @@ -254281,7 +254281,7 @@ sub_8090D30: ldr r0, [r0, 0x8] bx lr .align 2, 0 -_08090D40: .4byte gUnknown_20389A4 +_08090D40: .4byte gItemParametersFile + 4 thumb_func_end sub_8090D30 thumb_func_start sub_8090D44 @@ -254294,7 +254294,7 @@ sub_8090D44: ldrb r0, [r0, 0x1A] bx lr .align 2, 0 -_08090D54: .4byte gUnknown_20389A4 +_08090D54: .4byte gItemParametersFile + 4 thumb_func_end sub_8090D44 thumb_func_start sub_8090D58 @@ -254307,7 +254307,7 @@ sub_8090D58: ldrb r0, [r0, 0x1D] bx lr .align 2, 0 -_08090D68: .4byte gUnknown_20389A4 +_08090D68: .4byte gItemParametersFile + 4 thumb_func_end sub_8090D58 thumb_func_start sub_8090D6C @@ -254320,7 +254320,7 @@ sub_8090D6C: ldrb r0, [r0, 0x1E] bx lr .align 2, 0 -_08090D7C: .4byte gUnknown_20389A4 +_08090D7C: .4byte gItemParametersFile + 4 thumb_func_end sub_8090D6C thumb_func_start sub_8090D80 @@ -254335,7 +254335,7 @@ sub_8090D80: ldrb r0, [r0] bx lr .align 2, 0 -_08090D94: .4byte gUnknown_20389A4 +_08090D94: .4byte gItemParametersFile + 4 thumb_func_end sub_8090D80 thumb_func_start sub_8090D98 @@ -254348,7 +254348,7 @@ sub_8090D98: ldr r0, [r0, 0x10] bx lr .align 2, 0 -_08090DA8: .4byte gUnknown_20389A4 +_08090DA8: .4byte gItemParametersFile + 4 thumb_func_end sub_8090D98 thumb_func_start sub_8090DAC @@ -254363,7 +254363,7 @@ sub_8090DAC: ldrb r0, [r0] bx lr .align 2, 0 -_08090DC0: .4byte gUnknown_20389A4 +_08090DC0: .4byte gItemParametersFile + 4 thumb_func_end sub_8090DAC thumb_func_start sub_8090DC4 @@ -254404,7 +254404,7 @@ sub_8090DC4: pop {r0} bx r0 .align 2, 0 -_08090E10: .4byte gUnknown_20389A4 +_08090E10: .4byte gItemParametersFile + 4 thumb_func_end sub_8090DC4 thumb_func_start sub_8090E14 @@ -254453,7 +254453,7 @@ _08090E50: b _08090EC4 .align 2, 0 _08090E68: .4byte gUnknown_8109770 -_08090E6C: .4byte gUnknown_20389A4 +_08090E6C: .4byte gItemParametersFile + 4 _08090E70: ldr r1, _08090E88 ldrb r0, [r5, 0x2] @@ -254467,7 +254467,7 @@ _08090E70: b _08090EC4 .align 2, 0 _08090E88: .4byte gUnknown_8109778 -_08090E8C: .4byte gUnknown_20389A4 +_08090E8C: .4byte gItemParametersFile + 4 _08090E90: ldrb r0, [r5, 0x2] cmp r0, 0x69 @@ -254544,7 +254544,7 @@ _08090F14: bl sub_8090F58 b _08090F50 .align 2, 0 -_08090F2C: .4byte gUnknown_20389A4 +_08090F2C: .4byte gItemParametersFile + 4 _08090F30: .4byte gUnknown_8109784 _08090F34: .4byte gUnknown_810978C _08090F38: @@ -255209,7 +255209,7 @@ sub_80913CC: ldrh r0, [r0, 0x18] bx lr .align 2, 0 -_080913DC: .4byte gUnknown_20389A4 +_080913DC: .4byte gItemParametersFile + 4 thumb_func_end sub_80913CC thumb_func_start sub_80913E0 @@ -258154,7 +258154,7 @@ LoadWazaParameters: .align 2, 0 _08092868: .4byte gUnknown_81098D0 _0809286C: .4byte gUnknown_8300500 -_08092870: .4byte gUnknown_2038C64 +_08092870: .4byte gWazaParametersFile _08092874: .4byte gUnknown_2038C68 _08092878: .4byte gUnknown_2038C6C thumb_func_end LoadWazaParameters @@ -271490,7 +271490,7 @@ _080988F8: bl GroundEffect_Action bl nullsub_105 bl sub_809B474 - bl sub_80A2380 + bl GroundScript_Unlock bl sub_809D25C bl sub_80A59DC bl sub_809B614 @@ -271783,7 +271783,7 @@ _08098BD2: sub_8098BDC: push {lr} bl sub_809B57C - bl sub_80A2380 + bl GroundScript_Unlock bl sub_809D25C bl sub_80A59DC bl sub_809B614 @@ -279959,7 +279959,7 @@ sub_809CBBC: b _0809CC4A .align 2, 0 _0809CC0C: .4byte gUnknown_81163E4 -_0809CC10: .4byte gUnknown_20389A4 +_0809CC10: .4byte gItemParametersFile + 4 _0809CC14: .4byte gUnknown_203B460 _0809CC18: .4byte 0x0001869f _0809CC1C: @@ -284745,28 +284745,28 @@ _0809F3DC: .4byte gUnknown_2039A32 _0809F3E0: adds r0, r6, 0 adds r1, r5, 0 - bl sub_80A7988 + bl GroundLives_Cancel adds r0, r6, 0 adds r1, r5, 0 - bl sub_80ABC5C + bl GroundObject_Cancel adds r0, r6, 0 adds r1, r5, 0 - bl sub_80ACC98 + bl GroundEffect_Cancel b _0809F41E _0809F3FA: adds r0, r6, 0 adds r1, r5, 0 - bl sub_80A7988 + bl GroundLives_Cancel bl _0809EAE0 _0809F406: adds r0, r6, 0 adds r1, r5, 0 - bl sub_80ABC5C + bl GroundObject_Cancel bl _0809EAE0 _0809F412: adds r0, r6, 0 adds r1, r5, 0 - bl sub_80ACC98 + bl GroundEffect_Cancel bl _0809EAE0 _0809F41E: adds r0, r6, 0 @@ -284777,10 +284777,10 @@ _0809F42A: bl sub_80A79FC bl _0809EAE0 _0809F432: - bl sub_80ABCCC + bl GroundObject_CancelBlank bl _0809EAE0 _0809F43A: - bl sub_80ACD08 + bl GroundEffect_CancelBlank bl _0809EAE0 _0809F442: mov r2, r9 @@ -290448,7 +290448,7 @@ _080A233A: b _080A236A _080A2346: movs r0, 0 - bl sub_80A6C88 + bl GroundSprite_ExtendPaletteDelete b _080A236A _080A234E: movs r0, 0 @@ -290478,8 +290478,8 @@ _080A236C: bx r1 thumb_func_end sub_80A14E8 - thumb_func_start sub_80A2380 -sub_80A2380: + thumb_func_start GroundScript_Unlock +GroundScript_Unlock: push {r4-r7,lr} ldr r1, _080A241C ldrb r0, [r1] @@ -290557,7 +290557,7 @@ _080A241C: .4byte gUnknown_2039A36 _080A2420: .4byte gUnknown_2039A38 _080A2424: .4byte gUnknown_8116848 _080A2428: .4byte gUnknown_2039AC0 - thumb_func_end sub_80A2380 + thumb_func_end GroundScript_Unlock thumb_func_start sub_80A242C sub_80A242C: @@ -299986,7 +299986,7 @@ sub_80A69FC: cmp r4, 0 blt _080A6A7A adds r0, r6, 0 - bl sub_80A6C88 + bl GroundSprite_ExtendPaletteDelete movs r0, 0 str r0, [r5, 0x8] str r0, [r5] @@ -300303,8 +300303,8 @@ _080A6C78: bx r0 thumb_func_end GroundSprite_ExtendPaletteAdd - thumb_func_start sub_80A6C88 -sub_80A6C88: + thumb_func_start GroundSprite_ExtendPaletteDelete +GroundSprite_ExtendPaletteDelete: push {r4-r6,lr} adds r2, r0, 0 cmp r2, 0 @@ -300360,7 +300360,7 @@ _080A6CE6: .align 2, 0 _080A6CEC: .4byte gUnknown_3001B7C _080A6CF0: .4byte gUnknown_81178C0 - thumb_func_end sub_80A6C88 + thumb_func_end GroundSprite_ExtendPaletteDelete thumb_func_start sub_80A6CF4 sub_80A6CF4: @@ -301931,7 +301931,7 @@ _080A787C: cmp r0, r6 beq _080A788A adds r0, r1, 0 - bl sub_80A8684 + bl GroundLives_Delete _080A788A: adds r0, r5, 0 movs r1, 0x80 @@ -302062,8 +302062,8 @@ _080A7980: .4byte gUnknown_811808C _080A7984: .4byte gUnknown_8118098 thumb_func_end GroundLives_Select - thumb_func_start sub_80A7988 -sub_80A7988: + thumb_func_start GroundLives_Cancel +GroundLives_Cancel: push {r4-r7,lr} mov r7, r8 push {r7} @@ -302101,7 +302101,7 @@ _080A79B2: bne _080A79D4 _080A79CE: adds r0, r1, 0 - bl sub_80A8684 + bl GroundLives_Delete _080A79D4: adds r0, r6, 0 movs r1, 0x80 @@ -302121,7 +302121,7 @@ _080A79D4: .align 2, 0 _080A79F4: .4byte gUnknown_81180BC _080A79F8: .4byte gUnknown_3001B84 - thumb_func_end sub_80A7988 + thumb_func_end GroundLives_Cancel thumb_func_start sub_80A79FC sub_80A79FC: @@ -302164,7 +302164,7 @@ _080A7A20: cmp r0, 0 bne _080A7A50 adds r0, r6, 0 - bl sub_80A8684 + bl GroundLives_Delete _080A7A50: adds r0, r6, 0x1 lsls r0, 16 @@ -303749,8 +303749,8 @@ _080A8674: bx r1 thumb_func_end GroundLives_Add - thumb_func_start sub_80A8684 -sub_80A8684: + thumb_func_start GroundLives_Delete +GroundLives_Delete: push {r4,lr} adds r2, r0, 0 lsls r2, 16 @@ -303780,7 +303780,7 @@ sub_80A8684: _080A86BC: .4byte gUnknown_3001B84 _080A86C0: .4byte gUnknown_8118194 _080A86C4: .4byte 0x0000ffff - thumb_func_end sub_80A8684 + thumb_func_end GroundLives_Delete thumb_func_start sub_80A86C8 sub_80A86C8: @@ -309318,7 +309318,7 @@ _080AB278: b _080AB44C _080AB292: mov r0, r9 - bl sub_80A8684 + bl GroundLives_Delete b _080AB47C .align 2, 0 _080AB29C: .4byte gUnknown_3001B84 @@ -310631,8 +310631,8 @@ _080ABC54: .4byte gUnknown_81183E4 _080ABC58: .4byte gUnknown_81183F0 thumb_func_end GroundObject_Select - thumb_func_start sub_80ABC5C -sub_80ABC5C: + thumb_func_start GroundObject_Cancel +GroundObject_Cancel: push {r4-r7,lr} mov r7, r8 push {r7} @@ -310689,10 +310689,10 @@ _080ABCA6: .align 2, 0 _080ABCC4: .4byte gUnknown_8118414 _080ABCC8: .4byte gUnknown_3001B88 - thumb_func_end sub_80ABC5C + thumb_func_end GroundObject_Cancel - thumb_func_start sub_80ABCCC -sub_80ABCCC: + thumb_func_start GroundObject_CancelBlank +GroundObject_CancelBlank: push {r4-r7,lr} mov r7, r8 push {r7} @@ -310752,7 +310752,7 @@ _080ABD20: .align 2, 0 _080ABD40: .4byte gUnknown_811842C _080ABD44: .4byte gUnknown_3001B88 - thumb_func_end sub_80ABCCC + thumb_func_end GroundObject_CancelBlank thumb_func_start sub_80ABD48 sub_80ABD48: @@ -312792,7 +312792,7 @@ _080ACBE4: cmp r0, r6 beq _080ACBF2 adds r0, r1, 0 - bl sub_80AD080 + bl GroundEffect_Delete _080ACBF2: adds r0, r5, 0 movs r1, 0x80 @@ -312882,8 +312882,8 @@ _080ACC90: .4byte gUnknown_8118610 _080ACC94: .4byte gUnknown_811861C thumb_func_end GroundEffect_Select - thumb_func_start sub_80ACC98 -sub_80ACC98: + thumb_func_start GroundEffect_Cancel +GroundEffect_Cancel: push {r4-r7,lr} mov r7, r8 push {r7} @@ -312920,7 +312920,7 @@ _080ACCC0: bne _080ACCE2 _080ACCDC: adds r0, r1, 0 - bl sub_80AD080 + bl GroundEffect_Delete _080ACCE2: adds r0, r6, 0 movs r1, 0x80 @@ -312940,10 +312940,10 @@ _080ACCE2: .align 2, 0 _080ACD00: .4byte gUnknown_8118640 _080ACD04: .4byte gUnknown_3001B8C - thumb_func_end sub_80ACC98 + thumb_func_end GroundEffect_Cancel - thumb_func_start sub_80ACD08 -sub_80ACD08: + thumb_func_start GroundEffect_CancelBlank +GroundEffect_CancelBlank: push {r4-r7,lr} mov r7, r8 push {r7} @@ -312983,7 +312983,7 @@ _080ACD2C: cmp r0, 0 bne _080ACD5C adds r0, r6, 0 - bl sub_80AD080 + bl GroundEffect_Delete _080ACD5C: adds r0, r6, 0x1 lsls r0, 16 @@ -313003,7 +313003,7 @@ _080ACD5C: .align 2, 0 _080ACD7C: .4byte gUnknown_8118658 _080ACD80: .4byte gUnknown_3001B8C - thumb_func_end sub_80ACD08 + thumb_func_end GroundEffect_CancelBlank thumb_func_start sub_80ACD84 sub_80ACD84: @@ -313399,8 +313399,8 @@ _080AD078: .4byte gUnknown_812F1F8 _080AD07C: .4byte gUnknown_81186CC thumb_func_end GroundEffect_Add - thumb_func_start sub_80AD080 -sub_80AD080: + thumb_func_start GroundEffect_Delete +GroundEffect_Delete: push {r4,lr} adds r2, r0, 0 lsls r2, 16 @@ -313432,7 +313432,7 @@ sub_80AD080: _080AD0BC: .4byte gUnknown_3001B8C _080AD0C0: .4byte gUnknown_81186D8 _080AD0C4: .4byte 0x0000ffff - thumb_func_end sub_80AD080 + thumb_func_end GroundEffect_Delete thumb_func_start sub_80AD0C8 sub_80AD0C8: @@ -314398,7 +314398,7 @@ _080AD72C: cmp r0, 0x4 bne _080AD768 adds r0, r7, 0 - bl sub_80AD080 + bl GroundEffect_Delete b _080AD78A .align 2, 0 _080AD754: .4byte gUnknown_3001B8C diff --git a/asm/m4a.s b/asm/m4a.s index 7133670..602f9b9 100644 --- a/asm/m4a.s +++ b/asm/m4a.s @@ -1,5 +1,6 @@ - .include "constants/gba_constants.inc" .include "asm/macros.inc" + .include "constants/gba_constants.inc" + .include "constants/m4a_constants.inc" .syntax unified @@ -18,16 +19,16 @@ _080AE268: thumb_func_start SoundMain SoundMain: - ldr r0, _080AE2E0 + ldr r0, lt_SOUND_INFO_PTR ldr r0, [r0] - ldr r2, _080AE2E4 - ldr r3, [r0] + ldr r2, lt_ID_NUMBER + ldr r3, [r0, o_SoundInfo_ident] cmp r2, r3 - beq _080AE282 - bx lr -_080AE282: - adds r3, 0x1 - str r3, [r0] + beq SoundMain_1 + bx lr @ Exit the function if ident doesn't match ID_NUMBER. +SoundMain_1: + adds r3, 1 + str r3, [r0, o_SoundInfo_ident] push {r4-r7,lr} mov r1, r8 mov r2, r9 @@ -35,65 +36,66 @@ _080AE282: mov r4, r11 push {r0-r4} sub sp, 0x18 - ldrb r1, [r0, 0xC] - cmp r1, 0 - beq _080AE2A6 - ldr r2, _080AE2EC + ldrb r1, [r0, o_SoundInfo_maxLines] + cmp r1, 0 @ if maxLines is 0, there is no maximum + beq SoundMain_3 + ldr r2, lt_REG_VCOUNT ldrb r2, [r2] - cmp r2, 0xA0 - bcs _080AE2A4 - adds r2, 0xE4 -_080AE2A4: + cmp r2, VCOUNT_VBLANK + bhs SoundMain_2 + adds r2, TOTAL_SCANLINES +SoundMain_2: adds r1, r2 -_080AE2A6: +SoundMain_3: str r1, [sp, 0x14] - ldr r3, [r0, 0x20] + ldr r3, [r0, o_SoundInfo_func] cmp r3, 0 - beq _080AE2B6 - ldr r0, [r0, 0x24] + beq SoundMain_4 + ldr r0, [r0, o_SoundInfo_intp] bl call_r3 ldr r0, [sp, 0x18] -_080AE2B6: - ldr r3, [r0, 0x28] +SoundMain_4: + ldr r3, [r0, o_SoundInfo_CgbSound] bl call_r3 ldr r0, [sp, 0x18] - ldr r3, [r0, 0x10] + ldr r3, [r0, o_SoundInfo_pcmSamplesPerVBlank] mov r8, r3 - ldr r5, _080AE2F0 + ldr r5, lt_o_SoundInfo_pcmBuffer adds r5, r0 - ldrb r4, [r0, 0x4] - subs r7, r4, 0x1 - bls _080AE2D6 - ldrb r1, [r0, 0xB] + ldrb r4, [r0, o_SoundInfo_pcmDmaCounter] + subs r7, r4, 1 + bls SoundMain_5 + ldrb r1, [r0, o_SoundInfo_pcmDmaPeriod] subs r1, r7 mov r2, r8 muls r2, r1 adds r5, r2 -_080AE2D6: +SoundMain_5: str r5, [sp, 0x8] - ldr r6, _080AE2F4 - ldr r3, _080AE2E8 + ldr r6, lt_PCM_DMA_BUF_SIZE + ldr r3, lt_SoundMainRAM_Buffer bx r3 + .align 2, 0 -_080AE2E0: .4byte SOUND_INFO_PTR -_080AE2E4: .4byte 0x68736d53 -_080AE2E8: .4byte SoundMainRAM_Buffer + 1 -_080AE2EC: .4byte 0x04000006 -_080AE2F0: .4byte 0x00000350 -_080AE2F4: .4byte 0x00000630 +lt_SOUND_INFO_PTR: .word SOUND_INFO_PTR +lt_ID_NUMBER: .word ID_NUMBER +lt_SoundMainRAM_Buffer: .word SoundMainRAM_Buffer + 1 +lt_REG_VCOUNT: .word REG_VCOUNT +lt_o_SoundInfo_pcmBuffer: .word o_SoundInfo_pcmBuffer +lt_PCM_DMA_BUF_SIZE: .word PCM_DMA_BUF_SIZE thumb_func_end SoundMain - thumb_func_start sub_80AE2F8 -sub_80AE2F8: - ldrb r3, [r0, 0x5] + thumb_func_start SoundMainRAM +SoundMainRAM: + ldrb r3, [r0, o_SoundInfo_reverb] cmp r3, 0 - beq _080AE358 - adr r1, _080AE304 + beq SoundMainRAM_NoReverb + adr r1, SoundMainRAM_Reverb bx r1 .arm -_080AE304: +SoundMainRAM_Reverb: cmp r4, 0x2 - addeq r7, r0, 0x350 + addeq r7, r0, o_SoundInfo_pcmBuffer addne r7, r5, r8 mov r4, r8 _080AE314: @@ -115,22 +117,22 @@ _080AE314: add r0, pc, 0x2F bx r0 .thumb -_080AE358: +SoundMainRAM_NoReverb: movs r0, 0 mov r1, r8 adds r6, r5 lsrs r1, 3 - bcc _080AE366 + bcc SoundMainRAM_NoReverb_Ok stm r5!, {r0} stm r6!, {r0} -_080AE366: +SoundMainRAM_NoReverb_Ok: lsrs r1, 1 - bcc _080AE372 + bcc SoundMainRAM_NoReverb_Loop stm r5!, {r0} stm r6!, {r0} stm r5!, {r0} stm r6!, {r0} -_080AE372: +SoundMainRAM_NoReverb_Loop: stm r5!, {r0} stm r6!, {r0} stm r5!, {r0} @@ -140,31 +142,33 @@ _080AE372: stm r5!, {r0} stm r6!, {r0} subs r1, 0x1 - bgt _080AE372 + bgt SoundMainRAM_NoReverb_Loop +_080AE386: ldr r4, [sp, 0x18] - ldr r0, [r4, 0x18] + ldr r0, [r4, o_SoundInfo_divFreq] mov r12, r0 - ldrb r0, [r4, 0x6] - adds r4, 0x50 -_080AE390: + ldrb r0, [r4, o_SoundInfo_maxChans] + adds r4, o_SoundInfo_chans +SoundMainRAM_ChanLoop: str r0, [sp, 0x4] - ldr r3, [r4, 0x24] + ldr r3, [r4, o_SoundChannel_wav] ldr r0, [sp, 0x14] cmp r0, 0 beq _080AE3B0 - ldr r1, _080AE3AC + ldr r1, =REG_VCOUNT ldrb r1, [r1] - cmp r1, 0xA0 - bcs _080AE3A4 - adds r1, 0xE4 + cmp r1, VCOUNT_VBLANK + bhs _080AE3A4 + adds r1, TOTAL_SCANLINES _080AE3A4: cmp r1, r0 bcc _080AE3B0 b _080AE682 - .align 2, 0 -_080AE3AC: .4byte 0x04000006 + + .pool + _080AE3B0: - ldrb r6, [r4] + ldrb r6, [r4, o_SoundChannel_status] movs r0, 0xC7 tst r0, r6 bne _080AE3BA @@ -177,96 +181,96 @@ _080AE3BA: tst r0, r6 bne _080AE3FA movs r6, 0x3 - strb r6, [r4] + strb r6, [r4, o_SoundChannel_status] adds r0, r3, 0 adds r0, 0x10 - str r0, [r4, 0x28] + str r0, [r4, o_SoundChannel_cp] ldr r0, [r3, 0xC] - str r0, [r4, 0x18] + str r0, [r4, o_SoundChannel_ct] movs r5, 0 - strb r5, [r4, 0x9] - str r5, [r4, 0x1C] + strb r5, [r4, o_SoundChannel_ev] + str r5, [r4, o_SoundChannel_fw] ldrb r2, [r3, 0x3] movs r0, 0xC0 tst r0, r2 beq _080AE442 movs r0, 0x10 orrs r6, r0 - strb r6, [r4] + strb r6, [r4, o_SoundChannel_status] b _080AE442 _080AE3EA: - ldrb r5, [r4, 0x9] + ldrb r5, [r4, o_SoundChannel_ev] movs r0, 0x4 tst r0, r6 beq _080AE400 - ldrb r0, [r4, 0xD] + ldrb r0, [r4, o_SoundChannel_iel] subs r0, 0x1 - strb r0, [r4, 0xD] + strb r0, [r4, o_SoundChannel_iel] bhi _080AE450 _080AE3FA: movs r0, 0 - strb r0, [r4] + strb r0, [r4, o_SoundChannel_status] b _080AE678 _080AE400: movs r0, 0x40 tst r0, r6 beq _080AE420 - ldrb r0, [r4, 0x7] + ldrb r0, [r4, o_SoundChannel_release] muls r5, r0 lsrs r5, 8 - ldrb r0, [r4, 0xC] + ldrb r0, [r4, o_SoundChannel_iev] cmp r5, r0 bhi _080AE450 _080AE412: - ldrb r5, [r4, 0xC] + ldrb r5, [r4, o_SoundChannel_iev] cmp r5, 0 beq _080AE3FA movs r0, 0x4 orrs r6, r0 - strb r6, [r4] + strb r6, [r4, o_SoundChannel_status] b _080AE450 _080AE420: movs r2, 0x3 ands r2, r6 cmp r2, 0x2 bne _080AE43E - ldrb r0, [r4, 0x5] + ldrb r0, [r4, o_SoundChannel_decay] muls r5, r0 lsrs r5, 8 - ldrb r0, [r4, 0x6] + ldrb r0, [r4, o_SoundChannel_sustain] cmp r5, r0 bhi _080AE450 adds r5, r0, 0 beq _080AE412 subs r6, 0x1 - strb r6, [r4] + strb r6, [r4, o_SoundChannel_status] b _080AE450 _080AE43E: cmp r2, 0x3 bne _080AE450 _080AE442: - ldrb r0, [r4, 0x4] + ldrb r0, [r4, o_SoundChannel_attack] adds r5, r0 cmp r5, 0xFF bcc _080AE450 movs r5, 0xFF subs r6, 0x1 - strb r6, [r4] + strb r6, [r4, o_SoundChannel_status] _080AE450: - strb r5, [r4, 0x9] + strb r5, [r4, o_SoundChannel_ev] ldr r0, [sp, 0x18] - ldrb r0, [r0, 0x7] + ldrb r0, [r0, o_SoundChannel_release] adds r0, 0x1 muls r0, r5 lsrs r5, r0, 4 - ldrb r0, [r4, 0x2] + ldrb r0, [r4, o_SoundChannel_rightVolume] muls r0, r5 lsrs r0, 8 - strb r0, [r4, 0xA] - ldrb r0, [r4, 0x3] + strb r0, [r4, o_SoundChannel_er] + ldrb r0, [r4, o_SoundChannel_leftVolume] muls r0, r5 lsrs r0, 8 - strb r0, [r4, 0xB] + strb r0, [r4, o_SoundChannel_el] movs r0, 0x10 ands r0, r6 str r0, [sp, 0x10] @@ -281,18 +285,18 @@ _080AE450: str r0, [sp, 0x10] _080AE484: ldr r5, [sp, 0x8] - ldr r2, [r4, 0x18] - ldr r3, [r4, 0x28] + ldr r2, [r4, o_SoundChannel_ct] + ldr r3, [r4, o_SoundChannel_cp] adr r0, _080AE490 bx r0 .arm _080AE490: str r8, [sp] - ldrb r10, [r4, 0xA] - ldrb r11, [r4, 0xB] + ldrb r10, [r4, o_SoundChannel_er] + ldrb r11, [r4, o_SoundChannel_el] mov r10, r10, lsl 16 mov r11, r11, lsl 16 - ldrb r0, [r4, 0x1] + ldrb r0, [r4, o_SoundChannel_type] tst r0, 0x8 beq _080AE5D0 _080AE4B0: @@ -368,7 +372,7 @@ _080AE598: ldrne r3, [sp, 0xC] bne _080AE54C _080AE5A8: - strb r2, [r4] + strb r2, [r4, o_SoundChannel_status] mov r0, r5, lsr 30 bic r5, r5, 0xC0000000 rsb r0, r0, 0x3 @@ -380,8 +384,8 @@ _080AE5A8: b _080AE66C _080AE5D0: stmdb sp!, {r4,r12} - ldr lr, [r4, 0x1C] - ldr r1, [r4, 0x20] + ldr lr, [r4, o_SoundChannel_fw] + ldr r1, [r4, o_SoundChannel_freq] mul r4, r12, r1 ldrsb r0, [r3] ldrsb r1, [r3, 0x1]! @@ -419,10 +423,10 @@ _080AE640: bgt _080AE5EC sub r3, r3, 0x1 ldmia sp!, {r4,r12} - str lr, [r4, 0x1C] + str lr, [r4, o_SoundChannel_fw] _080AE664: - str r2, [r4, 0x18] - str r3, [r4, 0x28] + str r2, [r4, o_SoundChannel_ct] + str r3, [r4, o_SoundChannel_cp] _080AE66C: ldr r8, [sp] add r0, pc, 0x1 @@ -432,11 +436,11 @@ _080AE678: ldr r0, [sp, 0x4] subs r0, 0x1 ble _080AE682 - adds r4, 0x40 - b _080AE390 + adds r4, SoundChannel_size + b SoundMainRAM_ChanLoop _080AE682: ldr r0, [sp, 0x18] - ldr r3, _080AE698 + ldr r3, =ID_NUMBER str r3, [r0] add sp, 0x1C pop {r0-r7} @@ -448,10 +452,8 @@ _080AE682: call_r3: bx r3 - - .align 2, 0 -_080AE698: .4byte 0x68736D53 - thumb_func_end sub_80AE2F8 + .pool + thumb_func_end SoundMainRAM thumb_func_start sub_80AE69C sub_80AE69C: @@ -1770,7 +1772,7 @@ _080AEF72: pop {r0} bx r0 .align 2, 0 -_080AEF78: .4byte sub_80AE2F8 +_080AEF78: .4byte SoundMainRAM _080AEF7C: .4byte SoundMainRAM_Buffer _080AEF80: .4byte 0x04000100 _080AEF84: .4byte gUnknown_2039ED0 diff --git a/asm/memory.s b/asm/memory.s index 418056c..1b9d36e 100644 --- a/asm/memory.s +++ b/asm/memory.s @@ -5,107 +5,6 @@ .text - thumb_func_start InitHeapInternal -InitHeapInternal: - push {lr} - sub sp, 0x8 - ldr r0, =gHeap - str r0, [sp] - movs r0, 0x90 - lsls r0, 10 - str r0, [sp, 0x4] - ldr r1, =gUnknown_2000EA8 - movs r0, 0 - str r0, [r1] - ldr r0, =gUnknown_2000EB0 - ldr r2, =gHeapHeader - mov r1, sp - movs r3, 0x20 - bl DoInitHeap - add sp, 0x8 - pop {r0} - bx r0 - .align 2, 0 - .pool - thumb_func_end InitHeapInternal - - thumb_func_start DoInitHeap -DoInitHeap: - push {r4-r6,lr} - mov r6, r9 - mov r5, r8 - push {r5,r6} - ldr r4, [r1, 0x4] - mov r9, r4 - movs r4, 0x4 - negs r4, r4 - mov r5, r9 - ands r5, r4 - mov r9, r5 - ldr r6, =gUnknown_2000E88 - ldr r4, =gUnknown_2000EA8 - mov r8, r4 - ldr r5, [r4] - lsls r4, r5, 2 - adds r4, r6 - str r0, [r4] - adds r5, 0x1 - mov r4, r8 - str r5, [r4] - ldr r5, [r1] - str r5, [r0, 0x14] - mov r1, r9 - str r1, [r0, 0x18] - movs r1, 0x2 - str r1, [r0] - movs r4, 0 - str r4, [r0, 0x4] - str r2, [r0, 0x8] - movs r1, 0x1 - str r1, [r0, 0xC] - str r3, [r0, 0x10] - str r4, [r2] - str r4, [r2, 0x4] - str r5, [r2, 0xC] - mov r5, r9 - str r5, [r2, 0x10] - str r4, [r2, 0x14] - str r4, [r2, 0x8] - pop {r3,r4} - mov r8, r3 - mov r9, r4 - pop {r4-r6} - pop {r0} - bx r0 - .align 2, 0 - .pool - thumb_func_end DoInitHeap - - thumb_func_start InitSubHeap -InitSubHeap: - push {r4,r5,lr} - sub sp, 0x8 - adds r3, r2, 0 - lsls r4, r3, 1 - adds r4, r3 - movs r2, 0x4 - negs r2, r2 - lsls r4, 3 - ldr r5, [r1, 0x4] - subs r5, r4 - ands r5, r2 - ldr r2, [r1] - adds r4, r2, r4 - str r4, [sp] - str r5, [sp, 0x4] - mov r1, sp - bl DoInitHeap - add sp, 0x8 - pop {r4,r5} - pop {r0} - bx r0 - thumb_func_end InitSubHeap - thumb_func_start xxx_memory_attr_related xxx_memory_attr_related: push {lr} @@ -201,7 +100,7 @@ _080030C2: _080030CC: movs r7, 0x1 negs r7, r7 - ldr r1, =0x24001 + ldr r1, _08003100 movs r4, 0 ldr r3, [r5, 0x8] ldr r2, [r5, 0xC] @@ -229,7 +128,7 @@ _080030FC: adds r0, r7, 0 b _08003108 .align 2, 0 - .pool +_08003100: .4byte 0x00024001 _08003104: movs r0, 0x1 negs r0, r0 @@ -555,7 +454,7 @@ _LocateSet: adds r6, r2, 0 cmp r5, 0 bne _0800335C - ldr r5, =gUnknown_2000EB0 + ldr r5, =gMainHeapDescriptor _0800335C: asrs r4, r6, 8 movs r0, 0x1 @@ -619,7 +518,7 @@ MemoryAlloc: push {lr} adds r3, r0, 0 adds r2, r1, 0 - ldr r0, =gUnknown_2000EB0 + ldr r0, =gMainHeapDescriptor adds r1, r3, 0 bl DoAlloc pop {r1} @@ -632,7 +531,7 @@ MemoryAlloc: MemoryFree: push {lr} adds r1, r0, 0 - ldr r0, =gUnknown_2000EB0 + ldr r0, =gMainHeapDescriptor bl DoFree pop {r0} bx r0 @@ -650,7 +549,7 @@ MemoryLocate_LocalCreate: adds r6, r3, 0 cmp r4, 0 bne _08003412 - ldr r4, =gUnknown_2000EB0 + ldr r4, =gMainHeapDescriptor _08003412: adds r0, r4, 0 movs r1, 0x9 @@ -728,11 +627,11 @@ _080034A2: movs r0, 0 mov r12, r0 movs r3, 0 - ldr r6, =gUnknown_2000EA8 + ldr r6, =gHeapCount ldr r0, [r6] cmp r12, r0 bge _080034F2 - ldr r5, =gUnknown_2000E88 + ldr r5, =gHeapDescriptorList adds r1, r6, 0 adds r7, r5, 0 movs r2, 0 @@ -746,7 +645,7 @@ _080034BC: str r0, [r1] cmp r3, r0 bge _080034F8 - ldr r1, =gUnknown_2000EA8 + ldr r1, =gHeapCount adds r2, r7 _080034D2: ldr r0, [r2, 0x4] @@ -800,7 +699,7 @@ DoFree: adds r4, r0, 0 cmp r4, 0 bne _0800352E - ldr r4, =gUnknown_2000EB0 + ldr r4, =gMainHeapDescriptor _0800352E: cmp r1, 0 beq _080035E4 diff --git a/asm/rom_header.inc b/asm/rom_header.inc index 09b95ec..6730efa 100644 --- a/asm/rom_header.inc +++ b/asm/rom_header.inc @@ -1,37 +1,19 @@ .global RomHeaderNintendoLogo RomHeaderNintendoLogo: - .byte 0x24,0xff,0xae,0x51,0x69,0x9a,0xa2,0x21 - .byte 0x3d,0x84,0x82,0x0a,0x84,0xe4,0x09,0xad - .byte 0x11,0x24,0x8b,0x98,0xc0,0x81,0x7f,0x21 - .byte 0xa3,0x52,0xbe,0x19,0x93,0x09,0xce,0x20 - .byte 0x10,0x46,0x4a,0x4a,0xf8,0x27,0x31,0xec - .byte 0x58,0xc7,0xe8,0x33,0x82,0xe3,0xce,0xbf - .byte 0x85,0xf4,0xdf,0x94,0xce,0x4b,0x09,0xc1 - .byte 0x94,0x56,0x8a,0xc0,0x13,0x72,0xa7,0xfc - .byte 0x9f,0x84,0x4d,0x73,0xa3,0xca,0x9a,0x61 - .byte 0x58,0x97,0xa3,0x27,0xfc,0x03,0x98,0x76 - .byte 0x23,0x1d,0xc7,0x61,0x03,0x04,0xae,0x56 - .byte 0xbf,0x38,0x84,0x00,0x40,0xa7,0x0e,0xfd - .byte 0xff,0x52,0xfe,0x03,0x6f,0x95,0x30,0xf1 - .byte 0x97,0xfb,0xc0,0x85,0x60,0xd6,0x80,0x25 - .byte 0xa9,0x63,0xbe,0x03,0x01,0x4e,0x38,0xe2 - .byte 0xf9,0xa2,0x34,0xff,0xbb,0x3e,0x03,0x44 - .byte 0x78,0x00,0x90,0xcb,0x88,0x11,0x3a,0x94 - .byte 0x65,0xc0,0x7c,0x63,0x87,0xf0,0x3c,0xaf - .byte 0xd6,0x25,0xe4,0x8b,0x38,0x0a,0xac,0x72 - .byte 0x21,0xd4,0xf8,0x07 + .space 156 RomHeaderGameTitle: - .ascii "POKE DUNGEON" + .space 12 + .global RomHeaderGameCode RomHeaderGameCode: - .ascii "B24E" + .space 4 RomHeaderMakerCode: - .ascii "01" + .space 2 RomHeaderMagic: - .byte 0x96 + .byte 0 RomHeaderMainUnitCode: .byte 0 @@ -42,11 +24,12 @@ RomHeaderDeviceType: RomHeaderReserved1: .space 7 + .global RomHeaderSoftwareVersion RomHeaderSoftwareVersion: .byte 0 RomHeaderChecksum: - .byte 0xA4 + .byte 0 RomHeaderReserved2: .space 2 diff --git a/asm/save.s b/asm/save.s index b4e748f..2ebaaa4 100644 --- a/asm/save.s +++ b/asm/save.s @@ -5,48 +5,18 @@ .text - thumb_func_start sub_8011C7C -sub_8011C7C: - push {r4,lr} - adds r4, r0, 0 - movs r2, 0 - lsrs r1, 2 - cmp r1, 0x1 - ble _08011C96 - adds r3, r4, 0x4 - subs r1, 0x1 -_08011C8C: - ldm r3!, {r0} - adds r2, r0 - subs r1, 0x1 - cmp r1, 0 - bne _08011C8C -_08011C96: - ldr r0, [r4] - cmp r0, r2 - bne _08011CA0 - movs r0, 0 - b _08011CA2 -_08011CA0: - movs r0, 0x1 -_08011CA2: - pop {r4} - pop {r1} - bx r1 - thumb_func_end sub_8011C7C - thumb_func_start sub_8011CA8 sub_8011CA8: push {lr} adds r3, r0, 0 adds r2, r1, 0 - ldr r0, _08011CCC + ldr r0, =gUnknown_203B184 ldr r0, [r0] - ldr r0, _08011CD0 + ldr r0, =0xfff adds r1, r2, r0 cmp r1, 0 bge _08011CBE - ldr r0, _08011CD4 + ldr r0, =0x1ffe adds r1, r2, r0 _08011CBE: asrs r1, 12 @@ -56,13 +26,11 @@ _08011CBE: pop {r0} bx r0 .align 2, 0 -_08011CCC: .4byte gUnknown_203B184 -_08011CD0: .4byte 0x00000fff -_08011CD4: .4byte 0x00001ffe + .pool thumb_func_end sub_8011CA8 - thumb_func_start sub_8011CD8 -sub_8011CD8: + thumb_func_start WriteSaveSector +WriteSaveSector: push {r4-r6,lr} adds r5, r1, 0 adds r4, r2, 0 @@ -71,7 +39,7 @@ sub_8011CD8: bl sub_8011CA8 adds r0, r5, 0 adds r1, r4, 0 - bl sub_8011C58 + bl CalculateChecksum ldr r0, _08011D04 ldr r0, [r0] cmp r0, 0 @@ -115,10 +83,10 @@ _08011D3A: pop {r4-r6} pop {r1} bx r1 - thumb_func_end sub_8011CD8 + thumb_func_end WriteSaveSector - thumb_func_start sub_8011D40 -sub_8011D40: + thumb_func_start ReadSaveSector +ReadSaveSector: push {r4-r6,lr} adds r5, r1, 0 adds r4, r2, 0 @@ -160,7 +128,7 @@ _08011D8A: _08011D8E: adds r0, r5, 0 adds r1, r4, 0 - bl sub_8011C7C + bl ValidateChecksum lsls r0, 24 cmp r0, 0 bne _08011DA0 @@ -172,7 +140,7 @@ _08011DA2: pop {r4-r6} pop {r1} bx r1 - thumb_func_end sub_8011D40 + thumb_func_end ReadSaveSector thumb_func_start sub_8011DA8 sub_8011DA8: @@ -197,14 +165,14 @@ sub_8011DAC: adds r0, r6, 0 adds r1, r5, 0 mov r2, r8 - bl sub_8011D40 + bl ReadSaveSector adds r7, r0, 0 cmp r7, 0 beq _08011DE8 adds r0, r6, 0 adds r1, r5, 0 mov r2, r8 - bl sub_8011D40 + bl ReadSaveSector adds r7, r0, 0 b _08011DF0 .align 2, 0 @@ -423,7 +391,7 @@ _08011F98: .4byte 0x00000444 thumb_func_start sub_8011F9C sub_8011F9C: push {lr} - bl sub_8011D40 + bl ReadSaveSector pop {r1} bx r1 thumb_func_end sub_8011F9C @@ -443,7 +411,7 @@ sub_8011FA8: mov r0, sp adds r1, r5, 0 adds r2, r4, 0 - bl sub_8011D40 + bl ReadSaveSector adds r2, r0, 0 cmp r2, 0 bne _08011FD8 @@ -486,7 +454,7 @@ sub_8011FF8: mov r0, sp adds r1, r5, 0 adds r2, r4, 0 - bl sub_8011D40 + bl ReadSaveSector cmp r0, 0 bne _08012028 ldr r1, [r5, 0x14] @@ -654,12 +622,12 @@ _080120E8: adds r0, r7, 0 adds r1, r6, 0 adds r2, r4, 0 - bl sub_8011CD8 + bl WriteSaveSector adds r5, r0, 0 adds r0, r7, 0 adds r1, r6, 0 adds r2, r4, 0 - bl sub_8011CD8 + bl WriteSaveSector adds r4, r0, 0 adds r0, r6, 0 bl MemoryFree @@ -692,7 +660,7 @@ _080121CE: thumb_func_start sub_80121D4 sub_80121D4: push {lr} - bl sub_8011CD8 + bl WriteSaveSector pop {r1} bx r1 thumb_func_end sub_80121D4 @@ -728,7 +696,7 @@ sub_80121E0: mov r0, sp adds r1, r4, 0 adds r2, r6, 0 - bl sub_8011CD8 + bl WriteSaveSector adds r5, r0, 0 adds r0, r4, 0 bl MemoryFree @@ -1724,22 +1692,4 @@ _080129F2: bx r1 thumb_func_end sub_80128B0 - thumb_func_start sub_80129FC -sub_80129FC: - push {r4,lr} - ldr r4, _08012A14 - ldr r0, [r4] - cmp r0, 0 - beq _08012A0E - bl MemoryFree - movs r0, 0 - str r0, [r4] -_08012A0E: - pop {r4} - pop {r0} - bx r0 - .align 2, 0 -_08012A14: .4byte gUnknown_203B194 - thumb_func_end sub_80129FC - .align 2, 0 @ Don't pad with nop. diff --git a/asm/sprite.s b/asm/sprite.s index 5081f37..06d87f0 100644 --- a/asm/sprite.s +++ b/asm/sprite.s @@ -5,17 +5,6 @@ .text - thumb_func_start InitSprites -InitSprites: - push {lr} - movs r0, 0x1 - bl sub_8004D8C - movs r0, 0 - bl SetSavingIconCoords - pop {r0} - bx r0 - thumb_func_end InitSprites - thumb_func_start sub_8004D8C sub_8004D8C: push {r4,r5,lr} diff --git a/asm/text.s b/asm/text.s index a8e6dc5..bf0c037 100644 --- a/asm/text.s +++ b/asm/text.s @@ -121,7 +121,7 @@ _080062AC: _080062F4: .4byte gUnknown_20274AC _080062F8: .4byte gUnknown_80B87B4 _080062FC: .4byte gUnknown_8300500 -_08006300: .4byte gUnknown_202AFB4 +_08006300: .4byte gKanji _08006304: .4byte gUnknown_80B87BC _08006308: .4byte gUnknown_2027490 _0800630C: .4byte gUnknown_202B028 diff --git a/constants/m4a_constants.inc b/constants/m4a_constants.inc new file mode 100644 index 0000000..62ca5bb --- /dev/null +++ b/constants/m4a_constants.inc @@ -0,0 +1,199 @@ + .equiv ID_NUMBER, 0x68736d53 + + .equiv PCM_DMA_BUF_SIZE, 1584 + + .equiv TONEDATA_TYPE_CGB, 0x07 + .equiv TONEDATA_TYPE_FIX, 0x08 + .equiv TONEDATA_TYPE_SPL, 0x40 @ key split + .equiv TONEDATA_TYPE_RHY, 0x80 @ rhythm + + .macro struct_begin + .struct 0 + .endm + + .macro struct_field name, size +\name: + .struct \name + \size + .endm + + struct_begin + struct_field o_SoundInfo_ident, 4 + struct_field o_SoundInfo_pcmDmaCounter, 1 + struct_field o_SoundInfo_reverb, 1 + struct_field o_SoundInfo_maxChans, 1 + struct_field o_SoundInfo_masterVolume, 1 + struct_field o_SoundInfo_freq, 1 + struct_field o_SoundInfo_mode, 1 + struct_field o_SoundInfo_c15, 1 + struct_field o_SoundInfo_pcmDmaPeriod, 1 + struct_field o_SoundInfo_maxLines, 1 + struct_field o_SoundInfo_gap, 3 + struct_field o_SoundInfo_pcmSamplesPerVBlank, 4 + struct_field o_SoundInfo_pcmFreq, 4 + struct_field o_SoundInfo_divFreq, 4 + struct_field o_SoundInfo_cgbChans, 4 + struct_field o_SoundInfo_func, 4 + struct_field o_SoundInfo_intp, 4 + struct_field o_SoundInfo_CgbSound, 4 + struct_field o_SoundInfo_CgbOscOff, 4 + struct_field o_SoundInfo_MidiKeyToCgbFreq, 4 + struct_field o_SoundInfo_MPlayJumpTable, 4 + struct_field o_SoundInfo_plynote, 4 + struct_field o_SoundInfo_ExtVolPit, 4 + struct_field o_SoundInfo_gap2, 16 + struct_field o_SoundInfo_chans, 768 + struct_field o_SoundInfo_pcmBuffer, PCM_DMA_BUF_SIZE * 2 + struct_field SoundInfo_size, 0 + + struct_begin + struct_field o_SoundChannel_status, 1 + struct_field o_SoundChannel_type, 1 + struct_field o_SoundChannel_rightVolume, 1 + struct_field o_SoundChannel_leftVolume, 1 + struct_field o_SoundChannel_attack, 1 + struct_field o_SoundChannel_decay, 1 + struct_field o_SoundChannel_sustain, 1 + struct_field o_SoundChannel_release, 1 + struct_field o_SoundChannel_ky, 1 + struct_field o_SoundChannel_ev, 1 + struct_field o_SoundChannel_er, 1 + struct_field o_SoundChannel_el, 1 + struct_field o_SoundChannel_iev, 1 + struct_field o_SoundChannel_iel, 1 + struct_field o_SoundChannel_d1, 1 + struct_field o_SoundChannel_d2, 1 + struct_field o_SoundChannel_gt, 1 + struct_field o_SoundChannel_mk, 1 + struct_field o_SoundChannel_ve, 1 + struct_field o_SoundChannel_pr, 1 + struct_field o_SoundChannel_rp, 1 + struct_field o_SoundChannel_d3, 3 + struct_field o_SoundChannel_ct, 4 + struct_field o_SoundChannel_fw, 4 + struct_field o_SoundChannel_freq, 4 + struct_field o_SoundChannel_wav, 4 + struct_field o_SoundChannel_cp, 4 + struct_field o_SoundChannel_track, 4 + struct_field o_SoundChannel_pp, 4 + struct_field o_SoundChannel_np, 4 + struct_field o_SoundChannel_d4, 4 + struct_field o_SoundChannel_xpi, 2 + struct_field o_SoundChannel_xpc, 2 + struct_field SoundChannel_size, 0 + + struct_begin + struct_field o_MusicPlayerTrack_flags, 1 + struct_field o_MusicPlayerTrack_wait, 1 + struct_field o_MusicPlayerTrack_patternLevel, 1 + struct_field o_MusicPlayerTrack_repN, 1 + struct_field o_MusicPlayerTrack_gateTime, 1 + struct_field o_MusicPlayerTrack_key, 1 + struct_field o_MusicPlayerTrack_velocity, 1 + struct_field o_MusicPlayerTrack_runningStatus, 1 + struct_field o_MusicPlayerTrack_keyM, 1 + struct_field o_MusicPlayerTrack_pitM, 1 + struct_field o_MusicPlayerTrack_keyShift, 1 + struct_field o_MusicPlayerTrack_keyShiftX, 1 + struct_field o_MusicPlayerTrack_tune, 1 + struct_field o_MusicPlayerTrack_pitX, 1 + struct_field o_MusicPlayerTrack_bend, 1 + struct_field o_MusicPlayerTrack_bendRange, 1 + struct_field o_MusicPlayerTrack_volMR, 1 + struct_field o_MusicPlayerTrack_volML, 1 + struct_field o_MusicPlayerTrack_vol, 1 + struct_field o_MusicPlayerTrack_volX, 1 + struct_field o_MusicPlayerTrack_pan, 1 + struct_field o_MusicPlayerTrack_panX, 1 + struct_field o_MusicPlayerTrack_modM, 1 + struct_field o_MusicPlayerTrack_mod, 1 + struct_field o_MusicPlayerTrack_modT, 1 + struct_field o_MusicPlayerTrack_lfoSpeed, 1 + struct_field o_MusicPlayerTrack_lfoSpeedC, 1 + struct_field o_MusicPlayerTrack_lfoDelay, 1 + struct_field o_MusicPlayerTrack_lfoDelayC, 1 + struct_field o_MusicPlayerTrack_priority, 1 + struct_field o_MusicPlayerTrack_echoVolume, 1 + struct_field o_MusicPlayerTrack_echoLength, 1 + struct_field o_MusicPlayerTrack_chan, 4 + struct_field o_MusicPlayerTrack_ToneData_type, 1 + struct_field o_MusicPlayerTrack_ToneData_key, 1 + struct_field o_MusicPlayerTrack_ToneData_length, 1 + struct_field o_MusicPlayerTrack_ToneData_pan_sweep, 1 + struct_field o_MusicPlayerTrack_ToneData_wav, 4 + struct_field o_MusicPlayerTrack_ToneData_attack, 1 + struct_field o_MusicPlayerTrack_ToneData_decay, 1 + struct_field o_MusicPlayerTrack_ToneData_sustain, 1 + struct_field o_MusicPlayerTrack_ToneData_release, 1 + struct_field o_MusicPlayerTrack_gap, 10 + struct_field o_MusicPlayerTrack_unk_3A, 2 + struct_field o_MusicPlayerTrack_unk_3C, 4 + struct_field o_MusicPlayerTrack_cmdPtr, 4 + struct_field o_MusicPlayerTrack_patternStack, 12 + struct_field MusicPlayerTrack_size, 0 + + .equiv o_MusicPlayerTrack_ToneData_keySplitTable, o_MusicPlayerTrack_ToneData_attack + + struct_begin + struct_field o_MusicPlayerInfo_songHeader, 4 + struct_field o_MusicPlayerInfo_status, 4 + struct_field o_MusicPlayerInfo_trackCount, 1 + struct_field o_MusicPlayerInfo_priority, 1 + struct_field o_MusicPlayerInfo_cmd, 1 + struct_field o_MusicPlayerInfo_unk_B, 1 + struct_field o_MusicPlayerInfo_clock, 4 + struct_field o_MusicPlayerInfo_gap, 8 + struct_field o_MusicPlayerInfo_memAccArea, 4 + struct_field o_MusicPlayerInfo_tempoD, 2 + struct_field o_MusicPlayerInfo_tempoU, 2 + struct_field o_MusicPlayerInfo_tempoI, 2 + struct_field o_MusicPlayerInfo_tempoC, 2 + struct_field o_MusicPlayerInfo_fadeOI, 2 + struct_field o_MusicPlayerInfo_fadeOC, 2 + struct_field o_MusicPlayerInfo_fadeOV, 2 + struct_field o_MusicPlayerInfo_padding, 2 + struct_field o_MusicPlayerInfo_tracks, 4 + struct_field o_MusicPlayerInfo_tone, 4 + struct_field o_MusicPlayerInfo_ident, 4 + struct_field o_MusicPlayerInfo_func, 4 + struct_field o_MusicPlayerInfo_intp, 4 + struct_field MusicPlayerInfo_size, 0 + + struct_begin + struct_field o_CgbChannel_sf, 1 + struct_field o_CgbChannel_ty, 1 + struct_field o_CgbChannel_rightVolume, 1 + struct_field o_CgbChannel_leftVolume, 1 + struct_field o_CgbChannel_at, 1 + struct_field o_CgbChannel_de, 1 + struct_field o_CgbChannel_su, 1 + struct_field o_CgbChannel_re, 1 + struct_field o_CgbChannel_ky, 1 + struct_field o_CgbChannel_ev, 1 + struct_field o_CgbChannel_eg, 1 + struct_field o_CgbChannel_ec, 1 + struct_field o_CgbChannel_echoVolume, 1 + struct_field o_CgbChannel_echoLength, 1 + struct_field o_CgbChannel_d1, 1 + struct_field o_CgbChannel_d2, 1 + struct_field o_CgbChannel_gt, 1 + struct_field o_CgbChannel_mk, 1 + struct_field o_CgbChannel_ve, 1 + struct_field o_CgbChannel_pr, 1 + struct_field o_CgbChannel_rp, 1 + struct_field o_CgbChannel_d3, 3 + struct_field o_CgbChannel_d5, 1 + struct_field o_CgbChannel_sg, 1 + struct_field o_CgbChannel_n4, 1 + struct_field o_CgbChannel_pan, 1 + struct_field o_CgbChannel_panMask, 1 + struct_field o_CgbChannel_mo, 1 + struct_field o_CgbChannel_le, 1 + struct_field o_CgbChannel_sw, 1 + struct_field o_CgbChannel_fr, 4 + struct_field o_CgbChannel_wp, 4 + struct_field o_CgbChannel_cp, 4 + struct_field o_CgbChannel_tp, 4 + struct_field o_CgbChannel_pp, 4 + struct_field o_CgbChannel_np, 4 + struct_field o_CgbChannel_d4, 8 + struct_field CgbChannel_size, 0 diff --git a/include/gba/defines.h b/include/gba/defines.h index 7fd429d..5f0123a 100644 --- a/include/gba/defines.h +++ b/include/gba/defines.h @@ -8,6 +8,8 @@ #define IWRAM_DATA __attribute__((section("iwram_data"))) #define EWRAM_DATA __attribute__((section("ewram_data"))) +#define UNUSED __attribute__((unused)) +#define NAKED __attribute__((naked)) #define ALIGNED(n) __attribute__((aligned(n))) @@ -59,4 +61,4 @@ #define WIN_RANGE(a, b) (((a) << 8) | (b)) -#endif // GUARD_GBA_DEFINES +#endif // GUARD_GBA_DEFINES \ No newline at end of file diff --git a/include/memory.h b/include/memory.h new file mode 100644 index 0000000..99b03e0 --- /dev/null +++ b/include/memory.h @@ -0,0 +1,56 @@ +#ifndef GUARD_MEMORY_H +#define GUARD_MEMORY_H + +#define HEAP_SIZE 0x24000 + +struct HeapSettings +{ + u8 *start; + u32 size; +}; + +struct HeapMemoryBlock { + u8 *start; + s32 size; + s32 allocatedSize; +}; + +struct HeapFreeListElement +{ + u32 unk_atb; + u32 atb; + u32 grp; + struct HeapMemoryBlock block; +}; + +struct HeapDescriptor +{ + u32 unk0; + u32 unk4; + struct HeapFreeListElement *freeList; + s32 freeCount; + u32 freeListLength; + u8 *start; + u32 size; +}; + +void InitHeap(void); + +void MemoryClear8(u8 *dest, s32 size); +void MemoryClear16(u16 *dest, s32 size); +void MemoryClear32(u32 *dest, s32 size); +void MemoryFill8(u8 *dest, u8 value, s32 size); +void MemoryFill16(u16 *dest, u16 value, s32 size); +void MemoryFill32(u32 *dest, u32 value, s32 size); +void MemoryCopy8(u8 *dest, u8 *src, s32 size); +void MemoryCopy16(u16 *dest, u16 *src, s32 size); +void MemoryCopy32(u32 *dest, u32 *src, s32 size); +void MemoryCopy8(u8 *dest, u8 *src, s32 size); +void MemoryCopy16(u16 *dest, u16 *src, s32 size); +void MemoryCopy32(u32 *dest, u32 *src, s32 size); + +void InitHeapInternal(void); +void DoInitHeap(struct HeapDescriptor *, struct HeapSettings *, struct HeapFreeListElement *, u32); +void InitSubHeap(struct HeapDescriptor *, struct HeapFreeListElement *, u32); + +#endif // GUARD_MEMORY_H \ No newline at end of file diff --git a/ld_script.txt b/ld_script.txt index d1bbded..304c9c8 100755 --- a/ld_script.txt +++ b/ld_script.txt @@ -57,6 +57,7 @@ SECTIONS { src/bg_palette_buffer.o(.text); asm/input.o(.text); asm/code_8004AA0.o(.text); + src/sprite.o(.text); asm/sprite.o(.text); asm/code_800558C.o(.text); src/random.o(.text); @@ -70,6 +71,7 @@ SECTIONS { asm/code_800D090.o(.text); src/save.o(.text); asm/save.o(.text); + src/save1.o(.text); asm/code_8012A18.o(.text); asm/m4a.o(.text); asm/syscall.o(.text); diff --git a/src/bg_palette_buffer.c b/src/bg_palette_buffer.c index 5e078a0..6301bfa 100644 --- a/src/bg_palette_buffer.c +++ b/src/bg_palette_buffer.c @@ -1,7 +1,10 @@ #include "global.h" -extern u16 gBGPaletteBuffer[512]; -extern bool8 gBGPaletteUsed[32]; +#define BG_PALETTE_BUFFER_SIZE 512 +#define BG_PALETTE_BUFFER_CHUNK_SIZE 16 + +extern u16 gBGPaletteBuffer[BG_PALETTE_BUFFER_SIZE]; +extern bool8 gBGPaletteUsed[BG_PALETTE_BUFFER_SIZE / BG_PALETTE_BUFFER_CHUNK_SIZE]; extern void CpuCopy(void* src, void* dest, u32 size); @@ -55,13 +58,13 @@ void SetBGPaletteBufferColorRGB(s32 index, u8 *RGBArray, s32 a3, u8 *a4) void SetBGPaletteBufferColorArray(s32 index, u8 *colorArray) { - gBGPaletteUsed[index / 16] = TRUE; + gBGPaletteUsed[index / BG_PALETTE_BUFFER_CHUNK_SIZE] = TRUE; gBGPaletteBuffer[index] = (colorArray[2] >> 3) << 10 | (colorArray[1] >> 3) << 5 | colorArray[0] >> 3; } void SetBGPaletteBufferColor(s32 index, u16 *color) { - gBGPaletteUsed[index / 16] = TRUE; + gBGPaletteUsed[index / BG_PALETTE_BUFFER_CHUNK_SIZE] = TRUE; gBGPaletteBuffer[index] = *color; } @@ -98,5 +101,5 @@ void TransferBGPaletteBuffer(void) dest += 16; paletteBufferIndex += 16; } - while ( paletteBufferIndex < 512 ); -} \ No newline at end of file + while ( paletteBufferIndex < BG_PALETTE_BUFFER_SIZE ); +} diff --git a/src/file_system.c b/src/file_system.c index 296478d..9c069ff 100644 --- a/src/file_system.c +++ b/src/file_system.c @@ -25,9 +25,9 @@ struct SiroArchive u8 *data; }; -extern struct OpenedFile gUnknown_202D2A8[]; +extern struct OpenedFile gFileCache[64]; -extern u32 gUnknown_203B094; +extern u32 gFileCacheCursorPosition; extern u32 gUnknown_202D2A4; extern int sprintf(char *, const char *, ...); @@ -41,11 +41,11 @@ void InitFileSystem(void) for (i = 0; i < 64; i++) { - gUnknown_202D2A8[i].file = NULL; - gUnknown_202D2A8[i].data = NULL; + gFileCache[i].file = NULL; + gFileCache[i].data = NULL; } - gUnknown_203B094 = 0; + gFileCacheCursorPosition = 0; gUnknown_202D2A4 = 1; } @@ -62,8 +62,8 @@ struct OpenedFile *OpenFile(char *filename, struct FileArchive *arc) s32 left, right; s32 cursor; s32 i; - s32 magic = 0; - s32 magicFound; + u32 magic = 0; + bool32 magicFound; struct File *entries; struct File *file; @@ -71,7 +71,7 @@ struct OpenedFile *OpenFile(char *filename, struct FileArchive *arc) magicFound = 0; - if (!(u8)magic) + if (!(bool8)magic) magicFound = 1; if (!magicFound) @@ -108,18 +108,18 @@ struct OpenedFile *OpenFile(char *filename, struct FileArchive *arc) return NULL; } - cursor = gUnknown_203B094; + cursor = gFileCacheCursorPosition; for (i = 0; i < 64; i++) { cursor++; if (cursor > 63) cursor = 0; - if (!gUnknown_202D2A8[cursor].file) + if (!gFileCache[cursor].file) { - gUnknown_202D2A8[cursor].file = file; - gUnknown_202D2A8[cursor].data = NULL; - return &gUnknown_202D2A8[cursor]; + gFileCache[cursor].file = file; + gFileCache[cursor].data = NULL; + return &gFileCache[cursor]; } } @@ -157,11 +157,11 @@ void CloseFile(struct OpenedFile *openedFile) for (i = 0; i < 64; i++) { - if (&gUnknown_202D2A8[i] == openedFile) + if (&gFileCache[i] == openedFile) { - gUnknown_202D2A8[i].file = NULL; - gUnknown_202D2A8[i].data = NULL; - gUnknown_203B094 = i; + gFileCache[i].file = NULL; + gFileCache[i].data = NULL; + gFileCacheCursorPosition = i; return; } } diff --git a/src/flash.c b/src/flash.c index b9ccf40..11520b4 100644 --- a/src/flash.c +++ b/src/flash.c @@ -1,12 +1,11 @@ #include "global.h" #include "gba/flash.h" #include "flash.h" +#include "memory.h" extern u8 gFlashEnabled; extern FlashIntrFunc *sub_800B6E8(s32); -extern void MemoryFill8(void *, u8, s32); -extern void MemoryCopy8(void *, void *, s32); static u8 TryProgramSector(s32, u8 *); diff --git a/src/memory.c b/src/memory.c index 1ccbe54..0d282d5 100644 --- a/src/memory.c +++ b/src/memory.c @@ -1,8 +1,16 @@ #include "global.h" +#include "memory.h" + +extern struct HeapFreeListElement gMainHeapFreeList[32]; +extern u8 gMainHeap[HEAP_SIZE]; +extern u32 gHeapCount; +extern struct HeapDescriptor gMainHeapDescriptor; +extern struct HeapDescriptor *gHeapDescriptorList[8]; -extern void InitHeapInternal(void); extern void CpuClear(u32 *dest, s32 size); +void InitHeapInternal(void); + void InitHeap(void) { InitHeapInternal(); @@ -82,4 +90,56 @@ void MemoryCopy32(u32 *dest, u32 *src, s32 size) size -= 4; *dest++ = *src++; } +} + +void InitHeapInternal(void) +{ + struct HeapSettings settings; + + settings.start = gMainHeap; + settings.size = HEAP_SIZE; + gHeapCount = 0; + DoInitHeap(&gMainHeapDescriptor, &settings, gMainHeapFreeList, sizeof(gMainHeapFreeList) / sizeof(struct HeapFreeListElement)); +} + +void DoInitHeap(struct HeapDescriptor *descriptor, struct HeapSettings *settings, struct HeapFreeListElement *freeList, u32 freeListLength) +{ + u32 aligned_size; + + aligned_size = settings->size & 0xFFFFFFFC; + + gHeapDescriptorList[gHeapCount++] = descriptor; + + descriptor->start = settings->start; + descriptor->size = aligned_size; + descriptor->unk0 = 2; + descriptor->unk4 = 0; + descriptor->freeList = freeList; + descriptor->freeCount = 1; + descriptor->freeListLength = freeListLength; + + freeList->unk_atb = 0; + freeList->atb = 0; + freeList->block.start = descriptor->start; + freeList->block.size = aligned_size; + freeList->block.allocatedSize = 0; + freeList->grp = 0; +} + +void InitSubHeap(struct HeapDescriptor *parentHeap, struct HeapFreeListElement *start, u32 freeListMax) +{ + u32 freeListSize; + u32 aligned_size; + u32 alignment; + struct HeapFreeListElement *freeList; + struct HeapSettings settings; + + freeListSize = freeListMax * 3; + alignment = ~3; + freeListSize *= 8; + aligned_size = (start->atb - freeListSize) & alignment; //possible struct misalignment? + freeList = (struct HeapFreeListElement *)start->unk_atb; + settings.start = &((u8 *)start->unk_atb)[freeListSize]; + settings.size = aligned_size; + DoInitHeap(parentHeap, &settings, freeList, freeListMax); } \ No newline at end of file diff --git a/src/save.c b/src/save.c index 575d4f1..5d39bfe 100644 --- a/src/save.c +++ b/src/save.c @@ -2,8 +2,10 @@ extern u32 gUnknown_203B17C; extern u32 gUnknown_203B180; +extern u32 *gUnknown_203B184; extern u32 gUnknown_202DE28; + u32 sub_8011C1C(void) { return gUnknown_203B17C; @@ -29,17 +31,34 @@ u32 sub_8011C4C(void) return gUnknown_203B180; } -void sub_8011C58(u32 *out, u32 len) +void CalculateChecksum(u8 *out, u32 size) { - u32 sum = 0; - s32 i = len / 4; + u32 checksum = 0; + s32 i = size / 4; if (i > 1) { - u32 *ptr = &out[1]; + u32 *ptr = (u32 *)&out[4]; --i; do - sum += *ptr++; + checksum += *ptr++; while (--i); } - *out = sum; -} \ No newline at end of file + *(u32 *)out = checksum; +} + +bool8 ValidateChecksum(u8 *in, u32 size) +{ + u32 checksum = 0; + s32 i = size / 4; + if (i > 1) + { + u32 *ptr = (u32 *)&in[4]; + --i; + do + checksum += *ptr++; + while (--i); + } + if (*(u32 *)in != checksum) + return TRUE; + return FALSE; +} diff --git a/src/save1.c b/src/save1.c new file mode 100644 index 0000000..94f9c2b --- /dev/null +++ b/src/save1.c @@ -0,0 +1,13 @@ +#include "global.h" + +extern void MemoryFree(void *); + +extern u8 *gUnknown_203B194; + +void sub_80129FC() +{ + if (gUnknown_203B194) { + MemoryFree(gUnknown_203B194); + gUnknown_203B194 = NULL; + } +} \ No newline at end of file diff --git a/src/sprite.c b/src/sprite.c new file mode 100644 index 0000000..41a2a96 --- /dev/null +++ b/src/sprite.c @@ -0,0 +1,10 @@ +#include "global.h" + +void sub_8004D8C(u32); +void SetSavingIconCoords(u32); + +void InitSprites(void) +{ + sub_8004D8C(1); + SetSavingIconCoords(0); +} \ No newline at end of file diff --git a/sym_ewram.txt b/sym_ewram.txt index fb753c9..517dfc5 100644 --- a/sym_ewram.txt +++ b/sym_ewram.txt @@ -15,19 +15,20 @@ gUnknown_2000A80 = .; /* 2000A80 */ gUnknown_2000A88 = .; /* 2000A88 */ . += 0x400; -gUnknown_2000E88 = .; /* 2000E88 */ +gHeapDescriptorList = .; /* 2000E88 */ . += 0x20; -gUnknown_2000EA8 = .; /* 2000EA8 */ - . += 0x8; +gHeapCount = .; /* 2000EA8 */ + . += 0x4; + . = ALIGN(16); -gUnknown_2000EB0 = .; /* 2000EB0 */ +gMainHeapDescriptor = .; /* 2000EB0 */ . += 0x20; -gHeapHeader = .; /* 2000ED0 */ +gMainHeapFreeList = .; /* 2000ED0 */ . += 0x300; -gHeap = .; /* 20011D0 */ +gMainHeap = .; /* 20011D0 */ . += 0x24000; gBGPaletteUsed = .; /* 20251D0 */ @@ -156,8 +157,11 @@ gUnknown_20274B0 = .; /* 20274B0 */ gUnknown_20274B4 = .; /* 20274B4 */ . += 0x3B00; -gUnknown_202AFB4 = .; /* 202AFB4 */ - . += 0xC; +gKanji = .; /* 202AFB4 */ + . += 0x8; + +gUnknown_202AFBC = .; /* 202AFBC */ + . += 0x4; gUnknown_202AFC0 = .; /* 202AFC0 */ . += 0x60; @@ -237,11 +241,8 @@ gUnknown_202D2A0 = .; /* 202D2A0 */ gUnknown_202D2A4 = .; /* 202D2A4 */ . += 0x4; -gUnknown_202D2A8 = .; /* 202D2A8 */ - . += 0x110; - -gUnknown_202D3B8 = .; /* 202D3B8 */ - . += 0xF0; +gFileCache = .; /* 202D2A8 */ + . += 0x200; gUnknown_202D4A8 = .; /* 202D4A8 */ . += 0x4; @@ -514,14 +515,11 @@ gUnknown_202EC4C = .; /* 202EC4C */ gUnknown_202EC50 = .; /* 202EC50 */ . += 0x38; -gUnknown_202EC88 = .; /* 202EC88 */ +gDungeonNameBannerPalette = .; /* 202EC88 */ . += 0x4; -gUnknown_202EC8C = .; /* 202EC8C */ - . += 0x4; - -gUnknown_202EC90 = .; /* 202EC90 */ - . += 0x4; +gDungeonNameBannerFontFile = .; /* 202EC8C */ + . += 0x8; gUnknown_202EC94 = .; /* 202EC94 */ . += 0x4; @@ -850,10 +848,10 @@ gUnknown_202F3D0 = .; /* 202F3D0 */ gUnknown_202F3D8 = .; /* 202F3D8 */ . += 0x8; -gUnknown_202F3E0 = .; /* 202F3E0 */ +gMonsterParameters = .; /* 202F3E0 */ . += 0x4; -gUnknown_202F3E4 = .; /* 202F3E4 */ +gMonsterParametersFile = .; /* 202F3E4 */ . += 0x4; gUnknown_202F3E8 = .; /* 202F3E8 */ @@ -868,11 +866,8 @@ gUnknown_20384E8 = .; /* 20384E8 */ gUnknown_20384F0 = .; /* 20384F0 */ . += 0x4B0; -gUnknown_20389A0 = .; /* 20389A0 */ - . += 0x4; - -gUnknown_20389A4 = .; /* 20389A4 */ - . += 0x4; +gItemParametersFile = .; /* 20389A0 */ + . += 0x8; gUnknown_20389A8 = .; /* 20389A8 */ . += 0x268; @@ -883,7 +878,7 @@ gUnknown_2038C10 = .; /* 2038C10 */ gUnknown_2038C28 = .; /* 2038C28 */ . += 0x3C; -gUnknown_2038C64 = .; /* 2038C64 */ +gWazaParametersFile = .; /* 2038C64 */ . += 0x4; gUnknown_2038C68 = .; /* 2038C68 */ diff --git a/sym_ewram2.txt b/sym_ewram2.txt index 5df20ac..6e71482 100644 --- a/sym_ewram2.txt +++ b/sym_ewram2.txt @@ -86,7 +86,7 @@ gUnknown_203B08C = .; /* 203B08C */ gUnknown_203B090 = .; /* 203B090 */ . += 0x4; -gUnknown_203B094 = .; /* 203B094 */ +gFileCacheCursorPosition = .; /* 203B094 */ . += 0x4; gUnknown_203B098 = .; /* 203B098 */ -- cgit v1.2.3 From c7045ae3694f677b634f3908c1ea935c2998727e Mon Sep 17 00:00:00 2001 From: nullableVoidPtr <30564701+nullableVoidPtr@users.noreply.github.com> Date: Tue, 20 Nov 2018 13:17:30 +0800 Subject: Identify, split, decompile m4a, and more ResetSprites, gCharMemCursor, gSpriteCount; analysed subheaps; identified more file pointers --- Makefile | 3 + asm/code.s | 4 +- asm/code_800B540.s | 100 +- asm/code_800D090.s | 4 +- asm/code_8012A18.s | 32 +- asm/m4a.s | 4627 ----------------------------------------------- asm/m4a_1.s | 1647 +++++++++++++++++ asm/m4a_2.s | 70 + asm/m4a_3.s | 574 ++++++ asm/sprite.s | 22 +- data/data_80B9BB8.s | 39 - data/sound_data.s | 8 +- include/memory.h | 6 +- ld_script.txt | 28 +- src/bg_palette_buffer.c | 6 +- src/m4a_2.c | 834 +++++++++ src/m4a_4.c | 384 ++++ src/m4a_tables.c | 223 +++ src/memory.c | 12 +- src/save1.c | 2 +- src/sprite.c | 6 +- sym_ewram.txt | 11 +- sym_ewram2.txt | 11 +- 23 files changed, 3858 insertions(+), 4795 deletions(-) delete mode 100644 asm/m4a.s create mode 100644 asm/m4a_1.s create mode 100644 asm/m4a_2.s create mode 100644 asm/m4a_3.s create mode 100644 src/m4a_2.c create mode 100644 src/m4a_4.c create mode 100644 src/m4a_tables.c diff --git a/Makefile b/Makefile index 59e6caf..b998e1e 100755 --- a/Makefile +++ b/Makefile @@ -60,6 +60,9 @@ $(BUILD_DIR)/src/agb_flash.o : CC1FLAGS := -O -mthumb-interwork $(BUILD_DIR)/src/agb_flash_1m.o: CC1FLAGS := -O -mthumb-interwork $(BUILD_DIR)/src/agb_flash_mx.o: CC1FLAGS := -O -mthumb-interwork +$(BUILD_DIR)/src/m4a_2.o: CC1 := tools/agbcc/bin/old_agbcc +$(BUILD_DIR)/src/m4a_4.o: CC1 := tools/agbcc/bin/old_agbcc + #### Main Rules #### ALL_BUILDS := red diff --git a/asm/code.s b/asm/code.s index ba969d1..8a85646 100644 --- a/asm/code.s +++ b/asm/code.s @@ -198,7 +198,7 @@ _08000406: movs r0, 0x2 bl sub_800A8F8 movs r0, 0x1 - bl sub_8004D8C + bl ResetSprites movs r0, 0 bl xxx_update_some_bg_tiles bl sub_80097B0 @@ -431,7 +431,7 @@ xxx_update_stuff: bl sub_8009908 bl xxx_call_update_bg_sound_input movs r0, 0 - bl sub_8004D8C + bl ResetSprites pop {r0} bx r0 .align 2, 0 diff --git a/asm/code_800B540.s b/asm/code_800B540.s index 1f7afbc..85105f7 100644 --- a/asm/code_800B540.s +++ b/asm/code_800B540.s @@ -1062,7 +1062,7 @@ sub_800BD08: ands r3, r1 strh r3, [r0, 0xA] ldrh r0, [r0, 0xA] - bl sub_80AEF24 + bl m4aSoundInit ldr r0, _0800BDB8 movs r2, 0 strh r2, [r0] @@ -1184,7 +1184,7 @@ _0800BE4C: movs r0, 0x1 strh r0, [r1] adds r0, r6, 0 - bl sub_80AEFA8 + bl m4aSongNumStart _0800BE70: cmp r4, 0 beq _0800BE78 @@ -1258,19 +1258,19 @@ _0800BEE0: movs r1, 0x1 strh r1, [r0] adds r0, r6, 0 - bl sub_80AEFA8 + bl m4aSongNumStart ldr r4, _0800BF44 adds r0, r4, 0 - bl sub_80AF198 + bl m4aMPlayImmInit adds r0, r4, 0 movs r1, 0xFF movs r2, 0 - bl sub_80AFF50 + bl m4aMPlayVolumeControl adds r0, r6, 0 - bl sub_80AF074 + bl m4aSongNumStop adds r0, r4, 0 adds r1, r5, 0 - bl sub_80AF170 + bl m4aMPlayFadeIn _0800BF26: cmp r7, 0 beq _0800BF2E @@ -1333,7 +1333,7 @@ sub_800BF80: cmp r1, r0 beq _0800BFA2 ldr r0, _0800BFC8 - bl sub_80AF7C0 + bl m4aMPlayStop _0800BFA2: ldr r0, _0800BFC0 ldr r2, _0800BFC4 @@ -1392,7 +1392,7 @@ _0800BFE8: strh r0, [r1] ldr r0, _0800C028 adds r1, r4, 0 - bl sub_80AF140 + bl m4aMPlayFadeOut b _0800C044 .align 2, 0 _0800C018: .4byte gUnknown_202D690 @@ -1403,7 +1403,7 @@ _0800C028: .4byte gUnknown_20008F0 _0800C02C: strh r2, [r3] ldr r0, _0800C038 - bl sub_80AF7C0 + bl m4aMPlayStop b _0800C044 .align 2, 0 _0800C038: .4byte gUnknown_20008F0 @@ -1506,7 +1506,7 @@ _0800C0B4: strb r2, [r0] ldr r0, _0800C11C movs r1, 0x1 - bl sub_80AF150 + bl m4aMPlayFadeOutTemporarily b _0800C15E .align 2, 0 _0800C0FC: .4byte 0x000003e5 @@ -1529,9 +1529,9 @@ _0800C12C: movs r0, 0x3 strh r0, [r4] ldr r0, _0800C140 - bl sub_80AF7C0 + bl m4aMPlayStop ldrh r0, [r6] - bl sub_80AEFA8 + bl m4aSongNumStart b _0800C15E .align 2, 0 _0800C140: .4byte gUnknown_20008F0 @@ -1542,9 +1542,9 @@ _0800C144: cmp r0, 0x1 bls _0800C15E ldr r0, _0800C17C - bl sub_80AF7C0 + bl m4aMPlayStop ldrh r0, [r6] - bl sub_80AEFA8 + bl m4aSongNumStart movs r0, 0x3 _0800C15C: strh r0, [r4] @@ -1618,7 +1618,7 @@ _0800C1DC: lsls r0, 24 lsrs r5, r0, 24 mov r0, r8 - bl sub_80AEFA8 + bl m4aSongNumStart movs r0, 0x1 strh r0, [r4] mov r0, r8 @@ -1693,7 +1693,7 @@ _0800C22C: mov r0, r8 movs r1, 0xF adds r2, r7, 0 - bl sub_80AFF50 + bl m4aMPlayVolumeControl _0800C27E: cmp r6, 0 beq _0800C286 @@ -1705,7 +1705,7 @@ _0800C286: pop {r0} bx r0 .align 2, 0 -_0800C290: .4byte gUnknown_9E8665C +_0800C290: .4byte gMPlayTable _0800C294: .4byte gUnknown_3000FD8 thumb_func_end sub_800C214 @@ -1736,7 +1736,7 @@ sub_800C298: movs r5, 0x4 _0800C2C8: ldr r0, [r6] - bl sub_80AF7C0 + bl m4aMPlayStop strh r7, [r4] mov r2, r8 strh r2, [r4, 0x2] @@ -1756,7 +1756,7 @@ _0800C2C8: .align 2, 0 _0800C2F0: .4byte 0x000003e5 _0800C2F4: .4byte gUnknown_3000FE8 -_0800C2F8: .4byte gUnknown_9E8665C +_0800C2F8: .4byte gMPlayTable _0800C2FC: adds r0, r5, 0 bl sub_800CAAC @@ -1782,7 +1782,7 @@ _0800C2FC: bl nullsub_21 b _0800C3DE .align 2, 0 -_0800C330: .4byte gUnknown_9E8665C +_0800C330: .4byte gMPlayTable _0800C334: .4byte gUnknown_3000FD8 _0800C338: bl sub_800B620 @@ -1792,7 +1792,7 @@ _0800C338: cmp r0, r5 bne _0800C35A adds r0, r7, 0 - bl sub_80AF7C0 + bl m4aMPlayStop movs r1, 0 movs r0, 0 strh r0, [r4] @@ -1823,7 +1823,7 @@ _0800C364: mov r0, r8 strh r0, [r1] ldr r0, _0800C3A4 - bl sub_80AF7C0 + bl m4aMPlayStop _0800C38C: cmp r4, 0 beq _0800C3DE @@ -1854,7 +1854,7 @@ _0800C3A8: mov r2, r8 strh r2, [r1] ldr r0, _0800C3F4 - bl sub_80AF7C0 + bl m4aMPlayStop _0800C3D6: cmp r4, 0 beq _0800C3DE @@ -1924,15 +1924,15 @@ _0800C43E: beq _0800C46C ldr r0, [r6] mov r1, r9 - bl sub_80AF140 + bl m4aMPlayFadeOut b _0800C47E .align 2, 0 _0800C460: .4byte 0x000003e5 _0800C464: .4byte gUnknown_3000FE8 -_0800C468: .4byte gUnknown_9E8665C +_0800C468: .4byte gMPlayTable _0800C46C: ldr r0, [r6] - bl sub_80AF7C0 + bl m4aMPlayStop strh r4, [r5] mov r1, r8 strh r1, [r5, 0x2] @@ -1985,14 +1985,14 @@ _0800C496: beq _0800C4EC adds r0, r6, 0 mov r1, r9 - bl sub_80AF140 + bl m4aMPlayFadeOut b _0800C4FE .align 2, 0 _0800C4E4: .4byte gUnknown_3000FD8 -_0800C4E8: .4byte gUnknown_9E8665C +_0800C4E8: .4byte gMPlayTable _0800C4EC: adds r0, r6, 0 - bl sub_80AF7C0 + bl m4aMPlayStop movs r0, 0 strh r4, [r5] mov r1, r8 @@ -2026,7 +2026,7 @@ _0800C508: beq _0800C54C ldr r0, _0800C548 mov r1, r9 - bl sub_80AF140 + bl m4aMPlayFadeOut b _0800C556 .align 2, 0 _0800C53C: .4byte 0x000003e6 @@ -2035,7 +2035,7 @@ _0800C544: .4byte gUnknown_202D68E _0800C548: .4byte gUnknown_2000970 _0800C54C: ldr r0, _0800C560 - bl sub_80AF7C0 + bl m4aMPlayStop mov r0, r8 strh r0, [r4] _0800C556: @@ -2069,7 +2069,7 @@ _0800C564: beq _0800C5AC ldr r0, _0800C5A8 mov r1, r9 - bl sub_80AF140 + bl m4aMPlayFadeOut b _0800C5B6 .align 2, 0 _0800C5A0: .4byte gUnknown_202D690 @@ -2077,7 +2077,7 @@ _0800C5A4: .4byte gUnknown_202D68E _0800C5A8: .4byte gUnknown_2000970 _0800C5AC: ldr r0, _0800C5CC - bl sub_80AF7C0 + bl m4aMPlayStop mov r1, r8 strh r1, [r5] _0800C5B6: @@ -2246,7 +2246,7 @@ _0800C6D8: beq _0800C718 ldrh r0, [r2] _0800C6E4: - bl sub_80AEFA8 + bl m4aSongNumStart movs r0, 0x3 strh r0, [r4] b _0800C8A2 @@ -2297,7 +2297,7 @@ _0800C74C: .4byte gUnknown_202D68E _0800C750: .4byte 0x000003e5 _0800C754: ldr r0, _0800C76C - bl sub_80AF7C0 + bl m4aMPlayStop _0800C75A: ldr r1, _0800C770 ldrh r0, [r1] @@ -2324,7 +2324,7 @@ _0800C774: cmp r0, 0 beq _0800C7A4 ldrh r0, [r3] - bl sub_80AEFA8 + bl m4aSongNumStart b _0800C7BE .align 2, 0 _0800C794: .4byte gUnknown_202D68A @@ -2334,7 +2334,7 @@ _0800C7A0: .4byte gUnknown_202D694 _0800C7A4: ldr r0, _0800C7B0 movs r1, 0x4 - bl sub_80AF170 + bl m4aMPlayFadeIn b _0800C7BE .align 2, 0 _0800C7B0: .4byte gUnknown_20008F0 @@ -2342,7 +2342,7 @@ _0800C7B4: ldr r0, _0800C7CC strh r2, [r0] ldr r0, _0800C7D0 - bl sub_80AF7C0 + bl m4aMPlayStop _0800C7BE: ldr r1, _0800C7D4 movs r0, 0 @@ -2402,7 +2402,7 @@ _0800C834: .4byte gUnknown_202D68A _0800C838: .4byte 0x000003e7 _0800C83C: ldr r0, _0800C854 - bl sub_80AF7C0 + bl m4aMPlayStop _0800C842: ldr r1, _0800C858 movs r0, 0 @@ -2436,7 +2436,7 @@ _0800C864: ldr r0, _0800C898 strh r2, [r0] adds r0, r1, 0 - bl sub_80AEFA8 + bl m4aSongNumStart strh r4, [r6] b _0800C8A2 .align 2, 0 @@ -2503,10 +2503,10 @@ _0800C8F0: ldr r0, [r0] ldrh r2, [r4, 0x4] movs r1, 0xFF - bl sub_80AFF50 + bl m4aMPlayVolumeControl b _0800C926 .align 2, 0 -_0800C918: .4byte gUnknown_9E8665C +_0800C918: .4byte gMPlayTable _0800C91C: strh r0, [r4] mov r1, r8 @@ -2579,8 +2579,8 @@ _0800C9A8: strh r0, [r4] _0800C9AC: ldr r0, _0800C9C8 - bl sub_80AF7C0 - bl sub_80AF5AC + bl m4aMPlayStop + bl m4aSoundVSyncOff cmp r5, 0 beq _0800C9BE bl sub_800B5F0 @@ -2599,7 +2599,7 @@ sub_800C9CC: bl sub_800B620 lsls r0, 24 lsrs r4, r0, 24 - bl sub_80AF628 + bl m4aSoundVSyncOn ldr r0, _0800CA08 ldrh r0, [r0] cmp r0, 0 @@ -2620,7 +2620,7 @@ sub_800C9CC: cmp r0, 0 beq _0800CA1C ldrh r0, [r2] - bl sub_80AEFA8 + bl m4aSongNumStart b _0800CA22 .align 2, 0 _0800CA08: .4byte gUnknown_202D690 @@ -2630,7 +2630,7 @@ _0800CA14: .4byte gUnknown_202D688 _0800CA18: .4byte gUnknown_202D694 _0800CA1C: ldr r0, _0800CA30 - bl sub_80AF108 + bl m4aMPlayContinue _0800CA22: cmp r4, 0 beq _0800CA2A @@ -2762,7 +2762,7 @@ sub_800CAE0: ldrh r0, [r0, 0x4] bx lr .align 2, 0 -_0800CAEC: .4byte gUnknown_9E866BC +_0800CAEC: .4byte gSongTable thumb_func_end sub_800CAE0 thumb_func_start sub_800CAF0 @@ -2782,7 +2782,7 @@ sub_800CAF0: movs r0, 0x1 b _0800CB12 .align 2, 0 -_0800CB0C: .4byte gUnknown_9E8665C +_0800CB0C: .4byte gMPlayTable _0800CB10: movs r0, 0 _0800CB12: diff --git a/asm/code_800D090.s b/asm/code_800D090.s index 583fe83..4f43b66 100644 --- a/asm/code_800D090.s +++ b/asm/code_800D090.s @@ -7661,7 +7661,7 @@ sub_8010960: bl xxx_call_update_bg_sound_input bl sub_8011860 movs r0, 0 - bl sub_8004D8C + bl ResetSprites pop {r4-r6} pop {r0} bx r0 @@ -9290,7 +9290,7 @@ sub_801169C: bl xxx_call_update_bg_sound_input bl sub_8011860 movs r0, 0 - bl sub_8004D8C + bl ResetSprites add sp, 0x8 pop {r4-r6} pop {r0} diff --git a/asm/code_8012A18.s b/asm/code_8012A18.s index b1327f4..e462a67 100644 --- a/asm/code_8012A18.s +++ b/asm/code_8012A18.s @@ -25,7 +25,7 @@ sub_8012A18: bl sub_8009908 bl xxx_call_update_bg_sound_input movs r0, 0 - bl sub_8004D8C + bl ResetSprites pop {r0} bx r0 .align 2, 0 @@ -17484,7 +17484,7 @@ sub_801B3C0: push {r4,r5,lr} adds r5, r0, 0 movs r0, 0x1 - bl sub_8004D8C + bl ResetSprites ldr r4, _0801B40C movs r0, 0x94 movs r1, 0x8 @@ -19806,7 +19806,7 @@ sub_801C620: lsls r4, 24 lsrs r4, 24 movs r0, 0x1 - bl sub_8004D8C + bl ResetSprites ldr r5, _0801C670 movs r0, 0x94 movs r1, 0x8 @@ -26163,7 +26163,7 @@ sub_801F808: push {r4,r5,lr} adds r4, r0, 0 movs r0, 0x1 - bl sub_8004D8C + bl ResetSprites ldr r5, _0801F88C movs r0, 0xD4 movs r1, 0x8 @@ -41273,7 +41273,7 @@ _0802706E: sub_8027074: push {r4,lr} movs r0, 0 - bl sub_8004D8C + bl ResetSprites ldr r4, _080270A0 movs r0, 0xF0 lsls r0, 1 @@ -73146,7 +73146,7 @@ sub_8036FDC: movs r2, 0x1 bl sub_800641C movs r0, 0 - bl sub_8004D8C + bl ResetSprites ldr r5, _080370C0 ldr r0, [r5] cmp r0, 0 @@ -73610,7 +73610,7 @@ sub_80373C4: bl sub_8009908 bl xxx_call_update_bg_sound_input movs r0, 0 - bl sub_8004D8C + bl ResetSprites pop {r0} bx r0 thumb_func_end sub_80373C4 @@ -76245,7 +76245,7 @@ sub_8038830: add r0, r12 str r5, [r0] movs r0, 0 - bl sub_8004D8C + bl ResetSprites pop {r4,r5} pop {r0} bx r0 @@ -86815,7 +86815,7 @@ _0803DB88: .4byte gUnknown_83B0000 _0803DB8C: .4byte gDungeonNameBannerPalette _0803DB90: .4byte gUnknown_80F6100 _0803DB94: .4byte gDungeonNameBannerFontFile -_0803DB98: .4byte gDungeonNameBannerFontFile + 4 +_0803DB98: .4byte gDungeonNameBannerFont _0803DB9C: .4byte 0x06000140 _0803DBA0: .4byte gUnknown_203B418 _0803DBA4: .4byte 0x00000645 @@ -87287,7 +87287,7 @@ _0803DF08: adds r0, r2, r0 b _0803DF3A .align 2, 0 -_0803DF1C: .4byte gDungeonNameBannerFontFile + 4 +_0803DF1C: .4byte gDungeonNameBannerFont _0803DF20: lsls r0, r1, 3 adds r0, r5 @@ -88114,7 +88114,7 @@ _0803E5A2: bl sub_8011860 bl sub_8040B60 movs r0, 0 - bl sub_8004D8C + bl ResetSprites movs r0, 0 bl nullsub_10 ldr r1, _0803E664 @@ -88186,7 +88186,7 @@ sub_803E668: strb r1, [r0] bl sub_8011860 movs r0, 0 - bl sub_8004D8C + bl ResetSprites movs r0, 0 bl nullsub_10 ldr r0, [r4] @@ -273046,7 +273046,7 @@ _080995AE: _08099604: bl xxx_call_update_bg_sound_input movs r0, 0 - bl sub_8004D8C + bl ResetSprites mov r2, r9 cmp r2, 0 beq _08099524 @@ -299178,7 +299178,7 @@ _080A6434: _080A6444: strh r0, [r5, 0xA] movs r0, 0x1 - bl sub_8004D8C + bl ResetSprites movs r0, 0x1 bl nullsub_10 pop {r3,r4} @@ -299342,7 +299342,7 @@ sub_80A658C: push {r4,lr} bl sub_800DB7C movs r0, 0 - bl sub_8004D8C + bl ResetSprites movs r0, 0 bl nullsub_10 bl sub_8005180 @@ -300572,7 +300572,7 @@ _080A6E56: sub_80A6E68: push {lr} movs r0, 0 - bl sub_8004D8C + bl ResetSprites movs r0, 0 bl nullsub_10 bl sub_800E970 diff --git a/asm/m4a.s b/asm/m4a.s deleted file mode 100644 index 602f9b9..0000000 --- a/asm/m4a.s +++ /dev/null @@ -1,4627 +0,0 @@ - .include "asm/macros.inc" - .include "constants/gba_constants.inc" - .include "constants/m4a_constants.inc" - - .syntax unified - - .text - - thumb_func_start umul3232H32 -umul3232H32: - adr r2, _080AE268 - bx r2 - .arm -_080AE268: - umull r2, r3, r0, r1 - add r0, r3, 0 - bx lr - thumb_func_end umul3232H32 - - thumb_func_start SoundMain -SoundMain: - ldr r0, lt_SOUND_INFO_PTR - ldr r0, [r0] - ldr r2, lt_ID_NUMBER - ldr r3, [r0, o_SoundInfo_ident] - cmp r2, r3 - beq SoundMain_1 - bx lr @ Exit the function if ident doesn't match ID_NUMBER. -SoundMain_1: - adds r3, 1 - str r3, [r0, o_SoundInfo_ident] - push {r4-r7,lr} - mov r1, r8 - mov r2, r9 - mov r3, r10 - mov r4, r11 - push {r0-r4} - sub sp, 0x18 - ldrb r1, [r0, o_SoundInfo_maxLines] - cmp r1, 0 @ if maxLines is 0, there is no maximum - beq SoundMain_3 - ldr r2, lt_REG_VCOUNT - ldrb r2, [r2] - cmp r2, VCOUNT_VBLANK - bhs SoundMain_2 - adds r2, TOTAL_SCANLINES -SoundMain_2: - adds r1, r2 -SoundMain_3: - str r1, [sp, 0x14] - ldr r3, [r0, o_SoundInfo_func] - cmp r3, 0 - beq SoundMain_4 - ldr r0, [r0, o_SoundInfo_intp] - bl call_r3 - ldr r0, [sp, 0x18] -SoundMain_4: - ldr r3, [r0, o_SoundInfo_CgbSound] - bl call_r3 - ldr r0, [sp, 0x18] - ldr r3, [r0, o_SoundInfo_pcmSamplesPerVBlank] - mov r8, r3 - ldr r5, lt_o_SoundInfo_pcmBuffer - adds r5, r0 - ldrb r4, [r0, o_SoundInfo_pcmDmaCounter] - subs r7, r4, 1 - bls SoundMain_5 - ldrb r1, [r0, o_SoundInfo_pcmDmaPeriod] - subs r1, r7 - mov r2, r8 - muls r2, r1 - adds r5, r2 -SoundMain_5: - str r5, [sp, 0x8] - ldr r6, lt_PCM_DMA_BUF_SIZE - ldr r3, lt_SoundMainRAM_Buffer - bx r3 - - .align 2, 0 -lt_SOUND_INFO_PTR: .word SOUND_INFO_PTR -lt_ID_NUMBER: .word ID_NUMBER -lt_SoundMainRAM_Buffer: .word SoundMainRAM_Buffer + 1 -lt_REG_VCOUNT: .word REG_VCOUNT -lt_o_SoundInfo_pcmBuffer: .word o_SoundInfo_pcmBuffer -lt_PCM_DMA_BUF_SIZE: .word PCM_DMA_BUF_SIZE - thumb_func_end SoundMain - - thumb_func_start SoundMainRAM -SoundMainRAM: - ldrb r3, [r0, o_SoundInfo_reverb] - cmp r3, 0 - beq SoundMainRAM_NoReverb - adr r1, SoundMainRAM_Reverb - bx r1 - .arm -SoundMainRAM_Reverb: - cmp r4, 0x2 - addeq r7, r0, o_SoundInfo_pcmBuffer - addne r7, r5, r8 - mov r4, r8 -_080AE314: - ldrsb r0, [r5, r6] - ldrsb r1, [r5] - add r0, r0, r1 - ldrsb r1, [r7, r6] - add r0, r0, r1 - ldrsb r1, [r7], 0x1 - add r0, r0, r1 - mul r1, r0, r3 - mov r0, r1, asr 9 - tst r0, 0x80 - addne r0, r0, 0x1 - strb r0, [r5, r6] - strb r0, [r5], 0x1 - subs r4, r4, 0x1 - bgt _080AE314 - add r0, pc, 0x2F - bx r0 - .thumb -SoundMainRAM_NoReverb: - movs r0, 0 - mov r1, r8 - adds r6, r5 - lsrs r1, 3 - bcc SoundMainRAM_NoReverb_Ok - stm r5!, {r0} - stm r6!, {r0} -SoundMainRAM_NoReverb_Ok: - lsrs r1, 1 - bcc SoundMainRAM_NoReverb_Loop - stm r5!, {r0} - stm r6!, {r0} - stm r5!, {r0} - stm r6!, {r0} -SoundMainRAM_NoReverb_Loop: - stm r5!, {r0} - stm r6!, {r0} - stm r5!, {r0} - stm r6!, {r0} - stm r5!, {r0} - stm r6!, {r0} - stm r5!, {r0} - stm r6!, {r0} - subs r1, 0x1 - bgt SoundMainRAM_NoReverb_Loop -_080AE386: - ldr r4, [sp, 0x18] - ldr r0, [r4, o_SoundInfo_divFreq] - mov r12, r0 - ldrb r0, [r4, o_SoundInfo_maxChans] - adds r4, o_SoundInfo_chans -SoundMainRAM_ChanLoop: - str r0, [sp, 0x4] - ldr r3, [r4, o_SoundChannel_wav] - ldr r0, [sp, 0x14] - cmp r0, 0 - beq _080AE3B0 - ldr r1, =REG_VCOUNT - ldrb r1, [r1] - cmp r1, VCOUNT_VBLANK - bhs _080AE3A4 - adds r1, TOTAL_SCANLINES -_080AE3A4: - cmp r1, r0 - bcc _080AE3B0 - b _080AE682 - - .pool - -_080AE3B0: - ldrb r6, [r4, o_SoundChannel_status] - movs r0, 0xC7 - tst r0, r6 - bne _080AE3BA - b _080AE678 -_080AE3BA: - movs r0, 0x80 - tst r0, r6 - beq _080AE3EA - movs r0, 0x40 - tst r0, r6 - bne _080AE3FA - movs r6, 0x3 - strb r6, [r4, o_SoundChannel_status] - adds r0, r3, 0 - adds r0, 0x10 - str r0, [r4, o_SoundChannel_cp] - ldr r0, [r3, 0xC] - str r0, [r4, o_SoundChannel_ct] - movs r5, 0 - strb r5, [r4, o_SoundChannel_ev] - str r5, [r4, o_SoundChannel_fw] - ldrb r2, [r3, 0x3] - movs r0, 0xC0 - tst r0, r2 - beq _080AE442 - movs r0, 0x10 - orrs r6, r0 - strb r6, [r4, o_SoundChannel_status] - b _080AE442 -_080AE3EA: - ldrb r5, [r4, o_SoundChannel_ev] - movs r0, 0x4 - tst r0, r6 - beq _080AE400 - ldrb r0, [r4, o_SoundChannel_iel] - subs r0, 0x1 - strb r0, [r4, o_SoundChannel_iel] - bhi _080AE450 -_080AE3FA: - movs r0, 0 - strb r0, [r4, o_SoundChannel_status] - b _080AE678 -_080AE400: - movs r0, 0x40 - tst r0, r6 - beq _080AE420 - ldrb r0, [r4, o_SoundChannel_release] - muls r5, r0 - lsrs r5, 8 - ldrb r0, [r4, o_SoundChannel_iev] - cmp r5, r0 - bhi _080AE450 -_080AE412: - ldrb r5, [r4, o_SoundChannel_iev] - cmp r5, 0 - beq _080AE3FA - movs r0, 0x4 - orrs r6, r0 - strb r6, [r4, o_SoundChannel_status] - b _080AE450 -_080AE420: - movs r2, 0x3 - ands r2, r6 - cmp r2, 0x2 - bne _080AE43E - ldrb r0, [r4, o_SoundChannel_decay] - muls r5, r0 - lsrs r5, 8 - ldrb r0, [r4, o_SoundChannel_sustain] - cmp r5, r0 - bhi _080AE450 - adds r5, r0, 0 - beq _080AE412 - subs r6, 0x1 - strb r6, [r4, o_SoundChannel_status] - b _080AE450 -_080AE43E: - cmp r2, 0x3 - bne _080AE450 -_080AE442: - ldrb r0, [r4, o_SoundChannel_attack] - adds r5, r0 - cmp r5, 0xFF - bcc _080AE450 - movs r5, 0xFF - subs r6, 0x1 - strb r6, [r4, o_SoundChannel_status] -_080AE450: - strb r5, [r4, o_SoundChannel_ev] - ldr r0, [sp, 0x18] - ldrb r0, [r0, o_SoundChannel_release] - adds r0, 0x1 - muls r0, r5 - lsrs r5, r0, 4 - ldrb r0, [r4, o_SoundChannel_rightVolume] - muls r0, r5 - lsrs r0, 8 - strb r0, [r4, o_SoundChannel_er] - ldrb r0, [r4, o_SoundChannel_leftVolume] - muls r0, r5 - lsrs r0, 8 - strb r0, [r4, o_SoundChannel_el] - movs r0, 0x10 - ands r0, r6 - str r0, [sp, 0x10] - beq _080AE484 - adds r0, r3, 0 - adds r0, 0x10 - ldr r1, [r3, 0x8] - adds r0, r1 - str r0, [sp, 0xC] - ldr r0, [r3, 0xC] - subs r0, r1 - str r0, [sp, 0x10] -_080AE484: - ldr r5, [sp, 0x8] - ldr r2, [r4, o_SoundChannel_ct] - ldr r3, [r4, o_SoundChannel_cp] - adr r0, _080AE490 - bx r0 - .arm -_080AE490: - str r8, [sp] - ldrb r10, [r4, o_SoundChannel_er] - ldrb r11, [r4, o_SoundChannel_el] - mov r10, r10, lsl 16 - mov r11, r11, lsl 16 - ldrb r0, [r4, o_SoundChannel_type] - tst r0, 0x8 - beq _080AE5D0 -_080AE4B0: - cmp r2, 0x4 - ble _080AE520 - subs r2, r2, r8 - movgt lr, 0 - bgt _080AE4DC - mov lr, r8 - add r2, r2, r8 - sub r8, r2, 0x4 - sub lr, lr, r8 - ands r2, r2, 0x3 - moveq r2, 0x4 -_080AE4DC: - ldr r6, [r5] - ldr r7, [r5, 0x630] -_080AE4E4: - ldrsb r0, [r3], 0x1 - mul r1, r10, r0 - bic r1, r1, 0xFF0000 - add r6, r1, r6, ror 8 - mul r1, r11, r0 - bic r1, r1, 0xFF0000 - add r7, r1, r7, ror 8 - adds r5, r5, 0x40000000 - bcc _080AE4E4 - str r7, [r5, 0x630] - str r6, [r5], 0x4 - subs r8, r8, 0x4 - bgt _080AE4DC - adds r8, r8, lr - beq _080AE664 -_080AE520: - ldr r6, [r5] - ldr r7, [r5, 0x630] -_080AE528: - ldrsb r0, [r3], 0x1 - mul r1, r10, r0 - bic r1, r1, 0xFF0000 - add r6, r1, r6, ror 8 - mul r1, r11, r0 - bic r1, r1, 0xFF0000 - add r7, r1, r7, ror 8 - subs r2, r2, 0x1 - beq _080AE598 -_080AE54C: - adds r5, r5, 0x40000000 - bcc _080AE528 - str r7, [r5, 0x630] - str r6, [r5], 0x4 - subs r8, r8, 0x4 - bgt _080AE4B0 - b _080AE664 -_080AE568: - ldr r0, [sp, 0x18] - cmp r0, 0 - beq _080AE58C - ldr r3, [sp, 0x14] - rsb r9, r2, 0 -_080AE57C: - adds r2, r0, r2 - bgt _080AE634 - sub r9, r9, r0 - b _080AE57C -_080AE58C: - ldmia sp!, {r4,r12} - mov r2, 0 - b _080AE5A8 -_080AE598: - ldr r2, [sp, 0x10] - cmp r2, 0 - ldrne r3, [sp, 0xC] - bne _080AE54C -_080AE5A8: - strb r2, [r4, o_SoundChannel_status] - mov r0, r5, lsr 30 - bic r5, r5, 0xC0000000 - rsb r0, r0, 0x3 - mov r0, r0, lsl 3 - mov r6, r6, ror r0 - mov r7, r7, ror r0 - str r7, [r5, 0x630] - str r6, [r5], 0x4 - b _080AE66C -_080AE5D0: - stmdb sp!, {r4,r12} - ldr lr, [r4, o_SoundChannel_fw] - ldr r1, [r4, o_SoundChannel_freq] - mul r4, r12, r1 - ldrsb r0, [r3] - ldrsb r1, [r3, 0x1]! - sub r1, r1, r0 -_080AE5EC: - ldr r6, [r5] - ldr r7, [r5, 0x630] -_080AE5F4: - mul r9, lr, r1 - add r9, r0, r9, asr 23 - mul r12, r10, r9 - bic r12, r12, 0xFF0000 - add r6, r12, r6, ror 8 - mul r12, r11, r9 - bic r12, r12, 0xFF0000 - add r7, r12, r7, ror 8 - add lr, lr, r4 - movs r9, lr, lsr 23 - beq _080AE640 - bic lr, lr, 0x3F800000 - subs r2, r2, r9 - ble _080AE568 - subs r9, r9, 0x1 - addeq r0, r0, r1 -_080AE634: - ldrsbne r0, [r3, r9]! - ldrsb r1, [r3, 0x1]! - sub r1, r1, r0 -_080AE640: - adds r5, r5, 0x40000000 - bcc _080AE5F4 - str r7, [r5, 0x630] - str r6, [r5], 0x4 - subs r8, r8, 0x4 - bgt _080AE5EC - sub r3, r3, 0x1 - ldmia sp!, {r4,r12} - str lr, [r4, o_SoundChannel_fw] -_080AE664: - str r2, [r4, o_SoundChannel_ct] - str r3, [r4, o_SoundChannel_cp] -_080AE66C: - ldr r8, [sp] - add r0, pc, 0x1 - bx r0 - .thumb -_080AE678: - ldr r0, [sp, 0x4] - subs r0, 0x1 - ble _080AE682 - adds r4, SoundChannel_size - b SoundMainRAM_ChanLoop -_080AE682: - ldr r0, [sp, 0x18] - ldr r3, =ID_NUMBER - str r3, [r0] - add sp, 0x1C - pop {r0-r7} - mov r8, r0 - mov r9, r1 - mov r10, r2 - mov r11, r3 - pop {r3} - -call_r3: - bx r3 - .pool - thumb_func_end SoundMainRAM - - thumb_func_start sub_80AE69C -sub_80AE69C: - mov r12, r4 - movs r1, 0 - movs r2, 0 - movs r3, 0 - movs r4, 0 - stm r0!, {r1-r4} - stm r0!, {r1-r4} - stm r0!, {r1-r4} - stm r0!, {r1-r4} - mov r4, r12 - bx lr - thumb_func_end sub_80AE69C - - thumb_func_start sub_80AE6B4 -sub_80AE6B4: - ldr r3, [r0, 0x2C] - cmp r3, 0 - beq _080AE6D2 - ldr r1, [r0, 0x34] - ldr r2, [r0, 0x30] - cmp r2, 0 - beq _080AE6C6 - str r1, [r2, 0x34] - b _080AE6C8 -_080AE6C6: - str r1, [r3, 0x20] -_080AE6C8: - cmp r1, 0 - beq _080AE6CE - str r2, [r1, 0x30] -_080AE6CE: - movs r1, 0 - str r1, [r0, 0x2C] -_080AE6D2: - bx lr - thumb_func_end sub_80AE6B4 - - thumb_func_start sub_80AE6D4 -sub_80AE6D4: - push {r4,r5,lr} - adds r5, r1, 0 - ldr r4, [r5, 0x20] - cmp r4, 0 - beq _080AE6F8 -_080AE6DE: - ldrb r1, [r4] - movs r0, 0xC7 - tst r0, r1 - beq _080AE6EC - movs r0, 0x40 - orrs r1, r0 - strb r1, [r4] -_080AE6EC: - adds r0, r4, 0 - bl sub_80AE6B4 - ldr r4, [r4, 0x34] - cmp r4, 0 - bne _080AE6DE -_080AE6F8: - movs r0, 0 - strb r0, [r5] - pop {r4,r5} - pop {r0} - bx r0 - thumb_func_end sub_80AE6D4 - - thumb_func_start sub_80AE704 -sub_80AE704: - mov r12, lr - movs r1, 0x24 - ldr r2, _080AE734 -_080AE70A: - ldr r3, [r2] - bl _080AE71E - stm r0!, {r3} - adds r2, 0x4 - subs r1, 0x1 - bgt _080AE70A - bx r12 - thumb_func_end sub_80AE704 - - .align 2, 0 - .thumb_func -_080AE71C: - ldrb r3, [r2] - - .thumb_func -_080AE71E: - push {r0} - lsrs r0, r2, 25 - bne _080AE730 - ldr r0, _080AE734 - cmp r2, r0 - bcc _080AE72E - lsrs r0, r2, 14 - beq _080AE730 -_080AE72E: - movs r3, 0 -_080AE730: - pop {r0} - bx lr - .align 2, 0 -_080AE734: .4byte gUnknown_826F98C - - thumb_func_start sub_80AE738 -sub_80AE738: - ldr r2, [r1, 0x40] -_080AE73A: - adds r3, r2, 0x1 - str r3, [r1, 0x40] - ldrb r3, [r2] - b _080AE71E - thumb_func_end sub_80AE738 - - thumb_func_start sub_80AE744 -sub_80AE744: - push {lr} -_080AE746: - ldr r2, [r1, 0x40] - ldrb r0, [r2, 0x3] - lsls r0, 8 - ldrb r3, [r2, 0x2] - orrs r0, r3 - lsls r0, 8 - ldrb r3, [r2, 0x1] - orrs r0, r3 - lsls r0, 8 - bl _080AE71C - orrs r0, r3 - str r0, [r1, 0x40] - pop {r0} - bx r0 - thumb_func_end sub_80AE744 - - thumb_func_start sub_80AE764 -sub_80AE764: - ldrb r2, [r1, 0x2] - cmp r2, 0x3 - bcs _080AE77C - lsls r2, 2 - adds r3, r1, r2 - ldr r2, [r1, 0x40] - adds r2, 0x4 - str r2, [r3, 0x44] - ldrb r2, [r1, 0x2] - adds r2, 0x1 - strb r2, [r1, 0x2] - b sub_80AE744 -_080AE77C: - b sub_80AE6D4 - thumb_func_end sub_80AE764 - - thumb_func_start sub_80AE780 -sub_80AE780: - ldrb r2, [r1, 0x2] - cmp r2, 0 - beq _080AE792 - subs r2, 0x1 - strb r2, [r1, 0x2] - lsls r2, 2 - adds r3, r1, r2 - ldr r2, [r3, 0x44] - str r2, [r1, 0x40] -_080AE792: - bx lr - thumb_func_end sub_80AE780 - - thumb_func_start sub_80AE794 -sub_80AE794: - push {lr} - ldr r2, [r1, 0x40] - ldrb r3, [r2] - cmp r3, 0 - bne _080AE7A4 - adds r2, 0x1 - str r2, [r1, 0x40] - b _080AE746 -_080AE7A4: - ldrb r3, [r1, 0x3] - adds r3, 0x1 - strb r3, [r1, 0x3] - mov r12, r3 - bl sub_80AE738 - cmp r12, r3 - bcs _080AE7B6 - b _080AE746 -_080AE7B6: - movs r3, 0 - strb r3, [r1, 0x3] - adds r2, 0x5 - str r2, [r1, 0x40] - pop {r0} - bx r0 - thumb_func_end sub_80AE794 - - thumb_func_start sub_80AE7C4 -sub_80AE7C4: - mov r12, lr - bl sub_80AE738 - strb r3, [r1, 0x1D] - bx r12 - thumb_func_end sub_80AE7C4 - - thumb_func_start sub_80AE7D0 -sub_80AE7D0: - mov r12, lr - bl sub_80AE738 - lsls r3, 1 - strh r3, [r0, 0x1C] - ldrh r2, [r0, 0x1E] - muls r3, r2 - lsrs r3, 8 - strh r3, [r0, 0x20] - bx r12 - thumb_func_end sub_80AE7D0 - - thumb_func_start sub_80AE7E4 -sub_80AE7E4: - mov r12, lr - bl sub_80AE738 - strb r3, [r1, 0xA] - ldrb r3, [r1] - movs r2, 0xC - orrs r3, r2 - strb r3, [r1] - bx r12 - thumb_func_end sub_80AE7E4 - - thumb_func_start sub_80AE7F8 -sub_80AE7F8: - mov r12, lr - ldr r2, [r1, 0x40] - ldrb r3, [r2] - adds r2, 0x1 - str r2, [r1, 0x40] - lsls r2, r3, 1 - adds r2, r3 - lsls r2, 2 - ldr r3, [r0, 0x30] - adds r2, r3 - ldr r3, [r2] - bl _080AE71E - str r3, [r1, 0x24] - ldr r3, [r2, 0x4] - bl _080AE71E - str r3, [r1, 0x28] - ldr r3, [r2, 0x8] - bl _080AE71E - str r3, [r1, 0x2C] - bx r12 - thumb_func_end sub_80AE7F8 - - thumb_func_start sub_80AE828 -sub_80AE828: - mov r12, lr - bl sub_80AE738 - strb r3, [r1, 0x12] - ldrb r3, [r1] - movs r2, 0x3 - orrs r3, r2 - strb r3, [r1] - bx r12 - thumb_func_end sub_80AE828 - - thumb_func_start sub_80AE83C -sub_80AE83C: - mov r12, lr - bl sub_80AE738 - subs r3, 0x40 - strb r3, [r1, 0x14] - ldrb r3, [r1] - movs r2, 0x3 - orrs r3, r2 - strb r3, [r1] - bx r12 - thumb_func_end sub_80AE83C - - thumb_func_start sub_80AE850 -sub_80AE850: - mov r12, lr - bl sub_80AE738 - subs r3, 0x40 - strb r3, [r1, 0xE] - ldrb r3, [r1] - movs r2, 0xC - orrs r3, r2 - strb r3, [r1] - bx r12 - thumb_func_end sub_80AE850 - - thumb_func_start sub_80AE864 -sub_80AE864: - mov r12, lr - bl sub_80AE738 - strb r3, [r1, 0xF] - ldrb r3, [r1] - movs r2, 0xC - orrs r3, r2 - strb r3, [r1] - bx r12 - thumb_func_end sub_80AE864 - - thumb_func_start sub_80AE878 -sub_80AE878: - mov r12, lr - bl sub_80AE738 - strb r3, [r1, 0x1B] - bx r12 - thumb_func_end sub_80AE878 - - thumb_func_start sub_80AE884 -sub_80AE884: - mov r12, lr - bl sub_80AE738 - ldrb r0, [r1, 0x18] - cmp r0, r3 - beq _080AE89A - strb r3, [r1, 0x18] - ldrb r3, [r1] - movs r2, 0xF - orrs r3, r2 - strb r3, [r1] -_080AE89A: - bx r12 - thumb_func_end sub_80AE884 - - thumb_func_start sub_80AE89C -sub_80AE89C: - mov r12, lr - bl sub_80AE738 - subs r3, 0x40 - strb r3, [r1, 0xC] - ldrb r3, [r1] - movs r2, 0xC - orrs r3, r2 - strb r3, [r1] - bx r12 - thumb_func_end sub_80AE89C - - thumb_func_start sub_80AE8B0 -sub_80AE8B0: - mov r12, lr - ldr r2, [r1, 0x40] - ldrb r3, [r2] - adds r2, 0x1 - ldr r0, _080AE8C4 - adds r0, r3 - bl _080AE73A - strb r3, [r0] - bx r12 - .align 2, 0 -_080AE8C4: .4byte 0x04000060 - thumb_func_end sub_80AE8B0 - - thumb_func_start m4aSoundVSync -m4aSoundVSync: - ldr r0, _080AEB74 - ldr r0, [r0] - ldr r2, _080AEB78 - ldr r3, [r0] - subs r3, r2 - cmp r3, 0x1 - bhi _080AE908 - ldrb r1, [r0, 0x4] - subs r1, 0x1 - strb r1, [r0, 0x4] - bgt _080AE908 - ldrb r1, [r0, 0xB] - strb r1, [r0, 0x4] - ldr r2, _080AE90C - ldr r1, [r2, 0x8] - lsls r1, 7 - bcc _080AE8EE - ldr r1, _080AE910 - str r1, [r2, 0x8] -_080AE8EE: - ldr r1, [r2, 0x14] - lsls r1, 7 - bcc _080AE8F8 - ldr r1, _080AE910 - str r1, [r2, 0x14] -_080AE8F8: - movs r1, 0x4 - lsls r1, 8 - strh r1, [r2, 0xA] - strh r1, [r2, 0x16] - movs r1, 0xB6 - lsls r1, 8 - strh r1, [r2, 0xA] - strh r1, [r2, 0x16] -_080AE908: - bx lr - .align 2, 0 -_080AE90C: .4byte 0x040000bc -_080AE910: .4byte 0x84400004 - thumb_func_end m4aSoundVSync - - thumb_func_start sub_80AE914 -sub_80AE914: - ldr r2, _080AEB78 - ldr r3, [r0, 0x34] - cmp r2, r3 - beq _080AE91E - bx lr -_080AE91E: - adds r3, 0x1 - str r3, [r0, 0x34] - push {r0,lr} - ldr r3, [r0, 0x38] - cmp r3, 0 - beq _080AE930 - ldr r0, [r0, 0x3C] - bl _080AEB6C -_080AE930: - pop {r0} - push {r4-r7} - mov r4, r8 - mov r5, r9 - mov r6, r10 - mov r7, r11 - push {r4-r7} - adds r7, r0, 0 - ldr r0, [r7, 0x4] - cmp r0, 0 - bge _080AE948 - b _080AEB5C -_080AE948: - ldr r0, _080AEB74 - ldr r0, [r0] - mov r8, r0 - adds r0, r7, 0 - bl sub_80AF800 - ldr r0, [r7, 0x4] - cmp r0, 0 - bge _080AE95C - b _080AEB5C -_080AE95C: - ldrh r0, [r7, 0x22] - ldrh r1, [r7, 0x20] - adds r0, r1 - b _080AEAAC -_080AE964: - ldrb r6, [r7, 0x8] - ldr r5, [r7, 0x2C] - movs r3, 0x1 - movs r4, 0 -_080AE96C: - ldrb r0, [r5] - movs r1, 0x80 - tst r1, r0 - bne _080AE976 - b _080AEA88 -_080AE976: - mov r10, r3 - orrs r4, r3 - mov r11, r4 - ldr r4, [r5, 0x20] - cmp r4, 0 - beq _080AE9AA -_080AE982: - ldrb r1, [r4] - movs r0, 0xC7 - tst r0, r1 - beq _080AE99E - ldrb r0, [r4, 0x10] - cmp r0, 0 - beq _080AE9A4 - subs r0, 0x1 - strb r0, [r4, 0x10] - bne _080AE9A4 - movs r0, 0x40 - orrs r1, r0 - strb r1, [r4] - b _080AE9A4 -_080AE99E: - adds r0, r4, 0 - bl sub_80AF2FC -_080AE9A4: - ldr r4, [r4, 0x34] - cmp r4, 0 - bne _080AE982 -_080AE9AA: - ldrb r3, [r5] - movs r0, 0x40 - tst r0, r3 - beq _080AEA28 - adds r0, r5, 0 - bl sub_80AF310 - movs r0, 0x80 - strb r0, [r5] - movs r0, 0x2 - strb r0, [r5, 0xF] - movs r0, 0x40 - strb r0, [r5, 0x13] - movs r0, 0x16 - strb r0, [r5, 0x19] - movs r0, 0x1 - adds r1, r5, 0x6 - strb r0, [r1, 0x1E] - b _080AEA28 -_080AE9D0: - ldr r2, [r5, 0x40] - ldrb r1, [r2] - cmp r1, 0x80 - bcs _080AE9DC - ldrb r1, [r5, 0x7] - b _080AE9E6 -_080AE9DC: - adds r2, 0x1 - str r2, [r5, 0x40] - cmp r1, 0xBD - bcc _080AE9E6 - strb r1, [r5, 0x7] -_080AE9E6: - cmp r1, 0xCF - bcc _080AE9FC - mov r0, r8 - ldr r3, [r0, 0x38] - adds r0, r1, 0 - subs r0, 0xCF - adds r1, r7, 0 - adds r2, r5, 0 - bl _080AEB6C - b _080AEA28 -_080AE9FC: - cmp r1, 0xB0 - bls _080AEA1E - adds r0, r1, 0 - subs r0, 0xB1 - strb r0, [r7, 0xA] - mov r3, r8 - ldr r3, [r3, 0x34] - lsls r0, 2 - ldr r3, [r3, r0] - adds r0, r7, 0 - adds r1, r5, 0 - bl _080AEB6C - ldrb r0, [r5] - cmp r0, 0 - beq _080AEA84 - b _080AEA28 -_080AEA1E: - ldr r0, _080AEB70 - subs r1, 0x80 - adds r1, r0 - ldrb r0, [r1] - strb r0, [r5, 0x1] -_080AEA28: - ldrb r0, [r5, 0x1] - cmp r0, 0 - beq _080AE9D0 - subs r0, 0x1 - strb r0, [r5, 0x1] - ldrb r1, [r5, 0x19] - cmp r1, 0 - beq _080AEA84 - ldrb r0, [r5, 0x17] - cmp r0, 0 - beq _080AEA84 - ldrb r0, [r5, 0x1C] - cmp r0, 0 - beq _080AEA4A - subs r0, 0x1 - strb r0, [r5, 0x1C] - b _080AEA84 -_080AEA4A: - ldrb r0, [r5, 0x1A] - adds r0, r1 - strb r0, [r5, 0x1A] - adds r1, r0, 0 - subs r0, 0x40 - lsls r0, 24 - bpl _080AEA5E - lsls r2, r1, 24 - asrs r2, 24 - b _080AEA62 -_080AEA5E: - movs r0, 0x80 - subs r2, r0, r1 -_080AEA62: - ldrb r0, [r5, 0x17] - muls r0, r2 - asrs r2, r0, 6 - ldrb r0, [r5, 0x16] - eors r0, r2 - lsls r0, 24 - beq _080AEA84 - strb r2, [r5, 0x16] - ldrb r0, [r5] - ldrb r1, [r5, 0x18] - cmp r1, 0 - bne _080AEA7E - movs r1, 0xC - b _080AEA80 -_080AEA7E: - movs r1, 0x3 -_080AEA80: - orrs r0, r1 - strb r0, [r5] -_080AEA84: - mov r3, r10 - mov r4, r11 -_080AEA88: - subs r6, 0x1 - ble _080AEA94 - movs r0, 0x50 - adds r5, r0 - lsls r3, 1 - b _080AE96C -_080AEA94: - ldr r0, [r7, 0xC] - adds r0, 0x1 - str r0, [r7, 0xC] - cmp r4, 0 - bne _080AEAA6 - movs r0, 0x80 - lsls r0, 24 - str r0, [r7, 0x4] - b _080AEB5C -_080AEAA6: - str r4, [r7, 0x4] - ldrh r0, [r7, 0x22] - subs r0, 0x96 -_080AEAAC: - strh r0, [r7, 0x22] - cmp r0, 0x96 - bcc _080AEAB4 - b _080AE964 -_080AEAB4: - ldrb r2, [r7, 0x8] - ldr r5, [r7, 0x2C] -_080AEAB8: - ldrb r0, [r5] - movs r1, 0x80 - tst r1, r0 - beq _080AEB52 - movs r1, 0xF - tst r1, r0 - beq _080AEB52 - mov r9, r2 - adds r0, r7, 0 - adds r1, r5, 0 - bl sub_80AF8C8 - ldr r4, [r5, 0x20] - cmp r4, 0 - beq _080AEB48 -_080AEAD6: - ldrb r1, [r4] - movs r0, 0xC7 - tst r0, r1 - bne _080AEAE6 - adds r0, r4, 0 - bl sub_80AF2FC - b _080AEB42 -_080AEAE6: - ldrb r0, [r4, 0x1] - movs r6, 0x7 - ands r6, r0 - ldrb r3, [r5] - movs r0, 0x3 - tst r0, r3 - beq _080AEB04 - bl sub_80AEBC0 - cmp r6, 0 - beq _080AEB04 - ldrb r0, [r4, 0x1D] - movs r1, 0x1 - orrs r0, r1 - strb r0, [r4, 0x1D] -_080AEB04: - ldrb r3, [r5] - movs r0, 0xC - tst r0, r3 - beq _080AEB42 - ldrb r1, [r4, 0x8] - movs r0, 0x8 - ldrsb r0, [r5, r0] - adds r2, r1, r0 - bpl _080AEB18 - movs r2, 0 -_080AEB18: - cmp r6, 0 - beq _080AEB36 - mov r0, r8 - ldr r3, [r0, 0x30] - adds r1, r2, 0 - ldrb r2, [r5, 0x9] - adds r0, r6, 0 - bl _080AEB6C - str r0, [r4, 0x20] - ldrb r0, [r4, 0x1D] - movs r1, 0x2 - orrs r0, r1 - strb r0, [r4, 0x1D] - b _080AEB42 -_080AEB36: - adds r1, r2, 0 - ldrb r2, [r5, 0x9] - ldr r0, [r4, 0x24] - bl sub_80AEE80 - str r0, [r4, 0x20] -_080AEB42: - ldr r4, [r4, 0x34] - cmp r4, 0 - bne _080AEAD6 -_080AEB48: - ldrb r0, [r5] - movs r1, 0xF0 - ands r0, r1 - strb r0, [r5] - mov r2, r9 -_080AEB52: - subs r2, 0x1 - ble _080AEB5C - movs r0, 0x50 - adds r5, r0 - bgt _080AEAB8 -_080AEB5C: - ldr r0, _080AEB78 - str r0, [r7, 0x34] - pop {r0-r7} - mov r8, r0 - mov r9, r1 - mov r10, r2 - mov r11, r3 - pop {r3} -_080AEB6C: - bx r3 - .align 2, 0 -_080AEB70: .4byte gUnknown_826FC00 -_080AEB74: .4byte SOUND_INFO_PTR -_080AEB78: .4byte 0x68736d53 - thumb_func_end sub_80AE914 - - thumb_func_start sub_80AEB7C -sub_80AEB7C: - push {r4-r6,lr} - adds r5, r1, 0 - ldrb r1, [r5] - movs r0, 0x80 - tst r0, r1 - beq _080AEBB4 - ldr r4, [r5, 0x20] - cmp r4, 0 - beq _080AEBB2 - movs r6, 0 -_080AEB90: - ldrb r0, [r4] - cmp r0, 0 - beq _080AEBAA - ldrb r0, [r4, 0x1] - movs r3, 0x7 - ands r0, r3 - beq _080AEBA8 - ldr r3, _080AEBBC - ldr r3, [r3] - ldr r3, [r3, 0x2C] - bl _080AEB6C -_080AEBA8: - strb r6, [r4] -_080AEBAA: - str r6, [r4, 0x2C] - ldr r4, [r4, 0x34] - cmp r4, 0 - bne _080AEB90 -_080AEBB2: - str r4, [r5, 0x20] -_080AEBB4: - pop {r4-r6} - pop {r0} - bx r0 - .align 2, 0 -_080AEBBC: .4byte SOUND_INFO_PTR - thumb_func_end sub_80AEB7C - - thumb_func_start sub_80AEBC0 -sub_80AEBC0: - ldrb r1, [r4, 0x12] - movs r0, 0x14 - ldrsb r2, [r4, r0] - movs r3, 0x80 - adds r3, r2 - muls r3, r1 - ldrb r0, [r5, 0x10] - muls r0, r3 - asrs r0, 14 - cmp r0, 0xFF - bls _080AEBD8 - movs r0, 0xFF -_080AEBD8: - strb r0, [r4, 0x2] - movs r3, 0x7F - subs r3, r2 - muls r3, r1 - ldrb r0, [r5, 0x11] - muls r0, r3 - asrs r0, 14 - cmp r0, 0xFF - bls _080AEBEC - movs r0, 0xFF -_080AEBEC: - strb r0, [r4, 0x3] - bx lr - thumb_func_end sub_80AEBC0 - - thumb_func_start sub_80AEBF0 -sub_80AEBF0: - push {r4-r7,lr} - mov r4, r8 - mov r5, r9 - mov r6, r10 - mov r7, r11 - push {r4-r7} - sub sp, 0x18 - str r1, [sp] - adds r5, r2, 0 - ldr r1, _080AEDE8 - ldr r1, [r1] - str r1, [sp, 0x4] - ldr r1, _080AEDEC - adds r0, r1 - ldrb r0, [r0] - strb r0, [r5, 0x4] - ldr r3, [r5, 0x40] - ldrb r0, [r3] - cmp r0, 0x80 - bcs _080AEC36 - strb r0, [r5, 0x5] - adds r3, 0x1 - ldrb r0, [r3] - cmp r0, 0x80 - bcs _080AEC34 - strb r0, [r5, 0x6] - adds r3, 0x1 - ldrb r0, [r3] - cmp r0, 0x80 - bcs _080AEC34 - ldrb r1, [r5, 0x4] - adds r1, r0 - strb r1, [r5, 0x4] - adds r3, 0x1 -_080AEC34: - str r3, [r5, 0x40] -_080AEC36: - movs r0, 0 - str r0, [sp, 0x14] - adds r4, r5, 0 - adds r4, 0x24 - ldrb r2, [r4] - movs r0, 0xC0 - tst r0, r2 - beq _080AEC88 - ldrb r3, [r5, 0x5] - movs r0, 0x40 - tst r0, r2 - beq _080AEC56 - ldr r1, [r5, 0x2C] - adds r1, r3 - ldrb r0, [r1] - b _080AEC58 -_080AEC56: - adds r0, r3, 0 -_080AEC58: - lsls r1, r0, 1 - adds r1, r0 - lsls r1, 2 - ldr r0, [r5, 0x28] - adds r1, r0 - mov r9, r1 - mov r6, r9 - ldrb r1, [r6] - movs r0, 0xC0 - tst r0, r1 - beq _080AEC70 - b _080AEDD6 -_080AEC70: - movs r0, 0x80 - tst r0, r2 - beq _080AEC8C - ldrb r1, [r6, 0x3] - movs r0, 0x80 - tst r0, r1 - beq _080AEC84 - subs r1, 0xC0 - lsls r1, 1 - str r1, [sp, 0x14] -_080AEC84: - ldrb r3, [r6, 0x1] - b _080AEC8C -_080AEC88: - mov r9, r4 - ldrb r3, [r5, 0x5] -_080AEC8C: - str r3, [sp, 0x8] - ldr r6, [sp] - ldrb r1, [r6, 0x9] - ldrb r0, [r5, 0x1D] - adds r0, r1 - cmp r0, 0xFF - bls _080AEC9C - movs r0, 0xFF -_080AEC9C: - str r0, [sp, 0x10] - mov r6, r9 - ldrb r0, [r6] - movs r6, 0x7 - ands r6, r0 - str r6, [sp, 0xC] - beq _080AECDC - ldr r0, [sp, 0x4] - ldr r4, [r0, 0x1C] - cmp r4, 0 - bne _080AECB4 - b _080AEDD6 -_080AECB4: - subs r6, 0x1 - lsls r0, r6, 6 - adds r4, r0 - ldrb r1, [r4] - movs r0, 0xC7 - tst r0, r1 - beq _080AED30 - movs r0, 0x40 - tst r0, r1 - bne _080AED30 - ldrb r1, [r4, 0x13] - ldr r0, [sp, 0x10] - cmp r1, r0 - bcc _080AED30 - beq _080AECD4 - b _080AEDD6 -_080AECD4: - ldr r0, [r4, 0x2C] - cmp r0, r5 - bcs _080AED30 - b _080AEDD6 -_080AECDC: - ldr r6, [sp, 0x10] - adds r7, r5, 0 - movs r2, 0 - mov r8, r2 - ldr r4, [sp, 0x4] - ldrb r3, [r4, 0x6] - adds r4, 0x50 -_080AECEA: - ldrb r1, [r4] - movs r0, 0xC7 - tst r0, r1 - beq _080AED30 - movs r0, 0x40 - tst r0, r1 - beq _080AED04 - cmp r2, 0 - bne _080AED08 - adds r2, 0x1 - ldrb r6, [r4, 0x13] - ldr r7, [r4, 0x2C] - b _080AED22 -_080AED04: - cmp r2, 0 - bne _080AED24 -_080AED08: - ldrb r0, [r4, 0x13] - cmp r0, r6 - bcs _080AED14 - adds r6, r0, 0 - ldr r7, [r4, 0x2C] - b _080AED22 -_080AED14: - bhi _080AED24 - ldr r0, [r4, 0x2C] - cmp r0, r7 - bls _080AED20 - adds r7, r0, 0 - b _080AED22 -_080AED20: - bcc _080AED24 -_080AED22: - mov r8, r4 -_080AED24: - adds r4, 0x40 - subs r3, 0x1 - bgt _080AECEA - mov r4, r8 - cmp r4, 0 - beq _080AEDD6 -_080AED30: - adds r0, r4, 0 - bl sub_80AF2FC - movs r1, 0 - str r1, [r4, 0x30] - ldr r3, [r5, 0x20] - str r3, [r4, 0x34] - cmp r3, 0 - beq _080AED44 - str r4, [r3, 0x30] -_080AED44: - str r4, [r5, 0x20] - str r5, [r4, 0x2C] - ldrb r0, [r5, 0x1B] - strb r0, [r5, 0x1C] - cmp r0, r1 - beq _080AED56 - adds r1, r5, 0 - bl sub_80AEE30 -_080AED56: - ldr r0, [sp] - adds r1, r5, 0 - bl sub_80AF8C8 - ldr r0, [r5, 0x4] - str r0, [r4, 0x10] - ldr r0, [sp, 0x10] - strb r0, [r4, 0x13] - ldr r0, [sp, 0x8] - strb r0, [r4, 0x8] - ldr r0, [sp, 0x14] - strb r0, [r4, 0x14] - mov r6, r9 - ldrb r0, [r6] - strb r0, [r4, 0x1] - ldr r7, [r6, 0x4] - str r7, [r4, 0x24] - ldr r0, [r6, 0x8] - str r0, [r4, 0x4] - ldrh r0, [r5, 0x1E] - strh r0, [r4, 0xC] - bl sub_80AEBC0 - ldrb r1, [r4, 0x8] - movs r0, 0x8 - ldrsb r0, [r5, r0] - adds r3, r1, r0 - bpl _080AED90 - movs r3, 0 -_080AED90: - ldr r6, [sp, 0xC] - cmp r6, 0 - beq _080AEDBE - mov r6, r9 - ldrb r0, [r6, 0x2] - strb r0, [r4, 0x1E] - ldrb r1, [r6, 0x3] - movs r0, 0x80 - tst r0, r1 - bne _080AEDAA - movs r0, 0x70 - tst r0, r1 - bne _080AEDAC -_080AEDAA: - movs r1, 0x8 -_080AEDAC: - strb r1, [r4, 0x1F] - ldrb r2, [r5, 0x9] - adds r1, r3, 0 - ldr r0, [sp, 0xC] - ldr r3, [sp, 0x4] - ldr r3, [r3, 0x30] - bl _080AEB6C - b _080AEDC8 -_080AEDBE: - ldrb r2, [r5, 0x9] - adds r1, r3, 0 - adds r0, r7, 0 - bl sub_80AEE80 -_080AEDC8: - str r0, [r4, 0x20] - movs r0, 0x80 - strb r0, [r4] - ldrb r1, [r5] - movs r0, 0xF0 - ands r0, r1 - strb r0, [r5] -_080AEDD6: - add sp, 0x18 - pop {r0-r7} - mov r8, r0 - mov r9, r1 - mov r10, r2 - mov r11, r3 - pop {r0} - bx r0 - .align 2, 0 -_080AEDE8: .4byte SOUND_INFO_PTR -_080AEDEC: .4byte gUnknown_826FC00 - thumb_func_end sub_80AEBF0 - - thumb_func_start sub_80AEDF0 -sub_80AEDF0: - push {r4,r5} - ldr r2, [r1, 0x40] - ldrb r3, [r2] - cmp r3, 0x80 - bcs _080AEE02 - strb r3, [r1, 0x5] - adds r2, 0x1 - str r2, [r1, 0x40] - b _080AEE04 -_080AEE02: - ldrb r3, [r1, 0x5] -_080AEE04: - ldr r1, [r1, 0x20] - cmp r1, 0 - beq _080AEE2C - movs r4, 0x83 - movs r5, 0x40 -_080AEE0E: - ldrb r2, [r1] - tst r2, r4 - beq _080AEE26 - tst r2, r5 - bne _080AEE26 - ldrb r0, [r1, 0x11] - cmp r0, r3 - bne _080AEE26 - movs r0, 0x40 - orrs r2, r0 - strb r2, [r1] - b _080AEE2C -_080AEE26: - ldr r1, [r1, 0x34] - cmp r1, 0 - bne _080AEE0E -_080AEE2C: - pop {r4,r5} - bx lr - thumb_func_end sub_80AEDF0 - - thumb_func_start sub_80AEE30 -sub_80AEE30: - movs r2, 0 - strb r2, [r1, 0x16] - strb r2, [r1, 0x1A] - ldrb r2, [r1, 0x18] - cmp r2, 0 - bne _080AEE40 - movs r2, 0xC - b _080AEE42 -_080AEE40: - movs r2, 0x3 -_080AEE42: - ldrb r3, [r1] - orrs r3, r2 - strb r3, [r1] - bx lr - thumb_func_end sub_80AEE30 - - thumb_func_start sub_80AEE4C -sub_80AEE4C: - ldr r2, [r1, 0x40] - adds r3, r2, 0x1 - str r3, [r1, 0x40] - ldrb r3, [r2] - bx lr - thumb_func_end sub_80AEE4C - - thumb_func_start sub_80AEE58 -sub_80AEE58: - mov r12, lr - bl sub_80AEE4C - strb r3, [r1, 0x19] - cmp r3, 0 - bne _080AEE68 - bl sub_80AEE30 -_080AEE68: - bx r12 - thumb_func_end sub_80AEE58 - - thumb_func_start sub_80AEE6C -sub_80AEE6C: - mov r12, lr - bl sub_80AEE4C - strb r3, [r1, 0x17] - cmp r3, 0 - bne _080AEE7C - bl sub_80AEE30 -_080AEE7C: - bx r12 - thumb_func_end sub_80AEE6C - - thumb_func_start sub_80AEE80 -sub_80AEE80: - push {r4-r7,lr} - mov r12, r0 - lsls r1, 24 - lsrs r6, r1, 24 - lsls r7, r2, 24 - cmp r6, 0xB2 - bls _080AEE94 - movs r6, 0xB2 - movs r7, 0xFF - lsls r7, 24 -_080AEE94: - ldr r3, _080AEEDC - adds r0, r6, r3 - ldrb r5, [r0] - ldr r4, _080AEEE0 - movs r2, 0xF - adds r0, r5, 0 - ands r0, r2 - lsls r0, 2 - adds r0, r4 - lsrs r1, r5, 4 - ldr r5, [r0] - lsrs r5, r1 - adds r0, r6, 0x1 - adds r0, r3 - ldrb r1, [r0] - adds r0, r1, 0 - ands r0, r2 - lsls r0, 2 - adds r0, r4 - lsrs r1, 4 - ldr r0, [r0] - lsrs r0, r1 - mov r1, r12 - ldr r4, [r1, 0x4] - subs r0, r5 - adds r1, r7, 0 - bl umul3232H32 - adds r1, r0, 0 - adds r1, r5, r1 - adds r0, r4, 0 - bl umul3232H32 - pop {r4-r7} - pop {r1} - bx r1 - .align 2, 0 -_080AEEDC: .4byte gUnknown_826FA1C -_080AEEE0: .4byte gUnknown_826FAD0 - thumb_func_end sub_80AEE80 - - thumb_func_start nullsub_212 -nullsub_212: - bx lr - thumb_func_end nullsub_212 - - thumb_func_start sub_80AEEE8 -sub_80AEEE8: - adds r2, r0, 0 - ldr r3, [r2, 0x34] - ldr r0, _080AEEFC - cmp r3, r0 - bne _080AEEFA - ldr r0, [r2, 0x4] - ldr r1, _080AEF00 - ands r0, r1 - str r0, [r2, 0x4] -_080AEEFA: - bx lr - .align 2, 0 -_080AEEFC: .4byte 0x68736d53 -_080AEF00: .4byte 0x7fffffff - thumb_func_end sub_80AEEE8 - - thumb_func_start sub_80AEF04 -sub_80AEF04: - adds r2, r0, 0 - lsls r1, 16 - lsrs r1, 16 - ldr r3, [r2, 0x34] - ldr r0, _080AEF20 - cmp r3, r0 - bne _080AEF1C - strh r1, [r2, 0x26] - strh r1, [r2, 0x24] - movs r0, 0x80 - lsls r0, 1 - strh r0, [r2, 0x28] -_080AEF1C: - bx lr - .align 2, 0 -_080AEF20: .4byte 0x68736d53 - thumb_func_end sub_80AEF04 - - thumb_func_start sub_80AEF24 -sub_80AEF24: - push {r4-r6,lr} - ldr r0, _080AEF78 - movs r1, 0x2 - negs r1, r1 - ands r0, r1 - ldr r1, _080AEF7C - ldr r2, _080AEF80 - bl CpuSet - ldr r0, _080AEF84 - bl sub_80AF324 - ldr r0, _080AEF88 - bl sub_80AF1E0 - ldr r0, _080AEF8C - bl sub_80AF4C0 - ldr r0, _080AEF90 - lsls r0, 16 - lsrs r0, 16 - cmp r0, 0 - beq _080AEF72 - ldr r5, _080AEF94 - adds r6, r0, 0 -_080AEF56: - ldr r4, [r5] - ldr r1, [r5, 0x4] - ldrb r2, [r5, 0x8] - adds r0, r4, 0 - bl sub_80AF664 - ldrh r0, [r5, 0xA] - strb r0, [r4, 0xB] - ldr r0, _080AEF98 - str r0, [r4, 0x18] - adds r5, 0xC - subs r6, 0x1 - cmp r6, 0 - bne _080AEF56 -_080AEF72: - pop {r4-r6} - pop {r0} - bx r0 - .align 2, 0 -_080AEF78: .4byte SoundMainRAM -_080AEF7C: .4byte SoundMainRAM_Buffer -_080AEF80: .4byte 0x04000100 -_080AEF84: .4byte gUnknown_2039ED0 -_080AEF88: .4byte gUnknown_203AF10 -_080AEF8C: .4byte 0x0096e500 -_080AEF90: .4byte 0x00000008 -_080AEF94: .4byte 0x09e8665c -_080AEF98: .4byte gUnknown_2000A30 - thumb_func_end sub_80AEF24 - - thumb_func_start m4aSoundMain -m4aSoundMain: - push {lr} - bl SoundMain - pop {r0} - bx r0 - thumb_func_end m4aSoundMain - - thumb_func_start sub_80AEFA8 -sub_80AEFA8: - push {lr} - lsls r0, 16 - ldr r2, _080AEFCC - ldr r1, _080AEFD0 - lsrs r0, 13 - adds r0, r1 - ldrh r3, [r0, 0x4] - lsls r1, r3, 1 - adds r1, r3 - lsls r1, 2 - adds r1, r2 - ldr r2, [r1] - ldr r1, [r0] - adds r0, r2, 0 - bl sub_80AF6DC - pop {r0} - bx r0 - .align 2, 0 -_080AEFCC: .4byte 0x09e8665c -_080AEFD0: .4byte 0x09e866bc - thumb_func_end sub_80AEFA8 - - thumb_func_start sub_80AEFD4 -sub_80AEFD4: - push {lr} - lsls r0, 16 - ldr r2, _080AF000 - ldr r1, _080AF004 - lsrs r0, 13 - adds r0, r1 - ldrh r3, [r0, 0x4] - lsls r1, r3, 1 - adds r1, r3 - lsls r1, 2 - adds r1, r2 - ldr r1, [r1] - ldr r3, [r1] - ldr r2, [r0] - cmp r3, r2 - beq _080AF008 - adds r0, r1, 0 - adds r1, r2, 0 - bl sub_80AF6DC - b _080AF01C - .align 2, 0 -_080AF000: .4byte 0x09e8665c -_080AF004: .4byte 0x09e866bc -_080AF008: - ldr r2, [r1, 0x4] - ldrh r0, [r1, 0x4] - cmp r0, 0 - beq _080AF014 - cmp r2, 0 - bge _080AF01C -_080AF014: - adds r0, r1, 0 - adds r1, r3, 0 - bl sub_80AF6DC -_080AF01C: - pop {r0} - bx r0 - thumb_func_end sub_80AEFD4 - - thumb_func_start sub_80AF020 -sub_80AF020: - push {lr} - lsls r0, 16 - ldr r2, _080AF04C - ldr r1, _080AF050 - lsrs r0, 13 - adds r0, r1 - ldrh r3, [r0, 0x4] - lsls r1, r3, 1 - adds r1, r3 - lsls r1, 2 - adds r1, r2 - ldr r1, [r1] - ldr r3, [r1] - ldr r2, [r0] - cmp r3, r2 - beq _080AF054 - adds r0, r1, 0 - adds r1, r2, 0 - bl sub_80AF6DC - b _080AF070 - .align 2, 0 -_080AF04C: .4byte 0x09e8665c -_080AF050: .4byte 0x09e866bc -_080AF054: - ldr r2, [r1, 0x4] - ldrh r0, [r1, 0x4] - cmp r0, 0 - bne _080AF066 - adds r0, r1, 0 - adds r1, r3, 0 - bl sub_80AF6DC - b _080AF070 -_080AF066: - cmp r2, 0 - bge _080AF070 - adds r0, r1, 0 - bl sub_80AEEE8 -_080AF070: - pop {r0} - bx r0 - thumb_func_end sub_80AF020 - - thumb_func_start sub_80AF074 -sub_80AF074: - push {lr} - lsls r0, 16 - ldr r2, _080AF0A0 - ldr r1, _080AF0A4 - lsrs r0, 13 - adds r0, r1 - ldrh r3, [r0, 0x4] - lsls r1, r3, 1 - adds r1, r3 - lsls r1, 2 - adds r1, r2 - ldr r2, [r1] - ldr r1, [r2] - ldr r0, [r0] - cmp r1, r0 - bne _080AF09A - adds r0, r2, 0 - bl sub_80AF7C0 -_080AF09A: - pop {r0} - bx r0 - .align 2, 0 -_080AF0A0: .4byte 0x09e8665c -_080AF0A4: .4byte 0x09e866bc - thumb_func_end sub_80AF074 - - thumb_func_start sub_80AF0A8 -sub_80AF0A8: - push {lr} - lsls r0, 16 - ldr r2, _080AF0D4 - ldr r1, _080AF0D8 - lsrs r0, 13 - adds r0, r1 - ldrh r3, [r0, 0x4] - lsls r1, r3, 1 - adds r1, r3 - lsls r1, 2 - adds r1, r2 - ldr r2, [r1] - ldr r1, [r2] - ldr r0, [r0] - cmp r1, r0 - bne _080AF0CE - adds r0, r2, 0 - bl sub_80AEEE8 -_080AF0CE: - pop {r0} - bx r0 - .align 2, 0 -_080AF0D4: .4byte 0x09e8665c -_080AF0D8: .4byte 0x09e866bc - thumb_func_end sub_80AF0A8 - - thumb_func_start sub_80AF0DC -sub_80AF0DC: - push {r4,r5,lr} - ldr r0, _080AF100 - lsls r0, 16 - lsrs r0, 16 - cmp r0, 0 - beq _080AF0FA - ldr r5, _080AF104 - adds r4, r0, 0 -_080AF0EC: - ldr r0, [r5] - bl sub_80AF7C0 - adds r5, 0xC - subs r4, 0x1 - cmp r4, 0 - bne _080AF0EC -_080AF0FA: - pop {r4,r5} - pop {r0} - bx r0 - .align 2, 0 -_080AF100: .4byte 0x00000008 -_080AF104: .4byte 0x09e8665c - thumb_func_end sub_80AF0DC - - thumb_func_start sub_80AF108 -sub_80AF108: - push {lr} - bl sub_80AEEE8 - pop {r0} - bx r0 - thumb_func_end sub_80AF108 - - thumb_func_start sub_80AF114 -sub_80AF114: - push {r4,r5,lr} - ldr r0, _080AF138 - lsls r0, 16 - lsrs r0, 16 - cmp r0, 0 - beq _080AF132 - ldr r5, _080AF13C - adds r4, r0, 0 -_080AF124: - ldr r0, [r5] - bl sub_80AEEE8 - adds r5, 0xC - subs r4, 0x1 - cmp r4, 0 - bne _080AF124 -_080AF132: - pop {r4,r5} - pop {r0} - bx r0 - .align 2, 0 -_080AF138: .4byte 0x00000008 -_080AF13C: .4byte 0x09e8665c - thumb_func_end sub_80AF114 - - thumb_func_start sub_80AF140 -sub_80AF140: - push {lr} - lsls r1, 16 - lsrs r1, 16 - bl sub_80AEF04 - pop {r0} - bx r0 - thumb_func_end sub_80AF140 - - thumb_func_start sub_80AF150 -sub_80AF150: - adds r2, r0, 0 - lsls r1, 16 - lsrs r1, 16 - ldr r3, [r2, 0x34] - ldr r0, _080AF168 - cmp r3, r0 - bne _080AF166 - strh r1, [r2, 0x26] - strh r1, [r2, 0x24] - ldr r0, _080AF16C - strh r0, [r2, 0x28] -_080AF166: - bx lr - .align 2, 0 -_080AF168: .4byte 0x68736d53 -_080AF16C: .4byte 0x00000101 - thumb_func_end sub_80AF150 - - thumb_func_start sub_80AF170 -sub_80AF170: - adds r2, r0, 0 - lsls r1, 16 - lsrs r1, 16 - ldr r3, [r2, 0x34] - ldr r0, _080AF190 - cmp r3, r0 - bne _080AF18E - strh r1, [r2, 0x26] - strh r1, [r2, 0x24] - movs r0, 0x2 - strh r0, [r2, 0x28] - ldr r0, [r2, 0x4] - ldr r1, _080AF194 - ands r0, r1 - str r0, [r2, 0x4] -_080AF18E: - bx lr - .align 2, 0 -_080AF190: .4byte 0x68736d53 -_080AF194: .4byte 0x7fffffff - thumb_func_end sub_80AF170 - - thumb_func_start sub_80AF198 -sub_80AF198: - push {r4-r7,lr} - ldrb r5, [r0, 0x8] - ldr r4, [r0, 0x2C] - cmp r5, 0 - ble _080AF1DA - movs r7, 0x80 -_080AF1A4: - ldrb r1, [r4] - adds r0, r7, 0 - ands r0, r1 - cmp r0, 0 - beq _080AF1D2 - movs r6, 0x40 - adds r0, r6, 0 - ands r0, r1 - cmp r0, 0 - beq _080AF1D2 - adds r0, r4, 0 - bl sub_80AF310 - strb r7, [r4] - movs r0, 0x2 - strb r0, [r4, 0xF] - strb r6, [r4, 0x13] - movs r0, 0x16 - strb r0, [r4, 0x19] - adds r1, r4, 0 - adds r1, 0x24 - movs r0, 0x1 - strb r0, [r1] -_080AF1D2: - subs r5, 0x1 - adds r4, 0x50 - cmp r5, 0 - bgt _080AF1A4 -_080AF1DA: - pop {r4-r7} - pop {r0} - bx r0 - thumb_func_end sub_80AF198 - - thumb_func_start sub_80AF1E0 -sub_80AF1E0: - push {r4-r6,lr} - sub sp, 0x4 - adds r5, r0, 0 - ldr r1, _080AF2A8 - movs r0, 0x8F - strh r0, [r1] - ldr r3, _080AF2AC - movs r2, 0 - strh r2, [r3] - ldr r0, _080AF2B0 - movs r1, 0x8 - strb r1, [r0] - adds r0, 0x6 - strb r1, [r0] - adds r0, 0x10 - strb r1, [r0] - subs r0, 0x14 - movs r1, 0x80 - strb r1, [r0] - adds r0, 0x8 - strb r1, [r0] - adds r0, 0x10 - strb r1, [r0] - subs r0, 0xD - strb r2, [r0] - movs r0, 0x77 - strb r0, [r3] - ldr r0, _080AF2B4 - ldr r4, [r0] - ldr r6, [r4] - ldr r0, _080AF2B8 - cmp r6, r0 - bne _080AF2A0 - adds r0, r6, 0x1 - str r0, [r4] - ldr r1, _080AF2BC - ldr r0, _080AF2C0 - str r0, [r1, 0x20] - ldr r0, _080AF2C4 - str r0, [r1, 0x44] - ldr r0, _080AF2C8 - str r0, [r1, 0x4C] - ldr r0, _080AF2CC - str r0, [r1, 0x70] - ldr r0, _080AF2D0 - str r0, [r1, 0x74] - ldr r0, _080AF2D4 - str r0, [r1, 0x78] - ldr r0, _080AF2D8 - str r0, [r1, 0x7C] - adds r2, r1, 0 - adds r2, 0x80 - ldr r0, _080AF2DC - str r0, [r2] - adds r1, 0x84 - ldr r0, _080AF2E0 - str r0, [r1] - str r5, [r4, 0x1C] - ldr r0, _080AF2E4 - str r0, [r4, 0x28] - ldr r0, _080AF2E8 - str r0, [r4, 0x2C] - ldr r0, _080AF2EC - str r0, [r4, 0x30] - ldr r0, _080AF2F0 - movs r1, 0 - strb r0, [r4, 0xC] - str r1, [sp] - ldr r2, _080AF2F4 - mov r0, sp - adds r1, r5, 0 - bl CpuSet - movs r0, 0x1 - strb r0, [r5, 0x1] - movs r0, 0x11 - strb r0, [r5, 0x1C] - adds r1, r5, 0 - adds r1, 0x41 - movs r0, 0x2 - strb r0, [r1] - adds r1, 0x1B - movs r0, 0x22 - strb r0, [r1] - adds r1, 0x25 - movs r0, 0x3 - strb r0, [r1] - adds r1, 0x1B - movs r0, 0x44 - strb r0, [r1] - adds r1, 0x24 - movs r0, 0x4 - strb r0, [r1, 0x1] - movs r0, 0x88 - strb r0, [r1, 0x1C] - str r6, [r4] -_080AF2A0: - add sp, 0x4 - pop {r4-r6} - pop {r0} - bx r0 - .align 2, 0 -_080AF2A8: .4byte 0x04000084 -_080AF2AC: .4byte 0x04000080 -_080AF2B0: .4byte 0x04000063 -_080AF2B4: .4byte SOUND_INFO_PTR -_080AF2B8: .4byte 0x68736d53 -_080AF2BC: .4byte gUnknown_203AE80 -_080AF2C0: .4byte sub_80B019C -_080AF2C4: .4byte sub_80AEE58 -_080AF2C8: .4byte sub_80AEE6C -_080AF2CC: .4byte sub_80B02F4 -_080AF2D0: .4byte sub_80AEDF0 -_080AF2D4: .4byte sub_80AF41C -_080AF2D8: .4byte sub_80AEB7C -_080AF2DC: .4byte sub_80AF800 -_080AF2E0: .4byte sub_80AF8C8 -_080AF2E4: .4byte sub_80AFADC -_080AF2E8: .4byte sub_80AFA24 -_080AF2EC: .4byte sub_80AF97C -_080AF2F0: .4byte 0x00000000 -_080AF2F4: .4byte 0x05000040 - thumb_func_end sub_80AF1E0 - - thumb_func_start sub_80AF2F8 -sub_80AF2F8: - swi 0x2A - bx lr - thumb_func_end sub_80AF2F8 - - thumb_func_start sub_80AF2FC -sub_80AF2FC: - push {lr} - ldr r1, _080AF30C - ldr r1, [r1] - bl _call_via_r1 - pop {r0} - bx r0 - .align 2, 0 -_080AF30C: .4byte gUnknown_203AF08 - thumb_func_end sub_80AF2FC - - thumb_func_start sub_80AF310 -sub_80AF310: - push {lr} - ldr r1, _080AF320 - ldr r1, [r1] - bl _call_via_r1 - pop {r0} - bx r0 - .align 2, 0 -_080AF320: .4byte gUnknown_203AF0C - thumb_func_end sub_80AF310 - - thumb_func_start sub_80AF324 -sub_80AF324: - push {r4,r5,lr} - sub sp, 0x4 - adds r5, r0, 0 - movs r3, 0 - str r3, [r5] - ldr r1, _080AF3DC - ldr r0, [r1] - movs r2, 0x80 - lsls r2, 18 - ands r0, r2 - cmp r0, 0 - beq _080AF340 - ldr r0, _080AF3E0 - str r0, [r1] -_080AF340: - ldr r1, _080AF3E4 - ldr r0, [r1] - ands r0, r2 - cmp r0, 0 - beq _080AF34E - ldr r0, _080AF3E0 - str r0, [r1] -_080AF34E: - ldr r0, _080AF3E8 - movs r2, 0x80 - lsls r2, 3 - adds r1, r2, 0 - strh r1, [r0] - adds r0, 0xC - strh r1, [r0] - ldr r1, _080AF3EC - movs r0, 0x8F - strh r0, [r1] - subs r1, 0x2 - ldr r2, _080AF3F0 - adds r0, r2, 0 - strh r0, [r1] - ldr r2, _080AF3F4 - ldrb r1, [r2] - movs r0, 0x3F - ands r0, r1 - movs r1, 0x40 - orrs r0, r1 - strb r0, [r2] - ldr r1, _080AF3F8 - movs r2, 0xD4 - lsls r2, 2 - adds r0, r5, r2 - str r0, [r1] - adds r1, 0x4 - ldr r0, _080AF3FC - str r0, [r1] - adds r1, 0x8 - movs r2, 0x98 - lsls r2, 4 - adds r0, r5, r2 - str r0, [r1] - adds r1, 0x4 - ldr r0, _080AF400 - str r0, [r1] - ldr r0, _080AF404 - str r5, [r0] - str r3, [sp] - ldr r2, _080AF408 - mov r0, sp - adds r1, r5, 0 - bl CpuSet - movs r0, 0x8 - strb r0, [r5, 0x6] - movs r0, 0xF - strb r0, [r5, 0x7] - ldr r0, _080AF40C - str r0, [r5, 0x38] - ldr r0, _080AF410 - str r0, [r5, 0x28] - str r0, [r5, 0x2C] - str r0, [r5, 0x30] - str r0, [r5, 0x3C] - ldr r4, _080AF414 - adds r0, r4, 0 - bl sub_80AE704 - str r4, [r5, 0x34] - movs r0, 0x80 - lsls r0, 11 - bl sub_80AF41C - ldr r0, _080AF418 - str r0, [r5] - add sp, 0x4 - pop {r4,r5} - pop {r0} - bx r0 - .align 2, 0 -_080AF3DC: .4byte 0x040000c4 -_080AF3E0: .4byte 0x84400004 -_080AF3E4: .4byte 0x040000d0 -_080AF3E8: .4byte 0x040000c6 -_080AF3EC: .4byte 0x04000084 -_080AF3F0: .4byte 0x0000a90e -_080AF3F4: .4byte 0x04000089 -_080AF3F8: .4byte 0x040000bc -_080AF3FC: .4byte 0x040000a0 -_080AF400: .4byte 0x040000a4 -_080AF404: .4byte SOUND_INFO_PTR -_080AF408: .4byte 0x050003ec -_080AF40C: .4byte sub_80AEBF0 -_080AF410: .4byte nullsub_139 -_080AF414: .4byte gUnknown_203AE80 -_080AF418: .4byte 0x68736d53 - thumb_func_end sub_80AF324 - - thumb_func_start sub_80AF41C -sub_80AF41C: - push {r4-r6,lr} - adds r2, r0, 0 - ldr r0, _080AF49C - ldr r4, [r0] - movs r0, 0xF0 - lsls r0, 12 - ands r0, r2 - lsrs r2, r0, 16 - movs r6, 0 - strb r2, [r4, 0x8] - ldr r1, _080AF4A0 - subs r0, r2, 0x1 - lsls r0, 1 - adds r0, r1 - ldrh r5, [r0] - str r5, [r4, 0x10] - movs r0, 0xC6 - lsls r0, 3 - adds r1, r5, 0 - bl __divsi3 - strb r0, [r4, 0xB] - ldr r0, _080AF4A4 - muls r0, r5 - ldr r1, _080AF4A8 - adds r0, r1 - ldr r1, _080AF4AC - bl __divsi3 - adds r1, r0, 0 - str r1, [r4, 0x14] - movs r0, 0x80 - lsls r0, 17 - bl __divsi3 - adds r0, 0x1 - asrs r0, 1 - str r0, [r4, 0x18] - ldr r0, _080AF4B0 - strh r6, [r0] - ldr r4, _080AF4B4 - ldr r0, _080AF4B8 - adds r1, r5, 0 - bl __divsi3 - negs r0, r0 - strh r0, [r4] - bl sub_80AF628 - ldr r1, _080AF4BC -_080AF480: - ldrb r0, [r1] - cmp r0, 0x9F - beq _080AF480 - ldr r1, _080AF4BC -_080AF488: - ldrb r0, [r1] - cmp r0, 0x9F - bne _080AF488 - ldr r1, _080AF4B0 - movs r0, 0x80 - strh r0, [r1] - pop {r4-r6} - pop {r0} - bx r0 - .align 2, 0 -_080AF49C: .4byte SOUND_INFO_PTR -_080AF4A0: .4byte gUnknown_826FB00 -_080AF4A4: .4byte 0x00091d1b -_080AF4A8: .4byte 0x00001388 -_080AF4AC: .4byte 0x00002710 -_080AF4B0: .4byte 0x04000102 -_080AF4B4: .4byte 0x04000100 -_080AF4B8: .4byte 0x00044940 -_080AF4BC: .4byte 0x04000006 - thumb_func_end sub_80AF41C - - thumb_func_start sub_80AF4C0 -sub_80AF4C0: - push {r4,r5,lr} - adds r3, r0, 0 - ldr r0, _080AF54C - ldr r5, [r0] - ldr r1, [r5] - ldr r0, _080AF550 - cmp r1, r0 - bne _080AF546 - adds r0, r1, 0x1 - str r0, [r5] - movs r4, 0xFF - ands r4, r3 - cmp r4, 0 - beq _080AF4E2 - movs r0, 0x7F - ands r4, r0 - strb r4, [r5, 0x5] -_080AF4E2: - movs r4, 0xF0 - lsls r4, 4 - ands r4, r3 - cmp r4, 0 - beq _080AF502 - lsrs r0, r4, 8 - strb r0, [r5, 0x6] - movs r4, 0xC - adds r0, r5, 0 - adds r0, 0x50 - movs r1, 0 -_080AF4F8: - strb r1, [r0] - subs r4, 0x1 - adds r0, 0x40 - cmp r4, 0 - bne _080AF4F8 -_080AF502: - movs r4, 0xF0 - lsls r4, 8 - ands r4, r3 - cmp r4, 0 - beq _080AF510 - lsrs r0, r4, 12 - strb r0, [r5, 0x7] -_080AF510: - movs r4, 0xB0 - lsls r4, 16 - ands r4, r3 - cmp r4, 0 - beq _080AF52E - movs r0, 0xC0 - lsls r0, 14 - ands r0, r4 - lsrs r4, r0, 14 - ldr r2, _080AF554 - ldrb r1, [r2] - movs r0, 0x3F - ands r0, r1 - orrs r0, r4 - strb r0, [r2] -_080AF52E: - movs r4, 0xF0 - lsls r4, 12 - ands r4, r3 - cmp r4, 0 - beq _080AF542 - bl sub_80AF5AC - adds r0, r4, 0 - bl sub_80AF41C -_080AF542: - ldr r0, _080AF550 - str r0, [r5] -_080AF546: - pop {r4,r5} - pop {r0} - bx r0 - .align 2, 0 -_080AF54C: .4byte SOUND_INFO_PTR -_080AF550: .4byte 0x68736d53 -_080AF554: .4byte 0x04000089 - thumb_func_end sub_80AF4C0 - - thumb_func_start sub_80AF558 -sub_80AF558: - push {r4-r7,lr} - ldr r0, _080AF5A4 - ldr r6, [r0] - ldr r1, [r6] - ldr r0, _080AF5A8 - cmp r1, r0 - bne _080AF59E - adds r0, r1, 0x1 - str r0, [r6] - movs r5, 0xC - adds r4, r6, 0 - adds r4, 0x50 - movs r0, 0 -_080AF572: - strb r0, [r4] - subs r5, 0x1 - adds r4, 0x40 - cmp r5, 0 - bgt _080AF572 - ldr r4, [r6, 0x1C] - cmp r4, 0 - beq _080AF59A - movs r5, 0x1 - movs r7, 0 -_080AF586: - lsls r0, r5, 24 - lsrs r0, 24 - ldr r1, [r6, 0x2C] - bl _call_via_r1 - strb r7, [r4] - adds r5, 0x1 - adds r4, 0x40 - cmp r5, 0x4 - ble _080AF586 -_080AF59A: - ldr r0, _080AF5A8 - str r0, [r6] -_080AF59E: - pop {r4-r7} - pop {r0} - bx r0 - .align 2, 0 -_080AF5A4: .4byte SOUND_INFO_PTR -_080AF5A8: .4byte 0x68736d53 - thumb_func_end sub_80AF558 - - thumb_func_start sub_80AF5AC -sub_80AF5AC: - push {lr} - sub sp, 0x4 - ldr r0, _080AF60C - ldr r2, [r0] - ldr r1, [r2] - ldr r3, _080AF610 - adds r0, r1, r3 - cmp r0, 0x1 - bhi _080AF604 - adds r0, r1, 0 - adds r0, 0xA - str r0, [r2] - ldr r1, _080AF614 - ldr r0, [r1] - movs r3, 0x80 - lsls r3, 18 - ands r0, r3 - cmp r0, 0 - beq _080AF5D6 - ldr r0, _080AF618 - str r0, [r1] -_080AF5D6: - ldr r1, _080AF61C - ldr r0, [r1] - ands r0, r3 - cmp r0, 0 - beq _080AF5E4 - ldr r0, _080AF618 - str r0, [r1] -_080AF5E4: - ldr r0, _080AF620 - movs r3, 0x80 - lsls r3, 3 - adds r1, r3, 0 - strh r1, [r0] - adds r0, 0xC - strh r1, [r0] - movs r0, 0 - str r0, [sp] - movs r0, 0xD4 - lsls r0, 2 - adds r1, r2, r0 - ldr r2, _080AF624 - mov r0, sp - bl CpuSet -_080AF604: - add sp, 0x4 - pop {r0} - bx r0 - .align 2, 0 -_080AF60C: .4byte SOUND_INFO_PTR -_080AF610: .4byte 0x978c92ad -_080AF614: .4byte 0x040000c4 -_080AF618: .4byte 0x84400004 -_080AF61C: .4byte 0x040000d0 -_080AF620: .4byte 0x040000c6 -_080AF624: .4byte 0x05000318 - thumb_func_end sub_80AF5AC - - thumb_func_start sub_80AF628 -sub_80AF628: - push {r4,lr} - ldr r0, _080AF658 - ldr r2, [r0] - ldr r3, [r2] - ldr r0, _080AF65C - cmp r3, r0 - beq _080AF650 - ldr r0, _080AF660 - movs r4, 0xB6 - lsls r4, 8 - adds r1, r4, 0 - strh r1, [r0] - adds r0, 0xC - strh r1, [r0] - ldrb r0, [r2, 0x4] - movs r0, 0 - strb r0, [r2, 0x4] - adds r0, r3, 0 - subs r0, 0xA - str r0, [r2] -_080AF650: - pop {r4} - pop {r0} - bx r0 - .align 2, 0 -_080AF658: .4byte SOUND_INFO_PTR -_080AF65C: .4byte 0x68736d53 -_080AF660: .4byte 0x040000c6 - thumb_func_end sub_80AF628 - - thumb_func_start sub_80AF664 -sub_80AF664: - push {r4-r7,lr} - adds r7, r0, 0 - adds r6, r1, 0 - lsls r2, 24 - lsrs r4, r2, 24 - cmp r4, 0 - beq _080AF6C8 - cmp r4, 0x10 - bls _080AF678 - movs r4, 0x10 -_080AF678: - ldr r0, _080AF6D0 - ldr r5, [r0] - ldr r1, [r5] - ldr r0, _080AF6D4 - cmp r1, r0 - bne _080AF6C8 - adds r0, r1, 0x1 - str r0, [r5] - adds r0, r7, 0 - bl sub_80AF310 - str r6, [r7, 0x2C] - strb r4, [r7, 0x8] - movs r0, 0x80 - lsls r0, 24 - str r0, [r7, 0x4] - cmp r4, 0 - beq _080AF6AC - movs r1, 0 -_080AF69E: - strb r1, [r6] - subs r0, r4, 0x1 - lsls r0, 24 - lsrs r4, r0, 24 - adds r6, 0x50 - cmp r4, 0 - bne _080AF69E -_080AF6AC: - ldr r0, [r5, 0x20] - cmp r0, 0 - beq _080AF6BC - str r0, [r7, 0x38] - ldr r0, [r5, 0x24] - str r0, [r7, 0x3C] - movs r0, 0 - str r0, [r5, 0x20] -_080AF6BC: - str r7, [r5, 0x24] - ldr r0, _080AF6D8 - str r0, [r5, 0x20] - ldr r0, _080AF6D4 - str r0, [r5] - str r0, [r7, 0x34] -_080AF6C8: - pop {r4-r7} - pop {r0} - bx r0 - .align 2, 0 -_080AF6D0: .4byte SOUND_INFO_PTR -_080AF6D4: .4byte 0x68736d53 -_080AF6D8: .4byte sub_80AE914 - thumb_func_end sub_80AF664 - - thumb_func_start sub_80AF6DC -sub_80AF6DC: - push {r4-r7,lr} - mov r7, r8 - push {r7} - adds r5, r0, 0 - adds r7, r1, 0 - ldr r1, [r5, 0x34] - ldr r0, _080AF7BC - cmp r1, r0 - bne _080AF7B2 - ldrb r0, [r5, 0xB] - ldrb r2, [r7, 0x2] - cmp r0, 0 - beq _080AF71E - ldr r0, [r5] - cmp r0, 0 - beq _080AF708 - ldr r1, [r5, 0x2C] - movs r0, 0x40 - ldrb r1, [r1] - ands r0, r1 - cmp r0, 0 - bne _080AF714 -_080AF708: - ldr r1, [r5, 0x4] - ldrh r0, [r5, 0x4] - cmp r0, 0 - beq _080AF71E - cmp r1, 0 - blt _080AF71E -_080AF714: - ldrb r0, [r7, 0x2] - adds r2, r0, 0 - ldrb r0, [r5, 0x9] - cmp r0, r2 - bhi _080AF7B2 -_080AF71E: - ldr r0, [r5, 0x34] - adds r0, 0x1 - str r0, [r5, 0x34] - movs r1, 0 - str r1, [r5, 0x4] - str r7, [r5] - ldr r0, [r7, 0x4] - str r0, [r5, 0x30] - strb r2, [r5, 0x9] - str r1, [r5, 0xC] - movs r0, 0x96 - strh r0, [r5, 0x1C] - strh r0, [r5, 0x20] - adds r0, 0x6A - strh r0, [r5, 0x1E] - strh r1, [r5, 0x22] - strh r1, [r5, 0x24] - movs r6, 0 - ldr r4, [r5, 0x2C] - ldrb r1, [r7] - cmp r6, r1 - bge _080AF77E - ldrb r0, [r5, 0x8] - cmp r6, r0 - bge _080AF79E - mov r8, r6 -_080AF752: - adds r0, r5, 0 - adds r1, r4, 0 - bl sub_80AEB7C - movs r0, 0xC0 - strb r0, [r4] - mov r1, r8 - str r1, [r4, 0x20] - lsls r1, r6, 2 - adds r0, r7, 0 - adds r0, 0x8 - adds r0, r1 - ldr r0, [r0] - str r0, [r4, 0x40] - adds r6, 0x1 - adds r4, 0x50 - ldrb r0, [r7] - cmp r6, r0 - bge _080AF77E - ldrb r1, [r5, 0x8] - cmp r6, r1 - blt _080AF752 -_080AF77E: - ldrb r0, [r5, 0x8] - cmp r6, r0 - bge _080AF79E - movs r1, 0 - mov r8, r1 -_080AF788: - adds r0, r5, 0 - adds r1, r4, 0 - bl sub_80AEB7C - mov r0, r8 - strb r0, [r4] - adds r6, 0x1 - adds r4, 0x50 - ldrb r1, [r5, 0x8] - cmp r6, r1 - blt _080AF788 -_080AF79E: - movs r0, 0x80 - ldrb r1, [r7, 0x3] - ands r0, r1 - cmp r0, 0 - beq _080AF7AE - ldrb r0, [r7, 0x3] - bl sub_80AF4C0 -_080AF7AE: - ldr r0, _080AF7BC - str r0, [r5, 0x34] -_080AF7B2: - pop {r3} - mov r8, r3 - pop {r4-r7} - pop {r0} - bx r0 - .align 2, 0 -_080AF7BC: .4byte 0x68736d53 - thumb_func_end sub_80AF6DC - - thumb_func_start sub_80AF7C0 -sub_80AF7C0: - push {r4-r6,lr} - adds r6, r0, 0 - ldr r1, [r6, 0x34] - ldr r0, _080AF7FC - cmp r1, r0 - bne _080AF7F6 - adds r0, r1, 0x1 - str r0, [r6, 0x34] - ldr r0, [r6, 0x4] - movs r1, 0x80 - lsls r1, 24 - orrs r0, r1 - str r0, [r6, 0x4] - ldrb r4, [r6, 0x8] - ldr r5, [r6, 0x2C] - cmp r4, 0 - ble _080AF7F2 -_080AF7E2: - adds r0, r6, 0 - adds r1, r5, 0 - bl sub_80AEB7C - subs r4, 0x1 - adds r5, 0x50 - cmp r4, 0 - bgt _080AF7E2 -_080AF7F2: - ldr r0, _080AF7FC - str r0, [r6, 0x34] -_080AF7F6: - pop {r4-r6} - pop {r0} - bx r0 - .align 2, 0 -_080AF7FC: .4byte 0x68736d53 - thumb_func_end sub_80AF7C0 - - thumb_func_start sub_80AF800 -sub_80AF800: - push {r4-r7,lr} - adds r6, r0, 0 - ldrh r1, [r6, 0x24] - cmp r1, 0 - beq _080AF8C2 - ldrh r0, [r6, 0x26] - subs r0, 0x1 - strh r0, [r6, 0x26] - ldr r3, _080AF840 - adds r2, r3, 0 - lsls r0, 16 - lsrs r3, r0, 16 - cmp r3, 0 - bne _080AF8C2 - strh r1, [r6, 0x26] - ldrh r1, [r6, 0x28] - movs r0, 0x2 - ands r0, r1 - cmp r0, 0 - beq _080AF844 - adds r0, r1, 0 - adds r0, 0x10 - strh r0, [r6, 0x28] - ands r0, r2 - cmp r0, 0xFF - bls _080AF896 - movs r0, 0x80 - lsls r0, 1 - strh r0, [r6, 0x28] - strh r3, [r6, 0x24] - b _080AF896 - .align 2, 0 -_080AF840: .4byte 0x0000ffff -_080AF844: - adds r0, r1, 0 - subs r0, 0x10 - strh r0, [r6, 0x28] - ands r0, r2 - lsls r0, 16 - cmp r0, 0 - bgt _080AF896 - ldrb r5, [r6, 0x8] - ldr r4, [r6, 0x2C] - cmp r5, 0 - ble _080AF876 -_080AF85A: - adds r0, r6, 0 - adds r1, r4, 0 - bl sub_80AEB7C - movs r0, 0x1 - ldrh r7, [r6, 0x28] - ands r0, r7 - cmp r0, 0 - bne _080AF86E - strb r0, [r4] -_080AF86E: - subs r5, 0x1 - adds r4, 0x50 - cmp r5, 0 - bgt _080AF85A -_080AF876: - movs r0, 0x1 - ldrh r1, [r6, 0x28] - ands r0, r1 - cmp r0, 0 - beq _080AF88A - ldr r0, [r6, 0x4] - movs r1, 0x80 - lsls r1, 24 - orrs r0, r1 - b _080AF88E -_080AF88A: - movs r0, 0x80 - lsls r0, 24 -_080AF88E: - str r0, [r6, 0x4] - movs r0, 0 - strh r0, [r6, 0x24] - b _080AF8C2 -_080AF896: - ldrb r5, [r6, 0x8] - ldr r4, [r6, 0x2C] - cmp r5, 0 - ble _080AF8C2 - movs r3, 0x80 - movs r7, 0 - movs r2, 0x3 -_080AF8A4: - ldrb r1, [r4] - adds r0, r3, 0 - ands r0, r1 - cmp r0, 0 - beq _080AF8BA - ldrh r7, [r6, 0x28] - lsrs r0, r7, 2 - strb r0, [r4, 0x13] - adds r0, r1, 0 - orrs r0, r2 - strb r0, [r4] -_080AF8BA: - subs r5, 0x1 - adds r4, 0x50 - cmp r5, 0 - bgt _080AF8A4 -_080AF8C2: - pop {r4-r7} - pop {r0} - bx r0 - thumb_func_end sub_80AF800 - - thumb_func_start sub_80AF8C8 -sub_80AF8C8: - push {r4,lr} - adds r2, r1, 0 - movs r0, 0x1 - ldrb r1, [r2] - ands r0, r1 - cmp r0, 0 - beq _080AF92C - ldrb r3, [r2, 0x13] - ldrb r1, [r2, 0x12] - adds r0, r3, 0 - muls r0, r1 - lsrs r3, r0, 5 - ldrb r4, [r2, 0x18] - cmp r4, 0x1 - bne _080AF8F0 - movs r0, 0x16 - ldrsb r0, [r2, r0] - adds r0, 0x80 - muls r0, r3 - lsrs r3, r0, 7 -_080AF8F0: - movs r0, 0x14 - ldrsb r0, [r2, r0] - lsls r0, 1 - movs r1, 0x15 - ldrsb r1, [r2, r1] - adds r1, r0, r1 - cmp r4, 0x2 - bne _080AF906 - movs r0, 0x16 - ldrsb r0, [r2, r0] - adds r1, r0 -_080AF906: - movs r0, 0x80 - negs r0, r0 - cmp r1, r0 - bge _080AF912 - adds r1, r0, 0 - b _080AF918 -_080AF912: - cmp r1, 0x7F - ble _080AF918 - movs r1, 0x7F -_080AF918: - adds r0, r1, 0 - adds r0, 0x80 - muls r0, r3 - lsrs r0, 8 - strb r0, [r2, 0x10] - movs r0, 0x7F - subs r0, r1 - muls r0, r3 - lsrs r0, 8 - strb r0, [r2, 0x11] -_080AF92C: - ldrb r1, [r2] - movs r0, 0x4 - ands r0, r1 - adds r3, r1, 0 - cmp r0, 0 - beq _080AF970 - movs r0, 0xE - ldrsb r0, [r2, r0] - ldrb r1, [r2, 0xF] - muls r0, r1 - movs r1, 0xC - ldrsb r1, [r2, r1] - adds r1, r0 - lsls r1, 2 - movs r0, 0xA - ldrsb r0, [r2, r0] - lsls r0, 8 - adds r1, r0 - movs r0, 0xB - ldrsb r0, [r2, r0] - lsls r0, 8 - adds r1, r0 - ldrb r0, [r2, 0xD] - adds r1, r0, r1 - ldrb r0, [r2, 0x18] - cmp r0, 0 - bne _080AF96A - movs r0, 0x16 - ldrsb r0, [r2, r0] - lsls r0, 4 - adds r1, r0 -_080AF96A: - asrs r0, r1, 8 - strb r0, [r2, 0x8] - strb r1, [r2, 0x9] -_080AF970: - movs r0, 0xFA - ands r0, r3 - strb r0, [r2] - pop {r4} - pop {r0} - bx r0 - thumb_func_end sub_80AF8C8 - - thumb_func_start sub_80AF97C -sub_80AF97C: - push {r4-r7,lr} - lsls r0, 24 - lsrs r0, 24 - lsls r1, 24 - lsrs r5, r1, 24 - lsls r2, 24 - lsrs r2, 24 - mov r12, r2 - cmp r0, 0x4 - bne _080AF9B4 - cmp r5, 0x14 - bhi _080AF998 - movs r5, 0 - b _080AF9A6 -_080AF998: - adds r0, r5, 0 - subs r0, 0x15 - lsls r0, 24 - lsrs r5, r0, 24 - cmp r5, 0x3B - bls _080AF9A6 - movs r5, 0x3B -_080AF9A6: - ldr r0, _080AF9B0 - adds r0, r5, r0 - ldrb r0, [r0] - b _080AFA16 - .align 2, 0 -_080AF9B0: .4byte gUnknown_826FBB4 -_080AF9B4: - cmp r5, 0x23 - bhi _080AF9C0 - movs r0, 0 - mov r12, r0 - movs r5, 0 - b _080AF9D2 -_080AF9C0: - adds r0, r5, 0 - subs r0, 0x24 - lsls r0, 24 - lsrs r5, r0, 24 - cmp r5, 0x82 - bls _080AF9D2 - movs r5, 0x82 - movs r1, 0xFF - mov r12, r1 -_080AF9D2: - ldr r3, _080AFA1C - adds r0, r5, r3 - ldrb r6, [r0] - ldr r4, _080AFA20 - movs r2, 0xF - adds r0, r6, 0 - ands r0, r2 - lsls r0, 1 - adds r0, r4 - movs r7, 0 - ldrsh r1, [r0, r7] - asrs r0, r6, 4 - adds r6, r1, 0 - asrs r6, r0 - adds r0, r5, 0x1 - adds r0, r3 - ldrb r1, [r0] - adds r0, r1, 0 - ands r0, r2 - lsls r0, 1 - adds r0, r4 - movs r2, 0 - ldrsh r0, [r0, r2] - asrs r1, 4 - asrs r0, r1 - subs r0, r6 - mov r7, r12 - muls r7, r0 - adds r0, r7, 0 - asrs r0, 8 - adds r0, r6, r0 - movs r1, 0x80 - lsls r1, 4 - adds r0, r1 -_080AFA16: - pop {r4-r7} - pop {r1} - bx r1 - .align 2, 0 -_080AFA1C: .4byte gUnknown_826FB18 -_080AFA20: .4byte gUnknown_826FB9C - thumb_func_end sub_80AF97C - - thumb_func_start sub_80AFA24 -sub_80AFA24: - lsls r0, 24 - lsrs r0, 24 - adds r1, r0, 0 - cmp r0, 0x2 - beq _080AFA4C - cmp r0, 0x2 - bgt _080AFA38 - cmp r0, 0x1 - beq _080AFA3E - b _080AFA60 -_080AFA38: - cmp r1, 0x3 - beq _080AFA54 - b _080AFA60 -_080AFA3E: - ldr r1, _080AFA48 - movs r0, 0x8 - strb r0, [r1] - adds r1, 0x2 - b _080AFA68 - .align 2, 0 -_080AFA48: .4byte 0x04000063 -_080AFA4C: - ldr r1, _080AFA50 - b _080AFA62 - .align 2, 0 -_080AFA50: .4byte 0x04000069 -_080AFA54: - ldr r1, _080AFA5C - movs r0, 0 - b _080AFA6A - .align 2, 0 -_080AFA5C: .4byte 0x04000070 -_080AFA60: - ldr r1, _080AFA70 -_080AFA62: - movs r0, 0x8 - strb r0, [r1] - adds r1, 0x4 -_080AFA68: - movs r0, 0x80 -_080AFA6A: - strb r0, [r1] - bx lr - .align 2, 0 -_080AFA70: .4byte 0x04000079 - thumb_func_end sub_80AFA24 - - thumb_func_start sub_80AFA74 -sub_80AFA74: - push {r4,lr} - adds r1, r0, 0 - ldrb r0, [r1, 0x2] - lsls r2, r0, 24 - lsrs r4, r2, 24 - ldrb r3, [r1, 0x3] - lsls r0, r3, 24 - lsrs r3, r0, 24 - cmp r4, r3 - bcc _080AFA94 - lsrs r0, r2, 25 - cmp r0, r3 - bcc _080AFAA0 - movs r0, 0xF - strb r0, [r1, 0x1B] - b _080AFAAE -_080AFA94: - lsrs r0, 25 - cmp r0, r4 - bcc _080AFAA0 - movs r0, 0xF0 - strb r0, [r1, 0x1B] - b _080AFAAE -_080AFAA0: - movs r0, 0xFF - strb r0, [r1, 0x1B] - ldrb r2, [r1, 0x3] - ldrb r3, [r1, 0x2] - adds r0, r2, r3 - lsrs r0, 4 - b _080AFABE -_080AFAAE: - ldrb r2, [r1, 0x3] - ldrb r3, [r1, 0x2] - adds r0, r2, r3 - lsrs r0, 4 - strb r0, [r1, 0xA] - cmp r0, 0xF - bls _080AFAC0 - movs r0, 0xF -_080AFABE: - strb r0, [r1, 0xA] -_080AFAC0: - ldrb r2, [r1, 0x6] - ldrb r3, [r1, 0xA] - adds r0, r2, 0 - muls r0, r3 - adds r0, 0xF - asrs r0, 4 - strb r0, [r1, 0x19] - ldrb r0, [r1, 0x1C] - ldrb r2, [r1, 0x1B] - ands r0, r2 - strb r0, [r1, 0x1B] - pop {r4} - pop {r0} - bx r0 - thumb_func_end sub_80AFA74 - - thumb_func_start sub_80AFADC -sub_80AFADC: - push {r4-r7,lr} - mov r7, r10 - mov r6, r9 - mov r5, r8 - push {r5-r7} - sub sp, 0x1C - ldr r0, _080AFAFC - ldr r0, [r0] - str r0, [sp, 0x4] - ldrb r0, [r0, 0xA] - cmp r0, 0 - beq _080AFB00 - subs r0, 0x1 - ldr r1, [sp, 0x4] - strb r0, [r1, 0xA] - b _080AFB06 - .align 2, 0 -_080AFAFC: .4byte SOUND_INFO_PTR -_080AFB00: - movs r0, 0xE - ldr r2, [sp, 0x4] - strb r0, [r2, 0xA] -_080AFB06: - movs r6, 0x1 - ldr r0, [sp, 0x4] - ldr r4, [r0, 0x1C] -_080AFB0C: - ldrb r1, [r4] - movs r0, 0xC7 - ands r0, r1 - adds r2, r6, 0x1 - mov r10, r2 - movs r2, 0x40 - adds r2, r4 - mov r9, r2 - cmp r0, 0 - bne _080AFB22 - b _080AFF0C -_080AFB22: - cmp r6, 0x2 - beq _080AFB54 - cmp r6, 0x2 - bgt _080AFB30 - cmp r6, 0x1 - beq _080AFB36 - b _080AFB8C -_080AFB30: - cmp r6, 0x3 - beq _080AFB6C - b _080AFB8C -_080AFB36: - ldr r0, _080AFB48 - str r0, [sp, 0x8] - ldr r7, _080AFB4C - ldr r2, _080AFB50 - str r2, [sp, 0xC] - adds r0, 0x4 - str r0, [sp, 0x10] - adds r2, 0x2 - b _080AFB9C - .align 2, 0 -_080AFB48: .4byte 0x04000060 -_080AFB4C: .4byte 0x04000062 -_080AFB50: .4byte 0x04000063 -_080AFB54: - ldr r0, _080AFB60 - str r0, [sp, 0x8] - ldr r7, _080AFB64 - ldr r2, _080AFB68 - b _080AFB94 - .align 2, 0 -_080AFB60: .4byte 0x04000061 -_080AFB64: .4byte 0x04000068 -_080AFB68: .4byte 0x04000069 -_080AFB6C: - ldr r0, _080AFB80 - str r0, [sp, 0x8] - ldr r7, _080AFB84 - ldr r2, _080AFB88 - str r2, [sp, 0xC] - adds r0, 0x4 - str r0, [sp, 0x10] - adds r2, 0x2 - b _080AFB9C - .align 2, 0 -_080AFB80: .4byte 0x04000070 -_080AFB84: .4byte 0x04000072 -_080AFB88: .4byte 0x04000073 -_080AFB8C: - ldr r0, _080AFBEC - str r0, [sp, 0x8] - ldr r7, _080AFBF0 - ldr r2, _080AFBF4 -_080AFB94: - str r2, [sp, 0xC] - adds r0, 0xB - str r0, [sp, 0x10] - adds r2, 0x4 -_080AFB9C: - str r2, [sp, 0x14] - ldr r0, [sp, 0x4] - ldrb r0, [r0, 0xA] - str r0, [sp] - ldr r2, [sp, 0xC] - ldrb r0, [r2] - mov r8, r0 - adds r2, r1, 0 - movs r0, 0x80 - ands r0, r2 - cmp r0, 0 - beq _080AFC92 - movs r3, 0x40 - adds r0, r3, 0 - ands r0, r2 - lsls r0, 24 - lsrs r5, r0, 24 - adds r0, r6, 0x1 - mov r10, r0 - movs r1, 0x40 - adds r1, r4 - mov r9, r1 - cmp r5, 0 - bne _080AFCB6 - movs r0, 0x3 - strb r0, [r4] - strb r0, [r4, 0x1D] - adds r0, r4, 0 - str r3, [sp, 0x18] - bl sub_80AFA74 - ldr r3, [sp, 0x18] - cmp r6, 0x2 - beq _080AFC04 - cmp r6, 0x2 - bgt _080AFBF8 - cmp r6, 0x1 - beq _080AFBFE - b _080AFC58 - .align 2, 0 -_080AFBEC: .4byte 0x04000071 -_080AFBF0: .4byte 0x04000078 -_080AFBF4: .4byte 0x04000079 -_080AFBF8: - cmp r6, 0x3 - beq _080AFC10 - b _080AFC58 -_080AFBFE: - ldrb r0, [r4, 0x1F] - ldr r2, [sp, 0x8] - strb r0, [r2] -_080AFC04: - ldr r0, [r4, 0x24] - lsls r0, 6 - ldrb r1, [r4, 0x1E] - adds r0, r1, r0 - strb r0, [r7] - b _080AFC64 -_080AFC10: - ldr r1, [r4, 0x24] - ldr r0, [r4, 0x28] - cmp r1, r0 - beq _080AFC38 - ldr r2, [sp, 0x8] - strb r3, [r2] - ldr r1, _080AFC4C - ldr r2, [r4, 0x24] - ldr r0, [r2] - str r0, [r1] - adds r1, 0x4 - ldr r0, [r2, 0x4] - str r0, [r1] - adds r1, 0x4 - ldr r0, [r2, 0x8] - str r0, [r1] - adds r1, 0x4 - ldr r0, [r2, 0xC] - str r0, [r1] - str r2, [r4, 0x28] -_080AFC38: - ldr r0, [sp, 0x8] - strb r5, [r0] - ldrb r0, [r4, 0x1E] - strb r0, [r7] - ldrb r0, [r4, 0x1E] - cmp r0, 0 - beq _080AFC50 - movs r0, 0xC0 - b _080AFC72 - .align 2, 0 -_080AFC4C: .4byte 0x04000090 -_080AFC50: - movs r1, 0x80 - negs r1, r1 - strb r1, [r4, 0x1A] - b _080AFC74 -_080AFC58: - ldrb r0, [r4, 0x1E] - strb r0, [r7] - ldr r0, [r4, 0x24] - lsls r0, 3 - ldr r2, [sp, 0x10] - strb r0, [r2] -_080AFC64: - ldrb r0, [r4, 0x4] - adds r0, 0x8 - mov r8, r0 - ldrb r0, [r4, 0x1E] - cmp r0, 0 - beq _080AFC72 - movs r0, 0x40 -_080AFC72: - strb r0, [r4, 0x1A] -_080AFC74: - ldrb r1, [r4, 0x4] - movs r2, 0 - strb r1, [r4, 0xB] - movs r0, 0xFF - ands r0, r1 - adds r1, r6, 0x1 - mov r10, r1 - movs r1, 0x40 - adds r1, r4 - mov r9, r1 - cmp r0, 0 - bne _080AFC8E - b _080AFDCA -_080AFC8E: - strb r2, [r4, 0x9] - b _080AFDF8 -_080AFC92: - movs r0, 0x4 - ands r0, r2 - cmp r0, 0 - beq _080AFCC4 - ldrb r0, [r4, 0xD] - subs r0, 0x1 - strb r0, [r4, 0xD] - movs r2, 0xFF - ands r0, r2 - lsls r0, 24 - adds r1, r6, 0x1 - mov r10, r1 - movs r2, 0x40 - adds r2, r4 - mov r9, r2 - cmp r0, 0 - ble _080AFCB6 - b _080AFE0A -_080AFCB6: - lsls r0, r6, 24 - lsrs r0, 24 - bl sub_80AFA24 - movs r0, 0 - strb r0, [r4] - b _080AFF08 -_080AFCC4: - movs r0, 0x40 - ands r0, r1 - adds r2, r6, 0x1 - mov r10, r2 - movs r2, 0x40 - adds r2, r4 - mov r9, r2 - cmp r0, 0 - beq _080AFD04 - movs r0, 0x3 - ands r0, r1 - cmp r0, 0 - beq _080AFD04 - movs r0, 0xFC - ands r0, r1 - movs r2, 0 - strb r0, [r4] - ldrb r1, [r4, 0x7] - strb r1, [r4, 0xB] - movs r0, 0xFF - ands r0, r1 - cmp r0, 0 - beq _080AFD36 - movs r0, 0x1 - ldrb r1, [r4, 0x1D] - orrs r0, r1 - strb r0, [r4, 0x1D] - cmp r6, 0x3 - beq _080AFDF8 - ldrb r2, [r4, 0x7] - mov r8, r2 - b _080AFDF8 -_080AFD04: - ldrb r0, [r4, 0xB] - cmp r0, 0 - bne _080AFDF8 - cmp r6, 0x3 - bne _080AFD16 - movs r0, 0x1 - ldrb r1, [r4, 0x1D] - orrs r0, r1 - strb r0, [r4, 0x1D] -_080AFD16: - adds r0, r4, 0 - bl sub_80AFA74 - movs r0, 0x3 - ldrb r2, [r4] - ands r0, r2 - cmp r0, 0 - bne _080AFD6A - ldrb r0, [r4, 0x9] - subs r0, 0x1 - strb r0, [r4, 0x9] - movs r1, 0xFF - ands r0, r1 - lsls r0, 24 - cmp r0, 0 - bgt _080AFD66 -_080AFD36: - ldrb r2, [r4, 0xC] - ldrb r1, [r4, 0xA] - adds r0, r2, 0 - muls r0, r1 - adds r0, 0xFF - asrs r0, 8 - movs r1, 0 - strb r0, [r4, 0x9] - lsls r0, 24 - cmp r0, 0 - beq _080AFCB6 - movs r0, 0x4 - ldrb r2, [r4] - orrs r0, r2 - strb r0, [r4] - movs r0, 0x1 - ldrb r1, [r4, 0x1D] - orrs r0, r1 - strb r0, [r4, 0x1D] - cmp r6, 0x3 - beq _080AFE0A - movs r2, 0x8 - mov r8, r2 - b _080AFE0A -_080AFD66: - ldrb r0, [r4, 0x7] - b _080AFDF6 -_080AFD6A: - cmp r0, 0x1 - bne _080AFD76 -_080AFD6E: - ldrb r0, [r4, 0x19] - strb r0, [r4, 0x9] - movs r0, 0x7 - b _080AFDF6 -_080AFD76: - cmp r0, 0x2 - bne _080AFDBA - ldrb r0, [r4, 0x9] - subs r0, 0x1 - strb r0, [r4, 0x9] - movs r1, 0xFF - ands r0, r1 - lsls r0, 24 - ldrb r2, [r4, 0x19] - lsls r1, r2, 24 - cmp r0, r1 - bgt _080AFDB6 -_080AFD8E: - ldrb r0, [r4, 0x6] - cmp r0, 0 - bne _080AFD9E - movs r0, 0xFC - ldrb r1, [r4] - ands r0, r1 - strb r0, [r4] - b _080AFD36 -_080AFD9E: - ldrb r0, [r4] - subs r0, 0x1 - strb r0, [r4] - movs r0, 0x1 - ldrb r2, [r4, 0x1D] - orrs r0, r2 - strb r0, [r4, 0x1D] - cmp r6, 0x3 - beq _080AFD6E - movs r0, 0x8 - mov r8, r0 - b _080AFD6E -_080AFDB6: - ldrb r0, [r4, 0x5] - b _080AFDF6 -_080AFDBA: - ldrb r0, [r4, 0x9] - adds r0, 0x1 - strb r0, [r4, 0x9] - movs r1, 0xFF - ands r0, r1 - ldrb r2, [r4, 0xA] - cmp r0, r2 - bcc _080AFDF4 -_080AFDCA: - ldrb r0, [r4] - subs r0, 0x1 - movs r2, 0 - strb r0, [r4] - ldrb r1, [r4, 0x5] - strb r1, [r4, 0xB] - movs r0, 0xFF - ands r0, r1 - cmp r0, 0 - beq _080AFD8E - movs r0, 0x1 - ldrb r1, [r4, 0x1D] - orrs r0, r1 - strb r0, [r4, 0x1D] - ldrb r0, [r4, 0xA] - strb r0, [r4, 0x9] - cmp r6, 0x3 - beq _080AFDF8 - ldrb r2, [r4, 0x5] - mov r8, r2 - b _080AFDF8 -_080AFDF4: - ldrb r0, [r4, 0x4] -_080AFDF6: - strb r0, [r4, 0xB] -_080AFDF8: - ldrb r0, [r4, 0xB] - subs r0, 0x1 - strb r0, [r4, 0xB] - ldr r0, [sp] - cmp r0, 0 - bne _080AFE0A - subs r0, 0x1 - str r0, [sp] - b _080AFD04 -_080AFE0A: - movs r0, 0x2 - ldrb r1, [r4, 0x1D] - ands r0, r1 - cmp r0, 0 - beq _080AFE82 - cmp r6, 0x3 - bgt _080AFE4A - movs r0, 0x8 - ldrb r2, [r4, 0x1] - ands r0, r2 - cmp r0, 0 - beq _080AFE4A - ldr r0, _080AFE34 - ldrb r0, [r0] - cmp r0, 0x3F - bgt _080AFE3C - ldr r0, [r4, 0x20] - adds r0, 0x2 - ldr r1, _080AFE38 - b _080AFE46 - .align 2, 0 -_080AFE34: .4byte 0x04000089 -_080AFE38: .4byte 0x000007fc -_080AFE3C: - cmp r0, 0x7F - bgt _080AFE4A - ldr r0, [r4, 0x20] - adds r0, 0x1 - ldr r1, _080AFE58 -_080AFE46: - ands r0, r1 - str r0, [r4, 0x20] -_080AFE4A: - cmp r6, 0x4 - beq _080AFE5C - ldr r0, [r4, 0x20] - ldr r1, [sp, 0x10] - strb r0, [r1] - b _080AFE6A - .align 2, 0 -_080AFE58: .4byte 0x000007fe -_080AFE5C: - ldr r2, [sp, 0x10] - ldrb r0, [r2] - movs r1, 0x8 - ands r1, r0 - ldr r0, [r4, 0x20] - orrs r0, r1 - strb r0, [r2] -_080AFE6A: - movs r0, 0xC0 - ldrb r1, [r4, 0x1A] - ands r0, r1 - adds r1, r4, 0 - adds r1, 0x21 - ldrb r1, [r1] - adds r0, r1, r0 - strb r0, [r4, 0x1A] - movs r2, 0xFF - ands r0, r2 - ldr r1, [sp, 0x14] - strb r0, [r1] -_080AFE82: - movs r0, 0x1 - ldrb r2, [r4, 0x1D] - ands r0, r2 - cmp r0, 0 - beq _080AFF08 - ldr r1, _080AFECC - ldrb r0, [r1] - ldrb r2, [r4, 0x1C] - bics r0, r2 - ldrb r2, [r4, 0x1B] - orrs r0, r2 - strb r0, [r1] - cmp r6, 0x3 - bne _080AFED4 - ldr r0, _080AFED0 - ldrb r1, [r4, 0x9] - adds r0, r1, r0 - ldrb r0, [r0] - ldr r2, [sp, 0xC] - strb r0, [r2] - movs r1, 0x80 - adds r0, r1, 0 - ldrb r2, [r4, 0x1A] - ands r0, r2 - cmp r0, 0 - beq _080AFF08 - ldr r0, [sp, 0x8] - strb r1, [r0] - ldrb r0, [r4, 0x1A] - ldr r1, [sp, 0x14] - strb r0, [r1] - movs r0, 0x7F - ldrb r2, [r4, 0x1A] - ands r0, r2 - strb r0, [r4, 0x1A] - b _080AFF08 - .align 2, 0 -_080AFECC: .4byte 0x04000081 -_080AFED0: .4byte gUnknown_826FBF0 -_080AFED4: - movs r0, 0xF - mov r1, r8 - ands r1, r0 - mov r8, r1 - ldrb r2, [r4, 0x9] - lsls r0, r2, 4 - add r0, r8 - ldr r1, [sp, 0xC] - strb r0, [r1] - movs r2, 0x80 - ldrb r0, [r4, 0x1A] - orrs r0, r2 - ldr r1, [sp, 0x14] - strb r0, [r1] - cmp r6, 0x1 - bne _080AFF08 - ldr r0, [sp, 0x8] - ldrb r1, [r0] - movs r0, 0x8 - ands r0, r1 - cmp r0, 0 - bne _080AFF08 - ldrb r0, [r4, 0x1A] - orrs r0, r2 - ldr r1, [sp, 0x14] - strb r0, [r1] -_080AFF08: - movs r0, 0 - strb r0, [r4, 0x1D] -_080AFF0C: - mov r6, r10 - mov r4, r9 - cmp r6, 0x4 - bgt _080AFF16 - b _080AFB0C -_080AFF16: - add sp, 0x1C - pop {r3-r5} - mov r8, r3 - mov r9, r4 - mov r10, r5 - pop {r4-r7} - pop {r0} - bx r0 - thumb_func_end sub_80AFADC - - thumb_func_start sub_80AFF28 -sub_80AFF28: - push {r4,lr} - adds r2, r0, 0 - lsls r1, 16 - lsrs r1, 16 - ldr r3, [r2, 0x34] - ldr r0, _080AFF4C - cmp r3, r0 - bne _080AFF44 - strh r1, [r2, 0x1E] - ldrh r4, [r2, 0x1C] - adds r0, r1, 0 - muls r0, r4 - asrs r0, 8 - strh r0, [r2, 0x20] -_080AFF44: - pop {r4} - pop {r0} - bx r0 - .align 2, 0 -_080AFF4C: .4byte 0x68736d53 - thumb_func_end sub_80AFF28 - - thumb_func_start sub_80AFF50 -sub_80AFF50: - push {r4-r7,lr} - mov r7, r9 - mov r6, r8 - push {r6,r7} - adds r4, r0, 0 - lsls r1, 16 - lsrs r7, r1, 16 - lsls r6, r2, 16 - ldr r3, [r4, 0x34] - ldr r0, _080AFFB4 - cmp r3, r0 - bne _080AFFA8 - adds r0, r3, 0x1 - str r0, [r4, 0x34] - ldrb r2, [r4, 0x8] - ldr r1, [r4, 0x2C] - movs r5, 0x1 - cmp r2, 0 - ble _080AFFA4 - movs r0, 0x80 - mov r8, r0 - lsrs r6, 18 - movs r0, 0x3 - mov r12, r0 -_080AFF80: - adds r0, r7, 0 - ands r0, r5 - cmp r0, 0 - beq _080AFF9A - ldrb r3, [r1] - mov r0, r8 - ands r0, r3 - cmp r0, 0 - beq _080AFF9A - strb r6, [r1, 0x13] - mov r0, r12 - orrs r0, r3 - strb r0, [r1] -_080AFF9A: - subs r2, 0x1 - adds r1, 0x50 - lsls r5, 1 - cmp r2, 0 - bgt _080AFF80 -_080AFFA4: - ldr r0, _080AFFB4 - str r0, [r4, 0x34] -_080AFFA8: - pop {r3,r4} - mov r8, r3 - mov r9, r4 - pop {r4-r7} - pop {r0} - bx r0 - .align 2, 0 -_080AFFB4: .4byte 0x68736d53 - thumb_func_end sub_80AFF50 - - thumb_func_start sub_80AFFB8 -sub_80AFFB8: - push {r4-r7,lr} - mov r7, r10 - mov r6, r9 - mov r5, r8 - push {r5-r7} - adds r4, r0, 0 - lsls r1, 16 - lsrs r1, 16 - mov r12, r1 - lsls r2, 16 - lsrs r6, r2, 16 - ldr r3, [r4, 0x34] - ldr r0, _080B0028 - cmp r3, r0 - bne _080B001A - adds r0, r3, 0x1 - str r0, [r4, 0x34] - ldrb r2, [r4, 0x8] - ldr r3, [r4, 0x2C] - movs r5, 0x1 - cmp r2, 0 - ble _080B0016 - movs r0, 0x80 - mov r9, r0 - lsls r0, r6, 16 - asrs r7, r0, 24 - movs r0, 0xC - mov r8, r0 -_080AFFF0: - mov r0, r12 - ands r0, r5 - cmp r0, 0 - beq _080B000C - ldrb r1, [r3] - mov r0, r9 - ands r0, r1 - cmp r0, 0 - beq _080B000C - strb r7, [r3, 0xB] - strb r6, [r3, 0xD] - mov r0, r8 - orrs r0, r1 - strb r0, [r3] -_080B000C: - subs r2, 0x1 - adds r3, 0x50 - lsls r5, 1 - cmp r2, 0 - bgt _080AFFF0 -_080B0016: - ldr r0, _080B0028 - str r0, [r4, 0x34] -_080B001A: - pop {r3-r5} - mov r8, r3 - mov r9, r4 - mov r10, r5 - pop {r4-r7} - pop {r0} - bx r0 - .align 2, 0 -_080B0028: .4byte 0x68736d53 - thumb_func_end sub_80AFFB8 - - thumb_func_start sub_80B002C -sub_80B002C: - push {r4-r7,lr} - mov r7, r9 - mov r6, r8 - push {r6,r7} - adds r4, r0, 0 - lsls r1, 16 - lsrs r7, r1, 16 - lsls r2, 24 - lsrs r6, r2, 24 - ldr r3, [r4, 0x34] - ldr r0, _080B0090 - cmp r3, r0 - bne _080B0084 - adds r0, r3, 0x1 - str r0, [r4, 0x34] - ldrb r2, [r4, 0x8] - ldr r1, [r4, 0x2C] - movs r5, 0x1 - cmp r2, 0 - ble _080B0080 - movs r0, 0x80 - mov r8, r0 - movs r0, 0x3 - mov r12, r0 -_080B005C: - adds r0, r7, 0 - ands r0, r5 - cmp r0, 0 - beq _080B0076 - ldrb r3, [r1] - mov r0, r8 - ands r0, r3 - cmp r0, 0 - beq _080B0076 - strb r6, [r1, 0x15] - mov r0, r12 - orrs r0, r3 - strb r0, [r1] -_080B0076: - subs r2, 0x1 - adds r1, 0x50 - lsls r5, 1 - cmp r2, 0 - bgt _080B005C -_080B0080: - ldr r0, _080B0090 - str r0, [r4, 0x34] -_080B0084: - pop {r3,r4} - mov r8, r3 - mov r9, r4 - pop {r4-r7} - pop {r0} - bx r0 - .align 2, 0 -_080B0090: .4byte 0x68736d53 - thumb_func_end sub_80B002C - - thumb_func_start sub_80B0094 -sub_80B0094: - adds r1, r0, 0 - movs r2, 0 - movs r0, 0 - strb r0, [r1, 0x1A] - strb r0, [r1, 0x16] - ldrb r0, [r1, 0x18] - cmp r0, 0 - bne _080B00A8 - movs r0, 0xC - b _080B00AA -_080B00A8: - movs r0, 0x3 -_080B00AA: - ldrb r2, [r1] - orrs r0, r2 - strb r0, [r1] - bx lr - thumb_func_end sub_80B0094 - - thumb_func_start sub_80B00B4 -sub_80B00B4: - push {r4-r7,lr} - mov r7, r10 - mov r6, r9 - mov r5, r8 - push {r5-r7} - adds r6, r0, 0 - lsls r1, 16 - lsrs r1, 16 - mov r10, r1 - lsls r2, 24 - lsrs r2, 24 - mov r8, r2 - ldr r1, [r6, 0x34] - ldr r0, _080B0124 - cmp r1, r0 - bne _080B0114 - adds r0, r1, 0x1 - str r0, [r6, 0x34] - ldrb r5, [r6, 0x8] - ldr r4, [r6, 0x2C] - movs r7, 0x1 - cmp r5, 0 - ble _080B0110 - mov r9, r8 -_080B00E4: - mov r0, r10 - ands r0, r7 - cmp r0, 0 - beq _080B0106 - movs r0, 0x80 - ldrb r1, [r4] - ands r0, r1 - cmp r0, 0 - beq _080B0106 - mov r0, r8 - strb r0, [r4, 0x17] - mov r1, r9 - cmp r1, 0 - bne _080B0106 - adds r0, r4, 0 - bl sub_80B0094 -_080B0106: - subs r5, 0x1 - adds r4, 0x50 - lsls r7, 1 - cmp r5, 0 - bgt _080B00E4 -_080B0110: - ldr r0, _080B0124 - str r0, [r6, 0x34] -_080B0114: - pop {r3-r5} - mov r8, r3 - mov r9, r4 - mov r10, r5 - pop {r4-r7} - pop {r0} - bx r0 - .align 2, 0 -_080B0124: .4byte 0x68736d53 - thumb_func_end sub_80B00B4 - - thumb_func_start sub_80B0128 -sub_80B0128: - push {r4-r7,lr} - mov r7, r10 - mov r6, r9 - mov r5, r8 - push {r5-r7} - adds r6, r0, 0 - lsls r1, 16 - lsrs r1, 16 - mov r10, r1 - lsls r2, 24 - lsrs r2, 24 - mov r8, r2 - ldr r1, [r6, 0x34] - ldr r0, _080B0198 - cmp r1, r0 - bne _080B0188 - adds r0, r1, 0x1 - str r0, [r6, 0x34] - ldrb r5, [r6, 0x8] - ldr r4, [r6, 0x2C] - movs r7, 0x1 - cmp r5, 0 - ble _080B0184 - mov r9, r8 -_080B0158: - mov r0, r10 - ands r0, r7 - cmp r0, 0 - beq _080B017A - movs r0, 0x80 - ldrb r1, [r4] - ands r0, r1 - cmp r0, 0 - beq _080B017A - mov r0, r8 - strb r0, [r4, 0x19] - mov r1, r9 - cmp r1, 0 - bne _080B017A - adds r0, r4, 0 - bl sub_80B0094 -_080B017A: - subs r5, 0x1 - adds r4, 0x50 - lsls r7, 1 - cmp r5, 0 - bgt _080B0158 -_080B0184: - ldr r0, _080B0198 - str r0, [r6, 0x34] -_080B0188: - pop {r3-r5} - mov r8, r3 - mov r9, r4 - mov r10, r5 - pop {r4-r7} - pop {r0} - bx r0 - .align 2, 0 -_080B0198: .4byte 0x68736d53 - thumb_func_end sub_80B0128 - - thumb_func_start sub_80B019C -sub_80B019C: - push {r4-r6,lr} - adds r4, r0, 0 - adds r6, r1, 0 - ldr r1, [r6, 0x40] - ldrb r5, [r1] - adds r2, r1, 0x1 - str r2, [r6, 0x40] - ldr r0, [r4, 0x18] - ldrb r1, [r1, 0x1] - adds r3, r1, r0 - adds r0, r2, 0x1 - str r0, [r6, 0x40] - ldrb r2, [r2, 0x1] - adds r0, 0x1 - str r0, [r6, 0x40] - cmp r5, 0x11 - bls _080B01C0 - b _080B02EE -_080B01C0: - lsls r0, r5, 2 - ldr r1, _080B01CC - adds r0, r1 - ldr r0, [r0] - mov pc, r0 - .align 2, 0 -_080B01CC: .4byte _080B01D0 - .align 2, 0 -_080B01D0: - .4byte _080B0218 - .4byte _080B021C - .4byte _080B0224 - .4byte _080B022C - .4byte _080B0236 - .4byte _080B0244 - .4byte _080B0252 - .4byte _080B025A - .4byte _080B0262 - .4byte _080B026A - .4byte _080B0272 - .4byte _080B027A - .4byte _080B0282 - .4byte _080B0290 - .4byte _080B029E - .4byte _080B02AC - .4byte _080B02BA - .4byte _080B02C8 -_080B0218: - strb r2, [r3] - b _080B02EE -_080B021C: - ldrb r1, [r3] - adds r0, r1, r2 - strb r0, [r3] - b _080B02EE -_080B0224: - ldrb r1, [r3] - subs r0, r1, r2 - strb r0, [r3] - b _080B02EE -_080B022C: - ldr r0, [r4, 0x18] - adds r0, r2 - ldrb r0, [r0] - strb r0, [r3] - b _080B02EE -_080B0236: - ldr r0, [r4, 0x18] - adds r0, r2 - ldrb r1, [r3] - ldrb r0, [r0] - adds r0, r1, r0 - strb r0, [r3] - b _080B02EE -_080B0244: - ldr r0, [r4, 0x18] - adds r0, r2 - ldrb r1, [r3] - ldrb r0, [r0] - subs r0, r1, r0 - strb r0, [r3] - b _080B02EE -_080B0252: - ldrb r3, [r3] - cmp r3, r2 - beq _080B02D4 - b _080B02E8 -_080B025A: - ldrb r3, [r3] - cmp r3, r2 - bne _080B02D4 - b _080B02E8 -_080B0262: - ldrb r3, [r3] - cmp r3, r2 - bhi _080B02D4 - b _080B02E8 -_080B026A: - ldrb r3, [r3] - cmp r3, r2 - bcs _080B02D4 - b _080B02E8 -_080B0272: - ldrb r3, [r3] - cmp r3, r2 - bls _080B02D4 - b _080B02E8 -_080B027A: - ldrb r3, [r3] - cmp r3, r2 - bcc _080B02D4 - b _080B02E8 -_080B0282: - ldr r0, [r4, 0x18] - adds r0, r2 - ldrb r3, [r3] - ldrb r0, [r0] - cmp r3, r0 - beq _080B02D4 - b _080B02E8 -_080B0290: - ldr r0, [r4, 0x18] - adds r0, r2 - ldrb r3, [r3] - ldrb r0, [r0] - cmp r3, r0 - bne _080B02D4 - b _080B02E8 -_080B029E: - ldr r0, [r4, 0x18] - adds r0, r2 - ldrb r3, [r3] - ldrb r0, [r0] - cmp r3, r0 - bhi _080B02D4 - b _080B02E8 -_080B02AC: - ldr r0, [r4, 0x18] - adds r0, r2 - ldrb r3, [r3] - ldrb r0, [r0] - cmp r3, r0 - bcs _080B02D4 - b _080B02E8 -_080B02BA: - ldr r0, [r4, 0x18] - adds r0, r2 - ldrb r3, [r3] - ldrb r0, [r0] - cmp r3, r0 - bls _080B02D4 - b _080B02E8 -_080B02C8: - ldr r0, [r4, 0x18] - adds r0, r2 - ldrb r3, [r3] - ldrb r0, [r0] - cmp r3, r0 - bcs _080B02E8 -_080B02D4: - ldr r0, _080B02E4 - ldr r2, [r0] - adds r0, r4, 0 - adds r1, r6, 0 - bl _call_via_r2 - b _080B02EE - .align 2, 0 -_080B02E4: .4byte gUnknown_203AE84 -_080B02E8: - ldr r0, [r6, 0x40] - adds r0, 0x4 - str r0, [r6, 0x40] -_080B02EE: - pop {r4-r6} - pop {r0} - bx r0 - thumb_func_end sub_80B019C - - thumb_func_start sub_80B02F4 -sub_80B02F4: - push {lr} - ldr r2, [r1, 0x40] - ldrb r3, [r2] - adds r2, 0x1 - str r2, [r1, 0x40] - ldr r2, _080B0310 - lsls r3, 2 - adds r3, r2 - ldr r2, [r3] - bl _call_via_r2 - pop {r0} - bx r0 - .align 2, 0 -_080B0310: .4byte gUnknown_826FC34 - thumb_func_end sub_80B02F4 - - thumb_func_start sub_80B0314 -sub_80B0314: - push {lr} - ldr r2, _080B0324 - ldr r2, [r2] - bl _call_via_r2 - pop {r0} - bx r0 - .align 2, 0 -_080B0324: .4byte gUnknown_203AE80 - thumb_func_end sub_80B0314 - - thumb_func_start sub_80B0328 -sub_80B0328: - push {r4,lr} - ldr r2, [r1, 0x40] - ldr r0, _080B0360 - ands r4, r0 - ldrb r0, [r2] - orrs r4, r0 - ldrb r0, [r2, 0x1] - lsls r3, r0, 8 - ldr r0, _080B0364 - ands r4, r0 - orrs r4, r3 - ldrb r0, [r2, 0x2] - lsls r3, r0, 16 - ldr r0, _080B0368 - ands r4, r0 - orrs r4, r3 - ldrb r0, [r2, 0x3] - lsls r3, r0, 24 - ldr r0, _080B036C - ands r4, r0 - orrs r4, r3 - str r4, [r1, 0x28] - adds r2, 0x4 - str r2, [r1, 0x40] - pop {r4} - pop {r0} - bx r0 - .align 2, 0 -_080B0360: .4byte 0xffffff00 -_080B0364: .4byte 0xffff00ff -_080B0368: .4byte 0xff00ffff -_080B036C: .4byte 0x00ffffff - thumb_func_end sub_80B0328 - - thumb_func_start sub_80B0370 -sub_80B0370: - ldr r0, [r1, 0x40] - ldrb r2, [r0] - adds r0, r1, 0 - adds r0, 0x24 - strb r2, [r0] - ldr r0, [r1, 0x40] - adds r0, 0x1 - str r0, [r1, 0x40] - bx lr - thumb_func_end sub_80B0370 - - thumb_func_start sub_80B0384 -sub_80B0384: - ldr r0, [r1, 0x40] - ldrb r2, [r0] - adds r0, r1, 0 - adds r0, 0x2C - strb r2, [r0] - ldr r0, [r1, 0x40] - adds r0, 0x1 - str r0, [r1, 0x40] - bx lr - thumb_func_end sub_80B0384 - - thumb_func_start sub_80B0398 -sub_80B0398: - ldr r0, [r1, 0x40] - ldrb r0, [r0] - adds r2, r1, 0 - adds r2, 0x2D - strb r0, [r2] - ldr r0, [r1, 0x40] - adds r0, 0x1 - str r0, [r1, 0x40] - bx lr - thumb_func_end sub_80B0398 - - thumb_func_start sub_80B03AC -sub_80B03AC: - ldr r0, [r1, 0x40] - ldrb r0, [r0] - adds r2, r1, 0 - adds r2, 0x2E - strb r0, [r2] - ldr r0, [r1, 0x40] - adds r0, 0x1 - str r0, [r1, 0x40] - bx lr - thumb_func_end sub_80B03AC - - thumb_func_start sub_80B03C0 -sub_80B03C0: - ldr r0, [r1, 0x40] - ldrb r0, [r0] - adds r2, r1, 0 - adds r2, 0x2F - strb r0, [r2] - ldr r0, [r1, 0x40] - adds r0, 0x1 - str r0, [r1, 0x40] - bx lr - thumb_func_end sub_80B03C0 - - thumb_func_start sub_80B03D4 -sub_80B03D4: - ldr r0, [r1, 0x40] - ldrb r2, [r0] - strb r2, [r1, 0x1E] - adds r0, 0x1 - str r0, [r1, 0x40] - bx lr - thumb_func_end sub_80B03D4 - - thumb_func_start sub_80B03E0 -sub_80B03E0: - ldr r0, [r1, 0x40] - ldrb r2, [r0] - strb r2, [r1, 0x1F] - adds r0, 0x1 - str r0, [r1, 0x40] - bx lr - thumb_func_end sub_80B03E0 - - thumb_func_start sub_80B03EC -sub_80B03EC: - ldr r0, [r1, 0x40] - ldrb r0, [r0] - adds r2, r1, 0 - adds r2, 0x26 - strb r0, [r2] - ldr r0, [r1, 0x40] - adds r0, 0x1 - str r0, [r1, 0x40] - bx lr - thumb_func_end sub_80B03EC - - thumb_func_start ply_xswee -ply_xswee: - ldr r0, [r1, 0x40] - ldrb r0, [r0] - adds r2, r1, 0 - adds r2, 0x27 - strb r0, [r2] - ldr r0, [r1, 0x40] - adds r0, 0x1 - str r0, [r1, 0x40] - bx lr - thumb_func_end ply_xswee - - thumb_func_start nullsub_139 -nullsub_139: - bx lr - thumb_func_end nullsub_139 - - .align 2, 0 @ Don't pad with nop. diff --git a/asm/m4a_1.s b/asm/m4a_1.s new file mode 100644 index 0000000..8c1d78a --- /dev/null +++ b/asm/m4a_1.s @@ -0,0 +1,1647 @@ + .include "asm/macros.inc" + .include "constants/gba_constants.inc" + .include "constants/m4a_constants.inc" + + .syntax unified + + .text + + thumb_func_start umul3232H32 +umul3232H32: + adr r2, __umul3232H32 + bx r2 + .arm +__umul3232H32: + umull r2, r3, r0, r1 + add r0, r3, 0 + bx lr + thumb_func_end umul3232H32 + + thumb_func_start SoundMain +SoundMain: + ldr r0, lt_SOUND_INFO_PTR + ldr r0, [r0] + ldr r2, lt_ID_NUMBER + ldr r3, [r0, o_SoundInfo_ident] + cmp r2, r3 + beq SoundMain_1 + bx lr @ Exit the function if ident doesn't match ID_NUMBER. +SoundMain_1: + adds r3, 1 + str r3, [r0, o_SoundInfo_ident] + push {r4-r7,lr} + mov r1, r8 + mov r2, r9 + mov r3, r10 + mov r4, r11 + push {r0-r4} + sub sp, 0x18 + ldrb r1, [r0, o_SoundInfo_maxLines] + cmp r1, 0 @ if maxLines is 0, there is no maximum + beq SoundMain_3 + ldr r2, lt_REG_VCOUNT + ldrb r2, [r2] + cmp r2, VCOUNT_VBLANK + bhs SoundMain_2 + adds r2, TOTAL_SCANLINES +SoundMain_2: + adds r1, r2 +SoundMain_3: + str r1, [sp, 0x14] + ldr r3, [r0, o_SoundInfo_func] + cmp r3, 0 + beq SoundMain_4 + ldr r0, [r0, o_SoundInfo_intp] + bl call_r3 + ldr r0, [sp, 0x18] +SoundMain_4: + ldr r3, [r0, o_SoundInfo_CgbSound] + bl call_r3 + ldr r0, [sp, 0x18] + ldr r3, [r0, o_SoundInfo_pcmSamplesPerVBlank] + mov r8, r3 + ldr r5, lt_o_SoundInfo_pcmBuffer + adds r5, r0 + ldrb r4, [r0, o_SoundInfo_pcmDmaCounter] + subs r7, r4, 1 + bls SoundMain_5 + ldrb r1, [r0, o_SoundInfo_pcmDmaPeriod] + subs r1, r7 + mov r2, r8 + muls r2, r1 + adds r5, r2 +SoundMain_5: + str r5, [sp, 0x8] + ldr r6, lt_PCM_DMA_BUF_SIZE + ldr r3, lt_SoundMainRAM_Buffer + bx r3 + + .align 2, 0 +lt_SOUND_INFO_PTR: .word SOUND_INFO_PTR +lt_ID_NUMBER: .word ID_NUMBER +lt_SoundMainRAM_Buffer: .word SoundMainRAM_Buffer + 1 +lt_REG_VCOUNT: .word REG_VCOUNT +lt_o_SoundInfo_pcmBuffer: .word o_SoundInfo_pcmBuffer +lt_PCM_DMA_BUF_SIZE: .word PCM_DMA_BUF_SIZE + thumb_func_end SoundMain + + thumb_func_start SoundMainRAM +SoundMainRAM: + ldrb r3, [r0, o_SoundInfo_reverb] + cmp r3, 0 + beq SoundMainRAM_NoReverb + adr r1, SoundMainRAM_Reverb + bx r1 + .arm +SoundMainRAM_Reverb: + cmp r4, 0x2 + addeq r7, r0, o_SoundInfo_pcmBuffer + addne r7, r5, r8 + mov r4, r8 +_080AE314: + ldrsb r0, [r5, r6] + ldrsb r1, [r5] + add r0, r0, r1 + ldrsb r1, [r7, r6] + add r0, r0, r1 + ldrsb r1, [r7], 0x1 + add r0, r0, r1 + mul r1, r0, r3 + mov r0, r1, asr 9 + tst r0, 0x80 + addne r0, r0, 0x1 + strb r0, [r5, r6] + strb r0, [r5], 0x1 + subs r4, r4, 0x1 + bgt _080AE314 + add r0, pc, 0x2F + bx r0 + .thumb +SoundMainRAM_NoReverb: + movs r0, 0 + mov r1, r8 + adds r6, r5 + lsrs r1, 3 + bcc SoundMainRAM_NoReverb_Ok + stm r5!, {r0} + stm r6!, {r0} +SoundMainRAM_NoReverb_Ok: + lsrs r1, 1 + bcc SoundMainRAM_NoReverb_Loop + stm r5!, {r0} + stm r6!, {r0} + stm r5!, {r0} + stm r6!, {r0} +SoundMainRAM_NoReverb_Loop: + stm r5!, {r0} + stm r6!, {r0} + stm r5!, {r0} + stm r6!, {r0} + stm r5!, {r0} + stm r6!, {r0} + stm r5!, {r0} + stm r6!, {r0} + subs r1, 0x1 + bgt SoundMainRAM_NoReverb_Loop +_080AE386: + ldr r4, [sp, 0x18] + ldr r0, [r4, o_SoundInfo_divFreq] + mov r12, r0 + ldrb r0, [r4, o_SoundInfo_maxChans] + adds r4, o_SoundInfo_chans +SoundMainRAM_ChanLoop: + str r0, [sp, 0x4] + ldr r3, [r4, o_SoundChannel_wav] + ldr r0, [sp, 0x14] + cmp r0, 0 + beq _080AE3B0 + ldr r1, =REG_VCOUNT + ldrb r1, [r1] + cmp r1, VCOUNT_VBLANK + bhs _080AE3A4 + adds r1, TOTAL_SCANLINES +_080AE3A4: + cmp r1, r0 + bcc _080AE3B0 + b _080AE682 + + .pool + +_080AE3B0: + ldrb r6, [r4, o_SoundChannel_status] + movs r0, 0xC7 + tst r0, r6 + bne _080AE3BA + b _080AE678 +_080AE3BA: + movs r0, 0x80 + tst r0, r6 + beq _080AE3EA + movs r0, 0x40 + tst r0, r6 + bne _080AE3FA + movs r6, 0x3 + strb r6, [r4, o_SoundChannel_status] + adds r0, r3, 0 + adds r0, 0x10 + str r0, [r4, o_SoundChannel_cp] + ldr r0, [r3, 0xC] + str r0, [r4, o_SoundChannel_ct] + movs r5, 0 + strb r5, [r4, o_SoundChannel_ev] + str r5, [r4, o_SoundChannel_fw] + ldrb r2, [r3, 0x3] + movs r0, 0xC0 + tst r0, r2 + beq _080AE442 + movs r0, 0x10 + orrs r6, r0 + strb r6, [r4, o_SoundChannel_status] + b _080AE442 +_080AE3EA: + ldrb r5, [r4, o_SoundChannel_ev] + movs r0, 0x4 + tst r0, r6 + beq _080AE400 + ldrb r0, [r4, o_SoundChannel_iel] + subs r0, 0x1 + strb r0, [r4, o_SoundChannel_iel] + bhi _080AE450 +_080AE3FA: + movs r0, 0 + strb r0, [r4, o_SoundChannel_status] + b _080AE678 +_080AE400: + movs r0, 0x40 + tst r0, r6 + beq _080AE420 + ldrb r0, [r4, o_SoundChannel_release] + muls r5, r0 + lsrs r5, 8 + ldrb r0, [r4, o_SoundChannel_iev] + cmp r5, r0 + bhi _080AE450 +_080AE412: + ldrb r5, [r4, o_SoundChannel_iev] + cmp r5, 0 + beq _080AE3FA + movs r0, 0x4 + orrs r6, r0 + strb r6, [r4, o_SoundChannel_status] + b _080AE450 +_080AE420: + movs r2, 0x3 + ands r2, r6 + cmp r2, 0x2 + bne _080AE43E + ldrb r0, [r4, o_SoundChannel_decay] + muls r5, r0 + lsrs r5, 8 + ldrb r0, [r4, o_SoundChannel_sustain] + cmp r5, r0 + bhi _080AE450 + adds r5, r0, 0 + beq _080AE412 + subs r6, 0x1 + strb r6, [r4, o_SoundChannel_status] + b _080AE450 +_080AE43E: + cmp r2, 0x3 + bne _080AE450 +_080AE442: + ldrb r0, [r4, o_SoundChannel_attack] + adds r5, r0 + cmp r5, 0xFF + bcc _080AE450 + movs r5, 0xFF + subs r6, 0x1 + strb r6, [r4, o_SoundChannel_status] +_080AE450: + strb r5, [r4, o_SoundChannel_ev] + ldr r0, [sp, 0x18] + ldrb r0, [r0, o_SoundChannel_release] + adds r0, 0x1 + muls r0, r5 + lsrs r5, r0, 4 + ldrb r0, [r4, o_SoundChannel_rightVolume] + muls r0, r5 + lsrs r0, 8 + strb r0, [r4, o_SoundChannel_er] + ldrb r0, [r4, o_SoundChannel_leftVolume] + muls r0, r5 + lsrs r0, 8 + strb r0, [r4, o_SoundChannel_el] + movs r0, 0x10 + ands r0, r6 + str r0, [sp, 0x10] + beq _080AE484 + adds r0, r3, 0 + adds r0, 0x10 + ldr r1, [r3, 0x8] + adds r0, r1 + str r0, [sp, 0xC] + ldr r0, [r3, 0xC] + subs r0, r1 + str r0, [sp, 0x10] +_080AE484: + ldr r5, [sp, 0x8] + ldr r2, [r4, o_SoundChannel_ct] + ldr r3, [r4, o_SoundChannel_cp] + adr r0, _080AE490 + bx r0 + .arm +_080AE490: + str r8, [sp] + ldrb r10, [r4, o_SoundChannel_er] + ldrb r11, [r4, o_SoundChannel_el] + mov r10, r10, lsl 16 + mov r11, r11, lsl 16 + ldrb r0, [r4, o_SoundChannel_type] + tst r0, 0x8 + beq _080AE5D0 +_080AE4B0: + cmp r2, 0x4 + ble _080AE520 + subs r2, r2, r8 + movgt lr, 0 + bgt _080AE4DC + mov lr, r8 + add r2, r2, r8 + sub r8, r2, 0x4 + sub lr, lr, r8 + ands r2, r2, 0x3 + moveq r2, 0x4 +_080AE4DC: + ldr r6, [r5] + ldr r7, [r5, 0x630] +_080AE4E4: + ldrsb r0, [r3], 0x1 + mul r1, r10, r0 + bic r1, r1, 0xFF0000 + add r6, r1, r6, ror 8 + mul r1, r11, r0 + bic r1, r1, 0xFF0000 + add r7, r1, r7, ror 8 + adds r5, r5, 0x40000000 + bcc _080AE4E4 + str r7, [r5, 0x630] + str r6, [r5], 0x4 + subs r8, r8, 0x4 + bgt _080AE4DC + adds r8, r8, lr + beq _080AE664 +_080AE520: + ldr r6, [r5] + ldr r7, [r5, 0x630] +_080AE528: + ldrsb r0, [r3], 0x1 + mul r1, r10, r0 + bic r1, r1, 0xFF0000 + add r6, r1, r6, ror 8 + mul r1, r11, r0 + bic r1, r1, 0xFF0000 + add r7, r1, r7, ror 8 + subs r2, r2, 0x1 + beq _080AE598 +_080AE54C: + adds r5, r5, 0x40000000 + bcc _080AE528 + str r7, [r5, 0x630] + str r6, [r5], 0x4 + subs r8, r8, 0x4 + bgt _080AE4B0 + b _080AE664 +_080AE568: + ldr r0, [sp, 0x18] + cmp r0, 0 + beq _080AE58C + ldr r3, [sp, 0x14] + rsb r9, r2, 0 +_080AE57C: + adds r2, r0, r2 + bgt _080AE634 + sub r9, r9, r0 + b _080AE57C +_080AE58C: + ldmia sp!, {r4,r12} + mov r2, 0 + b _080AE5A8 +_080AE598: + ldr r2, [sp, 0x10] + cmp r2, 0 + ldrne r3, [sp, 0xC] + bne _080AE54C +_080AE5A8: + strb r2, [r4, o_SoundChannel_status] + mov r0, r5, lsr 30 + bic r5, r5, 0xC0000000 + rsb r0, r0, 0x3 + mov r0, r0, lsl 3 + mov r6, r6, ror r0 + mov r7, r7, ror r0 + str r7, [r5, 0x630] + str r6, [r5], 0x4 + b _080AE66C +_080AE5D0: + stmdb sp!, {r4,r12} + ldr lr, [r4, o_SoundChannel_fw] + ldr r1, [r4, o_SoundChannel_freq] + mul r4, r12, r1 + ldrsb r0, [r3] + ldrsb r1, [r3, 0x1]! + sub r1, r1, r0 +_080AE5EC: + ldr r6, [r5] + ldr r7, [r5, 0x630] +_080AE5F4: + mul r9, lr, r1 + add r9, r0, r9, asr 23 + mul r12, r10, r9 + bic r12, r12, 0xFF0000 + add r6, r12, r6, ror 8 + mul r12, r11, r9 + bic r12, r12, 0xFF0000 + add r7, r12, r7, ror 8 + add lr, lr, r4 + movs r9, lr, lsr 23 + beq _080AE640 + bic lr, lr, 0x3F800000 + subs r2, r2, r9 + ble _080AE568 + subs r9, r9, 0x1 + addeq r0, r0, r1 +_080AE634: + ldrsbne r0, [r3, r9]! + ldrsb r1, [r3, 0x1]! + sub r1, r1, r0 +_080AE640: + adds r5, r5, 0x40000000 + bcc _080AE5F4 + str r7, [r5, 0x630] + str r6, [r5], 0x4 + subs r8, r8, 0x4 + bgt _080AE5EC + sub r3, r3, 0x1 + ldmia sp!, {r4,r12} + str lr, [r4, o_SoundChannel_fw] +_080AE664: + str r2, [r4, o_SoundChannel_ct] + str r3, [r4, o_SoundChannel_cp] +_080AE66C: + ldr r8, [sp] + add r0, pc, 0x1 + bx r0 + .thumb +_080AE678: + ldr r0, [sp, 0x4] + subs r0, 0x1 + ble _080AE682 + adds r4, SoundChannel_size + b SoundMainRAM_ChanLoop +_080AE682: + ldr r0, [sp, 0x18] + ldr r3, =ID_NUMBER + str r3, [r0] + add sp, 0x1C + pop {r0-r7} + mov r8, r0 + mov r9, r1 + mov r10, r2 + mov r11, r3 + pop {r3} + +call_r3: + bx r3 + .pool + thumb_func_end SoundMainRAM + + thumb_func_start SoundMainBTM +SoundMainBTM: + mov r12, r4 + movs r1, 0 + movs r2, 0 + movs r3, 0 + movs r4, 0 + stm r0!, {r1-r4} + stm r0!, {r1-r4} + stm r0!, {r1-r4} + stm r0!, {r1-r4} + mov r4, r12 + bx lr + thumb_func_end SoundMainBTM + + thumb_func_start RealClearChain +RealClearChain: + ldr r3, [r0, 0x2C] + cmp r3, 0 + beq _080AE6D2 + ldr r1, [r0, 0x34] + ldr r2, [r0, 0x30] + cmp r2, 0 + beq _080AE6C6 + str r1, [r2, 0x34] + b _080AE6C8 +_080AE6C6: + str r1, [r3, 0x20] +_080AE6C8: + cmp r1, 0 + beq _080AE6CE + str r2, [r1, 0x30] +_080AE6CE: + movs r1, 0 + str r1, [r0, 0x2C] +_080AE6D2: + bx lr + thumb_func_end RealClearChain + + thumb_func_start ply_fine +ply_fine: + push {r4,r5,lr} + adds r5, r1, 0 + ldr r4, [r5, o_MusicPlayerTrack_chan] + cmp r4, 0 + beq ply_fine_done +ply_fine_loop: + ldrb r1, [r4] + movs r0, 0xC7 + tst r0, r1 + beq ply_fine_ok + movs r0, 0x40 + orrs r1, r0 + strb r1, [r4] +ply_fine_ok: + adds r0, r4, 0 + bl RealClearChain + ldr r4, [r4, 0x34] + cmp r4, 0 + bne ply_fine_loop +ply_fine_done: + movs r0, 0 + strb r0, [r5] + pop {r4,r5} + pop {r0} + bx r0 + thumb_func_end ply_fine + + thumb_func_start MPlayJumpTableCopy +MPlayJumpTableCopy: + mov r12, lr + movs r1, 0x24 + ldr r2, lt_MPlayJumpTableTemplate +MPlayJumpTableCopy_Loop: + ldr r3, [r2] + bl chk_adr_r2 + stm r0!, {r3} + adds r2, 0x4 + subs r1, 0x1 + bgt MPlayJumpTableCopy_Loop + bx r12 + thumb_func_end MPlayJumpTableCopy + + .align 2, 0 + .thumb_func +ldrb_r3_r2: + ldrb r3, [r2] + + .thumb_func +chk_adr_r2: + push {r0} + lsrs r0, r2, 25 + bne chk_adr_r2_done + ldr r0, lt_MPlayJumpTableTemplate + cmp r2, r0 + bcc chk_adr_r2_reject + lsrs r0, r2, 14 + beq chk_adr_r2_done +chk_adr_r2_reject: + movs r3, 0 +chk_adr_r2_done: + pop {r0} + bx lr + .align 2, 0 +lt_MPlayJumpTableTemplate: .word gMPlayJumpTableTemplate + + thumb_func_start ld_r3_tp_adr_i +ld_r3_tp_adr_i: + ldr r2, [r1, 0x40] +_080AE73A: + adds r3, r2, 0x1 + str r3, [r1, 0x40] + ldrb r3, [r2] + b chk_adr_r2 + thumb_func_end ld_r3_tp_adr_i + + thumb_func_start ply_goto +ply_goto: + push {lr} +ply_goto_1: + ldr r2, [r1, o_MusicPlayerTrack_cmdPtr] + ldrb r0, [r2, 0x3] + lsls r0, 8 + ldrb r3, [r2, 0x2] + orrs r0, r3 + lsls r0, 8 + ldrb r3, [r2, 0x1] + orrs r0, r3 + lsls r0, 8 + bl ldrb_r3_r2 + orrs r0, r3 + str r0, [r1, o_MusicPlayerTrack_cmdPtr] + pop {r0} + bx r0 + thumb_func_end ply_goto + + thumb_func_start ply_patt +ply_patt: + ldrb r2, [r1, o_MusicPlayerTrack_patternLevel] + cmp r2, 0x3 + bcs _080AE77C + lsls r2, 2 + adds r3, r1, r2 + ldr r2, [r1, o_MusicPlayerTrack_cmdPtr] + adds r2, 0x4 + str r2, [r3, o_MusicPlayerTrack_patternStack] + ldrb r2, [r1, o_MusicPlayerTrack_patternLevel] + adds r2, 0x1 + strb r2, [r1, o_MusicPlayerTrack_patternLevel] + b ply_goto +_080AE77C: + b ply_fine + thumb_func_end ply_patt + + thumb_func_start ply_pend +ply_pend: + ldrb r2, [r1, o_MusicPlayerTrack_patternLevel] + cmp r2, 0 + beq ply_pend_done + subs r2, 1 + strb r2, [r1, o_MusicPlayerTrack_patternLevel] + lsls r2, 2 + adds r3, r1, r2 + ldr r2, [r3, o_MusicPlayerTrack_patternStack] + str r2, [r1, o_MusicPlayerTrack_cmdPtr] +ply_pend_done: + bx lr + thumb_func_end ply_pend + + thumb_func_start ply_rept +ply_rept: + push {lr} + ldr r2, [r1, o_MusicPlayerTrack_cmdPtr] + ldrb r3, [r2] + cmp r3, 0 + bne ply_rept_1 + adds r2, 1 + str r2, [r1, o_MusicPlayerTrack_cmdPtr] + b ply_goto_1 +ply_rept_1: + ldrb r3, [r1, o_MusicPlayerTrack_repN] + adds r3, 1 + strb r3, [r1, o_MusicPlayerTrack_repN] + mov r12, r3 + bl ld_r3_tp_adr_i + cmp r12, r3 + bhs ply_rept_2 + b ply_goto_1 +ply_rept_2: + movs r3, 0 + strb r3, [r1, o_MusicPlayerTrack_repN] + adds r2, 5 + str r2, [r1, o_MusicPlayerTrack_cmdPtr] + pop {r0} + bx r0 + thumb_func_end ply_rept + + thumb_func_start ply_prio +ply_prio: + mov r12, lr + bl ld_r3_tp_adr_i + strb r3, [r1, o_MusicPlayerTrack_priority] + bx r12 + thumb_func_end ply_prio + + thumb_func_start ply_tempo +ply_tempo: + mov r12, lr + bl ld_r3_tp_adr_i + lsls r3, 1 + strh r3, [r0, o_MusicPlayerInfo_tempoD] + ldrh r2, [r0, o_MusicPlayerInfo_tempoU] + muls r3, r2 + lsrs r3, 8 + strh r3, [r0, o_MusicPlayerInfo_tempoI] + bx r12 + thumb_func_end ply_tempo + + thumb_func_start ply_keysh +ply_keysh: + mov r12, lr + bl ld_r3_tp_adr_i + strb r3, [r1, o_MusicPlayerTrack_keyShift] + ldrb r3, [r1, o_MusicPlayerTrack_flags] + movs r2, 0xC + orrs r3, r2 + strb r3, [r1, o_MusicPlayerTrack_flags] + bx r12 + thumb_func_end ply_keysh + + thumb_func_start ply_voice +ply_voice: + mov r12, lr + ldr r2, [r1, o_MusicPlayerTrack_cmdPtr] + ldrb r3, [r2] + adds r2, 1 + str r2, [r1, o_MusicPlayerTrack_cmdPtr] + lsls r2, r3, 1 + adds r2, r3 + lsls r2, 2 + ldr r3, [r0, o_MusicPlayerInfo_tone] + adds r2, r3 + ldr r3, [r2] + bl chk_adr_r2 + str r3, [r1, o_MusicPlayerTrack_ToneData_type] + ldr r3, [r2, 0x4] + bl chk_adr_r2 + str r3, [r1, o_MusicPlayerTrack_ToneData_wav] + ldr r3, [r2, 0x8] + bl chk_adr_r2 + str r3, [r1, o_MusicPlayerTrack_ToneData_attack] + bx r12 + thumb_func_end ply_voice + + thumb_func_start ply_vol +ply_vol: + mov r12, lr + bl ld_r3_tp_adr_i + strb r3, [r1, o_MusicPlayerTrack_vol] + ldrb r3, [r1, o_MusicPlayerTrack_flags] + movs r2, 0x3 + orrs r3, r2 + strb r3, [r1, o_MusicPlayerTrack_flags] + bx r12 + thumb_func_end ply_vol + + thumb_func_start ply_pan +ply_pan: + mov r12, lr + bl ld_r3_tp_adr_i + subs r3, 0x40 + strb r3, [r1, o_MusicPlayerTrack_pan] + ldrb r3, [r1, o_MusicPlayerTrack_flags] + movs r2, 0x3 + orrs r3, r2 + strb r3, [r1, o_MusicPlayerTrack_flags] + bx r12 + thumb_func_end ply_pan + + thumb_func_start ply_bend +ply_bend: + mov r12, lr + bl ld_r3_tp_adr_i + subs r3, 0x40 + strb r3, [r1, o_MusicPlayerTrack_bend] + ldrb r3, [r1, o_MusicPlayerTrack_flags] + movs r2, 0xC + orrs r3, r2 + strb r3, [r1, o_MusicPlayerTrack_flags] + bx r12 + thumb_func_end ply_bend + + thumb_func_start ply_bendr +ply_bendr: + mov r12, lr + bl ld_r3_tp_adr_i + strb r3, [r1, o_MusicPlayerTrack_bendRange] + ldrb r3, [r1, o_MusicPlayerTrack_flags] + movs r2, 0xC + orrs r3, r2 + strb r3, [r1, o_MusicPlayerTrack_flags] + bx r12 + thumb_func_end ply_bendr + + thumb_func_start ply_lfodl +ply_lfodl: + mov r12, lr + bl ld_r3_tp_adr_i + strb r3, [r1, o_MusicPlayerTrack_lfoDelay] + bx r12 + thumb_func_end ply_lfodl + + thumb_func_start ply_modt +ply_modt: + mov r12, lr + bl ld_r3_tp_adr_i + ldrb r0, [r1, o_MusicPlayerTrack_modT] + cmp r0, r3 + beq _080AE89A + strb r3, [r1, o_MusicPlayerTrack_modT] + ldrb r3, [r1, o_MusicPlayerTrack_flags] + movs r2, 0xF + orrs r3, r2 + strb r3, [r1, o_MusicPlayerTrack_flags] +_080AE89A: + bx r12 + thumb_func_end ply_modt + + thumb_func_start ply_tune +ply_tune: + mov r12, lr + bl ld_r3_tp_adr_i + subs r3, 0x40 + strb r3, [r1, o_MusicPlayerTrack_tune] + ldrb r3, [r1, o_MusicPlayerTrack_flags] + movs r2, 0xC + orrs r3, r2 + strb r3, [r1, o_MusicPlayerTrack_flags] + bx r12 + thumb_func_end ply_tune + + thumb_func_start ply_port +ply_port: + mov r12, lr + ldr r2, [r1, o_MusicPlayerTrack_cmdPtr] + ldrb r3, [r2] + adds r2, 0x1 + ldr r0, =REG_SOUND1CNT_L @ sound register base address + adds r0, r3 + bl _080AE73A + strb r3, [r0] + bx r12 + .pool + thumb_func_end ply_port + + thumb_func_start m4aSoundVSync +m4aSoundVSync: + ldr r0, lt2_SOUND_INFO_PTR + ldr r0, [r0] + + @ Exit the function if ident is not ID_NUMBER or ID_NUMBER+1. + ldr r2, lt2_ID_NUMBER + ldr r3, [r0, o_SoundInfo_ident] + subs r3, r2 + cmp r3, 0x1 + bhi m4aSoundVSync_Done + + @ Decrement the PCM DMA counter. If it reaches 0, we need to do a DMA. + ldrb r1, [r0, o_SoundInfo_pcmDmaCounter] + subs r1, 0x1 + strb r1, [r0, o_SoundInfo_pcmDmaCounter] + bgt m4aSoundVSync_Done + + @ Reload the PCM DMA counter. + ldrb r1, [r0, o_SoundInfo_pcmDmaPeriod] + strb r1, [r0, o_SoundInfo_pcmDmaCounter] + + ldr r2, =REG_DMA1 + + ldr r1, [r2, 0x8] @ DMA1CNT + lsls r1, 7 + bcc m4aSoundVSync_SkipDMA1 + + ldr r1, =((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4 + str r1, [r2, 0x8] @ DMA1CNT + +m4aSoundVSync_SkipDMA1: + ldr r1, [r2, 0xC + 0x8] @ DMA2CNT + lsls r1, 7 + bcc m4aSoundVSync_SkipDMA2 + ldr r1, =((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4 + str r1, [r2, 0xC + 0x8] @ DMA2CNT + +m4aSoundVSync_SkipDMA2: + movs r1, DMA_32BIT >> 8 + lsls r1, 8 + strh r1, [r2, 0xA] @ DMA1CNT_H + strh r1, [r2, 0xC + 0xA] @ DMA2CNT_H + + movs r1, (DMA_ENABLE | DMA_START_SPECIAL | DMA_32BIT | DMA_REPEAT) >> 8 + lsls r1, 8 @ LSB is 0, so DMA_SRC_INC is used (destination is always fixed in FIFO mode) + strh r1, [r2, 0xA] @ DMA1CNT_H + strh r1, [r2, 0xC + 0xA] @ DMA2CNT_H + +m4aSoundVSync_Done: + bx lr + + .pool + thumb_func_end m4aSoundVSync + + thumb_func_start MPlayMain +MPlayMain: + ldr r2, lt2_ID_NUMBER + ldr r3, [r0, o_MusicPlayerInfo_ident] + cmp r2, r3 + beq _080AE91E + bx lr +_080AE91E: + adds r3, 0x1 + str r3, [r0, o_MusicPlayerInfo_ident] + push {r0,lr} + ldr r3, [r0, o_MusicPlayerInfo_func] + cmp r3, 0 + beq _080AE930 + ldr r0, [r0, o_MusicPlayerInfo_intp] + bl call_r3_2 +_080AE930: + pop {r0} + push {r4-r7} + mov r4, r8 + mov r5, r9 + mov r6, r10 + mov r7, r11 + push {r4-r7} + adds r7, r0, 0 + ldr r0, [r7, o_MusicPlayerInfo_status] + cmp r0, 0 + bge _080AE948 + b _080AEB5C +_080AE948: + ldr r0, lt2_SOUND_INFO_PTR + ldr r0, [r0] + mov r8, r0 + adds r0, r7, 0 + bl FadeOutBody + ldr r0, [r7, o_MusicPlayerInfo_status] + cmp r0, 0 + bge _080AE95C + b _080AEB5C +_080AE95C: + ldrh r0, [r7, o_MusicPlayerInfo_tempoC] + ldrh r1, [r7, o_MusicPlayerInfo_tempoI] + adds r0, r1 + b _080AEAAC +_080AE964: + ldrb r6, [r7, o_MusicPlayerInfo_trackCount] + ldr r5, [r7, o_MusicPlayerInfo_tracks] + movs r3, 0x1 + movs r4, 0 +_080AE96C: + ldrb r0, [r5] + movs r1, 0x80 + tst r1, r0 + bne _080AE976 + b _080AEA88 +_080AE976: + mov r10, r3 + orrs r4, r3 + mov r11, r4 + ldr r4, [r5, o_MusicPlayerTrack_chan] + cmp r4, 0 + beq _080AE9AA +_080AE982: + ldrb r1, [r4] + movs r0, 0xC7 + tst r0, r1 + beq _080AE99E + ldrb r0, [r4, 0x10] + cmp r0, 0 + beq _080AE9A4 + subs r0, 0x1 + strb r0, [r4, 0x10] + bne _080AE9A4 + movs r0, 0x40 + orrs r1, r0 + strb r1, [r4] + b _080AE9A4 +_080AE99E: + adds r0, r4, 0 + bl ClearChain +_080AE9A4: + ldr r4, [r4, 0x34] + cmp r4, 0 + bne _080AE982 +_080AE9AA: + ldrb r3, [r5, o_MusicPlayerTrack_flags] + movs r0, 0x40 + tst r0, r3 + beq _080AEA28 + adds r0, r5, 0 + bl Clear64byte + movs r0, 0x80 + strb r0, [r5] + movs r0, 0x2 + strb r0, [r5, o_MusicPlayerTrack_bendRange] + movs r0, 0x40 + strb r0, [r5, o_MusicPlayerTrack_volX] + movs r0, 0x16 + strb r0, [r5, o_MusicPlayerTrack_lfoSpeed] + movs r0, 0x1 + adds r1, r5, 0x6 + strb r0, [r1, o_MusicPlayerTrack_ToneData_type - 0x6] + b _080AEA28 +_080AE9D0: + ldr r2, [r5, o_MusicPlayerTrack_cmdPtr] + ldrb r1, [r2] + cmp r1, 0x80 + bcs _080AE9DC + ldrb r1, [r5, o_MusicPlayerTrack_runningStatus] + b _080AE9E6 +_080AE9DC: + adds r2, 0x1 + str r2, [r5, o_MusicPlayerTrack_cmdPtr] + cmp r1, 0xBD + bcc _080AE9E6 + strb r1, [r5, o_MusicPlayerTrack_runningStatus] +_080AE9E6: + cmp r1, 0xCF + bcc _080AE9FC + mov r0, r8 + ldr r3, [r0, o_SoundInfo_plynote] + adds r0, r1, 0 + subs r0, 0xCF + adds r1, r7, 0 + adds r2, r5, 0 + bl call_r3_2 + b _080AEA28 +_080AE9FC: + cmp r1, 0xB0 + bls _080AEA1E + adds r0, r1, 0 + subs r0, 0xB1 + strb r0, [r7, o_MusicPlayerInfo_cmd] + mov r3, r8 + ldr r3, [r3, o_SoundInfo_MPlayJumpTable] + lsls r0, 2 + ldr r3, [r3, r0] + adds r0, r7, 0 + adds r1, r5, 0 + bl call_r3_2 + ldrb r0, [r5, o_MusicPlayerTrack_flags] + cmp r0, 0 + beq _080AEA84 + b _080AEA28 +_080AEA1E: + ldr r0, lt_gClockTable + subs r1, 0x80 + adds r1, r0 + ldrb r0, [r1] + strb r0, [r5, o_MusicPlayerTrack_wait] +_080AEA28: + ldrb r0, [r5, o_MusicPlayerTrack_wait] + cmp r0, 0 + beq _080AE9D0 + subs r0, 0x1 + strb r0, [r5, o_MusicPlayerTrack_wait] + ldrb r1, [r5, o_MusicPlayerTrack_lfoSpeed] + cmp r1, 0 + beq _080AEA84 + ldrb r0, [r5, o_MusicPlayerTrack_mod] + cmp r0, 0 + beq _080AEA84 + ldrb r0, [r5, o_MusicPlayerTrack_lfoDelayC] + cmp r0, 0 + beq _080AEA4A + subs r0, 0x1 + strb r0, [r5, o_MusicPlayerTrack_lfoDelayC] + b _080AEA84 +_080AEA4A: + ldrb r0, [r5, o_MusicPlayerTrack_lfoSpeedC] + adds r0, r1 + strb r0, [r5, o_MusicPlayerTrack_lfoSpeedC] + adds r1, r0, 0 + subs r0, 0x40 + lsls r0, 24 + bpl _080AEA5E + lsls r2, r1, 24 + asrs r2, 24 + b _080AEA62 +_080AEA5E: + movs r0, 0x80 + subs r2, r0, r1 +_080AEA62: + ldrb r0, [r5, o_MusicPlayerTrack_mod] + muls r0, r2 + asrs r2, r0, 6 + ldrb r0, [r5, o_MusicPlayerTrack_modM] + eors r0, r2 + lsls r0, 24 + beq _080AEA84 + strb r2, [r5, o_MusicPlayerTrack_modM] + ldrb r0, [r5] + ldrb r1, [r5, o_MusicPlayerTrack_modT] + cmp r1, 0 + bne _080AEA7E + movs r1, 0xC + b _080AEA80 +_080AEA7E: + movs r1, 0x3 +_080AEA80: + orrs r0, r1 + strb r0, [r5, o_MusicPlayerTrack_flags] +_080AEA84: + mov r3, r10 + mov r4, r11 +_080AEA88: + subs r6, 0x1 + ble _080AEA94 + movs r0, 0x50 + adds r5, r0 + lsls r3, 1 + b _080AE96C +_080AEA94: + ldr r0, [r7, o_MusicPlayerInfo_clock] + adds r0, 0x1 + str r0, [r7, o_MusicPlayerInfo_clock] + cmp r4, 0 + bne _080AEAA6 + movs r0, 0x80 + lsls r0, 24 + str r0, [r7, o_MusicPlayerInfo_status] + b _080AEB5C +_080AEAA6: + str r4, [r7, o_MusicPlayerInfo_status] + ldrh r0, [r7, o_MusicPlayerInfo_tempoC] + subs r0, 0x96 +_080AEAAC: + strh r0, [r7, o_MusicPlayerInfo_tempoC] + cmp r0, 0x96 + bcc _080AEAB4 + b _080AE964 +_080AEAB4: + ldrb r2, [r7, o_MusicPlayerInfo_trackCount] + ldr r5, [r7, o_MusicPlayerInfo_tracks] +_080AEAB8: + ldrb r0, [r5, o_MusicPlayerTrack_flags] + movs r1, 0x80 + tst r1, r0 + beq _080AEB52 + movs r1, 0xF + tst r1, r0 + beq _080AEB52 + mov r9, r2 + adds r0, r7, 0 + adds r1, r5, 0 + bl TrkVolPitSet + ldr r4, [r5, o_MusicPlayerTrack_chan] + cmp r4, 0 + beq _080AEB48 +_080AEAD6: + ldrb r1, [r4, o_SoundChannel_status] + movs r0, 0xC7 + tst r0, r1 + bne _080AEAE6 + adds r0, r4, 0 + bl ClearChain + b _080AEB42 +_080AEAE6: + ldrb r0, [r4, o_SoundChannel_type] + movs r6, 0x7 + ands r6, r0 + ldrb r3, [r5, o_MusicPlayerTrack_flags] + movs r0, 0x3 + tst r0, r3 + beq _080AEB04 + bl ChnVolSetAsm + cmp r6, 0 + beq _080AEB04 + ldrb r0, [r4, o_CgbChannel_mo] + movs r1, 0x1 + orrs r0, r1 + strb r0, [r4, o_CgbChannel_mo] +_080AEB04: + ldrb r3, [r5, o_MusicPlayerTrack_flags] + movs r0, 0xC + tst r0, r3 + beq _080AEB42 + ldrb r1, [r4, o_SoundChannel_ky] + movs r0, 0x8 + ldrsb r0, [r5, r0] + adds r2, r1, r0 + bpl _080AEB18 + movs r2, 0 +_080AEB18: + cmp r6, 0 + beq _080AEB36 + mov r0, r8 + ldr r3, [r0, o_SoundInfo_MidiKeyToCgbFreq] + adds r1, r2, 0 + ldrb r2, [r5, o_MusicPlayerTrack_pitM] + adds r0, r6, 0 + bl call_r3_2 + str r0, [r4, o_CgbChannel_fr] + ldrb r0, [r4, o_CgbChannel_mo] + movs r1, 0x2 + orrs r0, r1 + strb r0, [r4, o_CgbChannel_mo] + b _080AEB42 +_080AEB36: + adds r1, r2, 0 + ldrb r2, [r5, o_MusicPlayerTrack_pitM] + ldr r0, [r4, o_SoundChannel_wav] + bl MidiKeyToFreq + str r0, [r4, o_SoundChannel_freq] +_080AEB42: + ldr r4, [r4, o_SoundChannel_np] + cmp r4, 0 + bne _080AEAD6 +_080AEB48: + ldrb r0, [r5, o_MusicPlayerTrack_flags] + movs r1, 0xF0 + ands r0, r1 + strb r0, [r5, o_MusicPlayerTrack_flags] + mov r2, r9 +_080AEB52: + subs r2, 0x1 + ble _080AEB5C + movs r0, 0x50 + adds r5, r0 + bgt _080AEAB8 +_080AEB5C: + ldr r0, lt2_ID_NUMBER + str r0, [r7, o_MusicPlayerInfo_ident] + pop {r0-r7} + mov r8, r0 + mov r9, r1 + mov r10, r2 + mov r11, r3 + pop {r3} +call_r3_2: + bx r3 + .align 2, 0 + +lt_gClockTable: .word gClockTable +lt2_SOUND_INFO_PTR: .word SOUND_INFO_PTR +lt2_ID_NUMBER: .word ID_NUMBER + thumb_func_end MPlayMain + + thumb_func_start TrackStop +TrackStop: + push {r4-r6,lr} + adds r5, r1, 0 + ldrb r1, [r5, o_MusicPlayerTrack_flags] + movs r0, 0x80 + tst r0, r1 + beq TrackStop_Done + ldr r4, [r5, o_MusicPlayerTrack_chan] + cmp r4, 0 + beq TrackStop_3 + movs r6, 0 +TrackStop_Loop: + ldrb r0, [r4, o_SoundChannel_status] + cmp r0, 0 + beq TrackStop_2 + ldrb r0, [r4, o_SoundChannel_type] + movs r3, 0x7 + ands r0, r3 + beq TrackStop_1 + ldr r3, =SOUND_INFO_PTR + ldr r3, [r3] + ldr r3, [r3, o_SoundInfo_CgbOscOff] + bl call_r3_2 +TrackStop_1: + strb r6, [r4, o_SoundChannel_status] +TrackStop_2: + str r6, [r4, o_SoundChannel_track] + ldr r4, [r4, o_SoundChannel_np] + cmp r4, 0 + bne TrackStop_Loop +TrackStop_3: + str r4, [r5, o_MusicPlayerTrack_chan] +TrackStop_Done: + pop {r4-r6} + pop {r0} + bx r0 + .pool + thumb_func_end TrackStop + + thumb_func_start ChnVolSetAsm +ChnVolSetAsm: + ldrb r1, [r4, 0x12] + movs r0, 0x14 + ldrsb r2, [r4, r0] + movs r3, 0x80 + adds r3, r2 + muls r3, r1 + ldrb r0, [r5, 0x10] + muls r0, r3 + asrs r0, 14 + cmp r0, 0xFF + bls _080AEBD8 + movs r0, 0xFF +_080AEBD8: + strb r0, [r4, 0x2] + movs r3, 0x7F + subs r3, r2 + muls r3, r1 + ldrb r0, [r5, 0x11] + muls r0, r3 + asrs r0, 14 + cmp r0, 0xFF + bls _080AEBEC + movs r0, 0xFF +_080AEBEC: + strb r0, [r4, 0x3] + bx lr + thumb_func_end ChnVolSetAsm + + thumb_func_start ply_note +ply_note: + push {r4-r7,lr} + mov r4, r8 + mov r5, r9 + mov r6, r10 + mov r7, r11 + push {r4-r7} + sub sp, 0x18 + str r1, [sp] + adds r5, r2, 0 + ldr r1, =SOUND_INFO_PTR + ldr r1, [r1] + str r1, [sp, 0x4] + ldr r1, =gClockTable + adds r0, r1 + ldrb r0, [r0] + strb r0, [r5, o_MusicPlayerTrack_gateTime] + ldr r3, [r5, o_MusicPlayerTrack_cmdPtr] + ldrb r0, [r3] + cmp r0, 0x80 + bcs _080AEC36 + strb r0, [r5, o_MusicPlayerTrack_key] + adds r3, 0x1 + ldrb r0, [r3] + cmp r0, 0x80 + bcs _080AEC34 + strb r0, [r5, o_MusicPlayerTrack_velocity] + adds r3, 0x1 + ldrb r0, [r3] + cmp r0, 0x80 + bcs _080AEC34 + ldrb r1, [r5, o_MusicPlayerTrack_gateTime] + adds r1, r0 + strb r1, [r5, o_MusicPlayerTrack_gateTime] + adds r3, 0x1 +_080AEC34: + str r3, [r5, o_MusicPlayerTrack_cmdPtr] +_080AEC36: + movs r0, 0 + str r0, [sp, 0x14] + adds r4, r5, 0 + adds r4, o_MusicPlayerTrack_ToneData_type + ldrb r2, [r4] + movs r0, TONEDATA_TYPE_RHY | TONEDATA_TYPE_SPL + tst r0, r2 + beq _080AEC88 + ldrb r3, [r5, o_MusicPlayerTrack_key] + movs r0, TONEDATA_TYPE_SPL + tst r0, r2 + beq _080AEC56 + ldr r1, [r5, o_MusicPlayerTrack_ToneData_keySplitTable] + adds r1, r3 + ldrb r0, [r1] + b _080AEC58 +_080AEC56: + adds r0, r3, 0 +_080AEC58: + lsls r1, r0, 1 + adds r1, r0 + lsls r1, 2 + ldr r0, [r5, o_MusicPlayerTrack_ToneData_wav] + adds r1, r0 + mov r9, r1 + mov r6, r9 + ldrb r1, [r6] + movs r0, 0xC0 + tst r0, r1 + beq _080AEC70 + b _080AEDD6 +_080AEC70: + movs r0, 0x80 + tst r0, r2 + beq _080AEC8C + ldrb r1, [r6, 0x3] + movs r0, 0x80 + tst r0, r1 + beq _080AEC84 + subs r1, 0xC0 + lsls r1, 1 + str r1, [sp, 0x14] +_080AEC84: + ldrb r3, [r6, 0x1] + b _080AEC8C +_080AEC88: + mov r9, r4 + ldrb r3, [r5, 0x5] +_080AEC8C: + str r3, [sp, 0x8] + ldr r6, [sp] + ldrb r1, [r6, 0x9] + ldrb r0, [r5, 0x1D] + adds r0, r1 + cmp r0, 0xFF + bls _080AEC9C + movs r0, 0xFF +_080AEC9C: + str r0, [sp, 0x10] + mov r6, r9 + ldrb r0, [r6] + movs r6, 0x7 + ands r6, r0 + str r6, [sp, 0xC] + beq _080AECDC + ldr r0, [sp, 0x4] + ldr r4, [r0, 0x1C] + cmp r4, 0 + bne _080AECB4 + b _080AEDD6 +_080AECB4: + subs r6, 0x1 + lsls r0, r6, 6 + adds r4, r0 + ldrb r1, [r4] + movs r0, 0xC7 + tst r0, r1 + beq _080AED30 + movs r0, 0x40 + tst r0, r1 + bne _080AED30 + ldrb r1, [r4, 0x13] + ldr r0, [sp, 0x10] + cmp r1, r0 + bcc _080AED30 + beq _080AECD4 + b _080AEDD6 +_080AECD4: + ldr r0, [r4, 0x2C] + cmp r0, r5 + bcs _080AED30 + b _080AEDD6 +_080AECDC: + ldr r6, [sp, 0x10] + adds r7, r5, 0 + movs r2, 0 + mov r8, r2 + ldr r4, [sp, 0x4] + ldrb r3, [r4, 0x6] + adds r4, 0x50 +_080AECEA: + ldrb r1, [r4] + movs r0, 0xC7 + tst r0, r1 + beq _080AED30 + movs r0, 0x40 + tst r0, r1 + beq _080AED04 + cmp r2, 0 + bne _080AED08 + adds r2, 0x1 + ldrb r6, [r4, 0x13] + ldr r7, [r4, 0x2C] + b _080AED22 +_080AED04: + cmp r2, 0 + bne _080AED24 +_080AED08: + ldrb r0, [r4, 0x13] + cmp r0, r6 + bcs _080AED14 + adds r6, r0, 0 + ldr r7, [r4, 0x2C] + b _080AED22 +_080AED14: + bhi _080AED24 + ldr r0, [r4, 0x2C] + cmp r0, r7 + bls _080AED20 + adds r7, r0, 0 + b _080AED22 +_080AED20: + bcc _080AED24 +_080AED22: + mov r8, r4 +_080AED24: + adds r4, 0x40 + subs r3, 0x1 + bgt _080AECEA + mov r4, r8 + cmp r4, 0 + beq _080AEDD6 +_080AED30: + adds r0, r4, 0 + bl ClearChain + movs r1, 0 + str r1, [r4, 0x30] + ldr r3, [r5, 0x20] + str r3, [r4, 0x34] + cmp r3, 0 + beq _080AED44 + str r4, [r3, 0x30] +_080AED44: + str r4, [r5, 0x20] + str r5, [r4, 0x2C] + ldrb r0, [r5, 0x1B] + strb r0, [r5, 0x1C] + cmp r0, r1 + beq _080AED56 + adds r1, r5, 0 + bl clear_modM +_080AED56: + ldr r0, [sp] + adds r1, r5, 0 + bl TrkVolPitSet + ldr r0, [r5, 0x4] + str r0, [r4, 0x10] + ldr r0, [sp, 0x10] + strb r0, [r4, 0x13] + ldr r0, [sp, 0x8] + strb r0, [r4, 0x8] + ldr r0, [sp, 0x14] + strb r0, [r4, 0x14] + mov r6, r9 + ldrb r0, [r6] + strb r0, [r4, 0x1] + ldr r7, [r6, 0x4] + str r7, [r4, 0x24] + ldr r0, [r6, 0x8] + str r0, [r4, 0x4] + ldrh r0, [r5, 0x1E] + strh r0, [r4, 0xC] + bl ChnVolSetAsm + ldrb r1, [r4, 0x8] + movs r0, 0x8 + ldrsb r0, [r5, r0] + adds r3, r1, r0 + bpl _080AED90 + movs r3, 0 +_080AED90: + ldr r6, [sp, 0xC] + cmp r6, 0 + beq _080AEDBE + mov r6, r9 + ldrb r0, [r6, 0x2] + strb r0, [r4, 0x1E] + ldrb r1, [r6, 0x3] + movs r0, 0x80 + tst r0, r1 + bne _080AEDAA + movs r0, 0x70 + tst r0, r1 + bne _080AEDAC +_080AEDAA: + movs r1, 0x8 +_080AEDAC: + strb r1, [r4, 0x1F] + ldrb r2, [r5, 0x9] + adds r1, r3, 0 + ldr r0, [sp, 0xC] + ldr r3, [sp, 0x4] + ldr r3, [r3, 0x30] + bl call_r3_2 + b _080AEDC8 +_080AEDBE: + ldrb r2, [r5, 0x9] + adds r1, r3, 0 + adds r0, r7, 0 + bl MidiKeyToFreq +_080AEDC8: + str r0, [r4, 0x20] + movs r0, 0x80 + strb r0, [r4] + ldrb r1, [r5] + movs r0, 0xF0 + ands r0, r1 + strb r0, [r5] +_080AEDD6: + add sp, 0x18 + pop {r0-r7} + mov r8, r0 + mov r9, r1 + mov r10, r2 + mov r11, r3 + pop {r0} + bx r0 + .pool + thumb_func_end ply_note + + thumb_func_start ply_endtie +ply_endtie: + push {r4,r5} + ldr r2, [r1, o_MusicPlayerTrack_cmdPtr] + ldrb r3, [r2] + cmp r3, 0x80 + bcs _080AEE02 + strb r3, [r1, o_MusicPlayerTrack_key] + adds r2, 0x1 + str r2, [r1, o_MusicPlayerTrack_cmdPtr] + b _080AEE04 +_080AEE02: + ldrb r3, [r1, o_MusicPlayerTrack_key] +_080AEE04: + ldr r1, [r1, o_MusicPlayerTrack_chan] + cmp r1, 0 + beq _080AEE2C + movs r4, 0x83 + movs r5, 0x40 +_080AEE0E: + ldrb r2, [r1, o_SoundChannel_status] + tst r2, r4 + beq _080AEE26 + tst r2, r5 + bne _080AEE26 + ldrb r0, [r1, o_SoundChannel_mk] + cmp r0, r3 + bne _080AEE26 + movs r0, 0x40 + orrs r2, r0 + strb r2, [r1, o_SoundChannel_status] + b _080AEE2C +_080AEE26: + ldr r1, [r1, o_SoundChannel_np] + cmp r1, 0 + bne _080AEE0E +_080AEE2C: + pop {r4,r5} + bx lr + thumb_func_end ply_endtie + + thumb_func_start clear_modM +clear_modM: + movs r2, 0 + strb r2, [r1, o_MusicPlayerTrack_modM] + strb r2, [r1, o_MusicPlayerTrack_lfoSpeedC] + ldrb r2, [r1, o_MusicPlayerTrack_modT] + cmp r2, 0 + bne _080AEE40 + movs r2, 0xC + b _080AEE42 +_080AEE40: + movs r2, 0x3 +_080AEE42: + ldrb r3, [r1, o_MusicPlayerTrack_flags] + orrs r3, r2 + strb r3, [r1, o_MusicPlayerTrack_flags] + bx lr + thumb_func_end clear_modM + + thumb_func_start ld_r3_tp_adr_i_unchecked +ld_r3_tp_adr_i_unchecked: + ldr r2, [r1, 0x40] + adds r3, r2, 0x1 + str r3, [r1, 0x40] + ldrb r3, [r2] + bx lr + thumb_func_end ld_r3_tp_adr_i_unchecked + + thumb_func_start ply_lfos +ply_lfos: + mov r12, lr + bl ld_r3_tp_adr_i_unchecked + strb r3, [r1, o_MusicPlayerTrack_lfoSpeed] + cmp r3, 0 + bne _080AEE68 + bl clear_modM +_080AEE68: + bx r12 + thumb_func_end ply_lfos + + thumb_func_start ply_mod +ply_mod: + mov r12, lr + bl ld_r3_tp_adr_i_unchecked + strb r3, [r1, o_MusicPlayerTrack_mod] + cmp r3, 0 + bne _080AEE7C + bl clear_modM +_080AEE7C: + bx r12 + thumb_func_end ply_mod + + .align 2, 0 @ Don't pad with nop. diff --git a/asm/m4a_2.s b/asm/m4a_2.s new file mode 100644 index 0000000..eb525ce --- /dev/null +++ b/asm/m4a_2.s @@ -0,0 +1,70 @@ + .include "asm/macros.inc" + .include "constants/gba_constants.inc" + .include "constants/m4a_constants.inc" + + .syntax unified + + .text + + thumb_func_start CgbModVol +CgbModVol: + push {r4,lr} + adds r1, r0, 0 + ldrb r0, [r1, 0x2] + lsls r2, r0, 24 + lsrs r4, r2, 24 + ldrb r3, [r1, 0x3] + lsls r0, r3, 24 + lsrs r3, r0, 24 + cmp r4, r3 + bcc _080AFA94 + lsrs r0, r2, 25 + cmp r0, r3 + bcc _080AFAA0 + movs r0, 0xF + strb r0, [r1, 0x1B] + b _080AFAAE +_080AFA94: + lsrs r0, 25 + cmp r0, r4 + bcc _080AFAA0 + movs r0, 0xF0 + strb r0, [r1, 0x1B] + b _080AFAAE +_080AFAA0: + movs r0, 0xFF + strb r0, [r1, 0x1B] + ldrb r2, [r1, 0x3] + ldrb r3, [r1, 0x2] + adds r0, r2, r3 + lsrs r0, 4 + b _080AFABE +_080AFAAE: + ldrb r2, [r1, 0x3] + ldrb r3, [r1, 0x2] + adds r0, r2, r3 + lsrs r0, 4 + strb r0, [r1, 0xA] + cmp r0, 0xF + bls _080AFAC0 + movs r0, 0xF +_080AFABE: + strb r0, [r1, 0xA] +_080AFAC0: + ldrb r2, [r1, 0x6] + ldrb r3, [r1, 0xA] + adds r0, r2, 0 + muls r0, r3 + adds r0, 0xF + asrs r0, 4 + strb r0, [r1, 0x19] + ldrb r0, [r1, 0x1C] + ldrb r2, [r1, 0x1B] + ands r0, r2 + strb r0, [r1, 0x1B] + pop {r4} + pop {r0} + bx r0 + thumb_func_end CgbModVol + + .align 2, 0 @ Don't pad with nop. diff --git a/asm/m4a_3.s b/asm/m4a_3.s new file mode 100644 index 0000000..4747b3f --- /dev/null +++ b/asm/m4a_3.s @@ -0,0 +1,574 @@ + .include "asm/macros.inc" + .include "constants/gba_constants.inc" + .include "constants/m4a_constants.inc" + + .syntax unified + + .text + + thumb_func_start CgbSound +CgbSound: + push {r4-r7,lr} + mov r7, r10 + mov r6, r9 + mov r5, r8 + push {r5-r7} + sub sp, 0x1C + ldr r0, =SOUND_INFO_PTR + ldr r0, [r0] + str r0, [sp, 0x4] + ldrb r0, [r0, 0xA] + cmp r0, 0 + beq _080AFB00 + subs r0, 0x1 + ldr r1, [sp, 0x4] + strb r0, [r1, 0xA] + b _080AFB06 + .pool +_080AFB00: + movs r0, 0xE + ldr r2, [sp, 0x4] + strb r0, [r2, 0xA] +_080AFB06: + movs r6, 0x1 + ldr r0, [sp, 0x4] + ldr r4, [r0, 0x1C] +_080AFB0C: + ldrb r1, [r4] + movs r0, 0xC7 + ands r0, r1 + adds r2, r6, 0x1 + mov r10, r2 + movs r2, 0x40 + adds r2, r4 + mov r9, r2 + cmp r0, 0 + bne _080AFB22 + b _080AFF0C +_080AFB22: + cmp r6, 0x2 + beq _080AFB54 + cmp r6, 0x2 + bgt _080AFB30 + cmp r6, 0x1 + beq _080AFB36 + b _080AFB8C +_080AFB30: + cmp r6, 0x3 + beq _080AFB6C + b _080AFB8C +_080AFB36: + ldr r0, =REG_NR10 + str r0, [sp, 0x8] + ldr r7, =REG_NR11 + ldr r2, =REG_NR12 + str r2, [sp, 0xC] + adds r0, 0x4 + str r0, [sp, 0x10] + adds r2, 0x2 + b _080AFB9C + .pool +_080AFB54: + ldr r0, =REG_NR10 + 1 + str r0, [sp, 0x8] + ldr r7, =REG_NR21 + ldr r2, =REG_NR22 + b _080AFB94 + .pool +_080AFB6C: + ldr r0, =REG_NR30 + str r0, [sp, 0x8] + ldr r7, =REG_NR31 + ldr r2, =REG_NR32 + str r2, [sp, 0xC] + adds r0, 0x4 + str r0, [sp, 0x10] + adds r2, 0x2 + b _080AFB9C + .pool +_080AFB8C: + ldr r0, =REG_NR30 + 1 + str r0, [sp, 0x8] + ldr r7, =REG_NR41 + ldr r2, =REG_NR42 +_080AFB94: + str r2, [sp, 0xC] + adds r0, 0xB + str r0, [sp, 0x10] + adds r2, 0x4 +_080AFB9C: + str r2, [sp, 0x14] + ldr r0, [sp, 0x4] + ldrb r0, [r0, 0xA] + str r0, [sp] + ldr r2, [sp, 0xC] + ldrb r0, [r2] + mov r8, r0 + adds r2, r1, 0 + movs r0, 0x80 + ands r0, r2 + cmp r0, 0 + beq _080AFC92 + movs r3, 0x40 + adds r0, r3, 0 + ands r0, r2 + lsls r0, 24 + lsrs r5, r0, 24 + adds r0, r6, 0x1 + mov r10, r0 + movs r1, 0x40 + adds r1, r4 + mov r9, r1 + cmp r5, 0 + bne _080AFCB6 + movs r0, 0x3 + strb r0, [r4] + strb r0, [r4, 0x1D] + adds r0, r4, 0 + str r3, [sp, 0x18] + bl CgbModVol + ldr r3, [sp, 0x18] + cmp r6, 0x2 + beq _080AFC04 + cmp r6, 0x2 + bgt _080AFBF8 + cmp r6, 0x1 + beq _080AFBFE + b _080AFC58 + .pool +_080AFBF8: + cmp r6, 0x3 + beq _080AFC10 + b _080AFC58 +_080AFBFE: + ldrb r0, [r4, 0x1F] + ldr r2, [sp, 0x8] + strb r0, [r2] +_080AFC04: + ldr r0, [r4, 0x24] + lsls r0, 6 + ldrb r1, [r4, 0x1E] + adds r0, r1, r0 + strb r0, [r7] + b _080AFC64 +_080AFC10: + ldr r1, [r4, 0x24] + ldr r0, [r4, 0x28] + cmp r1, r0 + beq _080AFC38 + ldr r2, [sp, 0x8] + strb r3, [r2] + ldr r1, =REG_WAVE_RAM + ldr r2, [r4, 0x24] + ldr r0, [r2] + str r0, [r1] + adds r1, 0x4 + ldr r0, [r2, 0x4] + str r0, [r1] + adds r1, 0x4 + ldr r0, [r2, 0x8] + str r0, [r1] + adds r1, 0x4 + ldr r0, [r2, 0xC] + str r0, [r1] + str r2, [r4, 0x28] +_080AFC38: + ldr r0, [sp, 0x8] + strb r5, [r0] + ldrb r0, [r4, 0x1E] + strb r0, [r7] + ldrb r0, [r4, 0x1E] + cmp r0, 0 + beq _080AFC50 + movs r0, 0xC0 + b _080AFC72 + .pool +_080AFC50: + movs r1, 0x80 + negs r1, r1 + strb r1, [r4, 0x1A] + b _080AFC74 +_080AFC58: + ldrb r0, [r4, 0x1E] + strb r0, [r7] + ldr r0, [r4, 0x24] + lsls r0, 3 + ldr r2, [sp, 0x10] + strb r0, [r2] +_080AFC64: + ldrb r0, [r4, 0x4] + adds r0, 0x8 + mov r8, r0 + ldrb r0, [r4, 0x1E] + cmp r0, 0 + beq _080AFC72 + movs r0, 0x40 +_080AFC72: + strb r0, [r4, 0x1A] +_080AFC74: + ldrb r1, [r4, 0x4] + movs r2, 0 + strb r1, [r4, 0xB] + movs r0, 0xFF + ands r0, r1 + adds r1, r6, 0x1 + mov r10, r1 + movs r1, 0x40 + adds r1, r4 + mov r9, r1 + cmp r0, 0 + bne _080AFC8E + b _080AFDCA +_080AFC8E: + strb r2, [r4, 0x9] + b _080AFDF8 +_080AFC92: + movs r0, 0x4 + ands r0, r2 + cmp r0, 0 + beq _080AFCC4 + ldrb r0, [r4, 0xD] + subs r0, 0x1 + strb r0, [r4, 0xD] + movs r2, 0xFF + ands r0, r2 + lsls r0, 24 + adds r1, r6, 0x1 + mov r10, r1 + movs r2, 0x40 + adds r2, r4 + mov r9, r2 + cmp r0, 0 + ble _080AFCB6 + b _080AFE0A +_080AFCB6: + lsls r0, r6, 24 + lsrs r0, 24 + bl CgbOscOff + movs r0, 0 + strb r0, [r4] + b _080AFF08 +_080AFCC4: + movs r0, 0x40 + ands r0, r1 + adds r2, r6, 0x1 + mov r10, r2 + movs r2, 0x40 + adds r2, r4 + mov r9, r2 + cmp r0, 0 + beq _080AFD04 + movs r0, 0x3 + ands r0, r1 + cmp r0, 0 + beq _080AFD04 + movs r0, 0xFC + ands r0, r1 + movs r2, 0 + strb r0, [r4] + ldrb r1, [r4, 0x7] + strb r1, [r4, 0xB] + movs r0, 0xFF + ands r0, r1 + cmp r0, 0 + beq _080AFD36 + movs r0, 0x1 + ldrb r1, [r4, 0x1D] + orrs r0, r1 + strb r0, [r4, 0x1D] + cmp r6, 0x3 + beq _080AFDF8 + ldrb r2, [r4, 0x7] + mov r8, r2 + b _080AFDF8 +_080AFD04: + ldrb r0, [r4, 0xB] + cmp r0, 0 + bne _080AFDF8 + cmp r6, 0x3 + bne _080AFD16 + movs r0, 0x1 + ldrb r1, [r4, 0x1D] + orrs r0, r1 + strb r0, [r4, 0x1D] +_080AFD16: + adds r0, r4, 0 + bl CgbModVol + movs r0, 0x3 + ldrb r2, [r4] + ands r0, r2 + cmp r0, 0 + bne _080AFD6A + ldrb r0, [r4, 0x9] + subs r0, 0x1 + strb r0, [r4, 0x9] + movs r1, 0xFF + ands r0, r1 + lsls r0, 24 + cmp r0, 0 + bgt _080AFD66 +_080AFD36: + ldrb r2, [r4, 0xC] + ldrb r1, [r4, 0xA] + adds r0, r2, 0 + muls r0, r1 + adds r0, 0xFF + asrs r0, 8 + movs r1, 0 + strb r0, [r4, 0x9] + lsls r0, 24 + cmp r0, 0 + beq _080AFCB6 + movs r0, 0x4 + ldrb r2, [r4] + orrs r0, r2 + strb r0, [r4] + movs r0, 0x1 + ldrb r1, [r4, 0x1D] + orrs r0, r1 + strb r0, [r4, 0x1D] + cmp r6, 0x3 + beq _080AFE0A + movs r2, 0x8 + mov r8, r2 + b _080AFE0A +_080AFD66: + ldrb r0, [r4, 0x7] + b _080AFDF6 +_080AFD6A: + cmp r0, 0x1 + bne _080AFD76 +_080AFD6E: + ldrb r0, [r4, 0x19] + strb r0, [r4, 0x9] + movs r0, 0x7 + b _080AFDF6 +_080AFD76: + cmp r0, 0x2 + bne _080AFDBA + ldrb r0, [r4, 0x9] + subs r0, 0x1 + strb r0, [r4, 0x9] + movs r1, 0xFF + ands r0, r1 + lsls r0, 24 + ldrb r2, [r4, 0x19] + lsls r1, r2, 24 + cmp r0, r1 + bgt _080AFDB6 +_080AFD8E: + ldrb r0, [r4, 0x6] + cmp r0, 0 + bne _080AFD9E + movs r0, 0xFC + ldrb r1, [r4] + ands r0, r1 + strb r0, [r4] + b _080AFD36 +_080AFD9E: + ldrb r0, [r4] + subs r0, 0x1 + strb r0, [r4] + movs r0, 0x1 + ldrb r2, [r4, 0x1D] + orrs r0, r2 + strb r0, [r4, 0x1D] + cmp r6, 0x3 + beq _080AFD6E + movs r0, 0x8 + mov r8, r0 + b _080AFD6E +_080AFDB6: + ldrb r0, [r4, 0x5] + b _080AFDF6 +_080AFDBA: + ldrb r0, [r4, 0x9] + adds r0, 0x1 + strb r0, [r4, 0x9] + movs r1, 0xFF + ands r0, r1 + ldrb r2, [r4, 0xA] + cmp r0, r2 + bcc _080AFDF4 +_080AFDCA: + ldrb r0, [r4] + subs r0, 0x1 + movs r2, 0 + strb r0, [r4] + ldrb r1, [r4, 0x5] + strb r1, [r4, 0xB] + movs r0, 0xFF + ands r0, r1 + cmp r0, 0 + beq _080AFD8E + movs r0, 0x1 + ldrb r1, [r4, 0x1D] + orrs r0, r1 + strb r0, [r4, 0x1D] + ldrb r0, [r4, 0xA] + strb r0, [r4, 0x9] + cmp r6, 0x3 + beq _080AFDF8 + ldrb r2, [r4, 0x5] + mov r8, r2 + b _080AFDF8 +_080AFDF4: + ldrb r0, [r4, 0x4] +_080AFDF6: + strb r0, [r4, 0xB] +_080AFDF8: + ldrb r0, [r4, 0xB] + subs r0, 0x1 + strb r0, [r4, 0xB] + ldr r0, [sp] + cmp r0, 0 + bne _080AFE0A + subs r0, 0x1 + str r0, [sp] + b _080AFD04 +_080AFE0A: + movs r0, 0x2 + ldrb r1, [r4, 0x1D] + ands r0, r1 + cmp r0, 0 + beq _080AFE82 + cmp r6, 0x3 + bgt _080AFE4A + movs r0, 0x8 + ldrb r2, [r4, 0x1] + ands r0, r2 + cmp r0, 0 + beq _080AFE4A + ldr r0, =REG_SOUNDBIAS + 1 + ldrb r0, [r0] + cmp r0, 0x3F + bgt _080AFE3C + ldr r0, [r4, 0x20] + adds r0, 0x2 + ldr r1, =0x000007fc + b _080AFE46 + .pool +_080AFE3C: + cmp r0, 0x7F + bgt _080AFE4A + ldr r0, [r4, 0x20] + adds r0, 0x1 + ldr r1, =0x000007fe +_080AFE46: + ands r0, r1 + str r0, [r4, 0x20] +_080AFE4A: + cmp r6, 0x4 + beq _080AFE5C + ldr r0, [r4, 0x20] + ldr r1, [sp, 0x10] + strb r0, [r1] + b _080AFE6A + .pool +_080AFE5C: + ldr r2, [sp, 0x10] + ldrb r0, [r2] + movs r1, 0x8 + ands r1, r0 + ldr r0, [r4, 0x20] + orrs r0, r1 + strb r0, [r2] +_080AFE6A: + movs r0, 0xC0 + ldrb r1, [r4, 0x1A] + ands r0, r1 + adds r1, r4, 0 + adds r1, 0x21 + ldrb r1, [r1] + adds r0, r1, r0 + strb r0, [r4, 0x1A] + movs r2, 0xFF + ands r0, r2 + ldr r1, [sp, 0x14] + strb r0, [r1] +_080AFE82: + movs r0, 0x1 + ldrb r2, [r4, 0x1D] + ands r0, r2 + cmp r0, 0 + beq _080AFF08 + ldr r1, =REG_NR51 + ldrb r0, [r1] + ldrb r2, [r4, 0x1C] + bics r0, r2 + ldrb r2, [r4, 0x1B] + orrs r0, r2 + strb r0, [r1] + cmp r6, 0x3 + bne _080AFED4 + ldr r0, =gCgb3Vol + ldrb r1, [r4, 0x9] + adds r0, r1, r0 + ldrb r0, [r0] + ldr r2, [sp, 0xC] + strb r0, [r2] + movs r1, 0x80 + adds r0, r1, 0 + ldrb r2, [r4, 0x1A] + ands r0, r2 + cmp r0, 0 + beq _080AFF08 + ldr r0, [sp, 0x8] + strb r1, [r0] + ldrb r0, [r4, 0x1A] + ldr r1, [sp, 0x14] + strb r0, [r1] + movs r0, 0x7F + ldrb r2, [r4, 0x1A] + ands r0, r2 + strb r0, [r4, 0x1A] + b _080AFF08 + .pool +_080AFED4: + movs r0, 0xF + mov r1, r8 + ands r1, r0 + mov r8, r1 + ldrb r2, [r4, 0x9] + lsls r0, r2, 4 + add r0, r8 + ldr r1, [sp, 0xC] + strb r0, [r1] + movs r2, 0x80 + ldrb r0, [r4, 0x1A] + orrs r0, r2 + ldr r1, [sp, 0x14] + strb r0, [r1] + cmp r6, 0x1 + bne _080AFF08 + ldr r0, [sp, 0x8] + ldrb r1, [r0] + movs r0, 0x8 + ands r0, r1 + cmp r0, 0 + bne _080AFF08 + ldrb r0, [r4, 0x1A] + orrs r0, r2 + ldr r1, [sp, 0x14] + strb r0, [r1] +_080AFF08: + movs r0, 0 + strb r0, [r4, 0x1D] +_080AFF0C: + mov r6, r10 + mov r4, r9 + cmp r6, 0x4 + bgt _080AFF16 + b _080AFB0C +_080AFF16: + add sp, 0x1C + pop {r3-r5} + mov r8, r3 + mov r9, r4 + mov r10, r5 + pop {r4-r7} + pop {r0} + bx r0 + thumb_func_end CgbSound + + .align 2, 0 @ Don't pad with nop. diff --git a/asm/sprite.s b/asm/sprite.s index 06d87f0..284526c 100644 --- a/asm/sprite.s +++ b/asm/sprite.s @@ -5,8 +5,8 @@ .text - thumb_func_start sub_8004D8C -sub_8004D8C: + thumb_func_start ResetSprites +ResetSprites: push {r4,r5,lr} lsls r0, 24 lsrs r4, r0, 24 @@ -120,8 +120,8 @@ _08004E50: pop {r0} bx r0 .align 2, 0 -_08004E68: .4byte gUnknown_20266A8 -_08004E6C: .4byte gUnknown_2026E30 +_08004E68: .4byte gSpriteCount +_08004E6C: .4byte gCharMemCursor _08004E70: .4byte 0x06010000 _08004E74: .4byte gUnknown_203B074 _08004E78: .4byte gUnknown_20266B0 @@ -129,7 +129,7 @@ _08004E7C: .4byte gUnknown_20256A0 _08004E80: .4byte gUnknown_20262A8 _08004E84: .4byte gUnknown_2025EA8 _08004E88: .4byte 0x00000804 - thumb_func_end sub_8004D8C + thumb_func_end ResetSprites thumb_func_start sub_8004E8C sub_8004E8C: @@ -230,7 +230,7 @@ _08004F20: strh r0, [r1, 0x2] b _08004F86 .align 2, 0 -_08004F40: .4byte gUnknown_20266A8 +_08004F40: .4byte gSpriteCount _08004F44: .4byte 0x0000fcff _08004F48: .4byte 0x0000f1ff _08004F4C: .4byte 0x000003ff @@ -448,7 +448,7 @@ _080050D8: strh r0, [r2, 0x2] b _08005128 .align 2, 0 -_080050F4: .4byte gUnknown_20266A8 +_080050F4: .4byte gSpriteCount _080050F8: .4byte gUnknown_20262A8 _080050FC: ldrh r1, [r6] @@ -513,7 +513,7 @@ _08005168: bx r0 .align 2, 0 _08005174: .4byte gUnknown_2025EA8 -_08005178: .4byte gUnknown_20266A8 +_08005178: .4byte gSpriteCount _0800517C: .4byte gUnknown_20256A0 thumb_func_end AddSprite @@ -728,8 +728,8 @@ _080052F2: bx r0 .align 2, 0 _080052F8: .4byte gUnknown_203B074 -_080052FC: .4byte gUnknown_2026E30 -_08005300: .4byte gUnknown_2026E30 +_080052FC: .4byte gCharMemCursor +_08005300: .4byte gCharMemCursor thumb_func_end sub_80052BC thumb_func_start sub_8005304 @@ -790,7 +790,7 @@ sub_800533C: str r0, [r1] b _0800538E .align 2, 0 -_08005368: .4byte gUnknown_2026E30 +_08005368: .4byte gCharMemCursor _0800536C: .4byte 0x06010000 _08005370: cmp r6, 0 diff --git a/data/data_80B9BB8.s b/data/data_80B9BB8.s index 3b51eba..6c98e87 100644 --- a/data/data_80B9BB8.s +++ b/data/data_80B9BB8.s @@ -11966,42 +11966,3 @@ gUnknown_812F1F8: @ 812F1F8 gUnknown_813237C: @ 813237C .incbin "baserom.gba", 0x13237C, 0x13D610 - .global gUnknown_826F98C -gUnknown_826F98C: @ 826F98C - .incbin "baserom.gba", 0x26F98C, 0x90 - - .global gUnknown_826FA1C -gUnknown_826FA1C: @ 826FA1C - .incbin "baserom.gba", 0x26FA1C, 0xB4 - - .global gUnknown_826FAD0 -gUnknown_826FAD0: @ 826FAD0 - .incbin "baserom.gba", 0x26FAD0, 0x30 - - .global gUnknown_826FB00 -gUnknown_826FB00: @ 826FB00 - .incbin "baserom.gba", 0x26FB00, 0x18 - - .global gUnknown_826FB18 -gUnknown_826FB18: @ 826FB18 - .incbin "baserom.gba", 0x26FB18, 0x84 - - .global gUnknown_826FB9C -gUnknown_826FB9C: @ 826FB9C - .incbin "baserom.gba", 0x26FB9C, 0x18 - - .global gUnknown_826FBB4 -gUnknown_826FBB4: @ 826FBB4 - .incbin "baserom.gba", 0x26FBB4, 0x3C - - .global gUnknown_826FBF0 -gUnknown_826FBF0: @ 826FBF0 - .incbin "baserom.gba", 0x26FBF0, 0x10 - - .global gUnknown_826FC00 -gUnknown_826FC00: @ 826FC00 - .incbin "baserom.gba", 0x26FC00, 0x34 - - .global gUnknown_826FC34 -gUnknown_826FC34: @ 826FC34 - .incbin "baserom.gba", 0x26FC34, 0x30 diff --git a/data/sound_data.s b/data/sound_data.s index 043b59a..0987088 100644 --- a/data/sound_data.s +++ b/data/sound_data.s @@ -1,9 +1,9 @@ .section .rodata - .global gUnknown_9E8665C -gUnknown_9E8665C: @ 9E8665C + .global gMPlayTable +gMPlayTable: @ 9E8665C .incbin "baserom.gba", 0x1E8665C, 0x60 - .global gUnknown_9E866BC -gUnknown_9E866BC: @ 9E866BC + .global gSongTable +gSongTable: @ 9E866BC .incbin "baserom.gba", 0x1E866BC diff --git a/include/memory.h b/include/memory.h index 99b03e0..4b1e587 100644 --- a/include/memory.h +++ b/include/memory.h @@ -26,7 +26,7 @@ struct HeapFreeListElement struct HeapDescriptor { u32 unk0; - u32 unk4; + struct HeapDescriptor *parentHeap; struct HeapFreeListElement *freeList; s32 freeCount; u32 freeListLength; @@ -51,6 +51,6 @@ void MemoryCopy32(u32 *dest, u32 *src, s32 size); void InitHeapInternal(void); void DoInitHeap(struct HeapDescriptor *, struct HeapSettings *, struct HeapFreeListElement *, u32); -void InitSubHeap(struct HeapDescriptor *, struct HeapFreeListElement *, u32); +void InitSubHeap(struct HeapDescriptor *, struct HeapMemoryBlock *, u32); -#endif // GUARD_MEMORY_H \ No newline at end of file +#endif // GUARD_MEMORY_H diff --git a/ld_script.txt b/ld_script.txt index 304c9c8..214812f 100755 --- a/ld_script.txt +++ b/ld_script.txt @@ -1,5 +1,8 @@ ENTRY(Start) +gNumMusicPlayers = 8; +gMaxLines = 0; + SECTIONS { . = 0x2000000; @@ -8,23 +11,15 @@ SECTIONS { { ewram_start = .; INCLUDE "sym_ewram.ld" - . = ALIGN(4); src/agb_flash.o(.bss); - . = ALIGN(4); tools/agbcc/lib/libgcc.a:fp-bit.o(.bss); - . = ALIGN(4); tools/agbcc/lib/libgcc.a:dp-bit.o(.bss); - . = ALIGN(4); tools/agbcc/lib/libc.a:syscalls.o(.bss); . = ALIGN(16); INCLUDE "sym_ewram2.ld" - . = ALIGN(4); tools/agbcc/lib/libc.a:impure.o(.data); - . = ALIGN(4); tools/agbcc/lib/libc.a:locale.o(.data); - . = ALIGN(4); tools/agbcc/lib/libc.a:mallocr.o(.data); - . = ALIGN(4); gUnknown_203BC04 = .; . = 0x40000; } @@ -73,7 +68,11 @@ SECTIONS { asm/save.o(.text); src/save1.o(.text); asm/code_8012A18.o(.text); - asm/m4a.o(.text); + asm/m4a_1.o(.text); + src/m4a_2.o(.text); + asm/m4a_2.o(.text); + asm/m4a_3.o(.text); + src/m4a_4.o(.text); asm/syscall.o(.text); src/agb_flash.o(.text); src/agb_flash_1m.o(.text); @@ -138,23 +137,17 @@ SECTIONS { data/data.o(.rodata); src/file_system.o(.rodata); data/data_80B9BB8.o(.rodata); + src/m4a_tables.o(.rodata); src/agb_flash.o(.rodata); src/agb_flash_1m.o(.rodata); src/agb_flash_mx.o(.rodata); src/agb_flash_le.o(.rodata); - . = ALIGN(4); tools/agbcc/lib/libc.a:sprintf.o(.rodata); - . = ALIGN(4); tools/agbcc/lib/libc.a:vfprintf.o(.rodata); - . = ALIGN(4); tools/agbcc/lib/libc.a:dtoa.o(.rodata); - . = ALIGN(4); tools/agbcc/lib/libc.a:impure.o(.rodata); - . = ALIGN(4); tools/agbcc/lib/libc.a:locale.o(.rodata); - . = ALIGN(4); tools/agbcc/lib/libc.a:mprec.o(.rodata); - . = ALIGN(4); tools/agbcc/lib/libc.a:syscalls.o(.rodata); . = ALIGN(4); data/data_8270000.o(.rodata); @@ -169,7 +162,8 @@ SECTIONS { unk_code_end = .; } - unk_code_ram_end = unk_code_ram + (unk_code_end - unk_code); + unk_code_section_size = (unk_code_end - unk_code); + unk_code_ram_end = unk_code_ram + unk_code_section_size; end = unk_code_ram_end; . = 0x8300000; diff --git a/src/bg_palette_buffer.c b/src/bg_palette_buffer.c index 6301bfa..e36176d 100644 --- a/src/bg_palette_buffer.c +++ b/src/bg_palette_buffer.c @@ -18,7 +18,7 @@ void InitBGPaletteBuffer(void) u8* p; - ptr = gUnknown_20251F0; + ptr = gBGPaletteBuffer; i = 0x80; i <<= 2; @@ -30,12 +30,12 @@ void InitBGPaletteBuffer(void) paletteUsed = TRUE; - p = gUnknown_20251D0; + p = gBGPaletteUsed; p += 31; do *p-- = paletteUsed; - while ((s32) p >= (s32) &gUnknown_20251D0); + while ((s32) p >= (s32) &gBGPaletteUsed); } void SetBGPaletteBufferColorRGB(s32 index, u8 *RGBArray, s32 a3, u8 *a4) { diff --git a/src/m4a_2.c b/src/m4a_2.c new file mode 100644 index 0000000..176910e --- /dev/null +++ b/src/m4a_2.c @@ -0,0 +1,834 @@ +#include "gba/m4a_internal.h" + +extern char SoundMainRAM_Buffer[0x400]; + +extern struct SoundInfo gSoundInfo; + + +u32 MidiKeyToFreq(struct WaveData *wav, u8 key, u8 fineAdjust) +{ + u32 val1; + u32 val2; + u32 fineAdjustShifted = fineAdjust << 24; + + if (key > 178) + { + key = 178; + fineAdjustShifted = 255 << 24; + } + + val1 = gScaleTable[key]; + val1 = gFreqTable[val1 & 0xF] >> (val1 >> 4); + + val2 = gScaleTable[key + 1]; + val2 = gFreqTable[val2 & 0xF] >> (val2 >> 4); + + return umul3232H32(wav->freq, val1 + umul3232H32(val2 - val1, fineAdjustShifted)); +} + +void UnusedDummyFunc() +{ +} + +void MPlayContinue(struct MusicPlayerInfo *mplayInfo) +{ + if (mplayInfo->ident == ID_NUMBER) + { + mplayInfo->ident++; + mplayInfo->status &= ~MUSICPLAYER_STATUS_PAUSE; + mplayInfo->ident = ID_NUMBER; + } +} + +void MPlayFadeOut(struct MusicPlayerInfo *mplayInfo, u16 speed) +{ + if (mplayInfo->ident == ID_NUMBER) + { + mplayInfo->ident++; + mplayInfo->fadeOC = speed; + mplayInfo->fadeOI = speed; + mplayInfo->fadeOV = (64 << FADE_VOL_SHIFT); + mplayInfo->ident = ID_NUMBER; + } +} + +void m4aSoundInit(void) +{ + s32 i; + + CpuCopy32((void *)((s32)SoundMainRAM & ~1), SoundMainRAM_Buffer, sizeof(SoundMainRAM_Buffer)); + + SoundInit(&gSoundInfo); + MPlayExtender(gCgbChans); + m4aSoundMode(SOUND_MODE_DA_BIT_8 + | SOUND_MODE_FREQ_18157 + | (14 << SOUND_MODE_MASVOL_SHIFT) + | (5 << SOUND_MODE_MAXCHN_SHIFT)); + + for (i = 0; i < NUM_MUSIC_PLAYERS; i++) + { + struct MusicPlayerInfo *mplayInfo = gMPlayTable[i].info; + MPlayOpen(mplayInfo, gMPlayTable[i].track, gMPlayTable[i].unk_8); + mplayInfo->unk_B = gMPlayTable[i].unk_A; + mplayInfo->memAccArea = gMPlayMemAccArea; + } +} + +void m4aSoundMain(void) +{ + SoundMain(); +} + +void m4aSongNumStart(u16 n) +{ + const struct MusicPlayer *mplayTable = gMPlayTable; + const struct Song *songTable = gSongTable; + const struct Song *song = &songTable[n]; + const struct MusicPlayer *mplay = &mplayTable[song->ms]; + + MPlayStart(mplay->info, song->header); +} + +void m4aSongNumStartOrChange(u16 n) +{ + const struct MusicPlayer *mplayTable = gMPlayTable; + const struct Song *songTable = gSongTable; + const struct Song *song = &songTable[n]; + const struct MusicPlayer *mplay = &mplayTable[song->ms]; + + if (mplay->info->songHeader != song->header) + { + MPlayStart(mplay->info, song->header); + } + else + { + if ((mplay->info->status & MUSICPLAYER_STATUS_TRACK) == 0 + || (mplay->info->status & MUSICPLAYER_STATUS_PAUSE)) + { + MPlayStart(mplay->info, song->header); + } + } +} + +void m4aSongNumStartOrContinue(u16 n) +{ + const struct MusicPlayer *mplayTable = gMPlayTable; + const struct Song *songTable = gSongTable; + const struct Song *song = &songTable[n]; + const struct MusicPlayer *mplay = &mplayTable[song->ms]; + + if (mplay->info->songHeader != song->header) + MPlayStart(mplay->info, song->header); + else if ((mplay->info->status & MUSICPLAYER_STATUS_TRACK) == 0) + MPlayStart(mplay->info, song->header); + else if (mplay->info->status & MUSICPLAYER_STATUS_PAUSE) + MPlayContinue(mplay->info); +} + + +void m4aSongNumStop(u16 n) +{ + const struct MusicPlayer *mplayTable = gMPlayTable; + const struct Song *songTable = gSongTable; + const struct Song *song = &songTable[n]; + const struct MusicPlayer *mplay = &mplayTable[song->ms]; + + if (mplay->info->songHeader == song->header) + m4aMPlayStop(mplay->info); +} + +void m4aSongNumContinue(u16 n) +{ + const struct MusicPlayer *mplayTable = gMPlayTable; + const struct Song *songTable = gSongTable; + const struct Song *song = &songTable[n]; + const struct MusicPlayer *mplay = &mplayTable[song->ms]; + + if (mplay->info->songHeader == song->header) + MPlayContinue(mplay->info); +} + +void m4aMPlayAllStop(void) +{ + s32 i; + + for (i = 0; i < NUM_MUSIC_PLAYERS; i++) + m4aMPlayStop(gMPlayTable[i].info); +} + +void m4aMPlayContinue(struct MusicPlayerInfo *mplayInfo) +{ + MPlayContinue(mplayInfo); +} + +void m4aMPlayAllContinue(void) +{ + s32 i; + + for (i = 0; i < NUM_MUSIC_PLAYERS; i++) + MPlayContinue(gMPlayTable[i].info); +} + +void m4aMPlayFadeOut(struct MusicPlayerInfo *mplayInfo, u16 speed) +{ + MPlayFadeOut(mplayInfo, speed); +} + +void m4aMPlayFadeOutTemporarily(struct MusicPlayerInfo *mplayInfo, u16 speed) +{ + if (mplayInfo->ident == ID_NUMBER) + { + mplayInfo->ident++; + mplayInfo->fadeOC = speed; + mplayInfo->fadeOI = speed; + mplayInfo->fadeOV = (64 << FADE_VOL_SHIFT) | TEMPORARY_FADE; + mplayInfo->ident = ID_NUMBER; + } +} +void m4aMPlayFadeIn(struct MusicPlayerInfo *mplayInfo, u16 speed) +{ + if (mplayInfo->ident == ID_NUMBER) + { + mplayInfo->ident++; + mplayInfo->fadeOC = speed; + mplayInfo->fadeOI = speed; + mplayInfo->fadeOV = (0 << FADE_VOL_SHIFT) | FADE_IN; + mplayInfo->status &= ~MUSICPLAYER_STATUS_PAUSE; + mplayInfo->ident = ID_NUMBER; + } +} + +void m4aMPlayImmInit(struct MusicPlayerInfo *mplayInfo) +{ + s32 trackCount = mplayInfo->trackCount; + struct MusicPlayerTrack *track = mplayInfo->tracks; + + while (trackCount > 0) + { + if (track->flags & MPT_FLG_EXIST) + { + if (track->flags & MPT_FLG_START) + { + Clear64byte(track); + track->flags = MPT_FLG_EXIST; + track->bendRange = 2; + track->volX = 64; + track->lfoSpeed = 22; + track->tone.type = 1; + } + } + + trackCount--; + track++; + } +} + +void MPlayExtender(struct CgbChannel *cgbChans) +{ + struct SoundInfo *soundInfo; + u32 ident; + + REG_SOUNDCNT_X = SOUND_MASTER_ENABLE + | SOUND_4_ON + | SOUND_3_ON + | SOUND_2_ON + | SOUND_1_ON; + REG_SOUNDCNT_L = 0; // set master volume to zero + REG_NR12 = 0x8; + REG_NR22 = 0x8; + REG_NR42 = 0x8; + REG_NR14 = 0x80; + REG_NR24 = 0x80; + REG_NR44 = 0x80; + REG_NR30 = 0; + REG_NR50 = 0x77; + + soundInfo = SOUND_INFO_PTR; + + ident = soundInfo->ident; + + if (ident != ID_NUMBER) + return; + + soundInfo->ident++; + + gMPlayJumpTable[8] = ply_memacc; + gMPlayJumpTable[17] = ply_lfos; + gMPlayJumpTable[19] = ply_mod; + gMPlayJumpTable[28] = ply_xcmd; + gMPlayJumpTable[29] = ply_endtie; + gMPlayJumpTable[30] = SampleFreqSet; + gMPlayJumpTable[31] = TrackStop; + gMPlayJumpTable[32] = FadeOutBody; + gMPlayJumpTable[33] = TrkVolPitSet; + + soundInfo->cgbChans = (struct CgbChannel *)cgbChans; + soundInfo->CgbSound = CgbSound; + soundInfo->CgbOscOff = CgbOscOff; + soundInfo->MidiKeyToCgbFreq = MidiKeyToCgbFreq; + soundInfo->maxLines = MAX_LINES; + + CpuFill32(0, cgbChans, sizeof(struct CgbChannel) * 4); + + cgbChans[0].ty = 1; + cgbChans[0].panMask = 0x11; + cgbChans[1].ty = 2; + cgbChans[1].panMask = 0x22; + cgbChans[2].ty = 3; + cgbChans[2].panMask = 0x44; + cgbChans[3].ty = 4; + cgbChans[3].panMask = 0x88; + + soundInfo->ident = ident; +} + +void MusicPlayerJumpTableCopy(void) +{ + asm("swi 0x2A"); +} + +void ClearChain(void *x) +{ + void (*func)(void *) = *(&gMPlayJumpTable[34]); + func(x); +} + +void Clear64byte(void *x) +{ + void (*func)(void *) = *(&gMPlayJumpTable[35]); + func(x); +} + +void SoundInit(struct SoundInfo *soundInfo) +{ + soundInfo->ident = 0; + + if (REG_DMA1CNT & (DMA_REPEAT << 16)) + REG_DMA1CNT = ((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4; + + if (REG_DMA2CNT & (DMA_REPEAT << 16)) + REG_DMA2CNT = ((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4; + + REG_DMA1CNT_H = DMA_32BIT; + REG_DMA2CNT_H = DMA_32BIT; + REG_SOUNDCNT_X = SOUND_MASTER_ENABLE + | SOUND_4_ON + | SOUND_3_ON + | SOUND_2_ON + | SOUND_1_ON; + REG_SOUNDCNT_H = SOUND_B_FIFO_RESET | SOUND_B_TIMER_0 | SOUND_B_LEFT_OUTPUT + | SOUND_A_FIFO_RESET | SOUND_A_TIMER_0 | SOUND_A_RIGHT_OUTPUT + | SOUND_ALL_MIX_FULL; + REG_SOUNDBIAS_H = (REG_SOUNDBIAS_H & 0x3F) | 0x40; + + REG_DMA1SAD = (s32)soundInfo->pcmBuffer; + REG_DMA1DAD = (s32)®_FIFO_A; + REG_DMA2SAD = (s32)soundInfo->pcmBuffer + PCM_DMA_BUF_SIZE; + REG_DMA2DAD = (s32)®_FIFO_B; + + SOUND_INFO_PTR = soundInfo; + CpuFill32(0, soundInfo, sizeof(struct SoundInfo)); + + soundInfo->maxChans = 8; + soundInfo->masterVolume = 15; + soundInfo->plynote = (u32)ply_note; + soundInfo->CgbSound = DummyFunc; + soundInfo->CgbOscOff = (void (*)(u8))DummyFunc; + soundInfo->MidiKeyToCgbFreq = (u32 (*)(u8, u8, u8))DummyFunc; + soundInfo->ExtVolPit = (u32)DummyFunc; + + MPlayJumpTableCopy(gMPlayJumpTable); + + soundInfo->MPlayJumpTable = (u32)gMPlayJumpTable; + + SampleFreqSet(SOUND_MODE_FREQ_13379); + + soundInfo->ident = ID_NUMBER; +} + +void SampleFreqSet(u32 freq) +{ + struct SoundInfo *soundInfo = SOUND_INFO_PTR; + + freq = (freq & 0xF0000) >> 16; + soundInfo->freq = freq; + soundInfo->pcmSamplesPerVBlank = gPcmSamplesPerVBlankTable[freq - 1]; + soundInfo->pcmDmaPeriod = PCM_DMA_BUF_SIZE / soundInfo->pcmSamplesPerVBlank; + + // LCD refresh rate 59.7275Hz + soundInfo->pcmFreq = (597275 * soundInfo->pcmSamplesPerVBlank + 5000) / 10000; + + // CPU frequency 16.78Mhz + soundInfo->divFreq = (16777216 / soundInfo->pcmFreq + 1) >> 1; + + // Turn off timer 0. + REG_TM0CNT_H = 0; + + // cycles per LCD fresh 280896 + REG_TM0CNT_L = -(280896 / soundInfo->pcmSamplesPerVBlank); + + m4aSoundVSyncOn(); + + while (*(vu8 *)REG_ADDR_VCOUNT == 159) + ; + + while (*(vu8 *)REG_ADDR_VCOUNT != 159) + ; + + REG_TM0CNT_H = TIMER_ENABLE | TIMER_1CLK; +} + +void m4aSoundMode(u32 mode) +{ + struct SoundInfo *soundInfo = SOUND_INFO_PTR; + u32 temp; + + if (soundInfo->ident != ID_NUMBER) + return; + + soundInfo->ident++; + + temp = mode & (SOUND_MODE_REVERB_SET | SOUND_MODE_REVERB_VAL); + + if (temp) + soundInfo->reverb = temp & SOUND_MODE_REVERB_VAL; + + temp = mode & SOUND_MODE_MAXCHN; + + if (temp) + { + struct SoundChannel *chan; + + soundInfo->maxChans = temp >> SOUND_MODE_MAXCHN_SHIFT; + + temp = MAX_DIRECTSOUND_CHANNELS; + chan = &soundInfo->chans[0]; + + while (temp != 0) + { + chan->status = 0; + temp--; + chan++; + } + } + + temp = mode & SOUND_MODE_MASVOL; + + if (temp) + soundInfo->masterVolume = temp >> SOUND_MODE_MASVOL_SHIFT; + + temp = mode & SOUND_MODE_DA_BIT; + + if (temp) + { + temp = (temp & 0x300000) >> 14; + REG_SOUNDBIAS_H = (REG_SOUNDBIAS_H & 0x3F) | temp; + } + + temp = mode & SOUND_MODE_FREQ; + + if (temp) + { + m4aSoundVSyncOff(); + SampleFreqSet(temp); + } + + soundInfo->ident = ID_NUMBER; +} + +void SoundClear(void) +{ + struct SoundInfo *soundInfo = SOUND_INFO_PTR; + s32 i; + void *chan; + + if (soundInfo->ident != ID_NUMBER) + return; + + soundInfo->ident++; + + i = MAX_DIRECTSOUND_CHANNELS; + chan = &soundInfo->chans[0]; + + while (i > 0) + { + ((struct SoundChannel *)chan)->status = 0; + i--; + chan = (void *)((s32)chan + sizeof(struct SoundChannel)); + } + + chan = soundInfo->cgbChans; + + if (chan) + { + i = 1; + + while (i <= 4) + { + soundInfo->CgbOscOff(i); + ((struct CgbChannel *)chan)->sf = 0; + i++; + chan = (void *)((s32)chan + sizeof(struct CgbChannel)); + } + } + + soundInfo->ident = ID_NUMBER; +} + +void m4aSoundVSyncOff(void) +{ + struct SoundInfo *soundInfo = SOUND_INFO_PTR; + + if (soundInfo->ident >= ID_NUMBER && soundInfo->ident <= ID_NUMBER + 1) + { + soundInfo->ident += 10; + + if (REG_DMA1CNT & (DMA_REPEAT << 16)) + REG_DMA1CNT = ((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4; + + if (REG_DMA2CNT & (DMA_REPEAT << 16)) + REG_DMA2CNT = ((DMA_ENABLE | DMA_START_NOW | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 4; + + REG_DMA1CNT_H = DMA_32BIT; + REG_DMA2CNT_H = DMA_32BIT; + + CpuFill32(0, soundInfo->pcmBuffer, sizeof(soundInfo->pcmBuffer)); + } +} + +void m4aSoundVSyncOn(void) +{ + struct SoundInfo *soundInfo = SOUND_INFO_PTR; + u32 ident = soundInfo->ident; + + if (ident == ID_NUMBER) + return; + + REG_DMA1CNT_H = DMA_ENABLE | DMA_START_SPECIAL | DMA_32BIT | DMA_REPEAT; + REG_DMA2CNT_H = DMA_ENABLE | DMA_START_SPECIAL | DMA_32BIT | DMA_REPEAT; + + soundInfo->pcmDmaCounter = 0; + soundInfo->ident = ident - 10; +} + +void MPlayOpen(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *tracks, u8 trackCount) +{ + struct SoundInfo *soundInfo; + + if (trackCount == 0) + return; + + if (trackCount > MAX_MUSICPLAYER_TRACKS) + trackCount = MAX_MUSICPLAYER_TRACKS; + + soundInfo = SOUND_INFO_PTR; + + if (soundInfo->ident != ID_NUMBER) + return; + + soundInfo->ident++; + + Clear64byte(mplayInfo); + + mplayInfo->tracks = tracks; + mplayInfo->trackCount = trackCount; + mplayInfo->status = MUSICPLAYER_STATUS_PAUSE; + + while (trackCount != 0) + { + tracks->flags = 0; + trackCount--; + tracks++; + } + + if (soundInfo->func != 0) + { + mplayInfo->func = soundInfo->func; + mplayInfo->intp = soundInfo->intp; + soundInfo->func = 0; + } + + soundInfo->intp = (u32)mplayInfo; + soundInfo->func = (u32)MPlayMain; + soundInfo->ident = ID_NUMBER; + mplayInfo->ident = ID_NUMBER; +} + +void MPlayStart(struct MusicPlayerInfo *mplayInfo, struct SongHeader *songHeader) +{ + s32 i; + u8 unk_B; + struct MusicPlayerTrack *track; + + if (mplayInfo->ident != ID_NUMBER) + return; + + unk_B = mplayInfo->unk_B; + + if (!unk_B + || ((!mplayInfo->songHeader || !(mplayInfo->tracks[0].flags & MPT_FLG_START)) + && ((mplayInfo->status & MUSICPLAYER_STATUS_TRACK) == 0 + || (mplayInfo->status & MUSICPLAYER_STATUS_PAUSE))) + || (mplayInfo->priority <= songHeader->priority)) + { + mplayInfo->ident++; + mplayInfo->status = 0; + mplayInfo->songHeader = songHeader; + mplayInfo->tone = songHeader->tone; + mplayInfo->priority = songHeader->priority; + mplayInfo->clock = 0; + mplayInfo->tempoD = 150; + mplayInfo->tempoI = 150; + mplayInfo->tempoU = 0x100; + mplayInfo->tempoC = 0; + mplayInfo->fadeOI = 0; + + i = 0; + track = mplayInfo->tracks; + + while (i < songHeader->trackCount && i < mplayInfo->trackCount) + { + TrackStop(mplayInfo, track); + track->flags = MPT_FLG_EXIST | MPT_FLG_START; + track->chan = 0; + track->cmdPtr = songHeader->part[i]; + i++; + track++; + } + + while (i < mplayInfo->trackCount) + { + TrackStop(mplayInfo, track); + track->flags = 0; + i++; + track++; + } + + if (songHeader->reverb & 0x80) + m4aSoundMode(songHeader->reverb); + + mplayInfo->ident = ID_NUMBER; + } +} + +void m4aMPlayStop(struct MusicPlayerInfo *mplayInfo) +{ + s32 i; + struct MusicPlayerTrack *track; + + if (mplayInfo->ident != ID_NUMBER) + return; + + mplayInfo->ident++; + mplayInfo->status |= MUSICPLAYER_STATUS_PAUSE; + + i = mplayInfo->trackCount; + track = mplayInfo->tracks; + + while (i > 0) + { + TrackStop(mplayInfo, track); + i--; + track++; + } + + mplayInfo->ident = ID_NUMBER; +} + +void FadeOutBody(struct MusicPlayerInfo *mplayInfo) +{ + s32 i; + struct MusicPlayerTrack *track; + u16 fadeOI = mplayInfo->fadeOI; + register u32 temp asm("r3"); + register u16 mask asm("r2"); + + if (fadeOI == 0) + return; + + mplayInfo->fadeOC--; + + temp = 0xFFFF; + mask = temp; + + if (mplayInfo->fadeOC != 0) + return; + + mplayInfo->fadeOC = fadeOI; + + if (mplayInfo->fadeOV & FADE_IN) + { + mplayInfo->fadeOV += (4 << FADE_VOL_SHIFT); + + if ((u16)(mplayInfo->fadeOV & mask) >= (64 << FADE_VOL_SHIFT)) + { + mplayInfo->fadeOV = (64 << FADE_VOL_SHIFT); + mplayInfo->fadeOI = 0; + } + } + else + { + mplayInfo->fadeOV -= (4 << FADE_VOL_SHIFT); + + if ((s16)(mplayInfo->fadeOV & mask) <= 0) + { + i = mplayInfo->trackCount; + track = mplayInfo->tracks; + + while (i > 0) + { + register u32 fadeOV asm("r7"); + u32 val; + + TrackStop(mplayInfo, track); + + val = TEMPORARY_FADE; + fadeOV = mplayInfo->fadeOV; + val &= fadeOV; + + if (!val) + track->flags = 0; + + i--; + track++; + } + + if (mplayInfo->fadeOV & TEMPORARY_FADE) + mplayInfo->status |= MUSICPLAYER_STATUS_PAUSE; + else + mplayInfo->status = MUSICPLAYER_STATUS_PAUSE; + + mplayInfo->fadeOI = 0; + return; + } + } + + i = mplayInfo->trackCount; + track = mplayInfo->tracks; + + while (i > 0) + { + if (track->flags & MPT_FLG_EXIST) + { + track->volX = (mplayInfo->fadeOV >> FADE_VOL_SHIFT); + track->flags |= MPT_FLG_VOLCHG; + } + + i--; + track++; + } +} + +void TrkVolPitSet(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track) +{ + if (track->flags & MPT_FLG_VOLSET) + { + s32 x; + s32 y; + + x = (u32)(track->vol * track->volX) >> 5; + + if (track->modT == 1) + x = (u32)(x * (track->modM + 128)) >> 7; + + y = 2 * track->pan + track->panX; + + if (track->modT == 2) + y += track->modM; + + if (y < -128) + y = -128; + else if (y > 127) + y = 127; + + track->volMR = (u32)((y + 128) * x) >> 8; + track->volML = (u32)((127 - y) * x) >> 8; + } + + if (track->flags & MPT_FLG_PITSET) + { + s32 bend = track->bend * track->bendRange; + register s32 x asm("r1") = track->tune; + x += bend; + x *= 4; + x += (track->keyShift << 8); + x += (track->keyShiftX << 8); + x += track->pitX; + + if (track->modT == 0) + x += 16 * track->modM; + + track->keyM = x >> 8; + track->pitM = x; + } + + track->flags &= ~(MPT_FLG_PITSET | MPT_FLG_VOLSET); +} + +u32 MidiKeyToCgbFreq(u8 chanNum, u8 key, u8 fineAdjust) +{ + if (chanNum == 4) + { + if (key <= 20) + { + key = 0; + } + else + { + key -= 21; + if (key > 59) + key = 59; + } + + return gNoiseTable[key]; + } + else + { + s32 val1; + s32 val2; + + if (key <= 35) + { + fineAdjust = 0; + key = 0; + } + else + { + key -= 36; + if (key > 130) + { + key = 130; + fineAdjust = 255; + } + } + + val1 = gCgbScaleTable[key]; + val1 = gCgbFreqTable[val1 & 0xF] >> (val1 >> 4); + + val2 = gCgbScaleTable[key + 1]; + val2 = gCgbFreqTable[val2 & 0xF] >> (val2 >> 4); + + return val1 + ((fineAdjust * (val2 - val1)) >> 8) + 2048; + } +} + +void CgbOscOff(u8 chanNum) +{ + switch (chanNum) + { + case 1: + REG_NR12 = 8; + REG_NR14 = 0x80; + break; + case 2: + REG_NR22 = 8; + REG_NR24 = 0x80; + break; + case 3: + REG_NR30 = 0; + break; + default: + REG_NR42 = 8; + REG_NR44 = 0x80; + } +} diff --git a/src/m4a_4.c b/src/m4a_4.c new file mode 100644 index 0000000..595ea5a --- /dev/null +++ b/src/m4a_4.c @@ -0,0 +1,384 @@ +#include "gba/m4a_internal.h" + +void m4aMPlayTempoControl(struct MusicPlayerInfo *mplayInfo, u16 tempo) +{ + if (mplayInfo->ident == ID_NUMBER) + { + mplayInfo->ident++; + mplayInfo->tempoU = tempo; + mplayInfo->tempoI = (mplayInfo->tempoD * mplayInfo->tempoU) >> 8; + mplayInfo->ident = ID_NUMBER; + } +} + +void m4aMPlayVolumeControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u16 volume) +{ + s32 i; + u32 bit; + struct MusicPlayerTrack *track; + + if (mplayInfo->ident != ID_NUMBER) + return; + + mplayInfo->ident++; + + i = mplayInfo->trackCount; + track = mplayInfo->tracks; + bit = 1; + + while (i > 0) + { + if (trackBits & bit) + { + if (track->flags & MPT_FLG_EXIST) + { + track->volX = volume / 4; + track->flags |= MPT_FLG_VOLCHG; + } + } + + i--; + track++; + bit <<= 1; + } + + mplayInfo->ident = ID_NUMBER; +} + +void m4aMPlayPitchControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, s16 pitch) +{ + s32 i; + u32 bit; + struct MusicPlayerTrack *track; + + if (mplayInfo->ident != ID_NUMBER) + return; + + mplayInfo->ident++; + + i = mplayInfo->trackCount; + track = mplayInfo->tracks; + bit = 1; + + while (i > 0) + { + if (trackBits & bit) + { + if (track->flags & MPT_FLG_EXIST) + { + track->keyShiftX = pitch >> 8; + track->pitX = pitch; + track->flags |= MPT_FLG_PITCHG; + } + } + + i--; + track++; + bit <<= 1; + } + + mplayInfo->ident = ID_NUMBER; +} + +void m4aMPlayPanpotControl(struct MusicPlayerInfo *mplayInfo, u16 trackBits, s8 pan) +{ + s32 i; + u32 bit; + struct MusicPlayerTrack *track; + + if (mplayInfo->ident != ID_NUMBER) + return; + + mplayInfo->ident++; + + i = mplayInfo->trackCount; + track = mplayInfo->tracks; + bit = 1; + + while (i > 0) + { + if (trackBits & bit) + { + if (track->flags & MPT_FLG_EXIST) + { + track->panX = pan; + track->flags |= MPT_FLG_VOLCHG; + } + } + + i--; + track++; + bit <<= 1; + } + + mplayInfo->ident = ID_NUMBER; +} + +void ClearModM(struct MusicPlayerTrack *track) +{ + track->lfoSpeedC = 0; + track->modM = 0; + + if (track->modT == 0) + track->flags |= MPT_FLG_PITCHG; + else + track->flags |= MPT_FLG_VOLCHG; +} + +void m4aMPlayModDepthSet(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u8 modDepth) +{ + s32 i; + u32 bit; + struct MusicPlayerTrack *track; + + if (mplayInfo->ident != ID_NUMBER) + return; + + mplayInfo->ident++; + + i = mplayInfo->trackCount; + track = mplayInfo->tracks; + bit = 1; + + while (i > 0) + { + if (trackBits & bit) + { + if (track->flags & MPT_FLG_EXIST) + { + track->mod = modDepth; + + if (!track->mod) + ClearModM(track); + } + } + + i--; + track++; + bit <<= 1; + } + + mplayInfo->ident = ID_NUMBER; +} + +void m4aMPlayLFOSpeedSet(struct MusicPlayerInfo *mplayInfo, u16 trackBits, u8 lfoSpeed) +{ + s32 i; + u32 bit; + struct MusicPlayerTrack *track; + + if (mplayInfo->ident != ID_NUMBER) + return; + + mplayInfo->ident++; + + i = mplayInfo->trackCount; + track = mplayInfo->tracks; + bit = 1; + + while (i > 0) + { + if (trackBits & bit) + { + if (track->flags & MPT_FLG_EXIST) + { + track->lfoSpeed = lfoSpeed; + + if (!track->lfoSpeed) + ClearModM(track); + } + } + + i--; + track++; + bit <<= 1; + } + + mplayInfo->ident = ID_NUMBER; +} + +#define MEMACC_COND_JUMP(cond) \ +if (cond) \ + goto cond_true; \ +else \ + goto cond_false; \ + +void ply_memacc(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track) +{ + u32 op; + u8 *addr; + u8 data; + + op = *track->cmdPtr; + track->cmdPtr++; + + addr = mplayInfo->memAccArea + *track->cmdPtr; + track->cmdPtr++; + + data = *track->cmdPtr; + track->cmdPtr++; + + switch (op) + { + case 0: + *addr = data; + return; + case 1: + *addr += data; + return; + case 2: + *addr -= data; + return; + case 3: + *addr = mplayInfo->memAccArea[data]; + return; + case 4: + *addr += mplayInfo->memAccArea[data]; + return; + case 5: + *addr -= mplayInfo->memAccArea[data]; + return; + case 6: + MEMACC_COND_JUMP(*addr == data) + return; + case 7: + MEMACC_COND_JUMP(*addr != data) + return; + case 8: + MEMACC_COND_JUMP(*addr > data) + return; + case 9: + MEMACC_COND_JUMP(*addr >= data) + return; + case 10: + MEMACC_COND_JUMP(*addr <= data) + return; + case 11: + MEMACC_COND_JUMP(*addr < data) + return; + case 12: + MEMACC_COND_JUMP(*addr == mplayInfo->memAccArea[data]) + return; + case 13: + MEMACC_COND_JUMP(*addr != mplayInfo->memAccArea[data]) + return; + case 14: + MEMACC_COND_JUMP(*addr > mplayInfo->memAccArea[data]) + return; + case 15: + MEMACC_COND_JUMP(*addr >= mplayInfo->memAccArea[data]) + return; + case 16: + MEMACC_COND_JUMP(*addr <= mplayInfo->memAccArea[data]) + return; + case 17: + MEMACC_COND_JUMP(*addr < mplayInfo->memAccArea[data]) + return; + default: + return; + } + +cond_true: + { + void (*func)(struct MusicPlayerInfo *, struct MusicPlayerTrack *) = *(&gMPlayJumpTable[1]); + func(mplayInfo, track); + return; + } + +cond_false: + track->cmdPtr += 4; +} + +void ply_xcmd(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track) +{ + u32 n = *track->cmdPtr; + track->cmdPtr++; + + gXcmdTable[n](mplayInfo, track); +} + +void ply_xxx(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track) +{ + void (*func)(struct MusicPlayerInfo *, struct MusicPlayerTrack *) = *(&gMPlayJumpTable[0]); + func(mplayInfo, track); +} + +#define READ_XCMD_BYTE(var, n) \ +{ \ + u32 byte = track->cmdPtr[(n)]; \ + byte <<= n * 8; \ + (var) &= ~(0xFF << (n * 8)); \ + (var) |= byte; \ +} + +void ply_xwave(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track) +{ + u32 wav; + + READ_XCMD_BYTE(wav, 0) // UB: uninitialized variable + READ_XCMD_BYTE(wav, 1) + READ_XCMD_BYTE(wav, 2) + READ_XCMD_BYTE(wav, 3) + + track->tone.wav = (struct WaveData *)wav; + track->cmdPtr += 4; +} + +void ply_xtype(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track) +{ + track->tone.type = *track->cmdPtr; + track->cmdPtr++; +} + +void ply_xatta(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track) +{ + track->tone.attack = *track->cmdPtr; + track->cmdPtr++; +} + +void ply_xdeca(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track) +{ + track->tone.decay = *track->cmdPtr; + track->cmdPtr++; +} + +void ply_xsust(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track) +{ + track->tone.sustain = *track->cmdPtr; + track->cmdPtr++; +} + +void ply_xrele(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track) +{ + track->tone.release = *track->cmdPtr; + track->cmdPtr++; +} + +void ply_xiecv(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track) +{ + track->echoVolume = *track->cmdPtr; + track->cmdPtr++; +} + +void ply_xiecl(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track) +{ + track->echoLength = *track->cmdPtr; + track->cmdPtr++; +} + +void ply_xleng(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track) +{ + track->tone.length = *track->cmdPtr; + track->cmdPtr++; +} + +void ply_xswee(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track) +{ + track->tone.pan_sweep = *track->cmdPtr; + track->cmdPtr++; +} + +void DummyFunc() +{ + ; +} diff --git a/src/m4a_tables.c b/src/m4a_tables.c new file mode 100644 index 0000000..fd289a6 --- /dev/null +++ b/src/m4a_tables.c @@ -0,0 +1,223 @@ +#include "gba/m4a_internal.h" + +// Some of these functions have different signatures, so we need to make this +// an array of void pointers or a struct. It's simpler to just make it an array +// for now. +void * const gMPlayJumpTableTemplate[] = +{ + ply_fine, + ply_goto, + ply_patt, + ply_pend, + ply_rept, + ply_fine, + ply_fine, + ply_fine, + ply_fine, + ply_prio, + ply_tempo, + ply_keysh, + ply_voice, + ply_vol, + ply_pan, + ply_bend, + ply_bendr, + ply_lfos, + ply_lfodl, + ply_mod, + ply_modt, + ply_fine, + ply_fine, + ply_tune, + ply_fine, + ply_fine, + ply_fine, + ply_port, + ply_fine, + ply_endtie, + SampleFreqSet, + TrackStop, + FadeOutBody, + TrkVolPitSet, + RealClearChain, + SoundMainBTM, +}; + +const u8 gScaleTable[] = +{ + 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, + 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, + 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, + 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, +}; + +const u32 gFreqTable[] = +{ + 2147483648u, + 2275179671u, + 2410468894u, + 2553802834u, + 2705659852u, + 2866546760u, + 3037000500u, + 3217589947u, + 3408917802u, + 3611622603u, + 3826380858u, + 4053909305u, +}; + +const u16 gPcmSamplesPerVBlankTable[] = +{ + 96, + 132, + 176, + 224, + 264, + 304, + 352, + 448, + 528, + 608, + 672, + 704, +}; + +const u8 gCgbScaleTable[] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, + 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, +}; + +const s16 gCgbFreqTable[] = +{ + -2004, + -1891, + -1785, + -1685, + -1591, + -1501, + -1417, + -1337, + -1262, + -1192, + -1125, + -1062, +}; + +const u8 gNoiseTable[] = +{ + 0xD7, 0xD6, 0xD5, 0xD4, + 0xC7, 0xC6, 0xC5, 0xC4, + 0xB7, 0xB6, 0xB5, 0xB4, + 0xA7, 0xA6, 0xA5, 0xA4, + 0x97, 0x96, 0x95, 0x94, + 0x87, 0x86, 0x85, 0x84, + 0x77, 0x76, 0x75, 0x74, + 0x67, 0x66, 0x65, 0x64, + 0x57, 0x56, 0x55, 0x54, + 0x47, 0x46, 0x45, 0x44, + 0x37, 0x36, 0x35, 0x34, + 0x27, 0x26, 0x25, 0x24, + 0x17, 0x16, 0x15, 0x14, + 0x07, 0x06, 0x05, 0x04, + 0x03, 0x02, 0x01, 0x00, +}; + +const u8 gCgb3Vol[] = +{ + 0x00, 0x00, + 0x60, 0x60, 0x60, 0x60, + 0x40, 0x40, 0x40, 0x40, + 0x80, 0x80, 0x80, 0x80, + 0x20, 0x20, +}; + +const u8 gClockTable[] = +{ + 0x00, + 0x01, + 0x02, + 0x03, + 0x04, + 0x05, + 0x06, + 0x07, + 0x08, + 0x09, + 0x0A, + 0x0B, + 0x0C, + 0x0D, + 0x0E, + 0x0F, + 0x10, + 0x11, + 0x12, + 0x13, + 0x14, + 0x15, + 0x16, + 0x17, + 0x18, + 0x1C, + 0x1E, + 0x20, + 0x24, + 0x28, + 0x2A, + 0x2C, + 0x30, + 0x34, + 0x36, + 0x38, + 0x3C, + 0x40, + 0x42, + 0x44, + 0x48, + 0x4C, + 0x4E, + 0x50, + 0x54, + 0x58, + 0x5A, + 0x5C, + 0x60, +}; + +const XcmdFunc gXcmdTable[] = +{ + ply_xxx, + ply_xwave, + ply_xtype, + ply_xxx, + ply_xatta, + ply_xdeca, + ply_xsust, + ply_xrele, + ply_xiecv, + ply_xiecl, + ply_xleng, + ply_xswee +}; diff --git a/src/memory.c b/src/memory.c index 0d282d5..05c89a2 100644 --- a/src/memory.c +++ b/src/memory.c @@ -113,7 +113,7 @@ void DoInitHeap(struct HeapDescriptor *descriptor, struct HeapSettings *settings descriptor->start = settings->start; descriptor->size = aligned_size; descriptor->unk0 = 2; - descriptor->unk4 = 0; + descriptor->parentHeap = NULL; descriptor->freeList = freeList; descriptor->freeCount = 1; descriptor->freeListLength = freeListLength; @@ -126,7 +126,7 @@ void DoInitHeap(struct HeapDescriptor *descriptor, struct HeapSettings *settings freeList->grp = 0; } -void InitSubHeap(struct HeapDescriptor *parentHeap, struct HeapFreeListElement *start, u32 freeListMax) +void InitSubHeap(struct HeapDescriptor *parentHeap, struct HeapMemoryBlock *block, u32 freeListMax) { u32 freeListSize; u32 aligned_size; @@ -137,9 +137,9 @@ void InitSubHeap(struct HeapDescriptor *parentHeap, struct HeapFreeListElement * freeListSize = freeListMax * 3; alignment = ~3; freeListSize *= 8; - aligned_size = (start->atb - freeListSize) & alignment; //possible struct misalignment? - freeList = (struct HeapFreeListElement *)start->unk_atb; - settings.start = &((u8 *)start->unk_atb)[freeListSize]; + aligned_size = (block->size - freeListSize) & alignment; + freeList = (struct HeapFreeListElement *)block->start; + settings.start = &((u8 *)block->start)[freeListSize]; settings.size = aligned_size; DoInitHeap(parentHeap, &settings, freeList, freeListMax); -} \ No newline at end of file +} diff --git a/src/save1.c b/src/save1.c index 94f9c2b..b7de6c6 100644 --- a/src/save1.c +++ b/src/save1.c @@ -10,4 +10,4 @@ void sub_80129FC() MemoryFree(gUnknown_203B194); gUnknown_203B194 = NULL; } -} \ No newline at end of file +} diff --git a/src/sprite.c b/src/sprite.c index 41a2a96..d741fce 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -1,10 +1,10 @@ #include "global.h" -void sub_8004D8C(u32); +void ResetSprites(bool32); void SetSavingIconCoords(u32); void InitSprites(void) { - sub_8004D8C(1); + ResetSprites(1); SetSavingIconCoords(0); -} \ No newline at end of file +} diff --git a/sym_ewram.txt b/sym_ewram.txt index 517dfc5..a627dcf 100644 --- a/sym_ewram.txt +++ b/sym_ewram.txt @@ -6,7 +6,7 @@ gUnknown_20008F0 = .; /* 20008F0 */ gUnknown_2000970 = .; /* 2000970 */ . += 0xC0; -gUnknown_2000A30 = .; /* 2000A30 */ +gMPlayMemAccArea = .; /* 2000A30 */ . += 0x50; gUnknown_2000A80 = .; /* 2000A80 */ @@ -82,13 +82,13 @@ gUnknown_2025EA8 = .; /* 2025EA8 */ gUnknown_20262A8 = .; /* 20262A8 */ . += 0x400; -gUnknown_20266A8 = .; /* 20266A8 */ +gSpriteCount = .; /* 20266A8 */ . += 0x8; gUnknown_20266B0 = .; /* 20266B0 */ . += 0x780; -gUnknown_2026E30 = .; /* 2026E30 */ +gCharMemCursor = .; /* 2026E30 */ . += 0x8; gUnknown_2026E38 = .; /* 2026E38 */ @@ -519,7 +519,10 @@ gDungeonNameBannerPalette = .; /* 202EC88 */ . += 0x4; gDungeonNameBannerFontFile = .; /* 202EC8C */ - . += 0x8; + . += 0x4; + +gDungeonNameBannerFont = .; /* 202EC90 */ + . += 0x4; gUnknown_202EC94 = .; /* 202EC94 */ . += 0x4; diff --git a/sym_ewram2.txt b/sym_ewram2.txt index 6e71482..0f91946 100644 --- a/sym_ewram2.txt +++ b/sym_ewram2.txt @@ -1,13 +1,10 @@ . = ALIGN(2); -gUnknown_2039ED0 = .; /* 2039ED0 */ +gSoundInfo = .; /* 2039ED0 */ . += 0xFB0; -gUnknown_203AE80 = .; /* 203AE80 */ - . += 0x4; - -gUnknown_203AE84 = .; /* 203AE84 */ - . += 0x84; +gMPlayJumpTable = .; /* 203AE80 */ + . += 0x88; gUnknown_203AF08 = .; /* 203AF08 */ . += 0x4; @@ -15,7 +12,7 @@ gUnknown_203AF08 = .; /* 203AF08 */ gUnknown_203AF0C = .; /* 203AF0C */ . += 0x4; -gUnknown_203AF10 = .; /* 203AF10 */ +gCgbChans = .; /* 203AF10 */ . += 0x100; gFlashTimeoutFlag = .; /* 203B010 */ -- cgit v1.2.3 From ff37bfefe07cdbb6e087e0123576a1b338145dce Mon Sep 17 00:00:00 2001 From: nullableVoidPtr <30564701+nullableVoidPtr@users.noreply.github.com> Date: Tue, 20 Nov 2018 19:49:35 +0800 Subject: Dump gMPlayTable and gSongTable --- data/sound_data.s | 11 +- include/macros/m4a.inc | 13 + sound/music_player_table.inc | 11 + sound/song_table.inc | 943 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 972 insertions(+), 6 deletions(-) create mode 100644 include/macros/m4a.inc create mode 100644 sound/music_player_table.inc create mode 100644 sound/song_table.inc diff --git a/data/sound_data.s b/data/sound_data.s index 0987088..8ac86f7 100644 --- a/data/sound_data.s +++ b/data/sound_data.s @@ -1,9 +1,8 @@ .section .rodata - .global gMPlayTable -gMPlayTable: @ 9E8665C - .incbin "baserom.gba", 0x1E8665C, 0x60 + .include "include/macros/m4a.inc" - .global gSongTable -gSongTable: @ 9E866BC - .incbin "baserom.gba", 0x1E866BC + .include "sound/music_player_table.inc" + .include "sound/song_table.inc" + + .incbin "baserom.gba", 0x1E8841C diff --git a/include/macros/m4a.inc b/include/macros/m4a.inc new file mode 100644 index 0000000..6c5abc0 --- /dev/null +++ b/include/macros/m4a.inc @@ -0,0 +1,13 @@ + .macro song label, music_player, unknown + .4byte \label + .2byte \music_player + .2byte \unknown + .endm + + .macro music_player info_struct, track_struct, unknown_1, unknown_2 + .4byte \info_struct + .4byte \track_struct + .byte \unknown_1 + .space 1 + .2byte \unknown_2 + .endm diff --git a/sound/music_player_table.inc b/sound/music_player_table.inc new file mode 100644 index 0000000..f21c434 --- /dev/null +++ b/sound/music_player_table.inc @@ -0,0 +1,11 @@ + .align 2 + .global gMPlayTable +gMPlayTable: @ 9E8665C + music_player 0x20008F0, 0x2000000, 12, 0 + music_player 0x2000970, 0x20003C0, 6, 0 + music_player 0x20009B0, 0x20005A0, 1, 0 + music_player 0x2000A40, 0x20005F0, 1, 0 + music_player 0x20009F0, 0x2000640, 2, 0 + music_player 0x2000870, 0x20006E0, 2, 0 + music_player 0x20008B0, 0x2000780, 2, 0 + music_player 0x2000930, 0x2000820, 1, 0 diff --git a/sound/song_table.inc b/sound/song_table.inc new file mode 100644 index 0000000..86488a3 --- /dev/null +++ b/sound/song_table.inc @@ -0,0 +1,943 @@ + .align 2 + .global gSongTable +gSongTable: @ 9E866BC + song 0x9F5185C, 0, 0 + song 0x9F5218C, 0, 0 + song 0x9F52D24, 0, 0 + song 0x9F53728, 0, 0 + song 0x9F53B10, 0, 0 + song 0x9F54734, 0, 0 + song 0x9F5506C, 0, 0 + song 0x9F56720, 0, 0 + song 0x9F56B8C, 0, 0 + song 0x9F57254, 0, 0 + song 0x9F57C58, 0, 0 + song 0x9F588BC, 0, 0 + song 0x9F59210, 0, 0 + song 0x9F59F68, 0, 0 + song 0x9F5B598, 0, 0 + song 0x9F5CF8C, 0, 0 + song 0x9F5DE00, 0, 0 + song 0x9F5E8E0, 0, 0 + song 0x9F5F9C8, 0, 0 + song 0x9F60510, 0, 0 + song 0x9F61EA8, 0, 0 + song 0x9F63224, 0, 0 + song 0x9F666B8, 0, 0 + song 0x9F678E8, 0, 0 + song 0x9F698F0, 0, 0 + song 0x9F6AED8, 0, 0 + song 0x9F6CDDC, 0, 0 + song 0x9F6FBF8, 0, 0 + song 0x9F71EC8, 0, 0 + song 0x9F73E7C, 0, 0 + song 0x9F75DD0, 0, 0 + song 0x9F77848, 0, 0 + song 0x9F79C08, 0, 0 + song 0x9F7A6EC, 0, 0 + song 0x9F7B9BC, 0, 0 + song 0x9F7D470, 0, 0 + song 0x9F7DD20, 0, 0 + song 0x9F7FA74, 0, 0 + song 0x9F7FC3C, 0, 0 + song 0x9F81164, 0, 0 + song 0x9F8192C, 0, 0 + song 0x9F82150, 0, 0 + song 0x9F832D4, 0, 0 + song 0x9F83A88, 0, 0 + song 0x9F86808, 0, 0 + song 0x9F871BC, 0, 0 + song 0x9F87678, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9F876AC, 0, 0 + song 0x9F877DC, 0, 0 + song 0x9F878FC, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9F88B90, 0, 0 + song 0x9F89B38, 0, 0 + song 0x9F8AE6C, 0, 0 + song 0x9F8C1A0, 0, 0 + song 0x9F8DCFC, 0, 0 + song 0x9F8F384, 0, 0 + song 0x9F8FD4C, 0, 0 + song 0x9F90F70, 0, 0 + song 0x9F93C60, 0, 0 + song 0x9F94FBC, 0, 0 + song 0x9F96190, 0, 0 + song 0x9F976A0, 0, 0 + song 0x9F97C6C, 0, 0 + song 0x9F992BC, 0, 0 + song 0x9F9961C, 0, 0 + song 0x9F9B188, 0, 0 + song 0x9F9BA2C, 0, 0 + song 0x9F9CC24, 0, 0 + song 0x9F9DDA0, 0, 0 + song 0x9F9ECF4, 0, 0 + song 0x9FA06B0, 0, 0 + song 0x9FA0F50, 0, 0 + song 0x9FA3AA0, 0, 0 + song 0x9FA5254, 0, 0 + song 0x9FA79C8, 0, 0 + song 0x9FA8760, 0, 0 + song 0x9FA9C7C, 0, 0 + song 0x9FAB3D0, 0, 0 + song 0x9FAC714, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9FAC838, 1, 1 + song 0x9FAC944, 1, 1 + song 0x9FAC9C4, 1, 1 + song 0x9FACA5C, 1, 1 + song 0x9FACB10, 1, 1 + song 0x9FACC04, 1, 1 + song 0x9FACCBC, 1, 1 + song 0x9FACD28, 1, 1 + song 0x9FACE3C, 1, 1 + song 0x9E8841C, 0, 0 + song 0x9FACF88, 1, 1 + song 0x9FAD054, 1, 1 + song 0x9FAD140, 1, 1 + song 0x9FAD1DC, 1, 1 + song 0x9FAD270, 1, 1 + song 0x9FAD394, 1, 1 + song 0x9FAD494, 1, 1 + song 0x9FAD694, 1, 1 + song 0x9FAD784, 1, 1 + song 0x9FAD91C, 1, 1 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9FAD938, 2, 2 + song 0x9FAD95C, 2, 2 + song 0x9FAD984, 2, 2 + song 0x9FAD9A0, 2, 2 + song 0x9FAD9C0, 4, 4 + song 0x9FAD9E4, 2, 2 + song 0x9FADA08, 2, 2 + song 0x9FADA3C, 2, 2 + song 0x9FADA6C, 2, 2 + song 0x9FADA9C, 2, 2 + song 0x9FADAC0, 2, 2 + song 0x9FADB14, 6, 6 + song 0x9FADB20, 6, 6 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9FADB58, 2, 2 + song 0x9FADB94, 2, 2 + song 0x9FADBB4, 5, 5 + song 0x9FADBDC, 3, 3 + song 0x9E8841C, 0, 0 + song 0x9FADBE8, 3, 3 + song 0x9FADC30, 3, 3 + song 0x9FADCB8, 2, 2 + song 0x9FADD38, 2, 2 + song 0x9FADD8C, 2, 2 + song 0x9FADDB4, 5, 5 + song 0x9FADDDC, 5, 5 + song 0x9FADE20, 2, 2 + song 0x9FADE64, 2, 2 + song 0x9FADE88, 5, 5 + song 0x9FADF14, 3, 3 + song 0x9FADF34, 3, 3 + song 0x9FADF60, 3, 3 + song 0x9FADF80, 3, 3 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9FADFD8, 2, 2 + song 0x9FAE038, 4, 4 + song 0x9FAE184, 3, 3 + song 0x9FAE1C4, 2, 2 + song 0x9FAE250, 3, 3 + song 0x9FAE2A4, 2, 2 + song 0x9FAE2C8, 3, 3 + song 0x9FAE2FC, 2, 2 + song 0x9FAE328, 3, 3 + song 0x9FAE358, 3, 3 + song 0x9FAE380, 3, 3 + song 0x9FAE3A8, 2, 2 + song 0x9FAE3D4, 3, 3 + song 0x9FAE3E0, 2, 2 + song 0x9FAE408, 3, 3 + song 0x9FAE43C, 3, 3 + song 0x9FAE468, 3, 3 + song 0x9FAE49C, 2, 2 + song 0x9FAE4C4, 3, 3 + song 0x9FAE4EC, 4, 4 + song 0x9FAE968, 5, 5 + song 0x9FAEA48, 5, 5 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9FAEA78, 5, 5 + song 0x9FAEB64, 5, 5 + song 0x9FAEB8C, 5, 5 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9FAEBB8, 3, 3 + song 0x9FAEBEC, 6, 6 + song 0x9FAEC40, 5, 5 + song 0x9FAECCC, 5, 5 + song 0x9FAED10, 2, 2 + song 0x9FAEDBC, 2, 2 + song 0x9FAEDF8, 6, 6 + song 0x9FAEE64, 6, 6 + song 0x9FAEE84, 6, 6 + song 0x9FAEEAC, 3, 3 + song 0x9FAEED4, 3, 3 + song 0x9FAEEE0, 6, 6 + song 0x9FAEF34, 6, 6 + song 0x9FAEF58, 6, 6 + song 0x9FAEF90, 6, 6 + song 0x9FAF004, 6, 6 + song 0x9FAF044, 6, 6 + song 0x9FAF0E0, 6, 6 + song 0x9FAF16C, 6, 6 + song 0x9FAF1F4, 2, 2 + song 0x9FAF224, 3, 3 + song 0x9FAF308, 5, 5 + song 0x9FAF33C, 5, 5 + song 0x9FAF3F0, 5, 5 + song 0x9FAF3FC, 5, 5 + song 0x9FAF4C4, 5, 5 + song 0x9FAF654, 5, 5 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9FAF6A0, 3, 3 + song 0x9FAF6E8, 3, 3 + song 0x9FAF750, 3, 3 + song 0x9FAF784, 3, 3 + song 0x9FAF844, 4, 4 + song 0x9FAF88C, 2, 2 + song 0x9FAF904, 5, 5 + song 0x9FAF95C, 2, 2 + song 0x9FAF998, 2, 2 + song 0x9FAF9F8, 5, 5 + song 0x9FAFAD4, 3, 3 + song 0x9FAFB08, 5, 5 + song 0x9FAFB3C, 5, 5 + song 0x9FAFB70, 2, 2 + song 0x9FAFBAC, 5, 5 + song 0x9FAFBE4, 2, 2 + song 0x9FAFC20, 5, 5 + song 0x9FAFC7C, 5, 5 + song 0x9FAFCB0, 2, 2 + song 0x9FAFD08, 2, 2 + song 0x9FAFD74, 2, 2 + song 0x9FAFDE8, 2, 2 + song 0x9FAFE38, 2, 2 + song 0x9FAFE84, 5, 5 + song 0x9FAFF88, 5, 5 + song 0x9FAFFB4, 5, 5 + song 0x9FAFFE0, 5, 5 + song 0x9FB006C, 5, 5 + song 0x9FB0148, 5, 5 + song 0x9FB019C, 5, 5 + song 0x9FB0200, 5, 5 + song 0x9FB0254, 5, 5 + song 0x9FB02CC, 5, 5 + song 0x9FB035C, 5, 5 + song 0x9FB043C, 5, 5 + song 0x9FB04D8, 5, 5 + song 0x9FB05A8, 4, 4 + song 0x9FB062C, 5, 5 + song 0x9FB06C0, 5, 5 + song 0x9FB08C4, 5, 5 + song 0x9FB097C, 5, 5 + song 0x9FB09E0, 5, 5 + song 0x9FB0B9C, 5, 5 + song 0x9FB0C20, 5, 5 + song 0x9FB0CD0, 5, 5 + song 0x9FB0D40, 5, 5 + song 0x9E8841C, 0, 0 + song 0x9FB0D9C, 3, 3 + song 0x9FB0DC8, 3, 3 + song 0x9FB0F4C, 5, 5 + song 0x9FB11EC, 5, 5 + song 0x9FB120C, 5, 5 + song 0x9FB1254, 5, 5 + song 0x9FB12CC, 5, 5 + song 0x9FB1358, 5, 5 + song 0x9FB13E0, 5, 5 + song 0x9FB14F0, 5, 5 + song 0x9FB1718, 5, 5 + song 0x9FB17E4, 5, 5 + song 0x9FB1874, 5, 5 + song 0x9FB18A4, 2, 2 + song 0x9FB1960, 5, 5 + song 0x9FB198C, 3, 3 + song 0x9FB1FC4, 5, 5 + song 0x9FB2020, 5, 5 + song 0x9FB2090, 3, 3 + song 0x9FB20D8, 5, 5 + song 0x9FB2284, 5, 5 + song 0x9FB23C0, 5, 5 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9E8841C, 0, 0 + song 0x9FB2438, 5, 5 + song 0x9FB24F0, 5, 5 + song 0x9FB254C, 5, 5 + song 0x9FB257C, 5, 5 + song 0x9FB25D0, 5, 5 + song 0x9FB2644, 5, 5 + song 0x9FB2690, 5, 5 + song 0x9FB26D0, 3, 3 + song 0x9FB2708, 3, 3 + song 0x9FB2748, 3, 3 + song 0x9FB279C, 3, 3 + song 0x9FB2808, 5, 5 + song 0x9FB286C, 2, 2 + song 0x9FB28D0, 2, 2 + song 0x9FB291C, 5, 5 + song 0x9FB29A4, 5, 5 + song 0x9FB29E0, 5, 5 + song 0x9FB2A30, 5, 5 + song 0x9FB2A80, 5, 5 + song 0x9FB2AC8, 5, 5 + song 0x9FB2AF8, 5, 5 + song 0x9FB2B1C, 5, 5 + song 0x9FB2BB0, 5, 5 + song 0x9FB2C04, 5, 5 + song 0x9FB2C8C, 5, 5 + song 0x9FB2CDC, 5, 5 + song 0x9FB2D08, 5, 5 + song 0x9FB2D54, 5, 5 + song 0x9FB2D7C, 5, 5 + song 0x9FB2E28, 5, 5 + song 0x9FB2E80, 5, 5 + song 0x9FB2EB4, 5, 5 + song 0x9FB2F20, 5, 5 + song 0x9FB2F2C, 5, 5 + song 0x9FB2F34, 5, 5 + song 0x9FB2F3C, 5, 5 + song 0x9FB2F68, 5, 5 + song 0x9FB2F74, 5, 5 + song 0x9FB2FE4, 5, 5 + song 0x9FB3008, 5, 5 + song 0x9FB3074, 5, 5 + song 0x9FB30F0, 5, 5 + song 0x9FB314C, 5, 5 + song 0x9FB31B0, 5, 5 + song 0x9FB3228, 5, 5 + song 0x9FB327C, 5, 5 + song 0x9FB32EC, 5, 5 + song 0x9FB3334, 5, 5 + song 0x9FB3378, 5, 5 + song 0x9FB33F8, 5, 5 + song 0x9FB3474, 5, 5 + song 0x9FB34EC, 5, 5 + song 0x9FB3530, 5, 5 + song 0x9FB35A4, 5, 5 + song 0x9FB3618, 5, 5 + song 0x9FB3698, 5, 5 + song 0x9FB371C, 5, 5 + song 0x9FB37D0, 5, 5 + song 0x9FB37FC, 5, 5 + song 0x9FB384C, 5, 5 + song 0x9FB39C0, 5, 5 + song 0x9FB3A3C, 5, 5 + song 0x9FB3A9C, 5, 5 + song 0x9FB3AF4, 5, 5 + song 0x9FB3C08, 5, 5 + song 0x9FB3CB0, 5, 5 + song 0x9FB3D0C, 5, 5 + song 0x9FB3D5C, 5, 5 + song 0x9FB3DB0, 5, 5 + song 0x9FB3E24, 5, 5 + song 0x9FB3F60, 5, 5 + song 0x9FB400C, 5, 5 + song 0x9FB4094, 5, 5 + song 0x9FB411C, 5, 5 + song 0x9FB4230, 5, 5 + song 0x9FB4324, 5, 5 + song 0x9FB4350, 5, 5 + song 0x9FB43D0, 5, 5 + song 0x9FB44E0, 5, 5 + song 0x9FB4554, 5, 5 + song 0x9FB45B0, 5, 5 + song 0x9FB4658, 5, 5 + song 0x9FB46D4, 5, 5 + song 0x9FB4750, 5, 5 + song 0x9FB47C4, 5, 5 + song 0x9FB4820, 5, 5 + song 0x9FB4874, 5, 5 + song 0x9FB48B8, 5, 5 + song 0x9FB4910, 5, 5 + song 0x9FB497C, 5, 5 + song 0x9FB49E4, 5, 5 + song 0x9FB4A4C, 5, 5 + song 0x9FB4AF0, 5, 5 + song 0x9FB4B84, 5, 5 + song 0x9FB4BE8, 5, 5 + song 0x9FB4C58, 5, 5 + song 0x9FB4D44, 5, 5 + song 0x9FB4E88, 5, 5 + song 0x9FB4EDC, 5, 5 + song 0x9FB4F94, 5, 5 + song 0x9FB508C, 5, 5 + song 0x9FB5140, 5, 5 + song 0x9FB51A8, 5, 5 + song 0x9FB5208, 5, 5 + song 0x9FB5294, 5, 5 + song 0x9FB534C, 5, 5 + song 0x9FB53B0, 5, 5 + song 0x9FB54DC, 5, 5 + song 0x9FB55B0, 5, 5 + song 0x9FB5688, 5, 5 + song 0x9FB56DC, 5, 5 + song 0x9FB5730, 5, 5 + song 0x9FB57B8, 5, 5 + song 0x9FB57EC, 5, 5 + song 0x9FB5864, 5, 5 + song 0x9FB5898, 5, 5 + song 0x9FB58FC, 5, 5 + song 0x9FB59DC, 5, 5 + song 0x9FB5A64, 5, 5 + song 0x9FB5AB0, 5, 5 + song 0x9FB5B10, 5, 5 + song 0x9FB5B98, 5, 5 + song 0x9FB5CBC, 5, 5 + song 0x9FB5D24, 5, 5 + song 0x9FB5DD0, 5, 5 + song 0x9FB5E88, 5, 5 + song 0x9FB5ED4, 5, 5 + song 0x9FB5EFC, 5, 5 + song 0x9FB5F6C, 2, 2 + song 0x9FB5FD4, 5, 5 + song 0x9FB60A8, 5, 5 + song 0x9FB617C, 5, 5 + song 0x9FB6210, 5, 5 + song 0x9FB62A4, 5, 5 + song 0x9FB62EC, 5, 5 + song 0x9FB63C4, 5, 5 + song 0x9FB6440, 5, 5 + song 0x9FB6484, 5, 5 + song 0x9FB663C, 5, 5 + song 0x9FB6740, 5, 5 + song 0x9FB67C0, 5, 5 + song 0x9FB6830, 5, 5 + song 0x9FB68D8, 5, 5 + song 0x9FB696C, 5, 5 + song 0x9FB69D4, 5, 5 + song 0x9FB6A58, 5, 5 + song 0x9FB6AF8, 5, 5 + song 0x9FB6B28, 5, 5 + song 0x9FB6B70, 5, 5 + song 0x9FB6C30, 5, 5 + song 0x9FB6C94, 5, 5 + song 0x9FB6D40, 5, 5 + song 0x9FB6DB0, 5, 5 + song 0x9FB6E88, 5, 5 + song 0x9FB703C, 5, 5 + song 0x9FB71F0, 5, 5 + song 0x9FB73A8, 5, 5 + song 0x9FB7464, 5, 5 + song 0x9FB74D8, 5, 5 + song 0x9FB7534, 5, 5 + song 0x9FB7658, 5, 5 + song 0x9FB7688, 5, 5 + song 0x9FB7708, 5, 5 + song 0x9FB7798, 5, 5 + song 0x9FB77D8, 5, 5 + song 0x9FB78F0, 5, 5 + song 0x9FB792C, 5, 5 + song 0x9FB79F0, 5, 5 + song 0x9FB7AA8, 5, 5 + song 0x9FB7B88, 2, 2 + song 0x9FB7CDC, 5, 5 + song 0x9FB7DA0, 5, 5 + song 0x9FB7E28, 5, 5 + song 0x9FB7EC4, 5, 5 + song 0x9FB7F5C, 5, 5 + song 0x9FB8074, 5, 5 + song 0x9FB8150, 5, 5 + song 0x9FB82B8, 5, 5 + song 0x9FB834C, 5, 5 + song 0x9FB85C0, 5, 5 + song 0x9FB8670, 5, 5 + song 0x9FB86C8, 5, 5 + song 0x9FB87C4, 5, 5 + song 0x9FB880C, 5, 5 + song 0x9FB8884, 5, 5 + song 0x9FB893C, 5, 5 + song 0x9FB8B48, 5, 5 + song 0x9FB8C5C, 5, 5 + song 0x9FB8D14, 5, 5 + song 0x9FB8D54, 5, 5 + song 0x9FB8DF0, 5, 5 + song 0x9FB8E40, 5, 5 + song 0x9FB8F18, 5, 5 + song 0x9FB8F68, 5, 5 + song 0x9FB9000, 5, 5 + song 0x9FB9070, 5, 5 + song 0x9FB90E0, 5, 5 + song 0x9FB9150, 5, 5 + song 0x9FB9244, 5, 5 + song 0x9FB9388, 5, 5 + song 0x9FB93B4, 5, 5 + song 0x9FB943C, 5, 5 + song 0x9FB9528, 5, 5 + song 0x9FB955C, 5, 5 + song 0x9FB9568, 5, 5 + song 0x9FB961C, 5, 5 + song 0x9E8841C, 0, 0 + song 0x9FB965C, 5, 5 + song 0x9FB96B4, 5, 5 + song 0x9FB9764, 5, 5 + song 0x9FB97B8, 5, 5 + song 0x9FB97F8, 5, 5 + song 0x9FB9854, 5, 5 + song 0x9FB988C, 5, 5 + song 0x9FB9984, 5, 5 + song 0x9FB9A68, 5, 5 + song 0x9FB9AB0, 5, 5 + song 0x9FB9AF8, 5, 5 + song 0x9FB9BD0, 5, 5 + song 0x9FB9C54, 5, 5 + song 0x9FB9D58, 5, 5 + song 0x9FB9D9C, 5, 5 + song 0x9FB9DFC, 5, 5 + song 0x9FB9E60, 5, 5 + song 0x9FB9EBC, 5, 5 + song 0x9FB9F34, 5, 5 + song 0x9FBA014, 5, 5 + song 0x9FBA07C, 5, 5 + song 0x9FBA110, 5, 5 + song 0x9FBA178, 5, 5 + song 0x9FBA270, 5, 5 + song 0x9FBA31C, 5, 5 + song 0x9FBA3C8, 5, 5 + song 0x9FBA4B0, 5, 5 + song 0x9FBA508, 5, 5 + song 0x9FBA54C, 5, 5 + song 0x9FBA5C0, 5, 5 + song 0x9FBA638, 5, 5 + song 0x9FBA728, 5, 5 + song 0x9FBA7A4, 5, 5 + song 0x9FBA868, 5, 5 + song 0x9FBA928, 5, 5 + song 0x9FBA9A0, 5, 5 + song 0x9FBAA34, 5, 5 + song 0x9FBAA78, 5, 5 + song 0x9FBAAD4, 5, 5 + song 0x9FBAB48, 5, 5 + song 0x9FBAC60, 5, 5 + song 0x9FBACB0, 5, 5 + song 0x9FBAD68, 5, 5 + song 0x9FBADDC, 5, 5 + song 0x9FBAE50, 5, 5 + song 0x9FBAEC8, 5, 5 + song 0x9FBAF40, 5, 5 + song 0x9FBAF80, 5, 5 + song 0x9FBAFDC, 5, 5 + song 0x9FBB0B4, 5, 5 + song 0x9FBB110, 5, 5 + song 0x9FBB364, 5, 5 + song 0x9FBB454, 5, 5 + song 0x9FBB56C, 5, 5 + song 0x9FBB660, 5, 5 + song 0x9FBB754, 5, 5 + song 0x9FBB7FC, 5, 5 + song 0x9FBB848, 5, 5 + song 0x9FBB894, 5, 5 + song 0x9FBB90C, 5, 5 + song 0x9FBB9DC, 5, 5 + song 0x9FBBA20, 5, 5 + song 0x9FBBA58, 5, 5 + song 0x9FBBAC8, 5, 5 + song 0x9FBBB38, 5, 5 + song 0x9FBBB74, 5, 5 + song 0x9FBBC20, 5, 5 + song 0x9FBBC58, 5, 5 + song 0x9FBBD08, 5, 5 + song 0x9FBBD54, 5, 5 + song 0x9FBBEB4, 5, 5 + song 0x9FBBF44, 5, 5 + song 0x9FBBF80, 5, 5 + song 0x9FBBFC8, 5, 5 + song 0x9FBC080, 5, 5 + song 0x9FBC0C8, 5, 5 + song 0x9FBC0F4, 5, 5 + song 0x9FBC140, 2, 2 + song 0x9FBC178, 5, 5 + song 0x9FBC1B0, 5, 5 + song 0x9FBC1EC, 5, 5 + song 0x9FBC25C, 5, 5 + song 0x9FBC340, 5, 5 + song 0x9FBC37C, 5, 5 + song 0x9FBC3AC, 5, 5 + song 0x9FBC464, 5, 5 + song 0x9FBC538, 5, 5 + song 0x9FBC59C, 5, 5 + song 0x9FBC674, 5, 5 + song 0x9FBC6D8, 5, 5 + song 0x9FBC890, 5, 5 + song 0x9FBC8F4, 5, 5 + song 0x9FBC990, 5, 5 + song 0x9FBC9E0, 5, 5 + song 0x9FBCA38, 2, 2 + song 0x9FBCA94, 2, 2 + song 0x9FBCAD4, 2, 2 + song 0x9FBCB10, 2, 2 + song 0x9FBCB50, 2, 2 + song 0x9FBCB8C, 2, 2 + song 0x9FBCBC4, 3, 3 + song 0x9FBCBF4, 3, 3 + song 0x9FBCC30, 2, 2 + song 0x9FBCC6C, 2, 2 + song 0x9FBCCB4, 2, 2 + song 0x9FBCD0C, 5, 5 + song 0x9FBCD68, 5, 5 + song 0x9FBCDDC, 5, 5 + song 0x9FBCE38, 5, 5 + song 0x9FBCE44, 5, 5 + song 0x9FBCE4C, 5, 5 + song 0x9FBCE7C, 5, 5 + song 0x9FBCEB0, 5, 5 + song 0x9FBCEDC, 3, 3 + song 0x9FBCF18, 3, 3 + song 0x9FBCFA8, 5, 5 + song 0x9FBCFB4, 3, 3 + song 0x9FBCFD8, 3, 3 + song 0x9FBD0E0, 5, 5 + song 0x9FBD174, 5, 5 + song 0x9FBD1E4, 6, 6 + song 0x9FBD218, 6, 6 + song 0x9FBD268, 2, 2 + song 0x9FBD2D0, 2, 2 + song 0x9FBD310, 2, 2 + song 0x9FBD380, 5, 5 + song 0x9FBD3B8, 6, 6 + song 0x9FBD404, 2, 2 + song 0x9FBD430, 3, 3 + song 0x9FBD488, 2, 2 + song 0x9FBD4B4, 2, 2 + song 0x9FBD4EC, 6, 6 + song 0x9FBD5C4, 6, 6 -- cgit v1.2.3 From a611b9673e73eeb74af802250d9fee5157f76a20 Mon Sep 17 00:00:00 2001 From: nullableVoidPtr <30564701+nullableVoidPtr@users.noreply.github.com> Date: Wed, 21 Nov 2018 18:48:01 +0800 Subject: "Finish" decompiling bg_palette_buffer.s and m4a_2.s, and rename text variables We all have our breaking points :matchlikethis: --- asm/bg_palette_buffer.s | 148 ------------------------------------------- asm/m4a_2.s | 70 -------------------- asm/text.s | 2 +- include/global.h | 2 + ld_script.txt | 3 +- src/bg_palette_buffer.c | 165 ++++++++++++++++++++++++++++++++++++++++++++---- src/m4a_2.c | 113 +++++++++++++++++++++++++++++++++ src/text.c | 18 +++--- sym_ewram.txt | 4 +- 9 files changed, 281 insertions(+), 244 deletions(-) delete mode 100644 asm/bg_palette_buffer.s delete mode 100644 asm/m4a_2.s diff --git a/asm/bg_palette_buffer.s b/asm/bg_palette_buffer.s deleted file mode 100644 index 9cafb43..0000000 --- a/asm/bg_palette_buffer.s +++ /dev/null @@ -1,148 +0,0 @@ - .include "constants/gba_constants.inc" - .include "asm/macros.inc" - - .syntax unified - - .text - - thumb_func_start InitBGPaletteBuffer -InitBGPaletteBuffer: - push {lr} - movs r2, 0 - ldr r1, =gBGPaletteBuffer - movs r0, 0x80 - lsls r0, 2 -_0800463E: - strh r2, [r1] - adds r1, 0x2 - subs r0, 0x1 - cmp r0, 0 - bne _0800463E - ldr r1, =gBGPaletteUsed - movs r2, 0x1 - adds r0, r1, 0 - adds r0, 0x1F -_08004650: - strb r2, [r0] - subs r0, 0x1 - cmp r0, r1 - bge _08004650 - pop {r0} - bx r0 - .align 2, 0 - .pool - thumb_func_end InitBGPaletteBuffer - - thumb_func_start SetBGPaletteBufferColorRGB -SetBGPaletteBufferColorRGB: - push {r4-r7,lr} - adds r4, r0, 0 - adds r5, r1, 0 - cmp r2, 0 - bge _08004670 - movs r2, 0 -_08004670: - cmp r2, 0x1F - ble _08004676 - movs r2, 0x1F -_08004676: - ldr r1, =gBGPaletteUsed - adds r0, r4, 0 - cmp r4, 0 - bge _08004680 - adds r0, 0xF -_08004680: - asrs r0, 4 - adds r0, r1 - movs r1, 0x1 - strb r1, [r0] - cmp r3, 0 - bne _080046D4 - ldr r0, =gBGPaletteBuffer - lsls r1, r4, 1 - adds r6, r1, r0 - ldrb r0, [r5, 0x2] - muls r0, r2 - cmp r0, 0 - bge _0800469C - adds r0, 0xFF -_0800469C: - asrs r0, 8 - movs r3, 0x1F - ands r0, r3 - lsls r4, r0, 10 - ldrb r0, [r5, 0x1] - muls r0, r2 - cmp r0, 0 - bge _080046AE - adds r0, 0xFF -_080046AE: - asrs r0, 8 - ands r0, r3 - lsls r1, r0, 5 - orrs r1, r4 - ldrb r0, [r5] - muls r0, r2 - cmp r0, 0 - bge _080046C0 - adds r0, 0xFF -_080046C0: - asrs r0, 8 - ands r0, r3 - orrs r1, r0 - strh r1, [r6] - b _08004722 - .align 2, 0 - .pool -_080046D4: - ldr r1, =gBGPaletteBuffer - lsls r0, r4, 1 - adds r7, r0, r1 - ldrb r0, [r5, 0x2] - lsls r0, 2 - adds r0, r3 - ldrb r0, [r0, 0x2] - muls r0, r2 - cmp r0, 0 - bge _080046EA - adds r0, 0xFF -_080046EA: - asrs r0, 8 - movs r4, 0x1F - ands r0, r4 - lsls r6, r0, 10 - ldrb r0, [r5, 0x1] - lsls r0, 2 - adds r0, r3 - ldrb r0, [r0, 0x1] - muls r0, r2 - cmp r0, 0 - bge _08004702 - adds r0, 0xFF -_08004702: - asrs r0, 8 - ands r0, r4 - lsls r1, r0, 5 - orrs r1, r6 - ldrb r0, [r5] - lsls r0, 2 - adds r0, r3 - ldrb r0, [r0] - muls r0, r2 - cmp r0, 0 - bge _0800471A - adds r0, 0xFF -_0800471A: - asrs r0, 8 - ands r0, r4 - orrs r1, r0 - strh r1, [r7] -_08004722: - pop {r4-r7} - pop {r0} - bx r0 - .align 2, 0 - .pool - thumb_func_end SetBGPaletteBufferColorRGB - -.align 2, 0 @ Don't pad with nop. \ No newline at end of file diff --git a/asm/m4a_2.s b/asm/m4a_2.s deleted file mode 100644 index eb525ce..0000000 --- a/asm/m4a_2.s +++ /dev/null @@ -1,70 +0,0 @@ - .include "asm/macros.inc" - .include "constants/gba_constants.inc" - .include "constants/m4a_constants.inc" - - .syntax unified - - .text - - thumb_func_start CgbModVol -CgbModVol: - push {r4,lr} - adds r1, r0, 0 - ldrb r0, [r1, 0x2] - lsls r2, r0, 24 - lsrs r4, r2, 24 - ldrb r3, [r1, 0x3] - lsls r0, r3, 24 - lsrs r3, r0, 24 - cmp r4, r3 - bcc _080AFA94 - lsrs r0, r2, 25 - cmp r0, r3 - bcc _080AFAA0 - movs r0, 0xF - strb r0, [r1, 0x1B] - b _080AFAAE -_080AFA94: - lsrs r0, 25 - cmp r0, r4 - bcc _080AFAA0 - movs r0, 0xF0 - strb r0, [r1, 0x1B] - b _080AFAAE -_080AFAA0: - movs r0, 0xFF - strb r0, [r1, 0x1B] - ldrb r2, [r1, 0x3] - ldrb r3, [r1, 0x2] - adds r0, r2, r3 - lsrs r0, 4 - b _080AFABE -_080AFAAE: - ldrb r2, [r1, 0x3] - ldrb r3, [r1, 0x2] - adds r0, r2, r3 - lsrs r0, 4 - strb r0, [r1, 0xA] - cmp r0, 0xF - bls _080AFAC0 - movs r0, 0xF -_080AFABE: - strb r0, [r1, 0xA] -_080AFAC0: - ldrb r2, [r1, 0x6] - ldrb r3, [r1, 0xA] - adds r0, r2, 0 - muls r0, r3 - adds r0, 0xF - asrs r0, 4 - strb r0, [r1, 0x19] - ldrb r0, [r1, 0x1C] - ldrb r2, [r1, 0x1B] - ands r0, r2 - strb r0, [r1, 0x1B] - pop {r4} - pop {r0} - bx r0 - thumb_func_end CgbModVol - - .align 2, 0 @ Don't pad with nop. diff --git a/asm/text.s b/asm/text.s index 98b8797..bbf990b 100644 --- a/asm/text.s +++ b/asm/text.s @@ -4468,7 +4468,7 @@ sub_8008584: adds r1, r5, r1 b _08008624 .align 2, 0 -_080085C4: .4byte gUnknown_2027490 +_080085C4: .4byte gKanji _080085C8: .4byte gUnknown_20274AC _080085CC: .4byte 0xffff0800 _080085D0: .4byte 0x000007fe diff --git a/include/global.h b/include/global.h index 66c1b6d..b5a4593 100644 --- a/include/global.h +++ b/include/global.h @@ -24,6 +24,8 @@ #define asm_unified(x) asm(".syntax unified\n" x "\n.syntax divided\n") +#define NAKED __attribute__((naked)) + #define ARRAY_COUNT(array) (sizeof(array) / sizeof((array)[0])) #endif // GUARD_GLOBAL_H diff --git a/ld_script.txt b/ld_script.txt index 4fbe903..de750b1 100755 --- a/ld_script.txt +++ b/ld_script.txt @@ -48,7 +48,6 @@ SECTIONS { asm/code_80035F0.o(.text); src/other_random.o(.text); src/util.o(.text); - asm/bg_palette_buffer.o(.text); src/bg_palette_buffer.o(.text); asm/input.o(.text); asm/code_8004AA0.o(.text); @@ -57,6 +56,7 @@ SECTIONS { asm/code_800558C.o(.text); src/random.o(.text); src/text.o(.text); + . = ALIGN(4); asm/text.o(.text); asm/code_8009804.o(.text); src/file_system.o(.text); @@ -71,7 +71,6 @@ SECTIONS { asm/code_8012A18.o(.text); asm/m4a_1.o(.text); src/m4a_2.o(.text); - asm/m4a_2.o(.text); asm/m4a_3.o(.text); src/m4a_4.o(.text); asm/syscall.o(.text); diff --git a/src/bg_palette_buffer.c b/src/bg_palette_buffer.c index e36176d..9917adf 100644 --- a/src/bg_palette_buffer.c +++ b/src/bg_palette_buffer.c @@ -8,9 +8,12 @@ extern bool8 gBGPaletteUsed[BG_PALETTE_BUFFER_SIZE / BG_PALETTE_BUFFER_CHUNK_SIZ extern void CpuCopy(void* src, void* dest, u32 size); -/* +#ifndef NONMATCHING +NAKED +#endif void InitBGPaletteBuffer(void) { +#ifdef NONMATCHING u16 color = 0; u16* ptr; u32 i; @@ -36,25 +39,165 @@ void InitBGPaletteBuffer(void) do *p-- = paletteUsed; while ((s32) p >= (s32) &gBGPaletteUsed); +#else + asm_unified("\tpush {lr}\n" + "\tmovs r2, 0\n" + "\tldr r1, =gBGPaletteBuffer\n" + "\tmovs r0, 0x80\n" + "\tlsls r0, 2\n" + "_0800463E:\n" + "\tstrh r2, [r1]\n" + "\tadds r1, 0x2\n" + "\tsubs r0, 0x1\n" + "\tcmp r0, 0\n" + "\tbne _0800463E\n" + "\tldr r1, =gBGPaletteUsed\n" + "\tmovs r2, 0x1\n" + "\tadds r0, r1, 0\n" + "\tadds r0, 0x1F\n" + "_08004650:\n" + "\tstrb r2, [r0]\n" + "\tsubs r0, 0x1\n" + "\tcmp r0, r1\n" + "\tbge _08004650\n" + "\tpop {r0}\n" + "\tbx r0\n" + "\t.align 2, 0\n" + "\t.pool"); +#endif } -void SetBGPaletteBufferColorRGB(s32 index, u8 *RGBArray, s32 a3, u8 *a4) + +#ifndef NONMATCHING +NAKED +#endif +void SetBGPaletteBufferColorRGB(s32 index, u8 *RGBArray, s32 a1, u8 *a2) { - if (a3 < 0) { - a3 = 0; +#ifdef NONMATCHING + if (a1 < 0) { + a1 = 0; } - if (a3 > 31) { - a3 = 31; + if (a1 > 31) { + a1 = 31; } gBGPaletteUsed[index / 16] = 1; - if (!a4) { - gBGPaletteBuffer[index] = ((RGBArray[2] * a3 / 256 & 0x1F) << 10) | ((RGBArray[1] * a3 / 256 & 0x1F) << 5) | (RGBArray[0] * a3 / 256 & 0x1F); + if (!a2) { + gBGPaletteBuffer[index] = ((RGBArray[2] * a1 / 256 & 0x1F) << 10) | ((RGBArray[1] * a1 / 256 & 0x1F) << 5) | (RGBArray[0] * a1 / 256 & 0x1F); } else { - gBGPaletteBuffer[index] = ((a4[4 * RGBArray[2] + 2] * a3 / 256 & 0x1F) << 10) | ((a4[4 * RGBArray[1] + 1] * a3 / 256 & 0x1F) << 5) | (a4[4 * RGBArray[0]] * a3 / 256 & 0x1F); + gBGPaletteBuffer[index] = ((a2[4 * RGBArray[2] + 2] * a1 / 256 & 0x1F) << 10) | ((a2[4 * RGBArray[1] + 1] * a1 / 256 & 0x1F) << 5) | (a2[4 * RGBArray[0]] * a1 / 256 & 0x1F); } +#else + asm_unified("\tpush {r4-r7,lr}\n" + "\tadds r4, r0, 0\n" + "\tadds r5, r1, 0\n" + "\tcmp r2, 0\n" + "\tbge _08004670\n" + "\tmovs r2, 0\n" + "_08004670:\n" + "\tcmp r2, 0x1F\n" + "\tble _08004676\n" + "\tmovs r2, 0x1F\n" + "_08004676:\n" + "\tldr r1, =gBGPaletteUsed\n" + "\tadds r0, r4, 0\n" + "\tcmp r4, 0\n" + "\tbge _08004680\n" + "\tadds r0, 0xF\n" + "_08004680:\n" + "\tasrs r0, 4\n" + "\tadds r0, r1\n" + "\tmovs r1, 0x1\n" + "\tstrb r1, [r0]\n" + "\tcmp r3, 0\n" + "\tbne _080046D4\n" + "\tldr r0, =gBGPaletteBuffer\n" + "\tlsls r1, r4, 1\n" + "\tadds r6, r1, r0\n" + "\tldrb r0, [r5, 0x2]\n" + "\tmuls r0, r2\n" + "\tcmp r0, 0\n" + "\tbge _0800469C\n" + "\tadds r0, 0xFF\n" + "_0800469C:\n" + "\tasrs r0, 8\n" + "\tmovs r3, 0x1F\n" + "\tands r0, r3\n" + "\tlsls r4, r0, 10\n" + "\tldrb r0, [r5, 0x1]\n" + "\tmuls r0, r2\n" + "\tcmp r0, 0\n" + "\tbge _080046AE\n" + "\tadds r0, 0xFF\n" + "_080046AE:\n" + "\tasrs r0, 8\n" + "\tands r0, r3\n" + "\tlsls r1, r0, 5\n" + "\torrs r1, r4\n" + "\tldrb r0, [r5]\n" + "\tmuls r0, r2\n" + "\tcmp r0, 0\n" + "\tbge _080046C0\n" + "\tadds r0, 0xFF\n" + "_080046C0:\n" + "\tasrs r0, 8\n" + "\tands r0, r3\n" + "\torrs r1, r0\n" + "\tstrh r1, [r6]\n" + "\tb _08004722\n" + "\t.align 2, 0\n" + "\t.pool\n" + "_080046D4:\n" + "\tldr r1, =gBGPaletteBuffer\n" + "\tlsls r0, r4, 1\n" + "\tadds r7, r0, r1\n" + "\tldrb r0, [r5, 0x2]\n" + "\tlsls r0, 2\n" + "\tadds r0, r3\n" + "\tldrb r0, [r0, 0x2]\n" + "\tmuls r0, r2\n" + "\tcmp r0, 0\n" + "\tbge _080046EA\n" + "\tadds r0, 0xFF\n" + "_080046EA:\n" + "\tasrs r0, 8\n" + "\tmovs r4, 0x1F\n" + "\tands r0, r4\n" + "\tlsls r6, r0, 10\n" + "\tldrb r0, [r5, 0x1]\n" + "\tlsls r0, 2\n" + "\tadds r0, r3\n" + "\tldrb r0, [r0, 0x1]\n" + "\tmuls r0, r2\n" + "\tcmp r0, 0\n" + "\tbge _08004702\n" + "\tadds r0, 0xFF\n" + "_08004702:\n" + "\tasrs r0, 8\n" + "\tands r0, r4\n" + "\tlsls r1, r0, 5\n" + "\torrs r1, r6\n" + "\tldrb r0, [r5]\n" + "\tlsls r0, 2\n" + "\tadds r0, r3\n" + "\tldrb r0, [r0]\n" + "\tmuls r0, r2\n" + "\tcmp r0, 0\n" + "\tbge _0800471A\n" + "\tadds r0, 0xFF\n" + "_0800471A:\n" + "\tasrs r0, 8\n" + "\tands r0, r4\n" + "\torrs r1, r0\n" + "\tstrh r1, [r7]\n" + "_08004722:\n" + "\tpop {r4-r7}\n" + "\tpop {r0}\n" + "\tbx r0\n" + "\t.align 2, 0\n" + "\t.pool"); +#endif } -*/ void SetBGPaletteBufferColorArray(s32 index, u8 *colorArray) { @@ -68,7 +211,7 @@ void SetBGPaletteBufferColor(s32 index, u16 *color) gBGPaletteBuffer[index] = *color; } -void nullsub_4() +void nullsub_4(void) { } diff --git a/src/m4a_2.c b/src/m4a_2.c index 176910e..ce9ac19 100644 --- a/src/m4a_2.c +++ b/src/m4a_2.c @@ -1,4 +1,5 @@ #include "gba/m4a_internal.h" +#include "global.h" extern char SoundMainRAM_Buffer[0x400]; @@ -832,3 +833,115 @@ void CgbOscOff(u8 chanNum) REG_NR44 = 0x80; } } + +static inline int CgbPan(struct CgbChannel *chan) +{ + u32 rightVolume = chan->rightVolume; + u32 leftVolume = chan->leftVolume; + + if ((rightVolume = (u8)rightVolume) >= (leftVolume = (u8)leftVolume)) + { + if (rightVolume / 2 >= leftVolume) + { + chan->pan = 0x0F; + return 1; + } + } + else + { + if (leftVolume / 2 >= rightVolume) + { + chan->pan = 0xF0; + return 1; + } + } + + return 0; +} +#ifndef NONMATCHING +NAKED +#endif +void CgbModVol(struct CgbChannel *chan) +{ +#ifdef NONMATCHING + struct SoundInfo *soundInfo = SOUND_INFO_PTR; + + if ((soundInfo->mode & 1) || !CgbPan(chan)) + { + chan->pan = 0xFF; + chan->eg = (u32)(chan->rightVolume + chan->leftVolume) >> 4; + } + else + { + // Force chan->rightVolume and chan->leftVolume to be read from memory again, + // even though there is no reason to do so. + // The command line option "-fno-gcse" achieves the same result as this. + asm("" : : : "memory"); + + chan->eg = (u32)(chan->rightVolume + chan->leftVolume) >> 4; + if (chan->eg > 15) + chan->eg = 15; + } + + chan->sg = (chan->eg * chan->su + 15) >> 4; + chan->pan &= chan->panMask; +#else + asm_unified("\tpush {r4,lr}\n" + "\tadds r1, r0, 0\n" + "\tldrb r0, [r1, 0x2]\n" + "\tlsls r2, r0, 24\n" + "\tlsrs r4, r2, 24\n" + "\tldrb r3, [r1, 0x3]\n" + "\tlsls r0, r3, 24\n" + "\tlsrs r3, r0, 24\n" + "\tcmp r4, r3\n" + "\tbcc _080AFA94\n" + "\tlsrs r0, r2, 25\n" + "\tcmp r0, r3\n" + "\tbcc _080AFAA0\n" + "\tmovs r0, 0xF\n" + "\tstrb r0, [r1, 0x1B]\n" + "\tb _080AFAAE\n" + "_080AFA94:\n" + "\tlsrs r0, 25\n" + "\tcmp r0, r4\n" + "\tbcc _080AFAA0\n" + "\tmovs r0, 0xF0\n" + "\tstrb r0, [r1, 0x1B]\n" + "\tb _080AFAAE\n" + "_080AFAA0:\n" + "\tmovs r0, 0xFF\n" + "\tstrb r0, [r1, 0x1B]\n" + "\tldrb r2, [r1, 0x3]\n" + "\tldrb r3, [r1, 0x2]\n" + "\tadds r0, r2, r3\n" + "\tlsrs r0, 4\n" + "\tb _080AFABE\n" + "_080AFAAE:\n" + "\tldrb r2, [r1, 0x3]\n" + "\tldrb r3, [r1, 0x2]\n" + "\tadds r0, r2, r3\n" + "\tlsrs r0, 4\n" + "\tstrb r0, [r1, 0xA]\n" + "\tcmp r0, 0xF\n" + "\tbls _080AFAC0\n" + "\tmovs r0, 0xF\n" + "_080AFABE:\n" + "\tstrb r0, [r1, 0xA]\n" + "_080AFAC0:\n" + "\tldrb r2, [r1, 0x6]\n" + "\tldrb r3, [r1, 0xA]\n" + "\tadds r0, r2, 0\n" + "\tmuls r0, r3\n" + "\tadds r0, 0xF\n" + "\tasrs r0, 4\n" + "\tstrb r0, [r1, 0x19]\n" + "\tldrb r0, [r1, 0x1C]\n" + "\tldrb r2, [r1, 0x1B]\n" + "\tands r0, r2\n" + "\tstrb r0, [r1, 0x1B]\n" + "\tpop {r4}\n" + "\tpop {r0}\n" + "\tbx r0\n"); +#endif +} \ No newline at end of file diff --git a/src/text.c b/src/text.c index 5d93844..9de996a 100644 --- a/src/text.c +++ b/src/text.c @@ -23,13 +23,13 @@ struct UnkTextStruct2 { extern char gUnknown_3000E94[]; EWRAM_DATA struct UnkTextStruct1 gUnknown_2027370[4]; -EWRAM_DATA u8 *gUnknown_2027490[2]; +EWRAM_DATA u8 *gKanji[2]; EWRAM_DATA u16 gUnknown_2027498; EWRAM_DATA u8 gUnknown_20274A5; EWRAM_DATA u32 gUnknown_20274AC; EWRAM_DATA vu32 gUnknown_20274B0; EWRAM_DATA u8 gUnknown_20274B4[0x3b00]; -EWRAM_DATA struct OpenedFile *gKanji[2]; +EWRAM_DATA struct OpenedFile *gKanjiFiles[2]; EWRAM_DATA struct UnkTextStruct2 gUnknown_202AFC0[4]; EWRAM_DATA u32 gUnknown_202B020; EWRAM_DATA u32 gUnknown_202B024; @@ -60,10 +60,10 @@ void sub_8006218(void) int k; gUnknown_20274AC = 0; - gKanji[0] = OpenFileAndGetFileDataPtr(gUnknown_80B87B4, &gUnknown_8300500); - gKanji[1] = OpenFileAndGetFileDataPtr(gUnknown_80B87BC, &gUnknown_8300500); - gUnknown_2027490[0] = gKanji[0]->data; - gUnknown_2027490[1] = gKanji[1]->data; + gKanjiFiles[0] = OpenFileAndGetFileDataPtr(gUnknown_80B87B4, &gUnknown_8300500); + gKanjiFiles[1] = OpenFileAndGetFileDataPtr(gUnknown_80B87BC, &gUnknown_8300500); + gKanji[0] = gKanjiFiles[0]->data; + gKanji[1] = gKanjiFiles[1]->data; gUnknown_202B028[0] = 11; gUnknown_202B028[1] = 12; for (k = 0; k < 4; k++) @@ -188,13 +188,11 @@ void sub_8006438(const struct UnkTextStruct2 *a0, u8 a1, u8 a2, u32 *a3) gUnknown_203B078 = gUnknown_3000E94; gUnknown_20274A5 = 1; #else - asm(".syntax unified\n" - "\tldr r2, =gUnknown_203B078\n" + asm_unified("\tldr r2, =gUnknown_203B078\n" "\tldr r0, =gUnknown_3000E94\n" "\tldr r1, =gUnknown_20274A5\n" "\tstr r0, [r2]\n" "\tmovs r0, 0x1\n" - "\tstrb r0, [r1]\n" - ".syntax divided"); + "\tstrb r0, [r1]"); #endif } diff --git a/sym_ewram.txt b/sym_ewram.txt index a627dcf..1d287ee 100644 --- a/sym_ewram.txt +++ b/sym_ewram.txt @@ -133,7 +133,7 @@ gUnknown_2027370 = .; /* 2027370 */ gUnknown_20273B8 = .; /* 20273B8 */ . += 0xD8; -gUnknown_2027490 = .; /* 2027490 */ +gKanji = .; /* 2027490 */ . += 0x8; gUnknown_2027498 = .; /* 2027498 */ @@ -157,7 +157,7 @@ gUnknown_20274B0 = .; /* 20274B0 */ gUnknown_20274B4 = .; /* 20274B4 */ . += 0x3B00; -gKanji = .; /* 202AFB4 */ +gKanjiFiles = .; /* 202AFB4 */ . += 0x8; gUnknown_202AFBC = .; /* 202AFBC */ -- cgit v1.2.3 From 81f6704f3cb15c3f59fd3b48ec3622b63bc71297 Mon Sep 17 00:00:00 2001 From: nullableVoidPtr <30564701+nullableVoidPtr@users.noreply.github.com> Date: Thu, 22 Nov 2018 20:59:37 +0800 Subject: Use preprocessor for data asms, clean up sound/ and dump some text --- Makefile | 2 +- charmap.txt | 217 ++++++++++++ data/data.s | 32 +- data/data_80B9BB8.s | 682 +------------------------------------ data/text/luminous_cave.inc | 137 ++++++++ data/text/party_menu.inc | 147 ++++++++ data/text/save.inc | 58 ++++ data/text/wonder_mail_1.inc | 350 +++++++++++++++++++ data/text/wonder_mail_2.inc | 283 +++++++++++++++ data/text/wonder_mail_3.inc | 68 ++++ data/text/wonder_mail_4.inc | 195 +++++++++++ data/text/wonder_mail_complete.inc | 40 +++ sound/music_player_table.inc | 3 +- sound/song_table.inc | 3 +- 14 files changed, 1510 insertions(+), 707 deletions(-) create mode 100644 charmap.txt create mode 100644 data/text/luminous_cave.inc create mode 100644 data/text/party_menu.inc create mode 100644 data/text/save.inc create mode 100644 data/text/wonder_mail_1.inc create mode 100644 data/text/wonder_mail_2.inc create mode 100644 data/text/wonder_mail_3.inc create mode 100644 data/text/wonder_mail_4.inc create mode 100644 data/text/wonder_mail_complete.inc diff --git a/Makefile b/Makefile index 10c7dee..7e75101 100755 --- a/Makefile +++ b/Makefile @@ -127,7 +127,7 @@ $(C_OBJECTS): $(BUILD_DIR)/%.o: %.c $$(C_DEP) $(AS) $(ASFLAGS) -o $@ $(BUILD_DIR)/$*.s $(BUILD_DIR)/data/%.o: data/%.s $$(ASM_DEP) - $(AS) $(ASFLAGS) $< -o $@ + $(PREPROC) $< charmap.txt | $(CPP) -I include | $(AS) $(ASFLAGS) -o $@ $(BUILD_DIR)/%.o: %.s $$(ASM_DEP) $(AS) $(ASFLAGS) $< -o $@ \ No newline at end of file diff --git a/charmap.txt b/charmap.txt new file mode 100644 index 0000000..e7ea662 --- /dev/null +++ b/charmap.txt @@ -0,0 +1,217 @@ +' ' = 20 +'!' = 21 +'"' = 22 +'#' = 23 +'$' = 24 +'%' = 25 +'&' = 26 +'\'' = 27 +'(' = 28 +')' = 29 +'*' = 2A +'+' = 2B +',' = 2C +'-' = 2D +'.' = 2E +'/' = 2F +'0' = 30 +'1' = 31 +'2' = 32 +'3' = 33 +'4' = 34 +'5' = 35 +'6' = 36 +'7' = 37 +'8' = 38 +'9' = 39 +':' = 3A +';' = 3B +'<' = 3C +'=' = 3D +'>' = 3E +'?' = 3F +'@' = 40 +'A' = 41 +'B' = 42 +'C' = 43 +'D' = 44 +'E' = 45 +'F' = 46 +'G' = 47 +'H' = 48 +'I' = 49 +'J' = 4A +'K' = 4B +'L' = 4C +'M' = 4D +'N' = 4E +'O' = 4F +'P' = 50 +'Q' = 51 +'R' = 52 +'S' = 53 +'T' = 54 +'U' = 55 +'V' = 56 +'W' = 57 +'X' = 58 +'Y' = 59 +'Z' = 5A +'[' = 5B +@'\\' = 5C +']' = 5D +'^' = 5E +'_' = 5F +'`' = 60 +'a' = 61 +'b' = 62 +'c' = 63 +'d' = 64 +'e' = 65 +'f' = 66 +'g' = 67 +'h' = 68 +'i' = 69 +'j' = 6A +'k' = 6B +'l' = 6C +'m' = 6D +'n' = 6E +'o' = 6F +'p' = 70 +'q' = 71 +'r' = 72 +'s' = 73 +'t' = 74 +'u' = 75 +'v' = 76 +'w' = 77 +'x' = 78 +'y' = 79 +'z' = 7A +'{' = 7B +'|' = 7C +'}' = 7D +'~' = 7E +'€' = 80 +'⋯' = 85 +'†' = 86 +'ˆ' = 88 +'‰' = 89 +'Š' = 8A +'‹' = 8B +'Œ' = 8C +'Ž' = 8E +'•' = 8F +'‘' = 91 +'’' = 92 +'“' = 93 +'”' = 94 +'™' = 99 +'š' = 9A +'›' = 9B +'œ' = 9C +'ž' = 9E +'Ÿ' = 9F +'¡' = A1 +'¢' = A2 +'£' = A3 +'¤' = A4 +'¥' = A5 +'¦' = A6 +'§' = A7 +'¨' = A8 +'©' = A9 +'ª' = AA +'«' = AB +'¬' = AC +'—' = AD +'®' = AE +'¯' = AF +'°' = B0 +'±' = B1 +'²' = B2 +'³' = B3 +'´' = B4 +'µ' = B5 +'¶' = B6 +'„' = B7 +'‚' = B8 +'¹' = B9 +'⁰' = BA +'»' = BB +'←' = BC +'♂' = BD +'♀' = BE +'¿' = BF +'À' = C0 +'Á' = C1 +'Â' = C2 +'Ã' = C3 +'Ä' = C4 +'Å' = C5 +'Æ' = C6 +'Ç' = C7 +'È' = C8 +'É' = C9 +'Ê' = CA +'Ë' = CB +'Ì' = CC +'Í' = CD +'Î' = CE +'Ï' = CF +'Ð' = D0 +'Ñ' = D1 +'Ò' = D2 +'Ó' = D3 +'Ô' = D4 +'Õ' = D5 +'Ö' = D6 +'×' = D7 +'Ø' = D8 +'Ù' = D9 +'Ú' = DA +'Û' = DB +'Ü' = DC +'Ý' = DD +'Þ' = DE +'ß' = DF +'à' = E0 +'á' = E1 +'â' = E2 +'ã' = E3 +'ä' = E4 +'å' = E5 +'æ' = E6 +'ç' = E7 +'è' = E8 +'é' = E9 +'ê' = EA +'ë' = EB +'ì' = EC +'í' = ED +'î' = EE +'ï' = EF +'ð' = F0 +'ñ' = F1 +'ò' = F2 +'ó' = F3 +'ô' = F4 +'õ' = F5 +'ö' = F6 +'÷' = F7 +'ø' = F8 +'ù' = F9 +'ú' = FA +'û' = FB +'ü' = FC +'ý' = FD +'þ' = FE +'ÿ' = FF + +POKE = 83 BF 83 C4 + +A_BUTTON = 87 50 +B_BUTTON = 87 51 + +'\n' = 0A \ No newline at end of file diff --git a/data/data.s b/data/data.s index 656302e..2486395 100644 --- a/data/data.s +++ b/data/data.s @@ -22,37 +22,7 @@ gUnknown_80B69F8: @ 80B69F8 gUnknown_80B6A28: @ 80B6A28 .incbin "baserom.gba", 0xB6A28, 0xC - .global gUnknown_80B6A34 -gUnknown_80B6A34: @ 80B6A34 - .incbin "baserom.gba", 0xB6A34, 0x48 - - .global gUnknown_80B6A7C -gUnknown_80B6A7C: @ 80B6A7C - .incbin "baserom.gba", 0xB6A7C, 0x24 - - .global gUnknown_80B6AA0 -gUnknown_80B6AA0: @ 80B6AA0 - .incbin "baserom.gba", 0xB6AA0, 0x74 - - .global gUnknown_80B6B14 -gUnknown_80B6B14: @ 80B6B14 - .incbin "baserom.gba", 0xB6B14, 0x64 - - .global gUnknown_80B6B78 -gUnknown_80B6B78: @ 80B6B78 - .incbin "baserom.gba", 0xB6B78, 0x10 - - .global gUnknown_80B6B88 -gUnknown_80B6B88: @ 80B6B88 - .incbin "baserom.gba", 0xB6B88, 0x54 - - .global gUnknown_80B6BDC -gUnknown_80B6BDC: @ 80B6BDC - .incbin "baserom.gba", 0xB6BDC, 0xDC - - .global gUnknown_80B6CB8 -gUnknown_80B6CB8: @ 80B6CB8 - .incbin "baserom.gba", 0xB6CB8, 0xD8 + .include "data/text/save.inc" .global gUnknown_80B6D90 gUnknown_80B6D90: @ 80B6D90 diff --git a/data/data_80B9BB8.s b/data/data_80B9BB8.s index 6c98e87..eb4932c 100644 --- a/data/data_80B9BB8.s +++ b/data/data_80B9BB8.s @@ -156,7 +156,9 @@ gUnknown_80D40FC: @ 80D40FC .global gUnknown_80D4104 gUnknown_80D4104: @ 80D4104 - .incbin "baserom.gba", 0xD4104, 0x1C + .string "Where would you like to go?" + .byte 0 + .align 2, 0 .global gUnknown_80D4120 gUnknown_80D4120: @ 80D4120 @@ -1286,85 +1288,7 @@ gUnknown_80DCA24: @ 80DCA24 gUnknown_80DCA2C: @ 80DCA2C .incbin "baserom.gba", 0xDCA2C, 0x8 - .global gUnknown_80DCA34 -gUnknown_80DCA34: @ 80DCA34 - .incbin "baserom.gba", 0xDCA34, 0x84 - - .global gUnknown_80DCAB8 -gUnknown_80DCAB8: @ 80DCAB8 - .incbin "baserom.gba", 0xDCAB8, 0x18 - - .global gUnknown_80DCAD0 -gUnknown_80DCAD0: @ 80DCAD0 - .incbin "baserom.gba", 0xDCAD0, 0x28C - - .global gUnknown_80DCD5C -gUnknown_80DCD5C: @ 80DCD5C - .incbin "baserom.gba", 0xDCD5C, 0x34 - - .global gUnknown_80DCD90 -gUnknown_80DCD90: @ 80DCD90 - .incbin "baserom.gba", 0xDCD90, 0x28 - - .global gUnknown_80DCDB8 -gUnknown_80DCDB8: @ 80DCDB8 - .incbin "baserom.gba", 0xDCDB8, 0x24 - - .global gUnknown_80DCDDC -gUnknown_80DCDDC: @ 80DCDDC - .incbin "baserom.gba", 0xDCDDC, 0x3C - - .global gUnknown_80DCE18 -gUnknown_80DCE18: @ 80DCE18 - .incbin "baserom.gba", 0xDCE18, 0x20 - - .global gUnknown_80DCE38 -gUnknown_80DCE38: @ 80DCE38 - .incbin "baserom.gba", 0xDCE38, 0x30 - - .global gUnknown_80DCE68 -gUnknown_80DCE68: @ 80DCE68 - .incbin "baserom.gba", 0xDCE68, 0x48 - - .global gUnknown_80DCEB0 -gUnknown_80DCEB0: @ 80DCEB0 - .incbin "baserom.gba", 0xDCEB0, 0x2C - - .global gUnknown_80DCEDC -gUnknown_80DCEDC: @ 80DCEDC - .incbin "baserom.gba", 0xDCEDC, 0x68 - - .global gUnknown_80DCF44 -gUnknown_80DCF44: @ 80DCF44 - .incbin "baserom.gba", 0xDCF44, 0x44 - - .global gUnknown_80DCF88 -gUnknown_80DCF88: @ 80DCF88 - .incbin "baserom.gba", 0xDCF88, 0x24 - - .global gUnknown_80DCFAC -gUnknown_80DCFAC: @ 80DCFAC - .incbin "baserom.gba", 0xDCFAC, 0x48 - - .global gUnknown_80DCFF4 -gUnknown_80DCFF4: @ 80DCFF4 - .incbin "baserom.gba", 0xDCFF4, 0x60 - - .global gUnknown_80DD054 -gUnknown_80DD054: @ 80DD054 - .incbin "baserom.gba", 0xDD054, 0x44 - - .global gUnknown_80DD098 -gUnknown_80DD098: @ 80DD098 - .incbin "baserom.gba", 0xDD098, 0x48 - - .global gUnknown_80DD0E0 -gUnknown_80DD0E0: @ 80DD0E0 - .incbin "baserom.gba", 0xDD0E0, 0x24 - - .global gUnknown_80DD104 -gUnknown_80DD104: @ 80DD104 - .incbin "baserom.gba", 0xDD104, 0x44 + .include "data/text/luminous_cave.inc" .global gUnknown_80DD148 gUnknown_80DD148: @ 80DD148 @@ -1458,93 +1382,7 @@ gUnknown_80DD358: @ 80DD358 gUnknown_80DD370: @ 80DD370 .incbin "baserom.gba", 0xDD370, 0x18 - .global gUnknown_80DD388 -gUnknown_80DD388: @ 80DD388 - .incbin "baserom.gba", 0xDD388, 0x98 - - .global gUnknown_80DD420 -gUnknown_80DD420: @ 80DD420 - .incbin "baserom.gba", 0xDD420, 0xA4 - - .global gUnknown_80DD4C4 -gUnknown_80DD4C4: @ 80DD4C4 - .incbin "baserom.gba", 0xDD4C4, 0x30 - - .global gUnknown_80DD4F4 -gUnknown_80DD4F4: @ 80DD4F4 - .incbin "baserom.gba", 0xDD4F4, 0x40 - - .global gUnknown_80DD534 -gUnknown_80DD534: @ 80DD534 - .incbin "baserom.gba", 0xDD534, 0x30 - - .global gUnknown_80DD564 -gUnknown_80DD564: @ 80DD564 - .incbin "baserom.gba", 0xDD564, 0x30 - - .global gUnknown_80DD594 -gUnknown_80DD594: @ 80DD594 - .incbin "baserom.gba", 0xDD594, 0x24 - - .global gUnknown_80DD5B8 -gUnknown_80DD5B8: @ 80DD5B8 - .incbin "baserom.gba", 0xDD5B8, 0x54 - - .global gUnknown_80DD60C -gUnknown_80DD60C: @ 80DD60C - .incbin "baserom.gba", 0xDD60C, 0x30 - - .global gUnknown_80DD63C -gUnknown_80DD63C: @ 80DD63C - .incbin "baserom.gba", 0xDD63C, 0x28 - - .global gUnknown_80DD664 -gUnknown_80DD664: @ 80DD664 - .incbin "baserom.gba", 0xDD664, 0xC - - .global gUnknown_80DD670 -gUnknown_80DD670: @ 80DD670 - .incbin "baserom.gba", 0xDD670, 0xC - - .global gUnknown_80DD67C -gUnknown_80DD67C: @ 80DD67C - .incbin "baserom.gba", 0xDD67C, 0xC - - .global gUnknown_80DD688 -gUnknown_80DD688: @ 80DD688 - .incbin "baserom.gba", 0xDD688, 0xC - - .global gUnknown_80DD694 -gUnknown_80DD694: @ 80DD694 - .incbin "baserom.gba", 0xDD694, 0x8 - - .global gUnknown_80DD69C -gUnknown_80DD69C: @ 80DD69C - .incbin "baserom.gba", 0xDD69C, 0x8 - - .global gUnknown_80DD6A4 -gUnknown_80DD6A4: @ 80DD6A4 - .incbin "baserom.gba", 0xDD6A4, 0x10 - - .global gUnknown_80DD6B4 -gUnknown_80DD6B4: @ 80DD6B4 - .incbin "baserom.gba", 0xDD6B4, 0x8 - - .global gUnknown_80DD6BC -gUnknown_80DD6BC: @ 80DD6BC - .incbin "baserom.gba", 0xDD6BC, 0x8 - - .global gUnknown_80DD6C4 -gUnknown_80DD6C4: @ 80DD6C4 - .incbin "baserom.gba", 0xDD6C4, 0xC - - .global gUnknown_80DD6D0 -gUnknown_80DD6D0: @ 80DD6D0 - .incbin "baserom.gba", 0xDD6D0, 0x10 - - .global gUnknown_80DD6E0 -gUnknown_80DD6E0: @ 80DD6E0 - .incbin "baserom.gba", 0xDD6E0, 0xC + .include "data/text/party_menu.inc" .global gUnknown_80DD6EC gUnknown_80DD6EC: @ 80DD6EC @@ -1662,218 +1500,8 @@ gUnknown_80DDB24: @ 80DDB24 gUnknown_80DDB60: @ 80DDB60 .incbin "baserom.gba", 0xDDB60, 0x48 - .global gUnknown_80DDBA8 -gUnknown_80DDBA8: @ 80DDBA8 - .incbin "baserom.gba", 0xDDBA8, 0x54 - - .global gUnknown_80DDBFC -gUnknown_80DDBFC: @ 80DDBFC - .incbin "baserom.gba", 0xDDBFC, 0x34 - - .global gUnknown_80DDC30 -gUnknown_80DDC30: @ 80DDC30 - .incbin "baserom.gba", 0xDDC30, 0x40 - - .global gUnknown_80DDC70 -gUnknown_80DDC70: @ 80DDC70 - .incbin "baserom.gba", 0xDDC70, 0x4C - - .global gUnknown_80DDCBC -gUnknown_80DDCBC: @ 80DDCBC - .incbin "baserom.gba", 0xDDCBC, 0x70 - - .global gUnknown_80DDD2C -gUnknown_80DDD2C: @ 80DDD2C - .incbin "baserom.gba", 0xDDD2C, 0x5C - - .global gUnknown_80DDD88 -gUnknown_80DDD88: @ 80DDD88 - .incbin "baserom.gba", 0xDDD88, 0x34 - - .global gUnknown_80DDDBC -gUnknown_80DDDBC: @ 80DDDBC - .incbin "baserom.gba", 0xDDDBC, 0x1C - - .global gUnknown_80DDDD8 -gUnknown_80DDDD8: @ 80DDDD8 - .incbin "baserom.gba", 0xDDDD8, 0x48 - - .global gUnknown_80DDE20 -gUnknown_80DDE20: @ 80DDE20 - .incbin "baserom.gba", 0xDDE20, 0x38 - - .global gUnknown_80DDE58 -gUnknown_80DDE58: @ 80DDE58 - .incbin "baserom.gba", 0xDDE58, 0x68 - - .global gUnknown_80DDEC0 -gUnknown_80DDEC0: @ 80DDEC0 - .incbin "baserom.gba", 0xDDEC0, 0x6C - - .global gUnknown_80DDF2C -gUnknown_80DDF2C: @ 80DDF2C - .incbin "baserom.gba", 0xDDF2C, 0x8C - - .global gUnknown_80DDFB8 -gUnknown_80DDFB8: @ 80DDFB8 - .incbin "baserom.gba", 0xDDFB8, 0x64 - - .global gUnknown_80DE01C -gUnknown_80DE01C: @ 80DE01C - .incbin "baserom.gba", 0xDE01C, 0x50 - - .global gUnknown_80DE06C -gUnknown_80DE06C: @ 80DE06C - .incbin "baserom.gba", 0xDE06C, 0x54 - - .global gUnknown_80DE0C0 -gUnknown_80DE0C0: @ 80DE0C0 - .incbin "baserom.gba", 0xDE0C0, 0x64 - - .global gUnknown_80DE124 -gUnknown_80DE124: @ 80DE124 - .incbin "baserom.gba", 0xDE124, 0x54 - - .global gUnknown_80DE178 -gUnknown_80DE178: @ 80DE178 - .incbin "baserom.gba", 0xDE178, 0x3C - - .global gUnknown_80DE1B4 -gUnknown_80DE1B4: @ 80DE1B4 - .incbin "baserom.gba", 0xDE1B4, 0x30 - - .global gUnknown_80DE1E4 -gUnknown_80DE1E4: @ 80DE1E4 - .incbin "baserom.gba", 0xDE1E4, 0x9C - - .global gUnknown_80DE280 -gUnknown_80DE280: @ 80DE280 - .incbin "baserom.gba", 0xDE280, 0x30 - - .global gUnknown_80DE2B0 -gUnknown_80DE2B0: @ 80DE2B0 - .incbin "baserom.gba", 0xDE2B0, 0xB8 - - .global gUnknown_80DE368 -gUnknown_80DE368: @ 80DE368 - .incbin "baserom.gba", 0xDE368, 0xC8 - - .global gUnknown_80DE430 -gUnknown_80DE430: @ 80DE430 - .incbin "baserom.gba", 0xDE430, 0x5C - - .global gUnknown_80DE48C -gUnknown_80DE48C: @ 80DE48C - .incbin "baserom.gba", 0xDE48C, 0x2C - - .global gUnknown_80DE4B8 -gUnknown_80DE4B8: @ 80DE4B8 - .incbin "baserom.gba", 0xDE4B8, 0x38 - - .global gUnknown_80DE4F0 -gUnknown_80DE4F0: @ 80DE4F0 - .incbin "baserom.gba", 0xDE4F0, 0x34 - - .global gUnknown_80DE524 -gUnknown_80DE524: @ 80DE524 - .incbin "baserom.gba", 0xDE524, 0xF0 - - .global gUnknown_80DE614 -gUnknown_80DE614: @ 80DE614 - .incbin "baserom.gba", 0xDE614, 0x34 - - .global gUnknown_80DE648 -gUnknown_80DE648: @ 80DE648 - .incbin "baserom.gba", 0xDE648, 0x4C - - .global gUnknown_80DE694 -gUnknown_80DE694: @ 80DE694 - .incbin "baserom.gba", 0xDE694, 0x40 - - .global gUnknown_80DE6D4 -gUnknown_80DE6D4: @ 80DE6D4 - .incbin "baserom.gba", 0xDE6D4, 0x80 - - .global gUnknown_80DE754 -gUnknown_80DE754: @ 80DE754 - .incbin "baserom.gba", 0xDE754, 0x64 - - .global gUnknown_80DE7B8 -gUnknown_80DE7B8: @ 80DE7B8 - .incbin "baserom.gba", 0xDE7B8, 0x30 - - .global gUnknown_80DE7E8 -gUnknown_80DE7E8: @ 80DE7E8 - .incbin "baserom.gba", 0xDE7E8, 0x20 - - .global gUnknown_80DE808 -gUnknown_80DE808: @ 80DE808 - .incbin "baserom.gba", 0xDE808, 0x28 - - .global gUnknown_80DE830 -gUnknown_80DE830: @ 80DE830 - .incbin "baserom.gba", 0xDE830, 0x34 - - .global gUnknown_80DE864 -gUnknown_80DE864: @ 80DE864 - .incbin "baserom.gba", 0xDE864, 0x50 - - .global gUnknown_80DE8B4 -gUnknown_80DE8B4: @ 80DE8B4 - .incbin "baserom.gba", 0xDE8B4, 0x64 - - .global gUnknown_80DE918 -gUnknown_80DE918: @ 80DE918 - .incbin "baserom.gba", 0xDE918, 0x24 - - .global gUnknown_80DE93C -gUnknown_80DE93C: @ 80DE93C - .incbin "baserom.gba", 0xDE93C, 0x18 - - .global gUnknown_80DE954 -gUnknown_80DE954: @ 80DE954 - .incbin "baserom.gba", 0xDE954, 0x38 - - .global gUnknown_80DE98C -gUnknown_80DE98C: @ 80DE98C - .incbin "baserom.gba", 0xDE98C, 0x64 - - .global gUnknown_80DE9F0 -gUnknown_80DE9F0: @ 80DE9F0 - .incbin "baserom.gba", 0xDE9F0, 0x68 - - .global gUnknown_80DEA58 -gUnknown_80DEA58: @ 80DEA58 - .incbin "baserom.gba", 0xDEA58, 0x5C - - .global gUnknown_80DEAB4 -gUnknown_80DEAB4: @ 80DEAB4 - .incbin "baserom.gba", 0xDEAB4, 0x64 - - .global gUnknown_80DEB18 -gUnknown_80DEB18: @ 80DEB18 - .incbin "baserom.gba", 0xDEB18, 0x3C - - .global gUnknown_80DEB54 -gUnknown_80DEB54: @ 80DEB54 - .incbin "baserom.gba", 0xDEB54, 0xAC - - .global gUnknown_80DEC00 -gUnknown_80DEC00: @ 80DEC00 - .incbin "baserom.gba", 0xDEC00, 0x70 - - .global gUnknown_80DEC70 -gUnknown_80DEC70: @ 80DEC70 - .incbin "baserom.gba", 0xDEC70, 0x50 - - .global gUnknown_80DECC0 -gUnknown_80DECC0: @ 80DECC0 - .incbin "baserom.gba", 0xDECC0, 0x3C - - .global gUnknown_80DECFC -gUnknown_80DECFC: @ 80DECFC - .incbin "baserom.gba", 0xDECFC, 0x48 - + .include "data/text/wonder_mail_1.inc" + .global gUnknown_80DED44 gUnknown_80DED44: @ 80DED44 .incbin "baserom.gba", 0xDED44, 0x4 @@ -1918,169 +1546,7 @@ gUnknown_80DEEBC: @ 80DEEBC gUnknown_80DEEE4: @ 80DEEE4 .incbin "baserom.gba", 0xDEEE4, 0x20 - .global gUnknown_80DEF04 -gUnknown_80DEF04: @ 80DEF04 - .incbin "baserom.gba", 0xDEF04, 0x24 - - .global gUnknown_80DEF28 -gUnknown_80DEF28: @ 80DEF28 - .incbin "baserom.gba", 0xDEF28, 0x58 - - .global gUnknown_80DEF80 -gUnknown_80DEF80: @ 80DEF80 - .incbin "baserom.gba", 0xDEF80, 0x5C - - .global gUnknown_80DEFDC -gUnknown_80DEFDC: @ 80DEFDC - .incbin "baserom.gba", 0xDEFDC, 0x68 - - .global gUnknown_80DF044 -gUnknown_80DF044: @ 80DF044 - .incbin "baserom.gba", 0xDF044, 0x5C - - .global gUnknown_80DF0A0 -gUnknown_80DF0A0: @ 80DF0A0 - .incbin "baserom.gba", 0xDF0A0, 0x40 - - .global gUnknown_80DF0E0 -gUnknown_80DF0E0: @ 80DF0E0 - .incbin "baserom.gba", 0xDF0E0, 0x58 - - .global gUnknown_80DF138 -gUnknown_80DF138: @ 80DF138 - .incbin "baserom.gba", 0xDF138, 0x5C - - .global gUnknown_80DF194 -gUnknown_80DF194: @ 80DF194 - .incbin "baserom.gba", 0xDF194, 0x2C - - .global gUnknown_80DF1C0 -gUnknown_80DF1C0: @ 80DF1C0 - .incbin "baserom.gba", 0xDF1C0, 0x48 - - .global gUnknown_80DF208 -gUnknown_80DF208: @ 80DF208 - .incbin "baserom.gba", 0xDF208, 0x48 - - .global gUnknown_80DF250 -gUnknown_80DF250: @ 80DF250 - .incbin "baserom.gba", 0xDF250, 0xB4 - - .global gUnknown_80DF304 -gUnknown_80DF304: @ 80DF304 - .incbin "baserom.gba", 0xDF304, 0x2C - - .global gUnknown_80DF330 -gUnknown_80DF330: @ 80DF330 - .incbin "baserom.gba", 0xDF330, 0x50 - - .global gUnknown_80DF380 -gUnknown_80DF380: @ 80DF380 - .incbin "baserom.gba", 0xDF380, 0x34 - - .global gUnknown_80DF3B4 -gUnknown_80DF3B4: @ 80DF3B4 - .incbin "baserom.gba", 0xDF3B4, 0x64 - - .global gUnknown_80DF418 -gUnknown_80DF418: @ 80DF418 - .incbin "baserom.gba", 0xDF418, 0x34 - - .global gUnknown_80DF44C -gUnknown_80DF44C: @ 80DF44C - .incbin "baserom.gba", 0xDF44C, 0x20 - - .global gUnknown_80DF46C -gUnknown_80DF46C: @ 80DF46C - .incbin "baserom.gba", 0xDF46C, 0x88 - - .global gUnknown_80DF4F4 -gUnknown_80DF4F4: @ 80DF4F4 - .incbin "baserom.gba", 0xDF4F4, 0x50 - - .global gUnknown_80DF544 -gUnknown_80DF544: @ 80DF544 - .incbin "baserom.gba", 0xDF544, 0x50 - - .global gUnknown_80DF594 -gUnknown_80DF594: @ 80DF594 - .incbin "baserom.gba", 0xDF594, 0x50 - - .global gUnknown_80DF5E4 -gUnknown_80DF5E4: @ 80DF5E4 - .incbin "baserom.gba", 0xDF5E4, 0x58 - - .global gUnknown_80DF63C -gUnknown_80DF63C: @ 80DF63C - .incbin "baserom.gba", 0xDF63C, 0x58 - - .global gUnknown_80DF694 -gUnknown_80DF694: @ 80DF694 - .incbin "baserom.gba", 0xDF694, 0x5C - - .global gUnknown_80DF6F0 -gUnknown_80DF6F0: @ 80DF6F0 - .incbin "baserom.gba", 0xDF6F0, 0x20 - - .global gUnknown_80DF710 -gUnknown_80DF710: @ 80DF710 - .incbin "baserom.gba", 0xDF710, 0x2C - - .global gUnknown_80DF73C -gUnknown_80DF73C: @ 80DF73C - .incbin "baserom.gba", 0xDF73C, 0x40 - - .global gUnknown_80DF77C -gUnknown_80DF77C: @ 80DF77C - .incbin "baserom.gba", 0xDF77C, 0x58 - - .global gUnknown_80DF7D4 -gUnknown_80DF7D4: @ 80DF7D4 - .incbin "baserom.gba", 0xDF7D4, 0x9C - - .global gUnknown_80DF870 -gUnknown_80DF870: @ 80DF870 - .incbin "baserom.gba", 0xDF870, 0x44 - - .global gUnknown_80DF8B4 -gUnknown_80DF8B4: @ 80DF8B4 - .incbin "baserom.gba", 0xDF8B4, 0x38 - - .global gUnknown_80DF8EC -gUnknown_80DF8EC: @ 80DF8EC - .incbin "baserom.gba", 0xDF8EC, 0x3C - - .global gUnknown_80DF928 -gUnknown_80DF928: @ 80DF928 - .incbin "baserom.gba", 0xDF928, 0x24 - - .global gUnknown_80DF94C -gUnknown_80DF94C: @ 80DF94C - .incbin "baserom.gba", 0xDF94C, 0x20 - - .global gUnknown_80DF96C -gUnknown_80DF96C: @ 80DF96C - .incbin "baserom.gba", 0xDF96C, 0x38 - - .global gUnknown_80DF9A4 -gUnknown_80DF9A4: @ 80DF9A4 - .incbin "baserom.gba", 0xDF9A4, 0x4C - - .global gUnknown_80DF9F0 -gUnknown_80DF9F0: @ 80DF9F0 - .incbin "baserom.gba", 0xDF9F0, 0x8 - - .global gUnknown_80DF9F8 -gUnknown_80DF9F8: @ 80DF9F8 - .incbin "baserom.gba", 0xDF9F8, 0xB0 - - .global gUnknown_80DFAA8 -gUnknown_80DFAA8: @ 80DFAA8 - .incbin "baserom.gba", 0xDFAA8, 0x6C - - .global gUnknown_80DFB14 -gUnknown_80DFB14: @ 80DFB14 - .incbin "baserom.gba", 0xDFB14, 0xBC + .include "data/text/wonder_mail_2.inc" .global gUnknown_80DFBD0 gUnknown_80DFBD0: @ 80DFBD0 @@ -2194,73 +1660,13 @@ gUnknown_80DFE04: @ 80DFE04 gUnknown_80DFE1C: @ 80DFE1C .incbin "baserom.gba", 0xDFE1C, 0x30 - .global gUnknown_80DFE4C -gUnknown_80DFE4C: @ 80DFE4C - .incbin "baserom.gba", 0xDFE4C, 0x50 - - .global gUnknown_80DFE9C -gUnknown_80DFE9C: @ 80DFE9C - .incbin "baserom.gba", 0xDFE9C, 0x34 - - .global gUnknown_80DFED0 -gUnknown_80DFED0: @ 80DFED0 - .incbin "baserom.gba", 0xDFED0, 0x5C - - .global gUnknown_80DFF2C -gUnknown_80DFF2C: @ 80DFF2C - .incbin "baserom.gba", 0xDFF2C, 0x78 - - .global gUnknown_80DFFA4 -gUnknown_80DFFA4: @ 80DFFA4 - .incbin "baserom.gba", 0xDFFA4, 0x6C - - .global gUnknown_80E0010 -gUnknown_80E0010: @ 80E0010 - .incbin "baserom.gba", 0xE0010, 0x64 - - .global gUnknown_80E0074 -gUnknown_80E0074: @ 80E0074 - .incbin "baserom.gba", 0xE0074, 0x20 - - .global gUnknown_80E0094 -gUnknown_80E0094: @ 80E0094 - .incbin "baserom.gba", 0xE0094, 0x74 - - .global gUnknown_80E0108 -gUnknown_80E0108: @ 80E0108 - .incbin "baserom.gba", 0xE0108, 0x44 - - .global gUnknown_80E014C -gUnknown_80E014C: @ 80E014C - .incbin "baserom.gba", 0xE014C, 0xC - - .global gUnknown_80E0158 -gUnknown_80E0158: @ 80E0158 - .incbin "baserom.gba", 0xE0158, 0x14 + .include "data/text/wonder_mail_3.inc" .global gUnknown_80E016C gUnknown_80E016C: @ 80E016C .incbin "baserom.gba", 0xE016C, 0x18 - .global gUnknown_80E0184 -gUnknown_80E0184: @ 80E0184 - .incbin "baserom.gba", 0xE0184, 0x1C - - .global gUnknown_80E01A0 -gUnknown_80E01A0: @ 80E01A0 - .incbin "baserom.gba", 0xE01A0, 0x24 - - .global gUnknown_80E01C4 -gUnknown_80E01C4: @ 80E01C4 - .incbin "baserom.gba", 0xE01C4, 0x2C - - .global gUnknown_80E01F0 -gUnknown_80E01F0: @ 80E01F0 - .incbin "baserom.gba", 0xE01F0, 0x28 - - .global gUnknown_80E0218 -gUnknown_80E0218: @ 80E0218 - .incbin "baserom.gba", 0xE0218, 0x30 + .include "data/text/wonder_mail_complete.inc" .global gUnknown_80E0248 gUnknown_80E0248: @ 80E0248 @@ -2530,73 +1936,7 @@ gUnknown_80E0B3C: @ 80E0B3C gUnknown_80E0BD4: @ 80E0BD4 .incbin "baserom.gba", 0xE0BD4, 0x78 - .global gUnknown_80E0C4C -gUnknown_80E0C4C: @ 80E0C4C - .incbin "baserom.gba", 0xE0C4C, 0x24 - - .global gUnknown_80E0C70 -gUnknown_80E0C70: @ 80E0C70 - .incbin "baserom.gba", 0xE0C70, 0x160 - - .global gUnknown_80E0DD0 -gUnknown_80E0DD0: @ 80E0DD0 - .incbin "baserom.gba", 0xE0DD0, 0x108 - - .global gUnknown_80E0ED8 -gUnknown_80E0ED8: @ 80E0ED8 - .incbin "baserom.gba", 0xE0ED8, 0x1F0 - - .global gUnknown_80E10C8 -gUnknown_80E10C8: @ 80E10C8 - .incbin "baserom.gba", 0xE10C8, 0x144 - - .global gUnknown_80E120C -gUnknown_80E120C: @ 80E120C - .incbin "baserom.gba", 0xE120C, 0x160 - - .global gUnknown_80E136C -gUnknown_80E136C: @ 80E136C - .incbin "baserom.gba", 0xE136C, 0xB4 - - .global gUnknown_80E1420 -gUnknown_80E1420: @ 80E1420 - .incbin "baserom.gba", 0xE1420, 0x15C - - .global gUnknown_80E157C -gUnknown_80E157C: @ 80E157C - .incbin "baserom.gba", 0xE157C, 0x120 - - .global gUnknown_80E169C -gUnknown_80E169C: @ 80E169C - .incbin "baserom.gba", 0xE169C, 0x12C - - .global gUnknown_80E17C8 -gUnknown_80E17C8: @ 80E17C8 - .incbin "baserom.gba", 0xE17C8, 0x74 - - .global gUnknown_80E183C -gUnknown_80E183C: @ 80E183C - .incbin "baserom.gba", 0xE183C, 0x2C - - .global gUnknown_80E1868 -gUnknown_80E1868: @ 80E1868 - .incbin "baserom.gba", 0xE1868, 0x1C8 - - .global gUnknown_80E1A30 -gUnknown_80E1A30: @ 80E1A30 - .incbin "baserom.gba", 0xE1A30, 0xA8 - - .global gUnknown_80E1AD8 -gUnknown_80E1AD8: @ 80E1AD8 - .incbin "baserom.gba", 0xE1AD8, 0xB0 - - .global gUnknown_80E1B88 -gUnknown_80E1B88: @ 80E1B88 - .incbin "baserom.gba", 0xE1B88, 0x1FC - - .global gUnknown_80E1D84 -gUnknown_80E1D84: @ 80E1D84 - .incbin "baserom.gba", 0xE1D84, 0x178 + .include "data/text/wonder_mail_4.inc" .global gUnknown_80E1EFC gUnknown_80E1EFC: @ 80E1EFC diff --git a/data/text/luminous_cave.inc b/data/text/luminous_cave.inc new file mode 100644 index 0000000..6956c7f --- /dev/null +++ b/data/text/luminous_cave.inc @@ -0,0 +1,137 @@ +gUnknown_80DCA34:: @ 80DCA34 + .string "#+...#WA voice emanates from somewhere...#P#+...Ye who seek awak" + .string "ening...#P#+This is Luminous Cave.#W\n" + .string "#+Do ye seek a new evolution?" + .byte 0 + .align 2, 0 + +gUnknown_80DCAB8:: @ 80DCAB8 + .string "#+Do ye seek evolution?" + .byte 0 + .align 2, 0 + +gUnknown_80DCAD0:: @ 80DCAD0 + .string "#+There are those among Pokémon\n" + .string "#+that can evolve.#P#+Such Pokémon can evolve at this very\n" + .string "#+spot if they satisfy certain conditions.#P#+Evolution brings a" + .string "bout changes\n" + .string "#+in appearance and abilities.#P#+Not only that~2c some Pokémon even change\n" + .string "#+type and learn different moves.#P#+However...#W The requiremen" + .string "ts for\n" + .string "#+evolution differ among Pokémon.#P#+Some become ready for evolution\n" + .string "#+merely by leveling up.#P#+Still others may need special items\n" + .string "#+to attain evolution.#P#+Ye must also be aware of this:#P#+Once" + .string " it has evolved~2c a Pokémon\n" + .string "#+can never regain its previous form.#P#+That is why ye must thi" + .string "nk carefully\n" + .string "#+before committing to evolution." + .byte 0 + .align 2, 0 + +gUnknown_80DCD5C:: @ 80DCD5C + .string "#+Ye shall return if evolution\n" + .string "#+is what ye seek..." + .byte 0 + .align 2, 0 + +gUnknown_80DCD90:: @ 80DCD90 + .string "#+Will ye give an item for evolution?" + .byte 0 + .align 2, 0 + +gUnknown_80DCDB8:: @ 80DCDB8 + .string "#+Will ye give yet another item?" + .byte 0 + .align 2, 0 + +gUnknown_80DCDDC:: @ 80DCDDC + .string "#+Alas~2c ye seem to lack what is needed\n" + .string "#+for evolution." + .byte 0 + .align 2, 0 + +gUnknown_80DCE18:: @ 80DCE18 + .string "#+Ye seem to have but one item." + .byte 0 + .align 2, 0 + +gUnknown_80DCE38:: @ 80DCE38 + .string "#+...Ye who seek awakening...\n" + .string "#+Let us begin." + .byte 0 + .align 2, 0 + +gUnknown_80DCE68:: @ 80DCE68 + .string "#+...#W" + .byte 0x24 + .string "n0 is undergoing changes...#P#+" + .byte 0x24 + .string "n0~27s appearance changed...#P" + .byte 0 + .align 2, 0 + +gUnknown_80DCEB0:: @ 80DCEB0 + .string "#+It evolved from #C4" + .byte 0x24 + .string "m0#R\n" + .string "#+to #C6" + .byte 0x24 + .string "m1#R!" + .byte 0 + .align 2, 0 + +gUnknown_80DCEDC:: @ 80DCEDC + .string "#+...#P#+One cannot evolve if one\n" + .string "#+is in the company of others.#P#+Come alone if ye wish to evolve." + .byte 0 + .align 2, 0 + +gUnknown_80DCF44:: @ 80DCF44 + .string "#+...#P#+Ye cannot evolve yet.#P#+Ye have not high enough a level." + .byte 0 + .align 2, 0 + +gUnknown_80DCF88:: @ 80DCF88 + .string "#+...#P#+Ye cannot evolve anymore." + .byte 0 + .align 2, 0 + +gUnknown_80DCFAC:: @ 80DCFAC + .string "#+...#P#+Ye cannot evolve yet.#P#+Ye need your Friend Area to evolve." + .byte 0 + .align 2, 0 + +gUnknown_80DCFF4:: @ 80DCFF4 + .string "#+...#P#+Ye cannot evolve yet.#P#+The Friend Area to which ye shall go\n" + .string "#+has no room for ye." + .byte 0 + .align 2, 0 + +gUnknown_80DD054:: @ 80DD054 + .string "#+...#P#+Ye cannot evolve yet.#P#+Ye seem to lack the IQ to evolve." + .byte 0 + .align 2, 0 + +gUnknown_80DD098:: @ 80DD098 + .string "#+#+...#P#+Ye cannot evolve yet.#P#+Ye seem to lack an item to evolve." + .byte 0 + .align 2, 0 + +gUnknown_80DD0E0:: @ 80DD0E0 + .string "#+#+...#P#+Ye cannot evolve yet. " + .byte 0 + .align 2, 0 + +gUnknown_80DD104:: @ 80DD104 + .string "#+Ye must give a name to\n" + .string "#+the evolved Pokémon. " + .byte 0 + .align 2, 0 + + .string "pksdir0" + .byte 0 + .align 2, 0 + + .string "pksdir0" + .byte 0 + .align 2, 0 diff --git a/data/text/party_menu.inc b/data/text/party_menu.inc new file mode 100644 index 0000000..eaaabd1 --- /dev/null +++ b/data/text/party_menu.inc @@ -0,0 +1,147 @@ +gUnknown_80DD388:: @ 80DD388 + .string "You have chosen to say farewell\n" + .string "to this Pokémon.#PThe Pokémon will leave its Friend Area.\n" + .string "It will no longer be available for\n" + .string "adventures. Is that OK?" + .byte 0 + .align 2, 0 + +gUnknown_80DD420:: @ 80DD420 + .string "If you say farewell to this\n" + .string "Pokémon~2c it will be gone forever.#PYou will never be able to get another one\n" + .string "like it to join your team.\n" + .string "Will you release it anyway?" + .byte 0 + .align 2, 0 + +gUnknown_80DD4C4:: @ 80DD4C4 + .string "#+" + .byte 0x24 + .string "m1 joined the\n" + .string "#+rescue team for adventures!" + .byte 0 + .align 2, 0 + +gUnknown_80DD4F4:: @ 80DD4F4 + .string "#+" + .byte 0x24 + .string "m1 left the team to remain\n" + .string "#+on standby in the Friend Area." + .byte 0 + .align 2, 0 + +gUnknown_80DD534:: @ 80DD534 + .string "#+" + .byte 0x24 + .string "m1 became the leader\n" + .string "#+of the rescue team." + .byte 0 + .align 2, 0 + +gUnknown_80DD564:: @ 80DD564 + .string "#+" + .byte 0x24 + .string "m1 left\n" + .string "#+the Friend Area.\n" + .string "#+Bye-bye~2c " + .byte 0x24 + .string "m1!" + .byte 0 +gUnknown_80DD594:: @ 80DD594 + .string "#+The #C4" + .byte 0x24 + .string "i1#R was\n" + .string "#+handed over. " + .byte 0 + .align 2, 0 + +gUnknown_80DD5B8:: @ 80DD5B8 + .string "#+The #C4" + .byte 0x24 + .string "i1#R was\n" + .string "#+handed over.#P#+The #C4" + .byte 0x24 + .string "i0#R was\n" + .string "#+returned to the Toolbox." + .byte 0 + .align 2, 0 + +gUnknown_80DD60C:: @ 80DD60C + .string "#+The #C4" + .byte 0x24 + .string "i0#R was\n" + .string "#+returned to the Toolbox." + .byte 0 + .align 2, 0 + +gUnknown_80DD63C:: @ 80DD63C + .string "#+The #C4" + .byte 0x24 + .string "i0#R was\n" + .string "#+sent to storage." + .byte 0 + .align 2, 0 + +gUnknown_80DD664:: @ 80DD664 + .string "Stand By" + .byte 0 + .align 2, 0 +gUnknown_80DD670:: @ 80DD670 + .string "Make Leader" + .byte 0 + +gUnknown_80DD67C:: @ 80DD67C + .string "Join Team" + .byte 0 + .align 2, 0 + +gUnknown_80DD688:: @ 80DD688 + .string "Give Gummi" + .byte 0 + .align 2, 0 + +gUnknown_80DD694:: @ 80DD694 + .string "Give" + .byte 0 + .align 2, 0 + +gUnknown_80DD69C:: @ 80DD69C + .string "Take" + .byte 0 + .align 2, 0 + +gUnknown_80DD6A4:: @ 80DD6A4 + .string "Say Farewell" + .byte 0 + .align 2, 0 + +gUnknown_80DD6B4:: @ 80DD6B4 + .string "Summary" + .byte 0 + .align 2, 0 + +gUnknown_80DD6BC:: @ 80DD6BC + .string "Moves" + .byte 0 + .align 2, 0 + +gUnknown_80DD6C4:: @ 80DD6C4 + .string "Check IQ" + .byte 0 + .align 2, 0 + +gUnknown_80DD6D0:: @ 80DD6D0 + .string "Item: #C4" + .byte 0x24 + .string "i0#R " + .byte 0 + .align 2, 0 + +gUnknown_80DD6E0:: @ 80DD6E0 + .string "%s" + .byte 0 + .align 2, 0 + + .string "pksdir0" + .byte 0 + .align 2, 0 diff --git a/data/text/save.inc b/data/text/save.inc new file mode 100644 index 0000000..a944a8d --- /dev/null +++ b/data/text/save.inc @@ -0,0 +1,58 @@ +gUnknown_80B6A34:: @ 80B6A34 + .string "#+Quicksaving your adventure...\n" + .string "#+Please don~27t turn off the power." + .byte 0 + .align 2, 0 + +gUnknown_80B6A7C:: @ 80B6A7C + .string "#+Your adventure has been saved." + .byte 0 + .align 2, 0 + +gUnknown_80B6AA0:: @ 80B6AA0 + .string "#+Your adventure has been saved.\n" + .string "#+When you are in a dungeon~2c quicksave\n" + .string "#+your progress before ending the game." + .byte 0 + .align 2, 0 + +gUnknown_80B6B14:: @ 80B6B14 + .string "#+The data could not be written.\n" + .string "#+Please turn off the power and remove\n" + .string "#+and reinsert the DS Card." + .byte 0 + .align 2, 0 + +gUnknown_80B6B78:: @ 80B6B78 + .string "#+Save failed." + .byte 0 + .align 2, 0 + +gUnknown_80B6B88:: @ 80B6B88 + .string "#+Error reading data.\n" + .string "#+Please turn off the power and reinsert\n" + .string "#+the DS Game Card." + .byte 0 + .align 2, 0 + +gUnknown_80B6BDC:: @ 80B6BDC + .string "#+Your data was not properly saved~2c\n" + .string "#+so your game cannot be resumed\n" + .string "#+from your last spot.#P#+Your last outing is considered a defeat.\n" + .string "#+Before shutting down~2c save in your\n" + .string "#+team base~2c or quicksave in a dungeon." + .byte 0 + .align 2, 0 + +gUnknown_80B6CB8:: @ 80B6CB8 + .string "#+You may not resume your dungeon\n" + .string "#+adventure using this saved data.\n" + .string "#+Your last outing is considered a defeat." + .byte 0 + .align 2, 0 + + .string "pksdir0" + .byte 0 + .align 2, 0 + + .incbin "baserom.gba", 0xB6D30, 0x60 diff --git a/data/text/wonder_mail_1.inc b/data/text/wonder_mail_1.inc new file mode 100644 index 0000000..0c6915e --- /dev/null +++ b/data/text/wonder_mail_1.inc @@ -0,0 +1,350 @@ +gUnknown_80DDBA8:: @ 80DDBA8 + .string " What you need to do is\n" + .string "tell your friend--the one you rescued--\n" + .string "this here password." + .byte 0 + .align 2, 0 + +gUnknown_80DDBFC:: @ 80DDBFC + .string " All righty!\n" + .string "Here~27s your #CGA-OK Mail password#R." + .byte 0 + .align 2, 0 + +gUnknown_80DDC30:: @ 80DDC30 + .string " Okeydoke! That~27s all done.\n" + .string "Come around whenever you need." + .byte 0 + .align 2, 0 + +gUnknown_80DDC70:: @ 80DDC70 + .string " Okeydoke! I sent off your\n" + .string "#CGA-OK Mail#R.#P Let me save your adventure." + .byte 0 + .align 2, 0 + +gUnknown_80DDCBC:: @ 80DDCBC + .string "#+Please choose the Pokémon you want to\n" + .string "#+send as a helper to your friend.\n" + .string "#+(Its hold item will not be sent.)" + .byte 0 + .align 2, 0 + +gUnknown_80DDD2C:: @ 80DDD2C + .string " ...Uh~2c no?\n" + .string "There appear to be no Pokémon in your\n" + .string "Friend Areas. What do you want to do?" + .byte 0 + .align 2, 0 + +gUnknown_80DDD88:: @ 80DDD88 + .string " You~27re sure you want to\n" + .string "send this here Pokémon?" + .byte 0 + .align 2, 0 + +gUnknown_80DDDBC:: @ 80DDDBC + .string " You~27re sure about this?" + .byte 0 + .align 2, 0 + +gUnknown_80DDDD8:: @ 80DDDD8 + .string " All righty. I need you to\n" + .string "pick the #CGA-OK Mail#R you want to send." + .byte 0 + .align 2, 0 + +gUnknown_80DDE20:: @ 80DDE20 + .string " ...Uh~2c no?\n" + .string "I don~27t see any #CGA-OK Mail#R here." + .byte 0 + .align 2, 0 + +gUnknown_80DDE58:: @ 80DDE58 + .string " Did you know? If you use\n" + .string "a #CGGame Link cable#R~2c you can send\n" + .string "a #CGhelper Pokémon#R to your friend." + .byte 0 + .align 2, 0 + +gUnknown_80DDEC0:: @ 80DDEC0 + .string " Don~27t you worry. Sending\n" + .string "a Pokémon doesn~27t mean it will go away.\n" + .string "So! Want to send one to your friend?" + .byte 0 + .align 2, 0 + +gUnknown_80DDF2C:: @ 80DDF2C + .string " ...Uh~2c no?\n" + .string "There~27s no space at all to receive\n" + .string "any more mail.#P Delete some old mail~2c\n" + .string "and then come to me to receive\n" + .string "your mail~2c OK?" + .byte 0 + .align 2, 0 + +gUnknown_80DDFB8:: @ 80DDFB8 + .string " All righty! Connect up\n" + .string "the #CGGame Link cable#R~2c if you~27d please.\n" + .string "Your friend ready~2c too?" + .byte 0 + .align 2, 0 + +gUnknown_80DE01C:: @ 80DE01C + .incbin "baserom.gba", 0xDE01C, 0x50 + +gUnknown_80DE06C:: @ 80DE06C + .string " Okeydoke!\n" + .string "I received your friend~27s #CGSOS Mail#R.#P Let me save your adventure." + .byte 0 + .align 2, 0 + +gUnknown_80DE0C0:: @ 80DE0C0 + .string " Okeydoke! You~27re good to go.\n" + .string "Just give me a shout when you~27d like\n" + .string "to go rescue your friend." + .byte 0 + .align 2, 0 + +gUnknown_80DE124:: @ 80DE124 + .string " OK~2c I need you to enter\n" + .string "the #CGSOS Mail password#R that your\n" + .string "friend gave you." + .byte 0 + .align 2, 0 + +gUnknown_80DE178:: @ 80DE178 + .string " How do you want to receive\n" + .string "your friend~27s #CGSOS Mail#R?" + .byte 0 + .align 2, 0 + +gUnknown_80DE1B4:: @ 80DE1B4 + .string " How do you want to send\n" + .string "your #CGA-OK Mail#R?" + .byte 0 + .align 2, 0 + +gUnknown_80DE1E4:: @ 80DE1E4 + .string " ...Uh~2c no?\n" + .string "You don~27t have an #CGSOS Mail#R.#P You~27ll need to arrange\n" + .string "to receive your friend~27s #CGSOS Mail#R first.\n" + .string "That~27s what you need to do." + .byte 0 + .align 2, 0 + +gUnknown_80DE280:: @ 80DE280 + .string " Okeydoke!\n" + .string "Let me show you to the rescue site." + .byte 0 + .align 2, 0 + +gUnknown_80DE2B0:: @ 80DE2B0 + .string " ...Uh~2c no?\n" + .string "Doesn~27t look like you can go to the dungeon\n" + .string "named in this #CGSOS Mail#R.#P Come see me about doing\n" + .string "this rescue when you can actually go\n" + .string "to that dungeon~2c all right?" + .byte 0 + .align 2, 0 + +gUnknown_80DE368:: @ 80DE368 + .string " ...Uh~2c no?\n" + .string "You~27ve blown this rescue mission too\n" + .string "often. Your friend~27s team is beyond help.#P I~27m sorry to say this~2c\n" + .string "but you~27ll have to tell your friend that\n" + .string "your rescue attempts failed." + .byte 0 + .align 2, 0 + +gUnknown_80DE430:: @ 80DE430 + .string " Okeydoke.\n" + .string "I~27ll need you to choose the #CGSOS Mail#R\n" + .string "for you to go on a rescue mission." + .byte 0 + .align 2, 0 + +gUnknown_80DE48C:: @ 80DE48C + .string " What kind of mail do you\n" + .string "want to delete?" + .byte 0 + .align 2, 0 + +gUnknown_80DE4B8:: @ 80DE4B8 + .string " All righty. Choose\n" + .string "the #CGSOS Mail#R you don~27t need." + .byte 0 + +gUnknown_80DE4F0:: @ 80DE4F0 + .string " ...Uh~2c no?\n" + .string "You don~27t have any #CGSOS Mail#R." + .byte 0 + .align 2, 0 + +gUnknown_80DE524:: @ 80DE524 + .string " If you want a reward~2c #C2don~27t\n" + .string "delete an A-OK Mail#R before getting a\n" + .string "#CGThank-You Mail#R back for it.#P #C2Be careful#R if you~27re g" + .string "oing\n" + .string "to delete any #CGA-OK Mail#R.#P Okeydoke.\n" + .string "Choose an #CGA-OK Mail#R\n" + .string "you don~27t need anymore." + .byte 0 + .align 2, 0 + +gUnknown_80DE614:: @ 80DE614 + .string " ...Uh~2c no?\n" + .string "You don~27t have any #CGA-OK Mail#R." + .byte 0 + .align 2, 0 + +gUnknown_80DE648:: @ 80DE648 + .string " Uh~2c OK.\n" + .string "So~2c you want me to delete every piece\n" + .string "of mail that you have." + .byte 0 + .align 2, 0 + +gUnknown_80DE694:: @ 80DE694 + .string " ...Uh~2c no?\n" + .string "You don~27t have a single piece of\n" + .string "mail on you!" + .byte 0 + .align 2, 0 + +gUnknown_80DE6D4:: @ 80DE6D4 + .string " So~2c delete all your #CGSOS Mail#R~2c\n" + .string "#CGA-OK Mail#R~2c and your #CGThank-You Mail#R?\n" + .string "You~27re absolutely~2c positively sure?" + .byte 0 + +gUnknown_80DE754:: @ 80DE754 + .string " If I delete any mail~2c it~27s\n" + .string "gone forever and ever. Bye-bye.\n" + .string "You~27re really~2c really sure now?" + .byte 0 + +gUnknown_80DE7B8:: @ 80DE7B8 + .string " OK~2c then.\n" + .string "Let me save your adventure now." + .byte 0 + .align 2, 0 + +gUnknown_80DE7E8:: @ 80DE7E8 + .string " Okeydoke. That~27s all done." + .byte 0 + .align 2, 0 + +gUnknown_80DE808:: @ 80DE808 + .string " Do you want to delete\n" + .string "any other mail?" + .byte 0 + .align 2, 0 + +gUnknown_80DE830:: @ 80DE830 + .string " Okeydoke.\n" + .string "I~27ll delete #CGevery piece of mail#R." + .byte 0 + .align 2, 0 + +gUnknown_80DE864:: @ 80DE864 + .string " Okeydoke.\n" + .string "Every bit of mail has been deleted.#P Let me save your adventure" + .string "." + .byte 0 + .align 2, 0 + +gUnknown_80DE8B4:: @ 80DE8B4 + .string " Well~2c hello~2c there!\n" + .string "This is the #CGFriend Rescue#R counter.\n" + .string "What can I help you with today?" + .byte 0 + .align 2, 0 + +gUnknown_80DE918:: @ 80DE918 + .string " Help you with anything\n" + .string "else today?" + .byte 0 + +gUnknown_80DE93C:: @ 80DE93C + .string " Come again anytime!" + .byte 0 + .align 2, 0 + +gUnknown_80DE954:: @ 80DE954 + .string " ...Uh~2c no?\n" + .string "Something~27s not working right here..." + .byte 0 + .align 2, 0 + +gUnknown_80DE98C:: @ 80DE98C + .string " ...Uh~2c no?\n" + .string "The number of GBA systems isn~27t right.\n" + .string "You~27d better try this again from the top." + .byte 0 + .align 2, 0 + +gUnknown_80DE9F0:: @ 80DE9F0 + .string " ...Uh~2c no? You~27re not in the\n" + .string "same mode as your friend.\n" + .string "You~27d better try this again from the top." + .byte 0 + +gUnknown_80DEA58:: @ 80DEA58 + .string " ...Uh~2c no?\n" + .string "Your storage space is stuffed full.\n" + .string "You~27d better make room and try again." + .byte 0 + .align 2, 0 + +gUnknown_80DEAB4:: @ 80DEAB4 + .string " ...Uh~2c no? It looks like\n" + .string "you received this mail before.\n" + .string "You can~27t get the same mail twice. " + .byte 0 + .align 2, 0 + +gUnknown_80DEB18:: @ 80DEB18 + .string " ...Uh~2c no?\n" + .string "You~27re not eligible to receive this mail." + .byte 0 + .align 2, 0 + +gUnknown_80DEB54:: @ 80DEB54 + .string " ...Uh~2c no?\n" + .string "There~27s no room for you to \n" + .string "receive any more mail.#P You~27d better delete some\n" + .string "mail and make room before you come see\n" + .string "me again about receiving new mail." + .byte 0 + .align 2, 0 + +gUnknown_80DEC00:: @ 80DEC00 + .string " ...Uh~2c no? Looks like your\n" + .string "friend didn~27t do what needed doing.\n" + .string "You~27d better do this again from the top." + .byte 0 + .align 2, 0 + +gUnknown_80DEC70:: @ 80DEC70 + .string " ...Uh~2c no?\n" + .string "This here password looks wrong.\n" + .string "Do you want to try that again?" + .byte 0 + .align 2, 0 + +gUnknown_80DECC0:: @ 80DECC0 + .string " ...Uh~2c no? This password~27s\n" + .string "not for any #CGSOS Mail#R." + .byte 0 + .align 2, 0 + +gUnknown_80DECFC:: @ 80DECFC + .string ": I received the #CGSOS Mail#R.\n" + .string "Your adventure will be saved." + .byte 0 + .align 2, 0 + + .string "pksdir0" + .byte 0 + .align 2, 0 diff --git a/data/text/wonder_mail_2.inc b/data/text/wonder_mail_2.inc new file mode 100644 index 0000000..1cc51b9 --- /dev/null +++ b/data/text/wonder_mail_2.inc @@ -0,0 +1,283 @@ +gUnknown_80DEF04:: @ 80DEF04 + .string " ...Oh?\n" + .string "Something~27s gone wrong." + .byte 0 + .align 2, 0 + +gUnknown_80DEF28:: @ 80DEF28 + .string " ...Oh? The number of linked\n" + .string "GBA systems is incorrect.\n" + .string "Please try again from the start." + .byte 0 + .align 2, 0 + +gUnknown_80DEF80:: @ 80DEF80 + .string " ...Oh? It looks like your\n" + .string "friend chose a different mode.\n" + .string "Please try again from the start." + .byte 0 + .align 2, 0 + +gUnknown_80DEFDC:: @ 80DEFDC + .string " ...Oh? It looks like your\n" + .string "storage space is full. Please clear some\n" + .string "space and try again from the start." + .byte 0 + .align 2, 0 + +gUnknown_80DF044:: @ 80DF044 + .string " ...Oh?\n" + .string "I think you~27ve received this mail before.\n" + .string "You can~27t get the same mail twice." + .byte 0 + .align 2, 0 + +gUnknown_80DF0A0:: @ 80DF0A0 + .string " ...Oh?\n" + .string "I don~27t think you~27re eligible to receive\n" + .string "this mail." + .byte 0 + .align 2, 0 + +gUnknown_80DF0E0:: @ 80DF0E0 + .string " ...Oh?\n" + .string "There is no room to receive new mail.\n" + .string "Please delete some mail and try again." + .byte 0 + .align 2, 0 + +gUnknown_80DF138:: @ 80DF138 + .string " ...Oh? Your friend didn~27t\n" + .string "follow through on their side.\n" + .string "Please try again from the start." + .byte 0 + .align 2, 0 + +gUnknown_80DF194:: @ 80DF194 + .string " Your #CGThank-You Mail#R\n" + .string "has been sent." + .byte 0 + .align 2, 0 + +gUnknown_80DF1C0:: @ 80DF1C0 + .string " ...Oh?\n" + .string "This password appears to be wrong.\n" + .string "Would you like to try again?" + .byte 0 + .align 2, 0 + +gUnknown_80DF208:: @ 80DF208 + .string " ...Oh? This password doesn~27t\n" + .string "appear to be for a #CGThank-You Mail#R." + .byte 0 + .align 2, 0 + +gUnknown_80DF250:: @ 80DF250 + .string ": This is the counter for\n" + .string "#CGThank-You Mail#R.#P: Oh~2c hi~2c #CN%s#R.\n" + .string "I~27ve been waiting for you. You wanted me\n" + .string "to process a #CGThank-You Mail#R?#P: Let me get on it right away" + .string "." + .byte 0 + .align 2, 0 + +gUnknown_80DF304:: @ 80DF304 + .string " Is it OK to send this\n" + .string "#CGThank-You Mail#R?" + .byte 0 + .align 2, 0 + +gUnknown_80DF330:: @ 80DF330 + .string " Please choose the\n" + .string "#CGThank-You Mail#R that you want to\n" + .string "send to your friend." + .byte 0 + .align 2, 0 + +gUnknown_80DF380:: @ 80DF380 + .string " OK. Please enter the\n" + .string "#CGThank-You Mail password#R." + .byte 0 + .align 2, 0 + +gUnknown_80DF3B4:: @ 80DF3B4 + .string " Please give this password\n" + .string "to the friend that rescued your team.#P I also must save your\n" + .string "adventure." + .byte 0 + .align 2, 0 + +gUnknown_80DF418:: @ 80DF418 + .string " OK~2c here is your\n" + .string "#CGThank-You Mail password#R." + .byte 0 + .align 2, 0 + +gUnknown_80DF44C:: @ 80DF44C + .string " I need to save your\n" + .string "adventure." + .byte 0 + .align 2, 0 + +gUnknown_80DF46C:: @ 80DF46C + .string " There we go.\n" + .string "I~27m all done.#P Doesn~27t it feel great to\n" + .string "be appreciated for doing something good?\n" + .string "Please keep up your rescue work!" + .byte 0 + .align 2, 0 + +gUnknown_80DF4F4:: @ 80DF4F4 + .string " A #CGThank-You Mail#R has\n" + .string "arrived from your friend for your rescue\n" + .string "mission." + .byte 0 + .align 2, 0 + +gUnknown_80DF544:: @ 80DF544 + .string "#+Communicating...\n" + .string "#+Please wait with the power on.\n" + .string "#+To cancel~2c press {B_BUTTON}." + .byte 0 + .align 2, 0 + +gUnknown_80DF594:: @ 80DF594 + .string " There. I~27ve sent your\n" + .string "#CGThank-You Mail#R.\n" + .string "I need to save your adventure." + .byte 0 + .align 2, 0 + +gUnknown_80DF5E4:: @ 80DF5E4 + .string " Please connect the GBA\n" + .string "systems with a #CGGame Link cable#R.\n" + .string "Is your friend also ready?" + .byte 0 + .align 2, 0 + +gUnknown_80DF63C:: @ 80DF63C + .string " There~2c all done.\n" + .string "#CN%s#R~2c I hope your friend\n" + .string "appreciates your sense of gratitude." + .byte 0 + .align 2, 0 + +gUnknown_80DF694:: @ 80DF694 + .string " The item you~27ve chosen\n" + .string "here can~27t be exchanged later.\n" + .string "Are you certain this item is OK?" + .byte 0 + .align 2, 0 + +gUnknown_80DF6F0:: @ 80DF6F0 + .string " I~27ve saved your adventure. " + .byte 0 + .align 2, 0 + +gUnknown_80DF710:: @ 80DF710 + .string " OK~2c please choose\n" + .string "the item to be sent." + .byte 0 + .align 2, 0 + +gUnknown_80DF73C:: @ 80DF73C + .string " ...Oh?\n" + .string "Your storage space is empty.\n" + .string "What would you like to do?" + .byte 0 + .align 2, 0 + +gUnknown_80DF77C:: @ 80DF77C + .string " Would you like to choose\n" + .string "a #CGreward item#R from storage and\n" + .string "send it with your mail?" + .byte 0 + .align 2, 0 + +gUnknown_80DF7D4:: @ 80DF7D4 + .string " ...Oh?\n" + .string "You~27ve already attached a #CGreward item#R\n" + .string "to this mail.#P I~27m sorry~2c but once an item\n" + .string "has been attached to mail~2c it can~27t be\n" + .string "exchanged." + .byte 0 + .align 2, 0 + +gUnknown_80DF870:: @ 80DF870 + .string " Would you like to send it\n" + .string "again with the item you chose before?" + .byte 0 + .align 2, 0 + +gUnknown_80DF8B4:: @ 80DF8B4 + .string " ...Oh?\n" + .string "You don~27t seem to have a #CGThank-You Mail#R." + .byte 0 + .align 2, 0 + +gUnknown_80DF8EC:: @ 80DF8EC + .string " Hello.\n" + .string "I handle #CGThank-You Mail#R.\n" + .string "How may I serve you?" + .byte 0 + .align 2, 0 + +gUnknown_80DF928:: @ 80DF928 + .string " May I help you with\n" + .string "anything else?" + .byte 0 + .align 2, 0 + +gUnknown_80DF94C:: @ 80DF94C + .string " Please come see me\n" + .string "anytime." + .byte 0 + .align 2, 0 + +gUnknown_80DF96C:: @ 80DF96C + .string " How would you like to send\n" + .string "your #CGThank-You Mail#R?" + .byte 0 + .align 2, 0 + +gUnknown_80DF9A4:: @ 80DF9A4 + .string " How would you like to\n" + .string "receive your friend~27s #CGThank-You Mail#R?" + .byte 0 + + .string "pksdir0" + .byte 0 + .align 2, 0 + +gUnknown_80DF9F0:: @ 80DF9F0 + .string "????" + .byte 0 + .align 2, 0 + +gUnknown_80DF9F8:: @ 80DF9F8 + .string " Oh~2c hello!\n" + .string "Your rescue mission went well~2c didn~27t it?\n" + .string "I wouldn~27t expect any less~2c #CG%s#R!#P Well~2c well!\n" + .string "Here is your reward from the Pokémon\n" + .string "Rescue Organization!" + .byte 0 + .align 2, 0 + +gUnknown_80DFAA8:: @ 80DFAA8 + .string " I hope you will keep on\n" + .string "rescuing your friends in\n" + .string "dire straits.#P And now~2c I must save\n" + .string "your adventure." + .byte 0 + .align 2, 0 + +gUnknown_80DFB14:: @ 80DFB14 + .string " Oh~2c yes~2c that~27s right.\n" + .string "Please don~27t forget to send an #CGA-OK Mail#R\n" + .string "to the friend you just rescued.#P Please give me a shout if\n" + .string "you would like to send #CGA-OK Mail#R." + .byte 0 + .align 2, 0 + + .string "pksdir0" + .byte 0 diff --git a/data/text/wonder_mail_3.inc b/data/text/wonder_mail_3.inc new file mode 100644 index 0000000..1aa2213 --- /dev/null +++ b/data/text/wonder_mail_3.inc @@ -0,0 +1,68 @@ +gUnknown_80DFE4C:: @ 80DFE4C + .string "Are you sure you want to replace the\n" + .string "old #CGWonder Mail#R with the new one?" + .byte 0 + .align 2, 0 + +gUnknown_80DFE9C:: @ 80DFE9C + .string "This #CGWonder Mail#R has already been\n" + .string "received." + .byte 0 + .align 2, 0 + +gUnknown_80DFED0:: @ 80DFED0 + .string "This #CGWonder Mail#R has already been\n" + .string "received.\n" + .string "You may not receive the same one again." + .byte 0 + .align 2, 0 + +gUnknown_80DFF2C:: @ 80DFF2C + .string "Only #CGone piece#R of #CGWonder Mail#R can be held.\n" + .string "Please receive it after completing any\n" + .string "rescue mission in progress." + .byte 0 + .align 2, 0 + +gUnknown_80DFFA4:: @ 80DFFA4 + .string "The rescue team has quicksaved in\n" + .string "a dungeon with a mission in progress.\n" + .string "Please complete the mission first." + .byte 0 + .align 2, 0 + +gUnknown_80E0010:: @ 80E0010 + .string "The rescue team has quicksaved in\n" + .string "a dungeon with a mission in progress.\n" + .string "Mail cannot be deleted now." + .byte 0 +gUnknown_80E0074:: @ 80E0074 + .string "Received the #CGWonder Mail#R!" + .byte 0 + .align 2, 0 + +gUnknown_80E0094:: @ 80E0094 + .string "Only #CGone piece#R of #CGWonder Mail#R can be held.\n" + .string "Is it OK to replace the old #CGWonder Mail#R\n" + .string "with the new one?" + .byte 0 + .align 2, 0 + +gUnknown_80E0108:: @ 80E0108 + .string "Your #CGJob List#R is full.\n" + .string "Please select and delete unwanted mail." + .byte 0 + .align 2, 0 + +gUnknown_80E014C:: @ 80E014C + .string "New Mail" + .byte 0 + .align 2, 0 + +gUnknown_80E0158:: @ 80E0158 + .string "Old Mail" + .byte 0 + .align 2, 0 + + .string "pksdir0" + .byte 0 diff --git a/data/text/wonder_mail_4.inc b/data/text/wonder_mail_4.inc new file mode 100644 index 0000000..7f5b843 --- /dev/null +++ b/data/text/wonder_mail_4.inc @@ -0,0 +1,195 @@ +gUnknown_80E0C4C:: @ 80E0C4C + .string " So~2c what~27d you want to\n" + .string "know?" + .byte 0 + .align 2, 0 + +gUnknown_80E0C70:: @ 80E0C70 + .string " If you need to call for\n" + .string "help~2c first send your friend\n" + .string "an #CGSOS Mail#R.#P Once you send that mail~2c\n" + .string "wait until your friend sends you back\n" + .string "an #CGA-OK Mail#R.#P When you get that\n" + .string "#CGA-OK Mail#R back~2c your team\n" + .string "can continue from where it went down.#P Make sure you send your\n" + .string "friend a #CGThank-You Mail#R.\n" + .string "That~27s if you get revived~2c of course." + .byte 0 + .align 2, 0 + +gUnknown_80E0DD0:: @ 80E0DD0 + .string " If your team gets defeated\n" + .string "in a dungeon~2c you can send an #CGSOS Mail#R\n" + .string "to a friend willing to help.#P But I have to warn you.\n" + .string "You can~27t get anyone to rescue you\n" + .string "in certain places.#P If you need to send\n" + .string "an #CGSOS Mail#R~2c you send it from the\n" + .string "#CGmain menu#R." + .byte 0 + .align 2, 0 + +gUnknown_80E0ED8:: @ 80E0ED8 + .string " If your friend manages to\n" + .string "rescue your team~2c you need to receive\n" + .string "an #CGA-OK Mail#R from your friend.#P See~2c once you get that\n" + .string "#CGA-OK Mail#R~2c your team can continue from\n" + .string "where it went down in the dungeon.#P And~2c if you use\n" + .string "a #CGGame Link cable#R~2c your friend can\n" + .string "even send you a #CGhelper Pokémon#R.#P There~27s just one thing.\n" + .string "A #CGhelper Pokémon#R can~27t bring\n" + .string "any item it happens to be holding.#P You can receive that\n" + .string "team-saving #CGA-OK Mail#R on the #CGmain menu#R~2c\n" + .string "all right?" + .byte 0 + .align 2, 0 + +gUnknown_80E10C8:: @ 80E10C8 + .string " If your team gets rescued~2c\n" + .string "be sure to send your friend\n" + .string "a #CGThank-You Mail#R.#P You do that by going to\n" + .string "the #CGright counter#R~2c or\n" + .string "by selecting it from the #CGmain menu#R.#P You can attach an ite" + .string "m in\n" + .string "storage to your #CGThank-You Mail#R\n" + .string "as a #CGreward item#R.#P You don~27t want to ever\n" + .string "forget to express your thanks." + .byte 0 + .align 2, 0 + +gUnknown_80E120C:: @ 80E120C + .string " If you want to go and\n" + .string "rescue your friend~27s KO~27d team~2c\n" + .string "you need to receive an #CGSOS Mail#R.#P When you get that mail~2" + .string "c\n" + .string "you can rescue your friend at\n" + .string "the #CGleft counter#R over there.#P If you do manage to rescue\n" + .string "the team~2c you send your friend\n" + .string "an #CGA-OK Mail#R.#P After you do that~2c your\n" + .string "friend can send back to you\n" + .string "a #CGThank-You Mail#R." + .byte 0 + .align 2, 0 + +gUnknown_80E136C:: @ 80E136C + .string " To go off on a rescue~2c\n" + .string "you first need to receive your friend~27s\n" + .string "#CGSOS Mail#R.#P You do that at\n" + .string "the #CGleft counter#R over there~2c\n" + .string "or by selecting it from the #CGmain menu#R." + .byte 0 + .align 2, 0 + +gUnknown_80E1420:: @ 80E1420 + .string " If you succeed in rescuing\n" + .string "that team~2c you send your friend an\n" + .string "#CGA-OK Mail#R.#P You do that by going to\n" + .string "the #CGleft counter#R~2c\n" + .string "or from the #CGmain menu#R.#P You can send your friend\n" + .string "a Pokémon as a helper from your Friend\n" + .string "Areas using a #CGGame Link cable#R.#P This Pokémon won~27t\n" + .string "disappear from its Friend Area~2c so\n" + .string "don~27t you worry any." + .byte 0 + .align 2, 0 + +gUnknown_80E157C:: @ 80E157C + .string " If you get an #CGSOS Mail#R~2c\n" + .string "you head off on the rescue from\n" + .string "the #CGleft counter#R.#P But~2c I have to warn you.\n" + .string "You can~27t go off to rescue in a dungeon\n" + .string "if you can~27t get into it.#P You~27ll be able to get\n" + .string "there when you go farther in your\n" + .string "adventure~2c so it won~27t do to fret." + .byte 0 + .align 2, 0 + +gUnknown_80E169C:: @ 80E169C + .string " If you send your friend\n" + .string "an #CGA-OK Mail#R~2c you can look forward\n" + .string "to getting a #CGThank-You Mail#R back.#P You can receive it at\n" + .string "the #CGright counter#R\n" + .string "or on the #CGmain menu#R.#P But you need to #C2be careful#R.\n" + .string "You #C2must not delete the A-OK Mail#R\n" + .string "before you get the #CGThank-You Mail#R back." + .byte 0 + .align 2, 0 + +gUnknown_80E17C8:: @ 80E17C8 + .string " I~27m your guide to what you\n" + .string "can expect at the Pelipper Post Office.\n" + .string "If you have any questions~2c just ask away!" + .byte 0 + .align 2, 0 + +gUnknown_80E183C:: @ 80E183C + .string " Did you want to ask about\n" + .string "anything else?" + .byte 0 + .align 2, 0 + +gUnknown_80E1868:: @ 80E1868 + .string " #CGThe Pelipper Post Office#R\n" + .string "keeps track of information from\n" + .string "around the world.#P We inform folks\n" + .string "about everything from gossip to calls\n" + .string "for help from fellow Pokémon.#P For the latest news~2c check\n" + .string "#CGyour Mailbox#R or the #CGBulletin Board#R\n" + .string "outside~2c all right?#P Oh~2c that~27s not all.\n" + .string "You can arrange for #CGFriend Rescue#R\n" + .string "missions at that counter there.#P The #CGleft counter#R is\n" + .string "for rescues~2c and the #CGright counter#R\n" + .string "is for Thank-You Mail." + .byte 0 + .align 2, 0 + +gUnknown_80E1A30:: @ 80E1A30 + .string " The #CGBulletin Board#R outside\n" + .string "here lists rescue requests.#P Take on rescue jobs from\n" + .string "the Bulletin Board. Be a hero and handle\n" + .string "the jobs for fellow Pokémon in need!" + .byte 0 + .align 2, 0 + +gUnknown_80E1AD8:: @ 80E1AD8 + .string " If your rescue team\n" + .string "becomes famous for doing lots of rescues~2c\n" + .string "expect to get rescue requests directly.#P Our delivery " + .byte 0x24 + .string "m0\n" + .string "will take those jobs straight to your\n" + .string "#CGMailbox#R." + .byte 0 + .align 2, 0 + +gUnknown_80E1B88:: @ 80E1B88 + .string " Friend Rescue is what we\n" + .string "call rescue missions between friends using\n" + .string "a #CGGame Link cable#R~2c #CGpasswords#R~2c etc.#P For instance~" + .string "2c you can send\n" + .string "out for help saying your team wiped out\n" + .string "in a dungeon at such and such a place.#P Your friend could play\n" + .string "the hero and come to your team~27s rescue.\n" + .string "Or it can be the other way around~2c too.#P If you use #CGpasswo" + .string "rds#R~2c\n" + .string "you can do rescues with friends in\n" + .string "far-away places.#P You can apply for Friend\n" + .string "Rescue jobs at the #CGleft counter#R of\n" + .string "that counter there." + .byte 0 + .align 2, 0 + +gUnknown_80E1D84:: @ 80E1D84 + .string " Deleting mail just means\n" + .string "getting rid of old mail that you don~27t\n" + .string "need anymore.#P If you do lots of Friend\n" + .string "Rescues~2c you~27ll find #CGSOS Mail#R and\n" + .string "#CGA-OK Mail#R piling up.#P Once you get #CG30 pieces#R~2c\n" + .string "you won~27t be able to receive more mail.\n" + .string "That~27s why you~27ll need to delete old mail.#P You can look th" + .string "rough old\n" + .string "mail at the #CGleft counter#R over there." + .byte 0 + .align 2, 0 + + .string "pksdir0" + .byte 0 diff --git a/data/text/wonder_mail_complete.inc b/data/text/wonder_mail_complete.inc new file mode 100644 index 0000000..7b6fad1 --- /dev/null +++ b/data/text/wonder_mail_complete.inc @@ -0,0 +1,40 @@ +gUnknown_80E0184:: @ 80E0184 + .string " Thank you for rescuing me!" + .byte 0 + .align 2, 0 + +gUnknown_80E01A0:: @ 80E01A0 + .string " Thank you for rescuing\n" + .string "#C5" + .byte 0x24 + .string "m1#R!" + .byte 0 + .align 2, 0 + +gUnknown_80E01C4:: @ 80E01C4 + .string " Thank you for escorting me\n" + .string "to #C5" + .byte 0x24 + .string "m1#R! " + .byte 0 + .align 2, 0 + +gUnknown_80E01F0:: @ 80E01F0 + .string " Thank you for delivering\n" + .string "the #C4" + .byte 0x24 + .string "i0#R!" + .byte 0 + .align 2, 0 + +gUnknown_80E0218:: @ 80E0218 + .string " Thank you for getting me\n" + .string "the #C4" + .byte 0x24 + .string "i0#R!" + .byte 0 + .align 2, 0 + + .string "pksdir0" + .byte 0 + .align 2, 0 diff --git a/sound/music_player_table.inc b/sound/music_player_table.inc index f21c434..86c4795 100644 --- a/sound/music_player_table.inc +++ b/sound/music_player_table.inc @@ -1,6 +1,5 @@ .align 2 - .global gMPlayTable -gMPlayTable: @ 9E8665C +gMPlayTable:: @ 9E8665C music_player 0x20008F0, 0x2000000, 12, 0 music_player 0x2000970, 0x20003C0, 6, 0 music_player 0x20009B0, 0x20005A0, 1, 0 diff --git a/sound/song_table.inc b/sound/song_table.inc index 86488a3..df66710 100644 --- a/sound/song_table.inc +++ b/sound/song_table.inc @@ -1,6 +1,5 @@ .align 2 - .global gSongTable -gSongTable: @ 9E866BC +gSongTable:: @ 9E866BC song 0x9F5185C, 0, 0 song 0x9F5218C, 0, 0 song 0x9F52D24, 0, 0 -- cgit v1.2.3 From 0a3b060d298bfb89e83d21d9b7b9f96a07994f41 Mon Sep 17 00:00:00 2001 From: nullableVoidPtr <30564701+nullableVoidPtr@users.noreply.github.com> Date: Sun, 4 Aug 2019 09:47:55 +0000 Subject: Fix perms and linebreaks --- data/text/luminous_cave.inc | 18 ++++++------------ data/text/save.inc | 3 +-- data/text/wonder_mail_1.inc | 9 +++------ data/text/wonder_mail_4.inc | 15 +++++---------- 4 files changed, 15 insertions(+), 30 deletions(-) diff --git a/data/text/luminous_cave.inc b/data/text/luminous_cave.inc index 6956c7f..92b9c2d 100644 --- a/data/text/luminous_cave.inc +++ b/data/text/luminous_cave.inc @@ -13,17 +13,13 @@ gUnknown_80DCAB8:: @ 80DCAB8 gUnknown_80DCAD0:: @ 80DCAD0 .string "#+There are those among Pokémon\n" .string "#+that can evolve.#P#+Such Pokémon can evolve at this very\n" - .string "#+spot if they satisfy certain conditions.#P#+Evolution brings a" - .string "bout changes\n" + .string "#+spot if they satisfy certain conditions.#P#+Evolution brings about changes\n" .string "#+in appearance and abilities.#P#+Not only that~2c some Pokémon even change\n" - .string "#+type and learn different moves.#P#+However...#W The requiremen" - .string "ts for\n" + .string "#+type and learn different moves.#P#+However...#W The requirements for\n" .string "#+evolution differ among Pokémon.#P#+Some become ready for evolution\n" .string "#+merely by leveling up.#P#+Still others may need special items\n" - .string "#+to attain evolution.#P#+Ye must also be aware of this:#P#+Once" - .string " it has evolved~2c a Pokémon\n" - .string "#+can never regain its previous form.#P#+That is why ye must thi" - .string "nk carefully\n" + .string "#+to attain evolution.#P#+Ye must also be aware of this:#P#+Once it has evolved~2c a Pokémon\n" + .string "#+can never regain its previous form.#P#+That is why ye must think carefully\n" .string "#+before committing to evolution." .byte 0 .align 2, 0 @@ -128,10 +124,8 @@ gUnknown_80DD104:: @ 80DD104 .byte 0 .align 2, 0 - .string "pksdir0" - .byte 0 + .asciz "pksdir0" .align 2, 0 - .string "pksdir0" - .byte 0 + .asciz "pksdir0" .align 2, 0 diff --git a/data/text/save.inc b/data/text/save.inc index a944a8d..4843851 100644 --- a/data/text/save.inc +++ b/data/text/save.inc @@ -51,8 +51,7 @@ gUnknown_80B6CB8:: @ 80B6CB8 .byte 0 .align 2, 0 - .string "pksdir0" - .byte 0 + .asciz "pksdir0" .align 2, 0 .incbin "baserom.gba", 0xB6D30, 0x60 diff --git a/data/text/wonder_mail_1.inc b/data/text/wonder_mail_1.inc index 0c6915e..3fc142f 100644 --- a/data/text/wonder_mail_1.inc +++ b/data/text/wonder_mail_1.inc @@ -184,8 +184,7 @@ gUnknown_80DE4F0:: @ 80DE4F0 gUnknown_80DE524:: @ 80DE524 .string " If you want a reward~2c #C2don~27t\n" .string "delete an A-OK Mail#R before getting a\n" - .string "#CGThank-You Mail#R back for it.#P #C2Be careful#R if you~27re g" - .string "oing\n" + .string "#CGThank-You Mail#R back for it.#P #C2Be careful#R if you~27re going\n" .string "to delete any #CGA-OK Mail#R.#P Okeydoke.\n" .string "Choose an #CGA-OK Mail#R\n" .string "you don~27t need anymore." @@ -249,8 +248,7 @@ gUnknown_80DE830:: @ 80DE830 gUnknown_80DE864:: @ 80DE864 .string " Okeydoke.\n" - .string "Every bit of mail has been deleted.#P Let me save your adventure" - .string "." + .string "Every bit of mail has been deleted.#P Let me save your adventure." .byte 0 .align 2, 0 @@ -345,6 +343,5 @@ gUnknown_80DECFC:: @ 80DECFC .byte 0 .align 2, 0 - .string "pksdir0" - .byte 0 + .asciz "pksdir0" .align 2, 0 diff --git a/data/text/wonder_mail_4.inc b/data/text/wonder_mail_4.inc index 7f5b843..a8b30f9 100644 --- a/data/text/wonder_mail_4.inc +++ b/data/text/wonder_mail_4.inc @@ -48,8 +48,7 @@ gUnknown_80E10C8:: @ 80E10C8 .string "be sure to send your friend\n" .string "a #CGThank-You Mail#R.#P You do that by going to\n" .string "the #CGright counter#R~2c or\n" - .string "by selecting it from the #CGmain menu#R.#P You can attach an ite" - .string "m in\n" + .string "by selecting it from the #CGmain menu#R.#P You can attach an item in\n" .string "storage to your #CGThank-You Mail#R\n" .string "as a #CGreward item#R.#P You don~27t want to ever\n" .string "forget to express your thanks." @@ -59,8 +58,7 @@ gUnknown_80E10C8:: @ 80E10C8 gUnknown_80E120C:: @ 80E120C .string " If you want to go and\n" .string "rescue your friend~27s KO~27d team~2c\n" - .string "you need to receive an #CGSOS Mail#R.#P When you get that mail~2" - .string "c\n" + .string "you need to receive an #CGSOS Mail#R.#P When you get that mail~2c\n" .string "you can rescue your friend at\n" .string "the #CGleft counter#R over there.#P If you do manage to rescue\n" .string "the team~2c you send your friend\n" @@ -164,13 +162,11 @@ gUnknown_80E1AD8:: @ 80E1AD8 gUnknown_80E1B88:: @ 80E1B88 .string " Friend Rescue is what we\n" .string "call rescue missions between friends using\n" - .string "a #CGGame Link cable#R~2c #CGpasswords#R~2c etc.#P For instance~" - .string "2c you can send\n" + .string "a #CGGame Link cable#R~2c #CGpasswords#R~2c etc.#P For instance~2c you can send\n" .string "out for help saying your team wiped out\n" .string "in a dungeon at such and such a place.#P Your friend could play\n" .string "the hero and come to your team~27s rescue.\n" - .string "Or it can be the other way around~2c too.#P If you use #CGpasswo" - .string "rds#R~2c\n" + .string "Or it can be the other way around~2c too.#P If you use #CGpasswords#R~2c\n" .string "you can do rescues with friends in\n" .string "far-away places.#P You can apply for Friend\n" .string "Rescue jobs at the #CGleft counter#R of\n" @@ -185,8 +181,7 @@ gUnknown_80E1D84:: @ 80E1D84 .string "Rescues~2c you~27ll find #CGSOS Mail#R and\n" .string "#CGA-OK Mail#R piling up.#P Once you get #CG30 pieces#R~2c\n" .string "you won~27t be able to receive more mail.\n" - .string "That~27s why you~27ll need to delete old mail.#P You can look th" - .string "rough old\n" + .string "That~27s why you~27ll need to delete old mail.#P You can look through old\n" .string "mail at the #CGleft counter#R over there." .byte 0 .align 2, 0 -- cgit v1.2.3 From 5c4f2bd4d38b4865ff79287b62c31cac5b655301 Mon Sep 17 00:00:00 2001 From: nullableVoidPtr <30564701+nullableVoidPtr@users.noreply.github.com> Date: Sun, 4 Aug 2019 09:53:50 +0000 Subject: Add tools --- tools/aif2pcm/.gitignore | 2 + tools/aif2pcm/LICENSE | 20 + tools/aif2pcm/Makefile | 18 + tools/aif2pcm/extended.c | 172 ++++++++ tools/aif2pcm/main.c | 830 ++++++++++++++++++++++++++++++++++ tools/bin2c/.gitignore | 1 + tools/bin2c/LICENSE | 19 + tools/bin2c/Makefile | 16 + tools/bin2c/bin2c.c | 201 +++++++++ tools/gbafix/.gitignore | 2 + tools/gbafix/COPYING | 674 ++++++++++++++++++++++++++++ tools/gbafix/Makefile | 14 + tools/gbafix/gbafix.c | 289 ++++++++++++ tools/gbagfx/.gitignore | 1 + tools/gbagfx/LICENSE | 19 + tools/gbagfx/Makefile | 18 + tools/gbagfx/convert_png.c | 254 +++++++++++ tools/gbagfx/convert_png.h | 12 + tools/gbagfx/font.c | 326 ++++++++++++++ tools/gbagfx/font.h | 16 + tools/gbagfx/gfx.c | 344 +++++++++++++++ tools/gbagfx/gfx.h | 36 ++ tools/gbagfx/global.h | 31 ++ tools/gbagfx/jasc_pal.c | 172 ++++++++ tools/gbagfx/jasc_pal.h | 9 + tools/gbagfx/lz.c | 155 +++++++ tools/gbagfx/lz.h | 9 + tools/gbagfx/main.c | 465 +++++++++++++++++++ tools/gbagfx/options.h | 24 + tools/gbagfx/rl.c | 149 +++++++ tools/gbagfx/rl.h | 9 + tools/gbagfx/util.c | 124 ++++++ tools/gbagfx/util.h | 14 + tools/mapjson/.gitignore | 1 + tools/mapjson/Makefile | 18 + tools/mapjson/json11.cpp | 786 ++++++++++++++++++++++++++++++++ tools/mapjson/json11.h | 230 ++++++++++ tools/mapjson/mapjson.cpp | 538 ++++++++++++++++++++++ tools/mapjson/mapjson.h | 31 ++ tools/mid2agb/.gitignore | 1 + tools/mid2agb/LICENSE | 19 + tools/mid2agb/Makefile | 18 + tools/mid2agb/agb.cpp | 462 +++++++++++++++++++ tools/mid2agb/agb.h | 33 ++ tools/mid2agb/error.cpp | 36 ++ tools/mid2agb/error.h | 26 ++ tools/mid2agb/main.cpp | 228 ++++++++++ tools/mid2agb/main.h | 39 ++ tools/mid2agb/midi.cpp | 958 ++++++++++++++++++++++++++++++++++++++++ tools/mid2agb/midi.h | 87 ++++ tools/mid2agb/tables.cpp | 286 ++++++++++++ tools/mid2agb/tables.h | 29 ++ tools/preproc/.gitignore | 1 + tools/preproc/LICENSE | 19 + tools/preproc/Makefile | 20 + tools/preproc/asm_file.cpp | 529 ++++++++++++++++++++++ tools/preproc/asm_file.h | 72 +++ tools/preproc/c_file.cpp | 445 +++++++++++++++++++ tools/preproc/c_file.h | 58 +++ tools/preproc/char_util.h | 71 +++ tools/preproc/charmap.cpp | 408 +++++++++++++++++ tools/preproc/charmap.h | 64 +++ tools/preproc/preproc.cpp | 161 +++++++ tools/preproc/preproc.h | 54 +++ tools/preproc/string_parser.cpp | 355 +++++++++++++++ tools/preproc/string_parser.h | 55 +++ tools/preproc/utf8.cpp | 92 ++++ tools/preproc/utf8.h | 34 ++ tools/ramscrgen/.gitignore | 1 + tools/ramscrgen/LICENSE | 19 + tools/ramscrgen/Makefile | 18 + tools/ramscrgen/char_util.h | 71 +++ tools/ramscrgen/elf.cpp | 195 ++++++++ tools/ramscrgen/elf.h | 30 ++ tools/ramscrgen/main.cpp | 173 ++++++++ tools/ramscrgen/ramscrgen.h | 49 ++ tools/ramscrgen/sym_file.cpp | 492 +++++++++++++++++++++ tools/ramscrgen/sym_file.h | 71 +++ tools/rsfont/.gitignore | 1 + tools/rsfont/LICENSE | 19 + tools/rsfont/Makefile | 18 + tools/rsfont/convert_png.c | 169 +++++++ tools/rsfont/convert_png.h | 11 + tools/rsfont/font.c | 455 +++++++++++++++++++ tools/rsfont/font.h | 30 ++ tools/rsfont/gfx.h | 50 +++ tools/rsfont/global.h | 31 ++ tools/rsfont/main.c | 93 ++++ tools/rsfont/util.c | 124 ++++++ tools/rsfont/util.h | 14 + tools/scaninc/.gitignore | 1 + tools/scaninc/LICENSE | 19 + tools/scaninc/Makefile | 18 + tools/scaninc/asm_file.cpp | 191 ++++++++ tools/scaninc/asm_file.h | 119 +++++ tools/scaninc/c_file.cpp | 307 +++++++++++++ tools/scaninc/c_file.h | 57 +++ tools/scaninc/scaninc.cpp | 165 +++++++ tools/scaninc/scaninc.h | 59 +++ 99 files changed, 13779 insertions(+) create mode 100644 tools/aif2pcm/.gitignore create mode 100644 tools/aif2pcm/LICENSE create mode 100644 tools/aif2pcm/Makefile create mode 100644 tools/aif2pcm/extended.c create mode 100644 tools/aif2pcm/main.c create mode 100644 tools/bin2c/.gitignore create mode 100644 tools/bin2c/LICENSE create mode 100644 tools/bin2c/Makefile create mode 100644 tools/bin2c/bin2c.c create mode 100644 tools/gbafix/.gitignore create mode 100644 tools/gbafix/COPYING create mode 100644 tools/gbafix/Makefile create mode 100644 tools/gbafix/gbafix.c create mode 100644 tools/gbagfx/.gitignore create mode 100644 tools/gbagfx/LICENSE create mode 100644 tools/gbagfx/Makefile create mode 100644 tools/gbagfx/convert_png.c create mode 100644 tools/gbagfx/convert_png.h create mode 100644 tools/gbagfx/font.c create mode 100644 tools/gbagfx/font.h create mode 100644 tools/gbagfx/gfx.c create mode 100644 tools/gbagfx/gfx.h create mode 100644 tools/gbagfx/global.h create mode 100644 tools/gbagfx/jasc_pal.c create mode 100644 tools/gbagfx/jasc_pal.h create mode 100644 tools/gbagfx/lz.c create mode 100644 tools/gbagfx/lz.h create mode 100644 tools/gbagfx/main.c create mode 100755 tools/gbagfx/options.h create mode 100644 tools/gbagfx/rl.c create mode 100644 tools/gbagfx/rl.h create mode 100644 tools/gbagfx/util.c create mode 100644 tools/gbagfx/util.h create mode 100755 tools/mapjson/.gitignore create mode 100755 tools/mapjson/Makefile create mode 100755 tools/mapjson/json11.cpp create mode 100755 tools/mapjson/json11.h create mode 100755 tools/mapjson/mapjson.cpp create mode 100755 tools/mapjson/mapjson.h create mode 100644 tools/mid2agb/.gitignore create mode 100644 tools/mid2agb/LICENSE create mode 100644 tools/mid2agb/Makefile create mode 100644 tools/mid2agb/agb.cpp create mode 100644 tools/mid2agb/agb.h create mode 100644 tools/mid2agb/error.cpp create mode 100644 tools/mid2agb/error.h create mode 100644 tools/mid2agb/main.cpp create mode 100644 tools/mid2agb/main.h create mode 100644 tools/mid2agb/midi.cpp create mode 100644 tools/mid2agb/midi.h create mode 100644 tools/mid2agb/tables.cpp create mode 100644 tools/mid2agb/tables.h create mode 100644 tools/preproc/.gitignore create mode 100644 tools/preproc/LICENSE create mode 100644 tools/preproc/Makefile create mode 100644 tools/preproc/asm_file.cpp create mode 100644 tools/preproc/asm_file.h create mode 100644 tools/preproc/c_file.cpp create mode 100644 tools/preproc/c_file.h create mode 100644 tools/preproc/char_util.h create mode 100644 tools/preproc/charmap.cpp create mode 100644 tools/preproc/charmap.h create mode 100644 tools/preproc/preproc.cpp create mode 100644 tools/preproc/preproc.h create mode 100644 tools/preproc/string_parser.cpp create mode 100644 tools/preproc/string_parser.h create mode 100644 tools/preproc/utf8.cpp create mode 100644 tools/preproc/utf8.h create mode 100644 tools/ramscrgen/.gitignore create mode 100644 tools/ramscrgen/LICENSE create mode 100644 tools/ramscrgen/Makefile create mode 100644 tools/ramscrgen/char_util.h create mode 100644 tools/ramscrgen/elf.cpp create mode 100644 tools/ramscrgen/elf.h create mode 100644 tools/ramscrgen/main.cpp create mode 100644 tools/ramscrgen/ramscrgen.h create mode 100644 tools/ramscrgen/sym_file.cpp create mode 100644 tools/ramscrgen/sym_file.h create mode 100644 tools/rsfont/.gitignore create mode 100644 tools/rsfont/LICENSE create mode 100644 tools/rsfont/Makefile create mode 100644 tools/rsfont/convert_png.c create mode 100644 tools/rsfont/convert_png.h create mode 100644 tools/rsfont/font.c create mode 100644 tools/rsfont/font.h create mode 100644 tools/rsfont/gfx.h create mode 100644 tools/rsfont/global.h create mode 100644 tools/rsfont/main.c create mode 100644 tools/rsfont/util.c create mode 100644 tools/rsfont/util.h create mode 100644 tools/scaninc/.gitignore create mode 100644 tools/scaninc/LICENSE create mode 100644 tools/scaninc/Makefile create mode 100644 tools/scaninc/asm_file.cpp create mode 100644 tools/scaninc/asm_file.h create mode 100644 tools/scaninc/c_file.cpp create mode 100644 tools/scaninc/c_file.h create mode 100644 tools/scaninc/scaninc.cpp create mode 100644 tools/scaninc/scaninc.h diff --git a/tools/aif2pcm/.gitignore b/tools/aif2pcm/.gitignore new file mode 100644 index 0000000..3153179 --- /dev/null +++ b/tools/aif2pcm/.gitignore @@ -0,0 +1,2 @@ +aif2pcm + diff --git a/tools/aif2pcm/LICENSE b/tools/aif2pcm/LICENSE new file mode 100644 index 0000000..966b92b --- /dev/null +++ b/tools/aif2pcm/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2016 huderlem +Copyright (c) 2005, 2006 by Marco Trillo + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/tools/aif2pcm/Makefile b/tools/aif2pcm/Makefile new file mode 100644 index 0000000..790ed71 --- /dev/null +++ b/tools/aif2pcm/Makefile @@ -0,0 +1,18 @@ +CC = gcc + +CFLAGS = -Wall -Wextra -Wno-switch -Werror -std=c11 -O2 -s + +LIBS = -lm + +SRCS = main.c extended.c + +.PHONY: all clean + +all: aif2pcm + @: + +aif2pcm: $(SRCS) + $(CC) $(CFLAGS) $(SRCS) -o $@ $(LDFLAGS) $(LIBS) + +clean: + $(RM) aif2pcm aif2pcm.exe diff --git a/tools/aif2pcm/extended.c b/tools/aif2pcm/extended.c new file mode 100644 index 0000000..9444916 --- /dev/null +++ b/tools/aif2pcm/extended.c @@ -0,0 +1,172 @@ +/* $Id: extended.c,v 1.8 2006/12/23 11:17:49 toad32767 Exp $ */ +/*- + * Copyright (c) 2005, 2006 by Marco Trillo + * + * Permission is hereby granted, free of charge, to any + * person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the + * Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice + * shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS + * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include + +/* + * Infinite & NAN values + * for non-IEEE systems + */ +#ifndef HUGE_VAL +#ifdef HUGE +#define INFINITE_VALUE HUGE +#define NAN_VALUE HUGE +#endif +#else +#define INFINITE_VALUE HUGE_VAL +#define NAN_VALUE HUGE_VAL +#endif + +/* + * IEEE 754 Extended Precision + * + * Implementation here is the 80-bit extended precision + * format of Motorola 68881, Motorola 68882 and Motorola + * 68040 FPUs, as well as Intel 80x87 FPUs. + * + * See: + * http://www.freescale.com/files/32bit/doc/fact_sheet/BR509.pdf + */ +/* + * Exponent range: [-16383,16383] + * Precision for mantissa: 64 bits with no hidden bit + * Bias: 16383 + */ + +/* + * Write IEEE Extended Precision Numbers + */ +void +ieee754_write_extended(double in, uint8_t* out) +{ + int sgn, exp, shift; + double fraction, t; + unsigned int lexp, hexp; + unsigned long low, high; + + if (in == 0.0) { + memset(out, 0, 10); + return; + } + if (in < 0.0) { + in = fabs(in); + sgn = 1; + } else + sgn = 0; + + fraction = frexp(in, &exp); + + if (exp == 0 || exp > 16384) { + if (exp > 16384) /* infinite value */ + low = high = 0; + else { + low = 0x80000000; + high = 0; + } + exp = 32767; + goto done; + } + fraction = ldexp(fraction, 32); + t = floor(fraction); + low = (unsigned long) t; + fraction -= t; + t = floor(ldexp(fraction, 32)); + high = (unsigned long) t; + + /* Convert exponents < -16382 to -16382 (then they will be + * stored as -16383) */ + if (exp < -16382) { + shift = 0 - exp - 16382; + high >>= shift; + high |= (low << (32 - shift)); + low >>= shift; + exp = -16382; + } + exp += 16383 - 1; /* bias */ + +done: + lexp = ((unsigned int) exp) >> 8; + hexp = ((unsigned int) exp) & 0xFF; + + /* big endian */ + out[0] = ((uint8_t) sgn) << 7; + out[0] |= (uint8_t) lexp; + out[1] = (uint8_t) hexp; + out[2] = (uint8_t) (low >> 24); + out[3] = (uint8_t) ((low >> 16) & 0xFF); + out[4] = (uint8_t) ((low >> 8) & 0xFF); + out[5] = (uint8_t) (low & 0xFF); + out[6] = (uint8_t) (high >> 24); + out[7] = (uint8_t) ((high >> 16) & 0xFF); + out[8] = (uint8_t) ((high >> 8) & 0xFF); + out[9] = (uint8_t) (high & 0xFF); + + return; +} + + +/* + * Read IEEE Extended Precision Numbers + */ +double +ieee754_read_extended(uint8_t* in) +{ + int sgn, exp; + unsigned long low, high; + double out; + + /* Extract the components from the big endian buffer */ + sgn = (int) (in[0] >> 7); + exp = ((int) (in[0] & 0x7F) << 8) | ((int) in[1]); + low = (((unsigned long) in[2]) << 24) + | (((unsigned long) in[3]) << 16) + | (((unsigned long) in[4]) << 8) | (unsigned long) in[5]; + high = (((unsigned long) in[6]) << 24) + | (((unsigned long) in[7]) << 16) + | (((unsigned long) in[8]) << 8) | (unsigned long) in[9]; + + if (exp == 0 && low == 0 && high == 0) + return (sgn ? -0.0 : 0.0); + + switch (exp) { + case 32767: + if (low == 0 && high == 0) + return (sgn ? -INFINITE_VALUE : INFINITE_VALUE); + else + return (sgn ? -NAN_VALUE : NAN_VALUE); + default: + exp -= 16383; /* unbias exponent */ + + } + + out = ldexp((double) low, -31 + exp); + out += ldexp((double) high, -63 + exp); + + return (sgn ? -out : out); +} diff --git a/tools/aif2pcm/main.c b/tools/aif2pcm/main.c new file mode 100644 index 0000000..fbb024a --- /dev/null +++ b/tools/aif2pcm/main.c @@ -0,0 +1,830 @@ +// Copyright(c) 2016 huderlem +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include +#include +#include +#include +#include +#include + +/* extended.c */ +void ieee754_write_extended (double, uint8_t*); +double ieee754_read_extended (uint8_t*); + +#ifdef _MSC_VER + +#define FATAL_ERROR(format, ...) \ +do \ +{ \ + fprintf(stderr, format, __VA_ARGS__); \ + exit(1); \ +} while (0) + +#else + +#define FATAL_ERROR(format, ...) \ +do \ +{ \ + fprintf(stderr, format, ##__VA_ARGS__); \ + exit(1); \ +} while (0) + +#endif // _MSC_VER + +typedef struct { + unsigned long num_samples; + uint8_t *samples; + uint8_t midi_note; + bool has_loop; + unsigned long loop_offset; + double sample_rate; + unsigned long real_num_samples; +} AifData; + +struct Bytes { + unsigned long length; + uint8_t *data; +}; + +struct Bytes *read_bytearray(const char *filename) +{ + struct Bytes *bytes = malloc(sizeof(struct Bytes)); + FILE *f = fopen(filename, "rb"); + if (!f) + { + FATAL_ERROR("Failed to open '%s' for reading!\n", filename); + } + fseek(f, 0, SEEK_END); + bytes->length = ftell(f); + fseek(f, 0, SEEK_SET); + bytes->data = malloc(bytes->length); + unsigned long read = fread(bytes->data, bytes->length, 1, f); + fclose(f); + if (read <= 0) + { + FATAL_ERROR("Failed to read data from '%s'!\n", filename); + } + return bytes; +} + +void write_bytearray(const char *filename, struct Bytes *bytes) +{ + FILE *f = fopen(filename, "wb"); + if (!f) + { + FATAL_ERROR("Failed to open '%s' for writing!\n", filename); + } + fwrite(bytes->data, bytes->length, 1, f); + fclose(f); +} + +void free_bytearray(struct Bytes *bytes) +{ + free(bytes->data); + free(bytes); +} + +char *get_file_extension(char *filename) +{ + char *index = strrchr(filename, '.'); + if (!index || index == filename) + { + return NULL; + } + return index + 1; +} + +char *new_file_extension(char *filename, char *ext) +{ + char *index = strrchr(filename, '.'); + if (!index || index == filename) + { + index = filename + strlen(filename); + } + int length = index - filename; + char *new_filename = malloc(length + 1 + strlen(ext) + 1); + if (new_filename) + { + strcpy(new_filename, filename); + new_filename[length] = '.'; + strcpy(new_filename + length + 1, ext); + } + return new_filename; +} + +void read_aif(struct Bytes *aif, AifData *aif_data) +{ + aif_data->has_loop = false; + aif_data->num_samples = 0; + + unsigned long pos = 0; + char chunk_name[5]; chunk_name[4] = '\0'; + char chunk_type[5]; chunk_type[4] = '\0'; + + // Check for FORM Chunk + memcpy(chunk_name, &aif->data[pos], 4); + pos += 4; + if (strcmp(chunk_name, "FORM") != 0) + { + FATAL_ERROR("Input .aif file has invalid header Chunk '%s'!\n", chunk_name); + } + + // Read size of whole file. + unsigned long whole_chunk_size = aif->data[pos++] << 24; + whole_chunk_size |= (aif->data[pos++] << 16); + whole_chunk_size |= (aif->data[pos++] << 8); + whole_chunk_size |= (uint8_t)aif->data[pos++]; + + unsigned long expected_whole_chunk_size = aif->length - 8; + if (whole_chunk_size != expected_whole_chunk_size) + { + FATAL_ERROR("FORM Chunk ckSize '%lu' doesn't match actual size '%lu'!\n", whole_chunk_size, expected_whole_chunk_size); + } + + // Check for AIFF Form Type + memcpy(chunk_type, &aif->data[pos], 4); + pos += 4; + if (strcmp(chunk_type, "AIFF") != 0) + { + FATAL_ERROR("FORM Type is '%s', but it must be AIFF!", chunk_type); + } + + unsigned long num_sample_frames = 0; + + // Read all the Chunks to populate the AifData struct. + while ((pos + 8) < aif->length) + { + // Read Chunk id + memcpy(chunk_name, &aif->data[pos], 4); + pos += 4; + + unsigned long chunk_size = (aif->data[pos++] << 24); + chunk_size |= (aif->data[pos++] << 16); + chunk_size |= (aif->data[pos++] << 8); + chunk_size |= aif->data[pos++]; + + if ((pos + chunk_size) > aif->length) + { + FATAL_ERROR("%s chunk at 0x%lx reached end of file before finishing\n", chunk_name, pos); + } + + if (strcmp(chunk_name, "COMM") == 0) + { + short num_channels = (aif->data[pos++] << 8); + num_channels |= (uint8_t)aif->data[pos++]; + if (num_channels != 1) + { + FATAL_ERROR("numChannels (%d) in the COMM Chunk must be 1!\n", num_channels); + } + + num_sample_frames = (aif->data[pos++] << 24); + num_sample_frames |= (aif->data[pos++] << 16); + num_sample_frames |= (aif->data[pos++] << 8); + num_sample_frames |= (uint8_t)aif->data[pos++]; + + short sample_size = (aif->data[pos++] << 8); + sample_size |= (uint8_t)aif->data[pos++]; + if (sample_size != 8) + { + FATAL_ERROR("sampleSize (%d) in the COMM Chunk must be 8!\n", sample_size); + } + + double sample_rate = ieee754_read_extended((uint8_t*)(aif->data + pos)); + pos += 10; + + aif_data->sample_rate = sample_rate; + + if (aif_data->num_samples == 0) + { + aif_data->num_samples = num_sample_frames; + } + } + else if (strcmp(chunk_name, "MARK") == 0) + { + unsigned short num_markers = (aif->data[pos++] << 8); + num_markers |= (uint8_t)aif->data[pos++]; + + // Read each marker and look for the "START" marker. + for (int i = 0; i < num_markers; i++) + { + unsigned short marker_id = (aif->data[pos++] << 8); + marker_id |= (uint8_t)aif->data[pos++]; + + unsigned long marker_position = (aif->data[pos++] << 24); + marker_position |= (aif->data[pos++] << 16); + marker_position |= (aif->data[pos++] << 8); + marker_position |= (uint8_t)aif->data[pos++]; + + // Marker id is a pascal-style string. + uint8_t marker_name_size = aif->data[pos++]; + char *marker_name = (char *)malloc((marker_name_size + 1) * sizeof(char)); + memcpy(marker_name, &aif->data[pos], marker_name_size); + marker_name[marker_name_size] = '\0'; + pos += marker_name_size; + + if (strcmp(marker_name, "START") == 0) + { + aif_data->loop_offset = marker_position; + aif_data->has_loop = true; + } + else if (strcmp(marker_name, "END") == 0) + { + if (!aif_data->has_loop) { + aif_data->loop_offset = marker_position; + aif_data->has_loop = true; + } + aif_data->num_samples = marker_position; + } + + free(marker_name); + } + } + else if (strcmp(chunk_name, "INST") == 0) + { + uint8_t midi_note = (uint8_t)aif->data[pos++]; + + aif_data->midi_note = midi_note; + + // Skip over data we don't need. + pos += 19; + } + else if (strcmp(chunk_name, "SSND") == 0) + { + // SKip offset and blockSize + pos += 8; + + unsigned long num_samples = chunk_size - 8; + uint8_t *sample_data = (uint8_t *)malloc(num_samples * sizeof(uint8_t)); + memcpy(sample_data, &aif->data[pos], num_samples); + + aif_data->samples = sample_data; + aif_data->real_num_samples = num_samples; + pos += chunk_size - 8; + } + else + { + // Skip over unsupported chunks. + pos += chunk_size; + } + } +} + +// This is a table of deltas between sample values in compressed PCM data. +const int gDeltaEncodingTable[] = { + 0, 1, 4, 9, 16, 25, 36, 49, + -64, -49, -36, -25, -16, -9, -4, -1, +}; + +struct Bytes *delta_decompress(struct Bytes *delta, unsigned int expected_length) +{ + struct Bytes *pcm = malloc(sizeof(struct Bytes)); + pcm->length = expected_length; + pcm->data = malloc(pcm->length + 0x40); + + uint8_t hi, lo; + unsigned int i = 0; + unsigned int j = 0; + int k; + int8_t base; + while (i < delta->length) + { + base = (int8_t)delta->data[i++]; + pcm->data[j++] = (uint8_t)base; + if (i >= delta->length) + { + break; + } + if (j >= pcm->length) + { + break; + } + lo = delta->data[i] & 0xf; + base += gDeltaEncodingTable[lo]; + pcm->data[j++] = base; + i++; + if (i >= delta->length) + { + break; + } + if (j >= pcm->length) + { + break; + } + for (k = 0; k < 31; k++) + { + hi = (delta->data[i] >> 4) & 0xf; + base += gDeltaEncodingTable[hi]; + pcm->data[j++] = base; + if (j >= pcm->length) + { + break; + } + lo = delta->data[i] & 0xf; + base += gDeltaEncodingTable[lo]; + pcm->data[j++] = base; + i++; + if (i >= delta->length) + { + break; + } + if (j >= pcm->length) + { + break; + } + } + if (j >= pcm->length) + { + break; + } + } + + pcm->length = j; + return pcm; +} + +int get_delta_index(uint8_t sample, uint8_t prev_sample) +{ + int best_error = INT_MAX; + int best_index = -1; + + for (int i = 0; i < 16; i++) + { + uint8_t new_sample = prev_sample + gDeltaEncodingTable[i]; + int error = sample > new_sample ? sample - new_sample : new_sample - sample; + + if (error < best_error) + { + best_error = error; + best_index = i; + } + } + + return best_index; +} + +struct Bytes *delta_compress(struct Bytes *pcm) +{ + struct Bytes *delta = malloc(sizeof(struct Bytes)); + // estimate the length so we can malloc + int num_blocks = pcm->length / 64; + delta->length = num_blocks * 33; + + int extra = pcm->length % 64; + if (extra) + { + delta->length += 1; + extra -= 1; + } + if (extra) + { + delta->length += 1; + extra -= 1; + } + if (extra) + { + delta->length += (extra + 1) / 2; + } + + delta->data = malloc(delta->length + 33); + + unsigned int i = 0; + unsigned int j = 0; + int k; + uint8_t base; + int delta_index; + + while (i < pcm->length) + { + base = pcm->data[i++]; + delta->data[j++] = base; + + if (i >= pcm->length) + { + break; + } + delta_index = get_delta_index(pcm->data[i++], base); + base += gDeltaEncodingTable[delta_index]; + delta->data[j++] = delta_index; + + for (k = 0; k < 31; k++) + { + if (i >= pcm->length) + { + break; + } + delta_index = get_delta_index(pcm->data[i++], base); + base += gDeltaEncodingTable[delta_index]; + delta->data[j] = (delta_index << 4); + + if (i >= pcm->length) + { + break; + } + delta_index = get_delta_index(pcm->data[i++], base); + base += gDeltaEncodingTable[delta_index]; + delta->data[j++] |= delta_index; + } + } + + delta->length = j; + + return delta; +} + +#define STORE_U32_LE(dest, value) \ +do { \ + *(dest) = (value) & 0xff; \ + *((dest) + 1) = ((value) >> 8) & 0xff; \ + *((dest) + 2) = ((value) >> 16) & 0xff; \ + *((dest) + 3) = ((value) >> 24) & 0xff; \ +} while (0) + +#define LOAD_U32_LE(var, src) \ +do { \ + (var) = *(src); \ + (var) |= (*((src) + 1) << 8); \ + (var) |= (*((src) + 2) << 16); \ + (var) |= (*((src) + 3) << 24); \ +} while (0) + +// Reads an .aif file and produces a .pcm file containing an array of 8-bit samples. +void aif2pcm(const char *aif_filename, const char *pcm_filename, bool compress) +{ + struct Bytes *aif = read_bytearray(aif_filename); + AifData aif_data = {0}; + read_aif(aif, &aif_data); + + int header_size = 0x10; + struct Bytes *pcm; + struct Bytes output = {0}; + + if (compress) + { + struct Bytes *input = malloc(sizeof(struct Bytes)); + input->data = aif_data.samples; + input->length = aif_data.real_num_samples; + pcm = delta_compress(input); + free(input); + } + else + { + pcm = malloc(sizeof(struct Bytes)); + pcm->data = aif_data.samples; + pcm->length = aif_data.real_num_samples; + } + output.length = header_size + pcm->length; + output.data = malloc(output.length); + + uint32_t pitch_adjust = (uint32_t)(aif_data.sample_rate * 1024); + uint32_t loop_offset = (uint32_t)(aif_data.loop_offset); + uint32_t adjusted_num_samples = (uint32_t)(aif_data.num_samples - 1); + uint32_t flags = 0; + if (aif_data.has_loop) flags |= 0x40000000; + if (compress) flags |= 1; + STORE_U32_LE(output.data + 0, flags); + STORE_U32_LE(output.data + 4, pitch_adjust); + STORE_U32_LE(output.data + 8, loop_offset); + STORE_U32_LE(output.data + 12, adjusted_num_samples); + memcpy(&output.data[header_size], pcm->data, pcm->length); + write_bytearray(pcm_filename, &output); + + free(aif->data); + free(aif); + free(pcm); + free(output.data); + free(aif_data.samples); +} + +// Reads a .pcm file containing an array of 8-bit samples and produces an .aif file. +// See http://www-mmsp.ece.mcgill.ca/documents/audioformats/aiff/Docs/AIFF-1.3.pdf for .aif file specification. +void pcm2aif(const char *pcm_filename, const char *aif_filename, uint32_t base_note) +{ + struct Bytes *pcm = read_bytearray(pcm_filename); + + AifData *aif_data = malloc(sizeof(AifData)); + + uint32_t flags; + LOAD_U32_LE(flags, pcm->data + 0); + aif_data->has_loop = flags & 0x40000000; + bool compressed = flags & 1; + + uint32_t pitch_adjust; + LOAD_U32_LE(pitch_adjust, pcm->data + 4); + aif_data->sample_rate = pitch_adjust / 1024.0; + + LOAD_U32_LE(aif_data->loop_offset, pcm->data + 8); + LOAD_U32_LE(aif_data->num_samples, pcm->data + 12); + aif_data->num_samples += 1; + + if (compressed) + { + struct Bytes *delta = pcm; + uint8_t *pcm_data = pcm->data; + delta->length -= 0x10; + delta->data += 0x10; + pcm = delta_decompress(delta, aif_data->num_samples); + free(pcm_data); + free(delta); + } + else + { + pcm->length -= 0x10; + pcm->data += 0x10; + } + + aif_data->samples = malloc(pcm->length); + memcpy(aif_data->samples, pcm->data, pcm->length); + + struct Bytes *aif = malloc(sizeof(struct Bytes)); + aif->length = 54 + 60 + pcm->length; + aif->data = malloc(aif->length); + + long pos = 0; + + // First, write the FORM header chunk. + // FORM Chunk ckID + aif->data[pos++] = 'F'; + aif->data[pos++] = 'O'; + aif->data[pos++] = 'R'; + aif->data[pos++] = 'M'; + + // FORM Chunk ckSize + unsigned long form_size = pos; + unsigned long data_size = aif->length - 8; + aif->data[pos++] = ((data_size >> 24) & 0xFF); + aif->data[pos++] = ((data_size >> 16) & 0xFF); + aif->data[pos++] = ((data_size >> 8) & 0xFF); + aif->data[pos++] = (data_size & 0xFF); + + // FORM Chunk formType + aif->data[pos++] = 'A'; + aif->data[pos++] = 'I'; + aif->data[pos++] = 'F'; + aif->data[pos++] = 'F'; + + // Next, write the Common Chunk + // Common Chunk ckID + aif->data[pos++] = 'C'; + aif->data[pos++] = 'O'; + aif->data[pos++] = 'M'; + aif->data[pos++] = 'M'; + + // Common Chunk ckSize + aif->data[pos++] = 0; + aif->data[pos++] = 0; + aif->data[pos++] = 0; + aif->data[pos++] = 18; + + // Common Chunk numChannels + aif->data[pos++] = 0; + aif->data[pos++] = 1; // 1 channel + + // Common Chunk numSampleFrames + aif->data[pos++] = ((aif_data->num_samples >> 24) & 0xFF); + aif->data[pos++] = ((aif_data->num_samples >> 16) & 0xFF); + aif->data[pos++] = ((aif_data->num_samples >> 8) & 0xFF); + aif->data[pos++] = (aif_data->num_samples & 0xFF); + + // Common Chunk sampleSize + aif->data[pos++] = 0; + aif->data[pos++] = 8; // 8 bits per sample + + // Common Chunk sampleRate + //double sample_rate = pitch_adjust / 1024.0; + uint8_t sample_rate_buffer[10]; + ieee754_write_extended(aif_data->sample_rate, sample_rate_buffer); + for (int i = 0; i < 10; i++) + { + aif->data[pos++] = sample_rate_buffer[i]; + } + + if (aif_data->has_loop) + { + + // Marker Chunk ckID + aif->data[pos++] = 'M'; + aif->data[pos++] = 'A'; + aif->data[pos++] = 'R'; + aif->data[pos++] = 'K'; + + // Marker Chunk ckSize + aif->data[pos++] = 0; + aif->data[pos++] = 0; + aif->data[pos++] = 0; + aif->data[pos++] = 12 + (aif_data->has_loop ? 12 : 0); + + // Marker Chunk numMarkers + aif->data[pos++] = 0; + aif->data[pos++] = (aif_data->has_loop ? 2 : 1); + + // Marker loop start + aif->data[pos++] = 0; + aif->data[pos++] = 1; // id = 1 + + long loop_start = aif_data->loop_offset; + aif->data[pos++] = ((loop_start >> 24) & 0xFF); + aif->data[pos++] = ((loop_start >> 16) & 0xFF); + aif->data[pos++] = ((loop_start >> 8) & 0xFF); + aif->data[pos++] = (loop_start & 0xFF); // position + + aif->data[pos++] = 5; // pascal-style string length + aif->data[pos++] = 'S'; + aif->data[pos++] = 'T'; + aif->data[pos++] = 'A'; + aif->data[pos++] = 'R'; + aif->data[pos++] = 'T'; // markerName + + // Marker loop end + aif->data[pos++] = 0; + aif->data[pos++] = (aif_data->has_loop ? 2 : 1); // id = 2 + + long loop_end = aif_data->num_samples; + aif->data[pos++] = ((loop_end >> 24) & 0xFF); + aif->data[pos++] = ((loop_end >> 16) & 0xFF); + aif->data[pos++] = ((loop_end >> 8) & 0xFF); + aif->data[pos++] = (loop_end & 0xFF); // position + + aif->data[pos++] = 3; // pascal-style string length + aif->data[pos++] = 'E'; + aif->data[pos++] = 'N'; + aif->data[pos++] = 'D'; + } + + // Instrument Chunk ckID + aif->data[pos++] = 'I'; + aif->data[pos++] = 'N'; + aif->data[pos++] = 'S'; + aif->data[pos++] = 'T'; + + // Instrument Chunk ckSize + aif->data[pos++] = 0; + aif->data[pos++] = 0; + aif->data[pos++] = 0; + aif->data[pos++] = 20; + + aif->data[pos++] = base_note; // baseNote + aif->data[pos++] = 0; // detune + aif->data[pos++] = 0; // lowNote + aif->data[pos++] = 127; // highNote + aif->data[pos++] = 1; // lowVelocity + aif->data[pos++] = 127; // highVelocity + aif->data[pos++] = 0; // gain (hi) + aif->data[pos++] = 0; // gain (lo) + + // Instrument Chunk sustainLoop + aif->data[pos++] = 0; + aif->data[pos++] = 1; // playMode = ForwardLooping + + aif->data[pos++] = 0; + aif->data[pos++] = 1; // beginLoop marker id + + aif->data[pos++] = 0; + aif->data[pos++] = 2; // endLoop marker id + + // Instrument Chunk releaseLoop + aif->data[pos++] = 0; + aif->data[pos++] = 1; // playMode = ForwardLooping + + aif->data[pos++] = 0; + aif->data[pos++] = 1; // beginLoop marker id + + aif->data[pos++] = 0; + aif->data[pos++] = 2; // endLoop marker id + + // Finally, write the Sound Data Chunk + // Sound Data Chunk ckID + aif->data[pos++] = 'S'; + aif->data[pos++] = 'S'; + aif->data[pos++] = 'N'; + aif->data[pos++] = 'D'; + + // Sound Data Chunk ckSize + unsigned long sound_data_size = pcm->length + 8; + aif->data[pos++] = ((sound_data_size >> 24) & 0xFF); + aif->data[pos++] = ((sound_data_size >> 16) & 0xFF); + aif->data[pos++] = ((sound_data_size >> 8) & 0xFF); + aif->data[pos++] = (sound_data_size & 0xFF); + + // Sound Data Chunk offset + aif->data[pos++] = 0; + aif->data[pos++] = 0; + aif->data[pos++] = 0; + aif->data[pos++] = 0; + + // Sound Data Chunk blockSize + aif->data[pos++] = 0; + aif->data[pos++] = 0; + aif->data[pos++] = 0; + aif->data[pos++] = 0; + + // Sound Data Chunk soundData + for (unsigned int i = 0; i < aif_data->loop_offset; i++) + { + aif->data[pos++] = aif_data->samples[i]; + } + + int j = 0; + for (unsigned int i = aif_data->loop_offset; i < pcm->length; i++) + { + int pcm_index = aif_data->loop_offset + (j++ % (pcm->length - aif_data->loop_offset)); + aif->data[pos++] = aif_data->samples[pcm_index]; + } + + aif->length = pos; + + // Go back and rewrite ckSize + data_size = aif->length - 8; + aif->data[form_size + 0] = ((data_size >> 24) & 0xFF); + aif->data[form_size + 1] = ((data_size >> 16) & 0xFF); + aif->data[form_size + 2] = ((data_size >> 8) & 0xFF); + aif->data[form_size + 3] = (data_size & 0xFF); + + write_bytearray(aif_filename, aif); + + free(aif->data); + free(aif); +} + +void usage(void) +{ + fprintf(stderr, "Usage: aif2pcm bin_file [aif_file]\n"); + fprintf(stderr, " aif2pcm aif_file [bin_file] [--compress]\n"); +} + +int main(int argc, char **argv) +{ + if (argc < 2) + { + usage(); + exit(1); + } + + char *input_file = argv[1]; + char *extension = get_file_extension(input_file); + char *output_file; + bool compressed = false; + + if (argc > 3) + { + for (int i = 3; i < argc; i++) + { + if (strcmp(argv[i], "--compress") == 0) + { + compressed = true; + } + } + } + + if (strcmp(extension, "aif") == 0 || strcmp(extension, "aiff") == 0) + { + if (argc >= 3) + { + output_file = argv[2]; + aif2pcm(input_file, output_file, compressed); + } + else + { + output_file = new_file_extension(input_file, "bin"); + aif2pcm(input_file, output_file, compressed); + free(output_file); + } + } + else if (strcmp(extension, "bin") == 0) + { + if (argc >= 3) + { + output_file = argv[2]; + pcm2aif(input_file, output_file, 60); + } + else + { + output_file = new_file_extension(input_file, "aif"); + pcm2aif(input_file, output_file, 60); + free(output_file); + } + } + else + { + FATAL_ERROR("Input file must be .aif or .bin: '%s'\n", input_file); + } + + return 0; +} diff --git a/tools/bin2c/.gitignore b/tools/bin2c/.gitignore new file mode 100644 index 0000000..366f3d3 --- /dev/null +++ b/tools/bin2c/.gitignore @@ -0,0 +1 @@ +bin2c diff --git a/tools/bin2c/LICENSE b/tools/bin2c/LICENSE new file mode 100644 index 0000000..534d153 --- /dev/null +++ b/tools/bin2c/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2016 YamaArashi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/tools/bin2c/Makefile b/tools/bin2c/Makefile new file mode 100644 index 0000000..dd4e537 --- /dev/null +++ b/tools/bin2c/Makefile @@ -0,0 +1,16 @@ +CC = gcc + +CFLAGS = -Wall -Wextra -Werror -std=c11 -O2 -s + +.PHONY: all clean + +SRCS = bin2c.c + +all: bin2c + @: + +bin2c: $(SRCS) + $(CC) $(CFLAGS) $(SRCS) -o $@ $(LDFLAGS) + +clean: + $(RM) bin2c bin2c.exe diff --git a/tools/bin2c/bin2c.c b/tools/bin2c/bin2c.c new file mode 100644 index 0000000..b4bd437 --- /dev/null +++ b/tools/bin2c/bin2c.c @@ -0,0 +1,201 @@ +// Copyright(c) 2015-2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include +#include +#include +#include + +#ifdef _MSC_VER + +#define FATAL_ERROR(format, ...) \ +do \ +{ \ + fprintf(stderr, format, __VA_ARGS__); \ + exit(1); \ +} while (0) + +#else + +#define FATAL_ERROR(format, ...) \ +do \ +{ \ + fprintf(stderr, format, ##__VA_ARGS__); \ + exit(1); \ +} while (0) + +#endif // _MSC_VER + +unsigned char *ReadWholeFile(char *path, int *size) +{ + FILE *fp = fopen(path, "rb"); + + if (fp == NULL) + FATAL_ERROR("Failed to open \"%s\" for reading.\n", path); + + fseek(fp, 0, SEEK_END); + + *size = ftell(fp); + + unsigned char *buffer = malloc(*size); + + if (buffer == NULL) + FATAL_ERROR("Failed to allocate memory for reading \"%s\".\n", path); + + rewind(fp); + + if (fread(buffer, *size, 1, fp) != 1) + FATAL_ERROR("Failed to read \"%s\".\n", path); + + fclose(fp); + + return buffer; +} + +int ExtractData(unsigned char *buffer, int offset, int size) +{ + switch (size) + { + case 1: + return buffer[offset]; + case 2: + return (buffer[offset + 1] << 8) + | buffer[offset]; + case 4: + return (buffer[offset + 3] << 24) + | (buffer[offset + 2] << 16) + | (buffer[offset + 1] << 8) + | buffer[offset]; + default: + FATAL_ERROR("Invalid size passed to ExtractData.\n"); + } +} + +int main(int argc, char **argv) +{ + if (argc < 3) + FATAL_ERROR("Usage: bin2c INPUT_FILE VAR_NAME [OPTIONS...]\n"); + + int fileSize; + unsigned char *buffer = ReadWholeFile(argv[1], &fileSize); + char *var_name = argv[2]; + int col = 1; + int pad = 0; + int size = 1; + bool isSigned = false; + bool isStatic = false; + bool isDecimal = false; + + for (int i = 3; i < argc; i++) + { + if (!strcmp(argv[i], "-col")) + { + i++; + + if (i >= argc) + FATAL_ERROR("Missing argument after '-col'.\n"); + + col = atoi(argv[i]); + } + else if (!strcmp(argv[i], "-pad")) + { + i++; + + if (i >= argc) + FATAL_ERROR("Missing argument after '-pad'.\n"); + + pad = atoi(argv[i]); + } + else if (!strcmp(argv[i], "-size")) + { + i++; + + if (i >= argc) + FATAL_ERROR("Missing argument after '-size'.\n"); + + size = atoi(argv[i]); + + if (size != 1 && size != 2 && size != 4) + FATAL_ERROR("Size must be 1, 2, or 4.\n"); + } + else if (!strcmp(argv[i], "-signed")) + { + isSigned = true; + isDecimal = true; + } + else if (!strcmp(argv[i], "-static")) + { + isStatic = true; + } + else if (!strcmp(argv[i], "-decimal")) + { + isDecimal = true; + } + else + { + FATAL_ERROR("Unrecognized option '%s'.\n", argv[i]); + } + } + + if ((fileSize & (size - 1)) != 0) + FATAL_ERROR("Size %d doesn't evenly divide file size %d.\n", size, fileSize); + + printf("// Generated file. Do not edit.\n\n"); + + if (isStatic) + printf("static "); + + printf("const "); + + if (isSigned) + printf("s%d ", 8 * size); + else + printf("u%d ", 8 * size); + + printf("%s[] =\n{", var_name); + + int count = fileSize / size; + int offset = 0; + + for (int i = 0; i < count; i++) + { + if (i % col == 0) + printf("\n "); + + int data = ExtractData(buffer, offset, size); + offset += size; + + if (isDecimal) + { + if (isSigned) + printf("%*d, ", pad, data); + else + printf("%*uu, ", pad, data); + } + else + { + printf("%#*xu, ", pad, data); + } + } + + printf("\n};\n"); + + return 0; +} diff --git a/tools/gbafix/.gitignore b/tools/gbafix/.gitignore new file mode 100644 index 0000000..3cebf8a --- /dev/null +++ b/tools/gbafix/.gitignore @@ -0,0 +1,2 @@ +gbafix +README diff --git a/tools/gbafix/COPYING b/tools/gbafix/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/tools/gbafix/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/tools/gbafix/Makefile b/tools/gbafix/Makefile new file mode 100644 index 0000000..350af76 --- /dev/null +++ b/tools/gbafix/Makefile @@ -0,0 +1,14 @@ +CC = gcc + +SRCS = gbafix.c + +.PHONY: all clean + +all: gbafix + @: + +gbafix: $(SRCS) + $(CC) $(SRCS) -o $@ $(LDFLAGS) + +clean: + $(RM) gbafix gbafix.exe diff --git a/tools/gbafix/gbafix.c b/tools/gbafix/gbafix.c new file mode 100644 index 0000000..d5e2f62 --- /dev/null +++ b/tools/gbafix/gbafix.c @@ -0,0 +1,289 @@ +/* + "$Id: gbafix.c,v 1.2 2008-07-30 17:12:51 wntrmute Exp $" + + DevkitPro GBA ROM fix utility + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. + + Please report all bugs and problems through the bug tracker at + "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 $" + +*/ +//--------------------------------------------------------------------------------- +// gbafix.c +//--------------------------------------------------------------------------------- +/* + Gameboy Advance ROM fixer (by Dark Fader / BlackThunder / WinterMute / Diegoisawesome) + Validates header of GBA roms. + + History + ------- + v1.06 - added output silencing, (Diegoisawesome) + v1.05 - added debug offset argument, (Diegoisawesome) + v1.04 - converted to plain C, (WinterMute) + v1.03 - header.fixed, header.device_type + v1.02 - redefined the options (rgbfix style), checksum=0 + v1.01 - fix in parameters + v1.00 - logo, complement +*/ + +#pragma pack(1) + +#include +#include +#include +#include + +#define VER "1.06" +#define ARGV argv[arg] +#define VALUE (ARGV+2) +#define NUMBER strtoul(VALUE, NULL, 0) + +typedef struct +{ + uint32_t start_code; // B instruction + uint8_t logo[0xA0-0x04]; // logo data + uint8_t title[0xC]; // game title name + uint32_t game_code; // + uint16_t maker_code; // + uint8_t fixed; // 0x96 + uint8_t unit_code; // 0x00 + uint8_t device_type; // 0x00 + uint8_t unused[7]; // + uint8_t game_version; // 0x00 + uint8_t complement; // 800000A0..800000BC + uint16_t checksum; // 0x0000 +} Header; + + +Header header; + +unsigned short checksum_without_header = 0; + +const Header good_header = +{ + // start_code + 0xEA00002E, + // logo + { 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, + 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, + 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, + 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, + 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 } , + // title + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + // game code + 0x00000000, + // maker code + 0x3130, + // fixed + 0x96, + // unit_code + 0x00, + // device type + 0x00, + // unused + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + // game version + 0x00, + // complement + 0x00, + // checksum + 0x0000 +}; + +//--------------------------------------------------------------------------------- +char HeaderComplement() +/*--------------------------------------------------------------------------------- + Calculate Header complement check +---------------------------------------------------------------------------------*/ +{ + int n; + char c = 0; + char *p = (char *)&header + 0xA0; + for (n=0; n<0xBD-0xA0; n++) + { + c += *p++; + } + return -(0x19+c); +} + + +//--------------------------------------------------------------------------------- +int main(int argc, char *argv[]) +//--------------------------------------------------------------------------------- +{ + int arg; + char *argfile = 0; + FILE *infile; + int silent = 0; + + int size,bit; + + // show syntax + if (argc <= 1) + { + printf("GBA ROM fixer v"VER" by Dark Fader / BlackThunder / WinterMute / Diegoisawesome \n"); + printf("Syntax: gbafix [-p] [-t[title]] [-c] [-m] [-r] [-d] [--silent]\n"); + printf("\n"); + printf("parameters:\n"); + printf(" -p Pad to next exact power of 2. No minimum size!\n"); + printf(" -t[] Patch title. Stripped filename if none given.\n"); + printf(" -c<game_code> Patch game code (four characters)\n"); + printf(" -m<maker_code> Patch maker code (two characters)\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(" --silent Silence non-error output\n"); + return -1; + } + + // get filename + for (arg=1; arg<argc; arg++) + { + if ((ARGV[0] != '-')) { argfile=ARGV; } + if (strncmp("--silent", &ARGV[0], 7) == 0) { silent = 1; } + } + + // check filename + if (!argfile) + { + fprintf(stderr, "Filename needed!\n"); + return -1; + } + + // read file + infile = fopen(argfile, "r+b"); + if (!infile) { fprintf(stderr, "Error opening input file!\n"); return -1; } + fseek(infile, 0, SEEK_SET); + fread(&header, sizeof(header), 1, infile); + + // fix some data + memcpy(header.logo, good_header.logo, sizeof(header.logo)); + memcpy(&header.fixed, &good_header.fixed, sizeof(header.fixed)); + memcpy(&header.device_type, &good_header.device_type, sizeof(header.device_type)); + + // parse command line + for (arg=1; arg<argc; arg++) + { + if ((ARGV[0] == '-')) + { + 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 + { + char title[256]; + memset(title, 0, sizeof(title)); + if (VALUE[0]) + { + 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 'c': // game code + { + //if (!VALUE[0]) { fprintf(stderr, "Need value for %s\n", ARGV); break; } + //header.game_code = NUMBER; + header.game_code = VALUE[0] | VALUE[1]<<8 | VALUE[2]<<16 | VALUE[3]<<24; + break; + } + + case 'm': // maker code + { + //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 'v': // ignored, compatability with other gbafix + { + break; + } + + case 'r': // version + { + if (!VALUE[0]) { fprintf(stderr, "Need value for %s\n", ARGV); break; } + header.game_version = (unsigned char)NUMBER; + break; + } + + case 'd': // debug + { + if (!VALUE[0]) { fprintf(stderr, "Need value for %s\n", ARGV); break; } + header.logo[0x9C-0x04] = 0xA5; // debug enable + 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); + } + } + } + } + + // update complement check & total checksum + header.complement = 0; + header.checksum = 0; // must be 0 + header.complement = HeaderComplement(); + //header.checksum = checksum_without_header + HeaderChecksum(); + + fseek(infile, 0, SEEK_SET); + fwrite(&header, sizeof(header), 1, infile); + fclose(infile); + + if (!silent) printf("ROM fixed!\n"); + + return 0; +} diff --git a/tools/gbagfx/.gitignore b/tools/gbagfx/.gitignore new file mode 100644 index 0000000..dbbb3f0 --- /dev/null +++ b/tools/gbagfx/.gitignore @@ -0,0 +1 @@ +gbagfx diff --git a/tools/gbagfx/LICENSE b/tools/gbagfx/LICENSE new file mode 100644 index 0000000..b66bf81 --- /dev/null +++ b/tools/gbagfx/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015 YamaArashi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/tools/gbagfx/Makefile b/tools/gbagfx/Makefile new file mode 100644 index 0000000..c10b258 --- /dev/null +++ b/tools/gbagfx/Makefile @@ -0,0 +1,18 @@ +CC = gcc + +CFLAGS = -Wall -Wextra -Werror -std=c11 -O2 -s -DPNG_SKIP_SETJMP_CHECK + +LIBS = -lpng -lz + +SRCS = main.c convert_png.c gfx.c jasc_pal.c lz.c rl.c util.c font.c + +.PHONY: all clean + +all: gbagfx + @: + +gbagfx: $(SRCS) convert_png.h gfx.h global.h jasc_pal.h lz.h rl.h util.h font.h + $(CC) $(CFLAGS) $(SRCS) -o $@ $(LDFLAGS) $(LIBS) + +clean: + $(RM) gbagfx gbagfx.exe diff --git a/tools/gbagfx/convert_png.c b/tools/gbagfx/convert_png.c new file mode 100644 index 0000000..cdfa39a --- /dev/null +++ b/tools/gbagfx/convert_png.c @@ -0,0 +1,254 @@ +// Copyright (c) 2015 YamaArashi + +#include <stdio.h> +#include <setjmp.h> +#include <png.h> +#include "global.h" +#include "convert_png.h" +#include "gfx.h" + +static FILE *PngReadOpen(char *path, png_structp *pngStruct, png_infop *pngInfo) +{ + FILE *fp = fopen(path, "rb"); + + if (fp == NULL) + FATAL_ERROR("Failed to open \"%s\" for reading.\n", path); + + unsigned char sig[8]; + + if (fread(sig, 8, 1, fp) != 1) + FATAL_ERROR("Failed to read PNG signature from \"%s\".\n", path); + + if (png_sig_cmp(sig, 0, 8)) + FATAL_ERROR("\"%s\" does not have a valid PNG signature.\n", path); + + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + + if (!png_ptr) + FATAL_ERROR("Failed to create PNG read struct.\n"); + + png_infop info_ptr = png_create_info_struct(png_ptr); + + if (!info_ptr) + FATAL_ERROR("Failed to create PNG info struct.\n"); + + if (setjmp(png_jmpbuf(png_ptr))) + FATAL_ERROR("Failed to init I/O for reading \"%s\".\n", path); + + png_init_io(png_ptr, fp); + png_set_sig_bytes(png_ptr, 8); + png_read_info(png_ptr, info_ptr); + + *pngStruct = png_ptr; + *pngInfo = info_ptr; + + return fp; +} + +static unsigned char *ConvertBitDepth(unsigned char *src, int srcBitDepth, int destBitDepth, int numPixels) +{ + // Round the number of bits up to the next 8 and divide by 8 to get the number of bytes. + int srcSize = ((numPixels * srcBitDepth + 7) & ~7) / 8; + int destSize = ((numPixels * destBitDepth + 7) & ~7) / 8; + unsigned char *output = calloc(destSize, 1); + unsigned char *dest = output; + int i; + int j; + int destBit = 8 - destBitDepth; + + for (i = 0; i < srcSize; i++) + { + unsigned char srcByte = src[i]; + + for (j = 8 - srcBitDepth; j >= 0; j -= srcBitDepth) + { + unsigned char pixel = (srcByte >> j) % (1 << srcBitDepth); + + if (pixel >= (1 << destBitDepth)) + FATAL_ERROR("Image exceeds the maximum color value for a %ibpp image.\n", destBitDepth); + *dest |= pixel << destBit; + destBit -= destBitDepth; + if (destBit < 0) + { + dest++; + destBit = 8 - destBitDepth; + } + } + } + + return output; +} + +void ReadPng(char *path, struct Image *image) +{ + png_structp png_ptr; + png_infop info_ptr; + + FILE *fp = PngReadOpen(path, &png_ptr, &info_ptr); + + int bit_depth = png_get_bit_depth(png_ptr, info_ptr); + + int color_type = png_get_color_type(png_ptr, info_ptr); + + if (color_type != PNG_COLOR_TYPE_GRAY && color_type != PNG_COLOR_TYPE_PALETTE) + FATAL_ERROR("\"%s\" has an unsupported color type.\n", path); + + // Check if the image has a palette so that we can tell if the colors need to be inverted later. + // Don't read the palette because it's not needed for now. + image->hasPalette = (color_type == PNG_COLOR_TYPE_PALETTE); + + image->width = png_get_image_width(png_ptr, info_ptr); + image->height = png_get_image_height(png_ptr, info_ptr); + + int rowbytes = png_get_rowbytes(png_ptr, info_ptr); + + image->pixels = malloc(image->height * rowbytes); + + if (image->pixels == NULL) + FATAL_ERROR("Failed to allocate pixel buffer.\n"); + + png_bytepp row_pointers = malloc(image->height * sizeof(png_bytep)); + + if (row_pointers == NULL) + FATAL_ERROR("Failed to allocate row pointers.\n"); + + for (int i = 0; i < image->height; i++) + row_pointers[i] = (png_bytep)(image->pixels + (i * rowbytes)); + + if (setjmp(png_jmpbuf(png_ptr))) + FATAL_ERROR("Error reading from \"%s\".\n", path); + + png_read_image(png_ptr, row_pointers); + + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + + free(row_pointers); + fclose(fp); + + if (bit_depth != image->bitDepth) + { + unsigned char *src = image->pixels; + + if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 && bit_depth != 8) + FATAL_ERROR("Bit depth of image must be 1, 2, 4, or 8.\n"); + image->pixels = ConvertBitDepth(image->pixels, bit_depth, image->bitDepth, image->width * image->height); + free(src); + image->bitDepth = bit_depth; + } +} + +void ReadPngPalette(char *path, struct Palette *palette) +{ + png_structp png_ptr; + png_infop info_ptr; + png_colorp colors; + int numColors; + + FILE *fp = PngReadOpen(path, &png_ptr, &info_ptr); + + if (png_get_color_type(png_ptr, info_ptr) != PNG_COLOR_TYPE_PALETTE) + FATAL_ERROR("The image \"%s\" does not contain a palette.\n", path); + + if (png_get_PLTE(png_ptr, info_ptr, &colors, &numColors) != PNG_INFO_PLTE) + FATAL_ERROR("Failed to retrieve palette from \"%s\".\n", path); + + if (numColors > 256) + FATAL_ERROR("Images with more than 256 colors are not supported.\n"); + + palette->numColors = numColors; + for (int i = 0; i < numColors; i++) { + palette->colors[i].red = colors[i].red; + palette->colors[i].green = colors[i].green; + palette->colors[i].blue = colors[i].blue; + } + + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + + fclose(fp); +} + +void SetPngPalette(png_structp png_ptr, png_infop info_ptr, struct Palette *palette) +{ + png_colorp colors = malloc(palette->numColors * sizeof(png_color)); + + if (colors == NULL) + FATAL_ERROR("Failed to allocate PNG palette.\n"); + + for (int i = 0; i < palette->numColors; i++) { + colors[i].red = palette->colors[i].red; + colors[i].green = palette->colors[i].green; + colors[i].blue = palette->colors[i].blue; + } + + png_set_PLTE(png_ptr, info_ptr, colors, palette->numColors); + + free(colors); +} + +void WritePng(char *path, struct Image *image) +{ + FILE *fp = fopen(path, "wb"); + + if (fp == NULL) + FATAL_ERROR("Failed to open \"%s\" for writing.\n", path); + + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + + if (!png_ptr) + FATAL_ERROR("Failed to create PNG write struct.\n"); + + png_infop info_ptr = png_create_info_struct(png_ptr); + + if (!info_ptr) + FATAL_ERROR("Failed to create PNG info struct.\n"); + + if (setjmp(png_jmpbuf(png_ptr))) + FATAL_ERROR("Failed to init I/O for writing \"%s\".\n", path); + + png_init_io(png_ptr, fp); + + if (setjmp(png_jmpbuf(png_ptr))) + FATAL_ERROR("Error writing header for \"%s\".\n", path); + + int color_type = image->hasPalette ? PNG_COLOR_TYPE_PALETTE : PNG_COLOR_TYPE_GRAY; + + png_set_IHDR(png_ptr, info_ptr, image->width, image->height, + image->bitDepth, color_type, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + if (image->hasPalette) { + SetPngPalette(png_ptr, info_ptr, &image->palette); + + if (image->hasTransparency) { + png_byte trans = 0; + png_set_tRNS(png_ptr, info_ptr, &trans, 1, 0); + } + } + + png_write_info(png_ptr, info_ptr); + + png_bytepp row_pointers = malloc(image->height * sizeof(png_bytep)); + + if (row_pointers == NULL) + FATAL_ERROR("Failed to allocate row pointers.\n"); + + int rowbytes = png_get_rowbytes(png_ptr, info_ptr); + + for (int i = 0; i < image->height; i++) + row_pointers[i] = (png_bytep)(image->pixels + (i * rowbytes)); + + if (setjmp(png_jmpbuf(png_ptr))) + FATAL_ERROR("Error writing \"%s\".\n", path); + + png_write_image(png_ptr, row_pointers); + + if (setjmp(png_jmpbuf(png_ptr))) + FATAL_ERROR("Error ending write of \"%s\".\n", path); + + png_write_end(png_ptr, NULL); + + fclose(fp); + + png_destroy_write_struct(&png_ptr, &info_ptr); + free(row_pointers); +} diff --git a/tools/gbagfx/convert_png.h b/tools/gbagfx/convert_png.h new file mode 100644 index 0000000..caf081b --- /dev/null +++ b/tools/gbagfx/convert_png.h @@ -0,0 +1,12 @@ +// Copyright (c) 2015 YamaArashi + +#ifndef CONVERT_PNG_H +#define CONVERT_PNG_H + +#include "gfx.h" + +void ReadPng(char *path, struct Image *image); +void WritePng(char *path, struct Image *image); +void ReadPngPalette(char *path, struct Palette *palette); + +#endif // CONVERT_PNG_H diff --git a/tools/gbagfx/font.c b/tools/gbagfx/font.c new file mode 100644 index 0000000..0dd6fbc --- /dev/null +++ b/tools/gbagfx/font.c @@ -0,0 +1,326 @@ +// Copyright (c) 2015 YamaArashi + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdbool.h> +#include "global.h" +#include "font.h" +#include "gfx.h" +#include "util.h" + +unsigned char gFontPalette[][3] = { + {0x90, 0xC8, 0xFF}, // bg (saturated blue that contrasts well with the shadow color) + {0x38, 0x38, 0x38}, // fg (dark grey) + {0xD8, 0xD8, 0xD8}, // shadow (light grey) + {0xFF, 0xFF, 0xFF} // box (white) +}; + +static void ConvertFromLatinFont(unsigned char *src, unsigned char *dest, unsigned int numRows) +{ + unsigned int srcPixelsOffset = 0; + + for (unsigned int row = 0; row < numRows; row++) { + for (unsigned int column = 0; column < 16; column++) { + for (unsigned int glyphTile = 0; glyphTile < 4; glyphTile++) { + unsigned int pixelsX = (column * 16) + ((glyphTile & 1) * 8); + + for (unsigned int i = 0; i < 8; i++) { + unsigned int pixelsY = (row * 16) + ((glyphTile >> 1) * 8) + i; + unsigned int destPixelsOffset = (pixelsY * 64) + (pixelsX / 4); + + dest[destPixelsOffset] = src[srcPixelsOffset + 1]; + dest[destPixelsOffset + 1] = src[srcPixelsOffset]; + + srcPixelsOffset += 2; + } + } + } + } +} + +static void ConvertToLatinFont(unsigned char *src, unsigned char *dest, unsigned int numRows) +{ + unsigned int destPixelsOffset = 0; + + for (unsigned int row = 0; row < numRows; row++) { + for (unsigned int column = 0; column < 16; column++) { + for (unsigned int glyphTile = 0; glyphTile < 4; glyphTile++) { + unsigned int pixelsX = (column * 16) + ((glyphTile & 1) * 8); + + for (unsigned int i = 0; i < 8; i++) { + unsigned int pixelsY = (row * 16) + ((glyphTile >> 1) * 8) + i; + unsigned int srcPixelsOffset = (pixelsY * 64) + (pixelsX / 4); + + dest[destPixelsOffset] = src[srcPixelsOffset + 1]; + dest[destPixelsOffset + 1] = src[srcPixelsOffset]; + + destPixelsOffset += 2; + } + } + } + } +} + +static void ConvertFromHalfwidthJapaneseFont(unsigned char *src, unsigned char *dest, unsigned int numRows) +{ + for (unsigned int row = 0; row < numRows; row++) { + for (unsigned int column = 0; column < 16; column++) { + unsigned int glyphIndex = (row * 16) + column; + + for (unsigned int glyphTile = 0; glyphTile < 2; glyphTile++) { + unsigned int pixelsX = column * 8; + unsigned int srcPixelsOffset = 512 * (glyphIndex >> 4) + 16 * (glyphIndex & 0xF) + 256 * glyphTile; + + for (unsigned int i = 0; i < 8; i++) { + unsigned int pixelsY = (row * 16) + (glyphTile * 8) + i; + unsigned int destPixelsOffset = (pixelsY * 32) + (pixelsX / 4); + + dest[destPixelsOffset] = src[srcPixelsOffset + 1]; + dest[destPixelsOffset + 1] = src[srcPixelsOffset]; + + srcPixelsOffset += 2; + } + } + } + } +} + +static void ConvertToHalfwidthJapaneseFont(unsigned char *src, unsigned char *dest, unsigned int numRows) +{ + for (unsigned int row = 0; row < numRows; row++) { + for (unsigned int column = 0; column < 16; column++) { + unsigned int glyphIndex = (row * 16) + column; + + for (unsigned int glyphTile = 0; glyphTile < 2; glyphTile++) { + unsigned int pixelsX = column * 8; + unsigned int destPixelsOffset = 512 * (glyphIndex >> 4) + 16 * (glyphIndex & 0xF) + 256 * glyphTile; + + for (unsigned int i = 0; i < 8; i++) { + unsigned int pixelsY = (row * 16) + (glyphTile * 8) + i; + unsigned int srcPixelsOffset = (pixelsY * 32) + (pixelsX / 4); + + dest[destPixelsOffset] = src[srcPixelsOffset + 1]; + dest[destPixelsOffset + 1] = src[srcPixelsOffset]; + + destPixelsOffset += 2; + } + } + } + } +} + +static void ConvertFromFullwidthJapaneseFont(unsigned char *src, unsigned char *dest, unsigned int numRows) +{ + for (unsigned int row = 0; row < numRows; row++) { + for (unsigned int column = 0; column < 16; column++) { + unsigned int glyphIndex = (row * 16) + column; + + for (unsigned int glyphTile = 0; glyphTile < 4; glyphTile++) { + unsigned int pixelsX = (column * 16) + ((glyphTile & 1) * 8); + unsigned int srcPixelsOffset = 512 * (glyphIndex >> 3) + 32 * (glyphIndex & 7) + 256 * (glyphTile >> 1) + 16 * (glyphTile & 1); + + for (unsigned int i = 0; i < 8; i++) { + unsigned int pixelsY = (row * 16) + ((glyphTile >> 1) * 8) + i; + unsigned int destPixelsOffset = (pixelsY * 64) + (pixelsX / 4); + + dest[destPixelsOffset] = src[srcPixelsOffset + 1]; + dest[destPixelsOffset + 1] = src[srcPixelsOffset]; + + srcPixelsOffset += 2; + } + } + } + } +} + +static void ConvertToFullwidthJapaneseFont(unsigned char *src, unsigned char *dest, unsigned int numRows) +{ + for (unsigned int row = 0; row < numRows; row++) { + for (unsigned int column = 0; column < 16; column++) { + unsigned int glyphIndex = (row * 16) + column; + + for (unsigned int glyphTile = 0; glyphTile < 4; glyphTile++) { + unsigned int pixelsX = (column * 16) + ((glyphTile & 1) * 8); + unsigned int destPixelsOffset = 512 * (glyphIndex >> 3) + 32 * (glyphIndex & 7) + 256 * (glyphTile >> 1) + 16 * (glyphTile & 1); + + for (unsigned int i = 0; i < 8; i++) { + unsigned int pixelsY = (row * 16) + ((glyphTile >> 1) * 8) + i; + unsigned int srcPixelsOffset = (pixelsY * 64) + (pixelsX / 4); + + dest[destPixelsOffset] = src[srcPixelsOffset + 1]; + dest[destPixelsOffset + 1] = src[srcPixelsOffset]; + + destPixelsOffset += 2; + } + } + } + } +} + +static void SetFontPalette(struct Image *image) +{ + image->hasPalette = true; + + image->palette.numColors = 4; + + for (int i = 0; i < image->palette.numColors; i++) { + image->palette.colors[i].red = gFontPalette[i][0]; + image->palette.colors[i].green = gFontPalette[i][1]; + image->palette.colors[i].blue = gFontPalette[i][2]; + } + + image->hasTransparency = false; +} + +void ReadLatinFont(char *path, struct Image *image) +{ + int fileSize; + unsigned char *buffer = ReadWholeFile(path, &fileSize); + + int numGlyphs = fileSize / 64; + + if (numGlyphs % 16 != 0) + FATAL_ERROR("The number of glyphs (%d) is not a multiple of 16.\n", numGlyphs); + + int numRows = numGlyphs / 16; + + image->width = 256; + image->height = numRows * 16; + image->bitDepth = 2; + image->pixels = malloc(fileSize); + + if (image->pixels == NULL) + FATAL_ERROR("Failed to allocate memory for font.\n"); + + ConvertFromLatinFont(buffer, image->pixels, numRows); + + free(buffer); + + SetFontPalette(image); +} + +void WriteLatinFont(char *path, struct Image *image) +{ + if (image->width != 256) + FATAL_ERROR("The width of the font image (%d) is not 256.\n", image->width); + + if (image->height % 16 != 0) + FATAL_ERROR("The height of the font image (%d) is not a multiple of 16.\n", image->height); + + int numRows = image->height / 16; + int bufferSize = numRows * 16 * 64; + unsigned char *buffer = malloc(bufferSize); + + if (buffer == NULL) + FATAL_ERROR("Failed to allocate memory for font.\n"); + + ConvertToLatinFont(image->pixels, buffer, numRows); + + WriteWholeFile(path, buffer, bufferSize); + + free(buffer); +} + +void ReadHalfwidthJapaneseFont(char *path, struct Image *image) +{ + int fileSize; + unsigned char *buffer = ReadWholeFile(path, &fileSize); + + int glyphSize = 32; + + if (fileSize % glyphSize != 0) + FATAL_ERROR("The file size (%d) is not a multiple of %d.\n", fileSize, glyphSize); + + int numGlyphs = fileSize / glyphSize; + + if (numGlyphs % 16 != 0) + FATAL_ERROR("The number of glyphs (%d) is not a multiple of 16.\n", numGlyphs); + + int numRows = numGlyphs / 16; + + image->width = 128; + image->height = numRows * 16; + image->bitDepth = 2; + image->pixels = malloc(fileSize); + + if (image->pixels == NULL) + FATAL_ERROR("Failed to allocate memory for font.\n"); + + ConvertFromHalfwidthJapaneseFont(buffer, image->pixels, numRows); + + free(buffer); + + SetFontPalette(image); +} + +void WriteHalfwidthJapaneseFont(char *path, struct Image *image) +{ + if (image->width != 128) + FATAL_ERROR("The width of the font image (%d) is not 128.\n", image->width); + + if (image->height % 16 != 0) + FATAL_ERROR("The height of the font image (%d) is not a multiple of 16.\n", image->height); + + int numRows = image->height / 16; + int bufferSize = numRows * 16 * 32; + unsigned char *buffer = malloc(bufferSize); + + if (buffer == NULL) + FATAL_ERROR("Failed to allocate memory for font.\n"); + + ConvertToHalfwidthJapaneseFont(image->pixels, buffer, numRows); + + WriteWholeFile(path, buffer, bufferSize); + + free(buffer); +} + +void ReadFullwidthJapaneseFont(char *path, struct Image *image) +{ + int fileSize; + unsigned char *buffer = ReadWholeFile(path, &fileSize); + + int numGlyphs = fileSize / 64; + + if (numGlyphs % 16 != 0) + FATAL_ERROR("The number of glyphs (%d) is not a multiple of 16.\n", numGlyphs); + + int numRows = numGlyphs / 16; + + image->width = 256; + image->height = numRows * 16; + image->bitDepth = 2; + image->pixels = malloc(fileSize); + + if (image->pixels == NULL) + FATAL_ERROR("Failed to allocate memory for font.\n"); + + ConvertFromFullwidthJapaneseFont(buffer, image->pixels, numRows); + + free(buffer); + + SetFontPalette(image); +} + +void WriteFullwidthJapaneseFont(char *path, struct Image *image) +{ + if (image->width != 256) + FATAL_ERROR("The width of the font image (%d) is not 256.\n", image->width); + + if (image->height % 16 != 0) + FATAL_ERROR("The height of the font image (%d) is not a multiple of 16.\n", image->height); + + int numRows = image->height / 16; + int bufferSize = numRows * 16 * 64; + unsigned char *buffer = malloc(bufferSize); + + if (buffer == NULL) + FATAL_ERROR("Failed to allocate memory for font.\n"); + + ConvertToFullwidthJapaneseFont(image->pixels, buffer, numRows); + + WriteWholeFile(path, buffer, bufferSize); + + free(buffer); +} diff --git a/tools/gbagfx/font.h b/tools/gbagfx/font.h new file mode 100644 index 0000000..45086d0 --- /dev/null +++ b/tools/gbagfx/font.h @@ -0,0 +1,16 @@ +// Copyright (c) 2015 YamaArashi + +#ifndef FONT_H +#define FONT_H + +#include <stdbool.h> +#include "gfx.h" + +void ReadLatinFont(char *path, struct Image *image); +void WriteLatinFont(char *path, struct Image *image); +void ReadHalfwidthJapaneseFont(char *path, struct Image *image); +void WriteHalfwidthJapaneseFont(char *path, struct Image *image); +void ReadFullwidthJapaneseFont(char *path, struct Image *image); +void WriteFullwidthJapaneseFont(char *path, struct Image *image); + +#endif // FONT_H diff --git a/tools/gbagfx/gfx.c b/tools/gbagfx/gfx.c new file mode 100644 index 0000000..f927dee --- /dev/null +++ b/tools/gbagfx/gfx.c @@ -0,0 +1,344 @@ +// Copyright (c) 2015 YamaArashi + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdbool.h> +#include "global.h" +#include "gfx.h" +#include "util.h" + +#define GET_GBA_PAL_RED(x) (((x) >> 0) & 0x1F) +#define GET_GBA_PAL_GREEN(x) (((x) >> 5) & 0x1F) +#define GET_GBA_PAL_BLUE(x) (((x) >> 10) & 0x1F) + +#define SET_GBA_PAL(r, g, b) (((b) << 10) | ((g) << 5) | (r)) + +#define UPCONVERT_BIT_DEPTH(x) (((x) * 255) / 31) + +#define DOWNCONVERT_BIT_DEPTH(x) ((x) / 8) + +static void AdvanceMetatilePosition(int *subTileX, int *subTileY, int *metatileX, int *metatileY, int metatilesWide, int metatileWidth, int metatileHeight) +{ + (*subTileX)++; + if (*subTileX == metatileWidth) { + *subTileX = 0; + (*subTileY)++; + if (*subTileY == metatileHeight) { + *subTileY = 0; + (*metatileX)++; + if (*metatileX == metatilesWide) { + *metatileX = 0; + (*metatileY)++; + } + } + } +} + +static void ConvertFromTiles1Bpp(unsigned char *src, unsigned char *dest, int numTiles, int metatilesWide, int metatileWidth, int metatileHeight, bool invertColors) +{ + int subTileX = 0; + int subTileY = 0; + int metatileX = 0; + int metatileY = 0; + int pitch = metatilesWide * metatileWidth; + + for (int i = 0; i < numTiles; i++) { + for (int j = 0; j < 8; j++) { + int destY = (metatileY * metatileHeight + subTileY) * 8 + j; + int destX = metatileX * metatileWidth + subTileX; + unsigned char srcPixelOctet = *src++; + unsigned char *destPixelOctet = &dest[destY * pitch + destX]; + + for (int k = 0; k < 8; k++) { + *destPixelOctet <<= 1; + *destPixelOctet |= (srcPixelOctet & 1) ^ invertColors; + srcPixelOctet >>= 1; + } + } + + AdvanceMetatilePosition(&subTileX, &subTileY, &metatileX, &metatileY, metatilesWide, metatileWidth, metatileHeight); + } +} + +static void ConvertFromTiles4Bpp(unsigned char *src, unsigned char *dest, int numTiles, int metatilesWide, int metatileWidth, int metatileHeight, bool invertColors) +{ + int subTileX = 0; + int subTileY = 0; + int metatileX = 0; + int metatileY = 0; + int pitch = (metatilesWide * metatileWidth) * 4; + + for (int i = 0; i < numTiles; i++) { + for (int j = 0; j < 8; j++) { + int destY = (metatileY * metatileHeight + subTileY) * 8 + j; + + for (int k = 0; k < 4; k++) { + int destX = (metatileX * metatileWidth + subTileX) * 4 + k; + unsigned char srcPixelPair = *src++; + unsigned char leftPixel = srcPixelPair & 0xF; + unsigned char rightPixel = srcPixelPair >> 4; + + if (invertColors) { + leftPixel = 15 - leftPixel; + rightPixel = 15 - rightPixel; + } + + dest[destY * pitch + destX] = (leftPixel << 4) | rightPixel; + } + } + + AdvanceMetatilePosition(&subTileX, &subTileY, &metatileX, &metatileY, metatilesWide, metatileWidth, metatileHeight); + } +} + +static void ConvertFromTiles8Bpp(unsigned char *src, unsigned char *dest, int numTiles, int metatilesWide, int metatileWidth, int metatileHeight, bool invertColors) +{ + int subTileX = 0; + int subTileY = 0; + int metatileX = 0; + int metatileY = 0; + int pitch = (metatilesWide * metatileWidth) * 8; + + for (int i = 0; i < numTiles; i++) { + for (int j = 0; j < 8; j++) { + int destY = (metatileY * metatileHeight + subTileY) * 8 + j; + + for (int k = 0; k < 8; k++) { + int destX = (metatileX * metatileWidth + subTileX) * 8 + k; + unsigned char srcPixel = *src++; + + if (invertColors) + srcPixel = 255 - srcPixel; + + dest[destY * pitch + destX] = srcPixel; + } + } + + AdvanceMetatilePosition(&subTileX, &subTileY, &metatileX, &metatileY, metatilesWide, metatileWidth, metatileHeight); + } +} + +static void ConvertToTiles1Bpp(unsigned char *src, unsigned char *dest, int numTiles, int metatilesWide, int metatileWidth, int metatileHeight, bool invertColors) +{ + int subTileX = 0; + int subTileY = 0; + int metatileX = 0; + int metatileY = 0; + int pitch = metatilesWide * metatileWidth; + + for (int i = 0; i < numTiles; i++) { + for (int j = 0; j < 8; j++) { + int srcY = (metatileY * metatileHeight + subTileY) * 8 + j; + int srcX = metatileX * metatileWidth + subTileX; + unsigned char srcPixelOctet = src[srcY * pitch + srcX]; + unsigned char *destPixelOctet = dest++; + + for (int k = 0; k < 8; k++) { + *destPixelOctet <<= 1; + *destPixelOctet |= (srcPixelOctet & 1) ^ invertColors; + srcPixelOctet >>= 1; + } + } + + AdvanceMetatilePosition(&subTileX, &subTileY, &metatileX, &metatileY, metatilesWide, metatileWidth, metatileHeight); + } +} + +static void ConvertToTiles4Bpp(unsigned char *src, unsigned char *dest, int numTiles, int metatilesWide, int metatileWidth, int metatileHeight, bool invertColors) +{ + int subTileX = 0; + int subTileY = 0; + int metatileX = 0; + int metatileY = 0; + int pitch = (metatilesWide * metatileWidth) * 4; + + for (int i = 0; i < numTiles; i++) { + for (int j = 0; j < 8; j++) { + int srcY = (metatileY * metatileHeight + subTileY) * 8 + j; + + for (int k = 0; k < 4; k++) { + int srcX = (metatileX * metatileWidth + subTileX) * 4 + k; + unsigned char srcPixelPair = src[srcY * pitch + srcX]; + unsigned char leftPixel = srcPixelPair >> 4; + unsigned char rightPixel = srcPixelPair & 0xF; + + if (invertColors) { + leftPixel = 15 - leftPixel; + rightPixel = 15 - rightPixel; + } + + *dest++ = (rightPixel << 4) | leftPixel; + } + } + + AdvanceMetatilePosition(&subTileX, &subTileY, &metatileX, &metatileY, metatilesWide, metatileWidth, metatileHeight); + } +} + +static void ConvertToTiles8Bpp(unsigned char *src, unsigned char *dest, int numTiles, int metatilesWide, int metatileWidth, int metatileHeight, bool invertColors) +{ + int subTileX = 0; + int subTileY = 0; + int metatileX = 0; + int metatileY = 0; + int pitch = (metatilesWide * metatileWidth) * 8; + + for (int i = 0; i < numTiles; i++) { + for (int j = 0; j < 8; j++) { + int srcY = (metatileY * metatileHeight + subTileY) * 8 + j; + + for (int k = 0; k < 8; k++) { + int srcX = (metatileX * metatileWidth + subTileX) * 8 + k; + unsigned char srcPixel = src[srcY * pitch + srcX]; + + if (invertColors) + srcPixel = 255 - srcPixel; + + *dest++ = srcPixel; + } + } + + AdvanceMetatilePosition(&subTileX, &subTileY, &metatileX, &metatileY, metatilesWide, metatileWidth, metatileHeight); + } +} + +void ReadImage(char *path, int tilesWidth, int bitDepth, int metatileWidth, int metatileHeight, struct Image *image, bool invertColors) +{ + int tileSize = bitDepth * 8; + + int fileSize; + unsigned char *buffer = ReadWholeFile(path, &fileSize); + + int numTiles = fileSize / tileSize; + + int tilesHeight = (numTiles + tilesWidth - 1) / tilesWidth; + + if (tilesWidth % metatileWidth != 0) + FATAL_ERROR("The width in tiles (%d) isn't a multiple of the specified metatile width (%d)", tilesWidth, metatileWidth); + + if (tilesHeight % metatileHeight != 0) + FATAL_ERROR("The height in tiles (%d) isn't a multiple of the specified metatile height (%d)", tilesHeight, metatileHeight); + + image->width = tilesWidth * 8; + image->height = tilesHeight * 8; + image->bitDepth = bitDepth; + image->pixels = calloc(tilesWidth * tilesHeight, tileSize); + + if (image->pixels == NULL) + FATAL_ERROR("Failed to allocate memory for pixels.\n"); + + int metatilesWide = tilesWidth / metatileWidth; + + switch (bitDepth) { + case 1: + ConvertFromTiles1Bpp(buffer, image->pixels, numTiles, metatilesWide, metatileWidth, metatileHeight, invertColors); + break; + case 4: + ConvertFromTiles4Bpp(buffer, image->pixels, numTiles, metatilesWide, metatileWidth, metatileHeight, invertColors); + break; + case 8: + ConvertFromTiles8Bpp(buffer, image->pixels, numTiles, metatilesWide, metatileWidth, metatileHeight, invertColors); + break; + } + + free(buffer); +} + +void WriteImage(char *path, int numTiles, int bitDepth, int metatileWidth, int metatileHeight, struct Image *image, bool invertColors) +{ + int tileSize = bitDepth * 8; + + if (image->width % 8 != 0) + FATAL_ERROR("The width in pixels (%d) isn't a multiple of 8.\n", image->width); + + if (image->height % 8 != 0) + FATAL_ERROR("The height in pixels (%d) isn't a multiple of 8.\n", image->height); + + int tilesWidth = image->width / 8; + int tilesHeight = image->height / 8; + + if (tilesWidth % metatileWidth != 0) + FATAL_ERROR("The width in tiles (%d) isn't a multiple of the specified metatile width (%d)", tilesWidth, metatileWidth); + + if (tilesHeight % metatileHeight != 0) + FATAL_ERROR("The height in tiles (%d) isn't a multiple of the specified metatile height (%d)", tilesHeight, metatileHeight); + + int maxNumTiles = tilesWidth * tilesHeight; + + if (numTiles == 0) + numTiles = maxNumTiles; + else if (numTiles > maxNumTiles) + FATAL_ERROR("The specified number of tiles (%d) is greater than the maximum possible value (%d).\n", numTiles, maxNumTiles); + + int bufferSize = numTiles * tileSize; + unsigned char *buffer = malloc(bufferSize); + + if (buffer == NULL) + FATAL_ERROR("Failed to allocate memory for pixels.\n"); + + int metatilesWide = tilesWidth / metatileWidth; + + switch (bitDepth) { + case 1: + ConvertToTiles1Bpp(image->pixels, buffer, numTiles, metatilesWide, metatileWidth, metatileHeight, invertColors); + break; + case 4: + ConvertToTiles4Bpp(image->pixels, buffer, numTiles, metatilesWide, metatileWidth, metatileHeight, invertColors); + break; + case 8: + ConvertToTiles8Bpp(image->pixels, buffer, numTiles, metatilesWide, metatileWidth, metatileHeight, invertColors); + break; + } + + WriteWholeFile(path, buffer, bufferSize); + + free(buffer); +} + +void FreeImage(struct Image *image) +{ + free(image->pixels); + image->pixels = NULL; +} + +void ReadGbaPalette(char *path, struct Palette *palette) +{ + int fileSize; + unsigned char *data = ReadWholeFile(path, &fileSize); + + if (fileSize % 2 != 0) + FATAL_ERROR("The file size (%d) is not a multiple of 2.\n", fileSize); + + palette->numColors = fileSize / 2; + + for (int i = 0; i < palette->numColors; i++) { + uint16_t paletteEntry = (data[i * 2 + 1] << 8) | data[i * 2]; + palette->colors[i].red = UPCONVERT_BIT_DEPTH(GET_GBA_PAL_RED(paletteEntry)); + palette->colors[i].green = UPCONVERT_BIT_DEPTH(GET_GBA_PAL_GREEN(paletteEntry)); + palette->colors[i].blue = UPCONVERT_BIT_DEPTH(GET_GBA_PAL_BLUE(paletteEntry)); + } + + free(data); +} + +void WriteGbaPalette(char *path, struct Palette *palette) +{ + FILE *fp = fopen(path, "wb"); + + if (fp == NULL) + FATAL_ERROR("Failed to open \"%s\" for writing.\n", path); + + for (int i = 0; i < palette->numColors; i++) { + unsigned char red = DOWNCONVERT_BIT_DEPTH(palette->colors[i].red); + unsigned char green = DOWNCONVERT_BIT_DEPTH(palette->colors[i].green); + unsigned char blue = DOWNCONVERT_BIT_DEPTH(palette->colors[i].blue); + + uint16_t paletteEntry = SET_GBA_PAL(red, green, blue); + + fputc(paletteEntry & 0xFF, fp); + fputc(paletteEntry >> 8, fp); + } + + fclose(fp); +} diff --git a/tools/gbagfx/gfx.h b/tools/gbagfx/gfx.h new file mode 100644 index 0000000..5355ced --- /dev/null +++ b/tools/gbagfx/gfx.h @@ -0,0 +1,36 @@ +// Copyright (c) 2015 YamaArashi + +#ifndef GFX_H +#define GFX_H + +#include <stdint.h> +#include <stdbool.h> + +struct Color { + unsigned char red; + unsigned char green; + unsigned char blue; +}; + +struct Palette { + struct Color colors[256]; + int numColors; +}; + +struct Image { + int width; + int height; + int bitDepth; + unsigned char *pixels; + bool hasPalette; + struct Palette palette; + bool hasTransparency; +}; + +void ReadImage(char *path, int tilesWidth, int bitDepth, int metatileWidth, int metatileHeight, struct Image *image, bool invertColors); +void WriteImage(char *path, int numTiles, int bitDepth, int metatileWidth, int metatileHeight, struct Image *image, bool invertColors); +void FreeImage(struct Image *image); +void ReadGbaPalette(char *path, struct Palette *palette); +void WriteGbaPalette(char *path, struct Palette *palette); + +#endif // GFX_H diff --git a/tools/gbagfx/global.h b/tools/gbagfx/global.h new file mode 100644 index 0000000..65dd351 --- /dev/null +++ b/tools/gbagfx/global.h @@ -0,0 +1,31 @@ +// Copyright (c) 2015 YamaArashi + +#ifndef GLOBAL_H +#define GLOBAL_H + +#include <stdio.h> +#include <stdlib.h> + +#ifdef _MSC_VER + +#define FATAL_ERROR(format, ...) \ +do { \ + fprintf(stderr, format, __VA_ARGS__); \ + exit(1); \ +} while (0) + +#define UNUSED + +#else + +#define FATAL_ERROR(format, ...) \ +do { \ + fprintf(stderr, format, ##__VA_ARGS__); \ + exit(1); \ +} while (0) + +#define UNUSED __attribute__((__unused__)) + +#endif // _MSC_VER + +#endif // GLOBAL_H diff --git a/tools/gbagfx/jasc_pal.c b/tools/gbagfx/jasc_pal.c new file mode 100644 index 0000000..e5ba9c3 --- /dev/null +++ b/tools/gbagfx/jasc_pal.c @@ -0,0 +1,172 @@ +// Copyright (c) 2015 YamaArashi + +#include <stdio.h> +#include <string.h> +#include "global.h" +#include "gfx.h" +#include "util.h" + +// Read/write Paint Shop Pro palette files. + +// Format of a Paint Shop Pro palette file, line by line: +// "JASC-PAL\r\n" (signature) +// "0100\r\n" (version; seems to always be "0100") +// "<NUMBER_OF_COLORS>\r\n" (number of colors in decimal) +// +// <NUMBER_OF_COLORS> times: +// "<RED> <GREEN> <BLUE>\r\n" (color entry) +// +// Each color component is a decimal number from 0 to 255. +// Examples: +// Black - "0 0 0\r\n" +// Blue - "0 0 255\r\n" +// Brown - "150 75 0\r\n" + +#define MAX_LINE_LENGTH 11 + +void ReadJascPaletteLine(FILE *fp, char *line) +{ + int c; + int length = 0; + + for (;;) + { + c = fgetc(fp); + + if (c == '\r') + { + c = fgetc(fp); + + if (c != '\n') + FATAL_ERROR("CR line endings aren't supported.\n"); + + line[length] = 0; + + return; + } + + if (c == '\n') + FATAL_ERROR("LF line endings aren't supported.\n"); + + if (c == EOF) + FATAL_ERROR("Unexpected EOF. No CRLF at end of file.\n"); + + if (c == 0) + FATAL_ERROR("NUL character in file.\n"); + + if (length == MAX_LINE_LENGTH) + { + line[length] = 0; + FATAL_ERROR("The line \"%s\" is too long.\n", line); + } + + line[length++] = c; + } +} + +void ReadJascPalette(char *path, struct Palette *palette) +{ + char line[MAX_LINE_LENGTH + 1]; + + FILE *fp = fopen(path, "rb"); + + if (fp == NULL) + FATAL_ERROR("Failed to open JASC-PAL file \"%s\" for reading.\n", path); + + ReadJascPaletteLine(fp, line); + + if (strcmp(line, "JASC-PAL") != 0) + FATAL_ERROR("Invalid JASC-PAL signature.\n"); + + ReadJascPaletteLine(fp, line); + + if (strcmp(line, "0100") != 0) + FATAL_ERROR("Unsuported JASC-PAL version.\n"); + + ReadJascPaletteLine(fp, line); + + if (!ParseNumber(line, NULL, 10, &palette->numColors)) + FATAL_ERROR("Failed to parse number of colors.\n"); + + if (palette->numColors < 1 || palette->numColors > 256) + FATAL_ERROR("%d is an invalid number of colors. The number of colors must be in the range [1, 256].\n", palette->numColors); + + for (int i = 0; i < palette->numColors; i++) + { + ReadJascPaletteLine(fp, line); + + char *s = line; + char *end; + + int red; + int green; + int blue; + + if (!ParseNumber(s, &end, 10, &red)) + FATAL_ERROR("Failed to parse red color component.\n"); + + s = end; + + if (*s != ' ') + FATAL_ERROR("Expected a space after red color component.\n"); + + s++; + + if (*s < '0' || *s > '9') + FATAL_ERROR("Expected only a space between red and green color components.\n"); + + if (!ParseNumber(s, &end, 10, &green)) + FATAL_ERROR("Failed to parse green color component.\n"); + + s = end; + + if (*s != ' ') + FATAL_ERROR("Expected a space after green color component.\n"); + + s++; + + if (*s < '0' || *s > '9') + FATAL_ERROR("Expected only a space between green and blue color components.\n"); + + if (!ParseNumber(s, &end, 10, &blue)) + FATAL_ERROR("Failed to parse blue color component.\n"); + + if (*end != 0) + FATAL_ERROR("Garbage after blue color component.\n"); + + if (red < 0 || red > 255) + FATAL_ERROR("Red color component (%d) is outside the range [0, 255].\n", red); + + if (green < 0 || green > 255) + FATAL_ERROR("Green color component (%d) is outside the range [0, 255].\n", green); + + if (blue < 0 || blue > 255) + FATAL_ERROR("Blue color component (%d) is outside the range [0, 255].\n", blue); + + palette->colors[i].red = red; + palette->colors[i].green = green; + palette->colors[i].blue = blue; + } + + if (fgetc(fp) != EOF) + FATAL_ERROR("Garbage after color data.\n"); + + fclose(fp); +} + +void WriteJascPalette(char *path, struct Palette *palette) +{ + FILE *fp = fopen(path, "wb"); + + fputs("JASC-PAL\r\n", fp); + fputs("0100\r\n", fp); + fprintf(fp, "%d\r\n", palette->numColors); + + for (int i = 0; i < palette->numColors; i++) + { + struct Color *color = &palette->colors[i]; + fprintf(fp, "%d %d %d\r\n", color->red, color->green, color->blue); + } + + fclose(fp); +} diff --git a/tools/gbagfx/jasc_pal.h b/tools/gbagfx/jasc_pal.h new file mode 100644 index 0000000..b60b31f --- /dev/null +++ b/tools/gbagfx/jasc_pal.h @@ -0,0 +1,9 @@ +// Copyright (c) 2015 YamaArashi + +#ifndef JASC_PAL_H +#define JASC_PAL_H + +void ReadJascPalette(char *path, struct Palette *palette); +void WriteJascPalette(char *path, struct Palette *palette); + +#endif // JASC_PAL_H diff --git a/tools/gbagfx/lz.c b/tools/gbagfx/lz.c new file mode 100644 index 0000000..c2ba3e3 --- /dev/null +++ b/tools/gbagfx/lz.c @@ -0,0 +1,155 @@ +// Copyright (c) 2015 YamaArashi + +#include <stdlib.h> +#include <stdbool.h> +#include "global.h" +#include "lz.h" + +unsigned char *LZDecompress(unsigned char *src, int srcSize, int *uncompressedSize) +{ + if (srcSize < 4) + goto fail; + + int destSize = (src[3] << 16) | (src[2] << 8) | src[1]; + + unsigned char *dest = malloc(destSize); + + if (dest == NULL) + goto fail; + + int srcPos = 4; + int destPos = 0; + + for (;;) { + if (srcPos >= srcSize) + goto fail; + + unsigned char flags = src[srcPos++]; + + for (int i = 0; i < 8; i++) { + if (flags & 0x80) { + if (srcPos + 1 >= srcSize) + goto fail; + + int blockSize = (src[srcPos] >> 4) + 3; + int blockDistance = (((src[srcPos] & 0xF) << 8) | src[srcPos + 1]) + 1; + + srcPos += 2; + + int blockPos = destPos - blockDistance; + + // Some Ruby/Sapphire tilesets overflow. + if (destPos + blockSize > destSize) { + blockSize = destSize - destPos; + fprintf(stderr, "Destination buffer overflow.\n"); + } + + if (blockPos < 0) + goto fail; + + for (int j = 0; j < blockSize; j++) + dest[destPos++] = dest[blockPos + j]; + } else { + if (srcPos >= srcSize || destPos >= destSize) + goto fail; + + dest[destPos++] = src[srcPos++]; + } + + if (destPos == destSize) { + *uncompressedSize = destSize; + return dest; + } + + flags <<= 1; + } + } + +fail: + FATAL_ERROR("Fatal error while decompressing LZ file.\n"); +} + +unsigned char *LZCompress(unsigned char *src, int srcSize, int *compressedSize) +{ + const int minDistance = 2; // for compatibility with LZ77UnCompVram() + + if (srcSize <= 0) + goto fail; + + int worstCaseDestSize = 4 + srcSize + ((srcSize + 7) / 8); + + // Round up to the next multiple of four. + worstCaseDestSize = (worstCaseDestSize + 3) & ~3; + + unsigned char *dest = malloc(worstCaseDestSize); + + if (dest == NULL) + goto fail; + + // header + dest[0] = 0x10; // LZ compression type + dest[1] = (unsigned char)srcSize; + dest[2] = (unsigned char)(srcSize >> 8); + dest[3] = (unsigned char)(srcSize >> 16); + + int srcPos = 0; + int destPos = 4; + + for (;;) { + unsigned char *flags = &dest[destPos++]; + *flags = 0; + + for (int i = 0; i < 8; i++) { + int bestBlockDistance = 0; + int bestBlockSize = 0; + int blockDistance = minDistance; + + while (blockDistance <= srcPos && blockDistance <= 0x1000) { + int blockStart = srcPos - blockDistance; + int blockSize = 0; + + while (blockSize < 18 + && srcPos + blockSize < srcSize + && src[blockStart + blockSize] == src[srcPos + blockSize]) + blockSize++; + + if (blockSize > bestBlockSize) { + bestBlockDistance = blockDistance; + bestBlockSize = blockSize; + + if (blockSize == 18) + break; + } + + blockDistance++; + } + + if (bestBlockSize >= 3) { + *flags |= (0x80 >> i); + srcPos += bestBlockSize; + bestBlockSize -= 3; + bestBlockDistance--; + dest[destPos++] = (bestBlockSize << 4) | ((unsigned int)bestBlockDistance >> 8); + dest[destPos++] = (unsigned char)bestBlockDistance; + } else { + dest[destPos++] = src[srcPos++]; + } + + if (srcPos == srcSize) { + // Pad to multiple of 4 bytes. + int remainder = destPos % 4; + + if (remainder != 0) { + for (int i = 0; i < 4 - remainder; i++) + dest[destPos++] = 0; + } + + *compressedSize = destPos; + return dest; + } + } + } + +fail: + FATAL_ERROR("Fatal error while compressing LZ file.\n"); +} diff --git a/tools/gbagfx/lz.h b/tools/gbagfx/lz.h new file mode 100644 index 0000000..164d622 --- /dev/null +++ b/tools/gbagfx/lz.h @@ -0,0 +1,9 @@ +// Copyright (c) 2015 YamaArashi + +#ifndef LZ_H +#define LZ_H + +unsigned char *LZDecompress(unsigned char *src, int srcSize, int *uncompressedSize); +unsigned char *LZCompress(unsigned char *src, int srcSize, int *compressedSize); + +#endif // LZ_H diff --git a/tools/gbagfx/main.c b/tools/gbagfx/main.c new file mode 100644 index 0000000..86b0afa --- /dev/null +++ b/tools/gbagfx/main.c @@ -0,0 +1,465 @@ +// Copyright (c) 2015 YamaArashi + +#include <stdio.h> +#include <string.h> +#include <stdbool.h> +#include "global.h" +#include "util.h" +#include "options.h" +#include "gfx.h" +#include "convert_png.h" +#include "jasc_pal.h" +#include "lz.h" +#include "rl.h" +#include "font.h" + +struct CommandHandler +{ + const char *inputFileExtension; + const char *outputFileExtension; + void(*function)(char *inputPath, char *outputPath, int argc, char **argv); +}; + +void ConvertGbaToPng(char *inputPath, char *outputPath, struct GbaToPngOptions *options) +{ + struct Image image; + + if (options->paletteFilePath != NULL) + { + ReadGbaPalette(options->paletteFilePath, &image.palette); + image.hasPalette = true; + } + else + { + image.hasPalette = false; + } + + ReadImage(inputPath, options->width, options->bitDepth, options->metatileWidth, options->metatileHeight, &image, !image.hasPalette); + + image.hasTransparency = options->hasTransparency; + + WritePng(outputPath, &image); + + FreeImage(&image); +} + +void ConvertPngToGba(char *inputPath, char *outputPath, struct PngToGbaOptions *options) +{ + struct Image image; + + image.bitDepth = options->bitDepth; + + ReadPng(inputPath, &image); + + WriteImage(outputPath, options->numTiles, options->bitDepth, options->metatileWidth, options->metatileHeight, &image, !image.hasPalette); + + FreeImage(&image); +} + +void HandleGbaToPngCommand(char *inputPath, char *outputPath, int argc, char **argv) +{ + char *inputFileExtension = GetFileExtension(inputPath); + struct GbaToPngOptions options; + options.paletteFilePath = NULL; + options.bitDepth = inputFileExtension[0] - '0'; + options.hasTransparency = false; + options.width = 1; + options.metatileWidth = 1; + options.metatileHeight = 1; + + for (int i = 3; i < argc; i++) + { + char *option = argv[i]; + + if (strcmp(option, "-palette") == 0) + { + if (i + 1 >= argc) + FATAL_ERROR("No palette file path following \"-palette\".\n"); + + i++; + + options.paletteFilePath = argv[i]; + } + else if (strcmp(option, "-object") == 0) + { + options.hasTransparency = true; + } + else if (strcmp(option, "-width") == 0) + { + if (i + 1 >= argc) + FATAL_ERROR("No width following \"-width\".\n"); + + i++; + + if (!ParseNumber(argv[i], NULL, 10, &options.width)) + FATAL_ERROR("Failed to parse width.\n"); + + if (options.width < 1) + FATAL_ERROR("Width must be positive.\n"); + } + else if (strcmp(option, "-mwidth") == 0) + { + if (i + 1 >= argc) + FATAL_ERROR("No metatile width value following \"-mwidth\".\n"); + + i++; + + if (!ParseNumber(argv[i], NULL, 10, &options.metatileWidth)) + FATAL_ERROR("Failed to parse metatile width.\n"); + + if (options.metatileWidth < 1) + FATAL_ERROR("metatile width must be positive.\n"); + } + else if (strcmp(option, "-mheight") == 0) + { + if (i + 1 >= argc) + FATAL_ERROR("No metatile height value following \"-mheight\".\n"); + + i++; + + if (!ParseNumber(argv[i], NULL, 10, &options.metatileHeight)) + FATAL_ERROR("Failed to parse metatile height.\n"); + + if (options.metatileHeight < 1) + FATAL_ERROR("metatile height must be positive.\n"); + } + else + { + FATAL_ERROR("Unrecognized option \"%s\".\n", option); + } + } + + if (options.metatileWidth > options.width) + options.width = options.metatileWidth; + + ConvertGbaToPng(inputPath, outputPath, &options); +} + +void HandlePngToGbaCommand(char *inputPath, char *outputPath, int argc, char **argv) +{ + char *outputFileExtension = GetFileExtension(outputPath); + int bitDepth = outputFileExtension[0] - '0'; + struct PngToGbaOptions options; + options.numTiles = 0; + options.bitDepth = bitDepth; + options.metatileWidth = 1; + options.metatileHeight = 1; + + for (int i = 3; i < argc; i++) + { + char *option = argv[i]; + + if (strcmp(option, "-num_tiles") == 0) + { + if (i + 1 >= argc) + FATAL_ERROR("No number of tiles following \"-num_tiles\".\n"); + + i++; + + if (!ParseNumber(argv[i], NULL, 10, &options.numTiles)) + FATAL_ERROR("Failed to parse number of tiles.\n"); + + if (options.numTiles < 1) + FATAL_ERROR("Number of tiles must be positive.\n"); + } + else if (strcmp(option, "-mwidth") == 0) + { + if (i + 1 >= argc) + FATAL_ERROR("No metatile width value following \"-mwidth\".\n"); + + i++; + + if (!ParseNumber(argv[i], NULL, 10, &options.metatileWidth)) + FATAL_ERROR("Failed to parse metatile width.\n"); + + if (options.metatileWidth < 1) + FATAL_ERROR("metatile width must be positive.\n"); + } + else if (strcmp(option, "-mheight") == 0) + { + if (i + 1 >= argc) + FATAL_ERROR("No metatile height value following \"-mheight\".\n"); + + i++; + + if (!ParseNumber(argv[i], NULL, 10, &options.metatileHeight)) + FATAL_ERROR("Failed to parse metatile height.\n"); + + if (options.metatileHeight < 1) + FATAL_ERROR("metatile height must be positive.\n"); + } + else + { + FATAL_ERROR("Unrecognized option \"%s\".\n", option); + } + } + + ConvertPngToGba(inputPath, outputPath, &options); +} + +void HandlePngToGbaPaletteCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED) +{ + struct Palette palette; + + ReadPngPalette(inputPath, &palette); + WriteGbaPalette(outputPath, &palette); +} + +void HandleGbaToJascPaletteCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED) +{ + struct Palette palette; + + ReadGbaPalette(inputPath, &palette); + WriteJascPalette(outputPath, &palette); +} + +void HandleJascToGbaPaletteCommand(char *inputPath, char *outputPath, int argc, char **argv) +{ + int numColors = 0; + + for (int i = 3; i < argc; i++) + { + char *option = argv[i]; + + if (strcmp(option, "-num_colors") == 0) + { + if (i + 1 >= argc) + FATAL_ERROR("No number of colors following \"-num_colors\".\n"); + + i++; + + if (!ParseNumber(argv[i], NULL, 10, &numColors)) + FATAL_ERROR("Failed to parse number of colors.\n"); + + if (numColors < 1) + FATAL_ERROR("Number of colors must be positive.\n"); + } + else + { + FATAL_ERROR("Unrecognized option \"%s\".\n", option); + } + } + + struct Palette palette; + + ReadJascPalette(inputPath, &palette); + + if (numColors != 0) + palette.numColors = numColors; + + WriteGbaPalette(outputPath, &palette); +} + +void HandleLatinFontToPngCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED) +{ + struct Image image; + + ReadLatinFont(inputPath, &image); + WritePng(outputPath, &image); + + FreeImage(&image); +} + +void HandlePngToLatinFontCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED) +{ + struct Image image; + + image.bitDepth = 2; + + ReadPng(inputPath, &image); + WriteLatinFont(outputPath, &image); + + FreeImage(&image); +} + +void HandleHalfwidthJapaneseFontToPngCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED) +{ + struct Image image; + + ReadHalfwidthJapaneseFont(inputPath, &image); + WritePng(outputPath, &image); + + FreeImage(&image); +} + +void HandlePngToHalfwidthJapaneseFontCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED) +{ + struct Image image; + + image.bitDepth = 2; + + ReadPng(inputPath, &image); + WriteHalfwidthJapaneseFont(outputPath, &image); + + FreeImage(&image); +} + +void HandleFullwidthJapaneseFontToPngCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED) +{ + struct Image image; + + ReadFullwidthJapaneseFont(inputPath, &image); + WritePng(outputPath, &image); + + FreeImage(&image); +} + +void HandlePngToFullwidthJapaneseFontCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED) +{ + struct Image image; + + image.bitDepth = 2; + + ReadPng(inputPath, &image); + WriteFullwidthJapaneseFont(outputPath, &image); + + FreeImage(&image); +} + +void HandleLZCompressCommand(char *inputPath, char *outputPath, int argc, char **argv) +{ + int overflowSize = 0; + + for (int i = 3; i < argc; i++) + { + char *option = argv[i]; + + if (strcmp(option, "-overflow") == 0) + { + if (i + 1 >= argc) + FATAL_ERROR("No size following \"-overflow\".\n"); + + i++; + + if (!ParseNumber(argv[i], NULL, 10, &overflowSize)) + FATAL_ERROR("Failed to parse overflow size.\n"); + + if (overflowSize < 1) + FATAL_ERROR("Overflow size must be positive.\n"); + } + else + { + FATAL_ERROR("Unrecognized option \"%s\".\n", option); + } + } + + // The overflow option allows a quirk in some of Ruby/Sapphire's tilesets + // to be reproduced. It works by appending a number of zeros to the data + // before compressing it and then amending the LZ header's size field to + // reflect the expected size. This will cause an overflow when decompressing + // the data. + + int fileSize; + unsigned char *buffer = ReadWholeFileZeroPadded(inputPath, &fileSize, overflowSize); + + int compressedSize; + unsigned char *compressedData = LZCompress(buffer, fileSize + overflowSize, &compressedSize); + + compressedData[1] = (unsigned char)fileSize; + compressedData[2] = (unsigned char)(fileSize >> 8); + compressedData[3] = (unsigned char)(fileSize >> 16); + + free(buffer); + + WriteWholeFile(outputPath, compressedData, compressedSize); + + free(compressedData); +} + +void HandleLZDecompressCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED) +{ + int fileSize; + unsigned char *buffer = ReadWholeFile(inputPath, &fileSize); + + int uncompressedSize; + unsigned char *uncompressedData = LZDecompress(buffer, fileSize, &uncompressedSize); + + free(buffer); + + WriteWholeFile(outputPath, uncompressedData, uncompressedSize); + + free(uncompressedData); +} + +void HandleRLCompressCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED) +{ + int fileSize; + unsigned char *buffer = ReadWholeFile(inputPath, &fileSize); + + int compressedSize; + unsigned char *compressedData = RLCompress(buffer, fileSize, &compressedSize); + + free(buffer); + + WriteWholeFile(outputPath, compressedData, compressedSize); + + free(compressedData); +} + +void HandleRLDecompressCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED) +{ + int fileSize; + unsigned char *buffer = ReadWholeFile(inputPath, &fileSize); + + int uncompressedSize; + unsigned char *uncompressedData = RLDecompress(buffer, fileSize, &uncompressedSize); + + free(buffer); + + WriteWholeFile(outputPath, uncompressedData, uncompressedSize); + + free(uncompressedData); +} + +int main(int argc, char **argv) +{ + if (argc < 3) + FATAL_ERROR("Usage: gbagfx INPUT_PATH OUTPUT_PATH [options...]\n"); + + struct CommandHandler handlers[] = + { + { "1bpp", "png", HandleGbaToPngCommand }, + { "4bpp", "png", HandleGbaToPngCommand }, + { "8bpp", "png", HandleGbaToPngCommand }, + { "png", "1bpp", HandlePngToGbaCommand }, + { "png", "4bpp", HandlePngToGbaCommand }, + { "png", "8bpp", HandlePngToGbaCommand }, + { "png", "gbapal", HandlePngToGbaPaletteCommand }, + { "gbapal", "pal", HandleGbaToJascPaletteCommand }, + { "pal", "gbapal", HandleJascToGbaPaletteCommand }, + { "latfont", "png", HandleLatinFontToPngCommand }, + { "png", "latfont", HandlePngToLatinFontCommand }, + { "hwjpnfont", "png", HandleHalfwidthJapaneseFontToPngCommand }, + { "png", "hwjpnfont", HandlePngToHalfwidthJapaneseFontCommand }, + { "fwjpnfont", "png", HandleFullwidthJapaneseFontToPngCommand }, + { "png", "fwjpnfont", HandlePngToFullwidthJapaneseFontCommand }, + { NULL, "lz", HandleLZCompressCommand }, + { "lz", NULL, HandleLZDecompressCommand }, + { NULL, "rl", HandleRLCompressCommand }, + { "rl", NULL, HandleRLDecompressCommand }, + { NULL, NULL, NULL } + }; + + char *inputPath = argv[1]; + char *outputPath = argv[2]; + char *inputFileExtension = GetFileExtension(inputPath); + char *outputFileExtension = GetFileExtension(outputPath); + + if (inputFileExtension == NULL) + FATAL_ERROR("Input file \"%s\" has no extension.\n", inputPath); + + if (outputFileExtension == NULL) + FATAL_ERROR("Output file \"%s\" has no extension.\n", outputPath); + + for (int i = 0; handlers[i].function != NULL; i++) + { + if ((handlers[i].inputFileExtension == NULL || strcmp(handlers[i].inputFileExtension, inputFileExtension) == 0) + && (handlers[i].outputFileExtension == NULL || strcmp(handlers[i].outputFileExtension, outputFileExtension) == 0)) + { + handlers[i].function(inputPath, outputPath, argc, argv); + return 0; + } + } + + FATAL_ERROR("Don't know how to convert \"%s\" to \"%s\".\n", inputPath, outputPath); +} diff --git a/tools/gbagfx/options.h b/tools/gbagfx/options.h new file mode 100755 index 0000000..2ff3967 --- /dev/null +++ b/tools/gbagfx/options.h @@ -0,0 +1,24 @@ +// Copyright (c) 2018 huderlem + +#ifndef OPTIONS_H +#define OPTIONS_H + +#include <stdbool.h> + +struct GbaToPngOptions { + char *paletteFilePath; + int bitDepth; + bool hasTransparency; + int width; + int metatileWidth; + int metatileHeight; +}; + +struct PngToGbaOptions { + int numTiles; + int bitDepth; + int metatileWidth; + int metatileHeight; +}; + +#endif // OPTIONS_H diff --git a/tools/gbagfx/rl.c b/tools/gbagfx/rl.c new file mode 100644 index 0000000..968c934 --- /dev/null +++ b/tools/gbagfx/rl.c @@ -0,0 +1,149 @@ +// Copyright (c) 2016 YamaArashi + +#include <stdlib.h> +#include <stdbool.h> +#include "global.h" +#include "rl.h" + +unsigned char *RLDecompress(unsigned char *src, int srcSize, int *uncompressedSize) +{ + if (srcSize < 4) + goto fail; + + int destSize = (src[3] << 16) | (src[2] << 8) | src[1]; + + unsigned char *dest = malloc(destSize); + + if (dest == NULL) + goto fail; + + int srcPos = 4; + int destPos = 0; + + for (;;) + { + if (srcPos >= srcSize) + goto fail; + + unsigned char flags = src[srcPos++]; + bool compressed = ((flags & 0x80) != 0); + + if (compressed) + { + int length = (flags & 0x7F) + 3; + unsigned char data = src[srcPos++]; + + if (destPos + length > destSize) + goto fail; + + for (int i = 0; i < length; i++) + dest[destPos++] = data; + } + else + { + int length = (flags & 0x7F) + 1; + + if (destPos + length > destSize) + goto fail; + + for (int i = 0; i < length; i++) + dest[destPos++] = src[srcPos++]; + } + + if (destPos == destSize) + { + *uncompressedSize = destSize; + return dest; + } + } + +fail: + FATAL_ERROR("Fatal error while decompressing RL file.\n"); +} + +unsigned char *RLCompress(unsigned char *src, int srcSize, int *compressedSize) +{ + if (srcSize <= 0) + goto fail; + + int worstCaseDestSize = 4 + srcSize * 2; + + // Round up to the next multiple of four. + worstCaseDestSize = (worstCaseDestSize + 3) & ~3; + + unsigned char *dest = malloc(worstCaseDestSize); + + if (dest == NULL) + goto fail; + + // header + dest[0] = 0x30; // RL compression type + dest[1] = (unsigned char)srcSize; + dest[2] = (unsigned char)(srcSize >> 8); + dest[3] = (unsigned char)(srcSize >> 16); + + int srcPos = 0; + int destPos = 4; + + for (;;) + { + bool compress = false; + int uncompressedStart = srcPos; + int uncompressedLength = 0; + + while (srcPos < srcSize && uncompressedLength < (0x7F + 1)) + { + compress = (srcPos + 2 < srcSize && src[srcPos] == src[srcPos + 1] && src[srcPos] == src[srcPos + 2]); + + if (compress) + break; + + srcPos++; + uncompressedLength++; + } + + if (uncompressedLength > 0) + { + dest[destPos++] = uncompressedLength - 1; + + for (int i = 0; i < uncompressedLength; i++) + dest[destPos++] = src[uncompressedStart + i]; + } + + if (compress) + { + unsigned char data = src[srcPos]; + int compressedLength = 0; + + while (compressedLength < (0x7F + 3) + && srcPos + compressedLength < srcSize + && src[srcPos + compressedLength] == data) + { + compressedLength++; + } + + dest[destPos++] = 0x80 | (compressedLength - 3); + dest[destPos++] = data; + + srcPos += compressedLength; + } + + if (srcPos == srcSize) + { + // Pad to multiple of 4 bytes. + int remainder = destPos % 4; + + if (remainder != 0) + { + for (int i = 0; i < 4 - remainder; i++) + dest[destPos++] = 0; + } + + *compressedSize = destPos; + return dest; + } + } + +fail: + FATAL_ERROR("Fatal error while compressing RL file.\n"); +} diff --git a/tools/gbagfx/rl.h b/tools/gbagfx/rl.h new file mode 100644 index 0000000..02ad8d6 --- /dev/null +++ b/tools/gbagfx/rl.h @@ -0,0 +1,9 @@ +// Copyright (c) 2016 YamaArashi + +#ifndef RL_H +#define RL_H + +unsigned char *RLDecompress(unsigned char *src, int srcSize, int *uncompressedSize); +unsigned char *RLCompress(unsigned char *src, int srcSize, int *compressedSize); + +#endif // RL_H diff --git a/tools/gbagfx/util.c b/tools/gbagfx/util.c new file mode 100644 index 0000000..87abeb3 --- /dev/null +++ b/tools/gbagfx/util.c @@ -0,0 +1,124 @@ +// Copyright (c) 2015 YamaArashi + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> +#include <errno.h> +#include <limits.h> +#include "global.h" +#include "util.h" + +bool ParseNumber(char *s, char **end, int radix, int *intValue) +{ + char *localEnd; + + if (end == NULL) + end = &localEnd; + + errno = 0; + + const long longValue = strtol(s, end, radix); + + if (*end == s) + return false; // not a number + + if ((longValue == LONG_MIN || longValue == LONG_MAX) && errno == ERANGE) + return false; + + if (longValue > INT_MAX) + return false; + + if (longValue < INT_MIN) + return false; + + *intValue = (int)longValue; + + return true; +} + +char *GetFileExtension(char *path) +{ + char *extension = path; + + while (*extension != 0) + extension++; + + while (extension > path && *extension != '.') + extension--; + + if (extension == path) + return NULL; + + extension++; + + if (*extension == 0) + return NULL; + + return extension; +} + +unsigned char *ReadWholeFile(char *path, int *size) +{ + FILE *fp = fopen(path, "rb"); + + if (fp == NULL) + FATAL_ERROR("Failed to open \"%s\" for reading.\n", path); + + fseek(fp, 0, SEEK_END); + + *size = ftell(fp); + + unsigned char *buffer = malloc(*size); + + if (buffer == NULL) + FATAL_ERROR("Failed to allocate memory for reading \"%s\".\n", path); + + rewind(fp); + + if (fread(buffer, *size, 1, fp) != 1) + FATAL_ERROR("Failed to read \"%s\".\n", path); + + fclose(fp); + + return buffer; +} + +unsigned char *ReadWholeFileZeroPadded(char *path, int *size, int padAmount) +{ + FILE *fp = fopen(path, "rb"); + + if (fp == NULL) + FATAL_ERROR("Failed to open \"%s\" for reading.\n", path); + + fseek(fp, 0, SEEK_END); + + *size = ftell(fp); + + unsigned char *buffer = calloc(*size + padAmount, 1); + + if (buffer == NULL) + FATAL_ERROR("Failed to allocate memory for reading \"%s\".\n", path); + + rewind(fp); + + if (fread(buffer, *size, 1, fp) != 1) + FATAL_ERROR("Failed to read \"%s\".\n", path); + + fclose(fp); + + return buffer; +} + +void WriteWholeFile(char *path, void *buffer, int bufferSize) +{ + FILE *fp = fopen(path, "wb"); + + if (fp == NULL) + FATAL_ERROR("Failed to open \"%s\" for writing.\n", path); + + if (fwrite(buffer, bufferSize, 1, fp) != 1) + FATAL_ERROR("Failed to write to \"%s\".\n", path); + + fclose(fp); +} diff --git a/tools/gbagfx/util.h b/tools/gbagfx/util.h new file mode 100644 index 0000000..6d7a9c2 --- /dev/null +++ b/tools/gbagfx/util.h @@ -0,0 +1,14 @@ +// Copyright (c) 2015 YamaArashi + +#ifndef UTIL_H +#define UTIL_H + +#include <stdbool.h> + +bool ParseNumber(char *s, char **end, int radix, int *intValue); +char *GetFileExtension(char *path); +unsigned char *ReadWholeFile(char *path, int *size); +unsigned char *ReadWholeFileZeroPadded(char *path, int *size, int padAmount); +void WriteWholeFile(char *path, void *buffer, int bufferSize); + +#endif // UTIL_H diff --git a/tools/mapjson/.gitignore b/tools/mapjson/.gitignore new file mode 100755 index 0000000..a5d5684 --- /dev/null +++ b/tools/mapjson/.gitignore @@ -0,0 +1 @@ +mapjson diff --git a/tools/mapjson/Makefile b/tools/mapjson/Makefile new file mode 100755 index 0000000..9a49be5 --- /dev/null +++ b/tools/mapjson/Makefile @@ -0,0 +1,18 @@ +CXX := g++ + +CXXFLAGS := -Wall -std=c++11 -O2 + +SRCS := json11.cpp mapjson.cpp + +HEADERS := mapjson.h + +.PHONY: all clean + +all: mapjson + @: + +mapjson: $(SRCS) $(HEADERS) + $(CXX) $(CXXFLAGS) $(SRCS) -o $@ $(LDFLAGS) + +clean: + $(RM) mapjson mapjson.exe diff --git a/tools/mapjson/json11.cpp b/tools/mapjson/json11.cpp new file mode 100755 index 0000000..1da5302 --- /dev/null +++ b/tools/mapjson/json11.cpp @@ -0,0 +1,786 @@ +/* Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "json11.h" +#include <cassert> +#include <cmath> +#include <cstdlib> +#include <cstdio> +#include <limits> + +namespace json11 { + +static const int max_depth = 200; + +using std::string; +using std::vector; +using std::map; +using std::make_shared; +using std::initializer_list; +using std::move; + +/* Helper for representing null - just a do-nothing struct, plus comparison + * operators so the helpers in JsonValue work. We can't use nullptr_t because + * it may not be orderable. + */ +struct NullStruct { + bool operator==(NullStruct) const { return true; } + bool operator<(NullStruct) const { return false; } +}; + +/* * * * * * * * * * * * * * * * * * * * + * Serialization + */ + +static void dump(NullStruct, string &out) { + out += "null"; +} + +static void dump(double value, string &out) { + if (std::isfinite(value)) { + char buf[32]; + snprintf(buf, sizeof buf, "%.17g", value); + out += buf; + } else { + out += "null"; + } +} + +static void dump(int value, string &out) { + char buf[32]; + snprintf(buf, sizeof buf, "%d", value); + out += buf; +} + +static void dump(bool value, string &out) { + out += value ? "true" : "false"; +} + +static void dump(const string &value, string &out) { + out += '"'; + for (size_t i = 0; i < value.length(); i++) { + const char ch = value[i]; + if (ch == '\\') { + out += "\\\\"; + } else if (ch == '"') { + out += "\\\""; + } else if (ch == '\b') { + out += "\\b"; + } else if (ch == '\f') { + out += "\\f"; + } else if (ch == '\n') { + out += "\\n"; + } else if (ch == '\r') { + out += "\\r"; + } else if (ch == '\t') { + out += "\\t"; + } else if (static_cast<uint8_t>(ch) <= 0x1f) { + char buf[8]; + snprintf(buf, sizeof buf, "\\u%04x", ch); + out += buf; + } else if (static_cast<uint8_t>(ch) == 0xe2 && static_cast<uint8_t>(value[i+1]) == 0x80 + && static_cast<uint8_t>(value[i+2]) == 0xa8) { + out += "\\u2028"; + i += 2; + } else if (static_cast<uint8_t>(ch) == 0xe2 && static_cast<uint8_t>(value[i+1]) == 0x80 + && static_cast<uint8_t>(value[i+2]) == 0xa9) { + out += "\\u2029"; + i += 2; + } else { + out += ch; + } + } + out += '"'; +} + +static void dump(const Json::array &values, string &out) { + bool first = true; + out += "["; + for (const auto &value : values) { + if (!first) + out += ", "; + value.dump(out); + first = false; + } + out += "]"; +} + +static void dump(const Json::object &values, string &out) { + bool first = true; + out += "{"; + for (const auto &kv : values) { + if (!first) + out += ", "; + dump(kv.first, out); + out += ": "; + kv.second.dump(out); + first = false; + } + out += "}"; +} + +void Json::dump(string &out) const { + m_ptr->dump(out); +} + +/* * * * * * * * * * * * * * * * * * * * + * Value wrappers + */ + +template <Json::Type tag, typename T> +class Value : public JsonValue { +protected: + + // Constructors + explicit Value(const T &value) : m_value(value) {} + explicit Value(T &&value) : m_value(move(value)) {} + + // Get type tag + Json::Type type() const override { + return tag; + } + + // Comparisons + bool equals(const JsonValue * other) const override { + return m_value == static_cast<const Value<tag, T> *>(other)->m_value; + } + bool less(const JsonValue * other) const override { + return m_value < static_cast<const Value<tag, T> *>(other)->m_value; + } + + const T m_value; + void dump(string &out) const override { json11::dump(m_value, out); } +}; + +class JsonDouble final : public Value<Json::NUMBER, double> { + double number_value() const override { return m_value; } + int int_value() const override { return static_cast<int>(m_value); } + bool equals(const JsonValue * other) const override { return m_value == other->number_value(); } + bool less(const JsonValue * other) const override { return m_value < other->number_value(); } +public: + explicit JsonDouble(double value) : Value(value) {} +}; + +class JsonInt final : public Value<Json::NUMBER, int> { + double number_value() const override { return m_value; } + int int_value() const override { return m_value; } + bool equals(const JsonValue * other) const override { return m_value == other->number_value(); } + bool less(const JsonValue * other) const override { return m_value < other->number_value(); } +public: + explicit JsonInt(int value) : Value(value) {} +}; + +class JsonBoolean final : public Value<Json::BOOL, bool> { + bool bool_value() const override { return m_value; } +public: + explicit JsonBoolean(bool value) : Value(value) {} +}; + +class JsonString final : public Value<Json::STRING, string> { + const string &string_value() const override { return m_value; } +public: + explicit JsonString(const string &value) : Value(value) {} + explicit JsonString(string &&value) : Value(move(value)) {} +}; + +class JsonArray final : public Value<Json::ARRAY, Json::array> { + const Json::array &array_items() const override { return m_value; } + const Json & operator[](size_t i) const override; +public: + explicit JsonArray(const Json::array &value) : Value(value) {} + explicit JsonArray(Json::array &&value) : Value(move(value)) {} +}; + +class JsonObject final : public Value<Json::OBJECT, Json::object> { + const Json::object &object_items() const override { return m_value; } + const Json & operator[](const string &key) const override; +public: + explicit JsonObject(const Json::object &value) : Value(value) {} + explicit JsonObject(Json::object &&value) : Value(move(value)) {} +}; + +class JsonNull final : public Value<Json::NUL, NullStruct> { +public: + JsonNull() : Value({}) {} +}; + +/* * * * * * * * * * * * * * * * * * * * + * Static globals - static-init-safe + */ +struct Statics { + const std::shared_ptr<JsonValue> null = make_shared<JsonNull>(); + const std::shared_ptr<JsonValue> t = make_shared<JsonBoolean>(true); + const std::shared_ptr<JsonValue> f = make_shared<JsonBoolean>(false); + const string empty_string; + const vector<Json> empty_vector; + const map<string, Json> empty_map; + Statics() {} +}; + +static const Statics & statics() { + static const Statics s {}; + return s; +} + +static const Json & static_null() { + // This has to be separate, not in Statics, because Json() accesses statics().null. + static const Json json_null; + return json_null; +} + +/* * * * * * * * * * * * * * * * * * * * + * Constructors + */ + +Json::Json() noexcept : m_ptr(statics().null) {} +Json::Json(std::nullptr_t) noexcept : m_ptr(statics().null) {} +Json::Json(double value) : m_ptr(make_shared<JsonDouble>(value)) {} +Json::Json(int value) : m_ptr(make_shared<JsonInt>(value)) {} +Json::Json(bool value) : m_ptr(value ? statics().t : statics().f) {} +Json::Json(const string &value) : m_ptr(make_shared<JsonString>(value)) {} +Json::Json(string &&value) : m_ptr(make_shared<JsonString>(move(value))) {} +Json::Json(const char * value) : m_ptr(make_shared<JsonString>(value)) {} +Json::Json(const Json::array &values) : m_ptr(make_shared<JsonArray>(values)) {} +Json::Json(Json::array &&values) : m_ptr(make_shared<JsonArray>(move(values))) {} +Json::Json(const Json::object &values) : m_ptr(make_shared<JsonObject>(values)) {} +Json::Json(Json::object &&values) : m_ptr(make_shared<JsonObject>(move(values))) {} + +/* * * * * * * * * * * * * * * * * * * * + * Accessors + */ + +Json::Type Json::type() const { return m_ptr->type(); } +double Json::number_value() const { return m_ptr->number_value(); } +int Json::int_value() const { return m_ptr->int_value(); } +bool Json::bool_value() const { return m_ptr->bool_value(); } +const string & Json::string_value() const { return m_ptr->string_value(); } +const vector<Json> & Json::array_items() const { return m_ptr->array_items(); } +const map<string, Json> & Json::object_items() const { return m_ptr->object_items(); } +const Json & Json::operator[] (size_t i) const { return (*m_ptr)[i]; } +const Json & Json::operator[] (const string &key) const { return (*m_ptr)[key]; } + +double JsonValue::number_value() const { return 0; } +int JsonValue::int_value() const { return 0; } +bool JsonValue::bool_value() const { return false; } +const string & JsonValue::string_value() const { return statics().empty_string; } +const vector<Json> & JsonValue::array_items() const { return statics().empty_vector; } +const map<string, Json> & JsonValue::object_items() const { return statics().empty_map; } +const Json & JsonValue::operator[] (size_t) const { return static_null(); } +const Json & JsonValue::operator[] (const string &) const { return static_null(); } + +const Json & JsonObject::operator[] (const string &key) const { + auto iter = m_value.find(key); + return (iter == m_value.end()) ? static_null() : iter->second; +} +const Json & JsonArray::operator[] (size_t i) const { + if (i >= m_value.size()) return static_null(); + else return m_value[i]; +} + +/* * * * * * * * * * * * * * * * * * * * + * Comparison + */ + +bool Json::operator== (const Json &other) const { + if (m_ptr == other.m_ptr) + return true; + if (m_ptr->type() != other.m_ptr->type()) + return false; + + return m_ptr->equals(other.m_ptr.get()); +} + +bool Json::operator< (const Json &other) const { + if (m_ptr == other.m_ptr) + return false; + if (m_ptr->type() != other.m_ptr->type()) + return m_ptr->type() < other.m_ptr->type(); + + return m_ptr->less(other.m_ptr.get()); +} + +/* * * * * * * * * * * * * * * * * * * * + * Parsing + */ + +/* esc(c) + * + * Format char c suitable for printing in an error message. + */ +static inline string esc(char c) { + char buf[12]; + if (static_cast<uint8_t>(c) >= 0x20 && static_cast<uint8_t>(c) <= 0x7f) { + snprintf(buf, sizeof buf, "'%c' (%d)", c, c); + } else { + snprintf(buf, sizeof buf, "(%d)", c); + } + return string(buf); +} + +static inline bool in_range(long x, long lower, long upper) { + return (x >= lower && x <= upper); +} + +namespace { +/* JsonParser + * + * Object that tracks all state of an in-progress parse. + */ +struct JsonParser final { + + /* State + */ + const string &str; + size_t i; + string &err; + bool failed; + const JsonParse strategy; + + /* fail(msg, err_ret = Json()) + * + * Mark this parse as failed. + */ + Json fail(string &&msg) { + return fail(move(msg), Json()); + } + + template <typename T> + T fail(string &&msg, const T err_ret) { + if (!failed) + err = std::move(msg); + failed = true; + return err_ret; + } + + /* consume_whitespace() + * + * Advance until the current character is non-whitespace. + */ + void consume_whitespace() { + while (str[i] == ' ' || str[i] == '\r' || str[i] == '\n' || str[i] == '\t') + i++; + } + + /* consume_comment() + * + * Advance comments (c-style inline and multiline). + */ + bool consume_comment() { + bool comment_found = false; + if (str[i] == '/') { + i++; + if (i == str.size()) + return fail("unexpected end of input after start of comment", false); + if (str[i] == '/') { // inline comment + i++; + // advance until next line, or end of input + while (i < str.size() && str[i] != '\n') { + i++; + } + comment_found = true; + } + else if (str[i] == '*') { // multiline comment + i++; + if (i > str.size()-2) + return fail("unexpected end of input inside multi-line comment", false); + // advance until closing tokens + while (!(str[i] == '*' && str[i+1] == '/')) { + i++; + if (i > str.size()-2) + return fail( + "unexpected end of input inside multi-line comment", false); + } + i += 2; + comment_found = true; + } + else + return fail("malformed comment", false); + } + return comment_found; + } + + /* consume_garbage() + * + * Advance until the current character is non-whitespace and non-comment. + */ + void consume_garbage() { + consume_whitespace(); + if(strategy == JsonParse::COMMENTS) { + bool comment_found = false; + do { + comment_found = consume_comment(); + if (failed) return; + consume_whitespace(); + } + while(comment_found); + } + } + + /* get_next_token() + * + * Return the next non-whitespace character. If the end of the input is reached, + * flag an error and return 0. + */ + char get_next_token() { + consume_garbage(); + if (failed) return static_cast<char>(0); + if (i == str.size()) + return fail("unexpected end of input", static_cast<char>(0)); + + return str[i++]; + } + + /* encode_utf8(pt, out) + * + * Encode pt as UTF-8 and add it to out. + */ + void encode_utf8(long pt, string & out) { + if (pt < 0) + return; + + if (pt < 0x80) { + out += static_cast<char>(pt); + } else if (pt < 0x800) { + out += static_cast<char>((pt >> 6) | 0xC0); + out += static_cast<char>((pt & 0x3F) | 0x80); + } else if (pt < 0x10000) { + out += static_cast<char>((pt >> 12) | 0xE0); + out += static_cast<char>(((pt >> 6) & 0x3F) | 0x80); + out += static_cast<char>((pt & 0x3F) | 0x80); + } else { + out += static_cast<char>((pt >> 18) | 0xF0); + out += static_cast<char>(((pt >> 12) & 0x3F) | 0x80); + out += static_cast<char>(((pt >> 6) & 0x3F) | 0x80); + out += static_cast<char>((pt & 0x3F) | 0x80); + } + } + + /* parse_string() + * + * Parse a string, starting at the current position. + */ + string parse_string() { + string out; + long last_escaped_codepoint = -1; + while (true) { + if (i == str.size()) + return fail("unexpected end of input in string", ""); + + char ch = str[i++]; + + if (ch == '"') { + encode_utf8(last_escaped_codepoint, out); + return out; + } + + if (in_range(ch, 0, 0x1f)) + return fail("unescaped " + esc(ch) + " in string", ""); + + // The usual case: non-escaped characters + if (ch != '\\') { + encode_utf8(last_escaped_codepoint, out); + last_escaped_codepoint = -1; + out += ch; + continue; + } + + // Handle escapes + if (i == str.size()) + return fail("unexpected end of input in string", ""); + + ch = str[i++]; + + if (ch == 'u') { + // Extract 4-byte escape sequence + string esc = str.substr(i, 4); + // Explicitly check length of the substring. The following loop + // relies on std::string returning the terminating NUL when + // accessing str[length]. Checking here reduces brittleness. + if (esc.length() < 4) { + return fail("bad \\u escape: " + esc, ""); + } + for (size_t j = 0; j < 4; j++) { + if (!in_range(esc[j], 'a', 'f') && !in_range(esc[j], 'A', 'F') + && !in_range(esc[j], '0', '9')) + return fail("bad \\u escape: " + esc, ""); + } + + long codepoint = strtol(esc.data(), nullptr, 16); + + // JSON specifies that characters outside the BMP shall be encoded as a pair + // of 4-hex-digit \u escapes encoding their surrogate pair components. Check + // whether we're in the middle of such a beast: the previous codepoint was an + // escaped lead (high) surrogate, and this is a trail (low) surrogate. + if (in_range(last_escaped_codepoint, 0xD800, 0xDBFF) + && in_range(codepoint, 0xDC00, 0xDFFF)) { + // Reassemble the two surrogate pairs into one astral-plane character, per + // the UTF-16 algorithm. + encode_utf8((((last_escaped_codepoint - 0xD800) << 10) + | (codepoint - 0xDC00)) + 0x10000, out); + last_escaped_codepoint = -1; + } else { + encode_utf8(last_escaped_codepoint, out); + last_escaped_codepoint = codepoint; + } + + i += 4; + continue; + } + + encode_utf8(last_escaped_codepoint, out); + last_escaped_codepoint = -1; + + if (ch == 'b') { + out += '\b'; + } else if (ch == 'f') { + out += '\f'; + } else if (ch == 'n') { + out += '\n'; + } else if (ch == 'r') { + out += '\r'; + } else if (ch == 't') { + out += '\t'; + } else if (ch == '"' || ch == '\\' || ch == '/') { + out += ch; + } else { + return fail("invalid escape character " + esc(ch), ""); + } + } + } + + /* parse_number() + * + * Parse a double. + */ + Json parse_number() { + size_t start_pos = i; + + if (str[i] == '-') + i++; + + // Integer part + if (str[i] == '0') { + i++; + if (in_range(str[i], '0', '9')) + return fail("leading 0s not permitted in numbers"); + } else if (in_range(str[i], '1', '9')) { + i++; + while (in_range(str[i], '0', '9')) + i++; + } else { + return fail("invalid " + esc(str[i]) + " in number"); + } + + if (str[i] != '.' && str[i] != 'e' && str[i] != 'E' + && (i - start_pos) <= static_cast<size_t>(std::numeric_limits<int>::digits10)) { + return std::atoi(str.c_str() + start_pos); + } + + // Decimal part + if (str[i] == '.') { + i++; + if (!in_range(str[i], '0', '9')) + return fail("at least one digit required in fractional part"); + + while (in_range(str[i], '0', '9')) + i++; + } + + // Exponent part + if (str[i] == 'e' || str[i] == 'E') { + i++; + + if (str[i] == '+' || str[i] == '-') + i++; + + if (!in_range(str[i], '0', '9')) + return fail("at least one digit required in exponent"); + + while (in_range(str[i], '0', '9')) + i++; + } + + return std::strtod(str.c_str() + start_pos, nullptr); + } + + /* expect(str, res) + * + * Expect that 'str' starts at the character that was just read. If it does, advance + * the input and return res. If not, flag an error. + */ + Json expect(const string &expected, Json res) { + assert(i != 0); + i--; + if (str.compare(i, expected.length(), expected) == 0) { + i += expected.length(); + return res; + } else { + return fail("parse error: expected " + expected + ", got " + str.substr(i, expected.length())); + } + } + + /* parse_json() + * + * Parse a JSON object. + */ + Json parse_json(int depth) { + if (depth > max_depth) { + return fail("exceeded maximum nesting depth"); + } + + char ch = get_next_token(); + if (failed) + return Json(); + + if (ch == '-' || (ch >= '0' && ch <= '9')) { + i--; + return parse_number(); + } + + if (ch == 't') + return expect("true", true); + + if (ch == 'f') + return expect("false", false); + + if (ch == 'n') + return expect("null", Json()); + + if (ch == '"') + return parse_string(); + + if (ch == '{') { + map<string, Json> data; + ch = get_next_token(); + if (ch == '}') + return data; + + while (1) { + if (ch != '"') + return fail("expected '\"' in object, got " + esc(ch)); + + string key = parse_string(); + if (failed) + return Json(); + + ch = get_next_token(); + if (ch != ':') + return fail("expected ':' in object, got " + esc(ch)); + + data[std::move(key)] = parse_json(depth + 1); + if (failed) + return Json(); + + ch = get_next_token(); + if (ch == '}') + break; + if (ch != ',') + return fail("expected ',' in object, got " + esc(ch)); + + ch = get_next_token(); + } + return data; + } + + if (ch == '[') { + vector<Json> data; + ch = get_next_token(); + if (ch == ']') + return data; + + while (1) { + i--; + data.push_back(parse_json(depth + 1)); + if (failed) + return Json(); + + ch = get_next_token(); + if (ch == ']') + break; + if (ch != ',') + return fail("expected ',' in list, got " + esc(ch)); + + ch = get_next_token(); + (void)ch; + } + return data; + } + + return fail("expected value, got " + esc(ch)); + } +}; +}//namespace { + +Json Json::parse(const string &in, string &err, JsonParse strategy) { + JsonParser parser { in, 0, err, false, strategy }; + Json result = parser.parse_json(0); + + // Check for any trailing garbage + parser.consume_garbage(); + if (parser.failed) + return Json(); + if (parser.i != in.size()) + return parser.fail("unexpected trailing " + esc(in[parser.i])); + + return result; +} + +// Documented in json11.hpp +vector<Json> Json::parse_multi(const string &in, + std::string::size_type &parser_stop_pos, + string &err, + JsonParse strategy) { + JsonParser parser { in, 0, err, false, strategy }; + parser_stop_pos = 0; + vector<Json> json_vec; + while (parser.i != in.size() && !parser.failed) { + json_vec.push_back(parser.parse_json(0)); + if (parser.failed) + break; + + // Check for another object + parser.consume_garbage(); + if (parser.failed) + break; + parser_stop_pos = parser.i; + } + return json_vec; +} + +/* * * * * * * * * * * * * * * * * * * * + * Shape-checking + */ + +bool Json::has_shape(const shape & types, string & err) const { + if (!is_object()) { + err = "expected JSON object, got " + dump(); + return false; + } + + for (auto & item : types) { + if ((*this)[item.first].type() != item.second) { + err = "bad type for " + item.first + " in " + dump(); + return false; + } + } + + return true; +} + +} // namespace json11 diff --git a/tools/mapjson/json11.h b/tools/mapjson/json11.h new file mode 100755 index 0000000..c04c436 --- /dev/null +++ b/tools/mapjson/json11.h @@ -0,0 +1,230 @@ +/* json11 + * + * json11 is a tiny JSON library for C++11, providing JSON parsing and serialization. + * + * The core object provided by the library is json11::Json. A Json object represents any JSON + * value: null, bool, number (int or double), string (std::string), array (std::vector), or + * object (std::map). + * + * Json objects act like values: they can be assigned, copied, moved, compared for equality or + * order, etc. There are also helper methods Json::dump, to serialize a Json to a string, and + * Json::parse (static) to parse a std::string as a Json object. + * + * Internally, the various types of Json object are represented by the JsonValue class + * hierarchy. + * + * A note on numbers - JSON specifies the syntax of number formatting but not its semantics, + * so some JSON implementations distinguish between integers and floating-point numbers, while + * some don't. In json11, we choose the latter. Because some JSON implementations (namely + * Javascript itself) treat all numbers as the same type, distinguishing the two leads + * to JSON that will be *silently* changed by a round-trip through those implementations. + * Dangerous! To avoid that risk, json11 stores all numbers as double internally, but also + * provides integer helpers. + * + * Fortunately, double-precision IEEE754 ('double') can precisely store any integer in the + * range +/-2^53, which includes every 'int' on most systems. (Timestamps often use int64 + * or long long to avoid the Y2038K problem; a double storing microseconds since some epoch + * will be exact for +/- 275 years.) + */ + +/* Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include <string> +#include <vector> +#include <map> +#include <memory> +#include <initializer_list> + +#ifdef _MSC_VER + #if _MSC_VER <= 1800 // VS 2013 + #ifndef noexcept + #define noexcept throw() + #endif + + #ifndef snprintf + #define snprintf _snprintf_s + #endif + #endif +#endif + +namespace json11 { + +enum JsonParse { + STANDARD, COMMENTS +}; + +class JsonValue; + +class Json final { +public: + // Types + enum Type { + NUL, NUMBER, BOOL, STRING, ARRAY, OBJECT + }; + + // Array and object typedefs + typedef std::vector<Json> array; + typedef std::map<std::string, Json> object; + + // Constructors for the various types of JSON value. + Json() noexcept; // NUL + Json(std::nullptr_t) noexcept; // NUL + Json(double value); // NUMBER + Json(int value); // NUMBER + Json(bool value); // BOOL + Json(const std::string &value); // STRING + Json(std::string &&value); // STRING + Json(const char * value); // STRING + Json(const array &values); // ARRAY + Json(array &&values); // ARRAY + Json(const object &values); // OBJECT + Json(object &&values); // OBJECT + + // Implicit constructor: anything with a to_json() function. + template <class T, class = decltype(&T::to_json)> + Json(const T & t) : Json(t.to_json()) {} + + // Implicit constructor: map-like objects (std::map, std::unordered_map, etc) + template <class M, typename std::enable_if< + std::is_constructible<std::string, decltype(std::declval<M>().begin()->first)>::value + && std::is_constructible<Json, decltype(std::declval<M>().begin()->second)>::value, + int>::type = 0> + Json(const M & m) : Json(object(m.begin(), m.end())) {} + + // Implicit constructor: vector-like objects (std::list, std::vector, std::set, etc) + template <class V, typename std::enable_if< + std::is_constructible<Json, decltype(*std::declval<V>().begin())>::value, + int>::type = 0> + Json(const V & v) : Json(array(v.begin(), v.end())) {} + + // This prevents Json(some_pointer) from accidentally producing a bool. Use + // Json(bool(some_pointer)) if that behavior is desired. + Json(void *) = delete; + + // Accessors + Type type() const; + + bool is_null() const { return type() == NUL; } + bool is_number() const { return type() == NUMBER; } + bool is_bool() const { return type() == BOOL; } + bool is_string() const { return type() == STRING; } + bool is_array() const { return type() == ARRAY; } + bool is_object() const { return type() == OBJECT; } + + // Return the enclosed value if this is a number, 0 otherwise. Note that json11 does not + // distinguish between integer and non-integer numbers - number_value() and int_value() + // can both be applied to a NUMBER-typed object. + double number_value() const; + int int_value() const; + + // Return the enclosed value if this is a boolean, false otherwise. + bool bool_value() const; + // Return the enclosed string if this is a string, "" otherwise. + const std::string &string_value() const; + // Return the enclosed std::vector if this is an array, or an empty vector otherwise. + const array &array_items() const; + // Return the enclosed std::map if this is an object, or an empty map otherwise. + const object &object_items() const; + + // Return a reference to arr[i] if this is an array, Json() otherwise. + const Json & operator[](size_t i) const; + // Return a reference to obj[key] if this is an object, Json() otherwise. + const Json & operator[](const std::string &key) const; + + // Serialize. + void dump(std::string &out) const; + std::string dump() const { + std::string out; + dump(out); + return out; + } + + // Parse. If parse fails, return Json() and assign an error message to err. + static Json parse(const std::string & in, + std::string & err, + JsonParse strategy = JsonParse::STANDARD); + static Json parse(const char * in, + std::string & err, + JsonParse strategy = JsonParse::STANDARD) { + if (in) { + return parse(std::string(in), err, strategy); + } else { + err = "null input"; + return nullptr; + } + } + // Parse multiple objects, concatenated or separated by whitespace + static std::vector<Json> parse_multi( + const std::string & in, + std::string::size_type & parser_stop_pos, + std::string & err, + JsonParse strategy = JsonParse::STANDARD); + + static inline std::vector<Json> parse_multi( + const std::string & in, + std::string & err, + JsonParse strategy = JsonParse::STANDARD) { + std::string::size_type parser_stop_pos; + return parse_multi(in, parser_stop_pos, err, strategy); + } + + bool operator== (const Json &rhs) const; + bool operator< (const Json &rhs) const; + bool operator!= (const Json &rhs) const { return !(*this == rhs); } + bool operator<= (const Json &rhs) const { return !(rhs < *this); } + bool operator> (const Json &rhs) const { return (rhs < *this); } + bool operator>= (const Json &rhs) const { return !(*this < rhs); } + + /* has_shape(types, err) + * + * Return true if this is a JSON object and, for each item in types, has a field of + * the given type. If not, return false and set err to a descriptive message. + */ + typedef std::initializer_list<std::pair<std::string, Type>> shape; + bool has_shape(const shape & types, std::string & err) const; + +private: + std::shared_ptr<JsonValue> m_ptr; +}; + +// Internal class hierarchy - JsonValue objects are not exposed to users of this API. +class JsonValue { +protected: + friend class Json; + friend class JsonInt; + friend class JsonDouble; + virtual Json::Type type() const = 0; + virtual bool equals(const JsonValue * other) const = 0; + virtual bool less(const JsonValue * other) const = 0; + virtual void dump(std::string &out) const = 0; + virtual double number_value() const; + virtual int int_value() const; + virtual bool bool_value() const; + virtual const std::string &string_value() const; + virtual const Json::array &array_items() const; + virtual const Json &operator[](size_t i) const; + virtual const Json::object &object_items() const; + virtual const Json &operator[](const std::string &key) const; + virtual ~JsonValue() {} +}; + +} // namespace json11 diff --git a/tools/mapjson/mapjson.cpp b/tools/mapjson/mapjson.cpp new file mode 100755 index 0000000..1cf196f --- /dev/null +++ b/tools/mapjson/mapjson.cpp @@ -0,0 +1,538 @@ +// mapjson.cpp + +#include <iostream> +using std::cout; using std::endl; + +#include <string> +using std::string; + +#include <vector> +using std::vector; + +#include <algorithm> +using std::sort; using std::find; + +#include <map> +using std::map; + +#include <fstream> +using std::ofstream; using std::ifstream; + +#include <sstream> +using std::ostringstream; + +#include <limits> +using std::numeric_limits; + +#include "json11.h" +using json11::Json; + +#include "mapjson.h" + + +string read_text_file(string filepath) { + ifstream in_file(filepath); + + if (!in_file.is_open()) + FATAL_ERROR("Cannot open file %s for reading.\n", filepath.c_str()); + + string text; + + in_file.seekg(0, std::ios::end); + text.resize(in_file.tellg()); + + in_file.seekg(0, std::ios::beg); + in_file.read(&text[0], text.size()); + + in_file.close(); + + return text; +} + +void write_text_file(string filepath, string text) { + ofstream out_file(filepath, std::ofstream::binary); + + if (!out_file.is_open()) + FATAL_ERROR("Cannot open file %s for writing.\n", filepath.c_str()); + + out_file << text; + + out_file.close(); +} + +string generate_map_header_text(Json map_data, Json layouts_data, string version) { + string map_layout_id = map_data["layout"].string_value(); + + vector<Json> matched; + + for (auto &field : layouts_data["layouts"].array_items()) { + if (map_layout_id == field["id"].string_value()) + matched.push_back(field); + } + + if (matched.size() != 1) + FATAL_ERROR("Failed to find matching layout for %s.\n", map_layout_id.c_str()); + + Json layout = matched[0]; + + ostringstream text; + + text << map_data["name"].string_value() << ":\n" + << "\t.4byte " << layout["name"].string_value() << "\n"; + + if (map_data.object_items().find("shared_events_map") != map_data.object_items().end()) + text << "\t.4byte " << map_data["shared_events_map"].string_value() << "_MapEvents\n"; + else + text << "\t.4byte " << map_data["name"].string_value() << "_MapEvents\n"; + + if (map_data.object_items().find("shared_scripts_map") != map_data.object_items().end()) + text << "\t.4byte " << map_data["shared_scripts_map"].string_value() << "_MapScripts\n"; + else + text << "\t.4byte " << map_data["name"].string_value() << "_MapScripts\n"; + + if (map_data.object_items().find("connections") != map_data.object_items().end() + && map_data["connections"].array_items().size() > 0) + text << "\t.4byte " << map_data["name"].string_value() << "_MapConnections\n"; + else + text << "\t.4byte 0x0\n"; + + text << "\t.2byte " << map_data["music"].string_value() << "\n" + << "\t.2byte " << layout["id"].string_value() << "\n" + << "\t.byte " << map_data["region_map_section"].string_value() << "\n" + << "\t.byte " << map_data["requires_flash"].bool_value() << "\n" + << "\t.byte " << map_data["weather"].string_value() << "\n" + << "\t.byte " << map_data["map_type"].string_value() << "\n" + << "\t.2byte 0\n"; + + if (version == "ruby") + text << "\t.byte " << map_data["show_map_name"].bool_value() << "\n"; + else if (version == "emerald") + text << "\tmap_header_flags " + << "allow_bike=" << map_data["allow_bike"].bool_value() << ", " + << "allow_escape_rope=" << map_data["allow_escape_rope"].bool_value() << ", " + << "allow_run=" << map_data["allow_running"].bool_value() << ", " + << "show_map_name=" << map_data["show_map_name"].bool_value() << "\n"; + + text << "\t.byte " << map_data["battle_scene"].string_value() << "\n\n"; + + return text.str(); +} + +string generate_map_connections_text(Json map_data) { + if (map_data["connections"] == Json()) + return string("\n"); + + ostringstream text; + + text << map_data["name"].string_value() << "_MapConnectionsList:\n"; + + for (auto &connection : map_data["connections"].array_items()) { + text << "\tconnection " + << connection["direction"].string_value() << ", " + << connection["offset"].int_value() << ", " + << connection["map"].string_value() << "\n"; + } + + text << "\n" << map_data["name"].string_value() << "_MapConnections:\n" + << "\t.4byte " << map_data["connections"].array_items().size() << "\n" + << "\t.4byte " << map_data["name"].string_value() << "_MapConnectionsList\n\n"; + + return text.str(); +} + +string generate_map_events_text(Json map_data) { + if (map_data.object_items().find("shared_events_map") != map_data.object_items().end()) + return string("\n"); + + ostringstream text; + + string objects_label, warps_label, coords_label, bgs_label; + + if (map_data["object_events"].array_items().size() > 0) { + objects_label = map_data["name"].string_value() + "_EventObjects"; + text << objects_label << ":\n"; + for (unsigned int i = 0; i < map_data["object_events"].array_items().size(); i++) { + auto obj_event = map_data["object_events"].array_items()[i]; + text << "\tobject_event " << i + 1 << ", " + << obj_event["graphics_id"].string_value() << ", 0, " + << obj_event["x"].int_value() << ", " + << obj_event["y"].int_value() << ", " + << obj_event["elevation"].int_value() << ", " + << obj_event["movement_type"].string_value() << ", " + << obj_event["movement_range_x"].int_value() << ", " + << obj_event["movement_range_y"].int_value() << ", " + << obj_event["trainer_type"].string_value() << ", " + << obj_event["trainer_sight_or_berry_tree_id"].string_value() << ", " + << obj_event["script"].string_value() << ", " + << obj_event["flag"].string_value() << "\n"; + } + text << "\n"; + } else { + objects_label = "0x0"; + } + + if (map_data["warp_events"].array_items().size() > 0) { + warps_label = map_data["name"].string_value() + "_MapWarps"; + text << warps_label << ":\n"; + for (auto &warp_event : map_data["warp_events"].array_items()) { + text << "\twarp_def " + << warp_event["x"].int_value() << ", " + << warp_event["y"].int_value() << ", " + << warp_event["elevation"].int_value() << ", " + << warp_event["dest_warp_id"].int_value() << ", " + << warp_event["dest_map"].string_value() << "\n"; + } + text << "\n"; + } else { + warps_label = "0x0"; + } + + if (map_data["coord_events"].array_items().size() > 0) { + coords_label = map_data["name"].string_value() + "_MapCoordEvents"; + text << coords_label << ":\n"; + for (auto &coord_event : map_data["coord_events"].array_items()) { + if (coord_event["type"].string_value() == "trigger") { + text << "\tcoord_event " + << coord_event["x"].int_value() << ", " + << coord_event["y"].int_value() << ", " + << coord_event["elevation"].int_value() << ", " + << coord_event["var"].string_value() << ", " + << coord_event["var_value"].string_value() << ", " + << coord_event["script"].string_value() << "\n"; + } + else if (coord_event["type"] == "weather") { + text << "\tcoord_weather_event " + << coord_event["x"].int_value() << ", " + << coord_event["y"].int_value() << ", " + << coord_event["elevation"].int_value() << ", " + << coord_event["weather"].string_value() << "\n"; + } + } + text << "\n"; + } else { + coords_label = "0x0"; + } + + if (map_data["bg_events"].array_items().size() > 0) { + bgs_label = map_data["name"].string_value() + "_MapBGEvents"; + text << bgs_label << ":\n"; + for (auto &bg_event : map_data["bg_events"].array_items()) { + if (bg_event["type"] == "sign") { + text << "\tbg_event " + << bg_event["x"].int_value() << ", " + << bg_event["y"].int_value() << ", " + << bg_event["elevation"].int_value() << ", " + << bg_event["player_facing_dir"].string_value() << ", " + << bg_event["script"].string_value() << "\n"; + } + else if (bg_event["type"] == "hidden_item") { + text << "\tbg_hidden_item_event " + << bg_event["x"].int_value() << ", " + << bg_event["y"].int_value() << ", " + << bg_event["elevation"].int_value() << ", " + << bg_event["item"].string_value() << ", " + << bg_event["flag"].string_value() << "\n"; + } + else if (bg_event["type"] == "secret_base") { + text << "\tbg_secret_base_event " + << bg_event["x"].int_value() << ", " + << bg_event["y"].int_value() << ", " + << bg_event["elevation"].int_value() << ", " + << bg_event["secret_base_id"].string_value() << "\n"; + } + } + text << "\n"; + } else { + bgs_label = "0x0"; + } + + text << map_data["name"].string_value() << "_MapEvents::\n" + << "\tmap_events " << objects_label << ", " << warps_label << ", " + << coords_label << ", " << bgs_label << "\n\n"; + + return text.str(); +} + +string get_directory_name(string filename) { + size_t dir_pos = filename.find_last_of("/\\"); + + return filename.substr(0, dir_pos + 1); +} + +void process_map(string map_filepath, string layouts_filepath, string version) { + string mapdata_err, layouts_err; + + string mapdata_json_text = read_text_file(map_filepath); + string layouts_json_text = read_text_file(layouts_filepath); + + Json map_data = Json::parse(mapdata_json_text, mapdata_err); + if (map_data == Json()) + FATAL_ERROR("%s\n", mapdata_err.c_str()); + + Json layouts_data = Json::parse(layouts_json_text, layouts_err); + if (layouts_data == Json()) + FATAL_ERROR("%s\n", layouts_err.c_str()); + + string header_text = generate_map_header_text(map_data, layouts_data, version); + string events_text = generate_map_events_text(map_data); + string connections_text = generate_map_connections_text(map_data); + + string files_dir = get_directory_name(map_filepath); + write_text_file(files_dir + "header.inc", header_text); + write_text_file(files_dir + "events.inc", events_text); + write_text_file(files_dir + "connections.inc", connections_text); +} + +string generate_groups_text(Json groups_data) { + ostringstream text; + + for (auto &key : groups_data["group_order"].array_items()) { + string group = key.string_value(); + text << group << "::\n"; + auto maps = groups_data[group].array_items(); + for (Json &map_name : maps) + text << "\t.4byte " << map_name.string_value() << "\n"; + text << "\n"; + } + + text << "\t.align 2\n" << "gMapGroups::\n"; + for (auto &group : groups_data["group_order"].array_items()) + text << "\t.4byte " << group.string_value() << "\n"; + text << "\n"; + + return text.str(); +} + +string generate_connections_text(Json groups_data) { + vector<Json> map_names; + + for (auto &group : groups_data["group_order"].array_items()) + for (auto map_name : groups_data[group.string_value()].array_items()) + map_names.push_back(map_name); + + vector<Json> connections_include_order = groups_data["connections_include_order"].array_items(); + + if (connections_include_order.size() > 0) + sort(map_names.begin(), map_names.end(), [connections_include_order](const Json &a, const Json &b) { + auto iter_a = find(connections_include_order.begin(), connections_include_order.end(), a); + if (iter_a == connections_include_order.end()) + iter_a = connections_include_order.begin() + numeric_limits<int>::max(); + auto iter_b = find(connections_include_order.begin(), connections_include_order.end(), b); + if (iter_b == connections_include_order.end()) + iter_b = connections_include_order.begin() + numeric_limits<int>::max(); + return iter_a < iter_b; + }); + + ostringstream text; + + for (Json map_name : map_names) + text << "\t.include \"data/maps/" << map_name.string_value() << "/connections.inc\"\n"; + + return text.str(); +} + +string generate_headers_text(Json groups_data) { + vector<string> map_names; + + for (auto &group : groups_data["group_order"].array_items()) + for (auto map_name : groups_data[group.string_value()].array_items()) + map_names.push_back(map_name.string_value()); + + ostringstream text; + + for (string map_name : map_names) + text << "\t.include \"data/maps/" << map_name << "/header.inc\"\n"; + + return text.str(); +} + +string generate_events_text(Json groups_data) { + vector<string> map_names; + + for (auto &group : groups_data["group_order"].array_items()) + for (auto map_name : groups_data[group.string_value()].array_items()) + map_names.push_back(map_name.string_value()); + + ostringstream text; + + for (string map_name : map_names) + text << "\t.include \"data/maps/" << map_name << "/events.inc\"\n"; + + return text.str(); +} + +string generate_map_constants_text(string groups_filepath, Json groups_data) { + string file_dir = get_directory_name(groups_filepath); + char dir_separator = file_dir.back(); + + ostringstream text; + + text << "#ifndef GUARD_CONSTANTS_MAP_GROUPS_H\n" + << "#define GUARD_CONSTANTS_MAP_GROUPS_H\n\n"; + + int group_num = 0; + + for (auto &group : groups_data["group_order"].array_items()) { + text << "// Map Group " << group_num << "\n"; + vector<Json> map_ids; + size_t max_length = 0; + + for (auto &map_name : groups_data[group.string_value()].array_items()) { + string header_filepath = file_dir + map_name.string_value() + dir_separator + "map.json"; + string err_str; + Json map_data = Json::parse(read_text_file(header_filepath), err_str); + map_ids.push_back(map_data["id"]); + if (map_data["id"].string_value().length() > max_length) + max_length = map_data["id"].string_value().length(); + } + + int map_id_num = 0; + for (Json map_id : map_ids) { + text << "#define " << map_id.string_value() << string((max_length - map_id.string_value().length() + 1), ' ') + << "(" << map_id_num++ << " | (" << group_num << " << 8))\n"; + } + text << "\n"; + + group_num++; + } + + text << "#define MAP_GROUPS_COUNT " << group_num << "\n\n"; + text << "#endif // GUARD_CONSTANTS_MAP_GROUPS_H\n"; + + return text.str(); +} + +void process_groups(string groups_filepath) { + string err; + Json groups_data = Json::parse(read_text_file(groups_filepath), err); + + if (groups_data == Json()) + FATAL_ERROR("%s\n", err.c_str()); + + string groups_text = generate_groups_text(groups_data); + string connections_text = generate_connections_text(groups_data); + string headers_text = generate_headers_text(groups_data); + string events_text = generate_events_text(groups_data); + string map_header_text = generate_map_constants_text(groups_filepath, groups_data); + + string file_dir = get_directory_name(groups_filepath); + char s = file_dir.back(); + + write_text_file(file_dir + "groups.inc", groups_text); + write_text_file(file_dir + "connections.inc", connections_text); + write_text_file(file_dir + "headers.inc", headers_text); + write_text_file(file_dir + "events.inc", events_text); + write_text_file(file_dir + ".." + s + ".." + s + "include" + s + "constants" + s + "map_groups.h", map_header_text); +} + +string generate_layout_headers_text(Json layouts_data) { + ostringstream text; + + for (auto &layout : layouts_data["layouts"].array_items()) { + string border_label = layout["name"].string_value() + "_Border"; + string blockdata_label = layout["name"].string_value() + "_Blockdata"; + text << border_label << "::\n" + << "\t.incbin \"" << layout["border_filepath"].string_value() << "\"\n\n" + << blockdata_label << "::\n" + << "\t.incbin \"" << layout["blockdata_filepath"].string_value() << "\"\n\n" + << "\t.align 2\n" + << layout["name"].string_value() << "::\n" + << "\t.4byte " << layout["width"].int_value() << "\n" + << "\t.4byte " << layout["height"].int_value() << "\n" + << "\t.4byte " << border_label << "\n" + << "\t.4byte " << blockdata_label << "\n" + << "\t.4byte " << layout["primary_tileset"].string_value() << "\n" + << "\t.4byte " << layout["secondary_tileset"].string_value() << "\n\n"; + } + + return text.str(); +} + +string generate_layouts_table_text(Json layouts_data) { + ostringstream text; + + text << "\t.align 2\n" + << layouts_data["layouts_table_label"].string_value() << "::\n"; + + for (auto &layout : layouts_data["layouts"].array_items()) + text << "\t.4byte " << layout["name"].string_value() << "\n"; + + return text.str(); +} + +string generate_layouts_constants_text(Json layouts_data) { + ostringstream text; + + text << "#ifndef GUARD_CONSTANTS_LAYOUTS_H\n" + << "#define GUARD_CONSTANTS_LAYOUTS_H\n\n"; + + int i = 0; + for (auto &layout : layouts_data["layouts"].array_items()) + text << "#define " << layout["id"].string_value() << " " << ++i << "\n"; + + text << "\n#endif // GUARD_CONSTANTS_LAYOUTS_H\n"; + + return text.str(); +} + +void process_layouts(string layouts_filepath) { + string err; + Json layouts_data = Json::parse(read_text_file(layouts_filepath), err); + + if (layouts_data == Json()) + FATAL_ERROR("%s\n", err.c_str()); + + string layout_headers_text = generate_layout_headers_text(layouts_data); + string layouts_table_text = generate_layouts_table_text(layouts_data); + string layouts_constants_text = generate_layouts_constants_text(layouts_data); + + string file_dir = get_directory_name(layouts_filepath); + char s = file_dir.back(); + + write_text_file(file_dir + "layouts.inc", layout_headers_text); + write_text_file(file_dir + "layouts_table.inc", layouts_table_text); + write_text_file(file_dir + ".." + s + ".." + s + "include" + s + "constants" + s + "layouts.h", layouts_constants_text); +} + +int main(int argc, char *argv[]) { + if (argc < 3) + FATAL_ERROR("USAGE: mapjson <mode> <game-version> [options]\n"); + + char *version_arg = argv[2]; + string version(version_arg); + if (version != "emerald" && version != "ruby") + FATAL_ERROR("ERROR: <game-version> must be 'emerald' or 'ruby'.\n"); + + char *mode_arg = argv[1]; + string mode(mode_arg); + if (mode != "layouts" && mode != "map" && mode != "groups") + FATAL_ERROR("ERROR: <mode> must be 'layouts', 'map', or 'groups'.\n"); + + if (mode == "map") { + if (argc != 5) + FATAL_ERROR("USAGE: mapjson map <game-version> <map_file> <layouts_file>\n"); + + string filepath(argv[3]); + string layouts_filepath(argv[4]); + + process_map(filepath, layouts_filepath, version); + } + else if (mode == "groups") { + if (argc != 4) + FATAL_ERROR("USAGE: mapjson groups <game-version> <groups_file>\n"); + + string filepath(argv[3]); + + process_groups(filepath); + } + else if (mode == "layouts") { + if (argc != 4) + FATAL_ERROR("USAGE: mapjson layouts <game-version> <layouts_file>\n"); + + string filepath(argv[3]); + + process_layouts(filepath); + } + + return 0; +} diff --git a/tools/mapjson/mapjson.h b/tools/mapjson/mapjson.h new file mode 100755 index 0000000..6e961a2 --- /dev/null +++ b/tools/mapjson/mapjson.h @@ -0,0 +1,31 @@ +// mapjson.h + +#ifndef MAPJSON_H +#define MAPJSON_H + +#include <cstdio> +using std::fprintf; using std::exit; + +#include <cstdlib> + +#ifdef _MSC_VER + +#define FATAL_ERROR(format, ...) \ +do \ +{ \ + fprintf(stderr, format, __VA_ARGS__); \ + exit(1); \ +} while (0) + +#else + +#define FATAL_ERROR(format, ...) \ +do \ +{ \ + fprintf(stderr, format, ##__VA_ARGS__); \ + exit(1); \ +} while (0) + +#endif // _MSC_VER + +#endif // MAPJSON_H diff --git a/tools/mid2agb/.gitignore b/tools/mid2agb/.gitignore new file mode 100644 index 0000000..0e7264c --- /dev/null +++ b/tools/mid2agb/.gitignore @@ -0,0 +1 @@ +mid2agb diff --git a/tools/mid2agb/LICENSE b/tools/mid2agb/LICENSE new file mode 100644 index 0000000..534d153 --- /dev/null +++ b/tools/mid2agb/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2016 YamaArashi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/tools/mid2agb/Makefile b/tools/mid2agb/Makefile new file mode 100644 index 0000000..4dc2f12 --- /dev/null +++ b/tools/mid2agb/Makefile @@ -0,0 +1,18 @@ +CXX := g++ + +CXXFLAGS := -std=c++11 -O2 -s -Wall -Wno-switch -Werror + +SRCS := agb.cpp error.cpp main.cpp midi.cpp tables.cpp + +HEADERS := agb.h error.h main.h midi.h tables.h + +.PHONY: all clean + +all: mid2agb + @: + +mid2agb: $(SRCS) $(HEADERS) + $(CXX) $(CXXFLAGS) $(SRCS) -o $@ $(LDFLAGS) + +clean: + $(RM) mid2agb mid2agb.exe diff --git a/tools/mid2agb/agb.cpp b/tools/mid2agb/agb.cpp new file mode 100644 index 0000000..9ff1efa --- /dev/null +++ b/tools/mid2agb/agb.cpp @@ -0,0 +1,462 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include <cstdio> +#include <cstdarg> +#include <cstring> +#include <vector> +#include "agb.h" +#include "main.h" +#include "midi.h" +#include "tables.h" + +int g_agbTrack; + +static std::string s_lastOpName; +static int s_blockNum; +static bool s_keepLastOpName; +static int s_lastNote; +static int s_lastVelocity; +static bool s_noteChanged; +static bool s_velocityChanged; +static bool s_inPattern; +static int s_extendedCommand; + +void PrintAgbHeader() +{ + std::fprintf(g_outputFile, "\t.include \"MPlayDef.s\"\n\n"); + std::fprintf(g_outputFile, "\t.equ\t%s_grp, voicegroup%03u\n", g_asmLabel.c_str(), g_voiceGroup); + std::fprintf(g_outputFile, "\t.equ\t%s_pri, %u\n", g_asmLabel.c_str(), g_priority); + + if (g_reverb >= 0) + std::fprintf(g_outputFile, "\t.equ\t%s_rev, reverb_set+%u\n", g_asmLabel.c_str(), g_reverb); + else + std::fprintf(g_outputFile, "\t.equ\t%s_rev, 0\n", g_asmLabel.c_str()); + + std::fprintf(g_outputFile, "\t.equ\t%s_mvl, %u\n", g_asmLabel.c_str(), g_masterVolume); + std::fprintf(g_outputFile, "\t.equ\t%s_key, %u\n", g_asmLabel.c_str(), 0); + std::fprintf(g_outputFile, "\t.equ\t%s_tbs, %u\n", g_asmLabel.c_str(), g_clocksPerBeat); + std::fprintf(g_outputFile, "\t.equ\t%s_exg, %u\n", g_asmLabel.c_str(), g_exactGateTime); + std::fprintf(g_outputFile, "\t.equ\t%s_cmp, %u\n", g_asmLabel.c_str(), g_compressionEnabled); + + std::fprintf(g_outputFile, "\n\t.section .rodata\n"); + std::fprintf(g_outputFile, "\t.global\t%s\n", g_asmLabel.c_str()); + + std::fprintf(g_outputFile, "\t.align\t2\n"); +} + +void ResetTrackVars() +{ + s_lastVelocity = -1; + s_lastNote = -1; + s_velocityChanged = false; + s_noteChanged = false; + s_keepLastOpName = false; + s_lastOpName = ""; + s_inPattern = false; +} + +void PrintWait(int wait) +{ + if (wait > 0) + { + std::fprintf(g_outputFile, "\t.byte\tW%02d\n", wait); + s_velocityChanged = true; + s_noteChanged = true; + s_keepLastOpName = true; + } +} + +void PrintOp(int wait, std::string name, const char *format, ...) +{ + std::va_list args; + va_start(args, format); + std::fprintf(g_outputFile, "\t.byte\t\t"); + + if (format != nullptr) + { + if (!g_compressionEnabled || s_lastOpName != name) + { + std::fprintf(g_outputFile, "%s, ", name.c_str()); + s_lastOpName = name; + } + else + { + std::fprintf(g_outputFile, " "); + } + std::vfprintf(g_outputFile, format, args); + } + else + { + std::fputs(name.c_str(), g_outputFile); + s_lastOpName = name; + } + + std::fprintf(g_outputFile, "\n"); + + va_end(args); + + PrintWait(wait); +} + +void PrintByte(const char *format, ...) +{ + std::va_list args; + va_start(args, format); + std::fprintf(g_outputFile, "\t.byte\t"); + std::vfprintf(g_outputFile, format, args); + std::fprintf(g_outputFile, "\n"); + s_velocityChanged = true; + s_noteChanged = true; + s_keepLastOpName = true; + va_end(args); +} + +void PrintWord(const char *format, ...) +{ + std::va_list args; + va_start(args, format); + std::fprintf(g_outputFile, "\t .word\t"); + std::vfprintf(g_outputFile, format, args); + std::fprintf(g_outputFile, "\n"); + va_end(args); +} + +void PrintNote(const Event& event) +{ + int note = event.note; + int velocity = g_noteVelocityLUT[event.param1]; + int duration = -1; + + if (event.param2 != -1) + duration = g_noteDurationLUT[event.param2]; + + int gateTimeParam = 0; + + if (g_exactGateTime && duration != -1) + gateTimeParam = event.param2 - duration; + + char gtpBuf[16]; + + if (gateTimeParam > 0) + std::snprintf(gtpBuf, sizeof(gtpBuf), ", gtp%u", gateTimeParam); + else + gtpBuf[0] = 0; + + char opName[16]; + + if (duration == -1) + std::strcpy(opName, "TIE "); + else + std::snprintf(opName, sizeof(opName), "N%02u ", duration); + + bool noteChanged = true; + bool velocityChanged = true; + + if (g_compressionEnabled) + { + noteChanged = (note != s_lastNote); + velocityChanged = (velocity != s_lastVelocity); + } + + if (s_keepLastOpName) + s_keepLastOpName = false; + else + s_lastOpName = ""; + + if (noteChanged || velocityChanged || (gateTimeParam > 0)) + { + s_lastNote = note; + + char noteBuf[16]; + + if (note >= 24) + std::snprintf(noteBuf, sizeof(noteBuf), g_noteTable[note % 12], note / 12 - 2); + else + std::snprintf(noteBuf, sizeof(noteBuf), g_minusNoteTable[note % 12], note / -12 + 2); + + char velocityBuf[16]; + + if (velocityChanged || (gateTimeParam > 0)) + { + s_lastVelocity = velocity; + std::snprintf(velocityBuf, sizeof(velocityBuf), ", v%03u", velocity); + } + else + { + velocityBuf[0] = 0; + } + + PrintOp(event.time, opName, "%s%s%s", noteBuf, velocityBuf, gtpBuf); + } + else + { + PrintOp(event.time, opName, 0); + } + + s_noteChanged = noteChanged; + s_velocityChanged = velocityChanged; +} + +void PrintEndOfTieOp(const Event& event) +{ + int note = event.note; + bool noteChanged = (note != s_lastNote); + + if (!noteChanged || !s_noteChanged) + s_lastOpName = ""; + + if (!noteChanged && g_compressionEnabled) + { + PrintOp(event.time, "EOT ", nullptr); + } + else + { + s_lastNote = note; + if (note >= 24) + PrintOp(event.time, "EOT ", g_noteTable[note % 12], note / 12 - 2); + else + PrintOp(event.time, "EOT ", g_minusNoteTable[note % 12], note / -12 + 2); + } + + s_noteChanged = noteChanged; +} + +void PrintSeqLoopLabel(const Event& event) +{ + s_blockNum = event.param1 + 1; + std::fprintf(g_outputFile, "%s_%u_B%u:\n", g_asmLabel.c_str(), g_agbTrack, s_blockNum); + PrintWait(event.time); + ResetTrackVars(); +} + +void PrintExtendedOp(const Event& event) +{ + // TODO: support for other extended commands + + switch (s_extendedCommand) + { + case 0x08: + PrintOp(event.time, "XCMD ", "xIECV , %u", event.param2); + break; + case 0x09: + PrintOp(event.time, "XCMD ", "xIECL , %u", event.param2); + break; + default: + PrintWait(event.time); + break; + } +} + +void PrintControllerOp(const Event& event) +{ + switch (event.param1) + { + case 0x01: + PrintOp(event.time, "MOD ", "%u", event.param2); + break; + case 0x07: + PrintOp(event.time, "VOL ", "%u*%s_mvl/mxv", event.param2, g_asmLabel.c_str()); + break; + case 0x0A: + PrintOp(event.time, "PAN ", "c_v%+d", event.param2 - 64); + break; + case 0x0C: + case 0x10: + // TODO: memacc + break; + case 0x0D: + // TODO: memacc var + break; + case 0x0E: + // TODO: memacc var + break; + case 0x0F: + // TODO: memacc var + break; + case 0x11: + std::fprintf(g_outputFile, "%s_%u_L%u:\n", g_asmLabel.c_str(), g_agbTrack, event.param2); + PrintWait(event.time); + ResetTrackVars(); + break; + case 0x14: + PrintOp(event.time, "BENDR ", "%u", event.param2); + break; + case 0x15: + PrintOp(event.time, "LFOS ", "%u", event.param2); + break; + case 0x16: + PrintOp(event.time, "MODT ", "%u", event.param2); + break; + case 0x18: + PrintOp(event.time, "TUNE ", "c_v%+d", event.param2 - 64); + break; + case 0x1A: + PrintOp(event.time, "LFODL ", "%u", event.param2); + break; + case 0x1D: + case 0x1F: + PrintExtendedOp(event); + break; + case 0x1E: + s_extendedCommand = event.param2; + // TODO: loop op + break; + case 0x21: + case 0x27: + PrintByte("PRIO , %u", event.param2); + PrintWait(event.time); + break; + default: + PrintWait(event.time); + break; + } +} + +void PrintAgbTrack(std::vector<Event>& events) +{ + std::fprintf(g_outputFile, "\n@**************** Track %u (Midi-Chn.%u) ****************@\n\n", g_agbTrack, g_midiChan + 1); + std::fprintf(g_outputFile, "%s_%u:\n", g_asmLabel.c_str(), g_agbTrack); + PrintWait(g_initialWait); + PrintByte("KEYSH , %s_key%+d", g_asmLabel.c_str(), 0); + + int wholeNoteCount = 0; + int loopEndBlockNum = 0; + + ResetTrackVars(); + + bool foundVolBeforeNote = false; + + for (const Event& event : events) + { + if (event.type == EventType::Note) + break; + + if (event.type == EventType::Controller && event.param1 == 0x07) + { + foundVolBeforeNote = true; + break; + } + } + + if (!foundVolBeforeNote) + PrintByte("\tVOL , 127*%s_mvl/mxv", g_asmLabel.c_str()); + + for (unsigned i = 0; events[i].type != EventType::EndOfTrack; i++) + { + const Event& event = events[i]; + + if (IsPatternBoundary(event.type)) + { + if (s_inPattern) + PrintByte("PEND"); + s_inPattern = false; + } + + if (event.type == EventType::WholeNoteMark || event.type == EventType::Pattern) + std::fprintf(g_outputFile, "@ %03d ----------------------------------------\n", wholeNoteCount++); + + switch (event.type) + { + case EventType::Note: + PrintNote(event); + break; + case EventType::EndOfTie: + PrintEndOfTieOp(event); + break; + case EventType::Label: + PrintSeqLoopLabel(event); + break; + case EventType::LoopEnd: + PrintByte("GOTO"); + PrintWord("%s_%u_B%u", g_asmLabel.c_str(), g_agbTrack, loopEndBlockNum); + PrintSeqLoopLabel(event); + break; + case EventType::LoopEndBegin: + PrintByte("GOTO"); + PrintWord("%s_%u_B%u", g_asmLabel.c_str(), g_agbTrack, loopEndBlockNum); + PrintSeqLoopLabel(event); + loopEndBlockNum = s_blockNum; + break; + case EventType::LoopBegin: + PrintSeqLoopLabel(event); + loopEndBlockNum = s_blockNum; + break; + case EventType::WholeNoteMark: + if (event.param2 & 0x80000000) + { + std::fprintf(g_outputFile, "%s_%u_%03lu:\n", g_asmLabel.c_str(), g_agbTrack, (unsigned long)(event.param2 & 0x7FFFFFFF)); + ResetTrackVars(); + s_inPattern = true; + } + PrintWait(event.time); + break; + case EventType::Pattern: + PrintByte("PATT"); + PrintWord("%s_%u_%03lu", g_asmLabel.c_str(), g_agbTrack, event.param2); + + while (!IsPatternBoundary(events[i + 1].type)) + i++; + + ResetTrackVars(); + break; + case EventType::Tempo: + PrintByte("TEMPO , %u*%s_tbs/2", 60000000 / event.param2, g_asmLabel.c_str()); + PrintWait(event.time); + break; + case EventType::InstrumentChange: + PrintOp(event.time, "VOICE ", "%u", event.param1); + break; + case EventType::PitchBend: + PrintOp(event.time, "BEND ", "c_v%+d", event.param2 - 64); + break; + case EventType::Controller: + PrintControllerOp(event); + break; + default: + PrintWait(event.time); + break; + } + } + + PrintByte("FINE"); +} + +void PrintAgbFooter() +{ + int trackCount = g_agbTrack - 1; + + std::fprintf(g_outputFile, "\n@******************************************************@\n"); + std::fprintf(g_outputFile, "\t.align\t2\n"); + std::fprintf(g_outputFile, "\n%s:\n", g_asmLabel.c_str()); + std::fprintf(g_outputFile, "\t.byte\t%u\t@ NumTrks\n", trackCount); + std::fprintf(g_outputFile, "\t.byte\t%u\t@ NumBlks\n", 0); + std::fprintf(g_outputFile, "\t.byte\t%s_pri\t@ Priority\n", g_asmLabel.c_str()); + std::fprintf(g_outputFile, "\t.byte\t%s_rev\t@ Reverb.\n", g_asmLabel.c_str()); + std::fprintf(g_outputFile, "\n"); + std::fprintf(g_outputFile, "\t.word\t%s_grp\n", g_asmLabel.c_str()); + std::fprintf(g_outputFile, "\n"); + + // track pointers + for (int i = 1; i <= trackCount; i++) + std::fprintf(g_outputFile, "\t.word\t%s_%u\n", g_asmLabel.c_str(), i); + + std::fprintf(g_outputFile, "\n\t.end\n"); +} diff --git a/tools/mid2agb/agb.h b/tools/mid2agb/agb.h new file mode 100644 index 0000000..7eab3c1 --- /dev/null +++ b/tools/mid2agb/agb.h @@ -0,0 +1,33 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef AGB_H +#define AGB_H + +#include <vector> +#include "midi.h" + +void PrintAgbHeader(); +void PrintAgbTrack(std::vector<Event>& events); +void PrintAgbFooter(); + +extern int g_agbTrack; + +#endif // AGB_H diff --git a/tools/mid2agb/error.cpp b/tools/mid2agb/error.cpp new file mode 100644 index 0000000..13e38ff --- /dev/null +++ b/tools/mid2agb/error.cpp @@ -0,0 +1,36 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include <cstdio> +#include <cstdlib> +#include <cstdarg> + +// Reports an error diagnostic and terminates the program. +[[noreturn]] void RaiseError(const char* format, ...) +{ + const int bufferSize = 1024; + char buffer[bufferSize]; + std::va_list args; + va_start(args, format); + std::vsnprintf(buffer, bufferSize, format, args); + std::fprintf(stderr, "error: %s\n", buffer); + va_end(args); + std::exit(1); +} diff --git a/tools/mid2agb/error.h b/tools/mid2agb/error.h new file mode 100644 index 0000000..da4f011 --- /dev/null +++ b/tools/mid2agb/error.h @@ -0,0 +1,26 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef ERROR_H +#define ERROR_H + +[[noreturn]] void RaiseError(const char* format, ...); + +#endif // ERROR_H diff --git a/tools/mid2agb/main.cpp b/tools/mid2agb/main.cpp new file mode 100644 index 0000000..03feabd --- /dev/null +++ b/tools/mid2agb/main.cpp @@ -0,0 +1,228 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <cctype> +#include <cassert> +#include <string> +#include <set> +#include "main.h" +#include "error.h" +#include "midi.h" +#include "agb.h" + +FILE* g_inputFile = nullptr; +FILE* g_outputFile = nullptr; + +std::string g_asmLabel; +int g_masterVolume = 127; +int g_voiceGroup = 0; +int g_priority = 0; +int g_reverb = -1; +int g_clocksPerBeat = 1; +bool g_exactGateTime = false; +bool g_compressionEnabled = true; + +[[noreturn]] static void PrintUsage() +{ + std::printf( + "Usage: MID2AGB name [options]\n" + "\n" + " input_file filename(.mid) of MIDI file\n" + " output_file filename(.s) for AGB file (default:input_file)\n" + "\n" + "options -L??? label for assembler (default:output_file)\n" + " -V??? master volume (default:127)\n" + " -G??? voice group number (default:0)\n" + " -P??? priority (default:0)\n" + " -R??? reverb (default:off)\n" + " -X 48 clocks/beat (default:24 clocks/beat)\n" + " -E exact gate-time\n" + " -N no compression\n" + ); + std::exit(1); +} + +static std::string StripExtension(std::string s) +{ + std::size_t pos = s.find_last_of('.'); + + if (pos > 0 && pos != std::string::npos) + { + s = s.substr(0, pos); + } + + return s; +} + +static std::string GetExtension(std::string s) +{ + std::size_t pos = s.find_last_of('.'); + + if (pos > 0 && pos != std::string::npos) + { + return s.substr(pos + 1); + } + + return ""; +} + +static std::string BaseName(std::string s) +{ + std::size_t posAfterSlash = s.find_last_of("/\\"); + + if (posAfterSlash == std::string::npos) + posAfterSlash = 0; + else + posAfterSlash++; + + std::size_t dotPos = s.find_first_of('.', posAfterSlash); + if (dotPos > posAfterSlash && dotPos != std::string::npos) + s = s.substr(posAfterSlash, dotPos - posAfterSlash); + + return s; +} + +static const char *GetArgument(int argc, char **argv, int& index) +{ + assert(index >= 0 && index < argc); + + const char *option = argv[index]; + + assert(option != nullptr); + assert(option[0] == '-'); + + // If there is text following the letter, return that. + if (std::strlen(option) >= 3) + return option + 2; + + // Otherwise, try to get the next arg. + if (index + 1 < argc) + { + index++; + return argv[index]; + } + else + { + return nullptr; + } +} + +int main(int argc, char** argv) +{ + std::string inputFilename; + std::string outputFilename; + + for (int i = 1; i < argc; i++) + { + const char *option = argv[i]; + + if (option[0] == '-' && option[1] != '\0') + { + const char *arg = GetArgument(argc, argv, i); + + switch (std::toupper(option[1])) + { + case 'E': + g_exactGateTime = true; + break; + case 'G': + if (arg == nullptr) + PrintUsage(); + g_voiceGroup = std::stoi(arg); + break; + case 'L': + if (arg == nullptr) + PrintUsage(); + g_asmLabel = std::stoi(arg); + break; + case 'N': + g_compressionEnabled = false; + break; + case 'P': + if (arg == nullptr) + PrintUsage(); + g_priority = std::stoi(arg); + break; + case 'R': + if (arg == nullptr) + PrintUsage(); + g_reverb = std::stoi(arg); + break; + case 'V': + if (arg == nullptr) + PrintUsage(); + g_masterVolume = std::stoi(arg); + break; + case 'X': + g_clocksPerBeat = 2; + break; + default: + PrintUsage(); + } + } + else + { + if (inputFilename.empty()) + inputFilename = argv[i]; + else if (outputFilename.empty()) + outputFilename = argv[i]; + else + PrintUsage(); + } + } + + if (inputFilename.empty()) + PrintUsage(); + + if (GetExtension(inputFilename) != "mid") + RaiseError("input filename extension is not \"mid\""); + + if (outputFilename.empty()) + outputFilename = StripExtension(inputFilename) + ".s"; + + if (GetExtension(outputFilename) != "s") + RaiseError("output filename extension is not \"s\""); + + if (g_asmLabel.empty()) + g_asmLabel = BaseName(outputFilename); + + g_inputFile = std::fopen(inputFilename.c_str(), "rb"); + + if (g_inputFile == nullptr) + RaiseError("failed to open \"%s\" for reading", inputFilename.c_str()); + + g_outputFile = std::fopen(outputFilename.c_str(), "w"); + + if (g_outputFile == nullptr) + RaiseError("failed to open \"%s\" for writing", outputFilename.c_str()); + + ReadMidiFileHeader(); + PrintAgbHeader(); + ReadMidiTracks(); + PrintAgbFooter(); + + std::fclose(g_inputFile); + std::fclose(g_outputFile); + + return 0; +} diff --git a/tools/mid2agb/main.h b/tools/mid2agb/main.h new file mode 100644 index 0000000..6e71e73 --- /dev/null +++ b/tools/mid2agb/main.h @@ -0,0 +1,39 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef MAIN_H +#define MAIN_H + +#include <cstdio> +#include <string> + +extern FILE* g_inputFile; +extern FILE* g_outputFile; + +extern std::string g_asmLabel; +extern int g_masterVolume; +extern int g_voiceGroup; +extern int g_priority; +extern int g_reverb; +extern int g_clocksPerBeat; +extern bool g_exactGateTime; +extern bool g_compressionEnabled; + +#endif // MAIN_H diff --git a/tools/mid2agb/midi.cpp b/tools/mid2agb/midi.cpp new file mode 100644 index 0000000..09480e1 --- /dev/null +++ b/tools/mid2agb/midi.cpp @@ -0,0 +1,958 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include <cstdio> +#include <cassert> +#include <string> +#include <vector> +#include <algorithm> +#include <memory> +#include "midi.h" +#include "main.h" +#include "error.h" +#include "agb.h" +#include "tables.h" + +enum class MidiEventCategory +{ + Control, + SysEx, + Meta, + Invalid, +}; + +MidiFormat g_midiFormat; +std::int_fast32_t g_midiTrackCount; +std::int16_t g_midiTimeDiv; + +int g_midiChan; +std::int32_t g_initialWait; + +static long s_trackDataStart; +static std::vector<Event> s_seqEvents; +static std::vector<Event> s_trackEvents; +static std::int32_t s_absoluteTime; +static int s_blockCount = 0; +static int s_minNote; +static int s_maxNote; +static int s_runningStatus; + +void Seek(long offset) +{ + if (std::fseek(g_inputFile, offset, SEEK_SET) != 0) + RaiseError("failed to seek to %l", offset); +} + +void Skip(long offset) +{ + if (std::fseek(g_inputFile, offset, SEEK_CUR) != 0) + RaiseError("failed to skip %l bytes", offset); +} + +std::string ReadSignature() +{ + char signature[4]; + + if (std::fread(signature, 4, 1, g_inputFile) != 1) + RaiseError("failed to read signature"); + + return std::string(signature, 4); +} + +std::uint32_t ReadInt8() +{ + int c = std::fgetc(g_inputFile); + + if (c < 0) + RaiseError("unexpected EOF"); + + return c; +} + +std::uint32_t ReadInt16() +{ + std::uint32_t val = 0; + val |= ReadInt8() << 8; + val |= ReadInt8(); + return val; +} + +std::uint32_t ReadInt24() +{ + std::uint32_t val = 0; + val |= ReadInt8() << 16; + val |= ReadInt8() << 8; + val |= ReadInt8(); + return val; +} + +std::uint32_t ReadInt32() +{ + std::uint32_t val = 0; + val |= ReadInt8() << 24; + val |= ReadInt8() << 16; + val |= ReadInt8() << 8; + val |= ReadInt8(); + return val; +} + +std::uint32_t ReadVLQ() +{ + std::uint32_t val = 0; + std::uint32_t c; + + do + { + c = ReadInt8(); + val <<= 7; + val |= (c & 0x7F); + } while (c & 0x80); + + return val; +} + +void ReadMidiFileHeader() +{ + Seek(0); + + if (ReadSignature() != "MThd") + RaiseError("MIDI file header signature didn't match \"MThd\""); + + std::uint32_t headerLength = ReadInt32(); + + if (headerLength != 6) + RaiseError("MIDI file header length isn't 6"); + + std::uint16_t midiFormat = ReadInt16(); + + if (midiFormat >= 2) + RaiseError("unsupported MIDI format (%u)", midiFormat); + + g_midiFormat = (MidiFormat)midiFormat; + g_midiTrackCount = ReadInt16(); + g_midiTimeDiv = ReadInt16(); + + if (g_midiTimeDiv < 0) + RaiseError("unsupported MIDI time division (%d)", g_midiTimeDiv); +} + +long ReadMidiTrackHeader(long offset) +{ + Seek(offset); + + if (ReadSignature() != "MTrk") + RaiseError("MIDI track header signature didn't match \"MTrk\""); + + long size = ReadInt32(); + + s_trackDataStart = std::ftell(g_inputFile); + + return size + 8; +} + +void StartTrack() +{ + Seek(s_trackDataStart); + s_absoluteTime = 0; + s_runningStatus = 0; +} + +void SkipEventData() +{ + Skip(ReadVLQ()); +} + +void DetermineEventCategory(MidiEventCategory& category, int& typeChan, int& size) +{ + typeChan = ReadInt8(); + + if (typeChan < 0x80) + { + // If data byte was found, use the running status. + ungetc(typeChan, g_inputFile); + typeChan = s_runningStatus; + } + + if (typeChan == 0xFF) + { + category = MidiEventCategory::Meta; + size = 0; + s_runningStatus = 0; + } + else if (typeChan >= 0xF0) + { + category = MidiEventCategory::SysEx; + size = 0; + s_runningStatus = 0; + } + else if (typeChan >= 0x80) + { + category = MidiEventCategory::Control; + + switch (typeChan >> 4) + { + case 0xC: + case 0xD: + size = 1; + break; + default: + size = 2; + break; + } + s_runningStatus = typeChan; + } + else + { + category = MidiEventCategory::Invalid; + } +} + +void MakeBlockEvent(Event& event, EventType type) +{ + event.type = type; + event.param1 = s_blockCount++; + event.param2 = 0; +} + +std::string ReadEventText() +{ + char buffer[2]; + std::uint32_t length = ReadVLQ(); + + if (length <= 2) + { + if (fread(buffer, length, 1, g_inputFile) != 1) + RaiseError("failed to read event text"); + } + else + { + Skip(length); + length = 0; + } + + return std::string(buffer, length); +} + +bool ReadSeqEvent(Event& event) +{ + s_absoluteTime += ReadVLQ(); + event.time = s_absoluteTime; + + MidiEventCategory category; + int typeChan; + int size; + + DetermineEventCategory(category, typeChan, size); + + if (category == MidiEventCategory::Control) + { + Skip(size); + return false; + } + + if (category == MidiEventCategory::SysEx) + { + SkipEventData(); + return false; + } + + if (category == MidiEventCategory::Invalid) + RaiseError("invalid event"); + + // meta event + int metaEventType = ReadInt8(); + + if (metaEventType >= 1 && metaEventType <= 7) + { + // text event + std::string text = ReadEventText(); + + if (text == "[") + MakeBlockEvent(event, EventType::LoopBegin); + else if (text == "][") + MakeBlockEvent(event, EventType::LoopEndBegin); + else if (text == "]") + MakeBlockEvent(event, EventType::LoopEnd); + else if (text == ":") + MakeBlockEvent(event, EventType::Label); + else + return false; + } + else + { + switch (metaEventType) + { + case 0x2F: // end of track + SkipEventData(); + event.type = EventType::EndOfTrack; + event.param1 = 0; + event.param2 = 0; + break; + case 0x51: // tempo + if (ReadVLQ() != 3) + RaiseError("invalid tempo size"); + + event.type = EventType::Tempo; + event.param1 = 0; + event.param2 = ReadInt24(); + break; + case 0x58: // time signature + { + if (ReadVLQ() != 4) + RaiseError("invalid time signature size"); + + int numerator = ReadInt8(); + int denominatorExponent = ReadInt8(); + + if (denominatorExponent >= 16) + RaiseError("invalid time signature denominator"); + + Skip(2); // ignore other values + + int clockTicks = 96 * numerator * g_clocksPerBeat; + int denominator = 1 << denominatorExponent; + int timeSig = clockTicks / denominator; + + if (timeSig <= 0 || timeSig >= 0x10000) + RaiseError("invalid time signature"); + + event.type = EventType::TimeSignature; + event.param1 = 0; + event.param2 = timeSig; + break; + } + default: + SkipEventData(); + return false; + } + } + + return true; +} + +void ReadSeqEvents() +{ + StartTrack(); + + for (;;) + { + Event event = {}; + + if (ReadSeqEvent(event)) + { + s_seqEvents.push_back(event); + + if (event.type == EventType::EndOfTrack) + return; + } + } +} + +bool CheckNoteEnd(Event& event) +{ + event.param2 += ReadVLQ(); + + MidiEventCategory category; + int typeChan; + int size; + + DetermineEventCategory(category, typeChan, size); + + if (category == MidiEventCategory::Control) + { + int chan = typeChan & 0xF; + + if (chan != g_midiChan) + { + Skip(size); + return false; + } + + switch (typeChan & 0xF0) + { + case 0x80: // note off + { + int note = ReadInt8(); + ReadInt8(); // ignore velocity + if (note == event.note) + return true; + break; + } + case 0x90: // note on + { + int note = ReadInt8(); + int velocity = ReadInt8(); + if (velocity == 0 && note == event.note) + return true; + break; + } + default: + Skip(size); + break; + } + + return false; + } + + if (category == MidiEventCategory::SysEx) + { + SkipEventData(); + return false; + } + + if (category == MidiEventCategory::Meta) + { + int metaEventType = ReadInt8(); + SkipEventData(); + + if (metaEventType == 0x2F) + RaiseError("note doesn't end"); + + return false; + } + + RaiseError("invalid event"); +} + +void FindNoteEnd(Event& event) +{ + // Save the current file position and running status + // which get modified by CheckNoteEnd. + long startPos = ftell(g_inputFile); + int savedRunningStatus = s_runningStatus; + + event.param2 = 0; + + while (!CheckNoteEnd(event)) + ; + + Seek(startPos); + s_runningStatus = savedRunningStatus; +} + +bool ReadTrackEvent(Event& event) +{ + s_absoluteTime += ReadVLQ(); + event.time = s_absoluteTime; + + MidiEventCategory category; + int typeChan; + int size; + + DetermineEventCategory(category, typeChan, size); + + if (category == MidiEventCategory::Control) + { + int chan = typeChan & 0xF; + + if (chan != g_midiChan) + { + Skip(size); + return false; + } + + switch (typeChan & 0xF0) + { + case 0x90: // note on + { + int note = ReadInt8(); + int velocity = ReadInt8(); + + if (velocity != 0) + { + event.type = EventType::Note; + event.note = note; + event.param1 = velocity; + FindNoteEnd(event); + if (event.param2 > 0) + { + if (note < s_minNote) + s_minNote = note; + if (note > s_maxNote) + s_maxNote = note; + } + } + break; + } + case 0xB0: // controller event + event.type = EventType::Controller; + event.param1 = ReadInt8(); // controller index + event.param2 = ReadInt8(); // value + break; + case 0xC0: // instrument change + event.type = EventType::InstrumentChange; + event.param1 = ReadInt8(); // instrument + event.param2 = 0; + break; + case 0xE0: // pitch bend + event.type = EventType::PitchBend; + event.param1 = ReadInt8(); + event.param2 = ReadInt8(); + break; + default: + Skip(size); + return false; + } + + return true; + } + + if (category == MidiEventCategory::SysEx) + { + SkipEventData(); + return false; + } + + if (category == MidiEventCategory::Meta) + { + int metaEventType = ReadInt8(); + SkipEventData(); + + if (metaEventType == 0x2F) + { + event.type = EventType::EndOfTrack; + event.param1 = 0; + event.param2 = 0; + return true; + } + + return false; + } + + RaiseError("invalid event"); +} + +void ReadTrackEvents() +{ + StartTrack(); + + s_trackEvents.clear(); + + s_minNote = 0xFF; + s_maxNote = 0; + + for (;;) + { + Event event = {}; + + if (ReadTrackEvent(event)) + { + s_trackEvents.push_back(event); + + if (event.type == EventType::EndOfTrack) + return; + } + } +} + +bool EventCompare(const Event& event1, const Event& event2) +{ + if (event1.time < event2.time) + return true; + + if (event1.time > event2.time) + return false; + + unsigned event1Type = (unsigned)event1.type; + unsigned event2Type = (unsigned)event2.type; + + if (event1.type == EventType::Note) + event1Type += event1.note; + + if (event2.type == EventType::Note) + event2Type += event2.note; + + if (event1Type < event2Type) + return true; + + if (event1Type > event2Type) + return false; + + if (event1.type == EventType::EndOfTie) + { + if (event1.note < event2.note) + return true; + + if (event1.note > event2.note) + return false; + } + + return false; +} + +std::unique_ptr<std::vector<Event>> MergeEvents() +{ + std::unique_ptr<std::vector<Event>> events(new std::vector<Event>()); + + unsigned trackEventPos = 0; + unsigned seqEventPos = 0; + + while (s_trackEvents[trackEventPos].type != EventType::EndOfTrack + && s_seqEvents[seqEventPos].type != EventType::EndOfTrack) + { + if (EventCompare(s_trackEvents[trackEventPos], s_seqEvents[seqEventPos])) + events->push_back(s_trackEvents[trackEventPos++]); + else + events->push_back(s_seqEvents[seqEventPos++]); + } + + while (s_trackEvents[trackEventPos].type != EventType::EndOfTrack) + events->push_back(s_trackEvents[trackEventPos++]); + + while (s_seqEvents[seqEventPos].type != EventType::EndOfTrack) + events->push_back(s_seqEvents[seqEventPos++]); + + // Push the EndOfTrack event with the larger time. + if (EventCompare(s_trackEvents[trackEventPos], s_seqEvents[seqEventPos])) + events->push_back(s_seqEvents[seqEventPos]); + else + events->push_back(s_trackEvents[trackEventPos]); + + return events; +} + +void ConvertTimes(std::vector<Event>& events) +{ + for (Event& event : events) + { + event.time = (24 * g_clocksPerBeat * event.time) / g_midiTimeDiv; + + if (event.type == EventType::Note) + { + event.param1 = g_noteVelocityLUT[event.param1]; + + std::uint32_t duration = (24 * g_clocksPerBeat * event.param2) / g_midiTimeDiv; + + if (duration == 0) + duration = 1; + + if (!g_exactGateTime && duration < 96) + duration = g_noteDurationLUT[duration]; + + event.param2 = duration; + } + } +} + +std::unique_ptr<std::vector<Event>> InsertTimingEvents(std::vector<Event>& inEvents) +{ + std::unique_ptr<std::vector<Event>> outEvents(new std::vector<Event>()); + + Event timingEvent = {}; + timingEvent.time = 0; + timingEvent.type = EventType::TimeSignature; + timingEvent.param2 = 96 * g_clocksPerBeat; + + for (const Event& event : inEvents) + { + while (EventCompare(timingEvent, event)) + { + outEvents->push_back(timingEvent); + timingEvent.time += timingEvent.param2; + } + + if (event.type == EventType::TimeSignature) + { + if (g_agbTrack == 1 && event.param2 != timingEvent.param2) + { + Event originalTimingEvent = event; + originalTimingEvent.type = EventType::OriginalTimeSignature; + outEvents->push_back(originalTimingEvent); + } + timingEvent.param2 = event.param2; + timingEvent.time = event.time + timingEvent.param2; + } + + outEvents->push_back(event); + } + + return outEvents; +} + +std::unique_ptr<std::vector<Event>> SplitTime(std::vector<Event>& inEvents) +{ + std::unique_ptr<std::vector<Event>> outEvents(new std::vector<Event>()); + + std::int32_t time = 0; + + for (const Event& event : inEvents) + { + std::int32_t diff = event.time - time; + + if (diff > 96) + { + int wholeNoteCount = (diff - 1) / 96; + diff -= 96 * wholeNoteCount; + + for (int i = 0; i < wholeNoteCount; i++) + { + time += 96; + Event timeSplitEvent = {}; + timeSplitEvent.time = time; + timeSplitEvent.type = EventType::TimeSplit; + outEvents->push_back(timeSplitEvent); + } + } + + std::int32_t lutValue = g_noteDurationLUT[diff]; + + if (lutValue != diff) + { + Event timeSplitEvent = {}; + timeSplitEvent.time = time + lutValue; + timeSplitEvent.type = EventType::TimeSplit; + outEvents->push_back(timeSplitEvent); + } + + time = event.time; + + outEvents->push_back(event); + } + + return outEvents; +} + +std::unique_ptr<std::vector<Event>> CreateTies(std::vector<Event>& inEvents) +{ + std::unique_ptr<std::vector<Event>> outEvents(new std::vector<Event>()); + + for (const Event& event : inEvents) + { + if (event.type == EventType::Note && event.param2 > 96) + { + Event tieEvent = event; + tieEvent.param2 = -1; + outEvents->push_back(tieEvent); + + Event eotEvent = {}; + eotEvent.time = event.time + event.param2; + eotEvent.type = EventType::EndOfTie; + eotEvent.note = event.note; + outEvents->push_back(eotEvent); + } + else + { + outEvents->push_back(event); + } + } + + return outEvents; +} + +void CalculateWaits(std::vector<Event>& events) +{ + g_initialWait = events[0].time; + int wholeNoteCount = 0; + + for (unsigned i = 0; i < events.size() && events[i].type != EventType::EndOfTrack; i++) + { + events[i].time = events[i + 1].time - events[i].time; + + if (events[i].type == EventType::TimeSignature) + { + events[i].type = EventType::WholeNoteMark; + events[i].param2 = wholeNoteCount++; + } + } +} + +int CalculateCompressionScore(std::vector<Event>& events, int index) +{ + int score = 0; + std::uint8_t lastParam1 = events[index].param1; + std::uint8_t lastVelocity = 0x80u; + EventType lastType = events[index].type; + std::int32_t lastDuration = 0x80000000; + std::uint8_t lastNote = 0x80u; + + if (events[index].time > 0) + score++; + + for (int i = index + 1; !IsPatternBoundary(events[i].type); i++) + { + if (events[i].type == EventType::Note) + { + int val = 0; + + if (events[i].note != lastNote) + { + val++; + lastNote = events[i].note; + } + + if (events[i].param1 != lastVelocity) + { + val++; + lastVelocity = events[i].param1; + } + + std::int32_t duration = events[i].param2; + + if (g_noteDurationLUT[duration] != lastDuration) + { + val++; + lastDuration = g_noteDurationLUT[duration]; + } + + if (duration != lastDuration) + val++; + + if (val == 0) + val = 1; + + score += val; + } + else + { + lastDuration = 0x80000000; + + if (events[i].type == lastType) + { + if ((lastType != EventType::Controller && (int)lastType != 0x25 && lastType != EventType::EndOfTie) || events[i].param1 == lastParam1) + { + score++; + } + else + { + score += 2; + } + } + else + { + score += 2; + } + } + + lastParam1 = events[i].param1; + lastType = events[i].type; + + if (events[i].time) + ++score; + } + + return score; +} + +bool IsCompressionMatch(std::vector<Event>& events, int index1, int index2) +{ + index1++; + index2++; + + do + { + if (events[index1] != events[index2]) + return false; + + index1++; + index2++; + } while (!IsPatternBoundary(events[index1].type)); + + return IsPatternBoundary(events[index2].type); +} + +void CompressWholeNote(std::vector<Event>& events, int index) +{ + for (int j = index + 1; events[j].type != EventType::EndOfTrack; j++) + { + while (events[j].type != EventType::WholeNoteMark) + { + j++; + + if (events[j].type == EventType::EndOfTrack) + return; + } + + if (IsCompressionMatch(events, index, j)) + { + events[j].type = EventType::Pattern; + events[j].param2 = events[index].param2 & 0x7FFFFFFF; + events[index].param2 |= 0x80000000; + } + } +} + +void Compress(std::vector<Event>& events) +{ + for (int i = 0; events[i].type != EventType::EndOfTrack; i++) + { + while (events[i].type != EventType::WholeNoteMark) + { + i++; + + if (events[i].type == EventType::EndOfTrack) + return; + } + + if (CalculateCompressionScore(events, i) >= 6) + { + CompressWholeNote(events, i); + } + } +} + +void ReadMidiTracks() +{ + long trackHeaderStart = 14; + + ReadMidiTrackHeader(trackHeaderStart); + ReadSeqEvents(); + + g_agbTrack = 1; + + for (int midiTrack = 0; midiTrack < g_midiTrackCount; midiTrack++) + { + trackHeaderStart += ReadMidiTrackHeader(trackHeaderStart); + + for (g_midiChan = 0; g_midiChan < 16; g_midiChan++) + { + ReadTrackEvents(); + + if (s_minNote != 0xFF) + { +#ifdef DEBUG + printf("Track%d = Midi-Ch.%d\n", g_agbTrack, g_midiChan + 1); +#endif + + std::unique_ptr<std::vector<Event>> events(MergeEvents()); + + // We don't need TEMPO in anything but track 1. + if (g_agbTrack == 1) + { + auto it = std::remove_if(s_seqEvents.begin(), s_seqEvents.end(), [](const Event& event) { return event.type == EventType::Tempo; }); + s_seqEvents.erase(it, s_seqEvents.end()); + } + + ConvertTimes(*events); + events = InsertTimingEvents(*events); + events = CreateTies(*events); + std::stable_sort(events->begin(), events->end(), EventCompare); + events = SplitTime(*events); + CalculateWaits(*events); + + if (g_compressionEnabled) + Compress(*events); + + PrintAgbTrack(*events); + + g_agbTrack++; + } + } + } +} diff --git a/tools/mid2agb/midi.h b/tools/mid2agb/midi.h new file mode 100644 index 0000000..434c8e8 --- /dev/null +++ b/tools/mid2agb/midi.h @@ -0,0 +1,87 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef MIDI_H +#define MIDI_H + +#include <cstdint> + +enum class MidiFormat +{ + SingleTrack, + MultiTrack +}; + +enum class EventType +{ + EndOfTie = 0x01, + Label = 0x11, + LoopEnd = 0x12, + LoopEndBegin = 0x13, + LoopBegin = 0x14, + OriginalTimeSignature = 0x15, + WholeNoteMark = 0x16, + Pattern = 0x17, + TimeSignature = 0x18, + Tempo = 0x19, + InstrumentChange = 0x21, + Controller = 0x22, + PitchBend = 0x23, + KeyShift = 0x31, + Note = 0x40, + TimeSplit = 0xFE, + EndOfTrack = 0xFF, +}; + +struct Event +{ + std::int32_t time; + EventType type; + std::uint8_t note; + std::uint8_t param1; + std::int32_t param2; + + bool operator==(const Event& other) + { + return (time == other.time + && type == other.type + && note == other.note + && param1 == other.param1 + && param2 == other.param2); + } + + bool operator!=(const Event& other) + { + return !(*this == other); + } +}; + +void ReadMidiFileHeader(); +void ReadMidiTracks(); + +extern int g_midiChan; +extern std::int32_t g_initialWait; + +inline bool IsPatternBoundary(EventType type) +{ + return type == EventType::EndOfTrack || (int)type <= 0x17; +} + +#endif // MIDI_H diff --git a/tools/mid2agb/tables.cpp b/tools/mid2agb/tables.cpp new file mode 100644 index 0000000..f254664 --- /dev/null +++ b/tools/mid2agb/tables.cpp @@ -0,0 +1,286 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include "tables.h" + +const int g_noteDurationLUT[] = +{ + 0, // 0 + 1, // 1 + 2, // 2 + 3, // 3 + 4, // 4 + 5, // 5 + 6, // 6 + 7, // 7 + 8, // 8 + 9, // 9 + 10, // 10 + 11, // 11 + 12, // 12 + 13, // 13 + 14, // 14 + 15, // 15 + 16, // 16 + 17, // 17 + 18, // 18 + 19, // 19 + 20, // 20 + 21, // 21 + 22, // 22 + 23, // 23 + 24, // 24 + 24, // 25 + 24, // 26 + 24, // 27 + 28, // 28 + 28, // 29 + 30, // 30 + 30, // 31 + 32, // 32 + 32, // 33 + 32, // 34 + 32, // 35 + 36, // 36 + 36, // 37 + 36, // 38 + 36, // 39 + 40, // 40 + 40, // 41 + 42, // 42 + 42, // 43 + 44, // 44 + 44, // 45 + 44, // 46 + 44, // 47 + 48, // 48 + 48, // 49 + 48, // 50 + 48, // 51 + 52, // 52 + 52, // 53 + 54, // 54 + 54, // 55 + 56, // 56 + 56, // 57 + 56, // 58 + 56, // 59 + 60, // 60 + 60, // 61 + 60, // 62 + 60, // 63 + 64, // 64 + 64, // 65 + 66, // 66 + 66, // 67 + 68, // 68 + 68, // 69 + 68, // 70 + 68, // 71 + 72, // 72 + 72, // 73 + 72, // 74 + 72, // 75 + 76, // 76 + 76, // 77 + 78, // 78 + 78, // 79 + 80, // 80 + 80, // 81 + 80, // 82 + 80, // 83 + 84, // 84 + 84, // 85 + 84, // 86 + 84, // 87 + 88, // 88 + 88, // 89 + 90, // 90 + 90, // 91 + 92, // 92 + 92, // 93 + 92, // 94 + 92, // 95 + 96, // 96 +}; + +const int g_noteVelocityLUT[] = +{ + 0, // 0 + 4, // 1 + 4, // 2 + 4, // 3 + 4, // 4 + 8, // 5 + 8, // 6 + 8, // 7 + 8, // 8 + 12, // 9 + 12, // 10 + 12, // 11 + 12, // 12 + 16, // 13 + 16, // 14 + 16, // 15 + 16, // 16 + 20, // 17 + 20, // 18 + 20, // 19 + 20, // 20 + 24, // 21 + 24, // 22 + 24, // 23 + 24, // 24 + 28, // 25 + 28, // 26 + 28, // 27 + 28, // 28 + 32, // 29 + 32, // 30 + 32, // 31 + 32, // 32 + 36, // 33 + 36, // 34 + 36, // 35 + 36, // 36 + 40, // 37 + 40, // 38 + 40, // 39 + 40, // 40 + 44, // 41 + 44, // 42 + 44, // 43 + 44, // 44 + 48, // 45 + 48, // 46 + 48, // 47 + 48, // 48 + 52, // 49 + 52, // 50 + 52, // 51 + 52, // 52 + 56, // 53 + 56, // 54 + 56, // 55 + 56, // 56 + 60, // 57 + 60, // 58 + 60, // 59 + 60, // 60 + 64, // 61 + 64, // 62 + 64, // 63 + 64, // 64 + 68, // 65 + 68, // 66 + 68, // 67 + 68, // 68 + 72, // 69 + 72, // 70 + 72, // 71 + 72, // 72 + 76, // 73 + 76, // 74 + 76, // 75 + 76, // 76 + 80, // 77 + 80, // 78 + 80, // 79 + 80, // 80 + 84, // 81 + 84, // 82 + 84, // 83 + 84, // 84 + 88, // 85 + 88, // 86 + 88, // 87 + 88, // 88 + 92, // 89 + 92, // 90 + 92, // 91 + 92, // 92 + 96, // 93 + 96, // 94 + 96, // 95 + 96, // 96 + 100, // 97 + 100, // 98 + 100, // 99 + 100, // 100 + 104, // 101 + 104, // 102 + 104, // 103 + 104, // 104 + 108, // 105 + 108, // 106 + 108, // 107 + 108, // 108 + 112, // 109 + 112, // 110 + 112, // 111 + 112, // 112 + 116, // 113 + 116, // 114 + 116, // 115 + 116, // 116 + 120, // 117 + 120, // 118 + 120, // 119 + 120, // 120 + 124, // 121 + 124, // 122 + 124, // 123 + 124, // 124 + 127, // 125 + 127, // 126 + 127, // 127 +}; + +const char* g_noteTable[] = +{ + "Cn%01u ", + "Cs%01u ", + "Dn%01u ", + "Ds%01u ", + "En%01u ", + "Fn%01u ", + "Fs%01u ", + "Gn%01u ", + "Gs%01u ", + "An%01u ", + "As%01u ", + "Bn%01u ", +}; + +const char* g_minusNoteTable[] = +{ + "CnM%01u", + "CsM%01u", + "DnM%01u", + "DsM%01u", + "EnM%01u", + "FnM%01u", + "FsM%01u", + "GnM%01u", + "GsM%01u", + "AnM%01u", + "AsM%01u", + "BnM%01u", +}; diff --git a/tools/mid2agb/tables.h b/tools/mid2agb/tables.h new file mode 100644 index 0000000..da3c907 --- /dev/null +++ b/tools/mid2agb/tables.h @@ -0,0 +1,29 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef TABLES_H +#define TABLES_H + +extern const int g_noteDurationLUT[]; +extern const int g_noteVelocityLUT[]; +extern const char* g_noteTable[]; +extern const char* g_minusNoteTable[]; + +#endif // TABLES_H diff --git a/tools/preproc/.gitignore b/tools/preproc/.gitignore new file mode 100644 index 0000000..eb34708 --- /dev/null +++ b/tools/preproc/.gitignore @@ -0,0 +1 @@ +preproc diff --git a/tools/preproc/LICENSE b/tools/preproc/LICENSE new file mode 100644 index 0000000..534d153 --- /dev/null +++ b/tools/preproc/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2016 YamaArashi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/tools/preproc/Makefile b/tools/preproc/Makefile new file mode 100644 index 0000000..bf1c11b --- /dev/null +++ b/tools/preproc/Makefile @@ -0,0 +1,20 @@ +CXX := g++ + +CXXFLAGS := -std=c++11 -O2 -s -Wall -Wno-switch -Werror + +SRCS := asm_file.cpp c_file.cpp charmap.cpp preproc.cpp string_parser.cpp \ + utf8.cpp + +HEADERS := asm_file.h c_file.h char_util.h charmap.h preproc.h string_parser.h \ + utf8.h + +.PHONY: all clean + +all: preproc + @: + +preproc: $(SRCS) $(HEADERS) + $(CXX) $(CXXFLAGS) $(SRCS) -o $@ $(LDFLAGS) + +clean: + $(RM) preproc preproc.exe diff --git a/tools/preproc/asm_file.cpp b/tools/preproc/asm_file.cpp new file mode 100644 index 0000000..383010a --- /dev/null +++ b/tools/preproc/asm_file.cpp @@ -0,0 +1,529 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include <cstdio> +#include <cstdarg> +#include "preproc.h" +#include "asm_file.h" +#include "char_util.h" +#include "utf8.h" +#include "string_parser.h" + +AsmFile::AsmFile(std::string filename) : m_filename(filename) +{ + FILE *fp = std::fopen(filename.c_str(), "rb"); + + if (fp == NULL) + FATAL_ERROR("Failed to open \"%s\" for reading.\n", filename.c_str()); + + std::fseek(fp, 0, SEEK_END); + + m_size = std::ftell(fp); + + if (m_size < 0) + FATAL_ERROR("File size of \"%s\" is less than zero.\n", filename.c_str()); + + m_buffer = new char[m_size + 1]; + + std::rewind(fp); + + if (std::fread(m_buffer, m_size, 1, fp) != 1) + FATAL_ERROR("Failed to read \"%s\".\n", filename.c_str()); + + m_buffer[m_size] = 0; + + std::fclose(fp); + + m_pos = 0; + m_lineNum = 1; + m_lineStart = 0; + + RemoveComments(); +} + +AsmFile::AsmFile(AsmFile&& other) : m_filename(std::move(other.m_filename)) +{ + m_buffer = other.m_buffer; + m_pos = other.m_pos; + m_size = other.m_size; + m_lineNum = other.m_lineNum; + m_lineStart = other.m_lineStart; + + other.m_buffer = nullptr; +} + +AsmFile::~AsmFile() +{ + delete[] m_buffer; +} + +// Removes comments to simplify further processing. +// It stops upon encountering a null character, +// which may or may not be the end of file marker. +// If it's not, the error will be caught later. +void AsmFile::RemoveComments() +{ + long pos = 0; + char stringChar = 0; + + for (;;) + { + if (m_buffer[pos] == 0) + return; + + if (stringChar != 0) + { + if (m_buffer[pos] == '\\' && m_buffer[pos + 1] == stringChar) + { + pos += 2; + } + else + { + if (m_buffer[pos] == stringChar) + stringChar = 0; + pos++; + } + } + else if (m_buffer[pos] == '@' && (pos == 0 || m_buffer[pos - 1] != '\\')) + { + while (m_buffer[pos] != '\n' && m_buffer[pos] != 0) + m_buffer[pos++] = ' '; + } + else if (m_buffer[pos] == '/' && m_buffer[pos + 1] == '*') + { + m_buffer[pos++] = ' '; + m_buffer[pos++] = ' '; + + for (;;) + { + if (m_buffer[pos] == 0) + return; + + if (m_buffer[pos] == '*' && m_buffer[pos + 1] == '/') + { + m_buffer[pos++] = ' '; + m_buffer[pos++] = ' '; + break; + } + else + { + if (m_buffer[pos] != '\n') + m_buffer[pos] = ' '; + pos++; + } + } + } + else + { + if (m_buffer[pos] == '"' || m_buffer[pos] == '\'') + stringChar = m_buffer[pos]; + pos++; + } + } +} + +// Checks if we're at a particular directive and if so, consumes it. +// Returns whether the directive was found. +bool AsmFile::CheckForDirective(std::string name) +{ + long i; + long length = static_cast<long>(name.length()); + + for (i = 0; i < length && m_pos + i < m_size; i++) + if (name[i] != m_buffer[m_pos + i]) + return false; + + if (i < length) + return false; + + m_pos += length; + + return true; +} + +// Checks if we're at a known directive and if so, consumes it. +// Returns which directive was found. +Directive AsmFile::GetDirective() +{ + SkipWhitespace(); + + if (CheckForDirective(".include")) + return Directive::Include; + else if (CheckForDirective(".string")) + return Directive::String; + else if (CheckForDirective(".braille")) + return Directive::Braille; + else + return Directive::Unknown; +} + +// Checks if we're at label that ends with '::'. +// Returns the name if so and an empty string if not. +std::string AsmFile::GetGlobalLabel() +{ + long start = m_pos; + long pos = m_pos; + + if (IsIdentifierStartingChar(m_buffer[pos])) + { + pos++; + + while (IsIdentifierChar(m_buffer[pos])) + pos++; + } + + if (m_buffer[pos] == ':' && m_buffer[pos + 1] == ':') + { + m_pos = pos + 2; + ExpectEmptyRestOfLine(); + return std::string(&m_buffer[start], pos - start); + } + + return std::string(); +} + +// Skips tabs and spaces. +void AsmFile::SkipWhitespace() +{ + while (m_buffer[m_pos] == '\t' || m_buffer[m_pos] == ' ') + m_pos++; +} + +// Reads include path. +std::string AsmFile::ReadPath() +{ + SkipWhitespace(); + + if (m_buffer[m_pos] != '"') + RaiseError("expected file path"); + + m_pos++; + + int length = 0; + long startPos = m_pos; + + while (m_buffer[m_pos] != '"') + { + unsigned char c = m_buffer[m_pos++]; + + if (c == 0) + { + if (m_pos >= m_size) + RaiseError("unexpected EOF in include string"); + else + RaiseError("unexpected null character in include string"); + } + + if (!IsAsciiPrintable(c)) + RaiseError("unexpected character '\\x%02X' in include string", c); + + // Don't bother allowing any escape sequences. + if (c == '\\') + { + c = m_buffer[m_pos]; + RaiseError("unexpected escape '\\%c' in include string", c); + } + + length++; + + if (length > kMaxPath) + RaiseError("path is too long"); + } + + m_pos++; // Go past the right quote. + + ExpectEmptyRestOfLine(); + + return std::string(&m_buffer[startPos], length); +} + +// Reads a charmap string. +int AsmFile::ReadString(unsigned char* s) +{ + SkipWhitespace(); + + int length; + StringParser stringParser(m_buffer, m_size); + + try + { + m_pos += stringParser.ParseString(m_pos, s, length); + } + catch (std::runtime_error& e) + { + RaiseError(e.what()); + } + + SkipWhitespace(); + + if (ConsumeComma()) + { + SkipWhitespace(); + int padLength = ReadPadLength(); + + while (length < padLength) + { + s[length++] = 0; + } + } + + ExpectEmptyRestOfLine(); + + return length; +} + +int AsmFile::ReadBraille(unsigned char* s) +{ + static std::map<char, unsigned char> encoding = + { + { 'A', 0x01 }, + { 'B', 0x05 }, + { 'C', 0x03 }, + { 'D', 0x0B }, + { 'E', 0x09 }, + { 'F', 0x07 }, + { 'G', 0x0F }, + { 'H', 0x0D }, + { 'I', 0x06 }, + { 'J', 0x0E }, + { 'K', 0x11 }, + { 'L', 0x15 }, + { 'M', 0x13 }, + { 'N', 0x1B }, + { 'O', 0x19 }, + { 'P', 0x17 }, + { 'Q', 0x1F }, + { 'R', 0x1D }, + { 'S', 0x16 }, + { 'T', 0x1E }, + { 'U', 0x31 }, + { 'V', 0x35 }, + { 'W', 0x2E }, + { 'X', 0x33 }, + { 'Y', 0x3B }, + { 'Z', 0x39 }, + { ' ', 0x00 }, + { ',', 0x04 }, + { '.', 0x2C }, + { '$', 0xFF }, + }; + + SkipWhitespace(); + + int length = 0; + + if (m_buffer[m_pos] != '"') + RaiseError("expected braille string literal"); + + m_pos++; + + while (m_buffer[m_pos] != '"') + { + if (length == kMaxStringLength) + RaiseError("mapped string longer than %d bytes", kMaxStringLength); + + if (m_buffer[m_pos] == '\\' && m_buffer[m_pos + 1] == 'n') + { + s[length++] = 0xFE; + m_pos += 2; + } + else + { + char c = m_buffer[m_pos]; + + if (encoding.count(c) == 0) + { + if (IsAsciiPrintable(c)) + RaiseError("character '%c' not valid in braille string", m_buffer[m_pos]); + else + RaiseError("character '\\x%02X' not valid in braille string", m_buffer[m_pos]); + } + + s[length++] = encoding[c]; + m_pos++; + } + } + + m_pos++; // Go past the right quote. + + ExpectEmptyRestOfLine(); + + return length; +} + +// If we're at a comma, consumes it. +// Returns whether a comma was found. +bool AsmFile::ConsumeComma() +{ + if (m_buffer[m_pos] == ',') + { + m_pos++; + return true; + } + + return false; +} + +// Converts digit character to numerical value. +static int ConvertDigit(char c, int radix) +{ + int digit; + + if (c >= '0' && c <= '9') + digit = c - '0'; + else if (c >= 'A' && c <= 'F') + digit = 10 + c - 'A'; + else if (c >= 'a' && c <= 'f') + digit = 10 + c - 'a'; + else + return -1; + + return (digit < radix) ? digit : -1; +} + +// Reads an integer. If the integer is greater than maxValue, it returns -1. +int AsmFile::ReadPadLength() +{ + if (!IsAsciiDigit(m_buffer[m_pos])) + RaiseError("expected integer"); + + int radix = 10; + + if (m_buffer[m_pos] == '0' && m_buffer[m_pos + 1] == 'x') + { + radix = 16; + m_pos += 2; + } + + unsigned n = 0; + int digit; + + while ((digit = ConvertDigit(m_buffer[m_pos], radix)) != -1) + { + n = n * radix + digit; + + if (n > kMaxStringLength) + RaiseError("pad length greater than maximum length (%d)", kMaxStringLength); + + m_pos++; + } + + return n; +} + +// Outputs the current line and moves to the next one. +void AsmFile::OutputLine() +{ + while (m_buffer[m_pos] != '\n' && m_buffer[m_pos] != 0) + m_pos++; + + if (m_buffer[m_pos] == 0) + { + if (m_pos >= m_size) + { + RaiseWarning("file doesn't end with newline"); + puts(&m_buffer[m_lineStart]); + } + else + { + RaiseError("unexpected null character"); + } + } + else + { + m_buffer[m_pos] = 0; + puts(&m_buffer[m_lineStart]); + m_buffer[m_pos] = '\n'; + m_pos++; + m_lineStart = m_pos; + m_lineNum++; + } +} + +// Asserts that the rest of the line is empty and moves to the next one. +void AsmFile::ExpectEmptyRestOfLine() +{ + SkipWhitespace(); + + if (m_buffer[m_pos] == 0) + { + if (m_pos >= m_size) + RaiseWarning("file doesn't end with newline"); + else + RaiseError("unexpected null character"); + } + else if (m_buffer[m_pos] == '\n') + { + m_pos++; + m_lineStart = m_pos; + m_lineNum++; + } + else if (m_buffer[m_pos] == '\r') + { + RaiseError("only Unix-style LF newlines are supported"); + } + else + { + RaiseError("junk at end of line"); + } +} + +// Checks if we're at the end of the file. +bool AsmFile::IsAtEnd() +{ + return (m_pos >= m_size); +} + +// Output the current location to set gas's logical file and line numbers. +void AsmFile::OutputLocation() +{ + std::printf("# %ld \"%s\"\n", m_lineNum, m_filename.c_str()); +} + +// Reports a diagnostic message. +void AsmFile::ReportDiagnostic(const char* type, const char* format, std::va_list args) +{ + const int bufferSize = 1024; + char buffer[bufferSize]; + std::vsnprintf(buffer, bufferSize, format, args); + std::fprintf(stderr, "%s:%ld: %s: %s\n", m_filename.c_str(), m_lineNum, type, buffer); +} + +#define DO_REPORT(type) \ +do \ +{ \ + std::va_list args; \ + va_start(args, format); \ + ReportDiagnostic(type, format, args); \ + va_end(args); \ +} while (0) + +// Reports an error diagnostic and terminates the program. +void AsmFile::RaiseError(const char* format, ...) +{ + DO_REPORT("error"); + std::exit(1); +} + +// Reports a warning diagnostic. +void AsmFile::RaiseWarning(const char* format, ...) +{ + DO_REPORT("warning"); +} diff --git a/tools/preproc/asm_file.h b/tools/preproc/asm_file.h new file mode 100644 index 0000000..d73b36e --- /dev/null +++ b/tools/preproc/asm_file.h @@ -0,0 +1,72 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef ASM_FILE_H +#define ASM_FILE_H + +#include <cstdarg> +#include <cstdint> +#include <string> +#include "preproc.h" + +enum class Directive +{ + Include, + String, + Braille, + Unknown +}; + +class AsmFile +{ +public: + AsmFile(std::string filename); + AsmFile(AsmFile&& other); + AsmFile(const AsmFile&) = delete; + ~AsmFile(); + Directive GetDirective(); + std::string GetGlobalLabel(); + std::string ReadPath(); + int ReadString(unsigned char* s); + int ReadBraille(unsigned char* s); + bool IsAtEnd(); + void OutputLine(); + void OutputLocation(); + +private: + char* m_buffer; + long m_pos; + long m_size; + long m_lineNum; + long m_lineStart; + std::string m_filename; + + bool ConsumeComma(); + int ReadPadLength(); + void RemoveComments(); + bool CheckForDirective(std::string name); + void SkipWhitespace(); + void ExpectEmptyRestOfLine(); + void ReportDiagnostic(const char* type, const char* format, std::va_list args); + void RaiseError(const char* format, ...); + void RaiseWarning(const char* format, ...); +}; + +#endif // ASM_FILE_H diff --git a/tools/preproc/c_file.cpp b/tools/preproc/c_file.cpp new file mode 100644 index 0000000..b550a53 --- /dev/null +++ b/tools/preproc/c_file.cpp @@ -0,0 +1,445 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include <cstdio> +#include <cstdarg> +#include <string> +#include <memory> +#include <iostream> +#include <iterator> +#include <cstring> +#include "preproc.h" +#include "c_file.h" +#include "char_util.h" +#include "utf8.h" +#include "string_parser.h" + +CFile::CFile(std::string filename) : m_filename(filename) +{ + if (filename == "-") { + std::string s, b; + + while (!std::cin.eof()) { + std::getline(std::cin, b); + s += b + "\n"; + } + m_size = s.size(); + m_buffer = new char[m_size + 1]; + memcpy(m_buffer, s.c_str(), m_size); + m_buffer[m_size] = 0; + } else { + FILE *fp = std::fopen(filename.c_str(), "rb"); + + if (fp == NULL) + FATAL_ERROR("Failed to open \"%s\" for reading.\n", filename.c_str()); + + std::fseek(fp, 0, SEEK_END); + + m_size = std::ftell(fp); + + if (m_size < 0) + FATAL_ERROR("File size of \"%s\" is less than zero.\n", filename.c_str()); + + m_buffer = new char[m_size + 1]; + + std::rewind(fp); + + if (std::fread(m_buffer, m_size, 1, fp) != 1) + FATAL_ERROR("Failed to read \"%s\".\n", filename.c_str()); + + m_buffer[m_size] = 0; + + std::fclose(fp); + } + + m_pos = 0; + m_lineNum = 1; +} + +CFile::CFile(CFile&& other) : m_filename(std::move(other.m_filename)) +{ + m_buffer = other.m_buffer; + m_pos = other.m_pos; + m_size = other.m_size; + m_lineNum = other.m_lineNum; + + other.m_buffer = nullptr; +} + +CFile::~CFile() +{ + delete[] m_buffer; +} + +void CFile::Preproc() +{ + char stringChar = 0; + + while (m_pos < m_size) + { + if (stringChar) + { + if (m_buffer[m_pos] == stringChar) + { + std::putchar(stringChar); + m_pos++; + stringChar = 0; + } + else if (m_buffer[m_pos] == '\\' && m_buffer[m_pos + 1] == stringChar) + { + std::putchar('\\'); + std::putchar(stringChar); + m_pos += 2; + } + else + { + if (m_buffer[m_pos] == '\n') + m_lineNum++; + std::putchar(m_buffer[m_pos]); + m_pos++; + } + } + else + { + TryConvertString(); + TryConvertIncbin(); + + if (m_pos >= m_size) + break; + + char c = m_buffer[m_pos++]; + + std::putchar(c); + + if (c == '\n') + m_lineNum++; + else if (c == '"') + stringChar = '"'; + else if (c == '\'') + stringChar = '\''; + } + } +} + +bool CFile::ConsumeHorizontalWhitespace() +{ + if (m_buffer[m_pos] == '\t' || m_buffer[m_pos] == ' ') + { + m_pos++; + return true; + } + + return false; +} + +bool CFile::ConsumeNewline() +{ + if (m_buffer[m_pos] == '\r' && m_buffer[m_pos + 1] == '\n') + { + m_pos += 2; + m_lineNum++; + std::putchar('\n'); + return true; + } + + if (m_buffer[m_pos] == '\n') + { + m_pos++; + m_lineNum++; + std::putchar('\n'); + return true; + } + + return false; +} + +void CFile::SkipWhitespace() +{ + while (ConsumeHorizontalWhitespace() || ConsumeNewline()) + ; +} + +void CFile::TryConvertString() +{ + long oldPos = m_pos; + long oldLineNum = m_lineNum; + bool noTerminator = false; + + if (m_buffer[m_pos] != '_' || (m_pos > 0 && IsIdentifierChar(m_buffer[m_pos - 1]))) + return; + + m_pos++; + + if (m_buffer[m_pos] == '_') + { + noTerminator = true; + m_pos++; + } + + SkipWhitespace(); + + if (m_buffer[m_pos] != '(') + { + m_pos = oldPos; + m_lineNum = oldLineNum; + return; + } + + m_pos++; + + SkipWhitespace(); + + std::printf("{ "); + + while (1) + { + SkipWhitespace(); + + if (m_buffer[m_pos] == '"') + { + unsigned char s[kMaxStringLength]; + int length; + StringParser stringParser(m_buffer, m_size); + + try + { + m_pos += stringParser.ParseString(m_pos, s, length); + } + catch (std::runtime_error& e) + { + RaiseError(e.what()); + } + + for (int i = 0; i < length; i++) + printf("0x%02X, ", s[i]); + } + else if (m_buffer[m_pos] == ')') + { + m_pos++; + break; + } + else + { + if (m_pos >= m_size) + RaiseError("unexpected EOF"); + if (IsAsciiPrintable(m_buffer[m_pos])) + RaiseError("unexpected character '%c'", m_buffer[m_pos]); + else + RaiseError("unexpected character '\\x%02X'", m_buffer[m_pos]); + } + } + + if (noTerminator) + std::printf(" }"); + else + std::printf("0xFF }"); +} + +bool CFile::CheckIdentifier(const std::string& ident) +{ + unsigned int i; + + for (i = 0; i < ident.length() && m_pos + i < (unsigned)m_size; i++) + if (ident[i] != m_buffer[m_pos + i]) + return false; + + return (i == ident.length()); +} + +std::unique_ptr<unsigned char[]> CFile::ReadWholeFile(const std::string& path, int& size) +{ + FILE* fp = std::fopen(path.c_str(), "rb"); + + if (fp == nullptr) + RaiseError("Failed to open \"%s\" for reading.\n", path.c_str()); + + std::fseek(fp, 0, SEEK_END); + + size = std::ftell(fp); + + std::unique_ptr<unsigned char[]> buffer = std::unique_ptr<unsigned char[]>(new unsigned char[size]); + + std::rewind(fp); + + if (std::fread(buffer.get(), size, 1, fp) != 1) + RaiseError("Failed to read \"%s\".\n", path.c_str()); + + std::fclose(fp); + + return buffer; +} + +int ExtractData(const std::unique_ptr<unsigned char[]>& buffer, int offset, int size) +{ + switch (size) + { + case 1: + return buffer[offset]; + case 2: + return (buffer[offset + 1] << 8) + | buffer[offset]; + case 4: + return (buffer[offset + 3] << 24) + | (buffer[offset + 2] << 16) + | (buffer[offset + 1] << 8) + | buffer[offset]; + default: + FATAL_ERROR("Invalid size passed to ExtractData.\n"); + } +} + +void CFile::TryConvertIncbin() +{ + std::string idents[6] = { "INCBIN_S8", "INCBIN_U8", "INCBIN_S16", "INCBIN_U16", "INCBIN_S32", "INCBIN_U32" }; + int incbinType = -1; + + for (int i = 0; i < 6; i++) + { + if (CheckIdentifier(idents[i])) + { + incbinType = i; + break; + } + } + + if (incbinType == -1) + return; + + int size = 1 << (incbinType / 2); + bool isSigned = ((incbinType % 2) == 0); + + long oldPos = m_pos; + long oldLineNum = m_lineNum; + + m_pos += idents[incbinType].length(); + + SkipWhitespace(); + + if (m_buffer[m_pos] != '(') + { + m_pos = oldPos; + m_lineNum = oldLineNum; + return; + } + + m_pos++; + + std::printf("{"); + + while (true) + { + SkipWhitespace(); + + if (m_buffer[m_pos] != '"') + RaiseError("expected double quote"); + + m_pos++; + + int startPos = m_pos; + + while (m_buffer[m_pos] != '"') + { + if (m_buffer[m_pos] == 0) + { + if (m_pos >= m_size) + RaiseError("unexpected EOF in path string"); + else + RaiseError("unexpected null character in path string"); + } + + if (m_buffer[m_pos] == '\r' || m_buffer[m_pos] == '\n') + RaiseError("unexpected end of line character in path string"); + + if (m_buffer[m_pos] == '\\') + RaiseError("unexpected escape in path string"); + + m_pos++; + } + + std::string path(&m_buffer[startPos], m_pos - startPos); + + m_pos++; + + int fileSize; + std::unique_ptr<unsigned char[]> buffer = ReadWholeFile(path, fileSize); + + if ((fileSize % size) != 0) + RaiseError("Size %d doesn't evenly divide file size %d.\n", size, fileSize); + + int count = fileSize / size; + int offset = 0; + + for (int i = 0; i < count; i++) + { + int data = ExtractData(buffer, offset, size); + offset += size; + + if (isSigned) + std::printf("%d,", data); + else + std::printf("%uu,", data); + } + + SkipWhitespace(); + + if (m_buffer[m_pos] != ',') + break; + + m_pos++; + } + + if (m_buffer[m_pos] != ')') + RaiseError("expected ')'"); + + m_pos++; + + std::printf("}"); +} + +// Reports a diagnostic message. +void CFile::ReportDiagnostic(const char* type, const char* format, std::va_list args) +{ + const int bufferSize = 1024; + char buffer[bufferSize]; + std::vsnprintf(buffer, bufferSize, format, args); + std::fprintf(stderr, "%s:%ld: %s: %s\n", m_filename.c_str(), m_lineNum, type, buffer); +} + +#define DO_REPORT(type) \ +do \ +{ \ + std::va_list args; \ + va_start(args, format); \ + ReportDiagnostic(type, format, args); \ + va_end(args); \ +} while (0) + +// Reports an error diagnostic and terminates the program. +void CFile::RaiseError(const char* format, ...) +{ + DO_REPORT("error"); + std::exit(1); +} + +// Reports a warning diagnostic. +void CFile::RaiseWarning(const char* format, ...) +{ + DO_REPORT("warning"); +} diff --git a/tools/preproc/c_file.h b/tools/preproc/c_file.h new file mode 100644 index 0000000..7369aba --- /dev/null +++ b/tools/preproc/c_file.h @@ -0,0 +1,58 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef C_FILE_H +#define C_FILE_H + +#include <cstdarg> +#include <cstdint> +#include <string> +#include <memory> +#include "preproc.h" + +class CFile +{ +public: + CFile(std::string filename); + CFile(CFile&& other); + CFile(const CFile&) = delete; + ~CFile(); + void Preproc(); + +private: + char* m_buffer; + long m_pos; + long m_size; + long m_lineNum; + std::string m_filename; + + bool ConsumeHorizontalWhitespace(); + bool ConsumeNewline(); + void SkipWhitespace(); + void TryConvertString(); + std::unique_ptr<unsigned char[]> ReadWholeFile(const std::string& path, int& size); + bool CheckIdentifier(const std::string& ident); + void TryConvertIncbin(); + void ReportDiagnostic(const char* type, const char* format, std::va_list args); + void RaiseError(const char* format, ...); + void RaiseWarning(const char* format, ...); +}; + +#endif // C_FILE_H diff --git a/tools/preproc/char_util.h b/tools/preproc/char_util.h new file mode 100644 index 0000000..02a6e1c --- /dev/null +++ b/tools/preproc/char_util.h @@ -0,0 +1,71 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef CHAR_UTIL_H +#define CHAR_UTIL_H + +#include <cstdint> +#include <cassert> + +inline bool IsAscii(unsigned char c) +{ + return (c < 128); +} + +inline bool IsAsciiAlpha(unsigned char c) +{ + return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')); +} + +inline bool IsAsciiDigit(unsigned char c) +{ + return (c >= '0' && c <= '9'); +} + +inline bool IsAsciiHexDigit(unsigned char c) +{ + return ((c >= '0' && c <= '9') + || (c >= 'a' && c <= 'f') + || (c >= 'A' && c <= 'F')); +} + +inline bool IsAsciiAlphanum(unsigned char c) +{ + return (IsAsciiAlpha(c) || IsAsciiDigit(c)); +} + +inline bool IsAsciiPrintable(unsigned char c) +{ + return (c >= ' ' && c <= '~'); +} + +// Returns whether the character can start a C identifier or the identifier of a "{FOO}" constant in strings. +inline bool IsIdentifierStartingChar(unsigned char c) +{ + return IsAsciiAlpha(c) || c == '_'; +} + +// Returns whether the character can be used in a C identifier or the identifier of a "{FOO}" constant in strings. +inline bool IsIdentifierChar(unsigned char c) +{ + return IsAsciiAlphanum(c) || c == '_'; +} + +#endif // CHAR_UTIL_H diff --git a/tools/preproc/charmap.cpp b/tools/preproc/charmap.cpp new file mode 100644 index 0000000..a7bedfe --- /dev/null +++ b/tools/preproc/charmap.cpp @@ -0,0 +1,408 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include <cstdio> +#include <cstdint> +#include <cstdarg> +#include "preproc.h" +#include "charmap.h" +#include "char_util.h" +#include "utf8.h" + +enum LhsType +{ + Char, + Escape, + Constant, + None +}; + +struct Lhs +{ + LhsType type; + std::string name; + std::int32_t code; +}; + +class CharmapReader +{ +public: + CharmapReader(std::string filename); + CharmapReader(const CharmapReader&) = delete; + ~CharmapReader(); + Lhs ReadLhs(); + void ExpectEqualsSign(); + std::string ReadSequence(); + void ExpectEmptyRestOfLine(); + void RaiseError(const char* format, ...); + +private: + char* m_buffer; + long m_pos; + long m_size; + long m_lineNum; + std::string m_filename; + + void RemoveComments(); + std::string ReadConstant(); + void SkipWhitespace(); +}; + +CharmapReader::CharmapReader(std::string filename) : m_filename(filename) +{ + FILE *fp = std::fopen(filename.c_str(), "rb"); + + if (fp == NULL) + FATAL_ERROR("Failed to open \"%s\" for reading.\n", filename.c_str()); + + std::fseek(fp, 0, SEEK_END); + + m_size = std::ftell(fp); + + if (m_size < 0) + FATAL_ERROR("File size of \"%s\" is less than zero.\n", filename.c_str()); + + m_buffer = new char[m_size + 1]; + + std::rewind(fp); + + if (std::fread(m_buffer, m_size, 1, fp) != 1) + FATAL_ERROR("Failed to read \"%s\".\n", filename.c_str()); + + m_buffer[m_size] = 0; + + std::fclose(fp); + + m_pos = 0; + m_lineNum = 1; + + RemoveComments(); +} + +CharmapReader::~CharmapReader() +{ + delete[] m_buffer; +} + +Lhs CharmapReader::ReadLhs() +{ + Lhs lhs; + + for (;;) + { + SkipWhitespace(); + + if (m_buffer[m_pos] == '\n') + { + m_pos++; + m_lineNum++; + } + else + { + break; + } + } + + if (m_buffer[m_pos] == '\'') + { + m_pos++; + + bool isEscape = (m_buffer[m_pos] == '\\'); + + if (isEscape) + { + m_pos++; + } + + unsigned char c = m_buffer[m_pos]; + + if (c == 0) + { + if (m_pos >= m_size) + RaiseError("unexpected EOF in UTF-8 character literal"); + else + RaiseError("unexpected null character in UTF-8 character literal"); + } + + if (IsAscii(c) && !IsAsciiPrintable(c)) + RaiseError("unexpected character U+%X in UTF-8 character literal", c); + + UnicodeChar unicodeChar = DecodeUtf8(&m_buffer[m_pos]); + std::int32_t code = unicodeChar.code; + + if (code == -1) + RaiseError("invalid encoding in UTF-8 character literal"); + + m_pos += unicodeChar.encodingLength; + + if (m_buffer[m_pos] != '\'') + RaiseError("unterminated character literal"); + + m_pos++; + + lhs.code = code; + + if (isEscape) + { + if (code >= 128) + RaiseError("escapes using non-ASCII characters are invalid"); + + switch (code) + { + case '\'': + lhs.type = LhsType::Char; + break; + case '\\': + lhs.type = LhsType::Char; + case '"': + RaiseError("cannot escape double quote"); + break; + default: + lhs.type = LhsType::Escape; + } + } + else + { + if (code == '\'') + RaiseError("empty character literal"); + + lhs.type = LhsType::Char; + } + } + else if (IsIdentifierStartingChar(m_buffer[m_pos])) + { + lhs.type = LhsType::Constant; + lhs.name = ReadConstant(); + } + else if (m_buffer[m_pos] == '\r') + { + RaiseError("only Unix-style LF newlines are supported"); + } + else if (m_buffer[m_pos] == 0) + { + if (m_pos < m_size) + RaiseError("unexpected null character"); + lhs.type = LhsType::None; + } + else + { + RaiseError("junk at start of line"); + } + + return lhs; +} + +void CharmapReader::ExpectEqualsSign() +{ + SkipWhitespace(); + + if (m_buffer[m_pos] != '=') + RaiseError("expected equals sign"); + + m_pos++; +} + +static unsigned int ConvertHexDigit(char c) +{ + unsigned int digit = 0; + + if (c >= '0' && c <= '9') + digit = c - '0'; + else if (c >= 'A' && c <= 'F') + digit = 10 + c - 'A'; + else if (c >= 'a' && c <= 'f') + digit = 10 + c - 'a'; + + return digit; +} + +std::string CharmapReader::ReadSequence() +{ + SkipWhitespace(); + + long startPos = m_pos; + + unsigned int length = 0; + + while (IsAsciiHexDigit(m_buffer[m_pos]) && IsAsciiHexDigit(m_buffer[m_pos + 1])) + { + m_pos += 2; + length++; + + if (length > kMaxCharmapSequenceLength) + RaiseError("byte sequence too long (max is %lu bytes)", kMaxCharmapSequenceLength); + + SkipWhitespace(); + } + + if (IsAsciiHexDigit(m_buffer[m_pos])) + RaiseError("each byte must have 2 hex digits"); + + if (length == 0) + RaiseError("expected byte sequence"); + + std::string sequence; + sequence.reserve(length); + + m_pos = startPos; + + for (unsigned int i = 0; i < length; i++) + { + unsigned int digit1 = ConvertHexDigit(m_buffer[m_pos]); + unsigned int digit2 = ConvertHexDigit(m_buffer[m_pos + 1]); + unsigned char byte = digit1 * 16 + digit2; + sequence += byte; + + m_pos += 2; + SkipWhitespace(); + } + + return sequence; +} + +void CharmapReader::ExpectEmptyRestOfLine() +{ + SkipWhitespace(); + + if (m_buffer[m_pos] == 0) + { + if (m_pos < m_size) + RaiseError("unexpected null character"); + } + else if (m_buffer[m_pos] == '\n') + { + m_pos++; + m_lineNum++; + } + else if (m_buffer[m_pos] == '\r') + { + RaiseError("only Unix-style LF newlines are supported"); + } + else + { + RaiseError("junk at end of line"); + } +} + +void CharmapReader::RaiseError(const char* format, ...) +{ + const int bufferSize = 1024; + char buffer[bufferSize]; + + std::va_list args; + va_start(args, format); + std::vsnprintf(buffer, bufferSize, format, args); + va_end(args); + + std::fprintf(stderr, "%s:%ld: error: %s\n", m_filename.c_str(), m_lineNum, buffer); + + std::exit(1); +} + +void CharmapReader::RemoveComments() +{ + long pos = 0; + bool inString = false; + + for (;;) + { + if (m_buffer[pos] == 0) + return; + + if (inString) + { + if (m_buffer[pos] == '\\' && m_buffer[pos + 1] == '\'') + { + pos += 2; + } + else + { + if (m_buffer[pos] == '\'') + inString = false; + pos++; + } + } + else if (m_buffer[pos] == '@') + { + while (m_buffer[pos] != '\n' && m_buffer[pos] != 0) + m_buffer[pos++] = ' '; + } + else + { + if (m_buffer[pos] == '\'') + inString = true; + pos++; + } + } +} + +std::string CharmapReader::ReadConstant() +{ + long startPos = m_pos; + + while (IsIdentifierChar(m_buffer[m_pos])) + m_pos++; + + return std::string(&m_buffer[startPos], m_pos - startPos); +} + +void CharmapReader::SkipWhitespace() +{ + while (m_buffer[m_pos] == '\t' || m_buffer[m_pos] == ' ') + m_pos++; +} + +Charmap::Charmap(std::string filename) +{ + CharmapReader reader(filename); + + for (;;) + { + Lhs lhs = reader.ReadLhs(); + + if (lhs.type == LhsType::None) + return; + + reader.ExpectEqualsSign(); + + std::string sequence = reader.ReadSequence(); + + switch (lhs.type) + { + case LhsType::Char: + if (m_chars.find(lhs.code) != m_chars.end()) + reader.RaiseError("redefining char"); + m_chars[lhs.code] = sequence; + break; + case LhsType::Escape: + if (m_escapes[lhs.code].length() != 0) + reader.RaiseError("redefining escape"); + m_escapes[lhs.code] = sequence; + break; + case LhsType::Constant: + if (m_constants.find(lhs.name) != m_constants.end()) + reader.RaiseError("redefining constant"); + m_constants[lhs.name] = sequence; + break; + } + + reader.ExpectEmptyRestOfLine(); + } +} diff --git a/tools/preproc/charmap.h b/tools/preproc/charmap.h new file mode 100644 index 0000000..0d752ac --- /dev/null +++ b/tools/preproc/charmap.h @@ -0,0 +1,64 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef CHARMAP_H +#define CHARMAP_H + +#include <cstdint> +#include <string> +#include <map> +#include <vector> + +class Charmap +{ +public: + Charmap(std::string filename); + + std::string Char(std::int32_t code) + { + auto it = m_chars.find(code); + + if (it == m_chars.end()) + return std::string(); + + return it->second; + } + + std::string Escape(unsigned char code) + { + return m_escapes[code]; + } + + std::string Constant(std::string identifier) + { + auto it = m_constants.find(identifier); + + if (it == m_constants.end()) + return std::string(); + + return it->second; + } +private: + std::map<std::int32_t, std::string> m_chars; + std::string m_escapes[128]; + std::map<std::string, std::string> m_constants; +}; + +#endif // CHARMAP_H diff --git a/tools/preproc/preproc.cpp b/tools/preproc/preproc.cpp new file mode 100644 index 0000000..2d51ab1 --- /dev/null +++ b/tools/preproc/preproc.cpp @@ -0,0 +1,161 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include <string> +#include <stack> +#include "preproc.h" +#include "asm_file.h" +#include "c_file.h" +#include "charmap.h" + +Charmap* g_charmap; + +void PrintAsmBytes(unsigned char *s, int length) +{ + if (length > 0) + { + std::printf("\t.byte "); + for (int i = 0; i < length; i++) + { + std::printf("0x%02X", s[i]); + + if (i < length - 1) + std::printf(", "); + } + std::putchar('\n'); + } +} + +void PreprocAsmFile(std::string filename) +{ + std::stack<AsmFile> stack; + + stack.push(AsmFile(filename)); + + for (;;) + { + while (stack.top().IsAtEnd()) + { + stack.pop(); + + if (stack.empty()) + return; + else + stack.top().OutputLocation(); + } + + Directive directive = stack.top().GetDirective(); + + switch (directive) + { + case Directive::Include: + stack.push(AsmFile(stack.top().ReadPath())); + stack.top().OutputLocation(); + break; + case Directive::String: + { + unsigned char s[kMaxStringLength]; + int length = stack.top().ReadString(s); + PrintAsmBytes(s, length); + break; + } + case Directive::Braille: + { + unsigned char s[kMaxStringLength]; + int length = stack.top().ReadBraille(s); + PrintAsmBytes(s, length); + break; + } + case Directive::Unknown: + { + std::string globalLabel = stack.top().GetGlobalLabel(); + + if (globalLabel.length() != 0) + { + const char *s = globalLabel.c_str(); + std::printf("%s: ; .global %s\n", s, s); + } + else + { + stack.top().OutputLine(); + } + + break; + } + } + } +} + +void PreprocCFile(std::string filename) +{ + CFile cFile(filename); + cFile.Preproc(); +} + +char* GetFileExtension(char* filename) +{ + char* extension = filename; + + while (*extension != 0) + extension++; + + while (extension > filename && *extension != '.') + extension--; + + if (extension == filename) + return nullptr; + + extension++; + + if (*extension == 0) + return nullptr; + + return extension; +} + +int main(int argc, char **argv) +{ + if (argc != 3) + { + std::fprintf(stderr, "Usage: %s SRC_FILE CHARMAP_FILE", argv[0]); + return 1; + } + + g_charmap = new Charmap(argv[2]); + + if (argv[1][0] == '-' && argv[1][1] == 0) { + PreprocCFile("-"); + } else { + char* extension = GetFileExtension(argv[1]); + + if (!extension) + FATAL_ERROR("\"%s\" has no file extension.\n", argv[1]); + + if ((extension[0] == 's') && extension[1] == 0) + PreprocAsmFile(argv[1]); + else if ((extension[0] == 'c' || extension[0] == 'i') && extension[1] == 0) + PreprocCFile(argv[1]); + else + FATAL_ERROR("\"%s\" has an unknown file extension of \"%s\".\n", argv[1], extension); + } + + + return 0; +} diff --git a/tools/preproc/preproc.h b/tools/preproc/preproc.h new file mode 100644 index 0000000..515f64e --- /dev/null +++ b/tools/preproc/preproc.h @@ -0,0 +1,54 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef PREPROC_H +#define PREPROC_H + +#include <cstdio> +#include <cstdlib> +#include "charmap.h" + +#ifdef _MSC_VER + +#define FATAL_ERROR(format, ...) \ +do \ +{ \ + std::fprintf(stderr, format, __VA_ARGS__); \ + std::exit(1); \ +} while (0) + +#else + +#define FATAL_ERROR(format, ...) \ +do \ +{ \ + std::fprintf(stderr, format, ##__VA_ARGS__); \ + std::exit(1); \ +} while (0) + +#endif // _MSC_VER + +const int kMaxPath = 256; +const int kMaxStringLength = 1024; +const unsigned long kMaxCharmapSequenceLength = 16; + +extern Charmap* g_charmap; + +#endif // PREPROC_H diff --git a/tools/preproc/string_parser.cpp b/tools/preproc/string_parser.cpp new file mode 100644 index 0000000..dd5196a --- /dev/null +++ b/tools/preproc/string_parser.cpp @@ -0,0 +1,355 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include <cstdio> +#include <cstdarg> +#include <stdexcept> +#include "preproc.h" +#include "string_parser.h" +#include "char_util.h" +#include "utf8.h" + +// Reads a charmap char or escape sequence. +std::string StringParser::ReadCharOrEscape() +{ + std::string sequence; + + bool isEscape = (m_buffer[m_pos] == '\\'); + + if (isEscape) + { + m_pos++; + + if (m_buffer[m_pos] == '"') + { + sequence = g_charmap->Char('"'); + + if (sequence.length() == 0) + RaiseError("no mapping exists for double quote"); + + return sequence; + } + else if (m_buffer[m_pos] == '\\') + { + sequence = g_charmap->Char('\\'); + + if (sequence.length() == 0) + RaiseError("no mapping exists for backslash"); + + return sequence; + } + } + + unsigned char c = m_buffer[m_pos]; + + if (c == 0) + { + if (m_pos >= m_size) + RaiseError("unexpected EOF in UTF-8 string"); + else + RaiseError("unexpected null character in UTF-8 string"); + } + + if (IsAscii(c) && !IsAsciiPrintable(c)) + RaiseError("unexpected character U+%X in UTF-8 string", c); + + UnicodeChar unicodeChar = DecodeUtf8(&m_buffer[m_pos]); + m_pos += unicodeChar.encodingLength; + std::int32_t code = unicodeChar.code; + + if (code == -1) + RaiseError("invalid encoding in UTF-8 string"); + + if (isEscape && code >= 128) + RaiseError("escapes using non-ASCII characters are invalid"); + + sequence = isEscape ? g_charmap->Escape(code) : g_charmap->Char(code); + + if (sequence.length() == 0) + { + if (isEscape) + RaiseError("unknown escape '\\%c'", code); + else + RaiseError("unknown character U+%X", code); + } + + return sequence; +} + +// Reads a charmap constant, i.e. "{FOO}". +std::string StringParser::ReadBracketedConstants() +{ + std::string totalSequence; + + m_pos++; // Assume we're on the left curly bracket. + + while (m_buffer[m_pos] != '}') + { + SkipWhitespace(); + + if (IsIdentifierStartingChar(m_buffer[m_pos])) + { + long startPos = m_pos; + + m_pos++; + + while (IsIdentifierChar(m_buffer[m_pos])) + m_pos++; + + std::string sequence = g_charmap->Constant(std::string(&m_buffer[startPos], m_pos - startPos)); + + if (sequence.length() == 0) + { + m_buffer[m_pos] = 0; + RaiseError("unknown constant '%s'", &m_buffer[startPos]); + } + + totalSequence += sequence; + } + else if (IsAsciiDigit(m_buffer[m_pos])) + { + Integer integer = ReadInteger(); + + switch (integer.size) + { + case 1: + totalSequence += (unsigned char)integer.value; + break; + case 2: + totalSequence += (unsigned char)integer.value; + totalSequence += (unsigned char)(integer.value >> 8); + break; + case 4: + totalSequence += (unsigned char)integer.value; + totalSequence += (unsigned char)(integer.value >> 8); + totalSequence += (unsigned char)(integer.value >> 16); + totalSequence += (unsigned char)(integer.value >> 24); + break; + } + } + else if (m_buffer[m_pos] == 0) + { + if (m_pos >= m_size) + RaiseError("unexpected EOF after left curly bracket"); + else + RaiseError("unexpected null character within curly brackets"); + } + else + { + if (IsAsciiPrintable(m_buffer[m_pos])) + RaiseError("unexpected character '%c' within curly brackets", m_buffer[m_pos]); + else + RaiseError("unexpected character '\\x%02X' within curly brackets", m_buffer[m_pos]); + } + } + + m_pos++; // Go past the right curly bracket. + + return totalSequence; +} + +// Reads a charmap string. +int StringParser::ParseString(long srcPos, unsigned char* dest, int& destLength) +{ + m_pos = srcPos; + + if (m_buffer[m_pos] != '"') + RaiseError("expected UTF-8 string literal"); + + long start = m_pos; + + m_pos++; + + destLength = 0; + + while (m_buffer[m_pos] != '"') + { + std::string sequence = (m_buffer[m_pos] == '{') ? ReadBracketedConstants() : ReadCharOrEscape(); + + for (const char& c : sequence) + { + if (destLength == kMaxStringLength) + RaiseError("mapped string longer than %d bytes", kMaxStringLength); + + dest[destLength++] = c; + } + } + + m_pos++; // Go past the right quote. + + return m_pos - start; +} + +void StringParser::RaiseError(const char* format, ...) +{ + const int bufferSize = 1024; + char buffer[bufferSize]; + + std::va_list args; + va_start(args, format); + std::vsnprintf(buffer, bufferSize, format, args); + va_end(args); + + throw std::runtime_error(buffer); +} + +// Converts digit character to numerical value. +static int ConvertDigit(char c, int radix) +{ + int digit; + + if (c >= '0' && c <= '9') + digit = c - '0'; + else if (c >= 'A' && c <= 'F') + digit = 10 + c - 'A'; + else if (c >= 'a' && c <= 'f') + digit = 10 + c - 'a'; + else + return -1; + + return (digit < radix) ? digit : -1; +} + +void StringParser::SkipRestOfInteger(int radix) +{ + while (ConvertDigit(m_buffer[m_pos], radix) != -1) + m_pos++; +} + +StringParser::Integer StringParser::ReadDecimal() +{ + const int radix = 10; + std::uint64_t n = 0; + int digit; + std::uint64_t max = UINT32_MAX; + long startPos = m_pos; + + while ((digit = ConvertDigit(m_buffer[m_pos], radix)) != -1) + { + n = n * radix + digit; + + if (n >= max) + { + SkipRestOfInteger(radix); + + std::string intLiteral(m_buffer + startPos, m_pos - startPos); + RaiseError("integer literal \"%s\" is too large", intLiteral.c_str()); + } + + m_pos++; + } + + int size; + + if (m_buffer[m_pos] == 'H') + { + if (n >= 0x10000) + { + RaiseError("%lu is too large to be a halfword", (unsigned long)n); + } + + size = 2; + m_pos++; + } + else if (m_buffer[m_pos] == 'W') + { + size = 4; + m_pos++; + } + else + { + if (n >= 0x10000) + size = 4; + else if (n >= 0x100) + size = 2; + else + size = 1; + } + + return{ static_cast<std::uint32_t>(n), size }; +} + +StringParser::Integer StringParser::ReadHex() +{ + const int radix = 16; + std::uint64_t n = 0; + int digit; + std::uint64_t max = UINT32_MAX; + long startPos = m_pos; + + while ((digit = ConvertDigit(m_buffer[m_pos], radix)) != -1) + { + n = n * radix + digit; + + if (n >= max) + { + SkipRestOfInteger(radix); + + std::string intLiteral(m_buffer + startPos, m_pos - startPos); + RaiseError("integer literal \"%s\" is too large", intLiteral.c_str()); + } + + m_pos++; + } + + int length = m_pos - startPos; + int size = 0; + + switch (length) + { + case 2: + size = 1; + break; + case 4: + size = 2; + break; + case 8: + size = 4; + break; + default: + { + std::string intLiteral(m_buffer + startPos, m_pos - startPos); + RaiseError("hex integer literal \"0x%s\" doesn't have length of 2, 4, or 8 digits", intLiteral.c_str()); + } + } + + return{ static_cast<std::uint32_t>(n), size }; +} + +StringParser::Integer StringParser::ReadInteger() +{ + if (!IsAsciiDigit(m_buffer[m_pos])) + RaiseError("expected integer"); + + if (m_buffer[m_pos] == '0' && m_buffer[m_pos + 1] == 'x') + { + m_pos += 2; + return ReadHex(); + } + + return ReadDecimal(); +} + +// Skips tabs and spaces. +void StringParser::SkipWhitespace() +{ + while (m_buffer[m_pos] == '\t' || m_buffer[m_pos] == ' ') + m_pos++; +} diff --git a/tools/preproc/string_parser.h b/tools/preproc/string_parser.h new file mode 100644 index 0000000..abd2bfe --- /dev/null +++ b/tools/preproc/string_parser.h @@ -0,0 +1,55 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef STRING_PARSER_H +#define STRING_PARSER_H + +#include <cstdint> +#include <string> +#include "preproc.h" + +class StringParser +{ +public: + StringParser(char* buffer, long size) : m_buffer(buffer), m_size(size), m_pos(0) {} + int ParseString(long srcPos, unsigned char* dest, int &destLength); + +private: + struct Integer + { + std::uint32_t value; + int size; + }; + + char* m_buffer; + long m_size; + long m_pos; + + Integer ReadInteger(); + Integer ReadDecimal(); + Integer ReadHex(); + std::string ReadCharOrEscape(); + std::string ReadBracketedConstants(); + void SkipWhitespace(); + void SkipRestOfInteger(int radix); + void RaiseError(const char* format, ...); +}; + +#endif // STRING_PARSER_H diff --git a/tools/preproc/utf8.cpp b/tools/preproc/utf8.cpp new file mode 100644 index 0000000..7facfd4 --- /dev/null +++ b/tools/preproc/utf8.cpp @@ -0,0 +1,92 @@ +// Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de> +// See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. +// +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include <cstdint> +#include "utf8.h" + +static const unsigned char s_byteTypeTable[] = +{ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7f + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9f + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // a0..bf + 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c0..df + 0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, // e0..ef + 0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, // f0..ff +}; + +const unsigned char s0 = 0 * 12; +const unsigned char s1 = 1 * 12; +const unsigned char s2 = 2 * 12; +const unsigned char s3 = 3 * 12; +const unsigned char s4 = 4 * 12; +const unsigned char s5 = 5 * 12; +const unsigned char s6 = 6 * 12; +const unsigned char s7 = 7 * 12; +const unsigned char s8 = 8 * 12; + +static const unsigned char s_transitionTable[] = +{ + s0,s1,s2,s3,s5,s8,s7,s1,s1,s1,s4,s6, // s0 + s1,s1,s1,s1,s1,s1,s1,s1,s1,s1,s1,s1, // s1 + s1,s0,s1,s1,s1,s1,s1,s0,s1,s0,s1,s1, // s2 + s1,s2,s1,s1,s1,s1,s1,s2,s1,s2,s1,s1, // s3 + s1,s1,s1,s1,s1,s1,s1,s2,s1,s1,s1,s1, // s4 + s1,s2,s1,s1,s1,s1,s1,s1,s1,s2,s1,s1, // s5 + s1,s1,s1,s1,s1,s1,s1,s3,s1,s3,s1,s1, // s6 + s1,s3,s1,s1,s1,s1,s1,s3,s1,s3,s1,s1, // s7 + s1,s3,s1,s1,s1,s1,s1,s1,s1,s1,s1,s1, // s8 +}; + +// Decodes UTF-8 encoded Unicode code point at "s". +UnicodeChar DecodeUtf8(const char* s) +{ + UnicodeChar unicodeChar; + int state = s0; + auto start = s; + + do + { + unsigned char byte = *s++; + int type = s_byteTypeTable[byte]; + + if (state == s0) + unicodeChar.code = (0xFF >> type) & byte; + else + unicodeChar.code = (unicodeChar.code << 6) | (byte & 0x3F); + + state = s_transitionTable[state + type]; + + if (state == s1) + { + unicodeChar.code = -1; + return unicodeChar; + } + } while (state != s0); + + unicodeChar.encodingLength = s - start; + + return unicodeChar; +} diff --git a/tools/preproc/utf8.h b/tools/preproc/utf8.h new file mode 100644 index 0000000..259de67 --- /dev/null +++ b/tools/preproc/utf8.h @@ -0,0 +1,34 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef UTF8_H +#define UTF8_H + +#include <cstdint> + +struct UnicodeChar +{ + std::int32_t code; + int encodingLength; +}; + +UnicodeChar DecodeUtf8(const char* s); + +#endif // UTF8_H diff --git a/tools/ramscrgen/.gitignore b/tools/ramscrgen/.gitignore new file mode 100644 index 0000000..4d0ae82 --- /dev/null +++ b/tools/ramscrgen/.gitignore @@ -0,0 +1 @@ +ramscrgen diff --git a/tools/ramscrgen/LICENSE b/tools/ramscrgen/LICENSE new file mode 100644 index 0000000..534d153 --- /dev/null +++ b/tools/ramscrgen/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2016 YamaArashi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/tools/ramscrgen/Makefile b/tools/ramscrgen/Makefile new file mode 100644 index 0000000..2e51e4c --- /dev/null +++ b/tools/ramscrgen/Makefile @@ -0,0 +1,18 @@ +CXX := g++ + +CXXFLAGS := -std=c++11 -O2 -s -Wall -Wno-switch -Werror + +SRCS := main.cpp sym_file.cpp elf.cpp + +HEADERS := ramscrgen.h sym_file.h elf.h char_util.h + +.PHONY: all clean + +all: ramscrgen + @: + +ramscrgen: $(SRCS) $(HEADERS) + $(CXX) $(CXXFLAGS) $(SRCS) -o $@ $(LDFLAGS) + +clean: + $(RM) ramscrgen ramscrgen.exe diff --git a/tools/ramscrgen/char_util.h b/tools/ramscrgen/char_util.h new file mode 100644 index 0000000..ab20dbc --- /dev/null +++ b/tools/ramscrgen/char_util.h @@ -0,0 +1,71 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef CHAR_UTIL_H +#define CHAR_UTIL_H + +#include <cstdint> +#include <cassert> + +inline bool IsAscii(unsigned char c) +{ + return (c < 128); +} + +inline bool IsAsciiAlpha(unsigned char c) +{ + return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')); +} + +inline bool IsAsciiDigit(unsigned char c) +{ + return (c >= '0' && c <= '9'); +} + +inline bool IsAsciiHexDigit(unsigned char c) +{ + return ((c >= '0' && c <= '9') + || (c >= 'a' && c <= 'f') + || (c >= 'A' && c <= 'F')); +} + +inline bool IsAsciiAlphanum(unsigned char c) +{ + return (IsAsciiAlpha(c) || IsAsciiDigit(c)); +} + +inline bool IsAsciiPrintable(unsigned char c) +{ + return (c >= ' ' && c <= '~'); +} + +// Returns whether the character can start the identifier of a "{FOO}" constant in strings. +inline bool IsIdentifierStartingChar(unsigned char c) +{ + return IsAsciiAlpha(c) || c == '_'; +} + +// Returns whether the character can be used in the identifier of a "{FOO}" constant in strings. +inline bool IsIdentifierChar(unsigned char c) +{ + return IsAsciiAlphanum(c) || c == '_'; +} + +#endif // CHAR_UTIL_H diff --git a/tools/ramscrgen/elf.cpp b/tools/ramscrgen/elf.cpp new file mode 100644 index 0000000..7599fe0 --- /dev/null +++ b/tools/ramscrgen/elf.cpp @@ -0,0 +1,195 @@ +#include <cstdio> +#include <cstring> +#include <cstdint> +#include <map> +#include <vector> +#include <string> +#include "ramscrgen.h" +#include "elf.h" + +#define SHN_COMMON 0xFFF2 + +static std::string s_elfPath; + +static FILE *s_file; + +static std::uint32_t s_sectionHeaderOffset; +static int s_sectionHeaderEntrySize; +static int s_sectionCount; +static int s_shstrtabIndex; + +static std::uint32_t s_symtabOffset; +static std::uint32_t s_strtabOffset; + +static std::uint32_t s_symbolCount; + +struct Symbol +{ + std::uint32_t nameOffset; + std::uint32_t size; +}; + +static void Seek(long offset) +{ + if (std::fseek(s_file, offset, SEEK_SET) != 0) + FATAL_ERROR("error: failed to seek to %ld in \"%s\"", offset, s_elfPath.c_str()); +} + +static void Skip(long offset) +{ + if (std::fseek(s_file, offset, SEEK_CUR) != 0) + FATAL_ERROR("error: failed to skip %ld bytes in \"%s\"", offset, s_elfPath.c_str()); +} + +static std::uint32_t ReadInt8() +{ + int c = std::fgetc(s_file); + + if (c < 0) + FATAL_ERROR("error: unexpected EOF when reading ELF file \"%s\"\n", s_elfPath.c_str()); + + return c; +} + +static std::uint32_t ReadInt16() +{ + std::uint32_t val = 0; + val |= ReadInt8(); + val |= ReadInt8() << 8; + return val; +} + +static std::uint32_t ReadInt32() +{ + std::uint32_t val = 0; + val |= ReadInt8(); + val |= ReadInt8() << 8; + val |= ReadInt8() << 16; + val |= ReadInt8() << 24; + return val; +} + +static std::string ReadString() +{ + std::string s; + char c; + + while ((c = ReadInt8()) != 0) + s += c; + + return s; +} + +static void VerifyElfIdent() +{ + char expectedMagic[4] = { 0x7F, 'E', 'L', 'F' }; + char magic[4]; + + if (std::fread(magic, 4, 1, s_file) != 1) + FATAL_ERROR("error: failed to read ELF magic from \"%s\"\n", s_elfPath.c_str()); + + if (std::memcmp(magic, expectedMagic, 4) != 0) + FATAL_ERROR("error: ELF magic did not match in \"%s\"\n", s_elfPath.c_str()); + + if (std::fgetc(s_file) != 1) + FATAL_ERROR("error: \"%s\" not 32-bit ELF\n", s_elfPath.c_str()); + + if (std::fgetc(s_file) != 1) + FATAL_ERROR("error: \"%s\" not little-endian ELF\n", s_elfPath.c_str()); +} + +static void ReadElfHeader() +{ + Seek(0x20); + s_sectionHeaderOffset = ReadInt32(); + Seek(0x2E); + s_sectionHeaderEntrySize = ReadInt16(); + s_sectionCount = ReadInt16(); + s_shstrtabIndex = ReadInt16(); +} + +static std::string GetSectionName(std::uint32_t shstrtabOffset, int index) +{ + Seek(s_sectionHeaderOffset + s_sectionHeaderEntrySize * index); + std::uint32_t nameOffset = ReadInt32(); + Seek(shstrtabOffset + nameOffset); + return ReadString(); +} + +static void FindTableOffsets() +{ + s_symtabOffset = 0; + s_strtabOffset = 0; + + Seek(s_sectionHeaderOffset + s_sectionHeaderEntrySize * s_shstrtabIndex + 0x10); + std::uint32_t shstrtabOffset = ReadInt32(); + + for (int i = 0; i < s_sectionCount; i++) + { + std::string name = GetSectionName(shstrtabOffset, i); + + if (name == ".symtab") + { + if (s_symtabOffset) + FATAL_ERROR("error: mutiple .symtab sections found in \"%s\"\n", s_elfPath.c_str()); + Seek(s_sectionHeaderOffset + s_sectionHeaderEntrySize * i + 0x10); + s_symtabOffset = ReadInt32(); + std::uint32_t size = ReadInt32(); + s_symbolCount = size / 16; + } + else if (name == ".strtab") + { + if (s_strtabOffset) + FATAL_ERROR("error: mutiple .strtab sections found in \"%s\"\n", s_elfPath.c_str()); + Seek(s_sectionHeaderOffset + s_sectionHeaderEntrySize * i + 0x10); + s_strtabOffset = ReadInt32(); + } + } + + if (!s_symtabOffset) + FATAL_ERROR("error: couldn't find .symtab section in \"%s\"\n", s_elfPath.c_str()); + + if (!s_strtabOffset) + FATAL_ERROR("error: couldn't find .strtab section in \"%s\"\n", s_elfPath.c_str()); +} + +std::map<std::string, std::uint32_t> GetCommonSymbols(std::string path) +{ + s_elfPath = path; + + std::map<std::string, std::uint32_t> commonSymbols; + + s_file = std::fopen(s_elfPath.c_str(), "rb"); + + if (s_file == NULL) + FATAL_ERROR("error: failed to open \"%s\" for reading\n", path.c_str()); + + VerifyElfIdent(); + ReadElfHeader(); + FindTableOffsets(); + + std::vector<Symbol> commonSymbolVec; + + Seek(s_symtabOffset); + + for (std::uint32_t i = 0; i < s_symbolCount; i++) + { + Symbol sym; + sym.nameOffset = ReadInt32(); + Skip(4); + sym.size = ReadInt32(); + Skip(2); + std::uint16_t sectionIndex = ReadInt16(); + if (sectionIndex == SHN_COMMON) + commonSymbolVec.push_back(sym); + } + + for (const Symbol& sym : commonSymbolVec) + { + Seek(s_strtabOffset + sym.nameOffset); + std::string name = ReadString(); + commonSymbols[name] = sym.size; + } + + return commonSymbols; +} diff --git a/tools/ramscrgen/elf.h b/tools/ramscrgen/elf.h new file mode 100644 index 0000000..0bfdd69 --- /dev/null +++ b/tools/ramscrgen/elf.h @@ -0,0 +1,30 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef ELF_H +#define ELF_H + +#include <cstdint> +#include <map> +#include <string> + +std::map<std::string, std::uint32_t> GetCommonSymbols(std::string path); + +#endif // ELF_H diff --git a/tools/ramscrgen/main.cpp b/tools/ramscrgen/main.cpp new file mode 100644 index 0000000..6c4f4bb --- /dev/null +++ b/tools/ramscrgen/main.cpp @@ -0,0 +1,173 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include <cstdio> +#include <cstring> +#include <string> +#include "ramscrgen.h" +#include "sym_file.h" +#include "elf.h" + +void HandleCommonInclude(std::string filename, std::string sourcePath, std::string symOrderPath, std::string lang) +{ + auto commonSymbols = GetCommonSymbols(sourcePath + "/" + filename); + + std::size_t dotIndex = filename.find_last_of('.'); + + if (dotIndex == std::string::npos) + FATAL_ERROR("error: \"%s\" doesn't have a file extension\n", filename.c_str()); + + std::string symOrderFilename = filename.substr(0, dotIndex + 1) + "txt"; + + SymFile symFile(symOrderPath + "/" + symOrderFilename); + + while (!symFile.IsAtEnd()) + { + symFile.HandleLangConditional(lang); + + std::string label = symFile.GetLabel(false); + + if (label.length() == 0) + { + unsigned long length; + if (symFile.ReadInteger(length)) + { + if (length & 3) + symFile.RaiseWarning("gap length %d is not multiple of 4", length); + printf(". += 0x%lX;\n", length); + } + } + else + { + if (commonSymbols.count(label) == 0) + symFile.RaiseError("no common symbol named \"%s\"", label.c_str()); + unsigned long size = commonSymbols[label]; + int alignment = 4; + if (size > 4) + alignment = 8; + if (size > 8) + alignment = 16; + printf(". = ALIGN(%d);\n", alignment); + printf("%s = .;\n", label.c_str()); + printf(". += 0x%lX;\n", size); + } + + symFile.ExpectEmptyRestOfLine(); + } +} + +void ConvertSymFile(std::string filename, std::string sectionName, std::string lang, bool common, std::string sourcePath, std::string commonSymPath) +{ + SymFile symFile(filename); + + while (!symFile.IsAtEnd()) + { + symFile.HandleLangConditional(lang); + + Directive directive = symFile.GetDirective(); + + switch (directive) + { + case Directive::Include: + { + std::string incFilename = symFile.ReadPath(); + symFile.ExpectEmptyRestOfLine(); + printf(". = ALIGN(4);\n"); + if (common) + HandleCommonInclude(incFilename, sourcePath, commonSymPath, lang); + else + printf("%s(%s);\n", incFilename.c_str(), sectionName.c_str()); + break; + } + case Directive::Space: + { + unsigned long length; + if (!symFile.ReadInteger(length)) + symFile.RaiseError("expected integer after .space directive"); + symFile.ExpectEmptyRestOfLine(); + printf(". += 0x%lX;\n", length); + break; + } + case Directive::Align: + { + unsigned long amount; + if (!symFile.ReadInteger(amount)) + symFile.RaiseError("expected integer after .align directive"); + if (amount > 4) + symFile.RaiseError("max alignment amount is 4"); + amount = 1UL << amount; + symFile.ExpectEmptyRestOfLine(); + printf(". = ALIGN(%lu);\n", amount); + break; + } + case Directive::Unknown: + { + std::string label = symFile.GetLabel(); + + if (label.length() != 0) + { + printf("%s = .;\n", label.c_str()); + } + + symFile.ExpectEmptyRestOfLine(); + + break; + } + } + } +} + +int main(int argc, char **argv) +{ + if (argc < 4) + { + fprintf(stderr, "Usage: %s SECTION_NAME SYM_FILE LANG [-c SRC_PATH,COMMON_SYM_PATH]", argv[0]); + return 1; + } + + bool common = false; + std::string sectionName = std::string(argv[1]); + std::string symFileName = std::string(argv[2]); + std::string lang = std::string(argv[3]); + std::string sourcePath; + std::string commonSymPath; + + if (argc > 4) + { + if (std::strcmp(argv[4], "-c") != 0) + FATAL_ERROR("error: unrecognized argument \"%s\"\n", argv[4]); + + if (argc < 6) + FATAL_ERROR("error: missing SRC_PATH,COMMON_SYM_PATH after \"-c\"\n"); + + common = true; + std::string paths = std::string(argv[5]); + std::size_t commaPos = paths.find(','); + + if (commaPos == std::string::npos) + FATAL_ERROR("error: missing comma in argument after \"-c\"\n"); + + sourcePath = paths.substr(0, commaPos); + commonSymPath = paths.substr(commaPos + 1); + } + + ConvertSymFile(symFileName, sectionName, lang, common, sourcePath, commonSymPath); + return 0; +} diff --git a/tools/ramscrgen/ramscrgen.h b/tools/ramscrgen/ramscrgen.h new file mode 100644 index 0000000..1aed1c0 --- /dev/null +++ b/tools/ramscrgen/ramscrgen.h @@ -0,0 +1,49 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef RAMSCRGEN_H +#define RAMSCRGEN_H + +#include <cstdio> +#include <cstdlib> + +#ifdef _MSC_VER + +#define FATAL_ERROR(format, ...) \ +do \ +{ \ + std::fprintf(stderr, format, __VA_ARGS__); \ + std::exit(1); \ +} while (0) + +#else + +#define FATAL_ERROR(format, ...) \ +do \ +{ \ + std::fprintf(stderr, format, ##__VA_ARGS__); \ + std::exit(1); \ +} while (0) + +#endif // _MSC_VER + +const int kMaxPath = 256; + +#endif // RAMSCRGEN_H diff --git a/tools/ramscrgen/sym_file.cpp b/tools/ramscrgen/sym_file.cpp new file mode 100644 index 0000000..5379bd9 --- /dev/null +++ b/tools/ramscrgen/sym_file.cpp @@ -0,0 +1,492 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include <cstdio> +#include <cstdarg> +#include <climits> +#include "ramscrgen.h" +#include "sym_file.h" +#include "char_util.h" + +SymFile::SymFile(std::string filename) : m_filename(filename) +{ + FILE *fp = std::fopen(filename.c_str(), "rb"); + + if (fp == NULL) + FATAL_ERROR("Failed to open \"%s\" for reading.\n", filename.c_str()); + + std::fseek(fp, 0, SEEK_END); + + m_size = std::ftell(fp); + + if (m_size < 0) + FATAL_ERROR("File size of \"%s\" is less than zero.\n", filename.c_str()); + + m_buffer = new char[m_size + 1]; + + std::rewind(fp); + + if (std::fread(m_buffer, m_size, 1, fp) != 1) + FATAL_ERROR("Failed to read \"%s\".\n", filename.c_str()); + + m_buffer[m_size] = 0; + + std::fclose(fp); + + m_pos = 0; + m_lineNum = 1; + m_lineStart = 0; + m_inLangConditional = false; + + RemoveComments(); +} + +SymFile::SymFile(SymFile&& other) : m_filename(std::move(other.m_filename)) +{ + m_buffer = other.m_buffer; + m_pos = other.m_pos; + m_size = other.m_size; + m_lineNum = other.m_lineNum; + m_lineStart = other.m_lineStart; + + other.m_buffer = nullptr; +} + +SymFile::~SymFile() +{ + delete[] m_buffer; +} + +// Removes comments to simplify further processing. +// It stops upon encountering a null character, +// which may or may not be the end of file marker. +// If it's not, the error will be caught later. +void SymFile::RemoveComments() +{ + long pos = 0; + char stringChar = 0; + + for (;;) + { + if (m_buffer[pos] == 0) + return; + + if (stringChar != 0) + { + if (m_buffer[pos] == '\\' && m_buffer[pos + 1] == stringChar) + { + pos += 2; + } + else + { + if (m_buffer[pos] == stringChar) + stringChar = 0; + pos++; + } + } + else if (m_buffer[pos] == '@' && (pos == 0 || m_buffer[pos - 1] != '\\')) + { + while (m_buffer[pos] != '\n' && m_buffer[pos] != 0) + m_buffer[pos++] = ' '; + } + else if (m_buffer[pos] == '/' && m_buffer[pos + 1] == '*') + { + m_buffer[pos++] = ' '; + m_buffer[pos++] = ' '; + + char commentStringChar = 0; + + for (;;) + { + if (m_buffer[pos] == 0) + return; + + if (commentStringChar != 0) + { + if (m_buffer[pos] == '\\' && m_buffer[pos + 1] == commentStringChar) + { + m_buffer[pos++] = ' '; + m_buffer[pos++] = ' '; + } + else + { + if (m_buffer[pos] == commentStringChar) + commentStringChar = 0; + if (m_buffer[pos] != '\n') + m_buffer[pos] = ' '; + pos++; + } + } + else + { + if (m_buffer[pos] == '*' && m_buffer[pos + 1] == '/') + { + m_buffer[pos++] = ' '; + m_buffer[pos++] = ' '; + break; + } + else + { + if (m_buffer[pos] == '"' || m_buffer[pos] == '\'') + commentStringChar = m_buffer[pos]; + if (m_buffer[pos] != '\n') + m_buffer[pos] = ' '; + pos++; + } + } + } + } + else + { + if (m_buffer[pos] == '"' || m_buffer[pos] == '\'') + stringChar = m_buffer[pos]; + pos++; + } + } +} + +// Checks if we're at a particular directive and if so, consumes it. +// Returns whether the directive was found. +bool SymFile::CheckForDirective(std::string name) +{ + long i; + long length = static_cast<long>(name.length()); + + for (i = 0; i < length && m_pos + i < m_size; i++) + if (name[i] != m_buffer[m_pos + i]) + return false; + + if (i < length) + return false; + + m_pos += length; + + return true; +} + +// Checks if we're at a known directive and if so, consumes it. +// Returns which directive was found. +Directive SymFile::GetDirective() +{ + SkipWhitespace(); + + if (CheckForDirective(".include")) + return Directive::Include; + else if (CheckForDirective(".space")) + return Directive::Space; + else if (CheckForDirective(".align")) + return Directive::Align; + else + return Directive::Unknown; +} + +// Checks if we're at label. +// Returns the name if so and an empty string if not. +std::string SymFile::GetLabel(bool requireColon) +{ + long start = m_pos; + long pos = m_pos; + + if (IsIdentifierStartingChar(m_buffer[pos])) + { + pos++; + + while (IsIdentifierChar(m_buffer[pos])) + pos++; + } + + if (requireColon) + { + if (m_buffer[pos] == ':') + { + if (pos != start) + m_pos = pos + 1; + } + else + { + pos = start; + } + } + else + { + m_pos = pos; + } + + return std::string(&m_buffer[start], pos - start); +} + +// Skips tabs and spaces. +void SymFile::SkipWhitespace() +{ + while (m_buffer[m_pos] == '\t' || m_buffer[m_pos] == ' ') + m_pos++; +} + +// Reads include path. +std::string SymFile::ReadPath() +{ + SkipWhitespace(); + + if (m_buffer[m_pos] != '"') + RaiseError("expected file path"); + + m_pos++; + + int length = 0; + long startPos = m_pos; + + while (m_buffer[m_pos] != '"') + { + unsigned char c = m_buffer[m_pos++]; + + if (c == 0) + { + if (m_pos >= m_size) + RaiseError("unexpected EOF in include string"); + else + RaiseError("unexpected null character in include string"); + } + + if (!IsAsciiPrintable(c)) + RaiseError("unexpected character '\\x%02X' in include string", c); + + // Don't bother allowing any escape sequences. + if (c == '\\') + { + c = m_buffer[m_pos]; + RaiseError("unexpected escape '\\%c' in include string", c); + } + + length++; + + if (length > kMaxPath) + RaiseError("path is too long"); + } + + m_pos++; // Go past the right quote. + + return std::string(&m_buffer[startPos], length); +} + +// If we're at a comma, consumes it. +// Returns whether a comma was found. +bool SymFile::ConsumeComma() +{ + if (m_buffer[m_pos] == ',') + { + m_pos++; + return true; + } + + return false; +} + +// Converts digit character to numerical value. +static int ConvertDigit(char c, int radix) +{ + int digit; + + if (c >= '0' && c <= '9') + digit = c - '0'; + else if (c >= 'A' && c <= 'F') + digit = 10 + c - 'A'; + else if (c >= 'a' && c <= 'f') + digit = 10 + c - 'a'; + else + return -1; + + return (digit < radix) ? digit : -1; +} + +// Reads an integer. +bool SymFile::ReadInteger(unsigned long& n) +{ + SkipWhitespace(); + + if (!IsAsciiDigit(m_buffer[m_pos])) + return false; + + int startPos = m_pos; + int radix = 10; + + if (m_buffer[m_pos] == '0' && m_buffer[m_pos + 1] == 'x') + { + radix = 16; + m_pos += 2; + } + + unsigned long cutoff = ULONG_MAX / radix; + unsigned long cutoffRemainder = ULONG_MAX % radix; + int digit; + + n = 0; + + while ((digit = ConvertDigit(m_buffer[m_pos], radix)) != -1) + { + if (n < cutoff || (n == cutoff && (unsigned long)digit <= cutoffRemainder)) + { + n = n * radix + digit; + } + else + { + m_pos++; + + while (ConvertDigit(m_buffer[m_pos], radix) != -1) + m_pos++; + + RaiseError("integer is too large (%s)", std::string(&m_buffer[startPos], m_pos - startPos).c_str()); + } + + m_pos++; + } + + return true; +} + +// Asserts that the rest of the line is empty and moves to the next one. +void SymFile::ExpectEmptyRestOfLine() +{ + SkipWhitespace(); + + if (m_buffer[m_pos] == 0) + { + if (m_pos >= m_size) + RaiseWarning("file doesn't end with newline"); + else + RaiseError("unexpected null character"); + } + else if (m_buffer[m_pos] == '\n') + { + m_pos++; + m_lineStart = m_pos; + m_lineNum++; + } + else if (m_buffer[m_pos] == '\r') + { + RaiseError("only Unix-style LF newlines are supported"); + } + else + { + RaiseError("junk at end of line"); + } +} + + +void SymFile::SkipLine() +{ + while (m_buffer[m_pos] != 0 && m_buffer[m_pos] != '\n') + m_pos++; + + if (m_buffer[m_pos] == '\n') + m_pos++; +} + +// Checks if we're at the end of the file. +bool SymFile::IsAtEnd() +{ + return (m_pos >= m_size); +} + +void SymFile::HandleLangConditional(std::string lang) +{ + if (m_buffer[m_pos] != '#') + return; + + m_pos++; + + if (CheckForDirective("begin")) + { + if (m_inLangConditional) + RaiseError("already inside language conditional"); + + SkipWhitespace(); + + std::string label = GetLabel(false); + + if (label.length() == 0) + RaiseError("no language name after #begin"); + + ExpectEmptyRestOfLine(); + + if (lang == label) + { + m_inLangConditional = true; + } + else + { + while (!IsAtEnd() && m_buffer[m_pos] != '#') + SkipLine(); + + if (m_buffer[m_pos] != '#') + RaiseError("unterminated language conditional"); + + m_pos++; + + if (!CheckForDirective("end")) + RaiseError("expected #end"); + + ExpectEmptyRestOfLine(); + } + } + else if (CheckForDirective("end")) + { + if (!m_inLangConditional) + RaiseError("not inside language conditional"); + + m_inLangConditional = false; + + ExpectEmptyRestOfLine(); + } + else + { + RaiseError("unknown # directive"); + } +} + +// Reports a diagnostic message. +void SymFile::ReportDiagnostic(const char* type, const char* format, std::va_list args) +{ + const int bufferSize = 1024; + char buffer[bufferSize]; + std::vsnprintf(buffer, bufferSize, format, args); + std::fprintf(stderr, "%s:%ld: %s: %s\n", m_filename.c_str(), m_lineNum, type, buffer); +} + +#define DO_REPORT(type) \ +do \ +{ \ + std::va_list args; \ + va_start(args, format); \ + ReportDiagnostic(type, format, args); \ + va_end(args); \ +} while (0) + +// Reports an error diagnostic and terminates the program. +void SymFile::RaiseError(const char* format, ...) +{ + DO_REPORT("error"); + std::exit(1); +} + +// Reports a warning diagnostic. +void SymFile::RaiseWarning(const char* format, ...) +{ + DO_REPORT("warning"); +} diff --git a/tools/ramscrgen/sym_file.h b/tools/ramscrgen/sym_file.h new file mode 100644 index 0000000..bb0c803 --- /dev/null +++ b/tools/ramscrgen/sym_file.h @@ -0,0 +1,71 @@ +// Copyright(c) 2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef SYM_FILE_H +#define SYM_FILE_H + +#include <cstdarg> +#include <cstdint> +#include <string> +#include "ramscrgen.h" + +enum class Directive +{ + Include, + Space, + Align, + Unknown +}; + +class SymFile +{ +public: + SymFile(std::string filename); + SymFile(SymFile&& other); + SymFile(const SymFile&) = delete; + ~SymFile(); + Directive GetDirective(); + std::string GetLabel(bool requireColon = true); + std::string ReadPath(); + bool ReadInteger(unsigned long& value); + void ExpectEmptyRestOfLine(); + void SkipLine(); + bool IsAtEnd(); + void HandleLangConditional(std::string lang); + void RaiseError(const char* format, ...); + void RaiseWarning(const char* format, ...); + +private: + char* m_buffer; + long m_pos; + long m_size; + long m_lineNum; + long m_lineStart; + std::string m_filename; + bool m_inLangConditional; + + bool ConsumeComma(); + void RemoveComments(); + bool CheckForDirective(std::string name); + void SkipWhitespace(); + void ReportDiagnostic(const char* type, const char* format, std::va_list args); +}; + +#endif // SYM_FILE_H diff --git a/tools/rsfont/.gitignore b/tools/rsfont/.gitignore new file mode 100644 index 0000000..3140ece --- /dev/null +++ b/tools/rsfont/.gitignore @@ -0,0 +1 @@ +rsfont diff --git a/tools/rsfont/LICENSE b/tools/rsfont/LICENSE new file mode 100644 index 0000000..b497950 --- /dev/null +++ b/tools/rsfont/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015-2016 YamaArashi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/tools/rsfont/Makefile b/tools/rsfont/Makefile new file mode 100644 index 0000000..041ee0c --- /dev/null +++ b/tools/rsfont/Makefile @@ -0,0 +1,18 @@ +CC = gcc + +CFLAGS = -Wall -Wextra -Werror -std=c11 -O2 -s -DPNG_SKIP_SETJMP_CHECK + +LIBS = -lpng -lz + +SRCS = main.c convert_png.c util.c font.c + +.PHONY: all clean + +all: rsfont + @: + +rsfont: $(SRCS) convert_png.h gfx.h global.h util.h font.h + $(CC) $(CFLAGS) $(SRCS) -o $@ $(LDFLAGS) $(LIBS) + +clean: + $(RM) rsfont rsfont.exe diff --git a/tools/rsfont/convert_png.c b/tools/rsfont/convert_png.c new file mode 100644 index 0000000..f6a3080 --- /dev/null +++ b/tools/rsfont/convert_png.c @@ -0,0 +1,169 @@ +// Copyright (c) 2015 YamaArashi + +#include <stdio.h> +#include <setjmp.h> +#include <png.h> +#include "global.h" +#include "convert_png.h" +#include "gfx.h" + +void ReadPng(char *path, struct Image *image) +{ + FILE *fp = fopen(path, "rb"); + + if (fp == NULL) + FATAL_ERROR("Failed to open \"%s\" for reading.\n", path); + + unsigned char sig[8]; + + if (fread(sig, 8, 1, fp) != 1) + FATAL_ERROR("Failed to read PNG signature from \"%s\".\n", path); + + if (png_sig_cmp(sig, 0, 8)) + FATAL_ERROR("\"%s\" does not have a valid PNG signature.\n", path); + + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + + if (!png_ptr) + FATAL_ERROR("Failed to create PNG read struct.\n"); + + png_infop info_ptr = png_create_info_struct(png_ptr); + + if (!info_ptr) + FATAL_ERROR("Failed to create PNG info struct.\n"); + + if (setjmp(png_jmpbuf(png_ptr))) + FATAL_ERROR("Failed to init I/O for reading \"%s\".\n", path); + + png_init_io(png_ptr, fp); + png_set_sig_bytes(png_ptr, 8); + png_read_info(png_ptr, info_ptr); + + int bit_depth = png_get_bit_depth(png_ptr, info_ptr); + + if (bit_depth != image->bitDepth) + FATAL_ERROR("\"%s\" has a bit depth of %d, but the expected bit depth is %d.\n", path, bit_depth, image->bitDepth); + + int color_type = png_get_color_type(png_ptr, info_ptr); + + if (color_type != PNG_COLOR_TYPE_GRAY && color_type != PNG_COLOR_TYPE_PALETTE) + FATAL_ERROR("\"%s\" has an unsupported color type.\n", path); + + // Check if the image has a palette so that we can tell if the colors need to be inverted later. + // Don't read the palette because it's not needed for now. + image->hasPalette = (color_type == PNG_COLOR_TYPE_PALETTE); + + image->width = png_get_image_width(png_ptr, info_ptr); + image->height = png_get_image_height(png_ptr, info_ptr); + + int rowbytes = png_get_rowbytes(png_ptr, info_ptr); + + image->pixels = malloc(image->height * rowbytes); + + if (image->pixels == NULL) + FATAL_ERROR("Failed to allocate pixel buffer.\n"); + + png_bytepp row_pointers = malloc(image->height * sizeof(png_bytep)); + + if (row_pointers == NULL) + FATAL_ERROR("Failed to allocate row pointers.\n"); + + for (int i = 0; i < image->height; i++) + row_pointers[i] = (png_bytep)(image->pixels + (i * rowbytes)); + + if (setjmp(png_jmpbuf(png_ptr))) + FATAL_ERROR("Error reading from \"%s\".\n", path); + + png_read_image(png_ptr, row_pointers); + + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + + free(row_pointers); + fclose(fp); +} + +void SetPngPalette(png_structp png_ptr, png_infop info_ptr, struct Palette *palette) +{ + png_colorp colors = malloc(palette->numColors * sizeof(png_color)); + + if (colors == NULL) + FATAL_ERROR("Failed to allocate PNG palette.\n"); + + for (int i = 0; i < palette->numColors; i++) { + colors[i].red = palette->colors[i].red; + colors[i].green = palette->colors[i].green; + colors[i].blue = palette->colors[i].blue; + } + + png_set_PLTE(png_ptr, info_ptr, colors, palette->numColors); + + free(colors); +} + +void WritePng(char *path, struct Image *image) +{ + FILE *fp = fopen(path, "wb"); + + if (fp == NULL) + FATAL_ERROR("Failed to open \"%s\" for writing.\n", path); + + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + + if (!png_ptr) + FATAL_ERROR("Failed to create PNG write struct.\n"); + + png_infop info_ptr = png_create_info_struct(png_ptr); + + if (!info_ptr) + FATAL_ERROR("Failed to create PNG info struct.\n"); + + if (setjmp(png_jmpbuf(png_ptr))) + FATAL_ERROR("Failed to init I/O for writing \"%s\".\n", path); + + png_init_io(png_ptr, fp); + + if (setjmp(png_jmpbuf(png_ptr))) + FATAL_ERROR("Error writing header for \"%s\".\n", path); + + int color_type = image->hasPalette ? PNG_COLOR_TYPE_PALETTE : PNG_COLOR_TYPE_GRAY; + + png_set_IHDR(png_ptr, info_ptr, image->width, image->height, + image->bitDepth, color_type, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + if (image->hasPalette) { + SetPngPalette(png_ptr, info_ptr, &image->palette); + + if (image->hasTransparency) { + png_byte trans = 0; + png_set_tRNS(png_ptr, info_ptr, &trans, 1, 0); + } + } + + png_write_info(png_ptr, info_ptr); + + png_bytepp row_pointers = malloc(image->height * sizeof(png_bytep)); + + if (row_pointers == NULL) + FATAL_ERROR("Failed to allocate row pointers.\n"); + + int rowbytes = png_get_rowbytes(png_ptr, info_ptr); + + for (int i = 0; i < image->height; i++) + row_pointers[i] = (png_bytep)(image->pixels + (i * rowbytes)); + + if (setjmp(png_jmpbuf(png_ptr))) + FATAL_ERROR("Error writing \"%s\".\n", path); + + png_write_image(png_ptr, row_pointers); + + if (setjmp(png_jmpbuf(png_ptr))) + FATAL_ERROR("Error ending write of \"%s\".\n", path); + + png_write_end(png_ptr, NULL); + + fclose(fp); + + png_destroy_write_struct(&png_ptr, &info_ptr); + free(row_pointers); +} diff --git a/tools/rsfont/convert_png.h b/tools/rsfont/convert_png.h new file mode 100644 index 0000000..55d3d69 --- /dev/null +++ b/tools/rsfont/convert_png.h @@ -0,0 +1,11 @@ +// Copyright (c) 2015 YamaArashi + +#ifndef CONVERT_PNG_H +#define CONVERT_PNG_H + +#include "gfx.h" + +void ReadPng(char *path, struct Image *image); +void WritePng(char *path, struct Image *image); + +#endif // CONVERT_PNG_H diff --git a/tools/rsfont/font.c b/tools/rsfont/font.c new file mode 100644 index 0000000..ed48b31 --- /dev/null +++ b/tools/rsfont/font.c @@ -0,0 +1,455 @@ +// Copyright(c) 2015-2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdbool.h> +#include "global.h" +#include "font.h" +#include "gfx.h" +#include "util.h" + +unsigned char gFontPalette[][3] = +{ + {0xFF, 0xFF, 0xFF}, // bg (white) + {0x38, 0x38, 0x38}, // fg (dark grey) + {0xD8, 0xD8, 0xD8}, // shadow (light grey) +}; + +void ConvertFromTiles1Bpp(unsigned char *src, unsigned char *dest, int numGlyphs, int layout) +{ + for (int glyph = 0; glyph < numGlyphs; glyph++) + { + if (layout == 0) + { + for (int i = 0; i < 8; i++) + { + uint8_t srcRow = src[(glyph * 8) + i]; + + for (int j = 0; j < 8; j++) + { + int x = ((glyph % 16) * 8) + j; + int y = ((glyph / 16) * 8) + i; + dest[(y * 128) + x] = (srcRow >> (7 - j)) & 1; + } + } + } + else + { + // layout type 1 + + int tile1Offset = glyph * 16; + int tile2Offset = tile1Offset + 8; + + for (int i = 0; i < 8; i++) + { + uint8_t srcRow = src[tile1Offset + i]; + + for (int j = 0; j < 8; j++) + { + int x = ((glyph % 16) * 8) + j; + int y = ((glyph / 16) * 16) + i; + dest[(y * 128) + x] = (srcRow >> (7 - j)) & 1; + } + } + + for (int i = 0; i < 8; i++) + { + uint8_t srcRow = src[tile2Offset + i]; + + for (int j = 0; j < 8; j++) + { + int x = ((glyph % 16) * 8) + j; + int y = ((glyph / 16) * 16) + 8 + i; + dest[(y * 128) + x] = (srcRow >> (7 - j)) & 1; + } + } + } + } +} + +void ConvertToTiles1Bpp(unsigned char *src, unsigned char *dest, int numGlyphs, int layout) +{ + for (int glyph = 0; glyph < numGlyphs; glyph++) + { + if (layout == 0) + { + for (int i = 0; i < 8; i++) + { + uint8_t destRow = 0; + + for (int j = 0; j < 8; j++) + { + int x = ((glyph % 16) * 8) + j; + int y = ((glyph / 16) * 8) + i; + unsigned char color = src[(y * 128) + x]; + + if (color > 1) + FATAL_ERROR("More than 2 colors in 1 BPP font.\n"); + + destRow <<= 1; + destRow |= color; + } + + dest[(glyph * 8) + i] = destRow; + } + } + else + { + // layout type 1 + + int tile1Offset = glyph * 16; + int tile2Offset = tile1Offset + 8; + + for (int i = 0; i < 8; i++) + { + uint8_t destRow = 0; + + for (int j = 0; j < 8; j++) + { + int x = ((glyph % 16) * 8) + j; + int y = ((glyph / 16) * 16) + i; + unsigned char color = src[(y * 128) + x]; + + if (color > 1) + FATAL_ERROR("More than 2 colors in 1 BPP font.\n"); + + destRow <<= 1; + destRow |= color; + } + + dest[tile1Offset + i] = destRow; + } + + for (int i = 0; i < 8; i++) + { + uint8_t destRow = 0; + + for (int j = 0; j < 8; j++) + { + int x = ((glyph % 16) * 8) + j; + int y = ((glyph / 16) * 16) + 8 + i; + unsigned char color = src[(y * 128) + x]; + + if (color > 1) + FATAL_ERROR("More than 2 colors in 1 BPP font.\n"); + + destRow <<= 1; + destRow |= color; + } + + dest[tile2Offset + i] = destRow; + } + } + } +} + +void ConvertFromTiles4Bpp(unsigned char *src, unsigned char *dest, int numGlyphs, int layout) +{ + static unsigned char table[16] = + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, + }; + + for (int glyph = 0; glyph < numGlyphs; glyph++) + { + if (layout == 0) + { + int offset = glyph * 32; + + for (int i = 0; i < 8; i++) + { + uint32_t srcRow = (src[offset + 3] << 24) + | (src[offset + 2] << 16) + | (src[offset + 1] << 8) + | src[offset]; + + for (int j = 0; j < 8; j++) + { + int x = ((glyph % 16) * 8) + j; + int y = ((glyph / 16) * 8) + i; + dest[(y * 128) + x] = table[srcRow & 0xF]; + srcRow >>= 4; + } + + offset += 4; + } + } + else + { + int tile1Offset; + int tile2Offset; + + if (layout == 1) + { + tile1Offset = glyph * 64; + tile2Offset = tile1Offset + 32; + } + else + { + tile1Offset = ((glyph / 16) * 1024) + ((glyph % 16) * 32); + tile2Offset = tile1Offset + 512; + } + + for (int i = 0; i < 8; i++) + { + uint32_t srcRow = (src[tile1Offset + 3] << 24) + | (src[tile1Offset + 2] << 16) + | (src[tile1Offset + 1] << 8) + | src[tile1Offset]; + + for (int j = 0; j < 8; j++) + { + int x = ((glyph % 16) * 8) + j; + int y = ((glyph / 16) * 16) + i; + dest[(y * 128) + x] = table[srcRow & 0xF]; + srcRow >>= 4; + } + + tile1Offset += 4; + } + + for (int i = 0; i < 8; i++) + { + uint32_t srcRow = (src[tile2Offset + 3] << 24) + | (src[tile2Offset + 2] << 16) + | (src[tile2Offset + 1] << 8) + | src[tile2Offset]; + + for (int j = 0; j < 8; j++) + { + int x = ((glyph % 16) * 8) + j; + int y = ((glyph / 16) * 16) + 8 + i; + dest[(y * 128) + x] = table[srcRow & 0xF]; + srcRow >>= 4; + } + + tile2Offset += 4; + } + } + } +} + +void ConvertToTiles4Bpp(unsigned char *src, unsigned char *dest, int numGlyphs, int layout) +{ + static unsigned char table[3] = + { + 0, 15, 14, + }; + + for (int glyph = 0; glyph < numGlyphs; glyph++) + { + if (layout == 0) + { + int offset = glyph * 32; + + for (int i = 0; i < 8; i++) + { + uint32_t destRow = 0; + + for (int j = 0; j < 8; j++) + { + int x = ((glyph % 16) * 8) + j; + int y = ((glyph / 16) * 8) + i; + unsigned char color = src[(y * 128) + x]; + + if (color > 2) + FATAL_ERROR("More than 3 colors in 4 BPP font.\n"); + + destRow >>= 4; + destRow |= (table[color] << 28); + } + + dest[offset] = destRow & 0xFF; + dest[offset + 1] = (destRow >> 8) & 0xFF; + dest[offset + 2] = (destRow >> 16) & 0xFF; + dest[offset + 3] = (destRow >> 24) & 0xFF; + + offset += 4; + } + } + else + { + int tile1Offset; + int tile2Offset; + + if (layout == 1) + { + tile1Offset = glyph * 64; + tile2Offset = tile1Offset + 32; + } + else + { + tile1Offset = ((glyph / 16) * 1024) + ((glyph % 16) * 32); + tile2Offset = tile1Offset + 512; + } + + for (int i = 0; i < 8; i++) + { + uint32_t destRow = 0; + + for (int j = 0; j < 8; j++) + { + int x = ((glyph % 16) * 8) + j; + int y = ((glyph / 16) * 16) + i; + unsigned char color = src[(y * 128) + x]; + + if (color > 2) + FATAL_ERROR("More than 3 colors in 4 BPP font.\n"); + + destRow >>= 4; + destRow |= (table[color] << 28); + } + + dest[tile1Offset] = destRow & 0xFF; + dest[tile1Offset + 1] = (destRow >> 8) & 0xFF; + dest[tile1Offset + 2] = (destRow >> 16) & 0xFF; + dest[tile1Offset + 3] = (destRow >> 24) & 0xFF; + + tile1Offset += 4; + } + + for (int i = 0; i < 8; i++) + { + uint32_t destRow = 0; + + for (int j = 0; j < 8; j++) + { + int x = ((glyph % 16) * 8) + j; + int y = ((glyph / 16) * 16) + 8 + i; + unsigned char color = src[(y * 128) + x]; + + if (color > 2) + FATAL_ERROR("More than 3 colors in 4 BPP font.\n"); + + destRow >>= 4; + destRow |= (table[color] << 28); + } + + dest[tile2Offset] = destRow & 0xFF; + dest[tile2Offset + 1] = (destRow >> 8) & 0xFF; + dest[tile2Offset + 2] = (destRow >> 16) & 0xFF; + dest[tile2Offset + 3] = (destRow >> 24) & 0xFF; + + tile2Offset += 4; + } + } + } +} + +static void SetFontPalette(struct Image *image) +{ + image->hasPalette = true; + + image->palette.numColors = 3; + + for (int i = 0; i < image->palette.numColors; i++) + { + image->palette.colors[i].red = gFontPalette[i][0]; + image->palette.colors[i].green = gFontPalette[i][1]; + image->palette.colors[i].blue = gFontPalette[i][2]; + } + + image->hasTransparency = false; +} + +int CalcFileSize(int numGlyphs, int bpp, int layout) +{ + if (layout == 2) + { + // assume 4 BPP + int numFullRows = numGlyphs / 16; + int remainder = numGlyphs % 16; + int fullRowsSize = numFullRows * 1024; + int remainderSize = 0; + + if (remainder != 0) + remainderSize = 1024 - (16 - remainder) * 32; + + return fullRowsSize + remainderSize; + } + else + { + int tilesPerGlyph = layout > 0 ? 2 : 1; + int bytesPerTile = 8 * bpp; + return numGlyphs * tilesPerGlyph * bytesPerTile; + } +} + +void ReadFont(char *path, struct Image *image, int numGlyphs, int bpp, int layout) +{ + int fileSize; + unsigned char *buffer = ReadWholeFile(path, &fileSize); + + int expectedFileSize = CalcFileSize(numGlyphs, bpp, layout); + + if (fileSize != expectedFileSize) + FATAL_ERROR("The file size is %d but should be %d.\n", fileSize, expectedFileSize); + + int numRows = (numGlyphs + 15) / 16; + int rowHeight = layout > 0 ? 16 : 8; + + image->width = 128; + image->height = numRows * rowHeight; + image->bitDepth = 8; + image->pixels = calloc(image->width * image->height, 1); + + if (image->pixels == NULL) + FATAL_ERROR("Failed to allocate memory for font.\n"); + + if (bpp == 1) + ConvertFromTiles1Bpp(buffer, image->pixels, numGlyphs, layout); + else + ConvertFromTiles4Bpp(buffer, image->pixels, numGlyphs, layout); + + free(buffer); + + SetFontPalette(image); +} + +void WriteFont(char *path, struct Image *image, int numGlyphs, int bpp, int layout) +{ + if (image->width != 128) + FATAL_ERROR("The width of the font image (%d) is not 128.\n", image->width); + + int numRows = (numGlyphs + 15) / 16; + int rowHeight = layout > 0 ? 16 : 8; + int expectedHeight = numRows * rowHeight; + + if (image->height < expectedHeight) + FATAL_ERROR("The height of the font image (%d) is less than %d.\n", image->height, expectedHeight); + + int fileSize = CalcFileSize(numGlyphs, bpp, layout); + + unsigned char *buffer = calloc(fileSize, 1); + + if (buffer == NULL) + FATAL_ERROR("Failed to allocate memory for font.\n"); + + if (bpp == 1) + ConvertToTiles1Bpp(image->pixels, buffer, numGlyphs, layout); + else + ConvertToTiles4Bpp(image->pixels, buffer, numGlyphs, layout); + + WriteWholeFile(path, buffer, fileSize); + + free(buffer); +} diff --git a/tools/rsfont/font.h b/tools/rsfont/font.h new file mode 100644 index 0000000..1cd4875 --- /dev/null +++ b/tools/rsfont/font.h @@ -0,0 +1,30 @@ +// Copyright(c) 2015-2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef FONT_H +#define FONT_H + +#include <stdbool.h> +#include "gfx.h" + +void ReadFont(char *path, struct Image *image, int numGlyphs, int bpp, int layout); +void WriteFont(char *path, struct Image *image, int numGlyphs, int bpp, int layout); + +#endif // FONT_H diff --git a/tools/rsfont/gfx.h b/tools/rsfont/gfx.h new file mode 100644 index 0000000..04a3d80 --- /dev/null +++ b/tools/rsfont/gfx.h @@ -0,0 +1,50 @@ +// Copyright(c) 2015-2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef GFX_H +#define GFX_H + +#include <stdint.h> +#include <stdbool.h> + +struct Color +{ + unsigned char red; + unsigned char green; + unsigned char blue; +}; + +struct Palette +{ + struct Color colors[256]; + int numColors; +}; + +struct Image { + int width; + int height; + int bitDepth; + unsigned char *pixels; + bool hasPalette; + struct Palette palette; + bool hasTransparency; +}; + +#endif // GFX_H diff --git a/tools/rsfont/global.h b/tools/rsfont/global.h new file mode 100644 index 0000000..65dd351 --- /dev/null +++ b/tools/rsfont/global.h @@ -0,0 +1,31 @@ +// Copyright (c) 2015 YamaArashi + +#ifndef GLOBAL_H +#define GLOBAL_H + +#include <stdio.h> +#include <stdlib.h> + +#ifdef _MSC_VER + +#define FATAL_ERROR(format, ...) \ +do { \ + fprintf(stderr, format, __VA_ARGS__); \ + exit(1); \ +} while (0) + +#define UNUSED + +#else + +#define FATAL_ERROR(format, ...) \ +do { \ + fprintf(stderr, format, ##__VA_ARGS__); \ + exit(1); \ +} while (0) + +#define UNUSED __attribute__((__unused__)) + +#endif // _MSC_VER + +#endif // GLOBAL_H diff --git a/tools/rsfont/main.c b/tools/rsfont/main.c new file mode 100644 index 0000000..2f5d9d9 --- /dev/null +++ b/tools/rsfont/main.c @@ -0,0 +1,93 @@ +// Copyright(c) 2015-2016 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include <stdio.h> +#include <string.h> +#include <stdbool.h> +#include "global.h" +#include "util.h" +#include "gfx.h" +#include "convert_png.h" +#include "font.h" + +int ExtensionToBpp(const char *extension) +{ + if (!strcmp(extension, "1bpp")) + return 1; + else if (!strcmp(extension, "4bpp")) + return 4; + return 0; +} + +int main(int argc, char **argv) +{ + if (argc < 5) + FATAL_ERROR("Usage: rsfont INPUT_FILE OUTPUT_FILE NUM_GLYPHS LAYOUT_TYPE\n"); + + char *inputPath = argv[1]; + char *outputPath = argv[2]; + char *inputFileExtension = GetFileExtension(inputPath); + char *outputFileExtension = GetFileExtension(outputPath); + + if (inputFileExtension == NULL) + FATAL_ERROR("Input file \"%s\" has no extension.\n", inputPath); + + if (outputFileExtension == NULL) + FATAL_ERROR("Output file \"%s\" has no extension.\n", outputPath); + + int numGlyphs; + int bpp; + int layout; + + if (!ParseNumber(argv[3], NULL, 10, &numGlyphs)) + FATAL_ERROR("Failed to parse number of glyphs.\n"); + + if (!ParseNumber(argv[4], NULL, 10, &layout)) + FATAL_ERROR("Failed to parse layout type.\n"); + + if (layout < 0 || layout > 2) + FATAL_ERROR("Layout type %d is invalid. Layout type must be 0, 1, or 2.\n", layout); + + bool toPng; + + if (!strcmp(inputFileExtension, "png") && (bpp = ExtensionToBpp(outputFileExtension)) != 0) + toPng = false; + else if ((bpp = ExtensionToBpp(inputFileExtension)) != 0 && !strcmp(outputFileExtension, "png")) + toPng = true; + else + FATAL_ERROR("Don't know how to convert \"%s\" to \"%s\".\n", inputPath, outputPath); + + if (bpp == 1 && layout == 2) + FATAL_ERROR("Layout type 2 is not supported with 1 BPP fonts.\n"); + + struct Image image; + + if (toPng) + { + ReadFont(inputPath, &image, numGlyphs, bpp, layout); + WritePng(outputPath, &image); + } + else + { + image.bitDepth = 8; + ReadPng(inputPath, &image); + WriteFont(outputPath, &image, numGlyphs, bpp, layout); + } +} diff --git a/tools/rsfont/util.c b/tools/rsfont/util.c new file mode 100644 index 0000000..87abeb3 --- /dev/null +++ b/tools/rsfont/util.c @@ -0,0 +1,124 @@ +// Copyright (c) 2015 YamaArashi + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> +#include <errno.h> +#include <limits.h> +#include "global.h" +#include "util.h" + +bool ParseNumber(char *s, char **end, int radix, int *intValue) +{ + char *localEnd; + + if (end == NULL) + end = &localEnd; + + errno = 0; + + const long longValue = strtol(s, end, radix); + + if (*end == s) + return false; // not a number + + if ((longValue == LONG_MIN || longValue == LONG_MAX) && errno == ERANGE) + return false; + + if (longValue > INT_MAX) + return false; + + if (longValue < INT_MIN) + return false; + + *intValue = (int)longValue; + + return true; +} + +char *GetFileExtension(char *path) +{ + char *extension = path; + + while (*extension != 0) + extension++; + + while (extension > path && *extension != '.') + extension--; + + if (extension == path) + return NULL; + + extension++; + + if (*extension == 0) + return NULL; + + return extension; +} + +unsigned char *ReadWholeFile(char *path, int *size) +{ + FILE *fp = fopen(path, "rb"); + + if (fp == NULL) + FATAL_ERROR("Failed to open \"%s\" for reading.\n", path); + + fseek(fp, 0, SEEK_END); + + *size = ftell(fp); + + unsigned char *buffer = malloc(*size); + + if (buffer == NULL) + FATAL_ERROR("Failed to allocate memory for reading \"%s\".\n", path); + + rewind(fp); + + if (fread(buffer, *size, 1, fp) != 1) + FATAL_ERROR("Failed to read \"%s\".\n", path); + + fclose(fp); + + return buffer; +} + +unsigned char *ReadWholeFileZeroPadded(char *path, int *size, int padAmount) +{ + FILE *fp = fopen(path, "rb"); + + if (fp == NULL) + FATAL_ERROR("Failed to open \"%s\" for reading.\n", path); + + fseek(fp, 0, SEEK_END); + + *size = ftell(fp); + + unsigned char *buffer = calloc(*size + padAmount, 1); + + if (buffer == NULL) + FATAL_ERROR("Failed to allocate memory for reading \"%s\".\n", path); + + rewind(fp); + + if (fread(buffer, *size, 1, fp) != 1) + FATAL_ERROR("Failed to read \"%s\".\n", path); + + fclose(fp); + + return buffer; +} + +void WriteWholeFile(char *path, void *buffer, int bufferSize) +{ + FILE *fp = fopen(path, "wb"); + + if (fp == NULL) + FATAL_ERROR("Failed to open \"%s\" for writing.\n", path); + + if (fwrite(buffer, bufferSize, 1, fp) != 1) + FATAL_ERROR("Failed to write to \"%s\".\n", path); + + fclose(fp); +} diff --git a/tools/rsfont/util.h b/tools/rsfont/util.h new file mode 100644 index 0000000..6d7a9c2 --- /dev/null +++ b/tools/rsfont/util.h @@ -0,0 +1,14 @@ +// Copyright (c) 2015 YamaArashi + +#ifndef UTIL_H +#define UTIL_H + +#include <stdbool.h> + +bool ParseNumber(char *s, char **end, int radix, int *intValue); +char *GetFileExtension(char *path); +unsigned char *ReadWholeFile(char *path, int *size); +unsigned char *ReadWholeFileZeroPadded(char *path, int *size, int padAmount); +void WriteWholeFile(char *path, void *buffer, int bufferSize); + +#endif // UTIL_H diff --git a/tools/scaninc/.gitignore b/tools/scaninc/.gitignore new file mode 100644 index 0000000..94bfbf9 --- /dev/null +++ b/tools/scaninc/.gitignore @@ -0,0 +1 @@ +scaninc diff --git a/tools/scaninc/LICENSE b/tools/scaninc/LICENSE new file mode 100644 index 0000000..b66bf81 --- /dev/null +++ b/tools/scaninc/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015 YamaArashi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/tools/scaninc/Makefile b/tools/scaninc/Makefile new file mode 100644 index 0000000..32c16c3 --- /dev/null +++ b/tools/scaninc/Makefile @@ -0,0 +1,18 @@ +CXX = g++ + +CXXFLAGS = -Wall -Werror -std=c++11 -O2 -s + +SRCS = scaninc.cpp c_file.cpp asm_file.cpp + +HEADERS := scaninc.h asm_file.h c_file.h + +.PHONY: all clean + +all: scaninc + @: + +scaninc: $(SRCS) $(HEADERS) + $(CXX) $(CXXFLAGS) $(SRCS) -o $@ $(LDFLAGS) + +clean: + $(RM) scaninc scaninc.exe diff --git a/tools/scaninc/asm_file.cpp b/tools/scaninc/asm_file.cpp new file mode 100644 index 0000000..6322749 --- /dev/null +++ b/tools/scaninc/asm_file.cpp @@ -0,0 +1,191 @@ +// Copyright(c) 2015-2017 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include <cstdio> +#include <string> +#include "scaninc.h" +#include "asm_file.h" + +AsmFile::AsmFile(std::string path) +{ + m_path = path; + + FILE *fp = std::fopen(path.c_str(), "rb"); + + if (fp == NULL) + FATAL_ERROR("Failed to open \"%s\" for reading.\n", path.c_str()); + + std::fseek(fp, 0, SEEK_END); + + m_size = std::ftell(fp); + + m_buffer = new char[m_size]; + + std::rewind(fp); + + if (std::fread(m_buffer, m_size, 1, fp) != 1) + FATAL_ERROR("Failed to read \"%s\".\n", path.c_str()); + + std::fclose(fp); + + m_pos = 0; + m_lineNum = 1; +} + +AsmFile::~AsmFile() +{ + delete[] m_buffer; +} + +IncDirectiveType AsmFile::ReadUntilIncDirective(std::string &path) +{ + // At the beginning of each loop iteration, the current file position + // should be at the start of a line or at the end of the file. + for (;;) + { + SkipTabsAndSpaces(); + + IncDirectiveType incDirectiveType = IncDirectiveType::None; + + if (PeekChar() == '.') + { + m_pos++; + + if (MatchIncDirective("incbin", path)) + incDirectiveType = IncDirectiveType::Incbin; + else if (MatchIncDirective("include", path)) + incDirectiveType = IncDirectiveType::Include; + } + + for (;;) + { + int c = GetChar(); + + if (c == -1) + return incDirectiveType; + + if (c == ';') + { + SkipEndOfLineComment(); + break; + } + else if (c == '/' && PeekChar() == '*') + { + m_pos++; + SkipMultiLineComment(); + } + else if (c == '"') + { + SkipString(); + } + else if (c == '\n') + { + break; + } + } + + if (incDirectiveType != IncDirectiveType::None) + return incDirectiveType; + } +} + +std::string AsmFile::ReadPath() +{ + int length = 0; + int startPos = m_pos; + + for (;;) + { + int c = GetChar(); + + if (c == '"') + break; + + if (c == -1) + FATAL_INPUT_ERROR("unexpected EOF in include string\n"); + + if (c == 0) + FATAL_INPUT_ERROR("unexpected NUL character in include string\n"); + + if (c == '\n') + FATAL_INPUT_ERROR("unexpected end of line character in include string\n"); + + // Don't bother allowing any escape sequences. + if (c == '\\') + FATAL_INPUT_ERROR("unexpected escape in include string\n"); + + length++; + + if (length > SCANINC_MAX_PATH) + FATAL_INPUT_ERROR("path is too long"); + } + + return std::string(m_buffer + startPos, length); +} + +void AsmFile::SkipEndOfLineComment() +{ + int c; + + do + { + c = GetChar(); + } while (c != -1 && c != '\n'); +} + +void AsmFile::SkipMultiLineComment() +{ + for (;;) + { + int c = GetChar(); + + if (c == '*') + { + if (PeekChar() == '/') + { + m_pos++; + return; + } + } + else if (c == -1) + { + return; + } + } +} + +void AsmFile::SkipString() +{ + for (;;) + { + int c = GetChar(); + + if (c == '"') + break; + + if (c == -1) + FATAL_INPUT_ERROR("unexpected EOF in string\n"); + + if (c == '\\') + { + c = GetChar(); + } + } +} diff --git a/tools/scaninc/asm_file.h b/tools/scaninc/asm_file.h new file mode 100644 index 0000000..ad99b75 --- /dev/null +++ b/tools/scaninc/asm_file.h @@ -0,0 +1,119 @@ +// Copyright(c) 2015-2017 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef ASM_FILE_H +#define ASM_FILE_H + +#include <string> +#include "scaninc.h" + +enum class IncDirectiveType +{ + None, + Include, + Incbin +}; + +class AsmFile +{ +public: + AsmFile(std::string path); + ~AsmFile(); + IncDirectiveType ReadUntilIncDirective(std::string& path); + +private: + char *m_buffer; + int m_pos; + int m_size; + int m_lineNum; + std::string m_path; + + int GetChar() + { + if (m_pos >= m_size) + return -1; + + int c = m_buffer[m_pos++]; + + if (c == '\r') + { + if (m_pos < m_size && m_buffer[m_pos++] == '\n') + { + m_lineNum++; + return '\n'; + } + else + { + FATAL_INPUT_ERROR("CR line endings are not supported\n"); + } + } + + if (c == '\n') + m_lineNum++; + + return c; + } + + // No newline translation because it's not needed for any use of this function. + int PeekChar() + { + if (m_pos >= m_size) + return -1; + + return m_buffer[m_pos]; + } + + void SkipTabsAndSpaces() + { + while (m_pos < m_size && (m_buffer[m_pos] == '\t' || m_buffer[m_pos] == ' ')) + m_pos++; + } + + bool MatchIncDirective(std::string directiveName, std::string& path) + { + int length = directiveName.length(); + int i; + + for (i = 0; i < length && m_pos + i < m_size; i++) + if (directiveName[i] != m_buffer[m_pos + i]) + return false; + + if (i < length) + return false; + + m_pos += length; + + SkipTabsAndSpaces(); + + if (GetChar() != '"') + FATAL_INPUT_ERROR("no path after \".%s\" directive\n", directiveName.c_str()); + + path = ReadPath(); + + return true; + } + + std::string ReadPath(); + void SkipEndOfLineComment(); + void SkipMultiLineComment(); + void SkipString(); +}; + +#endif // ASM_FILE_H diff --git a/tools/scaninc/c_file.cpp b/tools/scaninc/c_file.cpp new file mode 100644 index 0000000..595f366 --- /dev/null +++ b/tools/scaninc/c_file.cpp @@ -0,0 +1,307 @@ +// Copyright(c) 2017 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include "c_file.h" + +CFile::CFile(std::string path) +{ + m_path = path; + + FILE *fp = std::fopen(path.c_str(), "rb"); + + if (fp == NULL) + FATAL_ERROR("Failed to open \"%s\" for reading.\n", path.c_str()); + + std::fseek(fp, 0, SEEK_END); + + m_size = std::ftell(fp); + + m_buffer = new char[m_size + 1]; + m_buffer[m_size] = 0; + + std::rewind(fp); + + if (std::fread(m_buffer, m_size, 1, fp) != 1) + FATAL_ERROR("Failed to read \"%s\".\n", path.c_str()); + + std::fclose(fp); + + m_pos = 0; + m_lineNum = 1; +} + +CFile::~CFile() +{ + delete[] m_buffer; +} + +void CFile::FindIncbins() +{ + char stringChar = 0; + + while (m_pos < m_size) + { + if (stringChar) + { + if (m_buffer[m_pos] == stringChar) + { + m_pos++; + stringChar = 0; + } + else if (m_buffer[m_pos] == '\\' && m_buffer[m_pos + 1] == stringChar) + { + m_pos += 2; + } + else + { + if (m_buffer[m_pos] == '\n') + m_lineNum++; + m_pos++; + } + } + else + { + SkipWhitespace(); + CheckInclude(); + CheckIncbin(); + + if (m_pos >= m_size) + break; + + char c = m_buffer[m_pos++]; + + if (c == '\n') + m_lineNum++; + else if (c == '"') + stringChar = '"'; + else if (c == '\'') + stringChar = '\''; + else if (c == 0) + FATAL_INPUT_ERROR("unexpected null character"); + } + } +} + +bool CFile::ConsumeHorizontalWhitespace() +{ + if (m_buffer[m_pos] == '\t' || m_buffer[m_pos] == ' ') + { + m_pos++; + return true; + } + + return false; +} + +bool CFile::ConsumeNewline() +{ + if (m_buffer[m_pos] == '\n') + { + m_pos++; + m_lineNum++; + return true; + } + + if (m_buffer[m_pos] == '\r' && m_buffer[m_pos + 1] == '\n') + { + m_pos += 2; + m_lineNum++; + return true; + } + + return false; +} + +bool CFile::ConsumeComment() +{ + if (m_buffer[m_pos] == '/' && m_buffer[m_pos + 1] == '*') + { + m_pos += 2; + while (m_buffer[m_pos] != '*' || m_buffer[m_pos + 1] != '/') + { + if (m_buffer[m_pos] == 0) + return false; + if (!ConsumeNewline()) + m_pos++; + } + m_pos += 2; + return true; + } + else if (m_buffer[m_pos] == '/' && m_buffer[m_pos + 1] == '/') + { + m_pos += 2; + while (!ConsumeNewline()) + { + if (m_buffer[m_pos] == 0) + return false; + m_pos++; + } + return true; + } + + return false; +} + +void CFile::SkipWhitespace() +{ + while (ConsumeHorizontalWhitespace() || ConsumeNewline() || ConsumeComment()) + ; +} + +bool CFile::CheckIdentifier(const std::string& ident) +{ + unsigned int i; + + for (i = 0; i < ident.length() && m_pos + i < (unsigned)m_size; i++) + if (ident[i] != m_buffer[m_pos + i]) + return false; + + return (i == ident.length()); +} + +void CFile::CheckInclude() +{ + if (m_buffer[m_pos] != '#') + return; + + std::string ident = "#include"; + + if (!CheckIdentifier(ident)) + { + return; + } + + m_pos += ident.length(); + + ConsumeHorizontalWhitespace(); + + std::string path = ReadPath(); + + if (!path.empty()) { + m_includes.emplace(path); + } +} + +void CFile::CheckIncbin() +{ + // Optimization: assume most lines are not incbins + if (!(m_buffer[m_pos+0] == 'I' + && m_buffer[m_pos+1] == 'N' + && m_buffer[m_pos+2] == 'C' + && m_buffer[m_pos+3] == 'B' + && m_buffer[m_pos+4] == 'I' + && m_buffer[m_pos+5] == 'N' + && m_buffer[m_pos+6] == '_')) + { + return; + } + + std::string idents[6] = { "INCBIN_S8", "INCBIN_U8", "INCBIN_S16", "INCBIN_U16", "INCBIN_S32", "INCBIN_U32" }; + int incbinType = -1; + + for (int i = 0; i < 6; i++) + { + if (CheckIdentifier(idents[i])) + { + incbinType = i; + break; + } + } + + if (incbinType == -1) + return; + + long oldPos = m_pos; + long oldLineNum = m_lineNum; + + m_pos += idents[incbinType].length(); + + SkipWhitespace(); + + if (m_buffer[m_pos] != '(') + { + m_pos = oldPos; + m_lineNum = oldLineNum; + return; + } + + m_pos++; + + while (true) + { + SkipWhitespace(); + + std::string path = ReadPath(); + + SkipWhitespace(); + + m_incbins.emplace(path); + + if (m_buffer[m_pos] != ',') + break; + + m_pos++; + } + + if (m_buffer[m_pos] != ')') + FATAL_INPUT_ERROR("expected ')'"); + + m_pos++; + +} + +std::string CFile::ReadPath() +{ + if (m_buffer[m_pos] != '"') + { + if (m_buffer[m_pos] == '<') + { + return std::string(); + } + FATAL_INPUT_ERROR("expected '\"' or '<'"); + } + + m_pos++; + + int startPos = m_pos; + + while (m_buffer[m_pos] != '"') + { + if (m_buffer[m_pos] == 0) + { + if (m_pos >= m_size) + FATAL_INPUT_ERROR("unexpected EOF in path string"); + else + FATAL_INPUT_ERROR("unexpected null character in path string"); + } + + if (m_buffer[m_pos] == '\r' || m_buffer[m_pos] == '\n') + FATAL_INPUT_ERROR("unexpected end of line character in path string"); + + if (m_buffer[m_pos] == '\\') + FATAL_INPUT_ERROR("unexpected escape in path string"); + + m_pos++; + } + + m_pos++; + + return std::string(m_buffer + startPos, m_pos - 1 - startPos); +} diff --git a/tools/scaninc/c_file.h b/tools/scaninc/c_file.h new file mode 100644 index 0000000..618901b --- /dev/null +++ b/tools/scaninc/c_file.h @@ -0,0 +1,57 @@ +// Copyright(c) 2017 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef C_FILE_H +#define C_FILE_H + +#include <string> +#include <set> +#include <memory> +#include "scaninc.h" + +class CFile +{ +public: + CFile(std::string path); + ~CFile(); + void FindIncbins(); + const std::set<std::string>& GetIncbins() { return m_incbins; } + const std::set<std::string>& GetIncludes() { return m_includes; } + +private: + char *m_buffer; + int m_pos; + int m_size; + int m_lineNum; + std::string m_path; + std::set<std::string> m_incbins; + std::set<std::string> m_includes; + + bool ConsumeHorizontalWhitespace(); + bool ConsumeNewline(); + bool ConsumeComment(); + void SkipWhitespace(); + bool CheckIdentifier(const std::string& ident); + void CheckInclude(); + void CheckIncbin(); + std::string ReadPath(); +}; + +#endif // C_FILE_H diff --git a/tools/scaninc/scaninc.cpp b/tools/scaninc/scaninc.cpp new file mode 100644 index 0000000..3dc2214 --- /dev/null +++ b/tools/scaninc/scaninc.cpp @@ -0,0 +1,165 @@ +// Copyright(c) 2015-2017 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include <cstdio> +#include <cstdlib> +#include <list> +#include <queue> +#include <set> +#include <string> +#include "scaninc.h" +#include "asm_file.h" +#include "c_file.h" + +bool CanOpenFile(std::string path) +{ + FILE *fp = std::fopen(path.c_str(), "rb"); + + if (fp == NULL) + return false; + + std::fclose(fp); + return true; +} + +const char *const USAGE = "Usage: scaninc [-I INCLUDE_PATH] FILE_PATH\n"; + +int main(int argc, char **argv) +{ + std::queue<std::string> filesToProcess; + std::set<std::string> dependencies; + + std::list<std::string> includeDirs; + + argc--; + argv++; + + while (argc > 1) + { + std::string arg(argv[0]); + if (arg.substr(0, 2) == "-I") + { + std::string includeDir = arg.substr(2); + if (includeDir.empty()) + { + argc--; + argv++; + includeDir = std::string(argv[0]); + } + if (includeDir.back() != '/') + { + includeDir += '/'; + } + includeDirs.push_back(includeDir); + } + else + { + FATAL_ERROR(USAGE); + } + argc--; + argv++; + } + + if (argc != 1) { + FATAL_ERROR(USAGE); + } + + std::string initialPath(argv[0]); + + std::size_t pos = initialPath.find_last_of('.'); + + if (pos == std::string::npos) + FATAL_ERROR("no file extension in path \"%s\"\n", initialPath.c_str()); + + std::string extension = initialPath.substr(pos + 1); + + std::string srcDir(""); + std::size_t slash = initialPath.rfind('/'); + if (slash != std::string::npos) + { + srcDir = initialPath.substr(0, slash + 1); + } + includeDirs.push_back(srcDir); + + if (extension == "c" || extension == "h") + { + filesToProcess.push(initialPath); + + while (!filesToProcess.empty()) + { + CFile file(filesToProcess.front()); + filesToProcess.pop(); + + file.FindIncbins(); + for (auto incbin : file.GetIncbins()) + { + dependencies.insert(incbin); + } + for (auto include : file.GetIncludes()) + { + for (auto includeDir : includeDirs) + { + std::string path(includeDir + include); + if (CanOpenFile(path)) + { + bool inserted = dependencies.insert(path).second; + if (inserted) + { + filesToProcess.push(path); + } + break; + } + } + } + } + } + else if (extension == "s" || extension == "inc") + { + filesToProcess.push(initialPath); + + while (!filesToProcess.empty()) + { + AsmFile file(filesToProcess.front()); + + filesToProcess.pop(); + + IncDirectiveType incDirectiveType; + std::string path; + + while ((incDirectiveType = file.ReadUntilIncDirective(path)) != IncDirectiveType::None) + { + bool inserted = dependencies.insert(path).second; + if (inserted + && incDirectiveType == IncDirectiveType::Include + && CanOpenFile(path)) + filesToProcess.push(path); + } + } + } + else + { + FATAL_ERROR("unknown extension \"%s\"\n", extension.c_str()); + } + + for (const std::string &path : dependencies) + { + std::printf("%s\n", path.c_str()); + } +} diff --git a/tools/scaninc/scaninc.h b/tools/scaninc/scaninc.h new file mode 100644 index 0000000..30cc961 --- /dev/null +++ b/tools/scaninc/scaninc.h @@ -0,0 +1,59 @@ +// Copyright(c) 2015-2017 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef SCANINC_H +#define SCANINC_H + +#include <cstdio> +#include <cstdlib> + +#ifdef _MSC_VER + +#define FATAL_INPUT_ERROR(format, ...) \ +do { \ + fprintf(stderr, "%s:%d " format, m_path.c_str(), m_lineNum, __VA_ARGS__); \ + exit(1); \ +} while (0) + +#define FATAL_ERROR(format, ...) \ +do { \ + fprintf(stderr, format, __VA_ARGS__); \ + exit(1); \ +} while (0) + +#else + +#define FATAL_INPUT_ERROR(format, ...) \ +do { \ + fprintf(stderr, "%s:%d " format, m_path.c_str(), m_lineNum, ##__VA_ARGS__); \ + exit(1); \ +} while (0) + +#define FATAL_ERROR(format, ...) \ +do { \ + fprintf(stderr, format, ##__VA_ARGS__); \ + exit(1); \ +} while (0) + +#endif // _MSC_VER + +#define SCANINC_MAX_PATH 255 + +#endif // SCANINC_H -- cgit v1.2.3 From 6211b0c5ecbe4a43aa3f6e8fd96e99af29caa77a Mon Sep 17 00:00:00 2001 From: nullableVoidPtr <30564701+nullableVoidPtr@users.noreply.github.com> Date: Sun, 4 Aug 2019 10:07:21 +0000 Subject: Add compare to Makefile --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 7e75101..cf08707 100755 --- a/Makefile +++ b/Makefile @@ -98,9 +98,9 @@ MAKEFLAGS += --no-print-directory $(shell mkdir -p $(SUBDIRS)) all: $(ROM) -ifeq ($(COMPARE),1) + +compare: all @$(SHA1SUM) $(BUILD_NAME).sha1 -endif clean: tidy $(RM) $(ALL_OBJECTS) @@ -130,4 +130,4 @@ $(BUILD_DIR)/data/%.o: data/%.s $$(ASM_DEP) $(PREPROC) $< charmap.txt | $(CPP) -I include | $(AS) $(ASFLAGS) -o $@ $(BUILD_DIR)/%.o: %.s $$(ASM_DEP) - $(AS) $(ASFLAGS) $< -o $@ \ No newline at end of file + $(AS) $(ASFLAGS) $< -o $@ -- cgit v1.2.3