nkeynes@31: /** nkeynes@31: * $Id: cdi.c,v 1.2 2005-12-25 08:24:11 nkeynes Exp $ nkeynes@31: * nkeynes@31: * CDI CD-image file support nkeynes@31: * nkeynes@31: * Copyright (c) 2005 Nathan Keynes. nkeynes@31: * nkeynes@31: * This program is free software; you can redistribute it and/or modify nkeynes@31: * it under the terms of the GNU General Public License as published by nkeynes@31: * the Free Software Foundation; either version 2 of the License, or nkeynes@31: * (at your option) any later version. nkeynes@31: * nkeynes@31: * This program is distributed in the hope that it will be useful, nkeynes@31: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@31: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@31: * GNU General Public License for more details. nkeynes@31: */ nkeynes@1: nkeynes@1: #include nkeynes@1: #include nkeynes@1: #include nkeynes@1: #include nkeynes@1: #include nkeynes@1: #include nkeynes@1: #include "cdi.h" nkeynes@1: nkeynes@1: #define CDI_V2 0x80000004 nkeynes@1: #define CDI_V3 0x80000005 nkeynes@1: nkeynes@1: static char track_start_marker[20] = { 0,0,1,0,0,0,255,255,255,255, nkeynes@1: 0,0,1,0,0,0,255,255,255,255 }; nkeynes@1: nkeynes@1: struct cdi_trailer { nkeynes@1: uint32_t cdi_version; nkeynes@1: uint32_t header_offset; nkeynes@1: }; nkeynes@1: nkeynes@1: struct cdi_track { nkeynes@1: int file_posn; nkeynes@1: int length; /* bytes */ nkeynes@1: int pregap; /* sectors */ nkeynes@1: int mode; nkeynes@1: int sector_size; nkeynes@1: int session; nkeynes@1: struct cdi_track *next; nkeynes@1: }; nkeynes@1: nkeynes@1: struct cdi_handle { nkeynes@1: int fd; nkeynes@1: uint16_t num_sessions; nkeynes@1: struct cdi_track *tracks; nkeynes@1: }; nkeynes@1: nkeynes@1: nkeynes@1: nkeynes@1: struct cdi_track_data { nkeynes@1: char unknown[0x19]; nkeynes@1: uint32_t pregap_length; nkeynes@1: uint32_t length; nkeynes@1: char unknown2[6]; nkeynes@1: uint32_t mode; nkeynes@1: char unknown3[0x0c]; nkeynes@1: uint32_t start_lba; nkeynes@1: uint32_t total_length; nkeynes@1: char unknown4[0x10]; nkeynes@1: uint32_t sector_size; nkeynes@1: char unknown5[0x1D]; nkeynes@1: } __attribute__((packed)); nkeynes@1: nkeynes@1: cdi_t cdi_open( char *filename ) nkeynes@1: { nkeynes@1: #define BAIL( x, ... ) { fprintf( stderr, x, __VA_ARGS__ ); if( fd != -1 ) close(fd); return NULL; } nkeynes@1: nkeynes@1: struct stat st; nkeynes@1: int fd = -1, i,j, tmp; nkeynes@1: int posn = 0, hdr; nkeynes@1: long len; nkeynes@1: struct cdi_trailer trail; nkeynes@1: struct cdi_handle cdi; nkeynes@1: uint16_t tracks; nkeynes@1: uint32_t new_fmt; nkeynes@1: char tmpc; nkeynes@1: char marker[20]; nkeynes@1: nkeynes@1: fd = open( filename, O_RDONLY ); nkeynes@1: if( fd == -1 ) nkeynes@1: BAIL( "Unable to open file: %s (%s)\n", filename, strerror(errno) ); nkeynes@1: fstat( fd, &st ); nkeynes@1: if( st.st_size < 8 ) nkeynes@1: BAIL( "File is too small to be a valid CDI image: %s\n", filename ); nkeynes@1: len = lseek( fd, -8, SEEK_END ); nkeynes@1: read( fd, &trail, sizeof(trail) ); nkeynes@1: if( trail.header_offset > st.st_size || nkeynes@1: trail.header_offset == 0 ) nkeynes@1: BAIL( "Not a valid CDI image: %s\n", filename ); nkeynes@1: nkeynes@1: if( trail.cdi_version == CDI_V2 ) trail.cdi_version = 2; nkeynes@1: else if( trail.cdi_version == CDI_V3 ) trail.cdi_version = 3; nkeynes@1: else BAIL( "Unknown CDI version code %08x in %s\n", trail.cdi_version, nkeynes@1: filename ); nkeynes@1: nkeynes@1: lseek( fd, trail.header_offset, SEEK_SET ); nkeynes@1: read( fd, &cdi.num_sessions, 2 ); nkeynes@1: nkeynes@1: nkeynes@1: printf( "CDI version: %d\n", trail.cdi_version ); nkeynes@1: printf( "Sessions: %d\n\n", cdi.num_sessions ); nkeynes@1: for( i=0; i< cdi.num_sessions; i++ ) { nkeynes@1: read( fd, &tracks, 2 ); nkeynes@1: printf( "Session %d - %d tracks:\n", i+1, tracks ); nkeynes@1: for( j=0; j