This is vic20mem.c in view mode; [Download] [Up]
/* * vic20mem.c -- VIC20 memory handling. * * Written by * Ettore Perazzoli (ettore@comm2000.it) * André Fachat (fachat@physik.tu-chemnitz.de) * * Multiple memory configuration support originally by * Alexander Lehmann (alex@mathematik.th-darmstadt.de) * * 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. * */ #ifndef VIC20 #define VIC20 /* for mkdep */ #endif #include "vice.h" #include <stdio.h> #include <string.h> #include "vic20mem.h" #include "cmdline.h" #include "interrupt.h" #include "maincpu.h" #include "memutils.h" #include "mon.h" #include "resources.h" #include "stdlib.h" #include "utils.h" #include "emuid.h" #include "vic.h" #include "vic20via.h" #include "vmachine.h" #include "cartridge.h" /* ------------------------------------------------------------------------- */ /* VIC20 memory-related resources. */ #define VIC_BLK0 1 #define VIC_BLK1 2 #define VIC_BLK2 4 #define VIC_BLK3 8 #define VIC_BLK5 16 #define VIC_BLK_ALL (VIC_BLK0 | VIC_BLK1 | VIC_BLK2 | VIC_BLK3 | VIC_BLK5) /* 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; /* which ROMs are loaded - bits are VIC_BLK* */ static int mem_rom_blocks; /* Flag: Do we have RAM block `n'? */ static int ram_block_0_enabled; static int ram_block_1_enabled; static int ram_block_2_enabled; static int ram_block_3_enabled; static int ram_block_5_enabled; /* 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; } /* Ugly hack... */ #define DEFINE_SET_BLOCK_FUNC(num) \ static int set_ram_block_##num##_enabled(resource_value_t v) \ { \ int value = (int) v; \ \ ram_block_##num##_enabled = value; \ if (value) \ return vic20_mem_enable_ram_block(num); \ else \ return vic20_mem_disable_ram_block(num); \ } DEFINE_SET_BLOCK_FUNC(0) DEFINE_SET_BLOCK_FUNC(1) DEFINE_SET_BLOCK_FUNC(2) DEFINE_SET_BLOCK_FUNC(3) DEFINE_SET_BLOCK_FUNC(5) static int set_emu_id_enabled(resource_value_t v) { emu_id_enabled = (int) v; return 0; } /* Enable/disable the Emulator ID. */ void mem_toggle_emu_id(int flag) { emu_id_enabled = flag; } 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}, {"RAMBlock0", RES_INTEGER, (resource_value_t) 1, (resource_value_t *) & ram_block_0_enabled, set_ram_block_0_enabled}, {"RAMBlock1", RES_INTEGER, (resource_value_t) 1, (resource_value_t *) & ram_block_1_enabled, set_ram_block_1_enabled}, {"RAMBlock2", RES_INTEGER, (resource_value_t) 1, (resource_value_t *) & ram_block_2_enabled, set_ram_block_2_enabled}, {"RAMBlock3", RES_INTEGER, (resource_value_t) 1, (resource_value_t *) & ram_block_3_enabled, set_ram_block_3_enabled}, {"RAMBlock5", RES_INTEGER, (resource_value_t) 1, (resource_value_t *) & ram_block_5_enabled, set_ram_block_5_enabled}, {"EmuID", RES_INTEGER, (resource_value_t) 0, (resource_value_t *) & emu_id_enabled, set_emu_id_enabled}, {NULL} }; int vic20_mem_init_resources(void) { return resources_register(resources); } /* ------------------------------------------------------------------------- */ /* This function parses the mem config string given as `-memory' and returns * the appropriate values or'ed together. * * basically we accept a comma separated list of options like the following: * "" - no extension * none - same * all - all blocks * 3k - 3k space in block 0 (=3k extension cartridge) * 8k - 1st 8k extension block * 16k - 1st and 2nd 8 extension (= 16k extension cartridge) * 24k - 1-3rd extension block (=8k and 16k extension cartridges) * * 0,1,2,3,5 - memory in respective block * 04,20,40,60,a0 - memory at respective address (same as block #s) * * example: xvic -memory "" * * enables unexpanded computer * * xvic -memory 60,a0 * * enables memory in blocks 3 and 5, which is the usual * configuration for 16k rom modules * * 12/27/96 Alexander Lehmann (alex@mathematik.th-darmstadt.de) * Edited by Ettore to fit in the new command-line parsing. */ static int cmdline_memory(const char *param, void *extra_param) { int memconf = 0; const char *memstring = param, *optend; char *opt = alloca(strlen(param) + 1); /* Default is all banks. */ if (!memstring) memconf = VIC_BLK_ALL; else { /* Maybe we should use strtok for this? */ while (*memstring) { for (optend = memstring; *optend && *optend != ','; optend++); strncpy(opt, memstring, optend - memstring); opt[optend - memstring] = '\0'; if (strcmp(opt, "") == 0 || strcmp(opt, "none") == 0) { /* no extension */ } else if (strcmp(opt, "all") == 0) { memconf = VIC_BLK_ALL; } else if (strcmp(opt, "3k") == 0) { memconf |= VIC_BLK0; } else if (strcmp(opt, "8k") == 0) { memconf |= VIC_BLK1; } else if (strcmp(opt, "16k") == 0) { memconf |= VIC_BLK1 | VIC_BLK2; } else if (strcmp(opt, "24k") == 0) { memconf |= VIC_BLK1 | VIC_BLK2 | VIC_BLK3;; } else if (strcmp(opt, "0") == 0 || strcmp(opt, "04") == 0) { memconf |= VIC_BLK0; } else if (strcmp(opt, "1") == 0 || strcmp(opt, "20") == 0) { memconf |= VIC_BLK1; } else if (strcmp(opt, "2") == 0 || strcmp(opt, "40") == 0) { memconf |= VIC_BLK2; } else if (strcmp(opt, "3") == 0 || strcmp(opt, "60") == 0) { memconf |= VIC_BLK3; } else if (strcmp(opt, "5") == 0 || strcmp(opt, "a0") == 0 || strcmp(opt, "A0") == 0) { memconf |= VIC_BLK5; } else { fprintf(stderr, "Unsupported memory extension option: \"%s\"\n", opt); return -1; } memstring = optend; if (*memstring) memstring++; /* skip ',' */ } } printf("Extension memory enabled: "); if (memconf & VIC_BLK0) { set_ram_block_0_enabled((resource_value_t) 1); printf("blk0 "); } else { set_ram_block_0_enabled((resource_value_t) 0); } if (memconf & VIC_BLK1) { set_ram_block_1_enabled((resource_value_t) 1); printf("blk1 "); } else { set_ram_block_1_enabled((resource_value_t) 0); } if (memconf & VIC_BLK2) { set_ram_block_2_enabled((resource_value_t) 1); printf("blk2 "); } else { set_ram_block_2_enabled((resource_value_t) 0); } if (memconf & VIC_BLK3) { set_ram_block_3_enabled((resource_value_t) 1); printf("blk3 "); } else { set_ram_block_3_enabled((resource_value_t) 0); } if (memconf & VIC_BLK5) { set_ram_block_5_enabled((resource_value_t) 1); printf("blk5"); } else { set_ram_block_5_enabled((resource_value_t) 0); } if (memconf == 0) printf("none"); printf("\n"); return 0; } /* VIC20 memory-related command-line options. */ static cmdline_option_t cmdline_options[] = { {"-memory", CALL_FUNCTION, 1, cmdline_memory, NULL, NULL, NULL, "<spec>", "Specify memory configuration"}, {"-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"}, {NULL} }; int vic20_mem_init_cmdline_options(void) { return cmdline_register_options(cmdline_options); } /* ------------------------------------------------------------------------- */ /* The VIC20 memory. */ BYTE ram[VIC20_RAM_SIZE]; int ram_size = VIC20_RAM_SIZE; BYTE rom[VIC20_BASIC_ROM_SIZE + VIC20_KERNAL_ROM_SIZE]; #define kernal_rom (rom + VIC20_BASIC_ROM_SIZE) #define basic_rom (rom) BYTE cartrom[0x10000]; /* The second 0x400 handles a possible segfault by a wraparound of the chargen by setting it to $8c00. FIXME: This does not cause the exact behavior to be emulated though! */ BYTE chargen_rom[0x400 + VIC20_CHARGEN_ROM_SIZE + 0x400]; /* Memory read and write tables. */ read_func_ptr_t _mem_read_tab[0x101]; store_func_ptr_t _mem_write_tab[0x101]; BYTE *_mem_read_base_tab[0x101]; /* These ones are used when watchpoints are turned on. */ read_func_ptr_t _mem_read_tab_watch[0x101]; store_func_ptr_t _mem_write_tab_watch[0x101]; read_func_ptr_t _mem_read_tab_nowatch[0x101]; store_func_ptr_t _mem_write_tab_nowatch[0x101]; read_func_ptr_t *_mem_read_tab_ptr; store_func_ptr_t *_mem_write_tab_ptr; BYTE **_mem_read_base_tab_ptr; /* Flag: nonzero if the Kernal and BASIC ROMs have been loaded. */ int rom_loaded = 0; /* ------------------------------------------------------------------------- */ void REGPARM2 store_wrap(ADDRESS addr, BYTE value) { ram[addr & (VIC20_RAM_SIZE - 1)] = value; chargen_rom[addr & 0x3ff] = value; } /* ------------------------------------------------------------------------- */ BYTE REGPARM1 read_basic(ADDRESS addr) { return basic_rom[addr & 0x1fff]; } BYTE REGPARM1 read_kernal(ADDRESS addr) { return kernal_rom[addr & 0x1fff]; } BYTE REGPARM1 read_chargen(ADDRESS addr) { return chargen_rom[0x400 + (addr & 0xfff)]; } BYTE REGPARM1 read_zero(ADDRESS addr) { return ram[addr & 0xff]; } void REGPARM2 store_zero(ADDRESS addr, BYTE value) { ram[addr & 0xff] = value; } BYTE REGPARM1 read_ram(ADDRESS addr) { return ram[addr]; } void REGPARM2 store_ram(ADDRESS addr, BYTE value) { ram[addr & (VIC20_RAM_SIZE - 1)] = value; } BYTE REGPARM1 read_cartrom(ADDRESS addr) { return cartrom[addr & 0xffff]; } BYTE REGPARM1 read_rom(ADDRESS addr) { switch (addr & 0xf000) { case 0x8000: return read_chargen(addr); case 0xc000: case 0xd000: return read_basic(addr); case 0xe000: case 0xf000: return read_kernal(addr); } return 0; } void REGPARM2 store_rom(ADDRESS addr, BYTE value) { switch (addr & 0xf000) { case 0x8000: chargen_rom[0x400 + (addr & 0x0fff)] = value; break; case 0xc000: case 0xd000: basic_rom[addr & 0x1fff] = value; break; case 0xe000: case 0xf000: kernal_rom[addr & 0x1fff] = value; break; } } void REGPARM2 store_via(ADDRESS addr, BYTE value) { if (addr & 0x10) /* $911x (VIA2) */ store_via2(addr, value); if (addr & 0x20) /* $912x (VIA1) */ store_via1(addr, value); } BYTE REGPARM1 read_via(ADDRESS addr) { BYTE ret = 0xff; if (addr & 0x10) /* $911x (VIA2) */ ret &= read_via2(addr); if (addr & 0x20) /* $912x (VIA1) */ ret &= read_via1(addr); return ret; } static BYTE REGPARM1 read_emuid(ADDRESS addr) { addr &= 0xff; if (emu_id_enabled && addr >= 0xa0) { return emulator_id[addr - 0xa0]; } return 0xff; } static void REGPARM2 store_emuid(ADDRESS addr, BYTE value) { addr &= 0xff; if(emu_id_enabled && (addr == 0xff)) { emulator_id[addr - 0xa0] ^= 0xff; } return; } static BYTE REGPARM1 read_dummy(ADDRESS addr) { return 0xff; } static void REGPARM2 store_dummy(ADDRESS addr, BYTE value) { return; } /* Watchpoint functions */ BYTE REGPARM1 read_watch(ADDRESS addr) { mon_watch_push_load_addr(addr, e_comp_space); return _mem_read_tab_nowatch[addr >> 8] (addr); } void REGPARM2 store_watch(ADDRESS addr, BYTE value) { mon_watch_push_store_addr(addr, e_comp_space); _mem_write_tab_nowatch[addr >> 8] (addr, value); } /* ------------------------------------------------------------------------- */ /* 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_ptr[addr >> 8] (addr); } /* ------------------------------------------------------------------------- */ static void set_mem(int start_page, int end_page, read_func_ptr_t read_func, store_func_ptr_t store_func, BYTE * read_base, int base_mask) { int i; if (read_base != NULL) { for (i = start_page; i <= end_page; i++) { _mem_read_tab_nowatch[i] = read_func; _mem_write_tab_nowatch[i] = store_func; _mem_read_base_tab[i] = read_base + ((i << 8) & base_mask); } } else { for (i = start_page; i <= end_page; i++) { _mem_read_tab_nowatch[i] = read_func; _mem_write_tab_nowatch[i] = store_func; _mem_read_base_tab[i] = NULL; } } } int vic20_mem_enable_rom_block(int num) { if (num == 1 || num == 3 || num == 5) { set_mem(num * 0x20, num * 0x20 + 0x1f, read_cartrom, store_dummy, cartrom, 0xffff); return 0; } else return -1; } int vic20_mem_enable_ram_block(int num) { if (num == 0) { set_mem(0x04, 0x0f, read_ram, store_ram, ram, 0xffff); return 0; } else if (num > 0 && num != 4 && num <= 5) { set_mem(num * 0x20, num * 0x20 + 0x1f, read_ram, store_ram, ram, 0xffff); return 0; } else return -1; } int vic20_mem_disable_ram_block(int num) { if (num == 0) { set_mem(0x04, 0x0f, read_dummy, store_dummy, ram, 0xffff); return 0; } else if (num > 0 && num != 4 && num <= 5) { set_mem(num * 0x20, num * 0x20 + 0x1f, read_dummy, store_dummy, ram, 0xffff); return 0; } else return -1; } void initialize_memory(void) { int i; /* Setup low standard RAM at $0000-$0300. */ set_mem(0x00, 0x03, read_ram, store_ram, ram, 0xffff); /* Setup more low RAM at $1000-$1FFFF. */ set_mem(0x10, 0x1b, read_ram, store_ram, ram, 0xffff); set_mem(0x1c, 0x1f, read_ram, store_wrap, ram, 0xffff); /* Setup RAM at $0400-$0FFF. */ if (ram_block_0_enabled) vic20_mem_enable_ram_block(0); else vic20_mem_disable_ram_block(0); /* Setup RAM or cartridge ROM at $2000-$3FFF. */ if (mem_rom_blocks & VIC_BLK1) vic20_mem_enable_rom_block(1); else if (ram_block_1_enabled) vic20_mem_enable_ram_block(1); else vic20_mem_disable_ram_block(1); /* Setup RAM at $4000-$5FFF. */ if (ram_block_2_enabled) vic20_mem_enable_ram_block(2); else vic20_mem_disable_ram_block(2); /* Setup RAM or cartridge ROM at $6000-$7FFF. */ if (mem_rom_blocks & VIC_BLK3) vic20_mem_enable_rom_block(3); else if (ram_block_3_enabled) vic20_mem_enable_ram_block(3); else vic20_mem_disable_ram_block(3); /* Setup RAM or cartridge ROM at $A000-$BFFF. */ if (mem_rom_blocks & VIC_BLK5) vic20_mem_enable_rom_block(5); else if (ram_block_5_enabled) vic20_mem_enable_ram_block(5); else vic20_mem_disable_ram_block(5); /* Setup character generator ROM at $8000-$8FFF. */ set_mem(0x80, 0x8f, read_chargen, store_dummy, chargen_rom + 0x400, 0x0fff); /* Setup VIC-I at $9000-$90FF. */ set_mem(0x90, 0x90, read_vic, store_vic, NULL, 0); /* Setup VIAs at $9100-$93FF. */ set_mem(0x91, 0x93, read_via, store_via, NULL, 0); /* Setup color memory at $9400-$9BFF. Warning: we use a kludge here. Instead of mapping the color memory separately, we map it directly in the corresponding RAM address space. */ set_mem(0x94, 0x9b, read_ram, store_ram, ram, 0xffff); set_mem(0x9c, 0x9e, read_dummy, store_dummy, NULL, 0); /* Setup emulator ID at $9F** */ set_mem(0x9f, 0x9f, read_emuid, store_emuid, NULL, 0); /* Setup BASIC ROM at $C000-$DFFF. */ set_mem(0xc0, 0xdf, read_basic, store_dummy, basic_rom, 0x1fff); /* Setup Kernal ROM at $E000-$FFFF. */ set_mem(0xe0, 0xff, read_kernal, store_dummy, kernal_rom, 0x1fff); _mem_read_tab_nowatch[0x100] = _mem_read_tab_nowatch[0]; _mem_write_tab_nowatch[0x100] = _mem_write_tab_nowatch[0]; _mem_read_base_tab[0x100] = _mem_read_base_tab[0]; _mem_read_base_tab_ptr = _mem_read_base_tab; for (i = 0; i <= 0x100; i++) { _mem_read_tab_watch[i] = read_watch; _mem_write_tab_watch[i] = store_watch; } mem_toggle_watchpoints(0); } void mem_toggle_watchpoints(int flag) { if (flag) { _mem_read_tab_ptr = _mem_read_tab_watch; _mem_write_tab_ptr = _mem_write_tab_watch; } else { _mem_read_tab_ptr = _mem_read_tab_nowatch; _mem_write_tab_ptr = _mem_write_tab_nowatch; } } /* ------------------------------------------------------------------------- */ /* 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 < VIC20_RAM_SIZE; 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 i; mem_powerup(); /* Load Kernal ROM. */ if (mem_load_sys_file(kernal_rom_name, kernal_rom, VIC20_KERNAL_ROM_SIZE, VIC20_KERNAL_ROM_SIZE) < 0) { fprintf(stderr, "Couldn't load kernal ROM.\n\n"); return -1; } /* Check Kernal ROM. */ for (i = 0, sum = 0; i < VIC20_KERNAL_ROM_SIZE; i++) sum += kernal_rom[i]; if (sum != VIC20_KERNAL_CHECKSUM) { fprintf(stderr, "Warning: Unknown Kernal image. Sum: %d ($%04X)\n", sum, sum); } /* Load Basic ROM. */ if (mem_load_sys_file(basic_rom_name, basic_rom, VIC20_BASIC_ROM_SIZE, VIC20_BASIC_ROM_SIZE) < 0) { fprintf(stderr, "Couldn't load basic ROM.\n\n"); return -1; } /* Check Basic ROM. */ for (i = 0, sum = 0; i < VIC20_BASIC_ROM_SIZE; i++) sum += basic_rom[i]; if (sum != VIC20_BASIC_CHECKSUM) fprintf(stderr, "Warning: Unknown Basic image. Sum: %d ($%04X)\n", sum, sum); /* Load chargen ROM. */ if (mem_load_sys_file(chargen_rom_name, chargen_rom + 0x400, VIC20_CHARGEN_ROM_SIZE, VIC20_CHARGEN_ROM_SIZE) < 0) { fprintf(stderr, "Couldn't load character ROM.\n"); return -1; } rom_loaded = 1; return 0; } /* ------------------------------------------------------------------------- */ void mem_attach_cartridge(int type, BYTE * rawcart) { switch(type) { case CARTRIDGE_VIC20_4KB_2000: case CARTRIDGE_VIC20_8KB_2000: printf("CART: attaching %dKB cartridge at $2000\n", (type == CARTRIDGE_VIC20_4KB_2000) ? 4 : 8); memcpy(cartrom + 0x2000, rawcart, 0x2000); mem_rom_blocks |= VIC_BLK1; break; case CARTRIDGE_VIC20_4KB_6000: case CARTRIDGE_VIC20_8KB_6000: printf("CART: attaching %dKB cartridge at $6000\n", (type == CARTRIDGE_VIC20_4KB_6000) ? 4 : 8); memcpy(cartrom + 0x6000, rawcart, 0x2000); mem_rom_blocks |= VIC_BLK3; break; case CARTRIDGE_VIC20_8KB_A000: case CARTRIDGE_VIC20_4KB_A000: printf("CART: attaching %dKB cartridge at $A000\n", (type == CARTRIDGE_VIC20_4KB_A000) ? 4 : 8); memcpy(cartrom + 0xA000, rawcart, (type == CARTRIDGE_VIC20_4KB_A000) ? 0x1000 : 0x2000); mem_rom_blocks |= VIC_BLK5; break; case CARTRIDGE_VIC20_4KB_B000: printf("CART: attaching 4KB cartridge at $B000\n"); memcpy(cartrom + 0xB000, rawcart, 0x1000); mem_rom_blocks |= VIC_BLK5; break; default: fprintf(stderr, "Unknown Cartridge Type!\n"); return; } initialize_memory(); return; } void mem_detach_cartridge(int type) { switch(type) { case CARTRIDGE_VIC20_8KB_2000: case CARTRIDGE_VIC20_4KB_2000: mem_rom_blocks &= ~VIC_BLK1; break; case CARTRIDGE_VIC20_8KB_6000: case CARTRIDGE_VIC20_4KB_6000: mem_rom_blocks &= ~VIC_BLK3; break; case CARTRIDGE_VIC20_8KB_A000: case CARTRIDGE_VIC20_4KB_A000: case CARTRIDGE_VIC20_4KB_B000: mem_rom_blocks &= ~VIC_BLK5; break; default: return; } initialize_memory(); return; } /* ------------------------------------------------------------------------- */ /* FIXME: this part needs to be checked. */ void mem_get_basic_text(ADDRESS * start, ADDRESS * end) { if (start != NULL) *start = ram[0x2b] | (ram[0x2c] << 8); if (end != NULL) *end = ram[0x2d] | (ram[0x2e] << 8); } void mem_set_basic_text(ADDRESS start, ADDRESS end) { ram[0x2b] = ram[0xac] = start & 0xff; ram[0x2c] = ram[0xad] = start >> 8; ram[0x2d] = ram[0x2f] = ram[0x31] = ram[0xae] = end & 0xff; ram[0x2e] = ram[0x30] = ram[0x32] = ram[0xaf] = end >> 8; } /* ------------------------------------------------------------------------- */ int mem_rom_trap_allowed(ADDRESS addr) { return addr >= 0xe000; } /* ------------------------------------------------------------------------- */ /* Banked memory access functions for the monitor */ /* Exported banked memory access functions for the monitor */ /* FIXME: peek */ static const char *banknames[] = { "default", "cpu", NULL }; const int banknums[] = { 0, 0 }; 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; } return 0xff; } BYTE mem_bank_peek(int bank, ADDRESS addr) { switch (bank) { case 0: /* current */ return mem_read(addr); /* FIXME */ break; } 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; } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.