random warning fixes
[fceu.git] / boards / copyfami_hwi.c
1 /* FCE Ultra - NES/Famicom Emulator\r
2  *\r
3  * Copyright notice for this file:\r
4  *  Copyright (C) 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19  */\r
20 \r
21 // *** COPY FAMICOM HARDWARE INTERFACE ***\r
22 \r
23 #ifdef COPYFAMI\r
24 \r
25 #define MESSAGE_LOG\r
26 #define NO_CACHE\r
27 #define NO_RAM\r
28 \r
29 #include "__serial.h"\r
30 #include "mapinc.h"\r
31 \r
32 #define FNV_32_PRIME    ((uint32)0x01000193)\r
33 \r
34 #define CHR_CACHE_SIZE  (1024 * 4)\r
35 #define WRAM_CACHE_SIZE (1024 / 2)\r
36 #define PRG_CACHE_SIZE  (1024 / 4)\r
37 #define CMD_CACHE_SIZE  (1024 * 128)\r
38 \r
39 #define CMD_MAX_SIZE    (5)\r
40 #define CMD_MAX_RETEST  (16)\r
41 #define CMD_MAX_VERIFY  (16)\r
42 \r
43 static uint8 *WRAM = NULL;\r
44 \r
45 uint8 InitVector[] =   {0xDE, 0xAD, 0xBE, 0xEF}; // args none,               return DE AD BE EF\r
46 uint8 ResetCmd[] =     {0x00};                                   // args none,                           return none\r
47 uint8 StateCmd[] =     {0x01};                   // args none,               return 7 bytes status\r
48 uint8 StatusCmd[] =    {0x02};                   // args none,               return 32 bytes status\r
49 uint8 LoadPlugCmd[] =  {0x03, 0x00, 0x00};       // args 2b size, Nb data    return none\r
50 uint8 RunPlugCmd[] =   {0x04};                   // args none,               return none\r
51 uint8 RunGameCmd[] =   {0x05};                   // args none,               return none\r
52 uint8 NROMSave[] =     {0x06};                   // args none,               return 16b + 32kb + 8kb\r
53 \r
54 uint8 PRGWBCmd[] =     {0x08, 0x00, 0x00, 0x00}; // args 2b addr, 1b data    return none\r
55 uint8 PRGRBCmd[] =     {0x09, 0x00, 0x00};       // args 2b addr             return 1b data\r
56 uint8 CHRWBCmd[] =     {0x0A, 0x00, 0x00, 0x00}; // args 2b addr, 1b data    return none\r
57 uint8 CHRRBCmd[] =     {0x0B, 0x00, 0x00};       // args 2b addr,            return 1b data\r
58 \r
59 uint8 PRGSUMCmd[] =    {0x10, 0x00, 0x00};       // args 1b addr, 1b size    return (256 * N)b\r
60 uint8 PRG32KSUMCmd[] = {0x10, 0x80, 0x80};       // args 1b addr, 1b size    return 32kb\r
61 uint8 PRG16KSUMCmd[] = {0x10, 0x00, 0x40};       // args 1b addr, 1b size    return 16kb\r
62 uint8 PRG8KSUMCmd[] =  {0x10, 0x00, 0x20};       // args 1b addr, 1b size    return 8kb\r
63 uint8 PRG4KSUMCmd[] =  {0x10, 0x00, 0x10};       // args 1b addr, 1b size    return 4kb\r
64 \r
65 uint8 CHRSUMCmd[] =    {0x11, 0x00, 0x00};       // args 1b addr, 1b size    return (256 * N)b\r
66 uint8 CHR8KSUMCmd[] =  {0x11, 0x00, 0x20};       // args 1b addr, 1b size    return 8kb\r
67 uint8 CHR4KSUMCmd[] =  {0x11, 0x00, 0x10};       // args 1b addr, 1b size    return 4kb\r
68 uint8 CHR2KSUMCmd[] =  {0x11, 0x00, 0x08};       // args 1b addr, 1b size    return 2kb\r
69 uint8 CHR1KSUMCmd[] =  {0x11, 0x00, 0x04};       // args 1b addr, 1b size    return 1kb\r
70 \r
71 uint8 PRGGetCmd[] =    {0x12, 0x00, 0x00};       // args 1b addr, 1b size    return (256 * N)b\r
72 uint8 PRG32KGetCmd[] = {0x12, 0x80, 0x80};       // args 1b addr, 1b size    return 32kb\r
73 uint8 PRG16KGetCmd[] = {0x12, 0x00, 0x40};       // args 1b addr, 1b size    return 16kb\r
74 uint8 PRG8KGetCmd[] =  {0x12, 0x00, 0x20};       // args 1b addr, 1b size    return 8kb\r
75 uint8 PRG4KGetCmd[] =  {0x12, 0x00, 0x10};       // args 1b addr, 1b size    return 4kb\r
76 \r
77 uint8 CHRGetCmd[] =    {0x13, 0x00, 0x00};       // args 1b addr, 1b size    return (256 * N)b\r
78 uint8 CHR8KGetCmd[] =  {0x13, 0x00, 0x20};       // args 1b addr, 1b size    return 8kb\r
79 uint8 CHR4KGetCmd[] =  {0x13, 0x00, 0x10};       // args 1b addr, 1b size    return 4kb\r
80 uint8 CHR2KGetCmd[] =  {0x13, 0x00, 0x08};       // args 1b addr, 1b size    return 2kb\r
81 uint8 CHR1KGetCmd[] =  {0x13, 0x00, 0x04};       // args 1b addr, 1b size    return 1kb\r
82 \r
83 uint8 CPUTestCmd[] =   {0x14, 0x00, 0x00};       // args 1b addr, 1b size    return (2b + 1b) * N + 3b\r
84 \r
85 typedef struct {\r
86   int32 mirror;\r
87   int32 chrsum[8];\r
88   int32 prgsum[4];\r
89 } SYNC_STATE;\r
90 \r
91 static SYNC_STATE    state_cur, state_new, state_def;\r
92 \r
93 typedef struct {\r
94   uint8 *buf;\r
95   int32 count;\r
96 } DATA_BANKS;\r
97 \r
98 static DATA_BANKS  chr_data;\r
99 static int32       chr_bank[0x10000];\r
100 static DATA_BANKS  prg_data;\r
101 static int32       prg_bank[0x10000];\r
102 \r
103 typedef struct {\r
104   SYNC_STATE   states[CMD_CACHE_SIZE];\r
105   int32        seqs[CMD_CACHE_SIZE][CMD_MAX_SIZE];\r
106   int32        count;\r
107 } SYNC_CMDS;\r
108 \r
109 typedef struct {\r
110   int32        seq[CMD_MAX_SIZE];\r
111   int32        size;\r
112   int32        found;\r
113   uint32       hash;\r
114   uint16       hashf;\r
115 } SYNC_CMD;\r
116 \r
117 static SYNC_CMD     cmd;\r
118 static SYNC_CMDS    cmds;\r
119 \r
120 typedef struct {\r
121   int32 index;\r
122   int32 size;\r
123   int32 retest;\r
124   int32 verify; \r
125 } CMD_CACHE;\r
126 \r
127 static CMD_CACHE   cmd_cache[0x10000];\r
128 \r
129 static SFORMAT StateRegs[]=\r
130 {\r
131   {state_cur.chrsum, sizeof(state_cur.chrsum), "CHRREG"},\r
132   {state_cur.prgsum, sizeof(state_cur.prgsum), "ROMREG"},\r
133   {&state_cur.mirror, sizeof(state_cur.mirror), "MIRREG"},\r
134   {0}\r
135 };\r
136 \r
137 #define MI_U 4\r
138 \r
139 static char *mirror_names[5] = {"Horizontal", "Vertical", "Mirror 0", "Mirror 1", "Unknown mirror"};\r
140 static int32 mirror_modes[16] = {\r
141   MI_0, MI_U, MI_U, MI_H, MI_U, MI_V, MI_U, MI_U,\r
142   MI_U, MI_U, MI_U, MI_U, MI_U, MI_U, MI_U, MI_1 };\r
143 \r
144 #define CHRDEF(slot)   (chr_bank[state_def.chrsum[slot]])\r
145 #define PRGDEF(slot)   (prg_bank[state_def.prgsum[slot]])\r
146 #define CHRCUR(slot)   (chr_bank[state_cur.chrsum[slot]])\r
147 #define PRGCUR(slot)   (prg_bank[state_cur.prgsum[slot]])\r
148 #define CHRNEW(slot)   (chr_bank[state_new.chrsum[slot]])\r
149 #define PRGNEW(slot)   (prg_bank[state_new.prgsum[slot]])\r
150 \r
151 static void GetStatus(SYNC_STATE *state)\r
152 {\r
153   uint8  resp0;\r
154   uint16 resp1, i;\r
155   SEND(StatusCmd);\r
156   GET(resp0, 1);\r
157   state->mirror = resp0;\r
158   GET(resp0, 1);\r
159   for(i=0; i<8; i++) {\r
160     GET(resp1, 2);\r
161     state->chrsum[i] = resp1;\r
162   }\r
163   for(i=0; i<4; i++) {\r
164     GET(resp1, 2);\r
165     state->prgsum[i] = resp1;\r
166   }  \r
167 }\r
168 \r
169 static int32 FetchNewCHRBank(int32 slot)\r
170 {\r
171   FILE *ofile;\r
172   char name[256];\r
173   int32 bank = chr_data.count++;\r
174   CHR1KGetCmd[1] = slot << 2;\r
175   SENDGET(CHR1KGetCmd, chr_data.buf[bank * 1024], 1024);\r
176   sprintf(name,"%04x.chr",bank);\r
177   ofile=fopen(name,"wb");\r
178   fwrite((void *)&chr_data.buf[bank * 1024], 1, 1024, ofile);\r
179   fclose(ofile);\r
180   return bank;\r
181 }\r
182 \r
183 static int32 FetchNewPRGBank(int32 slot)\r
184 {\r
185   FILE *ofile;\r
186   char name[256];\r
187   int32 bank = prg_data.count++;\r
188   PRG8KGetCmd[1] = 0x80 + (slot << 5);\r
189   SENDGET(PRG8KGetCmd, prg_data.buf[bank * 8192], 8192);\r
190   sprintf(name,"%04x.prg",bank);\r
191   ofile=fopen(name,"wb");\r
192   fwrite((void *)&prg_data.buf[bank * 8192], 1, 8192, ofile);\r
193   fclose(ofile);\r
194   return bank;\r
195 }\r
196 \r
197 static int CheckStatus(void)\r
198 {\r
199   int32 i, ischanged = 0;\r
200   GetStatus(&state_new);\r
201   if(state_cur.mirror != state_new.mirror) {\r
202     state_cur.mirror = state_new.mirror;\r
203 #ifdef MESSAGE_LOG\r
204     FCEU_printf(">> mirror changed to %s (%02X)\n",mirror_names[mirror_modes[state_cur.mirror]], state_cur.mirror);\r
205 #endif\r
206     ischanged = 1;\r
207   } else {\r
208     state_new.mirror = -1;\r
209   }\r
210   for(i=0; i<8; i++) {\r
211     if(state_cur.chrsum[i] != state_new.chrsum[i]) {\r
212       state_cur.chrsum[i] = state_new.chrsum[i];\r
213       if(CHRCUR(i) == -1) {\r
214         CHRCUR(i) = FetchNewCHRBank(i);\r
215 #ifdef MESSAGE_LOG\r
216         FCEU_printf(">> chr[%d] bank %d loaded\n", i, CHRCUR(i));\r
217 #endif\r
218       }\r
219 #ifdef MESSAGE_LOG\r
220       else\r
221         FCEU_printf(">> chr[%d] bank %d switched\n", i, CHRCUR(i));\r
222 #endif\r
223       ischanged = 1;\r
224     } else {\r
225       state_new.chrsum[i] = -1;\r
226     }\r
227   }\r
228   for(i=0; i<4; i++) {\r
229     if(state_cur.prgsum[i] != state_new.prgsum[i]) {\r
230       state_cur.prgsum[i] = state_new.prgsum[i];                                \r
231       if(PRGCUR(i) == -1) {\r
232         PRGCUR(i) = FetchNewPRGBank(i);\r
233 #ifdef MESSAGE_LOG\r
234         FCEU_printf(">> prg[%d] bank %d loaded\n", i, PRGCUR(i));\r
235 #endif\r
236       }\r
237 #ifdef MESSAGE_LOG\r
238       else\r
239         FCEU_printf(">> prg[%d] bank %d switched\n", i, PRGCUR(i));\r
240 #endif\r
241       ischanged = 1;\r
242     } else {\r
243       state_new.prgsum[i] = -1;\r
244     }\r
245   }\r
246   return ischanged;\r
247 }\r
248 \r
249 #ifndef NO_CACHE\r
250 static void ApplyStatus()\r
251 {\r
252   int32 i;\r
253   if ((cmds.states[cmd.found].mirror != -1) && (cmds.states[cmd.found].mirror != state_cur.mirror)) {\r
254     state_cur.mirror = cmds.states[cmd.found].mirror;\r
255     setmirror(mirror_modes[state_cur.mirror]);\r
256 #ifdef MESSAGE_LOG\r
257     FCEU_printf(">> mirror changed to %s (%02X)\n",mirror_names[mirror_modes[state_cur.mirror]], state_cur.mirror);\r
258 #endif\r
259   }\r
260   for(i=0; i<8; i++) {\r
261     int32 sum = cmds.states[cmd.found].chrsum[i];\r
262     if (sum != -1) {\r
263       if (sum != state_cur.chrsum[i]) {\r
264         state_cur.chrsum[i] = sum;\r
265         setchr1r(1, i * 1024, CHRCUR(i));\r
266 #ifdef MESSAGE_LOG\r
267         FCEU_printf(">> chr[%d] bank %d switched\n", i, chr_bank[sum]);\r
268 #endif\r
269       }\r
270       else\r
271 #ifdef MESSAGE_LOG\r
272         FCEU_printf(">> chr[%d] bank %d switched the same\n", i, chr_bank[sum]);\r
273     }\r
274 #endif\r
275   }\r
276   for(i=0; i<4; i++) {\r
277     int32 sum = cmds.states[cmd.found].prgsum[i];\r
278     if (sum != -1) {\r
279       if (sum != state_cur.prgsum[i]) {\r
280         state_cur.prgsum[i] = sum;\r
281         setprg8r(2, 0x8000 + (i * 8192), PRGCUR(i));\r
282 #ifdef MESSAGE_LOG\r
283         FCEU_printf(">> prg[%d] bank %d switched\n", i, prg_bank[sum]);\r
284 #endif\r
285       }\r
286       else\r
287 #ifdef MESSAGE_LOG\r
288         FCEU_printf(">> prg[%d] bank %d switched the same\n", i, prg_bank[sum]);\r
289     }\r
290 #endif\r
291   }\r
292 }\r
293 \r
294 static void LogCmd()\r
295 {\r
296   int32 i;\r
297   FCEU_printf(">> new cmd size %d [", cmd_cache[cmd.hashf].size);\r
298   for(i=0; i<cmd_cache[cmd.hashf].size; i++)\r
299     FCEU_printf(" %06X",cmds.seqs[cmd.found][i]);\r
300   FCEU_printf(" ], switched to (");    \r
301   if (cmds.states[cmd.found].mirror != -1)\r
302     FCEU_printf(" mirror=%s",mirror_names[mirror_modes[cmds.states[cmd.found].mirror]]);\r
303   for(i=0; i<8; i++)\r
304     if (cmds.states[cmd.found].chrsum[i] != -1)\r
305       FCEU_printf(" chr%d=%02X", i, chr_bank[cmds.states[cmd.found].chrsum[i]]);\r
306   for(i=0; i<4; i++)\r
307     if (cmds.states[cmd.found].prgsum[i] != -1)\r
308       FCEU_printf(" prg%d=%02X", i, prg_bank[cmds.states[cmd.found].prgsum[i]]);\r
309   FCEU_printf(" )\n");    \r
310 }\r
311 #endif\r
312 static void Sync()\r
313 {\r
314   setchr1r(1, 0x0000, CHRCUR(0));\r
315   setchr1r(1, 0x0400, CHRCUR(1));\r
316   setchr1r(1, 0x0800, CHRCUR(2));\r
317   setchr1r(1, 0x0C00, CHRCUR(3));\r
318   setchr1r(1, 0x1000, CHRCUR(4));\r
319   setchr1r(1, 0x1400, CHRCUR(5));\r
320   setchr1r(1, 0x1800, CHRCUR(6));\r
321   setchr1r(1, 0x1C00, CHRCUR(7));\r
322 #ifndef NO_RAM\r
323   setprg8r(1, 0x6000, 0);\r
324 #endif\r
325   setprg8r(2, 0x8000, PRGCUR(0));\r
326   setprg8r(2, 0xA000, PRGCUR(1));\r
327   setprg8r(2, 0xC000, PRGCUR(2));\r
328   setprg8r(2, 0xE000, PRGCUR(3));\r
329   setmirror(mirror_modes[state_cur.mirror]);\r
330 }\r
331 #ifndef NO_CACHE\r
332 static void UpdateCmd(uint32 val)\r
333 {\r
334   int32 index;\r
335   if(cmd.size < CMD_MAX_SIZE) {\r
336     index = cmd.size++;\r
337   } else {\r
338     // åñëè äîñòèãíóò ìàêñèìóì äëÿ êîìàíäû, âûáðîñèòü ïîñëåäíóþþ, äîáàâèòü íîâóþ,\r
339         // ïðîäîëæàòü äî áàíêñâè÷èíãà\r
340         cmd.hash = 0;\r
341         for(index = 0; index < (CMD_MAX_SIZE - 1); index++) {\r
342           cmd.seq[index] = cmd.seq[index + 1];\r
343       cmd.hash *= FNV_32_PRIME;\r
344       cmd.hash ^= cmd.seq[index];\r
345         }\r
346   }\r
347     cmd.seq[index] = val;\r
348     cmd.hash *= FNV_32_PRIME;\r
349     cmd.hash ^= val;\r
350     cmd.hashf = (cmd.hash >> 16) ^ (cmd.hash & 0xffff);\r
351     cmd.found = cmd_cache[cmd.hashf].index;\r
352   }\r
353 #endif\r
354 \r
355 static DECLFW(MCopyFamiWrite)\r
356 {\r
357 #ifndef NO_CACHE\r
358   int32 i;\r
359 #endif\r
360 \r
361 #ifdef MESSAGE_LOG\r
362   FCEU_printf("> WRITE %04X:%02X\n",A,V);\r
363 #endif\r
364 \r
365   PRGWBCmd[1] = A & 0xFF;\r
366   PRGWBCmd[2] = A >> 8;\r
367   PRGWBCmd[3] = V & 0xFF;\r
368   SEND(PRGWBCmd);\r
369 #ifdef NO_CACHE\r
370   CheckStatus();\r
371   Sync();\r
372 #else\r
373   UpdateCmd((A << 8) | V);\r
374   // èùåì êîìàíäó â êåøå\r
375   if(cmd.found == -1) {\r
376     // íå íàéäåíà, ïðîâåðÿåì, èçìåíèëîñü ëè ñîñòîÿíèå áàíêîâ\r
377     // ëèáî íå ïðåäåëüíîé ëè îíà äëèíû äëÿ êîìàíäû\r
378     cmd_cache[cmd.hashf].index = cmd.found = cmds.count++;\r
379     cmd_cache[cmd.hashf].retest = 0;\r
380     cmd_cache[cmd.hashf].verify = 0;\r
381     for(i=0; i<cmd.size; i++)\r
382       cmds.seqs[cmd.found][i] = cmd.seq[i];\r
383     cmd_cache[cmd.hashf].size = cmd.size;\r
384     if(CheckStatus()) {\r
385       cmds.states[cmd.found] = state_new;\r
386       LogCmd();\r
387       cmd.size = 0;\r
388       cmd.hash = 0;\r
389       Sync();\r
390     } else {\r
391       // åñëè äîáàâëåíà ïîëíàÿ êîìàíäà áåç áàíêñâèò÷èíãà\r
392       cmd_cache[cmd.hashf].index = -2;\r
393     }\r
394   } else if(cmd.found == -2) {\r
395     // ÷àñòè÷íîå ñîâïàäåíèå, åñëè ÷èñëî ïðîâåðîê íå ïðåâûñèëî ëèìèò\r
396     if(cmd_cache[cmd.hashf].retest < CMD_MAX_RETEST) {\r
397       // òî ïðîâåðèì ñîñòîÿíèå áàíêîâ\r
398       if(CheckStatus()) {\r
399         // èçìåíèëîñü, çàïèøåì íîâóþ êîìàíäó\r
400         cmd_cache[cmd.hashf].index = cmd.found = cmds.count++;\r
401         cmd_cache[cmd.hashf].retest = 0;\r
402         cmd_cache[cmd.hashf].verify = 0;\r
403         for(i=0; i<cmd.size; i++)\r
404           cmds.seqs[cmd.found][i] = cmd.seq[i];\r
405         cmd_cache[cmd.hashf].size = cmd.size;\r
406         cmds.states[cmd.found] = state_new;\r
407         LogCmd();\r
408         cmd.size = 0;\r
409         cmd.hash = 0;\r
410         Sync();\r
411       } else {\r
412         // íå èçìåíèëîñü, îòìåòèì óâåëè÷èì ñ÷åò÷èê ïðîâåðîê\r
413         cmd_cache[cmd.hashf].retest++;\r
414       }\r
415     }\r
416   } else {\r
417     // íàéäåíà, ïîñëåäíèé ðóáåæ îáîðîíû îò ãîâíà\r
418 /*\r
419     if(cmd_cache[cmd.hashf].verify < CMD_MAX_VERIFY) {\r
420       if(CheckStatus()) {\r
421         int32 changed = 0;\r
422       // åñëè åñòü èçìåíåíèÿ, ñðàâíèì íîâîå ñîñòîÿíèå ñ çàïèñàííûì\r
423         if(cmds.states[cmd.found].mirror != state_new.mirror)\r
424           changed = 1;\r
425         for(i=0; i<8; i++)\r
426           if(cmds.states[cmd.found].chrsum[i] != state_new.chrsum[i])\r
427             changed = 1;\r
428         for(i=0; i<4; i++)\r
429           if(cmds.states[cmd.found].prgsum[i] != state_new.prgsum[i])\r
430             changed = 1;\r
431         if(changed) {\r
432           cmd_cache[cmd.hashf].index = -1;\r
433           cmd_cache[cmd.hashf].retest = 0;\r
434           cmd_cache[cmd.hashf].verify = 0;\r
435           Sync();\r
436         }\r
437       } else\r
438         cmd_cache[cmd.hashf].verify++;\r
439     } else */ {\r
440       // ïðèìåíÿåì áåç ìàëåéøåãî çàçðåíèÿ ñîâåñòè\r
441       ApplyStatus();\r
442       cmd.size = 0;\r
443       cmd.hash = 0;\r
444     }\r
445   }\r
446 #endif\r
447 }\r
448 \r
449 static DECLFR(MCopyFamiRead)\r
450 {\r
451   uint8 result;\r
452   PRGRBCmd[1] = A & 0xFF;\r
453   PRGRBCmd[2] = A >> 8;\r
454   SENDGET(PRGRBCmd, result, 1);\r
455 #ifdef MESSAGE_LOG\r
456   FCEU_printf("> READ %04X:%02X\n",A,result);\r
457 #endif\r
458   return result;\r
459 }\r
460 \r
461 static void MCopyFamiReset(void)\r
462 {\r
463   state_cur = state_def;\r
464   Sync();\r
465 }\r
466 \r
467 static void MCopyFamiPower(void)\r
468 {\r
469 //  uint32 resp, presp;\r
470 \r
471   FCEU_printf("NOW POWERING... ");\r
472   \r
473   Sync();\r
474   \r
475   SetWriteHandler(0x4018, 0x7fff, MCopyFamiWrite);\r
476   SetReadHandler(0x4018, 0x7fff, MCopyFamiRead);\r
477 #ifndef NO_RAM\r
478   SetWriteHandler(0x6000, 0x7fff, CartBW);\r
479   SetReadHandler(0x6000, 0x7fff, CartBR);\r
480 #endif\r
481 \r
482 /*\r
483   FCEU_printf("READING MEMORY MAP...\n");\r
484   CPUTestCmd[1] = 0x50;\r
485   CPUTestCmd[2] = 0x30;\r
486   SEND(CPUTestCmd);\r
487   resp = 0;\r
488   presp = 0xffffffff;\r
489   while (presp != 0x00ff0000) {\r
490     GET(resp, 3);\r
491     if(presp != 0xffffffff) {\r
492       switch(presp & 0x00FF0000) {\r
493         case 0x00000000: // BUS\r
494           FCEU_printf("  %04X-%04X OPEN BUS\n",presp & 0x7fff, (resp - 1) & 0x7fff);\r
495           break;\r
496         case 0x00010000: // RAM\r
497           FCEU_printf("  %04X-%04X RAM\n",presp & 0x7fff, (resp - 1) & 0x7fff);\r
498           SetWriteHandler(presp & 0x7fff, (resp - 1) & 0x7fff, CartBW);\r
499           SetReadHandler(presp & 0x7fff, (resp - 1) & 0x7fff, CartBR);\r
500           break;\r
501       }      \r
502     }\r
503     presp = resp;\r
504   }\r
505 */\r
506   SetWriteHandler(0x8000, 0xffff, MCopyFamiWrite);\r
507   SetReadHandler(0x8000, 0xffff, CartBR);\r
508 \r
509   FCEU_printf("DONE!\nNOW COLLECTING DATA...\n");\r
510 }\r
511 \r
512 static void MCopyFamiClose(void)\r
513 {\r
514   if(chr_data.buf)\r
515     FCEU_gfree(chr_data.buf);\r
516   chr_data.buf=NULL;\r
517   if(prg_data.buf)\r
518     FCEU_gfree(prg_data.buf);\r
519   prg_data.buf=NULL;\r
520   if(WRAM)\r
521     FCEU_gfree(WRAM);\r
522   WRAM = NULL;\r
523   \r
524   SerialClose();\r
525 }\r
526 \r
527 static void StateRestore(int version)\r
528 {\r
529   Sync();\r
530 }\r
531 \r
532 void MapperCopyFami_Init(CartInfo *info)\r
533 {\r
534   uint32 resp = 0, i, size;\r
535 \r
536   memset(chr_bank, -1, sizeof(chr_bank));\r
537   memset(prg_bank, -1, sizeof(chr_bank));\r
538   memset(cmd_cache, -1, sizeof(cmd_cache));\r
539   memset(&cmds, 0, sizeof(cmds));\r
540   memset(&cmd, 0, sizeof(cmd));\r
541   \r
542   info->Reset=MCopyFamiReset;\r
543   info->Power=MCopyFamiPower;\r
544   info->Close=MCopyFamiClose;\r
545   GameStateRestore=StateRestore;\r
546 \r
547   size = 1024 * CHR_CACHE_SIZE; // ðàçìåð ñòðàíèöû 1êá\r
548   chr_data.buf = (uint8*)FCEU_gmalloc(size);\r
549   SetupCartCHRMapping(1, chr_data.buf, size, 1); // ïðîâåðÿòü ïïó ðàì, èíà÷å èãðà ìîæåò ïîðòèòü äàííûå\r
550   AddExState(chr_data.buf, size, 0, "CCHR");\r
551 \r
552   size = 8192; // ðàçìåð ñòðàíèöû 8êá\r
553   WRAM = (uint8*)FCEU_gmalloc(size);\r
554   SetupCartPRGMapping(1, WRAM, size, 1);\r
555   AddExState(WRAM, size, 0, "CPRM");\r
556 \r
557   size = 8192 * PRG_CACHE_SIZE; // ðàçìåð ñòðàíèöû 8êá\r
558   prg_data.buf = (uint8*)FCEU_gmalloc(size);\r
559   SetupCartPRGMapping(2, prg_data.buf, size, 0);\r
560   AddExState(prg_data.buf, size, 0, "CPPR");\r
561 \r
562 \r
563   FCEU_printf("WAITING FOR SERIAL PORT... ");\r
564   while(!SerialOpen(19, 921600)) { Sleep(500); }\r
565   FCEU_printf("READY!\n");\r
566 \r
567   FCEU_printf("WAITING FOR DEVICE... ");\r
568 \r
569   while(resp != *(uint32 *)&InitVector[0]) {\r
570     SEND(ResetCmd);\r
571     SENDGET(InitVector, resp, 4);\r
572     Sleep(500);\r
573   }\r
574 \r
575   FCEU_printf("READY!\n");\r
576   FCEU_printf("READING STATUS...\n");\r
577   GetStatus(&state_cur);\r
578   FCEU_printf("MIRRORING IS %s (%02X)\n",mirror_names[mirror_modes[state_cur.mirror]], state_cur.mirror);\r
579   FCEU_printf("READING CHR...\n INITIAL STATE:");\r
580     \r
581   for(i=0; i<8; i++) {\r
582     if(CHRCUR(i) == -1)\r
583       CHRCUR(i) = FetchNewCHRBank(i); \r
584     FCEU_printf(" CHR%d=%02X", i, CHRCUR(i));\r
585   }\r
586   FCEU_printf("\n");\r
587       \r
588   FCEU_printf("READING PRG...\n INITIAL STATE:");\r
589   for(i=0; i<4; i++) {\r
590     if(PRGCUR(i) == -1)\r
591       PRGCUR(i) = FetchNewPRGBank(i);\r
592     FCEU_printf(" PRG%d=%02X", i, PRGCUR(i));\r
593   }\r
594   FCEU_printf("\nDONE!\n");\r
595   \r
596   state_def = state_cur;\r
597 \r
598   AddExState(&StateRegs, ~0, 0, 0);\r
599 }\r
600 \r
601 #endif\r