<html>
<body>
  <div id="body" style="background-color:#ffffff;" >
<table cellspacing="0" cellpadding="0" border="0" rules="cols">
<tr class="head" style="border-bottom-width:1px;border-bottom-style:solid;" ><td class="headtd" style="padding:0;padding-top:.2em;" colspan="4">Commit in <b><tt>lxdream</tt></b></td></tr>
<tr><td><tt>src/<a href="#file1">bootstrap.h</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+1</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">305ef2082079 -> 700c5ab26a63</td></tr>
<tr class="alt" style=";" ><td><tt>src/cocoaui/<a href="#file2">cocoaui.m</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+17</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-4</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">305ef2082079 -> 700c5ab26a63</td></tr>
<tr><td><tt>src/<a href="#file3">dreamcast.c</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+8</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-8</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">305ef2082079 -> 700c5ab26a63</td></tr>
<tr class="alt" style=";" ><td><tt>src/drivers/cdrom/<a href="#file4">cd_cdi.c</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+1</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-1</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">305ef2082079 -> 700c5ab26a63</td></tr>
<tr><td><tt>                 /<a href="#file5">cd_gdi.c</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+7</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-6</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">305ef2082079 -> 700c5ab26a63</td></tr>
<tr class="alt" style=";" ><td><tt>                 /<a href="#file6">cd_linux.c</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+2</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-2</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">305ef2082079 -> 700c5ab26a63</td></tr>
<tr><td><tt>                 /<a href="#file7">cd_nrg.c</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+1</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-1</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">305ef2082079 -> 700c5ab26a63</td></tr>
<tr class="alt" style=";" ><td><tt>                 /<a href="#file8">cd_osx.c</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+1</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-1</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">305ef2082079 -> 700c5ab26a63</td></tr>
<tr><td><tt>                 /<a href="#file9">cdrom.c</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+7</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-5</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">305ef2082079 -> 700c5ab26a63</td></tr>
<tr class="alt" style=";" ><td><tt>                 /<a href="#file10">cdrom.h</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+1</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-1</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">305ef2082079 -> 700c5ab26a63</td></tr>
<tr><td><tt>                 /<a href="#file11">isofs.c</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+24</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-1</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">305ef2082079 -> 700c5ab26a63</td></tr>
<tr class="alt" style=";" ><td><tt>src/<a href="#file12">gdlist.c</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+5</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-3</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">305ef2082079 -> 700c5ab26a63</td></tr>
<tr><td><tt>   /<a href="#file13">gdlist.h</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+3</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-1</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">305ef2082079 -> 700c5ab26a63</td></tr>
<tr class="alt" style=";" ><td><tt>src/gdrom/<a href="#file14">gdrom.c</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+6</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-2</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">305ef2082079 -> 700c5ab26a63</td></tr>
<tr><td><tt>         /<a href="#file15">gdrom.h</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+1</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-1</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">305ef2082079 -> 700c5ab26a63</td></tr>
<tr class="alt" style=";" ><td><tt>src/gtkui/<a href="#file16">gtk_gd.c</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+16</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-2</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">305ef2082079 -> 700c5ab26a63</td></tr>
<tr><td><tt>         /<a href="#file17">gtkcb.c</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+12</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-2</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">305ef2082079 -> 700c5ab26a63</td></tr>
<tr class="alt" style=";" ><td><tt>         /<a href="#file18">gtkui.h</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+1</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">305ef2082079 -> 700c5ab26a63</td></tr>
<tr><td><tt>src/<a href="#file19">loader.c</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+221</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-117</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">305ef2082079 -> 700c5ab26a63</td></tr>
<tr class="alt" style=";" ><td><tt>   /<a href="#file20">loader.h</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+22</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-22</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">305ef2082079 -> 700c5ab26a63</td></tr>
<tr><td><tt>   /<a href="#file21">lxdream.h</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+12</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-1</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">305ef2082079 -> 700c5ab26a63</td></tr>
<tr class="alt" style=";" ><td><tt>   /<a href="#file22">main.c</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+43</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-28</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">305ef2082079 -> 700c5ab26a63</td></tr>
<tr><td><tt>test/<a href="#file23">Makefile.in</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+2</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-2</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">305ef2082079 -> 700c5ab26a63</td></tr>
<tr><td></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+414</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-211</td><td></td></tr>
</table>
<small id="info" style="color: #888888;" >23 modified files</small><br />
<pre class="comment" style="white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;padding:4px;border:1px dashed #000000;background-color:#ffffdd;" >
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
</pre>
<hr /><a name="file1" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>bootstrap.h</b></big> <small id="info" style="color: #888888;" >305ef2082079 -> 700c5ab26a63</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/bootstrap.h
+++ lxdream/src/bootstrap.h
@@ -35,6 +35,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #define BOOTSTRAP_MAGIC_SIZE 32
 
 #define BINARY_LOAD_ADDR 0x8C010000
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#define BINARY_MAX_SIZE (0x8D000000 - BINARY_LOAD_ADDR)
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 /**
  * Bootstrap header structure
</pre></div>
<hr /><a name="file2" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/cocoaui</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>cocoaui.m</b></big> <small id="info" style="color: #888888;" >305ef2082079 -> 700c5ab26a63</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/cocoaui/cocoaui.m
+++ lxdream/src/cocoaui/cocoaui.m
@@ -216,7 +216,8 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > - (BOOL)application: (NSApplication *)app openFile: (NSString *)filename
 {
     const gchar *cname = [filename UTF8String];
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    if( file_load_magic(cname) ) {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    ERROR err;
+    if( file_load_magic(cname, FALSE, &err) != FILE_ERROR ) {
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         // Queue up a run event
         gui_do_later(dreamcast_run);
         return YES;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -269,8 +270,12 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     int result = [panel runModalForDirectory: path file: nil types: nil];
     if( result == NSOKButton && [[panel filenames] count] > 0 ) {
         NSString *filename = [[panel filenames] objectAtIndex: 0];
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        file_load_magic( [filename UTF8String] );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        ERROR err;
+        gboolean ok = file_load_exec( [filename UTF8String], &err );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         set_gui_path(CONFIG_DEFAULT_PATH, [[panel directory] UTF8String]);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        if( !ok ) {
+            ERROR( err.msg );
+        }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 }
 - (void) mount_action: (id)sender
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -279,8 +284,12 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     NSString *path = [NSString stringWithCString: get_gui_path(CONFIG_DEFAULT_PATH)];
     int result = [panel runModalForDirectory: path file: nil types: nil];
     if( result == NSOKButton && [[panel filenames] count] > 0 ) {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        ERROR err;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         NSString *filename = [[panel filenames] objectAtIndex: 0];
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        gdrom_mount_image( [filename UTF8String] );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        gboolean ok = gdrom_mount_image( [filename UTF8String], &err );
+        if( !ok ) {
+            ERROR(err.msg);
+        }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         set_gui_path(CONFIG_DEFAULT_PATH, [[panel directory] UTF8String]);
     }
 }
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -301,7 +310,11 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 - (void) gdrom_list_action: (id)sender
 {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    gdrom_list_set_selection( [sender tag] );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    ERROR err;
+    gboolean ok = gdrom_list_set_selection( [sender tag], &err );
+    if( !ok ) {
+        ERROR( err.msg );
+    }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 - (void) fullscreen_action: (id)sender
 {
</pre></div>
<hr /><a name="file3" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>dreamcast.c</b></big> <small id="info" style="color: #888888;" >305ef2082079 -> 700c5ab26a63</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/dreamcast.c
+++ lxdream/src/dreamcast.c
@@ -448,7 +448,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     return NULL;
 }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-<span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >int</span> dreamcast_load_state( const gchar *filename )
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >gboolean</span> dreamcast_load_state( const gchar *filename )
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
     int i,j;
     int module_count;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -456,13 +456,13 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     int have_read[MAX_MODULES];
 
     FILE *f = fopen( filename, "r" );
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    if( f == NULL ) return <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >errno</span>;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( f == NULL ) return <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >FALSE</span>;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
     module_count = dreamcast_read_save_state_header(f, error, sizeof(error));
     if( module_count <= 0 ) {
        ERROR( error );
         fclose(f);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        return <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >1</span>;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        return <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >FALSE</span>;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 
     for( i=0; i<MAX_MODULES; i++ ) {
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -475,7 +475,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         if( strncmp(chunk.marker, "BLCK", 4) != 0 ) {
             ERROR( "%s save state is corrupted (missing block header %d)", APP_NAME, i );
             fclose(f);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-            return <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >2</span>;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+            return <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >FALSE</span>;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         }
 
         /* Find the matching module by name */
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -485,11 +485,11 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >                 if( modules[j]->load == NULL ) {
                     ERROR( "%s save state is corrupted (no loader for %s)", APP_NAME, modules[j]->name );
                     fclose(f);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-                    return <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >2</span>;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+                    return <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >FALSE</span>;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >                 } else if( modules[j]->load(f) != 0 ) {
                     ERROR( "%s save state is corrupted (%s failed)", APP_NAME, modules[j]->name );
                     fclose(f);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-                    return <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >2</span>;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+                    return <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >FALSE</span>;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >                 }
                 break;
             }
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -497,7 +497,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         if( j == num_modules ) {
             fclose(f);
             ERROR( "%s save state contains unrecognized section", APP_NAME );
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-            return <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >2</span>;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+            return <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >FALSE</span>;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         }
     }
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -512,7 +512,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
     fclose(f);
     INFO( "Save state read from %s", filename );
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    return <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >0</span>;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    return <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >TRUE</span>;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 
 int dreamcast_save_state( const gchar *filename )
