Mesen/Core/Console.cpp

233 lines
4.5 KiB
C++
Raw Normal View History

2014-06-14 15:27:55 +00:00
#include "stdafx.h"
#include "Console.h"
#include "MapperFactory.h"
2014-06-23 23:02:09 +00:00
#include "../Utilities/Timer.h"
2014-06-14 15:27:55 +00:00
2014-06-21 23:03:13 +00:00
uint32_t Console::Flags = 0;
2014-06-23 20:38:01 +00:00
uint32_t Console::CurrentFPS = 0;
2014-06-21 23:03:13 +00:00
Console::Console(wstring filename)
2014-06-14 15:27:55 +00:00
{
2014-06-22 12:38:42 +00:00
_romFilename = filename;
2014-06-14 15:27:55 +00:00
_mapper = MapperFactory::InitializeFromFile(filename);
_memoryManager.reset(new MemoryManager(_mapper));
_cpu.reset(new CPU(_memoryManager.get()));
_ppu.reset(new PPU(_memoryManager.get()));
_apu.reset(new APU(_memoryManager.get()));
2014-06-21 19:43:41 +00:00
_controlManager.reset(new ControlManager());
_memoryManager->RegisterIODevice(_mapper.get());
_memoryManager->RegisterIODevice(_ppu.get());
_memoryManager->RegisterIODevice(_apu.get());
2014-06-21 19:43:41 +00:00
_memoryManager->RegisterIODevice(_controlManager.get());
ResetComponents(false);
2014-06-14 15:27:55 +00:00
}
Console::~Console()
{
}
void Console::Reset()
{
_reset = true;
2014-06-14 15:27:55 +00:00
}
void Console::ResetComponents(bool softReset)
{
_cpu->Reset(softReset);
_ppu->Reset();
_apu->Reset();
}
void Console::Stop()
{
_stop = true;
2014-06-21 23:03:13 +00:00
}
void Console::SetFlags(int flags)
{
Console::Flags |= flags;
}
void Console::ClearFlags(int flags)
{
Console::Flags &= ~flags;
2014-06-21 23:03:13 +00:00
}
bool Console::CheckFlag(int flag)
{
return (Console::Flags & flag) == flag;
}
2014-06-23 20:38:01 +00:00
uint32_t Console::GetFPS()
{
return Console::CurrentFPS;
}
2014-06-14 15:27:55 +00:00
void Console::Run()
{
2014-06-21 19:43:41 +00:00
Timer clockTimer;
Timer fpsTimer;
2014-06-21 04:37:44 +00:00
uint32_t lastFrameCount = 0;
2014-06-22 14:07:40 +00:00
double elapsedTime = 0;
double targetTime = 16.6666666666666666;
2014-06-21 19:43:41 +00:00
while(true) {
uint32_t executedCycles = _cpu->Exec();
2014-06-16 01:45:36 +00:00
_ppu->Exec();
bool frameDone = _apu->Exec(executedCycles);
if(frameDone) {
_cpu->EndFrame();
_ppu->EndFrame();
}
if(CheckFlag(EmulationFlags::LimitFPS) && frameDone) {
2014-06-21 19:43:41 +00:00
elapsedTime = clockTimer.GetElapsedMS();
while(targetTime > elapsedTime) {
if(targetTime - elapsedTime > 2) {
2014-06-22 14:07:40 +00:00
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>((int)(targetTime - elapsedTime - 1)));
2014-06-21 19:43:41 +00:00
}
elapsedTime = clockTimer.GetElapsedMS();
}
clockTimer.Reset();
}
2014-06-21 19:43:41 +00:00
2014-06-22 14:07:40 +00:00
if(fpsTimer.GetElapsedMS() > 1000) {
2014-06-21 04:37:44 +00:00
uint32_t frameCount = _ppu->GetFrameCount();
Console::CurrentFPS = (int)(std::round((double)(frameCount - lastFrameCount) / (fpsTimer.GetElapsedMS() / 1000)));
2014-06-21 04:37:44 +00:00
lastFrameCount = frameCount;
2014-06-21 19:43:41 +00:00
fpsTimer.Reset();
}
2014-06-26 01:52:37 +00:00
if(!_saveStateFilename.empty()) {
SaveState();
} else if(!_loadStateFilename.empty()) {
LoadState();
}
2014-06-21 19:43:41 +00:00
if(_stop) {
_stop = false;
2014-06-21 19:43:41 +00:00
break;
2014-06-21 04:37:44 +00:00
}
if(_reset) {
clockTimer.Reset();
fpsTimer.Reset();
lastFrameCount = 0;
elapsedTime = 0;
ResetComponents(true);
_reset = false;
}
2014-06-14 22:20:56 +00:00
}
2014-06-14 15:27:55 +00:00
}
2014-06-26 01:52:37 +00:00
void Console::SaveState(wstring filename)
{
_saveStateFilename = filename;
}
void Console::SaveState()
{
ofstream file(_saveStateFilename, ios::out | ios::binary);
if(file) {
_cpu->SaveSnapshot(&file);
_ppu->SaveSnapshot(&file);
_memoryManager->SaveSnapshot(&file);
_mapper->SaveSnapshot(&file);
_apu->SaveSnapshot(&file);
file.close();
}
_saveStateFilename.clear();
}
bool Console::LoadState(wstring filename)
2014-06-26 01:52:37 +00:00
{
ifstream file(filename, ios::out | ios::binary);
if(file) {
file.close();
_loadStateFilename = filename;
return true;
}
return false;
2014-06-26 01:52:37 +00:00
}
void Console::LoadState()
{
ifstream file(_loadStateFilename, ios::out | ios::binary);
if(file) {
_cpu->LoadSnapshot(&file);
_ppu->LoadSnapshot(&file);
_memoryManager->LoadSnapshot(&file);
_mapper->LoadSnapshot(&file);
_apu->LoadSnapshot(&file);
file.close();
}
_loadStateFilename.clear();
}
2014-06-22 12:38:42 +00:00
bool Console::RunTest(uint8_t *expectedResult)
2014-06-14 15:27:55 +00:00
{
Timer timer;
2014-06-27 00:55:22 +00:00
uint8_t maxWait = 60;
uint8_t* lastFrameBuffer = new uint8_t[256 * 240 * 4];
2014-06-14 22:20:56 +00:00
while(true) {
uint32_t executedCycles = _cpu->Exec();
2014-06-16 01:45:36 +00:00
_ppu->Exec();
if(_apu->Exec(executedCycles)) {
_cpu->EndFrame();
_ppu->EndFrame();
}
2014-06-22 12:38:42 +00:00
if(timer.GetElapsedMS() > 100) {
2014-06-25 16:47:15 +00:00
if(memcmp(_ppu->GetFrameBuffer(), expectedResult, 256 * 240 * 4) == 0) {
2014-06-22 12:38:42 +00:00
return true;
}
2014-06-27 00:55:22 +00:00
timer.Reset();
2014-06-22 12:38:42 +00:00
2014-06-27 00:55:22 +00:00
if(memcmp(lastFrameBuffer, _ppu->GetFrameBuffer(), 256 * 240 * 4) != 0) {
memcpy(lastFrameBuffer, _ppu->GetFrameBuffer(), 256 * 240 * 4);
maxWait = 60;
}
maxWait--;
2014-06-22 12:38:42 +00:00
if(maxWait == 0) {
return false;
}
}
2014-06-14 22:20:56 +00:00
}
2014-06-27 00:55:22 +00:00
delete[] lastFrameBuffer;
2014-06-14 22:20:56 +00:00
2014-06-22 12:38:42 +00:00
return false;
}
2014-06-22 12:38:42 +00:00
void Console::SaveTestResult()
2014-06-14 22:20:56 +00:00
{
2014-06-22 12:38:42 +00:00
wstring filename = _romFilename + L".trt";
ofstream testResultFile(filename, ios::out | ios::binary);
if(!testResultFile) {
throw std::exception("File could not be opened");
}
uint8_t* buffer = new uint8_t[256 * 240 * 4];
memcpy(buffer, _ppu->GetFrameBuffer(), 256 * 240 * 4);
testResultFile.write((char *)buffer, 256 * 240 * 4);
testResultFile.close();
delete[] buffer;
2014-06-14 15:27:55 +00:00
}