1437 lines
36 KiB
C
1437 lines
36 KiB
C
/*
|
|
Copyright (C) 1997-2007 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )
|
|
|
|
http://www.zsnes.com
|
|
http://sourceforge.net/projects/zsnes
|
|
https://zsnes.bountysource.com
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
version 2 as published by the Free Software Foundation.
|
|
|
|
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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#ifndef NCURSES
|
|
#include <curses.h>
|
|
#else
|
|
#include <ncurses.h>
|
|
#endif
|
|
#include "zpath.h"
|
|
|
|
#ifdef __MSDOS__
|
|
#include <dpmi.h>
|
|
#endif // __MSDOS__
|
|
|
|
#include "asm_call.h"
|
|
|
|
// All of these should be in headers, people!
|
|
|
|
extern unsigned char oamram[1024], SPCRAM[65472], DSPMem[256];
|
|
|
|
extern unsigned char curblank;
|
|
extern unsigned char curcyc;
|
|
extern unsigned char curypos;
|
|
extern unsigned char CurrentCPU;
|
|
|
|
extern unsigned char soundon;
|
|
extern unsigned int cycpbl;
|
|
|
|
extern unsigned short xpc, xa, xx, xy, xs, xd;
|
|
extern unsigned char xpb, xdb, xp, xe;
|
|
|
|
extern void *snesmmap[256];
|
|
extern void *snesmap2[256];
|
|
extern char dmadata[];
|
|
|
|
extern unsigned char debuggeron;
|
|
|
|
extern void (*memtabler8[256])();
|
|
|
|
|
|
// SPC stuff
|
|
|
|
extern unsigned char *spcPCRam;
|
|
extern unsigned char spcA, spcX, spcY, spcS, spcNZ, spcP;
|
|
|
|
|
|
// these really shouldn't be written in ASM... (they are in debugasm.asm)
|
|
extern unsigned char memtabler8_wrapper(unsigned char, unsigned short);
|
|
extern void memtablew8_wrapper(unsigned char, unsigned short, unsigned char);
|
|
extern void breakops_wrapper(void);
|
|
|
|
extern void regaccessbankr8();
|
|
extern void start65816();
|
|
extern void endprog();
|
|
|
|
// should be in "zstate.h"
|
|
void debugloadstate();
|
|
void statesaver();
|
|
|
|
char *ocname;
|
|
unsigned char addrmode[];
|
|
char *spcnametab[];
|
|
char *AddressTable[];
|
|
unsigned char ArgumentTable[];
|
|
|
|
|
|
/*
|
|
unsigned short debugh = 0; // debug head
|
|
unsigned short debugt = 0; // debug tail
|
|
unsigned short debugv = 0; // debug view
|
|
*/
|
|
unsigned char debugds = 0; // debug disable (bit 0 = 65816, bit 1 = SPC)
|
|
unsigned int numinst = 0; // # of instructions
|
|
|
|
unsigned char wx = 0, wy = 0, wx2 = 0, wy2 = 0;
|
|
unsigned char execut = 0;
|
|
unsigned char debstop = 0, debstop2 = 0, debstop3 = 0, debstop4 = 0;
|
|
|
|
char debugsa1 = 0;
|
|
char skipdebugsa1 = 1;
|
|
|
|
#define CP(n) (A_BOLD | COLOR_PAIR(n))
|
|
|
|
enum color_pair {
|
|
cp_white = 1, cp_magenta, cp_red, cp_cyan, cp_green, cp_yellow,
|
|
cp_white_on_blue,
|
|
};
|
|
|
|
WINDOW *debugwin;
|
|
|
|
// can't get this to work right...
|
|
//#define CHECK (COLOR_PAIR(cp_white) | A_DIM | ACS_CKBOARD)
|
|
#define CHECK (CP(cp_white) | ' ')
|
|
|
|
void debugloop();
|
|
|
|
void startdisplay();
|
|
void nextopcode();
|
|
void cleardisplay();
|
|
void nextspcopcode();
|
|
void SaveOAMRamLog();
|
|
void debugdump();
|
|
void out65816();
|
|
void execnextop();
|
|
|
|
void traceops(unsigned count);
|
|
void SPCbreakops(unsigned short addr);
|
|
|
|
unsigned char *findop();
|
|
unsigned char *findoppage();
|
|
|
|
void startdebugger() {
|
|
static int firsttime = 1;
|
|
|
|
curblank = 0x40;
|
|
debuggeron = 1;
|
|
|
|
#ifdef __MSDOS__
|
|
__dpmi_regs regs;
|
|
regs.x.ax = 0x0003;
|
|
__dpmi_int(0x10, ®s);
|
|
#endif // __MSDOS__
|
|
|
|
if (firsttime) {
|
|
initscr(); cbreak(); noecho();
|
|
intrflush(stdscr, FALSE);
|
|
keypad(stdscr, TRUE);
|
|
|
|
/* set up colors */
|
|
start_color();
|
|
init_pair(cp_white, COLOR_WHITE, COLOR_BLACK);
|
|
init_pair(cp_magenta, COLOR_MAGENTA, COLOR_BLACK);
|
|
init_pair(cp_red, COLOR_RED, COLOR_BLACK);
|
|
init_pair(cp_cyan, COLOR_CYAN, COLOR_BLACK);
|
|
init_pair(cp_green, COLOR_GREEN, COLOR_BLACK);
|
|
init_pair(cp_yellow, COLOR_YELLOW, COLOR_BLACK);
|
|
init_pair(cp_white_on_blue, COLOR_WHITE, COLOR_BLUE);
|
|
}
|
|
|
|
execut = 0;
|
|
|
|
if (firsttime) {
|
|
startdisplay();
|
|
|
|
debugwin = newwin(20, 77, 2, 1);
|
|
|
|
wbkgd(debugwin, CP(cp_white_on_blue) | ' ');
|
|
// wattrset(debugwin, CP(cp_white_on_blue));
|
|
|
|
scrollok(debugwin, TRUE);
|
|
idlok(debugwin, TRUE);
|
|
|
|
firsttime = 0;
|
|
} else {
|
|
touchwin(stdscr);
|
|
touchwin(debugwin);
|
|
refresh();
|
|
wrefresh(debugwin);
|
|
}
|
|
|
|
debugloop();
|
|
cleardisplay();
|
|
|
|
// "pushad / call LastLog / ... / popad" elided
|
|
SaveOAMRamLog();
|
|
|
|
|
|
if (execut == 1) {
|
|
start65816(); return;
|
|
}
|
|
endprog(); return;
|
|
}
|
|
|
|
// Called from ASM
|
|
|
|
int my_getch_ret;
|
|
void my_getch() {
|
|
my_getch_ret = getch();
|
|
}
|
|
|
|
|
|
WINDOW *openwindow(int nlines, int ncols, int begin_y, int begin_x,
|
|
char *message) {
|
|
WINDOW *w = newwin(nlines, ncols, begin_y, begin_x);
|
|
wbkgd(w, CP(cp_white_on_blue|' '));
|
|
// wattrset(w, CP(cp_white_on_blue));
|
|
|
|
mvwprintw(w, 1, 1, "%s", message);
|
|
wclrtoeol(w);
|
|
box(w, 0, 0);
|
|
|
|
return w;
|
|
}
|
|
|
|
void closewindow(WINDOW *w) {
|
|
delwin(w);
|
|
touchwin(debugwin);
|
|
wrefresh(debugwin);
|
|
}
|
|
|
|
//*******************************************************
|
|
// Debug Loop
|
|
//*******************************************************
|
|
|
|
unsigned short PrevBreakPt_offset;
|
|
unsigned char PrevBreakPt_page;
|
|
|
|
void debugloop() {
|
|
int key;
|
|
a:
|
|
if (!(debugds & 2))
|
|
nextopcode();
|
|
if (!(debugds & 1))
|
|
nextspcopcode();
|
|
|
|
b:
|
|
// redrawing the display is always a good idea
|
|
refresh();
|
|
wrefresh(debugwin);
|
|
|
|
key = getch();
|
|
if (key >= 0 && key < 256)
|
|
key = toupper(key);
|
|
|
|
switch (key) {
|
|
case KEY_F(1): // run
|
|
execut = 1;
|
|
return;
|
|
|
|
case KEY_F(2): // debugsavestate
|
|
statesaver();
|
|
goto b;
|
|
|
|
case KEY_F(4): // debugloadstate
|
|
debugloadstate();
|
|
goto a;
|
|
|
|
case 27: // exit
|
|
return;
|
|
|
|
case '\n': // step
|
|
goto e;
|
|
|
|
|
|
/* Ported this but couldn't bring myself to commit it.
|
|
pagefault said to remove it.
|
|
case '-': // skip opcode
|
|
*/
|
|
|
|
case 'C': // clear
|
|
numinst = 0;
|
|
goto a;
|
|
|
|
case 'M': // modify
|
|
{
|
|
WINDOW *w;
|
|
unsigned addr, value, n;
|
|
|
|
w = openwindow(7, 33, 11, 24, " Enter Address : ");
|
|
mvwaddstr(w, 3, 1, " Previous Value: ");
|
|
mvwaddstr(w, 5, 1, " Enter Value : ");
|
|
|
|
wrefresh(w);
|
|
|
|
echo();
|
|
n = mvwscanw(w, 1, 21, "%x", &addr);
|
|
noecho();
|
|
|
|
if (n == 1) {
|
|
mvwprintw(w, 3, 21, "%02x", memtabler8_wrapper(addr >> 16, addr));
|
|
wrefresh(w);
|
|
|
|
echo();
|
|
n = mvwscanw(w, 5, 21, "%x", &value);
|
|
noecho();
|
|
|
|
if (n == 1) {
|
|
memtablew8_wrapper(addr >> 16, addr, value);
|
|
}}
|
|
|
|
closewindow(w);
|
|
goto b;
|
|
}
|
|
|
|
case 'B': // breakpoint
|
|
{
|
|
WINDOW *w = openwindow(3, 33, 11, 24, " Enter Address : ");
|
|
unsigned addr, n;
|
|
|
|
wrefresh(w);
|
|
|
|
echo();
|
|
n = wscanw(w, "%x", &addr);
|
|
noecho();
|
|
|
|
closewindow(w);
|
|
|
|
if (n == 1) {
|
|
w = openwindow(3, 52, 11, 14,
|
|
" Locating Breakpoint ... Press ESC to stop. ");
|
|
wrefresh(w);
|
|
nodelay(stdscr, 1);
|
|
|
|
PrevBreakPt_page = addr >> 16;
|
|
PrevBreakPt_offset = addr;
|
|
breakops_wrapper();
|
|
|
|
nodelay(stdscr, 0);
|
|
closewindow(w);
|
|
|
|
goto a;
|
|
}
|
|
|
|
goto b;
|
|
}
|
|
|
|
case 'R': // repeat breakpoint
|
|
breakops_wrapper();
|
|
goto a;
|
|
|
|
case 'S': // SPC breakpoint
|
|
{
|
|
WINDOW *w;
|
|
unsigned addr, n;
|
|
|
|
w = openwindow(3, 33, 11, 24, " Enter Address : ");
|
|
wrefresh(w);
|
|
|
|
echo();
|
|
n = mvwscanw(w, 1, 22, "%x", &addr);
|
|
noecho();
|
|
|
|
closewindow(w);
|
|
|
|
if (n == 1) {
|
|
SPCbreakops(addr);
|
|
goto a;
|
|
}
|
|
goto b;
|
|
}
|
|
|
|
case 'A': // SPC modify
|
|
{
|
|
WINDOW *w;
|
|
unsigned addr, value, n;
|
|
|
|
w = openwindow(7, 33, 11, 24, " Enter Address : ");
|
|
mvwaddstr(w, 3, 1, " Previous Value: ");
|
|
mvwaddstr(w, 5, 1, " Enter Value : ");
|
|
|
|
wrefresh(w);
|
|
|
|
echo();
|
|
n = mvwscanw(w, 1, 22, "%x", &addr);
|
|
noecho();
|
|
|
|
addr &= 0xFFFF;
|
|
|
|
if (n == 1) {
|
|
mvwprintw(w, 3, 22, "%02x", SPCRAM[addr]);
|
|
wrefresh(w);
|
|
|
|
echo();
|
|
n = mvwscanw(w, 5, 22, "%x", &value);
|
|
noecho();
|
|
|
|
if (n == 1) {
|
|
SPCRAM[addr] = value;
|
|
}}
|
|
|
|
closewindow(w);
|
|
goto b;
|
|
}
|
|
|
|
case 'T': // trace
|
|
{
|
|
WINDOW *w;
|
|
unsigned n, instrs;
|
|
|
|
w = openwindow(3,52,11,14, " Enter # of Instructions to Trace : ");
|
|
wrefresh(w);
|
|
|
|
echo();
|
|
n = wscanw(w, "%d", &instrs);
|
|
noecho();
|
|
|
|
closewindow(w);
|
|
if (n == 1) {
|
|
traceops(instrs);
|
|
goto a;
|
|
}
|
|
|
|
goto b;
|
|
}
|
|
|
|
case 'D': // debug dump
|
|
debugdump();
|
|
goto b;
|
|
|
|
case 'W': // break at signal (breakatsign)
|
|
{
|
|
WINDOW *w;
|
|
|
|
w = openwindow(3,52,11,14,
|
|
" Waiting for Signal .... Press ESC to stop.");
|
|
wrefresh(w);
|
|
|
|
debstop3 = 0;
|
|
nodelay(w, TRUE);
|
|
do {
|
|
asm_call(execnextop);
|
|
} while ( (! ((++numinst % 256) && (wgetch(w) == 27)))
|
|
&& (debstop3 != 1) );
|
|
debstop3 = 0;
|
|
nodelay(w, FALSE);
|
|
|
|
closewindow(w);
|
|
goto a;
|
|
}
|
|
|
|
case 'L': // break at signal & log (breakatsignlog)
|
|
{
|
|
FILE *fp;
|
|
WINDOW *w, *real_debugwin;
|
|
|
|
w = openwindow(3,52,11,14,
|
|
" Waiting for Signal .... Press ESC to stop.");
|
|
wrefresh(w);
|
|
|
|
// Open output file
|
|
fp = fopen_dir(ZStartPath, "debug.log","w");
|
|
|
|
real_debugwin = debugwin;
|
|
debugwin = newpad(2, 77);
|
|
scrollok(debugwin, TRUE);
|
|
|
|
debstop3 = 0;
|
|
nodelay(w, TRUE);
|
|
do {
|
|
char buf[78];
|
|
// log instruction
|
|
move(0,0);
|
|
out65816();
|
|
|
|
mvwinnstr(debugwin, 0, 0, buf, 77);
|
|
buf[77] = 0;
|
|
fprintf(fp, "%s\n", buf);
|
|
fflush(fp);
|
|
|
|
asm_call(execnextop);
|
|
} while ( (! ((++numinst % 256) && (wgetch(w) == 27)))
|
|
&& (debstop3 != 1) );
|
|
debstop3 = 0;
|
|
nodelay(w, FALSE);
|
|
|
|
fclose(fp);
|
|
delwin(debugwin);
|
|
debugwin = real_debugwin;
|
|
|
|
closewindow(w);
|
|
goto a;
|
|
}
|
|
|
|
|
|
case '1': // toggle SPC
|
|
debugds ^= 1;
|
|
break;
|
|
|
|
case '2': // toggle 65816
|
|
debugds ^= 2;
|
|
break;
|
|
|
|
default:
|
|
wprintw(debugwin, "Unknown key code: %d\n", key);
|
|
goto b;
|
|
}
|
|
|
|
e:
|
|
skipdebugsa1 = 0;
|
|
asm_call(execnextop);
|
|
skipdebugsa1 = 1;
|
|
if (soundon && (debugds & 2) && (cycpbl >= 55))
|
|
goto e;
|
|
goto a;
|
|
|
|
}
|
|
|
|
//*******************************************************
|
|
// BreakatSignC Breaks whenever sndwrit = 1
|
|
//*******************************************************
|
|
|
|
unsigned char sndwrit;
|
|
|
|
/* void breakatsignc() {} */
|
|
|
|
|
|
//*******************************************************
|
|
// BreakOps Breaks at Breakpoint
|
|
//*******************************************************
|
|
|
|
/* in ASM still, but not identical to other version
|
|
void breakops(unsigned char page, unsigned short offset) {
|
|
|
|
}
|
|
*/
|
|
|
|
void traceops(unsigned count) {
|
|
WINDOW *w;
|
|
|
|
w = openwindow(3,52,11,14, " Tracing. Press ESC to stop.");
|
|
wrefresh(w);
|
|
|
|
nodelay(w, TRUE);
|
|
while (count-- && (wgetch(w) != 27)) {
|
|
asm_call(execnextop);
|
|
}
|
|
|
|
closewindow(w);
|
|
}
|
|
|
|
void SPCbreakops(unsigned short addr) {
|
|
WINDOW *w;
|
|
unsigned char *breakarea;
|
|
|
|
breakarea = SPCRAM+addr;
|
|
|
|
w = openwindow(3,52,11,14, "Locating Breakpoint ... Press ESC to stop.");
|
|
wrefresh(w);
|
|
|
|
nodelay(w, TRUE);
|
|
do {
|
|
asm_call(execnextop);
|
|
} while ((!((++numinst % 256)
|
|
&& (wgetch(w) == 27)))
|
|
&& (spcPCRam != breakarea));
|
|
nodelay(w, FALSE);
|
|
|
|
closewindow(w);
|
|
}
|
|
|
|
|
|
void printinfo(char *s) {
|
|
while (s[0]) {
|
|
if (s[0] == '@') {
|
|
int colors[] = {
|
|
0, 0, cp_green, cp_cyan,
|
|
cp_red, cp_magenta, cp_yellow, cp_white
|
|
};
|
|
attrset(COLOR_PAIR(colors[s[1]-'0']));
|
|
s += 2;
|
|
} else {
|
|
addch(s[0]);
|
|
s += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Won't port too well - stuck it in debugasm.asm for now */
|
|
/* void execnextop() { */
|
|
/* char *page = findoppage(); */
|
|
/* initaddrl = page; */
|
|
/* char *address = page+xpc; */
|
|
/* } */
|
|
|
|
//*******************************************************
|
|
// Start Display
|
|
//*******************************************************
|
|
void startdisplay() {
|
|
int i;
|
|
|
|
// Clear the screen
|
|
bkgd(CP(cp_white) | ' ');
|
|
clear();
|
|
|
|
// Draw to screen
|
|
|
|
// ASM for some reason puts the same thing in the upper left corner again?
|
|
|
|
move(1, 0); attrset(CP(cp_white_on_blue));
|
|
addch(CurrentCPU+'0');
|
|
for (i = 15; i; i--)
|
|
addch(ACS_HLINE);
|
|
printw(" CC: Y: ");
|
|
for (i = 19; i; i--)
|
|
addch(ACS_HLINE);
|
|
addch(' ');
|
|
for (i = 11; i; i--)
|
|
addch(' ');
|
|
addch(' ');
|
|
for (i = 16; i; i--)
|
|
addch(ACS_HLINE);
|
|
addch(ACS_URCORNER);
|
|
|
|
for (i = 2; i < 22; i++) {
|
|
mvaddch(i, 0, ACS_VLINE);
|
|
hline(' ', 77);
|
|
mvaddch(i, 78, ACS_VLINE);
|
|
mvaddch(i, 79, CHECK);
|
|
}
|
|
|
|
mvaddch(22, 0, ACS_LLCORNER);
|
|
for(i = 77; i; i--)
|
|
addch(ACS_HLINE);
|
|
mvaddch(22, 78, ACS_LRCORNER);
|
|
mvaddch(22, 79, CHECK);
|
|
|
|
move(23, 1);
|
|
for(i = 79; i; i--)
|
|
addch(CHECK);
|
|
|
|
// Print debugger information
|
|
|
|
move(0, 2); attrset(CP(cp_white));
|
|
printinfo("- @5Z@4S@3N@2E@6S@7 debugger -");
|
|
|
|
move(1, 4); attrset(CP(cp_white_on_blue));
|
|
printinfo(" 65816 ");
|
|
|
|
// HACK ALERT! this should really be on the bottom line, but
|
|
// xterms default to being one line shorter than 80x25, so this
|
|
// won't be on the bottom line on DOS!
|
|
// Also, we are printing on top of the (currently invisible) drop shadow!"
|
|
move(23, 0);
|
|
printinfo("@4(@6T@4)@7race for @4(@6B@4)@7reakpoint "
|
|
"@4(@6Enter@4)@7 Next "
|
|
"@4(@6M@4)@7odify @4(@6F9@4)@7 Signal @4(@6F1@4)@7 Run");
|
|
|
|
// ...
|
|
move(0, 0);
|
|
refresh();
|
|
}
|
|
|
|
|
|
//*******************************************************
|
|
// Next Opcode Writes the next opcode & regs
|
|
//*******************************************************
|
|
// 008000 STZ $123456,x A:0000 X:0000 Y:0000 S:01FF DB:00 D:0000 P:33 E+
|
|
|
|
/*
|
|
void addtail() {
|
|
debugt++;
|
|
if (debugt == 100)
|
|
debugt = 0;
|
|
if (debugt == debugh)
|
|
debugh++;
|
|
if (debugh == 100)
|
|
debugh = 0;
|
|
}
|
|
*/
|
|
|
|
|
|
// I'm going to have to completely rip out byuu's effective address
|
|
// stuff, it is just plain *WRONG*, besides being unsafe...
|
|
|
|
// For next time, http://www.zophar.net/tech/files/65c816.txt seems
|
|
// like a good reference for effective address calculation; also, use
|
|
// 24-bit addresses for all calculations (so completely rip out
|
|
// memtabler8_wrapper, too). Also, preferably read memory in a
|
|
// non-destructive way.
|
|
|
|
// This whole instr[1] thing probably isn't quite right either, but it
|
|
// seems unlikely that instructions would be stored discontiguously
|
|
// than that data would span 64kb boundaries.
|
|
|
|
void out65816_addrmode (unsigned char *instr) {
|
|
char *padding = "";
|
|
|
|
#define GETXB() ((ocname[4*instr[0]] != 'J') ? xdb : xpb)
|
|
|
|
#define INDEX_RIGHT(addr, index) \
|
|
((xp & 0x10) \
|
|
? (((addr) & ~0xff) | (((addr) + (index)) & 0xff)) \
|
|
: (((addr) & ~0xffff) | (((addr) + (index)) & 0xffff)))
|
|
|
|
|
|
// each mode must output 19 characters
|
|
switch (addrmode[instr[0]]) {
|
|
|
|
case 0:
|
|
case 6:
|
|
case 21:
|
|
// nothing to show
|
|
|
|
wprintw(debugwin, "%19s", padding);
|
|
break;
|
|
|
|
case 1: // #$12,#$1234 (M-flag)
|
|
wprintw(debugwin, "#$");
|
|
if (xp != 0x20) {
|
|
wprintw(debugwin, "%02x", instr[1]);
|
|
wprintw(debugwin, "%15s", padding);
|
|
} else {
|
|
wprintw(debugwin, "%04x", *(unsigned short *)(instr+1));
|
|
wprintw(debugwin, "%13s", padding);
|
|
}
|
|
break;
|
|
|
|
case 2: // $1234 : db+$1234
|
|
wprintw(debugwin, "$%04x", *(unsigned short *)(instr+1));
|
|
wprintw(debugwin, "%5s[%02x%04x] ", padding, GETXB(),
|
|
*(unsigned short *)(instr+1));
|
|
break;
|
|
|
|
case 3: // $123456
|
|
wprintw(debugwin, "$%02x%04x", instr[3], *(unsigned short*)(instr+1));
|
|
wprintw(debugwin, "%12s", padding);
|
|
break;
|
|
|
|
case 4: // $12 : $12+d
|
|
wprintw(debugwin, "$%02x%7s[%02x%04x] ", instr[1], padding, 0,
|
|
instr[1]+xd);
|
|
break;
|
|
|
|
case 5: // A
|
|
wprintw(debugwin, "A%18s", padding);
|
|
break;
|
|
|
|
case 7: // ($12),y
|
|
{
|
|
wprintw(debugwin, "($%02x),Y ", instr[1]);
|
|
wprintw(debugwin, "[nnnnnn] ");
|
|
break;
|
|
}
|
|
|
|
case 8: // [$12],y
|
|
{
|
|
unsigned short addr;
|
|
unsigned int t;
|
|
|
|
wprintw(debugwin, "[$%02x],Y ", instr[1]);
|
|
|
|
addr = instr[1] + xd;
|
|
t = memtabler8_wrapper(0, addr);
|
|
t |= memtabler8_wrapper(0, addr+1) << 8;
|
|
t |= memtabler8_wrapper(0, addr+2) << 16;
|
|
t = INDEX_RIGHT(t, xy);
|
|
wprintw(debugwin, "[%06x] ", t);
|
|
|
|
break;
|
|
}
|
|
|
|
case 9: // ($12,x)
|
|
{
|
|
wprintw(debugwin, "($%02x,X) ", instr[1]);
|
|
wprintw(debugwin, "[nnnnnn] ");
|
|
break;
|
|
}
|
|
|
|
case 10: // $12,x : $12+d+x
|
|
{
|
|
wprintw(debugwin, "$%02x,X%5s", instr[1], padding);
|
|
wprintw(debugwin, "[%06x] ", INDEX_RIGHT(instr[1] + xd, xx));
|
|
break;
|
|
}
|
|
|
|
case 11: // $12,y
|
|
{
|
|
wprintw(debugwin, "$%02x,Y%5s", instr[1], padding);
|
|
wprintw(debugwin, "[%06x] ", INDEX_RIGHT(instr[1] + xd, xy));
|
|
break;
|
|
}
|
|
|
|
case 12: // $1234,x : dbr+$1234+x
|
|
{
|
|
unsigned int t = instr[1] | (instr[2] << 8);
|
|
wprintw(debugwin, "$%04x,X ", t);
|
|
t = INDEX_RIGHT(t, xx);
|
|
wprintw(debugwin, "[%02x%04x] ", xdb, t);
|
|
|
|
break;
|
|
}
|
|
|
|
case 13: // $1234,y : dbr+$1234+y
|
|
{
|
|
unsigned int t = instr[1] | (instr[2] << 8);
|
|
wprintw(debugwin, "$%04x,Y ", t);
|
|
t = INDEX_RIGHT(t, xy);
|
|
wprintw(debugwin, "[%02x%04x] ", xdb, t);
|
|
|
|
break;
|
|
}
|
|
|
|
case 14: // $123456,x : $123456+x
|
|
{
|
|
unsigned int t = instr[1] | (instr[2] << 8) | (instr[3] << 16);
|
|
wprintw(debugwin, "$%06x,X ", t);
|
|
t = INDEX_RIGHT(t, xx);
|
|
wprintw(debugwin, "[%06x] ", t);
|
|
|
|
break;
|
|
}
|
|
|
|
case 15: // +-$12 / $1234
|
|
{
|
|
signed char c = instr[1];
|
|
unsigned short t = c + xpc + 2;
|
|
|
|
wprintw(debugwin, "$%04x%4s [%02x%04x] ", t, padding, xpb, t);
|
|
|
|
break;
|
|
}
|
|
|
|
case 16: // +-$1234 / $1234
|
|
{
|
|
unsigned short s = instr[1] | (instr[2] << 8);
|
|
unsigned short t = s + xpc + 3;
|
|
|
|
wprintw(debugwin, "$%04x%4s [%02x%04x] ", t, padding, xpb, t);
|
|
|
|
break;
|
|
}
|
|
|
|
case 17: // ($1234)
|
|
{
|
|
wprintw(debugwin, "($%04x) ", instr[1]);
|
|
wprintw(debugwin, "[nnnnnn] ");
|
|
break;
|
|
}
|
|
|
|
case 18: // ($12)
|
|
{
|
|
unsigned short addr1, addr2;
|
|
wprintw(debugwin, "($%02x)%5s", instr[1], padding);
|
|
|
|
addr1 = instr[1] + xd;
|
|
|
|
addr2 = memtabler8_wrapper(00, addr1);
|
|
addr2 |= memtabler8_wrapper(00, addr1+1) << 8;
|
|
|
|
wprintw(debugwin, "[%02x%04x] ", xdb, addr2);
|
|
|
|
break;
|
|
}
|
|
|
|
case 19: // [$12]
|
|
{
|
|
// unsigned short addr1;
|
|
// unsigned int addr2;
|
|
|
|
wprintw(debugwin, "[$%02x]%5s", instr[1], padding);
|
|
|
|
/*
|
|
addr1 = instr[1] + xd;
|
|
|
|
addr2 = memtabler8_wrapper(0, addr1);
|
|
addr2 |= memtabler8_wrapper(
|
|
*/
|
|
|
|
wprintw(debugwin, "[nnnnnn] ");
|
|
|
|
break;
|
|
}
|
|
|
|
case 20: // ($1234,x)
|
|
{
|
|
unsigned short cx = *(unsigned short*)(instr+1);
|
|
unsigned short x;
|
|
|
|
wprintw(debugwin, "($%04x,X) [%02x", cx, xpb);
|
|
if (xp & 0x10)
|
|
cx = (cx & 0xFF00) | ((cx + xx) & 0xFF);
|
|
else
|
|
cx += xx;
|
|
// .out20n
|
|
x = memtabler8_wrapper(xpb, cx);
|
|
x += memtabler8_wrapper(xpb, cx+1) << 8;
|
|
wprintw(debugwin, "%04x] ", x);
|
|
|
|
break;
|
|
}
|
|
|
|
case 22: // d,s
|
|
wprintw(debugwin, "$%02x,S%5s", instr[1], padding);
|
|
wprintw(debugwin, "[nnnnnn] ");
|
|
break;
|
|
|
|
case 23: // (d,s),y
|
|
wprintw(debugwin, "($%02x,S),Y ", instr[1]);
|
|
wprintw(debugwin, "[nnnnnn] ");
|
|
break;
|
|
|
|
case 24: // xyc - $1234
|
|
wprintw(debugwin, "$%02x%02x%14s", instr[2], instr[1], padding);
|
|
break;
|
|
|
|
case 25: // #$12 (Flag Operations)
|
|
wprintw(debugwin, "#$%02x%15s", instr[1], padding);
|
|
break;
|
|
|
|
case 26: // #$12,#$1234 (X-flag)
|
|
if (xp & 0x10) {
|
|
wprintw(debugwin, "#$%02x%15s", instr[1], padding);
|
|
} else {
|
|
wprintw(debugwin, "#$%04x%13s",
|
|
*(unsigned short*)(instr+1), padding);
|
|
}
|
|
break;
|
|
|
|
case 27: // [$1234]
|
|
wprintw(debugwin, "[$%02x%02x] ", instr[2], instr[1]);
|
|
break;
|
|
|
|
default:
|
|
wprintw(debugwin, "%15s %02d ", "bad addr mode", addrmode[instr[0]]);
|
|
}
|
|
}
|
|
|
|
unsigned char *findoppage() {
|
|
if (xpc & 0x8000) {
|
|
return snesmmap[xpb];
|
|
} else {
|
|
// lower address
|
|
if ((xpc < 0x4300) || (memtabler8[xpb] != regaccessbankr8)) {
|
|
// lower memory
|
|
return snesmap2[xpb];
|
|
} else {
|
|
// dma
|
|
return (unsigned char*)(dmadata-0x4300);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* grinvader's version -- kept incase I didn't get mine to match
|
|
unsigned char *findoppage()
|
|
{
|
|
if (xpc & 0x8000) { return(snesmmap[xpb]); }
|
|
else
|
|
{ // lower address
|
|
if (xpc < 0x4300 || memtabler8[xpb] != regaccessbankr8)
|
|
{ return(snesmap2[xpb]); }
|
|
// dma
|
|
return(dmadata - 0x4300); // or maybe (&dmadata - 0x4300)
|
|
}
|
|
}
|
|
*/
|
|
|
|
unsigned char *findop() {
|
|
unsigned char *address = findoppage()+xpc;
|
|
return address;
|
|
}
|
|
|
|
// print out a 65816 instruction
|
|
void out65816() {
|
|
unsigned char *address, opcode;
|
|
char opname[5] = "FOO ";
|
|
|
|
wprintw(debugwin, "%02x%04x ", xpb, xpc);
|
|
|
|
// is this safe?
|
|
address = findop();
|
|
opcode = *address;
|
|
|
|
memcpy(opname, &ocname[opcode*4], 4);
|
|
wprintw(debugwin, "%s", opname);
|
|
|
|
out65816_addrmode(address);
|
|
|
|
wprintw(debugwin, "A:%04x X:%04x Y:%04x S:%04x DB:%02x D:%04x P:%02x %c",
|
|
xa, xx, xy, xs, xdb, xd, xp, (xe == 1) ? 'E' : 'e');
|
|
}
|
|
|
|
void outsa1() {
|
|
// stub!
|
|
}
|
|
|
|
|
|
void nextopcode() {
|
|
attrset(CP(cp_white_on_blue));
|
|
|
|
move(1,50); printw("%11d", numinst);
|
|
move(1,20); printw("%3d", curcyc);
|
|
move(1,26); printw("%3d", curypos);
|
|
|
|
// I don't understand the buffering scheme here... I'm just going
|
|
// to hope it isn't really all that important.
|
|
|
|
//if (debugsa1 != 1)
|
|
out65816();
|
|
//else
|
|
// outputbuffersa1();
|
|
}
|
|
|
|
|
|
void cleardisplay() {
|
|
move(0, 0); /* clear(); refresh(); */ endwin();
|
|
}
|
|
|
|
//*******************************************************
|
|
// Next SPC Opcode Writes the next opcode & regs
|
|
//*******************************************************
|
|
// 008000 STZ $123456,x A:0000 X:0000 Y:0000 S:01FF DB:00 D:0000 P:33 E+
|
|
|
|
void outspc_addrmode() {
|
|
unsigned char mode;
|
|
char *format;
|
|
char buf[16] = " ";
|
|
char *p;
|
|
|
|
#define HEX8(val) do { p += sprintf(p, "%02x", val); *p = ' '; } while (0)
|
|
#define HEX16(val) do { p += sprintf(p, "%04x", val); *p = ' '; } while (0)
|
|
|
|
mode = ArgumentTable[spcPCRam[0]];
|
|
format = AddressTable[mode];
|
|
|
|
// memset(buf, ' ', 15); buf[15] = 0;
|
|
|
|
p = buf;
|
|
while (*format) {
|
|
if (*format != '%') {
|
|
*p++ = *format++;
|
|
continue;
|
|
}
|
|
|
|
format++;
|
|
switch (*format++) {
|
|
|
|
case '1': // first byte
|
|
HEX8(spcPCRam[1]);
|
|
break;
|
|
|
|
case '2': // second byte
|
|
HEX8(spcPCRam[2]);
|
|
break;
|
|
|
|
case '3': // hinib
|
|
*p++ = (spcPCRam[0] >> 4) + '0';
|
|
*p++ = ' ';
|
|
break;
|
|
|
|
case '4': // hinib2
|
|
*p++ = (spcPCRam[0] >> 5) + '0';
|
|
*p++ = ' ';
|
|
break;
|
|
|
|
case '5': // rela2pc2
|
|
{
|
|
signed char off;
|
|
off = *(signed char*)(spcPCRam+1);
|
|
HEX16(off + 2 + (spcPCRam - SPCRAM));
|
|
// format += 3;
|
|
break;
|
|
}
|
|
|
|
case '6': // dp
|
|
{
|
|
*p++ = '$';
|
|
|
|
if (spcP & 0x20) {
|
|
*p++ = '1';
|
|
} else {
|
|
*p++ = '0';
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case '8': // memorybit
|
|
HEX16((*(unsigned short*)(spcPCRam+1)) >> 3);
|
|
// format += 2;
|
|
break;
|
|
|
|
case '9': // memorybitlow
|
|
*p++ = ',';
|
|
*p++ = (spcPCRam[1] & 0x7) + '0';
|
|
break;
|
|
|
|
case 'A': // rela2pc1
|
|
{
|
|
signed char off;
|
|
off = *(signed char*)(spcPCRam+1);
|
|
HEX16(off + 2 + spcPCRam - SPCRAM);
|
|
// format += 2;
|
|
break;
|
|
}
|
|
|
|
case 'B': // rela2pc2at2
|
|
{
|
|
signed char off;
|
|
off = *(signed char*)(spcPCRam+2);
|
|
HEX16(off + 2 + spcPCRam - SPCRAM);
|
|
// format += 2;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
buf[15] = 0;
|
|
waddstr(debugwin, buf);
|
|
}
|
|
|
|
void nextspcopcode() {
|
|
if (!soundon)
|
|
return;
|
|
if (cycpbl >= 55)
|
|
return;
|
|
|
|
// output spc pc & opcode #
|
|
wprintw(debugwin, " %04x/%02x ", spcPCRam - SPCRAM, spcPCRam[0]);
|
|
|
|
|
|
// output instruction
|
|
wprintw(debugwin, "%-6s", spcnametab[spcPCRam[0]]);
|
|
outspc_addrmode();
|
|
|
|
// output registers
|
|
wprintw(debugwin, "A:%02x X:%02x Y:%02x S:%02x ", spcA, spcX, spcY, spcS);
|
|
wprintw(debugwin, "N%cO%cD%c?%cH%cI%cZ%cC%c",
|
|
(spcNZ & 0x80) ? '+' : '-',
|
|
(spcP & 0x40) ? '+' : '-',
|
|
(spcP & 0x20) ? '+' : '-',
|
|
(spcP & 0x10) ? '+' : '-',
|
|
(spcP & 0x08) ? '+' : '-',
|
|
(spcP & 0x04) ? '+' : '-',
|
|
(spcP & 0x02) ? '+' : '-',
|
|
(spcP & 0x01) ? '+' : '-');
|
|
|
|
wprintw(debugwin, "\n");
|
|
|
|
}
|
|
|
|
|
|
//*******************************************************
|
|
// Debugger OpCode Information
|
|
//*******************************************************
|
|
|
|
// Yes, I know, not very C style, but I really really really didn't
|
|
// want to type all those quote marks and commas. --SamB
|
|
char *ocname =
|
|
"BRK ORA COP ORA TSB ORA ASL ORA PHP ORA ASL PHD TSB ORA ASL ORA "
|
|
"BPL ORA ORA ORA TRB ORA ASL ORA CLC ORA INC TCS TRB ORA ASL ORA "
|
|
"JSR AND JSL AND BIT AND ROL AND PLP AND ROL PLD BIT AND ROL AND "
|
|
"BMI AND AND AND BIT AND ROL AND SEC AND DEC TSC BIT AND ROL AND "
|
|
"RTI EOR WDM EOR MVP EOR LSR EOR PHA EOR LSR PHK JMP EOR LSR EOR "
|
|
"BVC EOR EOR EOR MVN EOR LSR EOR CLI EOR PHY TCD JMP EOR LSR EOR "
|
|
"RTS ADC PER ADC STZ ADC ROR ADC PLA ADC ROR RTL JMP ADC ROR ADC "
|
|
"BVS ADC ADC ADC STZ ADC ROR ADC SEI ADC PLY TDC JMP ADC ROR ADC "
|
|
"BRA STA BRL STA STY STA STX STA DEY BIT TXA PHB STY STA STX STA "
|
|
"BCC STA STA STA STY STA STX STA TYA STA TXS TXY STZ STA STZ STA "
|
|
"LDY LDA LDX LDA LDY LDA LDX LDA TAY LDA TAX PLB LDY LDA LDX LDA "
|
|
"BCS LDA LDA LDA LDY LDA LDX LDA CLV LDA TSX TYX LDY LDA LDX LDA "
|
|
"CPY CMP REP CMP CPY CMP DEC CMP INY CMP DEX WAI CPY CMP DEC CMP "
|
|
"BNE CMP CMP CMP PEI CMP DEC CMP CLD CMP PHX STP JML CMP DEC CMP "
|
|
"CPX SBC SEP SBC CPX SBC INC SBC INX SBC NOP XBA CPX SBC INC SBC "
|
|
"BEQ SBC SBC SBC PEA SBC INC SBC SED SBC PLX XCE JSR SBC INC SBC ";
|
|
|
|
|
|
// Immediate Addressing Modes :
|
|
// 09 - ORA-M, 29 - AND-M, 49 - EOR-M, 69 - ADC-M, 89 - BIT-M,
|
|
// A0 - LDY-X, A2 - LDX-X, A9 - LDA-M, C0 - CPY-X, C2 - REP-B,
|
|
// C9 - CMP-M, E0 - CPX-X, E2 - SEP-B, E9 - SBC-M
|
|
// Extra Addressing Mode Values : B(1-byte only) = 25, X(by X flag) = 26
|
|
|
|
unsigned char addrmode[256] = {
|
|
25, 9,25,22, 4, 4, 4,19,21, 1, 5,21, 2, 2, 2, 3,
|
|
15, 7,18,23, 4,10,10, 8, 6,13, 5, 6, 2,12,12,14,
|
|
2, 9, 3,22, 4, 4, 4,19,21, 1, 5,21, 2, 2, 2, 3,
|
|
15, 7,18,23,10,10,10, 8, 6,13, 5, 6,12,12,12,14,
|
|
21, 9, 0,22,24, 4, 4,19,21, 1, 5,21, 2, 2, 2, 3,
|
|
15, 7,18,23,24,10,10, 8, 6,13,21, 6, 3,12,12,14,
|
|
21, 9, 2,22, 4, 4, 4,19,21, 1, 5,21,17, 2, 2, 3,
|
|
15, 7,18,23,10,10,10, 8, 6,13,21, 6,20,12,12,14,
|
|
15, 9,16,22, 4, 4, 4,19, 6, 1, 6,21, 2, 2, 2, 3,
|
|
15, 7,18,23,10,10,11, 8, 6,13, 6, 6, 2,12,12,14,
|
|
26, 9,26,22, 4, 4, 4,19, 6, 1, 6,21, 2, 2, 2, 3,
|
|
15, 7,18,23,10,10,11, 8, 6,13, 6, 6,12,12,13,14,
|
|
26, 9,25,22, 4, 4, 4,19, 6, 1, 6, 6, 2, 2, 2, 3,
|
|
15, 7,18,23,18,10,10, 8, 6,13,21, 6,27,12,12,14,
|
|
26, 9,25,22, 4, 4, 4,19, 6, 1, 6, 6, 2, 2, 2, 3,
|
|
15, 7,18,23, 2,10,10, 8, 6,13,21, 6,20,12,12,14
|
|
};
|
|
|
|
|
|
char *spcnametab[256] = {
|
|
"NOP", "TCALL", "SET1", "BBS",
|
|
"OR", "OR", "OR", "OR",
|
|
"OR", "OR", "OR1", "ASL",
|
|
"ASL", "PUSH", "TSET1", "BRK",
|
|
|
|
"BPL", "TCALL", "CLR1", "BBC",
|
|
"OR", "OR", "OR", "OR",
|
|
"OR", "OR", "DECW", "ASL",
|
|
"ASL", "DEC", "CMP", "JMP",
|
|
|
|
"CLRP", "TCALL", "SET1", "BBS",
|
|
"AND", "AND", "AND", "AND",
|
|
"AND", "AND", "OR1", "ROL",
|
|
"ROL", "PUSH", "CBNE", "BRA",
|
|
|
|
"BMI", "TCALL", "CLR1", "BBC",
|
|
"AND", "AND", "AND", "AND",
|
|
"AND", "AND", "INCW", "ROL",
|
|
"ROL", "INC", "CMP", "CALL",
|
|
|
|
|
|
"SETP", "TCALL", "SET1", "BBS",
|
|
"EOR", "EOR", "EOR", "EOR",
|
|
"EOR", "EOR", "AND1", "LSR",
|
|
"LSR", "PUSH", "TCLR1", "PCALL",
|
|
|
|
"BVC", "TCALL", "CLR1", "BBC",
|
|
"EOR", "EOR", "EOR", "EOR",
|
|
"EOR", "EOR", "CMPW", "LSR",
|
|
"LSR", "MOV", "CMP", "JMP",
|
|
|
|
"CLRC", "TCALL", "SET1", "BBS",
|
|
"CMP", "CMP", "CMP", "CMP",
|
|
"CMP", "CMP", "AND1", "ROR",
|
|
"ROR", "PUSH", "DMNZ", "RET",
|
|
|
|
"BVS", "TCALL", "CLR1", "BBC",
|
|
"CMP", "CMP", "CMP", "CMP",
|
|
"CMP", "CMP", "ADDW", "ROR",
|
|
"ROR", "MOV", "CMP", "RET1",
|
|
|
|
|
|
"SETC", "TCALL", "SET1", "BBS",
|
|
"ADC", "ADC", "ADC", "ADC",
|
|
"ADC", "ADC", "EOR1", "DEC",
|
|
"DEC", "MOV", "POP", "MOV",
|
|
|
|
"BCC", "TCALL", "CLR1", "BBC",
|
|
"ADC", "ADC", "ADC", "ADC",
|
|
"ADC", "ADC", "SUBW", "DEC",
|
|
"DEC", "MOV", "DIV", "XCN",
|
|
|
|
"EI", "TCALL", "SET1", "BBS",
|
|
"SBC", "SBC", "SBC", "SBC",
|
|
"SBC", "SBC", "MOV1", "INC",
|
|
"INC", "CMP", "POP", "MOV",
|
|
|
|
"BCS", "TCALL", "CLR1", "BBC",
|
|
"SBC", "SBC", "SBC", "SBC",
|
|
"SBC", "SBC", "MOVW", "INC",
|
|
"INC", "MOV", "DAS", "MOV",
|
|
|
|
|
|
"DI", "TCALL", "SET1", "BBS",
|
|
"MOV", "MOV", "MOV", "MOV",
|
|
"CMP", "MOV", "MOV1", "MOV",
|
|
"MOV", "MOV", "POP", "MUL",
|
|
|
|
"BNE", "TCALL", "CLR1", "BBC",
|
|
"MOV", "MOV", "MOV", "MOV",
|
|
"MOV", "MOV", "MOVW", "MOV",
|
|
"DEC", "MOV", "CBNE", "DAA",
|
|
|
|
"CLRV", "TCALL", "SET1", "BBS",
|
|
"MOV", "MOV", "MOV", "MOV",
|
|
"MOV", "MOV", "NOT1", "MOV",
|
|
"MOV", "NOTC", "POP", "SLEEP",
|
|
|
|
"BEQ", "TCALL", "CLR1", "BBC",
|
|
"MOV", "MOV", "MOV", "MOV",
|
|
"MOV", "MOV", "MOV", "MOV",
|
|
"INC", "MOV", "DBNZ", "STOP"
|
|
};
|
|
// need... air... badly...!
|
|
|
|
|
|
// %1 = Byte, %2 = Second Byte, %3 = high nibble of opcode #,
|
|
// %4 = high nibble of opcode # and 07h, %5 = relative to PC+2
|
|
// %6 = dp ($0/$1)
|
|
// %7 = memory SHR 3 Low, %8 = memory SHR 3 High, %9 = ,memory AND 7h
|
|
// %A = relative to PC+1, %B = relative to PC+1 at second byte
|
|
char *AddressTable[68] = {
|
|
// 1 1 1
|
|
"", "%3", "%6%1,%4", "B%4 %6%1,$%B+1",
|
|
// 0 : nothing
|
|
// 1 : the high nibble
|
|
// 2 : the high nibble first 3 bit (and 0111000 then shift)
|
|
// 3 : 2 + relative
|
|
"A,%6%1", "A,$%2%1", "A,(X)", "A,(%6%1+x)",
|
|
// 4 : A,dp
|
|
// 5 : A,labs
|
|
// 6 : A,(X)
|
|
// 7 : A,(dp+X)
|
|
"A,#$%1", "(%6%2),(%6%1)", "CF,mbit%8%7%9", "%6%1",
|
|
// 8 : A,#inm
|
|
// 9 : dp(d),dp(s) (two dp)
|
|
// 10 : Carry flag, memory bit (can only access from 0 to 1fff)
|
|
// 11 : dp
|
|
"$%2%1", "PSW", "$%A", "A,%6%1+X",
|
|
// 12 : labs
|
|
// 13 : PSW
|
|
// 14 : rel
|
|
// 15 : A,dp+X
|
|
"A,$%2%1+X", "A,$%2%1+Y", "A,(%6%1)+Y", "%6%2,#$%1",
|
|
// 16 : A,labs+X
|
|
// 17 : A,labs+Y
|
|
// 18 : A,(dp)+Y
|
|
// 19 : dp,#inm
|
|
"(X),(Y)", "%6%1+X", "A", "X",
|
|
// 20 : (X),(Y)
|
|
// 21 : dp+X
|
|
// 22 : A
|
|
// 23 : X
|
|
"X,%2%1", "($%2%1+X)", "CF,/(mb%8%7%9)", "%6%1",
|
|
// 24 : X,labs
|
|
// 25 : (labs+X)
|
|
// 26 : C,/mem.bit
|
|
// 27 : upage (same as dp but for a call)
|
|
"YA,%6%1", "X,A", "Y,$%2%1", "Y",
|
|
// 28 : YA,dp
|
|
// 29 : X,A
|
|
// 30 : Y,labs
|
|
// 31 : Y
|
|
"Y,%6%1", "Y,#$%1", "%6%1,$%B", "X,%6%1",
|
|
// 32 : Y,dp
|
|
// 33 : Y,#inm
|
|
// 34 : dp,rel
|
|
// 35 : X,dp
|
|
"A,X", "%6%2,#$%1", "X,SP", "YA,X",
|
|
// 36 : A,X
|
|
// 37 : dp,#inm
|
|
// 38 : X,SP
|
|
// 39 : YA,X
|
|
"(X)+,A", "SP,X", "A,(X)+", "%6%1,A",
|
|
// 40 : (X)+,A
|
|
// 41 : SP,X
|
|
// 42 : A,(X)+
|
|
// 43 : dp,A
|
|
"$%2%1,A", "(X),A", "%6%1+X,A", "X,#$%1",
|
|
// 44 : labs,A
|
|
// 45 : (X),A
|
|
// 46 : (dp+X),A
|
|
// 47 : X,#inm
|
|
"$%2%1,X", "mb%8%7%9,CF", "%6%1,Y", "$%2%1,Y",
|
|
// 48 : labs,X
|
|
// 49 : mem.bit,C
|
|
// 50 : dp,Y
|
|
// 51 : labs,Y
|
|
"YA", "%6%1+X,A", "$%2%1+X,A", "$%2%1+Y,A",
|
|
// 52 : YA
|
|
// 53 : dp+X,A
|
|
// 54 : labs+X,A
|
|
// 55 : labs+Y,A
|
|
"(%6%1)+Y,A", "%6%1,X", "%6%1+Y,X", "%6%1,YA",
|
|
// 56 : (dp)+Y,A
|
|
// 57 : dp,X
|
|
// 58 : dp+Y,X
|
|
// 59 : dp,YA
|
|
"%6%1+X,Y", "A,Y", "%6%2+X,$%A", "mb%8%7%9,CF",
|
|
// 60 : dp+X,Y
|
|
// 61 : A,Y
|
|
// 62 : dp+X,rel
|
|
// 63 : mem.bit
|
|
"X,%6%1+Y", "Y,%6%1+X", "Y,A", "Y,$%A",
|
|
// 64 : X,dp+Y
|
|
// 65 : Y,dp+X
|
|
// 66 : Y,A
|
|
// 67 : Y,rel
|
|
|
|
};
|
|
|
|
unsigned char ArgumentTable[256] = {
|
|
// 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,12, 0,
|
|
// 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
|
|
14, 1, 2, 3,15,16,17,18,19,20,11,21,22,23,24,25,
|
|
// 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,26,11,12,22,34,14,
|
|
// 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
|
|
14, 1, 2, 3,15,16,17,18,19,20,11,21,22,23,35,12,
|
|
// 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,23,12,27,
|
|
// 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
|
|
14, 1, 2, 3,15,16,17,18,19,20,28,21,22,29,30,12,
|
|
// 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,26,11,12,31,34, 0,
|
|
// 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
|
|
14, 1, 2, 3,15,16,17,18,19,20,28,21,22,36,32, 0,
|
|
// 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,33,13,37,
|
|
// 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
|
|
14, 1, 2, 3,15,16,17,18,19,20,28,21,22,38,39,22,
|
|
// A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,33,22,40,
|
|
// B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
|
|
14, 1, 2, 3,15,16,17,18,19,20,28,21,22,41,22,42,
|
|
// C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
|
|
0, 1, 2, 3,43,44,45,46,47,48,49,50,51,47,23,52,
|
|
// D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
|
|
14, 1, 2, 3,53,54,55,56,57,58,59,60,31,61,62,22,
|
|
// E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8,24,63,32,30, 0,31, 0,
|
|
// F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
|
|
14, 1, 2, 3,15,16,17,18,35,64, 9,65,31,66,67, 0
|
|
};
|
|
|
|
|
|
// Jonas Quinn's file functions
|
|
|
|
void SaveOAMRamLog() {
|
|
FILE *fp = 0;
|
|
|
|
if ((fp = fopen_dir(ZCfgPath,"vram.dat","wb"))) {
|
|
fwrite(oamram,1,544,fp);
|
|
fclose(fp);
|
|
}
|
|
}
|
|
|
|
void debugdump() {
|
|
FILE *fp = 0;
|
|
|
|
if ((fp = fopen_dir(ZCfgPath,"SPCRAM.dmp","wb"))) {
|
|
fwrite(SPCRAM,1,65536,fp);
|
|
fclose(fp);
|
|
}
|
|
|
|
if ((fp = fopen_dir(ZCfgPath,"DSP.dmp","wb"))) {
|
|
fwrite(DSPMem,1,256,fp);
|
|
fclose(fp);
|
|
}
|
|
}
|