<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/src</tt></b></td></tr>
<tr><td><tt>drivers/cdrom/<a href="#file1">cdrom.c</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+75</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-12</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">7b279d10f46f -> 305ef2082079</td></tr>
<tr class="alt" style=";" ><td><tt>             /<a href="#file2">cdrom.h</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+9</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">7b279d10f46f -> 305ef2082079</td></tr>
<tr><td><tt>             /<a href="#file3">isofs.c</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+11</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">7b279d10f46f -> 305ef2082079</td></tr>
<tr class="alt" style=";" ><td><tt>             /<a href="#file4">isofs.h</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+4</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">7b279d10f46f -> 305ef2082079</td></tr>
<tr><td><tt>             /<a href="#file5">sector.c</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">7b279d10f46f -> 305ef2082079</td></tr>
<tr class="alt" style=";" ><td><tt><a href="#file6">loader.c</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+248</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-12</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">7b279d10f46f -> 305ef2082079</td></tr>
<tr><td><tt><a href="#file7">loader.h</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+4</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">7b279d10f46f -> 305ef2082079</td></tr>
<tr class="alt" style=";" ><td><tt><a href="#file8">main.c</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+21</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">7b279d10f46f -> 305ef2082079</td></tr>
<tr><td></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+373</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-27</td><td></td></tr>
</table>
<small id="info" style="color: #888888;" >8 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;" >
Add ability to wrap a binary program up in a virtual cd image (so that we
can boot it normally)
</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/drivers/cdrom</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>cdrom.c</b></big> <small id="info" style="color: #888888;" >7b279d10f46f -> 305ef2082079</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
@@ -24,6 +24,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #include "lxdream.h"
 #include "drivers/cdrom/cdrom.h"
 #include "drivers/cdrom/cdimpl.h"
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#include "drivers/cdrom/isofs.h"
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 extern struct cdrom_disc_factory linux_cdrom_drive_factory;
 extern struct cdrom_disc_factory nrg_disc_factory;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -193,20 +194,24 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 gboolean cdrom_disc_read_toc( cdrom_disc_t disc, ERROR *err )
 {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    /* First set the defaults for an empty disc */
-    cdrom_disc_clear_toc(disc);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( disc->read_toc != NULL ) {
+        /* First set the defaults for an empty disc */
+        cdrom_disc_clear_toc(disc);
</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( disc->read_toc(disc, err ) ) {
-        /* Success - update disc type and leadout if the TOC read didn't set them */
-        if( disc->disc_type == CDROM_DISC_NONE )
-            cdrom_disc_set_default_disc_type(disc);
-        cdrom_disc_compute_leadout(disc);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        if( disc->read_toc(disc, err ) ) {
+            /* Success - update disc type and leadout if the TOC read didn't set them */
+            if( disc->disc_type == CDROM_DISC_NONE )
+                cdrom_disc_set_default_disc_type(disc);
+            cdrom_disc_compute_leadout(disc);
+            return TRUE;
+        } else {
+            /* Reset to an empty disc in case the reader left things in an
+             * inconsistent state */
+            cdrom_disc_clear_toc(disc);
+            return FALSE;
+        }
+    } else {
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return TRUE;
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    } else {
-        /* Reset to an empty disc in case the reader left things in an
-         * inconsistent state */
-        cdrom_disc_clear_toc(disc);
-        return FALSE;
</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;" >@@ -273,6 +278,64 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 
 /**
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ * Construct a disc around a source track.
+ * @param type Disc type, which must be compatible with the track mode
+ * @param track The source of data for the main track
+ * @param lba The position on disc of the main track. If non-zero,
+ * a filler track is added before it, in 2 separate sessions.
+ */
+cdrom_disc_t cdrom_disc_new_from_track( cdrom_disc_type_t type, sector_source_t track, cdrom_lba_t lba )
+{
+    cdrom_disc_t disc = cdrom_disc_new( NULL, NULL );
+    if( disc != NULL ) {
+        disc->disc_type = type;
+        int trackno = 0;
+        if( lba != 0 ) {
+            cdrom_count_t size = lba - 150;
+            if( lba < 150 )
+                size = lba;
+            disc->track[0].trackno = 1;
+            disc->track[0].sessionno = 1;
+            disc->track[0].lba = 0;
+            disc->track[0].flags = 0;
+            disc->track[0].source = null_sector_source_new( SECTOR_CDDA, size );
+            sector_source_ref( disc->track[0].source );
+            trackno++;
+        }
+        disc->track[trackno].trackno = trackno+1;
+        disc->track[trackno].sessionno = trackno+1;
+        disc->track[trackno].lba = lba;
+        disc->track[trackno].flags = (track->mode == SECTOR_CDDA ? 0 : TRACK_FLAG_DATA);
+        disc->track[trackno].source = track;
+        sector_source_ref(track);
+
+        disc->track_count = trackno+1;
+        disc->session_count = trackno+1;
+        cdrom_disc_compute_leadout(disc);
+    }
+    return disc;
+}
+
+/**
+ * Construct a disc around an IsoImage track (convenience function)
+ */
+cdrom_disc_t cdrom_disc_new_from_iso_image( cdrom_disc_type_t type, IsoImage *iso, cdrom_lba_t lba,
+                                            const char *bootstrap, ERROR *err )
+{
+    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 ) {
+        cdrom_disc_t disc = cdrom_disc_new_from_track(type, source, lba);
+        if( disc == NULL ) {
+            sector_source_unref( source );
+        } else {
+            return disc;
+        }
+    }
+    return NULL;
+}
+
+/**
</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,
  * return NULL;
  */
</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/drivers/cdrom</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>cdrom.h</b></big> <small id="info" style="color: #888888;" >7b279d10f46f -> 305ef2082079</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
@@ -97,6 +97,15 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > cdrom_disc_t cdrom_disc_open( const char *filename, ERROR *err );
 
 /**
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ * Construct a disc around a source track.
+ * @param type Disc type, which must be compatible with the track mode
+ * @param track The source of data for the main track
+ * @param lba The position on disc of the main track. If non-zero,
+ * a filler track is added before it, in 2 separate sessions.
+ */
+cdrom_disc_t cdrom_disc_new_from_track( cdrom_disc_type_t type, sector_source_t track, cdrom_lba_t lba );
+
+/**
</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,
  * return NULL;
  */
</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/drivers/cdrom</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>isofs.c</b></big> <small id="info" style="color: #888888;" >7b279d10f46f -> 305ef2082079</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
@@ -17,6 +17,8 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  */
 
 #include <assert.h>
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#include <stdio.h>
+#include <unistd.h>
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #include <glib/gmem.h>
 
 #define LIBISOFS_WITHOUT_LIBBURN 1
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -169,8 +171,15 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     char buf[2048];
     cdrom_count_t expect = size/2048;
     cdrom_count_t count = 0;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    int fd = file_sector_source_get_fd(source);
+    source->size = expect;
+    lseek( fd, 0, SEEK_SET );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     for( cdrom_count_t count = 0; count < expect; count++ ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        status = burn->read(burn, buf, 2048);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        if( burn->read == NULL ) {
+            status = burn->read_xt(burn, buf, 2048);
+        } else {
+            status = burn->read(burn, buf, 2048);
+        }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         if( status == 0 ) {
             /* EOF */
             break;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -180,6 +189,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             source = NULL;
             break;
         }
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        write( fd, buf, 2048 );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
     burn->free_data(burn);
     free(burn);
</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>isofs.h</b></big> <small id="info" style="color: #888888;" >7b279d10f46f -> 305ef2082079</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/drivers/cdrom/isofs.h
+++ lxdream/src/drivers/cdrom/isofs.h
@@ -55,4 +55,8 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > sector_source_t iso_sector_source_new( IsoImage *image, sector_mode_t mode, cdrom_lba_t start_sector,
                                        const char *bootstrap, ERROR *err );
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+
+/** Prototypes for "Internal" Libisofs functions */
+int iso_memory_stream_new(unsigned char *buf, size_t size, IsoStream **stream);
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #endif /* !cdrom_isofs_H */
</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>sector.c</b></big> <small id="info" style="color: #888888;" >7b279d10f46f -> 305ef2082079</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/drivers/cdrom/sector.c
+++ lxdream/src/drivers/cdrom/sector.c
@@ -608,6 +608,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     dev->filename = tempfile;
     sector_source_t source = sector_source_init( &dev->file.dev, FILE_SECTOR_SOURCE, mode, 0, file_sector_source_read, tmpfile_sector_source_destroy );
     tmpfile_open_list = g_list_append(tmpfile_open_list, source);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    return source;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 
 /************************ Memory device implementation *************************/
</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</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>loader.c</b></big> <small id="info" style="color: #888888;" >7b279d10f46f -> 305ef2082079</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/loader.c
+++ lxdream/src/loader.c
@@ -2,7 +2,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  * $Id$
  *
  * File loading routines, mostly for loading demos without going through the
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >- * whole procedure of making a CD image for them.
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ * whole procedure of ma<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >nually ma</span>king a CD image for them.
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  *
  * Copyright (c) 2005 Nathan Keynes.
  *
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -24,24 +24,63 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #include <sys/stat.h>
 #include <errno.h>
 #include <stdint.h>
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#include <glib/gstrfuncs.h>
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #include <elf.h>
 #include "mem.h"
 #include "bootstrap.h"
 #include "dreamcast.h"
 #include "config.h"
 #include "loader.h"
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#include "drivers/cdrom/cdrom.h"
+#include "drivers/cdrom/isofs.h"
</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 bootstrap_magic[32] = "SEGA SEGAKATANA SEGA ENTERPRISES";
-char iso_magic[6] = "\001CD001";
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+const char bootstrap_magic[32] = "SEGA SEGAKATANA SEGA ENTERPRISES";
+const char iso_magic[6] = "\001CD001";
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > char *file_loader_extensions[][2] = { 
         { "sbi", "Self Boot Inducer" },
         { "bin", "SH4 Bin file" },
         { NULL, NULL } };
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-#define CDI_V2 0x80000004
-#define CDI_V3 0x80000005
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+gboolean file_load_elf_fd( const gchar *filename, int fd );
</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_fd( const gchar *filename, int fd );
</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,
+} lxdream_file_type_t;
+
+static lxdream_file_type_t file_magic( const gchar *filename, int fd, ERROR *err )
+{
+    char buf[32];
+
+    /* begin magic */
+    if( read( fd, buf, 32 ) != 32 ) {
+        SET_ERROR( err, errno, "Unable to read from file '%s'", filename );
+        return FILE_ERROR;
+
+    }
+
+    lseek( fd, 0, SEEK_SET );
+    if( buf[0] == 0x7F && buf[1] == 'E' &&
+            buf[2] == 'L' && buf[3] == 'F' ) {
+        return FILE_ELF;
+    } else if( memcmp( buf, "PK\x03\x04", 4 ) == 0 ) {
+        return FILE_ZIP;
+    } else if( memcmp( buf, DREAMCAST_SAVE_MAGIC, 16 ) == 0 ) {
+        return FILE_SAVE_STATE;
+    } else if( lseek( fd, 32768, SEEK_SET ) == 32768 &&
+            read( fd, buf, 8 ) == 8 &&
+            memcmp( buf, iso_magic, 6) == 0 ) {
+        lseek( fd, 0, SEEK_SET );
+        return FILE_ISO;
+    }
+    lseek( fd, 0, SEEK_SET );
+    return FILE_BINARY;
+}
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 
 gboolean file_load_magic( const gchar *filename )
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -128,6 +167,26 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 }
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+gboolean is_sh4_elf( Elf32_Ehdr *head )
+{
+    return ( head->e_ident[EI_CLASS] == ELFCLASS32 &&
+            head->e_ident[EI_DATA] == ELFDATA2LSB &&
+            head->e_ident[EI_VERSION] == 1 &&
+            head->e_type == ET_EXEC &&
+            head->e_machine == EM_SH &&
+            head->e_version == 1 );
+}
+
+gboolean is_arm_elf( Elf32_Ehdr *head )
+{
+    return ( head->e_ident[EI_CLASS] == ELFCLASS32 &&
+            head->e_ident[EI_DATA] == ELFDATA2LSB &&
+            head->e_ident[EI_VERSION] == 1 &&
+            head->e_type == ET_EXEC &&
+            head->e_machine == EM_ARM &&
+            head->e_version == 1 );
+}
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > gboolean file_load_elf_fd( const gchar *filename, int fd ) 
 {
     Elf32_Ehdr head;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -136,12 +195,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
     if( read( fd, &head, sizeof(head) ) != sizeof(head) )
         return FALSE;
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    if( head.e_ident[EI_CLASS] != ELFCLASS32 ||
-            head.e_ident[EI_DATA] != ELFDATA2LSB ||
-            head.e_ident[EI_VERSION] != 1 ||
-            head.e_type != ET_EXEC ||
-            head.e_machine != EM_SH ||
-            head.e_version != 1 ) {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( !is_sh4_elf(&head) ) {
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         ERROR( "File is not an SH4 ELF executable file" );
         return FALSE;
     }
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -164,3 +218,185 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     file_load_postload( filename, head.e_entry );
     return TRUE;
 }
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+
+/**
+ * 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
+ * @param bin The binary data (takes ownership)
+ * @param bin_size
+ */
+cdrom_disc_t cdrom_disc_new_wrapped_binary( cdrom_disc_type_t type, const gchar *filename, unsigned char *bin, size_t bin_size,
+                                            ERROR *err )
+{
+    IsoImage *iso = NULL;
+    unsigned char *data = bin;
+    cdrom_lba_t start_lba = 45000; /* GDROM_START */
+    char bootstrap[32768];
+
+    /* 1. Load in the bootstrap */
+    gchar *bootstrap_file = lxdream_get_global_config_path_value(CONFIG_BOOTSTRAP);
+    if( bootstrap_file == NULL || bootstrap_file[0] == '\0' ) {
+        g_free(data);
+        SET_ERROR( err, ENOENT, "Unable to create CD image: bootstrap file is not configured" );
+        return NULL;
+    }
+
+    FILE *f = fopen( bootstrap_file, "ro" );
+    if( f == NULL ) {
+        g_free(data);
+        SET_ERROR( err, errno, "Unable to create CD image: bootstrap file '%s' could not be opened", bootstrap_file );
+        return FALSE;
+    }
+    size_t len = fread( bootstrap, 1, 32768, f );
+    fclose(f);
+    if( len != 32768 ) {
+        g_free(data);
+        SET_ERROR( err, EINVAL, "Unable to create CD image: bootstrap file '%s' is invalid", bootstrap_file );
+        return FALSE;
+    }
+
+    /* 2. Scramble the binary if necessary (and set type settings) */
+    if( type != CDROM_DISC_GDROM ) {
+        /* scramble the binary if we're going the MIL-CD route */
+        unsigned char *scramblebin = g_malloc(bin_size);
+        bootprogram_scramble( scramblebin, bin, bin_size );
+        data = scramblebin;
+        start_lba = 0x2DB6; /* CDROM_START (does it matter?) */
+        g_free(bin);
+    }
+
+    /* 3. Frob the bootstrap data */
+    dc_bootstrap_head_t boot_header = (dc_bootstrap_head_t)bootstrap;
+    memcpy( boot_header->boot_file, "1ST_READ.BIN    ", 16 );
+    char tmp[129];
+    int name_len = snprintf( tmp, 129, "lxdream wrapped image: %s", filename );
+    if( name_len < 128 )
+        memset( tmp+name_len, ' ', 128-name_len );
+    memcpy( boot_header->product_name, tmp, 128 );
+//    bootstrap_update_crc(bootstrap);
+
+
+    /* 4. Build the ISO image */
+    int status = iso_image_new("autocd", &iso);
+    if( status != 1 ) {
+        g_free(data);
+        return NULL;
+    }
+
+    IsoStream *stream;
+    if( iso_memory_stream_new(data, bin_size, &stream) != 1 ) {
+        g_free(data);
+        iso_image_unref(iso);
+        return NULL;
+    }
+    iso_tree_add_new_file(iso_image_get_root(iso), "1ST_READ.BIN", stream, NULL);
+    sector_source_t track = iso_sector_source_new( iso, SECTOR_MODE2_FORM1, start_lba,
+            bootstrap, err );
+    if( track == NULL ) {
+        iso_image_unref(iso);
+        return NULL;
+    }
+
+    cdrom_disc_t disc = cdrom_disc_new_from_track( type, track, start_lba );
+    iso_image_unref(iso);
+    if( disc != NULL ) {
+        disc->name = g_strdup(filename);
+    }
+    return disc;
+}
+
+cdrom_disc_t cdrom_wrap_elf_fd( cdrom_disc_type_t type, const gchar *filename, int fd, ERROR *err )
+{
+    Elf32_Ehdr head;
+    int i;
+
+    /* Check the file header is actually an SH4 binary */
+    if( read( fd, &head, sizeof(head) ) != sizeof(head) )
+        return FALSE;
+    if( !is_sh4_elf(&head) ) {
+        SET_ERROR( err, EINVAL, "File is not an SH4 ELF executable file" );
+        return FALSE;
+    }
+    if( head.e_entry != BINARY_LOAD_ADDR ) {
+        SET_ERROR( err, EINVAL, "SH4 Binary has incorrect entry point (should be %08X but is %08X)", BINARY_LOAD_ADDR, head.e_entry );
+        return FALSE;
+    }
+
+    /* Load the program headers */
+    Elf32_Phdr phdr[head.e_phnum];
+    lseek( fd, head.e_phoff, SEEK_SET );
+    if( read( fd, phdr, sizeof(phdr) ) != sizeof(phdr) ) {
+        SET_ERROR( err, EINVAL, "File is not a valid executable file" );
+        return FALSE;
+    }
+
+    sh4addr_t start = (sh4addr_t)-1, end=0;
+    /* Scan program headers for memory range in use */
+    for( i=0; i<head.e_phnum; i++ ) {
+        if( phdr[i].p_type == PT_LOAD ) {
+            if( phdr[i].p_vaddr < start )
+                start = phdr[i].p_vaddr;
+            if( phdr[i].p_vaddr + phdr[i].p_memsz > end )
+                end = phdr[i].p_vaddr + phdr[i].p_memsz;
+        }
+    }
+
+    if( start != BINARY_LOAD_ADDR ) {
+        SET_ERROR( err, EINVAL, "SH4 Binary has incorrect load address (should be %08X but is %08X)", BINARY_LOAD_ADDR, start );
+        return FALSE;
+    }
+    if( end >= 0x8D000000 ) {
+        SET_ERROR( err, EINVAL, "SH4 binary is too large to fit in memory (end address is %08X)", end );
+        return FALSE;
+    }
+
+    /* Load the program into memory */
+    char *program = g_malloc0( end-start );
+    for( i=0; i<head.e_phnum; i++ ) {
+        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);
+            read( fd, program + phdr[i].p_vaddr, size );
+        }
+    }
+
+    /* And finally pass it over to the disc wrapper */
+    return cdrom_disc_new_wrapped_binary(type, filename, program, end-start, err );
+}
+
+cdrom_disc_t cdrom_wrap_magic( cdrom_disc_type_t type, const gchar *filename, ERROR *err )
+{
+    cdrom_disc_t disc;
+    char *data;
+    int len;
+    struct stat st;
+    int fd = open( filename, O_RDONLY );
+    if( fd == -1 ) {
+        SET_ERROR( err, errno, "Unable to open file '%s'", filename );
+        return NULL;
+    }
+
+
+    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 );
+        return NULL;
+    }
+
+}
</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</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>loader.h</b></big> <small id="info" style="color: #888888;" >7b279d10f46f -> 305ef2082079</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/loader.h
+++ lxdream/src/loader.h
@@ -22,6 +22,8 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #include <stdio.h>
 #include <glib/gtypes.h>
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#include "drivers/cdrom/cdrom.h"
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #ifdef __cplusplus
 extern "C" {
 #endif
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -64,6 +66,8 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  */
 gboolean file_load_magic( const gchar *filename );
 
</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 );
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #ifdef __cplusplus
 }
 #endif
</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</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>main.c</b></big> <small id="info" style="color: #888888;" >7b279d10f46f -> 305ef2082079</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,13 @@
</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:x?";
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+char *option_list = "a:A:bc:dfg:G:hHl:m:npt:T:uvV:<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >w:</span>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' },
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        { "debugger", no_argument, NULL, '<span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >D</span>' },
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        { "debugger", no_argument, NULL, '<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >d</span>' },
</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,6 +61,7 @@
</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="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        { "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;" >@@ -107,6 +108,7 @@
</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="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    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,6 +126,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     double t;
     gboolean display_ok;
     uint32_t time_secs, time_nanos;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    const char *wrap_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;" >@@ -200,6 +203,9 @@
</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="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        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;" >@@ -262,6 +268,19 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     maple_reattach_all();
     INFO( "%s! ready...", APP_NAME );
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( wrap_name != NULL ) {
+        ERROR err;
+        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="context" class="diff" style="margin:0; background-color:#eeeeee;" >     for( ; optind < argc; optind++ ) {
         gboolean ok = gdrom_mount_image(argv[optind]);
         if( !ok ) {
</pre></div>
<center><small>Chaos Theory</small></center>
</div></body></html>