1 /*
2 * c64mem.c -- C64 memory handling.
3 *
4 * Written by
5 * Andreas Boose <viceteam@t-online.de>
6 * Ettore Perazzoli <ettore@comm2000.it>
7 * Marco van den Heuvel <blackystardust68@yahoo.com>
8 *
9 * This file is part of VICE, the Versatile Commodore Emulator.
10 * See README for copyright notice.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25 * 02111-1307 USA.
26 *
27 */
28
29 #include "vice.h"
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include "alarm.h"
36 #include "c64.h"
37 #include "c64-resources.h"
38 #include "c64_256k.h"
39 #include "c64cart.h"
40 #include "c64cia.h"
41 #include "c64mem.h"
42 #include "c64meminit.h"
43 #include "c64memlimit.h"
44 #include "c64memrom.h"
45 #include "c64pla.h"
46 #include "c64ui.h"
47 #include "c64cartmem.h"
48 #include "cartio.h"
49 #include "cartridge.h"
50 #include "cia.h"
51 #include "clkguard.h"
52 #include "machine.h"
53 #include "maincpu.h"
54 #include "mem.h"
55 #include "monitor.h"
56 #include "plus256k.h"
57 #include "plus60k.h"
58 #include "ram.h"
59 #include "resources.h"
60 #include "reu.h"
61 #include "sid.h"
62 #include "tpi.h"
63 #include "vicii-mem.h"
64 #include "vicii-phi1.h"
65 #include "vicii.h"
66
67 /* Machine class (moved from c64.c to distinguish between x64 and x64sc) */
68 int machine_class = VICE_MACHINE_C64;
69
70 /* C64 memory-related resources. */
71
72 /* ------------------------------------------------------------------------- */
73
74 /* Number of possible memory configurations. */
75 #define NUM_CONFIGS 32
76
77 /* Number of possible video banks (16K each). */
78 #define NUM_VBANKS 4
79
80 /* The C64 memory. */
81 uint8_t mem_ram[C64_RAM_SIZE];
82
83 #ifdef USE_EMBEDDED
84 #include "c64chargen.h"
85 #else
86 uint8_t mem_chargen_rom[C64_CHARGEN_ROM_SIZE];
87 #endif
88
89 /* Internal color memory. */
90 static uint8_t mem_color_ram[0x400];
91 uint8_t *mem_color_ram_cpu, *mem_color_ram_vicii;
92
93 /* Pointer to the chargen ROM. */
94 uint8_t *mem_chargen_rom_ptr;
95
96 /* Pointers to the currently used memory read and write tables. */
97 read_func_ptr_t *_mem_read_tab_ptr;
98 store_func_ptr_t *_mem_write_tab_ptr;
99 static uint8_t **_mem_read_base_tab_ptr;
100 static uint32_t *mem_read_limit_tab_ptr;
101
102 /* Memory read and write tables. */
103 static store_func_ptr_t mem_write_tab[NUM_VBANKS][NUM_CONFIGS][0x101];
104 static read_func_ptr_t mem_read_tab[NUM_CONFIGS][0x101];
105 static uint8_t *mem_read_base_tab[NUM_CONFIGS][0x101];
106 static uint32_t mem_read_limit_tab[NUM_CONFIGS][0x101];
107
108 static store_func_ptr_t mem_write_tab_watch[0x101];
109 static read_func_ptr_t mem_read_tab_watch[0x101];
110
111 /* Current video bank (0, 1, 2 or 3). */
112 static int vbank;
113
114 /* Current memory configuration. */
115 static int mem_config;
116
117 /* Tape sense status: 1 = some button pressed, 0 = no buttons pressed. */
118 static int tape_sense = 0;
119
120 static int tape_write_in = 0;
121 static int tape_motor_in = 0;
122
123 /* Current watchpoint state. 1 = watchpoints active, 0 = no watchpoints */
124 static int watchpoints_active;
125
126 /* ------------------------------------------------------------------------- */
127
zero_read_watch(uint16_t addr)128 static uint8_t zero_read_watch(uint16_t addr)
129 {
130 addr &= 0xff;
131 monitor_watch_push_load_addr(addr, e_comp_space);
132 return mem_read_tab[mem_config][0](addr);
133 }
134
zero_store_watch(uint16_t addr,uint8_t value)135 static void zero_store_watch(uint16_t addr, uint8_t value)
136 {
137 addr &= 0xff;
138 monitor_watch_push_store_addr(addr, e_comp_space);
139 mem_write_tab[vbank][mem_config][0](addr, value);
140 }
141
read_watch(uint16_t addr)142 static uint8_t read_watch(uint16_t addr)
143 {
144 monitor_watch_push_load_addr(addr, e_comp_space);
145 return mem_read_tab[mem_config][addr >> 8](addr);
146 }
147
store_watch(uint16_t addr,uint8_t value)148 static void store_watch(uint16_t addr, uint8_t value)
149 {
150 monitor_watch_push_store_addr(addr, e_comp_space);
151 mem_write_tab[vbank][mem_config][addr >> 8](addr, value);
152 }
153
mem_toggle_watchpoints(int flag,void * context)154 void mem_toggle_watchpoints(int flag, void *context)
155 {
156 if (flag) {
157 _mem_read_tab_ptr = mem_read_tab_watch;
158 _mem_write_tab_ptr = mem_write_tab_watch;
159 } else {
160 _mem_read_tab_ptr = mem_read_tab[mem_config];
161 _mem_write_tab_ptr = mem_write_tab[vbank][mem_config];
162 }
163 watchpoints_active = flag;
164 }
165
166 /* ------------------------------------------------------------------------- */
167
168 /* $00/$01 unused bits emulation
169
170 - There are 2 different unused bits, 1) the output bits, 2) the input bits
171 - The output bits can be (re)set when the data-direction is set to output
172 for those bits and the output bits will not drop-off to 0.
173 - When the data-direction for the unused bits is set to output then the
174 unused input bits can be (re)set by writing to them, when set to 1 the
175 drop-off timer will start which will cause the unused input bits to drop
176 down to 0 in a certain amount of time.
177 - When an unused input bit already had the drop-off timer running, and is
178 set to 1 again, the drop-off timer will restart.
179 - when a an unused bit changes from output to input, and the current output
180 bit is 1, the drop-off timer will restart again
181
182 see testprogs/CPU/cpuport for details and tests
183 */
184
clk_overflow_callback(CLOCK sub,void * unused_data)185 static void clk_overflow_callback(CLOCK sub, void *unused_data)
186 {
187 if (pport.data_set_clk_bit6 > (CLOCK)0) {
188 pport.data_set_clk_bit6 -= sub;
189 }
190 if (pport.data_falloff_bit6 && (pport.data_set_clk_bit6 < maincpu_clk)) {
191 pport.data_falloff_bit6 = 0;
192 pport.data_set_bit6 = 0;
193 }
194 if (pport.data_set_clk_bit7 > (CLOCK)0) {
195 pport.data_set_clk_bit7 -= sub;
196 }
197 if (pport.data_falloff_bit7 && (pport.data_set_clk_bit7 < maincpu_clk)) {
198 pport.data_falloff_bit7 = 0;
199 pport.data_set_bit7 = 0;
200 }
201 }
202
c64_mem_init(void)203 void c64_mem_init(void)
204 {
205 clk_guard_add_callback(maincpu_clk_guard, clk_overflow_callback, NULL);
206 }
207
mem_pla_config_changed(void)208 void mem_pla_config_changed(void)
209 {
210 mem_config = (((~pport.dir | pport.data) & 0x7) | (export.exrom << 3) | (export.game << 4));
211
212 c64pla_config_changed(tape_sense, tape_write_in, tape_motor_in, 1, 0x17);
213
214 if (watchpoints_active) {
215 _mem_read_tab_ptr = mem_read_tab_watch;
216 _mem_write_tab_ptr = mem_write_tab_watch;
217 } else {
218 _mem_read_tab_ptr = mem_read_tab[mem_config];
219 _mem_write_tab_ptr = mem_write_tab[vbank][mem_config];
220 }
221
222 _mem_read_base_tab_ptr = mem_read_base_tab[mem_config];
223 mem_read_limit_tab_ptr = mem_read_limit_tab[mem_config];
224
225 maincpu_resync_limits();
226 }
227
zero_read(uint16_t addr)228 uint8_t zero_read(uint16_t addr)
229 {
230 uint8_t retval;
231
232 addr &= 0xff;
233 #ifdef FEATURE_CPUMEMHISTORY
234 if (!(memmap_state & MEMMAP_STATE_IGNORE)) {
235 monitor_memmap_store(addr, (memmap_state & MEMMAP_STATE_OPCODE) ? MEMMAP_RAM_X : (memmap_state & MEMMAP_STATE_INSTR) ? 0 : MEMMAP_RAM_R);
236 memmap_state &= ~(MEMMAP_STATE_OPCODE);
237 }
238 #endif
239 switch ((uint8_t)addr) {
240 case 0:
241 return pport.dir_read;
242 case 1:
243 retval = pport.data_read;
244
245 /* discharge the "capacitor" */
246
247 /* set real value of read bit 6 */
248 if (pport.data_falloff_bit6 && (pport.data_set_clk_bit6 < maincpu_clk)) {
249 pport.data_falloff_bit6 = 0;
250 pport.data_set_bit6 = 0;
251 }
252
253 /* set real value of read bit 7 */
254 if (pport.data_falloff_bit7 && (pport.data_set_clk_bit7 < maincpu_clk)) {
255 pport.data_falloff_bit7 = 0;
256 pport.data_set_bit7 = 0;
257 }
258
259 /* for unused bits in input mode, the value comes from the "capacitor" */
260
261 /* set real value of bit 6 */
262 if (!(pport.dir_read & 0x40)) {
263 retval &= ~0x40;
264 retval |= pport.data_set_bit6;
265 }
266
267 /* set real value of bit 7 */
268 if (!(pport.dir_read & 0x80)) {
269 retval &= ~0x80;
270 retval |= pport.data_set_bit7;
271 }
272
273 return retval;
274 }
275
276 if (c64_256k_enabled) {
277 return c64_256k_ram_segment0_read(addr);
278 } else {
279 if (plus256k_enabled) {
280 return plus256k_ram_low_read(addr);
281 } else {
282 return mem_ram[addr & 0xff];
283 }
284 }
285 }
286
zero_store(uint16_t addr,uint8_t value)287 void zero_store(uint16_t addr, uint8_t value)
288 {
289 addr &= 0xff;
290 #ifdef FEATURE_CPUMEMHISTORY
291 monitor_memmap_store(addr, MEMMAP_RAM_W);
292 #endif
293 switch ((uint8_t)addr) {
294 case 0:
295 if (vbank == 0) {
296 if (c64_256k_enabled) {
297 c64_256k_ram_segment0_store((uint16_t)0, vicii_read_phi1_lowlevel());
298 } else {
299 if (plus256k_enabled) {
300 plus256k_ram_low_store((uint16_t)0, vicii_read_phi1_lowlevel());
301 } else {
302 vicii_mem_vbank_store((uint16_t)0, vicii_read_phi1_lowlevel());
303 }
304 }
305 } else {
306 mem_ram[0] = vicii_read_phi1_lowlevel();
307 machine_handle_pending_alarms(maincpu_rmw_flag + 1);
308 }
309 /* when switching an unused bit from output (where it contained a
310 stable value) to input mode (where the input is floating), some
311 of the charge is transferred to the floating input */
312
313 /* check if bit 6 has flipped */
314 if ((pport.dir & 0x40)) {
315 if ((pport.dir ^ value) & 0x40) {
316 pport.data_set_clk_bit6 = maincpu_clk + C64_CPU6510_DATA_PORT_FALL_OFF_CYCLES;
317 pport.data_set_bit6 = pport.data & 0x40;
318 pport.data_falloff_bit6 = 1;
319 }
320 }
321
322 /* check if bit 7 has flipped */
323 if ((pport.dir & 0x80)) {
324 if ((pport.dir ^ value) & 0x80) {
325 pport.data_set_clk_bit7 = maincpu_clk + C64_CPU6510_DATA_PORT_FALL_OFF_CYCLES;
326 pport.data_set_bit7 = pport.data & 0x80;
327 pport.data_falloff_bit7 = 1;
328 }
329 }
330
331 if (pport.dir != value) {
332 pport.dir = value;
333 mem_pla_config_changed();
334 }
335 break;
336 case 1:
337 if (vbank == 0) {
338 if (c64_256k_enabled) {
339 c64_256k_ram_segment0_store((uint16_t)1, vicii_read_phi1_lowlevel());
340 } else {
341 if (plus256k_enabled) {
342 plus256k_ram_low_store((uint16_t)1, vicii_read_phi1_lowlevel());
343 } else {
344 vicii_mem_vbank_store((uint16_t)1, vicii_read_phi1_lowlevel());
345 }
346 }
347 } else {
348 mem_ram[1] = vicii_read_phi1_lowlevel();
349 machine_handle_pending_alarms(maincpu_rmw_flag + 1);
350 }
351
352 /* when writing to an unused bit that is output, charge the "capacitor",
353 otherwise don't touch it */
354 if (pport.dir & 0x80) {
355 pport.data_set_bit7 = value & 0x80;
356 pport.data_set_clk_bit7 = maincpu_clk + C64_CPU6510_DATA_PORT_FALL_OFF_CYCLES;
357 pport.data_falloff_bit7 = 1;
358 }
359
360 if (pport.dir & 0x40) {
361 pport.data_set_bit6 = value & 0x40;
362 pport.data_set_clk_bit6 = maincpu_clk + C64_CPU6510_DATA_PORT_FALL_OFF_CYCLES;
363 pport.data_falloff_bit6 = 1;
364 }
365
366 if (pport.data != value) {
367 pport.data = value;
368 mem_pla_config_changed();
369 }
370 break;
371 default:
372 if (vbank == 0) {
373 if (c64_256k_enabled) {
374 c64_256k_ram_segment0_store(addr, value);
375 } else {
376 if (plus256k_enabled) {
377 plus256k_ram_low_store(addr, value);
378 } else {
379 vicii_mem_vbank_store(addr, value);
380 }
381 }
382 } else {
383 mem_ram[addr] = value;
384 }
385 }
386 }
387
388 /* ------------------------------------------------------------------------- */
389
chargen_read(uint16_t addr)390 uint8_t chargen_read(uint16_t addr)
391 {
392 return mem_chargen_rom[addr & 0xfff];
393 }
394
chargen_store(uint16_t addr,uint8_t value)395 void chargen_store(uint16_t addr, uint8_t value)
396 {
397 mem_chargen_rom[addr & 0xfff] = value;
398 }
399
ram_read(uint16_t addr)400 uint8_t ram_read(uint16_t addr)
401 {
402 return mem_ram[addr];
403 }
404
ram_store(uint16_t addr,uint8_t value)405 void ram_store(uint16_t addr, uint8_t value)
406 {
407 mem_ram[addr] = value;
408 }
409
ram_hi_store(uint16_t addr,uint8_t value)410 void ram_hi_store(uint16_t addr, uint8_t value)
411 {
412 if (vbank == 3) {
413 vicii_mem_vbank_3fxx_store(addr, value);
414 } else {
415 mem_ram[addr] = value;
416 }
417
418 if (addr == 0xff00) {
419 reu_dma(-1);
420 }
421 }
422
423 /* unconnected memory space */
void_read(uint16_t addr)424 static uint8_t void_read(uint16_t addr)
425 {
426 return vicii_read_phi1();
427 }
428
void_store(uint16_t addr,uint8_t value)429 static void void_store(uint16_t addr, uint8_t value)
430 {
431 return;
432 }
433
434 /* ------------------------------------------------------------------------- */
435
436 /* Generic memory access. */
437
mem_store(uint16_t addr,uint8_t value)438 void mem_store(uint16_t addr, uint8_t value)
439 {
440 _mem_write_tab_ptr[addr >> 8](addr, value);
441 }
442
mem_read(uint16_t addr)443 uint8_t mem_read(uint16_t addr)
444 {
445 return _mem_read_tab_ptr[addr >> 8](addr);
446 }
447
mem_store_without_ultimax(uint16_t addr,uint8_t value)448 void mem_store_without_ultimax(uint16_t addr, uint8_t value)
449 {
450 store_func_ptr_t *write_tab_ptr;
451
452 write_tab_ptr = mem_write_tab[vbank][mem_config & 7];
453
454 write_tab_ptr[addr >> 8](addr, value);
455 }
456
mem_read_without_ultimax(uint16_t addr)457 uint8_t mem_read_without_ultimax(uint16_t addr)
458 {
459 read_func_ptr_t *read_tab_ptr;
460
461 read_tab_ptr = mem_read_tab[mem_config & 7];
462
463 return read_tab_ptr[addr >> 8](addr);
464 }
465
mem_store_without_romlh(uint16_t addr,uint8_t value)466 void mem_store_without_romlh(uint16_t addr, uint8_t value)
467 {
468 store_func_ptr_t *write_tab_ptr;
469
470 write_tab_ptr = mem_write_tab[vbank][0];
471
472 write_tab_ptr[addr >> 8](addr, value);
473 }
474
475 /* ------------------------------------------------------------------------- */
476
colorram_store(uint16_t addr,uint8_t value)477 void colorram_store(uint16_t addr, uint8_t value)
478 {
479 mem_color_ram[addr & 0x3ff] = value & 0xf;
480 }
481
colorram_read(uint16_t addr)482 uint8_t colorram_read(uint16_t addr)
483 {
484 return mem_color_ram[addr & 0x3ff] | (vicii_read_phi1() & 0xf0);
485 }
486
487 /* ------------------------------------------------------------------------- */
488
489 /* init 256k memory table changes */
490 /* FIXME: make sure all cartridge related callbacks are hooked correctly */
check_256k_ram_write(int k,int i,int j)491 static int check_256k_ram_write(int k, int i, int j)
492 {
493 if (mem_write_tab[k][i][j] == vicii_mem_vbank_39xx_store) {
494 return 1;
495 }
496 if (mem_write_tab[k][i][j] == vicii_mem_vbank_3fxx_store) {
497 return 1;
498 }
499 if (mem_write_tab[k][i][j] == vicii_mem_vbank_store) {
500 return 1;
501 }
502 if (mem_write_tab[k][i][j] == ram_hi_store) {
503 return 1;
504 }
505 if (mem_write_tab[k][i][j] == ram_store) {
506 return 1;
507 }
508 if (mem_write_tab[k][i][j] == raml_no_ultimax_store) { /* possibly breaks mmc64 and expert */
509 return 1;
510 }
511 if (mem_write_tab[k][i][j] == romh_no_ultimax_store) { /* possibly breaks mmc64 and expert */
512 return 1;
513 }
514 if (mem_write_tab[k][i][j] == ramh_no_ultimax_store) { /* possibly breaks mmc64 and expert */
515 return 1;
516 }
517 if (mem_write_tab[k][i][j] == romh_store) {
518 return 1;
519 }
520 return 0;
521 }
522
c64_256k_init_config(void)523 static void c64_256k_init_config(void)
524 {
525 int i, j, k;
526
527 if (c64_256k_enabled) {
528 mem_limit_256k_init(mem_read_limit_tab);
529 for (i = 0; i < NUM_CONFIGS; i++) {
530 for (j = 1; j <= 0xff; j++) {
531 for (k = 0; k < NUM_VBANKS; k++) {
532 if (check_256k_ram_write(k, i, j) == 1) {
533 if (j < 0x40) {
534 mem_write_tab[k][i][j] = c64_256k_ram_segment0_store;
535 }
536 if (j > 0x3f && j < 0x80) {
537 mem_write_tab[k][i][j] = c64_256k_ram_segment1_store;
538 }
539 if (j > 0x7f && j < 0xc0) {
540 mem_write_tab[k][i][j] = c64_256k_ram_segment2_store;
541 }
542 if (j > 0xbf) {
543 mem_write_tab[k][i][j] = c64_256k_ram_segment3_store;
544 }
545 }
546 }
547 if (mem_read_tab[i][j] == ram_read) {
548 if (j < 0x40) {
549 mem_read_tab[i][j] = c64_256k_ram_segment0_read;
550 }
551 if (j > 0x3f && j < 0x80) {
552 mem_read_tab[i][j] = c64_256k_ram_segment1_read;
553 }
554 if (j > 0x7f && j < 0xc0) {
555 mem_read_tab[i][j] = c64_256k_ram_segment2_read;
556 }
557 if (j > 0xbf) {
558 mem_read_tab[i][j] = c64_256k_ram_segment3_read;
559 }
560 }
561 }
562 }
563 }
564 }
565
566 /* ------------------------------------------------------------------------- */
567
568 /* init plus256k memory table changes */
569 /* FIXME: make sure all cartridge related callbacks are hooked correctly */
plus256k_init_config(void)570 static void plus256k_init_config(void)
571 {
572 int i, j, k;
573
574 if (plus256k_enabled) {
575 mem_limit_256k_init(mem_read_limit_tab);
576 for (i = 0; i < NUM_CONFIGS; i++) {
577 for (j = 1; j <= 0xff; j++) {
578 for (k = 0; k < NUM_VBANKS; k++) {
579 if (check_256k_ram_write(k, i, j) == 1) {
580 if (j < 0x10) {
581 mem_write_tab[k][i][j] = plus256k_ram_low_store;
582 } else {
583 mem_write_tab[k][i][j] = plus256k_ram_high_store;
584 }
585 }
586 }
587 if (mem_read_tab[i][j] == ram_read) {
588 if (j < 0x10) {
589 mem_read_tab[i][j] = plus256k_ram_low_read;
590 } else {
591 mem_read_tab[i][j] = plus256k_ram_high_read;
592 }
593 }
594 }
595 }
596 }
597 }
598
599 /* init plus60k memory table changes */
600 /* FIXME: make sure all cartridge related callbacks are hooked correctly */
plus60k_init_config(void)601 static void plus60k_init_config(void)
602 {
603 int i, j, k;
604
605 if (plus60k_enabled) {
606 mem_limit_plus60k_init(mem_read_limit_tab);
607 for (i = 0; i < NUM_CONFIGS; i++) {
608 for (j = 0x10; j <= 0xff; j++) {
609 for (k = 0; k < NUM_VBANKS; k++) {
610 if (mem_write_tab[k][i][j] == vicii_mem_vbank_39xx_store) {
611 mem_write_tab[k][i][j] = plus60k_vicii_mem_vbank_39xx_store;
612 }
613 if (mem_write_tab[k][i][j] == vicii_mem_vbank_3fxx_store) {
614 mem_write_tab[k][i][j] = plus60k_vicii_mem_vbank_3fxx_store;
615 }
616 if (mem_write_tab[k][i][j] == vicii_mem_vbank_store) {
617 mem_write_tab[k][i][j] = plus60k_vicii_mem_vbank_store;
618 }
619 if (mem_write_tab[k][i][j] == ram_hi_store) {
620 mem_write_tab[k][i][j] = plus60k_ram_hi_store;
621 }
622 if (mem_write_tab[k][i][j] == ram_store) {
623 mem_write_tab[k][i][j] = plus60k_ram_store;
624 }
625 if (mem_write_tab[k][i][j] == raml_no_ultimax_store) {
626 mem_write_tab[k][i][j] = plus60k_ram_store; /* possibly breaks mmc64 and expert */
627 }
628 if (mem_write_tab[k][i][j] == romh_no_ultimax_store) {
629 mem_write_tab[k][i][j] = plus60k_ram_store; /* possibly breaks mmc64 and expert */
630 }
631 if (mem_write_tab[k][i][j] == ramh_no_ultimax_store) {
632 mem_write_tab[k][i][j] = plus60k_ram_store; /* possibly breaks mmc64 and expert */
633 }
634 if (mem_write_tab[k][i][j] == romh_store) {
635 mem_write_tab[k][i][j] = plus60k_ram_store;
636 }
637 }
638 if (mem_read_tab[i][j] == ram_read) {
639 mem_read_tab[i][j] = plus60k_ram_read;
640 }
641 }
642 }
643 }
644 }
645
646 /* ------------------------------------------------------------------------- */
647
mem_set_write_hook(int config,int page,store_func_t * f)648 void mem_set_write_hook(int config, int page, store_func_t *f)
649 {
650 int i;
651
652 for (i = 0; i < NUM_VBANKS; i++) {
653 mem_write_tab[i][config][page] = f;
654 }
655 }
656
mem_read_tab_set(unsigned int base,unsigned int index,read_func_ptr_t read_func)657 void mem_read_tab_set(unsigned int base, unsigned int index, read_func_ptr_t read_func)
658 {
659 mem_read_tab[base][index] = read_func;
660 }
661
mem_read_base_set(unsigned int base,unsigned int index,uint8_t * mem_ptr)662 void mem_read_base_set(unsigned int base, unsigned int index, uint8_t *mem_ptr)
663 {
664 mem_read_base_tab[base][index] = mem_ptr;
665 }
666
mem_initialize_memory(void)667 void mem_initialize_memory(void)
668 {
669 int i, j, k;
670 int board;
671
672 mem_chargen_rom_ptr = mem_chargen_rom;
673 mem_color_ram_cpu = mem_color_ram;
674 mem_color_ram_vicii = mem_color_ram;
675
676 mem_limit_init(mem_read_limit_tab);
677
678 /* setup watchpoint tables */
679 mem_read_tab_watch[0] = zero_read_watch;
680 mem_write_tab_watch[0] = zero_store_watch;
681 for (i = 1; i <= 0x100; i++) {
682 mem_read_tab_watch[i] = read_watch;
683 mem_write_tab_watch[i] = store_watch;
684 }
685
686 resources_get_int("BoardType", &board);
687
688 /* Default is RAM. */
689 for (i = 0; i < NUM_CONFIGS; i++) {
690 mem_set_write_hook(i, 0, zero_store);
691 mem_read_tab[i][0] = zero_read;
692 mem_read_base_tab[i][0] = mem_ram;
693 for (j = 1; j <= 0xfe; j++) {
694 if (board == 1 && j >= 0x08) {
695 mem_read_tab[i][j] = void_read;
696 mem_read_base_tab[i][j] = NULL;
697 mem_set_write_hook(0, j, void_store);
698 continue;
699 }
700 mem_read_tab[i][j] = ram_read;
701 mem_read_base_tab[i][j] = mem_ram;
702 for (k = 0; k < NUM_VBANKS; k++) {
703 if ((j & 0xc0) == (k << 6)) {
704 switch (j & 0x3f) {
705 case 0x39:
706 mem_write_tab[k][i][j] = vicii_mem_vbank_39xx_store;
707 break;
708 case 0x3f:
709 mem_write_tab[k][i][j] = vicii_mem_vbank_3fxx_store;
710 break;
711 default:
712 mem_write_tab[k][i][j] = vicii_mem_vbank_store;
713 }
714 } else {
715 mem_write_tab[k][i][j] = ram_store;
716 }
717 }
718 }
719 if (board == 1) {
720 mem_read_tab[i][0xff] = void_read;
721 mem_read_base_tab[i][0xff] = NULL;
722 mem_set_write_hook(0, 0xff, void_store);
723 } else {
724 mem_read_tab[i][0xff] = ram_read;
725 mem_read_base_tab[i][0xff] = mem_ram;
726
727 /* vbank access is handled within `ram_hi_store()'. */
728 mem_set_write_hook(i, 0xff, ram_hi_store);
729 }
730 }
731
732 /* Setup character generator ROM at $D000-$DFFF (memory configs 1, 2, 3, 9, 10, 11, 26, 27). */
733 for (i = 0xd0; i <= 0xdf; i++) {
734 mem_read_tab[1][i] = chargen_read;
735 mem_read_tab[2][i] = chargen_read;
736 mem_read_tab[3][i] = chargen_read;
737 mem_read_tab[9][i] = chargen_read;
738 mem_read_tab[10][i] = chargen_read;
739 mem_read_tab[11][i] = chargen_read;
740 mem_read_tab[26][i] = chargen_read;
741 mem_read_tab[27][i] = chargen_read;
742 mem_read_base_tab[1][i] = (uint8_t *)(mem_chargen_rom - (uint8_t *)0xd000);
743 mem_read_base_tab[2][i] = (uint8_t *)(mem_chargen_rom - (uint8_t *)0xd000);
744 mem_read_base_tab[3][i] = (uint8_t *)(mem_chargen_rom - (uint8_t *)0xd000);
745 mem_read_base_tab[9][i] = (uint8_t *)(mem_chargen_rom - (uint8_t *)0xd000);
746 mem_read_base_tab[10][i] = (uint8_t *)(mem_chargen_rom - (uint8_t *)0xd000);
747 mem_read_base_tab[11][i] = (uint8_t *)(mem_chargen_rom - (uint8_t *)0xd000);
748 mem_read_base_tab[26][i] = (uint8_t *)(mem_chargen_rom - (uint8_t *)0xd000);
749 mem_read_base_tab[27][i] = (uint8_t *)(mem_chargen_rom - (uint8_t *)0xd000);
750 }
751
752 c64meminit(0);
753
754 for (i = 0; i < NUM_CONFIGS; i++) {
755 mem_read_tab[i][0x100] = mem_read_tab[i][0];
756 for (j = 0; j < NUM_VBANKS; j++) {
757 mem_write_tab[j][i][0x100] = mem_write_tab[j][i][0];
758 }
759 mem_read_base_tab[i][0x100] = mem_read_base_tab[i][0];
760 }
761
762 _mem_read_tab_ptr = mem_read_tab[7];
763 _mem_write_tab_ptr = mem_write_tab[vbank][7];
764 _mem_read_base_tab_ptr = mem_read_base_tab[7];
765 mem_read_limit_tab_ptr = mem_read_limit_tab[7];
766
767 vicii_set_chargen_addr_options(0x7000, 0x1000);
768
769 c64pla_pport_reset();
770 export.exrom = 0;
771 export.game = 0;
772
773 /* Setup initial memory configuration. */
774 mem_pla_config_changed();
775 cartridge_init_config();
776 /* internal expansions, these may modify the above mappings and must take
777 care of hooking up all callbacks correctly.
778 */
779 plus60k_init_config();
780 plus256k_init_config();
781 c64_256k_init_config();
782
783 if (board == 1) {
784 mem_limit_max_init(mem_read_limit_tab);
785 }
786 }
787
mem_mmu_translate(unsigned int addr,uint8_t ** base,int * start,int * limit)788 void mem_mmu_translate(unsigned int addr, uint8_t **base, int *start, int *limit)
789 {
790 uint8_t *p = _mem_read_base_tab_ptr[addr >> 8];
791 uint32_t limits;
792
793 if (p != NULL && addr > 1) {
794 *base = p;
795 limits = mem_read_limit_tab_ptr[addr >> 8];
796 *limit = limits & 0xffff;
797 *start = limits >> 16;
798 } else {
799 cartridge_mmu_translate(addr, base, start, limit);
800 }
801 }
802
803 /* ------------------------------------------------------------------------- */
804
805 /* Initialize RAM for power-up. */
mem_powerup(void)806 void mem_powerup(void)
807 {
808 ram_init(mem_ram, 0x10000);
809 cartridge_ram_init(); /* Clean cartridge ram too */
810 }
811
812 /* ------------------------------------------------------------------------- */
813
814 /* Change the current video bank. Call this routine only when the vbank
815 has really changed. */
mem_set_vbank(int new_vbank)816 void mem_set_vbank(int new_vbank)
817 {
818 vbank = new_vbank;
819
820 /* Do not override watchpoints on vbank switches. */
821 if (_mem_write_tab_ptr != mem_write_tab_watch) {
822 _mem_write_tab_ptr = mem_write_tab[new_vbank][mem_config];
823 }
824
825 vicii_set_vbank(new_vbank);
826 }
827
828 /* Set the tape sense status. */
mem_set_tape_sense(int sense)829 void mem_set_tape_sense(int sense)
830 {
831 tape_sense = sense;
832 mem_pla_config_changed();
833 }
834
835 /* Set the tape write in. */
mem_set_tape_write_in(int val)836 void mem_set_tape_write_in(int val)
837 {
838 tape_write_in = val;
839 mem_pla_config_changed();
840 }
841
842 /* Set the tape motor in. */
mem_set_tape_motor_in(int val)843 void mem_set_tape_motor_in(int val)
844 {
845 tape_motor_in = val;
846 mem_pla_config_changed();
847 }
848
849 /* ------------------------------------------------------------------------- */
850
851 /* FIXME: this part needs to be checked. */
852
mem_get_basic_text(uint16_t * start,uint16_t * end)853 void mem_get_basic_text(uint16_t *start, uint16_t *end)
854 {
855 if (start != NULL) {
856 *start = mem_ram[0x2b] | (mem_ram[0x2c] << 8);
857 }
858 if (end != NULL) {
859 *end = mem_ram[0x2d] | (mem_ram[0x2e] << 8);
860 }
861 }
862
mem_set_basic_text(uint16_t start,uint16_t end)863 void mem_set_basic_text(uint16_t start, uint16_t end)
864 {
865 mem_ram[0x2b] = mem_ram[0xac] = start & 0xff;
866 mem_ram[0x2c] = mem_ram[0xad] = start >> 8;
867 mem_ram[0x2d] = mem_ram[0x2f] = mem_ram[0x31] = mem_ram[0xae] = end & 0xff;
868 mem_ram[0x2e] = mem_ram[0x30] = mem_ram[0x32] = mem_ram[0xaf] = end >> 8;
869 }
870
mem_inject(uint32_t addr,uint8_t value)871 void mem_inject(uint32_t addr, uint8_t value)
872 {
873 /* could be made to handle various internal expansions in some sane way */
874 mem_ram[addr & 0xffff] = value;
875 }
876
877 /* ------------------------------------------------------------------------- */
878
mem_rom_trap_allowed(uint16_t addr)879 int mem_rom_trap_allowed(uint16_t addr)
880 {
881 if (addr >= 0xe000) {
882 switch (mem_config) {
883 case 2:
884 case 3:
885 case 6:
886 case 7:
887 case 10:
888 case 11:
889 case 14:
890 case 15:
891 case 26:
892 case 27:
893 case 30:
894 case 31:
895 return 1;
896 default:
897 return 0;
898 }
899 }
900
901 return 0;
902 }
903
904 /* ------------------------------------------------------------------------- */
905
906 /* Banked memory access functions for the monitor. */
907
store_bank_io(uint16_t addr,uint8_t byte)908 void store_bank_io(uint16_t addr, uint8_t byte)
909 {
910 switch (addr & 0xff00) {
911 case 0xd000:
912 c64io_d000_store(addr, byte);
913 break;
914 case 0xd100:
915 c64io_d100_store(addr, byte);
916 break;
917 case 0xd200:
918 c64io_d200_store(addr, byte);
919 break;
920 case 0xd300:
921 c64io_d300_store(addr, byte);
922 break;
923 case 0xd400:
924 c64io_d400_store(addr, byte);
925 break;
926 case 0xd500:
927 c64io_d500_store(addr, byte);
928 break;
929 case 0xd600:
930 c64io_d600_store(addr, byte);
931 break;
932 case 0xd700:
933 c64io_d700_store(addr, byte);
934 break;
935 case 0xd800:
936 case 0xd900:
937 case 0xda00:
938 case 0xdb00:
939 colorram_store(addr, byte);
940 break;
941 case 0xdc00:
942 cia1_store(addr, byte);
943 break;
944 case 0xdd00:
945 cia2_store(addr, byte);
946 break;
947 case 0xde00:
948 c64io_de00_store(addr, byte);
949 break;
950 case 0xdf00:
951 c64io_df00_store(addr, byte);
952 break;
953 }
954 return;
955 }
956
read_bank_io(uint16_t addr)957 uint8_t read_bank_io(uint16_t addr)
958 {
959 switch (addr & 0xff00) {
960 case 0xd000:
961 return c64io_d000_read(addr);
962 case 0xd100:
963 return c64io_d100_read(addr);
964 case 0xd200:
965 return c64io_d200_read(addr);
966 case 0xd300:
967 return c64io_d300_read(addr);
968 case 0xd400:
969 return c64io_d400_read(addr);
970 case 0xd500:
971 return c64io_d500_read(addr);
972 case 0xd600:
973 return c64io_d600_read(addr);
974 case 0xd700:
975 return c64io_d700_read(addr);
976 case 0xd800:
977 case 0xd900:
978 case 0xda00:
979 case 0xdb00:
980 return colorram_read(addr);
981 case 0xdc00:
982 return cia1_read(addr);
983 case 0xdd00:
984 return cia2_read(addr);
985 case 0xde00:
986 return c64io_de00_read(addr);
987 case 0xdf00:
988 return c64io_df00_read(addr);
989 }
990 return 0xff;
991 }
992
peek_bank_io(uint16_t addr)993 static uint8_t peek_bank_io(uint16_t addr)
994 {
995 switch (addr & 0xff00) {
996 case 0xd000:
997 return c64io_d000_peek(addr);
998 case 0xd100:
999 return c64io_d100_peek(addr);
1000 case 0xd200:
1001 return c64io_d200_peek(addr);
1002 case 0xd300:
1003 return c64io_d300_peek(addr);
1004 case 0xd400:
1005 return c64io_d400_peek(addr);
1006 case 0xd500:
1007 return c64io_d500_peek(addr);
1008 case 0xd600:
1009 return c64io_d600_peek(addr);
1010 case 0xd700:
1011 return c64io_d700_peek(addr);
1012 case 0xd800:
1013 case 0xd900:
1014 case 0xda00:
1015 case 0xdb00:
1016 return colorram_read(addr);
1017 case 0xdc00:
1018 return cia1_peek(addr);
1019 case 0xdd00:
1020 return cia2_peek(addr);
1021 case 0xde00:
1022 return c64io_de00_peek(addr);
1023 case 0xdf00:
1024 return c64io_df00_peek(addr);
1025 }
1026 return 0xff;
1027 }
1028
1029 /* ------------------------------------------------------------------------- */
1030
1031 /* Exported banked memory access functions for the monitor. */
1032
1033 static const char *banknames[] = {
1034 "default",
1035 "cpu",
1036 "ram",
1037 "rom",
1038 "io",
1039 "cart",
1040 NULL
1041 };
1042
1043 static const int banknums[] = { 1, 0, 1, 2, 3, 4 };
1044
mem_bank_list(void)1045 const char **mem_bank_list(void)
1046 {
1047 return banknames;
1048 }
1049
mem_bank_from_name(const char * name)1050 int mem_bank_from_name(const char *name)
1051 {
1052 int i = 0;
1053
1054 while (banknames[i]) {
1055 if (!strcmp(name, banknames[i])) {
1056 return banknums[i];
1057 }
1058 i++;
1059 }
1060 return -1;
1061 }
1062
1063 /* read memory with side-effects */
mem_bank_read(int bank,uint16_t addr,void * context)1064 uint8_t mem_bank_read(int bank, uint16_t addr, void *context)
1065 {
1066 switch (bank) {
1067 case 0: /* current */
1068 return mem_read(addr);
1069 break;
1070 case 3: /* io */
1071 if (addr >= 0xd000 && addr < 0xe000) {
1072 return read_bank_io(addr);
1073 }
1074 /* FALL THROUGH */
1075 case 4: /* cart */
1076 return cartridge_peek_mem(addr);
1077 case 2: /* rom */
1078 if (addr >= 0xa000 && addr <= 0xbfff) {
1079 return c64memrom_basic64_rom[addr & 0x1fff];
1080 }
1081 if (addr >= 0xd000 && addr <= 0xdfff) {
1082 return mem_chargen_rom[addr & 0x0fff];
1083 }
1084 if (addr >= 0xe000) {
1085 return c64memrom_kernal64_rom[addr & 0x1fff];
1086 }
1087 /* FALL THROUGH */
1088 case 1: /* ram */
1089 break;
1090 }
1091 return mem_ram[addr];
1092 }
1093
1094 /* read memory without side-effects */
mem_bank_peek(int bank,uint16_t addr,void * context)1095 uint8_t mem_bank_peek(int bank, uint16_t addr, void *context)
1096 {
1097 switch (bank) {
1098 case 0: /* current */
1099 /* we must check for which bank is currently active, and only use peek_bank_io
1100 when needed to avoid side effects */
1101 if (c64meminit_io_config[mem_config]) {
1102 if ((addr >= 0xd000) && (addr < 0xe000)) {
1103 return peek_bank_io(addr);
1104 }
1105 }
1106 return mem_read(addr);
1107 break;
1108 case 3: /* io */
1109 if ((addr >= 0xd000) && (addr < 0xe000)) {
1110 return peek_bank_io(addr);
1111 }
1112 break;
1113 case 4: /* cart */
1114 return cartridge_peek_mem(addr);
1115 }
1116 return mem_bank_read(bank, addr, context);
1117 }
1118
mem_bank_write(int bank,uint16_t addr,uint8_t byte,void * context)1119 void mem_bank_write(int bank, uint16_t addr, uint8_t byte, void *context)
1120 {
1121 switch (bank) {
1122 case 0: /* current */
1123 mem_store(addr, byte);
1124 return;
1125 case 3: /* io */
1126 if (addr >= 0xd000 && addr < 0xe000) {
1127 store_bank_io(addr, byte);
1128 return;
1129 }
1130 /* FALL THROUGH */
1131 case 2: /* rom */
1132 if (addr >= 0xa000 && addr <= 0xbfff) {
1133 return;
1134 }
1135 if (addr >= 0xd000 && addr <= 0xdfff) {
1136 return;
1137 }
1138 if (addr >= 0xe000) {
1139 return;
1140 }
1141 /* FALL THROUGH */
1142 case 1: /* ram */
1143 break;
1144 }
1145 mem_ram[addr] = byte;
1146 }
1147
mem_dump_io(void * context,uint16_t addr)1148 static int mem_dump_io(void *context, uint16_t addr)
1149 {
1150 if ((addr >= 0xdc00) && (addr <= 0xdc3f)) {
1151 return ciacore_dump(machine_context.cia1);
1152 } else if ((addr >= 0xdd00) && (addr <= 0xdd3f)) {
1153 return ciacore_dump(machine_context.cia2);
1154 }
1155 return -1;
1156 }
1157
mem_ioreg_list_get(void * context)1158 mem_ioreg_list_t *mem_ioreg_list_get(void *context)
1159 {
1160 mem_ioreg_list_t *mem_ioreg_list = NULL;
1161
1162 mon_ioreg_add_list(&mem_ioreg_list, "CIA1", 0xdc00, 0xdc0f, mem_dump_io, NULL);
1163 mon_ioreg_add_list(&mem_ioreg_list, "CIA2", 0xdd00, 0xdd0f, mem_dump_io, NULL);
1164
1165 io_source_ioreg_add_list(&mem_ioreg_list);
1166
1167 return mem_ioreg_list;
1168 }
1169
mem_get_screen_parameter(uint16_t * base,uint8_t * rows,uint8_t * columns,int * bank)1170 void mem_get_screen_parameter(uint16_t *base, uint8_t *rows, uint8_t *columns, int *bank)
1171 {
1172 *base = ((vicii_peek(0xd018) & 0xf0) << 6) | ((~cia2_peek(0xdd00) & 0x03) << 14);
1173 *rows = 25;
1174 *columns = 40;
1175 *bank = 0;
1176 }
1177
1178 /* ------------------------------------------------------------------------- */
1179
mem_color_ram_to_snapshot(uint8_t * color_ram)1180 void mem_color_ram_to_snapshot(uint8_t *color_ram)
1181 {
1182 memcpy(color_ram, mem_color_ram, 0x400);
1183 }
1184
mem_color_ram_from_snapshot(uint8_t * color_ram)1185 void mem_color_ram_from_snapshot(uint8_t *color_ram)
1186 {
1187 memcpy(mem_color_ram, color_ram, 0x400);
1188 }
1189
1190 /* ------------------------------------------------------------------------- */
1191
1192 /* UI functions (used to distinguish between x64 and x64sc) */
c64_mem_ui_init_early(void)1193 int c64_mem_ui_init_early(void)
1194 {
1195 return c64ui_init_early();
1196 }
1197
c64_mem_ui_init(void)1198 int c64_mem_ui_init(void)
1199 {
1200 return c64ui_init();
1201 }
1202
c64_mem_ui_shutdown(void)1203 void c64_mem_ui_shutdown(void)
1204 {
1205 c64ui_shutdown();
1206 }
1207