revision 1108:305ef2082079
summary |
tree |
shortlog |
changelog |
graph |
changeset |
raw | bz2 | zip | gz changeset | 1108:305ef2082079 |
parent | 1107:7b279d10f46f |
child | 1109:700c5ab26a63 |
author | nkeynes |
date | Fri Jun 04 09:13:40 2010 +1000 (13 years ago) |
Add ability to wrap a binary program up in a virtual cd image (so that we
can boot it normally)
can boot it normally)
1.1 --- a/src/drivers/cdrom/cdrom.c Mon May 17 22:01:23 2010 +10001.2 +++ b/src/drivers/cdrom/cdrom.c Fri Jun 04 09:13:40 2010 +10001.3 @@ -24,6 +24,7 @@1.4 #include "lxdream.h"1.5 #include "drivers/cdrom/cdrom.h"1.6 #include "drivers/cdrom/cdimpl.h"1.7 +#include "drivers/cdrom/isofs.h"1.9 extern struct cdrom_disc_factory linux_cdrom_drive_factory;1.10 extern struct cdrom_disc_factory nrg_disc_factory;1.11 @@ -193,20 +194,24 @@1.13 gboolean cdrom_disc_read_toc( cdrom_disc_t disc, ERROR *err )1.14 {1.15 - /* First set the defaults for an empty disc */1.16 - cdrom_disc_clear_toc(disc);1.17 + if( disc->read_toc != NULL ) {1.18 + /* First set the defaults for an empty disc */1.19 + cdrom_disc_clear_toc(disc);1.21 - if( disc->read_toc(disc, err ) ) {1.22 - /* Success - update disc type and leadout if the TOC read didn't set them */1.23 - if( disc->disc_type == CDROM_DISC_NONE )1.24 - cdrom_disc_set_default_disc_type(disc);1.25 - cdrom_disc_compute_leadout(disc);1.26 + if( disc->read_toc(disc, err ) ) {1.27 + /* Success - update disc type and leadout if the TOC read didn't set them */1.28 + if( disc->disc_type == CDROM_DISC_NONE )1.29 + cdrom_disc_set_default_disc_type(disc);1.30 + cdrom_disc_compute_leadout(disc);1.31 + return TRUE;1.32 + } else {1.33 + /* Reset to an empty disc in case the reader left things in an1.34 + * inconsistent state */1.35 + cdrom_disc_clear_toc(disc);1.36 + return FALSE;1.37 + }1.38 + } else {1.39 return TRUE;1.40 - } else {1.41 - /* Reset to an empty disc in case the reader left things in an1.42 - * inconsistent state */1.43 - cdrom_disc_clear_toc(disc);1.44 - return FALSE;1.45 }1.46 }1.48 @@ -273,6 +278,64 @@1.49 }1.51 /**1.52 + * Construct a disc around a source track.1.53 + * @param type Disc type, which must be compatible with the track mode1.54 + * @param track The source of data for the main track1.55 + * @param lba The position on disc of the main track. If non-zero,1.56 + * a filler track is added before it, in 2 separate sessions.1.57 + */1.58 +cdrom_disc_t cdrom_disc_new_from_track( cdrom_disc_type_t type, sector_source_t track, cdrom_lba_t lba )1.59 +{1.60 + cdrom_disc_t disc = cdrom_disc_new( NULL, NULL );1.61 + if( disc != NULL ) {1.62 + disc->disc_type = type;1.63 + int trackno = 0;1.64 + if( lba != 0 ) {1.65 + cdrom_count_t size = lba - 150;1.66 + if( lba < 150 )1.67 + size = lba;1.68 + disc->track[0].trackno = 1;1.69 + disc->track[0].sessionno = 1;1.70 + disc->track[0].lba = 0;1.71 + disc->track[0].flags = 0;1.72 + disc->track[0].source = null_sector_source_new( SECTOR_CDDA, size );1.73 + sector_source_ref( disc->track[0].source );1.74 + trackno++;1.75 + }1.76 + disc->track[trackno].trackno = trackno+1;1.77 + disc->track[trackno].sessionno = trackno+1;1.78 + disc->track[trackno].lba = lba;1.79 + disc->track[trackno].flags = (track->mode == SECTOR_CDDA ? 0 : TRACK_FLAG_DATA);1.80 + disc->track[trackno].source = track;1.81 + sector_source_ref(track);1.82 +1.83 + disc->track_count = trackno+1;1.84 + disc->session_count = trackno+1;1.85 + cdrom_disc_compute_leadout(disc);1.86 + }1.87 + return disc;1.88 +}1.89 +1.90 +/**1.91 + * Construct a disc around an IsoImage track (convenience function)1.92 + */1.93 +cdrom_disc_t cdrom_disc_new_from_iso_image( cdrom_disc_type_t type, IsoImage *iso, cdrom_lba_t lba,1.94 + const char *bootstrap, ERROR *err )1.95 +{1.96 + sector_mode_t mode = (type == CDROM_DISC_NONXA ? SECTOR_MODE1 : SECTOR_MODE2_FORM1 );1.97 + sector_source_t source = iso_sector_source_new( iso, mode, lba, bootstrap, err );1.98 + if( source != NULL ) {1.99 + cdrom_disc_t disc = cdrom_disc_new_from_track(type, source, lba);1.100 + if( disc == NULL ) {1.101 + sector_source_unref( source );1.102 + } else {1.103 + return disc;1.104 + }1.105 + }1.106 + return NULL;1.107 +}1.108 +1.109 +/**1.110 * Get the track information for the given track. If there is no such track,1.111 * return NULL;1.112 */
2.1 --- a/src/drivers/cdrom/cdrom.h Mon May 17 22:01:23 2010 +10002.2 +++ b/src/drivers/cdrom/cdrom.h Fri Jun 04 09:13:40 2010 +10002.3 @@ -97,6 +97,15 @@2.4 cdrom_disc_t cdrom_disc_open( const char *filename, ERROR *err );2.6 /**2.7 + * Construct a disc around a source track.2.8 + * @param type Disc type, which must be compatible with the track mode2.9 + * @param track The source of data for the main track2.10 + * @param lba The position on disc of the main track. If non-zero,2.11 + * a filler track is added before it, in 2 separate sessions.2.12 + */2.13 +cdrom_disc_t cdrom_disc_new_from_track( cdrom_disc_type_t type, sector_source_t track, cdrom_lba_t lba );2.14 +2.15 +/**2.16 * Get the track information for the given track. If there is no such track,2.17 * return NULL;2.18 */
3.1 --- a/src/drivers/cdrom/isofs.c Mon May 17 22:01:23 2010 +10003.2 +++ b/src/drivers/cdrom/isofs.c Fri Jun 04 09:13:40 2010 +10003.3 @@ -17,6 +17,8 @@3.4 */3.6 #include <assert.h>3.7 +#include <stdio.h>3.8 +#include <unistd.h>3.9 #include <glib/gmem.h>3.11 #define LIBISOFS_WITHOUT_LIBBURN 13.12 @@ -169,8 +171,15 @@3.13 char buf[2048];3.14 cdrom_count_t expect = size/2048;3.15 cdrom_count_t count = 0;3.16 + int fd = file_sector_source_get_fd(source);3.17 + source->size = expect;3.18 + lseek( fd, 0, SEEK_SET );3.19 for( cdrom_count_t count = 0; count < expect; count++ ) {3.20 - status = burn->read(burn, buf, 2048);3.21 + if( burn->read == NULL ) {3.22 + status = burn->read_xt(burn, buf, 2048);3.23 + } else {3.24 + status = burn->read(burn, buf, 2048);3.25 + }3.26 if( status == 0 ) {3.27 /* EOF */3.28 break;3.29 @@ -180,6 +189,7 @@3.30 source = NULL;3.31 break;3.32 }3.33 + write( fd, buf, 2048 );3.34 }3.35 burn->free_data(burn);3.36 free(burn);
4.1 --- a/src/drivers/cdrom/isofs.h Mon May 17 22:01:23 2010 +10004.2 +++ b/src/drivers/cdrom/isofs.h Fri Jun 04 09:13:40 2010 +10004.3 @@ -55,4 +55,8 @@4.4 sector_source_t iso_sector_source_new( IsoImage *image, sector_mode_t mode, cdrom_lba_t start_sector,4.5 const char *bootstrap, ERROR *err );4.7 +4.8 +/** Prototypes for "Internal" Libisofs functions */4.9 +int iso_memory_stream_new(unsigned char *buf, size_t size, IsoStream **stream);4.10 +4.11 #endif /* !cdrom_isofs_H */
5.1 --- a/src/drivers/cdrom/sector.c Mon May 17 22:01:23 2010 +10005.2 +++ b/src/drivers/cdrom/sector.c Fri Jun 04 09:13:40 2010 +10005.3 @@ -608,6 +608,7 @@5.4 dev->filename = tempfile;5.5 sector_source_t source = sector_source_init( &dev->file.dev, FILE_SECTOR_SOURCE, mode, 0, file_sector_source_read, tmpfile_sector_source_destroy );5.6 tmpfile_open_list = g_list_append(tmpfile_open_list, source);5.7 + return source;5.8 }5.10 /************************ Memory device implementation *************************/
6.1 --- a/src/loader.c Mon May 17 22:01:23 2010 +10006.2 +++ b/src/loader.c Fri Jun 04 09:13:40 2010 +10006.3 @@ -2,7 +2,7 @@6.4 * $Id$6.5 *6.6 * File loading routines, mostly for loading demos without going through the6.7 - * whole procedure of making a CD image for them.6.8 + * whole procedure of manually making a CD image for them.6.9 *6.10 * Copyright (c) 2005 Nathan Keynes.6.11 *6.12 @@ -24,24 +24,63 @@6.13 #include <sys/stat.h>6.14 #include <errno.h>6.15 #include <stdint.h>6.16 +#include <glib/gstrfuncs.h>6.17 #include <elf.h>6.18 #include "mem.h"6.19 #include "bootstrap.h"6.20 #include "dreamcast.h"6.21 #include "config.h"6.22 #include "loader.h"6.23 +#include "drivers/cdrom/cdrom.h"6.24 +#include "drivers/cdrom/isofs.h"6.26 -char bootstrap_magic[32] = "SEGA SEGAKATANA SEGA ENTERPRISES";6.27 -char iso_magic[6] = "\001CD001";6.28 +const char bootstrap_magic[32] = "SEGA SEGAKATANA SEGA ENTERPRISES";6.29 +const char iso_magic[6] = "\001CD001";6.30 char *file_loader_extensions[][2] = {6.31 { "sbi", "Self Boot Inducer" },6.32 { "bin", "SH4 Bin file" },6.33 { NULL, NULL } };6.35 -#define CDI_V2 0x800000046.36 -#define CDI_V3 0x800000056.37 +gboolean file_load_elf_fd( const gchar *filename, int fd );6.39 -gboolean file_load_elf_fd( const gchar *filename, int fd );6.40 +typedef enum {6.41 + FILE_ERROR,6.42 + FILE_BINARY,6.43 + FILE_ELF,6.44 + FILE_ISO,6.45 + FILE_DISC,6.46 + FILE_ZIP,6.47 + FILE_SAVE_STATE,6.48 +} lxdream_file_type_t;6.49 +6.50 +static lxdream_file_type_t file_magic( const gchar *filename, int fd, ERROR *err )6.51 +{6.52 + char buf[32];6.53 +6.54 + /* begin magic */6.55 + if( read( fd, buf, 32 ) != 32 ) {6.56 + SET_ERROR( err, errno, "Unable to read from file '%s'", filename );6.57 + return FILE_ERROR;6.58 +6.59 + }6.60 +6.61 + lseek( fd, 0, SEEK_SET );6.62 + if( buf[0] == 0x7F && buf[1] == 'E' &&6.63 + buf[2] == 'L' && buf[3] == 'F' ) {6.64 + return FILE_ELF;6.65 + } else if( memcmp( buf, "PK\x03\x04", 4 ) == 0 ) {6.66 + return FILE_ZIP;6.67 + } else if( memcmp( buf, DREAMCAST_SAVE_MAGIC, 16 ) == 0 ) {6.68 + return FILE_SAVE_STATE;6.69 + } else if( lseek( fd, 32768, SEEK_SET ) == 32768 &&6.70 + read( fd, buf, 8 ) == 8 &&6.71 + memcmp( buf, iso_magic, 6) == 0 ) {6.72 + lseek( fd, 0, SEEK_SET );6.73 + return FILE_ISO;6.74 + }6.75 + lseek( fd, 0, SEEK_SET );6.76 + return FILE_BINARY;6.77 +}6.80 gboolean file_load_magic( const gchar *filename )6.81 @@ -128,6 +167,26 @@6.82 }6.83 }6.85 +gboolean is_sh4_elf( Elf32_Ehdr *head )6.86 +{6.87 + return ( head->e_ident[EI_CLASS] == ELFCLASS32 &&6.88 + head->e_ident[EI_DATA] == ELFDATA2LSB &&6.89 + head->e_ident[EI_VERSION] == 1 &&6.90 + head->e_type == ET_EXEC &&6.91 + head->e_machine == EM_SH &&6.92 + head->e_version == 1 );6.93 +}6.94 +6.95 +gboolean is_arm_elf( Elf32_Ehdr *head )6.96 +{6.97 + return ( head->e_ident[EI_CLASS] == ELFCLASS32 &&6.98 + head->e_ident[EI_DATA] == ELFDATA2LSB &&6.99 + head->e_ident[EI_VERSION] == 1 &&6.100 + head->e_type == ET_EXEC &&6.101 + head->e_machine == EM_ARM &&6.102 + head->e_version == 1 );6.103 +}6.104 +6.105 gboolean file_load_elf_fd( const gchar *filename, int fd )6.106 {6.107 Elf32_Ehdr head;6.108 @@ -136,12 +195,7 @@6.110 if( read( fd, &head, sizeof(head) ) != sizeof(head) )6.111 return FALSE;6.112 - if( head.e_ident[EI_CLASS] != ELFCLASS32 ||6.113 - head.e_ident[EI_DATA] != ELFDATA2LSB ||6.114 - head.e_ident[EI_VERSION] != 1 ||6.115 - head.e_type != ET_EXEC ||6.116 - head.e_machine != EM_SH ||6.117 - head.e_version != 1 ) {6.118 + if( !is_sh4_elf(&head) ) {6.119 ERROR( "File is not an SH4 ELF executable file" );6.120 return FALSE;6.121 }6.122 @@ -164,3 +218,185 @@6.123 file_load_postload( filename, head.e_entry );6.124 return TRUE;6.125 }6.126 +6.127 +/**6.128 + * Create a new CDROM disc containing a single 1ST_READ.BIN.6.129 + * @param type The disc type - must be CDROM_DISC_GDROM or CDROM_DISC_XA6.130 + * @param bin The binary data (takes ownership)6.131 + * @param bin_size6.132 + */6.133 +cdrom_disc_t cdrom_disc_new_wrapped_binary( cdrom_disc_type_t type, const gchar *filename, unsigned char *bin, size_t bin_size,6.134 + ERROR *err )6.135 +{6.136 + IsoImage *iso = NULL;6.137 + unsigned char *data = bin;6.138 + cdrom_lba_t start_lba = 45000; /* GDROM_START */6.139 + char bootstrap[32768];6.140 +6.141 + /* 1. Load in the bootstrap */6.142 + gchar *bootstrap_file = lxdream_get_global_config_path_value(CONFIG_BOOTSTRAP);6.143 + if( bootstrap_file == NULL || bootstrap_file[0] == '\0' ) {6.144 + g_free(data);6.145 + SET_ERROR( err, ENOENT, "Unable to create CD image: bootstrap file is not configured" );6.146 + return NULL;6.147 + }6.148 +6.149 + FILE *f = fopen( bootstrap_file, "ro" );6.150 + if( f == NULL ) {6.151 + g_free(data);6.152 + SET_ERROR( err, errno, "Unable to create CD image: bootstrap file '%s' could not be opened", bootstrap_file );6.153 + return FALSE;6.154 + }6.155 + size_t len = fread( bootstrap, 1, 32768, f );6.156 + fclose(f);6.157 + if( len != 32768 ) {6.158 + g_free(data);6.159 + SET_ERROR( err, EINVAL, "Unable to create CD image: bootstrap file '%s' is invalid", bootstrap_file );6.160 + return FALSE;6.161 + }6.162 +6.163 + /* 2. Scramble the binary if necessary (and set type settings) */6.164 + if( type != CDROM_DISC_GDROM ) {6.165 + /* scramble the binary if we're going the MIL-CD route */6.166 + unsigned char *scramblebin = g_malloc(bin_size);6.167 + bootprogram_scramble( scramblebin, bin, bin_size );6.168 + data = scramblebin;6.169 + start_lba = 0x2DB6; /* CDROM_START (does it matter?) */6.170 + g_free(bin);6.171 + }6.172 +6.173 + /* 3. Frob the bootstrap data */6.174 + dc_bootstrap_head_t boot_header = (dc_bootstrap_head_t)bootstrap;6.175 + memcpy( boot_header->boot_file, "1ST_READ.BIN ", 16 );6.176 + char tmp[129];6.177 + int name_len = snprintf( tmp, 129, "lxdream wrapped image: %s", filename );6.178 + if( name_len < 128 )6.179 + memset( tmp+name_len, ' ', 128-name_len );6.180 + memcpy( boot_header->product_name, tmp, 128 );6.181 +// bootstrap_update_crc(bootstrap);6.182 +6.183 +6.184 + /* 4. Build the ISO image */6.185 + int status = iso_image_new("autocd", &iso);6.186 + if( status != 1 ) {6.187 + g_free(data);6.188 + return NULL;6.189 + }6.190 +6.191 + IsoStream *stream;6.192 + if( iso_memory_stream_new(data, bin_size, &stream) != 1 ) {6.193 + g_free(data);6.194 + iso_image_unref(iso);6.195 + return NULL;6.196 + }6.197 + iso_tree_add_new_file(iso_image_get_root(iso), "1ST_READ.BIN", stream, NULL);6.198 + sector_source_t track = iso_sector_source_new( iso, SECTOR_MODE2_FORM1, start_lba,6.199 + bootstrap, err );6.200 + if( track == NULL ) {6.201 + iso_image_unref(iso);6.202 + return NULL;6.203 + }6.204 +6.205 + cdrom_disc_t disc = cdrom_disc_new_from_track( type, track, start_lba );6.206 + iso_image_unref(iso);6.207 + if( disc != NULL ) {6.208 + disc->name = g_strdup(filename);6.209 + }6.210 + return disc;6.211 +}6.212 +6.213 +cdrom_disc_t cdrom_wrap_elf_fd( cdrom_disc_type_t type, const gchar *filename, int fd, ERROR *err )6.214 +{6.215 + Elf32_Ehdr head;6.216 + int i;6.217 +6.218 + /* Check the file header is actually an SH4 binary */6.219 + if( read( fd, &head, sizeof(head) ) != sizeof(head) )6.220 + return FALSE;6.221 + if( !is_sh4_elf(&head) ) {6.222 + SET_ERROR( err, EINVAL, "File is not an SH4 ELF executable file" );6.223 + return FALSE;6.224 + }6.225 + if( head.e_entry != BINARY_LOAD_ADDR ) {6.226 + SET_ERROR( err, EINVAL, "SH4 Binary has incorrect entry point (should be %08X but is %08X)", BINARY_LOAD_ADDR, head.e_entry );6.227 + return FALSE;6.228 + }6.229 +6.230 + /* Load the program headers */6.231 + Elf32_Phdr phdr[head.e_phnum];6.232 + lseek( fd, head.e_phoff, SEEK_SET );6.233 + if( read( fd, phdr, sizeof(phdr) ) != sizeof(phdr) ) {6.234 + SET_ERROR( err, EINVAL, "File is not a valid executable file" );6.235 + return FALSE;6.236 + }6.237 +6.238 + sh4addr_t start = (sh4addr_t)-1, end=0;6.239 + /* Scan program headers for memory range in use */6.240 + for( i=0; i<head.e_phnum; i++ ) {6.241 + if( phdr[i].p_type == PT_LOAD ) {6.242 + if( phdr[i].p_vaddr < start )6.243 + start = phdr[i].p_vaddr;6.244 + if( phdr[i].p_vaddr + phdr[i].p_memsz > end )6.245 + end = phdr[i].p_vaddr + phdr[i].p_memsz;6.246 + }6.247 + }6.248 +6.249 + if( start != BINARY_LOAD_ADDR ) {6.250 + SET_ERROR( err, EINVAL, "SH4 Binary has incorrect load address (should be %08X but is %08X)", BINARY_LOAD_ADDR, start );6.251 + return FALSE;6.252 + }6.253 + if( end >= 0x8D000000 ) {6.254 + SET_ERROR( err, EINVAL, "SH4 binary is too large to fit in memory (end address is %08X)", end );6.255 + return FALSE;6.256 + }6.257 +6.258 + /* Load the program into memory */6.259 + char *program = g_malloc0( end-start );6.260 + for( i=0; i<head.e_phnum; i++ ) {6.261 + if( phdr[i].p_type == PT_LOAD ) {6.262 + lseek( fd, phdr[i].p_offset, SEEK_SET );6.263 + uint32_t size = MIN( phdr[i].p_filesz, phdr[i].p_memsz);6.264 + read( fd, program + phdr[i].p_vaddr, size );6.265 + }6.266 + }6.267 +6.268 + /* And finally pass it over to the disc wrapper */6.269 + return cdrom_disc_new_wrapped_binary(type, filename, program, end-start, err );6.270 +}6.271 +6.272 +cdrom_disc_t cdrom_wrap_magic( cdrom_disc_type_t type, const gchar *filename, ERROR *err )6.273 +{6.274 + cdrom_disc_t disc;6.275 + char *data;6.276 + int len;6.277 + struct stat st;6.278 + int fd = open( filename, O_RDONLY );6.279 + if( fd == -1 ) {6.280 + SET_ERROR( err, errno, "Unable to open file '%s'", filename );6.281 + return NULL;6.282 + }6.283 +6.284 +6.285 + lxdream_file_type_t filetype = file_magic( filename, fd, err );6.286 + switch( filetype ) {6.287 + case FILE_BINARY:6.288 + fstat( fd, &st );6.289 + data = g_malloc(st.st_size);6.290 + len = read( fd, data, st.st_size );6.291 + close(fd);6.292 + if( len != st.st_size ) {6.293 + SET_ERROR( err, errno, "Error reading binary file '%s'", filename );6.294 + return NULL;6.295 + }6.296 + return cdrom_disc_new_wrapped_binary( type, filename, data, st.st_size, err );6.297 + case FILE_ELF:6.298 + disc = cdrom_wrap_elf_fd(type, filename, fd, err);6.299 + close(fd);6.300 + return disc;6.301 + default:6.302 + close(fd);6.303 + SET_ERROR( err, EINVAL, "File '%s' cannot be wrapped (not a binary)", filename );6.304 + return NULL;6.305 + }6.306 +6.307 +}
7.1 --- a/src/loader.h Mon May 17 22:01:23 2010 +10007.2 +++ b/src/loader.h Fri Jun 04 09:13:40 2010 +10007.3 @@ -22,6 +22,8 @@7.4 #include <stdio.h>7.5 #include <glib/gtypes.h>7.7 +#include "drivers/cdrom/cdrom.h"7.8 +7.9 #ifdef __cplusplus7.10 extern "C" {7.11 #endif7.12 @@ -64,6 +66,8 @@7.13 */7.14 gboolean file_load_magic( const gchar *filename );7.16 +cdrom_disc_t cdrom_wrap_magic( cdrom_disc_type_t type, const gchar *filename, ERROR *err );7.17 +7.18 #ifdef __cplusplus7.19 }7.20 #endif
8.1 --- a/src/main.c Mon May 17 22:01:23 2010 +10008.2 +++ b/src/main.c Fri Jun 04 09:13:40 2010 +10008.3 @@ -42,13 +42,13 @@8.4 #include "hotkeys.h"8.5 #include "plugin.h"8.7 -char *option_list = "a:A:bc:dfg:G:hHl:m:npt:T:uvV:x?";8.8 +char *option_list = "a:A:bc:dfg:G:hHl:m:npt:T:uvV:w:x?";8.9 struct option longopts[] = {8.10 { "aica", required_argument, NULL, 'a' },8.11 { "audio", required_argument, NULL, 'A' },8.12 { "biosless", no_argument, NULL, 'b' },8.13 { "config", required_argument, NULL, 'c' },8.14 - { "debugger", no_argument, NULL, 'D' },8.15 + { "debugger", no_argument, NULL, 'd' },8.16 { "fullscreen", no_argument, NULL, 'f' },8.17 { "gdb-sh4", required_argument, NULL, 'g' },8.18 { "gdb-arm", required_argument, NULL, 'G' },8.19 @@ -61,6 +61,7 @@8.20 { "unsafe", no_argument, NULL, 'u' },8.21 { "video", no_argument, NULL, 'V' },8.22 { "version", no_argument, NULL, 'v' },8.23 + { "wrap", required_argument, NULL, 'w' },8.24 { NULL, 0, 0, 0 } };8.25 char *aica_program = NULL;8.26 char *display_driver_name = NULL;8.27 @@ -107,6 +108,7 @@8.28 printf( " -u, --unsafe %s\n", _("Allow unsafe dcload syscalls") );8.29 printf( " -v, --version %s\n", _("Print the lxdream version string") );8.30 printf( " -V, --video=DRIVER %s\n", _("Use the specified video driver (? to list)") );8.31 + printf( " -w, --wrap=FILENAME %s\n", _("Wrap the specified binary file in a disc image") );8.32 printf( " -x %s\n", _("Disable the SH4 translator") );8.33 }8.35 @@ -124,6 +126,7 @@8.36 double t;8.37 gboolean display_ok;8.38 uint32_t time_secs, time_nanos;8.39 + const char *wrap_name = NULL;8.41 install_crash_handler();8.42 bind_gettext_domain();8.43 @@ -200,6 +203,9 @@8.44 case 'V': /* Video driver */8.45 display_driver_name = optarg;8.46 break;8.47 + case 'w': /* Wrap image file */8.48 + wrap_name = optarg;8.49 + break;8.50 case 'x': /* Disable translator */8.51 use_xlat = FALSE;8.52 break;8.53 @@ -262,6 +268,19 @@8.54 maple_reattach_all();8.55 INFO( "%s! ready...", APP_NAME );8.57 + if( wrap_name != NULL ) {8.58 + ERROR err;8.59 + cdrom_disc_t disc = cdrom_wrap_magic( CDROM_DISC_XA, wrap_name, &err );8.60 + if( disc == NULL )8.61 + ERROR(err.msg);8.62 + else {8.63 + gdrom_mount_disc(disc);8.64 + if( !no_start ) {8.65 + start_immediately = TRUE;8.66 + }8.67 + }8.68 + }8.69 +8.70 for( ; optind < argc; optind++ ) {8.71 gboolean ok = gdrom_mount_image(argv[optind]);8.72 if( !ok ) {
.