static void subfunc(uae_u8 *data, int cnt) { uae_u8 out[SUB_CHANNEL_SIZE]; sub_to_deinterleaved(data, out); setsubchannel(out); uae_sem_wait(&sub_sem); if (subcodebufferinuse[subcodebufferoffsetw]) { memset (subcodebufferinuse, 0,sizeof (subcodebufferinuse)); subcodebufferoffsetw = subcodebufferoffset = 0; } else { int offset = subcodebufferoffsetw; while (cnt > 0) { if (subcodebufferinuse[offset]) { write_log (_T("CD32: subcode buffer overflow 2\n")); break; } subcodebufferinuse[offset] = 1; memcpy (&subcodebuffer[offset * SUB_CHANNEL_SIZE], data, SUB_CHANNEL_SIZE); data += SUB_CHANNEL_SIZE; offset++; if (offset >= MAX_SUBCODEBUFFER) offset = 0; cnt--; } subcodebufferoffsetw = offset; } uae_sem_post(&sub_sem); }
static int getsub_deinterleaved (uae_u8 *dst, struct cdunit *cdu, struct cdtoc *t, int sector) { int ret = 0; uae_sem_wait (&cdu->sub_sem); if (t->subcode) { if (t->enctype == ENC_CHD) { const cdrom_track_info *cti = t->chdtrack; ret = do_read (cdu, t, dst, sector, cti->datasize, cti->subsize); if (ret) ret = t->subcode; } else if (t->subhandle) { int offset = 0; int totalsize = SUB_CHANNEL_SIZE; if (t->skipsize) { totalsize += t->size; offset = t->size; } zfile_fseek (t->subhandle, (uae_u64)sector * totalsize + t->suboffset + offset, SEEK_SET); if (zfile_fread (dst, SUB_CHANNEL_SIZE, 1, t->subhandle) > 0) ret = t->subcode; } else { memcpy (dst, t->subdata + sector * SUB_CHANNEL_SIZE + t->suboffset, SUB_CHANNEL_SIZE); ret = t->subcode; } } if (!ret) { memset (dst, 0, SUB_CHANNEL_SIZE); // regenerate Q-subchannel uae_u8 *s = dst + 12; s[0] = (t->ctrl << 4) | (t->adr << 0); s[1] = tobcd (t - &cdu->toc[0] + 1); s[2] = tobcd (1); int msf = lsn2msf (sector); tolongbcd (s + 7, msf); msf = lsn2msf (sector - t->address - 150); tolongbcd (s + 3, msf); ret = 2; } if (ret == 1) { uae_u8 tmp[SUB_CHANNEL_SIZE]; memcpy (tmp, dst, SUB_CHANNEL_SIZE); sub_to_deinterleaved (tmp, dst); ret = 2; } uae_sem_post (&cdu->sub_sem); return ret; }
static int ioctl_command_rawread (int unitnum, uae_u8 *data, int sector, int size, int sectorsize, uae_u32 extra) { struct dev_info_ioctl *ciw = unitisopen (unitnum); if (!ciw) return 0; uae_u8 *p = ciw->tempbuffer; int ret = 0; if (log_scsi) write_log (_T("IOCTL rawread unit=%d sector=%d blocksize=%d\n"), unitnum, sector, sectorsize); cdda_stop (ciw); gui_flicker_led (LED_CD, unitnum, LED_CD_ACTIVE); if (sectorsize > 0) { if (sectorsize != 2336 && sectorsize != 2352 && sectorsize != 2048 && sectorsize != 2336 + 96 && sectorsize != 2352 + 96 && sectorsize != 2048 + 96) return 0; while (size-- > 0) { if (!read_block (ciw, unitnum, data, sector, 1, sectorsize)) break; ciw->cd_last_pos = sector; data += sectorsize; ret += sectorsize; sector++; } } else { uae_u8 sectortype = extra >> 16; uae_u8 cmd9 = extra >> 8; int sync = (cmd9 >> 7) & 1; int headercodes = (cmd9 >> 5) & 3; int userdata = (cmd9 >> 4) & 1; int edcecc = (cmd9 >> 3) & 1; int errorfield = (cmd9 >> 1) & 3; uae_u8 subs = extra & 7; if (subs != 0 && subs != 1 && subs != 2 && subs != 4) return -1; if (errorfield >= 3) return -1; uae_u8 *d = data; if (isaudiotrack (&ciw->di.toc, sector)) { if (sectortype != 0 && sectortype != 1) return -2; for (int i = 0; i < size; i++) { uae_u8 *odata = data; int blocksize = errorfield == 0 ? 2352 : (errorfield == 1 ? 2352 + 294 : 2352 + 296); int readblocksize = errorfield == 0 ? 2352 : 2352 + 296; if (!read_block (ciw, unitnum, NULL, sector, 1, readblocksize)) { reseterrormode (ciw); return ret; } ciw->cd_last_pos = sector; if (subs == 0) { memcpy (data, p, blocksize); data += blocksize; } else if (subs == 4) { // all, de-interleaved memcpy (data, p, blocksize); data += blocksize; sub_to_deinterleaved (p + readblocksize, data); data += SUB_CHANNEL_SIZE; } else if (subs == 2) { // q-only memcpy (data, p, blocksize); data += blocksize; uae_u8 subdata[SUB_CHANNEL_SIZE]; sub_to_deinterleaved (p + readblocksize, subdata); memcpy (data, subdata + SUB_ENTRY_SIZE, SUB_ENTRY_SIZE); p += SUB_ENTRY_SIZE; } else if (subs == 1) { // all, interleaved memcpy (data, p, blocksize); memcpy (data + blocksize, p + readblocksize, SUB_CHANNEL_SIZE); data += blocksize + SUB_CHANNEL_SIZE; } ret += data - odata; sector++; } } } return ret; }