Search
lxdream.org :: lxdream/src/gdrom/nrg.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/gdrom/nrg.c
changeset 514:97f7e4bb2b54
prev468:3a49695e081a
next561:533f6b478071
author nkeynes
date Thu Nov 15 08:16:27 2007 +0000 (12 years ago)
permissions -rw-r--r--
last change Add support for NRG 5.5+ images
file annotate diff log raw
1.1 --- a/src/gdrom/nrg.c Sun Oct 28 07:23:46 2007 +0000
1.2 +++ b/src/gdrom/nrg.c Thu Nov 15 08:16:27 2007 +0000
1.3 @@ -20,7 +20,7 @@
1.4 #include <assert.h>
1.5 #include <stdio.h>
1.6 #include <errno.h>
1.7 -#include <netinet/in.h>
1.8 +#include <glib/gtypes.h>
1.9 #include "gdrom/gdrom.h"
1.10 #include "dream.h"
1.11
1.12 @@ -75,6 +75,14 @@
1.13 uint32_t padding;
1.14 };
1.15
1.16 +struct nrg_etn2 {
1.17 + uint64_t offset;
1.18 + uint64_t length;
1.19 + uint32_t mode;
1.20 + uint32_t lba;
1.21 + uint64_t padding;
1.22 +};
1.23 +
1.24 struct nrg_cues {
1.25 uint8_t type;
1.26 uint8_t track;
1.27 @@ -100,6 +108,23 @@
1.28 } track[0];
1.29 } __attribute__((packed));
1.30
1.31 +struct nrg_daox {
1.32 + uint32_t length;
1.33 + char mcn[14];
1.34 + uint8_t disc_mode;
1.35 + uint8_t unknown[2]; /* always 01 01? */
1.36 + uint8_t track_count;
1.37 + struct nrg_daox_track {
1.38 + char unknown[10];
1.39 + uint32_t sector_size __attribute__((packed)); /* Always 0? */
1.40 + uint8_t mode;
1.41 + uint8_t unknown2[3]; /* Always 00 00 01? */
1.42 + uint64_t pregap __attribute__((packed));
1.43 + uint64_t offset __attribute__((packed));
1.44 + uint64_t end __attribute__((packed));
1.45 + } track[0];
1.46 +} __attribute__((packed));
1.47 +
1.48 /**
1.49 * Convert an 8-bit BCD number to normal integer form.
1.50 * Eg, 0x79 => 79
1.51 @@ -117,7 +142,7 @@
1.52 */
1.53 uint32_t static msf_to_lba( uint32_t msf )
1.54 {
1.55 - msf = ntohl(msf);
1.56 + msf = GUINT32_FROM_BE(msf);
1.57 int f = bcd_to_uint8(msf);
1.58 int s = bcd_to_uint8(msf>>8);
1.59 int m = bcd_to_uint8(msf>>16);
1.60 @@ -144,7 +169,8 @@
1.61
1.62 fseek( f, -12, SEEK_END );
1.63 fread( &footer, sizeof(footer), 1, f );
1.64 - if( ntohl(footer.v50.id) == NERO_V50_ID ) {
1.65 + if( GUINT32_FROM_BE(footer.v50.id) == NERO_V50_ID ||
1.66 + GUINT32_FROM_BE(footer.v55.id) == NERO_V55_ID ) {
1.67 return TRUE;
1.68 } else {
1.69 return FALSE;
1.70 @@ -156,23 +182,27 @@
1.71 union nrg_footer footer;
1.72 struct nrg_chunk chunk;
1.73 struct nrg_daoi *dao;
1.74 + struct nrg_daox *daox;
1.75 + struct nrg_etnf *etnf;
1.76 + struct nrg_etn2 *etn2;
1.77 gdrom_disc_t disc;
1.78 gdrom_image_t image;
1.79 gboolean end = FALSE;
1.80 + uint32_t chunk_id;
1.81 int session_id = 0;
1.82 int session_track_id = 0;
1.83 int track_id = 0;
1.84 int cue_track_id = 0, cue_track_count = 0;
1.85 - int i;
1.86 + int i, count;
1.87
1.88 fseek( f, -12, SEEK_END );
1.89 fread( &footer, sizeof(footer), 1, f );
1.90 - if( ntohl(footer.v50.id) == NERO_V50_ID ) {
1.91 + if( GUINT32_FROM_BE(footer.v50.id) == NERO_V50_ID ) {
1.92 INFO( "Loading Nero 5.0 image" );
1.93 - fseek( f, ntohl(footer.v50.offset), SEEK_SET );
1.94 - } else if( ntohl(footer.v55.id) == NERO_V55_ID ) {
1.95 + fseek( f, GUINT32_FROM_BE(footer.v50.offset), SEEK_SET );
1.96 + } else if( GUINT32_FROM_BE(footer.v55.id) == NERO_V55_ID ) {
1.97 INFO( "Loading Nero 5.5+ image" );
1.98 - fseek( f, ntohl(footer.v55.offset), SEEK_SET );
1.99 + fseek( f, (uint32_t)GUINT64_FROM_BE(footer.v55.offset), SEEK_SET );
1.100 } else {
1.101 /* Not a (recognized) Nero image */
1.102 return NULL;
1.103 @@ -187,32 +217,40 @@
1.104
1.105 do {
1.106 fread( &chunk, sizeof(chunk), 1, f );
1.107 - chunk.length = ntohl(chunk.length);
1.108 + chunk.length = GUINT32_FROM_BE(chunk.length);
1.109 char data[chunk.length];
1.110 fread( data, chunk.length, 1, f );
1.111 - switch( ntohl(chunk.id) ) {
1.112 + chunk_id = GUINT32_FROM_BE(chunk.id);
1.113 + switch( chunk_id ) {
1.114 case CUES_ID:
1.115 + case CUEX_ID:
1.116 cue_track_id = track_id;
1.117 cue_track_count = ((chunk.length / sizeof(struct nrg_cues)) >> 1) - 1;
1.118 track_id += cue_track_count;
1.119 for( i=0; i<chunk.length; i+= sizeof(struct nrg_cues) ) {
1.120 struct nrg_cues *cue = (struct nrg_cues *)(data+i);
1.121 int track = 0;
1.122 + uint32_t lba;
1.123 + if( chunk_id == CUEX_ID ) {
1.124 + lba = GUINT32_FROM_BE( cue->addr ) + GDROM_PREGAP;
1.125 + } else {
1.126 + lba = msf_to_lba( cue->addr );
1.127 + }
1.128 if( cue->track == 0 )
1.129 continue; /* Track 0. Leadin? always 0? */
1.130 if( cue->track == 0xAA ) { /* end of disc */
1.131 image->track[track_id-1].sector_count =
1.132 - msf_to_lba( cue->addr ) - image->track[track_id-1].lba;
1.133 + lba - image->track[track_id-1].lba;
1.134 } else {
1.135 track = cue_track_id + bcd_to_uint8(cue->track) - 1;
1.136 if( (cue->control & 0x01) == 0 ) {
1.137 /* Pre-gap address. */
1.138 if( track != 0 ) {
1.139 image->track[track-1].sector_count =
1.140 - msf_to_lba( cue->addr ) - image->track[track-1].lba;
1.141 + lba - image->track[track-1].lba;
1.142 }
1.143 } else { /* Track-start address */
1.144 - image->track[track].lba = msf_to_lba( cue->addr );
1.145 + image->track[track].lba = lba;
1.146 image->track[track].flags = cue->type;
1.147 }
1.148 }
1.149 @@ -225,28 +263,46 @@
1.150 assert( dao->track_count * 30 + 22 == chunk.length );
1.151 assert( dao->track_count == cue_track_count );
1.152 for( i=0; i<dao->track_count; i++ ) {
1.153 - image->track[cue_track_id].sector_size = ntohl(dao->track[i].sector_size);
1.154 - image->track[cue_track_id].offset = ntohl(dao->track[i].offset);
1.155 + image->track[cue_track_id].sector_size = GUINT32_FROM_BE(dao->track[i].sector_size);
1.156 + image->track[cue_track_id].offset = GUINT32_FROM_BE(dao->track[i].offset);
1.157 image->track[cue_track_id].mode = nrg_track_mode( dao->track[i].mode );
1.158 image->track[cue_track_id].sector_count =
1.159 - (ntohl(dao->track[i].end) - ntohl(dao->track[i].offset))/
1.160 - ntohl(dao->track[i].sector_size);
1.161 + (GUINT32_FROM_BE(dao->track[i].end) - GUINT32_FROM_BE(dao->track[i].offset))/
1.162 + GUINT32_FROM_BE(dao->track[i].sector_size);
1.163 cue_track_id++;
1.164 }
1.165 break;
1.166 + case DAOX_ID:
1.167 + daox = (struct nrg_daox *)data;
1.168 + memcpy( image->mcn, daox->mcn, 13 );
1.169 + image->mcn[13] = '\0';
1.170 + assert( daox->track_count * 42 + 22 == chunk.length );
1.171 + assert( daox->track_count == cue_track_count );
1.172 + for( i=0; i<daox->track_count; i++ ) {
1.173 + image->track[cue_track_id].sector_size = GUINT32_FROM_BE(daox->track[i].sector_size);
1.174 + image->track[cue_track_id].offset = GUINT64_FROM_BE(daox->track[i].offset);
1.175 + image->track[cue_track_id].mode = nrg_track_mode( daox->track[i].mode );
1.176 + image->track[cue_track_id].sector_count =
1.177 + (GUINT64_FROM_BE(daox->track[i].end) - GUINT64_FROM_BE(daox->track[i].offset))/
1.178 + GUINT32_FROM_BE(daox->track[i].sector_size);
1.179 + cue_track_id++;
1.180 + }
1.181 + break;
1.182 +
1.183 case SINF_ID:
1.184 /* Data is a single 32-bit number representing number of tracks in session */
1.185 - i = ntohl( *(uint32_t *)data );
1.186 + i = GUINT32_FROM_BE( *(uint32_t *)data );
1.187 while( i-- > 0 )
1.188 image->track[session_track_id++].session = session_id;
1.189 session_id++;
1.190 break;
1.191 case ETNF_ID:
1.192 - for( i=0; i < chunk.length; i+= 0x14 ) {
1.193 - struct nrg_etnf *etnf = (struct nrg_etnf *)(data+i);
1.194 - image->track[track_id].offset = ntohl(etnf->offset);
1.195 - image->track[track_id].lba = ntohl(etnf->lba) + (i+1)*GDROM_PREGAP;
1.196 - image->track[track_id].mode = nrg_track_mode( ntohl(etnf->mode) );
1.197 + etnf = (struct nrg_etnf *)data;
1.198 + count = chunk.length / sizeof(struct nrg_etnf);
1.199 + for( i=0; i < count; i++, etnf++ ) {
1.200 + image->track[track_id].offset = GUINT32_FROM_BE(etnf->offset);
1.201 + image->track[track_id].lba = GUINT32_FROM_BE(etnf->lba) + (i+1)*GDROM_PREGAP;
1.202 + image->track[track_id].mode = nrg_track_mode( GUINT32_FROM_BE(etnf->mode) );
1.203 if( image->track[track_id].mode == -1 ) {
1.204 gdrom_image_destroy_no_close(disc);
1.205 return NULL;
1.206 @@ -256,11 +312,33 @@
1.207 else
1.208 image->track[track_id].flags = 0x01 | TRACK_DATA;
1.209 image->track[track_id].sector_size = GDROM_SECTOR_SIZE(image->track[track_id].mode);
1.210 - image->track[track_id].sector_count = ntohl(etnf->length) /
1.211 + image->track[track_id].sector_count = GUINT32_FROM_BE(etnf->length) /
1.212 image->track[track_id].sector_size;
1.213 track_id++;
1.214 }
1.215 break;
1.216 + case ETN2_ID:
1.217 + etn2 = (struct nrg_etn2 *)data;
1.218 + count = chunk.length / sizeof(struct nrg_etn2);
1.219 + for( i=0; i < count; i++, etn2++ ) {
1.220 + image->track[track_id].offset = (uint32_t)GUINT64_FROM_BE(etn2->offset);
1.221 + image->track[track_id].lba = GUINT32_FROM_BE(etn2->lba) + (i+1)*GDROM_PREGAP;
1.222 + image->track[track_id].mode = nrg_track_mode( GUINT32_FROM_BE(etn2->mode) );
1.223 + if( image->track[track_id].mode == -1 ) {
1.224 + gdrom_image_destroy_no_close(disc);
1.225 + return NULL;
1.226 + }
1.227 + if( image->track[track_id].mode == GDROM_CDDA )
1.228 + image->track[track_id].flags = 0x01;
1.229 + else
1.230 + image->track[track_id].flags = 0x01 | TRACK_DATA;
1.231 + image->track[track_id].sector_size = GDROM_SECTOR_SIZE(image->track[track_id].mode);
1.232 + image->track[track_id].sector_count = (uint32_t)(GUINT64_FROM_BE(etn2->length) /
1.233 + image->track[track_id].sector_size);
1.234 + track_id++;
1.235 + }
1.236 + break;
1.237 +
1.238 case END_ID:
1.239 end = TRUE;
1.240 break;
.