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