merge mapper code from FCEUX
[fceu.git] / boards / 23.c
... / ...
CommitLineData
1/* FCE Ultra - NES/Famicom Emulator\r
2 *\r
3 * Copyright notice for this file:\r
4 * Copyright (C) 2007 CaH4e3\r
5 *\r
6 * This program is free software; you can redistribute it and/or modify\r
7 * it under the terms of the GNU General Public License as published by\r
8 * the Free Software Foundation; either version 2 of the License, or\r
9 * (at your option) any later version.\r
10 *\r
11 * This program is distributed in the hope that it will be useful,\r
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
14 * GNU General Public License for more details.\r
15 *\r
16 * You should have received a copy of the GNU General Public License\r
17 * along with this program; if not, write to the Free Software\r
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\r
19 */\r
20\r
21#include "mapinc.h"\r
22\r
23static uint8 is23;\r
24static uint16 IRQCount;\r
25static uint8 IRQLatch,IRQa;\r
26static uint8 prgreg[2];\r
27static uint8 chrreg[8];\r
28static uint8 regcmd, irqcmd, mirr, big_bank;\r
29static uint16 acount=0;\r
30\r
31static uint8 *WRAM=NULL;\r
32static uint32 WRAMSIZE;\r
33\r
34static SFORMAT StateRegs[]=\r
35{\r
36 {prgreg, 2, "PRGREGS"},\r
37 {chrreg, 8, "CHRREGS"},\r
38 {&regcmd, 1, "REGCMD"},\r
39 {&irqcmd, 1, "IRQCMD"},\r
40 {&mirr, 1, "MIRR"},\r
41 {&big_bank, 1, "BIGB"},\r
42 {&IRQCount, 2, "IRCN"},\r
43 {&IRQLatch, 1, "IRQL"},\r
44 {&IRQa, 1, "IRQA"},\r
45 {0}\r
46};\r
47\r
48static void Sync(void)\r
49{\r
50 if(regcmd&2)\r
51 {\r
52 setprg8(0xC000,prgreg[0]|big_bank);\r
53 setprg8(0x8000,((~1)&0x1F)|big_bank);\r
54 }\r
55 else\r
56 {\r
57 setprg8(0x8000,prgreg[0]|big_bank);\r
58 setprg8(0xC000,((~1)&0x1F)|big_bank);\r
59 }\r
60 setprg8(0xA000,prgreg[1]|big_bank);\r
61 setprg8(0xE000,((~0)&0x1F)|big_bank);\r
62 if(UNIFchrrama)\r
63 setchr8(0);\r
64 else\r
65 {\r
66 uint8 i;\r
67 for(i=0; i<8; i++)\r
68 setchr1(i<<10, chrreg[i]);\r
69 }\r
70 switch(mirr&0x3)\r
71 {\r
72 case 0: setmirror(MI_V); break;\r
73 case 1: setmirror(MI_H); break;\r
74 case 2: setmirror(MI_0); break;\r
75 case 3: setmirror(MI_1); break;\r
76 }\r
77}\r
78\r
79static DECLFW(M23Write)\r
80{\r
81// FCEU_printf("%04x:%04x\n",A,V);\r
82 A|=((A>>2)&0x3)|((A>>4)&0x3)|((A>>6)&0x3); // actually there is many-in-one mapper source, some pirate or\r
83 // licensed games use various address bits for registers\r
84 A&=0xF003;\r
85 if((A>=0xB000)&&(A<=0xE003))\r
86 {\r
87 if(UNIFchrrama)\r
88 big_bank=(V&8)<<2; // my personally many-in-one feature ;) just for support pirate cart 2-in-1\r
89 else\r
90 { \r
91 uint16 i=((A>>1)&1)|((A-0xB000)>>11);\r
92 chrreg[i]&=(0xF0)>>((A&1)<<2);\r
93 chrreg[i]|=(V&0xF)<<((A&1)<<2);\r
94 }\r
95 Sync();\r
96 }\r
97 else\r
98 switch(A&0xF003)\r
99 {\r
100 case 0x8000: \r
101 case 0x8001: \r
102 case 0x8002: \r
103 case 0x8003: if(is23) \r
104 prgreg[0]=V&0x1F; \r
105 Sync(); \r
106 break;\r
107 case 0xA000: \r
108 case 0xA001: \r
109 case 0xA002: \r
110 case 0xA003: if(is23) \r
111 prgreg[1]=V&0x1F; \r
112 else\r
113 {\r
114 prgreg[0]=(V<<1)&0x1F;\r
115 prgreg[1]=((V<<1)&0x1F)|1;\r
116 }\r
117 Sync();\r
118 break;\r
119 case 0x9000:\r
120 case 0x9001: if(V!=0xFF) mirr=V; Sync(); break;\r
121 case 0x9002: \r
122 case 0x9003: regcmd=V; Sync(); break;\r
123 case 0xF000: X6502_IRQEnd(FCEU_IQEXT); IRQLatch&=0xF0; IRQLatch|=V&0xF; break;\r
124 case 0xF001: X6502_IRQEnd(FCEU_IQEXT); IRQLatch&=0x0F; IRQLatch|=V<<4; break;\r
125 case 0xF002: X6502_IRQEnd(FCEU_IQEXT); acount=0; IRQCount=IRQLatch; IRQa=V&2; irqcmd=V&1; break;\r
126 case 0xF003: X6502_IRQEnd(FCEU_IQEXT); IRQa=irqcmd; break;\r
127 }\r
128}\r
129\r
130static void M23Power(void)\r
131{\r
132 big_bank=0x20; \r
133 Sync();\r
134 setprg8r(0x10,0x6000,0); // another many-in-one code, WRAM actually contain only WaiWaiWorld game\r
135 SetReadHandler(0x6000,0x7FFF,CartBR);\r
136 SetWriteHandler(0x6000,0x7FFF,CartBW);\r
137 SetReadHandler(0x8000,0xFFFF,CartBR);\r
138 SetWriteHandler(0x8000,0xFFFF,M23Write);\r
139}\r
140\r
141static void M23Reset(void)\r
142{\r
143}\r
144\r
145void M23IRQHook(int a)\r
146{\r
147 #define LCYCS 341\r
148 if(IRQa)\r
149 {\r
150 acount+=a*3;\r
151 if(acount>=LCYCS)\r
152 {\r
153 while(acount>=LCYCS)\r
154 {\r
155 acount-=LCYCS;\r
156 IRQCount++;\r
157 if(IRQCount&0x100) \r
158 {\r
159 X6502_IRQBegin(FCEU_IQEXT);\r
160 IRQCount=IRQLatch;\r
161 }\r
162 }\r
163 }\r
164 }\r
165}\r
166\r
167static void StateRestore(int version)\r
168{\r
169 Sync();\r
170}\r
171\r
172static void M23Close(void)\r
173{\r
174 if(WRAM)\r
175 FCEU_gfree(WRAM);\r
176}\r
177\r
178void Mapper23_Init(CartInfo *info)\r
179{\r
180 is23=1;\r
181 info->Power=M23Power;\r
182 info->Close=M23Close;\r
183 MapIRQHook=M23IRQHook;\r
184 GameStateRestore=StateRestore;\r
185\r
186 WRAMSIZE=8192;\r
187 WRAM=(uint8*)FCEU_gmalloc(WRAMSIZE);\r
188 SetupCartPRGMapping(0x10,WRAM,WRAMSIZE,1);\r
189 AddExState(WRAM, WRAMSIZE, 0, "WRAM");\r
190\r
191 AddExState(&StateRegs, ~0, 0, 0);\r
192}\r
193\r
194void UNLT230_Init(CartInfo *info)\r
195{\r
196 is23=0;\r
197 info->Power=M23Power;\r
198 info->Close=M23Close;\r
199 MapIRQHook=M23IRQHook;\r
200 GameStateRestore=StateRestore;\r
201\r
202 WRAMSIZE=8192;\r
203 WRAM=(uint8*)FCEU_gmalloc(WRAMSIZE);\r
204 SetupCartPRGMapping(0x10,WRAM,WRAMSIZE,1);\r
205 AddExState(WRAM, WRAMSIZE, 0, "WRAM");\r
206\r
207 AddExState(&StateRegs, ~0, 0, 0);\r
208}\r