merge mappers from FCEU-mm
[fceu.git] / boards / 253.c
1 /* FCE Ultra - NES/Famicom Emulator\r
2  *\r
3  * Copyright notice for this file:\r
4  *  Copyright (C) 2009 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19  *\r
20  * TODO: cram disable cases! (Shen Hua Jian Yun III cannot boot with CRAM enabled)\r
21  */\r
22 \r
23 #include "mapinc.h"\r
24 \r
25 static uint8 chrlo[8], chrhi[8], prg[2], mirr;\r
26 static int32 IRQa, IRQCount, IRQLatch, IRQClock;\r
27 static uint8 *WRAM=NULL;\r
28 static uint32 WRAMSIZE;\r
29 static uint8 *CHRRAM=NULL;\r
30 static uint32 CHRRAMSIZE;\r
31 \r
32 static SFORMAT StateRegs[]=\r
33 {\r
34   {chrlo, 8, "CHRL"},\r
35   {chrhi, 8, "CHRH"},\r
36   {prg, 2, "PRGR"},\r
37   {&mirr, 1, "MIRR"},\r
38   {&IRQa, 4, "IRQA"},\r
39   {&IRQCount, 4, "IRQC"},\r
40   {&IRQLatch, 4, "IRQL"},\r
41   {&IRQClock, 4, "IRQK"},\r
42   {0}\r
43 };\r
44 \r
45 static void Sync(void)\r
46 {\r
47   uint8 i;\r
48   setprg8r(0x10,0x6000,0);\r
49   setprg8(0x8000,prg[0]);\r
50   setprg8(0xa000,prg[1]);\r
51   setprg8(0xc000,~1);\r
52   setprg8(0xe000,~0);\r
53   for(i=0; i<8; i++)\r
54   {\r
55     uint32 chr = chrlo[i]|(chrhi[i]<<8);\r
56     if((chr==4)||(chr==5))\r
57       setchr1r(0x10,i<<10,chr&1);\r
58     else\r
59       setchr1(i<<10,chr);\r
60   }\r
61   switch(mirr)\r
62   {\r
63     case 0: setmirror(MI_V); break;\r
64     case 1: setmirror(MI_H); break;\r
65     case 2: setmirror(MI_0); break;\r
66     case 3: setmirror(MI_1); break;\r
67   }\r
68 }\r
69 \r
70 static DECLFW(M253Write)\r
71 {\r
72   if((A>=0xB000)&&(A<=0xE00C))\r
73   {\r
74     uint8 ind=((((A&8)|(A>>8))>>3)+2)&7;\r
75     uint8 sar=A&4;\r
76     chrlo[ind]=(chrlo[ind]&(0xF0>>sar))|((V&0x0F)<<sar);\r
77     if(A&4)\r
78       chrhi[ind]=V>>4;\r
79     Sync();\r
80   }\r
81   else\r
82    switch(A)\r
83     {\r
84       case 0x8010: prg[0]=V; Sync(); break;\r
85       case 0xA010: prg[1]=V; Sync(); break;\r
86       case 0x9400: mirr=V&3; Sync(); break;\r
87       case 0xF000: IRQLatch = (IRQLatch & 0xF0) | (V & 0x0F); break;\r
88       case 0xF004: IRQLatch = (IRQLatch & 0x0F) | (V << 4); break;\r
89       case 0xF008:\r
90         IRQa = V&3;\r
91         if(IRQa&2)\r
92         {\r
93           IRQCount = IRQLatch;\r
94           IRQClock = 0;\r
95         }\r
96         X6502_IRQEnd(FCEU_IQEXT);\r
97         break;\r
98     }\r
99 }\r
100 \r
101 static void M253Power(void)\r
102 {\r
103   Sync();\r
104   SetReadHandler(0x6000,0x7FFF,CartBR);\r
105   SetWriteHandler(0x6000,0x7FFF,CartBW);\r
106   SetReadHandler(0x8000,0xFFFF,CartBR);\r
107   SetWriteHandler(0x8000,0xFFFF,M253Write);\r
108 }\r
109 \r
110 static void M253Close(void)\r
111 {\r
112   if(WRAM)\r
113     FCEU_gfree(WRAM);\r
114   if(CHRRAM)\r
115     FCEU_gfree(CHRRAM);\r
116   WRAM=CHRRAM=NULL;\r
117 }\r
118 \r
119 static void M253IRQ(int cycles)\r
120 {\r
121   if(IRQa&2)\r
122   {\r
123     if((IRQClock+=cycles)>=0x71)\r
124     {\r
125       IRQClock -= 0x71;\r
126       if(IRQCount==0xFF)\r
127       {\r
128         IRQCount = IRQLatch;\r
129         IRQa = IRQa|((IRQa&1)<<1);\r
130         X6502_IRQBegin(FCEU_IQEXT);\r
131       }\r
132       else\r
133         IRQCount++;\r
134     }\r
135   }\r
136 }\r
137 \r
138 static void StateRestore(int version)\r
139 {\r
140   Sync();\r
141 }\r
142 \r
143 void Mapper253_Init(CartInfo *info)\r
144 {\r
145   info->Power=M253Power;\r
146   info->Close=M253Close;\r
147   MapIRQHook=M253IRQ;\r
148   GameStateRestore=StateRestore;\r
149 \r
150   CHRRAMSIZE=4096;\r
151   CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSIZE);\r
152   SetupCartCHRMapping(0x10,CHRRAM,CHRRAMSIZE,1);\r
153   AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM");\r
154 \r
155   WRAMSIZE=8192;\r
156   WRAM=(uint8*)FCEU_gmalloc(WRAMSIZE);\r
157   SetupCartPRGMapping(0x10,WRAM,WRAMSIZE,1);\r
158   AddExState(WRAM, WRAMSIZE, 0, "WRAM");\r
159   if(info->battery)\r
160   {\r
161     info->SaveGame[0]=WRAM;\r
162     info->SaveGameLen[0]=WRAMSIZE;\r
163   }\r
164 \r
165   AddExState(&StateRegs, ~0, 0, 0);\r
166 }\r