1 /*
2 * megacart.c -- VIC20 Mega-Cart emulation.
3 *
4 * Written by
5 * Daniel Kahlin <daniel@kahlin.net>
6 *
7 * This file is part of VICE, the Versatile Commodore Emulator.
8 * See README for copyright notice.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23 * 02111-1307 USA.
24 *
25 */
26
27 #include "vice.h"
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include "archdep.h"
34 #include "cartio.h"
35 #include "cartridge.h"
36 #include "cmdline.h"
37 #include "export.h"
38 #include "lib.h"
39 #include "log.h"
40 #include "machine.h"
41 #include "megacart.h"
42 #include "mem.h"
43 #include "monitor.h"
44 #include "resources.h"
45 #include "snapshot.h"
46 #include "types.h"
47 #include "util.h"
48 #include "vic20cart.h"
49 #include "vic20cartmem.h"
50 #include "vic20mem.h"
51 #include "zfile.h"
52
53 /* ------------------------------------------------------------------------- */
54
55 /*
56 * Cartridge RAM
57 *
58 * Mapping
59 * RAM VIC20
60 * 0x0000 - 0x1fff -> 0xa000 - 0xbfff
61 * 0x2000 - 0x7fff -> 0x2000 - 0x7fff
62 *
63 * (by reasoning around minimal decoding, may be different on actual HW)
64 */
65 #define CART_RAM_SIZE 0x8000
66 static uint8_t *cart_ram = NULL;
67
68 /*
69 * Cartridge NvRAM
70 *
71 * Mapping
72 * NvRAM VIC20
73 * 0x0400 - 0x0fff -> 0x0400 - 0x0fff
74 * 0x1800 - 0x1fff -> 0x9800 - 0x9fff
75 *
76 * (by reasoning around minimal decoding, may be different on actual HW)
77 */
78 #define CART_NVRAM_SIZE 0x2000
79 static uint8_t *cart_nvram = NULL;
80
81 /*
82 * Cartridge ROM
83 *
84 * Mapping
85 * ROM
86 * 0x000000 - 0x0fffff -> Low ROM: banks 0x00-0x7f
87 * 0x100000 - 0x1fffff -> High ROM: banks 0x00-0x7f
88 *
89 */
90 #define CART_ROM_SIZE 0x200000
91 static uint8_t *cart_rom = NULL;
92
93 /* Cartridge States */
94 static enum { BUTTON_RESET, SOFTWARE_RESET } reset_mode = BUTTON_RESET;
95 static int oe_flop = 0;
96 static int nvram_en_flop = 0;
97 static uint8_t bank_low_reg = 0;
98 static uint8_t bank_high_reg = 0;
99
100 /* Resource variables */
101 static char *nvram_filename = NULL;
102 static int nvram_writeback = 0;
103
104 static log_t megacart_log = LOG_ERR;
105
106 /* ------------------------------------------------------------------------- */
107
108 /* helper pointers */
109 static uint8_t *cart_rom_low;
110 static uint8_t *cart_rom_high;
111
112 /* ------------------------------------------------------------------------- */
113
114 /* Some prototypes are needed */
115 static uint8_t megacart_io2_read(uint16_t addr);
116 static void megacart_io2_store(uint16_t addr, uint8_t value);
117 static uint8_t megacart_io3_read(uint16_t addr);
118 static uint8_t megacart_io3_peek(uint16_t addr);
119 static void megacart_io3_store(uint16_t addr, uint8_t value);
120 static int megacart_mon_dump(void);
121
122 static io_source_t megacart_io2_device = {
123 CARTRIDGE_VIC20_NAME_MEGACART, /* name of the device */
124 IO_DETACH_CART, /* use cartridge ID to detach the device when involved in a read-collision */
125 IO_DETACH_NO_RESOURCE, /* does not use a resource for detach */
126 0x9800, 0x9bff, 0x3ff, /* range for the device, regs:$9800-$9bff */
127 0, /* read validity is determined by the device upon a read */
128 megacart_io2_store, /* store function */
129 NULL, /* NO poke function */
130 megacart_io2_read, /* read function */
131 NULL, /* TODO: peek function */
132 megacart_mon_dump, /* device state information dump function */
133 CARTRIDGE_VIC20_MEGACART, /* cartridge ID */
134 IO_PRIO_NORMAL, /* normal priority, device read needs to be checked for collisions */
135 0 /* insertion order, gets filled in by the registration function */
136 };
137
138 static io_source_t megacart_io3_device = {
139 CARTRIDGE_VIC20_NAME_MEGACART, /* name of the device */
140 IO_DETACH_CART, /* use cartridge ID to detach the device when involved in a read-collision */
141 IO_DETACH_NO_RESOURCE, /* does not use a resource for detach */
142 0x9c00, 0x9fff, 0x3ff, /* range for the device, regs:$9c00-$9fff */
143 0, /* read validity is determined by the device upon a read */
144 megacart_io3_store, /* store function */
145 NULL, /* NO poke function */
146 megacart_io3_read, /* read function */
147 megacart_io3_peek, /* peek function */
148 megacart_mon_dump, /* device state information dump function */
149 CARTRIDGE_VIC20_MEGACART, /* cartridge ID */
150 IO_PRIO_NORMAL, /* normal priority, device read needs to be checked for collisions */
151 0 /* insertion order, gets filled in by the registration function */
152 };
153
154 static io_source_list_t *megacart_io2_list_item = NULL;
155 static io_source_list_t *megacart_io3_list_item = NULL;
156
157 static const export_resource_t export_res = {
158 CARTRIDGE_VIC20_NAME_MEGACART, 0, 0, &megacart_io2_device, &megacart_io3_device, CARTRIDGE_VIC20_MEGACART
159 };
160
161 /* ------------------------------------------------------------------------- */
162
163 /* read 0x0400-0x0fff (nvram 0x0400 - 0x0fff) */
megacart_ram123_read(uint16_t addr)164 uint8_t megacart_ram123_read(uint16_t addr)
165 {
166 if (nvram_en_flop) {
167 return cart_nvram[addr & 0x0fff];
168 } else {
169 return vic20_v_bus_last_data;
170 }
171 }
172
173 /* store 0x0400-0x0fff (nvram 0x0400 - 0x0fff) */
megacart_ram123_store(uint16_t addr,uint8_t value)174 void megacart_ram123_store(uint16_t addr, uint8_t value)
175 {
176 if (nvram_en_flop) {
177 cart_nvram[addr & 0x0fff] = value;
178 }
179 }
180
181 /* read 0x2000-0x7fff */
megacart_blk123_read(uint16_t addr)182 uint8_t megacart_blk123_read(uint16_t addr)
183 {
184 uint8_t bank_low;
185 uint8_t bank_high;
186 int ram_low_en;
187 int ram_high_en;
188
189 /* get bank registers */
190 bank_low = (oe_flop) ? bank_low_reg : 0x7f;
191 bank_high = (oe_flop) ? bank_high_reg : 0x7f;
192
193 /* determine flags from bank registers. */
194 ram_low_en = (bank_low & 0x80) ? 1 : 0;
195 ram_high_en = (bank_high & 0x80) ? 1 : 0;
196
197 if (!ram_low_en) {
198 return cart_rom_low[(addr & 0x1fff) | (bank_low * 0x2000)];
199 } else {
200 if (ram_high_en) {
201 return cart_ram[addr];
202 }
203 }
204
205 return vic20_cpu_last_data;
206 }
207
208 /* store 0x2000-0x7fff */
megacart_blk123_store(uint16_t addr,uint8_t value)209 void megacart_blk123_store(uint16_t addr, uint8_t value)
210 {
211 uint8_t bank_low;
212 uint8_t bank_high;
213 int ram_low_en;
214 int ram_high_en;
215 int ram_wp;
216
217 /* get bank registers */
218 bank_low = (oe_flop) ? bank_low_reg : 0x7f;
219 bank_high = (oe_flop) ? bank_high_reg : 0x7f;
220
221 /* determine flags from bank registers. */
222 ram_low_en = (bank_low & 0x80) ? 1 : 0;
223 ram_high_en = (bank_high & 0x80) ? 1 : 0;
224 ram_wp = (bank_high & 0x40) ? 0 : 1;
225
226 if (!ram_wp && (ram_low_en && ram_high_en)) {
227 cart_ram[addr] = value;
228 }
229 }
230
231 /* read 0xa000-0xbfff */
megacart_blk5_read(uint16_t addr)232 uint8_t megacart_blk5_read(uint16_t addr)
233 {
234 uint8_t bank_low;
235 uint8_t bank_high;
236 int ram_low_en;
237 int ram_high_en;
238
239 /* get bank registers */
240 bank_low = (oe_flop) ? bank_low_reg : 0x7f;
241 bank_high = (oe_flop) ? bank_high_reg : 0x7f;
242
243 /* determine flags from bank registers. */
244 ram_low_en = (bank_low & 0x80) ? 1 : 0;
245 ram_high_en = (bank_high & 0x80) ? 1 : 0;
246
247 if (!ram_high_en) {
248 return cart_rom_high[(addr & 0x1fff) | (bank_high * 0x2000)];
249 } else {
250 if (!ram_low_en) {
251 return cart_rom_low[(addr & 0x1fff) | (bank_low * 0x2000)];
252 }
253 }
254
255 return cart_ram[addr & 0x1fff];
256 }
257
258 /* store 0xa000-0xbfff */
megacart_blk5_store(uint16_t addr,uint8_t value)259 void megacart_blk5_store(uint16_t addr, uint8_t value)
260 {
261 uint8_t bank_low;
262 uint8_t bank_high;
263 int ram_low_en;
264 int ram_high_en;
265 int ram_wp;
266
267 /* get bank registers */
268 bank_low = (oe_flop) ? bank_low_reg : 0x7f;
269 bank_high = (oe_flop) ? bank_high_reg : 0x7f;
270
271 /* determine flags from bank registers. */
272 ram_low_en = (bank_low & 0x80) ? 1 : 0;
273 ram_high_en = (bank_high & 0x80) ? 1 : 0;
274 ram_wp = (bank_high & 0x40) ? 0 : 1;
275
276 if (!ram_wp && (ram_low_en && ram_high_en)) {
277 cart_ram[addr & 0x1fff] = value;
278 }
279 }
280
281 /* read 0x9800-0x9bff (nvram 0x1800 - 0x1bff) */
megacart_io2_read(uint16_t addr)282 static uint8_t megacart_io2_read(uint16_t addr)
283 {
284 uint8_t value;
285
286 if (nvram_en_flop) {
287 megacart_io2_device.io_source_valid = 1;
288 value = cart_nvram[0x1800 + (addr & 0x3ff)];
289 } else {
290 megacart_io2_device.io_source_valid = 0;
291 value = vic20_cpu_last_data;
292 }
293 return value;
294 }
295
296 /* store 0x9800-0x9bff (nvram 0x1800 - 0x1bff) */
megacart_io2_store(uint16_t addr,uint8_t value)297 static void megacart_io2_store(uint16_t addr, uint8_t value)
298 {
299 if (nvram_en_flop) {
300 cart_nvram[0x1800 + (addr & 0x3ff)] = value;
301 }
302 }
303
304 /* read 0x9c00-0x9fff (nvram 0x1c00 - 0x1fff) */
megacart_io3_read(uint16_t addr)305 static uint8_t megacart_io3_read(uint16_t addr)
306 {
307 uint8_t value;
308
309 if (nvram_en_flop) {
310 megacart_io3_device.io_source_valid = 1;
311 value = cart_nvram[0x1c00 + (addr & 0x3ff)];
312 } else {
313 megacart_io3_device.io_source_valid = 0;
314 value = vic20_cpu_last_data;
315 }
316 return value;
317 }
318
megacart_io3_peek(uint16_t addr)319 static uint8_t megacart_io3_peek(uint16_t addr)
320 {
321 if ((addr & 0x180) == 0x080) { /* $9c80 */
322 return bank_high_reg;
323 }
324
325 if ((addr & 0x180) == 0x100) { /* $9d00 */
326 return bank_low_reg;
327 }
328
329 return cart_nvram[0x1c00 + (addr & 0x3ff)];
330 }
331
332 /* store 0x9c00-0x9fff (nvram 0x1c00 - 0x1fff) */
megacart_io3_store(uint16_t addr,uint8_t value)333 static void megacart_io3_store(uint16_t addr, uint8_t value)
334 {
335 if (nvram_en_flop) {
336 cart_nvram[0x1c00 + (addr & 0x3ff)] = value;
337 }
338
339 if ((addr & 0x180) == 0x080) { /* $9c80 */
340 bank_high_reg = value;
341 }
342
343 if ((addr & 0x180) == 0x100) { /* $9d00 */
344 bank_low_reg = value;
345 }
346
347 if ((addr & 0x180) == 0x180) { /* $9d80 */
348 nvram_en_flop = (value & 0x1) ? 0 : 1;
349 bank_high_reg = value;
350 bank_low_reg = value;
351 }
352
353 if ((addr & 0x200) == 0x200) { /* $9e00 */
354 /* perform reset */
355 reset_mode = SOFTWARE_RESET;
356 machine_trigger_reset(MACHINE_RESET_MODE_SOFT);
357 }
358 }
359
360 /* ------------------------------------------------------------------------- */
361
megacart_init(void)362 void megacart_init(void)
363 {
364 if (megacart_log == LOG_ERR) {
365 megacart_log = log_open(CARTRIDGE_VIC20_NAME_MEGACART);
366 }
367
368 reset_mode = BUTTON_RESET;
369 oe_flop = 0;
370 nvram_en_flop = 0;
371 }
372
megacart_reset(void)373 void megacart_reset(void)
374 {
375 if (reset_mode == SOFTWARE_RESET) {
376 oe_flop = !oe_flop;
377 } else {
378 oe_flop = 0;
379 }
380 reset_mode = BUTTON_RESET;
381 }
382
megacart_config_setup(uint8_t * rawcart)383 void megacart_config_setup(uint8_t *rawcart)
384 {
385 }
386
zfile_load(const char * filename,uint8_t * dest,size_t size)387 static int zfile_load(const char *filename, uint8_t *dest, size_t size)
388 {
389 FILE *fd;
390
391 fd = zfile_fopen(filename, MODE_READ);
392 if (!fd) {
393 return -1;
394 }
395 if (util_file_length(fd) != size) {
396 zfile_fclose(fd);
397 return -1;
398 }
399 if (fread(dest, size, 1, fd) < 1) {
400 zfile_fclose(fd);
401 return -1;
402 }
403 zfile_fclose(fd);
404 return 0;
405 }
406
try_nvram_load(const char * filename)407 static int try_nvram_load(const char *filename)
408 {
409 if (cart_nvram && filename && *filename != '\0') {
410 if (zfile_load(filename, cart_nvram, (size_t)CART_NVRAM_SIZE) < 0) {
411 log_message(megacart_log, "Failed to read NvRAM image `%s'!", filename);
412 return -1;
413 } else {
414 log_message(megacart_log, "Read NvRAM image `%s'.", filename);
415 }
416 }
417
418 return 0;
419 }
420
try_nvram_save(const char * filename)421 static int try_nvram_save(const char *filename)
422 {
423 int ret = 0;
424 if (cart_nvram && filename && *filename != '\0') {
425 FILE *fd;
426 fd = fopen(filename, "wb");
427 if (fd) {
428 if (fwrite(cart_nvram, (size_t)CART_NVRAM_SIZE, 1, fd) > 0) {
429 log_message(megacart_log, "Wrote back NvRAM image `%s'.", filename);
430 } else {
431 ret = -1;
432 }
433 fclose(fd);
434 } else {
435 ret = -1;
436 }
437 if (ret == -1) {
438 log_message(megacart_log, "Failed to write back NvRAM image `%s'!", filename);
439 }
440 }
441
442 return ret;
443 }
444
megacart_bin_attach(const char * filename)445 int megacart_bin_attach(const char *filename)
446 {
447 if (!cart_ram) {
448 cart_ram = lib_malloc(CART_RAM_SIZE);
449 }
450 if (!cart_nvram) {
451 cart_nvram = lib_malloc(CART_NVRAM_SIZE);
452 }
453 if (!cart_rom) {
454 cart_rom = lib_malloc(CART_ROM_SIZE);
455 }
456
457 if (zfile_load(filename, cart_rom, (size_t)CART_ROM_SIZE) < 0) {
458 megacart_detach();
459 return -1;
460 }
461
462 if (export_add(&export_res) < 0) {
463 return -1;
464 }
465
466 try_nvram_load(nvram_filename);
467
468 cart_rom_low = cart_rom;
469 cart_rom_high = cart_rom + 0x100000;
470
471 mem_cart_blocks = VIC_CART_RAM123 |
472 VIC_CART_BLK1 | VIC_CART_BLK2 | VIC_CART_BLK3 | VIC_CART_BLK5 |
473 VIC_CART_IO2 | VIC_CART_IO3;
474 mem_initialize_memory();
475
476 megacart_io2_list_item = io_source_register(&megacart_io2_device);
477 megacart_io3_list_item = io_source_register(&megacart_io3_device);
478
479 return 0;
480 }
481
megacart_detach(void)482 void megacart_detach(void)
483 {
484 /* try to write back NvRAM contents if write back is enabled
485 and cartridge is not from a snapshot */
486 if (nvram_writeback && !cartridge_is_from_snapshot) {
487 try_nvram_save(nvram_filename);
488 }
489
490 mem_cart_blocks = 0;
491 mem_initialize_memory();
492 lib_free(cart_ram);
493 lib_free(cart_nvram);
494 lib_free(cart_rom);
495 cart_ram = NULL;
496 cart_nvram = NULL;
497 cart_rom = NULL;
498
499 export_remove(&export_res);
500
501 if (megacart_io2_list_item != NULL) {
502 io_source_unregister(megacart_io2_list_item);
503 megacart_io2_list_item = NULL;
504 }
505
506 if (megacart_io3_list_item != NULL) {
507 io_source_unregister(megacart_io3_list_item);
508 megacart_io3_list_item = NULL;
509 }
510 }
511
512 /* ------------------------------------------------------------------------- */
513
set_nvram_filename(const char * name,void * param)514 static int set_nvram_filename(const char *name, void *param)
515 {
516 if (nvram_filename && name && strcmp(name, nvram_filename) == 0) {
517 return 0;
518 }
519
520 /* try to write back NvRAM contents to the old file if write back is enabled
521 and NvRAM wasn't from a snapshot */
522 if (nvram_writeback && !cartridge_is_from_snapshot) {
523 try_nvram_save(nvram_filename);
524 }
525
526 util_string_set(&nvram_filename, name);
527
528 try_nvram_load(nvram_filename);
529 return 0;
530 }
531
532 static const resource_string_t resources_string[] = {
533 { "MegaCartNvRAMfilename", "", RES_EVENT_NO, NULL,
534 &nvram_filename, set_nvram_filename, NULL },
535 RESOURCE_STRING_LIST_END
536 };
537
set_nvram_writeback(int val,void * param)538 static int set_nvram_writeback(int val, void *param)
539 {
540 nvram_writeback = val ? 1 : 0;
541
542 return 0;
543 }
544
545 static const resource_int_t resources_int[] = {
546 { "MegaCartNvRAMWriteBack", 0, RES_EVENT_STRICT, (resource_value_t)0,
547 &nvram_writeback, set_nvram_writeback, NULL },
548 RESOURCE_INT_LIST_END
549 };
550
megacart_resources_init(void)551 int megacart_resources_init(void)
552 {
553 if (resources_register_string(resources_string) < 0) {
554 return -1;
555 }
556
557 return resources_register_int(resources_int);
558 }
559
megacart_resources_shutdown(void)560 void megacart_resources_shutdown(void)
561 {
562 lib_free(nvram_filename);
563 nvram_filename = NULL;
564 }
565
566 static const cmdline_option_t cmdline_options[] =
567 {
568 { "-mcnvramfile", SET_RESOURCE, CMDLINE_ATTRIB_NEED_ARGS,
569 NULL, NULL, "MegaCartNvRAMfilename", NULL,
570 "<Name>", "Set Mega-Cart NvRAM filename" },
571 { "-mcnvramwriteback", SET_RESOURCE, CMDLINE_ATTRIB_NONE,
572 NULL, NULL, "MegaCartNvRAMWriteBack", (resource_value_t)1,
573 NULL, "Enable Mega-Cart NvRAM writeback" },
574 { "+mcnvramwriteback", SET_RESOURCE, CMDLINE_ATTRIB_NONE,
575 NULL, NULL, "MegaCartNvRAMWriteBack", (resource_value_t)0,
576 NULL, "Disable Mega-Cart NvRAM writeback" },
577 CMDLINE_LIST_END
578 };
579
megacart_cmdline_options_init(void)580 int megacart_cmdline_options_init(void)
581 {
582 return cmdline_register_options(cmdline_options);
583 }
584
585 /* ------------------------------------------------------------------------- */
586
587 #define VIC20CART_DUMP_VER_MAJOR 2
588 #define VIC20CART_DUMP_VER_MINOR 0
589 #define SNAP_MODULE_NAME "MEGACART"
590
megacart_snapshot_write_module(snapshot_t * s)591 int megacart_snapshot_write_module(snapshot_t *s)
592 {
593 snapshot_module_t *m;
594
595 m = snapshot_module_create(s, SNAP_MODULE_NAME, VIC20CART_DUMP_VER_MAJOR, VIC20CART_DUMP_VER_MINOR);
596 if (m == NULL) {
597 return -1;
598 }
599
600 if (0
601 || (SMW_B(m, bank_low_reg) < 0)
602 || (SMW_B(m, bank_high_reg) < 0)
603 || (SMW_B(m, (uint8_t)oe_flop) < 0)
604 || (SMW_B(m, (uint8_t)nvram_en_flop) < 0)
605 || (SMW_BA(m, cart_ram, CART_RAM_SIZE) < 0)
606 || (SMW_BA(m, cart_rom, CART_ROM_SIZE) < 0)
607 || (SMW_BA(m, cart_nvram, CART_NVRAM_SIZE) < 0)) {
608 snapshot_module_close(m);
609 return -1;
610 }
611
612 snapshot_module_close(m);
613 return 0;
614 }
615
megacart_snapshot_read_module(snapshot_t * s)616 int megacart_snapshot_read_module(snapshot_t *s)
617 {
618 uint8_t vmajor, vminor;
619 snapshot_module_t *m;
620
621 m = snapshot_module_open(s, SNAP_MODULE_NAME, &vmajor, &vminor);
622 if (m == NULL) {
623 return -1;
624 }
625
626 if (vmajor != VIC20CART_DUMP_VER_MAJOR) {
627 snapshot_module_close(m);
628 return -1;
629 }
630
631 if (!cart_ram) {
632 cart_ram = lib_malloc(CART_RAM_SIZE);
633 }
634 if (!cart_nvram) {
635 cart_nvram = lib_malloc(CART_NVRAM_SIZE);
636 }
637 if (!cart_rom) {
638 cart_rom = lib_malloc(CART_ROM_SIZE);
639 }
640
641 if (0
642 || (SMR_B(m, &bank_low_reg) < 0)
643 || (SMR_B(m, &bank_high_reg) < 0)
644 || (SMR_B_INT(m, &oe_flop) < 0)
645 || (SMR_B_INT(m, &nvram_en_flop) < 0)
646 || (SMR_BA(m, cart_ram, CART_RAM_SIZE) < 0)
647 || (SMR_BA(m, cart_rom, CART_ROM_SIZE) < 0)
648 || (SMR_BA(m, cart_nvram, CART_NVRAM_SIZE) < 0)) {
649 snapshot_module_close(m);
650 lib_free(cart_ram);
651 lib_free(cart_nvram);
652 lib_free(cart_rom);
653 cart_ram = NULL;
654 cart_nvram = NULL;
655 cart_rom = NULL;
656 return -1;
657 }
658
659 snapshot_module_close(m);
660
661 cart_rom_low = cart_rom;
662 cart_rom_high = cart_rom + 0x100000;
663
664 reset_mode = BUTTON_RESET;
665
666 mem_cart_blocks = VIC_CART_RAM123 |
667 VIC_CART_BLK1 | VIC_CART_BLK2 | VIC_CART_BLK3 | VIC_CART_BLK5 |
668 VIC_CART_IO2 | VIC_CART_IO3;
669 mem_initialize_memory();
670
671 return 0;
672 }
673
674 /* ------------------------------------------------------------------------- */
675
megacart_mon_dump(void)676 static int megacart_mon_dump(void)
677 {
678 uint8_t bank_low;
679 uint8_t bank_high;
680 int ram_low_en;
681 int ram_high_en;
682 int ram_wp;
683
684 /* get bank registers */
685 bank_low = (oe_flop) ? bank_low_reg : 0x7f;
686 bank_high = (oe_flop) ? bank_high_reg : 0x7f;
687
688 /* determine flags from bank registers. */
689 ram_low_en = (bank_low & 0x80) ? 1 : 0;
690 ram_high_en = (bank_high & 0x80) ? 1 : 0;
691 ram_wp = (bank_high & 0x40) ? 0 : 1;
692
693 mon_out("Registers: Bank low $%02x, high $%02x\n", bank_low_reg, bank_high_reg);
694 mon_out("NvRAM flop: %i, OE flop: %i\n", nvram_en_flop, oe_flop);
695 mon_out("RAM123: %s\n", nvram_en_flop ? "NvRAM" : "off");
696
697 mon_out("BLKn: ");
698 if (!ram_low_en) {
699 mon_out("ROM bank $%02x (offset $%06x)\n",
700 bank_low, bank_low * 0x2000U);
701 } else {
702 if (ram_high_en) {
703 mon_out("RAM %s\n", ram_wp ? "(write protected)" : "");
704 } else {
705 mon_out("off\n");
706 }
707 }
708
709 mon_out("BLK5: ");
710 if (!ram_high_en) {
711 mon_out("ROM bank $%02x (offset $%06x)\n", bank_high, bank_high * 0x2000U + 0x100000U);
712 } else {
713 if (!ram_low_en) {
714 mon_out("ROM bank $%02x (offset $%06x)\n", bank_low, bank_low * 0x2000U);
715 } else {
716 mon_out("RAM %s\n", ram_wp ? "(write protected)" : "");
717 }
718 }
719
720 return 0;
721 }
722