mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2024-06-26 04:29:26 +00:00
Refactor the MOS6502 core:
* Use lambda, rather than std::bind, if reasonable * Tidy construction * Remove configuration etc. not needed for running Klaus Dormann 6502 tests
This commit is contained in:
parent
68b352d1df
commit
2de467dde8
|
@ -8,10 +8,7 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
Board::Board(const Configuration& configuration)
|
Board::Board(const Configuration& configuration)
|
||||||
: m_configuration(configuration),
|
: m_configuration(configuration) {}
|
||||||
m_cpu(EightBit::MOS6502(*this)),
|
|
||||||
m_disassembler(*this, m_cpu, m_symbols),
|
|
||||||
m_profiler(m_cpu, m_disassembler, m_symbols) {}
|
|
||||||
|
|
||||||
void Board::powerOn() {
|
void Board::powerOn() {
|
||||||
EightBit::Bus::powerOn();
|
EightBit::Bus::powerOn();
|
||||||
|
@ -28,113 +25,40 @@ void Board::initialise() {
|
||||||
auto programFilename = m_configuration.getProgram();
|
auto programFilename = m_configuration.getProgram();
|
||||||
auto programPath = m_configuration.getRomDirectory() + "/" + m_configuration.getProgram();
|
auto programPath = m_configuration.getRomDirectory() + "/" + m_configuration.getProgram();
|
||||||
auto loadAddress = m_configuration.getLoadAddress();
|
auto loadAddress = m_configuration.getLoadAddress();
|
||||||
|
m_ram.load(programPath, loadAddress.word);
|
||||||
|
|
||||||
switch (m_configuration.getLoadMethod()) {
|
// Disassembly output
|
||||||
case Configuration::LoadMethod::Ram:
|
if (m_configuration.isDebugMode())
|
||||||
m_ram.load(programPath, loadAddress.word);
|
CPU().ExecutingInstruction.connect([this] (EightBit::MOS6502& cpu) {
|
||||||
break;
|
const auto address = cpu.PC();
|
||||||
case Configuration::LoadMethod::Rom:
|
const auto cell = peek(address);
|
||||||
// m_rom.load(programPath, loadAddress);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_configuration.isProfileMode()) {
|
std::cout << std::hex;
|
||||||
CPU().ExecutingInstruction.connect(std::bind(&Board::Cpu_ExecutingInstruction_Profile, this, std::placeholders::_1));
|
std::cout << "PC=" << std::setw(4) << std::setfill('0') << address << ":";
|
||||||
}
|
std::cout << "P=" << m_disassembler.dump_Flags(CPU().P()) << ", ";
|
||||||
|
std::cout << std::setw(2) << std::setfill('0');
|
||||||
|
std::cout << "A=" << (int)CPU().A() << ", ";
|
||||||
|
std::cout << "X=" << (int)CPU().X() << ", ";
|
||||||
|
std::cout << "Y=" << (int)CPU().Y() << ", ";
|
||||||
|
std::cout << "S=" << (int)CPU().S() << "\t";
|
||||||
|
|
||||||
if (m_configuration.isDebugMode()) {
|
std::cout << m_disassembler.disassemble(address.word);
|
||||||
CPU().ExecutingInstruction.connect(std::bind(&Board::Cpu_ExecutingInstruction_Debug, this, std::placeholders::_1));
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (m_configuration.getStopCondition()) {
|
std::cout << "\n";
|
||||||
case Configuration::StopCondition::Loop:
|
});
|
||||||
CPU().ExecutedInstruction.connect(std::bind(&Board::Cpu_ExecutedInstruction_StopLoop, this, std::placeholders::_1));
|
|
||||||
break;
|
|
||||||
case Configuration::StopCondition::Halt:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw std::domain_error("Unknown stop condition");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_configuration.allowInput()) {
|
// Loop detected stop condition
|
||||||
ReadingByte.connect(std::bind(&Board::Memory_ReadingByte_Input, this, std::placeholders::_1));
|
CPU().ExecutedInstruction.connect([this] (EightBit::MOS6502& cpu) {
|
||||||
CPU().ExecutedInstruction.connect(std::bind(&Board::Cpu_ExecutedInstruction_Poll, this, std::placeholders::_1));
|
const auto pc = cpu.PC();
|
||||||
}
|
if (m_oldPC != pc) {
|
||||||
|
m_oldPC = pc;
|
||||||
if (m_configuration.allowOutput())
|
} else {
|
||||||
WrittenByte.connect(std::bind(&Board::Memory_WrittenByte_Output, this, std::placeholders::_1));
|
powerOff();
|
||||||
|
auto test = peek(0x0200);
|
||||||
m_pollCounter = 0;
|
std::cout << std::endl << "** Test=" << std::hex << (int)test;
|
||||||
m_pollInterval = m_configuration.getPollInterval();
|
}
|
||||||
|
});
|
||||||
|
|
||||||
poke(0x00, 0x4c);
|
poke(0x00, 0x4c);
|
||||||
CPU().pokeWord(1, m_configuration.getStartAddress());
|
CPU().pokeWord(1, m_configuration.getStartAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Board::Cpu_ExecutingInstruction_Profile(const EightBit::MOS6502& cpu) {
|
|
||||||
|
|
||||||
const auto pc = CPU().PC();
|
|
||||||
|
|
||||||
//m_profiler.addAddress(pc.word, m_cpu.);
|
|
||||||
//m_profiler.addInstruction(m_memory.peek(pc.word));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Board::Cpu_ExecutedInstruction_StopLoop(EightBit::MOS6502& cpu) {
|
|
||||||
|
|
||||||
auto pc = cpu.PC().word;
|
|
||||||
if (m_oldPC != pc) {
|
|
||||||
m_oldPC = pc;
|
|
||||||
} else {
|
|
||||||
powerOff();
|
|
||||||
auto test = peek(0x0200);
|
|
||||||
std::cout << std::endl << "** Test=" << std::hex << (int)test;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Board::Cpu_ExecutingInstruction_Debug(EightBit::MOS6502& cpu) {
|
|
||||||
|
|
||||||
auto address = cpu.PC().word;
|
|
||||||
auto cell = peek(address);
|
|
||||||
|
|
||||||
std::cout << std::hex;
|
|
||||||
std::cout << "PC=" << std::setw(4) << std::setfill('0') << address << ":";
|
|
||||||
std::cout << "P=" << m_disassembler.dump_Flags(CPU().P()) << ", ";
|
|
||||||
std::cout << std::setw(2) << std::setfill('0');
|
|
||||||
std::cout << "A=" << (int)CPU().A() << ", ";
|
|
||||||
std::cout << "X=" << (int)CPU().X() << ", ";
|
|
||||||
std::cout << "Y=" << (int)CPU().Y() << ", ";
|
|
||||||
std::cout << "S=" << (int)CPU().S() << "\t";
|
|
||||||
|
|
||||||
std::cout << m_disassembler.disassemble(address);
|
|
||||||
|
|
||||||
std::cout << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void Board::Memory_ReadingByte_Input(EightBit::EventArgs) {
|
|
||||||
if (ADDRESS() == m_configuration.getInputAddress()) {
|
|
||||||
if (!!DATA())
|
|
||||||
write(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Board::Memory_WrittenByte_Output(EightBit::EventArgs) {
|
|
||||||
if (ADDRESS() == m_configuration.getOutputAddress()) {
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
_putch(DATA());
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Board::Cpu_ExecutedInstruction_Poll(const EightBit::MOS6502& cpu) {
|
|
||||||
if (++m_pollCounter == m_pollInterval) {
|
|
||||||
m_pollCounter = 0;
|
|
||||||
pollKeyboard();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Board::pollKeyboard() {
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
if (_kbhit())
|
|
||||||
poke(m_configuration.getInputAddress(), _getch());
|
|
||||||
#endif
|
|
||||||
}
|
|
|
@ -6,10 +6,10 @@
|
||||||
|
|
||||||
#include <Ram.h>
|
#include <Ram.h>
|
||||||
#include <Bus.h>
|
#include <Bus.h>
|
||||||
#include <Profiler.h>
|
|
||||||
#include <Disassembly.h>
|
#include <Disassembly.h>
|
||||||
#include <mos6502.h>
|
#include <mos6502.h>
|
||||||
#include <Symbols.h>
|
#include <Symbols.h>
|
||||||
|
#include <Register.h>
|
||||||
|
|
||||||
class Board : public EightBit::Bus {
|
class Board : public EightBit::Bus {
|
||||||
public:
|
public:
|
||||||
|
@ -29,25 +29,10 @@ protected:
|
||||||
private:
|
private:
|
||||||
const Configuration& m_configuration;
|
const Configuration& m_configuration;
|
||||||
EightBit::Ram m_ram = 0x10000;
|
EightBit::Ram m_ram = 0x10000;
|
||||||
EightBit::MOS6502 m_cpu;
|
EightBit::MOS6502 m_cpu = *this;
|
||||||
EightBit::Symbols m_symbols;
|
EightBit::Symbols m_symbols;
|
||||||
EightBit::Disassembly m_disassembler;
|
EightBit::Disassembly m_disassembler = { *this, m_cpu, m_symbols };
|
||||||
EightBit::Profiler m_profiler;
|
|
||||||
|
|
||||||
uint16_t m_oldPC = 0xffff;
|
EightBit::register16_t m_oldPC = EightBit::Chip::Mask16;
|
||||||
bool m_stopped = false;
|
bool m_stopped = false;
|
||||||
uint64_t m_pollCounter = 0UL;
|
|
||||||
uint64_t m_pollInterval = 0UL;
|
|
||||||
|
|
||||||
void pollKeyboard();
|
|
||||||
|
|
||||||
void Cpu_ExecutingInstruction_Debug(EightBit::MOS6502& cpu);
|
|
||||||
void Cpu_ExecutingInstruction_Profile(const EightBit::MOS6502& cpu);
|
|
||||||
|
|
||||||
void Cpu_ExecutedInstruction_StopLoop(EightBit::MOS6502& cpu);
|
|
||||||
|
|
||||||
void Memory_ReadingByte_Input(EightBit::EventArgs);
|
|
||||||
void Memory_WrittenByte_Output(EightBit::EventArgs);
|
|
||||||
|
|
||||||
void Cpu_ExecutedInstruction_Poll(const EightBit::MOS6502& cpu);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,54 +6,21 @@
|
||||||
|
|
||||||
class Configuration {
|
class Configuration {
|
||||||
public:
|
public:
|
||||||
enum StopCondition {
|
|
||||||
Halt,
|
|
||||||
Loop
|
|
||||||
};
|
|
||||||
|
|
||||||
enum LoadMethod {
|
|
||||||
Ram,
|
|
||||||
Rom
|
|
||||||
};
|
|
||||||
|
|
||||||
Configuration() = default;
|
Configuration() = default;
|
||||||
|
|
||||||
bool isDebugMode() const { return m_debugMode; }
|
bool isDebugMode() const { return m_debugMode; }
|
||||||
void setDebugMode(bool value) { m_debugMode = value; }
|
void setDebugMode(bool value) { m_debugMode = value; }
|
||||||
|
|
||||||
bool isProfileMode() const { return m_profileMode; }
|
|
||||||
void setProfileMode(bool value) { m_profileMode = value; }
|
|
||||||
|
|
||||||
EightBit::register16_t getLoadAddress() const { return m_loadAddress; }
|
EightBit::register16_t getLoadAddress() const { return m_loadAddress; }
|
||||||
EightBit::register16_t getStartAddress() const { return m_startAddress; }
|
EightBit::register16_t getStartAddress() const { return m_startAddress; }
|
||||||
|
|
||||||
bool allowInput() const { return m_allowInput; }
|
|
||||||
EightBit::register16_t getInputAddress() const { return m_inputAddress; }
|
|
||||||
|
|
||||||
bool allowOutput() const { return m_allowOutput; }
|
|
||||||
EightBit::register16_t getOutputAddress() const { return m_outputAddress; }
|
|
||||||
|
|
||||||
uint64_t getPollInterval() const { return m_pollInterval; }
|
|
||||||
|
|
||||||
StopCondition getStopCondition() const { return m_stopCondition; }
|
|
||||||
|
|
||||||
std::string getRomDirectory() const { return m_romDirectory; }
|
std::string getRomDirectory() const { return m_romDirectory; }
|
||||||
std::string getProgram() const { return m_program; }
|
std::string getProgram() const { return m_program; }
|
||||||
|
|
||||||
LoadMethod getLoadMethod() const { return m_loadMethod; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_debugMode = false;
|
bool m_debugMode = false;
|
||||||
bool m_profileMode = false;
|
|
||||||
EightBit::register16_t m_loadAddress = 0x400;
|
EightBit::register16_t m_loadAddress = 0x400;
|
||||||
EightBit::register16_t m_startAddress = 0x400;
|
EightBit::register16_t m_startAddress = 0x400;
|
||||||
bool m_allowInput = false;
|
|
||||||
EightBit::register16_t m_inputAddress = 0xbff0;
|
|
||||||
bool m_allowOutput = false;
|
|
||||||
EightBit::register16_t m_outputAddress = 0xbff0;
|
|
||||||
uint64_t m_pollInterval = 2000000 / 50;
|
|
||||||
StopCondition m_stopCondition = StopCondition::Loop;
|
|
||||||
std::string m_romDirectory = "roms";
|
std::string m_romDirectory = "roms";
|
||||||
std::string m_program = "6502_functional_test.bin";
|
std::string m_program = "6502_functional_test.bin";
|
||||||
LoadMethod m_loadMethod = LoadMethod::Ram;
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user