Added support for automated testing
This commit is contained in:
parent
accac0f21e
commit
207282ed1e
26 changed files with 642 additions and 56 deletions
|
@ -30,6 +30,7 @@
|
|||
#include "MovieManager.h"
|
||||
#include "BatteryManager.h"
|
||||
#include "CheatManager.h"
|
||||
#include "MovieManager.h"
|
||||
#include "../Utilities/Serializer.h"
|
||||
#include "../Utilities/Timer.h"
|
||||
#include "../Utilities/VirtualFile.h"
|
||||
|
@ -39,7 +40,6 @@
|
|||
Console::Console()
|
||||
{
|
||||
_settings.reset(new EmuSettings());
|
||||
KeyManager::SetSettings(_settings.get());
|
||||
|
||||
_paused = false;
|
||||
_pauseOnNextFrame = false;
|
||||
|
@ -63,6 +63,7 @@ void Console::Initialize()
|
|||
_soundMixer.reset(new SoundMixer(this));
|
||||
_debugHud.reset(new DebugHud());
|
||||
_cheatManager.reset(new CheatManager(this));
|
||||
_movieManager.reset(new MovieManager(shared_from_this()));
|
||||
|
||||
_videoDecoder->StartThread();
|
||||
_videoRenderer->StartThread();
|
||||
|
@ -82,6 +83,8 @@ void Console::Release()
|
|||
_saveStateManager.reset();
|
||||
_soundMixer.reset();
|
||||
_settings.reset();
|
||||
_cheatManager.reset();
|
||||
_movieManager.reset();
|
||||
}
|
||||
|
||||
void Console::Run()
|
||||
|
@ -106,6 +109,7 @@ void Console::Run()
|
|||
_emulationThreadId = std::this_thread::get_id();
|
||||
|
||||
_memoryManager->IncMasterClockStartup();
|
||||
_controlManager->UpdateInputState();
|
||||
|
||||
auto lock = _runLock.AcquireSafe();
|
||||
while(!_stopFlag) {
|
||||
|
@ -136,8 +140,6 @@ void Console::Run()
|
|||
frameLimiter.ProcessFrame();
|
||||
frameLimiter.WaitForNextFrame();
|
||||
|
||||
_controlManager->UpdateControlDevices();
|
||||
|
||||
double newFrameDelay = GetFrameDelay();
|
||||
if(newFrameDelay != frameDelay) {
|
||||
frameDelay = newFrameDelay;
|
||||
|
@ -152,13 +154,14 @@ void Console::Run()
|
|||
}
|
||||
|
||||
_controlManager->UpdateInputState();
|
||||
_controlManager->UpdateControlDevices();
|
||||
_internalRegisters->ProcessAutoJoypadRead();
|
||||
|
||||
previousFrameCount = _ppu->GetFrameCount();
|
||||
}
|
||||
}
|
||||
|
||||
MovieManager::Stop();
|
||||
_movieManager->Stop();
|
||||
|
||||
_emulationThreadId = thread::id();
|
||||
|
||||
|
@ -254,7 +257,7 @@ void Console::Reset()
|
|||
ProcessEvent(EventType::Reset);
|
||||
|
||||
_memoryManager->IncMasterClockStartup();
|
||||
|
||||
|
||||
Unlock();
|
||||
|
||||
if(debugger) {
|
||||
|
@ -584,6 +587,11 @@ shared_ptr<CheatManager> Console::GetCheatManager()
|
|||
return _cheatManager;
|
||||
}
|
||||
|
||||
shared_ptr<MovieManager> Console::GetMovieManager()
|
||||
{
|
||||
return _movieManager;
|
||||
}
|
||||
|
||||
shared_ptr<Cpu> Console::GetCpu()
|
||||
{
|
||||
return _cpu;
|
||||
|
|
|
@ -25,6 +25,7 @@ class SaveStateManager;
|
|||
class RewindManager;
|
||||
class BatteryManager;
|
||||
class CheatManager;
|
||||
class MovieManager;
|
||||
enum class MemoryOperationType;
|
||||
enum class SnesMemoryType;
|
||||
enum class EventType;
|
||||
|
@ -54,7 +55,8 @@ private:
|
|||
shared_ptr<SaveStateManager> _saveStateManager;
|
||||
shared_ptr<RewindManager> _rewindManager;
|
||||
shared_ptr<CheatManager> _cheatManager;
|
||||
|
||||
shared_ptr<MovieManager> _movieManager;
|
||||
|
||||
thread::id _emulationThreadId;
|
||||
|
||||
atomic<uint32_t> _lockCounter;
|
||||
|
@ -116,6 +118,7 @@ public:
|
|||
shared_ptr<DebugHud> GetDebugHud();
|
||||
shared_ptr<BatteryManager> GetBatteryManager();
|
||||
shared_ptr<CheatManager> GetCheatManager();
|
||||
shared_ptr<MovieManager> GetMovieManager();
|
||||
|
||||
shared_ptr<Cpu> GetCpu();
|
||||
shared_ptr<Ppu> GetPpu();
|
||||
|
|
|
@ -143,7 +143,7 @@ void ControlManager::UpdateInputState()
|
|||
|
||||
auto lock = _deviceLock.AcquireSafe();
|
||||
|
||||
string log = "";
|
||||
//string log = "F: " + std::to_string(_console->GetPpu()->GetFrameCount()) + " C:" + std::to_string(_pollCounter) + " ";
|
||||
for(shared_ptr<BaseControlDevice> &device : _controlDevices) {
|
||||
device->ClearState();
|
||||
|
||||
|
|
|
@ -110,6 +110,7 @@
|
|||
<ClInclude Include="NtscFilter.h" />
|
||||
<ClInclude Include="Obc1.h" />
|
||||
<ClInclude Include="PpuTools.h" />
|
||||
<ClInclude Include="RecordedRomTest.h" />
|
||||
<ClInclude Include="RegisterHandlerB.h" />
|
||||
<ClInclude Include="CpuTypes.h" />
|
||||
<ClInclude Include="Debugger.h" />
|
||||
|
@ -239,6 +240,7 @@
|
|||
<ClCompile Include="Obc1.cpp" />
|
||||
<ClCompile Include="Ppu.cpp" />
|
||||
<ClCompile Include="PpuTools.cpp" />
|
||||
<ClCompile Include="RecordedRomTest.cpp" />
|
||||
<ClCompile Include="RegisterHandlerB.cpp" />
|
||||
<ClCompile Include="RewindData.cpp" />
|
||||
<ClCompile Include="RewindManager.cpp" />
|
||||
|
|
|
@ -410,6 +410,9 @@
|
|||
<ClInclude Include="CheatManager.h">
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="RecordedRomTest.h">
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp" />
|
||||
|
@ -665,6 +668,9 @@
|
|||
<ClCompile Include="SnesController.cpp">
|
||||
<Filter>SNES\Input</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="RecordedRomTest.cpp">
|
||||
<Filter>Misc</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="SNES">
|
||||
|
|
|
@ -16,9 +16,10 @@
|
|||
#include "BatteryManager.h"
|
||||
#include "CheatManager.h"
|
||||
|
||||
MesenMovie::MesenMovie(shared_ptr<Console> console)
|
||||
MesenMovie::MesenMovie(shared_ptr<Console> console, bool forTest)
|
||||
{
|
||||
_console = console;
|
||||
_forTest = forTest;
|
||||
}
|
||||
|
||||
MesenMovie::~MesenMovie()
|
||||
|
@ -29,7 +30,9 @@ MesenMovie::~MesenMovie()
|
|||
void MesenMovie::Stop()
|
||||
{
|
||||
if(_playing) {
|
||||
MessageManager::DisplayMessage("Movies", "MovieEnded");
|
||||
if(!_forTest) {
|
||||
MessageManager::DisplayMessage("Movies", "MovieEnded");
|
||||
}
|
||||
|
||||
if(_console->GetSettings()->GetPreferences().PauseOnMovieEnd) {
|
||||
_console->Pause();
|
||||
|
@ -56,7 +59,7 @@ bool MesenMovie::SetInput(BaseControlDevice *device)
|
|||
_deviceIndex = 0;
|
||||
}
|
||||
} else {
|
||||
MovieManager::Stop();
|
||||
_console->GetMovieManager()->Stop();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -73,11 +76,11 @@ vector<uint8_t> MesenMovie::LoadBattery(string extension)
|
|||
return batteryData;
|
||||
}
|
||||
|
||||
void MesenMovie::ProcessNotification(ConsoleNotificationType type, void * parameter)
|
||||
void MesenMovie::ProcessNotification(ConsoleNotificationType type, void* parameter)
|
||||
{
|
||||
if(type == ConsoleNotificationType::GameLoaded) {
|
||||
_console->GetControlManager()->RegisterInputProvider(this);
|
||||
_console->GetControlManager()->SetPollCounter(_lastPollCounter + 1);
|
||||
_console->GetControlManager()->SetPollCounter(_lastPollCounter);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,7 +143,14 @@ bool MesenMovie::Play(VirtualFile &file)
|
|||
}*/
|
||||
|
||||
_originalCheats = _console->GetCheatManager()->GetCheats();
|
||||
_console->PowerCycle();
|
||||
|
||||
controlManager->UpdateControlDevices();
|
||||
if(!_forTest) {
|
||||
_console->PowerCycle();
|
||||
} else {
|
||||
controlManager->RegisterInputProvider(this);
|
||||
}
|
||||
|
||||
LoadCheats();
|
||||
|
||||
stringstream saveStateData;
|
||||
|
@ -239,7 +249,9 @@ void MesenMovie::ApplySettings()
|
|||
inputConfig.Controllers[4].Type = FromString(LoadString(_settings, MovieKeys::Controller5), ControllerTypeNames, ControllerType::None);
|
||||
|
||||
emuConfig.Region = FromString(LoadString(_settings, MovieKeys::Region), ConsoleRegionNames, ConsoleRegion::Ntsc);
|
||||
emuConfig.RamPowerOnState = FromString(LoadString(_settings, MovieKeys::RamPowerOnState), RamStateNames, RamState::AllOnes);
|
||||
if(!_forTest) {
|
||||
emuConfig.RamPowerOnState = FromString(LoadString(_settings, MovieKeys::RamPowerOnState), RamStateNames, RamState::AllOnes);
|
||||
}
|
||||
emuConfig.PpuExtraScanlinesAfterNmi = LoadInt(_settings, MovieKeys::ExtraScanlinesAfterNmi);
|
||||
emuConfig.PpuExtraScanlinesBeforeNmi = LoadInt(_settings, MovieKeys::ExtraScanlinesBeforeNmi);
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ private:
|
|||
vector<CheatCode> _originalCheats;
|
||||
std::unordered_map<string, string> _settings;
|
||||
string _filename;
|
||||
bool _forTest;
|
||||
|
||||
private:
|
||||
void ParseSettings(stringstream &data);
|
||||
|
@ -40,7 +41,7 @@ private:
|
|||
bool LoadCheat(string cheatData, CheatCode &code);
|
||||
|
||||
public:
|
||||
MesenMovie(shared_ptr<Console> console);
|
||||
MesenMovie(shared_ptr<Console> console, bool silent);
|
||||
virtual ~MesenMovie();
|
||||
|
||||
bool Play(VirtualFile &file) override;
|
||||
|
|
|
@ -7,18 +7,20 @@
|
|||
#include "MesenMovie.h"
|
||||
#include "MovieRecorder.h"
|
||||
|
||||
shared_ptr<IMovie> MovieManager::_player;
|
||||
shared_ptr<MovieRecorder> MovieManager::_recorder;
|
||||
|
||||
void MovieManager::Record(RecordMovieOptions options, shared_ptr<Console> console)
|
||||
MovieManager::MovieManager(shared_ptr<Console> console)
|
||||
{
|
||||
shared_ptr<MovieRecorder> recorder(new MovieRecorder(console));
|
||||
_console = console;
|
||||
}
|
||||
|
||||
void MovieManager::Record(RecordMovieOptions options)
|
||||
{
|
||||
shared_ptr<MovieRecorder> recorder(new MovieRecorder(_console));
|
||||
if(recorder->Record(options)) {
|
||||
_recorder = recorder;
|
||||
}
|
||||
}
|
||||
|
||||
void MovieManager::Play(VirtualFile file, shared_ptr<Console> console)
|
||||
void MovieManager::Play(VirtualFile file, bool forTest)
|
||||
{
|
||||
vector<uint8_t> fileData;
|
||||
if(file.IsValid() && file.ReadFile(fileData)) {
|
||||
|
@ -30,13 +32,15 @@ void MovieManager::Play(VirtualFile file, shared_ptr<Console> console)
|
|||
|
||||
vector<string> files = reader.GetFileList();
|
||||
if(std::find(files.begin(), files.end(), "GameSettings.txt") != files.end()) {
|
||||
player.reset(new MesenMovie(console));
|
||||
player.reset(new MesenMovie(_console, forTest));
|
||||
}
|
||||
}
|
||||
|
||||
if(player && player->Play(file)) {
|
||||
_player = player;
|
||||
MessageManager::DisplayMessage("Movies", "MoviePlaying", file.GetFileName());
|
||||
if(!forTest) {
|
||||
MessageManager::DisplayMessage("Movies", "MoviePlaying", file.GetFileName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,13 +18,16 @@ public:
|
|||
class MovieManager
|
||||
{
|
||||
private:
|
||||
static shared_ptr<IMovie> _player;
|
||||
static shared_ptr<MovieRecorder> _recorder;
|
||||
shared_ptr<Console> _console;
|
||||
shared_ptr<IMovie> _player;
|
||||
shared_ptr<MovieRecorder> _recorder;
|
||||
|
||||
public:
|
||||
static void Record(RecordMovieOptions options, shared_ptr<Console> console);
|
||||
static void Play(VirtualFile file, shared_ptr<Console> console);
|
||||
static void Stop();
|
||||
static bool Playing();
|
||||
static bool Recording();
|
||||
MovieManager(shared_ptr<Console> console);
|
||||
|
||||
void Record(RecordMovieOptions options);
|
||||
void Play(VirtualFile file, bool silent = false);
|
||||
void Stop();
|
||||
bool Playing();
|
||||
bool Recording();
|
||||
};
|
12
Core/Ppu.cpp
12
Core/Ppu.cpp
|
@ -1500,12 +1500,6 @@ void Ppu::ProcessWindowMaskSettings(uint8_t value, uint8_t offset)
|
|||
|
||||
void Ppu::SendFrame()
|
||||
{
|
||||
_console->GetNotificationManager()->SendNotification(ConsoleNotificationType::PpuFrameDone);
|
||||
|
||||
if(_skipRender) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t width = _useHighResOutput ? 512 : 256;
|
||||
uint16_t height = _useHighResOutput ? 478 : 239;
|
||||
|
||||
|
@ -1517,6 +1511,12 @@ void Ppu::SendFrame()
|
|||
memset(_currentBuffer + width * (height - bottom), 0, width * bottom * sizeof(uint16_t));
|
||||
}
|
||||
|
||||
_console->GetNotificationManager()->SendNotification(ConsoleNotificationType::PpuFrameDone);
|
||||
|
||||
if(_skipRender) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool isRewinding = _console->GetRewindManager()->IsRewinding();
|
||||
#ifdef LIBRETRO
|
||||
_console->GetVideoDecoder()->UpdateFrameSync(_currentBuffer, width, height, _frameCount, isRewinding);
|
||||
|
|
284
Core/RecordedRomTest.cpp
Normal file
284
Core/RecordedRomTest.cpp
Normal file
|
@ -0,0 +1,284 @@
|
|||
#include "stdafx.h"
|
||||
|
||||
#include "RecordedRomTest.h"
|
||||
#include "Console.h"
|
||||
#include "EmuSettings.h"
|
||||
#include "MessageManager.h"
|
||||
#include "Ppu.h"
|
||||
#include "MovieManager.h"
|
||||
#include "BaseCartridge.h"
|
||||
#include "NotificationManager.h"
|
||||
#include "../Utilities/VirtualFile.h"
|
||||
#include "../Utilities/FolderUtilities.h"
|
||||
#include "../Utilities/md5.h"
|
||||
#include "../Utilities/ZipWriter.h"
|
||||
#include "../Utilities/ZipReader.h"
|
||||
#include "../Utilities/ArchiveReader.h"
|
||||
|
||||
RecordedRomTest::RecordedRomTest(shared_ptr<Console> console)
|
||||
{
|
||||
if(console) {
|
||||
_console = console;
|
||||
} else {
|
||||
_console.reset(new Console());
|
||||
_console->Initialize();
|
||||
}
|
||||
Reset();
|
||||
}
|
||||
|
||||
RecordedRomTest::~RecordedRomTest()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void RecordedRomTest::SaveFrame()
|
||||
{
|
||||
bool highRes = _ppu->IsHighResOutput();
|
||||
uint16_t width = highRes ? 512 : 256;
|
||||
uint16_t height = highRes ? 478 : 239;
|
||||
uint16_t* ppuFrameBuffer = _ppu->GetScreenBuffer();
|
||||
|
||||
uint8_t md5Hash[16];
|
||||
GetMd5Sum(md5Hash, ppuFrameBuffer, width*height*sizeof(uint16_t));
|
||||
|
||||
if(memcmp(_previousHash, md5Hash, 16) == 0 && _currentCount < 255) {
|
||||
_currentCount++;
|
||||
} else {
|
||||
uint8_t* hash = new uint8_t[16];
|
||||
memcpy(hash, md5Hash, 16);
|
||||
_screenshotHashes.push_back(hash);
|
||||
if(_currentCount > 0) {
|
||||
_repetitionCount.push_back(_currentCount);
|
||||
}
|
||||
_currentCount = 1;
|
||||
|
||||
memcpy(_previousHash, md5Hash, 16);
|
||||
|
||||
_signal.Signal();
|
||||
}
|
||||
}
|
||||
|
||||
void RecordedRomTest::ValidateFrame()
|
||||
{
|
||||
bool highRes = _ppu->IsHighResOutput();
|
||||
uint16_t width = highRes ? 512 : 256;
|
||||
uint16_t height = highRes ? 478 : 239;
|
||||
uint16_t* ppuFrameBuffer = _ppu->GetScreenBuffer();
|
||||
|
||||
uint8_t md5Hash[16];
|
||||
GetMd5Sum(md5Hash, ppuFrameBuffer, width * height * sizeof(uint16_t));
|
||||
|
||||
if(_currentCount == 0) {
|
||||
_currentCount = _repetitionCount.front();
|
||||
_repetitionCount.pop_front();
|
||||
_screenshotHashes.pop_front();
|
||||
}
|
||||
_currentCount--;
|
||||
|
||||
if(memcmp(_screenshotHashes.front(), md5Hash, 16) != 0) {
|
||||
_badFrameCount++;
|
||||
//_console->BreakIfDebugging();
|
||||
}
|
||||
|
||||
if(_currentCount == 0 && _repetitionCount.empty()) {
|
||||
//End of test
|
||||
if(memcmp(_screenshotHashes.front(), md5Hash, 16) == 0) {
|
||||
_badFrameCount = 0;
|
||||
}
|
||||
_runningTest = false;
|
||||
_signal.Signal();
|
||||
}
|
||||
}
|
||||
|
||||
void RecordedRomTest::ProcessNotification(ConsoleNotificationType type, void* parameter)
|
||||
{
|
||||
switch(type) {
|
||||
case ConsoleNotificationType::PpuFrameDone:
|
||||
if(_recording) {
|
||||
SaveFrame();
|
||||
} else if(_runningTest) {
|
||||
ValidateFrame();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RecordedRomTest::Reset()
|
||||
{
|
||||
memset(_previousHash, 0xFF, 16);
|
||||
|
||||
_currentCount = 0;
|
||||
_repetitionCount.clear();
|
||||
|
||||
for(uint8_t* hash : _screenshotHashes) {
|
||||
delete[] hash;
|
||||
}
|
||||
_screenshotHashes.clear();
|
||||
|
||||
_runningTest = false;
|
||||
_recording = false;
|
||||
_badFrameCount = 0;
|
||||
}
|
||||
|
||||
void RecordedRomTest::Record(string filename, bool reset)
|
||||
{
|
||||
_console->GetNotificationManager()->RegisterNotificationListener(shared_from_this());
|
||||
_filename = filename;
|
||||
|
||||
string mrtFilename = FolderUtilities::CombinePath(FolderUtilities::GetFolderName(filename), FolderUtilities::GetFilename(filename, false) + ".mrt");
|
||||
_file.open(mrtFilename, ios::out | ios::binary);
|
||||
|
||||
if(_file) {
|
||||
_console->Lock();
|
||||
Reset();
|
||||
|
||||
VideoConfig videoCfg = _console->GetSettings()->GetVideoConfig();
|
||||
videoCfg.DisableFrameSkipping = true;
|
||||
_console->GetSettings()->SetVideoConfig(videoCfg);
|
||||
|
||||
EmulationConfig emuCfg = _console->GetSettings()->GetEmulationConfig();
|
||||
emuCfg.RamPowerOnState = RamState::AllZeros;
|
||||
_console->GetSettings()->SetEmulationConfig(emuCfg);
|
||||
|
||||
//Start recording movie alongside with screenshots
|
||||
RecordMovieOptions options;
|
||||
string movieFilename = FolderUtilities::CombinePath(FolderUtilities::GetFolderName(filename), FolderUtilities::GetFilename(filename, false) + ".mmo");
|
||||
memcpy(options.Filename, movieFilename.c_str(), std::max(1000, (int)movieFilename.size()));
|
||||
options.RecordFrom = reset ? RecordMovieFrom::StartWithSaveData : RecordMovieFrom::CurrentState;
|
||||
_console->GetMovieManager()->Record(options);
|
||||
|
||||
_ppu = _console->GetPpu().get();
|
||||
_recording = true;
|
||||
_console->Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
int32_t RecordedRomTest::Run(string filename)
|
||||
{
|
||||
_console->GetNotificationManager()->RegisterNotificationListener(shared_from_this());
|
||||
|
||||
EmuSettings* settings = _console->GetSettings().get();
|
||||
string testName = FolderUtilities::GetFilename(filename, false);
|
||||
|
||||
VirtualFile testMovie(filename, "TestMovie.msm");
|
||||
VirtualFile testRom(filename, "TestRom.sfc");
|
||||
|
||||
ZipReader zipReader;
|
||||
zipReader.LoadArchive(filename);
|
||||
|
||||
stringstream testData;
|
||||
zipReader.GetStream("TestData.mrt", testData);
|
||||
|
||||
if(testData && testMovie.IsValid() && testRom.IsValid()) {
|
||||
char header[3];
|
||||
testData.read((char*)&header, 3);
|
||||
if(memcmp((char*)&header, "MRT", 3) != 0) {
|
||||
//Invalid test file
|
||||
return false;
|
||||
}
|
||||
|
||||
Reset();
|
||||
|
||||
uint32_t hashCount;
|
||||
testData.read((char*)&hashCount, sizeof(uint32_t));
|
||||
|
||||
for(uint32_t i = 0; i < hashCount; i++) {
|
||||
uint8_t repeatCount = 0;
|
||||
testData.read((char*)&repeatCount, sizeof(uint8_t));
|
||||
_repetitionCount.push_back(repeatCount);
|
||||
|
||||
uint8_t* screenshotHash = new uint8_t[16];
|
||||
testData.read((char*)screenshotHash, 16);
|
||||
_screenshotHashes.push_back(screenshotHash);
|
||||
}
|
||||
|
||||
_currentCount = _repetitionCount.front();
|
||||
_repetitionCount.pop_front();
|
||||
|
||||
VideoConfig cfg = settings->GetVideoConfig();
|
||||
cfg.DisableFrameSkipping = true;
|
||||
settings->SetVideoConfig(cfg);
|
||||
|
||||
EmulationConfig emuCfg = _console->GetSettings()->GetEmulationConfig();
|
||||
emuCfg.RamPowerOnState = RamState::AllZeros;
|
||||
_console->GetSettings()->SetEmulationConfig(emuCfg);
|
||||
|
||||
//Start playing movie
|
||||
if(_console->LoadRom(testRom, VirtualFile(""))) {
|
||||
settings->SetFlag(EmulationFlags::MaximumSpeed);
|
||||
_console->GetMovieManager()->Play(testMovie, true);
|
||||
|
||||
_ppu = _console->GetPpu().get();
|
||||
|
||||
_runningTest = true;
|
||||
_runThread = std::thread([=]() {
|
||||
_console->Run();
|
||||
});
|
||||
_signal.Wait();
|
||||
_console->Stop(false);
|
||||
//_console->Release();
|
||||
_runThread.join();
|
||||
_runningTest = false;
|
||||
} else {
|
||||
//Something went wrong when loading the rom
|
||||
return -2;
|
||||
}
|
||||
|
||||
settings->ClearFlag(EmulationFlags::MaximumSpeed);
|
||||
|
||||
return _badFrameCount;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void RecordedRomTest::Stop()
|
||||
{
|
||||
if(_recording) {
|
||||
Save();
|
||||
}
|
||||
Reset();
|
||||
}
|
||||
|
||||
void RecordedRomTest::Save()
|
||||
{
|
||||
//Wait until the next frame is captured to end the recording
|
||||
_signal.Wait();
|
||||
_repetitionCount.push_back(_currentCount);
|
||||
_recording = false;
|
||||
|
||||
//Stop playing/recording the movie
|
||||
_console->GetMovieManager()->Stop();
|
||||
|
||||
_file.write("MRT", 3);
|
||||
|
||||
uint32_t hashCount = (uint32_t)_screenshotHashes.size();
|
||||
_file.write((char*)&hashCount, sizeof(uint32_t));
|
||||
|
||||
for(uint32_t i = 0; i < hashCount; i++) {
|
||||
_file.write((char*)&_repetitionCount[i], sizeof(uint8_t));
|
||||
_file.write((char*)&_screenshotHashes[i][0], 16);
|
||||
}
|
||||
|
||||
_file.close();
|
||||
|
||||
ZipWriter writer;
|
||||
writer.Initialize(_filename);
|
||||
|
||||
string mrtFilename = FolderUtilities::CombinePath(FolderUtilities::GetFolderName(_filename), FolderUtilities::GetFilename(_filename, false) + ".mrt");
|
||||
writer.AddFile(mrtFilename, "TestData.mrt");
|
||||
std::remove(mrtFilename.c_str());
|
||||
|
||||
string mmoFilename = FolderUtilities::CombinePath(FolderUtilities::GetFolderName(_filename), FolderUtilities::GetFilename(_filename, false) + ".mmo");
|
||||
writer.AddFile(mmoFilename, "TestMovie.msm");
|
||||
std::remove(mmoFilename.c_str());
|
||||
|
||||
writer.AddFile(_console->GetCartridge()->GetRomInfo().RomFile.GetFilePath(), "TestRom.sfc");
|
||||
|
||||
writer.Save();
|
||||
|
||||
MessageManager::DisplayMessage("Test", "TestFileSavedTo", FolderUtilities::GetFilename(_filename, true));
|
||||
}
|
47
Core/RecordedRomTest.h
Normal file
47
Core/RecordedRomTest.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <deque>
|
||||
#include "INotificationListener.h"
|
||||
#include "../Utilities/AutoResetEvent.h"
|
||||
|
||||
class VirtualFile;
|
||||
class Console;
|
||||
class Ppu;
|
||||
|
||||
class RecordedRomTest : public INotificationListener, public std::enable_shared_from_this<RecordedRomTest>
|
||||
{
|
||||
private:
|
||||
shared_ptr<Console> _console;
|
||||
Ppu* _ppu;
|
||||
|
||||
bool _recording = false;
|
||||
bool _runningTest = false;
|
||||
int _badFrameCount = 0;
|
||||
|
||||
uint8_t _previousHash[16] = {};
|
||||
std::deque<uint8_t*> _screenshotHashes;
|
||||
std::deque<uint8_t> _repetitionCount;
|
||||
uint8_t _currentCount = 0;
|
||||
std::thread _runThread;
|
||||
|
||||
string _filename;
|
||||
ofstream _file;
|
||||
|
||||
AutoResetEvent _signal;
|
||||
|
||||
private:
|
||||
void Reset();
|
||||
__declspec(noinline) void ValidateFrame();
|
||||
void SaveFrame();
|
||||
void Save();
|
||||
|
||||
public:
|
||||
RecordedRomTest(shared_ptr<Console> console = nullptr);
|
||||
virtual ~RecordedRomTest();
|
||||
|
||||
void ProcessNotification(ConsoleNotificationType type, void* parameter) override;
|
||||
void Record(string filename, bool reset);
|
||||
int32_t Run(string filename);
|
||||
void Stop();
|
||||
};
|
|
@ -151,7 +151,7 @@ bool SaveStateManager::LoadState(istream &stream, bool hashCheckRequired)
|
|||
|
||||
//Stop any movie that might have been playing/recording if a state is loaded
|
||||
//(Note: Loading a state is disabled in the UI while a movie is playing/recording)
|
||||
MovieManager::Stop();
|
||||
_console->GetMovieManager()->Stop();
|
||||
|
||||
_console->Deserialize(stream, fileFormatVersion);
|
||||
|
||||
|
|
|
@ -266,7 +266,7 @@ struct EmulationConfig
|
|||
|
||||
uint32_t PpuExtraScanlinesBeforeNmi = 0;
|
||||
uint32_t PpuExtraScanlinesAfterNmi = 0;
|
||||
uint32_t GsuClockSpeed = 0;
|
||||
uint32_t GsuClockSpeed = 100;
|
||||
|
||||
RamState RamPowerOnState = RamState::Random;
|
||||
};
|
||||
|
|
|
@ -104,7 +104,7 @@ void ShortcutKeyHandler::CheckMappedKeys()
|
|||
shared_ptr<EmuSettings> settings = _console->GetSettings();
|
||||
bool isNetplayClient = false; //TODO GameClient::Connected();
|
||||
//bool isMovieActive = MovieManager::Playing() || MovieManager::Recording();
|
||||
bool isMovieRecording = MovieManager::Recording();
|
||||
bool isMovieRecording = _console->GetMovieManager()->Recording();
|
||||
|
||||
//Let the UI handle these shortcuts
|
||||
for(uint64_t i = (uint64_t)EmulatorShortcut::TakeScreenshot; i < (uint64_t)EmulatorShortcut::ShortcutCount; i++) {
|
||||
|
|
|
@ -79,7 +79,6 @@ public:
|
|||
if(_console) {
|
||||
if(IsPressed(SystemActionManager::Buttons::ResetButton)) {
|
||||
_console->Reset();
|
||||
_console->GetControlManager()->UpdateInputState();
|
||||
}
|
||||
if(IsPressed(SystemActionManager::Buttons::PowerButton)) {
|
||||
_console->PowerCycle();
|
||||
|
|
|
@ -60,6 +60,7 @@ extern "C" {
|
|||
DllExport void __stdcall InitDll()
|
||||
{
|
||||
_console.reset(new Console());
|
||||
KeyManager::SetSettings(_console->GetSettings().get());
|
||||
}
|
||||
|
||||
DllExport void __stdcall InitializeEmu(const char* homeFolder, void *windowHandle, void *viewerHandle, bool noAudio, bool noVideo, bool noInput)
|
||||
|
@ -240,6 +241,7 @@ extern "C" {
|
|||
std::cout << "Running: " << testRoms[i] << std::endl;
|
||||
|
||||
_console.reset(new Console());
|
||||
KeyManager::SetSettings(_console->GetSettings().get());
|
||||
_console->Initialize();
|
||||
_console->LoadRom((VirtualFile)testRoms[i], VirtualFile());
|
||||
|
||||
|
|
|
@ -470,6 +470,7 @@
|
|||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='PGO Profile|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='PGO Optimize|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TestApiWrapper.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
|
|
@ -40,5 +40,8 @@
|
|||
<ClCompile Include="RecordApiWrapper.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TestApiWrapper.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -17,13 +17,13 @@ extern "C"
|
|||
DllExport void __stdcall WaveStop() { _console->GetSoundMixer()->StopRecording(); }
|
||||
DllExport bool __stdcall WaveIsRecording() { return _console->GetSoundMixer()->IsRecording(); }
|
||||
|
||||
DllExport void __stdcall MoviePlay(char* filename) { MovieManager::Play(string(filename), _console); }
|
||||
DllExport void __stdcall MovieStop() { MovieManager::Stop(); }
|
||||
DllExport bool __stdcall MoviePlaying() { return MovieManager::Playing(); }
|
||||
DllExport bool __stdcall MovieRecording() { return MovieManager::Recording(); }
|
||||
DllExport void __stdcall MoviePlay(char* filename) { _console->GetMovieManager()->Play(string(filename)); }
|
||||
DllExport void __stdcall MovieStop() { _console->GetMovieManager()->Stop(); }
|
||||
DllExport bool __stdcall MoviePlaying() { return _console->GetMovieManager()->Playing(); }
|
||||
DllExport bool __stdcall MovieRecording() { return _console->GetMovieManager()->Recording(); }
|
||||
DllExport void __stdcall MovieRecord(RecordMovieOptions *options)
|
||||
{
|
||||
RecordMovieOptions opt = *options;
|
||||
MovieManager::Record(opt, _console);
|
||||
_console->GetMovieManager()->Record(opt);
|
||||
}
|
||||
}
|
31
InteropDLL/TestApiWrapper.cpp
Normal file
31
InteropDLL/TestApiWrapper.cpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
#include "stdafx.h"
|
||||
#include "../Core/RecordedRomTest.h"
|
||||
#include "../Core/Console.h"
|
||||
|
||||
extern shared_ptr<Console> _console;
|
||||
shared_ptr<RecordedRomTest> _recordedRomTest;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
DllExport int32_t __stdcall RunRecordedTest(char* filename, bool inBackground)
|
||||
{
|
||||
shared_ptr<RecordedRomTest> romTest(new RecordedRomTest(inBackground ? nullptr : _console));
|
||||
return romTest->Run(filename);
|
||||
}
|
||||
|
||||
DllExport void __stdcall RomTestRecord(char* filename, bool reset)
|
||||
{
|
||||
_recordedRomTest.reset(new RecordedRomTest(_console));
|
||||
_recordedRomTest->Record(filename, reset);
|
||||
}
|
||||
|
||||
DllExport void __stdcall RomTestStop()
|
||||
{
|
||||
if(_recordedRomTest) {
|
||||
_recordedRomTest->Stop();
|
||||
_recordedRomTest.reset();
|
||||
}
|
||||
}
|
||||
|
||||
DllExport bool __stdcall RomTestRecording() { return _recordedRomTest != nullptr; }
|
||||
}
|
68
UI/Forms/frmMain.Designer.cs
generated
68
UI/Forms/frmMain.Designer.cs
generated
|
@ -112,6 +112,7 @@
|
|||
this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.mnuPreferences = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuTools = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuCheats = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuMovies = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuPlayMovie = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuRecordMovie = new System.Windows.Forms.ToolStripMenuItem();
|
||||
|
@ -124,6 +125,11 @@
|
|||
this.mnuAviRecord = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuAviStop = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripMenuItem11 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.mnuTests = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuTestRun = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuTestRecord = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuTestStop = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuRunAllTests = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuLogWindow = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripMenuItem7 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.mnuRandomGame = new System.Windows.Forms.ToolStripMenuItem();
|
||||
|
@ -152,7 +158,6 @@
|
|||
this.mnuAbout = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.pnlRenderer = new System.Windows.Forms.Panel();
|
||||
this.ctrlRecentGames = new Mesen.GUI.Controls.ctrlRecentGames();
|
||||
this.mnuCheats = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuMain.SuspendLayout();
|
||||
this.pnlRenderer.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
|
@ -787,6 +792,7 @@
|
|||
this.mnuSoundRecorder,
|
||||
this.mnuVideoRecorder,
|
||||
this.toolStripMenuItem11,
|
||||
this.mnuTests,
|
||||
this.mnuLogWindow,
|
||||
this.toolStripMenuItem7,
|
||||
this.mnuRandomGame,
|
||||
|
@ -798,6 +804,13 @@
|
|||
this.mnuTools.DropDownOpening += new System.EventHandler(this.mnuTools_DropDownOpening);
|
||||
this.mnuTools.DropDownOpened += new System.EventHandler(this.mnu_DropDownOpened);
|
||||
//
|
||||
// mnuCheats
|
||||
//
|
||||
this.mnuCheats.Image = global::Mesen.GUI.Properties.Resources.CheatCode;
|
||||
this.mnuCheats.Name = "mnuCheats";
|
||||
this.mnuCheats.Size = new System.Drawing.Size(182, 22);
|
||||
this.mnuCheats.Text = "Cheats";
|
||||
//
|
||||
// mnuMovies
|
||||
//
|
||||
this.mnuMovies.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
|
@ -813,7 +826,7 @@
|
|||
//
|
||||
this.mnuPlayMovie.Image = global::Mesen.GUI.Properties.Resources.MediaPlay;
|
||||
this.mnuPlayMovie.Name = "mnuPlayMovie";
|
||||
this.mnuPlayMovie.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuPlayMovie.Size = new System.Drawing.Size(120, 22);
|
||||
this.mnuPlayMovie.Text = "Play...";
|
||||
this.mnuPlayMovie.Click += new System.EventHandler(this.mnuPlayMovie_Click);
|
||||
//
|
||||
|
@ -821,7 +834,7 @@
|
|||
//
|
||||
this.mnuRecordMovie.Image = global::Mesen.GUI.Properties.Resources.Record;
|
||||
this.mnuRecordMovie.Name = "mnuRecordMovie";
|
||||
this.mnuRecordMovie.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuRecordMovie.Size = new System.Drawing.Size(120, 22);
|
||||
this.mnuRecordMovie.Text = "Record...";
|
||||
this.mnuRecordMovie.Click += new System.EventHandler(this.mnuRecordMovie_Click);
|
||||
//
|
||||
|
@ -829,7 +842,7 @@
|
|||
//
|
||||
this.mnuStopMovie.Image = global::Mesen.GUI.Properties.Resources.MediaStop;
|
||||
this.mnuStopMovie.Name = "mnuStopMovie";
|
||||
this.mnuStopMovie.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuStopMovie.Size = new System.Drawing.Size(120, 22);
|
||||
this.mnuStopMovie.Text = "Stop";
|
||||
this.mnuStopMovie.Click += new System.EventHandler(this.mnuStopMovie_Click);
|
||||
//
|
||||
|
@ -895,6 +908,41 @@
|
|||
this.toolStripMenuItem11.Name = "toolStripMenuItem11";
|
||||
this.toolStripMenuItem11.Size = new System.Drawing.Size(179, 6);
|
||||
//
|
||||
// mnuTests
|
||||
//
|
||||
this.mnuTests.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.mnuTestRun,
|
||||
this.mnuTestRecord,
|
||||
this.mnuTestStop,
|
||||
this.mnuRunAllTests});
|
||||
this.mnuTests.Name = "mnuTests";
|
||||
this.mnuTests.Size = new System.Drawing.Size(182, 22);
|
||||
this.mnuTests.Text = "Tests";
|
||||
//
|
||||
// mnuTestRun
|
||||
//
|
||||
this.mnuTestRun.Name = "mnuTestRun";
|
||||
this.mnuTestRun.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuTestRun.Text = "Run...";
|
||||
//
|
||||
// mnuTestRecord
|
||||
//
|
||||
this.mnuTestRecord.Name = "mnuTestRecord";
|
||||
this.mnuTestRecord.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuTestRecord.Text = "Record...";
|
||||
//
|
||||
// mnuTestStop
|
||||
//
|
||||
this.mnuTestStop.Name = "mnuTestStop";
|
||||
this.mnuTestStop.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuTestStop.Text = "Stop recording";
|
||||
//
|
||||
// mnuRunAllTests
|
||||
//
|
||||
this.mnuRunAllTests.Name = "mnuRunAllTests";
|
||||
this.mnuRunAllTests.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuRunAllTests.Text = "Run all tests";
|
||||
//
|
||||
// mnuLogWindow
|
||||
//
|
||||
this.mnuLogWindow.Image = global::Mesen.GUI.Properties.Resources.LogWindow;
|
||||
|
@ -1115,13 +1163,6 @@
|
|||
this.ctrlRecentGames.TabIndex = 1;
|
||||
this.ctrlRecentGames.Visible = false;
|
||||
//
|
||||
// mnuCheats
|
||||
//
|
||||
this.mnuCheats.Image = global::Mesen.GUI.Properties.Resources.CheatCode;
|
||||
this.mnuCheats.Name = "mnuCheats";
|
||||
this.mnuCheats.Size = new System.Drawing.Size(182, 22);
|
||||
this.mnuCheats.Text = "Cheats";
|
||||
//
|
||||
// frmMain
|
||||
//
|
||||
this.AllowDrop = true;
|
||||
|
@ -1273,5 +1314,10 @@
|
|||
private System.Windows.Forms.ToolStripMenuItem mnuRegisterViewer;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuRandomGame;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuCheats;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuTests;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuTestRun;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuTestRecord;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuTestStop;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuRunAllTests;
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ using Mesen.GUI.Debugger;
|
|||
using Mesen.GUI.Debugger.Workspace;
|
||||
using Mesen.GUI.Emulation;
|
||||
using Mesen.GUI.Forms.Config;
|
||||
using Mesen.GUI.Interop;
|
||||
using Mesen.GUI.Updates;
|
||||
using Mesen.GUI.Utilities;
|
||||
using System;
|
||||
|
@ -54,6 +55,10 @@ namespace Mesen.GUI.Forms
|
|||
protected override void OnShown(EventArgs e)
|
||||
{
|
||||
base.OnShown(e);
|
||||
|
||||
#if HIDETESTMENU
|
||||
mnuTests.Visible = false;
|
||||
#endif
|
||||
|
||||
EmuApi.InitDll();
|
||||
bool showUpgradeMessage = UpdateHelper.PerformUpgrade();
|
||||
|
@ -211,6 +216,17 @@ namespace Mesen.GUI.Forms
|
|||
mnuMain.Focus();
|
||||
}
|
||||
}
|
||||
|
||||
#if !HIDETESTMENU
|
||||
if(keyData == Keys.Pause && EmuRunner.IsRunning()) {
|
||||
if(TestApi.RomTestRecording()) {
|
||||
TestApi.RomTestStop();
|
||||
} else {
|
||||
TestApi.RomTestRecord(ConfigManager.TestFolder + "\\" + EmuApi.GetRomInfo().GetRomName() + ".mtp", true);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return base.ProcessCmdKey(ref msg, keyData);
|
||||
}
|
||||
|
||||
|
@ -311,6 +327,11 @@ namespace Mesen.GUI.Forms
|
|||
mnuScriptWindow.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.ScriptWindow); };
|
||||
mnuRegisterViewer.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.RegisterViewer); };
|
||||
|
||||
mnuTestRun.Click += (s, e) => { RomTestHelper.RunTest(); };
|
||||
mnuTestRecord.Click += (s, e) => { RomTestHelper.RecordTest(); };
|
||||
mnuTestStop.Click += (s, e) => { RomTestHelper.StopRecording(); };
|
||||
mnuRunAllTests.Click += (s, e) => { RomTestHelper.RunAllTests(); };
|
||||
|
||||
UpdateDebuggerMenu();
|
||||
}
|
||||
|
||||
|
|
19
UI/Interop/TestApi.cs
Normal file
19
UI/Interop/TestApi.cs
Normal file
|
@ -0,0 +1,19 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Mesen.GUI.Interop
|
||||
{
|
||||
class TestApi
|
||||
{
|
||||
private const string DllPath = "MesenSCore.dll";
|
||||
|
||||
[DllImport(DllPath)] public static extern Int32 RunRecordedTest([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]string filename, [MarshalAs(UnmanagedType.I1)]bool inBackground);
|
||||
[DllImport(DllPath)] public static extern void RomTestRecord([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]string filename, [MarshalAs(UnmanagedType.I1)]bool reset);
|
||||
[DllImport(DllPath)] public static extern void RomTestStop();
|
||||
[DllImport(DllPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool RomTestRecording();
|
||||
}
|
||||
}
|
|
@ -835,6 +835,7 @@
|
|||
</Compile>
|
||||
<Compile Include="Interop\DebugState.cs" />
|
||||
<Compile Include="Interop\RecordApi.cs" />
|
||||
<Compile Include="Interop\TestApi.cs" />
|
||||
<Compile Include="Updates\frmDownloadProgress.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
|
@ -873,6 +874,7 @@
|
|||
<Compile Include="Utilities\Md5Helper.cs" />
|
||||
<Compile Include="Updates\UpdateHelper.cs" />
|
||||
<Compile Include="Utilities\RandomGameHelper.cs" />
|
||||
<Compile Include="Utilities\RomTestHelper.cs" />
|
||||
<Compile Include="Utilities\XmlColor.cs" />
|
||||
<None Include="Resources\GsuDebugger.png" />
|
||||
<None Include="Resources\Sa1Debugger.png" />
|
||||
|
|
92
UI/Utilities/RomTestHelper.cs
Normal file
92
UI/Utilities/RomTestHelper.cs
Normal file
|
@ -0,0 +1,92 @@
|
|||
using Mesen.GUI.Config;
|
||||
using Mesen.GUI.Forms;
|
||||
using Mesen.GUI.Interop;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Mesen.GUI.Utilities
|
||||
{
|
||||
public static class RomTestHelper
|
||||
{
|
||||
public static void RunTest()
|
||||
{
|
||||
using(OpenFileDialog ofd = new OpenFileDialog()) {
|
||||
ofd.SetFilter(ResourceHelper.GetMessage("FilterTest"));
|
||||
ofd.InitialDirectory = ConfigManager.TestFolder;
|
||||
if(ofd.ShowDialog(frmMain.Instance) == DialogResult.OK) {
|
||||
int result = TestApi.RunRecordedTest(ofd.FileName, false);
|
||||
|
||||
if(result == 0) {
|
||||
MessageBox.Show("Test passed.", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
} else {
|
||||
MessageBox.Show("ERROR: Test failed! (" + result + ")", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void RecordTest()
|
||||
{
|
||||
using(SaveFileDialog sfd = new SaveFileDialog()) {
|
||||
sfd.SetFilter(ResourceHelper.GetMessage("FilterTest"));
|
||||
sfd.InitialDirectory = ConfigManager.TestFolder;
|
||||
sfd.FileName = EmuApi.GetRomInfo().GetRomName() + ".mtp";
|
||||
if(sfd.ShowDialog(frmMain.Instance) == DialogResult.OK) {
|
||||
TestApi.RomTestRecord(sfd.FileName, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void RunAllTests()
|
||||
{
|
||||
Task.Run(() => {
|
||||
ConcurrentDictionary<string, int> results = new ConcurrentDictionary<string, int>();
|
||||
|
||||
List<string> testFiles = Directory.EnumerateFiles(ConfigManager.TestFolder, "*.mtp", SearchOption.AllDirectories).ToList();
|
||||
Parallel.ForEach(testFiles, new ParallelOptions() { MaxDegreeOfParallelism = 16 }, (string testFile) => {
|
||||
int result = TestApi.RunRecordedTest(testFile, true);
|
||||
results[Path.GetFileNameWithoutExtension(testFile)] = result;
|
||||
});
|
||||
|
||||
frmMain.Instance.BeginInvoke((Action)(() => {
|
||||
EmuApi.WriteLogEntry("==================");
|
||||
List<string> failedTests = new List<string>();
|
||||
foreach(var kvp in results) {
|
||||
if(kvp.Value > 0) {
|
||||
EmuApi.WriteLogEntry("[Test] Failed: " + kvp.Key + " (" + kvp.Value.ToString() + ")");
|
||||
failedTests.Add(kvp.Key);
|
||||
} else {
|
||||
EmuApi.WriteLogEntry("[Test] Passed: " + kvp.Key);
|
||||
}
|
||||
}
|
||||
|
||||
EmuApi.WriteLogEntry("==================");
|
||||
if(failedTests.Count > 0) {
|
||||
EmuApi.WriteLogEntry("Tests passed: " + (testFiles.Count - failedTests.Count));
|
||||
EmuApi.WriteLogEntry("Tests failed: " + failedTests.Count);
|
||||
foreach(string failedTest in failedTests) {
|
||||
EmuApi.WriteLogEntry(" Failed: " + failedTest);
|
||||
}
|
||||
} else {
|
||||
EmuApi.WriteLogEntry("All " + testFiles.Count + " tests passed!");
|
||||
}
|
||||
EmuApi.WriteLogEntry("==================");
|
||||
|
||||
new frmLogWindow().Show();
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
public static void StopRecording()
|
||||
{
|
||||
TestApi.RomTestStop();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue