mirror of
https://github.com/libretro/Mesen.git
synced 2025-03-03 22:07:10 +00:00
Improved code structure
This commit is contained in:
parent
909e73a8d5
commit
630db30484
66
Core/BaseMapper.h
Normal file
66
Core/BaseMapper.h
Normal file
@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "ROMLoader.h"
|
||||
#include "IMemoryHandler.h"
|
||||
|
||||
class BaseMapper : public IMemoryHandler
|
||||
{
|
||||
protected:
|
||||
NESHeader _header;
|
||||
vector<MemoryBank> _romBanks;
|
||||
vector<MemoryBank> _vromBanks;
|
||||
|
||||
public:
|
||||
void Initialize(NESHeader header, vector<MemoryBank> romBanks, vector<MemoryBank> vromBanks)
|
||||
{
|
||||
_header = header;
|
||||
_romBanks = romBanks;
|
||||
_vromBanks = vromBanks;
|
||||
}
|
||||
};
|
||||
|
||||
class DefaultMapper : public BaseMapper
|
||||
{
|
||||
private:
|
||||
|
||||
public:
|
||||
std::array<int, 2> GetIOAddresses()
|
||||
{
|
||||
return std::array<int, 2> {{ 0x8000, 0xFFFF }};
|
||||
}
|
||||
|
||||
uint8_t MemoryRead(uint16_t addr)
|
||||
{
|
||||
return _romBanks[(addr >> 14) & 0x01][addr & 0x3FFF];
|
||||
}
|
||||
|
||||
void MemoryWrite(uint16_t addr, uint8_t value)
|
||||
{
|
||||
_romBanks[(addr >> 14) & 0x01][addr & 0x3FFF] = value;
|
||||
}
|
||||
};
|
||||
|
||||
class MapperFactory
|
||||
{
|
||||
public:
|
||||
static shared_ptr<BaseMapper> InitializeFromFile(char *filename)
|
||||
{
|
||||
ROMLoader loader(filename);
|
||||
|
||||
NESHeader header = loader.GetHeader();
|
||||
|
||||
uint8_t mapperID = header.GetMapperID();
|
||||
shared_ptr<BaseMapper> mapper = nullptr;
|
||||
switch(mapperID) {
|
||||
case 0: mapper = shared_ptr<BaseMapper>(new DefaultMapper()); break;
|
||||
}
|
||||
|
||||
if(!mapper) {
|
||||
throw std::exception("Unsupported mapper");
|
||||
}
|
||||
|
||||
mapper->Initialize(header, loader.GetROMBanks(), loader.GetVROMBanks());
|
||||
return mapper;
|
||||
}
|
||||
};
|
20
Core/CPU.cpp
20
Core/CPU.cpp
@ -60,7 +60,6 @@ void CPU::Reset()
|
||||
|
||||
void CPU::Exec()
|
||||
{
|
||||
uint16_t lastPC = 65535;
|
||||
uint32_t cycleCount = 0;
|
||||
|
||||
Timer timer;
|
||||
@ -75,7 +74,6 @@ void CPU::Exec()
|
||||
//std::cout << "Invalid opcode: PC:" << _currentPC << std::endl;
|
||||
throw std::exception("Invalid opcode");
|
||||
}
|
||||
lastPC = _currentPC;
|
||||
|
||||
if(cycleCount >= 200000000) {
|
||||
break;
|
||||
@ -84,21 +82,3 @@ void CPU::Exec()
|
||||
std::wstring result = L"Frequency: " + std::to_wstring((int)(cycleCount / timer.GetElapsedMS() * 1000 / 1000000)) + L"mhz\n";
|
||||
OutputDebugString(result.c_str());
|
||||
}
|
||||
|
||||
void CPU::RunBenchmark()
|
||||
{
|
||||
std::ifstream romFile("6502_functional_test.bin", std::ios::in | std::ios::binary);
|
||||
if(!romFile) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t *romMemory = new uint8_t[65536];
|
||||
romFile.read((char *)romMemory, 65536);
|
||||
|
||||
//Test a;
|
||||
|
||||
MemoryManager memoryManager(MapperFactory::InitializeFromFile("mario.nes"));
|
||||
//memoryManager.OnMemoryRead()->RegisterHandler(&a, &IMemoryHandler::MemoryRead);
|
||||
CPU core(&memoryManager);
|
||||
core.Exec();
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Memory.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
namespace PSFlags
|
||||
{
|
||||
@ -38,7 +40,6 @@ private:
|
||||
|
||||
MemoryManager *_memoryManager = nullptr;
|
||||
|
||||
|
||||
uint16_t _currentPC = 0;
|
||||
uint8_t _cyclePenalty = 0;
|
||||
|
||||
@ -600,5 +601,4 @@ public:
|
||||
CPU(MemoryManager *memoryManager);
|
||||
void Reset();
|
||||
void Exec();
|
||||
static void RunBenchmark();
|
||||
};
|
||||
};
|
31
Core/Console.cpp
Normal file
31
Core/Console.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
#include "stdafx.h"
|
||||
#include "Console.h"
|
||||
|
||||
Console::Console(char* filename)
|
||||
{
|
||||
_mapper = MapperFactory::InitializeFromFile(filename);
|
||||
_memoryManager.RegisterIODevice(_mapper.get());
|
||||
_memoryManager.RegisterIODevice(&_ppu);
|
||||
_cpu.reset(new CPU(&_memoryManager));
|
||||
}
|
||||
|
||||
Console::~Console()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Console::Reset()
|
||||
{
|
||||
_cpu->Reset();
|
||||
}
|
||||
|
||||
void Console::Run()
|
||||
{
|
||||
_cpu->Exec();
|
||||
}
|
||||
|
||||
void Console::RunBenchmark()
|
||||
{
|
||||
Console console("mario.nes");
|
||||
console.Run();
|
||||
}
|
21
Core/Console.h
Normal file
21
Core/Console.h
Normal file
@ -0,0 +1,21 @@
|
||||
#include "stdafx.h"
|
||||
#include "CPU.h"
|
||||
#include "PPU.h"
|
||||
#include "BaseMapper.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
class Console
|
||||
{
|
||||
private:
|
||||
unique_ptr<CPU> _cpu;
|
||||
PPU _ppu;
|
||||
shared_ptr<BaseMapper> _mapper;
|
||||
MemoryManager _memoryManager;
|
||||
|
||||
public:
|
||||
Console(char* filename);
|
||||
~Console();
|
||||
void Run();
|
||||
void Reset();
|
||||
static void RunBenchmark();
|
||||
};
|
@ -73,7 +73,7 @@
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
||||
<OmitFramePointers>false</OmitFramePointers>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
@ -84,16 +84,20 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="BaseMapper.h" />
|
||||
<ClInclude Include="IMemoryHandler.h" />
|
||||
<ClInclude Include="Console.h" />
|
||||
<ClInclude Include="PPU.h" />
|
||||
<ClInclude Include="CPU.h" />
|
||||
<ClInclude Include="EventHandler.h" />
|
||||
<ClInclude Include="Memory.h" />
|
||||
<ClInclude Include="MemoryManager.h" />
|
||||
<ClInclude Include="ROMLoader.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Console.cpp" />
|
||||
<ClCompile Include="MemoryManager.cpp" />
|
||||
<ClCompile Include="PPU.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="CPU.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
|
@ -24,20 +24,26 @@
|
||||
<ClInclude Include="CPU.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="EventHandler.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Memory.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PPU.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MemoryManager.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ROMLoader.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="BaseMapper.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="IMemoryHandler.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Console.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Timer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClCompile>
|
||||
@ -50,5 +56,11 @@
|
||||
<ClCompile Include="PPU.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MemoryManager.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Console.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
11
Core/IMemoryHandler.h
Normal file
11
Core/IMemoryHandler.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
class IMemoryHandler
|
||||
{
|
||||
public:
|
||||
virtual std::array<int, 2> GetIOAddresses() = 0;
|
||||
virtual uint8_t MemoryRead(uint16_t addr) = 0;
|
||||
virtual void MemoryWrite(uint16_t addr, uint8_t value) = 0;
|
||||
};
|
240
Core/Memory.h
240
Core/Memory.h
@ -1,240 +0,0 @@
|
||||
#include "stdafx.h"
|
||||
#include "EventHandler.h"
|
||||
#include "PPU.h"
|
||||
|
||||
using std::vector;
|
||||
using std::shared_ptr;
|
||||
using std::unique_ptr;
|
||||
using std::ios;
|
||||
using std::ifstream;
|
||||
|
||||
struct NESHeader
|
||||
{
|
||||
char NES[4];
|
||||
uint8_t ROMCount;
|
||||
uint8_t VROMCount;
|
||||
uint8_t Flags1;
|
||||
uint8_t Flags2;
|
||||
uint8_t RAMCount;
|
||||
uint8_t CartType;
|
||||
uint8_t Reserved[6];
|
||||
|
||||
uint8_t GetMapperID()
|
||||
{
|
||||
return (Flags2 & 0xF0) | (Flags1 >> 4);
|
||||
}
|
||||
};
|
||||
|
||||
typedef vector<uint8_t> MemoryBank;
|
||||
|
||||
class ROMLoader
|
||||
{
|
||||
private:
|
||||
const int ROMBankSize = 0x4000;
|
||||
const int VROMBankSize = 0x2000;
|
||||
NESHeader _header;
|
||||
vector<MemoryBank> _romBanks;
|
||||
vector<MemoryBank> _vromBanks;
|
||||
|
||||
public:
|
||||
ROMLoader(const char* filename)
|
||||
{
|
||||
_romBanks.clear();
|
||||
_vromBanks.clear();
|
||||
|
||||
ifstream romFile(filename, ios::in | ios::binary);
|
||||
|
||||
if(!romFile) {
|
||||
return;
|
||||
}
|
||||
|
||||
romFile.read((char*)&_header, sizeof(NESHeader));
|
||||
|
||||
uint8_t *buffer = new uint8_t[max(ROMBankSize, VROMBankSize)];
|
||||
for(int i = 0; i < _header.ROMCount; i++) {
|
||||
romFile.read((char*)buffer, ROMBankSize);
|
||||
_romBanks.push_back(MemoryBank(buffer, buffer + ROMBankSize));
|
||||
}
|
||||
|
||||
for(int i = 0; i < _header.VROMCount; i++) {
|
||||
romFile.read((char*)buffer, VROMBankSize);
|
||||
_vromBanks.push_back(MemoryBank(buffer, buffer + VROMBankSize));
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
|
||||
romFile.close();
|
||||
}
|
||||
|
||||
vector<MemoryBank> GetROMBanks()
|
||||
{
|
||||
return _romBanks;
|
||||
}
|
||||
|
||||
vector<MemoryBank> GetVROMBanks()
|
||||
{
|
||||
return _vromBanks;
|
||||
}
|
||||
|
||||
NESHeader GetHeader()
|
||||
{
|
||||
return _header;
|
||||
}
|
||||
};
|
||||
|
||||
class BaseMapper : public IMemoryHandler
|
||||
{
|
||||
protected:
|
||||
NESHeader _header;
|
||||
vector<MemoryBank> _romBanks;
|
||||
vector<MemoryBank> _vromBanks;
|
||||
|
||||
public:
|
||||
void Initialize(NESHeader header, vector<MemoryBank> romBanks, vector<MemoryBank> vromBanks)
|
||||
{
|
||||
_header = header;
|
||||
_romBanks = romBanks;
|
||||
_vromBanks = vromBanks;
|
||||
}
|
||||
};
|
||||
|
||||
class DefaultMapper : public BaseMapper
|
||||
{
|
||||
private:
|
||||
|
||||
|
||||
public:
|
||||
uint8_t MemoryRead(uint16_t addr)
|
||||
{
|
||||
return _romBanks[addr <= 0xC000 ? 0 : 1][addr & 0x3FFF];
|
||||
}
|
||||
|
||||
void MemoryWrite(uint16_t addr, uint8_t value)
|
||||
{
|
||||
_romBanks[addr <= 0xC000 ? 0 : 1][addr & 0x3FFF] = value;
|
||||
}
|
||||
};
|
||||
|
||||
class MapperFactory
|
||||
{
|
||||
public:
|
||||
static shared_ptr<BaseMapper> InitializeFromFile(char *filename)
|
||||
{
|
||||
ROMLoader loader(filename);
|
||||
|
||||
NESHeader header = loader.GetHeader();
|
||||
|
||||
uint8_t mapperID = header.GetMapperID();
|
||||
shared_ptr<BaseMapper> mapper = nullptr;
|
||||
switch(mapperID) {
|
||||
case 0: mapper = shared_ptr<BaseMapper>(new DefaultMapper()); break;
|
||||
}
|
||||
|
||||
if(!mapper) {
|
||||
throw std::exception("Unsupported mapper");
|
||||
}
|
||||
|
||||
mapper->Initialize(header, loader.GetROMBanks(), loader.GetVROMBanks());
|
||||
return mapper;
|
||||
}
|
||||
};
|
||||
|
||||
class MemoryManager
|
||||
{
|
||||
private:
|
||||
const int InternalRAMSize = 0x800;
|
||||
const int SRAMSize = 0x800;
|
||||
|
||||
/*EventHandler<IMemoryHandler, uint16_t> _readRegisterHandler;
|
||||
EventHandler<IMemoryHandler, uint16_t> _writeRegisterHandler;*/
|
||||
|
||||
shared_ptr<BaseMapper> _mapper;
|
||||
uint8_t *_internalRAM;
|
||||
uint8_t *_SRAM;
|
||||
|
||||
PPU _ppu;
|
||||
|
||||
vector<IMemoryHandler*> _registerHandlers;
|
||||
|
||||
void RegisterIODevice(IMemoryHandler *handler, uint16_t startAddr, uint16_t endAddr)
|
||||
{
|
||||
for(int i = startAddr; i < endAddr; i++) {
|
||||
_registerHandlers[i] = handler;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t ReadRegister(uint16_t addr)
|
||||
{
|
||||
if(_registerHandlers[addr] != nullptr) {
|
||||
return _registerHandlers[addr]->MemoryRead(addr);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void WriteRegister(uint16_t addr, uint8_t value)
|
||||
{
|
||||
if(_registerHandlers[addr] != nullptr) {
|
||||
_registerHandlers[addr]->MemoryWrite(addr, value);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
MemoryManager(shared_ptr<BaseMapper> mapper) : _mapper(mapper)
|
||||
{
|
||||
_internalRAM = new uint8_t[InternalRAMSize];
|
||||
_SRAM = new uint8_t[SRAMSize];
|
||||
ZeroMemory(_SRAM, SRAMSize);
|
||||
ZeroMemory(_internalRAM, InternalRAMSize);
|
||||
|
||||
for(int i = 0; i < 0xFFFF; i++) {
|
||||
_registerHandlers.push_back(nullptr);
|
||||
}
|
||||
|
||||
RegisterIODevice(&_ppu, 0x2000, 0x3FFF);
|
||||
}
|
||||
|
||||
~MemoryManager()
|
||||
{
|
||||
delete[] _internalRAM;
|
||||
delete[] _SRAM;
|
||||
}
|
||||
|
||||
uint8_t Read(uint16_t addr) {
|
||||
if(addr <= 0x1FFF) {
|
||||
return _internalRAM[addr & 0x07FF];
|
||||
} else if(addr <= 0x401F) {
|
||||
return ReadRegister(addr);
|
||||
} else if(addr <= 0x5FFF) {
|
||||
throw std::exception("Not implemented yet");
|
||||
//return ReadExpansionROM();
|
||||
} else if(addr <= 0x7FFF) {
|
||||
return _SRAM[addr];
|
||||
} else {
|
||||
return _mapper->MemoryRead(addr);
|
||||
}
|
||||
}
|
||||
|
||||
void Write(uint16_t addr, uint8_t value) {
|
||||
//_writeHandler(addr);
|
||||
if(addr <= 0x1FFFF) {
|
||||
_internalRAM[addr & 0x07FF] = value;
|
||||
} else if(addr <= 0x401F) {
|
||||
WriteRegister(addr, value);
|
||||
} else if(addr <= 0x5FFF) {
|
||||
throw std::exception("Not implemented yet");
|
||||
//return ReadExpansionROM();
|
||||
} else if(addr <= 0x7FFF) {
|
||||
_SRAM[addr] = value;
|
||||
} else {
|
||||
_mapper->MemoryWrite(addr, value);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t ReadWord(uint16_t addr) {
|
||||
uint8_t lo = Read(addr);
|
||||
uint8_t hi = Read(addr+1);
|
||||
return lo | hi << 8;
|
||||
}
|
||||
};
|
||||
|
84
Core/MemoryManager.cpp
Normal file
84
Core/MemoryManager.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
#include "stdafx.h"
|
||||
#include "MemoryManager.h"
|
||||
|
||||
uint8_t MemoryManager::ReadRegister(uint16_t addr)
|
||||
{
|
||||
if(_registerHandlers[addr]) {
|
||||
return _registerHandlers[addr]->MemoryRead(addr);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryManager::WriteRegister(uint16_t addr, uint8_t value)
|
||||
{
|
||||
if(_registerHandlers[addr]) {
|
||||
_registerHandlers[addr]->MemoryWrite(addr, value);
|
||||
}
|
||||
}
|
||||
|
||||
MemoryManager::MemoryManager()
|
||||
{
|
||||
_internalRAM = new uint8_t[InternalRAMSize];
|
||||
_SRAM = new uint8_t[SRAMSize];
|
||||
ZeroMemory(_SRAM, SRAMSize);
|
||||
ZeroMemory(_internalRAM, InternalRAMSize);
|
||||
|
||||
for(int i = 0; i < 0xFFFF; i++) {
|
||||
_registerHandlers.push_back(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
MemoryManager::~MemoryManager()
|
||||
{
|
||||
delete[] _internalRAM;
|
||||
delete[] _SRAM;
|
||||
}
|
||||
|
||||
void MemoryManager::RegisterIODevice(IMemoryHandler *handler)
|
||||
{
|
||||
std::array<int, 2> addresses = handler->GetIOAddresses();
|
||||
for(int i = addresses[0]; i < addresses[1]; i++) {
|
||||
_registerHandlers[i] = handler;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t MemoryManager::Read(uint16_t addr)
|
||||
{
|
||||
if(addr <= 0x1FFF) {
|
||||
return _internalRAM[addr & 0x07FF];
|
||||
} else if(addr <= 0x401F) {
|
||||
return ReadRegister(addr);
|
||||
} else if(addr <= 0x5FFF) {
|
||||
throw std::exception("Not implemented yet");
|
||||
//return ReadExpansionROM();
|
||||
} else if(addr <= 0x7FFF) {
|
||||
return _SRAM[addr];
|
||||
} else {
|
||||
return ReadRegister(addr);
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryManager::Write(uint16_t addr, uint8_t value)
|
||||
{
|
||||
if(addr <= 0x1FFFF) {
|
||||
_internalRAM[addr & 0x07FF] = value;
|
||||
} else if(addr <= 0x401F) {
|
||||
WriteRegister(addr, value);
|
||||
} else if(addr <= 0x5FFF) {
|
||||
throw std::exception("Not implemented yet");
|
||||
//return ReadExpansionROM();
|
||||
} else if(addr <= 0x7FFF) {
|
||||
_SRAM[addr] = value;
|
||||
} else {
|
||||
WriteRegister(addr, value);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t MemoryManager::ReadWord(uint16_t addr)
|
||||
{
|
||||
uint8_t lo = Read(addr);
|
||||
uint8_t hi = Read(addr+1);
|
||||
return lo | hi << 8;
|
||||
}
|
||||
|
30
Core/MemoryManager.h
Normal file
30
Core/MemoryManager.h
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "IMemoryHandler.h"
|
||||
|
||||
class MemoryManager
|
||||
{
|
||||
private:
|
||||
const int InternalRAMSize = 0x800;
|
||||
const int SRAMSize = 0x800;
|
||||
|
||||
uint8_t *_internalRAM;
|
||||
uint8_t *_SRAM;
|
||||
|
||||
vector<IMemoryHandler*> _registerHandlers;
|
||||
|
||||
inline uint8_t ReadRegister(uint16_t addr);
|
||||
inline void WriteRegister(uint16_t addr, uint8_t value);
|
||||
|
||||
public:
|
||||
MemoryManager();
|
||||
~MemoryManager();
|
||||
|
||||
void RegisterIODevice(IMemoryHandler *handler);
|
||||
|
||||
uint8_t Read(uint16_t addr);
|
||||
void Write(uint16_t addr, uint8_t value);
|
||||
uint16_t ReadWord(uint16_t addr);
|
||||
};
|
||||
|
31
Core/PPU.cpp
31
Core/PPU.cpp
@ -1 +1,30 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "PPU.h"
|
||||
|
||||
PPU::PPU()
|
||||
{
|
||||
_state = {};
|
||||
_state.Status |= 0xFF;
|
||||
}
|
||||
|
||||
uint8_t PPU::MemoryRead(uint16_t addr)
|
||||
{
|
||||
switch(GetRegisterID(addr)) {
|
||||
case PPURegisters::Control:
|
||||
return (uint8_t)_state.Control;
|
||||
case PPURegisters::Control2:
|
||||
return (uint8_t)(_state.Control >> 8);
|
||||
case PPURegisters::Status:
|
||||
return _state.Status;
|
||||
case PPURegisters::SpriteData:
|
||||
return _spriteRAM[_state.SpriteRamAddr];
|
||||
case PPURegisters::VideoMemoryData:
|
||||
return _videoRAM[_state.VideoRamAddr];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PPU::MemoryWrite(uint16_t addr, uint8_t value)
|
||||
{
|
||||
|
||||
}
|
48
Core/PPU.h
48
Core/PPU.h
@ -1,4 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "IMemoryHandler.h"
|
||||
|
||||
enum PPURegisters
|
||||
{
|
||||
@ -22,37 +25,24 @@ struct PPUState
|
||||
|
||||
class PPU : public IMemoryHandler
|
||||
{
|
||||
private:
|
||||
PPUState _state;
|
||||
uint8_t _spriteRAM[256];
|
||||
uint8_t _videoRAM[16*1024];
|
||||
private:
|
||||
PPUState _state;
|
||||
uint8_t _spriteRAM[256];
|
||||
uint8_t _videoRAM[16*1024];
|
||||
|
||||
PPURegisters GetRegisterID(uint16_t addr) {
|
||||
return (PPURegisters)(addr & 0x07);
|
||||
}
|
||||
|
||||
public:
|
||||
PPU() {
|
||||
_state = {};
|
||||
_state.Status |= 0xFF;
|
||||
}
|
||||
|
||||
uint8_t MemoryRead(uint16_t addr) {
|
||||
switch(GetRegisterID(addr)) {
|
||||
case PPURegisters::Control:
|
||||
return (uint8_t)_state.Control;
|
||||
case PPURegisters::Control2:
|
||||
return (uint8_t)(_state.Control >> 8);
|
||||
case PPURegisters::Status:
|
||||
return _state.Status;
|
||||
case PPURegisters::SpriteData:
|
||||
return _spriteRAM[_state.SpriteRamAddr];
|
||||
case PPURegisters::VideoMemoryData:
|
||||
return _videoRAM[_state.VideoRamAddr];
|
||||
PPURegisters GetRegisterID(uint16_t addr)
|
||||
{
|
||||
return (PPURegisters)(addr & 0x07);
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryWrite(uint16_t addr, uint8_t value) {
|
||||
public:
|
||||
PPU();
|
||||
|
||||
std::array<int, 2> GetIOAddresses()
|
||||
{
|
||||
return std::array<int, 2> {{ 0x2000, 0x3FFF }};
|
||||
}
|
||||
|
||||
}
|
||||
uint8_t MemoryRead(uint16_t addr);
|
||||
void MemoryWrite(uint16_t addr, uint8_t value);
|
||||
};
|
77
Core/ROMLoader.h
Normal file
77
Core/ROMLoader.h
Normal file
@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
struct NESHeader
|
||||
{
|
||||
char NES[4];
|
||||
uint8_t ROMCount;
|
||||
uint8_t VROMCount;
|
||||
uint8_t Flags1;
|
||||
uint8_t Flags2;
|
||||
uint8_t RAMCount;
|
||||
uint8_t CartType;
|
||||
uint8_t Reserved[6];
|
||||
|
||||
uint8_t GetMapperID()
|
||||
{
|
||||
return (Flags2 & 0xF0) | (Flags1 >> 4);
|
||||
}
|
||||
};
|
||||
|
||||
typedef vector<uint8_t> MemoryBank;
|
||||
class ROMLoader
|
||||
{
|
||||
private:
|
||||
const int ROMBankSize = 0x4000;
|
||||
const int VROMBankSize = 0x2000;
|
||||
NESHeader _header;
|
||||
vector<MemoryBank> _romBanks;
|
||||
vector<MemoryBank> _vromBanks;
|
||||
|
||||
public:
|
||||
ROMLoader(const char* filename)
|
||||
{
|
||||
_romBanks.clear();
|
||||
_vromBanks.clear();
|
||||
|
||||
ifstream romFile(filename, ios::in | ios::binary);
|
||||
|
||||
if(!romFile) {
|
||||
return;
|
||||
}
|
||||
|
||||
romFile.read((char*)&_header, sizeof(NESHeader));
|
||||
|
||||
uint8_t *buffer = new uint8_t[max(ROMBankSize, VROMBankSize)];
|
||||
for(int i = 0; i < _header.ROMCount; i++) {
|
||||
romFile.read((char*)buffer, ROMBankSize);
|
||||
_romBanks.push_back(MemoryBank(buffer, buffer + ROMBankSize));
|
||||
}
|
||||
|
||||
for(int i = 0; i < _header.VROMCount; i++) {
|
||||
romFile.read((char*)buffer, VROMBankSize);
|
||||
_vromBanks.push_back(MemoryBank(buffer, buffer + VROMBankSize));
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
|
||||
romFile.close();
|
||||
}
|
||||
|
||||
vector<MemoryBank> GetROMBanks()
|
||||
{
|
||||
return _romBanks;
|
||||
}
|
||||
|
||||
vector<MemoryBank> GetVROMBanks()
|
||||
{
|
||||
return _vromBanks;
|
||||
}
|
||||
|
||||
NESHeader GetHeader()
|
||||
{
|
||||
return _header;
|
||||
}
|
||||
};
|
||||
|
121
Core/main.cpp
121
Core/main.cpp
@ -1,121 +0,0 @@
|
||||
#include "stdafx.h"
|
||||
#include "CPU.h"
|
||||
|
||||
/*
|
||||
template<typename T>
|
||||
class TemplatedClass
|
||||
{
|
||||
public:
|
||||
T Sum(T a, T b);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
T TemplatedClass<T>::Sum(T a, T b)
|
||||
{
|
||||
return a + b;
|
||||
}
|
||||
|
||||
template<typename T> using ptr = std::unique_ptr<T>;
|
||||
|
||||
class Test
|
||||
{
|
||||
private:
|
||||
int counter = 0;
|
||||
Test();
|
||||
|
||||
public:
|
||||
int Sum(int, int);
|
||||
void NewThread();
|
||||
static std::unique_ptr<Test> NewInstance();
|
||||
};
|
||||
|
||||
Test::Test()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int Test::Sum(int x, int y)
|
||||
{
|
||||
return x + y;
|
||||
}
|
||||
|
||||
void Test::NewThread()
|
||||
{
|
||||
for (int i = 0; i < 100; i++) {
|
||||
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(1000));
|
||||
printf("test %i", this->counter);
|
||||
this->counter++;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Test> Test::NewInstance()
|
||||
{
|
||||
return std::unique_ptr<Test>(new Test());
|
||||
}
|
||||
|
||||
void somefunction(void)
|
||||
{
|
||||
printf("test11111");
|
||||
}
|
||||
|
||||
void func2(int a)
|
||||
{
|
||||
//printf("%i", a);
|
||||
}*/
|
||||
|
||||
int _tmain(int argc, _TCHAR* argv[])
|
||||
{
|
||||
/* BaseMemoryHandler a;
|
||||
Test b;
|
||||
EventHandler<BaseMemoryHandler, uint16_t> eventHandler;
|
||||
eventHandler.RegisterHandler(&a, &BaseMemoryHandler::CallbackTest);
|
||||
eventHandler.RegisterHandler(&b, &BaseMemoryHandler::CallbackTest);
|
||||
eventHandler(eMemoryOperation::Read, 0);
|
||||
*/
|
||||
CPU::RunBenchmark();
|
||||
|
||||
/*Event<> eventHandler;
|
||||
eventHandler += somefunction;
|
||||
|
||||
Event<int> intHandler;
|
||||
intHandler += func2;
|
||||
intHandler += func2;
|
||||
intHandler += func2;
|
||||
|
||||
for (int i = 0; i < 1000000; i++) {
|
||||
intHandler(i);
|
||||
}
|
||||
eventHandler();
|
||||
|
||||
TemplatedClass<double> DoubleSum;
|
||||
printf("%d", DoubleSum.Sum(10.0, 20.0));
|
||||
|
||||
TemplatedClass<std::string> StringSum;
|
||||
std::cout << StringSum.Sum("asdas", "dsadasdsa");
|
||||
|
||||
auto str1 = std::string("aaaa");
|
||||
auto str2 = std::string("bbbb");
|
||||
auto str3 = str1 + str2;
|
||||
std::cout << str3;
|
||||
|
||||
std::unique_ptr<Test> test;
|
||||
|
||||
if (!test) {
|
||||
test = Test::NewInstance();
|
||||
}
|
||||
|
||||
std::thread t1(&Test::NewThread, test.get());
|
||||
|
||||
std::thread t2([]() {
|
||||
printf("test2");
|
||||
});
|
||||
|
||||
if (test) {
|
||||
printf("%i", test->Sum(1000, 10));
|
||||
}
|
||||
|
||||
t1.join();
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
@ -18,18 +18,15 @@
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
class IMemoryHandler
|
||||
{
|
||||
public:
|
||||
virtual uint8_t MemoryRead(uint16_t addr) = 0;
|
||||
virtual void MemoryWrite(uint16_t addr, uint8_t value) = 0;
|
||||
};
|
||||
|
||||
using std::vector;
|
||||
using std::shared_ptr;
|
||||
using std::unique_ptr;
|
||||
using std::ios;
|
||||
using std::ifstream;
|
||||
|
||||
// TODO: reference additional headers your program requires here
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "resource.h"
|
||||
#include "MainWindow.h"
|
||||
#include "..\Core\CPU.h"
|
||||
#include "..\Core\Console.h"
|
||||
#include "..\Core\Timer.h"
|
||||
using namespace DirectX;
|
||||
|
||||
@ -106,7 +106,7 @@ namespace NES
|
||||
|
||||
void MainWindow::RunBenchmark()
|
||||
{
|
||||
std::thread bmThread(&CPU::RunBenchmark);
|
||||
std::thread bmThread(&Console::RunBenchmark);
|
||||
bmThread.detach();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user