diff --git a/.gitignore b/.gitignore index 371a6c5..ecb78a3 100644 --- a/.gitignore +++ b/.gitignore @@ -9,9 +9,5 @@ to_compress/ *.zip *.exe .vscode/ -source/test_payload.txt -loader/data/multiboot_rom.bin -include/translated_text.h -source/translated_text.cpp -text_helper/output.json -text_helper/text.xlsx +.venv/ +tools/payload-generator/payload-generator \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 3f7e23b..24e4f93 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM devkitpro/devkitarm +FROM devkitpro/devkitarm:20251117 LABEL author="Poke Transporter GB" @@ -9,4 +9,4 @@ ARG GROUP_ID ENV DEBIAN_FRONTEND="noninteractive" -RUN apt update && apt install -y build-essential python3-pip && pip install pandas requests openpyxl --break-system-packages +RUN apt update && apt install -y build-essential python3-pip python3-png && pip install pandas requests openpyxl --break-system-packages diff --git a/Makefile b/Makefile index b7ddae6..52d2814 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,30 @@ -# Build configuration (set to either 'debug' or 'release') -BUILD_TYPE := release +BUILD_LANGS := japanese english french german italian spanishEU spanishLA +BUILD_TYPES := release debug + +# defaults +BUILD_LANG ?= english +BUILD_TYPE ?= release +GIT_SUFFIX := $(shell git describe --tags --long --dirty | sed -E 's/^[^-]+-([0-9]+)-g[0-9a-f]+(-dirty)?$$/\1/') +GIT_FULL := $(shell git describe --tags --always --dirty 2>/dev/null) + +ifeq ($(GIT_SUFFIX),0) +GIT_VERSION = $(shell git describe --tags --abbrev=0) +else +GIT_VERSION = $(shell git describe --tags --abbrev=0)b +endif + +CMD_GOALS := $(filter-out build,$(MAKECMDGOALS)) + +LANG_INDEX := $(shell echo $(BUILD_LANGS) | tr ' ' '\n' | nl -v0 | grep -w $(BUILD_LANG) | awk '{print $$1 + 1}') +TYPE_INDEX := $(shell echo $(BUILD_TYPES) | tr ' ' '\n' | nl -v0 | grep -w $(BUILD_TYPE) | awk '{print $$1}') + +CPPFLAGS += -DPTGB_BUILD_LANGUAGE=$(LANG_INDEX) +CPPFLAGS += -DDEBUG_MODE=$(TYPE_INDEX) +CPPFLAGS += -DBUILD_INFO=\"$(GIT_FULL)\" + +CFLAGS += $(CPPFLAGS) +CXXFLAGS += $(CPPFLAGS) + #--------------------------------------------------------------------------------- .SUFFIXES: @@ -35,6 +60,7 @@ LIBPCCS := $(CURDIR)/PCCS #--------------------------------------------------------------------------------- TARGET := $(notdir $(CURDIR))_mb BUILD := build +GENERATED_DIR := $(BUILD)/generated SOURCES := source INCLUDES := include PCCS/lib/include DATA := data @@ -46,12 +72,12 @@ GRAPHICS := graphics #--------------------------------------------------------------------------------- ARCH := -mthumb -mthumb-interwork -CFLAGS := -Wall -O2\ +CFLAGS += -Wall -O2\ -mcpu=arm7tdmi -mtune=arm7tdmi -masm-syntax-unified\ $(ARCH) CFLAGS += $(INCLUDE) -ffunction-sections -fdata-sections -Os -Wall -mthumb -mcpu=arm7tdmi -mtune=arm7tdmi -fstack-usage -CXXFLAGS := $(CFLAGS) -g0 -fno-rtti -fno-exceptions -fdata-sections -ffunction-sections -std=c++20 -Wno-volatile -D_GLIBCXX_USE_CXX20_ABI=0 -fstack-usage +CXXFLAGS += $(CFLAGS) -g0 -fno-rtti -fno-exceptions -fdata-sections -ffunction-sections -std=c++20 -Wno-volatile -D_GLIBCXX_USE_CXX20_ABI=0 -fstack-usage ifeq ($(BUILD_TYPE), debug) CFLAGS += -g -DDEBUG @@ -99,14 +125,15 @@ ifneq ($(BUILD),$(notdir $(CURDIR))) export OUTPUT := $(CURDIR)/$(TARGET) -export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ +export VPATH := $(CURDIR)/$(GENERATED_DIR) \ + $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ $(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir)) export DEPSDIR := $(CURDIR)/$(BUILD) CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) -CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +CPPFILES := $(sort $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) translated_text.cpp) SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) PNGFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.png))) @@ -135,22 +162,45 @@ export OFILES_GRAPHICS := $(PNGFILES:.png=.o) export OFILES := $(OFILES_SOURCES) $(OFILES_GRAPHICS) -export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES))) $(PNGFILES:.png=.h) +export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES))) $(PNGFILES:.png=.h) \ + $(CURDIR)/$(GENERATED_DIR)/translated_text.h \ + $(CURDIR)/$(GENERATED_DIR)/fonts.h export INCLUDE := $(foreach dir,$(INCLUDES),-iquote $(CURDIR)/$(dir)) \ $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(GENERATED_DIR) \ -I$(CURDIR)/$(BUILD) \ -I$(CURDIR)/tools/payload-generator/include export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) -.PHONY: $(BUILD) generate_data clean +.PHONY: clean -all: $(BUILD) +GENERATE_STAMP := $(BUILD)/.generate_data.$(BUILD_LANG).$(BUILD_TYPE).stamp +BUILD_STAMP := $(BUILD)/.build.$(BUILD_LANG).$(BUILD_TYPE).stamp -generate_data: - mkdir -p data - mkdir -p to_compress +PAYLOAD_GEN_INPUTS := $(shell find tools/payload-generator/src tools/payload-generator/include -type f \( -name "*.cpp" -o -name "*.h" -o -name "*.hpp" \)) + +all: $(BUILD_STAMP) + +text_generated: to_compress generated_dir data + @PTGB_GEN_DIR="$(CURDIR)/$(GENERATED_DIR)" python3 tools/text_helper/main.py $(BUILD_LANG) $(BUILD_TYPE) + +data: + @mkdir -p $@ + +to_compress: + @mkdir -p $@ + +generated_dir: + @mkdir -p $(GENERATED_DIR) + +generate_data: $(GENERATE_STAMP) + +$(GENERATE_STAMP): text_generated $(PAYLOAD_GEN_INPUTS) compress_lz10.sh | data to_compress generated_dir + @echo "----------------------------------------------------------------" + @echo "Building v$(GIT_VERSION) with parameters: $(BUILD_LANG), $(BUILD_TYPE)" + @echo "----------------------------------------------------------------" @env - \ PATH="$(PATH)" \ TMPDIR=/tmp TMP=/tmp TEMP=/tmp \ @@ -161,12 +211,11 @@ generate_data: CXXFLAGS= \ LDFLAGS= \ AR=ar \ - $(MAKE) -C tools/payload-generator + $(MAKE) -C tools/payload-generator BUILD_LANG=$(BUILD_LANG) BUILD_TYPE=$(BUILD_TYPE) @echo @echo "----------------------------------------------------------------" @echo @tools/payload-generator/payload-generator to_compress - @python3 text_helper/main.py @echo "Compressing bin files!" @echo -n "[" @find to_compress -name "*.bin" -print0 | xargs -0 -n1 ./compress_lz10.sh @@ -175,10 +224,10 @@ generate_data: @echo @echo "----------------------------------------------------------------" @echo + @touch $@ #--------------------------------------------------------------------------------- -$(BUILD): generate_data - @[ -d $@ ] || mkdir -p $@ +$(BUILD_STAMP): generate_data | $(BUILD) @$(MAKE) -C PCCS \ CC="$(CC)" \ CXX="$(CXX)" \ @@ -189,6 +238,10 @@ $(BUILD): generate_data @mkdir -p loader/data @cp $(TARGET).gba loader/data/multiboot_rom.bin @$(MAKE) -C loader + @touch $@ + +$(BUILD): + @mkdir -p $@ #--------------------------------------------------------------------------------- clean: @@ -197,7 +250,8 @@ clean: @$(MAKE) -C loader clean @$(MAKE) -C PCCS clean @rm -fr $(BUILD) $(TARGET).elf $(TARGET).gba data/ to_compress/ - @rm -f text_helper/output.json + @rm -fr tools/text_helper/build + @rm -fr $(GENERATED_DIR) diff --git a/PCCS b/PCCS index db430d8..6858e4b 160000 --- a/PCCS +++ b/PCCS @@ -1 +1 @@ -Subproject commit db430d84c27bf196ab61e07d4b4588ddc093da08 +Subproject commit 6858e4ba23f4553f06c41db77959467afba2e77e diff --git a/building_on_windows.txt b/building_on_windows.txt index c359334..6d5a432 100644 --- a/building_on_windows.txt +++ b/building_on_windows.txt @@ -19,4 +19,4 @@ break-system-packages = true pacman -S openssl-devel export CMAKE_TLS_VERIFY=0 -pip install pandas requests openpyxl \ No newline at end of file +pip install pandas requests openpyxl pypng \ No newline at end of file diff --git a/graphics/dexBG.png b/graphics/dexBG.png index 77ab9d9..399a0a2 100644 Binary files a/graphics/dexBG.png and b/graphics/dexBG.png differ diff --git a/graphics/menu_bars.png b/graphics/menu_bars.png index d5f13a8..fc91ebe 100644 Binary files a/graphics/menu_bars.png and b/graphics/menu_bars.png differ diff --git a/graphics/textBoxBG.png b/graphics/textBoxBG.png index 3c1f9b9..a8d4293 100644 Binary files a/graphics/textBoxBG.png and b/graphics/textBoxBG.png differ diff --git a/graphics/unused graphics/japanese_normal.png b/graphics/unused graphics/japanese_normal.png deleted file mode 100644 index 07bb453..0000000 Binary files a/graphics/unused graphics/japanese_normal.png and /dev/null differ diff --git a/graphics/unused graphics/latin_normal.png b/graphics/unused graphics/latin_normal.png deleted file mode 100644 index 774a05c..0000000 Binary files a/graphics/unused graphics/latin_normal.png and /dev/null differ diff --git a/graphics/unused graphics/latin_short.png b/graphics/unused graphics/latin_short.png index 2025943..52e40df 100644 Binary files a/graphics/unused graphics/latin_short.png and b/graphics/unused graphics/latin_short.png differ diff --git a/include/button_menu.h b/include/button_menu.h index cd923a6..78b8250 100644 --- a/include/button_menu.h +++ b/include/button_menu.h @@ -12,6 +12,7 @@ #define BTN_EVENTS 3 #define BTN_CREDITS 4 #define BTN_OPENING 5 +#define BTN_TEXT_DEBUG 6 #define BUTTON_CANCEL UINT8_MAX diff --git a/include/debug_mode.h b/include/debug_mode.h index 1b11c61..5c14c87 100644 --- a/include/debug_mode.h +++ b/include/debug_mode.h @@ -1,29 +1,39 @@ #ifndef DEBUG_MODE_H #define DEBUG_MODE_H -#define VERSION "v1.2.1" -#define PTGB_BUILD_LANGUAGE 2 +#ifndef BUILD_INFO +#define BUILD_INFO "NaN" +#endif -#define DEBUG_MODE false +#ifndef PTGB_BUILD_LANGUAGE +#define PTGB_BUILD_LANGUAGE 1 +#endif + +#ifndef DEBUG_MODE +#define DEBUG_MODE 0 +#endif #define PRINT_LINK_DATA (false && DEBUG_MODE) #define INSTANT_TEXT_SPEED (false && DEBUG_MODE) #define IGNORE_GAME_PAK (true && DEBUG_MODE) #define IGNORE_GAME_PAK_SPRITES (false && DEBUG_MODE) -#define IGNORE_LINK_CABLE (false && DEBUG_MODE) +#define IGNORE_LINK_CABLE (true && DEBUG_MODE) #define IGNORE_MG_E4_FLAGS (true && DEBUG_MODE) -#define IGNORE_UNRECEIVED_PKMN (true && DEBUG_MODE) +#define IGNORE_UNRECEIVED_PKMN (false && DEBUG_MODE) #define FORCE_TUTORIAL (false && DEBUG_MODE) #define DONT_REMOVE_PKMN (false && DEBUG_MODE) #define DONT_HIDE_INVALID_PKMN (false && DEBUG_MODE) #define IGNORE_DEX_COMPLETION (false && DEBUG_MODE) -#define FORCE_ALL_CAUGHT (false && DEBUG_MODE) +#define FORCE_ALL_CAUGHT (true && DEBUG_MODE) #define WRITE_CABLE_DATA_TO_SAVE (false && DEBUG_MODE) #define SHOW_DATA_PACKETS (false && DEBUG_MODE) #define DISPLAY_CONTROL_CHAR (false && DEBUG_MODE) #define PAYLOAD_EXPORT_TEST (false && DEBUG_MODE) #define DONT_TRANSFER_POKEMON_AT_INDEX_X (false && DEBUG_MODE) #define POKEMON_INDEX_TO_SKIP 5 +#define ENABLE_TEXT_DEBUG_SCREEN (true && DEBUG_MODE) +#define DEBUG_PAYLOADS (false && DEBUG_MODE) + #define DEBUG_GAME EMERALD_ID #define DEBUG_VERS VERS_1_0 diff --git a/include/global_frame_controller.h b/include/global_frame_controller.h index 8ab0b7a..d92514f 100644 --- a/include/global_frame_controller.h +++ b/include/global_frame_controller.h @@ -31,6 +31,7 @@ void set_treecko(bool val); bool get_treecko_enabled(); u32 fnv1a_hash(unsigned char *data, size_t length); int get_string_length(const byte *str); +int get_string_char_count(const byte *str); void convert_int_to_ptgb_str(int val, byte str[]); void convert_int_to_ptgb_str(int val, byte str[], int min_length); diff --git a/include/japanese_small.h b/include/japanese_small.h deleted file mode 100644 index 5529479..0000000 --- a/include/japanese_small.h +++ /dev/null @@ -1,21 +0,0 @@ -#include "debug_mode.h" -#include "pokemon_data.h" - -#if PTGB_BUILD_LANGUAGE == JPN_ID - -//{{BLOCK(japanese_small) - -#ifndef __JAPANESE_SMALL__ -#define __JAPANESE_SMALL__ - -extern const TFont japanese_smallFont; - -#define japanese_smallGlyphsLen 4096 -extern const unsigned int japanese_smallGlyphs[1024]; -#define BUILD_FONT &japanese_smallFont - -#endif // __JAPANESE_SMALL__ - -//}}BLOCK(japanese_small) - -#endif \ No newline at end of file diff --git a/include/latin_normal.h b/include/latin_normal.h deleted file mode 100644 index c6bdd7a..0000000 --- a/include/latin_normal.h +++ /dev/null @@ -1,14 +0,0 @@ - -//{{BLOCK(latin_normal) - -#ifndef __LATIN_NORMAL__ -#define __LATIN_NORMAL__ - -extern const TFont latin_normalFont; - -#define latin_normalGlyphsLen 4096 -extern const unsigned int latin_normalGlyphs[1024]; - -#endif // __LATIN_NORMAL__ - -//}}BLOCK(latin_normal) diff --git a/include/latin_short.h b/include/latin_short.h deleted file mode 100644 index 6e61434..0000000 --- a/include/latin_short.h +++ /dev/null @@ -1,21 +0,0 @@ -#include "debug_mode.h" -#include "pokemon_data.h" - -#if PTGB_BUILD_LANGUAGE != JPN_ID - -//{{BLOCK(latin_short) - -#ifndef __LATIN_SHORT__ -#define __LATIN_SHORT__ - -extern const TFont latin_shortFont; - -#define latin_shortGlyphsLen 4096 -extern const unsigned int latin_shortGlyphs[1024]; -#define BUILD_FONT &latin_shortFont - -#endif // __LATIN_SHORT__ - -//}}BLOCK(latin_short) - -#endif \ No newline at end of file diff --git a/include/rom_data.h b/include/rom_data.h index 98611a7..24c8bd2 100644 --- a/include/rom_data.h +++ b/include/rom_data.h @@ -25,7 +25,7 @@ class rom_data { public: rom_data(); - bool load_rom(); + bool load_rom(bool debug); bool is_hoenn(); bool is_ruby_sapphire(); void print_rom_info(); diff --git a/include/text_engine.h b/include/text_engine.h index e733c04..cc55c42 100644 --- a/include/text_engine.h +++ b/include/text_engine.h @@ -8,13 +8,17 @@ #define V_MAX 160 #define LEFT 8 #define RIGHT (H_MAX - LEFT) -#define TOP 112 +#define TOP 120 #define BOTTOM V_MAX #define INK_WHITE 15 #define INK_ROM_COLOR 14 #define INK_DARK_GREY 13 +#define SCRIPT_DEBUG 0 +#define SCRIPT_TRANSFER 1 +#define SCRIPT_EVENT 2 + void init_text_engine(); int text_loop(int script); int text_next_obj_id(script_obj current_line); @@ -26,5 +30,6 @@ int ptgb_write(const byte *text, bool instant); int ptgb_write(const byte *text, bool instant, int length); int ptgb_write_debug(const u16* charset, const char *text, bool instant); void wait_for_user_to_continue(bool clear_text); +void scroll_text(bool instant, TTC *tc); #endif \ No newline at end of file diff --git a/payload_builder copy.cpp b/payload_builder copy.cpp deleted file mode 100644 index 3cf5357..0000000 --- a/payload_builder copy.cpp +++ /dev/null @@ -1,996 +0,0 @@ -#include "payloads/payload_builder.h" -#include "gb_rom_values/base_gb_rom_struct.h" -#include "payloads/z80_asm.h" -#include "../../../include/debug_mode.h" -#include - -#define DATA_LOC (SHOW_DATA_PACKETS ? curr_rom.transferStringLocation : curr_rom.wEnemyMonSpecies) -#define DEBUG_PAYLOADS (false && DEBUG_MODE) - -void init_payload(byte *payload_buffer, const GB_ROM &curr_rom, int type, bool debug) -{ - if (DEBUG_PAYLOADS) - { - debug = true; - } - - (void)type; - /* 10 RNG bytes - 8 Preamble bytes - 418 / 441 Party bytes - 7 Preamble bytes - 194 Patch list bytes (last 2 are unused) - - 637 / 660 total bytes - */ - if ((curr_rom.generation == 1 && curr_rom.version != YELLOW_ID)) - { - std::vector jump_vector; - std::vector var_vector; - - z80_asm_handler z80_rng_seed(0x0A, curr_rom.wSerialOtherGameboyRandomNumberListBlock + 8); - z80_asm_handler z80_payload(0x1AA, curr_rom.wSerialEnemyDataBlock); - z80_asm_handler z80_patchlist(0xC9, curr_rom.wSerialEnemyMonsPatchList); - - z80_jump asm_start(&jump_vector); - z80_jump save_box(&jump_vector); - z80_jump remove_array_loop(&jump_vector); - z80_jump packet_loop(&jump_vector); - z80_jump fe_bypass(&jump_vector); - z80_jump send_packet_loop(&jump_vector); - - z80_variable array_counter(&var_vector, 1, 0x00); // 1 byte to store the current array counter - z80_variable removal_array(&var_vector); // 40 byte storage for list of Pokemon to remove, plus a permanent array terminator - - byte removal_array_data[41]; - for (int i = 0; i < 41; i++) - { - if (debug) - { - removal_array_data[i] = (i < 30 ? (29 - i) : 0xFF); - } - else - { - removal_array_data[i] = (i < 30 ? 0xFD : 0xFF); - } - } - removal_array.load_data(41, removal_array_data); - z80_variable transfer_wait_string(&var_vector, 13, // SENDING DATA - 0x92, 0x84, 0x8D, 0x83, 0x88, 0x8D, 0x86, 0x7F, 0x83, 0x80, 0x93, 0x80, 0x50); - z80_variable custom_name(&var_vector, 11, // FENNEL - 0x85, 0x84, 0x8D, 0x8D, 0x84, 0x8B, 0x50, 0x50, 0x50, 0x50, 0x50); - - // RNG Seed - // Location of the entrance vector - z80_rng_seed.index = 5; // Set the entrance vector - z80_rng_seed.JP(asm_start.place_direct_jump(&z80_rng_seed) | T_U16); - - // Preamble - // At 0x00, 0x07 in length - // Must be filled with 0xFD - for (int i = 0; i < 7; i++) - { - z80_payload.add_byte(0xFD); - } - - // Rival name - // At 0x07, 0x0B in length - // Set to stored name - z80_payload.index = 0x07; - custom_name.insert_variable(&z80_payload); - - // Number of Pokemon - // At 0x12, 0x01 in length - // Does not need to be set - z80_payload.index = 0x12; - z80_payload.add_byte(0x06); - - // Pokemon list - // At 0x13, can be up to 0x1A2 / 0x1B9 bytes in length. - // Calculate the number of Pokemon names that need to be printed, - // and add them to the list. Then terminate the list. - z80_payload.index = 0x13; - int distance = curr_rom.stack_overwrite_location - curr_rom.print_string_start; - distance /= 20; // Automatically truncated, so it won't overshoot - - for (int i = 0; i < distance; i++) - { - z80_payload.add_byte(curr_rom.short_pkmn_name); - } - z80_payload.add_byte(curr_rom.pointer_pkmn_name); - z80_payload.add_byte(0xFF); - - // Patchlist preamble - // At 0x1B4 / 0x1D7, 0x07 in length - // Set as five 0xFD and two 0xFF - - for (int i = 0; i < 7; i++) - { - z80_patchlist.add_byte(i < 5 ? 0xFD : 0xFF); - } - - // Patchlist - // At 0x1BB / 0x1DE, 0xC2 in length (0xC4, but the last 2 are unused) - // Fill with custom code - asm_start.set_start(&z80_patchlist); - - /* Write transferring message to screen: */ - // call ClearScreen - z80_patchlist.CALL(curr_rom.clearScreen | T_U16); - z80_patchlist.LD(HL, curr_rom.textBorderUppLeft | T_U16); - z80_patchlist.LD(C, curr_rom.textBorderWidth | T_U8); - z80_patchlist.LD(B, curr_rom.textBorderHeight | T_U8); - z80_patchlist.CALL(curr_rom.CableClub_TextBoxBorder | T_U16); - z80_patchlist.LD(HL, curr_rom.transferStringLocation | T_U16); - z80_patchlist.LD(DE, transfer_wait_string.place_ptr(&z80_patchlist) | T_U16); - z80_patchlist.CALL(curr_rom.placeString | T_U16); - - /* Build the packet */ - // HL is the current data pointer - // DE is the destination pointer - // A is the checksum - // B is the 0xFE flag byte - // C is the counter - send_packet_loop.set_start(&z80_patchlist); - - z80_patchlist.LD(HL, (DATA_LOC + PACKET_SIZE + 3) | T_U16); // Load the next data location into HL - z80_patchlist.LD(A, HLI_PTR); - z80_patchlist.LD(H, HL_PTR); - z80_patchlist.LD(L, A); - z80_patchlist.LD(DE, (DATA_LOC + 2) | T_U16); // Enemy Pokemon data, should be unused - z80_patchlist.XOR(A, A); // Clear the register - z80_patchlist.LD(B, A); // Clear B as well - z80_patchlist.LD(C, A); // Clear C as well - z80_patchlist.PUSH(AF); - packet_loop.set_start(&z80_patchlist); - z80_patchlist.LD(B, 0x00 | T_U8); // Reset the flag byte - z80_patchlist.POP(AF); - z80_patchlist.ADD(A, HL_PTR); // Add the current data to the checksum - z80_patchlist.PUSH(AF); - z80_patchlist.LD(A, 0xFE); - z80_patchlist.CP(A, HL_PTR); // Compare the current data to 0xFE - z80_patchlist.LD(A, HLI_PTR); // Load HL's data into A for modification (if need be) - - // If HL's data is 0xFE - z80_patchlist.JR(NZ_F, fe_bypass.place_relative_jump(&z80_patchlist) | T_I8); - z80_patchlist.DEC(A); - z80_patchlist.INC(B); // Set flag - - fe_bypass.set_start(&z80_patchlist); - z80_patchlist.LD(DE_PTR, A); // Place the data in - z80_patchlist.INC(DE); - z80_patchlist.PUSH(AF); - z80_patchlist.LD(A, B); - z80_patchlist.LD(DE_PTR, A); // Place the flag in as well - z80_patchlist.POP(AF); - z80_patchlist.INC(DE); - z80_patchlist.INC(C); - z80_patchlist.LD(A, DATA_PER_PACKET - 1); - z80_patchlist.CP(A, C); - z80_patchlist.JR(NC_F, packet_loop.place_relative_jump(&z80_patchlist) | T_I8); // If all the data has been set, send the rest of the data - z80_patchlist.POP(AF); - z80_patchlist.RES(7 | T_BIT, A); // Reset bit 7 of the checksum, guaranteeing that it will never be 0xFE - z80_patchlist.LD(DE_PTR, A); - z80_patchlist.INC(DE); - z80_patchlist.LD(A, H); - z80_patchlist.LD(DE_PTR, A); - z80_patchlist.INC(DE); - z80_patchlist.LD(A, L); - z80_patchlist.LD(DE_PTR, A); - - // z80_patchlist.LD(HL, curr_rom.garbageDataLocation | T_U16); - - /* Transfer box data packet: */ - z80_patchlist.LD(A, (debug ? 0x02 : 0x01) | T_U8); // Make sure GB is the slave, master if debug - z80_patchlist.LDH((curr_rom.hSerialConnectionStatus & 0xFF) | T_U8, A); // Since hSerialConnectionStatus is at 0xFFxx we can use this method instead - z80_patchlist.LD(HL, DATA_LOC | T_U16); - z80_patchlist.LD(HL_PTR, 0xFD | T_U8); // set the start of the data to 0xFD so Serial_ExchangeBytes is happy - z80_patchlist.INC(HL); - z80_patchlist.LD(HL_PTR, 0x00 | T_U8); // add a 0x00 after the 0xFD to prevent further 0xFDs from being interpreted as part of the preamble - z80_patchlist.DEC(HL); // Reset HL back so it points to 0xFD - z80_patchlist.LD(DE, (DATA_LOC + PACKET_SIZE) | T_U16); // location to put stored data - z80_patchlist.LD(BC, PACKET_SIZE | T_U16); - if (debug) // Don't call serialExchangeBytes if debug is enabled - { - z80_patchlist.index += 3; - } - else - { - z80_patchlist.CALL(curr_rom.Serial_ExchangeBytes | T_U16); - } - - z80_patchlist.LD(A, (DATA_LOC + PACKET_SIZE + 3 + 1) | T_U16); - z80_patchlist.CP(A, 0xFF); - z80_patchlist.JR(NZ_F, send_packet_loop.place_relative_jump(&z80_patchlist) | T_I8); - - /* Recieve the Pokemon to remove */ - z80_patchlist.LD(HL, curr_rom.hSerialConnectionStatus | T_U16); // This can also be shortened - z80_patchlist.LD(HL_PTR, (debug ? 0x02 : 0x01) | T_U8); // Make sure GB is the slave, master if debug - z80_patchlist.LD(HL, curr_rom.garbageDataLocation | T_U16); - z80_patchlist.LD(DE, removal_array.place_ptr(&z80_patchlist) | T_U16); - z80_patchlist.LD(BC, 0x001E | T_U16); // Preamble does *not* count - if (debug) // Don't add in the Serial_ExchangeBytes call if in debug - { - z80_patchlist.index += 3; - } - else - { - z80_patchlist.CALL(curr_rom.Serial_ExchangeBytes | T_U16); - } - - /* Remove the transfered Pokemon */ - z80_patchlist.LD(HL, curr_rom.wRemoveMonFromBox | T_U16); - z80_patchlist.LD(HL_PTR, 0x01 | T_U8); // != 0x00 specifies the current box - remove_array_loop.set_start(&z80_patchlist); - z80_patchlist.LD(A, array_counter.place_ptr(&z80_patchlist) | T_U16); - z80_patchlist.LD(E, A); - z80_patchlist.LD(D, 0x00 | T_U8); - z80_patchlist.LD(HL, removal_array.place_ptr(&z80_patchlist) | T_U16); - z80_patchlist.ADD(HL, DE); - z80_patchlist.INC(A); - z80_patchlist.LD(array_counter.place_ptr(&z80_patchlist) | T_U16, A); - z80_patchlist.LD(A, curr_rom.wBoxCount | T_U16); - z80_patchlist.LD(B, A); - z80_patchlist.LD(A, HL_PTR); - z80_patchlist.CP(A, 0xFF | T_U8); - z80_patchlist.JR(Z_F, save_box.place_relative_jump(&z80_patchlist) | T_I8); - z80_patchlist.CP(A, B); - z80_patchlist.JR(NC_F, remove_array_loop.place_relative_jump(&z80_patchlist) | T_I8); - z80_patchlist.LD(HL, curr_rom.wWhichPokemon | T_U16); - z80_patchlist.LD(HL_PTR, A); - if (DONT_REMOVE_PKMN) - { - z80_patchlist.index += 3; - } - else - { - z80_patchlist.CALL(curr_rom._RemovePokemon | T_U16); - } - z80_patchlist.JR((remove_array_loop.place_relative_jump(&z80_patchlist) & 0xFF) | T_I8); - - /* Save the current box */ - save_box.set_start(&z80_patchlist); - z80_patchlist.LD(B, (curr_rom.SaveSAVtoSRAM1 >> 16) | T_U8); // Load ROM Bank - z80_patchlist.LD(HL, curr_rom.SaveSAVtoSRAM1 | T_U16); - z80_patchlist.CALL(curr_rom.Bankswitch | T_U16); - z80_patchlist.LD(B, (curr_rom.SaveSAVtoSRAM1 >> 16) | T_U8); // Load ROM Bank - z80_patchlist.LD(HL, curr_rom.SaveSAVtoSRAM2 | T_U16); // TODO: We probably don't have to load the ROM bank twice - z80_patchlist.CALL(curr_rom.Bankswitch | T_U16); - z80_patchlist.JP(curr_rom.SoftReset | T_U16); - - // z80_patchlist.index += 5; - - array_counter.insert_variable(&z80_patchlist); - removal_array.insert_variable(&z80_payload); - transfer_wait_string.insert_variable(&z80_patchlist); - - // This payload works by placing Pokemon ID 0xFC's name in the stack, and causing a return to CD8E, - // which is part of the RNG seed. From there we can jump anywhere- and we choose to jump to D887, - // which is the rival's name. This code fixes the stack and jumps to the patchlist, which is where - // our final code is. - - // Update all the pointers - for (unsigned int i = 0; i < var_vector.size(); i++) - { - var_vector.at(i)->update_ptrs(); - } - for (unsigned int i = 0; i < jump_vector.size(); i++) - { - jump_vector.at(i)->update_jumps(); - } - - // Combine the vectors into the full payload - u8 *cur_out = payload_buffer; - memcpy(cur_out, z80_rng_seed.data_vector.data(), z80_rng_seed.data_vector.size()); - cur_out += z80_rng_seed.data_vector.size(); - memcpy(cur_out, z80_payload.data_vector.data(), z80_payload.data_vector.size()); - cur_out += z80_payload.data_vector.size(); - memcpy(cur_out, z80_patchlist.data_vector.data(), z80_patchlist.data_vector.size()); - cur_out += z80_patchlist.data_vector.size(); - - return; - } - - else if ((curr_rom.generation == 1 && curr_rom.version == YELLOW_ID)) - { - std::vector jump_vector; - std::vector var_vector; - - z80_asm_handler z80_rng_seed(0x0A, curr_rom.wSerialOtherGameboyRandomNumberListBlock + 8); - z80_asm_handler z80_payload(0x1AA, curr_rom.wSerialEnemyDataBlock - 8); // Subtracting 8 is because the data is shifted after patching, removing part of the enemy name. May change depending on language - z80_asm_handler z80_patchlist(0xC9, curr_rom.wSerialEnemyMonsPatchList); - - z80_jump asm_start(&jump_vector); - z80_jump save_box(&jump_vector); - z80_jump remove_array_loop(&jump_vector); - z80_jump packet_loop(&jump_vector); - z80_jump fe_bypass(&jump_vector); - z80_jump send_packet_loop(&jump_vector); - z80_jump skip_enemy_write(&jump_vector); - - z80_jump test_loop(&jump_vector); - - z80_variable array_counter(&var_vector, 1, 0x00); // 1 byte to store the current array counter - z80_variable removal_array(&var_vector); // 40 byte storage for list of Pokemon to remove, plus a permanent array terminator - - byte removal_array_data[41]; - for (int i = 0; i < 41; i++) - { - if (debug) - { - removal_array_data[i] = (i < 30 ? (29 - i) : 0xFF); - } - else - { - removal_array_data[i] = (i < 30 ? 0xFD : 0xFF); - } - } - removal_array.load_data(41, removal_array_data); - z80_variable transfer_wait_string(&var_vector, 13, // SENDING DATA - 0x92, 0x84, 0x8D, 0x83, 0x88, 0x8D, 0x86, 0x7F, 0x83, 0x80, 0x93, 0x80, 0x50); - z80_variable custom_name(&var_vector, 11, // FENNEL - 0x85, 0x84, 0x8D, 0x8D, 0x84, 0x8B, 0x50, 0x50, 0x50, 0x50, 0x50); - - // RNG Seed: - // at 0x00, 0x0A in length - // Can be empty - - // Preamble - // At 0x00, 0x07 in length - // Must be filled with 0xFD - for (int i = 0; i < 7; i++) - { - z80_payload.add_byte(0xFD); - } - - // Rival name - // At 0x07, 0x0B in length - // Set to stored name - z80_payload.index = 0x07; - custom_name.insert_variable(&z80_payload); - - // Number of Pokemon - // At 0x12, 0x01 in length - // 2 or higher, 0xE8 for JPN - z80_payload.index = 0x12; - z80_payload.add_byte(0x02); - - // Pokemon list - // At 0x13, is usually 6 bytes and 1 terminator - for (int i = 0; i < 7; i++) - { - z80_payload.add_byte(i < 6 ? i + 1 : 0xFF); - } - - // Pokemon data - // Specific for each language - - // Mon #1 HP - z80_payload.add_bytes(2, - 0x00, 0x00); - - // Mon #2 data - z80_payload.index = 0x46; - z80_payload.add_bytes(9, - 0x4E, 0x4E, 0x4E, 0x00, 0x01, 0x80, 0x80, 0xD4, 0xCF); - - z80_payload.add_bytes(2, asm_start.place_pointer(&z80_payload), 0x00); // These values must not have any control characters in them. - - z80_payload.add_bytes(33, - 0x4E, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x4E, 0x50, 0x00, 0x00, - 0x00, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x59); - - // Mon #2 name - z80_payload.index = 0x16F; - for (int i = 0; i < 11; i++) - { - z80_payload.add_byte(0x4E); - } - - // Now that the ACE has been set up, we can use the space between Mon #2's data and Mon #2's name to put our code. - // Since this space is larger than the patchlist, we will be able to fit everything in it - - // Patchlist preamble - // At 0x1B4 0x07 in length - // Set as five 0xFD, the 0xFF will be added as part of the patch list. - for (int i = 0; i < 5; i++) - { - z80_patchlist.add_byte(0xFD); - } - - z80_payload.index = 0x72; - - array_counter.insert_variable(&z80_payload); - removal_array.insert_variable(&z80_payload); - transfer_wait_string.insert_variable(&z80_payload); - - asm_start.set_start(&z80_payload); - - z80_payload.CALL(0x2233 | T_U16); // Stop the battle music - - /* Write transferring message to screen: */ - // call ClearScreen - z80_payload.CALL(curr_rom.clearScreen | T_U16); - z80_payload.LD(HL, curr_rom.textBorderUppLeft | T_U16); - z80_payload.LD(C, curr_rom.textBorderWidth | T_U8); - z80_payload.LD(B, curr_rom.textBorderHeight | T_U8); - z80_payload.CALL(curr_rom.CableClub_TextBoxBorder | T_U16); - z80_payload.LD(HL, curr_rom.transferStringLocation | T_U16); - z80_payload.LD(DE, transfer_wait_string.place_ptr(&z80_payload) | T_U16); - z80_payload.CALL(curr_rom.placeString | T_U16); - z80_payload.JR(skip_enemy_write.place_relative_jump(&z80_payload) | T_I8); // This is a simple way to avoid the enemy name placement. Might have to modify for other languages - - z80_payload.index = 0xCA; - - skip_enemy_write.set_start(&z80_payload); - - // Reload the save data to remove any data that was overwritten during exploit entry - z80_payload.LD(B, (curr_rom.LoadCurrentBoxData >> 16) | T_U8); - z80_payload.LD(HL, curr_rom.LoadCurrentBoxData | T_U16); - z80_payload.CALL(curr_rom.Bankswitch | T_U16); - if (!debug) - { - /* Build the packet */ - // HL is the current data pointer - // DE is the destination pointer - // A is the checksum - // B is the 0xFE flag byte - // C is the counter - send_packet_loop.set_start(&z80_payload); - - z80_payload.LD(HL, (DATA_LOC + PACKET_SIZE + 3) | T_U16); // Load the next data location into HL - z80_payload.LD(A, HLI_PTR); - z80_payload.LD(H, HL_PTR); - z80_payload.LD(L, A); - z80_payload.LD(DE, (DATA_LOC + 2) | T_U16); // Enemy Pokemon data, should be unused - z80_payload.XOR(A, A); // Clear the register - z80_payload.LD(B, A); // Clear B as well - z80_payload.LD(C, A); // Clear C as well - z80_payload.PUSH(AF); - packet_loop.set_start(&z80_payload); - z80_payload.LD(B, 0x00 | T_U8); // Reset the flag byte - z80_payload.POP(AF); - z80_payload.ADD(A, HL_PTR); // Add the current data to the checksum - z80_payload.PUSH(AF); - z80_payload.LD(A, 0xFE); - z80_payload.CP(A, HL_PTR); // Compare the current data to 0xFE - z80_payload.LD(A, HLI_PTR); // Load HL's data into A for modification (if need be) - - // If HL's data is 0xFE - z80_payload.JR(NZ_F, fe_bypass.place_relative_jump(&z80_payload) | T_I8); - z80_payload.DEC(A); - z80_payload.INC(B); // Set flag - - fe_bypass.set_start(&z80_payload); - z80_payload.LD(DE_PTR, A); // Place the data in - z80_payload.INC(DE); - z80_payload.PUSH(AF); - z80_payload.LD(A, B); - z80_payload.LD(DE_PTR, A); // Place the flag in as well - z80_payload.POP(AF); - z80_payload.INC(DE); - z80_payload.INC(C); - z80_payload.LD(A, DATA_PER_PACKET - 1); - z80_payload.CP(A, C); - z80_payload.JR(NC_F, packet_loop.place_relative_jump(&z80_payload) | T_I8); // If all the data has been set, send the rest of the data - z80_payload.POP(AF); - z80_payload.RES(7 | T_BIT, A); // Reset bit 7 of the checksum, guaranteeing that it will never be 0xFE - z80_payload.LD(DE_PTR, A); - z80_payload.INC(DE); - z80_payload.LD(A, H); - - z80_payload.LD(DE_PTR, A); - z80_payload.INC(DE); - z80_payload.LD(A, L); - z80_payload.LD(DE_PTR, A); - - /* Transfer box data packet: */ - z80_payload.LD(A, (debug ? 0x02 : 0x01) | T_U8); // Make sure GB is the slave, master if debug - z80_payload.LDH((curr_rom.hSerialConnectionStatus & 0xFF) | T_U8, A); // Since hSerialConnectionStatus is at 0xFFxx we can use this method instead - z80_payload.LD(HL, DATA_LOC | T_U16); - z80_payload.LD(HL_PTR, 0xFD | T_U8); // set the start of the data to 0xFD so Serial_ExchangeBytes is happy - z80_payload.INC(HL); - z80_payload.LD(HL_PTR, 0x00 | T_U8); // add a 0x00 after the 0xFD to prevent further 0xFDs from being interpreted as part of the preamble - z80_payload.DEC(HL); // Reset HL back so it points to 0xFD - z80_payload.LD(DE, (DATA_LOC + PACKET_SIZE) | T_U16); // location to put stored data - z80_payload.LD(BC, PACKET_SIZE | T_U16); - if (debug) // Don't call serialExchangeBytes if debug is enabled - { - z80_payload.index += 3; - } - else - { - z80_payload.CALL(curr_rom.Serial_ExchangeBytes | T_U16); - } - - z80_payload.LD(A, (DATA_LOC + PACKET_SIZE + 3 + 1) | T_U16); - z80_payload.CP(A, 0xFF); - if (debug && false) // Don't compare the "recieved" data if in debug - { - z80_payload.index += 2; - } - else - { - z80_payload.JR(NZ_F, send_packet_loop.place_relative_jump(&z80_payload) | T_I8); - } - } - /* Recieve the Pokemon to remove */ - z80_payload.LD(HL, curr_rom.hSerialConnectionStatus | T_U16); // This can also be shortened - z80_payload.LD(HL_PTR, (debug ? 0x02 : 0x01) | T_U8); // Make sure GB is the slave, master if debug - z80_payload.LD(HL, curr_rom.garbageDataLocation | T_U16); - z80_payload.LD(DE, removal_array.place_ptr(&z80_payload) | T_U16); - z80_payload.LD(BC, 0x001E | T_U16); // Preamble does *not* count - if (debug) // Don't add in the Serial_ExchangeBytes call if in debug - { - z80_payload.index += 3; - } - else - { - z80_payload.CALL(curr_rom.Serial_ExchangeBytes | T_U16); - } - - /* Remove the transfered Pokemon */ - z80_payload.LD(HL, curr_rom.wRemoveMonFromBox | T_U16); - z80_payload.LD(HL_PTR, 0x01 | T_U8); // != 0x00 specifies the current box - remove_array_loop.set_start(&z80_payload); - z80_payload.LD(A, array_counter.place_ptr(&z80_payload) | T_U16); - z80_payload.LD(E, A); - z80_payload.LD(D, 0x00 | T_U8); - z80_payload.LD(HL, removal_array.place_ptr(&z80_payload) | T_U16); - z80_payload.ADD(HL, DE); - z80_payload.INC(A); - z80_payload.LD(array_counter.place_ptr(&z80_payload) | T_U16, A); - z80_payload.LD(A, curr_rom.wBoxCount | T_U16); - z80_payload.LD(B, A); - z80_payload.LD(A, HL_PTR); - z80_payload.CP(A, 0xFF | T_U8); - z80_payload.JR(Z_F, save_box.place_relative_jump(&z80_payload) | T_I8); - z80_payload.CP(A, B); - z80_payload.JR(NC_F, remove_array_loop.place_relative_jump(&z80_payload) | T_I8); - z80_payload.LD(HL, curr_rom.wWhichPokemon | T_U16); - z80_payload.LD(HL_PTR, A); - if (DONT_REMOVE_PKMN) - { - z80_payload.index += 3; - } - else - { - z80_payload.LD(B, (curr_rom._RemovePokemon >> 16) | T_U8); // Load ROM Bank - z80_payload.LD(HL, curr_rom._RemovePokemon | T_U16); - z80_payload.CALL(curr_rom.Bankswitch | T_U16); - } - z80_payload.JR((remove_array_loop.place_relative_jump(&z80_payload) & 0xFF) | T_I8); - - // We need to move this in order to not corrupt the 4E's - z80_payload.JR((save_box.place_relative_jump(&z80_payload) & 0xFF) | T_I8); - z80_payload.index = 0x17A; - - /* Save the current box */ - save_box.set_start(&z80_payload); - z80_payload.LD(B, (curr_rom.SaveSAVtoSRAM1 >> 16) | T_U8); // Load ROM Bank - z80_payload.LD(HL, curr_rom.SaveSAVtoSRAM1 | T_U16); - z80_payload.CALL(curr_rom.Bankswitch | T_U16); - z80_payload.CALL(curr_rom.SaveSAVtoSRAM2 | T_U16); // The bank is already loaded, we don't have to load it again - z80_payload.JP(curr_rom.SoftReset | T_U16); - - // z80_payload.index += 5; - - // Patchlist - // At 0x1BB / 0x1DE, 0xC2 in length (0xC4, but the last 2 are unused) - z80_patchlist.generate_patchlist(&z80_payload); - - // This payload works by placing Pokemon ID 0xFC's name in the stack, and causing a return to CD8E, - // which is part of the RNG seed. From there we can jump anywhere- and we choose to jump to D887, - // which is the rival's name. This code fixes the stack and jumps to the patchlist, which is where - // our final code is. - - // Update all the pointers - for (unsigned int i = 0; i < var_vector.size(); i++) - { - var_vector.at(i)->update_ptrs(); - } - for (unsigned int i = 0; i < jump_vector.size(); i++) - { - jump_vector.at(i)->update_jumps(); - } - - // Combine the vectors into the full payload - u8 *cur_out = payload_buffer; - memcpy(cur_out, z80_rng_seed.data_vector.data(), z80_rng_seed.data_vector.size()); - cur_out += z80_rng_seed.data_vector.size(); - memcpy(cur_out, z80_payload.data_vector.data(), z80_payload.data_vector.size()); - cur_out += z80_payload.data_vector.size(); - memcpy(cur_out, z80_patchlist.data_vector.data(), z80_patchlist.data_vector.size()); - cur_out += z80_patchlist.data_vector.size(); - - return; - - /* - else if (type == EVENT) - { - // ld a, $03 - payload_storage[offset++] = 0x3A; - payload_storage[offset++] = 0x03; - - // call OpenSRAM - payload_storage[offset++] = 0xC3; - payload_storage[offset++] = (curr_rom.OpenSRAM >> 0) & 0xFF; - payload_storage[offset++] = (curr_rom.OpenSRAM >> 8) & 0xFF; - - // ld de, $BEB0 - payload_storage[offset++] = 0x11; - payload_storage[offset++] = 0xB0; - payload_storage[offset++] = 0xBE; - - // ld bc, $150 - payload_storage[offset++] = 0x01; - payload_storage[offset++] = 0x50; - payload_storage[offset++] = 0x01; - - // ld hl, ??? - payload_storage[offset++] = 0x21; - payload_storage[offset++] = 0x00; - payload_storage[offset++] = 0x00; - - // CUSTOM EVENT SCRIPT: - // Start with the table data - int init_offset = offset; - insert_ext_copy_cmd(&offset, 0x11410E, 0xD930, 18); // Copy text pointers - insert_ext_copy_cmd(&offset, 0x00C120, 0xC140, 10); // - insert_ext_copy_cmd(&offset, 0x00C220, 0xC240, 16); // - byte temp[] = {0xD0, 0x0A}; - insert_int_copy_cmd(&offset, 0xD4E9, 2, temp); // - byte temp1[] = {0x15, 0x05}; - insert_int_copy_cmd(&offset, 0xD517, 2, temp1); // - byte temp2[] = {0x30, 0xD9}; - insert_int_copy_cmd(&offset, 0xD36B, 2, temp2); // - byte temp3[] = {0x0B, 0xF0, 0xFF}; - insert_int_copy_cmd(&offset, 0xD5D3, 3, temp3); // - byte temp4[] = {0x05}; - insert_int_copy_cmd(&offset, 0xD4E0, 1, temp4); // - byte temp5[] = {0x44, 0xD9, 0x08, 0x21, 0x54, 0xD9, 0xCD, 0x68, 0x31, 0x21, 0xB0, 0xC1, 0x00, 0x00, 0xC3, 0xD2, 0x23, 0x01, 0x00, 0x5E, 0xD8, 0xD8, 0xC9, 0xD8, 0xC9, 0xD8, 0xC9, 0xD8, 0xC9, 0x00, 0x8C, 0xB8, 0xB4, 0xB4, 0xE7, 0x50, 0x08, 0x3E, 0x83, 0xCD, 0x8B, 0x11, 0xCD, 0x3E, 0x37, 0xC3, 0xD2, 0x23}; - insert_int_copy_cmd(&offset, 0xD942, 48, temp5); // - payload_storage[offset++] = 0xFF; - - - // call CloseSRAM - payload_storage[offset++] = 0xC3; - payload_storage[offset++] = (curr_rom.CloseSRAM >> 0) & 0xFF; - payload_storage[offset++] = (curr_rom.CloseSRAM >> 8) & 0xFF; - - // call SoftReset - payload_storage[offset++] = 0xC3; - payload_storage[offset++] = (curr_rom.SoftReset >> 0) & 0xFF; - payload_storage[offset++] = (curr_rom.SoftReset >> 8) & 0xFF; - - }*/ - } - - else if (curr_rom.generation == 2) - { - std::vector jump_vector; - std::vector var_vector; - - z80_asm_handler z80_rng_seed(0x0A, curr_rom.wSerialOtherGameboyRandomNumberListBlock); - z80_asm_handler z80_payload(0x1CD, curr_rom.wSerialEnemyDataBlock); // wOTPartyData - z80_asm_handler z80_patchlist(0xC9, curr_rom.wSerialEnemyMonsPatchList); // wOTPatchLists - - /* - Initally the entire wLinkData is copied into the data section at D26B. - then, CopyBytes is called four times within link.skip_mail: - 1. It copies 0xB bytes from wLinkData to wOTPlayerName (D26B) - 2. It copies 0x8 bytes from where the previous one ended (D280) to wOTPartyCount - 3. It copies 0x2 bytes from where the previous one ended (D276) to wOTPlayerID - 4. It copies 0x1A4 bytes from where the previous one ended (D288) to wOTPartyMons - - 8 bytes aren't overwritten when copied over (D278-D28F), which is where the weird offset comes from. These bytes are index 0xE through 0x15 in the original data - By having 9 bytes of 0xFD, the offset ends up working out correctly. - */ - - z80_jump asm_start(&jump_vector); - z80_jump save_box(&jump_vector); - z80_jump remove_array_loop(&jump_vector); - z80_jump jump_to_party(&jump_vector); - z80_jump jump_to_payload(&jump_vector); - z80_jump packet_loop(&jump_vector); - z80_jump fe_bypass(&jump_vector); - z80_jump send_packet_loop(&jump_vector); - - z80_variable array_counter(&var_vector, 1, 0x00); // 1 byte to store the current array counter - z80_variable removal_array(&var_vector); // 40 byte storage for list of Pokemon to remove, plus a permanent array terminator - byte removal_array_data[41]; - for (int i = 0; i < 41; i++) - { - if (debug) - { - removal_array_data[i] = (i < 30 ? (29 - i) : 0xFF); - } - else - { - removal_array_data[i] = (i < 30 ? 0xFD : 0xFF); - } - } - removal_array.load_data(41, removal_array_data); - z80_variable transfer_wait_string(&var_vector, 13, // SENDING DATA - 0x92, 0x84, 0x8D, 0x83, 0x88, 0x8D, 0x86, 0x7F, 0x83, 0x80, 0x93, 0x80, 0x50); - z80_variable custom_name(&var_vector, 11, // FENNEL - 0x85, 0x84, 0x8D, 0x8D, 0x84, 0x8B, 0x50, 0x50, 0x50, 0x50, 0x50); - - // RNG Seed: - // at 0x00, 0x0A in length - // Does not need to be set - - // Preamble - // At 0x00, 0x09 in length - // Must be filled with 0xFD - for (int i = 0; i < 9; i++) - { - z80_payload.add_byte(0xFD); - } - - // Preamble/Rival name - // At 0x00, 0x1C5 in length - // Set to stored name - int distance = curr_rom.stack_overwrite_location - curr_rom.print_string_start; - int remainder = distance % 40; - distance /= 40; // Automatically truncated, so it won't overshoot - distance -= 8; // There will be 8 extra bytes due to how the copy functions work. - - for (int i = 0; i < distance; i++) - { - z80_payload.add_byte(curr_rom.short_pkmn_name); - } - for (int i = 0; i < remainder; i++) - { - z80_payload.add_byte(0x80); - } - - z80_payload.index -= 1; // Prep for the direct jump, since it usually has to jump forward one for the ASM call - jump_to_payload.place_direct_jump(&z80_payload); - z80_payload.index += 3; - z80_payload.add_byte(0x50); // String terminator - - // Saving the box overwrites our code, so we need to move it here. - jump_to_party.set_start(&z80_payload); - z80_payload.LD(A, curr_rom.SaveBox >> 16 | T_U8); - z80_payload.RST(0x10); // Bank switch - z80_payload.CALL(curr_rom.SaveBox | T_U16); - - z80_payload.JP(curr_rom.SoftReset | T_U16); - - // Patchlist preamble - // At 0x1B4 / 0x1D7, 0x07 in length - // Set as five 0xFD and two 0xFF - - for (int i = 0; i < 7; i++) - { - z80_patchlist.add_byte(i < 5 ? 0xFD : 0xFF); - } - - // Patchlist - // At 0x1DE, 194 in length - // Fill with custom code - - // Write transferring message to screen: - // call ClearScreen - jump_to_payload.set_start(&z80_patchlist); - z80_patchlist.CALL(curr_rom.clearScreen | T_U16); - - z80_patchlist.LD(HL, curr_rom.textBorderUppLeft | T_U16); - z80_patchlist.LD(C, curr_rom.textBorderWidth | T_U8); - z80_patchlist.LD(B, curr_rom.textBorderHeight | T_U8); - z80_patchlist.LD(A, curr_rom.CableClub_TextBoxBorder >> 16 | T_U8); - z80_patchlist.RST(0x10); // Bank switch - z80_patchlist.CALL(curr_rom.CableClub_TextBoxBorder | T_U16); - z80_patchlist.LD(HL, curr_rom.transferStringLocation | T_U16); - z80_patchlist.LD(DE, transfer_wait_string.place_ptr(&z80_patchlist) | T_U16); - - // call PlaceString - z80_patchlist.CALL(curr_rom.placeString | T_U16); - - // call OpenSRAM - z80_patchlist.LD(A, 0x01 | T_U8); - z80_patchlist.CALL(curr_rom.OpenSRAM | T_U16); - - /* Build the packet */ - // HL is the current data pointer - // DE is the destination pointer - // A is the checksum - // B is the 0xFE flag byte - // C is the counter - send_packet_loop.set_start(&z80_patchlist); - - z80_patchlist.LD(HL, (DATA_LOC + PACKET_SIZE + 3) | T_U16); // Load the next data location into HL - z80_patchlist.LD(A, HLI_PTR); - z80_patchlist.LD(H, HL_PTR); - z80_patchlist.LD(L, A); - - z80_patchlist.LD(DE, (DATA_LOC + 2) | T_U16); // Enemy Pokemon data, should be unused - z80_patchlist.XOR(A, A); // Clear the register - z80_patchlist.LD(B, A); // Clear B as well - z80_patchlist.LD(C, A); // Clear C as well - z80_patchlist.PUSH(AF); - packet_loop.set_start(&z80_patchlist); - z80_patchlist.LD(B, 0x00 | T_U8); // Reset the flag byte - z80_patchlist.POP(AF); - z80_patchlist.ADD(A, HL_PTR); // Add the current data to the checksum - z80_patchlist.PUSH(AF); - z80_patchlist.LD(A, 0xFE); - z80_patchlist.CP(A, HL_PTR); // Compare the current data to 0xFE - z80_patchlist.LD(A, HLI_PTR); // Load HL's data into A for modification (if need be) - - // If HL's data is 0xFE - z80_patchlist.JR(NZ_F, fe_bypass.place_relative_jump(&z80_patchlist) | T_I8); - z80_patchlist.DEC(A); - z80_patchlist.INC(B); // Set flag - - fe_bypass.set_start(&z80_patchlist); - z80_patchlist.LD(DE_PTR, A); // Place the data in - z80_patchlist.INC(DE); - z80_patchlist.PUSH(AF); - z80_patchlist.LD(A, B); - z80_patchlist.LD(DE_PTR, A); // Place the flag in as well - z80_patchlist.POP(AF); - z80_patchlist.INC(DE); - z80_patchlist.INC(C); - z80_patchlist.LD(A, DATA_PER_PACKET - 1); - z80_patchlist.CP(A, C); - z80_patchlist.JR(NC_F, packet_loop.place_relative_jump(&z80_patchlist) | T_I8); // If all the data has been set, send the rest of the data - z80_patchlist.POP(AF); - z80_patchlist.RES(7 | T_BIT, A); // Reset bit 7 of the checksum, guaranteeing that it will never be 0xFE - z80_patchlist.LD(DE_PTR, A); - z80_patchlist.INC(DE); - z80_patchlist.LD(A, H); - z80_patchlist.LD(DE_PTR, A); - z80_patchlist.INC(DE); - z80_patchlist.LD(A, L); - z80_patchlist.LD(DE_PTR, A); - - /* Transfer box data packet: */ - z80_patchlist.LD(A, (debug ? 0x02 : 0x01) | T_U8); // Make sure GB is the slave, master if debug - z80_patchlist.LDH((curr_rom.hSerialConnectionStatus & 0xFF) | T_U8, A); // Since hSerialConnectionStatus is at 0xFFxx we can use this method instead - z80_patchlist.LD(HL, DATA_LOC | T_U16); - z80_patchlist.LD(HL_PTR, 0xFD | T_U8); // set the start of the data to 0xFD so Serial_ExchangeBytes is happy - z80_patchlist.INC(HL); - z80_patchlist.LD(HL_PTR, 0x00 | T_U8); // add a 0x00 after the 0xFD to prevent further 0xFDs from being interpreted as part of the preamble - z80_patchlist.DEC(HL); // Reset HL back so it points to 0xFD - z80_patchlist.LD(DE, (DATA_LOC + PACKET_SIZE) | T_U16); // location to put stored data - z80_patchlist.LD(BC, PACKET_SIZE | T_U16); - if (debug) // Don't call serialExchangeBytes if debug is enabled - { - z80_patchlist.index += 3; - } - else - { - z80_patchlist.CALL(curr_rom.Serial_ExchangeBytes | T_U16); - } - - z80_patchlist.LD(A, (DATA_LOC + PACKET_SIZE + 3 + 1) | T_U16); - z80_patchlist.CP(A, 0xFF); - z80_patchlist.JR(NZ_F, send_packet_loop.place_relative_jump(&z80_patchlist) | T_I8); - - // Recieve the Pokemon to remove - z80_patchlist.LD(HL, curr_rom.hSerialConnectionStatus | T_U16); // This can also be shortened - z80_patchlist.LD(HL_PTR, (debug ? 0x02 : 0x01) | T_U8); // Make sure GB is the slave, master if debug - z80_patchlist.LD(HL, curr_rom.garbageDataLocation | T_U16); - z80_patchlist.LD(DE, removal_array.place_ptr(&z80_patchlist) | T_U16); - z80_patchlist.LD(BC, 0x001E | T_U16); // Preamble does *not* count - if (debug) // Don't add in the Serial_ExchangeBytes call if in debug - { - z80_patchlist.index += 3; - } - else - { - z80_patchlist.CALL(curr_rom.Serial_ExchangeBytes | T_U16); - } - - // Remove the transfered Pokemon - z80_patchlist.LD(HL, curr_rom.wRemoveMonFromBox | T_U16); - z80_patchlist.LD(HL_PTR, 0x01 | T_U8); // != 0x00 specifies the current box - remove_array_loop.set_start(&z80_patchlist); - z80_patchlist.LD(A, array_counter.place_ptr(&z80_patchlist) | T_U16); - z80_patchlist.LD(E, A); - z80_patchlist.LD(D, 0x00 | T_U8); - z80_patchlist.LD(HL, removal_array.place_ptr(&z80_patchlist) | T_U16); - z80_patchlist.ADD(HL, DE); - z80_patchlist.INC(A); - z80_patchlist.LD(array_counter.place_ptr(&z80_patchlist) | T_U16, A); - z80_patchlist.LD(A, curr_rom.wBoxCount | T_U16); - z80_patchlist.LD(B, A); - z80_patchlist.LD(A, HL_PTR); - z80_patchlist.CP(A, 0xFF | T_U8); - z80_patchlist.JR(Z_F, save_box.place_relative_jump(&z80_patchlist) | T_I8); - z80_patchlist.CP(A, B); - z80_patchlist.JR(NC_F, remove_array_loop.place_relative_jump(&z80_patchlist) | T_I8); - z80_patchlist.LD(HL, curr_rom.wWhichPokemon | T_U16); - z80_patchlist.LD(HL_PTR, A); - if (DONT_REMOVE_PKMN) - { - z80_patchlist.index += 6; - } - else - { - z80_patchlist.LD(A, curr_rom._RemovePokemon >> 16 | T_U8); - z80_patchlist.RST(0x10); // Bank switch - z80_patchlist.CALL(curr_rom._RemovePokemon | T_U16); - } - z80_patchlist.JR(remove_array_loop.place_relative_jump(&z80_patchlist) | T_I8); - - save_box.set_start(&z80_patchlist); - z80_patchlist.JP(jump_to_party.place_direct_jump(&z80_patchlist) | T_U16); // jp pkmn list (because saving the box overwrites the data) - - array_counter.insert_variable(&z80_patchlist); - removal_array.insert_variable(&z80_payload); - transfer_wait_string.insert_variable(&z80_patchlist); - - // This payload works by placing Pokemon ID 0xFC's name in the stack, and causing a return to CD8E, - // which is part of the RNG seed. From there we can jump anywhere- and we choose to jump to D887, - // which is the rival's name. This code fixes the stack and jumps to the patchlist, which is where - // our final code is. - - // Update all the pointers - for (unsigned int i = 0; i < var_vector.size(); i++) - { - var_vector.at(i)->update_ptrs(); - } - for (unsigned int i = 0; i < jump_vector.size(); i++) - { - jump_vector.at(i)->update_jumps(); - } - - // Combine the vectors into the full payload - u8 *cur_out = payload_buffer; - memcpy(cur_out, z80_rng_seed.data_vector.data(), z80_rng_seed.data_vector.size()); - cur_out += z80_rng_seed.data_vector.size(); - memcpy(cur_out, z80_payload.data_vector.data(), z80_payload.data_vector.size()); - cur_out += z80_payload.data_vector.size(); - memcpy(cur_out, z80_patchlist.data_vector.data(), z80_patchlist.data_vector.size()); - cur_out += z80_patchlist.data_vector.size(); - - return; - - // This payload works by placing Pokemon ID 0xFC's name in the stack, and causing a return to CD8E, - // which is part of the RNG seed. From there we can jump anywhere- and we choose to jump to D887, - // which is the rival's name. This code fixes the stack and jumps to the patchlist, which is where - // our final code is. - } - memset(payload_buffer, 0x00, PAYLOAD_SIZE); -}; - -#if PAYLOAD_EXPORT_TEST -#include -#include "gb_rom_values/gb_rom_values.h" -int main() // Rename to "main" to send the payload to test_payload.txt -{ - byte buffer[672] = {0}; - freopen("test_payload.txt", "w", stdout); - printf("\n"); - init_payload(buffer, gb_rom_values_eng[RED_ID], TRANSFER, true); - - if (true) - { - for (int i = 0; i < 0x2A0; i++) - { - printf("0x%02X, ", (unsigned int)buffer[i]); - if (i % 0x10 == 0xF) - { - printf("\n# 0x%X\n", i + 1); - } - } - return 0; - } - else - { - for (int i = 0; i < 0x150; i++) - { - printf("%02X ", (unsigned int)buffer[i + ((0x10 * 28) + 9)]); - if (i % 0x10 == 0xF) - { - printf("\n"); - } - } - return 0; - } -} -#endif \ No newline at end of file diff --git a/source/background_engine.cpp b/source/background_engine.cpp index cf39cb4..93ad621 100644 --- a/source/background_engine.cpp +++ b/source/background_engine.cpp @@ -36,7 +36,7 @@ void reset_textbox() { tte_erase_rect(0, 0, H_MAX, V_MAX); reload_textbox_background(); - tte_set_pos(1 * 8, 14 * 8); + tte_set_pos(LEFT, TOP); tte_set_margins(LEFT, TOP, RIGHT, BOTTOM); } diff --git a/source/box_menu.cpp b/source/box_menu.cpp index e26f2f8..22e5265 100644 --- a/source/box_menu.cpp +++ b/source/box_menu.cpp @@ -36,7 +36,7 @@ int Box_Menu::box_main(PokeBox* box) obj_unhide(box_select, 0); int index = 0; - PKMN_NAMES.decompress(get_compressed_pkmn_names_table()); + PKMN_NAMES.decompress(get_compressed_text_table(PKMN_NAMES_INDEX)); while (true) { diff --git a/source/gameboy_colour.cpp b/source/gameboy_colour.cpp index d6a5984..4db3084 100644 --- a/source/gameboy_colour.cpp +++ b/source/gameboy_colour.cpp @@ -169,7 +169,7 @@ void setup(const u16 *debug_charset) u8 general_text_table_buffer[2048]; text_data_table general_text(general_text_table_buffer); - general_text.decompress(get_compressed_general_table()); + general_text.decompress(get_compressed_text_table(GENERAL_INDEX)); ptgb_write(general_text.get_text_entry(GENERAL_connecting), true); } } @@ -228,7 +228,7 @@ byte handleIncomingByte(byte in, byte *box_data_storage, byte *curr_payload, GB_ u8 general_text_table_buffer[2048]; text_data_table general_text(general_text_table_buffer); - general_text.decompress(get_compressed_general_table()); + general_text.decompress(get_compressed_text_table(GENERAL_INDEX)); ptgb_write(general_text.get_text_entry(curr_gb_rom->version != YELLOW_ID ? GENERAL_link_success : GENERAL_link_success_yellow), true); } @@ -280,7 +280,7 @@ byte handleIncomingByte(byte in, byte *box_data_storage, byte *curr_payload, GB_ u8 general_text_table_buffer[2048]; text_data_table general_text(general_text_table_buffer); - general_text.decompress(get_compressed_general_table()); + general_text.decompress(get_compressed_text_table(GENERAL_INDEX)); ptgb_write(general_text.get_text_entry(GENERAL_transferring), true); } diff --git a/source/global_frame_controller.cpp b/source/global_frame_controller.cpp index e12927c..081e63c 100644 --- a/source/global_frame_controller.cpp +++ b/source/global_frame_controller.cpp @@ -27,7 +27,7 @@ static void __attribute__((noinline)) show_pulled_cart_error() u8 general_text_table_buffer[2048]; text_data_table general_text(general_text_table_buffer); - general_text.decompress(get_compressed_general_table()); + general_text.decompress(get_compressed_text_table(GENERAL_INDEX)); ptgb_write(general_text.get_text_entry(GENERAL_pulled_cart_error), true); } @@ -267,7 +267,7 @@ bool get_treecko_enabled() return treecko_enabled; } -int get_string_length(const byte *str) +int get_string_char_count(const byte *str) { int size = 0; while (str[size] != 0xFF) @@ -277,6 +277,18 @@ int get_string_length(const byte *str) return size; } +int get_string_length(const byte *str) +{ + int size = 0; + int length = 0; + while (str[size] != 0xFF) + { + length += tte_get_glyph_width(str[size]); + size++; + } + return length; +} + void convert_int_to_ptgb_str(int val, byte str[], int min_length) { int div = 1; diff --git a/source/japanese_small.s b/source/japanese_small.s deleted file mode 100644 index 3238a8c..0000000 --- a/source/japanese_small.s +++ /dev/null @@ -1,163 +0,0 @@ - -@{{BLOCK(japanese_small) - - .section .rodata - .align 2 - .global japanese_smallFont -japanese_smallFont: - .word japanese_smallGlyphs, 0, 0 - .hword 0, 256 - .byte 8, 10 - .byte 8, 16 - .hword 16 - .byte 1, 0 - - .section .rodata - .align 2 - .global japanese_smallGlyphs @ 4096 unsigned chars -japanese_smallGlyphs: - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x3F040000,0x49553E04,0x00000026,0x00000000 - .word 0x21000000,0x0A414141,0x00000004,0x00000000,0x001E0000,0x1020201E,0x0000000C,0x00000000 - .word 0x001E0000,0x120C101F,0x00000061,0x00000000,0x5F440000,0x45453E04,0x00000026,0x00000000 - .word 0x4F220000,0x10111252,0x0000000C,0x00000000,0x3F080000,0x01107E08,0x0000003E,0x00000000 - .word 0x08100000,0x08040204,0x00000010,0x00000000,0x79200000,0x21212121,0x00000012,0x00000000 - .word 0x1F000000,0x01000020,0x0000003E,0x00000000,0x7F080000,0x01013E10,0x0000003E,0x00000000 - .word 0x02020000,0x42420202,0x0000003C,0x00000000,0x7F200000,0x203C223C,0x00000018,0x00000000 - .word 0x22220000,0x0212227F,0x0000003C,0x00000000,0x081E0000,0x020C3F04,0x0000001C,0x00000000 - - .word 0x3F040000,0x09027A02,0x00000071,0x00000000,0x3F040000,0x40423E02,0x00000038,0x00000000 - .word 0x3F000000,0x20404040,0x0000001C,0x00000000,0x307F0000,0x08040408,0x00000030,0x00000000 - .word 0x34040000,0x0101010E,0x0000007E,0x00000000,0x4F240000,0x623C2102,0x0000001C,0x00000000 - .word 0x01790000,0x05050101,0x00000079,0x00000000,0x12120000,0x55654B3E,0x00000032,0x00000000 - .word 0x37040000,0x5566444C,0x00000074,0x00000000,0x2A1C0000,0x49494949,0x00000026,0x00000000 - .word 0x79210000,0x65392121,0x00000019,0x00000000,0x240F0000,0x11312262,0x0000000E,0x00000000 - .word 0x101C0000,0x51511208,0x0000000C,0x00000000,0x04000000,0x4020110A,0x00000000,0x00000000 - .word 0x21790000,0x65392179,0x00000019,0x00000000,0x207C0000,0x623C207C,0x0000003C,0x00000000 - - .word 0x280E0000,0x25653E28,0x00000012,0x00000000,0x5F440000,0x46450506,0x0000003C,0x00000000 - .word 0x1A120000,0x4D495536,0x00000032,0x00000000,0x1F040000,0x44041F04,0x00000038,0x00000000 - .word 0x3F120000,0x04324252,0x00000004,0x00000000,0x3D080000,0x3C515153,0x00000008,0x00000000 - .word 0x38080000,0x093E0808,0x00000006,0x00000000,0x011C0000,0x2020231D,0x0000001E,0x00000000 - .word 0x22220000,0x10202222,0x0000000C,0x00000000,0x081E0000,0x524C413E,0x0000003C,0x00000000 - .word 0x37040000,0x2526444C,0x00000044,0x00000000,0x183E0000,0x4040423C,0x00000038,0x00000000 - .word 0x37040000,0x4546444C,0x00000024,0x00000000,0x3E040000,0x04143A0C,0x00000038,0x00000000 - .word 0x04040000,0x11120E04,0x00000061,0x00000000,0x04000000,0x351E143F,0x0000002E,0x00000000 - - .word 0x00000000,0x0A212111,0x00000004,0x00000000,0x1E000000,0x10201E00,0x0000000C,0x00000000 - .word 0x0E000000,0x1E081F00,0x00000031,0x00000000,0x24000000,0x251E042F,0x00000016,0x00000000 - .word 0x0A000000,0x14222B1E,0x00000004,0x00000000,0x08000000,0x1C292B1D,0x00000008,0x00000000 - .word 0x08000000,0x190E0818,0x0000000E,0x00000000,0x2F025050,0x10115252,0x0000000C,0x00000000 - .word 0x3F085050,0x01107E08,0x0000003E,0x00000000,0x08100000,0x08045254,0x00000010,0x00000000 - .word 0x79205050,0x21212121,0x00000012,0x00000000,0x1F005050,0x01000020,0x0000003E,0x00000000 - .word 0x7F085050,0x01013E10,0x0000003E,0x00000000,0x52020000,0x42420252,0x0000003C,0x00000000 - .word 0x7F205050,0x203C223C,0x00000018,0x00000000,0x22225050,0x0212227F,0x0000003C,0x00000000 - - .word 0x080E5050,0x020C3F04,0x0000001C,0x00000000,0x3F045050,0x09027A02,0x00000071,0x00000000 - .word 0x3F045050,0x40423E02,0x00000038,0x00000000,0x3F005050,0x20404040,0x0000001C,0x00000000 - .word 0x307F5050,0x08040408,0x00000030,0x00000000,0x34045050,0x0101010E,0x0000007E,0x00000000 - .word 0x79215050,0x65392121,0x00000019,0x00000000,0x240F5050,0x11312262,0x0000000E,0x00000000 - .word 0x100C5050,0x51511208,0x0000000C,0x00000000,0x54500000,0x4020110A,0x00000000,0x00000000 - .word 0x21795050,0x65392179,0x00000019,0x00000000,0x79216060,0x65392121,0x00000019,0x00000000 - .word 0x240F6060,0x11312262,0x0000000E,0x00000000,0x101C6060,0x51511208,0x0000000C,0x00000000 - .word 0x34300000,0x4020110A,0x00000000,0x00000000,0x21396060,0x65392179,0x00000019,0x00000000 - - .word 0x00000000,0x0810100F,0x00000006,0x00000000,0x407F0000,0x08083848,0x00000006,0x00000000 - .word 0x10200000,0x08080B0C,0x00000008,0x00000000,0x7F080000,0x20404141,0x00000018,0x00000000 - .word 0x3E000000,0x08080808,0x0000007F,0x00000000,0x7F100000,0x11121418,0x00000018,0x00000000 - .word 0x7E040000,0x42444444,0x00000031,0x00000000,0x7F080000,0x087F0808,0x00000008,0x00000000 - .word 0x223E0000,0x10202021,0x0000000E,0x00000000,0x7E020000,0x10202122,0x0000000C,0x00000000 - .word 0x203F0000,0x20202020,0x0000003F,0x00000000,0x7F220000,0x20202222,0x0000001C,0x00000000 - .word 0x400E0000,0x2040404E,0x0000001E,0x00000000,0x203F0000,0x24181020,0x00000043,0x00000000 - .word 0x7F020000,0x02022242,0x0000003C,0x00000000,0x41410000,0x10202042,0x0000000C,0x00000000 - - .word 0x427E0000,0x2040714E,0x0000001C,0x00000000,0x1E300000,0x08107F10,0x00000006,0x00000000 - .word 0x4A4A0000,0x2040404A,0x0000001C,0x00000000,0x003E0000,0x1010107F,0x0000000C,0x00000000 - .word 0x04040000,0x0404443C,0x00000004,0x00000000,0x7F100000,0x08101010,0x00000006,0x00000000 - .word 0x3E000000,0x00000000,0x0000007F,0x00000000,0x203F0000,0x14081420,0x00000023,0x00000000 - .word 0x7F080000,0x4B2C1820,0x00000008,0x00000000,0x20200000,0x0C101020,0x00000003,0x00000000 - .word 0x12000000,0x41422222,0x00000041,0x00000000,0x31010000,0x0101010F,0x0000007E,0x00000000 - .word 0x407F0000,0x10202040,0x0000000C,0x00000000,0x04000000,0x4020110A,0x00000000,0x00000000 - .word 0x7F080000,0x4A4A2A08,0x00000049,0x00000000,0x407F0000,0x08142240,0x00000010,0x00000000 - - .word 0x001E0000,0x03001C02,0x0000003C,0x00000000,0x04040000,0x41222204,0x0000007F,0x00000000 - .word 0x24200000,0x4C301028,0x00000003,0x00000000,0x043F0000,0x04047F04,0x00000078,0x00000000 - .word 0x7F040000,0x04142444,0x00000004,0x00000000,0x101E0000,0x7F101010,0x00000000,0x00000000 - .word 0x407F0000,0x40407E40,0x0000007F,0x00000000,0x003E0000,0x2040407F,0x0000001C,0x00000000 - .word 0x22220000,0x10202222,0x0000000C,0x00000000,0x0A0A0000,0x4A0A0A0A,0x00000039,0x00000000 - .word 0x02020000,0x1A224202,0x00000006,0x00000000,0x417F0000,0x7F414141,0x00000000,0x00000000 - .word 0x417F0000,0x20404041,0x0000001C,0x00000000,0x407F0000,0x20407E40,0x0000001E,0x00000000 - .word 0x40470000,0x20404040,0x0000001F,0x00000000,0x00000000,0x0C14101F,0x00000002,0x00000000 - - .word 0x00000000,0x080E0810,0x00000008,0x00000000,0x00000000,0x08111F04,0x00000006,0x00000000 - .word 0x00000000,0x04040E00,0x0000001F,0x00000000,0x00000000,0x0A0C1F08,0x00000009,0x00000000 - .word 0x00000000,0x0A121F02,0x00000002,0x00000000,0x00000000,0x08080E00,0x0000001F,0x00000000 - .word 0x00000000,0x080F080F,0x0000000F,0x00000000,0x7E045050,0x42444444,0x00000031,0x00000000 - .word 0x7F085050,0x087F0808,0x00000008,0x00000000,0x223E5050,0x10202021,0x0000000E,0x00000000 - .word 0x7E025050,0x10202122,0x0000000C,0x00000000,0x203F5050,0x20202020,0x0000003F,0x00000000 - .word 0x7F225050,0x20202222,0x0000001C,0x00000000,0x400E5050,0x2040404E,0x0000001E,0x00000000 - .word 0x203F5050,0x24181020,0x00000043,0x00000000,0x7F025050,0x02022242,0x0000003C,0x00000000 - - .word 0x41015050,0x10202042,0x0000000C,0x00000000,0x427E5050,0x2040714E,0x0000001C,0x00000000 - .word 0x1E305050,0x08107F10,0x00000006,0x00000000,0x4A0A5050,0x2040404A,0x0000001C,0x00000000 - .word 0x003E5050,0x1010107F,0x0000000C,0x00000000,0x04045050,0x0404443C,0x00000004,0x00000000 - .word 0x12005050,0x41422222,0x00000041,0x00000000,0x31015050,0x0101010F,0x0000007E,0x00000000 - .word 0x407F5050,0x10202040,0x0000000C,0x00000000,0x54500000,0x4020110A,0x00000000,0x00000000 - .word 0x7F085050,0x4A4A2A08,0x00000049,0x00000000,0x12606000,0x41422222,0x00000041,0x00000000 - .word 0x19616000,0x01010107,0x0000007E,0x00000000,0x7F606000,0x10202040,0x0000000C,0x00000000 - .word 0x34300000,0x4020110A,0x00000000,0x00000000,0x7F686000,0x4A4A2A08,0x00000049,0x00000000 - - .word 0x00000000,0x08101515,0x00000006,0x00000000,0x1C000000,0x26636332,0x0000001C,0x00000000 - .word 0x18000000,0x1818181C,0x0000007E,0x00000000,0x3E000000,0x071E7063,0x0000007F,0x00000000 - .word 0x7E000000,0x63601C30,0x0000003E,0x00000000,0x38000000,0x7F33363C,0x00000030,0x00000000 - .word 0x3F000000,0x63603F03,0x0000003E,0x00000000,0x3E000000,0x63633F03,0x0000003E,0x00000000 - .word 0x7F000000,0x0C183063,0x0000000C,0x00000000,0x3E000000,0x63633E63,0x0000003E,0x00000000 - .word 0x3E000000,0x607E6363,0x0000003E,0x00000000,0x3C3C0000,0x1800183C,0x00000018,0x00000000 - .word 0x673E0000,0x18001873,0x00000018,0x00000000,0x00000000,0x0A0E0000,0x0000000E,0x00000000 - .word 0x00000000,0x00003F00,0x00000000,0x00000000,0x00000000,0x00181800,0x00000000,0x00000000 - - .word 0x00000000,0x00220000,0x00000000,0x00000000,0x447C0000,0x1C141474,0x00000000,0x00000000 - .word 0x1C000000,0x11171414,0x0000001F,0x00000000,0x10700000,0x00001010,0x00000000,0x00000000 - .word 0x00000000,0x04040400,0x00000007,0x00000000,0x2A1C0000,0x22221C08,0x0000001C,0x00000000 - .word 0x221C0000,0x3E081C22,0x00000808,0x00000000,0x497F0000,0x41417F49,0x00000061,0x00000000 - .word 0x00000000,0x0C0C0000,0x00000000,0x00000000,0x22000000,0x22140814,0x00000000,0x00000000 - .word 0x20400000,0x02040810,0x00000001,0x00000000,0x361C0000,0x637F6363,0x00000063,0x00000000 - .word 0x633F0000,0x63633F63,0x0000003F,0x00000000,0x673E0000,0x67030303,0x0000003E,0x00000000 - .word 0x331F0000,0x33636363,0x0000001F,0x00000000,0x037F0000,0x03033F03,0x0000007F,0x00000000 - - .word 0x037F0000,0x03033F03,0x00000003,0x00000000,0x077E0000,0x67637303,0x0000007E,0x00000000 - .word 0x63630000,0x63637F63,0x00000063,0x00000000,0x187E0000,0x18181818,0x0000007E,0x00000000 - .word 0x60600000,0x63636060,0x0000003E,0x00000000,0x63630000,0x63331F33,0x00000063,0x00000000 - .word 0x06060000,0x06060606,0x0000007E,0x00000000,0x63410000,0x636B7F77,0x00000063,0x00000000 - .word 0x67630000,0x737B7F6F,0x00000063,0x00000000,0x633E0000,0x63636363,0x0000003E,0x00000000 - .word 0x633F0000,0x033F6363,0x00000003,0x00000000,0x633E0000,0x3B636363,0x0000006E,0x00000000 - .word 0x633F0000,0x3B1F7363,0x00000073,0x00000000,0x331E0000,0x63603E03,0x0000003E,0x00000000 - .word 0x187E0000,0x18181818,0x00000018,0x00000000,0x63630000,0x63636363,0x0000003E,0x00000000 - - .word 0x63630000,0x1C3E7763,0x00000008,0x00000000,0x63630000,0x777F7F6B,0x00000063,0x00000000 - .word 0x63630000,0x63361C36,0x00000063,0x00000000,0x66660000,0x18183C66,0x00000018,0x00000000 - .word 0x707F0000,0x070E1C38,0x0000007F,0x00000000,0x00000000,0x667E603C,0x0000007C,0x00000000 - .word 0x06000000,0x66663E06,0x0000003E,0x00000000,0x00000000,0x6606663C,0x0000003C,0x00000000 - .word 0x60000000,0x66667C60,0x0000007C,0x00000000,0x00000000,0x067E663C,0x0000003C,0x00000000 - .word 0x38000000,0x0C0C3E0C,0x0000000C,0x00000000,0x7C000000,0x607C6666,0x0000003E,0x00000000 - .word 0x06000000,0x66663E06,0x00000066,0x00000000,0x18000000,0x18181800,0x00000018,0x00000000 - .word 0x30000000,0x33303000,0x0000001E,0x00000000,0x06000000,0x361E3666,0x00000066,0x00000000 - - .word 0x0E000000,0x0C0C0C0C,0x0000000C,0x00000000,0x00000000,0x6B6B6B3F,0x00000063,0x00000000 - .word 0x00000000,0x6666663E,0x00000066,0x00000000,0x00000000,0x6666663C,0x0000003C,0x00000000 - .word 0x00000000,0x3E66663C,0x00000006,0x00000000,0x00000000,0x7C66663C,0x00000060,0x00000000 - .word 0x00000000,0x0C0C1C6C,0x0000000C,0x00000000,0x00000000,0x303E063C,0x0000001E,0x00000000 - .word 0x0C000000,0x0C0C0C1E,0x0000001C,0x00000000,0x00000000,0x66666666,0x0000007C,0x00000000 - .word 0x00000000,0x36666666,0x0000001C,0x00000000,0x00000000,0x6B6B6B63,0x00000037,0x00000000 - .word 0x00000000,0x361C3663,0x00000063,0x00000000,0x00000000,0x607C6666,0x0000003C,0x00000000 - .word 0x00000000,0x0C18307E,0x0000007E,0x00000000,0x0E060000,0x0E1E3E1E,0x00000006,0x00000000 - - .word 0x00000000,0x08000008,0x00000000,0x00000000,0x00660000,0x7F63361C,0x00000063,0x00000000 - .word 0x00660000,0x6363633E,0x0000003E,0x00000000,0x00660000,0x63636363,0x0000003E,0x00000000 - .word 0x00660000,0x667E603C,0x0000007C,0x00000000,0x00660000,0x6666663C,0x0000003C,0x00000000 - .word 0x00660000,0x66666666,0x0000007C,0x00000000,0xFFFFFE7C,0xC68339EF,0x0000007C,0x00000000 - .word 0x01010000,0x00010101,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - -@}}BLOCK(japanese_small) diff --git a/source/latin_short.s b/source/latin_short.s deleted file mode 100644 index 0fa33bf..0000000 --- a/source/latin_short.s +++ /dev/null @@ -1,163 +0,0 @@ - -@{{BLOCK(latin_short) - - .section .rodata - .align 2 - .global latin_shortFont -latin_shortFont: - .word latin_shortGlyphs, 0, 0 - .hword 0, 256 - .byte 6, 10 - .byte 8, 16 - .hword 16 - .byte 1, 0 - - .section .rodata - .align 2 - .global latin_shortGlyphs @ 4096 unsigned chars -latin_shortGlyphs: - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x0E000806,0x111F1111,0x00000011,0x00000000 - .word 0x0E00020C,0x111F1111,0x00000011,0x00000000,0x0E000A04,0x111F1111,0x00000011,0x00000000 - .word 0x0101110E,0x08041E11,0x00000006,0x00000000,0x1F000806,0x01010F01,0x0000001F,0x00000000 - .word 0x1F00020C,0x01010F01,0x0000001F,0x00000000,0x1F000A04,0x01010F01,0x0000001F,0x00000000 - .word 0x1F000011,0x01010F01,0x0000001F,0x00000000,0x1F000806,0x04040404,0x0000001F,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x1F000A04,0x04040404,0x0000001F,0x00000000 - .word 0x1F000011,0x04040404,0x0000001F,0x00000000,0x0E000806,0x11111111,0x0000000E,0x00000000 - .word 0x0E00020C,0x11111111,0x0000000E,0x00000000,0x0E000A04,0x11111111,0x0000000E,0x00000000 - - .word 0x76000000,0x19117119,0x00000076,0x00000000,0x11000806,0x11111111,0x0000000E,0x00000000 - .word 0x1100020C,0x11111111,0x0000000E,0x00000000,0x11000A04,0x11111111,0x0000000E,0x00000000 - .word 0x11001926,0x11191513,0x00000011,0x00000000,0x09090700,0x09110907,0x00000001,0x00000000 - .word 0x00080600,0x1911111E,0x00000016,0x00000000,0x00020C00,0x1911111E,0x00000016,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x01110E00,0x08040E11,0x00000006,0x00000000 - .word 0x00080600,0x011F110E,0x0000001E,0x00000000,0x00020C00,0x011F110E,0x0000001E,0x00000000 - .word 0x000A0400,0x011F110E,0x0000001E,0x00000000,0x00001100,0x011F110E,0x0000001E,0x00000000 - .word 0x00080600,0x04040404,0x00000004,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - - .word 0x000A0400,0x04040404,0x00000004,0x00000000,0x00001100,0x04040404,0x00000004,0x00000000 - .word 0x00080600,0x1111110E,0x0000000E,0x00000000,0x00020C00,0x1111110E,0x0000000E,0x00000000 - .word 0x000A0400,0x1111110E,0x0000000E,0x00000000,0x00000000,0x09794936,0x00000076,0x00000000 - .word 0x00080600,0x09090909,0x00000016,0x00000000,0x00020C00,0x09090909,0x00000016,0x00000000 - .word 0x000A0400,0x09090909,0x00000016,0x00000000,0x00192600,0x1212120E,0x00000012,0x00000000 - .word 0x1111110E,0x0000000E,0x00000000,0x00000000,0x0909090E,0x00000016,0x00000000,0x00000000 - .word 0x212F69A6,0x0000002E,0x00000000,0x00000000,0x08141408,0x12121428,0x0000002C,0x00000000 - .word 0x00000000,0x083E0808,0x00000008,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x11010100,0x47A1A111,0x00000000,0x00000000,0x013E0000,0x00003E01,0x00000000,0x00000000 - .word 0x00060600,0x04060600,0x00000002,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - - .word 0x1111111F,0x11111111,0x0000001F,0x00000000,0x04000404,0x11111106,0x0000000E,0x00000000 - .word 0x04000404,0x04040404,0x00000004,0x00000000,0x57555507,0x50515131,0x00000050,0x00000000 - .word 0x59494F09,0x49696959,0x00000048,0x00000000,0xBF858587,0x28A9A9A9,0x00000038,0x00000000 - .word 0x39021222,0x280A3A2A,0x00000038,0x00000000,0x95951300,0x95959593,0x00000073,0x00000000 - .word 0x8AAA9100,0xAA8A8A8A,0x00000091,0x00000000,0x02040400,0x04020101,0x00000004,0x00000000 - .word 0x1F00020C,0x04040404,0x0000001F,0x00000000,0x15252700,0x74080817,0x00725254,0x00000000 - .word 0x02020204,0x02020202,0x00000004,0x00000000,0x04040402,0x04040404,0x00000002,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x000A0400,0x1911111E,0x00000016,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00020C00,0x04040404,0x00000004,0x00000000 - - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0xFE7C3810,0x7C7C7CFF,0x00000000,0x00000000 - .word 0x7C7C7C00,0x387CFEFF,0x00000010,0x00000000,0xFEFC1810,0x18FCFEFF,0x00000010,0x00000000 - .word 0xFE7E3010,0x307EFEFE,0x00000010,0x00000000,0x00000000,0x00000001,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x010F0906,0x0000000E,0x00000000,0x00000000,0x04081020,0x10080402,0x00000020,0x00000000 - .word 0x10080402,0x04081020,0x00000002,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - - .word 0x09794B35,0x00000071,0x00000000,0x00000000,0x1111110E,0x11111111,0x0000000E,0x00000000 - .word 0x04040604,0x04040404,0x0000000E,0x00000000,0x1011110E,0x01020408,0x0000001F,0x00000000 - .word 0x1010110E,0x1110100C,0x0000000E,0x00000000,0x090A0A0C,0x081F0909,0x00000008,0x00000000 - .word 0x0101011F,0x1110100F,0x0000000E,0x00000000,0x0101110E,0x1111110F,0x0000000E,0x00000000 - .word 0x1010101F,0x04040808,0x00000004,0x00000000,0x1111110E,0x1111110E,0x0000000E,0x00000000 - .word 0x1111110E,0x1110101E,0x0000000E,0x00000000,0x04040404,0x04000404,0x00000004,0x00000000 - .word 0x1111110E,0x0400040C,0x00000004,0x00000000,0x00000000,0x06000000,0x00000006,0x00000000 - .word 0x00000000,0x0000001F,0x00000000,0x00000000,0x00000000,0x00000606,0x00000000,0x00000000 - - .word 0x00000000,0x00000000,0x00150000,0x00000000,0x1B1B0912,0x00000000,0x00000000,0x00000000 - .word 0x09121B1B,0x00000000,0x00000000,0x00000000,0x03030102,0x00000000,0x00000000,0x00000000 - .word 0x01020303,0x00000000,0x00000000,0x00000000,0x04150E04,0x1111110E,0x0000000E,0x00000000 - .word 0x1111110E,0x041F040E,0x00000004,0x00000000,0x1C24241C,0x3E043E04,0x00000004,0x00000000 - .word 0x00000000,0x04060600,0x00000002,0x00000000,0x42000000,0x24181824,0x00000042,0x00000000 - .word 0x08081000,0x02020404,0x00000001,0x00000000,0x11110E00,0x11111F11,0x00000011,0x00000000 - .word 0x11110F00,0x1111110F,0x0000000F,0x00000000,0x01110E00,0x11010101,0x0000000E,0x00000000 - .word 0x11110F00,0x11111111,0x0000000F,0x00000000,0x01011F00,0x0101010F,0x0000001F,0x00000000 - - .word 0x01011F00,0x0101010F,0x00000001,0x00000000,0x11110E00,0x11111901,0x0000000E,0x00000000 - .word 0x11111100,0x1111111F,0x00000011,0x00000000,0x04041F00,0x04040404,0x0000001F,0x00000000 - .word 0x10101000,0x11101010,0x0000000E,0x00000000,0x05091100,0x09050303,0x00000011,0x00000000 - .word 0x01010100,0x01010101,0x0000001F,0x00000000,0x1B1B1100,0x11111515,0x00000011,0x00000000 - .word 0x13131100,0x11191915,0x00000011,0x00000000,0x11110E00,0x11111111,0x0000000E,0x00000000 - .word 0x11110F00,0x01010F11,0x00000001,0x00000000,0x11110E00,0x19171111,0x0000002E,0x00000000 - .word 0x11110F00,0x11090F11,0x00000011,0x00000000,0x01110E00,0x11100806,0x0000000E,0x00000000 - .word 0x04041F00,0x04040404,0x00000004,0x00000000,0x11111100,0x11111111,0x0000000E,0x00000000 - - .word 0x11111100,0x040A0A11,0x00000004,0x00000000,0x15111100,0x1B1B1515,0x00000011,0x00000000 - .word 0x0A111100,0x110A0404,0x00000011,0x00000000,0x0A111100,0x0404040A,0x00000004,0x00000000 - .word 0x08101F00,0x01020404,0x0000001F,0x00000000,0x00000000,0x1911111E,0x00000016,0x00000000 - .word 0x01010100,0x1111110F,0x0000000F,0x00000000,0x00000000,0x1101110E,0x0000000E,0x00000000 - .word 0x10101000,0x1111111E,0x0000001E,0x00000000,0x00000000,0x011F110E,0x0000001E,0x00000000 - .word 0x02020C00,0x0202020F,0x00000002,0x00000000,0x00000000,0x101E111E,0x0000000E,0x00000000 - .word 0x01010100,0x1111110F,0x00000011,0x00000000,0x00000200,0x02020202,0x00000002,0x00000000 - .word 0x00000800,0x09090808,0x00000006,0x00000000,0x01010100,0x05030509,0x00000009,0x00000000 - - .word 0x04040600,0x04040404,0x00000004,0x00000000,0x00000000,0x1515150F,0x00000015,0x00000000 - .word 0x00000000,0x09090907,0x00000009,0x00000000,0x00000000,0x1111110E,0x0000000E,0x00000000 - .word 0x00000000,0x0F11110F,0x00000001,0x00000000,0x00000000,0x1E11111E,0x00000010,0x00000000 - .word 0x00000000,0x0101030D,0x00000001,0x00000000,0x00000000,0x0806010F,0x0000000F,0x00000000 - .word 0x02020000,0x0202020F,0x0000000E,0x00000000,0x00000000,0x09090909,0x00000016,0x00000000 - .word 0x00000000,0x0A0A1111,0x00000004,0x00000000,0x00000000,0x15151515,0x0000000A,0x00000000 - .word 0x00000000,0x0A040A11,0x00000011,0x00000000,0x00000000,0x101E1111,0x0000000F,0x00000000 - .word 0x00000000,0x0204081F,0x0000001F,0x00000000,0x1E0E0602,0x060E1E3E,0x00000002,0x00000000 - - .word 0x06060000,0x06060000,0x00000000,0x00000000,0x0E000011,0x111F1111,0x00000011,0x00000000 - .word 0x0E000011,0x11111111,0x0000000E,0x00000000,0x11000011,0x11111111,0x0000000E,0x00000000 - .word 0x00001100,0x1911111E,0x00000016,0x00000000,0x00001100,0x1111110E,0x0000000E,0x00000000 - .word 0x00001100,0x09090909,0x00000016,0x00000000,0x3F3F3E3C,0x0603392F,0x0000003C,0x00000000 - .word 0x07070301,0x03060407,0x00000001,0x00000000,0x10020702,0x0E041038,0x00000004,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - .word 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 - -@}}BLOCK(latin_short) diff --git a/source/main.cpp b/source/main.cpp index c86d003..9c69ab7 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -147,7 +147,7 @@ void game_load_error(void) u8 general_text_table_buffer[2048]; text_data_table general_text(general_text_table_buffer); - general_text.decompress(get_compressed_general_table()); + general_text.decompress(get_compressed_text_table(GENERAL_INDEX)); ptgb_write(general_text.get_text_entry(GENERAL_cart_load_error), true); } @@ -189,7 +189,7 @@ void first_load_message(void) u8 general_text_table_buffer[2048]; text_data_table general_text(general_text_table_buffer); - general_text.decompress(get_compressed_general_table()); + general_text.decompress(get_compressed_text_table(GENERAL_INDEX)); ptgb_write(general_text.get_text_entry(GENERAL_intro_first), true); } @@ -206,7 +206,7 @@ int credits() text_data_table credits_text_table(text_decompression_buffer); int curr_credits_num = 0; - credits_text_table.decompress(get_compressed_credits_table()); + credits_text_table.decompress(get_compressed_text_table(CREDITS_INDEX)); bool update = true; global_next_frame(); @@ -214,7 +214,7 @@ int credits() { if (update) { - create_textbox(4, 1, 160, 80, true); + create_textbox(1, 1, 200, 120, true); show_text_box(); ptgb_write(credits_text_table.get_text_entry(curr_credits_num), true); update = false; @@ -296,7 +296,7 @@ int credits() ptgb_write_debug(charset, hexBuffer, true); ptgb_write_debug(charset, "\n", true); - ptgb_write_debug(charset, VERSION, true); + ptgb_write_debug(charset, BUILD_INFO, true); if (get_treecko_enabled()) { ptgb_write_debug(charset, ".T", true); @@ -317,19 +317,25 @@ int credits() } }; -#define NUM_MENU_OPTIONS 3 - int main_menu_loop() { +#if ENABLE_TEXT_DEBUG_SCREEN +#define NUM_MENU_OPTIONS 4 + const uint8_t menu_options[NUM_MENU_OPTIONS] = {GENERAL_option_transfer, GENERAL_option_dreamdex, GENERAL_option_credits, GENERAL_option_text_debug}; + int return_values[NUM_MENU_OPTIONS] = {BTN_TRANSFER, BTN_POKEDEX, BTN_CREDITS, BTN_TEXT_DEBUG}; +#else +#define NUM_MENU_OPTIONS 3 + const uint8_t menu_options[NUM_MENU_OPTIONS] = {GENERAL_option_transfer, GENERAL_option_dreamdex, GENERAL_option_credits}; + int return_values[NUM_MENU_OPTIONS] = {BTN_TRANSFER, BTN_POKEDEX, BTN_CREDITS}; +#endif + uint8_t general_text_table_buffer[2048]; text_data_table general_text(general_text_table_buffer); bool update = true; - const uint8_t menu_options[NUM_MENU_OPTIONS] = {GENERAL_option_transfer, GENERAL_option_dreamdex, GENERAL_option_credits}; const uint8_t *text_entry; - int return_values[NUM_MENU_OPTIONS] = {BTN_TRANSFER, BTN_POKEDEX, BTN_CREDITS}; u16 test = 0; - general_text.decompress(get_compressed_general_table()); + general_text.decompress(get_compressed_text_table(GENERAL_INDEX)); while (true) { @@ -339,10 +345,9 @@ int main_menu_loop() for (int i = 0; i < NUM_MENU_OPTIONS; i++) { text_entry = general_text.get_text_entry(menu_options[i]); - int size = get_string_length(text_entry); - int char_width = (PTGB_BUILD_LANGUAGE == JPN_ID ? 8 : 6); - int x = ((240 - (size * char_width)) / 2); - tte_set_pos(x, ((i * 17) + 80)); + int string_length = get_string_length(text_entry); + int x = ((240 - string_length) / 2); + tte_set_pos(x, ((i * (16 + 10)) + 70)); if (i == curr_selection) { tte_set_ink(INK_WHITE); @@ -380,11 +385,11 @@ int main_menu_loop() } } -// Legal mumbo jumbo -static void show_legal_text(const u8* intro_text) +// Legal stuff +static void show_legal_text(const u8 *intro_text) { - tte_set_margins(8, 8, H_MAX - 8, V_MAX - 8); - tte_set_pos(8, 8); + tte_set_margins(4, 0, H_MAX - 4, V_MAX); + tte_set_pos(4, 0); tte_set_ink(INK_ROM_COLOR); ptgb_write(intro_text, true); bool wait = true; @@ -429,10 +434,10 @@ static void __attribute__((noinline)) show_intro() text_data_table general_text(general_text_table_buffer); const u8 *text_entry; - general_text.decompress(get_compressed_general_table()); + general_text.decompress(get_compressed_text_table(GENERAL_INDEX)); text_entry = general_text.get_text_entry(GENERAL_press_start); - press_start_text_length = get_string_length(text_entry); + press_start_text_length = get_string_char_count(text_entry); memcpy(press_start_text, text_entry, press_start_text_length + 1); text_entry = general_text.get_text_entry(GENERAL_intro_legal); @@ -442,7 +447,7 @@ static void __attribute__((noinline)) show_intro() REG_BG1CNT = REG_BG1CNT | BG_PRIO(3); key_poll(); // Reset the keys - curr_GBA_rom.load_rom(); + curr_GBA_rom.load_rom(false); obj_set_pos(ptgb_logo_l, 56, 12); obj_set_pos(ptgb_logo_r, 56 + 64, 12); @@ -464,7 +469,7 @@ static void __attribute__((noinline)) show_intro() global_next_frame(); start_pressed = key_hit(KEY_START) | key_hit(KEY_A); REG_BLDALPHA = BLDA_BUILD(0b10000, fade); - }; + } } int main(void) @@ -488,12 +493,20 @@ int main(void) REG_BLDALPHA = BLDA_BUILD(0b10000, 0); // Reset fade // Check if the game has been loaded correctly. - while (!curr_GBA_rom.load_rom()) + bool debug = false; + while (!curr_GBA_rom.load_rom(debug)) { - obj_hide_multi(ptgb_logo_l, 2); - global_next_frame(); - game_load_error(); - // initalization_script(); + if (IGNORE_GAME_PAK) + { + debug = true; + } + else + { + obj_hide_multi(ptgb_logo_l, 2); + global_next_frame(); + game_load_error(); + // initalization_script(); + } } // Initalize memory and save data after loading the game @@ -535,7 +548,7 @@ int main(void) tte_set_ink(INK_DARK_GREY); obj_hide_multi(ptgb_logo_l, 2); load_flex_background(BG_FENNEL, 3); - text_loop(BTN_TRANSFER); + text_loop(SCRIPT_TRANSFER); break; case (BTN_POKEDEX): if (get_tutorial_flag()) @@ -560,7 +573,13 @@ int main(void) break; case (BTN_EVENTS): obj_hide_multi(ptgb_logo_l, 2); - text_loop(BTN_EVENTS); + text_loop(SCRIPT_EVENT); + break; + case (BTN_TEXT_DEBUG): + tte_set_ink(INK_DARK_GREY); + REG_BG1CNT = (REG_BG1CNT & ~BG_PRIO_MASK) | BG_PRIO(3); + obj_hide_multi(ptgb_logo_l, 2); + text_loop(SCRIPT_DEBUG); break; default: global_next_frame(); diff --git a/source/multiboot_upload.cpp b/source/multiboot_upload.cpp index 9f6e133..a4b5ab9 100644 --- a/source/multiboot_upload.cpp +++ b/source/multiboot_upload.cpp @@ -19,7 +19,7 @@ void multiboot_upload_screen() text_data_table general_text(general_text_table_buffer); LinkCableMultiboot linkCableMultiboot; - general_text.decompress(get_compressed_general_table()); + general_text.decompress(get_compressed_text_table(GENERAL_INDEX)); multiboot_show_textbox(); ptgb_write(general_text.get_text_entry(GENERAL_send_multiboot_instructions), true); diff --git a/source/mystery_gift_builder.cpp b/source/mystery_gift_builder.cpp index 7e88000..978500c 100644 --- a/source/mystery_gift_builder.cpp +++ b/source/mystery_gift_builder.cpp @@ -379,7 +379,7 @@ void mystery_gift_script::build_script(PokeBox *box) // this decompresses the ZX0 compressed text table into the buffer inside of the decompressed_store union // thereby reusing the stack (=IWRAM) memory used earlier for the PokemonTables instance we used above - decompressed_text_table.decompress(get_compressed_rsefrlg_table()); + decompressed_text_table.decompress(get_compressed_text_table(RSEFRLG_INDEX)); switch (curr_GBA_rom.gamecode) { case RUBY_ID: diff --git a/source/pokedex.cpp b/source/pokedex.cpp index 97a6ec4..fa65e60 100644 --- a/source/pokedex.cpp +++ b/source/pokedex.cpp @@ -41,7 +41,7 @@ static void load_text_entry_into_buffer(text_data_table& data_table, u8 *output_ static void load_general_table_text_entries(u8 *decompression_buffer, u8 *kanto_buffer, u8 *johto_buffer) { text_data_table data_table(decompression_buffer); - data_table.decompress(get_compressed_general_table()); + data_table.decompress(get_compressed_text_table(GENERAL_INDEX)); load_text_entry_into_buffer(data_table, kanto_buffer, GENERAL_kanto_name); load_text_entry_into_buffer(data_table, johto_buffer, GENERAL_johto_name); @@ -105,7 +105,7 @@ int pokedex_loop() load_general_table_text_entries(decompression_buffer, kanto_name, johto_name); text_data_table PKMN_NAMES(decompression_buffer); - PKMN_NAMES.decompress(get_compressed_pkmn_names_table()); + PKMN_NAMES.decompress(get_compressed_text_table(PKMN_NAMES_INDEX)); pokedex_init(); pokedex_show(); @@ -116,7 +116,7 @@ int pokedex_loop() // TODO: For some reason there is screen tearing here. Probably not noticable on console, // but it should be removed at some point - tte_set_pos(8, 148); + tte_set_pos(8, 146); ptgb_write(kanto_name, true); convert_int_to_ptgb_str(kanto_dex_num, temp_string, 3); ptgb_write(temp_string, true); @@ -126,7 +126,7 @@ int pokedex_loop() convert_int_to_ptgb_str(mew_caught ? 151 : 150, temp_string, 3); ptgb_write(temp_string, true); - tte_set_pos(128, 148); + tte_set_pos(128, 146); ptgb_write(johto_name, true); convert_int_to_ptgb_str(johto_dex_num, temp_string, 3); ptgb_write(temp_string, true); @@ -216,18 +216,17 @@ int pokedex_loop() if (is_caught(dex_shift + i + 1 + mythic_skip)) { - tte_set_pos(dex_x_cord + (3 * 8 / 2), (i * 8 * 2) + 32); + tte_set_pos(dex_x_cord + (3 * 8 / 2), (i * 8 * 2) + 28); temp_string[0] = 0xF7; - temp_string[1] = 0xF8; - temp_string[2] = 0xFF; + temp_string[1] = 0xFF; ptgb_write(temp_string, true); } - tte_set_pos(dex_x_cord + (3 * 8), (i * 8 * 2) + 32); + tte_set_pos(dex_x_cord + (3 * 8), (i * 8 * 2) + 28); convert_int_to_ptgb_str(dex_shift + i + 1 + mythic_skip, temp_string, 3); ptgb_write(temp_string, true); - tte_set_pos(dex_x_cord + (7 * 8), (i * 8 * 2) + 32); + tte_set_pos(dex_x_cord + (7 * 8), (i * 8 * 2) + 28); ptgb_write(is_caught(dex_shift + i + 1 + mythic_skip) ? PKMN_NAMES.get_text_entry(dex_shift + i + 1 + mythic_skip) : undiscovered_text, true); } diff --git a/source/rom_data.cpp b/source/rom_data.cpp index ceceb81..8788373 100644 --- a/source/rom_data.cpp +++ b/source/rom_data.cpp @@ -16,14 +16,14 @@ extern rom_data curr_GBA_rom; rom_data::rom_data() {} -bool rom_data::load_rom() +bool rom_data::load_rom(bool debug) { u8 rom_list_buffer[2048]; u32 rom_list_size; const u8 *compressed_rom_list; const u8 *cur; - if (IGNORE_GAME_PAK) + if (debug) { gamecode = DEBUG_GAME; version = DEBUG_VERS; diff --git a/source/script_array.cpp b/source/script_array.cpp index f6ddcb6..f351a47 100644 --- a/source/script_array.cpp +++ b/source/script_array.cpp @@ -26,75 +26,75 @@ Box_Menu box_viewer; // Check that the conditions are set for the transfer // T_SCRIPT_START // COND_TUTORIAL_COMPLETE -// DIA_OPEN +// PTGB_DIA_OPEN // CMD_SET_TUTOR_TRUE // COND_BEAT_E4 -// DIA_E4 +// PTGB_DIA_E4 // COND_MG_ENABLED // COND_IS_FRLGE -// DIA_MG_FRLGE -// DIA_MG_RS +// PTGB_DIA_MG_FRLGE +// PTGB_DIA_MG_RS // COND_MG_OTHER_EVENT // COND_PKMN_TO_COLLECT -// DIA_MG_OTHER_EVENT -// DIA_PKMN_TO_COLLECT +// PTGB_DIA_MG_OTHER_EVENT +// PTGB_DIA_PKMN_TO_COLLECT // // Ask the user what game and language they're using -// DIA_WHAT_GAME_TRANS +// PTGB_DIA_WHAT_GAME_TRANS // CMD_GAME_MENU -// DIA_WHAT_LANG_TRANS +// PTGB_DIA_WHAT_LANG_TRANS // CMD_LANG_MENU -// DIA_ASK_QUEST +// PTGB_DIA_ASK_QUEST // CMD_SLIDE_PROF_LEFT // CMD_SLIDE_PROF_RIGHT // COND_GB_ROM_EXISTS -// DIA_NO_GB_ROM -// DIA_MENU_BACK +// PTGB_DIA_NO_GB_ROM +// PTGB_DIA_MENU_BACK // // Initiate the transfer and check for errors -// DIA_LETS_START -// DIA_START +// PTGB_DIA_LETS_START +// PTGB_DIA_START // CMD_START_LINK // COND_ERROR_TIMEOUT_ONE -// DIA_ERROR_TIME_ONE +// PTGB_DIA_ERROR_TIME_ONE // COND_ERROR_TIMEOUT_TWO -// DIA_ERROR_TIME_TWO +// PTGB_DIA_ERROR_TIME_TWO // COND_ERROR_COM_ENDED -// DIA_ERROR_COM_ENDED +// PTGB_DIA_ERROR_COM_ENDED // COND_ERROR_COLOSSEUM -// DIA_ERROR_COLOSSEUM +// PTGB_DIA_ERROR_COLOSSEUM // COND_ERROR_DISCONNECT -// DIA_ERROR_DISCONNECT +// PTGB_DIA_ERROR_DISCONNECT // // Pause the transfer and show the user their box data // CMD_IS_A_VALID_PKMN -// DIA_NO_VALID_PKMN +// PTGB_DIA_NO_VALID_PKMN // COND_SOME_INVALID_PKMN -// DIA_SOME_INVALID_PKMN +// PTGB_DIA_SOME_INVALID_PKMN // COND_CHECK_MYTHIC -// DIA_MYTHIC_CONVERT +// PTGB_DIA_MYTHIC_CONVERT // CMD_MYTHIC_MENU // COND_CHECK_MISSINGNO -// DIA_IS_MISSINGNO -// DIA_IN_BOX +// PTGB_DIA_IS_MISSINGNO +// PTGB_DIA_IN_BOX // CMD_BOX_MENU -// DIA_CANCEL +// PTGB_DIA_CANCEL // CMD_IMPORT_POKEMON // CMD_CONTINUE_LINK // CMD_CANCEL_LINK // CMD_END_MISSINGNO // // Complete the transfer and give messages based on the transfered Pokemon -// DIA_TRANS_GOOD +// PTGB_DIA_TRANS_GOOD // COND_NEW_POKEMON -// DIA_NEW_DEX -// DIA_NO_NEW_DEX +// PTGB_DIA_NEW_DEX +// PTGB_DIA_NO_NEW_DEX // COND_IS_HOENN_RS // COND_IS_HOENN_E -// DIA_SEND_FRIEND_HOENN_RS -// DIA_SEND_FRIEND_HOENN_E -// DIA_SEND_FRIEND_KANTO -// DIA_THANK +// PTGB_DIA_SEND_FRIEND_HOENN_RS +// PTGB_DIA_SEND_FRIEND_HOENN_E +// PTGB_DIA_SEND_FRIEND_KANTO +// PTGB_DIA_THANK // // Hide the dialogue and professor // CMD_END_SCRIPT @@ -104,184 +104,184 @@ Box_Menu box_viewer; // So if adding a new dia, command or condition, make sure to add it in the right position/index. // defining it this way does not generate an expensive function. It's all stored as read-only data in EWRAM. const script_obj_params transfer_script_params[SCRIPT_SIZE] = { - // DIA_OPEN + // PTGB_DIA_OPEN { - .text_entry_index = DIA_OPEN, + .text_entry_index = PTGB_DIA_OPEN, .next_if_true = CMD_SET_TUTOR_TRUE }, - // DIA_E4 + // PTGB_DIA_E4 { - .text_entry_index = DIA_E4, + .text_entry_index = PTGB_DIA_E4, .next_if_true = CMD_END_SCRIPT }, - // DIA_MG_FRLGE + // PTGB_DIA_MG_FRLGE { - .text_entry_index = DIA_MG_FRLGE, + .text_entry_index = PTGB_DIA_MG_FRLGE, .next_if_true = CMD_END_SCRIPT }, - // DIA_MG_RS + // PTGB_DIA_MG_RS { - .text_entry_index = DIA_MG_RS, + .text_entry_index = PTGB_DIA_MG_RS, .next_if_true = CMD_END_SCRIPT }, - // DIA_LETS_START + // PTGB_DIA_LETS_START { - .text_entry_index = DIA_LETS_START, - .next_if_true = DIA_START + .text_entry_index = PTGB_DIA_LETS_START, + .next_if_true = PTGB_DIA_START }, - // DIA_START + // PTGB_DIA_START { - .text_entry_index = DIA_START, + .text_entry_index = PTGB_DIA_START, .next_if_true = CMD_START_LINK }, - // DIA_TRANS_GOOD + // PTGB_DIA_TRANS_GOOD { - .text_entry_index = DIA_TRANS_GOOD, + .text_entry_index = PTGB_DIA_TRANS_GOOD, .next_if_true = COND_NEW_POKEMON }, - // DIA_NEW_DEX + // PTGB_DIA_NEW_DEX { - .text_entry_index = DIA_NEW_DEX, + .text_entry_index = PTGB_DIA_NEW_DEX, .next_if_true = COND_IS_HOENN_RS }, - // DIA_NO_NEW_DEX + // PTGB_DIA_NO_NEW_DEX { - .text_entry_index = DIA_NO_NEW_DEX, + .text_entry_index = PTGB_DIA_NO_NEW_DEX, .next_if_true = COND_IS_HOENN_RS }, - // DIA_SEND_FRIEND_KANTO + // PTGB_DIA_SEND_FRIEND_KANTO { - .text_entry_index = DIA_SEND_FRIEND_KANTO, - .next_if_true = DIA_THANK + .text_entry_index = PTGB_DIA_SEND_FRIEND_KANTO, + .next_if_true = PTGB_DIA_THANK }, - // DIA_SEND_FRIEND_HOENN_RS + // PTGB_DIA_SEND_FRIEND_HOENN_RS { - .text_entry_index = DIA_SEND_FRIEND_HOENN_RS, - .next_if_true = DIA_THANK + .text_entry_index = PTGB_DIA_SEND_FRIEND_HOENN_RS, + .next_if_true = PTGB_DIA_THANK }, - // DIA_SEND_FRIEND_HOENN_E + // PTGB_DIA_SEND_FRIEND_HOENN_E { - .text_entry_index = DIA_SEND_FRIEND_HOENN_E, - .next_if_true = DIA_THANK + .text_entry_index = PTGB_DIA_SEND_FRIEND_HOENN_E, + .next_if_true = PTGB_DIA_THANK }, - // DIA_THANK + // PTGB_DIA_THANK { - .text_entry_index = DIA_THANK, + .text_entry_index = PTGB_DIA_THANK, .next_if_true = CMD_END_SCRIPT }, - // DIA_GET_MON (unused) + // PTGB_DIA_GET_MON (unused) { - .text_entry_index = DIA_GET_MON, + .text_entry_index = PTGB_DIA_GET_MON, .next_if_true = CMD_END_SCRIPT }, - // DIA_MG_OTHER_EVENT + // PTGB_DIA_MG_OTHER_EVENT { - .text_entry_index = DIA_MG_OTHER_EVENT, - .next_if_true = DIA_ASK_QUEST + .text_entry_index = PTGB_DIA_MG_OTHER_EVENT, + .next_if_true = PTGB_DIA_ASK_QUEST }, - // DIA_PKMN_TO_COLLECT + // PTGB_DIA_PKMN_TO_COLLECT { - .text_entry_index = DIA_PKMN_TO_COLLECT, + .text_entry_index = PTGB_DIA_PKMN_TO_COLLECT, .next_if_true = CMD_END_SCRIPT }, - // DIA_NO_VALID_PKMN + // PTGB_DIA_NO_VALID_PKMN { - .text_entry_index = DIA_NO_VALID_PKMN, + .text_entry_index = PTGB_DIA_NO_VALID_PKMN, .next_if_true = CMD_CANCEL_LINK }, - // DIA_ASK_QUEST + // PTGB_DIA_ASK_QUEST { - .text_entry_index = DIA_ASK_QUEST, + .text_entry_index = PTGB_DIA_ASK_QUEST, .next_if_true = CMD_SLIDE_PROF_LEFT }, - // DIA_WHAT_GAME_TRANS + // PTGB_DIA_WHAT_GAME_TRANS { - .text_entry_index = DIA_WHAT_GAME_TRANS, + .text_entry_index = PTGB_DIA_WHAT_GAME_TRANS, .next_if_true = CMD_GAME_MENU }, - // DIA_WHAT_LANG_TRANS + // PTGB_DIA_WHAT_LANG_TRANS { - .text_entry_index = DIA_WHAT_LANG_TRANS, + .text_entry_index = PTGB_DIA_WHAT_LANG_TRANS, .next_if_true = CMD_LANG_MENU }, - // DIA_NO_GB_ROM + // PTGB_DIA_NO_GB_ROM { - .text_entry_index = DIA_NO_GB_ROM, - .next_if_true = DIA_WHAT_LANG_TRANS + .text_entry_index = PTGB_DIA_NO_GB_ROM, + .next_if_true = PTGB_DIA_WHAT_LANG_TRANS }, - // DIA_IN_BOX + // PTGB_DIA_IN_BOX { - .text_entry_index = DIA_IN_BOX, + .text_entry_index = PTGB_DIA_IN_BOX, .next_if_true = CMD_BOX_MENU }, - // DIA_MYTHIC_CONVERT + // PTGB_DIA_MYTHIC_CONVERT { - .text_entry_index = DIA_MYTHIC_CONVERT, + .text_entry_index = PTGB_DIA_MYTHIC_CONVERT, .next_if_true = CMD_MYTHIC_MENU }, - // DIA_CANCEL + // PTGB_DIA_CANCEL { - .text_entry_index = DIA_CANCEL, + .text_entry_index = PTGB_DIA_CANCEL, .next_if_true = CMD_CANCEL_LINK }, - // DIA_SOME_INVALID_PKMN + // PTGB_DIA_SOME_INVALID_PKMN { - .text_entry_index = DIA_SOME_INVALID_PKMN, + .text_entry_index = PTGB_DIA_SOME_INVALID_PKMN, .next_if_true = COND_CHECK_MYTHIC }, - // DIA_MENU_BACK + // PTGB_DIA_MENU_BACK { - .text_entry_index = DIA_MENU_BACK, + .text_entry_index = PTGB_DIA_MENU_BACK, .next_if_true = CMD_END_SCRIPT }, - // DIA_IS_MISSINGNO + // PTGB_DIA_IS_MISSINGNO { - .text_entry_index = DIA_IS_MISSINGNO, - .next_if_true = DIA_IN_BOX + .text_entry_index = PTGB_DIA_IS_MISSINGNO, + .next_if_true = PTGB_DIA_IN_BOX }, - // DIA_ERROR_COLOSSEUM + // PTGB_DIA_ERROR_COLOSSEUM { - .text_entry_index = DIA_ERROR_COLOSSEUM, - .next_if_true = DIA_START + .text_entry_index = PTGB_DIA_ERROR_COLOSSEUM, + .next_if_true = PTGB_DIA_START }, - // DIA_ERROR_COM_ENDED + // PTGB_DIA_ERROR_COM_ENDED { - .text_entry_index = DIA_ERROR_COM_ENDED, - .next_if_true = DIA_START + .text_entry_index = PTGB_DIA_ERROR_COM_ENDED, + .next_if_true = PTGB_DIA_START }, - // DIA_ERROR_DISCONNECT + // PTGB_DIA_ERROR_DISCONNECT { - .text_entry_index = DIA_ERROR_DISCONNECT, - .next_if_true = DIA_START + .text_entry_index = PTGB_DIA_ERROR_DISCONNECT, + .next_if_true = PTGB_DIA_START }, - // DIA_ERROR_TIME_ONE + // PTGB_DIA_ERROR_TIME_ONE { - .text_entry_index = DIA_ERROR_TIME_ONE, - .next_if_true = DIA_START + .text_entry_index = PTGB_DIA_ERROR_TIME_ONE, + .next_if_true = PTGB_DIA_START }, - // DIA_ERROR_TIME_TWO + // PTGB_DIA_ERROR_TIME_TWO { - .text_entry_index = DIA_ERROR_TIME_TWO, - .next_if_true = DIA_START + .text_entry_index = PTGB_DIA_ERROR_TIME_TWO, + .next_if_true = PTGB_DIA_START }, - // DIA_WHAT_LANG_EVENT + // PTGB_DIA_WHAT_LANG_EVENT { - .text_entry_index = DIA_WHAT_LANG_EVENT, + .text_entry_index = PTGB_DIA_WHAT_LANG_EVENT, .next_if_true = CMD_LANG_MENU }, - // DIA_WHAT_GAME_EVENT + // PTGB_DIA_WHAT_GAME_EVENT { - .text_entry_index = DIA_WHAT_GAME_EVENT, + .text_entry_index = PTGB_DIA_WHAT_GAME_EVENT, .next_if_true = CMD_GAME_MENU }, - // DIA_K_DEX_NOT_FULL + // PTGB_DIA_K_DEX_NOT_FULL { - .text_entry_index = DIA_K_DEX_NOT_FULL, + .text_entry_index = PTGB_DIA_K_DEX_NOT_FULL, .next_if_true = CMD_END_SCRIPT }, - // DIA_J_DEX_NOT_FULL + // PTGB_DIA_J_DEX_NOT_FULL { - .text_entry_index = DIA_J_DEX_NOT_FULL, + .text_entry_index = PTGB_DIA_J_DEX_NOT_FULL, .next_if_true = CMD_END_SCRIPT }, // T_SCRIPT_START @@ -292,7 +292,7 @@ const script_obj_params transfer_script_params[SCRIPT_SIZE] = { // E_SCRIPT_START { .conditional_index = CMD_SHOW_PROF, - .next_if_true = DIA_ASK_QUEST + .next_if_true = PTGB_DIA_ASK_QUEST }, // CMD_START_LINK { @@ -330,23 +330,23 @@ const script_obj_params transfer_script_params[SCRIPT_SIZE] = { { .conditional_index = CMD_GAME_MENU, .next_if_true = COND_GB_ROM_EXISTS, - .next_if_false = DIA_WHAT_LANG_TRANS + .next_if_false = PTGB_DIA_WHAT_LANG_TRANS }, // CMD_LANG_MENU { .conditional_index = CMD_LANG_MENU, - .next_if_true = DIA_WHAT_GAME_TRANS, - .next_if_false = DIA_CANCEL + .next_if_true = PTGB_DIA_WHAT_GAME_TRANS, + .next_if_false = PTGB_DIA_CANCEL }, // CMD_SLIDE_PROF_LEFT { .conditional_index = CMD_SLIDE_PROF_LEFT, - .next_if_true = DIA_WHAT_LANG_TRANS + .next_if_true = PTGB_DIA_WHAT_LANG_TRANS }, // CMD_SLIDE_PROF_RIGHT { .conditional_index = CMD_SLIDE_PROF_RIGHT, - .next_if_true = DIA_LETS_START + .next_if_true = PTGB_DIA_LETS_START }, // CMD_CONTINUE_LINK { @@ -357,7 +357,7 @@ const script_obj_params transfer_script_params[SCRIPT_SIZE] = { { .conditional_index = CMD_BOX_MENU, .next_if_true = CMD_IMPORT_POKEMON, - .next_if_false = DIA_CANCEL + .next_if_false = PTGB_DIA_CANCEL }, // CMD_MYTHIC_MENU { @@ -368,7 +368,7 @@ const script_obj_params transfer_script_params[SCRIPT_SIZE] = { { .conditional_index = CMD_IS_A_VALID_PKMN, .next_if_true = COND_SOME_INVALID_PKMN, - .next_if_false = DIA_NO_VALID_PKMN + .next_if_false = PTGB_DIA_NO_VALID_PKMN }, // CMD_CANCEL_LINK { @@ -378,43 +378,43 @@ const script_obj_params transfer_script_params[SCRIPT_SIZE] = { // CMD_END_MISSINGNO { .conditional_index = CMD_END_MISSINGNO, - .next_if_true = DIA_TRANS_GOOD + .next_if_true = PTGB_DIA_TRANS_GOOD }, // COND_ERROR_TIMEOUT_ONE { .conditional_index = COND_ERROR_TIMEOUT_ONE, .next_if_true = COND_ERROR_TIMEOUT_TWO, - .next_if_false = DIA_ERROR_TIME_ONE + .next_if_false = PTGB_DIA_ERROR_TIME_ONE }, // COND_ERROR_DISCONNECT { .conditional_index = COND_ERROR_DISCONNECT, .next_if_true = CMD_IS_A_VALID_PKMN, - .next_if_false = DIA_ERROR_DISCONNECT + .next_if_false = PTGB_DIA_ERROR_DISCONNECT }, // COND_ERROR_COM_ENDED { .conditional_index = COND_ERROR_COM_ENDED, .next_if_true = COND_ERROR_COLOSSEUM, - .next_if_false = DIA_ERROR_COM_ENDED + .next_if_false = PTGB_DIA_ERROR_COM_ENDED }, // COND_ERROR_TIMEOUT_TWO { .conditional_index = COND_ERROR_TIMEOUT_TWO, .next_if_true = COND_ERROR_COM_ENDED, - .next_if_false = DIA_ERROR_TIME_TWO + .next_if_false = PTGB_DIA_ERROR_TIME_TWO }, // COND_ERROR_COLOSSEUM { .conditional_index = COND_ERROR_COLOSSEUM, .next_if_true = COND_ERROR_DISCONNECT, - .next_if_false = DIA_ERROR_COLOSSEUM + .next_if_false = PTGB_DIA_ERROR_COLOSSEUM }, // COND_BEAT_E4 { .conditional_index = COND_BEAT_E4, .next_if_true = COND_MG_ENABLED, - .next_if_false = DIA_E4 + .next_if_false = PTGB_DIA_E4 }, // COND_MG_ENABLED { @@ -426,48 +426,48 @@ const script_obj_params transfer_script_params[SCRIPT_SIZE] = { { .conditional_index = COND_TUTORIAL_COMPLETE, .next_if_true = COND_BEAT_E4, - .next_if_false = DIA_OPEN + .next_if_false = PTGB_DIA_OPEN }, // COND_NEW_POKEMON { .conditional_index = COND_NEW_POKEMON, - .next_if_true = DIA_NEW_DEX, - .next_if_false = DIA_NO_NEW_DEX + .next_if_true = PTGB_DIA_NEW_DEX, + .next_if_false = PTGB_DIA_NO_NEW_DEX }, // COND_IS_HOENN_RS { .conditional_index = COND_IS_HOENN_RS, - .next_if_true = DIA_SEND_FRIEND_HOENN_RS, + .next_if_true = PTGB_DIA_SEND_FRIEND_HOENN_RS, .next_if_false = COND_IS_HOENN_E }, // COND_IS_FRLGE { .conditional_index = COND_IS_FRLGE, - .next_if_true = DIA_MG_FRLGE, - .next_if_false = DIA_MG_RS + .next_if_true = PTGB_DIA_MG_FRLGE, + .next_if_false = PTGB_DIA_MG_RS }, // COND_MG_OTHER_EVENT { .conditional_index = COND_MG_OTHER_EVENT, - .next_if_true = DIA_MG_OTHER_EVENT, + .next_if_true = PTGB_DIA_MG_OTHER_EVENT, .next_if_false = COND_PKMN_TO_COLLECT }, // COND_PKMN_TO_COLLECT { .conditional_index = COND_PKMN_TO_COLLECT, - .next_if_true = DIA_PKMN_TO_COLLECT, - .next_if_false = DIA_ASK_QUEST + .next_if_true = PTGB_DIA_PKMN_TO_COLLECT, + .next_if_false = PTGB_DIA_ASK_QUEST }, // COND_GB_ROM_EXISTS { .conditional_index = COND_GB_ROM_EXISTS, .next_if_true = CMD_SLIDE_PROF_RIGHT, - .next_if_false = DIA_NO_GB_ROM + .next_if_false = PTGB_DIA_NO_GB_ROM }, // COND_CHECK_MYTHIC { .conditional_index = COND_CHECK_MYTHIC, - .next_if_true = DIA_MYTHIC_CONVERT, + .next_if_true = PTGB_DIA_MYTHIC_CONVERT, .next_if_false = COND_CHECK_MISSINGNO }, // COND_CHECK_DEX @@ -479,26 +479,26 @@ const script_obj_params transfer_script_params[SCRIPT_SIZE] = { // COND_CHECK_KANTO { .conditional_index = COND_CHECK_KANTO, - .next_if_true = DIA_K_DEX_NOT_FULL, - .next_if_false = DIA_J_DEX_NOT_FULL + .next_if_true = PTGB_DIA_K_DEX_NOT_FULL, + .next_if_false = PTGB_DIA_J_DEX_NOT_FULL }, // COND_SOME_INVALID_PKMN { .conditional_index = COND_SOME_INVALID_PKMN, - .next_if_true = DIA_SOME_INVALID_PKMN, + .next_if_true = PTGB_DIA_SOME_INVALID_PKMN, .next_if_false = COND_CHECK_MYTHIC }, // COND_IS_HOENN_E { .conditional_index = COND_IS_HOENN_E, - .next_if_true = DIA_SEND_FRIEND_HOENN_E, - .next_if_false = DIA_SEND_FRIEND_KANTO + .next_if_true = PTGB_DIA_SEND_FRIEND_HOENN_E, + .next_if_false = PTGB_DIA_SEND_FRIEND_KANTO }, // COND_CHECK_MISSINGNO { .conditional_index = COND_CHECK_MISSINGNO, - .next_if_true = DIA_IS_MISSINGNO, - .next_if_false = DIA_IN_BOX + .next_if_true = PTGB_DIA_IS_MISSINGNO, + .next_if_false = PTGB_DIA_IN_BOX } }; @@ -506,24 +506,24 @@ const script_obj_params transfer_script_params[SCRIPT_SIZE] = { // -------- EVENTS SCRIPT -------- // Start the dialogue and show the menu // E_SCRIPT_START -// DIA_ASK_QUEST +// PTGB_DIA_ASK_QUEST // // Ask the user what game and language they're using -// DIA_WHAT_GAME_EVENT +// PTGB_DIA_WHAT_GAME_EVENT // CMD_GAME_MENU -// DIA_WHAT_LANG_EVENT +// PTGB_DIA_WHAT_LANG_EVENT // CMD_LANG_MENU -// DIA_ASK_QUEST +// PTGB_DIA_ASK_QUEST // CMD_SLIDE_PROF_LEFT // CMD_SLIDE_PROF_RIGHT // COND_GB_ROM_EXISTS -// DIA_NO_GB_ROM +// PTGB_DIA_NO_GB_ROM // // Check the player's dex // COND_CHECK_DEX // COND_CHECK_KANTO -// DIA_K_DEX_NOT_FULL -// DIA_J_DEX_NOT_FULL +// PTGB_DIA_K_DEX_NOT_FULL +// PTGB_DIA_J_DEX_NOT_FULL // // Hide the dialogue and professor // CMD_END_SCRIPT @@ -535,71 +535,71 @@ const script_obj_params transfer_script_params[SCRIPT_SIZE] = { // defining it this way does not generate an expensive function. It's all stored as read-only data in EWRAM. // Although frankly given the small amount of defined entries, we ARE wasting a lot of space with this one. (probably around 500 bytes) const script_obj_params event_script_params[SCRIPT_SIZE] = { - {}, // DIA_OPEN - {}, // DIA_E4 - {}, // DIA_MG_FRLGE - {}, // DIA_MG_RS - {}, // DIA_LETS_START - {}, // DIA_START - {}, // DIA_TRANS_GOOD - {}, // DIA_NEW_DEX - {}, // DIA_NO_NEW_DEX - {}, // DIA_SEND_FRIEND_KANTO - {}, // DIA_SEND_FRIEND_HOENN_RS - {}, // DIA_SEND_FRIEND_HOENN_E - {}, // DIA_THANK - {}, // DIA_GET_MON - {}, // DIA_MG_OTHER_EVENT - {}, // DIA_PKMN_TO_COLLECT - {}, // DIA_NO_VALID_PKMN - // DIA_ASK_QUEST + {}, // PTGB_DIA_OPEN + {}, // PTGB_DIA_E4 + {}, // PTGB_DIA_MG_FRLGE + {}, // PTGB_DIA_MG_RS + {}, // PTGB_DIA_LETS_START + {}, // PTGB_DIA_START + {}, // PTGB_DIA_TRANS_GOOD + {}, // PTGB_DIA_NEW_DEX + {}, // PTGB_DIA_NO_NEW_DEX + {}, // PTGB_DIA_SEND_FRIEND_KANTO + {}, // PTGB_DIA_SEND_FRIEND_HOENN_RS + {}, // PTGB_DIA_SEND_FRIEND_HOENN_E + {}, // PTGB_DIA_THANK + {}, // PTGB_DIA_GET_MON + {}, // PTGB_DIA_MG_OTHER_EVENT + {}, // PTGB_DIA_PKMN_TO_COLLECT + {}, // PTGB_DIA_NO_VALID_PKMN + // PTGB_DIA_ASK_QUEST { - .text_entry_index = DIA_ASK_QUEST, + .text_entry_index = PTGB_DIA_ASK_QUEST, .next_if_true = CMD_SLIDE_PROF_LEFT }, - {}, // DIA_WHAT_GAME_TRANS - {}, // DIA_WHAT_LANG_TRANS - // DIA_NO_GB_ROM + {}, // PTGB_DIA_WHAT_GAME_TRANS + {}, // PTGB_DIA_WHAT_LANG_TRANS + // PTGB_DIA_NO_GB_ROM { - .text_entry_index = DIA_NO_GB_ROM, - .next_if_true = DIA_WHAT_LANG_EVENT + .text_entry_index = PTGB_DIA_NO_GB_ROM, + .next_if_true = PTGB_DIA_WHAT_LANG_EVENT }, - {}, // DIA_IN_BOX - {}, // DIA_MYTHIC_CONVERT - {}, // DIA_CANCEL - {}, // DIA_SOME_INVALID_PKMN - {}, // DIA_MENU_BACK - {}, // DIA_IS_MISSINGNO - {}, // DIA_ERROR_COLOSSEUM - {}, // DIA_ERROR_COM_ENDED - {}, // DIA_ERROR_DISCONNECT - {}, // DIA_ERROR_TIME_ONE - {}, // DIA_ERROR_TIME_TWO - // DIA_WHAT_LANG_EVENT + {}, // PTGB_DIA_IN_BOX + {}, // PTGB_DIA_MYTHIC_CONVERT + {}, // PTGB_DIA_CANCEL + {}, // PTGB_DIA_SOME_INVALID_PKMN + {}, // PTGB_DIA_MENU_BACK + {}, // PTGB_DIA_IS_MISSINGNO + {}, // PTGB_DIA_ERROR_COLOSSEUM + {}, // PTGB_DIA_ERROR_COM_ENDED + {}, // PTGB_DIA_ERROR_DISCONNECT + {}, // PTGB_DIA_ERROR_TIME_ONE + {}, // PTGB_DIA_ERROR_TIME_TWO + // PTGB_DIA_WHAT_LANG_EVENT { - .text_entry_index = DIA_WHAT_LANG_EVENT, + .text_entry_index = PTGB_DIA_WHAT_LANG_EVENT, .next_if_true = CMD_LANG_MENU }, - // DIA_WHAT_GAME_EVENT + // PTGB_DIA_WHAT_GAME_EVENT { - .text_entry_index = DIA_WHAT_GAME_EVENT, + .text_entry_index = PTGB_DIA_WHAT_GAME_EVENT, .next_if_true = CMD_GAME_MENU }, - // DIA_K_DEX_NOT_FULL + // PTGB_DIA_K_DEX_NOT_FULL { - .text_entry_index = DIA_K_DEX_NOT_FULL, + .text_entry_index = PTGB_DIA_K_DEX_NOT_FULL, .next_if_true = CMD_END_SCRIPT }, - // DIA_J_DEX_NOT_FULL + // PTGB_DIA_J_DEX_NOT_FULL { - .text_entry_index = DIA_J_DEX_NOT_FULL, + .text_entry_index = PTGB_DIA_J_DEX_NOT_FULL, .next_if_true = CMD_END_SCRIPT }, {}, // T_SCRIPT_START // E_SCRIPT_START { .conditional_index = CMD_SHOW_PROF, - .next_if_true = DIA_ASK_QUEST + .next_if_true = PTGB_DIA_ASK_QUEST }, {}, // CMD_START_LINK {}, // CMD_IMPORT_POKEMON @@ -620,17 +620,17 @@ const script_obj_params event_script_params[SCRIPT_SIZE] = { { .conditional_index = CMD_GAME_MENU, .next_if_true = COND_GB_ROM_EXISTS, - .next_if_false = DIA_WHAT_LANG_EVENT + .next_if_false = PTGB_DIA_WHAT_LANG_EVENT }, // CMD_LANG_MENU { .conditional_index = CMD_LANG_MENU, - .next_if_true = DIA_WHAT_GAME_EVENT + .next_if_true = PTGB_DIA_WHAT_GAME_EVENT }, // CMD_SLIDE_PROF_LEFT { .conditional_index = CMD_SLIDE_PROF_LEFT, - .next_if_true = DIA_WHAT_LANG_EVENT + .next_if_true = PTGB_DIA_WHAT_LANG_EVENT }, // CMD_SLIDE_PROF_RIGHT { @@ -660,7 +660,7 @@ const script_obj_params event_script_params[SCRIPT_SIZE] = { { .conditional_index = COND_GB_ROM_EXISTS, .next_if_true = CMD_SLIDE_PROF_RIGHT, - .next_if_false = DIA_NO_GB_ROM + .next_if_false = PTGB_DIA_NO_GB_ROM }, {}, // COND_CHECK_MYTHIC // COND_CHECK_DEX @@ -672,8 +672,8 @@ const script_obj_params event_script_params[SCRIPT_SIZE] = { // COND_CHECK_KANTO { .conditional_index = COND_CHECK_KANTO, - .next_if_true = DIA_K_DEX_NOT_FULL, - .next_if_false = DIA_J_DEX_NOT_FULL + .next_if_true = PTGB_DIA_K_DEX_NOT_FULL, + .next_if_false = PTGB_DIA_J_DEX_NOT_FULL }, {}, // COND_SOME_INVALID_PKMN {}, // COND_IS_HOENN_E diff --git a/source/script_var.cpp b/source/script_var.cpp index f33d73b..9dfbf27 100644 --- a/source/script_var.cpp +++ b/source/script_var.cpp @@ -140,7 +140,7 @@ u32 xse_var::get_loc_in_sec30() void textbox_var::set_text(const byte nText[]) { text = nText; - text_length = get_string_length(nText); + text_length = get_string_char_count(nText); } void textbox_var::set_start() diff --git a/source/select_menu.cpp b/source/select_menu.cpp index fd8ae1d..2f51ffe 100644 --- a/source/select_menu.cpp +++ b/source/select_menu.cpp @@ -106,7 +106,7 @@ void Select_Menu::show_menu() { u8 decompression_buffer[2048]; text_data_table text_data(decompression_buffer); - text_data.decompress(get_compressed_general_table()); + text_data.decompress(get_compressed_text_table(GENERAL_INDEX)); add_menu_box(menu_options.size(), startTileX, startTileY); for (unsigned int i = 0; i < menu_options.size(); i++) diff --git a/source/text_engine.cpp b/source/text_engine.cpp index 51d94be..65fe827 100644 --- a/source/text_engine.cpp +++ b/source/text_engine.cpp @@ -8,9 +8,9 @@ #include "debug_mode.h" #include "button_menu.h" #include "sprite_data.h" -#include "latin_short.h" -#include "japanese_small.h" +#include "fonts.h" #include "text_data_table.h" +#include "background_engine.h" #define TEXT_CBB 0 #define TEXT_SBB 10 @@ -28,14 +28,14 @@ bool text_exit; // Doing it this way does mean that we need to completely restart decompression whenever we switch from dialog entry. // but given that it requires user input to do so, I believe it's worth it and not time-critical. // attribute noinline was used to make sure the compiler doesn't inline this code back into text_loop() -static __attribute__((noinline)) const u8* read_dialogue_text_entry(uint8_t index, u8 *output_buffer) +static __attribute__((noinline)) const u8 *read_dialogue_text_entry(uint8_t index, u8 *output_buffer) { u8 text_decompression_buffer[6144]; const u8 *text_entry; text_data_table dialogue_table(text_decompression_buffer); - dialogue_table.decompress(get_compressed_PTGB_table()); + dialogue_table.decompress(get_compressed_text_table(PTGB_INDEX)); text_entry = dialogue_table.get_text_entry(index); memcpy(output_buffer, text_entry, dialogue_table.get_text_entry_size(index)); @@ -43,17 +43,41 @@ static __attribute__((noinline)) const u8* read_dialogue_text_entry(uint8_t inde return output_buffer; } +static __attribute__((noinline)) const u8 *read_dialogue_text_entry(uint8_t index, uint8_t text_section, u8 *output_buffer) +{ + u8 text_decompression_buffer[6144]; + const u8 *text_entry; + + text_data_table dialogue_table(text_decompression_buffer); + + dialogue_table.decompress(get_compressed_text_table(text_section)); + + text_entry = dialogue_table.get_text_entry(index); + memcpy(output_buffer, text_entry, dialogue_table.get_text_entry_size(index)); + + return output_buffer; +} + +// This will have to be changed to be dynamic to support nicknamed Pokemon that are in a different language than the current build. +// Maybe combine Japanese and Latin into one larger font? + +#if PTGB_BUILD_LANGUAGE == 1 +#define BUILD_FONT &japanese_normalFont +#else +#define BUILD_FONT &latin_normalFont +#endif + void init_text_engine() { // Load the TTE // tte_init_se(3, BG_CBB(TEXT_CBB) | BG_SBB(TEXT_SBB) | BG_PRIO(0), 0, CLR_WHITE, 14, &japanese_smallFont, NULL); - tte_init_chr4c(3, // BG 0 - BG_CBB(TEXT_CBB) | BG_SBB(TEXT_SBB), // Charblock 0; screenblock 31 + tte_init_chr4c(3, // BG 3 + BG_CBB(TEXT_CBB) | BG_SBB(TEXT_SBB), // Charblock 0; screenblock 10 0xF000, // Screen-entry offset bytes2word( // Color attributes: - 15, // Text color - 0, // Shadow color + 13, // Text color + 15, // Shadow color 0, // Paper 0), // Special CLR_WHITE, // White text @@ -82,51 +106,150 @@ int text_loop(int script) u8 diag_entry_text_buffer[1024]; switch (script) { - case BTN_TRANSFER: + case SCRIPT_DEBUG: + curr_line = transfer_script_params[0]; + break; + + case SCRIPT_TRANSFER: curr_line = transfer_script_params[T_SCRIPT_START]; break; - case BTN_EVENTS: + case SCRIPT_EVENT: curr_line = event_script_params[E_SCRIPT_START]; break; } curr_text = (curr_line.has_text()) ? read_dialogue_text_entry(curr_line.get_text_entry_index(), diag_entry_text_buffer) : NULL; - REG_BG1CNT = (REG_BG1CNT && !BG_PRIO_MASK) | BG_PRIO(2); // Show Fennel - show_text_box(); // tte_set_margins(LEFT, TOP, RIGHT, BOTTOM); - while (true) // This loops through all the connected script objects + if (script != SCRIPT_DEBUG) { - if (curr_text != NULL && curr_text[char_index] != 0xFF && curr_text[char_index] != 0xFB) + REG_BG1CNT = (REG_BG1CNT && !BG_PRIO_MASK) | BG_PRIO(2); // Show Fennel + show_text_box(); + while (true) // This loops through all the connected script objects { - tte_set_pos(LEFT, TOP); - tte_erase_rect(LEFT, TOP, RIGHT, BOTTOM); - ptgb_write(curr_text, char_index); + if (curr_text != NULL && curr_text[char_index] != 0xFF && curr_text[char_index] != 0xFB) + { + tte_set_pos(LEFT, TOP); + tte_erase_rect(LEFT, TOP, RIGHT, BOTTOM); + ptgb_write(curr_text, false); + } + + wait_for_user_to_continue(false); + + line_char_index = 0; + switch (script) + { + case BTN_TRANSFER: + curr_line = transfer_script_params[text_next_obj_id(curr_line)]; + break; + case BTN_EVENTS: + curr_line = event_script_params[text_next_obj_id(curr_line)]; + break; + } + + curr_text = (curr_line.has_text()) ? read_dialogue_text_entry(curr_line.get_text_entry_index(), diag_entry_text_buffer) : NULL; + char_index = 0; + + if (text_exit) + { + hide_text_box(); + tte_erase_rect(LEFT, TOP, RIGHT, BOTTOM); + text_exit = false; + return 0; + } } + } + else // Debug script loop + { + u16 debug_charset[256]; + load_localized_charset(debug_charset, 3, ENGLISH); - wait_for_user_to_continue(false); - - line_char_index = 0; - switch (script) + int text_section = 0; + int text_identifier = 0; + while (true) { - case BTN_TRANSFER: - curr_line = transfer_script_params[text_next_obj_id(curr_line)]; - break; - case BTN_EVENTS: - curr_line = event_script_params[text_next_obj_id(curr_line)]; - break; - } + bool exit = false; + bool update_text = true; + bool instant_text = false; + key_poll(); + while (!exit) + { + if (key_hit(KEY_LEFT)) + { + text_identifier = (text_identifier + (text_section_lengths[text_section] - 1)) % text_section_lengths[text_section]; + update_text = true; + } + else if (key_hit(KEY_RIGHT)) + { + text_identifier = (text_identifier + 1) % text_section_lengths[text_section]; + update_text = true; + } + else if (key_hit(KEY_UP)) + { + text_section = (text_section + 1) % NUM_TEXT_SECTIONS; + update_text = true; + } + else if (key_hit(KEY_DOWN)) + { + text_section = (text_section + (NUM_TEXT_SECTIONS - 1)) % NUM_TEXT_SECTIONS; + update_text = true; + } + else if (key_hit(KEY_START) || key_hit(KEY_SELECT)) + { + instant_text = key_hit(KEY_START); // instant with start, not with select + exit = true; + } + if (update_text) + { + if (text_identifier > text_section_lengths[text_section]) + { + text_identifier = text_section_lengths[text_section]; + } + if (text_section > NUM_TEXT_SECTIONS) + { + text_section = NUM_TEXT_SECTIONS; + } + tte_set_pos(0, 0); + tte_erase_rect(0, 0, 240, 160); + ptgb_write_debug(debug_charset, "(", true); + ptgb_write_debug(debug_charset, ptgb::to_string(text_section), true); + ptgb_write_debug(debug_charset, ", ", true); + ptgb_write_debug(debug_charset, ptgb::to_string(text_identifier), true); + ptgb_write_debug(debug_charset, ")", true); + update_text = false; + } + global_next_frame(); + } - curr_text = (curr_line.has_text()) ? read_dialogue_text_entry(curr_line.get_text_entry_index(), diag_entry_text_buffer) : NULL; - char_index = 0; + line_char_index = 0; + curr_text = read_dialogue_text_entry(text_identifier, text_section, diag_entry_text_buffer); + char_index = 0; - if (text_exit) - { + if (curr_text != NULL && curr_text[char_index] != 0xFF && curr_text[char_index] != 0xFB) + { + if (text_section == PTGB_INDEX) + { + reset_textbox(); + } + else + { + create_textbox(4, 1, 160, 80, true); + } + show_text_box(); + tte_erase_rect(0, 0, 240, 160); + ptgb_write(curr_text, instant_text); + } + + wait_for_user_to_continue(false); + update_text = true; hide_text_box(); - tte_erase_rect(LEFT, TOP, RIGHT, BOTTOM); - text_exit = false; - return 0; + + if (text_exit) + { + text_exit = false; + return 0; + } } } } @@ -184,15 +307,15 @@ int ptgb_write(const byte *text, bool instant, int length) TFont *font; int num = 0; -/* - if (curr_text[char_index] == 0xFB) // This will need to be moved - { - line_char_index += char_index; - line_char_index++; - // Low key kinda scuffed, but it works to split the string - curr_text = &curr_line.get_text()[line_char_index]; - } -*/ + /* + if (curr_text[char_index] == 0xFB) // This will need to be moved + { + line_char_index += char_index; + line_char_index++; + // Low key kinda scuffed, but it works to split the string + curr_text = &curr_line.get_text()[line_char_index]; + } + */ while ((ch = *str) != 0xFF && num < length) { if (get_frame_count() % 2 == 0 || key_held(KEY_B) || key_held(KEY_A) || instant) @@ -200,6 +323,16 @@ int ptgb_write(const byte *text, bool instant, int length) str++; switch (ch) { + case 0xFA: + if (DISPLAY_CONTROL_CHAR) + { + tc->drawgProc(0x79); + } + wait_for_user_to_continue(false); + scroll_text(instant, tc); + tc->cursorY += tc->font->charH; + tc->cursorX = tc->marginLeft; + break; case 0xFB: if (DISPLAY_CONTROL_CHAR) { @@ -207,6 +340,21 @@ int ptgb_write(const byte *text, bool instant, int length) } wait_for_user_to_continue(true); break; + case 0xFC: + ch = *str; + str++; + num += 1; + if (DISPLAY_CONTROL_CHAR) + { + for (uint i = 0; i < ch; i++){ + tc->drawgProc(0xB9); + } + } + else + { + tc->cursorX += tc->font->widths[0xFC] * ch; + } + break; case 0xFE: if (DISPLAY_CONTROL_CHAR) { @@ -253,7 +401,7 @@ int ptgb_write(const byte *text, bool instant, int length) return 0; // str - text; } // This is mostly used for debug stuff, I shouldn't rely it on it much. -int ptgb_write_debug(const u16* charset, const char *text, bool instant) +int ptgb_write_debug(const u16 *charset, const char *text, bool instant) { byte temp_holding[256]; int i; @@ -296,6 +444,7 @@ void wait_for_user_to_continue(bool clear_text) fennel_speak(0); } } + key_poll(); while (!(key_hit(KEY_A) || key_hit(KEY_B) || curr_text == NULL)) { global_next_frame(); @@ -305,4 +454,28 @@ void wait_for_user_to_continue(bool clear_text) tte_erase_rect(LEFT, TOP, RIGHT, BOTTOM); tte_set_pos(LEFT, TOP); } -} \ No newline at end of file +} + +void scroll_text(bool instant, TTC *tc) +{ + for (int i = 1; i <= tc->font->charH; i++) + { + REG_BG3VOFS = i; + tte_erase_rect(LEFT, TOP - tc->font->charH, RIGHT, TOP + i); + if (!instant) + { + global_next_frame(); + } + } + REG_BG3VOFS = 0; + + // The map starts at tile 0 in the top left, increases by 1 as you go down, and then loops back at the top. + for (int i = 0; i < 30; i++) + { + tonccpy(&tile_mem[TEXT_CBB][14 + (i * 20)], &tile_mem[TEXT_CBB][16 + (i * 20)], 2 * 2 * 32); + } + + // Remove text that went outside of the box and set the position + tte_erase_rect(LEFT, TOP + tc->font->charH, RIGHT, BOTTOM); + tte_set_pos(LEFT, BOTTOM - (8 + (2 * tc->font->charH))); // The newline will trigger after this and move it down a line +} diff --git a/text_helper/main.py b/text_helper/main.py deleted file mode 100755 index b65b0cd..0000000 --- a/text_helper/main.py +++ /dev/null @@ -1,588 +0,0 @@ -# import pandas lib as pd -import pandas as pd -import os -from enum import Enum -import json -import requests -from collections import defaultdict -import copy -import math -import sys -import filecmp -import shutil - -update = True - -print ("Running text_helper:") - -if (update == True): - - url = 'https://docs.google.com/spreadsheets/d/14LLs5lLqWasFcssBmJdGXjjYxARAJBa_QUOUhXZt4v8/export?format=xlsx' - new_file_path = 'text_helper/new_text.xlsx' - old_file_path = 'text_helper/text.xlsx' - release_file_path = 'text_helper/release.xlsx' - json_file_path = 'text_helper/output.json' - - no_file = False - - if os.path.isfile(release_file_path): - print('Release file found. Using that instead!') - shutil.copy(release_file_path, new_file_path) - - else: - try: - response = requests.get(url, timeout=5) - response.raise_for_status() - if response.status_code == 200: - with open(new_file_path, 'wb') as file: - file.write(response.content) - print('File downloaded successfully') - except requests.exceptions.ReadTimeout as errrt: - if os.path.exists(old_file_path): - print("Connection timed out. Continuing with locally downloaded file.") - no_file = True - else: - print("xlsx file is missing and connection timed out. Exiting...") - except requests.exceptions.ConnectionError as conerr: - if os.path.exists(old_file_path): - print("Connection error. Continuing with locally downloaded file.") - no_file = True - else: - print("xlsx file is missing and connection timed out. Exiting...") - - -if os.path.exists(old_file_path): - if (not no_file): - new_file = pd.read_excel(new_file_path, sheet_name="Translations") - old_file = pd.read_excel(old_file_path, sheet_name="Translations") - if no_file or new_file.equals(old_file): - if os.path.exists(json_file_path): - print("Downloaded file is identical. Skipping parse\n") - if (not no_file): - os.remove(new_file_path) - exit() - print("json file missing - forcing rebuild.") - os.remove(old_file_path) - os.rename(new_file_path, old_file_path) -else: - print("xlsx file missing - forcing rebuild.") - os.rename(new_file_path, old_file_path) - - -engCharArray = [ -0x20, 0xC0, 0xC1, 0xC2, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0x20, 0xCE, 0xCF, 0xD2, 0xD3, 0xD4, -0x152, 0xD9, 0xDA, 0xDB, 0xD1, 0xDF, 0xE0, 0xE1, 0x20, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0x20, -0xEE, 0xEF, 0xF2, 0xF3, 0xF4, 0x153, 0xF9, 0xFA, 0xFB, 0xF1, 0xBA, 0xAA, 0x1D49, 0x26, 0x2B, 0x20, -0x20, 0x20, 0x20, 0x20, 0x20, 0x3D, 0x3B, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, -0x25AF, 0xBF, 0xA1, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xCD, 0x25, 0x28, 0x29, 0x20, 0x20, -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE2, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xED, -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2B07, 0x2B05, 0x27A1, 0x20, 0x20, 0x20, -0x20, 0x20, 0x20, 0x20, 0x1D49, 0x3C, 0x3E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, -0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, -0x2B3, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x21, 0x3F, 0x2E, 0x2D, 0x30FB, -0x2026, 0x201C, 0x201D, 0x2018, 0x2019, 0x2642, 0x2640, 0x20, 0x2C, 0xD7, 0x2F, 0x41, 0x42, 0x43, 0x44, 0x45, -0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, -0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, -0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x25B6, -0x3A, 0xC4, 0xD6, 0xDC, 0xE4, 0xF6, 0xFC, 0x2A, 0x20, 0x20, 0x15E, 0x23C, 0x206, 0x1B2, 0x147, 0x19E, -] - -engCharWidthArray = [ - 0x4, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x0, 0x6, 0x6, 0x6, 0x6, 0x6, -0x8, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x0, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x0, -0x6, 0x6, 0x6, 0x6, 0x6, 0x8, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x9, 0x6, 0x6, 0x0, -0x0, 0x0, 0x0, 0x0, 0xA, 0x8, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x6, 0x6, 0x4, 0x8, 0x8, 0x8, 0x7, 0x8, 0x8, 0x4, 0x6, 0x6, 0x4, 0x4, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x7, 0x7, 0x7, 0x2, 0x3, 0x4, -0x5, 0x5, 0x6, 0x7, 0x5, 0x6, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x8, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x4, 0x6, 0x3, 0x6, 0x3, -0x6, 0x6, 0x6, 0x3, 0x3, 0x6, 0x6, 0x6, 0x3, 0x7, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, -0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, -0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x4, 0x5, 0x6, -0x4, 0x6, 0x6, 0x6, 0x6, 0x6, 0x5, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x8, -0x3, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0x0, 0x0, ] - -jpnCharArray = [ -0x20, 0x3042, 0x3044, 0x3046, 0x3048, 0x304A, 0x304B, 0x304D, 0x304F, 0x3051, 0x3053, 0x3055, 0x3057, 0x3059, 0x305B, 0x305D, -0x305F, 0x3061, 0x3064, 0x3066, 0x3068, 0x306A, 0x306B, 0x306C, 0x306D, 0x306E, 0x306F, 0x3072, 0x3075, 0x3078, 0x307B, 0x307E, -0x307F, 0x3080, 0x3081, 0x3082, 0x3084, 0x3086, 0x3088, 0x3089, 0x308A, 0x308B, 0x308C, 0x308D, 0x308F, 0x3092, 0x3093, 0x3041, -0x3043, 0x3045, 0x3047, 0x3049, 0x3083, 0x3085, 0x3087, 0x304C, 0x304E, 0x3050, 0x3052, 0x3054, 0x3056, 0x3058, 0x305A, 0x305C, -0x305E, 0x3060, 0x3062, 0x3065, 0x3067, 0x3069, 0x3070, 0x3073, 0x3076, 0x3079, 0x307C, 0x3071, 0x3074, 0x3077, 0x307A, 0x307D, -0x3063, 0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD, 0x30AF, 0x30B1, 0x30B3, 0x30B5, 0x30B7, 0x30B9, 0x30BB, 0x30BD, -0x30BF, 0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA, 0x30CB, 0x30CC, 0x30CD, 0x30CE, 0x30CF, 0x30D2, 0x30D5, 0x30D8, 0x30DB, 0x30DE, -0x30DF, 0x30E0, 0x30E1, 0x30E2, 0x30E4, 0x30E6, 0x30E8, 0x30E9, 0x30EA, 0x20, 0x30EC, 0x30ED, 0x30EF, 0x30F2, 0x30F3, 0x30A1, -0x30A3, 0x30A5, 0x30A7, 0x30A9, 0x30E3, 0x30E5, 0x30E7, 0x30AC, 0x30AE, 0x30B0, 0x30B2, 0x30B4, 0x30B6, 0x30B8, 0x30BA, 0x30BC, -0x30BE, 0x30C0, 0x30C2, 0x30C5, 0x30C7, 0x30C9, 0x30D0, 0x30D3, 0x30D6, 0x30D9, 0x30DC, 0x30D1, 0x30D4, 0x30D7, 0x30DA, 0x30DD, -0x30C3, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0xFF01, 0xFF1F, 0x3002, 0x30FC, 0x30FB, -0x30FB, 0x300E, 0x300F, 0x300C, 0x300D, 0x2642, 0x2640, 0x5186, 0x2E, 0xD7, 0x2F, 0x41, 0x42, 0x43, 0x44, 0x45, -0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, -0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, -0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x25B6, -0x3A, 0xC4, 0xD6, 0xDC, 0xE4, 0xF6, 0xFC, 0x2A, 0x20, 0x20, 0x15E, 0x23C, 0x206, 0x1B2, 0x147, 0x19E, -] - -jpnCharWidthArray = [ - 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, -0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, -0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, -0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, -0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, -0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, -0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, -0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, -0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, -0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, -0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, -0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, -0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, -0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, -0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, -0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, ] - -charConversionList = [ - # replaces the first char in the list with the latter - ["'", "’"], -] - -def convertByte(incoming, array): - for pair in charConversionList: - if incoming == ord(pair[0]): - incoming = ord(pair[1]) - #print(f"Warning! {pair[0]} found, replacing with {pair[1]} !") - next_key = max(mainDict[lang.name]["Warnings"].keys(), default =- 1) + 1 - mainDict[lang.name]["Warnings"][next_key] = f"Warning! {pair[0]} found, replacing with {pair[1]} !" - - - index = 0 - for val in array: - if val == incoming: - return index - index += 1 - #print(f"Error! No match found for char [ {chr(incoming)} ]!") - - next_key = max(mainDict[lang.name]["Errors"].keys(), default =- 1) + 1 - mainDict[lang.name]["Errors"][next_key] = f"Error! No match found for char [ {chr(incoming)} ]!" - return 0 - -def SplitSentenceIntoLines(sentence, offset, pixelsPerChar, pixelsInLine): - # If we can optimize this to remove the spaces, it could save a few bytes. - - outStr = "" - currLine = "" - lineCount = 0 - currWordIndex = 0 - lineLength = 0 - spaceLength = 0 - words = sentence.split() - while(currWordIndex < len(words)): - word = words[currWordIndex] - wordLength = 0 - # print(word) - - # Figure out the length of the word in pixels - for char in word: - if (pixelsPerChar == "Variable"): - if(lang == Languages.Japanese): - wordLength += jpnCharWidthArray[convertByte(ord(char), engCharArray)] - spaceLength = jpnCharWidthArray[convertByte(ord(' '), engCharArray)] - else: - wordLength += engCharWidthArray[convertByte(ord(char), engCharArray)] - spaceLength = engCharWidthArray[convertByte(ord(' '), engCharArray)] - - elif (pixelsPerChar == "Default"): - if (lang == Languages.Japanese): - wordLength += 8 - spaceLength = 8 - - else: - wordLength += 6 - spaceLength = 6 - - # See if the whole sentence is a newline - if (sentence == "Ň"): - outStr += "Ň" - currLine = "" - lineCount += 1 - offset = 0 - lineLength = 0 - currWordIndex += 1 - - # See if the sentence is a new box - elif(sentence == "Ş" or sentence == "ȼ"): - outStr += sentence - currLine = "" - offset = 0 - lineLength = 0 - currWordIndex += 1 - - # Test if the word is too long in general - elif (wordLength > pixelsInLine): - #print(f"ERROR: Word {word} exceeds alloted length") - next_key = max(mainDict[lang.name]["Errors"].keys(), default =- 1) + 1 - mainDict[lang.name]["Errors"][next_key] = f"ERROR: Word {word} exceeds alloted length" - currWordIndex += 1 - - # Test if adding the word will go over our alloted space - elif ((wordLength + lineLength + offset) <= pixelsInLine): - # If not, add the word and increase the index - currLine += (word + " ") - lineLength += (wordLength + spaceLength) - currWordIndex += 1 - - # We need to move to the next line - else: - # Every line should already have a space at the end of it. Remove it here - outStr += (currLine[:-1] + "Ň") - currLine = "" - lineCount += 1 - lineLength = 0 - offset = 0 - - outStr += currLine - return lineLength + offset, lineCount, outStr - -# -*- coding: utf-8 -*- -import re -alphabets= r"([A-Za-z])" -prefixes = r"(Mr|St|Mrs|Ms|Dr)[.]" -suffixes = r"(Inc|Ltd|Jr|Sr|Co)" -starters = r"(Mr|Mrs|Ms|Dr|Prof|Capt|Cpt|Lt|He\s|She\s|It\s|They\s|Their\s|Our\s|We\s|But\s|However\s|That\s|This\s|Wherever)" -acronyms = r"([A-Z][.][A-Z][.](?:[A-Z][.])?)" -websites = r"[.](com|net|org|io|gov|edu|me)" -digits = r"([0-9])" -multiple_dots = r'\.{2,}' - -def split_into_sentences(text: str) -> list[str]: - """ - Split the text into sentences. - - If the text contains substrings "" or "", they would lead - to incorrect splitting because they are used as markers for splitting. - - :param text: text to be split into sentences - :type text: str - - :return: list of sentences - :rtype: list[str] - """ - text = " " + text + " " - text = text.replace("\n"," ") - text = re.sub(prefixes,"\\1",text) - text = re.sub(websites,"\\1",text) - text = re.sub(digits + "[.]" + digits,"\\1\\2",text) - text = re.sub(multiple_dots, lambda match: "" * len(match.group(0)) + "", text) - if "Ph.D" in text: text = text.replace("Ph.D.","PhD") - text = re.sub(r"\s" + alphabets + "[.] "," \\1 ",text) - text = re.sub(acronyms+" "+starters,"\\1 \\2",text) - text = re.sub(alphabets + "[.]" + alphabets + "[.]" + alphabets + "[.]","\\1\\2\\3",text) - text = re.sub(alphabets + "[.]" + alphabets + "[.]","\\1\\2",text) - text = re.sub(" "+suffixes+"[.] "+starters," \\1 \\2",text) - text = re.sub(" "+suffixes+"[.]"," \\1",text) - text = re.sub(" " + alphabets + "[.]"," \\1",text) - if "”" in text: text = text.replace(".”","”.") - if "\"" in text: text = text.replace(".\"","\".") - if "!" in text: text = text.replace("!\"","\"!") - if "?" in text: text = text.replace("?\"","\"?") - if "。" in text: text = text.replace("。\"","\"。") # Added for Japanese support - if "?" in text: text = text.replace("?\"","\"?") # Added for Japanese support - if "!" in text: text = text.replace("!\"","\"!") # Added for Japanese support - text = text.replace(".",".") - text = text.replace("?","?") - text = text.replace("!","!") - text = text.replace("。","。") # Added for Japanese support - text = text.replace("?","?") # Added for Japanese support - text = text.replace("!","!") # Added for Japanese support - text = text.replace("",".") - text = text.replace("Ň", "Ň") # Split newlines into their own sentences - text = text.replace("ȼ", "ȼ") # Split new boxes into their own sentences - text = text.replace("Ş", "Ş") # Split new boxes into their own sentences - sentences = text.split("") - sentences = [s.strip() for s in sentences] - if sentences and not sentences[-1]: sentences = sentences[:-1] - return sentences - -class Languages(Enum): - Japanese = 0 - English = 1 - ##French = 2 - ##German = 3 - ##Italian = 4 - ##SpanishEU = 5 - ##SpanishLA = 6 - -# read by default 1st sheet of an excel file -dir = os.curdir + "/text_helper" - -mainDict = {} - -for lang in Languages: - mainDict[lang.name] = { - "PTGB": {}, - "RSEFRLG": {}, - "GB": {}, - "GENERAL": {}, - "CREDITS": {}, - "PKMN_NAMES": {}, - "Warnings" : {}, - "Errors": {}, -} - -def convert_item(ogDict): - line = ogDict["bytes"] - numLines = ogDict["numLines"] - pixelsPerChar = ogDict["pixelsPerChar"] - pixelsInLine = ogDict["pixelsInLine"] - include_box_breaks = ogDict["includeBoxBreaks"] - split_sents = split_into_sentences(line) - index = 0 - outStr = "" - currLine = 0 - offset = 0 - escapeCount = 0 - while index < len(split_sents) and escapeCount < 100: - offset, recievedLine, out = SplitSentenceIntoLines(split_sents[index], offset, pixelsPerChar, pixelsInLine) - currLine += recievedLine - - if (out == "ȼ"): - offset = 0 - currLine = 0 - outStr = outStr[:-1] - outStr += "ȼ" - index += 1 - elif (currLine < numLines): - #print(split_sents[index]) - index += 1 - outStr += out - else: - outStr = outStr[:-1] - outStr += "ȼ" # new textbox character - offset = 0 - currLine = 0 - escapeCount += 1 - #print(index) - if not include_box_breaks: - #print(f"ERROR! Made a line break when disabled, sentence \"{outStr}\" is too long!") - next_key = max(mainDict[lang.name]["Errors"].keys(), default =- 1) + 1 - mainDict[lang.name]["Errors"][next_key] = f"ERROR! Made a line break when disabled, sentence \"{outStr}\" is too long!" - - if escapeCount == 100: - #print(f"ERROR! Sentence \"{out}\" is too long!") - next_key = max(mainDict[lang.name]["Errors"].keys(), default =- 1) + 1 - mainDict[lang.name]["Errors"][next_key] = f"ERROR! Sentence \"{out}\" is too long!" - - # Some cases that should be fixed - exitLoop = False - while(not exitLoop): - newStr = outStr - # A space right before a newline just takes up space - newStr = newStr.replace(" Ň", "Ň") - # Newlines shouldn't happen right after a new textbox - newStr = newStr.replace("ȼŇ", "ȼ") - # Nor should newlines be right before a new textbox - newStr = newStr.replace("Ňȼ", "ȼ") - # Nor should a new textbox be after a new textbox - newStr = newStr.replace("ȼȼ", "ȼ") - # Nor should a new scroll be after a new textbox - newStr = newStr.replace("Şȼ", "Ş") - # Nor should a new scroll be after a new textbox - newStr = newStr.replace("ȼŞ", "ȼ") - - exitLoop = (newStr == outStr) - outStr = newStr - - byteStr = "" - if lang == Languages.Japanese: - arr = jpnCharArray - else: - arr = engCharArray - for char in outStr[:-1]: - byteStr += f"{convertByte(ord(char), arr):02x} " - if (len(outStr) > 0 and outStr[-1] != ' '): # Check if the last char is a space - byteStr += f"{convertByte(ord(outStr[-1]), arr):02x} " - - byteStr += "ff" - - ogDict["bytes"] = byteStr - return ogDict - -def write_text_bin_file(filename, dictionary): - with open(filename, 'wb') as binFile: - # Let the first byte indicate the number of entries - dict_size = len(dictionary) - # We need to store 2 bytes instead of one, because not aligning the data to 16 bits will cause corruption on the gba. - binFile.write(bytes([dict_size & 0xFF, (dict_size >> 8) & 0xFF])) - # After this initial byte, we will read the offset (16 bit) of each line (relative to the last index byte) - index = bytearray(len(dictionary) * 2) - # bindata will contain the binary data of each entry - bindata = bytearray() - current_offset = 0 - - num = 0 - # Append every line's binary data to bindata - # keep an index of the binary offset within bindata at which each line starts - for key, line in dictionary.items(): - dictionary[key] = convert_item(line) - # store the offset of the line in the index as a 16 bit little endian value - index[num * 2] = (current_offset & 0xFF) - index[num * 2 + 1] = (current_offset >> 8) & 0xFF - linedata = bytes.fromhex(dictionary[key]['bytes']) - bindata.extend(linedata) - current_offset += len(linedata) - - if len(linedata) > 1024: - print(f"Error: entry '{key}' numBytes exceeds 1024 (got {len(linedata)})", file=sys.stderr) - sys.exit(1) - - num += 1 - - # Write the index and bindata to the file - binFile.write(index) - binFile.write(bindata) - binFile.close() - -def write_enum_to_header_file(hFile, prefix, dictionary): - num = 0 - for key, line in dictionary.items(): - hFile.write(f"#define {prefix}{key} {num}\n") - num += 1 - hFile.write("\n") - return num - - -print("Starting parse:") - -currSheet = pd.read_excel(dir + "/text.xlsx", sheet_name="Translations") -for row in currSheet.iterrows(): - #print(row) - for lang in Languages: - currRow = row[1] - #print(currRow) - offset = lang.value - if (pd.isna(currRow.iloc[7 + lang.value])): - offset = Languages.English.value - mainDict[lang.name][currRow.iloc[0]][currRow.iloc[1]] = {"bytes": currRow.iloc[7 + offset], - "numLines": currRow.iloc[2], - "pixelsPerChar": currRow.iloc[3], - "pixelsInLine" : currRow.iloc[4], - "includeBoxBreaks": currRow.iloc[5], - } - -# generate the header file -with open (os.curdir + '/include/translated_text.h', 'w') as hFile: - hFile.write("#ifndef DIALOGUE_H\n#define DIALOGUE_H\n\n#include \n\n") - - # PTGB - num = write_enum_to_header_file(hFile, "", mainDict[lang.name]["PTGB"]) - hFile.write(f"\n#define DIA_SIZE {num}\n#define DIA_END DIA_SIZE\n\n") - - # RSEFRLG - write_enum_to_header_file(hFile, "RSEFRLG_", mainDict[lang.name]["RSEFRLG"]) - - # GENERAL - write_enum_to_header_file(hFile, "GENERAL_", mainDict[lang.name]["GENERAL"]) - - # CREDITS - write_enum_to_header_file(hFile, "CREDITS_", mainDict[lang.name]["CREDITS"]) - - # PKMN_NAMES - write_enum_to_header_file(hFile, "PKMN_NAMES_", mainDict[lang.name]["PKMN_NAMES"]) - - hFile.write("/** Returns the LZ10 compressed PTGB text table.*/\n") - hFile.write("const u8* get_compressed_PTGB_table();\n\n") - hFile.write("/** Returns the LZ10 compressed RSEFRLG text table.*/\n") - hFile.write("const u8* get_compressed_rsefrlg_table();\n\n") - hFile.write("/** Returns the LZ10 compressed GENERAL text table.*/\n") - hFile.write("const u8* get_compressed_general_table();\n\n") - hFile.write("/** Returns the LZ10 compressed CREDITS text table.*/\n") - hFile.write("const u8* get_compressed_credits_table();\n\n") - hFile.write("/** Returns the LZ10 compressed PKMN_NAMES text table.*/\n") - hFile.write("const u8* get_compressed_pkmn_names_table();\n\n") - - hFile.write("\n#endif") - hFile.close() - -# now generate the text tables -for lang in Languages: - # PTGB - table_file = os.curdir + '/to_compress/PTGB_' + lang.name.lower() + '.bin' - write_text_bin_file(table_file, mainDict[lang.name]["PTGB"]) - - # RSEFRLG - table_file = os.curdir + '/to_compress/RSEFRLG_' + lang.name.lower() + '.bin' - write_text_bin_file(table_file, mainDict[lang.name]["RSEFRLG"]) - - # GENERAL - table_file = os.curdir + '/to_compress/GENERAL_' + lang.name.lower() + '.bin' - write_text_bin_file(table_file, mainDict[lang.name]["GENERAL"]) - - # CREDITS - table_file = os.curdir + '/to_compress/CREDITS_' + lang.name.lower() + '.bin' - write_text_bin_file(table_file, mainDict[lang.name]["CREDITS"]) - - # PKMN_NAMES - table_file = os.curdir + '/to_compress/PKMN_NAMES_' + lang.name.lower() + '.bin' - write_text_bin_file(table_file, mainDict[lang.name]["PKMN_NAMES"]) - -# now generate the cpp file. -with open(os.curdir + '/source/translated_text.cpp', 'w') as cppFile: - cppFile.write("#include \"translated_text.h\"\n#include \"debug_mode.h\"\n") - # generate includes for each language - for lang in Languages: - for cat in mainDict[lang.name]: - if cat in {"PTGB", "RSEFRLG", "GENERAL", "CREDITS", "PKMN_NAMES"}: - cppFile.write("#include \"" + cat.upper() + "_" + lang.name.lower() + "_lz10_bin.h\"\n") - - for lang in Languages: - cppFile.write(f"\n#if PTGB_BUILD_LANGUAGE == {lang.value + 1}\n") - # PTGB - cppFile.write("const u8* get_compressed_PTGB_table()\n") - cppFile.write("{\n") - cppFile.write("\treturn PTGB_" + lang.name.lower() + "_lz10_bin;\n") - cppFile.write("}\n\n") - # RSEFRLG - cppFile.write("const u8* get_compressed_rsefrlg_table()\n") - cppFile.write("{\n") - cppFile.write("\treturn RSEFRLG_" + lang.name.lower() + "_lz10_bin;\n") - cppFile.write("}\n\n") - # GENERAL - cppFile.write("const u8* get_compressed_general_table()\n") - cppFile.write("{\n") - cppFile.write("\treturn GENERAL_" + lang.name.lower() + "_lz10_bin;\n") - cppFile.write("}\n\n") - # CREDITS - cppFile.write("const u8* get_compressed_credits_table()\n") - cppFile.write("{\n") - cppFile.write("\treturn CREDITS_" + lang.name.lower() + "_lz10_bin;\n") - cppFile.write("}\n\n") - # PKMN_NAMES - cppFile.write("const u8* get_compressed_pkmn_names_table()\n") - cppFile.write("{\n") - cppFile.write("\treturn PKMN_NAMES_" + lang.name.lower() + "_lz10_bin;\n") - cppFile.write("}\n\n") - - cppFile.write(f"#endif\n\n\n") - - -for lang in Languages: - for cat in mainDict[lang.name]: - if cat in {"PTGB", "RSEFRLG", "GENERAL", "CREDITS", "PKMN_NAMES"}: - for item in mainDict[lang.name][cat]: - string = mainDict[lang.name][cat][item]["bytes"].split(" ") - outText = "" - if lang == Languages.Japanese: - arr = jpnCharArray - else: - arr = engCharArray - for byte in string: - byte = engCharArray[int(byte, 16)] - outText += chr(byte) - mainDict[lang.name][cat][item]["text"] = outText - -with open(dir + '/output.json', 'w') as jsonFile: - jsonFile.write(json.dumps(mainDict)) - -print("Parse finished!\n") diff --git a/tools/payload-generator/Makefile b/tools/payload-generator/Makefile index a5dcb98..bf978a4 100644 --- a/tools/payload-generator/Makefile +++ b/tools/payload-generator/Makefile @@ -1,5 +1,27 @@ + +BUILD_LANGS := japanese english french german italian spanishEU spanishLA +BUILD_TYPES := release debug + +# defaults +BUILD_LANG ?= english +BUILD_TYPE ?= release +GIT_VERSION ?= $(shell git describe --tags --abbrev=0) +GIT_FULL ?= $(shell git describe --tags --always --dirty 2>/dev/null) + +CMD_GOALS := $(filter-out build,$(MAKECMDGOALS)) + +LANG_INDEX := $(shell echo $(BUILD_LANGS) | tr ' ' '\n' | nl -v0 | grep -w $(BUILD_LANG) | awk '{print $$1 + 1}') +TYPE_INDEX := $(shell echo $(BUILD_TYPES) | tr ' ' '\n' | nl -v0 | grep -w $(BUILD_TYPE) | awk '{print $$1}') + +CPPFLAGS += -DPTGB_BUILD_LANGUAGE=$(LANG_INDEX) +CPPFLAGS += -DDEBUG_MODE=$(TYPE_INDEX) +CPPFLAGS += -DBUILD_INFO=\"$(GIT_FULL)\" + +CFLAGS += $(CPPFLAGS) +CXXFLAGS += $(CPPFLAGS) + # # Compiler flags -CXXFLAGS := -std=c++20 -fno-rtti -fno-exceptions -fno-unwind-tables -Wall -Wextra -I $(CURDIR)/include -g +CXXFLAGS += -std=c++20 -fno-rtti -fno-exceptions -fno-unwind-tables -Wall -Wextra -I $(CURDIR)/include -g # Source files directory SRC_DIR := ./src diff --git a/tools/payload-generator/src/payloads/payload_builder.cpp b/tools/payload-generator/src/payloads/payload_builder.cpp index 4fbe2cf..f1ee5c5 100644 --- a/tools/payload-generator/src/payloads/payload_builder.cpp +++ b/tools/payload-generator/src/payloads/payload_builder.cpp @@ -5,7 +5,6 @@ #include #define DATA_LOC (SHOW_DATA_PACKETS ? curr_rom.transferStringLocation : curr_rom.wEnemyMonSpecies) -#define DEBUG_PAYLOADS (false && DEBUG_MODE) void init_payload(byte *payload_buffer, const GB_ROM &curr_rom, int type, bool debug) { diff --git a/tools/text_helper/fonts/japanese_normal.png b/tools/text_helper/fonts/japanese_normal.png new file mode 100644 index 0000000..5aeacc2 Binary files /dev/null and b/tools/text_helper/fonts/japanese_normal.png differ diff --git a/tools/text_helper/fonts/latin_normal.png b/tools/text_helper/fonts/latin_normal.png new file mode 100644 index 0000000..97260c6 Binary files /dev/null and b/tools/text_helper/fonts/latin_normal.png differ diff --git a/tools/text_helper/main.py b/tools/text_helper/main.py new file mode 100644 index 0000000..f88e388 --- /dev/null +++ b/tools/text_helper/main.py @@ -0,0 +1,857 @@ +import pandas as pd +import os +from enum import Enum +import json +import requests +from collections import defaultdict +import sys +from pathlib import Path +import hashlib +import math +import numpy as np +import png +import shutil + +class Languages(Enum): + Japanese = 0 + English = 1 + French = 2 + German = 3 + Italian = 4 + SpanishEU = 5 + SpanishLA = 6 + +FIRST_TRANSLATION_COL_INDEX = 9 +PURPOSEFUL_SPACE_CHAR = '|' + +BASE_DIR = Path(__file__).resolve().parent +BUILD_DIR = BASE_DIR / "build" +GEN_DIR = BASE_DIR.parent.parent / "build" / "generated" +BUILD_DIR.mkdir(parents=True, exist_ok=True) +GEN_DIR.mkdir(parents=True, exist_ok=True) +TRANSLATED_H_PATH = GEN_DIR / "translated_text.h" +TRANSLATED_CPP_PATH = GEN_DIR / "translated_text.cpp" +FONTS_H_PATH = GEN_DIR / "fonts.h" +OUTPUT_JSON_PATH = BUILD_DIR / "output.json" +THIS_SCRIPT_PATH = BASE_DIR / "main.py" + +url = 'https://docs.google.com/spreadsheets/d/14LLs5lLqWasFcssBmJdGXjjYxARAJBa_QUOUhXZt4v8/export?format=xlsx' +new_file_path = BUILD_DIR / 'new_text.xlsx' +old_file_path = BUILD_DIR / 'text.xlsx' +release_file_path = BASE_DIR / 'release.xlsx' +json_file_path = BUILD_DIR / "output.json" + +if len(sys.argv) >= 3: + BUILD_LANG = sys.argv[1] + BUILD_TYPE = sys.argv[2] +else: + BUILD_LANG = "" # Not implemented yet + BUILD_TYPE = "debug" + +def split_into_sentences(text: str) -> list[str]: + # -*- coding: utf-8 -*- + import re + alphabets= r"([A-Za-z])" + prefixes = r"(Mr|St|Mrs|Ms|Dr)[.]" + suffixes = r"(Inc|Ltd|Jr|Sr|Co)" + starters = r"(Mr|Mrs|Ms|Dr|Prof|Capt|Cpt|Lt|He\s|She\s|It\s|They\s|Their\s|Our\s|We\s|But\s|However\s|That\s|This\s|Wherever)" + acronyms = r"([A-Z][.][A-Z][.](?:[A-Z][.])?)" + websites = r"[.](com|net|org|io|gov|edu|me)" + digits = r"([0-9])" + multiple_dots = r'\.{2,}' + + """ + Split the text into sentences. + + If the text contains substrings "" or "", they would lead + to incorrect splitting because they are used as markers for splitting. + + :param text: text to be split into sentences + :type text: str + + :return: list of sentences + :rtype: list[str] + """ + text = " " + text + " " + text = text.replace("\n"," ") + text = re.sub(prefixes,"\\1",text) + text = re.sub(websites,"\\1",text) + text = re.sub(digits + "[.]" + digits,"\\1\\2",text) + text = re.sub(multiple_dots, lambda match: "" * len(match.group(0)) + "", text) + if "Ph.D" in text: text = text.replace("Ph.D.","PhD") + text = re.sub(r"\s" + alphabets + "[.] "," \\1 ",text) + text = re.sub(acronyms+" "+starters,"\\1 \\2",text) + text = re.sub(alphabets + "[.]" + alphabets + "[.]" + alphabets + "[.]","\\1\\2\\3",text) + text = re.sub(alphabets + "[.]" + alphabets + "[.]","\\1\\2",text) + text = re.sub(" "+suffixes+"[.] "+starters," \\1 \\2",text) + text = re.sub(" "+suffixes+"[.]"," \\1",text) + text = re.sub(" " + alphabets + "[.]"," \\1",text) + if "”" in text: text = text.replace(".”","”.") + if "\"" in text: text = text.replace(".\"","\".") + if "!" in text: text = text.replace("!\"","\"!") + if "?" in text: text = text.replace("?\"","\"?") + if "。" in text: text = text.replace("。\"","\"。") # Added for Japanese support + if "?" in text: text = text.replace("?\"","\"?") # Added for Japanese support + if "!" in text: text = text.replace("!\"","\"!") # Added for Japanese support + text = text.replace(".",".") + text = text.replace("?","?") + text = text.replace("!","!") + text = text.replace("。","。") # Added for Japanese support + text = text.replace("?","?") # Added for Japanese support + text = text.replace("!","!") # Added for Japanese support + text = text.replace("",".") + text = text.replace("Ň", "Ň") # Split newlines into their own sentences + text = text.replace("ȼ", "ȼ") # Split new boxes into their own sentences + text = text.replace("Ş", "Ş") # Split new boxes into their own sentences + text = text.replace("Ω", "Ω") # Split centering into their own sentences + text = text.replace("ɑ", "ɑ") # Split centering into their own sentences + + sentences = text.split("") + sentences = [s.strip() for s in sentences] + if sentences and not sentences[-1]: sentences = sentences[:-1] + return sentences + +def split_sentence_into_lines(sentence, offset, pixelsPerChar, pixelsInLine, centered, lang): + outStr = "" + currLine = "" + lineCount = 0 + currWordIndex = 0 + lineLength = 0 + spaceLength = 0 + + words = sentence.split() + + + while(currWordIndex < len(words)): + word = words[currWordIndex] + wordLength = 0 + # print(word) + + # Figure out the length of the word in pixels + for char in word: + if (char == PURPOSEFUL_SPACE_CHAR): + char = " " + if (pixelsPerChar == "Variable"): + wordLength += charArrayOfLanguage[lang]["font"].charWidthTable[convert_char_to_byte(ord(char), charArrayOfLanguage[lang]["array"], lang)] + spaceLength = charArrayOfLanguage[lang]["font"].charWidthTable[0] + elif (pixelsPerChar == "Default"): + if (lang == Languages.Japanese): + wordLength += 8 + spaceLength = 8 + + else: + wordLength += 6 + spaceLength = 6 + + # See if the whole sentence is a newline or scroll + if (sentence == "Ň" or sentence == "Ş"): + if (sentence == "Ň"): + outStr += "Ň" + elif (sentence == "Ş"): + outStr += "Ş" + currLine = "" + lineCount += 1 + offset = 0 + lineLength = 0 + currWordIndex += 1 + + # See if the whole sentence is a center character + elif (sentence == "ɑ" or sentence == "Ω"): + if (sentence == "ɑ"): + centered = True + outStr += "Ň" + else: + centered = False + outStr += "Ň" + currLine = "" + lineCount += 1 + offset = 0 + lineLength = 0 + currWordIndex += 1 + + # See if the sentence is a new box + elif(sentence == "ȼ"): + outStr += sentence + currLine = "" + offset = 0 + lineLength = 0 + currWordIndex += 1 + + # Test if the word is too long in general + elif (wordLength > pixelsInLine): + log_warning_error(lang, "Error", f"Word {word} exceeds alloted length ({pixelsInLine} pixels)") + currWordIndex += 1 + + # Test if adding the word will go over our alloted space + elif ((wordLength + lineLength + offset) <= pixelsInLine): + # If not, add the word and increase the index + if (currWordIndex == (len(words) - 1)): + # Don't add a space to the end of the sentence. + currLine += word + lineLength += wordLength + else: + currLine += (word + " ") + lineLength += (wordLength + spaceLength) + currWordIndex += 1 + + # We need to move to the next line + else: + # Every line should already have a space at the end of it. Remove it here + outStr += (currLine[:-1] + "Ň") + currLine = "" + lineCount += 1 + lineLength = 0 + offset = 0 + if (centered and (len(words) > 0) and words[0] != 'ɑ'): + count = ((pixelsInLine - lineLength) // 2) + currLine = f'_[{count}]{currLine}' + lineLength += count + outStr += currLine + return lineLength + offset, lineCount, outStr, centered + +def convert_char_to_byte(incoming, array, lang): + for pair in charConversionList: + if incoming == ord(pair[0]): + incoming = ord(pair[1]) + log_warning_error(lang, "Warning", f"Character {pair[0]} was used but is not in character table. Replaced with {pair[1]} .") + + index = 0 + #print(array) + for val in array: + if str(val) == chr(incoming): + return index + index += 1 + if chr(incoming) != '_': + log_warning_error(lang, "Error", f"No match found for char [ {chr(incoming)} ]!") + return 0 + +def log_warning_error(lang, type, text): + nType = type + "s" + nText = type + ": " + text + if nText not in mainDict[lang.name][nType].values(): + mainDict[lang.name][nType][max(mainDict[lang.name][nType].keys(), default =- 1) + 1] = nText + #print(nText) + +def hash_excel(path): + sheets = pd.read_excel(path, sheet_name=None) + h = hashlib.sha256() + for name in sorted(sheets): + h.update(name.encode()) + h.update(pd.util.hash_pandas_object( + sheets[name], index=True + ).values) + return h.digest() + +def convert_item(ogDict, lang): + line = ogDict["bytes"] + numLines = ogDict["numLines"] + pixelsPerChar = ogDict["pixelsPerChar"] + pixelsInLine = ogDict["pixelsInLine"] + include_box_breaks = ogDict["includeBoxBreaks"] + include_scrolling = ogDict["includeScrolling"] + + arr = charArrayOfLanguage[lang]["array"] + escape_list = charArrayOfLanguage[lang]["escape"] + + for pair in escape_list: + if pair[0] in line: + escapeString = "" + for char in pair[1]: + escapeString += arr[char] + #print(f"Replacing {pair[0]} with {escapeString}!") + line = line.replace(pair[0], escapeString) + #print(line) + + # Special case for the centering escape character + line = line.replace("{CTR}", 'ɑ') + line = line.replace("{nCTR}", 'Ω') + + # Special case for the values that change by language. Probably should be built into the lang struct eventually + if (lang == Languages.English): + line = line.replace("{LVL}", arr[0x30]) + line = line.replace("{PP}", arr[0x60]) + line = line.replace("{NO}", arr[0x70]) + elif (lang == Languages.French): + line = line.replace("{LVL}", arr[0x31]) + line = line.replace("{PP}", arr[0x60]) + line = line.replace("{NO}", arr[0x71]) + elif (lang == Languages.German): + line = line.replace("{LVL}", arr[0x32]) + line = line.replace("{PP}", arr[0x61]) + line = line.replace("{NO}", arr[0x72]) + elif (lang == Languages.Italian): + line = line.replace("{LVL}", arr[0x33]) + line = line.replace("{PP}", arr[0x60]) + line = line.replace("{NO}", arr[0x71]) + elif (lang == Languages.SpanishEU or lang == Languages.SpanishLA): + line = line.replace("{LVL}", arr[0x34]) + line = line.replace("{PP}", arr[0x60]) + line = line.replace("{NO}", arr[0x72]) + + # Change all the punctuation marks followed by spaces into being followed by | temporarily + spaces = [' ', ' '] + puncts = ['.', '?', '!', '。', '!', '?'] + for space in spaces: + for punct in puncts: + line = line.replace(punct + space, punct + PURPOSEFUL_SPACE_CHAR) + + split_sents = split_into_sentences(line) + index = 0 + outStr = "" + currLine = 0 + offset = 0 + escapeCount = 0 + centered = False + while index < len(split_sents) and escapeCount < 100: + offset, recievedLine, out, centered = split_sentence_into_lines(split_sents[index], offset, pixelsPerChar, pixelsInLine, centered, lang) + currLine += recievedLine + + if (out == "ȼ"): + offset = 0 + currLine = 0 + # This tests if the character before the new box is a space, newline, or scroll + if outStr and (outStr[-1] in (" ", "Ň", "Ş")): + outStr = outStr[:-1] + outStr += "ȼ" + index += 1 + elif (currLine < (numLines + int(include_scrolling))): + #print(split_sents[index]) + index += 1 + # This tests if the character after the new box is a space, newline, or scroll + if outStr and out and outStr[-1] == 'ȼ' and out[0] in (" ", "Ň", "Ş"): + out = out[1:] + outStr += out + else: + if not include_box_breaks: + log_warning_error(lang, "Error", f"Attempted to make a new text box when disabled, sentence \"{outStr}\" is too long!") + # This tests if the character before the new box is a space, newline, or scroll(?) + elif outStr and (outStr[-1] in (" ", "Ň", "Ş")): + outStr = outStr[:-1] + outStr += "ȼ" # new textbox character + offset = 0 + currLine = 0 + escapeCount += 1 + #print(index) + + + if escapeCount == 100: + log_warning_error(lang, "Error", f"Sentence \"{out}\" is too long!") + + # It's safe to swap the purposeful spaces back + outStr = outStr.replace(PURPOSEFUL_SPACE_CHAR, " ") + + # Some cases that should be fixed + exitLoop = False + while(not exitLoop): + newStr = "" + + splitBoxes = outStr.split('ȼ') + outIndex = 0 + for box in splitBoxes: + if box and ((box[0] == " ")): + box = box[1:] + outIndex += 1 + # Make sure both kinds of newlines are being accounted for + box = box.replace('Ş', 'Ň') + splitLines = box.split('Ň') + outBox = "" + i = 1 + for split in splitLines: + outIndex += len(split) + if split == splitLines[-1]: + breakChar = "" + elif ((i >= numLines) and include_scrolling): + breakChar = 'Ş' + else: + breakChar = outStr[outIndex] + outBox += split + breakChar + outIndex += 1 + i += 1 + if (outBox and (outBox[:-1] == 'ȼ') or (outBox[:-1] == 'Ň')): + newStr += f'{outBox[:-1]}ȼ' + elif (outBox): + newStr += f'{outBox}ȼ' + newStr = newStr[:-1] # remove the last ȼ + + if len(newStr) > 1023: + newStr = newStr[:1023] + log_warning_error(lang, "Warning", f"String {newStr} exceeds character limit of 1023 and has been truncated.") + + exitLoop = (newStr == outStr) + outStr = newStr + + byteStr = "" + arr = charArrayOfLanguage[lang]["array"] + i = 0 + while i < len(outStr[:-1]): + char = outStr[i] + if (char == '['): + val = '' + i += 1 + while outStr[i] != ']': + val = val + outStr[i] + i += 1 + num = int(val) + byteStr += f"{num:02x} " + else: + byteStr += f"{convert_char_to_byte(ord(char), arr, lang):02x} " + i += 1 + if (len(outStr) > 0 and outStr[-1] != ' '): # Check if the last char is a space + byteStr += f"{convert_char_to_byte(ord(outStr[-1]), arr, lang):02x} " + + byteStr += "ff" + + ogDict["bytes"] = byteStr + return ogDict + +def write_text_bin_file(filename, dictionary, lang, section): + MAX_BIN_SIZES = { + "PTGB": 6144, + "RSEFRLG": 3444, + "GB": 9999, + "GENERAL": 2048, + "CREDITS": 2048, + "PKMN_NAMES": 3072, + } + + with open(filename, 'wb') as binFile: + # Let the first byte indicate the number of entries + dict_size = len(dictionary) + # We need to store 2 bytes instead of one, because not aligning the data to 16 bits will cause corruption on the gba. + binFile.write(bytes([dict_size & 0xFF, (dict_size >> 8) & 0xFF])) + # After this initial byte, we will read the offset (16 bit) of each line (relative to the last index byte) + index = bytearray(len(dictionary) * 2) + # bindata will contain the binary data of each entry + bindata = bytearray() + current_offset = 0 + + num = 0 + # Append every line's binary data to bindata + # keep an index of the binary offset within bindata at which each line starts + for key, line in dictionary.items(): + dictionary[key] = convert_item(line, lang) + # store the offset of the line in the index as a 16 bit little endian value + index[num * 2] = (current_offset & 0xFF) + index[num * 2 + 1] = (current_offset >> 8) & 0xFF + linedata = bytes.fromhex(dictionary[key]['bytes']) + + bindata.extend(linedata) + current_offset += len(linedata) + + num += 1 + + # Write the index and bindata to the file + binFile.write(index) + binFile.write(bindata) + binFile.seek(0, os.SEEK_END) + if binFile.tell() > MAX_BIN_SIZES[section]: + log_warning_error(lang, "Error", f'Section {section} exceeds the max binary file size by {binFile.tell() - MAX_BIN_SIZES[section]} bytes!') + binFile.close() + +def write_enum_to_header_file(hFile, prefix, dictionary): + num = 0 + for key, line in dictionary.items(): + hFile.write(f"#define {prefix}{key} {num}\n") + num += 1 + hFile.write(f"\n#define {prefix}LENGTH {num}\n") + hFile.write("\n") + return num + +def download_xlsx_file(): + if os.path.isfile(release_file_path): + print('Release file found. Using that instead!') + shutil.copy(release_file_path, new_file_path) + offline = False + else: + print("Downloading xlsx file") + offline = False + # ---- Attempt download ---- + try: + response = requests.get(url, timeout=5) + response.raise_for_status() + with open(new_file_path, 'wb') as f: + f.write(response.content) + print("File downloaded successfully") + + except (requests.exceptions.ReadTimeout, requests.exceptions.ConnectionError): + if old_file_path.exists(): + print("No internet. Using cached xlsx.") + offline = True + else: + print("ERROR: No internet and no cached xlsx. Cannot continue.") + sys.exit(1) + + # ---- Decision logic ---- + if offline: + # XML exists (guaranteed here) + if json_file_path.exists(): + print("Offline mode: trusting cached XML + JSON. Skipping parse.") + if os.path.getmtime(THIS_SCRIPT_PATH) > os.path.getmtime(OUTPUT_JSON_PATH): + print("\t...but the python file is new, so we're doing it anyway!") + return + sys.exit(0) + else: + print("Offline mode: XML present but JSON missing. Rebuilding.") + + else: + # Online mode + if old_file_path.exists(): + + if hash_excel(new_file_path) == hash_excel(old_file_path): + print("Downloaded file is identical") + new_file_path.unlink() + if json_file_path.exists(): + print("Skipping parse") + if os.path.getmtime(THIS_SCRIPT_PATH) > os.path.getmtime(OUTPUT_JSON_PATH): + print("\t...but the python file is new, so we're doing it anyway!") + return + sys.exit(0) + else: + print("JSON missing - forcing rebuild") + else: + old_file_path.unlink() + new_file_path.rename(old_file_path) + + else: + print("No cached xlsx - forcing rebuild") + new_file_path.rename(old_file_path) + +def transfer_xlsx_to_dict(): + print("\tGetting character arrays") + currSheet = pd.read_excel(old_file_path, sheet_name="Character Arrays", header=None) + offset = 0 + for key, value in charArrays.items(): + for r in range(16): + for c in range(16): + val = currSheet.iloc[r + 1, c + offset] + if pd.isna(val): + val = " " + value["array"][r * 0x10 + c] = val + # print(charArrays[key]) + offset += 16 + + + + print("\tGetting string data") + currSheet = pd.read_excel(old_file_path, sheet_name="Translations") + + for row in currSheet.iterrows(): + currRow = row[1]["Text Section"] + if (currRow not in textSections): + textSections.append(currRow) + + for lang in Languages: + mainDict[lang.name] = {} + for section in textSections: + mainDict[lang.name][section] = {} + mainDict[lang.name]["Warnings"] = {} + mainDict[lang.name]["Errors"] = {} + + for row in currSheet.iterrows(): + #print(row) + for lang in Languages: + currRow = row[1] + #print(currRow) + offset = lang.value + if (pd.isna(currRow.iloc[FIRST_TRANSLATION_COL_INDEX + lang.value])): + offset = Languages.English.value + mainDict[lang.name][currRow.iloc[0]][currRow.iloc[1]] = {"bytes": currRow.iloc[FIRST_TRANSLATION_COL_INDEX + offset], + "numLines": currRow.iloc[2], + "pixelsPerChar": currRow.iloc[3], + "pixelsInLine" : currRow.iloc[4], + "includeBoxBreaks": currRow.iloc[5], + "includeScrolling": currRow.iloc[6], + } +def test_if_release(): + if (BUILD_TYPE == 'release'): + print("\tis release. Saving text file as release.xlsx") + shutil.copy(old_file_path, release_file_path) + +def generate_header_file(): + print("\tGenerating header file") + with open(TRANSLATED_H_PATH, 'w') as hFile: + hFile.write("// THIS FILE HAS BEEN GENERATED BY text_helper/main.py !\n\n#ifndef TRANSLATED_TEXT_H\n#define TRANSLATED_TEXT_H\n\n#include \n\n") + + sectionEnds = [] + index = 0 + lang = Languages.English # This doesn't matter, it just needs to be there. They're all the same + for section in textSections: + num = write_enum_to_header_file(hFile, section + "_", mainDict[lang.name][section]) + hFile.write("#define " + section + "_INDEX " + str(index)) + if(section == "PTGB"): + hFile.write(f"\n#define DIA_END {num}\n") + + hFile.write("/** Returns the LZ10 compressed " + section + " text table.*/\n") + sectionEnds.append(num) + index += 1 + + hFile.write("#define NUM_TEXT_SECTIONS " + str(index) + "\n") + hFile.write("const int text_section_lengths[] = {\n") + for end in sectionEnds: + hFile.write("\t" + str(end) + ",\n") + hFile.write("};\n\n") + + hFile.write("const u8* get_compressed_text_table(int table_index);\n") + + + hFile.write("\n#endif") + hFile.close() + +def generate_text_tables(): + print("\tGenerating text tables") + for lang in Languages: + for section in textSections: + table_file = os.curdir + '/to_compress/' + section + '_' + lang.name.lower() + '.bin' + write_text_bin_file(table_file, mainDict[lang.name][section], lang, section) + +def generate_cpp_file(): + print("\tGenerating cpp file") + with open(TRANSLATED_CPP_PATH, 'w') as cppFile: + cppFile.write("// THIS FILE HAS BEEN GENERATED BY text_helper/main.py !\n#include \"translated_text.h\"\n#include \"debug_mode.h\"\n") + # generate includes for each language + for lang in Languages: + for section in textSections: + cppFile.write("#include \"" + section.upper() + "_" + lang.name.lower() + "_lz10_bin.h\"\n") + + + cppFile.write("\nconst u8* get_compressed_text_table(int table_index)\n") + + for i, lang in enumerate(Languages): + cppFile.write(f"\n#{'el' if i > 0 else ''}if PTGB_BUILD_LANGUAGE == {lang.value + 1}\n") + cppFile.write("{\n") + cppFile.write("\tswitch (table_index)\n\t{\n") + for section in textSections: + cppFile.write("\tcase(" + section + "_INDEX):\n") + if(section == "PTGB"): + cppFile.write("\tdefault:\n") + cppFile.write("\t\treturn " + section + "_" + lang.name.lower() + "_lz10_bin;\n") + cppFile.write("\t\tbreak;\n") + cppFile.write("\t}\n") + cppFile.write("}\n") + cppFile.write(f"#else\n#error \"Unsupported PTGB_BUILD_LANGUAGE\"\n#endif") + +def output_json_file(): + print("\tOutputting json file") + for lang in Languages: + for section in textSections: + for item in mainDict[lang.name][section]: + string = mainDict[lang.name][section][item]["bytes"].split(" ") + outText = "" + arr = charArrayOfLanguage[lang]["array"] + for byte in string: + byte = arr[int(byte, 16)] + outText += str(byte) + mainDict[lang.name][section][item]["text"] = outText + + with open(OUTPUT_JSON_PATH, 'w') as jsonFile: + jsonFile.write(json.dumps(mainDict)) + + +# This is for the font generation +fontDir = os.curdir +BACKGROUND_PAL_INDEX = 0 +CELL_PAL_INDEX = 1 + +class Font: + def __init__(self, fileName, numColors, numChars, numCharsX, numCharsY, cellWidth, cellHeight, charWidth, charHeight): + self.fileName = fileName + self.numColors = numColors + self.numChars = numChars + self.numCharsX = numCharsX + self.numCharsY = numCharsY + self.cellWidth = cellWidth + self.cellHeight = cellHeight + self.charWidth = charWidth + self.charHeight = charHeight + + self.bpp = int(math.log(numColors, 2)) + 1 + self.numWords = self.numChars * self.cellWidth * self.cellHeight * self.bpp // (8 * 4) + self.numBytes = self.numWords * 4 + + self.charWordTable = [0] * self.numWords + self.charWidthTable = [0] * self.numBytes + +def build_h(): + print("Building font.h") + with open(FONTS_H_PATH, 'w') as f: + f.write(f'''#ifndef PTGB_BUILD_LANGUAGE +#error "PTGB_BUILD_LANGUAGE not defined" +#endif + +#include "debug_mode.h" +#include "pokemon_data.h" + +#ifndef __FONTS_H__ +#define __FONTS_H__''') + + + for myFont in fonts.values(): + f.write(f'''\n +#define {myFont.fileName}GlyphsLen {myFont.numBytes} +#define {myFont.fileName}WidthsLen {myFont.numChars}''') + + f.write(f'\n\nconst unsigned int {myFont.fileName}Glyphs[{myFont.numWords}] __attribute__((aligned(4)))=\n{{\n\t') + + for i in range(myFont.numWords): + f.write(f'{myFont.charWordTable[i]:#010x},') + if (i == myFont.numWords - 1): + f.write("\n};\n\n") + elif (i % 64 == 63): + f.write("\n\n\t") + elif (i % 8 == 7): + f.write("\n\t") + + f.write(f'const unsigned char {myFont.fileName}Widths[{myFont.numChars}] __attribute__((aligned(4)))=\n{{\n\t') + + for i in range(myFont.numChars): + f.write(f'{myFont.charWidthTable[i]:#04x}, ') + if (i == myFont.numChars - 1): + f.write("\n};\n\n") + elif (i % 128 == 127): + f.write("\n\n\t") + elif (i % 16 == 15): + f.write("\n\t") + + f.write(f'''const TFont {myFont.fileName}Font= +{{ + {myFont.fileName}Glyphs, + {myFont.fileName}Widths, + 0, // All heights are the same + 0, // Character offset, is set to zero + {myFont.numChars}, + {myFont.charWidth}, {myFont.charHeight}, + {myFont.cellWidth}, {myFont.cellHeight}, + {myFont.numBytes // myFont.numChars}, + {myFont.bpp}, + 0, // Padding, left blank +}};''') + + f.write('\n\n#endif') + f.close() + +def generate_tables(): + print("Generating font tables") + for myFont in fonts.values(): + print(f'\t{myFont.fileName}') + reader = png.Reader(f'{BASE_DIR}/fonts/{myFont.fileName}.png') + png_info = reader.read()[3] + palette = png_info.get('palette') + if (palette is None): + print("Error: Image file does not contain a palette") + exit() + + width, height, rows, info = reader.read() + pixels = list(rows) + + bitsPerWord = 32 + pixelsPerTileX = 8 + pixelsPerTileY = 8 + tilesPerCharX = myFont.cellWidth // pixelsPerTileX + tilesPerCharY = myFont.cellHeight // pixelsPerTileY + charsPerChartX = myFont.numCharsX + charsPerChartY = myFont.numCharsY + + globalX = 0 + globalY = 0 + bitTotal = 0 + + for charY in range(charsPerChartY): + for charX in range(charsPerChartX): + for tileX in range(tilesPerCharX): # Tiles go from top to bottom, then left to right + for tileY in range(tilesPerCharY): + for pixelY in range(pixelsPerTileY): + for pixelX in range(pixelsPerTileX): + + arrayIndex = bitTotal // bitsPerWord + bitIndex = bitTotal % bitsPerWord + + globalX = pixelX + (tileX * pixelsPerTileX) + (charX * tilesPerCharX * pixelsPerTileX) + globalY = pixelY + (tileY * pixelsPerTileY) + (charY * tilesPerCharY * pixelsPerTileY) + + val = (pixels[globalY][globalX] - 1) + if val < 0: + val = 0 + val &= myFont.bpp + myFont.charWordTable[arrayIndex] |= val << bitIndex + + #print(f'globalX: {globalX}, globalY: {globalY}, arrayIndex:{arrayIndex}, bitIndex:{bitIndex}, val:{val}') + bitTotal += myFont.bpp + + #print(f'{charX, charY}') + + myFont.charWidthTable[(charY * charsPerChartX) + charX] = (tilesPerCharX * pixelsPerTileX) + for x in range(tilesPerCharX * pixelsPerTileX): + globalX = x + (charX * tilesPerCharX * pixelsPerTileX) + globalY = 0 + (charY * tilesPerCharY * pixelsPerTileY) + #print(f'x: {globalX}, y: {globalY}') + if (pixels[globalY][globalX] == BACKGROUND_PAL_INDEX): + myFont.charWidthTable[(charY * charsPerChartX) + charX] = x + break + +mainDict = {} +textSections = [] +fonts = { + "International": Font("latin_normal", 1, 256, 16, 16, 16, 16, 16, 16), + "Japanese": Font("japanese_normal", 1, 256, 16, 16, 16, 16, 16, 16), +} +charArrays = { + "International": { + "array": [0] * 0x100, + "font": fonts["International"], + "escape": [ + ["{SCL}", [0xFA]], + ["{CLR}", [0xFB]], + ["{DEF}", [0xFC, 0x01, 0x02]], + ["{FEM}", [0xFC, 0x01, 0x04]], + ["{FPC}", [0xFC, 0x01, 0x06]], + ["{MLE}", [0xFC, 0x01, 0x08]], + ["{SPA}", [0xFC]], + ["{PLR}", [0xFD, 0x01]], + ["{NEW}", [0xFE]], + ["{END}", [0xFF]], + ] + }, + "Japanese": { + "array": [0] * 0x100, + "font": fonts["Japanese"], + "escape": [ + ["{SCL}", [0xFA]], + ["{CLR}", [0xFB]], + ["{DEF}", [0xFC, 0x06, 0x02]], + ["{FEM}", [0xFC, 0x06, 0x03]], # ??? + ["{MLE}", [0xFC, 0x06, 0x04]], + ["{SPA}", [0xFC]], + ["{FPC}", [0xFC, 0x06, 0x05]], + ["{PLR}", [0xFD, 0x01]], + ["{NEW}", [0xFE]], + ["{END}", [0xFF]], + ] + }, +} +charArrayOfLanguage = { + Languages.Japanese: charArrays["Japanese"], + Languages.English: charArrays["International"], + Languages.French: charArrays["International"], + Languages.German: charArrays["International"], + Languages.Italian: charArrays["International"], + Languages.SpanishEU: charArrays["International"], + Languages.SpanishLA: charArrays["International"], +} + +charConversionList = [ + # replaces the first char in the list with the latter + ["'", "’"], +] + +# Main +print("Running text_helper:") +generate_tables() +build_h() +download_xlsx_file() +test_if_release() +transfer_xlsx_to_dict() +generate_header_file() +generate_text_tables() +generate_cpp_file() +output_json_file() +print("text_helper finished!\n") diff --git a/vbalink.ini b/vbalink.ini deleted file mode 100644 index f76dd23..0000000 Binary files a/vbalink.ini and /dev/null differ