Dump of all my C++ emulators, only Intel8080 integrated so far...

Signed-off-by: Adrian.Conlon <adrian.conlon@gmail.com>
This commit is contained in:
Adrian.Conlon 2017-06-04 21:38:34 +01:00
commit 105032f08a
67 changed files with 10430 additions and 0 deletions

51
.gitignore vendored Normal file
View File

@ -0,0 +1,51 @@
.vs/
Debug/
Release/
x64/
ipch/
cov-int/
packages/
*.opendb
*.sdf
*.vsp
*.VC.db
*.vcxproj.user
*.swp
*~
*.bin
*.rom
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
cpp_chip8
src/state

38
EightBit.sln Normal file
View File

@ -0,0 +1,38 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26430.12
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EightBit", "src\EightBit.vcxproj", "{A9C24BD9-0CB4-4C84-B09B-46B815F9DA47}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Intel8080", "Intel8080\src\Intel8080.vcxproj", "{93BDC8D8-9F0D-44ED-94FB-1BE6AC4B6BD6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A9C24BD9-0CB4-4C84-B09B-46B815F9DA47}.Debug|x64.ActiveCfg = Debug|x64
{A9C24BD9-0CB4-4C84-B09B-46B815F9DA47}.Debug|x64.Build.0 = Debug|x64
{A9C24BD9-0CB4-4C84-B09B-46B815F9DA47}.Debug|x86.ActiveCfg = Debug|Win32
{A9C24BD9-0CB4-4C84-B09B-46B815F9DA47}.Debug|x86.Build.0 = Debug|Win32
{A9C24BD9-0CB4-4C84-B09B-46B815F9DA47}.Release|x64.ActiveCfg = Release|x64
{A9C24BD9-0CB4-4C84-B09B-46B815F9DA47}.Release|x64.Build.0 = Release|x64
{A9C24BD9-0CB4-4C84-B09B-46B815F9DA47}.Release|x86.ActiveCfg = Release|Win32
{A9C24BD9-0CB4-4C84-B09B-46B815F9DA47}.Release|x86.Build.0 = Release|Win32
{93BDC8D8-9F0D-44ED-94FB-1BE6AC4B6BD6}.Debug|x64.ActiveCfg = Debug|x64
{93BDC8D8-9F0D-44ED-94FB-1BE6AC4B6BD6}.Debug|x64.Build.0 = Debug|x64
{93BDC8D8-9F0D-44ED-94FB-1BE6AC4B6BD6}.Debug|x86.ActiveCfg = Debug|Win32
{93BDC8D8-9F0D-44ED-94FB-1BE6AC4B6BD6}.Debug|x86.Build.0 = Debug|Win32
{93BDC8D8-9F0D-44ED-94FB-1BE6AC4B6BD6}.Release|x64.ActiveCfg = Release|x64
{93BDC8D8-9F0D-44ED-94FB-1BE6AC4B6BD6}.Release|x64.Build.0 = Release|x64
{93BDC8D8-9F0D-44ED-94FB-1BE6AC4B6BD6}.Release|x86.ActiveCfg = Release|Win32
{93BDC8D8-9F0D-44ED-94FB-1BE6AC4B6BD6}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,21 @@
#pragma once
#include <string>
namespace EightBit {
class Intel8080;
class Disassembler {
public:
Disassembler();
static std::string state(Intel8080& cpu);
static std::string disassemble(Intel8080& cpu);
static std::string hex(uint8_t value);
static std::string hex(uint16_t value);
static std::string binary(uint8_t value);
static std::string invalid(uint8_t value);
};
}

View File

@ -0,0 +1,38 @@
#pragma once
#include <cstdint>
#include "Signal.h"
#include "PortEventArgs.h"
namespace EightBit {
class InputOutput {
public:
InputOutput();
uint8_t read(uint8_t port) { return readInputPort(port); }
void write(uint8_t port, uint8_t value) { return writeOutputPort(port, value); }
uint8_t readInputPort(uint8_t port);
void writeInputPort(uint8_t port, uint8_t value) { input[port] = value; }
uint8_t readOutputPort(uint8_t port) { return output[port]; }
void writeOutputPort(uint8_t port, uint8_t value);
Signal<PortEventArgs> ReadingPort;
Signal<PortEventArgs> ReadPort;
Signal<PortEventArgs> WritingPort;
Signal<PortEventArgs> WrittenPort;
protected:
void OnReadingPort(uint8_t port);
void OnReadPort(uint8_t port);
void OnWritingPort(uint8_t port);
void OnWrittenPort(uint8_t port);
private:
std::array<uint8_t, 0x100> input;
std::array<uint8_t, 0x100> output;
};
}

708
Intel8080/inc/Intel8080.h Normal file
View File

