Codeburner Posted December 21, 2023 Posted December 21, 2023 (edited) Hi, Short Version: I have a corrupted save file for Pokemon Ruby and I'm not entirely sure what is wrong with it. I was hoping to see if there's any way we can fix the file and use it again because I had put 40+ hours in it. Long Version: I have a cartridge for Pokemon Ruby and I have been playing it using an Analogue Pocket. The Pocket doesn't really secure the Gameboy Advance cartridges very well and they can easily disconnect. While I was loading up the game in the Pocket (I just saw the black screen with the Pokemon copyright details), I accidentally pushed the cartridge out with my hands. I turned it off because it was making a glitch sound and when I turned it on again, the game gave me the message that the save file was corrupted and it's was forcing me to start a new game. I know that there are two game slots in the save file, so I started a new game and saved it immediately to see if moving to the other slot could solve the problem, but it didn't. When you load the game, it says that the file is corrupted and it will use the backup instead (which is the one that has no progress at all). I used the Analogue Pocket's "Memories" feature where you can get save state files and I followed this post on Redit (Solution for extracting Pokemon Emerald cartridge saves with Memories) to extract the .sav file from the save state. I've been trying to find what the problem with the file is and even if it's possible to fix it. I looked at your PKHeX GitHub repository and created a simple .NET program that references the PKHeX.Core library to try to see if I could load the save file correctly. I can load the save file fine into your SAV3RS Class fine. However, I can see that it's selecting the slot with no progress as the active slot (much like the game) because the slot 0 doesn't have all the 14 data sectors correctly. using PKHeX.Core; // Extract the .sav file from the .sta file byte[] saveData = ReadBytesInRange("PokemonRuby.sta", startOffset: 0x60F4A, endOffset: 0x80F49); // Save a copy of the .sav file File.WriteAllBytes("PokemonRuby.sav", saveData); Console.WriteLine("Checking sections of slot 0"); bool v0 = SAV3RS.IsAllMainSectorsPresent(saveData, 0, out _); Console.WriteLine("Checking sections of slot 1"); bool v1 = SAV3RS.IsAllMainSectorsPresent(saveData, 1, out _); Console.WriteLine("Does Slot 0 has all main sectors present? = {0}", v0); Console.WriteLine("Does Slot 1 has all main sectors present? = {0}", v1); Console.WriteLine("Done."); static byte[] ReadBytesInRange(string filePath, long startOffset, long endOffset) { using FileStream fileStream = new(filePath, FileMode.Open, FileAccess.Read); using BinaryReader binaryReader = new(fileStream); // Move the stream position to the start offset fileStream.Seek(startOffset, SeekOrigin.Begin); // Calculate the number of bytes to read int length = (int)(endOffset - startOffset); // Read the bytes into a byte array (inclusive) return binaryReader.ReadBytes(length + 1); } If I log each section ID from the SAV3.IsAllMainSectorsPresent method I can see the sections from 0-13 loaded fine for slot 1, but not for slot 0. Checking sections of slot 0 sector id = 5; BitTrack = 100000 sector id = 8; BitTrack = 100100000 sector id = 9; BitTrack = 1100100000 sector id = 8; BitTrack = 1100100000 sector id = 9; BitTrack = 1100100000 sector id = 12; BitTrack = 1001100100000 sector id = 13; BitTrack = 11001100100000 sector id = 0; BitTrack = 11001100100001 sector id = 1; BitTrack = 11001100100011 sector id = 0; BitTrack = 11001100100011 sector id = 1; BitTrack = 11001100100011 sector id = 4; BitTrack = 11001100110011 sector id = -1; BitTrack = 10000000000000000011001100110011 sector id = -1; BitTrack = 10000000000000000011001100110011 Checking sections of slot 1 sector id = 4; BitTrack = 10000 sector id = 5; BitTrack = 110000 sector id = 6; BitTrack = 1110000 sector id = 7; BitTrack = 11110000 sector id = 8; BitTrack = 111110000 sector id = 9; BitTrack = 1111110000 sector id = 10; BitTrack = 11111110000 sector id = 11; BitTrack = 111111110000 sector id = 12; BitTrack = 1111111110000 sector id = 13; BitTrack = 11111111110000 sector id = 0; BitTrack = 11111111110001 sector id = 1; BitTrack = 11111111110011 sector id = 2; BitTrack = 11111111110111 sector id = 3; BitTrack = 11111111111111 Does Slot 0 has all main sectors present? = False Does Slot 1 has all main sectors present? = True Done. Maybe only section 12, 13, 0, 1 are loaded correctly for slot 0, but I'm not sure. Do you have any clues or ideas? Have you seen something like this happen before? Is the data truly gone? Thanks, I appreciate any help. Also, your coding syntax is beautiful. It's like reading Shakespeare in C#. PokemonRuby.sav PokemonRuby.sta Edited December 21, 2023 by Codeburner Finished incomplete sentenses
Kaphotics Posted December 21, 2023 Posted December 21, 2023 If you open your save file in a hex editor (like HxD) you can visualize the 0x1000-sized save blocks for your data. As you can see, the second slot has all block IDs present, while your other one has D,1,0,4 with duplicates containing different checksums. The games store box data in block chunks [3,D], and player data (progress, etc) in blocks [0,2]. Unfortunately, your backup there does not contain a block for #2. I would try "transplanting" blocks (chunks of 0x1000 bytes) from the corrupt save into a donor save, to see what information you can recover. Maybe just overwriting the second save to see what data pops out in PKHeX.
Codeburner Posted December 21, 2023 Author Posted December 21, 2023 Hi thanks for the response, it really helped understand the save file better. I was able to copy the sections I had from the first slot over to the second one but nothing really changed, the game starts on the same initial save in Littleroot Town. Probably because I don’t have the sections 02 and 03. Unfortunately, I don’t think it’s possible to restore where I left off without the second section where we save the game state. Thanks again.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now