diff --git a/source/save.c b/source/save.c index d3d6875..44a29ea 100644 --- a/source/save.c +++ b/source/save.c @@ -31,14 +31,15 @@ #define BANK_LIMIT (NUM_BANKS * BANK_SIZE) #endif -uintptr_t bank_check(uintptr_t); +static uintptr_t bank_check(uintptr_t); +static size_t sanitize_save_size(uintptr_t, size_t); static u8 read_direct_single_byte_save(uintptr_t); static void write_direct_single_byte_save(uintptr_t, u8); u8 current_bank; u8 is_macronix; -IWRAM_CODE void init_bank(){ +IWRAM_CODE void init_bank() { REG_WAITCNT &= NON_SRAM_MASK; REG_WAITCNT |= SRAM_READING_VALID_WAITCYCLES; current_bank = NUM_BANKS; @@ -54,7 +55,7 @@ IWRAM_CODE void init_bank(){ #endif } -IWRAM_CODE uintptr_t bank_check(uintptr_t address){ +IWRAM_CODE uintptr_t bank_check(uintptr_t address) { address %= (NUM_BANKS * BANK_SIZE); #if IS_FLASH u8 bank = address / BANK_SIZE; @@ -114,103 +115,110 @@ IWRAM_CODE void write_direct_single_byte_save(uintptr_t address, u8 data) { } } -IWRAM_CODE u8 read_byte_save(uintptr_t address){ +IWRAM_CODE u8 read_byte_save(uintptr_t address) { address = bank_check(address); return read_direct_single_byte_save(address); } -IWRAM_CODE void write_byte_save(uintptr_t address, u8 data){ +IWRAM_CODE u16 read_short_save(uintptr_t address) { + u16 data_out = 0; + copy_save_to_ram(address, (u8*)&data_out, sizeof(u16)); + return data_out; +} + +IWRAM_CODE u32 read_int_save(uintptr_t address) { + u32 data_out = 0; + copy_save_to_ram(address, (u8*)&data_out, sizeof(u32)); + return data_out; +} + +IWRAM_CODE void write_byte_save(uintptr_t address, u8 data) { address = bank_check(address); write_direct_single_byte_save(address, data); } -IWRAM_CODE u32 read_int_save(uintptr_t address){ +IWRAM_CODE void write_short_save(uintptr_t address, u16 data) { + u16 data_in = data; + copy_ram_to_save((u8*)&data_in, address, sizeof(u16)); +} + +IWRAM_CODE void write_int_save(uintptr_t address, u32 data) { + u32 data_in = data; + copy_ram_to_save((u8*)&data_in, address, sizeof(u32)); +} + +IWRAM_CODE size_t sanitize_save_size(uintptr_t address, size_t size) { + address %= NUM_BANKS * BANK_SIZE; + if((address + size) > (NUM_BANKS * BANK_SIZE)) + size = (NUM_BANKS * BANK_SIZE) - address; + return size; +} + +IWRAM_CODE void copy_save_to_ram(uintptr_t address, u8* destination, size_t size) { + // Sanitize size + size = sanitize_save_size(address, size); + address = bank_check(address); - u32 data_out = 0; - if((address + sizeof(u32)) > BANK_LIMIT) { - for(size_t i = 0; i < sizeof(u32); i++) - data_out += read_byte_save(address + i) << (i*8); - } - else { - for(size_t i = 0; i < sizeof(u32); i++) - data_out += read_direct_single_byte_save(address + i) << (i*8); - } - return data_out; -} + size_t num_banks = (address + size + BANK_SIZE - 1) / BANK_SIZE; + for(size_t n = 0; n < num_banks; n++) { + size_t inner_size = size; + if(n != (num_banks - 1)) + inner_size = BANK_SIZE - address; -IWRAM_CODE u16 read_short_save(uintptr_t address){ - address = bank_check(address); - u16 data_out = 0; - if((address + sizeof(u16)) > BANK_LIMIT) { - for(size_t i = 0; i < sizeof(u16); i++) - data_out += read_byte_save(address + i) << (i*8); - } - else { - for(size_t i = 0; i < sizeof(u16); i++) - data_out += read_direct_single_byte_save(address + i) << (i*8); - } - return data_out; -} + for(size_t i = 0; i < inner_size; i++) + destination[i] = read_direct_single_byte_save(address + i); -IWRAM_CODE void write_int_save(uintptr_t address, u32 data){ - address = bank_check(address); - if((address + sizeof(u32)) > BANK_LIMIT) { - for(size_t i = 0; i < sizeof(u32); i++) - write_byte_save(address + i, (data >> (i*8)) & 0xFF); - } - else { - for(size_t i = 0; i < sizeof(u32); i++) - write_direct_single_byte_save(address + i, (data >> (i*8)) & 0xFF); + if(n != (num_banks - 1)) { + address = bank_check(address + inner_size); + destination += inner_size; + size -= inner_size; + } } } -IWRAM_CODE void write_short_save(uintptr_t address, u16 data){ - address = bank_check(address); - if((address + sizeof(u16)) > BANK_LIMIT) { - for(size_t i = 0; i < sizeof(u16); i++) - write_byte_save(address + i, (data >> (i*8)) & 0xFF); - } - else { - for(size_t i = 0; i < sizeof(u16); i++) - write_direct_single_byte_save(address + i, (data >> (i*8)) & 0xFF); - } -} +IWRAM_CODE void copy_ram_to_save(u8* base_address, uintptr_t save_address, size_t size) { + // Sanitize size + size = sanitize_save_size(save_address, size); -IWRAM_CODE void copy_save_to_ram(uintptr_t base_address, u8* new_address, size_t size){ - base_address = bank_check(base_address); - if((base_address + size) > BANK_LIMIT) { - for(size_t i = 0; i < size; i++) - new_address[i] = read_byte_save(base_address + i); - } - else { - for(size_t i = 0; i < size; i++) - new_address[i] = read_direct_single_byte_save(base_address + i); - } -} - -IWRAM_CODE void copy_ram_to_save(u8* base_address, uintptr_t save_address, size_t size){ save_address = bank_check(save_address); - if((save_address + size) > BANK_LIMIT) { - for(size_t i = 0; i < size; i++) - write_byte_save(save_address + i, base_address[i]); - } - else { - for(size_t i = 0; i < size; i++) + size_t num_banks = (save_address + size + BANK_SIZE - 1) / BANK_SIZE; + for(size_t n = 0; n < num_banks; n++) { + size_t inner_size = size; + if(n != (num_banks - 1)) + inner_size = BANK_SIZE - save_address; + + for(size_t i = 0; i < inner_size; i++) write_direct_single_byte_save(save_address + i, base_address[i]); + + if(n != (num_banks - 1)) { + save_address = bank_check(save_address + inner_size); + base_address += inner_size; + size -= inner_size; + } } } IWRAM_CODE u8 is_save_correct(u8* base_address, uintptr_t save_address, size_t size) { + // Sanitize size + size = sanitize_save_size(save_address, size); + save_address = bank_check(save_address); - if((save_address + size) > BANK_LIMIT) { - for(size_t i = 0; i < size; i++) - if(read_byte_save(save_address + i) != base_address[i]) - return 0; - } - else { - for(size_t i = 0; i < size; i++) + size_t num_banks = (save_address + size + BANK_SIZE - 1) / BANK_SIZE; + for(size_t n = 0; n < num_banks; n++) { + size_t inner_size = size; + if(n != (num_banks - 1)) + inner_size = BANK_SIZE - save_address; + + for(size_t i = 0; i < inner_size; i++) if(read_direct_single_byte_save(save_address + i) != base_address[i]) return 0; + + if(n != (num_banks - 1)) { + save_address = bank_check(save_address + inner_size); + base_address += inner_size; + size -= inner_size; + } } + return 1; }