suloku / gcmm

A gamecube/wii memory card manager
GNU General Public License v3.0
251 stars 24 forks source link

Restoring a backup fails if it would completely fill the memory card #23

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Steps to reproduce:
1. Have a memory card in the system with some number of empty blocks (call that 
number n)
2. Launch GCMM, select your sd card/hard drive and go to Restore
3. Attempt to restore a backed up save exactly n blocks large.

Expected behaviour:
GCMM copies the save file to the memory card.

Observed behaviour:
The restore fails, showing this error: "MemCard Error: -6 - File/Dir entry 
broken"

Additional information:
I haven't yet been able to test this with a non-empty memory card. My memory 
card is official by Nintendo and has a capacity of 59 blocks. I encounter this 
issue with my save from Pokémon Box Ruby & Sapphire. That game creates saves 
that are 59 blocks large, so I ran into this while trying to restore to an 
empty card. I believe the same behaviour would occur if, say, there were 55 
used blocks and I tried to restore a save that was 4 blocks large, but I don't 
know this for sure.

Cause:
I don't know for sure that this is the cause, though I have a pretty good idea.

In the __card_allocblock function of card.c is the following code:

count = 0; // blah blah blah while (1) { // blah blah blah

/*
  Since testing free space has already been done, if all the blocks
  the file takes up cannot be entered into the FAT, something is
  wrong.
*/
count++;
if(count>=((card->blocks)-CARD_SYSAREA)) return CARD_ERROR_BROKEN;

// blah blah blah

}


This code makes sure that you don't step over the end of the card's capacity 
while allocating blocks. However, it's slightly overzealous: 
"count>=((card->blocks)-CARD_SYSAREA)" is true if the current block is the last 
one on the card.

Proposed fix:
I've attached a modified card.c to this issue. The only change is in line 732 
(the one referred to above). "count>=[snip]" has been changed to 
"count>[snip]". This ensures that the error isn't encountered until the code is 
thinking about a block that actually doesn't exist.

This fix allowed me to restore my Pokémon Box save, but I haven't tested it 
beyond that. It could cause bugs elsewhere in the code, though I personally 
doubt that very much. (To be fair, I don't know anything. This fix is the first 
non-"Hello World" C I've ever written. You probably shouldn't trust me.)

Original issue reported on code.google.com by undergro...@gmail.com on 5 Mar 2015 at 4:16

Attachments: