04153386bdce065af521f83b86d1f87929c7ea25
[fceu.git] / boards / 8237.c
1 /* FCE Ultra - NES/Famicom Emulator\r
2  *\r
3  * Copyright notice for this file:\r
4  *  Copyright (C) 2005-2011 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  * Super Game (Sugar Softec) protected mapper\r
21  * Pocahontas 2 (Unl) [U][!], etc.\r
22  * TODO: 9in1 LION KING HANGS!\r
23  */\r
24 \r
25 #include "mapinc.h"\r
26 #include "mmc3.h"\r
27 \r
28 static uint8 cmdin;\r
29 \r
30 static uint8 regperm[8][8] = \r
31   {\r
32     {0, 1, 2, 3, 4, 5, 6, 7},\r
33     {0, 2, 6, 1, 7, 3, 4, 5},\r
34     {0, 5, 4, 1, 7, 2, 6, 3}, // unused\r
35     {0, 6, 3, 7, 5, 2, 4, 1},\r
36     {0, 2, 5, 3, 6, 1, 7, 4},\r
37     {0, 1, 2, 3, 4, 5, 6, 7}, // empty\r
38     {0, 1, 2, 3, 4, 5, 6, 7}, // empty\r
39     {0, 1, 2, 3, 4, 5, 6, 7}, // empty\r
40   };\r
41 \r
42 static uint8 adrperm[8][8] = \r
43   {\r
44     {0, 1, 2, 3, 4, 5, 6, 7},\r
45     {3, 2, 0, 4, 1, 5, 6, 7},\r
46     {0, 1, 2, 3, 4, 5, 6, 7}, // unused\r
47     {5, 0, 1, 2, 3, 7, 6, 4},\r
48     {3, 1, 0, 5, 2, 4, 6, 7},\r
49     {0, 1, 2, 3, 4, 5, 6, 7}, // empty\r
50     {0, 1, 2, 3, 4, 5, 6, 7}, // empty\r
51     {0, 1, 2, 3, 4, 5, 6, 7}, // empty\r
52   };\r
53 \r
54 static void UNL8237CW(uint32 A, uint8 V)\r
55 {\r
56   if(EXPREGS[0]&0x40)\r
57     setchr1(A,((EXPREGS[1]&0xc)<<6)|(V&0x7F)|((EXPREGS[1]&0x20)<<2));\r
58   else\r
59     setchr1(A,((EXPREGS[1]&0xc)<<6)|V);\r
60 }\r
61 \r
62 static void UNL8237PW(uint32 A, uint8 V)\r
63 {\r
64   if(EXPREGS[0]&0x40)\r
65   {\r
66     uint8 sbank = (EXPREGS[1]&0x10);\r
67     if(EXPREGS[0]&0x80)\r
68     {\r
69       uint8 bank = ((EXPREGS[1]&3)<<4)|(EXPREGS[0]&0x7)|(sbank>>1);\r
70       if(EXPREGS[0]&0x20)\r
71         setprg32(0x8000,bank>>1);\r
72       else\r
73       {\r
74         setprg16(0x8000,bank);\r
75         setprg16(0xC000,bank);\r
76       }\r
77     }\r
78     else\r
79       setprg8(A,((EXPREGS[1]&3)<<5)|(V&0x0F)|sbank);\r
80   }\r
81   else\r
82   {\r
83     if(EXPREGS[0]&0x80)\r
84     {\r
85       uint8 bank = ((EXPREGS[1]&3)<<4)|(EXPREGS[0]&0xF);\r
86       if(EXPREGS[0]&0x20)\r
87         setprg32(0x8000,bank>>1);\r
88       else\r
89       {\r
90         setprg16(0x8000,bank);\r
91         setprg16(0xC000,bank);\r
92       }\r
93     }\r
94     else\r
95       setprg8(A,((EXPREGS[1]&3)<<5)|(V&0x1F));\r
96   }\r
97 }\r
98 \r
99 static void UNL8237ACW(uint32 A, uint8 V)\r
100 {\r
101   if(EXPREGS[0]&0x40)\r
102     setchr1(A,((EXPREGS[1]&0xE)<<7)|(V&0x7F)|((EXPREGS[1]&0x20)<<2));\r
103   else\r
104     setchr1(A,((EXPREGS[1]&0xE)<<7)|V);\r
105 }\r
106 \r
107 static void UNL8237APW(uint32 A, uint8 V)\r
108 {\r
109   if(EXPREGS[0]&0x40)\r
110   {\r
111     uint8 sbank = (EXPREGS[1]&0x10);\r
112     if(EXPREGS[0]&0x80)\r
113     {\r
114       uint8 bank = ((EXPREGS[1]&3)<<4)|((EXPREGS[1]&8)<<3)|(EXPREGS[0]&0x7)|(sbank>>1);\r
115       if(EXPREGS[0]&0x20)\r
116         setprg32(0x8000,bank>>1);\r
117       else\r
118       {\r
119         setprg16(0x8000,bank);\r
120         setprg16(0xC000,bank);\r
121       }\r
122     }\r
123     else\r
124       setprg8(A,((EXPREGS[1]&3)<<5)|((EXPREGS[1]&8)<<4)|(V&0x0F)|sbank);\r
125   }\r
126   else\r
127   {\r
128     if(EXPREGS[0]&0x80)\r
129     {\r
130       uint8 bank = ((EXPREGS[1]&3)<<4)|((EXPREGS[1]&8)<<3)|(EXPREGS[0]&0xF);\r
131       if(EXPREGS[0]&0x20)\r
132         setprg32(0x8000,bank>>1);\r
133       else\r
134       {\r
135         setprg16(0x8000,bank);\r
136         setprg16(0xC000,bank);\r
137       }\r
138     }\r
139     else\r
140       setprg8(A,((EXPREGS[1]&3)<<5)|((EXPREGS[1]&8)<<4)|(V&0x1F));\r
141   }\r
142 }\r
143 static DECLFW(UNL8237Write)\r
144 {\r
145   uint8 dat = V;\r
146   uint8 adr = adrperm[EXPREGS[2]][((A>>12)&6)|(A&1)];\r
147   uint16 addr = (adr & 1)|((adr & 6)<<12)|0x8000;\r
148   if(adr < 4)\r
149   {\r
150     if(!adr)\r
151       dat = (dat & 0xC0)|(regperm[EXPREGS[2]][dat & 7]);\r
152     MMC3_CMDWrite(addr,dat);\r
153   }\r
154   else \r
155     MMC3_IRQWrite(addr,dat);\r
156 }\r
157 \r
158 static DECLFW(UNL8237ExWrite)\r
159 {\r
160   switch(A)\r
161   {\r
162     case 0x5000: EXPREGS[0]=V; FixMMC3PRG(MMC3_cmd); break;\r
163     case 0x5001: EXPREGS[1]=V; FixMMC3PRG(MMC3_cmd); FixMMC3CHR(MMC3_cmd); break;\r
164     case 0x5007: EXPREGS[2]=V; break;\r
165   }\r
166 }\r
167 \r
168 static void UNL8237Power(void)\r
169 {\r
170   EXPREGS[0]=EXPREGS[2]=0;\r
171   EXPREGS[1]=3;\r
172   GenMMC3Power();\r
173   SetWriteHandler(0x8000,0xFFFF,UNL8237Write);\r
174   SetWriteHandler(0x5000,0x7FFF,UNL8237ExWrite);\r
175 }\r
176 \r
177 void UNL8237_Init(CartInfo *info)\r
178 {\r
179   GenMMC3_Init(info, 256, 256, 0, 0);\r
180   cwrap=UNL8237CW;\r
181   pwrap=UNL8237PW;\r
182   info->Power=UNL8237Power;\r
183   AddExState(EXPREGS, 3, 0, "EXPR");\r
184   AddExState(&cmdin, 1, 0, "CMDIN");\r
185 }\r
186 \r
187 void UNL8237A_Init(CartInfo *info)\r
188 {\r
189   GenMMC3_Init(info, 256, 256, 0, 0);\r
190   cwrap=UNL8237ACW;\r
191   pwrap=UNL8237APW;\r
192   info->Power=UNL8237Power;\r
193   AddExState(EXPREGS, 3, 0, "EXPR");\r
194   AddExState(&cmdin, 1, 0, "CMDIN");\r
195 }\r