incorporate floating data bus in RAM (instead of just ROM) reads; some more refactoring and cleanup

This commit is contained in:
Christopher Mosher 2019-06-23 23:25:09 -04:00
parent 5cdb608fe7
commit 17a714e550
17 changed files with 177 additions and 470 deletions

View File

@ -21,7 +21,7 @@ keyboard.cpp keyboardbuffermode.cpp languagecard.cpp filterchroma.cpp \
filterluma.cpp lss.cpp main.cpp memory.cpp \
memorychip.cpp memoryrow.cpp memorystrapping.cpp memoryrandomaccess.cpp \
paddlebuttonstates.cpp \
paddles.cpp picturegenerator.cpp powerupreset.cpp raminitializer.cpp \
paddles.cpp picturegenerator.cpp powerupreset.cpp \
screenimage.cpp slots.cpp speakerclicker.cpp standardin.cpp \
standardinproducer.cpp standardout.cpp textcharacters.cpp \
timable.cpp video.cpp videoaddressing.cpp videomode.cpp \
@ -40,7 +40,7 @@ hypermode.h keyboardbuffermode.h keyboard.h languagecard.h filterchroma.h \
filterluma.h lss.h memory.h \
memorychip.h memoryrow.h memorystrapping.h memoryrandomaccess.h \
paddlebuttonstates.h paddles.h picturegenerator.h \
powerupreset.h raminitializer.h screenimage.h slots.h speakerclicker.h \
powerupreset.h screenimage.h slots.h speakerclicker.h \
standardin.h standardinproducer.h standardout.h \
textcharacterimages.h textcharacters.h timable.h util.h \
videoaddressing.h video.h videomode.h videostaticgenerator.h wozfile.h \

View File

