gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > Readin garbage from files

#169236 - DiscoStew - Wed Jun 24, 2009 9:23 pm

This is an odd problem for me, because it's a problem that "sometimes" happens. It's not random, as I can duplicate the error by reading each file in a particular order. Changing the order may bring up the error earlier or later, and the file the error comes up with in one order doesn't occur in another order, as some other file brings it up instead.

Anyways, this came up when working on a decompression method for my project. I haven't had any problems with the algorithm when it ran on the PC, but on the DS (hardware and emulator), the problem occurs "sometimes". I spent weeks on trying to fix it, thinking it was my algorithm......until just today when I thought about making duplicate copies of each file, reading them alongside the originals (ignoring my decompression algorithm altogether), and comparing the value read from one with the other.

The result? I think I'm reading garbage because the value between the 2 doesn't match, which is odd, because the garbage is read midway through the files, not at the beginning. Has anyone else been reading "garbage" from files? The functions I use for this are fopen, fclose, and fread (which will only read 1 byte at a time).
_________________
DS - It's all about DiscoStew

#169239 - elhobbs - Wed Jun 24, 2009 10:08 pm

If the error is occuring on hardware and emulators alike then I would say it is probably stack corruption.

#169262 - DiscoStew - Thu Jun 25, 2009 9:43 pm

If it is stack corruption, then maybe you can help me figure out what I'm doing wrong.

I made a small test program that does one thing; Examines 2 files that have equal contents, and errors if the 2 bytes that are read don't match. The files in question that I'm using have a 4 byte header that give the size of the file (minus the header itself), so I read those 4 bytes on both files, then loop through the rest of the files one byte at a time, comparing the 2 8-bit values together.

Code:
#include <nds.h>
#include <fat.h>

#include <stdio.h>


int fget8( FILE* fin ) {
   u8 a[1];
   fread( a, 1, 1, fin );
   return a[0];
}

int fget16( FILE* fin ) {
   return fget8( fin ) | ( fget8( fin ) << 8 );
}

u32 fget32( FILE* fin ) {
   return fget16( fin ) | ( fget16( fin ) << 16 );
}



int examine_Files( const char *file1, const char *file2 ) {

   FILE *fin1 = fopen( file1, "rb" );
   FILE *fin2 = fopen( file2, "rb" );

   int fSize1 = fget32( fin1 );
   int fSize2 = fget32( fin2 );

   sassert( fSize1 == fSize2, "Files not same size" );

   int fPos = 0;
   while( fPos < fSize1 )
   {
      sassert( feof( fin1 ) == feof( fin2 ), "One ended before the other." );
      int test1 = fget8( fin1 );
      int test2 = fget8( fin2 );
      sassert( test1 == test2, "Corruption detected." );
      fPos++;
   }

   fclose( fin2 );
   fclose( fin1 );

   iprintf( "good\n" );
   return 1;
}


int main(void) {

   consoleDemoInit();
   if( !fatInitDefault() ) {
      iprintf( "FAT is required.\n" );
      while( 1 ) swiWaitForVBlank();
   }

   while(1) {
      swiWaitForVBlank();

      scanKeys();
      int keysd = keysDown();
   
      if( keysd & KEY_UP )
         examine_Files( "test1a.dat", "test1b.dat" );
      else if( keysd & KEY_RIGHT )
         examine_Files( "test2a.dat", "test2b.dat" );
      else if( keysd & KEY_DOWN )
         examine_Files( "test3a.dat", "test3b.dat" );
      else if( keysd & KEY_LEFT )
         examine_Files( "test4a.dat", "test4b.dat" );
   }
}


When I try the "test1" or "test2" files first, it errors, but if I reset and try "test3" before "test1", I get no error on either, but "test3" before "test2" errors on "test2". The errors will always pop up at the right times when the same pattern for examining the files (by user input) is done.

I'm assuming that I am doing something wrong in my code, and I don't even recognize it.
_________________
DS - It's all about DiscoStew

#169267 - ingramb - Fri Jun 26, 2009 1:12 am

This probably won't do anything, but you could try
Quote:
int fget8( FILE* fin ) {
static u8 a[1];
fread( a, 1, 1, fin );
return a[0];
}


Just in case freading into the stack (DTCM) is causing problems.

#169268 - DiscoStew - Fri Jun 26, 2009 1:43 am

ingramb wrote:
This probably won't do anything


I beg to differ. I tried your change, and over the hundred tests I did (pattern and random), I have yet to see it error again. Until further notice, I believe you've fixed my problem. Thanks.
_________________
DS - It's all about DiscoStew

#169269 - elhobbs - Fri Jun 26, 2009 1:59 am

I think you may have an issue with sign extension on your return values. fget8 and fget16 return signed int values. I think they should be unsigned int or u8 and u16 respectively.

try reading a file in and writing it back to a different file. then check the results in a hex editor. if sign extension is the issue then you will probably see a lot of 0xff values in the file you write back.

#169271 - DiscoStew - Fri Jun 26, 2009 5:38 am

The stuff I've been doing atm hasn't been using any particular format outside of just reading the 3 types, but I see your point if I plan to read specific format straight from a file.
_________________
DS - It's all about DiscoStew