1 /* OpenCP Module Player
2  * copyright (c) '94-'10 Niklas Beisert <nbeisert@physik.tu-muenchen.de>
3  *
4  * ITPlay Instrument display code
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
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; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  *
20  * revision history: (please note changes here)
21  *  -nb980510   Niklas Beisert <nbeisert@physik.tu-muenchen.de>
22  *    -first release
main(int,char **)23  *  -kb980717   Tammo Hinrichs <opencp@gmx.net>
24  *    -changed some minor things for better output
25  */
26 
27 #include "config.h"
28 #include <stdlib.h>
29 #include <string.h>
30 #include "types.h"
31 #include "dev/mcp.h"
32 #include "stuff/poutput.h"
33 #include "cpiface/cpiface.h"
34 #include "itplay.h"
35 
36 static int instnum;
37 static int sampnum;
38 static uint8_t *plInstUsed = NULL;
39 static uint8_t *plSampUsed = NULL;
40 static uint8_t *plBigInstNum = NULL;
41 static uint16_t *plBigSampNum = NULL;
42 
43 /* extern uint8_t plNoteStr[132][4];  cpiface.h */
44 
45 static const struct it_instrument *plInstr;
46 static const struct it_sampleinfo *plSamples;
47 static const struct it_sample *plModSamples;
48 
49 static uint8_t plInstShowFreq;
50 
51 static void itDisplayIns40(uint16_t *buf, int n, int plInstMode)
52 {
53 	char col=plInstMode?0x07:"\x08\x08\x0B\x0A"[plInstUsed[n]];
54 	writestring(buf, 0, col, (!plInstMode&&plInstUsed[n])?"\xfe##: ":" ##: ", 5);
55 	writenum(buf, 1, col, n+1, 16, 2, 0);
56 	writestring(buf, 5, col, plInstr[n].name, 35);
57 }
58 
59 static void itDisplayIns33(uint16_t *buf, int n, int plInstMode)
60 {
61 	char col=plInstMode?0x07:"\x08\x08\x0B\x0A"[plInstUsed[n]];
62 	writestring(buf, 0, col, (!plInstMode&&plInstUsed[n])?"\xfe##: ":" ##: ", 5);
63 	writenum(buf, 1, col, n+1, 16, 2, 0);
64 	writestring(buf, 5, col, plInstr[n].name, 28);
65 }
66 
67 static void itDisplayIns52(uint16_t *buf, int n, int plInstMode)
68 {
69 	char col=plInstMode?0x07:"\x08\x08\x0B\x0A"[plInstUsed[n]];
70 	writestring(buf, 0, col, (!plInstMode&&plInstUsed[n])?"    \xfe##: ":"     ##: ", 9);
71 	writenum(buf, 5, col, n+1, 16, 2, 0);
72 	writestring(buf, 9, col, plInstr[n].name, 43);
73 }
74 
75 static void itDisplayIns80(uint16_t *buf, int n, int plInstMode)
76 {
77 	char col;
78 	writestring(buf, 0, 0, "", 80);
79 
80 	if (plBigInstNum[n]!=0xFF)
81 	{
82 		const struct it_instrument *ins=&plInstr[plBigInstNum[n]];
83 		col=plInstMode?0x07:"\x08\x08\x0B\x0A"[plInstUsed[plBigInstNum[n]]];
84 		writestring(buf, 0, col, (!plInstMode&&plInstUsed[plBigInstNum[n]])?"\xfe##: ":" ##: ", 5);
85 		writenum(buf, 1, col, plBigInstNum[n]+1, 16, 2, 0);
86 		writestring(buf, 5, col, ins->name, 31);
87 	}
88 
89 	if (plBigSampNum[n]!=0xFFFF)
90 	{
91 		const struct it_sample *sm=&plModSamples[plBigSampNum[n]];
92 		const struct it_sampleinfo *si=&plSamples[sm->handle];
93 
94 		col=plInstMode?0x07:"\x08\x08\x0B\x0A"[plSampUsed[plBigSampNum[n]]];
95 		writestring(buf, 34, col, (!plInstMode&&plSampUsed[plBigSampNum[n]])?"\xfe###: ":" ###: ", 6);
96 		writenum(buf, 35, col, plBigSampNum[n], 16, 3, 0);
97 		if (si->type&mcpSampLoop)
98 		{
99 			_writenum(buf, 40, col, si->loopend, 10, 6);
100 			_writenum(buf, 47, col, si->loopend-si->loopstart, 10, 6);
101 			if (si->type&mcpSampBiDi)
102 				writestring(buf, 53, col, "\x1D", 1);
103 		} else {
104 			_writenum(buf, 40, col, si->length, 10, 6);
105 			writestring(buf, 52, col, "-", 1);
106 		}
107 		writestring(buf, 55, col, (si->type&mcpSamp16Bit)?"16":" 8", 2);
108 		writestring(buf, 57, col, (si->type&mcpSampRedRate4)?"\xac":(si->type&mcpSampRedRate2)?"\xab":(si->type&mcpSampRedBits)?"!":" ", 2);
109 
110 		if (!plInstShowFreq)
111 		{
112 			writestring(buf, 60, col, plNoteStr[(sm->normnote+60*256)>>8], 3);
113 			writenum(buf, 64, col, sm->normnote&0xFF, 16, 2, 0);
114 		} else
115 			if (plInstShowFreq==1)
116 				writenum(buf, 60, col, mcpGetFreq8363(-sm->normnote), 10, 6, 1);
117 			else
118 				writenum(buf, 60, col, si->samprate, 10, 6, 1);
119 
120 		writenum(buf, 68, col, sm->vol, 16, 2, 0);
121 /*
122 		if (ins->stdpan!=-1)
123 				writenum(buf, 72, col, ins->stdpan, 16, 2, 0);
124 			else
125 				writestring(buf, 72, col, " -", 2);
126 		if (ins->volenv!=0xFFFF)
127 			writestring(buf, 76, col, "v", 1);
128 		if (ins->panenv!=0xFFFF)
129 			writestring(buf, 77, col, "p", 1);
130 		if (ins->vibdepth&&sm.vibrate)
131 			writestring(buf, 78, col, "~", 1);
132 		if (ins->fadeout)
133 			writestring(buf, 79, col, "\x19", 1);
134 */
135 	}
136 }
137 
138 static void itDisplayIns132(uint16_t *buf, int n, int plInstMode)
139 {
140 	char col;
141 	writestring(buf, 0, 0, "", 132);
142 
143 	if (plBigInstNum[n]!=0xFF)
144 	{
145 		const struct it_instrument *ins=&plInstr[plBigInstNum[n]];
146 		col=plInstMode?0x07:"\x08\x08\x0B\x0A"[plInstUsed[plBigInstNum[n]]];
147 		writestring(buf, 0, col, (!plInstMode&&plInstUsed[plBigInstNum[n]])?"\xfe##: ":" ##: ", 5);
148 		writenum(buf, 1, col, plBigInstNum[n]+1, 16, 2, 0);
149 		writestring(buf, 5, col, ins->name, 35);
150 	}
151 
152 	if (plBigSampNum[n]!=0xFFFF)
153 	{
154 		const struct it_sample *sm=&plModSamples[plBigSampNum[n]];
155 		const struct it_sampleinfo *si=&plSamples[sm->handle];
156 
157 		col=plInstMode?0x07:"\x08\x08\x0B\x0A"[plSampUsed[plBigSampNum[n]]];
158 		writestring(buf, 34, col, (!plInstMode&&plSampUsed[plBigSampNum[n]])?"\xfe###: ":" ###: ", 6);
159 		writenum(buf, 35, col, plBigSampNum[n], 16, 3, 0);
160 		writestring(buf, 40, col, sm->name, 28);
161 		if (si->type&mcpSampLoop)
162 		{
163 			_writenum(buf, 70, col, si->loopend, 10, 6);
164 			_writenum(buf, 77, col, si->loopend-si->loopstart, 10, 6);
165 			if (si->type&mcpSampBiDi)
166 				writestring(buf, 83, col, "\x1D", 1);
167 		} else {
168 			_writenum(buf, 70, col, si->length, 10, 6);
169 			writestring(buf, 82, col, "-", 1);
170 		}
171 		writestring(buf, 85, col, (si->type&mcpSamp16Bit)?"16":" 8", 2);
172 		writestring(buf, 87, col, (si->type&mcpSampRedRate4)?"\xac":(si->type&mcpSampRedRate2)?"\xab":(si->type&mcpSampRedBits)?"!":" ", 2);
173 
174 		if (!plInstShowFreq)
175 		{
176 			writestring(buf, 90, col, plNoteStr[(sm->normnote+60*256)>>8], 3);
177 			writenum(buf, 94, col, sm->normnote&0xFF, 16, 2, 0);
178 		} else if (plInstShowFreq==1)
179 			writenum(buf, 90, col, mcpGetFreq8363(-sm->normnote), 10, 6, 1);
180 		else
181 			writenum(buf, 90, col, si->samprate, 10, 6, 1);
182 
183 		writenum(buf, 98, col, sm->vol, 16, 2, 0);
184 /*
185 		if (ins->stdpan!=-1)
186 			writenum(buf, 102, col, ins->stdpan, 16, 2, 0);
187 		else
188 			writestring(buf, 102, col, " -", 2);
189 
190 		if (ins->volenv!=0xFFFF)
191 			writestring(buf, 106, col, "v", 1);
192 		if (ins->panenv!=0xFFFF)
193 			writestring(buf, 107, col, "p", 1);
194 		if (ins->vibdepth&&ins->vibrate)
195 			writestring(buf, 108, col, "~", 1);
196 
197 		if (ins->fadeout)
198 			writenum(buf, 110, col, ins->fadeout, 16, 4, 1);
199 		else
200 			writestring(buf, 113, col, "-", 1);
201  */
202 	}
203 }
204 
205 static void itDisplayIns(uint16_t *buf, int len, int n, int plInstMode)
206 {
207 	switch (len)
208 	{
209 		case 33:
210 			itDisplayIns33(buf, n, plInstMode);
211 			break;
212 		case 40:
213 			itDisplayIns40(buf, n, plInstMode);
214 			break;
215 		case 52:
216 			itDisplayIns52(buf, n, plInstMode);
217 			break;
218 		case 80:
219 			itDisplayIns80(buf, n, plInstMode);
220 			break;
221 		case 132:
222 			itDisplayIns132(buf, n, plInstMode);
223 			break;
224 	}
225 }
226 
227 static void (*Mark)(uint8_t *, uint8_t *);
228 
229 static void itMark(void)
230 {
231 	int i;
232 	for (i=0; i<instnum; i++)
233 		if (plInstUsed[i])
234 			plInstUsed[i]=1;
235 	for (i=0; i<sampnum; i++)
236 		if (plSampUsed[i])
237 			plSampUsed[i]=1;
238 	Mark(plInstUsed, plSampUsed);
239 }
240 
241 static void itpInstClear(void)
242 {
243 	memset(plInstUsed, 0, instnum);
244 	memset(plSampUsed, 0, sampnum);
245 }
246 
247 static void Done(void)
248 {
249 	if (plInstUsed)
250 	{
251 		free(plInstUsed);
252 		plInstUsed=NULL;
253 	}
254 	if (plSampUsed)
255 	{
256 		free(plSampUsed);
257 		plSampUsed=NULL;
258 	}
259 	if (plBigInstNum)
260 	{
261 		free(plBigInstNum);
262 		plBigInstNum=NULL;
263 	}
264 	if (plBigSampNum)
265 	{
266 		free(plBigSampNum);
267 		plBigSampNum=NULL;
268 	}
269 }
270 
271 void __attribute__ ((visibility ("internal"))) itpInstSetup(const struct it_instrument *ins, int nins, const struct it_sample *smp, int nsmp, const struct it_sampleinfo *smpi, /*int unused,*/ int type, void (*MarkyBoy)(uint8_t *, uint8_t *))
272 {
273 	int i,j;
274 	int biginstlen=0;
275 	struct insdisplaystruct plInsDisplay;
276 
277 	instnum=nins;
278 	sampnum=nsmp;
279 
280 	plSampUsed=malloc(sizeof(uint8_t)*sampnum);
281 	plInstUsed=malloc(sizeof(uint8_t)*instnum);
282 	if (!plSampUsed||!plInstUsed)
283 		return;
284 
285 	itpInstClear();
286 
287 	Mark=MarkyBoy;
288 
289 	plInstr=ins;
290 	plModSamples=smp;
291 	plSamples=smpi;
292 
293 	for (i=0; i<instnum; i++)
294 	{
295 		const struct it_instrument *ins=&plInstr[i];
296 		int num=0;
297 
298 		for (j=0; j<IT_KEYTABS; j++)
299 			if (ins->keytab[j][1]&&(ins->keytab[j][1]<=sampnum))
300 				if (plModSamples[ins->keytab[j][1]-1].handle<nsmp)
301 					plSampUsed[ins->keytab[j][1]-1]=1;
302 		for (j=0; j<sampnum; j++)
303 			if (plSampUsed[j])
304 				num++;
305 		biginstlen+=num?num:1;
306 	}
307 	plBigInstNum=malloc(sizeof(uint8_t)*biginstlen);
308 	plBigSampNum=malloc(sizeof(uint16_t)*biginstlen);
309 	if (!plBigInstNum||!plBigSampNum)
310 		return;
311 	memset(plBigInstNum, -1, biginstlen);
312 	memset(plBigSampNum, -1, biginstlen*2);
313 
314 	biginstlen=0;
315 	for (i=0; i<instnum; i++)
316 	{
317 		const struct it_instrument *ins=&plInstr[i];
318 		int num=0;
319 
320 		memset(plSampUsed, 0, sampnum);
321 
322 		for (j=0; j<IT_KEYTABS; j++)
323 			if (ins->keytab[j][1]&&(ins->keytab[j][1]<=sampnum))
324 				if (plModSamples[ins->keytab[j][1]-1].handle<nsmp)
325 					plSampUsed[ins->keytab[j][1]-1]=1;
326 
327 		plBigInstNum[biginstlen]=i;
328 		for (j=0; j<sampnum; j++)
329 			if (plSampUsed[j])
330 				plBigSampNum[biginstlen+num++]=j;
331 
332 		biginstlen+=num?num:1;
333 	}
334 
335 	plInstShowFreq=type;
336 	plInsDisplay.Clear=itpInstClear;
337 /*
338 	plInsDisplay.n40=instnum;
339 	plInsDisplay.n52=instnum;
340 	plInsDisplay.n80=biginstlen;
341 */
342 	plInsDisplay.height=instnum;
343 	plInsDisplay.bigheight=biginstlen;
344 	plInsDisplay.title80=plInstShowFreq?
345                          " ##   instrument name / song message    length replen bit samprate vol pan  flgs":
346                          " ##   instrument name / song message    length replen bit  base ft vol pan  flgs";
347 	plInsDisplay.title132=plInstShowFreq?
348                           " ##   instrument name / song message       sample name                length replen bit samprate vol pan  fl  fade           ":
349                           " ##   instrument name / song message       sample name                length replen bit  base ft vol pan  fl  fade           ";
350 
351 	plInsDisplay.Mark=itMark;
352 	plInsDisplay.Display=itDisplayIns;
353 	plInsDisplay.Done=Done;
354 	itpInstClear();
355 	plUseInstruments(&plInsDisplay);
356 }
357