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