~ubuntu-branches/debian/jessie/audacious-plugins/jessie

« back to all changes in this revision

Viewing changes to src/psf/peops/registers.c

  • Committer: Package Import Robot
  • Author(s): Alessio Treglia
  • Date: 2012-02-20 00:28:16 UTC
  • mfrom: (1.1.16)
  • Revision ID: package-import@ubuntu.com-20120220002816-mgn4vhn314z6mubs
Tags: 3.2.1-1
* Team upload.
* New upstream bugfix release.
* Remove correct_spelling_error.diff, applied upstream.
* Refresh ffaudio.diff.
* Reintroduce src/psf/*, it seems DFSG clean now.
* Fix and update debian/copyright.
* Update watch file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
                         registers.c  -  description
 
3
                             -------------------
 
4
    begin                : Wed May 15 2002
 
5
    copyright            : (C) 2002 by Pete Bernert
 
6
    email                : BlackDove@addcom.de
 
7
 ***************************************************************************/
 
8
 
 
9
/***************************************************************************
 
10
 *                                                                         *
 
11
 *   This program is free software; you can redistribute it and/or modify  *
 
12
 *   it under the terms of the GNU General Public License as published by  *
 
13
 *   the Free Software Foundation; either version 2 of the License, or     *
 
14
 *   (at your option) any later version. See also the license.txt file for *
 
15
 *   additional informations.                                              *
 
16
 *                                                                         *
 
17
 ***************************************************************************/
 
18
 
 
19
/* ChangeLog 
 
20
 
 
21
 February 8, 2004       -       xodnizel
 
22
 - Fixed setting of reverb volume.  Just typecast val("u16") to s16.
 
23
   Also adjusted the normal channel volume to be one less than what it was before when the 
 
24
   "phase invert" bit is set.  I'm assuming it's just in two's complement.
 
25
 
 
26
 2003/02/09 - kode54
 
27
 - removed &0x3fff from reverb volume registers, fixes a few games,
 
28
   hopefully won't be breaking anything
 
29
 
 
30
 2003/01/19 - Pete
 
31
 - added Neill's reverb
 
32
 
 
33
 2003/01/06 - Pete
 
34
 - added Neill's ADSR timings
 
35
 
 
36
 2002/05/15 - Pete
 
37
 - generic cleanup for the Peops release
 
38
 
 
39
*/
 
40
 
 
41
#include "stdafx.h"
 
42
 
 
43
#define _IN_REGISTERS
 
44
 
 
45
#include "../peops/externals.h"
 
46
#include "../peops/registers.h"
 
47
#include "../peops/regs.h"
 
48
 
 
49
static void SoundOn(int start,int end,u16 val);
 
50
static void SoundOff(int start,int end,u16 val);
 
51
static void FModOn(int start,int end,u16 val);
 
52
static void NoiseOn(int start,int end,u16 val);
 
53
static void SetVolumeLR(int right, u8 ch,s16 vol);
 
54
static void SetPitch(int ch,u16 val);
 
55
 
 
56
////////////////////////////////////////////////////////////////////////
 
57
// WRITE REGISTERS: called by main emu
 
58
////////////////////////////////////////////////////////////////////////
 
59
 
 
60
void SPUwriteRegister(u32 reg, u16 val)
 
