Search
lxdream.org :: lxdream/src/drivers/cdrom/cd_gdi.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/drivers/cdrom/cd_gdi.c
changeset 1286:8376a612a79d
prev1109:700c5ab26a63
next1296:30ecee61f811
author nkeynes
date Sun Jul 01 13:19:27 2012 +1000 (9 years ago)
permissions -rw-r--r--
last change Add glib/gfileutils.h includes, as some required defines were moved there in recent versions of glib
view annotate diff log raw
     1 /**
     2  * $Id$
     3  *
     4  * NullDC GDI image format
     5  *
     6  * Copyright (c) 2005 Nathan Keynes.
     7  *
     8  * This program is free software; you can redistribute it and/or modify
     9  * it under the terms of the GNU General Public License as published by
    10  * the Free Software Foundation; either version 2 of the License, or
    11  * (at your option) any later version.
    12  *
    13  * This program is distributed in the hope that it will be useful,
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  * GNU General Public License for more details.
    17  */
    19 #include <stdlib.h>
    20 #include <stdio.h>
    21 #include <stdint.h>
    22 #include <string.h>
    23 #include <fcntl.h>
    24 #include <errno.h>
    25 #include <sys/stat.h>
    26 #include <glib/gfileutils.h>
    27 #include <glib/gutils.h>
    28 #include <glib/gstrfuncs.h>
    29 #include "drivers/cdrom/cdimpl.h"
    32 static gboolean gdi_image_is_valid( FILE *f );
    33 static gboolean gdi_image_read_toc( cdrom_disc_t disc, ERROR *err );
    35 struct cdrom_disc_factory gdi_disc_factory = { "NullDC GD-Rom Image", "gdi",
    36         gdi_image_is_valid, NULL, gdi_image_read_toc };
    38 static gboolean gdi_image_is_valid( FILE *f )
    39 {
    40     char line[512];
    41     uint32_t track_count;
    43     fseek(f, 0, SEEK_SET);
    44     if( fgets( line, sizeof(line), f ) == NULL ) {
    45         return FALSE;
    46     }
    47     track_count = strtoul(line, NULL, 0);
    48     if( track_count == 0 || track_count > 99 ) {
    49         return FALSE;
    50     }
    51     return TRUE;
    52 }
    54 static gboolean gdi_image_read_toc( cdrom_disc_t disc, ERROR *err )
    55 {
    56     int i;
    57     uint32_t track_count;
    58     struct stat st;
    59     char line[512];
    60     int session = 1;
    61     gchar *dirname;
    63     FILE *f = cdrom_disc_get_base_file(disc);
    65     fseek(f, 0, SEEK_SET);
    67     if( fgets( line, sizeof(line), f ) == NULL ) {
    68         SET_ERROR( err, LX_ERR_FILE_INVALID, "Invalid GDI image" );
    69         return FALSE;
    70     }
    71     track_count = strtoul(line, NULL, 0);
    72     if( track_count == 0 || track_count > 99 ) {
    73         SET_ERROR( err, LX_ERR_FILE_INVALID, "Invalid GDI image" );
    74         return FALSE;
    75     }
    77     dirname = g_path_get_dirname(disc->name);
    78     disc->disc_type = CDROM_DISC_GDROM;
    79     disc->track_count = track_count;
    80     disc->session_count = 2;
    81     for( i=0; i<track_count; i++ ) {
    82         int track_no, start_lba, flags, size, offset;
    83         char filename[256];
    85         if( fgets( line, sizeof(line), f ) == NULL ) {
    86             cdrom_disc_unref(disc);
    87             SET_ERROR( err, LX_ERR_FILE_INVALID, "Invalid GDI image - unexpected end of file" );
    88             return FALSE;
    89         }
    90         sscanf( line, "%d %d %d %d %s %d", &track_no, &start_lba, &flags, &size,
    91                 filename, &offset );
    92         if( start_lba >= 45000 ) {
    93             session = 2;
    94         }
    95         disc->track[i].sessionno = session;
    96         disc->track[i].lba = start_lba;
    97         disc->track[i].flags = (flags & 0x0F)<<4;
    99         sector_mode_t mode;
   100         if( disc->track[i].flags & TRACK_FLAG_DATA ) {
   101             /* Data track */
   102             switch(size) {
   103             case 0:    mode = SECTOR_MODE2_FORM1; break; /* Default */
   104             case 2048: mode = SECTOR_MODE2_FORM1; break;
   105             case 2324: mode = SECTOR_MODE2_FORM2; break;
   106             case 2336: mode = SECTOR_SEMIRAW_MODE2; break;
   107             case 2352: mode = SECTOR_RAW_XA; break;
   108             default:
   109                 SET_ERROR( err, LX_ERR_FILE_INVALID, "Invalid sector size '%d' in GDI track %d", size, (i+1) );
   110                 g_free(dirname);
   111                 return FALSE;
   112             }
   113         } else {
   114             /* Audio track */
   115             mode = SECTOR_CDDA;
   116             if( size == 0 )
   117                 size = 2352;
   118             else if( size != 2352 ) {
   119                 SET_ERROR( err, LX_ERR_FILE_INVALID, "Invalid sector size '%d' for audio track %d", size, (i+1) );
   120                 g_free(dirname);
   121                 return FALSE;
   122             }
   123         }
   124         if( strcasecmp( filename, "none" ) == 0 ) {
   125             disc->track[i].source = null_sector_source_new( mode, 0 );
   126         } else {
   127             gchar *pathname = g_strdup_printf( "%s%c%s", dirname, G_DIR_SEPARATOR, filename );
   128             disc->track[i].source = file_sector_source_new_filename( pathname, mode,
   129                     offset, FILE_SECTOR_FULL_FILE );
   130             g_free(pathname);
   131             if( disc->track[i].source == NULL ) {
   132                 /* Note: status is invalid because it's a failure of the GDI file */
   133                 SET_ERROR( err, LX_ERR_FILE_INVALID, "GDI track file '%s' could not be opened (%s)", filename, strerror(errno) );
   134                 g_free(dirname);
   135                 return FALSE;
   136             }
   137         }
   138     }
   139     g_free(dirname);
   140     return TRUE;
   141 }
.