From e07dbc4094ef765621b6edd1869b383336049adf Mon Sep 17 00:00:00 2001 From: Gwenhael Le Moine Date: Sat, 13 Apr 2024 21:57:05 +0200 Subject: [PATCH] Persist RAM, port1&2 in files. Create files if needed. Path management yet to be done --- src/emulator.c | 9 ++- src/files.c | 206 ++++++++++++++++++++++++++++++++++++++++++------- src/files.h | 14 ++-- src/types.h | 1 + 4 files changed, 191 insertions(+), 39 deletions(-) diff --git a/src/emulator.c b/src/emulator.c index cb97056..f37f954 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -48,9 +48,9 @@ void emulator_init( void ) { static bool locked = false; - rom_init(); - ram_init(); - ports_init(); + rom_init( "./rom" ); + ram_init( "./ram" ); + ports_init( "./port1", "./port2" ); bus_init(); if ( !locked ) @@ -60,7 +60,8 @@ void emulator_init( void ) void emulator_exit( void ) { rom_exit(); - ram_exit(); + ram_exit( "./ram" ); + ports_exit( "./port1", "./port2" ); bus_exit(); } diff --git a/src/files.c b/src/files.c index 7d05f38..8547df1 100644 --- a/src/files.c +++ b/src/files.c @@ -4,6 +4,7 @@ #include // dirname #include // readlink #include // PATH_MAX +#include #include "gui.h" #include "rpl.h" @@ -38,14 +39,14 @@ void getExePath() strcpy( WorkingPath, programPath ); } -int file_size( char* name ) +int file_size( char* filename ) { memset( WorkingPath, 0, sizeof( WorkingPath ) ); getExePath(); FILE* f; char fullpath[ 1024 ]; - sprintf( fullpath, "%s/%s", WorkingPath, name ); + sprintf( fullpath, "%s/%s", WorkingPath, filename ); printf( "%s\n", fullpath ); f = fopen( fullpath, "r" ); if ( !f ) @@ -59,7 +60,135 @@ int file_size( char* name ) return size; } -void load_file_on_stack( char* name ) +int read_mem_file( char* filename, nibble* mem, int size ) +{ + struct stat st; + FILE* fp; + byte* tmp_mem; + byte rbyte; + int i, j; + + if ( NULL == ( fp = fopen( filename, "r" ) ) ) { + /* if ( verbose ) */ + /* fprintf( stderr, "ct open %s\n", filename ); */ + return 0; + } + + if ( stat( filename, &st ) < 0 ) { + /* if ( verbose ) */ + /* fprintf( stderr, "can\'t stat %s\n", filename ); */ + return 0; + } + + if ( st.st_size == size ) { + /* + * size is same as memory size, old version file + */ + if ( fread( mem, 1, ( size_t )size, fp ) != ( unsigned long )size ) { + /* if ( verbose ) */ + /* fprintf( stderr, "can\'t read %s\n", filename ); */ + fclose( fp ); + return 0; + } + } else { + /* + * size is different, check size and decompress memory + */ + + if ( st.st_size != size / 2 ) { + /* if ( verbose ) */ + /* fprintf( stderr, "strange size %s, expected %d, found %ld\n", filename, size / 2, st.st_size ); */ + fclose( fp ); + return 0; + } + + if ( NULL == ( tmp_mem = ( byte* )malloc( ( size_t )st.st_size ) ) ) { + for ( i = 0, j = 0; i < size / 2; i++ ) { + if ( 1 != fread( &rbyte, 1, 1, fp ) ) { + /* if ( verbose ) */ + /* fprintf( stderr, "can\'t read %s\n", filename ); */ + fclose( fp ); + return 0; + } + mem[ j++ ] = ( nibble )( ( int )rbyte & 0xf ); + mem[ j++ ] = ( nibble )( ( ( int )rbyte >> 4 ) & 0xf ); + } + } else { + if ( fread( tmp_mem, 1, ( size_t )size / 2, fp ) != ( unsigned long )( size / 2 ) ) { + /* if ( verbose ) */ + /* fprintf( stderr, "can\'t read %s\n", filename ); */ + fclose( fp ); + free( tmp_mem ); + return 0; + } + + for ( i = 0, j = 0; i < size / 2; i++ ) { + mem[ j++ ] = ( nibble )( ( int )tmp_mem[ i ] & 0xf ); + mem[ j++ ] = ( nibble )( ( ( int )tmp_mem[ i ] >> 4 ) & 0xf ); + } + + free( tmp_mem ); + } + } + + fclose( fp ); + + /* if ( verbose ) */ + /* printf( "read %s\n", filename ); */ + + return 1; +} + +int write_mem_file( char* filename, nibble* mem, int size ) +{ + FILE* fp; + byte* tmp_mem; + byte rbyte; + int i, j; + + if ( NULL == ( fp = fopen( filename, "w" ) ) ) { + /* if ( verbose ) */ + /* fprintf( stderr, "can\'t open %s\n", filename ); */ + return 0; + } + + if ( NULL == ( tmp_mem = ( byte* )malloc( ( size_t )size / 2 ) ) ) { + for ( i = 0, j = 0; i < size / 2; i++ ) { + rbyte = ( mem[ j++ ] & 0x0f ); + rbyte |= ( mem[ j++ ] << 4 ) & 0xf0; + if ( 1 != fwrite( &rbyte, 1, 1, fp ) ) { + /* if ( verbose ) */ + /* fprintf( stderr, "can\'t write %s\n", filename ); */ + fclose( fp ); + return 0; + } + } + } else { + for ( i = 0, j = 0; i < size / 2; i++ ) { + tmp_mem[ i ] = ( mem[ j++ ] & 0x0f ); + tmp_mem[ i ] |= ( mem[ j++ ] << 4 ) & 0xf0; + } + + if ( fwrite( tmp_mem, 1, ( size_t )size / 2, fp ) != ( unsigned long )size / 2 ) { + /* if ( verbose ) */ + /* fprintf( stderr, "can\'t write %s\n", filename ); */ + fclose( fp ); + free( tmp_mem ); + return 0; + } + + free( tmp_mem ); + } + + fclose( fp ); + + /* if ( verbose ) */ + /* printf( "wrote %s\n", filename ); */ + + return 1; +} + +void load_file_on_stack( char* filename ) { FILE* f; byte* buf; @@ -68,7 +197,7 @@ void load_file_on_stack( char* name ) int fsize; address size; - fsize = file_size( name ); + fsize = file_size( filename ); if ( fsize < 11 ) // "PHPH48-X" + prologue (8 + 2.5) return; @@ -76,7 +205,7 @@ void load_file_on_stack( char* name ) if ( !buf ) return; - f = fopen( name, "r" ); + f = fopen( filename, "r" ); if ( !f ) { free( buf ); return; @@ -115,52 +244,49 @@ void load_file_on_stack( char* name ) free( obj ); } -void rom_init( void ) +void rom_init( char* filename ) { int size; - char* name = "rom"; byte *buf, *ptr1, *ptr2; FILE* f; - size = file_size( name ); + size = file_size( filename ); if ( !size ) { - printf( "rom_init failed\n" ); + printf( "ERROR: Can't read ROM file size\n" ); exit( 0x10 ); } if ( size != 256 * 1024 && size != 512 * 1024 && size != 1024 * 1024 ) { - printf( "rom_init failed2..\n" ); + printf( "ERROR: ROM file size invalid\n" ); exit( 0x11 ); } buf = malloc( size ); if ( !buf ) { - printf( "rom_init failed3..\n" ); + printf( "ERROR: can't malloc ROM\n" ); exit( 0x12 ); } char fullpath[ 1024 ]; - sprintf( fullpath, "%s/%s", WorkingPath, name ); + sprintf( fullpath, "%s/%s", WorkingPath, filename ); - // f = pack_fopen(name, "r"); f = fopen( fullpath, "r" ); if ( !f ) { - printf( "rom_init failed4..\n" ); + printf( "ERROR: can't open ROM file\n" ); exit( 0x13 ); } - int r = ( int )fread( buf, sizeof( char ), size, f ); - if ( r != size ) { // pack_fread - printf( "rom_init failed5..\n" ); + if ( ( int )fread( buf, sizeof( char ), size, f ) != size ) { // pack_fread + printf( "ERROR: can't read ROM file\n" ); exit( 0x14 ); } // pack_fclose(f); fclose( f ); if ( buf[ 0 ] & 0xF0 || buf[ 1 ] & 0xF0 ) { if ( size == 1024 * 1024 ) { - printf( "rom_init failed6..\n" ); + printf( "ERROR: wrong ROM\n" ); exit( 0x15 ); } buf = realloc( buf, size * 2 ); if ( !buf ) { - printf( "rom_init failed7..\n" ); + printf( "ERROR: can't realloc ROM\n" ); exit( 0x16 ); } ptr1 = buf + size - 1; @@ -183,25 +309,36 @@ void rom_exit( void ) bus_info.rom_mask = 0x00000; } -void ram_init( void ) +void ram_init( char* filename ) { - byte* buf = malloc( ram_size ); - if ( !buf ) - exit( 0x20 ); + bus_info.ram_data = malloc( ram_size ); + + int filesize = file_size( filename ); + fprintf( stderr, "filesize(%i) == ram_size(%i)\n", filesize, ram_size ); + if ( filesize * 2 == ram_size ) + read_mem_file( filename, bus_info.ram_data, ram_size ); + else { + byte* buf = malloc( ram_size ); + if ( !buf ) + exit( 0x20 ); + + memset( buf, 0, ram_size ); + bus_info.ram_data = buf; + } - memset( buf, 0, ram_size ); - bus_info.ram_data = buf; bus_info.ram_mask = ram_size - 1; } -void ram_exit( void ) +void ram_exit( char* filename ) { + write_mem_file( filename, bus_info.ram_data, ram_size ); + free( bus_info.ram_data ); bus_info.ram_data = NULL; bus_info.ram_mask = 0x00000; } -void ports_init( void ) +void ports_init( char* filename1, char* filename2 ) { // ce1 = bank switcher bus_info.ce1_data = NULL; @@ -211,11 +348,20 @@ void ports_init( void ) // ce2 = port1 (plugged) bus_info.ce2_data = malloc( PORT1_SIZE ); + + int filesize = file_size( filename1 ); + if ( filesize * 2 == PORT1_SIZE ) + read_mem_file( filename1, bus_info.ce2_data, ram_size ); + bus_info.ce2_mask = PORT1_SIZE - 1; bus_info.ce2_r_o = false; // nce3 = port2 (plugged) port2 = malloc( PORT2_SIZE ); + + filesize = file_size( filename2 ); + if ( filesize * 2 == PORT2_SIZE ) + read_mem_file( filename2, port2, PORT2_SIZE ); port2mask = PORT2_SIZE - 1; bus_info.nce3_data = port2; bus_info.nce3_mask = port2mask & 0x3FFFF; @@ -225,4 +371,8 @@ void ports_init( void ) current_bank = 0; } -void ports_exit( void ) {} +void ports_exit( char* filename1, char* filename2 ) +{ + write_mem_file( filename1, bus_info.ce2_data, PORT1_SIZE ); + write_mem_file( filename2, port2, PORT2_SIZE ); +} diff --git a/src/files.h b/src/files.h index 18466cc..53caf95 100644 --- a/src/files.h +++ b/src/files.h @@ -5,16 +5,16 @@ extern char WorkingPath[ 512 ]; -extern int file_size( char* name ); -extern void load_file_on_stack( char* name ); +extern int file_size( char* filename ); +extern void load_file_on_stack( char* filename ); -extern void rom_init( void ); +extern void rom_init( char* filename ); extern void rom_exit( void ); -extern void ram_init( void ); -extern void ram_exit( void ); +extern void ram_init( char* filename ); +extern void ram_exit( char* filename ); -extern void ports_init( void ); -extern void ports_exit( void ); +extern void ports_init( char* filename1, char* filename2 ); +extern void ports_exit( char* filename1, char* filename2 ); #endif diff --git a/src/types.h b/src/types.h index daa2965..02e75c8 100644 --- a/src/types.h +++ b/src/types.h @@ -5,6 +5,7 @@ #define MIN( a, b ) ( ( a ) < ( b ) ? ( a ) : ( b ) ) +typedef unsigned char nibble; typedef unsigned char byte; typedef unsigned short word; typedef unsigned int dword;