1 /*
2 * NoisePacker_v3.c Copyright (C) 1998 Asle / ReDoX
3 *
4 * Converts NoisePacked MODs back to ptk
5 * Last revision : 26/11/1999 by Sylvain "Asle" Chipaux
6 * reduced to only one FREAD.
7 * Speed-up and Binary smaller.
8 *
9 * Modified in 2006,2007,2014,2015 by Claudio Matsuoka
10 */
11
12 #include "prowiz.h"
13
14
depack_np3(HIO_HANDLE * in,FILE * out)15 static int depack_np3(HIO_HANDLE *in, FILE *out)
16 {
17 uint8 tmp[1024];
18 uint8 c1, c2, c3, c4;
19 uint8 ptable[128];
20 int len, nins, npat;
21 int max_addr, smp_addr;
22 int size, ssize = 0;
23 /*int tsize;*/
24 int trk_addr[128][4];
25 int i, j, k;
26 int trk_start;
27
28 memset(ptable, 0, sizeof(ptable));
29 memset(trk_addr, 0, sizeof(trk_addr));
30
31 c1 = hio_read8(in); /* read number of samples */
32 c2 = hio_read8(in);
33 nins = ((c1 << 4) & 0xf0) | ((c2 >> 4) & 0x0f);
34
35 pw_write_zero(out, 20); /* write title */
36
37 len = hio_read16b(in) >> 1; /* size of pattern list */
38 if (len > 128) {
39 return -1;
40 }
41 hio_read16b(in); /* 2 unknown bytes */
42 /*tsize =*/ hio_read16b(in); /* read track data size */
43
44 /* read sample descriptions */
45 for (i = 0; i < nins; i++) {
46 hio_read(tmp, 1, 16, in);
47 pw_write_zero(out, 22); /* sample name */
48 write16b(out, size = readmem16b(tmp + 6));
49 ssize += size * 2;
50 write8(out, tmp[0]); /* write finetune */
51 write8(out, tmp[1]); /* write volume */
52 fwrite(tmp + 14, 2, 1, out); /* write loop start */
53 fwrite(tmp + 12, 2, 1, out); /* write loop size */
54 }
55
56 /* fill up to 31 samples */
57 memset(tmp, 0, 30);
58 tmp[29] = 0x01;
59 for (; i < 31; i++)
60 fwrite(tmp, 30, 1, out);
61
62 write8(out, len); /* write size of pattern list */
63 write8(out, 0x7f); /* write noisetracker byte */
64
65 hio_seek(in, 2, SEEK_CUR); /* always $02? */
66 hio_seek(in, 2, SEEK_CUR); /* unknown */
67
68 /* read pattern table */
69 npat = 0;
70 for (i = 0; i < len; i++) {
71 ptable[i] = hio_read16b(in) / 8;
72 if (ptable[i] > npat)
73 npat = ptable[i];
74 }
75 npat++;
76
77 fwrite(ptable, 128, 1, out); /* write pattern table */
78 write32b(out, PW_MOD_MAGIC); /* write ptk ID */
79
80 /* read tracks addresses per pattern */
81 for (max_addr = i = 0; i < npat; i++) {
82 if ((trk_addr[i][0] = hio_read16b(in)) > max_addr)
83 max_addr = trk_addr[i][0];
84 if ((trk_addr[i][1] = hio_read16b(in)) > max_addr)
85 max_addr = trk_addr[i][1];
86 if ((trk_addr[i][2] = hio_read16b(in)) > max_addr)
87 max_addr = trk_addr[i][2];
88 if ((trk_addr[i][3] = hio_read16b(in)) > max_addr)
89 max_addr = trk_addr[i][3];
90 }
91 trk_start = hio_tell(in);
92
93 /* the track data now ... */
94 smp_addr = 0;
95 for (i = 0; i < npat; i++) {
96 memset(tmp, 0, sizeof(tmp));
97 for (j = 0; j < 4; j++) {
98 int x;
99
100 hio_seek(in, trk_start + trk_addr[i][3 - j], SEEK_SET);
101 for (k = 0; k < 64; k++) {
102 int x = k * 16 + j * 4;
103
104 if ((c1 = hio_read8(in)) >= 0x80) {
105 k += (0x100 - c1) - 1;
106 continue;
107 }
108 c2 = hio_read8(in);
109 c3 = hio_read8(in);
110 c4 = (c1 & 0xfe) / 2;
111
112 if (hio_error(in) || !PTK_IS_VALID_NOTE(c4)) {
113 return -1;
114 }
115
116 tmp[x] = ((c1 << 4) & 0x10) | ptk_table[c4][0];
117 tmp[x + 1] = ptk_table[c4][1];
118
119 switch (c2 & 0x0f) {
120 case 0x08:
121 c2 &= 0xf0;
122 break;
123 case 0x07:
124 c2 = (c2 & 0xf0) + 0x0a;
125 /* fall through */
126 case 0x06:
127 case 0x05:
128 c3 = c3 > 0x80 ? 0x100 - c3 :
129 (c3 << 4) & 0xf0;
130 break;
131 case 0x0e:
132 c3 = 1;
133 break;
134 case 0x0b:
135 c3 = (c3 + 4) / 2;
136 break;
137 }
138
139 tmp[x + 2] = c2;
140 tmp[x + 3] = c3;
141
142 if ((c2 & 0x0f) == 0x0d)
143 break;
144 }
145
146 x = hio_tell(in);
147 if (x < 0) {
148 return -1;
149 }
150 if (x > smp_addr) {
151 smp_addr = x;
152 }
153 }
154 fwrite(tmp, 1024, 1, out);
155 }
156
157 /* sample data */
158 if (smp_addr & 1)
159 smp_addr++;
160 hio_seek(in, smp_addr, SEEK_SET);
161 pw_move_data(out, in, ssize);
162
163 return 0;
164 }
165
test_np3(const uint8 * data,char * t,int s)166 static int test_np3(const uint8 *data, char *t, int s)
167 {
168 int num_ins, ssize, hdr_size, ptab_size, trk_size, max_pptr;
169 int i;
170
171 PW_REQUEST_DATA(s, 10);
172
173 /* size of the pattern table */
174 ptab_size = readmem16b(data + 2);
175 if (ptab_size == 0 || ptab_size & 0x01 || ptab_size > 0xff)
176 return -1;
177
178 /* test number of samples */
179 if ((data[1] & 0x0f) != 0x0c)
180 return -1;
181
182 num_ins = ((data[0] << 4) & 0xf0) | ((data[1] >> 4) & 0x0f);
183 if (num_ins == 0 || num_ins > 0x1f)
184 return -1;
185
186 PW_REQUEST_DATA(s, 15 + num_ins * 16);
187
188 /* test volumes */
189 for (i = 0; i < num_ins; i++) {
190 if (data[9 + i * 16] > 0x40)
191 return -1;
192 }
193
194 /* test sample sizes */
195 ssize = 0;
196 for (i = 0; i < num_ins; i++) {
197 const uint8 *d = data + i * 16;
198 int len = readmem16b(d + 14) << 1;
199 int start = readmem16b(d + 20) << 1;
200 int lsize = readmem16b(d + 22) << 1;
201
202 if (len > 0xffff || start > 0xffff || lsize > 0xffff)
203 return -1;
204
205 if (start + lsize > len + 2)
206 return -1;
207
208 if (start == 0 && lsize != 0)
209 return -1;
210
211 ssize += len;
212 }
213
214 if (ssize <= 4)
215 return -1;
216
217 /* size of the header 'til the end of sample descriptions */
218 hdr_size = num_ins * 16 + 8 + 4;
219
220 PW_REQUEST_DATA(s, hdr_size + ptab_size + 2);
221
222 /* test pattern table */
223 max_pptr = 0;
224 for (i = 0; i < ptab_size; i += 2) {
225 int pptr = readmem16b(data + hdr_size + i);
226 if (pptr & 0x07 || pptr >= 0x400)
227 return -1;
228 if (pptr > max_pptr)
229 max_pptr = pptr;
230 }
231
232 /* max_pptr is the highest pattern number (*8) */
233
234 /* paske on a que l'address du dernier pattern .. */
235 /* size of the header 'til the end of the track list */
236 hdr_size += ptab_size + max_pptr + 8;
237
238 /* test track data size */
239 trk_size = readmem16b(data + 6);
240 if (trk_size <= 63)
241 return -1;
242
243 PW_REQUEST_DATA(s, hdr_size + trk_size + 2);
244
245 /* test notes */
246 /* re-calculate the number of sample */
247 for (i = 0; i < trk_size ; i++) {
248 const uint8 *d = data + hdr_size + i;
249
250 if (d[0] & 0x80)
251 continue;
252
253 /* si note trop grande et si effet = A */
254 if (d[0] > 0x49 || (d[1] & 0x0f) == 0x0a)
255 return -1;
256
257 /* si effet D et arg > 0x40 */
258 if ((d[1] & 0x0f) == 0x0d && d[2] > 0x40)
259 return -1;
260
261 /* sample nbr > ce qui est defini au debut ? */
262 if ((((d[0] << 4) & 0x10) | ((d[1] >> 4) & 0x0f)) > num_ins)
263 return -1;
264
265 /* all is empty ?!? ... cannot be ! */
266 if (d[0] == 0 && d[1] == 0 && d[2] == 0 && i < (trk_size - 3))
267 return -1;
268
269 i += 2;
270 }
271
272 pw_read_title(NULL, t, 0);
273
274 return 0;
275 }
276
277 const struct pw_format pw_np3 = {
278 "NoisePacker v3",
279 test_np3,
280 depack_np3
281 };
282