1
2 #include <stdio.h>
3 #include <strings.h>
4 #include <stdlib.h>
5 #include <unistd.h>
6 #include <math.h>
7
8 #include <system_includes.h>
9
10 #include "util.h"
11 #include "replay.h"
12 #include "tables.h"
13 #include "gui.h"
14 #include "undo.h"
15
16 extern BOOL quitting;
17 extern int32 defnotejump, definotejump;
18
19 APTR rp_mempool = NULL;
20
21 #ifndef __SDL_WRAPPER__
22 #define FREQ 48000
23 extern uint32 gui_tick_sig;
24 struct Task *rp_maintask = NULL;
25 struct Process *rp_subtask = NULL;
26 int32 rp_subtask_sig = -1;
27 struct MsgPort *rp_msgport = NULL;
28 uint32 rp_sigs = 0;
29
30 uint32 rp_freq = FREQ;
31 float64 rp_freqf = FREQ;
32 uint32 rp_audiobuflen;
33 int8 *rp_audiobuffer[2] = { NULL, NULL };
34
35 struct MsgPort *rp_replyport = NULL;
36 #endif
37
38 struct rp_command *rp_mainmsg = NULL;
39
40 struct List *rp_tunelist = NULL;
41
42 struct ahx_tune *rp_curtune = NULL;
43
44 struct SignalSemaphore *rp_list_ss = NULL;
45
46 enum {
47 STS_IDLE = 0,
48 STS_PLAYNOTE,
49 STS_PLAYPOS,
50 STS_PLAYSONG,
51 STS_RECORDING,
52 STS_CALCULATING,
53 STS_DEADED,
54 STS_PLAYROW
55 };
56
57 uint32 rp_state = STS_IDLE;
58 #ifdef __SDL_WRAPPER__
59 volatile uint32 rp_state_ack = STS_IDLE;
60 #endif
61 extern int32 pref_defstereo;
62
63 #ifndef __SDL_WRAPPER__
64 // Libraries and interfaces
65 struct Library *AHIBase = NULL;
66 struct AHIIFace *IAHI = NULL;
67
68 // AHI stuff
69 struct MsgPort *ahi_mp;
70 struct AHIRequest *ahi_io[2] = { NULL, NULL };
71 int32 ahi_dev = -1;
72 #else
73 #define FREQ 48000
74 #ifdef __linux__
75 #define OUTPUT_LEN ((FREQ/50)*2) /* Linux can't cope with buffer being too small, so we sacrifice GUI responsiveness... */
76 #else
77 #define OUTPUT_LEN (FREQ/50)
78 #endif
79 static struct ahx_tune *rp_playtune = NULL;
80 int16 rp_audiobuffer[OUTPUT_LEN*2];
81 uint32 rp_audiobuflen = OUTPUT_LEN*2;
82 #endif
83
84 /*
85 ** Waves
86 */
87
88 int8 waves[WAVES_SIZE];
89
90 uint32 panning_left[256], panning_right[256];
91 /*
92 static inline void clr_l( uint32 *src, uint32 longs)
93 {
94 do {
95 *src++ = 0;
96 longs--;
97 } while (longs > 0);
98 }
99 */
rp_GenPanningTables(void)100 void rp_GenPanningTables( void )
101 {
102 uint32 i;
103 float64 aa, ab;
104
105 // Sine based panning table
106 aa = (3.14159265f*2.0f)/4.0f; // Quarter of the way through the sinewave == top peak
107 ab = 0.0f; // Start of the climb from zero
108
109 for( i=0; i<256; i++ )
110 {
111 panning_left[i] = (uint32)(sin(aa)*255.0f);
112 panning_right[i] = (uint32)(sin(ab)*255.0f);
113
114 aa += (3.14159265*2.0f/4.0f)/256.0f;
115 ab += (3.14159265*2.0f/4.0f)/256.0f;
116 }
117 panning_left[255] = 0;
118 panning_right[0] = 0;
119
120 /*
121 // Original panning table (linear panning == poo)
122 for( i=0; i<256; i++ )
123 {
124 // Compensate for -128 to 127 range (ideally we want -128 to 128)
125
126 if( i < 64 )
127 panning_left[i] = 256-i;
128 else
129 panning_left[i] = 255-i;
130
131 if( i > 191 )
132 panning_right[i] = i+1;
133 else
134 panning_right[i] = i;
135
136 if( panning_left[i] == 128 ) panning_right[i] = 128;
137 if( panning_right[i] == 128 ) panning_left[i] = 128;
138 }
139 */
140 }
141
rp_GenSawtooth(int8 * buf,uint32 len)142 void rp_GenSawtooth( int8 *buf, uint32 len )
143 {
144 uint32 i;
145 int32 val, add;
146
147 add = 256 / (len-1);
148 val = -128;
149
150 for( i=0; i<len; i++, val += add )
151 *buf++ = (int8)val;
152 }
153
rp_GenTriangle(int8 * buf,uint32 len)154 void rp_GenTriangle( int8 *buf, uint32 len )
155 {
156 uint32 i;
157 int32 d2, d5, d1, d4;
158 int32 val;
159 const int8 *buf2;
160
161 d2 = len;
162 d5 = len >> 2;
163 d1 = 128/d5;
164 d4 = -(d2 >> 1);
165 val = 0;
166
167 for( i=0; i<d5; i++ )
168 {
169 *buf++ = val;
170 val += d1;
171 }
172 *buf++ = 0x7f;
173
174 if( d5 != 1 )
175 {
176 val = 128;
177 for( i=0; i<d5-1; i++ )
178 {
179 val -= d1;
180 *buf++ = val;
181 }
182 }
183
184 buf2 = buf + d4;
185 for( i=0; i<d5*2; i++ )
186 {
187 int8 c;
188
189 c = *buf2++;
190 if( c == 0x7f )
191 c = 0x80;
192 else
193 c = -c;
194
195 *buf++ = c;
196 }
197 }
198
rp_GenSquare(int8 * buf)199 void rp_GenSquare( int8 *buf )
200 {
201 uint32 i, j;
202
203 for( i=1; i<=0x20; i++ )
204 {
205 for( j=0; j<(0x40-i)*2; j++ )
206 *buf++ = 0x80;
207 for( j=0; j<i*2; j++ )
208 *buf++ = 0x7f;
209 }
210 }
211
clipshifted8(int32 in)212 static inline int32 clipshifted8(int32 in)
213 {
214 int16 top = (int16)(in >> 16);
215 if (top > 127) in = 127 << 16;
216 else if (top < -128) in = -(128 << 16);
217 return in;
218 }
219
rp_GenFilterWaves(const int8 * buf,int8 * lowbuf,int8 * highbuf)220 void rp_GenFilterWaves( const int8 *buf, int8 *lowbuf, int8 *highbuf )
221 {
222
223
224 const int16 * mid_table = &filter_thing[0];
225 const int16 * low_table = &filter_thing[1395];
226
227 int32 freq;
228 int32 i;
229
230 for( i=0, freq = 25; i<31; i++, freq += 9 )
231 {
232 uint32 wv;
233 const int8 *a0 = buf;
234
235 for( wv=0; wv<6+6+0x20+1; wv++ )
236 {
237 int32 in, fre, high, mid, low;
238 uint32 j;
239
240 mid = *mid_table++ << 8;
241 low = *low_table++ << 8;
242
243 for( j=0; j<=lentab[wv]; j++ )
244 {
245 in = a0[j] << 16;
246 high = clipshifted8( in - mid - low );
247 fre = (high >> 8) * freq;
248 mid = clipshifted8(mid + fre);
249 fre = (mid >> 8) * freq;
250 low = clipshifted8(low + fre);
251 *highbuf++ = high >> 16;
252 *lowbuf++ = low >> 16;
253 }
254 a0 += lentab[wv]+1;
255 }
256 }
257 }
258
rp_GenWhiteNoise(int8 * buf,uint32 len)259 void rp_GenWhiteNoise( int8 *buf, uint32 len )
260 {
261 uint32 ays;
262
263 ays = 0x41595321;
264
265 do {
266 uint16 ax, bx;
267 int8 s;
268
269 s = ays;
270
271 if( ays & 0x100 )
272 {
273 s = 0x7f;
274
275 if( ays & 0x8000 )
276 s = 0x80;
277 }
278
279 *buf++ = s;
280 len--;
281
282 ays = (ays >> 5) | (ays << 27);
283 ays = (ays & 0xffffff00) | ((ays & 0xff) ^ 0x9a);
284 bx = ays;
285 ays = (ays << 2) | (ays >> 30);
286 ax = ays;
287 bx += ax;
288 ax ^= bx;
289 ays = (ays & 0xffff0000) | ax;
290 ays = (ays >> 3) | (ays << 29);
291 } while( len );
292 }
293
rp_clear_instrument(struct ahx_instrument * ins)294 void rp_clear_instrument( struct ahx_instrument *ins )
295 {
296 int32 j;
297
298 ins->ins_Name[0] = 0;
299 ins->ins_Volume = 64;
300 ins->ins_WaveLength = 3;
301 ins->ins_FilterLowerLimit = 1;
302 ins->ins_FilterUpperLimit = 1;
303 ins->ins_FilterSpeed = 0;
304 ins->ins_SquareLowerLimit = 1;
305 ins->ins_SquareUpperLimit = 1;
306 ins->ins_SquareSpeed = 0;
307 ins->ins_VibratoDelay = 0;
308 ins->ins_VibratoSpeed = 0;
309 ins->ins_VibratoDepth = 0;
310 ins->ins_HardCutRelease = 0;
311 ins->ins_HardCutReleaseFrames = 0;
312 ins->ins_Envelope.aFrames = 1;
313 ins->ins_Envelope.aVolume = 0;
314 ins->ins_Envelope.dFrames = 1;
315 ins->ins_Envelope.dVolume = 0;
316 ins->ins_Envelope.sFrames = 1;
317 ins->ins_Envelope.rFrames = 1;
318 ins->ins_Envelope.rVolume = 0;
319 ins->ins_PList.pls_Speed = 0;
320 ins->ins_PList.pls_Length = 0;
321 for( j=0; j<256; j++ )
322 {
323 ins->ins_PList.pls_Entries[j].ple_Note = 0;
324 ins->ins_PList.pls_Entries[j].ple_Waveform = 0;
325 ins->ins_PList.pls_Entries[j].ple_Fixed = 0;
326 ins->ins_PList.pls_Entries[j].ple_FX[0] = 0;
327 ins->ins_PList.pls_Entries[j].ple_FXParam[0] = 0;
328 ins->ins_PList.pls_Entries[j].ple_FX[1] = 0;
329 ins->ins_PList.pls_Entries[j].ple_FXParam[1] = 0;
330 }
331 ins->ins_ptop = 0;
332 ins->ins_pcurx = 0;
333 ins->ins_pcury = 0;
334 }
335
rp_clear_tune(struct ahx_tune * at)336 void rp_clear_tune( struct ahx_tune *at )
337 {
338 int32 i, j;
339 int32 defgain[] = { 71, 72, 76, 85, 100 };
340
341 if( at == NULL ) return;
342 if( at == rp_curtune ) rp_stop();
343
344 free_undolists( at );
345
346 at->at_Name[0] = 0;
347 at->at_Time = 0;
348 at->at_ExactTime = 0;
349 at->at_LoopDetector = 0;
350 at->at_SongNum = 0;
351 at->at_Frequency = FREQ;
352 at->at_FreqF = (float64)FREQ;
353 at->at_WaveformTab[0] = &waves[WO_TRIANGLE_04];
354 at->at_WaveformTab[1] = &waves[WO_SAWTOOTH_04];
355 at->at_WaveformTab[3] = &waves[WO_WHITENOISE];
356 at->at_Restart = 0;
357 at->at_PositionNr = 1;
358 at->at_SpeedMultiplier = 1;
359 at->at_TrackLength = 64;
360 at->at_TrackNr = 0;
361 at->at_InstrumentNr = 0;
362 at->at_SubsongNr = 0;
363 at->at_PosJump = 0;
364 at->at_PlayingTime = 0;
365 at->at_Tempo = 6;
366 at->at_PosNr = 0;
367 at->at_NextPosNr = -1;
368 at->at_StepWaitFrames = 0;
369 at->at_NoteNr = 0;
370 at->at_PosJumpNote = 0;
371 at->at_GetNewPosition = 0;
372 at->at_PatternBreak = 0;
373 at->at_SongEndReached = 0;
374 at->at_posed_curs = 0;
375 at->at_tracked_curs = 0;
376 at->at_curins = 1;
377 at->at_drumpadnote = 25;
378 at->at_drumpadmode = FALSE;
379 at->at_topins = 1;
380 at->at_topinsb = 1;
381 at->at_curlch = 0;
382 at->at_Channels = 4;
383 at->at_baseins = 0;
384 at->at_curpanel = 0;
385 at->at_modified = FALSE;
386 at->at_defstereo = pref_defstereo;
387 at->at_defpanleft = stereopan_left[pref_defstereo];
388 at->at_defpanright = stereopan_right[pref_defstereo];
389 at->at_mixgain = (defgain[pref_defstereo]*256)/100;
390 at->at_mixgainP = defgain[pref_defstereo];
391
392 at->at_cbmarktrack = -1;
393 at->at_cbmarkstartnote = -1;
394 at->at_cbmarkendnote = -1;
395 at->at_cbmarkleftx = 0;
396 at->at_cbmarkrightx = 0;
397
398 at->at_cbpmarklft = -1;
399 at->at_cbpmarkmarklft = -1;
400
401 at->at_notejump = defnotejump;
402 at->at_inotejump = definotejump;
403
404 at->at_doing = D_IDLE;
405 at->at_editing = E_TRACK;
406 at->at_idoing = D_IDLE;
407
408 at->at_rempos[0] = 0;
409 at->at_rempos[1] = 16;
410 at->at_rempos[2] = 32;
411 at->at_rempos[3] = 48;
412 at->at_rempos[4] = 63;
413
414 for( i=0; i<MAX_CHANNELS; i++ )
415 {
416 at->at_Voices[i].vc_VUMeter = 0;
417 at->at_Voices[i].vc_SetTrackOn = 1;
418 }
419
420 for( i=0; i<MAX_CHANNELS; i+=4 )
421 {
422 at->at_Voices[i+0].vc_Pan = at->at_defpanleft;
423 at->at_Voices[i+0].vc_SetPan = at->at_defpanleft;
424 at->at_Voices[i+0].vc_PanMultLeft = panning_left[at->at_defpanleft];
425 at->at_Voices[i+0].vc_PanMultRight = panning_right[at->at_defpanleft];
426 at->at_Voices[i+1].vc_Pan = at->at_defpanright;
427 at->at_Voices[i+1].vc_SetPan = at->at_defpanright;
428 at->at_Voices[i+1].vc_PanMultLeft = panning_left[at->at_defpanright];
429 at->at_Voices[i+1].vc_PanMultRight = panning_right[at->at_defpanright];
430 at->at_Voices[i+2].vc_Pan = at->at_defpanright;
431 at->at_Voices[i+2].vc_SetPan = at->at_defpanright;
432 at->at_Voices[i+2].vc_PanMultLeft = panning_left[at->at_defpanright];
433 at->at_Voices[i+2].vc_PanMultRight = panning_right[at->at_defpanright];
434 at->at_Voices[i+3].vc_Pan = at->at_defpanleft;
435 at->at_Voices[i+3].vc_SetPan = at->at_defpanleft;
436 at->at_Voices[i+3].vc_PanMultLeft = panning_left[at->at_defpanleft];
437 at->at_Voices[i+3].vc_PanMultRight = panning_right[at->at_defpanleft];
438 }
439
440 for( i=0; i<256; i++ )
441 {
442 at->at_Subsongs[i] = 0;
443
444 for( j=0; j<64; j++ )
445 {
446 at->at_Tracks[i][j].stp_Note = 0;
447 at->at_Tracks[i][j].stp_Instrument = 0;
448 at->at_Tracks[i][j].stp_FX = 0;
449 at->at_Tracks[i][j].stp_FXParam = 0;
450 at->at_Tracks[i][j].stp_FXb = 0;
451 at->at_Tracks[i][j].stp_FXbParam = 0;
452 }
453 }
454
455 for( i=0; i<1000; i++ )
456 {
457 for( j=0; j<MAX_CHANNELS; j++ )
458 {
459 at->at_Positions[i].pos_Track[j] = 0;
460 at->at_Positions[i].pos_Transpose[j] = 0;
461 }
462 }
463
464
465 for( i=0; i<64; i++ )
466 rp_clear_instrument( &at->at_Instruments[i] );
467
468 at->at_ticks = at->at_secs = at->at_mins = at->at_hours = 0;
469 }
470
rp_reset_some_shit(struct ahx_tune * at)471 void rp_reset_some_shit( struct ahx_tune *at )
472 {
473 uint32 i;
474
475 at->at_ticks = at->at_secs = at->at_mins = at->at_hours = 0;
476
477 for( i=0; i<MAX_CHANNELS; i++ )
478 {
479 at->at_Voices[i].vc_Delta=1;
480 at->at_Voices[i].vc_OverrideTranspose = 1000; // 1.5
481 at->at_Voices[i].vc_SamplePos=at->at_Voices[i].vc_Track=at->at_Voices[i].vc_Transpose=at->at_Voices[i].vc_NextTrack = at->at_Voices[i].vc_NextTranspose = 0;
482 at->at_Voices[i].vc_ADSRVolume=at->at_Voices[i].vc_InstrPeriod=at->at_Voices[i].vc_TrackPeriod=at->at_Voices[i].vc_VibratoPeriod=at->at_Voices[i].vc_NoteMaxVolume=at->at_Voices[i].vc_PerfSubVolume=at->at_Voices[i].vc_TrackMasterVolume=0;
483 at->at_Voices[i].vc_NewWaveform=at->at_Voices[i].vc_Waveform=at->at_Voices[i].vc_PlantSquare=at->at_Voices[i].vc_PlantPeriod=at->at_Voices[i].vc_IgnoreSquare=0;
484 at->at_Voices[i].vc_TrackOn=at->at_Voices[i].vc_FixedNote=at->at_Voices[i].vc_VolumeSlideUp=at->at_Voices[i].vc_VolumeSlideDown=at->at_Voices[i].vc_HardCut=at->at_Voices[i].vc_HardCutRelease=at->at_Voices[i].vc_HardCutReleaseF=0;
485 at->at_Voices[i].vc_PeriodSlideSpeed=at->at_Voices[i].vc_PeriodSlidePeriod=at->at_Voices[i].vc_PeriodSlideLimit=at->at_Voices[i].vc_PeriodSlideOn=at->at_Voices[i].vc_PeriodSlideWithLimit=0;
486 at->at_Voices[i].vc_PeriodPerfSlideSpeed=at->at_Voices[i].vc_PeriodPerfSlidePeriod=at->at_Voices[i].vc_PeriodPerfSlideOn=at->at_Voices[i].vc_VibratoDelay=at->at_Voices[i].vc_VibratoCurrent=at->at_Voices[i].vc_VibratoDepth=at->at_Voices[i].vc_VibratoSpeed=0;
487 at->at_Voices[i].vc_SquareOn=at->at_Voices[i].vc_SquareInit=at->at_Voices[i].vc_SquareLowerLimit=at->at_Voices[i].vc_SquareUpperLimit=at->at_Voices[i].vc_SquarePos=at->at_Voices[i].vc_SquareSign=at->at_Voices[i].vc_SquareSlidingIn=at->at_Voices[i].vc_SquareReverse=0;
488 at->at_Voices[i].vc_FilterOn=at->at_Voices[i].vc_FilterInit=at->at_Voices[i].vc_FilterLowerLimit=at->at_Voices[i].vc_FilterUpperLimit=at->at_Voices[i].vc_FilterPos=at->at_Voices[i].vc_FilterSign=at->at_Voices[i].vc_FilterSpeed=at->at_Voices[i].vc_FilterSlidingIn=at->at_Voices[i].vc_IgnoreFilter=0;
489 at->at_Voices[i].vc_PerfCurrent=at->at_Voices[i].vc_PerfSpeed=at->at_Voices[i].vc_WaveLength=at->at_Voices[i].vc_NoteDelayOn=at->at_Voices[i].vc_NoteCutOn=0;
490 at->at_Voices[i].vc_AudioPeriod=at->at_Voices[i].vc_AudioVolume=at->at_Voices[i].vc_VoiceVolume=at->at_Voices[i].vc_VoicePeriod=at->at_Voices[i].vc_VoiceNum=at->at_Voices[i].vc_WNRandom=0;
491 at->at_Voices[i].vc_SquareWait=at->at_Voices[i].vc_FilterWait=at->at_Voices[i].vc_PerfWait=at->at_Voices[i].vc_NoteDelayWait=at->at_Voices[i].vc_NoteCutWait=0;
492 at->at_Voices[i].vc_PerfList=0;
493 at->at_Voices[i].vc_RingSamplePos=at->at_Voices[i].vc_RingDelta=at->at_Voices[i].vc_RingPlantPeriod=at->at_Voices[i].vc_RingAudioPeriod=at->at_Voices[i].vc_RingNewWaveform=at->at_Voices[i].vc_RingWaveform=at->at_Voices[i].vc_RingFixedPeriod=at->at_Voices[i].vc_RingBasePeriod=0;
494
495 at->at_Voices[i].vc_RingMixSource = NULL;
496 at->at_Voices[i].vc_RingAudioSource = NULL;
497
498 memset( &at->at_Voices[i].vc_SquareTempBuffer,0,0x80);
499 memset( &at->at_Voices[i].vc_ADSR,0,sizeof(struct ahx_envelope));
500 memset( &at->at_Voices[i].vc_VoiceBuffer,0,0x281);
501 memset( &at->at_Voices[i].vc_RingVoiceBuffer,0,0x281);
502 }
503
504 for( i=0; i<MAX_CHANNELS; i++ )
505 {
506 at->at_Voices[i].vc_WNRandom = 0x280;
507 at->at_Voices[i].vc_VoiceNum = i;
508 at->at_Voices[i].vc_TrackMasterVolume = 0x40;
509 at->at_Voices[i].vc_TrackOn = at->at_Voices[i].vc_SetTrackOn;
510 at->at_Voices[i].vc_MixSource = at->at_Voices[i].vc_VoiceBuffer;
511 }
512 }
513
rp_init_subsong(struct ahx_tune * at,uint32 nr)514 BOOL rp_init_subsong( struct ahx_tune *at, uint32 nr )
515 {
516 uint32 PosNr, i;
517
518 if( nr > at->at_SubsongNr )
519 return FALSE;
520
521 at->at_SongNum = nr;
522
523 PosNr = 0;
524 if( nr ) PosNr = at->at_Subsongs[nr-1];
525
526 at->at_PosNr = PosNr;
527 at->at_PosJump = 0;
528 at->at_PatternBreak = 0;
529 at->at_NoteNr = 0;
530 at->at_PosJumpNote = 0;
531 at->at_Tempo = 6;
532 at->at_StepWaitFrames = 0;
533 at->at_GetNewPosition = 1;
534 at->at_SongEndReached = 0;
535 at->at_PlayingTime = 0;
536 at->at_curss = nr;
537
538 for( i=0; i<MAX_CHANNELS; i+=4 )
539 {
540 at->at_Voices[i+0].vc_Pan = at->at_defpanleft;
541 at->at_Voices[i+0].vc_SetPan = at->at_defpanleft;
542 at->at_Voices[i+0].vc_PanMultLeft = panning_left[at->at_defpanleft];
543 at->at_Voices[i+0].vc_PanMultRight = panning_right[at->at_defpanleft];
544 at->at_Voices[i+1].vc_Pan = at->at_defpanright;
545 at->at_Voices[i+1].vc_SetPan = at->at_defpanright;
546 at->at_Voices[i+1].vc_PanMultLeft = panning_left[at->at_defpanright];
547 at->at_Voices[i+1].vc_PanMultRight = panning_right[at->at_defpanright];
548 at->at_Voices[i+2].vc_Pan = at->at_defpanright;
549 at->at_Voices[i+2].vc_SetPan = at->at_defpanright;
550 at->at_Voices[i+2].vc_PanMultLeft = panning_left[at->at_defpanright];
551 at->at_Voices[i+2].vc_PanMultRight = panning_right[at->at_defpanright];
552 at->at_Voices[i+3].vc_Pan = at->at_defpanleft;
553 at->at_Voices[i+3].vc_SetPan = at->at_defpanleft;
554 at->at_Voices[i+3].vc_PanMultLeft = panning_left[at->at_defpanleft];
555 at->at_Voices[i+3].vc_PanMultRight = panning_right[at->at_defpanleft];
556 }
557
558 rp_reset_some_shit( at );
559
560 return TRUE;
561 }
562
rp_new_tune(BOOL addtolist)563 struct ahx_tune *rp_new_tune( BOOL addtolist )
564 {
565 struct ahx_tune *at;
566
567 at = (struct ahx_tune *)allocnode(sizeof(struct ahx_tune));
568 if( !at )
569 {
570 printf( "Out of memory @ %s:%d\n", __FILE__, __LINE__ );
571 return NULL;
572 }
573
574 at->at_undolist = IExec->AllocSysObjectTags( ASOT_LIST, TAG_DONE );
575 if( !at->at_undolist )
576 {
577 IExec->FreeSysObject( ASOT_NODE, at );
578 printf( "Out of memory @ %s:%d\n", __FILE__, __LINE__ );
579 return NULL;
580 }
581
582 at->at_redolist = IExec->AllocSysObjectTags( ASOT_LIST, TAG_DONE );
583 if( !at->at_redolist )
584 {
585 IExec->FreeSysObject( ASOT_LIST, at->at_undolist );
586 IExec->FreeSysObject( ASOT_NODE, at );
587 printf( "Out of memory @ %s:%d\n", __FILE__, __LINE__ );
588 return NULL;
589 }
590
591 at->at_undomem = 0;
592
593 at->at_ln.ln_Succ = NULL;
594 at->at_ln.ln_Pred = NULL;
595 at->at_ln.ln_Name = &at->at_Name[0];
596 at->at_ln.ln_Pri = 0;
597 at->at_ln.ln_Type = NT_USER;
598
599 rp_clear_tune( at );
600
601 if( addtolist )
602 {
603 IExec->ObtainSemaphore( rp_list_ss );
604 IExec->AddTail( rp_tunelist, (struct Node *)at );
605 IExec->ReleaseSemaphore( rp_list_ss );
606 }
607
608 rp_init_subsong( at, 0 );
609 return at;
610 }
611
rp_free_tune(struct ahx_tune * at)612 void rp_free_tune( struct ahx_tune *at )
613 {
614 IExec->ObtainSemaphore( rp_list_ss );
615 IExec->Remove( (struct Node *)at );
616
617 free_undolists( at );
618
619 IExec->FreeSysObject( ASOT_LIST, at->at_undolist );
620 IExec->FreeSysObject( ASOT_LIST, at->at_redolist );
621 IExec->FreeSysObject( ASOT_NODE, at );
622 IExec->ReleaseSemaphore( rp_list_ss );
623 }
624
rp_free_all_tunes(void)625 void rp_free_all_tunes( void )
626 {
627 struct ahx_tune *at, *nat;
628
629 IExec->ObtainSemaphore( rp_list_ss );
630 at = (struct ahx_tune *)IExec->GetHead(rp_tunelist);
631 while( at )
632 {
633 nat = (struct ahx_tune *)IExec->GetSucc(&at->at_ln);
634 rp_free_tune( at );
635 at = nat;
636 }
637 IExec->ReleaseSemaphore( rp_list_ss );
638 }
639
rp_save_hvl_ins(const TEXT * name,struct ahx_instrument * ins)640 void rp_save_hvl_ins( const TEXT *name, struct ahx_instrument *ins )
641 {
642 FILE *fh;
643 int8 *buf, *bptr;
644 int32 buflen, i;
645
646 buflen = 26+ins->ins_PList.pls_Length*5;
647 buf = IExec->AllocPooled( rp_mempool, buflen );
648 if( !buf )
649 {
650 printf( "Out of memory @ %s:%d\n", __FILE__, __LINE__ );
651 return;
652 }
653
654 for( i=0; i<buflen; i++ ) buf[i] = 0;
655
656 strcpy( (TEXT *)buf, "HVLI" );
657
658 buf[4] = ins->ins_Volume;
659 buf[5] = (ins->ins_FilterSpeed&0x1f)<<3;
660 buf[16] = (ins->ins_FilterSpeed&0x20)<<2;
661 buf[5] |= ins->ins_WaveLength&0x07;
662
663 buf[6] = ins->ins_Envelope.aFrames;
664 buf[7] = ins->ins_Envelope.aVolume;
665 buf[8] = ins->ins_Envelope.dFrames;
666 buf[9] = ins->ins_Envelope.dVolume;
667 buf[10] = ins->ins_Envelope.sFrames;
668 buf[11] = ins->ins_Envelope.rFrames;
669 buf[12] = ins->ins_Envelope.rVolume;
670
671 buf[16] |= ins->ins_FilterLowerLimit&0x7f;
672 buf[17] = ins->ins_VibratoDelay;
673 buf[18] = (ins->ins_HardCutReleaseFrames&0x07)<<4;
674 buf[18] |= (ins->ins_HardCutRelease&0x1)<<7;
675 buf[18] |= ins->ins_VibratoDepth&0x0f;
676 buf[19] = ins->ins_VibratoSpeed;
677 buf[20] = ins->ins_SquareLowerLimit;
678 buf[21] = ins->ins_SquareUpperLimit;
679 buf[22] = ins->ins_SquareSpeed;
680 buf[23] = ins->ins_FilterUpperLimit&0x3f;
681 buf[24] = ins->ins_PList.pls_Speed;
682 buf[25] = ins->ins_PList.pls_Length;
683
684 bptr = &buf[26];
685
686 for( i=0; i<ins->ins_PList.pls_Length; i++ )
687 {
688 bptr[0] = ins->ins_PList.pls_Entries[i].ple_FX[0]&0xf;
689 bptr[1] = (ins->ins_PList.pls_Entries[i].ple_FX[1]&0xf)<<3;
690 bptr[1] |= ins->ins_PList.pls_Entries[i].ple_Waveform&7;
691 bptr[2] = (ins->ins_PList.pls_Entries[i].ple_Fixed&1)<<6;
692 bptr[2] |= ins->ins_PList.pls_Entries[i].ple_Note&0x3f;
693 bptr[3] = ins->ins_PList.pls_Entries[i].ple_FXParam[0];
694 bptr[4] = ins->ins_PList.pls_Entries[i].ple_FXParam[1];
695 bptr += 5;
696 }
697
698 fh = fopen( name, "wb" );
699 if( !fh )
700 {
701 printf( "unable to open file\n" );
702 IExec->FreePooled( rp_mempool, buf, buflen );
703 return;
704 }
705
706 fwrite( buf, buflen, 1, fh );
707 fwrite( ins->ins_Name, strlen( ins->ins_Name )+1, 1, fh );
708 fclose( fh );
709 IExec->FreePooled( rp_mempool, buf, buflen );
710 }
711
rp_save_ins(const TEXT * name,struct ahx_tune * at,int32 in)712 void rp_save_ins( const TEXT *name, struct ahx_tune *at, int32 in )
713 {
714 FILE *fh;
715 int8 *buf, *bptr;
716 int32 buflen, i, k, l;
717 struct ahx_instrument *ins;
718 BOOL saveahxi;
719 #ifdef __SDL_WRAPPER__
720 char mkname[4096];
721 #endif
722
723 if( at == NULL ) return;
724
725 #ifdef __SDL_WRAPPER__
726 // Enforce file extension since windows likes them so much
727 // (although let them use a prefix if they want to keep it oldskool)
728 if (strncasecmp(name, "ins.", 4) != 0)
729 {
730 // No prefix...
731 i = strlen(name);
732 if ((i < 4) || (strcasecmp(&name[i-4], ".ins") != 0))
733 {
734 // No extension
735 strncpy(mkname, name, 4096);
736 strncat(mkname, ".ins", 4096);
737 mkname[4095] = 0;
738 name = mkname;
739 }
740 }
741 #endif
742
743 ins = &at->at_Instruments[in];
744
745 saveahxi = TRUE;
746
747 // Have to save as HVL instrument?
748 for( i=0; i<ins->ins_PList.pls_Length; i++ )
749 {
750 if( ( ins->ins_PList.pls_Entries[i].ple_FX[0] > 5 ) &&
751 ( ins->ins_PList.pls_Entries[i].ple_FX[0] != 12 ) &&
752 ( ins->ins_PList.pls_Entries[i].ple_FX[0] != 15 ) )
753 saveahxi = FALSE;
754 if( ( ins->ins_PList.pls_Entries[i].ple_FX[1] > 5 ) &&
755 ( ins->ins_PList.pls_Entries[i].ple_FX[1] != 12 ) &&
756 ( ins->ins_PList.pls_Entries[i].ple_FX[1] != 15 ) )
757 saveahxi = FALSE;
758 }
759
760 if( saveahxi == FALSE )
761 {
762 rp_save_hvl_ins( name, ins );
763 return;
764 }
765
766 buflen = 26+ins->ins_PList.pls_Length*4;
767 buf = IExec->AllocPooled( rp_mempool, buflen );
768 if( !buf )
769 {
770 printf( "Out of memory @ %s:%d\n", __FILE__, __LINE__ );
771 return;
772 }
773
774 for( i=0; i<buflen; i++ ) buf[i] = 0;
775
776 strcpy( (TEXT *)buf, "THXI" );
777
778 buf[4] = ins->ins_Volume;
779 buf[5] = (ins->ins_FilterSpeed&0x1f)<<3;
780 buf[16] = (ins->ins_FilterSpeed&0x20)<<2;
781 buf[5] |= ins->ins_WaveLength&0x07;
782
783 buf[6] = ins->ins_Envelope.aFrames;
784 buf[7] = ins->ins_Envelope.aVolume;
785 buf[8] = ins->ins_Envelope.dFrames;
786 buf[9] = ins->ins_Envelope.dVolume;
787 buf[10] = ins->ins_Envelope.sFrames;
788 buf[11] = ins->ins_Envelope.rFrames;
789 buf[12] = ins->ins_Envelope.rVolume;
790
791 buf[16] |= ins->ins_FilterLowerLimit&0x7f;
792 buf[17] = ins->ins_VibratoDelay;
793 buf[18] = (ins->ins_HardCutReleaseFrames&0x07)<<4;
794 buf[18] |= (ins->ins_HardCutRelease&0x1)<<7;
795 buf[18] |= ins->ins_VibratoDepth&0x0f;
796 buf[19] = ins->ins_VibratoSpeed;
797 buf[20] = ins->ins_SquareLowerLimit;
798 buf[21] = ins->ins_SquareUpperLimit;
799 buf[22] = ins->ins_SquareSpeed;
800 buf[23] = ins->ins_FilterUpperLimit&0x3f;
801 buf[24] = ins->ins_PList.pls_Speed;
802 buf[25] = ins->ins_PList.pls_Length;
803
804 bptr = &buf[26];
805
806 for( i=0; i<ins->ins_PList.pls_Length; i++ )
807 {
808 // Convert to AHX format (this means that HVL instruments could have more FX! w00t!)
809 k = ins->ins_PList.pls_Entries[i].ple_FX[1];
810 if( k == 12 ) k = 6;
811 if( k == 15 ) k = 7;
812 l = ins->ins_PList.pls_Entries[i].ple_FX[0];
813 if( l == 12 ) l = 6;
814 if( l == 15 ) l = 7;
815 bptr[0] = (k&7)<<5;
816 bptr[0] |= (l&7)<<2;
817 bptr[0] |= (ins->ins_PList.pls_Entries[i].ple_Waveform&6)>>1;
818 bptr[1] = (ins->ins_PList.pls_Entries[i].ple_Waveform&1)<<7;
819 bptr[1] |= (ins->ins_PList.pls_Entries[i].ple_Fixed&1)<<6;
820 bptr[1] |= ins->ins_PList.pls_Entries[i].ple_Note&0x3f;
821 bptr[2] = ins->ins_PList.pls_Entries[i].ple_FXParam[0];
822 bptr[3] = ins->ins_PList.pls_Entries[i].ple_FXParam[1];
823 bptr += 4;
824 }
825
826 fh = fopen( name, "wb" );
827 if( !fh )
828 {
829 printf( "unable to open file\n" );
830 IExec->FreePooled( rp_mempool, buf, buflen );
831 return;
832 }
833
834 fwrite( buf, buflen, 1, fh );
835 fwrite( ins->ins_Name, strlen( ins->ins_Name )+1, 1, fh );
836 fclose( fh );
837 IExec->FreePooled( rp_mempool, buf, buflen );
838 }
839
rp_load_ins(const TEXT * name,struct ahx_tune * at,int32 in)840 void rp_load_ins( const TEXT *name, struct ahx_tune *at, int32 in )
841 {
842 FILE *fh;
843 uint8 *buf;
844 const uint8 *bptr;
845 uint32 buflen, i, k, l;
846 struct ahx_instrument *ni;
847 BOOL ahxi;
848
849 if( at == NULL ) return;
850
851 fh = fopen(name, "rb");
852 if( !fh )
853 {
854 printf( "Can't open file\n" );
855 return;
856 }
857
858 fseek(fh, 0, SEEK_END);
859 buflen = ftell(fh);
860 fseek(fh, 0, SEEK_SET);
861
862 buf = IExec->AllocPooled( rp_mempool, buflen );
863 if( !buf )
864 {
865 fclose(fh);
866 printf( "Out of memory @ %s:%d\n", __FILE__, __LINE__ );
867 return;
868 }
869
870 if( fread( buf, buflen, 1, fh ) != 1 )
871 {
872 IExec->FreePooled( rp_mempool, buf, buflen );
873 fclose(fh);
874 printf( "Unable to read from file!\n" );
875 return;
876 }
877 fclose(fh);
878
879 ahxi = TRUE;
880
881 if( ( buf[0] == 'H' ) &&
882 ( buf[1] == 'V' ) &&
883 ( buf[2] == 'L' ) &&
884 ( buf[3] == 'I' ) )
885 ahxi = FALSE;
886
887 if( ( ahxi == TRUE ) &&
888 ( ( buf[0] != 'T' ) ||
889 ( buf[1] != 'H' ) ||
890 ( buf[2] != 'X' ) ||
891 ( buf[3] != 'I' ) ) )
892 {
893 IExec->FreePooled( rp_mempool, buf, buflen );
894 printf( "Invalid file\n" );
895 return;
896 }
897
898 ni = &at->at_Instruments[in];
899
900 ni->ins_Volume = buf[4];
901 ni->ins_FilterSpeed = ((buf[5]>>3)&0x1f)|((buf[16]>>2)&0x20);
902 ni->ins_WaveLength = buf[5]&0x07;
903
904 ni->ins_Envelope.aFrames = buf[6];
905 ni->ins_Envelope.aVolume = buf[7];
906 ni->ins_Envelope.dFrames = buf[8];
907 ni->ins_Envelope.dVolume = buf[9];
908 ni->ins_Envelope.sFrames = buf[10];
909 ni->ins_Envelope.rFrames = buf[11];
910 ni->ins_Envelope.rVolume = buf[12];
911
912 ni->ins_FilterLowerLimit = buf[16]&0x7f;
913 ni->ins_VibratoDelay = buf[17];
914 ni->ins_HardCutReleaseFrames = (buf[18]>>4)&0x07;
915 ni->ins_HardCutRelease = buf[18]&0x80?1:0;
916 ni->ins_VibratoDepth = buf[18]&0x0f;
917 ni->ins_VibratoSpeed = buf[19];
918 ni->ins_SquareLowerLimit = buf[20];
919 ni->ins_SquareUpperLimit = buf[21];
920 ni->ins_SquareSpeed = buf[22];
921 ni->ins_FilterUpperLimit = buf[23]&0x3f;
922 ni->ins_PList.pls_Speed = buf[24];
923 ni->ins_PList.pls_Length = buf[25];
924
925 bptr = &buf[26];
926
927 if( ahxi )
928 {
929 for( i=0; i<ni->ins_PList.pls_Length; i++ )
930 {
931 k = (bptr[0]>>5)&7;
932 if( k == 6 ) k = 12;
933 if( k == 7 ) k = 15;
934 l = (bptr[0]>>2)&7;
935 if( l == 6 ) l = 12;
936 if( l == 7 ) l = 15;
937 ni->ins_PList.pls_Entries[i].ple_FX[1] = k;
938 ni->ins_PList.pls_Entries[i].ple_FX[0] = l;
939 ni->ins_PList.pls_Entries[i].ple_Waveform = ((bptr[0]<<1)&6) | (bptr[1]>>7);
940 ni->ins_PList.pls_Entries[i].ple_Fixed = (bptr[1]>>6)&1;
941 ni->ins_PList.pls_Entries[i].ple_Note = bptr[1]&0x3f;
942 ni->ins_PList.pls_Entries[i].ple_FXParam[0] = bptr[2];
943 ni->ins_PList.pls_Entries[i].ple_FXParam[1] = bptr[3];
944 bptr += 4;
945 }
946 } else {
947 for( i=0; i<ni->ins_PList.pls_Length; i++ )
948 {
949 ni->ins_PList.pls_Entries[i].ple_FX[0] = bptr[0]&0xf;
950 ni->ins_PList.pls_Entries[i].ple_FX[1] = (bptr[1]>>3)&0xf;
951 ni->ins_PList.pls_Entries[i].ple_Waveform = bptr[1]&7;
952 ni->ins_PList.pls_Entries[i].ple_Fixed = (bptr[2]>>6)&1;
953 ni->ins_PList.pls_Entries[i].ple_Note = bptr[2]&0x3f;
954 ni->ins_PList.pls_Entries[i].ple_FXParam[0] = bptr[3];
955 ni->ins_PList.pls_Entries[i].ple_FXParam[1] = bptr[4];
956 bptr += 5;
957 }
958 }
959
960 while( i < 256 )
961 {
962 ni->ins_PList.pls_Entries[i].ple_FX[0] = 0;
963 ni->ins_PList.pls_Entries[i].ple_FX[1] = 0;
964 ni->ins_PList.pls_Entries[i].ple_FXParam[0] = 0;
965 ni->ins_PList.pls_Entries[i].ple_FXParam[1] = 0;
966 ni->ins_PList.pls_Entries[i].ple_Waveform = 0;
967 ni->ins_PList.pls_Entries[i].ple_Fixed = 0;
968 ni->ins_PList.pls_Entries[i].ple_Note = 0;
969 i++;
970 }
971
972 ni->ins_ptop = 0;
973 ni->ins_pcurx = 0;
974 ni->ins_pcury = 0;
975
976 strncpy( ni->ins_Name, (TEXT *)bptr, 128 );
977
978 // printf( "Loaded '%s'!\n", ni->ins_Name );
979 }
980
rp_ahx_test(const struct ahx_tune * at)981 uint32 rp_ahx_test( const struct ahx_tune *at )
982 {
983 int32 i, j;
984 int32 hvlfeats;
985 const struct ahx_instrument *in;
986 const struct ahx_step *sp;
987
988 // First, check if the tune adheres to AHX limitations
989 hvlfeats = 0;
990
991 // >4 channels?
992 if( at->at_Channels > 4 ) hvlfeats |= SWF_MANYCHANS;
993
994 // Check instruments only use 1, 2, 3, 4, 5, C & F commands
995 for( i=1; i<64; i++ )
996 {
997 in = &at->at_Instruments[i];
998 for( j=0; j<in->ins_PList.pls_Length; j++ )
999 {
1000 switch( in->ins_PList.pls_Entries[j].ple_FX[0] )
1001 {
1002 case 0x6:
1003 case 0x7:
1004 case 0x8:
1005 case 0x9:
1006 case 0xa:
1007 case 0xb:
1008 case 0xd:
1009 case 0xe:
1010 hvlfeats |= SWF_NEWINSCMD;
1011 break;
1012 }
1013
1014 switch( in->ins_PList.pls_Entries[j].ple_FX[1] )
1015 {
1016 case 0x6:
1017 case 0x7:
1018 case 0x8:
1019 case 0x9:
1020 case 0xa:
1021 case 0xb:
1022 case 0xd:
1023 case 0xe:
1024 hvlfeats |= SWF_NEWINSCMD;
1025 break;
1026 }
1027
1028 if( hvlfeats & SWF_NEWINSCMD ) break;
1029 }
1030 }
1031
1032 // Check for double or new commands
1033 for( i=0; i<256; i++ )
1034 {
1035 for( j=0; j<at->at_TrackLength; j++ )
1036 {
1037 sp = &at->at_Tracks[i][j];
1038
1039 if( ( sp->stp_FX == 7 ) || ( sp->stp_FXb == 7 ) )
1040 hvlfeats |= SWF_PANCMD;
1041
1042 if( ((sp->stp_FX==0xe)&&((sp->stp_FXParam&0xf0)==0xf0)) ||
1043 ((sp->stp_FXb==0xe)&&((sp->stp_FXParam&0xf0)==0xf0)) )
1044 hvlfeats |= SWF_EFXCMD;
1045
1046 if( (( sp->stp_FX != 0 ) || ( sp->stp_FXParam != 0 )) &&
1047 (( sp->stp_FXb != 0 ) || ( sp->stp_FXbParam != 0 )) )
1048 hvlfeats |= SWF_DOUBLECMD;
1049 }
1050
1051 if( (hvlfeats & (SWF_PANCMD|SWF_EFXCMD|SWF_DOUBLECMD)) == (SWF_PANCMD|SWF_EFXCMD|SWF_DOUBLECMD) )
1052 break;
1053 }
1054
1055 return hvlfeats;
1056 }
1057
rp_save_hvl(const TEXT * name,struct ahx_tune * at)1058 void rp_save_hvl( const TEXT *name, struct ahx_tune *at )
1059 {
1060 FILE *fh;
1061 int32 i, j, k, tbl;
1062 int32 minver;
1063 uint8 emptytrk;
1064 uint8 *tbf;
1065 const struct ahx_instrument *in;
1066 #ifdef __SDL_WRAPPER__
1067 char mkname[4096];
1068 #endif
1069
1070 if( at == NULL ) return;
1071
1072 #ifdef __SDL_WRAPPER__
1073 // Enforce file extension since windows likes them so much
1074 // (although let them use a prefix if they want to keep it oldskool)
1075 if (strncasecmp(name, "hvl.", 4) != 0)
1076 {
1077 // No prefix...
1078 i = strlen(name);
1079 if ((i < 4) || (strcasecmp(&name[i-4], ".hvl") != 0))
1080 {
1081 // No extension
1082 strncpy(mkname, name, 4096);
1083 strncat(mkname, ".hvl", 4096);
1084 mkname[4095] = 0;
1085 name = mkname;
1086 }
1087 }
1088 #endif
1089
1090 // Calculate TrackNr
1091 at->at_TrackNr = 0;
1092 for( i=0; i<at->at_PositionNr; i++ )
1093 for( j=0; j<at->at_Channels; j++ )
1094 if( at->at_Positions[i].pos_Track[j] > at->at_TrackNr )
1095 at->at_TrackNr = at->at_Positions[i].pos_Track[j];
1096 if( at->at_TrackNr == 0 ) at->at_TrackNr = 1;
1097
1098 // Calculate InstrumentNr
1099 at->at_InstrumentNr = 0;
1100 for( i=1; i<64; i++ )
1101 if( at->at_Instruments[i].ins_PList.pls_Length > 0 )
1102 at->at_InstrumentNr = i;
1103
1104 emptytrk = 0x80;
1105 for( i=0; i<at->at_TrackLength; i++ )
1106 if( ( at->at_Tracks[0][i].stp_Note != 0 ) ||
1107 ( at->at_Tracks[0][i].stp_Instrument != 0 ) ||
1108 ( at->at_Tracks[0][i].stp_FX != 0 ) ||
1109 ( at->at_Tracks[0][i].stp_FXParam != 0 ) ||
1110 ( at->at_Tracks[0][i].stp_FXb != 0 ) ||
1111 ( at->at_Tracks[0][i].stp_FXbParam != 0 ) )
1112 emptytrk = 0;
1113
1114 // Calculate names offset
1115 tbl = 16;
1116 tbl += at->at_SubsongNr * 2;
1117 tbl += at->at_PositionNr * at->at_Channels * 2;
1118
1119 minver = 0;
1120 for( i=0; i<=at->at_TrackNr; i++ )
1121 {
1122 if( ( emptytrk != 0 ) && ( i == 0 ) )
1123 continue;
1124
1125 k = 0;
1126 for( j=0; j<at->at_TrackLength; j++ )
1127 {
1128 if( ( at->at_Tracks[i][j].stp_FX == 0xe ) &&
1129 ( (at->at_Tracks[i][j].stp_FXParam&0xf0) == 0xf0 ) &&
1130 ( minver < 1 ) )
1131 minver = 1;
1132 if( ( at->at_Tracks[i][j].stp_FXb == 0xe ) &&
1133 ( (at->at_Tracks[i][j].stp_FXbParam&0xf0) == 0xf0 ) &&
1134 ( minver < 1 ) )
1135 minver = 1;
1136
1137 if( ( at->at_Tracks[i][j].stp_Note == 0 ) &&
1138 ( at->at_Tracks[i][j].stp_Instrument == 0 ) &&
1139 ( at->at_Tracks[i][j].stp_FX == 0 ) &&
1140 ( at->at_Tracks[i][j].stp_FXParam == 0 ) &&
1141 ( at->at_Tracks[i][j].stp_FXb == 0 ) &&
1142 ( at->at_Tracks[i][j].stp_FXbParam == 0 ) )
1143 k++;
1144 else
1145 k+=5;
1146 }
1147 tbl += k;
1148 }
1149
1150 for( i=1; i<=at->at_InstrumentNr; i++ )
1151 tbl += 22 + at->at_Instruments[i].ins_PList.pls_Length*5;
1152
1153 tbf = IExec->AllocPooled( rp_mempool, tbl );
1154 if( !tbf )
1155 {
1156 printf( "Out of memory @ %s:%d\n", __FILE__, __LINE__ );
1157 return;
1158 }
1159
1160 fh = fopen( name, "wb" );
1161 if( !fh )
1162 {
1163 IExec->FreePooled( rp_mempool, tbf, tbl );
1164 return;
1165 }
1166
1167 strcpy( (TEXT *)tbf, "HVL" );
1168
1169 tbf[3] = minver;
1170 tbf[4] = (tbl >> 8)&0xff;
1171 tbf[5] = tbl&0xff;
1172 tbf[6] = (at->at_PositionNr>>8);
1173 tbf[6] |= ((at->at_SpeedMultiplier-1)&3)<<5;
1174 tbf[6] |= emptytrk;
1175 tbf[7] = at->at_PositionNr & 0xff;
1176 tbf[8] = (at->at_Channels-4)<<2;
1177 tbf[8] |= (at->at_Restart>>8)&0x3;
1178 tbf[9] = at->at_Restart&0xff;
1179 tbf[10] = at->at_TrackLength;
1180 tbf[11] = at->at_TrackNr;
1181 tbf[12] = at->at_InstrumentNr;
1182 tbf[13] = at->at_SubsongNr;
1183 tbf[14] = at->at_mixgainP;
1184 tbf[15] = at->at_defstereo;
1185 fwrite( tbf, 16, 1, fh );
1186
1187 // Subsongs
1188 if( at->at_SubsongNr > 0 )
1189 {
1190 for( i=0, k=0; i<at->at_SubsongNr; i++ )
1191 {
1192 tbf[k++] = at->at_Subsongs[i]>>8;
1193 tbf[k++] = at->at_Subsongs[i]&0xff;
1194 }
1195 fwrite( tbf, k, 1, fh );
1196 }
1197
1198 // Position list
1199 for( i=0, k=0; i<at->at_PositionNr; i++ )
1200 {
1201 for( j=0; j<at->at_Channels; j++ )
1202 {
1203 tbf[k++] = at->at_Positions[i].pos_Track[j];
1204 tbf[k++] = at->at_Positions[i].pos_Transpose[j];
1205 }
1206 }
1207 fwrite( tbf, k, 1, fh );
1208
1209 // Tracks
1210 for( i=0, k=0; i<=at->at_TrackNr; i++ )
1211 {
1212 if( ( emptytrk != 0 ) && ( i == 0 ) )
1213 continue;
1214
1215 for( j=0; j<at->at_TrackLength; j++ )
1216 {
1217 if( ( at->at_Tracks[i][j].stp_Note == 0 ) &&
1218 ( at->at_Tracks[i][j].stp_Instrument == 0 ) &&
1219 ( at->at_Tracks[i][j].stp_FX == 0 ) &&
1220 ( at->at_Tracks[i][j].stp_FXParam == 0 ) &&
1221 ( at->at_Tracks[i][j].stp_FXb == 0 ) &&
1222 ( at->at_Tracks[i][j].stp_FXbParam == 0 ) )
1223 {
1224 tbf[k++] = 0x3f;
1225 continue;
1226 }
1227
1228 tbf[k++] = at->at_Tracks[i][j].stp_Note;
1229 tbf[k++] = at->at_Tracks[i][j].stp_Instrument;
1230 tbf[k] = (at->at_Tracks[i][j].stp_FX&0xf)<<4;
1231 tbf[k++] |= (at->at_Tracks[i][j].stp_FXb&0xf);
1232 tbf[k++] = at->at_Tracks[i][j].stp_FXParam;
1233 tbf[k++] = at->at_Tracks[i][j].stp_FXbParam;
1234 }
1235 }
1236 fwrite( tbf, k, 1, fh );
1237
1238 // Instruments
1239 for( i=1; i<=at->at_InstrumentNr; i++ )
1240 {
1241 in = &at->at_Instruments[i];
1242 k = 0;
1243 tbf[0] = in->ins_Volume;
1244 tbf[1] = (in->ins_FilterSpeed&0x1f)<<3;
1245 tbf[1] |= in->ins_WaveLength&0x7;
1246 tbf[2] = in->ins_Envelope.aFrames;
1247 tbf[3] = in->ins_Envelope.aVolume;
1248 tbf[4] = in->ins_Envelope.dFrames;
1249 tbf[5] = in->ins_Envelope.dVolume;
1250 tbf[6] = in->ins_Envelope.sFrames;
1251 tbf[7] = in->ins_Envelope.rFrames;
1252 tbf[8] = in->ins_Envelope.rVolume;
1253 tbf[9] = 0;
1254 tbf[10] = 0;
1255 tbf[11] = 0;
1256 tbf[12] = (in->ins_FilterSpeed&0x20)<<2;
1257 tbf[12] |= in->ins_FilterLowerLimit&0x7f;
1258 tbf[13] = in->ins_VibratoDelay;
1259 tbf[14] = (in->ins_HardCutReleaseFrames&0x07)<<4;
1260 tbf[14] |= (in->ins_HardCutRelease&1)<<7;
1261 tbf[14] |= in->ins_VibratoDepth&0x0f;
1262 tbf[15] = in->ins_VibratoSpeed;
1263 tbf[16] = in->ins_SquareLowerLimit;
1264 tbf[17] = in->ins_SquareUpperLimit;
1265 tbf[18] = in->ins_SquareSpeed;
1266 tbf[19] = in->ins_FilterUpperLimit&0x3f;
1267 tbf[20] = in->ins_PList.pls_Speed;
1268 tbf[21] = in->ins_PList.pls_Length;
1269 fwrite( tbf, 22, 1, fh );
1270
1271 for( j=0, k=0; j<in->ins_PList.pls_Length; j++ )
1272 {
1273 tbf[k++] = in->ins_PList.pls_Entries[j].ple_FX[0]&0xf;
1274 tbf[k] = (in->ins_PList.pls_Entries[j].ple_FX[1]&0xf)<<3;
1275 tbf[k++] |= in->ins_PList.pls_Entries[j].ple_Waveform&7;
1276 tbf[k] = (in->ins_PList.pls_Entries[j].ple_Fixed&1)<<6;
1277 tbf[k++] |= in->ins_PList.pls_Entries[j].ple_Note&0x3f;
1278 tbf[k++] = in->ins_PList.pls_Entries[j].ple_FXParam[0];
1279 tbf[k++] = in->ins_PList.pls_Entries[j].ple_FXParam[1];
1280 }
1281 fwrite( tbf, k, 1, fh );
1282 }
1283
1284 fwrite( at->at_Name, strlen( at->at_Name )+1, 1, fh );
1285 for( i=1; i<=at->at_InstrumentNr; i++ )
1286 fwrite( at->at_Instruments[i].ins_Name, strlen( at->at_Instruments[i].ins_Name )+1, 1, fh );
1287
1288 fclose( fh );
1289 IExec->FreePooled( rp_mempool, tbf, tbl );
1290 }
1291
rp_save_ahx(const TEXT * name,struct ahx_tune * at)1292 void rp_save_ahx( const TEXT *name, struct ahx_tune *at )
1293 {
1294 FILE *fh;
1295 int32 i, j, k, l, m, tbl;
1296 uint8 emptytrk;
1297 uint8 *tbf;
1298 const struct ahx_instrument *in;
1299 #ifdef __SDL_WRAPPER__
1300 char mkname[4096];
1301 #endif
1302
1303 if( at == NULL ) return;
1304
1305 #ifdef __SDL_WRAPPER__
1306 // Enforce file extension since windows likes them so much
1307 // (although let them use a prefix if they want to keep it oldskool)
1308 if ((strncasecmp(name, "ahx.", 4) != 0) &&
1309 (strncasecmp(name, "thx.", 4) != 0))
1310 {
1311 // No prefix...
1312 i = strlen(name);
1313 if ((i < 4) ||
1314 ((strcasecmp(&name[i-4], ".ahx") != 0) &&
1315 (strcasecmp(&name[i-4], ".thx") != 0)))
1316 {
1317 // No extension
1318 strncpy(mkname, name, 4096);
1319 strncat(mkname, ".ahx", 4096);
1320 mkname[4095] = 0;
1321 name = mkname;
1322 }
1323 }
1324 #endif
1325
1326 // Calculate TrackNr
1327 at->at_TrackNr = 0;
1328 for( i=0; i<at->at_PositionNr; i++ )
1329 for( j=0; j<4; j++ )
1330 if( at->at_Positions[i].pos_Track[j] > at->at_TrackNr )
1331 at->at_TrackNr = at->at_Positions[i].pos_Track[j];
1332 if( at->at_TrackNr == 0 ) at->at_TrackNr = 1;
1333
1334 // Calculate InstrumentNr
1335 at->at_InstrumentNr = 0;
1336 for( i=1; i<64; i++ )
1337 if( at->at_Instruments[i].ins_PList.pls_Length > 0 )
1338 at->at_InstrumentNr = i;
1339
1340 emptytrk = 0x80;
1341 for( i=0; i<at->at_TrackLength; i++ )
1342 if( ( at->at_Tracks[0][i].stp_Note != 0 ) ||
1343 ( at->at_Tracks[0][i].stp_Instrument != 0 ) ||
1344 ( at->at_Tracks[0][i].stp_FX != 0 ) ||
1345 ( at->at_Tracks[0][i].stp_FXParam != 0 ) ||
1346 ( at->at_Tracks[0][i].stp_FXb != 0 ) ||
1347 ( at->at_Tracks[0][i].stp_FXbParam != 0 ) )
1348 emptytrk = 0;
1349
1350 // Calculate names offset
1351 tbl = 14;
1352 tbl += at->at_SubsongNr * 2;
1353 tbl += at->at_PositionNr * 8;
1354 tbl += (at->at_TrackNr+1) * at->at_TrackLength * 3;
1355
1356 for( i=1; i<=at->at_InstrumentNr; i++ )
1357 tbl += 22 + at->at_Instruments[i].ins_PList.pls_Length*4;
1358
1359 if( emptytrk != 0 ) tbl -= at->at_TrackLength * 3;
1360
1361 tbf = IExec->AllocPooled( rp_mempool, tbl );
1362 if( !tbf )
1363 {
1364 printf( "Out of memory @ %s:%d\n", __FILE__, __LINE__ );
1365 return;
1366 }
1367
1368 fh = fopen( name, "wb" );
1369 if( !fh )
1370 {
1371 IExec->FreePooled( rp_mempool, tbf, tbl );
1372 return;
1373 }
1374
1375 strcpy( (TEXT *)tbf, "THX\1" );
1376
1377 tbf[4] = (tbl >> 8)&0xff;
1378 tbf[5] = tbl&0xff;
1379 tbf[6] = (at->at_PositionNr>>8);
1380 tbf[6] |= ((at->at_SpeedMultiplier-1)&3)<<5;
1381 tbf[6] |= emptytrk;
1382 tbf[7] = at->at_PositionNr & 0xff;
1383 tbf[8] = at->at_Restart>>8;
1384 tbf[9] = at->at_Restart&0xff;
1385 tbf[10] = at->at_TrackLength;
1386 tbf[11] = at->at_TrackNr;
1387 tbf[12] = at->at_InstrumentNr;
1388 tbf[13] = at->at_SubsongNr;
1389 fwrite( tbf, 14, 1, fh );
1390
1391 // Subsongs
1392 if( at->at_SubsongNr > 0 )
1393 {
1394 for( i=0, k=0; i<at->at_SubsongNr; i++ )
1395 {
1396 tbf[k++] = at->at_Subsongs[i]>>8;
1397 tbf[k++] = at->at_Subsongs[i]&0xff;
1398 }
1399 fwrite( tbf, k, 1, fh );
1400 }
1401
1402 // Position list
1403 for( i=0, k=0; i<at->at_PositionNr; i++ )
1404 {
1405 for( j=0; j<4; j++ )
1406 {
1407 tbf[k++] = at->at_Positions[i].pos_Track[j];
1408 tbf[k++] = at->at_Positions[i].pos_Transpose[j];
1409 }
1410 }
1411 fwrite( tbf, k, 1, fh );
1412
1413 // Tracks
1414 for( i=0, k=0; i<=at->at_TrackNr; i++ )
1415 {
1416 if( ( emptytrk != 0 ) && ( i == 0 ) )
1417 continue;
1418
1419 for( j=0; j<at->at_TrackLength; j++ )
1420 {
1421 tbf[k] = (at->at_Tracks[i][j].stp_Note&0x3f)<<2;
1422 tbf[k++] |= (at->at_Tracks[i][j].stp_Instrument>>4)&0x3;
1423 tbf[k] = (at->at_Tracks[i][j].stp_Instrument&0xf)<<4;
1424
1425 if( ( at->at_Tracks[i][j].stp_FX != 0 ) ||
1426 ( at->at_Tracks[i][j].stp_FXParam != 0 ) )
1427 {
1428 tbf[k++] |= at->at_Tracks[i][j].stp_FX & 0xf;
1429 tbf[k++] = at->at_Tracks[i][j].stp_FXParam;
1430 } else {
1431 tbf[k++] |= at->at_Tracks[i][j].stp_FXb & 0xf;
1432 tbf[k++] = at->at_Tracks[i][j].stp_FXbParam;
1433 }
1434 }
1435 }
1436 fwrite( tbf, k, 1, fh );
1437
1438 // Instruments
1439 for( i=1; i<=at->at_InstrumentNr; i++ )
1440 {
1441 in = &at->at_Instruments[i];
1442 k = 0;
1443 tbf[0] = in->ins_Volume;
1444 tbf[1] = (in->ins_FilterSpeed&0x1f)<<3;
1445 tbf[1] |= in->ins_WaveLength&0x7;
1446 tbf[2] = in->ins_Envelope.aFrames;
1447 tbf[3] = in->ins_Envelope.aVolume;
1448 tbf[4] = in->ins_Envelope.dFrames;
1449 tbf[5] = in->ins_Envelope.dVolume;
1450 tbf[6] = in->ins_Envelope.sFrames;
1451 tbf[7] = in->ins_Envelope.rFrames;
1452 tbf[8] = in->ins_Envelope.rVolume;
1453 tbf[9] = 0;
1454 tbf[10] = 0;
1455 tbf[11] = 0;
1456 tbf[12] = (in->ins_FilterSpeed&0x20)<<2;
1457 tbf[12] |= in->ins_FilterLowerLimit&0x7f;
1458 tbf[13] = in->ins_VibratoDelay;
1459 tbf[14] = (in->ins_HardCutReleaseFrames&0x07)<<4;
1460 tbf[14] |= (in->ins_HardCutRelease&1)<<7;
1461 tbf[14] |= in->ins_VibratoDepth&0x0f;
1462 tbf[15] = in->ins_VibratoSpeed;
1463 tbf[16] = in->ins_SquareLowerLimit;
1464 tbf[17] = in->ins_SquareUpperLimit;
1465 tbf[18] = in->ins_SquareSpeed;
1466 tbf[19] = in->ins_FilterUpperLimit&0x3f;
1467 tbf[20] = in->ins_PList.pls_Speed;
1468 tbf[21] = in->ins_PList.pls_Length;
1469 fwrite( tbf, 22, 1, fh );
1470
1471 for( j=0, k=0; j<in->ins_PList.pls_Length; j++ )
1472 {
1473 l = in->ins_PList.pls_Entries[j].ple_FX[1];
1474 if( l == 12 ) l = 6;
1475 if( l == 15 ) l = 7;
1476 m = in->ins_PList.pls_Entries[j].ple_FX[0];
1477 if( m == 12 ) m = 6;
1478 if( m == 15 ) m = 7;
1479
1480 tbf[k] = (l&7)<<5;
1481 tbf[k] |= (m&7)<<2;
1482 tbf[k++] |= (in->ins_PList.pls_Entries[j].ple_Waveform&6)>>1;
1483 tbf[k] = (in->ins_PList.pls_Entries[j].ple_Waveform&1)<<7;
1484 tbf[k] |= (in->ins_PList.pls_Entries[j].ple_Fixed&1)<<6;
1485 tbf[k++] |= in->ins_PList.pls_Entries[j].ple_Note&0x3f;
1486 tbf[k++] = in->ins_PList.pls_Entries[j].ple_FXParam[0];
1487 tbf[k++] = in->ins_PList.pls_Entries[j].ple_FXParam[1];
1488 }
1489 fwrite( tbf, k, 1, fh );
1490 }
1491
1492 fwrite( at->at_Name, strlen( at->at_Name )+1, 1, fh );
1493 for( i=1; i<=at->at_InstrumentNr; i++ )
1494 fwrite( at->at_Instruments[i].ins_Name, strlen( at->at_Instruments[i].ins_Name )+1, 1, fh );
1495
1496 fclose( fh );
1497 IExec->FreePooled( rp_mempool, tbf, tbl );
1498 }
1499
rp_load_ahx(struct ahx_tune * at,uint8 * buf,uint32 buflen,BOOL passed)1500 struct ahx_tune *rp_load_ahx( struct ahx_tune *at, uint8 *buf, uint32 buflen, BOOL passed )
1501 {
1502 const uint8 *bptr;
1503 const TEXT *nptr;
1504 uint32 i, j, k, l;
1505
1506 at->at_PositionNr = ((buf[6]&0x0f)<<8)|buf[7];
1507 at->at_Restart = (buf[8]<<8)|buf[9];
1508 at->at_SpeedMultiplier = ((buf[6]>>5)&3)+1;
1509 at->at_TrackLength = buf[10];
1510 at->at_TrackNr = buf[11];
1511 at->at_InstrumentNr = buf[12];
1512 at->at_SubsongNr = buf[13];
1513
1514 if( at->at_Restart >= at->at_PositionNr )
1515 at->at_Restart = at->at_PositionNr-1;
1516
1517 // Do some validation
1518 if( ( at->at_PositionNr > 1000 ) ||
1519 ( at->at_TrackLength > 64 ) ||
1520 ( at->at_InstrumentNr > 64 ) )
1521 {
1522 printf( "%d,%d,%d\n", at->at_PositionNr,
1523 at->at_TrackLength,
1524 at->at_InstrumentNr );
1525 if( passed )
1526 rp_clear_tune( at );
1527 else
1528 rp_free_tune( at );
1529 IExec->FreePooled( rp_mempool, buf, buflen );
1530 printf( "Invalid file.\n" );
1531 return NULL;
1532 }
1533
1534 strncpy( at->at_Name, (TEXT *)&buf[(buf[4]<<8)|buf[5]], 128 );
1535 nptr = (TEXT *)&buf[((buf[4]<<8)|buf[5])+strlen( at->at_Name )+1];
1536
1537 bptr = &buf[14];
1538
1539 // Subsongs
1540 for( i=0; i<at->at_SubsongNr; i++ )
1541 {
1542 at->at_Subsongs[i] = (bptr[0]<<8)|bptr[1];
1543 bptr += 2;
1544 }
1545
1546 // Position list
1547 for( i=0; i<at->at_PositionNr; i++ )
1548 {
1549 for( j=0; j<4; j++ )
1550 {
1551 at->at_Positions[i].pos_Track[j] = *bptr++;
1552 at->at_Positions[i].pos_Transpose[j] = *(int8 *)bptr++;
1553 }
1554 }
1555
1556 // Tracks
1557 for( i=0; i<=at->at_TrackNr; i++ )
1558 {
1559 // rp_new_tune() clears it anyway
1560 if( ( ( buf[6]&0x80 ) == 0x80 ) && ( i == 0 ) )
1561 continue;
1562
1563 for( j=0; j<at->at_TrackLength; j++ )
1564 {
1565 at->at_Tracks[i][j].stp_Note = (bptr[0]>>2)&0x3f;
1566 at->at_Tracks[i][j].stp_Instrument = ((bptr[0]&0x3)<<4) | (bptr[1]>>4);
1567 at->at_Tracks[i][j].stp_FX = bptr[1]&0xf;
1568 at->at_Tracks[i][j].stp_FXParam = bptr[2];
1569 at->at_Tracks[i][j].stp_FXb = 0;
1570 at->at_Tracks[i][j].stp_FXbParam = 0;
1571 bptr += 3;
1572 }
1573 }
1574
1575 // Instruments
1576 for( i=1; i<=at->at_InstrumentNr; i++ )
1577 {
1578 if( nptr < (TEXT *)(buf+buflen) )
1579 {
1580 strncpy( at->at_Instruments[i].ins_Name, nptr, 128 );
1581 nptr += strlen( nptr )+1;
1582 } else {
1583 at->at_Instruments[i].ins_Name[0] = 0;
1584 }
1585
1586 at->at_Instruments[i].ins_Volume = bptr[0];
1587 at->at_Instruments[i].ins_FilterSpeed = ((bptr[1]>>3)&0x1f)|((bptr[12]>>2)&0x20);
1588 at->at_Instruments[i].ins_WaveLength = bptr[1]&0x07;
1589
1590 at->at_Instruments[i].ins_Envelope.aFrames = bptr[2];
1591 at->at_Instruments[i].ins_Envelope.aVolume = bptr[3];
1592 at->at_Instruments[i].ins_Envelope.dFrames = bptr[4];
1593 at->at_Instruments[i].ins_Envelope.dVolume = bptr[5];
1594 at->at_Instruments[i].ins_Envelope.sFrames = bptr[6];
1595 at->at_Instruments[i].ins_Envelope.rFrames = bptr[7];
1596 at->at_Instruments[i].ins_Envelope.rVolume = bptr[8];
1597
1598 at->at_Instruments[i].ins_FilterLowerLimit = bptr[12]&0x7f;
1599 at->at_Instruments[i].ins_VibratoDelay = bptr[13];
1600 at->at_Instruments[i].ins_HardCutReleaseFrames = (bptr[14]>>4)&0x07;
1601 at->at_Instruments[i].ins_HardCutRelease = bptr[14]&0x80?1:0;
1602 at->at_Instruments[i].ins_VibratoDepth = bptr[14]&0x0f;
1603 at->at_Instruments[i].ins_VibratoSpeed = bptr[15];
1604 at->at_Instruments[i].ins_SquareLowerLimit = bptr[16];
1605 at->at_Instruments[i].ins_SquareUpperLimit = bptr[17];
1606 at->at_Instruments[i].ins_SquareSpeed = bptr[18];
1607 at->at_Instruments[i].ins_FilterUpperLimit = bptr[19]&0x3f;
1608 at->at_Instruments[i].ins_PList.pls_Speed = bptr[20];
1609 at->at_Instruments[i].ins_PList.pls_Length = bptr[21];
1610
1611 bptr += 22;
1612 for( j=0; j<at->at_Instruments[i].ins_PList.pls_Length; j++ )
1613 {
1614 k = (bptr[0]>>5)&7;
1615 if( k == 6 ) k = 12;
1616 if( k == 7 ) k = 15;
1617 l = (bptr[0]>>2)&7;
1618 if( l == 6 ) l = 12;
1619 if( l == 7 ) l = 15;
1620 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_FX[1] = k;
1621 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_FX[0] = l;
1622 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_Waveform = ((bptr[0]<<1)&6) | (bptr[1]>>7);
1623 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_Fixed = (bptr[1]>>6)&1;
1624 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_Note = bptr[1]&0x3f;
1625 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_FXParam[0] = bptr[2];
1626 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_FXParam[1] = bptr[3];
1627
1628 // 1.6: Strip "toggle filter" commands if the module is
1629 // version 0 (pre-filters). This is what AHX also does.
1630 if( ( buf[3] == 0 ) && ( l == 4 ) && ( (bptr[2]&0xf0) != 0 ) )
1631 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_FXParam[0] &= 0x0f;
1632 if( ( buf[3] == 0 ) && ( k == 4 ) && ( (bptr[3]&0xf0) != 0 ) )
1633 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_FXParam[1] &= 0x0f;
1634
1635 bptr += 4;
1636 }
1637
1638 while( j < 256 )
1639 {
1640 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_FX[0] = 0;
1641 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_FX[1] = 0;
1642 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_FXParam[0] = 0;
1643 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_FXParam[1] = 0;
1644 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_Waveform = 0;
1645 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_Fixed = 0;
1646 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_Note = 0;
1647 j++;
1648 }
1649 at->at_Instruments[i].ins_ptop = 0;
1650 at->at_Instruments[i].ins_pcurx = 0;
1651 at->at_Instruments[i].ins_pcury = 0;
1652 }
1653
1654 if( !passed )
1655 {
1656 IExec->ObtainSemaphore( rp_list_ss );
1657 IExec->AddTail( rp_tunelist, (struct Node *)at );
1658 IExec->ReleaseSemaphore( rp_list_ss );
1659 }
1660
1661 rp_init_subsong( at, 0 );
1662 IExec->FreePooled( rp_mempool, buf, buflen );
1663 return at;
1664 }
1665
rp_mod_import(struct ahx_tune * at,uint8 * buf,uint32 buflen,BOOL passed)1666 struct ahx_tune *rp_mod_import( struct ahx_tune *at, uint8 *buf, uint32 buflen, BOOL passed )
1667 {
1668 int32 i, j, k, l;
1669 int32 cv_pos, cv_row, cv_chan;
1670
1671 rp_clear_tune( at );
1672
1673 if( strncmp( (TEXT *)&buf[1080], "M.K.", 4 ) != 0 )
1674 {
1675 if( passed )
1676 rp_clear_tune( at );
1677 else
1678 rp_free_tune( at );
1679 IExec->FreePooled( rp_mempool, buf, buflen );
1680 printf( "Invalid file.\n" );
1681 return NULL;
1682 }
1683
1684 for( i=0; i<20; i++ )
1685 {
1686 if( buf[i] == 0 ) break;
1687 at->at_Name[i] = buf[i];
1688 }
1689 at->at_Name[i] = 0;
1690
1691 for( k=1,j=20; k<32; k++,j+=30 )
1692 {
1693 for( i=0; i<22; i++ )
1694 {
1695 if( buf[j+i] == 0 ) break;
1696 at->at_Instruments[k].ins_Name[i] = buf[j+i];
1697 }
1698 at->at_Instruments[k].ins_Name[i] = 0;
1699
1700 if( ((buf[j+22]<<8)|(buf[j+23])) != 0 )
1701 {
1702 at->at_Instruments[k].ins_Volume = 64;
1703 at->at_Instruments[k].ins_WaveLength = 5;
1704 at->at_Instruments[k].ins_FilterLowerLimit = 1;
1705 at->at_Instruments[k].ins_FilterUpperLimit = 31;
1706 at->at_Instruments[k].ins_FilterSpeed = 0;
1707 at->at_Instruments[k].ins_SquareLowerLimit = 32;
1708 at->at_Instruments[k].ins_SquareUpperLimit = 63;
1709 at->at_Instruments[k].ins_SquareSpeed = 1;
1710 at->at_Instruments[k].ins_VibratoDelay = 0;
1711 at->at_Instruments[k].ins_VibratoDepth = 0;
1712 at->at_Instruments[k].ins_VibratoSpeed = 0;
1713 at->at_Instruments[k].ins_HardCutRelease = 0;
1714 at->at_Instruments[k].ins_HardCutReleaseFrames = 0;
1715 at->at_Instruments[k].ins_Envelope.aFrames = 1;
1716 at->at_Instruments[k].ins_Envelope.aVolume = 64;
1717 at->at_Instruments[k].ins_Envelope.dFrames = 1;
1718 at->at_Instruments[k].ins_Envelope.dVolume = 64;
1719 at->at_Instruments[k].ins_Envelope.sFrames = 1;
1720 at->at_Instruments[k].ins_Envelope.rFrames = 1;
1721 at->at_Instruments[k].ins_Envelope.rVolume = 64;
1722 at->at_Instruments[k].ins_Envelope.aFrames = 1;
1723 at->at_Instruments[k].ins_PList.pls_Speed = 1;
1724 at->at_Instruments[k].ins_PList.pls_Length = 1;
1725 at->at_Instruments[k].ins_PList.pls_Entries[0].ple_Note = 1;
1726 at->at_Instruments[k].ins_PList.pls_Entries[0].ple_Waveform = 2;
1727 at->at_Instruments[k].ins_PList.pls_Entries[0].ple_Fixed = 0;
1728 at->at_Instruments[k].ins_PList.pls_Entries[0].ple_FX[0] = 0;
1729 at->at_Instruments[k].ins_PList.pls_Entries[0].ple_FXParam[0] = 0;
1730 at->at_Instruments[k].ins_PList.pls_Entries[0].ple_FX[1] = 0;
1731 at->at_Instruments[k].ins_PList.pls_Entries[0].ple_FXParam[1] = 0;
1732 }
1733 }
1734
1735 at->at_PositionNr = buf[950];
1736 k=0;
1737 for( i=0; i<128; i++ )
1738 {
1739 if( i < at->at_PositionNr )
1740 {
1741 at->at_Positions[i].pos_Track[0] = buf[i+952]*4;
1742 at->at_Positions[i].pos_Track[1] = buf[i+952]*4+1;
1743 at->at_Positions[i].pos_Track[2] = buf[i+952]*4+2;
1744 at->at_Positions[i].pos_Track[3] = buf[i+952]*4+3;
1745 }
1746 if( buf[i+952] > k )
1747 k = buf[i+952];
1748 }
1749
1750 i = 1084;
1751 for( cv_pos=0; cv_pos<=k; cv_pos++ )
1752 {
1753 for( cv_row=0; cv_row<64; cv_row++ )
1754 {
1755 for( cv_chan=0; cv_chan<4; cv_chan++ )
1756 {
1757 l = ((buf[i]&0xf)<<8)|buf[i+1];
1758 for( j=0; j<37; j++ ) if( pt_import_period_tab[j] == l ) break;
1759 if( j < 37 )
1760 at->at_Tracks[cv_pos*4+cv_chan][cv_row].stp_Note = j;
1761 at->at_Tracks[cv_pos*4+cv_chan][cv_row].stp_Instrument = (buf[i]&0xf0)|((buf[i+2]>>4)&0xf);
1762 l = buf[i+2]&0xf;
1763 switch( l )
1764 {
1765 case 0x1:
1766 case 0x2:
1767 case 0x3:
1768 case 0x5:
1769 case 0xa:
1770 case 0xb:
1771 case 0xc:
1772 case 0xd:
1773 at->at_Tracks[cv_pos*4+cv_chan][cv_row].stp_FX = l;
1774 at->at_Tracks[cv_pos*4+cv_chan][cv_row].stp_FXParam = buf[i+3];
1775 break;
1776
1777 case 0xe:
1778 switch( (buf[i+3]>>4)&0xf )
1779 {
1780 case 0x1:
1781 case 0x2:
1782 case 0xa:
1783 case 0xb:
1784 case 0xc:
1785 case 0xd:
1786 at->at_Tracks[cv_pos*4+cv_chan][cv_row].stp_FX = l;
1787 at->at_Tracks[cv_pos*4+cv_chan][cv_row].stp_FXParam = buf[i+3];
1788 break;
1789 }
1790 break;
1791
1792 case 0xf:
1793 if( buf[i+3] >= 0x20 ) break;
1794 at->at_Tracks[cv_pos*4+cv_chan][cv_row].stp_FX = l;
1795 at->at_Tracks[cv_pos*4+cv_chan][cv_row].stp_FXParam = buf[i+3];
1796 break;
1797 }
1798
1799 i+=4;
1800 }
1801 }
1802 }
1803
1804 if( !passed )
1805 {
1806 IExec->ObtainSemaphore( rp_list_ss );
1807 IExec->AddTail( rp_tunelist, (struct Node *)at );
1808 IExec->ReleaseSemaphore( rp_list_ss );
1809 }
1810
1811 rp_init_subsong( at, 0 );
1812 IExec->FreePooled( rp_mempool, buf, buflen );
1813 return at;
1814 }
1815
rp_load_tune(const TEXT * name,struct ahx_tune * at)1816 struct ahx_tune *rp_load_tune( const TEXT *name, struct ahx_tune *at )
1817 {
1818 uint8 *buf;
1819 const uint8 *bptr;
1820 const TEXT *nptr;
1821 uint32 buflen, i, j;
1822 FILE *fh;
1823 BOOL passed;
1824
1825 if( at )
1826 {
1827 rp_clear_tune( at );
1828 passed = TRUE;
1829 } else {
1830 at = rp_new_tune( FALSE );
1831 if( !at )
1832 {
1833 printf( "Out of memory @ %s:%d\n", __FILE__, __LINE__ );
1834 return NULL;
1835 }
1836 passed = FALSE;
1837 }
1838
1839 fh = fopen(name, "rb");
1840 if (!fh)
1841 {
1842 if( !passed ) rp_free_tune( at );
1843 printf( "Can't open file\n" );
1844 return NULL;
1845 }
1846
1847 fseek(fh, 0, SEEK_END);
1848 buflen = ftell(fh);
1849 fseek(fh, 0, SEEK_SET);
1850
1851 buf = IExec->AllocPooled( rp_mempool, buflen );
1852 if( !buf )
1853 {
1854 if( !passed ) rp_free_tune( at );
1855 fclose(fh);
1856 printf( "Out of memory @ %s:%d\n", __FILE__, __LINE__ );
1857 return NULL;
1858 }
1859
1860 if( fread( buf, buflen, 1, fh ) != 1 )
1861 {
1862 if( !passed ) rp_free_tune( at );
1863 fclose(fh);
1864 printf( "Unable to read from file!\n" );
1865 return NULL;
1866 }
1867 fclose(fh);
1868
1869 if( ( buf[0] == 'T' ) &&
1870 ( buf[1] == 'H' ) &&
1871 ( buf[2] == 'X' ) &&
1872 ( buf[3] < 3 ) )
1873 return rp_load_ahx( at, buf, buflen, passed );
1874
1875 if( ( buf[0] != 'H' ) ||
1876 ( buf[1] != 'V' ) ||
1877 ( buf[2] != 'L' ) ||
1878 ( buf[3] > 1 ) )
1879 return rp_mod_import( at, buf, buflen, passed );
1880
1881 at->at_PositionNr = ((buf[6]&0x0f)<<8)|buf[7];
1882 at->at_Channels = (buf[8]>>2)+4;
1883 at->at_Restart = ((buf[8]&3)<<8)|buf[9];
1884 at->at_SpeedMultiplier = ((buf[6]>>5)&3)+1;
1885 at->at_TrackLength = buf[10];
1886 at->at_TrackNr = buf[11];
1887 at->at_InstrumentNr = buf[12];
1888 at->at_SubsongNr = buf[13];
1889 at->at_mixgainP = buf[14];
1890 at->at_mixgain = (at->at_mixgainP<<8)/100;
1891 at->at_defstereo = buf[15];
1892 at->at_defpanleft = stereopan_left[at->at_defstereo];
1893 at->at_defpanright = stereopan_right[at->at_defstereo];
1894
1895 if( at->at_Restart >= at->at_PositionNr )
1896 at->at_Restart = at->at_PositionNr-1;
1897
1898 // Do some validation
1899 if( ( at->at_PositionNr > 1000 ) ||
1900 ( at->at_TrackLength > 64 ) ||
1901 ( at->at_InstrumentNr > 64 ) )
1902 {
1903 printf( "%d,%d,%d\n", at->at_PositionNr,
1904 at->at_TrackLength,
1905 at->at_InstrumentNr );
1906 if( passed )
1907 rp_clear_tune( at );
1908 else
1909 rp_free_tune( at );
1910 IExec->FreePooled( rp_mempool, buf, buflen );
1911 printf( "Invalid file.\n" );
1912 return NULL;
1913 }
1914
1915 strncpy( at->at_Name, (TEXT *)&buf[(buf[4]<<8)|buf[5]], 128 );
1916 nptr = (TEXT *)&buf[((buf[4]<<8)|buf[5])+strlen( at->at_Name )+1];
1917
1918 bptr = &buf[16];
1919
1920 // Subsongs
1921 for( i=0; i<at->at_SubsongNr; i++ )
1922 {
1923 at->at_Subsongs[i] = (bptr[0]<<8)|bptr[1];
1924 bptr += 2;
1925 }
1926
1927 // Position list
1928 for( i=0; i<at->at_PositionNr; i++ )
1929 {
1930 for( j=0; j<at->at_Channels; j++ )
1931 {
1932 if( i < 1000 )
1933 {
1934 at->at_Positions[i].pos_Track[j] = *bptr++;
1935 at->at_Positions[i].pos_Transpose[j] = *(int8 *)bptr++;
1936 } else {
1937 bptr++;
1938 bptr++;
1939 }
1940 }
1941 }
1942
1943 // Tracks
1944 for( i=0; i<=at->at_TrackNr; i++ )
1945 {
1946 // rp_new_tune() clears it anyway
1947 if( ( ( buf[6]&0x80 ) == 0x80 ) && ( i == 0 ) )
1948 continue;
1949
1950 for( j=0; j<at->at_TrackLength; j++ )
1951 {
1952 if( bptr[0] == 0x3f )
1953 {
1954 at->at_Tracks[i][j].stp_Note = 0;
1955 at->at_Tracks[i][j].stp_Instrument = 0;
1956 at->at_Tracks[i][j].stp_FX = 0;
1957 at->at_Tracks[i][j].stp_FXParam = 0;
1958 at->at_Tracks[i][j].stp_FXb = 0;
1959 at->at_Tracks[i][j].stp_FXbParam = 0;
1960 bptr++;
1961 continue;
1962 }
1963
1964 at->at_Tracks[i][j].stp_Note = bptr[0];
1965 at->at_Tracks[i][j].stp_Instrument = bptr[1];
1966 at->at_Tracks[i][j].stp_FX = bptr[2]>>4;
1967 at->at_Tracks[i][j].stp_FXParam = bptr[3];
1968 at->at_Tracks[i][j].stp_FXb = bptr[2]&0xf;
1969 at->at_Tracks[i][j].stp_FXbParam = bptr[4];
1970
1971 // Strip out EFx commands from older modules
1972 // since they did nothing until HVL1
1973 if( buf[3] < 1 )
1974 {
1975 if( ((at->at_Tracks[i][j].stp_FX==0xe)&&((at->at_Tracks[i][j].stp_FXParam&0xf0)==0xf0)) ||
1976 ((at->at_Tracks[i][j].stp_FXb==0xe)&&((at->at_Tracks[i][j].stp_FXParam&0xf0)==0xf0)) )
1977 {
1978 at->at_Tracks[i][j].stp_FX = 0;
1979 at->at_Tracks[i][j].stp_FXParam = 0;
1980 }
1981 }
1982
1983 bptr += 5;
1984 }
1985 }
1986
1987 // Instruments
1988 for( i=1; i<=at->at_InstrumentNr; i++ )
1989 {
1990 if( nptr < (TEXT *)(buf+buflen) )
1991 {
1992 strncpy( at->at_Instruments[i].ins_Name, nptr, 128 );
1993 nptr += strlen( nptr )+1;
1994 } else {
1995 at->at_Instruments[i].ins_Name[0] = 0;
1996 }
1997
1998 at->at_Instruments[i].ins_Volume = bptr[0];
1999 at->at_Instruments[i].ins_FilterSpeed = ((bptr[1]>>3)&0x1f)|((bptr[12]>>2)&0x20);
2000 at->at_Instruments[i].ins_WaveLength = bptr[1]&0x07;
2001
2002 at->at_Instruments[i].ins_Envelope.aFrames = bptr[2];
2003 at->at_Instruments[i].ins_Envelope.aVolume = bptr[3];
2004 at->at_Instruments[i].ins_Envelope.dFrames = bptr[4];
2005 at->at_Instruments[i].ins_Envelope.dVolume = bptr[5];
2006 at->at_Instruments[i].ins_Envelope.sFrames = bptr[6];
2007 at->at_Instruments[i].ins_Envelope.rFrames = bptr[7];
2008 at->at_Instruments[i].ins_Envelope.rVolume = bptr[8];
2009
2010 at->at_Instruments[i].ins_FilterLowerLimit = bptr[12]&0x7f;
2011 at->at_Instruments[i].ins_VibratoDelay = bptr[13];
2012 at->at_Instruments[i].ins_HardCutReleaseFrames = (bptr[14]>>4)&0x07;
2013 at->at_Instruments[i].ins_HardCutRelease = bptr[14]&0x80?1:0;
2014 at->at_Instruments[i].ins_VibratoDepth = bptr[14]&0x0f;
2015 at->at_Instruments[i].ins_VibratoSpeed = bptr[15];
2016 at->at_Instruments[i].ins_SquareLowerLimit = bptr[16];
2017 at->at_Instruments[i].ins_SquareUpperLimit = bptr[17];
2018 at->at_Instruments[i].ins_SquareSpeed = bptr[18];
2019 at->at_Instruments[i].ins_FilterUpperLimit = bptr[19]&0x3f;
2020 at->at_Instruments[i].ins_PList.pls_Speed = bptr[20];
2021 at->at_Instruments[i].ins_PList.pls_Length = bptr[21];
2022
2023 bptr += 22;
2024 for( j=0; j<at->at_Instruments[i].ins_PList.pls_Length; j++ )
2025 {
2026 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_FX[0] = bptr[0]&0xf;
2027 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_FX[1] = (bptr[1]>>3)&0xf;
2028 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_Waveform = bptr[1]&7;
2029 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_Fixed = (bptr[2]>>6)&1;
2030 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_Note = bptr[2]&0x3f;
2031 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_FXParam[0] = bptr[3];
2032 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_FXParam[1] = bptr[4];
2033 bptr += 5;
2034 }
2035
2036 while( j < 256 )
2037 {
2038 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_FX[0] = 0;
2039 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_FX[1] = 0;
2040 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_FXParam[0] = 0;
2041 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_FXParam[1] = 0;
2042 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_Waveform = 0;
2043 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_Fixed = 0;
2044 at->at_Instruments[i].ins_PList.pls_Entries[j].ple_Note = 0;
2045 j++;
2046 }
2047 at->at_Instruments[i].ins_ptop = 0;
2048 at->at_Instruments[i].ins_pcurx = 0;
2049 at->at_Instruments[i].ins_pcury = 0;
2050 }
2051
2052 if( !passed )
2053 {
2054 IExec->ObtainSemaphore( rp_list_ss );
2055 IExec->AddTail( rp_tunelist, (struct Node *)at );
2056 IExec->ReleaseSemaphore( rp_list_ss );
2057 }
2058
2059 rp_init_subsong( at, 0 );
2060 IExec->FreePooled( rp_mempool, buf, buflen );
2061 return at;
2062 }
2063
rp_process_stepfx_1(struct ahx_tune * at,struct ahx_voice * voice,int32 FX,int32 FXParam)2064 void rp_process_stepfx_1( struct ahx_tune *at, struct ahx_voice *voice, int32 FX, int32 FXParam )
2065 {
2066 switch( FX )
2067 {
2068 case 0x0: // Position Jump HI
2069 if( ((FXParam&0x0f) > 0) && ((FXParam&0x0f) <= 9) )
2070 at->at_PosJump = FXParam & 0xf;
2071 break;
2072
2073 case 0x5: // Volume Slide + Tone Portamento
2074 case 0xa: // Volume Slide
2075 voice->vc_VolumeSlideDown = FXParam & 0x0f;
2076 voice->vc_VolumeSlideUp = FXParam >> 4;
2077 break;
2078
2079 case 0x7: // Panning
2080 if( FXParam > 127 )
2081 FXParam -= 256;
2082 voice->vc_Pan = (FXParam+128);
2083 voice->vc_SetPan = (FXParam+128);
2084 voice->vc_PanMultLeft = panning_left[voice->vc_Pan];
2085 voice->vc_PanMultRight = panning_right[voice->vc_Pan];
2086 break;
2087
2088 case 0xb: // Position jump
2089 at->at_PosJump = at->at_PosJump*100 + (FXParam & 0x0f) + (FXParam >> 4)*10;
2090 at->at_PatternBreak = 1;
2091 if( at->at_PosJump <= at->at_PosNr )
2092 at->at_SongEndReached = 1;
2093 break;
2094
2095 case 0xd: // Pattern break
2096 at->at_PosJump = at->at_PosNr+1;
2097 at->at_PosJumpNote = (FXParam & 0x0f) + (FXParam>>4)*10;
2098 at->at_PatternBreak = 1;
2099 if( at->at_PosJumpNote > at->at_TrackLength )
2100 at->at_PosJumpNote = 0;
2101 break;
2102
2103 case 0xe: // Extended commands
2104 switch( FXParam >> 4 )
2105 {
2106 case 0xc: // Note cut
2107 if( (FXParam & 0x0f) < at->at_Tempo )
2108 {
2109 voice->vc_NoteCutWait = FXParam & 0x0f;
2110 if( voice->vc_NoteCutWait )
2111 {
2112 voice->vc_NoteCutOn = 1;
2113 voice->vc_HardCutRelease = 0;
2114 }
2115 }
2116 break;
2117
2118 // 1.6: case for 0xd removed
2119 }
2120 break;
2121
2122 case 0xf: // Speed
2123 at->at_Tempo = FXParam;
2124 if( FXParam == 0 )
2125 at->at_SongEndReached = 1;
2126 break;
2127 }
2128 }
2129
rp_process_stepfx_2(struct ahx_tune * at,struct ahx_voice * voice,int32 FX,int32 FXParam,int32 * Note)2130 void rp_process_stepfx_2( struct ahx_tune *at, struct ahx_voice *voice, int32 FX, int32 FXParam, int32 *Note )
2131 {
2132 switch( FX )
2133 {
2134 case 0x9: // Set squarewave offset
2135 voice->vc_SquarePos = FXParam >> (5 - voice->vc_WaveLength);
2136 // voice->vc_PlantSquare = 1;
2137 voice->vc_IgnoreSquare = 1;
2138 break;
2139
2140 case 0x3: // Tone portamento
2141 if( FXParam != 0 ) voice->vc_PeriodSlideSpeed = FXParam;
2142 case 0x5: // Tone portamento + volume slide
2143
2144 if( *Note )
2145 {
2146 int32 new, diff;
2147
2148 new = period_tab[*Note];
2149 diff = period_tab[voice->vc_TrackPeriod];
2150 diff -= new;
2151 new = diff + voice->vc_PeriodSlidePeriod;
2152
2153 if( new )
2154 voice->vc_PeriodSlideLimit = -diff;
2155 }
2156 voice->vc_PeriodSlideOn = 1;
2157 voice->vc_PeriodSlideWithLimit = 1;
2158 *Note = 0;
2159 break;
2160 }
2161 }
2162
rp_process_stepfx_3(struct ahx_tune * at,struct ahx_voice * voice,int32 FX,int32 FXParam)2163 void rp_process_stepfx_3( struct ahx_tune *at, struct ahx_voice *voice, int32 FX, int32 FXParam )
2164 {
2165 int32 i;
2166
2167 switch( FX )
2168 {
2169 case 0x01: // Portamento up (period slide down)
2170 voice->vc_PeriodSlideSpeed = -FXParam;
2171 voice->vc_PeriodSlideOn = 1;
2172 voice->vc_PeriodSlideWithLimit = 0;
2173 break;
2174 case 0x02: // Portamento down
2175 voice->vc_PeriodSlideSpeed = FXParam;
2176 voice->vc_PeriodSlideOn = 1;
2177 voice->vc_PeriodSlideWithLimit = 0;
2178 break;
2179 case 0x04: // Filter override
2180 if( ( FXParam == 0 ) || ( FXParam == 0x40 ) ) break;
2181 if( FXParam < 0x40 )
2182 {
2183 voice->vc_IgnoreFilter = FXParam;
2184 break;
2185 }
2186 if( FXParam > 0x7f ) break;
2187 voice->vc_FilterPos = FXParam - 0x40;
2188 break;
2189 case 0x0c: // Volume
2190 FXParam &= 0xff;
2191 if( FXParam <= 0x40 )
2192 {
2193 voice->vc_NoteMaxVolume = FXParam;
2194 break;
2195 }
2196
2197 if( (FXParam -= 0x50) < 0 ) break; // 1.6
2198
2199 if( FXParam <= 0x40 )
2200 {
2201 for( i=0; i<at->at_Channels; i++ )
2202 at->at_Voices[i].vc_TrackMasterVolume = FXParam;
2203 break;
2204 }
2205
2206 if( (FXParam -= 0xa0-0x50) < 0 ) break; // 1.6
2207
2208 if( FXParam <= 0x40 )
2209 voice->vc_TrackMasterVolume = FXParam;
2210 break;
2211
2212 case 0xe: // Extended commands;
2213 switch( FXParam >> 4 )
2214 {
2215 case 0x1: // Fineslide up
2216 voice->vc_PeriodSlidePeriod -= (FXParam & 0x0f);
2217 voice->vc_PlantPeriod = 1;
2218 break;
2219
2220 case 0x2: // Fineslide down
2221 voice->vc_PeriodSlidePeriod += (FXParam & 0x0f);
2222 voice->vc_PlantPeriod = 1;
2223 break;
2224
2225 case 0x4: // Vibrato control
2226 voice->vc_VibratoDepth = FXParam & 0x0f;
2227 break;
2228
2229 case 0x0a: // Fine volume up
2230 voice->vc_NoteMaxVolume += FXParam & 0x0f;
2231
2232 if( voice->vc_NoteMaxVolume > 0x40 )
2233 voice->vc_NoteMaxVolume = 0x40;
2234 break;
2235
2236 case 0x0b: // Fine volume down
2237 voice->vc_NoteMaxVolume -= FXParam & 0x0f;
2238
2239 if( voice->vc_NoteMaxVolume < 0 )
2240 voice->vc_NoteMaxVolume = 0;
2241 break;
2242
2243 case 0x0f: // Miscellaneous (1.5+)
2244 switch( FXParam & 0x0f )
2245 {
2246 case 1: // Preserve track transpose (1.5+)
2247 voice->vc_OverrideTranspose = voice->vc_Transpose;
2248 break;
2249 }
2250 break;
2251 }
2252 break;
2253 }
2254 }
2255
rp_play_instrument(struct ahx_tune * at,int32 vcnum,int32 instr,int32 period)2256 void rp_play_instrument( struct ahx_tune *at, int32 vcnum, int32 instr, int32 period )
2257 {
2258 struct ahx_voice *voice;
2259 struct ahx_instrument *Ins;
2260 int16 SquareLower, SquareUpper, d6, d3, d4;
2261
2262 if( at->at_Instruments[instr].ins_PList.pls_Length == 0 )
2263 return;
2264
2265 if( period == 0 ) return;
2266 if( vcnum >= at->at_Channels ) return;
2267
2268 voice = &at->at_Voices[vcnum];
2269 Ins = &at->at_Instruments[instr];
2270
2271 voice->vc_Pan = voice->vc_SetPan;
2272 voice->vc_PanMultLeft = panning_left[voice->vc_Pan];
2273 voice->vc_PanMultRight = panning_right[voice->vc_Pan];
2274
2275 voice->vc_TrackOn = voice->vc_SetTrackOn;
2276 voice->vc_Transpose = 0;
2277 voice->vc_OverrideTranspose = 1000; // 1.5
2278
2279 voice->vc_PeriodSlideSpeed = voice->vc_PeriodSlidePeriod = voice->vc_PeriodSlideLimit = 0;
2280
2281 voice->vc_PerfSubVolume = 0x40;
2282 voice->vc_ADSRVolume = 0;
2283 voice->vc_Instrument = Ins;
2284 voice->vc_SamplePos = 0;
2285
2286 voice->vc_ADSR.aFrames = Ins->ins_Envelope.aFrames;
2287 voice->vc_ADSR.aVolume = Ins->ins_Envelope.aVolume*256/voice->vc_ADSR.aFrames;
2288 voice->vc_ADSR.dFrames = Ins->ins_Envelope.dFrames;
2289 voice->vc_ADSR.dVolume = (Ins->ins_Envelope.dVolume-Ins->ins_Envelope.aVolume)*256/voice->vc_ADSR.dFrames;
2290 voice->vc_ADSR.sFrames = Ins->ins_Envelope.sFrames;
2291 voice->vc_ADSR.rFrames = Ins->ins_Envelope.rFrames;
2292 voice->vc_ADSR.rVolume = (Ins->ins_Envelope.rVolume-Ins->ins_Envelope.dVolume)*256/voice->vc_ADSR.rFrames;
2293
2294 voice->vc_WaveLength = Ins->ins_WaveLength;
2295 voice->vc_NoteMaxVolume = Ins->ins_Volume;
2296
2297 voice->vc_VibratoCurrent = 0;
2298 voice->vc_VibratoDelay = Ins->ins_VibratoDelay;
2299 voice->vc_VibratoDepth = Ins->ins_VibratoDepth;
2300 voice->vc_VibratoSpeed = Ins->ins_VibratoSpeed;
2301 voice->vc_VibratoPeriod = 0;
2302
2303 voice->vc_HardCutRelease = Ins->ins_HardCutRelease;
2304 voice->vc_HardCut = Ins->ins_HardCutReleaseFrames;
2305
2306 voice->vc_IgnoreSquare = voice->vc_SquareSlidingIn = 0;
2307 voice->vc_SquareWait = voice->vc_SquareOn = 0;
2308
2309 SquareLower = Ins->ins_SquareLowerLimit >> (5 - voice->vc_WaveLength);
2310 SquareUpper = Ins->ins_SquareUpperLimit >> (5 - voice->vc_WaveLength);
2311
2312 if( SquareUpper < SquareLower )
2313 {
2314 int16 t = SquareUpper;
2315 SquareUpper = SquareLower;
2316 SquareLower = t;
2317 }
2318
2319 voice->vc_SquareUpperLimit = SquareUpper;
2320 voice->vc_SquareLowerLimit = SquareLower;
2321
2322 voice->vc_IgnoreFilter = voice->vc_FilterWait = voice->vc_FilterOn = 0;
2323 voice->vc_FilterSlidingIn = 0;
2324
2325 d6 = Ins->ins_FilterSpeed;
2326 d3 = Ins->ins_FilterLowerLimit;
2327 d4 = Ins->ins_FilterUpperLimit;
2328
2329 if( d3 & 0x80 ) d6 |= 0x20;
2330 if( d4 & 0x80 ) d6 |= 0x40;
2331
2332 voice->vc_FilterSpeed = d6;
2333 d3 &= ~0x80;
2334 d4 &= ~0x80;
2335
2336 if( d3 > d4 )
2337 {
2338 int16 t = d3;
2339 d3 = d4;
2340 d4 = t;
2341 }
2342
2343 voice->vc_FilterUpperLimit = d4;
2344 voice->vc_FilterLowerLimit = d3;
2345 voice->vc_FilterPos = 32;
2346
2347 voice->vc_PerfWait = voice->vc_PerfCurrent = 0;
2348 voice->vc_PerfSpeed = Ins->ins_PList.pls_Speed;
2349 voice->vc_PerfList = &voice->vc_Instrument->ins_PList;
2350
2351 voice->vc_TrackPeriod = period;
2352 voice->vc_InstrPeriod = period;
2353 voice->vc_PlantPeriod = 1;
2354
2355 voice->vc_RingMixSource = NULL; // No ring modulation
2356 voice->vc_RingSamplePos = 0;
2357 voice->vc_RingPlantPeriod = 0;
2358 voice->vc_RingNewWaveform = 0;
2359 }
2360
rp_process_step(struct ahx_tune * at,struct ahx_voice * voice)2361 void rp_process_step( struct ahx_tune *at, struct ahx_voice *voice )
2362 {
2363 int32 Note, Instr, donenotedel;
2364 struct ahx_step *Step;
2365
2366 if( voice->vc_TrackOn == 0 )
2367 return;
2368
2369 if( ( rp_state == STS_PLAYNOTE ) ||
2370 ( rp_state == STS_PLAYROW ) ) return;
2371
2372 voice->vc_VolumeSlideUp = voice->vc_VolumeSlideDown = 0;
2373
2374 Step = &at->at_Tracks[at->at_Positions[at->at_PosNr].pos_Track[voice->vc_VoiceNum]][at->at_NoteNr];
2375
2376 Note = Step->stp_Note;
2377 Instr = Step->stp_Instrument;
2378
2379 // --------- 1.6: from here --------------
2380
2381 donenotedel = 0;
2382
2383 // Do notedelay here
2384 if( ((Step->stp_FX&0xf)==0xe) && ((Step->stp_FXParam&0xf0)==0xd0) )
2385 {
2386 if( voice->vc_NoteDelayOn )
2387 {
2388 voice->vc_NoteDelayOn = 0;
2389 donenotedel = 1;
2390 } else {
2391 if( (Step->stp_FXParam&0x0f) < at->at_Tempo )
2392 {
2393 voice->vc_NoteDelayWait = Step->stp_FXParam & 0x0f;
2394 if( voice->vc_NoteDelayWait )
2395 {
2396 voice->vc_NoteDelayOn = 1;
2397 return;
2398 }
2399 }
2400 }
2401 }
2402
2403 if( (donenotedel==0) && ((Step->stp_FXb&0xf)==0xe) && ((Step->stp_FXbParam&0xf0)==0xd0) )
2404 {
2405 if( voice->vc_NoteDelayOn )
2406 {
2407 voice->vc_NoteDelayOn = 0;
2408 } else {
2409 if( (Step->stp_FXbParam&0x0f) < at->at_Tempo )
2410 {
2411 voice->vc_NoteDelayWait = Step->stp_FXbParam & 0x0f;
2412 if( voice->vc_NoteDelayWait )
2413 {
2414 voice->vc_NoteDelayOn = 1;
2415 return;
2416 }
2417 }
2418 }
2419 }
2420
2421 // ---------- 1.6: to here -------------
2422
2423 if( Note ) voice->vc_OverrideTranspose = 1000; // 1.5
2424
2425 rp_process_stepfx_1( at, voice, Step->stp_FX&0xf, Step->stp_FXParam );
2426 rp_process_stepfx_1( at, voice, Step->stp_FXb&0xf, Step->stp_FXbParam );
2427
2428 if( Instr )
2429 {
2430 struct ahx_instrument *Ins;
2431 int16 SquareLower, SquareUpper, d6, d3, d4;
2432
2433 /* 1.4: Reset panning to last set position */
2434 voice->vc_Pan = voice->vc_SetPan;
2435 voice->vc_PanMultLeft = panning_left[voice->vc_Pan];
2436 voice->vc_PanMultRight = panning_right[voice->vc_Pan];
2437
2438 voice->vc_PeriodSlideSpeed = voice->vc_PeriodSlidePeriod = voice->vc_PeriodSlideLimit = 0;
2439
2440 voice->vc_PerfSubVolume = 0x40;
2441 voice->vc_ADSRVolume = 0;
2442 voice->vc_Instrument = Ins = &at->at_Instruments[Instr];
2443 voice->vc_SamplePos = 0;
2444
2445 voice->vc_ADSR.aFrames = Ins->ins_Envelope.aFrames;
2446 voice->vc_ADSR.aVolume = voice->vc_ADSR.aFrames ? Ins->ins_Envelope.aVolume*256/voice->vc_ADSR.aFrames : Ins->ins_Envelope.aVolume * 256; // XXX
2447 voice->vc_ADSR.dFrames = Ins->ins_Envelope.dFrames;
2448 voice->vc_ADSR.dVolume = voice->vc_ADSR.dFrames ? (Ins->ins_Envelope.dVolume-Ins->ins_Envelope.aVolume)*256/voice->vc_ADSR.dFrames : Ins->ins_Envelope.dVolume * 256; // XXX
2449 voice->vc_ADSR.sFrames = Ins->ins_Envelope.sFrames;
2450 voice->vc_ADSR.rFrames = Ins->ins_Envelope.rFrames;
2451 voice->vc_ADSR.rVolume = voice->vc_ADSR.rFrames ? (Ins->ins_Envelope.rVolume-Ins->ins_Envelope.dVolume)*256/voice->vc_ADSR.rFrames : Ins->ins_Envelope.rVolume * 256; // XXX
2452
2453 voice->vc_WaveLength = Ins->ins_WaveLength;
2454 voice->vc_NoteMaxVolume = Ins->ins_Volume;
2455
2456 voice->vc_VibratoCurrent = 0;
2457 voice->vc_VibratoDelay = Ins->ins_VibratoDelay;
2458 voice->vc_VibratoDepth = Ins->ins_VibratoDepth;
2459 voice->vc_VibratoSpeed = Ins->ins_VibratoSpeed;
2460 voice->vc_VibratoPeriod = 0;
2461
2462 voice->vc_HardCutRelease = Ins->ins_HardCutRelease;
2463 voice->vc_HardCut = Ins->ins_HardCutReleaseFrames;
2464
2465 voice->vc_IgnoreSquare = voice->vc_SquareSlidingIn = 0;
2466 voice->vc_SquareWait = voice->vc_SquareOn = 0;
2467
2468 SquareLower = Ins->ins_SquareLowerLimit >> (5 - voice->vc_WaveLength);
2469 SquareUpper = Ins->ins_SquareUpperLimit >> (5 - voice->vc_WaveLength);
2470
2471 if( SquareUpper < SquareLower )
2472 {
2473 int16 t = SquareUpper;
2474 SquareUpper = SquareLower;
2475 SquareLower = t;
2476 }
2477
2478 voice->vc_SquareUpperLimit = SquareUpper;
2479 voice->vc_SquareLowerLimit = SquareLower;
2480
2481 voice->vc_IgnoreFilter = voice->vc_FilterWait = voice->vc_FilterOn = 0;
2482 voice->vc_FilterSlidingIn = 0;
2483
2484 d6 = Ins->ins_FilterSpeed;
2485 d3 = Ins->ins_FilterLowerLimit;
2486 d4 = Ins->ins_FilterUpperLimit;
2487
2488 if( d3 & 0x80 ) d6 |= 0x20;
2489 if( d4 & 0x80 ) d6 |= 0x40;
2490
2491 voice->vc_FilterSpeed = d6;
2492 d3 &= ~0x80;
2493 d4 &= ~0x80;
2494
2495 if( d3 > d4 )
2496 {
2497 int16 t = d3;
2498 d3 = d4;
2499 d4 = t;
2500 }
2501
2502 voice->vc_FilterUpperLimit = d4;
2503 voice->vc_FilterLowerLimit = d3;
2504 voice->vc_FilterPos = 32;
2505
2506 voice->vc_PerfWait = voice->vc_PerfCurrent = 0;
2507 voice->vc_PerfSpeed = Ins->ins_PList.pls_Speed;
2508 voice->vc_PerfList = &voice->vc_Instrument->ins_PList;
2509
2510 voice->vc_RingMixSource = NULL; // No ring modulation
2511 voice->vc_RingSamplePos = 0;
2512 voice->vc_RingPlantPeriod = 0;
2513 voice->vc_RingNewWaveform = 0;
2514 }
2515
2516 voice->vc_PeriodSlideOn = 0;
2517
2518 rp_process_stepfx_2( at, voice, Step->stp_FX&0xf, Step->stp_FXParam, &Note );
2519 rp_process_stepfx_2( at, voice, Step->stp_FXb&0xf, Step->stp_FXbParam, &Note );
2520
2521 if( Note )
2522 {
2523 voice->vc_TrackPeriod = Note;
2524 voice->vc_PlantPeriod = 1;
2525 }
2526
2527 rp_process_stepfx_3( at, voice, Step->stp_FX&0xf, Step->stp_FXParam );
2528 rp_process_stepfx_3( at, voice, Step->stp_FXb&0xf, Step->stp_FXbParam );
2529 }
2530
rp_plist_command_parse(struct ahx_tune * at,struct ahx_voice * voice,int32 FX,int32 FXParam)2531 void rp_plist_command_parse( struct ahx_tune *at, struct ahx_voice *voice, int32 FX, int32 FXParam )
2532 {
2533 switch( FX )
2534 {
2535 case 0:
2536 if( ( FXParam > 0 ) && ( FXParam < 0x40 ) )
2537 {
2538 if( voice->vc_IgnoreFilter )
2539 {
2540 voice->vc_FilterPos = voice->vc_IgnoreFilter;
2541 voice->vc_IgnoreFilter = 0;
2542 } else {
2543 voice->vc_FilterPos = FXParam;
2544 }
2545 voice->vc_NewWaveform = 1;
2546 }
2547 break;
2548
2549 case 1:
2550 voice->vc_PeriodPerfSlideSpeed = FXParam;
2551 voice->vc_PeriodPerfSlideOn = 1;
2552 break;
2553
2554 case 2:
2555 voice->vc_PeriodPerfSlideSpeed = -FXParam;
2556 voice->vc_PeriodPerfSlideOn = 1;
2557 break;
2558
2559 case 3:
2560 if( voice->vc_IgnoreSquare == 0 )
2561 voice->vc_SquarePos = FXParam >> (5-voice->vc_WaveLength);
2562 else
2563 voice->vc_IgnoreSquare = 0;
2564 break;
2565
2566 case 4:
2567 if( FXParam == 0 )
2568 {
2569 voice->vc_SquareInit = (voice->vc_SquareOn ^= 1);
2570 voice->vc_SquareSign = 1;
2571 } else {
2572
2573 if( FXParam & 0x0f )
2574 {
2575 voice->vc_SquareInit = (voice->vc_SquareOn ^= 1);
2576 voice->vc_SquareSign = 1;
2577 if(( FXParam & 0x0f ) == 0x0f )
2578 voice->vc_SquareSign = -1;
2579 }
2580
2581 if( FXParam & 0xf0 )
2582 {
2583 voice->vc_FilterInit = (voice->vc_FilterOn ^= 1);
2584 voice->vc_FilterSign = 1;
2585 if(( FXParam & 0xf0 ) == 0xf0 )
2586 voice->vc_FilterSign = -1;
2587 }
2588 }
2589 break;
2590
2591 case 5:
2592 voice->vc_PerfCurrent = FXParam;
2593 break;
2594
2595 case 7:
2596 // Ring modulate with triangle
2597 if(( FXParam >= 1 ) && ( FXParam <= 0x3C ))
2598 {
2599 voice->vc_RingBasePeriod = FXParam;
2600 voice->vc_RingFixedPeriod = 1;
2601 } else if(( FXParam >= 0x81 ) && ( FXParam <= 0xBC )) {
2602 voice->vc_RingBasePeriod = FXParam-0x80;
2603 voice->vc_RingFixedPeriod = 0;
2604 } else {
2605 voice->vc_RingBasePeriod = 0;
2606 voice->vc_RingFixedPeriod = 0;
2607 voice->vc_RingNewWaveform = 0;
2608 voice->vc_RingAudioSource = NULL; // turn it off
2609 voice->vc_RingMixSource = NULL;
2610 break;
2611 }
2612 voice->vc_RingWaveform = 0;
2613 voice->vc_RingNewWaveform = 1;
2614 voice->vc_RingPlantPeriod = 1;
2615 break;
2616
2617 case 8: // Ring modulate with sawtooth
2618 if(( FXParam >= 1 ) && ( FXParam <= 0x3C ))
2619 {
2620 voice->vc_RingBasePeriod = FXParam;
2621 voice->vc_RingFixedPeriod = 1;
2622 } else if(( FXParam >= 0x81 ) && ( FXParam <= 0xBC )) {
2623 voice->vc_RingBasePeriod = FXParam-0x80;
2624 voice->vc_RingFixedPeriod = 0;
2625 } else {
2626 voice->vc_RingBasePeriod = 0;
2627 voice->vc_RingFixedPeriod = 0;
2628 voice->vc_RingNewWaveform = 0;
2629 voice->vc_RingAudioSource = NULL;
2630 voice->vc_RingMixSource = NULL;
2631 break;
2632 }
2633
2634 voice->vc_RingWaveform = 1;
2635 voice->vc_RingNewWaveform = 1;
2636 voice->vc_RingPlantPeriod = 1;
2637 break;
2638
2639 case 9:
2640 if( FXParam > 127 )
2641 FXParam -= 256;
2642 voice->vc_Pan = (FXParam+128);
2643 voice->vc_PanMultLeft = panning_left[voice->vc_Pan];
2644 voice->vc_PanMultRight = panning_right[voice->vc_Pan];
2645 break;
2646
2647 case 12:
2648 if( FXParam <= 0x40 )
2649 {
2650 voice->vc_NoteMaxVolume = FXParam;
2651 break;
2652 }
2653
2654 if( (FXParam -= 0x50) < 0 ) break;
2655
2656 if( FXParam <= 0x40 )
2657 {
2658 voice->vc_PerfSubVolume = FXParam;
2659 break;
2660 }
2661
2662 if( (FXParam -= 0xa0-0x50) < 0 ) break;
2663
2664 if( FXParam <= 0x40 )
2665 voice->vc_TrackMasterVolume = FXParam;
2666 break;
2667
2668 case 15:
2669 voice->vc_PerfSpeed = voice->vc_PerfWait = FXParam;
2670 break;
2671 }
2672 }
2673
rp_process_frame(struct ahx_tune * at,struct ahx_voice * voice)2674 void rp_process_frame( struct ahx_tune *at, struct ahx_voice *voice )
2675 {
2676 static CONST uint8 Offsets[] = {0x00,0x04,0x04+0x08,0x04+0x08+0x10,0x04+0x08+0x10+0x20,0x04+0x08+0x10+0x20+0x40};
2677
2678 if( voice->vc_TrackOn == 0 )
2679 return;
2680
2681 if( rp_state != STS_PLAYNOTE )
2682 {
2683 if( voice->vc_NoteDelayOn )
2684 {
2685 if( voice->vc_NoteDelayWait <= 0 )
2686 rp_process_step( at, voice );
2687 else
2688 voice->vc_NoteDelayWait--;
2689 }
2690
2691 if( voice->vc_HardCut )
2692 {
2693 int32 nextinst;
2694
2695 if( at->at_NoteNr+1 < at->at_TrackLength )
2696 nextinst = at->at_Tracks[voice->vc_Track][at->at_NoteNr+1].stp_Instrument;
2697 else
2698 nextinst = at->at_Tracks[voice->vc_NextTrack][0].stp_Instrument;
2699
2700 if( nextinst )
2701 {
2702 int32 d1;
2703
2704 d1 = at->at_Tempo - voice->vc_HardCut;
2705
2706 if( d1 < 0 ) d1 = 0;
2707
2708 if( !voice->vc_NoteCutOn )
2709 {
2710 voice->vc_NoteCutOn = 1;
2711 voice->vc_NoteCutWait = d1;
2712 voice->vc_HardCutReleaseF = -(d1-at->at_Tempo);
2713 } else {
2714 voice->vc_HardCut = 0;
2715 }
2716 }
2717 }
2718
2719 if( voice->vc_NoteCutOn )
2720 {
2721 if( voice->vc_NoteCutWait <= 0 )
2722 {
2723 voice->vc_NoteCutOn = 0;
2724
2725 if( voice->vc_HardCutRelease )
2726 {
2727 voice->vc_ADSR.rVolume = -(voice->vc_ADSRVolume - (voice->vc_Instrument->ins_Envelope.rVolume << 8)) / voice->vc_HardCutReleaseF;
2728 voice->vc_ADSR.rFrames = voice->vc_HardCutReleaseF;
2729 voice->vc_ADSR.aFrames = voice->vc_ADSR.dFrames = voice->vc_ADSR.sFrames = 0;
2730 } else {
2731 voice->vc_NoteMaxVolume = 0;
2732 }
2733 } else {
2734 voice->vc_NoteCutWait--;
2735 }
2736 }
2737 }
2738
2739 // ADSR envelope
2740 if( voice->vc_ADSR.aFrames )
2741 {
2742 voice->vc_ADSRVolume += voice->vc_ADSR.aVolume;
2743
2744 if( --voice->vc_ADSR.aFrames <= 0 )
2745 voice->vc_ADSRVolume = voice->vc_Instrument->ins_Envelope.aVolume << 8;
2746
2747 } else if( voice->vc_ADSR.dFrames ) {
2748
2749 voice->vc_ADSRVolume += voice->vc_ADSR.dVolume;
2750
2751 if( --voice->vc_ADSR.dFrames <= 0 )
2752 voice->vc_ADSRVolume = voice->vc_Instrument->ins_Envelope.dVolume << 8;
2753
2754 } else if( voice->vc_ADSR.sFrames ) {
2755
2756 voice->vc_ADSR.sFrames--;
2757
2758 } else if( voice->vc_ADSR.rFrames ) {
2759
2760 voice->vc_ADSRVolume += voice->vc_ADSR.rVolume;
2761
2762 if( --voice->vc_ADSR.rFrames <= 0 )
2763 voice->vc_ADSRVolume = voice->vc_Instrument->ins_Envelope.rVolume << 8;
2764 }
2765
2766 if( ( rp_state != STS_PLAYNOTE ) &&
2767 ( rp_state != STS_PLAYROW ) )
2768 {
2769 // VolumeSlide
2770 voice->vc_NoteMaxVolume = voice->vc_NoteMaxVolume + voice->vc_VolumeSlideUp - voice->vc_VolumeSlideDown;
2771
2772 if( voice->vc_NoteMaxVolume < 0 )
2773 voice->vc_NoteMaxVolume = 0;
2774 else if( voice->vc_NoteMaxVolume > 0x40 )
2775 voice->vc_NoteMaxVolume = 0x40;
2776
2777 // Portamento
2778 if( voice->vc_PeriodSlideOn )
2779 {
2780 if( voice->vc_PeriodSlideWithLimit )
2781 {
2782 int32 d0, d2;
2783
2784 d0 = voice->vc_PeriodSlidePeriod - voice->vc_PeriodSlideLimit;
2785 d2 = voice->vc_PeriodSlideSpeed;
2786
2787 if( d0 > 0 )
2788 d2 = -d2;
2789
2790 if( d0 )
2791 {
2792 int32 d3;
2793
2794 d3 = (d0 + d2) ^ d0;
2795
2796 if( d3 >= 0 )
2797 d0 = voice->vc_PeriodSlidePeriod + d2;
2798 else
2799 d0 = voice->vc_PeriodSlideLimit;
2800
2801 voice->vc_PeriodSlidePeriod = d0;
2802 voice->vc_PlantPeriod = 1;
2803 }
2804 } else {
2805 voice->vc_PeriodSlidePeriod += voice->vc_PeriodSlideSpeed;
2806 voice->vc_PlantPeriod = 1;
2807 }
2808 }
2809 }
2810
2811 // Vibrato
2812 if( voice->vc_VibratoDepth )
2813 {
2814 if( voice->vc_VibratoDelay <= 0 )
2815 {
2816 voice->vc_VibratoPeriod = (vib_tab[voice->vc_VibratoCurrent] * voice->vc_VibratoDepth) >> 7;
2817 voice->vc_PlantPeriod = 1;
2818 voice->vc_VibratoCurrent = (voice->vc_VibratoCurrent + voice->vc_VibratoSpeed) & 0x3f;
2819 } else {
2820 voice->vc_VibratoDelay--;
2821 }
2822 }
2823
2824 // PList
2825 if( voice->vc_PerfList != 0 )
2826 {
2827 if( voice->vc_Instrument && voice->vc_PerfCurrent < voice->vc_Instrument->ins_PList.pls_Length )
2828 {
2829 if( --voice->vc_PerfWait <= 0 )
2830 {
2831 uint32 i;
2832 int32 cur;
2833
2834 cur = voice->vc_PerfCurrent++;
2835 voice->vc_PerfWait = voice->vc_PerfSpeed;
2836
2837 if( voice->vc_PerfList->pls_Entries[cur].ple_Waveform )
2838 {
2839 voice->vc_Waveform = voice->vc_PerfList->pls_Entries[cur].ple_Waveform-1;
2840 voice->vc_NewWaveform = 1;
2841 voice->vc_PeriodPerfSlideSpeed = voice->vc_PeriodPerfSlidePeriod = 0;
2842 }
2843
2844 // Holdwave
2845 voice->vc_PeriodPerfSlideOn = 0;
2846
2847 for( i=0; i<2; i++ )
2848 rp_plist_command_parse( at, voice, voice->vc_PerfList->pls_Entries[cur].ple_FX[i]&0xff, voice->vc_PerfList->pls_Entries[cur].ple_FXParam[i]&0xff );
2849
2850 // GetNote
2851 if( voice->vc_PerfList->pls_Entries[cur].ple_Note )
2852 {
2853 voice->vc_InstrPeriod = voice->vc_PerfList->pls_Entries[cur].ple_Note;
2854 voice->vc_PlantPeriod = 1;
2855 voice->vc_FixedNote = voice->vc_PerfList->pls_Entries[cur].ple_Fixed;
2856 }
2857 }
2858 } else {
2859 if( voice->vc_PerfWait )
2860 voice->vc_PerfWait--;
2861 else
2862 voice->vc_PeriodPerfSlideSpeed = 0;
2863 }
2864 }
2865
2866 // PerfPortamento
2867 if( voice->vc_PeriodPerfSlideOn )
2868 {
2869 voice->vc_PeriodPerfSlidePeriod -= voice->vc_PeriodPerfSlideSpeed;
2870
2871 if( voice->vc_PeriodPerfSlidePeriod )
2872 voice->vc_PlantPeriod = 1;
2873 }
2874
2875 if( voice->vc_Waveform == 3-1 && voice->vc_SquareOn )
2876 {
2877 if( --voice->vc_SquareWait <= 0 )
2878 {
2879 int32 d1, d2, d3;
2880
2881 d1 = voice->vc_SquareLowerLimit;
2882 d2 = voice->vc_SquareUpperLimit;
2883 d3 = voice->vc_SquarePos;
2884
2885 if( voice->vc_SquareInit )
2886 {
2887 voice->vc_SquareInit = 0;
2888
2889 if( d3 <= d1 )
2890 {
2891 voice->vc_SquareSlidingIn = 1;
2892 voice->vc_SquareSign = 1;
2893 } else if( d3 >= d2 ) {
2894 voice->vc_SquareSlidingIn = 1;
2895 voice->vc_SquareSign = -1;
2896 }
2897 }
2898
2899 // NoSquareInit
2900 if( d1 == d3 || d2 == d3 )
2901 {
2902 if( voice->vc_SquareSlidingIn )
2903 voice->vc_SquareSlidingIn = 0;
2904 else
2905 voice->vc_SquareSign = -voice->vc_SquareSign;
2906 }
2907
2908 d3 += voice->vc_SquareSign;
2909 voice->vc_SquarePos = d3;
2910 voice->vc_PlantSquare = 1;
2911 voice->vc_SquareWait = voice->vc_Instrument->ins_SquareSpeed;
2912 }
2913 }
2914
2915 if( voice->vc_FilterOn && --voice->vc_FilterWait <= 0 )
2916 {
2917 uint32 i, FMax;
2918 int32 d1, d2, d3;
2919
2920 d1 = voice->vc_FilterLowerLimit;
2921 d2 = voice->vc_FilterUpperLimit;
2922 d3 = voice->vc_FilterPos;
2923
2924 if( voice->vc_FilterInit )
2925 {
2926 voice->vc_FilterInit = 0;
2927 if( d3 <= d1 )
2928 {
2929 voice->vc_FilterSlidingIn = 1;
2930 voice->vc_FilterSign = 1;
2931 } else if( d3 >= d2 ) {
2932 voice->vc_FilterSlidingIn = 1;
2933 voice->vc_FilterSign = -1;
2934 }
2935 }
2936
2937 // NoFilterInit
2938 FMax = (voice->vc_FilterSpeed < 3) ? (5-voice->vc_FilterSpeed) : 1;
2939
2940 for( i=0; i<FMax; i++ )
2941 {
2942 if( ( d1 == d3 ) || ( d2 == d3 ) )
2943 {
2944 if( voice->vc_FilterSlidingIn )
2945 voice->vc_FilterSlidingIn = 0;
2946 else
2947 voice->vc_FilterSign = -voice->vc_FilterSign;
2948 }
2949 d3 += voice->vc_FilterSign;
2950 }
2951
2952 if( d3 < 1 ) d3 = 1;
2953 if( d3 > 63 ) d3 = 63;
2954 voice->vc_FilterPos = d3;
2955 voice->vc_NewWaveform = 1;
2956 voice->vc_FilterWait = voice->vc_FilterSpeed - 3;
2957
2958 if( voice->vc_FilterWait < 1 )
2959 voice->vc_FilterWait = 1;
2960 }
2961
2962 if( voice->vc_Waveform == 3-1 || voice->vc_PlantSquare )
2963 {
2964 // CalcSquare
2965 uint32 i;
2966 int32 Delta;
2967 int8 *SquarePtr;
2968 int32 X;
2969
2970 SquarePtr = &waves[WO_SQUARES+(voice->vc_FilterPos-0x20)*(0xfc+0xfc+0x80*0x1f+0x80+0x280*3)];
2971 X = voice->vc_SquarePos << (5 - voice->vc_WaveLength);
2972
2973 if( X > 0x20 )
2974 {
2975 X = 0x40 - X;
2976 voice->vc_SquareReverse = 1;
2977 }
2978
2979 // OkDownSquare
2980 if( X > 0 )
2981 SquarePtr += (X-1) << 7;
2982
2983 Delta = 32 >> voice->vc_WaveLength;
2984 at->at_WaveformTab[2] = voice->vc_SquareTempBuffer;
2985
2986 for( i=0; i<(1<<voice->vc_WaveLength)*4; i++ )
2987 {
2988 voice->vc_SquareTempBuffer[i] = *SquarePtr;
2989 SquarePtr += Delta;
2990 }
2991
2992 voice->vc_NewWaveform = 1;
2993 voice->vc_Waveform = 3-1;
2994 voice->vc_PlantSquare = 0;
2995 }
2996
2997 if( voice->vc_Waveform == 4-1 )
2998 voice->vc_NewWaveform = 1;
2999
3000 if( voice->vc_RingNewWaveform )
3001 {
3002 int8 *rasrc;
3003
3004 if( voice->vc_RingWaveform > 1 ) voice->vc_RingWaveform = 1;
3005
3006 rasrc = at->at_WaveformTab[voice->vc_RingWaveform];
3007 rasrc += Offsets[voice->vc_WaveLength];
3008
3009 voice->vc_RingAudioSource = rasrc;
3010 }
3011
3012
3013 if( voice->vc_NewWaveform )
3014 {
3015 int8 *AudioSource;
3016
3017 AudioSource = at->at_WaveformTab[voice->vc_Waveform];
3018
3019 if( voice->vc_Waveform != 3-1 )
3020 AudioSource += (voice->vc_FilterPos-0x20)*(0xfc+0xfc+0x80*0x1f+0x80+0x280*3);
3021
3022 if( voice->vc_Waveform < 3-1)
3023 {
3024 // GetWLWaveformlor2
3025 AudioSource += Offsets[voice->vc_WaveLength];
3026 }
3027
3028 if( voice->vc_Waveform == 4-1 )
3029 {
3030 // AddRandomMoving
3031 AudioSource += ( voice->vc_WNRandom & (2*0x280-1) ) & ~1;
3032 // GoOnRandom
3033 voice->vc_WNRandom += 2239384;
3034 voice->vc_WNRandom = ((((voice->vc_WNRandom >> 8) | (voice->vc_WNRandom << 24)) + 782323) ^ 75) - 6735;
3035 }
3036
3037 voice->vc_AudioSource = AudioSource;
3038 }
3039
3040 // Ring modulation period calculation
3041 if( voice->vc_RingAudioSource )
3042 {
3043 voice->vc_RingAudioPeriod = voice->vc_RingBasePeriod;
3044
3045 if( !(voice->vc_RingFixedPeriod) )
3046 {
3047 if( voice->vc_OverrideTranspose != 1000 ) // 1.5
3048 voice->vc_RingAudioPeriod += voice->vc_OverrideTranspose + voice->vc_TrackPeriod - 1;
3049 else
3050 voice->vc_RingAudioPeriod += voice->vc_Transpose + voice->vc_TrackPeriod - 1;
3051 }
3052
3053 if( voice->vc_RingAudioPeriod > 5*12 )
3054 voice->vc_RingAudioPeriod = 5*12;
3055
3056 if( voice->vc_RingAudioPeriod < 0 )
3057 voice->vc_RingAudioPeriod = 0;
3058
3059 voice->vc_RingAudioPeriod = period_tab[voice->vc_RingAudioPeriod];
3060
3061 if( !(voice->vc_RingFixedPeriod) )
3062 voice->vc_RingAudioPeriod += voice->vc_PeriodSlidePeriod;
3063
3064 voice->vc_RingAudioPeriod += voice->vc_PeriodPerfSlidePeriod + voice->vc_VibratoPeriod;
3065
3066 if( voice->vc_RingAudioPeriod > 0x0d60 )
3067 voice->vc_RingAudioPeriod = 0x0d60;
3068
3069 if( voice->vc_RingAudioPeriod < 0x0071 )
3070 voice->vc_RingAudioPeriod = 0x0071;
3071 }
3072
3073 // Normal period calculation
3074 voice->vc_AudioPeriod = voice->vc_InstrPeriod;
3075
3076 if( !(voice->vc_FixedNote) )
3077 {
3078 if( voice->vc_OverrideTranspose != 1000 ) // 1.5
3079 voice->vc_AudioPeriod += voice->vc_OverrideTranspose + voice->vc_TrackPeriod - 1;
3080 else
3081 voice->vc_AudioPeriod += voice->vc_Transpose + voice->vc_TrackPeriod - 1;
3082 }
3083
3084 if( voice->vc_AudioPeriod > 5*12 )
3085 voice->vc_AudioPeriod = 5*12;
3086
3087 if( voice->vc_AudioPeriod < 0 )
3088 voice->vc_AudioPeriod = 0;
3089
3090 voice->vc_AudioPeriod = period_tab[voice->vc_AudioPeriod];
3091
3092 if( !(voice->vc_FixedNote) )
3093 voice->vc_AudioPeriod += voice->vc_PeriodSlidePeriod;
3094
3095 voice->vc_AudioPeriod += voice->vc_PeriodPerfSlidePeriod + voice->vc_VibratoPeriod;
3096
3097 if( voice->vc_AudioPeriod > 0x0d60 )
3098 voice->vc_AudioPeriod = 0x0d60;
3099
3100 if( voice->vc_AudioPeriod < 0x0071 )
3101 voice->vc_AudioPeriod = 0x0071;
3102
3103 voice->vc_AudioVolume = (((((((voice->vc_ADSRVolume >> 8) * voice->vc_NoteMaxVolume) >> 6) * voice->vc_PerfSubVolume) >> 6) * voice->vc_TrackMasterVolume) >> 6);
3104 }
3105
rp_set_audio(struct ahx_voice * voice,float64 freqf)3106 void rp_set_audio( struct ahx_voice *voice, float64 freqf )
3107 {
3108 if( voice->vc_TrackOn == 0 )
3109 {
3110 voice->vc_VoiceVolume = 0;
3111 return;
3112 }
3113
3114 voice->vc_VoiceVolume = voice->vc_AudioVolume;
3115
3116 if( voice->vc_PlantPeriod )
3117 {
3118 float64 freq2;
3119 uint32 delta;
3120
3121 voice->vc_PlantPeriod = 0;
3122 voice->vc_VoicePeriod = voice->vc_AudioPeriod;
3123
3124 freq2 = Period2Freq( voice->vc_AudioPeriod );
3125 delta = (uint32)(freq2 / freqf);
3126
3127 if( delta > (0x280<<16) ) delta -= (0x280<<16);
3128 if( delta == 0 ) delta = 1;
3129 voice->vc_Delta = delta;
3130 }
3131
3132 if( voice->vc_NewWaveform )
3133 {
3134 int8 *src;
3135
3136 src = voice->vc_AudioSource;
3137
3138 if( voice->vc_Waveform == 4-1 )
3139 {
3140 IExec->CopyMem((void *)src, &voice->vc_VoiceBuffer[0], 0x280);
3141 } else {
3142 uint32 i, WaveLoops;
3143
3144 WaveLoops = (1 << (5 - voice->vc_WaveLength)) * 5;
3145
3146 for( i=0; i<WaveLoops; i++ )
3147 IExec->CopyMem((void *)src, &voice->vc_VoiceBuffer[i*4*(1<<voice->vc_WaveLength)], 4*(1<<voice->vc_WaveLength));
3148 }
3149
3150 voice->vc_VoiceBuffer[0x280] = voice->vc_VoiceBuffer[0];
3151 voice->vc_MixSource = voice->vc_VoiceBuffer;
3152 }
3153
3154 /* Ring Modulation */
3155 if( voice->vc_RingPlantPeriod )
3156 {
3157 float64 freq2;
3158 uint32 delta;
3159
3160 voice->vc_RingPlantPeriod = 0;
3161 freq2 = Period2Freq( voice->vc_RingAudioPeriod );
3162 delta = (uint32)(freq2 / freqf);
3163
3164 if( delta > (0x280<<16) ) delta -= (0x280<<16);
3165 if( delta == 0 ) delta = 1;
3166 voice->vc_RingDelta = delta;
3167 }
3168
3169 if( voice->vc_RingNewWaveform )
3170 {
3171 int8 *src;
3172 uint32 i, WaveLoops;
3173
3174 src = voice->vc_RingAudioSource;
3175
3176 WaveLoops = (1 << (5 - voice->vc_WaveLength)) * 5;
3177
3178 for( i=0; i<WaveLoops; i++ )
3179 IExec->CopyMem((void *)src, &voice->vc_RingVoiceBuffer[i*4*(1<<voice->vc_WaveLength)], 4*(1<<voice->vc_WaveLength));
3180
3181 voice->vc_RingVoiceBuffer[0x280] = voice->vc_RingVoiceBuffer[0];
3182 voice->vc_RingMixSource = voice->vc_RingVoiceBuffer;
3183 }
3184 }
3185
rp_play_irq(struct ahx_tune * at)3186 void rp_play_irq( struct ahx_tune *at )
3187 {
3188 uint32 i;
3189
3190 if( ( rp_state != STS_PLAYNOTE ) &&
3191 ( rp_state != STS_PLAYROW ) )
3192 {
3193 if( at->at_stopnextrow > 0 )
3194 {
3195 if( ( at->at_GetNewPosition ) ||
3196 ( at->at_StepWaitFrames <= 1 ) )
3197 {
3198 at->at_stopnextrow--;
3199 if( at->at_stopnextrow == 0 )
3200 rp_state = STS_PLAYROW;
3201 }
3202 }
3203 }
3204
3205 if( ( rp_state != STS_PLAYNOTE ) &&
3206 ( rp_state != STS_PLAYROW ) )
3207 {
3208 if( at->at_StepWaitFrames <= 0 )
3209 {
3210 if( at->at_GetNewPosition )
3211 {
3212 int32 nextpos = (at->at_PosNr+1==at->at_PositionNr)?0:(at->at_PosNr+1);
3213
3214 for( i=0; i<at->at_Channels; i++ )
3215 {
3216 at->at_Voices[i].vc_Track = at->at_Positions[at->at_PosNr].pos_Track[i];
3217 at->at_Voices[i].vc_Transpose = at->at_Positions[at->at_PosNr].pos_Transpose[i];
3218 at->at_Voices[i].vc_NextTrack = at->at_Positions[nextpos].pos_Track[i];
3219 at->at_Voices[i].vc_NextTranspose = at->at_Positions[nextpos].pos_Transpose[i];
3220 }
3221 at->at_GetNewPosition = 0;
3222 }
3223
3224 for( i=0; i<at->at_Channels; i++ )
3225 rp_process_step( at, &at->at_Voices[i] );
3226
3227 at->at_StepWaitFrames = at->at_Tempo;
3228 }
3229 }
3230
3231 for( i=0; i<at->at_Channels; i++ )
3232 rp_process_frame( at, &at->at_Voices[i] );
3233
3234 if( ( rp_state != STS_PLAYNOTE ) &&
3235 ( rp_state != STS_PLAYROW ) )
3236 {
3237 at->at_PlayingTime++;
3238 if( at->at_Tempo > 0 && --at->at_StepWaitFrames <= 0 )
3239 {
3240 if( !at->at_PatternBreak )
3241 {
3242 at->at_NoteNr++;
3243 if( at->at_NoteNr >= at->at_TrackLength )
3244 {
3245 at->at_PosJump = at->at_PosNr+1;
3246 at->at_PosJumpNote = 0;
3247 at->at_PatternBreak = 1;
3248 }
3249 }
3250
3251 if( at->at_PatternBreak )
3252 {
3253 at->at_PatternBreak = 0;
3254
3255 // Manual override?
3256 if( at->at_NextPosNr != -1 )
3257 {
3258 at->at_PosNr = at->at_NextPosNr;
3259 at->at_NextPosNr = -1;
3260 at->at_NoteNr = 0;
3261 } else {
3262 if( rp_state != STS_PLAYPOS )
3263 {
3264 at->at_PosNr = at->at_PosJump;
3265 at->at_NoteNr = at->at_PosJumpNote;
3266 if( at->at_PosNr == at->at_PositionNr )
3267 {
3268 at->at_SongEndReached = 1;
3269 at->at_PosNr = at->at_Restart;
3270 }
3271 } else {
3272 at->at_NoteNr = 0;
3273 }
3274 }
3275 at->at_PosJumpNote = 0;
3276 at->at_PosJump = 0;
3277
3278 at->at_GetNewPosition = 1;
3279 }
3280 }
3281 }
3282
3283 for( i=0; i<at->at_Channels; i++ )
3284 rp_set_audio( &at->at_Voices[i], (float64)FREQ );
3285
3286 }
3287
rp_mix_findloudest(struct ahx_tune * at,uint32 samples)3288 int32 rp_mix_findloudest( struct ahx_tune *at, uint32 samples )
3289 {
3290 const int8 *src[MAX_CHANNELS];
3291 const int8 *rsrc[MAX_CHANNELS];
3292 uint32 delta[MAX_CHANNELS];
3293 uint32 rdelta[MAX_CHANNELS];
3294 int32 vol[MAX_CHANNELS];
3295 uint32 pos[MAX_CHANNELS];
3296 uint32 rpos[MAX_CHANNELS];
3297 uint32 cnt;
3298 int32 panl[MAX_CHANNELS];
3299 int32 panr[MAX_CHANNELS];
3300 int32 a=0, b=0, j;
3301 uint32 loud;
3302 uint32 i, chans, loops;
3303
3304 loud = 0;
3305
3306 chans = at->at_Channels;
3307 for( i=0; i<chans; i++ )
3308 {
3309 delta[i] = at->at_Voices[i].vc_Delta;
3310 vol[i] = at->at_Voices[i].vc_VoiceVolume;
3311 pos[i] = at->at_Voices[i].vc_SamplePos;
3312 src[i] = at->at_Voices[i].vc_MixSource;
3313 panl[i] = at->at_Voices[i].vc_PanMultLeft;
3314 panr[i] = at->at_Voices[i].vc_PanMultRight;
3315 /* Ring Modulation */
3316 rdelta[i]= at->at_Voices[i].vc_RingDelta;
3317 rpos[i] = at->at_Voices[i].vc_RingSamplePos;
3318 rsrc[i] = at->at_Voices[i].vc_RingMixSource;
3319 }
3320
3321 do
3322 {
3323 loops = samples;
3324 for( i=0; i<chans; i++ )
3325 {
3326 if( pos[i] >= (0x280 << 16)) pos[i] -= 0x280<<16;
3327 cnt = ((0x280<<16) - pos[i] - 1) / delta[i] + 1;
3328 if( cnt < loops ) loops = cnt;
3329
3330 if( rsrc[i] )
3331 {
3332 if( rpos[i] >= (0x280<<16)) rpos[i] -= 0x280<<16;
3333 cnt = ((0x280<<16) - rpos[i] - 1) / rdelta[i] + 1;
3334 if( cnt < loops ) loops = cnt;
3335 }
3336 }
3337
3338 samples -= loops;
3339
3340 // Inner loop
3341 do
3342 {
3343 a=0;
3344 b=0;
3345 for( i=0; i<chans; i++ )
3346 {
3347 if( rsrc[i] )
3348 {
3349 /* Ring Modulation */
3350 j = ((src[i][pos[i]>>16]*rsrc[i][rpos[i]>>16])>>7)*vol[i];
3351 rpos[i] += rdelta[i];
3352 } else {
3353 j = src[i][pos[i]>>16]*vol[i];
3354 }
3355 a += (j * panl[i]) >> 7;
3356 b += (j * panr[i]) >> 7;
3357 pos[i] += delta[i];
3358 }
3359
3360 // a = (a*at->at_mixgain)>>8;
3361 // b = (b*at->at_mixgain)>>8;
3362 a = abs( a );
3363 b = abs( b );
3364
3365 if( a > loud ) loud = a;
3366 if( b > loud ) loud = b;
3367
3368 loops--;
3369 } while( loops > 0 );
3370 } while( samples > 0 );
3371
3372 for( i=0; i<chans; i++ )
3373 {
3374 at->at_Voices[i].vc_SamplePos = pos[i];
3375 at->at_Voices[i].vc_RingSamplePos = rpos[i];
3376 }
3377
3378 return loud;
3379 }
3380
rp_mixchunk(struct ahx_tune * at,uint32 samples,int8 * buf1,int8 * buf2,int32 bufmod)3381 void rp_mixchunk( struct ahx_tune *at, uint32 samples, int8 *buf1, int8 *buf2, int32 bufmod )
3382 {
3383 const int8 *src[MAX_CHANNELS];
3384 const int8 *rsrc[MAX_CHANNELS];
3385 uint32 delta[MAX_CHANNELS];
3386 uint32 rdelta[MAX_CHANNELS];
3387 int32 vol[MAX_CHANNELS];
3388 uint32 pos[MAX_CHANNELS];
3389 uint32 rpos[MAX_CHANNELS];
3390 uint32 cnt;
3391 int32 panl[MAX_CHANNELS];
3392 int32 panr[MAX_CHANNELS];
3393 uint32 vu[MAX_CHANNELS];
3394 int32 a=0, b=0, j;
3395 uint32 i, chans, loops;
3396
3397 chans = at->at_Channels;
3398 for( i=0; i<chans; i++ )
3399 {
3400 delta[i] = at->at_Voices[i].vc_Delta;
3401 vol[i] = at->at_Voices[i].vc_VoiceVolume;
3402 pos[i] = at->at_Voices[i].vc_SamplePos;
3403 src[i] = at->at_Voices[i].vc_MixSource;
3404 panl[i] = at->at_Voices[i].vc_PanMultLeft;
3405 panr[i] = at->at_Voices[i].vc_PanMultRight;
3406
3407 /* Ring Modulation */
3408 rdelta[i]= at->at_Voices[i].vc_RingDelta;
3409 rpos[i] = at->at_Voices[i].vc_RingSamplePos;
3410 rsrc[i] = at->at_Voices[i].vc_RingMixSource;
3411
3412 vu[i] = 0;
3413 }
3414
3415 do
3416 {
3417 loops = samples;
3418 for( i=0; i<chans; i++ )
3419 {
3420 if( pos[i] >= (0x280 << 16)) pos[i] -= 0x280<<16;
3421 cnt = ((0x280<<16) - pos[i] - 1) / delta[i] + 1;
3422 if( cnt < loops ) loops = cnt;
3423
3424 if( rsrc[i] )
3425 {
3426 if( rpos[i] >= (0x280<<16)) rpos[i] -= 0x280<<16;
3427 cnt = ((0x280<<16) - rpos[i] - 1) / rdelta[i] + 1;
3428 if( cnt < loops ) loops = cnt;
3429 }
3430
3431 }
3432
3433 samples -= loops;
3434
3435 // Inner loop
3436 do
3437 {
3438 a=0;
3439 b=0;
3440 for( i=0; i<chans; i++ )
3441 {
3442 if( rsrc[i] )
3443 {
3444 /* Ring Modulation */
3445 j = ((src[i][pos[i]>>16]*rsrc[i][rpos[i]>>16])>>7)*vol[i];
3446 rpos[i] += rdelta[i];
3447 } else {
3448 j = src[i][pos[i]>>16]*vol[i];
3449 }
3450
3451 if( abs( j ) > vu[i] ) vu[i] = abs( j );
3452
3453 a += (j * panl[i]) >> 7;
3454 b += (j * panr[i]) >> 7;
3455 pos[i] += delta[i];
3456 }
3457
3458 a = (a*at->at_mixgain)>>8;
3459 b = (b*at->at_mixgain)>>8;
3460
3461 *(int16 *)buf1 = a;
3462 *(int16 *)buf2 = b;
3463
3464 loops--;
3465
3466 buf1 += bufmod;
3467 buf2 += bufmod;
3468 } while( loops > 0 );
3469 } while( samples > 0 );
3470
3471 for( i=0; i<chans; i++ )
3472 {
3473 at->at_Voices[i].vc_SamplePos = pos[i];
3474 at->at_Voices[i].vc_RingSamplePos = rpos[i];
3475 at->at_Voices[i].vc_VUMeter = vu[i];
3476 }
3477 }
3478
3479
rp_decode_frame(struct ahx_tune * at,int8 * buf1,int8 * buf2,int32 bufmod)3480 void rp_decode_frame( struct ahx_tune *at, int8 *buf1, int8 *buf2, int32 bufmod )
3481 {
3482 uint32 samples, loops;
3483
3484 samples = FREQ/50/at->at_SpeedMultiplier;
3485 loops = at->at_SpeedMultiplier;
3486
3487 do
3488 {
3489 rp_play_irq( at );
3490 rp_mixchunk( at, samples, buf1, buf2, bufmod );
3491 buf1 += samples * bufmod;
3492 buf2 += samples * bufmod;
3493 loops--;
3494 } while( loops );
3495
3496 if( ( rp_state == STS_PLAYSONG ) ||
3497 ( rp_state == STS_PLAYPOS ) )
3498 {
3499 if( (at->at_ticks=(at->at_ticks+1)%50) == 0 )
3500 if( (at->at_secs =(at->at_secs +1)%60) == 0 )
3501 if( (at->at_mins =(at->at_mins +1)%60) == 0 )
3502 at->at_hours++;
3503 }
3504
3505 // Update the gui!
3506 rp_curtune = at;
3507 #ifndef __SDL_WRAPPER__
3508 IExec->Signal( rp_maintask, gui_tick_sig );
3509 #else
3510 {
3511 SDL_Event event;
3512 SDL_UserEvent userevent;
3513
3514 userevent.type = SDL_USEREVENT;
3515 userevent.code = 0;
3516 userevent.data1 = NULL;
3517 userevent.data2 = NULL;
3518
3519 event.type = SDL_USEREVENT;
3520 event.user = userevent;
3521
3522 SDL_PushEvent( &event );
3523 }
3524 #endif
3525 }
3526
3527 // You'd better not be playing this bastard!
rp_find_loudest(struct ahx_tune * at)3528 int32 rp_find_loudest( struct ahx_tune *at )
3529 {
3530 uint32 rsamp, rloop;
3531 uint32 samples, loops, loud, n, i;
3532
3533 rsamp = FREQ/50/at->at_SpeedMultiplier;
3534 rloop = at->at_SpeedMultiplier;
3535
3536 loud = 0;
3537
3538 for( i=0; i<=at->at_SubsongNr; i++ )
3539 {
3540 rp_init_subsong( at, i );
3541
3542 at->at_SongEndReached = 0;
3543
3544 while( at->at_SongEndReached == 0 )
3545 {
3546 samples = rsamp;
3547 loops = rloop;
3548
3549 // if( IExec->SetSignal( 0L, SIGBREAKF_CTRL_C ) & SIGBREAKF_CTRL_C )
3550 // break;
3551 do
3552 {
3553 rp_play_irq( at );
3554 n = rp_mix_findloudest( at, samples );
3555 if( n > loud ) loud = n;
3556 loops--;
3557 } while( loops );
3558 }
3559 }
3560
3561 return loud;
3562 }
3563
3564 #ifndef __SDL_WRAPPER__
rp_alloc_buffers(void)3565 BOOL rp_alloc_buffers( void )
3566 {
3567 int32 i;
3568
3569 if( rp_audiobuffer[0] ) IExec->FreePooled( rp_mempool, rp_audiobuffer[0], rp_audiobuflen * 2 );
3570
3571 rp_freqf = (float64)FREQ;
3572 rp_audiobuflen = FREQ * sizeof( uint16 ) * 2 / 50;
3573
3574 rp_audiobuffer[0] = IExec->AllocPooled( rp_mempool, rp_audiobuflen * 2 );
3575 if( rp_audiobuffer[0] == NULL ) return FALSE;
3576
3577 rp_audiobuffer[1] = &rp_audiobuffer[0][rp_audiobuflen];
3578
3579 for( i=0; i<rp_audiobuflen; i++ )
3580 rp_audiobuffer[0][i] = 0;
3581
3582 return TRUE;
3583 }
3584
rp_subtask_init(void)3585 BOOL rp_subtask_init( void )
3586 {
3587 if( !rp_alloc_buffers() ) return FALSE;
3588
3589 rp_msgport = IExec->AllocSysObjectTags(ASOT_PORT, TAG_DONE);
3590 if( !rp_msgport ) return FALSE;
3591
3592 ahi_mp = IExec->AllocSysObjectTags(ASOT_PORT, TAG_DONE);
3593 if( !ahi_mp ) return FALSE;
3594
3595 ahi_io[0] = (struct AHIRequest *)IExec->AllocSysObjectTags(ASOT_IOREQUEST,
3596 ASOIOR_ReplyPort, ahi_mp,
3597 ASOIOR_Size, sizeof( struct AHIRequest ),
3598 TAG_DONE);
3599 if( ahi_io[0] == NULL ) return FALSE;
3600
3601 ahi_io[0]->ahir_Version = 4;
3602
3603 ahi_dev = IExec->OpenDevice( AHINAME, AHI_DEFAULT_UNIT, (struct IORequest *)ahi_io[0], 0 );
3604 if( ahi_dev == -1 ) return FALSE;
3605
3606 AHIBase = (struct Library *)ahi_io[0]->ahir_Std.io_Device;
3607 IAHI = (struct AHIIFace *)IExec->GetInterface( AHIBase, "main", 1, NULL );
3608 if( !IAHI ) return FALSE;
3609
3610 ahi_io[1] = IExec->AllocSysObjectTags(ASOT_IOREQUEST, ASOIOR_Size, sizeof( struct AHIRequest ), ASOIOR_Duplicate, ahi_io[0], TAG_DONE );
3611 if( ahi_io[1] == NULL ) return FALSE;
3612
3613 return TRUE;
3614 }
3615
rp_subtask_shut(void)3616 void rp_subtask_shut( void )
3617 {
3618 if( IAHI ) IExec->DropInterface( (struct Interface *)IAHI );
3619 if( ahi_dev != -1 )
3620 {
3621 IExec->CloseDevice( (struct IORequest *)ahi_io[0] );
3622 IExec->FreeSysObject( ASOT_IOREQUEST, ahi_io[0] );
3623 }
3624 if( ahi_io[1] ) IExec->FreeSysObject( ASOT_IOREQUEST, ahi_io[1] );
3625 if( ahi_mp ) IExec->FreeSysObject( ASOT_PORT, ahi_mp );
3626 if( rp_msgport )
3627 {
3628 struct Message *msg;
3629 while( ( msg = IExec->GetMsg( rp_msgport ) ) ) IExec->ReplyMsg( msg );
3630 IExec->FreeSysObject( ASOT_PORT, rp_msgport );
3631 rp_msgport = NULL;
3632 }
3633 if( rp_audiobuffer[0] ) IExec->FreePooled( rp_mempool, rp_audiobuffer[0], rp_audiobuflen * 2 );
3634 }
3635
rp_mix_and_play_sounds(struct ahx_tune * at,BOOL * need_wait,struct AHIRequest ** prev_req,uint32 * nextbuf)3636 void rp_mix_and_play_sounds( struct ahx_tune *at, BOOL *need_wait, struct AHIRequest **prev_req, uint32 *nextbuf )
3637 {
3638 int32 rp_nextbuf;
3639
3640 rp_nextbuf = *nextbuf;
3641
3642 if( need_wait[rp_nextbuf] )
3643 IExec->WaitIO( (struct IORequest *)ahi_io[rp_nextbuf] );
3644
3645 rp_decode_frame( at, rp_audiobuffer[rp_nextbuf], rp_audiobuffer[rp_nextbuf]+sizeof( int16 ), 4 );
3646
3647 ahi_io[rp_nextbuf]->ahir_Std.io_Command = CMD_WRITE;
3648 ahi_io[rp_nextbuf]->ahir_Std.io_Data = rp_audiobuffer[rp_nextbuf];
3649 ahi_io[rp_nextbuf]->ahir_Std.io_Length = rp_audiobuflen;
3650 ahi_io[rp_nextbuf]->ahir_Std.io_Offset = 0;
3651 ahi_io[rp_nextbuf]->ahir_Type = AHIST_S16S;
3652 ahi_io[rp_nextbuf]->ahir_Frequency = rp_freq;
3653 ahi_io[rp_nextbuf]->ahir_Volume = 0x10000;
3654 ahi_io[rp_nextbuf]->ahir_Position = 0x8000;
3655 ahi_io[rp_nextbuf]->ahir_Link = *prev_req;
3656 IExec->SendIO( (struct IORequest *)ahi_io[rp_nextbuf] );
3657
3658 *prev_req = ahi_io[rp_nextbuf];
3659 need_wait[rp_nextbuf] = TRUE;
3660
3661 rp_nextbuf ^= 1;
3662
3663 if( ( need_wait[rp_nextbuf] == TRUE ) &&
3664 ( IExec->CheckIO( (struct IORequest *)ahi_io[rp_nextbuf] ) != NULL ) )
3665 {
3666 IExec->WaitIO( (struct IORequest *)ahi_io[rp_nextbuf] );
3667 need_wait[rp_nextbuf] = FALSE;
3668 }
3669
3670 if( need_wait[rp_nextbuf] == FALSE )
3671 {
3672 rp_decode_frame( at, rp_audiobuffer[rp_nextbuf], rp_audiobuffer[rp_nextbuf]+sizeof( int16 ), 4 );
3673
3674 ahi_io[rp_nextbuf]->ahir_Std.io_Command = CMD_WRITE;
3675 ahi_io[rp_nextbuf]->ahir_Std.io_Data = rp_audiobuffer[rp_nextbuf];
3676 ahi_io[rp_nextbuf]->ahir_Std.io_Length = rp_audiobuflen;
3677 ahi_io[rp_nextbuf]->ahir_Std.io_Offset = 0;
3678 ahi_io[rp_nextbuf]->ahir_Type = AHIST_S16S;
3679 ahi_io[rp_nextbuf]->ahir_Frequency = rp_freq;
3680 ahi_io[rp_nextbuf]->ahir_Volume = 0x10000;
3681 ahi_io[rp_nextbuf]->ahir_Position = 0x8000;
3682 ahi_io[rp_nextbuf]->ahir_Link = *prev_req;
3683 IExec->SendIO( (struct IORequest *)ahi_io[rp_nextbuf] );
3684
3685 *prev_req = ahi_io[rp_nextbuf];
3686 need_wait[rp_nextbuf] = TRUE;
3687 rp_nextbuf ^= 1;
3688 }
3689 *nextbuf = rp_nextbuf;
3690 }
3691
rp_subtask_main(void)3692 void rp_subtask_main( void )
3693 {
3694 uint32 gotsigs;
3695 uint32 rp_msgsig, rp_ahisig;
3696 uint32 rp_nextbuf, i;
3697 BOOL need_wait[2];
3698 struct ahx_tune *rp_tune;
3699 struct rp_command *msg;
3700
3701 if( rp_subtask_init() )
3702 {
3703 rp_state = STS_IDLE;
3704 rp_tune = NULL;
3705 rp_msgsig = 1L<<rp_msgport->mp_SigBit;
3706 rp_ahisig = 1L<<ahi_mp->mp_SigBit;
3707 rp_nextbuf = 0;
3708 need_wait[0] = FALSE;
3709 need_wait[1] = FALSE;
3710 struct AHIRequest *prev_req = NULL;
3711
3712 IExec->Signal( rp_maintask, (1L<<rp_subtask_sig) );
3713
3714 // IExec->DebugPrintF( "Replayer subtask, ready for action!\n" );
3715
3716 while( 1 )
3717 {
3718 gotsigs = IExec->Wait( rp_msgsig | rp_ahisig | SIGBREAKF_CTRL_C );
3719
3720 if( gotsigs & rp_msgsig )
3721 {
3722 while( ( msg = (struct rp_command *)IExec->GetMsg( rp_msgport ) ) )
3723 {
3724 // IExec->DebugPrintF( "Got command %ld, %ld, %08lX\n", msg->rpc_Command, msg->rpc_Data, msg->rpc_Tune );
3725 switch( msg->rpc_Command )
3726 {
3727 case RPC_STOP:
3728 if( need_wait[0] ) IExec->WaitIO( (struct IORequest *)ahi_io[0] );
3729 if( need_wait[1] ) IExec->WaitIO( (struct IORequest *)ahi_io[1] );
3730 need_wait[0] = need_wait[1] = FALSE;
3731 if( rp_tune )
3732 {
3733 for( i=0; i<MAX_CHANNELS; i++ )
3734 {
3735 rp_tune->at_Voices[i].vc_TrackOn = 0;
3736 rp_tune->at_Voices[i].vc_VUMeter = 0;
3737 }
3738 if( rp_tune->at_NextPosNr != -1 )
3739 {
3740 rp_tune->at_PosNr = rp_tune->at_NextPosNr;
3741 rp_tune->at_NextPosNr = -1;
3742 IExec->Signal( rp_maintask, gui_tick_sig );
3743 }
3744 rp_tune = NULL;
3745 }
3746 rp_state = STS_IDLE;
3747 break;
3748
3749 case RPC_PLAY_NOTE:
3750 if( rp_tune != msg->rpc_Tune )
3751 {
3752 if( need_wait[0] ) IExec->WaitIO( (struct IORequest *)ahi_io[0] );
3753 if( need_wait[1] ) IExec->WaitIO( (struct IORequest *)ahi_io[1] );
3754 need_wait[0] = need_wait[1] = FALSE;
3755 rp_tune = msg->rpc_Tune;
3756 }
3757
3758 if( rp_tune != NULL )
3759 {
3760 rp_play_instrument( rp_tune, msg->rpc_Data2>>8, msg->rpc_Data, msg->rpc_Data2&0xff );
3761 gotsigs |= rp_ahisig;
3762 rp_state = STS_PLAYNOTE;
3763 }
3764 break;
3765
3766 case RPC_PLAY_ROW:
3767 if( msg->rpc_Tune != NULL )
3768 {
3769 struct ahx_tune *ttune;
3770 ttune = rp_tune;
3771 rp_tune = msg->rpc_Tune;
3772 rp_tune->at_stopnextrow = 3;
3773 rp_tune->at_GetNewPosition = 1;
3774 rp_tune->at_ticks = rp_tune->at_secs = rp_tune->at_mins = rp_tune->at_hours = 0;
3775 if( ( rp_tune != ttune ) || ( rp_state != STS_PLAYROW ) )
3776 rp_reset_some_shit( rp_tune );
3777 gotsigs |= rp_ahisig;
3778 rp_state = STS_PLAYPOS;
3779 }
3780 break;
3781
3782 case RPC_CONT_POS:
3783 case RPC_PLAY_POS:
3784 if( rp_tune )
3785 {
3786 if( rp_tune->at_doing == D_PLAYING )
3787 rp_tune->at_doing = D_IDLE;
3788 }
3789
3790 rp_tune = msg->rpc_Tune;
3791
3792 if( rp_tune != NULL )
3793 {
3794 rp_tune->at_stopnextrow = 0;
3795 if( msg->rpc_Command == RPC_PLAY_POS )
3796 rp_tune->at_NoteNr = 0;
3797
3798 rp_tune->at_PosJumpNote = 0;
3799 rp_tune->at_StepWaitFrames = 0;
3800 rp_tune->at_GetNewPosition = 1;
3801 rp_tune->at_ticks = rp_tune->at_secs = rp_tune->at_mins = rp_tune->at_hours = 0;
3802 rp_reset_some_shit( rp_tune );
3803 gotsigs |= rp_ahisig;
3804 rp_state = STS_PLAYPOS;
3805 }
3806 break;
3807
3808 case RPC_CONT_SONG:
3809 case RPC_PLAY_SONG:
3810 if( rp_tune )
3811 {
3812 if( rp_tune->at_doing == D_PLAYING )
3813 rp_tune->at_doing = D_IDLE;
3814 }
3815
3816 rp_tune = msg->rpc_Tune;
3817 if( rp_tune != NULL )
3818 {
3819 rp_tune->at_stopnextrow = 0;
3820 if( msg->rpc_Command == RPC_PLAY_SONG )
3821 rp_tune->at_NoteNr = 0;
3822
3823 rp_tune->at_PosJumpNote = 0;
3824 rp_tune->at_StepWaitFrames = 0;
3825 rp_tune->at_GetNewPosition = 1;
3826 rp_tune->at_ticks = rp_tune->at_secs = rp_tune->at_mins = rp_tune->at_hours = 0;
3827 rp_reset_some_shit( rp_tune );
3828 }
3829
3830 if( rp_tune )
3831 {
3832 rp_state = STS_PLAYSONG;
3833 gotsigs |= rp_ahisig;
3834 } else {
3835 rp_state = STS_IDLE;
3836 }
3837
3838 msg->rpc_Tune = rp_tune;
3839 break;
3840 }
3841
3842 IExec->ReplyMsg( (struct Message *)msg );
3843 }
3844 }
3845
3846 if( gotsigs & SIGBREAKF_CTRL_C ) break;
3847
3848 if( gotsigs & rp_ahisig )
3849 {
3850 BOOL anychan;
3851 switch( rp_state )
3852 {
3853 case STS_CALCULATING:
3854 case STS_IDLE:
3855 prev_req = NULL;
3856 break;
3857 case STS_PLAYNOTE:
3858 case STS_PLAYROW:
3859 if( rp_tune == NULL )
3860 {
3861 rp_state = STS_IDLE;
3862 break;
3863 }
3864
3865 anychan = FALSE;
3866 for( i=0; i<rp_tune->at_Channels; i++ )
3867 if( rp_tune->at_Voices[i].vc_TrackOn )
3868 {
3869 anychan = TRUE;
3870 break;
3871 }
3872
3873 if( anychan == FALSE )
3874 {
3875 rp_state = STS_IDLE;
3876 break;
3877 }
3878
3879 rp_mix_and_play_sounds( rp_tune, &need_wait[0], &prev_req, &rp_nextbuf );
3880 break;
3881
3882 case STS_PLAYPOS:
3883 case STS_PLAYSONG:
3884 if( rp_tune == NULL )
3885 {
3886 rp_state = STS_IDLE;
3887 break;
3888 }
3889
3890 rp_mix_and_play_sounds( rp_tune, &need_wait[0], &prev_req, &rp_nextbuf );
3891
3892 break;
3893 default:
3894 // Unknown state?!
3895 rp_state = STS_IDLE;
3896 }
3897 }
3898 }
3899 }
3900 rp_subtask_shut();
3901 rp_state = STS_DEADED;
3902 IExec->Signal( rp_maintask, (1L<<rp_subtask_sig) );
3903 }
3904 #else
do_the_music(void * dummy,int8 * stream,int length)3905 void do_the_music( void *dummy, int8 *stream, int length )
3906 {
3907 if((rp_state != STS_IDLE) && (rp_playtune))
3908 {
3909 int i;
3910
3911 for (i=0; i<(length/2); i+=((FREQ/50)*2))
3912 rp_decode_frame( rp_playtune, (int8*)&rp_audiobuffer[i], (int8*)&rp_audiobuffer[i+1], 4 );
3913 memcpy(stream, rp_audiobuffer, length);
3914 }
3915 else
3916 {
3917 if (stream && length)
3918 memset(stream, 0, length);
3919 }
3920
3921 rp_state_ack = rp_state;
3922 }
3923 #endif
3924
rp_init(void)3925 BOOL rp_init( void )
3926 {
3927 #ifdef __SDL_WRAPPER__
3928 SDL_AudioSpec wanted;
3929 #endif
3930
3931 #ifndef __SDL_WRAPPER__
3932 rp_maintask = IExec->FindTask( NULL );
3933
3934 rp_subtask_sig = IExec->AllocSignal( -1 );
3935 if( rp_subtask_sig == -1 )
3936 {
3937 printf( "Unable to allocate signal\n" );
3938 return FALSE;
3939 }
3940
3941 rp_mempool = IExec->AllocSysObjectTags( ASOT_MEMPOOL,
3942 ASOPOOL_Puddle, 8192,
3943 ASOPOOL_Threshold, 8000,
3944 ASOPOOL_Protected, TRUE,
3945 TAG_DONE );
3946 if( !rp_mempool )
3947 {
3948 printf( "Unable to create memory pool\n" );
3949 return FALSE;
3950 }
3951 #endif
3952
3953 rp_tunelist = IExec->AllocSysObjectTags( ASOT_LIST, TAG_DONE );
3954 if( !rp_tunelist )
3955 {
3956 printf( "Out of memory @ %s:%d\n", __FILE__, __LINE__ );
3957 return FALSE;
3958 }
3959
3960 rp_list_ss = IExec->AllocSysObjectTags( ASOT_SEMAPHORE, TAG_DONE );
3961 if( !rp_list_ss )
3962 {
3963 printf( "Out of memory @ %s:%d\n", __FILE__, __LINE__ );
3964 return FALSE;
3965 }
3966
3967 #ifndef __SDL_WRAPPER__
3968 rp_replyport = IExec->AllocSysObject(ASOT_PORT, TAG_DONE);
3969 if( !rp_replyport )
3970 {
3971 printf( "Unable to create a message port\n" );
3972 return FALSE;
3973 }
3974
3975 rp_mainmsg = IExec->AllocSysObjectTags( ASOT_MESSAGE,
3976 ASOMSG_Size, sizeof( struct rp_command ),
3977 ASOMSG_ReplyPort, rp_replyport,
3978 TAG_DONE );
3979 #else
3980 rp_mainmsg = malloc(sizeof(struct rp_command));
3981 #endif
3982
3983 if( !rp_mainmsg )
3984 {
3985 printf( "Out of memory @ %s:%d\n", __FILE__, __LINE__ );
3986 return FALSE;
3987 }
3988
3989 rp_GenPanningTables();
3990 rp_GenSawtooth( &waves[WO_SAWTOOTH_04], 0x04 );
3991 rp_GenSawtooth( &waves[WO_SAWTOOTH_08], 0x08 );
3992 rp_GenSawtooth( &waves[WO_SAWTOOTH_10], 0x10 );
3993 rp_GenSawtooth( &waves[WO_SAWTOOTH_20], 0x20 );
3994 rp_GenSawtooth( &waves[WO_SAWTOOTH_40], 0x40 );
3995 rp_GenSawtooth( &waves[WO_SAWTOOTH_80], 0x80 );
3996 rp_GenTriangle( &waves[WO_TRIANGLE_04], 0x04 );
3997 rp_GenTriangle( &waves[WO_TRIANGLE_08], 0x08 );
3998 rp_GenTriangle( &waves[WO_TRIANGLE_10], 0x10 );
3999 rp_GenTriangle( &waves[WO_TRIANGLE_20], 0x20 );
4000 rp_GenTriangle( &waves[WO_TRIANGLE_40], 0x40 );
4001 rp_GenTriangle( &waves[WO_TRIANGLE_80], 0x80 );
4002 rp_GenSquare( &waves[WO_SQUARES] );
4003 rp_GenWhiteNoise( &waves[WO_WHITENOISE], WHITENOISELEN );
4004 rp_GenFilterWaves( &waves[WO_TRIANGLE_04], &waves[WO_LOWPASSES], &waves[WO_HIGHPASSES] );
4005
4006 #ifndef __SDL_WRAPPER__
4007 rp_subtask = IDOS->CreateNewProcTags( NP_Name, "ahx2006 Player Task",
4008 NP_Entry, rp_subtask_main,
4009 NP_Priority, 30,
4010 NP_Child, TRUE,
4011 TAG_DONE );
4012 if( rp_subtask == NULL )
4013 {
4014 printf( "Unable to create audio task\n" );
4015 return FALSE;
4016 }
4017
4018 IExec->Wait( (1L<<rp_subtask_sig) );
4019 if( rp_state == STS_DEADED )
4020 {
4021 printf( "Unable to initialise audio\n" );
4022 rp_subtask = NULL;
4023 return FALSE;
4024 }
4025
4026 rp_sigs = ((1L<<rp_subtask_sig)|(1L<<rp_replyport->mp_SigBit));
4027 #endif
4028
4029 rp_new_tune( TRUE );
4030
4031 #ifdef __SDL_WRAPPER__
4032 wanted.freq = FREQ;
4033 wanted.format = AUDIO_S16SYS;
4034 wanted.channels = 2; /* 1 = mono, 2 = stereo */
4035 wanted.samples = OUTPUT_LEN; // HIVELY_LEN;
4036
4037 wanted.callback = (void*)do_the_music;
4038 wanted.userdata = 0;
4039
4040 if( SDL_OpenAudio( &wanted, NULL ) < 0 )
4041 {
4042 printf( "SDL says: %s\n", SDL_GetError() );
4043 return FALSE;
4044 }
4045
4046 SDL_PauseAudio(0);
4047 #endif
4048 return TRUE;
4049 }
4050
rp_shutdown(void)4051 void rp_shutdown( void )
4052 {
4053 if( rp_tunelist )
4054 {
4055 rp_free_all_tunes();
4056 IExec->FreeSysObject( ASOT_LIST, rp_tunelist );
4057 }
4058
4059 if( rp_list_ss ) IExec->FreeSysObject( ASOT_SEMAPHORE, rp_list_ss );
4060
4061 #ifndef __SDL_WRAPPER__
4062 if( rp_subtask )
4063 {
4064 IExec->Signal( (struct Task *)rp_subtask, SIGBREAKF_CTRL_C );
4065 IExec->Wait( (1L<<rp_subtask_sig) );
4066 }
4067
4068 if( rp_mainmsg ) IExec->FreeSysObject( ASOT_MESSAGE, rp_mainmsg );
4069
4070 if( rp_replyport ) IExec->FreeSysObject( ASOT_PORT, rp_replyport );
4071
4072 if( rp_mempool ) IExec->FreeSysObject( ASOT_MEMPOOL, rp_mempool );
4073
4074 if( rp_subtask_sig != -1 ) IExec->FreeSignal( rp_subtask_sig );
4075 #else
4076 SDL_PauseAudio(1);
4077 if( rp_mainmsg ) free(rp_mainmsg);
4078 #endif
4079 }
4080
4081 #ifndef __SDL_WRAPPER__
rp_handler(uint32 gotsigs)4082 void rp_handler( uint32 gotsigs )
4083 {
4084 // audio subtask has quit!
4085 if( gotsigs & (1L<<rp_subtask_sig) )
4086 {
4087 rp_subtask = NULL;
4088 quitting = TRUE;
4089 return;
4090 }
4091 }
4092 #endif
4093
4094 #ifdef __SDL_WRAPPER__
set_player_state(uint32 newstate)4095 static void set_player_state(uint32 newstate)
4096 {
4097 rp_state = newstate;
4098 while (rp_state_ack != newstate)
4099 {
4100 usleep(1000);
4101 }
4102 }
4103 #endif
4104
rp_send_command(struct rp_command * cmd)4105 void rp_send_command( struct rp_command *cmd )
4106 {
4107 #ifndef __SDL_WRAPPER__
4108 uint32 wsigs, gsigs;
4109
4110 wsigs = (1L<<rp_replyport->mp_SigBit)|(1L<<rp_subtask_sig);
4111
4112 IExec->PutMsg( rp_msgport, (struct Message *)rp_mainmsg );
4113
4114 gsigs = IExec->Wait( wsigs );
4115
4116 if( gsigs & (1L<<rp_replyport->mp_SigBit))
4117 IExec->GetMsg( rp_replyport );
4118
4119 if( gsigs & (1L<<rp_subtask_sig) )
4120 {
4121 // If we got this signal, the subtask has
4122 // quit and we won't get a reply ever anyway. (== shit)
4123 quitting = TRUE;
4124 }
4125 #else
4126 int i;
4127 switch (cmd->rpc_Command)
4128 {
4129 case RPC_CONT_POS:
4130 case RPC_PLAY_POS:
4131 case RPC_CONT_SONG:
4132 case RPC_PLAY_SONG:
4133 set_player_state(STS_IDLE);
4134 if( rp_playtune )
4135 {
4136 if( rp_playtune->at_doing == D_PLAYING )
4137 rp_playtune->at_doing = D_IDLE;
4138 }
4139
4140 rp_playtune = cmd->rpc_Tune;
4141 if( rp_playtune != NULL )
4142 {
4143 rp_playtune->at_stopnextrow = 0;
4144 if( cmd->rpc_Command == RPC_PLAY_SONG )
4145 rp_playtune->at_NoteNr = 0;
4146
4147 rp_playtune->at_PosJumpNote = 0;
4148 rp_playtune->at_StepWaitFrames = 0;
4149 rp_playtune->at_GetNewPosition = 1;
4150 rp_playtune->at_ticks = rp_playtune->at_secs = rp_playtune->at_mins = rp_playtune->at_hours = 0;
4151 rp_reset_some_shit( rp_playtune );
4152 }
4153 break;
4154
4155 case RPC_PLAY_ROW:
4156 if( cmd->rpc_Tune != NULL )
4157 {
4158 if (cmd->rpc_Tune != rp_playtune)
4159 set_player_state(STS_IDLE);
4160
4161 ;
4162 cmd->rpc_Tune->at_stopnextrow = 3;
4163 cmd->rpc_Tune->at_GetNewPosition = 1;
4164 cmd->rpc_Tune->at_ticks = cmd->rpc_Tune->at_secs = cmd->rpc_Tune->at_mins = cmd->rpc_Tune->at_hours = 0;
4165 if( ( rp_playtune != cmd->rpc_Tune ) || ( rp_state != STS_PLAYROW ) )
4166 {
4167 rp_reset_some_shit( cmd->rpc_Tune );
4168 rp_playtune = cmd->rpc_Tune;
4169 }
4170 rp_state = STS_PLAYPOS;
4171 }
4172 break;
4173
4174 case RPC_PLAY_NOTE:
4175 if( rp_playtune != cmd->rpc_Tune )
4176 {
4177 set_player_state(STS_IDLE);
4178 rp_playtune = cmd->rpc_Tune;
4179 }
4180
4181 if( rp_playtune != NULL )
4182 {
4183 rp_play_instrument( rp_playtune, cmd->rpc_Data2>>8, cmd->rpc_Data, cmd->rpc_Data2&0xff );
4184 rp_state = STS_PLAYNOTE;
4185 }
4186 break;
4187
4188 case RPC_STOP:
4189 set_player_state(STS_IDLE);
4190 if( rp_playtune )
4191 {
4192 for( i=0; i<MAX_CHANNELS; i++ )
4193 {
4194 rp_playtune->at_Voices[i].vc_TrackOn = 0;
4195 rp_playtune->at_Voices[i].vc_VUMeter = 0;
4196 }
4197 if( rp_playtune->at_NextPosNr != -1 )
4198 {
4199 SDL_Event event;
4200 SDL_UserEvent userevent;
4201
4202 rp_playtune->at_PosNr = rp_playtune->at_NextPosNr;
4203 rp_playtune->at_NextPosNr = -1;
4204
4205 userevent.type = SDL_USEREVENT;
4206 userevent.code = 0;
4207 userevent.data1 = NULL;
4208 userevent.data2 = NULL;
4209
4210 event.type = SDL_USEREVENT;
4211 event.user = userevent;
4212
4213 SDL_PushEvent( &event );
4214 }
4215 rp_playtune = NULL;
4216 }
4217 break;
4218 }
4219
4220 switch (cmd->rpc_Command)
4221 {
4222 case RPC_CONT_POS:
4223 case RPC_PLAY_POS:
4224 rp_state = STS_PLAYPOS;
4225 break;
4226
4227 case RPC_CONT_SONG:
4228 case RPC_PLAY_SONG:
4229 if( rp_playtune )
4230 {
4231 rp_state = STS_PLAYSONG;
4232 } else {
4233 rp_state = STS_IDLE;
4234 }
4235
4236 cmd->rpc_Tune = rp_playtune;
4237 rp_curtune = rp_playtune;
4238 break;
4239 }
4240 #endif
4241 }
4242
rp_play_song(struct ahx_tune * at,uint32 subsong,BOOL cont)4243 BOOL rp_play_song( struct ahx_tune *at, uint32 subsong, BOOL cont )
4244 {
4245 rp_mainmsg->rpc_Command = cont ? RPC_CONT_SONG : RPC_PLAY_SONG;
4246 rp_mainmsg->rpc_Tune = at;
4247 rp_mainmsg->rpc_Data = subsong;
4248 rp_mainmsg->rpc_Data2 = 0;
4249
4250 rp_send_command( rp_mainmsg );
4251
4252 return (rp_mainmsg->rpc_Tune == at);
4253 }
4254
rp_play_pos(struct ahx_tune * at,BOOL cont)4255 BOOL rp_play_pos( struct ahx_tune *at, BOOL cont )
4256 {
4257 rp_mainmsg->rpc_Command = cont ? RPC_CONT_POS : RPC_PLAY_POS;
4258 rp_mainmsg->rpc_Tune = at;
4259 rp_mainmsg->rpc_Data = 0;
4260 rp_mainmsg->rpc_Data2 = 0;
4261
4262 rp_send_command( rp_mainmsg );
4263
4264 return (rp_mainmsg->rpc_Tune == at);
4265 }
4266
rp_play_row(struct ahx_tune * at)4267 BOOL rp_play_row( struct ahx_tune *at )
4268 {
4269 rp_mainmsg->rpc_Command = RPC_PLAY_ROW;
4270 rp_mainmsg->rpc_Tune = at;
4271 rp_mainmsg->rpc_Data = 0;
4272 rp_mainmsg->rpc_Data2 = 0;
4273
4274 rp_send_command( rp_mainmsg );
4275
4276 return (rp_mainmsg->rpc_Tune == at);
4277 }
4278
rp_play_note(struct ahx_tune * at,int32 inst,int32 note,int32 channel)4279 BOOL rp_play_note( struct ahx_tune *at, int32 inst, int32 note, int32 channel )
4280 {
4281 if( ( note < 1 ) || ( note > 60 ) )
4282 return TRUE;
4283
4284 rp_mainmsg->rpc_Command = RPC_PLAY_NOTE;
4285 rp_mainmsg->rpc_Tune = at;
4286 rp_mainmsg->rpc_Data = inst;
4287 rp_mainmsg->rpc_Data2 = (channel<<8)|note;
4288
4289 rp_send_command( rp_mainmsg );
4290
4291 return (rp_mainmsg->rpc_Tune == at);
4292 }
4293
rp_stop(void)4294 void rp_stop( void )
4295 {
4296 rp_mainmsg->rpc_Command = RPC_STOP;
4297 rp_mainmsg->rpc_Tune = NULL;
4298 rp_mainmsg->rpc_Data = 0;
4299 rp_mainmsg->rpc_Data2 = 0;
4300
4301 rp_send_command( rp_mainmsg );
4302
4303 #ifdef __SDL_WRAPPER__
4304 memset(rp_audiobuffer, 0, sizeof(rp_audiobuffer));
4305 #endif
4306 }
4307
rp_zap_tracks(struct ahx_tune * at)4308 void rp_zap_tracks( struct ahx_tune * at )
4309 {
4310 uint32 i, j;
4311
4312 if( !at ) return;
4313 if( at == rp_curtune ) rp_stop();
4314
4315 for( i=0; i<256; i++ )
4316 for( j=0; j<64; j++ )
4317 {
4318 at->at_Tracks[i][j].stp_Note = 0;
4319 at->at_Tracks[i][j].stp_Instrument = 0;
4320 at->at_Tracks[i][j].stp_FX = 0;
4321 at->at_Tracks[i][j].stp_FXParam = 0;
4322 at->at_Tracks[i][j].stp_FXb = 0;
4323 at->at_Tracks[i][j].stp_FXbParam = 0;
4324 }
4325 }
4326
rp_zap_positions(struct ahx_tune * at)4327 void rp_zap_positions( struct ahx_tune *at )
4328 {
4329 uint32 i, j;
4330
4331 if( !at ) return;
4332 if( at == rp_curtune ) rp_stop();
4333
4334 for( i=0; i<1000; i++ )
4335 {
4336 for( j=0; j<MAX_CHANNELS; j++ )
4337 {
4338 at->at_Positions[i].pos_Track[j] = 0;
4339 at->at_Positions[i].pos_Transpose[j] = 0;
4340 }
4341 }
4342
4343 for( i=0; i<256; i++ )
4344 at->at_Subsongs[i] = 0;
4345
4346 at->at_SubsongNr = 0;
4347 at->at_curss = 0;
4348 at->at_PosNr = 0;
4349 at->at_Restart = 0;
4350 }
4351
rp_zap_instruments(struct ahx_tune * at)4352 void rp_zap_instruments( struct ahx_tune *at )
4353 {
4354 uint32 i;
4355
4356 if( !at ) return;
4357 if( at == rp_curtune ) rp_stop();
4358
4359 for( i=0; i<64; i++ )
4360 rp_clear_instrument( &at->at_Instruments[i] );
4361 }
4362