home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ST-Computer Leser 2002 January
/
STC_CD_01_2002.iso
/
JAGUAR
/
JAG_SRC
/
SOURCE
/
DEBUGUI.C
< prev
next >
Wrap
C/C++ Source or Header
|
2001-08-18
|
26KB
|
936 lines
////////////////////////////////////////////////////////////////////////////////
// Jagulator: Atari Jaguar Console Emulation Project (debugui.c)
// -----------------------------------------------------------------------------
// Jagulator is the Copyright (c) RealityMan 1998-2001 and is provided "as is"
// without any expressed or implied warranty. I have no Trademarks, Legal or
// otherwise. Atari, Jaguar and the Atari Logo are copyright Hasbro Inc. All
// other Copyrights and Trademarks are acknowledged. This project is in no way
// linked to Atari/Hasbro or other associated Atari companies.
//
// 07-07-2001 GH: New Source, Rewritten for Release 1.5.0
// 00-00-0000 GH: All Previous Source Considered as Development Code Only
#include "core.h"
////////////////////////////////////////////////////////////////////////////////
// Globals
Con console; // Console Line Data
View view; // Console View Information
char statusline[128]; // Console Status Line
Win w_regs; // Register View
Win w_dm68; // 68000 Disassembly
Win w_dgpu; // GPU Disassembly
Win w_ddsp; // DSP Disassembly
Win w_data; // Data Disassembly
Win w_cons; // Console Window Information
int c_barfg = 0x0; // Bar Foreground Attribute
int c_barbg = 0x3; // Bar Background Attribute
int viewopen = 0; // View Open Flag
int exitflag = 0; // Exit Flag
struct // Console Information
{
HANDLE hconsole; // Console Handle
HANDLE hconsoleinput; // Console Input Handle
int sx, sy; // Console Size
int basey;
int cx, cy; // Cursor Position
int attr; // Current Attribute
int cix, ciy; // Output Buffer
int cicount;
CHAR_INFO ci[MAXSTRING];
} con;
static char editline[256]; // Console Keyboard Handling
static int editpos;
static char lastcmd[256];
static char breakcmd[256];
static char tmpcmd[256];
static char history[HISTORY][256];
static int historypos;
static int scrolling;
////////////////////////////////////////////////////////////////////////////////
// Exception Messages
void exception( char *txt, ... )
{
#ifdef DEBUG
static char buf[256]; // String Buffer
va_list argp; // Argument Pointer
va_start( argp, txt ); // Start of Arguments
sprintf( buf, YEL"Exception: " );
vsprintf( buf + strlen(buf), txt, argp );
strcat( buf, "\n" );
print( buf );
#endif
}
////////////////////////////////////////////////////////////////////////////////
// Error Messages
void error( char *txt, ... )
{
#ifdef DEBUG
static char buf[256]; // String Pointer
va_list argp; // Argument Pointer
va_start( argp, txt ); // Start of Arguments
sprintf( buf, YEL"Error: " );
vsprintf( buf + strlen(buf), txt, argp );
strcat( buf, "\n" );
print( buf );
#endif
}
////////////////////////////////////////////////////////////////////////////////
// Warning Messages
void warning( char *txt, ... )
{
#ifdef DEBUG
static char buf[256]; // String Pointer
va_list argp; // Argument Pointer
va_start( argp, txt ); // Start of Arguments
sprintf( buf, YEL"Warning: " );
vsprintf( buf + strlen(buf), txt, argp );
strcat( buf, "\n" );
printf( buf );
#endif
}
////////////////////////////////////////////////////////////////////////////////
// Read Input Event
int readevent( int dopeek )
{
INPUT_RECORD inp;
DWORD num;
int ascii, vkey, down, res;
if( !con.hconsole ) return( 0 );
if( dopeek )
{
PeekConsoleInput( con.hconsoleinput, &inp, 1, &num );
if( !num ) return( 0 );
}
ReadConsoleInput( con.hconsoleinput, &inp, 1, &num );
if( inp.EventType == KEY_EVENT )
{
ascii = inp.Event.KeyEvent.uChar.AsciiChar;
vkey = inp.Event.KeyEvent.wVirtualKeyCode;
down = inp.Event.KeyEvent.bKeyDown;
res = 0;
if( vkey >= 'A' && vkey <= 'Z' && (ascii < 'A' || ascii > 'z') )
{
res = vkey;
}
else if( vkey >= VK_F1 && vkey <= VK_F12 )
{
res = (KEY_F1 + vkey - VK_F1);
}
else switch( vkey )
{
case VK_DELETE: res = (KEY_DEL); break;
case VK_UP: res = (KEY_UP); break;
case VK_DOWN: res = (KEY_DOWN); break;
case VK_LEFT: res = (KEY_LEFT); break;
case VK_RIGHT: res = (KEY_RIGHT); break;
case VK_PRIOR: res = (KEY_PGUP); break;
case VK_NEXT: res = (KEY_PGDN); break;
case VK_HOME: res = (KEY_HOME); break;
case VK_END: res = (KEY_END); break;
default: res = (ascii); break;
}
if( !down ) res |= KEY_RELEASE;
return( res );
}
return( 0 );
}
////////////////////////////////////////////////////////////////////////////////
// Console Read Keystroke
int con_readkey_noblock( void )
{
if( !con.hconsole ) return( 0 );
return( readevent( 1 ) );
}
////////////////////////////////////////////////////////////////////////////////
// Console Sleep
void con_sleep( int ms )
{
Sleep( ms );
}
////////////////////////////////////////////////////////////////////////////////
// Console Print Character
void con_printchar( int ch )
{
if( !con.hconsole ) return;
if( con.cx != con.cix + con.cicount || con.cy != con.ciy || ch == -1 )
{
if( con.cicount )
{
COORD cisize, cibase;
SMALL_RECT region;
cisize.X = con.cicount;
cisize.Y = 1;
cibase.X = 0;
cibase.Y = 0;
region.Left = con.cix;
region.Top = con.ciy + con.basey;
region.Right = con.cix + con.cicount - 1;
region.Bottom = con.ciy + con.basey;
WriteConsoleOutput( con.hconsole, con.ci, cisize, cibase, ®ion );
}
con.cicount = 0;
con.cix = con.cx;
con.ciy = con.cy;
if( ch == -1 ) return;
}
con.ci[con.cicount].Char.AsciiChar = ch;
con.ci[con.cicount].Attributes = con.attr;
con.cicount++;
con.cx++;
}
////////////////////////////////////////////////////////////////////////////////
// Console Print
void con_print( char *text )
{
static CHAR_INFO ci[MAXSTRING];
int i = 0;
if( !con.hconsole ) return;
while( *text )
{
if( *text == 0x01 )
{ // Foreground Set
con.attr &= 0xfff0;
con.attr |= text[1] & 15;
text += 2;
}
else if( *text == 0x02 )
{ // Background Set
con.attr &= 0xff0f;
con.attr |= (text[1] & 15) << 4;
text += 2;
}
else if( *text == '\n' )
{
con_gotoxy( 0, con.cy + 1 );
text++;
}
else
{
con_printchar( *text++ );
}
}
}
////////////////////////////////////////////////////////////////////////////////
// Console Tab
void con_tabto( int ch, int x )
{
if( !con.hconsole ) return;
while( con.cx < con.sx && con.cx < x )
{
con_printchar( ch );
}
}
////////////////////////////////////////////////////////////////////////////////
// Console Formatted Output
void con_printf( char *txt, ... )
{
static char buf[MAXSTRING];
va_list argp;
va_start( argp, txt );
vsprintf( buf, txt, argp );
con_print( buf );
}
////////////////////////////////////////////////////////////////////////////////
// Set Console X, Y
void con_cursorxy( int x, int y, int size )
{
COORD c;
CONSOLE_CURSOR_INFO ci;
if( !con.hconsole ) return;
c.X = x;
c.Y = y + con.basey;
if( size < 1 || size > 100 )
{
ci.bVisible = FALSE;
ci.dwSize = 50;
}
else
{
ci.bVisible = TRUE;
ci.dwSize = size;
}
SetConsoleCursorInfo( con.hconsole, &ci );
SetConsoleCursorPosition( con.hconsole, c );
}
////////////////////////////////////////////////////////////////////////////////
// Set Fore and Background Console Attribute
void con_attr2( int fg, int bg )
{
con.attr = (bg << 4) | fg;
}
////////////////////////////////////////////////////////////////////////////////
// Return Console Rows
int con_rows( void )
{
return( con.sy );
}
////////////////////////////////////////////////////////////////////////////////
// Goto Console X,Y Coordinate
void con_gotoxy( int x, int y )
{
if( !con.hconsole ) return;
con_printchar( -1 );
con.cx = x;
con.cy = y;
}
////////////////////////////////////////////////////////////////////////////////
// Deinitialise Console
void con_deinit( void )
{
FreeConsole();
}
////////////////////////////////////////////////////////////////////////////////
// Clear Console Display
void con_clear( void )
{
COORD zero;
int x;
zero.X = 0;
zero.Y = 0;
FillConsoleOutputCharacter( con.hconsole, ' ', 65535, zero, &x );
FillConsoleOutputAttribute( con.hconsole, 0x7, 65535, zero, &x );
con.cx = con.cy = 0;
}
////////////////////////////////////////////////////////////////////////////////
// Resize Console
void ResizeConsole( HANDLE hConsole, SHORT xSize, SHORT ySize )
{
CONSOLE_SCREEN_BUFFER_INFO csbi; // Hold Current Console Buffer Info
BOOL bSuccess;
SMALL_RECT srWindowRect; // Hold the New Console Size
COORD coordScreen;
bSuccess = GetConsoleScreenBufferInfo( hConsole, &csbi );
// Get the Largest Size we can size the Console Window to
coordScreen = GetLargestConsoleWindowSize( hConsole );
// Define the New Console Window Size and Scroll Position
srWindowRect.Right = (SHORT)(min(xSize, coordScreen.X) - 1);
srWindowRect.Bottom = (SHORT)(min(ySize, coordScreen.Y) - 1);
srWindowRect.Left = srWindowRect.Top = (SHORT)0;
// Define the New Console Buffer Size
coordScreen.X = xSize;
coordScreen.Y = ySize;
// If the Current Buffer is Larger than what we want, Resize the
// Console Window First, then the Buffer
if( (DWORD)csbi.dwSize.X * csbi.dwSize.Y > (DWORD) xSize * ySize)
{
bSuccess = SetConsoleWindowInfo( hConsole, TRUE, &srWindowRect );
bSuccess = SetConsoleScreenBufferSize( hConsole, coordScreen );
}
// If the Current Buffer is Smaller than what we want, Resize the
// Buffer First, then the Console Window
if( (DWORD)csbi.dwSize.X * csbi.dwSize.Y < (DWORD) xSize * ySize )
{
bSuccess = SetConsoleScreenBufferSize( hConsole, coordScreen );
bSuccess = SetConsoleWindowInfo( hConsole, TRUE, &srWindowRect );
}
// If the Current Buffer *is* the Size we want, Don't do anything!
return;
}
////////////////////////////////////////////////////////////////////////////////
// Check if Console has been Resized
int con_resized( void )
{
int resized = 0, x, y;
CONSOLE_SCREEN_BUFFER_INFO info;
GetConsoleScreenBufferInfo( con.hconsole, &info );
x = info.srWindow.Right - info.srWindow.Left + 1;
y = info.srWindow.Bottom - info.srWindow.Top + 1;
con.basey = info.srWindow.Top;
if( x != con.sx )
{
resized = 1;
con.sx = x;
}
if( y != con.sy )
{
resized = 1;
con.sy = y;
}
return( resized );
}
////////////////////////////////////////////////////////////////////////////////
// Open New Console
void con_opennew( void )
{
FreeConsole();
AllocConsole();
#ifdef RELEASE
ResizeConsole( GetStdHandle(STD_OUTPUT_HANDLE), 80, 16 );
#else
ResizeConsole( GetStdHandle(STD_OUTPUT_HANDLE), 80, 60 );
#endif
}
////////////////////////////////////////////////////////////////////////////////
// Initialise Console
void con_init( void )
{
memset( &con, 0, sizeof(con) ); // Initialise Console Information
con_opennew(); // Open New Console
con.hconsole = GetStdHandle(STD_OUTPUT_HANDLE);
con.hconsoleinput = GetStdHandle(STD_INPUT_HANDLE);
con_resized();
con.sy--; // Force Another Resize
con.attr = 0x0F;
}
void con_initdummy( void )
{
memset( &con, 0, sizeof(con) );
con.sx = 80;
con.sy = 50;
}
////////////////////////////////////////////////////////////////////////////////
// Set Exit Flag
void exitnow( void )
{
exitflag = 1;
}
////////////////////////////////////////////////////////////////////////////////
// Execute a Command
void docommand( char *editline )
{
int i;
if( !*editline ) return;
if( *editline == '+' ) strcpy( editline, lastcmd );
else strcpy( lastcmd, editline );
// Put to History (Unless Same as Last)
if( strcmp( editline, history[0] ) )
{
for( i = HISTORY - 1; i > 0; i-- )
{
strcpy( history[i], history[i-1] );
}
strcpy( history[0], editline );
}
historypos = -1;
command( editline );
conkey( 0 );
view_changed( VIEW_ALL );
}
////////////////////////////////////////////////////////////////////////////////
// View Status Line
void view_status( char *text )
{
#ifdef DEBUG
int len = strlen(text);
if( len > 78 ) len = 78;
memset( statusline, ' ', 80 );
statusline[80] = 0;
memcpy( statusline + 1, text, len );
con_gotoxy( 0, con_rows() - 1 );
con_attr2( 0, 3 );
con_print( statusline );
#endif
}
////////////////////////////////////////////////////////////////////////////////
// View Console Window
void view_cons( void )
{
#ifdef DEBUG
int c_cur = 0x03;
int c_txt = 0x02;
int c_bg = 0x00;
int y, i;
y = w_cons.y;
con_gotoxy( 0, y++ );
con_attr2( c_barfg, c_barbg );
con_tabto( '─', 2 );
con_printf(" Debug Console ");
con_tabto( '─', 256 );
i = view.consolerow + w_cons.sy - 2;
while( y < w_cons.y + w_cons.sy )
{
if( !i ) con_cursorxy( view.consolecursor, y, 25 );
con_gotoxy( 0, y++ );
con_attr2( c_txt, c_bg );
con_print( console.line[i--] );
con_tabto( ' ', 256 );
}
if( view.consolerow > 0 ) con_cursorxy( 0, 0, 0 );
#endif
}
////////////////////////////////////////////////////////////////////////////////
// Check Console View Size
void view_checksize( void )
{
int h, y;
h = con_rows();
w_cons.sy = h - 1;
view.consrows = w_cons.sy-1;
y = 0;
w_cons.y = y;
y += w_cons.sy;
}
////////////////////////////////////////////////////////////////////////////////
// Redraw Console View
void view_redraw( void )
{
if( !view.changed )
return;
if( con_resized() || (view.changed & VIEW_RESIZE) )
view_checksize();
if( view.changed & VIEW_CLEAR )
con_clear();
if( view.changed & VIEW_CONS )
view_cons();
con_gotoxy( 0, con_rows() - 1 );
con_attr2( 0, 3 );
con_print( statusline );
con_gotoxy( 0, 0 ); // Will Flush Output Buffers
view.changed = 0;
}
////////////////////////////////////////////////////////////////////////////////
// Write to Console
void view_writeconsole( char *text )
{
if( !viewopen ) return;
while( *text )
{
if( *text == 0x1 || *text == 0x2 )
{
console.line[0][console.writepos++] = *text++;
console.line[0][console.writepos++] = *text;
}
else if( *text == '\r' )
{
console.line[0][console.writepos] = 0;
console.writepos = 0;
}
else if( *text == '\n' )
{
char *p;
console.line[0][console.writepos] = 0;
console.writepos = 0;
// Scroll
p = console.line[LINES-1];
memmove(console.line+1,console.line+0,sizeof(char *)*(LINES-1));
console.line[0] = p;
memset( console.line[0], 0, LINELEN );
}
else if( console.writepos < LINELEN - 1 )
{
console.line[0][console.writepos++] = *text;
}
text++;
if( console.writepos > 80 ) console.writepos = 80;
}
}
////////////////////////////////////////////////////////////////////////////////
// Update Log
void printtxt( char *txt )
{
static FILE *logfile; // File Pointer
char *p; // Character Pointer
static int printedstuff = 0; // Printed Flag
static int flushcnt = 0; // Flush Counter
if( !logfile ) // Open Log if Not Already Opened
logfile = fopen( "jagulator.log", "wt" );
if( !txt ) // Return if No Output
{
if( flushcnt )
{
flushcnt = 0; // Zero Flush Count
fflush( logfile );
}
return;
}
flushcnt++; // Increment Flush Count
view_writeconsole( txt );
if( flushcnt > 1000 ) // Redraw Screen Every 1000 Messages
flushdisplay();
p = txt; // Set Pointer
while( *p ) // While Valid Text Strip Codes
{
if( *p == 0x01 ) p += 2;
else if( *p == 0x02 ) p += 2;
else break;
}
fputs( p, logfile ); // Write to Logfile
}
////////////////////////////////////////////////////////////////////////////////
// Flush Log
void flushlog( void )
{
printtxt( NULL );
}
////////////////////////////////////////////////////////////////////////////////
// Flush Console Display
void flushdisplay( void )
{
flushlog();
view_changed( VIEW_ALL );
view_redraw();
}
////////////////////////////////////////////////////////////////////////////////
// Set View Changed Flag
void view_changed( int which )
{
view.changed |= which;
}
////////////////////////////////////////////////////////////////////////////////
// Open Debug Console View
void view_open( void )
{
int i; // Iterator
static char buf[256]; // Temp Buffer
view.changed = -1; // Initialise View Changed Flag
view.active = 0; // Initialise View Active Flag
con_initdummy();
/*
con_init();
wsprintf( buf, "%s - %s v%i.%i.%i (%s)",
APPNAME, TITLE, MAJORREV, MINORREV, PATCHLVL, PLATFORM );
SetConsoleTitle( buf );
*/
memset( &console, 0, sizeof(console) );
for( i = 0; i < LINES; i++ )
{
console.line[i] = console.linedata[i];
}
viewopen = 1; // Set View Open Flag
}
////////////////////////////////////////////////////////////////////////////////
// Close Debug Console View
void view_close( void )
{
viewopen = 0; // Unset View Open Flag
con_clear();
con_deinit();
}
////////////////////////////////////////////////////////////////////////////////
// Generic Print
void print( char *txt, ... )
{
static char buf[256]; // String Buffer
va_list argp; // Argument Pointer
va_start( argp, txt ); // Start of Arguments
if( !txt ) // Return if No Output
{
printtxt( NULL );
return;
}
vsprintf( buf, txt, argp ); // Format Text
printtxt( buf ); // Write Text
}
////////////////////////////////////////////////////////////////////////////////
// Debug User Interface Key Handling
void debugui_key( int a )
{
int flag = 1;
if( a >= KEY_F1 && a <= KEY_F12 ) command_fkey( a );
else
{
flag = 0;
if( a >= 32 && a < 256 && view.active != WIN_CONS )
{
view.active = WIN_CONS;
flag = 1;
}
if( view.active == WIN_CONS ) conkey( a );
}
if( flag ) view_changed( VIEW_ALL );
}
////////////////////////////////////////////////////////////////////////////////
// Console Key Handling
void conkey( int a )
{
int editlen = strlen(editline);
int resetrow = 1, x;
switch( a )
{
case KEY_PGUP:
resetrow = 0;
view.consolerow += view.consrows - 1;
scrolling = 1;
break;
case KEY_PGDN:
resetrow = 0;
if( view.consolerow == 0 ) scrolling = 0;
else scrolling = 1;
view.consolerow -= view.consrows - 1;
break;
case KEY_UP:
if( scrolling )
{
resetrow = 0;
view.consolerow += 1;
}
else
{
x = historypos + 1;
if( x < HISTORY && *history[x] )
{
historypos = x;
strcpy( editline, history[historypos] );
editpos=strlen( editline );
}
}
break;
case KEY_DOWN:
if( scrolling )
{
resetrow = 0;
view.consolerow -= 1;
}
else
{
x = historypos - 1;
if( x > 0 && *history[x] )
{
historypos = x;
strcpy( editline, history[historypos] );
editpos = strlen(editline);
}
}
break;
case KEY_LEFT:
editpos--;
if( editpos < 0 ) editpos = 0;
break;
case KEY_RIGHT:
editpos++;
if( editpos > editlen ) editpos = editlen;
break;
case KEY_HOME:
editpos = 0;
break;
case KEY_END:
editpos = editlen;
break;
case KEY_BKSPACE:
if( editpos == 0 ) break;
editpos--;
case KEY_DEL:
if( editline[editpos] )
memmove(editline+editpos,editline+editpos+1,256-1-editpos);
break;
case KEY_ENTER:
view_writeconsole( "\x01\x17" );
#ifndef RELEASE
print( ": %s\n", editline );
#endif
// Execute
docommand( editline );
// Flow On
case KEY_ESC:
// Clear
scrolling = 0;
*editline = 0;
editpos = 0;
break;
default:
if( a >= 32 && a < 256 )
{
memmove(editline+editpos+1,editline+editpos,256-1-editpos);
editline[editpos++] = a;
}
else resetrow = 0;
break;
}
if( scrolling ) view_status( "Scrolling (Esc to Stop)" );
else view_status( "Ready... (PgUp to Scroll Console)" );
if( editpos > 77 ) editpos = 77;
if( resetrow ) view.consolerow = 0;
if( view.consolerow < 0 ) view.consolerow = 0;
else if( view.consolerow > 1024 - 50 ) view.consolerow = 1024 - 50;
#ifndef RELEASE
view.consolecursor = editpos + 2;
view_writeconsole( "\x01\x17: " );
view_writeconsole( editline );
view_writeconsole( "\r" );
#endif
view_changed( VIEW_CONS );
}
////////////////////////////////////////////////////////////////////////////////
// Main Debug User Interface Loop
void debugui( void )
{
int key;
conkey( 0 );
while( !exitflag )
{
view_redraw();
if( *breakcmd )
{
print( NORMAL":: %s\n", breakcmd );
strcpy( tmpcmd, breakcmd );
*breakcmd = 0;
command( tmpcmd );
flushdisplay();
}
else
{
key = con_readkey_noblock();
if( key )
{
debugui_key( key );
}
else
{
con_sleep( 10 );
}
}
con_sleep( 0 );
}
}