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