7cf0646e2db3d16eaefeefdafe7014d1f461d622
[fceu.git] / boards / super24.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 //undef printf
23
24 static int32 IRQCount,IRQLatch;
25 static uint8 IRQa,resetmode,mbia;
26 static uint8 sizer,bigbank,bigbank2;
27
28 static uint8 DRegBuf[8],MMC3_cmd;
29
30 static int masko8[8]={63,31,15,1,3,0,0,0};
31 //static int masko1[8]={511,255,127,7,7,0,0,0};
32
33 static void swsetprg8(uint32 A, uint32 V)
34 {
35  V&=masko8[sizer&7];
36  V|=(bigbank*2);
37  setprg8r((V/64)&15,A,V);
38 }
39
40 static void swsetchr1(uint32 A, uint32 V)
41 {
42  if(sizer&0x20)
43   setchr1r(0x10,A,V);
44  else
45  {
46 //  V&=masko1[sizer&7];
47   V|=bigbank2*8;
48   setchr1r((V/512)&15,A,V);
49  }
50 }
51
52 static void swsetchr2(uint32 A, uint32 V)
53 {
54  if(sizer&0x20)
55   setchr2r(0x10,A,V);
56  else
57  {
58   //V&=masko1[sizer&7]>>1;
59   V|=bigbank2*4;
60   setchr2r((V/256)&15,A,V);
61  }
62 }
63
64 static void Sup24_hb(void)
65 {
66      if(ScreenON || SpriteON)
67      {
68       resetmode=0;
69       if(IRQCount>=0)
70       {
71         IRQCount--;
72         if(IRQCount<0)
73         {
74          if(IRQa)
75          {
76             resetmode = 1;
77             X6502_IRQBegin(FCEU_IQEXT);
78          }
79         }
80       }
81      }
82 }
83
84 static DECLFW(Sup24IRQWrite)
85 {
86         switch(A&0xE001)
87         {
88          case 0xc000:IRQLatch=V;
89                      if(resetmode==1)
90                       IRQCount=IRQLatch;
91                      break;
92          case 0xc001:resetmode=1;
93                      IRQCount=IRQLatch;
94                      break;
95          case 0xE000:IRQa=0;X6502_IRQEnd(FCEU_IQEXT);
96                      if(resetmode==1)
97                       {IRQCount=IRQLatch;}
98                      break;
99          case 0xE001:IRQa=1;
100                      if(resetmode==1)
101                        {IRQCount=IRQLatch;}
102                      break;
103         }
104 }
105
106 static INLINE void FixMMC3PRG(int V)
107 {
108           swsetprg8(0xA000,DRegBuf[7]);
109           swsetprg8(0xE000,~0);
110           if(V&0x40)
111            {
112             swsetprg8(0xC000,DRegBuf[6]);
113             swsetprg8(0x8000,~1);
114            }
115           else
116            {
117             swsetprg8(0x8000,DRegBuf[6]);
118             swsetprg8(0xC000,~1);
119            }
120           X6502_Rebase();
121 }
122
123 static INLINE void FixMMC3CHR(int V)
124 {
125            int cbase=(V&0x80)<<5;
126            swsetchr2((cbase^0x000),DRegBuf[0]>>1);
127            swsetchr2((cbase^0x800),DRegBuf[1]>>1);
128            swsetchr1(cbase^0x1000,DRegBuf[2]);
129            swsetchr1(cbase^0x1400,DRegBuf[3]);
130            swsetchr1(cbase^0x1800,DRegBuf[4]);
131            swsetchr1(cbase^0x1c00,DRegBuf[5]);
132 }
133
134 static DECLFW(Super24hiwrite)
135 {
136         //printf("$%04x:$%02x, %d\n",A,V,scanline);
137         switch(A&0xE001)
138         {
139          case 0x8000:
140           if((V&0x40) != (MMC3_cmd&0x40))
141            FixMMC3PRG(V);
142           if((V&0x80) != (MMC3_cmd&0x80))
143            FixMMC3CHR(V);
144           MMC3_cmd = V;
145           break;
146
147         case 0x8001:
148                 {
149                  int cbase=(MMC3_cmd&0x80)<<5;
150                  DRegBuf[MMC3_cmd&0x7]=V;
151                  switch(MMC3_cmd&0x07)
152                  {
153                   case 0: V>>=1;swsetchr2((cbase^0x000),V);break;
154                   case 1: V>>=1;swsetchr2((cbase^0x800),V);break;
155                   case 2: swsetchr1(cbase^0x1000,V); break;
156                   case 3: swsetchr1(cbase^0x1400,V); break;
157                   case 4: swsetchr1(cbase^0x1800,V); break;
158                   case 5: swsetchr1(cbase^0x1C00,V); break;
159                   case 6: if (MMC3_cmd&0x40) swsetprg8(0xC000,V);
160                           else swsetprg8(0x8000,V);
161                           X6502_Rebase();
162                           break;
163                   case 7: swsetprg8(0xA000,V);
164                           X6502_Rebase();
165                           break;
166                  }
167                 }
168                 break;
169
170         case 0xA000:
171                 mbia=V;
172                 setmirror((V&1)^1);
173                 break;
174  }
175 }
176
177
178 DECLFW(Super24Write)
179 {
180  //printf("$%04x:$%02x\n",A,V);
181  switch(A)
182  {
183   case 0x5ff0:sizer=V;
184               FixMMC3PRG(MMC3_cmd);
185               FixMMC3CHR(MMC3_cmd);
186               break;
187   case 0x5FF1:
188               bigbank=V;
189               FixMMC3PRG(MMC3_cmd);
190               break;
191   case 0x5FF2:
192               bigbank2=V;
193               FixMMC3CHR(MMC3_cmd);
194               break;
195  }
196 }
197
198 static void Super24Reset(void)
199 {
200  SetWriteHandler(0x8000,0xBFFF,Super24hiwrite);
201  SetWriteHandler(0x5000,0x7FFF,Super24Write);
202  SetWriteHandler(0xC000,0xFFFF,Sup24IRQWrite);
203  SetReadHandler(0x8000,0xFFFF,CartBR);
204  GameHBIRQHook=Sup24_hb;
205  IRQCount=IRQLatch=IRQa=resetmode=0;
206  sizer=0x24;
207  bigbank=159;
208  bigbank2=0;
209
210  MMC3_cmd=0;
211  DRegBuf[6]=0;
212  DRegBuf[7]=1;
213
214  FixMMC3PRG(0);
215  FixMMC3CHR(0);
216 }
217
218 static void MrRestore(int version)
219 {
220  FixMMC3PRG(MMC3_cmd);
221  FixMMC3CHR(MMC3_cmd);
222  setmirror((mbia&1)^1);
223 }
224
225 void Super24_Init(void)
226 {
227  BoardPower=Super24Reset;
228  SetupCartCHRMapping(0x10, GameMemBlock, 8192, 1);
229  GameStateRestore=MrRestore;
230
231  AddExState(GameMemBlock, 8192, 0, "CHRR");
232  AddExState(DRegBuf, 8, 0, "DREG");
233  AddExState(&IRQCount, 4, 1, "IRQC");
234  AddExState(&IRQLatch, 4, 1, "IQL1");
235  AddExState(&IRQa, 1, 0, "IRQA");
236  AddExState(&sizer, 1, 0, "SIZA");
237  AddExState(&bigbank, 1, 0, "BIG1");
238  AddExState(&bigbank2, 1, 0, "BIG2");
239 }