From a4bda4c67377eee4b163f608ff8aa91dd4d7dcd6 Mon Sep 17 00:00:00 2001 From: Remnants of Forgotten Disney Date: Wed, 17 Apr 2024 09:17:15 -0500 Subject: [PATCH] Adding in event stabilization --- README.md | 11 +- graphics/button_no.grit | 3 + graphics/button_no.png | Bin 0 -> 235 bytes graphics/button_yes.grit | 3 + graphics/button_yes.png | Bin 0 -> 249 bytes include/debug_mode.h | 10 +- include/main_menu.h | 2 + include/pokemon.h | 19 +- include/pokemon_data.h | 11 +- include/pokemon_party.h | 7 +- include/random.h | 8 +- include/script_array.h | 9 +- include/sprite_data.h | 4 + source/global_frame_controller.cpp | 9 + source/main.cpp | 6 + source/pokemon.cpp | 391 +++++++++++++++++++++++------ source/pokemon_data.cpp | 187 ++++++++------ source/pokemon_party.cpp | 24 +- source/random.cpp | 17 +- source/script_array.cpp | 13 +- source/sprite_data.cpp | 90 +++++-- 21 files changed, 609 insertions(+), 215 deletions(-) create mode 100644 graphics/button_no.grit create mode 100644 graphics/button_no.png create mode 100644 graphics/button_yes.grit create mode 100644 graphics/button_yes.png diff --git a/README.md b/README.md index 931c077..e8af2da 100644 --- a/README.md +++ b/README.md @@ -25,9 +25,16 @@ Please note that transfering Pokémon will only work with a Game Boy Color Link Due to limitations of the transfer process, some Pok@mon will not be considered legal until they reach certain generations: -| Pok@mon | Generation III | Generation IV | Generation V | Passes through Pok@mon Bank | Generation VI | Generation VII+ | +| Pokémon | Generation III | Generation IV | Generation V | Passes through Pokémon Bank | Generation VI | Generation VII+ | |---|---|---|---|---|---|---| -| Standard Pok@mon from Generation I | No\n(Illegal Met Location)| Yes | Yes | Yes | Yes | Yes | +| Standard Pokémon from Generation I | No\n(Illegal Met Location)| Yes | Yes | Yes | Yes | Yes | +| Standard Pokémon from Generation II | No\n(Illegal Met Location, Illegal Game of Origin)| No\n(Illegal Encounter type) | No\n(Illegal Encounter type) | Yes | No\n(Illegal Encounter type) | Yes | +| Legendary Pokémon from Generation I | No\n(Illegal Met Location)| Yes | Yes | Yes | Yes | Yes | +| Legendary Pokémon from Generation II | No\n(Illegal Met Location, Illegal Game of Origin)| No\n(Illegal Encounter type) | No\n(Illegal Encounter type) | Yes | No\n(Illegal Encounter type) | Yes | +| Mew from Generation I/II | No\n(Does not match event)| No\n(Does not match event) | No\n(Does not match event) | Yes\n(No if Shiny) |No\n(Does not match event) | No\n(Does not match event) | +| Celebi from Generation II | No\n(Does not match event)| No\n(Does not match event) | No\n(Does not match event) | Yes\n(No if Shiny) |No\n(Does not match event) | No\n(Does not match event) | +| Stabilized Mew | Yes | Yes | Yes | Yes | Yes | Yes | +| Stabilized Celebi | Yes | Yes | Yes | Yes | Yes | Yes | diff --git a/graphics/button_no.grit b/graphics/button_no.grit new file mode 100644 index 0000000..aa1971c --- /dev/null +++ b/graphics/button_no.grit @@ -0,0 +1,3 @@ +# +# Button : 4bpp, not compressed. Pallet 2, copy from 32 to 48. +-gB4 -ps32 -pe48 \ No newline at end of file diff --git a/graphics/button_no.png b/graphics/button_no.png new file mode 100644 index 0000000000000000000000000000000000000000..d3cbfaf39fda12f3c0a5cf6ba0a2b1ebf6c1161e GIT binary patch literal 235 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!VDw>HYaZfQU(D&A+AS{9yPQy{PF+C|NsAi zVg$iG``lKbBF2&+zhDN3XE)M-oJ>y_$B>FSZzr7=JfOhg;>(`6mchE_ezH9YK2^=9>?ia_si);uanr5H2SS@K2yJfA`LVcx<8YKj>Vvc9k^+LAVNKeJ yd$hY$DDsVVuJej&%EX}Z#0U87EPA|In&eC&t;ucLK6U*%1LAZ literal 0 HcmV?d00001 diff --git a/graphics/button_yes.grit b/graphics/button_yes.grit new file mode 100644 index 0000000..aa1971c --- /dev/null +++ b/graphics/button_yes.grit @@ -0,0 +1,3 @@ +# +# Button : 4bpp, not compressed. Pallet 2, copy from 32 to 48. +-gB4 -ps32 -pe48 \ No newline at end of file diff --git a/graphics/button_yes.png b/graphics/button_yes.png new file mode 100644 index 0000000000000000000000000000000000000000..bdde91f8472908a253c8d8bd0018cd6e814df6b6 GIT binary patch literal 249 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!VDw>HYaZfQU(D&A+AS{9yPQy{PF+C|NsAi zVg$iG``lKbBF2&+zhDN3XE)M-oN`YW$B>FSZ!et|Y*64~33zirM^r`D;M@J#iBArF zI_cQI?lDh$dQ;<+d(Q<M4i8Rn zVD1+C>YShW>b=mGwMpC?n9s+riE=6CaIkpw!sPJp1Iu-J4rzaXKKsrBLk(q~OQ+R9 Oj`no*b6Mw<&;$Uk=2BJw literal 0 HcmV?d00001 diff --git a/include/debug_mode.h b/include/debug_mode.h index 8a0d2ef..58534e5 100644 --- a/include/debug_mode.h +++ b/include/debug_mode.h @@ -1,13 +1,15 @@ #ifndef DEBUG_MODE_H #define DEBUG_MODE_H -#define DEBUG_MODE false +#define DEBUG_MODE true #define IGNORE_GAME_PAK true -#define IGNORE_LINK_CABLE false +#define IGNORE_LINK_CABLE true #define IGNORE_MG_E4_FLAGS true -#define DEBUG_GAME RUBY_ID -#define DEBUG_VERS VERS_1_0 +#define DEBUG_GAME LEAFGREEN_ID +#define DEBUG_VERS VERS_1_1 #define DEBUG_LANG LANG_ENG +#define ENABLE_MATCH_PID true + #endif \ No newline at end of file diff --git a/include/main_menu.h b/include/main_menu.h index 316171d..9ae8696 100644 --- a/include/main_menu.h +++ b/include/main_menu.h @@ -46,4 +46,6 @@ private: bool cancel_enabled; }; +extern Button_Menu yes_no_menu; + #endif \ No newline at end of file diff --git a/include/pokemon.h b/include/pokemon.h index 99185df..90bb3cb 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -14,7 +14,8 @@ #define GEN2_JPN_SIZE 383 #define GEN2_INT_SIZE 444 -struct Simplified_Pokemon{ +struct Simplified_Pokemon +{ byte dex_number; byte met_level; byte nickname[10]; @@ -31,7 +32,7 @@ public: int nickname_size = 0; Pokemon(); void load_data(int index, byte *party_data, int game, int lang); - void convert_to_gen_three(); + void convert_to_gen_three(bool simplified, bool stabilize_mythical); void copy_from_to(byte *source, byte *destination, int size, bool reverse_endian); void alocate_data_chunks(byte *G, byte *A, byte *E, byte *M); void insert_data(byte *first, byte *second, byte *third, byte *fourth); @@ -39,14 +40,18 @@ public: byte *get_full_gen_3_array(); byte get_unencrypted_data(int index); byte *convert_text(byte *text_array, int size, int gen, int lang); - u32 generate_pid(byte pid_species_index, byte nature, byte *pid_ivs); + u32 generate_pid_save_iv(byte pid_species_index, byte nature, byte *pid_dvs); + u32 generate_pid_iv_match(byte pid_species_index, byte nature, byte *pid_dvs); 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(); bool get_validity(); bool get_is_new(); Simplified_Pokemon get_simple_pkmn(); - + u8 get_letter_from_pid(u32 pid); + u8 get_nature_from_pid(u32 pid); + u8 get_gender_from_pid(u32 pid); + void set_to_event(); private: byte gen = 2; @@ -63,8 +68,8 @@ private: byte caught_data[2]; byte met_level; byte gen_3_pkmn[80]; - byte unencrypted_data[49]; // Contains the 48 GAEM bytes, along with the modulo int - byte pid[4] = {0b00000001, 0b10101010, 0b11111111, 0b10011001}; // Little Endian, reverse of Bulbapedia + byte unencrypted_data[49]; // Contains the 48 GAEM bytes, along with the modulo int + byte pid[4] = {0, 0, 0, 0}; // Little Endian, reverse of Bulbapedia byte blank_word[4] = {0}; byte data_section_G[12]; byte data_section_A[12]; @@ -79,7 +84,7 @@ private: byte pure_pp_values[4]; byte dvs[2]; byte ivs[6]; - byte ribbons[4]; + byte ribbons[4] = {0, 0, 0, 0}; u32 iv_egg_ability; bool is_valid; bool is_new = false; diff --git a/include/pokemon_data.h b/include/pokemon_data.h index 5500bfb..ab45a2a 100644 --- a/include/pokemon_data.h +++ b/include/pokemon_data.h @@ -11,7 +11,6 @@ #define slow_max 1250000 #define flux_max 1640000 -#define INTERNATIONAL 0 #define JPN_ID 1 #define ENG_ID 2 #define FRE_ID 3 @@ -27,6 +26,15 @@ #define GOLD_SILVER_ID 4 #define CRYSTAL_ID 5 +#define EVENT_MEW_JPN 0 +#define EVENT_MEW_ENG 1 +#define EVENT_MEW_FRE 2 +#define EVENT_MEW_ITA 3 +#define EVENT_MEW_GER 4 +#define EVENT_MEW_SPA 5 +#define EVENT_CELEBI 6 + + #define MAX_PKMN_IN_BOX 30 extern const u8 EXP_MAX[252]; @@ -52,6 +60,7 @@ extern const u16 gen_2_FreGer_char_array[256]; extern const u16 gen_2_ItaSpa_char_array[256]; extern const u16 gen_3_Jpn_char_array[256]; extern const u16 gen_3_Intern_char_array[256]; +extern const byte EVENT_PKMN[8][80]; u32 get_max_exp(int index_num); u8 get_gender_threshold(int index_num, bool is_gen_3); diff --git a/include/pokemon_party.h b/include/pokemon_party.h index e286607..fcf283a 100644 --- a/include/pokemon_party.h +++ b/include/pokemon_party.h @@ -25,11 +25,16 @@ public: Simplified_Pokemon simple_pkmn_array[30]; Simplified_Pokemon get_simple_pkmn(int index); void fill_simple_pkmn_array(); + bool get_contains_mythical(); + void set_mythic_stabilization(bool stabilize); + private: byte box_data_array[0x462]; int last_error; - bool has_new_pkmn; + bool has_new_pkmn = false; + bool contains_mythical = false; + bool stabilize_mythic = false; int game; char lang; }; diff --git a/include/random.h b/include/random.h index ad7e89a..a717d62 100644 --- a/include/random.h +++ b/include/random.h @@ -1,9 +1,15 @@ #ifndef RANDOM_H #define RANDOM_H +#include + void rand_set_seed(unsigned int init_seed); +unsigned int rand_get_seed(); void rand_next_frame(); -unsigned int get_rand_u32(); +u32 get_rand_u32(); +u16 get_rand_u16(); +void enable_auto_random(); +void disable_auto_random(); unsigned int get_rand_range(unsigned int inc_min, unsigned int exc_max); diff --git a/include/script_array.h b/include/script_array.h index 5d6791d..f1fb867 100644 --- a/include/script_array.h +++ b/include/script_array.h @@ -35,8 +35,9 @@ #define DIA_ASK_QUEST 26 #define DIA_NO_PAYLOAD 27 #define DIA_IN_BOX 28 +#define DIA_MYTHIC_CONVERT 29 -#define DIA_SIZE 29 +#define DIA_SIZE 30 #define DIA_END DIA_SIZE // Commands @@ -54,8 +55,9 @@ #define CMD_SLIDE_PROF_RIGHT DIA_END + 11 #define CMD_CONTINUE_LINK DIA_END + 12 #define CMD_BOX_MENU DIA_END + 13 +#define CMD_MYTHIC_MENU DIA_END + 14 -#define CMD_SIZE 14 +#define CMD_SIZE 15 #define CMDS_END DIA_END + CMD_SIZE // Conditionals @@ -73,8 +75,9 @@ #define COND_MG_OTHER_EVENT CMDS_END + 11 #define COND_PKMN_TO_COLLECT CMDS_END + 12 #define COND_PAYLOAD_EXISTS CMDS_END + 13 +#define COND_CHECK_MYTHIC CMDS_END + 14 -#define COND_SIZE 14 +#define COND_SIZE 15 #define COND_END CMDS_END + COND_SIZE // Ends diff --git a/include/sprite_data.h b/include/sprite_data.h index 713ae79..1c8f19e 100644 --- a/include/sprite_data.h +++ b/include/sprite_data.h @@ -30,6 +30,10 @@ extern OBJ_ATTR *btn_c_r; extern OBJ_ATTR *btn_d_l; #include "btn_d_r.h" extern OBJ_ATTR *btn_d_r; +#include "button_yes.h" +extern OBJ_ATTR *button_yes; +#include "button_no.h" +extern OBJ_ATTR *button_no; #define SPRITE_BATCH_DEX 0 #include "dex_l.h" diff --git a/source/global_frame_controller.cpp b/source/global_frame_controller.cpp index b80e617..f8ed072 100644 --- a/source/global_frame_controller.cpp +++ b/source/global_frame_controller.cpp @@ -8,6 +8,7 @@ #include "string.h" int global_frame_count = 0; +bool rand_enabled = true; void global_next_frame() { @@ -33,4 +34,12 @@ void global_next_frame() int get_frame_count() { return global_frame_count; +} + +void enable_auto_random(){ + rand_enabled = true; +} + +void disable_auto_random(){ + rand_enabled = false; } \ No newline at end of file diff --git a/source/main.cpp b/source/main.cpp index e8dded5..887a094 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -58,6 +58,7 @@ int delay_counter = 0; bool skip = true; rom_data curr_rom; Button_Menu main_menu(3, 1, 96, 32, false); +Button_Menu yes_no_menu(1, 2, 40, 24, false); /* int test_main(void) Music @@ -103,6 +104,11 @@ void load_graphics() main_menu.add_button(Button(btn_p_l, btn_p_r, 48), BTN_POKEDEX); //main_menu.add_button(Button(btn_d_l, btn_d_r), BTN_LANGUAGE); main_menu.add_button(Button(btn_c_l, btn_c_r, 48), BTN_CREDITS); + + // Set up global yes no button + yes_no_menu.clear_vector(); + yes_no_menu.add_button(Button(button_yes), true); + yes_no_menu.add_button(Button(button_no), false); } void initalization_script(void) diff --git a/source/pokemon.cpp b/source/pokemon.cpp index 7deda79..1ca297a 100644 --- a/source/pokemon.cpp +++ b/source/pokemon.cpp @@ -3,11 +3,14 @@ #include "pokemon_data.h" #include "random.h" #include "save_data_manager.h" +#include "debug_mode.h" Pokemon::Pokemon(){}; // TODO: Rewrite this with two different classes/structs that have arrays as input/output // GBpkmn and GBApkmn +// A lot of the event Pokemon script is reused. Really should be split into many different functions +// Endian-ness too is all over the place... :/ void Pokemon::load_data(int index, byte *party_data, int game, int lang) { @@ -120,7 +123,7 @@ void Pokemon::load_data(int index, byte *party_data, int game, int lang) } } } -void Pokemon::convert_to_gen_three() +void Pokemon::convert_to_gen_three(bool simplified, bool stabilize_mythical) { // Convert the species indexes if (gen == 1) @@ -137,12 +140,119 @@ void Pokemon::convert_to_gen_three() return; } is_valid = true; + + // Update dex + if (!is_caught(species_index_struct)) + { + is_new = true; + set_caught(species_index_struct); + } + + // Set nickname + if (language == KOR_ID) + { + + gen_3_pkmn[18] = JPN_ID; // Set to JPN + byte new_nickname[10]; + byte new_ot[7]; + for (int i = 0; i < 6; i++) + { // Read the JPN name and convert it + new_nickname[i] = get_gen_3_char(JPN_NAMES[species_index_struct][i], true); + } + + if (gen == 1) + { + // レッド (Red) + new_ot[0] = 0x7A; // レ + new_ot[1] = 0xA0; // ッ + new_ot[2] = 0x95; // ド + new_ot[3] = 0xFF; + } + else + { + if (((caught_data[1] & 0b10000000) >> 7) == 1) // Checks if the Gen 2 player is male or female + { + // クリス (Kurisu) + new_ot[0] = 0x58; // ク + new_ot[1] = 0x78; // リ + new_ot[2] = 0x5D; // ス + new_ot[3] = 0xFF; + } + else + { + // ヒビキ (Hibiki) + new_ot[0] = 0x6B; // ヒ + new_ot[1] = 0x97; // ビ + new_ot[2] = 0x57; // キ + new_ot[3] = 0xFF; + } + } + copy_from_to(&new_nickname[0], &gen_3_pkmn[8], 10, false); // Nickname + copy_from_to(&new_ot[0], &gen_3_pkmn[20], 7, false); // OT Name + } + else + { + gen_3_pkmn[18] = language; // Language + copy_from_to(convert_text(&nickname[0], 10, gen, language), &gen_3_pkmn[8], 10, false); // Nickname + copy_from_to(convert_text(&trainer_name[0], 7, gen, language), &gen_3_pkmn[20], 7, false); // OT Name + } + + if (simplified) + { + return; + } + else if (stabilize_mythical && (species_index_struct == 151 || species_index_struct == 251)) + { + set_to_event(); + return; + } + // Generate PID - u32 n_pid = generate_pid(species_index_struct, *(vu32 *)exp % 25, &dvs[0]); + disable_auto_random(); + u32 n_pid; + if (ENABLE_MATCH_PID) + { + n_pid = generate_pid_iv_match(species_index_struct, *(vu32 *)exp % 25, &dvs[0]); + + u16 curr_rand = get_rand_u16(); + ivs[0] = (curr_rand >> 0) & 0b11111; + ivs[1] = (curr_rand >> 5) & 0b11111; + ivs[2] = (curr_rand >> 10) & 0b11111; + curr_rand = get_rand_u16(); + ivs[3] = (curr_rand >> 0) & 0b11111; + ivs[4] = (curr_rand >> 5) & 0b11111; + ivs[5] = (curr_rand >> 10) & 0b11111; + iv_egg_ability = 0; + for (int i = 0; i < 6; i++) + { + iv_egg_ability |= ((ivs[i] & 0b11111) << (i * 5)); + } + } + else + { + n_pid = generate_pid_save_iv(species_index_struct, *(vu32 *)exp % 25, &dvs[0]); + + // Convert and set IVs + int hp_iv = 0; + for (int i = 0; i < 4; i++) + { + ivs[i + 1] = (dvs[i / 2] >> (((i + 1) % 2) * 4)) & 0b1111; + hp_iv |= ((ivs[i + 1] & 0x1) << i); + }; + ivs[0] = hp_iv; + ivs[5] = ivs[4]; + + for (int i = 0; i < 6; i++) + { + ivs[i] = (ivs[i] * 2) + 1; + iv_egg_ability |= ((ivs[i] & 0b11111) << (i * 5)); + } + } for (int i = 0; i < 4; i++) { pid[i] = (n_pid >> (i * 8)) & 0xFF; } + enable_auto_random(); // Make sure Level is not over 100 based on EXP if (*(vu32 *)exp > get_max_exp(species_index_struct)) @@ -207,22 +317,6 @@ void Pokemon::convert_to_gen_three() pure_pp_values[i] = POWER_POINTS[moves[i]] + ((POWER_POINTS[moves[i]] / 5) * pp_bonus[i]); } - // Convert and set IVs - int hp_iv = 0; - for (int i = 0; i < 4; i++) - { - ivs[i + 1] = (dvs[i / 2] >> (((i + 1) % 2) * 4)) & 0b1111; - hp_iv |= ((ivs[i + 1] & 0x1) << i); - }; - ivs[0] = hp_iv; - ivs[5] = ivs[4]; - - for (int i = 0; i < 6; i++) - { - ivs[i] = (ivs[i] * 2) + 1; - iv_egg_ability |= ((ivs[i] & 0b11111) << (i * 5)); - } - // Determine and set Ability iv_egg_ability |= ((pid[0] & 0x1) ? get_num_abilities(species_index_struct) : 0) << 31; @@ -234,7 +328,10 @@ void Pokemon::convert_to_gen_three() // Ribbons and Obedience // ribbons[2] |= 0b00000100; // Artist Ribbon - ribbons[3] |= 0b10000000; // Fateful Encounter flag + if (species_index_struct == 151 || species_index_struct == 251) // Pokemon is Mew or Celebi + { + ribbons[3] |= 0b10000000; // Fateful Encounter flag + } // Personality Value copy_from_to(&pid[0], &gen_3_pkmn[0], 4, false); // Trainer ID @@ -253,7 +350,7 @@ void Pokemon::convert_to_gen_three() else // Not shiny, make sure it isn't { if (((trainer_id[0] ^ secret_id[0] ^ pid[0] ^ pid[2]) == 0) && - ((trainer_id[1] ^ secret_id[1] ^ pid[1] ^ pid[3]) > 7)) + ((trainer_id[1] ^ secret_id[1] ^ pid[1] ^ pid[3]) < 8)) { secret_id[0] = 0xFF; secret_id[1] = 0xFF; @@ -261,53 +358,6 @@ void Pokemon::convert_to_gen_three() } copy_from_to(&secret_id[0], &gen_3_pkmn[6], 2, false); // Set SID - if (language == KOR_ID) - { - - gen_3_pkmn[18] = JPN_ID; // Set to JPN - byte new_nickname[10]; - byte new_ot[7]; - for (int i = 0; i < 6; i++) - { // Read the JPN name and convert it - new_nickname[i] = get_gen_3_char(JPN_NAMES[species_index_struct][i], true); - } - - if (gen == 1) - { - // レッド (Red) - new_ot[0] = 0x7A; // レ - new_ot[1] = 0xA0; // ッ - new_ot[2] = 0x95; // ド - new_ot[3] = 0xFF; - } - else - { - if (((caught_data[1] & 0b10000000) >> 7) == 1) // Checks if the Gen 2 player is male or female - { - // クリス (Kurisu) - new_ot[0] = 0x58; // ク - new_ot[1] = 0x78; // リ - new_ot[2] = 0x5D; // ス - new_ot[3] = 0xFF; - } - else - { - // ヒビキ (Hibiki) - new_ot[0] = 0x6B; // ヒ - new_ot[1] = 0x97; // ビ - new_ot[2] = 0x57; // キ - new_ot[3] = 0xFF; - } - } - copy_from_to(&new_nickname[0], &gen_3_pkmn[8], 10, false); // Nickname - copy_from_to(&new_ot[0], &gen_3_pkmn[20], 7, false); // OT Name - } - else - { - gen_3_pkmn[18] = language; // Language - copy_from_to(convert_text(&nickname[0], 10, gen, language), &gen_3_pkmn[8], 10, false); // Nickname - copy_from_to(convert_text(&trainer_name[0], 7, gen, language), &gen_3_pkmn[20], 7, false); // OT Name - } gen_3_pkmn[19] = 0b00000010; // Egg Name (has species sanity flag) gen_3_pkmn[27] = 0b00000000; // Markings @@ -324,16 +374,7 @@ void Pokemon::convert_to_gen_three() data_section_G[0] = species_index_struct; data_section_G[1] = 0x00; // Species Index, check for glitch Pokemon - if (!is_caught(species_index_struct)) - { - data_section_G[2] = 0x44; // Rare Candy - is_new = true; - set_caught(species_index_struct); - } - else - { - data_section_G[2] = 0x00; // No item - } + data_section_G[2] = (is_new ? 0x44 : 0x00); // Rare Candy if new data_section_G[3] = 0x00; copy_from_to(&exp[0], &data_section_G[4], 3, false); data_section_G[8] = (pp_bonus[0] << 0 | pp_bonus[1] << 2 | pp_bonus[2] << 4 | pp_bonus[3] << 6); @@ -347,7 +388,7 @@ void Pokemon::convert_to_gen_three() // Data section E is all zero (EVs and Contest Stats) data_section_M[0] = pokerus; - data_section_M[1] = 0xFF; // Met location - set to Fateful Encounter (separate from flag), cannot be seen by player and is replaced by Pal Park in gen 4 + data_section_M[1] = 0xFF; // Met location - set to Fateful Encounter (separate from flag), is replaced by Pal Park in gen 4 data_section_M[2] = origin_info & 0x00FF; // Lower origins info data_section_M[3] = (origin_info >> 8) & 0xFF; // Upper origins info for (int i = 0; i < 4; i++) @@ -567,7 +608,53 @@ byte *Pokemon::convert_text(byte *text_array, int size, int gen, int lang) return text_array; } -u32 Pokemon::generate_pid(byte pid_species_index, byte nature, byte *pid_dvs) +u32 Pokemon::generate_pid_iv_match(byte pid_species_index, byte nature, byte *pid_dvs) +{ + u32 new_pid = 0; + int letter = -1; + int gen2_gender_threshold = get_gender_threshold(pid_species_index, false); + int gen3_gender_threshold = get_gender_threshold(pid_species_index, true); + bool gender = (((pid_dvs[0] >> 4) & 0b1111) < gen2_gender_threshold); + if (pid_species_index == 0xC9) // Checks if the Pokemon is Unown + { + letter |= ((pid_dvs[0] >> 5) & 0b11) << 6; + letter |= ((pid_dvs[0] >> 1) & 0b11) << 4; + letter |= ((pid_dvs[1] >> 5) & 0b11) << 2; + letter |= ((pid_dvs[1] >> 1) & 0b11); + letter = letter / 10; + } + + do + { + new_pid = get_rand_u16() | (get_rand_u16() << 16); + } while (!( + (letter != -1 ? get_letter_from_pid(new_pid) == letter : true) && + get_nature_from_pid(new_pid) == nature && + (gen2_gender_threshold != -1 + ? ((get_gender_from_pid(new_pid) < gen3_gender_threshold) == gender) + : true))); + + return new_pid; +} + +u8 Pokemon::get_letter_from_pid(u32 pid) +{ + return (((pid & 0x3000) >> 18) | + ((pid & 0x0300) >> 12) | + ((pid & 0x0030) >> 6) | + ((pid & 0x0003) >> 0)) % + 28; +}; +u8 Pokemon::get_nature_from_pid(u32 pid) +{ + return (pid % 25); +}; +u8 Pokemon::get_gender_from_pid(u32 pid) +{ + return (pid & 0xFF); +}; + +u32 Pokemon::generate_pid_save_iv(byte pid_species_index, byte nature, byte *pid_dvs) { // Set Unown Letter u32 new_pid = 0; @@ -665,4 +752,150 @@ Simplified_Pokemon Pokemon::get_simple_pkmn() curr_pkmn.is_valid = get_validity(); curr_pkmn.is_transferred = false; return curr_pkmn; +} + +void Pokemon::set_to_event() +{ + // Things that need to be modified: PID, IV_egg_ability, checksum, OT gender, and the encryption + + int event_id = 0; + if (species_index_struct == 151) + { + switch (language) + { + case JPN_ID: + case KOR_ID: + event_id = 0; + break; + case ENG_ID: + event_id = 1; + break; + case FRE_ID: + event_id = 2; + break; + case ITA_ID: + event_id = 3; + break; + case GER_ID: + event_id = 4; + break; + case SPA_ID: + event_id = 5; + break; + } + } + else + { + switch (language) + { + case JPN_ID: + case KOR_ID: + event_id = 6; + break; + case ENG_ID: + case FRE_ID: + case ITA_ID: + case GER_ID: + case SPA_ID: + event_id = 7; + break; + } + } + + // Load the event into the Pokemon array and unencrypted data array + for (int i = 0; i < 0x20; i++) + { + gen_3_pkmn[i] = EVENT_PKMN[event_id][i]; + } + + for (int i = 0; i < 12; i++) + { + data_section_G[i] = EVENT_PKMN[event_id][i + 0x20 + 0]; + data_section_A[i] = EVENT_PKMN[event_id][i + 0x20 + 12]; + data_section_E[i] = EVENT_PKMN[event_id][i + 0x20 + 24]; + data_section_M[i] = EVENT_PKMN[event_id][i + 0x20 + 36]; + } + + // Set garbage data at end of nickname to PTGB for true event preservation efforts + gen_3_pkmn[0x10] = 0xCA; + gen_3_pkmn[0x11] = 0xCE; + + // get a new PID in the BACD_R format, and make sure it isn't shiny + u32 n_pid; + do + { + // Make the seed 16 bits long, per the BACD_R format + rand_set_seed(rand_get_seed() & 0xFFFF); + n_pid = (get_rand_u16() << 16) | get_rand_u16(); + for (int i = 0; i < 4; i++) + { + gen_3_pkmn[i] = (n_pid >> (i * 8)) & 0xFF; + pid[i] = (n_pid >> (i * 8)) & 0xFF; + }; + } while (((pid[0] ^ pid[2] ^ gen_3_pkmn[4] ^ gen_3_pkmn[6]) < 8) && + ((pid[1] ^ pid[3] ^ gen_3_pkmn[5] ^ gen_3_pkmn[7]) == 0)); + + // Set and fill the IVs + u16 curr_rand = get_rand_u16(); + ivs[0] = (curr_rand >> 0) & 0b11111; + ivs[1] = (curr_rand >> 5) & 0b11111; + ivs[2] = (curr_rand >> 10) & 0b11111; + curr_rand = get_rand_u16(); + ivs[3] = (curr_rand >> 0) & 0b11111; + ivs[4] = (curr_rand >> 5) & 0b11111; + ivs[5] = (curr_rand >> 10) & 0b11111; + + iv_egg_ability = 0; + for (int i = 0; i < 6; i++) + { + iv_egg_ability |= ((ivs[i] & 0b11111) << (i * 5)); + } + + // Determine and set Ability + iv_egg_ability |= ((pid[0] & 0x1) ? get_num_abilities(species_index_struct) : 0) << 31; + + // Set IVs, Egg, and Ability + for (int i = 0; i < 4; i++) + { + data_section_M[i + 4] = (iv_egg_ability >> (i * 8) & 0xFF); + } + + // Determine and set OT gender + data_section_M[3] |= (caught_data[1] & 0b10000000); + + // Update and set the checksum + checksum = 0x0000; + for (int i = 0; i < 12; i = i + 2) + { + checksum = checksum + ((data_section_G[i + 1] << 8) | data_section_G[i]); + checksum = checksum + ((data_section_A[i + 1] << 8) | data_section_A[i]); + checksum = checksum + ((data_section_E[i + 1] << 8) | data_section_E[i]); + checksum = checksum + ((data_section_M[i + 1] << 8) | data_section_M[i]); + } + + gen_3_pkmn[28] = checksum & 0xFF; + gen_3_pkmn[29] = (checksum & 0xFF00) >> 8; + + // Determine the encryption key + for (int i = 0; i < 4; i++) + { + encryption_key[i] = gen_3_pkmn[4 + i] ^ pid[i]; // XOR SID and TID with PID + } + + // Encrypt the data + for (int i = 0; i < 12; i++) + { + unencrypted_data[i] = data_section_G[i]; + data_section_G[i] ^= encryption_key[i % 4]; + unencrypted_data[12 + i] = data_section_A[i]; + data_section_A[i] ^= encryption_key[i % 4]; + unencrypted_data[24 + i] = data_section_E[i]; + data_section_E[i] ^= encryption_key[i % 4]; + unencrypted_data[36 + i] = data_section_M[i]; + data_section_M[i] ^= encryption_key[i % 4]; + } + + // Puts the four data chunks into their correct locations based on the PID + alocate_data_chunks(data_section_G, data_section_A, data_section_E, data_section_M); + return; } \ No newline at end of file diff --git a/source/pokemon_data.cpp b/source/pokemon_data.cpp index b16c3bd..633d10f 100644 --- a/source/pokemon_data.cpp +++ b/source/pokemon_data.cpp @@ -4368,7 +4368,7 @@ const std::string_view NAMES[252]{ "Celebi", }; const u16 JPN_NAMES[252][6]{ - {}, // Offset the list to remove "off by one" errors + {}, // Offset the list to remove "off by one" errors {0x30D5, 0x30B7, 0x30AE, 0x30C0, 0x30CD, 0x19E}, // Bulbasaur {0x30D5, 0x30B7, 0x30AE, 0x30BD, 0x30A6, 0x19E}, // Ivysaur {0x30D5, 0x30B7, 0x30AE, 0x30D0, 0x30CA, 0x19E}, // Venusaur @@ -5131,7 +5131,7 @@ const u8 POWER_POINTS[252]{ }; const u8 MENU_SPRITES[252] = { - 0, // Offset the list to remove "off by one" errors + 0, // Offset the list to remove "off by one" errors 22, // Bulbasaur 22, // Ivysaur 22, // Venusaur @@ -5147,31 +5147,31 @@ const u8 MENU_SPRITES[252] = { 24, // Weedle 24, // Kakuna 11, // Beedrill - 7, // Pidgey - 7, // Pidgeotto - 7, // Pidgeot + 7, // Pidgey + 7, // Pidgeotto + 7, // Pidgeot 15, // Rattata 15, // Raticate - 7, // Spearow - 7, // Fearow + 7, // Spearow + 7, // Fearow 19, // Ekans 19, // Arbok - 4, // Pikachu - 4, // Raichu - 8, // Sandshrew - 8, // Sandslash + 4, // Pikachu + 4, // Raichu + 8, // Sandshrew + 8, // Sandslash 15, // Nidoran♀ 15, // Nidorina - 8, // Nidoqueen + 8, // Nidoqueen 15, // Nidoran♂ 15, // Nidorino - 8, // Nidoking - 9, // Clefairy - 9, // Clefable + 8, // Nidoking + 9, // Clefairy + 9, // Clefable 15, // Vulpix 15, // Ninetales - 2, // Jigglypuff - 2, // Wigglytuff + 2, // Jigglypuff + 2, // Wigglytuff 31, // Zubat 31, // Golbat 10, // Oddish @@ -5181,19 +5181,19 @@ const u8 MENU_SPRITES[252] = { 11, // Parasect 24, // Venonat 30, // Venomoth - 3, // Diglett - 3, // Dugtrio + 3, // Diglett + 3, // Dugtrio 15, // Meowth 15, // Persian - 8, // Psyduck - 8, // Golduck + 8, // Psyduck + 8, // Golduck 27, // Mankey 27, // Primeape 15, // Growlithe 15, // Arcanine - 1, // Poliwag - 1, // Poliwhirl - 1, // Poliwrath + 1, // Poliwag + 1, // Poliwhirl + 1, // Poliwrath 14, // Abra 14, // Kadabra 14, // Alakazam @@ -5214,9 +5214,9 @@ const u8 MENU_SPRITES[252] = { 36, // Slowbro 20, // Magnemite 20, // Magneton - 7, // Farfetch'd - 7, // Doduo - 7, // Dodrio + 7, // Farfetch'd + 7, // Doduo + 7, // Dodrio 13, // Seel 13, // Dewgong 18, // Grimer @@ -5235,24 +5235,24 @@ const u8 MENU_SPRITES[252] = { 20, // Electrode 10, // Exeggcute 10, // Exeggutor - 8, // Cubone - 8, // Marowak + 8, // Cubone + 8, // Marowak 27, // Hitmonlee 27, // Hitmonchan - 8, // Lickitung + 8, // Lickitung 18, // Koffing 18, // Weezing 16, // Rhyhorn - 8, // Rhydon - 9, // Chansey + 8, // Rhydon + 9, // Chansey 10, // Tangela - 8, // Kangaskhan - 6, // Horsea - 6, // Seadra - 6, // Goldeen - 6, // Seaking - 5, // Staryu - 5, // Starmie + 8, // Kangaskhan + 6, // Horsea + 6, // Seadra + 6, // Goldeen + 6, // Seaking + 5, // Staryu + 5, // Starmie 14, // Mr. Mime 11, // Scyther 14, // Jynx @@ -5260,7 +5260,7 @@ const u8 MENU_SPRITES[252] = { 14, // Magmar 11, // Pinsir 16, // Tauros - 6, // Magikarp + 6, // Magikarp 35, // Gyarados 13, // Lapras 18, // Ditto @@ -5273,11 +5273,11 @@ const u8 MENU_SPRITES[252] = { 17, // Omastar 17, // Kabuto 17, // Kabutops - 7, // Aerodactyl + 7, // Aerodactyl 32, // Snorlax - 7, // Articuno - 7, // Zapdos - 7, // Moltres + 7, // Articuno + 7, // Zapdos + 7, // Moltres 19, // Dratini 19, // Dragonair 38, // Dragonite @@ -5289,47 +5289,47 @@ const u8 MENU_SPRITES[252] = { 15, // Cyndaquil 15, // Quilava 15, // Typhlosion - 8, // Totodile - 8, // Croconaw - 8, // Feraligatr + 8, // Totodile + 8, // Croconaw + 8, // Feraligatr 15, // Sentret 15, // Furret - 7, // Hoothoot - 7, // Noctowl + 7, // Hoothoot + 7, // Noctowl 11, // Ledyba 11, // Ledian 11, // Spinarak 11, // Ariados 31, // Crobat - 6, // Chinchou - 6, // Lanturn - 4, // Pichu - 9, // Cleffa - 2, // Igglybuff - 9, // Togepi - 7, // Togetic - 7, // Natu - 7, // Xatu + 6, // Chinchou + 6, // Lanturn + 4, // Pichu + 9, // Cleffa + 2, // Igglybuff + 9, // Togepi + 7, // Togetic + 7, // Natu + 7, // Xatu 15, // Mareep - 8, // Flaaffy - 8, // Ampharos + 8, // Flaaffy + 8, // Ampharos 10, // Bellossom - 2, // Marill - 2, // Azumarill + 2, // Marill + 2, // Azumarill 27, // Sudowoodo - 1, // Politoed + 1, // Politoed 10, // Hoppip 10, // Skiploom 10, // Jumpluff - 8, // Aipom + 8, // Aipom 10, // Sunkern 10, // Sunflora 11, // Yanma - 8, // Wooper - 8, // Quagsire + 8, // Wooper + 8, // Quagsire 15, // Espeon 15, // Umbreon - 7, // Murkrow + 7, // Murkrow 36, // Slowking 12, // Misdreavus 25, // Unown @@ -5340,25 +5340,25 @@ const u8 MENU_SPRITES[252] = { 19, // Dunsparce 11, // Gligar 19, // Steelix - 8, // Snubbull - 8, // Granbull - 6, // Qwilfish + 8, // Snubbull + 8, // Granbull + 6, // Qwilfish 11, // Scizor 11, // Shuckle 11, // Heracross 15, // Sneasel - 8, // Teddiursa - 8, // Ursaring + 8, // Teddiursa + 8, // Ursaring 18, // Slugma 18, // Magcargo 16, // Swinub 16, // Piloswine 17, // Corsola - 6, // Remoraid - 6, // Octillery - 8, // Delibird - 6, // Mantine - 7, // Skarmory + 6, // Remoraid + 6, // Octillery + 8, // Delibird + 6, // Mantine + 7, // Skarmory 15, // Houndour 15, // Houndoom 38, // Kingdra @@ -5366,21 +5366,42 @@ const u8 MENU_SPRITES[252] = { 16, // Donphan 20, // Porygon2 16, // Stantler - 8, // Smeargle + 8, // Smeargle 27, // Tyrogue 27, // Hitmontop 14, // Smoochum 14, // Elekid 14, // Magby 16, // Miltank - 9, // Blissey + 9, // Blissey 15, // Raikou 15, // Entei 15, // Suicune - 8, // Larvitar - 8, // Pupitar - 8, // Tyranitar + 8, // Larvitar + 8, // Pupitar + 8, // Tyranitar 34, // Lugia 33, // Ho-Oh 14, // Celebi -}; \ No newline at end of file +}; + +extern const byte EVENT_PKMN[8][80]{ // Events taken from the PKHeX Event Database. + // Sanitize 4 bytes at 0x00, 2 bytes at 0x1C, the highest bit at 0x46 and 4 bytes at 0x48 + + // Japanese Hadō (Aura) Mew + {0x00, 0x00, 0x00, 0x00, 0x1C, 0xC6, 0x00, 0x00, 0x70, 0x85, 0x53, 0xFF, 0x08, 0x70, 0x01, 0x34, 0x01, 0x31, 0x01, 0x02, 0x6A, 0x95, 0x53, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x01, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0A, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80}, + // English Aura Mew + {0x00, 0x00, 0x00, 0x00, 0x6E, 0x4E, 0x00, 0x00, 0xC7, 0xBF, 0xD1, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0xBB, 0xE9, 0xE6, 0xD5, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x01, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0A, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80}, + // French Aura Mew + {0x00, 0x00, 0x00, 0x00, 0x6E, 0x4E, 0x00, 0x00, 0xC7, 0xBF, 0xD1, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0xBB, 0xE9, 0xE6, 0xD5, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x01, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0A, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80}, + // Italian Aura Mew + {0x00, 0x00, 0x00, 0x00, 0x6E, 0x4E, 0x00, 0x00, 0xC7, 0xBF, 0xD1, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0xBB, 0xE9, 0xE6, 0xD5, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x01, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0A, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80}, + // German Aura Mew + {0x00, 0x00, 0x00, 0x00, 0x6E, 0x4E, 0x00, 0x00, 0xC7, 0xBF, 0xD1, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x02, 0xBB, 0xE9, 0xE6, 0xD5, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x01, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0A, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80}, + // Spanish Aura Mew + {0x00, 0x00, 0x00, 0x00, 0x6E, 0x4E, 0x00, 0x00, 0xC7, 0xBF, 0xD1, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x02, 0xBB, 0xE9, 0xE6, 0xD5, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x01, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0A, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80}, + // Mitsurin Celebi + {0x00, 0x00, 0x00, 0x00, 0x30, 0xED, 0x00, 0x00, 0x5E, 0x7A, 0x97, 0x80, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x70, 0x62, 0x78, 0x7E, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFB, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x49, 0x00, 0x69, 0x00, 0xD7, 0x00, 0xDB, 0x00, 0x0A, 0x14, 0x05, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0A, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + // 10th Anniversary Celebi + {0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xBD, 0xBF, 0xC6, 0xBF, 0xBC, 0xC3, 0xFF, 0x34, 0x01, 0x31, 0x02, 0x02, 0xA2, 0xA1, 0x00, 0xBB, 0xC8, 0xC3, 0xD0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFB, 0x00, 0x00, 0x00, 0x80, 0x43, 0x05, 0x00, 0x00, 0x64, 0x00, 0x00, 0xF6, 0x00, 0xF8, 0x00, 0xE2, 0x00, 0xC3, 0x00, 0x05, 0x0F, 0x28, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x46, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + }; diff --git a/source/pokemon_party.cpp b/source/pokemon_party.cpp index 05c55c3..f2aa5f1 100644 --- a/source/pokemon_party.cpp +++ b/source/pokemon_party.cpp @@ -18,7 +18,8 @@ byte debug_box_data[0x462] = { // num of Pokemon 0x14, // Pokemon 1-20 - 0x02, 0x70, 0x70, 0x70, 0x71, 0x71, 0x70, 0x71, 0x7B, 0x71, 0x71, 0x7C, 0x71, 0x71, 0x71, 0x71, 0x24, 0x24, 0xA5, 0x24, 0xFF, + //0x02, 0x70, 0x70, 0x70, 0x71, 0x71, 0x70, 0x71, 0x7B, 0x71, 0x71, 0x7C, 0x71, 0x71, 0x71, 0x71, 0x24, 0x24, 0xA5, 0x15, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xFF, // Pokemon list 0x02, 0x00, 0x11, 100, 0x00, 0x07, 0x03, 0xFF, 0x28, 0x51, 0x00, 0x00, 0x6F, 0xC6, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xDE, 0x23, 0x28, 0x00, 0x00, 0x70, 0x00, 0x12, 0x04, 0x00, 0x07, 0x03, 0xFF, 0x28, 0x51, 0x00, 0x00, 0x6F, 0xC6, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5D, 0xD8, 0x23, 0x28, 0x00, 0x00, @@ -39,7 +40,7 @@ byte debug_box_data[0x462] = { 0x24, 0x00, 0x12, 0x04, 0x00, 0x00, 0x02, 0xFF, 0x10, 0x00, 0x00, 0x00, 0x6F, 0xC6, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0xC2, 0x23, 0x00, 0x00, 0x00, 0x24, 0x00, 0x11, 0x04, 0x00, 0x00, 0x02, 0xFF, 0x10, 0x00, 0x00, 0x00, 0x6F, 0xC6, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x2A, 0x23, 0x00, 0x00, 0x00, 0xA5, 0x00, 0x0E, 0x03, 0x00, 0x00, 0x00, 0xFF, 0x21, 0x27, 0x00, 0x00, 0x6F, 0xC6, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0xBE, 0x23, 0x1E, 0x00, 0x00, - 0x24, 0x00, 0x0F, 0x03, 0x00, 0x00, 0x02, 0xFF, 0x10, 0x00, 0x00, 0x00, 0x6F, 0xC6, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0xE6, 0x23, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x0F, 0x03, 0x00, 0x00, 0x02, 0xFF, 0x10, 0x00, 0x00, 0x00, 0x6F, 0xC6, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0xE6, 0x23, 0x00, 0x00, 0x00, // Trainer names 0x80, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -102,7 +103,9 @@ void Pokemon_Party::start_link() } void Pokemon_Party::continue_link(){ - last_error = loop(&box_data_array[0], &curr_payload, simple_pkmn_array); + if (!IGNORE_LINK_CABLE){ + last_error = loop(&box_data_array[0], &curr_payload, simple_pkmn_array); + } } int Pokemon_Party::get_last_error() @@ -114,7 +117,7 @@ Pokemon Pokemon_Party::get_converted_pkmn(int index) { Pokemon converted_mon; converted_mon.load_data(index, box_data_array, game, lang); - converted_mon.convert_to_gen_three(); + converted_mon.convert_to_gen_three(false, stabilize_mythic); has_new_pkmn = has_new_pkmn || converted_mon.get_is_new(); simple_pkmn_array[index] = converted_mon.get_simple_pkmn(); return converted_mon; @@ -125,6 +128,15 @@ bool Pokemon_Party::get_has_new_pkmn() // If Pokemon is not in the dex return has_new_pkmn; } +bool Pokemon_Party::get_contains_mythical(){ + return contains_mythical; +} + +void Pokemon_Party::set_mythic_stabilization(bool stabilize){ + stabilize_mythic = stabilize; +} + + void Pokemon_Party::set_game(int nGame) { game = nGame; @@ -160,8 +172,10 @@ void Pokemon_Party::fill_simple_pkmn_array(){ for (int index = 0; index < 30; index++){ Pokemon converted_mon; converted_mon.load_data(index, box_data_array, game, lang); - converted_mon.convert_to_gen_three(); + converted_mon.convert_to_gen_three(true, stabilize_mythic); has_new_pkmn = has_new_pkmn || converted_mon.get_is_new(); + contains_mythical = contains_mythical || + converted_mon.get_dex_number() == 151 || converted_mon.get_dex_number() == 251; simple_pkmn_array[index] = converted_mon.get_simple_pkmn(); } } \ No newline at end of file diff --git a/source/random.cpp b/source/random.cpp index 44d83c1..9fcd079 100644 --- a/source/random.cpp +++ b/source/random.cpp @@ -1,4 +1,5 @@ #include "random.h" +#include unsigned int u32_rand; @@ -6,15 +7,25 @@ void rand_set_seed(unsigned int init_seed){ u32_rand = init_seed; } -void rand_next_frame(){ - u32_rand = 0x41C64E6D * u32_rand + 0x00006073; // This is the randomization method used in Gen 3 +unsigned int rand_get_seed(){ + return u32_rand; } -unsigned int get_rand_u32(){ + +void rand_next_frame(){ + u32_rand = (0x41C64E6D * u32_rand) + 0x6073; // This is the randomization method used in Gen 3 +} + +u32 get_rand_u32(){ rand_next_frame(); return u32_rand; } +u16 get_rand_u16(){ + rand_next_frame(); + return (u32_rand >> 16); +} + unsigned int get_rand_range(unsigned int inc_min, unsigned int exc_max){ return ((double)((get_rand_u32() / (double)0x100000000) * (exc_max - inc_min)) + inc_min); } \ No newline at end of file diff --git a/source/script_array.cpp b/source/script_array.cpp index e8ba486..57136df 100644 --- a/source/script_array.cpp +++ b/source/script_array.cpp @@ -45,6 +45,7 @@ void populate_dialogue() dialogue[DIA_WHAT_LANG] = "What language is the Game\nBoy Pok@mon game that you're\ntransferring from?"; dialogue[DIA_NO_PAYLOAD] = "I'm sorry, but that version\nin that language is not\ncurrently supported."; dialogue[DIA_IN_BOX] = "Great! Let's take a look at\nthe Pok@mon that will be\ntransfered.|Please remember, once a\nPok@mon is transfered, it\nCANNOT be returned to the\nGame Boy Game Pak.|Select confirm once you're\nready, or select cancel if\nyou want to keep the Pok@mon\non your Game Boy Game Pak."; + dialogue[DIA_MYTHIC_CONVERT] = "It looks like you have a really rare Mythical Pok@mon!|Due to their strength, it seems they've corrupted the machine.|I can stablize them if you'd like, but it'll modify some things like nickname, Original Trainer, and Shininess.|Otherwise I can leave them as is, but there's no guarentee that they'll be transferrable in the future.|Do you want me to stablize them?"; dialogue[DIA_ERROR_COLOSSEUM] = "It looks like you went to\nthe colosseum instead of the\ntrading room!|Let's try that again!"; dialogue[DIA_ERROR_COM_ENDED] = "Communication with the other\ndevice was terminated.|Let's try that again!"; @@ -94,10 +95,13 @@ void populate_script() script[DIA_ERROR_COM_ENDED] = script_obj(dialogue[DIA_ERROR_COM_ENDED], DIA_START); script[COND_ERROR_COLOSSEUM] = script_obj(COND_ERROR_COLOSSEUM, COND_ERROR_DISCONNECT, DIA_ERROR_COLOSSEUM); script[DIA_ERROR_COLOSSEUM] = script_obj(dialogue[DIA_ERROR_COLOSSEUM], DIA_START); - script[COND_ERROR_DISCONNECT] = script_obj(COND_ERROR_DISCONNECT, DIA_IN_BOX, DIA_ERROR_DISCONNECT); + script[COND_ERROR_DISCONNECT] = script_obj(COND_ERROR_DISCONNECT, COND_CHECK_MYTHIC, DIA_ERROR_DISCONNECT); script[DIA_ERROR_DISCONNECT] = script_obj(dialogue[DIA_ERROR_DISCONNECT], DIA_START); // Pause the transfer and show the user their box data + script[COND_CHECK_MYTHIC] = script_obj(COND_CHECK_MYTHIC, DIA_MYTHIC_CONVERT, DIA_IN_BOX); + script[DIA_MYTHIC_CONVERT] = script_obj(dialogue[DIA_MYTHIC_CONVERT], CMD_MYTHIC_MENU); + script[CMD_MYTHIC_MENU] = script_obj(CMD_MYTHIC_MENU, DIA_IN_BOX); script[DIA_IN_BOX] = script_obj(dialogue[DIA_IN_BOX], CMD_BOX_MENU); script[CMD_BOX_MENU] = script_obj(CMD_BOX_MENU, CMD_CONTINUE_LINK); script[CMD_CONTINUE_LINK] = script_obj(CMD_CONTINUE_LINK, CMD_IMPORT_POKEMON); @@ -204,6 +208,9 @@ bool run_conditional(int index) case COND_PAYLOAD_EXISTS: return party_data.load_payload(); + case COND_CHECK_MYTHIC: + return party_data.get_contains_mythical(); + case CMD_START_LINK: party_data.start_link(); return true; @@ -291,6 +298,10 @@ bool run_conditional(int index) box_viewer.box_main(party_data); return true; + case CMD_MYTHIC_MENU: + party_data.set_mythic_stabilization(yes_no_menu.button_main()); + return true; + default: tte_set_pos(0, 0); tte_write("ERROR! No conditional found."); diff --git a/source/sprite_data.cpp b/source/sprite_data.cpp index 3ed2e70..9011494 100644 --- a/source/sprite_data.cpp +++ b/source/sprite_data.cpp @@ -7,28 +7,37 @@ OBJ_ATTR obj_buffer[128]; OBJ_AFFINE *obj_aff_buffer = (OBJ_AFFINE *)obj_buffer; - -// These are the two pallets used by the menu sprites, +// These are the two pallets used by the menu sprites, // it's easier to set them up this way instead of through grit // (R + G*32 + B*1024) -#define WHITE (31 + 31*32 + 31*1024) -#define YELLOW (31 + 19*32 + 10*1024) -#define RED (31 + 07*32 + 04*1024) -#define BLACK (00 + 00*32 + 00*1024) +#define WHITE (31 + 31 * 32 + 31 * 1024) +#define YELLOW (31 + 19 * 32 + 10 * 1024) +#define RED (31 + 07 * 32 + 04 * 1024) +#define BLACK (00 + 00 * 32 + 00 * 1024) const unsigned short frame_one_pal[16] = { - WHITE, WHITE, WHITE, WHITE, + WHITE, WHITE, WHITE, WHITE, YELLOW, YELLOW, YELLOW, YELLOW, - RED, RED, RED, RED, - BLACK, BLACK, BLACK, BLACK -}; + RED, RED, RED, RED, + BLACK, BLACK, BLACK, BLACK}; const unsigned short frame_two_pal[16] = { - WHITE, YELLOW, RED, BLACK, - WHITE, YELLOW, RED, BLACK, - WHITE, YELLOW, RED, BLACK, - WHITE, YELLOW, RED, BLACK, + WHITE, + YELLOW, + RED, + BLACK, + WHITE, + YELLOW, + RED, + BLACK, + WHITE, + YELLOW, + RED, + BLACK, + WHITE, + YELLOW, + RED, + BLACK, }; - // BACKGROUNDS #include "background.h" @@ -91,6 +100,8 @@ OBJ_ATTR *btn_c_l = &obj_buffer[num_sprites++]; OBJ_ATTR *btn_c_r = &obj_buffer[num_sprites++]; OBJ_ATTR *btn_d_l = &obj_buffer[num_sprites++]; OBJ_ATTR *btn_d_r = &obj_buffer[num_sprites++]; +OBJ_ATTR *button_yes = &obj_buffer[num_sprites++]; +OBJ_ATTR *button_no = &obj_buffer[num_sprites++]; OBJ_ATTR *dex_sprites[3][6] = { // Fills the dex sprites top to bottom, left to right {&obj_buffer[num_sprites++], &obj_buffer[num_sprites++], &obj_buffer[num_sprites++], @@ -124,13 +135,37 @@ OBJ_ATTR *button_crystal_right = &obj_buffer[num_sprites++]; OBJ_ATTR *box_select = &obj_buffer[num_sprites++]; OBJ_ATTR *party_sprites[30] = { - &obj_buffer[num_sprites++], &obj_buffer[num_sprites++], &obj_buffer[num_sprites++], &obj_buffer[num_sprites++], &obj_buffer[num_sprites++], - &obj_buffer[num_sprites++], &obj_buffer[num_sprites++], &obj_buffer[num_sprites++], &obj_buffer[num_sprites++], &obj_buffer[num_sprites++], - &obj_buffer[num_sprites++], &obj_buffer[num_sprites++], &obj_buffer[num_sprites++], &obj_buffer[num_sprites++], &obj_buffer[num_sprites++], - &obj_buffer[num_sprites++], &obj_buffer[num_sprites++], &obj_buffer[num_sprites++], &obj_buffer[num_sprites++], &obj_buffer[num_sprites++], - &obj_buffer[num_sprites++], &obj_buffer[num_sprites++], &obj_buffer[num_sprites++], &obj_buffer[num_sprites++], &obj_buffer[num_sprites++], - &obj_buffer[num_sprites++], &obj_buffer[num_sprites++], &obj_buffer[num_sprites++], &obj_buffer[num_sprites++], &obj_buffer[num_sprites++], - }; + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], + &obj_buffer[num_sprites++], +}; OBJ_ATTR *button_cancel_left = &obj_buffer[num_sprites++]; OBJ_ATTR *button_cancel_right = &obj_buffer[num_sprites++]; @@ -157,6 +192,8 @@ void load_eternal_sprites() load_sprite(btn_c_r, btn_c_rTiles, btn_c_rTilesLen, curr_tile_id, BTN_PAL, ATTR0_WIDE, ATTR1_SIZE_64x32, 1); load_sprite(btn_d_l, btn_d_lTiles, btn_d_lTilesLen, curr_tile_id, BTN_PAL, ATTR0_WIDE, ATTR1_SIZE_64x32, 1); load_sprite(btn_d_r, btn_d_rTiles, btn_d_rTilesLen, curr_tile_id, BTN_PAL, ATTR0_WIDE, ATTR1_SIZE_64x32, 1); + load_sprite(button_yes, button_yesTiles, button_yesTilesLen, curr_tile_id, BTN_PAL, ATTR0_WIDE, ATTR1_SIZE_64x32, 1); + load_sprite(button_no, button_noTiles, button_noTilesLen, curr_tile_id, BTN_PAL, ATTR0_WIDE, ATTR1_SIZE_64x32, 1); global_tile_id_end = curr_tile_id; } @@ -200,10 +237,13 @@ void load_temp_sprites(int sprite_batch_id) } } -void load_temp_box_sprites(Pokemon_Party party_data){ +void load_temp_box_sprites(Pokemon_Party party_data) +{ u32 curr_tile_id = global_tile_id_end; - for (int i = 0; i < 30; i++){ - if (party_data.get_simple_pkmn(i).is_valid){ + for (int i = 0; i < 30; i++) + { + if (party_data.get_simple_pkmn(i).is_valid) + { load_sprite(party_sprites[i], &duel_frame_menu_spritesTiles[(MENU_SPRITES[party_data.get_simple_pkmn(i).dex_number] - 1) * 32], 256, curr_tile_id, MENU_SPRITE_PAL, ATTR0_SQUARE, ATTR1_SIZE_16x16, 1); obj_set_pos(party_sprites[i], (16 * (i % 10)) + 40, (16 * (i / 10)) + 24); }