1 /*
2  * petmem.c - PET memory handling.
3  *
4  * Written by
5  *  Ettore Perazzoli <ettore@comm2000.it>
6  *  Andre Fachat <fachat@physik.tu-chemnitz.de>
7  *  Andreas Boose <viceteam@t-online.de>
8  *  Marco van den Heuvel <blackystardust68@yahoo.com>
9  *
10  * This file is part of VICE, the Versatile Commodore Emulator.
11  * See README for copyright notice.
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 2 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, write to the Free Software
25  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26  *  02111-1307  USA.
27  *
28  */
29 
30 #include "vice.h"
31 
32 #include <stdio.h>
33 #include <string.h>
34 #include <stdlib.h>
35 
36 #include "6809.h"
37 #include "cartio.h"
38 #include "cartridge.h"
39 #include "crtc-mem.h"
40 #include "crtctypes.h"
41 #include "lib.h"
42 #include "log.h"
43 #include "machine.h"
44 #include "maincpu.h"
45 #include "mem.h"
46 #include "monitor.h"
47 #include "pet.h"
48 #include "pet-resources.h"
49 #include "petacia.h"
50 #include "petcolour.h"
51 #include "petdww.h"
52 #include "pethre.h"
53 #include "petmem.h"
54 #include "petmodel.h"
55 #include "petpia.h"
56 #include "pets.h"
57 #include "petvia.h"
58 #include "ram.h"
59 #include "resources.h"
60 #include "types.h"
61 #include "via.h"
62 #include "vsync.h"
63 
64 static uint8_t mem_read_patchbuf(uint16_t addr);
65 static void mem_initialize_memory_6809_flat(void);
66 
67 uint8_t petmem_2001_buf_ef[256];
68 
69 /* ------------------------------------------------------------------------- */
70 
71 /*
72  * We keep the current system config in here.
73  * It is initialized to defaults from the default resource values.
74  */
75 
76 petres_t petres;
77 
78 /* if the above is true, there's no need for this: */
79 #if 0
80 = {
81     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
82     NULL, NULL, NULL, NULL, NULL, NULL, NULL,
83     { NULL, NULL, NULL, NULL, NULL, NULL }, /* h6809romName[] */
84     0, 0, 0, 0, 0, 0, 0, 0, 0
85 };
86 #endif
87 
88 /* ------------------------------------------------------------------------- */
89 
90 /* The PET memory. */
91 
92 #define RAM_ARRAY 0x20000 /* this includes 8x96 expansion RAM */
93 
94 uint8_t mem_ram[RAM_ARRAY]; /* 128K to make things easier. Real size is 4-128K. */
95 uint8_t mem_rom[PET_ROM_SIZE];
96 uint8_t mem_chargen_rom[PET_CHARGEN_ROM_SIZE];
97 uint8_t mem_6809rom[PET_6809_ROMSIZE];
98 
99 #define EXT_RAM         (64 * 1024)
100 
101 static int ram_size = RAM_ARRAY;       /* FIXME? */
102 
103 /* Memory read and write tables. */
104 static read_func_ptr_t _mem_read_tab[0x101];
105 static store_func_ptr_t _mem_write_tab[0x101];
106 static read_func_ptr_t _mem_read_tab_watch[0x101];
107 static store_func_ptr_t _mem_write_tab_watch[0x101];
108 static uint8_t *_mem_read_base_tab[0x101];
109 static int mem_read_limit_tab[0x101];
110 
111 read_func_ptr_t *_mem_read_tab_ptr;
112 store_func_ptr_t *_mem_write_tab_ptr;
113 static uint8_t **_mem_read_base_tab_ptr;
114 static int *mem_read_limit_tab_ptr;
115 
116 /* 8x96 mapping register */
117 uint8_t petmem_map_reg = 0;
118 #define FFF0_ENABLED                0x80
119 #define FFF0_IO_PEEK_THROUGH        0x40
120 #define FFF0_SCREEN_PEEK_THROUGH    0x20
121 /* Internal jumper, used by HRE board */
122 uint8_t petmem_ramON = 0;
123 
124 static int bank8offset = 0;
125 static int bankCoffset = 0;
126 
127 /* memory tables for the 6809 */
128 static read_func_ptr_t _mem6809_read_tab[0x101];
129 static store_func_ptr_t _mem6809_write_tab[0x101];
130 static read_func_ptr_t _mem6809_read_tab_watch[0x101];
131 static store_func_ptr_t _mem6809_write_tab_watch[0x101];
132 static uint8_t *_mem6809_read_base_tab[0x101];
133 static int mem6809_read_limit_tab[0x101];
134 
135 read_func_ptr_t *_mem6809_read_tab_ptr;
136 store_func_ptr_t *_mem6809_write_tab_ptr;
137 
138 static log_t pet_mem_log = LOG_ERR;
139 
140 static uint8_t last_access = 0;
141 
142 /* ------------------------------------------------------------------------- */
143 
zero_read(uint16_t addr)144 uint8_t zero_read(uint16_t addr)
145 {
146     last_access = mem_ram[addr & 0xff];
147     return last_access;
148 }
149 
zero_store(uint16_t addr,uint8_t value)150 void zero_store(uint16_t addr, uint8_t value)
151 {
152     mem_ram[addr & 0xff] = value;
153     last_access = value;
154 }
155 
ram_read(uint16_t addr)156 static uint8_t ram_read(uint16_t addr)
157 {
158     last_access = mem_ram[addr];
159     return last_access;
160 }
161 
ram_store(uint16_t addr,uint8_t value)162 static void ram_store(uint16_t addr, uint8_t value)
163 {
164     mem_ram[addr] = value;
165     last_access = value;
166 }
167 
read_ext8(uint16_t addr)168 static uint8_t read_ext8(uint16_t addr)
169 {
170     last_access = mem_ram[addr + bank8offset];
171     return last_access;
172 }
173 
store_ext8(uint16_t addr,uint8_t value)174 static void store_ext8(uint16_t addr, uint8_t value)
175 {
176     mem_ram[addr + bank8offset] = value;
177     last_access = value;
178 }
179 
read_extC(uint16_t addr)180 static uint8_t read_extC(uint16_t addr)
181 {
182     last_access = mem_ram[addr + bankCoffset];
183     return last_access;
184 }
185 
store_extC(uint16_t addr,uint8_t value)186 static void store_extC(uint16_t addr, uint8_t value)
187 {
188     mem_ram[addr + bankCoffset] = value;
189     last_access = value;
190 }
191 
192 /*
193  * Map $8400-$87FF to $8000-$83FF and $8C00-$8FFF to $8800-$8BFF.
194  * This is only relevant for 40 column models, since 80 column models
195  * don't have a mirror image of the screen memory.
196  * Above $8800 there is normally empty space, but the colour extension
197  * places its colour memory there, which in turn may have a mirror
198  * if it is the 40 column model.
199  */
read_vmirror(uint16_t addr)200 static uint8_t read_vmirror(uint16_t addr)
201 {
202     last_access = mem_ram[0x8000 + (addr & 0x0bff)];   /* 0x3FF + 0x800 */
203     return last_access;
204 }
205 
store_vmirror(uint16_t addr,uint8_t value)206 static void store_vmirror(uint16_t addr, uint8_t value)
207 {
208     mem_ram[0x8000 + (addr & 0xbff)] = value;
209     last_access = value;
210 }
211 
rom_read(uint16_t addr)212 uint8_t rom_read(uint16_t addr)
213 {
214     last_access = mem_rom[addr & 0x7fff];
215     return last_access;
216 }
217 
rom_store(uint16_t addr,uint8_t value)218 void rom_store(uint16_t addr, uint8_t value)
219 {
220     mem_rom[addr & 0x7fff] = value;
221     last_access = value;
222 }
223 
224 #define ROM6809_BASE    0xA000
225 
rom6809_read(uint16_t addr)226 static uint8_t rom6809_read(uint16_t addr)
227 {
228     last_access = mem_6809rom[addr - ROM6809_BASE];
229     return last_access;
230 }
231 
232 #if 0
233 static void rom6809_store(uint16_t addr, uint8_t value)
234 {
235     mem_6809rom[addr - ROM6809_BASE] = value;
236     last_access = value;
237 }
238 #endif
239 
read_unused(uint16_t addr)240 uint8_t read_unused(uint16_t addr)
241 {
242     return last_access;
243 }
244 
read_io_88_8f(uint16_t addr)245 static uint8_t read_io_88_8f(uint16_t addr)
246 {
247     switch (addr & 0xff00) {
248         case 0x8800:
249             return petio_8800_read(addr);
250         case 0x8900:
251             return petio_8900_read(addr);
252         case 0x8a00:
253             return petio_8a00_read(addr);
254         case 0x8b00:
255             return petio_8b00_read(addr);
256         case 0x8c00:
257             return petio_8c00_read(addr);
258         case 0x8d00:
259             return petio_8d00_read(addr);
260         case 0x8e00:
261             return petio_8e00_read(addr);
262         case 0x8f00:
263             return petio_8f00_read(addr);
264     }
265 
266     return last_access;
267 }
268 
read_io_e9_ef(uint16_t addr)269 static uint8_t read_io_e9_ef(uint16_t addr)
270 {
271     switch (addr & 0xff00) {
272         case 0xe900:
273             return petio_e900_read(addr);
274         case 0xea00:
275             return petio_ea00_read(addr);
276         case 0xeb00:
277             return petio_eb00_read(addr);
278         case 0xec00:
279             return petio_ec00_read(addr);
280         case 0xed00:
281             return petio_ed00_read(addr);
282         case 0xee00:
283             return petio_ee00_read(addr);
284         case 0xef00:
285             return petio_ef00_read(addr);
286     }
287 
288     return last_access;
289 }
290 
mem_read_patchbuf(uint16_t addr)291 static uint8_t mem_read_patchbuf(uint16_t addr)
292 {
293     last_access = petmem_2001_buf_ef[addr & 0xff];
294     return last_access;
295 }
296 
297 /* ------------------------------------------------------------------------- */
298 
299 /* Functions for watchpoint memory access.  */
300 
zero_read_watch(uint16_t addr)301 static uint8_t zero_read_watch(uint16_t addr)
302 {
303     addr &= 0xff;
304     monitor_watch_push_load_addr(addr, e_comp_space);
305     return _mem_read_tab[0](addr);
306 }
307 
zero_store_watch(uint16_t addr,uint8_t value)308 static void zero_store_watch(uint16_t addr, uint8_t value)
309 {
310     addr &= 0xff;
311     monitor_watch_push_store_addr(addr, e_comp_space);
312     _mem_write_tab[0](addr, value);
313 }
314 
read_watch(uint16_t addr)315 static uint8_t read_watch(uint16_t addr)
316 {
317     monitor_watch_push_load_addr(addr, e_comp_space);
318     return _mem_read_tab[addr >> 8](addr);
319 }
320 
store_watch(uint16_t addr,uint8_t value)321 static void store_watch(uint16_t addr, uint8_t value)
322 {
323     monitor_watch_push_store_addr(addr, e_comp_space);
324     _mem_write_tab[addr >> 8](addr, value);
325 }
326 
read6809_watch(uint16_t addr)327 static uint8_t read6809_watch(uint16_t addr)
328 {
329     monitor_watch_push_load_addr(addr, e_comp_space);
330     return _mem6809_read_tab[addr >> 8](addr);
331 }
332 
store6809_watch(uint16_t addr,uint8_t value)333 static void store6809_watch(uint16_t addr, uint8_t value)
334 {
335     monitor_watch_push_store_addr(addr, e_comp_space);
336     _mem6809_write_tab[addr >> 8](addr, value);
337 }
338 
339 /* ------------------------------------------------------------------------- */
340 
341 /* SuperPET handling
342  *
343  * This adds some write-only registers at $eff*, an ACIA at $eff0 and
344  * 64k RAM that are mapped in 4k pages at $9***.
345  * Here the 8x96 expansion RAM doubles as the SuperPET banked RAM.
346  * There is also a dongle (6702) at $efe0.
347  */
348 
349 int spet_ramen = 1;
350 int spet_bank = 0;
351 static uint8_t *spet_bank_ptr;
352 int spet_ctrlwp = 1;
353 int spet_diag = 0;
354 int spet_ramwp = 0;
355 int spet_flat_mode = 0;         /* This is for the extra TPUG-designed */
356 int spet_firq_disabled = 0;     /* ...Super OS/9 MMU. */
357 #define DEBUG_DONGLE    0
358 
359 /* Internal state of the 6702 dongle */
360 #define DONGLE_MAGIC    (128 + 64 + 16 + 4 + 2) /* = 214 = $D6 = %1101 0110 */
361 static const int leftmost[8] = {
362     1 << (6 - 1),       /*   1 The size of each shift register is 6, 3, 7... */
363     1 << (3 - 1),       /*   2 and therefore those are also the periods of */
364     1 << (7 - 1),       /*   4 the output bits. */
365     1 << (8 - 1),       /*   8 */
366     1 << (1 - 1),       /*  16 */
367     1 << (3 - 1),       /*  32 */
368     1 << (5 - 1),       /*  64 */
369     1 << (2 - 1),       /* 128 */
370 };
371 struct dongle6702_s dongle6702;
372 
reset6702(void)373 static void reset6702(void)
374 {
375     int i;
376 
377     for (i = 0; i < 8; i++) {
378         if ((1 << i) & (DONGLE_MAGIC | 1)) {
379             dongle6702.shift[i] = leftmost[i];
380         } else {
381             dongle6702.shift[i] = 0;
382         }
383     }
384     dongle6702.val = DONGLE_MAGIC;
385     dongle6702.prevodd = 1;
386     dongle6702.wantodd = 0;
387 }
388 
read6702(void)389 static inline uint8_t read6702(void)
390 {
391     last_access = dongle6702.val;
392     return last_access;
393 }
394 
395 /*
396  * Only the first odd value which is written after
397  * an even value has an effect.
398  *
399  * Thanks to Ruud Baltissen, William Levak, Rob Clarke,
400  * Kajtar Zsolt and Segher Boessenkool, Dave E Roberts,
401  * from cbm-hackers, for their contributions.
402  * -Olaf Seibert.
403  */
write6702(uint8_t input)404 static inline void write6702(uint8_t input)
405 {
406     last_access = input;
407 
408     if ((input & 1) == dongle6702.wantodd) {
409         if (dongle6702.wantodd) {
410             int i;
411             int v = dongle6702.val;
412             int changed = dongle6702.prevodd ^ input;
413             int mask = 0x80;
414 
415             /* loop over all 8 output bits / shift registers */
416             for (i = 7; i >= 0; i--, mask >>= 1) {
417                 /* If the input bit changed: toggle leftmost bit */
418                 if (changed & mask) {
419                     dongle6702.shift[i] ^= leftmost[i];
420                 }
421                 /* The rightmost bit (the one that gets shifted out in
422                  * a moment) determines if the output changes.
423                  * I.e., if the rightmost bit is set, toggle it in v.
424                  * Also simulate a rotate of the shift register by setting
425                  * a 1 just left of the leftmost bit, so that the
426                  * subsequent right-shift will put a 1 at the left.
427                  * (If there is a 0, all this is a no-op.)
428                  */
429                 if (dongle6702.shift[i] & 1) {
430                     v ^= mask;
431                     dongle6702.shift[i] |= leftmost[i] << 1; /* wrap bit around */
432                 }
433                 dongle6702.shift[i] >>= 1;
434             }
435 
436             dongle6702.prevodd = input;
437             dongle6702.val = v;
438         }
439         dongle6702.wantodd ^= 1;
440     }
441 }
442 
efe0_dump(void)443 static int efe0_dump(void)
444 {
445     int i;
446     int mask = 1;
447 
448     mon_out("efe0 = $%02x; previous in = $%02x; odd/even = %d\n", dongle6702.val, dongle6702.prevodd, dongle6702.wantodd);
449     for (i = 0; i < 8; i++, mask <<= 1) {
450         int j;
451         int maskj;
452         int sh = dongle6702.shift[i];
453         int lm = leftmost[i];
454 
455         mon_out("%d %3d: $%02x  %%", i, mask, sh);
456 
457         for (j = 7, maskj = 1 << j; j >= 0; j--, maskj >>= 1) {
458             if (maskj > lm) {
459                 mon_out(" ");
460             } else if (sh & maskj) {
461                 mon_out("1");
462             } else {
463                 mon_out("0");
464             }
465         }
466         mon_out("\n");
467     }
468 
469     return 0;
470 }
471 
set_spet_bank(int banknr)472 void set_spet_bank(int banknr)
473 {
474     spet_bank_ptr = &mem_ram[EXT_RAM + (banknr << 12)];
475 }
476 
petmem_reset(void)477 void petmem_reset(void)
478 {
479     spet_ramen = 1;
480     set_spet_bank(0);
481     spet_ctrlwp = 1;
482     spet_flat_mode = 0;
483     spet_firq_disabled = 0;
484 
485     petmem_map_reg = 0;
486     petmem_ramON = 0;
487 #if DEBUG_DONGLE
488     printf("reset 6702\n");
489 #endif
490     reset6702();
491 }
492 
superpet_mem_powerup(void)493 static void superpet_mem_powerup(void)
494 {
495 /* Those two are not reset by a soft reset (/RES), only by power down */
496     spet_diag = 0;
497     spet_ramwp = 0;     /* should look at hardware switch */
498 }
499 
petmem_superpet_diag(void)500 int petmem_superpet_diag(void)
501 {
502     return petres.superpet && spet_diag;
503 }
504 
read_super_io(uint16_t addr)505 static uint8_t read_super_io(uint16_t addr)
506 {
507     if (addr >= 0xeff4) {       /* unused / readonly */
508         return last_access;
509     } else if (addr >= 0xeff0) {       /* ACIA */
510         last_access = acia1_read((uint16_t)(addr & 0x03));
511     } else if ((addr & 0x0010) == 0) {
512         /* Dongle E F xxx0 xxxx, see zimmers.net,
513          * schematics/computers/pet/SuperPET/324055.gif.
514          * Typical address is $EFE0, possibly EFE0...3.
515          */
516         if (addr >= 0xefe0 && addr < 0xefe4) {
517             last_access = read6702();
518 #if DEBUG_DONGLE
519             log_message(pet_mem_log, "*** DONGLE %04x -> 0x%02X %3d", addr, last_access, last_access);
520 #endif /* DEBUG_DONGLE */
521         } else {
522             last_access = 0xff;
523         }
524     }
525     return last_access;   /* fallback */
526 }
527 
store_super_io(uint16_t addr,uint8_t value)528 static void store_super_io(uint16_t addr, uint8_t value)
529 {
530     last_access = value;
531 
532     if (addr >= 0xeffe) {       /* RAM/ROM switch */
533         spet_ramen = !(value & 1);
534         /* printf("spet_ramen := %d\n", spet_ramen); */
535     } else
536     if (addr >= 0xeffc) {       /* Bank select */
537         set_spet_bank(value & 0x0F);
538         spet_firq_disabled = (value & 0x20);
539         spet_flat_mode = (value & 0x40);
540         spet_ctrlwp = !(value & 0x80);
541         /* printf("spet_bank := %x  ", spet_bank);
542            printf("spet_flat_mode := %d  ", !!spet_flat_mode);
543            printf("spet_firq_disabled := %d  ", !!spet_firq_disabled);
544            printf("spet_ctrlwp := %d\n", !!spet_ctrlwp); */
545         if (spet_flat_mode) {
546             /* This is for the extra TPUG-designed Super OS/9 MMU.
547              * There is no need to check if this is a change in value,
548              * since in the new state there is no access to I/O;
549              * it it switched off by the SYNC instruction.
550              * See http://mikenaberezny.com/hardware/superpet/super-os9-mmu/
551              */
552             mem_initialize_memory_6809_flat();
553             /* mon_bank(e_default_space, "extram");
554                extern WORD PC;
555                 printf("next opcode: %04X: banked %02X, flat %02X\n",
556                        PC,
557                        mem_ram[EXT_RAM + spet_bank_4k + (PC & 0x0FFF)],
558                        mem_ram[EXT_RAM + PC]
559                   ); */
560         }
561         /* else if (spet_bank_4k != old_spet_bank_4k) {
562          *      maincpu_resync_limits(); notyet: 6809 doesn't use bank_base yet.
563          * }
564          */
565     } else {
566         if (addr >= 0xeff8) {
567             if (!spet_ctrlwp) {
568                 if (!(value & 1)) {
569                     log_error(pet_mem_log, "SuperPET: switching to 6809 not emulated!");
570                     machine_trigger_reset(MACHINE_RESET_MODE_SOFT);
571                 }
572                 spet_ramwp = !(value & 0x2);    /* IF hardware w/p switch is PROG */
573                 /* printf("spet_ramwp := %d\n", spet_ramwp); */
574                 spet_diag = (value & 0x8);
575             }
576         } else
577         if (addr >= 0xeff4) {   /* unused */
578         } else
579         if (addr >= 0xeff0) {   /* ACIA */
580             acia1_store((uint16_t)(addr & 0x03), value);
581         } else if (addr >= 0xefe0 && addr < 0xefe4) { /* dongle */
582 #if DEBUG_DONGLE
583             log_message(pet_mem_log, "*** DONGLE %04x := %02X %3d", addr, value, value);
584 #endif
585             write6702(value);
586         }
587     }
588 }
589 
read_super_9(uint16_t addr)590 static uint8_t read_super_9(uint16_t addr)
591 {
592     if (spet_ramen) {
593         last_access = spet_bank_ptr[addr & 0x0fff];
594     } else {
595         last_access = rom_read(addr);
596     }
597     return last_access;
598 }
599 
store_super_9(uint16_t addr,uint8_t value)600 static void store_super_9(uint16_t addr, uint8_t value)
601 {
602     last_access = value;
603 
604     if (spet_ramen && !spet_ramwp) {
605         spet_bank_ptr[addr & 0x0fff] = value;
606     }
607 }
608 
read_super_flat(uint16_t addr)609 static uint8_t read_super_flat(uint16_t addr)
610 {
611     last_access = (mem_ram + EXT_RAM)[addr];
612     return last_access;
613 }
614 
store_super_flat(uint16_t addr,uint8_t value)615 static void store_super_flat(uint16_t addr, uint8_t value)
616 {
617     last_access = value;
618     (mem_ram + EXT_RAM)[addr] = value;
619 }
620 
621 
622 /* ------------------------------------------------------------------------- */
623 
624 /* Generic memory access.  */
625 
mem_store(uint16_t addr,uint8_t value)626 void mem_store(uint16_t addr, uint8_t value)
627 {
628     _mem_write_tab_ptr[addr >> 8](addr, value);
629 }
630 
mem_read(uint16_t addr)631 uint8_t mem_read(uint16_t addr)
632 {
633     return _mem_read_tab_ptr[addr >> 8](addr);
634 }
635 
636 #define PRINT_6809_STORE        0
637 #define PRINT_6809_READ         0
638 
mem6809_store(uint16_t addr,uint8_t value)639 void mem6809_store(uint16_t addr, uint8_t value)
640 {
641 #if PRINT_6809_STORE
642     if (addr >= 0x8000 && addr < 0x9000) {
643         printf("mem6809_store   %04x <- %02x\n", addr, value);
644     }
645 #endif
646     _mem6809_write_tab_ptr[addr >> 8](addr, value);
647 }
648 
mem6809_read(uint16_t addr)649 uint8_t mem6809_read(uint16_t addr)
650 {
651 #if PRINT_6809_READ
652     uint8_t v;
653     v = _mem6809_read_tab_ptr[addr >> 8](addr);
654     printf("mem6809_read   %04x -> %02x\n", addr, v);
655     return v;
656 #else
657     return _mem6809_read_tab_ptr[addr >> 8](addr);
658 #endif
659 }
660 
mem6809_store16(uint16_t addr,uint16_t value)661 void mem6809_store16(uint16_t addr, uint16_t value)
662 {
663 #if PRINT_6809_STORE0
664     printf("mem6809_store16 %04x <- %04x\n", addr, value);
665 #endif
666     addr++;
667     _mem6809_write_tab_ptr[addr >> 8](addr, (uint8_t)(value & 0xFF));
668     addr--;
669     _mem6809_write_tab_ptr[addr >> 8](addr, (uint8_t)(value >> 8));
670 }
671 
mem6809_read16(uint16_t addr)672 uint16_t mem6809_read16(uint16_t addr)
673 {
674     uint16_t val;
675     val = _mem6809_read_tab_ptr[addr >> 8](addr) << 8;
676     addr++;
677     val |= _mem6809_read_tab_ptr[addr >> 8](addr);
678 #if PRINT_6809_READ
679     printf("mem6809_read16 %04x -> %04x\n", addr, val);
680 #endif
681     return val;
682 }
683 
684 #ifdef H6309
mem6809_store32(uint16_t addr,uint32_t value)685 void mem6809_store32(uint16_t addr, uint32_t value)
686 {
687 #if PRINT_6809_STORE0
688     printf("mem6809_store32 %04x <- %04x\n", addr, value);
689 #endif
690     addr += 3;
691     _mem6809_write_tab_ptr[addr >> 8](addr, (uint8_t)(value & 0xFF));
692     addr--;
693     _mem6809_write_tab_ptr[addr >> 8](addr, (uint8_t)((value >> 8) & 0xFF));
694     addr--;
695     _mem6809_write_tab_ptr[addr >> 8](addr, (uint8_t)((value >> 16) & 0xFF));
696     addr--;
697     _mem6809_write_tab_ptr[addr >> 8](addr, (uint8_t)(value >> 24));
698 }
699 
mem6809_read32(uint16_t addr)700 uint32_t mem6809_read32(uint16_t addr)
701 {
702     uint32_t val;
703     val = _mem6809_read_tab_ptr[addr >> 8](addr) << 24;
704     addr++;
705     val |= _mem6809_read_tab_ptr[addr >> 8](addr) << 16;
706     addr++;
707     val |= _mem6809_read_tab_ptr[addr >> 8](addr) << 8;
708     addr++;
709     val |= _mem6809_read_tab_ptr[addr >> 8](addr);
710 #if PRINT_6809_READ
711     printf("mem6809_read32 %04x -> %04x\n", addr, val);
712 #endif
713     return val;
714 }
715 #endif
716 
717 /* ------------------------------------------------------------------------- */
718 
719 /* The PET have all I/O chips connected to the same select lines.  Only one
720    address lines is used as separate (high-active) select input.  I.e. PIA1
721    always reacts when address & 0x10 is high, for example $e810, $e830,
722    $e850, etc.  PIA2 reacts when address & 0x20 is high, for example $e820,
723    $e830 $e860,...  The next two functions try to reflect this behaviour.  */
724 
725 /* When we write, we write all involved chips.  */
726 
store_io_e8(uint16_t addr,uint8_t value)727 static void store_io_e8(uint16_t addr, uint8_t value)
728 {
729     last_access = value;
730 
731     if (addr & 0x10) {
732         pia1_store(addr, value);
733     }
734 
735     if (addr & 0x20) {
736         pia2_store(addr, value);
737     }
738 
739     if (addr & 0x40) {
740         via_store(addr, value);
741     }
742 
743     if ((addr & 0x80) && petres.crtc) {
744         crtc_store(addr, value);
745         crtc_store_hre(addr, value);
746     }
747 }
748 
749 
750 /*
751  * When we read, we only read sensible values. In real operation,
752  * the bus drivers of all involved chips interact and you get strange
753  * results...
754  */
read_io_e8(uint16_t addr)755 static uint8_t read_io_e8(uint16_t addr)
756 {
757     uint8_t v1, v2, v3, v4;
758 
759     switch (addr & 0xf0) {
760         case 0x10:              /* PIA1 */
761             last_access = pia1_read(addr);
762             break;
763         case 0x20:              /* PIA2 */
764             last_access = pia2_read(addr);
765             break;
766         case 0x40:
767             last_access = via_read(addr); /* VIA */
768             break;
769         case 0x80:              /* CRTC */
770             if (petres.crtc) {
771                 last_access = crtc_read(addr);
772             } /* fall through */
773         case 0x00:
774             return last_access;
775         default:                /* 0x30, 0x50, 0x60, 0x70, 0x90-0xf0 */
776             if (addr & 0x10) {
777                 v1 = pia1_read(addr);
778             } else {
779                 v1 = 0xff;
780             }
781             if (addr & 0x20) {
782                 v2 = pia2_read(addr);
783             } else {
784                 v2 = 0xff;
785             }
786             if (addr & 0x40) {
787                 v3 = via_read(addr);
788             } else {
789                 v3 = 0xff;
790             }
791             v4 = 0xff;
792             if ((addr & 0x80) && petres.crtc) {
793                 v4 = crtc_read(addr);
794             }
795             last_access = v1 & v2 & v3 & v4;
796     }
797     return last_access;
798 }
799 
store_void(uint16_t addr,uint8_t value)800 static void store_void(uint16_t addr, uint8_t value)
801 {
802     last_access = value;
803 }
804 
805 /*
806  * store_dummy() stores in normally-unassigned memory space,
807  * except that some hardware expansions may be there.
808  * For adresses < 0x8000 it is faster to use store_void().
809  */
store_dummy(uint16_t addr,uint8_t value)810 static void store_dummy(uint16_t addr, uint8_t value)
811 {
812     last_access = value;
813 }
814 
store_io_88_8f(uint16_t addr,uint8_t value)815 static void store_io_88_8f(uint16_t addr, uint8_t value)
816 {
817     last_access = value;
818 
819     switch (addr & 0xff00) {
820         case 0x8800:
821             petio_8800_store(addr, value);
822             break;
823         case 0x8900:
824             petio_8900_store(addr, value);
825             break;
826         case 0x8a00:
827             petio_8a00_store(addr, value);
828             break;
829         case 0x8b00:
830             petio_8b00_store(addr, value);
831             break;
832         case 0x8c00:
833             petio_8c00_store(addr, value);
834             break;
835         case 0x8d00:
836             petio_8d00_store(addr, value);
837             break;
838         case 0x8e00:
839             petio_8e00_store(addr, value);
840             break;
841         case 0x8f00:
842             petio_8f00_store(addr, value);
843             break;
844     }
845 }
846 
store_io_e9_ef(uint16_t addr,uint8_t value)847 static void store_io_e9_ef(uint16_t addr, uint8_t value)
848 {
849     last_access = value;
850 
851     switch (addr & 0xff00) {
852         case 0xe900:
853             petio_e900_store(addr, value);
854             break;
855         case 0xea00:
856             petio_ea00_store(addr, value);
857             break;
858         case 0xeb00:
859             petio_eb00_store(addr, value);
860             break;
861         case 0xec00:
862             petio_ec00_store(addr, value);
863             break;
864         case 0xed00:
865             petio_ed00_store(addr, value);
866             break;
867         case 0xee00:
868             petio_ee00_store(addr, value);
869             break;
870         case 0xef00:
871             petio_ef00_store(addr, value);
872             break;
873     }
874 }
875 
876 /*
877  * This sets the standard PET memory configuration from $9000-$10000.
878  * It is used in store_8x96() and mem_initialize_memory().
879  *
880 [/NO ROM = 1; see page 12 for more cases]
881 +-----+--------+------------+-------------------------------------------------+
882 |     |Control |            |                                                 |
883 |     |Register|            |      main memory $8000 - $FFFF        [UB1-UB8] |
884 |     |        |            |      [$0000 - $7FFF is always RAM from UB1-UB8] |
885 |     |$FFF0   |            |                                                 |
886 +-----+--------+------------+-------------------------------------------------+
887 |     |    I/O |___ ___ ___ |              E000                               |
888 | ___ |    peek|RAM RAM RAM | E800  F000  -E7FF  B000  A000  9000  8000       |
889 | NO_ |    thr.|___ ___ ___ |              E900                               |
890 | ROM |CR7 CR6 |ON  S.9 S.A |-E8FF -FFFF  -EFFF -DFFF -AFFF -9FFF -8FFF       |
891 +-----+--------+------------+-------------------------------------------------+
892 |     |        |            |                                                 |
893 |  1  | 0   X  | 1   1   1  | I/O  Kernal Editor BASIC EPROM EPROM SCREEN     |
894 |     |        |            |                                                 |
895 |  1  | 0   X  | 1   1   0  | I/O  Kernal Editor BASIC  RAM  EPROM SCREEN     |
896 |     |        |            |                               +-----+           |
897 |  1  | 0   X  | 1   0   1  | I/O  Kernal Editor BASIC EPROM  RAM  SCREEN     |
898 |     |        |            |                         +-----+                 |
899 |  1  | 0   X  | 1   0   0  | I/O  Kernal Editor BASIC  RAM   RAM  SCREEN     |
900 |     |        |            |                   +-----+                       |
901 |  1  | 0   X  | 0   1   1  | I/O  Kernal Editor  RAM   RAM   RAM  SCREEN     |
902 |     |        |            |            +------+                             |
903 |  1  | 0   X  | 0   0   1  | I/O  Kernal  RAM    RAM   RAM   RAM  SCREEN     |
904 |     |        |            |     +------+                                    |
905 |  1  | 0   1  | 0   X   0  | I/O   RAM    RAM    RAM   RAM   RAM  SCREEN     |
906 |     |        |            |+----+                                           |
907 |  1  | 0   0  | 0   X   0  | RAM   RAM    RAM    RAM   RAM   RAM  SCREEN     |
908 |     |        |            |                                                 |
909 +-----+--------+------------+-------------------------------------------------+
910 SCREEN: 2000 bytes for screen memory, and 2096 bytes of available RAM.
911  *
912  */
913 
set_std_9tof(void)914 static void set_std_9tof(void)
915 {
916     int i, l;
917     void (*store)(uint16_t, uint8_t);
918     uint8_t (*fetch)(uint16_t);
919     int ram9, ramA, ramBCD, ramE, ramE8, ramF;
920 
921     /* printf("set_std_9tof: petres.ramSize=%d, petres.map=%d\n", petres.ramSize, petres.map); */
922     if (petres.map == PET_MAP_8296) {
923         store = ram_store;
924 
925         if (petmem_ramON) {
926             ram9 = ramA = ramBCD = 1;
927             ramE = petres.ramsel9 || petres.ramselA;
928             ramE8 = petres.ramselA && !(petmem_map_reg & FFF0_IO_PEEK_THROUGH);
929             ramF = petres.ramselA;
930             /*
931              * XXX: If there is no I/O peek through, how can we write
932              * again to the E888 register to restore I/O?
933              */
934         } else {
935             ram9 = petres.ramsel9;
936             ramA = petres.ramselA;
937             ramBCD = ramE = ramE8 = ramF = 0;
938         }
939     } else {
940         store = store_dummy;
941         ram9 = ramA = ramBCD = ramE = ramE8 = ramF = 0;
942     }
943 
944     /* Setup RAM/ROM at $9000 - $9FFF. */
945     if (petres.superpet) {
946         for (i = 0x90; i < 0xa0; i++) {
947             _mem_read_tab[i] = read_super_9;
948             _mem_write_tab[i] = store_super_9;
949             _mem_read_base_tab[i] = NULL;
950             mem_read_limit_tab[i] = 0;
951         }
952     } else {
953         fetch = ram9 ? ram_read : rom_read;
954         for (i = 0x90; i < 0xa0; i++) {
955             _mem_read_tab[i] = fetch;
956             _mem_write_tab[i] = store;
957             _mem_read_base_tab[i] = NULL;
958             mem_read_limit_tab[i] = 0;
959         }
960     }
961 
962     /* Possibly set up the Double-W HiRes board at $9000 - $9FFF. */
963     if (petdww_enabled && petdww_mem_at_9000()) {
964         petdww_override_std_9toa(_mem_read_tab, _mem_write_tab,
965                                  _mem_read_base_tab, mem_read_limit_tab);
966     }
967 
968     /* Setup RAM/ROM at $A000 - $AFFF. */
969     fetch = ramA ? ram_read : rom_read;
970     for (i = 0xa0; i < 0xb0; i++) {
971         _mem_read_tab[i] = fetch;
972         _mem_write_tab[i] = store;
973         _mem_read_base_tab[i] = NULL;
974         mem_read_limit_tab[i] = 0;
975     }
976 
977     /* Setup RAM/ROM at $B000 - $DFFF: Basic. */
978     fetch = ramBCD ? ram_read : rom_read;
979     for (i = 0xb0; i <= 0xdf; i++) {
980         _mem_read_tab[i] = fetch;
981         _mem_write_tab[i] = store;
982         _mem_read_base_tab[i] = NULL;
983         mem_read_limit_tab[i] = 0;
984     }
985 
986     /* Setup RAM/ROM at $E000 - $E7FF: Editor. */
987     fetch = ramE ? ram_read : rom_read;
988     for (i = 0xe0; i <= 0xe7; i++) {
989         _mem_read_tab[i] = fetch;
990         _mem_write_tab[i] = store;
991         _mem_read_base_tab[i] = NULL;
992         mem_read_limit_tab[i] = 0;
993     }
994 
995     /* End of I/O address space */
996     l = ((0xe800 + petres.IOSize) >> 8) & 0xff;
997 
998     if (ramE8) {
999         /* Setup RAM at $E800 - $E800 + petres.IOSize. */
1000         for (i = 0xe0; i < l; i++) {
1001             _mem_read_tab[i] = ram_read;
1002             _mem_write_tab[i] = store;
1003             _mem_read_base_tab[i] = NULL;
1004             mem_read_limit_tab[i] = 0;
1005         }
1006     } else {
1007         /* Setup I/O at $e800 - $e800 + petres.IOSize. */
1008         /* i.e. IO at $e800... */
1009         _mem_read_tab[0xe8] = read_io_e8;
1010         _mem_write_tab[0xe8] = store_io_e8;
1011         _mem_read_base_tab[0xe8] = NULL;
1012         mem_read_limit_tab[0xe8] = 0;
1013 
1014         /* ... and unused address space following it, if any. */
1015         for (i = 0xe9; i < l; i++) {
1016             _mem_read_tab[i] = read_io_e9_ef;
1017             _mem_write_tab[i] = store_io_e9_ef;
1018             _mem_read_base_tab[i] = NULL;
1019             mem_read_limit_tab[i] = 0;
1020         }
1021     }
1022 
1023     /* Setup RAM/ROM at $E800 + petres.IOSize - $EFFF: Extended Editor */
1024     fetch = ramE ? ram_read : rom_read;
1025     for (i = l; i <= 0xef; i++) {
1026         _mem_read_tab[i] = fetch;
1027         _mem_write_tab[i] = store;
1028         _mem_read_base_tab[i] = NULL;
1029         mem_read_limit_tab[i] = 0;
1030     }
1031 
1032     /*
1033      * $EF00 is needed for SuperPET I/O or 2001 ROM patch.
1034      * This means that those models can't support an extended editor ROM.
1035      */
1036     if (petres.superpet) {
1037         _mem_read_tab[0xef] = read_super_io;
1038         _mem_write_tab[0xef] = store_super_io;
1039         _mem_read_base_tab[0xef] = NULL;
1040         mem_read_limit_tab[0xef] = 0;
1041     } else if (petres.rompatch) {
1042         _mem_read_tab[0xef] = mem_read_patchbuf;
1043         _mem_write_tab[0xef] = store_void;
1044         _mem_read_base_tab[0xef] = NULL;
1045         mem_read_limit_tab[0xef] = 0;
1046     }
1047 
1048     /* Setup RAM/ROM at $f000 - $ffff: Kernal */
1049     fetch = ramF ? ram_read : rom_read;
1050     for (i = 0xf0; i <= 0xff; i++) {
1051         _mem_read_tab[i] = fetch;
1052         _mem_write_tab[i] = store;
1053         _mem_read_base_tab[i] = NULL;
1054         mem_read_limit_tab[i] = 0;
1055     }
1056 
1057     _mem_read_base_tab_ptr = _mem_read_base_tab;
1058     mem_read_limit_tab_ptr = mem_read_limit_tab;
1059 }
1060 
ramsel_changed()1061 void ramsel_changed()
1062 {
1063     set_std_9tof();
1064     maincpu_resync_limits();
1065 }
1066 
get_mem_access_tables(read_func_ptr_t ** read,store_func_ptr_t ** write,uint8_t *** base,int ** limit)1067 void get_mem_access_tables(read_func_ptr_t **read, store_func_ptr_t **write, uint8_t ***base, int **limit)
1068 {
1069     *read = _mem_read_tab;
1070     *write = _mem_write_tab;
1071     *base = _mem_read_base_tab;
1072     *limit = mem_read_limit_tab;
1073 }
1074 
mem_toggle_watchpoints(int flag,void * context)1075 void mem_toggle_watchpoints(int flag, void *context)
1076 {
1077     if (flag) {
1078         _mem_read_tab_ptr = _mem_read_tab_watch;
1079         _mem_write_tab_ptr = _mem_write_tab_watch;
1080         _mem6809_read_tab_ptr = _mem6809_read_tab_watch;
1081         _mem6809_write_tab_ptr = _mem6809_write_tab_watch;
1082     } else {
1083         _mem_read_tab_ptr = _mem_read_tab;
1084         _mem_write_tab_ptr = _mem_write_tab;
1085         _mem6809_read_tab_ptr = _mem6809_read_tab;
1086         _mem6809_write_tab_ptr = _mem6809_write_tab;
1087     }
1088 }
1089 
1090 /*
1091  * From PETdoc.txt:
1092  *
1093  * $fff0 register in PET 8x96
1094  * 8096 exp-mem (64K):
1095  * The control register is at $FFF0/65520
1096  * You have 4 16K-banks, 0...3
1097  *
1098  * $8000     $9000               $C000           $E800    $F000     $FFFF
1099  * !----------------------------!!--------------------------------------!
1100  *         Bank 0 or 2                     Bank 1 or 3
1101  * !--------!                                    !-------!
1102  *   screen                                        io
1103  *
1104  * Control Register $FFF0:
1105  * bit 7:  0 normal 8032 configuration (screen, ROMs, IO, ROMs)
1106  *        80 expansion memory
1107  * bit 6:  0 RAM $E800-$EFFF (only when bit7=1)
1108  *        40 IO peek through
1109  * bit 5:  0 exp-mem $8000-$8FFF (-"-)
1110  *        20 screen peek through
1111  * bit 4: 10 not used
1112  * bit 3:  0 bank 1 $C000-$FFFF
1113  *        08 bank 3
1114  * bit 2:  0 bank 0 $8000-$BFFF
1115  *        04 bank 2
1116  * bit 1: 02 write protect bank 1/3
1117  * bit 0: 01 write protect bank 0/2
1118  * when bit7=0, all other bits are ignored
1119  *
1120  * The missing 32K can't be accessed witout hardware modifications.
1121  * You can only use the 2K "behind" the screen $8800-$8FFF (exact: 34768-
1122  * 36863), available in the normal configuration.
1123  * The register is write-only, and the value is written through to the
1124  * previously selected ram bank.
1125  *
1126  */
1127 
1128 #define FFF0_BANK_C      0x08
1129 #define FFF0_BANK_8      0x04
1130 #define FFF0_BANK_C_WP   0x02
1131 #define FFF0_BANK_8_WP   0x01
1132 
1133 /* Save old store function for last byte.  */
1134 static void (*store_ff)(uint16_t addr, uint8_t value) = NULL;
1135 
1136 /* Write to last page of memory in 8x96.  */
store_8x96(uint16_t addr,uint8_t value)1137 static void store_8x96(uint16_t addr, uint8_t value)
1138 {
1139     uint8_t changed;
1140     int l, protected;
1141 
1142     last_access = value;
1143 
1144     if (store_ff) {
1145         store_ff(addr, value);
1146     }
1147 
1148     changed = petmem_map_reg ^ value;
1149 
1150     if (addr == 0xfff0 && changed &&
1151         ((petmem_map_reg | changed) & FFF0_ENABLED)) {
1152         if (value & FFF0_ENABLED) {     /* ext. RAM enabled */
1153             /* A5 = FFF0_ENABLED | FFF0_SCREEN_PEEK_THROUGH |
1154              *      FFF0_BANK_8 | FFF0_BANK_8_WP
1155              */
1156             if (changed & 0xa5) {       /* $8000-$bfff */
1157                 protected = value & FFF0_BANK_8_WP;
1158                 l = 0x80;
1159                 if (value & FFF0_SCREEN_PEEK_THROUGH) {
1160                     /* screen memory mapped through */
1161                     for (; l < 0x90; l++) {
1162                         _mem_read_tab[l] = ram_read;
1163                         _mem_write_tab[l] = ram_store;
1164                         _mem_read_base_tab[l] = NULL;
1165                         mem_read_limit_tab[l] = 0;
1166                     }
1167                 }
1168                 bank8offset = 0x8000 + ((value & FFF0_BANK_8) ? 0x8000 : 0);
1169                 for (; l < 0xc0; l++) {
1170                     _mem_read_tab[l] = read_ext8;
1171                     if (protected) {
1172                         _mem_write_tab[l] = store_dummy;
1173                     } else {
1174                         _mem_write_tab[l] = store_ext8;
1175                     }
1176                     _mem_read_base_tab[l] = NULL;
1177                     mem_read_limit_tab[l] = 0;
1178                 }
1179                 maincpu_resync_limits();
1180             }
1181             /* CA = FFF0_ENABLED | FFF0_IO_PEEK_THROUGH |
1182              *       FFF0_BANK_C | FFF0_BANK_C_WP
1183              */
1184             if (changed & 0xca) {       /* $c000-$ffff */
1185                 protected = value & FFF0_BANK_C_WP;
1186                 bankCoffset = 0x8000 + ((value & FFF0_BANK_C) ? 0x8000 : 0);
1187                 for (l = 0xc0; l < 0x100; l++) {
1188                     if ((l == 0xe8) && (value & FFF0_IO_PEEK_THROUGH)) {
1189                         _mem_read_tab[l] = read_io_e8;
1190                         _mem_write_tab[l] = store_io_e8;
1191                         _mem_read_base_tab[l] = NULL;
1192                         mem_read_limit_tab[l] = 0;
1193                     } else {
1194                         _mem_read_tab[l] = read_extC;
1195                         if (protected) {
1196                             _mem_write_tab[l] = store_dummy;
1197                         } else {
1198                             _mem_write_tab[l] = store_extC;
1199                         }
1200                         _mem_read_base_tab[l] = NULL;
1201                         mem_read_limit_tab[l] = 0;
1202                     }
1203                 }
1204                 store_ff = _mem_write_tab[0xff];
1205                 _mem_write_tab[0xff] = store_8x96;
1206                 maincpu_resync_limits();
1207             }
1208         } else {                /* disable ext. RAM */
1209             petmem_set_vidmem();
1210             set_std_9tof();
1211             store_ff = _mem_write_tab[0xff];
1212             _mem_write_tab[0xff] = store_8x96;
1213             maincpu_resync_limits();
1214         }
1215         petmem_map_reg = value;
1216     }
1217 }
1218 
fff0_dump(void)1219 static int fff0_dump(void)
1220 {
1221     mon_out("%s memory mapping.\n",
1222             (petres.map == PET_MAP_8296 ? "8296" :
1223              petres.map == PET_MAP_8096 ? "8096" :
1224              petres.map == PET_MAP_LINEAR ? "plain" :
1225              "unknown"));
1226     mon_out("fff0 = %02x: ", petmem_map_reg);
1227     if (petmem_map_reg & FFF0_ENABLED) {
1228         mon_out("enabled, ");
1229         if (petmem_map_reg & FFF0_IO_PEEK_THROUGH) {
1230             mon_out("I/O peek through, ");
1231         }
1232         if (petmem_map_reg & FFF0_SCREEN_PEEK_THROUGH) {
1233             mon_out("screen peek through, ");
1234         }
1235         if (petmem_map_reg & 0x10) {
1236             mon_out("$10 unused bit set, ");
1237         }
1238         mon_out("\nC000-FFFF: bank %d %s, ",
1239                 ((petmem_map_reg & FFF0_BANK_C) ? 3 : 1),
1240                 ((petmem_map_reg & FFF0_BANK_C_WP) ? "(write protected)" : "(r/w)")
1241                 );
1242         mon_out("8000-BFFF: bank %d %s.\n",
1243                 ((petmem_map_reg & FFF0_BANK_8) ? 2 : 0),
1244                 ((petmem_map_reg & FFF0_BANK_8_WP) ? "(write protected)" : "(r/w)")
1245                 );
1246     } else {
1247         mon_out("disabled.\n");
1248     }
1249     return 0;
1250 }
1251 
1252 /* ------------------------------------------------------------------------- */
1253 
petmem_set_vidmem(void)1254 void petmem_set_vidmem(void)
1255 {
1256     int i, l;
1257 
1258     l = ((0x8000 + petres.videoSize) >> 8) & 0xff;
1259 /*
1260     log_message(pet_mem_log, "petmem_set_vidmem(videoSize=%04x, l=%d)",
1261                 petres.videoSize,l);
1262 */
1263     /* Setup RAM from $8000 to $8000 + petres.videoSize ($8400 or $8800) */
1264     for (i = 0x80; i < l; i++) {
1265         _mem_read_tab[i] = ram_read;
1266         _mem_write_tab[i] = ram_store;
1267         _mem_read_base_tab[i] = NULL;
1268         mem_read_limit_tab[i] = 0;
1269     }
1270 
1271     /* Setup video mirror from $8000 + petres.videoSize to $87ff */
1272     /* falls through if videoSize >= 0x800 */
1273     for (; i < 0x88; i++) {
1274         _mem_read_tab[i] = read_vmirror;
1275         _mem_write_tab[i] = store_vmirror;
1276         _mem_read_base_tab[i] = NULL;
1277         mem_read_limit_tab[i] = 0;
1278     }
1279 
1280     if (pet_colour_type == PET_COLOUR_TYPE_OFF) {
1281         /* Setup unused from $8800 to $8FFF */
1282         /* falls through if videoSize >= 0x1000 */
1283         for (; i < 0x90; i++) {
1284             _mem_read_tab[i] = read_io_88_8f;
1285             _mem_write_tab[i] = store_io_88_8f;
1286             _mem_read_base_tab[i] = NULL;
1287             mem_read_limit_tab[i] = 0;
1288         }
1289     } else {
1290         /* Setup colour RAM from $8800 to $8BFF or $8FFF */
1291         int c = 0x8000 + COLOUR_MEMORY_START;
1292         i = (c >> 8) & 0xff;
1293         l = ((c + petres.videoSize) >> 8) & 0xff;
1294         if (l > 0x90) { /* compatibility with 8296 */
1295             l = 0x90;
1296         }
1297 
1298         for (; i < l; i++) {
1299             _mem_read_tab[i] = ram_read;
1300             _mem_write_tab[i] = ram_store;
1301             _mem_read_base_tab[i] = NULL;
1302             mem_read_limit_tab[i] = 0;
1303         }
1304 
1305         /* Setup colour mirror from $8800 + petres.videoSize to $8FFF */
1306         /* falls through if videoSize >= 0x800 */
1307         for (; i < 0x90; i++) {
1308             _mem_read_tab[i] = read_vmirror;
1309             _mem_write_tab[i] = store_vmirror;
1310             _mem_read_base_tab[i] = NULL;
1311             mem_read_limit_tab[i] = 0;
1312         }
1313     }
1314 }
1315 
1316 /* ------------------------------------------------------------------------- */
1317 
mem_initialize_memory_6809_banked(void)1318 static void mem_initialize_memory_6809_banked(void)
1319 {
1320     int i;
1321 
1322     /* extern WORD iPC; printf("mem_initialize_memory_6809_banked %04x bank %x\n", iPC, spet_bank); */
1323     for (i = 0x00; i < 0xa0; i++) {
1324         _mem6809_read_tab[i] = _mem_read_tab[i];
1325         _mem6809_write_tab[i] = _mem_write_tab[i];
1326         _mem6809_read_base_tab[i] = _mem_read_base_tab[i];
1327         mem6809_read_limit_tab[i] = mem_read_limit_tab[i];
1328     }
1329     /*
1330      * Set up the ROMs.
1331      */
1332     for (i = 0xa0; i < 0xe8; i++) {
1333         _mem6809_read_tab[i] = rom6809_read;
1334         _mem6809_write_tab[i] = store_void;
1335         _mem6809_read_base_tab[i] = mem_6809rom + i - (ROM6809_BASE >> 8);
1336         mem6809_read_limit_tab[i] = 0xe7fc;
1337     }
1338     for (i = 0xf0; i < 0x100; i++) {
1339         _mem6809_read_tab[i] = rom6809_read;
1340         _mem6809_write_tab[i] = store_void;
1341         _mem6809_read_base_tab[i] = mem_6809rom + i - (ROM6809_BASE >> 8);
1342         mem6809_read_limit_tab[i] = 0xfffc;
1343     }
1344     /*
1345      * Also copy the I/O setup from the 6502 view.
1346      */
1347     for (i = 0xe8; i < 0xf0; i++) {
1348         _mem6809_read_tab[i] = _mem_read_tab[i];
1349         _mem6809_write_tab[i] = _mem_write_tab[i];
1350         _mem6809_read_base_tab[i] = _mem_read_base_tab[i];
1351         mem6809_read_limit_tab[i] = mem_read_limit_tab[i];
1352     }
1353 
1354     _mem6809_read_tab[0x100] = _mem6809_read_tab[0];
1355     _mem6809_write_tab[0x100] = _mem6809_write_tab[0];
1356     _mem6809_read_base_tab[0x100] = _mem6809_read_base_tab[0];
1357     mem6809_read_limit_tab[0x100] = -1;
1358 
1359     /* maincpu_resync_limits(); notyet: 6809 doesn't use bank_base yet. */
1360 }
1361 
mem_initialize_memory_6809_flat(void)1362 static void mem_initialize_memory_6809_flat(void)
1363 {
1364     int i;
1365 
1366     /* extern WORD iPC; printf("mem_initialize_memory_6809_flat   %04X bank %x\n", iPC, spet_bank); */
1367 
1368     for (i = 0x00; i < 0x101; i++) {
1369         _mem6809_read_tab[i] = read_super_flat;
1370         _mem6809_write_tab[i] = store_super_flat;
1371         _mem6809_read_base_tab[i] = mem_ram + EXT_RAM + (i << 8);
1372         mem6809_read_limit_tab[i] = 0xfffc;
1373     }
1374 
1375     _mem6809_read_base_tab[0x100] = _mem6809_read_base_tab[0];
1376     mem6809_read_limit_tab[0x100] = -1;
1377     /* maincpu_resync_limits(); notyet: 6809 doesn't use bank_base yet. */
1378 }
1379 
mem_initialize_memory_6809()1380 void mem_initialize_memory_6809()
1381 {
1382     if (spet_flat_mode) {
1383         mem_initialize_memory_6809_flat();
1384     } else {
1385         mem_initialize_memory_6809_banked();
1386     }
1387 }
1388 
superpet_sync(void)1389 int superpet_sync(void)
1390 {
1391     if (spet_firq_disabled) {
1392         log_error(pet_mem_log, "SuperPET: SYNC encountered, but no FIRQ possible!");
1393         return 1;
1394     } else {
1395         spet_flat_mode = 0;
1396         mem_initialize_memory_6809_banked();
1397         /* mon_bank(e_default_space, "6809");
1398            extern WORD PC;
1399            printf("next opcode: %04X: banked %02X, flat %02X\n",
1400                    PC,
1401                    mem_ram[EXT_RAM + spet_bank_4k + (PC & 0x0FFF)],
1402                    mem_ram[EXT_RAM + PC]
1403               ); */
1404 
1405         return 0;
1406     }
1407 }
1408 
1409 /* This does the plain 8032 configuration, as 8096 stuff only comes up when
1410    writing to $fff0.  */
mem_initialize_memory(void)1411 void mem_initialize_memory(void)
1412 {
1413     int i, l;
1414 
1415     l = petres.ramSize << 2;       /* ramSize in kB, l in 256 Byte */
1416     if (l > (32 << 2)) {
1417         l = (32 << 2);             /* fix 8096 / 8296 */
1418     }
1419     /* Setup RAM from $0000 to petres.ramSize */
1420     _mem_read_tab[0] = zero_read;
1421     _mem_write_tab[0] = zero_store;
1422     _mem_read_base_tab[0] = NULL;
1423     mem_read_limit_tab[0] = 0;
1424 
1425     for (i = 0x01; i < l; i++) {
1426         _mem_read_tab[i] = ram_read;
1427         _mem_write_tab[i] = ram_store;
1428         _mem_read_base_tab[i] = NULL;
1429         mem_read_limit_tab[i] = 0;
1430     }
1431 
1432     /* Setup unused from petres.ramSize to $7fff */
1433     for (i = l; i < 0x80; i++) {
1434         _mem_read_tab[i] = read_unused;
1435         _mem_write_tab[i] = store_void;
1436         _mem_read_base_tab[i] = NULL;
1437         mem_read_limit_tab[i] = 0;
1438     }
1439 
1440     petmem_set_vidmem();
1441 
1442     set_std_9tof();
1443 
1444     if (petres.map) {              /* catch writes to $fff0 register */
1445         store_ff = _mem_write_tab[0xff];
1446         _mem_write_tab[0xff] = store_8x96;
1447     }
1448     _mem_read_tab[0x100] = _mem_read_tab[0];
1449     _mem_write_tab[0x100] = _mem_write_tab[0];
1450     _mem_read_base_tab[0x100] = _mem_read_base_tab[0];
1451     mem_read_limit_tab[0x100] = 0;
1452 
1453     ram_size = petres.ramSize * 1024;
1454     _mem_read_tab_ptr = _mem_read_tab;
1455     _mem_write_tab_ptr = _mem_write_tab;
1456 
1457     /* setup watchpoint tables */
1458     _mem_read_tab_watch[0] = zero_read_watch;
1459     _mem_write_tab_watch[0] = zero_store_watch;
1460     for (i = 1; i < 0x101; i++) {
1461         _mem_read_tab_watch[i] = read_watch;
1462         _mem_write_tab_watch[i] = store_watch;
1463     }
1464 
1465     if (petres.map && petmem_map_reg) {
1466         uint8_t old_map_reg;
1467 
1468         old_map_reg = petmem_map_reg;
1469         petmem_map_reg = 0;
1470         store_8x96(0xfff0, old_map_reg);
1471     } else {
1472         petmem_map_reg = 0;
1473     }
1474 
1475 
1476     if (petres.superpet) {
1477         /*
1478          * Initialize SuperPET 6809 memory view.
1479          * Basically, it is the same as the 6502 view, except for the
1480          * ROMs in addresses $A000 - $FFFF and but including the I/O range
1481          * of $E800 - $EFFF.
1482          */
1483         mem_initialize_memory_6809();
1484 
1485         for (i = 0; i < 0x101; i++) {
1486             _mem6809_read_tab_watch[i] = read6809_watch;
1487             _mem6809_write_tab_watch[i] = store6809_watch;
1488         }
1489 
1490         _mem6809_read_tab_ptr = _mem6809_read_tab;
1491         _mem6809_write_tab_ptr = _mem6809_write_tab;
1492     }
1493 
1494     maincpu_resync_limits();
1495 }
1496 
mem_mmu_translate(unsigned int addr,uint8_t ** base,int * start,int * limit)1497 void mem_mmu_translate(unsigned int addr, uint8_t **base, int *start, int *limit)
1498 {
1499     uint8_t *p = _mem_read_base_tab_ptr[addr >> 8];
1500 
1501     *base = (p == NULL) ? NULL : (p - (addr & 0xff00));
1502     *start = addr; /* TODO */
1503     *limit = mem_read_limit_tab_ptr[addr >> 8];
1504 }
1505 
mem_powerup(void)1506 void mem_powerup(void)
1507 {
1508     int i;
1509     ram_init(mem_ram, RAM_ARRAY);
1510     /*
1511      * A more realistic initial memory is random.
1512      * Especially on the screen, which is different memory in most
1513      * models.
1514      * (And it helps a bit with the colour option when a proper editor
1515      * ROM isn't installed)
1516      *
1517      * FIXME: use memory init pattern
1518      *
1519      */
1520     for (i = 0; i < 0x1000; i++) {
1521         mem_ram[0x8000 + i] = (uint8_t)lib_unsigned_rand(0, 255);
1522     }
1523 
1524     superpet_mem_powerup();
1525 }
1526 
1527 /* ------------------------------------------------------------------------- */
1528 
mem_get_basic_text(uint16_t * start,uint16_t * end)1529 void mem_get_basic_text(uint16_t *start, uint16_t *end)
1530 {
1531     int basicstart;
1532 
1533     /* FIXME: should really check a basic_checksum */
1534     if (petres.kernal_checksum == PET_KERNAL1_CHECKSUM) {
1535         basicstart = 0x7a;
1536     } else {
1537         basicstart = 0x28;
1538     }
1539 
1540     if (start != NULL) {
1541         *start = mem_ram[basicstart] | (mem_ram[basicstart + 1] << 8);
1542     }
1543     if (end != NULL) {
1544         *end = mem_ram[basicstart + 2] | (mem_ram[basicstart + 3] << 8);
1545     }
1546 }
1547 
mem_set_basic_text(uint16_t start,uint16_t end)1548 void mem_set_basic_text(uint16_t start, uint16_t end)
1549 {
1550     int basicstart, loadadr;
1551 
1552     if (petres.kernal_checksum == PET_KERNAL1_CHECKSUM) {
1553         basicstart = 0x7a;    /* Pointers to Basic program + variables */
1554         loadadr = 0xe3;       /* Utility pointers for start and end of load */
1555     } else {
1556         basicstart = 0x28;
1557         loadadr = 0xc7;
1558     }
1559 
1560     mem_ram[basicstart] = mem_ram[loadadr] = start & 0xff;
1561     mem_ram[basicstart + 1] = mem_ram[loadadr + 1] = start >> 8;
1562 
1563     mem_ram[basicstart + 2] =
1564         mem_ram[basicstart + 4] =
1565             mem_ram[basicstart + 6] = mem_ram[loadadr + 2] = end & 0xff;
1566     mem_ram[basicstart + 3] =
1567         mem_ram[basicstart + 5] =
1568             mem_ram[basicstart + 7] = mem_ram[loadadr + 3] = end >> 8;
1569 }
1570 
mem_inject(uint32_t addr,uint8_t value)1571 void mem_inject(uint32_t addr, uint8_t value)
1572 {
1573     /* just call mem_store() to be safe.
1574        This could possibly be changed to write straight into the
1575        memory array.  mem_ram[addr & mask] = value; */
1576     mem_store((uint16_t)(addr & 0xffff), value);
1577 }
1578 
1579 /* ------------------------------------------------------------------------- */
1580 
mem_rom_trap_allowed(uint16_t addr)1581 int mem_rom_trap_allowed(uint16_t addr)
1582 {
1583     return (addr >= 0xf000) && !(petmem_map_reg & 0x80);
1584 }
1585 
1586 /* ------------------------------------------------------------------------- */
1587 
1588 /* Banked memory access functions for the monitor.  */
1589 
peek_bank_io(uint16_t addr)1590 static uint8_t peek_bank_io(uint16_t addr)
1591 {
1592     uint8_t v1, v2, v3, v4;
1593 
1594     switch (addr & 0xf0) {
1595         case 0x10:              /* PIA1 */
1596             return pia1_peek(addr);
1597         case 0x20:              /* PIA2 */
1598             return pia2_peek(addr);
1599         case 0x40:
1600             return via_peek(addr); /* VIA */
1601         case 0x80:              /* CRTC */
1602             if (petres.crtc) {
1603                 return crtc_read(addr);
1604             }
1605             /* FALL THROUGH */
1606         case 0x00:
1607             return addr >> 8;
1608         default:                /* 0x30, 0x50, 0x60, 0x70, 0x90-0xf0 */
1609             break;
1610     }
1611 
1612     if (addr & 0x10) {
1613         v1 = pia1_peek(addr);
1614     } else {
1615         v1 = 0xff;
1616     }
1617     if (addr & 0x20) {
1618         v2 = pia2_peek(addr);
1619     } else {
1620         v2 = 0xff;
1621     }
1622     if (addr & 0x40) {
1623         v3 = via_peek(addr);
1624     } else {
1625         v3 = 0xff;
1626     }
1627     v4 = 0xff;
1628     if ((addr & 0x80) && petres.crtc) {
1629         v4 = crtc_read(addr);
1630     }
1631     return v1 & v2 & v3 & v4;
1632 }
1633 
1634 /* Exported banked memory access functions for the monitor.  */
1635 
1636 static const char *banknames[] = {
1637     "default", "cpu", "ram", "rom", "io", "extram", "6809", NULL
1638 };
1639 
1640 enum {
1641     bank_default, bank_cpu = 0, bank_ram, bank_rom, bank_io, bank_extram,
1642     bank_cpu6809
1643 };
1644 
1645 static const int banknums[] = {
1646     bank_default, bank_cpu, bank_ram, bank_rom, bank_io, bank_extram,
1647     bank_cpu6809,
1648 };
1649 
mem_bank_list(void)1650 const char **mem_bank_list(void)
1651 {
1652     return banknames;
1653 }
1654 
mem_bank_from_name(const char * name)1655 int mem_bank_from_name(const char *name)
1656 {
1657     int i = 0;
1658 
1659     while (banknames[i]) {
1660         if (!strcmp(name, banknames[i])) {
1661             return banknums[i];
1662         }
1663         i++;
1664     }
1665     return -1;
1666 }
1667 
mem_bank_read(int bank,uint16_t addr,void * context)1668 uint8_t mem_bank_read(int bank, uint16_t addr, void *context)
1669 {
1670     switch (bank) {
1671         case bank_default:      /* current */
1672             return mem_read(addr);
1673             break;
1674         case bank_extram:       /* extended RAM area (8x96, SuperPET) */
1675             return mem_ram[addr + EXT_RAM];
1676             break;
1677         case bank_io:          /* io */
1678             if (addr >= 0xe800 && addr < 0xe900) {
1679                 return read_io_e8(addr);
1680             }
1681             if (petres.superpet && (addr & 0xff00) == 0xef00) {
1682                 return read_super_io(addr);
1683             }
1684             if (addr >= 0xe900 && addr < 0xe800 + petres.IOSize) {
1685                 return read_io_e9_ef(addr);
1686             }
1687             /* FALL THROUGH */
1688         case bank_rom:         /* rom */
1689             if (addr >= 0x9000) {
1690                 return mem_rom[addr & 0x7fff];
1691             }
1692             break;
1693         case bank_cpu6809:     /* 6809 */
1694             return mem6809_read(addr);
1695         case bank_ram:         /* ram */
1696             break;
1697     }
1698     return mem_ram[addr];
1699 }
1700 
mem_bank_peek(int bank,uint16_t addr,void * context)1701 uint8_t mem_bank_peek(int bank, uint16_t addr, void *context)
1702 {
1703     switch (bank) {
1704         case bank_default:      /* current */
1705             return mem_read(addr); /* FIXME */
1706             break;
1707         case bank_io:           /* io */
1708             if (addr >= 0xe800 && addr < 0xe900) {
1709                 return peek_bank_io(addr);
1710             }
1711             if (petres.superpet && (addr & 0xff00) == 0xef00) {
1712                 return read_super_io(addr);
1713             }
1714             if (addr >= 0xe900 && addr < 0xe800 + petres.IOSize) {
1715                 uint8_t result;
1716                 /* is_peek_access = 1; FIXME */
1717                 result = read_unused(addr);
1718                 /* is_peek_access = 0; FIXME */
1719                 return result;
1720             }
1721     }
1722     return mem_bank_read(bank, addr, context);
1723 }
1724 
mem_bank_write(int bank,uint16_t addr,uint8_t byte,void * context)1725 void mem_bank_write(int bank, uint16_t addr, uint8_t byte, void *context)
1726 {
1727     switch (bank) {
1728         case bank_default:      /* current */
1729             mem_store(addr, byte);
1730             return;
1731         case bank_extram:       /* extended RAM area (8x96, SuperPET) */
1732             mem_ram[addr + EXT_RAM] = byte;
1733             return;
1734         case bank_io:           /* io */
1735             if (addr >= 0xe800 && addr < 0xe900) {
1736                 store_io_e8(addr, byte);
1737                 return;
1738             }
1739             if (petres.superpet && (addr & 0xff00) == 0xef00) {
1740                 store_super_io(addr, byte);
1741                 return;
1742             }
1743             if (addr >= 0xe900 && addr < 0xe800 + petres.IOSize) {
1744                 store_io_e9_ef(addr, byte);
1745                 return;
1746             }
1747             /* FALL THROUGH */
1748         case bank_rom:          /* rom */
1749             if (addr >= 0x9000) {
1750                 return;
1751             }
1752             break;
1753         case bank_cpu6809:      /* rom */
1754             mem6809_store(addr, byte);
1755             return;
1756         case 1:                 /* ram */
1757             break;
1758     }
1759     mem_ram[addr] = byte;
1760 }
1761 
mem_dump_io(void * context,uint16_t addr)1762 static int mem_dump_io(void *context, uint16_t addr)
1763 {
1764     if ((addr >= 0xe810) && (addr <= 0xe81f)) {
1765         return pia1_dump();
1766     } else if ((addr >= 0xe820) && (addr <= 0xe82f)) {
1767         return pia2_dump();
1768     } else if ((addr >= 0xe840) && (addr <= 0xe84f)) {
1769         return viacore_dump(machine_context.via);
1770     } else if ((addr >= 0xe880) && (addr <= 0xe881)) {
1771         if (petres.crtc) {
1772             return crtc_dump();
1773         }
1774     } else if (addr == 0xe888) {
1775         return e888_dump();
1776     } else if ((addr >= 0xeb00) && (addr <= 0xeb0f)) {
1777         if (petdww_enabled) {
1778             return petdwwpia_dump();
1779         }
1780     } else if (addr == 0xfff0) {
1781         if (petres.map) {
1782             return fff0_dump();
1783         }
1784     }
1785     if (petres.superpet) {
1786         if (addr >= 0xefe0 && addr <= 0xefe3) {
1787             return efe0_dump();
1788         } else if (addr >= 0xeff0 && addr <= 0xeff3) {
1789             /* ACIA */
1790             /* return aciacore_dump(); */
1791         } else if (addr == 0xeff8) {
1792             /* Control switch */
1793             mon_out("CPU: %s\n",
1794                     petres.superpet_cpu_switch == SUPERPET_CPU_6502 ? "6502" :
1795                     petres.superpet_cpu_switch == SUPERPET_CPU_6809 ? "6809" :
1796                     "PROG (unimpl)");
1797             mon_out("RAM write protect: $%x\n", spet_ramwp);
1798             mon_out("diagnostic sense: $%x\n", spet_diag);
1799             return 0;
1800         } else if (addr == 0xeffc) {
1801             /* Bank select */
1802             mon_out("bank: $%x\n", spet_bank);
1803             mon_out("control write protect: %d\n", spet_ctrlwp);
1804             mon_out("flat (super-os9) mode: %d\n", !!spet_flat_mode);
1805             mon_out("firq disabled: %d\n", !!spet_firq_disabled);
1806             return 0;
1807         } else if (addr == 0xeffe) {
1808             /* RAM/ROM switch */
1809             mon_out("ram_enable: %d\n", spet_ramen);
1810             return 0;
1811         }
1812     }
1813     return -1;
1814 }
1815 
mem_ioreg_list_get(void * context)1816 mem_ioreg_list_t *mem_ioreg_list_get(void *context)
1817 {
1818     mem_ioreg_list_t *mem_ioreg_list = NULL;
1819 
1820     io_source_ioreg_add_list(&mem_ioreg_list);
1821     mon_ioreg_add_list(&mem_ioreg_list, "PIA1", 0xe810, 0xe81f, mem_dump_io, NULL);
1822     mon_ioreg_add_list(&mem_ioreg_list, "PIA2", 0xe820, 0xe82f, mem_dump_io, NULL);
1823     mon_ioreg_add_list(&mem_ioreg_list, "VIA", 0xe840, 0xe84f, mem_dump_io, NULL);
1824     if (petres.crtc) {
1825         mon_ioreg_add_list(&mem_ioreg_list, "CRTC", 0xe880, 0xe881, mem_dump_io, NULL);
1826     }
1827     if (pethre_enabled) {
1828         mon_ioreg_add_list(&mem_ioreg_list, "HRE", 0xe888, 0xe888, mem_dump_io, NULL);
1829     }
1830     if (petres.map) {
1831         mon_ioreg_add_list(&mem_ioreg_list, "8096", 0xfff0, 0xfff0, mem_dump_io, NULL);
1832     }
1833     if (petres.superpet) {
1834         mon_ioreg_add_list(&mem_ioreg_list, "6702", 0xefe0, 0xefe3, mem_dump_io, NULL);
1835         mon_ioreg_add_list(&mem_ioreg_list, "ACIA", 0xeff0, 0xeff3, mem_dump_io, NULL);
1836         mon_ioreg_add_list(&mem_ioreg_list, "Control", 0xeff8, 0xeff8, mem_dump_io, NULL);
1837         mon_ioreg_add_list(&mem_ioreg_list, "Bank", 0xeffc, 0xeffc, mem_dump_io, NULL);
1838         mon_ioreg_add_list(&mem_ioreg_list, "RAM/ROM", 0xeffe, 0xeffe, mem_dump_io, NULL);
1839     }
1840 
1841     return mem_ioreg_list;
1842 }
1843 
petmem_get_screen_columns(void)1844 int petmem_get_screen_columns(void)
1845 {
1846     int cols;
1847 
1848     cols = petres.video;
1849     if (!cols) {
1850         cols = petres.rom_video;
1851         if (!cols) {
1852             cols = PET_COLS;
1853         }
1854     }
1855 
1856     return cols;
1857 }
1858 
petmem_get_rom_columns(void)1859 int petmem_get_rom_columns(void)
1860 {
1861     return petres.rom_video;
1862 }
1863 
mem_get_screen_parameter(uint16_t * base,uint8_t * rows,uint8_t * columns,int * bank)1864 void mem_get_screen_parameter(uint16_t *base, uint8_t *rows, uint8_t *columns, int *bank)
1865 {
1866     *base = 0x8000;
1867     *rows = 25;
1868     *columns = (uint8_t)petmem_get_screen_columns();
1869     *bank = 0;
1870 }
1871 
1872 /************************** PET resource handling ************************/
1873 
1874 /* check PetInfo struct for consistency after change? */
1875 
petmem_check_info(petres_t * pi)1876 void petmem_check_info(petres_t *pi)
1877 {
1878     if (pi->video == 40 || (pi->video == 0 && pi->rom_video == 40)) {
1879         pi->vmask = 0x3ff;
1880         pi->videoSize = 0x400;
1881     } else {
1882         pi->vmask = 0x7ff;
1883         pi->videoSize = 0x800;
1884     }
1885 
1886     if (pi->ramSize == 128) {
1887         pi->vmask = 0x1fff;
1888         pi->videoSize = 0x1000;
1889     }
1890 }
1891 
1892 /* dummy function to satisfy the global cartridge system */
cartridge_attach_image(int type,const char * name)1893 int cartridge_attach_image(int type, const char *name)
1894 {
1895     return -1;
1896 }
1897