Search
lxdream.org :: lxdream/src/dreamcast.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/dreamcast.c
changeset 477:9a373f2ff009
prev466:a6935f46ed78
next480:d28c2992f5ee
author nkeynes
date Wed Oct 31 09:11:14 2007 +0000 (16 years ago)
permissions -rw-r--r--
last change Add warning for non-direct rendering
file annotate diff log raw
1.1 --- a/src/dreamcast.c Sat Oct 27 05:47:55 2007 +0000
1.2 +++ b/src/dreamcast.c Wed Oct 31 09:11:14 2007 +0000
1.3 @@ -1,5 +1,5 @@
1.4 /**
1.5 - * $Id: dreamcast.c,v 1.26 2007-10-27 05:47:55 nkeynes Exp $
1.6 + * $Id: dreamcast.c,v 1.27 2007-10-31 09:10:23 nkeynes Exp $
1.7 * Central switchboard for the system. This pulls all the individual modules
1.8 * together into some kind of coherent structure. This is also where you'd
1.9 * add Naomi support, if I ever get a board to play with...
1.10 @@ -220,62 +220,137 @@
1.11 uint32_t module_count;
1.12 };
1.13
1.14 +struct chunk_header {
1.15 + char marker[4]; /* Always BLCK */
1.16 + char name[8]; /* Block (module) name */
1.17 + uint32_t block_length;
1.18 +};
1.19 +
1.20 +/**
1.21 + * Check the save state header to ensure that it is a valid, supported
1.22 + * file.
1.23 + * @return the number of blocks following, or 0 if the file is invalid.
1.24 + */
1.25 +int dreamcast_read_save_state_header( FILE *f )
1.26 +{
1.27 + struct save_state_header header;
1.28 + if( fread( &header, sizeof(header), 1, f ) != 1 ) {
1.29 + return 0;
1.30 + }
1.31 + if( strncmp( header.magic, DREAMCAST_SAVE_MAGIC, 16 ) != 0 ) {
1.32 + ERROR( "Not a %s save state file", APP_NAME );
1.33 + return 0;
1.34 + }
1.35 + if( header.version != DREAMCAST_SAVE_VERSION ) {
1.36 + ERROR( "%s save state version not supported", APP_NAME );
1.37 + return 0;
1.38 + }
1.39 + if( header.module_count > MAX_MODULES ) {
1.40 + ERROR( "%s save state is corrupted (bad module count)", APP_NAME );
1.41 + return 0;
1.42 + }
1.43 + return header.module_count;
1.44 +}
1.45 +
1.46 +int dreamcast_write_chunk_header( const gchar *name, uint32_t length, FILE *f )
1.47 +{
1.48 + struct chunk_header head;
1.49 +
1.50 + memcpy( head.marker, "BLCK", 4 );
1.51 + memset( head.name, 0, 8 );
1.52 + memcpy( head.name, name, strlen(name) );
1.53 + head.block_length = length;
1.54 + return fwrite( &head, sizeof(head), 1, f );
1.55 +}
1.56 +
1.57 +
1.58 +frame_buffer_t dreamcast_load_preview( const gchar *filename )
1.59 +{
1.60 + int i;
1.61 + FILE *f = fopen( filename, "r" );
1.62 + if( f == NULL ) return NULL;
1.63 +
1.64 + int module_count = dreamcast_read_save_state_header(f);
1.65 + if( module_count <= 0 ) {
1.66 + fclose(f);
1.67 + return NULL;
1.68 + }
1.69 + for( i=0; i<module_count; i++ ) {
1.70 + struct chunk_header head;
1.71 + if( fread( &head, sizeof(head), 1, f ) != 1 ) {
1.72 + fclose(f);
1.73 + return NULL;
1.74 + }
1.75 + if( memcmp("BLCK", head.marker, 4) != 0 ) {
1.76 + fclose(f);
1.77 + return NULL;
1.78 + }
1.79 +
1.80 + if( strcmp("PVR2", head.name) == 0 ) {
1.81 + uint32_t buf_count;
1.82 + int has_front;
1.83 + fread( &buf_count, sizeof(buf_count), 1, f );
1.84 + fread( &has_front, sizeof(has_front), 1, f );
1.85 + if( buf_count != 0 && has_front ) {
1.86 + frame_buffer_t result = read_png_from_stream(f);
1.87 + fclose(f);
1.88 + return result;
1.89 + }
1.90 + break;
1.91 + } else {
1.92 + fseek( f, head.block_length, SEEK_CUR );
1.93 + }
1.94 + }
1.95 + return NULL;
1.96 +}
1.97 +
1.98 int dreamcast_load_state( const gchar *filename )
1.99 {
1.100 int i,j;
1.101 uint32_t len;
1.102 + int module_count;
1.103 int have_read[MAX_MODULES];
1.104 - char tmp[64];
1.105 - struct save_state_header header;
1.106 - FILE *f;
1.107
1.108 - f = fopen( filename, "r" );
1.109 + FILE *f = fopen( filename, "r" );
1.110 if( f == NULL ) return errno;
1.111
1.112 - fread( &header, sizeof(header), 1, f );
1.113 - if( strncmp( header.magic, DREAMCAST_SAVE_MAGIC, 16 ) != 0 ) {
1.114 - ERROR( "Not a %s save state file", APP_NAME );
1.115 + module_count = dreamcast_read_save_state_header(f);
1.116 + if( module_count <= 0 ) {
1.117 + fclose(f);
1.118 return 1;
1.119 }
1.120 - if( header.version != DREAMCAST_SAVE_VERSION ) {
1.121 - ERROR( "%s save state version not supported", APP_NAME );
1.122 - return 1;
1.123 - }
1.124 - if( header.module_count > MAX_MODULES ) {
1.125 - ERROR( "%s save state is corrupted (bad module count)", APP_NAME );
1.126 - return 1;
1.127 - }
1.128 +
1.129 for( i=0; i<MAX_MODULES; i++ ) {
1.130 have_read[i] = 0;
1.131 }
1.132
1.133 - for( i=0; i<header.module_count; i++ ) {
1.134 - fread(tmp, 4, 1, f );
1.135 - if( strncmp(tmp, "BLCK", 4) != 0 ) {
1.136 + for( i=0; i<module_count; i++ ) {
1.137 + struct chunk_header chunk;
1.138 + fread( &chunk, sizeof(chunk), 1, f );
1.139 + if( strncmp(chunk.marker, "BLCK", 4) != 0 ) {
1.140 ERROR( "%s save state is corrupted (missing block header %d)", APP_NAME, i );
1.141 - return 2;
1.142 - }
1.143 - len = fread_string(tmp, sizeof(tmp), f );
1.144 - if( len > 64 || len < 1 ) {
1.145 - ERROR( "%s save state is corrupted (bad string)", APP_NAME );
1.146 + fclose(f);
1.147 return 2;
1.148 }
1.149
1.150 /* Find the matching module by name */
1.151 for( j=0; j<num_modules; j++ ) {
1.152 - if( strcmp(modules[j]->name,tmp) == 0 ) {
1.153 + if( strcmp(modules[j]->name,chunk.name) == 0 ) {
1.154 have_read[j] = 1;
1.155 if( modules[j]->load == NULL ) {
1.156 ERROR( "%s save state is corrupted (no loader for %s)", APP_NAME, modules[j]->name );
1.157 + fclose(f);
1.158 return 2;
1.159 } else if( modules[j]->load(f) != 0 ) {
1.160 ERROR( "%s save state is corrupted (%s failed)", APP_NAME, modules[j]->name );
1.161 + fclose(f);
1.162 return 2;
1.163 }
1.164 break;
1.165 }
1.166 }
1.167 if( j == num_modules ) {
1.168 + fclose(f);
1.169 ERROR( "%s save state contains unrecognized section", APP_NAME );
1.170 return 2;
1.171 }
1.172 @@ -315,9 +390,15 @@
1.173 fwrite( &header, sizeof(header), 1, f );
1.174 for( i=0; i<num_modules; i++ ) {
1.175 if( modules[i]->save != NULL ) {
1.176 - fwrite( "BLCK", 4, 1, f );
1.177 - fwrite_string( modules[i]->name, f );
1.178 + uint32_t blocklen, posn1, posn2;
1.179 + dreamcast_write_chunk_header( modules[i]->name, 0, f );
1.180 + posn1 = ftell(f);
1.181 modules[i]->save(f);
1.182 + posn2 = ftell(f);
1.183 + blocklen = posn2 - posn1;
1.184 + fseek( f, posn1-4, SEEK_SET );
1.185 + fwrite( &blocklen, sizeof(blocklen), 1, f );
1.186 + fseek( f, posn2, SEEK_SET );
1.187 }
1.188 }
1.189 fclose( f );
.