@ -28,14 +28,11 @@
#include "slots.h"
AddressBus::AddressBus(ScreenImage& gui, int& revision, MemoryRandomAccess& ram, Memory& rom, Keyboard& kbd, VideoMode& vid, Paddles& paddles, PaddleButtonStates& paddleButtonStates, SpeakerClicker& speaker, CassetteIn& cassetteIn, CassetteOut& cassetteOut, Slots& slts):
gui(gui), revision(revision), ram(ram), rom(rom), kbd(kbd), vid(vid), paddles(paddles), paddleButtonStates(paddleButtonStates), speaker(speaker), cassetteIn(cassetteIn), cassetteOut(cassetteOut), slts(slts)
{
gui(gui), revision(revision), ram(ram), rom(rom), kbd(kbd), vid(vid), paddles(paddles), paddleButtonStates(paddleButtonStates), speaker(speaker), cassetteIn(cassetteIn), cassetteOut(cassetteOut), slts(slts) {
}
AddressBus::~AddressBus()
{
}
AddressBus::~AddressBus() = default;
@ -45,70 +42,51 @@ AddressBus::~AddressBus()
unsigned char AddressBus::read(const unsigned short address)
{
if ((address >> 14 == 3)) // >= $C000
{
if ((address >> 12) == 0xC)
{
unsigned char AddressBus::read(const unsigned short address) {
if ((address >> 14) == 3) { // >= $C000
if ((address >> 12) == 0xC) {
// 11007sss,xxxxxxxx
const bool seventh = address & 0x0800;
const int slot = (address >> 8) & 7;
if (seventh)
{
this->data = this->slts.readSeventhRom(address & 0x07FF, this->data);
}
else if (slot == 0)
{
this->data = readSwitch(address & 0x00FF);
}
else
{
this->data = this->slts.readRom(slot,address & 0x00FF, this->data);
}
}
else
{
this->data = this->slts.ioBankRom(address - 0xD000,this->data,false);
if (!this->slts.inhibitMotherboardRom())
{
this->data = this->rom.read(address - 0xD000);
}
}
}
else // < $C000
{
this->data = this->ram.read(address);
}
const bool seventh = address & 0x0800;
const int slot = (address >> 8) & 7;
if (seventh) {
this->data = this->slts.readSeventhRom(address & 0x07FF, this->data);
} else if (slot == 0) {
readSwitch(address & 0x00FF);
} else {
this->data = this->slts.readRom(slot, address & 0x00FF, this->data);
}
} else {
this->data = this->slts.ioBankRom(address - 0xD000, this->data, false);
if (!this->slts.inhibitMotherboardRom()) {
this->data = this->rom.read(address - 0xD000, this->data);
}
}
} else { // < $C000
this->data = this->ram.read(address, this->data);
}
return this->data;
return this->data;
}
void AddressBus::write(const unsigned short address, const unsigned char d)
{
this->data = d;
void AddressBus::write(const unsigned short address, const unsigned char d) {
this->data = d;
if ((address >> 14 == 3)) // >= $C000
{
if ((address >> 12) == 0xC)
{
if ((address >> 14 == 3)) { // >= $C000
if ((address >> 12) == 0xC) {
// 11007sss,xxxxxxxx
const bool seventh = address & 0x0800;
const int slot = (address >> 8) & 7;
if (!seventh && slot == 0)
{
writeSwitch(address & 0x00FF);
}
}
else
{
this->slts.ioBankRom(address - 0xD000,this->data,true);
}
}
else // < $C000
{
this->ram.write(address,this->data);
}
const bool seventh = address & 0x0800;
const int slot = (address >> 8) & 7;
if (!seventh && slot == 0) {
writeSwitch(address & 0x00FF);
}
}
else {
this->data = this->slts.ioBankRom(address - 0xD000, this->data, true);
}
}
else { // < $C000
this->ram.write(address, this->data);
}
}
@ -118,122 +96,84 @@ void AddressBus::write(const unsigned short address, const unsigned char d)
unsigned char AddressBus::readSwitch(unsigned short address)
{
if (address < 0x80)
{
const int islot = (address >> 4) & 0xF;
const int iswch = (address & 0xF);
if (islot == 0x0)
{
this->data = this->kbd.get();
}
else if (islot == 0x1)
{
this->kbd.clear();
}
else if (islot == 0x2)
{
void AddressBus::setD7(const bool set) {
if (set) {
this->data |= 0x80;
} else {
this->data &= 0x7F;
}
}
void AddressBus::readSwitch(unsigned short address) {
if (address < 0x80) {
const int islot = (address >> 4) & 0xF;
const int iswch = (address & 0xF);
if (islot == 0x0) {
this->data = this->kbd.get();
} else if (islot == 0x1) {
this->kbd.clear();
} else if (islot == 0x2) {
this->cassetteOut.output();
}
else if (islot == 0x3)
{
} else if (islot == 0x3) {
if (this->revision == 0) {
this->cassetteOut.output();
}
this->speaker.click();
}
else if (islot == 0x4)
{
this->speaker.click();
} else if (islot == 0x4) {
// TODO ? utility strobe
}
else if (islot == 0x5)
{
if (iswch < 0x8)
{
this->data = this->vid.io(address,this->data);
}
else
{
} else if (islot == 0x5) {
if (iswch < 0x8) {
this->data = this->vid.io(address, this->data);
} else {
// 11000000,01011aaf
// aa = annunciator, 0-3
// f == on/off
const bool on = iswch & 1;
const int ann = (iswch >> 1) & 3;
this->gui.setAnnunciator(ann, on);
}
}
else if (islot == 0x6)
{
int sw2 = iswch & 0x7;
if (sw2 == 0)
{
}
} else if (islot == 0x6) {
int sw2 = iswch & 0x7;
if (sw2 == 0) {
setD7(this->cassetteIn.input());
}
else if (sw2 < 4)
{
setD7(this->paddleButtonStates.isDown(sw2-1));
}
else
{
sw2 &= 3;
setD7(!this->paddles.isTimedOut(sw2));
}
}
else if (islot == 0x7)
{
this->paddles.startTimers();
setD7(true);
}
}
else
{
// slot I/O switches
address &= 0x7F;
const int islot = (address >> 4) & 0xF;
const int iswch = (address & 0xF);
this->data = this->slts.io(islot,iswch,this->data,false);
}
return this->data;
} else if (sw2 < 4) {
setD7(this->paddleButtonStates.isDown(sw2-1));
} else {
sw2 &= 3;
setD7(!this->paddles.isTimedOut(sw2));
}
} else if (islot == 0x7) {
this->paddles.startTimers();
setD7(true);
}
} else {
// slot I/O switches
address &= 0x7F;
const int islot = (address >> 4) & 0xF;
const int iswch = (address & 0xF);
this->data = this->slts.io(islot, iswch, this->data, false);
}
}
void AddressBus::setD7(const bool set)
{
if (set)
{
this->data |= 0x80;
}
else
{
this->data &= 0x7F;
}
}
void AddressBus::writeSwitch(unsigned short address){
if (address < 0x80) {
const int islot = (address >> 4) & 0xF;
const int iswch = (address & 0xF);
void AddressBus::writeSwitch(unsigned short address)
{
if (address < 0x80)
{
const int islot = (address >> 4) & 0xF;
const int iswch = (address & 0xF);
if (islot == 0x1)
{
this->kbd.clear();
}
else if (islot == 0x5)
{
if (iswch < 0x8)
this->vid.io(address,this->data);
}
// ignore all other switch writes
}
else
{
// slot I/O switches
address &= 0x7F;
const int islot = (address >> 4) & 0xF;
const int iswch = (address & 0xF);
this->slts.io(islot,iswch,this->data,true);
}
if (islot == 0x1) {
this->kbd.clear();
} else if (islot == 0x5) {
if (iswch < 0x8) {
this->vid.io(address, this->data);
}
}
// ignore all other switch writes
} else {
// slot I/O switches
address &= 0x7F;
const int islot = (address >> 4) & 0xF;
const int iswch = (address & 0xF);
this->slts.io(islot, iswch, this->data, true);
}
}

View File

@ -33,9 +33,9 @@ class Slots;
class AddressBus {
private:
ScreenImage& gui;
int& revision;
const int& revision;
MemoryRandomAccess& ram;
Memory& rom;
Memory& rom; // TODO fix ROM so it doesn't use deprecated Memory class
Keyboard& kbd;
VideoMode& vid;
Paddles& paddles;
@ -47,21 +47,24 @@ class AddressBus {
unsigned char data; // this emulates the (floating) data bus
public:
void setD7(const bool set);
void readSwitch(unsigned short address);
void writeSwitch(unsigned short address);
public:
AddressBus(ScreenImage& gui, int& revision, MemoryRandomAccess& ram, Memory& rom, Keyboard& kbd, VideoMode& vid, Paddles& paddles, PaddleButtonStates& paddleButtonStates, SpeakerClicker& speaker, CassetteIn& cassetteIn, CassetteOut& cassetteOut, Slots& slts);
~AddressBus();
unsigned char read(const unsigned short address);
void write(const unsigned short address, const unsigned char d);
unsigned char readSwitch(unsigned short address);
void setD7(const bool set);
void writeSwitch(unsigned short address);
enum { MOTHERBOARD_RAM_BAS = 0x00000 } ;
enum { MOTHERBOARD_RAM_LIM = 0x0C000 } ;
enum { MOTHERBOARD_RAM_SIZ = MOTHERBOARD_RAM_LIM-MOTHERBOARD_RAM_BAS };
enum { MOTHERBOARD_ROM_BAS = 0x0D000 } ;
enum { MOTHERBOARD_ROM_LIM = 0x10000 } ;
enum { MOTHERBOARD_ROM_SIZ = MOTHERBOARD_ROM_LIM-MOTHERBOARD_ROM_BAS } ;
static const int MOTHERBOARD_RAM_BAS = 0x00000;
static const int MOTHERBOARD_RAM_LIM = 0x0C000;
static const int MOTHERBOARD_RAM_SIZ = MOTHERBOARD_RAM_LIM-MOTHERBOARD_RAM_BAS;
static const int MOTHERBOARD_ROM_BAS = 0x0D000;
static const int MOTHERBOARD_ROM_LIM = 0x10000;
static const int MOTHERBOARD_ROM_SIZ = MOTHERBOARD_ROM_LIM-MOTHERBOARD_ROM_BAS;
};
#endif

View File

@ -49,7 +49,7 @@ unsigned char Card::io(const unsigned short /*address*/, const unsigned char dat
unsigned char Card::readRom(const unsigned short address, const unsigned char data)
{
this->activeSeventhRom = true;
return this->rom.read(address);
return this->rom.read(address, data);
}
void Card::readSeventhRom(const unsigned short address, unsigned char* const pb)
@ -60,7 +60,7 @@ void Card::readSeventhRom(const unsigned short address, unsigned char* const pb)
}
else if (this->activeSeventhRom && hasSeventhRom())
{
*pb = this->seventhRom.read(address);
*pb = this->seventhRom.read(address, *pb);
}
}

View File

@ -96,14 +96,12 @@ void DiskController::tick() {
this->ioStepped = false;
return;
}
this->motor.tick(); // only need to send tick when motor is powered on
/*
* TODO
* Every CPU clock, add 8 to your bit timing clock. If your bit timing clock is >= optimal bit timing,
* then inject the next bit and subtract the optimal bit timing from your bit timing clock.
* That will give you 125ns resolution on your bits being fed to the sequencer.
*/
// run two LSS cycles = 2MHz
@ -118,10 +116,10 @@ void DiskController::tick() {
}
void DiskController::rotateCurrentDisk() {
this->t += 1.0f;
if (this->currentDrive->optimal_timing()/4.0f <= this->t) { // 4us interval between bits
this->t += 1.0;
if (this->currentDrive->optimal_timing()/4.0 <= this->t) { // wait for optimal interval between bits
this->currentDrive->rotateDiskOneBit(); // (will also generate a read-pulse when it reads a 1-bit)
this->t -= this->currentDrive->optimal_timing()/4.0f;
this->t -= this->currentDrive->optimal_timing()/4.0;
}
}

View File

@ -45,7 +45,7 @@ void FirmwareCard::ioBankRom(const unsigned short addr, unsigned char* const pb,
{
if (this->inhibitBankRom)
{
*pb = this->bankRom.read(addr);
*pb = this->bankRom.read(addr, *pb);
this->inhibit = true;
}
}
@ -53,7 +53,7 @@ void FirmwareCard::ioBankRom(const unsigned short addr, unsigned char* const pb,
{
if (this->inhibitF8Rom)
{
*pb = this->bankRom.read(addr);
*pb = this->bankRom.read(addr, *pb);
this->inhibit = true;
}
}

View File

@ -73,11 +73,11 @@ void LanguageCard::ioBankRom(const unsigned short addr, unsigned char* const pb,
{
if (addr < 0x1000)
{
*pb = this->ramBank[this->bank]->read(addr);
*pb = this->ramBank[this->bank]->read(addr, *pb);
}
else
{
*pb = this->ramTop.read(addr-0x1000);
*pb = this->ramTop.read(addr-0x1000, *pb);
}
this->inhibit = true;
}

View File

@ -22,29 +22,6 @@
#include <istream>
#include <cstdlib>
#include <cstddef>
#include "raminitializer.h"
/*
* If any RAM IC sockets are empty, set the corresponding bits to 1 most of the time.
* But set to 0 instead, with probability 1 in 137 (a rough estimate obtained empirically)
*/
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<double>(std::rand())/RAND_MAX;
if (r < 1.0/137.0) {
v &= ~bit;
} else {
v |= bit;
}
}
bit <<= 1;
}
return v;
}
@ -54,25 +31,16 @@ Memory::Memory(const size_t n):
missing_bits(0u) {
}
void Memory::clear() {
std::fill(this->bytes.begin(), this->bytes.end(), this->clear_value);
}
void Memory::init() {
RAMInitializer initRam(*this);
initRam.init();
}
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));
}
void Memory::powerOn() {
init();
clear();
}
void Memory::powerOff() {
@ -83,12 +51,8 @@ size_t Memory::size() const {
return this->bytes.size();
}
std::uint8_t Memory::read(const std::uint16_t address) const {
std::uint8_t v = this->bytes[address];
if (this->missing_bits) {
v = randomize_missing_bits(v, this->missing_bits);
}
return v;
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);
}
void Memory::write(const std::uint16_t address, const std::uint8_t data) {

View File

@ -30,10 +30,10 @@ class Memory {
public:
Memory(const size_t n);
virtual ~Memory() { }
virtual ~Memory() = default;
size_t size() const;
std::uint8_t read(const std::uint16_t address) const;
std::uint8_t read(const std::uint16_t address, const std::uint8_t data) const;
void write(const std::uint16_t address, const std::uint8_t data);
void powerOn();
void powerOff();

View File

@ -59,44 +59,44 @@ bool MemoryRandomAccess::k20or24() const {
}
/* 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) const {
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);
return this->strapE.read(ax, data);
}
if (this->strapD.contains(ax)) {
return this->strapD.read(ax);
return this->strapD.read(ax, data);
}
if (this->strapC.contains(ax)) {
return this->strapC.read(ax);
return this->strapC.read(ax, data);
}
ax = address | 0x2000u;
if (this->strapE.contains(ax)) {
return this->strapE.read(ax);
return this->strapE.read(ax, data);
}
if (this->strapD.contains(ax)) {
return this->strapD.read(ax);
return this->strapD.read(ax, data);
}
if (this->strapC.contains(ax)) {
return this->strapC.read(ax);
return this->strapC.read(ax, data);
}
return MemoryRow::missing_memory_byte_value();
return data;
}
std::uint8_t MemoryRandomAccess::read(const std::uint16_t address) const {
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);
return buggyRamRead(address, data);
}
if (this->strapE.contains(address)) {
return this->strapE.read(address);
return this->strapE.read(address, data);
}
if (this->strapD.contains(address)) {
return this->strapD.read(address);
return this->strapD.read(address, data);
}
if (this->strapC.contains(address)) {
return this->strapC.read(address);
return this->strapC.read(address, data);
}
return MemoryRow::missing_memory_byte_value();
return data;
}
void MemoryRandomAccess::buggyRamWrite(std::uint16_t address, const std::uint8_t data) {

View File

@ -18,7 +18,7 @@ class MemoryRandomAccess {
MemoryRow &row_of(const std::string &row);
MemoryStrapping &strapping_of(const std::string &row);
std::uint8_t buggyRamRead(std::uint16_t address) const;
std::uint8_t buggyRamRead(std::uint16_t address, std::uint8_t data) const;
void buggyRamWrite(std::uint16_t address, const std::uint8_t data);
bool k20or24() const;
@ -31,7 +31,7 @@ public:
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);
std::uint8_t read(std::uint16_t address) const;
std::uint8_t read(std::uint16_t address, const std::uint8_t data) const;
void write(std::uint16_t address, const std::uint8_t data);
void powerOn();
void powerOff();

View File

@ -2,27 +2,6 @@
#include <exception>
#include <cstdlib>
/*
* 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 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<double>(std::rand())/RAND_MAX;
if (r < 0.04) {
v &= ~bit;
} else {
v |= bit;
}
}
bit <<= 1;
}
return v;
}
MemoryRow::MemoryRow(const char label):
@ -102,22 +81,23 @@ std::uint16_t MemoryRow::size() const {
return static_cast<std::uint16_t>(this->values_stored.size());
}
std::uint8_t MemoryRow::missing_memory_byte_value() {
return randomize_missing_bits(0xFFu, 0xFFu);
}
std::uint8_t MemoryRow::read(const std::uint16_t address_offset) const {
std::uint8_t MemoryRow::read(const std::uint16_t address_offset, std::uint8_t data) const {
if (this->power) {
std::uint8_t v;
if (address_offset < this->values_stored.size()) {
v = this->values_stored[address_offset];
if (this->missing_bits) {
v = randomize_missing_bits(v, this->missing_bits);
}
} else {
v = missing_memory_byte_value();
/* We need to float the data bits corresponding to missing chips:
* 01010101 data bits (previously places on data bus from elsewhere)
* 00110011 mask of memory chips (1=missing, 0=present)
* 00001111 bits stored in chips
* --------
* 00010001 data & missing
* 11001100 ~missing
* 00001100 stored & ~missing
* --------
* 00011101 (stored & ~missing) | (data & missing)
*/
data = (this->values_stored[address_offset] & ~this->missing_bits) | (data & this->missing_bits);
}
return v;
return data;
} else {
throw std::logic_error("cannot read memory when power is off");
}
@ -125,6 +105,8 @@ std::uint8_t MemoryRow::read(const std::uint16_t address_offset) const {
void MemoryRow::write(const std::uint16_t address, const std::uint8_t data) {
if (this->power) {
// 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)
this->values_stored[address] = data;
} else {
throw std::logic_error("cannot write memory when power is off");

View File

@ -40,11 +40,9 @@ class MemoryRow {
/* 4K or 16K, size of each chip (or minimum in corner case of mixed sizes) */
std::uint16_t size() const;
std::uint8_t read(const std::uint16_t address) const;
std::uint8_t read(const std::uint16_t address, const std::uint8_t data) const;
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;
};

View File

@ -14,8 +14,8 @@ bool MemoryStrapping::contains(std::uint16_t address) const {
return this->addr_base <= address && address < this->addr_base + size();
}
std::uint8_t MemoryStrapping::read(const std::uint16_t address) const {
return this->row.read(address - this->addr_base);
std::uint8_t MemoryStrapping::read(const std::uint16_t address, const std::uint8_t data) const {
return this->row.read(address - this->addr_base, data);
}
void MemoryStrapping::write(const std::uint16_t address, const std::uint8_t data) {

View File

@ -13,7 +13,7 @@ class MemoryStrapping {
MemoryStrapping(MemoryRow &row);
void strap_to(std::uint16_t addr_base, std::uint16_t addr_size);
bool contains(std::uint16_t address) const;
std::uint8_t read(const std::uint16_t address) const;
std::uint8_t read(const std::uint16_t address, const std::uint8_t data) const;
void write(const std::uint16_t address, const std::uint8_t data);
std::uint16_t size() const;
};

View File

@ -1,137 +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 "raminitializer.h"
#include "memory.h"
#include <ctime>
#include <cstdlib>
RAMInitializer::RAMInitializer(Memory& mem):
ram(mem)
{
srand(time(0));
}
void RAMInitializer::init()
{
this->ram.clear();
int b(0);
// TODO make the types of RAM chips configurable
putBytesUntilFull(b++,1);
putBytesUntilFull(b++,2);
putBytesUntilFull(b++,1);
putBytesUntilFull(b++,2);
putBytesUntilFull(b++,1);
putBytesUntilFull(b++,2);
putBytesUntilFull(b++,2);
putBytesUntilFull(b++,1);
}
void RAMInitializer::putBytesUntilFull(int bit, int pat)
{
this->nextinit = 0;
try
{
while (true)
{
if (pat==1)
ramPattern1(bit);
else
ramPattern2(bit);
}
}
catch (const done&)
{
// done filling this bit in RAM
}
}
void RAMInitializer::ramPattern1(const int bit)
{
for (int k = 0; k < 2; ++k)
{
for (int j = 0; j < 8; ++j)
{
int i;
for (i = 0; i < 0x10; ++i)
{
putn(4,false,bit);
putn(2,true,bit);
putn(2,false,bit);
}
for (i = 0; i < 0x40; ++i)
{
putn(2,true,bit);
putn(2,false,bit);
}
for (i = 0; i < 0x08; ++i)
{
putn(2,true,bit);
putn(1,false,bit);
putn(3,true,bit);
putn(2,false,bit);
putn(2,true,bit);
putn(2,false,bit);
putn(2,true,bit);
putn(2,false,bit);
}
}
for (int i = 0; i < 0x400; ++i)
{
putn(2,true,bit);
putn(2,false,bit);
}
}
}
void RAMInitializer::ramPattern2(const int bit)
{
for (int i = 0; i < 0x40; ++i)
{
putn(0x80,true,bit);
putn(0x80,false,bit);
}
}
void RAMInitializer::putn(const int c, bool on, const int bit)
{
if (((rand() >> 9) & 0x1F) == 5)
on = !on;
const unsigned char mask(1 << bit);
for (int i = 0; i < c; ++i)
{
if (this->nextinit >= this->ram.size())
{
throw done();
}
unsigned char b = this->ram.read(this->nextinit);
if (on)
{
b |= mask;
}
else
{
b &= ~mask;
}
this->ram.write(this->nextinit,b);
++this->nextinit;
}
}

View File

@ -1,41 +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 RAMINITIALIZER_H
#define RAMINITIALIZER_H
class Memory;
class RAMInitializer
{
private:
class done {};
Memory& ram;
unsigned short nextinit;
void putBytesUntilFull(int bit, int pat);
void ramPattern1(const int bit);
void ramPattern2(const int bit);
void putn(const int c, bool on, const int bit);
public:
RAMInitializer(Memory& mem);
void init();
};
#endif