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.