61
{
 
62
 const u32 r=reg&0xfff;
 
63
 regArea[(r-0xc00)>>1] = val;
 
64
 
 
65
// printf("SPUwrite: r %x val %x\n", r, val);
 
66
 
 
67
 if(r>=0x0c00 && r<0x0d80)                             // some channel info?
 
68
  {
 
69
   int ch=(r>>4)-0xc0;                                 // calc channel
 
70
 
 
71
   //if(ch==20) printf("%08x: %04x\n",reg,val);
 
72
 
 
73
   switch(r&0x0f)
 
74
    {
 
75
     //------------------------------------------------// r volume
 
76
     case 0:                                           
 
77
       SetVolumeLR(0,(u8)ch,val);
 
78
       break;
 
79
     //------------------------------------------------// l volume
 
80
     case 2:                                           
 
81
       SetVolumeLR(1,(u8)ch,val);
 
82
       break;
 
83
     //------------------------------------------------// pitch
 
84
     case 4:                                           
 
85
       SetPitch(ch,val);
 
86
       break;
 
87
     //------------------------------------------------// start
 
88
     case 6:      
 
89
       s_chan[ch].pStart=spuMemC+((u32) val<<3);
 
90
       break;
 
91
     //------------------------------------------------// level with pre-calcs
 
92
     case 8:
 
93
       {
 
94
        const u32 lval=val; // DEBUG CHECK
 
95
        //---------------------------------------------//
 
96
        s_chan[ch].ADSRX.AttackModeExp=(lval&0x8000)?1:0; 
 
97
        s_chan[ch].ADSRX.AttackRate=(lval>>8) & 0x007f;
 
98
        s_chan[ch].ADSRX.DecayRate=(lval>>4) & 0x000f;
 
99
        s_chan[ch].ADSRX.SustainLevel=lval & 0x000f;
 
100
        //---------------------------------------------//
 
101
      }
 
102
      break;
 
103
     //------------------------------------------------// adsr times with pre-calcs
 
104
     case 10:
 
105
      {
 
106
       const u32 lval=val; // DEBUG CHECK
 
107
 
 
108
       //----------------------------------------------//
 
109
       s_chan[ch].ADSRX.SustainModeExp = (lval&0x8000)?1:0;
 
110
       s_chan[ch].ADSRX.SustainIncrease= (lval&0x4000)?0:1;
 
111
       s_chan[ch].ADSRX.SustainRate = (lval>>6) & 0x007f;
 
112
       s_chan[ch].ADSRX.ReleaseModeExp = (lval&0x0020)?1:0;
 
113
       s_chan[ch].ADSRX.ReleaseRate = lval & 0x001f;
 
114
       //----------------------------------------------//
 
115
      }
 
116
     break;
 
117
     //------------------------------------------------// adsr volume... mmm have to investigate this
 
118
     //case 0xC:
 
119
     //  break;
 
120
     //------------------------------------------------//
 
121
     case 0xE:                                          // loop?
 
122
       s_chan[ch].pLoop=spuMemC+((u32) val<<3);
 
123
       s_chan[ch].bIgnoreLoop=1;
 
124
       break;
 
125
     //------------------------------------------------//
 
126
    }
 
127
   return;
 
128
  }
 
129
 
 
130
 switch(r)
 
131
   {
 
132
    //-------------------------------------------------//
 
133
    case H_SPUaddr:
 
134
      spuAddr = (u32) val<<3;
 
135
      break;
 
136
    //-------------------------------------------------//
 
137
    case H_SPUdata:
 
138
      spuMem[spuAddr>>1] = BFLIP16(val);
 
139
      spuAddr+=2;
 
140
      if(spuAddr>0x7ffff) spuAddr=0;
 
141
      break;
 
142
    //-------------------------------------------------//
 
143
    case H_SPUctrl:
 
144
      spuCtrl=val;
 
145
      break;
 
146
    //-------------------------------------------------//
 
147
    case H_SPUstat:
 
148
      spuStat=val & 0xf800;
 
149
      break;
 
150
    //-------------------------------------------------//
 
151
    case H_SPUReverbAddr:
 
152
      if(val==0xFFFF || val<=0x200)
 
153
       {rvb.StartAddr=rvb.CurrAddr=0;}
 
154
      else
 
155
       {
 
156
        const s32 iv=(u32)val<<2;
 
157
        if(rvb.StartAddr!=iv)
 
158
         {
 
159
          rvb.StartAddr=(u32)val<<2;
 
160
          rvb.CurrAddr=rvb.StartAddr;
 
161
         }
 
162
       }
 
163
      break;
 
164
    //-------------------------------------------------//
 
165
    case H_SPUirqAddr:
 
166
      spuIrq = val;
 
167
      pSpuIrq=spuMemC+((u32) val<<3);
 
168
      break;
 
169
    //-------------------------------------------------//
 
170
    /* Volume settings appear to be at least 15-bit unsigned in this case.  
 
171
       Definitely NOT 15-bit signed.  Probably 16-bit signed, so s16 type cast.
 
172
       Check out "Chrono Cross:  Shadow's End Forest"
 
173
    */
 
174
    case H_SPUrvolL:
 
175
      rvb.VolLeft=(s16)val;
 
176
      //printf("%d\n",val);
 
177
      break;
 
178
    //-------------------------------------------------//
 
179
    case H_SPUrvolR:
 
180
      rvb.VolRight=(s16)val;
 
181
      //printf("%d\n",val);
 
182
      break;
 
183
    //-------------------------------------------------//
 
184
 
 
185
/*
 
186
    case H_ExtLeft:
 
187
     //auxprintf("EL %d\n",val);
 
188
      break;
 
189
    //-------------------------------------------------//
 
190
    case H_ExtRight:
 
191
     //auxprintf("ER %d\n",val);
 
192
      break;
 
193
    //-------------------------------------------------//
 
194
    case H_SPUmvolL:
 
195
     //auxprintf("ML %d\n",val);
 
196
      break;
 
197
    //-------------------------------------------------//
 
198
    case H_SPUmvolR:
 
199
     //auxprintf("MR %d\n",val);
 
200
      break;
 
201
    //-------------------------------------------------//
 
202
    case H_SPUMute1:
 
203
     //printf("M0 %04x\n",val);
 
204
      break;
 
205
    //-------------------------------------------------//
 
206
    case H_SPUMute2:
 
207
    // printf("M1 %04x\n",val);
 
208
      break;
 
209
*/
 
210
    //-------------------------------------------------//
 
211
    case H_SPUon1:
 
212
      SoundOn(0,16,val);
 
213
      break;
 
214
    //-------------------------------------------------//
 
215
     case H_SPUon2:
 
216
        // printf("Boop: %08x: %04x\n",reg,val);
 
217
      SoundOn(16,24,val);
 
218
      break;
 
219
    //-------------------------------------------------//
 
220
    case H_SPUoff1:
 
221
      SoundOff(0,16,val);
 
222
      break;
 
223
    //-------------------------------------------------//
 
224
    case H_SPUoff2:
 
225
      SoundOff(16,24,val);
 
226
        // printf("Boop: %08x: %04x\n",reg,val);
 
227
      break;
 
228
    //-------------------------------------------------//
 
229
    case H_FMod1:
 
230
      FModOn(0,16,val);
 
231
      break;
 
232
    //-------------------------------------------------//
 
233
    case H_FMod2:
 
234
      FModOn(16,24,val);
 
235
      break;
 
236
    //-------------------------------------------------//
 
237
    case H_Noise1:
 
238
      NoiseOn(0,16,val);
 
239
      break;
 
240
    //-------------------------------------------------//
 
241
    case H_Noise2:
 
242
      NoiseOn(16,24,val);
 
243
      break;
 
244
    //-------------------------------------------------//
 
245
    case H_RVBon1:
 
246
      rvb.Enabled&=~0xFFFF;
 
247
      rvb.Enabled|=val;
 
248
      break;
 
249
 
 
250
    //-------------------------------------------------//
 
251
    case H_RVBon2:
 
252
      rvb.Enabled&=0xFFFF;
 
253
      rvb.Enabled|=val<<16;
 
254
      break;
 
255
 
 
256
    //-------------------------------------------------//
 
257
    case H_Reverb+0:
 
258
      rvb.FB_SRC_A=val;
 
259
      break;
 
260
 
 
261
    case H_Reverb+2   : rvb.FB_SRC_B=(s16)val;       break;
 
262
    case H_Reverb+4   : rvb.IIR_ALPHA=(s16)val;      break;
 
263
    case H_Reverb+6   : rvb.ACC_COEF_A=(s16)val;     break;
 
264
    case H_Reverb+8   : rvb.ACC_COEF_B=(s16)val;     break;
 
265
    case H_Reverb+10  : rvb.ACC_COEF_C=(s16)val;     break;
 
266
    case H_Reverb+12  : rvb.ACC_COEF_D=(s16)val;     break;
 
267
    case H_Reverb+14  : rvb.IIR_COEF=(s16)val;       break;
 
268
    case H_Reverb+16  : rvb.FB_ALPHA=(s16)val;       break;
 
269
    case H_Reverb+18  : rvb.FB_X=(s16)val;           break;
 
270
    case H_Reverb+20  : rvb.IIR_DEST_A0=(s16)val;    break;
 
271
    case H_Reverb+22  : rvb.IIR_DEST_A1=(s16)val;    break;
 
272
    case H_Reverb+24  : rvb.ACC_SRC_A0=(s16)val;     break;
 
273
    case H_Reverb+26  : rvb.ACC_SRC_A1=(s16)val;     break;
 
274
    case H_Reverb+28  : rvb.ACC_SRC_B0=(s16)val;     break;
 
275
    case H_Reverb+30  : rvb.ACC_SRC_B1=(s16)val;     break;
 
276
    case H_Reverb+32  : rvb.IIR_SRC_A0=(s16)val;     break;
 
277
    case H_Reverb+34  : rvb.IIR_SRC_A1=(s16)val;     break;
 
278
    case H_Reverb+36  : rvb.IIR_DEST_B0=(s16)val;    break;
 
279
    case H_Reverb+38  : rvb.IIR_DEST_B1=(s16)val;    break;
 
280
    case H_Reverb+40  : rvb.ACC_SRC_C0=(s16)val;     break;
 
281
    case H_Reverb+42  : rvb.ACC_SRC_C1=(s16)val;     break;
 
282
    case H_Reverb+44  : rvb.ACC_SRC_D0=(s16)val;     break;
 
283
    case H_Reverb+46  : rvb.ACC_SRC_D1=(s16)val;     break;
 
284
    case H_Reverb+48  : rvb.IIR_SRC_B1=(s16)val;     break;
 
285
    case H_Reverb+50  : rvb.IIR_SRC_B0=(s16)val;     break;
 
286
    case H_Reverb+52  : rvb.MIX_DEST_A0=(s16)val;    break;
 
287
    case H_Reverb+54  : rvb.MIX_DEST_A1=(s16)val;    break;
 
288
    case H_Reverb+56  : rvb.MIX_DEST_B0=(s16)val;    break;
 
289
    case H_Reverb+58  : rvb.MIX_DEST_B1=(s16)val;    break;
 
290
    case H_Reverb+60  : rvb.IN_COEF_L=(s16)val;      break;
 
291
    case H_Reverb+62  : rvb.IN_COEF_R=(s16)val;      break;
 
292
   }
 
293
 
 
294
}
 