@ -0,0 +1,708 @@
#pragma once
// Auxiliary carry logic from https://github.com/begoon/i8080-core
#include "Processor.h"
#include "StatusFlags.h"
#include "InputOutput.h"
namespace EightBit {
class Intel8080 : public Processor {
public:
typedef std::function<void()> instruction_t;
enum AddressingMode {
Unknown,
Implied, // zero bytes
Immediate, // single byte
Absolute // two bytes, little endian
};
struct Instruction {
instruction_t vector = nullptr;
AddressingMode mode = Unknown;
std::string disassembly;
int count = 0;
};
Intel8080(Memory& memory, InputOutput& ports);
Signal<Intel8080> ExecutingInstruction;
const std::array<Instruction, 0x100>& getInstructions() const { return instructions; }
uint8_t& A() { return a; }
StatusFlags& F() { return f; }
register16_t& BC() { return bc; }
uint8_t& B() { return BC().high; }
uint8_t& C() { return BC().low; }
register16_t& DE() { return de; }
uint8_t& D() { return DE().high; }
uint8_t& E() { return DE().low; }
register16_t& HL() { return hl; }
uint8_t& H() { return HL().high; }
uint8_t& L() { return HL().low; }
bool isInterruptable() const {
return m_interrupt;
}
void disableInterrupts() { m_interrupt = false; }
void enableInterrupts() { m_interrupt = true; }
int interrupt(uint8_t value) {
if (isInterruptable()) {
disableInterrupts();
return execute(value);
}
return 0;
}
virtual void initialise();
int step();
private:
InputOutput m_ports;
std::array<Instruction, 0x100> instructions;
std::array<bool, 8> m_halfCarryTableAdd = { { false, false, true, false, true, false, true, true } };
std::array<bool, 8> m_halfCarryTableSub = { { false, true, true, true, false, false, false, true } };
uint8_t a;
StatusFlags f;
register16_t bc;
register16_t de;
register16_t hl;
bool m_interrupt;
int execute(uint8_t opcode);
int execute(const Instruction& instruction) {
cycles = 0;
instruction.vector();
return cycles + instruction.count;
}
void adjustSign(uint8_t value) { F().S = ((value & 0x80) != 0); }
void adjustZero(uint8_t value) { F().Z = (value == 0); }
void adjustParity(uint8_t value) {
static const uint8_t lookup[0x10] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
auto set = (lookup[highNibble(value)] + lookup[lowNibble(value)]);
F().P = (set % 2) == 0;
}
void adjustSZP(uint8_t value) {
adjustSign(value);
adjustZero(value);
adjustParity(value);
}
int buildAuxiliaryCarryIndex(uint8_t value, int calculation) {
return ((A() & 0x88) >> 1) | ((value & 0x88) >> 2) | ((calculation & 0x88) >> 3);
}
void adjustAuxiliaryCarryAdd(uint8_t value, int calculation) {
auto index = buildAuxiliaryCarryIndex(value, calculation);
F().AC = m_halfCarryTableAdd[index & 0x7];
}
void adjustAuxiliaryCarrySub(uint8_t value, int calculation) {
auto index = buildAuxiliaryCarryIndex(value, calculation);
F().AC = !m_halfCarryTableSub[index & 0x7];
}
void postIncrement(uint8_t value) {
adjustSZP(value);
F().AC = (value & 0x0f) == 0;
}
void postDecrement(uint8_t value) {
adjustSZP(value);
F().AC = (value & 0x0f) != 0xf;
}
static Instruction INS(instruction_t method, AddressingMode mode, std::string disassembly, int cycles);
Instruction UNKNOWN();
void installInstructions();
//
void compare(uint8_t value) {
uint16_t subtraction = A() - value;
adjustSZP((uint8_t)subtraction);
adjustAuxiliaryCarrySub(value, subtraction);
F().C = subtraction > 0xff;
}
void callAddress(uint16_t address) {
register16_t saved = pc;
saved.word += 2;
pushWord(saved);
pc.word = address;
}
void restart(uint8_t position) {
uint16_t address = position << 3;
pushWord(pc);
pc.word = address;
}
void jmpConditional(int conditional) {
auto destination = fetchWord();
if (conditional)
pc.word = destination;
}
void callConditional(int condition) {
if (condition) {
call();
cycles += 6;
}
else {
pc.word += 2;
}
}
void returnConditional(int condition) {
if (condition) {
ret();
cycles += 6;
}
}
void anda(uint8_t value) {
F().AC = (((A() | value) & 0x8) != 0);
F().C = false;
adjustSZP(A() &= value);
}
void ora(uint8_t value) {
F().AC = F().C = false;
adjustSZP(A() |= value);
}
void xra(uint8_t value) {
F().AC = F().C = false;
adjustSZP(A() ^= value);
}
void add(uint8_t value, int carry = 0) {
register16_t sum;
sum.word = A() + value + carry;
adjustAuxiliaryCarryAdd(value, sum.word);
A() = sum.low;
F().C = sum.word > 0xff;
adjustSZP(A());
}
void adc(uint8_t value) {
add(value, F().C);
}
void dad(uint16_t value) {
uint32_t sum = HL().word + value;
F().C = sum > 0xffff;
HL().word = (uint16_t)sum;
}
void sub(uint8_t value, int carry = 0) {
register16_t difference;
difference.word = A() - value - carry;
adjustAuxiliaryCarrySub(value, difference.word);
A() = difference.low;
F().C = difference.word > 0xff;
adjustSZP(A());
}
void sbb(uint8_t value) {
sub(value, F().C);
}
void mov_m_r(uint8_t value) {
m_memory.set(HL().word, value);
}
uint8_t mov_r_m() {
return m_memory.get(HL().word);
}
//
void ___();
// Move, load, and store
void mov_a_a() { }
void mov_a_b() { A() = B(); }
void mov_a_c() { A() = C(); }
void mov_a_d() { A() = D(); }
void mov_a_e() { A() = E(); }
void mov_a_h() { A() = H(); }
void mov_a_l() { A() = L(); }
void mov_b_a() { B() = A(); }
void mov_b_b() { }
void mov_b_c() { B() = C(); }
void mov_b_d() { B() = D(); }
void mov_b_e() { B() = E(); }
void mov_b_h() { B() = H(); }
void mov_b_l() { B() = L(); }
void mov_c_a() { C() = A(); }
void mov_c_b() { C() = B(); }
void mov_c_c() { }
void mov_c_d() { C() = D(); }
void mov_c_e() { C() = E(); }
void mov_c_h() { C() = H(); }
void mov_c_l() { C() = L(); }
void mov_d_a() { D() = A(); }
void mov_d_b() { D() = B(); }
void mov_d_c() { D() = C(); }
void mov_d_d() { }
void mov_d_e() { D() = E(); }
void mov_d_h() { D() = H(); }
void mov_d_l() { D() = L(); }
void mov_e_a() { E() = A(); }
void mov_e_b() { E() = B(); }
void mov_e_c() { E() = C(); }
void mov_e_d() { E() = D(); }
void mov_e_e() { }
void mov_e_h() { E() = H(); }
void mov_e_l() { E() = L(); }
void mov_h_a() { H() = A(); }
void mov_h_b() { H() = B(); }
void mov_h_c() { H() = C(); }
void mov_h_d() { H() = D(); }
void mov_h_e() { H() = E(); }
void mov_h_h() { }
void mov_h_l() { H() = L(); }
void mov_l_a() { L() = A(); }
void mov_l_b() { L() = B(); }
void mov_l_c() { L() = C(); }
void mov_l_d() { L() = D(); }
void mov_l_e() { L() = E(); }
void mov_l_h() { L() = H(); }
void mov_l_l() { }
void mov_m_a() { mov_m_r(A()); }
void mov_m_b() { mov_m_r(B()); }
void mov_m_c() { mov_m_r(C()); }
void mov_m_d() { mov_m_r(D()); }
void mov_m_e() { mov_m_r(E()); }
void mov_m_h() { mov_m_r(H()); }
void mov_m_l() { mov_m_r(L()); }
void mov_a_m() { A() = mov_r_m(); }
void mov_b_m() { B() = mov_r_m(); }
void mov_c_m() { C() = mov_r_m(); }
void mov_d_m() { D() = mov_r_m(); }
void mov_e_m() { E() = mov_r_m(); }
void mov_h_m() { H() = mov_r_m(); }
void mov_l_m() { L() = mov_r_m(); }
void mvi_a() { A() = fetchByte(); }
void mvi_b() { B() = fetchByte(); }
void mvi_c() { C() = fetchByte(); }
void mvi_d() { D() = fetchByte(); }
void mvi_e() { E() = fetchByte(); }
void mvi_h() { H() = fetchByte(); }
void mvi_l() { L() = fetchByte(); }
void mvi_m() {
auto data = fetchByte();
m_memory.set(HL().word, data);
}
void lxi_b() { BC().word = fetchWord(); }
void lxi_d() { DE().word = fetchWord(); }
void lxi_h() { HL().word = fetchWord(); }
void stax_b() { m_memory.set(BC().word, A()); }
void stax_d() { m_memory.set(DE().word, A()); }
void ldax_b() { A() = m_memory.get(BC().word); }
void ldax_d() { A() = m_memory.get(DE().word); }
void sta() {
auto destination = fetchWord();
m_memory.set(destination, A());
}
void lda() {
auto source = fetchWord();
A() = m_memory.get(source);
}
void shld() {
auto destination = fetchWord();
setWord(destination, HL());
}
void lhld() {
HL() = getWord(fetchWord());
}
void xchg() {
std::swap(DE(), HL());
}
// stack ops
void push_b() { pushWord(BC()); }
void push_d() { pushWord(DE()); }
void push_h() { pushWord(HL()); }
void push_psw() {
register16_t pair;
pair.low = F();
pair.high = A();
pushWord(pair);
}
void pop_b() { BC() = popWord(); }
void pop_d() { DE() = popWord(); }
void pop_h() { HL() = popWord(); }
void pop_psw() {
auto af = popWord();
A() = af.high;
F() = af.low;
}
void xhtl() {
auto tos = getWord(sp.word);
setWord(sp.word, HL());
HL() = tos;
}
void sphl() {
sp = HL();
}
void lxi_sp() {
sp.word = fetchWord();
}
void inx_sp() { ++sp.word; }
void dcx_sp() { --sp.word; }
// jump
void jmp() { jmpConditional(true); }
void jc() { jmpConditional(F().C); }
void jnc() { jmpConditional(!F().C); }
void jz() { jmpConditional(F().Z); }
void jnz() { jmpConditional(!F().Z); }
void jpe() { jmpConditional(F().P); }
void jpo() { jmpConditional(!F().P); }
void jm() { jmpConditional(F().S); }
void jp() { jmpConditional(!F().S); }
void pchl() {
pc = HL();
}
// call
void call() {
auto destination = getWord(pc.word);
callAddress(destination.word);
}
void cc() { callConditional(F().C); }
void cnc() { callConditional(!F().C); }
void cpe() { callConditional(F().P); }
void cpo() { callConditional(!F().P); }
void cz() { callConditional(F().Z); }
void cnz() { callConditional(!F().Z); }
void cm() { callConditional(F().S); }
void cp() { callConditional(!F().S); }
// return
void ret() {
pc = popWord();
}
void rc() { returnConditional(F().C); }
void rnc() { returnConditional(!F().C); }
void rz() { returnConditional(F().Z); }
void rnz() { returnConditional(!F().Z); }
void rpe() { returnConditional(F().P); }
void rpo() { returnConditional(!F().P); }
void rm() { returnConditional(F().S); }
void rp() { returnConditional(!F().S); }
// restart
void rst_0() { restart(0); }
void rst_1() { restart(1); }
void rst_2() { restart(2); }
void rst_3() { restart(3); }
void rst_4() { restart(4); }
void rst_5() { restart(5); }
void rst_6() { restart(6); }
void rst_7() { restart(7); }
// increment and decrement
void inr_a() { postIncrement(++A()); }
void inr_b() { postIncrement(++B()); }
void inr_c() { postIncrement(++C()); }
void inr_d() { postIncrement(++D()); }
void inr_e() { postIncrement(++E()); }
void inr_h() { postIncrement(++H()); }
void inr_l() { postIncrement(++L()); }
void inr_m() {
auto value = m_memory.get(HL().word);
postIncrement(++value);
m_memory.set(HL().word, value);
}
void dcr_a() { postDecrement(--A()); }
void dcr_b() { postDecrement(--B()); }
void dcr_c() { postDecrement(--C()); }
void dcr_d() { postDecrement(--D()); }
void dcr_e() { postDecrement(--E()); }
void dcr_h() { postDecrement(--H()); }
void dcr_l() { postDecrement(--L()); }
void dcr_m() {
auto value = m_memory.get(HL().word);
postDecrement(--value);
m_memory.set(HL().word, value);
}
void inx_b() { ++BC().word; }
void inx_d() { ++DE().word; }
void inx_h() { ++HL().word; }
void dcx_b() { --BC().word; }
void dcx_d() { --DE().word; }
void dcx_h() { --HL().word; }
// add
void add_a() { add(A()); }
void add_b() { add(B()); }
void add_c() { add(C()); }
void add_d() { add(D()); }
void add_e() { add(E()); }
void add_h() { add(H()); }
void add_l() { add(L()); }
void add_m() {
auto value = m_memory.get(HL().word);
add(value);
}
void adi() { add(fetchByte()); }
void adc_a() { adc(A()); }
void adc_b() { adc(B()); }
void adc_c() { adc(C()); }
void adc_d() { adc(D()); }
void adc_e() { adc(E()); }
void adc_h() { adc(H()); }
void adc_l() { adc(L()); }
void adc_m() {
auto value = m_memory.get(HL().word);
adc(value);
}
void aci() { adc(fetchByte()); }
void dad_b() { dad(BC().word); }
void dad_d() { dad(DE().word); }
void dad_h() { dad(HL().word); }
void dad_sp() { dad(sp.word); }
// subtract
void sub_a() { sub(A()); }
void sub_b() { sub(B()); }
void sub_c() { sub(C()); }
void sub_d() { sub(D()); }
void sub_e() { sub(E()); }
void sub_h() { sub(H()); }
void sub_l() { sub(L()); }
void sub_m() {
auto value = m_memory.get(HL().word);
sub(value);
}
void sbb_a() { sbb(A()); }
void sbb_b() { sbb(B()); }
void sbb_c() { sbb(C()); }
void sbb_d() { sbb(D()); }
void sbb_e() { sbb(E()); }
void sbb_h() { sbb(H()); }
void sbb_l() { sbb(L()); }
void sbb_m() {
auto value = m_memory.get(HL().word);
sbb(value);
}
void sbi() {
auto value = fetchByte();
sbb(value);
}
void sui() {
auto value = fetchByte();
sub(value);
}
// logical
void ana_a() { anda(A()); }
void ana_b() { anda(B()); }
void ana_c() { anda(C()); }
void ana_d() { anda(D()); }
void ana_e() { anda(E()); }
void ana_h() { anda(H()); }
void ana_l() { anda(L()); }
void ana_m() {
auto value = m_memory.get(HL().word);
anda(value);
}
void ani() { anda(fetchByte()); }
void xra_a() { xra(A()); }
void xra_b() { xra(B()); }
void xra_c() { xra(C()); }
void xra_d() { xra(D()); }
void xra_e() { xra(E()); }
void xra_h() { xra(H()); }
void xra_l() { xra(L()); }
void xra_m() {
auto value = m_memory.get(HL().word);
xra(value);
}
void xri() { xra(fetchByte()); }
void ora_a() { ora(A()); }
void ora_b() { ora(B()); }
void ora_c() { ora(C()); }
void ora_d() { ora(D()); }
void ora_e() { ora(E()); }
void ora_h() { ora(H()); }
void ora_l() { ora(L()); }
void ora_m() {
auto value = m_memory.get(HL().word);
ora(value);
}
void ori() { ora(fetchByte()); }
void cmp_a() { compare(A()); }
void cmp_b() { compare(B()); }
void cmp_c() { compare(C()); }
void cmp_d() { compare(D()); }
void cmp_e() { compare(E()); }
void cmp_h() { compare(H()); }
void cmp_l() { compare(L()); }
void cmp_m() {
auto value = m_memory.get(HL().word);
compare(value);
}
void cpi() { compare(fetchByte()); }
// rotate
void rlc() {
auto carry = A() & 0x80;
A() <<= 1;
A() |= carry >> 7;
F().C = carry != 0;
}
void rrc() {
auto carry = A() & 1;
A() >>= 1;
A() |= carry << 7;
F().C = carry != 0;
}
void ral() {
auto carry = A() & 0x80;
A() <<= 1;
A() |= (uint8_t)F().C;
F().C = carry != 0;
}
void rar() {
auto carry = A() & 1;
A() >>= 1;
A() |= F().C << 7;
F().C = carry != 0;
}
// specials
void cma() { A() ^= 0xff; }
void stc() { F().C = true; }
void cmc() { F().C = !F().C; }
void daa() {
auto carry = F().C;
uint8_t addition = 0;
if (F().AC || lowNibble(A()) > 9) {
addition = 0x6;
}
if (F().C || highNibble(A()) > 9 || (highNibble(A()) >= 9 && lowNibble(A()) > 9)) {
addition |= 0x60;
carry = true;
}
add(addition);
F().C = carry;
}
// input/output
void out() { m_ports.write(fetchByte(), A()); }
void in() { A() = m_ports.read(fetchByte()); }
// control
void ei() { enableInterrupts(); }
void di() { disableInterrupts(); }
void nop() {}
void hlt() { m_halted = true; }
};
}

