diff --git a/include/flash_mem.h b/include/flash_mem.h index bb1797a..d587e59 100644 --- a/include/flash_mem.h +++ b/include/flash_mem.h @@ -15,10 +15,25 @@ extern char mem_name; extern u8 global_memory_buffer[0x1000]; extern rom_data curr_GBA_rom; -void initalize_memory_locations(); +/** + * @brief Given that the save sections within a save slot are not saved in a fixed order, + * This function will walk through the save slot to fill the memory_section_array map. + * + * After calling this, memory_section_array will point to the save offset by each section ID. + * So memory_section_array[0] will point to the save offset of section 0, etc. + */ +void initialize_memory_locations(); + void print_mem_section(); //bool insert_pokemon(Pokemon party_array[], int num); void reverse_endian(u8 *data, size_t size); + +/** + * @brief This function will update the checksum in global_memory_buffer. + * It assumes that global_memory_buffer contains one of the save data sections. + * + * @param hall_of_fame This is needed to indicate if you're trying to save the hall of fame section. The checksum offset is slightly different there. + */ void update_memory_buffer_checksum(bool hall_of_fame); bool read_flag(u16 flag_id); bool compare_map_and_npc_data(int map_bank, int map_id, int npc_id); diff --git a/include/mystery_gift_builder.h b/include/mystery_gift_builder.h index 42a7ebc..07deac3 100644 --- a/include/mystery_gift_builder.h +++ b/include/mystery_gift_builder.h @@ -4,7 +4,7 @@ #include #include "pokemon_party.h" #include "debug_mode.h" -#include "save_data_manager.h" +#include "ptgb_save_data_manager.h" #include "script_var.h" #include "pokemon_data.h" diff --git a/include/save_data_manager.h b/include/ptgb_save_data_manager.h similarity index 75% rename from include/save_data_manager.h rename to include/ptgb_save_data_manager.h index 3885bda..b2849b4 100644 --- a/include/save_data_manager.h +++ b/include/ptgb_save_data_manager.h @@ -1,12 +1,14 @@ -#ifndef SAVE_DATA_MANAGER_H -#define SAVE_DATA_MANAGER_H +#ifndef PTGB_SAVE_DATA_MANAGER_H +#define PTGB_SAVE_DATA_MANAGER_H -#include #include "rom_data.h" #define HALL_OF_FAME 0x01C000 #define HOF_SECTION 2032 +// NOTE: This module doesn't manage the _game_ save. It manages Poke_Transporter's specific save data. +// This save data is stored at an unused section (HOF_SECTION) of the HALL OF FAME save section. + // Data map: // There are 1936 (0x790) unused bytes starting at 0x1D7F0 @@ -27,7 +29,7 @@ void set_def_lang(int nLang); int get_def_lang_num(); bool get_tutorial_flag(); void set_tutorial_flag(bool value); -void initalize_save_data(); +void initialize_save_data(); int get_dex_completion(int gen, bool include_mythicals); bool check_can_save(); #endif diff --git a/source/box_menu.cpp b/source/box_menu.cpp index 22e5265..f9ea386 100644 --- a/source/box_menu.cpp +++ b/source/box_menu.cpp @@ -2,7 +2,7 @@ #include "typeDefs.h" #include "button_menu.h" #include "button_handler.h" -#include "save_data_manager.h" +#include "ptgb_save_data_manager.h" #include "global_frame_controller.h" #include "string" #include "sprite_data.h" diff --git a/source/button_menu.cpp b/source/button_menu.cpp index 196986d..acead91 100644 --- a/source/button_menu.cpp +++ b/source/button_menu.cpp @@ -1,7 +1,7 @@ #include #include "button_menu.h" #include "button_handler.h" -#include "save_data_manager.h" +#include "ptgb_save_data_manager.h" #include "global_frame_controller.h" #include "string" diff --git a/source/flash_mem.cpp b/source/flash_mem.cpp index b8f570f..81507ae 100644 --- a/source/flash_mem.cpp +++ b/source/flash_mem.cpp @@ -6,19 +6,17 @@ #include "libraries/Pokemon-Gen3-to-Gen-X/include/save.h" #include "text_engine.h" -#define pkmn_length 80 -#define READ_SAVE_SECTIONS 5 +#define READ_SAVE_SECTIONS 14 #define TOTAL_SAVE_SECTIONS 14 vu32 newest_save_offset = SAVE_A_OFFSET; -vu32 memory_section_array[READ_SAVE_SECTIONS] = {}; +vu32 memory_section_array[READ_SAVE_SECTIONS]; u8 global_memory_buffer[0x1000]; -char mem_name = 'A'; u8 mem_id; // Fills the variables with the current offset information -void initalize_memory_locations() +void initialize_memory_locations() { u8 save_A_index[4]; u8 save_B_index[4]; @@ -31,10 +29,12 @@ void initalize_memory_locations() if (*(vu32 *)save_B_index > *(vu32 *)save_A_index) { newest_save_offset = SAVE_B_OFFSET; - mem_name = 'B'; } // Populates the memory_section_array with the correct pointer locations + // The sections within the save slot are rotated on every save. So it doesn't + // start at the first section. However, the next sections follow sequentially. + // https://bulbapedia.bulbagarden.net/wiki/Save_data_structure_(Generation_III)#Section_ID copy_save_to_ram(newest_save_offset + SECTION_ID_OFFSET, &mem_id, 1); for (int i = 0; i < TOTAL_SAVE_SECTIONS; i++) { @@ -99,6 +99,7 @@ void print_mem_section() /* uint16_t charset[256]; byte out[4] = {0, 0, 0, 0xFF}; + const char mem_name = (newest_save_offset == SAVE_A_OFFSET) ? 'A' : 'B'; load_localized_charset(charset, 3, ENGLISH); @@ -124,33 +125,28 @@ void reverse_endian(u8 *data, size_t size) void update_memory_buffer_checksum(bool hall_of_fame) { - vu32 checksum = 0x00; + u32 checksum = 0x00; - vu32 num_of_bytes = 3968; - if (global_memory_buffer[0x0FF4] == 13) + // Section 13 is the last PC buffer (I) and that one only has 2000 bytes of data. + // source: https://bulbapedia.bulbagarden.net/wiki/Save_data_structure_(Generation_III)#Section_ID + const u32 num_of_bytes = (global_memory_buffer[SECTION_ID_OFFSET] != 13) ? 3968 : 2000; + + // the cpu is little endian and the data is read as little endian too. + // therefore, we can do a straightforward sum of the data as u32's. + const u32 *cur = (const u32 *)global_memory_buffer; + const u32 * const end = (const u32 *)(global_memory_buffer + num_of_bytes); + while (cur < end) { - num_of_bytes = 2000; + checksum += *cur; + ++cur; } - for (unsigned int i = 0; i < num_of_bytes / 4; i++) - { - checksum += (global_memory_buffer[(4 * i) + 3] << 24) | - (global_memory_buffer[(4 * i) + 2] << 16) | - (global_memory_buffer[(4 * i) + 1] << 8) | - (global_memory_buffer[(4 * i) + 0] << 0); - } + const u16 small_checksum = ((checksum & 0xFFFF0000) >> 16) + (checksum & 0x0000FFFF); + const u32 checksum_offset = hall_of_fame ? 0x0FF4 : 0x0FF6; + + global_memory_buffer[checksum_offset] = small_checksum & 0x00FF; + global_memory_buffer[checksum_offset + 1] = (small_checksum & 0xFF00) >> 8; - vu16 small_checksum = ((checksum & 0xFFFF0000) >> 16) + (checksum & 0x0000FFFF); - if (hall_of_fame) - { - global_memory_buffer[0x0FF4] = small_checksum & 0x00FF; - global_memory_buffer[0x0FF5] = (small_checksum & 0xFF00) >> 8; - } - else - { - global_memory_buffer[0x0FF6] = small_checksum & 0x00FF; - global_memory_buffer[0x0FF7] = (small_checksum & 0xFF00) >> 8; - } } bool read_flag(u16 flag_id) diff --git a/source/main.cpp b/source/main.cpp index 3fda236..4fb9393 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -21,7 +21,7 @@ #include "pokedex.h" #include "global_frame_controller.h" #include "pkmn_font.h" -#include "save_data_manager.h" +#include "ptgb_save_data_manager.h" #include "mystery_gift_injector.h" #include "mystery_gift_builder.h" #include "multiboot_upload.h" @@ -72,9 +72,9 @@ void load_graphics() yes_no_menu.add_button(Button(button_no), false); } -void initalization_script(void) +void initialization_script(void) { - // Initalizations + // Initializations REG_DISPCNT = DCNT_BLANK | DCNT_MODE0 | DCNT_BG0 | DCNT_BG1 | DCNT_BG2 | DCNT_BG3 | DCNT_OBJ | DCNT_OBJ_1D; // Disable for save data read/write @@ -452,7 +452,7 @@ static void __attribute__((noinline)) show_intro() int main(void) { malloc_init_default_pool(); - initalization_script(); + initialization_script(); // Set colors based on current ROM set_background_pal(0, false, false); @@ -482,15 +482,15 @@ int main(void) obj_hide_multi(ptgb_logo_l, 2); global_next_frame(); game_load_error(); - // initalization_script(); + // initialization_script(); } } - // Initalize memory and save data after loading the game + // Initialize memory and save data after loading the game reset_textbox(); REG_BG2CNT = REG_BG2CNT | BG_PRIO(3); init_bank(); - initalize_memory_locations(); + initialize_memory_locations(); load_custom_save_data(); set_background_pal(curr_GBA_rom.gamecode, false, true); @@ -499,7 +499,7 @@ int main(void) { obj_hide_multi(ptgb_logo_l, 2); text_loop(BTN_TRANSFER); - initalize_save_data(); + initialize_save_data(); // TODO: We should be able to test for a Bootleg rom in here- if the save data isn't written, then it is bootleg. } diff --git a/source/pokedex.cpp b/source/pokedex.cpp index fa65e60..22a9709 100644 --- a/source/pokedex.cpp +++ b/source/pokedex.cpp @@ -6,7 +6,7 @@ #include "sprite_data.h" #include "pokemon_data.h" #include "global_frame_controller.h" -#include "save_data_manager.h" +#include "ptgb_save_data_manager.h" #include "button_handler.h" #include "translated_text.h" #include "text_engine.h" diff --git a/source/pokemon_party.cpp b/source/pokemon_party.cpp index d533b58..83bd377 100644 --- a/source/pokemon_party.cpp +++ b/source/pokemon_party.cpp @@ -12,7 +12,7 @@ #include "gb_gen1_payloads_RB_lz10_bin.h" #include "gb_gen1_payloads_Y_lz10_bin.h" #include "gb_gen2_payloads_lz10_bin.h" -#include "save_data_manager.h" +#include "ptgb_save_data_manager.h" #include "libraries/Pokemon-Gen3-to-Gen-X/include/save.h" static byte gen1_rb_debug_box_data[0x462] = { diff --git a/source/save_data_manager.cpp b/source/ptgb_save_data_manager.cpp similarity index 88% rename from source/save_data_manager.cpp rename to source/ptgb_save_data_manager.cpp index d6c99c3..a40776a 100644 --- a/source/save_data_manager.cpp +++ b/source/ptgb_save_data_manager.cpp @@ -1,5 +1,5 @@ #include -#include "save_data_manager.h" +#include "ptgb_save_data_manager.h" #include "flash_mem.h" #include "debug_mode.h" #include "button_menu.h" @@ -11,19 +11,14 @@ byte save_data_array[SAVE_DATA_SIZE]; void load_custom_save_data() { copy_save_to_ram(HALL_OF_FAME + 0x1000, &global_memory_buffer[0], 0x1000); - for (int i = 0; i < SAVE_DATA_SIZE; i++) - { - save_data_array[i] = global_memory_buffer[HOF_SECTION + i]; - } + memcpy(save_data_array, global_memory_buffer + HOF_SECTION, SAVE_DATA_SIZE); } void write_custom_save_data() { copy_save_to_ram(HALL_OF_FAME + 0x1000, &global_memory_buffer[0], 0x1000); - for (int i = 0; i < SAVE_DATA_SIZE; i++) - { - global_memory_buffer[HOF_SECTION + i] = save_data_array[i]; - } + memcpy(global_memory_buffer + HOF_SECTION, save_data_array, SAVE_DATA_SIZE); + update_memory_buffer_checksum(true); erase_sector(HALL_OF_FAME + 0x1000); copy_ram_to_save(&global_memory_buffer[0], HALL_OF_FAME + 0x1000, 0x1000); @@ -59,12 +54,9 @@ bool get_tutorial_flag() return save_data_array[TUTORIAL_FLAG]; } -void initalize_save_data() +void initialize_save_data() { - for (int i = 0; i < SAVE_DATA_SIZE; i++) - { - save_data_array[i] = 0; - } + memset(save_data_array, 0, SAVE_DATA_SIZE); set_tutorial_flag(true); write_custom_save_data(); } diff --git a/source/rom_data.cpp b/source/rom_data.cpp index 8788373..ba4be89 100644 --- a/source/rom_data.cpp +++ b/source/rom_data.cpp @@ -3,7 +3,7 @@ #include "pokemon_party.h" #include "pokemon_data.h" #include "text_engine.h" -#include "save_data_manager.h" +#include "ptgb_save_data_manager.h" #include "gba_rom_values/gba_rom_values.h" #include "libraries/nanoprintf/nanoprintf.h" #include "gba_rom_values_eng_lz10_bin.h"