revision 1109:700c5ab26a63
summary |
tree |
shortlog |
changelog |
graph |
changeset |
raw | bz2 | zip | gz changeset | 1109:700c5ab26a63 |
parent | 1108:305ef2082079 |
child | 1110:eb1c005ba3cb |
author | nkeynes |
date | Thu Jun 10 22:13:16 2010 +1000 (13 years ago) |
Integrate executable wrapping into the user interface
- command-line now loads wrapped by default, -e <bin> to run binary
- add support for .bin executables
- Add useful (internal) error codes
- command-line now loads wrapped by default, -e <bin> to run binary
- add support for .bin executables
- Add useful (internal) error codes
1.1 --- a/src/bootstrap.h Fri Jun 04 09:13:40 2010 +10001.2 +++ b/src/bootstrap.h Thu Jun 10 22:13:16 2010 +10001.3 @@ -35,6 +35,7 @@1.4 #define BOOTSTRAP_MAGIC_SIZE 321.6 #define BINARY_LOAD_ADDR 0x8C0100001.7 +#define BINARY_MAX_SIZE (0x8D000000 - BINARY_LOAD_ADDR)1.9 /**1.10 * Bootstrap header structure
2.1 --- a/src/cocoaui/cocoaui.m Fri Jun 04 09:13:40 2010 +10002.2 +++ b/src/cocoaui/cocoaui.m Thu Jun 10 22:13:16 2010 +10002.3 @@ -216,7 +216,8 @@2.4 - (BOOL)application: (NSApplication *)app openFile: (NSString *)filename2.5 {2.6 const gchar *cname = [filename UTF8String];2.7 - if( file_load_magic(cname) ) {2.8 + ERROR err;2.9 + if( file_load_magic(cname, FALSE, &err) != FILE_ERROR ) {2.10 // Queue up a run event2.11 gui_do_later(dreamcast_run);2.12 return YES;2.13 @@ -269,8 +270,12 @@2.14 int result = [panel runModalForDirectory: path file: nil types: nil];2.15 if( result == NSOKButton && [[panel filenames] count] > 0 ) {2.16 NSString *filename = [[panel filenames] objectAtIndex: 0];2.17 - file_load_magic( [filename UTF8String] );2.18 + ERROR err;2.19 + gboolean ok = file_load_exec( [filename UTF8String], &err );2.20 set_gui_path(CONFIG_DEFAULT_PATH, [[panel directory] UTF8String]);2.21 + if( !ok ) {2.22 + ERROR( err.msg );2.23 + }2.24 }2.25 }2.26 - (void) mount_action: (id)sender2.27 @@ -279,8 +284,12 @@2.28 NSString *path = [NSString stringWithCString: get_gui_path(CONFIG_DEFAULT_PATH)];2.29 int result = [panel runModalForDirectory: path file: nil types: nil];2.30 if( result == NSOKButton && [[panel filenames] count] > 0 ) {2.31 + ERROR err;2.32 NSString *filename = [[panel filenames] objectAtIndex: 0];2.33 - gdrom_mount_image( [filename UTF8String] );2.34 + gboolean ok = gdrom_mount_image( [filename UTF8String], &err );2.35 + if( !ok ) {2.36 + ERROR(err.msg);2.37 + }2.38 set_gui_path(CONFIG_DEFAULT_PATH, [[panel directory] UTF8String]);2.39 }2.40 }2.41 @@ -301,7 +310,11 @@2.42 }2.43 - (void) gdrom_list_action: (id)sender2.44 {2.45 - gdrom_list_set_selection( [sender tag] );2.46 + ERROR err;2.47 + gboolean ok = gdrom_list_set_selection( [sender tag], &err );2.48 + if( !ok ) {2.49 + ERROR( err.msg );2.50 + }2.51 }2.52 - (void) fullscreen_action: (id)sender2.53 {
3.1 --- a/src/dreamcast.c Fri Jun 04 09:13:40 2010 +10003.2 +++ b/src/dreamcast.c Thu Jun 10 22:13:16 2010 +10003.3 @@ -448,7 +448,7 @@3.4 return NULL;3.5 }3.7 -int dreamcast_load_state( const gchar *filename )3.8 +gboolean dreamcast_load_state( const gchar *filename )3.9 {3.10 int i,j;3.11 int module_count;3.12 @@ -456,13 +456,13 @@3.13 int have_read[MAX_MODULES];3.15 FILE *f = fopen( filename, "r" );3.16 - if( f == NULL ) return errno;3.17 + if( f == NULL ) return FALSE;3.19 module_count = dreamcast_read_save_state_header(f, error, sizeof(error));3.20 if( module_count <= 0 ) {3.21 ERROR( error );3.22 fclose(f);3.23 - return 1;3.24 + return FALSE;3.25 }3.27 for( i=0; i<MAX_MODULES; i++ ) {3.28 @@ -475,7 +475,7 @@3.29 if( strncmp(chunk.marker, "BLCK", 4) != 0 ) {3.30 ERROR( "%s save state is corrupted (missing block header %d)", APP_NAME, i );3.31 fclose(f);3.32 - return 2;3.33 + return FALSE;3.34 }3.36 /* Find the matching module by name */3.37 @@ -485,11 +485,11 @@3.38 if( modules[j]->load == NULL ) {3.39 ERROR( "%s save state is corrupted (no loader for %s)", APP_NAME, modules[j]->name );3.40 fclose(f);3.41 - return 2;3.42 + return FALSE;3.43 } else if( modules[j]->load(f) != 0 ) {3.44 ERROR( "%s save state is corrupted (%s failed)", APP_NAME, modules[j]->name );3.45 fclose(f);3.46 - return 2;3.47 + return FALSE;3.48 }3.49 break;3.50 }3.51 @@ -497,7 +497,7 @@3.52 if( j == num_modules ) {3.53 fclose(f);3.54 ERROR( "%s save state contains unrecognized section", APP_NAME );3.55 - return 2;3.56 + return FALSE;3.57 }3.58 }3.60 @@ -512,7 +512,7 @@3.61 }3.62 fclose(f);3.63 INFO( "Save state read from %s", filename );3.64 - return 0;3.65 + return TRUE;3.66 }3.68 int dreamcast_save_state( const gchar *filename )
4.1 --- a/src/drivers/cdrom/cd_cdi.c Fri Jun 04 09:13:40 2010 +10004.2 +++ b/src/drivers/cdrom/cd_cdi.c Thu Jun 10 22:13:16 2010 +10004.3 @@ -73,7 +73,7 @@4.4 trail.cdi_version == CDI_V35_ID;4.5 }4.7 -#define RETURN_PARSE_ERROR( ... ) do { SET_ERROR(err, EINVAL, __VA_ARGS__); return FALSE; } while(0)4.8 +#define RETURN_PARSE_ERROR( ... ) do { SET_ERROR(err, LX_ERR_FILE_INVALID, __VA_ARGS__); return FALSE; } while(0)4.10 static gboolean cdi_image_read_toc( cdrom_disc_t disc, ERROR *err )4.11 {
5.1 --- a/src/drivers/cdrom/cd_gdi.c Fri Jun 04 09:13:40 2010 +10005.2 +++ b/src/drivers/cdrom/cd_gdi.c Thu Jun 10 22:13:16 2010 +10005.3 @@ -64,12 +64,12 @@5.4 fseek(f, 0, SEEK_SET);5.6 if( fgets( line, sizeof(line), f ) == NULL ) {5.7 - SET_ERROR( err, EINVAL, "Invalid GDI image" );5.8 + SET_ERROR( err, LX_ERR_FILE_INVALID, "Invalid GDI image" );5.9 return FALSE;5.10 }5.11 track_count = strtoul(line, NULL, 0);5.12 if( track_count == 0 || track_count > 99 ) {5.13 - SET_ERROR( err, EINVAL, "Invalid GDI image" );5.14 + SET_ERROR( err, LX_ERR_FILE_INVALID, "Invalid GDI image" );5.15 return FALSE;5.16 }5.18 @@ -83,7 +83,7 @@5.20 if( fgets( line, sizeof(line), f ) == NULL ) {5.21 cdrom_disc_unref(disc);5.22 - SET_ERROR( err, EINVAL, "Invalid GDI image - unexpected end of file" );5.23 + SET_ERROR( err, LX_ERR_FILE_INVALID, "Invalid GDI image - unexpected end of file" );5.24 return FALSE;5.25 }5.26 sscanf( line, "%d %d %d %d %s %d", &track_no, &start_lba, &flags, &size,5.27 @@ -105,7 +105,7 @@5.28 case 2336: mode = SECTOR_SEMIRAW_MODE2; break;5.29 case 2352: mode = SECTOR_RAW_XA; break;5.30 default:5.31 - SET_ERROR( err, EINVAL, "Invalid sector size '%d' in GDI track %d", size, (i+1) );5.32 + SET_ERROR( err, LX_ERR_FILE_INVALID, "Invalid sector size '%d' in GDI track %d", size, (i+1) );5.33 g_free(dirname);5.34 return FALSE;5.35 }5.36 @@ -115,7 +115,7 @@5.37 if( size == 0 )5.38 size = 2352;5.39 else if( size != 2352 ) {5.40 - SET_ERROR( err, EINVAL, "Invalid sector size '%d' for audio track %d", size, (i+1) );5.41 + SET_ERROR( err, LX_ERR_FILE_INVALID, "Invalid sector size '%d' for audio track %d", size, (i+1) );5.42 g_free(dirname);5.43 return FALSE;5.44 }5.45 @@ -128,7 +128,8 @@5.46 offset, FILE_SECTOR_FULL_FILE );5.47 g_free(pathname);5.48 if( disc->track[i].source == NULL ) {5.49 - SET_ERROR( err, ENOENT, "GDI track file '%s' could not be opened (%s)", filename, strerror(errno) );5.50 + /* Note: status is invalid because it's a failure of the GDI file */5.51 + SET_ERROR( err, LX_ERR_FILE_INVALID, "GDI track file '%s' could not be opened (%s)", filename, strerror(errno) );5.52 g_free(dirname);5.53 return FALSE;5.54 }
6.1 --- a/src/drivers/cdrom/cd_linux.c Fri Jun 04 09:13:40 2010 +10006.2 +++ b/src/drivers/cdrom/cd_linux.c Thu Jun 10 22:13:16 2010 +10006.3 @@ -103,12 +103,12 @@6.5 int fd = open(drive->name, O_RDONLY|O_NONBLOCK);6.6 if( fd == -1 ) {6.7 - SET_ERROR(err, errno, "Unable to open device '%s': %s", drive->name, strerror(errno) );6.8 + SET_ERROR(err, LX_ERR_FILE_NOOPEN, "Unable to open device '%s': %s", drive->name, strerror(errno) );6.9 return NULL;6.10 } else {6.11 FILE *f = fdopen(fd,"ro");6.12 if( !linux_is_cdrom_device(f) ) {6.13 - SET_ERROR(err, EINVAL, "Device '%s' is not a CDROM drive", drive->name );6.14 + SET_ERROR(err, LX_ERR_FILE_UNKNOWN, "Device '%s' is not a CDROM drive", drive->name );6.15 return NULL;6.16 }6.17 return cdrom_disc_scsi_new_file(f, drive->name, &linux_scsi_transport, err);
7.1 --- a/src/drivers/cdrom/cd_nrg.c Fri Jun 04 09:13:40 2010 +10007.2 +++ b/src/drivers/cdrom/cd_nrg.c Thu Jun 10 22:13:16 2010 +10007.3 @@ -150,7 +150,7 @@7.4 }7.5 }7.7 -#define RETURN_PARSE_ERROR( ... ) do { SET_ERROR(err, EINVAL, __VA_ARGS__); return FALSE; } while(0)7.8 +#define RETURN_PARSE_ERROR( ... ) do { SET_ERROR(err, LX_ERR_FILE_INVALID, __VA_ARGS__); return FALSE; } while(0)7.10 static gboolean nrg_image_read_toc( cdrom_disc_t disc, ERROR *err )7.11 {
8.1 --- a/src/drivers/cdrom/cd_osx.c Fri Jun 04 09:13:40 2010 +10008.2 +++ b/src/drivers/cdrom/cd_osx.c Thu Jun 10 22:13:16 2010 +10008.3 @@ -81,7 +81,7 @@8.5 osx_cdrom_drive_t osx_drive = osx_cdrom_open_drive(drive->name);8.6 if( osx_drive == NULL ) {8.7 - SET_ERROR( err, ENOENT, "Unable to open CDROM drive" );8.8 + SET_ERROR( err, LX_ERR_FILE_NOOPEN, "Unable to open CDROM drive" );8.9 return NULL;8.10 } else {8.11 return cdrom_osx_new( drive->name, osx_drive, err );
9.1 --- a/src/drivers/cdrom/cdrom.c Fri Jun 04 09:13:40 2010 +10009.2 +++ b/src/drivers/cdrom/cdrom.c Thu Jun 10 22:13:16 2010 +10009.3 @@ -116,7 +116,7 @@9.4 if( disc != NULL ) {9.5 cdrom_disc_init( disc, name );9.6 } else {9.7 - SET_ERROR(err, ENOMEM, "Unable to allocate memory for cdrom disc");9.8 + SET_ERROR(err, LX_ERR_NOMEM, "Unable to allocate memory for cdrom disc");9.9 }9.10 return disc;9.11 }9.12 @@ -131,7 +131,7 @@9.13 if( disc != NULL && filename != NULL ) {9.14 disc->base_source = file_sector_source_new_filename( filename, SECTOR_UNKNOWN, 0, FILE_SECTOR_FULL_FILE );9.15 if( disc->base_source == NULL ) {9.16 - SET_ERROR( err, errno, "Unable to open cdrom file '%s': %s", filename, strerror(errno) );9.17 + SET_ERROR( err, LX_ERR_FILE_NOOPEN, "Unable to open cdrom file '%s': %s", filename, strerror(errno) );9.18 cdrom_disc_unref(disc);9.19 disc = NULL;9.20 } else {9.21 @@ -272,7 +272,7 @@9.22 } else {9.23 /* No handler found for file */9.24 cdrom_disc_unref( disc );9.25 - SET_ERROR( err, EINVAL, "File '%s' could not be recognized as any known image file or device type" );9.26 + SET_ERROR( err, LX_ERR_FILE_UNKNOWN, "File '%s' could not be recognized as any known image file or device type", filename );9.27 return NULL;9.28 }9.29 }9.30 @@ -284,7 +284,7 @@9.31 * @param lba The position on disc of the main track. If non-zero,9.32 * a filler track is added before it, in 2 separate sessions.9.33 */9.34 -cdrom_disc_t cdrom_disc_new_from_track( cdrom_disc_type_t type, sector_source_t track, cdrom_lba_t lba )9.35 +cdrom_disc_t cdrom_disc_new_from_track( cdrom_disc_type_t type, sector_source_t track, cdrom_lba_t lba, ERROR *err )9.36 {9.37 cdrom_disc_t disc = cdrom_disc_new( NULL, NULL );9.38 if( disc != NULL ) {9.39 @@ -312,6 +312,8 @@9.40 disc->track_count = trackno+1;9.41 disc->session_count = trackno+1;9.42 cdrom_disc_compute_leadout(disc);9.43 + } else {9.44 + SET_ERROR(err, LX_ERR_NOMEM, "Unable to allocate memory for cdrom disc");9.45 }9.46 return disc;9.47 }9.48 @@ -325,7 +327,7 @@9.49 sector_mode_t mode = (type == CDROM_DISC_NONXA ? SECTOR_MODE1 : SECTOR_MODE2_FORM1 );9.50 sector_source_t source = iso_sector_source_new( iso, mode, lba, bootstrap, err );9.51 if( source != NULL ) {9.52 - cdrom_disc_t disc = cdrom_disc_new_from_track(type, source, lba);9.53 + cdrom_disc_t disc = cdrom_disc_new_from_track(type, source, lba, err);9.54 if( disc == NULL ) {9.55 sector_source_unref( source );9.56 } else {
10.1 --- a/src/drivers/cdrom/cdrom.h Fri Jun 04 09:13:40 2010 +100010.2 +++ b/src/drivers/cdrom/cdrom.h Thu Jun 10 22:13:16 2010 +100010.3 @@ -103,7 +103,7 @@10.4 * @param lba The position on disc of the main track. If non-zero,10.5 * a filler track is added before it, in 2 separate sessions.10.6 */10.7 -cdrom_disc_t cdrom_disc_new_from_track( cdrom_disc_type_t type, sector_source_t track, cdrom_lba_t lba );10.8 +cdrom_disc_t cdrom_disc_new_from_track( cdrom_disc_type_t type, sector_source_t track, cdrom_lba_t lba, ERROR *err );10.10 /**10.11 * Get the track information for the given track. If there is no such track,
11.1 --- a/src/drivers/cdrom/isofs.c Fri Jun 04 09:13:40 2010 +100011.2 +++ b/src/drivers/cdrom/isofs.c Thu Jun 10 22:13:16 2010 +100011.3 @@ -60,6 +60,24 @@11.4 return src;11.5 }11.7 +static void iso_error_convert( int status, ERROR *err )11.8 +{11.9 + switch( status ) {11.10 + case ISO_SUCCESS:11.11 + err->code = LX_ERR_NONE;11.12 + break;11.13 + case ISO_OUT_OF_MEM:11.14 + SET_ERROR( err, LX_ERR_NOMEM, "Unable to allocate memory for ISO filesystem" );11.15 + break;11.16 + case ISO_FILE_READ_ERROR:11.17 + SET_ERROR( err, LX_ERR_FILE_IOERROR, "Read error" );11.18 + break;11.19 + default:11.20 + SET_ERROR( err, LX_ERR_UNHANDLED, "Unknown error in ISO filesystem" );11.21 + break;11.22 + }11.23 +}11.24 +11.25 /**11.26 * Construct an isofs image from an existing sector source.11.27 */11.28 @@ -110,6 +128,7 @@11.30 int status = iso_read_opts_new(&opts,0);11.31 if( status != 1 ) {11.32 + iso_error_convert(status, err);11.33 return NULL;11.34 }11.36 @@ -119,6 +138,7 @@11.37 iso_data_source_unref(src);11.38 iso_read_opts_free(opts);11.39 if( status != 1 ) {11.40 + iso_error_convert(status, err);11.41 return NULL;11.42 }11.43 return iso;11.44 @@ -148,8 +168,10 @@11.45 struct burn_source *burn;11.47 int status = iso_write_opts_new(&opts, 0);11.48 - if( status != 1 )11.49 + if( status != 1 ) {11.50 + iso_error_convert(status, err);11.51 return NULL;11.52 + }11.53 iso_write_opts_set_appendable(opts,0);11.54 iso_write_opts_set_ms_block(opts, start_sector);11.55 iso_write_opts_set_system_area(opts, (char *)bootstrap, 0, 0);11.56 @@ -157,6 +179,7 @@11.57 status = iso_image_create_burn_source(image, opts, &burn);11.58 iso_write_opts_free(opts);11.59 if( status != 1 ) {11.60 + iso_error_convert(status, err);11.61 return NULL;11.62 }
12.1 --- a/src/gdlist.c Fri Jun 04 09:13:40 2010 +100012.2 +++ b/src/gdlist.c Thu Jun 10 22:13:16 2010 +100012.3 @@ -147,7 +147,7 @@12.4 CALL_HOOKS( gdrom_list_change_hook, TRUE, gdrom_list_get_selection() );12.5 }12.7 -gboolean gdrom_list_set_selection( int posn )12.8 +gboolean gdrom_list_set_selection( int posn, ERROR *err )12.9 {12.10 if( posn == 0 ) { // Always 'Empty'12.11 gdrom_unmount_disc();12.12 @@ -156,15 +156,17 @@12.14 if( posn <= gdrom_device_count ) {12.15 cdrom_drive_t device = g_list_nth_data(gdrom_device_list, posn-1);12.16 - return gdrom_mount_image(device->name);12.17 + return gdrom_mount_image(device->name, err);12.18 }12.20 posn -= FIRST_RECENT_INDEX;12.21 if( posn >= 0 && posn < gdrom_recent_count ) {12.22 gchar *entry = g_list_nth_data(gdrom_recent_list, posn);12.23 - return gdrom_mount_image(entry);12.24 + return gdrom_mount_image(entry, err);12.25 }12.27 + /* Should never happen */12.28 + SET_ERROR( err, LX_ERR_BUG, "Invalid selection: This is probably a bug" );12.29 return FALSE;12.30 }
13.1 --- a/src/gdlist.h Fri Jun 04 09:13:40 2010 +100013.2 +++ b/src/gdlist.h Thu Jun 10 22:13:16 2010 +100013.3 @@ -20,6 +20,7 @@13.4 #ifndef lxdream_gdlist_H13.5 #define lxdream_gdlist_H 113.7 +#include <stdio.h>13.8 #include "hook.h"13.10 #ifdef __cplusplus13.11 @@ -64,9 +65,10 @@13.12 /**13.13 * Change the current gdrom selection to the selected index. This will mount the13.14 * appropriate drive/image where necessary.13.15 + * @param err Updated if there was an error loading the selected gdrom13.16 * @return TRUE if the selection was updated, FALSE if the position was invalid.13.17 */13.18 -gboolean gdrom_list_set_selection(int posn);13.19 +gboolean gdrom_list_set_selection(int posn, ERROR *err);13.21 #ifdef __cplusplus13.22 }
14.1 --- a/src/gdrom/gdrom.c Fri Jun 04 09:13:40 2010 +100014.2 +++ b/src/gdrom/gdrom.c Thu Jun 10 22:13:16 2010 +100014.3 @@ -28,6 +28,7 @@14.4 #include "gdrom/gdrom.h"14.5 #include "gdrom/packet.h"14.6 #include "bootstrap.h"14.7 +#include "loader.h"14.8 #include "drivers/cdrom/cdrom.h"14.10 #define GDROM_LBA_OFFSET 15014.11 @@ -58,9 +59,12 @@14.12 }14.13 }14.15 -gboolean gdrom_mount_image( const gchar *filename )14.16 +gboolean gdrom_mount_image( const gchar *filename, ERROR *err )14.17 {14.18 - cdrom_disc_t disc = cdrom_disc_open(filename, NULL);14.19 + cdrom_disc_t disc = cdrom_disc_open(filename, err);14.20 + if( disc == NULL && err->code == LX_ERR_FILE_UNKNOWN ) {14.21 + disc = cdrom_wrap_magic( CDROM_DISC_XA, filename, err );14.22 + }14.23 if( disc != NULL ) {14.24 gdrom_mount_disc( disc );14.25 return TRUE;
15.1 --- a/src/gdrom/gdrom.h Fri Jun 04 09:13:40 2010 +100015.2 +++ b/src/gdrom/gdrom.h Thu Jun 10 22:13:16 2010 +100015.3 @@ -53,7 +53,7 @@15.4 * Shortcut to open and mount an image file15.5 * @return true on success15.6 */15.7 -gboolean gdrom_mount_image( const gchar *filename );15.8 +gboolean gdrom_mount_image( const gchar *filename, ERROR *err );15.10 void gdrom_mount_disc( cdrom_disc_t disc );
16.1 --- a/src/gtkui/gtk_gd.c Fri Jun 04 09:13:40 2010 +100016.2 +++ b/src/gtkui/gtk_gd.c Thu Jun 10 22:13:16 2010 +100016.3 @@ -27,17 +27,31 @@16.5 static gboolean gdrom_menu_adjusting = FALSE;16.7 +gboolean gtk_gui_gdrom_mount_image( const char *filename )16.8 +{16.9 + ERROR err;16.10 + gboolean ok = gdrom_mount_image( filename, &err );16.11 + if( !ok ) {16.12 + ERROR( err.msg );16.13 + }16.14 + return ok;16.15 +}16.16 +16.17 static void gdrom_menu_open_image_callback( GtkWidget *widget, gpointer user_data )16.18 {16.19 if( !gdrom_menu_adjusting ) {16.20 - open_file_dialog_cb( _("Open..."), gdrom_mount_image, NULL, NULL, CONFIG_DEFAULT_PATH );16.21 + open_file_dialog_cb( _("Open..."), gtk_gui_gdrom_mount_image, NULL, NULL, CONFIG_DEFAULT_PATH );16.22 }16.23 }16.25 void gdrom_menu_item_callback( GtkWidget *widget, gpointer user_data )16.26 {16.27 if( !gdrom_menu_adjusting ) {16.28 - gdrom_list_set_selection( GPOINTER_TO_INT(user_data) );16.29 + ERROR err;16.30 + gboolean ok = gdrom_list_set_selection( GPOINTER_TO_INT(user_data), &err );16.31 + if( !ok ) {16.32 + ERROR( err.msg );16.33 + }16.34 }16.35 }
17.1 --- a/src/gtkui/gtkcb.c Fri Jun 04 09:13:40 2010 +100017.2 +++ b/src/gtkui/gtkcb.c Thu Jun 10 22:13:16 2010 +100017.3 @@ -129,7 +129,7 @@17.5 void mount_action_callback( GtkAction *action, gpointer user_data)17.6 {17.7 - open_file_dialog_cb( "Open...", gdrom_mount_image, NULL, NULL, CONFIG_DEFAULT_PATH );17.8 + open_file_dialog_cb( "Open...", gtk_gui_gdrom_mount_image, NULL, NULL, CONFIG_DEFAULT_PATH );17.9 }17.10 void reset_action_callback( GtkAction *action, gpointer user_data)17.11 {17.12 @@ -146,9 +146,19 @@17.13 dreamcast_run();17.14 }17.16 +gboolean gtk_gui_load_exec( const gchar *filename )17.17 +{17.18 + ERROR err;17.19 + gboolean ok = file_load_exec(filename, &err);17.20 + if( !ok ) {17.21 + ERROR(err.msg);17.22 + }17.23 + return ok;17.24 +}17.25 +17.26 void load_binary_action_callback( GtkAction *action, gpointer user_data)17.27 {17.28 - open_file_dialog_cb( "Open Binary...", file_load_magic, NULL, NULL, CONFIG_DEFAULT_PATH );17.29 + open_file_dialog_cb( "Open Binary...", gtk_gui_load_exec, NULL, NULL, CONFIG_DEFAULT_PATH );17.30 }17.32 void load_state_preview_callback( GtkFileChooser *chooser, gpointer user_data )
18.1 --- a/src/gtkui/gtkui.h Fri Jun 04 09:13:40 2010 +100018.2 +++ b/src/gtkui/gtkui.h Thu Jun 10 22:13:16 2010 +100018.3 @@ -98,6 +98,7 @@18.4 int initial_dir_key );18.5 void save_file_dialog_cb( const char *title, file_callback_t action, const char *pattern, const char *patname,18.6 int initial_dir_key );18.7 +gboolean gtk_gui_gdrom_mount_image( const char *filename );18.8 /**18.9 * Extract the keyval of the key event if no modifier keys were pressed -18.10 * in other words get the keyval of the key by itself. The other way around
19.1 --- a/src/loader.c Fri Jun 04 09:13:40 2010 +100019.2 +++ b/src/loader.c Thu Jun 10 22:13:16 2010 +100019.3 @@ -33,6 +33,7 @@19.4 #include "loader.h"19.5 #include "drivers/cdrom/cdrom.h"19.6 #include "drivers/cdrom/isofs.h"19.7 +#include "gdrom/gdrom.h"19.9 const char bootstrap_magic[32] = "SEGA SEGAKATANA SEGA ENTERPRISES";19.10 const char iso_magic[6] = "\001CD001";19.11 @@ -41,101 +42,171 @@19.12 { "bin", "SH4 Bin file" },19.13 { NULL, NULL } };19.15 -gboolean file_load_elf_fd( const gchar *filename, int fd );19.16 +static cdrom_disc_t cdrom_wrap_elf( cdrom_disc_type_t type, const gchar *filename, int fd, ERROR *err );19.17 +static cdrom_disc_t cdrom_wrap_binary( cdrom_disc_type_t type, const gchar *filename, int fd, ERROR *err );19.18 +static gboolean file_load_binary( const gchar *filename, int fd, ERROR *err );19.19 +static gboolean file_load_elf( const gchar *filename, int fd, ERROR *err );19.21 -typedef enum {19.22 - FILE_ERROR,19.23 - FILE_BINARY,19.24 - FILE_ELF,19.25 - FILE_ISO,19.26 - FILE_DISC,19.27 - FILE_ZIP,19.28 - FILE_SAVE_STATE,19.29 -} lxdream_file_type_t;19.31 -static lxdream_file_type_t file_magic( const gchar *filename, int fd, ERROR *err )19.32 +19.33 +lxdream_file_type_t file_identify( const gchar *filename, int fd, ERROR *err )19.34 {19.35 char buf[32];19.36 + lxdream_file_type_t result = FILE_UNKNOWN;19.37 + gboolean mustClose = FALSE;19.38 + off_t posn;19.40 - /* begin magic */19.41 - if( read( fd, buf, 32 ) != 32 ) {19.42 - SET_ERROR( err, errno, "Unable to read from file '%s'", filename );19.43 - return FILE_ERROR;19.44 -19.45 + if( fd == -1 ) {19.46 + fd = open( filename, O_RDONLY );19.47 + if( fd == -1 ) {19.48 + SET_ERROR( err, LX_ERR_FILE_NOOPEN, "Unable to open file '%s' (%s)" ,filename, strerror(errno) );19.49 + return FILE_ERROR;19.50 + }19.51 + mustClose = TRUE;19.52 + } else {19.53 + /* Save current file position */19.54 + posn = lseek(fd, 0, SEEK_CUR);19.55 + if( posn == -1 ) {19.56 + SET_ERROR( err, LX_ERR_FILE_IOERROR, "Unable to read from file '%s' (%s)", filename, strerror(errno) );19.57 + return FILE_ERROR;19.58 + }19.59 }19.61 - lseek( fd, 0, SEEK_SET );19.62 - if( buf[0] == 0x7F && buf[1] == 'E' &&19.63 + int status = read(fd, buf, 32);19.64 + if( status == -1 ) {19.65 + SET_ERROR( err, LX_ERR_FILE_IOERROR, "Unable to read from file '%s' (%s)", filename, strerror(errno) );19.66 + result = FILE_ERROR;19.67 + } else if( status != 32 ) {19.68 + result = FILE_UNKNOWN;19.69 + } else if( buf[0] == 0x7F && buf[1] == 'E' &&19.70 buf[2] == 'L' && buf[3] == 'F' ) {19.71 - return FILE_ELF;19.72 + result = FILE_ELF;19.73 } else if( memcmp( buf, "PK\x03\x04", 4 ) == 0 ) {19.74 - return FILE_ZIP;19.75 + result = FILE_ZIP;19.76 } else if( memcmp( buf, DREAMCAST_SAVE_MAGIC, 16 ) == 0 ) {19.77 - return FILE_SAVE_STATE;19.78 + result = FILE_SAVE_STATE;19.79 } else if( lseek( fd, 32768, SEEK_SET ) == 32768 &&19.80 read( fd, buf, 8 ) == 8 &&19.81 memcmp( buf, iso_magic, 6) == 0 ) {19.82 - lseek( fd, 0, SEEK_SET );19.83 - return FILE_ISO;19.84 + result = FILE_ISO;19.85 + } else {19.86 + /* Check the file extension - .bin = sh4 binary */19.87 + int len = strlen(filename);19.88 + struct stat st;19.89 +19.90 + if( len > 4 && strcasecmp(filename + (len-4), ".bin") == 0 &&19.91 + fstat(fd, &st) != -1 && st.st_size <= BINARY_MAX_SIZE ) {19.92 + result = FILE_BINARY;19.93 + }19.94 }19.95 - lseek( fd, 0, SEEK_SET );19.96 - return FILE_BINARY;19.97 +19.98 + if( mustClose ) {19.99 + close(fd);19.100 + } else {19.101 + lseek( fd, posn, SEEK_SET );19.102 + }19.103 + return result;19.104 }19.107 -gboolean file_load_magic( const gchar *filename )19.108 +gboolean file_load_exec( const gchar *filename, ERROR *err )19.109 {19.110 - char buf[32];19.111 - struct stat st;19.112 gboolean result = TRUE;19.114 int fd = open( filename, O_RDONLY );19.115 if( fd == -1 ) {19.116 + SET_ERROR( err, LX_ERR_FILE_NOOPEN, "Unable to open file '%s' (%s)" ,filename, strerror(errno) );19.117 return FALSE;19.118 }19.120 - fstat( fd, &st );19.121 + lxdream_file_type_t type = file_identify(filename, fd, err);19.122 + switch( type ) {19.123 + case FILE_ERROR:19.124 + result = FALSE;19.125 + break;19.126 + case FILE_ELF:19.127 + result = file_load_elf( filename, fd, err );19.128 + break;19.129 + case FILE_BINARY:19.130 + result = file_load_binary( filename, fd, err );19.131 + break;19.132 + default:19.133 + SET_ERROR( err, LX_ERR_FILE_UNKNOWN, "File '%s' could not be recognized as an executable binary", filename );19.134 + result = FALSE;19.135 + break;19.136 + }19.138 - /* begin magic */19.139 - if( read( fd, buf, 32 ) != 32 ) {19.140 - ERROR( "Unable to read from file '%s'", filename );19.141 - close(fd);19.142 - return FALSE;19.143 + close(fd);19.144 + return result;19.145 +}19.146 +19.147 +lxdream_file_type_t file_load_magic( const gchar *filename, gboolean wrap_exec, ERROR *err )19.148 +{19.149 + gboolean result;19.150 + /* Try disc types first */19.151 + cdrom_disc_t disc = cdrom_disc_open( filename, err );19.152 + if( disc != NULL ) {19.153 + gdrom_mount_disc(disc);19.154 + return FILE_DISC;19.155 + } else if( err != LX_ERR_FILE_UNKNOWN ) {19.156 + return FILE_ERROR;19.157 }19.158 - if( memcmp( buf, bootstrap_magic, 32 ) == 0 ) {19.159 - /* we have a DC bootstrap */19.160 - if( st.st_size == BOOTSTRAP_SIZE ) {19.161 - sh4ptr_t load = mem_get_region( BOOTSTRAP_LOAD_ADDR );19.162 - lseek( fd, 0, SEEK_SET );19.163 - read( fd, load, BOOTSTRAP_SIZE );19.164 - bootstrap_dump( load, TRUE );19.165 - dreamcast_program_loaded( filename, BOOTSTRAP_LOAD_ADDR + 0x300 );19.166 +19.167 + int fd = open( filename, O_RDONLY );19.168 + if( fd == -1 ) {19.169 + SET_ERROR( err, LX_ERR_FILE_NOOPEN, "Unable to open file '%s' (%s)" ,filename, strerror(errno) );19.170 + return FILE_ERROR;19.171 + }19.172 +19.173 + lxdream_file_type_t type = file_identify(filename, fd, err);19.174 + switch( type ) {19.175 + case FILE_ERROR:19.176 + result = FALSE;19.177 + break;19.178 + case FILE_ELF:19.179 + if( wrap_exec ) {19.180 + disc = cdrom_wrap_elf( CDROM_DISC_XA, filename, fd, err );19.181 + result = disc != NULL;19.182 + if( disc != NULL ) {19.183 + gdrom_mount_disc(disc);19.184 + }19.185 } else {19.186 - /* look for a valid ISO9660 header */19.187 - lseek( fd, 32768, SEEK_SET );19.188 - read( fd, buf, 8 );19.189 - if( memcmp( buf, iso_magic, 6 ) == 0 ) {19.190 - /* Alright, got it */19.191 - WARN( "ISO images not supported yet" );19.192 + result = file_load_elf( filename, fd, err );19.193 + }19.194 + break;19.195 + case FILE_BINARY:19.196 + if( wrap_exec ) {19.197 + disc = cdrom_wrap_binary( CDROM_DISC_XA, filename, fd, err );19.198 + result = disc != NULL;19.199 + if( disc != NULL ) {19.200 + gdrom_mount_disc(disc);19.201 }19.202 + } else {19.203 + result = file_load_binary( filename, fd, err );19.204 }19.205 - } else if( memcmp( buf, "PK\x03\x04", 4 ) == 0 ) {19.206 - /* ZIP file, aka SBI file */19.207 - WARN( "SBI files not supported yet" );19.208 + break;19.209 + case FILE_SAVE_STATE:19.210 + result = dreamcast_load_state( filename );19.211 + break;19.212 + case FILE_ZIP:19.213 + SET_ERROR( err, LX_ERR_FILE_UNSUP, "ZIP/SBI not currently supported" );19.214 result = FALSE;19.215 - } else if( memcmp( buf, DREAMCAST_SAVE_MAGIC, 16 ) == 0 ) {19.216 - /* Save state */19.217 - result = (dreamcast_load_state( filename )==0);19.218 - } else if( buf[0] == 0x7F && buf[1] == 'E' &&19.219 - buf[2] == 'L' && buf[3] == 'F' ) {19.220 - /* ELF binary */19.221 - lseek( fd, 0, SEEK_SET );19.222 - result = file_load_elf_fd( filename, fd );19.223 - } else {19.224 + break;19.225 + case FILE_ISO:19.226 + SET_ERROR( err, LX_ERR_FILE_UNSUP, "ISO files are not currently supported" );19.227 result = FALSE;19.228 + break;19.229 + default:19.230 + SET_ERROR( err, LX_ERR_FILE_UNKNOWN, "File '%s' could not be recognized", filename );19.231 + result = FALSE;19.232 + break;19.233 }19.234 close(fd);19.235 - return result;19.236 + if( result ) {19.237 + CLEAR_ERROR(err);19.238 + return type;19.239 + }19.240 + return FILE_ERROR;19.241 }19.243 void file_load_postload( const gchar *filename, int pc )19.244 @@ -156,18 +227,7 @@19.245 }19.248 -gboolean file_load_binary( const gchar *filename )19.249 -{19.250 - /* Load the binary itself */19.251 - if( mem_load_block( filename, BINARY_LOAD_ADDR, -1 ) == 0 ) {19.252 - file_load_postload( filename, BINARY_LOAD_ADDR );19.253 - return TRUE;19.254 - } else {19.255 - return FALSE;19.256 - }19.257 -}19.258 -19.259 -gboolean is_sh4_elf( Elf32_Ehdr *head )19.260 +static gboolean is_sh4_elf( Elf32_Ehdr *head )19.261 {19.262 return ( head->e_ident[EI_CLASS] == ELFCLASS32 &&19.263 head->e_ident[EI_DATA] == ELFDATA2LSB &&19.264 @@ -177,7 +237,7 @@19.265 head->e_version == 1 );19.266 }19.268 -gboolean is_arm_elf( Elf32_Ehdr *head )19.269 +static gboolean is_arm_elf( Elf32_Ehdr *head )19.270 {19.271 return ( head->e_ident[EI_CLASS] == ELFCLASS32 &&19.272 head->e_ident[EI_DATA] == ELFDATA2LSB &&19.273 @@ -187,7 +247,7 @@19.274 head->e_version == 1 );19.275 }19.277 -gboolean file_load_elf_fd( const gchar *filename, int fd )19.278 +static gboolean file_load_elf( const gchar *filename, int fd, ERROR *err )19.279 {19.280 Elf32_Ehdr head;19.281 Elf32_Phdr phdr;19.282 @@ -196,7 +256,7 @@19.283 if( read( fd, &head, sizeof(head) ) != sizeof(head) )19.284 return FALSE;19.285 if( !is_sh4_elf(&head) ) {19.286 - ERROR( "File is not an SH4 ELF executable file" );19.287 + SET_ERROR( err, LX_ERR_FILE_INVALID, "File is not an SH4 ELF executable file" );19.288 return FALSE;19.289 }19.291 @@ -211,7 +271,6 @@19.292 if( phdr.p_memsz > phdr.p_filesz ) {19.293 memset( target + phdr.p_filesz, 0, phdr.p_memsz - phdr.p_filesz );19.294 }19.295 - INFO( "Loaded %d bytes to %08X", phdr.p_filesz, phdr.p_vaddr );19.296 }19.297 }19.299 @@ -219,6 +278,30 @@19.300 return TRUE;19.301 }19.303 +static gboolean file_load_binary( const gchar *filename, int fd, ERROR *err )19.304 +{19.305 + struct stat st;19.306 +19.307 + if( fstat( fd, &st ) == -1 ) {19.308 + SET_ERROR( err, LX_ERR_FILE_IOERROR, "Error reading binary file '%s' (%s)", filename, strerror(errno) );19.309 + return FALSE;19.310 + }19.311 +19.312 + if( st.st_size > BINARY_MAX_SIZE ) {19.313 + SET_ERROR( err, LX_ERR_FILE_INVALID, "Binary file '%s' is too large to fit in memory", filename );19.314 + return FALSE;19.315 + }19.316 +19.317 + sh4ptr_t target = mem_get_region( BINARY_LOAD_ADDR );19.318 + if( read( fd, target, st.st_size ) != st.st_size ) {19.319 + SET_ERROR( err, LX_ERR_FILE_IOERROR, "Error reading binary file '%s' (%s)", filename, strerror(errno) );19.320 + return FALSE;19.321 + }19.322 +19.323 + file_load_postload( filename, BINARY_LOAD_ADDR );19.324 + return TRUE;19.325 +}19.326 +19.327 /**19.328 * Create a new CDROM disc containing a single 1ST_READ.BIN.19.329 * @param type The disc type - must be CDROM_DISC_GDROM or CDROM_DISC_XA19.330 @@ -233,25 +316,25 @@19.331 cdrom_lba_t start_lba = 45000; /* GDROM_START */19.332 char bootstrap[32768];19.334 - /* 1. Load in the bootstrap */19.335 + /* 1. Load in the bootstrap: Note failures here are considered configuration errors */19.336 gchar *bootstrap_file = lxdream_get_global_config_path_value(CONFIG_BOOTSTRAP);19.337 if( bootstrap_file == NULL || bootstrap_file[0] == '\0' ) {19.338 g_free(data);19.339 - SET_ERROR( err, ENOENT, "Unable to create CD image: bootstrap file is not configured" );19.340 + SET_ERROR( err, LX_ERR_CONFIG, "Unable to create CD image: bootstrap file is not configured" );19.341 return NULL;19.342 }19.344 FILE *f = fopen( bootstrap_file, "ro" );19.345 if( f == NULL ) {19.346 g_free(data);19.347 - SET_ERROR( err, errno, "Unable to create CD image: bootstrap file '%s' could not be opened", bootstrap_file );19.348 + SET_ERROR( err, LX_ERR_CONFIG, "Unable to create CD image: bootstrap file '%s' could not be opened", bootstrap_file );19.349 return FALSE;19.350 }19.351 size_t len = fread( bootstrap, 1, 32768, f );19.352 fclose(f);19.353 if( len != 32768 ) {19.354 g_free(data);19.355 - SET_ERROR( err, EINVAL, "Unable to create CD image: bootstrap file '%s' is invalid", bootstrap_file );19.356 + SET_ERROR( err, LX_ERR_CONFIG, "Unable to create CD image: bootstrap file '%s' is invalid", bootstrap_file );19.357 return FALSE;19.358 }19.360 @@ -280,6 +363,7 @@19.361 int status = iso_image_new("autocd", &iso);19.362 if( status != 1 ) {19.363 g_free(data);19.364 + SET_ERROR( err, LX_ERR_NOMEM, "Unable to create CD image: out of memory" );19.365 return NULL;19.366 }19.368 @@ -287,6 +371,7 @@19.369 if( iso_memory_stream_new(data, bin_size, &stream) != 1 ) {19.370 g_free(data);19.371 iso_image_unref(iso);19.372 + SET_ERROR( err, LX_ERR_NOMEM, "Unable to create CD image: out of memory" );19.373 return NULL;19.374 }19.375 iso_tree_add_new_file(iso_image_get_root(iso), "1ST_READ.BIN", stream, NULL);19.376 @@ -297,15 +382,15 @@19.377 return NULL;19.378 }19.380 - cdrom_disc_t disc = cdrom_disc_new_from_track( type, track, start_lba );19.381 + cdrom_disc_t disc = cdrom_disc_new_from_track( type, track, start_lba, err );19.382 iso_image_unref(iso);19.383 if( disc != NULL ) {19.384 disc->name = g_strdup(filename);19.385 - }19.386 + }19.387 return disc;19.388 }19.390 -cdrom_disc_t cdrom_wrap_elf_fd( cdrom_disc_type_t type, const gchar *filename, int fd, ERROR *err )19.391 +static cdrom_disc_t cdrom_wrap_elf( cdrom_disc_type_t type, const gchar *filename, int fd, ERROR *err )19.392 {19.393 Elf32_Ehdr head;19.394 int i;19.395 @@ -313,12 +398,13 @@19.396 /* Check the file header is actually an SH4 binary */19.397 if( read( fd, &head, sizeof(head) ) != sizeof(head) )19.398 return FALSE;19.399 +19.400 if( !is_sh4_elf(&head) ) {19.401 - SET_ERROR( err, EINVAL, "File is not an SH4 ELF executable file" );19.402 + SET_ERROR( err, LX_ERR_FILE_INVALID, "File is not an SH4 ELF executable file" );19.403 return FALSE;19.404 }19.405 if( head.e_entry != BINARY_LOAD_ADDR ) {19.406 - SET_ERROR( err, EINVAL, "SH4 Binary has incorrect entry point (should be %08X but is %08X)", BINARY_LOAD_ADDR, head.e_entry );19.407 + SET_ERROR( err, LX_ERR_FILE_INVALID, "SH4 Binary has incorrect entry point (should be %08X but is %08X)", BINARY_LOAD_ADDR, head.e_entry );19.408 return FALSE;19.409 }19.411 @@ -326,7 +412,7 @@19.412 Elf32_Phdr phdr[head.e_phnum];19.413 lseek( fd, head.e_phoff, SEEK_SET );19.414 if( read( fd, phdr, sizeof(phdr) ) != sizeof(phdr) ) {19.415 - SET_ERROR( err, EINVAL, "File is not a valid executable file" );19.416 + SET_ERROR( err, LX_ERR_FILE_INVALID, "File is not a valid executable file" );19.417 return FALSE;19.418 }19.420 @@ -342,11 +428,11 @@19.421 }19.423 if( start != BINARY_LOAD_ADDR ) {19.424 - SET_ERROR( err, EINVAL, "SH4 Binary has incorrect load address (should be %08X but is %08X)", BINARY_LOAD_ADDR, start );19.425 + SET_ERROR( err, LX_ERR_FILE_INVALID, "SH4 Binary has incorrect load address (should be %08X but is %08X)", BINARY_LOAD_ADDR, start );19.426 return FALSE;19.427 }19.428 if( end >= 0x8D000000 ) {19.429 - SET_ERROR( err, EINVAL, "SH4 binary is too large to fit in memory (end address is %08X)", end );19.430 + SET_ERROR( err, LX_ERR_FILE_INVALID, "SH4 binary is too large to fit in memory (end address is %08X)", end );19.431 return FALSE;19.432 }19.434 @@ -356,7 +442,12 @@19.435 if( phdr[i].p_type == PT_LOAD ) {19.436 lseek( fd, phdr[i].p_offset, SEEK_SET );19.437 uint32_t size = MIN( phdr[i].p_filesz, phdr[i].p_memsz);19.438 - read( fd, program + phdr[i].p_vaddr, size );19.439 + int status = read( fd, program + phdr[i].p_vaddr, size );19.440 + if( status == -1 ) {19.441 + SET_ERROR( err, LX_ERR_FILE_IOERROR, "I/O error reading SH4 binary %s (%s)", filename, strerror(errno) );19.442 + } else if( status != size ) {19.443 + SET_ERROR( err, LX_ERR_FILE_IOERROR, "SH4 binary %s is corrupt", filename );19.444 + }19.445 }19.446 }19.448 @@ -364,39 +455,52 @@19.449 return cdrom_disc_new_wrapped_binary(type, filename, program, end-start, err );19.450 }19.452 -cdrom_disc_t cdrom_wrap_magic( cdrom_disc_type_t type, const gchar *filename, ERROR *err )19.453 +static cdrom_disc_t cdrom_wrap_binary( cdrom_disc_type_t type, const gchar *filename, int fd, ERROR *err )19.454 {19.455 - cdrom_disc_t disc;19.456 + struct stat st;19.457 char *data;19.458 - int len;19.459 - struct stat st;19.460 - int fd = open( filename, O_RDONLY );19.461 - if( fd == -1 ) {19.462 - SET_ERROR( err, errno, "Unable to open file '%s'", filename );19.463 + size_t len;19.464 +19.465 + if( fstat(fd, &st) == -1 ) {19.466 + SET_ERROR( err, LX_ERR_FILE_IOERROR, "Error reading binary file '%s' (%s)", filename, strerror(errno) );19.467 return NULL;19.468 }19.470 -19.471 - lxdream_file_type_t filetype = file_magic( filename, fd, err );19.472 - switch( filetype ) {19.473 - case FILE_BINARY:19.474 - fstat( fd, &st );19.475 - data = g_malloc(st.st_size);19.476 - len = read( fd, data, st.st_size );19.477 - close(fd);19.478 - if( len != st.st_size ) {19.479 - SET_ERROR( err, errno, "Error reading binary file '%s'", filename );19.480 - return NULL;19.481 - }19.482 - return cdrom_disc_new_wrapped_binary( type, filename, data, st.st_size, err );19.483 - case FILE_ELF:19.484 - disc = cdrom_wrap_elf_fd(type, filename, fd, err);19.485 - close(fd);19.486 - return disc;19.487 - default:19.488 - close(fd);19.489 - SET_ERROR( err, EINVAL, "File '%s' cannot be wrapped (not a binary)", filename );19.490 + data = g_malloc(st.st_size);19.491 + len = read( fd, data, st.st_size );19.492 + if( len != st.st_size ) {19.493 + SET_ERROR( err, LX_ERR_FILE_IOERROR, "Error reading binary file '%s' (%s)", filename, strerror(errno) );19.494 + free(data);19.495 return NULL;19.496 }19.498 + return cdrom_disc_new_wrapped_binary( type, filename, data, st.st_size, err );19.499 }19.500 +19.501 +cdrom_disc_t cdrom_wrap_magic( cdrom_disc_type_t type, const gchar *filename, ERROR *err )19.502 +{19.503 + cdrom_disc_t disc = NULL;19.504 +19.505 + int fd = open( filename, O_RDONLY );19.506 + if( fd == -1 ) {19.507 + SET_ERROR( err, LX_ERR_FILE_NOOPEN, "Unable to open file '%s'", filename );19.508 + return NULL;19.509 + }19.510 +19.511 + lxdream_file_type_t filetype = file_identify( filename, fd, err );19.512 + switch( filetype ) {19.513 + case FILE_ELF:19.514 + disc = cdrom_wrap_elf(type, filename, fd, err);19.515 + break;19.516 + case FILE_BINARY:19.517 + disc = cdrom_wrap_binary(type, filename, fd, err);19.518 + break;19.519 + default:19.520 + SET_ERROR( err, LX_ERR_FILE_UNKNOWN, "File '%s' cannot be wrapped (not a recognized binary)", filename );19.521 + break;19.522 + }19.523 +19.524 + close(fd);19.525 + return disc;19.526 +19.527 +}
20.1 --- a/src/loader.h Fri Jun 04 09:13:40 2010 +100020.2 +++ b/src/loader.h Thu Jun 10 22:13:16 2010 +100020.3 @@ -34,37 +34,37 @@20.4 */20.5 extern char *file_loader_extensions[][2];20.7 -/**20.8 - * Load the CD bootstrap, aka IP.BIN. Identified by "SEGA SEGAKATANA" at20.9 - * start of file. IP.BIN is loaded as-is at 8C008000.20.10 - * This is mainly for testing as it's unlikely anyone would want to do this20.11 - * for any other reason.20.12 - * @return TRUE on success, otherwise FALSE and errno20.13 - */20.14 -gboolean file_load_bootstrap( const gchar *filename );20.15 +typedef enum {20.16 + FILE_ERROR,20.17 + FILE_BINARY,20.18 + FILE_ELF,20.19 + FILE_ISO,20.20 + FILE_DISC,20.21 + FILE_ZIP,20.22 + FILE_SAVE_STATE,20.23 + FILE_UNKNOWN,20.24 +} lxdream_file_type_t;20.26 /**20.27 - * Load a miscellaneous .bin file, as commonly used in demos. No magic20.28 - * applies, file is loaded as is at 8C01000020.29 + * Attempt to identify the given file as one of the above file types20.30 */20.31 -gboolean file_load_binary( const gchar *filename );20.32 +lxdream_file_type_t file_identify( const gchar *filename, int fd, ERROR *err );20.34 /**20.35 - * Load a "Self Boot Inducer" .sbi file, also commonly used to package20.36 - * demos. (Actually a ZIP file with a predefined structure20.37 + * Load any supported file, and return the type of file loaded.20.38 + * If the file is a disc, the disc is mounted.20.39 + *20.40 + * @param filename The file to load20.41 + * @param wrap_exec If true, load executables as disc images. Otherwise load20.42 + * directly into RAM20.43 + * @param err Updated with error message on failure.20.44 */20.45 -gboolean file_load_sbi( const gchar *filename );20.46 +lxdream_file_type_t file_load_magic( const gchar *filename, gboolean wrap_exec, ERROR *err );20.48 /**20.49 - * Load an ELF executable binary file. Origin is file-dependent.20.50 + * Load an ELF or .bin executable file based on magic.20.51 */20.52 -gboolean file_load_elf( const gchar *filename );20.53 -20.54 -/**20.55 - * Load any of the above file types, using the appropriate magic to determine20.56 - * which is actually applicable20.57 - */20.58 -gboolean file_load_magic( const gchar *filename );20.59 +gboolean file_load_exec( const gchar *filename, ERROR *err );20.61 cdrom_disc_t cdrom_wrap_magic( cdrom_disc_type_t type, const gchar *filename, ERROR *err );
21.1 --- a/src/lxdream.h Fri Jun 04 09:13:40 2010 +100021.2 +++ b/src/lxdream.h Thu Jun 10 22:13:16 2010 +100021.3 @@ -94,8 +94,19 @@21.4 char msg[MAX_ERROR_MSG_SIZE];21.5 } ERROR;21.7 +#define LX_ERR_NONE 021.8 +#define LX_ERR_NOMEM 1 /* Out-of-memory */21.9 +#define LX_ERR_CONFIG 2 /* Configuration problem */21.10 +#define LX_ERR_UNHANDLED 3 /* A lower-level error occurred which we don't understand */21.11 +#define LX_ERR_BUG 421.12 +#define LX_ERR_FILE_NOOPEN 9 /* File could not be opened (ENOENT or EACCESS usually) */21.13 +#define LX_ERR_FILE_IOERROR 10 /* I/O error encountered in file */21.14 +#define LX_ERR_FILE_INVALID 11 /* File contents are invalid for its type */21.15 +#define LX_ERR_FILE_UNKNOWN 12 /* File type is unrecognized */21.16 +#define LX_ERR_FILE_UNSUP 13 /* File type is unsupported */21.17 +21.18 #define SET_ERROR(err, n, ...) if( (err) != NULL ) { (err)->code = n; snprintf( (err)->msg, sizeof((err)->msg), __VA_ARGS__ ); }21.19 -#define CLEAR_ERROR(err) do { err.code = 0; err.msg[0] = 0; } while(0)21.20 +#define CLEAR_ERROR(err) do { (err)->code = 0; (err)->msg[0] = 0; } while(0)21.23 #ifdef HAVE_FASTCALL
22.1 --- a/src/main.c Fri Jun 04 09:13:40 2010 +100022.2 +++ b/src/main.c Thu Jun 10 22:13:16 2010 +100022.3 @@ -42,13 +42,14 @@22.4 #include "hotkeys.h"22.5 #include "plugin.h"22.7 -char *option_list = "a:A:bc:dfg:G:hHl:m:npt:T:uvV:w:x?";22.8 +char *option_list = "a:A:bc:e:dfg:G:hHl:m:npt:T:uvV:x?";22.9 struct option longopts[] = {22.10 { "aica", required_argument, NULL, 'a' },22.11 { "audio", required_argument, NULL, 'A' },22.12 { "biosless", no_argument, NULL, 'b' },22.13 { "config", required_argument, NULL, 'c' },22.14 { "debugger", no_argument, NULL, 'd' },22.15 + { "execute", required_argument, NULL, 'e' },22.16 { "fullscreen", no_argument, NULL, 'f' },22.17 { "gdb-sh4", required_argument, NULL, 'g' },22.18 { "gdb-arm", required_argument, NULL, 'G' },22.19 @@ -61,7 +62,6 @@22.20 { "unsafe", no_argument, NULL, 'u' },22.21 { "video", no_argument, NULL, 'V' },22.22 { "version", no_argument, NULL, 'v' },22.23 - { "wrap", required_argument, NULL, 'w' },22.24 { NULL, 0, 0, 0 } };22.25 char *aica_program = NULL;22.26 char *display_driver_name = NULL;22.27 @@ -86,13 +86,14 @@22.28 static void print_usage()22.29 {22.30 print_version();22.31 - printf( "Usage: lxdream %s [options] [disc-file] [program-file]\n\n", lxdream_full_version );22.32 + printf( "Usage: lxdream %s [options] [disc-file] [save-state]\n\n", lxdream_full_version );22.34 printf( "Options:\n" );22.35 printf( " -a, --aica=PROGFILE %s\n", _("Run the AICA SPU only, with the supplied program") );22.36 printf( " -A, --audio=DRIVER %s\n", _("Use the specified audio driver (? to list)") );22.37 printf( " -b, --biosless %s\n", _("Run without the BIOS boot rom even if available") );22.38 printf( " -c, --config=CONFFILE %s\n", _("Load configuration from CONFFILE") );22.39 + printf( " -e, --execute=PROGRAM %s\n", _("Load and execute the given SH4 program") );22.40 printf( " -d, --debugger %s\n", _("Start in debugger mode") );22.41 printf( " -f, --fullscreen %s\n", _("Start in fullscreen mode") );22.42 printf( " -g, --gdb-sh4=PORT %s\n", _("Start GDB remote server on PORT for SH4") );22.43 @@ -108,7 +109,6 @@22.44 printf( " -u, --unsafe %s\n", _("Allow unsafe dcload syscalls") );22.45 printf( " -v, --version %s\n", _("Print the lxdream version string") );22.46 printf( " -V, --video=DRIVER %s\n", _("Use the specified video driver (? to list)") );22.47 - printf( " -w, --wrap=FILENAME %s\n", _("Wrap the specified binary file in a disc image") );22.48 printf( " -x %s\n", _("Disable the SH4 translator") );22.49 }22.51 @@ -124,9 +124,9 @@22.52 {22.53 int opt;22.54 double t;22.55 - gboolean display_ok;22.56 + gboolean display_ok, have_disc = FALSE, have_save = FALSE, have_exec = FALSE;22.57 uint32_t time_secs, time_nanos;22.58 - const char *wrap_name = NULL;22.59 + const char *exec_name = NULL;22.61 install_crash_handler();22.62 bind_gettext_domain();22.63 @@ -148,6 +148,9 @@22.64 case 'd': /* Launch w/ debugger */22.65 show_debugger = TRUE;22.66 break;22.67 + case 'e':22.68 + exec_name = optarg;22.69 + break;22.70 case 'f':22.71 show_fullscreen = TRUE;22.72 break;22.73 @@ -203,9 +206,6 @@22.74 case 'V': /* Video driver */22.75 display_driver_name = optarg;22.76 break;22.77 - case 'w': /* Wrap image file */22.78 - wrap_name = optarg;22.79 - break;22.80 case 'x': /* Disable translator */22.81 use_xlat = FALSE;22.82 break;22.83 @@ -268,37 +268,52 @@22.84 maple_reattach_all();22.85 INFO( "%s! ready...", APP_NAME );22.87 - if( wrap_name != NULL ) {22.88 + for( ; optind < argc; optind++ ) {22.89 ERROR err;22.90 - cdrom_disc_t disc = cdrom_wrap_magic( CDROM_DISC_XA, wrap_name, &err );22.91 - if( disc == NULL )22.92 - ERROR(err.msg);22.93 - else {22.94 - gdrom_mount_disc(disc);22.95 - if( !no_start ) {22.96 - start_immediately = TRUE;22.97 + lxdream_file_type_t type = file_identify(argv[optind], -1, &err);22.98 + if( type == FILE_SAVE_STATE ) {22.99 + if( have_save ) {22.100 + ERROR( "Multiple save states given on command-line, ignoring %s", argv[optind] );22.101 + } else {22.102 + have_save = dreamcast_load_state(argv[optind]);22.103 + if( !have_save )22.104 + no_start = TRUE;22.105 + }22.106 + } else {22.107 + if( have_disc ) {22.108 + ERROR( "Multiple GD-ROM discs given on command-line, ignoring %s", argv[optind] );22.109 + } else {22.110 + have_disc = gdrom_mount_image(argv[optind], &err);22.111 + if( !have_disc )22.112 + no_start = TRUE;22.113 }22.114 }22.115 }22.117 - for( ; optind < argc; optind++ ) {22.118 - gboolean ok = gdrom_mount_image(argv[optind]);22.119 - if( !ok ) {22.120 - ok = file_load_magic( argv[optind] );22.121 - }22.122 - if( !ok ) {22.123 - ERROR( "Unrecognized file '%s'", argv[optind] );22.124 - }22.125 - if( !no_start ) {22.126 - start_immediately = ok;22.127 + if( exec_name != NULL ) {22.128 + ERROR err;22.129 + if( have_save ) {22.130 + ERROR( "Both a save state and an executable were specified, ignoring %s", exec_name );22.131 + } else {22.132 + have_exec = file_load_exec( exec_name, &err );22.133 + if( !have_exec )22.134 + no_start = TRUE;22.135 }22.136 }22.138 + if( !no_start && (have_exec || have_disc || have_save) ) {22.139 + start_immediately = TRUE;22.140 + }22.141 +22.142 if( gdrom_get_current_disc() == NULL ) {22.143 + ERROR err;22.144 gchar *disc_file = lxdream_get_global_config_path_value( CONFIG_GDROM );22.145 if( disc_file != NULL ) {22.146 - gdrom_mount_image( disc_file );22.147 + gboolean ok = gdrom_mount_image( disc_file, &err );22.148 g_free(disc_file);22.149 + if( !ok ) {22.150 + WARN( err.msg );22.151 + }22.152 }22.153 }
23.1 --- a/test/Makefile.in Fri Jun 04 09:13:40 2010 +100023.2 +++ b/test/Makefile.in Thu Jun 10 22:13:16 2010 +100023.3 @@ -30,8 +30,8 @@23.4 ARMLIBS = -Wl,--start-group -lc -lgcc -lm -Wl,--end-group23.5 ARMOBJCOPY = @ARMOBJCOPY@ -O binary23.7 -RUNTEST = ../src/lxdream -c $(srcdir)/lxdream.rc -puH -A null23.8 -RUNTESTX = ../src/lxdream -c $(srcdir)/lxdream.rc -xpuH -A null23.9 +RUNTEST = ../src/lxdream -c $(srcdir)/lxdream.rc -puH -A null -e23.10 +RUNTESTX = ../src/lxdream -c $(srcdir)/lxdream.rc -xpuH -A null -e23.12 BUILD_SYSTEST_FALSE = @BUILD_SYSTEST_FALSE@23.13 BUILD_SYSTEST_TRUE = @BUILD_SYSTEST_TRUE@
.