~ubuntu-branches/debian/sid/mame/sid

« back to all changes in this revision

Viewing changes to mess/src/tools/chdcd.c

  • Committer: Package Import Robot
  • Author(s): Jordi Mallach, Jordi Mallach, Emmanuel Kasper
  • Date: 2011-12-19 22:56:27 UTC
  • mfrom: (0.1.2)
  • Revision ID: package-import@ubuntu.com-20111219225627-ub5oga1oys4ogqzm
Tags: 0.144-1
[ Jordi Mallach ]
* Fix syntax errors in DEP5 copyright file (lintian).
* Use a versioned copyright Format specification field.
* Update Vcs-* URLs.
* Move transitional packages to the new metapackages section, and make
  them priority extra.
* Remove references to GNU/Linux and MESS sources from copyright.
* Add build variables for s390x.
* Use .xz tarballs as it cuts 4MB for the upstream sources.
* Add nplayers.ini as a patch. Update copyright file to add CC-BY-SA-3.0.

[ Emmanuel Kasper ]
* New upstream release. Closes: #651538.
* Add Free Desktop compliant png icons of various sizes taken from
  the hydroxygen iconset
* Mess is now built from a new source package, to avoid possible source
  incompatibilities between mame and the mess overlay.
* Mame-tools are not built from the mame source package anymore, but
  from the mess source package

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/***************************************************************************
2
 
 
3
 
    TOC parser for CHD compression frontend
4
 
    Handles CDRDAO .toc, CDRWIN .cue, and Sega GDROM .gdi
5
 
 
6
 
    Copyright Nicola Salmoria and the MAME Team.
7
 
    Visit http://mamedev.org for licensing and usage restrictions.
8
 
 
9
 
***************************************************************************/
10
 
 
11
 
#include <ctype.h>
12
 
#include <stdlib.h>
13
 
#include "osdcore.h"
14
 
#include "chd.h"
15
 
#include "chdcd.h"
16
 
#include "corefile.h"
17
 
 
18
 
 
19
 
 
20
 
/***************************************************************************
21
 
    CONSTANTS & DEFINES
22
 
***************************************************************************/
23
 
 
24
 
#define TOKENIZE i = tokenize( linebuffer, i, sizeof(linebuffer), token, sizeof(token) );
25
 
 
26
 
 
27
 
 
28
 
/***************************************************************************
29
 
    GLOBAL VARIABLES
30
 
***************************************************************************/
31
 
 
32
 
static char linebuffer[512];
33
 
 
34
 
 
35
 
 
36
 
/***************************************************************************
37
 
    IMPLEMENTATION
38
 
***************************************************************************/
39
 
 
40
 
/*-------------------------------------------------
41
 
    get_file_size - get the size of a file
42
 
-------------------------------------------------*/
43
 
 
44
 
static UINT64 get_file_size(const char *filename)
45
 
{
46
 
        osd_file *file;
47
 
        UINT64 filesize = 0;
48
 
        file_error filerr;
49
 
 
50
 
        filerr = osd_open(filename, OPEN_FLAG_READ, &file, &filesize);
51
 
        if (filerr == FILERR_NONE)
52
 
                osd_close(file);
53
 
 
54
 
        return filesize;
55
 
}
56
 
 
57
 
 
58
 
/*-------------------------------------------------
59
 
    tokenize - get a token from the line buffer
60
 
-------------------------------------------------*/
61
 
 
62
 
static int tokenize( const char *linebuffer, int i, int linebuffersize, char *token, int tokensize )
63
 
{
64
 
        int j = 0;
65
 
        int singlequote = 0;
66
 
        int doublequote = 0;
67
 
 
68
 
        while ((i < linebuffersize) && isspace((UINT8)linebuffer[i]))
69
 
        {
70
 
                i++;
71
 
        }
72
 
 
73
 
        while ((i < linebuffersize) && (j < tokensize))
74
 
        {
75
 
                if (!singlequote && linebuffer[i] == '"' )
76
 
                {
77
 
                        doublequote = !doublequote;
78
 
                }
79
 
                else if (!doublequote && linebuffer[i] == '\'')
80
 
                {
81
 
                        singlequote = !singlequote;
82
 
                }
83
 
                else if (!singlequote && !doublequote && isspace((UINT8)linebuffer[i]))
84
 
                {
85
 
                        break;
86
 
                }
87
 
                else
88
 
                {
89
 
                        token[j] = linebuffer[i];
90
 
                        j++;
91
 
                }
92
 
 
93
 
                i++;
94
 
        }
95
 
 
96
 
        token[j] = '\0';
97
 
 
98
 
        return i;
99
 
}
100
 
 
101
 
 
102
 
/*-------------------------------------------------
103
 
    msf_to_frames - convert m:s:f into a number of frames
104
 
-------------------------------------------------*/
105
 
 
106
 
static int msf_to_frames( char *token )
107
 
{
108
 
        int m = 0;
109
 
        int s = 0;
110
 
        int f = 0;
111
 
 
112
 
        if( sscanf( token, "%d:%d:%d", &m, &s, &f ) == 1 )
113
 
        {
114
 
                f = m;
115
 
        }
116
 
        else
117
 
        {
118
 
                /* convert to just frames */
119
 
                s += (m * 60);
120
 
                f += (s * 75);
121
 
        }
122
 
 
123
 
        return f;
124
 
}
125
 
 
126
 