View File

@ -0,0 +1,18 @@
#pragma once
#include <cstdint>
namespace EightBit {
class PortEventArgs {
public:
PortEventArgs(uint8_t port)
: m_port(port) {}
uint8_t getPort() const {
return m_port;
}
private:
uint8_t m_port;
};
}

24
Intel8080/inc/Profiler.h Normal file
View File

@ -0,0 +1,24 @@
#pragma once
#include <array>
#include <cstdint>
namespace EightBit {
class Profiler {
public:
Profiler();
~Profiler();
void addInstruction(uint8_t instruction);
void addAddress(uint16_t address);
void dump() const;
private:
std::array<uint64_t, 0x100> m_instructions;
std::array<uint64_t, 0x10000> m_addresses;
void dumpInstructionProfiles() const;
void dumpAddressProfiles() const;
};
}

View File

@ -0,0 +1,72 @@
#pragma once
#include <string>
#include <cstdint>
namespace EightBit {
struct StatusFlags {
bool S;
bool Z;
bool AC;
bool P;
bool C;
enum StatusBits {
Sign = 0x80, // S
Zero = 0x40, // Z
AuxiliaryCarry = 0x10, // AC
Parity = 0x4, // Z
Carry = 0x1, // S
};
StatusFlags(uint8_t value) {
S = (value & StatusBits::Sign) != 0;
Z = (value & StatusBits::Zero) != 0;
AC = (value & StatusBits::AuxiliaryCarry) != 0;
P = (value & StatusBits::Parity) != 0;
C = (value & StatusBits::Carry) != 0;
}
operator uint8_t() const {
uint8_t flags = 0;
if (S)
flags |= StatusBits::Sign;
if (Z)
flags |= StatusBits::Zero;
flags &= ~0x20; // Reserved off
if (AC)
flags |= StatusBits::AuxiliaryCarry;
flags &= ~0x8; // Reserved off
if (P)
flags |= StatusBits::Parity;
flags |= 0x2; // Reserved on
if (C)
flags |= StatusBits::Carry;
return flags;
}
operator std::string() const {
std::string returned;
returned += S ? "S" : "-";
returned += Z ? "Z" : "-";
returned += "0";
returned += AC ? "A" : "-";
returned += "0";
returned += P ? "P" : "-";
returned += "1";
returned += C ? "C" : "-";
return returned;
}
};
}

