mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2025-08-15 10:27:26 +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:
@@ -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,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
enum AddressingMode {
|
||||
namespace EightBit {
|
||||
enum AddressingMode {
|
||||
Illegal,
|
||||
Implied,
|
||||
Accumulator,
|
||||
@@ -18,4 +19,5 @@ enum AddressingMode {
|
||||
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 {
|
||||
typedef std::function<std::string(uint16_t current)> dumper_t;
|
||||
|
||||
struct AddressingModeDumper {
|
||||
dumper_t byteDumper;
|
||||
dumper_t disassemblyDumper;
|
||||
};
|
||||
};
|
||||
}
|
@@ -3,15 +3,15 @@
|
||||
#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:
|
||||
namespace EightBit {
|
||||
class Disassembly {
|
||||
public:
|
||||
MOS6502& processor;
|
||||
const Symbols& symbols;
|
||||
|
||||
@@ -26,7 +26,7 @@ public:
|
||||
std::string Disassemble(uint16_t current) const;
|
||||
std::string DumpOperand(AddressingMode mode, uint16_t current) const;
|
||||
|
||||
private:
|
||||
private:
|
||||
uint8_t GetByte(uint16_t address) const;
|
||||
uint16_t GetWord(uint16_t address) const;
|
||||
|
||||
@@ -61,4 +61,5 @@ private:
|
||||
throw std::invalid_argument("Illegal addressing mode");
|
||||
return dumper->second;
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
@@ -2,14 +2,15 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
class DisassemblyEventArgs
|
||||
{
|
||||
private:
|
||||
namespace EightBit {
|
||||
class DisassemblyEventArgs {
|
||||
private:
|
||||
std::string m_output;
|
||||
|
||||
public:
|
||||
public:
|
||||
DisassemblyEventArgs(std::string output)
|
||||
: m_output(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 {
|
||||
namespace EightBit {
|
||||
enum ProcessorType {
|
||||
Cpu6502,
|
||||
Cpu65SC02,
|
||||
Cpu65C02
|
||||
};
|
||||
};
|
||||
}
|
@@ -2,14 +2,15 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
class ProfileEventArgs
|
||||
{
|
||||
private:
|
||||
namespace EightBit {
|
||||
class ProfileEventArgs {
|
||||
private:
|
||||
std::string m_output;
|
||||
|
||||
public:
|
||||
public:
|
||||
ProfileEventArgs(std::string output)
|
||||
: m_output(output) {}
|
||||
|
||||
const std::string& getOutput() const { return m_output; }
|
||||
};
|
||||
};
|
||||
}
|
@@ -3,16 +3,18 @@
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
|
||||
class ProfileLineEventArgs
|
||||
{
|
||||
private:
|
||||
namespace EightBit {
|
||||
class ProfileLineEventArgs
|
||||
{
|
||||
private:
|
||||
std::string m_source;
|
||||
uint64_t m_cycles;
|
||||
|
||||
public:
|
||||
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; }
|
||||
};
|
||||
};
|
||||
}
|
@@ -3,19 +3,19 @@
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
|
||||
class ProfileScopeEventArgs
|
||||
{
|
||||
private:
|
||||
namespace EightBit {
|
||||
class ProfileScopeEventArgs {
|
||||
private:
|
||||
std::string m_scope;
|
||||
uint64_t m_cycles;
|
||||
uint64_t m_count;
|
||||
|
||||
public:
|
||||
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,19 +5,21 @@
|
||||
#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:
|
||||
#include "mos6502.h"
|
||||
|
||||
namespace EightBit {
|
||||
class Profiler {
|
||||
public:
|
||||
std::array<uint64_t, 0x100> instructionCounts;
|
||||
std::array<uint64_t, 0x10000> addressProfiles;
|
||||
std::array<uint64_t, 0x10000> addressCounts;
|
||||
@@ -25,16 +27,11 @@ public:
|
||||
std::array<std::string, 0x10000> addressScopes;
|
||||
std::map<std::string, uint64_t> scopeCycles;
|
||||
|
||||
System6502& processor;
|
||||
MOS6502& processor;
|
||||
const Disassembly& disassembler;
|
||||
const Symbols& symbols;
|
||||
|
||||
bool countInstructions;
|
||||
bool profileAddresses;
|
||||
|
||||
uint64_t priorCycleCount = 0;
|
||||
|
||||
Profiler(System6502& processor, Disassembly& disassembler, Symbols& symbols, bool countInstructions, bool profileAddresses);
|
||||
Profiler(MOS6502& processor, Disassembly& disassembler, Symbols& symbols);
|
||||
|
||||
Signal<EventArgs> StartingOutput;
|
||||
Signal<EventArgs> FinishedOutput;
|
||||
@@ -49,14 +46,14 @@ public:
|
||||
|
||||
Signal<ProfileScopeEventArgs> EmitScope;
|
||||
|
||||
void addInstruction(uint8_t instruction);
|
||||
void addAddress(uint16_t address, int cycles);
|
||||
|
||||
void Generate();
|
||||
|
||||
private:
|
||||
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();
|
||||
};
|
||||
};
|
||||
}
|
@@ -3,7 +3,8 @@
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
|
||||
struct StatusFlags {
|
||||
namespace EightBit {
|
||||
struct StatusFlags {
|
||||
|
||||
bool negative;
|
||||
bool overflow;
|
||||
@@ -79,4 +80,5 @@ struct StatusFlags {
|
||||
returned += carry ? "C" : "-";
|
||||
return returned;
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
@@ -5,9 +5,9 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
class Symbols
|
||||
{
|
||||
public:
|
||||
namespace EightBit {
|
||||
class Symbols {
|
||||
public:
|
||||
Symbols(std::string path);
|
||||
|
||||
const std::map<uint16_t, std::string>& getLabels() const { return labels; }
|
||||
@@ -15,7 +15,7 @@ public:
|
||||
const std::map<std::string, uint16_t>& getScopes() const { return scopes; }
|
||||
const std::map<std::string, uint64_t>& getAddresses() const { return addresses; }
|
||||
|
||||
private:
|
||||
private:
|
||||
void AssignScopes();
|
||||
void AssignSymbols();
|
||||
|
||||
@@ -33,4 +33,5 @@ private:
|
||||
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,9 +8,11 @@
|
||||
#include "ProcessorType.h"
|
||||
#include "StatusFlags.h"
|
||||
#include "AddressingMode.h"
|
||||
#include "Signal.h"
|
||||
|
||||
class MOS6502 {
|
||||
public:
|
||||
namespace EightBit {
|
||||
class MOS6502 {
|
||||
public:
|
||||
typedef std::function<void()> instruction_t;
|
||||
|
||||
struct Instruction {
|
||||
@@ -22,6 +24,8 @@ public:
|
||||
|
||||
MOS6502(ProcessorType level);
|
||||
|
||||
Signal<MOS6502> ExecutingInstruction;
|
||||
|
||||
ProcessorType getLevel() const { return level; }
|
||||
uint64_t getCycles() const { return cycles; }
|
||||
|
||||
@@ -56,7 +60,7 @@ public:
|
||||
virtual uint8_t GetByte(uint16_t offset) const = 0;
|
||||
virtual void SetByte(uint16_t offset, uint8_t value) = 0;
|
||||
|
||||
protected:
|
||||
protected:
|
||||
virtual void Interrupt(uint16_t vector);
|
||||
|
||||
virtual void Execute(uint8_t cell);
|
||||
@@ -65,7 +69,7 @@ protected:
|
||||
|
||||
void ResetRegisters();
|
||||
|
||||
private:
|
||||
private:
|
||||
static Instruction INS(instruction_t method, uint64_t cycles, AddressingMode addressing, std::string display);
|
||||
|
||||
static uint8_t LowNybble(uint8_t value);
|
||||
@@ -461,4 +465,5 @@ private:
|
||||
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">
|
||||
|
Reference in New Issue
Block a user