/*-------------------------------------------------
127
 
    parse_wav_sample - takes a .WAV file, verifies
128
 
    that the file is 16 bits, and returns the
129
 
    length in bytes of the data and the offset in
130
 
    bytes to where the data starts in the file.
131
 
-------------------------------------------------*/
132
 
static UINT32 parse_wav_sample(char *filename, UINT32 *dataoffs)
133
 
{
134
 
        unsigned long offset = 0;
135
 
        UINT32 length, rate, filesize;
136
 
        UINT16 bits, temp16;
137
 
        char buf[32];
138
 
        osd_file *file;
139
 
        file_error filerr;
140
 
        UINT64 fsize = 0;
141
 
        UINT32 actual;
142
 
 
143
 
        filerr = osd_open(filename, OPEN_FLAG_READ, &file, &fsize);
144
 
        if (filerr != FILERR_NONE)
145
 
        {
146
 
                osd_close(file);
147
 
                return 0;
148
 
        }
149
 
 
150
 
        /* read the core header and make sure it's a WAVE file */
151
 
        osd_read(file, buf, 0, 4, &actual);
152
 
        offset += actual;
153
 
        if (offset < 4)
154
 
                return 0;
155
 
        if (memcmp(&buf[0], "RIFF", 4) != 0)
156
 
                return 0;
157
 
 
158
 
        /* get the total size */
159
 
        osd_read(file, &filesize, offset, 4, &actual);
160
 
        offset += actual;
161
 
        if (offset < 8)
162
 
                return 0;
163
 
        filesize = LITTLE_ENDIANIZE_INT32(filesize);
164
 
 
165
 
        /* read the RIFF file type and make sure it's a WAVE file */
166
 
        osd_read(file, buf, offset, 4, &actual);
167
 
        offset += actual;
168
 
        if (offset < 12)
169
 
                return 0;
170
 
        if (memcmp(&buf[0], "WAVE", 4) != 0)
171
 
                return 0;
172
 
 
173
 
        /* seek until we find a format tag */
174
 
        while (1)
175
 
        {
176
 
                osd_read(file, buf, offset, 4, &actual);
177
 
                offset += actual;
178
 
                osd_read(file, &length, offset, 4, &actual);
179
 
                offset += actual;
180
 
                length = LITTLE_ENDIANIZE_INT32(length);
181
 
                if (memcmp(&buf[0], "fmt ", 4) == 0)
182
 
                        break;
183
 
 
184
 
                /* seek to the next block */
185
 
                offset += length;
186
 
                if (offset >= filesize)
187
 
                        return 0;
188
 
        }
189
 
 
190
 
        /* read the format -- make sure it is PCM */
191
 
        osd_read(file, &temp16, offset, 2, &actual);
192
 
        offset += actual;
193
 
        temp16 = LITTLE_ENDIANIZE_INT16(temp16);
194
 
        if (temp16 != 1)
195
 
                return 0;
196
 
 
197
 
        /* number of channels -- only mono is supported */
198
 
        osd_read(file, &temp16, offset, 2, &actual);
199
 
        offset += actual;
200
 
        temp16 = LITTLE_ENDIANIZE_INT16(temp16);
201
 
        if (temp16 != 2)
202
 
                return 0;
203
 
 
204
 
        /* sample rate */
205
 
        osd_read(file, &rate, offset, 4, &actual);
206
 
        offset += actual;
207
 
        rate = LITTLE_ENDIANIZE_INT32(rate);
208
 
        if (rate != 44100)
209
 
                return 0;
210
 
 
211
 
        /* bytes/second and block alignment are ignored */
212
 
        osd_read(file, buf, offset, 6, &actual);
213
 
        offset += actual;
214
 
 
215
 
        /* bits/sample */
216
 
        osd_read(file, &bits, offset, 2, &actual);
217
 
        offset += actual;
218
 
        if (bits != 16)
219
 
                return 0;
220
 
 
221
 
        /* seek past any extra data */
222
 
        offset += length - 16;
223
 
 
224
 
        /* seek until we find a data tag */
225
 
        while (1)
226
 
        {
227
 
                osd_read(file, buf, offset, 4, &actual);
228
 
                offset += actual;
229
 
                osd_read(file, &length, offset, 4, &actual);
230
 
                offset += actual;
231
 
                length = LITTLE_ENDIANIZE_INT32(length);
232
 
                if (memcmp(&buf[0], "data", 4) == 0)
233
 
                        break;
234
 
 
235
 
                /* seek to the next block */
236
 
                offset += length;
237
 
                if (offset >= filesize)
238
 
                        return 0;
239
 
        }
240
 
 
241
 
        /* if there was a 0 length data block, we're done */
242
 
        if (length == 0)
243
 
                return 0;
244
 
 
245
 
        osd_close(file);
246
 
 
247
 
        *dataoffs = offset;
248
 
 
249
 
        return length;
250
 
}
251
 
 
252
 
UINT16 read_uint16(FILE *infile)
253
 
{
254
 
        UINT16 res = 0;
255
 
        unsigned char buffer[2];
256
 
 
257
 
        fread(buffer, 2, 1, infile);
258
 
 
259
 
        res = buffer[1] | buffer[0]<<8;
260
 
 
261
 
        return res;
262
 
}
263
 
 
264
 
