make keyboard usable (not fully tested yet); reformat file

This commit is contained in:
Christopher Mosher 2013-10-10 22:32:39 -04:00
parent 13481ab90e
commit bda6d62294
1 changed files with 383 additions and 407 deletions

View File

@ -14,7 +14,7 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
*/
#include "emulator.h"
#include "configep2.h"
#include "e2const.h"
@ -23,445 +23,421 @@
#include <ctime>
Emulator::Emulator():
display(screenImage),
videoStatic(display),
apple2(keypresses,paddleButtonStates,display,fhyper,buffered,screenImage),
timable(0), // No ticked object (NULL pointer)
quit(false),
repeat(false),
keysDown(0),
command(false),
pendingCommandExit(false)
{
Emulator::Emulator() :
display(screenImage),
videoStatic(display),
apple2(keypresses, paddleButtonStates, display, fhyper, buffered, screenImage),
timable(0), // No ticked object (NULL pointer)
quit(false),
repeat(false),
keysDown(0),
command(false),
pendingCommandExit(false) {
}
Emulator::~Emulator()
{
Emulator::~Emulator() {
}
void Emulator::toggleComputerPower()
{
if (this->timable==&this->videoStatic)
powerOnComputer();
else
powerOffComputer();
void Emulator::toggleComputerPower() {
if (this->timable == &this->videoStatic)
powerOnComputer();
else
powerOffComputer();
}
void Emulator::powerOnComputer()
{
this->apple2.powerOn();
this->screenImage.drawPower(true);
this->display.setNoise(false);
void Emulator::powerOnComputer() {
this->apple2.powerOn();
this->screenImage.drawPower(true);
this->display.setNoise(false);
// The apple2 becomes the ticked object
this->timable = &this->apple2;
// The apple2 becomes the ticked object
this->timable = &this->apple2;
}
void Emulator::powerOffComputer()
{
// TODO Need to ask user if OK to lose any unsaved changes to disks
this->apple2.powerOff();
this->screenImage.drawPower(false);
this->display.setNoise(true);
this->videoStatic.powerOn();
void Emulator::powerOffComputer() {
// TODO Need to ask user if OK to lose any unsaved changes to disks
this->apple2.powerOff();
this->screenImage.drawPower(false);
this->display.setNoise(true);
this->videoStatic.powerOn();
// The video static becomes the ticked object
this->timable = &this->videoStatic;
// The video static becomes the ticked object
this->timable = &this->videoStatic;
}
void Emulator::config(Config& cfg)
{
cfg.parse(this->apple2.ram,this->apple2.rom,this->apple2.slts,this->apple2.revision,this->screenImage,this->apple2.cassette);
void Emulator::config(Config& cfg) {
cfg.parse(this->apple2.ram, this->apple2.rom, this->apple2.slts, this->apple2.revision, this->screenImage, this->apple2.cassette);
}
void Emulator::init()
{
powerOffComputer();
this->display.setType(AnalogTV::MONITOR_COLOR);
this->display.powerOn(true);
void Emulator::init() {
powerOffComputer();
this->display.setType(AnalogTV::MONITOR_COLOR);
this->display.powerOn(true);
}
// How many emulation ticks between asking SDL if there is any new input
// from the user or other GUI events.
// This is also how often we shall update the estimate of the emulator's
// actual speed performance
// When the CPU is the object being ticked (each tick is a CPU cycle), then
// this is 20.04378892 Hz in emulated seconds time
// How many emulation ticks between asking SDL if there is any new input
// from the user or other GUI events.
// This is also how often we shall update the estimate of the emulator's
// actual speed performance
// When the CPU is the object being ticked (each tick is a CPU cycle), then
// this is 20.04378892 Hz in emulated seconds time
#define CHECK_EVERY_CYCLE 51024
#define CHECK_CYCLES_K 51024000
#define EXPECTED_MS 50
// U.A.2 p. 7-13: REPT key repeats at 10Hz.
static const int CYCLES_PER_REPT(E2Const::AVG_CPU_HZ/10);
static const int CYCLES_PER_REPT(E2Const::AVG_CPU_HZ / 10);
// The core of this Apple
int Emulator::run()
{
int skip = CHECK_EVERY_CYCLE;
Uint32 prev_ms = SDL_GetTicks();
// While the user still wants to run this emulation...
while (!this->quit)
{
// (Obligatory protection against NULL object pointer)
if (this->timable)
{
this->timable->tick();
// If the Apple ][ keyboard repeat is on (the REPT key is
// down)...
if (this->repeat)
{
// Count our way down to when the timer for the REPT key
// fires off: 10Hz in terms of how many CPU cycles have gone
// by
--this->rept;
// If it's time for the REPT key timer to fire (at long
// last)...
if (this->rept <= 0)
{
// ...reload the timer for the next firing 1/10 second from
// now ( *reset* the timer )
this->rept = CYCLES_PER_REPT;
// If any other keys are actually being held down...
if (this->keysDown > 0)
{
// ...REPEAT the most recent one that was pressed
this->keypresses.push(this->lastKeyDown);
}
}
}
}
// The core of this Apple
// People who have too many press releases should be referred to as
// keyboards
--skip;
// If skip has been decremented to zero...
if (!skip)
{
// ...then it's time to drain away any piled-up user interaction
// events that SDL has stored up for us
// Reload the skip quantity
skip = CHECK_EVERY_CYCLE;
SDL_Event event;
while (SDL_PollEvent(&event))
{
switch (event.type)
{
// If SDL is going away...
case SDL_QUIT:
this->quit = true;
break;
case SDL_KEYDOWN:
// If we're collecting a command line for changing any
// of the configurables of the emulator...
if (this->command)
cmdKey(event.key);
else
// ...else we're collecting keypresses for the keyboard
// emulation (and thus the Apple ][ emulation itself)
dispatchKeypress(event.key);
break;
case SDL_KEYUP:
// If we're collecting a command line for changing any
// of the configurables of the emulator...
if (this->command)
{
if (this->pendingCommandExit)
{
this->command = false;
this->pendingCommandExit = false;
}
}
else
{
// ...else we're collecting keypresses for the keyboard
// emulation (and thus the Apple ][ emulation itself)
dispatchKeyUp(event.key);
}
break;
}
}
// If we're trying to run as slow as a real Apple ][...
if (!this->fhyper.isHyper())
{
const int delta_ms = EXPECTED_MS-(SDL_GetTicks()-prev_ms);
if (0 < delta_ms && delta_ms <= EXPECTED_MS)
{
SDL_Delay(delta_ms);
}
}
// Display the current estimate of the emulator's actual speed
// performance
this->screenImage.displayHz(CHECK_CYCLES_K/(SDL_GetTicks()-prev_ms));
prev_ms = SDL_GetTicks();
}
}
return 0;
}
void Emulator::dispatchKeyUp(const SDL_KeyboardEvent& keyEvent)
{
SDL_Keycode sym = keyEvent.keysym.sym;
SDL_Keymod mod = (SDL_Keymod)keyEvent.keysym.mod;
unsigned char key = (unsigned char)(sym & 0x7F);
// printf("key UP: %d sym: %d mod: %04X scn: %d\n",key,sym,mod,scancode);
if ((sym < 0x7F || sym == SDLK_LEFT || sym == SDLK_RIGHT) &&
!(sym == SDLK_TAB || sym == SDLK_BACKQUOTE || sym == '[' || sym == '\\' || sym == SDLK_DELETE) &&
!(sym == ']' && mod&KMOD_SHIFT))
{
--this->keysDown;
}
// ...else if this is the emulated REPT key on the Apple keyboard...
else if (sym == SDLK_F10)
{
// ...stop repeating. The key has been released
this->repeat = false;
this->rept = 0;
}
}
// Take real-world keystrokes from SDL and filter them to emulate the
// Apple ][ or Apple ][ plus keyboard
void Emulator::dispatchKeypress(const SDL_KeyboardEvent& keyEvent)
{
if (keyEvent.repeat)
{
return;
int Emulator::run() {
int skip = CHECK_EVERY_CYCLE;
Uint32 prev_ms = SDL_GetTicks();
// While the user still wants to run this emulation...
while (!this->quit) {
// (Obligatory protection against NULL object pointer)
if (this->timable) {
this->timable->tick();
// If the Apple ][ keyboard repeat is on (the REPT key is
// down)...
if (this->repeat) {
// Count our way down to when the timer for the REPT key
// fires off: 10Hz in terms of how many CPU cycles have gone
// by
--this->rept;
// If it's time for the REPT key timer to fire (at long
// last)...
if (this->rept <= 0) {
// ...reload the timer for the next firing 1/10 second from
// now ( *reset* the timer )
this->rept = CYCLES_PER_REPT;
// If any other keys are actually being held down...
if (this->keysDown > 0) {
// ...REPEAT the most recent one that was pressed
this->keypresses.push(this->lastKeyDown);
}
}
}
}
SDL_Keycode sym = keyEvent.keysym.sym;
SDL_Keymod mod = (SDL_Keymod)keyEvent.keysym.mod;
unsigned char key = (unsigned char)(sym & 0x7F);
// People who have too many press releases should be referred to as
// keyboards
// printf("key DN: %d sym: %d mod: %04X scn: %d\n",key,sym,mod,scancode);
--skip;
// If skip has been decremented to zero...
if (!skip) {
// ...then it's time to drain away any piled-up user interaction
// events that SDL has stored up for us
// Reload the skip quantity
skip = CHECK_EVERY_CYCLE;
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
// If SDL is going away...
case SDL_QUIT:
this->quit = true;
break;
case SDL_KEYDOWN:
// If we're collecting a command line for changing any
// of the configurables of the emulator...
if (this->command)
cmdKey(event.key);
else
// ...else we're collecting keypresses for the keyboard
// emulation (and thus the Apple ][ emulation itself)
dispatchKeypress(event.key);
break;
case SDL_KEYUP:
// If we're collecting a command line for changing any
// of the configurables of the emulator...
if (this->command) {
if (this->pendingCommandExit) {
this->command = false;
this->pendingCommandExit = false;
}
} else {
// ...else we're collecting keypresses for the keyboard
// emulation (and thus the Apple ][ emulation itself)
dispatchKeyUp(event.key);
}
break;
}
}
// If we're trying to run as slow as a real Apple ][...
if (!this->fhyper.isHyper()) {
const int delta_ms = EXPECTED_MS - (SDL_GetTicks() - prev_ms);
if (0 < delta_ms && delta_ms <= EXPECTED_MS) {
SDL_Delay(delta_ms);
}
if ((sym < 0x7F || sym == SDLK_LEFT || sym == SDLK_RIGHT) &&
!(sym == SDLK_TAB || sym == SDLK_BACKQUOTE || sym == '[' || sym == '\\' || sym == SDLK_DELETE) &&
!(sym == ']' && mod&KMOD_SHIFT))
{
++this->keysDown;
}
if (sym == SDLK_LEFT)
{
key = 8;
}
else if (sym == SDLK_RIGHT)
{
key = 21;
}
else if (sym == SDLK_PAUSE)
{
this->apple2.reset();
return;
}
else if (sym == SDLK_INSERT)
{
// Feed input from the clipboard to the Apple keyboard
std::string s = this->clip.getText();
for (unsigned int i = 0; i < s.length(); ++i)
{
key = s[i];
// TODO fix pasting line-endings
if (key == '\n')
key = '\r';
if ('a' <= key && key <= 'z')
{
key -= 32;
}
this->keypresses.push(key);
}
return;
}
// ...else if this is the emulated REPT key on the Apple keyboard...
else if (sym == SDLK_F10)
{
// ...start auto-repeat
this->repeat = true;
this->rept = CYCLES_PER_REPT;
return;
}
// ...else if the user wants to run at full speed instead of emulating
// the Apple's speed...
else if (sym == SDLK_F11)
{
this->fhyper.toggleHyper();
this->screenImage.toggleHyperLabel();
return;
}
else if (sym == SDLK_F12)
{
this->buffered.toggleBuffered();
this->screenImage.toggleKdbBufferLabel();
return;
}
// ...else if the user has hit the rocker switch on the back of the Apple...
else if (sym == SDLK_F1)
{
toggleComputerPower();
return;
}
// ...else if the user wants to look at a different video display medium...
else if (sym == SDLK_F2)
{
this->display.cycleType();
this->screenImage.cycleDisplayLabel();
return;
}
// ...else if the user wants to switch to/from full screen and an
// individual application window...
else if (sym == SDLK_F3)
{
this->screenImage.toggleFullScreen();
this->screenImage.drawPower(this->timable==&this->apple2);
return;
}
// ...else if the user wants to switch between the interlaced extension
// of the display and the non-interlaced historically correct display...
else if (sym == SDLK_F4)
{
this->display.toggleBleedDown();
this->screenImage.toggleFillLinesLabel();
return;
}
// ...else initiate command line entry at the bottom of the emulator window
else if (sym == SDLK_F5)
{
this->command = true;
this->screenImage.enterCommandMode();
}
// ...else exit the entire emulation
else if (sym == SDLK_END)
{
this->quit = true;
return;
}
// ...else save a screen shot
else if (sym == SDLK_PRINTSCREEN)
{
this->screenImage.saveBMP();
}
// The unmodified Apple ][ hardware keyboard only generates upper-case
if ('a' <= key && key <= 'z')
{
key -= 32;
}
if ((mod&KMOD_SHIFT) && (mod&KMOD_CTRL) && sym == '2')
{
// Ctrl-Shift-2 == Ctrl-@ == NUL == ASCII: 0
key = 0;
}
else if ((mod&KMOD_SHIFT) && (mod&KMOD_CTRL) && sym == ' ')
{
// Ctrl-Shift-Space is the same as Space
key = ' ';
}
else if ((mod&KMOD_CTRL) && !(mod&KMOD_SHIFT) && SDLK_KP_0 <= sym && sym <= SDLK_KP_9)
{
// Control-only numeric keypad keys are converted to regular digit keys
key = sym-SDLK_KP_0+'0';
}
else if ((mod&KMOD_CTRL) && !(mod&KMOD_SHIFT) && (('0' <= sym && sym <= '9') || sym == '/' || sym == ' '))
{
// Control-only upon 0-9, / and space leaves them unchanged, the
// same as unmodified
key = sym;
}
else if (sym == ']')
{
if (mod&KMOD_SHIFT)
{
// ignore '}' (shift ']')
return;
}
if (mod&KMOD_CTRL)
{
// Ctrl-] == ASCII: $1D
key = 29;
}
}
// ...else if this is one of the keys that can't be typed on an Apple ][
// keyboard...
else if (key == 0 || sym == SDLK_TAB || sym == SDLK_BACKQUOTE || sym == '[' || sym == '\\' || sym == SDLK_DELETE)
{
return;
}
// printf(" sending to apple as ascii------------------------------>%02X (%02X)\n",key,key|0x80);
this->keypresses.push(key);
this->lastKeyDown = key;
}
// Display the current estimate of the emulator's actual speed
// performance
this->screenImage.displayHz(CHECK_CYCLES_K / (SDL_GetTicks() - prev_ms));
prev_ms = SDL_GetTicks();
}
}
return 0;
}
// Collect and edit a command line typed at the bottom of the emulator
// window
void Emulator::cmdKey(const SDL_KeyboardEvent& keyEvent)
{
SDL_Keycode sym = keyEvent.keysym.sym;
SDL_Keymod mod = (SDL_Keymod)keyEvent.keysym.mod;
unsigned char key = (unsigned char)(sym & 0x7F);
void Emulator::dispatchKeyUp(const SDL_KeyboardEvent& keyEvent) {
SDL_Keycode sym = keyEvent.keysym.sym;
SDL_Keymod mod = (SDL_Keymod) keyEvent.keysym.mod;
unsigned char key = (unsigned char) (sym & 0x7F);
if (sym == SDLK_RETURN)
{
processCommand();
}
else if (sym == SDLK_ESCAPE)
{
cmdline.erase(cmdline.begin(),cmdline.end());
processCommand();
}
else if (sym == SDLK_BACKSPACE)
{
if (cmdline.length())
{
cmdline.erase(cmdline.end()-1);
this->screenImage.backspaceCommand();
}
}
else if (sym == SDLK_INSERT)
{
std::string s = this->clip.getText();
for (unsigned int i = 0; i < s.length(); ++i)
{
key = s[i];
if (key == '\n' || key == '\r')
{
processCommand();
break;
}
else
{
cmdline += key;
this->screenImage.addkeyCommand(key);
}
}
}
else if (key)
{
cmdline += key;
this->screenImage.addkeyCommand(key);
}
if ((sym < 0x7F || sym == SDLK_LEFT || sym == SDLK_RIGHT) &&
!(sym == SDLK_TAB || sym == SDLK_BACKQUOTE || sym == '[' || sym == '\\' || sym == SDLK_DELETE) &&
!(sym == ']' && mod & KMOD_SHIFT)) {
--this->keysDown;
}// ...else if this is the emulated REPT key on the Apple keyboard...
else if (sym == SDLK_F10) {
// ...stop repeating. The key has been released
this->repeat = false;
this->rept = 0;
}
}
// Process a command line typed at the bottom of the emulator window
void Emulator::processCommand()
{
this->screenImage.exitCommandMode();
this->pendingCommandExit = true;
static bool translateKeysToAppleModernized(SDL_Keycode keycode, SDL_Keymod modifiers, unsigned char* key) {
if (keycode >= 0x100) {
return false;
}
if (cmdline.empty())
{
return;
}
*key = (unsigned char) (keycode & 0x7F);
Config::parseLine(cmdline,this->apple2.ram,this->apple2.rom,this->apple2.slts,this->apple2.revision,this->screenImage,this->apple2.cassette);
cmdline.erase(cmdline.begin(),cmdline.end());
// The Apple ][ hardware keyboard only generates upper-case
if ('a' <= *key && *key <= 'z') {
*key -= 32;
}
// from SDL 1.2 to 2.0, we can't use UNICODE so we need to
// apply shift and control modifiers ourselves
if (modifiers & KMOD_SHIFT) {
if (keycode == SDLK_BACKQUOTE) *key = '~';
else if (keycode == SDLK_1) *key = '!';
else if (keycode == SDLK_2) *key = '@';
else if (keycode == SDLK_3) *key = '#';
else if (keycode == SDLK_4) *key = '$';
else if (keycode == SDLK_5) *key = '%';
else if (keycode == SDLK_6) *key = '^';
else if (keycode == SDLK_7) *key = '&';
else if (keycode == SDLK_8) *key = '*';
else if (keycode == SDLK_9) *key = '(';
else if (keycode == SDLK_0) *key = ')';
else if (keycode == SDLK_MINUS) *key = '_';
else if (keycode == SDLK_EQUALS) *key = '+';
else if (keycode == SDLK_SEMICOLON) *key = ':';
else if (keycode == SDLK_QUOTE) *key = '\"';
else if (keycode == SDLK_COMMA) *key = '<';
else if (keycode == SDLK_PERIOD) *key = '>';
else if (keycode == SDLK_SLASH) *key = '?';
}
if (modifiers & KMOD_CTRL) {
if ('A' <= *key && *key <= 'Z') {
*key -= 64;
}
}
if (keycode == SDLK_LEFT) {
*key = 8;
} else if (keycode == SDLK_RIGHT) {
*key = 21;
}
if ((modifiers & KMOD_SHIFT) && (modifiers & KMOD_CTRL) && keycode == '2') {
// Ctrl-Shift-2 == Ctrl-@ == NUL == ASCII: 0
*key = 0;
} else if ((modifiers & KMOD_SHIFT) && (modifiers & KMOD_CTRL) && keycode == ' ') {
// Ctrl-Shift-Space is the same as Space
*key = ' ';
} else if ((modifiers & KMOD_CTRL) && !(modifiers & KMOD_SHIFT) && SDLK_KP_0 <= keycode && keycode <= SDLK_KP_9) {
// Control-only numeric *keypad *keys are converted to regular digit *keys
*key = keycode - SDLK_KP_0 + '0';
} else if ((modifiers & KMOD_CTRL) && !(modifiers & KMOD_SHIFT) && (('0' <= keycode && keycode <= '9') || keycode == '/' || keycode == ' ')) {
// Control-only upon 0-9, / and space leaves them unchanged, the
// same as unmodified
*key = keycode;
} else if (keycode == ']') {
if (modifiers & KMOD_SHIFT) {
// ignore '}' (shift ']')
return false;
}
if (modifiers & KMOD_CTRL) {
// Ctrl-] == ASCII: $1D
*key = 29;
}
}// ...else if this is one of the *keys that can't be typed on an Apple ][
// *keyboard...
else if (*key == 0 || keycode == SDLK_TAB || keycode == SDLK_BACKQUOTE || keycode == '[' || keycode == '\\' || keycode == SDLK_DELETE) {
return false;
}
return true;
}
// Take real-world keystrokes from SDL and filter them to emulate the
// Apple ][ or Apple ][ plus keyboard
void Emulator::dispatchKeypress(const SDL_KeyboardEvent& keyEvent) {
if (keyEvent.repeat) {
return;
}
SDL_Keycode sym = keyEvent.keysym.sym;
SDL_Keymod mod = (SDL_Keymod) keyEvent.keysym.mod;
SDL_Scancode scan = keyEvent.keysym.scancode;
printf("keydown: mod: %04X sym: %08X scan:%04X name:%s\n", mod, sym, scan, SDL_GetKeyName(sym));
if ((sym < 0x7F || sym == SDLK_LEFT || sym == SDLK_RIGHT) &&
!(sym == SDLK_TAB || sym == SDLK_BACKQUOTE || sym == '[' || sym == '\\' || sym == SDLK_DELETE) &&
!(sym == ']' && mod & KMOD_SHIFT)) {
++this->keysDown;
}
/*
* First handle the key presses that are for commands, as opposed to
* simple key-presses that we send to the apple.
*/
if (sym == SDLK_PAUSE) {
this->apple2.reset();
return;
} else if (sym == SDLK_INSERT) {
// Feed input from the clipboard to the Apple keyboard
std::string s = this->clip.getText();
for (unsigned int i = 0; i < s.length(); ++i) {
unsigned char key = s[i];
// TODO fix pasting line-endings
if (key == '\n')
key = '\r';
if ('a' <= key && key <= 'z') {
key -= 32;
}
this->keypresses.push(key);
}
return;
}// ...else if this is the emulated REPT key on the Apple keyboard...
else if (sym == SDLK_F10) {
// ...start auto-repeat
this->repeat = true;
this->rept = CYCLES_PER_REPT;
return;
}// ...else if the user wants to run at full speed instead of emulating
// the Apple's speed...
else if (sym == SDLK_F11) {
this->fhyper.toggleHyper();
this->screenImage.toggleHyperLabel();
return;
} else if (sym == SDLK_F12) {
this->buffered.toggleBuffered();
this->screenImage.toggleKdbBufferLabel();
return;
}// ...else if the user has hit the rocker switch on the back of the Apple...
else if (sym == SDLK_F1) {
toggleComputerPower();
return;
}// ...else if the user wants to look at a different video display medium...
else if (sym == SDLK_F2) {
this->display.cycleType();
this->screenImage.cycleDisplayLabel();
return;
}// ...else if the user wants to switch to/from full screen and an
// individual application window...
else if (sym == SDLK_F3) {
this->screenImage.toggleFullScreen();
this->screenImage.drawPower(this->timable == &this->apple2);
return;
}// ...else if the user wants to switch between the interlaced extension
// of the display and the non-interlaced historically correct display...
else if (sym == SDLK_F4) {
this->display.toggleBleedDown();
this->screenImage.toggleFillLinesLabel();
return;
}// ...else initiate command line entry at the bottom of the emulator window
else if (sym == SDLK_F5) {
this->command = true;
this->screenImage.enterCommandMode();
return;
}// ...else exit the entire emulation
else if (sym == SDLK_END) {
this->quit = true;
return;
}// ...else save a screen shot
else if (sym == SDLK_PRINTSCREEN) {
this->screenImage.saveBMP();
return;
}
unsigned char key;
const bool sendKey = translateKeysToAppleModernized(sym, mod, &key);
if (sendKey) {
printf(" sending to apple as ASCII ------------------------------> %02X (%02X)\n", key, key | 0x80);
this->keypresses.push(key);
this->lastKeyDown = key;
}
}
// Collect and edit a command line typed at the bottom of the emulator
// window
void Emulator::cmdKey(const SDL_KeyboardEvent& keyEvent) {
SDL_Keycode sym = keyEvent.keysym.sym;
SDL_Keymod mod = (SDL_Keymod) keyEvent.keysym.mod;
unsigned char key = (unsigned char) (sym & 0x7F);
if (sym == SDLK_RETURN) {
processCommand();
} else if (sym == SDLK_ESCAPE) {
cmdline.erase(cmdline.begin(), cmdline.end());
processCommand();
} else if (sym == SDLK_BACKSPACE) {
if (cmdline.length()) {
cmdline.erase(cmdline.end() - 1);
this->screenImage.backspaceCommand();
}
} else if (sym == SDLK_INSERT) {
std::string s = this->clip.getText();
for (unsigned int i = 0; i < s.length(); ++i) {
key = s[i];
if (key == '\n' || key == '\r') {
processCommand();
break;
} else {
cmdline += key;
this->screenImage.addkeyCommand(key);
}
}
} else if (key) {
cmdline += key;
this->screenImage.addkeyCommand(key);
}
}
// Process a command line typed at the bottom of the emulator window
void Emulator::processCommand() {
this->screenImage.exitCommandMode();
this->pendingCommandExit = true;
if (cmdline.empty()) {
return;
}
Config::parseLine(cmdline, this->apple2.ram, this->apple2.rom, this->apple2.slts, this->apple2.revision, this->screenImage, this->apple2.cassette);
cmdline.erase(cmdline.begin(), cmdline.end());
}