mirror of
https://github.com/cmosher01/Epple-II.git
synced 2024-12-26 10:32:56 +00:00
replace cpu with 6502 emulator
This commit is contained in:
parent
97419f5538
commit
a217a0a096
78
src/Circuit.cpp
Normal file
78
src/Circuit.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* File: Circuit.cpp
|
||||
* Author: Christopher
|
||||
*
|
||||
* Created on December 12, 2013, 7:04 PM
|
||||
*/
|
||||
|
||||
#include "Circuit.h"
|
||||
#include "trans.h"
|
||||
|
||||
/*
|
||||
* Adds segment extendFrom, and all segments electrically connected to it.
|
||||
* This happens recursively, but we don't recurse past ground or voltage supply.
|
||||
*/
|
||||
void Circuit::extend(Segment* extendFrom) {
|
||||
auto ret = this->segs.insert(extendFrom);
|
||||
if (!ret.second) {
|
||||
/* We've already processed this segment. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Don't recurse past ground or voltage supply. */
|
||||
if (extendFrom->vss || extendFrom->vcc) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* For every ON transistor this seg is connected to via a leg (source or
|
||||
* drain), add the seg that's connected to the OTHER leg of the transistor.
|
||||
* This is a RECURSIVE addition.
|
||||
*
|
||||
* Also note that, upon system startup, all transistors are initialized
|
||||
* to OFF, so at the time of the very first recalcAll call, *no* other
|
||||
* segments will be added here.
|
||||
*/
|
||||
for (auto t : extendFrom->c1c2s) {
|
||||
if (t->on) {
|
||||
if (t->c1 == extendFrom) {
|
||||
extend(t->c2);
|
||||
} else if (t->c2 == extendFrom) {
|
||||
extend(t->c1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Upon system startup, this will return the "pullup" value of
|
||||
* each segment, except for VCC and VSS (which will of course be
|
||||
* ON and OFF respectively).
|
||||
*/
|
||||
bool Circuit::getValue() {
|
||||
/* If group contains ground, it's OFF, */
|
||||
for (auto s : this->segs) {
|
||||
if (s->vss) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* otherwise, if any segment in the group is not floating,
|
||||
* return that segment as the value, otherwise if any floating
|
||||
* segment is ON, then return ON as the value.
|
||||
*/
|
||||
for (auto s : this->segs) {
|
||||
if (s->pull != Pull::FLOAT) {
|
||||
return (s->pull == Pull::UP);
|
||||
} else if (s->on) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* otherwise, if we get here, it means that all segments in the
|
||||
* group are floating and OFF, so return OFF as the value.
|
||||
*/
|
||||
return false;
|
||||
}
|
49
src/Circuit.h
Normal file
49
src/Circuit.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* File: Circuit.h
|
||||
* Author: Christopher
|
||||
*
|
||||
* Created on December 12, 2013, 7:04 PM
|
||||
*/
|
||||
|
||||
#ifndef CIRCUIT_H
|
||||
#define CIRCUIT_H
|
||||
|
||||
#include "SegmentTypes.h"
|
||||
#include <set>
|
||||
|
||||
/*
|
||||
* Builds a circuit, given one segment in that circuit.
|
||||
* Extends the given segment by traversing the ON
|
||||
* transistors it is connected to, recursively, until
|
||||
* hitting ground and voltage supply. Provides iterators
|
||||
* for retrieving all the circuit's segments, and a method
|
||||
* to get the ON value of the circuit.
|
||||
*/
|
||||
class Circuit final {
|
||||
public:
|
||||
|
||||
Circuit(Segment* extendFrom) {
|
||||
extend(extendFrom);
|
||||
}
|
||||
|
||||
bool getValue();
|
||||
|
||||
SegmentSet::iterator begin() {
|
||||
return this->segs.begin();
|
||||
}
|
||||
|
||||
SegmentSet::iterator end() {
|
||||
return this->segs.end();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Circuit(const Circuit&) = delete;
|
||||
Circuit& operator=(const Circuit&) = delete;
|
||||
|
||||
void extend(Segment* extendFrom);
|
||||
|
||||
SegmentSet segs;
|
||||
};
|
||||
|
||||
#endif /* CIRCUIT_H */
|
83
src/Common.cpp
Normal file
83
src/Common.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* File: Common.cpp
|
||||
* Author: Christopher
|
||||
*
|
||||
* Created on December 14, 2013, 8:47 PM
|
||||
*/
|
||||
|
||||
#include "Common.h"
|
||||
#include "TransNetwork.h"
|
||||
#include "SegmentCache.h"
|
||||
#include "trans.h"
|
||||
|
||||
Common::Common(const TransNetwork& tn) :
|
||||
Common(
|
||||
tn.segs.get("-vss"), tn.segs.get("+vcc"),
|
||||
tn.segs.get("-clk0"),
|
||||
tn.segs.get("-irq"), tn.segs.get("-res"), tn.segs.get("-nmi"),
|
||||
tn.segs.get("+rdy"), tn.segs.get("+so"),
|
||||
tn.segs.get("-db0"), tn.segs.get("-db1"), tn.segs.get("-db2"), tn.segs.get("-db3"), tn.segs.get("-db4"), tn.segs.get("-db5"), tn.segs.get("-db6"), tn.segs.get("-db7"),
|
||||
tn.segs.get("-ab0"), tn.segs.get("-ab1"), tn.segs.get("-ab2"), tn.segs.get("-ab3"), tn.segs.get("-ab4"), tn.segs.get("-ab5"), tn.segs.get("-ab6"), tn.segs.get("-ab7"),
|
||||
tn.segs.get("-ab8"), tn.segs.get("-ab9"), tn.segs.get("-ab10"), tn.segs.get("-ab11"), tn.segs.get("-ab12"), tn.segs.get("-ab13"), tn.segs.get("-ab14"), tn.segs.get("-ab15"),
|
||||
tn.segs.get("-rw"), tn.segs.get("-sync"),
|
||||
tn.segs.get("-clk1out"), tn.segs.get("-clk2out"),
|
||||
tn.segs.get("-a0"), tn.segs.get("-a1"), tn.segs.get("-a2"), tn.segs.get("-a3"), tn.segs.get("-a4"), tn.segs.get("-a5"), tn.segs.get("-a6"), tn.segs.get("-a7"),
|
||||
tn.segs.get("-x0"), tn.segs.get("-x1"), tn.segs.get("-x2"), tn.segs.get("-x3"), tn.segs.get("-x4"), tn.segs.get("-x5"), tn.segs.get("-x6"), tn.segs.get("-x7"),
|
||||
tn.segs.get("-y0"), tn.segs.get("-y1"), tn.segs.get("-y2"), tn.segs.get("-y3"), tn.segs.get("-y4"), tn.segs.get("-y5"), tn.segs.get("-y6"), tn.segs.get("-y7"),
|
||||
tn.segs.get("-pcl0"), tn.segs.get("-pcl1"), tn.segs.get("-pcl2"), tn.segs.get("-pcl3"), tn.segs.get("-pcl4"), tn.segs.get("-pcl5"), tn.segs.get("-pcl6"), tn.segs.get("-pcl7"),
|
||||
tn.segs.get("-pch0"), tn.segs.get("-pch1"), tn.segs.get("-pch2"), tn.segs.get("-pch3"), tn.segs.get("-pch4"), tn.segs.get("-pch5"), tn.segs.get("-pch6"), tn.segs.get("-pch7"),
|
||||
tn.segs.get("+Pout0"), tn.segs.get("+Pout1"), tn.segs.get("+Pout2"), tn.segs.get("+Pout3"), tn.segs.get("+Pout4"), /*no P5 */tn.segs.get("+Pout6"), tn.segs.get("+Pout7"),
|
||||
tn.segs.get("-s0"), tn.segs.get("-s1"), tn.segs.get("-s2"), tn.segs.get("-s3"), tn.segs.get("-s4"), tn.segs.get("-s5"), tn.segs.get("-s6"), tn.segs.get("-s7")) {
|
||||
}
|
||||
|
||||
unsigned short Common::rAddr() const {
|
||||
return Segment::asWord(this->AB15, this->AB14, this->AB13, this->AB12, this->AB11, this->AB10, this->AB9, this->AB8, this->AB7, this->AB6, this->AB5, this->AB4, this->AB3, this->AB2, this->AB1, this->AB0);
|
||||
}
|
||||
|
||||
unsigned char Common::rData() const {
|
||||
return Segment::asByte(this->DB7, this->DB6, this->DB5, this->DB4, this->DB3, this->DB2, this->DB1, this->DB0);
|
||||
}
|
||||
|
||||
unsigned char Common::rA() const {
|
||||
return Segment::asByte(this->A7, this->A6, this->A5, this->A4, this->A3, this->A2, this->A1, this->A0);
|
||||
}
|
||||
|
||||
unsigned char Common::rX() const {
|
||||
return Segment::asByte(this->X7, this->X6, this->X5, this->X4, this->X3, this->X2, this->X1, this->X0);
|
||||
}
|
||||
|
||||
unsigned char Common::rY() const {
|
||||
return Segment::asByte(this->Y7, this->Y6, this->Y5, this->Y4, this->Y3, this->Y2, this->Y1, this->Y0);
|
||||
}
|
||||
|
||||
unsigned char Common::rS() const {
|
||||
return Segment::asByte(this->S7, this->S6, this->S5, this->S4, this->S3, this->S2, this->S1, this->S0);
|
||||
}
|
||||
|
||||
unsigned short Common::rPC() const {
|
||||
return Segment::asWord(this->PCH7, this->PCH6, this->PCH5, this->PCH4, this->PCH3, this->PCH2, this->PCH1, this->PCH0, this->PCL7, this->PCL6, this->PCL5, this->PCL4, this->PCL3, this->PCL2, this->PCL1, this->PCL0);
|
||||
}
|
||||
|
||||
PinSettings Common::getDataPinSettings(const unsigned char data) const {
|
||||
unsigned char x = data;
|
||||
|
||||
PinSettings ps;
|
||||
|
||||
ps.insert(std::make_pair(this->DB0,x & 1));
|
||||
x >>= 1;
|
||||
ps.insert(std::make_pair(this->DB1,x & 1));
|
||||
x >>= 1;
|
||||
ps.insert(std::make_pair(this->DB2,x & 1));
|
||||
x >>= 1;
|
||||
ps.insert(std::make_pair(this->DB3,x & 1));
|
||||
x >>= 1;
|
||||
ps.insert(std::make_pair(this->DB4,x & 1));
|
||||
x >>= 1;
|
||||
ps.insert(std::make_pair(this->DB5,x & 1));
|
||||
x >>= 1;
|
||||
ps.insert(std::make_pair(this->DB6,x & 1));
|
||||
x >>= 1;
|
||||
ps.insert(std::make_pair(this->DB7,x & 1));
|
||||
|
||||
return ps;
|
||||
}
|
88
src/Common.h
Normal file
88
src/Common.h
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* File: Common.h
|
||||
* Author: Christopher
|
||||
*
|
||||
* Created on December 14, 2013, 8:47 PM
|
||||
*/
|
||||
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
#include "SegmentTypes.h"
|
||||
|
||||
class TransNetwork;
|
||||
|
||||
class Common final {
|
||||
public:
|
||||
|
||||
Segment * const VSS, * const VCC;
|
||||
Segment * const CLK0;
|
||||
Segment * const IRQ, * const RES, * const NMI;
|
||||
Segment * const RDY, * const SO;
|
||||
Segment * const DB0, * const DB1, * const DB2, * const DB3, * const DB4, * const DB5, * const DB6, * const DB7;
|
||||
Segment * const AB0, * const AB1, * const AB2, * const AB3, * const AB4, * const AB5, * const AB6, * const AB7, * const AB8, * const AB9, * const AB10, * const AB11, * const AB12, * const AB13, * const AB14, * const AB15;
|
||||
Segment * const RW, * const SYNC;
|
||||
Segment * const CLK1OUT, * const CLK2OUT;
|
||||
Segment * const A0, * const A1, * const A2, * const A3, * const A4, * const A5, * const A6, * const A7;
|
||||
Segment * const X0, * const X1, * const X2, * const X3, * const X4, * const X5, * const X6, * const X7;
|
||||
Segment * const Y0, * const Y1, * const Y2, * const Y3, * const Y4, * const Y5, * const Y6, * const Y7;
|
||||
Segment * const PCL0, * const PCL1, * const PCL2, * const PCL3, * const PCL4, * const PCL5, * const PCL6, * const PCL7;
|
||||
Segment * const PCH0, * const PCH1, * const PCH2, * const PCH3, * const PCH4, * const PCH5, * const PCH6, * const PCH7;
|
||||
Segment * const P0, * const P1, * const P2, * const P3, * const P4, /* no P5 */ * const P6, * const P7;
|
||||
Segment * const S0, * const S1, * const S2, * const S3, * const S4, * const S5, * const S6, * const S7;
|
||||
|
||||
|
||||
|
||||
Common(const TransNetwork& segs);
|
||||
|
||||
unsigned char rA() const;
|
||||
unsigned char rX() const;
|
||||
unsigned char rY() const;
|
||||
unsigned char rS() const;
|
||||
unsigned short rPC() const;
|
||||
unsigned short rAddr() const;
|
||||
unsigned char rData() const;
|
||||
|
||||
PinSettings getDataPinSettings(const unsigned char data) const;
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
Common(
|
||||
Segment* VSS, Segment* VCC,
|
||||
Segment* CLK0,
|
||||
Segment* IRQ, Segment* RES, Segment* NMI,
|
||||
Segment* RDY, Segment* SO,
|
||||
Segment* DB0, Segment* DB1, Segment* DB2, Segment* DB3, Segment* DB4, Segment* DB5, Segment* DB6, Segment* DB7,
|
||||
Segment* AB0, Segment* AB1, Segment* AB2, Segment* AB3, Segment* AB4, Segment* AB5, Segment* AB6, Segment* AB7,
|
||||
Segment* AB8, Segment* AB9, Segment* AB10, Segment* AB11, Segment* AB12, Segment* AB13, Segment* AB14, Segment* AB15,
|
||||
Segment* RW, Segment* SYNC,
|
||||
Segment* CLK1OUT, Segment* CLK2OUT,
|
||||
Segment* A0, Segment* A1, Segment* A2, Segment* A3, Segment* A4, Segment* A5, Segment* A6, Segment* A7,
|
||||
Segment* X0, Segment* X1, Segment* X2, Segment* X3, Segment* X4, Segment* X5, Segment* X6, Segment* X7,
|
||||
Segment* Y0, Segment* Y1, Segment* Y2, Segment* Y3, Segment* Y4, Segment* Y5, Segment* Y6, Segment* Y7,
|
||||
Segment* PCL0, Segment* PCL1, Segment* PCL2, Segment* PCL3, Segment* PCL4, Segment* PCL5, Segment* PCL6, Segment* PCL7,
|
||||
Segment* PCH0, Segment* PCH1, Segment* PCH2, Segment* PCH3, Segment* PCH4, Segment* PCH5, Segment* PCH6, Segment* PCH7,
|
||||
Segment* P0, Segment* P1, Segment* P2, Segment* P3, Segment* P4, /* no P5 */ Segment* P6, Segment* P7,
|
||||
Segment* S0, Segment* S1, Segment* S2, Segment* S3, Segment* S4, Segment* S5, Segment* S6, Segment* S7) :
|
||||
VSS(VSS), VCC(VCC),
|
||||
CLK0(CLK0),
|
||||
IRQ(IRQ), RES(RES), NMI(NMI),
|
||||
RDY(RDY), SO(SO),
|
||||
DB0(DB0), DB1(DB1), DB2(DB2), DB3(DB3), DB4(DB4), DB5(DB5), DB6(DB6), DB7(DB7),
|
||||
AB0(AB0), AB1(AB1), AB2(AB2), AB3(AB3), AB4(AB4), AB5(AB5), AB6(AB6), AB7(AB7),
|
||||
AB8(AB8), AB9(AB9), AB10(AB10), AB11(AB11), AB12(AB12), AB13(AB13), AB14(AB14), AB15(AB15),
|
||||
RW(RW), SYNC(SYNC),
|
||||
CLK1OUT(CLK1OUT), CLK2OUT(CLK2OUT),
|
||||
A0(A0), A1(A1), A2(A2), A3(A3), A4(A4), A5(A5), A6(A6), A7(A7),
|
||||
X0(X0), X1(X1), X2(X2), X3(X3), X4(X4), X5(X5), X6(X6), X7(X7),
|
||||
Y0(Y0), Y1(Y1), Y2(Y2), Y3(Y3), Y4(Y4), Y5(Y5), Y6(Y6), Y7(Y7),
|
||||
PCL0(PCL0), PCL1(PCL1), PCL2(PCL2), PCL3(PCL3), PCL4(PCL4), PCL5(PCL5), PCL6(PCL6), PCL7(PCL7),
|
||||
PCH0(PCH0), PCH1(PCH1), PCH2(PCH2), PCH3(PCH3), PCH4(PCH4), PCH5(PCH5), PCH6(PCH6), PCH7(PCH7),
|
||||
P0(P0), P1(P1), P2(P2), P3(P3), P4(P4), /* no P5 */ P6(P6), P7(P7),
|
||||
S0(S0), S1(S1), S2(S2), S3(S3), S4(S4), S5(S5), S6(S6), S7(S7) {
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* COMMON_H */
|
63
src/Cpu6502.cpp
Normal file
63
src/Cpu6502.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* File: Cpu6502.cpp
|
||||
* Author: Christopher
|
||||
*
|
||||
* Created on December 12, 2013, 10:14 PM
|
||||
*/
|
||||
|
||||
#include "Cpu6502.h"
|
||||
#include "addressbus.h"
|
||||
#include "StateCalculator.h"
|
||||
#include "Trace.h"
|
||||
#include "Common.h"
|
||||
#include "trans.h"
|
||||
|
||||
|
||||
|
||||
#define TRACEREG 1
|
||||
//#define TRACESEG 1
|
||||
|
||||
|
||||
|
||||
|
||||
void Cpu6502::setPins(const PinSettings& ps) {
|
||||
SegmentSet rec;
|
||||
for (auto p : ps) {
|
||||
p.first->set(p.second);
|
||||
rec.insert(p.first);
|
||||
}
|
||||
StateCalculator::recalc(rec);
|
||||
}
|
||||
|
||||
void Cpu6502::clock(bool phase) {
|
||||
setPins(PinSettings{std::make_pair(common.CLK0,phase)});
|
||||
rw();
|
||||
|
||||
#ifdef TRACEREG
|
||||
this->trace.dumpRegisters();
|
||||
#endif
|
||||
|
||||
#ifdef TRACESEG
|
||||
this->trace.dumpSegments();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Cpu6502::rw() {
|
||||
/* database read/write happens (only) during Clock Phase 2 */
|
||||
if (common.CLK2OUT->on) {
|
||||
readData();
|
||||
writeData();
|
||||
}
|
||||
}
|
||||
|
||||
void Cpu6502::readData() {
|
||||
if (this->common.RW->on) {
|
||||
setPins(this->common.getDataPinSettings(this->addressBus.read(this->common.rAddr())));
|
||||
}
|
||||
}
|
||||
|
||||
void Cpu6502::writeData() {
|
||||
if (!this->common.RW->on) {
|
||||
this->addressBus.write(this->common.rAddr(), this->common.rData());
|
||||
}
|
||||
}
|
45
src/Cpu6502.h
Normal file
45
src/Cpu6502.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* File: Cpu6502.h
|
||||
* Author: Christopher
|
||||
*
|
||||
* Created on December 12, 2013, 10:14 PM
|
||||
*/
|
||||
|
||||
#ifndef CPU6502_H
|
||||
#define CPU6502_H
|
||||
|
||||
#include "SegmentTypes.h"
|
||||
#include "Trace.h"
|
||||
|
||||
class AddressBus;
|
||||
class Trace;
|
||||
class Common;
|
||||
|
||||
class Cpu6502 final {
|
||||
public:
|
||||
|
||||
Cpu6502(AddressBus& addressBus, Trace& trace, Common& common) : addressBus(addressBus), trace(trace), common(common) {
|
||||
#if 0
|
||||
trace.dumpTransistors();
|
||||
#endif
|
||||
}
|
||||
|
||||
void setPins(const PinSettings& ps);
|
||||
void clock(bool phase);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
Cpu6502(const Cpu6502&) = delete;
|
||||
Cpu6502& operator=(const Cpu6502&) = delete;
|
||||
|
||||
void rw();
|
||||
void readData();
|
||||
void writeData();
|
||||
|
||||
AddressBus& addressBus;
|
||||
Trace& trace;
|
||||
Common& common;
|
||||
};
|
||||
|
||||
#endif /* CPU6502_H */
|
72
src/Cpu6502Helper.cpp
Normal file
72
src/Cpu6502Helper.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* File: Cpu6502Helper.cpp
|
||||
* Author: Christopher
|
||||
*
|
||||
* Created on December 12, 2013, 10:22 PM
|
||||
*/
|
||||
|
||||
#include "Cpu6502Helper.h"
|
||||
#include "Cpu6502.h"
|
||||
#include "Common.h"
|
||||
#include "SegmentTypes.h"
|
||||
|
||||
void Cpu6502Helper::powerOn() {
|
||||
PinSettings ps;
|
||||
|
||||
// set voltage supply and ground.
|
||||
ps.insert(std::make_pair(this->common.VCC, true));
|
||||
ps.insert(std::make_pair(this->common.VSS, false));
|
||||
|
||||
// don't do the set-overflow overriding functionality
|
||||
ps.insert(std::make_pair(this->common.SO, false));
|
||||
|
||||
// ready to run (i.e., do not do single-stepping of instructions)
|
||||
ps.insert(std::make_pair(this->common.RDY, true));
|
||||
|
||||
// pull up to indicate that we are not interrupting now
|
||||
ps.insert(std::make_pair(this->common.IRQ, true));
|
||||
ps.insert(std::make_pair(this->common.NMI, true));
|
||||
|
||||
|
||||
/*
|
||||
* RES_BAR pin means "not resetting". Since it is a negated pin, pulling it low means "resetting"
|
||||
* and pulling it high means "not resetting" or equivalently "running".
|
||||
*/
|
||||
|
||||
/*
|
||||
* RES_BAR false: resetting now (i.e., in power-up now; pull high to begin normal operation)
|
||||
* We want to hold RES_BAR low for a while, indicating power-up phase during which the
|
||||
* CPU does not start up normal operations yet. The caller can set RES_BAR high (by calling
|
||||
* reset) whenever he is ready to start the CPU running.
|
||||
*/
|
||||
ps.insert(std::make_pair(this->common.RES, false));
|
||||
|
||||
this->cpu.setPins(ps);
|
||||
|
||||
this->nextPhase = true;
|
||||
}
|
||||
|
||||
void Cpu6502Helper::tick() {
|
||||
step();
|
||||
step();
|
||||
}
|
||||
|
||||
void Cpu6502Helper::step() {
|
||||
/*
|
||||
* We cheat a little bit here: instead of requiring the
|
||||
* caller to toggle clock-zero pin, we let him just call
|
||||
* "step" and *we* keep track of which phase we are in.
|
||||
* To do this, we just use the CLK0 segment value (as
|
||||
* a kind of temporary variable), and just toggle it in
|
||||
* order to know which phase we are going into.
|
||||
*
|
||||
* The real 6502, of course, does not do this.
|
||||
*/
|
||||
this->nextPhase = !this->nextPhase;
|
||||
|
||||
this->cpu.clock(this->nextPhase);
|
||||
}
|
||||
|
||||
void Cpu6502Helper::reset() {
|
||||
this->cpu.setPins(PinSettings{std::make_pair(this->common.RES, true)});
|
||||
}
|
37
src/Cpu6502Helper.h
Normal file
37
src/Cpu6502Helper.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* File: Cpu6502Helper.h
|
||||
* Author: Christopher
|
||||
*
|
||||
* Created on December 12, 2013, 10:22 PM
|
||||
*/
|
||||
|
||||
#ifndef CPU6502HELPER_H
|
||||
#define CPU6502HELPER_H
|
||||
|
||||
class Cpu6502;
|
||||
class Common;
|
||||
|
||||
class Cpu6502Helper final {
|
||||
public:
|
||||
|
||||
Cpu6502Helper(Cpu6502& cpu, Common& common) : cpu(cpu), common(common), nextPhase(true) {
|
||||
}
|
||||
|
||||
void powerOn();
|
||||
void tick();
|
||||
void reset();
|
||||
|
||||
private:
|
||||
|
||||
Cpu6502Helper(const Cpu6502Helper&) = delete;
|
||||
Cpu6502Helper& operator=(const Cpu6502Helper&) = delete;
|
||||
|
||||
void step();
|
||||
|
||||
Cpu6502& cpu;
|
||||
Common& common;
|
||||
|
||||
bool nextPhase;
|
||||
};
|
||||
|
||||
#endif /* CPU6502HELPER_H */
|
8
src/Emu6502.cpp
Normal file
8
src/Emu6502.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
/*
|
||||
* File: Emu6502.cpp
|
||||
* Author: Christopher
|
||||
*
|
||||
* Created on December 15, 2013, 12:43 AM
|
||||
*/
|
||||
|
||||
#include "Emu6502.h"
|
57
src/Emu6502.h
Normal file
57
src/Emu6502.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* File: Emu6502.h
|
||||
* Author: Christopher
|
||||
*
|
||||
* Created on December 15, 2013, 12:43 AM
|
||||
*/
|
||||
|
||||
#ifndef EMU6502_H
|
||||
#define EMU6502_H
|
||||
|
||||
#include "Cpu6502Helper.h"
|
||||
#include "Cpu6502.h"
|
||||
#include "Trace.h"
|
||||
#include "Common.h"
|
||||
#include "TransNetwork.h"
|
||||
#include "TransCache.h"
|
||||
#include "SegmentCache.h"
|
||||
#include <istream>
|
||||
|
||||
class AddressBus;
|
||||
|
||||
class Emu6502 {
|
||||
public:
|
||||
|
||||
Emu6502(std::istream& transistors, AddressBus& mem) : tn(transistors, segs, transes), c(tn), trace(segs, transes, c), cpu(mem, trace, c), cpuhelper(cpu, c) {
|
||||
}
|
||||
|
||||
virtual ~Emu6502() {
|
||||
}
|
||||
|
||||
void powerOn() {
|
||||
this->cpuhelper.powerOn();
|
||||
}
|
||||
|
||||
void tick() {
|
||||
this->cpuhelper.tick();
|
||||
}
|
||||
|
||||
void reset() {
|
||||
this->cpuhelper.reset();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Emu6502(const Emu6502&) = delete;
|
||||
Emu6502 operator=(const Emu6502&) = delete;
|
||||
|
||||
SegmentCache segs;
|
||||
TransCache transes;
|
||||
TransNetwork tn;
|
||||
Common c;
|
||||
Trace trace;
|
||||
Cpu6502 cpu;
|
||||
Cpu6502Helper cpuhelper;
|
||||
};
|
||||
|
||||
#endif /* EMU6502_H */
|
@ -20,7 +20,9 @@ epple2_SOURCES = a2colorsobserved.cpp addressbus.cpp analogtv.cpp apple2.cpp \
|
||||
screenimage.cpp slots.cpp speakerclicker.cpp standardin.cpp \
|
||||
standardinproducer.cpp standardout.cpp steppermotor.cpp textcharacters.cpp \
|
||||
timable.cpp video.cpp videoaddressing.cpp videomode.cpp \
|
||||
videostaticgenerator.cpp
|
||||
videostaticgenerator.cpp \
|
||||
Circuit.cpp Common.cpp Cpu6502.cpp Cpu6502Helper.cpp Emu6502.cpp SegmentCache.cpp \
|
||||
StateCalculator.cpp Trace.cpp TransCache.cpp TransNetwork.cpp v6502.cpp
|
||||
|
||||
noinst_HEADERS = a2colorsobserved.h addressbus.h analogtv.h apple2.h applentsc.h \
|
||||
card.h cassette.h clipboardhandler.h clockcard.h configep2.h cpu.h diskbytes.h \
|
||||
@ -30,4 +32,6 @@ noinst_HEADERS = a2colorsobserved.h addressbus.h analogtv.h apple2.h applentsc.h
|
||||
powerupreset.h raminitializer.h screenimage.h slots.h speakerclicker.h \
|
||||
standardin.h standardinproducer.h standardout.h steppermotor.h \
|
||||
textcharacterimages.h textcharacters.h timable.h util.h \
|
||||
videoaddressing.h video.h videomode.h videostaticgenerator.h
|
||||
videoaddressing.h video.h videomode.h videostaticgenerator.h \
|
||||
Circuit.h Common.h Cpu6502.h Cpu6502Helper.h Emu6502.h SegmentCache.h SegmentTypes.h \
|
||||
StateCalculator.h Trace.h TransCache.h TransNetwork.h addressbus.h ptr_less.h trans.h
|
||||
|
53
src/SegmentCache.cpp
Normal file
53
src/SegmentCache.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* File: SegmentCache.cpp
|
||||
* Author: cmosher
|
||||
*
|
||||
* Created on December 10, 2013, 9:56 PM
|
||||
*/
|
||||
|
||||
#include "SegmentCache.h"
|
||||
#include "trans.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
bool SegmentCache::cached(const std::string& id) const {
|
||||
return this->cache.find(id) != this->cache.end();
|
||||
}
|
||||
|
||||
Segment* SegmentCache::getOrAdd(const std::string& id) {
|
||||
if (!cached(id)) {
|
||||
this->cache[id] = std::make_shared<Segment>(id);
|
||||
|
||||
/*
|
||||
* We want to optimize VSS and VCC checking in
|
||||
* the rest of the program, so we check here
|
||||
* for those two special cases, and flag them.
|
||||
* So, for example, checking (s->vss) is equivalent
|
||||
* to checking (s==VCC).
|
||||
*/
|
||||
if (id == "-vss") {
|
||||
this->cache[id]->vss = true;
|
||||
} else if (id == "+vcc") {
|
||||
this->cache[id]->vcc = true;
|
||||
}
|
||||
}
|
||||
|
||||
return get(id);
|
||||
}
|
||||
|
||||
Segment* SegmentCache::get(const std::string& id) const {
|
||||
if (!cached(id)) {
|
||||
throw "Cannot find segment: " + id;
|
||||
}
|
||||
|
||||
return this->cache.at(id).get();
|
||||
}
|
||||
|
||||
SegmentSet SegmentCache::all() const {
|
||||
SegmentSet s;
|
||||
for (auto i : this->cache) {
|
||||
s.insert(i.second.get());
|
||||
}
|
||||
return s;
|
||||
}
|
58
src/SegmentCache.h
Normal file
58
src/SegmentCache.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* File: SegmentCache.h
|
||||
* Author: Christopher
|
||||
*
|
||||
* Created on December 10, 2013, 9:56 PM
|
||||
*/
|
||||
|
||||
#ifndef SEGMENTCACHE_H
|
||||
#define SEGMENTCACHE_H
|
||||
|
||||
#include "SegmentTypes.h"
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
class Common;
|
||||
|
||||
class SegmentCache final {
|
||||
public:
|
||||
|
||||
SegmentCache() {
|
||||
}
|
||||
|
||||
Segment* getOrAdd(const std::string& id);
|
||||
|
||||
SegmentSet all() const;
|
||||
|
||||
|
||||
|
||||
typedef std::map<const std::string, std::shared_ptr<Segment>> Map;
|
||||
|
||||
Map::const_iterator begin() const {
|
||||
return this->cache.begin();
|
||||
}
|
||||
|
||||
Map::const_iterator end() const {
|
||||
return this->cache.end();
|
||||
}
|
||||
|
||||
Map::size_type size() const {
|
||||
return this->cache.size();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Map cache;
|
||||
|
||||
SegmentCache(const SegmentCache&) = delete;
|
||||
SegmentCache& operator=(const SegmentCache&) = delete;
|
||||
|
||||
Segment* get(const std::string& id) const;
|
||||
bool cached(const std::string& id) const;
|
||||
|
||||
friend Common;
|
||||
};
|
||||
|
||||
#endif /* SEGMENTCACHE_H */
|
21
src/SegmentTypes.h
Normal file
21
src/SegmentTypes.h
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* File: setpSeg.h
|
||||
* Author: Christopher
|
||||
*
|
||||
* Created on December 15, 2013, 12:16 AM
|
||||
*/
|
||||
|
||||
#ifndef SETPSEG_H
|
||||
#define SETPSEG_H
|
||||
|
||||
#include "ptr_less.h"
|
||||
#include <set>
|
||||
#include <utility>
|
||||
|
||||
class Segment;
|
||||
|
||||
typedef std::set<Segment*,ptr_less<Segment>> SegmentSet;
|
||||
typedef std::set<std::pair<Segment*, bool>> PinSettings;
|
||||
|
||||
#endif /* SETPSEG_H */
|
||||
|
69
src/StateCalculator.cpp
Normal file
69
src/StateCalculator.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* File: StateCalculator.cpp
|
||||
* Author: Christopher
|
||||
*
|
||||
* Created on December 12, 2013, 8:29 PM
|
||||
*/
|
||||
|
||||
#include "StateCalculator.h"
|
||||
#include "Circuit.h"
|
||||
#include "trans.h"
|
||||
|
||||
/*
|
||||
* Recalculate segment states (on/off), based on the fact that the segments
|
||||
* in segs have just changed state. Keep track of which other segments are
|
||||
* affected, and repeat the process on those segments. Repeat until no more
|
||||
* segments change state.
|
||||
*/
|
||||
#define SANE (100)
|
||||
|
||||
void StateCalculator::recalc(const SegmentSet& segs) {
|
||||
int sanity(0);
|
||||
|
||||
SegmentSet changed(segs);
|
||||
while (!changed.empty()) {
|
||||
if (++sanity >= SANE) {
|
||||
throw "ERROR: reached maximum iteration limit while recalculating CPU state";
|
||||
}
|
||||
|
||||
StateCalculator c;
|
||||
for (auto s : changed) {
|
||||
c.recalcNode(s);
|
||||
}
|
||||
changed = c.segs;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets group of segments currently electrically connected to seg,
|
||||
* gets what their group value is (or should be), goes through all
|
||||
* those segments and sets their "on" value. For all connected gates,
|
||||
* turn on/off, and indicate that the segments connected to those
|
||||
* transistors' source and drain legs have changed, by adding them
|
||||
* to this->segs.
|
||||
*/
|
||||
void StateCalculator::recalcNode(Segment* seg) {
|
||||
if (!(seg->vss || seg->vcc)) {
|
||||
Circuit c(seg);
|
||||
for (auto s : c) {
|
||||
setSeg(s, c.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StateCalculator::setSeg(Segment* s, const bool on) {
|
||||
if (s->on != on) {
|
||||
s->on = on;
|
||||
for (auto t : s->gates) {
|
||||
setTrans(t, on);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StateCalculator::setTrans(Trans* t, const bool on) {
|
||||
if (t->on != on) {
|
||||
t->on = on;
|
||||
this->segs.insert(t->c1);
|
||||
this->segs.insert(t->c2);
|
||||
}
|
||||
}
|
36
src/StateCalculator.h
Normal file
36
src/StateCalculator.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* File: StateCalculator.h
|
||||
* Author: Christopher
|
||||
*
|
||||
* Created on December 12, 2013, 8:29 PM
|
||||
*/
|
||||
|
||||
#ifndef STATECALCULATOR_H
|
||||
#define STATECALCULATOR_H
|
||||
|
||||
#include <set>
|
||||
#include "SegmentTypes.h"
|
||||
|
||||
class Trans;
|
||||
|
||||
class StateCalculator final {
|
||||
public:
|
||||
|
||||
static void recalc(const SegmentSet& rSeg);
|
||||
|
||||
private:
|
||||
|
||||
StateCalculator() {
|
||||
}
|
||||
|
||||
StateCalculator(const StateCalculator&) = delete;
|
||||
StateCalculator& operator=(const StateCalculator&) = delete;
|
||||
|
||||
void recalcNode(Segment* seg);
|
||||
void setSeg(Segment* s, const bool on);
|
||||
void setTrans(Trans* t, const bool on);
|
||||
|
||||
SegmentSet segs;
|
||||
};
|
||||
|
||||
#endif /* STATECALCULATOR_H */
|
103
src/Trace.cpp
Normal file
103
src/Trace.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* File: Trace.cpp
|
||||
* Author: cmosher
|
||||
*
|
||||
* Created on December 12, 2013, 3:39 PM
|
||||
*/
|
||||
|
||||
#include "Trace.h"
|
||||
#include "TransCache.h"
|
||||
#include "SegmentCache.h"
|
||||
#include "Common.h"
|
||||
#include "trans.h"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
static void pHex(const unsigned long x, const int width) {
|
||||
std::cout << std::setw(width) << std::setfill('0') << std::hex << x << std::dec;
|
||||
}
|
||||
|
||||
static void pHexb(const unsigned char x) {
|
||||
pHex(x, 2);
|
||||
}
|
||||
|
||||
static void pHexw(const unsigned short x) {
|
||||
pHex(x, 4);
|
||||
}
|
||||
|
||||
void Trace::dumpSegments() const {
|
||||
for (auto sp : this->segs) {
|
||||
Segment* seg = sp.second.get();
|
||||
if (seg->pull == Pull::UP) {
|
||||
std::cout << (seg->on ? "U" : "u");
|
||||
} else if (seg->pull == Pull::DOWN) {
|
||||
std::cout << (seg->on ? "D" : "d");
|
||||
} else {
|
||||
std::cout << (seg->on ? "F" : "f");
|
||||
}
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
void Trace::dumpRegisters() const {
|
||||
std::cout << "A";
|
||||
pHexb(this->common.rA());
|
||||
|
||||
std::cout << " X";
|
||||
pHexb(this->common.rX());
|
||||
|
||||
std::cout << " Y";
|
||||
pHexb(this->common.rY());
|
||||
|
||||
std::cout << " ";
|
||||
std::cout << (this->common.P7->on ? "N" : "n");
|
||||
std::cout << (this->common.P6->on ? "V" : "v");
|
||||
std::cout << ".";
|
||||
std::cout << (this->common.P4->on ? "B" : "b");
|
||||
std::cout << (this->common.P3->on ? "D" : "d");
|
||||
std::cout << (this->common.P2->on ? "I" : "i");
|
||||
std::cout << (this->common.P1->on ? "Z" : "z");
|
||||
std::cout << (this->common.P0->on ? "C" : "c");
|
||||
|
||||
std::cout << " S";
|
||||
pHexb(this->common.rS());
|
||||
|
||||
std::cout << " PC";
|
||||
pHexw(this->common.rPC());
|
||||
|
||||
if (this->common.CLK1OUT->on) {
|
||||
std::cout << " PH1 ";
|
||||
}
|
||||
if (this->common.CLK2OUT->on) {
|
||||
std::cout << " PH2";
|
||||
if (this->common.RW->on) {
|
||||
std::cout << " R";
|
||||
} else {
|
||||
std::cout << " W";
|
||||
}
|
||||
}
|
||||
if (!(this->common.CLK1OUT->on || this->common.CLK2OUT->on)) {
|
||||
std::cout << " PH- ";
|
||||
}
|
||||
|
||||
std::cout << " DB";
|
||||
pHexb(this->common.rData());
|
||||
|
||||
std::cout << " AB";
|
||||
pHexw(this->common.rAddr());
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
void Trace::dumpTransistors() const {
|
||||
/* count depletion-mode MOSFETs */
|
||||
int cd(0);
|
||||
for (auto sp : this->segs) {
|
||||
Segment* seg = sp.second.get();
|
||||
if (seg->dmos) {
|
||||
++cd;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "eMOSFETs: " << this->transes.size() << ", dMOSFETs: " << cd << std::endl;
|
||||
}
|
35
src/Trace.h
Normal file
35
src/Trace.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* File: Trace.h
|
||||
* Author: cmosher
|
||||
*
|
||||
* Created on December 12, 2013, 3:39 PM
|
||||
*/
|
||||
|
||||
#ifndef TRACE_H
|
||||
#define TRACE_H
|
||||
|
||||
class SegmentCache;
|
||||
class TransCache;
|
||||
class Common;
|
||||
|
||||
class Trace final {
|
||||
public:
|
||||
|
||||
Trace(const SegmentCache& segs, const TransCache& transes, const Common& common) : segs(segs), transes(transes), common(common) {
|
||||
}
|
||||
|
||||
void dumpSegments() const;
|
||||
void dumpTransistors() const;
|
||||
void dumpRegisters() const;
|
||||
|
||||
private:
|
||||
|
||||
Trace(const Trace&) = delete;
|
||||
Trace& operator=(const Trace&) = delete;
|
||||
|
||||
const SegmentCache& segs;
|
||||
const TransCache& transes;
|
||||
const Common& common;
|
||||
};
|
||||
|
||||
#endif /* TRACE_H */
|
13
src/TransCache.cpp
Normal file
13
src/TransCache.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* File: TransCache.cpp
|
||||
* Author: Christopher
|
||||
*
|
||||
* Created on December 15, 2013, 1:39 PM
|
||||
*/
|
||||
|
||||
#include "TransCache.h"
|
||||
#include "trans.h"
|
||||
|
||||
void TransCache::add(Segment* c1, Segment* gate, Segment* c2) {
|
||||
this->cache.insert(std::make_shared<Trans>(c1,gate,c2));
|
||||
}
|
47
src/TransCache.h
Normal file
47
src/TransCache.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* File: TransCache.h
|
||||
* Author: Christopher
|
||||
*
|
||||
* Created on December 15, 2013, 1:39 PM
|
||||
*/
|
||||
|
||||
#ifndef TRANSCACHE_H
|
||||
#define TRANSCACHE_H
|
||||
|
||||
#include <set>
|
||||
#include <memory>
|
||||
|
||||
class Trans;
|
||||
class Segment;
|
||||
|
||||
class TransCache final {
|
||||
public:
|
||||
|
||||
TransCache() {
|
||||
}
|
||||
|
||||
void add(Segment* c1, Segment* gate, Segment* c2);
|
||||
|
||||
typedef std::set<std::shared_ptr<Trans>> Set;
|
||||
|
||||
Set::const_iterator begin() const {
|
||||
return this->cache.begin();
|
||||
}
|
||||
|
||||
Set::const_iterator end() const {
|
||||
return this->cache.end();
|
||||
}
|
||||
|
||||
Set::size_type size() const {
|
||||
return this->cache.size();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
TransCache(const TransCache&) = delete;
|
||||
TransCache& operator=(const TransCache&) = delete;
|
||||
|
||||
Set cache;
|
||||
};
|
||||
|
||||
#endif /* TRANSCACHE_H */
|
27
src/TransNetwork.cpp
Normal file
27
src/TransNetwork.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* File: TransNetwork.cpp
|
||||
* Author: cmosher
|
||||
*
|
||||
* Created on December 11, 2013, 10:44 AM
|
||||
*/
|
||||
|
||||
#include "TransNetwork.h"
|
||||
#include "TransCache.h"
|
||||
#include "SegmentCache.h"
|
||||
#include "StateCalculator.h"
|
||||
#include "trans.h"
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
TransNetwork::TransNetwork(std::istream& in, SegmentCache& segs, TransCache& transes) : segs(segs), transes(transes) {
|
||||
std::string c1, gate, c2;
|
||||
in >> c1 >> gate >> c2;
|
||||
while (in.good()) {
|
||||
this->transes.add(this->segs.getOrAdd(c1), this->segs.getOrAdd(gate), this->segs.getOrAdd(c2));
|
||||
in >> c1 >> gate >> c2;
|
||||
}
|
||||
|
||||
StateCalculator::recalc(this->segs.all());
|
||||
}
|
36
src/TransNetwork.h
Normal file
36
src/TransNetwork.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* File: TransNetwork.h
|
||||
* Author: cmosher
|
||||
*
|
||||
* Created on December 11, 2013, 10:44 AM
|
||||
*/
|
||||
|
||||
#ifndef TRANSNETWORK_H
|
||||
#define TRANSNETWORK_H
|
||||
|
||||
#include <istream>
|
||||
#include <set>
|
||||
#include <memory>
|
||||
|
||||
class TransCache;
|
||||
class SegmentCache;
|
||||
class Common;
|
||||
class Trans;
|
||||
|
||||
class TransNetwork final {
|
||||
public:
|
||||
|
||||
TransNetwork(std::istream& readFromHere, SegmentCache& segs, TransCache& transes);
|
||||
|
||||
private:
|
||||
|
||||
TransNetwork(const TransNetwork&) = delete;
|
||||
TransNetwork& operator=(const TransNetwork&) = delete;
|
||||
|
||||
SegmentCache& segs;
|
||||
TransCache& transes;
|
||||
|
||||
friend Common;
|
||||
};
|
||||
|
||||
#endif /* TRANSNETWORK_H */
|
@ -35,6 +35,7 @@
|
||||
#include "screenimage.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <istream>
|
||||
#include <fstream>
|
||||
|
||||
Apple2::Apple2(KeypressQueue& keypresses, PaddleButtonStates& paddleButtonStates, AnalogTV& tv, HyperMode& fhyper, KeyboardBufferMode& buffered, ScreenImage& gui):
|
||||
@ -46,7 +47,9 @@ Apple2::Apple2(KeypressQueue& keypresses, PaddleButtonStates& paddleButtonStates
|
||||
addressBus(ram,rom,kbd,videoMode,paddles,paddleButtonStates,speaker,cassette,slts),
|
||||
picgen(tv,videoMode,this->revision),
|
||||
video(videoMode,addressBus,picgen,textRows),
|
||||
cpu(addressBus),
|
||||
transistors("transistors"),
|
||||
cpu(transistors,addressBus),
|
||||
// cpu(addressBus),
|
||||
powerUpReset(*this),
|
||||
revision(1)
|
||||
{
|
||||
|
@ -34,6 +34,8 @@
|
||||
#include "analogtv.h"
|
||||
#include "powerupreset.h"
|
||||
#include "cassette.h"
|
||||
#include "Emu6502.h"
|
||||
#include <fstream>
|
||||
class Emulator;
|
||||
class ScreenImage;
|
||||
|
||||
@ -51,7 +53,9 @@ class Apple2 : public Timable
|
||||
PictureGenerator picgen;
|
||||
TextCharacters textRows;
|
||||
Video video;
|
||||
CPU cpu;
|
||||
// CPU cpu;
|
||||
std::ifstream transistors;
|
||||
Emu6502 cpu;
|
||||
PowerUpReset powerUpReset;
|
||||
int revision;
|
||||
|
||||
|
20
src/ptr_less.h
Normal file
20
src/ptr_less.h
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* File: ptr_less.h
|
||||
* Author: Christopher
|
||||
*
|
||||
* Created on December 14, 2013, 5:44 PM
|
||||
*/
|
||||
|
||||
#ifndef PTR_LESS_H
|
||||
#define PTR_LESS_H
|
||||
|
||||
template<typename T>
|
||||
struct ptr_less {
|
||||
|
||||
bool operator()(T* pa, T* pb) {
|
||||
return *pa < *pb;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif /* PTR_LESS_H */
|
92
src/trans.h
Normal file
92
src/trans.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* File: trans.h
|
||||
* Author: cmosher
|
||||
*
|
||||
* Created on December 10, 2013, 2:37 PM
|
||||
*/
|
||||
|
||||
#ifndef TRANS_H
|
||||
#define TRANS_H
|
||||
|
||||
#include "SegmentTypes.h"
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
|
||||
|
||||
class Trans;
|
||||
|
||||
enum class Pull { UP, DOWN, FLOAT };
|
||||
|
||||
class Segment final {
|
||||
private:
|
||||
const std::string id;
|
||||
|
||||
public:
|
||||
std::set<Trans*> gates;
|
||||
std::set<Trans*> c1c2s;
|
||||
bool dmos;
|
||||
bool vss;
|
||||
bool vcc;
|
||||
|
||||
Pull pull;
|
||||
bool on;
|
||||
|
||||
|
||||
|
||||
Segment(const std::string& id) : id(id), dmos(id[0]=='+'), vss(false), vcc(false), pull(dmos ? Pull::UP : Pull::FLOAT), on(false) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
void set(const bool up) {
|
||||
this->pull = (up ? Pull::UP : Pull::DOWN);
|
||||
}
|
||||
|
||||
bool operator<(const Segment& that) const { return this->id < that.id; }
|
||||
|
||||
|
||||
|
||||
static unsigned char asByte(Segment* b7, Segment* b6, Segment* b5, Segment* b4, Segment* b3, Segment* b2, Segment* b1, Segment* b0) {
|
||||
return b7->on << 0x7 | b6->on << 0x6 | b5->on << 0x5 | b4->on << 0x4 | b3->on << 0x3 | b2->on << 0x2 | b1->on << 0x1 | b0->on;
|
||||
}
|
||||
|
||||
static unsigned short asWord(Segment* bf, Segment* be, Segment* bd, Segment* bc, Segment* bb, Segment* ba, Segment* b9, Segment* b8, Segment* b7, Segment* b6, Segment* b5, Segment* b4, Segment* b3, Segment* b2, Segment* b1, Segment* b0) {
|
||||
return bf->on << 0xf | be->on << 0xe | bd->on << 0xd | bc->on << 0xc | bb->on << 0xb | ba->on << 0xa | b9->on << 0x9 | b8->on << 0x8 | b7->on << 0x7 | b6->on << 0x6 | b5->on << 0x5 | b4->on << 0x4 | b3->on << 0x3 | b2->on << 0x2 | b1->on << 0x1 | b0->on;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Segment(const Segment&) = delete;
|
||||
Segment& operator=(const Segment&) = delete;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class Trans final {
|
||||
public:
|
||||
|
||||
Segment* c1;
|
||||
Segment* c2;
|
||||
|
||||
bool on;
|
||||
|
||||
|
||||
|
||||
Trans(Segment* c1, Segment* gate, Segment* c2) : c1(c1), c2(c2), on(false) {
|
||||
c1->c1c2s.insert(this);
|
||||
gate->gates.insert(this);
|
||||
c2->c1c2s.insert(this);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Trans(const Trans&) = delete;
|
||||
Trans& operator=(const Trans&) = delete;
|
||||
};
|
||||
|
||||
#endif /* TRANS_H */
|
3239
transistors
Normal file
3239
transistors
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user