1 /*
2 * ProPacker_21.c Copyright (C) 1997 Sylvain "Asle" Chipaux
3 *
4 * Converts PP21 packed MODs back to PTK MODs
5 * thanks to Gryzor and his ProWizard tool ! ... without it, this prog
6 * would not exist !!!
7 *
8 * Modified in 2006,2009,2014 by Claudio Matsuoka
9 * - Code cleanup
10 *
11 * Modified in 2015 by Claudio Matsuoka
12 * - Add PP30 support
13 */
14
15 #include "prowiz.h"
16
17
depack_pp21_pp30(HIO_HANDLE * in,FILE * out,int is_30)18 static int depack_pp21_pp30(HIO_HANDLE *in, FILE *out, int is_30)
19 {
20 uint8 ptable[128];
21 int max = 0;
22 uint8 trk[4][128];
23 int tptr[512][64];
24 uint8 numpat;
25 uint8 *tab;
26 uint8 buf[1024];
27 int i, j;
28 int size;
29 int ssize;
30 int tabsize; /* Reference Table Size */
31
32 memset(ptable, 0, sizeof(ptable));
33 memset(trk, 0, sizeof(trk));
34 memset(tptr, 0, sizeof(tptr));
35
36 pw_write_zero(out, 20); /* title */
37
38 ssize = 0;
39 for (i = 0; i < 31; i++) {
40 pw_write_zero(out, 22); /* sample name */
41 write16b(out, size = hio_read16b(in));
42 ssize += size * 2;
43 write8(out, hio_read8(in)); /* finetune */
44 write8(out, hio_read8(in)); /* volume */
45 write16b(out, hio_read16b(in)); /* loop start */
46 write16b(out, hio_read16b(in)); /* loop size */
47 }
48
49 numpat = hio_read8(in); /* number of patterns */
50
51 /* Sanity check */
52 if (numpat > 128) {
53 return -1;
54 }
55
56 write8(out, numpat); /* number of patterns */
57 write8(out, hio_read8(in)); /* NoiseTracker restart byte */
58
59 max = 0;
60 for (j = 0; j < 4; j++) {
61 for (i = 0; i < 128; i++) {
62 trk[j][i] = hio_read8(in);
63 if (trk[j][i] > max)
64 max = trk[j][i];
65 }
66 }
67
68 /* write pattern table without any optimizing ! */
69 for (i = 0; i < numpat; i++)
70 write8(out, i);
71 pw_write_zero(out, 128 - i);
72
73 write32b(out, PW_MOD_MAGIC); /* M.K. */
74
75 /* PATTERN DATA code starts here */
76
77 /*printf ("Highest track number : %d\n", max); */
78 for (j = 0; j <= max; j++) {
79 for (i = 0; i < 64; i++) {
80 tptr[j][i] = hio_read16b(in);
81 if (is_30) {
82 tptr[j][i] >>= 2;
83 }
84 }
85 }
86
87 /* read "reference table" size */
88 tabsize = hio_read32b(in);
89 if (tabsize == 0) {
90 return -1;
91 }
92
93 /* read "reference Table" */
94 tab = (uint8 *)malloc(tabsize);
95 if (hio_read(tab, tabsize, 1, in) != 1) {
96 free(tab);
97 return -1;
98 }
99
100 for (i = 0; i < numpat; i++) {
101 memset(buf, 0, sizeof(buf));
102 for (j = 0; j < 64; j++) {
103 uint8 *b = buf + j * 16;
104 memcpy(b, tab + tptr[trk[0][i]][j] * 4, 4);
105 memcpy(b + 4, tab + tptr[trk[1][i]][j] * 4, 4);
106 memcpy(b + 8, tab + tptr[trk[2][i]][j] * 4, 4);
107 memcpy(b + 12, tab + tptr[trk[3][i]][j] * 4, 4);
108 }
109 fwrite (buf, 1024, 1, out);
110 }
111
112 free (tab);
113
114 /* Now, it's sample data ... though, VERY quickly handled :) */
115 pw_move_data(out, in, ssize);
116
117 return 0;
118 }
119
depack_pp21(HIO_HANDLE * in,FILE * out)120 static int depack_pp21(HIO_HANDLE *in, FILE *out)
121 {
122 return depack_pp21_pp30(in, out, 0);
123 }
124
depack_pp30(HIO_HANDLE * in,FILE * out)125 static int depack_pp30(HIO_HANDLE *in, FILE *out)
126 {
127 return depack_pp21_pp30(in, out, 1);
128 }
129
test_pp21(const uint8 * data,char * t,int s)130 static int test_pp21(const uint8 *data, char *t, int s)
131 {
132 int i;
133 int ssize, tsize, npat, max_ref;
134
135 PW_REQUEST_DATA(s, 762);
136
137 ssize = 0;
138 for (i = 0; i < 31; i++) {
139 const uint8 *d = data + i * 8;
140 int len = readmem16b(d) << 1;
141 int start = readmem16b(d + 4) << 1;
142
143 ssize += len;
144
145 /* finetune > 0x0f ? */
146 if (d[2] > 0x0f)
147 return -1;
148
149 /* volume > 0x40 ? */
150 if (d[3] > 0x40)
151 return -1;
152
153 /* loop start > size ? */
154 if (start > len)
155 return -1;
156 }
157
158 if (ssize <= 2)
159 return -1;
160
161 /* test #3 about size of pattern list */
162 npat = data[248];
163 if (npat == 0 || npat > 127)
164 return -1;
165
166 /* get the highest track value */
167 tsize = 0;
168 for (i = 0; i < 512; i++) {
169 int trk = data[250 + i];
170 if (trk > tsize)
171 tsize = trk;
172 }
173
174 tsize++;
175 tsize <<= 6;
176
177 PW_REQUEST_DATA(s, tsize * 2 + 4 + 762);
178
179 /* test #4 track data value > $4000 ? */
180 max_ref = 0;
181 for (i = 0; i < tsize; i++) {
182 int ref = readmem16b(data + i * 2 + 762);
183
184 if (ref > 0x4000)
185 return -1;
186
187 if (ref > max_ref)
188 max_ref = ref;
189
190 }
191
192 /* test #5 reference table size *4 ? */
193 if (readmem32b(data + (tsize << 1) + 762) != (max_ref + 1) * 4)
194 return -1;
195
196 pw_read_title(NULL, t, 0);
197
198 return 0;
199 }
200
201
test_pp30(const uint8 * data,char * t,int s)202 static int test_pp30(const uint8 *data, char *t, int s)
203 {
204 int i;
205 int ssize, tsize, npat, max_ref, ref_size;
206
207 PW_REQUEST_DATA(s, 762);
208
209 ssize = 0;
210 for (i = 0; i < 31; i++) {
211 const uint8 *d = data + i * 8;
212 int len = readmem16b(d) << 1;
213 int start = readmem16b(d + 4) << 1;
214
215 ssize += len;
216
217 /* finetune > 0x0f ? */
218 if (d[2] > 0x0f)
219 return -1;
220
221 /* volume > 0x40 ? */
222 if (d[3] > 0x40)
223 return -1;
224
225 /* loop start > size ? */
226 if (start > len)
227 return -1;
228 }
229
230 if (ssize <= 2)
231 return -1;
232
233 /* test #3 about size of pattern list */
234 npat = data[248];
235 if (npat == 0 || npat > 127)
236 return -1;
237
238 /* get the highest track value */
239 tsize = 0;
240 for (i = 0; i < 512; i++) {
241 int trk = data[250 + i];
242 if (trk > tsize)
243 tsize = trk;
244 }
245
246 tsize++;
247 tsize <<= 6;
248
249 PW_REQUEST_DATA(s, (tsize * 2) + 4 + 762);
250
251 /* test #4 track data value *4 ? */
252 max_ref = 0;
253 for (i = 0; i < tsize; i++) {
254 int ref = readmem16b(data + i * 2 + 762);
255
256 if (ref > max_ref)
257 max_ref = ref;
258
259 if (ref & 0x0003) {
260 return -1;
261 }
262 }
263 max_ref >>= 2;
264
265 /* test #5 reference table size *4 ? */
266 ref_size = readmem32b(data + (tsize << 1) + 762);
267
268 if (ref_size > 0xffff) {
269 return -1;
270 }
271
272 if (ref_size != ((max_ref + 1) << 2)) {
273 return -1;
274 }
275
276 ref_size >>= 2;
277
278 PW_REQUEST_DATA(s, (ref_size * 4) + (tsize * 2) + 4 + 762);
279
280 /* test #6 data in reference table ... */
281 for (i = 0; i < ref_size; i++) {
282 const uint8 *d = data + (tsize * 2) + 766 + i * 4;
283 uint8 fxt = d[2] & 0x0f;
284 uint8 fxp = d[3];
285
286 /* volume > 41 ? */
287 if (fxt == 0x0c && fxp > 0x41) {
288 return -1;
289 }
290
291 /* break > 64 (packed decimal) ? */
292 if (fxt == 0x0d && (fxp > 0x64 || (fxp & 0xf) > 9)) {
293 return -1;
294 }
295
296 /* jump > 128 */
297 if (fxt == 0x0b && fxp > 0x7f) {
298 return -1;
299 }
300
301 /* smp > 1f ? */
302 if ((d[0] & 0xf0) > 0x10) {
303 return -1;
304 }
305 }
306
307 pw_read_title(NULL, t, 0);
308
309 return 0;
310 }
311
312 const struct pw_format pw_pp21 = {
313 "ProPacker 2.1",
314 test_pp21,
315 depack_pp21
316 };
317
318 const struct pw_format pw_pp30 = {
319 "ProPacker 3.0",
320 test_pp30,
321 depack_pp30
322 };
323