mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2024-09-29 00:54:54 +00:00
Merge branch 'master' of https://github.com/MoleskiCoder/EightBit into master
This commit is contained in:
commit
502c554e84
@ -3,19 +3,20 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stdexcept>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
|
||||||
#include <Device.h>
|
#include <Device.h>
|
||||||
|
|
||||||
#include "GameController.h"
|
|
||||||
#include "SDLWrapper.h"
|
#include "SDLWrapper.h"
|
||||||
|
|
||||||
class Configuration;
|
class Configuration;
|
||||||
|
|
||||||
namespace Gaming {
|
namespace Gaming {
|
||||||
|
|
||||||
|
class GameController;
|
||||||
|
|
||||||
class Game : public EightBit::Device {
|
class Game : public EightBit::Device {
|
||||||
public:
|
public:
|
||||||
Game();
|
Game();
|
||||||
@ -28,10 +29,10 @@ namespace Gaming {
|
|||||||
virtual float fps() const = 0;
|
virtual float fps() const = 0;
|
||||||
virtual bool useVsync() const = 0;
|
virtual bool useVsync() const = 0;
|
||||||
|
|
||||||
virtual int windowWidth() const noexcept { return displayWidth() * displayScale(); }
|
virtual int windowWidth() const noexcept;
|
||||||
virtual int windowHeight() const noexcept { return displayHeight() * displayScale(); }
|
virtual int windowHeight() const noexcept;
|
||||||
virtual int displayWidth() const noexcept { return rasterWidth(); }
|
virtual int displayWidth() const noexcept;
|
||||||
virtual int displayHeight() const noexcept { return rasterHeight(); }
|
virtual int displayHeight() const noexcept;
|
||||||
virtual int displayScale() const noexcept = 0;
|
virtual int displayScale() const noexcept = 0;
|
||||||
virtual int rasterWidth() const noexcept = 0;
|
virtual int rasterWidth() const noexcept = 0;
|
||||||
virtual int rasterHeight() const noexcept = 0;
|
virtual int rasterHeight() const noexcept = 0;
|
||||||
@ -67,19 +68,8 @@ namespace Gaming {
|
|||||||
|
|
||||||
void toggleFullscreen();
|
void toggleFullscreen();
|
||||||
|
|
||||||
std::shared_ptr<GameController> gameController(const int which) const {
|
std::shared_ptr<GameController> gameController(int which) const;
|
||||||
const auto i = m_gameControllers.find(which);
|
int mappedController(const SDL_JoystickID which) const;
|
||||||
if (i == m_gameControllers.cend())
|
|
||||||
throw std::runtime_error("Unknown controller");
|
|
||||||
return i->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mappedController(const SDL_JoystickID which) const {
|
|
||||||
const auto i = m_mappedControllers.find(which);
|
|
||||||
if (i == m_mappedControllers.cend())
|
|
||||||
throw std::runtime_error("Unknown joystick");
|
|
||||||
return i->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
int chooseControllerIndex(int who) const;
|
int chooseControllerIndex(int who) const;
|
||||||
std::shared_ptr<GameController> chooseController(int who) const;
|
std::shared_ptr<GameController> chooseController(int who) const;
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
namespace Gaming {
|
namespace Gaming {
|
||||||
class SDLWrapper final {
|
class SDLWrapper final {
|
||||||
public:
|
public:
|
||||||
|
@ -1,12 +1,30 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
|
|
||||||
|
#include "GameController.h"
|
||||||
|
|
||||||
namespace Gaming {
|
namespace Gaming {
|
||||||
|
|
||||||
Game::Game() {}
|
Game::Game() {}
|
||||||
|
|
||||||
Game::~Game() {}
|
Game::~Game() {}
|
||||||
|
|
||||||
|
int Game::windowWidth() const noexcept {
|
||||||
|
return displayWidth() * displayScale();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Game::windowHeight() const noexcept {
|
||||||
|
return displayHeight() * displayScale();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Game::displayWidth() const noexcept {
|
||||||
|
return rasterWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Game::displayHeight() const noexcept {
|
||||||
|
return rasterHeight();
|
||||||
|
}
|
||||||
|
|
||||||
void Game::raisePOWER() {
|
void Game::raisePOWER() {
|
||||||
|
|
||||||
Device::raisePOWER();
|
Device::raisePOWER();
|
||||||
@ -168,6 +186,20 @@ void Game::addJoystick(SDL_Event& e) {
|
|||||||
SDL_Log("Joystick device %d added (%zd controllers)", which, m_gameControllers.size());
|
SDL_Log("Joystick device %d added (%zd controllers)", which, m_gameControllers.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<GameController> Game::gameController(const int which) const {
|
||||||
|
const auto i = m_gameControllers.find(which);
|
||||||
|
if (i == m_gameControllers.cend())
|
||||||
|
throw std::runtime_error("Unknown controller");
|
||||||
|
return i->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Game::mappedController(const SDL_JoystickID which) const {
|
||||||
|
const auto i = m_mappedControllers.find(which);
|
||||||
|
if (i == m_mappedControllers.cend())
|
||||||
|
throw std::runtime_error("Unknown joystick");
|
||||||
|
return i->second;
|
||||||
|
}
|
||||||
|
|
||||||
// -1 if no controllers, otherwise index
|
// -1 if no controllers, otherwise index
|
||||||
int Game::chooseControllerIndex(const int who) const {
|
int Game::chooseControllerIndex(const int who) const {
|
||||||
const auto count = m_gameControllers.size();
|
const auto count = m_gameControllers.size();
|
||||||
|
@ -40,7 +40,7 @@ namespace EightBit {
|
|||||||
Signal<EventArgs> MachineTicked;
|
Signal<EventArgs> MachineTicked;
|
||||||
|
|
||||||
void tickMachine(const int extra) { for (int i = 0; i < extra; ++i) tickMachine(); }
|
void tickMachine(const int extra) { for (int i = 0; i < extra; ++i) tickMachine(); }
|
||||||
void tickMachine() { tick(4); MachineTicked.fire(EventArgs::empty()); }
|
void tickMachine() { tick(4); MachineTicked.fire(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int execute() final;
|
int execute() final;
|
||||||
|
@ -32,15 +32,15 @@ namespace EightBit {
|
|||||||
Signal<MOS6502> ExecutedInstruction;
|
Signal<MOS6502> ExecutedInstruction;
|
||||||
|
|
||||||
int execute() final;
|
int execute() final;
|
||||||
int step() final;
|
[[nodiscard]] int step() final;
|
||||||
|
|
||||||
auto& X() { return x; }
|
[[nodiscard]] auto& X() { return x; }
|
||||||
auto& Y() { return y; }
|
[[nodiscard]] auto& Y() { return y; }
|
||||||
auto& A() { return a; }
|
[[nodiscard]] auto& A() { return a; }
|
||||||
auto& S() { return s; }
|
[[nodiscard]] auto& S() { return s; }
|
||||||
|
|
||||||
auto& P() { return p; }
|
[[nodiscard]] auto& P() { return p; }
|
||||||
const auto& P() const { return p; }
|
[[nodiscard]] const auto& P() const { return p; }
|
||||||
|
|
||||||
DECLARE_PIN_INPUT(NMI)
|
DECLARE_PIN_INPUT(NMI)
|
||||||
DECLARE_PIN_INPUT(SO)
|
DECLARE_PIN_INPUT(SO)
|
||||||
@ -49,21 +49,21 @@ namespace EightBit {
|
|||||||
DECLARE_PIN_OUTPUT(RW)
|
DECLARE_PIN_OUTPUT(RW)
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void handleRESET() final;
|
void handleRESET() final;
|
||||||
virtual void handleINT() final;
|
void handleINT() final;
|
||||||
|
|
||||||
virtual void busWrite() final;
|
void busWrite() final;
|
||||||
virtual uint8_t busRead() final;
|
[[nodiscard]] uint8_t busRead() final;
|
||||||
|
|
||||||
virtual uint8_t sub(uint8_t operand, uint8_t data, int borrow = 0);
|
[[nodiscard]] virtual uint8_t sub(uint8_t operand, uint8_t data, int borrow = 0);
|
||||||
uint8_t sbc(uint8_t operand, uint8_t data);
|
[[nodiscard]] uint8_t sbc(uint8_t operand, uint8_t data);
|
||||||
uint8_t sub_b(uint8_t operand, uint8_t data, int borrow);
|
[[nodiscard]] uint8_t sub_b(uint8_t operand, uint8_t data, int borrow);
|
||||||
uint8_t sub_d(uint8_t operand, uint8_t data, int borrow);
|
[[nodiscard]] uint8_t sub_d(uint8_t operand, uint8_t data, int borrow);
|
||||||
|
|
||||||
virtual uint8_t add(uint8_t operand, uint8_t data, int carry = 0);
|
[[nodiscard]] virtual uint8_t add(uint8_t operand, uint8_t data, int carry = 0);
|
||||||
uint8_t adc(uint8_t operand, uint8_t data);
|
[[nodiscard]] uint8_t adc(uint8_t operand, uint8_t data);
|
||||||
uint8_t add_b(uint8_t operand, uint8_t data, int carry);
|
[[nodiscard]] uint8_t add_b(uint8_t operand, uint8_t data, int carry);
|
||||||
uint8_t add_d(uint8_t operand, uint8_t data, int carry);
|
[[nodiscard]] uint8_t add_d(uint8_t operand, uint8_t data, int carry);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const uint8_t IRQvector = 0xfe; // IRQ vector
|
const uint8_t IRQvector = 0xfe; // IRQ vector
|
||||||
@ -75,25 +75,25 @@ namespace EightBit {
|
|||||||
|
|
||||||
void interrupt();
|
void interrupt();
|
||||||
|
|
||||||
virtual void push(uint8_t value) final;
|
void push(uint8_t value) final;
|
||||||
virtual uint8_t pop() final;
|
[[nodiscard]] uint8_t pop() final;
|
||||||
|
|
||||||
// Dummy stack push, used during RESET
|
// Dummy stack push, used during RESET
|
||||||
void dummyPush(uint8_t value);
|
void dummyPush(uint8_t value);
|
||||||
|
|
||||||
// Addressing modes
|
// Addressing modes
|
||||||
|
|
||||||
register16_t Address_Absolute();
|
[[nodiscard]] register16_t Address_Absolute();
|
||||||
uint8_t Address_ZeroPage();
|
[[nodiscard]] uint8_t Address_ZeroPage();
|
||||||
register16_t Address_ZeroPageIndirect();
|
[[nodiscard]] register16_t Address_ZeroPageIndirect();
|
||||||
register16_t Address_Indirect();
|
[[nodiscard]] register16_t Address_Indirect();
|
||||||
uint8_t Address_ZeroPageX();
|
[[nodiscard]] uint8_t Address_ZeroPageX();
|
||||||
uint8_t Address_ZeroPageY();
|
[[nodiscard]] uint8_t Address_ZeroPageY();
|
||||||
std::pair<register16_t, uint8_t> Address_AbsoluteX();
|
[[nodiscard]] std::pair<register16_t, uint8_t> Address_AbsoluteX();
|
||||||
std::pair<register16_t, uint8_t> Address_AbsoluteY();
|
[[nodiscard]] std::pair<register16_t, uint8_t> Address_AbsoluteY();
|
||||||
register16_t Address_IndexedIndirectX();
|
[[nodiscard]] register16_t Address_IndexedIndirectX();
|
||||||
std::pair<register16_t, uint8_t> Address_IndirectIndexedY();
|
[[nodiscard]] std::pair<register16_t, uint8_t> Address_IndirectIndexedY();
|
||||||
register16_t Address_relative_byte();
|
[[nodiscard]] register16_t Address_relative_byte();
|
||||||
|
|
||||||
// Addressing modes, read
|
// Addressing modes, read
|
||||||
|
|
||||||
@ -121,19 +121,19 @@ namespace EightBit {
|
|||||||
|
|
||||||
// Flag checking
|
// Flag checking
|
||||||
|
|
||||||
auto interruptMasked() const { return P() & IF; }
|
[[nodiscard]] auto interruptMasked() const { return P() & IF; }
|
||||||
auto decimal() const { return P() & DF; }
|
[[nodiscard]] auto decimal() const { return P() & DF; }
|
||||||
|
|
||||||
auto negative() const { return P() & NF; }
|
[[nodiscard]] auto negative() const { return P() & NF; }
|
||||||
auto zero() const { return P() & ZF; }
|
[[nodiscard]] auto zero() const { return P() & ZF; }
|
||||||
auto overflow() const { return P() & VF; }
|
[[nodiscard]] auto overflow() const { return P() & VF; }
|
||||||
auto carry() const { return P() & CF; }
|
[[nodiscard]] auto carry() const { return P() & CF; }
|
||||||
|
|
||||||
// Miscellaneous
|
// Miscellaneous
|
||||||
|
|
||||||
void branch(int condition);
|
void branch(int condition);
|
||||||
|
|
||||||
auto through(const uint8_t data) {
|
[[nodiscard]] auto through(const uint8_t data) {
|
||||||
adjustNZ(data);
|
adjustNZ(data);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
@ -146,20 +146,20 @@ namespace EightBit {
|
|||||||
|
|
||||||
// Instruction implementations
|
// Instruction implementations
|
||||||
|
|
||||||
uint8_t andr(uint8_t operand, uint8_t data);
|
[[nodiscard]] uint8_t andr(uint8_t operand, uint8_t data);
|
||||||
uint8_t asl(uint8_t value);
|
[[nodiscard]] uint8_t asl(uint8_t value);
|
||||||
void bit(uint8_t operand, uint8_t data);
|
void bit(uint8_t operand, uint8_t data);
|
||||||
void cmp(uint8_t first, uint8_t second);
|
void cmp(uint8_t first, uint8_t second);
|
||||||
uint8_t dec(uint8_t value);
|
[[nodiscard]] uint8_t dec(uint8_t value);
|
||||||
uint8_t eorr(uint8_t operand, uint8_t data);
|
[[nodiscard]] uint8_t eorr(uint8_t operand, uint8_t data);
|
||||||
uint8_t inc(uint8_t value);
|
[[nodiscard]] uint8_t inc(uint8_t value);
|
||||||
void jsr();
|
void jsr();
|
||||||
uint8_t lsr(uint8_t value);
|
[[nodiscard]] uint8_t lsr(uint8_t value);
|
||||||
uint8_t orr(uint8_t operand, uint8_t data);
|
[[nodiscard]] uint8_t orr(uint8_t operand, uint8_t data);
|
||||||
void php();
|
void php();
|
||||||
void plp();
|
void plp();
|
||||||
uint8_t rol(uint8_t operand);
|
[[nodiscard]] uint8_t rol(uint8_t operand);
|
||||||
uint8_t ror(uint8_t operand);
|
[[nodiscard]] uint8_t ror(uint8_t operand);
|
||||||
void rti();
|
void rti();
|
||||||
void rts();
|
void rts();
|
||||||
|
|
||||||
|
@ -17,15 +17,15 @@ EightBit::Profiler::Profiler(MOS6502& targetProcessor, Disassembly& disassembler
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EightBit::Profiler::Generate() {
|
void EightBit::Profiler::Generate() {
|
||||||
StartingOutput.fire(EventArgs::empty());
|
StartingOutput.fire();
|
||||||
EmitProfileInformation();
|
EmitProfileInformation();
|
||||||
StartingOutput.fire(EventArgs::empty());
|
StartingOutput.fire();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EightBit::Profiler::EmitProfileInformation() {
|
void EightBit::Profiler::EmitProfileInformation() {
|
||||||
|
|
||||||
{
|
{
|
||||||
StartingLineOutput.fire(EventArgs::empty());
|
StartingLineOutput.fire();
|
||||||
// For each memory address
|
// For each memory address
|
||||||
for (int address = 0; address < 0x10000; ++address) {
|
for (int address = 0; address < 0x10000; ++address) {
|
||||||
// If there are any cycles associated
|
// If there are any cycles associated
|
||||||
@ -37,11 +37,11 @@ void EightBit::Profiler::EmitProfileInformation() {
|
|||||||
EmitLine.fire(event);
|
EmitLine.fire(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FinishedLineOutput.fire(EventArgs::empty());
|
FinishedLineOutput.fire();
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
StartingScopeOutput.fire(EventArgs::empty());
|
StartingScopeOutput.fire();
|
||||||
for (auto& scopeCycle : scopeCycles) {
|
for (auto& scopeCycle : scopeCycles) {
|
||||||
auto name = scopeCycle.first;
|
auto name = scopeCycle.first;
|
||||||
auto cycles = scopeCycle.second;
|
auto cycles = scopeCycle.second;
|
||||||
@ -50,7 +50,7 @@ void EightBit::Profiler::EmitProfileInformation() {
|
|||||||
ProfileScopeEventArgs event(name, cycles, count);
|
ProfileScopeEventArgs event(name, cycles, count);
|
||||||
EmitScope.fire(event);
|
EmitScope.fire(event);
|
||||||
}
|
}
|
||||||
FinishedScopeOutput.fire(EventArgs::empty());
|
FinishedScopeOutput.fire();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ void EightBit::M6532::step() {
|
|||||||
if (!activated())
|
if (!activated())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Accessing.fire(EventArgs::empty());
|
Accessing.fire();
|
||||||
|
|
||||||
if (lowered(RES())) {
|
if (lowered(RES())) {
|
||||||
reset();
|
reset();
|
||||||
@ -120,7 +120,7 @@ void EightBit::M6532::step() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Accessed.fire(EventArgs::empty());
|
Accessed.fire();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EightBit::M6532::reset() {
|
void EightBit::M6532::reset() {
|
||||||
|
@ -12,11 +12,24 @@ namespace EightBit {
|
|||||||
public:
|
public:
|
||||||
Disassembly(Bus& bus, mc6809& processor);
|
Disassembly(Bus& bus, mc6809& processor);
|
||||||
|
|
||||||
bool ignore();
|
[[nodiscard]] bool ignore();
|
||||||
|
|
||||||
std::string trace(uint16_t current);
|
[[nodiscard]] std::string trace(uint16_t current);
|
||||||
std::string trace(register16_t current);
|
[[nodiscard]] std::string disassemble(uint16_t current);
|
||||||
std::string trace();
|
|
||||||
|
[[nodiscard]] std::string trace(register16_t current);
|
||||||
|
[[nodiscard]] std::string disassemble(register16_t current);
|
||||||
|
|
||||||
|
[[nodiscard]] std::string trace();
|
||||||
|
[[nodiscard]] std::string disassemble();
|
||||||
|
|
||||||
|
static [[nodiscard]] std::string dump_Flags(uint8_t value);
|
||||||
|
static [[nodiscard]] std::string dump_ByteValue(uint8_t value);
|
||||||
|
static [[nodiscard]] std::string dump_RelativeValue(int8_t value);
|
||||||
|
static [[nodiscard]] std::string dump_WordValue(uint16_t value);
|
||||||
|
static [[nodiscard]] std::string dump_WordValue(register16_t value);
|
||||||
|
static [[nodiscard]] std::string dump_RelativeValue(int16_t value);
|
||||||
|
static [[nodiscard]] std::string dump_RelativeValue(register16_t value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Bus& m_bus;
|
Bus& m_bus;
|
||||||
@ -27,63 +40,50 @@ namespace EightBit {
|
|||||||
bool m_prefix10 = false;
|
bool m_prefix10 = false;
|
||||||
bool m_prefix11 = false;
|
bool m_prefix11 = false;
|
||||||
|
|
||||||
static std::string dump_Flags(uint8_t value);
|
|
||||||
static std::string dump_ByteValue(uint8_t value);
|
|
||||||
static std::string dump_RelativeValue(int8_t value);
|
|
||||||
static std::string dump_WordValue(uint16_t value);
|
|
||||||
static std::string dump_WordValue(register16_t value);
|
|
||||||
static std::string dump_RelativeValue(int16_t value);
|
|
||||||
static std::string dump_RelativeValue(register16_t value);
|
|
||||||
|
|
||||||
std::string disassemble(uint16_t current);
|
|
||||||
std::string disassemble(register16_t current);
|
|
||||||
std::string disassemble();
|
|
||||||
|
|
||||||
static void dump(std::ostream& out, int value, int width);
|
static void dump(std::ostream& out, int value, int width);
|
||||||
|
|
||||||
mc6809& CPU() { return m_cpu; }
|
[[nodiscard]] mc6809& CPU() { return m_cpu; }
|
||||||
|
[[nodiscard]] Bus& BUS() { return m_bus; }
|
||||||
|
|
||||||
uint8_t getByte(uint16_t address);
|
[[nodiscard]] uint8_t getByte(uint16_t address);
|
||||||
uint16_t getWord(uint16_t address);
|
[[nodiscard]] uint16_t getWord(uint16_t address);
|
||||||
|
|
||||||
std::string disassembleUnprefixed();
|
[[nodiscard]] std::string disassembleUnprefixed();
|
||||||
std::string disassemble10();
|
[[nodiscard]] std::string disassemble10();
|
||||||
std::string disassemble11();
|
[[nodiscard]] std::string disassemble11();
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
std::string RR(int which);
|
[[nodiscard]] std::string RR(int which);
|
||||||
std::string wrapIndirect(std::string what, bool indirect);
|
[[nodiscard]] std::string wrapIndirect(std::string what, bool indirect);
|
||||||
|
|
||||||
std::string Address_direct(std::string mnemomic);
|
[[nodiscard]] std::string Address_direct(std::string mnemomic);
|
||||||
std::string Address_indexed(std::string mnemomic);
|
[[nodiscard]] std::string Address_indexed(std::string mnemomic);
|
||||||
std::string Address_extended(std::string mnemomic);
|
[[nodiscard]] std::string Address_extended(std::string mnemomic);
|
||||||
std::string Address_relative_byte(std::string mnemomic);
|
[[nodiscard]] std::string Address_relative_byte(std::string mnemomic);
|
||||||
std::string Address_relative_word(std::string mnemomic);
|
[[nodiscard]] std::string Address_relative_word(std::string mnemomic);
|
||||||
|
|
||||||
std::string AM_immediate_byte(std::string mnemomic);
|
[[nodiscard]] std::string AM_immediate_byte(std::string mnemomic);
|
||||||
std::string AM_immediate_word(std::string mnemomic);
|
[[nodiscard]] std::string AM_immediate_word(std::string mnemomic);
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
std::string branchShort(std::string mnemomic);
|
[[nodiscard]] std::string branchShort(std::string mnemomic);
|
||||||
std::string branchLong(std::string mnemomic);
|
[[nodiscard]] std::string branchLong(std::string mnemomic);
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
std::string referenceTransfer8(int specifier);
|
[[nodiscard]] std::string referenceTransfer8(int specifier);
|
||||||
std::string referenceTransfer16(int specifier);
|
[[nodiscard]] std::string referenceTransfer16(int specifier);
|
||||||
std::string tfr(std::string mnemomic);
|
[[nodiscard]] std::string tfr(std::string mnemomic);
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
std::string pulS();
|
[[nodiscard]] std::string pulS();
|
||||||
std::string pulU();
|
[[nodiscard]] std::string pulU();
|
||||||
std::string pshS();
|
[[nodiscard]] std::string pshS();
|
||||||
std::string pshU();
|
[[nodiscard]] std::string pshU();
|
||||||
std::string pulX(std::string mnemomic, std::string upon);
|
[[nodiscard]] std::string pulX(std::string mnemomic, std::string upon);
|
||||||
std::string pshX(std::string mnemomic, std::string upon);
|
[[nodiscard]] std::string pshX(std::string mnemomic, std::string upon);
|
||||||
|
|
||||||
Bus& BUS() { return m_bus; }
|
|
||||||
};
|
};
|
||||||
}
|
}
|
22
MC6809/inc/ProfileLineEventArgs.h
Normal file
22
MC6809/inc/ProfileLineEventArgs.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace EightBit {
|
||||||
|
class ProfileLineEventArgs
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
int m_address;
|
||||||
|
std::string m_source;
|
||||||
|
uint64_t m_cycles;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ProfileLineEventArgs(int address, std::string source, uint64_t cycles)
|
||||||
|
: m_address(address), m_source(source), m_cycles(cycles) {}
|
||||||
|
|
||||||
|
int address() const { return m_address; }
|
||||||
|
const std::string& source() const { return m_source; }
|
||||||
|
uint64_t cycles() const { return m_cycles; }
|
||||||
|
};
|
||||||
|
}
|
41
MC6809/inc/Profiler.h
Normal file
41
MC6809/inc/Profiler.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <EventArgs.h>
|
||||||
|
#include <Signal.h>
|
||||||
|
|
||||||
|
#include "ProfileLineEventArgs.h"
|
||||||
|
|
||||||
|
namespace EightBit {
|
||||||
|
|
||||||
|
class Disassembly;
|
||||||
|
class mc6809;
|
||||||
|
|
||||||
|
class Profiler {
|
||||||
|
public:
|
||||||
|
std::array<uint64_t, 0x100> instructionCounts;
|
||||||
|
std::array<uint64_t, 0x10000> addressProfiles;
|
||||||
|
std::array<uint64_t, 0x10000> addressCounts;
|
||||||
|
|
||||||
|
mc6809& processor;
|
||||||
|
Disassembly& disassembler;
|
||||||
|
|
||||||
|
Profiler(mc6809& processor, Disassembly& disassembler);
|
||||||
|
|
||||||
|
Signal<EventArgs> StartingOutput;
|
||||||
|
Signal<EventArgs> FinishedOutput;
|
||||||
|
|
||||||
|
Signal<ProfileLineEventArgs> EmitLine;
|
||||||
|
|
||||||
|
void addInstruction(uint8_t instruction);
|
||||||
|
void addAddress(uint16_t address, int cycles);
|
||||||
|
|
||||||
|
void Generate();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void EmitProfileInformation();
|
||||||
|
};
|
||||||
|
}
|
@ -21,11 +21,14 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\inc\Disassembly.h" />
|
<ClInclude Include="..\inc\Disassembly.h" />
|
||||||
<ClInclude Include="..\inc\mc6809.h" />
|
<ClInclude Include="..\inc\mc6809.h" />
|
||||||
|
<ClInclude Include="..\inc\ProfileLineEventArgs.h" />
|
||||||
|
<ClInclude Include="..\inc\Profiler.h" />
|
||||||
<ClInclude Include="stdafx.h" />
|
<ClInclude Include="stdafx.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="Disassembly.cpp" />
|
<ClCompile Include="Disassembly.cpp" />
|
||||||
<ClCompile Include="mc6809.cpp" />
|
<ClCompile Include="mc6809.cpp" />
|
||||||
|
<ClCompile Include="Profiler.cpp" />
|
||||||
<ClCompile Include="stdafx.cpp">
|
<ClCompile Include="stdafx.cpp">
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||||
|
@ -20,6 +20,12 @@
|
|||||||
<ClInclude Include="stdafx.h">
|
<ClInclude Include="stdafx.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\inc\ProfileLineEventArgs.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\inc\Profiler.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="stdafx.cpp">
|
<ClCompile Include="stdafx.cpp">
|
||||||
@ -31,5 +37,8 @@
|
|||||||
<ClCompile Include="Disassembly.cpp">
|
<ClCompile Include="Disassembly.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Profiler.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
41
MC6809/src/Profiler.cpp
Normal file
41
MC6809/src/Profiler.cpp
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
#include "Profiler.h"
|
||||||
|
|
||||||
|
#include "Disassembly.h"
|
||||||
|
|
||||||
|
EightBit::Profiler::Profiler(mc6809& targetProcessor, Disassembly& disassemblerTarget)
|
||||||
|
: processor(targetProcessor),
|
||||||
|
disassembler(disassemblerTarget) {
|
||||||
|
instructionCounts.fill(0);
|
||||||
|
addressProfiles.fill(0);
|
||||||
|
addressCounts.fill(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EightBit::Profiler::Generate() {
|
||||||
|
StartingOutput.fire();
|
||||||
|
EmitProfileInformation();
|
||||||
|
StartingOutput.fire();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EightBit::Profiler::EmitProfileInformation() {
|
||||||
|
// For each memory address
|
||||||
|
for (int address = 0; address < 0x10000; ++address) {
|
||||||
|
// If there are any cycles associated
|
||||||
|
auto cycles = addressProfiles[address];
|
||||||
|
if (cycles > 0) {
|
||||||
|
// Dump a profile/disassembly line
|
||||||
|
auto source = disassembler.disassemble(address);
|
||||||
|
ProfileLineEventArgs event(address, source, cycles);
|
||||||
|
EmitLine.fire(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EightBit::Profiler::addInstruction(uint8_t instruction) {
|
||||||
|
++instructionCounts[instruction];
|
||||||
|
}
|
||||||
|
|
||||||
|
void EightBit::Profiler::addAddress(uint16_t address, int cycles) {
|
||||||
|
addressCounts[address]++;
|
||||||
|
addressProfiles[address] += cycles;
|
||||||
|
}
|
@ -27,6 +27,14 @@ void Board::raisePOWER() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Board::lowerPOWER() {
|
void Board::lowerPOWER() {
|
||||||
|
|
||||||
|
if (m_configuration.isProfileMode()) {
|
||||||
|
m_profiler.EmitLine.connect([this](EightBit::ProfileLineEventArgs line) {
|
||||||
|
std::cout << EightBit::Disassembly::dump_WordValue(line.address()) << " " << line.source() << std::endl;
|
||||||
|
});
|
||||||
|
m_profiler.Generate();
|
||||||
|
}
|
||||||
|
|
||||||
ACIA().lowerPOWER();
|
ACIA().lowerPOWER();
|
||||||
CPU().lowerPOWER();
|
CPU().lowerPOWER();
|
||||||
EightBit::Bus::lowerPOWER();
|
EightBit::Bus::lowerPOWER();
|
||||||
@ -71,6 +79,15 @@ void Board::initialise() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (m_configuration.isProfileMode()) {
|
||||||
|
m_cpu.ExecutingInstruction.connect([this](EightBit::mc6809& cpu) {
|
||||||
|
m_profiler.addInstruction(peek(cpu.PC()));
|
||||||
|
});
|
||||||
|
m_cpu.ExecutedInstruction.connect([this](EightBit::mc6809& cpu) {
|
||||||
|
m_profiler.addAddress(cpu.PC().word, cpu.cycles());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (m_configuration.isDebugMode()) {
|
if (m_configuration.isDebugMode()) {
|
||||||
// MC6809 disassembly wiring
|
// MC6809 disassembly wiring
|
||||||
CPU().ExecutingInstruction.connect([this] (EightBit::mc6809& cpu) {
|
CPU().ExecutingInstruction.connect([this] (EightBit::mc6809& cpu) {
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <Disassembly.h>
|
#include <Disassembly.h>
|
||||||
#include <MC6850.h>
|
#include <MC6850.h>
|
||||||
#include <UnusedMemory.h>
|
#include <UnusedMemory.h>
|
||||||
|
#include <Profiler.h>
|
||||||
|
|
||||||
class Board : public EightBit::Bus {
|
class Board : public EightBit::Bus {
|
||||||
public:
|
public:
|
||||||
@ -38,6 +39,7 @@ private:
|
|||||||
|
|
||||||
EightBit::mc6809 m_cpu = *this;
|
EightBit::mc6809 m_cpu = *this;
|
||||||
EightBit::Disassembly m_disassembler = { *this, m_cpu };
|
EightBit::Disassembly m_disassembler = { *this, m_cpu };
|
||||||
|
EightBit::Profiler m_profiler = { m_cpu, m_disassembler };
|
||||||
|
|
||||||
uint64_t m_totalCycleCount = 0UL;
|
uint64_t m_totalCycleCount = 0UL;
|
||||||
int64_t m_frameCycleCount = 0L;
|
int64_t m_frameCycleCount = 0L;
|
||||||
|
@ -14,6 +14,9 @@ public:
|
|||||||
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; }
|
||||||
|
|
||||||
bool terminatesEarly() const { return m_terminatesEarly; }
|
bool terminatesEarly() const { return m_terminatesEarly; }
|
||||||
void setTerminatesEarly(bool value) { m_terminatesEarly = value; }
|
void setTerminatesEarly(bool value) { m_terminatesEarly = value; }
|
||||||
|
|
||||||
@ -21,6 +24,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_debugMode = false;
|
bool m_debugMode = false;
|
||||||
|
bool m_profileMode = false;
|
||||||
bool m_terminatesEarly = false;
|
bool m_terminatesEarly = false;
|
||||||
std::string m_romDirectory = "roms\\searle";
|
std::string m_romDirectory = "roms\\searle";
|
||||||
};
|
};
|
||||||
|
@ -25,20 +25,17 @@ void Board::lowerPOWER() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Board::initialise() {
|
void Board::initialise() {
|
||||||
//CPU().ExecutingInstruction.connect(std::bind(&Board::Cpu_ExecutingInstruction_Debug, this, std::placeholders::_1));
|
CPU().ExecutingInstruction.connect([this](EightBit::mc6809& cpu) {
|
||||||
//CPU().ExecutedInstruction.connect(std::bind(&Board::Cpu_ExecutedInstruction_Debug, this, std::placeholders::_1));
|
m_disassembleAt = CPU().PC();
|
||||||
|
m_ignoreDisassembly = m_disassembler.ignore();
|
||||||
|
});
|
||||||
|
|
||||||
|
CPU().ExecutedInstruction.connect([this](EightBit::mc6809& cpu) {
|
||||||
|
if (!m_ignoreDisassembly)
|
||||||
|
std::cout << m_disassembler.trace(m_disassembleAt) << " " << std::endl;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
EightBit::MemoryMapping Board::mapping(uint16_t) {
|
EightBit::MemoryMapping Board::mapping(uint16_t) {
|
||||||
return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite };
|
return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite };
|
||||||
}
|
}
|
||||||
|
|
||||||
void Board::Cpu_ExecutingInstruction_Debug(EightBit::mc6809&) {
|
|
||||||
m_disassembleAt = CPU().PC();
|
|
||||||
m_ignoreDisassembly = m_disassembler.ignore();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Board::Cpu_ExecutedInstruction_Debug(EightBit::mc6809&) {
|
|
||||||
if (!m_ignoreDisassembly)
|
|
||||||
std::cout << m_disassembler.trace(m_disassembleAt) << " " << std::endl;
|
|
||||||
}
|
|
||||||
|
@ -5,19 +5,19 @@
|
|||||||
#include <mc6809.h>
|
#include <mc6809.h>
|
||||||
#include <Disassembly.h>
|
#include <Disassembly.h>
|
||||||
|
|
||||||
class Board : public EightBit::Bus {
|
class Board final : public EightBit::Bus {
|
||||||
public:
|
public:
|
||||||
Board();
|
Board();
|
||||||
|
|
||||||
EightBit::mc6809& CPU() { return m_cpu; }
|
EightBit::mc6809& CPU() { return m_cpu; }
|
||||||
|
|
||||||
virtual void raisePOWER() final;
|
void raisePOWER() final;
|
||||||
virtual void lowerPOWER() final;
|
void lowerPOWER() final;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void initialise() final;
|
void initialise() final;
|
||||||
|
|
||||||
virtual EightBit::MemoryMapping mapping(uint16_t address) final;
|
EightBit::MemoryMapping mapping(uint16_t address) final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EightBit::Ram m_ram = 0x10000; // 0000 - FFFF, 64K RAM
|
EightBit::Ram m_ram = 0x10000; // 0000 - FFFF, 64K RAM
|
||||||
@ -27,7 +27,4 @@ private:
|
|||||||
// The m_disassembleAt and m_ignoreDisassembly are used to skip pin events
|
// The m_disassembleAt and m_ignoreDisassembly are used to skip pin events
|
||||||
EightBit::register16_t m_disassembleAt = 0x0000;
|
EightBit::register16_t m_disassembleAt = 0x0000;
|
||||||
bool m_ignoreDisassembly = false;
|
bool m_ignoreDisassembly = false;
|
||||||
|
|
||||||
void Cpu_ExecutingInstruction_Debug(EightBit::mc6809&);
|
|
||||||
void Cpu_ExecutedInstruction_Debug(EightBit::mc6809&);
|
|
||||||
};
|
};
|
||||||
|
@ -18,9 +18,9 @@ namespace EightBit {
|
|||||||
// | Bus | (high)(low) | (high)(high) | (low)(low) | (low)(low) |
|
// | Bus | (high)(low) | (high)(high) | (low)(low) | (low)(low) |
|
||||||
// | Line | Transmit | Receive | | |
|
// | Line | Transmit | Receive | | |
|
||||||
// | Number | Data | Data | Control | Status |
|
// | Number | Data | Data | Control | Status |
|
||||||
// | | Register | Register | register | register |
|
// | | Register | Register | Register | register |
|
||||||
// | +------------------+------------------+--------------------+-----------------------+
|
// | +------------------+------------------+--------------------+-----------------------+
|
||||||
// | | (Write only) + (Read only) + (Write only) | (Read only) |
|
// | | (Write only) | (Read only) | (Write only) | (Read only) |
|
||||||
// +--------+------------------+------------------+--------------------+-----------------------+
|
// +--------+------------------+------------------+--------------------+-----------------------+
|
||||||
// | 0 | Data bit 0* | Data bit 0 | Counter divide | Receive data register |
|
// | 0 | Data bit 0* | Data bit 0 | Counter divide | Receive data register |
|
||||||
// | | | | select 1 (CR0) | full (RDRF) |
|
// | | | | select 1 (CR0) | full (RDRF) |
|
||||||
@ -284,10 +284,10 @@ namespace EightBit {
|
|||||||
bool m_statusRead = false;
|
bool m_statusRead = false;
|
||||||
|
|
||||||
// Control registers
|
// Control registers
|
||||||
CounterDivideSelect m_counterDivide = One;
|
CounterDivideSelect m_counterDivide = CounterDivideSelect::One;
|
||||||
WordSelect m_wordSelect = SevenEvenTwo;
|
WordSelect m_wordSelect = WordSelect::SevenEvenTwo;
|
||||||
TransmitterControl m_transmitControl = ReadyLowInterruptDisabled;
|
TransmitterControl m_transmitControl = TransmitterControl::ReadyLowInterruptDisabled;
|
||||||
ReceiveControl m_receiveControl = ReceiveInterruptDisable;
|
ReceiveControl m_receiveControl = ReceiveControl::ReceiveInterruptDisable;
|
||||||
|
|
||||||
// Status registers
|
// Status registers
|
||||||
bool m_statusRDRF = false;
|
bool m_statusRDRF = false;
|
||||||
|
Binary file not shown.
@ -15,7 +15,7 @@ namespace EightBit {
|
|||||||
static std::string state(Z80& cpu);
|
static std::string state(Z80& cpu);
|
||||||
std::string disassemble(Z80& cpu);
|
std::string disassemble(Z80& cpu);
|
||||||
|
|
||||||
static std::string flag(uint8_t value, int flag, const std::string& represents);
|
static std::string flag(uint8_t value, int flag, std::string represents);
|
||||||
static std::string flags(uint8_t value);
|
static std::string flags(uint8_t value);
|
||||||
static std::string hex(uint8_t value);
|
static std::string hex(uint8_t value);
|
||||||
static std::string hex(uint16_t value);
|
static std::string hex(uint16_t value);
|
||||||
|
@ -726,7 +726,7 @@ void EightBit::Disassembler::disassembleOther(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string EightBit::Disassembler::flag(uint8_t value, int flag, const std::string& represents) {
|
std::string EightBit::Disassembler::flag(uint8_t value, int flag, const std::string represents) {
|
||||||
std::ostringstream output;
|
std::ostringstream output;
|
||||||
output << (value & flag ? represents : "-");
|
output << (value & flag ? represents : "-");
|
||||||
return output.str();
|
return output.str();
|
||||||
|
@ -103,7 +103,7 @@ namespace EightBit {
|
|||||||
|
|
||||||
virtual ~Device() = default;
|
virtual ~Device() = default;
|
||||||
|
|
||||||
[[nodiscard]] bool powered() noexcept { return raised(POWER()); }
|
[[nodiscard]] bool powered() const noexcept { return raised(POWER()); }
|
||||||
|
|
||||||
DECLARE_PIN_INPUT(POWER)
|
DECLARE_PIN_INPUT(POWER)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user