295
 
 
296
////////////////////////////////////////////////////////////////////////
 
297
// READ REGISTER: called by main emu
 
298
////////////////////////////////////////////////////////////////////////
 
299
 
 
300
u16 SPUreadRegister(u32 reg)
 
301
{
 
302
 const u32 r=reg&0xfff;
 
303
 
 
304
 if(r>=0x0c00 && r<0x0d80)
 
305
  {
 
306
   switch(r&0x0f)
 
307
    {
 
308
     case 0xC:                                          // get adsr vol
 
309
      {
 
310
       const int ch=(r>>4)-0xc0;
 
311
       if(s_chan[ch].bNew) return 1;                   // we are started, but not processed? return 1
 
312
       if(s_chan[ch].ADSRX.lVolume &&                  // same here... we haven't decoded one sample yet, so no envelope yet. return 1 as well
 
313
          !s_chan[ch].ADSRX.EnvelopeVol)                   
 
314
        return 1;
 
315
       return (u16)(s_chan[ch].ADSRX.EnvelopeVol>>16);
 
316
      }
 
317
 
 
318
     case 0xE:                                          // get loop address
 
319
      {
 
320
       const int ch=(r>>4)-0xc0;
 
321
       if(s_chan[ch].pLoop==NULL) return 0;
 
322
       return (u16)((s_chan[ch].pLoop-spuMemC)>>3);
 
323
      }
 
324
    }
 
325
  }
 
326
 
 
327
 switch(r)
 
328
  {
 
329
    case H_SPUctrl:
 
330
     return spuCtrl;
 
331
 
 
332
    case H_SPUstat:
 
333
     return spuStat;
 
334
        
 
335
    case H_SPUaddr:
 
336
     return (u16)(spuAddr>>3);
 
337
 
 
338
    case H_SPUdata:
 
339
     {
 
340
      u16 s=BFLIP16(spuMem[spuAddr>>1]);
 
341
      spuAddr+=2;
 
342
      if(spuAddr>0x7ffff) spuAddr=0;
 
343
      return s;
 
344
     }
 
345
 
 
346
    case H_SPUirqAddr:
 
347
     return spuIrq;
 
348
 
 
349
    //case H_SPUIsOn1:
 
350
    // return IsSoundOn(0,16);
 
351
 
 
352
    //case H_SPUIsOn2:
 
353
    // return IsSoundOn(16,24);
 
354
 
 
355
  }
 
356
 
 
357
 return regArea[(r-0xc00)>>1];
 
358
}
 
