Epple-II/src/memoryrandomaccess.cpp

183 lines
5.2 KiB
C++

#include "memoryrandomaccess.h"
#include <cstdint>
#include <cstdio>
#include <stdexcept>
#define K 1024u
MemoryRandomAccess::MemoryRandomAccess(int &revision):
revision(revision),
rowE('E'),
strapE(rowE),
rowD('D'),
strapD(rowD),
rowC('C'),
strapC(rowC) {
}
MemoryRow &MemoryRandomAccess::row_of(const std::string &row) {
if (row == "E") {
return this->rowE;
}
if (row == "D") {
return this->rowD;
}
if (row == "C") {
return this->rowC;
}
throw std::logic_error("expected C/D/E");
}
MemoryStrapping &MemoryRandomAccess::strapping_of(const std::string &row) {
if (row == "E") {
return this->strapE;
}
if (row == "D") {
return this->strapD;
}
if (row == "C") {
return this->strapC;
}
throw std::logic_error("expected C/D/E");
}
void MemoryRandomAccess::insert_chip(const std::string &row, MemoryChip *chip, const std::uint_fast8_t socket) {
row_of(row).insert_chip(chip, socket);
}
void MemoryRandomAccess::remove_chip(const std::string &row, const std::uint_fast8_t socket) {
row_of(row).remove_chip(socket);
}
void MemoryRandomAccess::strap_to(const std::string &row, std::uint16_t addr_base, std::uint16_t addr_size) {
strapping_of(row).strap_to(addr_base, addr_size);
}
bool MemoryRandomAccess::k20or24() const {
const std::uint32_t k = this->rowC.size() + this->rowD.size() + this->rowD.size();
return (k==20*K) || (k==24*K);
}
/* for 20K or 24K on rev. 0: pages 40-5F are dup w/ 60-7F */
std::uint8_t MemoryRandomAccess::buggyRamRead(const std::uint16_t address, std::uint8_t data) const {
std::uint16_t ax = address & ~0x2000u;
if (this->strapE.contains(ax)) {
return this->strapE.read(ax, data);
}
if (this->strapD.contains(ax)) {
return this->strapD.read(ax, data);
}
if (this->strapC.contains(ax)) {
return this->strapC.read(ax, data);
}
ax = address | 0x2000u;
if (this->strapE.contains(ax)) {
return this->strapE.read(ax, data);
}
if (this->strapD.contains(ax)) {
return this->strapD.read(ax, data);
}
if (this->strapC.contains(ax)) {
return this->strapC.read(ax, data);
}
return data;
}
std::uint8_t MemoryRandomAccess::read(const std::uint16_t address, std::uint8_t data) const {
if (this->revision == 0 && k20or24() && ((address & 0xC000u) == 0x4000u)) {
return buggyRamRead(address, data);
}
if (this->strapE.contains(address)) {
return this->strapE.read(address, data);
}
if (this->strapD.contains(address)) {
return this->strapD.read(address, data);
}
if (this->strapC.contains(address)) {
return this->strapC.read(address, data);
}
return data;
}
void MemoryRandomAccess::buggyRamWrite(std::uint16_t address, const std::uint8_t data) {
std::uint16_t ax = address & ~0x2000u;
if (this->strapE.contains(ax)) {
this->strapE.write(ax, data);
}
if (this->strapD.contains(ax)) {
this->strapD.write(ax, data);
}
if (this->strapC.contains(ax)) {
this->strapC.write(ax, data);
}
ax = address | 0x2000u;
if (this->strapE.contains(ax)) {
this->strapE.write(ax, data);
}
if (this->strapD.contains(ax)) {
this->strapD.write(ax, data);
}
if (this->strapC.contains(ax)) {
this->strapC.write(ax, data);
}
}
void MemoryRandomAccess::write(const std::uint16_t address, const std::uint8_t data) {
if (this->revision == 0 && k20or24() && ((address & 0xC000u) == 0x4000u)) {
buggyRamWrite(address, data);
}
if (this->strapE.contains(address)) {
this->strapE.write(address, data);
}
if (this->strapD.contains(address)) {
this->strapD.write(address, data);
}
if (this->strapC.contains(address)) {
this->strapC.write(address, data);
}
}
void MemoryRandomAccess::powerOn() {
this->rowE.powerOn();
this->rowD.powerOn();
this->rowC.powerOn();
}
void MemoryRandomAccess::powerOff() {
this->rowE.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);
}