add wx menu handling for F1,F7,F9; fix initial value (random) of keyboard latch
This commit is contained in:
parent
7552b0ce11
commit
b064d06efd
|
@ -360,7 +360,6 @@ void E2wxApp::StartEmulator() {
|
||||||
this->emu = new Emulator();
|
this->emu = new Emulator();
|
||||||
E2Config cfg{this->arg_configfile, this->opt_config_from_prefs_only};
|
E2Config cfg{this->arg_configfile, this->opt_config_from_prefs_only};
|
||||||
this->emu->config(cfg);
|
this->emu->config(cfg);
|
||||||
this->emu->init();
|
|
||||||
|
|
||||||
this->emu_timer = new EmuTimer{this->emu};
|
this->emu_timer = new EmuTimer{this->emu};
|
||||||
this->emu_timer->begin();
|
this->emu_timer->begin();
|
||||||
|
@ -373,3 +372,9 @@ bool E2wxApp::EnsureCanQuit() {
|
||||||
}
|
}
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void E2wxApp::Paste() {
|
||||||
|
if (this->emu) {
|
||||||
|
this->emu->handlePaste();
|
||||||
|
}
|
||||||
|
}
|
|
@ -83,6 +83,7 @@ public:
|
||||||
|
|
||||||
bool CloseMainFrame();
|
bool CloseMainFrame();
|
||||||
bool EnsureCanQuit();
|
bool EnsureCanQuit();
|
||||||
|
void Paste();
|
||||||
|
|
||||||
virtual bool OnInit() override;
|
virtual bool OnInit() override;
|
||||||
virtual int OnExit() override;
|
virtual int OnExit() override;
|
||||||
|
|
|
@ -23,18 +23,19 @@
|
||||||
#include "PreferencesDialog.h"
|
#include "PreferencesDialog.h"
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
#include <wx/menu.h>
|
#include <wx/menu.h>
|
||||||
|
#include <wx/accel.h>
|
||||||
#include <wx/msgdlg.h>
|
#include <wx/msgdlg.h>
|
||||||
#include <wx/event.h>
|
#include <wx/event.h>
|
||||||
#include <wx/persist/toplevel.h>
|
#include <wx/persist/toplevel.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
enum E2MenuID {
|
enum E2MenuID {
|
||||||
ID_MENUITEM_POWER = wxID_HIGHEST+1
|
ID_MENUITEM_POWER = wxID_HIGHEST+1
|
||||||
};
|
};
|
||||||
|
|
||||||
wxBEGIN_EVENT_TABLE(E2wxFrame, wxFrame)
|
wxBEGIN_EVENT_TABLE(E2wxFrame, wxFrame)
|
||||||
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)
|
||||||
|
@ -65,15 +66,20 @@ void E2wxFrame::InitMenuBar() {
|
||||||
|
|
||||||
wxMenu *menuFile = new wxMenu();
|
wxMenu *menuFile = new wxMenu();
|
||||||
menuBar->Append(menuFile, "&File");
|
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();
|
wxMenu *menuEdit = new wxMenu();
|
||||||
menuBar->Append(menuEdit, "&Edit");
|
menuBar->Append(menuEdit, "&Edit");
|
||||||
|
wxMenuItem *miPaste = menuEdit->Append(wxID_PASTE);
|
||||||
|
miPaste->AddExtraAccel(wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F7));
|
||||||
|
menuEdit->AppendSeparator();
|
||||||
menuEdit->Append(wxID_PREFERENCES);
|
menuEdit->Append(wxID_PREFERENCES);
|
||||||
|
|
||||||
wxMenu *menuMachine = new wxMenu();
|
wxMenu *menuMachine = new wxMenu();
|
||||||
menuBar->Append(menuMachine, "&Machine");
|
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));
|
||||||
|
|
||||||
wxMenu *menuHelp = new wxMenu();
|
wxMenu *menuHelp = new wxMenu();
|
||||||
menuBar->Append(menuHelp, "&Help");
|
menuBar->Append(menuHelp, "&Help");
|
||||||
|
@ -104,6 +110,10 @@ 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) {
|
void E2wxFrame::OnPreferences(wxCommandEvent& event) {
|
||||||
PreferencesDialog *dlg = new PreferencesDialog(this);
|
PreferencesDialog *dlg = new PreferencesDialog(this);
|
||||||
dlg->OnInit();
|
dlg->OnInit();
|
||||||
|
|
|
@ -34,6 +34,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OnExit(wxCommandEvent& event);
|
void OnExit(wxCommandEvent& event);
|
||||||
|
void OnPaste(wxCommandEvent& event);
|
||||||
void OnPreferences(wxCommandEvent& event);
|
void OnPreferences(wxCommandEvent& event);
|
||||||
void OnAbout(wxCommandEvent& event);
|
void OnAbout(wxCommandEvent& event);
|
||||||
void OnTogglePower(wxCommandEvent& event);
|
void OnTogglePower(wxCommandEvent& event);
|
||||||
|
|
|
@ -94,6 +94,7 @@ void Apple2::powerOn() {
|
||||||
this->video.powerOn();
|
this->video.powerOn();
|
||||||
this->picgen.powerOn();
|
this->picgen.powerOn();
|
||||||
this->powerUpReset.powerOn();
|
this->powerUpReset.powerOn();
|
||||||
|
this->kbd.powerOn();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Apple2::powerOff() {
|
void Apple2::powerOff() {
|
||||||
|
|
|
@ -52,11 +52,6 @@ void Emulator::toggleComputerPower() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Emulator::powerOnComputer() {
|
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->apple2.powerOn();
|
||||||
this->screenImage.drawPower(true);
|
this->screenImage.drawPower(true);
|
||||||
this->display.setNoise(false);
|
this->display.setNoise(false);
|
||||||
|
@ -78,9 +73,6 @@ void Emulator::powerOffComputer() {
|
||||||
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);
|
||||||
this->apple2.ram.dump_config();
|
this->apple2.ram.dump_config();
|
||||||
}
|
|
||||||
|
|
||||||
void Emulator::init() {
|
|
||||||
powerOffComputer();
|
powerOffComputer();
|
||||||
this->display.powerOn(true);
|
this->display.powerOn(true);
|
||||||
}
|
}
|
||||||
|
@ -299,23 +291,15 @@ void Emulator::dispatchKeypress(const SDL_KeyboardEvent& keyEvent) {
|
||||||
* First handle the key presses that are for commands, as opposed to
|
* First handle the key presses that are for commands, as opposed to
|
||||||
* simple key-presses that we send to the apple.
|
* 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) {
|
if (sym == SDLK_F6) {
|
||||||
this->apple2.reset();
|
this->apple2.reset();
|
||||||
return;
|
return;
|
||||||
} else if (sym == SDLK_F7) {
|
} else if (sym == SDLK_F7) {
|
||||||
// Feed input from the clipboard to the Apple keyboard
|
handlePaste();
|
||||||
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;
|
return;
|
||||||
}// ...else if this is the emulated REPT key on the Apple keyboard...
|
}// ...else if this is the emulated REPT key on the Apple keyboard...
|
||||||
else if (sym == SDLK_F10) {
|
else if (sym == SDLK_F10) {
|
||||||
|
@ -325,7 +309,7 @@ void Emulator::dispatchKeypress(const SDL_KeyboardEvent& keyEvent) {
|
||||||
return;
|
return;
|
||||||
}// ...else if the user wants to run at full speed instead of emulating
|
}// ...else if the user wants to run at full speed instead of emulating
|
||||||
// the Apple's speed...
|
// the Apple's speed...
|
||||||
else if (sym == SDLK_F11) {
|
else if (sym == SDLK_F11) { // TODO remove hyper
|
||||||
this->fhyper.toggleHyper();
|
this->fhyper.toggleHyper();
|
||||||
this->screenImage.toggleHyperLabel();
|
this->screenImage.toggleHyperLabel();
|
||||||
return;
|
return;
|
||||||
|
@ -350,12 +334,12 @@ void Emulator::dispatchKeypress(const SDL_KeyboardEvent& keyEvent) {
|
||||||
return;
|
return;
|
||||||
}// ...else if the user wants to switch between the interlaced extension
|
}// ...else if the user wants to switch between the interlaced extension
|
||||||
// of the display and the non-interlaced historically correct display...
|
// of the display and the non-interlaced historically correct display...
|
||||||
else if (sym == SDLK_F4) {
|
else if (sym == SDLK_F4) { // TODO remove bleed-down
|
||||||
this->display.toggleBleedDown();
|
this->display.toggleBleedDown();
|
||||||
this->screenImage.toggleFillLinesLabel();
|
this->screenImage.toggleFillLinesLabel();
|
||||||
return;
|
return;
|
||||||
}// ...else initiate command line entry at the bottom of the emulator window
|
}// ...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->command = true;
|
||||||
this->screenImage.enterCommandMode();
|
this->screenImage.enterCommandMode();
|
||||||
return;
|
return;
|
||||||
|
@ -474,3 +458,18 @@ bool Emulator::isSafeToQuit() {
|
||||||
void Emulator::handleUserQuitRequest() {
|
void Emulator::handleUserQuitRequest() {
|
||||||
wxGetApp().CloseMainFrame();
|
wxGetApp().CloseMainFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Emulator::handlePaste() {
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -61,6 +61,8 @@ class Emulator {
|
||||||
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();
|
||||||
|
void powerOnComputer();
|
||||||
|
void powerOffComputer();
|
||||||
|
|
||||||
void handleRepeatKey();
|
void handleRepeatKey();
|
||||||
void handleAnyPendingEvents();
|
void handleAnyPendingEvents();
|
||||||
|
@ -72,15 +74,11 @@ public:
|
||||||
|
|
||||||
void config(E2Config& cfg);
|
void config(E2Config& cfg);
|
||||||
|
|
||||||
void init();
|
|
||||||
|
|
||||||
void powerOnComputer();
|
|
||||||
void powerOffComputer();
|
|
||||||
void toggleComputerPower();
|
|
||||||
void cycleDisplayType();
|
|
||||||
bool isSafeToQuit();
|
|
||||||
|
|
||||||
void tick50ms();
|
void tick50ms();
|
||||||
|
|
||||||
|
void toggleComputerPower();
|
||||||
|
void handlePaste();
|
||||||
|
bool isSafeToQuit();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -14,32 +14,34 @@
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#include "keyboard.h"
|
#include "keyboard.h"
|
||||||
#include "hypermode.h"
|
#include "hypermode.h"
|
||||||
#include "keyboardbuffermode.h"
|
#include "keyboardbuffermode.h"
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
Keyboard::Keyboard(KeypressQueue& q, HyperMode& fhyper, KeyboardBufferMode& buffered):
|
|
||||||
|
|
||||||
|
Keyboard::Keyboard(KeypressQueue& q, HyperMode& fhyper, KeyboardBufferMode& buffered) :
|
||||||
keys(q),
|
keys(q),
|
||||||
fhyper(fhyper),
|
fhyper(fhyper),
|
||||||
buffered(buffered),
|
buffered(buffered),
|
||||||
latch(0xC1u), // TODO: randomize this a little
|
latch(0),
|
||||||
cGet(0)
|
cGet(0) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Keyboard::clear()
|
void Keyboard::powerOn() {
|
||||||
{
|
this->latch = 0xA1u + std::rand() % (0xFEu-0xA1+1u);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Keyboard::clear() {
|
||||||
this->latch &= 0x7F;
|
this->latch &= 0x7F;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char Keyboard::get()
|
unsigned char Keyboard::get() {
|
||||||
{
|
|
||||||
waitIfTooFast();
|
waitIfTooFast();
|
||||||
if (!this->buffered.isBuffered() || !(this->latch & 0x80))
|
if (!this->buffered.isBuffered() || !(this->latch & 0x80)) {
|
||||||
{
|
if (!this->keys.empty()) {
|
||||||
if (!this->keys.empty())
|
|
||||||
{
|
|
||||||
this->latch = this->keys.front() | 0x80;
|
this->latch = this->keys.front() | 0x80;
|
||||||
this->keys.pop();
|
this->keys.pop();
|
||||||
}
|
}
|
||||||
|
@ -47,28 +49,27 @@ unsigned char Keyboard::get()
|
||||||
return this->latch;
|
return this->latch;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Keyboard::waitIfTooFast()
|
void Keyboard::waitIfTooFast() {
|
||||||
{
|
// TODO remove all hyper stuff; it doesn't do anything anymore,
|
||||||
if (this->fhyper.isHyper())
|
// since the new architecture with wxTimer
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
++this->cGet;
|
// if (this->fhyper.isHyper()) {
|
||||||
if (!this->cGet)
|
// return;
|
||||||
{
|
// }
|
||||||
if (SDL_GetTicks() - this->lastGet <= 1000)
|
//
|
||||||
{
|
// ++this->cGet;
|
||||||
/*
|
// if (!this->cGet) {
|
||||||
* Check every 256 gets to see if they are
|
// if (SDL_GetTicks() - this->lastGet <= 1000) {
|
||||||
* happening too fast (within one second).
|
// /*
|
||||||
* If so, it means we are probably just
|
// * Check every 256 gets to see if they are
|
||||||
* looping waiting for a keypress, so
|
// * happening too fast (within one second).
|
||||||
* wait a millisecond (or so) just to
|
// * If so, it means we are probably just
|
||||||
* prevent us from using 100% of CPU time.
|
// * looping waiting for a keypress, so
|
||||||
*/
|
// * wait a millisecond (or so) just to
|
||||||
SDL_Delay(1);
|
// * prevent us from using 100% of CPU time.
|
||||||
}
|
// */
|
||||||
}
|
// SDL_Delay(1);
|
||||||
this->lastGet = SDL_GetTicks();
|
// }
|
||||||
|
// }
|
||||||
|
// this->lastGet = SDL_GetTicks();
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#ifndef KEYBOARD_H
|
#ifndef KEYBOARD_H
|
||||||
#define KEYBOARD_H
|
#define KEYBOARD_H
|
||||||
|
|
||||||
|
@ -26,9 +26,7 @@ typedef std::queue<unsigned char> KeypressQueue;
|
||||||
class HyperMode;
|
class HyperMode;
|
||||||
class KeyboardBufferMode;
|
class KeyboardBufferMode;
|
||||||
|
|
||||||
class Keyboard
|
class Keyboard {
|
||||||
{
|
|
||||||
private:
|
|
||||||
KeypressQueue& keys;
|
KeypressQueue& keys;
|
||||||
HyperMode& fhyper;
|
HyperMode& fhyper;
|
||||||
KeyboardBufferMode& buffered;
|
KeyboardBufferMode& buffered;
|
||||||
|
@ -41,6 +39,7 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Keyboard(KeypressQueue& q, HyperMode& fhyper, KeyboardBufferMode& buffered);
|
Keyboard(KeypressQueue& q, HyperMode& fhyper, KeyboardBufferMode& buffered);
|
||||||
|
void powerOn();
|
||||||
void clear();
|
void clear();
|
||||||
unsigned char get();
|
unsigned char get();
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue