6e3b5692fd6ce1dc2c9e7393f6dc258a7275752a
[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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\r
19  */\r
20 \r
21 #include "mapinc.h"\r
22 \r
23 static uint8 chrlo[8], chrhi[8], prg[2], mirr, vlock;\r
24 static int32 IRQa, IRQCount, IRQLatch, IRQClock; \r
25 static uint8 *WRAM=NULL;\r
26 static uint32 WRAMSIZE;\r
27 static uint8 *CHRRAM=NULL;\r
28 static uint32 CHRRAMSIZE;\r
29 \r
30 static SFORMAT StateRegs[]=\r
31 {\r
32   {chrlo, 8, "CHRLO"},\r
33   {chrhi, 8, "CHRHI"},\r
34   {prg, 2, "PRGR"},\r
35   {&mirr, 1, "MIRR"},\r
36   {&vlock, 1, "VLOCK"},\r
37   {&IRQa, 4, "IRQA"},\r
38   {&IRQCount, 4, "IRQC"},\r
39   {&IRQLatch, 4, "IRQL"},\r
40   {&IRQClock, 4, "IRQK"},\r
41   {0}\r
42 };\r
43 \r
44 static void Sync(void)\r
45 {\r
46   uint8 i;\r
47   setprg8r(0x10,0x6000,0);\r
48   setprg8(0x8000,prg[0]);\r
49   setprg8(0xa000,prg[1]);\r
50   setprg8(0xc000,~1);\r
51   setprg8(0xe000,~0);\r
52   for(i=0; i<8; i++)\r
53   {\r
54     uint32 chr = chrlo[i]|(chrhi[i]<<8);\r
55     if(chrlo[i]==0xc8)\r
56     {\r
57       vlock = 0;\r
58       continue;\r
59     }\r
60     else if(chrlo[i]==0x88)\r
61     {\r
62       vlock = 1;\r
63       continue;\r
64     }\r
65     if(((chrlo[i]==4)||(chrlo[i]==5))&&!vlock)\r
66       setchr1r(0x10,i<<10,chr&1);\r
67     else\r
68       setchr1(i<<10,chr);\r
69   }\r
70   switch(mirr)\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
79 static DECLFW(M253Write)\r
80 {\r
81   if((A>=0xB000)&&(A<=0xE00C))\r
82   {\r
83     uint8 ind=((((A&8)|(A>>8))>>3)+2)&7;\r
84     uint8 sar=A&4;\r
85     chrlo[ind]=(chrlo[ind]&(0xF0>>sar))|((V&0x0F)<<sar);\r
86     if(A&4)\r
87       chrhi[ind]=V>>4;\r
88     Sync();\r
89   }\r
90   else\r
91    switch(A)\r
92     {\r
93       case 0x8010: prg[0]=V; Sync(); break;\r
94       case 0xA010: prg[1]=V; Sync(); break;\r
95       case 0x9400: mirr=V&3; Sync(); break;\r
96       case 0xF000: IRQLatch = (IRQLatch & 0xF0) | (V & 0x0F); break;\r
97       case 0xF004: IRQLatch = (IRQLatch & 0x0F) | (V << 4); break;\r
98       case 0xF008:\r
99         IRQa = V&3;\r
100         if(IRQa&2)\r
101         {\r
102           IRQCount = IRQLatch;\r
103           IRQClock = 0;\r
104         }\r
105         X6502_IRQEnd(FCEU_IQEXT);\r
106         break;\r
107     }\r
108 }\r
109 \r
110 static void M253Power(void)\r
111 {\r
112   Sync();\r
113   SetReadHandler(0x6000,0x7FFF,CartBR);\r
114   SetWriteHandler(0x6000,0x7FFF,CartBW);\r
115   SetReadHandler(0x8000,0xFFFF,CartBR);\r
116   SetWriteHandler(0x8000,0xFFFF,M253Write);\r
117 }\r
118 \r
119 static void M253Close(void)\r
120 {\r
121   if(WRAM)\r
122     FCEU_gfree(WRAM);\r
123   if(CHRRAM)\r
124     FCEU_gfree(CHRRAM);\r
125   WRAM=CHRRAM=NULL;\r
126 }\r
127 \r
128 static void M253IRQ(int cycles)\r
129 {\r
130   if(IRQa&2) \r
131   {\r
132     if((IRQClock+=cycles)>=0x72) \r
133     {\r
134       IRQClock -= 0x72;\r
135       if(IRQCount==0xFF)  \r
136       {\r
137         IRQCount = IRQLatch;\r
138         IRQa = IRQa|((IRQa&1)<<1);\r
139         X6502_IRQBegin(FCEU_IQEXT);\r
140       }\r
141       else \r
142         IRQCount++;\r
143     }\r
144   }\r
145 }\r
146 \r
147 static void StateRestore(int version)\r
148 {\r
149   Sync();\r
150 }\r
151 \r
152 void Mapper253_Init(CartInfo *info)\r
153 {\r
154   info->Power=M253Power;\r
155   info->Close=M253Close;\r
156   MapIRQHook=M253IRQ;\r
157   GameStateRestore=StateRestore;\r
158 \r
159   CHRRAMSIZE=4096;\r
160   CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSIZE);\r
161   SetupCartCHRMapping(0x10,CHRRAM,CHRRAMSIZE,1);\r
162   AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM");\r
163 \r
164   WRAMSIZE=8192;\r
165   WRAM=(uint8*)FCEU_gmalloc(WRAMSIZE);\r
166   SetupCartPRGMapping(0x10,WRAM,WRAMSIZE,1);\r
167   AddExState(WRAM, WRAMSIZE, 0, "WRAM");\r
168   if(info->battery)\r
169   {\r
170     info->SaveGame[0]=WRAM;\r
171     info->SaveGameLen[0]=WRAMSIZE;\r
172   }\r
173 \r
174   AddExState(&StateRegs, ~0, 0, 0);\r
175 }\r