From b8b0dd25e442672c1b39db597f52fcb4dffef167 Mon Sep 17 00:00:00 2001 From: Philippe Symons Date: Tue, 11 Aug 2026 13:40:07 +0200 Subject: [PATCH] Integrate the pregenerated payload into mystery_gift_injector (WIP, untested) This commit integrates the pregenerated payload into mystery_gift_injector. It currently hardcodes the English Ruby v1.2 payload for testing purposes though. The next test I'll have to do is to see if the transfer process works with this specific rom. If it works, I can start integrating Pi's work in regards to delta patching using BPS. --- container.mk | 9 +- include/mystery_gift_builder.h | 349 ---- include/script_var.h | 87 - source/main.cpp | 1 - source/mystery_gift_builder.cpp | 1716 ----------------- source/mystery_gift_injector.cpp | 101 +- source/rom_data.cpp | 2 +- source/script_array.cpp | 2 +- source/script_var.cpp | 289 --- .../include/script_var.h | 1 + tools/gba-payload-generator/src/main.cpp | 120 +- .../src/mystery_gift_builder.cpp | 4 +- 12 files changed, 155 insertions(+), 2526 deletions(-) delete mode 100644 include/mystery_gift_builder.h delete mode 100644 include/script_var.h delete mode 100644 source/mystery_gift_builder.cpp delete mode 100644 source/script_var.cpp diff --git a/container.mk b/container.mk index 96771bc..d123cb3 100644 --- a/container.mk +++ b/container.mk @@ -76,9 +76,9 @@ HOST_ENV := env - \ # the makefile is found # #--------------------------------------------------------------------------------- -PTGB_PROJECT_NAME ?= $(notdir $(CURDIR)) -TARGET := $(PTGB_PROJECT_NAME)_mb -LOADERNAME := $(PTGB_PROJECT_NAME)_standalone +PTGB_PROJECT_NAME ?= $(notdir $(CURDIR)) +TARGET := $(PTGB_PROJECT_NAME)_mb +LOADERNAME := $(PTGB_PROJECT_NAME)_standalone BUILD := build GENERATED_DIR := $(BUILD)/generated SOURCES := source @@ -243,11 +243,13 @@ $(GENERATE_STAMP): compress_lz10.sh | data to_compress generated_dir @echo "----------------------------------------------------------------" @$(HOST_ENV) $(MAKE) -C tools/make-file-container @$(HOST_ENV) $(MAKE) -C tools/gb-payload-generator + @$(HOST_ENV) $(MAKE) -C tools/gba-payload-generator @echo @echo "----------------------------------------------------------------" @echo @find $(FILE_CONTAINERS) -name "*.containerdef" -print0 | xargs -0 -n1 tools/make-file-container/make-file-container -H $(BUILD) to_compress @find tools/text_helper/build -name "*.containerdef" -print0 | xargs -0 -n1 tools/make-file-container/make-file-container to_compress + tools/gba-payload-generator/gba-payload-generator to_compress/RSEFRLG.chunk0.bin data/ @echo "Compressing bin files!" @echo -n "[" @find to_compress -name "*.bin" -print0 | xargs -0 -n1 $(SRCDIR)/compress_lz10.sh @@ -281,6 +283,7 @@ clean: @echo clean ... @$(MAKE) -C tools/make-file-container clean @$(MAKE) -C tools/gb-payload-generator clean + @$(MAKE) -C tools/gba-payload-generator clean @$(MAKE) -C loader clean @$(MAKE) -C PCCS clean @rm -fr $(BUILD) $(TARGET).elf $(TARGET).gba $(LOADERNAME).gba data/ to_compress/ diff --git a/include/mystery_gift_builder.h b/include/mystery_gift_builder.h deleted file mode 100644 index acd57d2..0000000 --- a/include/mystery_gift_builder.h +++ /dev/null @@ -1,349 +0,0 @@ -#ifndef MYSTERY_GIFT_BUILDER_H -#define MYSTERY_GIFT_BUILDER_H - -#include -#include "dbg/debug_mode.h" -#include "ptgb_save_data_manager.h" -#include "script_var.h" -#include "pokemon_data.h" -#include "PokeBox.h" - -#define VIR_ADDRESS 0x08000000 -#define MG_SCRIPT_SIZE 0x3E8 -#define NPC_LOCATION_OFFSET 0x4 -#define READ_AS_THUMB 0x1 - -#define VAR_ID_START 0x8000 // This one should also stay consistant -#define VIRTUAL_ADDRESS 0x08000000 // This will also stay constant - -#define TEXT_KANTO 0 -#define TEXT_HOENN 1 - -#define COND_LESSTHAN 0 -#define COND_EQUALS 1 -#define COND_GREATERTHAN 2 -#define COND_LESSEQUALTHAN 3 -#define COND_GREATEREQUALTHAN 4 -#define COND_NOTEQUAL 5 -#define COND_FLAGTRUE 1 -#define COND_FLAGFALSE 5 - -#define r0 0b0000 -#define r1 0b0001 -#define r2 0b0010 -#define r3 0b0011 -#define r4 0b0100 -#define r5 0b0101 -#define r6 0b0110 -#define r7 0b0111 -#define r8 0b1000 -#define r9 0b1001 -#define r10 0b1010 -#define r11 0b1011 -#define r12 0b1100 -#define r13 0b1101 -#define r14 0b1110 -#define r15 0b1111 - -#define rlist_r0 0b000000001 -#define rlist_r1 0b000000010 -#define rlist_r2 0b000000101 -#define rlist_r3 0b000001001 -#define rlist_r4 0b000010001 -#define rlist_r5 0b000100001 -#define rlist_r6 0b001000001 -#define rlist_r7 0b010000001 -#define rlist_lr 0b100000000 - -// Each is two bytes, first is Hoenn, second is FRLG -#define MOVEMENT_ACTION_FACE_DOWN 0x0, 0x0 -#define MOVEMENT_ACTION_FACE_UP 0x1, 0x1 -#define MOVEMENT_ACTION_FACE_LEFT 0x2, 0x2 -#define MOVEMENT_ACTION_FACE_RIGHT 0x3, 0x3 -#define MOVEMENT_ACTION_WALK_SLOW_DOWN 0x4, 0xC -#define MOVEMENT_ACTION_WALK_SLOW_UP 0x5, 0xD -#define MOVEMENT_ACTION_WALK_SLOW_LEFT 0x6, 0xE -#define MOVEMENT_ACTION_WALK_SLOW_RIGHT 0x7, 0xF -#define MOVEMENT_ACTION_WALK_NORMAL_DOWN 0x8, 0x10 -#define MOVEMENT_ACTION_WALK_NORMAL_UP 0x9, 0x11 -#define MOVEMENT_ACTION_WALK_NORMAL_LEFT 0xA, 0x12 -#define MOVEMENT_ACTION_WALK_NORMAL_RIGHT 0xB, 0x13 -#define MOVEMENT_ACTION_JUMP_2_DOWN 0xC, 0x14 -#define MOVEMENT_ACTION_JUMP_2_UP 0xD, 0x15 -#define MOVEMENT_ACTION_JUMP_2_LEFT 0xE, 0x16 -#define MOVEMENT_ACTION_JUMP_2_RIGHT 0xF, 0x17 -#define MOVEMENT_ACTION_DELAY_1 0x10, 0x18 -#define MOVEMENT_ACTION_DELAY_2 0x11, 0x19 -#define MOVEMENT_ACTION_DELAY_4 0x12, 0x1A -#define MOVEMENT_ACTION_DELAY_8 0x13, 0x1B -#define MOVEMENT_ACTION_DELAY_16 0x14, 0x1C -#define MOVEMENT_ACTION_WALK_FAST_DOWN 0x15, 0x1D -#define MOVEMENT_ACTION_WALK_FAST_UP 0x16, 0x1E -#define MOVEMENT_ACTION_WALK_FAST_LEFT 0x17, 0x1F -#define MOVEMENT_ACTION_WALK_FAST_RIGHT 0x18, 0x20 -#define MOVEMENT_ACTION_WALK_IN_PLACE_SLOW_DOWN 0x19, 0x21 -#define MOVEMENT_ACTION_WALK_IN_PLACE_SLOW_UP 0x1A, 0x22 -#define MOVEMENT_ACTION_WALK_IN_PLACE_SLOW_LEFT 0x1B, 0x23 -#define MOVEMENT_ACTION_WALK_IN_PLACE_SLOW_RIGHT 0x1C, 0x24 -#define MOVEMENT_ACTION_WALK_IN_PLACE_NORMAL_DOWN 0x1D, 0x25 -#define MOVEMENT_ACTION_WALK_IN_PLACE_NORMAL_UP 0x1E, 0x26 -#define MOVEMENT_ACTION_WALK_IN_PLACE_NORMAL_LEFT 0x1F, 0x27 -#define MOVEMENT_ACTION_WALK_IN_PLACE_NORMAL_RIGHT 0x20, 0x28 -#define MOVEMENT_ACTION_WALK_IN_PLACE_FAST_DOWN 0x21, 0x29 -#define MOVEMENT_ACTION_WALK_IN_PLACE_FAST_UP 0x22, 0x2A -#define MOVEMENT_ACTION_WALK_IN_PLACE_FAST_LEFT 0x23, 0x2B -#define MOVEMENT_ACTION_WALK_IN_PLACE_FAST_RIGHT 0x24, 0x2C -#define MOVEMENT_ACTION_WALK_IN_PLACE_FASTER_DOWN 0x25, 0x2D -#define MOVEMENT_ACTION_WALK_IN_PLACE_FASTER_UP 0x26, 0x2E -#define MOVEMENT_ACTION_WALK_IN_PLACE_FASTER_LEFT 0x27, 0x2F -#define MOVEMENT_ACTION_WALK_IN_PLACE_FASTER_RIGHT 0x28, 0x30 -#define MOVEMENT_ACTION_RIDE_WATER_CURRENT_DOWN 0x29, 0x31 -#define MOVEMENT_ACTION_RIDE_WATER_CURRENT_UP 0x2A, 0x32 -#define MOVEMENT_ACTION_RIDE_WATER_CURRENT_LEFT 0x2B, 0x33 -#define MOVEMENT_ACTION_RIDE_WATER_CURRENT_RIGHT 0x2C, 0x34 -#define MOVEMENT_ACTION_WALK_FASTER_DOWN 0x2D, 0x35 -#define MOVEMENT_ACTION_WALK_FASTER_UP 0x2E, 0x36 -#define MOVEMENT_ACTION_WALK_FASTER_LEFT 0x2F, 0x37 -#define MOVEMENT_ACTION_WALK_FASTER_RIGHT 0x30, 0x38 -#define MOVEMENT_ACTION_SLIDE_DOWN 0x31, 0x39 -#define MOVEMENT_ACTION_SLIDE_UP 0x32, 0x3A -#define MOVEMENT_ACTION_SLIDE_LEFT 0x33, 0x3B -#define MOVEMENT_ACTION_SLIDE_RIGHT 0x34, 0x3C -#define MOVEMENT_ACTION_PLAYER_RUN_DOWN 0x35, 0x3D -#define MOVEMENT_ACTION_PLAYER_RUN_UP 0x36, 0x3E -#define MOVEMENT_ACTION_PLAYER_RUN_LEFT 0x37, 0x3F -#define MOVEMENT_ACTION_PLAYER_RUN_RIGHT 0x38, 0x40 -#define MOVEMENT_ACTION_START_ANIM_IN_DIRECTION 0x39, 0x45 -#define MOVEMENT_ACTION_JUMP_SPECIAL_DOWN 0x3A, 0x46 -#define MOVEMENT_ACTION_JUMP_SPECIAL_UP 0x3B, 0x47 -#define MOVEMENT_ACTION_JUMP_SPECIAL_LEFT 0x3C, 0x48 -#define MOVEMENT_ACTION_JUMP_SPECIAL_RIGHT 0x3D, 0x49 -#define MOVEMENT_ACTION_FACE_PLAYER 0x3E, 0x4A -#define MOVEMENT_ACTION_FACE_AWAY_PLAYER 0x3F, 0x4B -#define MOVEMENT_ACTION_LOCK_FACING_DIRECTION 0x40, 0x4C -#define MOVEMENT_ACTION_UNLOCK_FACING_DIRECTION 0x41, 0x4D -#define MOVEMENT_ACTION_JUMP_DOWN 0x42, 0x4E -#define MOVEMENT_ACTION_JUMP_UP 0x43, 0x4F -#define MOVEMENT_ACTION_JUMP_LEFT 0x44, 0x50 -#define MOVEMENT_ACTION_JUMP_RIGHT 0x45, 0x51 -#define MOVEMENT_ACTION_JUMP_IN_PLACE_DOWN 0x46, 0x52 -#define MOVEMENT_ACTION_JUMP_IN_PLACE_UP 0x47, 0x53 -#define MOVEMENT_ACTION_JUMP_IN_PLACE_LEFT 0x48, 0x54 -#define MOVEMENT_ACTION_JUMP_IN_PLACE_RIGHT 0x49, 0x55 -#define MOVEMENT_ACTION_JUMP_IN_PLACE_DOWN_UP 0x4A, 0x56 -#define MOVEMENT_ACTION_JUMP_IN_PLACE_UP_DOWN 0x4B, 0x57 -#define MOVEMENT_ACTION_JUMP_IN_PLACE_LEFT_RIGHT 0x4C, 0x58 -#define MOVEMENT_ACTION_JUMP_IN_PLACE_RIGHT_LEFT 0x4D, 0x59 -#define MOVEMENT_ACTION_FACE_ORIGINAL_DIRECTION 0x4E, 0x5A -#define MOVEMENT_ACTION_NURSE_JOY_BOW_DOWN 0x4F, 0x5B -#define MOVEMENT_ACTION_ENABLE_JUMP_LANDING_GROUND_EFFECT 0x50, 0x5C -#define MOVEMENT_ACTION_DISABLE_JUMP_LANDING_GROUND_EFFECT 0x51, 0x5D -#define MOVEMENT_ACTION_DISABLE_ANIMATION 0x52, 0x5E -#define MOVEMENT_ACTION_RESTORE_ANIMATION 0x53, 0x5F -#define MOVEMENT_ACTION_SET_INVISIBLE 0x54, 0x60 -#define MOVEMENT_ACTION_SET_VISIBLE 0x55, 0x61 -#define MOVEMENT_ACTION_EMOTE_EXCLAMATION_MARK 0x56, 0x62 -#define MOVEMENT_ACTION_EMOTE_QUESTION_MARK 0x57, 0x63 -#define MOVEMENT_ACTION_EMOTE_HEART 0x58, 0xFF -#define MOVEMENT_ACTION_REVEAL_TRAINER 0x59, 0x67 -#define MOVEMENT_ACTION_ROCK_SMASH_BREAK 0x5A, 0x68 -#define MOVEMENT_ACTION_CUT_TREE 0x5B, 0x69 -#define MOVEMENT_ACTION_SET_FIXED_PRIORITY 0x5C, 0x6A -#define MOVEMENT_ACTION_CLEAR_FIXED_PRIORITY 0x5D, 0x6B -#define MOVEMENT_ACTION_INIT_AFFINE_ANIM 0x5E, 0x6C -#define MOVEMENT_ACTION_CLEAR_AFFINE_ANIM 0x5F, 0x6D -#define MOVEMENT_ACTION_HIDE_REFLECTION 0x60, 0xFF -#define MOVEMENT_ACTION_SHOW_REFLECTION 0x61, 0xFF -#define MOVEMENT_ACTION_WALK_DOWN_START_AFFINE 0x62, 0x6E -#define MOVEMENT_ACTION_WALK_DOWN_AFFINE 0x63, 0x6F -#define MOVEMENT_ACTION_ACRO_WHEELIE_FACE_DOWN 0x64, 0x70 -#define MOVEMENT_ACTION_ACRO_WHEELIE_FACE_UP 0x65, 0x71 -#define MOVEMENT_ACTION_ACRO_WHEELIE_FACE_LEFT 0x66, 0x72 -#define MOVEMENT_ACTION_ACRO_WHEELIE_FACE_RIGHT 0x67, 0x73 -#define MOVEMENT_ACTION_ACRO_POP_WHEELIE_DOWN 0x68, 0x74 -#define MOVEMENT_ACTION_ACRO_POP_WHEELIE_UP 0x69, 0x75 -#define MOVEMENT_ACTION_ACRO_POP_WHEELIE_LEFT 0x6A, 0x76 -#define MOVEMENT_ACTION_ACRO_POP_WHEELIE_RIGHT 0x6B, 0x77 -#define MOVEMENT_ACTION_ACRO_END_WHEELIE_FACE_DOWN 0x6C, 0x78 -#define MOVEMENT_ACTION_ACRO_END_WHEELIE_FACE_UP 0x6D, 0x79 -#define MOVEMENT_ACTION_ACRO_END_WHEELIE_FACE_LEFT 0x6E, 0x7A -#define MOVEMENT_ACTION_ACRO_END_WHEELIE_FACE_RIGHT 0x6F, 0x7B -#define MOVEMENT_ACTION_ACRO_WHEELIE_HOP_FACE_DOWN 0x70, 0x7C -#define MOVEMENT_ACTION_ACRO_WHEELIE_HOP_FACE_UP 0x71, 0x7D -#define MOVEMENT_ACTION_ACRO_WHEELIE_HOP_FACE_LEFT 0x72, 0x7E -#define MOVEMENT_ACTION_ACRO_WHEELIE_HOP_FACE_RIGHT 0x73, 0x7F -#define MOVEMENT_ACTION_ACRO_WHEELIE_HOP_DOWN 0x74, 0x80 -#define MOVEMENT_ACTION_ACRO_WHEELIE_HOP_UP 0x75, 0x81 -#define MOVEMENT_ACTION_ACRO_WHEELIE_HOP_LEFT 0x76, 0x82 -#define MOVEMENT_ACTION_ACRO_WHEELIE_HOP_RIGHT 0x77, 0x83 -#define MOVEMENT_ACTION_ACRO_WHEELIE_JUMP_DOWN 0x78, 0x84 -#define MOVEMENT_ACTION_ACRO_WHEELIE_JUMP_UP 0x79, 0x85 -#define MOVEMENT_ACTION_ACRO_WHEELIE_JUMP_LEFT 0x7A, 0x86 -#define MOVEMENT_ACTION_ACRO_WHEELIE_JUMP_RIGHT 0x7B, 0x87 -#define MOVEMENT_ACTION_ACRO_WHEELIE_IN_PLACE_DOWN 0x7C, 0x88 -#define MOVEMENT_ACTION_ACRO_WHEELIE_IN_PLACE_UP 0x7D, 0x89 -#define MOVEMENT_ACTION_ACRO_WHEELIE_IN_PLACE_LEFT 0x7E, 0x8A -#define MOVEMENT_ACTION_ACRO_WHEELIE_IN_PLACE_RIGHT 0x7F, 0x8B -#define MOVEMENT_ACTION_ACRO_POP_WHEELIE_MOVE_DOWN 0x80, 0x8C -#define MOVEMENT_ACTION_ACRO_POP_WHEELIE_MOVE_UP 0x81, 0x8D -#define MOVEMENT_ACTION_ACRO_POP_WHEELIE_MOVE_LEFT 0x82, 0x8E -#define MOVEMENT_ACTION_ACRO_POP_WHEELIE_MOVE_RIGHT 0x83, 0x8F -#define MOVEMENT_ACTION_ACRO_WHEELIE_MOVE_DOWN 0x84, 0x90 -#define MOVEMENT_ACTION_ACRO_WHEELIE_MOVE_UP 0x85, 0x91 -#define MOVEMENT_ACTION_ACRO_WHEELIE_MOVE_LEFT 0x86, 0x92 -#define MOVEMENT_ACTION_ACRO_WHEELIE_MOVE_RIGHT 0x87, 0x93 -#define MOVEMENT_ACTION_ACRO_END_WHEELIE_MOVE_DOWN 0x88, 0xFF -#define MOVEMENT_ACTION_ACRO_END_WHEELIE_MOVE_UP 0x89, 0xFF -#define MOVEMENT_ACTION_ACRO_END_WHEELIE_MOVE_LEFT 0x8A, 0xFF -#define MOVEMENT_ACTION_ACRO_END_WHEELIE_MOVE_RIGHT 0x8B, 0xFF -#define MOVEMENT_ACTION_WALK_NORMAL_DIAGONAL_UP_LEFT 0x8C, 0xFF -#define MOVEMENT_ACTION_WALK_NORMAL_DIAGONAL_UP_RIGHT 0x8D, 0xFF -#define MOVEMENT_ACTION_WALK_NORMAL_DIAGONAL_DOWN_LEFT 0x8E, 0xFF -#define MOVEMENT_ACTION_WALK_NORMAL_DIAGONAL_DOWN_RIGHT 0x8F, 0xFF -#define MOVEMENT_ACTION_WALK_SLOW_DIAGONAL_UP_LEFT 0x90, 0xFF -#define MOVEMENT_ACTION_WALK_SLOW_DIAGONAL_UP_RIGHT 0x91, 0xFF -#define MOVEMENT_ACTION_WALK_SLOW_DIAGONAL_DOWN_LEFT 0x92, 0xFF -#define MOVEMENT_ACTION_WALK_SLOW_DIAGONAL_DOWN_RIGHT 0x93, 0xFF -#define MOVEMENT_ACTION_LOCK_ANIM 0x94, 0xFF -#define MOVEMENT_ACTION_UNLOCK_ANIM 0x95, 0xFF -#define MOVEMENT_ACTION_WALK_LEFT_AFFINE 0x96, 0xFF -#define MOVEMENT_ACTION_WALK_RIGHT_AFFINE 0x97, 0xFF -#define MOVEMENT_ACTION_LEVITATE 0x98, 0xFF -#define MOVEMENT_ACTION_STOP_LEVITATE 0x99, 0xFF -#define MOVEMENT_ACTION_STOP_LEVITATE_AT_TOP 0x9A, 0xFF -#define MOVEMENT_ACTION_FIGURE_8 0x9B, 0xFF -#define MOVEMENT_ACTION_FLY_UP 0x9C, 0xA4 -#define MOVEMENT_ACTION_FLY_DOWN 0x9D, 0xA5 -#define MOVEMENT_ACTION_FACE_DOWN_FAST 0xFF, 0x4 -#define MOVEMENT_ACTION_FACE_UP_FAST 0xFF, 0x5 -#define MOVEMENT_ACTION_FACE_LEFT_FAST 0xFF, 0x6 -#define MOVEMENT_ACTION_FACE_RIGHT_FAST 0xFF, 0x7 -#define MOVEMENT_ACTION_WALK_SLOWER_DOWN 0xFF, 0x8 -#define MOVEMENT_ACTION_WALK_SLOWER_UP 0xFF, 0x9 -#define MOVEMENT_ACTION_WALK_SLOWER_LEFT 0xFF, 0xA -#define MOVEMENT_ACTION_WALK_SLOWER_RIGHT 0xFF, 0xB -#define MOVEMENT_ACTION_PLAYER_RUN_DOWN_SLOW 0xFF, 0x41 -#define MOVEMENT_ACTION_PLAYER_RUN_UP_SLOW 0xFF, 0x42 -#define MOVEMENT_ACTION_PLAYER_RUN_LEFT_SLOW 0xFF, 0x43 -#define MOVEMENT_ACTION_PLAYER_RUN_RIGHT_SLOW 0xFF, 0x44 -#define MOVEMENT_ACTION_EMOTE_X 0xFF, 0x64 -#define MOVEMENT_ACTION_EMOTE_DOUBLE_EXCL_MARK 0xFF, 0x65 -#define MOVEMENT_ACTION_EMOTE_SMILE 0xFF, 0x66 -#define MOVEMENT_ACTION_SPIN_DOWN 0xFF, 0x94 -#define MOVEMENT_ACTION_SPIN_UP 0xFF, 0x95 -#define MOVEMENT_ACTION_SPIN_LEFT 0xFF, 0x96 -#define MOVEMENT_ACTION_SPIN_RIGHT 0xFF, 0x97 -#define MOVEMENT_ACTION_RAISE_HAND_AND_STOP 0xFF, 0x98 -#define MOVEMENT_ACTION_RAISE_HAND_AND_JUMP 0xFF, 0x99 -#define MOVEMENT_ACTION_RAISE_HAND_AND_SWIM 0xFF, 0x9A -#define MOVEMENT_ACTION_WALK_SLOWEST_DOWN 0xFF, 0x9B -#define MOVEMENT_ACTION_WALK_SLOWEST_UP 0xFF, 0x9C -#define MOVEMENT_ACTION_WALK_SLOWEST_LEFT 0xFF, 0x9D -#define MOVEMENT_ACTION_WALK_SLOWEST_RIGHT 0xFF, 0x9E -#define MOVEMENT_ACTION_SHAKE_HEAD_OR_WALK_IN_PLACE 0xFF, 0x9F -#define MOVEMENT_ACTION_GLIDE_DOWN 0xFF, 0xA0 -#define MOVEMENT_ACTION_GLIDE_UP 0xFF, 0xA1 -#define MOVEMENT_ACTION_GLIDE_LEFT 0xFF, 0xA2 -#define MOVEMENT_ACTION_GLIDE_RIGHT 0xFF, 0xA3 -#define MOVEMENT_ACTION_JUMP_SPECIAL_WITH_EFFECT_DOWN 0xFF, 0xA6 -#define MOVEMENT_ACTION_JUMP_SPECIAL_WITH_EFFECT_UP 0xFF, 0xA7 -#define MOVEMENT_ACTION_JUMP_SPECIAL_WITH_EFFECT_LEFT 0xFF, 0xA8 -#define MOVEMENT_ACTION_JUMP_SPECIAL_WITH_EFFECT_RIGHT 0xFF, 0xA9 - -#define CPU_SET_16BIT 0x00000000 -#define CPU_SET_32BIT 0x04000000 -class mystery_gift_script -{ - int curr_mg_index = 0; - int curr_section30_index = 0; - u8 *save_section_30; - u8 mg_script[MG_SCRIPT_SIZE]; - u8 value_buffer[9]; - u8 four_align_value; - -public: - /** - * @brief Construct a new mystery gift script object - * - * @param save_section_30_buffer This needs to be a 4KB buffer to store the section 30 data. - * It was done this way to pass the global_memory_buffer to this class, thereby saving IWRAM. - * - * Be careful of what you do with this buffer after running build_script(). - * Especially if you're using global_memory_buffer! - * You're in control! - */ - mystery_gift_script(u8 *save_section_30_buffer); - void build_script(PokeBox *box); - //void build_script_old(Pokemon_Party &incoming_box_data); - const u8 *get_script() const; - const u8 * get_section30() const; - u32 calc_checksum32(); - u16 calc_crc16(); - -private: - void add_command(int len); - u16 rev_endian(u16 num); - void add_asm(u16 command); - void init_npc_location(u8 bank, u8 map, u8 npc); - void add_word(u32 word); - - // Scripting commands - void setvirtualaddress(u32 location); - void lock(); - void faceplayer(); - void checkflag(u16 flag_id); - void virtualgotoif(u8 condition, u32 location); - void virtualmsgbox(u32 location); - void waitmsg(); - void waitkeypress(); - void setvar(u16 var_id, u16 value); - void copybyte(u32 destination, u32 source); - void addvar(u16 var_id, u16 value); - void subvar(u16 var_id, u16 value); - void call(u32 script_ptr); - void compare(u16 var_id, u16 value); - void setflag(u16 flag_id); - void fanfare(u16 fanfare_number); - void waitfanfare(); - void special(u16 special_id); - void callstd(u8 function_index); - void release(); - void end(); - void killscript(); - void spritebehave(u16 objectID, u8 behaviorType); - void spriteface(u16 npc, u8 direction); - void waitmovement(u16 npc); - void doanimation(u16 animation); - void applymovement(u16 npc, u32 movements); - void callASM(u32 script_ptr); - void loadpointer(u8 destinationBank, u32 value); - void setMapLayoutIndex(u16 footer); - void fadeScreen(u8 effect); - void setMetaTile(u16 x, u16 y, u16 metaTileId, u16 impassible); - void playse(u16 soundId); - void writebytetooffset(u8 byte, u32 offset); - void waitse(); - - void msgboxMacro(u32 location); - void changeSpriteMacro(u8 npcId, u32 spriteTablePtr); - void changePaletteMacro(u8 npcId, u8 palNum); - - // ASM commands - void push(u16 register_list); - void ldr3(u8 rd, u8 immed_8); - void ldr1(u8 rd, u8 rn, u8 immed_5); - void add5(u8 rd, u8 immed_8); - void add3(u8 rm, u8 rn, u8 rd); - void mov3(u8 rm, u8 rd); - void add2(u8 rd, u8 immed_8); - void bx(u8 rm); - void str1(u8 immed_5, u8 rn, u8 rd); - void pop(u16 register_list); - void mov1(u8 rd, u8 immed_8); - void and1(u8 rd, u8 rm); - void ldr2(u8 rd, u8 rn, u8 rm); - void strh(u8 rd, u8 rn, u8 immed_5); - void swi(u8 immed_8); -}; - -#endif diff --git a/include/script_var.h b/include/script_var.h deleted file mode 100644 index b0745a2..0000000 --- a/include/script_var.h +++ /dev/null @@ -1,87 +0,0 @@ -#include -#include "libstd_replacements.h" -#include "rom_data.h" - -class script_var -{ -public: - script_var(u32 nValue, ptgb::vector &var_list_ref, int *nCurr_loc_ptr); - script_var(ptgb::vector &var_list_ref, int *nCurr_loc_ptr); - virtual void fill_refrences(u8 mg_array_ptr[]); // goes through all the script locations and updates them to point to the start - virtual void set_start(); // Add a pointer to where the start is - u32 place_word(); // Place the value in memory - int *curr_loc_ptr; - u32 value; - ptgb::vector location_list; // stores all the locations in the script that need to be updated - u32 start_location_in_script; -}; - -class asm_var : public script_var -{ -public: - using script_var::script_var; - void set_start(); // Add a pointer to where the start is - void set_start(bool nIsDirect); // Add a pointer to where the start is - u8 add_reference(); // Add a location for the variable to be refrenced in the script - u8 add_reference(int nCommand_offset); // Add a location for the variable to be refrenced in the script - void fill_refrences(u8 mg_array_ptr[]); // goes through all the script locations and updates them to point to the start - u32 get_loc_in_sec30(); - bool isDirect; -}; - -class xse_var : public script_var -{ -public: - using script_var::script_var; - int command_offset; // The amount of bytes in the command before the variable - xse_var *refrence_var; // The offset from a different location in the script. Used to point to functions through addition/subtraction - bool has_reference_var; - void set_start(); // Add a pointer to where the start is - u8 add_reference(int nCommand_offset); // Add a location for the variable to be refrenced in the script - u8 add_reference(int nCommand_offset, xse_var *offset_from); - void fill_refrences(u8 mg_array_ptr[]); // goes through all the script locations and updates them to point to the start - u32 get_loc_in_sec30(); -}; - -class textbox_var : public xse_var -{ -public: - using xse_var::xse_var; - void set_text(const byte nText[]); - void insert_text(const u16 *charset, u8 mg_array[], bool should_set_virtual_start = false); - void set_start(); - void set_virtual_start(); - const byte *text; - int text_length; -}; - -class movement_var : public xse_var -{ -public: - using xse_var::xse_var; - void set_movement(const byte movement[], unsigned int nSize); - void insert_movement(u8 mg_array[]); - void set_start(); - const byte *movement; - unsigned int size; -}; - -class sprite_var : public xse_var -{ -public: - using xse_var::xse_var; - void insert_sprite_data(u8 mg_array[], const unsigned int sprite_array[], unsigned int size, const unsigned short palette_array[]); - void set_start(); -}; - -class music_var : public xse_var -{ -public: - using xse_var::xse_var; - void insert_music_data(u8 mg_array[], u8 blockCount, u8 priority, u8 reverb, u32 toneDataPointer); - void set_start(); - void add_track(const byte* trackBytes, size_t trackSize); - int numTracks; - ptgb::vector trackPointers; - ptgb::vector> trackArrays; -}; diff --git a/source/main.cpp b/source/main.cpp index 964ad7d..d7dfa16 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -22,7 +22,6 @@ #include "pkmn_font.h" #include "ptgb_save_data_manager.h" #include "mystery_gift_injector.h" -#include "mystery_gift_builder.h" #include "multiboot_upload.h" #include "rom_data.h" #include "libraries/Pokemon-Gen3-to-Gen-X/include/save.h" diff --git a/source/mystery_gift_builder.cpp b/source/mystery_gift_builder.cpp deleted file mode 100644 index 5953bb4..0000000 --- a/source/mystery_gift_builder.cpp +++ /dev/null @@ -1,1716 +0,0 @@ -#include -#include "libstd_replacements.h" -#include "mystery_gift_builder.h" -#include "pokemon_data.h" -#include "rom_data.h" -#include "translated_text.h" -#include "FileContainerReader.h" -#include "text_tables.h" - -#define MG_SCRIPT false -#define S30_SCRIPT true - -extern rom_data curr_GBA_rom; -bool asm_payload_location; - -// These are static variables -int var_call_check_flag = (VAR_ID_START + 0x04); -int var_call_return_2 = (VAR_ID_START + 0x05); -int var_box_return = (VAR_ID_START + 0x06); -int var_dex_seen_caught = (VAR_ID_START + 0x07); -int var_index = (VAR_ID_START + 0x09); -int var_pkmn_offset = (VAR_ID_START + 0x0A); - -// These values will be defined once we recieve the ROM pointers -int ptr_call_check_flag; -int ptr_call_return_2; -int ptr_box_return; -int ptr_dex_seen_caught; -int ptr_index; -int ptr_pkmn_offset; - -// TODO: For old script, can be removed later -int ptr_callASM; -int ptr_script_ptr_low; -int ptr_script_ptr_high; -int ptr_call_return_1; -int ptr_block_ptr_low; -int ptr_block_ptr_high; -int var_callASM = (VAR_ID_START + 0x00); -int var_script_ptr_low = (VAR_ID_START + 0x01); -int var_script_ptr_high = (VAR_ID_START + 0x02); -int var_call_return_1 = (VAR_ID_START + 0x03); - -// the below structs and union are a scheme to reuse stack (IWRAM) memory of the -// PokemonTables instance for storing decompressed text data once it's no longer needed. -// The reason is that depending on the optimization level (-O0 specifically), the compiler may not do so automatically -// if you'd use anonymous scopes for that purpose. -// Having a union forces this behaviour. - -// this struct is used to hold the PokemonTables data -// within the decompressed_store union -struct decompressed_data_tables -{ - // This is about 3,4 KB - PokemonTables data; -}; - -// this struct is used to hold decompressed text data -// within the decompressed_store union -struct decompressed_text_data -{ - // the buffer is specifically chosen to be -at least- the size of PokemonTables - // to ensure that writing to gen3_charset_eng FROM the PokemonTables instance of the - // union doesn't overwrite said instance during the copy - - // Increasing the size to 4096 since that is the smallest size allowed by the table reader. - //u8 buffer[sizeof(PokemonTables)]; - u8 buffer[4096]; - u16 gen3_charset[256]; -}; - -// This union is used to hold the PokemonTables data on the stack when it's needed, -// and reclaim the memory for decompressed text data when it's not. -union decompressed_data_storage_union -{ - decompressed_data_tables tables; - decompressed_text_data text; - - // constructor and destructor are needed to make the compiler stop complaining - // about the decompressed_data_tables struct not being trivial - decompressed_data_storage_union() {} - ~decompressed_data_storage_union() {} -}; - -mystery_gift_script::mystery_gift_script(u8 *save_section_30_buffer) - : curr_mg_index(NPC_LOCATION_OFFSET), curr_section30_index(0), save_section_30(save_section_30_buffer), mg_script(), value_buffer(), four_align_value(0) -{ - ptr_call_check_flag = (curr_GBA_rom.loc_gSpecialVar_0x8000 + 0x08); - ptr_call_return_2 = (curr_GBA_rom.loc_gSpecialVar_0x8000 + 0x0A); - ptr_box_return = (curr_GBA_rom.loc_gSpecialVar_0x8000 + 0x0C); - ptr_dex_seen_caught = (curr_GBA_rom.loc_gSpecialVar_0x8000 + 0x0E); - ptr_index = (curr_GBA_rom.loc_gSpecialVar_0x8000 + 0x12); - ptr_pkmn_offset = (curr_GBA_rom.loc_gSpecialVar_0x8000 + 0x14); - - // TODO: For old script, can be removed later - ptr_callASM = (curr_GBA_rom.loc_gSpecialVar_0x8000 + 0x00); - ptr_script_ptr_low = (curr_GBA_rom.loc_gSpecialVar_0x8000 + 0x02); - ptr_script_ptr_high = (curr_GBA_rom.loc_gSpecialVar_0x8000 + 0x04); - ptr_call_return_1 = (curr_GBA_rom.loc_gSpecialVar_0x8000 + 0x06); - ptr_block_ptr_low = (curr_GBA_rom.loc_gSaveBlock1PTR + 0x00); - ptr_block_ptr_high = (curr_GBA_rom.loc_gSaveBlock1PTR + 0x02); -} - -void mystery_gift_script::build_script(PokeBox *box) -{ - decompressed_data_storage_union decompressed_store; - const u8 **rsefrlgTableChunkList; - u32 rsefrlgNumChunks; - u32 rsefrlgChunkSize; - - // in order to safely use getPointerToFileInDecompressionBuffer() in FileContainerReader - // we must ensure that the table fits inside a single chunk - get_text_table_chunks(RSEFRLG_INDEX, &rsefrlgTableChunkList, &rsefrlgNumChunks, &rsefrlgChunkSize); - FileContainerReader rsefrlgTableReader(rsefrlgTableChunkList, rsefrlgNumChunks, rsefrlgChunkSize); - - ptgb::vector mg_variable_list; - ptgb::vector sec30_variable_list; - - asm_var sendMonToPC_ptr(curr_GBA_rom.loc_sendMonToPC + READ_AS_THUMB, sec30_variable_list, &curr_section30_index); - asm_var returned_box_success_ptr(ptr_box_return, sec30_variable_list, &curr_section30_index); - asm_var curr_pkmn_index_ptr(ptr_pkmn_offset, sec30_variable_list, &curr_section30_index); - asm_var setPokedexFlag_ptr(curr_GBA_rom.loc_setPokedexFlag + READ_AS_THUMB, sec30_variable_list, &curr_section30_index); - asm_var dexSeenCaught_ptr(ptr_dex_seen_caught, sec30_variable_list, &curr_section30_index); - asm_var currPkmnIndex_ptr(ptr_index, sec30_variable_list, &curr_section30_index); - asm_var pkmnStruct(curr_GBA_rom.loc_gSaveDataBuffer, sec30_variable_list, &curr_section30_index); - asm_var dexStruct(curr_GBA_rom.loc_gSaveDataBuffer + (MAX_PKMN_IN_BOX * POKEMON_SIZE), sec30_variable_list, &curr_section30_index); - asm_var m4aMPlayStop_ptr(curr_GBA_rom.loc_m4aMPlayStop + READ_AS_THUMB, sec30_variable_list, &curr_section30_index); - asm_var gMPlayInfo_BGM_ptr(curr_GBA_rom.loc_gMPlayInfo_BGM, sec30_variable_list, &curr_section30_index); - asm_var gMPlayInfo_SE2_ptr(curr_GBA_rom.loc_gMPlayInfo_SE2, sec30_variable_list, &curr_section30_index); - asm_var MPlayStart_ptr(curr_GBA_rom.loc_MPlayStart + READ_AS_THUMB, sec30_variable_list, &curr_section30_index); - asm_var CreateFanfareTask_ptr(curr_GBA_rom.loc_CreateFanfareTask + READ_AS_THUMB, sec30_variable_list, &curr_section30_index); - asm_var sFanfareCounter_ptr(curr_GBA_rom.loc_sFanfareCounter, sec30_variable_list, &curr_section30_index); - asm_var gPlttBufferFaded_ptr(curr_GBA_rom.loc_gPlttBufferFaded + (32 * 0x1A), sec30_variable_list, &curr_section30_index); // 0x1A is the pallet number - asm_var copySizeControl(CPU_SET_32BIT | ((32) / (32 / 8) & 0x1FFFFF), sec30_variable_list, &curr_section30_index); // CPU_SET_32BIT | ((size)/(32/8) & 0x1FFFFF) - - asm_var flashBuffer_ptr(curr_GBA_rom.loc_gSaveDataBuffer, mg_variable_list, &curr_mg_index); - asm_var readFlashSector_ptr(curr_GBA_rom.loc_readFlashSector + READ_AS_THUMB, mg_variable_list, &curr_mg_index); - - asm_var mainAsmStart(sec30_variable_list, &curr_section30_index); - asm_var dexAsmStart(sec30_variable_list, &curr_section30_index); - asm_var customSoundASM(sec30_variable_list, &curr_section30_index); - asm_var loadPalette(sec30_variable_list, &curr_section30_index); - asm_var loadSec30(mg_variable_list, &curr_mg_index); - - xse_var jumpLoop(mg_variable_list, &curr_mg_index); - xse_var jumpBoxFull(mg_variable_list, &curr_mg_index); - xse_var jumpPkmnCollected(mg_variable_list, &curr_mg_index); - xse_var jumpAllCollected(mg_variable_list, &curr_mg_index); - xse_var jumpNotInWay(mg_variable_list, &curr_mg_index); - xse_var jumpNotToSide(mg_variable_list, &curr_mg_index); - xse_var jumpNotToSideFull(mg_variable_list, &curr_mg_index); - - textbox_var textGreet(mg_variable_list, &curr_mg_index); - textbox_var textYouMustBe(mg_variable_list, &curr_mg_index); - textbox_var textIAm(mg_variable_list, &curr_mg_index); - - textbox_var textReceived(sec30_variable_list, &curr_section30_index); - textbox_var textPCFull(sec30_variable_list, &curr_section30_index); - textbox_var textThank(sec30_variable_list, &curr_section30_index); - textbox_var textTest(sec30_variable_list, &curr_section30_index); - textbox_var textWeHere(sec30_variable_list, &curr_section30_index); - textbox_var textPCConvo(sec30_variable_list, &curr_section30_index); - textbox_var textPCThanks(sec30_variable_list, &curr_section30_index); - textbox_var textLookerFull(sec30_variable_list, &curr_section30_index); - textbox_var textMoveBox(sec30_variable_list, &curr_section30_index); - - movement_var movementSlowSpin(sec30_variable_list, &curr_section30_index); - movement_var movementFastSpin(sec30_variable_list, &curr_section30_index); - movement_var movementExclaim(sec30_variable_list, &curr_section30_index); - movement_var movementToBoxes(sec30_variable_list, &curr_section30_index); - movement_var movementWalkBack(sec30_variable_list, &curr_section30_index); - movement_var movementLookDown(sec30_variable_list, &curr_section30_index); - movement_var movementOutOfWay(sec30_variable_list, &curr_section30_index); - movement_var movementInWay(sec30_variable_list, &curr_section30_index); - movement_var movementGoUp(sec30_variable_list, &curr_section30_index); - movement_var movementGoDown(sec30_variable_list, &curr_section30_index); - - sprite_var spriteLooker(sec30_variable_list, &curr_section30_index); - - music_var songLooker(sec30_variable_list, &curr_section30_index); - - // This determines if the event has been done before - bool first_time = true; - for (int i = 1; i <= 251; i++) - { - if (is_caught(i)) - { - first_time = false; - break; - } - } - - // Note that each MOVEMENT macro contains TWO bytes, one for Hoenn and one for FRLG. - static const byte movementSlowSpinArray[32] = { - MOVEMENT_ACTION_FACE_LEFT, - MOVEMENT_ACTION_DELAY_8, - MOVEMENT_ACTION_FACE_UP, - MOVEMENT_ACTION_DELAY_8, - MOVEMENT_ACTION_FACE_RIGHT, - MOVEMENT_ACTION_DELAY_8, - MOVEMENT_ACTION_FACE_DOWN, - MOVEMENT_ACTION_DELAY_8, - MOVEMENT_ACTION_FACE_LEFT, - MOVEMENT_ACTION_DELAY_8, - MOVEMENT_ACTION_FACE_UP, - MOVEMENT_ACTION_DELAY_8, - MOVEMENT_ACTION_FACE_RIGHT, - MOVEMENT_ACTION_DELAY_8, - MOVEMENT_ACTION_FACE_DOWN, - MOVEMENT_ACTION_DELAY_8, - }; - movementSlowSpin.set_movement(movementSlowSpinArray, 16); - - static const byte movementFastSpinArray[60] = { - MOVEMENT_ACTION_FACE_LEFT, - MOVEMENT_ACTION_DELAY_4, - MOVEMENT_ACTION_FACE_UP, - MOVEMENT_ACTION_DELAY_4, - MOVEMENT_ACTION_FACE_RIGHT, - MOVEMENT_ACTION_DELAY_4, - MOVEMENT_ACTION_FACE_DOWN, - MOVEMENT_ACTION_DELAY_4, - MOVEMENT_ACTION_FACE_LEFT, - MOVEMENT_ACTION_DELAY_4, - MOVEMENT_ACTION_FACE_UP, - MOVEMENT_ACTION_DELAY_4, - MOVEMENT_ACTION_FACE_RIGHT, - MOVEMENT_ACTION_DELAY_4, - MOVEMENT_ACTION_FACE_DOWN, - MOVEMENT_ACTION_DELAY_4, - MOVEMENT_ACTION_FACE_LEFT, - MOVEMENT_ACTION_DELAY_4, - MOVEMENT_ACTION_FACE_UP, - MOVEMENT_ACTION_DELAY_4, - MOVEMENT_ACTION_FACE_RIGHT, - MOVEMENT_ACTION_DELAY_4, - MOVEMENT_ACTION_FACE_DOWN, - MOVEMENT_ACTION_DELAY_4, - MOVEMENT_ACTION_FACE_LEFT, - MOVEMENT_ACTION_DELAY_4, - MOVEMENT_ACTION_FACE_UP, - MOVEMENT_ACTION_DELAY_4, - MOVEMENT_ACTION_FACE_RIGHT, - MOVEMENT_ACTION_DELAY_4, - }; - movementFastSpin.set_movement(movementFastSpinArray, 30); - - static const byte movementExclaimArray[2] = {MOVEMENT_ACTION_EMOTE_EXCLAMATION_MARK}; - movementExclaim.set_movement(movementExclaimArray, 1); - - static const byte movementToBoxesArrayRS[8] = {MOVEMENT_ACTION_WALK_FAST_UP, MOVEMENT_ACTION_WALK_FAST_LEFT, MOVEMENT_ACTION_WALK_FAST_UP, MOVEMENT_ACTION_EMOTE_EXCLAMATION_MARK}; - static const byte movementToBoxesArrayFRLG[6] = {MOVEMENT_ACTION_WALK_FAST_UP, MOVEMENT_ACTION_WALK_FAST_UP, MOVEMENT_ACTION_EMOTE_EXCLAMATION_MARK}; - static const byte movementToBoxesArrayE[12] = {MOVEMENT_ACTION_WALK_FAST_UP, MOVEMENT_ACTION_WALK_FAST_LEFT, MOVEMENT_ACTION_WALK_FAST_LEFT, MOVEMENT_ACTION_WALK_FAST_LEFT, MOVEMENT_ACTION_FACE_UP, MOVEMENT_ACTION_EMOTE_EXCLAMATION_MARK}; - - static const byte movementWalkBackArrayRS[6] = {MOVEMENT_ACTION_WALK_FAST_DOWN, MOVEMENT_ACTION_WALK_FAST_RIGHT, MOVEMENT_ACTION_WALK_FAST_DOWN}; - static const byte movementWalkBackArrayFRLG[4] = {MOVEMENT_ACTION_WALK_FAST_DOWN, MOVEMENT_ACTION_WALK_FAST_DOWN}; - static const byte movementWalkBackArrayE[8] = {MOVEMENT_ACTION_WALK_FAST_RIGHT, MOVEMENT_ACTION_WALK_FAST_RIGHT, MOVEMENT_ACTION_WALK_FAST_RIGHT, MOVEMENT_ACTION_WALK_FAST_DOWN}; - - switch (curr_GBA_rom.gamecode) - { - case RUBY_ID: - case SAPPHIRE_ID: - movementToBoxes.set_movement(movementToBoxesArrayRS, 4); - movementWalkBack.set_movement(movementWalkBackArrayRS, 3); - break; - case FIRERED_ID: - case LEAFGREEN_ID: - movementToBoxes.set_movement(movementToBoxesArrayFRLG, 3); - movementWalkBack.set_movement(movementWalkBackArrayFRLG, 2); - break; - case EMERALD_ID: - movementToBoxes.set_movement(movementToBoxesArrayE, 6); - movementWalkBack.set_movement(movementWalkBackArrayE, 4); - break; - } - - static const byte movementLookDownArray[2] = {MOVEMENT_ACTION_FACE_DOWN}; - movementLookDown.set_movement(movementLookDownArray, 1); - - static const byte movementOutOfWayArray[4] = {MOVEMENT_ACTION_WALK_FAST_RIGHT, MOVEMENT_ACTION_FACE_LEFT}; - movementOutOfWay.set_movement(movementOutOfWayArray, 2); - - static const byte movementInWayArray[4] = {MOVEMENT_ACTION_WALK_FAST_LEFT, MOVEMENT_ACTION_FACE_DOWN}; - movementInWay.set_movement(movementInWayArray, 2); - - static const byte movementGoUpArray[2] = {MOVEMENT_ACTION_WALK_FAST_UP}; - movementGoUp.set_movement(movementGoUpArray, 1); - - static const byte movementGoDownArray[4] = {MOVEMENT_ACTION_WALK_FAST_DOWN, MOVEMENT_ACTION_FACE_UP}; - movementGoDown.set_movement(movementGoDownArray, 2); - - // const byte track_1[] = {0xBC, 0x00, 0xBB, 0x38, 0xBD, 0x38, 0xC4, 0x00, 0xBE, 0x60, 0xBF, 0x3D, 0xC0, 0x40, 0xD4, 0x51, 0x70, 0x86, 0xD4, 0x8C, 0x53, 0x86, 0xD4, 0x8C, 0x54, 0x86, 0xD4, 0x92, 0xE8, 0x55, 0x92, 0xBE, 0x64, 0x82, 0x6C, 0x84, 0x74, 0x85, 0xB1}; - // songLooker.add_track(track_1, sizeof(track_1)); - - const byte track_2[] = {0xBC, 0x00, 0xBD, 0x38, 0xC4, 0x00, 0xBE, 0x60, 0xBF, 0x46, 0xC0, 0x40, 0x83, 0xD4, 0x51, 0x3C, 0x86, 0xD4, 0x8C, 0x53, 0x86, 0xD4, 0x8C, 0x54, 0x86, 0xD4, 0x92, 0xE8, 0x55, 0x99, 0x81, 0xB1}; - songLooker.add_track(track_2, sizeof(track_2)); - - const byte track_3[] = {0xBC, 0x00, 0xBD, 0x38, 0xC4, 0x00, 0xBF, 0x34, 0xBE, 0x6E, 0xC0, 0x40, 0xD4, 0x3C, 0x70, 0x86, 0xD4, 0x8C, 0x3B, 0x86, 0xD4, 0x8C, 0x3C, 0x86, 0xD4, 0x92, 0xEA, 0x3D, 0x9B, 0x83, 0xB1}; - songLooker.add_track(track_3, sizeof(track_3)); - - const byte track_4[] = {0xBC, 0x00, 0xBD, 0x38, 0xC4, 0x00, 0xBF, 0x34, 0xBE, 0x6E, 0xC0, 0x40, 0xD4, 0x39, 0x70, 0x86, 0xD4, 0x8C, 0x36, 0x86, 0xD4, 0x8C, 0x37, 0x86, 0xD4, 0x92, 0xEA, 0x39, 0x9B, 0x83, 0xB1}; - songLooker.add_track(track_4, sizeof(track_4)); - - const byte track_5[] = {0xBC, 0x00, 0xBD, 0x38, 0xC4, 0x00, 0xBF, 0x34, 0xBE, 0x6E, 0xC0, 0x40, 0xD4, 0x34, 0x70, 0x86, 0xD4, 0x8C, 0x32, 0x86, 0xD4, 0x8C, 0x34, 0x86, 0xD4, 0x92, 0xEA, 0x37, 0x9B, 0x83, 0xB1}; - songLooker.add_track(track_5, sizeof(track_5)); - - // const byte track_6[] = {0xBC, 0x00, 0xBD, 0x3C, 0xC4, 0x00, 0xBF, 0x58, 0xBE, 0x3B, 0xC0, 0x40, 0xD4, 0x40, 0x70, 0x86, 0xD4, 0x8C, 0x42, 0x86, 0xD4, 0x8C, 0x43, 0x86, 0xD4, 0x92, 0xE8, 0x99, 0x81, 0xB1}; - // songLooker.add_track(track_6, sizeof(track_6)); - - // const byte track_7[] = {0xBC, 0x00, 0xBD, 0x18, 0xC4, 0x00, 0xBE, 0x48, 0xBF, 0x1E, 0xC0, 0x40, 0xA0, 0xD0, 0x43, 0x70, 0x86, 0x45, 0x8C, 0x46, 0x8C, 0x45, 0x86, 0x47, 0x86, 0x49, 0x81, 0xB1}; - // songLooker.add_track(track_7, sizeof(track_7)); - - unsigned char instrument; - switch (curr_GBA_rom.gamecode) - { - case RUBY_ID: - case SAPPHIRE_ID: - instrument = 0x24; - break; - case FIRERED_ID: - case LEAFGREEN_ID: - instrument = 0x3E; - break; - case EMERALD_ID: - default: - instrument = 0x26; - break; - }; - - const byte track_instrument_1[] = {0xBC, 0x00, 0xBD, instrument, 0xC4, 0x00, 0xBE, 0x7F, 0xBF, 0x40, 0xC0, 0x40, 0xD4, 0x21, 0x70, 0x86, 0xD4, 0x8C, 0x20, 0x86, 0xD4, 0x8C, 0x1F, 0x86, 0xDA, 0x8C, 0xD4, 0x2D, 0x86, 0x21, 0x8C, 0xD4, 0x86, 0xD4, 0x8C, 0xD4, 0x85, 0xB1}; - songLooker.add_track(track_instrument_1, sizeof(track_instrument_1)); - - // const byte track_unused[] = {0xBC, 0x00, 0xBD, 0x7E, 0xC4, 0x00, 0xBE, 0x53, 0xBF, 0x40, 0xD4, 0x24, 0x70, 0x8C, 0xD4, 0x98, 0x32, 0x86, 0xD4, 0x86, 0x30, 0x86, 0xD4, 0x86, 0xD4, 0x86, 0xD4, 0x86, 0x2D, 0x86, 0xD4, 0x86, 0xD4, 0x86, 0xD4, 0x85, 0xB1}; - // songLooker.add_track(track_unused, sizeof(track_unused)); - - u8 dex_nums[MAX_PKMN_IN_BOX] = {}; - - // placement new is required to run the constructor of PokemonTables for the decompressed_store's instance - // it won't get called automatically because it's part of the union (and neither will the destructor) - new (&decompressed_store.tables.data) PokemonTables(); - - // TODO make it so that the table is added here(?) - box->setTable(&decompressed_store.tables.data); - box->convertAll(); - for (int i = 0; i < box->getNumInBox(); i++) // Add in the Pokemon data - { - Gen3Pokemon *curr_pkmn = box->getGen3Pokemon(i); - if (curr_pkmn->isValid) - { - for (int j = 0; j < POKEMON_SIZE; j++) - { - *(save_section_30 + curr_section30_index + j) = curr_pkmn->dataArrayPtr[j]; - } - // memcpy(save_section_30 + curr_section30_index, curr_pkmn->dataArrayPtr, POKEMON_SIZE); - - curr_section30_index += POKEMON_SIZE; - dex_nums[i] = curr_pkmn->getSpeciesIndexNumber(); - } - else - { - curr_section30_index += POKEMON_SIZE; - } - } - // the PokemonTables instance is no longer needed, but we do need to keep the english gen3 charset around - // for our insert_text() calls - decompressed_store.tables.data.load_gen3_charset(ENGLISH); - // we specifically defined the decompressed_text_data struct to ensure the memcpy shouldn't overlap - memcpy(decompressed_store.text.gen3_charset, decompressed_store.tables.data.gen3_charset, sizeof(decompressed_store.text.gen3_charset)); - // calling the destructor is nothing more than a formality for our PokemonTables class, - // but let's do it anyway for the sake of being explicit after having used placement new - decompressed_store.tables.data.~PokemonTables(); - - // Add in the dex numbers - memcpy(save_section_30 + curr_section30_index, dex_nums, MAX_PKMN_IN_BOX); - curr_section30_index += MAX_PKMN_IN_BOX; - - // insert text - - // Ş = Wait for button and scroll text - // ȼ = Wait for button and clear text - // Ȇ = Escape character - // À = Change text color - // Ç = Red - // É = Green - // Ë = Blue - // Ʋ = Variable escape sequence - // À = Player name - // Ň = New line - // ƞ = string terminator - - // 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 - rsefrlgTableReader.init(decompressed_store.text.buffer, sizeof(decompressed_store.text.buffer)); - switch (curr_GBA_rom.gamecode) - { - case RUBY_ID: - textGreet.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textGreet_rse)); - textMoveBox.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textMoveBox_rs)); - textWeHere.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textWeHere_rs)); - textReceived.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textRecieved_rs)); - textIAm.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(first_time ? RSEFRLG_dia_textIAm_first_rs : RSEFRLG_dia_textIAm_second_rs)); - textPCConvo.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textPCConvo_rs)); // ȼDon’t worry ƲÀ,Ňyou won’t have to do a thing!"); - textPCThanks.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textPCThanks_rs)); - textThank.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textThank_rs)); - textPCFull.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textPCFull_rs)); - textLookerFull.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textLookerFull_rs)); - break; - case SAPPHIRE_ID: - textGreet.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textGreet_rse)); - textMoveBox.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textMoveBox_rs)); - textWeHere.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textWeHere_rs)); - textReceived.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textRecieved_rs)); - textIAm.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(first_time ? RSEFRLG_dia_textIAm_first_rs : RSEFRLG_dia_textIAm_second_rs)); - textPCConvo.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textPCConvo_rs)); // ȼDon’t worry ƲÀ,Ňyou won’t have to do a thing!"); - textPCThanks.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textPCThanks_rs)); - textThank.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textThank_rs)); - textPCFull.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textPCFull_rs)); - textLookerFull.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textLookerFull_rs)); - break; - case FIRERED_ID: - case LEAFGREEN_ID: - textGreet.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textGreet_frlg)); - textMoveBox.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textMoveBox_frlg)); - textWeHere.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textWeHere_frlg)); - textReceived.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textRecieved_frlge)); - textIAm.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(first_time ? RSEFRLG_dia_textIAm_first_frlge : RSEFRLG_dia_textIAm_second_frlge)); - textPCConvo.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textPCConvo_frlge)); // ȼDon’t worry ƲÀ,Ňyou won’t have to do a thing!"); - textPCThanks.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textPCThanks_frlge)); - textThank.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textThank_frlge)); - textPCFull.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textPCFull_frlge)); - textLookerFull.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textLookerFull_frlge)); - break; - case EMERALD_ID: - textGreet.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textGreet_rse)); - textMoveBox.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textMoveBox_e)); - textWeHere.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textWeHere_e)); - textReceived.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textRecieved_frlge)); - textIAm.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(first_time ? RSEFRLG_dia_textIAm_first_frlge : RSEFRLG_dia_textIAm_second_frlge)); - textPCConvo.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textPCConvo_frlge)); // ȼDon’t worry ƲÀ,Ňyou won’t have to do a thing!"); - textPCThanks.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textPCThanks_frlge)); - textThank.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textThank_frlge)); - textPCFull.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textPCFull_frlge)); - textLookerFull.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textLookerFull_frlge)); - break; - } - // Split these between rs and frlge - textReceived.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textRecieved_frlge)); - textYouMustBe.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(first_time ? RSEFRLG_dia_textYouMustBe_first : RSEFRLG_dia_textYouMustBe_second)); - textIAm.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(first_time ? RSEFRLG_dia_textIAm_first_frlge : RSEFRLG_dia_textIAm_second_frlge)); - textPCConvo.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textPCConvo_frlge)); // ȼDon’t worry ƲÀ,Ňyou won’t have to do a thing!"); - textPCThanks.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textPCThanks_frlge)); - textThank.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textThank_frlge)); - textPCFull.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textPCFull_frlge)); - textLookerFull.set_text(rsefrlgTableReader.getPointerToFileInDecompressionBuffer(RSEFRLG_dia_textLookerFull_frlge)); - - textThank.insert_text(decompressed_store.text.gen3_charset, save_section_30); - textPCFull.insert_text(decompressed_store.text.gen3_charset, save_section_30); - textWeHere.insert_text(decompressed_store.text.gen3_charset, save_section_30); - textPCConvo.insert_text(decompressed_store.text.gen3_charset, save_section_30); - textPCThanks.insert_text(decompressed_store.text.gen3_charset, save_section_30); - textLookerFull.insert_text(decompressed_store.text.gen3_charset, save_section_30); - textMoveBox.insert_text(decompressed_store.text.gen3_charset, save_section_30); - textReceived.insert_text(decompressed_store.text.gen3_charset, save_section_30); - - movementSlowSpin.insert_movement(save_section_30); - movementFastSpin.insert_movement(save_section_30); - movementExclaim.insert_movement(save_section_30); - movementToBoxes.insert_movement(save_section_30); - movementWalkBack.insert_movement(save_section_30); - movementLookDown.insert_movement(save_section_30); - movementOutOfWay.insert_movement(save_section_30); - movementInWay.insert_movement(save_section_30); - movementGoUp.insert_movement(save_section_30); - movementGoDown.insert_movement(save_section_30); - - while (curr_section30_index % 4 != 0) - { - curr_section30_index++; // Align the code so that it is byte aligned - } - - songLooker.insert_music_data(save_section_30, 0, 0, 0, curr_GBA_rom.loc_voicegroup); - - asm_var customSong(songLooker.get_loc_in_sec30(), sec30_variable_list, &curr_section30_index); - asm_var customSongDuration(119, sec30_variable_list, &curr_section30_index); - - while (curr_section30_index % 4 != 0) - { - curr_section30_index++; // Align the code so that it is byte aligned - } - -#include "lookerFRLG.h" -#include "lookerRSE.h" - if (curr_GBA_rom.is_hoenn()) - { - spriteLooker.insert_sprite_data(save_section_30, lookerRSETiles, 256, lookerRSEPal); - } - else - { - spriteLooker.insert_sprite_data(save_section_30, lookerFRLGTiles, 256, lookerFRLGPal); - } - asm_var paletteData(curr_GBA_rom.loc_gSaveDataBuffer + (curr_section30_index - 32), sec30_variable_list, &curr_section30_index); - - asm_payload_location = S30_SCRIPT; - - mainAsmStart.set_start(false); // Set the memory pointer location for ASM start - push(rlist_lr); // save the load register to the stack - ldr3(r3, curr_pkmn_index_ptr.add_reference()); // set r3 to the pointer to the pokemon index variable - ldr1(r3, r3, 0); // set r3 to the value in memory r3 points to - add5(r0, pkmnStruct.add_reference()); // set r0 to a pointer to the start of the Pokemon struct. - ldr1(r0, r0, 0); // set r0 to the value in memory r0 points to - add3(r0, r0, r3); // add r3 to r0, giving it the correct offset for the current index - ldr3(r1, sendMonToPC_ptr.add_reference()); // set r1 to the location of "SendMonToPC" plus one, since it is thumb code - mov3(r2, r15); // move r15 (the program counter) to r2 - add2(r2, 5); // add 5 to r2 to compensate for the four following bytes, plus to tell the system to read as thumb code - mov3(r14, r2); // move r2 into r14 (the load register) - bx(r1); // jump to the pointer stored in r1 (SendMonToPC) - ldr3(r2, returned_box_success_ptr.add_reference()); // load variable 0x8006's pointer into r2 - str1(r0, r2, 0); // put the value of r0 into the memory location pointed at by r2, plus 0 - pop(rlist_r0); // remove r0 from the stack and put it into r0 - bx(r0); // jump to r0 (return to where the function was called) - while (curr_section30_index % 4 != 0) - { - curr_section30_index++; // Align the code so that it is byte aligned - } - - add_word(curr_pkmn_index_ptr.place_word()); // the location of variable "0x8008" (the pokemon offset) - add_word(pkmnStruct.place_word()); // the location of the Pokemon Struct - add_word(sendMonToPC_ptr.place_word()); // the location of "SendMonToPC", plus one (so it is interpreted as thumb code) - add_word(returned_box_success_ptr.place_word()); // the location of variable "0x8006" (the return value) - - dexAsmStart.set_start(false); // Note the location where the Dex ASM starts - push(rlist_lr); // save the load register to the stack - ldr3(r0, currPkmnIndex_ptr.add_reference()); // load the pointer to the index variable into r0 - ldr1(r0, r0, 0); // load the value at r0's pointer - mov1(r3, 0xFF); // load 0xFF into r3 - and1(r0, r3); // AND r0 and r3, which will give us just the least significant byte - add5(r1, dexStruct.add_reference()); // set r1 to the value stored X bytes ahead - ldr1(r1, r1, 0); // loda the value at the memory location stored in r1 - add3(r0, r0, r1); // add r0 and r1, which is the current index and dex_struct respectivly - ldr1(r0, r0, 0); // load the value at the memory location stored in r0 - and1(r0, r3); // truncate to just the least significant byte, which is the current dex number - ldr3(r1, dexSeenCaught_ptr.add_reference()); // load the dex_seen_caught variable's pointer into r1 - ldr1(r1, r1, 0); // load the value of memory pointed at by r1 - and1(r1, r3); // AND r1 and r3, which will keep only the least significant byte - ldr3(r2, setPokedexFlag_ptr.add_reference()); // load the GetSetPokedexFlag function location into r2 - mov3(r3, r15); // move r15 (the program counter) to r3 - add2(r3, 5); // add 5 to r3 to compensate for the four following bytes, as well as to tell it to read as THUMB code - mov3(r14, r3); // move r3 into r14 (the load register) - bx(r2); // jump to the pointer stored in r2 (GetSetPokedexFlag) - pop(rlist_r0); // remove r0 from the stack and put it into r0 - bx(r0); // jump to r0 (return to where the function was called) - while (curr_section30_index % 4 != 0) - { - curr_section30_index++; // Align the code so that it is byte aligned - } - add_word(currPkmnIndex_ptr.place_word()); // the location of the INDEX variable - add_word(dexStruct.place_word()); // the location of the dex struct - add_word(dexSeenCaught_ptr.place_word()); // the location of the DEX_SEEN_CAUGHT variable - add_word(setPokedexFlag_ptr.place_word()); // the location of GetSetPokedexFlag, plus one (so it is interpreted as thumb code) - - customSoundASM.set_start(false); // Note the location where the custom sound ASM starts - push(rlist_lr); // save the load register to the stack - ldr3(r0, gMPlayInfo_BGM_ptr.add_reference()); // load the gMPlayInfo_BGM function location into r0 - ldr3(r2, m4aMPlayStop_ptr.add_reference()); // load the m4aMPlayStop location into r2 - mov3(r3, r15); // move r15 (the program counter) to r3 - add2(r3, 5); // add 5 to r3 to compensate for the four following bytes, as well as to tell it to read as THUMB code - mov3(r14, r3); // move r3 into r14 (the load register) - bx(r2); // jump to the pointer stored in r2 (m4aMPlayStop) - ldr3(r0, sFanfareCounter_ptr.add_reference()); // load the sFanfareCounter_ptr function location into r0 - ldr3(r1, customSongDuration.add_reference()); // load the custom song duration into r1 - strh(r1, r0, 0); // Load the value into memory - ldr3(r0, gMPlayInfo_SE2_ptr.add_reference()); // load the gMPlayInfo_SE2 function location into r0 - ldr3(r1, customSong.add_reference()); // load the custom song location into r1 - ldr3(r2, MPlayStart_ptr.add_reference()); // load the m4aMPlayStop location into r2 - mov3(r3, r15); // move r15 (the program counter) to r3 - add2(r3, 5); // add 5 to r3 to compensate for the four following bytes, as well as to tell it to read as THUMB code - mov3(r14, r3); // move r3 into r14 (the load register) - bx(r2); // jump to the pointer stored in r2 (MPlayStart) - ldr3(r2, CreateFanfareTask_ptr.add_reference()); // load the m4aMPlayStop location into r2 - mov3(r3, r15); // move r15 (the program counter) to r3 - add2(r3, 5); // add 5 to r3 to compensate for the four following bytes, as well as to tell it to read as THUMB code - mov3(r14, r3); // move r3 into r14 (the load register) - bx(r2); // jump to the pointer stored in r2 (MPlayStart) - pop(rlist_r0); // remove r0 from the stack and put it into r0 - bx(r0); // jump to r0 (return to where the function was called) - while (curr_section30_index % 4 != 0) - { - curr_section30_index++; // Align the code so that it is byte aligned - } - add_word(m4aMPlayStop_ptr.place_word()); // the location of the INDEX variable - add_word(gMPlayInfo_BGM_ptr.place_word()); // the location of the dex struct - add_word(gMPlayInfo_SE2_ptr.place_word()); - add_word(MPlayStart_ptr.place_word()); - add_word(CreateFanfareTask_ptr.place_word()); - add_word(sFanfareCounter_ptr.place_word()); - add_word(customSong.place_word()); - add_word(customSongDuration.place_word()); - - loadPalette.set_start(false); // Note the location where the custom sound ASM starts - push(rlist_lr); // save the load register to the stack - ldr3(r0, paletteData.add_reference()); // load the paletteData location into r0 - ldr3(r1, gPlttBufferFaded_ptr.add_reference()); // load the gPlttBufferFaded location into r1 - ldr3(r2, copySizeControl.add_reference()); // load the copySizeControl location into r2 - mov3(r3, r15); // move r15 (the program counter) to r3 - add2(r3, 5); // add 5 to r3 to compensate for the four following bytes, as well as to tell it to read as THUMB code - mov3(r14, r3); // move r3 into r14 (the load register) - swi(0x0B); // Call the CpuSet SWI for copying data (CpuCopy16) - pop(rlist_r0); // remove r0 from the stack and put it into r0 - bx(r0); // jump to r0 (return to where the function was called) - while (curr_section30_index % 4 != 0) - { - curr_section30_index++; // Align the code so that it is byte aligned - } - add_word(paletteData.place_word()); - add_word(gPlttBufferFaded_ptr.place_word()); - add_word(copySizeControl.place_word()); - - // The start of the Mystery Gift Script - - asm_payload_location = MG_SCRIPT; - // Located at 0x?8A8 in the .sav - init_npc_location(curr_GBA_rom.map_bank, curr_GBA_rom.map_id, curr_GBA_rom.npc_id); // Set the location of the NPC - setvirtualaddress(VIRTUAL_ADDRESS); // Set virtual address - if (curr_GBA_rom.gamecode == RUBY_ID || curr_GBA_rom.gamecode == SAPPHIRE_ID) - { - callASM(loadSec30.add_reference(1)); - } - else - { - callASM(curr_GBA_rom.loc_loadSaveSection30 + READ_AS_THUMB); // Load save section 30 into saveDataBuffer - } - lock(); // Lock the player - faceplayer(); // Have the NPC face the player - virtualmsgbox(textGreet.add_reference(1)); // Start the dialouge - waitmsg(); - waitkeypress(); - applymovement(curr_GBA_rom.npc_id, movementExclaim.get_loc_in_sec30()); - playse(0x15); - waitse(); - waitmovement(curr_GBA_rom.npc_id); - virtualmsgbox(textYouMustBe.add_reference(1)); - waitmsg(); - waitkeypress(); - applymovement(curr_GBA_rom.npc_id, movementSlowSpin.get_loc_in_sec30()); - waitmovement(curr_GBA_rom.npc_id); - applymovement(curr_GBA_rom.npc_id, movementFastSpin.get_loc_in_sec30()); - waitmovement(curr_GBA_rom.npc_id); - changeSpriteMacro(1, spriteLooker.get_loc_in_sec30()); - callASM(loadPalette.get_loc_in_sec30()); - changePaletteMacro(curr_GBA_rom.npc_id, 0xA); - applymovement(curr_GBA_rom.npc_id, movementLookDown.get_loc_in_sec30()); - callASM(customSoundASM.get_loc_in_sec30()); - waitfanfare(); - virtualmsgbox(textIAm.add_reference(1)); - waitmsg(); - waitkeypress(); - changeSpriteMacro(1, curr_GBA_rom.loc_sPicTable_NPC); - changePaletteMacro(curr_GBA_rom.npc_id, curr_GBA_rom.npc_palette); - applymovement(curr_GBA_rom.npc_id, movementFastSpin.get_loc_in_sec30()); - waitmovement(curr_GBA_rom.npc_id); - applymovement(curr_GBA_rom.npc_id, movementSlowSpin.get_loc_in_sec30()); - waitmovement(curr_GBA_rom.npc_id); - faceplayer(); - msgboxMacro(textWeHere.get_loc_in_sec30()); - compare(0x800C, 1); // 0x800C == SpecialVar_Facing - virtualgotoif(COND_NOTEQUAL, jumpNotInWay.add_reference(2)); - applymovement(0xFF, movementOutOfWay.get_loc_in_sec30()); - waitmovement(0xFF); - jumpNotInWay.set_start(); - applymovement(curr_GBA_rom.npc_id, movementToBoxes.get_loc_in_sec30()); - waitmovement(curr_GBA_rom.npc_id); - playse(0x15); - waitse(); - msgboxMacro(textMoveBox.get_loc_in_sec30()); - fadeScreen(1); - switch (curr_GBA_rom.gamecode) - { - case RUBY_ID: - case SAPPHIRE_ID: - setMetaTile(3, 1, 4, 1); - setMetaTile(3, 0, 515, 0); - break; - case FIRERED_ID: - case LEAFGREEN_ID: - setMetaTile(4, 1, 98, 0); - setMetaTile(2, 1, 385, 1); - setMetaTile(2, 2, 386, 0); - break; - case EMERALD_ID: - setMetaTile(3, 1, 4, 1); - setMetaTile(3, 2, 566, 1); - setMetaTile(1, 1, 531, 1); - setMetaTile(1, 2, 539, 0); - applymovement(curr_GBA_rom.npc_id, movementGoUp.get_loc_in_sec30()); - break; - } - special(curr_GBA_rom.special_DrawWholeMapView); - switch (curr_GBA_rom.gamecode) - { - case RUBY_ID: - case SAPPHIRE_ID: - playse(0x2C); - break; - case FIRERED_ID: - case LEAFGREEN_ID: - case EMERALD_ID: - playse(0xC); - break; - } - waitse(); - fadeScreen(0); - switch (curr_GBA_rom.gamecode) - { - case RUBY_ID: - case SAPPHIRE_ID: - setMetaTile(3, 1, 5, 1); - break; - case FIRERED_ID: - case LEAFGREEN_ID: - setMetaTile(4, 1, 99, 0); - break; - case EMERALD_ID: - setMetaTile(3, 1, 5, 1); - break; - } - special(curr_GBA_rom.special_DrawWholeMapView); - playse(0x2); - waitse(); - msgboxMacro(textPCConvo.get_loc_in_sec30()); - // -- POKEMON INJECTION START-- - setvar(var_index, 0); // set the index to 0 - setvar(var_pkmn_offset, 0); // Set the Pokemon struct offset to 0 - setvar(var_call_check_flag, rev_endian(0x2B00)); // Set the variable to 0x2B. 0x2B = CHECK FLAG - addvar(var_call_check_flag, rev_endian(curr_GBA_rom.pkmn_collected_flag_start)); // Add the starting flag ID (plus one to ignore the is collected flag) to the check flag ASM variable - setvar(var_call_return_2, rev_endian(0x0003)); // Set the variable to 0x03. 0x03 = RETURN - jumpLoop.set_start(); // Set the jump destination for the JUMP_LOOP - call(ptr_call_check_flag); // Call the check flag ASM - virtualgotoif(COND_FLAGFALSE, jumpPkmnCollected.add_reference(2)); // If the "pokemon collected" flag is false, jump to the end of the loop - callASM(mainAsmStart.get_loc_in_sec30()); // Call SendMonToPC ASM - compare(var_box_return, 2); // Compare the resulting return to #2 - virtualgotoif(COND_EQUALS, jumpBoxFull.add_reference(2)); // If the return value was #2, jump to the box full message - setvar(var_dex_seen_caught, 2); // set the seen caught variable to 2, so that the Pokemon is set to "seen" - callASM(dexAsmStart.get_loc_in_sec30()); // call "PTR_DEX_START" - addvar(var_dex_seen_caught, 1); // add 1 to the seen caught variable so that the Pokemon will be "Caught" - callASM(dexAsmStart.get_loc_in_sec30()); // Call "PTR_DEX_START" again - jumpPkmnCollected.set_start(); // Set the jump destination for if the Pokemon has already been collected - addvar(var_pkmn_offset, POKEMON_SIZE); // Add the size of one Pokmeon to the Pokemon offset - addvar(var_index, 1); // Add one to the index - addvar(var_call_check_flag, rev_endian(1)); // Add one to the flag index - compare(var_index, MAX_PKMN_IN_BOX); // Compare the index to 30 - virtualgotoif(COND_LESSTHAN, jumpLoop.add_reference(2)); // if index is less than six, jump to the start of the loop - setflag(curr_GBA_rom.all_collected_flag); // Set the "all collected" flag - fanfare(257); // Play the received fanfare - msgboxMacro(textReceived.get_loc_in_sec30()); // Display the recieved text - waitfanfare(); // Wait for the fanfare - - // -- POKEMON INJECTION END -- - jumpAllCollected.set_start(); // Set the destination for if all the Pokemon have already been collected - msgboxMacro(textPCThanks.get_loc_in_sec30()); // Display the thank text - switch (curr_GBA_rom.gamecode) - { - case RUBY_ID: - case SAPPHIRE_ID: - setMetaTile(3, 1, 4, 1); - break; - case FIRERED_ID: - case LEAFGREEN_ID: - setMetaTile(4, 1, 98, 0); - break; - case EMERALD_ID: - setMetaTile(3, 1, 4, 0); - break; - } - special(curr_GBA_rom.special_DrawWholeMapView); - playse(0x3); - waitse(); - fadeScreen(1); - // Place the PC and boxes - switch (curr_GBA_rom.gamecode) - { - case RUBY_ID: - case SAPPHIRE_ID: - setMetaTile(3, 1, 661, 1); - setMetaTile(3, 0, 653, 0); - break; - case FIRERED_ID: - case LEAFGREEN_ID: - setMetaTile(4, 1, 385, 1); - setMetaTile(2, 1, 272, 1); - setMetaTile(2, 2, 273, 0); - break; - case EMERALD_ID: - setMetaTile(3, 1, 577, 1); - setMetaTile(3, 2, 539, 1); - setMetaTile(1, 1, 525, 1); - setMetaTile(1, 2, 566, 0); - applymovement(curr_GBA_rom.npc_id, movementGoDown.get_loc_in_sec30()); - break; - } - special(curr_GBA_rom.special_DrawWholeMapView); - switch (curr_GBA_rom.gamecode) - { - case RUBY_ID: - case SAPPHIRE_ID: - playse(0x2C); - break; - case FIRERED_ID: - case LEAFGREEN_ID: - case EMERALD_ID: - playse(0xC); - break; - } - waitse(); - fadeScreen(0); - applymovement(curr_GBA_rom.npc_id, movementWalkBack.get_loc_in_sec30()); - waitmovement(curr_GBA_rom.npc_id); - compare(0x800C, 1); // 0x800C == SpecialVar_Facing - virtualgotoif(COND_NOTEQUAL, jumpNotToSide.add_reference(2)); - applymovement(0xFF, movementInWay.get_loc_in_sec30()); - waitmovement(0xFF); - jumpNotToSide.set_start(); - faceplayer(); - msgboxMacro(textThank.get_loc_in_sec30()); - release(); // Release the player - killscript(); // Erase RAMscript - - // -- BOX IS FULL TEXT -- - jumpBoxFull.set_start(); // Set the destination for if the box is full - msgboxMacro(textPCFull.get_loc_in_sec30()); // Display the thank text - setMetaTile(4, 1, 98, 0); - special(curr_GBA_rom.special_DrawWholeMapView); - playse(0x3); - waitse(); - fadeScreen(1); - // Place the PC - setMetaTile(4, 1, 385, 1); - // Place the boxes - setMetaTile(2, 1, 272, 1); - setMetaTile(2, 2, 273, 0); - special(curr_GBA_rom.special_DrawWholeMapView); - switch (curr_GBA_rom.gamecode) - { - case RUBY_ID: - case SAPPHIRE_ID: - playse(0x2C); - break; - case FIRERED_ID: - case LEAFGREEN_ID: - case EMERALD_ID: - playse(0xC); - break; - } - waitse(); - fadeScreen(0); - applymovement(curr_GBA_rom.npc_id, movementWalkBack.get_loc_in_sec30()); - waitmovement(curr_GBA_rom.npc_id); - compare(0x800C, 1); // 0x800C == SpecialVar_Facing - virtualgotoif(COND_NOTEQUAL, jumpNotToSideFull.add_reference(2)); - applymovement(0xFF, movementInWay.get_loc_in_sec30()); - waitmovement(0xFF); - jumpNotToSideFull.set_start(); - faceplayer(); - msgboxMacro(textLookerFull.get_loc_in_sec30()); - release(); // Release the player - end(); // End the script - - while (curr_mg_index % 4 != 0) - { - curr_mg_index++; // Align the code so that it is byte aligned - } - loadSec30.set_start(true); - push(rlist_lr); // save the load register to the stack - mov1(r0, 30); // set r0 to 30 (the sector ID for eReader data) - ldr3(r1, flashBuffer_ptr.add_reference()); // set r1 to the location of "flashBuffer" plus one, since it is thumb code - ldr3(r2, readFlashSector_ptr.add_reference()); // set r2 to the location of "readFlashSector" plus one, since it is thumb code - mov3(r3, r15); // move r15 (the program counter) to r3 - add2(r3, 5); // add 5 to r3 to compensate for the four following bytes, plus to tell the system to read as thumb code - mov3(r14, r3); // move r3 into r14 (the load register) - bx(r2); // jump to the pointer stored in r2 (readFlashSector) - pop(rlist_r0); // remove r0 from the stack and put it into r0 - bx(r0); // go to r0 - add_word(flashBuffer_ptr.place_word()); - add_word(readFlashSector_ptr.place_word()); - - constexpr bool should_set_virtual_start = true; - textGreet.insert_text(decompressed_store.text.gen3_charset, mg_script, should_set_virtual_start); - textYouMustBe.insert_text(decompressed_store.text.gen3_charset, mg_script, should_set_virtual_start); - textIAm.insert_text(decompressed_store.text.gen3_charset, mg_script, should_set_virtual_start); - - for (unsigned int i = 0; i < mg_variable_list.size(); i++) // Fill all the refrences for script variables in the mg - { - mg_variable_list[i]->fill_refrences(mg_script); - } - - for (unsigned int i = 0; i < sec30_variable_list.size(); i++) // Fill all the refrences for script variables in save section 30 - { - sec30_variable_list[i]->fill_refrences(save_section_30); - } - - if (curr_mg_index > MG_SCRIPT_SIZE) // Throw an error if the script is too large - { - tte_erase_screen(); - int val = (curr_mg_index - MG_SCRIPT_SIZE) - four_align_value; - tte_write("MG Script exceeded by "); - tte_write(ptgb::to_string(val)); - tte_write(" bytes"); - while (true) - { - } - } - - if (curr_section30_index > 0x4096) // Throw an error if the script is too large - { - tte_erase_screen(); - int val = (curr_section30_index - 0x4096) - four_align_value; - tte_write("S30 Script exceeded by "); - tte_write(ptgb::to_string(val)); - tte_write(" bytes"); - while (true) - { - } - } -}; - -/* -void mystery_gift_script::build_script_old(Pokemon_Party &incoming_box_data) -{ - ptgb::vector asm_variable_list; - asm_var sendMonToPC_ptr(curr_rom.loc_sendMonToPC + READ_AS_THUMB, asm_variable_list, &curr_mg_index); - asm_var returned_box_success_ptr(ptr_box_return, asm_variable_list, &curr_mg_index); - asm_var curr_pkmn_index_ptr(ptr_pkmn_offset, asm_variable_list, &curr_mg_index); - asm_var setPokedexFlag_ptr(curr_rom.loc_setPokedexFlag + READ_AS_THUMB, asm_variable_list, &curr_mg_index); - asm_var dexSeenCaught_ptr(ptr_dex_seen_caught, asm_variable_list, &curr_mg_index); - asm_var currPkmnIndex_ptr(ptr_index, asm_variable_list, &curr_mg_index); - asm_var pkmnStruct(curr_rom.loc_gSaveDataBuffer, asm_variable_list, &curr_mg_index); - asm_var dexStruct(curr_rom.loc_gSaveDataBuffer + (MAX_PKMN_IN_BOX * POKEMON_SIZE), asm_variable_list, &curr_mg_index); - asm_var flashBuffer_ptr(curr_rom.loc_gSaveDataBuffer, asm_variable_list, &curr_mg_index); - asm_var readFlashSector_ptr(curr_rom.loc_readFlashSector + READ_AS_THUMB, asm_variable_list, &curr_mg_index); - xse_var mainAsmStart(asm_variable_list, &curr_mg_index); - xse_var dexAsmStart(asm_variable_list, &curr_mg_index); - xse_var readFlashStart(asm_variable_list, &curr_mg_index); - - xse_var jumpLoop(asm_variable_list, &curr_mg_index); - xse_var jumpBoxFull(asm_variable_list, &curr_mg_index); - xse_var jumpPkmnCollected(asm_variable_list, &curr_mg_index); - xse_var jumpAllCollected(asm_variable_list, &curr_mg_index); - - textbox_var textGreet(asm_variable_list, &curr_mg_index); - textbox_var textReceived(asm_variable_list, &curr_mg_index); - textbox_var textPCFull(asm_variable_list, &curr_mg_index); - textbox_var textThank(asm_variable_list, &curr_mg_index); - textbox_var textTest(asm_variable_list, &curr_mg_index); - - // Ş = Wait for button and scroll text - // ȼ = Wait for button and clear text - // Ȇ = Escape character - // Ʋ = Variable escape sequence - // À = Player name - // Ň = New line - // ƞ = string terminator - textGreet.set_text((curr_rom.text_region == TEXT_HOENN) - ? u"LANETTE: Hey ƲÀ!ȼPROFESSOR FENNEL told me that you’dŇbe coming by for these POKÉMON!" - : u"BILL: Hey ƲÀ!ȼPROFESSOR FENNEL told me that you’dŇbe coming by for these POKÉMON!"); - textThank.set_text(u"Thanks for helping out FENNEL!"); - textPCFull.set_text(u"The PC is full…ȼGo make some more room!"); - textReceived.set_text(u"ȆÀÁƲÀ’S POKÉMON were sent to theŇPC!"); - textTest.set_text(u"Testing..."); - - // Located at 0x?8A8 in the .sav - init_npc_location(curr_rom.map_bank, curr_rom.map_id, curr_rom.npc_id); // Set the location of the NPC - setvirtualaddress(VIRTUAL_ADDRESS); // Set virtual address - lock(); // Lock the player - faceplayer(); // Have the NPC face the player - checkflag(curr_rom.all_collected_flag); // Check if the "all collected" flag has been set - virtualgotoif(COND_FLAGTRUE, jumpAllCollected.add_reference(2)); // If "all collected" is true, then jump to the "thank you" text - virtualmsgbox(textGreet.add_reference(1)); // Otherwise, greet the player - waitmsg(); // Wait for the message to finish - waitkeypress(); // Wait for the player to press A/B - setvar(var_index, 0); // set the index to 0 - setvar(var_callASM, rev_endian(0x0023)); // set the call_asm variable to 0x23: 0x23 = CALL ASM - setvar(var_pkmn_offset, 0); // Set the Pokemon struct offset to 0 - if (curr_rom.is_ruby_sapphire()) // Ruby and Sapphire don't shift their save blocks around, so we can hardcode it - { // FOR RUBY AND SAPPHIRE: - setvar(var_script_ptr_low, curr_rom.loc_gSaveBlock1 & 0xFFFF); // Copy the first two bytes of the saveblock1 location to a variable - setvar(var_script_ptr_high, curr_rom.loc_gSaveBlock1 >> 16); // Copy the second two bytes of the saveblock1 location to a variable - } // - else // - { // FOR FIRERED, LEAFGREEN, AND EMERALD - copybyte(ptr_script_ptr_low, ptr_block_ptr_low); // Copy the first byte of the saveblock1ptr to a variable - copybyte(ptr_script_ptr_low + 1, ptr_block_ptr_low + 1); // Copy the second byte of the saveblock1ptr to a variable - copybyte(ptr_script_ptr_high, ptr_block_ptr_high); // Copy the third byte of the saveblock1ptr to a variable - copybyte(ptr_script_ptr_high + 1, ptr_block_ptr_high + 1); // Copy the fourth byte of the saveblock1ptr to a variable - } // - addvar(var_script_ptr_low, curr_rom.offset_ramscript + 8 + READ_AS_THUMB); // add the offset for ramscript, plus 8. 8 is for the 8 bytes of Checksum, padding and NPC info - addvar(var_script_ptr_low, readFlashStart.add_reference(3)); // Add the offset for the start of ASM - setvar(var_call_return_1, rev_endian(0x0300)); // Set the vairable to 0x03. 0x03 = RETURN - setvar(var_call_check_flag, rev_endian(0x2B00)); // Set the variable to 0x2B. 0x2B = CHECK FLAG - addvar(var_call_check_flag, rev_endian(curr_rom.pkmn_collected_flag_start)); // Add the starting flag ID (plus one to ignore the is collected flag) to the check flag ASM variable - setvar(var_call_return_2, rev_endian(0x0003)); // Set the variable to 0x03. 0x03 = RETURN - jumpLoop.set_start(); // Set the jump destination for the JUMP_LOOP - call(ptr_call_check_flag); // Call the check flag ASM - virtualgotoif(COND_FLAGFALSE, jumpPkmnCollected.add_reference(2)); // If the "pokemon collected" flag is false, jump to the end of the loop - call(ptr_callASM); // Call readFlash ASM - addvar(var_script_ptr_low, mainAsmStart.add_reference(3, &readFlashStart)); // add to the CallASM offset so that it points to MAIN_ASM_START instead - call(ptr_callASM); // Call SendMonToPC ASM - compare(var_box_return, 2); // Compare the resulting return to #2 - virtualgotoif(COND_EQUALS, jumpBoxFull.add_reference(2)); // If the return value was #2, jump to the box full message - addvar(var_script_ptr_low, dexAsmStart.add_reference(3, &mainAsmStart)); // add to the CallASM offset so that it points to PTR_DEX_START instead - setvar(var_dex_seen_caught, 2); // set the seen caught variable to 2, so that the Pokemon is set to "seen" - call(ptr_callASM); // call "PTR_DEX_START" - addvar(var_dex_seen_caught, 1); // add 1 to the seen caught variable so that the Pokemon will be "Caught" - call(ptr_callASM); // Call "PTR_DEX_START" again - subvar(var_script_ptr_low, dexAsmStart.add_reference(3, &mainAsmStart)); // subtract from the CallASM offset so that it points to CALL_ASM again - subvar(var_script_ptr_low, mainAsmStart.add_reference(3, &readFlashStart)); // subtract from the CallASM offset so that it points to READ_FLASH - jumpPkmnCollected.set_start(); // Set the jump destination for if the Pokemon has already been collected - addvar(var_pkmn_offset, POKEMON_SIZE); // Add the size of one Pokmeon to the Pokemon offset - addvar(var_index, 1); // Add one to the index - addvar(var_call_check_flag, rev_endian(1)); // Add one to the flag index - compare(var_index, MAX_PKMN_IN_BOX); // Compare the index to 30 - virtualgotoif(COND_LESSTHAN, jumpLoop.add_reference(2)); // if index is less than six, jump to the start of the loop - setflag(curr_rom.all_collected_flag); // Set the "all collected" flag - fanfare(0xA4); // Play the received fanfare - virtualmsgbox(textReceived.add_reference(1)); // Display the recieved text - waitfanfare(); // Wait for the fanfare - waitmsg(); // Wait for the text to finish - waitkeypress(); // Wait for the player to press A/B - jumpAllCollected.set_start(); // Set the destination for if all the Pokemon have already been collected - virtualmsgbox(textThank.add_reference(1)); // Display the thank test - waitmsg(); // Wait for the message - waitkeypress(); // Wait for the player to press A/B - release(); // Release the player - killscript(); // Erase RAMscript - jumpBoxFull.set_start(); // Set the destination for if the box is full - virtualmsgbox(textPCFull.add_reference(1)); // Display the full box message - waitmsg(); // Wait for the message - waitkeypress(); // Wait for the player to presse A/B - release(); // Release the player - end(); // End the script - - textGreet.insert_text(mg_script); - textThank.insert_text(mg_script); - textPCFull.insert_text(mg_script); - textReceived.insert_text(mg_script); - textTest.insert_text(mg_script); - - while (curr_mg_index % 4 != 0) - { - curr_mg_index++; // Align the code so that it is byte aligned - } - - readFlashStart.set_start(); - push(rlist_lr); // save the load register to the stack - mov1(r0, 30); // set r0 to 30 (the sector ID for eReader data) - ldr3(r1, flashBuffer_ptr.add_reference()); // set r1 to the location of "flashBuffer" plus one, since it is thumb code - ldr3(r2, readFlashSector_ptr.add_reference()); // set r2 to the location of "readFlashSector" plus one, since it is thumb code - mov3(r3, r15); // move r15 (the program counter) to r3 - add2(r3, 5); // add 5 to r3 to compensate for the four following bytes, plus to tell the system to read as thumb code - mov3(r14, r3); // move r3 into r14 (the load register) - bx(r2); // jump to the pointer stored in r2 (readFlashSector) - pop(rlist_r0); // remove r0 from the stack and put it into r0 - bx(r0); // go to r0 - // - mainAsmStart.set_start(); // Set the memory pointer location for ASM start - push(rlist_lr); // save the load register to the stack - ldr3(r3, curr_pkmn_index_ptr.add_reference()); // set r3 to the pointer to the pokemon index variable - ldr1(r3, r3, 0); // set r3 to the value in memory r3 points to - add5(r0, pkmnStruct.add_reference()); // set r0 to a pointer to the start of the Pokemon struct. - ldr1(r0, r0, 0); // set r0 to the value in memory r0 points to - add3(r0, r0, r3); // add r3 to r0, giving it the correct offset for the current index - ldr3(r1, sendMonToPC_ptr.add_reference()); // set r1 to the location of "SendMonToPC" plus one, since it is thumb code - mov3(r2, r15); // move r15 (the program counter) to r2 - add2(r2, 5); // add 5 to r2 to compensate for the four following bytes, plus to tell the system to read as thumb code - mov3(r14, r2); // move r2 into r14 (the load register) - bx(r1); // jump to the pointer stored in r1 (SendMonToPC) - ldr3(r2, returned_box_success_ptr.add_reference()); // load variable 0x8006's pointer into r2 - str1(r0, r2, 0); // put the value of r0 into the memory location pointed at by r2, plus 0 - pop(rlist_r0); // remove r0 from the stack and put it into r0 - bx(r0); // jump to r0 (return to where the function was called) - // - dexAsmStart.set_start(); // Note the location where the Dex ASM starts - push(rlist_lr); // save the load register to the stack - ldr3(r0, currPkmnIndex_ptr.add_reference()); // load the pointer to the index variable into r0 - ldr1(r0, r0, 0); // load the value at r0's pointer - mov1(r3, 0xFF); // load 0xFF into r3 - and1(r0, r3); // AND r0 and r3, which will give us just the least significant byte - // - add5(r1, dexStruct.add_reference()); // set r1 to the value stored X bytes ahead - ldr1(r1, r1, 0); // loda the value at the memory location stored in r1 - add3(r0, r0, r1); // add r0 and r1, which is the current index and dex_struct respectivly - ldr1(r0, r0, 0); // load the value at the memory location stored in r0 - and1(r0, r3); // truncate to just the least significant byte, which is the current dex number - ldr3(r1, dexSeenCaught_ptr.add_reference()); // load the dex_seen_caught variable's pointer into r1 - ldr1(r1, r1, 0); // load the value of memory pointed at by r1 - and1(r1, r3); // AND r1 and r3, which will keep only the least significant byte - ldr3(r2, setPokedexFlag_ptr.add_reference()); // load the GetSetPokedexFlag function location into r2 - mov3(r3, r15); // move r15 (the program counter) to r3 - add2(r3, 5); // add 5 to r3 to compensate for the four following bytes, as well as to tell it to read as THUMB code - mov3(r14, r3); // move r3 into r14 (the load register) - bx(r2); // jump to the pointer stored in r2 (GetSetPokedexFlag) - pop(rlist_r0); // remove r0 from the stack and put it into r0 - bx(r0); // jump to r0 (return to where the function was called) - // - // - while (curr_mg_index % 4 != 0) - { - curr_mg_index++; // Align the code so that it is byte aligned - } - add_word(sendMonToPC_ptr.place_word()); // the location of "SendMonToPC", plus one (so it is interpreted as thumb code) - add_word(returned_box_success_ptr.place_word()); // the location of variable "0x8006" (the return value) - add_word(curr_pkmn_index_ptr.place_word()); // the location of variable "0x8008" (the pokemon offset) - add_word(setPokedexFlag_ptr.place_word()); // the location of GetSetPokedexFlag, plus one (so it is interpreted as thumb code) - add_word(dexSeenCaught_ptr.place_word()); // the location of the DEX_SEEN_CAUGHT variable - add_word(currPkmnIndex_ptr.place_word()); // the location of the INDEX variable - add_word(flashBuffer_ptr.place_word()); // the location of the FLASH_BUFFER variable - add_word(readFlashSector_ptr.place_word()); // the location of "readFlashSector", plus one (so it is interpreted as thumb code) - add_word(pkmnStruct.place_word()); // the location of the Pokemon Struct - add_word(dexStruct.place_word()); // the location of the dex struct - // - while (curr_mg_index % 4 != 0) - { - curr_mg_index++; // Align the code so that it is byte aligned - } - for (unsigned int i = 0; i < asm_variable_list.size(); i++) // Fill all the refrences for script variables - { - asm_variable_list[i]->fill_refrences(mg_script); - } - - if (curr_mg_index > MG_SCRIPT_SIZE) // Throw an error if the script is too large - { - tte_erase_screen(); - int val = (curr_mg_index - MG_SCRIPT_SIZE) - four_align_value; - tte_write("Script exceeded by "); - tte_write(ptgb::to_string(val)); - tte_write(" bytes"); - while (true) - { - } - } -}; -*/ - -const u8 *mystery_gift_script::get_script() const -{ - return mg_script; -} - -const u8 *mystery_gift_script::get_section30() const -{ - return save_section_30; -} - -u16 mystery_gift_script::rev_endian(u16 num) -{ - return ((num & 0xFF) << 8) | (num >> 8); -} - -void mystery_gift_script::add_command(int len) -{ - for (int i = 0; i < len; i++) - { - mg_script[curr_mg_index] = value_buffer[i]; - curr_mg_index++; - } -} - -u32 mystery_gift_script::calc_checksum32() -{ - u16 i; - u32 checksum = 0; - - for (i = 0; i < MG_SCRIPT_SIZE; i++) - { - checksum += mg_script[i]; - } - - return checksum; -} - -u16 mystery_gift_script::calc_crc16() // Implementation taken from PokeEmerald Decomp -{ - u16 i, j; - u16 crc = 0x1121; - - for (i = 0; i < MG_SCRIPT_SIZE; i++) - { - crc ^= mg_script[i]; - for (j = 0; j < 8; j++) - { - if (crc & 1) - crc = (crc >> 1) ^ 0x8408; - else - crc >>= 1; - } - } - return ~crc; -}; - -void mystery_gift_script::add_asm(u16 command) -{ - if (asm_payload_location == S30_SCRIPT) - { - save_section_30[curr_section30_index] = command >> 0; - save_section_30[curr_section30_index + 1] = command >> 8; - curr_section30_index += 2; - } - else - { - mg_script[curr_mg_index] = command >> 0; - mg_script[curr_mg_index + 1] = command >> 8; - curr_mg_index += 2; - } -} - -// Scripting commands: - -void mystery_gift_script::setvirtualaddress(u32 location) -{ - value_buffer[0] = 0xB8; - value_buffer[1] = location >> 0; - value_buffer[2] = location >> 8; - value_buffer[3] = location >> 16; - value_buffer[4] = location >> 24; - add_command(5); -} - -void mystery_gift_script::lock() -{ - value_buffer[0] = 0x6A; - add_command(1); -} - -void mystery_gift_script::faceplayer() -{ - value_buffer[0] = 0x5A; - add_command(1); -} - -void mystery_gift_script::checkflag(u16 flag_id) -{ - value_buffer[0] = 0x2B; - value_buffer[1] = flag_id >> 0; - value_buffer[2] = flag_id >> 8; - add_command(3); -} - -void mystery_gift_script::virtualgotoif(u8 condition, u32 location) -{ - value_buffer[0] = 0xBB; - value_buffer[1] = condition; - value_buffer[2] = (VIRTUAL_ADDRESS >> 0) & 0xFF; - value_buffer[3] = (VIRTUAL_ADDRESS >> 8) & 0xFF; - value_buffer[4] = (VIRTUAL_ADDRESS >> 16) & 0xFF; - value_buffer[5] = (VIRTUAL_ADDRESS >> 24) & 0xFF; - add_command(6); -} - -void mystery_gift_script::virtualmsgbox(u32 location) -{ - value_buffer[0] = 0xBD; - value_buffer[1] = (VIRTUAL_ADDRESS >> 0) & 0xFF; - value_buffer[2] = (VIRTUAL_ADDRESS >> 8) & 0xFF; - value_buffer[3] = (VIRTUAL_ADDRESS >> 16) & 0xFF; - value_buffer[4] = (VIRTUAL_ADDRESS >> 24) & 0xFF; - add_command(5); -} - -void mystery_gift_script::loadpointer(u8 destinationBank, u32 value) -{ - value_buffer[0] = 0x0F; - value_buffer[1] = destinationBank; - value_buffer[2] = value >> 0; - value_buffer[3] = value >> 8; - value_buffer[4] = value >> 16; - value_buffer[5] = value >> 24; - add_command(6); -} - -void mystery_gift_script::waitmsg() -{ - value_buffer[0] = 0x66; - add_command(1); -} - -void mystery_gift_script::waitkeypress() -{ - value_buffer[0] = 0x6D; - add_command(1); -} - -void mystery_gift_script::setvar(u16 var_id, u16 value) -{ - value_buffer[0] = 0x16; - value_buffer[1] = var_id >> 0; - value_buffer[2] = var_id >> 8; - value_buffer[3] = value >> 0; - value_buffer[4] = value >> 8; - add_command(5); -} - -void mystery_gift_script::copybyte(u32 destination, u32 source) -{ - value_buffer[0] = 0x15; - value_buffer[1] = destination >> 0; - value_buffer[2] = destination >> 8; - value_buffer[3] = destination >> 16; - value_buffer[4] = destination >> 24; - value_buffer[5] = source >> 0; - value_buffer[6] = source >> 8; - value_buffer[7] = source >> 16; - value_buffer[8] = source >> 24; - add_command(9); -} - -void mystery_gift_script::addvar(u16 var_id, u16 value) -{ - value_buffer[0] = 0x17; - value_buffer[1] = var_id >> 0; - value_buffer[2] = var_id >> 8; - value_buffer[3] = value >> 0; - value_buffer[4] = value >> 8; - add_command(5); -} - -void mystery_gift_script::subvar(u16 var_id, u16 value) -{ - value_buffer[0] = 0x18; - value_buffer[1] = var_id >> 0; - value_buffer[2] = var_id >> 8; - value_buffer[3] = value >> 0; - value_buffer[4] = value >> 8; - add_command(5); -} - -void mystery_gift_script::call(u32 script_ptr) -{ - value_buffer[0] = 0x04; - value_buffer[1] = script_ptr >> 0; - value_buffer[2] = script_ptr >> 8; - value_buffer[3] = script_ptr >> 16; - value_buffer[4] = script_ptr >> 24; - add_command(5); -} - -void mystery_gift_script::compare(u16 var_id, u16 value) -{ - value_buffer[0] = 0x21; - value_buffer[1] = var_id >> 0; - value_buffer[2] = var_id >> 8; - value_buffer[3] = value >> 0; - value_buffer[4] = value >> 8; - add_command(5); -} - -void mystery_gift_script::setflag(u16 flag_id) -{ - value_buffer[0] = 0x29; - value_buffer[1] = flag_id >> 0; - value_buffer[2] = flag_id >> 8; - add_command(3); -} - -void mystery_gift_script::fanfare(u16 fanfare_number) -{ - value_buffer[0] = 0x31; - value_buffer[1] = fanfare_number >> 0; - value_buffer[2] = fanfare_number >> 8; - add_command(3); -} - -void mystery_gift_script::waitfanfare() -{ - value_buffer[0] = 0x32; - add_command(1); -} - -void mystery_gift_script::special(u16 special_id) -{ - value_buffer[0] = 0x25; - value_buffer[1] = special_id >> 0; - value_buffer[2] = special_id >> 8; - add_command(3); -} - -void mystery_gift_script::callstd(u8 function_index) -{ - value_buffer[0] = 0x09; - value_buffer[1] = function_index; - add_command(2); -} - -void mystery_gift_script::release() -{ - value_buffer[0] = 0x6C; - add_command(1); -} - -void mystery_gift_script::end() -{ - value_buffer[0] = 0x02; - add_command(1); -} - -void mystery_gift_script::killscript() -{ - value_buffer[0] = 0x0D; - add_command(1); -} - -void mystery_gift_script::spritebehave(u16 objectID, u8 behaviorType) -{ - value_buffer[0] = 0x65; - value_buffer[1] = objectID >> 0; - value_buffer[2] = objectID >> 8; - value_buffer[3] = behaviorType; - add_command(4); -} - -void mystery_gift_script::spriteface(u16 npc, u8 direction) -{ - value_buffer[0] = 0x5B; - value_buffer[1] = npc >> 0; - value_buffer[2] = npc >> 8; - value_buffer[3] = direction; - add_command(4); -} - -void mystery_gift_script::waitmovement(u16 npc) -{ - value_buffer[0] = 0x51; - value_buffer[1] = npc >> 0; - value_buffer[2] = npc >> 8; - add_command(3); -} - -void mystery_gift_script::doanimation(u16 animation) -{ - value_buffer[0] = 0x9C; - value_buffer[1] = animation >> 0; - value_buffer[2] = animation >> 8; - add_command(3); -} - -void mystery_gift_script::applymovement(u16 npc, u32 movements) -{ - value_buffer[0] = 0x4F; - value_buffer[1] = npc >> 0; - value_buffer[2] = npc >> 8; - value_buffer[3] = movements >> 0; - value_buffer[4] = movements >> 8; - value_buffer[5] = movements >> 16; - value_buffer[6] = movements >> 24; - add_command(7); -} - -void mystery_gift_script::callASM(u32 script_ptr) -{ - value_buffer[0] = 0x23; - value_buffer[1] = script_ptr >> 0; - value_buffer[2] = script_ptr >> 8; - value_buffer[3] = script_ptr >> 16; - value_buffer[4] = script_ptr >> 24; - add_command(5); -} - -void mystery_gift_script::setMapLayoutIndex(u16 footer) -{ - value_buffer[0] = 0xA7; - value_buffer[1] = footer >> 0; - value_buffer[2] = footer >> 8; - add_command(3); -} - -void mystery_gift_script::fadeScreen(u8 effect) -{ - value_buffer[0] = 0x97; - value_buffer[1] = effect >> 0; - add_command(2); -} - -void mystery_gift_script::setMetaTile(u16 x, u16 y, u16 metaTileId, u16 impassible) -{ - value_buffer[0] = 0xA2; - value_buffer[1] = x >> 0; - value_buffer[2] = x >> 8; - value_buffer[3] = y >> 0; - value_buffer[4] = y >> 8; - value_buffer[5] = metaTileId >> 0; - value_buffer[6] = metaTileId >> 8; - value_buffer[7] = impassible >> 0; - value_buffer[8] = impassible >> 8; - add_command(9); -} - -void mystery_gift_script::playse(u16 soundId) -{ - value_buffer[0] = 0x2F; - value_buffer[1] = soundId >> 0; - value_buffer[2] = soundId >> 8; - add_command(3); -} - -void mystery_gift_script::waitse() -{ - value_buffer[0] = 0x30; - add_command(1); -} - -void mystery_gift_script::writebytetooffset(u8 byte, u32 offset) -{ - value_buffer[0] = 0x11; - value_buffer[1] = byte; - value_buffer[2] = offset >> 0; - value_buffer[3] = offset >> 8; - value_buffer[4] = offset >> 16; - value_buffer[5] = offset >> 24; - add_command(6); -} - -void mystery_gift_script::init_npc_location(u8 bank, u8 map, u8 npc) -{ - mg_script[0] = 0x33; // File ID? - mg_script[1] = bank; - mg_script[2] = map; - mg_script[3] = npc; -} - -void mystery_gift_script::msgboxMacro(u32 location) -{ - loadpointer(0, location); - callstd(4); -} - -void mystery_gift_script::changeSpriteMacro(u8 npcId, u32 spriteTablePtr) -{ - writebytetooffset(spriteTablePtr >> 0, curr_GBA_rom.loc_gSprites + (0x44 * npcId) + 0xC + 0); - writebytetooffset(spriteTablePtr >> 8, curr_GBA_rom.loc_gSprites + (0x44 * npcId) + 0xC + 1); - writebytetooffset(spriteTablePtr >> 16, curr_GBA_rom.loc_gSprites + (0x44 * npcId) + 0xC + 2); - writebytetooffset(spriteTablePtr >> 24, curr_GBA_rom.loc_gSprites + (0x44 * npcId) + 0xC + 3); -} - -void mystery_gift_script::changePaletteMacro(u8 npcId, u8 palNum) -{ - writebytetooffset((palNum << 4) | 0x08, curr_GBA_rom.loc_gSprites + (0x44 * npcId) + 0x5); -} - -// ASM Commands -// Documentation found here: -// https://github.com/LunarLambda/arm-docs - -/** - * @brief PUSH (Push Multiple Registers) stores a subset (or possibly all) of the general-purpose registers R0-R7 and the LR to the stack - * - * @param register_list Is the list of registers to be stored, separated by commas and surrounded by { and }. The list is encoded in the register_list field of the instruction, by setting bit[i] to 1 if register Ri is included in the list and to 0 otherwise, for each of i=0 to 7. The R bit (bit[8]) is set to 1 if the LR is in the list and to 0 otherwise. - */ - -void mystery_gift_script::push(u16 register_list) -{ - add_asm((0b1011010 << 9) | register_list); -} - -/** - * @brief LDR (3) loads 32-bit memory data into a general-purpose register. The addressing mode is useful for accessing PC-relative data. - * - * @param rd Is the destination register for the word loaded from memory. - * @param immed_8 Is an 8-bit value that is multiplied by 4 and added to the value of the PC to form the memory address. - */ -void mystery_gift_script::ldr3(u8 rd, u8 immed_8) -{ - add_asm(0b01001 << 11 | rd << 8 | immed_8); -} - -/** - * @brief LDR (1) (Load Register) allows 32-bit memory data to be loaded into a general-purpose register. The addressing mode is useful for accessing structure (record) fields. With an offset of zero, the address produced is the unaltered value of the base register . - * - * @param rd Is the destination register for the word loaded from memory. - * @param rn Is the register containing the base address for the instruction. - * @param immed_5 Is a 5-bit value that is multiplied by 4 and added to the value of to form the memory address. - */ -void mystery_gift_script::ldr1(u8 rd, u8 rn, u8 immed_5) -{ - add_asm(0b01101 << 11 | immed_5 << 6 | rn << 3 | rd); -} - -/** - * @brief ADD (5) adds an immediate value to the PC and writes the resulting PC-relative address to a destination register. The immediate can be any multiple of 4 in the range 0 to 1020. - * - * @param rd Is the destination register for the completed operation. - * @param immed_8 Specifies an 8-bit immediate value that is quadrupled and added to the value of the PC. - */ -void mystery_gift_script::add5(u8 rd, u8 immed_8) -{ - add_asm(0b10100 << 11 | rd << 8 | immed_8); -} - -/** - * @brief ADD (3) adds the value of one register to the value of a second register, and stores the result in a third register. It updates the condition code flags, based on the result. - * - * @param rd Is the destination register for the completed operation. - * @param rn Specifies the register containing the first value for the addition. - * @param rm Specifies the register containing the second value for the addition. - */ -void mystery_gift_script::add3(u8 rd, u8 rn, u8 rm) -{ - add_asm(0b0001100 << 9 | rm << 6 | rn << 3 | rd); -} - -/** - * @brief MOV (3) moves a value to, from, or between high registers. Unlike the low register MOV instruction described in MOV (2) on page A7-73, this instruction does not change the flags. - * - * @param rd Is the destination register for the operation. It can be any of R0 to R15, and its number is encoded in the instruction in H1 (most significant bit) and Rd (remaining three bits) - * @param rm Is the register containing the value to be copied. It can be any of R0 to R15, and its number is encoded in the instruction in H2 (most significant bit) and Rm (remaining three bits). - */ -void mystery_gift_script::mov3(u8 rd, u8 rm) -{ - add_asm(0b01000110 << 8 | (rd >> 3) << 7 | (rm >> 3) << 6 | (rm & 0b111) << 3 | (rd & 0b111)); -} - -/** - * @brief ADD (2) adds a large immediate value to the value of a register and stores the result back in the same register. The condition code flags are updated, based on the result. - * - * @param rd Holds the first operand for the addition, and is the destination register for the completed operation. - * @param immed_8 Specifies an 8-bit immediate value that is added to the value of - */ -void mystery_gift_script::add2(u8 rd, u8 immed_8) -{ - add_asm(0b00110 << 11 | rd << 8 | immed_8); -} - -/** - * @brief BX (Branch and Exchange) branches between ARM code and Thumb code. - * - * @param rm Is the register that contains the branch target address. It can be any of R0 to R15. The register number is encoded in the instruction in H2 (most significant bit) and Rm (remaining three bits) - */ -void mystery_gift_script::bx(u8 rm) -{ - add_asm(0b010001110 << 7 | (rm >> 3) << 6 | (rm & 0b111) << 3); -} - -/** - * @brief STR (1) (Store Register) stores 32-bit data from a general-purpose register to memory. The addressing mode is useful for accessing structure (record) fields. With an offset of zero, the address produced is the unaltered value of the base register . - * - * @param rd Is the register that contains the word to be stored to memory. - * @param rn Is the register containing the base address for the instruction. - * @param immed_5 Is a 5-bit value that is multiplied by 4 and added to the value of to form the memory address. - */ -void mystery_gift_script::str1(u8 rd, u8 rn, u8 immed_5) -{ - add_asm(0b01100 << 11 | immed_5 << 6 | rn << 3 | rd); -} - -/** - * @brief POP (Pop Multiple Registers) loads a subset (or possibly all) of the general-purpose registers R0-R7 and the PC from the stack. - * - * @param register_list Is the list of registers, separated by commas and surrounded by { and }. The list is encoded in the register_list field of the instruction, by setting bit[i] to 1 if register Ri is included in the list and to 0 otherwise, for each of i=0 to 7. The R bit (bit[8]) is set to 1 if the PC is in the list and to 0 otherwise. - */ -void mystery_gift_script::pop(u16 register_list) -{ - add_asm(0b1011110 << 9 | register_list); -} -/** - * @brief MOV (1) (Move) moves a large immediate value to a register. - * - * @param rd Is the destination register for the operation. - * @param immed_8 Is an 8-bit immediate value, in the range 0 to 255, to move into . - */ -void mystery_gift_script::mov1(u8 rd, u8 immed_8) -{ - add_asm(0b00100 << 11 | rd << 8 | immed_8); -} -/** - * @brief AND (Logical AND) performs a bitwise AND of the values in two registers. - * - * @param rd Specifies the register containing the first operand, and is also the destination register. - * @param rm Specifies the register containing the second operand. - */ -void mystery_gift_script::and1(u8 rd, u8 rm) -{ - add_asm(0b0100000000 << 6 | rm << 3 | rd); -} -/** - * @brief LDR (2) loads 32-bit memory data into a general-purpose register. The addressing mode is useful for pointer+large offset arithmetic and for accessing a single element of an array. - * - * @param rd Is the destination register for the word loaded from memory. - * @param rn Is the register containing the first value used in forming the memory address. - * @param rm Is the register containing the second value used in forming the memory address. - */ -void mystery_gift_script::ldr2(u8 rd, u8 rn, u8 rm) -{ - add_asm(0b0101100 << 9 | rm << 6 | rm << 3 | rd); -} -/** - * @brief STRH (1) (Store Register Halfword) stores 16-bit data from a general-purpose register to memory. The addressing mode is useful for accessing structure (record) fields. With an offset of zero, the address produced is the unaltered value of the base register . - * - * @param immed_8 Is an 8-bit immediate value that is put into bits[7:0] of the instruction. This value is ignored by the processor, but can be used by an operating system's SWI exception handler to determine which operating system service is being requested. - */ -void mystery_gift_script::strh(u8 rd, u8 rn, u8 immed_5) -{ - add_asm(0b10000 << 11 | (immed_5 & 0b11111) << 6 | rn << 3 | rd); -} -/** - * @brief SWI (Software Interrupt) generates a software interrupt or SWI, which is handled by an operating system. See Exceptions on page A2-16. Use it as a call to an operating system service to provide a service. - * - * @param rd Is the register whose least significant halfword is stored to memory. - * @param rn Is the register containing the base address for the instruction. - * @param immed_5 Is a 5-bit immediate value that is multiplied by two and added to the value of to form the memory address. - */ -void mystery_gift_script::swi(u8 immed_8) -{ - add_asm(0b11011111 << 8 | immed_8); -} - -void mystery_gift_script::add_word(u32 word) -{ - add_asm(word >> 0); - add_asm(word >> 16); -} diff --git a/source/mystery_gift_injector.cpp b/source/mystery_gift_injector.cpp index 2c1107b..54d61be 100644 --- a/source/mystery_gift_injector.cpp +++ b/source/mystery_gift_injector.cpp @@ -1,10 +1,16 @@ #include #include "mystery_gift_injector.h" +#include "pokemon_data.h" #include "flash_mem.h" -#include "mystery_gift_builder.h" #include "rom_data.h" #include "libraries/Pokemon-Gen3-to-Gen-X/include/save.h" #include "pokemon_data.h" +#include "ptgb_save_data_manager.h" +#include "script_ruby_english_1_2_bin.h" +#include "section30_ruby_english_1_2_bin.h" +#include + +#define MG_SCRIPT_SIZE 0x3E8 // This will need to be modified for the JP releases static const u8 em_wonder_card[0x14E] = { @@ -14,32 +20,101 @@ static const u8 em_wonder_card[0x14E] = { static const u8 frlg_wonder_card[0x14E] = { 0x67, 0x18, 0x00, 0x00, 0xBA, 0xB4, 0xBE, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xCA, 0xCC, 0xC9, 0xC0, 0xBF, 0xCD, 0xCD, 0xC9, 0xCC, 0x00, 0xC0, 0xBF, 0xC8, 0xC8, 0xBF, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0xE6, 0xD5, 0xE2, 0xE7, 0xDA, 0xD9, 0xE6, 0x00, 0xBD, 0xD9, 0xE6, 0xE8, 0xDD, 0xDA, 0xDD, 0xD7, 0xD5, 0xE8, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xDD, 0xE7, 0xDD, 0xE8, 0x00, 0xE8, 0xDC, 0xD9, 0x00, 0xDC, 0xE3, 0xE9, 0xE7, 0xD9, 0x00, 0xE7, 0xE3, 0xE9, 0xE8, 0xDC, 0x00, 0xE3, 0xDA, 0x00, 0xE8, 0xDC, 0xD9, 0x00, 0xCA, 0xC9, 0xC5, 0x1B, 0xC7, 0xC9, 0xC8, 0x00, 0x00, 0x00, 0x00, 0xBD, 0xBF, 0xC8, 0xCE, 0xBF, 0xCC, 0x00, 0xE3, 0xE2, 0x00, 0xCD, 0xD9, 0xEA, 0xD9, 0xE2, 0x00, 0xC3, 0xE7, 0xE0, 0xD5, 0xE2, 0xD8, 0x00, 0xE8, 0xE3, 0x00, 0xE6, 0xD9, 0xD7, 0xDD, 0xD9, 0xEA, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xED, 0xE3, 0xE9, 0xE6, 0x00, 0xE8, 0xE6, 0xD5, 0xE2, 0xE7, 0xDA, 0xD9, 0xE6, 0xD9, 0xD8, 0x00, 0xCA, 0xC9, 0xC5, 0x1B, 0xC7, 0xC9, 0xC8, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xE3, 0x00, 0xE2, 0xE3, 0xE8, 0x00, 0xE8, 0xE3, 0xE7, 0xE7, 0x00, 0xE8, 0xDC, 0xDD, 0xE7, 0x00, 0xBF, 0xEC, 0xD7, 0xDC, 0xD5, 0xE2, 0xDB, 0xD9, 0x00, 0xBD, 0xD5, 0xE6, 0xD8, 0x00, 0xD6, 0xD9, 0xDA, 0xE3, 0xE6, 0xD9, 0x00, 0x00, 0x00, 0xE6, 0xD9, 0xD7, 0xD9, 0xDD, 0xEA, 0xDD, 0xE2, 0xDB, 0x00, 0xED, 0xE3, 0xE9, 0xE6, 0x00, 0xE8, 0xE6, 0xD5, 0xE2, 0xE7, 0xDA, 0xD9, 0xE6, 0xD9, 0xD8, 0x00, 0xCA, 0xC9, 0xC5, 0x1B, 0xC7, 0xC9, 0xC8, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // checksum -bool inject_mystery(PokeBox* box) +/// function to calculate a 32-bit checksum of a script buffer. +static u32 calc_checksum32(const u8 *buffer, u32 size) { - // WARNING: Look right here: we're passing global_memory_buffer to mystery_gift_script to be used as its save_section_30 buffer. - // Since we're going to be reusing global_memory_buffer later, we need to be careful about the timing/sequence of operations. - // The goal is to use write that save_section_30 to the save as soon as we can. - mystery_gift_script script(global_memory_buffer); + u16 i; u32 checksum = 0; - script.build_script(box); + for (i = 0; i < size; ++i) + { + checksum += buffer[i]; + } + + return checksum; +} + +/// function to calculate a 16-bit CRC of a script buffer. +static u16 calc_crc16(const u8 *buffer, u32 size) // Implementation taken from PokeEmerald Decomp +{ + u16 i, j; + u16 crc = 0x1121; + + for (i = 0; i < size; ++i) + { + crc ^= buffer[i]; + for (j = 0; j < 8; ++j) + { + if (crc & 1) + crc = (crc >> 1) ^ 0x8408; + else + crc >>= 1; + } + } + return ~crc; +}; + +/** + * @brief This function injects the PokeBox pokémons into section30 at offset 0x0, which is what the payload expects. + * + * @param box pointer to the PokeBox instance containing the Pokémon to inject. + * @param section30Buffer The buffer representing section 30 of the save file. + */ +static void __attribute__((noinline)) injectBoxIntoSection30(PokeBox* box, u8* section30Buffer) +{ + u8 dex_nums[MAX_PKMN_IN_BOX] = {}; + PokemonTables tableData; + u8 *curSection30 = section30Buffer; + + box->setTable(&tableData); + box->convertAll(); + for (int i = 0; i < MAX_PKMN_IN_BOX; i++) // Add in the Pokemon data + { + Gen3Pokemon *curr_pkmn = box->getGen3Pokemon(i); + if (curr_pkmn->isValid) + { + tonccpy(curSection30, curr_pkmn->dataArrayPtr, POKEMON_SIZE); + + dex_nums[i] = curr_pkmn->getSpeciesIndexNumber(); + } + + curSection30 += POKEMON_SIZE; + } + + // Add in the dex numbers + tonccpy(curSection30, dex_nums, MAX_PKMN_IN_BOX); +} + +bool inject_mystery(PokeBox* box) +{ + u32 checksum; + u8 script_buffer[MG_SCRIPT_SIZE]; + + // make sure the buffers are filled with zeros. + memset(global_memory_buffer, 0, 0x1000); + memset(script_buffer, 0, MG_SCRIPT_SIZE); + + //now use the pregenerated script and section30 data. + tonccpy(script_buffer, script_ruby_english_1_2_bin, script_ruby_english_1_2_bin_size); + tonccpy(global_memory_buffer, section30_ruby_english_1_2_bin, section30_ruby_english_1_2_bin_size); + + // One thing our pregeneration process obviously leaves out is the pokemon data. + // so let's add that in now. + injectBoxIntoSection30(box, global_memory_buffer); if (curr_GBA_rom.is_ruby_sapphire()) { - checksum = script.calc_checksum32(); + checksum = calc_checksum32(script_buffer, MG_SCRIPT_SIZE); } else { - checksum = script.calc_crc16(); + checksum = calc_crc16(script_buffer, MG_SCRIPT_SIZE); } // Add in Pokemon and Dex data - // We need to do this NOW, because mystery_gift_script::build_script() actually fills the global_memory_buffer. // In the steps after this, we will be recycling the global_memory_buffer to read and write data to other sections of the save. // So we really MUST write the generated data now, before we lose it. - memcpy(global_memory_buffer, script.get_section30(), 0x1000); - update_memory_buffer_checksum(global_memory_buffer, false); erase_sector(0x1E000); copy_ram_to_save(&global_memory_buffer[0], 0x1E000, 0x1000); @@ -72,7 +147,7 @@ bool inject_mystery(PokeBox* box) global_memory_buffer[curr_GBA_rom.offset_script + 3] = checksum >> 24; // Add in Mystery Script data - memcpy(global_memory_buffer + curr_GBA_rom.offset_script + 4, script.get_script(), MG_SCRIPT_SIZE); + memcpy(global_memory_buffer + curr_GBA_rom.offset_script + 4, script_buffer, MG_SCRIPT_SIZE); update_memory_buffer_checksum(global_memory_buffer, false); erase_sector(memory_section_array[4]); diff --git a/source/rom_data.cpp b/source/rom_data.cpp index d9f30e4..20f544f 100644 --- a/source/rom_data.cpp +++ b/source/rom_data.cpp @@ -1,5 +1,5 @@ #include "rom_data.h" -#include "mystery_gift_builder.h" +#include "dbg/debug_mode.h" #include "pokemon_data.h" #include "text_engine.h" #include "ptgb_save_data_manager.h" diff --git a/source/script_array.cpp b/source/script_array.cpp index 6dd7009..35ef9c0 100644 --- a/source/script_array.cpp +++ b/source/script_array.cpp @@ -6,8 +6,8 @@ #include "gb_rom_values/gb_rom_values.h" #include "global_frame_controller.h" #include "link_handler.h" -#include "mystery_gift_builder.h" #include "mystery_gift_injector.h" +#include "ptgb_save_data_manager.h" #include "pokemon_data.h" #include "select_menu.h" #include "sprite_data.h" diff --git a/source/script_var.cpp b/source/script_var.cpp deleted file mode 100644 index 0ec07e9..0000000 --- a/source/script_var.cpp +++ /dev/null @@ -1,289 +0,0 @@ -#include -#include "libstd_replacements.h" -#include "script_var.h" -#include "pokemon_data.h" -#include "dbg/debug_mode.h" -#include "global_frame_controller.h" - -extern rom_data curr_GBA_rom; - -script_var::script_var(u32 nValue, ptgb::vector &var_list_ref, int *nCurr_loc_ptr) -{ - var_list_ref.push_back(this); // Place the new object in the var_list - value = nValue; - curr_loc_ptr = nCurr_loc_ptr; -}; - -script_var::script_var(ptgb::vector &var_list_ref, int *nCurr_loc_ptr) -{ - var_list_ref.push_back(this); // Place the new object in the var_list - curr_loc_ptr = nCurr_loc_ptr; -}; - -u32 script_var::place_word() -{ - set_start(); - return value; -} - -void script_var::set_start() -{ - tte_write("set_start error"); - while (true) - { - // This should never run - } -} - -void script_var::fill_refrences(u8 mg_array[]) -{ - tte_write("fill_refrences error"); - while (true) - { - // This should never run - }; -} - -// ASM VAR ---------------- - -void asm_var::set_start() -{ - start_location_in_script = *curr_loc_ptr - 2; - isDirect = false; -} - -void asm_var::set_start(bool nIsDirect) -{ - start_location_in_script = *curr_loc_ptr - 2; - isDirect = nIsDirect; -} - -u8 asm_var::add_reference() -{ - return add_reference(0); -} - -u8 asm_var::add_reference(int nCommand_offset) -{ - location_list.push_back(*curr_loc_ptr + nCommand_offset); - return 0x00; -} - -void asm_var::fill_refrences(u8 mg_array[]) -{ - for (unsigned int i = 0; i < location_list.size(); i++) - { - if (isDirect) - { - for (int j = 0; j < 4; j++) - { - mg_array[location_list[i] + j] += (start_location_in_script + curr_GBA_rom.loc_gSaveBlock1 + curr_GBA_rom.offset_ramscript + 7) >> (j * 8); - } - } - else - { - mg_array[location_list[i]] += ((start_location_in_script - location_list[i]) / 4) & 0xFF; - } - } -} - -u32 asm_var::get_loc_in_sec30() -{ - return start_location_in_script + curr_GBA_rom.loc_gSaveDataBuffer + 3; // plus 3 to offset the -2 in set_start, and one for reading as thumb -} - -// XSE VAR ---------------- - -void xse_var::set_start() -{ - start_location_in_script = *curr_loc_ptr - 4; -} - -u8 xse_var::add_reference(int nCommand_offset) -{ - location_list.push_back(*curr_loc_ptr + nCommand_offset); - command_offset = nCommand_offset; - has_reference_var = false; - refrence_var = nullptr; - return 0x0000; -} - -u8 xse_var::add_reference(int nCommand_offset, xse_var *offset_from) -{ - add_reference(nCommand_offset); - has_reference_var = true; - refrence_var = offset_from; - return 0x0000; -} - -void xse_var::fill_refrences(u8 mg_array[]) -{ - for (unsigned int i = 0; i < location_list.size(); i++) - { - int internal_offset = 0; - if (has_reference_var) - { - internal_offset = refrence_var->start_location_in_script; - } - mg_array[location_list[i]] += (start_location_in_script - internal_offset) & 0xFF; - mg_array[location_list[i] + 1] += ((start_location_in_script - internal_offset) & 0xFF00) >> 8; - } -} - -u32 xse_var::get_loc_in_sec30() -{ - return start_location_in_script + curr_GBA_rom.loc_gSaveDataBuffer; -} - -// TEXTBOX VAR - -void textbox_var::set_text(const byte nText[]) -{ - text = nText; - text_length = get_string_char_count(nText); -} - -void textbox_var::set_start() -{ - start_location_in_script = *curr_loc_ptr; -} - -void textbox_var::set_virtual_start() -{ - start_location_in_script = *curr_loc_ptr - 4; -} - -void textbox_var::insert_text(const u16 *charset, u8 mg_array[], bool should_set_virtual_start) -{ - if(!should_set_virtual_start) - { - set_start(); - } - else - { - set_virtual_start(); - } - - for (int parser = 0; parser < text_length; parser++) - { - if (curr_GBA_rom.is_hoenn() && (text[parser] == 0xFC) && (get_char_from_charset(charset, (char16_t)(text[parser + 1])) == 0x01)) // Removes colored text - { - parser += 2; - } - else - { - mg_array[*curr_loc_ptr] = text[parser]; - (*curr_loc_ptr)++; - } - } - mg_array[*curr_loc_ptr] = 0xFF; // End string - (*curr_loc_ptr)++; -} - -// MOVEMENT VAR - -void movement_var::set_movement(const byte nMovement[], unsigned int nSize) -{ - movement = nMovement; - size = nSize; -} - -void movement_var::set_start() -{ - start_location_in_script = *curr_loc_ptr; -} - -void movement_var::insert_movement(u8 mg_array[]) -{ - set_start(); - // movement data is { hoenn, frlg, hoenn, frlg, ...} - int offset = curr_GBA_rom.is_hoenn() ? 0 : 1; - - for (unsigned int parser = 0; parser < size; parser++) - { - mg_array[*curr_loc_ptr] = movement[parser * 2 + offset]; - (*curr_loc_ptr)++; - } - mg_array[*curr_loc_ptr] = 0xFE; // End list - (*curr_loc_ptr)++; -} - -// SPRITE VAR - -void sprite_var::set_start() -{ - start_location_in_script = *curr_loc_ptr; -} - -void sprite_var::insert_sprite_data(u8 mg_array[], const unsigned int sprite_array[], unsigned int size, const unsigned short palette_array[]) -{ - - set_start(); - u32 pointer = curr_GBA_rom.loc_gSaveDataBuffer + *curr_loc_ptr + 8; - for (int i = 0; i < 4; i++) - { - mg_array[*curr_loc_ptr] = pointer >> (8 * i); - (*curr_loc_ptr)++; - } - for (int i = 0; i < 4; i++) - { - mg_array[*curr_loc_ptr] = size >> (8 * i); - (*curr_loc_ptr)++; - } - - LZ77UnCompWram(sprite_array, &mg_array[*curr_loc_ptr]); - *curr_loc_ptr += size; - - for (unsigned int parser = 0; parser < 32; parser++) - { - mg_array[*curr_loc_ptr] = palette_array[parser / 2] >> (8 * (parser % 2)); - (*curr_loc_ptr)++; - } -} - -// MUSIC VAR - -void music_var::set_start() -{ - start_location_in_script = *curr_loc_ptr; -} - -void music_var::add_track(const byte* trackBytes, size_t trackSize) -{ - const ptgb::vector track(trackBytes, trackSize); - trackArrays.push_back(track); -} - -void music_var::insert_music_data(u8 mg_array[], u8 blockCount, u8 priority, u8 reverb, u32 toneDataPointer) -{ - for (unsigned int i = 0; i < trackArrays.size(); i++) - { - trackPointers.push_back(*curr_loc_ptr + curr_GBA_rom.loc_gSaveDataBuffer); - for (unsigned int j = 0; j < trackArrays[i].size(); j++) - { - mg_array[(*curr_loc_ptr)++] = trackArrays[i][j]; - } - } - - while ((*curr_loc_ptr) % 4 != 0) - { - (*curr_loc_ptr)++; - } - set_start(); - mg_array[(*curr_loc_ptr)++] = trackArrays.size(); - mg_array[(*curr_loc_ptr)++] = blockCount; - mg_array[(*curr_loc_ptr)++] = priority; - mg_array[(*curr_loc_ptr)++] = reverb; - for (int i = 0; i < 4; i++) - { - mg_array[(*curr_loc_ptr)++] = toneDataPointer >> (8 * i); - } - - for (unsigned int i = 0; i < trackArrays.size(); i++) - { - mg_array[(*curr_loc_ptr)++] = trackPointers[i] >> 0; - mg_array[(*curr_loc_ptr)++] = trackPointers[i] >> 8; - mg_array[(*curr_loc_ptr)++] = trackPointers[i] >> 16; - mg_array[(*curr_loc_ptr)++] = trackPointers[i] >> 24; - } -} diff --git a/tools/gba-payload-generator/include/script_var.h b/tools/gba-payload-generator/include/script_var.h index ec9d7df..3f82f70 100644 --- a/tools/gba-payload-generator/include/script_var.h +++ b/tools/gba-payload-generator/include/script_var.h @@ -3,6 +3,7 @@ #include #include +#include using u8 = uint8_t; using u16 = uint16_t; diff --git a/tools/gba-payload-generator/src/main.cpp b/tools/gba-payload-generator/src/main.cpp index bf8fc32..43cdb13 100644 --- a/tools/gba-payload-generator/src/main.cpp +++ b/tools/gba-payload-generator/src/main.cpp @@ -35,15 +35,6 @@ static const uint16_t gen3CharsetEng[256]{ 0x20, 0x20, 0x15E, 0x23C, 0x206, 0x1B2, 0x147, 0x19E }; -static const std::pair languageMap[] = { - {"english", LANG_ENG}, - {"french", LANG_FRE}, - {"spanish", LANG_SPA}, - {"italian", LANG_ITA}, - {"german", LANG_GER}, - {"japanese", LANG_JPN} -}; - static const std::pair romIdStringMap[] = { {RUBY_ID, "ruby"}, {SAPPHIRE_ID, "sapphire"}, @@ -67,23 +58,6 @@ static const std::pair romLanguageStringMap[] = { { LANG_SPA, "spanish" } }; -/** - * @brief This function parses the language cmdline arg and returns the corresponding language code. - * Note: if the language is not recognized, it defaults to LANG_ENG (English). - */ -static char parseLanguageArg(const char *languageArg) -{ - size_t numLangs = sizeof(languageMap) / sizeof(languageMap[0]); - for (size_t i = 0; i < numLangs; ++i) - { - if (strcmp(languageArg, languageMap[i].first) == 0) - { - return languageMap[i].second; - } - } - return LANG_ENG; -} - /** * @brief Template utility function to look up a string conversion from a pair list. */ @@ -163,55 +137,20 @@ static void generateOutputPath(char *outputPathBuffer, const char *outputDir, co static void printUsage() { - printf("Usage: mystery_gift_builder path/to/RSEFRLG_text_table.bin language outputPath\n"); + printf("Usage: mystery_gift_builder path/to/RSEFRLG_text_table.bin outputPath\n"); printf(" path/to/RSEFRLG_text_table.bin: Path to the input RSEFRLG text table file.\n"); - printf(" language: (english, french, spanish, italian, german, japanese)\n"); printf(" outputPath: Path to a directory to output our language-specific payloads to.\n\n"); printf("gba-payload-generator will generate all payloads for the specified language.\n"); } -int main(int argc, char **argv) +static void generatePayloadsForLanguage(const char* outputPath, char languageCode, u8 *textTableBuffer, uint32_t textTableSize) { u8 section30Buffer[FLASH_SECTOR_SIZE]; u8 mgScriptBuffer[MG_SCRIPT_SIZE]; char outputPathBuffer[PATH_MAX]; - u8 *textTableBuffer = nullptr; - uint32_t textTableSize = 0; const ROM_DATA *gbaRomDataArray; uint16_t gbaRomDataArraySize; - char languageCode; - // set up dependencies. - FILE *text_table_file = fopen(argv[1], "rb"); - if (!text_table_file) - { - fprintf(stderr, "Error: Could not open RSEFRLG text table file %s!\n", argv[1]); - printUsage(); - return 1; - } - - // determine file size and allocate buffer - fseek(text_table_file, 0, SEEK_END); - textTableSize = ftell(text_table_file); - fseek(text_table_file, 0, SEEK_SET); - textTableBuffer = new u8[textTableSize]; - - // read RSEFRLG text table into buffer - size_t read_size = fread(textTableBuffer, 1, textTableSize, text_table_file); - if (read_size != textTableSize) - { - fprintf(stderr, "Error: Could not read RSEFRLG text table file %s!\n", argv[1]); - printUsage(); - - delete[] textTableBuffer; - textTableBuffer = nullptr; - - fclose(text_table_file); - return 1; - } - fclose(text_table_file); - - languageCode = parseLanguageArg(argv[2]); pickGBARomDataArray(languageCode, gbaRomDataArray, gbaRomDataArraySize); // now we can start the real work. @@ -223,7 +162,7 @@ int main(int argc, char **argv) for(size_t i = 0; i < gbaRomDataArraySize; ++i) { - generateOutputPath(outputPathBuffer, argv[3], "section30", gbaRomDataArray + i); + generateOutputPath(outputPathBuffer, outputPath, "section30", gbaRomDataArray + i); printf("Generating %zu:%s...\n", i, outputPathBuffer); builder.build_script(rsefrlgTableReader, gbaRomDataArray[i], gen3CharsetEng, nullptr, true); @@ -242,7 +181,7 @@ int main(int argc, char **argv) } fclose(section30OutputFile); - generateOutputPath(outputPathBuffer, argv[3], "script", gbaRomDataArray + i); + generateOutputPath(outputPathBuffer, outputPath, "script", gbaRomDataArray + i); printf("Generating %zu:%s...\n", i, outputPathBuffer); FILE *mgScriptOutputFile = fopen(outputPathBuffer, "wb"); if (!mgScriptOutputFile) @@ -258,6 +197,57 @@ int main(int argc, char **argv) } fclose(mgScriptOutputFile); } +} + +int main(int argc, char **argv) +{ + u8 *textTableBuffer = nullptr; + uint32_t textTableSize = 0; + char languageCode; + + if(argc != 3) + { + printUsage(); + return 1; + } + + // set up dependencies. + FILE *text_table_file = fopen(argv[1], "rb"); + if (!text_table_file) + { + fprintf(stderr, "Error: Could not open RSEFRLG text table file %s!\n", argv[1]); + printUsage(); + return 1; + } + + // determine file size and allocate buffer + fseek(text_table_file, 0, SEEK_END); + textTableSize = ftell(text_table_file); + fseek(text_table_file, 0, SEEK_SET); + textTableBuffer = new u8[textTableSize]; + + // read RSEFRLG text table into buffer + const size_t read_size = fread(textTableBuffer, 1, textTableSize, text_table_file); + if (read_size != textTableSize) + { + fprintf(stderr, "Error: Could not read RSEFRLG text table file %s!\n", argv[1]); + printUsage(); + + delete[] textTableBuffer; + textTableBuffer = nullptr; + + fclose(text_table_file); + return 1; + } + fclose(text_table_file); + + const char langCodes[] = { LANG_ENG, LANG_FRE, LANG_SPA, LANG_ITA, LANG_GER, LANG_JPN }; + + for(char langCode : langCodes) + { + printf("Generating payloads for language code %c...\n", langCode); + generatePayloadsForLanguage(argv[2], langCode, textTableBuffer, textTableSize); + } delete[] textTableBuffer; textTableBuffer = nullptr; diff --git a/tools/gba-payload-generator/src/mystery_gift_builder.cpp b/tools/gba-payload-generator/src/mystery_gift_builder.cpp index 2176efd..03f9205 100644 --- a/tools/gba-payload-generator/src/mystery_gift_builder.cpp +++ b/tools/gba-payload-generator/src/mystery_gift_builder.cpp @@ -974,6 +974,7 @@ void mystery_gift_script::checkflag(u16 flag_id) void mystery_gift_script::virtualgotoif(u8 condition, u32 location) { + (void)location; //unused parameter, but the add_reference() call in the script is needed. value_buffer[0] = 0xBB; value_buffer[1] = condition; value_buffer[2] = (VIRTUAL_ADDRESS >> 0) & 0xFF; @@ -985,6 +986,7 @@ void mystery_gift_script::virtualgotoif(u8 condition, u32 location) void mystery_gift_script::virtualmsgbox(u32 location) { + (void)location; //unused parameter, but the add_reference() call in the script is needed. value_buffer[0] = 0xBD; value_buffer[1] = (VIRTUAL_ADDRESS >> 0) & 0xFF; value_buffer[2] = (VIRTUAL_ADDRESS >> 8) & 0xFF; @@ -1415,7 +1417,7 @@ void mystery_gift_script::and1(u8 rd, u8 rm) */ void mystery_gift_script::ldr2(u8 rd, u8 rn, u8 rm) { - add_asm(0b0101100 << 9 | rm << 6 | rm << 3 | rd); + add_asm(0b0101100 << 9 | rm << 6 | rn << 3 | rd); } /** * @brief STRH (1) (Store Register Halfword) stores 16-bit data from a general-purpose register to memory. The addressing mode is useful for accessing structure (record) fields. With an offset of zero, the address produced is the unaltered value of the base register .