From 4c5dbdcb42aeda46186fc1c6595f15d3992afd3b Mon Sep 17 00:00:00 2001 From: Souryo Date: Tue, 10 Jun 2014 16:58:37 -0400 Subject: [PATCH] Initial commit --- .gitattributes | 63 ++++ .gitignore | 156 +++++++++ 6502_functional_test.bin | Bin 0 -> 65536 bytes CPU.cpp | 40 +++ CPU.h | 736 +++++++++++++++++++++++++++++++++++++++ Core.vcxproj | 104 ++++++ Core.vcxproj.filters | 45 +++ NES.sln | 22 ++ ReadMe.txt | 40 +++ Timer.h | 28 ++ main.cpp | 164 +++++++++ stdafx.cpp | 1 + stdafx.h | 26 ++ targetver.h | 8 + 14 files changed, 1433 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 6502_functional_test.bin create mode 100644 CPU.cpp create mode 100644 CPU.h create mode 100644 Core.vcxproj create mode 100644 Core.vcxproj.filters create mode 100644 NES.sln create mode 100644 ReadMe.txt create mode 100644 Timer.h create mode 100644 main.cpp create mode 100644 stdafx.cpp create mode 100644 stdafx.h create mode 100644 targetver.h diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..1ff0c423 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..1bc915c5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,156 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +build/ +[Bb]in/ +[Oo]bj/ + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +!packages/*/build/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml + +# NuGet Packages Directory +## TODO: If you have NuGet Package Restore enabled, uncomment the next line +#packages/ + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + + +#LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml + +# ========================= +# Windows detritus +# ========================= + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac desktop service store files +.DS_Store diff --git a/6502_functional_test.bin b/6502_functional_test.bin new file mode 100644 index 0000000000000000000000000000000000000000..8a20227a6decf69bcdf87155cace7278caa2996a GIT binary patch literal 65536 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 Hf9U>yF)>V1 literal 0 HcmV?d00001 diff --git a/CPU.cpp b/CPU.cpp new file mode 100644 index 00000000..475bb754 --- /dev/null +++ b/CPU.cpp @@ -0,0 +1,40 @@ +#include "stdafx.h" +#include "CPU.h" +#include "Timer.h" + +void Core::Reset() +{ + _state.A = 0; + _state.PC = 0x0400; + _state.SP = 0xFF; + _state.X = 0; + _state.Y = 0; + _state.PS = PSFlags::Zero | PSFlags::Reserved;// | PSFlags::Interrupt; +} + +void Core::Exec() +{ + uint16_t lastPC = 65535; + int executedCount = 0; + std::list pcList; + + Timer timer; + while(true) { + _currentPC = _state.PC; + uint8_t opCode = ReadByte(); + if(_opTable[opCode] != 0) { + (this->*_opTable[opCode])(); + } else { + std::cout << "Invalid opcode: PC:" << _currentPC << std::endl; + } + lastPC = _currentPC; + executedCount++; + + if(executedCount >= 200000000) { + break; + } + } + + std::cout << "Executed:" << executedCount << " in " << timer.GetElapsedMS() << " ms"; +} + diff --git a/CPU.h b/CPU.h new file mode 100644 index 00000000..6e214c0b --- /dev/null +++ b/CPU.h @@ -0,0 +1,736 @@ +#include "stdafx.h" + +namespace PSFlags +{ + enum PSFlags : uint8_t + { + Carry = 0x01, + Zero = 0x02, + Interrupt = 0x04, + Decimal = 0x08, + Break = 0x10, + Reserved = 0x20, + Overflow = 0x40, + Negative = 0x80 + }; +} + +struct State +{ + uint16_t PC; + uint8_t SP; + uint8_t A; + uint8_t X; + uint8_t Y; + uint8_t PS; +}; + +class Core +{ +private: + typedef void(Core::*Func)(); + + Func _opTable[256]; + State _state; + int8_t* _memory; + uint16_t _currentPC; + + inline uint8_t Core::ReadByte() + { + return _memory[_state.PC++]; + } + + uint16_t Core::ReadWord() + { + uint16_t value = (uint16_t)(((uint8_t)_memory[_state.PC] | (((uint8_t)_memory[_state.PC + 1]) << 8))); + _state.PC += 2; + return value; + } + + void ClearFlags(uint8_t flags) + { + _state.PS &= ~flags; + } + + uint16_t lastNegative = 0; + void SetFlags(uint8_t flags) + { + if(flags & PSFlags::Negative) { + lastNegative = _state.PC; + } + _state.PS |= flags; + } + + bool CheckFlag(uint8_t flag) + { + return (_state.PS & flag) == flag; + } + + void SetZeroNegativeFlags(uint8_t value) + { + if(value == 0) { + SetFlags(PSFlags::Zero); + } else if(value & 0x80) { + SetFlags(PSFlags::Negative); + } + } + + void MemoryWrite(uint16_t addr, uint8_t value) + { + //SetZeroNegativeFlags(value); + _memory[addr] = value; + if(addr == 0x200) { + std::cout << "------------------" << std::endl; + std::cout << "TEST NUMBER: " << std::dec << (int)value << std::endl; + std::cout << "------------------" << std::endl; + } else { + //std::cout << "(0x" << std::hex << (short)_currentPC << ") W: 0x" << std::hex << (short)addr << " = 0x" << std::hex << (short)value << std::endl; + } + } + + uint8_t MemoryRead(uint16_t addr) { + //std::cout << "\t\t\t\t(0x" << std::hex << (short)_currentPC << ") R: 0x" << std::hex << (short)addr << " = 0x" << std::hex << (short)_memory[addr] << std::endl; + return _memory[addr]; + } + + uint16_t MemoryReadWord(uint16_t addr) { + return (_memory[addr] | (_memory[addr + 1] << 8)); + } + + void SetRegister(uint8_t ®, int8_t value) { + ClearFlags(PSFlags::Zero | PSFlags::Negative); + SetZeroNegativeFlags(value); + reg = value; + } + + void Push(uint8_t value) { + _memory[SP() + 0x100] = value; + SetSP(SP() - 1); + } + + void Push(uint16_t value) { + Push((uint8_t)(value >> 8)); + Push((uint8_t)value); + } + + uint8_t Pop() { + SetSP(SP() + 1); + int8_t value = _memory[0x100 + SP()]; + return value; + } + + uint16_t PopWord() { + return Pop() | (Pop() << 8); + } + + uint8_t A() { return _state.A; } + void SetA(uint8_t value) { SetRegister(_state.A, value); } + uint8_t X() { return _state.X; } + void SetX(uint8_t value) { SetRegister(_state.X, value); } + uint8_t Y() { return _state.Y; } + void SetY(uint8_t value) { SetRegister(_state.Y, value); } + uint8_t SP() { return _state.SP; } + void SetSP(uint8_t value) { _state.SP = value; } + uint8_t PS() { return _state.PS; } + void SetPS(uint8_t value) { _state.PS = value | PSFlags::Reserved; } + uint16_t PC() { return _state.PC; } + void SetPC(uint16_t value) { _state.PC = value; } + + uint8_t GetImmediate() { return ReadByte(); } + uint8_t GetZero() { return MemoryRead(GetZeroAddr()); } + uint8_t GetZeroAddr() { return ReadByte(); } + + uint8_t GetZeroX() { return MemoryRead(GetZeroXAddr()); } + uint8_t GetZeroXAddr() { return ReadByte() + X(); } + + int8_t GetZeroY() { return MemoryRead(GetZeroYAddr()); } + int8_t GetZeroYAddr() { return ReadByte() + Y(); } + + + int8_t GetAbs() { return MemoryRead(GetAbsAddr()); } + uint16_t GetAbsAddr() { return ReadWord(); } + + int8_t GetAbsX() { return MemoryRead(GetAbsXAddr()); } + uint16_t GetAbsXAddr() { + return ReadWord() + X(); + } + + int8_t GetAbsY() { return MemoryRead(GetAbsYAddr()); } + uint16_t GetAbsYAddr() { + return ReadWord() + Y(); + } + + uint16_t GetInd() { return MemoryReadWord(ReadByte() | (ReadByte() << 8)); } + + int8_t GetIndX() { return MemoryRead(GetIndXAddr()); } + uint16_t GetIndXAddr() { + uint8_t zero = ReadByte() + X(); + //std::cout << (int)zero << std::endl; + uint16_t addr = MemoryRead(zero) | (MemoryRead(zero + 1) << 8); + return addr; + } + + int8_t GetIndY() { return MemoryRead(GetIndYAddr()); } + uint16_t GetIndYAddr() { + uint8_t zero = ReadByte(); + //std::cout << (int)zero << std::endl; + uint16_t addr = MemoryRead(zero) | (MemoryRead(zero + 1) << 8); + return addr + Y(); + } + + + void AND(int8_t value) { SetA(A() & value); } + void XOR(int8_t value) { + SetA(A() ^ value); + } + void OR(int8_t value) { SetA(A() | value); } + + void ADC(uint8_t value) { + uint16_t result = (uint16_t)A() + (uint16_t)value + (CheckFlag(PSFlags::Carry) ? PSFlags::Carry : 0x00); + if(result == 0x100) { + //std::cout << std::hex << (short)A() << " + " << (short)value << (CheckFlag(PSFlags::Carry) ? "(+1) " : "") << " = " << (short)result << std::endl; + } + + ClearFlags(PSFlags::Carry | PSFlags::Negative | PSFlags::Overflow | PSFlags::Zero); + SetZeroNegativeFlags((uint8_t)result); + if(~(A() ^ value) & (A() ^ result) & 0x80) { + SetFlags(PSFlags::Overflow); + } + if(result > 0xFF) { + SetFlags(PSFlags::Carry); + } + SetA((uint8_t)result); + } + + void SBC(int8_t value) { + ADC(value ^ 0xFF); + /*uint8_t result = A() - (value - ~(CheckFlag(PSFlags::Carry) ? PSFlags::Carry : 0x00)); + + ClearFlags(PSFlags::Carry | PSFlags::Negative | PSFlags::Overflow | PSFlags::Zero); + + if (result & 0x80) { + SetFlags(PSFlags::Overflow); + } + + SetA(result);*/ + } + + void CMP(uint8_t reg, uint8_t value) { + ClearFlags(PSFlags::Carry | PSFlags::Negative | PSFlags::Zero); + if(reg >= value) { + SetFlags(PSFlags::Carry); + } + if(reg == value) { + SetFlags(PSFlags::Zero); + } + if(reg < value) { + SetFlags(PSFlags::Negative); + } + } + + void CPA(int8_t value) { CMP(A(), value); } + void CPX(int8_t value) { CMP(X(), value); } + void CPY(int8_t value) { CMP(Y(), value); } + + void INC(uint16_t addr) { + ClearFlags(PSFlags::Negative | PSFlags::Zero); + uint8_t memory = MemoryRead(addr) + 1; + SetZeroNegativeFlags(memory); + MemoryWrite(addr, memory); + } + + void DEC(uint16_t addr) { + ClearFlags(PSFlags::Negative | PSFlags::Zero); + uint8_t memory = MemoryRead(addr) - 1; + SetZeroNegativeFlags(memory); + MemoryWrite(addr, memory); + } + + uint8_t ASL(uint8_t value) + { + ClearFlags(PSFlags::Carry | PSFlags::Negative | PSFlags::Zero); + if(value & 0x80) { + SetFlags(PSFlags::Carry); + } + + uint8_t result = value << 1; + SetZeroNegativeFlags(result); + return result; + } + + uint8_t LSR(uint8_t value) { + ClearFlags(PSFlags::Carry | PSFlags::Negative | PSFlags::Zero); + if(value & 0x01) { + SetFlags(PSFlags::Carry); + } + + uint8_t result = value >> 1; + SetZeroNegativeFlags(result); + return value >> 1; + } + + uint8_t ROL(uint8_t value) { + bool carryFlag = CheckFlag(PSFlags::Carry); + ClearFlags(PSFlags::Carry | PSFlags::Negative | PSFlags::Zero); + + if(value & 0x80) { + SetFlags(PSFlags::Carry); + } + + uint8_t result = (value << 1 | (carryFlag ? 0x01 : 0x00)); + SetZeroNegativeFlags(result); + return result; + } + + uint8_t ROR(uint8_t value) { + bool carryFlag = CheckFlag(PSFlags::Carry); + ClearFlags(PSFlags::Carry | PSFlags::Negative | PSFlags::Zero); + if(value & 0x01) { + SetFlags(PSFlags::Carry); + } + + uint8_t result = (value >> 1 | (carryFlag ? 0x80 : 0x00)); + SetZeroNegativeFlags(result); + return result; + } + + void ASLAddr(uint16_t addr) { + int8_t value = MemoryRead(addr); + MemoryWrite(addr, ASL(value)); + } + + void LSRAddr(uint16_t addr) { + int8_t value = MemoryRead(addr); + MemoryWrite(addr, LSR(value)); + } + + void ROLAddr(uint16_t addr) { + int8_t value = MemoryRead(addr); + MemoryWrite(addr, ROL(value)); + } + + void RORAddr(uint16_t addr) { + int8_t value = MemoryRead(addr); + MemoryWrite(addr, ROR(value)); + } + + void JMP(uint16_t addr) { + _state.PC = addr; + } + + void BranchRelative(bool branch) { + int8_t offset = GetImmediate(); + if(branch) { + SetPC(PC() + offset); + if(_currentPC == PC()) { + std::cout << "Infinite loop at: 0x" << std::hex << (short)_currentPC; + std::cout << std::endl; + Reset(); + } + } + } + +#pragma region OP Codes + void LDA_Imm() { SetA(GetImmediate()); } + void LDA_Zero() { SetA(GetZero()); } + void LDA_ZeroX() { SetA(GetZeroX()); } + void LDA_Abs() { SetA(GetAbs()); } + void LDA_AbsX() { SetA(GetAbsX()); } + void LDA_AbsY() { SetA(GetAbsY()); } + void LDA_IndX() { SetA(GetIndX()); } + void LDA_IndY() { SetA(GetIndY()); } + + void LDX_Imm() { SetX(GetImmediate()); } + void LDX_Zero() { SetX(GetZero()); } + void LDX_ZeroY() { SetX(GetZeroY()); } + void LDX_Abs() { SetX(GetAbs()); } + void LDX_AbsY() { SetX(GetAbsY()); } + + void LDY_Imm() { SetY(GetImmediate()); } + void LDY_Zero() { SetY(GetZero()); } + void LDY_ZeroX() { SetY(GetZeroX()); } + void LDY_Abs() { SetY(GetAbs()); } + void LDY_AbsX() { SetY(GetAbsX()); } + + void STA_Zero() { MemoryWrite(ReadByte(), A()); } + void STA_ZeroX() { MemoryWrite((uint8_t)(ReadByte() + X()), A()); } + void STA_Abs() { MemoryWrite(ReadWord(), A()); } + void STA_AbsX() { MemoryWrite(GetAbsXAddr(), A()); } + void STA_AbsY() { MemoryWrite(GetAbsYAddr(), A()); } + void STA_IndX() { MemoryWrite(GetIndXAddr(), A()); } + void STA_IndY() { MemoryWrite(GetIndYAddr(), A()); } + + void STX_Zero() { MemoryWrite(ReadByte(), X()); } + void STX_ZeroY() { MemoryWrite((uint8_t)(ReadByte() + Y()), X()); } + void STX_Abs() { MemoryWrite(ReadWord(), X()); } + + void STY_Zero() { MemoryWrite(ReadByte(), Y()); } + void STY_ZeroX() { MemoryWrite((uint8_t)(ReadByte() + X()), Y()); } + void STY_Abs() { MemoryWrite(ReadWord(), Y()); } + + void TAX() { SetX(A()); } + void TAY() { SetY(A()); } + void TSX() { SetX(SP()); } + void TXA() { SetA(X()); } + void TXS() { SetSP(X()); } + void TYA() { SetA(Y()); } + + void PHA() { Push(A()); } + void PHP() { + SetFlags(PSFlags::Break); + Push((uint8_t)PS()); + } + void PLA() { SetA(Pop()); } + void PLP() { SetPS(Pop()); } + + void AND_Imm() { AND(GetImmediate()); } + void AND_Zero() { AND(GetZero()); } + void AND_ZeroX() { AND(GetZeroX()); } + void AND_Abs() { AND(GetAbs()); } + void AND_AbsX() { AND(GetAbsX()); } + void AND_AbsY() { AND(GetAbsY()); } + void AND_IndX() { AND(GetIndX()); } + void AND_IndY() { AND(GetIndY()); } + + void EOR_Imm() { XOR(GetImmediate()); } + void EOR_Zero() { XOR(GetZero()); } + void EOR_ZeroX() { XOR(GetZeroX()); } + void EOR_Abs() { XOR(GetAbs()); } + void EOR_AbsX() { XOR(GetAbsX()); } + void EOR_AbsY() { XOR(GetAbsY()); } + void EOR_IndX() { XOR(GetIndX()); } + void EOR_IndY() { XOR(GetIndY()); } + + void ORA_Imm() { OR(GetImmediate()); } + void ORA_Zero() { OR(GetZero()); } + void ORA_ZeroX() { OR(GetZeroX()); } + void ORA_Abs() { OR(GetAbs()); } + void ORA_AbsX() { OR(GetAbsX()); } + void ORA_AbsY() { OR(GetAbsY()); } + void ORA_IndX() { OR(GetIndX()); } + void ORA_IndY() { OR(GetIndY()); } + + void BIT(uint8_t value) { + ClearFlags(PSFlags::Zero | PSFlags::Overflow | PSFlags::Negative); + if((A() & value) == 0) { + SetFlags(PSFlags::Zero); + } + if(value & 0x40) { + SetFlags(PSFlags::Overflow); + } + if(value & 0x80) { + SetFlags(PSFlags::Negative); + } + } + + void BIT_Zero() { + BIT(GetZero()); + } + void BIT_Abs() { + BIT(GetAbs()); + } + + void ADC_Imm() { ADC(GetImmediate()); } + void ADC_Zero() { ADC(GetZero()); } + void ADC_ZeroX() { ADC(GetZeroX()); } + void ADC_Abs() { ADC(GetAbs()); } + void ADC_AbsX() { ADC(GetAbsX()); } + void ADC_AbsY() { ADC(GetAbsY()); } + void ADC_IndX() { ADC(GetIndX()); } + void ADC_IndY() { ADC(GetIndY()); } + + void SBC_Imm() { SBC(GetImmediate()); } + void SBC_Zero() { SBC(GetZero()); } + void SBC_ZeroX() { SBC(GetZeroX()); } + void SBC_Abs() { SBC(GetAbs()); } + void SBC_AbsX() { SBC(GetAbsX()); } + void SBC_AbsY() { SBC(GetAbsY()); } + void SBC_IndX() { SBC(GetIndX()); } + void SBC_IndY() { SBC(GetIndY()); } + + void CMP_Imm() { CPA(GetImmediate()); } + void CMP_Zero() { CPA(GetZero()); } + void CMP_ZeroX() { CPA(GetZeroX()); } + void CMP_Abs() { CPA(GetAbs()); } + void CMP_AbsX() { CPA(GetAbsX()); } + void CMP_AbsY() { CPA(GetAbsY()); } + void CMP_IndX() { CPA(GetIndX()); } + void CMP_IndY() { CPA(GetIndY()); } + + void CPX_Imm() { CPX(GetImmediate()); } + void CPX_Zero() { CPX(GetZero()); } + void CPX_Abs() { CPX(GetAbs()); } + + void CPY_Imm() { CPY(GetImmediate()); } + void CPY_Zero() { CPY(GetZero()); } + void CPY_Abs() { CPY(GetAbs()); } + + void INC_Zero() { INC(GetZeroAddr()); } + void INC_ZeroX() { INC(GetZeroXAddr()); } + void INC_Abs() { INC(GetAbsAddr()); } + void INC_AbsX() { INC(GetAbsXAddr()); } + void INX() { SetX(X() + 1); } + void INY() { SetY(Y() + 1); } + + void DEC_Zero() { DEC(GetZeroAddr()); } + void DEC_ZeroX() { DEC(GetZeroXAddr()); } + void DEC_Abs() { DEC(GetAbsAddr()); } + void DEC_AbsX() { DEC(GetAbsXAddr()); } + void DEX() { SetX(X() - 1); } + void DEY() { SetY(Y() - 1); } + + void ASL_Acc() { SetA(ASL(A())); } + void ASL_Zero() { ASLAddr(GetZeroAddr()); } + void ASL_ZeroX() { ASLAddr(GetZeroXAddr()); } + void ASL_Abs() { ASLAddr(GetAbsAddr()); } + void ASL_AbsX() { ASLAddr(GetAbsXAddr()); } + + void LSR_Acc() { SetA(LSR(A())); } + void LSR_Zero() { LSRAddr(GetZeroAddr()); } + void LSR_ZeroX() { LSRAddr(GetZeroXAddr()); } + void LSR_Abs() { LSRAddr(GetAbsAddr()); } + void LSR_AbsX() { LSRAddr(GetAbsXAddr()); } + + void ROL_Acc() { SetA(ROL(A())); } + void ROL_Zero() { ROLAddr(GetZeroAddr()); } + void ROL_ZeroX() { ROLAddr(GetZeroXAddr()); } + void ROL_Abs() { ROLAddr(GetAbsAddr()); } + void ROL_AbsX() { ROLAddr(GetAbsXAddr()); } + + void ROR_Acc() { SetA(ROR(A())); } + void ROR_Zero() { RORAddr(GetZeroAddr()); } + void ROR_ZeroX() { RORAddr(GetZeroXAddr()); } + void ROR_Abs() { RORAddr(GetAbsAddr()); } + void ROR_AbsX() { RORAddr(GetAbsXAddr()); } + + void JMP_Abs() { + auto currentPC = _state.PC - 1; + auto newPC = ReadWord(); + if(currentPC == newPC) { + std::cout << "Infinite loop at: " << std::hex << (short)newPC << std::endl; + } + JMP(newPC); + } + void JMP_Ind() { JMP(GetInd()); } + void JSR() { + Push((uint16_t)(PC() + 1)); + JMP(GetAbsAddr()); + } + void RTS() { + SetPC(PopWord() + 1); + } + + void BCC() { + BranchRelative(!CheckFlag(PSFlags::Carry)); + } + + void BCS() { + BranchRelative(CheckFlag(PSFlags::Carry)); + } + + void BEQ() { + BranchRelative(CheckFlag(PSFlags::Zero)); + } + + void BMI() { + BranchRelative(CheckFlag(PSFlags::Negative)); + } + + void BNE() { + BranchRelative(!CheckFlag(PSFlags::Zero)); + } + + void BPL() { + BranchRelative(!CheckFlag(PSFlags::Negative)); + } + + void BVC() { + BranchRelative(!CheckFlag(PSFlags::Overflow)); + } + + void BVS() { + BranchRelative(CheckFlag(PSFlags::Overflow)); + } + + void CLC() { ClearFlags(PSFlags::Carry); } + void CLD() { ClearFlags(PSFlags::Decimal); } + void CLI() { ClearFlags(PSFlags::Interrupt); } + void CLV() { ClearFlags(PSFlags::Overflow); } + void SEC() { SetFlags(PSFlags::Carry); } + void SED() { SetFlags(PSFlags::Decimal); } + void SEI() { SetFlags(PSFlags::Interrupt); } + + void BRK() { + SetFlags(PSFlags::Break); + Push((uint16_t)(PC() + 1)); + Push((uint8_t)PS()); + SetFlags(PSFlags::Interrupt); + ClearFlags(PSFlags::Break); + SetPC((uint8_t)_memory[0xFFFE] | ((uint8_t)_memory[0xFFFF] << 8)); + } + + void NOP() {} + void RTI() { + SetPS(Pop()); + SetPC(PopWord()); + } +#pragma endregion +public: + Core(int8_t *memory) : _memory(memory) { + Reset(); + memset(_opTable, 0, 256 * sizeof(void*)); + _opTable[0x00] = &Core::BRK; + _opTable[0x01] = &Core::ORA_IndX; + _opTable[0x05] = &Core::ORA_Zero; + _opTable[0x06] = &Core::ASL_Zero; + _opTable[0x08] = &Core::PHP; + _opTable[0x09] = &Core::ORA_Imm; + _opTable[0x0A] = &Core::ASL_Acc; + _opTable[0x0D] = &Core::ORA_Abs; + _opTable[0x0E] = &Core::ASL_Abs; + _opTable[0x10] = &Core::BPL; + _opTable[0x11] = &Core::ORA_IndY; + _opTable[0x15] = &Core::ORA_ZeroX; + _opTable[0x16] = &Core::ASL_ZeroX; + _opTable[0x18] = &Core::CLC; + _opTable[0x19] = &Core::ORA_AbsY; + _opTable[0x1D] = &Core::ORA_AbsX; + _opTable[0x1E] = &Core::ASL_AbsX; + _opTable[0x20] = &Core::JSR; + _opTable[0x21] = &Core::AND_IndX; + _opTable[0x24] = &Core::BIT_Zero; + _opTable[0x25] = &Core::AND_Zero; + _opTable[0x26] = &Core::ROL_Zero; + _opTable[0x28] = &Core::PLP; + _opTable[0x29] = &Core::AND_Imm; + _opTable[0x2A] = &Core::ROL_Acc; + _opTable[0x2C] = &Core::BIT_Abs; + _opTable[0x2D] = &Core::AND_Abs; + _opTable[0x2E] = &Core::ROL_Abs; + _opTable[0x30] = &Core::BMI; + _opTable[0x31] = &Core::AND_IndY; + _opTable[0x35] = &Core::AND_ZeroX; + _opTable[0x36] = &Core::ROL_ZeroX; + _opTable[0x38] = &Core::SEC; + _opTable[0x39] = &Core::AND_AbsY; + _opTable[0x3D] = &Core::AND_AbsX; + _opTable[0x3E] = &Core::ROL_AbsX; + _opTable[0x40] = &Core::RTI; + _opTable[0x41] = &Core::EOR_IndX; + _opTable[0x45] = &Core::EOR_Zero; + _opTable[0x46] = &Core::LSR_Zero; + _opTable[0x48] = &Core::PHA; + _opTable[0x49] = &Core::EOR_Imm; + _opTable[0x4A] = &Core::LSR_Acc; + _opTable[0x4C] = &Core::JMP_Abs; + _opTable[0x4D] = &Core::EOR_Abs; + _opTable[0x4E] = &Core::LSR_Abs; + _opTable[0x50] = &Core::BVC; + _opTable[0x51] = &Core::EOR_IndY; + _opTable[0x55] = &Core::EOR_ZeroX; + _opTable[0x56] = &Core::LSR_ZeroX; + _opTable[0x58] = &Core::CLI; + _opTable[0x59] = &Core::EOR_AbsY; + _opTable[0x5D] = &Core::EOR_AbsX; + _opTable[0x5E] = &Core::LSR_AbsX; + _opTable[0x60] = &Core::RTS; + _opTable[0x61] = &Core::ADC_IndX; + _opTable[0x65] = &Core::ADC_Zero; + _opTable[0x66] = &Core::ROR_Zero; + _opTable[0x68] = &Core::PLA; + _opTable[0x69] = &Core::ADC_Imm; + _opTable[0x6A] = &Core::ROR_Acc; + _opTable[0x6C] = &Core::JMP_Ind; + _opTable[0x6D] = &Core::ADC_Abs; + _opTable[0x6E] = &Core::ROR_Abs; + _opTable[0x70] = &Core::BVS; + _opTable[0x71] = &Core::ADC_IndY; + _opTable[0x75] = &Core::ADC_ZeroX; + _opTable[0x76] = &Core::ROR_ZeroX; + _opTable[0x78] = &Core::SEI; + _opTable[0x79] = &Core::ADC_AbsY; + _opTable[0x7D] = &Core::ADC_AbsX; + _opTable[0x7E] = &Core::ROR_AbsX; + _opTable[0x81] = &Core::STA_IndX; + _opTable[0x84] = &Core::STY_Zero; + _opTable[0x85] = &Core::STA_Zero; + _opTable[0x86] = &Core::STX_Zero; + _opTable[0x88] = &Core::DEY; + _opTable[0x8A] = &Core::TXA; + _opTable[0x8C] = &Core::STY_Abs; + _opTable[0x8D] = &Core::STA_Abs; + _opTable[0x8E] = &Core::STX_Abs; + _opTable[0x90] = &Core::BCC; + _opTable[0x91] = &Core::STA_IndY; + _opTable[0x94] = &Core::STY_ZeroX; + _opTable[0x95] = &Core::STA_ZeroX; + _opTable[0x96] = &Core::STX_ZeroY; + _opTable[0x98] = &Core::TYA; + _opTable[0x99] = &Core::STA_AbsY; + _opTable[0x9A] = &Core::TXS; + _opTable[0x9D] = &Core::STA_AbsX; + _opTable[0xA0] = &Core::LDY_Imm; + _opTable[0xA1] = &Core::LDA_IndX; + _opTable[0xA2] = &Core::LDX_Imm; + _opTable[0xA4] = &Core::LDY_Zero; + _opTable[0xA5] = &Core::LDA_Zero; + _opTable[0xA6] = &Core::LDX_Zero; + _opTable[0xA8] = &Core::TAY; + _opTable[0xA9] = &Core::LDA_Imm; + _opTable[0xAA] = &Core::TAX; + _opTable[0xAC] = &Core::LDY_Abs; + _opTable[0xAD] = &Core::LDA_Abs; + _opTable[0xAE] = &Core::LDX_Abs; + _opTable[0xB0] = &Core::BCS; + _opTable[0xB1] = &Core::LDA_IndY; + _opTable[0xB4] = &Core::LDY_ZeroX; + _opTable[0xB5] = &Core::LDA_ZeroX; + _opTable[0xB6] = &Core::LDX_ZeroY; + _opTable[0xB8] = &Core::CLV; + _opTable[0xB9] = &Core::LDA_AbsY; + _opTable[0xBA] = &Core::TSX; + _opTable[0xBC] = &Core::LDY_AbsX; + _opTable[0xBD] = &Core::LDA_AbsX; + _opTable[0xBE] = &Core::LDX_AbsY; + _opTable[0xC0] = &Core::CPY_Imm; + _opTable[0xC1] = &Core::CMP_IndX; + _opTable[0xC4] = &Core::CPY_Zero; + _opTable[0xC5] = &Core::CMP_Zero; + _opTable[0xC6] = &Core::DEC_Zero; + _opTable[0xC8] = &Core::INY; + _opTable[0xC9] = &Core::CMP_Imm; + _opTable[0xCA] = &Core::DEX; + _opTable[0xCC] = &Core::CPY_Abs; + _opTable[0xCD] = &Core::CMP_Abs; + _opTable[0xCE] = &Core::DEC_Abs; + _opTable[0xD0] = &Core::BNE; + _opTable[0xD1] = &Core::CMP_IndY; + _opTable[0xD5] = &Core::CMP_ZeroX; + _opTable[0xD6] = &Core::DEC_ZeroX; + _opTable[0xD8] = &Core::CLD; + _opTable[0xD9] = &Core::CMP_AbsY; + _opTable[0xDD] = &Core::CMP_AbsX; + _opTable[0xDE] = &Core::DEC_AbsX; + _opTable[0xE0] = &Core::CPX_Imm; + _opTable[0xE1] = &Core::SBC_IndX; + _opTable[0xE4] = &Core::CPX_Zero; + _opTable[0xE5] = &Core::SBC_Zero; + _opTable[0xE6] = &Core::INC_Zero; + _opTable[0xE8] = &Core::INX; + _opTable[0xE9] = &Core::SBC_Imm; + _opTable[0xEA] = &Core::NOP; + _opTable[0xEC] = &Core::CPX_Abs; + _opTable[0xED] = &Core::SBC_Abs; + _opTable[0xEE] = &Core::INC_Abs; + _opTable[0xF0] = &Core::BEQ; + _opTable[0xF1] = &Core::SBC_IndY; + _opTable[0xF5] = &Core::SBC_ZeroX; + _opTable[0xF6] = &Core::INC_ZeroX; + _opTable[0xF8] = &Core::SED; + _opTable[0xF9] = &Core::SBC_AbsY; + _opTable[0xFD] = &Core::SBC_AbsX; + _opTable[0xFE] = &Core::INC_AbsX; + } + void Reset(); + void Exec(); +}; diff --git a/Core.vcxproj b/Core.vcxproj new file mode 100644 index 00000000..9ee28c0f --- /dev/null +++ b/Core.vcxproj @@ -0,0 +1,104 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0} + Win32Proj + Core + Core + + + + Application + true + v120 + Unicode + + + Application + false + v120 + true + Unicode + + + + + + + + + + + + + true + + + false + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + + + Console + true + + + + + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + AnySuitable + true + + + Console + true + true + true + + + + + + + + + + + + + + + Create + + + + + + + \ No newline at end of file diff --git a/Core.vcxproj.filters b/Core.vcxproj.filters new file mode 100644 index 00000000..a204d396 --- /dev/null +++ b/Core.vcxproj.filters @@ -0,0 +1,45 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Header Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/NES.sln b/NES.sln new file mode 100644 index 00000000..f0f7211e --- /dev/null +++ b/NES.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.30501.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "Core.vcxproj", "{78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.Debug|Win32.ActiveCfg = Debug|Win32 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.Debug|Win32.Build.0 = Debug|Win32 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.Release|Win32.ActiveCfg = Release|Win32 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/ReadMe.txt b/ReadMe.txt new file mode 100644 index 00000000..4cb8a2f4 --- /dev/null +++ b/ReadMe.txt @@ -0,0 +1,40 @@ +======================================================================== + CONSOLE APPLICATION : ConsoleApplication1 Project Overview +======================================================================== + +AppWizard has created this ConsoleApplication1 application for you. + +This file contains a summary of what you will find in each of the files that +make up your ConsoleApplication1 application. + + +ConsoleApplication1.vcxproj + This is the main project file for VC++ projects generated using an Application Wizard. + It contains information about the version of Visual C++ that generated the file, and + information about the platforms, configurations, and project features selected with the + Application Wizard. + +ConsoleApplication1.vcxproj.filters + This is the filters file for VC++ projects generated using an Application Wizard. + It contains information about the association between the files in your project + and the filters. This association is used in the IDE to show grouping of files with + similar extensions under a specific node (for e.g. ".cpp" files are associated with the + "Source Files" filter). + +ConsoleApplication1.cpp + This is the main application source file. + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named ConsoleApplication1.pch and a precompiled types file named StdAfx.obj. + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" comments to indicate parts of the source code you +should add to or customize. + +///////////////////////////////////////////////////////////////////////////// diff --git a/Timer.h b/Timer.h new file mode 100644 index 00000000..20738930 --- /dev/null +++ b/Timer.h @@ -0,0 +1,28 @@ +#include "stdafx.h" + +class Timer +{ + private: + double _frequency = 0.0; + LARGE_INTEGER _start; + + public: + Timer() { + LARGE_INTEGER li; + if(!QueryPerformanceFrequency(&li)) { + throw; + } + + _frequency = double(li.QuadPart) / 1000.0; + + QueryPerformanceCounter(&li); + _start = li; + } + + double GetElapsedMS() + { + LARGE_INTEGER li; + QueryPerformanceCounter(&li); + return double(li.QuadPart - _start.QuadPart) / _frequency; + } +}; \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 00000000..c60d420b --- /dev/null +++ b/main.cpp @@ -0,0 +1,164 @@ +#include "stdafx.h" +#include "CPU.h" + +/* +template +class Event +{ + typedef void(*Func)(Types...); + private: + std::list handlerList; + Func lastFunc; + + public: + void RegisterHandler(Func handler); + void operator+=(Func handler); + void operator()(Types ...types); +}; + +template +void Event::RegisterHandler(Func handler) +{ + this->handlerList.push_back(handler); + lastFunc = this->handlerList.size() == 1 ? handler : nullptr; +} + +template +void Event::operator+=(Func handler) { + this->RegisterHandler(handler); +} + +template +void Event::operator()(Types... types) +{ + if (lastFunc) { + lastFunc(types...); + } else { + for (auto handler : this->handlerList) { + handler(types...); + } + } +} + +template +class TemplatedClass +{ + public: + T Sum(T a, T b); +}; + +template +T TemplatedClass::Sum(T a, T b) +{ + return a + b; +} + +template using ptr = std::unique_ptr; + +class Test +{ + private: + int counter = 0; + Test(); + + public: + int Sum(int, int); + void NewThread(); + static std::unique_ptr NewInstance(); +}; + +Test::Test() +{ + +} + +int Test::Sum(int x, int y) +{ + return x + y; +} + +void Test::NewThread() +{ + for (int i = 0; i < 100; i++) { + std::this_thread::sleep_for(std::chrono::duration(1000)); + printf("test %i", this->counter); + this->counter++; + } +} + +std::unique_ptr Test::NewInstance() +{ + return std::unique_ptr(new Test()); +} + +void somefunction(void) +{ + printf("test11111"); +} + +void func2(int a) +{ + //printf("%i", a); +}*/ + +int _tmain(int argc, _TCHAR* argv[]) +{ + std::ifstream romFile("6502_functional_test.bin", std::ios::in | std::ios::binary); + if(!romFile) { + std::cout << "Error"; + } + + int8_t romMemory[65536]; + romFile.read((char *)romMemory, 65536); + /*int8_t* memory = new int8_t[8000]; + memory[0x0600] = 0xA9; + memory[0x0601] = 0x55;*/ + + Core core(romMemory); + core.Exec(); + + /*Event<> eventHandler; + eventHandler += somefunction; + + Event intHandler; + intHandler += func2; + intHandler += func2; + intHandler += func2; + + for (int i = 0; i < 1000000; i++) { + intHandler(i); + } + eventHandler(); + + TemplatedClass DoubleSum; + printf("%d", DoubleSum.Sum(10.0, 20.0)); + + TemplatedClass StringSum; + std::cout << StringSum.Sum("asdas", "dsadasdsa"); + + auto str1 = std::string("aaaa"); + auto str2 = std::string("bbbb"); + auto str3 = str1 + str2; + std::cout << str3; + + std::unique_ptr test; + + if (!test) { + test = Test::NewInstance(); + } + + std::thread t1(&Test::NewThread, test.get()); + + std::thread t2([]() { + printf("test2"); + }); + + if (test) { + printf("%i", test->Sum(1000, 10)); + } + + t1.join(); + */ + return 0; +} + diff --git a/stdafx.cpp b/stdafx.cpp new file mode 100644 index 00000000..1577c4e3 --- /dev/null +++ b/stdafx.cpp @@ -0,0 +1 @@ +#include "stdafx.h" \ No newline at end of file diff --git a/stdafx.h b/stdafx.h new file mode 100644 index 00000000..50806df7 --- /dev/null +++ b/stdafx.h @@ -0,0 +1,26 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + + +// TODO: reference additional headers your program requires here diff --git a/targetver.h b/targetver.h new file mode 100644 index 00000000..87c0086d --- /dev/null +++ b/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include