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();
|
||||
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();
|
||||
|
@ -373,3 +372,9 @@ bool E2wxApp::EnsureCanQuit() {
|
|||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
void E2wxApp::Paste() {
|
||||
if (this->emu) {
|
||||
this->emu->handlePaste();
|
||||
}
|
||||
}
|
|
@ -83,6 +83,7 @@ public:
|
|||
|
||||
bool CloseMainFrame();
|
||||
bool EnsureCanQuit();
|
||||
void Paste();
|
||||
|
||||
virtual bool OnInit() override;
|
||||
virtual int OnExit() override;
|
||||
|
|
|
@ -23,18 +23,19 @@
|
|||
#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
|
||||
};
|
||||
|
||||
wxBEGIN_EVENT_TABLE(E2wxFrame, wxFrame)
|
||||
EVT_MENU(wxID_EXIT, E2wxFrame::OnExit)
|
||||
EVT_MENU(wxID_PASTE, E2wxFrame::OnPaste)
|
||||
EVT_MENU(wxID_PREFERENCES, E2wxFrame::OnPreferences)
|
||||
EVT_MENU(wxID_ABOUT, E2wxFrame::OnAbout)
|
||||
EVT_MENU(ID_MENUITEM_POWER, E2wxFrame::OnTogglePower)
|
||||
|
@ -65,15 +66,20 @@ 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");
|
||||
wxMenuItem *miPaste = menuEdit->Append(wxID_PASTE);
|
||||
miPaste->AddExtraAccel(wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F7));
|
||||
menuEdit->AppendSeparator();
|
||||
menuEdit->Append(wxID_PREFERENCES);
|
||||
|
||||
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));
|
||||
|
||||
wxMenu *menuHelp = new wxMenu();
|
||||
menuBar->Append(menuHelp, "&Help");
|
||||
|
@ -104,6 +110,10 @@ void E2wxFrame::OnAbout(wxCommandEvent& event) {
|
|||
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();
|
||||
|
|
|
@ -34,6 +34,7 @@ public:
|
|||
|
||||
private:
|
||||
void OnExit(wxCommandEvent& event);
|
||||
void OnPaste(wxCommandEvent& event);
|
||||
void OnPreferences(wxCommandEvent& event);
|
||||
void OnAbout(wxCommandEvent& event);
|
||||
void OnTogglePower(wxCommandEvent& event);
|
||||
|
|
|
@ -94,6 +94,7 @@ void Apple2::powerOn() {
|
|||
this->video.powerOn();
|
||||
this->picgen.powerOn();
|
||||
this->powerUpReset.powerOn();
|
||||
this->kbd.powerOn();
|
||||
}
|
||||
|
||||
void Apple2::powerOff() {
|
||||
|
|
|
@ -52,11 +52,6 @@ void Emulator::toggleComputerPower() {
|
|||
}
|
||||
|
||||
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);
|
||||
|
@ -78,9 +73,6 @@ void Emulator::powerOffComputer() {
|
|||
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);
|
||||
}
|
||||
|
@ -299,23 +291,15 @@ void Emulator::dispatchKeypress(const SDL_KeyboardEvent& keyEvent) {
|
|||
* 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) {
|
||||
// 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);
|
||||
}
|
||||
handlePaste();
|
||||
return;
|
||||
}// ...else if this is the emulated REPT key on the Apple keyboard...
|
||||
else if (sym == SDLK_F10) {
|
||||
|
@ -325,7 +309,7 @@ void Emulator::dispatchKeypress(const SDL_KeyboardEvent& keyEvent) {
|
|||
return;
|
||||
}// ...else if the user wants to run at full speed instead of emulating
|
||||
// the Apple's speed...
|
||||
else if (sym == SDLK_F11) {
|
||||
else if (sym == SDLK_F11) { // TODO remove hyper
|
||||
this->fhyper.toggleHyper();
|
||||
this->screenImage.toggleHyperLabel();
|
||||
return;
|
||||
|
@ -350,12 +334,12 @@ void Emulator::dispatchKeypress(const SDL_KeyboardEvent& keyEvent) {
|
|||
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) {
|
||||
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) {
|
||||
else if (sym == SDLK_F5) { // TODO re-do user-entered command line
|
||||
this->command = true;
|
||||
this->screenImage.enterCommandMode();
|
||||
return;
|
||||
|
@ -474,3 +458,18 @@ bool Emulator::isSafeToQuit() {
|
|||
void Emulator::handleUserQuitRequest() {
|
||||
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 cmdKey(const SDL_KeyboardEvent& keyEvent);
|
||||
void processCommand();
|
||||
void powerOnComputer();
|
||||
void powerOffComputer();
|
||||
|
||||
void handleRepeatKey();
|
||||
void handleAnyPendingEvents();
|
||||
|
@ -72,15 +74,11 @@ public:
|
|||
|
||||
void config(E2Config& cfg);
|
||||
|
||||
void init();
|
||||
|
||||
void powerOnComputer();
|
||||
void powerOffComputer();
|
||||
void toggleComputerPower();
|
||||
void cycleDisplayType();
|
||||
bool isSafeToQuit();
|
||||
|
||||
void tick50ms();
|
||||
|
||||
void toggleComputerPower();
|
||||
void handlePaste();
|
||||
bool isSafeToQuit();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue