@@ -292,17 +292,101 @@ msf_to_bcd(int *m, int *s, int *f)
292292*f = bin2bcd(*f);
293293}
294294295+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;
299364300365if (dev->cached_sector != lba) {
301366dev->cached_sector = lba;
302367303368ret = dev->ops->read_sector(dev->local,
304369dev->raw_buffer[dev->cur_buf ^ 1], lba);
305370371+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+306390if (ret <= 0) {
307391memset(dev->raw_buffer[dev->cur_buf ^ 1], 0x00, 2448);
308392dev->cached_sector = -1;
@@ -322,7 +406,7 @@ cdrom_get_subchannel(cdrom_t *dev, const uint32_t lba,
322406if (lba != dev->cached_sector)
323407dev->cached_sector = -1;
324408325- (void) read_data(dev, lba);
409+ (void) read_data(dev, lba, 0);
326410327411for (int i = 0; i < 12; i++)
328412for (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);
683767684768memcpy(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
23792463if (dm != CD_TRACK_NORMAL)
23802464mode2 = 1;
238124652466+dev->mode2 = mode2;
2467+23822468memset(dev->extra_buffer, 0, 296);
2383246923842470if ((cdrom_sector_flags & 0xf8) == 0x08) {
@@ -2405,7 +2491,7 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, const int sector, const int
24052491else
24062492ret = read_audio(dev, lba, temp_b);
24072493 } else {
2408-ret = read_data(dev, lba);
2494+ret = read_data(dev, lba, 1);
2409249524102496/* Return with error if we had one. */
24112497if (ret > 0) {
@@ -2800,7 +2886,7 @@ cdrom_read_track_information(cdrom_t *dev, const uint8_t *cdb, uint8_t *buffer)
28002886 }
2801288728022888if (track->adr_ctl & 0x04) {
2803-ret = read_data(dev, start);
2889+ret = read_data(dev, start, 0);
28042890mode = 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{
28312917if (dev->cached_sector == -1)
2832- (void) read_data(dev, dev->seek_pos);
2918+ (void) read_data(dev, dev->seek_pos, 0);
28332919else
2834- (void) read_data(dev, dev->cached_sector);
2920+ (void) read_data(dev, dev->cached_sector, 0);
2835292128362922return dev->raw_buffer[dev->cur_buf][3];
28372923}
@@ -3011,6 +3097,11 @@ cdrom_hard_reset(void)
3011309730123098cdrom_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