diff --git a/Core/Gameboy/GbPpu.cpp b/Core/Gameboy/GbPpu.cpp index c6a8872a..2d75a60c 100644 --- a/Core/Gameboy/GbPpu.cpp +++ b/Core/Gameboy/GbPpu.cpp @@ -994,7 +994,10 @@ uint8_t GbPpu::ReadOam(uint8_t addr) return 0xFF; } } - return 0; + + //"This area returns $FF when OAM is blocked, and otherwise the behavior depends on the hardware revision." + //TODOGB CGB behavior + return _memoryManager->IsOamDmaRunning() ? 0xFF : 0; } void GbPpu::WriteOam(uint8_t addr, uint8_t value, bool forDma) diff --git a/InteropDLL/TestApiWrapper.cpp b/InteropDLL/TestApiWrapper.cpp index 0f2f6db4..a4e268b0 100644 --- a/InteropDLL/TestApiWrapper.cpp +++ b/InteropDLL/TestApiWrapper.cpp @@ -22,7 +22,7 @@ extern "C" } } - DllExport uint32_t __stdcall RunTest(char* filename) + DllExport uint64_t __stdcall RunTest(char* filename, uint32_t address, MemoryType memType) { unique_ptr emu(new Emulator()); emu->Initialize(); @@ -33,11 +33,20 @@ extern "C" emu->GetSettings()->SetFlag(EmulationFlags::MaximumSpeed); while(emu->GetFrameCount() < 500) { - std::this_thread::sleep_for(std::chrono::duration(50)); + std::this_thread::sleep_for(std::chrono::duration(10)); } - uint8_t result = ((uint8_t*)emu->GetMemory(MemoryType::GbHighRam).Memory)[2]; - + ConsoleMemoryInfo memInfo = emu->GetMemory(memType); + uint8_t* memBuffer = (uint8_t*)memInfo.Memory; + uint64_t result = memBuffer[address]; + for(int i = 1; i < 8; i++) { + if(address + i < memInfo.Size) { + result |= ((uint64_t)memBuffer[address + i] << (8*i)); + } else { + break; + } + } + emu->Stop(false); emu->Release(); diff --git a/UI/Interop/TestApi.cs b/UI/Interop/TestApi.cs index 9a655654..2ce1c251 100644 --- a/UI/Interop/TestApi.cs +++ b/UI/Interop/TestApi.cs @@ -12,7 +12,7 @@ namespace Mesen.Interop private const string DllPath = EmuApi.DllName; [DllImport(DllPath)] public static extern RomTestResult RunRecordedTest([MarshalAs(UnmanagedType.LPUTF8Str)]string filename, [MarshalAs(UnmanagedType.I1)]bool inBackground); - [DllImport(DllPath)] public static extern UInt32 RunTest([MarshalAs(UnmanagedType.LPUTF8Str)]string filename); + [DllImport(DllPath)] public static extern UInt64 RunTest([MarshalAs(UnmanagedType.LPUTF8Str)]string filename, int address, MemoryType memType); [DllImport(DllPath)] public static extern void RomTestRecord([MarshalAs(UnmanagedType.LPUTF8Str)]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(); diff --git a/UI/Utilities/RomTestHelper.cs b/UI/Utilities/RomTestHelper.cs index 33d2acaf..0ca61e31 100644 --- a/UI/Utilities/RomTestHelper.cs +++ b/UI/Utilities/RomTestHelper.cs @@ -9,6 +9,7 @@ using System.Drawing; using System.IO; using System.Linq; using System.Text; +using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; @@ -85,15 +86,15 @@ namespace Mesen.Utilities }); } - public static void RunGbMicroTests(bool all) + public static void RunGbMicroTests() { Task.Run(() => { - ConcurrentDictionary results = new(); + ConcurrentDictionary results = new(); - List testFiles = Directory.EnumerateFiles(@"C:\Code\gbmicrotest-main\bin" + (all ? "" : "\\pass"), "*.gb", SearchOption.AllDirectories).ToList(); + List testFiles = Directory.EnumerateFiles(@"C:\Code\gbmicrotest-main\bin", "*.gb", SearchOption.AllDirectories).ToList(); Parallel.ForEach(testFiles, new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount - 2 }, (string testFile) => { string entryName = Path.GetFileName(testFile); - results[entryName] = TestApi.RunTest(testFile); + results[entryName] = TestApi.RunTest(testFile, 0x02, MemoryType.GbHighRam); }); EmuApi.WriteLogEntry("=================="); @@ -102,7 +103,7 @@ namespace Mesen.Utilities entries.Sort(); foreach(var entry in entries) { - UInt32 result = results[entry]; + UInt64 result = results[entry] & 0xFF; string msg = "[Test] "; switch(result) { case 1: msg += "Pass"; break; @@ -136,5 +137,62 @@ namespace Mesen.Utilities }); }); } + + public static void RunGambatteTests() + { + Task.Run(() => { + ConcurrentDictionary results = new(); + + Regex regex = new Regex("dmg08_(cgb04c_){0,1}out([a-f0-9]+)[.]", RegexOptions.Compiled | RegexOptions.IgnoreCase); + string folder = @"C:\Code\gambatte-tests\"; + List testFiles = Directory.EnumerateFiles(folder, "*.gb*", SearchOption.AllDirectories).Where(x=>x.Contains("dmg08_") && regex.IsMatch(x)).ToList(); + Parallel.ForEach(testFiles, new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount - 2 }, (string testFile) => { + string entryName = testFile.Substring(folder.Length); + results[entryName] = TestApi.RunTest(testFile, 0x1800, MemoryType.GbVideoRam); + }); + + EmuApi.WriteLogEntry("=================="); + List failedTests = new List(); + List entries = results.Keys.ToList(); + entries.Sort(); + + foreach(var entry in entries) { + int resultSize = regex.Match(entry).Groups[2].Value.Length; + if(resultSize > 16) { + continue; + } + UInt64 mask = UInt64.Parse(new string('F', resultSize), System.Globalization.NumberStyles.AllowHexSpecifier); + + UInt64 decodedResult = 0; + for(int i = 0; i < resultSize; i++) { + decodedResult |= (results[entry] & ((ulong)0xF << i * 8)) >> (i * 4); + } + + UInt64 result = decodedResult & mask; + string hexResult = string.Join(null, result.ToString("X" + resultSize).Reverse()); + + bool passed = string.Compare(regex.Match(entry).Groups[2].Value, hexResult, true) == 0; + if(!passed) { + string msg = "[Test] FAIL [" + hexResult + "]: " + entry; + EmuApi.WriteLogEntry(msg); + failedTests.Add(entry); + } + } + + EmuApi.WriteLogEntry("=================="); + if(failedTests.Count > 0) { + EmuApi.WriteLogEntry("=================="); + EmuApi.WriteLogEntry("Tests passed: " + (testFiles.Count - failedTests.Count)); + EmuApi.WriteLogEntry("Tests failed: " + failedTests.Count); + } else { + EmuApi.WriteLogEntry("All " + testFiles.Count + " tests passed!"); + } + EmuApi.WriteLogEntry("=================="); + + Dispatcher.UIThread.Post(() => { + ApplicationHelper.GetOrCreateUniqueWindow(null, () => new LogWindow()); + }); + }); + } } } diff --git a/UI/Windows/MainWindow.axaml.cs b/UI/Windows/MainWindow.axaml.cs index 27f15ed6..e45aa23e 100644 --- a/UI/Windows/MainWindow.axaml.cs +++ b/UI/Windows/MainWindow.axaml.cs @@ -538,10 +538,10 @@ namespace Mesen.Windows RomTestHelper.RunAllTests(); return true; } else if(key == Key.F7) { - RomTestHelper.RunGbMicroTests(false); + RomTestHelper.RunGbMicroTests(); return true; } else if(key == Key.F8) { - RomTestHelper.RunGbMicroTests(true); + RomTestHelper.RunGambatteTests(); return true; } else if(key == Key.F6) { //For testing purposes (to test for memory leaks)