</pre></div>
<hr /><a name="file4" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/drivers/cdrom</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>cd_cdi.c</b></big> <small id="info" style="color: #888888;" >305ef2082079 -> 700c5ab26a63</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/drivers/cdrom/cd_cdi.c
+++ lxdream/src/drivers/cdrom/cd_cdi.c
@@ -73,7 +73,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     trail.cdi_version == CDI_V35_ID;
 }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-#define RETURN_PARSE_ERROR( ... ) do { SET_ERROR(err, <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >EINVAL</span>, __VA_ARGS__); return FALSE; } while(0)
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#define RETURN_PARSE_ERROR( ... ) do { SET_ERROR(err, <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >LX_ERR_FILE_INVALID</span>, __VA_ARGS__); return FALSE; } while(0)
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 static gboolean cdi_image_read_toc( cdrom_disc_t disc, ERROR *err )
 {
</pre></div>
<hr /><a name="file5" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/drivers/cdrom</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>cd_gdi.c</b></big> <small id="info" style="color: #888888;" >305ef2082079 -> 700c5ab26a63</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/drivers/cdrom/cd_gdi.c
+++ lxdream/src/drivers/cdrom/cd_gdi.c
@@ -64,12 +64,12 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     fseek(f, 0, SEEK_SET);
 
     if( fgets( line, sizeof(line), f ) == NULL ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        SET_ERROR( err, <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >EINVAL</span>, "Invalid GDI image" );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        SET_ERROR( err, <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >LX_ERR_FILE_INVALID</span>, "Invalid GDI image" );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return FALSE;
     }
     track_count = strtoul(line, NULL, 0);
     if( track_count == 0 || track_count > 99 ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        SET_ERROR( err, <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >EINVAL</span>, "Invalid GDI image" );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        SET_ERROR( err, <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >LX_ERR_FILE_INVALID</span>, "Invalid GDI image" );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return FALSE;
     }
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -83,7 +83,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
         if( fgets( line, sizeof(line), f ) == NULL ) {
             cdrom_disc_unref(disc);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-            SET_ERROR( err, <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >EINVAL</span>, "Invalid GDI image - unexpected end of file" );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+            SET_ERROR( err, <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >LX_ERR_FILE_INVALID</span>, "Invalid GDI image - unexpected end of file" );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             return FALSE;
         }
         sscanf( line, "%d %d %d %d %s %d", &track_no, &start_lba, &flags, &size,
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -105,7 +105,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             case 2336: mode = SECTOR_SEMIRAW_MODE2; break;
             case 2352: mode = SECTOR_RAW_XA; break;
             default:
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-                SET_ERROR( err, <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >EINVAL</span>, "Invalid sector size '%d' in GDI track %d", size, (i+1) );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+                SET_ERROR( err, <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >LX_ERR_FILE_INVALID</span>, "Invalid sector size '%d' in GDI track %d", size, (i+1) );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >                 g_free(dirname);
                 return FALSE;
             }
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -115,7 +115,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             if( size == 0 )
                 size = 2352;
             else if( size != 2352 ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-                SET_ERROR( err, <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >EINVAL</span>, "Invalid sector size '%d' for audio track %d", size, (i+1) );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+                SET_ERROR( err, <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >LX_ERR_FILE_INVALID</span>, "Invalid sector size '%d' for audio track %d", size, (i+1) );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >                 g_free(dirname);
                 return FALSE;
             }
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -128,7 +128,8 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >                     offset, FILE_SECTOR_FULL_FILE );
             g_free(pathname);
             if( disc->track[i].source == NULL ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-                SET_ERROR( err, ENOENT, "GDI track file '%s' could not be opened (%s)", filename, strerror(errno) );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+                /* Note: status is invalid because it's a failure of the GDI file */
+                SET_ERROR( err, LX_ERR_FILE_INVALID, "GDI track file '%s' could not be opened (%s)", filename, strerror(errno) );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >                 g_free(dirname);
                 return FALSE;
             }
