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