From 8ad76f6c3112285a41a832f6179ff472edaffe39 Mon Sep 17 00:00:00 2001 From: Sour Date: Mon, 11 Feb 2019 19:18:47 -0500 Subject: [PATCH] 65816 core working in 6502 emulation mode --- .editorconfig | 5 + .gitattributes | 63 ++ .gitignore | 197 ++++++ Core/Core.vcxproj | 528 +++++++++++++++ Core/Core.vcxproj.filters | 13 + Core/Cpu.cpp | 1292 +++++++++++++++++++++++++++++++++++++ Core/Cpu.h | 232 +++++++ Core/CpuTypes.h | 92 +++ Core/main.cpp | 37 ++ Core/stdafx.cpp | 1 + Core/stdafx.h | 50 ++ Mesen-S.sln | 385 +++++++++++ build.sh | 17 + buildPGO.sh | 66 ++ makefile | 173 +++++ 15 files changed, 3151 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 Core/Core.vcxproj create mode 100644 Core/Core.vcxproj.filters create mode 100644 Core/Cpu.cpp create mode 100644 Core/Cpu.h create mode 100644 Core/CpuTypes.h create mode 100644 Core/main.cpp create mode 100644 Core/stdafx.cpp create mode 100644 Core/stdafx.h create mode 100644 Mesen-S.sln create mode 100644 build.sh create mode 100644 buildPGO.sh create mode 100644 makefile diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..651c804 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,5 @@ +root = true + +[*] +indent_style = tab +indent_size = 3 \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /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 0000000..fcae9bf --- /dev/null +++ b/.gitignore @@ -0,0 +1,197 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates +.vs/* + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +build/ +[Bb]in/ +[Oo]bj/ +[Oo]bj.x86/ +[Oo]bj.x64/ + +# 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 + +# Libretro build files +*.o + +# 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 +*.nes +*.sav +*.svs +*.trt +*.rar + +*.VC.opendb +*.VC.db +*.VC.db-wal +*.VC.db-shm + +Docs/docs/ +Docs/*.exe + +PGOHelper/PGOMesenHome +*.profraw +*.profdata + +packages/* + +!Libretro/hakchi/bin + +Dependencies/* +GUI.NET/* +Windows/* +Linux/* +Libretro/* +Docs/* +SevenZip/* +Lua/* +TestHelper/* +UpdateHelper/* +Utilities/* +PGOHelper/* +DependencyPacker/* +InteropDLL/* \ No newline at end of file diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj new file mode 100644 index 0000000..ddae04d --- /dev/null +++ b/Core/Core.vcxproj @@ -0,0 +1,528 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Libretro + Win32 + + + Libretro + x64 + + + PGO Optimize + Win32 + + + PGO Optimize + x64 + + + PGO Profile + Win32 + + + PGO Profile + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + + + + + Create + Create + Create + Create + Create + Create + Create + Create + Create + Create + + + + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0} + Win32Proj + Core + Core + 10.0.16299.0 + + + + Application + true + v141 + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + false + v141 + true + Unicode + + + Application + false + v141 + true + Unicode + + + Application + false + v141 + true + Unicode + + + Application + false + v141 + true + Unicode + + + Application + false + v141 + true + Unicode + + + Application + false + v141 + true + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + $(IncludePath) + $(LibraryPath) + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + obj\$(Platform)\$(Configuration)\ + + + true + $(IncludePath) + $(LibraryPath) + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\bin\$(PlatformTarget)\PGO Profile\ + obj\$(Platform)\PGO Profile\ + + + false + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + obj\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\bin\$(PlatformTarget)\PGO Profile\ + obj\$(Platform)\PGO Profile\ + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + + ProgramDatabase + Default + Cdecl + + + Default + MultiThreadedDebug + true + true + false + + + + + Console + true + + + + + + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + + + ProgramDatabase + Default + Cdecl + + + Default + MultiThreadedDebug + true + true + false + + + + + Console + true + + + + + + + + + Level3 + Use + Full + true + true + WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + AnySuitable + true + Speed + + + Default + MultiThreaded + true + true + + + + + Console + true + true + true + + + + + Level3 + Use + Full + true + true + LIBRETRO;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + AnySuitable + true + Speed + + + Default + MultiThreaded + true + true + + + + + Console + true + true + true + + + + + Level3 + Use + Full + true + true + WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + AnySuitable + true + Speed + + + Default + MultiThreaded + true + true + + + + + Console + true + true + true + + + + + Level3 + Use + Full + true + true + WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + AnySuitable + true + Speed + + + Default + MultiThreaded + true + true + + + + + Console + true + true + true + + + + + Level3 + Use + Full + true + true + WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + false + AnySuitable + true + Speed + + + Default + MultiThreaded + true + true + + + + + false + + + + + Console + true + true + true + + + + + Level3 + Use + Full + true + true + LIBRETRO;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + false + AnySuitable + true + Speed + + + Default + MultiThreaded + true + true + + + + + false + + + + + Console + true + true + true + + + + + Level3 + Use + Full + true + true + WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + Disabled + true + Speed + + + Default + MultiThreaded + true + true + + + + + Console + true + true + true + + + + + Level3 + Use + Full + true + true + WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + true + AnySuitable + true + Speed + + + Default + MultiThreaded + true + true + + + + + Console + true + true + true + + + + + + \ No newline at end of file diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters new file mode 100644 index 0000000..3d5c93d --- /dev/null +++ b/Core/Core.vcxproj.filters @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/Core/Cpu.cpp b/Core/Cpu.cpp new file mode 100644 index 0000000..bd38640 --- /dev/null +++ b/Core/Cpu.cpp @@ -0,0 +1,1292 @@ +#include "stdafx.h" +#include "CpuTypes.h" +#include "Cpu.h" +#include "../Utilities/HexUtilities.h" + +uint8_t lastTest = -1; +bool _enableLogging = false; + +/************************ +Add/substract operations +*************************/ +void Cpu::Add8(uint8_t value) +{ + uint32_t result; + if(CheckFlag(ProcFlags::Decimal)) { + result = (_state.A & 0x0F) + (value & 0x0F) + (_state.PS & ProcFlags::Carry); + if(result > 0x09) result += 0x06; + result = (_state.A & 0xF0) + (value & 0xF0) + (result > 0x0F ? 0x10 : 0) + (result & 0x0F); + } else { + result = (uint32_t)_state.A + value + (_state.PS & ProcFlags::Carry); + } + + if(~(_state.A ^ value) & (_state.A ^ result) & 0x80) { + SetFlags(ProcFlags::Overflow); + } else { + ClearFlags(ProcFlags::Overflow); + } + + if(CheckFlag(ProcFlags::Decimal) && result > 0x9F) { + result += 0x60; + } + + ClearFlags(ProcFlags::Carry | ProcFlags::Negative | ProcFlags::Zero); + SetZeroNegativeFlags((uint8_t)result); + + if(result & 0x100) { + SetFlags(ProcFlags::Carry); + } + + _state.A = (uint8_t)result; +} + +void Cpu::Add16(uint16_t value) +{ + uint32_t result; + if(CheckFlag(ProcFlags::Decimal)) { + result = (_state.A & 0x0F) + (value & 0x0F) + (_state.PS & ProcFlags::Carry); + + if(result > 0x09) result += 0x06; + result = (_state.A & 0xF0) + (value & 0xF0) + (result > 0x0F ? 0x10 : 0) + (result & 0x0F); + + if(result > 0x9F) result += 0x60; + result = (_state.A & 0xF00) + (value & 0xF00) + (result > 0xFF ? 0x100 : 0) + (result & 0xFF); + + if(result > 0x9FF) result += 0x600; + result = (_state.A & 0xF000) + (value & 0xF000) + (result > 0xFFF ? 0x1000 : 0) + (result & 0xFFF); + } else { + result = (uint32_t)_state.A + value + (_state.PS & ProcFlags::Carry); + } + + if(~(_state.A ^ value) & (_state.A ^ result) & 0x8000) { + SetFlags(ProcFlags::Overflow); + } else { + ClearFlags(ProcFlags::Overflow); + } + + if(CheckFlag(ProcFlags::Decimal) && result > 0x9FFF) { + result += 0x6000; + } + + ClearFlags(ProcFlags::Carry | ProcFlags::Negative | ProcFlags::Zero); + SetZeroNegativeFlags((uint16_t)result); + + if(result & 0x10000) { + SetFlags(ProcFlags::Carry); + } + + _state.A = (uint16_t)result; +} + +void Cpu::ADC() +{ + if(CheckFlag(ProcFlags::MemoryMode8)) { + Add8(GetByteValue()); + } else { + Add16(GetWordValue()); + } +} + +void Cpu::Sub8(uint8_t value) +{ + uint32_t result; + if(CheckFlag(ProcFlags::Decimal)) { + result = (_state.A & 0x0F) + (value & 0x0F) + (_state.PS & ProcFlags::Carry); + if(result <= 0x0F) result -= 0x06; + result = (_state.A & 0xF0) + (value & 0xF0) + (result > 0x0F ? 0x10 : 0) + (result & 0x0F); + } else { + result = (uint32_t)_state.A + value + (_state.PS & ProcFlags::Carry); + } + + if(~(_state.A ^ value) & (_state.A ^ result) & 0x80) { + SetFlags(ProcFlags::Overflow); + } else { + ClearFlags(ProcFlags::Overflow); + } + + if(CheckFlag(ProcFlags::Decimal) && result <= 0xFF) { + result -= 0x60; + } + + ClearFlags(ProcFlags::Carry | ProcFlags::Negative | ProcFlags::Zero); + SetZeroNegativeFlags((uint8_t)result); + + if(result & 0x100) { + SetFlags(ProcFlags::Carry); + } + + _state.A = (uint8_t)result; +} + +void Cpu::Sub16(uint16_t value) +{ + uint32_t result; + if(CheckFlag(ProcFlags::Decimal)) { + result = (_state.A & 0x0F) + (value & 0x0F) + (_state.PS & ProcFlags::Carry); + + if(result <= 0x0F) result -= 0x06; + result = (_state.A & 0xF0) + (value & 0xF0) + (result > 0x0F ? 0x10 : 0) + (result & 0x0F); + + if(result <= 0xFF) result -= 0x60; + result = (_state.A & 0xF00) + (value & 0xF00) + (result > 0xFF ? 0x100 : 0) + (result & 0xFF); + + if(result <= 0xFFF) result -= 0x600; + result = (_state.A & 0xF000) + (value & 0xF000) + (result > 0xFFF ? 0x1000 : 0) + (result & 0xFFF); + } else { + result = (uint32_t)_state.A + value + (_state.PS & ProcFlags::Carry); + } + + if(~(_state.A ^ value) & (_state.A ^ result) & 0x8000) { + SetFlags(ProcFlags::Overflow); + } else { + ClearFlags(ProcFlags::Overflow); + } + + if(CheckFlag(ProcFlags::Decimal) && result <= 0xFFFF) { + result -= 0x6000; + } + + ClearFlags(ProcFlags::Carry | ProcFlags::Negative | ProcFlags::Zero); + SetZeroNegativeFlags((uint16_t)result); + + if(result & 0x10000) { + SetFlags(ProcFlags::Carry); + } + + _state.A = (uint16_t)result; +} + +void Cpu::SBC() +{ + if(CheckFlag(ProcFlags::MemoryMode8)) { + Sub8(~GetByteValue()); + } else { + Sub16(~GetWordValue()); + } +} + +/**************** +Branch operations +****************/ +void Cpu::BCC() +{ + BranchRelative(!CheckFlag(ProcFlags::Carry)); +} + +void Cpu::BCS() +{ + BranchRelative(CheckFlag(ProcFlags::Carry)); +} + +void Cpu::BEQ() +{ + BranchRelative(CheckFlag(ProcFlags::Zero)); +} + +void Cpu::BMI() +{ + BranchRelative(CheckFlag(ProcFlags::Negative)); +} + +void Cpu::BNE() +{ + BranchRelative(!CheckFlag(ProcFlags::Zero)); +} + +void Cpu::BPL() +{ + BranchRelative(!CheckFlag(ProcFlags::Negative)); +} + +void Cpu::BRA() +{ + BranchRelative(true); +} + +void Cpu::BRL() +{ + _state.PC = (uint16_t)(_state.PC + (int16_t)_operand); +} + +void Cpu::BVC() +{ + BranchRelative(!CheckFlag(ProcFlags::Overflow)); +} + +void Cpu::BVS() +{ + BranchRelative(CheckFlag(ProcFlags::Overflow)); +} + +void Cpu::BranchRelative(bool branch) +{ + int8_t offset = _operand; + if(branch) { + _state.PC = (uint16_t)(_state.PC + offset); + } +} + +/*************************** +Set/clear flag instructions +****************************/ +void Cpu::CLC() +{ + ClearFlags(ProcFlags::Carry); +} + +void Cpu::CLD() +{ + ClearFlags(ProcFlags::Decimal); +} + +void Cpu::CLI() +{ + ClearFlags(ProcFlags::IrqDisable); +} + +void Cpu::CLV() +{ + ClearFlags(ProcFlags::Overflow); +} + +void Cpu::SEC() +{ + SetFlags(ProcFlags::Carry); +} + +void Cpu::SED() +{ + SetFlags(ProcFlags::Decimal); +} + +void Cpu::SEI() +{ + SetFlags(ProcFlags::IrqDisable); +} + +void Cpu::REP() +{ + ClearFlags((uint8_t)_operand); +} + +void Cpu::SEP() +{ + SetFlags((uint8_t)_operand); +} + +/****************************** +Increment/decrement operations +*******************************/ +void Cpu::DEX() +{ + IncDecReg(_state.X, -1); +} + +void Cpu::DEY() +{ + IncDecReg(_state.Y, -1); +} + +void Cpu::INX() +{ + IncDecReg(_state.X, 1); +} + +void Cpu::INY() +{ + IncDecReg(_state.Y, 1); +} + +void Cpu::DEC() +{ + IncDec(-1); +} + +void Cpu::INC() +{ + IncDec(1); +} + +void Cpu::IncDecReg(uint16_t ®, int8_t offset) +{ + SetRegister(reg, reg + offset, CheckFlag(ProcFlags::IndexMode8)); +} + +void Cpu::IncDec(int8_t offset) +{ + if(_instAddrMode == AddrMode::Acc) { + SetRegister(_state.A, _state.A + offset, CheckFlag(ProcFlags::MemoryMode8)); + } else { + if(CheckFlag(ProcFlags::MemoryMode8)) { + uint8_t value = GetByteValue() + offset; + SetZeroNegativeFlags(value); + Write(_operand, value); + } else { + uint16_t value = GetWordValue() + offset; + SetZeroNegativeFlags(value); + WriteWord(_operand, value); + } + } +} + +/******************** +Compare instructions +*********************/ +void Cpu::Compare(uint16_t reg, bool eightBitMode) +{ + if(eightBitMode) { + uint8_t value = GetByteValue(); + if((uint8_t)reg >= value) { + SetFlags(ProcFlags::Carry); + } else { + ClearFlags(ProcFlags::Carry); + } + uint8_t result = (uint8_t)reg - value; + SetZeroNegativeFlags(result); + } else { + uint16_t value = GetWordValue(); + if(reg >= value) { + SetFlags(ProcFlags::Carry); + } else { + ClearFlags(ProcFlags::Carry); + } + + uint16_t result = reg - value; + SetZeroNegativeFlags(result); + } +} + +void Cpu::CMP() +{ + Compare(_state.A, CheckFlag(ProcFlags::MemoryMode8)); +} + +void Cpu::CPX() +{ + Compare(_state.X, CheckFlag(ProcFlags::IndexMode8)); +} + +void Cpu::CPY() +{ + Compare(_state.Y, CheckFlag(ProcFlags::IndexMode8)); +} + +/***************** +Jump instructions +******************/ +void Cpu::JML() +{ + _state.K = (_operand >> 16) & 0xFF; + _state.PC = (uint16_t)_operand; +} + +void Cpu::JMP() +{ + _state.PC = (uint16_t)_operand; +} + +void Cpu::JSL() +{ + PushByte(_state.K); + PushWord(_state.PC - 1); + _state.K = (_operand >> 16) & 0xFF; + _state.PC = (uint16_t)_operand; +} + +void Cpu::JSR() +{ + PushWord(_state.PC - 1); + _state.PC = (uint16_t)_operand; +} + +void Cpu::RTI() +{ + if(_state.EmulationMode) { + _state.PS = PopByte(); //TODO: incorrect + _state.PC = PopWord(); + } else { + _state.PS = PopByte(); //TODO: incorrect + _state.PC = PopWord(); + _state.K = PopByte(); + } +} + +void Cpu::RTL() +{ + _state.PC = PopWord(); + _state.PC++; + _state.K = PopByte(); +} + +void Cpu::RTS() +{ + _state.PC = PopWord(); + _state.PC++; +} + +/********** +Interrupts +***********/ +void Cpu::ProcessInterrupt(uint16_t vector) +{ + if(_state.EmulationMode) { + PushWord(_state.PC + 1); + PushByte(_state.PS | 0x20); + + SetFlags(ProcFlags::IrqDisable); + ClearFlags(ProcFlags::Decimal); + + _state.PC = ReadDataWord(vector); + } else { + PushByte(_state.K); + PushWord(_state.PC + 1); + PushByte(_state.PS); + + SetFlags(ProcFlags::IrqDisable); + ClearFlags(ProcFlags::Decimal); + + _state.PC = ReadDataWord(vector); + } +} + +void Cpu::BRK() +{ + ProcessInterrupt(_state.EmulationMode ? Cpu::LegacyBreakVector : Cpu::BreakVector); +} + +void Cpu::COP() +{ + ProcessInterrupt(_state.EmulationMode ? Cpu::LegacyCoprocessorVector : Cpu::CoprocessorVector); +} + +/****************** +Bitwise operations +*******************/ +void Cpu::AND() +{ + SetRegister(_state.A, _state.A & GetByteValue(), CheckFlag(ProcFlags::MemoryMode8)); +} + +void Cpu::EOR() +{ + SetRegister(_state.A, _state.A ^ GetByteValue(), CheckFlag(ProcFlags::MemoryMode8)); +} + +void Cpu::ORA() +{ + SetRegister(_state.A, _state.A | GetByteValue(), CheckFlag(ProcFlags::MemoryMode8)); +} + +/**************** +Shift operations +*****************/ +template T Cpu::ShiftLeft(T value) +{ + T result = value << 1; + if(value & (1 << (sizeof(T)*8-1))) { + SetFlags(ProcFlags::Carry); + } else { + ClearFlags(ProcFlags::Carry); + } + SetZeroNegativeFlags(result); + return result; +} + +template T Cpu::RollLeft(T value) +{ + T result = value << 1 | (_state.PS & ProcFlags::Carry); + if(value & (1 << (sizeof(T) * 8 - 1))) { + SetFlags(ProcFlags::Carry); + } else { + ClearFlags(ProcFlags::Carry); + } + SetZeroNegativeFlags(result); + return result; +} + +template T Cpu::ShiftRight(T value) +{ + T result = value >> 1; + if(value & 0x01) { + SetFlags(ProcFlags::Carry); + } else { + ClearFlags(ProcFlags::Carry); + } + SetZeroNegativeFlags(result); + return result; +} + +template T Cpu::RollRight(T value) +{ + T result = value >> 1 | ((_state.PS & 0x01) << (sizeof(T) * 8 - 1)); + if(value & 0x01) { + SetFlags(ProcFlags::Carry); + } else { + ClearFlags(ProcFlags::Carry); + } + SetZeroNegativeFlags(result); + return result; +} + +void Cpu::ASL() +{ + if(_instAddrMode == AddrMode::Acc) { + if(CheckFlag(ProcFlags::MemoryMode8)) { + _state.A = ShiftLeft((uint8_t)_state.A); + } else { + _state.A = ShiftLeft(_state.A); + } + } else { + if(CheckFlag(ProcFlags::MemoryMode8)) { + Write(_operand, ShiftLeft(GetByteValue())); + } else { + WriteWord(_operand, ShiftLeft(GetWordValue())); + } + } +} + +void Cpu::LSR() +{ + if(_instAddrMode == AddrMode::Acc) { + if(CheckFlag(ProcFlags::MemoryMode8)) { + _state.A = ShiftRight((uint8_t)_state.A); + } else { + _state.A = ShiftRight(_state.A); + } + } else { + if(CheckFlag(ProcFlags::MemoryMode8)) { + Write(_operand, ShiftRight(GetByteValue())); + } else { + WriteWord(_operand, ShiftRight(GetWordValue())); + } + } +} + +void Cpu::ROL() +{ + if(_instAddrMode == AddrMode::Acc) { + if(CheckFlag(ProcFlags::MemoryMode8)) { + _state.A = RollLeft((uint8_t)_state.A); + } else { + _state.A = RollLeft(_state.A); + } + } else { + if(CheckFlag(ProcFlags::MemoryMode8)) { + Write(_operand, RollLeft(GetByteValue())); + } else { + WriteWord(_operand, RollLeft(GetWordValue())); + } + } +} + +void Cpu::ROR() +{ + if(_instAddrMode == AddrMode::Acc) { + if(CheckFlag(ProcFlags::MemoryMode8)) { + _state.A = RollRight((uint8_t)_state.A); + } else { + _state.A = RollRight(_state.A); + } + } else { + if(CheckFlag(ProcFlags::MemoryMode8)) { + Write(_operand, RollRight(GetByteValue())); + } else { + WriteWord(_operand, RollRight(GetWordValue())); + } + } +} + +/*************** +Move operations +****************/ +void Cpu::MVN() +{ + //TODO +} + +void Cpu::MVP() +{ + //TODO +} + +/******************** + Push/pull operations +*********************/ +void Cpu::PEA() +{ + //Push Effective Address + PushWord((uint16_t)_operand); +} + +void Cpu::PEI() +{ + //Push Effective Indirect address + PushWord((uint16_t)_operand); +} + +void Cpu::PER() +{ + //Push Effective Relative address + PushWord((uint16_t)_operand); +} + +void Cpu::PHB() +{ + PushWord(_state.DBR); +} + +void Cpu::PHD() +{ + PushWord(_state.D); +} + +void Cpu::PHK() +{ + //"PHP, PHK, PHP, PLB, and PLP push and pull one byte from the stack" + PushByte(_state.K); +} + +void Cpu::PHP() +{ + //"PHP, PHK, PHP, PLB, and PLP push and pull one byte from the stack" + PushByte(_state.PS); +} + +void Cpu::PLB() +{ + //"PHP, PHK, PHP, PLB, and PLP push and pull one byte from the stack" + SetRegister(_state.DBR, PopByte()); +} + +void Cpu::PLD() +{ + //"PHD and PLD push and pull two bytes from the stack." + SetRegister(_state.D, PopWord(), false); +} + +void Cpu::PLP() +{ + //"For PLP, (all of) the flags are pulled from the stack. Note that when the e flag is 1, the m and x flag are forced to 1, so after the PLP, both flags will still be 1 no matter what value is pulled from the stack." + if(_state.EmulationMode) { + _state.PS = PopByte() | ProcFlags::MemoryMode8 | ProcFlags::IndexMode8; + } else { + _state.PS = PopByte(); + } +} + +void Cpu::PHA() +{ + //"When the m flag is 0, PHA and PLA push and pull a 16-bit value, and when the m flag is 1, PHA and PLA push and pull an 8-bit value. " + PushRegister(_state.A, CheckFlag(ProcFlags::MemoryMode8)); +} + +void Cpu::PHX() +{ + PushRegister(_state.X, CheckFlag(ProcFlags::IndexMode8)); +} + +void Cpu::PHY() +{ + PushRegister(_state.Y, CheckFlag(ProcFlags::IndexMode8)); +} + +void Cpu::PLA() +{ + //"When the m flag is 0, PHA and PLA push and pull a 16-bit value, and when the m flag is 1, PHA and PLA push and pull an 8-bit value." + PullRegister(_state.A, CheckFlag(ProcFlags::MemoryMode8)); +} + +void Cpu::PLX() +{ + PullRegister(_state.X, CheckFlag(ProcFlags::IndexMode8)); +} + +void Cpu::PLY() +{ + PullRegister(_state.Y, CheckFlag(ProcFlags::IndexMode8)); +} + +void Cpu::PushRegister(uint16_t reg, bool eightBitMode) +{ + //"When the x flag is 0, PHX, PHY, PLX, and PLY push and pull a 16-bit value, and when the x flag is 1, PHX, PHY, PLX, and PLY push and pull an 8-bit value." + if(eightBitMode) { + PushByte((uint8_t)reg); + } else { + PushWord(reg); + } +} + +void Cpu::PullRegister(uint16_t ®, bool eightBitMode) +{ + //"When the x flag is 0, PHX, PHY, PLX, and PLY push and pull a 16-bit value, and when the x flag is 1, PHX, PHY, PLX, and PLY push and pull an 8-bit value." + if(eightBitMode) { + SetRegister(reg, PopByte(), true); + } else { + SetRegister(reg, PopWord(), false); + } +} + +/********************* +Store/load operations +**********************/ +void Cpu::LoadRegister(uint16_t ®, bool eightBitMode) +{ + if(eightBitMode) { + SetRegister(reg, GetByteValue(), true); + } else { + SetRegister(reg, GetWordValue(), false); + } +} + +void Cpu::StoreRegister(uint16_t val, bool eightBitMode) +{ + if(eightBitMode) { + Write(_operand, (uint8_t)val); + } else { + WriteWord(_operand, val); + } +} + +void Cpu::LDA() +{ + //"When the m flag is 0, LDA, STA, and STZ are 16-bit operations" + LoadRegister(_state.A, CheckFlag(ProcFlags::MemoryMode8)); +} + +void Cpu::LDX() +{ + //"When the x flag is 0, LDX, LDY, STX, and STY are 16-bit operations" + LoadRegister(_state.X, CheckFlag(ProcFlags::IndexMode8)); +} + +void Cpu::LDY() +{ + //"When the x flag is 0, LDX, LDY, STX, and STY are 16-bit operations" + LoadRegister(_state.Y, CheckFlag(ProcFlags::IndexMode8)); +} + +void Cpu::STA() +{ + //"When the m flag is 0, LDA, STA, and STZ are 16-bit operations" + StoreRegister(_state.A, CheckFlag(ProcFlags::MemoryMode8)); +} + +void Cpu::STX() +{ + //"When the x flag is 0, LDX, LDY, STX, and STY are 16-bit operations" + StoreRegister(_state.X, CheckFlag(ProcFlags::IndexMode8)); +} + +void Cpu::STY() +{ + //"When the x flag is 0, LDX, LDY, STX, and STY are 16-bit operations" + StoreRegister(_state.Y, CheckFlag(ProcFlags::IndexMode8)); +} + +void Cpu::STZ() +{ + //"When the m flag is 0, LDA, STA, and STZ are 16-bit operations" + StoreRegister(0, CheckFlag(ProcFlags::MemoryMode8)); +} + +/******************* +Bit test operations +********************/ +template void Cpu::TestBits(T value) +{ + ClearFlags(ProcFlags::Zero | ProcFlags::Overflow | ProcFlags::Negative); + if(((T)_state.A & value) == 0) { + SetFlags(ProcFlags::Zero); + } + if(value & (1 << (sizeof(T) * 8 - 2))) { + SetFlags(ProcFlags::Overflow); + } + if(value & (1 << (sizeof(T) * 8 - 1))) { + SetFlags(ProcFlags::Negative); + } +} + +void Cpu::BIT() +{ + if(CheckFlag(ProcFlags::MemoryMode8)) { + TestBits(GetByteValue()); + } else { + TestBits(GetWordValue()); + } +} + +void Cpu::TRB() +{ + //TODO +} + +void Cpu::TSB() +{ + //TODO +} + +/****************** +Transfer operations +*******************/ +void Cpu::TAX() +{ + SetRegister(_state.X, _state.A, CheckFlag(ProcFlags::IndexMode8)); +} + +void Cpu::TAY() +{ + SetRegister(_state.Y, _state.A, CheckFlag(ProcFlags::IndexMode8)); +} + +void Cpu::TCD() +{ + SetRegister(_state.DBR, (uint8_t)_state.A); +} + +void Cpu::TCS() +{ + _state.SP = _state.A; +} + +void Cpu::TDC() +{ + SetRegister(_state.A, _state.DBR, CheckFlag(ProcFlags::MemoryMode8)); +} + +void Cpu::TSC() +{ + SetRegister(_state.A, _state.SP, CheckFlag(ProcFlags::MemoryMode8)); +} + +void Cpu::TSX() +{ + SetRegister(_state.X, _state.SP, CheckFlag(ProcFlags::IndexMode8)); +} + +void Cpu::TXA() +{ + SetRegister(_state.A, _state.X, CheckFlag(ProcFlags::MemoryMode8)); +} + +void Cpu::TXS() +{ + _state.SP = _state.X; +} + +void Cpu::TXY() +{ + SetRegister(_state.Y, _state.X, CheckFlag(ProcFlags::IndexMode8)); +} + +void Cpu::TYA() +{ + SetRegister(_state.A, _state.Y, CheckFlag(ProcFlags::MemoryMode8)); +} + +void Cpu::TYX() +{ + SetRegister(_state.X, _state.Y, CheckFlag(ProcFlags::IndexMode8)); +} + +void Cpu::XBA() +{ + _state.A = ((_state.A & 0xFF) << 8) | ((_state.A >> 8) & 0xFF); + SetZeroNegativeFlags((uint8_t)_state.A); +} + +void Cpu::XCE() +{ + _state.EmulationMode = (_state.PS & ProcFlags::Carry) ? true : false; +} + +/***************** +No operation (NOP) +******************/ +void Cpu::NOP() +{ + //1-byte NOP +} + +void Cpu::WDM() +{ + //2-byte NOP +} + +/**************** +Misc. operations +*****************/ +void Cpu::STP() +{ + //Stop the CPU +} + +void Cpu::WAI() +{ + //Wait for interrupt +} + +Cpu::Cpu(uint8_t* memory, bool enableLogging) +{ + typedef Cpu C; + Func opTable[256] = { + //0 1 2 3 4 5 6 7 8 9 A B C D E F + &C::BRK, &C::ORA, &C::COP, &C::ORA, &C::TSB, &C::ORA, &C::ASL, &C::ORA, &C::PHP, &C::ORA, &C::ASL, &C::PHD, &C::TSB, &C::ORA, &C::ASL, &C::ORA, // 0 + &C::BPL, &C::ORA, &C::ORA, &C::ORA, &C::TRB, &C::ORA, &C::ASL, &C::ORA, &C::CLC, &C::ORA, &C::INC, &C::TCS, &C::TRB, &C::ORA, &C::ASL, &C::ORA, // 1 + &C::JSR, &C::AND, &C::JSL, &C::AND, &C::BIT, &C::AND, &C::ROL, &C::AND, &C::PLP, &C::AND, &C::ROL, &C::PLD, &C::BIT, &C::AND, &C::ROL, &C::AND, // 2 + &C::BMI, &C::AND, &C::AND, &C::AND, &C::BIT, &C::AND, &C::ROL, &C::AND, &C::SEC, &C::AND, &C::DEC, &C::TSC, &C::BIT, &C::AND, &C::ROL, &C::AND, // 3 + &C::RTI, &C::EOR, &C::WDM, &C::EOR, &C::MVP, &C::EOR, &C::LSR, &C::EOR, &C::PHA, &C::EOR, &C::LSR, &C::PHK, &C::JMP, &C::EOR, &C::LSR, &C::EOR, // 4 + &C::BVC, &C::EOR, &C::EOR, &C::EOR, &C::MVN, &C::EOR, &C::LSR, &C::EOR, &C::CLI, &C::EOR, &C::PHY, &C::TCD, &C::JMP, &C::EOR, &C::LSR, &C::EOR, // 5 + &C::RTS, &C::ADC, &C::PER, &C::ADC, &C::STZ, &C::ADC, &C::ROR, &C::ADC, &C::PLA, &C::ADC, &C::ROR, &C::RTL, &C::JMP, &C::ADC, &C::ROR, &C::ADC, // 6 + &C::BVS, &C::ADC, &C::ADC, &C::ADC, &C::STZ, &C::ADC, &C::ROR, &C::ADC, &C::SEI, &C::ADC, &C::PLY, &C::TDC, &C::JMP, &C::ADC, &C::ROR, &C::ADC, // 7 + &C::BRA, &C::STA, &C::BRL, &C::STA, &C::STY, &C::STA, &C::STX, &C::STA, &C::DEY, &C::BIT, &C::TXA, &C::PHB, &C::STY, &C::STA, &C::STX, &C::STA, // 8 + &C::BCC, &C::STA, &C::STA, &C::STA, &C::STY, &C::STA, &C::STX, &C::STA, &C::TYA, &C::STA, &C::TXS, &C::TXY, &C::STZ, &C::STA, &C::STZ, &C::STA, // 9 + &C::LDY, &C::LDA, &C::LDX, &C::LDA, &C::LDY, &C::LDA, &C::LDX, &C::LDA, &C::TAY, &C::LDA, &C::TAX, &C::PLB, &C::LDY, &C::LDA, &C::LDX, &C::LDA, // A + &C::BCS, &C::LDA, &C::LDA, &C::LDA, &C::LDY, &C::LDA, &C::LDX, &C::LDA, &C::CLV, &C::LDA, &C::TSX, &C::TYX, &C::LDY, &C::LDA, &C::LDX, &C::LDA, // B + &C::CPY, &C::CMP, &C::REP, &C::CMP, &C::CPY, &C::CMP, &C::DEC, &C::CMP, &C::INY, &C::CMP, &C::DEX, &C::WAI, &C::CPY, &C::CMP, &C::DEC, &C::CMP, // C + &C::BNE, &C::CMP, &C::CMP, &C::CMP, &C::PEI, &C::CMP, &C::DEC, &C::CMP, &C::CLD, &C::CMP, &C::PHX, &C::STP, &C::JML, &C::CMP, &C::DEC, &C::CMP, // D + &C::CPX, &C::SBC, &C::SEP, &C::SBC, &C::CPX, &C::SBC, &C::INC, &C::SBC, &C::INX, &C::SBC, &C::NOP, &C::XBA, &C::CPX, &C::SBC, &C::INC, &C::SBC, // E + &C::BEQ, &C::SBC, &C::SBC, &C::SBC, &C::PEA, &C::SBC, &C::INC, &C::SBC, &C::SED, &C::SBC, &C::PLX, &C::XCE, &C::JSR, &C::SBC, &C::INC, &C::SBC // F + }; + + typedef AddrMode M; + AddrMode addrMode[256] = { + //0 1 2 3 4 5 6 7 8 9 A B C D E F + M::Stk, M::DirIdxIndX, M::Stk, M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Stk, M::Imm, M::Acc, M::Stk, M::Abs, M::Abs, M::Abs, M::AbsLng, // 0 + M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::Dir, M::DirIdxX, M::DirIdxX, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Acc, M::Imp, M::Abs, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX, // 1 + M::Abs, M::DirIdxIndX, M::AbsLng, M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Stk, M::Imm, M::Acc, M::Stk, M::Abs, M::Abs, M::Abs, M::AbsLng, // 2 + M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::DirIdxX, M::DirIdxX, M::DirIdxX, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Acc, M::Imp, M::AbsIdxX, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX, // 3 + M::Stk, M::DirIdxIndX, M::Imm, M::StkRel, M::BlkMov, M::Dir, M::Dir, M::DirIndLng, M::Stk, M::Imm, M::Acc, M::Stk, M::Abs, M::Abs, M::Abs, M::AbsLng, // 4 + M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::BlkMov, M::DirIdxX, M::DirIdxX, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Stk, M::Imp, M::AbsLng, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX, // 5 + M::Stk, M::DirIdxIndX, M::Stk, M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Stk, M::Imm, M::Acc, M::Stk, M::AbsInd, M::Abs, M::Abs, M::AbsLng, // 6 + M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::DirIdxX, M::DirIdxX, M::DirIdxX, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Stk, M::Imp, M::AbsIdxXInd, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX, // 7 + M::Rel, M::DirIdxIndX, M::RelLng, M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Imp, M::Imm, M::Imp, M::Stk, M::Abs, M::Abs, M::Abs, M::AbsLng, // 8 + M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::DirIdxX, M::DirIdxX, M::DirIdxY, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Imp, M::Imp, M::Abs, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX, // 9 + M::Imm, M::DirIdxIndX, M::Imm, M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Imp, M::Imm, M::Imp, M::Stk, M::Abs, M::Abs, M::Abs, M::AbsLng, // A + M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::DirIdxX, M::DirIdxX, M::DirIdxY, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Imp, M::Imp, M::AbsIdxX, M::AbsIdxX, M::AbsIdxY, M::AbsLngIdxX, // B + M::Imm, M::DirIdxIndX, M::Imm, M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Imp, M::Imm, M::Imp, M::Imp, M::Abs, M::Abs, M::Abs, M::AbsLng, // C + M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::Stk, M::DirIdxX, M::DirIdxX, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Stk, M::Imp, M::AbsIndLng, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX, // D + M::Imm, M::DirIdxIndX, M::Imm, M::StkRel, M::Dir, M::Dir, M::Dir, M::DirIndLng, M::Imp, M::Imm, M::Imp, M::Imp, M::Abs, M::Abs, M::Abs, M::AbsLng, // E + M::Rel, M::DirIndIdxY, M::DirInd, M::StkRelIndIdxY, M::Stk, M::DirIdxX, M::DirIdxX, M::DirIndLngIdxY, M::Imp, M::AbsIdxY, M::Stk, M::Imp, M::AbsIdxXInd, M::AbsIdxX, M::AbsIdxX, M::AbsLngIdxX // F + }; + + memcpy(_opTable, opTable, sizeof(opTable)); + memcpy(_addrMode, addrMode, sizeof(addrMode)); + + _enableLogging = enableLogging; + _memory = memory; + _state = {}; + _state.PC = 0x400; + _state.EmulationMode = true; + SetFlags(ProcFlags::MemoryMode8); + SetFlags(ProcFlags::IndexMode8); +} + +Cpu::~Cpu() +{ +} + +void Cpu::Reset() +{ +} + +void Cpu::Exec() +{ + if(lastTest != _memory[0x200] || _enableLogging) { + std::cout << + "$" << HexUtilities::ToHex(_state.PC) << + " $" << HexUtilities::ToHex(_memory[_state.PC]) << + " A:$" << HexUtilities::ToHex(_state.A) << + " X:$" << HexUtilities::ToHex(_state.X) << + " Y:$" << HexUtilities::ToHex(_state.Y) << + " Test#:" << HexUtilities::ToHex(_memory[0x200]) << + std::endl; + lastTest = _memory[0x200]; + if(_memory[0x200] >= 0x2B) { + _enableLogging = true; + } + } + uint8_t opCode = GetOpCode(); + _instAddrMode = _addrMode[opCode]; + _operand = FetchEffectiveAddress(); + (this->*_opTable[opCode])(); + + opCount++; +} + +uint32_t Cpu::GetBank() +{ + return _state.DBR << 16; +} + +uint32_t Cpu::GetProgramAddress() +{ + return (_state.K << 16) | _state.PC; +} + +uint32_t Cpu::GetDataAddress(uint16_t addr) +{ + return (_state.DBR << 16) | addr; +} + +uint8_t Cpu::GetOpCode() +{ + uint8_t opCode = ReadCode(_state.PC, MemoryOperationType::ExecOpCode); + _state.PC++; + return opCode; +} + +void Cpu::DummyRead() +{ + ReadCode(_state.PC, MemoryOperationType::DummyRead); +} + +uint8_t Cpu::ReadOperandByte() +{ + return ReadCode(_state.PC++, MemoryOperationType::ExecOperand); +} + +uint16_t Cpu::ReadOperandWord() +{ + uint8_t lsb = ReadOperandByte(); + uint8_t msb = ReadOperandByte(); + return (msb << 8) | lsb; +} + +uint32_t Cpu::ReadOperandLong() +{ + uint8_t b1 = ReadOperandByte(); + uint8_t b2 = ReadOperandByte(); + uint8_t b3 = ReadOperandByte(); + return (b3 << 16) | (b2 << 8) | b1; +} + +uint8_t Cpu::ReadCode(uint16_t addr, MemoryOperationType type) +{ + return _memory[(_state.K << 16) | addr]; +} + +uint8_t Cpu::ReadData(uint32_t addr, MemoryOperationType type) +{ + return _memory[addr]; +} + +uint16_t Cpu::ReadDataWord(uint32_t addr, MemoryOperationType type) +{ + uint8_t lsb = ReadData(addr); + uint8_t msb = ReadData(addr + 1); + return (msb << 8) | lsb; +} + +uint32_t Cpu::ReadDataLong(uint32_t addr, MemoryOperationType type) +{ + uint8_t b1 = ReadData(addr); + uint8_t b2 = ReadData(addr + 1); + uint8_t b3 = ReadData(addr + 2); + return (b3 << 16) | (b2 << 8) | b1; +} + +void Cpu::Write(uint32_t addr, uint8_t value, MemoryOperationType type) +{ + _memory[addr] = value; + if(_enableLogging) { + std::cout << "W: $" << HexUtilities::ToHex(addr) << " = $" << HexUtilities::ToHex(value) << std::endl; + } +} + +void Cpu::WriteWord(uint32_t addr, uint16_t value, MemoryOperationType type) +{ + Write(addr, (uint8_t)value); + Write(addr + 1, (uint8_t)(value >> 8)); +} + +uint8_t Cpu::GetByteValue() +{ + if(_instAddrMode == AddrMode::Imm) { + return (uint8_t)_operand; + } else { + return ReadData(_operand); + } +} + +uint16_t Cpu::GetWordValue() +{ + if(_instAddrMode == AddrMode::Imm) { + return (uint16_t)_operand; + } else { + return ReadDataWord(_operand); + } +} + +void Cpu::PushByte(uint8_t value) +{ + if(_state.EmulationMode) { + _state.SP = 0x100 | (_state.SP & 0xFF); + Write(_state.SP, value); + _state.SP = 0x100 | ((_state.SP - 1) & 0xFF); + } else { + Write(_state.SP, value); + _state.SP--; + } +} + +uint8_t Cpu::PopByte() +{ + if(_state.EmulationMode) { + _state.SP = 0x100 | ((_state.SP + 1) & 0xFF); + } else { + _state.SP++; + } + return _memory[_state.SP]; +} + +void Cpu::PushWord(uint16_t value) +{ + PushByte(value >> 8); + PushByte((uint8_t)value); +} + +uint16_t Cpu::PopWord() +{ + uint8_t lo = PopByte(); + uint8_t hi = PopByte(); + return lo | hi << 8; +} + +uint16_t Cpu::GetDirectAddress(uint8_t baseAddress, uint16_t offset, bool allowEmulationMode) +{ + if(allowEmulationMode && _state.EmulationMode && (_state.D & 0xFF) == 0) { + //TODO: Check if new instruction or not (PEI) + return (uint16_t)((_state.D & 0xFF00) | ((baseAddress + offset) & 0xFF)); + } else { + return (uint16_t)(_state.D + baseAddress + offset); + } +} + +uint32_t Cpu::FetchEffectiveAddress() +{ + switch(_instAddrMode) { + /* OK */ case AddrMode::Abs: return GetBank() | ReadOperandWord(); + /* OK */ case AddrMode::AbsIdxXInd: return ReadDataWord((_state.K << 16) | ReadOperandWord()); //JMP/JSR + /* OK */ case AddrMode::AbsIdxX: return (GetBank() | ReadOperandWord()) + _state.X; + /* OK */ case AddrMode::AbsIdxY: return (GetBank() | ReadOperandWord()) + _state.Y; + /* OK */ case AddrMode::AbsInd: return ReadDataWord(ReadOperandWord()); //JMP only + /* OK */ case AddrMode::AbsIndLng: return ReadDataLong(ReadOperandLong()); //JML only + + /* OK */ case AddrMode::AbsLngIdxX: return ReadOperandLong() + _state.X; + /* OK */ case AddrMode::AbsLng: return ReadOperandLong(); + + /* OK */ case AddrMode::Acc: DummyRead(); return 0; + + case AddrMode::BlkMov: return ReadOperandWord(); + + /* OK */ case AddrMode::DirIdxIndX: { + uint8_t operand = ReadOperandByte(); + uint8_t lsb = ReadData(GetDirectAddress(operand, _state.X)); + uint8_t msb = ReadData(GetDirectAddress(operand, _state.X + 1)); + return GetBank() | (msb << 8) | lsb; + } + + /* OK */ case AddrMode::DirIdxX: return GetDirectAddress(ReadOperandByte(), _state.X); + /* OK */ case AddrMode::DirIdxY: return GetDirectAddress(ReadOperandByte(), _state.Y); + + /* OK */ case AddrMode::DirIndIdxY:{ + uint8_t operand = ReadOperandByte(); + uint8_t lsb = ReadData(GetDirectAddress(operand)); + uint8_t msb = ReadData(GetDirectAddress(operand, 1)); + return (GetBank() | (msb << 8) | lsb) + _state.Y; + } + + /* OK */ case AddrMode::DirIndLngIdxY: { + uint8_t operand = ReadOperandByte(); + uint8_t b1 = ReadData(GetDirectAddress(operand)); + uint8_t b2 = ReadData(GetDirectAddress(operand, 1)); + uint8_t b3 = ReadData(GetDirectAddress(operand, 2)); + return ((b3 << 16) | (b2 << 8) | b1) + _state.Y; + } + + /* OK */ case AddrMode::DirIndLng: { + uint8_t operand = ReadOperandByte(); + uint8_t b1 = ReadData(GetDirectAddress(operand)); + uint8_t b2 = ReadData(GetDirectAddress(operand, 1)); + uint8_t b3 = ReadData(GetDirectAddress(operand, 2)); + return (b3 << 16) | (b2 << 8) | b1; + } + + /* OK */ case AddrMode::DirInd: { + uint8_t operand = ReadOperandByte(); + uint8_t lsb = ReadData(GetDirectAddress(operand)); + uint8_t msb = ReadData(GetDirectAddress(operand, 1)); + return GetBank() | (msb << 8) | lsb; + } + + /* OK */ case AddrMode::Dir: return GetDirectAddress(ReadOperandByte()); + + /* OK */ case AddrMode::Imm: return _state.EmulationMode ? ReadOperandByte() : ReadOperandWord(); + /* OK */ case AddrMode::Imp: DummyRead(); return 0; + + /* OK */ case AddrMode::RelLng: return ReadOperandWord(); + /* OK */ case AddrMode::Rel: return ReadOperandByte(); + + /* OK */ case AddrMode::Stk: return _state.SP; + /* OK */ case AddrMode::StkRel: return (uint16_t)(ReadOperandByte() + _state.SP); + + /* OK */ case AddrMode::StkRelIndIdxY: { + uint16_t addr = (uint16_t)(ReadOperandByte() + _state.SP); + return (GetBank() | addr) + _state.Y; + } + } + + throw new std::runtime_error("Unreacheable code"); +} + +void Cpu::SetRegister(uint8_t ®, uint8_t value) +{ + SetZeroNegativeFlags(value); + reg = value; +} + +void Cpu::SetRegister(uint16_t ®, uint16_t value, bool eightBitMode) +{ + if(eightBitMode) { + SetZeroNegativeFlags((uint8_t)value); + reg = (reg & 0xFF00) | (uint8_t)value; + } else { + SetZeroNegativeFlags(value); + reg = value; + } +} + +void Cpu::SetZeroNegativeFlags(uint16_t value) +{ + ClearFlags(ProcFlags::Zero | ProcFlags::Negative); + if(value == 0) { + SetFlags(ProcFlags::Zero); + } else if(value & 0x8000) { + SetFlags(ProcFlags::Negative); + } +} + +void Cpu::SetZeroNegativeFlags(uint8_t value) +{ + ClearFlags(ProcFlags::Zero | ProcFlags::Negative); + if(value == 0) { + SetFlags(ProcFlags::Zero); + } else if(value & 0x80) { + SetFlags(ProcFlags::Negative); + } +} + +void Cpu::ClearFlags(uint8_t flags) +{ + _state.PS &= ~flags; +} + +void Cpu::SetFlags(uint8_t flags) +{ + _state.PS |= flags; +} + +bool Cpu::CheckFlag(uint8_t flag) +{ + return (_state.PS & flag) == flag; +} diff --git a/Core/Cpu.h b/Core/Cpu.h new file mode 100644 index 0000000..c241c18 --- /dev/null +++ b/Core/Cpu.h @@ -0,0 +1,232 @@ +#pragma once +#include "stdafx.h" +#include "CpuTypes.h" + +class Cpu +{ +public: + uint64_t opCount = 0; + uint16_t GetPc() { return _state.PC; } + +private: + static constexpr uint32_t NmiVector = 0x00FFFA; + static constexpr uint32_t ResetVector = 0x00FFFC; + static constexpr uint32_t IrqVector = 0x00FFFE; + static constexpr uint32_t AbortVector = 0x00FFE8; + static constexpr uint32_t BreakVector = 0x00FFE6; + static constexpr uint32_t CoprocessorVector = 0x00FFE4; + + static constexpr uint16_t LegacyNmiVector = 0xFFFA; + static constexpr uint32_t LegacyBreakVector = 0xFFFE; + static constexpr uint32_t LegacyCoprocessorVector = 0x00FFF4; + + typedef void(Cpu::*Func)(); + + CpuState _state; + AddrMode _instAddrMode; + uint32_t _operand; + + uint8_t *_memory; + + Func _opTable[256]; + AddrMode _addrMode[256]; + + uint32_t GetBank(); + uint32_t GetProgramAddress(); + uint16_t GetDirectAddress(uint8_t baseAddress, uint16_t offset = 0, bool allowEmulationMode = true); + uint32_t GetDataAddress(uint16_t addr); + uint8_t GetOpCode(); + + void DummyRead(); + + uint8_t ReadOperandByte(); + uint16_t ReadOperandWord(); + uint32_t ReadOperandLong(); + uint32_t FetchEffectiveAddress(); + + void SetRegister(uint8_t ®, uint8_t value); + void SetRegister(uint16_t ®, uint16_t value, bool eightBitMode); + + void SetZeroNegativeFlags(uint16_t value); + void SetZeroNegativeFlags(uint8_t value); + + void ClearFlags(uint8_t flags); + void SetFlags(uint8_t flags); + bool CheckFlag(uint8_t flag); + + uint8_t ReadCode(uint16_t addr, MemoryOperationType type); + uint8_t ReadData(uint32_t addr, MemoryOperationType type = MemoryOperationType::Read); + uint16_t ReadDataWord(uint32_t addr, MemoryOperationType type = MemoryOperationType::Read); + uint32_t ReadDataLong(uint32_t addr, MemoryOperationType type = MemoryOperationType::Read); + + void Write(uint32_t addr, uint8_t value, MemoryOperationType type = MemoryOperationType::Write); + void WriteWord(uint32_t addr, uint16_t value, MemoryOperationType type = MemoryOperationType::Write); + + uint8_t GetByteValue(); + + uint16_t GetWordValue(); + + void PushByte(uint8_t value); + uint8_t PopByte(); + + void PushWord(uint16_t value); + uint16_t PopWord(); + + //Add/substract instructions + void Add8(uint8_t value); + void Add16(uint16_t value); + void ADC(); + + void Sub8(uint8_t value); + void Sub16(uint16_t value); + void SBC(); + + //Branch instructions + void BCC(); + void BCS(); + void BEQ(); + void BMI(); + void BNE(); + void BPL(); + void BRA(); + void BRL(); + void BVC(); + void BVS(); + void BranchRelative(bool branch); + + //Set/clear flag instructions + void CLC(); + void CLD(); + void CLI(); + void CLV(); + void SEC(); + void SED(); + void SEI(); + + void REP(); + void SEP(); + + //Increment/decrement instructions + void DEX(); + void DEY(); + void INX(); + void INY(); + void DEC(); + void INC(); + + void IncDecReg(uint16_t & reg, int8_t offset); + void IncDec(int8_t offset); + + //Compare instructions + void Compare(uint16_t reg, bool eightBitMode); + void CMP(); + void CPX(); + void CPY(); + + //Jump instructions + void JML(); + void JMP(); + void JSL(); + void JSR(); + void RTI(); + void RTL(); + void RTS(); + + //Interrupts + void ProcessInterrupt(uint16_t vector); + void BRK(); + void COP(); + + //Bitwise operations + void AND(); + void EOR(); + void ORA(); + + template T ShiftLeft(T value); + template T RollLeft(T value); + template T ShiftRight(T value); + template T RollRight(T value); + + //Shift operations + void ASL(); + void LSR(); + void ROL(); + void ROR(); + + //Move operations + void MVN(); + void MVP(); + + //Push/pull instructions + void PEA(); + void PEI(); + void PER(); + void PHB(); + void PHD(); + void PHK(); + void PHP(); + void PLB(); + void PLD(); + void PLP(); + + void PHA(); + void PHX(); + void PHY(); + void PLA(); + void PLX(); + void PLY(); + + void PushRegister(uint16_t reg, bool eightBitMode); + void PullRegister(uint16_t ®, bool eightBitMode); + + //Store/load instructions + void LoadRegister(uint16_t ®, bool eightBitMode); + void StoreRegister(uint16_t val, bool eightBitMode); + + void LDA(); + void LDX(); + void LDY(); + + void STA(); + void STX(); + void STY(); + void STZ(); + + //Test bits + template void TestBits(T value); + void BIT(); + + void TRB(); + void TSB(); + + //Transfer registers + void TAX(); + void TAY(); + void TCD(); + void TCS(); + void TDC(); + void TSC(); + void TSX(); + void TXA(); + void TXS(); + void TXY(); + void TYA(); + void TYX(); + void XBA(); + void XCE(); + + //No operation + void NOP(); + void WDM(); + + //Misc. + void STP(); + void WAI(); + +public: + Cpu(uint8_t* memory, bool enableLogging); + ~Cpu(); + + void Reset(); + void Exec(); +}; \ No newline at end of file diff --git a/Core/CpuTypes.h b/Core/CpuTypes.h new file mode 100644 index 0000000..156a68a --- /dev/null +++ b/Core/CpuTypes.h @@ -0,0 +1,92 @@ +#pragma once +#include "stdafx.h" + +struct CpuState +{ + uint64_t CycleCount; + + uint16_t A; + uint16_t X; + uint16_t Y; + + /* 16-bit stack pointer */ + uint16_t SP; + + /* 16-bit Direct Register provides an address offset for all instructions using direct addressing */ + uint16_t D; + + /* 16-bit Program Counter */ + uint16_t PC; + + /* 8-bit Program Bank Register holds the bank address for all instruction fetches. */ + uint8_t K; + + /* 8-bit Data Bank Register holds the bank address for memory transfers. The 24-bit address + is composed of the 16-bit instruction effective address and the 8-bit Data Bank address */ + uint8_t DBR; + + /* 8-bit status flags */ + uint8_t PS; + + /* 6502 emulation mode */ + bool EmulationMode; +}; + +namespace ProcFlags +{ + enum ProcFlags : uint8_t + { + Carry = 0x01, + Zero = 0x02, + IrqDisable = 0x04, + Decimal = 0x08, + + /* Use 8-bit operations on indexes */ + IndexMode8 = 0x10, + + /* Use 8-bit operations on memory accesses and accumulator */ + MemoryMode8 = 0x20, + + Overflow = 0x40, + Negative = 0x80 + }; +} + +enum class AddrMode +{ + Abs, + AbsIdxXInd, //JMP/JSR only + AbsIdxX, + AbsIdxY, + AbsInd, //JMP only + AbsIndLng, //JMP only (unofficial) + AbsLngIdxX, + AbsLng, + Acc, + BlkMov, + DirIdxIndX, + DirIdxX, + DirIdxY, + DirIndIdxY, + DirIndLngIdxY, + DirIndLng, + DirInd, + Dir, + Imm, + Imp, + RelLng, + Rel, + Stk, + StkRel, + StkRelIndIdxY +}; + +enum class MemoryOperationType +{ + Read = 0, + Write = 1, + ExecOpCode = 2, + ExecOperand = 3, + DummyRead = 5, + DummyWrite = 6 +}; \ No newline at end of file diff --git a/Core/main.cpp b/Core/main.cpp new file mode 100644 index 0000000..8cc9b65 --- /dev/null +++ b/Core/main.cpp @@ -0,0 +1,37 @@ +#include "stdafx.h" +#include "Cpu.h" +#include "../Utilities/Timer.h" + +int main() +{ + uint8_t* memory = new uint8_t[0x1000000]; + memset(memory, 0, 0x1000000); + ifstream testRom("..\\bin\\x64\\Debug\\6502_functional_test_v2.bin", ios::binary); + if(testRom) { + testRom.read((char*)memory+0x400, 0x10000); + } + + shared_ptr cpu(new Cpu(memory, false)); + Timer timer; + while(cpu->GetPc() != 0x32E9) { + cpu->Exec(); + } + + std::cout << "Time: " << std::to_string(timer.GetElapsedMS()) << std::endl; + std::cout << "OP Count: " << std::to_string(cpu->opCount) << std::endl; + std::cout << "OP/sec: " << std::to_string(cpu->opCount * 1000 / timer.GetElapsedMS()) << std::endl; +/* + memset(memory, 0, 0x1000000); + ifstream testRom2("..\\bin\\x64\\Debug\\65C02_extended_opcodes_test.bin", ios::binary); + if(testRom2) { + testRom2.read((char*)memory, 0x10000); + } + + cpu.reset(new Cpu(memory, true)); + timer.Reset(); + while(true) { + cpu->Exec(); + } + */ + while(true); +} \ No newline at end of file diff --git a/Core/stdafx.cpp b/Core/stdafx.cpp new file mode 100644 index 0000000..fd4f341 --- /dev/null +++ b/Core/stdafx.cpp @@ -0,0 +1 @@ +#include "stdafx.h" diff --git a/Core/stdafx.h b/Core/stdafx.h new file mode 100644 index 0000000..e0e5a34 --- /dev/null +++ b/Core/stdafx.h @@ -0,0 +1,50 @@ +#pragma once + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../Utilities/UTF8Util.h" + +#ifdef __clang__ + #define __forceinline __attribute__((always_inline)) +#else + #ifdef __GNUC__ + #define __forceinline + #endif +#endif + +using std::vector; +using std::shared_ptr; +using std::unique_ptr; +using std::weak_ptr; +using std::ios; +using std::istream; +using std::ostream; +using std::stringstream; +using utf8::ifstream; +using utf8::ofstream; +using std::list; +using std::max; +using std::string; +using std::atomic_flag; +using std::atomic; + +#ifdef _DEBUG +#pragma comment(lib, "C:\\Code\\Mesen-S\\bin\\x64\\Debug\\Utilities.lib") +#else +#pragma comment(lib, "C:\\Code\\Mesen-S\\bin\\x64\\Release\\Utilities.lib") +#endif \ No newline at end of file diff --git a/Mesen-S.sln b/Mesen-S.sln new file mode 100644 index 0000000..f2285c7 --- /dev/null +++ b/Mesen-S.sln @@ -0,0 +1,385 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2036 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "Core\Core.vcxproj", "{78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}" + ProjectSection(ProjectDependencies) = postProject + {B5330148-E8C7-46BA-B54E-69BE59EA337D} = {B5330148-E8C7-46BA-B54E-69BE59EA337D} + {B609E0A0-5050-4871-91D6-E760633BCDD1} = {B609E0A0-5050-4871-91D6-E760633BCDD1} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Utilities", "Utilities\Utilities.vcxproj", "{B5330148-E8C7-46BA-B54E-69BE59EA337D}" + ProjectSection(ProjectDependencies) = postProject + {52C4BA3A-E699-4305-B23F-C9083FD07AB6} = {52C4BA3A-E699-4305-B23F-C9083FD07AB6} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GUI.NET", "GUI.NET\GUI.NET.csproj", "{08D83A7E-52A9-451E-A53A-1A7946F8BB77}" + ProjectSection(ProjectDependencies) = postProject + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9} = {36ABBF1C-66E1-4577-828A-619A2EF0DAE9} + {AABB5225-3A49-47FF-8A48-031673CADCE9} = {AABB5225-3A49-47FF-8A48-031673CADCE9} + {37749BB2-FA78-4EC9-8990-5628FC0BBA19} = {37749BB2-FA78-4EC9-8990-5628FC0BBA19} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Windows", "Windows\Windows.vcxproj", "{7761E790-B42C-4179-8550-8365FF9EB23E}" + ProjectSection(ProjectDependencies) = postProject + {B5330148-E8C7-46BA-B54E-69BE59EA337D} = {B5330148-E8C7-46BA-B54E-69BE59EA337D} + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0} = {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InteropDLL", "InteropDLL\InteropDLL.vcxproj", "{37749BB2-FA78-4EC9-8990-5628FC0BBA19}" + ProjectSection(ProjectDependencies) = postProject + {B5330148-E8C7-46BA-B54E-69BE59EA337D} = {B5330148-E8C7-46BA-B54E-69BE59EA337D} + {7761E790-B42C-4179-8550-8365FF9EB23E} = {7761E790-B42C-4179-8550-8365FF9EB23E} + {B609E0A0-5050-4871-91D6-E760633BCDD1} = {B609E0A0-5050-4871-91D6-E760633BCDD1} + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0} = {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PGOHelper", "PGOHelper\PGOHelper.vcxproj", "{38D74EE1-5276-4D24-AABC-104B912A27D2}" + ProjectSection(ProjectDependencies) = postProject + {37749BB2-FA78-4EC9-8990-5628FC0BBA19} = {37749BB2-FA78-4EC9-8990-5628FC0BBA19} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestHelper", "TestHelper\TestHelper.vcxproj", "{2A607369-8B5D-494A-9E40-C5DC8D821AA3}" + ProjectSection(ProjectDependencies) = postProject + {37749BB2-FA78-4EC9-8990-5628FC0BBA19} = {37749BB2-FA78-4EC9-8990-5628FC0BBA19} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DependencyPacker", "DependencyPacker\DependencyPacker.csproj", "{AABB5225-3A49-47FF-8A48-031673CADCE9}" + ProjectSection(ProjectDependencies) = postProject + {37749BB2-FA78-4EC9-8990-5628FC0BBA19} = {37749BB2-FA78-4EC9-8990-5628FC0BBA19} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpdateHelper", "UpdateHelper\UpdateHelper.csproj", "{36ABBF1C-66E1-4577-828A-619A2EF0DAE9}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SevenZip", "SevenZip\SevenZip.vcxproj", "{52C4BA3A-E699-4305-B23F-C9083FD07AB6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Lua", "Lua\Lua.vcxproj", "{B609E0A0-5050-4871-91D6-E760633BCDD1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Libretro", "Libretro\Libretro.vcxproj", "{4432139E-528B-44DE-961C-B37CD5E92E0E}" + ProjectSection(ProjectDependencies) = postProject + {B5330148-E8C7-46BA-B54E-69BE59EA337D} = {B5330148-E8C7-46BA-B54E-69BE59EA337D} + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0} = {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Libretro|Any CPU = Libretro|Any CPU + Libretro|x64 = Libretro|x64 + Libretro|x86 = Libretro|x86 + PGO Optimize|Any CPU = PGO Optimize|Any CPU + PGO Optimize|x64 = PGO Optimize|x64 + PGO Optimize|x86 = PGO Optimize|x86 + PGO Profile|Any CPU = PGO Profile|Any CPU + PGO Profile|x64 = PGO Profile|x64 + PGO Profile|x86 = PGO Profile|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.Debug|x64.ActiveCfg = Debug|x64 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.Debug|x64.Build.0 = Debug|x64 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.Debug|x86.ActiveCfg = Debug|Win32 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.Debug|x86.Build.0 = Debug|Win32 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.Libretro|Any CPU.ActiveCfg = Libretro|Win32 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.Libretro|x64.ActiveCfg = Libretro|x64 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.Libretro|x64.Build.0 = Libretro|x64 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.Libretro|x86.ActiveCfg = Libretro|Win32 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.Libretro|x86.Build.0 = Libretro|Win32 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.PGO Optimize|Any CPU.ActiveCfg = PGO Optimize|Win32 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.PGO Optimize|x64.ActiveCfg = PGO Optimize|x64 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.PGO Optimize|x64.Build.0 = PGO Optimize|x64 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.PGO Optimize|x86.ActiveCfg = PGO Optimize|Win32 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.PGO Optimize|x86.Build.0 = PGO Optimize|Win32 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.PGO Profile|Any CPU.ActiveCfg = PGO Profile|Win32 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.PGO Profile|x64.ActiveCfg = PGO Profile|x64 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.PGO Profile|x64.Build.0 = PGO Profile|x64 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.PGO Profile|x86.ActiveCfg = PGO Profile|Win32 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.PGO Profile|x86.Build.0 = PGO Profile|Win32 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.Release|Any CPU.ActiveCfg = Release|Win32 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.Release|x64.ActiveCfg = Release|x64 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.Release|x64.Build.0 = Release|x64 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.Release|x86.ActiveCfg = Release|Win32 + {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}.Release|x86.Build.0 = Release|Win32 + {B5330148-E8C7-46BA-B54E-69BE59EA337D}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {B5330148-E8C7-46BA-B54E-69BE59EA337D}.Debug|x64.ActiveCfg = Debug|x64 + {B5330148-E8C7-46BA-B54E-69BE59EA337D}.Debug|x64.Build.0 = Debug|x64 + {B5330148-E8C7-46BA-B54E-69BE59EA337D}.Debug|x86.ActiveCfg = Debug|Win32 + {B5330148-E8C7-46BA-B54E-69BE59EA337D}.Debug|x86.Build.0 = Debug|Win32 + {B5330148-E8C7-46BA-B54E-69BE59EA337D}.Libretro|Any CPU.ActiveCfg = Libretro|Win32 + {B5330148-E8C7-46BA-B54E-69BE59EA337D}.Libretro|x64.ActiveCfg = Libretro|x64 + {B5330148-E8C7-46BA-B54E-69BE59EA337D}.Libretro|x64.Build.0 = Libretro|x64 + {B5330148-E8C7-46BA-B54E-69BE59EA337D}.Libretro|x86.ActiveCfg = Libretro|Win32 + {B5330148-E8C7-46BA-B54E-69BE59EA337D}.Libretro|x86.Build.0 = Libretro|Win32 + {B5330148-E8C7-46BA-B54E-69BE59EA337D}.PGO Optimize|Any CPU.ActiveCfg = PGO Optimize|Win32 + {B5330148-E8C7-46BA-B54E-69BE59EA337D}.PGO Optimize|x64.ActiveCfg = PGO Optimize|x64 + {B5330148-E8C7-46BA-B54E-69BE59EA337D}.PGO Optimize|x64.Build.0 = PGO Optimize|x64 + {B5330148-E8C7-46BA-B54E-69BE59EA337D}.PGO Optimize|x86.ActiveCfg = PGO Optimize|Win32 + {B5330148-E8C7-46BA-B54E-69BE59EA337D}.PGO Optimize|x86.Build.0 = PGO Optimize|Win32 + {B5330148-E8C7-46BA-B54E-69BE59EA337D}.PGO Profile|Any CPU.ActiveCfg = PGO Profile|Win32 + {B5330148-E8C7-46BA-B54E-69BE59EA337D}.PGO Profile|x64.ActiveCfg = PGO Profile|x64 + {B5330148-E8C7-46BA-B54E-69BE59EA337D}.PGO Profile|x64.Build.0 = PGO Profile|x64 + {B5330148-E8C7-46BA-B54E-69BE59EA337D}.PGO Profile|x86.ActiveCfg = PGO Profile|Win32 + {B5330148-E8C7-46BA-B54E-69BE59EA337D}.PGO Profile|x86.Build.0 = PGO Profile|Win32 + {B5330148-E8C7-46BA-B54E-69BE59EA337D}.Release|Any CPU.ActiveCfg = Release|Win32 + {B5330148-E8C7-46BA-B54E-69BE59EA337D}.Release|x64.ActiveCfg = Release|x64 + {B5330148-E8C7-46BA-B54E-69BE59EA337D}.Release|x64.Build.0 = Release|x64 + {B5330148-E8C7-46BA-B54E-69BE59EA337D}.Release|x86.ActiveCfg = Release|Win32 + {B5330148-E8C7-46BA-B54E-69BE59EA337D}.Release|x86.Build.0 = Release|Win32 + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.Debug|Any CPU.Build.0 = Debug|Any CPU + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.Debug|x64.ActiveCfg = Debug|x64 + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.Debug|x64.Build.0 = Debug|x64 + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.Debug|x86.ActiveCfg = Debug|x86 + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.Debug|x86.Build.0 = Debug|x86 + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.Libretro|Any CPU.ActiveCfg = Libretro|Any CPU + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.Libretro|Any CPU.Build.0 = Libretro|Any CPU + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.Libretro|x64.ActiveCfg = Libretro|x64 + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.Libretro|x86.ActiveCfg = Libretro|x86 + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.PGO Optimize|Any CPU.ActiveCfg = PGO Optimize|Any CPU + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.PGO Optimize|Any CPU.Build.0 = PGO Optimize|Any CPU + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.PGO Optimize|x64.ActiveCfg = PGO Optimize|x64 + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.PGO Optimize|x64.Build.0 = PGO Optimize|x64 + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.PGO Optimize|x86.ActiveCfg = PGO Optimize|x86 + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.PGO Optimize|x86.Build.0 = PGO Optimize|x86 + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.PGO Profile|Any CPU.ActiveCfg = PGO Profile|Any CPU + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.PGO Profile|Any CPU.Build.0 = PGO Profile|Any CPU + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.PGO Profile|x64.ActiveCfg = PGO Profile|x64 + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.PGO Profile|x64.Build.0 = PGO Profile|x64 + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.PGO Profile|x86.ActiveCfg = PGO Profile|x86 + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.PGO Profile|x86.Build.0 = PGO Profile|x86 + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.Release|Any CPU.ActiveCfg = Release|Any CPU + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.Release|Any CPU.Build.0 = Release|Any CPU + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.Release|x64.ActiveCfg = Release|x64 + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.Release|x64.Build.0 = Release|x64 + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.Release|x86.ActiveCfg = Release|x86 + {08D83A7E-52A9-451E-A53A-1A7946F8BB77}.Release|x86.Build.0 = Release|x86 + {7761E790-B42C-4179-8550-8365FF9EB23E}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {7761E790-B42C-4179-8550-8365FF9EB23E}.Debug|x64.ActiveCfg = Debug|x64 + {7761E790-B42C-4179-8550-8365FF9EB23E}.Debug|x64.Build.0 = Debug|x64 + {7761E790-B42C-4179-8550-8365FF9EB23E}.Debug|x86.ActiveCfg = Debug|Win32 + {7761E790-B42C-4179-8550-8365FF9EB23E}.Debug|x86.Build.0 = Debug|Win32 + {7761E790-B42C-4179-8550-8365FF9EB23E}.Libretro|Any CPU.ActiveCfg = Libretro|Win32 + {7761E790-B42C-4179-8550-8365FF9EB23E}.Libretro|x64.ActiveCfg = Libretro|x64 + {7761E790-B42C-4179-8550-8365FF9EB23E}.Libretro|x86.ActiveCfg = Libretro|Win32 + {7761E790-B42C-4179-8550-8365FF9EB23E}.PGO Optimize|Any CPU.ActiveCfg = PGO Optimize|Win32 + {7761E790-B42C-4179-8550-8365FF9EB23E}.PGO Optimize|x64.ActiveCfg = PGO Optimize|x64 + {7761E790-B42C-4179-8550-8365FF9EB23E}.PGO Optimize|x64.Build.0 = PGO Optimize|x64 + {7761E790-B42C-4179-8550-8365FF9EB23E}.PGO Optimize|x86.ActiveCfg = PGO Optimize|Win32 + {7761E790-B42C-4179-8550-8365FF9EB23E}.PGO Optimize|x86.Build.0 = PGO Optimize|Win32 + {7761E790-B42C-4179-8550-8365FF9EB23E}.PGO Profile|Any CPU.ActiveCfg = PGO Profile|Win32 + {7761E790-B42C-4179-8550-8365FF9EB23E}.PGO Profile|x64.ActiveCfg = PGO Profile|x64 + {7761E790-B42C-4179-8550-8365FF9EB23E}.PGO Profile|x64.Build.0 = PGO Profile|x64 + {7761E790-B42C-4179-8550-8365FF9EB23E}.PGO Profile|x86.ActiveCfg = PGO Profile|Win32 + {7761E790-B42C-4179-8550-8365FF9EB23E}.PGO Profile|x86.Build.0 = PGO Profile|Win32 + {7761E790-B42C-4179-8550-8365FF9EB23E}.Release|Any CPU.ActiveCfg = Release|Win32 + {7761E790-B42C-4179-8550-8365FF9EB23E}.Release|x64.ActiveCfg = Release|x64 + {7761E790-B42C-4179-8550-8365FF9EB23E}.Release|x64.Build.0 = Release|x64 + {7761E790-B42C-4179-8550-8365FF9EB23E}.Release|x86.ActiveCfg = Release|Win32 + {7761E790-B42C-4179-8550-8365FF9EB23E}.Release|x86.Build.0 = Release|Win32 + {37749BB2-FA78-4EC9-8990-5628FC0BBA19}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {37749BB2-FA78-4EC9-8990-5628FC0BBA19}.Debug|x64.ActiveCfg = Debug|x64 + {37749BB2-FA78-4EC9-8990-5628FC0BBA19}.Debug|x64.Build.0 = Debug|x64 + {37749BB2-FA78-4EC9-8990-5628FC0BBA19}.Debug|x86.ActiveCfg = Debug|Win32 + {37749BB2-FA78-4EC9-8990-5628FC0BBA19}.Debug|x86.Build.0 = Debug|Win32 + {37749BB2-FA78-4EC9-8990-5628FC0BBA19}.Libretro|Any CPU.ActiveCfg = Libretro|Win32 + {37749BB2-FA78-4EC9-8990-5628FC0BBA19}.Libretro|x64.ActiveCfg = Libretro|x64 + {37749BB2-FA78-4EC9-8990-5628FC0BBA19}.Libretro|x86.ActiveCfg = Libretro|Win32 + {37749BB2-FA78-4EC9-8990-5628FC0BBA19}.PGO Optimize|Any CPU.ActiveCfg = PGO Optimize|Win32 + {37749BB2-FA78-4EC9-8990-5628FC0BBA19}.PGO Optimize|x64.ActiveCfg = PGO Optimize|x64 + {37749BB2-FA78-4EC9-8990-5628FC0BBA19}.PGO Optimize|x64.Build.0 = PGO Optimize|x64 + {37749BB2-FA78-4EC9-8990-5628FC0BBA19}.PGO Optimize|x86.ActiveCfg = PGO Optimize|Win32 + {37749BB2-FA78-4EC9-8990-5628FC0BBA19}.PGO Optimize|x86.Build.0 = PGO Optimize|Win32 + {37749BB2-FA78-4EC9-8990-5628FC0BBA19}.PGO Profile|Any CPU.ActiveCfg = PGO Profile|Win32 + {37749BB2-FA78-4EC9-8990-5628FC0BBA19}.PGO Profile|x64.ActiveCfg = PGO Profile|x64 + {37749BB2-FA78-4EC9-8990-5628FC0BBA19}.PGO Profile|x64.Build.0 = PGO Profile|x64 + {37749BB2-FA78-4EC9-8990-5628FC0BBA19}.PGO Profile|x86.ActiveCfg = PGO Profile|Win32 + {37749BB2-FA78-4EC9-8990-5628FC0BBA19}.PGO Profile|x86.Build.0 = PGO Profile|Win32 + {37749BB2-FA78-4EC9-8990-5628FC0BBA19}.Release|Any CPU.ActiveCfg = Release|Win32 + {37749BB2-FA78-4EC9-8990-5628FC0BBA19}.Release|x64.ActiveCfg = Release|x64 + {37749BB2-FA78-4EC9-8990-5628FC0BBA19}.Release|x64.Build.0 = Release|x64 + {37749BB2-FA78-4EC9-8990-5628FC0BBA19}.Release|x86.ActiveCfg = Release|Win32 + {37749BB2-FA78-4EC9-8990-5628FC0BBA19}.Release|x86.Build.0 = Release|Win32 + {38D74EE1-5276-4D24-AABC-104B912A27D2}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {38D74EE1-5276-4D24-AABC-104B912A27D2}.Debug|x64.ActiveCfg = Debug|x64 + {38D74EE1-5276-4D24-AABC-104B912A27D2}.Debug|x64.Build.0 = Debug|x64 + {38D74EE1-5276-4D24-AABC-104B912A27D2}.Debug|x86.ActiveCfg = Debug|Win32 + {38D74EE1-5276-4D24-AABC-104B912A27D2}.Debug|x86.Build.0 = Debug|Win32 + {38D74EE1-5276-4D24-AABC-104B912A27D2}.Libretro|Any CPU.ActiveCfg = Libretro|Win32 + {38D74EE1-5276-4D24-AABC-104B912A27D2}.Libretro|x64.ActiveCfg = Libretro|x64 + {38D74EE1-5276-4D24-AABC-104B912A27D2}.Libretro|x86.ActiveCfg = Libretro|Win32 + {38D74EE1-5276-4D24-AABC-104B912A27D2}.PGO Optimize|Any CPU.ActiveCfg = PGO Optimize|Win32 + {38D74EE1-5276-4D24-AABC-104B912A27D2}.PGO Optimize|x64.ActiveCfg = PGO Optimize|x64 + {38D74EE1-5276-4D24-AABC-104B912A27D2}.PGO Optimize|x64.Build.0 = PGO Optimize|x64 + {38D74EE1-5276-4D24-AABC-104B912A27D2}.PGO Optimize|x86.ActiveCfg = PGO Optimize|Win32 + {38D74EE1-5276-4D24-AABC-104B912A27D2}.PGO Optimize|x86.Build.0 = PGO Optimize|Win32 + {38D74EE1-5276-4D24-AABC-104B912A27D2}.PGO Profile|Any CPU.ActiveCfg = PGO Profile|Win32 + {38D74EE1-5276-4D24-AABC-104B912A27D2}.PGO Profile|x64.ActiveCfg = PGO Profile|x64 + {38D74EE1-5276-4D24-AABC-104B912A27D2}.PGO Profile|x64.Build.0 = PGO Profile|x64 + {38D74EE1-5276-4D24-AABC-104B912A27D2}.PGO Profile|x86.ActiveCfg = PGO Profile|Win32 + {38D74EE1-5276-4D24-AABC-104B912A27D2}.PGO Profile|x86.Build.0 = PGO Profile|Win32 + {38D74EE1-5276-4D24-AABC-104B912A27D2}.Release|Any CPU.ActiveCfg = Release|Win32 + {38D74EE1-5276-4D24-AABC-104B912A27D2}.Release|x64.ActiveCfg = Release|x64 + {38D74EE1-5276-4D24-AABC-104B912A27D2}.Release|x64.Build.0 = Release|x64 + {38D74EE1-5276-4D24-AABC-104B912A27D2}.Release|x86.ActiveCfg = Release|Win32 + {38D74EE1-5276-4D24-AABC-104B912A27D2}.Release|x86.Build.0 = Release|Win32 + {2A607369-8B5D-494A-9E40-C5DC8D821AA3}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {2A607369-8B5D-494A-9E40-C5DC8D821AA3}.Debug|x64.ActiveCfg = Debug|x64 + {2A607369-8B5D-494A-9E40-C5DC8D821AA3}.Debug|x64.Build.0 = Debug|x64 + {2A607369-8B5D-494A-9E40-C5DC8D821AA3}.Debug|x86.ActiveCfg = Debug|Win32 + {2A607369-8B5D-494A-9E40-C5DC8D821AA3}.Debug|x86.Build.0 = Debug|Win32 + {2A607369-8B5D-494A-9E40-C5DC8D821AA3}.Libretro|Any CPU.ActiveCfg = Libretro|Win32 + {2A607369-8B5D-494A-9E40-C5DC8D821AA3}.Libretro|x64.ActiveCfg = Libretro|x64 + {2A607369-8B5D-494A-9E40-C5DC8D821AA3}.Libretro|x86.ActiveCfg = Libretro|Win32 + {2A607369-8B5D-494A-9E40-C5DC8D821AA3}.PGO Optimize|Any CPU.ActiveCfg = PGO Optimize|Win32 + {2A607369-8B5D-494A-9E40-C5DC8D821AA3}.PGO Optimize|x64.ActiveCfg = PGO Optimize|x64 + {2A607369-8B5D-494A-9E40-C5DC8D821AA3}.PGO Optimize|x64.Build.0 = PGO Optimize|x64 + {2A607369-8B5D-494A-9E40-C5DC8D821AA3}.PGO Optimize|x86.ActiveCfg = PGO Optimize|Win32 + {2A607369-8B5D-494A-9E40-C5DC8D821AA3}.PGO Optimize|x86.Build.0 = PGO Optimize|Win32 + {2A607369-8B5D-494A-9E40-C5DC8D821AA3}.PGO Profile|Any CPU.ActiveCfg = PGO Profile|Win32 + {2A607369-8B5D-494A-9E40-C5DC8D821AA3}.PGO Profile|x64.ActiveCfg = PGO Profile|x64 + {2A607369-8B5D-494A-9E40-C5DC8D821AA3}.PGO Profile|x64.Build.0 = PGO Profile|x64 + {2A607369-8B5D-494A-9E40-C5DC8D821AA3}.PGO Profile|x86.ActiveCfg = PGO Profile|Win32 + {2A607369-8B5D-494A-9E40-C5DC8D821AA3}.PGO Profile|x86.Build.0 = PGO Profile|Win32 + {2A607369-8B5D-494A-9E40-C5DC8D821AA3}.Release|Any CPU.ActiveCfg = Release|Win32 + {2A607369-8B5D-494A-9E40-C5DC8D821AA3}.Release|x64.ActiveCfg = Release|x64 + {2A607369-8B5D-494A-9E40-C5DC8D821AA3}.Release|x64.Build.0 = Release|x64 + {2A607369-8B5D-494A-9E40-C5DC8D821AA3}.Release|x86.ActiveCfg = Release|Win32 + {2A607369-8B5D-494A-9E40-C5DC8D821AA3}.Release|x86.Build.0 = Release|Win32 + {AABB5225-3A49-47FF-8A48-031673CADCE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AABB5225-3A49-47FF-8A48-031673CADCE9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AABB5225-3A49-47FF-8A48-031673CADCE9}.Debug|x64.ActiveCfg = Debug|x64 + {AABB5225-3A49-47FF-8A48-031673CADCE9}.Debug|x64.Build.0 = Debug|x64 + {AABB5225-3A49-47FF-8A48-031673CADCE9}.Debug|x86.ActiveCfg = Debug|x86 + {AABB5225-3A49-47FF-8A48-031673CADCE9}.Debug|x86.Build.0 = Debug|x86 + {AABB5225-3A49-47FF-8A48-031673CADCE9}.Libretro|Any CPU.ActiveCfg = Libretro|Any CPU + {AABB5225-3A49-47FF-8A48-031673CADCE9}.Libretro|Any CPU.Build.0 = Libretro|Any CPU + {AABB5225-3A49-47FF-8A48-031673CADCE9}.Libretro|x64.ActiveCfg = Libretro|x64 + {AABB5225-3A49-47FF-8A48-031673CADCE9}.Libretro|x86.ActiveCfg = Libretro|x86 + {AABB5225-3A49-47FF-8A48-031673CADCE9}.PGO Optimize|Any CPU.ActiveCfg = PGO Optimize|Any CPU + {AABB5225-3A49-47FF-8A48-031673CADCE9}.PGO Optimize|Any CPU.Build.0 = PGO Optimize|Any CPU + {AABB5225-3A49-47FF-8A48-031673CADCE9}.PGO Optimize|x64.ActiveCfg = PGO Optimize|x64 + {AABB5225-3A49-47FF-8A48-031673CADCE9}.PGO Optimize|x64.Build.0 = PGO Optimize|x64 + {AABB5225-3A49-47FF-8A48-031673CADCE9}.PGO Optimize|x86.ActiveCfg = PGO Optimize|x86 + {AABB5225-3A49-47FF-8A48-031673CADCE9}.PGO Optimize|x86.Build.0 = PGO Optimize|x86 + {AABB5225-3A49-47FF-8A48-031673CADCE9}.PGO Profile|Any CPU.ActiveCfg = PGO Profile|Any CPU + {AABB5225-3A49-47FF-8A48-031673CADCE9}.PGO Profile|Any CPU.Build.0 = PGO Profile|Any CPU + {AABB5225-3A49-47FF-8A48-031673CADCE9}.PGO Profile|x64.ActiveCfg = PGO Profile|x64 + {AABB5225-3A49-47FF-8A48-031673CADCE9}.PGO Profile|x64.Build.0 = PGO Profile|x64 + {AABB5225-3A49-47FF-8A48-031673CADCE9}.PGO Profile|x86.ActiveCfg = PGO Profile|x86 + {AABB5225-3A49-47FF-8A48-031673CADCE9}.PGO Profile|x86.Build.0 = PGO Profile|x86 + {AABB5225-3A49-47FF-8A48-031673CADCE9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AABB5225-3A49-47FF-8A48-031673CADCE9}.Release|Any CPU.Build.0 = Release|Any CPU + {AABB5225-3A49-47FF-8A48-031673CADCE9}.Release|x64.ActiveCfg = Release|x64 + {AABB5225-3A49-47FF-8A48-031673CADCE9}.Release|x64.Build.0 = Release|x64 + {AABB5225-3A49-47FF-8A48-031673CADCE9}.Release|x86.ActiveCfg = Release|x86 + {AABB5225-3A49-47FF-8A48-031673CADCE9}.Release|x86.Build.0 = Release|x86 + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.Debug|x64.ActiveCfg = Debug|x64 + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.Debug|x64.Build.0 = Debug|x64 + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.Debug|x86.ActiveCfg = Debug|x86 + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.Debug|x86.Build.0 = Debug|x86 + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.Libretro|Any CPU.ActiveCfg = Libretro|Any CPU + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.Libretro|Any CPU.Build.0 = Libretro|Any CPU + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.Libretro|x64.ActiveCfg = Libretro|x64 + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.Libretro|x86.ActiveCfg = Libretro|x86 + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.PGO Optimize|Any CPU.ActiveCfg = PGO Optimize|Any CPU + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.PGO Optimize|Any CPU.Build.0 = PGO Optimize|Any CPU + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.PGO Optimize|x64.ActiveCfg = PGO Optimize|x64 + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.PGO Optimize|x64.Build.0 = PGO Optimize|x64 + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.PGO Optimize|x86.ActiveCfg = PGO Optimize|x86 + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.PGO Optimize|x86.Build.0 = PGO Optimize|x86 + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.PGO Profile|Any CPU.ActiveCfg = PGO Profile|Any CPU + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.PGO Profile|Any CPU.Build.0 = PGO Profile|Any CPU + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.PGO Profile|x64.ActiveCfg = PGO Profile|x64 + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.PGO Profile|x64.Build.0 = PGO Profile|x64 + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.PGO Profile|x86.ActiveCfg = PGO Profile|x86 + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.PGO Profile|x86.Build.0 = PGO Profile|x86 + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.Release|Any CPU.Build.0 = Release|Any CPU + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.Release|x64.ActiveCfg = Release|x64 + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.Release|x64.Build.0 = Release|x64 + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.Release|x86.ActiveCfg = Release|x86 + {36ABBF1C-66E1-4577-828A-619A2EF0DAE9}.Release|x86.Build.0 = Release|x86 + {52C4BA3A-E699-4305-B23F-C9083FD07AB6}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {52C4BA3A-E699-4305-B23F-C9083FD07AB6}.Debug|x64.ActiveCfg = Debug|x64 + {52C4BA3A-E699-4305-B23F-C9083FD07AB6}.Debug|x64.Build.0 = Debug|x64 + {52C4BA3A-E699-4305-B23F-C9083FD07AB6}.Debug|x86.ActiveCfg = Debug|Win32 + {52C4BA3A-E699-4305-B23F-C9083FD07AB6}.Debug|x86.Build.0 = Debug|Win32 + {52C4BA3A-E699-4305-B23F-C9083FD07AB6}.Libretro|Any CPU.ActiveCfg = Libretro|Win32 + {52C4BA3A-E699-4305-B23F-C9083FD07AB6}.Libretro|x64.ActiveCfg = Libretro|x64 + {52C4BA3A-E699-4305-B23F-C9083FD07AB6}.Libretro|x64.Build.0 = Libretro|x64 + {52C4BA3A-E699-4305-B23F-C9083FD07AB6}.Libretro|x86.ActiveCfg = Libretro|Win32 + {52C4BA3A-E699-4305-B23F-C9083FD07AB6}.Libretro|x86.Build.0 = Libretro|Win32 + {52C4BA3A-E699-4305-B23F-C9083FD07AB6}.PGO Optimize|Any CPU.ActiveCfg = PGO Optimize|Win32 + {52C4BA3A-E699-4305-B23F-C9083FD07AB6}.PGO Optimize|x64.ActiveCfg = PGO Optimize|x64 + {52C4BA3A-E699-4305-B23F-C9083FD07AB6}.PGO Optimize|x64.Build.0 = PGO Optimize|x64 + {52C4BA3A-E699-4305-B23F-C9083FD07AB6}.PGO Optimize|x86.ActiveCfg = PGO Optimize|Win32 + {52C4BA3A-E699-4305-B23F-C9083FD07AB6}.PGO Optimize|x86.Build.0 = PGO Optimize|Win32 + {52C4BA3A-E699-4305-B23F-C9083FD07AB6}.PGO Profile|Any CPU.ActiveCfg = PGO Profile|Win32 + {52C4BA3A-E699-4305-B23F-C9083FD07AB6}.PGO Profile|x64.ActiveCfg = PGO Profile|x64 + {52C4BA3A-E699-4305-B23F-C9083FD07AB6}.PGO Profile|x64.Build.0 = PGO Profile|x64 + {52C4BA3A-E699-4305-B23F-C9083FD07AB6}.PGO Profile|x86.ActiveCfg = PGO Profile|Win32 + {52C4BA3A-E699-4305-B23F-C9083FD07AB6}.PGO Profile|x86.Build.0 = PGO Profile|Win32 + {52C4BA3A-E699-4305-B23F-C9083FD07AB6}.Release|Any CPU.ActiveCfg = Release|Win32 + {52C4BA3A-E699-4305-B23F-C9083FD07AB6}.Release|x64.ActiveCfg = Release|x64 + {52C4BA3A-E699-4305-B23F-C9083FD07AB6}.Release|x64.Build.0 = Release|x64 + {52C4BA3A-E699-4305-B23F-C9083FD07AB6}.Release|x86.ActiveCfg = Release|Win32 + {52C4BA3A-E699-4305-B23F-C9083FD07AB6}.Release|x86.Build.0 = Release|Win32 + {B609E0A0-5050-4871-91D6-E760633BCDD1}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {B609E0A0-5050-4871-91D6-E760633BCDD1}.Debug|x64.ActiveCfg = Debug|x64 + {B609E0A0-5050-4871-91D6-E760633BCDD1}.Debug|x64.Build.0 = Debug|x64 + {B609E0A0-5050-4871-91D6-E760633BCDD1}.Debug|x86.ActiveCfg = Debug|Win32 + {B609E0A0-5050-4871-91D6-E760633BCDD1}.Debug|x86.Build.0 = Debug|Win32 + {B609E0A0-5050-4871-91D6-E760633BCDD1}.Libretro|Any CPU.ActiveCfg = Libretro|Win32 + {B609E0A0-5050-4871-91D6-E760633BCDD1}.Libretro|x64.ActiveCfg = Libretro|x64 + {B609E0A0-5050-4871-91D6-E760633BCDD1}.Libretro|x86.ActiveCfg = Libretro|Win32 + {B609E0A0-5050-4871-91D6-E760633BCDD1}.PGO Optimize|Any CPU.ActiveCfg = PGO Optimize|Win32 + {B609E0A0-5050-4871-91D6-E760633BCDD1}.PGO Optimize|x64.ActiveCfg = PGO Optimize|x64 + {B609E0A0-5050-4871-91D6-E760633BCDD1}.PGO Optimize|x64.Build.0 = PGO Optimize|x64 + {B609E0A0-5050-4871-91D6-E760633BCDD1}.PGO Optimize|x86.ActiveCfg = PGO Optimize|Win32 + {B609E0A0-5050-4871-91D6-E760633BCDD1}.PGO Optimize|x86.Build.0 = PGO Optimize|Win32 + {B609E0A0-5050-4871-91D6-E760633BCDD1}.PGO Profile|Any CPU.ActiveCfg = PGO Profile|Win32 + {B609E0A0-5050-4871-91D6-E760633BCDD1}.PGO Profile|x64.ActiveCfg = PGO Profile|x64 + {B609E0A0-5050-4871-91D6-E760633BCDD1}.PGO Profile|x64.Build.0 = PGO Profile|x64 + {B609E0A0-5050-4871-91D6-E760633BCDD1}.PGO Profile|x86.ActiveCfg = PGO Profile|Win32 + {B609E0A0-5050-4871-91D6-E760633BCDD1}.PGO Profile|x86.Build.0 = PGO Profile|Win32 + {B609E0A0-5050-4871-91D6-E760633BCDD1}.Release|Any CPU.ActiveCfg = Release|Win32 + {B609E0A0-5050-4871-91D6-E760633BCDD1}.Release|x64.ActiveCfg = Release|x64 + {B609E0A0-5050-4871-91D6-E760633BCDD1}.Release|x64.Build.0 = Release|x64 + {B609E0A0-5050-4871-91D6-E760633BCDD1}.Release|x86.ActiveCfg = Release|Win32 + {B609E0A0-5050-4871-91D6-E760633BCDD1}.Release|x86.Build.0 = Release|Win32 + {4432139E-528B-44DE-961C-B37CD5E92E0E}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {4432139E-528B-44DE-961C-B37CD5E92E0E}.Debug|x64.ActiveCfg = Debug|x64 + {4432139E-528B-44DE-961C-B37CD5E92E0E}.Debug|x86.ActiveCfg = Debug|Win32 + {4432139E-528B-44DE-961C-B37CD5E92E0E}.Libretro|Any CPU.ActiveCfg = Libretro|Win32 + {4432139E-528B-44DE-961C-B37CD5E92E0E}.Libretro|x64.ActiveCfg = Libretro|x64 + {4432139E-528B-44DE-961C-B37CD5E92E0E}.Libretro|x64.Build.0 = Libretro|x64 + {4432139E-528B-44DE-961C-B37CD5E92E0E}.Libretro|x86.ActiveCfg = Libretro|Win32 + {4432139E-528B-44DE-961C-B37CD5E92E0E}.Libretro|x86.Build.0 = Libretro|Win32 + {4432139E-528B-44DE-961C-B37CD5E92E0E}.PGO Optimize|Any CPU.ActiveCfg = Release|x64 + {4432139E-528B-44DE-961C-B37CD5E92E0E}.PGO Optimize|x64.ActiveCfg = Release|x64 + {4432139E-528B-44DE-961C-B37CD5E92E0E}.PGO Optimize|x86.ActiveCfg = Release|Win32 + {4432139E-528B-44DE-961C-B37CD5E92E0E}.PGO Profile|Any CPU.ActiveCfg = Release|x64 + {4432139E-528B-44DE-961C-B37CD5E92E0E}.PGO Profile|x64.ActiveCfg = Release|x64 + {4432139E-528B-44DE-961C-B37CD5E92E0E}.PGO Profile|x86.ActiveCfg = Release|Win32 + {4432139E-528B-44DE-961C-B37CD5E92E0E}.Release|Any CPU.ActiveCfg = Release|Win32 + {4432139E-528B-44DE-961C-B37CD5E92E0E}.Release|x64.ActiveCfg = Release|x64 + {4432139E-528B-44DE-961C-B37CD5E92E0E}.Release|x86.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {26BA923A-ECE6-4040-8BA4-C9B43DE004B4} + EndGlobalSection + GlobalSection(Performance) = preSolution + HasPerformanceSessions = true + EndGlobalSection +EndGlobal diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..ef22dcc --- /dev/null +++ b/build.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +#This is a build script used for official releases which does not build the UI +#Read the makefile and use "make" to build Mesen normally + +if [ "$1" = libretro ]; then + MESENPLATFORM=x64 make clean + LTO=true MESENPLATFORM=x64 make libretro -j 16 + + MESENPLATFORM=x86 make clean + LTO=true MESENPLATFORM=x86 make libretro -j 16 +else + MESENPLATFORM=x64 BUILDTARGET=core ./buildPGO.sh + MESENPLATFORM=x86 BUILDTARGET=core ./buildPGO.sh + cp ./InteropDLL/obj.x64/libMesenCore.x64.dll ./bin/Any\ CPU/PGO\ Profile/Dependencies + cp ./InteropDLL/obj.x86/libMesenCore.x86.dll ./bin/Any\ CPU/PGO\ Profile/Dependencies +fi diff --git a/buildPGO.sh b/buildPGO.sh new file mode 100644 index 0000000..3bebdb5 --- /dev/null +++ b/buildPGO.sh @@ -0,0 +1,66 @@ +#!/bin/sh + +# This build is used to compile an instrumented version of the binary, run it, and then optimize the binary with the profiling data. +# LTO is also enabled by default by this script. +# On clang, this results in a +60% speed boost compared to using just "make" (w/o LTO) +# +# Rom files must be copied to the PGOHelper/PGOGames folder beforehand - all *.nes files in that folder will be executed as part of the profiling process. +# Using a variety of roms is recommended (e.g different mappers, etc.) +# +# You can run this script via make: +# For clang, run "make pgo" +# For GCC, run "USE_GCC=true make pgo" +# +# Note: While GCC runs through this script just fine, the runtime performance is pretty terrible (something must be wrong with the way this is built) +# +# This will produce the following binary: bin/x64/Release/Mesen.exe +if [ "$MESENPLATFORM" = x86 ]; then + PLAT="x86" +else + PLAT="x64" +fi + +if [ "$BUILDTARGET" = libretro ]; then + TARG="libretro" +else + TARG="core" +fi + +OBJ="PGOHelper/obj.${PLAT}/" +FLAGS="LTO=true MESENPLATFORM=${PLAT}" + +eval ${FLAGS} make clean + +#create instrumented binary +eval ${FLAGS} PGO=profile make ${TARG} -j 16 +eval ${FLAGS} PGO=profile make pgohelper -B +eval cp bin/pgohelperlib.so ${OBJ} + +#run the instrumented binary +cd ${OBJ} +./pgohelper +cd .. + +if [ "$USE_GCC" != true ]; then + #clang-specific steps to convert the profiling data and clean the files + llvm-profdata merge -output=pgo.profdata pgo.profraw + cd .. + eval ${FLAGS} make clean +else + cd .. +fi + +if [ "$BUILDTARGET" = "" ]; then + TARG="" +fi + +#rebuild using the profiling data to optimize +eval ${FLAGS} PGO=optimize make ${TARG} -j 16 -B + +if [ "$USE_GCC" != true ]; then + rm PGOHelper/pgo.profdata + rm PGOHelper/pgo.profraw +else + rm ./*.gcda +fi + diff --git a/makefile b/makefile new file mode 100644 index 0000000..28ce787 --- /dev/null +++ b/makefile @@ -0,0 +1,173 @@ +#Welcome to what must be the most terrible makefile ever (but hey, it works) +#Both clang & gcc work fine - clang seems to output faster code +#The only external dependency is SDL2 - everything else is pretty standard. +#Run "make" to build, "make run" to run + +#---------------------- +#Platform Configuration +#---------------------- +#To specify whether you want to build for x86 or x64: +#"MESENPLATFORM=x86 make" or "MESENPLATFORM=x64 make" +#Default is x64 + +#----------------------- +# Link Time Optimization +#----------------------- +#LTO is supported for clang and gcc (but only seems to help for clang?) +#LTO gives a 25-30% performance boost, so use it whenever you can +#Usage: LTO=true make + +MESENFLAGS= +libretro : MESENFLAGS=-D LIBRETRO + +ifeq ($(USE_GCC),true) + CPPC=g++ + CC=gcc + PROFILE_GEN_FLAG=-fprofile-generate + PROFILE_USE_FLAG=-fprofile-use +else + CPPC=clang++ + CC=clang + PROFILE_GEN_FLAG = -fprofile-instr-generate=$(CURDIR)/PGOHelper/pgo.profraw + PROFILE_USE_FLAG = -fprofile-instr-use=$(CURDIR)/PGOHelper/pgo.profdata +endif + +GCCOPTIONS=-fPIC -Wall --std=c++14 -O3 $(MESENFLAGS) +CCOPTIONS=-fPIC -Wall -O3 $(MESENFLAGS) + +ifeq ($(MESENPLATFORM),x86) + MESENPLATFORM=x86 + + GCCOPTIONS += -m32 + CCOPTIONS += -m32 +else + MESENPLATFORM=x64 + GCCOPTIONS += -m64 + CCOPTIONS += -m64 +endif + +ifeq ($(LTO),true) + CCOPTIONS += -flto + GCCOPTIONS += -flto +endif + +ifeq ($(PGO),profile) + CCOPTIONS += ${PROFILE_GEN_FLAG} + GCCOPTIONS += ${PROFILE_GEN_FLAG} +endif + +ifeq ($(PGO),optimize) + CCOPTIONS += ${PROFILE_USE_FLAG} + GCCOPTIONS += ${PROFILE_USE_FLAG} +endif + +OBJFOLDER=obj.$(MESENPLATFORM) +SHAREDLIB=libMesenCore.$(MESENPLATFORM).dll +LIBRETROLIB=mesen_libretro.$(MESENPLATFORM).so +RELEASEFOLDER=bin/$(MESENPLATFORM)/Release + +COREOBJ=$(patsubst Core/%.cpp,Core/$(OBJFOLDER)/%.o,$(wildcard Core/*.cpp)) +UTILOBJ=$(patsubst Utilities/%.cpp,Utilities/$(OBJFOLDER)/%.o,$(wildcard Utilities/*.cpp)) $(patsubst Utilities/HQX/%.cpp,Utilities/$(OBJFOLDER)/%.o,$(wildcard Utilities/HQX/*.cpp)) $(patsubst Utilities/xBRZ/%.cpp,Utilities/$(OBJFOLDER)/%.o,$(wildcard Utilities/xBRZ/*.cpp)) $(patsubst Utilities/KreedSaiEagle/%.cpp,Utilities/$(OBJFOLDER)/%.o,$(wildcard Utilities/KreedSaiEagle/*.cpp)) $(patsubst Utilities/Scale2x/%.cpp,Utilities/$(OBJFOLDER)/%.o,$(wildcard Utilities/Scale2x/*.cpp)) +LINUXOBJ=$(patsubst Linux/%.cpp,Linux/$(OBJFOLDER)/%.o,$(wildcard Linux/*.cpp)) +SEVENZIPOBJ=$(patsubst SevenZip/%.c,SevenZip/$(OBJFOLDER)/%.o,$(wildcard SevenZip/*.c)) +LUAOBJ=$(patsubst Lua/%.c,Lua/$(OBJFOLDER)/%.o,$(wildcard Lua/*.c)) + +ifeq ($(SYSTEM_LIBEVDEV), true) + LIBEVDEVLIB=$(shell pkg-config --libs libevdev) + LIBEVDEVINC=$(shell pkg-config --cflags libevdev) +else + LIBEVDEVOBJ=$(patsubst Linux/libevdev/%.c,Linux/$(OBJFOLDER)/%.o,$(wildcard Linux/libevdev/*.c)) + LIBEVDEVINC=-I../ +endif +SDL2LIB=$(shell sdl2-config --libs) +SDL2INC=$(shell sdl2-config --cflags) +FSLIB=-lstdc++fs + +all: ui + +ui: InteropDLL/$(OBJFOLDER)/$(SHAREDLIB) + mkdir -p $(RELEASEFOLDER)/Dependencies + rm -fr $(RELEASEFOLDER)/Dependencies/* + cd UpdateHelper && msbuild /property:Configuration="Release" /property:Platform="AnyCPU" + cp "bin/Any CPU/Release/MesenUpdater.exe" $(RELEASEFOLDER)/Dependencies/ + cp -r GUI.NET/Dependencies/* $(RELEASEFOLDER)/Dependencies/ + cp InteropDLL/$(OBJFOLDER)/$(SHAREDLIB) $(RELEASEFOLDER)/Dependencies/$(SHAREDLIB) + cd $(RELEASEFOLDER)/Dependencies && zip -r ../Dependencies.zip * + cd GUI.NET && msbuild /property:Configuration="Release" /property:Platform="$(MESENPLATFORM)" /property:PreBuildEvent="" '/property:DefineConstants="HIDETESTMENU;DISABLEAUTOUPDATE"' /property:CodeAnalysisRuleSet="" + +libretro: Libretro/$(OBJFOLDER)/$(LIBRETROLIB) + mkdir -p bin + cp ./Libretro/$(OBJFOLDER)/$(LIBRETROLIB) ./bin/ + +core: InteropDLL/$(OBJFOLDER)/$(SHAREDLIB) + +runtests: + cd TestHelper/$(OBJFOLDER) && ./testhelper + +rungametests: + cd TestHelper/$(OBJFOLDER) && ./testhelper ~/Mesen/TestGames + +testhelper: InteropDLL/$(OBJFOLDER)/$(SHAREDLIB) + mkdir -p TestHelper/$(OBJFOLDER) + $(CPPC) $(GCCOPTIONS) -Wl,-z,defs -o testhelper TestHelper/*.cpp InteropDLL/ConsoleWrapper.cpp $(SEVENZIPOBJ) $(LUAOBJ) $(LINUXOBJ) $(LIBEVDEVOBJ) $(UTILOBJ) $(COREOBJ) -pthread $(FSLIB) $(SDL2LIB) $(LIBEVDEVLIB) + mv testhelper TestHelper/$(OBJFOLDER) + +pgohelper: + mkdir -p PGOHelper/$(OBJFOLDER) && cd PGOHelper/$(OBJFOLDER) && $(CPPC) $(GCCOPTIONS) -Wl,-z,defs -o pgohelper ../PGOHelper.cpp ../../bin/pgohelperlib.so -pthread $(FSLIB) $(SDL2LIB) $(LIBEVDEVLIB) + +SevenZip/$(OBJFOLDER)/%.o: SevenZip/%.c + mkdir -p SevenZip/$(OBJFOLDER) && cd SevenZip/$(OBJFOLDER) && $(CC) $(CCOPTIONS) -c $(patsubst SevenZip/%, ../%, $<) +Lua/$(OBJFOLDER)/%.o: Lua/%.c + mkdir -p Lua/$(OBJFOLDER) && cd Lua/$(OBJFOLDER) && $(CC) $(CCOPTIONS) -c $(patsubst Lua/%, ../%, $<) +Utilities/$(OBJFOLDER)/%.o: Utilities/%.cpp + mkdir -p Utilities/$(OBJFOLDER) && cd Utilities/$(OBJFOLDER) && $(CPPC) $(GCCOPTIONS) -c $(patsubst Utilities/%, ../%, $<) +Utilities/$(OBJFOLDER)/%.o: Utilities/HQX/%.cpp + mkdir -p Utilities/$(OBJFOLDER) && cd Utilities/$(OBJFOLDER) && $(CPPC) $(GCCOPTIONS) -c $(patsubst Utilities/%, ../%, $<) +Utilities/$(OBJFOLDER)/%.o: Utilities/xBRZ/%.cpp + mkdir -p Utilities/$(OBJFOLDER) && cd Utilities/$(OBJFOLDER) && $(CPPC) $(GCCOPTIONS) -c $(patsubst Utilities/%, ../%, $<) +Utilities/$(OBJFOLDER)/%.o: Utilities/KreedSaiEagle/%.cpp + mkdir -p Utilities/$(OBJFOLDER) && cd Utilities/$(OBJFOLDER) && $(CPPC) $(GCCOPTIONS) -c $(patsubst Utilities/%, ../%, $<) +Utilities/$(OBJFOLDER)/%.o: Utilities/Scale2x/%.cpp + mkdir -p Utilities/$(OBJFOLDER) && cd Utilities/$(OBJFOLDER) && $(CPPC) $(GCCOPTIONS) -c $(patsubst Utilities/%, ../%, $<) +Core/$(OBJFOLDER)/%.o: Core/%.cpp + mkdir -p Core/$(OBJFOLDER) && cd Core/$(OBJFOLDER) && $(CPPC) $(GCCOPTIONS) -c $(patsubst Core/%, ../%, $<) +Linux/$(OBJFOLDER)/%.o: Linux/%.cpp + mkdir -p Linux/$(OBJFOLDER) && cd Linux/$(OBJFOLDER) && $(CPPC) $(GCCOPTIONS) -c $(patsubst Linux/%, ../%, $<) $(SDL2INC) $(LIBEVDEVINC) +Linux/$(OBJFOLDER)/%.o: Linux/libevdev/%.c + mkdir -p Linux/$(OBJFOLDER) && cd Linux/$(OBJFOLDER) && $(CC) $(CCOPTIONS) -c $(patsubst Linux/%, ../%, $<) + +InteropDLL/$(OBJFOLDER)/$(SHAREDLIB): $(SEVENZIPOBJ) $(LUAOBJ) $(UTILOBJ) $(COREOBJ) $(LIBEVDEVOBJ) $(LINUXOBJ) InteropDLL/ConsoleWrapper.cpp InteropDLL/DebugWrapper.cpp + mkdir -p InteropDLL/$(OBJFOLDER) + $(CPPC) $(GCCOPTIONS) -Wl,-z,defs -shared -o $(SHAREDLIB) InteropDLL/*.cpp $(SEVENZIPOBJ) $(LUAOBJ) $(LINUXOBJ) $(LIBEVDEVOBJ) $(UTILOBJ) $(COREOBJ) $(SDL2INC) -pthread $(FSLIB) $(SDL2LIB) $(LIBEVDEVLIB) + cp $(SHAREDLIB) bin/pgohelperlib.so + mv $(SHAREDLIB) InteropDLL/$(OBJFOLDER) + +Libretro/$(OBJFOLDER)/$(LIBRETROLIB): $(SEVENZIPOBJ) $(UTILOBJ) $(COREOBJ) $(LUAOBJ) Libretro/libretro.cpp + mkdir -p Libretro/$(OBJFOLDER) + $(CPPC) $(GCCOPTIONS) -Wl,-z,defs -shared -o $(LIBRETROLIB) Libretro/*.cpp $(SEVENZIPOBJ) $(UTILOBJ) $(COREOBJ) $(LUAOBJ) -pthread $(FSLIB) + cp $(LIBRETROLIB) bin/pgohelperlib.so + mv $(LIBRETROLIB) Libretro/$(OBJFOLDER) + +pgo: + ./buildPGO.sh + +official: + ./build.sh + +debug: + MONO_LOG_LEVEL=debug mono $(RELEASEFOLDER)/Mesen.exe + +run: + mono $(RELEASEFOLDER)/Mesen.exe + +clean: + rm -rf Lua/$(OBJFOLDER) + rm -rf SevenZip/$(OBJFOLDER) + rm -rf Utilities/$(OBJFOLDER) + rm -rf Core/$(OBJFOLDER) + rm -rf Linux/$(OBJFOLDER) + rm -rf InteropDLL/$(OBJFOLDER) + rm -rf Libretro/$(OBJFOLDER) + rm -rf TestHelper/$(OBJFOLDER) + rm -rf PGOHelper/$(OBJFOLDER) + rm -rf $(RELEASEFOLDER)