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