2014-06-14 11:27:55 -04:00
|
|
|
#include "stdafx.h"
|
|
|
|
#include "Console.h"
|
2014-06-23 19:02:09 -04:00
|
|
|
#include "../Utilities/Timer.h"
|
2014-06-14 11:27:55 -04:00
|
|
|
|
2014-06-21 19:03:13 -04:00
|
|
|
uint32_t Console::Flags = 0;
|
2014-06-23 16:38:01 -04:00
|
|
|
uint32_t Console::CurrentFPS = 0;
|
2014-06-21 19:03:13 -04:00
|
|
|
|
2014-06-20 21:48:55 -04:00
|
|
|
Console::Console(wstring filename)
|
2014-06-14 11:27:55 -04:00
|
|
|
{
|
2014-06-22 08:38:42 -04:00
|
|
|
_romFilename = filename;
|
|
|
|
|
2014-06-14 11:27:55 -04:00
|
|
|
_mapper = MapperFactory::InitializeFromFile(filename);
|
2014-06-19 19:58:15 -04:00
|
|
|
_memoryManager.reset(new MemoryManager(_mapper->GetHeader()));
|
|
|
|
_cpu.reset(new CPU(_memoryManager.get()));
|
|
|
|
_ppu.reset(new PPU(_memoryManager.get()));
|
2014-06-22 22:15:35 -04:00
|
|
|
_apu.reset(new APU());
|
|
|
|
|
2014-06-21 15:43:41 -04:00
|
|
|
_controlManager.reset(new ControlManager());
|
|
|
|
|
2014-06-19 19:58:15 -04:00
|
|
|
_memoryManager->RegisterIODevice(_mapper.get());
|
|
|
|
_memoryManager->RegisterIODevice(_ppu.get());
|
2014-06-22 22:15:35 -04:00
|
|
|
_memoryManager->RegisterIODevice(_apu.get());
|
2014-06-21 15:43:41 -04:00
|
|
|
_memoryManager->RegisterIODevice(_controlManager.get());
|
2014-06-19 19:58:15 -04:00
|
|
|
|
|
|
|
Reset();
|
2014-06-14 11:27:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
Console::~Console()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void Console::Reset()
|
|
|
|
{
|
2014-06-23 13:52:53 -04:00
|
|
|
_reset = true;
|
2014-06-14 11:27:55 -04:00
|
|
|
}
|
|
|
|
|
2014-06-20 21:48:55 -04:00
|
|
|
void Console::Stop()
|
|
|
|
{
|
|
|
|
_stop = true;
|
2014-06-21 19:03:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void Console::SetFlags(int flags)
|
|
|
|
{
|
|
|
|
Console::Flags |= flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Console::ClearFlags(int flags)
|
|
|
|
{
|
2014-06-23 20:00:51 -04:00
|
|
|
Console::Flags &= ~flags;
|
2014-06-21 19:03:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Console::CheckFlag(int flag)
|
|
|
|
{
|
|
|
|
return (Console::Flags & flag) == flag;
|
2014-06-20 21:48:55 -04:00
|
|
|
}
|
|
|
|
|
2014-06-23 16:38:01 -04:00
|
|
|
uint32_t Console::GetFPS()
|
|
|
|
{
|
|
|
|
return Console::CurrentFPS;
|
|
|
|
}
|
|
|
|
|
2014-06-14 11:27:55 -04:00
|
|
|
void Console::Run()
|
|
|
|
{
|
2014-06-21 15:43:41 -04:00
|
|
|
Timer clockTimer;
|
|
|
|
Timer fpsTimer;
|
2014-06-21 00:37:44 -04:00
|
|
|
uint32_t lastFrameCount = 0;
|
2014-06-22 10:07:40 -04:00
|
|
|
double elapsedTime = 0;
|
2014-06-23 13:52:53 -04:00
|
|
|
double targetTime = 16.6666666666666666;
|
2014-06-21 15:43:41 -04:00
|
|
|
while(true) {
|
2014-06-22 22:15:35 -04:00
|
|
|
uint32_t executedCycles = _cpu->Exec();
|
2014-06-15 21:45:36 -04:00
|
|
|
_ppu->Exec();
|
2014-06-23 13:52:53 -04:00
|
|
|
bool frameDone = _apu->Exec(executedCycles);
|
2014-06-22 22:15:35 -04:00
|
|
|
|
2014-06-23 13:52:53 -04:00
|
|
|
if(CheckFlag(EmulationFlags::LimitFPS) && frameDone) {
|
2014-06-21 15:43:41 -04:00
|
|
|
elapsedTime = clockTimer.GetElapsedMS();
|
|
|
|
while(targetTime > elapsedTime) {
|
|
|
|
if(targetTime - elapsedTime > 2) {
|
2014-06-22 10:07:40 -04:00
|
|
|
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>((int)(targetTime - elapsedTime - 1)));
|
2014-06-21 15:43:41 -04:00
|
|
|
}
|
|
|
|
elapsedTime = clockTimer.GetElapsedMS();
|
|
|
|
}
|
|
|
|
clockTimer.Reset();
|
2014-06-20 21:48:55 -04:00
|
|
|
}
|
2014-06-21 15:43:41 -04:00
|
|
|
|
2014-06-22 10:07:40 -04:00
|
|
|
if(fpsTimer.GetElapsedMS() > 1000) {
|
2014-06-21 00:37:44 -04:00
|
|
|
uint32_t frameCount = _ppu->GetFrameCount();
|
2014-06-23 16:38:01 -04:00
|
|
|
Console::CurrentFPS = (int)((frameCount - lastFrameCount) / (fpsTimer.GetElapsedMS() / 1000));
|
2014-06-21 00:37:44 -04:00
|
|
|
lastFrameCount = frameCount;
|
2014-06-23 16:38:01 -04:00
|
|
|
//std::cout << Console::CurrentFPS << std::endl;
|
2014-06-21 15:43:41 -04:00
|
|
|
fpsTimer.Reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(_stop) {
|
2014-06-23 13:52:53 -04:00
|
|
|
_stop = false;
|
2014-06-21 15:43:41 -04:00
|
|
|
break;
|
2014-06-21 00:37:44 -04:00
|
|
|
}
|
2014-06-23 13:52:53 -04:00
|
|
|
|
|
|
|
if(_reset) {
|
|
|
|
clockTimer.Reset();
|
|
|
|
fpsTimer.Reset();
|
|
|
|
lastFrameCount = 0;
|
|
|
|
elapsedTime = 0;
|
|
|
|
_cpu->Reset();
|
|
|
|
_ppu->Reset();
|
|
|
|
_apu->Reset();
|
|
|
|
_reset = false;
|
|
|
|
}
|
2014-06-14 18:20:56 -04:00
|
|
|
}
|
2014-06-14 11:27:55 -04:00
|
|
|
}
|
|
|
|
|
2014-06-22 08:38:42 -04:00
|
|
|
bool Console::RunTest(uint8_t *expectedResult)
|
2014-06-14 11:27:55 -04:00
|
|
|
{
|
2014-06-18 22:54:23 -04:00
|
|
|
Timer timer;
|
2014-06-22 08:38:42 -04:00
|
|
|
uint8_t maxWait = 30;
|
2014-06-14 18:20:56 -04:00
|
|
|
while(true) {
|
2014-06-22 22:35:44 -04:00
|
|
|
_apu->Exec(_cpu->Exec());
|
2014-06-15 21:45:36 -04:00
|
|
|
_ppu->Exec();
|
2014-06-18 22:54:23 -04:00
|
|
|
|
2014-06-22 08:38:42 -04:00
|
|
|
if(timer.GetElapsedMS() > 100) {
|
|
|
|
if(memcmp(_ppu->GetFrameBuffer(), expectedResult, 256 * 240 * 4)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-06-18 22:54:23 -04:00
|
|
|
timer.Reset();
|
2014-06-22 08:38:42 -04:00
|
|
|
maxWait--;
|
|
|
|
|
|
|
|
if(maxWait == 0) {
|
|
|
|
return false;
|
|
|
|
}
|
2014-06-18 22:54:23 -04:00
|
|
|
}
|
2014-06-14 18:20:56 -04:00
|
|
|
}
|
|
|
|
|
2014-06-22 08:38:42 -04:00
|
|
|
return false;
|
2014-06-20 21:48:55 -04:00
|
|
|
}
|
|
|
|
|
2014-06-22 08:38:42 -04:00
|
|
|
void Console::SaveTestResult()
|
2014-06-14 18:20:56 -04:00
|
|
|
{
|
2014-06-22 08:38:42 -04: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 11:27:55 -04:00
|
|
|
}
|