diff --git a/Core/AutomaticRomTest.cpp b/Core/AutomaticRomTest.cpp new file mode 100644 index 00000000..30e15ed9 --- /dev/null +++ b/Core/AutomaticRomTest.cpp @@ -0,0 +1,167 @@ +#include "stdafx.h" +#include "../Utilities/FolderUtilities.h" +#include "AutomaticRomTest.h" +#include "EmulationSettings.h" +#include "Console.h" +#include "PPU.h" +#include "VideoDecoder.h" +#include "StandardController.h" + +bool AutomaticRomTest::_running = false; + +AutomaticRomTest::AutomaticRomTest() +{ + _running = true; + _errorCode = 0; + MessageManager::RegisterNotificationListener(this); +} + +AutomaticRomTest::~AutomaticRomTest() +{ + _running = false; + MessageManager::UnregisterNotificationListener(this); +} + +void AutomaticRomTest::ProcessNotification(ConsoleNotificationType type, void* parameter) +{ + if(type == ConsoleNotificationType::PpuFrameDone) { + uint16_t *frameBuffer = (uint16_t*)parameter; + if(PPU::GetFrameCount() == 5) { + memcpy(_prevFrameBuffer, frameBuffer, sizeof(_prevFrameBuffer)); + } else if(PPU::GetFrameCount() == 300) { + if(memcmp(_prevFrameBuffer, frameBuffer, sizeof(_prevFrameBuffer)) == 0) { + //No change + _errorCode |= 0x20; + } + memcpy(_prevFrameBuffer, frameBuffer, sizeof(_prevFrameBuffer)); + VideoDecoder::GetInstance()->TakeScreenshot(); + } else if(PPU::GetFrameCount() == 900) { + if(memcmp(_prevFrameBuffer, frameBuffer, sizeof(_prevFrameBuffer)) == 0) { + //No change + _errorCode |= 0x01; + } + + bool allZeros = true; + for(int i = 0; i < 256 * 240; i++) { + if(frameBuffer[i] != 0) { + allZeros = false; + break; + } + } + + if(allZeros) { + _errorCode |= 0x04; + } + + memcpy(_prevFrameBuffer, frameBuffer, sizeof(_prevFrameBuffer)); + VideoDecoder::GetInstance()->TakeScreenshot(); + } else if(PPU::GetFrameCount() == 1800) { + bool continueTest = false; + if(memcmp(_prevFrameBuffer, frameBuffer, sizeof(_prevFrameBuffer)) == 0) { + //No change, change input pattern and keep trying + continueTest = true; + } + + bool allZeros = true; + for(int i = 0; i < 256 * 240; i++) { + if(frameBuffer[i] != 0) { + allZeros = false; + break; + } + } + + if(allZeros) { + _errorCode |= 0x08; + } + + VideoDecoder::GetInstance()->TakeScreenshot(); + + if(!continueTest) { + //Stop test + _signal.Signal(); + } + } else if(PPU::GetFrameCount() == 3600) { + if(memcmp(_prevFrameBuffer, frameBuffer, sizeof(_prevFrameBuffer)) == 0) { + //No change + _errorCode |= 0x02; + } + + bool allZeros = true; + for(int i = 0; i < 256 * 240; i++) { + if(frameBuffer[i] != 0) { + allZeros = false; + break; + } + } + + if(allZeros) { + _errorCode |= 0x40; + } + + VideoDecoder::GetInstance()->TakeScreenshot(); + + //Stop test + _signal.Signal(); + } + } +} + +int32_t AutomaticRomTest::Run(string filename) +{ + EmulationSettings::SetEmulationSpeed(0); + EmulationSettings::SetMasterVolume(0); + Console::Pause(); + if(Console::LoadROM(filename)) { + Console::Resume(); + EmulationSettings::ClearFlags(EmulationFlags::Paused); + _signal.Wait(); + + EmulationSettings::SetFlags(EmulationFlags::Paused); + + if(PPU::GetFrameCount() < 1800) { + //Finished early + _errorCode |= 0x10; + } + + EmulationSettings::SetEmulationSpeed(100); + EmulationSettings::SetMasterVolume(1.0); + + Console::GetInstance()->Stop(); + + return _errorCode; + } + + return -1; +} + +bool AutomaticRomTest::Running() +{ + return _running; +} + +uint8_t AutomaticRomTest::GetControllerState(uint8_t port) +{ + if(port == 0) { + uint32_t frameNumber = PPU::GetFrameCount(); + + if(frameNumber <= 1800) { + if(frameNumber % 30 < 10) { + //Press 1 button for 10 frames every second + if((frameNumber / 30) % 8 != 1) { + return 1 << ((frameNumber / 60) % 8); + } + } + } else { + if(frameNumber % 30 < 10) { + if((frameNumber / 30) % 2) { + return 0x01; + } else { + return 0x08; + } + } + } + return 0; + } else { + return 0; + } +} diff --git a/Core/AutomaticRomTest.h b/Core/AutomaticRomTest.h new file mode 100644 index 00000000..48d9f4cf --- /dev/null +++ b/Core/AutomaticRomTest.h @@ -0,0 +1,23 @@ +#pragma once +#include "stdafx.h" +#include "INotificationListener.h" +#include "../Utilities/AutoResetEvent.h" + +class AutomaticRomTest : public INotificationListener +{ +private: + AutoResetEvent _signal; + static bool _running; + uint16_t _prevFrameBuffer[256 * 240]; + uint32_t _errorCode; + +public: + AutomaticRomTest(); + ~AutomaticRomTest(); + + void ProcessNotification(ConsoleNotificationType type, void* parameter) override; + int32_t Run(string filename); + + static bool Running(); + static uint8_t GetControllerState(uint8_t port); +}; \ No newline at end of file diff --git a/Core/BaseControlDevice.cpp b/Core/BaseControlDevice.cpp index b73ed016..77d42e8c 100644 --- a/Core/BaseControlDevice.cpp +++ b/Core/BaseControlDevice.cpp @@ -5,6 +5,7 @@ #include "EmulationSettings.h" #include "GameClient.h" #include "GameServerConnection.h" +#include "AutomaticRomTest.h" BaseControlDevice::BaseControlDevice(uint8_t port) { @@ -63,6 +64,8 @@ uint8_t BaseControlDevice::GetControlState() _currentState = MovieManager::GetState(_port); } else if(GameClient::Connected()) { _currentState = GameClient::GetControllerState(_port); + } else if(AutomaticRomTest::Running()) { + _currentState = AutomaticRomTest::GetControllerState(_port); } else if(netPlayDevice) { _currentState = ProcessNetPlayState(netPlayDevice->GetState()); } else { diff --git a/Core/Console.cpp b/Core/Console.cpp index 7567029b..c9e950a5 100644 --- a/Core/Console.cpp +++ b/Core/Console.cpp @@ -43,7 +43,7 @@ void Console::Release() Console::Instance.reset(new Console()); } -void Console::Initialize(string romFilename, stringstream *filestream, string patchFilename, int32_t archiveFileIndex) +bool Console::Initialize(string romFilename, stringstream *filestream, string patchFilename, int32_t archiveFileIndex) { SoundMixer::StopAudio(); @@ -105,16 +105,19 @@ void Console::Initialize(string romFilename, stringstream *filestream, string pa if(EmulationSettings::GetOverclockRate() != 100) { MessageManager::DisplayMessage("ClockRate", std::to_string(EmulationSettings::GetOverclockRate()) + "%"); } + return true; } else { MessageManager::DisplayMessage("Error", "CouldNotLoadFile", FolderUtilities::GetFilename(romFilename, true)); + return false; } } -void Console::LoadROM(string filepath, stringstream *filestream, int32_t archiveFileIndex, string patchFilepath) +bool Console::LoadROM(string filepath, stringstream *filestream, int32_t archiveFileIndex, string patchFilepath) { Console::Pause(); - Instance->Initialize(filepath, filestream, patchFilepath, archiveFileIndex); + bool result = Instance->Initialize(filepath, filestream, patchFilepath, archiveFileIndex); Console::Resume(); + return result; } bool Console::LoadROM(string romName, uint32_t crc32Hash) @@ -145,8 +148,7 @@ bool Console::LoadROM(string romName, HashInfo hashInfo) for(string folder : FolderUtilities::GetKnownGameFolders()) { string match = RomLoader::FindMatchingRomInFolder(folder, romName, hashInfo, true, archiveFileIndex); if(!match.empty()) { - Console::LoadROM(match, nullptr, archiveFileIndex); - return true; + return Console::LoadROM(match, nullptr, archiveFileIndex); } } @@ -154,8 +156,7 @@ bool Console::LoadROM(string romName, HashInfo hashInfo) for(string folder : FolderUtilities::GetKnownGameFolders()) { string match = RomLoader::FindMatchingRomInFolder(folder, romName, hashInfo, false, archiveFileIndex); if(!match.empty()) { - Console::LoadROM(match, nullptr, archiveFileIndex); - return true; + return Console::LoadROM(match, nullptr, archiveFileIndex); } } diff --git a/Core/Console.h b/Core/Console.h index cecdb4bb..1509d1ee 100644 --- a/Core/Console.h +++ b/Core/Console.h @@ -47,7 +47,7 @@ class Console bool _initialized = false; void ResetComponents(bool softReset); - void Initialize(string filename, stringstream *filestream = nullptr, string patchFilename = "", int32_t archiveFileIndex = -1); + bool Initialize(string filename, stringstream *filestream = nullptr, string patchFilename = "", int32_t archiveFileIndex = -1); void UpdateNesModel(bool sendNotification); double GetFrameDelay(); @@ -73,7 +73,7 @@ class Console static void LoadState(istream &loadStream); static void LoadState(uint8_t *buffer, uint32_t bufferSize); - static void LoadROM(string filepath, stringstream *filestream = nullptr, int32_t archiveFileIndex = -1, string patchFilepath = ""); + static bool LoadROM(string filepath, stringstream *filestream = nullptr, int32_t archiveFileIndex = -1, string patchFilepath = ""); static bool LoadROM(string romName, HashInfo hashInfo); static bool LoadROM(string romName, uint32_t crc32Hash); static bool LoadROM(string romName, string sha1Hash); diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 3dddf80f..aa74f7ea 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -410,7 +410,8 @@ - + + @@ -764,7 +765,8 @@ - + + diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index 54a34887..7be3550d 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -553,9 +553,6 @@ Nes - - Misc - Misc @@ -1156,6 +1153,12 @@ Movies + + Misc + + + Misc + @@ -1185,9 +1188,6 @@ Debugger - - Misc - VideoDecoder @@ -1365,5 +1365,11 @@ Movies + + Misc + + + Misc + \ No newline at end of file diff --git a/Core/AutoRomTest.cpp b/Core/RecordedRomTest.cpp similarity index 89% rename from Core/AutoRomTest.cpp rename to Core/RecordedRomTest.cpp index 6fd6d75f..031a6792 100644 --- a/Core/AutoRomTest.cpp +++ b/Core/RecordedRomTest.cpp @@ -1,6 +1,6 @@ #include "stdafx.h" -#include "AutoRomTest.h" +#include "RecordedRomTest.h" #include "Console.h" #include "EmulationSettings.h" #include "MessageManager.h" @@ -11,21 +11,21 @@ #include "../Utilities/ZipWriter.h" #include "../Utilities/ZipReader.h" -AutoRomTest::AutoRomTest() +RecordedRomTest::RecordedRomTest() { Reset(); MessageManager::RegisterNotificationListener(this); } -AutoRomTest::~AutoRomTest() +RecordedRomTest::~RecordedRomTest() { Reset(); MessageManager::UnregisterNotificationListener(this); } -void AutoRomTest::SaveFrame(uint16_t* ppuFrameBuffer) +void RecordedRomTest::SaveFrame(uint16_t* ppuFrameBuffer) { uint8_t md5Hash[16]; GetMd5Sum(md5Hash, ppuFrameBuffer, PPU::PixelCount * sizeof(uint16_t)); @@ -47,7 +47,7 @@ void AutoRomTest::SaveFrame(uint16_t* ppuFrameBuffer) } } -void AutoRomTest::ValidateFrame(uint16_t* ppuFrameBuffer) +void RecordedRomTest::ValidateFrame(uint16_t* ppuFrameBuffer) { uint8_t md5Hash[16]; GetMd5Sum(md5Hash, ppuFrameBuffer, PPU::PixelCount * sizeof(uint16_t)); @@ -71,7 +71,7 @@ void AutoRomTest::ValidateFrame(uint16_t* ppuFrameBuffer) } } -void AutoRomTest::ProcessNotification(ConsoleNotificationType type, void* parameter) +void RecordedRomTest::ProcessNotification(ConsoleNotificationType type, void* parameter) { switch(type) { case ConsoleNotificationType::PpuFrameDone: @@ -89,7 +89,7 @@ void AutoRomTest::ProcessNotification(ConsoleNotificationType type, void* parame } } -void AutoRomTest::Reset() +void RecordedRomTest::Reset() { memset(_previousHash, 0xFF, 16); @@ -107,7 +107,7 @@ void AutoRomTest::Reset() _recordingFromMovie = false; } -void AutoRomTest::Record(string filename, bool reset) +void RecordedRomTest::Record(string filename, bool reset) { _filename = filename; @@ -127,7 +127,7 @@ void AutoRomTest::Record(string filename, bool reset) } } -void AutoRomTest::RecordFromMovie(string testFilename, stringstream &movieStream, bool autoLoadRom) +void RecordedRomTest::RecordFromMovie(string testFilename, stringstream &movieStream, bool autoLoadRom) { _filename = testFilename; @@ -151,7 +151,7 @@ void AutoRomTest::RecordFromMovie(string testFilename, stringstream &movieStream } } -void AutoRomTest::RecordFromMovie(string testFilename, string movieFilename) +void RecordedRomTest::RecordFromMovie(string testFilename, string movieFilename) { stringstream ss; ifstream file(movieFilename, ios::in | ios::binary); @@ -162,7 +162,7 @@ void AutoRomTest::RecordFromMovie(string testFilename, string movieFilename) } } -void AutoRomTest::RecordFromTest(string newTestFilename, string existingTestFilename) +void RecordedRomTest::RecordFromTest(string newTestFilename, string existingTestFilename) { ZipReader zipReader; zipReader.LoadArchive(existingTestFilename); @@ -180,7 +180,7 @@ void AutoRomTest::RecordFromTest(string newTestFilename, string existingTestFile } } -int32_t AutoRomTest::Run(string filename) +int32_t RecordedRomTest::Run(string filename) { string testName = FolderUtilities::GetFilename(filename, false); if(testName.compare("5.MMC3_rev_A") == 0 || testName.compare("6-MMC6") == 0 || testName.compare("6-MMC3_alt") == 0) { @@ -255,7 +255,7 @@ int32_t AutoRomTest::Run(string filename) return -1; } -void AutoRomTest::Stop() +void RecordedRomTest::Stop() { if(_recording) { Save(); @@ -263,7 +263,7 @@ void AutoRomTest::Stop() Reset(); } -void AutoRomTest::Save() +void RecordedRomTest::Save() { //Wait until the next frame is captured to end the recording _signal.Wait(); diff --git a/Core/AutoRomTest.h b/Core/RecordedRomTest.h similarity index 91% rename from Core/AutoRomTest.h rename to Core/RecordedRomTest.h index a3e55565..4eab3f01 100644 --- a/Core/AutoRomTest.h +++ b/Core/RecordedRomTest.h @@ -5,7 +5,7 @@ #include "INotificationListener.h" #include "../Utilities/AutoResetEvent.h" -class AutoRomTest : public INotificationListener +class RecordedRomTest : public INotificationListener { private: bool _recording; @@ -35,8 +35,8 @@ private: void RecordFromMovie(string testFilename, stringstream &movieStream, bool autoLoadRom); public: - AutoRomTest(); - virtual ~AutoRomTest(); + RecordedRomTest(); + virtual ~RecordedRomTest(); void ProcessNotification(ConsoleNotificationType type, void* parameter) override; void Record(string filename, bool reset); diff --git a/GUI.NET/Forms/frmMain.Designer.cs b/GUI.NET/Forms/frmMain.Designer.cs index 5da77b7c..f06834d3 100644 --- a/GUI.NET/Forms/frmMain.Designer.cs +++ b/GUI.NET/Forms/frmMain.Designer.cs @@ -179,6 +179,7 @@ namespace Mesen.GUI.Forms this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripSeparator(); this.mnuHelpWindow = new System.Windows.Forms.ToolStripMenuItem(); this.mnuAbout = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuRunAutomaticTest = new System.Windows.Forms.ToolStripMenuItem(); this.panelRenderer.SuspendLayout(); this.menuStrip.SuspendLayout(); this.SuspendLayout(); @@ -1238,7 +1239,8 @@ namespace Mesen.GUI.Forms this.mnuTestRecordFrom, this.mnuTestStopRecording, this.mnuRunAllTests, - this.mnuRunAllGameTests}); + this.mnuRunAllGameTests, + this.mnuRunAutomaticTest}); this.mnuTests.Name = "mnuTests"; this.mnuTests.Size = new System.Drawing.Size(231, 22); this.mnuTests.Text = "Tests"; @@ -1265,28 +1267,28 @@ namespace Mesen.GUI.Forms // this.mnuTestRecordStart.Name = "mnuTestRecordStart"; this.mnuTestRecordStart.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.W))); - this.mnuTestRecordStart.Size = new System.Drawing.Size(143, 22); + this.mnuTestRecordStart.Size = new System.Drawing.Size(152, 22); this.mnuTestRecordStart.Text = "Start"; this.mnuTestRecordStart.Click += new System.EventHandler(this.mnuTestRecordStart_Click); // // mnuTestRecordNow // this.mnuTestRecordNow.Name = "mnuTestRecordNow"; - this.mnuTestRecordNow.Size = new System.Drawing.Size(143, 22); + this.mnuTestRecordNow.Size = new System.Drawing.Size(152, 22); this.mnuTestRecordNow.Text = "Now"; this.mnuTestRecordNow.Click += new System.EventHandler(this.mnuTestRecordNow_Click); // // mnuTestRecordMovie // this.mnuTestRecordMovie.Name = "mnuTestRecordMovie"; - this.mnuTestRecordMovie.Size = new System.Drawing.Size(143, 22); + this.mnuTestRecordMovie.Size = new System.Drawing.Size(152, 22); this.mnuTestRecordMovie.Text = "Movie"; this.mnuTestRecordMovie.Click += new System.EventHandler(this.mnuTestRecordMovie_Click); // // mnuTestRecordTest // this.mnuTestRecordTest.Name = "mnuTestRecordTest"; - this.mnuTestRecordTest.Size = new System.Drawing.Size(143, 22); + this.mnuTestRecordTest.Size = new System.Drawing.Size(152, 22); this.mnuTestRecordTest.Text = "Test"; this.mnuTestRecordTest.Click += new System.EventHandler(this.mnuTestRecordTest_Click); // @@ -1406,6 +1408,13 @@ namespace Mesen.GUI.Forms this.mnuAbout.Text = "About"; this.mnuAbout.Click += new System.EventHandler(this.mnuAbout_Click); // + // mnuRunAutomaticTest + // + this.mnuRunAutomaticTest.Name = "mnuRunAutomaticTest"; + this.mnuRunAutomaticTest.Size = new System.Drawing.Size(192, 22); + this.mnuRunAutomaticTest.Text = "Run automatic test"; + this.mnuRunAutomaticTest.Click += new System.EventHandler(this.mnuRunAutomaticTest_Click); + // // frmMain // this.AllowDrop = true; @@ -1580,6 +1589,7 @@ namespace Mesen.GUI.Forms private System.Windows.Forms.ToolStripMenuItem mnuPrescale6xFilter; private System.Windows.Forms.ToolStripMenuItem mnuPrescale8xFilter; private System.Windows.Forms.ToolStripMenuItem mnuPrescale10xFilter; + private System.Windows.Forms.ToolStripMenuItem mnuRunAutomaticTest; } } diff --git a/GUI.NET/Forms/frmMain.cs b/GUI.NET/Forms/frmMain.cs index eb962ebc..b43171f3 100644 --- a/GUI.NET/Forms/frmMain.cs +++ b/GUI.NET/Forms/frmMain.cs @@ -1060,7 +1060,7 @@ namespace Mesen.GUI.Forms Task.Run(() => { foreach(string filename in ofd.FileNames) { - int result = InteropEmu.RomTestRun(filename); + int result = InteropEmu.RunRecordedTest(filename); if(result == 0) { passedTests.Add(Path.GetFileNameWithoutExtension(filename)); @@ -1207,6 +1207,20 @@ namespace Mesen.GUI.Forms InteropEmu.SetNesModel(ConfigManager.Config.Region); } + private void mnuRunAutomaticTest_Click(object sender, EventArgs e) + { + using(OpenFileDialog ofd = new OpenFileDialog()) { + ofd.SetFilter("*.nes|*.nes"); + if(ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { + string filename = ofd.FileName; + + Task.Run(() => { + int result = InteropEmu.RunAutomaticTest(filename); + }); + } + } + } + private void mnuRunAllTests_Click(object sender, EventArgs e) { string workingDirectory = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)); diff --git a/GUI.NET/InteropEmu.cs b/GUI.NET/InteropEmu.cs index 7ebbce58..94dd1de2 100644 --- a/GUI.NET/InteropEmu.cs +++ b/GUI.NET/InteropEmu.cs @@ -99,7 +99,8 @@ namespace Mesen.GUI [DllImport(DLLPath)] public static extern void WaveStop(); [DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool WaveIsRecording(); - [DllImport(DLLPath)] public static extern Int32 RomTestRun([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename); + [DllImport(DLLPath)] public static extern Int32 RunRecordedTest([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename); + [DllImport(DLLPath)] public static extern Int32 RunAutomaticTest([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string filename); [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 RomTestRecordFromMovie([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string testFilename, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string movieFilename); [DllImport(DLLPath)] public static extern void RomTestRecordFromTest([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string newTestFilename, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string existingTestFilename); diff --git a/InteropDLL/ConsoleWrapper.cpp b/InteropDLL/ConsoleWrapper.cpp index 73ff9694..aa7cc8d4 100644 --- a/InteropDLL/ConsoleWrapper.cpp +++ b/InteropDLL/ConsoleWrapper.cpp @@ -9,7 +9,8 @@ #include "../Core/CheatManager.h" #include "../Core/EmulationSettings.h" #include "../Core/VideoDecoder.h" -#include "../Core/AutoRomTest.h" +#include "../Core/AutomaticRomTest.h" +#include "../Core/RecordedRomTest.h" #include "../Core/FDS.h" #include "../Core/VsControlManager.h" #include "../Core/SoundMixer.h" @@ -37,7 +38,7 @@ void* _windowHandle = nullptr; void* _viewerHandle = nullptr; string _returnString; string _logString; -AutoRomTest *_autoRomTest = nullptr; +RecordedRomTest *_recordedRomTest = nullptr; typedef void (__stdcall *NotificationListenerCallback)(int); @@ -313,43 +314,49 @@ namespace InteropEmu { DllExport void __stdcall WaveStop() { SoundMixer::StopRecording(); } DllExport bool __stdcall WaveIsRecording() { return SoundMixer::IsRecording(); } - DllExport int32_t __stdcall RomTestRun(char* filename) + DllExport int32_t __stdcall RunRecordedTest(char* filename) { - AutoRomTest romTest; + RecordedRomTest romTest; + return romTest.Run(filename); + } + + DllExport int32_t __stdcall RunAutomaticTest(char* filename) + { + AutomaticRomTest romTest; return romTest.Run(filename); } DllExport void __stdcall RomTestRecord(char* filename, bool reset) { - if(_autoRomTest) { - delete _autoRomTest; + if(_recordedRomTest) { + delete _recordedRomTest; } - _autoRomTest = new AutoRomTest(); - _autoRomTest->Record(filename, reset); + _recordedRomTest = new RecordedRomTest(); + _recordedRomTest->Record(filename, reset); } DllExport void __stdcall RomTestRecordFromMovie(char* testFilename, char* movieFilename) { - _autoRomTest = new AutoRomTest(); - _autoRomTest->RecordFromMovie(testFilename, movieFilename); + _recordedRomTest = new RecordedRomTest(); + _recordedRomTest->RecordFromMovie(testFilename, movieFilename); } DllExport void __stdcall RomTestRecordFromTest(char* newTestFilename, char* existingTestFilename) { - _autoRomTest = new AutoRomTest(); - _autoRomTest->RecordFromTest(newTestFilename, existingTestFilename); + _recordedRomTest = new RecordedRomTest(); + _recordedRomTest->RecordFromTest(newTestFilename, existingTestFilename); } DllExport void __stdcall RomTestStop() { - if(_autoRomTest) { - _autoRomTest->Stop(); - delete _autoRomTest; - _autoRomTest = nullptr; + if(_recordedRomTest) { + _recordedRomTest->Stop(); + delete _recordedRomTest; + _recordedRomTest = nullptr; } } - DllExport bool __stdcall RomTestRecording() { return _autoRomTest != nullptr; } + DllExport bool __stdcall RomTestRecording() { return _recordedRomTest != nullptr; } DllExport void __stdcall SetCheats(CheatInfo cheats[], uint32_t length) { CheatManager::SetCheats(cheats, length); } diff --git a/TestHelper/TestHelper.cpp b/TestHelper/TestHelper.cpp index 9374f2c3..37e98f11 100644 --- a/TestHelper/TestHelper.cpp +++ b/TestHelper/TestHelper.cpp @@ -46,7 +46,8 @@ public: extern "C" { void __stdcall InitializeEmu(const char* homeFolder, void*, void*, bool, bool, bool); void __stdcall SetControllerType(uint32_t port, ControllerType type); - int __stdcall RomTestRun(char* filename); + int __stdcall RunAutomaticTest(char* filename); + int __stdcall RunRecordedTest(char* filename); void __stdcall LoadROM(char* filename); void __stdcall Run(); void __stdcall Stop(); @@ -57,21 +58,27 @@ std::thread *runThread = nullptr; std::atomic testIndex; vector testFilenames; vector failedTests; +vector failedTestErrorCode; SimpleLock lock; Timer timer; +bool automaticTests = false; + +void RunEmu() +{ + try { + Run(); + } catch(std::exception ex) { + + } +} void __stdcall OnNotificationReceived(ConsoleNotificationType type) { if(type == ConsoleNotificationType::GameLoaded) { - runThread = new std::thread(Run); + runThread = new std::thread(RunEmu); } } -void RunEmu() -{ - Run(); -} - void RunTest() { while(true) { @@ -82,11 +89,21 @@ void RunTest() if(index < testFilenames.size()) { string filepath = testFilenames[index]; string filename = FolderUtilities::GetFilename(filepath, false); - #ifdef _WIN32 - string command = "TestHelper.exe /testrom \"" + filepath + "\""; - #else - string command = "./testhelper /testrom \"" + filepath + "\""; - #endif + + string command; + if(automaticTests) { + #ifdef _WIN32 + command = "TestHelper.exe /autotest \"" + filepath + "\""; + #else + command = "./testhelper /autotest \"" + filepath + "\""; + #endif + } else { + #ifdef _WIN32 + command = "TestHelper.exe /testrom \"" + filepath + "\""; + #else + command = "./testhelper /testrom \"" + filepath + "\""; + #endif + } lock.Acquire(); std::cout << std::to_string(index) << ") " << filename << std::endl; @@ -101,6 +118,7 @@ void RunTest() //Test failed lock.Acquire(); failedTests.push_back(filename); + failedTestErrorCode.push_back(failedFrames); std::cout << " **** " << std::to_string(index) << ") " << filename << " failed (" << failedFrames << ")" << std::endl; lock.Release(); } @@ -132,18 +150,24 @@ int main(int argc, char* argv[]) signal(SIGSEGV, handler); #endif - if(argc <= 2) { + if(argc >= 3 && strcmp(argv[1], "/auto") == 0) { + string romFolder = argv[2]; + testFilenames = FolderUtilities::GetFilesInFolder(romFolder, ".nes", true); + automaticTests = true; + } else if(argc <= 2) { string testFolder; if(argc == 1) { testFolder = FolderUtilities::CombinePath(mesenFolder, "Tests"); } else { testFolder = argv[1]; } - - vector testThreads; testFilenames = FolderUtilities::GetFilesInFolder(testFolder, ".mtp", true); - testIndex = 0; + automaticTests = false; + } + if(!testFilenames.empty()) { + vector testThreads; + testIndex = 0; timer.Reset(); int numberOfThreads = 4; @@ -162,9 +186,10 @@ int main(int argc, char* argv[]) std::cout << "------------" << std::endl; std::cout << "Failed tests" << std::endl; std::cout << "------------" << std::endl; - for(string failedTest : failedTests) { - std::cout << failedTest << std::endl; + for(int i = 0; i < failedTests.size(); i++) { + std::cout << failedTests[i] << " (" << std::to_string(failedTestErrorCode[i]) << ")" << std::endl; } + std::cout << std::endl << std::to_string(failedTests.size()) << " tests failed." << std::endl; } else { std::cout << std::endl << std::endl << "All tests passed."; } @@ -179,7 +204,13 @@ int main(int argc, char* argv[]) SetControllerType(0, ControllerType::StandardController); SetControllerType(1, ControllerType::StandardController); - int result = RomTestRun(testFilename); + int result = 0; + if(strcmp(argv[1], "/testrom") == 0) { + result = RunRecordedTest(testFilename); + } else { + result = RunAutomaticTest(testFilename); + } + if(runThread != nullptr) { runThread->join(); delete runThread;