UINT32 read_uint32(FILE *infile)
265
 
{
266
 
        UINT32 res = 0;
267
 
        unsigned char buffer[4];
268
 
 
269
 
        fread(buffer, 4, 1, infile);
270
 
 
271
 
        res = buffer[3] | buffer[2]<<8 | buffer[1]<<16 | buffer[0]<<24;
272
 
 
273
 
        return res;
274
 
}
275
 
 
276
 
UINT64 read_uint64(FILE *infile)
277
 
{
278
 
        UINT64 res0 = U64(0), res1 = U64(0);
279
 
        UINT64 res;
280
 
        unsigned char buffer[8];
281
 
 
282
 
        fread(buffer, 8, 1, infile);
283
 
 
284
 
        res0 = buffer[3] | buffer[2]<<8 | buffer[1]<<16 | buffer[0]<<24;
285
 
        res1 = buffer[7] | buffer[6]<<8 | buffer[5]<<16 | buffer[4]<<24;
286
 
 
287
 
        res = res0<<32 | res1;
288
 
 
289
 
        return res;
290
 
}
291
 
 
292
 
/*-------------------------------------------------
293
 
    chdcd_parse_toc - parse a CDRWin format CUE file
294
 
-------------------------------------------------*/
295
 
 
296
 
chd_error chdcd_parse_nero(const char *tocfname, cdrom_toc *outtoc, chdcd_track_input_info *outinfo)
297
 
{
298
 
        FILE *infile;
299
 
        unsigned char buffer[12];
300
 
        UINT32 chain_offs, chunk_size;
301
 
        int done = 0;
302
 
 
303
 
        infile = fopen(tocfname, "rt");
304
 
 
305
 
        if (infile == (FILE *)NULL)
306
 
        {
307
 
                return CHDERR_FILE_NOT_FOUND;
308
 
        }
309
 
 
310
 
        /* clear structures */
311
 
        memset(outtoc, 0, sizeof(cdrom_toc));
312
 
        memset(outinfo, 0, sizeof(chdcd_track_input_info));
313
 
 
314
 
        // seek to 12 bytes before the end
315
 
        fseek(infile, -12, SEEK_END);
316
 
        fread(buffer, 12, 1, infile);
317
 
 
318
 
        if (memcmp(buffer, "NER5", 4))
319
 
        {
320
 
                printf("ERROR: Not a Nero 5.5 or later image!\n");
321
 
                fclose(infile);
322
 
                return CHDERR_FILE_NOT_FOUND;
323
 
        }
324
 
 
325
 
        chain_offs = buffer[11] | (buffer[10]<<8) | (buffer[9]<<16) | (buffer[8]<<24);
326
 
 
327
 
        if ((buffer[7] != 0) || (buffer[6] != 0) || (buffer[5] != 0) || (buffer[4] != 0))
328
 
        {
329
 
                printf("ERROR: File size is > 4GB, this version of CHDMAN cannot handle it.");
330
 
                fclose(infile);
331
 
                return CHDERR_FILE_NOT_FOUND;
332
 
        }
333
 
 
334
 
//  printf("NER5 detected, chain offset: %x\n", chain_offs);
335
 
 
336
 
        while (!done)
337
 
        {
338
 
                UINT32 offset;
339
 
                UINT8 start, end;
340
 
                int track;
341
 
 
342
 
                fseek(infile, chain_offs, SEEK_SET);
343
 
                fread(buffer, 8, 1, infile);
344
 
 
345
 
                chunk_size = (buffer[7] | buffer[6]<<8 | buffer[5]<<16 | buffer[4]<<24);
346
 
 
347
 
//      printf("Chunk type: %c%c%c%c, size %x\n", buffer[0], buffer[1], buffer[2], buffer[3], chunk_size);
348
 
 
349
 
                // we want the DAOX chunk, which has the TOC information
350
 
                if (!memcmp(buffer, "DAOX", 4))
351
 
                {
352
 
                        // skip second chunk size and UPC code
353
 
                        fseek(infile, 16, SEEK_CUR);
354
 
 
355
 
                        read_uint32(infile);
356
 
                        fread(&start, 1, 1, infile);
357
 
                        fread(&end, 1, 1, infile);
358
 
 
359
 
//          printf("TOC type: %08x.  Start track %d  End track: %d\n", toc_type, start, end);
360
 
 
361
 
                        outtoc->numtrks = (end-start) + 1;
362
 
 
363
 
                        offset = 0;
364
 
                        for (track = start; track <= end; track++)
365
 
                        {
366
 
                                UINT32 size, mode;
367
 
                                UINT64 index0, index1, index2;
368
 
 
369
 
                                fseek(infile, 12, SEEK_CUR);    // skip ISRC code
370
 
                                size = read_uint16(infile);
371
 
                                mode = read_uint32(infile);
372
 
                                index0 = read_uint64(infile);
373
 
                                index1 = read_uint64(infile);
374
 
                                index2 = read_uint64(infile);
375
 
 
376
 
//              printf("Track %d: sector size %d mode %x index0 %llx index1 %llx index2 %llx (pregap %d sectors, length %d sectors)\n", track, size, mode, index0, index1, index2, (UINT32)(index1-index0)/size, (UINT32)(index2-index1)/size);
377
 
 
378
 
                                strcpy(outinfo->fname[track-1], tocfname);
379
 
                                outinfo->offset[track-1] = offset + (UINT32)(index1-index0);
380
 
                                outinfo->idx0offs[track-1] = 0;
381
 
                                outinfo->idx1offs[track-1] = 0;
382
 
 
383
 
                                switch (mode>>24)
384
 
                                {
385
 
                                        case 0x00:      // 2048 byte data
386
 
                                                outtoc->tracks[track-1].trktype = CD_TRACK_MODE1;
387
 
                                                outinfo->swap[track-1] = 0;
388
 
                                                break;
389
 
 
390
 
                                        case 0x06:      // 2352 byte mode 2 raw
391
 
                                                outtoc->tracks[track-1].trktype = CD_TRACK_MODE2_RAW;
392
 
                                                outinfo->swap[track-1] = 0;
393
 
                                                break;
394
 
 
395
 
                                        case 0x07:      // 2352 byte audio
396
 
                                                outtoc->tracks[track-1].trktype = CD_TRACK_AUDIO;
397
 
                                                outinfo->swap[track-1] = 1;
398
 
                                                break;
399
 
 
400
 
                                        default:
401
 
                                                printf("ERROR: Unknown track type %x, contact MAMEDEV!\n", mode>>24);
402
 
                                                break;
403
 
                                }
404
 
 
405
 
                                outtoc->tracks[track-1].datasize = size;
406
 
 
407
 
                                outtoc->tracks[track-1].subtype = CD_SUB_NONE;
408
 
                                outtoc->tracks[track-1].subsize = 0;
409
 
 
410
 
                                outtoc->tracks[track-1].pregap = (UINT32)(index1-index0)/size;
411
 
                                outtoc->tracks[track-1].frames = (UINT32)(index2-index1)/size;
412
 
                                outtoc->tracks[track-1].postgap = 0;
413
 
                                outtoc->tracks[track-1].pgtype = 0;
414
 
                                outtoc->tracks[track-1].pgsub = CD_SUB_NONE;
415
 
                                outtoc->tracks[track-1].pgdatasize = 0;
416
 
                                outtoc->tracks[track-1].pgsubsize = 0;
417
 
 
418
 
                                offset += (UINT32)index2-index1;
419
 
                        }
420
 
                }
421
 
 
422
 
                if (!memcmp(buffer, "END!", 4))
423
 
                {
424
 
                        done = 1;
425
 
                }
426
 
                else
427
 
                {
428
 
                        chain_offs += chunk_size + 8;
429
 
                }
430
 
        }
431
 
 
432
 
        fclose(infile);
433
 
 
434
 
        return CHDERR_NONE;
435
 
}
436
 
 
437
 
