initial fce ultra 0.81 import
[fceu.git] / mappers / 19.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 dopol mapbyte1[0]
24 #define gorfus mapbyte1[1]
25 #define gorko mapbyte1[2]
26
27 static void NamcoSound(int Count);
28 static void NamcoSoundHack(void);
29
30 static int32 inc;
31 void FP_FASTAPASS(1) NamcoIRQHook(int a)
32 {
33   if(IRQa)
34   {
35    IRQCount+=a;
36    if(IRQCount>=0x7fff)
37    {
38     X6502_IRQBegin(FCEU_IQEXT);
39     IRQa=0;
40     IRQCount=0x7fff;
41    }
42   }
43 }
44
45 DECLFR(Namco_Read4800)
46 {
47         uint8 ret=MapperExRAM[dopol&0x7f];
48         if(dopol&0x80)
49          dopol=(dopol&0x80)|((dopol+1)&0x7f);
50         return ret;
51 }
52
53 DECLFR(Namco_Read5000)
54 {
55  return(IRQCount);
56 }
57
58 DECLFR(Namco_Read5800)
59 {
60  return(IRQCount>>8);
61 }
62
63 static void FASTAPASS(2) DoNTARAMROM(int w, uint8 V)
64 {
65         mapbyte2[w]=V;
66         //if(V>=0xE0)
67         // setntamem(NTARAM+((V&1)<<10), 1, w);
68         if((V>=0xE0)) // || ((gorko>>(6+(w>>1)))&1) )
69          setntamem(NTARAM+((V&1)<<10), 1, w);
70         else 
71         {
72          V&=CHRmask1[0];
73          setntamem(VROM+(V<<10), 0, w);
74         }
75 //      else
76 //       setntamem(NTARAM+((V&1)<<10), 1, w);
77 }
78
79 static void FixNTAR(void)
80 {
81  int x;
82
83  for(x=0;x<4;x++)
84   DoNTARAMROM(x,mapbyte2[x]);
85 }
86
87 static void FASTAPASS(2) DoCHRRAMROM(int x, uint8 V)
88 {
89          mapbyte3[x]=V;
90          if(!((gorfus>>((x>>2)+6))&1) && (V>=0xE0))
91           VRAM_BANK1(x<<10,V&7);
92          else
93           VROM_BANK1(x<<10,V);
94 }
95
96 static void FixCRR(void)
97 {
98  int x;
99  for(x=0;x<8;x++)
100   DoCHRRAMROM(x,mapbyte3[x]);
101 }
102
103 static DECLFW(Mapper19_write)
104 {
105         A&=0xF800;
106
107         if(A>=0x8000 && A<=0xb800)
108          DoCHRRAMROM((A-0x8000)>>11,V);
109         else if(A>=0xC000 && A<=0xd800)
110          DoNTARAMROM((A-0xC000)>>11,V);
111         else switch(A)
112         {
113          case 0x4800:
114                    if(dopol&0x40)
115                    {
116                     if(FSettings.SndRate)
117                     {
118                      NamcoSoundHack();
119                      GameExpSound.Fill=NamcoSound;
120                     }
121                    }
122                    MapperExRAM[dopol&0x7f]=V;
123                    if(dopol&0x80)
124                     dopol=(dopol&0x80)|((dopol+1)&0x7f);
125                    break;
126
127         case 0xf800: dopol=V;break;
128         case 0x5000: IRQCount&=0xFF00;IRQCount|=V;X6502_IRQEnd(FCEU_IQEXT);break;
129         case 0x5800: IRQCount&=0x00ff;IRQCount|=(V&0x7F)<<8;
130                      IRQa=V&0x80;
131                      X6502_IRQEnd(FCEU_IQEXT);
132                      break;
133
134         case 0xE000:gorko=V&0xC0;
135                     //FixNTAR();
136                     ROM_BANK8(0x8000,V);
137                     break;
138         case 0xE800:gorfus=V&0xC0;
139                     FixCRR();
140                     ROM_BANK8(0xA000,V);
141                     break;
142         case 0xF000:
143                     ROM_BANK8(0xC000,V);
144                     break;
145         }
146 }
147
148 static int dwave=0;
149 static void DoNamcoSound(uint32 *Wave, int Count);
150
151 static void NamcoSoundHack(void)
152 {
153  int32 z,a;
154
155  z=((timestamp<<16)/soundtsinc)>>4;  
156  a=z-dwave;
157  if(a)
158   DoNamcoSound(&Wave[dwave], a);
159  dwave+=a;
160 }
161
162 static void NamcoSound(int Count)
163 {
164  int32 z,a;
165
166  z=((timestamp<<16)/soundtsinc)>>4;
167  a=z-dwave;
168  if(a)
169    DoNamcoSound(&Wave[dwave], a);
170  dwave=0;
171 }
172
173 static uint8 PlayIndex[8];
174 static int32 vcount[8];
175
176 static void DoNamcoSound(uint32 *Wave, int Count)
177 {
178         int P,V;
179
180
181       //FCEU_DispMessage("%d",MapperExRAM[0x7F]>>4);
182       for(P=7;P>=7-((MapperExRAM[0x7F]>>4)&7);P--)
183       {
184        if((MapperExRAM[0x44+(P<<3)]&0xE0) && (MapperExRAM[0x47+(P<<3)]&0xF))
185        {
186         uint32 freq;
187         int32 vco;
188         uint32 duff,duff2,lengo,envelope;
189         //uint64 ta;
190
191         vco=vcount[P];
192         freq=MapperExRAM[0x40+(P<<3)];
193         freq|=MapperExRAM[0x42+(P<<3)]<<8;
194         freq|=(MapperExRAM[0x44+(P<<3)]&3)<<16;
195
196         if(!freq) continue;
197
198         {
199          int c=((MapperExRAM[0x7F]>>4)&7)+1;
200
201          inc=(long double)(FSettings.SndRate<<15)/((long double)freq*
202                 21477272/((long double)0x400000*c*45));
203         }
204
205         envelope=((MapperExRAM[0x47+(P<<3)]&0xF)<<18)/15;
206         duff=MapperExRAM[(((MapperExRAM[0x46+(P<<3)]+PlayIndex[P])>>1)&0xFF)];
207         if((MapperExRAM[0x46+(P<<3)]+PlayIndex[P])&1)
208          duff>>=4;
209         duff&=0xF;
210         duff2=(duff*envelope)>>14;
211   
212         lengo=((8-((MapperExRAM[0x44+(P<<3)]>>2)&7)))<<2;
213         for(V=0;V<Count OVERSAMPLE;V++)
214         {
215          if(vco>=inc)
216          {
217           PlayIndex[P]++;
218           if(PlayIndex[P]>=lengo)
219            PlayIndex[P]=0;
220           vco-=inc;
221           duff=MapperExRAM[(((MapperExRAM[0x46+(P<<3)]+PlayIndex[P])&0xFF)>>1)];
222           if((MapperExRAM[0x46+(P<<3)]+PlayIndex[P])&1)
223            duff>>=4;
224           duff&=0xF;
225           duff2=(duff*envelope)>>14;
226          }
227           Wave[V>>4]+=duff2;
228           vco+=0x8000;
229         }
230         vcount[P]=vco;
231        }
232       }
233 }
234
235 static void Mapper19_StateRestore(int version)
236 {
237  FixNTAR();
238  if(version>=80)
239   FixCRR();
240 }
241
242 static void M19SC(void)
243 {
244  if(FSettings.SndRate)
245   Mapper19_ESI();
246 }
247
248 void Mapper19_ESI(void)
249 {
250   GameExpSound.RChange=M19SC;
251   SetWriteHandler(0xf800,0xffff,Mapper19_write);
252   SetWriteHandler(0x4800,0x4fff,Mapper19_write);
253   SetReadHandler(0x4800,0x4fff,Namco_Read4800);
254 }
255
256 void Mapper19_init(void)
257 {
258         if(!Mirroring)
259         {
260          DoNTARAMROM(0,0xE0);
261          DoNTARAMROM(1,0xE0);
262          DoNTARAMROM(2,0xE1);
263          DoNTARAMROM(3,0xE1);
264         }
265         else
266         {
267          DoNTARAMROM(0,0xE0);
268          DoNTARAMROM(2,0xE0);
269          DoNTARAMROM(1,0xE1);
270          DoNTARAMROM(3,0xE1);
271         }
272         VROM_BANK8(~0);
273         SetWriteHandler(0x8000,0xffff,Mapper19_write);
274         SetWriteHandler(0x4020,0x5fff,Mapper19_write);
275         SetReadHandler(0x4800,0x4fff,Namco_Read4800);
276         SetReadHandler(0x5000,0x57ff,Namco_Read5000);
277         SetReadHandler(0x5800,0x5fff,Namco_Read5800);
278
279         MapIRQHook=NamcoIRQHook;
280         MapStateRestore=Mapper19_StateRestore;
281         GameExpSound.RChange=M19SC;
282         if(FSettings.SndRate)
283          Mapper19_ESI();
284         gorfus=0xFF;
285 }
286