359
 
 
360
////////////////////////////////////////////////////////////////////////
 
361
// SOUND ON register write
 
362
////////////////////////////////////////////////////////////////////////
 
363
 
 
364
static void SoundOn(int start,int end,u16 val)     // SOUND ON PSX COMAND
 
365
{
 
366
 int ch;
 
367
 
 
368
 for(ch=start;ch<end;ch++,val>>=1)                     // loop channels
 
369
  {
 
370
   if((val&1) && s_chan[ch].pStart)                    // mmm... start has to be set before key on !?!
 
371
    {
 
372
     s_chan[ch].bIgnoreLoop=0;
 
373
     s_chan[ch].bNew=1;
 
374
    }
 
375
  }
 
376
}
 
377
 
 
378
////////////////////////////////////////////////////////////////////////
 
379
// SOUND OFF register write
 
380
////////////////////////////////////////////////////////////////////////
 
381
 
 
382
static void SoundOff(int start,int end,u16 val)    // SOUND OFF PSX COMMAND
 
383
{
 
384
 int ch;
 
385
 for(ch=start;ch<end;ch++,val>>=1)                     // loop channels
 
386
  {
 
387
   if(val&1)                                           // && s_chan[i].bOn)  mmm...
 
388
    {
 
389
     s_chan[ch].bStop=1;
 
390
    }                                                  
 
391
  }
 
392
}
 
