1 #include "chdtypes.h"
2
3 /***************************************************************************
4
5 cdrom.c
6
7 Generic MAME CD-ROM utilties - build IDE and SCSI CD-ROMs on top of this
8
9 ****************************************************************************
10
11 Copyright Aaron Giles
12 All rights reserved.
13
14 Redistribution and use in source and binary forms, with or without
15 modification, are permitted provided that the following conditions are
16 met:
17
18 * Redistributions of source code must retain the above copyright
19 notice, this list of conditions and the following disclaimer.
20 * Redistributions in binary form must reproduce the above copyright
21 notice, this list of conditions and the following disclaimer in
22 the documentation and/or other materials provided with the
23 distribution.
24 * Neither the name 'MAME' nor the names of its contributors may be
25 used to endorse or promote products derived from this software
26 without specific prior written permission.
27
28 THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
29 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
30 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
32 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
37 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 POSSIBILITY OF SUCH DAMAGE.
39
40 ****************************************************************************
41
42 IMPORTANT:
43 "physical" block addresses are the actual addresses on the emulated CD.
44 "chd" block addresses are the block addresses in the CHD file.
45 Because we pad each track to a 4-frame boundry, these addressing
46 schemes will differ after track 1!
47
48 ***************************************************************************/
49
50 #include "chdcdrom.h"
51
52 #include <stdlib.h>
53 #include "chdcd.h"
54
55
56 /***************************************************************************
57 DEBUGGING
58 ***************************************************************************/
59
60 #define VERBOSE (0)
61 #if VERBOSE
62 #define LOG(x) do { if (VERBOSE) logerror x; } while (0)
63 void CLIB_DECL logerror(const char *text,...);
64 #else
65 #define LOG(x)
66 #endif
67
68
69
70 /***************************************************************************
71 CONSTANTS
72 ***************************************************************************/
73
74 const int SYNC_OFFSET = 0x000; // offset within sector
75 const int SYNC_NUM_BYTES = 12; // 12 bytes
76
77 const int MODE_OFFSET = 0x00f; // offset within sector
78
79 const int ECC_P_OFFSET = 0x81c; // offset within sector
80 const int ECC_P_NUM_BYTES = 86; // 2 lots of 86
81 const int ECC_P_COMP = 24; // 24 bytes each
82
83 const int ECC_Q_OFFSET = ECC_P_OFFSET + 2 * ECC_P_NUM_BYTES;
84 const int ECC_Q_NUM_BYTES = 52; // 2 lots of 52
85 const int ECC_Q_COMP = 43; // 43 bytes each
86
87
88
89 /***************************************************************************
90 TYPE DEFINITIONS
91 ***************************************************************************/
92
93 struct cdrom_file
94 {
95 chd_file * chd; /* CHD file */
96 cdrom_toc cdtoc; /* TOC for the CD */
97 chdcd_track_input_info track_info; /* track info */
98 struct zfile * fhandle[CD_MAX_TRACKS];/* file handle */
99 };
100
101
102
103 /***************************************************************************
104 INLINE FUNCTIONS
105 ***************************************************************************/
106
107 /*-------------------------------------------------
108 physical_to_chd_lba - find the CHD LBA
109 and the track number
110 -------------------------------------------------*/
111
physical_to_chd_lba(cdrom_file * file,UINT32 physlba,UINT32 & tracknum)112 INLINE UINT32 physical_to_chd_lba(cdrom_file *file, UINT32 physlba, UINT32 &tracknum)
113 {
114 UINT32 chdlba;
115 int track;
116
117 /* loop until our current LBA is less than the start LBA of the next track */
118 for (track = 0; track < file->cdtoc.numtrks; track++)
119 if (physlba < file->cdtoc.tracks[track + 1].physframeofs)
120 {
121 chdlba = physlba - file->cdtoc.tracks[track].physframeofs + file->cdtoc.tracks[track].chdframeofs;
122 tracknum = track;
123 return chdlba;
124 }
125
126 return physlba;
127 }
128
129
130
131 /***************************************************************************
132 BASE FUNCTIONALITY
133 ***************************************************************************/
134
135 #if 0
136 cdrom_file *cdrom_open(const char *inputfile)
137 {
138 int i;
139 cdrom_file *file;
140 UINT32 physofs;
141
142 /* allocate memory for the CD-ROM file */
143 file = new cdrom_file();
144 if (file == NULL)
145 return NULL;
146
147 /* setup the CDROM module and get the disc info */
148 chd_error err = chdcd_parse_toc(inputfile, file->cdtoc, file->track_info);
149 if (err != CHDERR_NONE)
150 {
151 fprintf(stderr, "Error reading input file: %s\n", chd_file::error_string(err));
152 delete file;
153 return NULL;
154 }
155
156 /* fill in the data */
157 file->chd = NULL;
158
159 LOG(("CD has %d tracks\n", file->cdtoc.numtrks));
160
161 for (i = 0; i < file->cdtoc.numtrks; i++)
162 {
163 file_error filerr = core_fopen(file->track_info.track[i].fname, OPEN_FLAG_READ, &file->fhandle[i]);
164 if (filerr != FILERR_NONE)
165 {
166 fprintf(stderr, "Unable to open file: %s\n", file->track_info.track[i].fname.cstr());
167 cdrom_close(file);
168 return NULL;
169 }
170 }
171 /* calculate the starting frame for each track, keeping in mind that CHDMAN
172 pads tracks out with extra frames to fit 4-frame size boundries
173 */
174 physofs = 0;
175 for (i = 0; i < file->cdtoc.numtrks; i++)
176 {
177 file->cdtoc.tracks[i].physframeofs = physofs;
178 file->cdtoc.tracks[i].chdframeofs = 0;
179
180 physofs += file->cdtoc.tracks[i].frames;
181
182 LOG(("Track %02d is format %d subtype %d datasize %d subsize %d frames %d extraframes %d physofs %d chdofs %d\n", i+1,
183 file->cdtoc.tracks[i].trktype,
184 file->cdtoc.tracks[i].subtype,
185 file->cdtoc.tracks[i].datasize,
186 file->cdtoc.tracks[i].subsize,
187 file->cdtoc.tracks[i].frames,
188 file->cdtoc.tracks[i].extraframes,
189 file->cdtoc.tracks[i].physframeofs,
190 file->cdtoc.tracks[i].chdframeofs));
191 }
192
193 /* fill out dummy entries for the last track to help our search */
194 file->cdtoc.tracks[i].physframeofs = physofs;
195 file->cdtoc.tracks[i].chdframeofs = 0;
196
197 return file;
198 }
199 #endif
200
201 /*-------------------------------------------------
202 cdrom_open - "open" a CD-ROM file from an
203 already-opened CHD file
204 -------------------------------------------------*/
205
cdrom_open(chd_file * chd)206 cdrom_file *cdrom_open(chd_file *chd)
207 {
208 int i;
209 cdrom_file *file;
210 UINT32 physofs, chdofs;
211 chd_error err;
212
213 /* punt if no CHD */
214 if (!chd)
215 return NULL;
216
217 /* validate the CHD information */
218 if (chd->hunk_bytes() % CD_FRAME_SIZE != 0)
219 return NULL;
220 if (chd->unit_bytes() != CD_FRAME_SIZE)
221 return NULL;
222
223 /* allocate memory for the CD-ROM file */
224 file = new cdrom_file();
225 if (file == NULL)
226 return NULL;
227
228 /* fill in the data */
229 file->chd = chd;
230
231 /* read the CD-ROM metadata */
232 err = cdrom_parse_metadata(chd, &file->cdtoc);
233 if (err != CHDERR_NONE)
234 {
235 delete file;
236 return NULL;
237 }
238
239 LOG(("CD has %d tracks\n", file->cdtoc.numtrks));
240
241 /* calculate the starting frame for each track, keeping in mind that CHDMAN
242 pads tracks out with extra frames to fit 4-frame size boundries
243 */
244 physofs = chdofs = 0;
245 for (i = 0; i < file->cdtoc.numtrks; i++)
246 {
247 file->cdtoc.tracks[i].physframeofs = physofs;
248 file->cdtoc.tracks[i].chdframeofs = chdofs;
249
250 physofs += file->cdtoc.tracks[i].frames;
251 chdofs += file->cdtoc.tracks[i].frames;
252 chdofs += file->cdtoc.tracks[i].extraframes;
253
254 LOG(("Track %02d is format %d subtype %d datasize %d subsize %d frames %d extraframes %d physofs %d chdofs %d\n", i+1,
255 file->cdtoc.tracks[i].trktype,
256 file->cdtoc.tracks[i].subtype,
257 file->cdtoc.tracks[i].datasize,
258 file->cdtoc.tracks[i].subsize,
259 file->cdtoc.tracks[i].frames,
260 file->cdtoc.tracks[i].extraframes,
261 file->cdtoc.tracks[i].physframeofs,
262 file->cdtoc.tracks[i].chdframeofs));
263 }
264
265 /* fill out dummy entries for the last track to help our search */
266 file->cdtoc.tracks[i].physframeofs = physofs;
267 file->cdtoc.tracks[i].chdframeofs = chdofs;
268
269 return file;
270 }
271
272
273 /*-------------------------------------------------
274 cdrom_close - "close" a CD-ROM file
275 -------------------------------------------------*/
276
cdrom_close(cdrom_file * file)277 void cdrom_close(cdrom_file *file)
278 {
279 if (file == NULL)
280 return;
281
282 if (file->chd == NULL)
283 {
284 for (int i = 0; i < file->cdtoc.numtrks; i++)
285 {
286 zfile_fclose(file->fhandle[i]);
287 }
288 }
289
290 delete file;
291 }
292
293
294
295 /***************************************************************************
296 CORE READ ACCESS
297 ***************************************************************************/
298
read_partial_sector(cdrom_file * file,void * dest,UINT32 chdsector,UINT32 tracknum,UINT32 startoffs,UINT32 length)299 chd_error read_partial_sector(cdrom_file *file, void *dest, UINT32 chdsector, UINT32 tracknum, UINT32 startoffs, UINT32 length)
300 {
301 // if a CHD, just read
302 if (file->chd != NULL)
303 return file->chd->read_bytes(UINT64(chdsector) * UINT64(CD_FRAME_SIZE) + startoffs, dest, length);
304 #if 0
305 // else read from the appropriate file
306 core_file *srcfile = file->fhandle[tracknum];
307
308 UINT64 sourcefileoffset = file->track_info.track[tracknum].offset;
309 int bytespersector = file->cdtoc.tracks[tracknum].datasize + file->cdtoc.tracks[tracknum].subsize;
310
311 sourcefileoffset += chdsector * bytespersector + startoffs;
312
313 core_fseek(srcfile, sourcefileoffset, SEEK_SET);
314 core_fread(srcfile, dest, length);
315
316 if (file->track_info.track[tracknum].swap)
317 {
318 UINT8 *buffer = (UINT8 *)dest - startoffs;
319 for (int swapindex = startoffs; swapindex < 2352; swapindex += 2 )
320 {
321 int swaptemp = buffer[ swapindex ];
322 buffer[ swapindex ] = buffer[ swapindex + 1 ];
323 buffer[ swapindex + 1 ] = swaptemp;
324 }
325 }
326 #endif
327 return CHDERR_NONE;
328 }
329
330
331 /*-------------------------------------------------
332 cdrom_read_data - read one or more sectors
333 from a CD-ROM
334 -------------------------------------------------*/
335
cdrom_read_data(cdrom_file * file,UINT32 lbasector,void * buffer,UINT32 datatype)336 UINT32 cdrom_read_data(cdrom_file *file, UINT32 lbasector, void *buffer, UINT32 datatype)
337 {
338 if (file == NULL)
339 return 0;
340
341 // compute CHD sector and tracknumber
342 UINT32 tracknum = 0;
343 UINT32 chdsector = physical_to_chd_lba(file, lbasector, tracknum);
344
345 /* copy out the requested sector */
346 UINT32 tracktype = file->cdtoc.tracks[tracknum].trktype;
347 if ((datatype == tracktype) || (datatype == CD_TRACK_RAW_DONTCARE))
348 {
349 return (read_partial_sector(file, buffer, chdsector, tracknum, 0, file->cdtoc.tracks[tracknum].datasize) == CHDERR_NONE);
350 }
351 else
352 {
353 /* return 2048 bytes of mode 1 data from a 2352 byte mode 1 raw sector */
354 if ((datatype == CD_TRACK_MODE1) && (tracktype == CD_TRACK_MODE1_RAW))
355 {
356 return (read_partial_sector(file, buffer, chdsector, tracknum, 16, 2048) == CHDERR_NONE);
357 }
358
359 /* return 2352 byte mode 1 raw sector from 2048 bytes of mode 1 data */
360 if ((datatype == CD_TRACK_MODE1_RAW) && (tracktype == CD_TRACK_MODE1))
361 {
362 UINT8 *bufptr = (UINT8 *)buffer;
363 UINT32 msf = lba_to_msf(lbasector);
364
365 static const UINT8 syncbytes[12] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00};
366 memcpy(bufptr, syncbytes, 12);
367 bufptr[12] = msf>>16;
368 bufptr[13] = msf>>8;
369 bufptr[14] = msf&0xff;
370 bufptr[15] = 1; // mode 1
371 LOG(("CDROM: promotion of mode1/form1 sector to mode1 raw is not complete!\n"));
372 return (read_partial_sector(file, bufptr+16, chdsector, tracknum, 0, 2048) == CHDERR_NONE);
373 }
374
375 /* return 2048 bytes of mode 1 data from a mode2 form1 or raw sector */
376 if ((datatype == CD_TRACK_MODE1) && ((tracktype == CD_TRACK_MODE2_FORM1)||(tracktype == CD_TRACK_MODE2_RAW)))
377 {
378 return (read_partial_sector(file, buffer, chdsector, tracknum, 24, 2048) == CHDERR_NONE);
379 }
380
381 /* return mode 2 2336 byte data from a 2352 byte mode 1 or 2 raw sector (skip the header) */
382 if ((datatype == CD_TRACK_MODE2) && ((tracktype == CD_TRACK_MODE1_RAW) || (tracktype == CD_TRACK_MODE2_RAW)))
383 {
384 return (read_partial_sector(file, buffer, chdsector, tracknum, 16, 2336) == CHDERR_NONE);
385 }
386
387 LOG(("CDROM: Conversion from type %d to type %d not supported!\n", tracktype, datatype));
388 return 0;
389 }
390 }
391
392
393 /*-------------------------------------------------
394 cdrom_read_subcode - read subcode data for
395 a sector
396 -------------------------------------------------*/
397
cdrom_read_subcode(cdrom_file * file,UINT32 lbasector,void * buffer)398 UINT32 cdrom_read_subcode(cdrom_file *file, UINT32 lbasector, void *buffer)
399 {
400 if (file == NULL)
401 return ~0;
402
403 // compute CHD sector and tracknumber
404 UINT32 tracknum = 0;
405 UINT32 chdsector = physical_to_chd_lba(file, lbasector, tracknum);
406 if (file->cdtoc.tracks[tracknum].subsize == 0)
407 return 1;
408
409 // read the data
410 chd_error err = read_partial_sector(file, buffer, chdsector, tracknum, file->cdtoc.tracks[tracknum].datasize, file->cdtoc.tracks[tracknum].subsize);
411 return (err == CHDERR_NONE);
412 }
413
414
415
416 /***************************************************************************
417 HANDY UTILITIES
418 ***************************************************************************/
419
420 /*-------------------------------------------------
421 cdrom_get_track - get the track number
422 for a physical frame number
423 -------------------------------------------------*/
424
cdrom_get_track(cdrom_file * file,UINT32 frame)425 UINT32 cdrom_get_track(cdrom_file *file, UINT32 frame)
426 {
427 UINT32 track = 0;
428
429 if (file == NULL)
430 return ~0;
431
432 /* convert to a CHD sector offset and get track information */
433 physical_to_chd_lba(file, frame, track);
434 return track;
435 }
436
437
438 /*-------------------------------------------------
439 cdrom_get_track_start - get the frame number
440 that a track starts at
441 -------------------------------------------------*/
442
cdrom_get_track_start(cdrom_file * file,UINT32 track)443 UINT32 cdrom_get_track_start(cdrom_file *file, UINT32 track)
444 {
445 if (file == NULL)
446 return ~0;
447
448 /* handle lead-out specially */
449 if (track == 0xaa)
450 track = file->cdtoc.numtrks;
451
452 return file->cdtoc.tracks[track].physframeofs;
453 }
454
455
456
457 /***************************************************************************
458 TOC UTILITIES
459 ***************************************************************************/
460
461 /*-------------------------------------------------
462 cdrom_get_last_track - returns the last track
463 number
464 -------------------------------------------------*/
465
cdrom_get_last_track(cdrom_file * file)466 int cdrom_get_last_track(cdrom_file *file)
467 {
468 if (file == NULL)
469 return -1;
470
471 return file->cdtoc.numtrks;
472 }
473
474
475 /*-------------------------------------------------
476 cdrom_get_adr_control - get the ADR | CONTROL
477 for a track
478 -------------------------------------------------*/
479
cdrom_get_adr_control(cdrom_file * file,int track)480 int cdrom_get_adr_control(cdrom_file *file, int track)
481 {
482 if (file == NULL)
483 return -1;
484
485 if (track == 0xaa || file->cdtoc.tracks[track].trktype == CD_TRACK_AUDIO)
486 {
487 return 0x10; // audio track, subchannel is position
488 }
489
490 return 0x14; // data track, subchannel is position
491 }
492
493
494 /*-------------------------------------------------
495 cdrom_get_track_type - return the track type
496 -------------------------------------------------*/
497
cdrom_get_track_type(cdrom_file * file,int track)498 int cdrom_get_track_type(cdrom_file *file, int track)
499 {
500 if (file == NULL)
501 return -1;
502
503 return file->cdtoc.tracks[track].trktype;
504 }
505
506
507 /*-------------------------------------------------
508 cdrom_get_toc - return the TOC data for a
509 CD-ROM
510 -------------------------------------------------*/
511
cdrom_get_toc(cdrom_file * file)512 const cdrom_toc *cdrom_get_toc(cdrom_file *file)
513 {
514 if (file == NULL)
515 return NULL;
516
517 return &file->cdtoc;
518 }
519
520
521
522 /***************************************************************************
523 EXTRA UTILITIES
524 ***************************************************************************/
525
526 /*-------------------------------------------------
527 cdrom_get_info_from_type_string
528 take a string and convert it into track type
529 and track data size
530 -------------------------------------------------*/
531
cdrom_get_info_from_type_string(const char * typestring,UINT32 * trktype,UINT32 * datasize)532 static void cdrom_get_info_from_type_string(const char *typestring, UINT32 *trktype, UINT32 *datasize)
533 {
534 if (!strcmp(typestring, "MODE1"))
535 {
536 *trktype = CD_TRACK_MODE1;
537 *datasize = 2048;
538 }
539 else if (!strcmp(typestring, "MODE1/2048"))
540 {
541 *trktype = CD_TRACK_MODE1;
542 *datasize = 2048;
543 }
544 else if (!strcmp(typestring, "MODE1_RAW"))
545 {
546 *trktype = CD_TRACK_MODE1_RAW;
547 *datasize = 2352;
548 }
549 else if (!strcmp(typestring, "MODE1/2352"))
550 {
551 *trktype = CD_TRACK_MODE1_RAW;
552 *datasize = 2352;
553 }
554 else if (!strcmp(typestring, "MODE2"))
555 {
556 *trktype = CD_TRACK_MODE2;
557 *datasize = 2336;
558 }
559 else if (!strcmp(typestring, "MODE2/2336"))
560 {
561 *trktype = CD_TRACK_MODE2;
562 *datasize = 2336;
563 }
564 else if (!strcmp(typestring, "MODE2_FORM1"))
565 {
566 *trktype = CD_TRACK_MODE2_FORM1;
567 *datasize = 2048;
568 }
569 else if (!strcmp(typestring, "MODE2/2048"))
570 {
571 *trktype = CD_TRACK_MODE2_FORM1;
572 *datasize = 2048;
573 }
574 else if (!strcmp(typestring, "MODE2_FORM2"))
575 {
576 *trktype = CD_TRACK_MODE2_FORM2;
577 *datasize = 2324;
578 }
579 else if (!strcmp(typestring, "MODE2/2324"))
580 {
581 *trktype = CD_TRACK_MODE2_FORM2;
582 *datasize = 2324;
583 }
584 else if (!strcmp(typestring, "MODE2_FORM_MIX"))
585 {
586 *trktype = CD_TRACK_MODE2_FORM_MIX;
587 *datasize = 2336;
588 }
589 else if (!strcmp(typestring, "MODE2/2336"))
590 {
591 *trktype = CD_TRACK_MODE2_FORM_MIX;
592 *datasize = 2336;
593 }
594 else if (!strcmp(typestring, "MODE2_RAW"))
595 {
596 *trktype = CD_TRACK_MODE2_RAW;
597 *datasize = 2352;
598 }
599 else if (!strcmp(typestring, "MODE2/2352"))
600 {
601 *trktype = CD_TRACK_MODE2_RAW;
602 *datasize = 2352;
603 }
604 else if (!strcmp(typestring, "AUDIO"))
605 {
606 *trktype = CD_TRACK_AUDIO;
607 *datasize = 2352;
608 }
609 }
610
611 /*-------------------------------------------------
612 cdrom_convert_type_string_to_track_info -
613 take a string and convert it into track type
614 and track data size
615 -------------------------------------------------*/
616
cdrom_convert_type_string_to_track_info(const char * typestring,cdrom_track_info * info)617 void cdrom_convert_type_string_to_track_info(const char *typestring, cdrom_track_info *info)
618 {
619 cdrom_get_info_from_type_string(typestring, &info->trktype, &info->datasize);
620 }
621
622 /*-------------------------------------------------
623 cdrom_convert_type_string_to_pregap_info -
624 take a string and convert it into pregap type
625 and pregap data size
626 -------------------------------------------------*/
627
cdrom_convert_type_string_to_pregap_info(const char * typestring,cdrom_track_info * info)628 void cdrom_convert_type_string_to_pregap_info(const char *typestring, cdrom_track_info *info)
629 {
630 cdrom_get_info_from_type_string(typestring, &info->pgtype, &info->pgdatasize);
631 }
632
633 /*-------------------------------------------------
634 cdrom_convert_subtype_string_to_track_info -
635 take a string and convert it into track subtype
636 and track subcode data size
637 -------------------------------------------------*/
638
cdrom_convert_subtype_string_to_track_info(const char * typestring,cdrom_track_info * info)639 void cdrom_convert_subtype_string_to_track_info(const char *typestring, cdrom_track_info *info)
640 {
641 if (!strcmp(typestring, "RW"))
642 {
643 info->subtype = CD_SUB_NORMAL;
644 info->subsize = 96;
645 }
646 else if (!strcmp(typestring, "RW_RAW"))
647 {
648 info->subtype = CD_SUB_RAW;
649 info->subsize = 96;
650 }
651 }
652
653 /*-------------------------------------------------
654 cdrom_convert_subtype_string_to_pregap_info -
655 take a string and convert it into track subtype
656 and track subcode data size
657 -------------------------------------------------*/
658
cdrom_convert_subtype_string_to_pregap_info(const char * typestring,cdrom_track_info * info)659 void cdrom_convert_subtype_string_to_pregap_info(const char *typestring, cdrom_track_info *info)
660 {
661 if (!strcmp(typestring, "RW"))
662 {
663 info->pgsub = CD_SUB_NORMAL;
664 info->pgsubsize = 96;
665 }
666 else if (!strcmp(typestring, "RW_RAW"))
667 {
668 info->pgsub = CD_SUB_RAW;
669 info->pgsubsize = 96;
670 }
671 }
672
673 /*-------------------------------------------------
674 cdrom_get_type_string - get the string
675 associated with the given type
676 -------------------------------------------------*/
677
cdrom_get_type_string(UINT32 trktype)678 const char *cdrom_get_type_string(UINT32 trktype)
679 {
680 switch (trktype)
681 {
682 case CD_TRACK_MODE1: return "MODE1";
683 case CD_TRACK_MODE1_RAW: return "MODE1_RAW";
684 case CD_TRACK_MODE2: return "MODE2";
685 case CD_TRACK_MODE2_FORM1: return "MODE2_FORM1";
686 case CD_TRACK_MODE2_FORM2: return "MODE2_FORM2";
687 case CD_TRACK_MODE2_FORM_MIX: return "MODE2_FORM_MIX";
688 case CD_TRACK_MODE2_RAW: return "MODE2_RAW";
689 case CD_TRACK_AUDIO: return "AUDIO";
690 default: return "UNKNOWN";
691 }
692 }
693
694
695 /*-------------------------------------------------
696 cdrom_get_subtype_string - get the string
697 associated with the given subcode type
698 -------------------------------------------------*/
699
cdrom_get_subtype_string(UINT32 subtype)700 const char *cdrom_get_subtype_string(UINT32 subtype)
701 {
702 switch (subtype)
703 {
704 case CD_SUB_NORMAL: return "RW";
705 case CD_SUB_RAW: return "RW_RAW";
706 default: return "NONE";
707 }
708 }
709
710
711
712 /***************************************************************************
713 INTERNAL UTILITIES
714 ***************************************************************************/
715
716 /*-------------------------------------------------
717 cdrom_parse_metadata - parse metadata into the
718 TOC structure
719 -------------------------------------------------*/
720
cdrom_parse_metadata(chd_file * chd,cdrom_toc * toc)721 chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc)
722 {
723 astring metadata;
724 chd_error err;
725 int i;
726
727 /* start with no tracks */
728 for (toc->numtrks = 0; toc->numtrks < CD_MAX_TRACKS; toc->numtrks++)
729 {
730 int tracknum = -1, frames = 0, pregap, postgap, padframes;
731 char type[16], subtype[16], pgtype[16], pgsub[16];
732 cdrom_track_info *track;
733
734 pregap = postgap = padframes = 0;
735
736 /* fetch the metadata for this track */
737 err = chd->read_metadata(CDROM_TRACK_METADATA_TAG, toc->numtrks, metadata);
738 if (err == CHDERR_NONE)
739 {
740 /* parse the metadata */
741 type[0] = subtype[0] = 0;
742 pgtype[0] = pgsub[0] = 0;
743 if (sscanf(metadata, CDROM_TRACK_METADATA_FORMAT, &tracknum, type, subtype, &frames) != 4)
744 return CHDERR_INVALID_DATA;
745 if (tracknum == 0 || tracknum > CD_MAX_TRACKS)
746 return CHDERR_INVALID_DATA;
747 track = &toc->tracks[tracknum - 1];
748 }
749 else
750 {
751 err = chd->read_metadata(CDROM_TRACK_METADATA2_TAG, toc->numtrks, metadata);
752 if (err == CHDERR_NONE)
753 {
754 /* parse the metadata */
755 type[0] = subtype[0] = 0;
756 pregap = postgap = 0;
757 if (sscanf(metadata, CDROM_TRACK_METADATA2_FORMAT, &tracknum, type, subtype, &frames, &pregap, pgtype, pgsub, &postgap) != 8)
758 return CHDERR_INVALID_DATA;
759 if (tracknum == 0 || tracknum > CD_MAX_TRACKS)
760 return CHDERR_INVALID_DATA;
761 track = &toc->tracks[tracknum - 1];
762 }
763 else
764 {
765 err = chd->read_metadata(GDROM_TRACK_METADATA_TAG, toc->numtrks, metadata);
766
767 if (err == CHDERR_NONE)
768 {
769 /* parse the metadata */
770 type[0] = subtype[0] = 0;
771 pregap = postgap = 0;
772 if (sscanf(metadata, GDROM_TRACK_METADATA_FORMAT, &tracknum, type, subtype, &frames, &padframes, &pregap, pgtype, pgsub, &postgap) != 9)
773 return CHDERR_INVALID_DATA;
774 if (tracknum == 0 || tracknum > CD_MAX_TRACKS)
775 return CHDERR_INVALID_DATA;
776 track = &toc->tracks[tracknum - 1];
777 }
778 else
779 {
780 break;
781 }
782 }
783 }
784
785 /* extract the track type and determine the data size */
786 track->trktype = CD_TRACK_MODE1;
787 track->datasize = 0;
788 cdrom_convert_type_string_to_track_info(type, track);
789 if (track->datasize == 0)
790 return CHDERR_INVALID_DATA;
791
792 /* extract the subtype and determine the subcode data size */
793 track->subtype = CD_SUB_NONE;
794 track->subsize = 0;
795 cdrom_convert_subtype_string_to_track_info(subtype, track);
796
797 /* set the frames and extra frames data */
798 track->frames = frames;
799 track->padframes = padframes;
800 int padded = (frames + CD_TRACK_PADDING - 1) / CD_TRACK_PADDING;
801 track->extraframes = padded * CD_TRACK_PADDING - frames;
802
803 /* set the pregap info */
804 track->pregap = pregap;
805 track->pgtype = CD_TRACK_MODE1;
806 track->pgsub = CD_SUB_NONE;
807 track->pgdatasize = 0;
808 track->pgsubsize = 0;
809 cdrom_convert_type_string_to_pregap_info(pgtype, track);
810 cdrom_convert_subtype_string_to_pregap_info(pgsub, track);
811
812 /* set the postgap info */
813 track->postgap = postgap;
814 }
815
816 /* if we got any tracks this way, we're done */
817 if (toc->numtrks > 0)
818 return CHDERR_NONE;
819
820 //printf("toc->numtrks = %d?!\n", toc->numtrks);
821
822 /* look for old-style metadata */
823 dynamic_buffer oldmetadata;
824 err = chd->read_metadata(CDROM_OLD_METADATA_TAG, 0, oldmetadata);
825 if (err != CHDERR_NONE)
826 return err;
827
828 /* reconstruct the TOC from it */
829 UINT32 *mrp = reinterpret_cast<UINT32 *>(&oldmetadata[0]);
830 toc->numtrks = *mrp++;
831
832 for (i = 0; i < CD_MAX_TRACKS; i++)
833 {
834 toc->tracks[i].trktype = *mrp++;
835 toc->tracks[i].subtype = *mrp++;
836 toc->tracks[i].datasize = *mrp++;
837 toc->tracks[i].subsize = *mrp++;
838 toc->tracks[i].frames = *mrp++;
839 toc->tracks[i].extraframes = *mrp++;
840 toc->tracks[i].pregap = 0;
841 toc->tracks[i].postgap = 0;
842 toc->tracks[i].pgtype = 0;
843 toc->tracks[i].pgsub = 0;
844 toc->tracks[i].pgdatasize = 0;
845 toc->tracks[i].pgsubsize = 0;
846 }
847
848 /* TODO: I don't know why sometimes the data is one endian and sometimes another */
849 if (toc->numtrks > CD_MAX_TRACKS)
850 {
851 toc->numtrks = FLIPENDIAN_INT32(toc->numtrks);
852 for (i = 0; i < CD_MAX_TRACKS; i++)
853 {
854 toc->tracks[i].trktype = FLIPENDIAN_INT32(toc->tracks[i].trktype);
855 toc->tracks[i].subtype = FLIPENDIAN_INT32(toc->tracks[i].subtype);
856 toc->tracks[i].datasize = FLIPENDIAN_INT32(toc->tracks[i].datasize);
857 toc->tracks[i].subsize = FLIPENDIAN_INT32(toc->tracks[i].subsize);
858 toc->tracks[i].frames = FLIPENDIAN_INT32(toc->tracks[i].frames);
859 toc->tracks[i].padframes = FLIPENDIAN_INT32(toc->tracks[i].padframes);
860 toc->tracks[i].extraframes = FLIPENDIAN_INT32(toc->tracks[i].extraframes);
861 }
862 }
863
864 return CHDERR_NONE;
865 }
866
867
868 /*-------------------------------------------------
869 cdrom_write_metadata - write metadata
870 -------------------------------------------------*/
871 #if 0
872 chd_error cdrom_write_metadata(chd_file *chd, const cdrom_toc *toc)
873 {
874 chd_error err;
875 int i;
876
877 /* write the metadata */
878 for (i = 0; i < toc->numtrks; i++)
879 {
880 astring metadata;
881 if (!(toc->flags & CD_FLAG_GDROM))
882 {
883 metadata.format(CDROM_TRACK_METADATA2_FORMAT, i + 1, cdrom_get_type_string(toc->tracks[i].trktype),
884 cdrom_get_subtype_string(toc->tracks[i].subtype), toc->tracks[i].frames, toc->tracks[i].pregap,
885 cdrom_get_type_string(toc->tracks[i].pgtype), cdrom_get_subtype_string(toc->tracks[i].pgsub),
886 toc->tracks[i].postgap);
887
888 err = chd->write_metadata(CDROM_TRACK_METADATA2_TAG, i, metadata);
889 }
890 else
891 {
892 metadata.format(GDROM_TRACK_METADATA_FORMAT, i + 1, cdrom_get_type_string(toc->tracks[i].trktype),
893 cdrom_get_subtype_string(toc->tracks[i].subtype), toc->tracks[i].frames, toc->tracks[i].padframes,
894 toc->tracks[i].pregap, cdrom_get_type_string(toc->tracks[i].pgtype),
895 cdrom_get_subtype_string(toc->tracks[i].pgsub), toc->tracks[i].postgap);
896
897 err = chd->write_metadata(GDROM_TRACK_METADATA_TAG, i, metadata);
898 }
899 if (err != CHDERR_NONE)
900 return err;
901 }
902 return CHDERR_NONE;
903 }
904 #endif
905
906 //-------------------------------------------------
907 // ECC lookup tables
908 // pre-calculated tables for ECC data calcs
909 //-------------------------------------------------
910
911 static const UINT8 ecclow[256] =
912 {
913 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
914 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,
915 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
916 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,
917 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
918 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
919 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
920 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe,
921 0x1d, 0x1f, 0x19, 0x1b, 0x15, 0x17, 0x11, 0x13, 0x0d, 0x0f, 0x09, 0x0b, 0x05, 0x07, 0x01, 0x03,
922 0x3d, 0x3f, 0x39, 0x3b, 0x35, 0x37, 0x31, 0x33, 0x2d, 0x2f, 0x29, 0x2b, 0x25, 0x27, 0x21, 0x23,
923 0x5d, 0x5f, 0x59, 0x5b, 0x55, 0x57, 0x51, 0x53, 0x4d, 0x4f, 0x49, 0x4b, 0x45, 0x47, 0x41, 0x43,
924 0x7d, 0x7f, 0x79, 0x7b, 0x75, 0x77, 0x71, 0x73, 0x6d, 0x6f, 0x69, 0x6b, 0x65, 0x67, 0x61, 0x63,
925 0x9d, 0x9f, 0x99, 0x9b, 0x95, 0x97, 0x91, 0x93, 0x8d, 0x8f, 0x89, 0x8b, 0x85, 0x87, 0x81, 0x83,
926 0xbd, 0xbf, 0xb9, 0xbb, 0xb5, 0xb7, 0xb1, 0xb3, 0xad, 0xaf, 0xa9, 0xab, 0xa5, 0xa7, 0xa1, 0xa3,
927 0xdd, 0xdf, 0xd9, 0xdb, 0xd5, 0xd7, 0xd1, 0xd3, 0xcd, 0xcf, 0xc9, 0xcb, 0xc5, 0xc7, 0xc1, 0xc3,
928 0xfd, 0xff, 0xf9, 0xfb, 0xf5, 0xf7, 0xf1, 0xf3, 0xed, 0xef, 0xe9, 0xeb, 0xe5, 0xe7, 0xe1, 0xe3
929 };
930
931 static const UINT8 ecchigh[256] =
932 {
933 0x00, 0xf4, 0xf5, 0x01, 0xf7, 0x03, 0x02, 0xf6, 0xf3, 0x07, 0x06, 0xf2, 0x04, 0xf0, 0xf1, 0x05,
934 0xfb, 0x0f, 0x0e, 0xfa, 0x0c, 0xf8, 0xf9, 0x0d, 0x08, 0xfc, 0xfd, 0x09, 0xff, 0x0b, 0x0a, 0xfe,
935 0xeb, 0x1f, 0x1e, 0xea, 0x1c, 0xe8, 0xe9, 0x1d, 0x18, 0xec, 0xed, 0x19, 0xef, 0x1b, 0x1a, 0xee,
936 0x10, 0xe4, 0xe5, 0x11, 0xe7, 0x13, 0x12, 0xe6, 0xe3, 0x17, 0x16, 0xe2, 0x14, 0xe0, 0xe1, 0x15,
937 0xcb, 0x3f, 0x3e, 0xca, 0x3c, 0xc8, 0xc9, 0x3d, 0x38, 0xcc, 0xcd, 0x39, 0xcf, 0x3b, 0x3a, 0xce,
938 0x30, 0xc4, 0xc5, 0x31, 0xc7, 0x33, 0x32, 0xc6, 0xc3, 0x37, 0x36, 0xc2, 0x34, 0xc0, 0xc1, 0x35,
939 0x20, 0xd4, 0xd5, 0x21, 0xd7, 0x23, 0x22, 0xd6, 0xd3, 0x27, 0x26, 0xd2, 0x24, 0xd0, 0xd1, 0x25,
940 0xdb, 0x2f, 0x2e, 0xda, 0x2c, 0xd8, 0xd9, 0x2d, 0x28, 0xdc, 0xdd, 0x29, 0xdf, 0x2b, 0x2a, 0xde,
941 0x8b, 0x7f, 0x7e, 0x8a, 0x7c, 0x88, 0x89, 0x7d, 0x78, 0x8c, 0x8d, 0x79, 0x8f, 0x7b, 0x7a, 0x8e,
942 0x70, 0x84, 0x85, 0x71, 0x87, 0x73, 0x72, 0x86, 0x83, 0x77, 0x76, 0x82, 0x74, 0x80, 0x81, 0x75,
943 0x60, 0x94, 0x95, 0x61, 0x97, 0x63, 0x62, 0x96, 0x93, 0x67, 0x66, 0x92, 0x64, 0x90, 0x91, 0x65,
944 0x9b, 0x6f, 0x6e, 0x9a, 0x6c, 0x98, 0x99, 0x6d, 0x68, 0x9c, 0x9d, 0x69, 0x9f, 0x6b, 0x6a, 0x9e,
945 0x40, 0xb4, 0xb5, 0x41, 0xb7, 0x43, 0x42, 0xb6, 0xb3, 0x47, 0x46, 0xb2, 0x44, 0xb0, 0xb1, 0x45,
946 0xbb, 0x4f, 0x4e, 0xba, 0x4c, 0xb8, 0xb9, 0x4d, 0x48, 0xbc, 0xbd, 0x49, 0xbf, 0x4b, 0x4a, 0xbe,
947 0xab, 0x5f, 0x5e, 0xaa, 0x5c, 0xa8, 0xa9, 0x5d, 0x58, 0xac, 0xad, 0x59, 0xaf, 0x5b, 0x5a, 0xae,
948 0x50, 0xa4, 0xa5, 0x51, 0xa7, 0x53, 0x52, 0xa6, 0xa3, 0x57, 0x56, 0xa2, 0x54, 0xa0, 0xa1, 0x55
949 };
950
951
952 //-------------------------------------------------
953 // poffsets - each row represents the addresses
954 // used to calculate a byte of the ECC P data
955 // 86 (*2) ECC P bytes, 24 values represented by
956 // each
957 //-------------------------------------------------
958
959 static const UINT16 poffsets[ECC_P_NUM_BYTES][ECC_P_COMP] =
960 {
961 { 0x000,0x056,0x0ac,0x102,0x158,0x1ae,0x204,0x25a,0x2b0,0x306,0x35c,0x3b2,0x408,0x45e,0x4b4,0x50a,0x560,0x5b6,0x60c,0x662,0x6b8,0x70e,0x764,0x7ba },
962 { 0x001,0x057,0x0ad,0x103,0x159,0x1af,0x205,0x25b,0x2b1,0x307,0x35d,0x3b3,0x409,0x45f,0x4b5,0x50b,0x561,0x5b7,0x60d,0x663,0x6b9,0x70f,0x765,0x7bb },
963 { 0x002,0x058,0x0ae,0x104,0x15a,0x1b0,0x206,0x25c,0x2b2,0x308,0x35e,0x3b4,0x40a,0x460,0x4b6,0x50c,0x562,0x5b8,0x60e,0x664,0x6ba,0x710,0x766,0x7bc },
964 { 0x003,0x059,0x0af,0x105,0x15b,0x1b1,0x207,0x25d,0x2b3,0x309,0x35f,0x3b5,0x40b,0x461,0x4b7,0x50d,0x563,0x5b9,0x60f,0x665,0x6bb,0x711,0x767,0x7bd },
965 { 0x004,0x05a,0x0b0,0x106,0x15c,0x1b2,0x208,0x25e,0x2b4,0x30a,0x360,0x3b6,0x40c,0x462,0x4b8,0x50e,0x564,0x5ba,0x610,0x666,0x6bc,0x712,0x768,0x7be },
966 { 0x005,0x05b,0x0b1,0x107,0x15d,0x1b3,0x209,0x25f,0x2b5,0x30b,0x361,0x3b7,0x40d,0x463,0x4b9,0x50f,0x565,0x5bb,0x611,0x667,0x6bd,0x713,0x769,0x7bf },
967 { 0x006,0x05c,0x0b2,0x108,0x15e,0x1b4,0x20a,0x260,0x2b6,0x30c,0x362,0x3b8,0x40e,0x464,0x4ba,0x510,0x566,0x5bc,0x612,0x668,0x6be,0x714,0x76a,0x7c0 },
968 { 0x007,0x05d,0x0b3,0x109,0x15f,0x1b5,0x20b,0x261,0x2b7,0x30d,0x363,0x3b9,0x40f,0x465,0x4bb,0x511,0x567,0x5bd,0x613,0x669,0x6bf,0x715,0x76b,0x7c1 },
969 { 0x008,0x05e,0x0b4,0x10a,0x160,0x1b6,0x20c,0x262,0x2b8,0x30e,0x364,0x3ba,0x410,0x466,0x4bc,0x512,0x568,0x5be,0x614,0x66a,0x6c0,0x716,0x76c,0x7c2 },
970 { 0x009,0x05f,0x0b5,0x10b,0x161,0x1b7,0x20d,0x263,0x2b9,0x30f,0x365,0x3bb,0x411,0x467,0x4bd,0x513,0x569,0x5bf,0x615,0x66b,0x6c1,0x717,0x76d,0x7c3 },
971 { 0x00a,0x060,0x0b6,0x10c,0x162,0x1b8,0x20e,0x264,0x2ba,0x310,0x366,0x3bc,0x412,0x468,0x4be,0x514,0x56a,0x5c0,0x616,0x66c,0x6c2,0x718,0x76e,0x7c4 },
972 { 0x00b,0x061,0x0b7,0x10d,0x163,0x1b9,0x20f,0x265,0x2bb,0x311,0x367,0x3bd,0x413,0x469,0x4bf,0x515,0x56b,0x5c1,0x617,0x66d,0x6c3,0x719,0x76f,0x7c5 },
973 { 0x00c,0x062,0x0b8,0x10e,0x164,0x1ba,0x210,0x266,0x2bc,0x312,0x368,0x3be,0x414,0x46a,0x4c0,0x516,0x56c,0x5c2,0x618,0x66e,0x6c4,0x71a,0x770,0x7c6 },
974 { 0x00d,0x063,0x0b9,0x10f,0x165,0x1bb,0x211,0x267,0x2bd,0x313,0x369,0x3bf,0x415,0x46b,0x4c1,0x517,0x56d,0x5c3,0x619,0x66f,0x6c5,0x71b,0x771,0x7c7 },
975 { 0x00e,0x064,0x0ba,0x110,0x166,0x1bc,0x212,0x268,0x2be,0x314,0x36a,0x3c0,0x416,0x46c,0x4c2,0x518,0x56e,0x5c4,0x61a,0x670,0x6c6,0x71c,0x772,0x7c8 },
976 { 0x00f,0x065,0x0bb,0x111,0x167,0x1bd,0x213,0x269,0x2bf,0x315,0x36b,0x3c1,0x417,0x46d,0x4c3,0x519,0x56f,0x5c5,0x61b,0x671,0x6c7,0x71d,0x773,0x7c9 },
977 { 0x010,0x066,0x0bc,0x112,0x168,0x1be,0x214,0x26a,0x2c0,0x316,0x36c,0x3c2,0x418,0x46e,0x4c4,0x51a,0x570,0x5c6,0x61c,0x672,0x6c8,0x71e,0x774,0x7ca },
978 { 0x011,0x067,0x0bd,0x113,0x169,0x1bf,0x215,0x26b,0x2c1,0x317,0x36d,0x3c3,0x419,0x46f,0x4c5,0x51b,0x571,0x5c7,0x61d,0x673,0x6c9,0x71f,0x775,0x7cb },
979 { 0x012,0x068,0x0be,0x114,0x16a,0x1c0,0x216,0x26c,0x2c2,0x318,0x36e,0x3c4,0x41a,0x470,0x4c6,0x51c,0x572,0x5c8,0x61e,0x674,0x6ca,0x720,0x776,0x7cc },
980 { 0x013,0x069,0x0bf,0x115,0x16b,0x1c1,0x217,0x26d,0x2c3,0x319,0x36f,0x3c5,0x41b,0x471,0x4c7,0x51d,0x573,0x5c9,0x61f,0x675,0x6cb,0x721,0x777,0x7cd },
981 { 0x014,0x06a,0x0c0,0x116,0x16c,0x1c2,0x218,0x26e,0x2c4,0x31a,0x370,0x3c6,0x41c,0x472,0x4c8,0x51e,0x574,0x5ca,0x620,0x676,0x6cc,0x722,0x778,0x7ce },
982 { 0x015,0x06b,0x0c1,0x117,0x16d,0x1c3,0x219,0x26f,0x2c5,0x31b,0x371,0x3c7,0x41d,0x473,0x4c9,0x51f,0x575,0x5cb,0x621,0x677,0x6cd,0x723,0x779,0x7cf },
983 { 0x016,0x06c,0x0c2,0x118,0x16e,0x1c4,0x21a,0x270,0x2c6,0x31c,0x372,0x3c8,0x41e,0x474,0x4ca,0x520,0x576,0x5cc,0x622,0x678,0x6ce,0x724,0x77a,0x7d0 },
984 { 0x017,0x06d,0x0c3,0x119,0x16f,0x1c5,0x21b,0x271,0x2c7,0x31d,0x373,0x3c9,0x41f,0x475,0x4cb,0x521,0x577,0x5cd,0x623,0x679,0x6cf,0x725,0x77b,0x7d1 },
985 { 0x018,0x06e,0x0c4,0x11a,0x170,0x1c6,0x21c,0x272,0x2c8,0x31e,0x374,0x3ca,0x420,0x476,0x4cc,0x522,0x578,0x5ce,0x624,0x67a,0x6d0,0x726,0x77c,0x7d2 },
986 { 0x019,0x06f,0x0c5,0x11b,0x171,0x1c7,0x21d,0x273,0x2c9,0x31f,0x375,0x3cb,0x421,0x477,0x4cd,0x523,0x579,0x5cf,0x625,0x67b,0x6d1,0x727,0x77d,0x7d3 },
987 { 0x01a,0x070,0x0c6,0x11c,0x172,0x1c8,0x21e,0x274,0x2ca,0x320,0x376,0x3cc,0x422,0x478,0x4ce,0x524,0x57a,0x5d0,0x626,0x67c,0x6d2,0x728,0x77e,0x7d4 },
988 { 0x01b,0x071,0x0c7,0x11d,0x173,0x1c9,0x21f,0x275,0x2cb,0x321,0x377,0x3cd,0x423,0x479,0x4cf,0x525,0x57b,0x5d1,0x627,0x67d,0x6d3,0x729,0x77f,0x7d5 },
989 { 0x01c,0x072,0x0c8,0x11e,0x174,0x1ca,0x220,0x276,0x2cc,0x322,0x378,0x3ce,0x424,0x47a,0x4d0,0x526,0x57c,0x5d2,0x628,0x67e,0x6d4,0x72a,0x780,0x7d6 },
990 { 0x01d,0x073,0x0c9,0x11f,0x175,0x1cb,0x221,0x277,0x2cd,0x323,0x379,0x3cf,0x425,0x47b,0x4d1,0x527,0x57d,0x5d3,0x629,0x67f,0x6d5,0x72b,0x781,0x7d7 },
991 { 0x01e,0x074,0x0ca,0x120,0x176,0x1cc,0x222,0x278,0x2ce,0x324,0x37a,0x3d0,0x426,0x47c,0x4d2,0x528,0x57e,0x5d4,0x62a,0x680,0x6d6,0x72c,0x782,0x7d8 },
992 { 0x01f,0x075,0x0cb,0x121,0x177,0x1cd,0x223,0x279,0x2cf,0x325,0x37b,0x3d1,0x427,0x47d,0x4d3,0x529,0x57f,0x5d5,0x62b,0x681,0x6d7,0x72d,0x783,0x7d9 },
993 { 0x020,0x076,0x0cc,0x122,0x178,0x1ce,0x224,0x27a,0x2d0,0x326,0x37c,0x3d2,0x428,0x47e,0x4d4,0x52a,0x580,0x5d6,0x62c,0x682,0x6d8,0x72e,0x784,0x7da },
994 { 0x021,0x077,0x0cd,0x123,0x179,0x1cf,0x225,0x27b,0x2d1,0x327,0x37d,0x3d3,0x429,0x47f,0x4d5,0x52b,0x581,0x5d7,0x62d,0x683,0x6d9,0x72f,0x785,0x7db },
995 { 0x022,0x078,0x0ce,0x124,0x17a,0x1d0,0x226,0x27c,0x2d2,0x328,0x37e,0x3d4,0x42a,0x480,0x4d6,0x52c,0x582,0x5d8,0x62e,0x684,0x6da,0x730,0x786,0x7dc },
996 { 0x023,0x079,0x0cf,0x125,0x17b,0x1d1,0x227,0x27d,0x2d3,0x329,0x37f,0x3d5,0x42b,0x481,0x4d7,0x52d,0x583,0x5d9,0x62f,0x685,0x6db,0x731,0x787,0x7dd },
997 { 0x024,0x07a,0x0d0,0x126,0x17c,0x1d2,0x228,0x27e,0x2d4,0x32a,0x380,0x3d6,0x42c,0x482,0x4d8,0x52e,0x584,0x5da,0x630,0x686,0x6dc,0x732,0x788,0x7de },
998 { 0x025,0x07b,0x0d1,0x127,0x17d,0x1d3,0x229,0x27f,0x2d5,0x32b,0x381,0x3d7,0x42d,0x483,0x4d9,0x52f,0x585,0x5db,0x631,0x687,0x6dd,0x733,0x789,0x7df },
999 { 0x026,0x07c,0x0d2,0x128,0x17e,0x1d4,0x22a,0x280,0x2d6,0x32c,0x382,0x3d8,0x42e,0x484,0x4da,0x530,0x586,0x5dc,0x632,0x688,0x6de,0x734,0x78a,0x7e0 },
1000 { 0x027,0x07d,0x0d3,0x129,0x17f,0x1d5,0x22b,0x281,0x2d7,0x32d,0x383,0x3d9,0x42f,0x485,0x4db,0x531,0x587,0x5dd,0x633,0x689,0x6df,0x735,0x78b,0x7e1 },
1001 { 0x028,0x07e,0x0d4,0x12a,0x180,0x1d6,0x22c,0x282,0x2d8,0x32e,0x384,0x3da,0x430,0x486,0x4dc,0x532,0x588,0x5de,0x634,0x68a,0x6e0,0x736,0x78c,0x7e2 },
1002 { 0x029,0x07f,0x0d5,0x12b,0x181,0x1d7,0x22d,0x283,0x2d9,0x32f,0x385,0x3db,0x431,0x487,0x4dd,0x533,0x589,0x5df,0x635,0x68b,0x6e1,0x737,0x78d,0x7e3 },
1003 { 0x02a,0x080,0x0d6,0x12c,0x182,0x1d8,0x22e,0x284,0x2da,0x330,0x386,0x3dc,0x432,0x488,0x4de,0x534,0x58a,0x5e0,0x636,0x68c,0x6e2,0x738,0x78e,0x7e4 },
1004 { 0x02b,0x081,0x0d7,0x12d,0x183,0x1d9,0x22f,0x285,0x2db,0x331,0x387,0x3dd,0x433,0x489,0x4df,0x535,0x58b,0x5e1,0x637,0x68d,0x6e3,0x739,0x78f,0x7e5 },
1005 { 0x02c,0x082,0x0d8,0x12e,0x184,0x1da,0x230,0x286,0x2dc,0x332,0x388,0x3de,0x434,0x48a,0x4e0,0x536,0x58c,0x5e2,0x638,0x68e,0x6e4,0x73a,0x790,0x7e6 },
1006 { 0x02d,0x083,0x0d9,0x12f,0x185,0x1db,0x231,0x287,0x2dd,0x333,0x389,0x3df,0x435,0x48b,0x4e1,0x537,0x58d,0x5e3,0x639,0x68f,0x6e5,0x73b,0x791,0x7e7 },
1007 { 0x02e,0x084,0x0da,0x130,0x186,0x1dc,0x232,0x288,0x2de,0x334,0x38a,0x3e0,0x436,0x48c,0x4e2,0x538,0x58e,0x5e4,0x63a,0x690,0x6e6,0x73c,0x792,0x7e8 },
1008 { 0x02f,0x085,0x0db,0x131,0x187,0x1dd,0x233,0x289,0x2df,0x335,0x38b,0x3e1,0x437,0x48d,0x4e3,0x539,0x58f,0x5e5,0x63b,0x691,0x6e7,0x73d,0x793,0x7e9 },
1009 { 0x030,0x086,0x0dc,0x132,0x188,0x1de,0x234,0x28a,0x2e0,0x336,0x38c,0x3e2,0x438,0x48e,0x4e4,0x53a,0x590,0x5e6,0x63c,0x692,0x6e8,0x73e,0x794,0x7ea },
1010 { 0x031,0x087,0x0dd,0x133,0x189,0x1df,0x235,0x28b,0x2e1,0x337,0x38d,0x3e3,0x439,0x48f,0x4e5,0x53b,0x591,0x5e7,0x63d,0x693,0x6e9,0x73f,0x795,0x7eb },
1011 { 0x032,0x088,0x0de,0x134,0x18a,0x1e0,0x236,0x28c,0x2e2,0x338,0x38e,0x3e4,0x43a,0x490,0x4e6,0x53c,0x592,0x5e8,0x63e,0x694,0x6ea,0x740,0x796,0x7ec },
1012 { 0x033,0x089,0x0df,0x135,0x18b,0x1e1,0x237,0x28d,0x2e3,0x339,0x38f,0x3e5,0x43b,0x491,0x4e7,0x53d,0x593,0x5e9,0x63f,0x695,0x6eb,0x741,0x797,0x7ed },
1013 { 0x034,0x08a,0x0e0,0x136,0x18c,0x1e2,0x238,0x28e,0x2e4,0x33a,0x390,0x3e6,0x43c,0x492,0x4e8,0x53e,0x594,0x5ea,0x640,0x696,0x6ec,0x742,0x798,0x7ee },
1014 { 0x035,0x08b,0x0e1,0x137,0x18d,0x1e3,0x239,0x28f,0x2e5,0x33b,0x391,0x3e7,0x43d,0x493,0x4e9,0x53f,0x595,0x5eb,0x641,0x697,0x6ed,0x743,0x799,0x7ef },
1015 { 0x036,0x08c,0x0e2,0x138,0x18e,0x1e4,0x23a,0x290,0x2e6,0x33c,0x392,0x3e8,0x43e,0x494,0x4ea,0x540,0x596,0x5ec,0x642,0x698,0x6ee,0x744,0x79a,0x7f0 },
1016 { 0x037,0x08d,0x0e3,0x139,0x18f,0x1e5,0x23b,0x291,0x2e7,0x33d,0x393,0x3e9,0x43f,0x495,0x4eb,0x541,0x597,0x5ed,0x643,0x699,0x6ef,0x745,0x79b,0x7f1 },
1017 { 0x038,0x08e,0x0e4,0x13a,0x190,0x1e6,0x23c,0x292,0x2e8,0x33e,0x394,0x3ea,0x440,0x496,0x4ec,0x542,0x598,0x5ee,0x644,0x69a,0x6f0,0x746,0x79c,0x7f2 },
1018 { 0x039,0x08f,0x0e5,0x13b,0x191,0x1e7,0x23d,0x293,0x2e9,0x33f,0x395,0x3eb,0x441,0x497,0x4ed,0x543,0x599,0x5ef,0x645,0x69b,0x6f1,0x747,0x79d,0x7f3 },
1019 { 0x03a,0x090,0x0e6,0x13c,0x192,0x1e8,0x23e,0x294,0x2ea,0x340,0x396,0x3ec,0x442,0x498,0x4ee,0x544,0x59a,0x5f0,0x646,0x69c,0x6f2,0x748,0x79e,0x7f4 },
1020 { 0x03b,0x091,0x0e7,0x13d,0x193,0x1e9,0x23f,0x295,0x2eb,0x341,0x397,0x3ed,0x443,0x499,0x4ef,0x545,0x59b,0x5f1,0x647,0x69d,0x6f3,0x749,0x79f,0x7f5 },
1021 { 0x03c,0x092,0x0e8,0x13e,0x194,0x1ea,0x240,0x296,0x2ec,0x342,0x398,0x3ee,0x444,0x49a,0x4f0,0x546,0x59c,0x5f2,0x648,0x69e,0x6f4,0x74a,0x7a0,0x7f6 },
1022 { 0x03d,0x093,0x0e9,0x13f,0x195,0x1eb,0x241,0x297,0x2ed,0x343,0x399,0x3ef,0x445,0x49b,0x4f1,0x547,0x59d,0x5f3,0x649,0x69f,0x6f5,0x74b,0x7a1,0x7f7 },
1023 { 0x03e,0x094,0x0ea,0x140,0x196,0x1ec,0x242,0x298,0x2ee,0x344,0x39a,0x3f0,0x446,0x49c,0x4f2,0x548,0x59e,0x5f4,0x64a,0x6a0,0x6f6,0x74c,0x7a2,0x7f8 },
1024 { 0x03f,0x095,0x0eb,0x141,0x197,0x1ed,0x243,0x299,0x2ef,0x345,0x39b,0x3f1,0x447,0x49d,0x4f3,0x549,0x59f,0x5f5,0x64b,0x6a1,0x6f7,0x74d,0x7a3,0x7f9 },
1025 { 0x040,0x096,0x0ec,0x142,0x198,0x1ee,0x244,0x29a,0x2f0,0x346,0x39c,0x3f2,0x448,0x49e,0x4f4,0x54a,0x5a0,0x5f6,0x64c,0x6a2,0x6f8,0x74e,0x7a4,0x7fa },
1026 { 0x041,0x097,0x0ed,0x143,0x199,0x1ef,0x245,0x29b,0x2f1,0x347,0x39d,0x3f3,0x449,0x49f,0x4f5,0x54b,0x5a1,0x5f7,0x64d,0x6a3,0x6f9,0x74f,0x7a5,0x7fb },
1027 { 0x042,0x098,0x0ee,0x144,0x19a,0x1f0,0x246,0x29c,0x2f2,0x348,0x39e,0x3f4,0x44a,0x4a0,0x4f6,0x54c,0x5a2,0x5f8,0x64e,0x6a4,0x6fa,0x750,0x7a6,0x7fc },
1028 { 0x043,0x099,0x0ef,0x145,0x19b,0x1f1,0x247,0x29d,0x2f3,0x349,0x39f,0x3f5,0x44b,0x4a1,0x4f7,0x54d,0x5a3,0x5f9,0x64f,0x6a5,0x6fb,0x751,0x7a7,0x7fd },
1029 { 0x044,0x09a,0x0f0,0x146,0x19c,0x1f2,0x248,0x29e,0x2f4,0x34a,0x3a0,0x3f6,0x44c,0x4a2,0x4f8,0x54e,0x5a4,0x5fa,0x650,0x6a6,0x6fc,0x752,0x7a8,0x7fe },
1030 { 0x045,0x09b,0x0f1,0x147,0x19d,0x1f3,0x249,0x29f,0x2f5,0x34b,0x3a1,0x3f7,0x44d,0x4a3,0x4f9,0x54f,0x5a5,0x5fb,0x651,0x6a7,0x6fd,0x753,0x7a9,0x7ff },
1031 { 0x046,0x09c,0x0f2,0x148,0x19e,0x1f4,0x24a,0x2a0,0x2f6,0x34c,0x3a2,0x3f8,0x44e,0x4a4,0x4fa,0x550,0x5a6,0x5fc,0x652,0x6a8,0x6fe,0x754,0x7aa,0x800 },
1032 { 0x047,0x09d,0x0f3,0x149,0x19f,0x1f5,0x24b,0x2a1,0x2f7,0x34d,0x3a3,0x3f9,0x44f,0x4a5,0x4fb,0x551,0x5a7,0x5fd,0x653,0x6a9,0x6ff,0x755,0x7ab,0x801 },
1033 { 0x048,0x09e,0x0f4,0x14a,0x1a0,0x1f6,0x24c,0x2a2,0x2f8,0x34e,0x3a4,0x3fa,0x450,0x4a6,0x4fc,0x552,0x5a8,0x5fe,0x654,0x6aa,0x700,0x756,0x7ac,0x802 },
1034 { 0x049,0x09f,0x0f5,0x14b,0x1a1,0x1f7,0x24d,0x2a3,0x2f9,0x34f,0x3a5,0x3fb,0x451,0x4a7,0x4fd,0x553,0x5a9,0x5ff,0x655,0x6ab,0x701,0x757,0x7ad,0x803 },
1035 { 0x04a,0x0a0,0x0f6,0x14c,0x1a2,0x1f8,0x24e,0x2a4,0x2fa,0x350,0x3a6,0x3fc,0x452,0x4a8,0x4fe,0x554,0x5aa,0x600,0x656,0x6ac,0x702,0x758,0x7ae,0x804 },
1036 { 0x04b,0x0a1,0x0f7,0x14d,0x1a3,0x1f9,0x24f,0x2a5,0x2fb,0x351,0x3a7,0x3fd,0x453,0x4a9,0x4ff,0x555,0x5ab,0x601,0x657,0x6ad,0x703,0x759,0x7af,0x805 },
1037 { 0x04c,0x0a2,0x0f8,0x14e,0x1a4,0x1fa,0x250,0x2a6,0x2fc,0x352,0x3a8,0x3fe,0x454,0x4aa,0x500,0x556,0x5ac,0x602,0x658,0x6ae,0x704,0x75a,0x7b0,0x806 },
1038 { 0x04d,0x0a3,0x0f9,0x14f,0x1a5,0x1fb,0x251,0x2a7,0x2fd,0x353,0x3a9,0x3ff,0x455,0x4ab,0x501,0x557,0x5ad,0x603,0x659,0x6af,0x705,0x75b,0x7b1,0x807 },
1039 { 0x04e,0x0a4,0x0fa,0x150,0x1a6,0x1fc,0x252,0x2a8,0x2fe,0x354,0x3aa,0x400,0x456,0x4ac,0x502,0x558,0x5ae,0x604,0x65a,0x6b0,0x706,0x75c,0x7b2,0x808 },
1040 { 0x04f,0x0a5,0x0fb,0x151,0x1a7,0x1fd,0x253,0x2a9,0x2ff,0x355,0x3ab,0x401,0x457,0x4ad,0x503,0x559,0x5af,0x605,0x65b,0x6b1,0x707,0x75d,0x7b3,0x809 },
1041 { 0x050,0x0a6,0x0fc,0x152,0x1a8,0x1fe,0x254,0x2aa,0x300,0x356,0x3ac,0x402,0x458,0x4ae,0x504,0x55a,0x5b0,0x606,0x65c,0x6b2,0x708,0x75e,0x7b4,0x80a },
1042 { 0x051,0x0a7,0x0fd,0x153,0x1a9,0x1ff,0x255,0x2ab,0x301,0x357,0x3ad,0x403,0x459,0x4af,0x505,0x55b,0x5b1,0x607,0x65d,0x6b3,0x709,0x75f,0x7b5,0x80b },
1043 { 0x052,0x0a8,0x0fe,0x154,0x1aa,0x200,0x256,0x2ac,0x302,0x358,0x3ae,0x404,0x45a,0x4b0,0x506,0x55c,0x5b2,0x608,0x65e,0x6b4,0x70a,0x760,0x7b6,0x80c },
1044 { 0x053,0x0a9,0x0ff,0x155,0x1ab,0x201,0x257,0x2ad,0x303,0x359,0x3af,0x405,0x45b,0x4b1,0x507,0x55d,0x5b3,0x609,0x65f,0x6b5,0x70b,0x761,0x7b7,0x80d },
1045 { 0x054,0x0aa,0x100,0x156,0x1ac,0x202,0x258,0x2ae,0x304,0x35a,0x3b0,0x406,0x45c,0x4b2,0x508,0x55e,0x5b4,0x60a,0x660,0x6b6,0x70c,0x762,0x7b8,0x80e },
1046 { 0x055,0x0ab,0x101,0x157,0x1ad,0x203,0x259,0x2af,0x305,0x35b,0x3b1,0x407,0x45d,0x4b3,0x509,0x55f,0x5b5,0x60b,0x661,0x6b7,0x70d,0x763,0x7b9,0x80f }
1047 };
1048
1049
1050 //-------------------------------------------------
1051 // qoffsets - each row represents the addresses
1052 // used to calculate a byte of the ECC Q data
1053 // 52 (*2) ECC Q bytes, 43 values represented by
1054 // each
1055 //-------------------------------------------------
1056
1057 static const UINT16 qoffsets[ECC_Q_NUM_BYTES][ECC_Q_COMP] =
1058 {
1059 { 0x000,0x058,0x0b0,0x108,0x160,0x1b8,0x210,0x268,0x2c0,0x318,0x370,0x3c8,0x420,0x478,0x4d0,0x528,0x580,0x5d8,0x630,0x688,0x6e0,0x738,0x790,0x7e8,0x840,0x898,0x034,0x08c,0x0e4,0x13c,0x194,0x1ec,0x244,0x29c,0x2f4,0x34c,0x3a4,0x3fc,0x454,0x4ac,0x504,0x55c,0x5b4 },
1060 { 0x001,0x059,0x0b1,0x109,0x161,0x1b9,0x211,0x269,0x2c1,0x319,0x371,0x3c9,0x421,0x479,0x4d1,0x529,0x581,0x5d9,0x631,0x689,0x6e1,0x739,0x791,0x7e9,0x841,0x899,0x035,0x08d,0x0e5,0x13d,0x195,0x1ed,0x245,0x29d,0x2f5,0x34d,0x3a5,0x3fd,0x455,0x4ad,0x505,0x55d,0x5b5 },
1061 { 0x056,0x0ae,0x106,0x15e,0x1b6,0x20e,0x266,0x2be,0x316,0x36e,0x3c6,0x41e,0x476,0x4ce,0x526,0x57e,0x5d6,0x62e,0x686,0x6de,0x736,0x78e,0x7e6,0x83e,0x896,0x032,0x08a,0x0e2,0x13a,0x192,0x1ea,0x242,0x29a,0x2f2,0x34a,0x3a2,0x3fa,0x452,0x4aa,0x502,0x55a,0x5b2,0x60a },
1062 { 0x057,0x0af,0x107,0x15f,0x1b7,0x20f,0x267,0x2bf,0x317,0x36f,0x3c7,0x41f,0x477,0x4cf,0x527,0x57f,0x5d7,0x62f,0x687,0x6df,0x737,0x78f,0x7e7,0x83f,0x897,0x033,0x08b,0x0e3,0x13b,0x193,0x1eb,0x243,0x29b,0x2f3,0x34b,0x3a3,0x3fb,0x453,0x4ab,0x503,0x55b,0x5b3,0x60b },
1063 { 0x0ac,0x104,0x15c,0x1b4,0x20c,0x264,0x2bc,0x314,0x36c,0x3c4,0x41c,0x474,0x4cc,0x524,0x57c,0x5d4,0x62c,0x684,0x6dc,0x734,0x78c,0x7e4,0x83c,0x894,0x030,0x088,0x0e0,0x138,0x190,0x1e8,0x240,0x298,0x2f0,0x348,0x3a0,0x3f8,0x450,0x4a8,0x500,0x558,0x5b0,0x608,0x660 },
1064 { 0x0ad,0x105,0x15d,0x1b5,0x20d,0x265,0x2bd,0x315,0x36d,0x3c5,0x41d,0x475,0x4cd,0x525,0x57d,0x5d5,0x62d,0x685,0x6dd,0x735,0x78d,0x7e5,0x83d,0x895,0x031,0x089,0x0e1,0x139,0x191,0x1e9,0x241,0x299,0x2f1,0x349,0x3a1,0x3f9,0x451,0x4a9,0x501,0x559,0x5b1,0x609,0x661 },
1065 { 0x102,0x15a,0x1b2,0x20a,0x262,0x2ba,0x312,0x36a,0x3c2,0x41a,0x472,0x4ca,0x522,0x57a,0x5d2,0x62a,0x682,0x6da,0x732,0x78a,0x7e2,0x83a,0x892,0x02e,0x086,0x0de,0x136,0x18e,0x1e6,0x23e,0x296,0x2ee,0x346,0x39e,0x3f6,0x44e,0x4a6,0x4fe,0x556,0x5ae,0x606,0x65e,0x6b6 },
1066 { 0x103,0x15b,0x1b3,0x20b,0x263,0x2bb,0x313,0x36b,0x3c3,0x41b,0x473,0x4cb,0x523,0x57b,0x5d3,0x62b,0x683,0x6db,0x733,0x78b,0x7e3,0x83b,0x893,0x02f,0x087,0x0df,0x137,0x18f,0x1e7,0x23f,0x297,0x2ef,0x347,0x39f,0x3f7,0x44f,0x4a7,0x4ff,0x557,0x5af,0x607,0x65f,0x6b7 },
1067 { 0x158,0x1b0,0x208,0x260,0x2b8,0x310,0x368,0x3c0,0x418,0x470,0x4c8,0x520,0x578,0x5d0,0x628,0x680,0x6d8,0x730,0x788,0x7e0,0x838,0x890,0x02c,0x084,0x0dc,0x134,0x18c,0x1e4,0x23c,0x294,0x2ec,0x344,0x39c,0x3f4,0x44c,0x4a4,0x4fc,0x554,0x5ac,0x604,0x65c,0x6b4,0x70c },
1068 { 0x159,0x1b1,0x209,0x261,0x2b9,0x311,0x369,0x3c1,0x419,0x471,0x4c9,0x521,0x579,0x5d1,0x629,0x681,0x6d9,0x731,0x789,0x7e1,0x839,0x891,0x02d,0x085,0x0dd,0x135,0x18d,0x1e5,0x23d,0x295,0x2ed,0x345,0x39d,0x3f5,0x44d,0x4a5,0x4fd,0x555,0x5ad,0x605,0x65d,0x6b5,0x70d },
1069 { 0x1ae,0x206,0x25e,0x2b6,0x30e,0x366,0x3be,0x416,0x46e,0x4c6,0x51e,0x576,0x5ce,0x626,0x67e,0x6d6,0x72e,0x786,0x7de,0x836,0x88e,0x02a,0x082,0x0da,0x132,0x18a,0x1e2,0x23a,0x292,0x2ea,0x342,0x39a,0x3f2,0x44a,0x4a2,0x4fa,0x552,0x5aa,0x602,0x65a,0x6b2,0x70a,0x762 },
1070 { 0x1af,0x207,0x25f,0x2b7,0x30f,0x367,0x3bf,0x417,0x46f,0x4c7,0x51f,0x577,0x5cf,0x627,0x67f,0x6d7,0x72f,0x787,0x7df,0x837,0x88f,0x02b,0x083,0x0db,0x133,0x18b,0x1e3,0x23b,0x293,0x2eb,0x343,0x39b,0x3f3,0x44b,0x4a3,0x4fb,0x553,0x5ab,0x603,0x65b,0x6b3,0x70b,0x763 },
1071 { 0x204,0x25c,0x2b4,0x30c,0x364,0x3bc,0x414,0x46c,0x4c4,0x51c,0x574,0x5cc,0x624,0x67c,0x6d4,0x72c,0x784,0x7dc,0x834,0x88c,0x028,0x080,0x0d8,0x130,0x188,0x1e0,0x238,0x290,0x2e8,0x340,0x398,0x3f0,0x448,0x4a0,0x4f8,0x550,0x5a8,0x600,0x658,0x6b0,0x708,0x760,0x7b8 },
1072 { 0x205,0x25d,0x2b5,0x30d,0x365,0x3bd,0x415,0x46d,0x4c5,0x51d,0x575,0x5cd,0x625,0x67d,0x6d5,0x72d,0x785,0x7dd,0x835,0x88d,0x029,0x081,0x0d9,0x131,0x189,0x1e1,0x239,0x291,0x2e9,0x341,0x399,0x3f1,0x449,0x4a1,0x4f9,0x551,0x5a9,0x601,0x659,0x6b1,0x709,0x761,0x7b9 },
1073 { 0x25a,0x2b2,0x30a,0x362,0x3ba,0x412,0x46a,0x4c2,0x51a,0x572,0x5ca,0x622,0x67a,0x6d2,0x72a,0x782,0x7da,0x832,0x88a,0x026,0x07e,0x0d6,0x12e,0x186,0x1de,0x236,0x28e,0x2e6,0x33e,0x396,0x3ee,0x446,0x49e,0x4f6,0x54e,0x5a6,0x5fe,0x656,0x6ae,0x706,0x75e,0x7b6,0x80e },
1074 { 0x25b,0x2b3,0x30b,0x363,0x3bb,0x413,0x46b,0x4c3,0x51b,0x573,0x5cb,0x623,0x67b,0x6d3,0x72b,0x783,0x7db,0x833,0x88b,0x027,0x07f,0x0d7,0x12f,0x187,0x1df,0x237,0x28f,0x2e7,0x33f,0x397,0x3ef,0x447,0x49f,0x4f7,0x54f,0x5a7,0x5ff,0x657,0x6af,0x707,0x75f,0x7b7,0x80f },
1075 { 0x2b0,0x308,0x360,0x3b8,0x410,0x468,0x4c0,0x518,0x570,0x5c8,0x620,0x678,0x6d0,0x728,0x780,0x7d8,0x830,0x888,0x024,0x07c,0x0d4,0x12c,0x184,0x1dc,0x234,0x28c,0x2e4,0x33c,0x394,0x3ec,0x444,0x49c,0x4f4,0x54c,0x5a4,0x5fc,0x654,0x6ac,0x704,0x75c,0x7b4,0x80c,0x864 },
1076 { 0x2b1,0x309,0x361,0x3b9,0x411,0x469,0x4c1,0x519,0x571,0x5c9,0x621,0x679,0x6d1,0x729,0x781,0x7d9,0x831,0x889,0x025,0x07d,0x0d5,0x12d,0x185,0x1dd,0x235,0x28d,0x2e5,0x33d,0x395,0x3ed,0x445,0x49d,0x4f5,0x54d,0x5a5,0x5fd,0x655,0x6ad,0x705,0x75d,0x7b5,0x80d,0x865 },
1077 { 0x306,0x35e,0x3b6,0x40e,0x466,0x4be,0x516,0x56e,0x5c6,0x61e,0x676,0x6ce,0x726,0x77e,0x7d6,0x82e,0x886,0x022,0x07a,0x0d2,0x12a,0x182,0x1da,0x232,0x28a,0x2e2,0x33a,0x392,0x3ea,0x442,0x49a,0x4f2,0x54a,0x5a2,0x5fa,0x652,0x6aa,0x702,0x75a,0x7b2,0x80a,0x862,0x8ba },
1078 { 0x307,0x35f,0x3b7,0x40f,0x467,0x4bf,0x517,0x56f,0x5c7,0x61f,0x677,0x6cf,0x727,0x77f,0x7d7,0x82f,0x887,0x023,0x07b,0x0d3,0x12b,0x183,0x1db,0x233,0x28b,0x2e3,0x33b,0x393,0x3eb,0x443,0x49b,0x4f3,0x54b,0x5a3,0x5fb,0x653,0x6ab,0x703,0x75b,0x7b3,0x80b,0x863,0x8bb },
1079 { 0x35c,0x3b4,0x40c,0x464,0x4bc,0x514,0x56c,0x5c4,0x61c,0x674,0x6cc,0x724,0x77c,0x7d4,0x82c,0x884,0x020,0x078,0x0d0,0x128,0x180,0x1d8,0x230,0x288,0x2e0,0x338,0x390,0x3e8,0x440,0x498,0x4f0,0x548,0x5a0,0x5f8,0x650,0x6a8,0x700,0x758,0x7b0,0x808,0x860,0x8b8,0x054 },
1080 { 0x35d,0x3b5,0x40d,0x465,0x4bd,0x515,0x56d,0x5c5,0x61d,0x675,0x6cd,0x725,0x77d,0x7d5,0x82d,0x885,0x021,0x079,0x0d1,0x129,0x181,0x1d9,0x231,0x289,0x2e1,0x339,0x391,0x3e9,0x441,0x499,0x4f1,0x549,0x5a1,0x5f9,0x651,0x6a9,0x701,0x759,0x7b1,0x809,0x861,0x8b9,0x055 },
1081 { 0x3b2,0x40a,0x462,0x4ba,0x512,0x56a,0x5c2,0x61a,0x672,0x6ca,0x722,0x77a,0x7d2,0x82a,0x882,0x01e,0x076,0x0ce,0x126,0x17e,0x1d6,0x22e,0x286,0x2de,0x336,0x38e,0x3e6,0x43e,0x496,0x4ee,0x546,0x59e,0x5f6,0x64e,0x6a6,0x6fe,0x756,0x7ae,0x806,0x85e,0x8b6,0x052,0x0aa },
1082 { 0x3b3,0x40b,0x463,0x4bb,0x513,0x56b,0x5c3,0x61b,0x673,0x6cb,0x723,0x77b,0x7d3,0x82b,0x883,0x01f,0x077,0x0cf,0x127,0x17f,0x1d7,0x22f,0x287,0x2df,0x337,0x38f,0x3e7,0x43f,0x497,0x4ef,0x547,0x59f,0x5f7,0x64f,0x6a7,0x6ff,0x757,0x7af,0x807,0x85f,0x8b7,0x053,0x0ab },
1083 { 0x408,0x460,0x4b8,0x510,0x568,0x5c0,0x618,0x670,0x6c8,0x720,0x778,0x7d0,0x828,0x880,0x01c,0x074,0x0cc,0x124,0x17c,0x1d4,0x22c,0x284,0x2dc,0x334,0x38c,0x3e4,0x43c,0x494,0x4ec,0x544,0x59c,0x5f4,0x64c,0x6a4,0x6fc,0x754,0x7ac,0x804,0x85c,0x8b4,0x050,0x0a8,0x100 },
1084 { 0x409,0x461,0x4b9,0x511,0x569,0x5c1,0x619,0x671,0x6c9,0x721,0x779,0x7d1,0x829,0x881,0x01d,0x075,0x0cd,0x125,0x17d,0x1d5,0x22d,0x285,0x2dd,0x335,0x38d,0x3e5,0x43d,0x495,0x4ed,0x545,0x59d,0x5f5,0x64d,0x6a5,0x6fd,0x755,0x7ad,0x805,0x85d,0x8b5,0x051,0x0a9,0x101 },
1085 { 0x45e,0x4b6,0x50e,0x566,0x5be,0x616,0x66e,0x6c6,0x71e,0x776,0x7ce,0x826,0x87e,0x01a,0x072,0x0ca,0x122,0x17a,0x1d2,0x22a,0x282,0x2da,0x332,0x38a,0x3e2,0x43a,0x492,0x4ea,0x542,0x59a,0x5f2,0x64a,0x6a2,0x6fa,0x752,0x7aa,0x802,0x85a,0x8b2,0x04e,0x0a6,0x0fe,0x156 },
1086 { 0x45f,0x4b7,0x50f,0x567,0x5bf,0x617,0x66f,0x6c7,0x71f,0x777,0x7cf,0x827,0x87f,0x01b,0x073,0x0cb,0x123,0x17b,0x1d3,0x22b,0x283,0x2db,0x333,0x38b,0x3e3,0x43b,0x493,0x4eb,0x543,0x59b,0x5f3,0x64b,0x6a3,0x6fb,0x753,0x7ab,0x803,0x85b,0x8b3,0x04f,0x0a7,0x0ff,0x157 },
1087 { 0x4b4,0x50c,0x564,0x5bc,0x614,0x66c,0x6c4,0x71c,0x774,0x7cc,0x824,0x87c,0x018,0x070,0x0c8,0x120,0x178,0x1d0,0x228,0x280,0x2d8,0x330,0x388,0x3e0,0x438,0x490,0x4e8,0x540,0x598,0x5f0,0x648,0x6a0,0x6f8,0x750,0x7a8,0x800,0x858,0x8b0,0x04c,0x0a4,0x0fc,0x154,0x1ac },
1088 { 0x4b5,0x50d,0x565,0x5bd,0x615,0x66d,0x6c5,0x71d,0x775,0x7cd,0x825,0x87d,0x019,0x071,0x0c9,0x121,0x179,0x1d1,0x229,0x281,0x2d9,0x331,0x389,0x3e1,0x439,0x491,0x4e9,0x541,0x599,0x5f1,0x649,0x6a1,0x6f9,0x751,0x7a9,0x801,0x859,0x8b1,0x04d,0x0a5,0x0fd,0x155,0x1ad },
1089 { 0x50a,0x562,0x5ba,0x612,0x66a,0x6c2,0x71a,0x772,0x7ca,0x822,0x87a,0x016,0x06e,0x0c6,0x11e,0x176,0x1ce,0x226,0x27e,0x2d6,0x32e,0x386,0x3de,0x436,0x48e,0x4e6,0x53e,0x596,0x5ee,0x646,0x69e,0x6f6,0x74e,0x7a6,0x7fe,0x856,0x8ae,0x04a,0x0a2,0x0fa,0x152,0x1aa,0x202 },
1090 { 0x50b,0x563,0x5bb,0x613,0x66b,0x6c3,0x71b,0x773,0x7cb,0x823,0x87b,0x017,0x06f,0x0c7,0x11f,0x177,0x1cf,0x227,0x27f,0x2d7,0x32f,0x387,0x3df,0x437,0x48f,0x4e7,0x53f,0x597,0x5ef,0x647,0x69f,0x6f7,0x74f,0x7a7,0x7ff,0x857,0x8af,0x04b,0x0a3,0x0fb,0x153,0x1ab,0x203 },
1091 { 0x560,0x5b8,0x610,0x668,0x6c0,0x718,0x770,0x7c8,0x820,0x878,0x014,0x06c,0x0c4,0x11c,0x174,0x1cc,0x224,0x27c,0x2d4,0x32c,0x384,0x3dc,0x434,0x48c,0x4e4,0x53c,0x594,0x5ec,0x644,0x69c,0x6f4,0x74c,0x7a4,0x7fc,0x854,0x8ac,0x048,0x0a0,0x0f8,0x150,0x1a8,0x200,0x258 },
1092 { 0x561,0x5b9,0x611,0x669,0x6c1,0x719,0x771,0x7c9,0x821,0x879,0x015,0x06d,0x0c5,0x11d,0x175,0x1cd,0x225,0x27d,0x2d5,0x32d,0x385,0x3dd,0x435,0x48d,0x4e5,0x53d,0x595,0x5ed,0x645,0x69d,0x6f5,0x74d,0x7a5,0x7fd,0x855,0x8ad,0x049,0x0a1,0x0f9,0x151,0x1a9,0x201,0x259 },
1093 { 0x5b6,0x60e,0x666,0x6be,0x716,0x76e,0x7c6,0x81e,0x876,0x012,0x06a,0x0c2,0x11a,0x172,0x1ca,0x222,0x27a,0x2d2,0x32a,0x382,0x3da,0x432,0x48a,0x4e2,0x53a,0x592,0x5ea,0x642,0x69a,0x6f2,0x74a,0x7a2,0x7fa,0x852,0x8aa,0x046,0x09e,0x0f6,0x14e,0x1a6,0x1fe,0x256,0x2ae },
1094 { 0x5b7,0x60f,0x667,0x6bf,0x717,0x76f,0x7c7,0x81f,0x877,0x013,0x06b,0x0c3,0x11b,0x173,0x1cb,0x223,0x27b,0x2d3,0x32b,0x383,0x3db,0x433,0x48b,0x4e3,0x53b,0x593,0x5eb,0x643,0x69b,0x6f3,0x74b,0x7a3,0x7fb,0x853,0x8ab,0x047,0x09f,0x0f7,0x14f,0x1a7,0x1ff,0x257,0x2af },
1095 { 0x60c,0x664,0x6bc,0x714,0x76c,0x7c4,0x81c,0x874,0x010,0x068,0x0c0,0x118,0x170,0x1c8,0x220,0x278,0x2d0,0x328,0x380,0x3d8,0x430,0x488,0x4e0,0x538,0x590,0x5e8,0x640,0x698,0x6f0,0x748,0x7a0,0x7f8,0x850,0x8a8,0x044,0x09c,0x0f4,0x14c,0x1a4,0x1fc,0x254,0x2ac,0x304 },
1096 { 0x60d,0x665,0x6bd,0x715,0x76d,0x7c5,0x81d,0x875,0x011,0x069,0x0c1,0x119,0x171,0x1c9,0x221,0x279,0x2d1,0x329,0x381,0x3d9,0x431,0x489,0x4e1,0x539,0x591,0x5e9,0x641,0x699,0x6f1,0x749,0x7a1,0x7f9,0x851,0x8a9,0x045,0x09d,0x0f5,0x14d,0x1a5,0x1fd,0x255,0x2ad,0x305 },
1097 { 0x662,0x6ba,0x712,0x76a,0x7c2,0x81a,0x872,0x00e,0x066,0x0be,0x116,0x16e,0x1c6,0x21e,0x276,0x2ce,0x326,0x37e,0x3d6,0x42e,0x486,0x4de,0x536,0x58e,0x5e6,0x63e,0x696,0x6ee,0x746,0x79e,0x7f6,0x84e,0x8a6,0x042,0x09a,0x0f2,0x14a,0x1a2,0x1fa,0x252,0x2aa,0x302,0x35a },
1098 { 0x663,0x6bb,0x713,0x76b,0x7c3,0x81b,0x873,0x00f,0x067,0x0bf,0x117,0x16f,0x1c7,0x21f,0x277,0x2cf,0x327,0x37f,0x3d7,0x42f,0x487,0x4df,0x537,0x58f,0x5e7,0x63f,0x697,0x6ef,0x747,0x79f,0x7f7,0x84f,0x8a7,0x043,0x09b,0x0f3,0x14b,0x1a3,0x1fb,0x253,0x2ab,0x303,0x35b },
1099 { 0x6b8,0x710,0x768,0x7c0,0x818,0x870,0x00c,0x064,0x0bc,0x114,0x16c,0x1c4,0x21c,0x274,0x2cc,0x324,0x37c,0x3d4,0x42c,0x484,0x4dc,0x534,0x58c,0x5e4,0x63c,0x694,0x6ec,0x744,0x79c,0x7f4,0x84c,0x8a4,0x040,0x098,0x0f0,0x148,0x1a0,0x1f8,0x250,0x2a8,0x300,0x358,0x3b0 },
1100 { 0x6b9,0x711,0x769,0x7c1,0x819,0x871,0x00d,0x065,0x0bd,0x115,0x16d,0x1c5,0x21d,0x275,0x2cd,0x325,0x37d,0x3d5,0x42d,0x485,0x4dd,0x535,0x58d,0x5e5,0x63d,0x695,0x6ed,0x745,0x79d,0x7f5,0x84d,0x8a5,0x041,0x099,0x0f1,0x149,0x1a1,0x1f9,0x251,0x2a9,0x301,0x359,0x3b1 },
1101 { 0x70e,0x766,0x7be,0x816,0x86e,0x00a,0x062,0x0ba,0x112,0x16a,0x1c2,0x21a,0x272,0x2ca,0x322,0x37a,0x3d2,0x42a,0x482,0x4da,0x532,0x58a,0x5e2,0x63a,0x692,0x6ea,0x742,0x79a,0x7f2,0x84a,0x8a2,0x03e,0x096,0x0ee,0x146,0x19e,0x1f6,0x24e,0x2a6,0x2fe,0x356,0x3ae,0x406 },
1102 { 0x70f,0x767,0x7bf,0x817,0x86f,0x00b,0x063,0x0bb,0x113,0x16b,0x1c3,0x21b,0x273,0x2cb,0x323,0x37b,0x3d3,0x42b,0x483,0x4db,0x533,0x58b,0x5e3,0x63b,0x693,0x6eb,0x743,0x79b,0x7f3,0x84b,0x8a3,0x03f,0x097,0x0ef,0x147,0x19f,0x1f7,0x24f,0x2a7,0x2ff,0x357,0x3af,0x407 },
1103 { 0x764,0x7bc,0x814,0x86c,0x008,0x060,0x0b8,0x110,0x168,0x1c0,0x218,0x270,0x2c8,0x320,0x378,0x3d0,0x428,0x480,0x4d8,0x530,0x588,0x5e0,0x638,0x690,0x6e8,0x740,0x798,0x7f0,0x848,0x8a0,0x03c,0x094,0x0ec,0x144,0x19c,0x1f4,0x24c,0x2a4,0x2fc,0x354,0x3ac,0x404,0x45c },
1104 { 0x765,0x7bd,0x815,0x86d,0x009,0x061,0x0b9,0x111,0x169,0x1c1,0x219,0x271,0x2c9,0x321,0x379,0x3d1,0x429,0x481,0x4d9,0x531,0x589,0x5e1,0x639,0x691,0x6e9,0x741,0x799,0x7f1,0x849,0x8a1,0x03d,0x095,0x0ed,0x145,0x19d,0x1f5,0x24d,0x2a5,0x2fd,0x355,0x3ad,0x405,0x45d },
1105 { 0x7ba,0x812,0x86a,0x006,0x05e,0x0b6,0x10e,0x166,0x1be,0x216,0x26e,0x2c6,0x31e,0x376,0x3ce,0x426,0x47e,0x4d6,0x52e,0x586,0x5de,0x636,0x68e,0x6e6,0x73e,0x796,0x7ee,0x846,0x89e,0x03a,0x092,0x0ea,0x142,0x19a,0x1f2,0x24a,0x2a2,0x2fa,0x352,0x3aa,0x402,0x45a,0x4b2 },
1106 { 0x7bb,0x813,0x86b,0x007,0x05f,0x0b7,0x10f,0x167,0x1bf,0x217,0x26f,0x2c7,0x31f,0x377,0x3cf,0x427,0x47f,0x4d7,0x52f,0x587,0x5df,0x637,0x68f,0x6e7,0x73f,0x797,0x7ef,0x847,0x89f,0x03b,0x093,0x0eb,0x143,0x19b,0x1f3,0x24b,0x2a3,0x2fb,0x353,0x3ab,0x403,0x45b,0x4b3 },
1107 { 0x810,0x868,0x004,0x05c,0x0b4,0x10c,0x164,0x1bc,0x214,0x26c,0x2c4,0x31c,0x374,0x3cc,0x424,0x47c,0x4d4,0x52c,0x584,0x5dc,0x634,0x68c,0x6e4,0x73c,0x794,0x7ec,0x844,0x89c,0x038,0x090,0x0e8,0x140,0x198,0x1f0,0x248,0x2a0,0x2f8,0x350,0x3a8,0x400,0x458,0x4b0,0x508 },
1108 { 0x811,0x869,0x005,0x05d,0x0b5,0x10d,0x165,0x1bd,0x215,0x26d,0x2c5,0x31d,0x375,0x3cd,0x425,0x47d,0x4d5,0x52d,0x585,0x5dd,0x635,0x68d,0x6e5,0x73d,0x795,0x7ed,0x845,0x89d,0x039,0x091,0x0e9,0x141,0x199,0x1f1,0x249,0x2a1,0x2f9,0x351,0x3a9,0x401,0x459,0x4b1,0x509 },
1109 { 0x866,0x002,0x05a,0x0b2,0x10a,0x162,0x1ba,0x212,0x26a,0x2c2,0x31a,0x372,0x3ca,0x422,0x47a,0x4d2,0x52a,0x582,0x5da,0x632,0x68a,0x6e2,0x73a,0x792,0x7ea,0x842,0x89a,0x036,0x08e,0x0e6,0x13e,0x196,0x1ee,0x246,0x29e,0x2f6,0x34e,0x3a6,0x3fe,0x456,0x4ae,0x506,0x55e },
1110 { 0x867,0x003,0x05b,0x0b3,0x10b,0x163,0x1bb,0x213,0x26b,0x2c3,0x31b,0x373,0x3cb,0x423,0x47b,0x4d3,0x52b,0x583,0x5db,0x633,0x68b,0x6e3,0x73b,0x793,0x7eb,0x843,0x89b,0x037,0x08f,0x0e7,0x13f,0x197,0x1ef,0x247,0x29f,0x2f7,0x34f,0x3a7,0x3ff,0x457,0x4af,0x507,0x55f }
1111 };
1112
1113
1114 //-------------------------------------------------
1115 // ecc_source_byte - return data from the sector
1116 // at the given offset, masking anything
1117 // particular to a mode
1118 //-------------------------------------------------
1119
ecc_source_byte(const UINT8 * sector,UINT32 offset)1120 inline UINT8 ecc_source_byte(const UINT8 *sector, UINT32 offset)
1121 {
1122 // in mode 2 always treat these as 0 bytes
1123 return (sector[MODE_OFFSET] == 2 && offset < 4) ? 0x00 : sector[SYNC_OFFSET + SYNC_NUM_BYTES + offset];
1124 }
1125
1126
1127 //-------------------------------------------------
1128 // ecc_compute_bytes - calculate an ECC value
1129 // (P or Q)
1130 //-------------------------------------------------
1131
ecc_compute_bytes(const UINT8 * sector,const UINT16 * row,int rowlen,UINT8 & val1,UINT8 & val2)1132 void ecc_compute_bytes(const UINT8 *sector, const UINT16 *row, int rowlen, UINT8 &val1, UINT8 &val2)
1133 {
1134 val1 = val2 = 0;
1135 for (int component = 0; component < rowlen; component++)
1136 {
1137 val1 ^= ecc_source_byte(sector, row[component]);
1138 val2 ^= ecc_source_byte(sector, row[component]);
1139 val1 = ecclow[val1];
1140 }
1141 val1 = ecchigh[ecclow[val1] ^ val2];
1142 val2 ^= val1;
1143 }
1144
1145
1146 //-------------------------------------------------
1147 // ecc_verify - verify the P and Q ECC codes in
1148 // a sector
1149 //-------------------------------------------------
1150
ecc_verify(const UINT8 * sector)1151 bool ecc_verify(const UINT8 *sector)
1152 {
1153 // first verify P bytes
1154 for (int byte = 0; byte < ECC_P_NUM_BYTES; byte++)
1155 {
1156 UINT8 val1, val2;
1157 ecc_compute_bytes(sector, poffsets[byte], ECC_P_COMP, val1, val2);
1158 if (sector[ECC_P_OFFSET + byte] != val1 || sector[ECC_P_OFFSET + ECC_P_NUM_BYTES + byte] != val2)
1159 return false;
1160 }
1161
1162 // then verify Q bytes
1163 for (int byte = 0; byte < ECC_Q_NUM_BYTES; byte++)
1164 {
1165 UINT8 val1, val2;
1166 ecc_compute_bytes(sector, qoffsets[byte], ECC_Q_COMP, val1, val2);
1167 if (sector[ECC_Q_OFFSET + byte] != val1 || sector[ECC_Q_OFFSET + ECC_Q_NUM_BYTES + byte] != val2)
1168 return false;
1169 }
1170 return true;
1171 }
1172
1173
1174 //-------------------------------------------------
1175 // ecc_generate - generate the P and Q ECC codes
1176 // for a sector, overwriting any existing codes
1177 //-------------------------------------------------
1178
ecc_generate(UINT8 * sector)1179 void ecc_generate(UINT8 *sector)
1180 {
1181 // first verify P bytes
1182 for (int byte = 0; byte < ECC_P_NUM_BYTES; byte++)
1183 ecc_compute_bytes(sector, poffsets[byte], ECC_P_COMP, sector[ECC_P_OFFSET + byte], sector[ECC_P_OFFSET + ECC_P_NUM_BYTES + byte]);
1184
1185 // then verify Q bytes
1186 for (int byte = 0; byte < ECC_Q_NUM_BYTES; byte++)
1187 ecc_compute_bytes(sector, qoffsets[byte], ECC_Q_COMP, sector[ECC_Q_OFFSET + byte], sector[ECC_Q_OFFSET + ECC_Q_NUM_BYTES + byte]);
1188 }
1189
1190
1191 //-------------------------------------------------
1192 // ecc_clear - erase the ECC P and Q cods to 0
1193 // within a sector
1194 //-------------------------------------------------
1195
ecc_clear(UINT8 * sector)1196 void ecc_clear(UINT8 *sector)
1197 {
1198 memset(§or[ECC_P_OFFSET], 0, 2 * ECC_P_NUM_BYTES);
1199 memset(§or[ECC_Q_OFFSET], 0, 2 * ECC_Q_NUM_BYTES);
1200 }
1201