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