some warnings fixed, nsf fixed, palettes, more code backported
[fceu.git] / mappers / 85.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 #define vrctemp mapbyte1[0]
24 static uint8 indox;
25
26 #include "emu2413.h"
27
28 static int acount=0;
29
30 static OPLL *VRC7Sound=NULL;
31 static int dwave=0;
32
33 void DoVRC7Sound(void)
34 {
35  int32 z,a;
36
37  //if(FSettings.soundq>=1) return;
38  z=((SOUNDTS<<16)/soundtsinc)>>4;
39  a=z-dwave;
40
41  moocow(VRC7Sound, (int32 *)&Wave[dwave], a, 1);
42
43  dwave+=a;
44 }
45
46 void UpdateOPLNEO(int32 *Wave, int Count)
47 {
48  moocow(VRC7Sound, Wave, Count, 4);
49 }
50
51 void UpdateOPL(int Count)
52 {
53  int32 z,a;
54
55   z=((SOUNDTS<<16)/soundtsinc)>>4;
56  a=z-dwave;
57
58  if(VRC7Sound && a)
59   moocow(VRC7Sound, (int32 *)&Wave[dwave], a, 1);
60
61  dwave=0;
62 }
63
64 static INLINE void DaMirror(int V)
65 {
66  int salpo[4]={MI_V,MI_H,MI_0,MI_1};
67  setmirror(salpo[V&3]);
68 }
69
70 DECLFW(Mapper85_write)
71 {
72         A|=(A&8)<<1;
73
74         if(A>=0xa000 && A<=0xDFFF)
75         {
76         // printf("$%04x, $%04x\n",X.PC,A);
77          A&=0xF010;
78          {
79           int x=((A>>4)&1)|((A-0xA000)>>11);
80            mapbyte3[x]=V;
81           setchr1(x<<10,V);
82          }
83         }
84         else if(A==0x9030)
85         {
86          if(FSettings.SndRate)
87          {
88           OPLL_writeReg(VRC7Sound, indox, V);
89           GameExpSound.Fill=UpdateOPL;
90           GameExpSound.NeoFill=UpdateOPLNEO;
91          }
92         }
93         else switch(A&0xF010)
94         {
95          case 0x8000:mapbyte2[0]=V;setprg8(0x8000,V);break;
96          case 0x8010:mapbyte2[1]=V;setprg8(0xa000,V);break;
97          case 0x9000:mapbyte2[2]=V;setprg8(0xc000,V);break;
98          case 0x9010:indox=V;break;
99          case 0xe000:mapbyte2[3]=V;DaMirror(V);break;
100          case 0xE010:IRQLatch=V;
101                      X6502_IRQEnd(FCEU_IQEXT);
102                      break;
103          case 0xF000:IRQa=V&2;
104                      vrctemp=V&1;
105                      if(V&2) {IRQCount=IRQLatch;}
106                      acount=0;
107                      X6502_IRQEnd(FCEU_IQEXT);
108                      break;
109          case 0xf010:if(vrctemp) IRQa=1;
110                      else IRQa=0;
111                      X6502_IRQEnd(FCEU_IQEXT);
112                      break;
113         }
114 }
115
116 static void FP_FASTAPASS(1) KonamiIRQHook(int a)
117 {
118   #define ACBOO 341
119 //  #define ACBOO ((227*2)+1)
120   if(IRQa)
121    {
122     acount+=a*3;
123
124     if(acount>=ACBOO)
125     {
126      doagainbub:acount-=ACBOO;
127      IRQCount++;
128      if(IRQCount&0x100) {X6502_IRQBegin(FCEU_IQEXT);IRQCount=IRQLatch;}
129      if(acount>=ACBOO) goto doagainbub;
130     }
131  }
132 }
133
134 void Mapper85_StateRestore(int version)
135 {
136  int x;
137
138  if(version<7200)
139  {
140   for(x=0;x<8;x++)
141    mapbyte3[x]=CHRBankList[x];
142   for(x=0;x<3;x++)
143    mapbyte2[x]=PRGBankList[x];
144   mapbyte2[3]=(Mirroring<0x10)?Mirroring:Mirroring-0xE;
145  }
146
147  for(x=0;x<8;x++)
148   setchr1(x*0x400,mapbyte3[x]);
149  for(x=0;x<3;x++)
150   setprg8(0x8000+x*8192,mapbyte2[x]);
151  DaMirror(mapbyte2[3]);
152  //LoadOPL();
153 }
154
155 static void M85SC(void)
156 {
157  if(VRC7Sound)
158   OPLL_set_rate(VRC7Sound, FSettings.SndRate);
159 }
160
161 static void M85SKill(void)
162 {
163  if(VRC7Sound)
164   OPLL_delete(VRC7Sound);
165  VRC7Sound=NULL;
166 }
167
168 static void VRC7SI(void)
169 {
170   GameExpSound.RChange=M85SC;
171   GameExpSound.Kill=M85SKill;
172
173   VRC7Sound=OPLL_new(3579545, FSettings.SndRate?FSettings.SndRate:44100);
174   OPLL_reset(VRC7Sound);
175   OPLL_reset(VRC7Sound);
176 }
177
178 void NSFVRC7_Init(void)
179 {
180     SetWriteHandler(0x9010,0x901F,Mapper85_write);
181     SetWriteHandler(0x9030,0x903F,Mapper85_write);
182     VRC7SI();
183 }
184
185 void Mapper85_init(void)
186 {
187   MapIRQHook=KonamiIRQHook;
188   SetWriteHandler(0x8000,0xffff,Mapper85_write);
189   GameStateRestore=Mapper85_StateRestore;
190   if(!VROM_size)
191    SetupCartCHRMapping(0, CHRRAM, 8192, 1);
192   //AddExState(VRC7Instrument, 16, 0, "VC7I");
193   //AddExState(VRC7Chan, sizeof(VRC7Chan), 0, "V7CH");
194   VRC7SI();
195 }