/*-------------------------------------------------
438
 
    chdcd_parse_gdi - parse a Sega GD-ROM rip
439
 
-------------------------------------------------*/
440
 
 
441
 
static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc *outtoc, chdcd_track_input_info *outinfo)
442
 
{
443
 
        FILE *infile;
444
 
        int i, numtracks;
445
 
        //int chdpos=0;
446
 
 
447
 
        infile = fopen(tocfname, "rt");
448
 
 
449
 
        if (infile == (FILE *)NULL)
450
 
        {
451
 
                return CHDERR_FILE_NOT_FOUND;
452
 
        }
453
 
 
454
 
        /* clear structures */
455
 
        memset(outtoc, 0, sizeof(cdrom_toc));
456
 
        memset(outinfo, 0, sizeof(chdcd_track_input_info));
457
 
 
458
 
 
459
 
        fgets(linebuffer,511,infile);
460
 
        numtracks=atoi(linebuffer);
461
 
 
462
 
        for(i=0;i<numtracks;++i)
463
 
        {
464
 
                char *tok;
465
 
                int trknum;
466
 
                int trksize,trktype;
467
 
                int sz;
468
 
                int hunks;
469
 
 
470
 
 
471
 
                fgets(linebuffer,511,infile);
472
 
 
473
 
                tok=strtok(linebuffer," ");
474
 
 
475
 
                trknum=atoi(tok)-1;
476
 
 
477
 
                outinfo->swap[trknum]=0;
478
 
                outinfo->offset[trknum]=0;
479
 
 
480
 
                //outtoc->tracks[trknum].trktype = CD_TRACK_MODE1;
481
 
                outtoc->tracks[trknum].datasize = 0;
482
 
                outtoc->tracks[trknum].subtype = CD_SUB_NONE;
483
 
                outtoc->tracks[trknum].subsize = 0;
484
 
 
485
 
                tok=strtok(NULL," ");
486
 
                outtoc->tracks[trknum].physframeofs=atoi(tok);
487
 
 
488
 
                tok=strtok(NULL," ");
489
 
                trktype=atoi(tok);
490
 
 
491
 
                tok=strtok(NULL," ");
492
 
                trksize=atoi(tok);
493
 
 
494
 
                if(trktype==4 && trksize==2352)
495
 
                {
496
 
                        outtoc->tracks[trknum].trktype=CD_TRACK_MODE1_RAW;
497
 
                        outtoc->tracks[trknum].datasize=2352;
498
 
                }
499
 
                if(trktype==4 && trksize==2048)
500
 
                {
501
 
                        outtoc->tracks[trknum].trktype=CD_TRACK_MODE1;
502
 
                        outtoc->tracks[trknum].datasize=2048;
503
 
                }
504
 
                if(trktype==0)
505
 
                {
506
 
                        //assert(trksize==2352);
507
 
                        outtoc->tracks[trknum].trktype=CD_TRACK_AUDIO;
508
 
                        outtoc->tracks[trknum].datasize=2352;
509
 
                }
510
 
 
511
 
                tok=strtok(NULL," ");
512
 
                strcpy(&(outinfo->fname[trknum][0]),tok);
513
 
                sz=get_file_size(outinfo->fname[trknum]);
514
 
 
515
 
                outtoc->tracks[trknum].frames=sz/trksize;
516
 
                outtoc->tracks[trknum].extraframes=0;
517
 
 
518
 
                if(trknum!=0)
519
 
                {
520
 
                        int dif=outtoc->tracks[trknum].physframeofs-(outtoc->tracks[trknum-1].frames+outtoc->tracks[trknum-1].physframeofs);
521
 
                        outtoc->tracks[trknum-1].frames+=dif;
522
 
                }
523
 
 
524
 
/*
525
 
        if(trknum!=0)
526
 
        {
527
 
            outtoc->tracks[trknum-1].extraframes=outtoc->tracks[trknum].physframeofs-(outtoc->tracks[trknum-1].frames+outtoc->tracks[trknum-1].physframeofs);
528
 
        }
529
 
*/
530
 
                hunks = (outtoc->tracks[trknum].frames+CD_FRAMES_PER_HUNK - 1) / CD_FRAMES_PER_HUNK;
531
 
                outtoc->tracks[trknum].extraframes = hunks * CD_FRAMES_PER_HUNK - outtoc->tracks[trknum].frames;
532
 
 
533
 
                //chdpos+=outtoc->tracks[trknum].frames+outtoc->tracks[trknum].extraframes;
534
 
 
535
 
        }
536
 
        /*
537
 
    for(i=0;i<numtracks;++i)
538
 
    {
539
 
        printf("%s %d %d %d\n",outinfo->fname[i],outtoc->tracks[i].frames,outtoc->tracks[i].extraframes,outtoc->tracks[i].physframeofs);
540
 
    }
541
 
    */
542
 
        /* close the input TOC */
543
 
        fclose(infile);
544
 
 
545
 
        /* store the number of tracks found */
546
 
        outtoc->numtrks = numtracks;
547
 
 
548
 
        return CHDERR_NONE;
549
 
}
550
 
 
551
 
