Search
lxdream.org :: lxdream :: r1108:305ef2082079
lxdream 0.9.1
released Jun 29
Download Now
changeset1108:305ef2082079
parent1107:7b279d10f46f
child1109:700c5ab26a63
authornkeynes
dateFri Jun 04 09:13:40 2010 +1000 (9 years ago)
Add ability to wrap a binary program up in a virtual cd image (so that we
can boot it normally)
src/drivers/cdrom/cdrom.c
src/drivers/cdrom/cdrom.h
src/drivers/cdrom/isofs.c
src/drivers/cdrom/isofs.h
src/drivers/cdrom/sector.c
src/loader.c
src/loader.h
src/main.c
1.1 --- a/src/drivers/cdrom/cdrom.c Mon May 17 22:01:23 2010 +1000
1.2 +++ b/src/drivers/cdrom/cdrom.c Fri Jun 04 09:13:40 2010 +1000
1.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.8
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.12
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.20
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 an
1.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 an
1.42 - * inconsistent state */
1.43 - cdrom_disc_clear_toc(disc);
1.44 - return FALSE;
1.45 }
1.46 }
1.47
1.48 @@ -273,6 +278,64 @@
1.49 }
1.50
1.51 /**
1.52 + * Construct a disc around a source track.
1.53 + * @param type Disc type, which must be compatible with the track mode
1.54 + * @param track The source of data for the main track
1.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 +1000
2.2 +++ b/src/drivers/cdrom/cdrom.h Fri Jun 04 09:13:40 2010 +1000
2.3 @@ -97,6 +97,15 @@
2.4 cdrom_disc_t cdrom_disc_open( const char *filename, ERROR *err );
2.5
2.6 /**
2.7 + * Construct a disc around a source track.
2.8 + * @param type Disc type, which must be compatible with the track mode
2.9 + * @param track The source of data for the main track
2.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 +1000
3.2 +++ b/src/drivers/cdrom/isofs.c Fri Jun 04 09:13:40 2010 +1000
3.3 @@ -17,6 +17,8 @@
3.4 */
3.5
3.6 #include <assert.h>
3.7 +#include <stdio.h>
3.8 +#include <unistd.h>
3.9 #include <glib/gmem.h>
3.10
3.11 #define LIBISOFS_WITHOUT_LIBBURN 1
3.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 +1000
4.2 +++ b/src/drivers/cdrom/isofs.h Fri Jun 04 09:13:40 2010 +1000
4.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.6
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 +1000
5.2 +++ b/src/drivers/cdrom/sector.c Fri Jun 04 09:13:40 2010 +1000
5.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.9
5.10 /************************ Memory device implementation *************************/
6.1 --- a/src/loader.c Mon May 17 22:01:23 2010 +1000
6.2 +++ b/src/loader.c Fri Jun 04 09:13:40 2010 +1000
6.3 @@ -2,7 +2,7 @@
6.4 * $Id$
6.5 *
6.6 * File loading routines, mostly for loading demos without going through the
6.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.25
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.34
6.35 -#define CDI_V2 0x80000004
6.36 -#define CDI_V3 0x80000005
6.37 +gboolean file_load_elf_fd( const gchar *filename, int fd );
6.38
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.78
6.79
6.80 gboolean file_load_magic( const gchar *filename )
6.81 @@ -128,6 +167,26 @@
6.82 }
6.83 }
6.84
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.109
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_XA
6.130 + * @param bin The binary data (takes ownership)
6.131 + * @param bin_size
6.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 +1000
7.2 +++ b/src/loader.h Fri Jun 04 09:13:40 2010 +1000
7.3 @@ -22,6 +22,8 @@
7.4 #include <stdio.h>
7.5 #include <glib/gtypes.h>
7.6
7.7 +#include "drivers/cdrom/cdrom.h"
7.8 +
7.9 #ifdef __cplusplus
7.10 extern "C" {
7.11 #endif
7.12 @@ -64,6 +66,8 @@
7.13 */
7.14 gboolean file_load_magic( const gchar *filename );
7.15
7.16 +cdrom_disc_t cdrom_wrap_magic( cdrom_disc_type_t type, const gchar *filename, ERROR *err );
7.17 +
7.18 #ifdef __cplusplus
7.19 }
7.20 #endif
8.1 --- a/src/main.c Mon May 17 22:01:23 2010 +1000
8.2 +++ b/src/main.c Fri Jun 04 09:13:40 2010 +1000
8.3 @@ -42,13 +42,13 @@
8.4 #include "hotkeys.h"
8.5 #include "plugin.h"
8.6
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.34
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.40
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.56
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 ) {
.