1 /*
2     Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org>
3     Copyright 1998-2002 by Heiko Eissfeldt <heiko@colossus.escape.de>
4     Copyright 2002 by Joerg Schilling
5                   portions used & Chris Smith
6 
7     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License version 2
9     as published by the Free Software Foundation.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; see the file COPYING.  If not, write to
18     the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
19     MA 02111-1307, USA.  */
20 
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
24 
25 #include <string.h>
26 
27 #include <cdio/cdio.h>
28 #include <cdio/bytesex.h>
29 
30 #include <libvcd/types.h>
31 
32 #include <libvcd/sector.h>
33 
34 /* Private includes */
35 #include "vcd_assert.h"
36 #include "salloc.h"
37 #include "sector_private.h"
38 
39 static const uint8_t sync_pattern[12] = {
40   0x00, 0xff, 0xff, 0xff,
41   0xff, 0xff, 0xff, 0xff,
42   0xff, 0xff, 0xff, 0x00
43 };
44 
45 static void
build_address(void * buf,sectortype_t sectortype,uint32_t address)46 build_address (void *buf, sectortype_t sectortype, uint32_t address)
47 {
48   raw_cd_sector_t *sector = buf;
49 
50   vcd_assert (sizeof(raw_cd_sector_t) == CDIO_CD_FRAMESIZE_RAW-DATA_LEN);
51 
52   cdio_lba_to_msf(address, &(sector->msf));
53 
54   switch(sectortype) {
55   case MODE_0:
56     sector->mode = 0;
57     break;
58   case MODE_2:
59   case MODE_2_FORM_1:
60   case MODE_2_FORM_2:
61     sector->mode = 2;
62     break;
63   default:
64     vcd_assert_not_reached ();
65     break;
66   }
67 }
68 
69 /* From cdrtools-1.11a25 */
70 static uint32_t
build_edc(const uint8_t inout[],int from,int upto)71 build_edc(const uint8_t inout[], int from, int upto)
72 {
73   const uint8_t *p = inout+from;
74   uint32_t result = 0;
75 
76   upto -= from-1;
77   upto /= 4;
78   while (--upto >= 0) {
79     result = EDC_crctable[(result ^ *p++) & 0xffL] ^ (result >> 8);
80     result = EDC_crctable[(result ^ *p++) & 0xffL] ^ (result >> 8);
81     result = EDC_crctable[(result ^ *p++) & 0xffL] ^ (result >> 8);
82     result = EDC_crctable[(result ^ *p++) & 0xffL] ^ (result >> 8);
83   }
84   return (result);
85 }
86 
87 /* From cdrtools-1.11a40 */
88 static void
encode_L2_Q(uint8_t inout[4+L2_RAW+4+8+L2_P+L2_Q])89 encode_L2_Q(uint8_t inout[4 + L2_RAW + 4 + 8 + L2_P + L2_Q])
90 {
91   uint8_t *dps;
92   uint8_t *dp;
93   uint8_t *Q;
94   int i, j;
95 
96   Q = inout + 4 + L2_RAW + 4 + 8 + L2_P;
97 
98   dps = inout;
99   for (j = 0; j < 26; j++) {
100     uint16_t a, b;
101 
102     a = b = 0;
103     dp = dps;
104     for (i = 0; i < 43; i++) {
105 
106       /* LSB */
107       a ^= L2sq[i][*dp++];
108 
109       /* MSB */
110       b ^= L2sq[i][*dp];
111 
112       dp += 2*44-1;
113       if (dp >= &inout[(4 + L2_RAW + 4 + 8 + L2_P)]) {
114         dp -= (4 + L2_RAW + 4 + 8 + L2_P);
115       }
116     }
117     Q[0]      = a >> 8;
118     Q[26*2]   = a;
119     Q[1]      = b >> 8;
120     Q[26*2+1] = b;
121 
122     Q += 2;
123     dps += 2*43;
124   }
125 }
126 
127 static void
encode_L2_P(uint8_t inout[4+L2_RAW+4+8+L2_P])128 encode_L2_P (uint8_t inout[4 + L2_RAW + 4 + 8 + L2_P])
129 {
130   uint8_t *dp;
131   unsigned char *P;
132   int i, j;
133 
134   P = inout + 4 + L2_RAW + 4 + 8;
135 
136   for (j = 0; j < 43; j++) {
137     uint16_t a;
138     uint16_t b;
139 
140     a = b = 0;
141     dp = inout;
142     for (i = 19; i < 43; i++) {
143 
144       /* LSB */
145       a ^= L2sq[i][*dp++];
146 
147       /* MSB */
148       b ^= L2sq[i][*dp];
149 
150       dp += 2*43 -1;
151     }
152     P[0]      = a >> 8;
153     P[43*2]   = a;
154     P[1]      = b >> 8;
155     P[43*2+1] = b;
156 
157     P += 2;
158     inout += 2;
159   }
160 }
161 
162 /* Layer 2 Product code en/decoder */
163 static void
do_encode_L2(void * buf,sectortype_t sectortype,uint32_t address)164 do_encode_L2 (void *buf, sectortype_t sectortype, uint32_t address)
165 {
166   raw_cd_sector_t *raw_sector = buf;
167 
168   vcd_assert (buf != NULL);
169 
170   vcd_assert (sizeof (sync_pattern) == SYNC_LEN);
171   vcd_assert (sizeof (mode2_form1_sector_t) == CDIO_CD_FRAMESIZE_RAW);
172   vcd_assert (sizeof (mode2_form2_sector_t) == CDIO_CD_FRAMESIZE_RAW);
173   vcd_assert (sizeof (mode0_sector_t) == CDIO_CD_FRAMESIZE_RAW);
174   vcd_assert (sizeof (raw_cd_sector_t) == SYNC_LEN+HEADER_LEN);
175 
176   memset (raw_sector, 0, SYNC_LEN+HEADER_LEN);
177   memcpy (raw_sector->sync, sync_pattern, sizeof (sync_pattern));
178 
179   switch (sectortype) {
180   case MODE_0:
181     {
182       mode0_sector_t *sector = buf;
183 
184       memset(sector->data, 0, sizeof(sector->data));
185     }
186     break;
187   case MODE_2:
188     break;
189   case MODE_2_FORM_1:
190     {
191       mode2_form1_sector_t *sector = buf;
192 
193       sector->edc = uint32_to_le(build_edc(buf, 16, 16+8+2048-1));
194 
195       encode_L2_P((uint8_t*)buf+SYNC_LEN);
196       encode_L2_Q((uint8_t*)buf+SYNC_LEN);
197     }
198     break;
199   case MODE_2_FORM_2:
200     {
201       mode2_form2_sector_t *sector = buf;
202 
203       sector->edc = uint32_to_le(build_edc(buf, 16, 16+8+2324-1));
204     }
205     break;
206   default:
207     vcd_assert_not_reached ();
208   }
209 
210   build_address (buf, sectortype, address);
211 }
212 
213 void
_vcd_make_mode2(void * raw_sector,const void * data,uint32_t extent,uint8_t fnum,uint8_t cnum,uint8_t sm,uint8_t ci)214 _vcd_make_mode2 (void *raw_sector, const void *data, uint32_t extent,
215                  uint8_t fnum, uint8_t cnum, uint8_t sm, uint8_t ci)
216 {
217   uint8_t *subhdr = (uint8_t*)raw_sector+16;
218 
219   vcd_assert (raw_sector != NULL);
220   vcd_assert (data != NULL);
221   vcd_assert (extent != SECTOR_NIL);
222 
223   memset (raw_sector, 0, CDIO_CD_FRAMESIZE_RAW);
224 
225   subhdr[0] = subhdr[4] = fnum;
226   subhdr[1] = subhdr[5] = cnum;
227   subhdr[2] = subhdr[6] = sm;
228   subhdr[3] = subhdr[7] = ci;
229 
230   if (sm & SM_FORM2)
231     {
232       memcpy ((char*)raw_sector+CDIO_CD_XA_SYNC_HEADER, data,
233               M2F2_SECTOR_SIZE);
234       do_encode_L2 (raw_sector, MODE_2_FORM_2, extent+CDIO_PREGAP_SECTORS);
235     }
236   else
237     {
238       memcpy ((char*)raw_sector+CDIO_CD_XA_SYNC_HEADER, data,
239               CDIO_CD_FRAMESIZE);
240       do_encode_L2 (raw_sector, MODE_2_FORM_1, extent+CDIO_PREGAP_SECTORS);
241     }
242 }
243 
244 void
_vcd_make_raw_mode2(void * raw_sector,const void * data,uint32_t extent)245 _vcd_make_raw_mode2 (void *raw_sector, const void *data, uint32_t extent)
246 {
247   vcd_assert (raw_sector != NULL);
248   vcd_assert (data != NULL);
249   vcd_assert (extent != SECTOR_NIL);
250 
251   memset (raw_sector, 0, CDIO_CD_FRAMESIZE_RAW);
252 
253   memcpy ((char*)raw_sector+12+4, data, M2RAW_SECTOR_SIZE);
254   do_encode_L2 (raw_sector, MODE_2, extent+CDIO_PREGAP_SECTORS);
255 }
256 
257 
258 /*
259  * Local variables:
260  *  c-file-style: "gnu"
261  *  tab-width: 8
262  *  indent-tabs-mode: nil
263  * End:
264  */
265