/*-------------------------------------------------
552
 
    chdcd_parse_toc - parse a CDRWin format CUE file
553
 
-------------------------------------------------*/
554
 
 
555
 
chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc *outtoc, chdcd_track_input_info *outinfo)
556
 
{
557
 
        FILE *infile;
558
 
        int i, trknum;
559
 
        static char token[128];
560
 
        static char lastfname[128];
561
 
        UINT32 wavlen, wavoffs;
562
 
 
563
 
        infile = fopen(tocfname, "rt");
564
 
 
565
 
        if (infile == (FILE *)NULL)
566
 
        {
567
 
                return CHDERR_FILE_NOT_FOUND;
568
 
        }
569
 
 
570
 
        /* clear structures */
571
 
        memset(outtoc, 0, sizeof(cdrom_toc));
572
 
        memset(outinfo, 0, sizeof(chdcd_track_input_info));
573
 
 
574
 
        trknum = -1;
575
 
        wavoffs = wavlen = 0;
576
 
 
577
 
        while (!feof(infile))
578
 
        {
579
 
                /* get the next line */
580
 
                fgets(linebuffer, 511, infile);
581
 
 
582
 
                /* if EOF didn't hit, keep going */
583
 
                if (!feof(infile))
584
 
                {
585
 
                        i = 0;
586
 
 
587
 
                        TOKENIZE
588
 
 
589
 
                        if (!strcmp(token, "FILE"))
590
 
                        {
591
 
                                /* found the data file for a track */
592
 
                                TOKENIZE
593
 
 
594
 
                                /* keep the filename */
595
 
                                strncpy(lastfname, token, 128);
596
 
 
597
 
                                /* get the file type */
598
 
                                TOKENIZE
599
 
 
600
 
                                if (!strcmp(token, "BINARY"))
601
 
                                {
602
 
                                        outinfo->swap[trknum] = 0;
603
 
                                }
604
 
                                else if (!strcmp(token, "MOTOROLA"))
605
 
                                {
606
 
                                        outinfo->swap[trknum] = 1;
607
 
                                }
608
 
                                else if (!strcmp(token, "WAVE"))
609
 
                                {
610
 
                                        wavlen = parse_wav_sample(lastfname, &wavoffs);
611
 
                                        if (!wavlen)
612
 
                                        {
613
 
                                                file_error err;
614
 
                                                core_file *fhand;
615
 
 
616
 
                                                err = core_fopen(lastfname, OPEN_FLAG_READ, &fhand);
617
 
                                                if (err != FILERR_NONE) printf("holy moley!\n");
618
 
                                                else core_fclose(fhand);
619
 
 
620
 
                                                printf("ERROR: couldn't read [%s] or not a valid .WAV\n", lastfname);
621
 
                                                return CHDERR_FILE_NOT_FOUND;
622
 
                                        }
623
 
                                }
624
 
                                else
625
 
                                {
626
 
                                        printf("ERROR: Unhandled track type %s\n", token);
627
 
                                        return CHDERR_FILE_NOT_FOUND;
628
 
                                }
629
 
                        }
630
 
                        else if (!strcmp(token, "TRACK"))
631
 
                        {
632
 
                                /* get the track number */
633
 
                                TOKENIZE
634
 
                                trknum = strtoul(token, NULL, 10) - 1;
635
 
 
636
 
                                /* next token on the line is the track type */
637
 
                                TOKENIZE
638
 
 
639
 
                                if (wavlen != 0)
640
 
                                {
641
 
                                        outtoc->tracks[trknum].trktype = CD_TRACK_AUDIO;
642
 
                                        outtoc->tracks[trknum].frames = wavlen/2352;
643
 
                                        outinfo->offset[trknum] = wavoffs;
644
 
                                        wavoffs = wavlen = 0;
645
 
                                }
646
 
                                else
647
 
                                {
648
 
                                        outtoc->tracks[trknum].trktype = CD_TRACK_MODE1;
649
 
                                        outtoc->tracks[trknum].datasize = 0;
650
 
                                        outinfo->offset[trknum] = 0;
651
 
                                }
652
 
                                outtoc->tracks[trknum].subtype = CD_SUB_NONE;
653
 
                                outtoc->tracks[trknum].subsize = 0;
654
 
                                outtoc->tracks[trknum].pregap = 0;
655
 
                                outinfo->idx0offs[trknum] = -1;
656
 
                                outinfo->idx1offs[trknum] = 0;
657
 
                                strcpy(&outinfo->fname[trknum][0], lastfname);  // default filename to the last one
658
 
//              printf("trk %d: fname %s offset %d\n", trknum, &outinfo->fname[trknum][0], outinfo->offset[trknum]);
659
 
 
660
 
                                cdrom_convert_type_string_to_track_info(token, &outtoc->tracks[trknum]);
661
 
                                if (outtoc->tracks[trknum].datasize == 0)
662
 
                                {
663
 
                                        printf("ERROR: Unknown track type [%s].  Contact MAMEDEV.\n", token);
664
 
                                        return CHDERR_FILE_NOT_FOUND;
665
 
                                }
666
 
 
667
 
                                /* next (optional) token on the line is the subcode type */
668
 
                                TOKENIZE
669
 
 
670
 
                                cdrom_convert_subtype_string_to_track_info(token, &outtoc->tracks[trknum]);
671
 
                        }
672
 
                        else if (!strcmp(token, "INDEX"))       /* only in bin/cue files */
673
 
                        {
674
 
                                int idx, frames;
675
 
 
676
 
                                /* get index number */
677
 
                                TOKENIZE
678
 
                                idx = strtoul(token, NULL, 10);
679
 
 
680
 
                                /* get index */
681
 
                                TOKENIZE
682
 
                                frames = msf_to_frames( token );
683
 
 
684
 
                                if (idx == 0)
685
 
                                {
686
 
                                        outinfo->idx0offs[trknum] = frames;
687
 
                                }
688
 
                                else if (idx == 1)
689
 
                                {
690
 
                                        outinfo->idx1offs[trknum] = frames;
691
 
                                        if ((outtoc->tracks[trknum].pregap == 0) && (outinfo->idx0offs[trknum] != -1))
692
 
                                        {
693
 
                                                outtoc->tracks[trknum].pregap = frames - outinfo->idx0offs[trknum];
694
 
                                        }
695
 
                                }
696
 
                        }
697
 
                        else if (!strcmp(token, "PREGAP"))
698
 
                        {
699
 
                                int frames;
700
 
 
701
 
                                /* get index */
702
 
                                TOKENIZE
703
 
                                frames = msf_to_frames( token );
704
 
 
705
 
                                outtoc->tracks[trknum].pregap = frames;
706
 
                        }
707
 
                        else if (!strcmp(token, "POSTGAP"))
708
 
                        {
709
 
                                int frames;
710
 
 
711
 
                                /* get index */
712
 
                                TOKENIZE
713
 
                                frames = msf_to_frames( token );
714
 
 
715
 
                                outtoc->tracks[trknum].postgap = frames;
716
 
                        }
717
 
                }
718
 
        }
719
 
 
720
 
        /* close the input CUE */
721
 
        fclose(infile);
722
 
 
723
 
        /* store the number of tracks found */
724
 
        outtoc->numtrks = trknum + 1;
725
 
 
726
 
        /* now go over the files again and set the lengths */
727
 
        for (trknum = 0; trknum < outtoc->numtrks; trknum++)
728
 
        {
729
 
                UINT64 tlen = 0;
730
 
 
731
 
                // this is true for cue/bin and cue/iso, and we need it for cue/wav since .WAV is little-endian
732
 
                if (outtoc->tracks[trknum].trktype == CD_TRACK_AUDIO)
733
 
                {
734
 
                        outinfo->swap[trknum] = 1;
735
 
                }
736
 
 
737
 
                // don't do this for .WAV tracks, we already have their length and offset filled out
738
 
                if (outinfo->offset[trknum] == 0)
739
 
                {
740
 
                        // is this the last track?
741
 
                        if (trknum == (outtoc->numtrks-1))
742
 
                        {
743
 
                                /* if we have the same filename as the last track, do it that way */
744
 
                                if (!strcmp(&outinfo->fname[trknum][0], &outinfo->fname[trknum-1][0]))
745
 
                                {
746
 
                                        tlen = get_file_size(outinfo->fname[trknum]);
747
 
                                        if (tlen == 0)
748
 
                                        {
749
 
                                                printf("ERROR: couldn't find bin file [%s]\n", outinfo->fname[trknum-1]);
750
 
                                                return CHDERR_FILE_NOT_FOUND;
751
 
                                        }
752
 
                                        outinfo->offset[trknum] = outinfo->offset[trknum-1] + outtoc->tracks[trknum-1].frames * (outtoc->tracks[trknum-1].datasize + outtoc->tracks[trknum-1].subsize);
753
 
                                        outtoc->tracks[trknum].frames = (tlen - outinfo->offset[trknum]) / (outtoc->tracks[trknum].datasize + outtoc->tracks[trknum].subsize);
754
 
                                }
755
 
                                else    /* data files are different */
756
 
                                {
757
 
                                        tlen = get_file_size(outinfo->fname[trknum]);
758
 
                                        if (tlen == 0)
759
 
                                        {
760
 
                                                printf("ERROR: couldn't find bin file [%s]\n", outinfo->fname[trknum-1]);
761
 
                                                return CHDERR_FILE_NOT_FOUND;
762
 
                                        }
763
 
                                        tlen /= (outtoc->tracks[trknum].datasize + outtoc->tracks[trknum].subsize);
764
 
                                        outtoc->tracks[trknum].frames = tlen;
765
 
                                        outinfo->offset[trknum] = 0;
766
 
                                }
767
 
                        }
768
 
                        else
769
 
                        {
770
 
                                /* if we have the same filename as the next track, do it that way */
771
 
                                if (!strcmp(&outinfo->fname[trknum][0], &outinfo->fname[trknum+1][0]))
772
 
                                {
773
 
                                        outtoc->tracks[trknum].frames = outinfo->idx1offs[trknum+1] - outinfo->idx1offs[trknum];
774
 
 
775
 
                                        if (trknum == 0)        // track 0 offset is 0
776
 
                                        {
777
 
                                                outinfo->offset[trknum] = 0;
778
 
                                        }
779
 
                                        else
780
 
                                        {
781
 
                                                outinfo->offset[trknum] = outinfo->offset[trknum-1] + outtoc->tracks[trknum-1].frames * (outtoc->tracks[trknum-1].datasize + outtoc->tracks[trknum-1].subsize);
782
 
                                        }
783
 
 
784
 
                                        if (!outtoc->tracks[trknum].frames)
785
 
                                        {
786
 
                                                printf("ERROR: unable to determine size of track %d, missing INDEX 01 markers?\n", trknum+1);
787
 
                                                return CHDERR_FILE_NOT_FOUND;
788
 
                                        }
789
 
                                }
790
 
                                else    /* data files are different */
791
 
                                {
792
 
                                        tlen = get_file_size(outinfo->fname[trknum]);
793
 
                                        if (tlen == 0)
794
 
                                        {
795
 
                                                printf("ERROR: couldn't find bin file [%s]\n", outinfo->fname[trknum]);
796
 
                                                return CHDERR_FILE_NOT_FOUND;
797
 
                                        }
798
 
                                        tlen /= (outtoc->tracks[trknum].datasize + outtoc->tracks[trknum].subsize);
799
 
                                        outtoc->tracks[trknum].frames = tlen;
800
 
                                        outinfo->offset[trknum] = 0;
801
 
                                }
802
 
                        }
803
 
                }
804
 
                printf("trk %d: %d frames @ offset %d\n", trknum+1, outtoc->tracks[trknum].frames, outinfo->offset[trknum]);
805
 
        }
806
 
 
807
 
        return CHDERR_NONE;
808
 
}
809
 
 
810
 
