updated bords/mappers/stuff to 0.98.15, lots of them got broken, asmcore support...
[fceu.git] / mappers / 24and26.c
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 FP_FASTAPASS(1) 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 #if 0
226 static INLINE void DoSQVHQ(int x)
227 {
228  int32 V;
229  int32 amp=((VPSG[x<<2]&15)<<8)*6/8;
230
231  if(VPSG[(x<<2)|0x2]&0x80)
232  {
233   if(VPSG[x<<2]&0x80)
234   {
235    for(V=CVBC[x];V<SOUNDTS;V++)
236     WaveHi[V]+=amp;
237   }
238   else
239   {
240    int32 thresh=(VPSG[x<<2]>>4)&7;
241    for(V=CVBC[x];V<SOUNDTS;V++)
242    {
243     if(dcount[x]>thresh)        /* Greater than, not >=.  Important. */
244      WaveHi[V]+=amp;
245     vcount[x]--;
246     if(vcount[x]<=0)            /* Should only be <0 in a few circumstances. */
247     {
248      vcount[x]=(VPSG[(x<<2)|0x1]|((VPSG[(x<<2)|0x2]&15)<<8))+1;
249      dcount[x]=(dcount[x]+1)&15;
250     }
251    }
252   }
253  }
254  CVBC[x]=SOUNDTS;
255 }
256
257 static void DoSQV1HQ(void)
258 {
259  DoSQVHQ(0);
260 }
261
262 static void DoSQV2HQ(void)
263 {
264  DoSQVHQ(1);
265 }
266
267 static void DoSawVHQ(void)
268 {
269  static uint8 b3=0;
270  static int32 phaseacc=0;
271  int32 V;
272
273  if(VPSG2[2]&0x80)
274  {
275   for(V=CVBC[2];V<SOUNDTS;V++)
276   {
277    WaveHi[V]+=(((phaseacc>>3)&0x1f)<<8)*6/8;
278    vcount[2]--;
279    if(vcount[2]<=0)
280    {
281     vcount[2]=(VPSG2[1]+((VPSG2[2]&15)<<8)+1)<<1;
282     phaseacc+=VPSG2[0]&0x3f;
283     b3++;
284     if(b3==7)
285     {
286      b3=0;
287      phaseacc=0;
288    }
289
290    }
291   }
292  }
293  CVBC[2]=SOUNDTS;
294 }
295 #endif
296
297
298 void VRC6Sound(int Count)
299 {
300     int x;
301
302     DoSQV1();
303     DoSQV2();
304     DoSawV();
305     for(x=0;x<3;x++)
306      CVBC[x]=Count;
307 }
308
309 #if 0
310 void VRC6SoundHQ(void)
311 {
312     DoSQV1HQ();
313     DoSQV2HQ();
314     DoSawVHQ();
315 }
316
317 void VRC6SyncHQ(int32 ts)
318 {
319  int x;
320  for(x=0;x<3;x++) CVBC[x]=ts;
321 }
322 #endif
323
324 static void VRC6_ESI(void)
325 {
326         GameExpSound.RChange=VRC6_ESI;
327         GameExpSound.Fill=VRC6Sound;
328         GameExpSound.HiFill=0;//VRC6SoundHQ;
329         GameExpSound.HiSync=0;//VRC6SyncHQ;
330
331         memset(CVBC,0,sizeof(CVBC));
332         memset(vcount,0,sizeof(vcount));
333         memset(dcount,0,sizeof(dcount));
334         if(FSettings.SndRate)
335         {
336 #if 0
337          if(FSettings.soundq>=1)
338          {
339           sfun[0]=DoSQV1HQ;
340           sfun[1]=DoSQV2HQ;
341           sfun[2]=DoSawVHQ;
342          }
343          else
344 #endif
345          {
346           sfun[0]=DoSQV1;
347           sfun[1]=DoSQV2;
348           sfun[2]=DoSawV;
349          }
350         }
351         else
352          memset(sfun,0,sizeof(sfun));
353 }
354
355 void Mapper24_init(void)
356 {
357         SetWriteHandler(0x8000,0xffff,Mapper24_write);
358         VRC6_ESI();
359         MapIRQHook=KonamiIRQHook;
360         swaparoo=0;
361 }
362
363 void Mapper26_init(void)
364 {
365         SetWriteHandler(0x8000,0xffff,Mapper24_write);
366         VRC6_ESI();
367         MapIRQHook=KonamiIRQHook;
368         swaparoo=1;
369 }
370
371 void NSFVRC6_Init(void)
372 {
373         VRC6_ESI();
374         SetWriteHandler(0x8000,0xbfff,VRC6SW);
375 }