diff --git a/include/debug_mode.h b/include/debug_mode.h index 7341585..efbef62 100644 --- a/include/debug_mode.h +++ b/include/debug_mode.h @@ -2,8 +2,8 @@ #define DEBUG_MODE_H #define DEBUG_MODE true -#define DEBUG_GAME EMERALD_ID -#define DEBUG_VERS VERS_1_0 +#define DEBUG_GAME LEAFGREEN_ID +#define DEBUG_VERS VERS_1_1 // This is literally it. Yay. #endif \ No newline at end of file diff --git a/include/pokemon.h b/include/pokemon.h index 11b5faf..c087568 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -33,6 +33,7 @@ public: u32 generate_pid(byte pid_species_index, byte nature, byte *pid_ivs); byte rand_reverse_mod(byte modulo_divisor, byte target_mod); byte get_rand_gender_byte(byte index_num, byte attack_DVs); + byte get_dex_number(); private: diff --git a/include/script_array.h b/include/script_array.h index bfcec46..743b6e0 100644 --- a/include/script_array.h +++ b/include/script_array.h @@ -73,6 +73,5 @@ void populate_script(); void populate_dialouge(); void add_script_party_var(Pokemon_Party var); bool run_conditional(int index); -std::string_view format_text(std::string_view text); #endif \ No newline at end of file diff --git a/include/script_builder.h b/include/script_builder.h index 9be1469..2e02dfc 100644 --- a/include/script_builder.h +++ b/include/script_builder.h @@ -28,14 +28,19 @@ #define TEXT_FULL 2 #define TEXT_RECEIVED 3 -#define NUM_ASM_OFFSET 4 +#define NUM_ASM_OFFSET 8 #define ASM_OFFSET_PKMN_OFFSET 0 #define ASM_OFFSET_PKMN_STRUCT 1 #define ASM_OFFSET_SENDMON_PTR 2 #define ASM_OFFSET_BOX_SUC_PTR 3 +#define ASM_OFFSET_DEX_ASM_PTR_1 4 +#define ASM_OFFSET_DEX_SEEN_CAUGHT 5 +#define ASM_OFFSET_DEX_STRUCT 6 +#define ASM_OFFSET_INDEX 7 -#define NUM_RELATIVE_PTR 1 +#define NUM_RELATIVE_PTR 1 // THIS STAYS AS 1, THERE IS NO RELATIVE POINTER TO DEX AT THE MOMENT, IT IS A STATIC 28!!! #define REL_PTR_ASM_START 0 +#define REL_PTR_DEX_START 1 #define COND_LESSTHAN 0 #define COND_EQUALS 1 @@ -91,7 +96,7 @@ class mystery_gift_script // Ň = New line // ƞ = string terminator { - u": Hey ƲÀ!ȼPROFESSOR FENNEL told me that theseŇwere for you!ȼDon’t worry about making room…ŇI’ll send them to the PC!", + u": Hey ƲÀ!ȼPROFESSOR FENNEL",// told me that theseŇwere for you!ȼDon’t worry about making room…ŇI’ll send them to the PC!", u": Thanks for helping out FENNEL!", u": It looks like the PC is full…ȼCome back once you have more room!", u"ƲÀ’S POKÉMON were sent to the PC!", @@ -132,6 +137,7 @@ private: u8 asm_offset_distance(u8 asm_offset_id); void four_align(); void set_ptr_destination(u8 relative_ptr_id); + void add_padding(); // Scripting commands void setvirtualaddress(u32 location); @@ -145,13 +151,16 @@ private: 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 release(); void end(); + // ASM commands void push(u16 register_list); @@ -164,6 +173,10 @@ private: 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); + // Custom scripting/ASM commands }; diff --git a/source/main.cpp b/source/main.cpp index c5f964b..86b1ce9 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -48,7 +48,12 @@ INJECTION: - Set flags for the number of Pokemon injected - Set Pokedex flags - Check what happens when the PC is full, but the last Pokemon doesn't exist (is zero) -- Set text color for FRLG (what happens if you set it in RSE?) +- Set text color for FRLG for when a Pokemon is sent (what happens if you set it in RSE?) +- Check text overflow for the "recieved" text. What happens if the name is too long? + Maybe use the standard function for that? https://www.pokecommunity.com/showthread.php?t=201077 +- Figure out how to shrink the size of the mystery gift script. Especially with padding? idk, there's a lot of + multiple FFs and 00s + I think we can combine some of the ldr and add functions. SAVE DATA: - Add warning diff --git a/source/pokemon.cpp b/source/pokemon.cpp index d2cba53..b8df61b 100644 --- a/source/pokemon.cpp +++ b/source/pokemon.cpp @@ -552,4 +552,8 @@ byte Pokemon::get_rand_gender_byte(byte index_num, byte attack_DVs) { return get_rand_range(gen3_threshold, 256); } +} + +byte Pokemon::get_dex_number(){ + return species_index_party; } \ No newline at end of file diff --git a/source/script_array.cpp b/source/script_array.cpp index 4e03abe..a637eb1 100644 --- a/source/script_array.cpp +++ b/source/script_array.cpp @@ -17,7 +17,7 @@ void populate_dialouge() dialouge[DIA_INDEX_E4_1] = "Hi trainer! I'm thrilled\nyou've decided to help with our research, but we need\nthe best of the best!"; dialouge[DIA_INDEX_E4_2] = "Come back once you've taken down the Elite Four!"; dialouge[DIA_INDEX_MG] = "Looks like Mystery gift isn't enabled..."; - dialouge[DIA_INDEX_START] = format_text("Alright then, let's get started! Please connect your Game Boy Advance to a Game Boy family system, using a Game Boy Color link cable. Load the Game Boy Pokemon game you want to transfer Pokemon from. Once both devices have been connected and the Game Boy Pokemon game has been loaded, press A."); + dialouge[DIA_INDEX_START] = "Alright then, let's get started! Please connect your Game Boy Advance to a Game Boy family system, using a Game Boy Color link cable. Load the Game Boy Pokemon game you want to transfer Pokemon from. Once both devices have been connected and the Game Boy Pokemon game has been loaded, press A."; dialouge[DIA_INDEX_ERROR_1] = "Hmm, it looks like something isn't right. Let's try that again!"; dialouge[DIA_INDEX_CONN_GOOD] = "Great! Now head to the nearest Pokemon Center. Put any Pokemon you wish to bring out of your dreams into your party, and go to the Cable Club attendant. Ask them to perform a Link Trade, and then press A."; dialouge[DIA_INDEX_LINK_GOOD] = "We're almost set! Once you're ready, talk to the trainer across the table from you to start the process!"; @@ -30,13 +30,15 @@ void populate_dialouge() void populate_script() { + script[SCRIPT_START] = script_obj(CMD_SHOW_PROF, COND_BEAT_E4); script[COND_BEAT_E4] = script_obj(COND_BEAT_E4, COND_MG_ENABLED, DIA_F_E4_1); script[COND_MG_ENABLED] = script_obj(COND_MG_ENABLED, DIA_F_START, DIA_F_MG); script[CMD_BACK_TO_MENU] = script_obj(CMD_BACK_TO_MENU, SCRIPT_START); - script[DIA_F_START] = script_obj(dialouge[DIA_INDEX_START], CMD_BACK_TO_MENU); + script[DIA_F_START] = script_obj("welcome", CMD_START_LINK, DIA_F_CONN_GOOD); + script[DIA_F_CONN_GOOD] = script_obj("good", CMD_IMPORT_POKEMON, CMD_BACK_TO_MENU); script[DIA_F_E4_1] = script_obj(dialouge[DIA_INDEX_E4_1], DIA_F_E4_2); script[DIA_F_E4_2] = script_obj(dialouge[DIA_INDEX_E4_2], CMD_HIDE_PROF, CMD_BACK_TO_MENU); script[DIA_F_MG] = script_obj(dialouge[DIA_INDEX_MG], CMD_HIDE_PROF, CMD_BACK_TO_MENU); @@ -127,30 +129,4 @@ bool run_conditional(int index) tte_write("ERROR! No conditional found."); return false; } -} - -#define BOX_LENGTH 28 - -std::string_view format_text(std::string_view text) -{ - std::string out; - int last_space = 0; - int curr_line_length = 0; - for (unsigned int i = 0; i < text.size(); i++) - { - if (text.at(i) == ' ') - { - last_space = i; - } - if (curr_line_length >= BOX_LENGTH) - { - i = last_space; - out += '\n'; - } - else - { - out += text.at(i); - } - } - return (std::string_view)out; } \ No newline at end of file diff --git a/source/script_builder.cpp b/source/script_builder.cpp index a23a529..30a75a2 100644 --- a/source/script_builder.cpp +++ b/source/script_builder.cpp @@ -10,8 +10,10 @@ int var_call_return_1 = (VAR_ID_START + 0x03); 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_index = (VAR_ID_START + 0x07); -int var_pkmn_offset = (VAR_ID_START + 0x08); +int var_dex_seen_caught = (VAR_ID_START + 0x07); +int var_dex_num = (VAR_ID_START + 0x08); +int var_index = (VAR_ID_START + 0x09); +int var_pkmn_offset = (VAR_ID_START + 0x0A); // FIX SWAPPING 0x8008 AND MAKE THE CODE COMMENTS CORRECT int ptr_callASM; int ptr_script_ptr_low; @@ -20,6 +22,7 @@ int ptr_call_return_1; 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; @@ -37,6 +40,7 @@ int flag_all_collected = (FLAG_ID_START + 0x6); int loc_sendMonToPC; int loc_gSpecialVar_0x8000; int loc_gSaveBlock1PTR; +int loc_setPokedexFlag; int offset_ramscript; // Source: https://github.com/pret/pokeemerald/blob/master/include/global.h#L1012 int offset_flags; // Flag offset as found within the SaveBlock1 struct in global.h int offset_wondercard; @@ -62,6 +66,7 @@ mystery_gift_script::mystery_gift_script() loc_sendMonToPC = 0; loc_gSpecialVar_0x8000 = 0; loc_gSaveBlock1PTR = 0; + loc_setPokedexFlag = 0; offset_ramscript = 0; offset_flags = 0; break; @@ -69,6 +74,7 @@ mystery_gift_script::mystery_gift_script() loc_sendMonToPC = 0; loc_gSpecialVar_0x8000 = 0; loc_gSaveBlock1PTR = 0; + loc_setPokedexFlag = 0; offset_ramscript = 0; offset_flags = 0; break; @@ -76,6 +82,7 @@ mystery_gift_script::mystery_gift_script() loc_sendMonToPC = 0; loc_gSpecialVar_0x8000 = 0; loc_gSaveBlock1PTR = 0; + loc_setPokedexFlag = 0; offset_ramscript = 0; offset_flags = 0; break; @@ -94,6 +101,7 @@ mystery_gift_script::mystery_gift_script() loc_sendMonToPC = 0; loc_gSpecialVar_0x8000 = 0; loc_gSaveBlock1PTR = 0; + loc_setPokedexFlag = 0; offset_ramscript = 0; offset_flags = 0; break; @@ -101,6 +109,7 @@ mystery_gift_script::mystery_gift_script() loc_sendMonToPC = 0x08040BA4; loc_gSpecialVar_0x8000 = 0x020370B8; loc_gSaveBlock1PTR = 0x03005008; + loc_setPokedexFlag = 0x08088e5c; offset_ramscript = 0x361C; offset_flags = 0x0EE0; break; @@ -116,6 +125,7 @@ mystery_gift_script::mystery_gift_script() loc_sendMonToPC = 0x0806B490; loc_gSpecialVar_0x8000 = 0x020375D8; loc_gSaveBlock1PTR = 0x03005D8C; + loc_setPokedexFlag = 0; offset_ramscript = 0x3728; offset_flags = 0x1270; break; @@ -128,8 +138,9 @@ mystery_gift_script::mystery_gift_script() ptr_call_check_flag = (loc_gSpecialVar_0x8000 + 0x08); ptr_call_return_2 = (loc_gSpecialVar_0x8000 + 0x0A); ptr_box_return = (loc_gSpecialVar_0x8000 + 0x0C); - ptr_index = (loc_gSpecialVar_0x8000 + 0x0E); - ptr_pkmn_offset = (loc_gSpecialVar_0x8000 + 0x10); + ptr_dex_seen_caught = (loc_gSpecialVar_0x8000 + 0x0E); + ptr_index = (loc_gSpecialVar_0x8000 + 0x12); + ptr_pkmn_offset = (loc_gSpecialVar_0x8000 + 0x14); // EXPLAIN HERE TOO. Also like, we can and it?? ptr_block_ptr_low = (loc_gSaveBlock1PTR + 0x00); ptr_block_ptr_high = (loc_gSaveBlock1PTR + 0x02); @@ -160,69 +171,125 @@ void mystery_gift_script::build_script(Pokemon incoming_party_array[]) setvar(var_call_check_flag, rev_endian(0x2B00)); // Set the variable to 0x2B. 0x2B = CHECK FLAG addvar(var_call_check_flag, rev_endian(FLAG_ID_START)); // Add the starting flag ID to the check flag ASM variable setvar(var_call_return_2, rev_endian(0x0003)); // Set the variable to 0x03. 0x03 = RETURN - set_jump_destination(JUMP_LOOP); // Set the jump destination for the JUMP_LOOP + /**/ set_jump_destination(JUMP_LOOP); // Set the jump destination for the JUMP_LOOP call(ptr_call_check_flag); // Call the check flag ASM virtualgotoif(COND_FLAGFALSE, JUMP_PKMN_COLLECTED); // If the "pokemon collected" flag is false, jump to the end of the loop call(ptr_callASM); // Call SendMonToPC ASM compare(var_box_return, 2); // Compare the resulting return to #2 virtualgotoif(COND_EQUALS, JUMP_BOX_FULL); // If the return value was #2, jump to the box full message - set_jump_destination(JUMP_PKMN_COLLECTED); // 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, 6); // Compare the index to 6 - virtualgotoif(COND_LESSTHAN, JUMP_LOOP); // if index is less than six, jump to the start of the loop - setflag(flag_all_collected); // Set the "all collected" flag - fanfare(0xA4); // Play the received fanfare - virtualmsgbox(TEXT_RECEIVED); // 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 - set_jump_destination(JUMP_ALL_COLLECTED); // Set the destination for if all the Pokemon have already been collected - virtualmsgbox(TEXT_THANK); // Display the thank test - waitmsg(); // Wait for the message - waitkeypress(); // Wait for the player to press A/B - release(); // Release the player - end(); // End the script - set_jump_destination(JUMP_BOX_FULL); // Set the destination for if the box is full - virtualmsgbox(TEXT_FULL); // 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 + addvar(var_script_ptr_low, 28); // This is stupid. 28 is the size of the main ASM function + setvar(var_dex_num, 6); + setvar(var_dex_seen_caught, 2); + call(ptr_callASM); // This should really be changed so that the size isn't static + addvar(var_dex_seen_caught, 1); + call(ptr_callASM); + subvar(var_script_ptr_low, 28); // But it is 11:30 and I can't be bothered right now. It works :| + /**/ set_jump_destination(JUMP_PKMN_COLLECTED); // 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, 6); // Compare the index to 6 + virtualgotoif(COND_LESSTHAN, JUMP_LOOP); // if index is less than six, jump to the start of the loop + setflag(flag_all_collected); // Set the "all collected" flag + fanfare(0xA4); // Play the received fanfare + virtualmsgbox(TEXT_RECEIVED); // 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 + /**/ set_jump_destination(JUMP_ALL_COLLECTED); // Set the destination for if all the Pokemon have already been collected + virtualmsgbox(TEXT_THANK); // Display the thank test + waitmsg(); // Wait for the message + waitkeypress(); // Wait for the player to press A/B + release(); // Release the player + end(); // End the script + /**/ set_jump_destination(JUMP_BOX_FULL); // Set the destination for if the box is full + virtualmsgbox(TEXT_FULL); // 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 insert_textboxes(); four_align(); - set_ptr_destination(REL_PTR_ASM_START); + /**/ set_ptr_destination(REL_PTR_ASM_START); push(rlist_lr); // save the load register to the stack - ldr3(r3, asm_offset_distance(ASM_OFFSET_PKMN_OFFSET)); // set r3 to variable to the pokemon offset, variable 0x8008's pointer + ldr3(r3, asm_offset_distance(ASM_OFFSET_PKMN_OFFSET)); // set r3 to the pokemon offset, variable 0x8008's pointer ldr1(r3, r3, 0); // set r3 to the value in memory r3 points to add5(r0, asm_offset_distance(ASM_OFFSET_PKMN_STRUCT)); // set r0 to a pointer 28 bytes ahead, which is the start of the Pokemon struct. add3(r0, r0, r3); // add r3 to r0, giving it the correct offset for the current index ldr3(r1, asm_offset_distance(ASM_OFFSET_SENDMON_PTR)); // 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 7 to r2 to compensate for the four following bytes, plus to tell the system to read as thumb code + 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, asm_offset_distance(ASM_OFFSET_BOX_SUC_PTR)); // 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) - set_asm_offset_destination(ASM_OFFSET_SENDMON_PTR); // set the SENDMON ptr offset - add_word(loc_sendMonToPC + READ_AS_THUMB); // the location of "SendMonToPC", plus one (so it is interpreted as thumb code) - set_asm_offset_destination(ASM_OFFSET_BOX_SUC_PTR); // set the BOX_SUCCESS ptr offset - add_word(ptr_box_return); // the location of variable "0x8006" (the return value) - set_asm_offset_destination(ASM_OFFSET_PKMN_OFFSET); // set the PKMN_OFFSET ptr offset - add_word(ptr_pkmn_offset); // the location of variable "0x8008" (the pokemon offset) - set_asm_offset_destination(ASM_OFFSET_PKMN_STRUCT); // set the PKMN_STRUCT ptr offset + + /**/ set_ptr_destination(REL_PTR_DEX_START); + push(rlist_lr); + ldr3(r0, asm_offset_distance(ASM_OFFSET_INDEX)); + ldr1(r0, r0, 0); + mov1(r3, 0xFF); + and1(r0, r3); + add5(r1, asm_offset_distance(ASM_OFFSET_DEX_STRUCT)); + add3(r0, r0, r1); + ldr1(r0, r0, 0); + and1(r0, r3); + + // Instead of what we have, set r0 to the value of index, and then add the ASM_OFFSET_DEX_STRUCT, + // since that's the current memory location. That *should* make it work. Also AND it with 0xFF. Same with r1, + // and the index value in general. Idk why I didn't do that earlier + // matter of fact... is index already stored somewhere else? + // No, we store the offset, not the index. And that really should be AND'd as well... but that's gonna be + // two extra bytes. But it's good coding so eh idk. I mean *two* bytes isn't awful for stabilitiy... + + // There are issues! But he shows up lol. I'll take it. + + ldr3(r1, asm_offset_distance(ASM_OFFSET_DEX_SEEN_CAUGHT)); + ldr1(r1, r1, 0); + and1(r1, r3); + ldr3(r2, asm_offset_distance(ASM_OFFSET_DEX_ASM_PTR_1)); + mov3(r3, r15); + add2(r3, 5); + mov3(r14, r3); + + bx(r2); + 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) + + add_padding(); + set_asm_offset_destination(ASM_OFFSET_SENDMON_PTR); // set the SENDMON ptr offset + add_word(loc_sendMonToPC + READ_AS_THUMB); // the location of "SendMonToPC", plus one (so it is interpreted as thumb code) + set_asm_offset_destination(ASM_OFFSET_BOX_SUC_PTR); // set the BOX_SUCCESS ptr offset + add_word(ptr_box_return); // the location of variable "0x8006" (the return value) + set_asm_offset_destination(ASM_OFFSET_PKMN_OFFSET); // set the PKMN_OFFSET ptr offset + add_word(ptr_pkmn_offset); // the location of variable "0x8008" (the pokemon offset) + set_asm_offset_destination(ASM_OFFSET_DEX_ASM_PTR_1); + add_word(loc_setPokedexFlag + READ_AS_THUMB); + set_asm_offset_destination(ASM_OFFSET_DEX_SEEN_CAUGHT); + add_word(ptr_dex_seen_caught); + set_asm_offset_destination(ASM_OFFSET_INDEX); + add_word(ptr_index); + + set_asm_offset_destination(ASM_OFFSET_DEX_STRUCT); + + for (int i = 0; i < 6; i++) + { + mg_script[curr_index] = incoming_party_array[i].get_dex_number(); // FIX MEEEEE + curr_index++; + } + curr_index += 2; // make the offset a multiple of 4 + + set_asm_offset_destination(ASM_OFFSET_PKMN_STRUCT); // set the PKMN_STRUCT ptr offset for (int i = 0; i < 6; i++) { - Pokemon curr_pkmn = incoming_party_array[i]; for (int curr_byte = 0; curr_byte < POKEMON_SIZE; curr_byte++) { - mg_script[curr_index] = curr_pkmn.get_gen_3_data(curr_byte); + mg_script[curr_index] = incoming_party_array[i].get_gen_3_data(curr_byte); curr_index++; } } @@ -519,6 +586,16 @@ void mystery_gift_script::addvar(u16 var_id, u16 value) 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; @@ -561,6 +638,14 @@ void mystery_gift_script::waitfanfare() 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::release() { value_buffer[0] = 0x6C; @@ -694,6 +779,37 @@ 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); +} void mystery_gift_script::add_word(u32 word) { @@ -734,4 +850,12 @@ void mystery_gift_script::fill_relative_pointers() void mystery_gift_script::set_ptr_destination(u8 relative_ptr_id) { relative_offset_destination[relative_ptr_id] = curr_index - 4; +} + +void mystery_gift_script::add_padding() +{ + if (curr_index % 4 != 0) + { + add_asm(0x0000); + } } \ No newline at end of file