mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2024-12-23 00:29:47 +00:00
Initial stab at getting MOS6502 imported to the EightBit library.
Signed-off-by: Adrian.Conlon <adrian.conlon@gmail.com>
This commit is contained in:
parent
6af1857cb0
commit
88d3e4fd47
@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class AddressEventArgs
|
||||
{
|
||||
private:
|
||||
uint16_t m_address;
|
||||
uint8_t m_cell;
|
||||
|
||||
public:
|
||||
AddressEventArgs(uint16_t address, uint8_t cell)
|
||||
: m_address(address), m_cell(cell) {}
|
||||
|
||||
uint16_t getAddress() const { return m_address; }
|
||||
uint8_t getCell() const { return m_cell; }
|
||||
};
|
@ -1,21 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
enum AddressingMode {
|
||||
Illegal,
|
||||
Implied,
|
||||
Accumulator,
|
||||
Immediate,
|
||||
Relative,
|
||||
XIndexed,
|
||||
IndexedY,
|
||||
ZeroPage,
|
||||
ZeroPageX,
|
||||
ZeroPageY,
|
||||
Absolute,
|
||||
AbsoluteX,
|
||||
AbsoluteY,
|
||||
AbsoluteXIndirect,
|
||||
Indirect,
|
||||
ZeroPageIndirect,
|
||||
ZeroPageRelative
|
||||
};
|
||||
namespace EightBit {
|
||||
enum AddressingMode {
|
||||
Illegal,
|
||||
Implied,
|
||||
Accumulator,
|
||||
Immediate,
|
||||
Relative,
|
||||
XIndexed,
|
||||
IndexedY,
|
||||
ZeroPage,
|
||||
ZeroPageX,
|
||||
ZeroPageY,
|
||||
Absolute,
|
||||
AbsoluteX,
|
||||
AbsoluteY,
|
||||
AbsoluteXIndirect,
|
||||
Indirect,
|
||||
ZeroPageIndirect,
|
||||
ZeroPageRelative
|
||||
};
|
||||
}
|
@ -3,9 +3,12 @@
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
|
||||
typedef std::function<std::string(uint16_t current)> dumper_t;
|
||||
namespace EightBit {
|
||||
|
||||
struct AddressingModeDumper {
|
||||
dumper_t byteDumper;
|
||||
dumper_t disassemblyDumper;
|
||||
};
|
||||
typedef std::function<std::string(uint16_t current)> dumper_t;
|
||||
|
||||
struct AddressingModeDumper {
|
||||
dumper_t byteDumper;
|
||||
dumper_t disassemblyDumper;
|
||||
};
|
||||
}
|
@ -3,62 +3,63 @@
|
||||
#include <map>
|
||||
#include <cstdint>
|
||||
|
||||
#include <mos6502.h>
|
||||
#include <AddressingMode.h>
|
||||
#include "mos6502.h"
|
||||
#include "AddressingMode.h"
|
||||
|
||||
#include "Symbols.h"
|
||||
#include "AddressingModeDumper.h"
|
||||
|
||||
class Disassembly
|
||||
{
|
||||
public:
|
||||
MOS6502& processor;
|
||||
const Symbols& symbols;
|
||||
namespace EightBit {
|
||||
class Disassembly {
|
||||
public:
|
||||
MOS6502& processor;
|
||||
const Symbols& symbols;
|
||||
|
||||
std::map<AddressingMode, AddressingModeDumper> dumpers;
|
||||
std::map<AddressingMode, AddressingModeDumper> dumpers;
|
||||
|
||||
Disassembly(MOS6502& processor, const Symbols& symbols);
|
||||
Disassembly(MOS6502& processor, const Symbols& symbols);
|
||||
|
||||
std::string Dump_ByteValue(uint8_t value) const;
|
||||
std::string Dump_WordValue(uint16_t value) const;
|
||||
std::string Dump_ByteValue(uint8_t value) const;
|
||||
std::string Dump_WordValue(uint16_t value) const;
|
||||
|
||||
std::string DumpBytes(AddressingMode mode, uint16_t current) const;
|
||||
std::string Disassemble(uint16_t current) const;
|
||||
std::string DumpOperand(AddressingMode mode, uint16_t current) const;
|
||||
std::string DumpBytes(AddressingMode mode, uint16_t current) const;
|
||||
std::string Disassemble(uint16_t current) const;
|
||||
std::string DumpOperand(AddressingMode mode, uint16_t current) const;
|
||||
|
||||
private:
|
||||
uint8_t GetByte(uint16_t address) const;
|
||||
uint16_t GetWord(uint16_t address) const;
|
||||
private:
|
||||
uint8_t GetByte(uint16_t address) const;
|
||||
uint16_t GetWord(uint16_t address) const;
|
||||
|
||||
std::string Dump_Nothing(uint16_t unused) const;
|
||||
std::string Dump_Byte(uint16_t address) const;
|
||||
std::string Dump_DByte(uint16_t address) const;
|
||||
std::string Dump_Nothing(uint16_t unused) const;
|
||||
std::string Dump_Byte(uint16_t address) const;
|
||||
std::string Dump_DByte(uint16_t address) const;
|
||||
|
||||
std::string ConvertAddress(uint16_t address) const;
|
||||
std::string ConvertAddress(uint8_t address) const;
|
||||
std::string ConvertConstant(uint16_t constant) const;
|
||||
std::string ConvertConstant(uint8_t constant) const;
|
||||
std::string ConvertAddress(uint16_t address) const;
|
||||
std::string ConvertAddress(uint8_t address) const;
|
||||
std::string ConvertConstant(uint16_t constant) const;
|
||||
std::string ConvertConstant(uint8_t constant) const;
|
||||
|
||||
std::string Dump_A(uint16_t unused) const;
|
||||
std::string Dump_imm(uint16_t current) const;
|
||||
std::string Dump_abs(uint16_t current) const;
|
||||
std::string Dump_zp(uint16_t current) const;
|
||||
std::string Dump_zpx(uint16_t current) const;
|
||||
std::string Dump_zpy(uint16_t current) const;
|
||||
std::string Dump_absx(uint16_t current) const;
|
||||
std::string Dump_absy(uint16_t current) const;
|
||||
std::string Dump_absxind(uint16_t current) const;
|
||||
std::string Dump_xind(uint16_t current) const;
|
||||
std::string Dump_indy(uint16_t current) const;
|
||||
std::string Dump_ind(uint16_t current) const;
|
||||
std::string Dump_zpind(uint16_t current) const;
|
||||
std::string Dump_rel(uint16_t current) const;
|
||||
std::string Dump_zprel(uint16_t current) const;
|
||||
std::string Dump_A(uint16_t unused) const;
|
||||
std::string Dump_imm(uint16_t current) const;
|
||||
std::string Dump_abs(uint16_t current) const;
|
||||
std::string Dump_zp(uint16_t current) const;
|
||||
std::string Dump_zpx(uint16_t current) const;
|
||||
std::string Dump_zpy(uint16_t current) const;
|
||||
std::string Dump_absx(uint16_t current) const;
|
||||
std::string Dump_absy(uint16_t current) const;
|
||||
std::string Dump_absxind(uint16_t current) const;
|
||||
std::string Dump_xind(uint16_t current) const;
|
||||
std::string Dump_indy(uint16_t current) const;
|
||||
std::string Dump_ind(uint16_t current) const;
|
||||
std::string Dump_zpind(uint16_t current) const;
|
||||
std::string Dump_rel(uint16_t current) const;
|
||||
std::string Dump_zprel(uint16_t current) const;
|
||||
|
||||
const AddressingModeDumper& getDumper(AddressingMode mode) const {
|
||||
auto dumper = dumpers.find(mode);
|
||||
if (dumper == dumpers.end())
|
||||
throw std::invalid_argument("Illegal addressing mode");
|
||||
return dumper->second;
|
||||
}
|
||||
};
|
||||
const AddressingModeDumper& getDumper(AddressingMode mode) const {
|
||||
auto dumper = dumpers.find(mode);
|
||||
if (dumper == dumpers.end())
|
||||
throw std::invalid_argument("Illegal addressing mode");
|
||||
return dumper->second;
|
||||
}
|
||||
};
|
||||
}
|
@ -2,14 +2,15 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
class DisassemblyEventArgs
|
||||
{
|
||||
private:
|
||||
std::string m_output;
|
||||
namespace EightBit {
|
||||
class DisassemblyEventArgs {
|
||||
private:
|
||||
std::string m_output;
|
||||
|
||||
public:
|
||||
DisassemblyEventArgs(std::string output)
|
||||
: m_output(output) {}
|
||||
public:
|
||||
DisassemblyEventArgs(std::string output)
|
||||
: m_output(output) {}
|
||||
|
||||
const std::string& getOutput() const { return m_output; }
|
||||
};
|
||||
const std::string& getOutput() const { return m_output; }
|
||||
};
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
|
||||
#include "Signal.h"
|
||||
#include "AddressEventArgs.h"
|
||||
|
||||
class Memory
|
||||
{
|
||||
private:
|
||||
std::vector<uint8_t> memory;
|
||||
std::vector<bool> locked;
|
||||
|
||||
public:
|
||||
Memory(unsigned memorySize)
|
||||
: memory(memorySize),
|
||||
locked(memorySize) {}
|
||||
|
||||
Signal<AddressEventArgs> InvalidWriteAttempt;
|
||||
Signal<AddressEventArgs> WritingByte;
|
||||
Signal<AddressEventArgs> ReadingByte;
|
||||
|
||||
void ClearMemory() {
|
||||
std::fill(memory.begin(), memory.end(), 0);
|
||||
}
|
||||
|
||||
void ClearLocking() {
|
||||
std::fill(locked.begin(), locked.end(), false);
|
||||
}
|
||||
|
||||
uint8_t GetByte(uint16_t offset) const {
|
||||
auto content = memory[offset];
|
||||
ReadingByte.fire(AddressEventArgs(offset, content));
|
||||
return content;
|
||||
}
|
||||
|
||||
void SetByte(uint16_t offset, uint8_t value) {
|
||||
AddressEventArgs e(offset, value);
|
||||
if (locked[offset]) {
|
||||
InvalidWriteAttempt.fire(e);
|
||||
} else {
|
||||
memory[offset] = value;
|
||||
WritingByte.fire(e);
|
||||
}
|
||||
}
|
||||
|
||||
void LoadRom(std::string path, uint16_t offset) {
|
||||
auto length = LoadMemory(path, offset);
|
||||
LockMemory(offset, length);
|
||||
}
|
||||
|
||||
void LoadRam(std::string path, uint16_t offset) {
|
||||
LoadMemory(path, offset);
|
||||
}
|
||||
|
||||
void LockMemory(uint16_t offset, uint16_t length) {
|
||||
for (auto i = 0; i < length; ++i)
|
||||
locked[offset + i] = true;
|
||||
}
|
||||
|
||||
uint16_t LoadMemory(std::string path, uint16_t offset) {
|
||||
std::ifstream file(path, std::ios::binary | std::ios::ate);
|
||||
auto size = (int)file.tellg();
|
||||
file.seekg(0, std::ios::beg);
|
||||
std::vector<char> buffer(size);
|
||||
file.read(&buffer[0], size);
|
||||
file.close();
|
||||
|
||||
std::copy(buffer.begin(), buffer.end(), memory.begin() + offset);
|
||||
|
||||
return (uint16_t)size;
|
||||
}
|
||||
};
|
@ -1,7 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
enum ProcessorType {
|
||||
Cpu6502,
|
||||
Cpu65SC02,
|
||||
Cpu65C02
|
||||
};
|
||||
namespace EightBit {
|
||||
enum ProcessorType {
|
||||
Cpu6502,
|
||||
Cpu65SC02,
|
||||
Cpu65C02
|
||||
};
|
||||
}
|
@ -2,14 +2,15 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
class ProfileEventArgs
|
||||
{
|
||||
private:
|
||||
std::string m_output;
|
||||
namespace EightBit {
|
||||
class ProfileEventArgs {
|
||||
private:
|
||||
std::string m_output;
|
||||
|
||||
public:
|
||||
ProfileEventArgs(std::string output)
|
||||
: m_output(output) {}
|
||||
public:
|
||||
ProfileEventArgs(std::string output)
|
||||
: m_output(output) {}
|
||||
|
||||
const std::string& getOutput() const { return m_output; }
|
||||
};
|
||||
const std::string& getOutput() const { return m_output; }
|
||||
};
|
||||
}
|
@ -3,16 +3,18 @@
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
|
||||
class ProfileLineEventArgs
|
||||
{
|
||||
private:
|
||||
std::string m_source;
|
||||
uint64_t m_cycles;
|
||||
namespace EightBit {
|
||||
class ProfileLineEventArgs
|
||||
{
|
||||
private:
|
||||
std::string m_source;
|
||||
uint64_t m_cycles;
|
||||
|
||||
public:
|
||||
ProfileLineEventArgs(std::string source, uint64_t cycles)
|
||||
: m_source(source), m_cycles(cycles) {}
|
||||
public:
|
||||
ProfileLineEventArgs(std::string source, uint64_t cycles)
|
||||
: m_source(source), m_cycles(cycles) {}
|
||||
|
||||
const std::string& getSource() const { return m_source; }
|
||||
uint64_t getCycles() const { return m_cycles; }
|
||||
};
|
||||
const std::string& getSource() const { return m_source; }
|
||||
uint64_t getCycles() const { return m_cycles; }
|
||||
};
|
||||
}
|
@ -3,19 +3,19 @@
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
|
||||
class ProfileScopeEventArgs
|
||||
{
|
||||
private:
|
||||
std::string m_scope;
|
||||
uint64_t m_cycles;
|
||||
uint64_t m_count;
|
||||
namespace EightBit {
|
||||
class ProfileScopeEventArgs {
|
||||
private:
|
||||
std::string m_scope;
|
||||
uint64_t m_cycles;
|
||||
uint64_t m_count;
|
||||
|
||||
public:
|
||||
ProfileScopeEventArgs(std::string scope, uint64_t cycles, uint64_t count)
|
||||
: m_scope(scope), m_cycles(cycles), m_count(count) {}
|
||||
|
||||
const std::string& getScope() const { return m_scope; }
|
||||
uint64_t getCycles() const { return m_cycles; }
|
||||
uint64_t getCount() const { return m_count; }
|
||||
};
|
||||
public:
|
||||
ProfileScopeEventArgs(std::string scope, uint64_t cycles, uint64_t count)
|
||||
: m_scope(scope), m_cycles(cycles), m_count(count) {}
|
||||
|
||||
const std::string& getScope() const { return m_scope; }
|
||||
uint64_t getCycles() const { return m_cycles; }
|
||||
uint64_t getCount() const { return m_count; }
|
||||
};
|
||||
}
|
@ -5,58 +5,55 @@
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
|
||||
#include <system6502.h>
|
||||
#include <EventArgs.h>
|
||||
#include <Signal.h>
|
||||
#include "EventArgs.h"
|
||||
#include "Signal.h"
|
||||
|
||||
#include "Disassembly.h"
|
||||
#include "Symbols.h"
|
||||
|
||||
#include "AddressEventArgs.h"
|
||||
#include "ProfileLineEventArgs.h"
|
||||
#include "ProfileScopeEventArgs.h"
|
||||
|
||||
class Profiler
|
||||
{
|
||||
public:
|
||||
std::array<uint64_t, 0x100> instructionCounts;
|
||||
std::array<uint64_t, 0x10000> addressProfiles;
|
||||
std::array<uint64_t, 0x10000> addressCounts;
|
||||
#include "mos6502.h"
|
||||
|
||||
std::array<std::string, 0x10000> addressScopes;
|
||||
std::map<std::string, uint64_t> scopeCycles;
|
||||
namespace EightBit {
|
||||
class Profiler {
|
||||
public:
|
||||
std::array<uint64_t, 0x100> instructionCounts;
|
||||
std::array<uint64_t, 0x10000> addressProfiles;
|
||||
std::array<uint64_t, 0x10000> addressCounts;
|
||||
|
||||
System6502& processor;
|
||||
const Disassembly& disassembler;
|
||||
const Symbols& symbols;
|
||||
std::array<std::string, 0x10000> addressScopes;
|
||||
std::map<std::string, uint64_t> scopeCycles;
|
||||
|
||||
bool countInstructions;
|
||||
bool profileAddresses;
|
||||
MOS6502& processor;
|
||||
const Disassembly& disassembler;
|
||||
const Symbols& symbols;
|
||||
|
||||
uint64_t priorCycleCount = 0;
|
||||
Profiler(MOS6502& processor, Disassembly& disassembler, Symbols& symbols);
|
||||
|
||||
Profiler(System6502& processor, Disassembly& disassembler, Symbols& symbols, bool countInstructions, bool profileAddresses);
|
||||
Signal<EventArgs> StartingOutput;
|
||||
Signal<EventArgs> FinishedOutput;
|
||||
|
||||
Signal<EventArgs> StartingOutput;
|
||||
Signal<EventArgs> FinishedOutput;
|
||||
Signal<EventArgs> StartingLineOutput;
|
||||
Signal<EventArgs> FinishedLineOutput;
|
||||
|
||||
Signal<EventArgs> StartingLineOutput;
|
||||
Signal<EventArgs> FinishedLineOutput;
|
||||
Signal<ProfileLineEventArgs> EmitLine;
|
||||
|
||||
Signal<ProfileLineEventArgs> EmitLine;
|
||||
Signal<EventArgs> StartingScopeOutput;
|
||||
Signal<EventArgs> FinishedScopeOutput;
|
||||
|
||||
Signal<EventArgs> StartingScopeOutput;
|
||||
Signal<EventArgs> FinishedScopeOutput;
|
||||
Signal<ProfileScopeEventArgs> EmitScope;
|
||||
|
||||
Signal<ProfileScopeEventArgs> EmitScope;
|
||||
void addInstruction(uint8_t instruction);
|
||||
void addAddress(uint16_t address, int cycles);
|
||||
|
||||
void Generate();
|
||||
void Generate();
|
||||
|
||||
private:
|
||||
void EmitProfileInformation();
|
||||
private:
|
||||
void EmitProfileInformation();
|
||||
|
||||
void Processor_ExecutingInstruction_ProfileAddresses(const AddressEventArgs& addressEvent);
|
||||
void Processor_ExecutingInstruction_CountInstructions(const AddressEventArgs& addressEvent);
|
||||
void Processor_ExecutedInstruction_ProfileAddresses(const AddressEventArgs& addressEvent);
|
||||
|
||||
void BuildAddressScopes();
|
||||
};
|
||||
void BuildAddressScopes();
|
||||
};
|
||||
}
|
@ -3,80 +3,82 @@
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
|
||||
struct StatusFlags {
|
||||
namespace EightBit {
|
||||
struct StatusFlags {
|
||||
|
||||
bool negative;
|
||||
bool overflow;
|
||||
bool reserved;
|
||||
bool brk;
|
||||
bool decimal;
|
||||
bool interrupt;
|
||||
bool zero;
|
||||
bool carry;
|
||||
bool negative;
|
||||
bool overflow;
|
||||
bool reserved;
|
||||
bool brk;
|
||||
bool decimal;
|
||||
bool interrupt;
|
||||
bool zero;
|
||||
bool carry;
|
||||
|
||||
enum StatusBits {
|
||||
Negative = 0x80, // N
|
||||
Overflow = 0x40, // V
|
||||
Reserved = 0x20, // ignored
|
||||
Break = 0x10, // B
|
||||
Decimal = 0x08, // D (use BCD for arithmetic)
|
||||
Interrupt = 0x04, // I (IRQ disable)
|
||||
Zero = 0x02, // Z
|
||||
Carry = 0x01, // C
|
||||
enum StatusBits {
|
||||
Negative = 0x80, // N
|
||||
Overflow = 0x40, // V
|
||||
Reserved = 0x20, // ignored
|
||||
Break = 0x10, // B
|
||||
Decimal = 0x08, // D (use BCD for arithmetic)
|
||||
Interrupt = 0x04, // I (IRQ disable)
|
||||
Zero = 0x02, // Z
|
||||
Carry = 0x01, // C
|
||||
};
|
||||
|
||||
StatusFlags(uint8_t value) {
|
||||
negative = (value & StatusBits::Negative) != 0;
|
||||
overflow = (value & StatusBits::Overflow) != 0;
|
||||
reserved = (value & StatusBits::Reserved) != 0;
|
||||
brk = (value & StatusBits::Break) != 0;
|
||||
decimal = (value & StatusBits::Decimal) != 0;
|
||||
interrupt = (value & StatusBits::Interrupt) != 0;
|
||||
zero = (value & StatusBits::Zero) != 0;
|
||||
carry = (value & StatusBits::Carry) != 0;
|
||||
}
|
||||
|
||||
operator uint8_t() const {
|
||||
|
||||
uint8_t flags = 0;
|
||||
|
||||
if (negative)
|
||||
flags |= StatusBits::Negative;
|
||||
|
||||
if (overflow)
|
||||
flags |= StatusBits::Overflow;
|
||||
|
||||
if (reserved)
|
||||
flags |= StatusBits::Reserved;
|
||||
|
||||
if (brk)
|
||||
flags |= StatusBits::Break;
|
||||
|
||||
if (decimal)
|
||||
flags |= StatusBits::Decimal;
|
||||
|
||||
if (interrupt)
|
||||
flags |= StatusBits::Interrupt;
|
||||
|
||||
if (zero)
|
||||
flags |= StatusBits::Zero;
|
||||
|
||||
if (carry)
|
||||
flags |= StatusBits::Carry;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
operator std::string() const {
|
||||
std::string returned;
|
||||
returned += negative ? "N" : "-";
|
||||
returned += overflow ? "O" : "-";
|
||||
returned += reserved ? "R" : "-";
|
||||
returned += brk ? "B" : "-";
|
||||
returned += decimal ? "D" : "-";
|
||||
returned += interrupt ? "I" : "-";
|
||||
returned += zero ? "Z" : "-";
|
||||
returned += carry ? "C" : "-";
|
||||
return returned;
|
||||
}
|
||||
};
|
||||
|
||||
StatusFlags(uint8_t value) {
|
||||
negative = (value & StatusBits::Negative) != 0;
|
||||
overflow = (value & StatusBits::Overflow) != 0;
|
||||
reserved = (value & StatusBits::Reserved) != 0;
|
||||
brk = (value & StatusBits::Break) != 0;
|
||||
decimal = (value & StatusBits::Decimal) != 0;
|
||||
interrupt = (value & StatusBits::Interrupt) != 0;
|
||||
zero = (value & StatusBits::Zero) != 0;
|
||||
carry = (value & StatusBits::Carry) != 0;
|
||||
}
|
||||
|
||||
operator uint8_t() const {
|
||||
|
||||
uint8_t flags = 0;
|
||||
|
||||
if (negative)
|
||||
flags |= StatusBits::Negative;
|
||||
|
||||
if (overflow)
|
||||
flags |= StatusBits::Overflow;
|
||||
|
||||
if (reserved)
|
||||
flags |= StatusBits::Reserved;
|
||||
|
||||
if (brk)
|
||||
flags |= StatusBits::Break;
|
||||
|
||||
if (decimal)
|
||||
flags |= StatusBits::Decimal;
|
||||
|
||||
if (interrupt)
|
||||
flags |= StatusBits::Interrupt;
|
||||
|
||||
if (zero)
|
||||
flags |= StatusBits::Zero;
|
||||
|
||||
if (carry)
|
||||
flags |= StatusBits::Carry;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
operator std::string() const {
|
||||
std::string returned;
|
||||
returned += negative ? "N" : "-";
|
||||
returned += overflow ? "O" : "-";
|
||||
returned += reserved ? "R" : "-";
|
||||
returned += brk ? "B" : "-";
|
||||
returned += decimal ? "D" : "-";
|
||||
returned += interrupt ? "I" : "-";
|
||||
returned += zero ? "Z" : "-";
|
||||
returned += carry ? "C" : "-";
|
||||
return returned;
|
||||
}
|
||||
};
|
||||
}
|
@ -5,32 +5,33 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
class Symbols
|
||||
{
|
||||
public:
|
||||
Symbols(std::string path);
|
||||
namespace EightBit {
|
||||
class Symbols {
|
||||
public:
|
||||
Symbols(std::string path);
|
||||
|
||||
const std::map<uint16_t, std::string>& getLabels() const { return labels; }
|
||||
const std::map<uint16_t, std::string>& getConstants() const { return constants; }
|
||||
const std::map<std::string, uint16_t>& getScopes() const { return scopes; }
|
||||
const std::map<std::string, uint64_t>& getAddresses() const { return addresses; }
|
||||
const std::map<uint16_t, std::string>& getLabels() const { return labels; }
|
||||
const std::map<uint16_t, std::string>& getConstants() const { return constants; }
|
||||
const std::map<std::string, uint16_t>& getScopes() const { return scopes; }
|
||||
const std::map<std::string, uint64_t>& getAddresses() const { return addresses; }
|
||||
|
||||
private:
|
||||
void AssignScopes();
|
||||
void AssignSymbols();
|
||||
private:
|
||||
void AssignScopes();
|
||||
void AssignSymbols();
|
||||
|
||||
void Parse(std::string path);
|
||||
void Parse(std::string path);
|
||||
|
||||
std::map<uint16_t, std::string> labels;
|
||||
std::map<uint16_t, std::string> constants;
|
||||
std::map<std::string, uint16_t> scopes;
|
||||
std::map<std::string, uint64_t> addresses;
|
||||
std::map<uint16_t, std::string> labels;
|
||||
std::map<uint16_t, std::string> constants;
|
||||
std::map<std::string, uint16_t> scopes;
|
||||
std::map<std::string, uint64_t> addresses;
|
||||
|
||||
struct kv_pair_t {
|
||||
std::map<std::string, std::string> element;
|
||||
struct kv_pair_t {
|
||||
std::map<std::string, std::string> element;
|
||||
};
|
||||
|
||||
std::vector<std::string> split(const std::string& input, const std::vector<std::string>& delimiters);
|
||||
|
||||
std::map<std::string, std::map<std::string, kv_pair_t>> parsed;
|
||||
};
|
||||
|
||||
std::vector<std::string> split(const std::string& input, const std::vector<std::string>& delimiters);
|
||||
|
||||
std::map<std::string, std::map<std::string, kv_pair_t>> parsed;
|
||||
};
|
||||
}
|
@ -8,457 +8,462 @@
|
||||
#include "ProcessorType.h"
|
||||
#include "StatusFlags.h"
|
||||
#include "AddressingMode.h"
|
||||
#include "Signal.h"
|
||||
|
||||
class MOS6502 {
|
||||
public:
|
||||
typedef std::function<void()> instruction_t;
|
||||
namespace EightBit {
|
||||
class MOS6502 {
|
||||
public:
|
||||
typedef std::function<void()> instruction_t;
|
||||
|
||||
struct Instruction {
|
||||
instruction_t vector = nullptr;
|
||||
uint64_t count = 0;
|
||||
AddressingMode mode = AddressingMode::Illegal;
|
||||
std::string display = "";
|
||||
struct Instruction {
|
||||
instruction_t vector = nullptr;
|
||||
uint64_t count = 0;
|
||||
AddressingMode mode = AddressingMode::Illegal;
|
||||
std::string display = "";
|
||||
};
|
||||
|
||||
MOS6502(ProcessorType level);
|
||||
|
||||
Signal<MOS6502> ExecutingInstruction;
|
||||
|
||||
ProcessorType getLevel() const { return level; }
|
||||
uint64_t getCycles() const { return cycles; }
|
||||
|
||||
bool getProceed() const { return proceed; }
|
||||
void setProceed(bool value) { proceed = value; }
|
||||
|
||||
uint16_t getPC() const { return pc; }
|
||||
uint8_t getX() const { return x; }
|
||||
uint8_t getY() const { return y; }
|
||||
uint8_t getA() const { return a; }
|
||||
uint8_t getS() const { return s; }
|
||||
|
||||
const StatusFlags& getP() const { return p; }
|
||||
|
||||
const Instruction& getInstruction(uint8_t code) const {
|
||||
return instructions[code];
|
||||
}
|
||||
|
||||
virtual void Initialise();
|
||||
|
||||
virtual void Start(uint16_t address);
|
||||
virtual void Run();
|
||||
virtual void Step();
|
||||
|
||||
virtual void Reset();
|
||||
|
||||
virtual void TriggerIRQ();
|
||||
virtual void TriggerNMI();
|
||||
|
||||
uint16_t GetWord(uint16_t offset) const;
|
||||
|
||||
virtual uint8_t GetByte(uint16_t offset) const = 0;
|
||||
virtual void SetByte(uint16_t offset, uint8_t value) = 0;
|
||||
|
||||
protected:
|
||||
virtual void Interrupt(uint16_t vector);
|
||||
|
||||
virtual void Execute(uint8_t cell);
|
||||
|
||||
void ___();
|
||||
|
||||
void ResetRegisters();
|
||||
|
||||
private:
|
||||
static Instruction INS(instruction_t method, uint64_t cycles, AddressingMode addressing, std::string display);
|
||||
|
||||
static uint8_t LowNybble(uint8_t value);
|
||||
static uint8_t HighNybble(uint8_t value);
|
||||
static uint8_t PromoteNybble(uint8_t value);
|
||||
static uint8_t DemoteNybble(uint8_t value);
|
||||
static uint8_t LowByte(uint16_t value);
|
||||
static uint8_t HighByte(uint16_t value);
|
||||
static uint16_t MakeWord(uint8_t low, uint8_t high);
|
||||
|
||||
void Install6502Instructions();
|
||||
void Install65sc02Instructions();
|
||||
void Install65c02Instructions();
|
||||
|
||||
void InstallInstructionSet(std::array<Instruction, 0x100> basis);
|
||||
void OverlayInstructionSet(std::array<Instruction, 0x100> overlay);
|
||||
void OverlayInstructionSet(std::array<Instruction, 0x100> overlay, bool includeIllegal);
|
||||
|
||||
bool UpdateZeroFlag(uint8_t datum);
|
||||
bool UpdateNegativeFlag(int8_t datum);
|
||||
void UpdateZeroNegativeFlags(uint8_t datum);
|
||||
|
||||
void PushByte(uint8_t value);
|
||||
uint8_t PopByte();
|
||||
void PushWord(uint16_t value);
|
||||
uint16_t PopWord();
|
||||
|
||||
uint8_t FetchByte();
|
||||
uint16_t FetchWord();
|
||||
|
||||
uint16_t Address_ZeroPage();
|
||||
uint16_t Address_ZeroPageX();
|
||||
uint16_t Address_ZeroPageY();
|
||||
uint16_t Address_IndexedIndirectX();
|
||||
uint16_t Address_IndexedIndirectY_Read();
|
||||
uint16_t Address_IndexedIndirectY_Write();
|
||||
uint16_t Address_Absolute();
|
||||
uint16_t Address_AbsoluteXIndirect();
|
||||
uint16_t Address_AbsoluteX_Read();
|
||||
uint16_t Address_AbsoluteX_Write();
|
||||
uint16_t Address_AbsoluteY_Read();
|
||||
uint16_t Address_AbsoluteY_Write();
|
||||
uint16_t Address_ZeroPageIndirect();
|
||||
|
||||
uint8_t ReadByte_Immediate();
|
||||
int8_t ReadByte_ImmediateDisplacement();
|
||||
uint8_t ReadByte_ZeroPage();
|
||||
uint8_t ReadByte_ZeroPageX();
|
||||
uint8_t ReadByte_ZeroPageY();
|
||||
uint8_t ReadByte_Absolute();
|
||||
uint8_t ReadByte_AbsoluteX();
|
||||
uint8_t ReadByte_AbsoluteY();
|
||||
uint8_t ReadByte_IndexedIndirectX();
|
||||
uint8_t ReadByte_IndirectIndexedY();
|
||||
uint8_t ReadByte_ZeroPageIndirect();
|
||||
|
||||
void WriteByte_ZeroPage(uint8_t value);
|
||||
void WriteByte_Absolute(uint8_t value);
|
||||
void WriteByte_AbsoluteX(uint8_t value);
|
||||
void WriteByte_AbsoluteY(uint8_t value);
|
||||
void WriteByte_ZeroPageX(uint8_t value);
|
||||
void WriteByte_ZeroPageY(uint8_t value);
|
||||
void WriteByte_IndirectIndexedY(uint8_t value);
|
||||
void WriteByte_IndexedIndirectX(uint8_t value);
|
||||
void WriteByte_ZeroPageIndirect(uint8_t value);
|
||||
|
||||
void DEC(uint16_t offset);
|
||||
|
||||
uint8_t ROR(uint8_t data);
|
||||
void ROR(uint16_t offset);
|
||||
|
||||
uint8_t LSR(uint8_t data);
|
||||
void LSR(uint16_t offset);
|
||||
|
||||
void BIT_immediate(uint8_t data);
|
||||
void BIT(uint8_t data);
|
||||
|
||||
void TSB(uint16_t address);
|
||||
void TRB(uint16_t address);
|
||||
|
||||
void INC(uint16_t offset);
|
||||
|
||||
void ROL(uint16_t offset);
|
||||
uint8_t ROL(uint8_t data);
|
||||
|
||||
void ASL(uint16_t offset);
|
||||
uint8_t ASL(uint8_t data);
|
||||
|
||||
void ORA(uint8_t data);
|
||||
|
||||
void AND(uint8_t data);
|
||||
|
||||
void SBC(uint8_t data);
|
||||
void SBC_b(uint8_t data);
|
||||
void SBC_d(uint8_t data);
|
||||
|
||||
void EOR(uint8_t data);
|
||||
|
||||
void CPX(uint8_t data);
|
||||
void CPY(uint8_t data);
|
||||
void CMP(uint8_t data);
|
||||
void CMP(uint8_t first, uint8_t second);
|
||||
|
||||
void LDA(uint8_t data);
|
||||
void LDY(uint8_t data);
|
||||
void LDX(uint8_t data);
|
||||
|
||||
void ADC(uint8_t data);
|
||||
void ADC_b(uint8_t data);
|
||||
void ADC_d(uint8_t data);
|
||||
|
||||
void RMB(uint16_t address, uint8_t flag);
|
||||
void SMB(uint16_t address, uint8_t flag);
|
||||
|
||||
void Branch(int8_t displacement);
|
||||
void Branch();
|
||||
void Branch(bool flag);
|
||||
void BitBranch_Clear(uint8_t check);
|
||||
void BitBranch_Set(uint8_t check);
|
||||
|
||||
void NOP_imp();
|
||||
void NOP2_imp();
|
||||
void NOP3_imp();
|
||||
|
||||
void ORA_xind();
|
||||
void ORA_zp();
|
||||
void ORA_imm();
|
||||
void ORA_abs();
|
||||
void ORA_absx();
|
||||
void ORA_absy();
|
||||
void ORA_zpx();
|
||||
void ORA_indy();
|
||||
void ORA_zpind();
|
||||
|
||||
void AND_zpx();
|
||||
void AND_indy();
|
||||
void AND_zp();
|
||||
void AND_absx();
|
||||
void AND_absy();
|
||||
void AND_imm();
|
||||
void AND_xind();
|
||||
void AND_abs();
|
||||
void AND_zpind();
|
||||
|
||||
void EOR_absx();
|
||||
void EOR_absy();
|
||||
void EOR_zpx();
|
||||
void EOR_indy();
|
||||
void EOR_abs();
|
||||
void EOR_imm();
|
||||
void EOR_zp();
|
||||
void EOR_xind();
|
||||
void EOR_zpind();
|
||||
|
||||
void LDA_absx();
|
||||
void LDA_absy();
|
||||
void LDA_zpx();
|
||||
void LDA_indy();
|
||||
void LDA_abs();
|
||||
void LDA_imm();
|
||||
void LDA_zp();
|
||||
void LDA_xind();
|
||||
void LDA_zpind();
|
||||
|
||||
void LDX_imm();
|
||||
void LDX_zp();
|
||||
void LDX_abs();
|
||||
void LDX_zpy();
|
||||
void LDX_absy();
|
||||
|
||||
void LDY_imm();
|
||||
void LDY_zp();
|
||||
void LDY_abs();
|
||||
void LDY_zpx();
|
||||
void LDY_absx();
|
||||
|
||||
void CMP_absx();
|
||||
void CMP_absy();
|
||||
void CMP_zpx();
|
||||
void CMP_indy();
|
||||
void CMP_abs();
|
||||
void CMP_imm();
|
||||
void CMP_zp();
|
||||
void CMP_xind();
|
||||
void CMP_zpind();
|
||||
|
||||
void CPX_abs();
|
||||
void CPX_zp();
|
||||
void CPX_imm();
|
||||
|
||||
void CPY_imm();
|
||||
void CPY_zp();
|
||||
void CPY_abs();
|
||||
|
||||
void ADC_zp();
|
||||
void ADC_xind();
|
||||
void ADC_imm();
|
||||
void ADC_abs();
|
||||
void ADC_zpx();
|
||||
void ADC_indy();
|
||||
void ADC_absx();
|
||||
void ADC_absy();
|
||||
void ADC_zpind();
|
||||
|
||||
void SBC_xind();
|
||||
void SBC_zp();
|
||||
void SBC_imm();
|
||||
void SBC_abs();
|
||||
void SBC_zpx();
|
||||
void SBC_indy();
|
||||
void SBC_absx();
|
||||
void SBC_absy();
|
||||
void SBC_zpind();
|
||||
|
||||
void BIT_imm();
|
||||
void BIT_zp();
|
||||
void BIT_zpx();
|
||||
void BIT_abs();
|
||||
void BIT_absx();
|
||||
|
||||
void DEC_a();
|
||||
void DEC_absx();
|
||||
void DEC_zpx();
|
||||
void DEC_abs();
|
||||
void DEC_zp();
|
||||
|
||||
void DEX_imp();
|
||||
void DEY_imp();
|
||||
|
||||
void INC_a();
|
||||
void INC_zp();
|
||||
void INC_absx();
|
||||
void INC_zpx();
|
||||
void INC_abs();
|
||||
|
||||
void INX_imp();
|
||||
void INY_imp();
|
||||
|
||||
void STX_zpy();
|
||||
void STX_abs();
|
||||
void STX_zp();
|
||||
|
||||
void STY_zpx();
|
||||
void STY_abs();
|
||||
void STY_zp();
|
||||
|
||||
void STA_absx();
|
||||
void STA_absy();
|
||||
void STA_zpx();
|
||||
void STA_indy();
|
||||
void STA_abs();
|
||||
void STA_zp();
|
||||
void STA_xind();
|
||||
void STA_zpind();
|
||||
|
||||
void STZ_zp();
|
||||
void STZ_zpx();
|
||||
void STZ_abs();
|
||||
void STZ_absx();
|
||||
|
||||
void TSX_imp();
|
||||
void TAX_imp();
|
||||
void TAY_imp();
|
||||
void TXS_imp();
|
||||
void TYA_imp();
|
||||
void TXA_imp();
|
||||
|
||||
void PHP_imp();
|
||||
void PLP_imp();
|
||||
void PLA_imp();
|
||||
void PHA_imp();
|
||||
void PHX_imp();
|
||||
void PHY_imp();
|
||||
void PLX_imp();
|
||||
void PLY_imp();
|
||||
|
||||
void ASL_a();
|
||||
void ASL_zp();
|
||||
void ASL_abs();
|
||||
void ASL_absx();
|
||||
void ASL_zpx();
|
||||
|
||||
void LSR_absx();
|
||||
void LSR_zpx();
|
||||
void LSR_abs();
|
||||
void LSR_a();
|
||||
void LSR_zp();
|
||||
|
||||
void ROL_absx();
|
||||
void ROL_zpx();
|
||||
void ROL_abs();
|
||||
void ROL_a();
|
||||
void ROL_zp();
|
||||
|
||||
void ROR_absx();
|
||||
void ROR_zpx();
|
||||
void ROR_abs();
|
||||
void ROR_a();
|
||||
void ROR_zp();
|
||||
|
||||
void TSB_zp();
|
||||
void TSB_abs();
|
||||
|
||||
void TRB_zp();
|
||||
void TRB_abs();
|
||||
|
||||
void RMB0_zp();
|
||||
void RMB1_zp();
|
||||
void RMB2_zp();
|
||||
void RMB3_zp();
|
||||
void RMB4_zp();
|
||||
void RMB5_zp();
|
||||
void RMB6_zp();
|
||||
void RMB7_zp();
|
||||
|
||||
void SMB0_zp();
|
||||
void SMB1_zp();
|
||||
void SMB2_zp();
|
||||
void SMB3_zp();
|
||||
void SMB4_zp();
|
||||
void SMB5_zp();
|
||||
void SMB6_zp();
|
||||
void SMB7_zp();
|
||||
|
||||
void JSR_abs();
|
||||
void RTI_imp();
|
||||
void RTS_imp();
|
||||
void JMP_abs();
|
||||
void JMP_ind();
|
||||
void JMP_absxind();
|
||||
void BRK_imp();
|
||||
|
||||
void WAI_imp();
|
||||
void STP_imp();
|
||||
|
||||
void SED_imp();
|
||||
void CLD_imp();
|
||||
void CLV_imp();
|
||||
void SEI_imp();
|
||||
void CLI_imp();
|
||||
void CLC_imp();
|
||||
void SEC_imp();
|
||||
|
||||
void BMI_rel();
|
||||
void BPL_rel();
|
||||
void BVC_rel();
|
||||
void BVS_rel();
|
||||
void BCC_rel();
|
||||
void BCS_rel();
|
||||
void BNE_rel();
|
||||
void BEQ_rel();
|
||||
void BRA_rel();
|
||||
|
||||
void BBR0_zprel();
|
||||
void BBR1_zprel();
|
||||
void BBR2_zprel();
|
||||
void BBR3_zprel();
|
||||
void BBR4_zprel();
|
||||
void BBR5_zprel();
|
||||
void BBR6_zprel();
|
||||
void BBR7_zprel();
|
||||
|
||||
void BBS0_zprel();
|
||||
void BBS1_zprel();
|
||||
void BBS2_zprel();
|
||||
void BBS3_zprel();
|
||||
void BBS4_zprel();
|
||||
void BBS5_zprel();
|
||||
void BBS6_zprel();
|
||||
void BBS7_zprel();
|
||||
|
||||
const uint16_t PageOne = 0x100;
|
||||
const uint16_t IRQvector = 0xfffe;
|
||||
const uint16_t RSTvector = 0xfffc;
|
||||
const uint16_t NMIvector = 0xfffa;
|
||||
|
||||
uint16_t pc; // program counter
|
||||
uint8_t x; // index register X
|
||||
uint8_t y; // index register Y
|
||||
uint8_t a; // accumulator
|
||||
uint8_t s; // stack pointer
|
||||
|
||||
StatusFlags p = 0; // processor status
|
||||
|
||||
uint64_t cycles;
|
||||
|
||||
bool proceed = true;
|
||||
|
||||
std::array<Instruction, 0x100> instructions;
|
||||
|
||||
ProcessorType level;
|
||||
|
||||
std::array<Instruction, 0x100> overlay6502;
|
||||
std::array<Instruction, 0x100> overlay65sc02;
|
||||
std::array<Instruction, 0x100> overlay65c02;
|
||||
};
|
||||
|
||||
MOS6502(ProcessorType level);
|
||||
|
||||
ProcessorType getLevel() const { return level; }
|
||||
uint64_t getCycles() const { return cycles; }
|
||||
|
||||
bool getProceed() const { return proceed; }
|
||||
void setProceed(bool value) { proceed = value; }
|
||||
|
||||
uint16_t getPC() const { return pc; }
|
||||
uint8_t getX() const { return x; }
|
||||
uint8_t getY() const { return y; }
|
||||
uint8_t getA() const { return a; }
|
||||
uint8_t getS() const { return s; }
|
||||
|
||||
const StatusFlags& getP() const { return p; }
|
||||
|
||||
const Instruction& getInstruction(uint8_t code) const {
|
||||
return instructions[code];
|
||||
}
|
||||
|
||||
virtual void Initialise();
|
||||
|
||||
virtual void Start(uint16_t address);
|
||||
virtual void Run();
|
||||
virtual void Step();
|
||||
|
||||
virtual void Reset();
|
||||
|
||||
virtual void TriggerIRQ();
|
||||
virtual void TriggerNMI();
|
||||
|
||||
uint16_t GetWord(uint16_t offset) const;
|
||||
|
||||
virtual uint8_t GetByte(uint16_t offset) const = 0;
|
||||
virtual void SetByte(uint16_t offset, uint8_t value) = 0;
|
||||
|
||||
protected:
|
||||
virtual void Interrupt(uint16_t vector);
|
||||
|
||||
virtual void Execute(uint8_t cell);
|
||||
|
||||
void ___();
|
||||
|
||||
void ResetRegisters();
|
||||
|
||||
private:
|
||||
static Instruction INS(instruction_t method, uint64_t cycles, AddressingMode addressing, std::string display);
|
||||
|
||||
static uint8_t LowNybble(uint8_t value);
|
||||
static uint8_t HighNybble(uint8_t value);
|
||||
static uint8_t PromoteNybble(uint8_t value);
|
||||
static uint8_t DemoteNybble(uint8_t value);
|
||||
static uint8_t LowByte(uint16_t value);
|
||||
static uint8_t HighByte(uint16_t value);
|
||||
static uint16_t MakeWord(uint8_t low, uint8_t high);
|
||||
|
||||
void Install6502Instructions();
|
||||
void Install65sc02Instructions();
|
||||
void Install65c02Instructions();
|
||||
|
||||
void InstallInstructionSet(std::array<Instruction, 0x100> basis);
|
||||
void OverlayInstructionSet(std::array<Instruction, 0x100> overlay);
|
||||
void OverlayInstructionSet(std::array<Instruction, 0x100> overlay, bool includeIllegal);
|
||||
|
||||
bool UpdateZeroFlag(uint8_t datum);
|
||||
bool UpdateNegativeFlag(int8_t datum);
|
||||
void UpdateZeroNegativeFlags(uint8_t datum);
|
||||
|
||||
void PushByte(uint8_t value);
|
||||
uint8_t PopByte();
|
||||
void PushWord(uint16_t value);
|
||||
uint16_t PopWord();
|
||||
|
||||
uint8_t FetchByte();
|
||||
uint16_t FetchWord();
|
||||
|
||||
uint16_t Address_ZeroPage();
|
||||
uint16_t Address_ZeroPageX();
|
||||
uint16_t Address_ZeroPageY();
|
||||
uint16_t Address_IndexedIndirectX();
|
||||
uint16_t Address_IndexedIndirectY_Read();
|
||||
uint16_t Address_IndexedIndirectY_Write();
|
||||
uint16_t Address_Absolute();
|
||||
uint16_t Address_AbsoluteXIndirect();
|
||||
uint16_t Address_AbsoluteX_Read();
|
||||
uint16_t Address_AbsoluteX_Write();
|
||||
uint16_t Address_AbsoluteY_Read();
|
||||
uint16_t Address_AbsoluteY_Write();
|
||||
uint16_t Address_ZeroPageIndirect();
|
||||
|
||||
uint8_t ReadByte_Immediate();
|
||||
int8_t ReadByte_ImmediateDisplacement();
|
||||
uint8_t ReadByte_ZeroPage();
|
||||
uint8_t ReadByte_ZeroPageX();
|
||||
uint8_t ReadByte_ZeroPageY();
|
||||
uint8_t ReadByte_Absolute();
|
||||
uint8_t ReadByte_AbsoluteX();
|
||||
uint8_t ReadByte_AbsoluteY();
|
||||
uint8_t ReadByte_IndexedIndirectX();
|
||||
uint8_t ReadByte_IndirectIndexedY();
|
||||
uint8_t ReadByte_ZeroPageIndirect();
|
||||
|
||||
void WriteByte_ZeroPage(uint8_t value);
|
||||
void WriteByte_Absolute(uint8_t value);
|
||||
void WriteByte_AbsoluteX(uint8_t value);
|
||||
void WriteByte_AbsoluteY(uint8_t value);
|
||||
void WriteByte_ZeroPageX(uint8_t value);
|
||||
void WriteByte_ZeroPageY(uint8_t value);
|
||||
void WriteByte_IndirectIndexedY(uint8_t value);
|
||||
void WriteByte_IndexedIndirectX(uint8_t value);
|
||||
void WriteByte_ZeroPageIndirect(uint8_t value);
|
||||
|
||||
void DEC(uint16_t offset);
|
||||
|
||||
uint8_t ROR(uint8_t data);
|
||||
void ROR(uint16_t offset);
|
||||
|
||||
uint8_t LSR(uint8_t data);
|
||||
void LSR(uint16_t offset);
|
||||
|
||||
void BIT_immediate(uint8_t data);
|
||||
void BIT(uint8_t data);
|
||||
|
||||
void TSB(uint16_t address);
|
||||
void TRB(uint16_t address);
|
||||
|
||||
void INC(uint16_t offset);
|
||||
|
||||
void ROL(uint16_t offset);
|
||||
uint8_t ROL(uint8_t data);
|
||||
|
||||
void ASL(uint16_t offset);
|
||||
uint8_t ASL(uint8_t data);
|
||||
|
||||
void ORA(uint8_t data);
|
||||
|
||||
void AND(uint8_t data);
|
||||
|
||||
void SBC(uint8_t data);
|
||||
void SBC_b(uint8_t data);
|
||||
void SBC_d(uint8_t data);
|
||||
|
||||
void EOR(uint8_t data);
|
||||
|
||||
void CPX(uint8_t data);
|
||||
void CPY(uint8_t data);
|
||||
void CMP(uint8_t data);
|
||||
void CMP(uint8_t first, uint8_t second);
|
||||
|
||||
void LDA(uint8_t data);
|
||||
void LDY(uint8_t data);
|
||||
void LDX(uint8_t data);
|
||||
|
||||
void ADC(uint8_t data);
|
||||
void ADC_b(uint8_t data);
|
||||
void ADC_d(uint8_t data);
|
||||
|
||||
void RMB(uint16_t address, uint8_t flag);
|
||||
void SMB(uint16_t address, uint8_t flag);
|
||||
|
||||
void Branch(int8_t displacement);
|
||||
void Branch();
|
||||
void Branch(bool flag);
|
||||
void BitBranch_Clear(uint8_t check);
|
||||
void BitBranch_Set(uint8_t check);
|
||||
|
||||
void NOP_imp();
|
||||
void NOP2_imp();
|
||||
void NOP3_imp();
|
||||
|
||||
void ORA_xind();
|
||||
void ORA_zp();
|
||||
void ORA_imm();
|
||||
void ORA_abs();
|
||||
void ORA_absx();
|
||||
void ORA_absy();
|
||||
void ORA_zpx();
|
||||
void ORA_indy();
|
||||
void ORA_zpind();
|
||||
|
||||
void AND_zpx();
|
||||
void AND_indy();
|
||||
void AND_zp();
|
||||
void AND_absx();
|
||||
void AND_absy();
|
||||
void AND_imm();
|
||||
void AND_xind();
|
||||
void AND_abs();
|
||||
void AND_zpind();
|
||||
|
||||
void EOR_absx();
|
||||
void EOR_absy();
|
||||
void EOR_zpx();
|
||||
void EOR_indy();
|
||||
void EOR_abs();
|
||||
void EOR_imm();
|
||||
void EOR_zp();
|
||||
void EOR_xind();
|
||||
void EOR_zpind();
|
||||
|
||||
void LDA_absx();
|
||||
void LDA_absy();
|
||||
void LDA_zpx();
|
||||
void LDA_indy();
|
||||
void LDA_abs();
|
||||
void LDA_imm();
|
||||
void LDA_zp();
|
||||
void LDA_xind();
|
||||
void LDA_zpind();
|
||||
|
||||
void LDX_imm();
|
||||
void LDX_zp();
|
||||
void LDX_abs();
|
||||
void LDX_zpy();
|
||||
void LDX_absy();
|
||||
|
||||
void LDY_imm();
|
||||
void LDY_zp();
|
||||
void LDY_abs();
|
||||
void LDY_zpx();
|
||||
void LDY_absx();
|
||||
|
||||
void CMP_absx();
|
||||
void CMP_absy();
|
||||
void CMP_zpx();
|
||||
void CMP_indy();
|
||||
void CMP_abs();
|
||||
void CMP_imm();
|
||||
void CMP_zp();
|
||||
void CMP_xind();
|
||||
void CMP_zpind();
|
||||
|
||||
void CPX_abs();
|
||||
void CPX_zp();
|
||||
void CPX_imm();
|
||||
|
||||
void CPY_imm();
|
||||
void CPY_zp();
|
||||
void CPY_abs();
|
||||
|
||||
void ADC_zp();
|
||||
void ADC_xind();
|
||||
void ADC_imm();
|
||||
void ADC_abs();
|
||||
void ADC_zpx();
|
||||
void ADC_indy();
|
||||
void ADC_absx();
|
||||
void ADC_absy();
|
||||
void ADC_zpind();
|
||||
|
||||
void SBC_xind();
|
||||
void SBC_zp();
|
||||
void SBC_imm();
|
||||
void SBC_abs();
|
||||
void SBC_zpx();
|
||||
void SBC_indy();
|
||||
void SBC_absx();
|
||||
void SBC_absy();
|
||||
void SBC_zpind();
|
||||
|
||||
void BIT_imm();
|
||||
void BIT_zp();
|
||||
void BIT_zpx();
|
||||
void BIT_abs();
|
||||
void BIT_absx();
|
||||
|
||||
void DEC_a();
|
||||
void DEC_absx();
|
||||
void DEC_zpx();
|
||||
void DEC_abs();
|
||||
void DEC_zp();
|
||||
|
||||
void DEX_imp();
|
||||
void DEY_imp();
|
||||
|
||||
void INC_a();
|
||||
void INC_zp();
|
||||
void INC_absx();
|
||||
void INC_zpx();
|
||||
void INC_abs();
|
||||
|
||||
void INX_imp();
|
||||
void INY_imp();
|
||||
|
||||
void STX_zpy();
|
||||
void STX_abs();
|
||||
void STX_zp();
|
||||
|
||||
void STY_zpx();
|
||||
void STY_abs();
|
||||
void STY_zp();
|
||||
|
||||
void STA_absx();
|
||||
void STA_absy();
|
||||
void STA_zpx();
|
||||
void STA_indy();
|
||||
void STA_abs();
|
||||
void STA_zp();
|
||||
void STA_xind();
|
||||
void STA_zpind();
|
||||
|
||||
void STZ_zp();
|
||||
void STZ_zpx();
|
||||
void STZ_abs();
|
||||
void STZ_absx();
|
||||
|
||||
void TSX_imp();
|
||||
void TAX_imp();
|
||||
void TAY_imp();
|
||||
void TXS_imp();
|
||||
void TYA_imp();
|
||||
void TXA_imp();
|
||||
|
||||
void PHP_imp();
|
||||
void PLP_imp();
|
||||
void PLA_imp();
|
||||
void PHA_imp();
|
||||
void PHX_imp();
|
||||
void PHY_imp();
|
||||
void PLX_imp();
|
||||
void PLY_imp();
|
||||
|
||||
void ASL_a();
|
||||
void ASL_zp();
|
||||
void ASL_abs();
|
||||
void ASL_absx();
|
||||
void ASL_zpx();
|
||||
|
||||
void LSR_absx();
|
||||
void LSR_zpx();
|
||||
void LSR_abs();
|
||||
void LSR_a();
|
||||
void LSR_zp();
|
||||
|
||||
void ROL_absx();
|
||||
void ROL_zpx();
|
||||
void ROL_abs();
|
||||
void ROL_a();
|
||||
void ROL_zp();
|
||||
|
||||
void ROR_absx();
|
||||
void ROR_zpx();
|
||||
void ROR_abs();
|
||||
void ROR_a();
|
||||
void ROR_zp();
|
||||
|
||||
void TSB_zp();
|
||||
void TSB_abs();
|
||||
|
||||
void TRB_zp();
|
||||
void TRB_abs();
|
||||
|
||||
void RMB0_zp();
|
||||
void RMB1_zp();
|
||||
void RMB2_zp();
|
||||
void RMB3_zp();
|
||||
void RMB4_zp();
|
||||
void RMB5_zp();
|
||||
void RMB6_zp();
|
||||
void RMB7_zp();
|
||||
|
||||
void SMB0_zp();
|
||||
void SMB1_zp();
|
||||
void SMB2_zp();
|
||||
void SMB3_zp();
|
||||
void SMB4_zp();
|
||||
void SMB5_zp();
|
||||
void SMB6_zp();
|
||||
void SMB7_zp();
|
||||
|
||||
void JSR_abs();
|
||||
void RTI_imp();
|
||||
void RTS_imp();
|
||||
void JMP_abs();
|
||||
void JMP_ind();
|
||||
void JMP_absxind();
|
||||
void BRK_imp();
|
||||
|
||||
void WAI_imp();
|
||||
void STP_imp();
|
||||
|
||||
void SED_imp();
|
||||
void CLD_imp();
|
||||
void CLV_imp();
|
||||
void SEI_imp();
|
||||
void CLI_imp();
|
||||
void CLC_imp();
|
||||
void SEC_imp();
|
||||
|
||||
void BMI_rel();
|
||||
void BPL_rel();
|
||||
void BVC_rel();
|
||||
void BVS_rel();
|
||||
void BCC_rel();
|
||||
void BCS_rel();
|
||||
void BNE_rel();
|
||||
void BEQ_rel();
|
||||
void BRA_rel();
|
||||
|
||||
void BBR0_zprel();
|
||||
void BBR1_zprel();
|
||||
void BBR2_zprel();
|
||||
void BBR3_zprel();
|
||||
void BBR4_zprel();
|
||||
void BBR5_zprel();
|
||||
void BBR6_zprel();
|
||||
void BBR7_zprel();
|
||||
|
||||
void BBS0_zprel();
|
||||
void BBS1_zprel();
|
||||
void BBS2_zprel();
|
||||
void BBS3_zprel();
|
||||
void BBS4_zprel();
|
||||
void BBS5_zprel();
|
||||
void BBS6_zprel();
|
||||
void BBS7_zprel();
|
||||
|
||||
const uint16_t PageOne = 0x100;
|
||||
const uint16_t IRQvector = 0xfffe;
|
||||
const uint16_t RSTvector = 0xfffc;
|
||||
const uint16_t NMIvector = 0xfffa;
|
||||
|
||||
uint16_t pc; // program counter
|
||||
uint8_t x; // index register X
|
||||
uint8_t y; // index register Y
|
||||
uint8_t a; // accumulator
|
||||
uint8_t s; // stack pointer
|
||||
|
||||
StatusFlags p = 0; // processor status
|
||||
|
||||
uint64_t cycles;
|
||||
|
||||
bool proceed = true;
|
||||
|
||||
std::array<Instruction, 0x100> instructions;
|
||||
|
||||
ProcessorType level;
|
||||
|
||||
std::array<Instruction, 0x100> overlay6502;
|
||||
std::array<Instruction, 0x100> overlay65sc02;
|
||||
std::array<Instruction, 0x100> overlay65c02;
|
||||
};
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <ctime>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
|
||||
#include "mos6502.h"
|
||||
#include "EventArgs.h"
|
||||
#include "AddressEventArgs.h"
|
||||
#include "Signal.h"
|
||||
#include "Memory.h"
|
||||
|
||||
class System6502 : public MOS6502
|
||||
{
|
||||
public:
|
||||
const double Mega = 1000000;
|
||||
const double Milli = 0.001;
|
||||
const unsigned MemorySize = 0x10000;
|
||||
|
||||
uint64_t getHeldCycles() const { return heldCycles; }
|
||||
|
||||
public:
|
||||
System6502(ProcessorType level, double speed, clock_t pollInterval);
|
||||
|
||||
Memory& getMemory() {
|
||||
return memory;
|
||||
}
|
||||
|
||||
virtual void Initialise();
|
||||
virtual void Run();
|
||||
|
||||
Signal<EventArgs> Starting;
|
||||
Signal<EventArgs> Finished;
|
||||
Signal<EventArgs> Polling;
|
||||
Signal<AddressEventArgs> ExecutingInstruction;
|
||||
Signal<AddressEventArgs> ExecutedInstruction;
|
||||
|
||||
virtual uint8_t GetByte(uint16_t offset) const;
|
||||
virtual void SetByte(uint16_t offset, uint8_t value);
|
||||
|
||||
protected:
|
||||
virtual void Execute(uint8_t cell);
|
||||
|
||||
private:
|
||||
void CheckPoll();
|
||||
|
||||
void System6502_Starting();
|
||||
void System6502_Finished();
|
||||
|
||||
void Throttle();
|
||||
|
||||
double speed; // Speed in MHz, e.g. 2.0 == 2Mhz, 1.79 = 1.79Mhz
|
||||
|
||||
double cyclesPerSecond;
|
||||
double cyclesPerMillisecond;
|
||||
uint64_t cyclesPerInterval;
|
||||
uint64_t intervalCycles;
|
||||
|
||||
uint64_t heldCycles = 0;
|
||||
|
||||
bool running;
|
||||
|
||||
Memory memory;
|
||||
|
||||
std::chrono::high_resolution_clock::time_point startTime;
|
||||
};
|
@ -1,23 +0,0 @@
|
||||
namespace Processor
|
||||
{
|
||||
public enum AddressingMode
|
||||
{
|
||||
Illegal,
|
||||
Implied,
|
||||
Accumulator,
|
||||
Immediate,
|
||||
Relative,
|
||||
XIndexed,
|
||||
IndexedY,
|
||||
ZeroPage,
|
||||
ZeroPageX,
|
||||
ZeroPageY,
|
||||
Absolute,
|
||||
AbsoluteX,
|
||||
AbsoluteY,
|
||||
AbsoluteXIndirect,
|
||||
Indirect,
|
||||
ZeroPageIndirect,
|
||||
ZeroPageRelative
|
||||
}
|
||||
}
|
@ -7,10 +7,9 @@
|
||||
|
||||
using namespace std::placeholders;
|
||||
|
||||
Disassembly::Disassembly(MOS6502& targetProcessor, const Symbols& targetSymbols)
|
||||
EightBit::Disassembly::Disassembly(MOS6502& targetProcessor, const Symbols& targetSymbols)
|
||||
: processor(targetProcessor),
|
||||
symbols(targetSymbols)
|
||||
{
|
||||
symbols(targetSymbols) {
|
||||
dumpers = {
|
||||
{ AddressingMode::Illegal, { std::bind(&Disassembly::Dump_Nothing, this, std::placeholders::_1), std::bind(&Disassembly::Dump_Nothing, this, std::placeholders::_1) } },
|
||||
{ AddressingMode::Implied, { std::bind(&Disassembly::Dump_Nothing, this, std::placeholders::_1), std::bind(&Disassembly::Dump_Nothing, this, std::placeholders::_1) } },
|
||||
@ -32,23 +31,23 @@ Disassembly::Disassembly(MOS6502& targetProcessor, const Symbols& targetSymbols)
|
||||
};
|
||||
}
|
||||
|
||||
std::string Disassembly::Dump_ByteValue(uint8_t value) const {
|
||||
std::string EightBit::Disassembly::Dump_ByteValue(uint8_t value) const {
|
||||
std::ostringstream output;
|
||||
output << std::hex << std::setw(2) << std::setfill('0') << (int)value;
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembly::Dump_WordValue(uint16_t value) const {
|
||||
std::string EightBit::Disassembly::Dump_WordValue(uint16_t value) const {
|
||||
std::ostringstream output;
|
||||
output << std::hex << std::setw(4) << std::setfill('0') << (int)value;
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembly::DumpBytes(AddressingMode mode, uint16_t current) const {
|
||||
std::string EightBit::Disassembly::DumpBytes(AddressingMode mode, uint16_t current) const {
|
||||
return getDumper(mode).byteDumper(current);
|
||||
}
|
||||
|
||||
std::string Disassembly::Disassemble(uint16_t current) const {
|
||||
std::string EightBit::Disassembly::Disassemble(uint16_t current) const {
|
||||
|
||||
std::ostringstream output;
|
||||
|
||||
@ -68,37 +67,37 @@ std::string Disassembly::Disassemble(uint16_t current) const {
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembly::DumpOperand(AddressingMode mode, uint16_t current) const {
|
||||
std::string EightBit::Disassembly::DumpOperand(AddressingMode mode, uint16_t current) const {
|
||||
return getDumper(mode).disassemblyDumper(current);
|
||||
}
|
||||
|
||||
////
|
||||
|
||||
uint8_t Disassembly::GetByte(uint16_t address) const {
|
||||
uint8_t EightBit::Disassembly::GetByte(uint16_t address) const {
|
||||
return processor.GetByte(address);
|
||||
}
|
||||
|
||||
uint16_t Disassembly::GetWord(uint16_t address) const {
|
||||
uint16_t EightBit::Disassembly::GetWord(uint16_t address) const {
|
||||
return processor.GetWord(address);
|
||||
}
|
||||
|
||||
////
|
||||
|
||||
std::string Disassembly::Dump_Nothing(uint16_t) const {
|
||||
std::string EightBit::Disassembly::Dump_Nothing(uint16_t) const {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string Disassembly::Dump_Byte(uint16_t address) const {
|
||||
std::string EightBit::Disassembly::Dump_Byte(uint16_t address) const {
|
||||
return Dump_ByteValue(GetByte(address));
|
||||
}
|
||||
|
||||
std::string Disassembly::Dump_DByte(uint16_t address) const {
|
||||
std::string EightBit::Disassembly::Dump_DByte(uint16_t address) const {
|
||||
return Dump_Byte(address) + Dump_Byte(address + 1);
|
||||
}
|
||||
|
||||
////
|
||||
|
||||
std::string Disassembly::ConvertAddress(uint16_t address) const {
|
||||
std::string EightBit::Disassembly::ConvertAddress(uint16_t address) const {
|
||||
auto label = symbols.getLabels().find(address);
|
||||
if (label != symbols.getLabels().end())
|
||||
return label->second;
|
||||
@ -107,7 +106,7 @@ std::string Disassembly::ConvertAddress(uint16_t address) const {
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembly::ConvertAddress(uint8_t address) const {
|
||||
std::string EightBit::Disassembly::ConvertAddress(uint8_t address) const {
|
||||
auto label = symbols.getLabels().find(address);
|
||||
if (label != symbols.getLabels().end())
|
||||
return label->second;
|
||||
@ -116,14 +115,14 @@ std::string Disassembly::ConvertAddress(uint8_t address) const {
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembly::ConvertConstant(uint16_t constant) const {
|
||||
std::string EightBit::Disassembly::ConvertConstant(uint16_t constant) const {
|
||||
auto label = symbols.getConstants().find(constant);
|
||||
if (label != symbols.getConstants().end())
|
||||
return label->second;
|
||||
return Dump_DByte(constant);
|
||||
}
|
||||
|
||||
std::string Disassembly::ConvertConstant(uint8_t constant) const {
|
||||
std::string EightBit::Disassembly::ConvertConstant(uint8_t constant) const {
|
||||
auto label = symbols.getConstants().find(constant);
|
||||
if (label != symbols.getConstants().end())
|
||||
return label->second;
|
||||
@ -132,96 +131,96 @@ std::string Disassembly::ConvertConstant(uint8_t constant) const {
|
||||
|
||||
////
|
||||
|
||||
std::string Disassembly::Dump_A(uint16_t) const {
|
||||
std::string EightBit::Disassembly::Dump_A(uint16_t) const {
|
||||
return "A";
|
||||
}
|
||||
|
||||
std::string Disassembly::Dump_imm(uint16_t current) const {
|
||||
std::string EightBit::Disassembly::Dump_imm(uint16_t current) const {
|
||||
std::ostringstream output;
|
||||
auto immediate = GetByte(current);
|
||||
output << "#" << ConvertConstant(immediate);
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembly::Dump_abs(uint16_t current) const {
|
||||
std::string EightBit::Disassembly::Dump_abs(uint16_t current) const {
|
||||
auto address = GetWord(current);
|
||||
return ConvertAddress(address);
|
||||
}
|
||||
|
||||
std::string Disassembly::Dump_zp(uint16_t current) const {
|
||||
std::string EightBit::Disassembly::Dump_zp(uint16_t current) const {
|
||||
auto zp = GetByte(current);
|
||||
return ConvertAddress(zp);
|
||||
}
|
||||
|
||||
std::string Disassembly::Dump_zpx(uint16_t current) const {
|
||||
std::string EightBit::Disassembly::Dump_zpx(uint16_t current) const {
|
||||
std::ostringstream output;
|
||||
auto zp = GetByte(current);
|
||||
output << ConvertAddress(zp) << ",X";
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembly::Dump_zpy(uint16_t current) const {
|
||||
std::string EightBit::Disassembly::Dump_zpy(uint16_t current) const {
|
||||
std::ostringstream output;
|
||||
auto zp = GetByte(current);
|
||||
output << ConvertAddress(zp) << ",Y";
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembly::Dump_absx(uint16_t current) const {
|
||||
std::string EightBit::Disassembly::Dump_absx(uint16_t current) const {
|
||||
std::ostringstream output;
|
||||
auto address = GetWord(current);
|
||||
output << ConvertAddress(address) << ",X";
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembly::Dump_absy(uint16_t current) const {
|
||||
std::string EightBit::Disassembly::Dump_absy(uint16_t current) const {
|
||||
std::ostringstream output;
|
||||
auto address = GetWord(current);
|
||||
output << ConvertAddress(address) << ",Y";
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembly::Dump_absxind(uint16_t current) const {
|
||||
std::string EightBit::Disassembly::Dump_absxind(uint16_t current) const {
|
||||
std::ostringstream output;
|
||||
auto address = GetWord(current);
|
||||
output << "(" << ConvertAddress(address) << ",X)";
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembly::Dump_xind(uint16_t current) const {
|
||||
std::string EightBit::Disassembly::Dump_xind(uint16_t current) const {
|
||||
std::ostringstream output;
|
||||
auto zp = GetByte(current);
|
||||
output << "(" << ConvertAddress(zp) << ",X)";
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembly::Dump_indy(uint16_t current) const {
|
||||
std::string EightBit::Disassembly::Dump_indy(uint16_t current) const {
|
||||
std::ostringstream output;
|
||||
auto zp = GetByte(current);
|
||||
output << "(" << ConvertAddress(zp) << "),Y";
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembly::Dump_ind(uint16_t current) const {
|
||||
std::string EightBit::Disassembly::Dump_ind(uint16_t current) const {
|
||||
std::ostringstream output;
|
||||
auto address = GetWord(current);
|
||||
output << "(" << ConvertAddress(address) << ")";
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembly::Dump_zpind(uint16_t current) const {
|
||||
std::string EightBit::Disassembly::Dump_zpind(uint16_t current) const {
|
||||
std::ostringstream output;
|
||||
auto zp = GetByte(current);
|
||||
output << "(" << ConvertAddress(zp) << ")";
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string Disassembly::Dump_rel(uint16_t current) const {
|
||||
std::string EightBit::Disassembly::Dump_rel(uint16_t current) const {
|
||||
uint16_t relative = 1 + current + (int8_t)GetByte(current);
|
||||
return ConvertAddress(relative);
|
||||
}
|
||||
|
||||
std::string Disassembly::Dump_zprel(uint16_t current) const {
|
||||
std::string EightBit::Disassembly::Dump_zprel(uint16_t current) const {
|
||||
std::ostringstream output;
|
||||
auto zp = GetByte(current);
|
||||
int8_t displacement = GetByte(current + 1);
|
||||
|
167
M6502/src/M6502.vcxproj
Normal file
167
M6502/src/M6502.vcxproj
Normal file
@ -0,0 +1,167 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{D8726A1B-BBFE-47EF-9860-26B90140BA66}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>M6502</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<IncludePath>..\inc;..\..\inc;C:\local\boost_1_64_0;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<IncludePath>..\inc;..\..\inc;C:\local\boost_1_64_0;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<IncludePath>..\inc;..\..\inc;C:\local\boost_1_64_0;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<IncludePath>..\inc;..\..\inc;C:\local\boost_1_64_0;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\inc\AddressingMode.h" />
|
||||
<ClInclude Include="..\inc\AddressingModeDumper.h" />
|
||||
<ClInclude Include="..\inc\Disassembly.h" />
|
||||
<ClInclude Include="..\inc\DisassemblyEventArgs.h" />
|
||||
<ClInclude Include="..\inc\mos6502.h" />
|
||||
<ClInclude Include="..\inc\ProcessorType.h" />
|
||||
<ClInclude Include="..\inc\ProfileEventArgs.h" />
|
||||
<ClInclude Include="..\inc\ProfileLineEventArgs.h" />
|
||||
<ClInclude Include="..\inc\Profiler.h" />
|
||||
<ClInclude Include="..\inc\ProfileScopeEventArgs.h" />
|
||||
<ClInclude Include="..\inc\StatusFlags.h" />
|
||||
<ClInclude Include="..\inc\Symbols.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Disassembly.cpp" />
|
||||
<ClCompile Include="mos6502.cpp" />
|
||||
<ClCompile Include="Profiler.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Symbols.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
71
M6502/src/M6502.vcxproj.filters
Normal file
71
M6502/src/M6502.vcxproj.filters
Normal file
@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\AddressingMode.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\AddressingModeDumper.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\Disassembly.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\DisassemblyEventArgs.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\mos6502.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\ProcessorType.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\ProfileEventArgs.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\ProfileLineEventArgs.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\Profiler.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\ProfileScopeEventArgs.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\StatusFlags.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\Symbols.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Disassembly.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="mos6502.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Profiler.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Symbols.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,9 +0,0 @@
|
||||
namespace Processor
|
||||
{
|
||||
public enum ProcessorType
|
||||
{
|
||||
Cpu6502,
|
||||
Cpu65SC02,
|
||||
Cpu65C02
|
||||
}
|
||||
}
|
@ -1,34 +1,25 @@
|
||||
#include "stdafx.h"
|
||||
#include "Profiler.h"
|
||||
|
||||
Profiler::Profiler(System6502& targetProcessor, Disassembly& disassemblerTarget, Symbols& symbolsTarget, bool instructions, bool addresses)
|
||||
EightBit::Profiler::Profiler(MOS6502& targetProcessor, Disassembly& disassemblerTarget, Symbols& symbolsTarget)
|
||||
: processor(targetProcessor),
|
||||
disassembler(disassemblerTarget),
|
||||
symbols(symbolsTarget),
|
||||
countInstructions(instructions),
|
||||
profileAddresses(addresses)
|
||||
{
|
||||
symbols(symbolsTarget) {
|
||||
|
||||
instructionCounts.fill(0);
|
||||
addressProfiles.fill(0);
|
||||
addressCounts.fill(0);
|
||||
|
||||
if (profileAddresses)
|
||||
processor.ExecutingInstruction.connect(std::bind(&Profiler::Processor_ExecutingInstruction_ProfileAddresses, this, std::placeholders::_1));
|
||||
if (countInstructions)
|
||||
processor.ExecutingInstruction.connect(std::bind(&Profiler::Processor_ExecutingInstruction_CountInstructions, this, std::placeholders::_1));
|
||||
if (profileAddresses)
|
||||
processor.ExecutedInstruction.connect(std::bind(&Profiler::Processor_ExecutedInstruction_ProfileAddresses, this, std::placeholders::_1));
|
||||
|
||||
BuildAddressScopes();
|
||||
}
|
||||
|
||||
void Profiler::Generate() {
|
||||
void EightBit::Profiler::Generate() {
|
||||
StartingOutput.fire(EventArgs());
|
||||
EmitProfileInformation();
|
||||
StartingOutput.fire(EventArgs());
|
||||
}
|
||||
|
||||
void Profiler::EmitProfileInformation() {
|
||||
void EightBit::Profiler::EmitProfileInformation() {
|
||||
|
||||
{
|
||||
StartingLineOutput.fire(EventArgs());
|
||||
@ -58,22 +49,16 @@ void Profiler::EmitProfileInformation() {
|
||||
}
|
||||
}
|
||||
|
||||
void Profiler::Processor_ExecutingInstruction_ProfileAddresses(const AddressEventArgs& addressEvent) {
|
||||
assert(profileAddresses);
|
||||
priorCycleCount = processor.getCycles();
|
||||
addressCounts[addressEvent.getAddress()]++;
|
||||
void EightBit::Profiler::addInstruction(uint8_t instruction) {
|
||||
++instructionCounts[instruction];
|
||||
}
|
||||
|
||||
void Profiler::Processor_ExecutingInstruction_CountInstructions(const AddressEventArgs& addressEvent) {
|
||||
assert(countInstructions);
|
||||
++instructionCounts[addressEvent.getCell()];
|
||||
}
|
||||
void EightBit::Profiler::addAddress(uint16_t address, int cycles) {
|
||||
|
||||
void Profiler::Processor_ExecutedInstruction_ProfileAddresses(const AddressEventArgs& addressEvent) {
|
||||
assert(profileAddresses);
|
||||
auto cycles = processor.getCycles() - priorCycleCount;
|
||||
addressProfiles[addressEvent.getAddress()] += cycles;
|
||||
auto addressScope = addressScopes[addressEvent.getAddress()];
|
||||
addressCounts[address]++;
|
||||
|
||||
addressProfiles[address] += cycles;
|
||||
auto addressScope = addressScopes[address];
|
||||
if (!addressScope.empty()) {
|
||||
if (scopeCycles.find(addressScope) == scopeCycles.end())
|
||||
scopeCycles[addressScope] = 0;
|
||||
@ -81,7 +66,7 @@ void Profiler::Processor_ExecutedInstruction_ProfileAddresses(const AddressEvent
|
||||
}
|
||||
}
|
||||
|
||||
void Profiler::BuildAddressScopes() {
|
||||
void EightBit::Profiler::BuildAddressScopes() {
|
||||
for (auto& label : symbols.getLabels()) {
|
||||
auto address = label.first;
|
||||
auto key = label.second;
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include <boost/algorithm/string/regex.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
Symbols::Symbols(std::string path) {
|
||||
EightBit::Symbols::Symbols(std::string path) {
|
||||
if (!path.empty()) {
|
||||
Parse(path);
|
||||
AssignSymbols();
|
||||
@ -18,7 +18,7 @@ Symbols::Symbols(std::string path) {
|
||||
}
|
||||
}
|
||||
|
||||
void Symbols::AssignScopes() {
|
||||
void EightBit::Symbols::AssignScopes() {
|
||||
auto parsedScopes = parsed["scope"];
|
||||
for(auto& parsedScopeElement : parsedScopes) {
|
||||
auto& parsedScope = parsedScopeElement.second.element;
|
||||
@ -29,7 +29,7 @@ void Symbols::AssignScopes() {
|
||||
}
|
||||
}
|
||||
|
||||
void Symbols::AssignSymbols() {
|
||||
void EightBit::Symbols::AssignSymbols() {
|
||||
auto symbols = parsed["sym"];
|
||||
for(auto& symbolElement : symbols) {
|
||||
auto& symbol = symbolElement.second.element;
|
||||
@ -47,7 +47,7 @@ void Symbols::AssignSymbols() {
|
||||
}
|
||||
}
|
||||
|
||||
void Symbols::Parse(std::string path) {
|
||||
void EightBit::Symbols::Parse(std::string path) {
|
||||
std::string line;
|
||||
std::ifstream reader(path);
|
||||
while (std::getline(reader, line)) {
|
||||
@ -73,7 +73,7 @@ void Symbols::Parse(std::string path) {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> Symbols::split(const std::string& input, const std::vector<std::string>& delimiters) {
|
||||
std::vector<std::string> EightBit::Symbols::split(const std::string& input, const std::vector<std::string>& delimiters) {
|
||||
std::vector<std::string> tokens;
|
||||
boost::algorithm::split_regex(
|
||||
tokens,
|
||||
|
File diff suppressed because it is too large
Load Diff
1
M6502/src/stdafx.cpp
Normal file
1
M6502/src/stdafx.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "stdafx.h"
|
1
M6502/src/stdafx.h
Normal file
1
M6502/src/stdafx.h
Normal file
@ -0,0 +1 @@
|
||||
#pragma once
|
@ -1,91 +0,0 @@
|
||||
#include "stdafx.h"
|
||||
#include "system6502.h"
|
||||
|
||||
#include <thread>
|
||||
#include <functional>
|
||||
|
||||
System6502::System6502(ProcessorType level, double processorSpeed, clock_t pollInterval)
|
||||
: MOS6502(level),
|
||||
memory(MemorySize)
|
||||
{
|
||||
speed = processorSpeed;
|
||||
|
||||
cyclesPerSecond = speed * Mega; // speed is in MHz
|
||||
cyclesPerMillisecond = cyclesPerSecond * Milli;
|
||||
cyclesPerInterval = (uint64_t)(cyclesPerMillisecond * pollInterval);
|
||||
|
||||
Starting.connect(std::bind(&System6502::System6502_Starting, this));
|
||||
Finished.connect(std::bind(&System6502::System6502_Finished, this));
|
||||
}
|
||||
|
||||
void System6502::Initialise() {
|
||||
__super::Initialise();
|
||||
memory.ClearLocking();
|
||||
memory.ClearMemory();
|
||||
intervalCycles = 0;
|
||||
}
|
||||
|
||||
void System6502::Run() {
|
||||
Starting.fire(EventArgs());
|
||||
__super::Run();
|
||||
Finished.fire(EventArgs());
|
||||
}
|
||||
|
||||
uint8_t System6502::GetByte(uint16_t offset) const {
|
||||
return memory.GetByte(offset);
|
||||
}
|
||||
|
||||
void System6502::SetByte(uint16_t offset, uint8_t value) {
|
||||
memory.SetByte(offset, value);
|
||||
}
|
||||
|
||||
void System6502::Execute(uint8_t cell) {
|
||||
|
||||
auto oldCycles = getCycles();
|
||||
|
||||
CheckPoll();
|
||||
|
||||
// XXXX Fetch byte has already incremented PC.
|
||||
auto executingAddress = (uint16_t)(getPC() - 1);
|
||||
|
||||
AddressEventArgs e(executingAddress, cell);
|
||||
ExecutingInstruction.fire(e);
|
||||
__super::Execute(cell);
|
||||
ExecutedInstruction.fire(e);
|
||||
|
||||
auto deltaCycles = getCycles() - oldCycles;
|
||||
intervalCycles += deltaCycles;
|
||||
}
|
||||
|
||||
void System6502::CheckPoll() {
|
||||
if (intervalCycles >= cyclesPerInterval) {
|
||||
intervalCycles -= cyclesPerInterval;
|
||||
Throttle();
|
||||
Polling.fire(EventArgs());
|
||||
}
|
||||
}
|
||||
|
||||
void System6502::System6502_Starting() {
|
||||
startTime = std::chrono::high_resolution_clock::now();
|
||||
running = true;
|
||||
}
|
||||
|
||||
void System6502::System6502_Finished() {
|
||||
running = false;
|
||||
}
|
||||
|
||||
void System6502::Throttle() {
|
||||
auto now = std::chrono::high_resolution_clock::now();
|
||||
auto elapsed = now - startTime;
|
||||
auto timerCurrent = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count();
|
||||
|
||||
auto cyclesAllowed = timerCurrent * cyclesPerMillisecond;
|
||||
auto cyclesMismatch = getCycles() - cyclesAllowed;
|
||||
if (cyclesMismatch > 0.0) {
|
||||
auto delay = cyclesMismatch / cyclesPerMillisecond;
|
||||
if (delay > 0) {
|
||||
heldCycles += (uint64_t)cyclesMismatch;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds((long long)delay));
|
||||
}
|
||||
}
|
||||
}
|
18
inc/AddressEventArgs.h
Normal file
18
inc/AddressEventArgs.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace EightBit {
|
||||
class AddressEventArgs {
|
||||
private:
|
||||
uint16_t m_address;
|
||||
uint8_t m_cell;
|
||||
|
||||
public:
|
||||
AddressEventArgs(uint16_t address, uint8_t cell)
|
||||
: m_address(address), m_cell(cell) {}
|
||||
|
||||
uint16_t getAddress() const { return m_address; }
|
||||
uint8_t getCell() const { return m_cell; }
|
||||
};
|
||||
}
|
21
inc/Memory.h
21
inc/Memory.h
@ -4,6 +4,9 @@
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "Signal.h"
|
||||
#include "AddressEventArgs.h"
|
||||
|
||||
#if defined(_M_X64) || defined(_M_IX86 )
|
||||
# define HOST_LITTLE_ENDIAN
|
||||
#else
|
||||
@ -39,6 +42,10 @@ namespace EightBit {
|
||||
|
||||
Memory(uint16_t addressMask);
|
||||
|
||||
// Only fired with read/write methods
|
||||
Signal<AddressEventArgs> WritingByte;
|
||||
Signal<AddressEventArgs> ReadingByte;
|
||||
|
||||
register16_t& ADDRESS() { return m_address; }
|
||||
uint8_t& DATA() { return *m_data; }
|
||||
|
||||
@ -65,6 +72,20 @@ namespace EightBit {
|
||||
return address & m_addressMask;
|
||||
}
|
||||
|
||||
uint8_t read(uint16_t offset) {
|
||||
ADDRESS().word = offset;
|
||||
const auto content = reference();
|
||||
ReadingByte.fire(AddressEventArgs(offset, content));
|
||||
return content;
|
||||
}
|
||||
|
||||
void write(uint16_t offset, uint8_t value) {
|
||||
AddressEventArgs e(offset, value);
|
||||
WritingByte.fire(e);
|
||||
ADDRESS().word = offset;
|
||||
reference() = value;
|
||||
}
|
||||
|
||||
void clear();
|
||||
void loadRom(const std::string& path, uint16_t offset);
|
||||
void loadRam(const std::string& path, uint16_t offset);
|
||||
|
@ -138,6 +138,7 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\inc\AddressEventArgs.h" />
|
||||
<ClInclude Include="..\inc\EventArgs.h" />
|
||||
<ClInclude Include="..\inc\IntelProcessor.h" />
|
||||
<ClInclude Include="..\inc\Memory.h" />
|
||||
|
@ -32,6 +32,9 @@
|
||||
<ClInclude Include="..\inc\TestHarness.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\AddressEventArgs.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
|
Loading…
Reference in New Issue
Block a user