</pre></div>
<hr /><a name="file6" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/drivers/cdrom</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>cd_linux.c</b></big> <small id="info" style="color: #888888;" >305ef2082079 -> 700c5ab26a63</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/drivers/cdrom/cd_linux.c
+++ lxdream/src/drivers/cdrom/cd_linux.c
@@ -103,12 +103,12 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     
     int fd = open(drive->name, O_RDONLY|O_NONBLOCK);
     if( fd == -1 ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        SET_ERROR(err, <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >errno</span>, "Unable to open device '%s': %s", drive->name, strerror(errno) );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        SET_ERROR(err, <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >LX_ERR_FILE_NOOPEN</span>, "Unable to open device '%s': %s", drive->name, strerror(errno) );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return NULL;
     } else {
         FILE *f = fdopen(fd,"ro");
         if( !linux_is_cdrom_device(f) ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-            SET_ERROR(err, <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >EINVAL</span>, "Device '%s' is not a CDROM drive", drive->name );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+            SET_ERROR(err, <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >LX_ERR_FILE_UNKNOWN</span>, "Device '%s' is not a CDROM drive", drive->name );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             return NULL;
         }
         return cdrom_disc_scsi_new_file(f, drive->name, &linux_scsi_transport, err);
</pre></div>
<hr /><a name="file7" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/drivers/cdrom</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>cd_nrg.c</b></big> <small id="info" style="color: #888888;" >305ef2082079 -> 700c5ab26a63</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/drivers/cdrom/cd_nrg.c
+++ lxdream/src/drivers/cdrom/cd_nrg.c
@@ -150,7 +150,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-#define RETURN_PARSE_ERROR( ... ) do { SET_ERROR(err, <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >EINVAL</span>, __VA_ARGS__); return FALSE; } while(0)
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#define RETURN_PARSE_ERROR( ... ) do { SET_ERROR(err, <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >LX_ERR_FILE_INVALID</span>, __VA_ARGS__); return FALSE; } while(0)
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 static gboolean nrg_image_read_toc( cdrom_disc_t disc, ERROR *err )
 {
</pre></div>
<hr /><a name="file8" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/drivers/cdrom</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>cd_osx.c</b></big> <small id="info" style="color: #888888;" >305ef2082079 -> 700c5ab26a63</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/drivers/cdrom/cd_osx.c
+++ lxdream/src/drivers/cdrom/cd_osx.c
@@ -81,7 +81,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
     osx_cdrom_drive_t osx_drive = osx_cdrom_open_drive(drive->name);
     if( osx_drive == NULL ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        SET_ERROR( err, <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >ENOENT</span>, "Unable to open CDROM drive" );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        SET_ERROR( err, <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >LX_ERR_FILE_NOOPEN</span>, "Unable to open CDROM drive" );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return NULL;
     } else {
         return cdrom_osx_new( drive->name, osx_drive, err );
</pre></div>
<hr /><a name="file9" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/drivers/cdrom</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>cdrom.c</b></big> <small id="info" style="color: #888888;" >305ef2082079 -> 700c5ab26a63</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/drivers/cdrom/cdrom.c
+++ lxdream/src/drivers/cdrom/cdrom.c
@@ -116,7 +116,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     if( disc != NULL ) {
         cdrom_disc_init( disc, name );
     } else {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        SET_ERROR(err, <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >E</span>NOMEM, "Unable to allocate memory for cdrom disc");
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        SET_ERROR(err, <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >LX_ERR_</span>NOMEM, "Unable to allocate memory for cdrom disc");
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
     return disc;
 }
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -131,7 +131,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     if( disc != NULL && filename != NULL ) {
         disc->base_source = file_sector_source_new_filename( filename, SECTOR_UNKNOWN, 0, FILE_SECTOR_FULL_FILE );
         if( disc->base_source == NULL ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-            SET_ERROR( err, <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >errno</span>, "Unable to open cdrom file '%s': %s", filename, strerror(errno) );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+            SET_ERROR( err, <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >LX_ERR_FILE_NOOPEN</span>, "Unable to open cdrom file '%s': %s", filename, strerror(errno) );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             cdrom_disc_unref(disc);
             disc = NULL;
         } else {
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -272,7 +272,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     } else {
         /* No handler found for file */
         cdrom_disc_unref( disc );
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        SET_ERROR( err, EINVAL, "File '%s' could not be recognized as any known image file or device type" );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        SET_ERROR( err, LX_ERR_FILE_UNKNOWN, "File '%s' could not be recognized as any known image file or device type", filename );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return NULL;
     }
 }
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -284,7 +284,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  * @param lba The position on disc of the main track. If non-zero,
  * a filler track is added before it, in 2 separate sessions.
  */
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-cdrom_disc_t cdrom_disc_new_from_track( cdrom_disc_type_t type, sector_source_t track, cdrom_lba_t lba )
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+cdrom_disc_t cdrom_disc_new_from_track( cdrom_disc_type_t type, sector_source_t track, cdrom_lba_t lba<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >, ERROR *err</span> )
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
     cdrom_disc_t disc = cdrom_disc_new( NULL, NULL );
     if( disc != NULL ) {
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -312,6 +312,8 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         disc->track_count = trackno+1;
         disc->session_count = trackno+1;
         cdrom_disc_compute_leadout(disc);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    } else {
+        SET_ERROR(err, LX_ERR_NOMEM, "Unable to allocate memory for cdrom disc");
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
     return disc;
 }
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -325,7 +327,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     sector_mode_t mode = (type == CDROM_DISC_NONXA ? SECTOR_MODE1 : SECTOR_MODE2_FORM1 );
     sector_source_t source = iso_sector_source_new( iso, mode, lba, bootstrap, err );
     if( source != NULL ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        cdrom_disc_t disc = cdrom_disc_new_from_track(type, source, lba);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        cdrom_disc_t disc = cdrom_disc_new_from_track(type, source, lba<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >, err</span>);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         if( disc == NULL ) {
             sector_source_unref( source );
         } else {
</pre></div>
<hr /><a name="file10" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/drivers/cdrom</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>cdrom.h</b></big> <small id="info" style="color: #888888;" >305ef2082079 -> 700c5ab26a63</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/drivers/cdrom/cdrom.h
+++ lxdream/src/drivers/cdrom/cdrom.h
@@ -103,7 +103,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  * @param lba The position on disc of the main track. If non-zero,
  * a filler track is added before it, in 2 separate sessions.
  */
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-cdrom_disc_t cdrom_disc_new_from_track( cdrom_disc_type_t type, sector_source_t track, cdrom_lba_t lba );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+cdrom_disc_t cdrom_disc_new_from_track( cdrom_disc_type_t type, sector_source_t track, cdrom_lba_t lba<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >, ERROR *err</span> );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 /**
  * Get the track information for the given track. If there is no such track,
</pre></div>
<hr /><a name="file11" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/drivers/cdrom</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>isofs.c</b></big> <small id="info" style="color: #888888;" >305ef2082079 -> 700c5ab26a63</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/drivers/cdrom/isofs.c
+++ lxdream/src/drivers/cdrom/isofs.c
@@ -60,6 +60,24 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     return src;
 }
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static void iso_error_convert( int status, ERROR *err )
+{
+    switch( status ) {
+    case ISO_SUCCESS:
+        err->code = LX_ERR_NONE;
+        break;
+    case ISO_OUT_OF_MEM:
+        SET_ERROR( err, LX_ERR_NOMEM, "Unable to allocate memory for ISO filesystem" );
+        break;
+    case ISO_FILE_READ_ERROR:
+        SET_ERROR( err, LX_ERR_FILE_IOERROR, "Read error" );
+        break;
+    default:
+        SET_ERROR( err, LX_ERR_UNHANDLED, "Unknown error in ISO filesystem" );
+        break;
+    }
+}
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > /**
  * Construct an isofs image from an existing sector source.
  */
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -110,6 +128,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
     int status = iso_read_opts_new(&opts,0);
     if( status != 1 ) {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        iso_error_convert(status, err);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return NULL;
     }
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -119,6 +138,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     iso_data_source_unref(src);
     iso_read_opts_free(opts);
     if( status != 1 ) {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        iso_error_convert(status, err);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return NULL;
     }
     return iso;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -148,8 +168,10 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     struct burn_source *burn;
 
     int status = iso_write_opts_new(&opts, 0);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    if( status != 1 )
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( status != 1 )<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" > {</span>
+        iso_error_convert(status, err);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return NULL;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     iso_write_opts_set_appendable(opts,0);
     iso_write_opts_set_ms_block(opts, start_sector);
     iso_write_opts_set_system_area(opts, (char *)bootstrap, 0, 0);
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -157,6 +179,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     status = iso_image_create_burn_source(image, opts, &burn);
     iso_write_opts_free(opts);
     if( status != 1 ) {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        iso_error_convert(status, err);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return NULL;
     }
 
</pre></div>
<hr /><a name="file12" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>gdlist.c</b></big> <small id="info" style="color: #888888;" >305ef2082079 -> 700c5ab26a63</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/gdlist.c
+++ lxdream/src/gdlist.c
@@ -147,7 +147,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     CALL_HOOKS( gdrom_list_change_hook, TRUE, gdrom_list_get_selection() );
 }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-gboolean gdrom_list_set_selection( int posn )
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+gboolean gdrom_list_set_selection( int posn<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >, ERROR *err</span> )
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
     if( posn == 0 ) { // Always 'Empty'
         gdrom_unmount_disc();
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -156,15 +156,17 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
     if( posn <= gdrom_device_count ) {
         cdrom_drive_t device = g_list_nth_data(gdrom_device_list, posn-1);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        return gdrom_mount_image(device->name);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        return gdrom_mount_image(device->name<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >, err</span>);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 
     posn -= FIRST_RECENT_INDEX;
     if( posn >= 0 && posn < gdrom_recent_count ) {
         gchar *entry = g_list_nth_data(gdrom_recent_list, posn);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        return gdrom_mount_image(entry);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        return gdrom_mount_image(entry<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >, err</span>);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    /* Should never happen */
+    SET_ERROR( err, LX_ERR_BUG, "Invalid selection: This is probably a bug" );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     return FALSE;
 }
 
</pre></div>
<hr /><a name="file13" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>gdlist.h</b></big> <small id="info" style="color: #888888;" >305ef2082079 -> 700c5ab26a63</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/gdlist.h
+++ lxdream/src/gdlist.h
@@ -20,6 +20,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #ifndef lxdream_gdlist_H
 #define lxdream_gdlist_H 1
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#include <stdio.h>
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #include "hook.h"
 
 #ifdef __cplusplus
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -64,9 +65,10 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > /**
  * Change the current gdrom selection to the selected index. This will mount the
  * appropriate drive/image where necessary.
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ * @param err Updated if there was an error loading the selected gdrom
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  * @return TRUE if the selection was updated, FALSE if the position was invalid. 
  */
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-gboolean gdrom_list_set_selection(int posn);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+gboolean gdrom_list_set_selection(int posn<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >, ERROR *err</span>);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 #ifdef __cplusplus
 }
</pre></div>
<hr /><a name="file14" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/gdrom</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>gdrom.c</b></big> <small id="info" style="color: #888888;" >305ef2082079 -> 700c5ab26a63</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/gdrom/gdrom.c
+++ lxdream/src/gdrom/gdrom.c
@@ -28,6 +28,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #include "gdrom/gdrom.h"
 #include "gdrom/packet.h"
 #include "bootstrap.h"
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#include "loader.h"
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #include "drivers/cdrom/cdrom.h"
 
 #define GDROM_LBA_OFFSET 150
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -58,9 +59,12 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-gboolean gdrom_mount_image( const gchar *filename )
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+gboolean gdrom_mount_image( const gchar *filename<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >,  ERROR *err</span> )
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    cdrom_disc_t disc = cdrom_disc_open(filename, <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >NULL</span>);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    cdrom_disc_t disc = cdrom_disc_open(filename, <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >err</span>);
+    if( disc == NULL && err->code == LX_ERR_FILE_UNKNOWN ) {
+        disc = cdrom_wrap_magic( CDROM_DISC_XA, filename, err );
+    } 
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     if( disc != NULL ) {         
         gdrom_mount_disc( disc );
         return TRUE;
</pre></div>
<hr /><a name="file15" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/gdrom</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>gdrom.h</b></big> <small id="info" style="color: #888888;" >305ef2082079 -> 700c5ab26a63</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/gdrom/gdrom.h
+++ lxdream/src/gdrom/gdrom.h
@@ -53,7 +53,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  * Shortcut to open and mount an image file
  * @return true on success
  */
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-gboolean gdrom_mount_image( const gchar *filename );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+gboolean gdrom_mount_image( const gchar *filename<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >, ERROR *err</span> );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 void gdrom_mount_disc( cdrom_disc_t disc );
 
</pre></div>
<hr /><a name="file16" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/gtkui</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>gtk_gd.c</b></big> <small id="info" style="color: #888888;" >305ef2082079 -> 700c5ab26a63</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/gtkui/gtk_gd.c
+++ lxdream/src/gtkui/gtk_gd.c
@@ -27,17 +27,31 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 static gboolean gdrom_menu_adjusting = FALSE;
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+gboolean gtk_gui_gdrom_mount_image( const char *filename )
+{
+    ERROR err;
+    gboolean ok = gdrom_mount_image( filename, &err );
+    if( !ok ) {
+        ERROR( err.msg );
+    }
+    return ok;
+}
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > static void gdrom_menu_open_image_callback( GtkWidget *widget, gpointer user_data )
 {
     if( !gdrom_menu_adjusting ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        open_file_dialog_cb( _("Open..."), gdrom_mount_image, NULL, NULL, CONFIG_DEFAULT_PATH );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        open_file_dialog_cb( _("Open..."), g<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >tk_gui_g</span>drom_mount_image, NULL, NULL, CONFIG_DEFAULT_PATH );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 }
 
 void gdrom_menu_item_callback( GtkWidget *widget, gpointer user_data )
 {
     if( !gdrom_menu_adjusting ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        gdrom_list_set_selection( GPOINTER_TO_INT(user_data) );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        ERROR err;
+        gboolean ok = gdrom_list_set_selection( GPOINTER_TO_INT(user_data), &err );
+        if( !ok ) {
+            ERROR( err.msg );
+        }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 }
 
</pre></div>
<hr /><a name="file17" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/gtkui</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>gtkcb.c</b></big> <small id="info" style="color: #888888;" >305ef2082079 -> 700c5ab26a63</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/gtkui/gtkcb.c
+++ lxdream/src/gtkui/gtkcb.c
@@ -129,7 +129,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 void mount_action_callback( GtkAction *action, gpointer user_data)
 {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    open_file_dialog_cb( "Open...", gdrom_mount_image, NULL, NULL, CONFIG_DEFAULT_PATH );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    open_file_dialog_cb( "Open...", g<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >tk_gui_g</span>drom_mount_image, NULL, NULL, CONFIG_DEFAULT_PATH );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 void reset_action_callback( GtkAction *action, gpointer user_data)
 {
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -146,9 +146,19 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     dreamcast_run();
 }
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+gboolean gtk_gui_load_exec( const gchar *filename )
+{
+    ERROR err;
+    gboolean ok = file_load_exec(filename, &err);
+    if( !ok ) {
+        ERROR(err.msg);
+    }
+    return ok;
+}
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > void load_binary_action_callback( GtkAction *action, gpointer user_data)
 {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    open_file_dialog_cb( "Open Binary...", <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >file_load_magi</span>c, NULL, NULL, CONFIG_DEFAULT_PATH );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    open_file_dialog_cb( "Open Binary...", <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >gtk_gui_load_exe</span>c, NULL, NULL, CONFIG_DEFAULT_PATH );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 
 void load_state_preview_callback( GtkFileChooser *chooser, gpointer user_data )
</pre></div>
<hr /><a name="file18" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/gtkui</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>gtkui.h</b></big> <small id="info" style="color: #888888;" >305ef2082079 -> 700c5ab26a63</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/gtkui/gtkui.h
+++ lxdream/src/gtkui/gtkui.h
@@ -98,6 +98,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >                           int initial_dir_key );
 void save_file_dialog_cb( const char *title, file_callback_t action, const char *pattern, const char *patname,
                           int initial_dir_key );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+gboolean gtk_gui_gdrom_mount_image( const char *filename );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > /**
  * Extract the keyval of the key event if no modifier keys were pressed -
  * in other words get the keyval of the key by itself. The other way around
</pre></div>
<hr /><a name="file19" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>loader.c</b></big> <small id="info" style="color: #888888;" >305ef2082079 -> 700c5ab26a63</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/loader.c
+++ lxdream/src/loader.c
@@ -33,6 +33,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #include "loader.h"
 #include "drivers/cdrom/cdrom.h"
 #include "drivers/cdrom/isofs.h"
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#include "gdrom/gdrom.h"
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 const char bootstrap_magic[32] = "SEGA SEGAKATANA SEGA ENTERPRISES";
 const char iso_magic[6] = "\001CD001";
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -41,101 +42,171 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         { "bin", "SH4 Bin file" },
         { NULL, NULL } };
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-gboolean file_load_elf_fd( const gchar *filename, int fd );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static cdrom_disc_t cdrom_wrap_elf( cdrom_disc_type_t type, const gchar *filename, int fd, ERROR *err );
+static cdrom_disc_t cdrom_wrap_binary( cdrom_disc_type_t type, const gchar *filename, int fd, ERROR *err );
+static gboolean file_load_binary( const gchar *filename, int fd, ERROR *err );
+static gboolean file_load_elf( const gchar *filename, int fd, ERROR *err );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-typedef enum {
-    FILE_ERROR,
-    FILE_BINARY,
-    FILE_ELF,
-    FILE_ISO,
-    FILE_DISC,
-    FILE_ZIP,
-    FILE_SAVE_STATE,
-} lxdream_file_type_t;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-static lxdream_file_type_t file_magic( const gchar *filename, int fd, ERROR *err )
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+
+lxdream_file_type_t file_identify( const gchar *filename, int fd, ERROR *err )
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
     char buf[32];
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    lxdream_file_type_t result = FILE_UNKNOWN;
+    gboolean mustClose = FALSE;
+    off_t posn;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    /* begin magic */
-    if( read( fd, buf, 32 ) != 32 ) {
-        SET_ERROR( err, errno, "Unable to read from file '%s'", filename );
-        return FILE_ERROR;
-
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( fd == -1 ) {
+        fd = open( filename, O_RDONLY );
+        if( fd == -1 ) {
+            SET_ERROR( err, LX_ERR_FILE_NOOPEN, "Unable to open file '%s' (%s)" ,filename, strerror(errno) );
+            return FILE_ERROR;
+        }
+        mustClose = TRUE;
+    } else {
+        /* Save current file position */
+        posn = lseek(fd, 0, SEEK_CUR);
+        if( posn == -1 ) {
+            SET_ERROR( err, LX_ERR_FILE_IOERROR, "Unable to read from file '%s' (%s)", filename, strerror(errno) );
+            return FILE_ERROR;
+        }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    lseek( fd, 0, SEEK_SET );
-    if( buf[0] == 0x7F && buf[1] == 'E' &&
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    int status = read(fd, buf, 32);
+    if( status == -1 ) {
+        SET_ERROR( err, LX_ERR_FILE_IOERROR, "Unable to read from file '%s' (%s)", filename, strerror(errno) );
+        result = FILE_ERROR;
+    } else if( status != 32 ) {
+        result = FILE_UNKNOWN;
+    } else if( buf[0] == 0x7F && buf[1] == 'E' &&
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             buf[2] == 'L' && buf[3] == 'F' ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        re<span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >turn</span> FILE_ELF;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        re<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >sult =</span> FILE_ELF;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     } else if( memcmp( buf, "PK\x03\x04", 4 ) == 0 ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        re<span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >turn</span> FILE_ZIP;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        re<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >sult =</span> FILE_ZIP;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     } else if( memcmp( buf, DREAMCAST_SAVE_MAGIC, 16 ) == 0 ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        re<span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >turn</span> FILE_SAVE_STATE;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        re<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >sult =</span> FILE_SAVE_STATE;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     } else if( lseek( fd, 32768, SEEK_SET ) == 32768 &&
             read( fd, buf, 8 ) == 8 &&
             memcmp( buf, iso_magic, 6) == 0 ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        lseek( fd, 0, SEEK_SET );
-        return FILE_ISO;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        result = FILE_ISO;
+    } else {
+        /* Check the file extension - .bin = sh4 binary */
+        int len = strlen(filename);
+        struct stat st;
+
+        if( len > 4 && strcasecmp(filename + (len-4), ".bin") == 0 &&
+            fstat(fd, &st) != -1 && st.st_size <= BINARY_MAX_SIZE ) {
+            result = FILE_BINARY;
+        }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    lseek( fd, 0, SEEK_SET );
-    return FILE_BINARY;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+
+    if( mustClose ) {
+        close(fd);
+    } else {
+        lseek( fd, posn, SEEK_SET );
+    }
+    return result;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-gboolean file_load_magic( const gchar *filename )
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+gboolean file_load_exec( const gchar *filename, ERROR *err )
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    char buf[32];
-    struct stat st;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     gboolean result = TRUE;
 
     int fd = open( filename, O_RDONLY );
     if( fd == -1 ) {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        SET_ERROR( err, LX_ERR_FILE_NOOPEN, "Unable to open file '%s' (%s)" ,filename, strerror(errno) );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return FALSE;
     }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    fstat( fd, &st );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    lxdream_file_type_t type = file_identify(filename, fd, err);
+    switch( type ) {
+    case FILE_ERROR:
+        result = FALSE;
+        break;
+    case FILE_ELF:
+        result = file_load_elf( filename, fd, err );
+        break;
+    case FILE_BINARY:
+        result = file_load_binary( filename, fd, err );
+        break;
+    default:
+        SET_ERROR( err, LX_ERR_FILE_UNKNOWN, "File '%s' could not be recognized as an executable binary", filename );
+        result = FALSE;
+        break;
+    }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    /* begin magic */
-    if( read( fd, buf, 32 ) != 32 ) {
-        ERROR( "Unable to read from file '%s'", filename );
-        close(fd);
-        return FALSE;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    close(fd);
+    return result;
+}
+
+lxdream_file_type_t file_load_magic( const gchar *filename, gboolean wrap_exec, ERROR *err )
+{
+    gboolean result;
+    /* Try disc types first */
+    cdrom_disc_t disc = cdrom_disc_open( filename, err );
+    if( disc != NULL ) {
+        gdrom_mount_disc(disc);
+        return FILE_DISC;
+    } else if( err != LX_ERR_FILE_UNKNOWN ) {
+        return FILE_ERROR;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    if( memcmp( buf, bootstrap_magic, 32 ) == 0 ) {
-        /* we have a DC bootstrap */
-        if( st.st_size == BOOTSTRAP_SIZE ) {
-            sh4ptr_t load = mem_get_region( BOOTSTRAP_LOAD_ADDR );
-            lseek( fd, 0, SEEK_SET );
-            read( fd, load, BOOTSTRAP_SIZE );
-            bootstrap_dump( load, TRUE );
-            dreamcast_program_loaded( filename, BOOTSTRAP_LOAD_ADDR + 0x300 );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+
+    int fd = open( filename, O_RDONLY );
+    if( fd == -1 ) {
+        SET_ERROR( err, LX_ERR_FILE_NOOPEN, "Unable to open file '%s' (%s)" ,filename, strerror(errno) );
+        return FILE_ERROR;
+    }
+
+    lxdream_file_type_t type = file_identify(filename, fd, err);
+    switch( type ) {
+    case FILE_ERROR:
+        result = FALSE;
+        break;
+    case FILE_ELF:
+        if( wrap_exec ) {
+            disc = cdrom_wrap_elf( CDROM_DISC_XA, filename, fd, err );
+            result = disc != NULL;
+            if( disc != NULL ) {
+                gdrom_mount_disc(disc);
+            }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         } else {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-            /* look for a valid ISO9660 header */
-            lseek( fd, 32768, SEEK_SET );
-            read( fd, buf, 8 );
-            if( memcmp( buf, iso_magic, 6 ) == 0 ) {
-                /* Alright, got it */
-                WARN( "ISO images not supported yet" );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+            result = file_load_elf( filename, fd, err );
+        }
+        break;
+    case FILE_BINARY:
+        if( wrap_exec ) {
+            disc = cdrom_wrap_binary( CDROM_DISC_XA, filename, fd, err );
+            result = disc != NULL;
+            if( disc != NULL ) {
+                gdrom_mount_disc(disc);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             }
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        } else {
+            result = file_load_binary( filename, fd, err );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         }
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    } else if( memcmp( buf, "PK\x03\x04", 4 ) == 0 ) {
-        /* ZIP file, aka SBI file */
-        WARN( "SBI files not supported yet" );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        break;
+    case FILE_SAVE_STATE:
+        result = dreamcast_load_state( filename );
+        break;
+    case FILE_ZIP:
+        SET_ERROR( err, LX_ERR_FILE_UNSUP, "ZIP/SBI not currently supported" );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         result = FALSE;
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    } else if( memcmp( buf, DREAMCAST_SAVE_MAGIC, 16 ) == 0 ) {
-        /* Save state */
-        result = (dreamcast_load_state( filename )==0);
-    } else if( buf[0] == 0x7F && buf[1] == 'E' && 
-            buf[2] == 'L' && buf[3] == 'F' ) {
-        /* ELF binary */
-        lseek( fd, 0, SEEK_SET );
-        result = file_load_elf_fd( filename, fd );
-    } else {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        break;
+    case FILE_ISO:
+        SET_ERROR( err, LX_ERR_FILE_UNSUP, "ISO files are not currently supported" );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         result = FALSE;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        break;
+    default:
+        SET_ERROR( err, LX_ERR_FILE_UNKNOWN, "File '%s' could not be recognized", filename );
+        result = FALSE;
+        break;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
     close(fd);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    return result;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( result ) {
+        CLEAR_ERROR(err);
+        return type;
+    }
+    return FILE_ERROR;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 
 void file_load_postload( const gchar *filename, int pc )
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -156,18 +227,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }    
 
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-gboolean file_load_binary( const gchar *filename )
-{
-    /* Load the binary itself */
-    if(  mem_load_block( filename, BINARY_LOAD_ADDR, -1 ) == 0 ) {
-        file_load_postload( filename, BINARY_LOAD_ADDR );
-        return TRUE;
-    } else {
-        return FALSE;
-    }
-}
-
-gboolean is_sh4_elf( Elf32_Ehdr *head )
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static gboolean is_sh4_elf( Elf32_Ehdr *head )
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
     return ( head->e_ident[EI_CLASS] == ELFCLASS32 &&
             head->e_ident[EI_DATA] == ELFDATA2LSB &&
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -177,7 +237,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             head->e_version == 1 );
 }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-gboolean is_arm_elf( Elf32_Ehdr *head )
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >static </span>gboolean is_arm_elf( Elf32_Ehdr *head )
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
     return ( head->e_ident[EI_CLASS] == ELFCLASS32 &&
             head->e_ident[EI_DATA] == ELFDATA2LSB &&
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -187,7 +247,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             head->e_version == 1 );
 }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-gboolean file_load_elf_fd( const gchar *filename, int fd ) 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static gboolean file_load_elf( const gchar *filename, int fd, ERROR *err )
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
     Elf32_Ehdr head;
     Elf32_Phdr phdr;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -196,7 +256,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     if( read( fd, &head, sizeof(head) ) != sizeof(head) )
         return FALSE;
     if( !is_sh4_elf(&head) ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        ERROR( "File is not an SH4 ELF executable file" );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        SET_ERROR( err, LX_ERR_FILE_INVALID, "File is not an SH4 ELF executable file" );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return FALSE;
     }
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -211,7 +271,6 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             if( phdr.p_memsz > phdr.p_filesz ) {
                 memset( target + phdr.p_filesz, 0, phdr.p_memsz - phdr.p_filesz );
             }
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-            INFO( "Loaded %d bytes to %08X", phdr.p_filesz, phdr.p_vaddr );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         }
     }
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -219,6 +278,30 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     return TRUE;
 }
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static gboolean file_load_binary( const gchar *filename, int fd, ERROR *err )
+{
+    struct stat st;
+
+    if( fstat( fd, &st ) == -1 ) {
+        SET_ERROR( err, LX_ERR_FILE_IOERROR, "Error reading binary file '%s' (%s)", filename, strerror(errno) );
+        return FALSE;
+    }
+
+    if( st.st_size > BINARY_MAX_SIZE ) {
+        SET_ERROR( err, LX_ERR_FILE_INVALID, "Binary file '%s' is too large to fit in memory", filename );
+        return FALSE;
+    }
+
+    sh4ptr_t target = mem_get_region( BINARY_LOAD_ADDR );
+    if( read( fd, target, st.st_size ) != st.st_size ) {
+        SET_ERROR( err, LX_ERR_FILE_IOERROR, "Error reading binary file '%s' (%s)", filename, strerror(errno) );
+        return FALSE;
+    }
+
+    file_load_postload( filename, BINARY_LOAD_ADDR );
+    return TRUE;
+}
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > /**
  * Create a new CDROM disc containing a single 1ST_READ.BIN.
  * @param type The disc type - must be CDROM_DISC_GDROM or CDROM_DISC_XA
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -233,25 +316,25 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     cdrom_lba_t start_lba = 45000; /* GDROM_START */
     char bootstrap[32768];
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    /* 1. Load in the bootstrap */
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    /* 1. Load in the bootstrap: Note failures here are considered configuration errors */
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     gchar *bootstrap_file = lxdream_get_global_config_path_value(CONFIG_BOOTSTRAP);
     if( bootstrap_file == NULL || bootstrap_file[0] == '\0' ) {
         g_free(data);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        SET_ERROR( err, <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >ENOENT</span>, "Unable to create CD image: bootstrap file is not configured" );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        SET_ERROR( err, <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >LX_ERR_CONFIG</span>, "Unable to create CD image: bootstrap file is not configured" );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return NULL;
     }
 
     FILE *f = fopen( bootstrap_file, "ro" );
     if( f == NULL ) {
         g_free(data);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        SET_ERROR( err, <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >errno</span>, "Unable to create CD image: bootstrap file '%s' could not be opened", bootstrap_file );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        SET_ERROR( err, <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >LX_ERR_CONFIG</span>, "Unable to create CD image: bootstrap file '%s' could not be opened", bootstrap_file );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return FALSE;
     }
     size_t len = fread( bootstrap, 1, 32768, f );
     fclose(f);
     if( len != 32768 ) {
         g_free(data);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        SET_ERROR( err, <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >EINVAL</span>, "Unable to create CD image: bootstrap file '%s' is invalid", bootstrap_file );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        SET_ERROR( err, <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >LX_ERR_CONFIG</span>, "Unable to create CD image: bootstrap file '%s' is invalid", bootstrap_file );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return FALSE;
     }
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -280,6 +363,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     int status = iso_image_new("autocd", &iso);
     if( status != 1 ) {
         g_free(data);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        SET_ERROR( err, LX_ERR_NOMEM, "Unable to create CD image: out of memory" );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return NULL;
     }
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -287,6 +371,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     if( iso_memory_stream_new(data, bin_size, &stream) != 1 ) {
         g_free(data);
         iso_image_unref(iso);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        SET_ERROR( err, LX_ERR_NOMEM, "Unable to create CD image: out of memory" );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return NULL;
     }
     iso_tree_add_new_file(iso_image_get_root(iso), "1ST_READ.BIN", stream, NULL);
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -297,15 +382,15 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return NULL;
     }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    cdrom_disc_t disc = cdrom_disc_new_from_track( type, track, start_lba );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    cdrom_disc_t disc = cdrom_disc_new_from_track( type, track, start_lba<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >, err</span> );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     iso_image_unref(iso);
     if( disc != NULL ) {
         disc->name = g_strdup(filename);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    }
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    }<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" > </span>
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     return disc;
 }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-<span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >cdrom_disc_t cdrom_wrap_elf_fd</span>( cdrom_disc_type_t type, const gchar *filename, int fd, ERROR *err )
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >static cdrom_disc_t cdrom_wrap_elf</span>( cdrom_disc_type_t type, const gchar *filename, int fd, ERROR *err )
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
     Elf32_Ehdr head;
     int i;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -313,12 +398,13 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     /* Check the file header is actually an SH4 binary */
     if( read( fd, &head, sizeof(head) ) != sizeof(head) )
         return FALSE;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     if( !is_sh4_elf(&head) ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        SET_ERROR( err, <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >EINVAL</span>, "File is not an SH4 ELF executable file" );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        SET_ERROR( err, <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >LX_ERR_FILE_INVALID</span>, "File is not an SH4 ELF executable file" );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return FALSE;
     }
     if( head.e_entry != BINARY_LOAD_ADDR ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        SET_ERROR( err, <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >EINVAL</span>, "SH4 Binary has incorrect entry point (should be %08X but is %08X)", BINARY_LOAD_ADDR, head.e_entry );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        SET_ERROR( err, <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >LX_ERR_FILE_INVALID</span>, "SH4 Binary has incorrect entry point (should be %08X but is %08X)", BINARY_LOAD_ADDR, head.e_entry );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return FALSE;
     }
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -326,7 +412,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     Elf32_Phdr phdr[head.e_phnum];
     lseek( fd, head.e_phoff, SEEK_SET );
     if( read( fd, phdr, sizeof(phdr) ) != sizeof(phdr) ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        SET_ERROR( err, <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >EINVAL</span>, "File is not a valid executable file" );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        SET_ERROR( err, <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >LX_ERR_FILE_INVALID</span>, "File is not a valid executable file" );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return FALSE;
     }
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -342,11 +428,11 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 
     if( start != BINARY_LOAD_ADDR ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        SET_ERROR( err, <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >EINVAL</span>, "SH4 Binary has incorrect load address (should be %08X but is %08X)", BINARY_LOAD_ADDR, start );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        SET_ERROR( err, <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >LX_ERR_FILE_INVALID</span>, "SH4 Binary has incorrect load address (should be %08X but is %08X)", BINARY_LOAD_ADDR, start );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return FALSE;
     }
     if( end >= 0x8D000000 ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        SET_ERROR( err, <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >EINVAL</span>, "SH4 binary is too large to fit in memory (end address is %08X)", end );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        SET_ERROR( err, <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >LX_ERR_FILE_INVALID</span>, "SH4 binary is too large to fit in memory (end address is %08X)", end );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return FALSE;
     }
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -356,7 +442,12 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         if( phdr[i].p_type == PT_LOAD ) {
             lseek( fd, phdr[i].p_offset, SEEK_SET );
             uint32_t size = MIN( phdr[i].p_filesz, phdr[i].p_memsz);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-            read( fd, program + phdr[i].p_vaddr, size );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+            <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >int status = </span>read( fd, program + phdr[i].p_vaddr, size );
+            if( status == -1 ) {
+                SET_ERROR( err, LX_ERR_FILE_IOERROR, "I/O error reading SH4 binary %s (%s)", filename, strerror(errno) );
+            } else if( status != size ) {
+                SET_ERROR( err, LX_ERR_FILE_IOERROR, "SH4 binary %s is corrupt", filename );
+            }            
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         }
     }
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -364,39 +455,52 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     return cdrom_disc_new_wrapped_binary(type, filename, program, end-start, err );
 }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-cdrom_disc_t cdrom_wrap_magic( cdrom_disc_type_t type, const gchar *filename, ERROR *err )
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static cdrom_disc_t cdrom_wrap_binary( cdrom_disc_type_t type, const gchar *filename, int fd, ERROR *err )
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    cdrom_disc_t disc;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    struct stat st;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     char *data;
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    int len;
-    struct stat st;
-    int fd = open( filename, O_RDONLY );
-    if( fd == -1 ) {
-        SET_ERROR( err, errno, "Unable to open file '%s'", filename );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    size_t len;
+
+    if( fstat(fd, &st) == -1 ) {
+        SET_ERROR( err, LX_ERR_FILE_IOERROR, "Error reading binary file '%s' (%s)", filename, strerror(errno) );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return NULL;
     }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-
-    lxdream_file_type_t filetype = file_magic( filename, fd, err );
-    switch( filetype ) {
-    case FILE_BINARY:
-        fstat( fd, &st );
-        data = g_malloc(st.st_size);
-        len = read( fd, data, st.st_size );
-        close(fd);
-        if( len != st.st_size ) {
-            SET_ERROR( err, errno, "Error reading binary file '%s'", filename );
-            return NULL;
-        }
-        return cdrom_disc_new_wrapped_binary( type, filename, data, st.st_size, err );
-    case FILE_ELF:
-        disc = cdrom_wrap_elf_fd(type, filename, fd, err);
-        close(fd);
-        return disc;
-    default:
-        close(fd);
-        SET_ERROR( err, EINVAL, "File '%s' cannot be wrapped (not a binary)", filename );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    data = g_malloc(st.st_size);
+    len = read( fd, data, st.st_size );
+    if( len != st.st_size ) {
+        SET_ERROR( err, LX_ERR_FILE_IOERROR, "Error reading binary file '%s' (%s)", filename, strerror(errno) );
+        free(data);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return NULL;
     }
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    return cdrom_disc_new_wrapped_binary( type, filename, data, st.st_size, err );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+
+cdrom_disc_t cdrom_wrap_magic( cdrom_disc_type_t type, const gchar *filename, ERROR *err )
+{
+    cdrom_disc_t disc = NULL;
+
+    int fd = open( filename, O_RDONLY );
+    if( fd == -1 ) {
+        SET_ERROR( err, LX_ERR_FILE_NOOPEN, "Unable to open file '%s'", filename );
+        return NULL;
+    }
+
+    lxdream_file_type_t filetype = file_identify( filename, fd, err );
+    switch( filetype ) {
+    case FILE_ELF:
+        disc = cdrom_wrap_elf(type, filename, fd, err);
+        break;
+    case FILE_BINARY:
+        disc = cdrom_wrap_binary(type, filename, fd, err);
+        break;
+    default:
+        SET_ERROR( err, LX_ERR_FILE_UNKNOWN, "File '%s' cannot be wrapped (not a recognized binary)", filename );
+        break;
+    }
+
+    close(fd);
+    return disc;
+
+}
</pre></div>
<hr /><a name="file20" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>loader.h</b></big> <small id="info" style="color: #888888;" >305ef2082079 -> 700c5ab26a63</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/loader.h
+++ lxdream/src/loader.h
@@ -34,37 +34,37 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  */
 extern char *file_loader_extensions[][2];
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-/**
- * Load the CD bootstrap, aka IP.BIN. Identified by "SEGA SEGAKATANA" at
- * start of file. IP.BIN is loaded as-is at 8C008000.
- * This is mainly for testing as it's unlikely anyone would want to do this
- * for any other reason.
- * @return TRUE on success, otherwise FALSE and errno 
- */
-gboolean file_load_bootstrap( const gchar *filename );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+typedef enum {
+    FILE_ERROR,
+    FILE_BINARY,
+    FILE_ELF,
+    FILE_ISO,
+    FILE_DISC,
+    FILE_ZIP,
+    FILE_SAVE_STATE,
+    FILE_UNKNOWN,
+} lxdream_file_type_t;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 /**
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >- * Load a miscellaneous .bin file, as commonly used in demos. No magic
- * applies, file is loaded as is at 8C010000
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ * Attempt to identify the given file as one of the above file types
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  */
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-gboolean file_load_binary( const gchar *filename );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+lxdream_file_type_t file_identify( const gchar *filename, int fd, ERROR *err );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 /**
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >- * Load a "Self Boot Inducer" .sbi file, also commonly used to package
- * demos. (Actually a ZIP file with a predefined structure
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ * Load any supported file, and return the type of file loaded.
+ * If the file is a disc, the disc is mounted. 
+ * 
+ * @param filename The file to load
+ * @param wrap_exec If true, load executables as disc images. Otherwise load 
+ *    directly into RAM
+ * @param err Updated with error message on failure.
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  */
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-gboolean file_load_sbi( const gchar *filename );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+lxdream_file_type_t file_load_magic( const gchar *filename, gboolean wrap_exec, ERROR *err );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 /**
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >- * Load an ELF executable binary file. Origin is file-dependent.
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ * Load an ELF or .bin executable file based on magic.
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  */
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-gboolean file_load_elf( const gchar *filename );
-
-/**
- * Load any of the above file types, using the appropriate magic to determine
- * which is actually applicable
- */
-gboolean file_load_magic( const gchar *filename );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+gboolean file_load_exec( const gchar *filename, ERROR *err );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 cdrom_disc_t cdrom_wrap_magic( cdrom_disc_type_t type, const gchar *filename, ERROR *err );
 
</pre></div>
<hr /><a name="file21" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>lxdream.h</b></big> <small id="info" style="color: #888888;" >305ef2082079 -> 700c5ab26a63</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/lxdream.h
+++ lxdream/src/lxdream.h
@@ -94,8 +94,19 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     char msg[MAX_ERROR_MSG_SIZE];
 } ERROR;
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#define LX_ERR_NONE          0
+#define LX_ERR_NOMEM         1  /* Out-of-memory */
+#define LX_ERR_CONFIG        2  /* Configuration problem */
+#define LX_ERR_UNHANDLED     3  /* A lower-level error occurred which we don't understand */
+#define LX_ERR_BUG           4
+#define LX_ERR_FILE_NOOPEN   9  /* File could not be opened (ENOENT or EACCESS usually) */
+#define LX_ERR_FILE_IOERROR 10  /* I/O error encountered in file */
+#define LX_ERR_FILE_INVALID 11  /* File contents are invalid for its type */
+#define LX_ERR_FILE_UNKNOWN 12  /* File type is unrecognized */
+#define LX_ERR_FILE_UNSUP   13  /* File type is unsupported */
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #define SET_ERROR(err, n, ...) if( (err) != NULL ) { (err)->code = n; snprintf( (err)->msg, sizeof((err)->msg), __VA_ARGS__ ); }
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-#define CLEAR_ERROR(err) do { <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >err.code = 0; err.</span>msg[0] = 0; } while(0)
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#define CLEAR_ERROR(err) do { <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >(err)->code = 0; (err)-></span>msg[0] = 0; } while(0)
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 
 #ifdef HAVE_FASTCALL
</pre></div>
<hr /><a name="file22" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>main.c</b></big> <small id="info" style="color: #888888;" >305ef2082079 -> 700c5ab26a63</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/main.c
+++ lxdream/src/main.c
@@ -42,13 +42,14 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #include "hotkeys.h"
 #include "plugin.h"
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-char *option_list = "a:A:bc:dfg:G:hHl:m:npt:T:uvV:w:x?";
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+char *option_list = "a:A:bc:e:dfg:G:hHl:m:npt:T:uvV:x?";
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > struct option longopts[] = {
         { "aica", required_argument, NULL, 'a' },
         { "audio", required_argument, NULL, 'A' },
         { "biosless", no_argument, NULL, 'b' },
         { "config", required_argument, NULL, 'c' },
         { "debugger", no_argument, NULL, 'd' },
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        { "execute", required_argument, NULL, 'e' },
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         { "fullscreen", no_argument, NULL, 'f' },
         { "gdb-sh4", required_argument, NULL, 'g' },  
         { "gdb-arm", required_argument, NULL, 'G' },  
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -61,7 +62,6 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         { "unsafe", no_argument, NULL, 'u' },
         { "video", no_argument, NULL, 'V' },
         { "version", no_argument, NULL, 'v' }, 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        { "wrap", required_argument, NULL, 'w' },
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         { NULL, 0, 0, 0 } };
 char *aica_program = NULL;
 char *display_driver_name = NULL;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -86,13 +86,14 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > static void print_usage()
 {
     print_version();
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    printf( "Usage: lxdream %s [options] [disc-file] [<span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >program-fil</span>e]\n\n", lxdream_full_version );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    printf( "Usage: lxdream %s [options] [disc-file] [<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >save-stat</span>e]\n\n", lxdream_full_version );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
     printf( "Options:\n" );
     printf( "   -a, --aica=PROGFILE    %s\n", _("Run the AICA SPU only, with the supplied program") );
     printf( "   -A, --audio=DRIVER     %s\n", _("Use the specified audio driver (? to list)") );
     printf( "   -b, --biosless         %s\n", _("Run without the BIOS boot rom even if available") );
     printf( "   -c, --config=CONFFILE  %s\n", _("Load configuration from CONFFILE") );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    printf( "   -e, --execute=PROGRAM  %s\n", _("Load and execute the given SH4 program") );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     printf( "   -d, --debugger         %s\n", _("Start in debugger mode") );
     printf( "   -f, --fullscreen       %s\n", _("Start in fullscreen mode") );
     printf( "   -g, --gdb-sh4=PORT     %s\n", _("Start GDB remote server on PORT for SH4") );
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -108,7 +109,6 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     printf( "   -u, --unsafe           %s\n", _("Allow unsafe dcload syscalls") );
     printf( "   -v, --version          %s\n", _("Print the lxdream version string") );
     printf( "   -V, --video=DRIVER     %s\n", _("Use the specified video driver (? to list)") );
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    printf( "   -w, --wrap=FILENAME    %s\n", _("Wrap the specified binary file in a disc image") );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     printf( "   -x                     %s\n", _("Disable the SH4 translator") );
 }
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -124,9 +124,9 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
     int opt;
     double t;
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    gboolean display_ok;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    gboolean display_ok, have_disc = FALSE, have_save = FALSE, have_exec = FALSE;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     uint32_t time_secs, time_nanos;
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    const char *<span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >wrap</span>_name = NULL;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    const char *<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >exec</span>_name = NULL;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
     install_crash_handler();
     bind_gettext_domain();
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -148,6 +148,9 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         case 'd': /* Launch w/ debugger */
             show_debugger = TRUE;
             break;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        case 'e':
+            exec_name = optarg;
+            break;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         case 'f':
             show_fullscreen = TRUE;
             break;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -203,9 +206,6 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         case 'V': /* Video driver */
             display_driver_name = optarg;
             break;
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        case 'w': /* Wrap image file */
-            wrap_name = optarg;
-            break;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         case 'x': /* Disable translator */
             use_xlat = FALSE;
             break;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -268,37 +268,52 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     maple_reattach_all();
     INFO( "%s! ready...", APP_NAME );
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    if( wrap_name != NULL ) {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    for( ; optind < argc; optind++ ) {
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         ERROR err;
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        cdrom_disc_t disc = cdrom_wrap_magic( CDROM_DISC_XA, wrap_name, &err );
-        if( disc == NULL )
-            ERROR(err.msg);
-        else {
-            gdrom_mount_disc(disc);
-            if( !no_start ) {
-                start_immediately = TRUE;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        lxdream_file_type_t type = file_identify(argv[optind], -1, &err);
+        if( type == FILE_SAVE_STATE ) {
+            if( have_save ) {
+                ERROR( "Multiple save states given on command-line, ignoring %s", argv[optind] );
+            } else {
+                have_save = dreamcast_load_state(argv[optind]);
+                if( !have_save )
+                    no_start = TRUE;
+            }
+        } else {
+            if( have_disc ) {
+                ERROR( "Multiple GD-ROM discs given on command-line, ignoring %s", argv[optind] );
+            } else {
+                have_disc = gdrom_mount_image(argv[optind], &err);
+                if( !have_disc )
+                    no_start = TRUE;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             }
         }
     }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    for( ; optind < argc; optind++ ) {
-        gboolean ok = gdrom_mount_image(argv[optind]);
-        if( !ok ) {
-            ok = file_load_magic( argv[optind] );
-        }
-        if( !ok ) {
-            ERROR( "Unrecognized file '%s'", argv[optind] );
-        }
-        if( !no_start ) {
-            start_immediately = ok;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( exec_name != NULL ) {
+        ERROR err;
+        if( have_save ) {
+            ERROR( "Both a save state and an executable were specified, ignoring %s", exec_name );
+        } else {
+            have_exec = file_load_exec( exec_name, &err );
+            if( !have_exec )
+                no_start = TRUE;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         }
     }
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( !no_start && (have_exec || have_disc || have_save) ) {
+        start_immediately = TRUE;
+    }
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     if( gdrom_get_current_disc() == NULL ) {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        ERROR err;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         gchar *disc_file = lxdream_get_global_config_path_value( CONFIG_GDROM );
         if( disc_file != NULL ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-            gdrom_mount_image( disc_file );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+            gboolean ok = gdrom_mount_image( disc_file, &err );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             g_free(disc_file);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+            if( !ok ) {
+                WARN( err.msg );
+            }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         }
     }
 
</pre></div>
<hr /><a name="file23" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/test</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>Makefile.in</b></big> <small id="info" style="color: #888888;" >305ef2082079 -> 700c5ab26a63</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/test/Makefile.in
+++ lxdream/test/Makefile.in
@@ -30,8 +30,8 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > ARMLIBS         = -Wl,--start-group -lc -lgcc -lm -Wl,--end-group
 ARMOBJCOPY     = @ARMOBJCOPY@ -O binary
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-RUNTEST            = ../src/lxdream -c $(srcdir)/lxdream.rc -puH -A null
-RUNTESTX       = ../src/lxdream -c $(srcdir)/lxdream.rc -xpuH -A null
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+RUNTEST              = ../src/lxdream -c $(srcdir)/lxdream.rc -puH -A null -e
+RUNTESTX       = ../src/lxdream -c $(srcdir)/lxdream.rc -xpuH -A null -e
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 BUILD_SYSTEST_FALSE = @BUILD_SYSTEST_FALSE@
 BUILD_SYSTEST_TRUE = @BUILD_SYSTEST_TRUE@
</pre></div>
<center><small>Chaos Theory</small></center>
</div></body></html>