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(&sector[ECC_P_OFFSET], 0, 2 * ECC_P_NUM_BYTES);
1199 	memset(&sector[ECC_Q_OFFSET], 0, 2 * ECC_Q_NUM_BYTES);
1200 }
1201