From 270e94a76a3e5f2b5c4edd3c908757f08a990b5c Mon Sep 17 00:00:00 2001 From: Christopher Mosher Date: Thu, 7 Feb 2019 00:45:54 -0500 Subject: [PATCH] add RAM chips and better init algorithm; dump RAM --- conf/epple2.a2ploaded.conf.in | 6 +- conf/epple2.conf.in | 6 +- src/configep2.cpp | 29 ++------- src/emulator.cpp | 1 + src/lss.cpp | 1 + src/memorychip.cpp | 118 ++++++++++++++++++++++++++++------ src/memorychip.h | 30 +++++++-- src/memoryrandomaccess.cpp | 35 +++++++++- src/memoryrandomaccess.h | 4 +- src/memoryrow.cpp | 27 ++++---- src/memoryrow.h | 6 +- src/memorystrapping.cpp | 6 +- src/memorystrapping.h | 1 + 13 files changed, 203 insertions(+), 67 deletions(-) diff --git a/conf/epple2.a2ploaded.conf.in b/conf/epple2.a2ploaded.conf.in index 8464bfc..66b6d88 100644 --- a/conf/epple2.a2ploaded.conf.in +++ b/conf/epple2.a2ploaded.conf.in @@ -10,9 +10,9 @@ # 48K RAM -motherboard ram E 16K -motherboard ram D 16K -motherboard ram C 16K +motherboard ram E MM5290 MM5290 MM5290 MK4116 MM5290 MM5290 MM5290 MK4116 +motherboard ram D MM5290 MM5290 MK4116 MK4116 MM5290 MK4116 MM5290 MCM4116 +motherboard ram C MK4116 MK4116 MM5290 MM5290 MM5290 MM5290 MM5290 MM5290 motherboard strap E 16K 8000 motherboard strap D 16K 4000 motherboard strap C 16K 0000 diff --git a/conf/epple2.conf.in b/conf/epple2.conf.in index 2d9f427..cf84256 100644 --- a/conf/epple2.conf.in +++ b/conf/epple2.conf.in @@ -12,9 +12,9 @@ # standard 48K RAM -motherboard ram E 16K -motherboard ram D 16K -motherboard ram C 16K +motherboard ram E MM5290 MM5290 MM5290 MK4116 MM5290 MM5290 MM5290 MK4116 +motherboard ram D MM5290 MM5290 MK4116 MK4116 MM5290 MK4116 MM5290 MCM4116 +motherboard ram C MK4116 MK4116 MM5290 MM5290 MM5290 MM5290 MM5290 MM5290 motherboard strap E 16K 8000 motherboard strap D 16K 4000 motherboard strap C 16K 0000 diff --git a/src/configep2.cpp b/src/configep2.cpp index 0904b6f..1b027b3 100644 --- a/src/configep2.cpp +++ b/src/configep2.cpp @@ -42,18 +42,7 @@ #define K 1024u -static std::uint16_t chip_size(const std::string &chip_model) { - if (chip_model == "4K") { - return 4u*K; - } - if (chip_model == "16K") { - return 16u*K; - } - if (chip_model == "-") { - return 0u; - } - throw ConfigException("unrecognized RAM chip model"); -} + static std::uint16_t memory_block_size(const std::string &block_size) { if (block_size == "4K") { @@ -233,27 +222,23 @@ void Config::tryParseLine(const std::string& line, MemoryRandomAccess& ram, Memo if (row != "C" && row != "D" && row != "E") { throw ConfigException("expected row to be C, D, or E"); } + std::string chip_model; tok >> chip_model; - std::uint16_t siz = chip_size(chip_model); for (std::uint_fast8_t bit = 0u; bit < 8u; ++bit) { - if (siz) { - ram.insert_chip(row, MemoryChip(siz,chip_model), bit); - } else { - ram.remove_chip(row, bit); - } + ram.insert_chip(row, MemoryChip::instance(chip_model), bit); + std::string chip_model_optional; tok >> chip_model_optional; if (chip_model_optional.length()) { chip_model = chip_model_optional; } - siz = chip_size(chip_model); } } else if (op == "strap") { /* strap ROM K start-addr - * strap c 4K 0000 - * strap d 4K 1000 - * strap e 4K 2000 + * strap e 4K 5000 + * strap d 4K 4000 + * strap c 16K 0000 */ std::string row; tok >> row; diff --git a/src/emulator.cpp b/src/emulator.cpp index 3eb7161..3a6b7ba 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -73,6 +73,7 @@ void Emulator::powerOffComputer() { void Emulator::config(Config& 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.ram.dump_config(); } void Emulator::init() { diff --git a/src/lss.cpp b/src/lss.cpp index 39a6bd0..f859fa8 100644 --- a/src/lss.cpp +++ b/src/lss.cpp @@ -217,6 +217,7 @@ LSS::LSS(bool use13SectorDos32LSS): setseq(lss13rom,0x23u,0x30u); setseq(lss13rom,0x33u,0xD0u); + printf("Disk ][ Controller Logic State Sequencer ROM:\n"); if (use13Sector) { for (unsigned int seq = 0; seq < 0x100u; seq += 0x10u) { showua2seq(lss13rom,seq); diff --git a/src/memorychip.cpp b/src/memorychip.cpp index 2df994b..b2ba8fd 100644 --- a/src/memorychip.cpp +++ b/src/memorychip.cpp @@ -2,9 +2,39 @@ #include #include #include +#include #define K 1024 +static MemoryChip *chip_empty = new MemoryChipEmptySocket(); +static MemoryChip *chip_4096 = new MemoryChip(4u*K, "4096"); +static MemoryChip *chip_4116 = new MemoryChip(16u*K, "4116"); +static MemoryChip *chip_mm5290 = new MemoryChipMM5290(); +static MemoryChip *chip_mk4116 = new MemoryChipMK4116(); +static MemoryChip *chip_mcm4116 = new MemoryChipMCM4116(); + +MemoryChip *MemoryChip::instance(const std::string &id_model) { + if (id_model == "-") { + return chip_empty; + } + if (id_model == "4K" || id_model == "4096") { + return chip_4096; + } + if (id_model == "16K" || id_model == "4116") { + return chip_4116; + } + if (id_model == "MM5290") { + return chip_mm5290; + } + if (id_model == "MK4116") { + return chip_mk4116; + } + if (id_model == "MCM4116") { + return chip_mcm4116; + } + throw std::logic_error("unrecognized RAM chip model: "+id_model); +} + MemoryChip::MemoryChip(const std::uint16_t size, const std::string &id_model): size_bits(size), id_model(id_model) { @@ -13,17 +43,6 @@ MemoryChip::MemoryChip(const std::uint16_t size, const std::string &id_model): } } -MemoryChip::MemoryChip(const MemoryChip &that): - size_bits(that.size_bits), - id_model(that.id_model) { -} - -MemoryChip &MemoryChip::operator=(const MemoryChip &that) { - this->size_bits = that.size_bits; - this->id_model = that.id_model; - return *this; -} - MemoryChip::~MemoryChip() { } @@ -47,21 +66,44 @@ static void bitflag(const bool on, const std::uint8_t mask, std::uint8_t &byte) } } -//#define CYCLE 128u -#define CYCLE 2u - void MemoryChip::init(const std::uint8_t mask, std::vector &bytes, const std::uint16_t size) const { + rand_init(mask, bytes, size, 128u, 0.0, 0.0); +} + +void MemoryChip::rand_init(const std::uint8_t mask, std::vector &bytes, const std::uint16_t size, const std::uint_fast32_t cycle, const double glitch, const double chaos) const { + const double GLITCH = glitch*0.001; + const double CHAOS = chaos*0.05; + + std::uint_fast32_t c_cycle = 0u; + std::uint_fast32_t c_chaos16 = 65u; + std::uint_fast32_t c_chaos16sub = 15u; bool on = false; - std::uint8_t c = 0u; - for (std::uint16_t i = 0u; i < std::min(size, this->size_bits); ++i) { - bitflag(on, mask, bytes[i]); - if (CYCLE <= ++c) { - c = 0u; + for (std::uint_fast16_t i = 0u; i < 16*K; ++i) { + double r = static_cast(std::rand())/RAND_MAX; + bool is_rand = false; + if (r < GLITCH && c_chaos16 == 65u) { + --c_chaos16; + } + if (c_chaos16 < 65u) { + if (c_chaos16sub-- == 0u) { + is_rand = true; + c_chaos16sub = 15u; + if (c_chaos16-- == 0u) { + c_chaos16 = 65u; + } + } + } + is_rand |= (r < CHAOS); + bitflag(is_rand?!on:on, mask, bytes[i]); + if (c_cycle++ == cycle-1) { on = !on; + c_cycle = 0u; } } } + + MemoryChipEmptySocket::MemoryChipEmptySocket(): MemoryChip(4*K,"[empty]") { } @@ -72,3 +114,41 @@ MemoryChipEmptySocket::~MemoryChipEmptySocket() { bool MemoryChipEmptySocket::exists() const { return false; } + + + +MemoryChipMM5290::MemoryChipMM5290(): // National Semiconductor + MemoryChip(16*K,"MM5290") { +} + +MemoryChipMM5290::~MemoryChipMM5290() { +} + +void MemoryChipMM5290::init(const std::uint8_t mask, std::vector &bytes, const std::uint16_t size) const { + rand_init(mask, bytes, size, 128u, 0.1, 0.05); +} + + +MemoryChipMK4116::MemoryChipMK4116(): // Mostek + MemoryChip(16*K,"MK4116") { +} + +MemoryChipMK4116::~MemoryChipMK4116() { +} + +void MemoryChipMK4116::init(const std::uint8_t mask, std::vector &bytes, const std::uint16_t size) const { + rand_init(mask, bytes, size, 2u, 0.1, 0.05); +} + + + +MemoryChipMCM4116::MemoryChipMCM4116(): // Motorola + MemoryChip(16*K,"MCM4116") { +} + +MemoryChipMCM4116::~MemoryChipMCM4116() { +} + +void MemoryChipMCM4116::init(const std::uint8_t mask, std::vector &bytes, const std::uint16_t size) const { + rand_init(mask, bytes, size, 4096u, 0.1, 0.05); +} diff --git a/src/memorychip.h b/src/memorychip.h index 1d43094..862133a 100644 --- a/src/memorychip.h +++ b/src/memorychip.h @@ -7,17 +7,18 @@ class MemoryChip { private: - std::uint16_t size_bits; - std::string id_model; + const std::uint16_t size_bits; + const std::string id_model; public: + static MemoryChip *instance(const std::string &id_model); MemoryChip(const std::uint16_t size, const std::string &id_model); - MemoryChip(const MemoryChip &that); - MemoryChip &operator=(const MemoryChip &that); virtual ~MemoryChip(); std::uint16_t size() const; std::string id() const; virtual void init(const std::uint8_t mask, std::vector &bytes, const std::uint16_t size) const; virtual bool exists() const; + protected: + virtual void rand_init(const std::uint8_t mask, std::vector &bytes, const std::uint16_t size, const std::uint_fast32_t cycle, const double glitch, const double chaos) const; }; class MemoryChipEmptySocket : public MemoryChip { @@ -27,4 +28,25 @@ class MemoryChipEmptySocket : public MemoryChip { virtual bool exists() const; }; +class MemoryChipMM5290 : public MemoryChip { + public: + MemoryChipMM5290(); + virtual ~MemoryChipMM5290(); + virtual void init(const std::uint8_t mask, std::vector &bytes, const std::uint16_t size) const; +}; + +class MemoryChipMK4116 : public MemoryChip { + public: + MemoryChipMK4116(); + virtual ~MemoryChipMK4116(); + virtual void init(const std::uint8_t mask, std::vector &bytes, const std::uint16_t size) const; +}; + +class MemoryChipMCM4116 : public MemoryChip { + public: + MemoryChipMCM4116(); + virtual ~MemoryChipMCM4116(); + virtual void init(const std::uint8_t mask, std::vector &bytes, const std::uint16_t size) const; +}; + #endif // MEMORYCHIP_H diff --git a/src/memoryrandomaccess.cpp b/src/memoryrandomaccess.cpp index 7836fd5..eb73a27 100644 --- a/src/memoryrandomaccess.cpp +++ b/src/memoryrandomaccess.cpp @@ -1,5 +1,6 @@ #include "memoryrandomaccess.h" #include +#include #include #define K 1024u @@ -40,7 +41,7 @@ MemoryStrapping &MemoryRandomAccess::strapping_of(const std::string &row) { throw std::logic_error("expected C/D/E"); } -void MemoryRandomAccess::insert_chip(const std::string &row, MemoryChip chip, const std::uint_fast8_t socket) { +void MemoryRandomAccess::insert_chip(const std::string &row, MemoryChip *chip, const std::uint_fast8_t socket) { row_of(row).insert_chip(chip, socket); } @@ -147,3 +148,35 @@ void MemoryRandomAccess::powerOff() { this->rowD.powerOff(); this->rowC.powerOff(); } + +static void dump_row(const std::string &name, const MemoryRow &row) { + std::printf("RAM %s ", name.c_str()); + for (std::uint_fast8_t i = 0u; i < 8u; ++i) { + std::printf("%s ", row.chip_id(i).c_str()); + } + std::printf("\n"); +} + +void MemoryRandomAccess::dump_config() const { + std::printf("motherboard RAM rows contain chips:\n"); + std::printf(" "); dump_row("E", this->rowE); + std::printf(" "); dump_row("D", this->rowD); + std::printf(" "); dump_row("C", this->rowC); + std::printf("address $1000 blocks strapped to RAM row:\n"); + std::uint_fast8_t i = 0xCu; + while (i--) { + std::string r; + const uint16_t addr = i*0x1000u; + if (this->strapE.contains(addr)) { + r = "E"; + } else if (this->strapD.contains(addr)) { + r = "D"; + } else if (this->strapC.contains(addr)) { + r = "C"; + } else { + r = "[not strapped]"; + } + std::printf(" $%X %s\n", i, r.c_str()); + } + std::printf("total RAM: %dK\n", (this->strapE.size()+this->strapD.size()+this->strapC.size())/1024u); +} diff --git a/src/memoryrandomaccess.h b/src/memoryrandomaccess.h index e95b8c4..5ea721e 100644 --- a/src/memoryrandomaccess.h +++ b/src/memoryrandomaccess.h @@ -25,7 +25,9 @@ class MemoryRandomAccess { public: MemoryRandomAccess(int &revision); - void insert_chip(const std::string &row, MemoryChip chip, const std::uint_fast8_t socket); + void dump_config() const; + + void insert_chip(const std::string &row, MemoryChip *chip, const std::uint_fast8_t socket); void remove_chip(const std::string &row, const std::uint_fast8_t socket); void strap_to(const std::string &row, std::uint16_t addr_base, std::uint16_t addr_size); diff --git a/src/memoryrow.cpp b/src/memoryrow.cpp index 1d9998f..a0dfb5c 100644 --- a/src/memoryrow.cpp +++ b/src/memoryrow.cpp @@ -5,14 +5,14 @@ /* * If any RAM IC sockets are empty, set the corresponding bits to 1 most of the time. * For some addresses it seems they are always 1, but for other addresses they can return - * 0 sometimes, empirically I've seen anywhere from 8% to 15% of the time. + * 0 sometimes, empirically about 4% of the time. */ static std::uint8_t randomize_missing_bits(std::uint8_t v, const std::uint8_t bits) { std::uint8_t bit = 1u; for (std::uint_fast8_t i = 0; i < 8; ++i) { if (bits & bit) { double r = static_cast(std::rand())/RAND_MAX; - if (r < 0.11) { + if (r < 0.04) { v &= ~bit; } else { v |= bit; @@ -27,15 +27,16 @@ static std::uint8_t randomize_missing_bits(std::uint8_t v, const std::uint8_t bi MemoryRow::MemoryRow(const char label): label(label) { + this->chips.fill(MemoryChip::instance("-")); } MemoryRow::~MemoryRow() { } -void MemoryRow::insert_chip(MemoryChip chip, const std::uint_fast8_t socket) { +void MemoryRow::insert_chip(MemoryChip *chip, const std::uint_fast8_t socket) { if (socket < 8u) { remove_chip(socket); - if (chip.exists()) { + if (chip->exists()) { this->chips[socket] = chip; this->missing_bits &= ~(1u << socket); this->values_stored.resize(calculate_size()); @@ -47,7 +48,7 @@ void MemoryRow::insert_chip(MemoryChip chip, const std::uint_fast8_t socket) { void MemoryRow::remove_chip(const std::uint_fast8_t socket) { if (socket < 8u) { - this->chips[socket] = MemoryChipEmptySocket(); + this->chips[socket] = MemoryChip::instance("-"); this->missing_bits |= (1u << socket); this->values_stored.resize(calculate_size()); } else { @@ -63,9 +64,9 @@ std::uint16_t MemoryRow::calculate_size() const { std::uint16_t size_new = 0u; for (std::uint_fast8_t i_chip = 0; i_chip < 8; ++i_chip) { - const MemoryChip &chip = this->chips[i_chip]; - if (chip.exists()) { - const std::uint16_t s = chip.size(); + const MemoryChip *chip = this->chips[i_chip]; + if (chip->exists()) { + const std::uint16_t s = chip->size(); if (size_new == 0u || s < size_new) { size_new = s; } @@ -88,9 +89,9 @@ void MemoryRow::powerOn() { std::uint8_t mask_bit = 1u; for (std::uint_fast8_t i_bit = 0; i_bit < 8; ++i_bit) { - const MemoryChip &chip = this->chips[i_bit]; - if (chip.exists()) { - chip.init(mask_bit, this->values_stored, size()); + const MemoryChip *chip = this->chips[i_bit]; + if (chip->exists()) { + chip->init(mask_bit, this->values_stored, size()); } mask_bit <<= 1; } @@ -129,3 +130,7 @@ void MemoryRow::write(const std::uint16_t address, const std::uint8_t data) { throw std::logic_error("cannot write memory when power is off"); } } + +std::string MemoryRow::chip_id(std::uint_fast8_t socket) const { + return this->chips[socket]->id(); +} diff --git a/src/memoryrow.h b/src/memoryrow.h index 52990ef..ed18fd5 100644 --- a/src/memoryrow.h +++ b/src/memoryrow.h @@ -15,7 +15,7 @@ class MemoryRow { bool power = false; /* 8 sockets for memory chips (empty socket represented by MemoryChipEmptySocket) */ - std::array chips = {{MemoryChipEmptySocket(),MemoryChipEmptySocket(),MemoryChipEmptySocket(),MemoryChipEmptySocket(),MemoryChipEmptySocket(),MemoryChipEmptySocket(),MemoryChipEmptySocket(),MemoryChipEmptySocket()}}; + std::array chips; /* bit mask of empty chip sockets */ std::uint8_t missing_bits = 0xFFu; @@ -32,7 +32,7 @@ class MemoryRow { MemoryRow(const char label); virtual ~MemoryRow(); - void insert_chip(MemoryChip chip, const std::uint_fast8_t socket); + void insert_chip(MemoryChip *chip, const std::uint_fast8_t socket); void remove_chip(const std::uint_fast8_t socket); void powerOff(); void powerOn(); @@ -44,6 +44,8 @@ class MemoryRow { void write(const std::uint16_t address, const std::uint8_t data); static std::uint8_t missing_memory_byte_value(); + + std::string chip_id(std::uint_fast8_t socket) const; }; #endif // MEMORYROW_H diff --git a/src/memorystrapping.cpp b/src/memorystrapping.cpp index 492127a..3bae794 100644 --- a/src/memorystrapping.cpp +++ b/src/memorystrapping.cpp @@ -11,7 +11,7 @@ void MemoryStrapping::strap_to(std::uint16_t addr_base, std::uint16_t addr_size) } bool MemoryStrapping::contains(std::uint16_t address) const { - return this->addr_base <= address && address < this->addr_base + std::min(this->row.size(), this->addr_size); + return this->addr_base <= address && address < this->addr_base + size(); } std::uint8_t MemoryStrapping::read(const std::uint16_t address) const { @@ -21,3 +21,7 @@ std::uint8_t MemoryStrapping::read(const std::uint16_t address) const { void MemoryStrapping::write(const std::uint16_t address, const std::uint8_t data) { this->row.write(address - this->addr_base, data); } + +std::uint16_t MemoryStrapping::size() const { + return std::min(this->row.size(), this->addr_size); +} diff --git a/src/memorystrapping.h b/src/memorystrapping.h index 79b0f22..5354774 100644 --- a/src/memorystrapping.h +++ b/src/memorystrapping.h @@ -15,6 +15,7 @@ class MemoryStrapping { bool contains(std::uint16_t address) const; std::uint8_t read(const std::uint16_t address) const; void write(const std::uint16_t address, const std::uint8_t data); + std::uint16_t size() const; }; #endif