@@ -292,17 +292,101 @@ msf_to_bcd(int *m, int *s, int *f)
292292 * f = bin2bcd (* f );
293293}
294294
295+ void
296+ cdrom_compute_ecc_block (cdrom_t * dev , uint8_t * parity , const uint8_t * data ,
297+ uint32_t major_count , uint32_t minor_count ,
298+ uint32_t major_mult , uint32_t minor_inc )
299+ {
300+ uint32_t size = major_count * minor_count ;
301+
302+ for (uint32_t major = 0 ; major < major_count ; ++ major ) {
303+ uint32_t index = (major >> 1 ) * major_mult + (major & 1 );
304+
305+ uint8_t ecc_a = 0 ;
306+ uint8_t ecc_b = 0 ;
307+
308+ for (uint32_t minor = 0 ; minor < minor_count ; ++ minor ) {
309+ uint8_t temp = data [index ];
310+
311+ index += minor_inc ;
312+
313+ if (index >= size )
314+ index -= size ;
315+
316+ ecc_a ^= temp ;
317+ ecc_b ^= temp ;
318+ ecc_a = dev -> _F_LUT [ecc_a ];
319+ }
320+
321+ parity [major ] = dev -> _B_LUT [dev -> _F_LUT [ecc_a ] ^ ecc_b ];
322+ parity [major + major_count ] = parity [major ] ^ ecc_b ;
323+ }
324+ }
325+
326+ extern void
327+ cdrom_generate_ecc_data (cdrom_t * dev , const uint8_t * data )
328+ {
329+ /* Compute ECC P code. */
330+ cdrom_compute_ecc_block (dev , dev -> p_parity , data , 86 , 24 , 2 , 86 );
331+
332+ /* Compute ECC Q code. */
333+ cdrom_compute_ecc_block (dev , dev -> q_parity , data , 52 , 43 , 86 , 88 );
334+ }
335+
295336static int
296- read_data (cdrom_t * dev , const uint32_t lba )
337+ cdrom_is_sector_good (cdrom_t * dev , const uint8_t * b , const uint8_t mode2 , const uint8_t form )
297338{
298- int ret = 1 ;
339+ int ret = 1 ;
340+
341+ if (mode2 && (form == 1 )) {
342+ const uint32_t crc = cdrom_crc32 (0xffffffff , b , 2072 ) ^ 0xffffffff ;
343+
344+ ret = ret && (crc == (* (uint32_t * ) & (b [2072 ])));
345+ } else if (!mode2 ) {
346+ const uint32_t crc = cdrom_crc32 (0xffffffff , b , 2064 ) ^ 0xffffffff ;
347+
348+ ret = ret && (crc == (* (uint32_t * ) & (b [2064 ])));
349+ }
350+
351+ cdrom_generate_ecc_data (dev , & (b [12 ]));
352+
353+ ret = ret && !memcmp (dev -> p_parity , & (b [2076 ]), 172 );
354+ ret = ret && !memcmp (dev -> q_parity , & (b [2248 ]), 104 );
355+
356+ return ret ;
357+ }
358+
359+ static int
360+ read_data (cdrom_t * dev , const uint32_t lba , int check )
361+ {
362+ int ret = 1 ;
363+ int form = 0 ;
299364
300365 if (dev -> cached_sector != lba ) {
301366 dev -> cached_sector = lba ;
302367
303368 ret = dev -> ops -> read_sector (dev -> local ,
304369 dev -> raw_buffer [dev -> cur_buf ^ 1 ], lba );
305370
371+ if ((ret > 0 ) && check ) {
372+ if (dev -> mode2 ) {
373+ if (dev -> raw_buffer [dev -> cur_buf ^ 1 ][0x000f ] == 0x01 )
374+ /*
375+ Use Mode 1, since evidently specification-violating
376+ discs exist.
377+ */
378+ dev -> mode2 = 0 ;
379+ else if (dev -> raw_buffer [dev -> cur_buf ^ 1 ][0x0012 ] ==
380+ dev -> raw_buffer [dev -> cur_buf ^ 1 ][0x0016 ])
381+ form = ((dev -> raw_buffer [dev -> cur_buf ^ 1 ][0x0012 ] &
382+ 0x20 ) >> 5 ) + 1 ;
383+ } else if (dev -> raw_buffer [dev -> cur_buf ^ 1 ][0x000f ] == 0x02 )
384+ dev -> mode2 = 1 ;
385+
386+ if (!cdrom_is_sector_good (dev , dev -> raw_buffer [dev -> cur_buf ^ 1 ], dev -> mode2 , form ))
387+ ret = -1 ;
388+ }
389+
306390 if (ret <= 0 ) {
307391 memset (dev -> raw_buffer [dev -> cur_buf ^ 1 ], 0x00 , 2448 );
308392 dev -> cached_sector = -1 ;
@@ -322,7 +406,7 @@ cdrom_get_subchannel(cdrom_t *dev, const uint32_t lba,
322406 if (lba != dev -> cached_sector )
323407 dev -> cached_sector = -1 ;
324408
325- (void ) read_data (dev , lba );
409+ (void ) read_data (dev , lba , 0 );
326410
327411 for (int i = 0 ; i < 12 ; i ++ )
328412 for (int j = 0 ; j < 8 ; j ++ )
@@ -679,7 +763,7 @@ track_type_is_valid(UNUSED(const cdrom_t *dev), const int type, const int flags,
679763static int
680764read_audio (cdrom_t * dev , const uint32_t lba , uint8_t * b )
681765{
682- const int ret = read_data (dev , lba );
766+ const int ret = read_data (dev , lba , 0 );
683767
684768 memcpy (b , dev -> raw_buffer [dev -> cur_buf ], 2352 );
685769
@@ -2379,6 +2463,8 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, const int sector, const int
23792463 if (dm != CD_TRACK_NORMAL )
23802464 mode2 = 1 ;
23812465
2466+ dev -> mode2 = mode2 ;
2467+
23822468 memset (dev -> extra_buffer , 0 , 296 );
23832469
23842470 if ((cdrom_sector_flags & 0xf8 ) == 0x08 ) {
@@ -2405,7 +2491,7 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, const int sector, const int
24052491 else
24062492 ret = read_audio (dev , lba , temp_b );
24072493 } else {
2408- ret = read_data (dev , lba );
2494+ ret = read_data (dev , lba , 1 );
24092495
24102496 /* Return with error if we had one. */
24112497 if (ret > 0 ) {
@@ -2800,7 +2886,7 @@ cdrom_read_track_information(cdrom_t *dev, const uint8_t *cdb, uint8_t *buffer)
28002886 }
28012887
28022888 if (track -> adr_ctl & 0x04 ) {
2803- ret = read_data (dev , start );
2889+ ret = read_data (dev , start , 0 );
28042890 mode = dev -> raw_buffer [dev -> cur_buf ][3 ];
28052891 }
28062892 } else if (track -> point != 0xa2 )
@@ -2829,9 +2915,9 @@ uint8_t
28292915cdrom_get_current_mode (cdrom_t * dev )
28302916{
28312917 if (dev -> cached_sector == -1 )
2832- (void ) read_data (dev , dev -> seek_pos );
2918+ (void ) read_data (dev , dev -> seek_pos , 0 );
28332919 else
2834- (void ) read_data (dev , dev -> cached_sector );
2920+ (void ) read_data (dev , dev -> cached_sector , 0 );
28352921
28362922 return dev -> raw_buffer [dev -> cur_buf ][3 ];
28372923}
@@ -3011,6 +3097,11 @@ cdrom_hard_reset(void)
30113097
30123098 cdrom_load (dev , dev -> image_path , 0 );
30133099 }
3100+
3101+ for (uint32_t j = 0 ; j < _LUT_SIZE ; ++ j ) {
3102+ dev -> _F_LUT [j ] = (j << 1 ) ^ (j & 0x80 ? 0x11d : 0 );
3103+ dev -> _B_LUT [j ^ dev -> _F_LUT [j ]] = j ;
3104+ }
30143105 }
30153106 }
30163107
0 commit comments