2017-06-05 16:31:21 +00:00
|
|
|
#include "stdafx.h"
|
|
|
|
#include "Board.h"
|
|
|
|
#include "Configuration.h"
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
Board::Board(const Configuration& configuration)
|
|
|
|
: m_configuration(configuration),
|
2017-09-06 23:55:06 +00:00
|
|
|
m_cpu(EightBit::Intel8080(*this, m_ports)) {
|
2017-06-05 16:31:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Board::initialise() {
|
|
|
|
|
|
|
|
auto romDirectory = m_configuration.getRomDirectory();
|
|
|
|
|
2017-09-06 23:55:06 +00:00
|
|
|
//m_ram.load(romDirectory + "/TEST.COM", 0x100); // Microcosm
|
|
|
|
//m_ram.load(romDirectory + "/8080PRE.COM", 0x100); // Bartholomew preliminary
|
|
|
|
m_ram.load(romDirectory + "/8080EX1.COM", 0x100); // Cringle/Bartholomew
|
|
|
|
//m_ram.load(romDirectory + "/CPUTEST.COM", 0x100); // SuperSoft diagnostics
|
2017-06-05 16:31:21 +00:00
|
|
|
|
2017-09-06 23:55:06 +00:00
|
|
|
poke(5, 0xc9); // ret
|
2017-06-05 16:31:21 +00:00
|
|
|
m_cpu.ExecutingInstruction.connect(std::bind(&Board::Cpu_ExecutingInstruction_Cpm, this, std::placeholders::_1));
|
|
|
|
|
|
|
|
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-12-10 21:41:48 +00:00
|
|
|
CPU().powerOn();
|
|
|
|
CPU().PC() = m_configuration.getStartAddress();
|
2017-06-05 16:31:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Board::Cpu_ExecutingInstruction_Cpm(const EightBit::Intel8080&) {
|
2017-12-10 21:41:48 +00:00
|
|
|
auto pc = CPU().PC();
|
2017-06-05 16:31:21 +00:00
|
|
|
switch (pc.word) {
|
|
|
|
case 0x0: // CP/M warm start
|
2017-12-10 21:41:48 +00:00
|
|
|
CPU().powerOff();
|
2017-06-22 09:27:19 +00:00
|
|
|
if (m_configuration.isProfileMode()) {
|
|
|
|
m_profiler.dump();
|
|
|
|
}
|
2017-06-05 16:31:21 +00:00
|
|
|
break;
|
|
|
|
case 0x5: // BDOS
|
|
|
|
bdos();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Board::bdos() {
|
2017-12-10 21:41:48 +00:00
|
|
|
auto c = CPU().C();
|
2017-06-05 16:31:21 +00:00
|
|
|
switch (c) {
|
|
|
|
case 0x2: {
|
2017-12-10 21:41:48 +00:00
|
|
|
auto character = CPU().E();
|
2017-06-05 16:31:21 +00:00
|
|
|
std::cout << character;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 0x9:
|
2017-12-10 21:41:48 +00:00
|
|
|
for (uint16_t i = CPU().DE().word; peek(i) != '$'; ++i) {
|
2017-09-06 23:55:06 +00:00
|
|
|
std::cout << peek(i);
|
2017-06-05 16:31:21 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Board::Cpu_ExecutingInstruction_Profile(const EightBit::Intel8080& cpu) {
|
|
|
|
|
2017-12-10 21:41:48 +00:00
|
|
|
const auto pc = CPU().PC();
|
2017-06-05 16:31:21 +00:00
|
|
|
|
|
|
|
m_profiler.addAddress(pc.word);
|
2017-09-06 23:55:06 +00:00
|
|
|
m_profiler.addInstruction(peek(pc.word));
|
2017-06-05 16:31:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Board::Cpu_ExecutingInstruction_Debug(const EightBit::Intel8080&) {
|
|
|
|
|
|
|
|
std::cerr
|
2017-12-10 21:41:48 +00:00
|
|
|
<< EightBit::Disassembler::state(CPU())
|
2017-06-05 16:31:21 +00:00
|
|
|
<< "\t"
|
2017-12-10 21:41:48 +00:00
|
|
|
<< m_disassembler.disassemble(CPU())
|
2017-06-05 16:31:21 +00:00
|
|
|
<< '\n';
|
|
|
|
}
|