filename | src/gdrom/gdimage.c |
changeset | 1023:264e2fd90be8 |
prev | 840:c6a778c228a6 |
next | 1030:864417a57662 |
author | nkeynes |
date | Mon Jun 08 04:12:21 2009 +0000 (13 years ago) |
permissions | -rw-r--r-- |
last change | General cleanup of the GD-rom subsystem - merge gdrom_image_t and gdrom_disc_t - Abstract MMC devices using a lower-level scsi transport - OSX: only look at the whole disc device, and ignore partitions |
file | annotate | diff | log | raw |
1.1 --- a/src/gdrom/gdimage.c Tue Sep 02 03:34:23 2008 +00001.2 +++ b/src/gdrom/gdimage.c Mon Jun 08 04:12:21 2009 +00001.3 @@ -21,20 +21,17 @@1.4 #include <string.h>1.5 #include <ctype.h>1.6 #include <sys/types.h>1.7 +#include <sys/stat.h>1.8 +#include <fcntl.h>1.9 #include <netinet/in.h>1.11 #include "gdrom/gddriver.h"1.12 #include "gdrom/packet.h"1.13 #include "ecc.h"1.14 -#include "bootstrap.h"1.16 -static void gdrom_image_destroy( gdrom_disc_t disc );1.17 +static gboolean gdrom_null_check_status( gdrom_disc_t disc );1.18 static gdrom_error_t gdrom_image_read_sector( gdrom_disc_t disc, uint32_t lba, int mode,1.19 unsigned char *buf, uint32_t *readlength );1.20 -static gdrom_error_t gdrom_image_read_toc( gdrom_disc_t disc, unsigned char *buf );1.21 -static gdrom_error_t gdrom_image_read_session( gdrom_disc_t disc, int session, unsigned char *buf );1.22 -static gdrom_error_t gdrom_image_read_position( gdrom_disc_t disc, uint32_t lba, unsigned char *buf );1.23 -static int gdrom_image_drive_status( gdrom_disc_t disc );1.25 static uint8_t gdrom_default_sync[12] = { 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0 };1.27 @@ -44,7 +41,11 @@1.28 /* Data offset (from start of raw sector) by sector mode */1.29 static int gdrom_data_offset[] = { 16, 16, 16, 24, 24, 0, 8, 0, 0 };1.31 -1.32 +gdrom_image_class_t gdrom_image_classes[] = { &cdrom_device_class,1.33 + &nrg_image_class,1.34 + &cdi_image_class,1.35 + &gdi_image_class,1.36 + NULL };1.38 struct cdrom_sector_header {1.39 uint8_t sync[12];1.40 @@ -53,96 +54,139 @@1.41 uint8_t subhead[8]; // Mode-2 XA sectors only1.42 };1.44 -/**1.45 - * Initialize a gdrom_disc structure with the gdrom_image_* methods1.46 - */1.47 -void gdrom_image_init( gdrom_disc_t disc )1.48 +gdrom_disc_t gdrom_disc_new( const gchar *filename, FILE *f )1.49 {1.50 - memset( disc, 0, sizeof(struct gdrom_disc) ); /* safety */1.51 - disc->read_sector = gdrom_image_read_sector;1.52 - disc->read_toc = gdrom_image_read_toc;1.53 - disc->read_session = gdrom_image_read_session;1.54 - disc->read_position = gdrom_image_read_position;1.55 - disc->drive_status = gdrom_image_drive_status;1.56 - disc->play_audio = NULL; /* not supported yet */1.57 - disc->run_time_slice = NULL; /* not needed */1.58 - disc->close = gdrom_image_destroy;1.59 -}1.60 -1.61 -gdrom_disc_t gdrom_image_new( const gchar *filename, FILE *f )1.62 -{1.63 - gdrom_image_t image = (gdrom_image_t)g_malloc0(sizeof(struct gdrom_image));1.64 - if( image == NULL ) {1.65 + gdrom_disc_t disc = (gdrom_disc_t)g_malloc0(sizeof(struct gdrom_disc));1.66 + if( disc == NULL ) {1.67 return NULL;1.68 }1.69 - image->disc_type = IDE_DISC_CDROMXA;1.70 - image->file = f;1.71 - gdrom_disc_t disc = (gdrom_disc_t)image;1.72 - gdrom_image_init(disc);1.73 + disc->disc_type = IDE_DISC_NONE;1.74 + disc->file = f;1.75 if( filename == NULL ) {1.76 disc->name = NULL;1.77 } else {1.78 disc->name = g_strdup(filename);1.79 }1.81 + disc->check_status = gdrom_null_check_status;1.82 + disc->destroy = gdrom_disc_destroy;1.83 return disc;1.84 }1.86 -static void gdrom_image_destroy( gdrom_disc_t disc )1.87 +void gdrom_disc_destroy( gdrom_disc_t disc, gboolean close_fh )1.88 {1.89 int i;1.90 FILE *lastfile = NULL;1.91 - gdrom_image_t img = (gdrom_image_t)disc;1.92 - if( img->file != NULL ) {1.93 - fclose(img->file);1.94 - img->file = NULL;1.95 + if( disc->file != NULL ) {1.96 + if( close_fh ) {1.97 + fclose(disc->file);1.98 + }1.99 + disc->file = NULL;1.100 }1.101 - for( i=0; i<img->track_count; i++ ) {1.102 - if( img->track[i].file != NULL && img->track[i].file != lastfile ) {1.103 - lastfile = img->track[i].file;1.104 + for( i=0; i<disc->track_count; i++ ) {1.105 + if( disc->track[i].file != NULL && disc->track[i].file != lastfile ) {1.106 + lastfile = disc->track[i].file;1.107 + /* Track files (if any) are closed regardless of the value of close_fh */1.108 fclose(lastfile);1.109 - img->track[i].file = NULL;1.110 + disc->track[i].file = NULL;1.111 }1.112 }1.113 if( disc->name != NULL ) {1.114 g_free( (gpointer)disc->name );1.115 disc->name = NULL;1.116 }1.117 - free( disc );1.118 -}1.119 -1.120 -void gdrom_image_destroy_no_close( gdrom_disc_t disc )1.121 -{1.122 - int i;1.123 - FILE *lastfile = NULL;1.124 - gdrom_image_t img = (gdrom_image_t)disc;1.125 - if( img->file != NULL ) {1.126 - img->file = NULL;1.127 - }1.128 - for( i=0; i<img->track_count; i++ ) {1.129 - if( img->track[i].file != NULL && img->track[i].file != lastfile ) {1.130 - lastfile = img->track[i].file;1.131 - fclose(lastfile);1.132 - img->track[i].file = NULL;1.133 - }1.134 - }1.135 - if( disc->name != NULL ) {1.136 - g_free( (gpointer)disc->name );1.137 - disc->name = NULL;1.138 + if( disc->display_name != NULL ) {1.139 + g_free( (gpointer)disc->name );1.140 + disc->display_name = NULL;1.141 }1.142 free( disc );1.143 }1.145 -int gdrom_image_get_track_by_lba( gdrom_image_t image, uint32_t lba )1.146 +/**1.147 + * Construct a new gdrom_disc_t and initalize the vtable to the gdrom image1.148 + * default functions.1.149 + */1.150 +gdrom_disc_t gdrom_image_new( const gchar *filename, FILE *f )1.151 {1.152 + gdrom_disc_t disc = gdrom_disc_new( filename, f );1.153 + if( disc != NULL ) {1.154 + disc->read_sector = gdrom_image_read_sector;1.155 + disc->play_audio = NULL; /* not supported yet */1.156 + disc->run_time_slice = NULL; /* not needed */1.157 + }1.158 +}1.159 +1.160 +1.161 +gdrom_disc_t gdrom_image_open( const gchar *inFilename )1.162 +{1.163 + const gchar *filename = inFilename;1.164 + const gchar *ext = strrchr(filename, '.');1.165 + gdrom_disc_t disc = NULL;1.166 + int fd;1.167 + FILE *f;1.168 int i;1.169 - for( i=0; i<image->track_count; i++ ) {1.170 - if( image->track[i].lba <= lba &&1.171 - lba < (image->track[i].lba + image->track[i].sector_count) ) {1.172 - return i+1;1.173 + gdrom_image_class_t extclz = NULL;1.174 +1.175 + // Check for a url-style filename.1.176 + char *lizard_lips = strstr( filename, "://" );1.177 + if( lizard_lips != NULL ) {1.178 + gchar *path = lizard_lips + 3;1.179 + int method_len = (lizard_lips-filename);1.180 + gchar method[method_len + 1];1.181 + memcpy( method, filename, method_len );1.182 + method[method_len] = '\0';1.183 +1.184 + if( strcasecmp( method, "file" ) == 0 ) {1.185 + filename = path;1.186 + } else if( strcasecmp( method, "dvd" ) == 0 ||1.187 + strcasecmp( method, "cd" ) == 0 ||1.188 + strcasecmp( method, "cdrom" ) ) {1.189 + return cdrom_open_device( method, path );1.190 + } else {1.191 + ERROR( "Unrecognized URL method '%s' in filename '%s'", method, filename );1.192 + return NULL;1.193 }1.194 }1.195 - return -1;1.196 +1.197 + fd = open( filename, O_RDONLY | O_NONBLOCK );1.198 + if( fd == -1 ) {1.199 + return NULL;1.200 + }1.201 +1.202 + f = fdopen(fd, "ro");1.203 +1.204 +1.205 + /* try extensions */1.206 + if( ext != NULL ) {1.207 + ext++; /* Skip the '.' */1.208 + for( i=0; gdrom_image_classes[i] != NULL; i++ ) {1.209 + if( gdrom_image_classes[i]->extension != NULL &&1.210 + strcasecmp( gdrom_image_classes[i]->extension, ext ) == 0 ) {1.211 + extclz = gdrom_image_classes[i];1.212 + if( extclz->is_valid_file(f) ) {1.213 + disc = extclz->open_image_file(filename, f);1.214 + if( disc != NULL )1.215 + return disc;1.216 + }1.217 + break;1.218 + }1.219 + }1.220 + }1.221 +1.222 + /* Okay, fall back to magic */1.223 + gboolean recognized = FALSE;1.224 + for( i=0; gdrom_image_classes[i] != NULL; i++ ) {1.225 + if( gdrom_image_classes[i] != extclz &&1.226 + gdrom_image_classes[i]->is_valid_file(f) ) {1.227 + recognized = TRUE;1.228 + disc = gdrom_image_classes[i]->open_image_file(filename, f);1.229 + if( disc != NULL )1.230 + return disc;1.231 + }1.232 + }1.233 +1.234 + fclose(f);1.235 + return NULL;1.236 }1.238 /**1.239 @@ -247,6 +291,15 @@1.240 }1.242 /**1.243 + * Default check media status that does nothing and always returns1.244 + * false (unchanged).1.245 + */1.246 +static gboolean gdrom_null_check_status( gdrom_disc_t disc )1.247 +{1.248 + return FALSE;1.249 +}1.250 +1.251 +/**1.252 * Read a single sector from a disc image. If you thought this would be simple,1.253 * I have just one thing to say to you: Bwahahahahahahahah.1.254 *1.255 @@ -264,23 +317,22 @@1.256 static gdrom_error_t gdrom_image_read_sector( gdrom_disc_t disc, uint32_t lba,1.257 int mode, unsigned char *buf, uint32_t *length )1.258 {1.259 - gdrom_image_t image = (gdrom_image_t)disc;1.260 struct cdrom_sector_header secthead;1.261 int file_offset, read_len, track_no;1.263 FILE *f;1.265 - track_no = gdrom_image_get_track_by_lba( image, lba );1.266 + track_no = gdrom_disc_get_track_by_lba( disc, lba );1.267 if( track_no == -1 ) {1.268 return PKT_ERR_BADREAD;1.269 }1.270 - struct gdrom_track *track = &image->track[track_no-1];1.271 + struct gdrom_track *track = &disc->track[track_no-1];1.272 file_offset = track->offset + track->sector_size * (lba - track->lba);1.273 read_len = track->sector_size;1.274 if( track->file != NULL ) {1.275 f = track->file;1.276 } else {1.277 - f = image->file;1.278 + f = disc->file;1.279 }1.281 /* First figure out what the real sector mode is for raw/semiraw sectors */1.282 @@ -387,142 +439,3 @@1.283 return PKT_ERR_OK;1.284 }1.286 -static gdrom_error_t gdrom_image_read_toc( gdrom_disc_t disc, unsigned char *buf )1.287 -{1.288 - gdrom_image_t image = (gdrom_image_t)disc;1.289 - struct gdrom_toc *toc = (struct gdrom_toc *)buf;1.290 - int i;1.291 -1.292 - for( i=0; i<image->track_count; i++ ) {1.293 - toc->track[i] = htonl( image->track[i].lba ) | image->track[i].flags;1.294 - }1.295 - toc->first = 0x0100 | image->track[0].flags;1.296 - toc->last = (image->track_count<<8) | image->track[i-1].flags;1.297 - toc->leadout = htonl(image->track[i-1].lba + image->track[i-1].sector_count) |1.298 - image->track[i-1].flags;1.299 - for( ;i<99; i++ )1.300 - toc->track[i] = 0xFFFFFFFF;1.301 - return PKT_ERR_OK;1.302 -}1.303 -1.304 -static gdrom_error_t gdrom_image_read_session( gdrom_disc_t disc, int session, unsigned char *buf )1.305 -{1.306 - gdrom_image_t image = (gdrom_image_t)disc;1.307 - struct gdrom_track *last_track = &image->track[image->track_count-1];1.308 - unsigned int end_of_disc = last_track->lba + last_track->sector_count;1.309 - int i;1.310 - buf[0] = 0x01; /* Disc status? */1.311 - buf[1] = 0;1.312 -1.313 - if( session == 0 ) {1.314 - buf[2] = last_track->session+1; /* last session */1.315 - buf[3] = (end_of_disc >> 16) & 0xFF;1.316 - buf[4] = (end_of_disc >> 8) & 0xFF;1.317 - buf[5] = end_of_disc & 0xFF;1.318 - return PKT_ERR_OK;1.319 - } else {1.320 - session--;1.321 - for( i=0; i<image->track_count; i++ ) {1.322 - if( image->track[i].session == session ) {1.323 - buf[2] = i+1; /* first track of session */1.324 - buf[3] = (image->track[i].lba >> 16) & 0xFF;1.325 - buf[4] = (image->track[i].lba >> 8) & 0xFF;1.326 - buf[5] = image->track[i].lba & 0xFF;1.327 - return PKT_ERR_OK;1.328 - }1.329 - }1.330 - return PKT_ERR_BADFIELD; /* No such session */1.331 - }1.332 -}1.333 -1.334 -static gdrom_error_t gdrom_image_read_position( gdrom_disc_t disc, uint32_t lba, unsigned char *buf )1.335 -{1.336 - gdrom_image_t image = (gdrom_image_t)disc;1.337 - int track_no = gdrom_image_get_track_by_lba( image, lba );1.338 - if( track_no == -1 ) {1.339 - track_no = 1;1.340 - lba = 150;1.341 - }1.342 - struct gdrom_track *track = &image->track[track_no-1];1.343 - uint32_t offset = lba - track->lba;1.344 - buf[4] = track->flags;1.345 - buf[5] = track_no;1.346 - buf[6] = 0x01; /* ?? */1.347 - buf[7] = (offset >> 16) & 0xFF;1.348 - buf[8] = (offset >> 8) & 0xFF;1.349 - buf[9] = offset & 0xFF;1.350 - buf[10] = 0;1.351 - buf[11] = (lba >> 16) & 0xFF;1.352 - buf[12] = (lba >> 8) & 0xFF;1.353 - buf[13] = lba & 0xFF;1.354 - return PKT_ERR_OK;1.355 -}1.356 -1.357 -static int gdrom_image_drive_status( gdrom_disc_t disc )1.358 -{1.359 - gdrom_image_t image = (gdrom_image_t)disc;1.360 - if( image->disc_type == IDE_DISC_NONE ) {1.361 - return IDE_DISC_NONE;1.362 - } else {1.363 - return image->disc_type | IDE_DISC_READY;1.364 - }1.365 -}1.366 -1.367 -gdrom_device_t gdrom_device_new( const gchar *name, const gchar *dev_name )1.368 -{1.369 - struct gdrom_device *dev = g_malloc0( sizeof(struct gdrom_device) );1.370 - dev->name = g_strdup(name);1.371 - dev->device_name = g_strdup(dev_name);1.372 - return dev;1.373 -}1.374 -1.375 -void gdrom_device_destroy( gdrom_device_t dev )1.376 -{1.377 - if( dev->name != NULL ) {1.378 - g_free( dev->name );1.379 - dev->name = NULL;1.380 - }1.381 - if( dev->device_name != NULL ) {1.382 - g_free( dev->device_name );1.383 - dev->device_name = NULL;1.384 - }1.385 - g_free( dev );1.386 -}1.387 -1.388 -/**1.389 - * Check the disc for a useable DC bootstrap, and update the disc1.390 - * with the title accordingly.1.391 - * @return TRUE if we found a bootstrap, otherwise FALSE.1.392 - */1.393 -gboolean gdrom_image_read_info( gdrom_disc_t d ) {1.394 - gdrom_image_t disc = (gdrom_image_t)d;1.395 - if( disc->track_count > 0 ) {1.396 - /* Find the first data track of the last session */1.397 - int last_session = disc->track[disc->track_count-1].session;1.398 - int i, boot_track = -1;1.399 - for( i=disc->track_count-1; i>=0 && disc->track[i].session == last_session; i-- ) {1.400 - if( disc->track[i].flags & TRACK_DATA ) {1.401 - boot_track = i;1.402 - }1.403 - }1.404 - if( boot_track != -1 ) {1.405 - unsigned char boot_sector[MAX_SECTOR_SIZE];1.406 - uint32_t length = sizeof(boot_sector);1.407 - if( d->read_sector( d, disc->track[boot_track].lba, 0x28,1.408 - boot_sector, &length ) == PKT_ERR_OK ) {1.409 - if( memcmp( boot_sector, "SEGA SEGAKATANA SEGA ENTERPRISES", 32) == 0 ) {1.410 - /* Got magic */1.411 - memcpy( d->title, boot_sector+128, 128 );1.412 - for( i=127; i>=0; i-- ) {1.413 - if( !isspace(d->title[i]) )1.414 - break;1.415 - }1.416 - d->title[i+1] = '\0';1.417 - }1.418 - bootstrap_dump(boot_sector, FALSE);1.419 - return TRUE;1.420 - }1.421 - }1.422 - }1.423 - return FALSE;1.424 -}
.