393
 
 
394
////////////////////////////////////////////////////////////////////////
 
395
// FMOD register write
 
396
////////////////////////////////////////////////////////////////////////
 
397
 
 
398
static void FModOn(int start,int end,u16 val)      // FMOD ON PSX COMMAND
 
399
{
 
400
 int ch;
 
401
 
 
402
 for(ch=start;ch<end;ch++,val>>=1)                     // loop channels
 
403
  {
 
404
   if(val&1)                                           // -> fmod on/off
 
405
    {
 
406
     if(ch>0) 
 
407
      {
 
408
       s_chan[ch].bFMod=1;                             // --> sound channel
 
409
       s_chan[ch-1].bFMod=2;                           // --> freq channel
 
410
      }
 
411
    }
 
412
   else
 
413
    {
 
414
     s_chan[ch].bFMod=0;                               // --> turn off fmod
 
415
    }
 
416
  }
 
417
}
 
418
 
 
419
////////////////////////////////////////////////////////////////////////
 
420
// NOISE register write
 
421
////////////////////////////////////////////////////////////////////////
 
422
 
 
423
static void NoiseOn(int start,int end,u16 val)     // NOISE ON PSX COMMAND
 
424
{
 
425
 int ch;
 
426
 
 
427
 for(ch=start;ch<end;ch++,val>>=1)                     // loop channels
 
428
  {
 
429
   if(val&1)                                           // -> noise on/off
 
430
    {
 
431
     s_chan[ch].bNoise=1;
 
432
    }
 
433
   else 
 
434
    {
 
435
     s_chan[ch].bNoise=0;
 
436
    }
 
437
  }
 
438
}
 
439
 
 
440
////////////////////////////////////////////////////////////////////////
 
441
// LEFT VOLUME register write
 
442
////////////////////////////////////////////////////////////////////////
 
443
 
 
444
// please note: sweep is wrong.
 
445
 
 
446
static void SetVolumeLR(int right, u8 ch,s16 vol)            // LEFT VOLUME
 
447
{
 
448
 //if(vol&0xc000)
 
449
 //printf("%d %08x\n",right,vol);
 
450
 if(right)
 
451
  s_chan[ch].iRightVolRaw=vol;
 
452
 else
 
453
  s_chan[ch].iLeftVolRaw=vol;
 
454
 
 
455
 if(vol&0x8000)                                        // sweep?
 
456
  {
 
457
   s16 sInc=1;                                       // -> sweep up?
 
458
   if(vol&0x2000) sInc=-1;                             // -> or down?
 
459
   if(vol&0x1000) vol^=0xffff;                         // -> mmm... phase inverted? have to investigate this
 
460
   vol=((vol&0x7f)+1)/2;                               // -> sweep: 0..127 -> 0..64
 
461
   vol+=vol/(2*sInc);                                  // -> HACK: we don't sweep right now, so we just raise/lower the volume by the half!
 
462
   vol*=128;
 
463
   vol&=0x3fff;
 
464
   //puts("Sweep");
 
465
  }
 
466
 else                                                  // no sweep:
 
467
  {
 
468
   if(vol&0x4000)
 
469
    vol=(vol&0x3FFF)-0x4000;
 
470
   else
 
471
    vol&=0x3FFF;
 
472
 
 
473
   //if(vol&0x4000)                                      // -> mmm... phase inverted? have to investigate this
 
474
   // vol=0-(0x3fff-(vol&0x3fff));
 
475
   //else
 
476
   // vol&=0x3fff;
 
477
  }
 
478
 if(right)
 
479
  s_chan[ch].iRightVolume=vol;
 
480
 else
 
481
  s_chan[ch].iLeftVolume=vol;                           // store volume
 
482
}
 
483
 
 
484
////////////////////////////////////////////////////////////////////////
 
485
// PITCH register write
 
486
////////////////////////////////////////////////////////////////////////
 
487
 
 
488
static void SetPitch(int ch,u16 val)               // SET PITCH
 
489
{
 
490
 int NP;
 
491
 if(val>0x3fff) NP=0x3fff;                             // get pitch val
 
492
 else           NP=val;
 
493
 
 
494
 s_chan[ch].iRawPitch=NP;
 
495
 
 
496
 NP=(44100L*NP)/4096L;                                 // calc frequency
 
497
 if(NP<1) NP=1;                                        // some security
 
498
 s_chan[ch].iActFreq=NP;                               // store frequency
 
499
}