diff --git a/.gitignore b/.gitignore index 026531c..b10f8a7 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ build/ *.zip .vscode/ source/payload_builder.exe -source/test_payload.txt \ No newline at end of file +source/test_payload.txt +loader/data/multiboot_rom.bin diff --git a/include/debug_mode.h b/include/debug_mode.h index e1b47f1..22f1d1e 100644 --- a/include/debug_mode.h +++ b/include/debug_mode.h @@ -9,7 +9,8 @@ #define PRINT_LINK_DATA (false && DEBUG_MODE) // This is currently broken... not sure why #define INSTANT_TEXT_SPEED (false && DEBUG_MODE) #define IGNORE_GAME_PAK (true && DEBUG_MODE) -#define IGNORE_LINK_CABLE (true && DEBUG_MODE) +#define IGNORE_GAME_PAK_SPRITES (true && DEBUG_MODE) +#define IGNORE_LINK_CABLE (false && DEBUG_MODE) #define IGNORE_MG_E4_FLAGS (true && DEBUG_MODE) #define IGNORE_UNRECEIVED_PKMN (true && DEBUG_MODE) #define FORCE_TUTORIAL (false && DEBUG_MODE) diff --git a/include/pokemon.h b/include/pokemon.h index 379ac2a..3fc51d6 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -54,6 +54,7 @@ public: byte *convert_text(byte *text_array, int size, int gen, int lang); 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); + u32 generate_pid_iv_legendary(byte pid_species_index, byte *pid_dvs, byte *out_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(); diff --git a/include/random.h b/include/random.h index a717d62..70e5ecd 100644 --- a/include/random.h +++ b/include/random.h @@ -8,6 +8,8 @@ unsigned int rand_get_seed(); void rand_next_frame(); u32 get_rand_u32(); u16 get_rand_u16(); +u32 get_rev_rand_u32(u32 input); +u16 get_rev_rand_u16(u32 input); void enable_auto_random(); void disable_auto_random(); diff --git a/source/gameboy_colour.cpp b/source/gameboy_colour.cpp index bf66f45..c806624 100644 --- a/source/gameboy_colour.cpp +++ b/source/gameboy_colour.cpp @@ -144,7 +144,7 @@ void setup() end_of_data = false; create_textbox(0, 0, 80, 80, true); - tte_erase_screen(); + //tte_erase_screen(); tte_set_pos(40, 24); ptgb_write("\n\n\n Connecting to\n GameBoy"); } diff --git a/source/gen_converter.cpp b/source/gen_converter.cpp deleted file mode 100644 index 1a3d275..0000000 --- a/source/gen_converter.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* -void set_origin_pid_iv(struct gen3_mon* dst, struct gen3_mon_data_unenc* data_dst, u16 species, u16 wanted_ivs, u8 wanted_nature, u8 ot_gender, u8 is_egg, u8 no_restrictions) { - struct game_data_t* trainer_data = get_own_game_data(); - struct gen3_mon_misc* misc = &data_dst->misc; - u8 trainer_game_version = id_to_version(&trainer_data->game_identifier); - u8 trainer_gender = trainer_data->trainer_gender; - - // Normalize nature - wanted_nature = get_nature(wanted_nature); - - // Handle eggs separately - u32 ot_id = dst->ot_id; - if(is_egg) - ot_id = trainer_data->trainer_id; - - // Prepare the TSV - u16 tsv = (ot_id & 0xFFFF) ^ (ot_id >> 16); - - u8 chosen_version = get_default_conversion_game(); - if(!no_restrictions) { - chosen_version = trainer_game_version; - ot_gender = trainer_gender; - } - - u8 encounter_type = get_encounter_type_gen3(species); - u8 is_shiny = is_shiny_gen2_unfiltered(wanted_ivs); - // To debug shiny Unown stuff more than normally possible - //is_shiny = 1; - u32 ivs = 0; - u8 ability = 0; - u8 is_ability_set = 0; - u32 valid_balls = 0; - const u8* searchable_table = egg_locations_bin; - u8 find_in_table = 0; - - // Get PID and IVs - switch(encounter_type) { - case STATIC_ENCOUNTER: - valid_balls = VALID_POKEBALL_NO_EGG; - if(get_event_info_replacement() && (species == CELEBI_SPECIES)) { - valid_balls = VALID_POKEBALL_CELEBI; - chosen_version = R_VERSION_ID; - generate_generic_genderless_shadow_info_xd(wanted_nature, 0, wanted_ivs, tsv, &dst->pid, &ivs, &ability); - is_ability_set = 1; - ot_gender = 1; - } - else if(!is_shiny) { - // Prefer Colosseum/XD encounter, if possible - if(get_conversion_colo_xd() && is_static_in_xd(species) && are_colo_valid_tid_sid(ot_id & 0xFFFF, ot_id >> 0x10) && ((ot_gender == 0) || (!get_prioritize_ot_gender()))) { - chosen_version = COLOSSEUM_CODE; - generate_generic_genderless_shadow_info_xd(wanted_nature, has_prev_check_tsv_in_xd(species), wanted_ivs, tsv, &dst->pid, &ivs, &ability); - misc->ribbons |= COLO_RIBBON_VALUE; - is_ability_set = 1; - ot_gender = 0; - data_dst->learnable_moves = (const struct learnset_data_mon_moves*)get_learnset_for_species((const u16*)learnset_static_xd_bin, species); - } - else - generate_static_info(wanted_nature, wanted_ivs, tsv, &dst->pid, &ivs); - } - else - generate_static_shiny_info(wanted_nature, tsv, &dst->pid, &ivs); - searchable_table = encounters_static_bin; - find_in_table = 1; - break; - case ROAMER_ENCOUNTER: - valid_balls = VALID_POKEBALL_NO_EGG; - // Prefer Colosseum/XD encounter, if possible - if(get_conversion_colo_xd() && are_colo_valid_tid_sid(ot_id & 0xFFFF, ot_id >> 0x10) && ((ot_gender == 0) || (!get_prioritize_ot_gender()))) { - chosen_version = COLOSSEUM_CODE; - if(!is_shiny) - generate_generic_genderless_shadow_info_colo(wanted_nature, wanted_ivs, tsv, &dst->pid, &ivs, &ability); - else - generate_generic_genderless_shadow_shiny_info_colo(wanted_nature, tsv, &dst->pid, &ivs, &ability); - misc->ribbons |= COLO_RIBBON_VALUE; - is_ability_set = 1; - ot_gender = 0; - } - else { - if(!is_shiny) - generate_static_info(wanted_nature, wanted_ivs, tsv, &dst->pid, &ivs); - else - generate_static_shiny_info(wanted_nature, tsv, &dst->pid, &ivs); - // Roamers only get the first byte of their IVs - ivs &= 0xFF; - } - searchable_table = encounters_roamers_bin; - find_in_table = 1; - break; - case UNOWN_ENCOUNTER: - valid_balls = VALID_POKEBALL_NO_EGG; - if(!is_shiny) - generate_unown_info(wanted_nature, wanted_ivs, tsv, &dst->pid, &ivs); - else - generate_unown_shiny_info(wanted_nature, wanted_ivs, tsv, &dst->pid, &ivs); - searchable_table = encounters_unown_bin; - find_in_table = 1; - break; - default: - valid_balls = VALID_POKEBALL_EGG; - if(!is_shiny) - generate_egg_info(species, wanted_nature, wanted_ivs, tsv, 2, &dst->pid, &ivs); - else - generate_egg_shiny_info(species, wanted_nature, wanted_ivs, tsv, 2, &dst->pid, &ivs); - break; - } - - // Set met location and origins info - u8 met_location = egg_locations_bin[chosen_version]; - if(!is_egg) - met_location = get_egg_met_location(); - u8 met_level = 0; - u8 obedience = 0; - - if(find_in_table) { - u16 mon_index = get_mon_index(species, dst->pid, 0, 0); - const struct mon_general_met_data_gen3* possible_met_data = (const struct mon_general_met_data_gen3*)search_table_for_index(searchable_table, mon_index); - if(possible_met_data != NULL) { - u8 num_elems = possible_met_data->num_entries; - u8 chosen_entry = 0; - for(int i = 0; i < num_elems; i++) - if((possible_met_data->met_data_entries[i].origin_game) == chosen_version) - chosen_entry = i; - chosen_version = possible_met_data->met_data_entries[chosen_entry].origin_game; - obedience = possible_met_data->met_data_entries[chosen_entry].obedience; - met_location = possible_met_data->met_data_entries[chosen_entry].location; - met_level = possible_met_data->met_data_entries[chosen_entry].level; - } - } - -*/ \ No newline at end of file diff --git a/source/main.cpp b/source/main.cpp index 8745d33..da5db0a 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -102,7 +102,8 @@ void load_graphics() tte_erase_rect(0, 0, H_MAX, V_MAX); // Load opening background first so it hides everything else load_flex_background(BG_OPENING, 1); - load_background(); load_textbox_background(); + load_background(); + load_textbox_background(); load_eternal_sprites(); // Set up global yes no button diff --git a/source/pokemon.cpp b/source/pokemon.cpp index aa8a434..cb21023 100644 --- a/source/pokemon.cpp +++ b/source/pokemon.cpp @@ -288,31 +288,14 @@ void Pokemon::convert_to_gen_three(Conversion_Types conv_type, bool simplified, ((dvs[0] & 0xF) == 0b1010) && // Checks if the Defense DVs equal 10 ((dvs[0] & 0b00100000) >> 5)); // Checks if the second bit of the Attack DV is true - byte e_arr[7] = {0xBF, 0xC6, 0xC6, 0xC3, 0xC9, 0xCE, 0xFF}; - byte p_arr[8] = {0xCA, 0xBF, 0xCE, 0xCF, 0xC8, 0xC3, 0xBB, 0xFF}; - byte a_arr[7] = {0xBB, 0xCF, 0xCD, 0xCE, 0xC3, 0xC8, 0xFF}; - - int e = fnv1a_hash(e_arr, 7); - int p = fnv1a_hash(p_arr, 8); - int a = fnv1a_hash(a_arr, 7); - if (species_index_struct == 52 && fnv1a_hash(nickname, 7) == 1515822901 && - (fnv1a_hash(trainer_name, 7) == -1623517410 || fnv1a_hash(trainer_name, 7) == 1342961308)) + (fnv1a_hash(trainer_name, 7) == 2671449886 || fnv1a_hash(trainer_name, 7) == 1342961308)) { is_shiny = true; dvs[0] = 0xFF; dvs[1] = 0xFF; } - int val = e + p + a; - if (val > 10) - { - while (true) - { - val++; - } - } - if (species_index_struct == 201) // Checks if the Pokemon is Unown { unown_letter = 0; @@ -426,15 +409,17 @@ void Pokemon::convert_to_gen_three(Conversion_Types conv_type, bool simplified, if (ENABLE_MATCH_PID) { n_pid = generate_pid_iv_match(species_index_struct, nature_mod, &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; + ///n_pid = generate_pid_iv_legendary(species_index_struct, &dvs[0], &ivs[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++) { @@ -845,6 +830,68 @@ u32 Pokemon::generate_pid_iv_match(byte pid_species_index, byte nature, byte *pi return new_pid; } +u32 Pokemon::generate_pid_iv_legendary(byte pid_species_index, byte *pid_dvs, byte *out_ivs) +{ + // Convert and set IVs + + // This stores the DVs in the IV order + byte ivs[6] = { + (((dvs[0] >> 4) & 0b1) << 3) | + (((dvs[0] >> 0) & 0b1) << 2) | + (((dvs[1] >> 4) & 0b1) << 1) | + (((dvs[1] >> 0) & 0b1) << 0), + + (dvs[0] >> 4) & 0b1111, // Attack + (dvs[0] >> 0) & 0b1111, // Defense + (dvs[1] >> 4) & 0b1111, // Speed + (dvs[1] >> 0) & 0b1111, // Special Attack + (dvs[1] >> 0) & 0b1111, // Special Defense + }; + + u32 iv_low_rng; + u32 iv_high_rng; + u32 pid_high_rng; + u32 pid_low_rng; + u32 pid; + u32 seed; + + u32 comp; + u32 n_val; + u32 n_comp; + + for (int i = 0; i < 65535; i++) + { + // Generate the low IV byte, being the SpD, SpA, Spe + iv_low_rng = (i % 2) << 31 | (ivs[5] << 27) | (ivs[4] << 22) | (ivs[3] << 17) | (i >> 1); + iv_high_rng = get_rev_rand_u32(iv_low_rng); + pid_high_rng = get_rev_rand_u32(iv_high_rng); + pid_low_rng = get_rev_rand_u32(pid_high_rng); + seed = get_rev_rand_u32(pid_low_rng); + pid = ((pid_high_rng & 0xFFFF0000) << 0) | (pid_low_rng & 0xFFFF0000) >> 16; + + // Test it against the high IV byte, being the Def, Atk, HP + comp = (ivs[2] << 11) | (ivs[1] << 6) | (ivs[0] << 1); + n_val = (iv_high_rng >> 16) & 0b0111101111011110; + n_comp = comp & 0b0111101111011110; + + if (n_comp == n_val) + { + if ((pid % 25) % 6 == 0) + { + out_ivs[0] = (iv_low_rng >> 0) & 0b11111; // HP + out_ivs[1] = (iv_low_rng >> 5) & 0b11111; // Atk + out_ivs[2] = (iv_low_rng >> 10) & 0b11111; // Def + out_ivs[3] = (iv_high_rng >> 5) & 0b11111; // SpA + out_ivs[4] = (iv_high_rng >> 10) & 0b11111; // SpD + out_ivs[5] = (iv_high_rng >> 0) & 0b11111; // Spe + + return pid_low_rng | seed; + } + } + } + return 0; +} + u8 Pokemon::get_letter_from_pid(u32 pid) { return ( diff --git a/source/random.cpp b/source/random.cpp index 9fcd079..060d21f 100644 --- a/source/random.cpp +++ b/source/random.cpp @@ -3,29 +3,44 @@ unsigned int u32_rand; -void rand_set_seed(unsigned int init_seed){ +void rand_set_seed(unsigned int init_seed) +{ u32_rand = init_seed; } -unsigned int rand_get_seed(){ +unsigned int rand_get_seed() +{ return u32_rand; } - -void rand_next_frame(){ - u32_rand = (0x41C64E6D * u32_rand) + 0x6073; // This is the randomization method used in Gen 3 +void rand_next_frame() +{ + u32_rand = (0x41C64E6D * u32_rand) + 0x6073; // This is the randomization method used in Gen 3 } -u32 get_rand_u32(){ +u32 get_rand_u32() +{ rand_next_frame(); return u32_rand; } -u16 get_rand_u16(){ +u16 get_rand_u16() +{ rand_next_frame(); return (u32_rand >> 16); } -unsigned int get_rand_range(unsigned int inc_min, unsigned int exc_max){ +u32 get_rev_rand_u32(u32 input) +{ + return (input - 24691) * 4005161829; +} + +u16 get_rev_rand_u16(u32 input) +{ + return (get_rev_rand_u32(input) >> 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/sprite_data.cpp b/source/sprite_data.cpp index 85671d1..1accccb 100644 --- a/source/sprite_data.cpp +++ b/source/sprite_data.cpp @@ -465,7 +465,7 @@ void load_temp_box_sprites(Pokemon_Party *party_data) { u32 curr_tile_id = global_tile_id_end; - if (!IGNORE_GAME_PAK) + if (!(IGNORE_GAME_PAK || IGNORE_GAME_PAK_SPRITES)) { for (int i = 0; i < 30; i++) { @@ -855,7 +855,7 @@ void update_y_offset() void update_front_box_sprite(Simplified_Pokemon *curr_pkmn) { - if (IGNORE_GAME_PAK) + if (IGNORE_GAME_PAK || IGNORE_GAME_PAK_SPRITES) { return; // We don't want to look into garbage data, get out of here. } @@ -897,7 +897,7 @@ void update_front_box_sprite(Simplified_Pokemon *curr_pkmn) void update_menu_sprite(Pokemon_Party *party_data, int index, int frame) { - if (IGNORE_GAME_PAK) + if (IGNORE_GAME_PAK || IGNORE_GAME_PAK_SPRITES) { return; // We don't want to look into garbage data, get out of here. } diff --git a/source/text_engine.cpp b/source/text_engine.cpp index 726479d..90d3318 100644 --- a/source/text_engine.cpp +++ b/source/text_engine.cpp @@ -155,6 +155,7 @@ int ptgb_write(const byte *text, bool instant, int length) TFont *font; int num = 0; +/* if (curr_text[char_index] == 0xFB) // This will need to be moved { line_char_index += char_index; @@ -162,7 +163,7 @@ int ptgb_write(const byte *text, bool instant, int length) // Low key kinda scuffed, but it works to split the string curr_text = &curr_line.get_text()[line_char_index]; } - +*/ while ((ch = *str) != 0xFF && num < length) { if (get_frame_count() % 2 == 0 || key_held(KEY_B) || key_held(KEY_A) || instant)