~ubuntu-branches/ubuntu/lucid/fceux/lucid

« back to all changes in this revision

Viewing changes to fceu/src/mappers/24and26.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Fabrice Coutadeur
  • Date: 2009-12-14 08:05:17 UTC
  • Revision ID: james.westby@ubuntu.com-20091214080517-abi5tj8avthfan7c
Tags: upstream-2.1.2+repack
ImportĀ upstreamĀ versionĀ 2.1.2+repack

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* FCE Ultra - NES/Famicom Emulator
 
2
 *
 
3
 * Copyright notice for this file:
 
4
 *  Copyright (C) 2002 Xodnizel
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
19
 */
 
20
 
 
21
#include "mapinc.h"
 
22
 
 
23
static void (*sfun[3])(void);
 
24
 
 
25
#define vrctemp mapbyte1[0]
 
26
#define VPSG2 mapbyte3
 
27
#define VPSG mapbyte2
 
28
 
 
29
static void DoSQV1(void);
 
30
static void DoSQV2(void);
 
31
static void DoSawV(void);
 
32
 
 
33
static int swaparoo;
 
34
 
 
35
static int acount=0;
 
36
 
 
37
static void KonamiIRQHook(int a)
 
38
{
 
39
  #define LCYCS 341
 
40
//  #define LCYCS ((227*2)+1)
 
41
  if(IRQa)
 
42
  {
 
43
   acount+=a*3;
 
44
   if(acount>=LCYCS)
 
45
   {
 
46
    doagainbub:acount-=LCYCS;IRQCount++;
 
47
    if(IRQCount==0x100)
 
48
    {
 
49
     X6502_IRQBegin(FCEU_IQEXT);
 
50
     IRQCount=IRQLatch;
 
51
    }
 
52
    if(acount>=LCYCS) goto doagainbub;
 
53
   }
 
54
 }
 
55
}
 
56
 
 
57
static DECLFW(VRC6SW)
 
58
{
 
59
        A&=0xF003;
 
60
        if(A>=0x9000 && A<=0x9002)
 
61
        {
 
62
         VPSG[A&3]=V;
 
63
         if(sfun[0]) sfun[0]();
 
64
        }
 
65
        else if(A>=0xa000 && A<=0xa002)
 
66
        {
 
67
         VPSG[4|(A&3)]=V;
 
68
         if(sfun[1]) sfun[1]();
 
69
        }
 
70
        else if(A>=0xb000 && A<=0xb002)
 
71
        {
 
72
         VPSG2[A&3]=V;
 
73
         if(sfun[2]) sfun[2]();
 
74
        }
 
75
 
 
76
}
 
77
 
 
78
static DECLFW(Mapper24_write)
 
79
{
 
80
        if(swaparoo)
 
81
         A=(A&0xFFFC)|((A>>1)&1)|((A<<1)&2);
 
82
        if(A>=0x9000 && A<=0xb002)
 
83
        {
 
84
         VRC6SW(A,V);
 
85
         return;
 
86
        }
 
87
        A&=0xF003;
 
88
//        if(A>=0xF000) printf("%d, %d, $%04x:$%02x\n",scanline,timestamp,A,V);
 
89
        switch(A&0xF003)
 
90
        {
 
91
         case 0x8000:ROM_BANK16(0x8000,V);break;
 
92
         case 0xB003:
 
93
                    switch(V&0xF)
 
94
                 {
 
95
                  case 0x0:MIRROR_SET2(1);break;
 
96
                  case 0x4:MIRROR_SET2(0);break;
 
97
                  case 0x8:onemir(0);break;
 
98
                  case 0xC:onemir(1);break;
 
99
                 }
 
100
                 break;
 
101
         case 0xC000:ROM_BANK8(0xC000,V);break;
 
102
         case 0xD000:VROM_BANK1(0x0000,V);break;
 
103
         case 0xD001:VROM_BANK1(0x0400,V);break;
 
104
         case 0xD002:VROM_BANK1(0x0800,V);break;
 
105
         case 0xD003:VROM_BANK1(0x0c00,V);break;
 
106
         case 0xE000:VROM_BANK1(0x1000,V);break;
 
107
         case 0xE001:VROM_BANK1(0x1400,V);break;
 
108
         case 0xE002:VROM_BANK1(0x1800,V);break;
 
109
         case 0xE003:VROM_BANK1(0x1c00,V);break;
 
110
         case 0xF000:IRQLatch=V;
 
111
                        //acount=0;
 
112
                        break;
 
113
         case 0xF001:IRQa=V&2;
 
114
                     vrctemp=V&1;
 
115
                     if(V&2)
 
116
                     {
 
117
                      IRQCount=IRQLatch;
 
118
                      acount=0;
 
119
                     }
 
120
                     X6502_IRQEnd(FCEU_IQEXT);
 
121
                     break;
 
122
         case 0xf002:IRQa=vrctemp;
 
123
                     X6502_IRQEnd(FCEU_IQEXT);break;
 
124
         case 0xF003:break;
 
125
  }
 
126
}
 