/*-------------------------------------------------
811
 
    chdcd_parse_toc - parse a CDRDAO format TOC file
812
 
-------------------------------------------------*/
813
 
 
814
 
chd_error chdcd_parse_toc(const char *tocfname, cdrom_toc *outtoc, chdcd_track_input_info *outinfo)
815
 
{
816
 
        FILE *infile;
817
 
        int i, trknum;
818
 
        static char token[128];
819
 
 
820
 
        if (strstr(tocfname,".gdi"))
821
 
        {
822
 
                return chdcd_parse_gdi(tocfname, outtoc, outinfo);
823
 
        }
824
 
 
825
 
        if (strstr(tocfname,".cue"))
826
 
        {
827
 
                return chdcd_parse_cue(tocfname, outtoc, outinfo);
828
 
        }
829
 
 
830
 
        if (strstr(tocfname,".nrg"))
831
 
        {
832
 
                return chdcd_parse_nero(tocfname, outtoc, outinfo);
833
 
        }
834
 
 
835
 
        infile = fopen(tocfname, "rt");
836
 
 
837
 
        if (infile == (FILE *)NULL)
838
 
        {
839
 
                return CHDERR_FILE_NOT_FOUND;
840
 
        }
841
 
 
842
 
        /* clear structures */
843
 
        memset(outtoc, 0, sizeof(cdrom_toc));
844
 
        memset(outinfo, 0, sizeof(chdcd_track_input_info));
845
 
 
846
 
        trknum = -1;
847
 
 
848
 
        while (!feof(infile))
849
 
        {
850
 
                /* get the next line */
851
 
                fgets(linebuffer, 511, infile);
852
 
 
853
 
                /* if EOF didn't hit, keep going */
854
 
                if (!feof(infile))
855
 
                {
856
 
                        i = 0;
857
 
 
858
 
                        TOKENIZE
859
 
 
860
 
                        if ((!strcmp(token, "DATAFILE")) || (!strcmp(token, "AUDIOFILE")) || (!strcmp(token, "FILE")))
861
 
                        {
862
 
                                int f;
863
 
 
864
 
                                /* found the data file for a track */
865
 
                                TOKENIZE
866
 
 
867
 
                                /* keep the filename */
868
 
                                strncpy(&outinfo->fname[trknum][0], token, strlen(token));
869
 
 
870
 
                                /* get either the offset or the length */
871
 
                                TOKENIZE
872
 
 
873
 
                                if (!strcmp(token, "SWAP"))
874
 
                                {
875
 
                                        TOKENIZE
876
 
 
877
 
                                        outinfo->swap[trknum] = 1;
878
 
                                }
879
 
                                else
880
 
                                {
881
 
                                        outinfo->swap[trknum] = 0;
882
 
                                }
883
 
 
884
 
                                if (token[0] == '#')
885
 
                                {
886
 
                                        /* it's a decimal offset, use it */
887
 
                                        f = strtoul(&token[1], NULL, 10);
888
 
                                }
889
 
                                else if (isdigit((UINT8)token[0]))
890
 
                                {
891
 
                                        /* convert the time to an offset */
892
 
                                        f = msf_to_frames( token );
893
 
 
894
 
                                        f *= (outtoc->tracks[trknum].datasize + outtoc->tracks[trknum].subsize);
895
 
                                }
896
 
                                else
897
 
                                {
898
 
                                        f = 0;
899
 
                                }
900
 
 
901
 
                                outinfo->offset[trknum] = f;
902
 
 
903
 
                                TOKENIZE
904
 
 
905
 
                                if (isdigit((UINT8)token[0]))
906
 
                                {
907
 
                                        // this could be the length or an offset from the previous field.
908
 
                                        f = msf_to_frames( token );
909
 
 
910
 
                                        TOKENIZE
911
 
 
912
 
                                        if (isdigit((UINT8)token[0]))
913
 
                                        {
914
 
                                                // it was an offset.
915
 
                                                f *= (outtoc->tracks[trknum].datasize + outtoc->tracks[trknum].subsize);
916
 
 
917
 
                                                outinfo->offset[trknum] += f;
918
 
 
919
 
                                                // this is the length.
920
 
                                                f = msf_to_frames( token );
921
 
                                        }
922
 
                                }
923
 
                                else if( trknum == 0 && outinfo->offset[trknum] != 0 )
924
 
                                {
925
 
                                        /* the 1st track might have a length with no offset */
926
 
                                        f = outinfo->offset[trknum] / (outtoc->tracks[trknum].datasize + outtoc->tracks[trknum].subsize);
927
 
                                        outinfo->offset[trknum] = 0;
928
 
                                }
929
 
                                else
930
 
                                {
931
 
                                        /* guesstimate the track length? */
932
 
                                        f = 0;
933
 
                                }
934
 
 
935
 
                                outtoc->tracks[trknum].frames = f;
936
 
                        }
937
 
                        else if (!strcmp(token, "TRACK"))
938
 
                        {
939
 
                                trknum++;
940
 
 
941
 
                                /* next token on the line is the track type */
942
 
                                TOKENIZE
943
 
 
944
 
                                outtoc->tracks[trknum].trktype = CD_TRACK_MODE1;
945
 
                                outtoc->tracks[trknum].datasize = 0;
946
 
                                outtoc->tracks[trknum].subtype = CD_SUB_NONE;
947
 
                                outtoc->tracks[trknum].subsize = 0;
948
 
 
949
 
                                cdrom_convert_type_string_to_track_info(token, &outtoc->tracks[trknum]);
950
 
                                if (outtoc->tracks[trknum].datasize == 0)
951
 
                                {
952
 
                                        printf("ERROR: Unknown track type [%s].  Contact MAMEDEV.\n", token);
953
 
                                        return CHDERR_FILE_NOT_FOUND;
954
 
                                }
955
 
 
956
 
                                /* next (optional) token on the line is the subcode type */
957
 
                                TOKENIZE
958
 
 
959
 
                                cdrom_convert_subtype_string_to_track_info(token, &outtoc->tracks[trknum]);
960
 
                        }
961
 
                        else if (!strcmp(token, "START"))
962
 
                        {
963
 
                                int frames;
964
 
 
965
 
                                /* get index */
966
 
                                TOKENIZE
967
 
                                frames = msf_to_frames( token );
968
 
 
969
 
                                outtoc->tracks[trknum].pregap = frames;
970
 
                        }
971
 
                }
972
 
        }
973
 
 
974
 
        /* close the input TOC */
975
 
        fclose(infile);
976
 
 
977
 
        /* store the number of tracks found */
978
 
        outtoc->numtrks = trknum + 1;
979
 
 
980
 
        return CHDERR_NONE;
981
 
}