Search
lxdream.org :: lxdream :: r1109:700c5ab26a63
lxdream 0.9.1
released Jun 29
Download Now
changeset1109:700c5ab26a63
parent1108:305ef2082079
child1110:eb1c005ba3cb
authornkeynes
dateThu 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
src/bootstrap.h
src/cocoaui/cocoaui.m
src/dreamcast.c
src/drivers/cdrom/cd_cdi.c
src/drivers/cdrom/cd_gdi.c
src/drivers/cdrom/cd_linux.c
src/drivers/cdrom/cd_nrg.c
src/drivers/cdrom/cd_osx.c
src/drivers/cdrom/cdrom.c
src/drivers/cdrom/cdrom.h
src/drivers/cdrom/isofs.c
src/gdlist.c
src/gdlist.h
src/gdrom/gdrom.c
src/gdrom/gdrom.h
src/gtkui/gtk_gd.c
src/gtkui/gtkcb.c
src/gtkui/gtkui.h
src/loader.c
src/loader.h
src/lxdream.h
src/main.c
test/Makefile.in
1.1 --- a/src/bootstrap.h Fri Jun 04 09:13:40 2010 +1000
1.2 +++ b/src/bootstrap.h Thu Jun 10 22:13:16 2010 +1000
1.3 @@ -35,6 +35,7 @@
1.4 #define BOOTSTRAP_MAGIC_SIZE 32
1.5
1.6 #define BINARY_LOAD_ADDR 0x8C010000
1.7 +#define BINARY_MAX_SIZE (0x8D000000 - BINARY_LOAD_ADDR)
1.8
1.9 /**
1.10 * Bootstrap header structure
2.1 --- a/src/cocoaui/cocoaui.m Fri Jun 04 09:13:40 2010 +1000
2.2 +++ b/src/cocoaui/cocoaui.m Thu Jun 10 22:13:16 2010 +1000
2.3 @@ -216,7 +216,8 @@
2.4 - (BOOL)application: (NSApplication *)app openFile: (NSString *)filename
2.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 event
2.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)sender
2.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)sender
2.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)sender
2.53 {
3.1 --- a/src/dreamcast.c Fri Jun 04 09:13:40 2010 +1000
3.2 +++ b/src/dreamcast.c Thu Jun 10 22:13:16 2010 +1000
3.3 @@ -448,7 +448,7 @@
3.4 return NULL;
3.5 }
3.6
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.14
3.15 FILE *f = fopen( filename, "r" );
3.16 - if( f == NULL ) return errno;
3.17 + if( f == NULL ) return FALSE;
3.18
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.26
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.35
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.59
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.67
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 +1000
4.2 +++ b/src/drivers/cdrom/cd_cdi.c Thu Jun 10 22:13:16 2010 +1000
4.3 @@ -73,7 +73,7 @@
4.4 trail.cdi_version == CDI_V35_ID;
4.5 }
4.6
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.9
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 +1000
5.2 +++ b/src/drivers/cdrom/cd_gdi.c Thu Jun 10 22:13:16 2010 +1000
5.3 @@ -64,12 +64,12 @@
5.4 fseek(f, 0, SEEK_SET);
5.5
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.17
5.18 @@ -83,7 +83,7 @@
5.19
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 +1000
6.2 +++ b/src/drivers/cdrom/cd_linux.c Thu Jun 10 22:13:16 2010 +1000
6.3 @@ -103,12 +103,12 @@
6.4
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 +1000
7.2 +++ b/src/drivers/cdrom/cd_nrg.c Thu Jun 10 22:13:16 2010 +1000
7.3 @@ -150,7 +150,7 @@
7.4 }
7.5 }
7.6
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.9
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 +1000
8.2 +++ b/src/drivers/cdrom/cd_osx.c Thu Jun 10 22:13:16 2010 +1000
8.3 @@ -81,7 +81,7 @@
8.4
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 +1000
9.2 +++ b/src/drivers/cdrom/cdrom.c Thu Jun 10 22:13:16 2010 +1000
9.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 +1000
10.2 +++ b/src/drivers/cdrom/cdrom.h Thu Jun 10 22:13:16 2010 +1000
10.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.9
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 +1000
11.2 +++ b/src/drivers/cdrom/isofs.c Thu Jun 10 22:13:16 2010 +1000
11.3 @@ -60,6 +60,24 @@
11.4 return src;
11.5 }
11.6
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.29
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.35
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.46
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 }
11.63
12.1 --- a/src/gdlist.c Fri Jun 04 09:13:40 2010 +1000
12.2 +++ b/src/gdlist.c Thu Jun 10 22:13:16 2010 +1000
12.3 @@ -147,7 +147,7 @@
12.4 CALL_HOOKS( gdrom_list_change_hook, TRUE, gdrom_list_get_selection() );
12.5 }
12.6
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.13
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.19
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.26
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 }
12.31
13.1 --- a/src/gdlist.h Fri Jun 04 09:13:40 2010 +1000
13.2 +++ b/src/gdlist.h Thu Jun 10 22:13:16 2010 +1000
13.3 @@ -20,6 +20,7 @@
13.4 #ifndef lxdream_gdlist_H
13.5 #define lxdream_gdlist_H 1
13.6
13.7 +#include <stdio.h>
13.8 #include "hook.h"
13.9
13.10 #ifdef __cplusplus
13.11 @@ -64,9 +65,10 @@
13.12 /**
13.13 * Change the current gdrom selection to the selected index. This will mount the
13.14 * appropriate drive/image where necessary.
13.15 + * @param err Updated if there was an error loading the selected gdrom
13.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.20
13.21 #ifdef __cplusplus
13.22 }
14.1 --- a/src/gdrom/gdrom.c Fri Jun 04 09:13:40 2010 +1000
14.2 +++ b/src/gdrom/gdrom.c Thu Jun 10 22:13:16 2010 +1000
14.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.9
14.10 #define GDROM_LBA_OFFSET 150
14.11 @@ -58,9 +59,12 @@
14.12 }
14.13 }
14.14
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 +1000
15.2 +++ b/src/gdrom/gdrom.h Thu Jun 10 22:13:16 2010 +1000
15.3 @@ -53,7 +53,7 @@
15.4 * Shortcut to open and mount an image file
15.5 * @return true on success
15.6 */
15.7 -gboolean gdrom_mount_image( const gchar *filename );
15.8 +gboolean gdrom_mount_image( const gchar *filename, ERROR *err );
15.9
15.10 void gdrom_mount_disc( cdrom_disc_t disc );
15.11
16.1 --- a/src/gtkui/gtk_gd.c Fri Jun 04 09:13:40 2010 +1000
16.2 +++ b/src/gtkui/gtk_gd.c Thu Jun 10 22:13:16 2010 +1000
16.3 @@ -27,17 +27,31 @@
16.4
16.5 static gboolean gdrom_menu_adjusting = FALSE;
16.6
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.24
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 }
16.36
17.1 --- a/src/gtkui/gtkcb.c Fri Jun 04 09:13:40 2010 +1000
17.2 +++ b/src/gtkui/gtkcb.c Thu Jun 10 22:13:16 2010 +1000
17.3 @@ -129,7 +129,7 @@
17.4
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.15
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.31
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 +1000
18.2 +++ b/src/gtkui/gtkui.h Thu Jun 10 22:13:16 2010 +1000
18.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 +1000
19.2 +++ b/src/loader.c Thu Jun 10 22:13:16 2010 +1000
19.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.8
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.14
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.20
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.30
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.39
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.60
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.105
19.106
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.113
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.119
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.137
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.242
19.243 void file_load_postload( const gchar *filename, int pc )
19.244 @@ -156,18 +227,7 @@
19.245 }
19.246
19.247
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.267
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.276
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.290
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.298
19.299 @@ -219,6 +278,30 @@
19.300 return TRUE;
19.301 }
19.302
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_XA
19.330 @@ -233,25 +316,25 @@
19.331 cdrom_lba_t start_lba = 45000; /* GDROM_START */
19.332 char bootstrap[32768];
19.333
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.343
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.359
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.367
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.379
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.389
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.410
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.419
19.420 @@ -342,11 +428,11 @@
19.421 }
19.422
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.433
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.447
19.448 @@ -364,39 +455,52 @@
19.449 return cdrom_disc_new_wrapped_binary(type, filename, program, end-start, err );
19.450 }
19.451
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.469
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.497
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 +1000
20.2 +++ b/src/loader.h Thu Jun 10 22:13:16 2010 +1000
20.3 @@ -34,37 +34,37 @@
20.4 */
20.5 extern char *file_loader_extensions[][2];
20.6
20.7 -/**
20.8 - * Load the CD bootstrap, aka IP.BIN. Identified by "SEGA SEGAKATANA" at
20.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 this
20.11 - * for any other reason.
20.12 - * @return TRUE on success, otherwise FALSE and errno
20.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.25
20.26 /**
20.27 - * Load a miscellaneous .bin file, as commonly used in demos. No magic
20.28 - * applies, file is loaded as is at 8C010000
20.29 + * Attempt to identify the given file as one of the above file types
20.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.33
20.34 /**
20.35 - * Load a "Self Boot Inducer" .sbi file, also commonly used to package
20.36 - * demos. (Actually a ZIP file with a predefined structure
20.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 load
20.41 + * @param wrap_exec If true, load executables as disc images. Otherwise load
20.42 + * directly into RAM
20.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.47
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 determine
20.56 - * which is actually applicable
20.57 - */
20.58 -gboolean file_load_magic( const gchar *filename );
20.59 +gboolean file_load_exec( const gchar *filename, ERROR *err );
20.60
20.61 cdrom_disc_t cdrom_wrap_magic( cdrom_disc_type_t type, const gchar *filename, ERROR *err );
20.62
21.1 --- a/src/lxdream.h Fri Jun 04 09:13:40 2010 +1000
21.2 +++ b/src/lxdream.h Thu Jun 10 22:13:16 2010 +1000
21.3 @@ -94,8 +94,19 @@
21.4 char msg[MAX_ERROR_MSG_SIZE];
21.5 } ERROR;
21.6
21.7 +#define LX_ERR_NONE 0
21.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 4
21.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.21
21.22
21.23 #ifdef HAVE_FASTCALL
22.1 --- a/src/main.c Fri Jun 04 09:13:40 2010 +1000
22.2 +++ b/src/main.c Thu Jun 10 22:13:16 2010 +1000
22.3 @@ -42,13 +42,14 @@
22.4 #include "hotkeys.h"
22.5 #include "plugin.h"
22.6
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.33
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.50
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.60
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.86
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.116
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.137
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 }
22.154
23.1 --- a/test/Makefile.in Fri Jun 04 09:13:40 2010 +1000
23.2 +++ b/test/Makefile.in Thu Jun 10 22:13:16 2010 +1000
23.3 @@ -30,8 +30,8 @@
23.4 ARMLIBS = -Wl,--start-group -lc -lgcc -lm -Wl,--end-group
23.5 ARMOBJCOPY = @ARMOBJCOPY@ -O binary
23.6
23.7 -RUNTEST = ../src/lxdream -c $(srcdir)/lxdream.rc -puH -A null
23.8 -RUNTESTX = ../src/lxdream -c $(srcdir)/lxdream.rc -xpuH -A null
23.9 +RUNTEST = ../src/lxdream -c $(srcdir)/lxdream.rc -puH -A null -e
23.10 +RUNTESTX = ../src/lxdream -c $(srcdir)/lxdream.rc -xpuH -A null -e
23.11
23.12 BUILD_SYSTEST_FALSE = @BUILD_SYSTEST_FALSE@
23.13 BUILD_SYSTEST_TRUE = @BUILD_SYSTEST_TRUE@
.