mapper fixes for ncpu, debug is broken atm
[fceu.git] / mappers / 24and26.c
1 /* FCE Ultra - NES/Famicom Emulator
2  *
3  * Copyright notice for this file:
4  *  Copyright (C) 2002 Ben Parnell
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 #define vrctemp mapbyte1[0]
24 #define regb000 mapbyte3[0]
25 #define regb001 mapbyte3[1]
26 #define regb002 mapbyte3[2]
27 #define exchstat mapbyte4[0]
28 #define VPSG2 mapbyte3
29 #define VPSG mapbyte2
30
31 static void DoSQV1(void);
32 static void DoSQV2(void);
33 static void DoSawV(void);
34
35 static int swaparoo;
36 static int32 inc;
37 static DECLFW(VRC6PSGW90)
38 {
39  DoSQV1();VPSG[0]=V;
40 }
41 static DECLFW(VRC6PSGW91)
42 {
43  DoSQV1();VPSG[2]=V;
44 }
45 static DECLFW(VRC6PSGW92)
46 {
47  DoSQV1();VPSG[3]=V;
48 }
49 static DECLFW(VRC6PSGWA0)
50 {
51  DoSQV2();VPSG[4]=V;
52 }
53 static DECLFW(VRC6PSGWA1)
54 {
55  DoSQV2();VPSG[6]=V;
56 }
57 static DECLFW(VRC6PSGWA2)
58 {
59  DoSQV2();VPSG[7]=V;
60 }
61 static DECLFW(VRC6PSGWB0)
62 {
63  DoSawV();VPSG2[0]=V;
64 }
65 static DECLFW(VRC6PSGWB1)
66 {
67  DoSawV();VPSG2[1]=V;
68 }
69 static DECLFW(VRC6PSGWB2)
70 {
71  DoSawV();VPSG2[2]=V;
72 }
73
74 static int acount=0;
75
76 static void FP_FASTAPASS(1) KonamiIRQHook(int a)
77 {
78   #define LCYCS 114
79   if(IRQa)
80   {
81    acount+=a;
82    if(acount>=LCYCS)
83    {
84     doagainbub:acount-=LCYCS;IRQCount++;
85     if(IRQCount==0x100) {TriggerIRQ();IRQCount=IRQLatch;}
86     if(acount>=LCYCS) goto doagainbub;
87    }
88  }
89 }
90
91 DECLFW(Mapper24_write)
92 {
93         if(swaparoo)
94          A=(A&0xFFFC)|((A>>1)&1)|((A<<1)&2);
95
96         switch(A&0xF003)
97         {
98          case 0x8000:ROM_BANK16(0x8000,V);
99                      X6502_Rebase();break;
100          case 0xB003:
101                  switch(V&0xF)
102                  {
103                   case 0x0:MIRROR_SET2(1);break;
104                   case 0x4:MIRROR_SET2(0);break;
105                   case 0x8:onemir(0);break;
106                   case 0xC:onemir(1);break;
107                  }
108                  break;
109          case 0xC000:ROM_BANK8(0xC000,V);
110                      X6502_Rebase();break;
111          case 0xD000:VROM_BANK1(0x0000,V);break;
112          case 0xD001:VROM_BANK1(0x0400,V);break;
113          case 0xD002:VROM_BANK1(0x0800,V);break;
114          case 0xD003:VROM_BANK1(0x0c00,V);break;
115          case 0xE000:VROM_BANK1(0x1000,V);break;
116          case 0xE001:VROM_BANK1(0x1400,V);break;
117          case 0xE002:VROM_BANK1(0x1800,V);break;
118          case 0xE003:VROM_BANK1(0x1c00,V);break;
119          case 0xF000:IRQLatch=V;break;
120          case 0xF001:IRQa=V&2;
121                      vrctemp=V&1;
122                      if(V&2) {IRQCount=IRQLatch;}
123                      //acount=0;
124                      break;
125          case 0xf002:IRQa=vrctemp;break;
126          case 0xF003:break;
127   }
128 }
129
130 static int CVBC[3]={0,0,0};
131 static int32 vcount[2];
132
133 static void DoSQV1(void)
134 {
135     uint8 amp;
136     int32 freq;
137     int V;
138     int32 start,end;
139
140     start=CVBC[0];
141     end=(timestamp<<16)/soundtsinc;
142     if(end<=start) return;
143     CVBC[0]=end;
144
145     if(VPSG[0x3]&0x80)
146     {
147      amp=(VPSG[0]&15)<<4;
148      if(VPSG[0]&0x80)
149      {
150       for(V=start;V<end;V++)
151        Wave[V>>4]+=amp;
152      }
153      else
154      {
155       unsigned long dcycs;
156       freq=(((VPSG[0x2]|((VPSG[0x3]&15)<<8))+1));
157       inc=(long double)((unsigned long)((FSettings.SndRate OVERSAMPLE)<<12))/((long double)PSG_base/freq);
158       switch(VPSG[0]&0x70)
159       {
160        default:
161        case 0x00:dcycs=inc>>4;break;
162        case 0x10:dcycs=inc>>3;break;
163        case 0x20:dcycs=(inc*3)>>4;break;
164        case 0x30:dcycs=inc>>2;break;
165        case 0x40:dcycs=(inc*5)>>4;break;
166        case 0x50:dcycs=(inc*6)>>4;break;
167        case 0x60:dcycs=(inc*7)>>4;break;
168        case 0x70:dcycs=inc>>1;break;
169       }
170              for(V=start;V<end;V++)
171               {
172                if(vcount[0]<dcycs)
173                  Wave[V>>4]+=amp;
174                vcount[0]+=0x1000;
175                if(vcount[0]>=inc) vcount[0]-=inc;
176                }
177      }
178     }
179 }
180 static void DoSQV2(void)
181 {
182     uint8 amp;
183     int32 freq;
184     int V;
185     int32 start,end;
186
187     start=CVBC[1];
188     end=(timestamp<<16)/soundtsinc;
189     if(end<=start) return;
190     CVBC[1]=end;
191
192     if(VPSG[0x7]&0x80)
193     {
194      amp=(VPSG[4]&15)<<4;
195      if(VPSG[4]&0x80)
196      {
197       for(V=start;V<end;V++)
198        Wave[V>>4]+=amp;
199      }
200      else
201      {
202       unsigned long dcycs;
203       freq=(((VPSG[0x6]|((VPSG[0x7]&15)<<8))+1));
204       inc=(long double)((unsigned long)((FSettings.SndRate OVERSAMPLE)<<12))/((long double)PSG_base/freq);
205       switch(VPSG[4]&0x70)
206       {
207        default:
208        case 0x00:dcycs=inc>>4;break;
209        case 0x10:dcycs=inc>>3;break;
210        case 0x20:dcycs=(inc*3)>>4;break;
211        case 0x30:dcycs=inc>>2;break;
212        case 0x40:dcycs=(inc*5)>>4;break;
213        case 0x50:dcycs=(inc*6)>>4;break;
214        case 0x60:dcycs=(inc*7)>>4;break;
215        case 0x70:dcycs=inc>>1;break;
216       }
217              for(V=start;V<end;V++)
218               {
219                if(vcount[1]<dcycs)
220                  Wave[V>>4]+=amp;
221                vcount[1]+=0x1000;
222                if(vcount[1]>=inc) vcount[1]-=inc;
223                }
224      }
225     }
226 }
227
228 static void DoSawV(void)
229 {
230     int V;
231     int32 start,end;
232
233     start=CVBC[2];
234     end=(timestamp<<16)/soundtsinc;
235     if(end<=start) return;
236     CVBC[2]=end;
237
238    if(VPSG2[2]&0x80)
239    {
240     static int64 saw1phaseacc=0;
241     uint32 freq3;
242     static uint8 b3=0;
243     static int32 phaseacc=0;
244     static uint32 duff=0;
245
246     freq3=(VPSG2[1]+((VPSG2[2]&15)<<8)+1);
247
248     for(V=start;V<end;V++)
249     {
250      saw1phaseacc-=nesincsizeLL;
251      if(saw1phaseacc<=0)
252      {
253       int64 t;
254       rea:
255       t=freq3;
256       t<<=50;   // 49 + 1
257       saw1phaseacc+=t;
258       phaseacc+=VPSG2[0]&0x3f;
259       b3++;
260       if(b3==7)
261       {
262        b3=0;
263        phaseacc=0;
264       }
265       if(saw1phaseacc<=0)
266        goto rea;
267       duff=(((phaseacc>>3)&0x1f)<<4);
268       }
269      Wave[V>>4]+=duff;
270     }
271    }
272 }
273
274 void VRC6Sound(int Count)
275 {
276     int x;
277
278     DoSQV1();
279     DoSQV2();
280     DoSawV();
281     for(x=0;x<3;x++)
282      CVBC[x]=Count;
283 }
284
285 static int satype=0;
286
287 void VRC6SoundC(void)
288 {
289   int x;
290
291   if(FSettings.SndRate)
292    VRC6_ESI(satype);
293   else
294   {
295    for(x=000;x<0x1000;x+=4)
296    {
297           SetWriteHandler(0x9000+x,0x9002+x,0);
298           SetWriteHandler(0xa000+x,0xa002+x,0);
299           SetWriteHandler(0xb000+x,0xb002+x,0);
300    }
301   }
302 }
303
304 void VRC6_ESI(int t)
305 {
306         int x;
307
308         satype=t;
309
310         GameExpSound.RChange=VRC6SoundC;
311         GameExpSound.Fill=VRC6Sound;
312         if(FSettings.SndRate)
313          for(x=000;x<0x1000;x+=4)
314          {
315           uint32 a;
316
317           a=0x9000+x;
318           SetWriteHandler(a,a,VRC6PSGW90);
319           SetWriteHandler(a+(1^t),a+(1^t),VRC6PSGW91);
320           SetWriteHandler(a+(2^t),a+(2^t),VRC6PSGW92);
321
322           a=0xa000+x;
323           SetWriteHandler(a,a,VRC6PSGWA0);
324           SetWriteHandler(a+(1^t),a+(1^t),VRC6PSGWA1);
325           SetWriteHandler(a+(2^t),a+(2^t),VRC6PSGWA2);
326
327           a=0xb000+x;
328           SetWriteHandler(a,a,VRC6PSGWB0);
329           SetWriteHandler(a+(1^t),a+(1^t),VRC6PSGWB1);
330           SetWriteHandler(a+(2^t),a+(2^t),VRC6PSGWB2);
331          }
332 }
333
334 void Mapper24_init(void)
335 {
336         SetWriteHandler(0x8000,0xffff,Mapper24_write);
337         if(FSettings.SndRate)
338          VRC6_ESI(0);
339         GameExpSound.RChange=VRC6SoundC;
340         MapIRQHook=KonamiIRQHook;
341         swaparoo=0;
342 }
343
344 void Mapper26_init(void)
345 {
346         SetWriteHandler(0x8000,0xffff,Mapper24_write);
347         if(FSettings.SndRate)
348          VRC6_ESI(3);
349         GameExpSound.RChange=VRC6SoundC;
350         MapIRQHook=KonamiIRQHook;
351         swaparoo=1;
352 }
353