diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2012-12-31 05:04:42 +0400 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2012-12-31 05:04:42 +0400 |
commit | 71dc8760ff4de5f365330d1bc571d934deb54af9 (patch) | |
tree | 7346d42a282562a3937d82307012b5857d642ce6 /wodim/subchan.c | |
download | cdrkit-71dc8760ff4de5f365330d1bc571d934deb54af9.tar.gz |
Imported Upstream version 1.1.11upstream/1.1.11upstream
Diffstat (limited to 'wodim/subchan.c')
-rw-r--r-- | wodim/subchan.c | 997 |
1 files changed, 997 insertions, 0 deletions
diff --git a/wodim/subchan.c b/wodim/subchan.c new file mode 100644 index 0000000..7195992 --- /dev/null +++ b/wodim/subchan.c @@ -0,0 +1,997 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)subchan.c 1.20 05/06/11 Copyright 2000-2004 J. Schilling */ +/* + * Subchannel processing + * + * Copyright (c) 2000-2004 J. Schilling + */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <mconfig.h> +#include <stdio.h> +#include <unixstd.h> +#include <standard.h> +#include <utypes.h> +#include <schily.h> + +#include <usal/scsitransp.h> + +#include "wodim.h" +#include "crc16.h" + +int do_leadin(track_t *trackp); +int write_leadin(SCSI *usalp, cdr_t *dp, track_t *trackp, int leadinstart); +int write_leadout(SCSI *usalp, cdr_t *dp, track_t *trackp); +void fillsubch(track_t *trackp, Uchar *sp, int secno, int nsecs); +void filltpoint(Uchar *sub, int ctrl_adr, int point, msf_t *mp); +void fillttime(Uchar *sub, msf_t *mp); +static void filldsubq(Uchar *sub, int ca, int t, int i, msf_t *mrp, + msf_t *mp); +static void fillmcn(Uchar *sub, Uchar *mcn); +static void fillisrc(Uchar *sub, Uchar *isrc); +static int ascii2q(int c); +static void qpto16(Uchar *sub, Uchar *subq, int dop); +void qpto96(Uchar *sub, Uchar *subq, int dop); +void addrw(Uchar *sub, Uchar *subrwptr); +void qwto16(Uchar *subq, Uchar *subptr); +void subrecodesecs(track_t *trackp, Uchar *bp, int address, int nsecs); +static void subinterleave(Uchar *sub); + +/*#define TEST_CRC*/ +#ifdef TEST_CRC +static void testcrc(void); +#endif + +/*Die 96 Bits == 12 Bytes haben folgendes Aussehen:*/ + +struct q { + Uchar ctrl_adr; /* 0 (ctrl << 4) | adr */ + Uchar track; /* 1 current track # */ + Uchar index; /* 2 current index # */ + Uchar pmin; /* 3 Relative time minutes part */ + Uchar psec; /* 4 Relative time seconds part */ + Uchar pframe; /* 5 Relative time frames part */ + Uchar zero; /* 6 */ + Uchar amin; /* 7 Absolute time minutes part */ + Uchar asec; /* 8 Absolute time seconds part */ + Uchar aframe; /* 9 Absolute time frames part */ + Uchar crc1; /* 10 all bits inverted. Polynom is */ + Uchar crc2; /* 11 X^16 + X^12 + X^5 + 1 */ +}; + +Uchar _subq[110][12]; +int _nsubh; + +extern int lverbose; +extern int xdebug; + +/* + * Prepare master sunchannel data for RAW TOC. + */ +int +do_leadin(track_t *trackp) +{ + int tracks = trackp->tracks; + msf_t m; + int ctrl; + int i; + int toctype = trackp[0].tracktype & TOC_MASK; + + if (_nsubh) { + if (xdebug) + printf("Using CLONE TOC....\n"); + return (0); + } + if (xdebug) + printf("Leadin TOC Type: %d\n", trackp[0].tracktype & TOC_MASK); + if (lverbose > 1) { + for (i = 1; i <= tracks+1; i++) + printf("Track %d start %ld\n", i, trackp[i].trackstart); + } + +#ifdef TEST_CRC + testcrc(); +/* exit(1);*/ +#endif + + fillbytes(_subq, sizeof (_subq), '\0'); + + /* + * Fill in point 0xA0 for first track # on disk + */ + ctrl = (st2mode[trackp[0].sectype & ST_MASK]) << 4; + if (is_copy(&trackp[0])) + ctrl |= TM_ALLOW_COPY << 4; + m.msf_min = trackp[1].trackno; + /* + * Disk Type: 0 = AUDIO/DATA, 0x10 = CDI, 0x20 = XA mode 2 + */ + m.msf_sec = toc2sess[toctype & TOC_MASK]; + m.msf_sec = from_bcd(m.msf_sec); /* convert to BCD */ + m.msf_frame = 0; + filltpoint(_subq[0], ctrl|0x01, 0xA0, &m); + if (lverbose > 2) + usal_prbytes("", _subq[0], 12); + + /* + * Fill in point 0xA1 for last track # on disk + */ + ctrl = (st2mode[trackp[tracks].sectype & ST_MASK]) << 4; + if (is_copy(&trackp[tracks])) + ctrl |= TM_ALLOW_COPY << 4; + m.msf_min = trackp[tracks].trackno; + m.msf_sec = 0; + m.msf_frame = 0; + filltpoint(_subq[1], ctrl|0x01, 0xA1, &m); + if (lverbose > 2) + usal_prbytes("", _subq[1], 12); + + /* + * Fill in point 0xA2 for lead out start time on disk + */ + lba_to_msf(trackp[tracks+1].trackstart, &m); + ctrl = (st2mode[trackp[tracks].sectype & ST_MASK]) << 4; + if (is_copy(&trackp[tracks])) + ctrl |= TM_ALLOW_COPY << 4; + filltpoint(_subq[2], ctrl|0x01, 0xA2, &m); + if (lverbose > 2) + usal_prbytes("", _subq[2], 12); + + /* + * Fill in track start times. + */ + for (i = 1; i <= tracks; i++) { + lba_to_msf(trackp[i].trackstart, &m); + ctrl = (st2mode[trackp[i].sectype & ST_MASK]) << 4; + if (is_copy(&trackp[i])) + ctrl |= TM_ALLOW_COPY << 4; + filltpoint(_subq[i-1+3], ctrl|0x01, to_bcd(trackp[i].trackno), &m); /* track n */ + if (lverbose > 2) + usal_prbytes("", _subq[i-1+3], 12); + } + return (0); +} + +/* + * Write TOC (lead-in) + * + * Use previously prepared master subchannel data to create the + * subchannel frames for the lead-in. + */ +int +write_leadin(SCSI *usalp, cdr_t *dp, track_t *trackp, int leadinstart) +{ + msf_t m; + int i; + Uint j; + Uchar *bp = usalp->bufptr; + Uchar *subp; + Uchar *sp; + int secsize; + int secspt; + int bytespt; + long amount; + int startsec; + long bytes = 0L; + int textoff = 0; + msf_t msf; + + secsize = trackp[0].secsize; + secspt = trackp[0].secspt; + bytespt = secspt * secsize; + + lba_to_msf(leadinstart, &msf); + + fillbytes(bp, bytespt, '\0'); + + if (_nsubh) { + if (xdebug) + printf("Using CLONE LEADIN\n"); + } + if (xdebug) { + printf("Leadinstart: %d %d:%d/%d", + leadinstart, + msf.msf_min, msf.msf_sec, msf.msf_frame); + printf(" FLAGS: 0x%X sect: %X RAW16:%d secs: %d spt: %d\n", + trackp[0].flags, trackp[0].sectype, + is_raw16(&trackp[0]), secsize, secspt); + } + + startsec = leadinstart; + sp = bp; + subp = bp + 2352; + for (i = leadinstart, j = 0; i < -150; i++, j++) { + /* + * TOC hat folgende unterschiedliche Sub Q Frames: + * A0 First Track + * A1 Last Track + * A3 Lead out start + * 1..99 Tracks + * == 3 + N* tracks + * Jeder Frame wird 3x wiederholt. + */ + if (_nsubh) { + if (j >= (3*_nsubh)) + j = 0; + } else { + if (j >= (3*3 + 3*trackp->tracks)) + j = 0; + } + lba_to_msf((long)i, &m); + fillttime(_subq[j/3], &m); + fillcrc(_subq[j/3], 12); + if (xdebug > 2) + usal_prbytes("", _subq[j/3], 12); + if (is_raw16(&trackp[0])) { + qpto16(subp, _subq[j/3], 0); + } else { + extern Uchar *textsub; + extern int textlen; + + qpto96(subp, _subq[j/3], 0); + if (textsub) { + addrw(subp, &textsub[textoff]); + textoff += 96; + if (textoff >= textlen) + textoff = 0; + } +/* if (is_raw96p(&trackp[0]))*/ +/* subinterleave(subp);*/ + } + if ((startsec+secspt-1) == i || i == -151) { + if ((i-startsec+1) < secspt) { + secspt = i-startsec+1; + bytespt = secspt * secsize; + } + encsectors(trackp, bp, startsec, secspt); + + amount = write_secs(usalp, dp, + (char *)bp, startsec, bytespt, secspt, FALSE); + if (amount < 0) { + printf("write leadin data: error after %ld bytes\n", + bytes); + return (-1); + } + bytes += amount; + startsec = i+1; + sp = bp; + subp = bp + 2352; + continue; + } + sp += secsize; + subp += secsize; + } + return (0); +} + +/* + * Write Track 0xAA (lead-out) + */ +int +write_leadout(SCSI *usalp, cdr_t *dp, track_t *trackp) +{ + int tracks = trackp->tracks; + msf_t m; + msf_t mr; + int ctrl; + int i; + int j; + Uchar *bp = usalp->bufptr; + Uchar *subp; + Uchar *sp; + int secsize; + int secspt; + int bytespt; + long amount; + long startsec; + long endsec; + long bytes = 0L; + int leadoutstart; + Uchar sub[12]; + BOOL p; + msf_t msf; + + fillbytes(sub, 12, '\0'); + + secsize = trackp[tracks+1].secsize; + secspt = trackp[tracks+1].secspt; + bytespt = secspt * secsize; + + leadoutstart = trackp[tracks+1].trackstart; + lba_to_msf(leadoutstart, &msf); + + fillbytes(bp, bytespt, '\0'); + + if (xdebug) { + printf("Leadoutstart: %d %d:%d/%d amt %ld", + leadoutstart, + msf.msf_min, msf.msf_sec, msf.msf_frame, + trackp[tracks+1].tracksecs); + printf(" FLAGS: 0x%X sect: %X RAW16:%d secs: %d spt: %d\n", + trackp[tracks+1].flags, trackp[tracks+1].sectype, + is_raw16(&trackp[tracks+1]), secsize, secspt); + } + + startsec = leadoutstart; + endsec = startsec + trackp[tracks+1].tracksecs; + sp = bp; + subp = bp + 2352; + ctrl = (st2mode[trackp->sectype & ST_MASK]) << 4; + if (is_copy(trackp)) + ctrl |= TM_ALLOW_COPY << 4; + + for (i = leadoutstart, j = 0; i < endsec; i++, j++) { + + lba_to_msf((long)i, &m); + sec_to_msf((long)j, &mr); + filldsubq(sub, ctrl|0x01, 0xAA, 1, &mr, &m); + sub[1] = 0xAA; + fillcrc(sub, 12); + p = (j % 150) < 75; + if (j < 150) + p = FALSE; + if (xdebug > 2) + usal_prbytes(p?"P":" ", sub, 12); + + if (is_raw16(&trackp[0])) { + qpto16(subp, sub, p); + } else { + qpto96(subp, sub, p); +/* if (is_raw96p(&trackp[0]))*/ +/* subinterleave(subp);*/ + } + if ((startsec+secspt-1) == i || i == (endsec-1)) { + if ((i-startsec+1) < secspt) { + secspt = i-startsec+1; + bytespt = secspt * secsize; + } + encsectors(trackp, bp, startsec, secspt); + + amount = write_secs(usalp, dp, + (char *)bp, startsec, bytespt, secspt, FALSE); + if (amount < 0) { + printf("write leadout data: error after %ld bytes\n", + bytes); + return (-1); + } + bytes += amount; + startsec = i+1; + sp = bp; + subp = bp + 2352; + continue; + } + sp += secsize; + subp += secsize; + } + return (0); +} + +/* + * Fill in subchannel data. + * + * This function is used to prepare the sub channels when writing + * the data part of a CD (bewteen lead-in and lead-out). + */ +void +fillsubch(track_t *trackp, + Uchar *sp /* Sector data pointer */, + int secno /* Starting sector # */, + int nsecs /* # of sectors to fill */) +{ + msf_t m; + msf_t mr; + int ctrl; + int i; + int rsecno; + int end; + int secsize = trackp->secsize; + int trackno = trackp->trackno; + int nindex = trackp->nindex; + int curindex; + long *tindex = NULL; + long nextindex = 0L; + Uchar sub[12]; + Uchar *sup; + char *mcn; + /* + * In theory this should make fillsubch() non-reenrtrant but it seems + * that the probability check at the beginning of the function is + * sufficient to make it work as expected. + */ +static long nextmcn = -1000000L; +static long nextisrc = -1000000L; +static Uchar lastindex = 255; + + fillbytes(sub, 12, '\0'); + + mcn = track_base(trackp)->isrc; + rsecno = secno - trackp->trackstart; + if ((secno + nsecs) > (trackp->trackstart + trackp->tracksecs)) { + comerrno(EX_BAD, "Implementation botch: track boundary in buffer.\n"); + } + sup = sp + 2352; + if (mcn && (nextmcn < secno || nextmcn > (secno+100))) { + nextmcn = secno/100*100 + 99; + } + if (trackp->isrc && (nextisrc < secno || nextisrc > (secno+100))) { + nextisrc = secno/100*100 + 49; + } + ctrl = (st2mode[trackp->sectype & ST_MASK]) << 4; + if (is_copy(trackp)) + ctrl |= TM_ALLOW_COPY << 4; + +#ifdef SUB_DEBUG + fprintf(stderr, "Tracknl %d nindex %d trackstart %ld rsecno %d index0start %ld nsecs %d\n", + trackno, nindex, trackp->trackstart, rsecno, trackp->index0start, nsecs); +#endif + + if (rsecno < 0) { + /* + * Called to manually write pregap null data into the pregap + * while 'trackp' points to the curent track. For this reason, + * the sectors are before the start of track 'n' index 0. + */ + curindex = 0; + end = trackp->trackstart; + + } else if (rsecno > trackp->index0start) { + /* + * This track contains pregap of next track. + * We currently are inside this pregap. + */ + trackno++; + curindex = 0; + end = trackp->trackstart + trackp->tracksecs; + } else { + /* + * We are inside the normal data part of this track. + * This is index_1...index_m for track n. + * Set 'end' to 0 in this case although it is only used + * if 'index' is 0. But GCC gives a warning that 'end' + * might be uninitialized. + */ + end = 0; + curindex = 1; + if (nindex > 1) { + tindex = trackp->tindex; + nextindex = trackp->tracksecs; + /* + * find current index in list + */ + for (curindex = nindex; curindex >= 1; curindex--) { + if (rsecno >= tindex[curindex]) { + if (curindex < nindex) + nextindex = tindex[curindex+1]; + break; + } + } + } + } + + for (i = 0; i < nsecs; i++) { + + if (tindex != NULL && rsecno >= nextindex) { + /* + * Skip to next index in list. + */ + if (curindex < nindex) { + curindex++; + nextindex = tindex[curindex+1]; + } + } + if (rsecno == trackp->index0start) { + /* + * This track contains pregap of next track. + */ + trackno++; + curindex = 0; + end = trackp->trackstart + trackp->tracksecs; + } + lba_to_msf((long)secno, &m); + if (curindex == 0) + sec_to_msf((long)end-1 - secno, &mr); + else + sec_to_msf((long)rsecno, &mr); + if (is_scms(trackp)) { + if ((secno % 8) <= 3) { + ctrl &= ~(TM_ALLOW_COPY << 4); + } else { + ctrl |= TM_ALLOW_COPY << 4; + } + } + filldsubq(sub, ctrl|0x01, trackno, curindex, &mr, &m); + if (mcn && (secno == nextmcn)) { + if (curindex == lastindex) { + fillmcn(sub, (Uchar *)mcn); + nextmcn = (secno+1)/100*100 + 99; + } else { + nextmcn++; + } + } + if (trackp->isrc && (secno == nextisrc)) { + if (curindex == lastindex) { + fillisrc(sub, (Uchar *)trackp->isrc); + nextisrc = (secno+1)/100*100 + 49; + } else { + nextisrc++; + } + } + fillcrc(sub, 12); + if (xdebug > 2) + usal_prbytes(curindex == 0 ? "P":" ", sub, 12); + if (is_raw16(trackp)) { + qpto16(sup, sub, curindex == 0); + } else { + qpto96(sup, sub, curindex == 0); +/* if (is_raw96p(trackp))*/ +/* subinterleave(sup);*/ + } + lastindex = curindex; + secno++; + rsecno++; + sup += secsize; + } +} + + +/* + * Fill TOC Point + * Ax Werte einfüllen. + */ +void +filltpoint(Uchar *sub, int ctrl_adr, int point, msf_t *mp) +{ + sub[0] = ctrl_adr; + sub[2] = point; + sub[7] = to_bcd(mp->msf_min); + sub[8] = to_bcd(mp->msf_sec); + sub[9] = to_bcd(mp->msf_frame); +} + +/* + * Fill TOC time + * Aktuelle Zeit in TOC Sub-Q einfüllen. + */ +void +fillttime(Uchar *sub, msf_t *mp) +{ + sub[3] = to_bcd(mp->msf_min); + sub[4] = to_bcd(mp->msf_sec); + sub[5] = to_bcd(mp->msf_frame); +} + +/* + * Q-Sub in Datenbereich füllen. + */ +static void +filldsubq(Uchar *sub, int ca, int t, int i, msf_t *mrp, msf_t *mp) +{ + sub[0] = ca; + sub[1] = to_bcd(t); + sub[2] = to_bcd(i); + sub[3] = to_bcd(mrp->msf_min); + sub[4] = to_bcd(mrp->msf_sec); + sub[5] = to_bcd(mrp->msf_frame); + + sub[7] = to_bcd(mp->msf_min); + sub[8] = to_bcd(mp->msf_sec); + sub[9] = to_bcd(mp->msf_frame); +} + +/* + * Fill MCN + * MCN konvertieren und in Sub-Q einfüllen. + */ +static void +fillmcn(Uchar *sub, Uchar *mcn) +{ + register int i; + register int c; + + sub[0] = ADR_MCN; + for (i = 1; i <= 8; i++) { + c = *mcn++; + if (c >= '0' && c <= '9') + sub[i] = (c - '0') << 4; + else + sub[i] = 0; + + if (c != '\0') + c = *mcn++; + if (c >= '0' && c <= '9') + sub[i] |= (c - '0'); + + if (c == '\0') { + i++; + break; + } + } + for (; i <= 8; i++) + sub[i] = '\0'; +} + +/* + * Fill ISRC + * ISRC konvertieren und in Sub-Q einfüllen. + */ +static void +fillisrc(Uchar *sub, Uchar *isrc) +{ + register int i; + register int j; + Uchar tmp[13]; + Uchar *sp; + + sub[0] = ADR_ISRC; + sp = &sub[1]; + + /* + * Convert into Sub-Q character coding + */ + for (i = 0, j = 0; i < 12; i++) { + if (isrc[i+j] == '-') + j++; + if (isrc[i+j] == '\0') + break; + tmp[i] = ascii2q(isrc[i+j]); + } + for (; i < 13; i++) + tmp[i] = '\0'; + + /* + * The first 5 chars from e.g. "FI-BAR-99-00312" + */ + sp[0] = tmp[0] << 2; + sp[0] |= (tmp[1] >> 4) & 0x03; + sp[1] = (tmp[1] << 4) & 0xF0; + sp[1] |= (tmp[2] >> 2) & 0x0F; + sp[2] = (tmp[2] << 6) & 0xC0; + sp[2] |= tmp[3] & 0x3F; + sp[3] = tmp[4] << 2; + + /* + * Now 7 digits from e.g. "FI-BAR-99-00312" + */ + for (i = 4, j = 5; i < 8; i++) { + sp[i] = tmp[j++] << 4; + sp[i] |= tmp[j++]; + } +} + +/* + * ASCII -> Sub-Q ISRC code conversion + */ +static int +ascii2q(int c) +{ + if (c >= '0' && c <= '9') + return (c - '0'); + else if (c >= '@' && c <= 'o') + return (0x10 + c - '@'); + return (0); +} + +/* + * Q-Sub auf 16 Bytes blähen und P-Sub addieren + * + * OUT: sub, IN: subqptr + */ +static void +qpto16(Uchar *sub, Uchar *subqptr, int dop) +{ + if (sub != subqptr) + movebytes(subqptr, sub, 12); + sub[12] = '\0'; + sub[13] = '\0'; + sub[14] = '\0'; + sub[15] = '\0'; + if (dop) + sub[15] |= 0x80; + +} + +/* + * Q-Sub auf 96 Bytes blähen und P-Sub addieren + * + * OUT: sub, IN: subqptr + */ +void +qpto96(Uchar *sub, Uchar *subqptr, int dop) +{ + Uchar tmp[16]; + Uchar *p; + int c; + int i; + + if (subqptr == sub) { + /* + * Remember 12 byte subchannel data if subchannel + * is overlapping. + */ + movebytes(subqptr, tmp, 12); + subqptr = tmp; + } + /* + * Clear all subchannel bits in the 96 byte target space. + */ + fillbytes(sub, 96, '\0'); + + /* BEGIN CSTYLED */ + if (dop) for (i = 0, p = sub; i < 96; i++) { + *p++ |= 0x80; + } + for (i = 0, p = sub; i < 12; i++) { + c = subqptr[i] & 0xFF; +/*printf("%02X\n", c);*/ + if (c & 0x80) + *p++ |= 0x40; + else + p++; + if (c & 0x40) + *p++ |= 0x40; + else + p++; + if (c & 0x20) + *p++ |= 0x40; + else + p++; + if (c & 0x10) + *p++ |= 0x40; + else + p++; + if (c & 0x08) + *p++ |= 0x40; + else + p++; + if (c & 0x04) + *p++ |= 0x40; + else + p++; + if (c & 0x02) + *p++ |= 0x40; + else + p++; + if (c & 0x01) + *p++ |= 0x40; + else + p++; + } +} + +/* + * Add R-W-Sub (96 Bytes) to P-Q-Sub (96 Bytes) + * + * OUT: sub, IN: subrwptr + */ +void +addrw(register Uchar *sub, register Uchar *subrwptr) +{ + register int i; + +#define DO8(a) a; a; a; a; a; a; a; a; + + for (i = 0; i < 12; i++) { + DO8(*sub++ |= *subrwptr++ & 0x3F); + } +} + +/* + * Q-W-Sub (96 Bytes) auf 16 Bytes schrumpfen + * + * OUT: subq, IN: subptr + */ +void +qwto16(Uchar *subq, Uchar *subptr) +{ + register int i; + register int np = 0; + register Uchar *p; + Uchar tmp[96]; + + p = subptr; + for (i = 0; i < 96; i++) + if (*p++ & 0x80) + np++; + p = subptr; + if (subptr == subq) { + /* + * Remember 96 byte subchannel data if subchannel + * is overlapping. + */ + movebytes(subptr, tmp, 96); + p = tmp; + } + + for (i = 0; i < 12; i++) { + subq[i] = 0; + if (*p++ & 0x40) + subq[i] |= 0x80; + if (*p++ & 0x40) + subq[i] |= 0x40; + if (*p++ & 0x40) + subq[i] |= 0x20; + if (*p++ & 0x40) + subq[i] |= 0x10; + if (*p++ & 0x40) + subq[i] |= 0x08; + if (*p++ & 0x40) + subq[i] |= 0x04; + if (*p++ & 0x40) + subq[i] |= 0x02; + if (*p++ & 0x40) + subq[i] |= 0x01; + } + subq[12] = 0; + subq[13] = 0; + subq[14] = 0; + if (np > (96/2)) + subq[15] = 0x80; +} + +/* + * Recode subchannels of sectors from 2352 + 96 bytes to 2352 + 16 bytes + */ +void +subrecodesecs(track_t *trackp, Uchar *bp, int address, int nsecs) +{ + bp += 2352; + while (--nsecs >= 0) { + qwto16(bp, bp); + bp += trackp->isecsize; + } +} + +#ifndef HAVE_LIB_EDC_ECC +void +encsectors(track_t *trackp, Uchar *bp, int address, int nsecs) +{ + int sectype = trackp->sectype; + + if ((sectype & ST_MODE_MASK) == ST_MODE_AUDIO) + return; + + comerrno(EX_BAD, "Can only write audio sectors in RAW mode.\n"); +} + +void +scrsectors(track_t *trackp, Uchar *bp, int address, int nsecs) +{ + comerrno(EX_BAD, "Cannot write in clone RAW mode.\n"); +} +#endif + +/*--------------------------------------------------------------------------*/ +#ifdef TEST_CRC + +Uchar tq[12] = { 0x01, 0x00, 0xA0, 0x98, 0x06, 0x12, 0x00, 0x01, 0x00, 0x00, 0xE3, 0x74 }; + +/* +01 00 A0 98 06 12 00 01 00 00 E3 74 +01 00 A0 98 06 13 00 01 00 00 49 25 +01 00 A1 98 06 14 00 13 00 00 44 21 +01 00 A1 98 06 15 00 13 00 00 EE 70 +01 00 A1 98 06 16 00 13 00 00 00 A2 +01 00 A2 98 06 17 00 70 40 73 E3 85 +01 00 A2 98 06 18 00 70 40 73 86 7C +01 00 A2 98 06 19 00 70 40 73 2C 2D +01 00 01 98 06 20 00 00 02 00 3B 71 +01 00 01 98 06 21 00 00 02 00 91 20 +01 00 01 98 06 22 00 00 02 00 7F F2 +01 00 02 98 06 23 00 03 48 45 BE E0 +01 00 02 98 06 24 00 03 48 45 D9 34 + +*/ + +static int b(int bcd); + + +static int +b(int bcd) +{ + return ((bcd & 0x0F) + 10 * (((bcd)>> 4) & 0x0F)); +} + +static void +testcrc() +{ + struct q q; + int ocrc; + int crc1; + int crc2; + + movebytes(&tq, &q, 12); + crc1 = q.crc1 & 0xFF; + crc2 = q.crc2 & 0xFF; + + /* + * Per RED Book, CRC Bits on disk are inverted. + * Invert them again to make calcCRC() work. + */ + q.crc1 ^= 0xFF; + q.crc2 ^= 0xFF; + + ocrc = calcCRC((Uchar *)&q, 12); + printf("AC: %02X t: %3d (%02X) i: %3d (%02X) %d:%d:%d %d:%d:%d %02X%02X %X (%X)\n", + q.ctrl_adr, + b(q.track), + b(q.track) & 0xFF, + b(q.index), + q.index & 0xFF, + b(q.pmin), + b(q.psec), + b(q.pframe), + b(q.amin), + b(q.asec), + b(q.aframe), + crc1, crc2, + ocrc, + fillcrc((Uchar *)&q, 12) & 0xFFFF); +} +#endif /* TEST_CRC */ + +#ifdef sss +96 / 24 = 4 + +index 1 < - > 18 +index 2 < - > 5 +index 3 < - > 23 + +delay index mod 8 +#endif + +/* + * Sub 96 Bytes Interleave + */ +static void +subinterleave(Uchar *sub) +{ + Uchar *p; + int i; + + for (i = 0, p = sub; i < 4; i++) { + Uchar save; + + /* + * index 1 < - > 18 + * index 2 < - > 5 + * index 3 < - > 23 + */ + save = p[1]; + p[1] = p[18]; + p[18] = save; + + save = p[2]; + p[2] = p[5]; + p[5] = save; + + save = p[3]; + p[3] = p[23]; + p[23] = save; + + p += 24; + } +} |