Search
lxdream.org :: lxdream/src/gdrom/gdrom.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/gdrom/gdrom.c
changeset 1023:264e2fd90be8
prev837:4eae2ddccf9c
next1074:397d77b6e346
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/gdrom.c Thu Aug 28 01:39:51 2008 +0000
1.2 +++ b/src/gdrom/gdrom.c Mon Jun 08 04:12:21 2009 +0000
1.3 @@ -1,4 +1,3 @@
1.4 -
1.5 /**
1.6 * $Id$
1.7 *
1.8 @@ -20,12 +19,14 @@
1.9 #include <stdio.h>
1.10 #include <fcntl.h>
1.11 #include <errno.h>
1.12 +#include <ctype.h>
1.13 #include <glib/gutils.h>
1.14 #include "gdrom/ide.h"
1.15 #include "gdrom/gdrom.h"
1.16 #include "gdrom/gddriver.h"
1.17 #include "gdrom/packet.h"
1.18 #include "dream.h"
1.19 +#include "bootstrap.h"
1.20
1.21 extern gdrom_disc_t gdrom_disc;
1.22
1.23 @@ -36,96 +37,40 @@
1.24 CALL_HOOKS( gdrom_disc_change_hook, disc, disc == NULL ? NULL : disc->name );
1.25 }
1.26
1.27 -gdrom_image_class_t gdrom_image_classes[] = { &cdrom_device_class,
1.28 - &nrg_image_class,
1.29 - &cdi_image_class,
1.30 - &gdi_image_class,
1.31 - NULL };
1.32 -
1.33 char *gdrom_mode_names[] = { "Mode 0", "Mode 1", "Mode 2", "Mode 2 Form 1", "Mode 2 Form 2", "Audio",
1.34 "Mode 2 semiraw", "XA Raw", "Non-XA Raw" };
1.35 uint32_t gdrom_sector_size[] = { 0, 2048, 2336, 2048, 2324, 2352, 2336, 2352, 2352 };
1.36
1.37 -gdrom_disc_t gdrom_image_open( const gchar *inFilename )
1.38 +
1.39 +gdrom_device_t gdrom_device_new( const gchar *name, const gchar *dev_name )
1.40 {
1.41 - const gchar *filename = inFilename;
1.42 - const gchar *ext = strrchr(filename, '.');
1.43 - gdrom_disc_t disc = NULL;
1.44 - int fd;
1.45 - FILE *f;
1.46 - int i;
1.47 - gdrom_image_class_t extclz = NULL;
1.48 + struct gdrom_device *dev = g_malloc0( sizeof(struct gdrom_device) );
1.49 + dev->name = g_strdup(name);
1.50 + dev->device_name = g_strdup(dev_name);
1.51 + return dev;
1.52 +}
1.53
1.54 - // Check for a url-style filename.
1.55 - char *lizard_lips = strstr( filename, "://" );
1.56 - if( lizard_lips != NULL ) {
1.57 - gchar *path = lizard_lips + 3;
1.58 - int method_len = (lizard_lips-filename);
1.59 - gchar method[method_len + 1];
1.60 - memcpy( method, filename, method_len );
1.61 - method[method_len] = '\0';
1.62 -
1.63 - if( strcasecmp( method, "file" ) == 0 ) {
1.64 - filename = path;
1.65 - } else if( strcasecmp( method, "dvd" ) == 0 ||
1.66 - strcasecmp( method, "cd" ) == 0 ||
1.67 - strcasecmp( method, "cdrom" ) ) {
1.68 - return cdrom_open_device( method, path );
1.69 - } else {
1.70 - ERROR( "Unrecognized URL method '%s' in filename '%s'", method, filename );
1.71 - return NULL;
1.72 - }
1.73 +void gdrom_device_destroy( gdrom_device_t dev )
1.74 +{
1.75 + if( dev->name != NULL ) {
1.76 + g_free( dev->name );
1.77 + dev->name = NULL;
1.78 }
1.79 -
1.80 - fd = open( filename, O_RDONLY | O_NONBLOCK );
1.81 - if( fd == -1 ) {
1.82 - return NULL;
1.83 + if( dev->device_name != NULL ) {
1.84 + g_free( dev->device_name );
1.85 + dev->device_name = NULL;
1.86 }
1.87 -
1.88 - f = fdopen(fd, "ro");
1.89 -
1.90 -
1.91 - /* try extensions */
1.92 - if( ext != NULL ) {
1.93 - ext++; /* Skip the '.' */
1.94 - for( i=0; gdrom_image_classes[i] != NULL; i++ ) {
1.95 - if( gdrom_image_classes[i]->extension != NULL &&
1.96 - strcasecmp( gdrom_image_classes[i]->extension, ext ) == 0 ) {
1.97 - extclz = gdrom_image_classes[i];
1.98 - if( extclz->is_valid_file(f) ) {
1.99 - disc = extclz->open_image_file(filename, f);
1.100 - if( disc != NULL )
1.101 - return disc;
1.102 - }
1.103 - break;
1.104 - }
1.105 - }
1.106 - }
1.107 -
1.108 - /* Okay, fall back to magic */
1.109 - gboolean recognized = FALSE;
1.110 - for( i=0; gdrom_image_classes[i] != NULL; i++ ) {
1.111 - if( gdrom_image_classes[i] != extclz &&
1.112 - gdrom_image_classes[i]->is_valid_file(f) ) {
1.113 - recognized = TRUE;
1.114 - disc = gdrom_image_classes[i]->open_image_file(filename, f);
1.115 - if( disc != NULL )
1.116 - return disc;
1.117 - }
1.118 - }
1.119 -
1.120 - fclose(f);
1.121 - return NULL;
1.122 + g_free( dev );
1.123 }
1.124
1.125 void gdrom_mount_disc( gdrom_disc_t disc )
1.126 {
1.127 if( disc != gdrom_disc ) {
1.128 if( gdrom_disc != NULL ) {
1.129 - gdrom_disc->close(gdrom_disc);
1.130 + gdrom_disc->destroy(gdrom_disc,TRUE);
1.131 }
1.132 gdrom_disc = disc;
1.133 - gdrom_image_read_info( disc );
1.134 + gdrom_disc_read_title( disc );
1.135 gdrom_fire_disc_changed( disc );
1.136 }
1.137 }
1.138 @@ -143,7 +88,7 @@
1.139 void gdrom_unmount_disc( )
1.140 {
1.141 if( gdrom_disc != NULL ) {
1.142 - gdrom_disc->close(gdrom_disc);
1.143 + gdrom_disc->destroy(gdrom_disc, TRUE);
1.144 gdrom_fire_disc_changed(NULL);
1.145 gdrom_disc = NULL;
1.146 }
1.147 @@ -172,11 +117,160 @@
1.148 }
1.149 }
1.150
1.151 -gchar *gdrom_get_relative_filename( const gchar *base_name, const gchar *rel_name )
1.152 +int gdrom_disc_get_track_by_lba( gdrom_disc_t disc, uint32_t lba )
1.153 {
1.154 - gchar *dirname = g_path_get_dirname(base_name);
1.155 - gchar *pathname = g_strdup_printf( "%s%c%s", dirname, G_DIR_SEPARATOR, rel_name );
1.156 - g_free(dirname);
1.157 - return pathname;
1.158 + int i;
1.159 + for( i=0; i<disc->track_count; i++ ) {
1.160 + if( disc->track[i].lba <= lba &&
1.161 + lba < (disc->track[i].lba + disc->track[i].sector_count) ) {
1.162 + return i+1;
1.163 + }
1.164 + }
1.165 + return -1;
1.166 }
1.167
1.168 +#define CHECK_DISC(disc) do { \
1.169 + if( disc == NULL ) { return PKT_ERR_NODISC; } \
1.170 + disc->check_status(disc); \
1.171 + if( disc->disc_type == IDE_DISC_NONE ) { return PKT_ERR_NODISC; } \
1.172 + } while(0)
1.173 +
1.174 +gdrom_error_t gdrom_disc_check_media( gdrom_disc_t disc )
1.175 +{
1.176 + CHECK_DISC(disc);
1.177 + return PKT_ERR_OK;
1.178 +}
1.179 +
1.180 +gdrom_error_t gdrom_disc_get_toc( gdrom_disc_t disc, unsigned char *buf )
1.181 +{
1.182 + struct gdrom_toc {
1.183 + uint32_t track[99];
1.184 + uint32_t first, last, leadout;
1.185 + };
1.186 +
1.187 + struct gdrom_toc *toc = (struct gdrom_toc *)buf;
1.188 + int i;
1.189 +
1.190 + CHECK_DISC(disc);
1.191 +
1.192 + for( i=0; i<disc->track_count; i++ ) {
1.193 + toc->track[i] = htonl( disc->track[i].lba ) | disc->track[i].flags;
1.194 + }
1.195 + toc->first = 0x0100 | disc->track[0].flags;
1.196 + toc->last = (disc->track_count<<8) | disc->track[i-1].flags;
1.197 + toc->leadout = htonl(disc->track[i-1].lba + disc->track[i-1].sector_count) |
1.198 + disc->track[i-1].flags;
1.199 + for( ;i<99; i++ )
1.200 + toc->track[i] = 0xFFFFFFFF;
1.201 + return PKT_ERR_OK;
1.202 +}
1.203 +
1.204 +gdrom_error_t gdrom_disc_get_session_info( gdrom_disc_t disc, int session, unsigned char *buf )
1.205 +{
1.206 + CHECK_DISC(disc);
1.207 +
1.208 + struct gdrom_track *last_track = &disc->track[disc->track_count-1];
1.209 + unsigned int end_of_disc = last_track->lba + last_track->sector_count;
1.210 + int i;
1.211 + buf[0] = 0x01; /* Disc status? */
1.212 + buf[1] = 0;
1.213 +
1.214 + if( session == 0 ) {
1.215 + buf[2] = last_track->session+1; /* last session */
1.216 + buf[3] = (end_of_disc >> 16) & 0xFF;
1.217 + buf[4] = (end_of_disc >> 8) & 0xFF;
1.218 + buf[5] = end_of_disc & 0xFF;
1.219 + return PKT_ERR_OK;
1.220 + } else {
1.221 + session--;
1.222 + for( i=0; i<disc->track_count; i++ ) {
1.223 + if( disc->track[i].session == session ) {
1.224 + buf[2] = i+1; /* first track of session */
1.225 + buf[3] = (disc->track[i].lba >> 16) & 0xFF;
1.226 + buf[4] = (disc->track[i].lba >> 8) & 0xFF;
1.227 + buf[5] = disc->track[i].lba & 0xFF;
1.228 + return PKT_ERR_OK;
1.229 + }
1.230 + }
1.231 + return PKT_ERR_BADFIELD; /* No such session */
1.232 + }
1.233 +}
1.234 +
1.235 +gdrom_error_t gdrom_disc_get_short_status( gdrom_disc_t disc, uint32_t lba, unsigned char *buf )
1.236 +{
1.237 + CHECK_DISC(disc);
1.238 +
1.239 + int track_no = gdrom_disc_get_track_by_lba( disc, lba );
1.240 + if( track_no == -1 ) {
1.241 + track_no = 1;
1.242 + lba = 150;
1.243 + }
1.244 + struct gdrom_track *track = &disc->track[track_no-1];
1.245 + uint32_t offset = lba - track->lba;
1.246 + buf[0] = 0x00;
1.247 + buf[1] = 0x15; /* audio status ? */
1.248 + buf[2] = 0x00;
1.249 + buf[3] = 0x0E;
1.250 + buf[4] = track->flags;
1.251 + buf[5] = track_no;
1.252 + buf[6] = 0x01; /* ?? */
1.253 + buf[7] = (offset >> 16) & 0xFF;
1.254 + buf[8] = (offset >> 8) & 0xFF;
1.255 + buf[9] = offset & 0xFF;
1.256 + buf[10] = 0;
1.257 + buf[11] = (lba >> 16) & 0xFF;
1.258 + buf[12] = (lba >> 8) & 0xFF;
1.259 + buf[13] = lba & 0xFF;
1.260 + return PKT_ERR_OK;
1.261 +}
1.262 +
1.263 +int gdrom_disc_get_drive_status( gdrom_disc_t disc )
1.264 +{
1.265 + if( disc == NULL ) {
1.266 + return IDE_DISC_NONE;
1.267 + }
1.268 +
1.269 + disc->check_status(disc);
1.270 + if( disc->disc_type == IDE_DISC_NONE ) {
1.271 + return IDE_DISC_NONE;
1.272 + } else {
1.273 + return disc->disc_type | IDE_DISC_READY;
1.274 + }
1.275 +}
1.276 +
1.277 +/**
1.278 + * Check the disc for a useable DC bootstrap, and update the disc
1.279 + * with the title accordingly.
1.280 + * @return TRUE if we found a bootstrap, otherwise FALSE.
1.281 + */
1.282 +gboolean gdrom_disc_read_title( gdrom_disc_t disc ) {
1.283 + if( disc->track_count > 0 ) {
1.284 + /* Find the first data track of the last session */
1.285 + int last_session = disc->track[disc->track_count-1].session;
1.286 + int i, boot_track = -1;
1.287 + for( i=disc->track_count-1; i>=0 && disc->track[i].session == last_session; i-- ) {
1.288 + if( disc->track[i].flags & TRACK_DATA ) {
1.289 + boot_track = i;
1.290 + }
1.291 + }
1.292 + if( boot_track != -1 ) {
1.293 + unsigned char boot_sector[MAX_SECTOR_SIZE];
1.294 + uint32_t length = sizeof(boot_sector);
1.295 + if( disc->read_sector( disc, disc->track[boot_track].lba, 0x28,
1.296 + boot_sector, &length ) == PKT_ERR_OK ) {
1.297 + if( memcmp( boot_sector, "SEGA SEGAKATANA SEGA ENTERPRISES", 32) == 0 ) {
1.298 + /* Got magic */
1.299 + memcpy( disc->title, boot_sector+128, 128 );
1.300 + for( i=127; i>=0; i-- ) {
1.301 + if( !isspace(disc->title[i]) )
1.302 + break;
1.303 + }
1.304 + disc->title[i+1] = '\0';
1.305 + }
1.306 + bootstrap_dump(boot_sector, FALSE);
1.307 + return TRUE;
1.308 + }
1.309 + }
1.310 + }
1.311 + return FALSE;
1.312 +}
.