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