127
 
 
128
static int32 CVBC[3];
 
129
static int32 vcount[3];
 
130
static int32 dcount[2];
 
131
 
 
132
static INLINE void DoSQV(int x)
 
133
{
 
134
 int32 V;
 
135
 int32 amp=(((VPSG[x<<2]&15)<<8)*6/8)>>4;
 
136
 int32 start,end;
 
137
 
 
138
 start=CVBC[x];
 
139
 end=(SOUNDTS<<16)/soundtsinc;
 
140
 if(end<=start) return;
 
141
 CVBC[x]=end;
 
142
 
 
143
 if(VPSG[(x<<2)|0x2]&0x80)
 
144
 {
 
145
  if(VPSG[x<<2]&0x80)
 
146
  {
 
147
   for(V=start;V<end;V++)
 
148
    Wave[V>>4]+=amp;
 
149
  }
 
150
  else
 
151
  {
 
152
   int32 thresh=(VPSG[x<<2]>>4)&7;
 
153
   int32 freq=((VPSG[(x<<2)|0x1]|((VPSG[(x<<2)|0x2]&15)<<8))+1)<<17;
 
154
   for(V=start;V<end;V++)
 
155
   {
 
156
    if(dcount[x]>thresh)        /* Greater than, not >=.  Important. */
 
157
     Wave[V>>4]+=amp;
 
158
    vcount[x]-=nesincsize;
 
159
    while(vcount[x]<=0)            /* Should only be <0 in a few circumstances. */
 
160
    {
 
161
     vcount[x]+=freq;
 
162
     dcount[x]=(dcount[x]+1)&15;
 
163
    }
 
164
   }
 
165
  }
 
166
 }
 
167
}
 
168
 
 
169
static void DoSQV1(void)
 
170
{
 
171
 DoSQV(0);
 
172
}
 
173
 
 
174
static void DoSQV2(void)
 
175
{
 
176
 DoSQV(1);
 
177
}
 
178
 
 
179
static void DoSawV(void)
 
180
{
 
181
    int V;
 
182
    int32 start,end;
 
183
 
 
184
    start=CVBC[2];
 
185
    end=(SOUNDTS<<16)/soundtsinc;
 
186
    if(end<=start) return;
 
187
    CVBC[2]=end;
 
188
 
 
189
   if(VPSG2[2]&0x80)
 
190
   {
 
191
    static int32 saw1phaseacc=0;
 
192
    uint32 freq3;
 
193
    static uint8 b3=0;
 
194
    static int32 phaseacc=0;
 
195
    static uint32 duff=0;
 
196
 
 
197
    freq3=(VPSG2[1]+((VPSG2[2]&15)<<8)+1);
 
198
 
 
199
    for(V=start;V<end;V++)
 
200
    {
 
201
     saw1phaseacc-=nesincsize;
 
202
     if(saw1phaseacc<=0)
 
203
     {
 
204
      int32 t;
 
205
      rea:
 
206
      t=freq3;
 
207
      t<<=18;
 
208
      saw1phaseacc+=t;
 
209
      phaseacc+=VPSG2[0]&0x3f;
 
210
      b3++;
 
211
      if(b3==7)
 
212
      {
 
213
       b3=0;
 
214
       phaseacc=0;
 
215
      }
 
216
      if(saw1phaseacc<=0)
 
217
       goto rea;
 
218
      duff=(((phaseacc>>3)&0x1f)<<4)*6/8;
 
219
      }
 
220
     Wave[V>>4]+=duff;
 
221
    }
 
222
   }
 
223
}
 
224
 
 
225
static INLINE void DoSQVHQ(int x)
 
226
{
 
227
 uint32 V; //mbg merge 7/17/06 made uint
 
228
 int32 amp=((VPSG[x<<2]&15)<<8)*6/8;
 
229
 
 
230
 if(VPSG[(x<<2)|0x2]&0x80)
 
231
 {
 
232
  if(VPSG[x<<2]&0x80)
 
233
  {
 
234
   for(V=CVBC[x];V<SOUNDTS;V++)
 
235
    WaveHi[V]+=amp;
 
236
  }
 
237
  else
 
238
  {
 
239
   int32 thresh=(VPSG[x<<2]>>4)&7;
 
240
   for(V=CVBC[x];V<SOUNDTS;V++)
 
241
   {
 
242
    if(dcount[x]>thresh)        /* Greater than, not >=.  Important. */
 
243
     WaveHi[V]+=amp;
 
244
    vcount[x]--;
 
245
    if(vcount[x]<=0)            /* Should only be <0 in a few circumstances. */
 
246
    {
 
247
     vcount[x]=(VPSG[(x<<2)|0x1]|((VPSG[(x<<2)|0x2]&15)<<8))+1;
 
248
     dcount[x]=(dcount[x]+1)&15;
 
249
    }
 
250
   }
 
251
  }
 
252
 }
 
253
 CVBC[x]=SOUNDTS;
 
254
}
 
