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