add wx menu handling for F1,F7,F9; fix initial value (random) of keyboard latch

This commit is contained in:
Christopher A. Mosher 2022-12-12 13:03:30 -05:00
parent 7552b0ce11
commit b064d06efd
9 changed files with 91 additions and 76 deletions

View File

@ -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();
}
}

View File

@ -83,6 +83,7 @@ public:
bool CloseMainFrame();
bool EnsureCanQuit();
void Paste();
virtual bool OnInit() override;
virtual int OnExit() override;

View File

@ -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();

View File

@ -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);

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

@ -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);
}
}

View File

@ -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

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();
};