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