mirror of https://github.com/stella-emu/stella.git
Major surgery on the breakpoint support. It all seems to work correctly
now: set/clear a breakpoint, clear all breakpoints, list breakpoints (including labels in the output!). The 6502 no longer gets "stuck" on a breakpoint if you quit the debugger while the current PC is a breakpoint. Some work on the prompt console. The CPU state information shouldn't be stale any more. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@516 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
f1617b1db8
commit
379aa0c3ed
|
@ -13,7 +13,7 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: Debugger.cxx,v 1.12 2005-06-16 16:26:27 stephena Exp $
|
||||
// $Id: Debugger.cxx,v 1.13 2005-06-17 03:49:08 urchlay Exp $
|
||||
//============================================================================
|
||||
|
||||
#include "bspf.hxx"
|
||||
|
@ -44,7 +44,7 @@ Debugger::Debugger(OSystem* osystem)
|
|||
// Init parser
|
||||
myParser = new DebuggerParser(this);
|
||||
equateList = new EquateList();
|
||||
breakPoints = new PackedBitArray(0xffff);
|
||||
breakPoints = new PackedBitArray(0x10000);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -65,7 +65,9 @@ void Debugger::initialize()
|
|||
h = kDebuggerHeight - y;
|
||||
|
||||
delete myBaseDialog;
|
||||
myBaseDialog = new DebuggerDialog(myOSystem, this, x, y, w, h);
|
||||
DebuggerDialog *dd = new DebuggerDialog(myOSystem, this, x, y, w, h);
|
||||
myPrompt = dd->prompt();
|
||||
myBaseDialog = dd;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -101,6 +103,7 @@ const string Debugger::state()
|
|||
string result;
|
||||
char buf[255], bbuf[255];
|
||||
|
||||
//cerr << "state(): pc is " << myDebugger->pc() << endl;
|
||||
result += "\nPC=";
|
||||
result += to_hex_16(myDebugger->pc());
|
||||
result += " A=";
|
||||
|
@ -120,6 +123,11 @@ const string Debugger::state()
|
|||
sprintf(buf, "%d", mySystem->cycles());
|
||||
result += buf;
|
||||
result += "\n ";
|
||||
char *label = equateList->getLabel(myDebugger->pc());
|
||||
if(label != NULL) {
|
||||
result += label;
|
||||
result += ": ";
|
||||
}
|
||||
int count = myDebugger->disassemble(myDebugger->pc(), buf, equateList);
|
||||
for(int i=0; i<count; i++) {
|
||||
sprintf(bbuf, "%02x ", readRAM(myDebugger->pc() + i));
|
||||
|
@ -257,17 +265,28 @@ const string Debugger::dumpTIA()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Debugger::start()
|
||||
bool Debugger::start()
|
||||
{
|
||||
if(myOSystem->eventHandler().state() != EventHandler::S_DEBUGGER)
|
||||
if(myOSystem->eventHandler().state() != EventHandler::S_DEBUGGER) {
|
||||
myOSystem->eventHandler().enterDebugMode();
|
||||
myPrompt->printPrompt();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Debugger::quit()
|
||||
{
|
||||
if(myOSystem->eventHandler().state() == EventHandler::S_DEBUGGER)
|
||||
if(myOSystem->eventHandler().state() == EventHandler::S_DEBUGGER) {
|
||||
// execute one instruction on quit, IF we're
|
||||
// sitting at a breakpoint. This will get us past it.
|
||||
// Somehow this feels like a hack to me, but I don't know why
|
||||
if(breakPoints->isSet(myDebugger->pc()))
|
||||
mySystem->m6502().execute(1);
|
||||
myOSystem->eventHandler().leaveDebugMode();
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -360,10 +379,13 @@ EquateList *Debugger::equates() {
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Debugger::toggleBreakPoint(int bp) {
|
||||
mySystem->m6502().setBreakPoints(breakPoints);
|
||||
if(bp < 0) bp = myDebugger->pc();
|
||||
breakPoints->toggle(bp);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool Debugger::breakPoint(int bp) {
|
||||
if(bp < 0) bp = myDebugger->pc();
|
||||
return breakPoints->isSet(bp) != 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: Debugger.hxx,v 1.8 2005-06-16 12:28:53 stephena Exp $
|
||||
// $Id: Debugger.hxx,v 1.9 2005-06-17 03:49:08 urchlay Exp $
|
||||
//============================================================================
|
||||
|
||||
#ifndef DEBUGGER_HXX
|
||||
|
@ -30,6 +30,7 @@ class D6502;
|
|||
#include "M6502.hxx"
|
||||
#include "EquateList.hxx"
|
||||
#include "PackedBitArray.hxx"
|
||||
#include "PromptWidget.hxx"
|
||||
#include "bspf.hxx"
|
||||
|
||||
enum {
|
||||
|
@ -48,7 +49,7 @@ enum {
|
|||
for all debugging operations in Stella (parser, 6502 debugger, etc).
|
||||
|
||||
@author Stephen Anthony
|
||||
@version $Id: Debugger.hxx,v 1.8 2005-06-16 12:28:53 stephena Exp $
|
||||
@version $Id: Debugger.hxx,v 1.9 2005-06-17 03:49:08 urchlay Exp $
|
||||
*/
|
||||
class Debugger : public DialogContainer
|
||||
{
|
||||
|
@ -124,7 +125,7 @@ class Debugger : public DialogContainer
|
|||
// set a bunch of RAM locations at once
|
||||
const string setRAM(int argCount, int *args);
|
||||
|
||||
void start();
|
||||
bool start();
|
||||
void quit();
|
||||
void trace();
|
||||
void step();
|
||||
|
@ -142,6 +143,7 @@ class Debugger : public DialogContainer
|
|||
|
||||
void formatFlags(int f, char *out);
|
||||
EquateList *equates();
|
||||
PromptWidget *prompt();
|
||||
|
||||
protected:
|
||||
Console* myConsole;
|
||||
|
@ -151,6 +153,7 @@ class Debugger : public DialogContainer
|
|||
D6502* myDebugger;
|
||||
EquateList *equateList;
|
||||
PackedBitArray *breakPoints;
|
||||
PromptWidget *myPrompt;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: DebuggerParser.cxx,v 1.8 2005-06-16 16:18:57 urchlay Exp $
|
||||
// $Id: DebuggerParser.cxx,v 1.9 2005-06-17 03:49:08 urchlay Exp $
|
||||
//============================================================================
|
||||
|
||||
#include "bspf.hxx"
|
||||
|
@ -170,6 +170,24 @@ bool DebuggerParser::subStringMatch(const string& needle, const string& haystack
|
|||
return false;
|
||||
}
|
||||
|
||||
string DebuggerParser::listBreaks() {
|
||||
char buf[255];
|
||||
int count = 0;
|
||||
string ret;
|
||||
|
||||
for(unsigned int i=0; i<0x10000; i++) {
|
||||
if(debugger->breakPoints->isSet(i)) {
|
||||
sprintf(buf, "%s ", debugger->equateList->getFormatted(i, 4));
|
||||
ret += buf;
|
||||
if(! (++count % 8) ) ret += "\n";
|
||||
}
|
||||
}
|
||||
if(count)
|
||||
return ret;
|
||||
else
|
||||
return "no breakpoints set";
|
||||
}
|
||||
|
||||
string DebuggerParser::run(const string& command) {
|
||||
string result;
|
||||
|
||||
|
@ -194,7 +212,7 @@ string DebuggerParser::run(const string& command) {
|
|||
|
||||
// TODO: de-uglify this somehow. (it may not be worth doing?)
|
||||
|
||||
if(subStringMatch(verb, "quit")) {
|
||||
if(subStringMatch(verb, "quit") || subStringMatch(verb, "run")) {
|
||||
debugger->quit();
|
||||
return "";
|
||||
} else if(subStringMatch(verb, "a")) {
|
||||
|
@ -266,44 +284,57 @@ string DebuggerParser::run(const string& command) {
|
|||
} else if(subStringMatch(verb, "reset")) {
|
||||
debugger->reset();
|
||||
} else if(subStringMatch(verb, "break")) {
|
||||
if(argCount == 1) {
|
||||
debugger->toggleBreakPoint(args[0]);
|
||||
if(debugger->breakPoint(args[0]))
|
||||
return "Set breakpoint";
|
||||
else
|
||||
return "Cleared breakpoint";
|
||||
} else {
|
||||
return "one argument required";
|
||||
int bp = -1;
|
||||
|
||||
if(argCount > 1) {
|
||||
return "zero or one arguments required";
|
||||
} else if(argCount == 0) {
|
||||
bp = -1;
|
||||
} else if(argCount == 1) {
|
||||
bp = args[0];
|
||||
}
|
||||
|
||||
debugger->toggleBreakPoint(bp);
|
||||
|
||||
if(debugger->breakPoint(bp))
|
||||
return "Set breakpoint";
|
||||
else
|
||||
return "Cleared breakpoint";
|
||||
} else if(subStringMatch(verb, "listbreaks")) {
|
||||
return listBreaks();
|
||||
} else if(subStringMatch(verb, "clearbreaks")) {
|
||||
//debugger->clearAllBreakPoints();
|
||||
return "cleared all breakpoints";
|
||||
} else if(subStringMatch(verb, "help") || verb == "?") {
|
||||
// please leave each option on its own line so they're
|
||||
// easy to sort - bkw
|
||||
return
|
||||
"a xx - Set Accumulator to xx\n"
|
||||
// "break - Show all breakpoints\n"
|
||||
"break xx - Set/clear breakpoint at address xx\n"
|
||||
"c - Toggle Carry Flag\n"
|
||||
"d - Toggle Decimal Flag\n"
|
||||
"loadsym f - Load DASM symbols from file f\n"
|
||||
"n - Toggle Negative Flag\n"
|
||||
"pc xx - Set Program Counter to xx\n"
|
||||
"ram - Show RIOT RAM contents\n"
|
||||
"ram xx yy - Set RAM location xx to value yy (multiple values may be given)\n"
|
||||
"reset - Jump to 6502 init vector (does not reset TIA/RIOT)\n"
|
||||
"s xx - Set Stack Pointer to xx\n"
|
||||
"step - Single-step\n"
|
||||
"tia - Show TIA register contents\n"
|
||||
"trace - Single-step treating subroutine calls as one instruction\n"
|
||||
"v - Toggle Overflow Flag\n"
|
||||
"x xx - Set X register to xx\n"
|
||||
"y xx - Set Y register to xx\n"
|
||||
"z - Toggle Zero Flag\n"
|
||||
"a xx - Set Accumulator to xx\n"
|
||||
"break - Set/clear breakpoint at current PC\n"
|
||||
"break xx - Set/clear breakpoint at address xx\n"
|
||||
"c - Toggle Carry Flag\n"
|
||||
"clearbreaks - Clear all breakpoints\n"
|
||||
"d - Toggle Decimal Flag\n"
|
||||
"listbreaks - List all breakpoints\n"
|
||||
"loadsym f - Load DASM symbols from file f\n"
|
||||
"n - Toggle Negative Flag\n"
|
||||
"pc xx - Set Program Counter to xx\n"
|
||||
"ram - Show RIOT RAM contents\n"
|
||||
"ram xx yy - Set RAM location xx to value yy (multiple values may be given)\n"
|
||||
"reset - Jump to 6502 init vector (does not reset TIA/RIOT)\n"
|
||||
"run - Exit debugger (back to emulator)\n"
|
||||
"s xx - Set Stack Pointer to xx\n"
|
||||
"step - Single-step\n"
|
||||
"tia - Show TIA register contents\n"
|
||||
"trace - Single-step treating subroutine calls as one instruction\n"
|
||||
"v - Toggle Overflow Flag\n"
|
||||
"x xx - Set X register to xx\n"
|
||||
"y xx - Set Y register to xx\n"
|
||||
"z - Toggle Zero Flag\n"
|
||||
;
|
||||
} else {
|
||||
return "unimplemented command (try \"help\")";
|
||||
}
|
||||
|
||||
// result += debugger->state();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: DebuggerParser.hxx,v 1.4 2005-06-14 03:11:03 urchlay Exp $
|
||||
// $Id: DebuggerParser.hxx,v 1.5 2005-06-17 03:49:08 urchlay Exp $
|
||||
//============================================================================
|
||||
|
||||
#ifndef DEBUGGER_PARSER_HXX
|
||||
|
@ -34,6 +34,7 @@ class DebuggerParser
|
|||
void setDone();
|
||||
string run(const string& command);
|
||||
bool getArgs(const string& command);
|
||||
string listBreaks();
|
||||
|
||||
private:
|
||||
int DebuggerParser::conv_hex_digit(char d);
|
||||
|
|
|
@ -2,16 +2,6 @@
|
|||
#include "bspf.hxx"
|
||||
#include "PackedBitArray.hxx"
|
||||
|
||||
/*
|
||||
|
||||
boolean set();
|
||||
boolean clear();
|
||||
|
||||
void set(int bit);
|
||||
void clear(int bit);
|
||||
void toggle(int bit);
|
||||
*/
|
||||
|
||||
PackedBitArray::PackedBitArray(int length) {
|
||||
size = length;
|
||||
words = length / wordSize + 1;
|
||||
|
@ -21,8 +11,6 @@ PackedBitArray::PackedBitArray(int length) {
|
|||
// start out zeroed already?
|
||||
for(int i=0; i<words; i++)
|
||||
bits[i] = 0;
|
||||
|
||||
// cerr << "size==" << size << " words==" << words << endl;
|
||||
}
|
||||
|
||||
PackedBitArray::~PackedBitArray() {
|
||||
|
@ -47,8 +35,6 @@ void PackedBitArray::toggle(unsigned int bit) {
|
|||
unsigned int word = bit / wordSize;
|
||||
bit %= wordSize;
|
||||
|
||||
// cerr << "word==" << word << ", bit==" << bit << endl;
|
||||
|
||||
bits[word] ^= (1 << bit);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: M6502Hi.cxx,v 1.5 2005-06-16 12:28:54 stephena Exp $
|
||||
// $Id: M6502Hi.cxx,v 1.6 2005-06-17 03:49:09 urchlay Exp $
|
||||
//============================================================================
|
||||
|
||||
#include "M6502Hi.hxx"
|
||||
|
@ -76,8 +76,11 @@ bool M6502High::execute(uInt32 number)
|
|||
|
||||
if(breakPoints != NULL)
|
||||
{
|
||||
if(breakPoints->isSet(PC))
|
||||
myDebugger->start();
|
||||
if(breakPoints->isSet(PC)) {
|
||||
if(myDebugger->start()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: M6502Low.cxx,v 1.5 2005-06-16 12:28:54 stephena Exp $
|
||||
// $Id: M6502Low.cxx,v 1.6 2005-06-17 03:49:10 urchlay Exp $
|
||||
//============================================================================
|
||||
|
||||
#include "M6502Low.hxx"
|
||||
|
@ -63,7 +63,8 @@ bool M6502Low::execute(uInt32 number)
|
|||
if(breakPoints != NULL)
|
||||
{
|
||||
if(breakPoints->isSet(PC))
|
||||
myDebugger->start();
|
||||
if(myDebugger->start())
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: DebuggerDialog.cxx,v 1.11 2005-06-16 22:18:02 stephena Exp $
|
||||
// $Id: DebuggerDialog.cxx,v 1.12 2005-06-17 03:49:10 urchlay Exp $
|
||||
//
|
||||
// Based on code from ScummVM - Scumm Interpreter
|
||||
// Copyright (C) 2002-2004 The ScummVM project
|
||||
|
@ -40,8 +40,8 @@ DebuggerDialog::DebuggerDialog(OSystem* osystem, DialogContainer* parent,
|
|||
|
||||
// 1) The Prompt/console tab
|
||||
myTab->addTab("Prompt");
|
||||
PromptWidget* prompt = new PromptWidget(myTab, 2, 2, _w - vBorder, _h - 25);
|
||||
myTab->setParentWidget(0, prompt, prompt);
|
||||
myPrompt = new PromptWidget(myTab, 2, 2, _w - vBorder, _h - 25);
|
||||
myTab->setParentWidget(0, myPrompt, myPrompt);
|
||||
|
||||
// 2) The CPU tab
|
||||
myTab->addTab("CPU");
|
||||
|
@ -85,3 +85,8 @@ void DebuggerDialog::handleKeyDown(int ascii, int keycode, int modifiers)
|
|||
{
|
||||
myTab->handleKeyDown(ascii, keycode, modifiers);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
PromptWidget *DebuggerDialog::prompt() {
|
||||
return myPrompt;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: DebuggerDialog.hxx,v 1.7 2005-06-16 00:55:59 stephena Exp $
|
||||
// $Id: DebuggerDialog.hxx,v 1.8 2005-06-17 03:49:10 urchlay Exp $
|
||||
//
|
||||
// Based on code from ScummVM - Scumm Interpreter
|
||||
// Copyright (C) 2002-2004 The ScummVM project
|
||||
|
@ -27,6 +27,7 @@ class DialogContainer;
|
|||
class TabWidget;
|
||||
|
||||
#include "Dialog.hxx"
|
||||
#include "PromptWidget.hxx"
|
||||
|
||||
class DebuggerDialog : public Dialog
|
||||
{
|
||||
|
@ -35,11 +36,13 @@ class DebuggerDialog : public Dialog
|
|||
int x, int y, int w, int h);
|
||||
~DebuggerDialog();
|
||||
|
||||
PromptWidget *prompt();
|
||||
virtual void loadConfig();
|
||||
virtual void handleKeyDown(int ascii, int keycode, int modifiers);
|
||||
|
||||
protected:
|
||||
TabWidget* myTab;
|
||||
PromptWidget *myPrompt;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: PromptWidget.cxx,v 1.7 2005-06-16 16:18:57 urchlay Exp $
|
||||
// $Id: PromptWidget.cxx,v 1.8 2005-06-17 03:49:10 urchlay Exp $
|
||||
//
|
||||
// Based on code from ScummVM - Scumm Interpreter
|
||||
// Copyright (C) 2002-2004 The ScummVM project
|
||||
|
@ -78,7 +78,7 @@ PromptWidget::PromptWidget(GuiObject* boss, int x, int y, int w, int h)
|
|||
string version = string("Stella version ") + STELLA_VERSION + "\n";
|
||||
print(version.c_str());
|
||||
print("Debugger is ready\n");
|
||||
print( instance()->debugger().state() + "\n"); // FIXME: this doesn't work yet
|
||||
//print( instance()->debugger().state() + "\n"); // FIXME: this doesn't work yet
|
||||
print(PROMPT);
|
||||
_promptStartPos = _promptEndPos = _currentPos;
|
||||
}
|
||||
|
@ -137,6 +137,12 @@ void PromptWidget::handleMouseWheel(int x, int y, int direction)
|
|||
_scrollBar->handleMouseWheel(x, y, direction);
|
||||
}
|
||||
|
||||
void PromptWidget::printPrompt() {
|
||||
print( instance()->debugger().state() + "\n");
|
||||
print(PROMPT);
|
||||
_promptStartPos = _promptEndPos = _currentPos;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool PromptWidget::handleKeyDown(int ascii, int keycode, int modifiers)
|
||||
{
|
||||
|
@ -174,9 +180,7 @@ bool PromptWidget::handleKeyDown(int ascii, int keycode, int modifiers)
|
|||
delete [] str;
|
||||
}
|
||||
|
||||
print( instance()->debugger().state() + "\n");
|
||||
print(PROMPT);
|
||||
_promptStartPos = _promptEndPos = _currentPos;
|
||||
printPrompt();
|
||||
|
||||
draw();
|
||||
instance()->frameBuffer().refresh();
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: PromptWidget.hxx,v 1.2 2005-06-16 00:56:00 stephena Exp $
|
||||
// $Id: PromptWidget.hxx,v 1.3 2005-06-17 03:49:10 urchlay Exp $
|
||||
//
|
||||
// Based on code from ScummVM - Scumm Interpreter
|
||||
// Copyright (C) 2002-2004 The ScummVM project
|
||||
|
@ -49,6 +49,9 @@ class PromptWidget : public Widget, public CommandSender
|
|||
int vprintf(const char *format, va_list argptr);
|
||||
#undef putchar
|
||||
void putchar(int c);
|
||||
void print(const char *str);
|
||||
void print(string str);
|
||||
void printPrompt();
|
||||
|
||||
protected:
|
||||
inline char &buffer(int idx) { return _buffer[idx % kBufferSize]; }
|
||||
|
@ -57,8 +60,6 @@ class PromptWidget : public Widget, public CommandSender
|
|||
void drawCaret();
|
||||
void putcharIntern(int c);
|
||||
void insertIntoPrompt(const char *str);
|
||||
void print(const char *str);
|
||||
void print(string str);
|
||||
void updateScrollBuffer();
|
||||
void scrollToCurrent();
|
||||
|
||||
|
|
Loading…
Reference in New Issue