2013-07-06 04:37:13 +00:00
|
|
|
/*
|
2013-06-11 07:08:15 +00:00
|
|
|
* Apple // emulator for Linux: Main debugger routines
|
|
|
|
*
|
2013-07-06 04:37:13 +00:00
|
|
|
* Copyright 1997, 1998, 2013 Aaron Culliney
|
2013-06-11 07:08:15 +00:00
|
|
|
* Copyright 1998, 1999, 2000 Michael Deutschmann
|
|
|
|
*
|
|
|
|
* This software package is subject to the GNU General Public License
|
2013-07-06 04:37:13 +00:00
|
|
|
* version 2 or later (your choice) as published by the Free Software
|
2013-06-11 07:08:15 +00:00
|
|
|
* Foundation.
|
|
|
|
*
|
2013-07-06 04:37:13 +00:00
|
|
|
* THERE ARE NO WARRANTIES WHATSOEVER.
|
|
|
|
*
|
|
|
|
* Originally added to emulator project in 1997 by Aaron Culliney
|
2013-06-11 07:08:15 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "debug.h"
|
|
|
|
#include "misc.h"
|
|
|
|
#include "keys.h"
|
|
|
|
#include "video.h"
|
|
|
|
#include "disk.h"
|
|
|
|
#include "interface.h"
|
|
|
|
#include "cpu.h"
|
|
|
|
#include "prefs.h"
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
const struct opcode_struct *opcodes;
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
int step_next; /* stepping over instructions */
|
|
|
|
char second_buf[BUF_Y][BUF_X]; /* scratch buffer for output */
|
|
|
|
int num_buffer_lines; /* num lines of output */
|
|
|
|
int arg1, arg2, arg3; /* command arguments */
|
|
|
|
int breakpoints[MAX_BRKPTS]; /* memory breakpoints */
|
|
|
|
int watchpoints[MAX_BRKPTS]; /* memory watchpoints */
|
2013-06-11 07:08:15 +00:00
|
|
|
|
|
|
|
/* debugger globals */
|
2013-06-19 07:07:41 +00:00
|
|
|
static char screen[SCREEN_Y][SCREEN_X] =
|
2013-07-06 04:37:13 +00:00
|
|
|
{ "||||||||||||||||||||||||||||||||||||||||",
|
|
|
|
"| |",
|
|
|
|
"| |",
|
|
|
|
"| |",
|
|
|
|
"| |",
|
|
|
|
"| |",
|
|
|
|
"| |",
|
|
|
|
"| |",
|
|
|
|
"| |",
|
|
|
|
"| |",
|
|
|
|
"| |",
|
|
|
|
"| |",
|
|
|
|
"| |",
|
|
|
|
"| |",
|
|
|
|
"| |",
|
|
|
|
"| |",
|
|
|
|
"| |",
|
|
|
|
"| |",
|
|
|
|
"| |",
|
|
|
|
"| |",
|
|
|
|
"| |",
|
|
|
|
"| |",
|
|
|
|
"| |",
|
|
|
|
"||||||||||||||||||||||||||||||||||||||||" };
|
|
|
|
|
|
|
|
static char command_buf[BUF_Y][BUF_X]; /* command line prompt */
|
|
|
|
char lexbuf[BUF_X+2]; /* comman line to be flex'ed */
|
2013-06-11 07:08:15 +00:00
|
|
|
|
|
|
|
unsigned char current_opcode;
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
int op_breakpoints[256]; /* opcode breakpoints */
|
2013-06-11 07:08:15 +00:00
|
|
|
|
|
|
|
/* in debug.l */
|
2013-07-06 04:37:13 +00:00
|
|
|
extern int debuglex(); /* yylex() */
|
2013-06-11 07:08:15 +00:00
|
|
|
extern void init_lex(char *buf, int size);
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
c_get_current_rambank (addrs) - return the current ram bank for addrs.
|
2013-07-06 04:37:13 +00:00
|
|
|
returns 0 = bank 0
|
|
|
|
1 = bank 1
|
2013-06-11 07:08:15 +00:00
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
int c_get_current_rambank(int addrs) {
|
2013-07-06 04:37:13 +00:00
|
|
|
if ((addrs >= 0x200) && (addrs < 0xD000))
|
|
|
|
{
|
2013-06-11 07:08:15 +00:00
|
|
|
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
/* SLOTROM */
|
|
|
|
if ((addrs >= 0xC100) && (addrs < 0xD000))
|
|
|
|
{
|
|
|
|
/* expansion rom */
|
|
|
|
if ((addrs >= 0xC800) && (addrs < 0xD000))
|
|
|
|
{
|
|
|
|
return 1; /* always internal
|
2013-06-11 07:08:15 +00:00
|
|
|
* (the real rules are more complex, but
|
|
|
|
* this'll suffice since the slot 3 pseudo-card
|
|
|
|
* is the only one with c8 space) */
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* if SLOTCXROM, then internal rom (regardless of
|
2013-06-11 07:08:15 +00:00
|
|
|
SLOTC3ROM setting). */
|
2013-07-06 04:37:13 +00:00
|
|
|
if (softswitches & SS_CXROM)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* slot 3 rom */
|
|
|
|
if ((addrs >= 0xC300) && (addrs < 0xC400))
|
|
|
|
{
|
|
|
|
return !!(softswitches & SS_C3ROM);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0; /* peripheral rom */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* text page 1 */
|
|
|
|
if ((addrs >= 0x400) && (addrs < 0x800))
|
|
|
|
{
|
|
|
|
return !!(softswitches & SS_TEXTRD);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* hires page 1 with 80STORE and HIRES on */
|
|
|
|
if ((addrs >= 0x2000) && (addrs < 0x4000))
|
|
|
|
{
|
|
|
|
return !!(softswitches & SS_HGRRD);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* otherwise return RAMRD flag */
|
|
|
|
return !!(softswitches & SS_RAMRD);
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* executing in ALTZP space. */
|
|
|
|
return !!(softswitches & SS_ALTZP);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
get_current_opcode () - returns the opcode from the address that
|
|
|
|
the PC is currently reading from.
|
2013-07-06 04:37:13 +00:00
|
|
|
returns 0 = bank 0
|
|
|
|
1 = bank 1
|
2013-06-11 07:08:15 +00:00
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
unsigned char get_current_opcode() {
|
|
|
|
int bank = c_get_current_rambank(cpu65_current.pc);
|
|
|
|
int lcbank = 0;
|
|
|
|
|
|
|
|
/* main RAM */
|
2013-07-06 04:37:13 +00:00
|
|
|
if (cpu65_current.pc < 0xD000)
|
|
|
|
{
|
|
|
|
return apple_ii_64k[bank][cpu65_current.pc];
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* LC RAM */
|
2013-07-06 04:37:13 +00:00
|
|
|
if (cpu65_current.pc >= 0xE000)
|
|
|
|
{
|
|
|
|
if (softswitches & SS_LCRAM)
|
|
|
|
{
|
|
|
|
return language_card[bank][cpu65_current.pc-0xE000];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return apple_ii_64k[bank][cpu65_current.pc];
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* LC BANK RAM */
|
|
|
|
if (softswitches & SS_BANK2)
|
2013-07-06 04:37:13 +00:00
|
|
|
{
|
|
|
|
lcbank = 0x1000;
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
|
|
|
|
if (softswitches & SS_LCRAM)
|
2013-07-06 04:37:13 +00:00
|
|
|
{
|
|
|
|
return language_banks[bank][cpu65_current.pc-0xD000+lcbank];
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
else
|
2013-07-06 04:37:13 +00:00
|
|
|
{
|
|
|
|
return apple_ii_64k[bank][cpu65_current.pc];
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
dump_mem () - hexdump of memory to debug console
|
2013-07-06 04:37:13 +00:00
|
|
|
we DO NOT wrap the display : 0xffff -> 0x0 (programs can't wrap)
|
2013-06-11 07:08:15 +00:00
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
void dump_mem(int addrs, int len, int lc, int do_ascii, int rambank) {
|
|
|
|
int i, j, mod, end;
|
|
|
|
unsigned char op;
|
2013-07-06 04:37:13 +00:00
|
|
|
int orig_addrs = addrs; /* address for display */
|
2013-06-11 07:08:15 +00:00
|
|
|
|
|
|
|
/* check which rambank */
|
2013-07-06 04:37:13 +00:00
|
|
|
if (rambank == -1)
|
|
|
|
{
|
|
|
|
rambank = c_get_current_rambank(addrs);
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!lc && (softswitches & SS_LCRAM) && (addrs >= 0xd000))
|
2013-07-06 04:37:13 +00:00
|
|
|
{
|
2013-06-11 07:08:15 +00:00
|
|
|
/* read lc anyway */
|
2013-07-06 04:37:13 +00:00
|
|
|
lc = 1 + !!(softswitches & SS_BANK2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((addrs < 0) || (addrs > 0xffff))
|
|
|
|
{
|
|
|
|
addrs = cpu65_current.pc;
|
|
|
|
orig_addrs = addrs;
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
if (lc)
|
|
|
|
{
|
|
|
|
orig_addrs = addrs;
|
|
|
|
if ((addrs >= 0xd000) && (addrs <= 0xffff))
|
|
|
|
{
|
|
|
|
addrs -= 0xd000;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((addrs < 0) || (addrs > 0x2fff))
|
|
|
|
{
|
|
|
|
addrs = 0;
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
2013-07-06 04:37:13 +00:00
|
|
|
|
|
|
|
if ((len < 1) || (len > 256))
|
|
|
|
{
|
|
|
|
len = 256;
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
if (do_ascii && (len > 128))
|
|
|
|
{
|
|
|
|
len = 128;
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* save hexdump in second_buf */
|
|
|
|
end = (lc) ? 0x3000 : 0x10000;
|
2013-07-06 04:37:13 +00:00
|
|
|
for (i = num_buffer_lines-1, j = 0; ((j < len) && (addrs+j < end)); j++)
|
|
|
|
{
|
|
|
|
|
|
|
|
mod = j % (16 >> do_ascii);
|
|
|
|
|
|
|
|
if (lc)
|
|
|
|
{
|
|
|
|
op = (addrs+j >= 0x1000) ? language_card[rambank][(addrs+j)-0x1000]
|
|
|
|
: (lc == 1) ? language_banks[rambank][addrs+j]
|
|
|
|
: language_banks[rambank][0x1000+addrs+j];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
op = apple_ii_64k[rambank][addrs+j];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mod)
|
|
|
|
{
|
|
|
|
if (++i)
|
|
|
|
{
|
|
|
|
for (mod=0; mod<BUF_X; mod++)
|
|
|
|
{
|
|
|
|
if (second_buf[i-1][mod] == '\0')
|
|
|
|
{
|
|
|
|
second_buf[i-1][mod] = ' ';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(second_buf[i], ' ', BUF_X); mod = 0;
|
|
|
|
sprintf(second_buf[i], "%04X:%02X", orig_addrs+j, op);
|
|
|
|
if (do_ascii)
|
|
|
|
{
|
|
|
|
sprintf(second_buf[i]+23, "%c",
|
|
|
|
((op&0x7f) > 31) ? (op&0x7f) : '.');
|
|
|
|
}
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
sprintf(second_buf[i]+5+mod*2, "%02X", op);
|
|
|
|
if (do_ascii)
|
|
|
|
{
|
|
|
|
sprintf(second_buf[i]+23+mod, "%c",
|
|
|
|
((op&0x7f) > 31) ? (op&0x7f) : '.');
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
2013-07-06 04:37:13 +00:00
|
|
|
|
2013-06-11 07:08:15 +00:00
|
|
|
for (mod=0; mod<BUF_X; mod++)
|
2013-07-06 04:37:13 +00:00
|
|
|
{
|
|
|
|
if (second_buf[i][mod] == '\0')
|
|
|
|
{
|
|
|
|
second_buf[i][mod] = ' ';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-11 07:08:15 +00:00
|
|
|
num_buffer_lines = i + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
search_mem () - search memory for bytes
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
void search_mem(char *hexstr, int lc, int rambank) {
|
|
|
|
int i = 0, j = 0, end, op;
|
|
|
|
static char scratch[3];
|
|
|
|
unsigned char byte;
|
|
|
|
|
|
|
|
end = (lc) ? 0x3000 : 0x10000;
|
|
|
|
|
|
|
|
/* check which rambank for cpu65_current.pc */
|
2013-07-06 04:37:13 +00:00
|
|
|
if (rambank == -1)
|
|
|
|
{
|
|
|
|
rambank = c_get_current_rambank(cpu65_current.pc);
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* iterate over memory */
|
2013-07-06 04:37:13 +00:00
|
|
|
for (i = 0; i < end; i++)
|
|
|
|
{
|
|
|
|
strncpy(scratch, hexstr+j, 2); /* extract a byte */
|
|
|
|
byte = (unsigned char) strtol(scratch, (char**)NULL, 16);
|
|
|
|
|
|
|
|
if (lc)
|
|
|
|
{
|
|
|
|
op = (i >= 0x1000) ? language_card[rambank][i-0x1000]
|
|
|
|
: (lc == 1) ? language_banks[rambank][i]
|
|
|
|
: language_banks[rambank][0x1000+i];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
op = apple_ii_64k[rambank][i];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (byte == op) /* matched byte? */
|
|
|
|
{
|
|
|
|
++j; /* increment */
|
|
|
|
if (!isxdigit(*(hexstr+j))) /* end of bytes? */
|
|
|
|
{ /* then we found a match */
|
|
|
|
sprintf(second_buf[num_buffer_lines], "%04X: %s",
|
|
|
|
i-(j>>1), hexstr);
|
|
|
|
num_buffer_lines = (num_buffer_lines + 1) % (BUF_Y-2);
|
|
|
|
j = 0; continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
++j;
|
|
|
|
if (!isxdigit(*(hexstr+j))) /* end of bytes? */
|
|
|
|
{ /* then we found a match */
|
|
|
|
sprintf(second_buf[num_buffer_lines], "%04X: %s",
|
|
|
|
i-(j>>1)+1, hexstr);
|
|
|
|
num_buffer_lines = (num_buffer_lines + 1) % (BUF_Y-2);
|
|
|
|
j = 0; continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
j = 0;
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
set_mem () - write to memory. we use the do_write_memory routine
|
|
|
|
to "safely" set memory...
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
void set_mem(int addrs, char *hexstr) {
|
|
|
|
static char scratch[3];
|
|
|
|
unsigned char data;
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
if ((addrs < 0) || (addrs > 0xffff))
|
|
|
|
{
|
|
|
|
sprintf(second_buf[num_buffer_lines++], "invalid address");
|
|
|
|
return;
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
while (*hexstr)
|
|
|
|
{
|
|
|
|
strncpy(scratch, hexstr, 2);
|
|
|
|
data = (unsigned char) strtol(scratch, (char**)NULL, 16);
|
2013-06-11 07:08:15 +00:00
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
/* call the set_memory routine, which knows how to route the
|
2013-06-11 07:08:15 +00:00
|
|
|
request */
|
2013-07-06 04:37:13 +00:00
|
|
|
cpu65_direct_write(addrs,data);
|
|
|
|
|
|
|
|
++hexstr;
|
|
|
|
if (!*hexstr)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
++hexstr;
|
|
|
|
if (++addrs > 0xffff)
|
|
|
|
{
|
|
|
|
return; /* don't overwrite memory */
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
set_lc_mem () - specifically write to apple II language card RAM memory
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
void set_lc_mem(int addrs, int lcbank, char *hexstr) {
|
|
|
|
static char scratch[3];
|
|
|
|
unsigned char data;
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
if ((addrs >= 0xd000) && (addrs <= 0xffff))
|
|
|
|
{
|
|
|
|
addrs -= 0xd000;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((addrs < 0) || (addrs > 0x2fff))
|
|
|
|
{
|
|
|
|
sprintf(second_buf[num_buffer_lines++], "invalid LC address");
|
|
|
|
return;
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
while (*hexstr)
|
|
|
|
{
|
|
|
|
strncpy(scratch, hexstr, 2);
|
|
|
|
data = (unsigned char) strtol(scratch, (char**)NULL, 16);
|
2013-06-11 07:08:15 +00:00
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
/* ??? no way to write to aux LC banks */
|
2013-06-11 07:08:15 +00:00
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
if (addrs >= 0x1000)
|
|
|
|
{
|
2013-06-11 07:08:15 +00:00
|
|
|
language_card[0][addrs - 0x1000] = data;
|
2013-07-06 04:37:13 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
if (lcbank)
|
|
|
|
{
|
|
|
|
language_banks[0][addrs] = data;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
language_banks[0][addrs + 0x1000] = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
++hexstr;
|
|
|
|
if (!*hexstr)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
++hexstr;
|
|
|
|
if (++addrs > 0x2fff)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
bload () - bload file data into emulator. this is essentially the
|
|
|
|
same as the set_mem routine. we use the do_write_memory routine to
|
|
|
|
"safely" set memory...
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
void bload(FILE *f, char *name, int addrs) {
|
|
|
|
unsigned char *hexstr = NULL;
|
|
|
|
int len = -1;
|
|
|
|
unsigned char data;
|
2013-07-06 04:37:13 +00:00
|
|
|
|
|
|
|
if ((addrs < 0) || (addrs > 0xffff))
|
|
|
|
{
|
|
|
|
sprintf(second_buf[num_buffer_lines++], "invalid address");
|
|
|
|
return;
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
while ((len = fread(temp, 1, TEMPSIZE, f)))
|
|
|
|
{
|
|
|
|
hexstr = (unsigned char*)temp;
|
|
|
|
for (; len > 0; len--)
|
|
|
|
{
|
|
|
|
data = *hexstr;
|
|
|
|
|
|
|
|
/* call the set_memory routine, which knows how to route
|
|
|
|
the request */
|
|
|
|
cpu65_direct_write(addrs,data);
|
|
|
|
|
|
|
|
++hexstr;
|
|
|
|
if (++addrs > 0xffff)
|
|
|
|
{
|
|
|
|
return; /* don't overwrite memory */
|
|
|
|
}
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
2013-07-06 04:37:13 +00:00
|
|
|
|
2013-06-11 07:08:15 +00:00
|
|
|
sprintf(second_buf[num_buffer_lines++], "bloaded: %s", name);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
disasm () - disassemble instructions
|
2013-07-06 04:37:13 +00:00
|
|
|
we DO NOT wrap the display : 0xffff -> 0x0
|
2013-06-11 07:08:15 +00:00
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
void disasm(int addrs, int len, int lc, int rambank) {
|
|
|
|
static char fmt[64];
|
|
|
|
unsigned char op;
|
|
|
|
char arg1, arg2;
|
|
|
|
int i, j, k, end, orig_addrs = addrs;
|
|
|
|
|
|
|
|
/* check which rambank for cpu65_current.pc */
|
2013-07-06 04:37:13 +00:00
|
|
|
if (rambank == -1)
|
|
|
|
{
|
|
|
|
rambank = c_get_current_rambank(addrs);
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!lc && (softswitches & SS_LCRAM) && (addrs >= 0xd000))
|
2013-07-06 04:37:13 +00:00
|
|
|
{
|
2013-06-11 07:08:15 +00:00
|
|
|
/* read lc anyway */
|
2013-07-06 04:37:13 +00:00
|
|
|
lc = 1 + !!(softswitches & SS_BANK2);
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
|
|
|
|
/* handle invalid address request */
|
2013-07-06 04:37:13 +00:00
|
|
|
if ((addrs < 0) || (addrs > 0xffff))
|
|
|
|
{
|
|
|
|
addrs = cpu65_current.pc;
|
|
|
|
orig_addrs = addrs;
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* disassembling from language card */
|
2013-07-06 04:37:13 +00:00
|
|
|
if (lc)
|
|
|
|
{
|
|
|
|
if ((addrs >= 0xd000) && (addrs <= 0xffff))
|
|
|
|
{
|
|
|
|
addrs -= 0xd000;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((addrs < 0) || (addrs > 0x2fff))
|
|
|
|
{
|
|
|
|
addrs = 0;
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
if (len > BUF_Y - 2)
|
|
|
|
{
|
|
|
|
len = BUF_Y - 2 - num_buffer_lines;
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
|
|
|
|
/* save hexdump in second_buf */
|
|
|
|
end = (lc) ? 0x3000 : 0x10000;
|
|
|
|
for (i = num_buffer_lines, j = addrs, k=orig_addrs;
|
2013-07-06 04:37:13 +00:00
|
|
|
((i<len) && (j<end)); i++, j++)
|
2013-06-11 07:08:15 +00:00
|
|
|
{
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
if (lc)
|
|
|
|
{
|
|
|
|
op = (j >= 0x1000) ? language_card[rambank][j-0x1000]
|
|
|
|
: (lc == 1) ? language_banks[rambank][j]
|
|
|
|
: language_banks[rambank][0x1000+j];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
op = apple_ii_64k[rambank][j];
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (opcodes[op].mode)
|
|
|
|
{
|
|
|
|
case addr_implied:
|
|
|
|
case addr_accumulator: /* no arg */
|
|
|
|
sprintf(second_buf[i], "/%02X/%04X: %02X %s %s",
|
|
|
|
rambank, k++, op, opcodes[op].mnemonic,
|
2013-06-11 07:08:15 +00:00
|
|
|
disasm_templates[opcodes[op].mode]);
|
2013-07-06 04:37:13 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case addr_immediate:
|
|
|
|
case addr_zeropage:
|
|
|
|
case addr_zeropage_x:
|
|
|
|
case addr_zeropage_y:
|
|
|
|
case addr_indirect:
|
|
|
|
case addr_indirect_x:
|
|
|
|
case addr_indirect_y: /* byte arg */
|
|
|
|
if (k == 0xffff)
|
|
|
|
{
|
|
|
|
num_buffer_lines = i;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lc)
|
|
|
|
{
|
|
|
|
arg1 = (j >= 0x1000) ? language_card[rambank][++j-0x1000]
|
|
|
|
: (lc == 1) ? language_banks[rambank][++j]
|
|
|
|
: language_banks[rambank][++j+0x1000];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
arg1 = apple_ii_64k[rambank][++j];
|
|
|
|
}
|
|
|
|
|
|
|
|
sprintf(fmt, "/%02X/%04X: %02X%02X %s %s",
|
|
|
|
rambank, k, op, (unsigned char)arg1,
|
|
|
|
opcodes[op].mnemonic,
|
2013-06-11 07:08:15 +00:00
|
|
|
disasm_templates[opcodes[op].mode]);
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
sprintf(second_buf[i], fmt, (unsigned char)arg1);
|
|
|
|
k+=2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case addr_absolute:
|
|
|
|
case addr_absolute_x:
|
|
|
|
case addr_absolute_y:
|
|
|
|
case addr_j_indirect:
|
|
|
|
case addr_j_indirect_x: /* word arg */
|
|
|
|
if (k >= 0xfffe)
|
|
|
|
{
|
|
|
|
num_buffer_lines = i;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lc)
|
|
|
|
{
|
|
|
|
arg1 = (j >= 0x1000) ? language_card[rambank][++j-0x1000]
|
|
|
|
: (lc == 1) ? language_banks[rambank][++j]
|
|
|
|
: language_banks[rambank][++j+0x1000];
|
|
|
|
arg2 = (j >= 0x1000) ? language_card[rambank][++j-0x1000]
|
|
|
|
: (lc == 1) ? language_banks[rambank][++j]
|
|
|
|
: language_banks[rambank][++j+0x1000];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
arg1 = apple_ii_64k[rambank][++j];
|
|
|
|
arg2 = apple_ii_64k[rambank][++j];
|
|
|
|
}
|
|
|
|
|
|
|
|
sprintf(fmt, "/%02X/%04X: %02X%02X%02X %s %s",
|
|
|
|
rambank, k, op, (unsigned char)arg1, (unsigned char)arg2,
|
|
|
|
opcodes[op].mnemonic,
|
2013-06-11 07:08:15 +00:00
|
|
|
disasm_templates[opcodes[op].mode]);
|
2013-07-06 04:37:13 +00:00
|
|
|
sprintf(second_buf[i], fmt, (unsigned char)arg2,
|
|
|
|
(unsigned char)arg1);
|
|
|
|
k+=3;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case addr_relative: /* offset */
|
|
|
|
if (k == 0xffff)
|
|
|
|
{
|
|
|
|
num_buffer_lines = i;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lc)
|
|
|
|
{
|
|
|
|
arg1 = (j >= 0x1000) ? language_card[rambank][++j-0x1000]
|
|
|
|
: (lc == 1) ? language_banks[rambank][++j]
|
|
|
|
: language_banks[rambank][++j+0x1000];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
arg1 = apple_ii_64k[rambank][++j];
|
|
|
|
}
|
|
|
|
|
|
|
|
sprintf(fmt, "/%02X/%04X: %02X%02X %s %s",
|
|
|
|
rambank, k, op, (unsigned char)arg1,
|
|
|
|
opcodes[op].mnemonic,
|
2013-06-11 07:08:15 +00:00
|
|
|
disasm_templates[opcodes[op].mode]);
|
2013-07-06 04:37:13 +00:00
|
|
|
if (arg1 < 0)
|
|
|
|
{
|
|
|
|
sprintf(second_buf[i], fmt,
|
|
|
|
k + arg1 + 2, '-', (unsigned char)(-arg1));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf(second_buf[i], fmt,
|
|
|
|
k + arg1 + 2, '+', (unsigned char)arg1);
|
|
|
|
}
|
|
|
|
|
|
|
|
k+=2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: /* shouldn't happen */
|
|
|
|
sprintf(second_buf[i], "args to opcode incorrect!");
|
|
|
|
break;
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
2013-07-06 04:37:13 +00:00
|
|
|
|
2013-06-11 07:08:15 +00:00
|
|
|
num_buffer_lines = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
show_regs () - shows 6502 registers
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
void show_regs() {
|
|
|
|
sprintf(second_buf[num_buffer_lines++], "PC = %04X EA = %04X SP = %04X",
|
2013-07-06 04:37:13 +00:00
|
|
|
cpu65_current.pc,
|
|
|
|
cpu65_debug.ea,
|
|
|
|
cpu65_current.sp + 0x0100);
|
2013-06-11 07:08:15 +00:00
|
|
|
sprintf(second_buf[num_buffer_lines++],
|
2013-07-06 04:37:13 +00:00
|
|
|
"X = %02X Y = %02X A = %02X F = %02X",
|
|
|
|
cpu65_current.x,
|
|
|
|
cpu65_current.y,
|
|
|
|
cpu65_current.a,
|
|
|
|
cpu65_current.f);
|
2013-06-11 07:08:15 +00:00
|
|
|
|
|
|
|
memset(second_buf[num_buffer_lines], ' ', BUF_X);
|
2013-07-06 04:37:13 +00:00
|
|
|
if (cpu65_current.f & C_Flag)
|
|
|
|
{
|
|
|
|
second_buf[num_buffer_lines][0]='C';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpu65_current.f & X_Flag)
|
|
|
|
{
|
|
|
|
second_buf[num_buffer_lines][1]='X';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpu65_current.f & I_Flag)
|
|
|
|
{
|
|
|
|
second_buf[num_buffer_lines][2]='I';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpu65_current.f & V_Flag)
|
|
|
|
{
|
|
|
|
second_buf[num_buffer_lines][3]='V';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpu65_current.f & B_Flag)
|
|
|
|
{
|
|
|
|
second_buf[num_buffer_lines][4]='B';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpu65_current.f & D_Flag)
|
|
|
|
{
|
|
|
|
second_buf[num_buffer_lines][5]='D';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpu65_current.f & Z_Flag)
|
|
|
|
{
|
|
|
|
second_buf[num_buffer_lines][6]='Z';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpu65_current.f & N_Flag)
|
|
|
|
{
|
|
|
|
second_buf[num_buffer_lines][7]='N';
|
|
|
|
}
|
|
|
|
|
2013-06-11 07:08:15 +00:00
|
|
|
++num_buffer_lines;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
will_branch () = will instruction branch?
|
2013-07-06 04:37:13 +00:00
|
|
|
-1 - n/a
|
|
|
|
0 - no it won't
|
|
|
|
>0 - yes it will
|
2013-06-11 07:08:15 +00:00
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
static int will_branch() {
|
|
|
|
|
|
|
|
unsigned char op = get_current_opcode();
|
2013-07-06 04:37:13 +00:00
|
|
|
|
|
|
|
switch (op)
|
|
|
|
{
|
|
|
|
case 0x10: /* BPL */
|
|
|
|
return (int) !(cpu65_current.f & N_Flag);
|
|
|
|
case 0x30: /* BMI */
|
|
|
|
return (int) (cpu65_current.f & N_Flag);
|
|
|
|
case 0x50: /* BVC */
|
|
|
|
return (int) !(cpu65_current.f & V_Flag);
|
|
|
|
case 0x70: /* BVS */
|
|
|
|
return (int) (cpu65_current.f & V_Flag);
|
|
|
|
case 0x80: /* BRA */
|
|
|
|
return 1;
|
|
|
|
case 0x90: /* BCC */
|
|
|
|
return (int) !(cpu65_current.f & C_Flag);
|
|
|
|
case 0xb0: /* BCS */
|
|
|
|
return (int) (cpu65_current.f & C_Flag);
|
|
|
|
case 0xd0: /* BNE */
|
|
|
|
return (int) !(cpu65_current.f & Z_Flag);
|
|
|
|
case 0xf0: /* BEQ */
|
|
|
|
return (int) (cpu65_current.f & Z_Flag);
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
set_halt () = set a breakpoint or watchpoint in memory
|
2013-07-06 04:37:13 +00:00
|
|
|
type = points to "watchpoints" or "breakpoints" array
|
2013-06-11 07:08:15 +00:00
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
void set_halt(int *type, int addrs) {
|
|
|
|
int i;
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
for (i = 0; i < MAX_BRKPTS; i++)
|
|
|
|
{
|
|
|
|
if (type[i] == -1)
|
|
|
|
{
|
|
|
|
type[i] = addrs;
|
|
|
|
sprintf(second_buf[num_buffer_lines++], "set at %04X", addrs);
|
|
|
|
return;
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
2013-07-06 04:37:13 +00:00
|
|
|
|
2013-06-11 07:08:15 +00:00
|
|
|
sprintf(second_buf[num_buffer_lines++], "too many!");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
clear_halt () = unset a critical breakpoint or watchpoint in memory
|
2013-07-06 04:37:13 +00:00
|
|
|
type = points to "watchpoints" or "breakpoints" array
|
|
|
|
pt = (pt - 1) into type. 0 indicates clear all.
|
2013-06-11 07:08:15 +00:00
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
void clear_halt(int *type, int pt) {
|
|
|
|
int i;
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
if (!pt) /* unset all */
|
|
|
|
{
|
|
|
|
for (i = 0; i < MAX_BRKPTS; i++)
|
|
|
|
{
|
|
|
|
type[i] = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
2013-07-06 04:37:13 +00:00
|
|
|
|
|
|
|
type[pt-1] = -1; /* unset single */
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
set_halt_opcode () = set a breakpoint on a particular opcode.
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
void set_halt_opcode(unsigned char opcode) {
|
|
|
|
op_breakpoints[opcode] = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
clear_halt_opcode () = unset an opcode breakpoint.
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
void clear_halt_opcode(unsigned char opcode) {
|
|
|
|
op_breakpoints[opcode] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
set_halt_65c02 () = set a breakpoint on all 65c02 instructions.
|
|
|
|
assumes that you are in //e mode...
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
void set_halt_65c02() {
|
|
|
|
set_halt_opcode((uchar)0x02); set_halt_opcode((uchar)0x04);
|
|
|
|
set_halt_opcode((uchar)0x0C); set_halt_opcode((uchar)0x12);
|
|
|
|
set_halt_opcode((uchar)0x14); set_halt_opcode((uchar)0x1A);
|
|
|
|
set_halt_opcode((uchar)0x1C); set_halt_opcode((uchar)0x32);
|
|
|
|
set_halt_opcode((uchar)0x34); set_halt_opcode((uchar)0x3A);
|
|
|
|
set_halt_opcode((uchar)0x3C); set_halt_opcode((uchar)0x52);
|
|
|
|
set_halt_opcode((uchar)0x5A); set_halt_opcode((uchar)0x64);
|
|
|
|
set_halt_opcode((uchar)0x72); set_halt_opcode((uchar)0x74);
|
|
|
|
set_halt_opcode((uchar)0x7A); set_halt_opcode((uchar)0x7C);
|
|
|
|
set_halt_opcode((uchar)0x80); set_halt_opcode((uchar)0x89);
|
|
|
|
set_halt_opcode((uchar)0x92); set_halt_opcode((uchar)0x9C);
|
|
|
|
set_halt_opcode((uchar)0x9E); set_halt_opcode((uchar)0xB2);
|
|
|
|
set_halt_opcode((uchar)0xD2); set_halt_opcode((uchar)0xDA);
|
|
|
|
set_halt_opcode((uchar)0xF2); set_halt_opcode((uchar)0xFA);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
clear_halt_65c02 () = clear all 65c02 instructions
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
void clear_halt_65c02() {
|
|
|
|
clear_halt_opcode((uchar)0x02); clear_halt_opcode((uchar)0x04);
|
|
|
|
clear_halt_opcode((uchar)0x0C); clear_halt_opcode((uchar)0x12);
|
|
|
|
clear_halt_opcode((uchar)0x14); clear_halt_opcode((uchar)0x1A);
|
|
|
|
clear_halt_opcode((uchar)0x1C); clear_halt_opcode((uchar)0x32);
|
|
|
|
clear_halt_opcode((uchar)0x34); clear_halt_opcode((uchar)0x3A);
|
|
|
|
clear_halt_opcode((uchar)0x3C); clear_halt_opcode((uchar)0x52);
|
|
|
|
clear_halt_opcode((uchar)0x5A); clear_halt_opcode((uchar)0x64);
|
|
|
|
clear_halt_opcode((uchar)0x72); clear_halt_opcode((uchar)0x74);
|
|
|
|
clear_halt_opcode((uchar)0x7A); clear_halt_opcode((uchar)0x7C);
|
|
|
|
clear_halt_opcode((uchar)0x80); clear_halt_opcode((uchar)0x89);
|
|
|
|
clear_halt_opcode((uchar)0x92); clear_halt_opcode((uchar)0x9C);
|
|
|
|
clear_halt_opcode((uchar)0x9E); clear_halt_opcode((uchar)0xB2);
|
|
|
|
clear_halt_opcode((uchar)0xD2); clear_halt_opcode((uchar)0xDA);
|
|
|
|
clear_halt_opcode((uchar)0xF2); clear_halt_opcode((uchar)0xFA);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
at_haltpt () - tests if at haltpt
|
2013-07-06 04:37:13 +00:00
|
|
|
returns 0 = no breaks or watches
|
|
|
|
1 = one break or watchpoint fired
|
|
|
|
n = two or more breaks and/or watches fired
|
2013-06-11 07:08:15 +00:00
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
int at_haltpt() {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* check op_breakpoints */
|
|
|
|
unsigned char op = get_current_opcode();
|
|
|
|
if (op_breakpoints[op])
|
2013-07-06 04:37:13 +00:00
|
|
|
{
|
|
|
|
sprintf(second_buf[num_buffer_lines++],
|
|
|
|
"stopped at %04X bank %d instruction %02X",
|
|
|
|
cpu65_current.pc, c_get_current_rambank(cpu65_current.pc), op);
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
for (i = 0; i < MAX_BRKPTS; i++)
|
|
|
|
{
|
2013-06-11 07:08:15 +00:00
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
if (cpu65_current.pc == breakpoints[i])
|
|
|
|
{
|
|
|
|
sprintf(second_buf[num_buffer_lines++], "stopped at %04X bank %d",
|
|
|
|
breakpoints[i], c_get_current_rambank(cpu65_current.pc));
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
if (cpu65_debug.op) /* only check watchpoints if read/write occured */
|
2013-06-11 07:08:15 +00:00
|
|
|
{
|
2013-07-06 04:37:13 +00:00
|
|
|
for (i = 0; i < MAX_BRKPTS; i++)
|
|
|
|
{
|
|
|
|
if (cpu65_debug.ea == watchpoints[i])
|
|
|
|
{
|
|
|
|
if (cpu65_debug.op & 2)
|
|
|
|
{
|
|
|
|
sprintf(second_buf[num_buffer_lines++],
|
|
|
|
"wrote: %04X: %02X",
|
|
|
|
watchpoints[i], cpu65_debug.d);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf(second_buf[num_buffer_lines++],
|
|
|
|
"read: %04X", watchpoints[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
cpu65_debug.op = 0; /* only allow WP to trip once */
|
|
|
|
}
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
2013-07-06 04:37:13 +00:00
|
|
|
|
|
|
|
return num_buffer_lines; /* 0 indicates nothing happened */
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
show_breakpts () - show breakpoints and watchpoints
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
void show_breakpts() {
|
|
|
|
int i=num_buffer_lines, k;
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
for (k = 0; k < MAX_BRKPTS; k++)
|
|
|
|
{
|
|
|
|
if ((breakpoints[k] >= 0) && (watchpoints[k] >= 0))
|
|
|
|
{
|
|
|
|
sprintf(second_buf[i++], "break %02d at %04X watch %02d at %04X",
|
|
|
|
k+1, breakpoints[k], k+1, watchpoints[k]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (breakpoints[k] >= 0)
|
|
|
|
{
|
|
|
|
sprintf(second_buf[i++], "break %02d at %04X",
|
|
|
|
k+1, breakpoints[k]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (watchpoints[k] >= 0)
|
|
|
|
{
|
|
|
|
memset(second_buf[i], ' ', BUF_X);
|
|
|
|
sprintf(second_buf[i++]+16, " watch %02d at %04X",
|
|
|
|
k+1, watchpoints[k]);
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
2013-07-06 04:37:13 +00:00
|
|
|
|
2013-06-11 07:08:15 +00:00
|
|
|
num_buffer_lines = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
show_opcode_breakpts () - show opcode breakpoints
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
void show_opcode_breakpts() {
|
|
|
|
int i=num_buffer_lines, k;
|
|
|
|
|
|
|
|
sprintf(second_buf[i++], " 0 1 2 3 4 5 6 7 8 9 A B C D E F");
|
|
|
|
sprintf(second_buf[i++], " |-------------------------------|");
|
2013-07-06 04:37:13 +00:00
|
|
|
for (k = 0; k < 0x10; k++)
|
|
|
|
{
|
|
|
|
sprintf(second_buf[i++],
|
|
|
|
" %X|%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s|", k,
|
|
|
|
op_breakpoints[k ] ? "x" : " ",
|
|
|
|
op_breakpoints[k+0x10] ? "x" : " ",
|
|
|
|
op_breakpoints[k+0x20] ? "x" : " ",
|
|
|
|
op_breakpoints[k+0x30] ? "x" : " ",
|
|
|
|
op_breakpoints[k+0x40] ? "x" : " ",
|
|
|
|
op_breakpoints[k+0x50] ? "x" : " ",
|
|
|
|
op_breakpoints[k+0x60] ? "x" : " ",
|
|
|
|
op_breakpoints[k+0x70] ? "x" : " ",
|
|
|
|
op_breakpoints[k+0x80] ? "x" : " ",
|
|
|
|
op_breakpoints[k+0x90] ? "x" : " ",
|
|
|
|
op_breakpoints[k+0xA0] ? "x" : " ",
|
|
|
|
op_breakpoints[k+0xB0] ? "x" : " ",
|
|
|
|
op_breakpoints[k+0xC0] ? "x" : " ",
|
|
|
|
op_breakpoints[k+0xD0] ? "x" : " ",
|
|
|
|
op_breakpoints[k+0xE0] ? "x" : " ",
|
|
|
|
op_breakpoints[k+0xF0] ? "x" : " ");
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
2013-07-06 04:37:13 +00:00
|
|
|
|
2013-06-11 07:08:15 +00:00
|
|
|
sprintf(second_buf[i++], " |-------------------------------|");
|
|
|
|
|
|
|
|
num_buffer_lines = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
show_lc_info () - show language card info
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
void show_lc_info() {
|
|
|
|
int i = num_buffer_lines;
|
|
|
|
sprintf(second_buf[i++], "lc bank = %d", 1 + !!(softswitches && SS_BANK2));
|
|
|
|
(softswitches & SS_LCWRT) ? sprintf(second_buf[i++], "write LC")
|
2013-07-06 04:37:13 +00:00
|
|
|
: sprintf(second_buf[i++], "LC write protected");
|
2013-06-11 07:08:15 +00:00
|
|
|
(softswitches & SS_LCRAM) ? sprintf(second_buf[i++], "read LC")
|
2013-07-06 04:37:13 +00:00
|
|
|
: sprintf(second_buf[i++], "read ROM");
|
|
|
|
sprintf(second_buf[i++], "second = %d", !!(softswitches && SS_LCSEC));
|
2013-06-11 07:08:15 +00:00
|
|
|
num_buffer_lines = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
void show_misc_info() {
|
|
|
|
int i = num_buffer_lines;
|
2013-07-06 04:37:13 +00:00
|
|
|
sprintf(second_buf[i++], "TEXT (%04X): %s",
|
2013-06-11 07:08:15 +00:00
|
|
|
SW_TEXT + !!(softswitches & SS_TEXT),
|
2013-07-06 04:37:13 +00:00
|
|
|
(softswitches & SS_TEXT) ? "on" : "off");
|
|
|
|
sprintf(second_buf[i++], "MIXED (%04X): %s",
|
2013-06-11 07:08:15 +00:00
|
|
|
SW_MIXED + !!(softswitches & SS_MIXED),
|
2013-07-06 04:37:13 +00:00
|
|
|
(softswitches & SS_MIXED) ? "on" : "off");
|
|
|
|
sprintf(second_buf[i++], "PAGE2 (%04X): %s",
|
2013-06-11 07:08:15 +00:00
|
|
|
SW_PAGE2 + !!(softswitches & SS_PAGE2),
|
2013-07-06 04:37:13 +00:00
|
|
|
(softswitches & SS_PAGE2) ? "on" : "off");
|
|
|
|
sprintf(second_buf[i++], "HIRES (%04X): %s",
|
2013-06-11 07:08:15 +00:00
|
|
|
SW_HIRES + !!(softswitches & SS_HIRES),
|
2013-07-06 04:37:13 +00:00
|
|
|
(softswitches & SS_HIRES) ? "on" : "off");
|
|
|
|
sprintf(second_buf[i++], "80STORE (%04X): %s",
|
2013-06-11 07:08:15 +00:00
|
|
|
SW_80STORE + !!(softswitches & SS_80STORE),
|
2013-07-06 04:37:13 +00:00
|
|
|
(softswitches & SS_80STORE) ? "on" : "off");
|
|
|
|
sprintf(second_buf[i++], "RAMRD (%04X): %s",
|
2013-06-11 07:08:15 +00:00
|
|
|
SW_RAMRD + !!(softswitches & SS_RAMRD),
|
2013-07-06 04:37:13 +00:00
|
|
|
(softswitches & SS_RAMRD) ? "on" : "off");
|
|
|
|
sprintf(second_buf[i++], "RAMWRT (%04X): %s",
|
2013-06-11 07:08:15 +00:00
|
|
|
SW_RAMWRT + !!(softswitches & SS_RAMWRT),
|
|
|
|
(softswitches & SS_RAMWRT) ? "on" : "off");
|
2013-07-06 04:37:13 +00:00
|
|
|
sprintf(second_buf[i++], "ALTZP (%04X): %s",
|
2013-06-11 07:08:15 +00:00
|
|
|
SW_ALTZP + !!(softswitches & SS_ALTZP),
|
2013-07-06 04:37:13 +00:00
|
|
|
(softswitches & SS_ALTZP) ? "on" : "off");
|
|
|
|
sprintf(second_buf[i++], "80COL (%04X): %s",
|
2013-06-11 07:08:15 +00:00
|
|
|
SW_80COL + !!(softswitches & SS_80COL),
|
2013-07-06 04:37:13 +00:00
|
|
|
(softswitches & SS_80COL) ? "on" : "off");
|
|
|
|
sprintf(second_buf[i++], "ALTCHAR (%04X): %s",
|
2013-06-11 07:08:15 +00:00
|
|
|
SW_ALTCHAR + !!(softswitches & SS_ALTCHAR),
|
2013-07-06 04:37:13 +00:00
|
|
|
(softswitches & SS_ALTCHAR) ? "on" : "off");
|
|
|
|
sprintf(second_buf[i++], "SLOTC3ROM (%04X): %s",
|
2013-06-11 07:08:15 +00:00
|
|
|
SW_SLOTC3ROM -/*anomaly*/ !!(softswitches & SS_C3ROM),
|
|
|
|
(softswitches & SS_C3ROM) ? "on" : "off");
|
2013-07-06 04:37:13 +00:00
|
|
|
sprintf(second_buf[i++], "SLOTCXROM (%04X): %s",
|
2013-06-11 07:08:15 +00:00
|
|
|
SW_SLOTCXROM + !!(softswitches & SS_CXROM),
|
|
|
|
(softswitches & SS_CXROM) ? "on" : "off");
|
2013-07-06 04:37:13 +00:00
|
|
|
sprintf(second_buf[i++], "DHIRES (%04X): %s",
|
2013-06-11 07:08:15 +00:00
|
|
|
SW_DHIRES + !!(softswitches && SS_DHIRES),
|
2013-07-06 04:37:13 +00:00
|
|
|
(softswitches & SS_DHIRES) ? "on" : "off");
|
|
|
|
sprintf(second_buf[i++], "IOUDIS (%04X): %s",
|
2013-06-11 07:08:15 +00:00
|
|
|
SW_IOUDIS + !!(softswitches && SS_IOUDIS),
|
2013-07-06 04:37:13 +00:00
|
|
|
(softswitches && SS_IOUDIS) ? "on" : "off");
|
2013-06-11 07:08:15 +00:00
|
|
|
/* sprintf(second_buf[i++], "RDVBLBAR: %s", (SLOTCXROM & 0x80) */
|
2013-07-06 04:37:13 +00:00
|
|
|
/* ? "on" : "off"); */
|
2013-06-11 07:08:15 +00:00
|
|
|
|
|
|
|
num_buffer_lines = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
show_disk_info () - disk II info
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
void show_disk_info() {
|
|
|
|
static char tmp[32];
|
|
|
|
int i = num_buffer_lines, len = 0, off = 19;
|
|
|
|
|
|
|
|
/* generic information */
|
|
|
|
sprintf(second_buf[i++], "drive %s", (disk6.drive) ? "B" : "A");
|
|
|
|
sprintf(second_buf[i++], "motor %s", (disk6.motor) ? "off" : "on");
|
|
|
|
sprintf(second_buf[i++], "%s", (disk6.ddrw) ? "write" : "read");
|
|
|
|
sprintf(second_buf[i++], "byte = %02X", disk6.disk_byte);
|
2013-07-06 04:37:13 +00:00
|
|
|
if (!disk6.disk[disk6.drive].nibblized)
|
|
|
|
{
|
|
|
|
sprintf(second_buf[i++], "volume = %d", disk6.volume);
|
|
|
|
sprintf(second_buf[i++], "checksum = %d", disk6.checksum);
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
sprintf(second_buf[i++], "-------------------------------------");
|
|
|
|
|
|
|
|
/* drive / image specific information */
|
|
|
|
memset(second_buf[i], ' ', BUF_X);
|
2013-07-06 04:37:13 +00:00
|
|
|
if ((len = strlen(disk6.disk[0].file_name)))
|
|
|
|
{
|
|
|
|
while ((--len) && (disk6.disk[0].file_name[len] != '/'))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
strncpy(tmp, disk6.disk[0].file_name + len + 1, 31);
|
|
|
|
*(second_buf[i] + sprintf(second_buf[i], "%s", tmp)) = ' ';
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
if ((len = strlen(disk6.disk[1].file_name)))
|
|
|
|
{
|
|
|
|
while ((--len) && (disk6.disk[1].file_name[len] != '/'))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
strncpy(tmp, disk6.disk[1].file_name + len + 1, 31);
|
|
|
|
sprintf(second_buf[i]+off, "%s", tmp);
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
memset(second_buf[++i], ' ', BUF_X);
|
2013-07-06 04:37:13 +00:00
|
|
|
*(second_buf[i] + sprintf(second_buf[i],
|
|
|
|
"%s %d bytes",
|
|
|
|
(disk6.disk[0].nibblized) ? ".nib" : ".dsk",
|
|
|
|
(int)disk6.disk[0].file_size)) = ' ';
|
2013-06-11 07:08:15 +00:00
|
|
|
sprintf(second_buf[i++]+off, "%s %d bytes",
|
2013-07-06 04:37:13 +00:00
|
|
|
(disk6.disk[1].nibblized) ? ".nib" : ".dsk",
|
2013-06-11 07:08:15 +00:00
|
|
|
(int)disk6.disk[1].file_size);
|
|
|
|
|
|
|
|
memset(second_buf[i], ' ', BUF_X);
|
|
|
|
*(second_buf[i] + sprintf(second_buf[i], "write %s",
|
2013-07-06 04:37:13 +00:00
|
|
|
(disk6.disk[0].protected) ? "protected" : "enabled")) = ' ';
|
2013-06-11 07:08:15 +00:00
|
|
|
sprintf(second_buf[i++]+off, "write %s",
|
2013-07-06 04:37:13 +00:00
|
|
|
(disk6.disk[1].protected) ? "protected" : "enabled");
|
2013-06-11 07:08:15 +00:00
|
|
|
|
|
|
|
memset(second_buf[i], ' ', BUF_X);
|
2013-07-06 04:37:13 +00:00
|
|
|
*(second_buf[i] + sprintf(second_buf[i],
|
|
|
|
"phase %d %s",
|
|
|
|
disk6.disk[0].phase,
|
|
|
|
(disk6.disk[0].phase_change) ? "(new)" : "")) = ' ';
|
|
|
|
sprintf(second_buf[i++]+off,
|
|
|
|
"phase %d %s",
|
2013-06-11 07:08:15 +00:00
|
|
|
disk6.disk[1].phase,
|
2013-07-06 04:37:13 +00:00
|
|
|
(disk6.disk[1].phase_change) ? "(new)" : "");
|
2013-06-11 07:08:15 +00:00
|
|
|
|
|
|
|
memset(second_buf[i], ' ', BUF_X);
|
2013-07-06 04:37:13 +00:00
|
|
|
if (!disk6.disk[0].nibblized)
|
|
|
|
{
|
|
|
|
*(second_buf[i] + sprintf(second_buf[i], "sector %d",
|
|
|
|
disk6.disk[0].sector)) = ' ';
|
|
|
|
if (disk6.disk[1].nibblized)
|
|
|
|
{
|
|
|
|
++i;
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
2013-07-06 04:37:13 +00:00
|
|
|
|
2013-06-11 07:08:15 +00:00
|
|
|
if (!disk6.disk[1].nibblized)
|
2013-07-06 04:37:13 +00:00
|
|
|
{
|
|
|
|
sprintf(second_buf[i++]+off, "sector %d",
|
2013-06-11 07:08:15 +00:00
|
|
|
disk6.disk[1].sector);
|
2013-07-06 04:37:13 +00:00
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
|
|
|
|
num_buffer_lines = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
clear_debugger_screen () - clears the screen of graphics artifacts.
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
void clear_debugger_screen() {
|
|
|
|
int i;
|
|
|
|
video_setpage( 0 );
|
|
|
|
for (i = 0; i < 24; i++)
|
2013-07-06 04:37:13 +00:00
|
|
|
{
|
|
|
|
c_interface_print(0, i, 2, screen[ i ] );
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
end_step () - finish a stepping command
|
2013-07-06 04:37:13 +00:00
|
|
|
display the next instruction, and tell whether it will branch
|
2013-06-11 07:08:15 +00:00
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
void end_step() {
|
|
|
|
int branch;
|
|
|
|
|
|
|
|
clear_debugger_screen();
|
2013-07-06 04:37:13 +00:00
|
|
|
disasm(cpu65_current.pc, 1, 0, -1); /* show next instruction */
|
|
|
|
branch = will_branch(); /* test if it will branch */
|
|
|
|
if (branch == -1)
|
|
|
|
{
|
|
|
|
return; /* n/a */
|
|
|
|
}
|
|
|
|
|
2013-06-11 07:08:15 +00:00
|
|
|
sprintf(second_buf[num_buffer_lines++], "%s",
|
2013-07-06 04:37:13 +00:00
|
|
|
(branch) ? "will branch" : "will not branch");
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
c_do_step () - step into or step over commands
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
void c_do_step(int step_count) {
|
|
|
|
char ch;
|
|
|
|
unsigned char op;
|
|
|
|
int step_frame = 0;
|
|
|
|
|
|
|
|
/* do step while step_count AND no breaks AND no keypress */
|
2013-07-06 04:37:13 +00:00
|
|
|
do
|
|
|
|
{
|
|
|
|
op = get_current_opcode();
|
|
|
|
|
|
|
|
if (step_next && (op == 0x20))
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
op = get_current_opcode();
|
|
|
|
if (op == 0x20)
|
|
|
|
{
|
|
|
|
++step_frame; /* JSR */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (op == 0x60)
|
|
|
|
{
|
|
|
|
--step_frame; /* RTS */
|
|
|
|
}
|
|
|
|
|
|
|
|
cpu65_step();
|
|
|
|
} while (((ch = c_mygetch(0)) == -1) && !at_haltpt() && step_frame);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cpu65_step(); /* step one instruction */
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
} while (--step_count && !at_haltpt() && (c_mygetch(0) == -1));
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
end_step(); /* print location */
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
display_help ()
|
2013-07-06 04:37:13 +00:00
|
|
|
show quick reference command usage
|
2013-06-11 07:08:15 +00:00
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
void display_help() {
|
|
|
|
/* "|||||||||||||||||||||||||||||||||||||" */
|
|
|
|
int i = num_buffer_lines;
|
|
|
|
sprintf(second_buf[i++], "d{is} {lc1|lc2} {/bank/addr} {+}{len}");
|
|
|
|
sprintf(second_buf[i++], "m{em} {lc1|lc2} {/bank/addr} {+}{len}");
|
|
|
|
sprintf(second_buf[i++], "a{sc} {lc1|lc2} {/bank/addr} {+}{len}");
|
|
|
|
sprintf(second_buf[i++], "r{egs} ");
|
|
|
|
sprintf(second_buf[i++], "<addr> {lc1|lc2} : <byteseq> ");
|
|
|
|
sprintf(second_buf[i++], "(s{tep} | n{ext}) {len} ");
|
|
|
|
sprintf(second_buf[i++], "f{inish} ");
|
|
|
|
sprintf(second_buf[i++], "u{ntil} ");
|
|
|
|
sprintf(second_buf[i++], "g{o} {addr} ");
|
|
|
|
sprintf(second_buf[i++], "sea{rch} {lc1|lc2} {bank} <bytes> ");
|
|
|
|
sprintf(second_buf[i++], "(b{reak} | w{atch}) {addr} ");
|
|
|
|
sprintf(second_buf[i++], "b{reak} op <byte> ");
|
|
|
|
sprintf(second_buf[i++], "(c{lear} | i{gnore}) {num} ");
|
|
|
|
sprintf(second_buf[i++], "c{lear} op <byte> ");
|
|
|
|
sprintf(second_buf[i++], "(sta{tus} | op{codes}) ");
|
|
|
|
sprintf(second_buf[i++], "(l{ang} | d{rive} | vm) ");
|
|
|
|
sprintf(second_buf[i++], "bsave <filename> </bank/addr> <len> ");
|
|
|
|
sprintf(second_buf[i++], "bload <filename> <addr> ");
|
|
|
|
sprintf(second_buf[i++], "fr{esh} ");
|
|
|
|
sprintf(second_buf[i++], "(h{elp} | ?) ");
|
|
|
|
num_buffer_lines = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
do_debug_command ()
|
2013-07-06 04:37:13 +00:00
|
|
|
perform a debugger command
|
2013-06-11 07:08:15 +00:00
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
void do_debug_command() {
|
|
|
|
int i = 0, j = 0, k = 0;
|
2013-07-06 04:37:13 +00:00
|
|
|
|
2013-06-11 07:08:15 +00:00
|
|
|
/* reset key local vars */
|
|
|
|
step_next = 0;
|
|
|
|
num_buffer_lines = 0;
|
|
|
|
|
|
|
|
/* call lex to perform the command.*/
|
|
|
|
strncpy(lexbuf, command_line + PROMPT_X, BUF_X);
|
|
|
|
init_lex(lexbuf, BUF_X+2);
|
|
|
|
debuglex();
|
|
|
|
|
|
|
|
/* set up to copy results into main buffer */
|
2013-07-06 04:37:13 +00:00
|
|
|
if (num_buffer_lines >= PROMPT_Y)
|
|
|
|
{
|
|
|
|
k = BUF_Y - PROMPT_Y;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* scroll buffer */
|
|
|
|
for (i = 0, j = 0; i < PROMPT_Y - num_buffer_lines; i++, j = 0)
|
|
|
|
{
|
|
|
|
memcpy(command_buf[i], command_buf[num_buffer_lines+1+i], BUF_X);
|
|
|
|
while ((j < BUF_X) && (command_buf[i][j] != '\0'))
|
|
|
|
{
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(command_buf[i] + j, ' ', BUF_X - j - 1);
|
|
|
|
command_buf[i][BUF_X - 1] = '\0';
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
2013-07-06 04:37:13 +00:00
|
|
|
|
2013-06-11 07:08:15 +00:00
|
|
|
/* copy the debug results into debug console window. change '\0's
|
|
|
|
to ' 's and cap with a single '\0' */
|
2013-07-06 04:37:13 +00:00
|
|
|
while (i < PROMPT_Y)
|
|
|
|
{
|
|
|
|
j = 0;
|
|
|
|
memcpy(command_buf[i], second_buf[k++], BUF_X);
|
|
|
|
while ((j < BUF_X) && (command_buf[i][j] != '\0'))
|
|
|
|
{
|
|
|
|
++j;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(command_buf[i] + j, ' ', BUF_X - j - 1);
|
|
|
|
command_buf[i++][BUF_X - 1] = '\0';
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* new prompt */
|
|
|
|
memset(command_line, ' ', BUF_X);
|
|
|
|
command_line[0] = '>';
|
|
|
|
command_line[BUF_X - 1] = '\0';
|
|
|
|
|
|
|
|
/* display the new information */
|
2013-07-06 04:37:13 +00:00
|
|
|
for (i=0; i<BUF_Y; i++)
|
|
|
|
{
|
|
|
|
c_interface_print(1, 1+i, 0, command_buf[i]);
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* reset before we return */
|
|
|
|
num_buffer_lines = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
c_do_debugging()
|
2013-07-06 04:37:13 +00:00
|
|
|
main debugging console
|
2013-06-11 07:08:15 +00:00
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
void c_do_debugging() {
|
|
|
|
|
|
|
|
static char lex_initted = 0;
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
int i;
|
2013-06-11 07:08:15 +00:00
|
|
|
int ch;
|
|
|
|
int command_pos = PROMPT_X;
|
|
|
|
|
|
|
|
opcodes = (apple_mode == 0) ? opcodes_6502 :
|
2013-07-06 04:37:13 +00:00
|
|
|
(apple_mode == 1) ? opcodes_undoc :
|
|
|
|
opcodes_65c02;
|
2013-06-11 07:08:15 +00:00
|
|
|
|
|
|
|
/* initialize the buffers */
|
2013-07-06 04:37:13 +00:00
|
|
|
for (i=0; i<BUF_Y; i++)
|
|
|
|
{
|
|
|
|
memset(command_buf[i], '\0', BUF_X);
|
|
|
|
memset(second_buf [i], '\0', BUF_X);
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
2013-07-06 04:37:13 +00:00
|
|
|
|
2013-06-11 07:08:15 +00:00
|
|
|
memset(command_line, ' ', BUF_X);
|
|
|
|
command_line[0] = '>';
|
|
|
|
command_line[BUF_X - 1] = '\0';
|
|
|
|
|
|
|
|
/* initialize the lexical scanner */
|
2013-07-06 04:37:13 +00:00
|
|
|
if (!lex_initted)
|
|
|
|
{
|
|
|
|
memset(lexbuf, '\0', BUF_X+2);
|
|
|
|
/*init_lex(lexbuf, BUF_X+2);*/
|
|
|
|
lex_initted = 1;
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
video_setpage( 0 );
|
|
|
|
c_interface_translate_screen( screen );
|
|
|
|
for (i = 0; i < 24; i++)
|
2013-07-06 04:37:13 +00:00
|
|
|
{
|
|
|
|
c_interface_print(0, i, 2, screen[ i ] );
|
|
|
|
}
|
|
|
|
|
|
|
|
for (;; )
|
|
|
|
{
|
|
|
|
/* print command line */
|
|
|
|
c_interface_print(1, 1+PROMPT_Y, 0, command_line);
|
|
|
|
|
|
|
|
/* highlight cursor */
|
|
|
|
video_plotchar(1+command_pos, 1+PROMPT_Y, 1,
|
|
|
|
command_line[command_pos]);
|
|
|
|
|
|
|
|
while ((ch = c_mygetch(1)) == -1)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ch == kESC)
|
|
|
|
{
|
|
|
|
c_interface_exit();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* backspace */
|
|
|
|
if ((ch == 127 || ch == 8) &&
|
|
|
|
(command_pos > PROMPT_X))
|
|
|
|
{
|
|
|
|
command_line[--command_pos] = ' ';
|
|
|
|
}
|
|
|
|
/* return */
|
|
|
|
else
|
|
|
|
if (ch == 13)
|
|
|
|
{
|
|
|
|
command_line[command_pos] = '\0';
|
|
|
|
do_debug_command();
|
|
|
|
command_pos = PROMPT_X;
|
|
|
|
}
|
|
|
|
/* normal character */
|
|
|
|
else
|
|
|
|
if ((ch >= ' ') && (ch < 127) &&
|
|
|
|
(command_pos < PROMPT_END_X))
|
|
|
|
{
|
|
|
|
command_line[command_pos++] = ch;
|
|
|
|
}
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|