2013-07-06 04:37:13 +00:00
/*
2015-10-22 05:13:26 +00:00
* Apple // emulator for *ix
2013-06-11 07:08:15 +00:00
*
* This software package is subject to the GNU General Public License
2015-10-22 05:13:26 +00:00
* version 3 or later ( your choice ) as published by the Free Software
2013-06-11 07:08:15 +00:00
* Foundation .
*
2015-10-22 05:13:26 +00:00
* Copyright 1997 , 1998 Aaron Culliney
* Copyright 1998 , 1999 , 2000 Michael Deutschmann
* Copyright 2013 - 2015 Aaron Culliney
2013-06-11 07:08:15 +00:00
*
*/
2014-01-23 04:42:34 +00:00
# include "common.h"
2013-06-11 07:08:15 +00:00
2015-02-18 21:42:28 +00:00
# include <test/sha1.h>
2014-03-30 19:23:08 +00:00
2015-01-10 17:44:23 +00:00
# define SW_TEXT 0xC050
# define SW_MIXED 0xC052
# define SW_PAGE2 0xC054
# define SW_HIRES 0xC056
# define SW_80STORE 0xC000
# define SW_RAMRD 0xC002
# define SW_RAMWRT 0xC004
# define SW_ALTZP 0xC008
# define SW_80COL 0xC00C
# define SW_ALTCHAR 0xC00E
# define SW_SLOTC3ROM 0xC00B /* anomaly */
# define SW_SLOTCXROM 0xC006
# define SW_DHIRES 0xC05E
# define SW_IOUDIS 0xC07E
2013-06-11 07:08:15 +00:00
const struct opcode_struct * opcodes ;
2014-03-30 19:23:08 +00:00
static stepping_struct_t stepping_struct = { 0 } ;
static unsigned int stepping_timeout = 0 ;
2014-03-22 18:24:57 +00:00
volatile bool is_debugging = false ;
2015-07-26 20:38:43 +00:00
extern pthread_mutex_t interface_mutex ;
extern pthread_cond_t cpu_thread_cond ;
extern pthread_cond_t dbg_thread_cond ;
# warning ^^^ HACK FIXME TODO ... debugger should not have raw access to mutex variables
2014-03-22 18:24:57 +00:00
# define BUF_X DEBUGGER_BUF_X
# define BUF_Y DEBUGGER_BUF_Y
# define SCREEN_X 81 // 80col + 1
# define SCREEN_Y 24
# define PROMPT_X 2
# define PROMPT_Y BUF_Y - 1
# define PROMPT_END_X BUF_X - 2
# define command_line command_buf[PROMPT_Y]
2013-07-06 04:37:13 +00:00
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
2014-06-21 21:33:23 +00:00
# ifdef INTERFACE_CLASSIC
2013-06-11 07:08:15 +00:00
/* debugger globals */
2013-11-27 20:43:58 +00:00
//1. 5. 10. 15. 20. 25. 30. 35. 40. 45. 50. 55. 60. 65. 70. 75. 80.",
2013-06-19 07:07:41 +00:00
static char screen [ SCREEN_Y ] [ SCREEN_X ] =
2013-11-27 20:43:58 +00:00
{ " |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| " ,
" | | | " ,
" | | | " ,
" | | | " ,
" | | | " ,
" | | | " ,
" | | | " ,
" | | | " ,
" | | | " ,
" | | | " ,
" | | | " ,
" | | | " ,
" | | | " ,
" | | | " ,
" | | | " ,
" | | | " ,
" | | | " ,
" | | | " ,
" | | | " ,
" | | | " ,
" | | | " ,
" | | | " ,
" | | | " ,
" |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| " } ;
2013-07-06 04:37:13 +00:00
static char command_buf [ BUF_Y ] [ BUF_X ] ; /* command line prompt */
2014-06-21 21:33:23 +00:00
# endif
2013-07-06 04:37:13 +00:00
char lexbuf [ BUF_X + 2 ] ; /* comman line to be flex'ed */
2013-06-11 07:08:15 +00:00
2014-03-22 18:24:57 +00:00
uint8_t current_opcode ;
2013-06-11 07:08:15 +00:00
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 */
2014-01-23 04:42:34 +00:00
extern int 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 ) ;
}
2014-03-22 18:24:57 +00:00
/* -------------------------------------------------------------------------
get_last_opcode ( ) - returns the last executed opcode
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
uint8_t get_last_opcode ( ) {
2014-06-22 18:16:38 +00:00
return cpu65_opcode ;
2014-03-22 18:24:57 +00:00
}
2013-06-11 07:08:15 +00:00
/* -------------------------------------------------------------------------
get_current_opcode ( ) - returns the opcode from the address that
the PC is currently reading from .
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2014-03-22 18:24:57 +00:00
uint8_t get_current_opcode ( ) {
2014-06-22 18:16:38 +00:00
int bank = c_get_current_rambank ( cpu65_pc ) ;
2013-06-11 07:08:15 +00:00
int lcbank = 0 ;
/* main RAM */
2014-06-22 18:16:38 +00:00
if ( cpu65_pc < 0xD000 )
2013-07-06 04:37:13 +00:00
{
2014-06-22 18:16:38 +00:00
return apple_ii_64k [ bank ] [ cpu65_pc ] ;
2013-06-11 07:08:15 +00:00
}
/* LC RAM */
2014-06-22 18:16:38 +00:00
if ( cpu65_pc > = 0xE000 )
2013-07-06 04:37:13 +00:00
{
if ( softswitches & SS_LCRAM )
{
2014-06-22 18:16:38 +00:00
return language_card [ bank ] [ cpu65_pc - 0xE000 ] ;
2013-07-06 04:37:13 +00:00
}
else
{
2014-06-22 18:16:38 +00:00
return apple_ii_64k [ bank ] [ cpu65_pc ] ;
2013-07-06 04:37:13 +00:00
}
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
{
2014-06-22 18:16:38 +00:00
return language_banks [ bank ] [ cpu65_pc - 0xD000 + lcbank ] ;
2013-07-06 04:37:13 +00:00
}
2013-06-11 07:08:15 +00:00
else
2013-07-06 04:37:13 +00:00
{
2014-06-22 18:16:38 +00:00
return apple_ii_64k [ bank ] [ cpu65_pc ] ;
2013-07-06 04:37:13 +00:00
}
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 ;
2014-03-22 18:24:57 +00:00
uint8_t 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 ) )
{
2014-06-22 18:16:38 +00:00
addrs = cpu65_pc ;
2013-07-06 04:37:13 +00:00
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 )
{
2013-10-07 04:01:00 +00:00
op = ( addrs + j > = 0x1000 ) ? language_card [ rambank ] [ ( addrs + j ) - 0x1000 ] : ( lc = = 1 ) ? language_banks [ rambank ] [ addrs + j ] : language_banks [ rambank ] [ 0x1000 + addrs + j ] ;
2013-07-06 04:37:13 +00:00
}
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 ] = ' ' ;
}
}
}
2014-10-25 18:38:28 +00:00
memset ( second_buf [ i ] , ' ' , BUF_X ) ;
2013-07-06 04:37:13 +00:00
sprintf ( second_buf [ i ] , " %04X:%02X " , orig_addrs + j , op ) ;
if ( do_ascii )
{
2013-10-07 04:01:00 +00:00
sprintf ( second_buf [ i ] + 23 , " %c " , ( ( op & 0x7f ) > 31 ) ? ( op & 0x7f ) : ' . ' ) ;
2013-07-06 04:37:13 +00:00
}
continue ;
}
sprintf ( second_buf [ i ] + 5 + mod * 2 , " %02X " , op ) ;
if ( do_ascii )
{
2013-10-07 04:01:00 +00:00
sprintf ( second_buf [ i ] + 23 + mod , " %c " , ( ( op & 0x7f ) > 31 ) ? ( op & 0x7f ) : ' . ' ) ;
2013-07-06 04:37:13 +00:00
}
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 ] ;
2014-03-22 18:24:57 +00:00
uint8_t byte ;
2013-06-11 07:08:15 +00:00
end = ( lc ) ? 0x3000 : 0x10000 ;
2014-06-22 18:16:38 +00:00
/* check which rambank for cpu65_pc */
2013-07-06 04:37:13 +00:00
if ( rambank = = - 1 )
{
2014-06-22 18:16:38 +00:00
rambank = c_get_current_rambank ( cpu65_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 */
2014-03-22 18:24:57 +00:00
byte = ( uint8_t ) strtol ( scratch , ( char * * ) NULL , 16 ) ;
2013-07-06 04:37:13 +00:00
if ( lc )
{
2013-10-07 04:01:00 +00:00
op = ( i > = 0x1000 ) ? language_card [ rambank ] [ i - 0x1000 ] : ( lc = = 1 ) ? language_banks [ rambank ] [ i ] : language_banks [ rambank ] [ 0x1000 + i ] ;
2013-07-06 04:37:13 +00:00
}
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 */
2013-10-07 04:01:00 +00:00
sprintf ( second_buf [ num_buffer_lines ] , " %04X: %s " , i - ( j > > 1 ) , hexstr ) ;
2013-07-06 04:37:13 +00:00
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 */
2013-10-07 04:01:00 +00:00
sprintf ( second_buf [ num_buffer_lines ] , " %04X: %s " , i - ( j > > 1 ) + 1 , hexstr ) ;
2013-07-06 04:37:13 +00:00
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 ] ;
2014-03-22 18:24:57 +00:00
uint8_t data ;
2013-06-11 07:08:15 +00:00
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 ) ;
2014-03-22 18:24:57 +00:00
data = ( uint8_t ) 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 ] ;
2014-03-22 18:24:57 +00:00
uint8_t data ;
2013-06-11 07:08:15 +00:00
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 ) ;
2014-03-22 18:24:57 +00:00
data = ( uint8_t ) 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
}
2013-10-07 04:01:00 +00:00
else if ( lcbank )
2013-07-06 04:37:13 +00:00
{
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 . . .
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2014-06-14 17:37:14 +00:00
void bload ( FILE * f , char * name , int bank , int addrs ) {
2014-03-22 18:24:57 +00:00
uint8_t * hexstr = NULL ;
2014-06-21 21:33:23 +00:00
size_t len = - 1 ;
2014-03-22 18:24:57 +00:00
uint8_t data ;
2013-07-06 04:37:13 +00:00
if ( ( addrs < 0 ) | | ( addrs > 0xffff ) )
{
2014-03-30 20:17:47 +00:00
sprintf ( second_buf [ num_buffer_lines + + ] , " problem: invalid address " ) ;
2013-07-06 04:37:13 +00:00
return ;
2013-06-11 07:08:15 +00:00
}
2014-05-12 02:18:53 +00:00
# define TEMPSIZE 1024
char temp [ TEMPSIZE ] ;
2013-07-06 04:37:13 +00:00
while ( ( len = fread ( temp , 1 , TEMPSIZE , f ) ) )
{
2014-03-22 18:24:57 +00:00
hexstr = ( uint8_t * ) temp ;
2013-07-06 04:37:13 +00:00
for ( ; len > 0 ; len - - )
{
data = * hexstr ;
2014-03-30 20:17:47 +00:00
if ( addrs + len > = 0x10000 ) {
sprintf ( second_buf [ num_buffer_lines + + ] , " problem: bload will overflow " ) ;
return ;
}
2013-07-06 04:37:13 +00:00
/* 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 ] ;
2014-03-22 18:24:57 +00:00
uint8_t op ;
2013-06-11 07:08:15 +00:00
char arg1 , arg2 ;
int i , j , k , end , orig_addrs = addrs ;
2014-06-22 18:16:38 +00:00
/* check which rambank for cpu65_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 ) )
{
2014-06-22 18:16:38 +00:00
addrs = cpu65_pc ;
2013-07-06 04:37:13 +00:00
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 ;
2013-10-07 04:01:00 +00:00
for ( i = num_buffer_lines , j = addrs , k = orig_addrs ; ( ( i < len ) & & ( j < end ) ) ; i + + , j + + )
2013-06-11 07:08:15 +00:00
{
2013-07-06 04:37:13 +00:00
if ( lc )
{
2013-10-07 04:01:00 +00:00
op = ( j > = 0x1000 ) ? language_card [ rambank ] [ j - 0x1000 ] : ( lc = = 1 ) ? language_banks [ rambank ] [ j ] : language_banks [ rambank ] [ 0x1000 + j ] ;
2013-07-06 04:37:13 +00:00
}
else
{
op = apple_ii_64k [ rambank ] [ j ] ;
}
switch ( opcodes [ op ] . mode )
{
case addr_implied :
case addr_accumulator : /* no arg */
2013-10-07 04:01:00 +00:00
sprintf ( second_buf [ i ] , " /%02X/%04X: %02X %s %s " , rambank , k + + , op , opcodes [ op ] . mnemonic , 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 )
{
2013-10-07 04:01:00 +00:00
arg1 = ( j > = 0x1000 ) ? language_card [ rambank ] [ + + j - 0x1000 ] : ( lc = = 1 ) ? language_banks [ rambank ] [ + + j ] : language_banks [ rambank ] [ + + j + 0x1000 ] ;
2013-07-06 04:37:13 +00:00
}
else
{
arg1 = apple_ii_64k [ rambank ] [ + + j ] ;
}
2014-03-22 18:24:57 +00:00
sprintf ( fmt , " /%02X/%04X: %02X%02X %s %s " , rambank , k , op , ( uint8_t ) arg1 , opcodes [ op ] . mnemonic , disasm_templates [ opcodes [ op ] . mode ] ) ;
2013-06-11 07:08:15 +00:00
2014-03-22 18:24:57 +00:00
sprintf ( second_buf [ i ] , fmt , ( uint8_t ) arg1 ) ;
2013-07-06 04:37:13 +00:00
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 )
{
2013-10-07 04:01:00 +00:00
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 ] ;
2013-07-06 04:37:13 +00:00
}
else
{
arg1 = apple_ii_64k [ rambank ] [ + + j ] ;
arg2 = apple_ii_64k [ rambank ] [ + + j ] ;
}
2014-03-22 18:24:57 +00:00
sprintf ( fmt , " /%02X/%04X: %02X%02X%02X %s %s " , rambank , k , op , ( uint8_t ) arg1 , ( uint8_t ) arg2 , opcodes [ op ] . mnemonic , disasm_templates [ opcodes [ op ] . mode ] ) ;
sprintf ( second_buf [ i ] , fmt , ( uint8_t ) arg2 , ( uint8_t ) arg1 ) ;
2013-07-06 04:37:13 +00:00
k + = 3 ;
break ;
case addr_relative : /* offset */
if ( k = = 0xffff )
{
num_buffer_lines = i ;
return ;
}
if ( lc )
{
2013-10-07 04:01:00 +00:00
arg1 = ( j > = 0x1000 ) ? language_card [ rambank ] [ + + j - 0x1000 ] : ( lc = = 1 ) ? language_banks [ rambank ] [ + + j ] : language_banks [ rambank ] [ + + j + 0x1000 ] ;
2013-07-06 04:37:13 +00:00
}
else
{
arg1 = apple_ii_64k [ rambank ] [ + + j ] ;
}
2014-03-22 18:24:57 +00:00
sprintf ( fmt , " /%02X/%04X: %02X%02X %s %s " , rambank , k , op , ( uint8_t ) arg1 , opcodes [ op ] . mnemonic , disasm_templates [ opcodes [ op ] . mode ] ) ;
2013-07-06 04:37:13 +00:00
if ( arg1 < 0 )
{
2014-03-22 18:24:57 +00:00
sprintf ( second_buf [ i ] , fmt , k + arg1 + 2 , ' - ' , ( uint8_t ) ( - arg1 ) ) ;
2013-07-06 04:37:13 +00:00
}
else
{
2014-03-22 18:24:57 +00:00
sprintf ( second_buf [ i ] , fmt , k + arg1 + 2 , ' + ' , ( uint8_t ) arg1 ) ;
2013-07-06 04:37:13 +00:00
}
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 ( ) {
2014-06-22 18:16:38 +00:00
sprintf ( second_buf [ num_buffer_lines + + ] , " PC = %04X EA = %04X SP = %04X " , cpu65_pc , cpu65_ea , cpu65_sp + 0x0100 ) ;
sprintf ( second_buf [ num_buffer_lines + + ] , " X = %02X Y = %02X A = %02X F = %02X " , cpu65_x , cpu65_y , cpu65_a , cpu65_f ) ;
2013-06-11 07:08:15 +00:00
memset ( second_buf [ num_buffer_lines ] , ' ' , BUF_X ) ;
2014-06-22 18:16:38 +00:00
if ( cpu65_f & C_Flag_6502 )
2013-07-06 04:37:13 +00:00
{
second_buf [ num_buffer_lines ] [ 0 ] = ' C ' ;
}
2014-06-22 18:16:38 +00:00
if ( cpu65_f & X_Flag_6502 )
2013-07-06 04:37:13 +00:00
{
second_buf [ num_buffer_lines ] [ 1 ] = ' X ' ;
}
2014-06-22 18:16:38 +00:00
if ( cpu65_f & I_Flag_6502 )
2013-07-06 04:37:13 +00:00
{
second_buf [ num_buffer_lines ] [ 2 ] = ' I ' ;
}
2014-06-22 18:16:38 +00:00
if ( cpu65_f & V_Flag_6502 )
2013-07-06 04:37:13 +00:00
{
second_buf [ num_buffer_lines ] [ 3 ] = ' V ' ;
}
2014-06-22 18:16:38 +00:00
if ( cpu65_f & B_Flag_6502 )
2013-07-06 04:37:13 +00:00
{
second_buf [ num_buffer_lines ] [ 4 ] = ' B ' ;
}
2014-06-22 18:16:38 +00:00
if ( cpu65_f & D_Flag_6502 )
2013-07-06 04:37:13 +00:00
{
second_buf [ num_buffer_lines ] [ 5 ] = ' D ' ;
}
2014-06-22 18:16:38 +00:00
if ( cpu65_f & Z_Flag_6502 )
2013-07-06 04:37:13 +00:00
{
second_buf [ num_buffer_lines ] [ 6 ] = ' Z ' ;
}
2014-06-22 18:16:38 +00:00
if ( cpu65_f & N_Flag_6502 )
2013-07-06 04:37:13 +00:00
{
second_buf [ num_buffer_lines ] [ 7 ] = ' N ' ;
}
2013-06-11 07:08:15 +00:00
+ + num_buffer_lines ;
}
2015-02-16 02:32:45 +00:00
# if !TESTING
2013-06-11 07:08:15 +00:00
/* -------------------------------------------------------------------------
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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2014-03-30 19:23:08 +00:00
# define BRANCH_NA -1
2013-06-11 07:08:15 +00:00
static int will_branch ( ) {
2014-03-22 18:24:57 +00:00
uint8_t op = get_current_opcode ( ) ;
2013-07-06 04:37:13 +00:00
switch ( op )
{
case 0x10 : /* BPL */
2014-06-22 18:16:38 +00:00
return ( int ) ! ( cpu65_f & N_Flag_6502 ) ;
2013-07-06 04:37:13 +00:00
case 0x30 : /* BMI */
2014-06-22 18:16:38 +00:00
return ( int ) ( cpu65_f & N_Flag_6502 ) ;
2013-07-06 04:37:13 +00:00
case 0x50 : /* BVC */
2014-06-22 18:16:38 +00:00
return ( int ) ! ( cpu65_f & V_Flag_6502 ) ;
2013-07-06 04:37:13 +00:00
case 0x70 : /* BVS */
2014-06-22 18:16:38 +00:00
return ( int ) ( cpu65_f & V_Flag_6502 ) ;
2013-07-06 04:37:13 +00:00
case 0x80 : /* BRA */
return 1 ;
case 0x90 : /* BCC */
2014-06-22 18:16:38 +00:00
return ( int ) ! ( cpu65_f & C_Flag_6502 ) ;
2013-07-06 04:37:13 +00:00
case 0xb0 : /* BCS */
2014-06-22 18:16:38 +00:00
return ( int ) ( cpu65_f & C_Flag_6502 ) ;
2013-07-06 04:37:13 +00:00
case 0xd0 : /* BNE */
2014-06-22 18:16:38 +00:00
return ( int ) ! ( cpu65_f & Z_Flag_6502 ) ;
2013-07-06 04:37:13 +00:00
case 0xf0 : /* BEQ */
2014-06-22 18:16:38 +00:00
return ( int ) ( cpu65_f & Z_Flag_6502 ) ;
2013-06-11 07:08:15 +00:00
}
2014-03-30 19:23:08 +00:00
return BRANCH_NA ;
2013-06-11 07:08:15 +00:00
}
2014-04-06 03:58:29 +00:00
# endif
2013-06-11 07:08:15 +00:00
/* -------------------------------------------------------------------------
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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2014-03-30 19:35:09 +00:00
bool set_halt ( int * type , int addrs ) {
2013-06-11 07:08:15 +00:00
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 ) ;
2014-03-30 19:35:09 +00:00
return true ;
2013-07-06 04:37:13 +00:00
}
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! " ) ;
2014-03-30 19:35:09 +00:00
return false ;
2013-06-11 07:08:15 +00:00
}
/* -------------------------------------------------------------------------
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 .
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2014-03-22 18:24:57 +00:00
void set_halt_opcode ( uint8_t opcode ) {
2013-06-11 07:08:15 +00:00
op_breakpoints [ opcode ] = 1 ;
}
/* -------------------------------------------------------------------------
clear_halt_opcode ( ) = unset an opcode breakpoint .
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2014-03-22 18:24:57 +00:00
void clear_halt_opcode ( uint8_t opcode ) {
2013-06-11 07:08:15 +00:00
op_breakpoints [ opcode ] = 0 ;
}
/* -------------------------------------------------------------------------
set_halt_65c02 ( ) = set a breakpoint on all 65 c02 instructions .
assumes that you are in //e mode...
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void set_halt_65c02 ( ) {
2014-03-22 18:24:57 +00:00
set_halt_opcode ( ( uint8_t ) 0x02 ) ; set_halt_opcode ( ( uint8_t ) 0x04 ) ;
set_halt_opcode ( ( uint8_t ) 0x0C ) ; set_halt_opcode ( ( uint8_t ) 0x12 ) ;
set_halt_opcode ( ( uint8_t ) 0x14 ) ; set_halt_opcode ( ( uint8_t ) 0x1A ) ;
set_halt_opcode ( ( uint8_t ) 0x1C ) ; set_halt_opcode ( ( uint8_t ) 0x32 ) ;
set_halt_opcode ( ( uint8_t ) 0x34 ) ; set_halt_opcode ( ( uint8_t ) 0x3A ) ;
set_halt_opcode ( ( uint8_t ) 0x3C ) ; set_halt_opcode ( ( uint8_t ) 0x52 ) ;
set_halt_opcode ( ( uint8_t ) 0x5A ) ; set_halt_opcode ( ( uint8_t ) 0x64 ) ;
set_halt_opcode ( ( uint8_t ) 0x72 ) ; set_halt_opcode ( ( uint8_t ) 0x74 ) ;
set_halt_opcode ( ( uint8_t ) 0x7A ) ; set_halt_opcode ( ( uint8_t ) 0x7C ) ;
set_halt_opcode ( ( uint8_t ) 0x80 ) ; set_halt_opcode ( ( uint8_t ) 0x89 ) ;
set_halt_opcode ( ( uint8_t ) 0x92 ) ; set_halt_opcode ( ( uint8_t ) 0x9C ) ;
set_halt_opcode ( ( uint8_t ) 0x9E ) ; set_halt_opcode ( ( uint8_t ) 0xB2 ) ;
set_halt_opcode ( ( uint8_t ) 0xD2 ) ; set_halt_opcode ( ( uint8_t ) 0xDA ) ;
set_halt_opcode ( ( uint8_t ) 0xF2 ) ; set_halt_opcode ( ( uint8_t ) 0xFA ) ;
2013-06-11 07:08:15 +00:00
}
/* -------------------------------------------------------------------------
clear_halt_65c02 ( ) = clear all 65 c02 instructions
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void clear_halt_65c02 ( ) {
2014-03-22 18:24:57 +00:00
clear_halt_opcode ( ( uint8_t ) 0x02 ) ; clear_halt_opcode ( ( uint8_t ) 0x04 ) ;
clear_halt_opcode ( ( uint8_t ) 0x0C ) ; clear_halt_opcode ( ( uint8_t ) 0x12 ) ;
clear_halt_opcode ( ( uint8_t ) 0x14 ) ; clear_halt_opcode ( ( uint8_t ) 0x1A ) ;
clear_halt_opcode ( ( uint8_t ) 0x1C ) ; clear_halt_opcode ( ( uint8_t ) 0x32 ) ;
clear_halt_opcode ( ( uint8_t ) 0x34 ) ; clear_halt_opcode ( ( uint8_t ) 0x3A ) ;
clear_halt_opcode ( ( uint8_t ) 0x3C ) ; clear_halt_opcode ( ( uint8_t ) 0x52 ) ;
clear_halt_opcode ( ( uint8_t ) 0x5A ) ; clear_halt_opcode ( ( uint8_t ) 0x64 ) ;
clear_halt_opcode ( ( uint8_t ) 0x72 ) ; clear_halt_opcode ( ( uint8_t ) 0x74 ) ;
clear_halt_opcode ( ( uint8_t ) 0x7A ) ; clear_halt_opcode ( ( uint8_t ) 0x7C ) ;
clear_halt_opcode ( ( uint8_t ) 0x80 ) ; clear_halt_opcode ( ( uint8_t ) 0x89 ) ;
clear_halt_opcode ( ( uint8_t ) 0x92 ) ; clear_halt_opcode ( ( uint8_t ) 0x9C ) ;
clear_halt_opcode ( ( uint8_t ) 0x9E ) ; clear_halt_opcode ( ( uint8_t ) 0xB2 ) ;
clear_halt_opcode ( ( uint8_t ) 0xD2 ) ; clear_halt_opcode ( ( uint8_t ) 0xDA ) ;
clear_halt_opcode ( ( uint8_t ) 0xF2 ) ; clear_halt_opcode ( ( uint8_t ) 0xFA ) ;
2013-06-11 07:08:15 +00:00
}
/* -------------------------------------------------------------------------
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 ( ) {
2014-03-30 19:35:09 +00:00
int count = 0 ;
2013-06-11 07:08:15 +00:00
/* check op_breakpoints */
2014-03-22 18:24:57 +00:00
uint8_t op = get_last_opcode ( ) ;
2013-06-11 07:08:15 +00:00
if ( op_breakpoints [ op ] )
2013-07-06 04:37:13 +00:00
{
2014-06-22 18:16:38 +00:00
sprintf ( second_buf [ num_buffer_lines + + ] , " stopped at %04X bank %d instruction %02X " , cpu65_pc , c_get_current_rambank ( cpu65_pc ) , op ) ;
2014-03-30 19:35:09 +00:00
+ + count ;
2013-07-06 04:37:13 +00:00
}
2013-06-11 07:08:15 +00:00
2014-03-30 19:35:09 +00:00
for ( int i = 0 ; i < MAX_BRKPTS ; i + + )
2013-07-06 04:37:13 +00:00
{
2014-06-22 18:16:38 +00:00
if ( cpu65_pc = = breakpoints [ i ] )
2013-07-06 04:37:13 +00:00
{
2014-06-22 18:16:38 +00:00
sprintf ( second_buf [ num_buffer_lines + + ] , " stopped at %04X bank %d " , breakpoints [ i ] , c_get_current_rambank ( cpu65_pc ) ) ;
2014-03-30 19:35:09 +00:00
+ + count ;
2013-07-06 04:37:13 +00:00
}
2013-06-11 07:08:15 +00:00
}
2014-06-22 18:16:38 +00:00
if ( cpu65_rw ) /* only check watchpoints if read/write occured */
2013-06-11 07:08:15 +00:00
{
2014-03-30 19:35:09 +00:00
for ( int i = 0 ; i < MAX_BRKPTS ; i + + )
2013-07-06 04:37:13 +00:00
{
2014-06-22 18:16:38 +00:00
if ( cpu65_ea = = watchpoints [ i ] )
2013-07-06 04:37:13 +00:00
{
2014-06-22 18:16:38 +00:00
if ( cpu65_rw & 0x2 )
2013-07-06 04:37:13 +00:00
{
2014-06-22 18:16:38 +00:00
sprintf ( second_buf [ num_buffer_lines + + ] , " wrote: %04X: %02X " , watchpoints [ i ] , cpu65_d ) ;
2014-03-30 19:35:09 +00:00
+ + count ;
2013-07-06 04:37:13 +00:00
}
else
{
2013-10-07 04:01:00 +00:00
sprintf ( second_buf [ num_buffer_lines + + ] , " read: %04X " , watchpoints [ i ] ) ;
2014-03-30 19:35:09 +00:00
+ + count ;
2013-07-06 04:37:13 +00:00
}
2014-06-22 18:16:38 +00:00
cpu65_rw = 0 ; /* only allow WP to trip once */
2013-07-06 04:37:13 +00:00
}
}
2013-06-11 07:08:15 +00:00
}
2013-07-06 04:37:13 +00:00
2014-03-30 19:35:09 +00:00
return count ; /* 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 ) )
{
2013-10-07 04:01:00 +00:00
sprintf ( second_buf [ i + + ] , " break %02d at %04X watch %02d at %04X " , k + 1 , breakpoints [ k ] , k + 1 , watchpoints [ k ] ) ;
2013-07-06 04:37:13 +00:00
}
2013-10-07 04:01:00 +00:00
else if ( breakpoints [ k ] > = 0 )
2013-07-06 04:37:13 +00:00
{
2013-10-07 04:01:00 +00:00
sprintf ( second_buf [ i + + ] , " break %02d at %04X " , k + 1 , breakpoints [ k ] ) ;
2013-07-06 04:37:13 +00:00
}
2013-10-07 04:01:00 +00:00
else if ( watchpoints [ k ] > = 0 )
2013-07-06 04:37:13 +00:00
{
memset ( second_buf [ i ] , ' ' , BUF_X ) ;
2013-10-07 04:01:00 +00:00
sprintf ( second_buf [ i + + ] + 16 , " watch %02d at %04X " , k + 1 , watchpoints [ k ] ) ;
2013-07-06 04:37:13 +00:00
}
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 ;
2014-10-25 16:00:06 +00:00
# warning FIXME TODO ... investigate / refactor all uses of !! here and elsewhere
sprintf ( second_buf [ i + + ] , " lc bank = %d " , 1 + ! ! ( softswitches & SS_BANK2 ) ) ;
2013-10-07 04:01:00 +00:00
( softswitches & SS_LCWRT ) ? sprintf ( second_buf [ i + + ] , " write LC " ) : sprintf ( second_buf [ i + + ] , " LC write protected " ) ;
( softswitches & SS_LCRAM ) ? sprintf ( second_buf [ i + + ] , " read LC " ) : sprintf ( second_buf [ i + + ] , " read ROM " ) ;
2014-10-25 16:00:06 +00:00
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-10-07 04:01:00 +00:00
sprintf ( second_buf [ i + + ] , " TEXT (%04X): %s " , SW_TEXT + ! ! ( softswitches & SS_TEXT ) , ( softswitches & SS_TEXT ) ? " on " : " off " ) ;
sprintf ( second_buf [ i + + ] , " MIXED (%04X): %s " , SW_MIXED + ! ! ( softswitches & SS_MIXED ) , ( softswitches & SS_MIXED ) ? " on " : " off " ) ;
sprintf ( second_buf [ i + + ] , " PAGE2 (%04X): %s " , SW_PAGE2 + ! ! ( softswitches & SS_PAGE2 ) , ( softswitches & SS_PAGE2 ) ? " on " : " off " ) ;
sprintf ( second_buf [ i + + ] , " HIRES (%04X): %s " , SW_HIRES + ! ! ( softswitches & SS_HIRES ) , ( softswitches & SS_HIRES ) ? " on " : " off " ) ;
sprintf ( second_buf [ i + + ] , " 80STORE (%04X): %s " , SW_80STORE + ! ! ( softswitches & SS_80STORE ) , ( softswitches & SS_80STORE ) ? " on " : " off " ) ;
sprintf ( second_buf [ i + + ] , " RAMRD (%04X): %s " , SW_RAMRD + ! ! ( softswitches & SS_RAMRD ) , ( softswitches & SS_RAMRD ) ? " on " : " off " ) ;
sprintf ( second_buf [ i + + ] , " RAMWRT (%04X): %s " , SW_RAMWRT + ! ! ( softswitches & SS_RAMWRT ) , ( softswitches & SS_RAMWRT ) ? " on " : " off " ) ;
sprintf ( second_buf [ i + + ] , " ALTZP (%04X): %s " , SW_ALTZP + ! ! ( softswitches & SS_ALTZP ) , ( softswitches & SS_ALTZP ) ? " on " : " off " ) ;
sprintf ( second_buf [ i + + ] , " 80COL (%04X): %s " , SW_80COL + ! ! ( softswitches & SS_80COL ) , ( softswitches & SS_80COL ) ? " on " : " off " ) ;
sprintf ( second_buf [ i + + ] , " ALTCHAR (%04X): %s " , SW_ALTCHAR + ! ! ( softswitches & SS_ALTCHAR ) , ( softswitches & SS_ALTCHAR ) ? " on " : " off " ) ;
sprintf ( second_buf [ i + + ] , " SLOTC3ROM (%04X): %s " , SW_SLOTC3ROM - /*anomaly*/ ! ! ( softswitches & SS_C3ROM ) , ( softswitches & SS_C3ROM ) ? " on " : " off " ) ;
sprintf ( second_buf [ i + + ] , " SLOTCXROM (%04X): %s " , SW_SLOTCXROM + ! ! ( softswitches & SS_CXROM ) , ( softswitches & SS_CXROM ) ? " on " : " off " ) ;
2014-10-25 16:00:06 +00:00
sprintf ( second_buf [ i + + ] , " DHIRES (%04X): %s " , SW_DHIRES + ! ! ( softswitches & SS_DHIRES ) , ( softswitches & SS_DHIRES ) ? " on " : " off " ) ;
sprintf ( second_buf [ i + + ] , " IOUDIS (%04X): %s " , SW_IOUDIS + ! ! ( softswitches & SS_IOUDIS ) , ( 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 ] ;
2014-06-21 21:33:23 +00:00
int i = num_buffer_lines ;
size_t len = 0 ;
int off = 19 ;
2013-06-11 07:08:15 +00:00
/* generic information */
sprintf ( second_buf [ i + + ] , " drive %s " , ( disk6 . drive ) ? " B " : " A " ) ;
2015-01-11 20:03:07 +00:00
sprintf ( second_buf [ i + + ] , " motor %s " , ( disk6 . motor_off ) ? " off " : " on " ) ;
2013-06-11 07:08:15 +00:00
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 )
{
2014-12-28 21:07:13 +00:00
//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 ) ;
2015-10-17 04:47:56 +00:00
if ( disk6 . disk [ 0 ] . file_name & & ( len = strlen ( disk6 . disk [ 0 ] . file_name ) ) )
2013-07-06 04:37:13 +00:00
{
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
}
2015-10-17 04:47:56 +00:00
if ( disk6 . disk [ 1 ] . file_name & & ( len = strlen ( disk6 . disk [ 1 ] . file_name ) ) )
2013-07-06 04:37:13 +00:00
{
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 ) ;
2014-12-28 21:07:13 +00:00
* ( second_buf [ i ] + sprintf ( second_buf [ i ] , " %s " , ( disk6 . disk [ 0 ] . nibblized ) ? " .nib " : " .dsk " ) ) = ' ' ;
sprintf ( second_buf [ i + + ] + off , " %s " , ( disk6 . disk [ 1 ] . nibblized ) ? " .nib " : " .dsk " ) ;
2013-06-11 07:08:15 +00:00
memset ( second_buf [ i ] , ' ' , BUF_X ) ;
2013-12-01 18:42:05 +00:00
* ( second_buf [ i ] + sprintf ( second_buf [ i ] , " write %s " , ( disk6 . disk [ 0 ] . is_protected ) ? " protected " : " enabled " ) ) = ' ' ;
sprintf ( second_buf [ i + + ] + off , " write %s " , ( disk6 . disk [ 1 ] . is_protected ) ? " protected " : " enabled " ) ;
2013-06-11 07:08:15 +00:00
memset ( second_buf [ i ] , ' ' , BUF_X ) ;
2014-12-28 21:07:13 +00:00
* ( second_buf [ i ] + sprintf ( second_buf [ i ] , " phase %d " , disk6 . disk [ 0 ] . phase ) ) = ' ' ;
sprintf ( second_buf [ i + + ] + off , " phase %d " , disk6 . disk [ 1 ] . phase ) ;
2013-06-11 07:08:15 +00:00
memset ( second_buf [ i ] , ' ' , BUF_X ) ;
num_buffer_lines = i ;
}
/* -------------------------------------------------------------------------
clear_debugger_screen ( ) - clears the screen of graphics artifacts .
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void clear_debugger_screen ( ) {
2014-06-21 21:26:39 +00:00
# ifdef INTERFACE_CLASSIC
2013-06-11 07:08:15 +00:00
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 ] ) ;
}
2014-06-21 21:26:39 +00:00
# endif
2013-06-11 07:08:15 +00:00
}
/* -------------------------------------------------------------------------
2014-03-30 19:23:08 +00:00
fb_sha1 ( ) - - prints SHA1 of the current Apple // framebuffer
2013-06-11 07:08:15 +00:00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2014-03-30 19:23:08 +00:00
void fb_sha1 ( ) {
uint8_t md [ SHA_DIGEST_LENGTH ] ;
char buf [ ( SHA_DIGEST_LENGTH * 2 ) + 1 ] ;
2013-06-11 07:08:15 +00:00
2014-03-30 19:23:08 +00:00
video_setpage ( ! ! ( softswitches & SS_SCREEN ) ) ;
video_redraw ( ) ;
const uint8_t * const fb = video_current_framebuffer ( ) ;
SHA1 ( fb , SCANWIDTH * SCANHEIGHT , md ) ;
int i = 0 ;
for ( int j = 0 ; j < SHA_DIGEST_LENGTH ; j + + , i + = 2 ) {
sprintf ( buf + i , " %02X " , md [ j ] ) ;
}
sprintf ( buf + i , " %c " , ' \0 ' ) ;
LOG ( " SHA1 : %s " , buf ) ;
int ch = - 1 ;
2015-05-31 19:57:33 +00:00
# ifdef INTERFACE_CLASSIC
2014-03-30 19:23:08 +00:00
while ( ( ch = c_mygetch ( 1 ) ) = = - 1 ) {
// ...
2013-07-06 04:37:13 +00:00
}
2015-05-31 19:57:33 +00:00
# endif
2014-03-30 19:23:08 +00:00
clear_debugger_screen ( ) ;
2013-07-06 04:37:13 +00:00
2014-03-30 19:23:08 +00:00
sprintf ( second_buf [ num_buffer_lines + + ] , " %s " , buf ) ;
2013-10-07 04:01:00 +00:00
}
2014-03-22 18:24:57 +00:00
2013-10-07 04:01:00 +00:00
/* -------------------------------------------------------------------------
2014-03-30 19:23:08 +00:00
begin_cpu_stepping ( ) - step the CPU
2013-10-07 04:01:00 +00:00
set the CPU into stepping mode and yield to CPU thread
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2014-03-30 19:23:08 +00:00
static int begin_cpu_stepping ( ) {
int ch = - 1 ;
2013-10-07 04:01:00 +00:00
int err = 0 ;
2014-03-30 19:23:08 +00:00
// kludgey set max CPU speed...
double saved_scale = cpu_scale_factor ;
double saved_altscale = cpu_altscale_factor ;
2015-01-31 21:57:10 +00:00
bool saved_fullspeed = is_fullspeed ;
2014-03-30 19:23:08 +00:00
cpu_scale_factor = CPU_SCALE_FASTEST ;
cpu_altscale_factor = CPU_SCALE_FASTEST ;
2015-09-06 22:15:33 +00:00
timing_initialize ( ) ;
2014-03-30 19:23:08 +00:00
unsigned int idx = 0 ;
2014-06-21 21:33:23 +00:00
size_t textlen = 0 ;
2014-03-30 19:23:08 +00:00
if ( stepping_struct . step_text ) {
textlen = strlen ( stepping_struct . step_text ) ;
}
2014-03-22 18:24:57 +00:00
do {
2014-03-30 19:23:08 +00:00
if ( textlen & & ! ( ( apple_ii_64k [ 0 ] [ 0xC000 ] & 0x80 ) | | ( apple_ii_64k [ 1 ] [ 0xC000 ] & 0x80 ) ) ) {
uint8_t text_ch = ( uint8_t ) stepping_struct . step_text [ idx ] ;
if ( text_ch = = ' \n ' ) {
text_ch = ' \r ' ;
}
apple_ii_64k [ 0 ] [ 0xC000 ] = text_ch | 0x80 ;
apple_ii_64k [ 1 ] [ 0xC000 ] = text_ch | 0x80 ;
+ + idx ;
if ( idx > = textlen ) {
textlen = 0 ;
}
}
2014-03-30 18:17:12 +00:00
if ( ( err = pthread_cond_signal ( & cpu_thread_cond ) ) ) {
2014-03-22 18:24:57 +00:00
ERRLOG ( " pthread_cond_signal : %d " , err ) ;
}
2015-02-16 16:46:29 +00:00
if ( ( err = pthread_cond_wait ( & dbg_thread_cond , & interface_mutex ) ) ) {
2014-03-22 18:24:57 +00:00
ERRLOG ( " pthread_cond_wait : %d " , err ) ;
}
2013-10-07 04:01:00 +00:00
2015-02-16 02:32:45 +00:00
# if TESTING
# warning FIXME TODO : this is mis-named now ... GLVideo pushes sync state so we do not need to force poll ... but we need this to type the testing strings ... should refactor to leverage a common codepath, preferablly using the 'typing' mechanism here...
2014-04-26 20:22:19 +00:00
extern void testing_video_sync ( ) ;
testing_video_sync ( ) ;
2015-05-31 19:57:33 +00:00
# elif defined(INTERFACE_CLASSIC)
2014-03-30 19:23:08 +00:00
if ( ( ch = c_mygetch ( 0 ) ) ! = - 1 ) {
2014-03-22 18:24:57 +00:00
break ;
}
2014-03-30 19:23:08 +00:00
# endif
2014-03-30 20:58:34 +00:00
if ( ( stepping_struct . step_type ! = TYPING ) & & ( idx > textlen ) ) {
2014-03-30 19:23:08 +00:00
break ; // finished typing
}
if ( stepping_timeout & & ( stepping_struct . timeout < time ( NULL ) ) ) {
break ; // timeout
}
2014-03-22 18:24:57 +00:00
} while ( ! stepping_struct . should_break ) ;
2014-03-30 18:17:12 +00:00
if ( ( err = pthread_cond_signal ( & cpu_thread_cond ) ) ) {
2014-03-22 18:24:57 +00:00
ERRLOG ( " pthread_cond_signal : %d " , err ) ;
2013-10-07 04:01:00 +00:00
}
2014-03-22 18:24:57 +00:00
2014-03-30 19:23:08 +00:00
cpu_scale_factor = saved_scale ;
cpu_altscale_factor = saved_altscale ;
2015-09-06 22:15:33 +00:00
timing_initialize ( ) ;
2014-03-30 19:23:08 +00:00
return ch ;
2013-10-07 04:01:00 +00:00
}
/* -------------------------------------------------------------------------
2014-03-22 18:24:57 +00:00
c_debugger_should_break ( )
2013-10-07 04:01:00 +00:00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2014-03-22 18:24:57 +00:00
bool c_debugger_should_break ( ) {
2013-06-11 07:08:15 +00:00
2014-03-30 17:57:56 +00:00
if ( pthread_self ( ) ! = cpu_thread_id ) {
// OOPS ...
ERRLOG ( " should only call this from cpu thread, bailing... " ) ;
void * ptr = NULL ;
free ( ptr ) ;
}
2013-07-06 04:37:13 +00:00
2014-03-22 18:24:57 +00:00
if ( at_haltpt ( ) ) {
stepping_struct . should_break = true ;
} else {
uint8_t op = get_last_opcode ( ) ;
switch ( stepping_struct . step_type ) {
case STEPPING :
2013-07-06 04:37:13 +00:00
{
2014-03-22 18:24:57 +00:00
- - stepping_struct . step_count ;
if ( stepping_struct . step_count = = 0 ) {
stepping_struct . should_break = true ;
2013-07-06 04:37:13 +00:00
}
2014-03-22 18:24:57 +00:00
}
break ;
2013-07-06 04:37:13 +00:00
2014-03-22 18:24:57 +00:00
case NEXTING :
{
if ( stepping_struct . step_count > 0 ) {
- - stepping_struct . step_count ;
2013-07-06 04:37:13 +00:00
}
2014-03-22 18:24:57 +00:00
if ( op = = 0x20 ) {
+ + stepping_struct . step_frame ; // JSR
}
if ( op = = 0x60 ) {
- - stepping_struct . step_frame ; // RTS
}
if ( ( stepping_struct . step_frame = = 0 ) & & ( stepping_struct . step_count = = 0 ) ) {
stepping_struct . should_break = true ;
}
}
break ;
case UNTILING :
{
2014-06-22 18:16:38 +00:00
if ( stepping_struct . step_pc = = cpu65_pc ) {
2014-03-22 18:24:57 +00:00
stepping_struct . should_break = true ;
}
}
break ;
case FINISHING :
{
if ( op = = 0x20 ) {
+ + stepping_struct . step_frame ; // JSR
}
if ( op = = 0x60 ) {
- - stepping_struct . step_frame ; // RTS
}
if ( stepping_struct . step_frame = = 0 ) {
stepping_struct . should_break = true ;
}
}
break ;
case GOING :
2014-03-30 19:23:08 +00:00
case TYPING :
2014-03-30 20:58:34 +00:00
case LOADING :
2014-03-22 18:24:57 +00:00
break ;
2013-07-06 04:37:13 +00:00
}
2014-03-22 18:24:57 +00:00
}
2013-06-11 07:08:15 +00:00
2014-03-22 18:24:57 +00:00
return stepping_struct . should_break ;
}
/* -------------------------------------------------------------------------
2014-03-30 19:23:08 +00:00
debugger_go ( ) - step into or step over commands
2014-03-22 18:24:57 +00:00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2014-03-30 19:23:08 +00:00
int debugger_go ( stepping_struct_t s ) {
2014-03-22 18:24:57 +00:00
stepping_struct = s ;
2014-03-30 19:23:08 +00:00
int ch = begin_cpu_stepping ( ) ;
2015-02-16 02:32:45 +00:00
# if !TESTING
2014-03-30 20:58:34 +00:00
if ( stepping_struct . step_type ! = LOADING ) {
clear_debugger_screen ( ) ;
2014-06-22 18:16:38 +00:00
disasm ( cpu65_pc , 1 , 0 , - 1 ) ;
2014-03-30 19:23:08 +00:00
int branch = will_branch ( ) ;
if ( branch ! = BRANCH_NA ) {
sprintf ( second_buf [ num_buffer_lines + + ] , " %s " , ( branch ) ? " will branch " : " will not branch " ) ;
}
}
# endif
stepping_struct = ( stepping_struct_t ) { 0 } ;
return ch ;
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 ( ) {
2013-10-07 04:01:00 +00:00
/* "|||||||||||||||||||||||||||||||||||||" */
2013-06-11 07:08:15 +00:00
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> " ) ;
2014-06-14 17:37:14 +00:00
sprintf ( second_buf [ i + + ] , " bload <filename> </bank/addr> " ) ;
2013-06-11 07:08:15 +00:00
sprintf ( second_buf [ i + + ] , " fr{esh} " ) ;
sprintf ( second_buf [ i + + ] , " (h{elp} | ?) " ) ;
num_buffer_lines = i ;
}
2015-09-06 22:15:33 +00:00
__attribute__ ( ( constructor ( CTOR_PRIORITY_LATE ) ) )
static void _init_debugger ( void ) {
LOG ( " Initializing virtual machine debugger subsystem " ) ;
2014-03-30 17:53:57 +00:00
for ( unsigned int i = 0 ; i < MAX_BRKPTS ; i + + )
{
breakpoints [ i ] = - 1 ;
watchpoints [ i ] = - 1 ;
}
for ( unsigned int i = 0 ; i < 0x100 ; i + + )
{
op_breakpoints [ ( unsigned char ) i ] = 0 ;
}
}
2013-06-11 07:08:15 +00:00
2014-03-30 19:23:08 +00:00
# ifdef INTERFACE_CLASSIC
2013-06-11 07:08:15 +00:00
/* -------------------------------------------------------------------------
do_debug_command ( )
2013-07-06 04:37:13 +00:00
perform a debugger command
2013-06-11 07:08:15 +00:00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2014-03-30 19:23:08 +00:00
static void do_debug_command ( ) {
2013-06-11 07:08:15 +00:00
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 */
num_buffer_lines = 0 ;
/* call lex to perform the command.*/
strncpy ( lexbuf , command_line + PROMPT_X , BUF_X ) ;
init_lex ( lexbuf , BUF_X + 2 ) ;
2014-01-23 04:42:34 +00:00
yylex ( ) ;
2013-06-11 07:08:15 +00:00
/* 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 ;
}
2013-10-07 04:01:00 +00:00
memset ( command_buf [ i ] + j , ' ' , BUF_X - j /* - 1*/ ) ;
2013-07-06 04:37:13 +00:00
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 ;
}
/* -------------------------------------------------------------------------
2014-03-22 18:24:57 +00:00
c_interface_debugging ( )
2013-07-06 04:37:13 +00:00
main debugging console
2013-06-11 07:08:15 +00:00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2014-03-22 18:24:57 +00:00
void c_interface_debugging ( ) {
2013-06-11 07:08:15 +00:00
static char lex_initted = 0 ;
2014-03-22 18:24:57 +00:00
int err = 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 ] ) ;
}
2014-03-22 18:24:57 +00:00
is_debugging = true ;
2013-10-07 04:01:00 +00:00
for ( ; ; )
2013-07-06 04:37:13 +00:00
{
/* print command line */
c_interface_print ( 1 , 1 + PROMPT_Y , 0 , command_line ) ;
/* highlight cursor */
2013-10-07 04:01:00 +00:00
video_plotchar ( 1 + command_pos , 1 + PROMPT_Y , 1 , command_line [ command_pos ] ) ;
2013-07-06 04:37:13 +00:00
while ( ( ch = c_mygetch ( 1 ) ) = = - 1 )
{
}
if ( ch = = kESC )
{
2014-03-22 18:24:57 +00:00
break ;
2013-07-06 04:37:13 +00:00
}
else
{
/* backspace */
2013-10-07 04:01:00 +00:00
if ( ( ch = = 127 | | ch = = 8 ) & & ( command_pos > PROMPT_X ) )
2013-07-06 04:37:13 +00:00
{
command_line [ - - command_pos ] = ' ' ;
}
/* return */
2013-10-07 04:01:00 +00:00
else if ( ch = = 13 )
2013-07-06 04:37:13 +00:00
{
command_line [ command_pos ] = ' \0 ' ;
do_debug_command ( ) ;
command_pos = PROMPT_X ;
}
/* normal character */
2013-10-07 04:01:00 +00:00
else if ( ( ch > = ' ' ) & & ( ch < 127 ) & & ( command_pos < PROMPT_END_X ) )
2013-07-06 04:37:13 +00:00
{
command_line [ command_pos + + ] = ch ;
}
}
2013-06-11 07:08:15 +00:00
}
2014-03-22 18:24:57 +00:00
c_interface_exit ( - 1 ) ;
is_debugging = false ;
2014-03-30 18:17:12 +00:00
if ( ( err = pthread_cond_signal ( & cpu_thread_cond ) ) )
2014-03-22 18:24:57 +00:00
{
ERRLOG ( " pthread_cond_signal : %d " , err ) ;
}
return ;
2013-06-11 07:08:15 +00:00
}
2014-03-23 21:25:28 +00:00
# endif
2013-06-11 07:08:15 +00:00
2014-03-30 19:23:08 +00:00
/* -------------------------------------------------------------------------
debugger testing - driven API
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void c_debugger_go ( ) {
stepping_struct_t s = ( stepping_struct_t ) {
. step_type = GOING ,
. timeout = time ( NULL ) + stepping_timeout
} ;
num_buffer_lines = 0 ;
is_debugging = true ;
debugger_go ( s ) ;
is_debugging = false ;
num_buffer_lines = 0 ;
}
void c_debugger_set_timeout ( const unsigned int secs ) {
stepping_timeout = secs ;
}
2014-03-30 19:35:09 +00:00
bool c_debugger_set_watchpoint ( const uint16_t addr ) {
return set_halt ( watchpoints , addr ) ;
}