--- a/src/dreamcast.c Sat Oct 27 05:47:55 2007 +0000 +++ b/src/dreamcast.c Wed Oct 31 09:10:23 2007 +0000 @@ -1,5 +1,5 @@ /** - * $Id: dreamcast.c,v 1.26 2007-10-27 05:47:55 nkeynes Exp $ + * $Id: dreamcast.c,v 1.27 2007-10-31 09:10:23 nkeynes Exp $ * Central switchboard for the system. This pulls all the individual modules * together into some kind of coherent structure. This is also where you'd * add Naomi support, if I ever get a board to play with... @@ -220,62 +220,137 @@ uint32_t module_count; }; +struct chunk_header { + char marker[4]; /* Always BLCK */ + char name[8]; /* Block (module) name */ + uint32_t block_length; +}; + +/** + * Check the save state header to ensure that it is a valid, supported + * file. + * @return the number of blocks following, or 0 if the file is invalid. + */ +int dreamcast_read_save_state_header( FILE *f ) +{ + struct save_state_header header; + if( fread( &header, sizeof(header), 1, f ) != 1 ) { + return 0; + } + if( strncmp( header.magic, DREAMCAST_SAVE_MAGIC, 16 ) != 0 ) { + ERROR( "Not a %s save state file", APP_NAME ); + return 0; + } + if( header.version != DREAMCAST_SAVE_VERSION ) { + ERROR( "%s save state version not supported", APP_NAME ); + return 0; + } + if( header.module_count > MAX_MODULES ) { + ERROR( "%s save state is corrupted (bad module count)", APP_NAME ); + return 0; + } + return header.module_count; +} + +int dreamcast_write_chunk_header( const gchar *name, uint32_t length, FILE *f ) +{ + struct chunk_header head; + + memcpy( head.marker, "BLCK", 4 ); + memset( head.name, 0, 8 ); + memcpy( head.name, name, strlen(name) ); + head.block_length = length; + return fwrite( &head, sizeof(head), 1, f ); +} + + +frame_buffer_t dreamcast_load_preview( const gchar *filename ) +{ + int i; + FILE *f = fopen( filename, "r" ); + if( f == NULL ) return NULL; + + int module_count = dreamcast_read_save_state_header(f); + if( module_count <= 0 ) { + fclose(f); + return NULL; + } + for( i=0; i MAX_MODULES ) { - ERROR( "%s save state is corrupted (bad module count)", APP_NAME ); - return 1; - } + for( i=0; i 64 || len < 1 ) { - ERROR( "%s save state is corrupted (bad string)", APP_NAME ); + fclose(f); return 2; } /* Find the matching module by name */ for( j=0; jname,tmp) == 0 ) { + if( strcmp(modules[j]->name,chunk.name) == 0 ) { have_read[j] = 1; if( modules[j]->load == NULL ) { ERROR( "%s save state is corrupted (no loader for %s)", APP_NAME, modules[j]->name ); + fclose(f); return 2; } else if( modules[j]->load(f) != 0 ) { ERROR( "%s save state is corrupted (%s failed)", APP_NAME, modules[j]->name ); + fclose(f); return 2; } break; } } if( j == num_modules ) { + fclose(f); ERROR( "%s save state contains unrecognized section", APP_NAME ); return 2; } @@ -315,9 +390,15 @@ fwrite( &header, sizeof(header), 1, f ); for( i=0; isave != NULL ) { - fwrite( "BLCK", 4, 1, f ); - fwrite_string( modules[i]->name, f ); + uint32_t blocklen, posn1, posn2; + dreamcast_write_chunk_header( modules[i]->name, 0, f ); + posn1 = ftell(f); modules[i]->save(f); + posn2 = ftell(f); + blocklen = posn2 - posn1; + fseek( f, posn1-4, SEEK_SET ); + fwrite( &blocklen, sizeof(blocklen), 1, f ); + fseek( f, posn2, SEEK_SET ); } } fclose( f );