View File

@ -0,0 +1,112 @@
#include "stdafx.h"
#include "Disassembler.h"
#include <sstream>
#include <iomanip>
#include <bitset>
#include "Memory.h"
#include "Intel8080.h"
#include "StatusFlags.h"
EightBit::Disassembler::Disassembler() {
}
std::string EightBit::Disassembler::state(Intel8080& cpu) {
auto pc = cpu.getProgramCounter();
auto sp = cpu.getStackPointer();
auto a = cpu.A();
auto f = cpu.F();
auto b = cpu.B();
auto c = cpu.C();
auto d = cpu.D();
auto e = cpu.E();
auto h = cpu.H();
auto l = cpu.L();
std::ostringstream output;
output
<< "PC=" << hex(pc.word)
<< " "
<< "SP=" << hex(sp.word)
<< " " << "A=" << hex(a) << " " << "F=" << (std::string)f
<< " " << "B=" << hex(b) << " " << "C=" << hex(c)
<< " " << "D=" << hex(d) << " " << "E=" << hex(e)
<< " " << "H=" << hex(h) << " " << "L=" << hex(l);
return output.str();
}
std::string EightBit::Disassembler::disassemble(Intel8080& cpu) {
const auto& memory = cpu.getMemory();
auto pc = cpu.getProgramCounter();
auto opcode = memory.peek(pc.word);
const auto& instruction = cpu.getInstructions()[opcode];
std::ostringstream output;
// hex opcode
output << hex(opcode);
// hex raw operand
switch (instruction.mode) {
case Intel8080::Immediate:
output << hex(memory.peek(pc.word + 1));
break;
case Intel8080::Absolute:
output << hex(memory.peek(pc.word + 1));
output << hex(memory.peek(pc.word + 2));
break;
default:
break;
}
output << "\t";
// base disassembly
output << instruction.disassembly;
// disassembly operand
switch (instruction.mode) {
case Intel8080::Immediate:
output << hex(memory.peek(pc.word + 1));
break;
case Intel8080::Absolute:
output << hex(cpu.getWord(pc.word + 1).word);
break;
default:
break;
}
return output.str();
}
std::string EightBit::Disassembler::hex(uint8_t value) {
std::ostringstream output;
output << std::hex << std::setw(2) << std::setfill('0') << (int)value;
return output.str();
}
std::string EightBit::Disassembler::hex(uint16_t value) {
std::ostringstream output;
output << std::hex << std::setw(4) << std::setfill('0') << (int)value;
return output.str();
}
std::string EightBit::Disassembler::binary(uint8_t value) {
std::ostringstream output;
output << std::bitset<8>(value);
return output.str();
}
std::string EightBit::Disassembler::invalid(uint8_t value) {
std::ostringstream output;
output << "Invalid instruction: " << hex(value) << "(" << binary(value) << ")";
return output.str();
}

