mapper fixes for ncpu, debug is broken atm
[fceu.git] / mappers / 69.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 static void AYSound(int Count);
23 static void DoAYSQ(int x);
24 static void DoAYNoise(void);
25
26 #define sunselect mapbyte1[0]
27 #define sungah    mapbyte1[1]
28 #define sunindex  mapbyte1[2]
29
30 static uint16 znreg;
31 static int32 inc;
32
33 DECLFW(SUN5BWRAM)
34 {
35  if((sungah&0xC0)==0xC0)
36   (WRAM-0x6000)[A]=V;
37 }
38
39 DECLFR(SUN5AWRAM)
40 {
41  if((sungah&0xC0)==0x40)
42   return X.DB;
43  return CartBR(A);
44 }
45
46 DECLFW(Mapper69_SWL)
47 {
48   sunindex=V%14;
49 }
50 DECLFW(Mapper69_SWH)
51 {
52              GameExpSound.Fill=AYSound;
53              switch(sunindex)
54              {
55               case 0:
56               case 1:
57               case 8:DoAYSQ(0);break;
58               case 2:
59               case 3:
60               case 9:DoAYSQ(1);break;
61               case 4:
62               case 5:
63               case 10:DoAYSQ(2);break;
64               case 6:DoAYNoise();znreg=0xFFFF;break;
65               case 7:DoAYNoise();
66                      DoAYSQ(0);
67                      DoAYSQ(1);
68                      DoAYSQ(2);break;
69              }
70              MapperExRAM[sunindex]=V;
71 }
72
73 DECLFW(Mapper69_write)
74 {
75  switch(A&0xE000)
76  {
77   case 0x8000:sunselect=V;break;
78   case 0xa000:
79               sunselect&=0xF;
80               if(sunselect<=7)
81                VROM_BANK1(sunselect<<10,V);
82               else
83                switch(sunselect&0x0f)
84                {
85                 case 8:
86                        sungah=V;
87                        if(V&0x40)
88                         {
89                          if(V&0x80) // Select WRAM
90                           setprg8r(0x10,0x6000,0);
91                         }
92                         else
93                          setprg8(0x6000,V);
94                         X6502_Rebase();
95                         break;
96                 case 9:ROM_BANK8(0x8000,V);
97                          X6502_Rebase();break;
98                 case 0xa:ROM_BANK8(0xa000,V);
99                          X6502_Rebase();break;
100                 case 0xb:ROM_BANK8(0xc000,V);
101                          X6502_Rebase();break;
102                 case 0xc:
103                          switch(V&3)
104                          {
105                           case 0:MIRROR_SET2(1);break;
106                           case 1:MIRROR_SET2(0);break;
107                           case 2:onemir(0);break;
108                           case 3:onemir(1);break;
109                          }
110                          break;
111              case 0xd:IRQa=V;break;
112              case 0xe:IRQCount&=0xFF00;IRQCount|=V;break;
113              case 0xf:IRQCount&=0x00FF;IRQCount|=V<<8;break;
114              }
115              break;
116  }
117 }
118
119 static int32 vcount[4];
120 static int CAYBC[4]={0,0,0,0};
121 static void DoAYSQ(int x)
122 {
123     int V;
124     uint32 freq;
125     unsigned char amp;
126     int32 start,end;
127
128     start=CAYBC[x];
129     end=(timestamp<<16)/soundtsinc;
130     if(end<=start) return;
131     CAYBC[x]=end;
132
133     if(!(MapperExRAM[0x7]&(1<<x)))
134     {
135       long vcoo;
136       freq=(MapperExRAM[x<<1]|((MapperExRAM[(x<<1)+1]&15)<<8))+1;
137       inc=(long double)((unsigned long)((FSettings.SndRate OVERSAMPLE)<<12))/
138         ((long double)PSG_base/freq);
139                             amp=MapperExRAM[0x8+x]&15;
140               amp<<=3;
141               vcoo=vcount[x];
142              if(amp)
143               for(V=start;V<end;V++)
144                {
145                 if(vcoo<(inc>>1))
146                   Wave[V>>4]+=amp;
147                 vcoo+=0x1000;
148                 if(vcoo>=inc) vcoo-=inc;
149                 }
150               vcount[x]=vcoo;
151      }
152 }
153 static void DoAYNoise(void)
154 {
155     int V;
156     uint32 freq;
157     unsigned char amp;
158     int32 start,end;
159
160     start=CAYBC[3];
161     end=(timestamp<<16)/soundtsinc;
162     if(end<=start) return;
163     CAYBC[3]=end;
164
165         amp=0;
166         for(V=0;V<3;V++)
167          {
168           if(!(MapperExRAM[0x7]&(8<<V)))
169           {
170           //if(MapperExRAM[0x8+V]&0x10) amp+=MapperExRAM[0x20]&15;
171                                 //else
172                                 amp+=MapperExRAM[0x8+V]&15;
173           }
174          }
175      amp<<=3;
176
177      if(amp)
178        {
179         freq=PSG_base/(MapperExRAM[0x6]+1);
180         if(freq>44100)
181          inc=((freq<<11)/(FSettings.SndRate OVERSAMPLE))<<4;
182         else
183          inc=(freq<<15)/(FSettings.SndRate OVERSAMPLE);
184
185          for(V=start;V<end;V++)
186           {
187              static uint32 mixer;
188
189              if(vcount[3]>=32768)
190              {
191                unsigned char feedback;
192                mixer=0;
193                if(znreg&1) mixer+=amp;
194                feedback=((znreg>>13)&1)^((znreg>>14)&1);
195                znreg=(znreg<<1)+(feedback);
196                vcount[3]-=32768;
197              }
198              Wave[V>>4]+=mixer;
199              vcount[3]+=inc;
200            }
201        }
202
203
204 }
205 static void AYSound(int Count)
206 {
207     int x;
208     DoAYSQ(0);
209     DoAYSQ(1);
210     DoAYSQ(2);
211     DoAYNoise();
212     for(x=0;x<4;x++)
213      CAYBC[x]=Count;
214 }
215
216 static void FP_FASTAPASS(1) SunIRQHook(int a)
217 {
218   if(IRQa)
219   {
220    IRQCount-=a;
221    if(IRQCount<=0)
222    {TriggerIRQ();IRQa=0;IRQCount=0xFFFF;}
223   }
224 }
225
226 void Mapper69_StateRestore(int version)
227 {
228    if(version>=19)
229    {
230     if(mapbyte1[1]&0x40)
231     {
232      if(mapbyte1[1]&0x80) // Select WRAM
233       setprg8r(0x10,0x6000,0);
234     }
235     else
236      setprg8(0x6000,mapbyte1[1]);
237    }
238    else
239     mapbyte1[1]=0xC0;
240 }
241
242 static void M69SC(void)
243 {
244  if(FSettings.SndRate)
245   Mapper69_ESI();
246  else
247   SetWriteHandler(0xc000,0xffff,(writefunc)0);
248 }
249
250 void Mapper69_ESI(void)
251 {
252  GameExpSound.RChange=M69SC;
253  if(FSettings.SndRate)
254  {
255   SetWriteHandler(0xc000,0xdfff,Mapper69_SWL);
256   SetWriteHandler(0xe000,0xffff,Mapper69_SWH);
257  }
258 }
259
260 void Mapper69_init(void)
261 {
262  SetupCartPRGMapping(0x10,WRAM,8192,1);
263
264  SetWriteHandler(0x8000,0xbfff,Mapper69_write);
265  SetWriteHandler(0x6000,0x7fff,SUN5BWRAM);
266  SetReadHandler(0x6000,0x7fff,SUN5AWRAM);
267  Mapper69_ESI();
268  MapIRQHook=SunIRQHook;
269  MapStateRestore=Mapper69_StateRestore;
270  znreg=0;
271 }
272