mirror of
https://github.com/cmosher01/Epple-II.git
synced 2024-12-27 02:32:27 +00:00
Move FN key handling from SDL to main App, and add menu items for them
This commit is contained in:
parent
b064d06efd
commit
498edf22e1
@ -28,6 +28,8 @@
|
|||||||
#include "e2const.h"
|
#include "e2const.h"
|
||||||
|
|
||||||
#include <wx/app.h>
|
#include <wx/app.h>
|
||||||
|
#include <wx/uiaction.h>
|
||||||
|
#include <wx/window.h>
|
||||||
#include <wx/xrc/xmlres.h>
|
#include <wx/xrc/xmlres.h>
|
||||||
#include <wx/fileconf.h>
|
#include <wx/fileconf.h>
|
||||||
#include <wx/log.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 E2wxApp::CloseMainFrame() {
|
||||||
bool r = false;
|
bool r = false;
|
||||||
if (this->frame) {
|
if (this->frame) {
|
||||||
@ -365,6 +395,8 @@ void E2wxApp::StartEmulator() {
|
|||||||
this->emu_timer->begin();
|
this->emu_timer->begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool E2wxApp::EnsureCanQuit() {
|
bool E2wxApp::EnsureCanQuit() {
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
if (this->emu) {
|
if (this->emu) {
|
||||||
@ -375,6 +407,42 @@ bool E2wxApp::EnsureCanQuit() {
|
|||||||
|
|
||||||
void E2wxApp::Paste() {
|
void E2wxApp::Paste() {
|
||||||
if (this->emu) {
|
if (this->emu) {
|
||||||
this->emu->handlePaste();
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -23,10 +23,13 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <SDL_keycode.h>
|
||||||
|
|
||||||
#include <wx/app.h>
|
#include <wx/app.h>
|
||||||
#include <wx/cmdline.h>
|
#include <wx/cmdline.h>
|
||||||
#include <wx/timer.h>
|
#include <wx/timer.h>
|
||||||
#include <wx/string.h>
|
#include <wx/string.h>
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -81,9 +84,17 @@ public:
|
|||||||
const std::filesystem::path GetConfigDir() const;
|
const std::filesystem::path GetConfigDir() const;
|
||||||
const std::filesystem::path GetDocumentsDir() const;
|
const std::filesystem::path GetDocumentsDir() const;
|
||||||
|
|
||||||
|
void OnFnKeyPressed(const SDL_Keycode k);
|
||||||
|
|
||||||
bool CloseMainFrame();
|
bool CloseMainFrame();
|
||||||
bool EnsureCanQuit();
|
bool EnsureCanQuit();
|
||||||
void Paste();
|
void Paste();
|
||||||
|
void CycleMonitor();
|
||||||
|
void ScreenShot();
|
||||||
|
void Reset();
|
||||||
|
void TogglePower();
|
||||||
|
void ToggleBuffered();
|
||||||
|
void ToggleFullScreen();
|
||||||
|
|
||||||
virtual bool OnInit() override;
|
virtual bool OnInit() override;
|
||||||
virtual int OnExit() override;
|
virtual int OnExit() override;
|
||||||
|
@ -30,16 +30,26 @@
|
|||||||
|
|
||||||
|
|
||||||
enum E2MenuID {
|
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)
|
wxBEGIN_EVENT_TABLE(E2wxFrame, wxFrame)
|
||||||
|
EVT_CLOSE(E2wxFrame::HandleUserQuitRequest)
|
||||||
EVT_MENU(wxID_EXIT, E2wxFrame::OnExit)
|
EVT_MENU(wxID_EXIT, E2wxFrame::OnExit)
|
||||||
EVT_MENU(wxID_PASTE, E2wxFrame::OnPaste)
|
|
||||||
EVT_MENU(wxID_PREFERENCES, E2wxFrame::OnPreferences)
|
EVT_MENU(wxID_PREFERENCES, E2wxFrame::OnPreferences)
|
||||||
EVT_MENU(wxID_ABOUT, E2wxFrame::OnAbout)
|
EVT_MENU(wxID_ABOUT, E2wxFrame::OnAbout)
|
||||||
EVT_MENU(ID_MENUITEM_POWER, E2wxFrame::OnTogglePower)
|
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()
|
wxEND_EVENT_TABLE()
|
||||||
|
|
||||||
|
|
||||||
@ -50,6 +60,8 @@ E2wxFrame::E2wxFrame() : wxFrame(nullptr, wxID_ANY, "epple2") {
|
|||||||
E2wxFrame::~E2wxFrame() {
|
E2wxFrame::~E2wxFrame() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void E2wxFrame::DoInit() {
|
void E2wxFrame::DoInit() {
|
||||||
InitMenuBar();
|
InitMenuBar();
|
||||||
InitStatusBar();
|
InitStatusBar();
|
||||||
@ -74,12 +86,29 @@ void E2wxFrame::InitMenuBar() {
|
|||||||
wxMenuItem *miPaste = menuEdit->Append(wxID_PASTE);
|
wxMenuItem *miPaste = menuEdit->Append(wxID_PASTE);
|
||||||
miPaste->AddExtraAccel(wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F7));
|
miPaste->AddExtraAccel(wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F7));
|
||||||
menuEdit->AppendSeparator();
|
menuEdit->AppendSeparator();
|
||||||
menuEdit->Append(wxID_PREFERENCES);
|
wxMenuItem *miPrefs = menuEdit->Append(wxID_PREFERENCES);
|
||||||
|
miPrefs->SetAccel(new wxAcceleratorEntry(wxACCEL_CTRL, ','));
|
||||||
|
|
||||||
|
|
||||||
wxMenu *menuMachine = new wxMenu();
|
wxMenu *menuMachine = new wxMenu();
|
||||||
menuBar->Append(menuMachine, "&Machine");
|
menuBar->Append(menuMachine, "&Machine");
|
||||||
wxMenuItem *miPower = menuMachine->Append(ID_MENUITEM_POWER, "Toggle Power");
|
wxMenuItem *miPower = menuMachine->Append(ID_MENUITEM_POWER, "Toggle Power");
|
||||||
miPower->SetAccel(new wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F1));
|
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();
|
wxMenu *menuHelp = new wxMenu();
|
||||||
menuBar->Append(menuHelp, "&Help");
|
menuBar->Append(menuHelp, "&Help");
|
||||||
@ -93,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) {
|
void E2wxFrame::OnExit(wxCommandEvent& event) {
|
||||||
Close(false);
|
Close(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void E2wxFrame::OnPreferences(wxCommandEvent& event) {
|
||||||
|
PreferencesDialog *dlg = new PreferencesDialog(this);
|
||||||
|
dlg->OnInit();
|
||||||
|
dlg->ShowModal();
|
||||||
|
}
|
||||||
|
|
||||||
void E2wxFrame::OnAbout(wxCommandEvent& event) {
|
void E2wxFrame::OnAbout(wxCommandEvent& event) {
|
||||||
wxString msg = "";
|
wxString msg = "";
|
||||||
|
|
||||||
@ -110,25 +156,34 @@ void E2wxFrame::OnAbout(wxCommandEvent& event) {
|
|||||||
wxMessageBox(msg, "About "+wxGetApp().GetID(), wxOK | wxICON_INFORMATION);
|
wxMessageBox(msg, "About "+wxGetApp().GetID(), wxOK | wxICON_INFORMATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
void E2wxFrame::OnPaste(wxCommandEvent& event) {
|
|
||||||
wxGetApp().Paste();
|
|
||||||
}
|
|
||||||
|
|
||||||
void E2wxFrame::OnPreferences(wxCommandEvent& event) {
|
|
||||||
PreferencesDialog *dlg = new PreferencesDialog(this);
|
|
||||||
dlg->OnInit();
|
|
||||||
dlg->ShowModal();
|
|
||||||
}
|
|
||||||
|
|
||||||
void E2wxFrame::OnTogglePower(wxCommandEvent& event) {
|
void E2wxFrame::OnTogglePower(wxCommandEvent& event) {
|
||||||
GUI::queueTogglePower();
|
GUI::queueTogglePower();
|
||||||
}
|
}
|
||||||
|
|
||||||
void E2wxFrame::HandleUserQuitRequest(wxCloseEvent& event) {
|
void E2wxFrame::OnCycleMonitor(wxCommandEvent& event) {
|
||||||
// TODO how to handle event.CanVeto() ? I'd like to auto-save everything
|
wxGetApp().CycleMonitor();
|
||||||
if (wxGetApp().EnsureCanQuit()) {
|
|
||||||
event.Skip();
|
|
||||||
} else {
|
|
||||||
event.Veto();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,16 +33,23 @@ public:
|
|||||||
void DoInit();
|
void DoInit();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OnExit(wxCommandEvent& event);
|
|
||||||
void OnPaste(wxCommandEvent& event);
|
|
||||||
void OnPreferences(wxCommandEvent& event);
|
|
||||||
void OnAbout(wxCommandEvent& event);
|
|
||||||
void OnTogglePower(wxCommandEvent& event);
|
|
||||||
void HandleUserQuitRequest(wxCloseEvent& event);
|
|
||||||
|
|
||||||
void InitMenuBar();
|
void InitMenuBar();
|
||||||
void InitStatusBar();
|
void InitStatusBar();
|
||||||
|
|
||||||
|
void HandleUserQuitRequest(wxCloseEvent& event);
|
||||||
|
|
||||||
|
void OnExit(wxCommandEvent& event);
|
||||||
|
void OnPreferences(wxCommandEvent& event);
|
||||||
|
void OnAbout(wxCommandEvent& event);
|
||||||
|
|
||||||
|
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();
|
wxDECLARE_EVENT_TABLE();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
252
src/emulator.cpp
252
src/emulator.cpp
@ -27,48 +27,39 @@
|
|||||||
|
|
||||||
#include <ctime>
|
#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() :
|
Emulator::Emulator() :
|
||||||
display(screenImage),
|
display(screenImage),
|
||||||
videoStatic(display),
|
videoStatic(display),
|
||||||
apple2(keypresses, paddleButtonStates, display, fhyper, buffered, screenImage),
|
apple2(keypresses, paddleButtonStates, display, fhyper, buffered, screenImage),
|
||||||
timable(0), // No ticked object (NULL pointer)
|
timable(nullptr), // No ticked object (NULL pointer)
|
||||||
quit(false),
|
repeat(false),
|
||||||
repeat(false),
|
keysDown(0),
|
||||||
keysDown(0),
|
prev_ms(SDL_GetTicks()),
|
||||||
skip(0),
|
command(false),
|
||||||
prev_ms(SDL_GetTicks()),
|
pendingCommandExit(false) {
|
||||||
command(false),
|
|
||||||
pendingCommandExit(false) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Emulator::~Emulator() {
|
Emulator::~Emulator() {
|
||||||
}
|
}
|
||||||
|
|
||||||
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::config(E2Config& cfg) {
|
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);
|
cfg.parse(this->apple2.ram, this->apple2.rom, this->apple2.slts, this->apple2.revision, this->screenImage, this->apple2.cassetteIn, this->apple2.cassetteOut, &this->apple2);
|
||||||
@ -112,7 +103,7 @@ void Emulator::handleAnyPendingEvents() {
|
|||||||
// If SDL is going away...
|
// If SDL is going away...
|
||||||
// could be due to user closing the SDL window, pressing cmd-Q on Mac,
|
// 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.
|
// ctrl-C from the command line on Linux, process being killed, etc.
|
||||||
handleUserQuitRequest();
|
wxGetApp().CloseMainFrame();
|
||||||
break;
|
break;
|
||||||
case SDL_KEYDOWN:
|
case SDL_KEYDOWN:
|
||||||
// If we're collecting a command line for changing any
|
// If we're collecting a command line for changing any
|
||||||
@ -122,7 +113,7 @@ void Emulator::handleAnyPendingEvents() {
|
|||||||
else
|
else
|
||||||
// ...else we're collecting keypresses for the keyboard
|
// ...else we're collecting keypresses for the keyboard
|
||||||
// emulation (and thus the Apple ][ emulation itself)
|
// 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"
|
// People who have too many press-releases should be referred to as "keyboards"
|
||||||
break;
|
break;
|
||||||
case SDL_KEYUP:
|
case SDL_KEYUP:
|
||||||
@ -164,27 +155,10 @@ void Emulator::tick50ms() {
|
|||||||
handleAnyPendingEvents();
|
handleAnyPendingEvents();
|
||||||
this->screenImage.displayHz((1000*CHECK_EVERY_CYCLE)/(SDL_GetTicks() - this->prev_ms));
|
this->screenImage.displayHz((1000*CHECK_EVERY_CYCLE)/(SDL_GetTicks() - this->prev_ms));
|
||||||
this->prev_ms = SDL_GetTicks();
|
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) {
|
static bool translateKeysToAppleModernized(SDL_Keycode keycode, SDL_Keymod modifiers, unsigned char* key) {
|
||||||
if (keycode == SDLK_LEFT) {
|
if (keycode == SDLK_LEFT) {
|
||||||
*key = 8;
|
*key = 8;
|
||||||
@ -264,101 +238,38 @@ static bool translateKeysToAppleModernized(SDL_Keycode keycode, SDL_Keymod modif
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Take real-world keystrokes from SDL and filter them to emulate the Apple ][ keyboard
|
||||||
|
void Emulator::dispatchKeyDown(const SDL_KeyboardEvent& keyEvent) {
|
||||||
// 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) {
|
if (keyEvent.repeat) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Keycode sym = keyEvent.keysym.sym;
|
const SDL_Keycode sym = keyEvent.keysym.sym;
|
||||||
SDL_Keymod mod = (SDL_Keymod) keyEvent.keysym.mod;
|
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));
|
//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) &&
|
if (isKeyDown(sym, mod)) {
|
||||||
!(sym == SDLK_TAB || sym == SDLK_BACKQUOTE || sym == '[' || sym == '\\' || sym == SDLK_DELETE) &&
|
|
||||||
!(sym == ']' && mod & KMOD_SHIFT)) {
|
|
||||||
++this->keysDown;
|
++this->keysDown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sym == SDLK_F10) {
|
||||||
|
|
||||||
/*
|
|
||||||
* First handle the key presses that are for commands, as opposed to
|
|
||||||
* simple key-presses that we send to the apple.
|
|
||||||
*/
|
|
||||||
// TODO remove all function key handling from here, and
|
|
||||||
// instead redirect them to the main frame, which will call back
|
|
||||||
// our appropriate handler functions
|
|
||||||
// Note: REPT key is special (need to track key-up event)
|
|
||||||
if (sym == SDLK_F6) {
|
|
||||||
this->apple2.reset();
|
|
||||||
return;
|
|
||||||
} else if (sym == SDLK_F7) {
|
|
||||||
handlePaste();
|
|
||||||
return;
|
|
||||||
}// ...else if this is the emulated REPT key on the Apple keyboard...
|
|
||||||
else if (sym == SDLK_F10) {
|
|
||||||
// ...start auto-repeat
|
// ...start auto-repeat
|
||||||
this->repeat = true;
|
this->repeat = true;
|
||||||
this->rept = CYCLES_PER_REPT;
|
this->rept = CYCLES_PER_REPT;
|
||||||
return;
|
return;
|
||||||
}// ...else if the user wants to run at full speed instead of emulating
|
} else if (sym == SDLK_F5) { // TODO re-do user-entered command line
|
||||||
// the Apple's speed...
|
|
||||||
else if (sym == SDLK_F11) { // TODO remove hyper
|
|
||||||
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) { // TODO remove bleed-down
|
|
||||||
this->display.toggleBleedDown();
|
|
||||||
this->screenImage.toggleFillLinesLabel();
|
|
||||||
return;
|
|
||||||
}// ...else initiate command line entry at the bottom of the emulator window
|
|
||||||
else if (sym == SDLK_F5) { // TODO re-do user-entered command line
|
|
||||||
this->command = true;
|
this->command = true;
|
||||||
this->screenImage.enterCommandMode();
|
this->screenImage.enterCommandMode();
|
||||||
return;
|
return;
|
||||||
}// ...else exit the entire emulation
|
} else if (SDLK_F1 <= sym && sym <= SDLK_F12) {
|
||||||
else if (sym == SDLK_F9) {
|
wxGetApp().OnFnKeyPressed(sym);
|
||||||
handleUserQuitRequest();
|
|
||||||
return;
|
|
||||||
}// ...else save a screen shot
|
|
||||||
else if (sym == SDLK_F8) {
|
|
||||||
this->screenImage.saveBMP();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned char key;
|
unsigned char key;
|
||||||
const bool sendKey = translateKeysToAppleModernized(sym, mod, &key);
|
const bool sendKey = translateKeysToAppleModernized(sym, mod, &key);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (sendKey) {
|
if (sendKey) {
|
||||||
//printf(" sending to apple as ASCII ------------------------------> %02X (%02X) (%d)\n", key, key | 0x80, key | 0x80);
|
//printf(" sending to apple as ASCII ------------------------------> %02X (%02X) (%d)\n", key, key | 0x80, key | 0x80);
|
||||||
this->keypresses.push(key);
|
this->keypresses.push(key);
|
||||||
@ -366,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
|
if (isKeyDown(sym, mod)) {
|
||||||
// window
|
--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) {
|
void Emulator::cmdKey(const SDL_KeyboardEvent& keyEvent) {
|
||||||
SDL_Keycode sym = keyEvent.keysym.sym;
|
SDL_Keycode sym = keyEvent.keysym.sym;
|
||||||
unsigned char key = (unsigned char) (sym & 0x7F);
|
unsigned char key = (unsigned char) (sym & 0x7F);
|
||||||
@ -416,6 +344,14 @@ void Emulator::processCommand() {
|
|||||||
cmdline.erase(cmdline.begin(), cmdline.end());
|
cmdline.erase(cmdline.begin(), cmdline.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int askSave() {
|
static int askSave() {
|
||||||
wxMessageDialog *dlg = new wxMessageDialog{
|
wxMessageDialog *dlg = new wxMessageDialog{
|
||||||
nullptr,
|
nullptr,
|
||||||
@ -455,11 +391,42 @@ bool Emulator::isSafeToQuit() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Emulator::handleUserQuitRequest() {
|
|
||||||
wxGetApp().CloseMainFrame();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Emulator::toggleComputerPower() {
|
||||||
|
if (this->timable == &this->videoStatic)
|
||||||
|
powerOnComputer();
|
||||||
|
else
|
||||||
|
powerOffComputer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Emulator::handlePaste() {
|
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
|
// Feed input from the clipboard to the Apple keyboard
|
||||||
std::string s = this->clip.getText();
|
std::string s = this->clip.getText();
|
||||||
for (unsigned int i = 0; i < s.length(); ++i) {
|
for (unsigned int i = 0; i < s.length(); ++i) {
|
||||||
@ -473,3 +440,26 @@ void Emulator::handlePaste() {
|
|||||||
this->keypresses.push(key);
|
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();
|
||||||
|
}
|
||||||
|
@ -46,18 +46,16 @@ class Emulator {
|
|||||||
|
|
||||||
Timable* timable;
|
Timable* timable;
|
||||||
|
|
||||||
bool quit;
|
|
||||||
bool repeat;
|
bool repeat;
|
||||||
int keysDown;
|
int keysDown;
|
||||||
int rept;
|
int rept;
|
||||||
unsigned char lastKeyDown;
|
unsigned char lastKeyDown;
|
||||||
int skip;
|
|
||||||
Uint32 prev_ms;
|
Uint32 prev_ms;
|
||||||
bool command;
|
bool command;
|
||||||
bool pendingCommandExit;
|
bool pendingCommandExit;
|
||||||
std::string cmdline;
|
std::string cmdline;
|
||||||
|
|
||||||
void dispatchKeypress(const SDL_KeyboardEvent& keyEvent);
|
void dispatchKeyDown(const SDL_KeyboardEvent& keyEvent);
|
||||||
void dispatchKeyUp(const SDL_KeyboardEvent& keyEvent);
|
void dispatchKeyUp(const SDL_KeyboardEvent& keyEvent);
|
||||||
void cmdKey(const SDL_KeyboardEvent& keyEvent);
|
void cmdKey(const SDL_KeyboardEvent& keyEvent);
|
||||||
void processCommand();
|
void processCommand();
|
||||||
@ -66,19 +64,22 @@ class Emulator {
|
|||||||
|
|
||||||
void handleRepeatKey();
|
void handleRepeatKey();
|
||||||
void handleAnyPendingEvents();
|
void handleAnyPendingEvents();
|
||||||
void handleUserQuitRequest();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Emulator();
|
Emulator();
|
||||||
virtual ~Emulator();
|
virtual ~Emulator();
|
||||||
|
|
||||||
void config(E2Config& cfg);
|
void config(E2Config& cfg);
|
||||||
|
|
||||||
void tick50ms();
|
void tick50ms();
|
||||||
|
bool isSafeToQuit();
|
||||||
|
|
||||||
void toggleComputerPower();
|
void toggleComputerPower();
|
||||||
void handlePaste();
|
void monitorCycle();
|
||||||
bool isSafeToQuit();
|
void paste();
|
||||||
|
void reset();
|
||||||
|
void toggleBuffered();
|
||||||
|
void toggleFullScreen();
|
||||||
|
void screenshot();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user