Compare commits

...

2 Commits

Author SHA1 Message Date
Christopher A. Mosher 498edf22e1 Move FN key handling from SDL to main App, and add menu items for them 2022-12-12 21:47:10 -05:00
Christopher A. Mosher b064d06efd add wx menu handling for F1,F7,F9; fix initial value (random) of keyboard latch 2022-12-12 13:03:30 -05:00
9 changed files with 368 additions and 221 deletions

View File

@ -28,6 +28,8 @@
#include "e2const.h"
#include <wx/app.h>
#include <wx/uiaction.h>
#include <wx/window.h>
#include <wx/xrc/xmlres.h>
#include <wx/fileconf.h>
#include <wx/log.h>
@ -201,6 +203,34 @@ bool E2wxApp::OnInit() {
void E2wxApp::OnFnKeyPressed(const SDL_Keycode k) {
if (k == SDLK_F1) {
this->TogglePower();
} else if (k == SDLK_F2) {
this->CycleMonitor();
} else if (k == SDLK_F3) {
this->ToggleFullScreen();
} else if (k == SDLK_F4) {
//
} else if (k == SDLK_F5) {
//
} else if (k == SDLK_F6) {
this->Reset();
} else if (k == SDLK_F7) {
this->Paste();
} else if (k == SDLK_F8) {
this->ScreenShot();
} else if (k == SDLK_F9) {
this->CloseMainFrame();
} else if (k == SDLK_F10) {
//
} else if (k == SDLK_F11) {
//
} else if (k == SDLK_F12) {
this->ToggleBuffered();
}
}
bool E2wxApp::CloseMainFrame() {
bool r = false;
if (this->frame) {
@ -360,12 +390,13 @@ void E2wxApp::StartEmulator() {
this->emu = new Emulator();
E2Config cfg{this->arg_configfile, this->opt_config_from_prefs_only};
this->emu->config(cfg);
this->emu->init();
this->emu_timer = new EmuTimer{this->emu};
this->emu_timer->begin();
}
bool E2wxApp::EnsureCanQuit() {
bool ok = true;
if (this->emu) {
@ -373,3 +404,45 @@ bool E2wxApp::EnsureCanQuit() {
}
return ok;
}
void E2wxApp::Paste() {
if (this->emu) {
this->emu->paste();
}
}
void E2wxApp::CycleMonitor() {
if (this->emu) {
this->emu->monitorCycle();
}
}
void E2wxApp::ScreenShot() {
if (this->emu) {
this->emu->screenshot();
}
}
void E2wxApp::Reset() {
if (this->emu) {
this->emu->reset();
}
}
void E2wxApp::TogglePower() {
if (this->emu) {
this->emu->toggleComputerPower();
}
}
void E2wxApp::ToggleBuffered() {
if (this->emu) {
this->emu->toggleBuffered();
}
}
void E2wxApp::ToggleFullScreen() {
if (this->emu) {
this->emu->toggleFullScreen();
}
}

View File

@ -23,10 +23,13 @@
#include <SDL_keycode.h>
#include <wx/app.h>
#include <wx/cmdline.h>
#include <wx/timer.h>
#include <wx/string.h>
#include <filesystem>
#include <string>
@ -81,8 +84,17 @@ public:
const std::filesystem::path GetConfigDir() const;
const std::filesystem::path GetDocumentsDir() const;
void OnFnKeyPressed(const SDL_Keycode k);
bool CloseMainFrame();
bool EnsureCanQuit();
void Paste();
void CycleMonitor();
void ScreenShot();
void Reset();
void TogglePower();
void ToggleBuffered();
void ToggleFullScreen();
virtual bool OnInit() override;
virtual int OnExit() override;

View File

@ -23,22 +23,33 @@
#include "PreferencesDialog.h"
#include "gui.h"
#include <wx/menu.h>
#include <wx/accel.h>
#include <wx/msgdlg.h>
#include <wx/event.h>
#include <wx/persist/toplevel.h>
enum E2MenuID {
ID_MENUITEM_POWER = wxID_HIGHEST+1
ID_MENUITEM_POWER = wxID_HIGHEST+1,
ID_MENUITEM_CYCLE_MONITOR,
ID_MENUITEM_TOGGLE_FULL_SCREEN,
ID_MENUITEM_RESET,
ID_MENUITEM_SCREEN_SHOT,
ID_MENUITEM_TOGGLE_BUFFERED,
};
wxBEGIN_EVENT_TABLE(E2wxFrame, wxFrame)
EVT_CLOSE(E2wxFrame::HandleUserQuitRequest)
EVT_MENU(wxID_EXIT, E2wxFrame::OnExit)
EVT_MENU(wxID_PREFERENCES, E2wxFrame::OnPreferences)
EVT_MENU(wxID_ABOUT, E2wxFrame::OnAbout)
EVT_MENU(ID_MENUITEM_POWER, E2wxFrame::OnTogglePower)
EVT_CLOSE(E2wxFrame::HandleUserQuitRequest)
EVT_MENU(ID_MENUITEM_CYCLE_MONITOR, E2wxFrame::OnCycleMonitor)
EVT_MENU(ID_MENUITEM_TOGGLE_FULL_SCREEN, E2wxFrame::OnToggleFullScreen)
EVT_MENU(ID_MENUITEM_RESET, E2wxFrame::OnReset)
EVT_MENU(wxID_PASTE, E2wxFrame::OnPaste)
EVT_MENU(ID_MENUITEM_SCREEN_SHOT, E2wxFrame::OnScreenShot)
EVT_MENU(ID_MENUITEM_TOGGLE_BUFFERED, E2wxFrame::OnToggleBuffered)
wxEND_EVENT_TABLE()
@ -49,6 +60,8 @@ E2wxFrame::E2wxFrame() : wxFrame(nullptr, wxID_ANY, "epple2") {
E2wxFrame::~E2wxFrame() {
}
void E2wxFrame::DoInit() {
InitMenuBar();
InitStatusBar();
@ -65,15 +78,37 @@ void E2wxFrame::InitMenuBar() {
wxMenu *menuFile = new wxMenu();
menuBar->Append(menuFile, "&File");
menuFile->Append(wxID_EXIT);
wxMenuItem *miExit = menuFile->Append(wxID_EXIT);
miExit->AddExtraAccel(wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F9));
wxMenu *menuEdit = new wxMenu();
menuBar->Append(menuEdit, "&Edit");
menuEdit->Append(wxID_PREFERENCES);
wxMenuItem *miPaste = menuEdit->Append(wxID_PASTE);
miPaste->AddExtraAccel(wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F7));
menuEdit->AppendSeparator();
wxMenuItem *miPrefs = menuEdit->Append(wxID_PREFERENCES);
miPrefs->SetAccel(new wxAcceleratorEntry(wxACCEL_CTRL, ','));
wxMenu *menuMachine = new wxMenu();
menuBar->Append(menuMachine, "&Machine");
menuMachine->Append(ID_MENUITEM_POWER, "Toggle Power");
wxMenuItem *miPower = menuMachine->Append(ID_MENUITEM_POWER, "Toggle Power");
miPower->SetAccel(new wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F1));
wxMenuItem *miReset = menuMachine->Append(ID_MENUITEM_RESET, "Reset");
miReset->SetAccel(new wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F6));
menuMachine->AppendSeparator();
wxMenuItem *miBuffered = menuMachine->Append(ID_MENUITEM_TOGGLE_BUFFERED, "Toggle Keyboard Buffer");
miBuffered->SetAccel(new wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F12));
wxMenu *menuMonitor = new wxMenu();
menuBar->Append(menuMonitor, "Mo&nitor");
wxMenuItem *miCycleMonitor = menuMonitor->Append(ID_MENUITEM_CYCLE_MONITOR, "Cycle Type");
miCycleMonitor->SetAccel(new wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F2));
wxMenuItem *miToggleFullScreen = menuMonitor->Append(ID_MENUITEM_TOGGLE_FULL_SCREEN, "Toggle Full Screen");
miToggleFullScreen->SetAccel(new wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F3));
menuMonitor->AppendSeparator();
wxMenuItem *miScreenShot = menuMonitor->Append(ID_MENUITEM_SCREEN_SHOT, "Screen Shot!");
miScreenShot->SetAccel(new wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F8));
wxMenu *menuHelp = new wxMenu();
menuBar->Append(menuHelp, "&Help");
@ -87,10 +122,27 @@ void E2wxFrame::InitStatusBar() {
void E2wxFrame::HandleUserQuitRequest(wxCloseEvent& event) {
// TODO how to handle event.CanVeto() ? I'd like to auto-save everything
if (wxGetApp().EnsureCanQuit()) {
event.Skip();
} else {
event.Veto();
}
}
void E2wxFrame::OnExit(wxCommandEvent& event) {
Close(false);
}
void E2wxFrame::OnPreferences(wxCommandEvent& event) {
PreferencesDialog *dlg = new PreferencesDialog(this);
dlg->OnInit();
dlg->ShowModal();
}
void E2wxFrame::OnAbout(wxCommandEvent& event) {
wxString msg = "";
@ -104,21 +156,34 @@ void E2wxFrame::OnAbout(wxCommandEvent& event) {
wxMessageBox(msg, "About "+wxGetApp().GetID(), wxOK | wxICON_INFORMATION);
}
void E2wxFrame::OnPreferences(wxCommandEvent& event) {
PreferencesDialog *dlg = new PreferencesDialog(this);
dlg->OnInit();
dlg->ShowModal();
}
void E2wxFrame::OnTogglePower(wxCommandEvent& event) {
GUI::queueTogglePower();
}
void E2wxFrame::HandleUserQuitRequest(wxCloseEvent& event) {
// TODO how to handle event.CanVeto() ? I'd like to auto-save everything
if (wxGetApp().EnsureCanQuit()) {
event.Skip();
} else {
event.Veto();
}
void E2wxFrame::OnCycleMonitor(wxCommandEvent& event) {
wxGetApp().CycleMonitor();
}
void E2wxFrame::OnToggleFullScreen(wxCommandEvent& event) {
wxGetApp().ToggleFullScreen();
}
void E2wxFrame::OnReset(wxCommandEvent& event) {
wxGetApp().Reset();
}
void E2wxFrame::OnPaste(wxCommandEvent& event) {
wxGetApp().Paste();
}
void E2wxFrame::OnScreenShot(wxCommandEvent& event) {
wxGetApp().ScreenShot();
}
void E2wxFrame::OnToggleBuffered(wxCommandEvent& event) {
wxGetApp().ToggleBuffered();
}

View File

@ -33,14 +33,22 @@ public:
void DoInit();
private:
void InitMenuBar();
void InitStatusBar();
void HandleUserQuitRequest(wxCloseEvent& event);
void OnExit(wxCommandEvent& event);
void OnPreferences(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
void OnTogglePower(wxCommandEvent& event);
void HandleUserQuitRequest(wxCloseEvent& event);
void InitMenuBar();
void InitStatusBar();
void OnTogglePower(wxCommandEvent& event);
void OnCycleMonitor(wxCommandEvent& event);
void OnToggleFullScreen(wxCommandEvent& event);
void OnReset(wxCommandEvent& event);
void OnPaste(wxCommandEvent& event);
void OnScreenShot(wxCommandEvent& event);
void OnToggleBuffered(wxCommandEvent& event);
wxDECLARE_EVENT_TABLE();
};

View File

@ -94,6 +94,7 @@ void Apple2::powerOn() {
this->video.powerOn();
this->picgen.powerOn();
this->powerUpReset.powerOn();
this->kbd.powerOn();
}
void Apple2::powerOff() {

View File

@ -27,60 +27,43 @@
#include <ctime>
static bool isKeyDown(const SDL_Keycode sym, const SDL_Keymod mod) {
return (
(sym < 0x7F || sym == SDLK_LEFT || sym == SDLK_RIGHT) &&
!(sym == SDLK_TAB || sym == SDLK_BACKQUOTE || sym == '[' || sym == '\\' || sym == SDLK_DELETE) &&
!(sym == ']' && mod & KMOD_SHIFT)
);
}
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),
skip(0),
prev_ms(SDL_GetTicks()),
command(false),
pendingCommandExit(false) {
display(screenImage),
videoStatic(display),
apple2(keypresses, paddleButtonStates, display, fhyper, buffered, screenImage),
timable(nullptr), // No ticked object (NULL pointer)
repeat(false),
keysDown(0),
prev_ms(SDL_GetTicks()),
command(false),
pendingCommandExit(false) {
}
Emulator::~Emulator() {
}
void Emulator::toggleComputerPower() {
if (this->timable == &this->videoStatic)
powerOnComputer();
else
powerOffComputer();
}
void Emulator::powerOnComputer() {
if (this->apple2.revision == 0) {
unsigned char key = 33u + rand()%94;
this->keypresses.push(key);
this->lastKeyDown = key;
}
this->apple2.powerOn();
this->screenImage.drawPower(true);
this->display.setNoise(false);
// The apple2 becomes the ticked object
this->timable = &this->apple2;
}
void Emulator::powerOffComputer() {
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;
}
void Emulator::config(E2Config& cfg) {
cfg.parse(this->apple2.ram, this->apple2.rom, this->apple2.slts, this->apple2.revision, this->screenImage, this->apple2.cassetteIn, this->apple2.cassetteOut, &this->apple2);
this->apple2.ram.dump_config();
}
void Emulator::init() {
powerOffComputer();
this->display.powerOn(true);
}
@ -120,7 +103,7 @@ void Emulator::handleAnyPendingEvents() {
// If SDL is going away...
// could be due to user closing the SDL window, pressing cmd-Q on Mac,
// ctrl-C from the command line on Linux, process being killed, etc.
handleUserQuitRequest();
wxGetApp().CloseMainFrame();
break;
case SDL_KEYDOWN:
// If we're collecting a command line for changing any
@ -130,7 +113,7 @@ void Emulator::handleAnyPendingEvents() {
else
// ...else we're collecting keypresses for the keyboard
// emulation (and thus the Apple ][ emulation itself)
dispatchKeypress(event.key);
dispatchKeyDown(event.key);
// People who have too many press-releases should be referred to as "keyboards"
break;
case SDL_KEYUP:
@ -172,27 +155,10 @@ void Emulator::tick50ms() {
handleAnyPendingEvents();
this->screenImage.displayHz((1000*CHECK_EVERY_CYCLE)/(SDL_GetTicks() - this->prev_ms));
this->prev_ms = SDL_GetTicks();
// TODO: how to check this->quit ?
}
void Emulator::dispatchKeyUp(const SDL_KeyboardEvent& keyEvent) {
SDL_Keycode sym = keyEvent.keysym.sym;
SDL_Keymod mod = (SDL_Keymod) keyEvent.keysym.mod;
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;
}
}
static bool translateKeysToAppleModernized(SDL_Keycode keycode, SDL_Keymod modifiers, unsigned char* key) {
if (keycode == SDLK_LEFT) {
*key = 8;
@ -272,109 +238,38 @@ static bool translateKeysToAppleModernized(SDL_Keycode keycode, SDL_Keymod modif
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) {
// Take real-world keystrokes from SDL and filter them to emulate the Apple ][ keyboard
void Emulator::dispatchKeyDown(const SDL_KeyboardEvent& keyEvent) {
if (keyEvent.repeat) {
return;
}
SDL_Keycode sym = keyEvent.keysym.sym;
SDL_Keymod mod = (SDL_Keymod) keyEvent.keysym.mod;
const SDL_Keycode sym = keyEvent.keysym.sym;
const SDL_Keymod mod = (SDL_Keymod) keyEvent.keysym.mod;
//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)) {
if (isKeyDown(sym, mod)) {
++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_F6) {
this->apple2.reset();
return;
} else if (sym == SDLK_F7) {
// 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) {
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) {
} else if (sym == SDLK_F5) { // TODO re-do user-entered command line
this->command = true;
this->screenImage.enterCommandMode();
return;
}// ...else exit the entire emulation
else if (sym == SDLK_F9) {
handleUserQuitRequest();
return;
}// ...else save a screen shot
else if (sym == SDLK_F8) {
this->screenImage.saveBMP();
} else if (SDLK_F1 <= sym && sym <= SDLK_F12) {
wxGetApp().OnFnKeyPressed(sym);
return;
}
unsigned char key;
const bool sendKey = translateKeysToAppleModernized(sym, mod, &key);
if (sendKey) {
//printf(" sending to apple as ASCII ------------------------------> %02X (%02X) (%d)\n", key, key | 0x80, key | 0x80);
this->keypresses.push(key);
@ -382,10 +277,27 @@ void Emulator::dispatchKeypress(const SDL_KeyboardEvent& keyEvent) {
}
}
void Emulator::dispatchKeyUp(const SDL_KeyboardEvent& keyEvent) {
const SDL_Keycode sym = keyEvent.keysym.sym;
const SDL_Keymod mod = (SDL_Keymod) keyEvent.keysym.mod;
// Collect and edit a command line typed at the bottom of the emulator
// window
if (isKeyDown(sym, mod)) {
--this->keysDown;
} else if (sym == SDLK_F10) {
// ...else if this is the emulated REPT key on the Apple keyboard...
// ...stop repeating. The key has been released
this->repeat = false;
this->rept = 0;
}
}
// TODO redo command line handling
// 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;
unsigned char key = (unsigned char) (sym & 0x7F);
@ -432,6 +344,14 @@ void Emulator::processCommand() {
cmdline.erase(cmdline.begin(), cmdline.end());
}
static int askSave() {
wxMessageDialog *dlg = new wxMessageDialog{
nullptr,
@ -471,6 +391,75 @@ bool Emulator::isSafeToQuit() {
return true;
}
void Emulator::handleUserQuitRequest() {
wxGetApp().CloseMainFrame();
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);
// The apple2 becomes the ticked object
this->timable = &this->apple2;
}
void Emulator::powerOffComputer() {
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;
}
void Emulator::paste() {
// 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);
}
}
void Emulator::monitorCycle() {
this->display.cycleType();
this->screenImage.cycleDisplayLabel();
}
void Emulator::reset() {
this->apple2.reset();
}
void Emulator::toggleBuffered() {
this->buffered.toggleBuffered();
this->screenImage.toggleKdbBufferLabel();
}
void Emulator::toggleFullScreen() {
this->screenImage.toggleFullScreen();
this->screenImage.drawPower(this->timable == &this->apple2);
}
void Emulator::screenshot() {
this->screenImage.saveBMP();
}

View File

@ -46,41 +46,40 @@ class Emulator {
Timable* timable;
bool quit;
bool repeat;
int keysDown;
int rept;
unsigned char lastKeyDown;
int skip;
Uint32 prev_ms;
bool command;
bool pendingCommandExit;
std::string cmdline;
void dispatchKeypress(const SDL_KeyboardEvent& keyEvent);
void dispatchKeyDown(const SDL_KeyboardEvent& keyEvent);
void dispatchKeyUp(const SDL_KeyboardEvent& keyEvent);
void cmdKey(const SDL_KeyboardEvent& keyEvent);
void processCommand();
void powerOnComputer();
void powerOffComputer();
void handleRepeatKey();
void handleAnyPendingEvents();
void handleUserQuitRequest();
public:
Emulator();
virtual ~Emulator();
void config(E2Config& cfg);
void init();
void powerOnComputer();
void powerOffComputer();
void toggleComputerPower();
void cycleDisplayType();
void tick50ms();
bool isSafeToQuit();
void tick50ms();
void toggleComputerPower();
void monitorCycle();
void paste();
void reset();
void toggleBuffered();
void toggleFullScreen();
void screenshot();
};
#endif

View File

@ -14,32 +14,34 @@
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 "keyboard.h"
#include "hypermode.h"
#include "keyboardbuffermode.h"
#include <cstdlib>
Keyboard::Keyboard(KeypressQueue& q, HyperMode& fhyper, KeyboardBufferMode& buffered):
Keyboard::Keyboard(KeypressQueue& q, HyperMode& fhyper, KeyboardBufferMode& buffered) :
keys(q),
fhyper(fhyper),
buffered(buffered),
latch(0xC1u), // TODO: randomize this a little
cGet(0)
{
latch(0),
cGet(0) {
}
void Keyboard::clear()
{
void Keyboard::powerOn() {
this->latch = 0xA1u + std::rand() % (0xFEu-0xA1+1u);
}
void Keyboard::clear() {
this->latch &= 0x7F;
}
unsigned char Keyboard::get()
{
unsigned char Keyboard::get() {
waitIfTooFast();
if (!this->buffered.isBuffered() || !(this->latch & 0x80))
{
if (!this->keys.empty())
{
if (!this->buffered.isBuffered() || !(this->latch & 0x80)) {
if (!this->keys.empty()) {
this->latch = this->keys.front() | 0x80;
this->keys.pop();
}
@ -47,28 +49,27 @@ unsigned char Keyboard::get()
return this->latch;
}
void Keyboard::waitIfTooFast()
{
if (this->fhyper.isHyper())
{
return;
}
void Keyboard::waitIfTooFast() {
// TODO remove all hyper stuff; it doesn't do anything anymore,
// since the new architecture with wxTimer
++this->cGet;
if (!this->cGet)
{
if (SDL_GetTicks() - this->lastGet <= 1000)
{
/*
* Check every 256 gets to see if they are
* happening too fast (within one second).
* If so, it means we are probably just
* looping waiting for a keypress, so
* wait a millisecond (or so) just to
* prevent us from using 100% of CPU time.
*/
SDL_Delay(1);
}
}
this->lastGet = SDL_GetTicks();
// if (this->fhyper.isHyper()) {
// return;
// }
//
// ++this->cGet;
// if (!this->cGet) {
// if (SDL_GetTicks() - this->lastGet <= 1000) {
// /*
// * Check every 256 gets to see if they are
// * happening too fast (within one second).
// * If so, it means we are probably just
// * looping waiting for a keypress, so
// * wait a millisecond (or so) just to
// * prevent us from using 100% of CPU time.
// */
// SDL_Delay(1);
// }
// }
// this->lastGet = SDL_GetTicks();
}

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/>.
*/
*/
#ifndef KEYBOARD_H
#define KEYBOARD_H
@ -26,9 +26,7 @@ typedef std::queue<unsigned char> KeypressQueue;
class HyperMode;
class KeyboardBufferMode;
class Keyboard
{
private:
class Keyboard {
KeypressQueue& keys;
HyperMode& fhyper;
KeyboardBufferMode& buffered;
@ -41,6 +39,7 @@ private:
public:
Keyboard(KeypressQueue& q, HyperMode& fhyper, KeyboardBufferMode& buffered);
void powerOn();
void clear();
unsigned char get();
};