2017-07-05 16:46:02 +00:00
|
|
|
#include "stdafx.h"
|
|
|
|
#include "Board.h"
|
|
|
|
#include "Disassembly.h"
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
#include <sstream>
|
|
|
|
#include <iomanip>
|
2017-07-08 00:04:20 +00:00
|
|
|
#include <assert.h>
|
2017-07-05 16:46:02 +00:00
|
|
|
|
|
|
|
Board::Board(const Configuration& configuration)
|
|
|
|
: m_configuration(configuration),
|
2017-09-06 23:58:56 +00:00
|
|
|
m_ram(0x10000),
|
|
|
|
m_cpu(EightBit::MOS6502(*this)),
|
2017-07-05 16:46:02 +00:00
|
|
|
m_symbols(""),
|
|
|
|
m_disassembler(m_cpu, m_symbols),
|
|
|
|
m_profiler(m_cpu, m_disassembler, m_symbols),
|
|
|
|
m_oldPC(0xffff),
|
|
|
|
m_stopped(false) {
|
|
|
|
}
|
|
|
|
|
|
|
|
void Board::initialise() {
|
|
|
|
|
2017-07-17 09:16:15 +00:00
|
|
|
auto programFilename = m_configuration.getProgram();
|
|
|
|
auto programPath = m_configuration.getRomDirectory() + "\\" + m_configuration.getProgram();
|
|
|
|
auto loadAddress = m_configuration.getLoadAddress();
|
|
|
|
|
|
|
|
switch (m_configuration.getLoadMethod()) {
|
|
|
|
case Configuration::LoadMethod::Ram:
|
2017-09-06 23:58:56 +00:00
|
|
|
m_ram.load(programPath, loadAddress);
|
2017-07-17 09:16:15 +00:00
|
|
|
break;
|
|
|
|
case Configuration::LoadMethod::Rom:
|
2017-09-06 23:58:56 +00:00
|
|
|
// m_rom.load(programPath, loadAddress);
|
2017-07-17 09:16:15 +00:00
|
|
|
break;
|
|
|
|
}
|
2017-07-05 16:46:02 +00:00
|
|
|
|
|
|
|
if (m_configuration.isProfileMode()) {
|
|
|
|
m_cpu.ExecutingInstruction.connect(std::bind(&Board::Cpu_ExecutingInstruction_Profile, this, std::placeholders::_1));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_configuration.isDebugMode()) {
|
|
|
|
m_cpu.ExecutingInstruction.connect(std::bind(&Board::Cpu_ExecutingInstruction_Debug, this, std::placeholders::_1));
|
|
|
|
}
|
|
|
|
|
2017-07-17 09:16:15 +00:00
|
|
|
switch (m_configuration.getStopCondition()) {
|
|
|
|
case Configuration::StopCondition::Loop:
|
|
|
|
m_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");
|
|
|
|
}
|
2017-07-05 16:46:02 +00:00
|
|
|
|
2017-07-08 00:04:20 +00:00
|
|
|
if (m_configuration.allowInput()) {
|
2017-10-28 12:06:56 +00:00
|
|
|
ReadingByte.connect(std::bind(&Board::Memory_ReadingByte_Input, this, std::placeholders::_1));
|
2017-07-08 00:04:20 +00:00
|
|
|
m_cpu.ExecutedInstruction.connect(std::bind(&Board::Cpu_ExecutedInstruction_Poll, this, std::placeholders::_1));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_configuration.allowOutput())
|
2017-09-06 23:58:56 +00:00
|
|
|
WrittenByte.connect(std::bind(&Board::Memory_WrittenByte_Output, this, std::placeholders::_1));
|
2017-07-08 00:04:20 +00:00
|
|
|
|
|
|
|
m_pollCounter = 0;
|
|
|
|
m_pollInterval = m_configuration.getPollInterval();
|
|
|
|
|
2017-07-05 16:46:02 +00:00
|
|
|
m_cpu.initialise();
|
2017-07-17 09:16:15 +00:00
|
|
|
m_cpu.PC().word = m_configuration.getStartAddress();
|
2017-07-05 16:46:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Board::Cpu_ExecutingInstruction_Profile(const EightBit::MOS6502& cpu) {
|
|
|
|
|
|
|
|
const auto pc = m_cpu.PC();
|
|
|
|
|
|
|
|
//m_profiler.addAddress(pc.word, m_cpu.);
|
|
|
|
//m_profiler.addInstruction(m_memory.peek(pc.word));
|
|
|
|
}
|
|
|
|
|
2017-07-06 20:32:52 +00:00
|
|
|
void Board::Cpu_ExecutedInstruction_StopLoop(const EightBit::MOS6502& cpu) {
|
|
|
|
|
2017-07-05 16:46:02 +00:00
|
|
|
auto pc = m_cpu.PC().word;
|
|
|
|
if (m_oldPC == pc) {
|
|
|
|
m_cpu.halt();
|
2017-09-06 23:58:56 +00:00
|
|
|
auto test = peek(0x0200);
|
2017-07-05 16:46:02 +00:00
|
|
|
std::cout << std::endl << "** Test=" << std::hex << (int)test;
|
2017-07-06 20:32:52 +00:00
|
|
|
} else {
|
|
|
|
m_oldPC = pc;
|
2017-07-05 16:46:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Board::Cpu_ExecutingInstruction_Debug(const EightBit::MOS6502& cpu) {
|
|
|
|
|
|
|
|
auto address = m_cpu.PC().word;
|
2017-09-06 23:58:56 +00:00
|
|
|
auto cell = peek(address);
|
2017-07-05 16:46:02 +00:00
|
|
|
|
|
|
|
std::cout << std::hex;
|
|
|
|
std::cout << "PC=" << std::setw(4) << std::setfill('0') << address << ":";
|
2017-07-17 14:35:24 +00:00
|
|
|
std::cout << "P=" << m_disassembler.dump_Flags(m_cpu.P()) << ", ";
|
2017-07-06 20:32:52 +00:00
|
|
|
std::cout << std::setw(2) << std::setfill('0');
|
2017-07-07 08:24:58 +00:00
|
|
|
std::cout << "A=" << (int)m_cpu.A() << ", ";
|
|
|
|
std::cout << "X=" << (int)m_cpu.X() << ", ";
|
|
|
|
std::cout << "Y=" << (int)m_cpu.Y() << ", ";
|
|
|
|
std::cout << "S=" << (int)m_cpu.S() << "\t";
|
2017-07-05 16:46:02 +00:00
|
|
|
|
2017-07-17 14:35:24 +00:00
|
|
|
std::cout << m_disassembler.disassemble(address);
|
2017-07-05 16:46:02 +00:00
|
|
|
|
2017-07-06 20:32:52 +00:00
|
|
|
std::cout << "\n";
|
2017-07-05 16:46:02 +00:00
|
|
|
}
|
2017-07-08 00:04:20 +00:00
|
|
|
|
2017-10-28 12:06:56 +00:00
|
|
|
void Board::Memory_ReadingByte_Input(const uint16_t address) {
|
2017-07-08 00:04:20 +00:00
|
|
|
if (address == m_configuration.getInputAddress()) {
|
2017-09-13 22:12:47 +00:00
|
|
|
if (DATA() != 0) {
|
2017-09-06 23:58:56 +00:00
|
|
|
assert(address == ADDRESS().word);
|
|
|
|
write(0);
|
2017-07-08 00:04:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-13 22:12:47 +00:00
|
|
|
void Board::Memory_WrittenByte_Output(const uint16_t address) {
|
|
|
|
if (address == m_configuration.getOutputAddress()) {
|
|
|
|
_putch(DATA());
|
2017-07-08 00:04:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Board::Cpu_ExecutedInstruction_Poll(const EightBit::MOS6502& cpu) {
|
|
|
|
if (++m_pollCounter == m_pollInterval) {
|
|
|
|
m_pollCounter = 0;
|
|
|
|
pollKeyboard();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Board::pollKeyboard() {
|
2017-08-06 16:06:48 +00:00
|
|
|
if (_kbhit())
|
2017-09-06 23:58:56 +00:00
|
|
|
poke(m_configuration.getInputAddress(), _getch());
|
2017-07-08 00:04:20 +00:00
|
|
|
}
|