Compare commits
4 Commits
498edf22e1
...
e0f4ad5ccc
Author | SHA1 | Date |
---|---|---|
Christopher A. Mosher | e0f4ad5ccc | |
Christopher A. Mosher | 7bab1ac971 | |
Christopher A. Mosher | 027248a002 | |
Christopher A. Mosher | a5c0fc047e |
|
@ -89,7 +89,6 @@ filterchroma.cpp
|
||||||
filterluma.cpp
|
filterluma.cpp
|
||||||
firmwarecard.cpp
|
firmwarecard.cpp
|
||||||
gui.cpp
|
gui.cpp
|
||||||
hypermode.cpp
|
|
||||||
keyboardbuffermode.cpp
|
keyboardbuffermode.cpp
|
||||||
keyboard.cpp
|
keyboard.cpp
|
||||||
languagecard.cpp
|
languagecard.cpp
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#include "e2const.h"
|
#include "e2const.h"
|
||||||
|
|
||||||
#include <wx/app.h>
|
#include <wx/app.h>
|
||||||
#include <wx/uiaction.h>
|
#include <wx/textdlg.h>
|
||||||
#include <wx/window.h>
|
#include <wx/window.h>
|
||||||
#include <wx/xrc/xmlres.h>
|
#include <wx/xrc/xmlres.h>
|
||||||
#include <wx/fileconf.h>
|
#include <wx/fileconf.h>
|
||||||
|
@ -151,6 +151,10 @@ bool E2wxApp::OnInit() {
|
||||||
// wxLogVerbose("%s", "verbose");
|
// wxLogVerbose("%s", "verbose");
|
||||||
// wxFile().Open("foobar.txt");
|
// wxFile().Open("foobar.txt");
|
||||||
|
|
||||||
|
// TODO wx log file window?
|
||||||
|
// TODO remove all logging from stdout/err to log file
|
||||||
|
// TODO define components to turn on/off for trace level logging (disk, cassette, woz, keyboard, ram, lss, audio, etc.)
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << "Application ID: " << this->GetID();
|
BOOST_LOG_TRIVIAL(info) << "Application ID: " << this->GetID();
|
||||||
BOOST_LOG_TRIVIAL(info) << "Application version: " << this->GetVersion();
|
BOOST_LOG_TRIVIAL(info) << "Application version: " << this->GetVersion();
|
||||||
|
|
||||||
|
@ -213,7 +217,7 @@ void E2wxApp::OnFnKeyPressed(const SDL_Keycode k) {
|
||||||
} else if (k == SDLK_F4) {
|
} else if (k == SDLK_F4) {
|
||||||
//
|
//
|
||||||
} else if (k == SDLK_F5) {
|
} else if (k == SDLK_F5) {
|
||||||
//
|
this->EmulatorCommand();
|
||||||
} else if (k == SDLK_F6) {
|
} else if (k == SDLK_F6) {
|
||||||
this->Reset();
|
this->Reset();
|
||||||
} else if (k == SDLK_F7) {
|
} else if (k == SDLK_F7) {
|
||||||
|
@ -446,3 +450,14 @@ void E2wxApp::ToggleFullScreen() {
|
||||||
this->emu->toggleFullScreen();
|
this->emu->toggleFullScreen();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const wxString message = "Enter a command for the emulator. See https://cmosher01.github.io/Epple-II/usermanual.html";
|
||||||
|
static const wxString title = "Emulator command";
|
||||||
|
void E2wxApp::EmulatorCommand() {
|
||||||
|
if (this->emu) {
|
||||||
|
wxTextEntryDialog dlg(this->frame, message, title);
|
||||||
|
if (dlg.ShowModal() == wxID_OK) {
|
||||||
|
this->emu->cmd(dlg.GetValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -95,6 +95,7 @@ public:
|
||||||
void TogglePower();
|
void TogglePower();
|
||||||
void ToggleBuffered();
|
void ToggleBuffered();
|
||||||
void ToggleFullScreen();
|
void ToggleFullScreen();
|
||||||
|
void EmulatorCommand();
|
||||||
|
|
||||||
virtual bool OnInit() override;
|
virtual bool OnInit() override;
|
||||||
virtual int OnExit() override;
|
virtual int OnExit() override;
|
||||||
|
|
|
@ -33,6 +33,7 @@ enum E2MenuID {
|
||||||
ID_MENUITEM_POWER = wxID_HIGHEST+1,
|
ID_MENUITEM_POWER = wxID_HIGHEST+1,
|
||||||
ID_MENUITEM_CYCLE_MONITOR,
|
ID_MENUITEM_CYCLE_MONITOR,
|
||||||
ID_MENUITEM_TOGGLE_FULL_SCREEN,
|
ID_MENUITEM_TOGGLE_FULL_SCREEN,
|
||||||
|
ID_MENUITEM_EMULATOR_COMMAND,
|
||||||
ID_MENUITEM_RESET,
|
ID_MENUITEM_RESET,
|
||||||
ID_MENUITEM_SCREEN_SHOT,
|
ID_MENUITEM_SCREEN_SHOT,
|
||||||
ID_MENUITEM_TOGGLE_BUFFERED,
|
ID_MENUITEM_TOGGLE_BUFFERED,
|
||||||
|
@ -46,6 +47,7 @@ wxBEGIN_EVENT_TABLE(E2wxFrame, wxFrame)
|
||||||
EVT_MENU(ID_MENUITEM_POWER, E2wxFrame::OnTogglePower)
|
EVT_MENU(ID_MENUITEM_POWER, E2wxFrame::OnTogglePower)
|
||||||
EVT_MENU(ID_MENUITEM_CYCLE_MONITOR, E2wxFrame::OnCycleMonitor)
|
EVT_MENU(ID_MENUITEM_CYCLE_MONITOR, E2wxFrame::OnCycleMonitor)
|
||||||
EVT_MENU(ID_MENUITEM_TOGGLE_FULL_SCREEN, E2wxFrame::OnToggleFullScreen)
|
EVT_MENU(ID_MENUITEM_TOGGLE_FULL_SCREEN, E2wxFrame::OnToggleFullScreen)
|
||||||
|
EVT_MENU(ID_MENUITEM_EMULATOR_COMMAND, E2wxFrame::OnEmulatorCommand)
|
||||||
EVT_MENU(ID_MENUITEM_RESET, E2wxFrame::OnReset)
|
EVT_MENU(ID_MENUITEM_RESET, E2wxFrame::OnReset)
|
||||||
EVT_MENU(wxID_PASTE, E2wxFrame::OnPaste)
|
EVT_MENU(wxID_PASTE, E2wxFrame::OnPaste)
|
||||||
EVT_MENU(ID_MENUITEM_SCREEN_SHOT, E2wxFrame::OnScreenShot)
|
EVT_MENU(ID_MENUITEM_SCREEN_SHOT, E2wxFrame::OnScreenShot)
|
||||||
|
@ -97,6 +99,9 @@ void E2wxFrame::InitMenuBar() {
|
||||||
wxMenuItem *miReset = menuMachine->Append(ID_MENUITEM_RESET, "Reset");
|
wxMenuItem *miReset = menuMachine->Append(ID_MENUITEM_RESET, "Reset");
|
||||||
miReset->SetAccel(new wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F6));
|
miReset->SetAccel(new wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F6));
|
||||||
menuMachine->AppendSeparator();
|
menuMachine->AppendSeparator();
|
||||||
|
wxMenuItem *miCmd = menuMachine->Append(ID_MENUITEM_EMULATOR_COMMAND, "Command...");
|
||||||
|
miCmd->SetAccel(new wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F5));
|
||||||
|
menuMachine->AppendSeparator();
|
||||||
wxMenuItem *miBuffered = menuMachine->Append(ID_MENUITEM_TOGGLE_BUFFERED, "Toggle Keyboard Buffer");
|
wxMenuItem *miBuffered = menuMachine->Append(ID_MENUITEM_TOGGLE_BUFFERED, "Toggle Keyboard Buffer");
|
||||||
miBuffered->SetAccel(new wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F12));
|
miBuffered->SetAccel(new wxAcceleratorEntry(wxACCEL_NORMAL, WXK_F12));
|
||||||
|
|
||||||
|
@ -170,6 +175,10 @@ void E2wxFrame::OnToggleFullScreen(wxCommandEvent& event) {
|
||||||
wxGetApp().ToggleFullScreen();
|
wxGetApp().ToggleFullScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void E2wxFrame::OnEmulatorCommand(wxCommandEvent& event) {
|
||||||
|
wxGetApp().EmulatorCommand();
|
||||||
|
}
|
||||||
|
|
||||||
void E2wxFrame::OnReset(wxCommandEvent& event) {
|
void E2wxFrame::OnReset(wxCommandEvent& event) {
|
||||||
wxGetApp().Reset();
|
wxGetApp().Reset();
|
||||||
}
|
}
|
||||||
|
@ -185,5 +194,3 @@ void E2wxFrame::OnScreenShot(wxCommandEvent& event) {
|
||||||
void E2wxFrame::OnToggleBuffered(wxCommandEvent& event) {
|
void E2wxFrame::OnToggleBuffered(wxCommandEvent& event) {
|
||||||
wxGetApp().ToggleBuffered();
|
wxGetApp().ToggleBuffered();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ private:
|
||||||
void OnTogglePower(wxCommandEvent& event);
|
void OnTogglePower(wxCommandEvent& event);
|
||||||
void OnCycleMonitor(wxCommandEvent& event);
|
void OnCycleMonitor(wxCommandEvent& event);
|
||||||
void OnToggleFullScreen(wxCommandEvent& event);
|
void OnToggleFullScreen(wxCommandEvent& event);
|
||||||
|
void OnEmulatorCommand(wxCommandEvent& event);
|
||||||
void OnReset(wxCommandEvent& event);
|
void OnReset(wxCommandEvent& event);
|
||||||
void OnPaste(wxCommandEvent& event);
|
void OnPaste(wxCommandEvent& event);
|
||||||
void OnScreenShot(wxCommandEvent& event);
|
void OnScreenShot(wxCommandEvent& event);
|
||||||
|
|
|
@ -44,8 +44,7 @@ AnalogTV::AnalogTV(ScreenImage& image):
|
||||||
image(image),
|
image(image),
|
||||||
on(false),
|
on(false),
|
||||||
noise(false),
|
noise(false),
|
||||||
type(TV_OLD_COLOR),
|
type(TV_OLD_COLOR)
|
||||||
bleed_down(true)
|
|
||||||
{
|
{
|
||||||
hirescolor.push_back(colors.c()[A2ColorsObserved::HIRES_GREEN]);
|
hirescolor.push_back(colors.c()[A2ColorsObserved::HIRES_GREEN]);
|
||||||
hirescolor.push_back(colors.c()[A2ColorsObserved::HIRES_ORANGE]);
|
hirescolor.push_back(colors.c()[A2ColorsObserved::HIRES_ORANGE]);
|
||||||
|
@ -84,13 +83,6 @@ void AnalogTV::cycleType()
|
||||||
this->type = (DisplayType)((((int)this->type)+1)%NUM_DISPLAY_TYPES);
|
this->type = (DisplayType)((((int)this->type)+1)%NUM_DISPLAY_TYPES);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnalogTV::toggleBleedDown()
|
|
||||||
{
|
|
||||||
this->bleed_down = !this->bleed_down;
|
|
||||||
this->image.blank();
|
|
||||||
this->image.notifyObservers();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -268,8 +260,7 @@ void AnalogTV::drawMonitorColor()
|
||||||
rgbv = 0xFFFFFF;
|
rgbv = 0xFFFFFF;
|
||||||
}
|
}
|
||||||
this->image.setElem(ip,rgbv);
|
this->image.setElem(ip,rgbv);
|
||||||
if (bleed_down)
|
this->image.setElem(ip+D_IP,rgbv); // display same pixel on next row
|
||||||
this->image.setElem(ip+D_IP,rgbv); // display same pixel on next row
|
|
||||||
++ip;
|
++ip;
|
||||||
}
|
}
|
||||||
ip += D_IP;
|
ip += D_IP;
|
||||||
|
@ -292,8 +283,7 @@ void AnalogTV::drawMonitorMonochrome(const unsigned int color)
|
||||||
const int is = row*AppleNTSC::H+col;
|
const int is = row*AppleNTSC::H+col;
|
||||||
const unsigned int rgb = this->signal[is] > 50 ? color : 0;
|
const unsigned int rgb = this->signal[is] > 50 ? color : 0;
|
||||||
this->image.setElem(ip,rgb);
|
this->image.setElem(ip,rgb);
|
||||||
if (bleed_down)
|
this->image.setElem(ip+D_IP,rgb);
|
||||||
this->image.setElem(ip+D_IP,rgb);
|
|
||||||
++ip;
|
++ip;
|
||||||
}
|
}
|
||||||
ip += D_IP;
|
ip += D_IP;
|
||||||
|
@ -314,8 +304,7 @@ void AnalogTV::drawTVOld()
|
||||||
{
|
{
|
||||||
const int rgb = yiq2rgb(yiq[col-348]); // shift display left 1 pixel
|
const int rgb = yiq2rgb(yiq[col-348]); // shift display left 1 pixel
|
||||||
this->image.setElem(ip,rgb);
|
this->image.setElem(ip,rgb);
|
||||||
if (bleed_down)
|
this->image.setElem(ip+D_IP,rgb);
|
||||||
this->image.setElem(ip+D_IP,rgb);
|
|
||||||
++ip;
|
++ip;
|
||||||
}
|
}
|
||||||
ip += D_IP;
|
ip += D_IP;
|
||||||
|
|
|
@ -46,7 +46,6 @@ private:
|
||||||
bool on;
|
bool on;
|
||||||
bool noise;
|
bool noise;
|
||||||
DisplayType type;
|
DisplayType type;
|
||||||
bool bleed_down;
|
|
||||||
|
|
||||||
static int* rcb;
|
static int* rcb;
|
||||||
|
|
||||||
|
@ -95,7 +94,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void powerOn(bool b);
|
void powerOn(bool b);
|
||||||
void toggleBleedDown();
|
|
||||||
void restartSignal();
|
void restartSignal();
|
||||||
void setType(DisplayType type);
|
void setType(DisplayType type);
|
||||||
void cycleType();
|
void cycleType();
|
||||||
|
|
|
@ -38,9 +38,9 @@
|
||||||
#include <istream>
|
#include <istream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
Apple2::Apple2(KeypressQueue& keypresses, PaddleButtonStates& paddleButtonStates, AnalogTV& tv, HyperMode& fhyper, KeyboardBufferMode& buffered, ScreenImage& gui) :
|
Apple2::Apple2(KeypressQueue& keypresses, PaddleButtonStates& paddleButtonStates, AnalogTV& tv, KeyboardBufferMode& buffered, ScreenImage& gui) :
|
||||||
slts(gui),
|
slts(gui),
|
||||||
kbd(keypresses, fhyper, buffered),
|
kbd(keypresses, buffered),
|
||||||
rom(AddressBus::MOTHERBOARD_ROM_SIZ),
|
rom(AddressBus::MOTHERBOARD_ROM_SIZ),
|
||||||
ram(revision),
|
ram(revision),
|
||||||
cassetteIn(gui),
|
cassetteIn(gui),
|
||||||
|
|
|
@ -63,7 +63,7 @@ class Apple2 : public Timable
|
||||||
int revision;
|
int revision;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Apple2(KeypressQueue& keypresses, PaddleButtonStates& paddleButtonStates, AnalogTV& tv, HyperMode& fhyper, KeyboardBufferMode& buffered, ScreenImage& gui);
|
Apple2(KeypressQueue& keypresses, PaddleButtonStates& paddleButtonStates, AnalogTV& tv, KeyboardBufferMode& buffered, ScreenImage& gui);
|
||||||
~Apple2();
|
~Apple2();
|
||||||
|
|
||||||
void useEpple2Cpu();
|
void useEpple2Cpu();
|
||||||
|
|
|
@ -326,7 +326,6 @@ void E2Command::tryParseLine(const std::string& line, MemoryRandomAccess& ram, M
|
||||||
void E2Command::loadDisk(Slots& slts, int slot, int drive, const std::filesystem::path &media) {
|
void E2Command::loadDisk(Slots& slts, int slot, int drive, const std::filesystem::path &media) {
|
||||||
Card* card = slts.get(slot);
|
Card* card = slts.get(slot);
|
||||||
if (!card->hasMedia()) {
|
if (!card->hasMedia()) {
|
||||||
// TODO if file doesn't exist, name still gets displayed, and there's no error message
|
|
||||||
// TODO error message
|
// TODO error message
|
||||||
// std::cerr << "Slot " << slot << " doesn't have a disk controller card" << std::endl;
|
// std::cerr << "Slot " << slot << " doesn't have a disk controller card" << std::endl;
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -18,9 +18,12 @@
|
||||||
#ifndef CONFIGEP2_H
|
#ifndef CONFIGEP2_H
|
||||||
#define CONFIGEP2_H
|
#define CONFIGEP2_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include <wx/string.h>
|
#include <wx/string.h>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class Memory;
|
class Memory;
|
||||||
class MemoryRandomAccess;
|
class MemoryRandomAccess;
|
||||||
class Slots;
|
class Slots;
|
||||||
|
@ -30,9 +33,7 @@ class CassetteOut;
|
||||||
class Apple2;
|
class Apple2;
|
||||||
|
|
||||||
|
|
||||||
// TODO split out all static things into their own class (and don't make them static)
|
|
||||||
// Remember that, besides config, also command line entry calls parseLine
|
|
||||||
// This will also help with adding menu items in place of commands
|
|
||||||
class E2Config {
|
class E2Config {
|
||||||
private:
|
private:
|
||||||
const std::filesystem::path file_path;
|
const std::filesystem::path file_path;
|
||||||
|
@ -50,4 +51,6 @@ public:
|
||||||
void parse(MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut, Apple2* apple2);
|
void parse(MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut, Apple2* apple2);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -47,13 +47,11 @@ static bool isKeyDown(const SDL_Keycode sym, const SDL_Keymod mod) {
|
||||||
Emulator::Emulator() :
|
Emulator::Emulator() :
|
||||||
display(screenImage),
|
display(screenImage),
|
||||||
videoStatic(display),
|
videoStatic(display),
|
||||||
apple2(keypresses, paddleButtonStates, display, fhyper, buffered, screenImage),
|
apple2(keypresses, paddleButtonStates, display, buffered, screenImage),
|
||||||
timable(nullptr), // No ticked object (NULL pointer)
|
timable(nullptr), // No ticked object (NULL pointer)
|
||||||
repeat(false),
|
repeat(false),
|
||||||
keysDown(0),
|
keysDown(0),
|
||||||
prev_ms(SDL_GetTicks()),
|
prev_ms(SDL_GetTicks()) {
|
||||||
command(false),
|
|
||||||
pendingCommandExit(false) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Emulator::~Emulator() {
|
Emulator::~Emulator() {
|
||||||
|
@ -106,29 +104,13 @@ void Emulator::handleAnyPendingEvents() {
|
||||||
wxGetApp().CloseMainFrame();
|
wxGetApp().CloseMainFrame();
|
||||||
break;
|
break;
|
||||||
case SDL_KEYDOWN:
|
case SDL_KEYDOWN:
|
||||||
// If we're collecting a command line for changing any
|
// we're collecting keypresses for the keyboard
|
||||||
// of the configurables of the emulator...
|
// emulation (and thus the Apple ][ emulation itself)
|
||||||
if (this->command)
|
dispatchKeyDown(event.key);
|
||||||
cmdKey(event.key);
|
// People who have too many press-releases should be referred to as "keyboards"
|
||||||
else
|
|
||||||
// ...else we're collecting keypresses for the keyboard
|
|
||||||
// emulation (and thus the Apple ][ emulation itself)
|
|
||||||
dispatchKeyDown(event.key);
|
|
||||||
// People who have too many press-releases should be referred to as "keyboards"
|
|
||||||
break;
|
break;
|
||||||
case SDL_KEYUP:
|
case SDL_KEYUP:
|
||||||
// If we're collecting a command line for changing any
|
dispatchKeyUp(event.key);
|
||||||
// of the configurables of the emulator...
|
|
||||||
if (this->command) {
|
|
||||||
if (this->pendingCommandExit) {
|
|
||||||
this->command = false;
|
|
||||||
this->pendingCommandExit = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// ...else we're collecting keypresses for the keyboard
|
|
||||||
// emulation (and thus the Apple ][ emulation itself)
|
|
||||||
dispatchKeyUp(event.key);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -234,7 +216,6 @@ static bool translateKeysToAppleModernized(SDL_Keycode keycode, SDL_Keymod modif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,10 +239,6 @@ void Emulator::dispatchKeyDown(const SDL_KeyboardEvent& keyEvent) {
|
||||||
this->repeat = true;
|
this->repeat = true;
|
||||||
this->rept = CYCLES_PER_REPT;
|
this->rept = CYCLES_PER_REPT;
|
||||||
return;
|
return;
|
||||||
} else if (sym == SDLK_F5) { // TODO re-do user-entered command line
|
|
||||||
this->command = true;
|
|
||||||
this->screenImage.enterCommandMode();
|
|
||||||
return;
|
|
||||||
} else if (SDLK_F1 <= sym && sym <= SDLK_F12) {
|
} else if (SDLK_F1 <= sym && sym <= SDLK_F12) {
|
||||||
wxGetApp().OnFnKeyPressed(sym);
|
wxGetApp().OnFnKeyPressed(sym);
|
||||||
return;
|
return;
|
||||||
|
@ -295,63 +272,19 @@ void Emulator::dispatchKeyUp(const SDL_KeyboardEvent& keyEvent) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Emulator::cmd(const wxString& c) {
|
||||||
// TODO redo command line handling
|
if (c.empty()) {
|
||||||
// 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);
|
|
||||||
|
|
||||||
if (sym == SDLK_RETURN) {
|
|
||||||
processCommand();
|
|
||||||
} else if (sym == SDLK_ESCAPE) {
|
|
||||||
cmdline.erase(cmdline.begin(), cmdline.end());
|
|
||||||
processCommand();
|
|
||||||
} else if (sym == SDLK_BACKSPACE) {
|
|
||||||
if (cmdline.length()) {
|
|
||||||
cmdline.erase(cmdline.end() - 1);
|
|
||||||
this->screenImage.backspaceCommand();
|
|
||||||
}
|
|
||||||
} else if (sym == SDLK_INSERT) {
|
|
||||||
std::string s = this->clip.getText();
|
|
||||||
for (unsigned int i = 0; i < s.length(); ++i) {
|
|
||||||
key = s[i];
|
|
||||||
if (key == '\n' || key == '\r') {
|
|
||||||
processCommand();
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
cmdline += key;
|
|
||||||
this->screenImage.addkeyCommand(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (key) {
|
|
||||||
cmdline += key;
|
|
||||||
this->screenImage.addkeyCommand(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process a command line typed at the bottom of the emulator window
|
|
||||||
void Emulator::processCommand() {
|
|
||||||
this->screenImage.exitCommandMode();
|
|
||||||
this->screenImage.drawPower(this->timable == &this->apple2);
|
|
||||||
this->pendingCommandExit = true;
|
|
||||||
|
|
||||||
if (cmdline.empty()) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
E2Command{}.parseLine(
|
||||||
E2Command{}.parseLine(cmdline, this->apple2.ram, this->apple2.rom, this->apple2.slts, this->apple2.revision, this->screenImage, this->apple2.cassetteIn, this->apple2.cassetteOut, NULL);
|
c.c_str().AsChar(),
|
||||||
cmdline.erase(cmdline.begin(), cmdline.end());
|
this->apple2.ram, this->apple2.rom, this->apple2.slts, this->apple2.revision, this->screenImage, this->apple2.cassetteIn, this->apple2.cassetteOut, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int askSave() {
|
static int askSave() {
|
||||||
wxMessageDialog *dlg = new wxMessageDialog{
|
wxMessageDialog *dlg = new wxMessageDialog{
|
||||||
nullptr,
|
nullptr,
|
||||||
|
|
|
@ -25,9 +25,9 @@
|
||||||
#include "screenimage.h"
|
#include "screenimage.h"
|
||||||
#include "analogtv.h"
|
#include "analogtv.h"
|
||||||
#include "keyboardbuffermode.h"
|
#include "keyboardbuffermode.h"
|
||||||
#include "hypermode.h"
|
|
||||||
#include "clipboardhandler.h"
|
#include "clipboardhandler.h"
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
#include <wx/string.h>
|
||||||
|
|
||||||
class Timable;
|
class Timable;
|
||||||
class E2Config;
|
class E2Config;
|
||||||
|
@ -36,7 +36,6 @@ class Emulator {
|
||||||
PaddleButtonStates paddleButtonStates;
|
PaddleButtonStates paddleButtonStates;
|
||||||
KeypressQueue keypresses;
|
KeypressQueue keypresses;
|
||||||
|
|
||||||
HyperMode fhyper;
|
|
||||||
KeyboardBufferMode buffered;
|
KeyboardBufferMode buffered;
|
||||||
ScreenImage screenImage;
|
ScreenImage screenImage;
|
||||||
AnalogTV display;
|
AnalogTV display;
|
||||||
|
@ -51,14 +50,9 @@ class Emulator {
|
||||||
int rept;
|
int rept;
|
||||||
unsigned char lastKeyDown;
|
unsigned char lastKeyDown;
|
||||||
Uint32 prev_ms;
|
Uint32 prev_ms;
|
||||||
bool command;
|
|
||||||
bool pendingCommandExit;
|
|
||||||
std::string cmdline;
|
|
||||||
|
|
||||||
void dispatchKeyDown(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 processCommand();
|
|
||||||
void powerOnComputer();
|
void powerOnComputer();
|
||||||
void powerOffComputer();
|
void powerOffComputer();
|
||||||
|
|
||||||
|
@ -71,6 +65,7 @@ public:
|
||||||
|
|
||||||
void config(E2Config& cfg);
|
void config(E2Config& cfg);
|
||||||
void tick50ms();
|
void tick50ms();
|
||||||
|
void cmd(const wxString& c);
|
||||||
bool isSafeToQuit();
|
bool isSafeToQuit();
|
||||||
|
|
||||||
void toggleComputerPower();
|
void toggleComputerPower();
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
/*
|
|
||||||
epple2
|
|
||||||
Copyright (C) 2008 by Christopher A. Mosher <cmosher01@gmail.com>
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY, without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
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 "hypermode.h"
|
|
|
@ -1,45 +0,0 @@
|
||||||
/*
|
|
||||||
epple2
|
|
||||||
Copyright (C) 2008 by Christopher A. Mosher <cmosher01@gmail.com>
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY, without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
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 HYPERMODE_H
|
|
||||||
#define HYPERMODE_H
|
|
||||||
|
|
||||||
class HyperMode
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
bool fhyper;
|
|
||||||
|
|
||||||
public:
|
|
||||||
HyperMode(): fhyper(false) { }
|
|
||||||
~HyperMode() { }
|
|
||||||
bool isHyper()
|
|
||||||
{
|
|
||||||
return this->fhyper;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setHyper(bool isHyper)
|
|
||||||
{
|
|
||||||
this->fhyper = isHyper;
|
|
||||||
}
|
|
||||||
|
|
||||||
void toggleHyper()
|
|
||||||
{
|
|
||||||
this->fhyper = !this->fhyper;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -16,15 +16,13 @@
|
||||||
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 "keyboardbuffermode.h"
|
#include "keyboardbuffermode.h"
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Keyboard::Keyboard(KeypressQueue& q, HyperMode& fhyper, KeyboardBufferMode& buffered) :
|
Keyboard::Keyboard(KeypressQueue& q, KeyboardBufferMode& buffered) :
|
||||||
keys(q),
|
keys(q),
|
||||||
fhyper(fhyper),
|
|
||||||
buffered(buffered),
|
buffered(buffered),
|
||||||
latch(0),
|
latch(0),
|
||||||
cGet(0) {
|
cGet(0) {
|
||||||
|
@ -39,7 +37,6 @@ void Keyboard::clear() {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char Keyboard::get() {
|
unsigned char Keyboard::get() {
|
||||||
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;
|
||||||
|
@ -48,28 +45,3 @@ unsigned char Keyboard::get() {
|
||||||
}
|
}
|
||||||
return this->latch;
|
return this->latch;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Keyboard::waitIfTooFast() {
|
|
||||||
// TODO remove all hyper stuff; it doesn't do anything anymore,
|
|
||||||
// since the new architecture with wxTimer
|
|
||||||
|
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
|
|
|
@ -23,22 +23,18 @@
|
||||||
|
|
||||||
typedef std::queue<unsigned char> KeypressQueue;
|
typedef std::queue<unsigned char> KeypressQueue;
|
||||||
|
|
||||||
class HyperMode;
|
|
||||||
class KeyboardBufferMode;
|
class KeyboardBufferMode;
|
||||||
|
|
||||||
class Keyboard {
|
class Keyboard {
|
||||||
KeypressQueue& keys;
|
KeypressQueue& keys;
|
||||||
HyperMode& fhyper;
|
|
||||||
KeyboardBufferMode& buffered;
|
KeyboardBufferMode& buffered;
|
||||||
|
|
||||||
unsigned char latch;
|
unsigned char latch;
|
||||||
unsigned char cGet;
|
unsigned char cGet;
|
||||||
Uint32 lastGet;
|
Uint32 lastGet;
|
||||||
|
|
||||||
void waitIfTooFast();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Keyboard(KeypressQueue& q, HyperMode& fhyper, KeyboardBufferMode& buffered);
|
Keyboard(KeypressQueue& q, KeyboardBufferMode& buffered);
|
||||||
void powerOn();
|
void powerOn();
|
||||||
void clear();
|
void clear();
|
||||||
unsigned char get();
|
unsigned char get();
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
// TODO For screen image in general, remove items from this SDL window to the wx frame as appropriate
|
||||||
|
|
||||||
static const char* power =
|
static const char* power =
|
||||||
" @@@@ @@@ @ @ @ @@@@@ @@@@ "
|
" @@@@ @@@ @ @ @ @@@@@ @@@@ "
|
||||||
" @ @ @ @ @ @ @ @ @ @ @"
|
" @ @ @ @ @ @ @ @ @ @ @"
|
||||||
|
@ -56,9 +58,7 @@ class ScreenException {
|
||||||
|
|
||||||
ScreenImage::ScreenImage() :
|
ScreenImage::ScreenImage() :
|
||||||
fullscreen(false),
|
fullscreen(false),
|
||||||
hyper_a2_speed(false),
|
|
||||||
buffer(true),
|
buffer(true),
|
||||||
fillLines(true),
|
|
||||||
display(AnalogTV::TV_OLD_COLOR),
|
display(AnalogTV::TV_OLD_COLOR),
|
||||||
slotnames(8),
|
slotnames(8),
|
||||||
cassInName(32, ' '),
|
cassInName(32, ' '),
|
||||||
|
@ -165,37 +165,23 @@ void ScreenImage::drawFnKeys() {
|
||||||
int r(76);
|
int r(76);
|
||||||
int c(1);
|
int c(1);
|
||||||
drawText(
|
drawText(
|
||||||
" FULLSCRN SCAN-LINES KEYBOARD", r++, c);
|
" FULLSCRN KEYBOARD", r++, c);
|
||||||
drawText(
|
drawText(
|
||||||
" XXXXXXXXXXXXXX WINDOW FILL-LINES CMD RESET PASTE SAVE BMP QUIT! REPT HYPER BUFFER ", r++, c);
|
" XXXXXXXXXXXXXX WINDOW CMD RESET PASTE SAVE BMP QUIT! REPT BUFFER ", r++, c);
|
||||||
drawText(
|
drawText(
|
||||||
" F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 ", r++, c);
|
" F1 F2 F3 F5 F6 F7 F8 F9 F10 F12 ", r++, c);
|
||||||
|
|
||||||
if (this->fullscreen)
|
if (this->fullscreen)
|
||||||
invertText(76, 32, 42); // FULLSCRN
|
invertText(76, 32, 42); // FULLSCRN
|
||||||
else
|
else
|
||||||
invertText(77, 32, 40); // WINDOW
|
invertText(77, 32, 40); // WINDOW
|
||||||
|
|
||||||
if (this->fillLines)
|
|
||||||
invertText(77, 43, 55); // FILL-LINES
|
|
||||||
else
|
|
||||||
invertText(76, 43, 55); // SCAN-LINES
|
|
||||||
|
|
||||||
if (this->hyper_a2_speed)
|
|
||||||
invertText(77, 102, 109); // HYPER
|
|
||||||
|
|
||||||
if (this->buffer)
|
if (this->buffer)
|
||||||
invertText(77, 110, 118); // BUFFER
|
invertText(77, 110, 118); // BUFFER
|
||||||
|
|
||||||
drawDisplayLabel();
|
drawDisplayLabel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenImage::toggleFillLinesLabel() {
|
|
||||||
this->fillLines = !this->fillLines;
|
|
||||||
invertText(76, 43, 55); // SCAN-LINES
|
|
||||||
invertText(77, 43, 55); // FILL-LINES
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScreenImage::drawDisplayLabel() {
|
void ScreenImage::drawDisplayLabel() {
|
||||||
const char* label = displays[(int) (this->display)];
|
const char* label = displays[(int) (this->display)];
|
||||||
drawText(label, 77, 17);
|
drawText(label, 77, 17);
|
||||||
|
@ -206,11 +192,6 @@ void ScreenImage::cycleDisplayLabel() {
|
||||||
drawDisplayLabel();
|
drawDisplayLabel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenImage::toggleHyperLabel() {
|
|
||||||
this->hyper_a2_speed = !this->hyper_a2_speed;
|
|
||||||
invertText(77, 102, 109); // HYPER
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScreenImage::toggleKdbBufferLabel() {
|
void ScreenImage::toggleKdbBufferLabel() {
|
||||||
this->buffer = !this->buffer;
|
this->buffer = !this->buffer;
|
||||||
invertText(77, 110, 118); // BUFFER
|
invertText(77, 110, 118); // BUFFER
|
||||||
|
@ -320,35 +301,6 @@ void ScreenImage::blank() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenImage::enterCommandMode() {
|
|
||||||
int r(76);
|
|
||||||
int c(1);
|
|
||||||
unsigned int* pn = this->pixels;
|
|
||||||
pn += r * FONTH * SCRW + c*FONTW;
|
|
||||||
|
|
||||||
memset((char*) pn, 0, SCRW * 4 * FONTH * 3);
|
|
||||||
|
|
||||||
drawText("command: ", 78, 1);
|
|
||||||
this->cmdpos = 9;
|
|
||||||
|
|
||||||
notifyObservers();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScreenImage::exitCommandMode() {
|
|
||||||
drawFnKeys();
|
|
||||||
notifyObservers();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScreenImage::addkeyCommand(unsigned char key) {
|
|
||||||
++this->cmdpos;
|
|
||||||
drawChar((char) key, 78, this->cmdpos);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScreenImage::backspaceCommand() {
|
|
||||||
drawChar(' ', 78, this->cmdpos);
|
|
||||||
--this->cmdpos;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScreenImage::updateSlotName(const int slot, Card* card) {
|
void ScreenImage::updateSlotName(const int slot, Card* card) {
|
||||||
int r(R_SLOT + slot);
|
int r(R_SLOT + slot);
|
||||||
int c(20);
|
int c(20);
|
||||||
|
|
|
@ -36,11 +36,8 @@ private:
|
||||||
unsigned int* pixels;
|
unsigned int* pixels;
|
||||||
int screen_pitch;
|
int screen_pitch;
|
||||||
bool fullscreen;
|
bool fullscreen;
|
||||||
bool hyper_a2_speed;
|
|
||||||
bool buffer;
|
bool buffer;
|
||||||
bool fillLines;
|
|
||||||
AnalogTV::DisplayType display;
|
AnalogTV::DisplayType display;
|
||||||
unsigned int cmdpos;
|
|
||||||
void createScreen();
|
void createScreen();
|
||||||
std::vector<std::string> slotnames;
|
std::vector<std::string> slotnames;
|
||||||
std::string cassInName;
|
std::string cassInName;
|
||||||
|
@ -66,7 +63,6 @@ public:
|
||||||
void drawSlot(int slot, int r, int c);
|
void drawSlot(int slot, int r, int c);
|
||||||
void drawCassette();
|
void drawCassette();
|
||||||
void drawFnKeys();
|
void drawFnKeys();
|
||||||
void toggleHyperLabel();
|
|
||||||
void toggleKdbBufferLabel();
|
void toggleKdbBufferLabel();
|
||||||
void cycleDisplayLabel();
|
void cycleDisplayLabel();
|
||||||
void displayHz(int hz);
|
void displayHz(int hz);
|
||||||
|
@ -76,11 +72,6 @@ public:
|
||||||
void updateSlotName(const int slot, Card* card);
|
void updateSlotName(const int slot, Card* card);
|
||||||
void removeCard(const int slot, Card* card /* empty */);
|
void removeCard(const int slot, Card* card /* empty */);
|
||||||
|
|
||||||
void enterCommandMode();
|
|
||||||
void exitCommandMode();
|
|
||||||
void addkeyCommand(unsigned char key);
|
|
||||||
void backspaceCommand();
|
|
||||||
|
|
||||||
void setDiskFile(int slot, int drive, const std::filesystem::path& filename);
|
void setDiskFile(int slot, int drive, const std::filesystem::path& filename);
|
||||||
|
|
||||||
void setAnnunciator(int ann, bool on);
|
void setAnnunciator(int ann, bool on);
|
||||||
|
|
Loading…
Reference in New Issue