1 /*
2 * c64dtvmem.c -- C64DTV memory handling.
3 *
4 * Written by
5 * M.Kiesel <mayne@users.sourceforge.net>
6 * Hannu Nuotio <hannu.nuotio@tut.fi>
7 * Daniel Kahlin <daniel@kahlin.net>
8 * Based on code by
9 * Andreas Boose <viceteam@t-online.de>
10 * Ettore Perazzoli <ettore@comm2000.it>
11 * Marco van den Heuvel <blackystardust68@yahoo.com>
12 *
13 * This file is part of VICE, the Versatile Commodore Emulator.
14 * See README for copyright notice.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
29 * 02111-1307 USA.
30 *
31 */
32
33 #include "vice.h"
34
35 #include "c64dtvmem.h"
36 #include "c64dtvblitter.h"
37 #include "c64dtvcpu.h"
38 #include "c64dtvdma.h"
39 #include "c64dtvflash.h"
40 #include "cia.h"
41 #include "cmdline.h"
42 #include "debugcart.h"
43 #include "lib.h"
44 #include "log.h"
45 #include "util.h"
46 #include "resources.h"
47 #include "mos6510dtv.h"
48 #include "interrupt.h"
49 #include "alarm.h"
50 #include "hummeradc.h"
51 #include "ps2mouse.h"
52
53 /* TODO this is a hack */
54 #define C64_RAM_SIZE 0x200000
55
56 #ifndef C64DTV
57 #define C64DTV
58 #endif
59
60 /* start of c64dtvmem_main.c */
61
62 #include "vice.h"
63
64 #include <stdio.h>
65 #include <stdlib.h>
66 #include <string.h>
67
68 #include "c64.h"
69 #include "c64-resources.h"
70 #include "c64cia.h"
71 #include "c64mem.h"
72 #include "c64dtvmeminit.h"
73 #include "c64memrom.h"
74 #include "c64pla.h"
75 #include "machine.h"
76 #include "maincpu.h"
77 #include "mem.h"
78 #include "monitor.h"
79 #include "ram.h"
80 #include "sid.h"
81 #include "vicii-mem.h"
82 #include "vicii-phi1.h"
83 #include "vicii.h"
84 #include "viciitypes.h"
85
86 /* #define DBGMEM */
87
88 #ifdef DBGMEM
89 #define DBG(x) log_message(c64dtvmem_log, x);
90 #else
91 #define DBG(x)
92 #endif
93
94 /* C64 memory-related resources. */
95
96 /* ------------------------------------------------------------------------- */
97
98 /* Number of possible memory configurations. */
99 #define NUM_CONFIGS 8
100 /* Number of possible video banks (16K each). */
101 #define NUM_VBANKS 4
102
103 /* The C64 memory, see ../mem.h. */
104 uint8_t mem_ram[C64_RAM_SIZE];
105
106 #ifdef USE_EMBEDDED
107 #include "c64chargen.h"
108 #else
109 uint8_t mem_chargen_rom[C64_CHARGEN_ROM_SIZE];
110 #endif
111
112 /* Internal color memory. */
113 uint8_t *mem_color_ram_cpu;
114 uint8_t *mem_color_ram_vicii; /* unused; needed by vicii-fetch.c */
115
116 /* Pointer to the chargen ROM. */
117 uint8_t *mem_chargen_rom_ptr;
118
119 /* Pointers to the currently used memory read and write tables. */
120 read_func_ptr_t *_mem_read_tab_ptr;
121 store_func_ptr_t *_mem_write_tab_ptr;
122 static uint8_t **_mem_read_base_tab_ptr;
123 static uint32_t *mem_read_limit_tab_ptr;
124
125 /* Memory read and write tables. */
126 static store_func_ptr_t mem_write_tab[NUM_VBANKS][NUM_CONFIGS][0x101];
127 static read_func_ptr_t mem_read_tab[NUM_CONFIGS][0x101];
128 static uint8_t *mem_read_base_tab[NUM_CONFIGS][0x101];
129 static uint32_t mem_read_limit_tab[NUM_CONFIGS][0x101];
130
131 static store_func_ptr_t mem_write_tab_watch[0x101];
132 static read_func_ptr_t mem_read_tab_watch[0x101];
133
134 /* Current video bank (0, 1, 2 or 3). */
135 static int vbank;
136
137 /* Current memory configuration. */
138 static int mem_config;
139
140 /* Current watchpoint state. 1 = watchpoints active, 0 = no watchpoints */
141 static int watchpoints_active;
142
143 /* ------------------------------------------------------------------------- */
144
zero_read_watch(uint16_t addr)145 static uint8_t zero_read_watch(uint16_t addr)
146 {
147 addr &= 0xff;
148 monitor_watch_push_load_addr(addr, e_comp_space);
149 return mem_read_tab[mem_config][0](addr);
150 }
151
zero_store_watch(uint16_t addr,uint8_t value)152 static void zero_store_watch(uint16_t addr, uint8_t value)
153 {
154 addr &= 0xff;
155 monitor_watch_push_store_addr(addr, e_comp_space);
156 mem_write_tab[vbank][mem_config][0](addr, value);
157 }
158
read_watch(uint16_t addr)159 static uint8_t read_watch(uint16_t addr)
160 {
161 monitor_watch_push_load_addr(addr, e_comp_space);
162 return mem_read_tab[mem_config][addr >> 8](addr);
163 }
164
store_watch(uint16_t addr,uint8_t value)165 static void store_watch(uint16_t addr, uint8_t value)
166 {
167 monitor_watch_push_store_addr(addr, e_comp_space);
168 mem_write_tab[vbank][mem_config][addr >> 8](addr, value);
169 }
170
mem_toggle_watchpoints(int flag,void * context)171 void mem_toggle_watchpoints(int flag, void *context)
172 {
173 if (flag) {
174 _mem_read_tab_ptr = mem_read_tab_watch;
175 _mem_write_tab_ptr = mem_write_tab_watch;
176 } else {
177 _mem_read_tab_ptr = mem_read_tab[mem_config];
178 _mem_write_tab_ptr = mem_write_tab[vbank][mem_config];
179 }
180 watchpoints_active = flag;
181 }
182
183 /* ------------------------------------------------------------------------- */
184
mem_pla_config_changed(void)185 void mem_pla_config_changed(void)
186 {
187 mem_config = (((~pport.dir | pport.data) & 0x7));
188
189 c64pla_config_changed(0, 0, 0, 1, 0x17);
190
191 if (watchpoints_active) {
192 _mem_read_tab_ptr = mem_read_tab_watch;
193 _mem_write_tab_ptr = mem_write_tab_watch;
194 } else {
195 _mem_read_tab_ptr = mem_read_tab[mem_config];
196 _mem_write_tab_ptr = mem_write_tab[vbank][mem_config];
197 }
198
199 _mem_read_base_tab_ptr = mem_read_base_tab[mem_config];
200 mem_read_limit_tab_ptr = mem_read_limit_tab[mem_config];
201
202 maincpu_resync_limits();
203 }
204
zero_read(uint16_t addr)205 uint8_t zero_read(uint16_t addr)
206 {
207 addr &= 0xff;
208
209 switch ((uint8_t)addr) {
210 case 0:
211 return pport.dir_read;
212 case 1:
213 return pport.data_read;
214 }
215
216 return mem_ram[addr & 0xff];
217 }
218
zero_store(uint16_t addr,uint8_t value)219 void zero_store(uint16_t addr, uint8_t value)
220 {
221 addr &= 0xff;
222
223 switch ((uint8_t)addr) {
224 case 0:
225 if (vbank == 0) {
226 vicii_mem_vbank_store((uint16_t)0, vicii_read_phi1_lowlevel());
227 } else {
228 mem_ram[0] = vicii_read_phi1_lowlevel();
229 machine_handle_pending_alarms(maincpu_rmw_flag + 1);
230 }
231 if (pport.dir != value) {
232 pport.dir = value;
233 mem_pla_config_changed();
234 }
235 break;
236 case 1:
237 if (vbank == 0) {
238 vicii_mem_vbank_store((uint16_t)1, vicii_read_phi1_lowlevel());
239 } else {
240 mem_ram[1] = vicii_read_phi1_lowlevel();
241 machine_handle_pending_alarms(maincpu_rmw_flag + 1);
242 }
243 if (pport.data != value) {
244 pport.data = value;
245 mem_pla_config_changed();
246 }
247 break;
248 default:
249 if (vbank == 0) {
250 vicii_mem_vbank_store(addr, value);
251 } else {
252 mem_ram[addr] = value;
253 }
254 }
255 }
256
257 /* ------------------------------------------------------------------------- */
258
chargen_read(uint16_t addr)259 uint8_t chargen_read(uint16_t addr)
260 {
261 return c64dtvflash_read(addr);
262 }
263
264 /*void chargen_store(uint16_t addr, uint8_t value)
265 {
266 return;
267 }*/
268
ram_read(uint16_t addr)269 uint8_t ram_read(uint16_t addr)
270 {
271 return mem_ram[addr];
272 }
273
ram_store(uint16_t addr,uint8_t value)274 void ram_store(uint16_t addr, uint8_t value)
275 {
276 mem_ram[addr] = value;
277 }
278
ram_hi_store(uint16_t addr,uint8_t value)279 void ram_hi_store(uint16_t addr, uint8_t value)
280 {
281 if (vbank == 3) {
282 vicii_mem_vbank_3fxx_store(addr, value);
283 } else {
284 mem_ram[addr] = value;
285 }
286 }
287
288 /* ------------------------------------------------------------------------- */
289
mem_set_write_hook(int config,int page,store_func_t * f)290 void mem_set_write_hook(int config, int page, store_func_t *f)
291 {
292 int i;
293
294 for (i = 0; i < NUM_VBANKS; i++) {
295 mem_write_tab[i][config][page] = f;
296 }
297 }
298
mem_read_tab_set(unsigned int base,unsigned int index,read_func_ptr_t read_func)299 void mem_read_tab_set(unsigned int base, unsigned int index,
300 read_func_ptr_t read_func)
301 {
302 mem_read_tab[base][index] = read_func;
303 }
304
mem_read_base_set(unsigned int base,unsigned int index,uint8_t * mem_ptr)305 void mem_read_base_set(unsigned int base, unsigned int index, uint8_t *mem_ptr)
306 {
307 mem_read_base_tab[base][index] = mem_ptr;
308 }
309
mem_initialize_memory(void)310 void mem_initialize_memory(void)
311 {
312 int i, j, k;
313
314 mem_chargen_rom_ptr = &c64dtvflash_mem[0x1000]; /* FIXME: 1000 or 9000 based on vicii bank */
315 mem_color_ram_cpu = &mem_ram[0x01d800];
316 mem_color_ram_vicii = NULL;
317
318 /* setup watchpoint tables */
319 mem_read_tab_watch[0] = zero_read_watch;
320 mem_write_tab_watch[0] = zero_store_watch;
321 for (i = 1; i <= 0x100; i++) {
322 mem_read_tab_watch[i] = read_watch;
323 mem_write_tab_watch[i] = store_watch;
324 }
325
326 /* Default is RAM. */
327 for (i = 0; i < NUM_CONFIGS; i++) {
328 mem_set_write_hook(i, 0, zero_store);
329 mem_read_tab[i][0] = zero_read;
330 mem_read_base_tab[i][0] = mem_ram;
331 for (j = 1; j <= 0xfe; j++) {
332 mem_read_tab[i][j] = ram_read;
333 mem_read_base_tab[i][j] = mem_ram + (j << 8);
334 for (k = 0; k < NUM_VBANKS; k++) {
335 if ((j & 0xc0) == (k << 6)) {
336 switch (j & 0x3f) {
337 case 0x39:
338 mem_write_tab[k][i][j] = vicii_mem_vbank_39xx_store;
339 break;
340 case 0x3f:
341 mem_write_tab[k][i][j] = vicii_mem_vbank_3fxx_store;
342 break;
343 default:
344 mem_write_tab[k][i][j] = vicii_mem_vbank_store;
345 }
346 } else {
347 mem_write_tab[k][i][j] = ram_store;
348 }
349 }
350 }
351 mem_read_tab[i][0xff] = ram_read;
352 mem_read_base_tab[i][0xff] = mem_ram + 0xff00;
353
354 /* vbank access is handled within `ram_hi_store()'. */
355 mem_set_write_hook(i, 0xff, ram_hi_store);
356 }
357
358 /* Setup character generator ROM at $D000-$DFFF (memory configs 1, 2,
359 3). */
360 for (i = 0xd0; i <= 0xdf; i++) {
361 mem_read_tab[1][i] = chargen_read;
362 mem_read_tab[2][i] = chargen_read;
363 mem_read_tab[3][i] = chargen_read;
364 mem_read_base_tab[1][i] = NULL;
365 mem_read_base_tab[2][i] = NULL;
366 mem_read_base_tab[3][i] = NULL;
367 }
368
369 c64dtvmeminit(0);
370 c64dtvmem_limit_init(mem_read_limit_tab);
371
372 for (i = 0; i < NUM_CONFIGS; i++) {
373 mem_read_tab[i][0x100] = mem_read_tab[i][0];
374 for (j = 0; j < NUM_VBANKS; j++) {
375 mem_write_tab[j][i][0x100] = mem_write_tab[j][i][0];
376 }
377 mem_read_base_tab[i][0x100] = mem_read_base_tab[i][0];
378 }
379
380 _mem_read_tab_ptr = mem_read_tab[7];
381 _mem_write_tab_ptr = mem_write_tab[vbank][7];
382 _mem_read_base_tab_ptr = mem_read_base_tab[7];
383 mem_read_limit_tab_ptr = mem_read_limit_tab[7];
384
385 vicii_set_chargen_addr_options(0x7000, 0x1000);
386
387 c64pla_pport_reset();
388
389 /* Setup initial memory configuration. */
390 mem_pla_config_changed();
391 c64dtvmem_init_config();
392 }
393
mem_mmu_translate(unsigned int addr,uint8_t ** base,int * start,int * limit)394 void mem_mmu_translate(unsigned int addr, uint8_t **base, int *start, int *limit)
395 {
396 #ifdef FEATURE_CPUMEMHISTORY
397 *base = NULL;
398 *start = addr;
399 *limit = 0;
400 #else
401 int bank = addr >> 14;
402 int paddr;
403 uint8_t *p;
404 uint32_t limits;
405
406 if ((((dtv_registers[8] >> (bank * 2)) & 0x03) == 0x00)) {
407 if (c64dtvflash_state) {
408 *base = NULL; /* not idle */
409 *limit = 0;
410 *start = 0;
411 return;
412 }
413 paddr = (((int)dtv_registers[12 + bank]) << 14) & (C64_RAM_SIZE - 1);
414 *base = &c64dtvflash_mem[paddr] - (addr & 0xc000);
415 *limit = (addr & 0xc000) | 0x3ffd;
416 *start = addr & 0xc000;
417 return;
418 }
419 paddr = (((int)dtv_registers[12 + bank]) << 14) & (C64_RAM_SIZE - 1);
420 if (paddr < 0x10000) {
421 paddr |= addr & 0x3fff;
422 p = _mem_read_base_tab_ptr[paddr >> 8];
423 if (p) { /* easy */
424 if (addr > 1) {
425 *base = p - (addr & 0xff00);
426 limits = mem_read_limit_tab_ptr[paddr >> 8];
427 *limit = (limits & 0xffff) - paddr + addr;
428 *start = (limits >> 16) - paddr + addr;
429 } else {
430 *base = NULL;
431 *limit = 0;
432 *start = 0;
433 }
434 return;
435 } else {
436 if (!c64dtvflash_state) {
437 read_func_ptr_t ptr = _mem_read_tab_ptr[paddr >> 8];
438 if (ptr == c64memrom_kernal64_read) {
439 int mapping = c64dtvmem_memmapper[0];
440 paddr = ((mapping & 0x1f) << 16) + (paddr & ~0x3fff) - (addr & 0xc000);
441 *base = ((mapping & 0xc0) ? mem_ram : c64dtvflash_mem) + paddr;
442 *limit = (addr & 0xe000) | 0x1ffd;
443 *start = addr & 0xe000;
444 return;
445 }
446 if (ptr == c64memrom_basic64_read) {
447 int mapping = c64dtvmem_memmapper[1];
448 paddr = ((mapping & 0x1f) << 16) + (paddr & ~0x3fff) - (addr & 0xc000);
449 *base = ((mapping & 0xc0) ? mem_ram : c64dtvflash_mem) + paddr;
450 *limit = (addr & 0xe000) | 0x1ffd;
451 *start = addr & 0xe000;
452 return;
453 }
454 if (ptr == chargen_read) { /* not likely but anyway */
455 *base = c64dtvflash_mem + (paddr & ~0x3fff) - (addr & 0xc000);
456 *limit = (addr & 0xf000) | 0x0ffd;
457 *start = addr & 0xf000;
458 return;
459 }
460 }
461 *base = NULL;
462 *limit = 0;
463 *start = 0;
464 }
465 } else {
466 *base = &mem_ram[paddr] - (addr & 0xc000);
467 *limit = (addr & 0xc000) | 0x3ffd;
468 *start = addr & 0xc000;
469 }
470 #endif
471 }
472
473 /* ------------------------------------------------------------------------- */
474
475 /* Initialize RAM for power-up. */
mem_powerup(void)476 void mem_powerup(void)
477 {
478 ram_init(mem_ram, C64_RAM_SIZE);
479 }
480
481 /* ------------------------------------------------------------------------- */
482
483 /* Change the current video bank. Call this routine only when the vbank
484 has really changed. */
mem_set_vbank(int new_vbank)485 void mem_set_vbank(int new_vbank)
486 {
487 vbank = new_vbank;
488 _mem_write_tab_ptr = mem_write_tab[new_vbank][mem_config];
489 vicii_set_vbank(new_vbank);
490 }
491
492 /* ------------------------------------------------------------------------- */
493
494 /* FIXME: this part needs to be checked. */
495
mem_get_basic_text(uint16_t * start,uint16_t * end)496 void mem_get_basic_text(uint16_t *start, uint16_t *end)
497 {
498 if (start != NULL) {
499 *start = mem_ram[0x2b] | (mem_ram[0x2c] << 8);
500 }
501 if (end != NULL) {
502 *end = mem_ram[0x2d] | (mem_ram[0x2e] << 8);
503 }
504 }
505
mem_set_basic_text(uint16_t start,uint16_t end)506 void mem_set_basic_text(uint16_t start, uint16_t end)
507 {
508 mem_ram[0x2b] = mem_ram[0xac] = start & 0xff;
509 mem_ram[0x2c] = mem_ram[0xad] = start >> 8;
510 mem_ram[0x2d] = mem_ram[0x2f] = mem_ram[0x31] = mem_ram[0xae] = end & 0xff;
511 mem_ram[0x2e] = mem_ram[0x30] = mem_ram[0x32] = mem_ram[0xaf] = end >> 8;
512 }
513
mem_inject(uint32_t addr,uint8_t value)514 void mem_inject(uint32_t addr, uint8_t value)
515 {
516 mem_ram[addr & 0x1fffff] = value;
517 }
518
519 /* ------------------------------------------------------------------------- */
520
mem_rom_trap_allowed(uint16_t addr)521 int mem_rom_trap_allowed(uint16_t addr)
522 {
523 if (addr >= 0xe000) {
524 switch (mem_config) {
525 case 2:
526 case 3:
527 case 6:
528 case 7:
529 return 1;
530 default:
531 return 0;
532 }
533 }
534
535 return 0;
536 }
537
538 /* ------------------------------------------------------------------------- */
539
540 /* Banked memory access functions for the monitor. */
541
542 /* FIXME: peek, cartridge support */
543
store_bank_io(uint16_t addr,uint8_t byte)544 void store_bank_io(uint16_t addr, uint8_t byte)
545 {
546 switch (addr & 0xff00) {
547 case 0xd000:
548 case 0xd100:
549 case 0xd200:
550 case 0xd300:
551 vicii_store(addr, byte);
552 break;
553 case 0xd400:
554 case 0xd500:
555 case 0xd600:
556 case 0xd700:
557 sid_store(addr, byte);
558 debugcart_store(addr, byte);
559 break;
560 case 0xd800:
561 case 0xd900:
562 case 0xda00:
563 case 0xdb00:
564 colorram_store(addr, byte);
565 break;
566 case 0xdc00:
567 cia1_store(addr, byte);
568 break;
569 case 0xdd00:
570 cia2_store(addr, byte);
571 break;
572 case 0xde00:
573 c64io1_store(addr, byte);
574 break;
575 case 0xdf00:
576 c64io2_store(addr, byte);
577 break;
578 }
579 return;
580 }
581
read_bank_io(uint16_t addr)582 uint8_t read_bank_io(uint16_t addr)
583 {
584 switch (addr & 0xff00) {
585 case 0xd000:
586 case 0xd100:
587 case 0xd200:
588 case 0xd300:
589 return vicii_read(addr);
590 case 0xd400:
591 case 0xd500:
592 case 0xd600:
593 case 0xd700:
594 return sid_read(addr);
595 case 0xd800:
596 case 0xd900:
597 case 0xda00:
598 case 0xdb00:
599 return colorram_read(addr);
600 case 0xdc00:
601 return cia1_read(addr);
602 case 0xdd00:
603 return cia2_read(addr);
604 case 0xde00:
605 return c64io1_read(addr);
606 case 0xdf00:
607 return c64io2_read(addr);
608 }
609 return 0xff;
610 }
611
peek_bank_io(uint16_t addr)612 static uint8_t peek_bank_io(uint16_t addr)
613 {
614 switch (addr & 0xff00) {
615 case 0xd000:
616 case 0xd100:
617 case 0xd200:
618 case 0xd300:
619 return vicii_peek(addr);
620 case 0xd400:
621 case 0xd500:
622 case 0xd600:
623 case 0xd700:
624 return sid_read(addr);
625 case 0xd800:
626 case 0xd900:
627 case 0xda00:
628 case 0xdb00:
629 return colorram_read(addr);
630 case 0xdc00:
631 return cia1_peek(addr);
632 case 0xdd00:
633 return cia2_peek(addr);
634 case 0xde00:
635 return c64io1_read(addr); /* FIXME */
636 case 0xdf00:
637 return c64io2_read(addr); /* FIXME */
638 }
639 return 0xff;
640 }
641
642 /* ------------------------------------------------------------------------- */
643
644 /* Exported banked memory access functions for the monitor. */
645
mem_dump_io(void * context,uint16_t addr)646 static int mem_dump_io(void *context, uint16_t addr)
647 {
648 if ((addr >= 0xd000) && (addr <= 0xd04f)) {
649 return vicii_dump();
650 } else if ((addr >= 0xd400) && (addr <= 0xd41f)) {
651 /* return sidcore_dump(machine_context.sid); */ /* FIXME */
652 } else if ((addr >= 0xdc00) && (addr <= 0xdc3f)) {
653 return ciacore_dump(machine_context.cia1);
654 } else if ((addr >= 0xdd00) && (addr <= 0xdd3f)) {
655 return ciacore_dump(machine_context.cia2);
656 }
657 return -1;
658 }
659
mem_ioreg_list_get(void * context)660 mem_ioreg_list_t *mem_ioreg_list_get(void *context)
661 {
662 mem_ioreg_list_t *mem_ioreg_list = NULL;
663
664 mon_ioreg_add_list(&mem_ioreg_list, "VIC-II", 0xd000, 0xd04f, mem_dump_io, NULL);
665 /* TODO blitter, DMA... */
666 mon_ioreg_add_list(&mem_ioreg_list, "SID", 0xd400, 0xd41f, mem_dump_io, NULL);
667 mon_ioreg_add_list(&mem_ioreg_list, "CIA1", 0xdc00, 0xdc0f, mem_dump_io, NULL);
668 mon_ioreg_add_list(&mem_ioreg_list, "CIA2", 0xdd00, 0xdd0f, mem_dump_io, NULL);
669
670 return mem_ioreg_list;
671 }
672
mem_get_screen_parameter(uint16_t * base,uint8_t * rows,uint8_t * columns,int * bank)673 void mem_get_screen_parameter(uint16_t *base, uint8_t *rows, uint8_t *columns, int *bank)
674 {
675 *base = ((vicii_peek(0xd018) & 0xf0) << 6)
676 | ((~cia2_peek(0xdd00) & 0x03) << 14);
677 *rows = 25;
678 *columns = 40;
679 *bank = 0;
680 }
681
682 /* end of c64dtvmem_main.c */
683
684 static log_t c64dtvmem_log = LOG_ERR;
685
686 /* I/O of the memory mapper ($D100/$D101) */
687 uint8_t c64dtvmem_memmapper[0x2];
688
689 /* The memory banking mechanism/virtual memory is visible to the CPU only. */
690 /* VICII, DMA Engine, Blitter have access to physical memory. */
691 /* Kernal/Basic ROM is visible in physical memory only since DTV address */
692 /* translation is done before determining access type (C64 MMU). */
693 /* Note that zeropage/stack mapping (reg10/11) is done before this - */
694 /* see c64dtvcpu. */
695
addr_to_paddr(uint16_t addr)696 static inline int addr_to_paddr(uint16_t addr)
697 {
698 int bank = addr >> 14;
699 /* DTV register 12-15 - Remap 16k memory banks */
700 return ((((int) dtv_registers[12 + bank]) << 14) + (addr & 0x3fff)) & (C64_RAM_SIZE - 1);
701 }
702
access_rom(uint16_t addr)703 static inline int access_rom(uint16_t addr)
704 {
705 int bank = addr >> 14;
706 return(((dtv_registers[8] >> (bank * 2)) & 0x03) == 0x00);
707 /* TODO 00 is ROM, 01 is RAM, what about 10 and 11? */
708 }
709
710 /* ------------------------------------------------------------------------- */
711 /* Replacements for c64mem.c code */
712
mem_store(uint16_t addr,uint8_t value)713 void mem_store(uint16_t addr, uint8_t value)
714 {
715 #ifdef FEATURE_CPUMEMHISTORY
716 store_func_ptr_t rptr;
717 #endif
718
719 int paddr = addr_to_paddr(addr);
720 /* if (addr != paddr) printf("Store to adress %x mapped to %x - %d %d %d %d\n", addr, paddr, dtv_registers[12], dtv_registers[13], dtv_registers[14], dtv_registers[15]); */ /* DEBUG */
721 if (access_rom(addr)) {
722 #ifdef FEATURE_CPUMEMHISTORY
723 monitor_memmap_store(paddr, MEMMAP_ROM_W);
724 #endif
725 c64dtvflash_store(paddr, value);
726 return;
727 }
728 if (paddr <= 0xffff) {
729 #ifdef FEATURE_CPUMEMHISTORY
730 rptr = _mem_write_tab_ptr[paddr >> 8];
731 if ((rptr == ram_store)
732 || (rptr == ram_hi_store)
733 || (rptr == vicii_mem_vbank_store)
734 || (rptr == zero_store)) {
735 monitor_memmap_store(paddr, MEMMAP_RAM_W);
736 } else {
737 monitor_memmap_store(paddr, MEMMAP_I_O_W);
738 }
739 #endif
740 /* disable dummy write if skip cycle */
741 if (dtv_registers[9] & 1) {
742 maincpu_rmw_flag = 0;
743 }
744 _mem_write_tab_ptr[paddr >> 8]((uint16_t)paddr, value);
745 } else {
746 #ifdef FEATURE_CPUMEMHISTORY
747 monitor_memmap_store(paddr, MEMMAP_RAM_W);
748 #endif
749 mem_ram[paddr] = value;
750 }
751 }
752
mem_read(uint16_t addr)753 uint8_t mem_read(uint16_t addr)
754 {
755 #ifdef FEATURE_CPUMEMHISTORY
756 read_func_ptr_t rptr;
757 #endif
758
759 int paddr = addr_to_paddr(addr);
760 /* if (addr != paddr) printf("Read from adress %x mapped to %x - %d %d %d %d\n", addr, paddr, dtv_registers[12], dtv_registers[13], dtv_registers[14], dtv_registers[15]); */ /* DEBUG */
761 if (access_rom(addr)) {
762 #ifdef FEATURE_CPUMEMHISTORY
763 monitor_memmap_store(paddr, (memmap_state & MEMMAP_STATE_OPCODE) ? MEMMAP_ROM_X : (memmap_state & MEMMAP_STATE_INSTR) ? 0 : MEMMAP_ROM_R);
764 memmap_state &= ~(MEMMAP_STATE_OPCODE);
765 #endif
766 return c64dtvflash_read(paddr);
767 }
768 if (paddr <= 0xffff) {
769 #ifdef FEATURE_CPUMEMHISTORY
770 rptr = _mem_read_tab_ptr[paddr >> 8];
771 if ((rptr == ram_read)
772 || (rptr == zero_read)) {
773 monitor_memmap_store(paddr, (memmap_state & MEMMAP_STATE_OPCODE) ? MEMMAP_RAM_X : (memmap_state & MEMMAP_STATE_INSTR) ? 0 : MEMMAP_RAM_R);
774 } else if ((rptr == c64memrom_basic64_read)
775 || (rptr == c64memrom_kernal64_read)) {
776 monitor_memmap_store(paddr, (memmap_state & MEMMAP_STATE_OPCODE) ? MEMMAP_ROM_X : (memmap_state & MEMMAP_STATE_INSTR) ? 0 : MEMMAP_ROM_R);
777 } else {
778 monitor_memmap_store(paddr, MEMMAP_I_O_R);
779 }
780 memmap_state &= ~(MEMMAP_STATE_OPCODE);
781 #endif
782 return _mem_read_tab_ptr[paddr >> 8]((uint16_t)paddr);
783 } else {
784 #ifdef FEATURE_CPUMEMHISTORY
785 monitor_memmap_store(paddr, (memmap_state & MEMMAP_STATE_OPCODE) ? MEMMAP_RAM_X : (memmap_state & MEMMAP_STATE_INSTR) ? 0 : MEMMAP_RAM_R);
786 memmap_state &= ~(MEMMAP_STATE_OPCODE);
787 #endif
788 return mem_ram[paddr];
789 }
790 }
791
colorram_store(uint16_t addr,uint8_t value)792 void colorram_store(uint16_t addr, uint8_t value)
793 {
794 mem_color_ram_cpu[addr & 0x3ff] = value;
795 }
796
colorram_read(uint16_t addr)797 uint8_t colorram_read(uint16_t addr)
798 {
799 return mem_color_ram_cpu[addr & 0x3ff];
800 }
801
802
803 /* ------------------------------------------------------------------------- */
804
c64dtv_init(void)805 void c64dtv_init(void)
806 {
807 int trapfl;
808 if (c64dtvmem_log == LOG_ERR) {
809 c64dtvmem_log = log_open("C64DTVMEM");
810 }
811
812 hummeradc_init();
813 c64dtvblitter_init();
814 c64dtvdma_init();
815 c64dtvflash_init();
816 DBG("installing floppy traps");
817 /* TODO disable copying by command line parameter */
818 /* Make sure serial code traps are in place. */
819 resources_get_int("VirtualDevices", &trapfl);
820 resources_set_int("VirtualDevices", 0);
821 resources_set_int("VirtualDevices", trapfl);
822 /* TODO chargen ROM support */
823
824 DBG("END init");
825 }
826
827 /* init C64DTV memory table changes */
c64dtvmem_init_config(void)828 void c64dtvmem_init_config(void)
829 {
830 int i, j, k;
831
832 /* install DMA engine handlers */
833 DBG("install mem_read/mem_write handlers");
834 for (i = 0; i < NUM_CONFIGS; i++)
835 {
836 for (j = 1; j <= 0xff; j++)
837 {
838 for (k = 0; k < NUM_VBANKS; k++)
839 {
840 if (mem_write_tab[k][i][j] == vicii_store && j == 0xd3) {
841 mem_write_tab[k][i][j] = c64dtv_dmablit_store;
842 }
843 if (mem_write_tab[k][i][j] == vicii_store && j == 0xd1) {
844 mem_write_tab[k][i][j] = c64dtv_mapper_store;
845 }
846 if (mem_write_tab[k][i][j] == vicii_store && j == 0xd2) {
847 mem_write_tab[k][i][j] = c64dtv_palette_store;
848 }
849 }
850 if (mem_read_tab[i][j] == vicii_read && j == 0xd3) {
851 mem_read_tab[i][j] = c64dtv_dmablit_read;
852 }
853 if (mem_read_tab[i][j] == vicii_read && j == 0xd1) {
854 mem_read_tab[i][j] = c64dtv_mapper_read;
855 }
856 if (mem_read_tab[i][j] == vicii_read && j == 0xd2) {
857 mem_read_tab[i][j] = c64dtv_palette_read;
858 }
859 }
860 }
861 DBG("END init_config");
862 }
863
864
c64dtvmem_shutdown(void)865 void c64dtvmem_shutdown(void)
866 {
867 int trapfl;
868
869 hummeradc_shutdown();
870 c64dtvblitter_shutdown();
871 c64dtvdma_shutdown();
872 /* work around for non transparent kernal traps.
873 Disable serial traps when shutting down c64dtvflash, which
874 saves the contents if enabled */
875 resources_get_int("VirtualDevices", &trapfl);
876 resources_set_int("VirtualDevices", 0);
877 c64dtvflash_shutdown();
878 resources_set_int("VirtualDevices", trapfl);
879
880 DBG("END shutdown");
881 }
882
c64dtvmem_reset(void)883 void c64dtvmem_reset(void)
884 {
885 int trapfl;
886 DBG("reset");
887
888 /* Disable serial traps when resetting mem mapper */
889 resources_get_int("VirtualDevices", &trapfl);
890 resources_set_int("VirtualDevices", 0);
891 c64dtvmem_memmapper[0x00] = 0; /* KERNAL ROM segment (0x10000 byte segments) */
892 c64dtvmem_memmapper[0x01] = 0; /* BASIC ROM segment (0x10000 byte segments) */
893 resources_set_int("VirtualDevices", trapfl);
894
895 /* TODO move register file initialization somewhere else? */
896 dtv_registers[8] = 0x55; /* RAM/ROM access mode */
897 dtv_registers[9] = 0; /* skip cycle and burst mode */
898 dtv_registers[10] = 0; /* zero page (0x100 byte segments) */
899 dtv_registers[11] = 1; /* stack page (0x100 byte segments) */
900 dtv_registers[12] = 0; /* bank 0 (0x4000 byte segments) */
901 dtv_registers[13] = 1; /* bank 1 */
902 dtv_registers[14] = 2; /* bank 2 */
903 dtv_registers[15] = 3; /* bank 3 */
904 ps2mouse_reset();
905 hummeradc_reset();
906 c64dtvblitter_reset();
907 c64dtvdma_reset();
908 c64dtvflash_reset();
909 }
910
911 /* ------------------------------------------------------------------------- */
912
913 /* These are the $D100/$D101 memory mapper register handlers */
914
c64dtv_mapper_read(uint16_t addr)915 uint8_t c64dtv_mapper_read(uint16_t addr)
916 {
917 if (!vicii_extended_regs()) {
918 return vicii_read(addr);
919 }
920
921 return mem_ram[addr];
922 }
923
c64dtv_mapper_store(uint16_t addr,uint8_t value)924 void c64dtv_mapper_store(uint16_t addr, uint8_t value)
925 {
926 int trapfl;
927 if (!vicii_extended_regs()) {
928 vicii_store(addr, value);
929 return;
930 }
931
932 /* always write through to $d100 (this is a hardware bug) */
933 mem_ram[addr] = value;
934
935 /* handle aliasing */
936 addr &= 0x0f;
937
938 /* DBG("Wrote %d to %x", value, addr); */
939
940 switch (addr) {
941 case 0x00:
942 /* Deinstall serial traps, change KERNAL segment, reinstall traps */
943 resources_get_int("VirtualDevices", &trapfl);
944 resources_set_int("VirtualDevices", 0);
945 c64dtvmem_memmapper[0] = value;
946 maincpu_resync_limits();
947 resources_set_int("VirtualDevices", trapfl);
948 if (trapfl) {
949 log_message(c64dtvmem_log, "Changed KERNAL segment - disable VirtualDevices if you encounter problems");
950 }
951 break;
952 case 0x01:
953 c64dtvmem_memmapper[1] = value;
954 maincpu_resync_limits();
955 break;
956 default:
957 break;
958 }
959 }
960
961
c64io1_read(uint16_t addr)962 uint8_t c64io1_read(uint16_t addr)
963 {
964 return 0x00;
965 }
966
c64io1_store(uint16_t addr,uint8_t value)967 void c64io1_store(uint16_t addr, uint8_t value)
968 {
969 }
970
c64io2_read(uint16_t addr)971 uint8_t c64io2_read(uint16_t addr)
972 {
973 return 0x00;
974 }
975
c64io2_store(uint16_t addr,uint8_t value)976 void c64io2_store(uint16_t addr, uint8_t value)
977 {
978 }
979
980 /* ------------------------------------------------------------------------- */
981
982 /* These are the $D200 palette register handlers */
983
c64dtv_palette_read(uint16_t addr)984 uint8_t c64dtv_palette_read(uint16_t addr)
985 {
986 if (!vicii_extended_regs()) {
987 return vicii_read(addr);
988 }
989
990 return vicii_palette_read(addr);
991 }
992
c64dtv_palette_store(uint16_t addr,uint8_t value)993 void c64dtv_palette_store(uint16_t addr, uint8_t value)
994 {
995 if (!vicii_extended_regs()) {
996 vicii_store(addr, value);
997 return;
998 }
999
1000 vicii_palette_store(addr, value);
1001 return;
1002 }
1003
1004
1005 /* ------------------------------------------------------------------------- */
1006
1007 /* These are the $D300 DMA and blitter register handlers */
1008
c64dtv_dmablit_read(uint16_t addr)1009 uint8_t c64dtv_dmablit_read(uint16_t addr)
1010 {
1011 if (!vicii_extended_regs()) {
1012 return vicii_read(addr);
1013 }
1014
1015 addr &= 0x3f;
1016
1017 if (addr & 0x20) {
1018 return c64dtv_blitter_read((uint16_t)(addr & 0x1f));
1019 } else {
1020 return c64dtv_dma_read(addr);
1021 }
1022 }
1023
c64dtv_dmablit_store(uint16_t addr,uint8_t value)1024 void c64dtv_dmablit_store(uint16_t addr, uint8_t value)
1025 {
1026 if (!vicii_extended_regs()) {
1027 vicii_store(addr, value);
1028 return;
1029 }
1030
1031 addr &= 0x3f;
1032
1033 if (addr & 0x20) {
1034 c64dtv_blitter_store((uint16_t)(addr & 0x1f), value);
1035 } else {
1036 c64dtv_dma_store(addr, value);
1037 }
1038 }
1039
1040
1041
1042 /* ------------------------------------------------------------------------- */
1043
1044 /* Exported banked memory access functions for the monitor. */
1045
1046 static const char *banknames[] =
1047 {
1048 "default", "cpu", "ram", "rom", "io", "cart",
1049 "ram00", "ram01", "ram02", "ram03", "ram04", "ram05", "ram06", "ram07",
1050 "ram08", "ram09", "ram0a", "ram0b", "ram0c", "ram0d", "ram0e", "ram0f",
1051 "ram10", "ram11", "ram12", "ram13", "ram14", "ram15", "ram16", "ram17",
1052 "ram18", "ram19", "ram1a", "ram1b", "ram1c", "ram1d", "ram1e", "ram1f",
1053 "rom00", "rom01", "rom02", "rom03", "rom04", "rom05", "rom06", "rom07",
1054 "rom08", "rom09", "rom0a", "rom0b", "rom0c", "rom0d", "rom0e", "rom0f",
1055 "rom10", "rom11", "rom12", "rom13", "rom14", "rom15", "rom16", "rom17",
1056 "rom18", "rom19", "rom1a", "rom1b", "rom1c", "rom1d", "rom1e", "rom1f",
1057 NULL
1058 };
1059
1060 static const int banknums[] =
1061 {
1062 1, 0, 1, 2, 3, 4,
1063 5, 6, 7, 8, 9, 10, 11, 12,
1064 13, 14, 15, 16, 17, 18, 19, 20,
1065 21, 22, 23, 24, 25, 26, 27, 28,
1066 29, 30, 31, 32, 33, 34, 35, 36,
1067 37, 38, 39, 40, 41, 42, 43, 44,
1068 45, 46, 47, 48, 49, 50, 51, 52,
1069 53, 54, 55, 56, 57, 58, 59, 60,
1070 61, 62, 63, 64, 65, 66, 67, 68
1071 };
1072
mem_bank_list(void)1073 const char **mem_bank_list(void)
1074 {
1075 return banknames;
1076 }
1077
mem_bank_from_name(const char * name)1078 int mem_bank_from_name(const char *name)
1079 {
1080 int i = 0;
1081
1082 while (banknames[i]) {
1083 if (!strcmp(name, banknames[i])) {
1084 return banknums[i];
1085 }
1086 i++;
1087 }
1088 return -1;
1089 }
1090
mem_bank_read(int bank,uint16_t addr,void * context)1091 uint8_t mem_bank_read(int bank, uint16_t addr, void *context)
1092 {
1093 int paddr;
1094
1095 if ((bank >= 5) && (bank <= 36)) {
1096 return mem_ram[((bank - 5) << 16) + addr]; /* ram00..1f */
1097 }
1098 if ((bank >= 37) && (bank <= 68)) {
1099 return c64dtvflash_mem[((bank - 37) << 16) + addr]; /* rom00..1f */
1100 }
1101
1102 /* TODO: is restoring r8, r10..15 needed? */
1103 dtv_registers[8] = MOS6510DTV_REGS_GET_R8(&maincpu_regs);
1104 dtv_registers[10] = MOS6510DTV_REGS_GET_R10(&maincpu_regs);
1105 dtv_registers[11] = MOS6510DTV_REGS_GET_R11(&maincpu_regs);
1106 dtv_registers[12] = MOS6510DTV_REGS_GET_R12(&maincpu_regs);
1107 dtv_registers[13] = MOS6510DTV_REGS_GET_R13(&maincpu_regs);
1108 dtv_registers[14] = MOS6510DTV_REGS_GET_R14(&maincpu_regs);
1109 dtv_registers[15] = MOS6510DTV_REGS_GET_R15(&maincpu_regs);
1110
1111 paddr = addr_to_paddr(addr);
1112 switch (bank) {
1113 case 0: /* current */
1114 return mem_read(addr);
1115 case 3: /* io */
1116 if (paddr >= 0xd000 && paddr < 0xe000) {
1117 return read_bank_io((uint16_t)paddr);
1118 }
1119 case 4: /* cart */
1120 break;
1121 case 2: /* rom */
1122 if (paddr >= 0xa000 && paddr <= 0xbfff) {
1123 return c64memrom_basic64_read((uint16_t)paddr);
1124 }
1125 if (paddr >= 0xd000 && paddr <= 0xdfff) {
1126 return chargen_read((uint16_t)paddr);
1127 }
1128 if (paddr >= 0xe000) {
1129 return c64memrom_kernal64_read((uint16_t)paddr);
1130 }
1131 case 1: /* ram */
1132 break; /* yes, this could be flash as well */
1133 }
1134 return access_rom(addr) ? c64dtvflash_read(paddr) : mem_ram[paddr];
1135 }
1136
1137
mem_bank_peek(int bank,uint16_t addr,void * context)1138 uint8_t mem_bank_peek(int bank, uint16_t addr, void *context)
1139 {
1140 int paddr;
1141 if (bank >= 5) {
1142 return mem_bank_read(bank, addr, context);
1143 }
1144
1145 /* TODO: is restoring r8, r10..15 needed? */
1146 dtv_registers[8] = MOS6510DTV_REGS_GET_R8(&maincpu_regs);
1147 dtv_registers[10] = MOS6510DTV_REGS_GET_R10(&maincpu_regs);
1148 dtv_registers[11] = MOS6510DTV_REGS_GET_R11(&maincpu_regs);
1149 dtv_registers[12] = MOS6510DTV_REGS_GET_R12(&maincpu_regs);
1150 dtv_registers[13] = MOS6510DTV_REGS_GET_R13(&maincpu_regs);
1151 dtv_registers[14] = MOS6510DTV_REGS_GET_R14(&maincpu_regs);
1152 dtv_registers[15] = MOS6510DTV_REGS_GET_R15(&maincpu_regs);
1153
1154 paddr = addr_to_paddr(addr);
1155 switch (bank) {
1156 case 0: /* current */
1157 if (access_rom(addr)) {
1158 return c64dtvflash_mem[paddr];
1159 }
1160 if (paddr <= 0xffff) {
1161 if (c64dtvmeminit_io_config[mem_config]) {
1162 if ((paddr >= 0xd000) && (paddr < 0xe000)) {
1163 return peek_bank_io((uint16_t)paddr);
1164 }
1165 }
1166 if (_mem_read_tab_ptr[paddr >> 8] == c64memrom_basic64_read) {
1167 int mapping = c64dtvmem_memmapper[1];
1168 paddr |= (mapping & 0x1f) << 16;
1169 return (mapping & 0xc0) ? mem_ram[paddr] : c64dtvflash_mem[paddr];
1170 }
1171 if (_mem_read_tab_ptr[paddr >> 8] == chargen_read) {
1172 return c64dtvflash_mem[paddr];
1173 }
1174 if (_mem_read_tab_ptr[paddr >> 8] == c64memrom_kernal64_read) {
1175 int mapping = c64dtvmem_memmapper[0];
1176 paddr |= (mapping & 0x1f) << 16;
1177 return (mapping & 0xc0) ? mem_ram[paddr] : c64dtvflash_mem[paddr];
1178 } /* no side effects on the rest */
1179 return _mem_read_tab_ptr[paddr >> 8]((uint16_t)paddr);
1180 }
1181 return mem_ram[paddr];
1182 case 3: /* io */
1183 if (paddr >= 0xd000 && paddr < 0xe000) {
1184 return peek_bank_io((uint16_t)paddr);
1185 }
1186 case 4: /* cart */
1187 break;
1188 case 2: /* rom */
1189 if (paddr >= 0xa000 && paddr <= 0xbfff) {
1190 int mapping = c64dtvmem_memmapper[1];
1191 paddr += ((mapping & 0x1f) << 16);
1192 return ((mapping >> 6) == 0) ? c64dtvflash_mem[paddr] : mem_ram[paddr];
1193 }
1194 if (paddr >= 0xd000 && paddr <= 0xdfff) {
1195 return c64dtvflash_mem[paddr];
1196 }
1197 if (paddr >= 0xe000) {
1198 int mapping = c64dtvmem_memmapper[0];
1199 paddr += ((mapping & 0x1f) << 16);
1200 return ((mapping >> 6) == 0) ? c64dtvflash_mem[paddr] : mem_ram[paddr];
1201 }
1202 case 1: /* ram */
1203 break; /* yes, this could be flash as well */
1204 }
1205 return access_rom(addr) ? c64dtvflash_mem[paddr] : mem_ram[paddr];
1206 }
1207
mem_bank_write(int bank,uint16_t addr,uint8_t byte,void * context)1208 void mem_bank_write(int bank, uint16_t addr, uint8_t byte, void *context)
1209 {
1210 int paddr;
1211
1212 if ((bank >= 5) && (bank <= 36)) { /* ram00..1f */
1213 mem_ram[((bank - 5) << 16) + addr] = byte;
1214 return;
1215 }
1216
1217 if ((bank >= 37) && (bank <= 68)) {
1218 c64dtvflash_mem[((bank - 37) << 16) + addr] = byte; /* rom00..1f */
1219 return;
1220 }
1221
1222 /* TODO: is restoring r8, r10..15 needed? */
1223 dtv_registers[8] = MOS6510DTV_REGS_GET_R8(&maincpu_regs);
1224 dtv_registers[10] = MOS6510DTV_REGS_GET_R10(&maincpu_regs);
1225 dtv_registers[11] = MOS6510DTV_REGS_GET_R11(&maincpu_regs);
1226 dtv_registers[12] = MOS6510DTV_REGS_GET_R12(&maincpu_regs);
1227 dtv_registers[13] = MOS6510DTV_REGS_GET_R13(&maincpu_regs);
1228 dtv_registers[14] = MOS6510DTV_REGS_GET_R14(&maincpu_regs);
1229 dtv_registers[15] = MOS6510DTV_REGS_GET_R15(&maincpu_regs);
1230
1231 paddr = addr_to_paddr(addr);
1232 switch (bank) {
1233 case 0: /* current */
1234 mem_store(addr, byte);
1235 return;
1236 case 3: /* io */
1237 if (paddr >= 0xd000 && paddr < 0xe000) {
1238 store_bank_io((uint16_t)paddr, byte);
1239 return;
1240 }
1241 case 4: /* cart */
1242 break;
1243 case 2: /* rom */
1244 if (paddr >= 0xa000 && paddr <= 0xbfff) {
1245 return;
1246 }
1247 if (paddr >= 0xd000 && paddr <= 0xdfff) {
1248 return;
1249 }
1250 if (paddr >= 0xe000) {
1251 return;
1252 }
1253 case 1: /* ram */
1254 break; /* yes, this could be flash as well */
1255 }
1256 if (access_rom(addr)) {
1257 c64dtvflash_mem[paddr] = byte;
1258 } else {
1259 mem_ram[paddr] = byte;
1260 }
1261 }
1262
1263 /* ------------------------------------------------------------------------- */
1264
c64dtvmem_resources_init(void)1265 int c64dtvmem_resources_init(void)
1266 {
1267 return c64dtvblitter_resources_init() < 0 ||
1268 c64dtvdma_resources_init() < 0 ||
1269 c64dtvflash_resources_init() < 0;
1270 }
1271
c64dtvmem_resources_shutdown(void)1272 void c64dtvmem_resources_shutdown(void)
1273 {
1274 c64dtvblitter_resources_shutdown();
1275 c64dtvdma_resources_shutdown();
1276 c64dtvflash_resources_shutdown();
1277 }
1278
1279
c64dtvmem_cmdline_options_init(void)1280 int c64dtvmem_cmdline_options_init(void)
1281 {
1282 return c64dtvblitter_cmdline_options_init() < 0 ||
1283 c64dtvdma_cmdline_options_init() < 0 ||
1284 c64dtvflash_cmdline_options_init() < 0;
1285 }
1286