View File

@ -0,0 +1,34 @@
#include "stdafx.h"
#include "InputOutput.h"
EightBit::InputOutput::InputOutput() {
}
uint8_t EightBit::InputOutput::readInputPort(uint8_t port) {
OnReadingPort(port);
auto value = input[port];
OnReadPort(port);
return value;
}
void EightBit::InputOutput::writeOutputPort(uint8_t port, uint8_t value) {
OnWritingPort(port);
output[port] = value;
OnWrittenPort(port);
}
void EightBit::InputOutput::OnReadingPort(uint8_t port) {
ReadingPort.fire(PortEventArgs(port));
}
void EightBit::InputOutput::OnReadPort(uint8_t port) {
ReadPort.fire(PortEventArgs(port));
}
void EightBit::InputOutput::OnWritingPort(uint8_t port) {
WritingPort.fire(PortEventArgs(port));
}
void EightBit::InputOutput::OnWrittenPort(uint8_t port) {
WrittenPort.fire(PortEventArgs(port));
}

View File

@ -0,0 +1,83 @@
#include "stdafx.h"
#include "Intel8080.h"
#include "Memory.h"
#include "Disassembler.h"
EightBit::Intel8080::Intel8080(Memory& memory, InputOutput& ports)
: Processor(memory),
a(0),
f(0),
m_interrupt(false) {
bc.word = de.word = hl.word = 0;
installInstructions();
}
EightBit::Intel8080::Instruction EightBit::Intel8080::INS(instruction_t method, AddressingMode mode, std::string disassembly, int cycles) {
Intel8080::Instruction returnValue;
returnValue.vector = method;
returnValue.mode = mode;
returnValue.disassembly = disassembly;
returnValue.count = cycles;
return returnValue;
}
EightBit::Intel8080::Instruction EightBit::Intel8080::UNKNOWN() {
Intel8080::Instruction returnValue;
returnValue.vector = std::bind(&Intel8080::___, this);
returnValue.mode = Unknown;
returnValue.disassembly = "";
returnValue.count = 0;
return returnValue;
}
#define BIND(method) std::bind(&Intel8080:: method, this)
void EightBit::Intel8080::installInstructions() {
instructions = {
//// 0 1 2 3 4 5 6 7 8 9 A B C D E F
/* 0 */ INS(BIND(nop), Implied, "NOP", 4), INS(BIND(lxi_b), Absolute, "LXI B,", 10), INS(BIND(stax_b), Implied, "STAX B", 7), INS(BIND(inx_b), Implied, "INX B", 5), INS(BIND(inr_b), Implied, "INR B", 5), INS(BIND(dcr_b), Implied, "DCR B", 5), INS(BIND(mvi_b), Immediate, "MVI B,", 7), INS(BIND(rlc), Implied, "RLC", 4), UNKNOWN(), INS(BIND(dad_b), Implied, "DAD B", 10), INS(BIND(ldax_b), Implied, "LDAX B", 7), INS(BIND(dcx_b), Implied, "DCX B", 5), INS(BIND(inr_c), Implied, "INR C", 5), INS(BIND(dcr_c), Implied, "DCR C", 5), INS(BIND(mvi_c), Immediate, "MVI C,", 7), INS(BIND(rrc), Implied, "RRC", 4), // 0
/* 1 */ UNKNOWN(), INS(BIND(lxi_d), Absolute, "LXI D,", 10), INS(BIND(stax_d), Implied, "STAX D", 7), INS(BIND(inx_d), Implied, "INX D", 5), INS(BIND(inr_d), Implied, "INR D", 5), INS(BIND(dcr_d), Implied, "DCR D", 5), INS(BIND(mvi_d), Immediate, "MVI D,", 7), INS(BIND(ral), Implied, "RAL", 4), UNKNOWN(), INS(BIND(dad_d), Implied, "DAD D", 10), INS(BIND(ldax_d), Implied, "LDAX D", 7), INS(BIND(dcx_d), Implied, "DCX D", 5), INS(BIND(inr_e), Implied, "INR E", 5), INS(BIND(dcr_e), Implied, "DCR E", 5), INS(BIND(mvi_e), Immediate, "MVI E,", 7), INS(BIND(rar), Implied, "RAR", 4), // 1
/* 2 */ UNKNOWN(), INS(BIND(lxi_h), Absolute, "LXI H,", 10), INS(BIND(shld), Absolute, "SHLD", 16), INS(BIND(inx_h), Implied, "INX H", 5), INS(BIND(inr_h), Implied, "INR H", 5), INS(BIND(dcr_h), Implied, "DCR H", 5), INS(BIND(mvi_h), Immediate, "MVI H,",7), INS(BIND(daa), Implied, "DAA", 4), UNKNOWN(), INS(BIND(dad_h), Implied, "DAD H", 10), INS(BIND(lhld), Absolute, "LHLD ", 16), INS(BIND(dcx_h), Implied, "DCX H", 5), INS(BIND(inr_l), Implied, "INR L", 5), INS(BIND(dcr_l), Implied, "DCR L", 5), INS(BIND(mvi_l), Immediate, "MVI L,", 7), INS(BIND(cma), Implied, "CMA", 4), // 2
/* 3 */ UNKNOWN(), INS(BIND(lxi_sp), Absolute, "LXI SP,", 10), INS(BIND(sta), Absolute, "STA ", 13), INS(BIND(inx_sp), Implied, "INX SP", 5), INS(BIND(inr_m), Implied, "INR M", 10), INS(BIND(dcr_m), Implied, "DCR M", 10), INS(BIND(mvi_m), Immediate, "MVI M,", 10), INS(BIND(stc), Implied, "STC", 4), UNKNOWN(), INS(BIND(dad_sp), Implied, "DAD SP", 10), INS(BIND(lda), Absolute, "LDA ", 13), INS(BIND(dcx_sp), Implied, "DCX SP", 5), INS(BIND(inr_a), Implied, "INR A", 5), INS(BIND(dcr_a), Implied, "DCR A", 5), INS(BIND(mvi_a), Immediate, "MVI A,", 7), INS(BIND(cmc), Implied, "CMC", 4), // 3
/* 4 */ INS(BIND(mov_b_b), Implied, "MOV B,B", 5), INS(BIND(mov_b_c), Implied, "MOV B,C", 5), INS(BIND(mov_b_d), Implied, "MOV B,D", 5), INS(BIND(mov_b_e), Implied, "MOV B,E", 5), INS(BIND(mov_b_h), Implied, "MOV B,H", 5), INS(BIND(mov_b_l), Implied, "MOV B,L", 5), INS(BIND(mov_b_m), Implied, "MOV B,M", 7), INS(BIND(mov_b_a), Implied, "MOV B,A", 5), INS(BIND(mov_c_b), Implied, "MOV C,B", 5), INS(BIND(mov_c_c), Implied, "MOV C,C", 5), INS(BIND(mov_c_d), Implied, "MOV C,D", 5), INS(BIND(mov_c_e), Implied, "MOV C,E", 5), INS(BIND(mov_c_h), Implied, "MOV C,H", 5), INS(BIND(mov_c_l), Implied, "MOV C,L", 5), INS(BIND(mov_c_m), Implied, "MOV C,M", 7), INS(BIND(mov_c_a), Implied, "MOV C,A", 5), // 4
/* 5 */ INS(BIND(mov_d_b), Implied, "MOV D,B", 5), INS(BIND(mov_d_c), Implied, "MOV D,C", 5), INS(BIND(mov_d_d), Implied, "MOV D,D", 5), INS(BIND(mov_d_e), Implied, "MOV D,E", 5), INS(BIND(mov_d_h), Implied, "MOV D,H", 5), INS(BIND(mov_d_l), Implied, "MOV D,L", 5), INS(BIND(mov_d_m), Implied, "MOV D,M", 7), INS(BIND(mov_d_a), Implied, "MOV D,A", 5), INS(BIND(mov_e_b), Implied, "MOV E,B", 5), INS(BIND(mov_e_c), Implied, "MOV E,C", 5), INS(BIND(mov_e_d), Implied, "MOV E,D", 5), INS(BIND(mov_e_e), Implied, "MOV E,E", 5), INS(BIND(mov_e_h), Implied, "MOV E,H", 5), INS(BIND(mov_e_l), Implied, "MOV E,L", 5), INS(BIND(mov_e_m), Implied, "MOV E,M", 7), INS(BIND(mov_e_a), Implied, "MOV E,A", 5), // 5
/* 6 */ INS(BIND(mov_h_b), Implied, "MOV H,B", 5), INS(BIND(mov_h_c), Implied, "MOV H,C", 5), INS(BIND(mov_h_d), Implied, "MOV H,D", 5), INS(BIND(mov_h_e), Implied, "MOV H,E", 5), INS(BIND(mov_h_h), Implied, "MOV H,H", 5), INS(BIND(mov_h_l), Implied, "MOV H,L", 5), INS(BIND(mov_h_m), Implied, "MOV H,M", 7), INS(BIND(mov_h_a), Implied, "MOV H,A", 5), INS(BIND(mov_l_b), Implied, "MOV L,B", 5), INS(BIND(mov_l_c), Implied, "MOV L,C", 5), INS(BIND(mov_l_d), Implied, "MOV L,D", 5), INS(BIND(mov_l_e), Implied, "MOV L,E", 5), INS(BIND(mov_l_h), Implied, "MOV L,H", 5), INS(BIND(mov_l_l), Implied, "MOV L,L", 5), INS(BIND(mov_l_m), Implied, "MOV L,M", 7), INS(BIND(mov_l_a), Implied, "MOV L,A", 5), // 6
/* 7 */ INS(BIND(mov_m_b), Implied, "MOV M,B", 7), INS(BIND(mov_m_c), Implied, "MOV M,C", 7), INS(BIND(mov_m_d), Implied, "MOV M,D", 7), INS(BIND(mov_m_e), Implied, "MOV M,E", 7), INS(BIND(mov_m_h), Implied, "MOV M,H", 7), INS(BIND(mov_m_l), Implied, "MOV M,L", 7), INS(BIND(hlt), Implied, "HLT", 7), INS(BIND(mov_m_a), Implied, "MOV M,A", 7), INS(BIND(mov_a_b), Implied, "MOV A,B", 5), INS(BIND(mov_a_c), Implied, "MOV A,C", 5), INS(BIND(mov_a_d), Implied, "MOV A,D", 5), INS(BIND(mov_a_e), Implied, "MOV A,E", 5), INS(BIND(mov_a_h), Implied, "MOV A,H", 5), INS(BIND(mov_a_l), Implied, "MOV A,L", 5), INS(BIND(mov_a_m), Implied, "MOV A,M", 7), INS(BIND(mov_a_a), Implied, "MOV A,A", 5), // 7
/* 8 */ INS(BIND(add_b), Implied, "ADD B", 4), INS(BIND(add_c), Implied, "ADD C", 4), INS(BIND(add_d), Implied, "ADD D", 4), INS(BIND(add_e), Implied, "ADD E", 4), INS(BIND(add_h), Implied, "ADD H", 4), INS(BIND(add_l), Implied, "ADD L", 4), INS(BIND(add_m), Implied, "ADD M", 7), INS(BIND(add_a), Implied, "ADD A", 4), INS(BIND(adc_b), Implied, "ADC B", 4), INS(BIND(adc_c), Implied, "ADC C", 4), INS(BIND(adc_d), Implied, "ADC D", 4), INS(BIND(adc_e), Implied, "ADC E", 4), INS(BIND(adc_h), Implied, "ADC H", 4), INS(BIND(adc_l), Implied, "ADC L", 4), INS(BIND(adc_m), Implied, "ADC M", 4), INS(BIND(adc_a), Implied, "ADC A", 4), // 8
/* 9 */ INS(BIND(sub_b), Implied, "SUB B", 4), INS(BIND(sub_c), Implied, "SUB C", 4), INS(BIND(sub_d), Implied, "SUB D", 4), INS(BIND(sub_e), Implied, "SUB E", 4), INS(BIND(sub_h), Implied, "SUB H", 4), INS(BIND(sub_l), Implied, "SUB L", 4), INS(BIND(sub_m), Implied, "SUB M", 7), INS(BIND(sub_a), Implied, "SUB A", 4), INS(BIND(sbb_b), Implied, "SBB B", 4), INS(BIND(sbb_c), Implied, "SBB C", 4), INS(BIND(sbb_d), Implied, "SBB D", 4), INS(BIND(sbb_e), Implied, "SBB E", 4), INS(BIND(sbb_h), Implied, "SBB H", 4), INS(BIND(sbb_l), Implied, "SBB L", 4), INS(BIND(sbb_m), Implied, "SBB M", 4), INS(BIND(sbb_a), Implied, "SBB A", 4), // 9
/* A */ INS(BIND(ana_b), Implied, "ANA B", 4), INS(BIND(ana_c), Implied, "ANA C", 4), INS(BIND(ana_d), Implied, "ANA D", 4), INS(BIND(ana_e), Implied, "ANA E", 4), INS(BIND(ana_h), Implied, "ANA H", 4), INS(BIND(ana_l), Implied, "ANA L", 4), INS(BIND(ana_m), Implied, "ANA M", 7), INS(BIND(ana_a), Implied, "ANA A", 4), INS(BIND(xra_b), Implied, "XRA B", 4), INS(BIND(xra_c), Implied, "XRA C", 4), INS(BIND(xra_d), Implied, "XRA D", 4), INS(BIND(xra_e), Implied, "XRA E", 4), INS(BIND(xra_h), Implied, "XRA H", 4), INS(BIND(xra_l), Implied, "XRA L", 4), INS(BIND(xra_m), Implied, "XRA M", 4), INS(BIND(xra_a), Implied, "XRA A", 4), // A
/* B */ INS(BIND(ora_b), Implied, "ORA B", 4), INS(BIND(ora_c), Implied, "ORA C", 4), INS(BIND(ora_d), Implied, "ORA D", 4), INS(BIND(ora_e), Implied, "ORA E", 4), INS(BIND(ora_h), Implied, "ORA H", 4), INS(BIND(ora_l), Implied, "ORA L", 4), INS(BIND(ora_m), Implied, "ORA M", 7), INS(BIND(ora_a), Implied, "ORA A", 4), INS(BIND(cmp_b), Implied, "CMP B", 4), INS(BIND(cmp_c), Implied, "CMP C", 4), INS(BIND(cmp_d), Implied, "CMP D", 4), INS(BIND(cmp_e), Implied, "CMP E", 4), INS(BIND(cmp_h), Implied, "CMP H", 4), INS(BIND(cmp_l), Implied, "CMP L", 4), INS(BIND(cmp_m), Implied, "CMP M", 4), INS(BIND(cmp_a), Implied, "CMP A", 4), // B
/* C */ INS(BIND(rnz), Implied, "RNZ", 5), INS(BIND(pop_b), Implied, "POP B", 10), INS(BIND(jnz), Absolute, "JNZ ", 10), INS(BIND(jmp), Absolute, "JMP ", 10), INS(BIND(cnz), Absolute, "CNZ ", 11), INS(BIND(push_b), Implied, "PUSH B", 11), INS(BIND(adi), Immediate, "ADI ", 7), INS(BIND(rst_0), Implied, "RST 0", 11), INS(BIND(rz), Implied, "RZ", 11), INS(BIND(ret), Implied, "RET", 10), INS(BIND(jz), Absolute, "JZ ", 10), UNKNOWN(), INS(BIND(cz), Absolute, "CZ ", 11), INS(BIND(call), Absolute, "CALL ", 17), INS(BIND(aci), Immediate, "ACI ", 7), INS(BIND(rst_1), Implied, "RST 1", 11), // C
/* D */ INS(BIND(rnc), Implied, "RNC", 5), INS(BIND(pop_d), Implied, "POP D", 10), INS(BIND(jnc), Absolute, "JNC ", 10), INS(BIND(out), Immediate, "OUT ", 10), INS(BIND(cnc), Absolute, "CNC ", 11), INS(BIND(push_d), Implied, "PUSH D", 11), INS(BIND(sui), Immediate, "SUI ", 7), INS(BIND(rst_2), Implied, "RST 2", 11), INS(BIND(rc), Implied, "RC", 11), UNKNOWN(), INS(BIND(jc), Absolute, "JC ", 10), INS(BIND(in), Immediate, "IN ", 10), INS(BIND(cc), Absolute, "CC ", 11), UNKNOWN(), INS(BIND(sbi), Immediate, "SBI ", 7), INS(BIND(rst_3), Implied, "RST 3", 11), // D
/* E */ INS(BIND(rpo), Implied, "RPO", 5), INS(BIND(pop_h), Implied, "POP H", 10), INS(BIND(jpo), Absolute, "JPO ", 10), INS(BIND(xhtl), Implied, "XHTL", 18), INS(BIND(cpo), Absolute, "CPO ", 11), INS(BIND(push_h), Implied, "PUSH H", 11), INS(BIND(ani), Immediate, "ANI ", 7), INS(BIND(rst_4), Implied, "RST 4", 11), INS(BIND(rpe), Implied, "RPE", 11), INS(BIND(pchl), Implied, "PCHL", 5), INS(BIND(jpe), Absolute, "JPE ", 10), INS(BIND(xchg), Implied, "XCHG", 4), INS(BIND(cpe), Absolute, "CPE ", 11), UNKNOWN(), INS(BIND(xri), Immediate, "XRI ", 7), INS(BIND(rst_5), Implied, "RST 5", 11), // E
/* F */ INS(BIND(rp), Implied, "RP", 5), INS(BIND(pop_psw), Implied, "POP PSW", 10), INS(BIND(jp), Absolute, "JP ", 10), INS(BIND(di), Implied, "DI ", 4), INS(BIND(cp), Absolute, "CP ", 11), INS(BIND(push_psw), Implied, "PUSH PSW", 11), INS(BIND(ori), Immediate, "ORI ", 7), INS(BIND(rst_6), Implied, "RST 6", 11), INS(BIND(rm), Implied, "RM", 11), INS(BIND(sphl), Implied, "SPHL", 5), INS(BIND(jm), Absolute, "JM ", 10), INS(BIND(ei), Implied, "EI", 4), INS(BIND(cm), Absolute, "CM ", 11), UNKNOWN(), INS(BIND(cpi), Immediate, "CPI ", 7), INS(BIND(rst_7), Implied, "RST 7", 11), // F
};
}
void EightBit::Intel8080::initialise() {
Processor::initialise();
bc.word = de.word = hl.word = 0;
a = f = 0;
}
int EightBit::Intel8080::step() {
ExecutingInstruction.fire(*this);
return execute(fetchByte());
}
int EightBit::Intel8080::execute(uint8_t opcode) {
const auto& instruction = instructions[opcode];
return execute(instruction);
}
//
void EightBit::Intel8080::___() {
auto opcode = m_memory.get(pc.word - 1);
auto message = Disassembler::invalid(opcode);
throw std::domain_error(message);
}

View File

@ -0,0 +1,162 @@
<?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>{93BDC8D8-9F0D-44ED-94FB-1BE6AC4B6BD6}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>Win32Project1</RootNamespace>
<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
<ProjectName>Intel8080</ProjectName>
</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;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<IncludePath>../inc;../../inc;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath>
</PropertyGroup>