This is c128mem.c in view mode; [Download] [Up]
/* * c128mem.c -- Memory handling for the C128 emulator. * * Written by * Ettore Perazzoli (ettore@comm2000.it) * * Based on the original work in VICE 0.11.0 by * Jouko Valta (jopi@stekt.oulu.fi) * * This file is part of VICE, the Versatile Commodore Emulator. * See README for copyright notice. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. * */ /* This is just a quick hack! */ /* TODO: - cartridge support; - maybe C64 mode? */ #include "vice.h" #include <stdio.h> #include "vmachine.h" #include "true1541.h" #include "c128mem.h" #include "resources.h" #include "cmdline.h" #include "c64cia.h" #include "sid.h" #include "memutils.h" #include "maincpu.h" #include "parallel.h" #include "c64tpi.h" #include "tapeunit.h" #include "mon.h" #include "utils.h" #include "vdc.h" #include "emuid.h" #include "rs232.h" #include "../c64/vicii.h" #ifdef HAVE_RS232 #include "c64acia.h" #endif /* #define DEBUG_MMU */ #ifdef DEBUG_MMU #define DEBUG(x) printf x #else #define DEBUG(x) #endif /* ------------------------------------------------------------------------- */ /* C128 memory-related resources. */ /* Name of the character ROM. */ static char *chargen_rom_name; /* Name of the BASIC ROM. */ static char *basic_rom_name; /* Name of the Kernal ROM. */ static char *kernal_rom_name; /* Flag: Do we enable the Emulator ID? */ static int emu_id_enabled; /* Flag: Do we enable the IEEE488 interface emulation? */ static int ieee488_enabled; /* Flag: Do we enable the external REU? */ static int reu_enabled; #ifdef HAVE_RS232 /* Flag: Do we enable the $DE** ACIA RS232 interface emulation? */ static int acia_de_enabled; /* Flag: Do we enable the $D7** ACIA RS232 interface emulation? */ static int acia_d7_enabled; #endif /* FIXME: Should load the new character ROM. */ static int set_chargen_rom_name(resource_value_t v) { const char *name = (const char *) v; if (chargen_rom_name != NULL && name != NULL && strcmp(name, chargen_rom_name) == 0) return 0; string_set(&chargen_rom_name, name); return 0; } /* FIXME: Should load the new Kernal ROM. */ static int set_kernal_rom_name(resource_value_t v) { const char *name = (const char *) v; if (kernal_rom_name != NULL && name != NULL && strcmp(name, kernal_rom_name) == 0) return 0; string_set(&kernal_rom_name, name); return 0; } /* FIXME: Should load the new BASIC ROM. */ static int set_basic_rom_name(resource_value_t v) { const char *name = (const char *) v; if (basic_rom_name != NULL && name != NULL && strcmp(name, basic_rom_name) == 0) return 0; string_set(&basic_rom_name, name); return 0; } static int set_emu_id_enabled(resource_value_t v) { if (!(int) v) { emu_id_enabled = 0; return 0; } else { emu_id_enabled = 1; return 0; } } static int set_ieee488_enabled(resource_value_t v) { if (!(int) v) { ieee488_enabled = 0; return 0; } else if (!reu_enabled) { ieee488_enabled = 1; return 0; } else { /* The REU and the IEEE488 interface share the same address space, so they cannot be enabled at the same time. */ return -1; } } /* FIXME: Should initialize the REU when turned on. */ static int set_reu_enabled(resource_value_t v) { if (!(int) v) { reu_enabled = 0; return 0; } else if (!ieee488_enabled) { reu_enabled = 1; return 0; } else { /* The REU and the IEEE488 interface share the same address space, so they cannot be enabled at the same time. */ return -1; } } #ifdef HAVE_RS232 static int set_acia_d7_enabled(resource_value_t v) { acia_d7_enabled = (int) v; return 0; } static int set_acia_de_enabled(resource_value_t v) { acia_de_enabled = (int) v; return 0; } #endif static resource_t resources[] = { { "ChargenName", RES_STRING, (resource_value_t) "chargen", (resource_value_t *) & chargen_rom_name, set_chargen_rom_name }, { "KernalName", RES_STRING, (resource_value_t) "kernal", (resource_value_t *) & kernal_rom_name, set_kernal_rom_name }, { "BasicName", RES_STRING, (resource_value_t) "basic", (resource_value_t *) & basic_rom_name, set_basic_rom_name }, { "REU", RES_INTEGER, (resource_value_t) 0, (resource_value_t *) & reu_enabled, set_reu_enabled }, { "IEEE488", RES_INTEGER, (resource_value_t) 0, (resource_value_t *) & ieee488_enabled, set_ieee488_enabled }, { "EmuID", RES_INTEGER, (resource_value_t) 0, (resource_value_t *) & emu_id_enabled, set_emu_id_enabled }, #ifdef HAVE_RS232 { "AciaDE", RES_INTEGER, (resource_value_t) 0, (resource_value_t *) & acia_de_enabled, set_acia_de_enabled }, { "AciaD7", RES_INTEGER, (resource_value_t) 0, (resource_value_t *) & acia_d7_enabled, set_acia_d7_enabled }, #endif { NULL } }; int c128_mem_init_resources(void) { return resources_register(resources); } /* ------------------------------------------------------------------------- */ /* C128 memory-related command-line options. */ static cmdline_option_t cmdline_options[] = { { "-kernal", SET_RESOURCE, 1, NULL, NULL, "KernalName", NULL, "<name>", "Specify name of Kernal ROM image" }, { "-basic", SET_RESOURCE, 1, NULL, NULL, "BasicName", NULL, "<name>", "Specify name of BASIC ROM image" }, { "-chargen", SET_RESOURCE, 1, NULL, NULL, "ChargenName", NULL, "<name>", "Specify name of character generator ROM image" }, { "-reu", SET_RESOURCE, 0, NULL, NULL, "REU", (resource_value_t) 1, NULL, "Enable the 512K RAM expansion unit" }, { "+reu", SET_RESOURCE, 0, NULL, NULL, "REU", (resource_value_t) 0, NULL, "Disable the 512K RAM expansion unit" }, { "-emuid", SET_RESOURCE, 0, NULL, NULL, "EmuID", (resource_value_t) 1, NULL, "Enable emulator identification" }, { "+emuid", SET_RESOURCE, 0, NULL, NULL, "EmuID", (resource_value_t) 0, NULL, "Disable emulator identification" }, { "-ieee488", SET_RESOURCE, 0, NULL, NULL, "IEEE488", (resource_value_t) 1, NULL, "Enable the IEEE488 interface emulation" }, { "+ieee488", SET_RESOURCE, 0, NULL, NULL, "IEEE488", (resource_value_t) 0, NULL, "Disable the IEEE488 interface emulation" }, { "-kernalrev", SET_RESOURCE, 1, NULL, NULL, "KernalRev", NULL, "<revision>", "Patch the Kernal ROM to the specified <revision>" }, #ifdef HAVE_RS232 { "-acia1", SET_RESOURCE, 0, NULL, NULL, "AciaDE", (resource_value_t) 1, NULL, "Enable the $DE** ACIA RS232 interface emulation" }, { "+acia1", SET_RESOURCE, 0, NULL, NULL, "AciaDE", (resource_value_t) 0, NULL, "Disable the $DE** ACIA RS232 interface emulation" }, #if 0 { "-acia2", SET_RESOURCE, 0, NULL, NULL, "AciaD7", (resource_value_t) 1, NULL, "Enable the $D7** ACIA RS232 interface emulation" }, { "+acia2", SET_RESOURCE, 0, NULL, NULL, "AciaD7", (resource_value_t) 0, NULL, "Disable the $D7** ACIA RS232 interface emulation" }, #endif #endif { NULL } }; int c128_mem_init_cmdline_options(void) { return cmdline_register_options(cmdline_options); } /* ------------------------------------------------------------------------- */ /* Number of possible video banks (16K each). */ #define NUM_VBANKS 4 /* The C128 memory. */ BYTE ram[C128_RAM_SIZE]; BYTE basic_rom[C128_BASIC_ROM_SIZE + C128_EDITOR_ROM_SIZE]; BYTE kernal_rom[C128_KERNAL_ROM_SIZE]; BYTE chargen_rom[C128_CHARGEN_ROM_SIZE]; /* Size of RAM... */ int ram_size = C128_RAM_SIZE; /* Currently selected RAM bank. */ static BYTE *ram_bank; /* Memory configuration. */ static int chargen_in; static int basic_lo_in; static int basic_hi_in; static int kernal_in; static int editor_in; static int io_in; /* Shared memory. */ static ADDRESS top_shared_limit, bottom_shared_limit; /* Tape sense status: 1 = some button pressed, 0 = no buttons pressed. */ static int tape_sense = 0; /* Pointers to pages 0 and 1 (which can be physically placed anywhere). */ BYTE *page_zero, *page_one; static BYTE mmu[11]; /* Flag: nonzero if the Kernal and BASIC ROMs have been loaded. */ int rom_loaded = 0; /* Memory read and write tables. These are non-static to allow the CPU code to access them. */ store_func_ptr_t _mem_write_tab[0x101]; read_func_ptr_t _mem_read_tab[0x101]; store_func_ptr_t *_mem_write_tab_ptr = _mem_write_tab; read_func_ptr_t *_mem_read_tab_ptr = _mem_read_tab; /* Fake BIOS initialization. This is required because the real C128 is normally booted by the Z80, which we currently don't emulate at all. */ static BYTE biostab[] = { 0x78, 0xa9, 0x3e, 0x8d, 0x00, 0xff, 0xa9, 0xb0, 0x8d, 0x05, 0xd5, 0xea, 0x58, 0x60, 0x00, 0x00, 0xf3, 0x3e, 0x3e, 0x32, 0x00, 0xff, 0x01, 0x05, 0xd5, 0x3e, 0xb1, 0xed, 0x79, 0x00, 0xcf }; /* Current video bank (0, 1, 2 or 3). */ static int vbank; /* ------------------------------------------------------------------------- */ /* MMU Implementation. */ inline BYTE REGPARM1 read_mmu(ADDRESS addr) { addr &= 0xff; if (addr < 0xb) { if (addr == 5) { /* 0x80 = 40/80 key released. */ return mmu[5] | 0x80; } else { return mmu[addr]; } } else { return 0xf; } } inline void REGPARM2 store_mmu(ADDRESS address, BYTE value) { address &= 0xff; if (address < 0xb) { mmu[address] = value; switch (address) { case 0: /* Configuration register (CR). */ { io_in = !(value & 0x1); basic_lo_in = !(value & 0x2); basic_hi_in = !(value & 0xc); kernal_in = chargen_in = editor_in = !(value & 0x30); /* (We handle only 128K here.) */ ram_bank = ram + (((long) value & 0x40) << 10); DEBUG(("MMU: Store CR = $%02x\n", value)); DEBUG(("MMU: RAM bank at $%05X\n", ram_bank - ram)); } break; case 6: /* RAM configuration register (RCR). */ { int shared_size; vic_ii_set_ram_base(ram + ((value & 0xc0) << 2)); DEBUG(("MMU: Store RCR = $%02x\n", value)); DEBUG(("MMU: VIC-II base at $%05X\n", ((value & 0xc0) << 2))); if (value & 0x3) shared_size = 0x1000 << (value & 0x3); else shared_size = 0x400; /* Share high memory? */ if (value & 0x8) { top_shared_limit = 0xffff - shared_size; DEBUG(("MMU: Sharing high RAM from $%04X\n", top_shared_limit + 1)); } else { top_shared_limit = 0xffff; DEBUG(("MMU: No high shared RAM\n")); } /* Share low memory? */ if (value & 0x4) { bottom_shared_limit = shared_size; DEBUG(("MMU: Sharing low RAM up to $%04X\n", bottom_shared_limit - 1)); } else { bottom_shared_limit = 0; DEBUG(("MMU: No low shared RAM\n")); } } break; case 5: value = (value & 0x7f) | 0x30; if ((value & 0x41) != 0x01) fprintf(stderr, "MMU: Attempted accessing unimplemented mode: $D505 <- $%02X.\n", value); break; case 7: case 8: case 9: case 10: page_zero = (ram + (mmu[0x8] & 0x1 ? 0x10000 : 0x00000) + (mmu[0x7] << 8)); page_one = (ram + (mmu[0xa] & 0x1 ? 0x10000 : 0x00000) + (mmu[0x9] << 8)); DEBUG(("MMU: Page Zero at $%05X, Page One at $%05X\n", page_zero - ram, page_one - ram)); break; } } } /* ------------------------------------------------------------------------- */ /* External memory access functions. */ BYTE REGPARM1 read_basic(ADDRESS addr) { return basic_rom[addr - 0x4000]; } void REGPARM2 store_basic(ADDRESS addr, BYTE value) { basic_rom[addr - 0x4000] = value; } BYTE REGPARM1 read_kernal(ADDRESS addr) { return kernal_rom[addr & 0x1fff]; } void REGPARM2 store_kernal(ADDRESS addr, BYTE value) { kernal_rom[addr & 0x1fff] = value; } BYTE REGPARM1 read_chargen(ADDRESS addr) { return chargen_rom[addr & 0xffff]; } BYTE REGPARM1 read_rom(ADDRESS addr) { switch (addr & 0xf000) { case 0xe000: case 0xf000: return read_kernal(addr); case 0x4000: case 0x5000: case 0x6000: case 0x7000: case 0x8000: case 0x9000: case 0xa000: case 0xb000: return read_basic(addr); } return 0; } void REGPARM2 store_rom(ADDRESS addr, BYTE value) { switch (addr & 0xf000) { case 0xe000: case 0xf000: store_kernal(addr, value); break; case 0x4000: case 0x5000: case 0x6000: case 0x7000: case 0x8000: case 0x9000: case 0xa000: case 0xb000: store_basic(addr, value); break; } } /* Generic memory access. */ void REGPARM2 mem_store(ADDRESS addr, BYTE value) { _mem_write_tab_ptr[addr >> 8](addr, value); } BYTE REGPARM1 mem_read(ADDRESS addr) { return _mem_read_tab[addr >> 8](addr); } /* ------------------------------------------------------------------------- */ /* CPU Memory interface. */ /* The MMU can basically do the following: - select one of the two (four) memory banks as the standard (non-shared) memory; - turn ROM and I/O on and off; - enable/disable top/bottom shared RAM (from 1K to 16K, so bottom shared RAM cannot go beyond $3FFF and top shared RAM cannot go under $C000); - move pages 0 and 1 to any physical address. */ #define READ_TOP_SHARED(addr) \ ((addr) > top_shared_limit ? ram[(addr)] \ : ram_bank[(addr)]) #define STORE_TOP_SHARED(addr, value) \ ((addr) > top_shared_limit ? (ram[(addr)] = (value)) \ : (ram_bank[(addr)] = (value))) #define READ_BOTTOM_SHARED(addr) \ ((addr) < bottom_shared_limit ? ram[(addr)] \ : ram_bank[(addr)]) #define STORE_BOTTOM_SHARED(addr, value) \ ((addr) < bottom_shared_limit ? (ram[(addr)] = (value)) \ : (ram_bank[(addr)] = (value))) BYTE REGPARM1 read_zero(ADDRESS addr) { return page_zero[addr]; } void REGPARM2 store_zero(ADDRESS addr, BYTE value) { page_zero[addr] = value; } static BYTE REGPARM1 read_one(ADDRESS addr) { return page_one[addr - 0x100]; } static void REGPARM2 store_one(ADDRESS addr, BYTE value) { page_one[addr - 0x100] = value; } /* $0200 - $3FFF: RAM (normal or shared). */ static BYTE REGPARM1 read_lo(ADDRESS addr) { return READ_BOTTOM_SHARED(addr); } static void REGPARM2 store_lo(ADDRESS addr, BYTE value) { STORE_BOTTOM_SHARED(addr, value); } /* $4000 - $7FFF: RAM or low BASIC ROM. */ static BYTE REGPARM1 read_basic_lo(ADDRESS addr) { if (basic_lo_in) return basic_rom[addr - 0x4000]; else return ram_bank[addr]; } static void REGPARM2 store_basic_lo(ADDRESS addr, BYTE value) { ram_bank[addr] = value; } /* $8000 - $BFFF: RAM or high BASIC ROM. */ static BYTE REGPARM1 read_basic_hi(ADDRESS addr) { if (basic_hi_in) { return basic_rom[addr - 0x4000]; } else return ram_bank[addr]; } static void REGPARM2 store_basic_hi(ADDRESS addr, BYTE value) { ram_bank[addr] = value; } /* $C000 - $CFFF: RAM (normal or shared) or Editor ROM. */ static BYTE REGPARM1 read_editor(ADDRESS addr) { if (editor_in) return basic_rom[addr - 0x4000]; else return READ_TOP_SHARED(addr); } static void REGPARM2 store_editor(ADDRESS addr, BYTE value) { STORE_TOP_SHARED(addr, value); } static BYTE REGPARM1 read_d0xx(ADDRESS addr) { if (io_in) return read_vic(addr); else if (chargen_in) return chargen_rom[addr]; else return READ_TOP_SHARED(addr); } static void REGPARM2 store_d0xx(ADDRESS addr, BYTE value) { if (io_in) store_vic(addr, value); else STORE_TOP_SHARED(addr, value); } static BYTE REGPARM1 read_d4xx(ADDRESS addr) { if (io_in) return read_sid(addr); else if (chargen_in) return chargen_rom[addr]; else return READ_TOP_SHARED(addr); } static void REGPARM2 store_d4xx(ADDRESS addr, BYTE value) { if (io_in) store_sid(addr, value); else STORE_TOP_SHARED(addr, value); } static BYTE REGPARM1 read_d5xx(ADDRESS addr) { if (io_in) return read_mmu(addr); else if (chargen_in) return chargen_rom[addr]; else return READ_TOP_SHARED(addr); } static void REGPARM2 store_d5xx(ADDRESS addr, BYTE value) { if (io_in) store_mmu(addr, value); else STORE_TOP_SHARED(addr, value); } static BYTE REGPARM1 read_d6xx(ADDRESS addr) { if (io_in) return read_vdc(addr); else if (chargen_in) return chargen_rom[addr]; else return READ_TOP_SHARED(addr); } static void REGPARM2 store_d6xx(ADDRESS addr, BYTE value) { if (io_in) store_vdc(addr, value); else STORE_TOP_SHARED(addr, value); } static BYTE REGPARM1 read_d7xx(ADDRESS addr) { if (io_in) { #if 0 /*def HAVE_RS232 */ if (acia_d7_enabled) return read_acia2(addr); else #endif return 0xff; } else if (chargen_in) return chargen_rom[addr]; else return READ_TOP_SHARED(addr); } static void REGPARM2 store_d7xx(ADDRESS addr, BYTE value) { if (io_in) { #if 0 /*def HAVE_RS232 */ if (acia_d7_enabled) { store_acia2(addr, value); } #endif } else STORE_TOP_SHARED(addr, value); } static BYTE REGPARM1 read_d8xx(ADDRESS addr) { if (io_in) return read_colorram(addr); else if (chargen_in) return chargen_rom[addr]; else return READ_TOP_SHARED(addr); } static void REGPARM2 store_d8xx(ADDRESS addr, BYTE value) { if (io_in) store_colorram(addr, value); else STORE_TOP_SHARED(addr, value); } static BYTE REGPARM1 read_dcxx(ADDRESS addr) { if (io_in) return read_cia1(addr); else if (chargen_in) return chargen_rom[addr]; else return READ_TOP_SHARED(addr); } static void REGPARM2 store_dcxx(ADDRESS addr, BYTE value) { if (io_in) store_cia1(addr, value); else STORE_TOP_SHARED(addr, value); } static BYTE REGPARM1 read_ddxx(ADDRESS addr) { if (io_in) return read_cia2(addr); else if (chargen_in) return chargen_rom[addr]; else return READ_TOP_SHARED(addr); } static void REGPARM2 store_ddxx(ADDRESS addr, BYTE value) { if (io_in) store_cia2(addr, value); else STORE_TOP_SHARED(addr, value); } /* $E000 - $FFFF: RAM or Kernal. */ static BYTE REGPARM1 read_hi(ADDRESS addr) { if (kernal_in) return kernal_rom[addr & 0x1fff]; else return READ_TOP_SHARED(addr); } /* $E000 - $FEFF: RAM or Kernal. */ static void REGPARM2 store_hi(ADDRESS addr, BYTE value) { STORE_TOP_SHARED(addr, value); } /* $FF00 - $FFFF: RAM or Kernal, with MMU at $FF00 - $FF04. */ static BYTE REGPARM1 read_ffxx(ADDRESS addr) { if (addr == 0xff00) return mmu[0]; else if (kernal_in) return kernal_rom[addr & 0x1fff]; else return READ_TOP_SHARED(addr); } static void REGPARM2 store_ffxx(ADDRESS addr, BYTE value) { if (addr == 0xff00) store_mmu(0, value); else if (addr <= 0xff04) store_mmu(0, mmu[addr & 0xf]); else STORE_TOP_SHARED(addr, value); } static BYTE REGPARM1 read_empty_io(ADDRESS addr) { if (io_in) return 0xff; else if (chargen_in) return chargen_rom[addr - 0xd000]; else return READ_TOP_SHARED(addr); } static void REGPARM2 store_empty_io(ADDRESS addr, BYTE value) { if (!io_in) STORE_TOP_SHARED(addr, value); } /* ------------------------------------------------------------------------- */ /* those are approximate copies from the c64 versions.... * they leave out the cartridge support */ void REGPARM2 store_io1(ADDRESS addr, BYTE value) { if (!io_in) { STORE_TOP_SHARED(addr, value); } else { #ifdef HAVE_RS232 if (acia_de_enabled) store_acia1(addr & 0x03, value); #endif } return; } BYTE REGPARM1 read_io1(ADDRESS addr) { if (io_in) { #ifdef HAVE_RS232 if (acia_de_enabled) return read_acia1(addr & 0x03); #endif return 0xff; /* rand(); - C64 has rand(), which is correct? */ } else if (chargen_in) return chargen_rom[addr - 0xd000]; else return READ_TOP_SHARED(addr); } void REGPARM2 store_io2(ADDRESS addr, BYTE value) { if (!io_in) { STORE_TOP_SHARED(addr, value); } else { if (ieee488_enabled) { store_tpi(addr & 0x07, value); } } return; } BYTE REGPARM1 read_io2(ADDRESS addr) { if (io_in) { if (emu_id_enabled && addr >= 0xdfa0) { addr &= 0xff; if (addr == 0xff) emulator_id[addr - 0xa0] ^= 0xff; return emulator_id[addr - 0xa0]; } if (ieee488_enabled) { return read_tpi(addr & 0x07); } return 0xff; /* rand(); - C64 has rand(), which is correct? */ } else if (chargen_in) return chargen_rom[addr - 0xd000]; else return READ_TOP_SHARED(addr); } /* ------------------------------------------------------------------------- */ void initialize_memory(void) { int i; _mem_read_tab[0] = read_zero; _mem_write_tab[0] = store_zero; _mem_read_tab[1] = read_one; _mem_write_tab[1] = store_one; for (i = 0x02; i <= 0x3f; i++) { _mem_read_tab[i] = read_lo; _mem_write_tab[i] = store_lo; } for (i = 0x40; i <= 0x7f; i++) { _mem_read_tab[i] = read_basic_lo; _mem_write_tab[i] = store_basic_lo; } for (i = 0x80; i <= 0xbf; i++) { _mem_read_tab[i] = read_basic_hi; _mem_write_tab[i] = store_basic_hi; } for (i = 0xc0; i <= 0xcf; i++) { _mem_read_tab[i] = read_editor; _mem_write_tab[i] = store_editor; } for (i = 0xd0; i <= 0xd3; i++) { _mem_read_tab[i] = read_d0xx; _mem_write_tab[i] = store_d0xx; } _mem_read_tab[0xd4] = read_d4xx; _mem_write_tab[0xd4] = store_d4xx; _mem_read_tab[0xd5] = read_d5xx; _mem_write_tab[0xd5] = store_d5xx; _mem_read_tab[0xd6] = read_d6xx; _mem_write_tab[0xd6] = store_d6xx; _mem_read_tab[0xd7] = read_d7xx; /* read_empty_io; */ _mem_write_tab[0xd7] = store_d7xx; /* store_empty_io; */ _mem_read_tab[0xd8] = _mem_read_tab[0xd9] = read_d8xx; _mem_read_tab[0xda] = _mem_read_tab[0xdb] = read_d8xx; _mem_write_tab[0xd8] = _mem_write_tab[0xd9] = store_d8xx; _mem_write_tab[0xda] = _mem_write_tab[0xdb] = store_d8xx; _mem_read_tab[0xdc] = read_dcxx; _mem_write_tab[0xdc] = store_dcxx; _mem_read_tab[0xdd] = read_ddxx; _mem_write_tab[0xdd] = store_ddxx; _mem_read_tab[0xde] = read_io1; _mem_write_tab[0xde] = store_io1; _mem_read_tab[0xdf] = read_io2; _mem_write_tab[0xdf] = store_io2; for (i = 0xe0; i <= 0xfe; i++) { _mem_read_tab[i] = read_hi; _mem_write_tab[i] = store_hi; } _mem_read_tab[0xff] = read_ffxx; _mem_write_tab[0xff] = store_ffxx; _mem_read_tab[0x100] = _mem_read_tab[0x0]; _mem_write_tab[0x100] = _mem_write_tab[0x0]; /* FIXME? Is this the real configuration? */ basic_lo_in = basic_hi_in = kernal_in = editor_in = 1; io_in = 1; chargen_in = 0; top_shared_limit = 0xffff; bottom_shared_limit = 0x0000; ram_bank = ram; page_zero = ram; page_one = ram + 0x100; } /* ------------------------------------------------------------------------- */ /* Initialize RAM for power-up. */ void mem_powerup(void) { int i; #ifndef __MSDOS__ printf("Initializing RAM for power-up...\n"); #endif for (i = 0; i < 0x20000; i += 0x80) { memset(ram + i, 0, 0x40); memset(ram + i + 0x40, 0xff, 0x40); } } /* Load ROMs at startup. This is half-stolen from the old `load_mem()' in `memory.c'. */ int mem_load(void) { WORD sum; /* ROM checksum */ int id; /* ROM identification number */ int i; mem_powerup(); page_zero = ram; page_one = ram + 0x100; initialize_memory(); /* Load Kernal ROM. */ if (mem_load_sys_file(kernal_rom_name, kernal_rom, C128_KERNAL_ROM_SIZE, C128_KERNAL_ROM_SIZE) < 0) { fprintf(stderr, "Couldn't load kernal ROM `%s'.\n", kernal_rom_name); return -1; } /* Check Kernal ROM. */ for (i = 0, sum = 0; i < C128_KERNAL_ROM_SIZE; i++) sum += kernal_rom[i]; id = read_rom(0xff80); printf("Kernal rev #%d.\n", id); if (id == 1 && sum != C128_KERNAL_CHECKSUM_R01 && sum != C128_KERNAL_CHECKSUM_R01SWE && sum != C128_KERNAL_CHECKSUM_R01GER) fprintf(stderr, "Warning: Kernal image may be corrupted. Sum: %d\n", sum); /* Load Basic ROM. */ if (mem_load_sys_file(basic_rom_name, basic_rom, C128_BASIC_ROM_SIZE + C128_EDITOR_ROM_SIZE, C128_BASIC_ROM_SIZE + C128_EDITOR_ROM_SIZE) < 0) { fprintf(stderr, "Couldn't load basic ROM `%s'.\n", basic_rom_name); return -1; } /* Check Basic ROM. */ for (i = 0, sum = 0; i < C128_BASIC_ROM_SIZE; i++) sum += basic_rom[i]; if (sum != C128_BASIC_CHECKSUM_85 && sum != C128_BASIC_CHECKSUM_86) fprintf(stderr, "Warning: Unknown Basic image `%s'. Sum: %d ($%04X)\n", basic_rom_name, sum, sum); /* Check Editor ROM. */ for (i = C128_BASIC_ROM_SIZE, sum = 0; i < C128_BASIC_ROM_SIZE + C128_EDITOR_ROM_SIZE; i++) sum += basic_rom[i]; if (id == 01 && sum != C128_EDITOR_CHECKSUM_R01 && sum != C128_EDITOR_CHECKSUM_R01SWE && sum != C128_EDITOR_CHECKSUM_R01GER) { fprintf(stderr, "Warning: EDITOR image may be corrupted. Sum: %d\n", sum); fprintf(stderr, "Check your Basic ROM\n"); } /* Load chargen ROM. */ if (mem_load_sys_file(chargen_rom_name, chargen_rom, C128_CHARGEN_ROM_SIZE, C128_CHARGEN_ROM_SIZE) < 0) { fprintf(stderr, "Couldn't load character ROM `%s'.\n", chargen_rom_name); return -1; } /* Fake BIOS initialization. This is needed because the real C128 is initialized by the Z80, which we currently do not implement. */ memcpy(ram + 0xffd0, biostab, sizeof(biostab)); rom_loaded = 1; return 0; } /* ------------------------------------------------------------------------- */ /* Change the current video bank. */ void mem_set_vbank(int new_vbank) { /* FIXME: Still to do. */ } void mem_toggle_watchpoints(int flag) { /* FIXME: Still to do. */ } /* Set the tape sense status. */ void mem_set_tape_sense(int sense) { tape_sense = sense; } /* Enable/disable the REU. FIXME: should initialize the REU if necessary? */ void mem_toggle_reu(int flag) { reu_enabled = flag; } /* Enable/disable the IEEE488 interface. */ void mem_toggle_ieee488(int flag) { ieee488_enabled = flag; } /* Enable/disable the Emulator ID. */ void mem_toggle_emu_id(int flag) { emu_id_enabled = flag; } /* ------------------------------------------------------------------------- */ void mem_get_basic_text(ADDRESS * start, ADDRESS * end) { if (start != NULL) *start = ram[0x2b] | (ram[0x2c] << 8); if (end != NULL) *end = ram[0x1210] | (ram[0x1211] << 8); } void mem_set_basic_text(ADDRESS start, ADDRESS end) { ram[0x2b] = ram[0xac] = start & 0xff; ram[0x2c] = ram[0xad] = start >> 8; ram[0x1210] = end & 0xff; ram[0x1211] = end >> 8; } /* ------------------------------------------------------------------------- */ int mem_rom_trap_allowed(ADDRESS addr) { return 1; } /* ------------------------------------------------------------------------- */ /* Banked memory access functions for the monitor */ /* FIXME: peek, cartridge support */ static void store_bank_io(ADDRESS addr, BYTE byte) { switch (addr &= 0xff00) { case 0xd000: case 0xd100: case 0xd200: case 0xd300: store_d0xx(addr, byte); break; case 0xd400: store_d4xx(addr, byte); break; case 0xd500: store_d5xx(addr, byte); break; case 0xd600: store_d6xx(addr, byte); break; case 0xd700: store_d7xx(addr, byte); break; case 0xd800: case 0xd900: case 0xda00: case 0xdb00: store_colorram(addr, byte); break; case 0xdc00: store_cia1(addr, byte); break; case 0xdd00: store_cia2(addr, byte); break; case 0xde00: store_io1(addr, byte); break; case 0xdf00: store_io2(addr, byte); break; } return; } static BYTE read_bank_io(ADDRESS addr) { switch (addr &= 0xff00) { case 0xd000: case 0xd100: case 0xd200: case 0xd300: return read_d0xx(addr); case 0xd400: return read_d4xx(addr); case 0xd500: return read_d5xx(addr); case 0xd600: return read_d6xx(addr); case 0xd700: return read_d7xx(addr); case 0xd800: case 0xd900: case 0xda00: case 0xdb00: return read_colorram(addr); case 0xdc00: return read_cia1(addr); case 0xdd00: return read_cia2(addr); case 0xde00: return read_io1(addr); case 0xdf00: return read_io2(addr); } return 0xff; } static BYTE peek_bank_io(ADDRESS addr) { switch (addr &= 0xff00) { case 0xd000: case 0xd100: case 0xd200: case 0xd300: return read_d0xx(addr); /* FIXME */ case 0xd400: return read_d4xx(addr); /* FIXME */ case 0xd500: return read_d5xx(addr); /* FIXME */ case 0xd600: return read_d6xx(addr); /* FIXME */ case 0xd700: return read_d7xx(addr); /* FIXME */ case 0xd800: case 0xd900: case 0xda00: case 0xdb00: return read_colorram(addr); case 0xdc00: return peek_cia1(addr); case 0xdd00: return peek_cia2(addr); case 0xde00: return read_io1(addr); /* FIXME */ case 0xdf00: return read_io2(addr); /* FIXME */ } return 0xff; } /* Exported banked memory access functions for the monitor. */ static const char *banknames[] = { "default", "cpu", "ram", "rom", "io", "ram1", NULL }; static int banknums[] = { 1, 0, 1, 2, 3, 4 }; const char **mem_bank_list(void) { return banknames; } int mem_bank_from_name(const char *name) { int i = 0; while (banknames[i]) { if (!strcmp(name, banknames[i])) { return banknums[i]; } i++; } return -1; } BYTE mem_bank_read(int bank, ADDRESS addr) { switch (bank) { case 0: /* current */ return mem_read(addr); break; case 4: /* ram1 */ return ram[addr + 0x10000]; case 3: /* io */ if (addr >= 0xd000 && addr < 0xe000) { return read_bank_io(addr); } case 2: /* rom */ if (addr >= 0x4000 && addr <= 0xCFFF) { return basic_rom[addr - 0x4000]; } if (addr >= 0xD000 && addr <= 0xDFFF) { return chargen_rom[addr & 0x0fff]; } if (addr >= 0xE000 && addr <= 0xFFFF) { return kernal_rom[addr & 0x1fff]; } case 1: /* ram */ } return ram[addr]; } BYTE mem_bank_peek(int bank, ADDRESS addr) { switch (bank) { case 0: /* current */ return mem_read(addr); /* FIXME */ break; case 3: /* io */ if (addr >= 0xd000 && addr < 0xe000) { return peek_bank_io(addr); } } return mem_bank_read(bank, addr); } void mem_bank_write(int bank, ADDRESS addr, BYTE byte) { switch (bank) { case 0: /* current */ mem_store(addr, byte); return; case 4: /* ram1 */ ram[addr + 0x10000] = byte; return; case 3: /* io */ if (addr >= 0xd000 && addr < 0xe000) { store_bank_io(addr, byte); return; } case 2: /* rom */ if (addr >= 0x4000 && addr <= 0xCFFF) { return; } if (addr >= 0xE000 && addr <= 0xffff) { return; } case 1: /* ram */ } ram[addr] = byte; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.