mirror of
https://github.com/makarcz/vm6502.git
synced 2025-05-13 06:38:11 +00:00
Char I/O
Improvements to character I/O emulation: * Performance. * Use native console STDIO in execute mode, text display emulation in debug mode. * Always shadow character I/O with text device emulation, even when native STDIO is used.
This commit is contained in:
parent
d99ed03232
commit
dce9babd36
53
Display.cpp
53
Display.cpp
@ -52,6 +52,7 @@ Display::~Display()
|
||||
*/
|
||||
void Display::InitScr()
|
||||
{
|
||||
mLastChar = 0;
|
||||
mScrLines = SCREENDIM_ROW;
|
||||
mScrColumns = SCREENDIM_COL;
|
||||
mShellConsoleWidth = GetConsoleWidth();
|
||||
@ -133,11 +134,11 @@ void Display::ScrollUp()
|
||||
{
|
||||
for (unsigned int row=0; row<mScrLines-1; row++) {
|
||||
for (unsigned int col=0; col<mScrColumns; col++) {
|
||||
mScreen[col][row] = mScreen[col][row+1];
|
||||
mScreen[row][col] = mScreen[row+1][col];
|
||||
}
|
||||
}
|
||||
for (unsigned int col=0; col<mScrColumns; col++) {
|
||||
mScreen[col][mScrLines-1] = ' ';
|
||||
mScreen[mScrLines-1][col] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,6 +200,7 @@ void Display::PutChar(char c)
|
||||
if (isalnum(c) || ispunct(c) || isspace(c) || IsSpecChar(c))
|
||||
{
|
||||
if (c == SCREENSPECCHARS_NL) {
|
||||
mLastChar = SCREENSPECCHARS_NL;
|
||||
//mCursorCoord.col = 0;
|
||||
mCursorCoord.row++;
|
||||
if (mCursorCoord.row >= mScrLines) {
|
||||
@ -206,19 +208,24 @@ void Display::PutChar(char c)
|
||||
mCursorCoord.row = mScrLines-1;
|
||||
}
|
||||
} else if (c == SCREENSPECCHARS_CR) {
|
||||
mLastChar = SCREENSPECCHARS_CR;
|
||||
mCursorCoord.col = 0;
|
||||
} else if (c == SCREENSPECCHARS_TB) {
|
||||
mLastChar = SCREENSPECCHARS_TB;
|
||||
mCursorCoord.col += TABSIZE;
|
||||
if (mCursorCoord.col >= mScrColumns) {
|
||||
mCursorCoord.col = mScrColumns-1; // must work on it some more
|
||||
}
|
||||
} else if (c == SCREENSPECCHARS_BS) {
|
||||
mLastChar = SCREENSPECCHARS_BS;
|
||||
if (mCursorCoord.col > 0) mCursorCoord.col--;
|
||||
} else if (c == SCREENSPECCHARS_BE) {
|
||||
mLastChar = SCREENSPECCHARS_BE;
|
||||
// no action
|
||||
}
|
||||
else {
|
||||
mScreen[mCursorCoord.col][mCursorCoord.row] = c;
|
||||
mScreen[mCursorCoord.row][mCursorCoord.col] = c;
|
||||
mLastChar = c;
|
||||
mCursorCoord.col++;
|
||||
if (mCursorCoord.col >= mScrColumns) {
|
||||
mCursorCoord.col = 0;
|
||||
@ -245,7 +252,7 @@ void Display::ClrScr()
|
||||
{
|
||||
for (unsigned int col=0; col<mScrColumns; col++) {
|
||||
for (unsigned int row=0; row<mScrLines; row++) {
|
||||
mScreen[col][row] = ' ';
|
||||
mScreen[row][col] = ' ';
|
||||
}
|
||||
}
|
||||
mCursorCoord.col = mCursorCoord.row = 0;
|
||||
@ -264,7 +271,7 @@ char Display::GetCharAt(unsigned int col, unsigned int row)
|
||||
char c = -1;
|
||||
|
||||
if (col < mScrColumns && row < mScrLines)
|
||||
c = mScreen[col][row];
|
||||
c = mScreen[row][col];
|
||||
|
||||
return c;
|
||||
}
|
||||
@ -280,20 +287,23 @@ char Display::GetCharAt(unsigned int col, unsigned int row)
|
||||
*/
|
||||
void Display::ShowScr()
|
||||
{
|
||||
char buf[SCREENDIM_COL] = {0};
|
||||
string scr;
|
||||
scr.clear();
|
||||
for (unsigned int row=0; row<mScrLines; row++) {
|
||||
string line;
|
||||
line.clear();
|
||||
for (unsigned int col=0; col<mScrColumns; col++) {
|
||||
char c = mScreen[col][row];
|
||||
if (mCursorCoord.col == col && mCursorCoord.row == row) {
|
||||
c = '_';
|
||||
char *linebuf = &(mScreen[row][0]);
|
||||
memset(buf, 0, mScrColumns);
|
||||
strncpy(buf, linebuf, mScrColumns);
|
||||
buf[mScrColumns] = 0;
|
||||
if (mCursorCoord.row == row) {
|
||||
buf[mCursorCoord.col] = '_';
|
||||
}
|
||||
line = line + c;
|
||||
}
|
||||
cout << line;
|
||||
string line(buf);
|
||||
// add extra NL if the real console is wider than emulated one
|
||||
if (mShellConsoleWidth > mScrColumns) cout << endl;
|
||||
if (mShellConsoleWidth > mScrColumns) line = line + "\n";
|
||||
scr = scr + line;
|
||||
}
|
||||
cout << scr;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -309,4 +319,17 @@ CursorCoord *Display::GetCursorCoord()
|
||||
return &mCursorCoord;
|
||||
}
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------------
|
||||
* Method:
|
||||
* Purpose:
|
||||
* Arguments:
|
||||
* Returns:
|
||||
*--------------------------------------------------------------------
|
||||
*/
|
||||
char Display::GetLastChar()
|
||||
{
|
||||
return mLastChar;
|
||||
}
|
||||
|
||||
} // namespace MKBasic
|
||||
|
@ -37,12 +37,14 @@ class Display
|
||||
char GetCharAt(unsigned int col, unsigned int row);
|
||||
void ShowScr();
|
||||
CursorCoord *GetCursorCoord();
|
||||
char GetLastChar();
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
|
||||
char mScreen[SCREENDIM_COL][SCREENDIM_ROW];
|
||||
char mScreen[SCREENDIM_ROW][SCREENDIM_COL];
|
||||
char mLastChar;
|
||||
CursorCoord mCursorCoord;
|
||||
unsigned int mShellConsoleWidth;
|
||||
unsigned int mScrLines;
|
||||
|
10
Memory.cpp
10
Memory.cpp
@ -225,10 +225,10 @@ unsigned char Memory::ReadCharKb(bool nonblock)
|
||||
set_conio_terminal_mode();
|
||||
#endif
|
||||
static int c = ' ';
|
||||
putchar('\n');
|
||||
//putchar('\n');
|
||||
if (mIOEcho && isprint(c)) putchar(c);
|
||||
else putchar(' ');
|
||||
fputs("<-Character Input (CTRL-Y to BREAK) ?\r",stdout);
|
||||
//else putchar(' ');
|
||||
//fputs("<-Character Input (CTRL-Y to BREAK) ?\r",stdout);
|
||||
fflush(stdout);
|
||||
if (!nonblock) while(!kbhit());
|
||||
else c = 0;
|
||||
@ -239,8 +239,8 @@ unsigned char Memory::ReadCharKb(bool nonblock)
|
||||
kill(getpid(),SIGINT);
|
||||
}
|
||||
#endif
|
||||
fputs(" \r",stdout);
|
||||
fflush(stdout);
|
||||
//fputs(" \r",stdout);
|
||||
//fflush(stdout);
|
||||
mCharIOBufIn[mInBufDataEnd] = c;
|
||||
mInBufDataEnd++;
|
||||
if (mInBufDataEnd >= CHARIO_BUF_SIZE) mInBufDataEnd = 0;
|
||||
|
51
ReadMe.txt
51
ReadMe.txt
@ -193,18 +193,49 @@ This function will return value 0 in the memory location and Acc register
|
||||
if there was no key pressed by the user (no character waiting in buffer).
|
||||
If there was a key typed, the function will act as the blocking counterpart.
|
||||
|
||||
Note that there is no clearly distinguished prompt generated by emulator
|
||||
when there is character input operation performed. It is designed like that
|
||||
to avoid interfering with the character I/O performed by native 6502 code.
|
||||
Therefore if user performs multi-step debugging in the debug console and
|
||||
program suddenly stops, it is likely waiting for character input.
|
||||
This is more clear when running the native 6502 code in non-debug execute
|
||||
mode. In this case the I/O operations are represented on the screen instantly
|
||||
and 6502 code may also produce prompts so user is aware when to enter data
|
||||
to the program.
|
||||
|
||||
Writing to IOADDR inside the 6502 code will result in character code
|
||||
being put in the IOADDR memory location and also written to the character
|
||||
output buffer of the emulated display device. That character is not
|
||||
immediately transferred to the user's DOS/shell session. It is written to the
|
||||
emulated display's text memory instead. Depending on the mode in which
|
||||
emulator is currently working (continuous or step-by-step code execution),
|
||||
the emulated display device contents may or may not be updated on the user's
|
||||
screen in real time fashion. Remember that this is a DOS/shell console
|
||||
application. The user's console is shared among various functions of the
|
||||
program. In step-by-step mode, if the character I/O emulation is enabled, the
|
||||
current contents of the emulated display device can be displayed with
|
||||
corresponding debug console command: 'T'.
|
||||
output buffer of the emulated display device.
|
||||
|
||||
When VM is running in one of the debug modes, like step-by-step mode
|
||||
(S - step, N - go number of steps) or one of the debug code execution modes
|
||||
(C- continue or G - go/cont. from new address), that character is not
|
||||
immediately transferred to the user's DOS/shell session.
|
||||
It is only written to the emulated display's text memory.
|
||||
|
||||
When VM is running in non-debug code execution mode (X - execute from new
|
||||
address), the character is also output to the native DOS/shell console
|
||||
(user's screen).
|
||||
The character output history is therefore always kept in the memory of the
|
||||
emulated text display device and can be recalled to the screen in debug
|
||||
console with command 'T'.
|
||||
|
||||
There are 2 reasons for this:
|
||||
|
||||
* Performance.
|
||||
In previous version only the emulated text display device approach was used.
|
||||
That meant that each time there was a new character in the emulated display
|
||||
buffer, the entire emulated text output device screen had to be refreshed on
|
||||
the DOS/shell console. That was slow and caused screen flicker when characters
|
||||
were output at high rate of speed.
|
||||
|
||||
* Record of character I/O operation.
|
||||
During step-by-step debugging or multiple-step animated registers mode, any
|
||||
characters output is immediately replaced by the registers and stack status
|
||||
on the screen and is not visible on the screen. However user must be able to
|
||||
debug applications that perform character I/O operations and recall the
|
||||
history of the characters output to the emulated text display device. This is
|
||||
when shadow copy of character I/O comes handy.
|
||||
|
||||
4. ROM (read-only memory) emulation.
|
||||
|
||||
|
@ -280,7 +280,8 @@ Regs *VMachine::Exec()
|
||||
while (true) {
|
||||
cpureg = Step();
|
||||
if (mCharIO) {
|
||||
ShowDisp();
|
||||
cout << mpDisp->GetLastChar();
|
||||
cout << flush;
|
||||
}
|
||||
if (cpureg->LastRTS || mOpInterrupt) break;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
10 LET A=0
|
||||
20 PR A;") HELLO WORLD FROM MKHBC!"
|
||||
20 PRINT A;") HELLO WORLD FROM MKHBC!"
|
||||
30 LET A=A+1
|
||||
40 IF A>100 THEN END
|
||||
50 GOTO 20
|
||||
|
2
main.cpp
2
main.cpp
@ -346,6 +346,8 @@ int main(int argc, char** argv) {
|
||||
newaddr = 0x10000;
|
||||
}
|
||||
if (brk || opbrk || stop || lrts) {
|
||||
pvm->ClearScreen();
|
||||
pvm->ShowIO();
|
||||
cout << endl;
|
||||
if (opbrk) {
|
||||
cout << "Interrupted at " << hex << preg->PtrAddr << endl;
|
||||
|
@ -13,3 +13,6 @@ $F0 $06 $8D $00 $E0 $E8 $D0 $F5
|
||||
$00 $00 $EA $4C $00 $02 $45 $6E
|
||||
$74 $65 $72 $20 $74 $65 $78 $74
|
||||
$3A $00 $00 $00 $00 $00 $00 $00
|
||||
ENIO
|
||||
EXEC
|
||||
$0200
|
Loading…
x
Reference in New Issue
Block a user