This is traps.c in view mode; [Download] [Up]
/*
* traps.c - Allow VICE to replace ROM code with C function calls.
*
* Written by
* Teemu Rantanen (tvr@cs.hut.fi)
* Jarkko Sonninen (sonninen@lut.fi)
* Ettore Perazzoli (ettore@comm2000.it)
*
* 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.
*
*/
#include "vice.h"
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include "traps.h"
#include "maincpu.h"
#include "mem.h"
#include "interrupt.h"
#include "resources.h"
#include "cmdline.h"
#include "utils.h"
/* #define DEBUG_TRAPS */
#ifdef DEBUG_TRAPS
#define DEBUG(x) printf x
#else
#define DEBUG(x)
#endif
typedef struct _traplist_t {
struct _traplist_t *next;
const trap_t *trap;
} traplist_t;
static traplist_t *traplist;
static int install_trap(const trap_t *t);
static int remove_trap(const trap_t *t);
/* ------------------------------------------------------------------------- */
/* Trap-related resources. */
/* Flag: Should we avoid installing traps at all? */
static int no_traps_enabled;
static int set_no_traps_enabled(resource_value_t v)
{
int new_value = (int) v;
if ((!no_traps_enabled && new_value) || (no_traps_enabled && !new_value)) {
if (new_value) {
/* Traps have been disabled. */
traplist_t *p;
for (p = traplist; p != NULL; p = p->next)
remove_trap(p->trap);
} else {
/* Traps have been enabled. */
traplist_t *p;
for (p = traplist; p != NULL; p = p->next)
install_trap(p->trap);
}
}
no_traps_enabled = new_value;
return 0;
}
static resource_t resources[] = {
{ "NoTraps", RES_INTEGER, (resource_value_t) 0,
(resource_value_t) &no_traps_enabled, set_no_traps_enabled },
{ NULL }
};
int traps_init_resources(void)
{
return resources_register(resources);
}
/* ------------------------------------------------------------------------- */
/* Trap-related command-line options. */
static cmdline_option_t cmdline_options[] = {
{ "-traps", SET_RESOURCE, 0, NULL, NULL, "NoTraps", (resource_value_t) 0,
NULL, "Enable Kernal serial traps for fast serial/tape emulation" },
{ "+traps", SET_RESOURCE, 0, NULL, NULL, "NoTraps", (resource_value_t) 1,
NULL, "Do not install any Kernal traps" },
{ NULL }
};
int traps_init_cmdline_options(void)
{
return cmdline_register_options(cmdline_options);
}
/* ------------------------------------------------------------------------- */
void traps_init(void)
{
traplist = NULL;
}
static int install_trap(const trap_t *t)
{
int i;
DEBUG(("TRAPS: Patching ROM for trap `%s' at $%04X\n",
t->name, t->address));
for (i = 0; i < 3; i++) {
if (read_rom(t->address + i) != t->check[i]) {
printf("TRAPS: Incorrect checkbyte for trap `%s'. Not installed.\n",
t->name);
return -1;
}
}
/* BRK (0x00) is trap-opcode. */
store_rom(t->address, 0x00);
return 0;
}
int traps_add(const trap_t *t)
{
traplist_t *p;
DEBUG(("TRAPS: Adding trap `%s' at $%04X (enabled=%d).\n", t->name, t->address, !no_traps_enabled));
p = (traplist_t *) xmalloc (sizeof (traplist_t));
p->next = traplist;
p->trap = t;
traplist = p;
if (!no_traps_enabled)
install_trap(t);
return 0;
}
static int remove_trap(const trap_t *t)
{
DEBUG(("TRAPS: Removing trap `%s' at $%04X.\n", t->name, t->address));
if (read_rom(t->address) != 0x00) {
printf("TRAPS: No trap `%s' installed?\n", t->name);
return -1;
}
store_rom(t->address, t->check[0]);
return 0;
}
int traps_remove(const trap_t *t)
{
traplist_t *p = traplist, *prev = NULL;
while (p) {
if (p->trap->address == t->address)
break;
prev = p;
p = p->next;
}
if (!p) {
printf("TRAPS: Trap `%s' not found.\n", t->name);
return -1;
}
if (prev)
prev->next = p->next;
else
traplist = p ->next;
free(p);
if (!no_traps_enabled)
remove_trap(t);
return 0;
}
int traps_handler(void)
{
traplist_t *p = traplist;
unsigned int pc = MOS6510_REGS_GET_PC(&maincpu_regs);
DEBUG(("TRAPS: Checking for trap at PC=$%04X, p=%p.\n", maincpu_regs.pc,p));
while (p) {
DEBUG(("TRAPS: check Address %04X\n", p->trap->address));
if (p->trap->address == pc) {
/* This allows the trap function to remove traps. */
ADDRESS resume_address = p->trap->resume_address;
DEBUG(("TRAPS: Found %s\n", p->trap->name));
(*p->trap->func)();
/* XXX ALERT! `p' might not be valid anymore here, because
`p->trap->func()' might have removed all the traps. */
MOS6510_REGS_SET_PC(&maincpu_regs, resume_address);
return 0;
}
p = p->next;
}
return -1;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.