1 /*
2 music.c
3
4 Copyright (C) 1986 Eckhard Kruse
5 Copyright (C) 2011 Thomas Huth
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 as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 /*********************************************************************
22 * Abspielen von Musik-Editor St�cken *
23 * *
24 * Gleich einmal vorweg wie ein Programm aussieht, das die hier *
25 * definierten Routinen verwendet: *
26 * *
27 * extern void m_laden(), m_musik(), m_wloop(); *
28 * main() *
29 * { *
30 * int save_ssp; *
31 * m_laden("DATEI.MUS"); Datei laden *
32 * m_musik(); Musik abspielen *
33 * } *
34 * int m_wait() Warteschleife *
35 * { *
36 * m_wloop(); *
37 * return 0; return 1 um abzubrechen *
38 * } *
39 *********************************************************************/
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <SDL.h>
44 #include <SDL_endian.h>
45 #include "psg.h"
46 #include "music.h"
47 #include "paths.h"
48
49 extern int m_wait(void); /* Diese Funktion muss in Ihrem Hauptprogramm stehen, *
50 * sie wird von m_musik() nach jedem 1/96 Takt aufgerufen, und sie sollte *
51 * immer eine bestimmte Zeitspanne warten ( bestimmt die Ablaufgeschwindig- *
52 * keit der Musik ). Dies kann durch den Aufruf von m_wloop() geschehen. */
53
54 unsigned short *takte;
55 short buffer[100], *liste,
56 max_abl, max_tkt, walz, tempo, temp,
57 w_len, save7, reg7, kanal,
58 tra[3], lau[3];
59
60 /**************** Tabellen f�r Noten- und Frequenzwerte **********************/
61 short st_wert[] =
62 {
63 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 27, 28, 30,
64 32, 34, 36, 38, 40, 42, 45, 47, 50, 53, 56, 60,
65 63, 67, 71, 75, 80, 84, 89, 95, 100, 106, 113, 119,
66 127, 134, 142, 150, 159, 169, 179, 190, 201, 213, 226, 239,
67 253, 268, 284, 301, 319, 338, 358, 379, 402, 426, 451, 478,
68 506, 536, 568, 602, 638, 676, 716, 759, 804, 852, 903, 956,
69 1013, 1073, 1136, 1204, 1276, 1351, 1432, 1517, 1607, 1703, 1804, 1911,
70 2025, 2145, 2273, 2408, 2553, 2703, 2864, 3034, 3214, 3405, 3608, 3823
71 } ;
72
73 char st_ton[] =
74 {
75 0, 1, 3, 5, 7, 8, 10, 12, 13, 15, 17, 19, 20, 22, 24, 25,
76 27, 29, 31, 32, 34, 36, 37, 39, 41, 43, 44, 46, 48, 49, 51, 53,
77 55, 56, 58, 60, 61, 63, 65, 67, 68, 70, 72, 73,
78 75, 77, 79, 80, 82, 84, 85, 87, 89, 91, 92, 94, 96
79 } ;
80
81 /******************** Laden und Speicher reservieren *************************/
m_laden(const char * string)82 void m_laden(const char * string)
83 {
84 FILE *f_handle;
85 int i;
86 char *fname;
87
88 fname = malloc(FILENAME_MAX);
89 if (!fname)
90 {
91 perror("m_laden");
92 return;
93 }
94 snprintf(fname, FILENAME_MAX, "%s/%s",
95 Paths_GetDataDir(), string);
96
97 /* Open file in data directory */
98 f_handle = fopen(fname, "rb");
99 free(fname); fname = NULL;
100 if (!f_handle)
101 {
102 /* Try local directory instead */
103 f_handle = fopen(string, "rb");
104 if (!f_handle)
105 {
106 perror("Loading music failed");
107 return;
108 }
109 }
110
111 if (fread(buffer, 16, 1, f_handle) != 1)
112 {
113 perror("Failed to read music file");
114 goto out;
115 }
116 for (i = 0; i < 16/2; i++)
117 {
118 buffer[i] = SDL_SwapBE16(buffer[i]);
119 }
120
121 tempo=buffer[2];
122 max_abl=buffer[3];
123 max_tkt=buffer[4];
124 walz=buffer[7];
125 if( walz )
126 w_len=72;
127 else
128 w_len=96;
129
130 liste=( short *)malloc((max_abl+2)<<3 );
131 /* Reserviere Speicherbereich der Gr��e (w_len*2)*(max_tkt+2) und l�sch ihn. */
132 takte=( unsigned short *)calloc( w_len*2, max_tkt+2+2 );
133
134 if (fread(buffer, 1, 36, f_handle) != 36)
135 {
136 perror("Failed to read music file");
137 goto out;
138 }
139 for (i = 0; i < 36/2; i++)
140 {
141 buffer[i] = SDL_SwapBE16(buffer[i]);
142 }
143
144 if (fread(liste, (max_abl+1)<<3, 1, f_handle) != 1)
145 {
146 perror("Failed to read music file");
147 goto out;
148 }
149 for (i = 0; i < ((max_abl+1)<<3)/2; i++)
150 {
151 liste[i] = SDL_SwapBE16(liste[i]);
152 }
153
154 if (fread(&takte[100], (max_tkt+1)*w_len, 2, f_handle) != 2)
155 {
156 perror("Failed to read music file");
157 goto out;
158 }
159 for (i = 0; i < (max_tkt+1)*w_len; i++)
160 {
161 takte[100+i] = SDL_SwapBE16(takte[100+i]);
162 }
163
164 out:
165 fclose(f_handle);
166 }
167
m_quit(void)168 void m_quit(void)
169 {
170 free(liste); liste = NULL;
171 free(takte); takte = NULL;
172 }
173
174 /************************ St�ck spielen **************************************/
m_musik(void)175 void m_musik(void)
176 {
177 short buf_ptr, lis_ptr, ende, help,
178 kan1, kan2, kan3, rau;
179
180 if (!liste || !takte)
181 return;
182
183 s_init();
184 buffer[0]=0;
185 buffer[1]=-2;
186 buf_ptr=2;
187 lis_ptr=0;
188 temp=100;
189 lau[0]=lau[1]=lau[2]=100;
190 tra[0]=tra[1]=tra[2]=0;
191 ende=0;
192
193 while( !ende )
194 {
195 switch( liste[lis_ptr] )
196 {
197 case -1:
198 if( buffer[--buf_ptr]==-2 ) ende=1;
199 lis_ptr=buffer[--buf_ptr];
200 break;
201 case -2:
202 tra[0]=liste[++lis_ptr];
203 tra[1]=liste[++lis_ptr];
204 tra[2]=liste[++lis_ptr];
205 lis_ptr++;
206 break;
207 case -3:
208 lau[0]=liste[++lis_ptr];
209 lau[1]=liste[++lis_ptr];
210 lau[2]=liste[++lis_ptr];
211 lis_ptr++;
212 break;
213 case -4:
214 temp=liste[++lis_ptr];
215 lis_ptr+=3;
216 break;
217 case -5:
218 lis_ptr+=4;
219 buffer[buf_ptr++]=lis_ptr;
220 buffer[buf_ptr++]=0;
221 break;
222 case -6:
223 lis_ptr+=4;
224 if( buffer[buf_ptr-1]==liste[lis_ptr-3] )
225 {
226 buf_ptr-=2;
227 help=0;
228 while( help>=0 )
229 {
230 if( liste[lis_ptr]==-1 ) help=-1;
231 help+=( liste[lis_ptr]==-5 )-( liste[lis_ptr]==-7 );
232 lis_ptr+=4;
233 }
234 }
235 break;
236 case -7:
237 buffer[buf_ptr-1]++;
238 lis_ptr=buffer[buf_ptr-2];
239 break;
240 case -8:
241 if( liste[++lis_ptr]<0 )
242 lis_ptr+=3;
243 else
244 {
245 buffer[buf_ptr++]=lis_ptr+3;
246 buffer[buf_ptr++]=-5;
247 lis_ptr=(liste[lis_ptr]-1)<<2;
248 }
249 break;
250 default:
251 rau =( liste[lis_ptr]>=0 )*(( liste[lis_ptr+0] )*w_len +100);
252 lis_ptr++;
253 kan1=( liste[lis_ptr]>=0 )*(( liste[lis_ptr+0] )*w_len +100);
254 lis_ptr++;
255 kan2=( liste[lis_ptr]>=0 )*(( liste[lis_ptr+0] )*w_len +100);
256 lis_ptr++;
257 kan3=( liste[lis_ptr]>=0 )*(( liste[lis_ptr+0] )*w_len +100);
258 lis_ptr++;
259 for( help=0; help<w_len; help++ )
260 {
261 s_rausch( takte[rau++]&255 );
262 kanal=0;
263 s_note( takte[kan1++] );
264 kanal++;
265 s_note( takte[kan2++] );
266 kanal++;
267 s_note( takte[kan3++] );
268
269 if (m_wait())
270 {
271 help=100;
272 ende++; /* Bei Taste Abbruch */
273 }
274 }
275 }
276 }
277 s_quit();
278 }
279
280 /************* Standardroutine f�r m_wait(): Pause machen ********************/
m_wloop(void)281 void m_wloop(void)
282 {
283 SDL_Delay(1800/w_len);
284 }
285
286 /*****************************************************************************
287 * Und nun die Routinen zur eigentlichen Tonerzeugung; sie brauchen von *
288 * Ihrem Programm nicht aufgerufen zu werden. */
289 /****************************** Note spielen *********************************/
s_note(unsigned int wert)290 void s_note(unsigned int wert)
291 {
292 short ton_nr;
293 ton_nr=st_ton[ wert>>2 & 63 ];
294 if( wert & 0x4000 ) ton_nr--;
295 if( wert & 0x8000 ) ton_nr++;
296 if( ( wert & 0xc000 ) == 0xc000 )
297 {
298 s_rausch( wert&255 );
299 }
300 else
301 {
302 ton_nr-=tra[kanal];
303 if( ton_nr<0 ) ton_nr=0;
304 if( ton_nr>95 ) ton_nr=95;
305 s_freq( (st_wert[ton_nr]*(4-(wert&3))+st_wert[ton_nr+1]*(wert&3) )>>2 );
306 if( wert & 0x1000 ) s_t_an();
307 else s_t_aus();
308 if( wert & 0x2000 ) s_r_an();
309 else s_r_aus();
310 s_laut( (wert>>8 & 15)*lau[kanal]/100 );
311 }
312 }
313
314 /*************************** Sound Ansteuerung *******************************/
315
316 /**************************** Initialisierung ********************************/
s_init(void)317 void s_init(void)
318 {
319 reg7=save7=Giaccess( 0, 0x07 );
320 s_rausch( 0 );
321 }
322
323 /*********************** Wiederherstellen vor Ende ***************************/
s_quit(void)324 void s_quit(void)
325 {
326 s_aus();
327 Giaccess( save7, 0x87 );
328 }
329
330 /************************** Tonfrequenz setzen *******************************/
s_freq(unsigned short freq)331 void s_freq(unsigned short freq)
332 {
333 short kan;
334 kan=kanal<<1;
335 Giaccess( freq&0xff, kan+0x80 );
336 Giaccess( freq>>8, kan+0x81 );
337 }
338
339 /************************** Lautst�rke setzen ********************************/
s_laut(short laut)340 void s_laut(short laut)
341 {
342 Giaccess( laut, kanal+0x88 );
343 }
344
345 /************************* Rauschperiode setzen ******************************/
s_rausch(short periode)346 void s_rausch(short periode)
347 {
348 Giaccess( periode, 0x86 );
349 }
350
351 /**************************** Ton einschalten ********************************/
s_t_an(void)352 void s_t_an(void)
353 {
354 reg7&=( 254-kanal-( kanal==2 ) );
355 Giaccess( reg7, 0x87 );
356 }
357
358 /**************************** Ton ausschalten ********************************/
s_t_aus(void)359 void s_t_aus(void)
360 {
361 reg7|=( 1+kanal+( kanal==2 ) );
362 Giaccess( reg7, 0x87 );
363 }
364
365 /*************************** Rauschen einschalten ****************************/
s_r_an(void)366 void s_r_an(void)
367 {
368 reg7 &= 255 -((1 + kanal + (kanal == 2)) << 3);
369 Giaccess(reg7, 0x87);
370 }
371
372 /*************************** Rauschen ausschalten ****************************/
s_r_aus(void)373 void s_r_aus(void)
374 {
375 reg7 |= ((1 + kanal + (kanal == 2)) << 3);
376 Giaccess(reg7, 0x87);
377 }
378
379 /*************************** Sound abschalten ********************************/
s_aus(void)380 void s_aus(void)
381 {
382 kanal=0;
383 s_laut( 0 );
384 kanal=1;
385 s_laut( 0 );
386 kanal=2;
387 s_laut( 0 );
388 }
389