255
 
 
256
static void DoSQV1HQ(void)
 
257
{
 
258
 DoSQVHQ(0);
 
259
}
 
260
 
 
261
static void DoSQV2HQ(void)
 
262
{
 
263
 DoSQVHQ(1);
 
264
}
 
265
 
 
266
static void DoSawVHQ(void)
 
267
{
 
268
 static uint8 b3=0;
 
269
 static int32 phaseacc=0;
 
270
 uint32 V; //mbg merge 7/17/06 made uint32
 
271
 
 
272
 if(VPSG2[2]&0x80)
 
273
 {
 
274
  for(V=CVBC[2];V<SOUNDTS;V++)
 
275
  {
 
276
   WaveHi[V]+=(((phaseacc>>3)&0x1f)<<8)*6/8;
 
277
   vcount[2]--;
 
278
   if(vcount[2]<=0)
 
279
   {
 
280
    vcount[2]=(VPSG2[1]+((VPSG2[2]&15)<<8)+1)<<1;
 
281
    phaseacc+=VPSG2[0]&0x3f;
 
282
    b3++;
 
283
    if(b3==7)
 
284
    {
 
285
     b3=0;
 
286
     phaseacc=0;
 
287
   }
 
288
 
 
289
   }
 
290
  }
 
291
 }
 
292
 CVBC[2]=SOUNDTS;
 
293
}
 
294
 
 
295
 
 
296
void VRC6Sound(int Count)
 
297
{
 
298
    int x;
 
299
 
 
300
    DoSQV1();
 
301
    DoSQV2();
 
302
    DoSawV();
 
303
    for(x=0;x<3;x++)
 
304
     CVBC[x]=Count;
 
305
}
 
306
 
 
307
void VRC6SoundHQ(void)
 
308
{
 
309
    DoSQV1HQ();
 
310
    DoSQV2HQ();
 
311
    DoSawVHQ();
 
312
}
 
313
 
 
314
void VRC6SyncHQ(int32 ts)
 
315
{
 
316
 int x;
 
317
 for(x=0;x<3;x++) CVBC[x]=ts;
 
318
}
 
319
 
 
320
static void VRC6_ESI(void)
 
321
{
 
322
        GameExpSound.RChange=VRC6_ESI;
 
323
        GameExpSound.Fill=VRC6Sound;
 
324
        GameExpSound.HiFill=VRC6SoundHQ;
 
325
        GameExpSound.HiSync=VRC6SyncHQ;
 
326
 
 
327
        memset(CVBC,0,sizeof(CVBC));
 
328
        memset(vcount,0,sizeof(vcount));
 
329
        memset(dcount,0,sizeof(dcount));
 
330
        if(FSettings.SndRate)
 
331
        {
 
332
         if(FSettings.soundq>=1)
 
333
         {
 
334
          sfun[0]=DoSQV1HQ;
 
335
          sfun[1]=DoSQV2HQ;
 
336
          sfun[2]=DoSawVHQ;
 
337
         }
 
338
         else
 
339
         {
 
340
          sfun[0]=DoSQV1;
 
341
          sfun[1]=DoSQV2;
 
342
          sfun[2]=DoSawV;
 
343
         }
 
344
        }
 
345
        else
 
346
         memset(sfun,0,sizeof(sfun));
 
347
}
 
348
 
 
349
void Mapper24_init(void)
 
350
{
 
351
        SetWriteHandler(0x8000,0xffff,Mapper24_write);
 
352
        VRC6_ESI();
 
353
        MapIRQHook=KonamiIRQHook;
 
354
        swaparoo=0;
 
355
}
 
356
 
 
357
void Mapper26_init(void)
 
358
{
 
359
        SetWriteHandler(0x8000,0xffff,Mapper24_write);
 
360
        VRC6_ESI();
 
361
        MapIRQHook=KonamiIRQHook;
 
362
        swaparoo=1;
 
363
}
 
364
 
 
365
void NSFVRC6_Init(void)
 
366
{
 
367
        VRC6_ESI();
 
368
        SetWriteHandler(0x8000,0xbfff,VRC6SW);
 
369
}