diff --git a/.gitignore b/.gitignore index e70f09b..25219a6 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ armips output.* output-*.png snakewood.* +snakewood_decapped.* pokeruby.map .D[Ss]_[Ss]tore [Dd]esktop.ini diff --git a/Makefile b/Makefile index d3b6ba8..9b050b8 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,8 @@ #!/usr/bin/env make -INPUT := snakewood.gba -OUTPUT := output.gba +INPUT := snakewood.gba +INPUT_DECAPPED := snakewood_decapped.gba +OUTPUT := output.gba ifeq ($(strip $(DEVKITARM)),) $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") @@ -32,9 +33,10 @@ LD = $(PREFIX)ld LDFLAGS = -i rom.ld -T linker.ld ARMIPS := ./armips -ARMIPSFLAGS := -strequ INPUT_FILE $(INPUT) -strequ OUTPUT_FILE $(OUTPUT) +ARMIPSFLAGS := -strequ INPUT_FILE $(INPUT_DECAPPED) -strequ OUTPUT_FILE $(OUTPUT) ELFEDIT := tools/elfedit/elfedit$(EXE) +DECAP := tools/decap/decap$(EXE) PREPROC := tools/preproc/preproc$(EXE) SCANINC := tools/scaninc/scaninc$(EXE) @@ -57,11 +59,15 @@ $(shell $(MAKE) tools > /dev/null) include $(OBJ_FILES:%.o=%.d) endif -all: $(OUTPUT) +all: $(INPUT_DECAPPED) $(OUTPUT) @$(ARMIPS) $(ARMIPSFLAGS) main.asm -sym2 output.map @echo "$(ARMIPS) main.asm -sym2 output.map" -$(OUTPUT): $(INPUT) build/linked_processed.o +$(INPUT_DECAPPED) : $(INPUT) + @$(DECAP) $(INPUT) $(INPUT_DECAPPED) + @echo "$(DECAP) $(INPUT) $(INPUT_DECAPPED)" + +$(OUTPUT): $(INPUT_DECAPPED) build/linked_processed.o format: @find . -not -path "./tools/*" -name *.c -o -not -path "./tools/*" -name *.h | xargs clang-format -i @@ -71,11 +77,13 @@ tools: @$(MAKE) -C tools/elfedit @$(MAKE) -C tools/preproc @$(MAKE) -C tools/scaninc + @$(MAKE) -C tools/decap clean_tools: @$(MAKE) -C tools/elfedit clean @$(MAKE) -C tools/preproc clean @$(MAKE) -C tools/scaninc clean + @$(MAKE) -C tools/decap clean clean: clean_tools rm -rf build @@ -104,4 +112,4 @@ build/linked.o: $(OBJ_FILES) linker.ld rom.ld linker/**.ld @$(LD) $(LDFLAGS) -Map build/linked.map -o $@ $(OBJ_FILES) build/linked_processed.o: build/linked.o - @$(ELFEDIT) $< $@ savemap.txt + @$(ELFEDIT) $< $@ diff --git a/config.asm b/config.asm index 4ad2f67..651b99b 100644 --- a/config.asm +++ b/config.asm @@ -154,5 +154,5 @@ ; Change Birch chase script with the default Ruby one. .definelabel REPLACE_BIRCH_CHASE_SCRIPT, 1 -; Show Chef sprite in Seashore House. -.definelabel FIX_SEASHORE_HOUSE_CHEF, 1 \ No newline at end of file +; Fix issue with Chef battle flags. +.definelabel FIX_CHEF_SCRIPTS, 1 \ No newline at end of file diff --git a/main.asm b/main.asm index 9a721a4..9985b7f 100644 --- a/main.asm +++ b/main.asm @@ -35,6 +35,7 @@ .include "scripts/bugfixes/movement/pestilence_exit.asm" .include "scripts/bugfixes/birch_chase.asm" +.include "scripts/bugfixes/chef_flags.asm" .include "scripts/bugfixes/fadescreen_shade.asm" .include "scripts/bugfixes/field_mon_sprite.asm" .include "scripts/bugfixes/fix_poke_types.asm" @@ -46,7 +47,6 @@ .include "scripts/bugfixes/meteor_portrait.asm" .include "scripts/bugfixes/necropolis_respawn.asm" .include "scripts/bugfixes/roclobster.asm" -.include "scripts/bugfixes/seashore_house_chef.asm" .include "scripts/bugfixes/senex_lilycove.asm" .include "scripts/bugfixes/shop_frame_tiles.asm" .include "scripts/bugfixes/ss_cangrejo.asm" diff --git a/scripts/bugfixes/seashore_house_chef.asm b/scripts/bugfixes/chef_flags.asm similarity index 54% rename from scripts/bugfixes/seashore_house_chef.asm rename to scripts/bugfixes/chef_flags.asm index 72eeb3c..e13dc54 100644 --- a/scripts/bugfixes/seashore_house_chef.asm +++ b/scripts/bugfixes/chef_flags.asm @@ -1,4 +1,4 @@ -.if FIX_SEASHORE_HOUSE_CHEF +.if FIX_CHEF_SCRIPTS ; Set the object flag to the trainer flag .org 0x86B6A74 @@ -10,4 +10,13 @@ .org 0x8811A4C + 5 .byte 0x54 +.org 0x881241D + 1 +.halfword 0x17 + +.org 0x8812424 + 1 +.halfword 0x17 + +.org 0x88124D4 +.byte 0xfe + .endif \ No newline at end of file diff --git a/scripts/bugfixes/item_desc.asm b/scripts/bugfixes/item_desc.asm index fb6e975..c9f5a32 100644 --- a/scripts/bugfixes/item_desc.asm +++ b/scripts/bugfixes/item_desc.asm @@ -28,9 +28,9 @@ repoint_item_desc ITEM_NECRO_BALL, @NecroBall_Desc .autoregion @MagicStars_Desc: -.string "Chocolate stars\nwith faces. Raise\nSPEED." +.string "Chocolate stars\nwith faces. Raise\nSpeed." @NecroBall_Desc: -.string "An ancient BALL\nforged in hellfire\n1000 years ago." +.string "An ancient Ball\nforged in hellfire\n1000 years ago." .endautoregion .endif diff --git a/scripts/bugfixes/item_names.asm b/scripts/bugfixes/item_names.asm index 0548651..2b75237 100644 --- a/scripts/bugfixes/item_names.asm +++ b/scripts/bugfixes/item_names.asm @@ -7,14 +7,14 @@ .endmacro .if ITEM_NAMES -fix_item_name ITEM_AFRO_BALL, "AFRO BALL" -fix_item_name ITEM_RIESEN, "RIESEN" -fix_item_name ITEM_POKEPHONE, "POKéPHONE" -fix_item_name ITEM_GATEAU, "GATEAU" -fix_item_name ITEM_SPANNER, "SPANNER" -fix_item_name ITEM_SOMA, "SOMA" -fix_item_name ITEM_COLOGNE, "COLOGNE" -fix_item_name ITEM_SPARK_TOKEN, "SPARK TOKEN" -fix_item_name ITEM_ELECTRICHONEY, "ELECTRIHONEY" -fix_item_name ITEM_PLUS_BAND, "PLUS BAND" +fix_item_name ITEM_AFRO_BALL, "Afro Ball" +fix_item_name ITEM_RIESEN, "Riesen" +fix_item_name ITEM_POKEPHONE, "PokéPhone" +fix_item_name ITEM_GATEAU, "Gateau" +fix_item_name ITEM_SPANNER, "Spanner" +fix_item_name ITEM_SOMA, "Soma" +fix_item_name ITEM_COLOGNE, "Cologne" +fix_item_name ITEM_SPARK_TOKEN, "Spark Token" +fix_item_name ITEM_ELECTRICHONEY, "Electrichoney" +fix_item_name ITEM_PLUS_BAND, "Plus Band" .endif diff --git a/src/data/trainers.c b/src/data/trainers.c index 626e22a..70203ef 100644 --- a/src/data/trainers.c +++ b/src/data/trainers.c @@ -233,22 +233,22 @@ const struct TrainerMonNoItemDefaultMoves gTrainerParty_Wattson2[6] = { }, { .iv = 110, - .level = 27, + .level = 25, .species = SPECIES_PIKACHU, }, { .iv = 110, - .level = 27, + .level = 25, .species = SPECIES_JOLTEON, }, { .iv = 110, - .level = 28, + .level = 26, .species = SPECIES_LUXIO, }, { .iv = 110, - .level = 33, + .level = 27, .species = SPECIES_RAIKOU, }, }; diff --git a/tools/decap/.gitignore b/tools/decap/.gitignore new file mode 100644 index 0000000..9198134 --- /dev/null +++ b/tools/decap/.gitignore @@ -0,0 +1 @@ +decap \ No newline at end of file diff --git a/tools/decap/Makefile b/tools/decap/Makefile new file mode 100644 index 0000000..8853524 --- /dev/null +++ b/tools/decap/Makefile @@ -0,0 +1,18 @@ +CXX := g++ + +CXXFLAGS := -std=c++11 -O2 -Wall -Wno-switch -Werror + +SRCS := decap.cpp file.cpp + +HEADERS := decap.h file.h + +.PHONY: all clean + +all: decap + @: + +decap: $(SRCS) $(HEADERS) + $(CXX) $(CXXFLAGS) $(SRCS) -o $@ $(LDFLAGS) + +clean: + $(RM) decap decap.exe diff --git a/tools/decap/decap.cpp b/tools/decap/decap.cpp new file mode 100644 index 0000000..08b97ab --- /dev/null +++ b/tools/decap/decap.cpp @@ -0,0 +1,27 @@ +#include "decap.h" +#include "file.h" + +int main(int argc, char *argv[]) +{ + if (argc < 3 || argc > 4) + { + fprintf(stderr, "Usage: %s ROM_FILE OUTPUT_FILE\n", argv[0]); + return 1; + } + + File f = File(argv[1]); + f.ProcessStringArray(0x1f716c, 11, 412); // Species names + f.ProcessStringArray(0x1f8320, 13, 355); // Move names + f.ProcessStringArray(0x1fa248, 13, 78); // Ability names + f.ProcessStringArray(0x1f0208, 13, 58); // Trainer class names + + f.ProcessStringPointerArray(0x3c1004, 25); // Nature names + f.ProcessStringPointerArray(0x3c1068, 8); // Summary Screen headers + f.ProcessStringPointerArray(0x39f494, 10, 8); // Party menu options + f.ProcessStringPointerArray(0x1fa110, 78); // Ability descriptions + f.ProcessStringPointerArray(0x3e73c4 + 4, 88, 8); // Map names + + f.Save(argv[2]); + + return 0; +} \ No newline at end of file diff --git a/tools/decap/decap.h b/tools/decap/decap.h new file mode 100644 index 0000000..c7b8b68 --- /dev/null +++ b/tools/decap/decap.h @@ -0,0 +1,27 @@ +#ifndef DECAP_H +#define DECAP_H + +#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 + +#endif diff --git a/tools/decap/file.cpp b/tools/decap/file.cpp new file mode 100644 index 0000000..ef1161e --- /dev/null +++ b/tools/decap/file.cpp @@ -0,0 +1,93 @@ +#include "file.h" +#include "decap.h" + +File::File(const std::string &filename) +{ + FILE *fp = fopen(filename.c_str(), "r"); + if (fp == NULL) FATAL_ERROR("Failed to open \"%s\" for reading.\n", filename.c_str()); + + fseek(fp, 0, SEEK_END); + + m_Size = ftell(fp); + if (m_Size < 0) + FATAL_ERROR("File size of \"%s\" is less than zero.\n", filename.c_str()); + else if (m_Size == 0) + return; // Empty file + + m_Buffer = new unsigned char[m_Size]; + rewind(fp); + + if (fread(m_Buffer, m_Size, 1, fp) != 1) + FATAL_ERROR("Failed to read \"%s\".\n", filename.c_str()); + + m_Pos = 0; + + fclose(fp); +} + +void File::Save(const std::string &filename) +{ + FILE *fp = fopen(filename.c_str(), "w"); + if (fp == NULL) FATAL_ERROR("Failed to open \"%s\" for writing.\n", filename.c_str()); + + fwrite(m_Buffer, m_Size, 1, fp); + + fclose(fp); +} + +// 0x0 is space +// 0xBB - 0xD4 -> A - Z +// 0xD5 - 0xEE -> a - z +void File::ProcessString(int location, int max_size) +{ + bool shouldCapLetter = true; + + for (int j = 0; j < max_size; ++j) + { + int idx = location + j; + if (idx > m_Size) FATAL_ERROR("Index %d is greater than file size (%ld)\n", idx, m_Size); + + unsigned char c = m_Buffer[idx]; + + if (c == 0x0) + { + shouldCapLetter = true; + } + else if ((c >= 0xBB && c <= 0xD4) && !shouldCapLetter) + { + m_Buffer[idx] = c - 0xBB + 0xD5; + } + else if ((c >= 0x01 && c <= 0x14) && !shouldCapLetter) + { + m_Buffer[idx] = c - 0x01 + 0x16; + } + else if (c == 0xFF) + { + break; + } + else + { + shouldCapLetter = false; + } + } +} + +void File::ProcessStringArray(int location, int size, int count) +{ + for (int i = 0; i < count; ++i) ProcessString(location + i * size, size); +} + +void File::ProcessStringPointerArray(int location, int count, int stride) +{ + if (location + 4 * count > m_Size) FATAL_ERROR("Pointer array end %d greater than file size (%ld)\n", location + 4 * count, m_Size); + + for (int i = 0; i < count; ++i) + { + unsigned int ptr = (m_Buffer[location] | m_Buffer[location + 1] << 8 | m_Buffer[location + 2] << 16 | m_Buffer[location + 3] << 24); + ptr -= 0x8000000; + + if (ptr > m_Size) FATAL_ERROR("Pointer %d greater than file size (%ld)\n", ptr, m_Size); + ProcessString(ptr, __INT32_MAX__); + location += stride; + } +} diff --git a/tools/decap/file.h b/tools/decap/file.h new file mode 100644 index 0000000..7e74960 --- /dev/null +++ b/tools/decap/file.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +class File +{ +public: + File(const std::string &filename); + ~File() = default; + + void Save(const std::string &filename); + + void ProcessString(int location, int max_size); + void ProcessStringArray(int location, int size, int count); + void ProcessStringPointerArray(int location, int count, int stride = 4); +private: + unsigned char *m_Buffer; + long m_Pos, m_Size; +}; \ No newline at end of file