fix: user config writeable, memory init out of bounds for 4K, unstrapped memory, remove one instance of tinyfd

This commit is contained in:
Christopher A. Mosher 2022-12-10 11:26:39 -05:00
parent 5ff50c9c0c
commit 5c3d14b795
9 changed files with 55 additions and 41 deletions

View File

@ -151,8 +151,10 @@ void PreferencesDialog::Save(const std::filesystem::path& to) {
CTRL(wxTextCtrl, txtConfig); CTRL(wxTextCtrl, txtConfig);
const wxString sConfig = txtConfig->GetValue(); const wxString sConfig = txtConfig->GetValue();
if (sConfig != this->sOrigConfig) { if (sConfig != this->sOrigConfig) {
BOOST_LOG_TRIVIAL(info) << "saving config file: " << to.c_str();
std::ofstream out(to); std::ofstream out(to);
out << sConfig; out << sConfig;
out.flush();
this->sOrigConfig = sConfig; this->sOrigConfig = sConfig;
} }
} }
@ -252,6 +254,7 @@ void PreferencesDialog::OnDuplicate(wxCommandEvent& evt) {
BOOST_LOG_TRIVIAL(info) << "copy from: " << data->path().c_str(); BOOST_LOG_TRIVIAL(info) << "copy from: " << data->path().c_str();
if (!std::filesystem::exists(f)) { if (!std::filesystem::exists(f)) {
std::filesystem::copy_file(data->path(), f, std::filesystem::copy_options::skip_existing); std::filesystem::copy_file(data->path(), f, std::filesystem::copy_options::skip_existing);
std::filesystem::permissions(f, std::filesystem::perms::owner_write, std::filesystem::perm_options::add);
BuildItemTree(); BuildItemTree();
PreSelectUserConfigItemName(f); PreSelectUserConfigItemName(f);
} else { } else {

View File

@ -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/>.
*/ */
#include "apple2.h" #include "apple2.h"
#include "slots.h" #include "slots.h"
#include "videomode.h" #include "videomode.h"
@ -38,20 +38,20 @@
#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, HyperMode& fhyper, KeyboardBufferMode& buffered, ScreenImage& gui) :
slts(gui), slts(gui),
kbd(keypresses,fhyper,buffered), kbd(keypresses, fhyper, buffered),
rom(AddressBus::MOTHERBOARD_ROM_SIZ), rom(AddressBus::MOTHERBOARD_ROM_SIZ),
ram(revision), ram(revision),
cassetteIn(gui), cassetteIn(gui),
cassetteOut(gui), cassetteOut(gui),
addressBus(gui,revision,ram,rom,kbd,videoMode,paddles,paddleButtonStates,speaker,cassetteIn,cassetteOut,slts), addressBus(gui, revision, ram, rom, kbd, videoMode, paddles, paddleButtonStates, speaker, cassetteIn, cassetteOut, slts),
picgen(tv,videoMode,revision), picgen(tv, videoMode, revision),
video(videoMode,addressBus,picgen,textRows), video(videoMode, addressBus, picgen, textRows),
transistors("transistors"), // TODO load file from resources transistors("transistors"), // TODO load file from resources
cpu(NULL), cpu(NULL),
powerUpReset(*this), powerUpReset(*this),
revision(1) { revision(1) {
} }
Apple2::~Apple2() { Apple2::~Apple2() {
@ -72,6 +72,7 @@ void Apple2::useVisual6502Cpu() {
} }
void Apple2::tick() { void Apple2::tick() {
useEpple2Cpu(); // default, if not already set
this->cpu->tick(); this->cpu->tick();
this->slts.tick(); this->slts.tick();
this->video.tick(); this->video.tick();
@ -85,8 +86,7 @@ void Apple2::tick() {
} }
} }
void Apple2::powerOn() void Apple2::powerOn() {
{
useEpple2Cpu(); // default, if not already set useEpple2Cpu(); // default, if not already set
this->ram.powerOn(); this->ram.powerOn();
this->cpu->powerOn(); this->cpu->powerOn();
@ -96,13 +96,12 @@ void Apple2::powerOn()
this->powerUpReset.powerOn(); this->powerUpReset.powerOn();
} }
void Apple2::powerOff() void Apple2::powerOff() {
{
this->ram.powerOff(); this->ram.powerOff();
} }
void Apple2::reset() void Apple2::reset() {
{ useEpple2Cpu(); // default, if not already set
this->cpu->reset(); this->cpu->reset();
this->slts.reset(); this->slts.reset();
} }

View File

@ -33,6 +33,7 @@
#include "cassetteout.h" #include "cassetteout.h"
#include "tinyfiledialogs.h" #include "tinyfiledialogs.h"
#include <wx/filedlg.h>
#include <wx/config.h> #include <wx/config.h>
#include <wx/string.h> #include <wx/string.h>
@ -456,14 +457,12 @@ void Config::tryParseLine(const std::string& line, MemoryRandomAccess& ram, Memo
trim(fn_optional); trim(fn_optional);
if (fn_optional.length() == 0) { if (fn_optional.length() == 0) {
gui.exitFullScreen(); gui.exitFullScreen();
char const *ft[1] = {"*.woz"}; wxFileDialog dlg{nullptr, "Load floppy", "", "", "WOZ 2.0 disk images (*.woz)|*.woz", wxFD_OPEN|wxFD_FILE_MUST_EXIST};
char const *fn = tinyfd_openFileDialog("Load floppy", "", 1, ft, "WOZ 2.0 disk images", 0); if (dlg.ShowModal() == wxID_OK) {
if (fn) { fn_optional = dlg.GetPath().c_str();
fn_optional = std::string(fn);
} }
} }
if (fn_optional.length() > 0) { if (fn_optional.length() > 0) {
// TODO check if file exists, if not then check resources
loadDisk(slts, slot, drive, fn_optional); loadDisk(slts, slot, drive, fn_optional);
} }
} else if (cmd == "unload") { } else if (cmd == "unload") {

View File

@ -24,7 +24,7 @@
*/ */
GUI::GUI() { GUI::GUI() {
const int result = SDL_Init(SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO); const int result = SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO);
if (result != 0) { if (result != 0) {
std::cerr << "Failed to initialize SDL: " << SDL_GetError() << std::endl; std::cerr << "Failed to initialize SDL: " << SDL_GetError() << std::endl;
throw GUI::NotInitException(); throw GUI::NotInitException();

View File

@ -36,7 +36,7 @@ void Memory::clear() {
} }
void Memory::load(const std::uint16_t base, std::istream& in) { void Memory::load(const std::uint16_t base, std::istream& in) {
in.read(reinterpret_cast<char*>(&this->bytes[base]), static_cast<ptrdiff_t>(this->bytes.size()-base)); in.read(reinterpret_cast<char*>(&this->bytes.at(base)), static_cast<ptrdiff_t>(this->bytes.size()-base));
} }
void Memory::powerOn() { void Memory::powerOn() {
@ -52,9 +52,9 @@ size_t Memory::size() const {
} }
std::uint8_t Memory::read(const std::uint16_t address, const std::uint8_t data) const { std::uint8_t Memory::read(const std::uint16_t address, const std::uint8_t data) const {
return (this->bytes[address] & ~this->missing_bits) | (data & this->missing_bits); return (this->bytes.at(address) & ~this->missing_bits) | (data & this->missing_bits);
} }
void Memory::write(const std::uint16_t address, const std::uint8_t data) { void Memory::write(const std::uint16_t address, const std::uint8_t data) {
this->bytes[address] = data; this->bytes.at(address) = data;
} }

View File

@ -78,7 +78,7 @@ void MemoryChip::rand_init(const std::uint8_t mask, std::vector<std::uint8_t> &b
std::uint_fast32_t c_chaos16 = 65u; std::uint_fast32_t c_chaos16 = 65u;
std::uint_fast32_t c_chaos16sub = 15u; std::uint_fast32_t c_chaos16sub = 15u;
bool on = false; bool on = false;
for (std::uint_fast16_t i = 0u; i < 16*K; ++i) { for (std::uint_fast16_t i = 0u; i < size; ++i) {
double r = static_cast<double>(std::rand())/RAND_MAX; double r = static_cast<double>(std::rand())/RAND_MAX;
bool is_rand = false; bool is_rand = false;
if (r < GLITCH && c_chaos16 == 65u) { if (r < GLITCH && c_chaos16 == 65u) {
@ -94,7 +94,7 @@ void MemoryChip::rand_init(const std::uint8_t mask, std::vector<std::uint8_t> &b
} }
} }
is_rand |= (r < CHAOS); is_rand |= (r < CHAOS);
bitflag(is_rand?!on:on, mask, bytes[i]); bitflag(is_rand?!on:on, mask, bytes.at(i));
if (c_cycle++ == cycle-1) { if (c_cycle++ == cycle-1) {
on = !on; on = !on;
c_cycle = 0u; c_cycle = 0u;

View File

@ -16,7 +16,7 @@ void MemoryRow::insert_chip(MemoryChip *chip, const std::uint_fast8_t socket) {
if (socket < 8u) { if (socket < 8u) {
remove_chip(socket); remove_chip(socket);
if (chip->exists()) { if (chip->exists()) {
this->chips[socket] = chip; this->chips.at(socket) = chip;
this->missing_bits &= ~(1u << socket); this->missing_bits &= ~(1u << socket);
this->values_stored.resize(calculate_size()); this->values_stored.resize(calculate_size());
} }
@ -27,7 +27,7 @@ void MemoryRow::insert_chip(MemoryChip *chip, const std::uint_fast8_t socket) {
void MemoryRow::remove_chip(const std::uint_fast8_t socket) { void MemoryRow::remove_chip(const std::uint_fast8_t socket) {
if (socket < 8u) { if (socket < 8u) {
this->chips[socket] = MemoryChip::instance("-"); this->chips.at(socket) = MemoryChip::instance("-");
this->missing_bits |= (1u << socket); this->missing_bits |= (1u << socket);
this->values_stored.resize(calculate_size()); this->values_stored.resize(calculate_size());
} else { } else {
@ -43,7 +43,7 @@ std::uint16_t MemoryRow::calculate_size() const {
std::uint16_t size_new = 0u; std::uint16_t size_new = 0u;
for (std::uint_fast8_t i_chip = 0; i_chip < 8; ++i_chip) { for (std::uint_fast8_t i_chip = 0; i_chip < 8; ++i_chip) {
const MemoryChip *chip = this->chips[i_chip]; const MemoryChip *chip = this->chips.at(i_chip);
if (chip->exists()) { if (chip->exists()) {
const std::uint16_t s = chip->size(); const std::uint16_t s = chip->size();
if (size_new == 0u || s < size_new) { if (size_new == 0u || s < size_new) {
@ -68,7 +68,7 @@ void MemoryRow::powerOn() {
std::uint8_t mask_bit = 1u; std::uint8_t mask_bit = 1u;
for (std::uint_fast8_t i_bit = 0; i_bit < 8; ++i_bit) { for (std::uint_fast8_t i_bit = 0; i_bit < 8; ++i_bit) {
const MemoryChip *chip = this->chips[i_bit]; const MemoryChip *chip = this->chips.at(i_bit);
if (chip->exists()) { if (chip->exists()) {
chip->init(mask_bit, this->values_stored, size()); chip->init(mask_bit, this->values_stored, size());
} }
@ -95,7 +95,7 @@ std::uint8_t MemoryRow::read(const std::uint16_t address_offset, std::uint8_t da
* -------- * --------
* 00011101 (stored & ~missing) | (data & missing) * 00011101 (stored & ~missing) | (data & missing)
*/ */
data = (this->values_stored[address_offset] & ~this->missing_bits) | (data & this->missing_bits); data = (this->values_stored.at(address_offset) & ~this->missing_bits) | (data & this->missing_bits);
} }
return data; return data;
} else { } else {
@ -107,12 +107,12 @@ void MemoryRow::write(const std::uint16_t address, const std::uint8_t data) {
if (this->power) { if (this->power) {
// if there are missing bits, they do get stored, so we need to // if there are missing bits, they do get stored, so we need to
// be careful to mask them out when giving them back (in read method) // be careful to mask them out when giving them back (in read method)
this->values_stored[address] = data; this->values_stored.at(address) = data;
} else { } else {
throw std::logic_error("cannot write memory when power is off"); throw std::logic_error("cannot write memory when power is off");
} }
} }
std::string MemoryRow::chip_id(std::uint_fast8_t socket) const { std::string MemoryRow::chip_id(std::uint_fast8_t socket) const {
return this->chips[socket]->id(); return this->chips.at(socket)->id();
} }

View File

@ -1,27 +1,39 @@
#include "memorystrapping.h" #include "memorystrapping.h"
#include <algorithm> #include <algorithm>
MemoryStrapping::MemoryStrapping(MemoryRow &row): MemoryStrapping::MemoryStrapping(MemoryRow &row): row{row}, strapped{false} {
row(row) {
} }
void MemoryStrapping::strap_to(std::uint16_t addr_base, std::uint16_t addr_size) { void MemoryStrapping::strap_to(std::uint16_t addr_base, std::uint16_t addr_size) {
this->addr_base = addr_base; this->addr_base = addr_base;
this->addr_size = addr_size; this->addr_size = addr_size;
this->strapped = true;
} }
bool MemoryStrapping::contains(std::uint16_t address) const { bool MemoryStrapping::contains(std::uint16_t address) const {
if (!this->strapped) {
return false;
}
return this->addr_base <= address && address < this->addr_base + size(); return this->addr_base <= address && address < this->addr_base + size();
} }
std::uint8_t MemoryStrapping::read(const std::uint16_t address, const std::uint8_t data) const { std::uint8_t MemoryStrapping::read(const std::uint16_t address, const std::uint8_t data) const {
if (!this->strapped) {
return 0xFFu;
}
return this->row.read(address - this->addr_base, data); return this->row.read(address - this->addr_base, data);
} }
void MemoryStrapping::write(const std::uint16_t address, const std::uint8_t data) { void MemoryStrapping::write(const std::uint16_t address, const std::uint8_t data) {
if (!this->strapped) {
return;
}
this->row.write(address - this->addr_base, data); this->row.write(address - this->addr_base, data);
} }
std::uint16_t MemoryStrapping::size() const { std::uint16_t MemoryStrapping::size() const {
if (!this->strapped) {
return 0;
}
return std::min(this->row.size(), this->addr_size); return std::min(this->row.size(), this->addr_size);
} }

View File

@ -6,6 +6,7 @@
class MemoryStrapping { class MemoryStrapping {
private: private:
bool strapped;
MemoryRow &row; MemoryRow &row;
std::uint16_t addr_base; std::uint16_t addr_base;
std::uint16_t addr_size; std::uint16_t addr_size;