mirror of
https://github.com/MoleskiCoder/EightBitNet.git
synced 2026-01-22 16:16:17 +00:00
Starting to port Fuse test runner for LR35902 emulator. Not running yet.
Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
This commit is contained in:
28
EightBit.sln
28
EightBit.sln
@@ -27,6 +27,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MC6850", "MC6850\MC6850.csp
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MC6809.Test", "MC6809\MC6809.Test\MC6809.Test.csproj", "{5ADB4727-2F5F-4A41-979B-6734501E34BC}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LR35902", "LR35902\LR35902.csproj", "{01F61A1D-CB4A-4EA3-96EF-222F831DF483}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LR35902.FuseTest", "LR35902\LR35902.FuseTest\LR35902.FuseTest.csproj", "{CC24B08D-1C51-43FD-961D-7C9A49253D69}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -181,6 +185,30 @@ Global
|
||||
{5ADB4727-2F5F-4A41-979B-6734501E34BC}.Release|x64.Build.0 = Release|Any CPU
|
||||
{5ADB4727-2F5F-4A41-979B-6734501E34BC}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{5ADB4727-2F5F-4A41-979B-6734501E34BC}.Release|x86.Build.0 = Release|Any CPU
|
||||
{01F61A1D-CB4A-4EA3-96EF-222F831DF483}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{01F61A1D-CB4A-4EA3-96EF-222F831DF483}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{01F61A1D-CB4A-4EA3-96EF-222F831DF483}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{01F61A1D-CB4A-4EA3-96EF-222F831DF483}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{01F61A1D-CB4A-4EA3-96EF-222F831DF483}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{01F61A1D-CB4A-4EA3-96EF-222F831DF483}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{01F61A1D-CB4A-4EA3-96EF-222F831DF483}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{01F61A1D-CB4A-4EA3-96EF-222F831DF483}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{01F61A1D-CB4A-4EA3-96EF-222F831DF483}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{01F61A1D-CB4A-4EA3-96EF-222F831DF483}.Release|x64.Build.0 = Release|Any CPU
|
||||
{01F61A1D-CB4A-4EA3-96EF-222F831DF483}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{01F61A1D-CB4A-4EA3-96EF-222F831DF483}.Release|x86.Build.0 = Release|Any CPU
|
||||
{CC24B08D-1C51-43FD-961D-7C9A49253D69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CC24B08D-1C51-43FD-961D-7C9A49253D69}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CC24B08D-1C51-43FD-961D-7C9A49253D69}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{CC24B08D-1C51-43FD-961D-7C9A49253D69}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{CC24B08D-1C51-43FD-961D-7C9A49253D69}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{CC24B08D-1C51-43FD-961D-7C9A49253D69}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{CC24B08D-1C51-43FD-961D-7C9A49253D69}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CC24B08D-1C51-43FD-961D-7C9A49253D69}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CC24B08D-1C51-43FD-961D-7C9A49253D69}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{CC24B08D-1C51-43FD-961D-7C9A49253D69}.Release|x64.Build.0 = Release|Any CPU
|
||||
{CC24B08D-1C51-43FD-961D-7C9A49253D69}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{CC24B08D-1C51-43FD-961D-7C9A49253D69}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
6
LR35902/LR35902.FuseTest/App.config
Normal file
6
LR35902/LR35902.FuseTest/App.config
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
|
||||
</startup>
|
||||
</configuration>
|
||||
58
LR35902/LR35902.FuseTest/ExpectedTestResult.cs
Normal file
58
LR35902/LR35902.FuseTest/ExpectedTestResult.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
namespace Fuse
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
public class ExpectedTestResult
|
||||
{
|
||||
private readonly TestEvents events = new TestEvents();
|
||||
|
||||
public bool Finish { get; private set; } = false;
|
||||
|
||||
public string Description { get; private set; }
|
||||
|
||||
public RegisterState RegisterState { get; } = new RegisterState();
|
||||
|
||||
public List<MemoryDatum> MemoryData { get; } = new List<MemoryDatum>();
|
||||
|
||||
public void Read(StreamReader file)
|
||||
{
|
||||
this.Finish = false;
|
||||
do
|
||||
{
|
||||
this.Description = file.ReadLine();
|
||||
this.Finish = file.EndOfStream;
|
||||
}
|
||||
while (string.IsNullOrEmpty(this.Description) && !this.Finish);
|
||||
|
||||
if (this.Finish)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.events.Read(file);
|
||||
this.RegisterState.Read(file);
|
||||
|
||||
var line = file.ReadLine();
|
||||
if (line.Length > 0)
|
||||
{
|
||||
throw new InvalidOperationException("EOL swallow failure!!");
|
||||
}
|
||||
|
||||
var finished = false;
|
||||
do
|
||||
{
|
||||
line = file.ReadLine();
|
||||
finished = string.IsNullOrEmpty(line);
|
||||
if (!finished)
|
||||
{
|
||||
var datum = new MemoryDatum();
|
||||
datum.Parse(line);
|
||||
this.MemoryData.Add(datum);
|
||||
}
|
||||
}
|
||||
while (!finished);
|
||||
}
|
||||
}
|
||||
}
|
||||
33
LR35902/LR35902.FuseTest/ExpectedTestResults.cs
Normal file
33
LR35902/LR35902.FuseTest/ExpectedTestResults.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
namespace Fuse
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
public class ExpectedTestResults
|
||||
{
|
||||
public Dictionary<string, ExpectedTestResult> Results { get; } = new Dictionary<string, ExpectedTestResult>();
|
||||
|
||||
public void Read(string path)
|
||||
{
|
||||
using (var file = new StreamReader(path))
|
||||
{
|
||||
this.Read(file);
|
||||
}
|
||||
}
|
||||
|
||||
private void Read(StreamReader file)
|
||||
{
|
||||
var finished = false;
|
||||
while (!file.EndOfStream)
|
||||
{
|
||||
var result = new ExpectedTestResult();
|
||||
result.Read(file);
|
||||
finished = result.Finish;
|
||||
if (!finished)
|
||||
{
|
||||
this.Results[result.Description] = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
73
LR35902/LR35902.FuseTest/LR35902.FuseTest.csproj
Normal file
73
LR35902/LR35902.FuseTest/LR35902.FuseTest.csproj
Normal file
@@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{CC24B08D-1C51-43FD-961D-7C9A49253D69}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>Fuse</RootNamespace>
|
||||
<AssemblyName>LR35902.FuseTest</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ExpectedTestResult.cs" />
|
||||
<Compile Include="ExpectedTestResults.cs" />
|
||||
<Compile Include="MemoryDatum.cs" />
|
||||
<Compile Include="RegisterState.cs" />
|
||||
<Compile Include="Test.cs" />
|
||||
<Compile Include="TestEvent.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="TestEvents.cs" />
|
||||
<Compile Include="TestRunner.cs" />
|
||||
<Compile Include="Tests.cs" />
|
||||
<Compile Include="TestSuite.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\EightBit\EightBit.csproj">
|
||||
<Project>{6ebf8857-62a3-4ef4-af21-c1844031d7e4}</Project>
|
||||
<Name>EightBit</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\LR35902.csproj">
|
||||
<Project>{01f61a1d-cb4a-4ea3-96ef-222f831df483}</Project>
|
||||
<Name>LR35902</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
34
LR35902/LR35902.FuseTest/MemoryDatum.cs
Normal file
34
LR35902/LR35902.FuseTest/MemoryDatum.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
namespace Fuse
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class MemoryDatum
|
||||
{
|
||||
public ushort Address { get; private set; } = (ushort)EightBit.Mask.Mask16;
|
||||
|
||||
public List<byte> Bytes { get; } = new List<byte>();
|
||||
|
||||
public void Parse(string line)
|
||||
{
|
||||
var tokens = line.Split(new char[] { ' ', '\t' });
|
||||
this.Parse(tokens);
|
||||
}
|
||||
|
||||
public void Parse(string[] tokens)
|
||||
{
|
||||
this.Address = Convert.ToUInt16(tokens[0], 16);
|
||||
|
||||
var finished = false;
|
||||
for (var i = 1; !finished && (i < tokens.Length); ++i)
|
||||
{
|
||||
var token = tokens[i];
|
||||
finished = token == "-1";
|
||||
if (!finished)
|
||||
{
|
||||
this.Bytes.Add(Convert.ToByte(token, 16));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
LR35902/LR35902.FuseTest/Program.cs
Normal file
11
LR35902/LR35902.FuseTest/Program.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace Fuse
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
TestSuite testSuite = new TestSuite("fuse-tests\\tests");
|
||||
testSuite.Run();
|
||||
}
|
||||
}
|
||||
}
|
||||
36
LR35902/LR35902.FuseTest/Properties/AssemblyInfo.cs
Normal file
36
LR35902/LR35902.FuseTest/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("LR35902.FuseTest")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("LR35902.FuseTest")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2019")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("cc24b08d-1c51-43fd-961d-7c9a49253d69")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
44
LR35902/LR35902.FuseTest/RegisterState.cs
Normal file
44
LR35902/LR35902.FuseTest/RegisterState.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
namespace Fuse
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using EightBit;
|
||||
|
||||
public class RegisterState
|
||||
{
|
||||
public enum Register
|
||||
{
|
||||
AF, BC, DE, HL, SP, PC
|
||||
};
|
||||
|
||||
public List<Register16> Registers { get; } = new List<Register16>();
|
||||
public bool Halted { get; private set; } = false;
|
||||
public int TStates { get; private set; } = -1;
|
||||
|
||||
public void Read(StreamReader file)
|
||||
{
|
||||
this.ReadExternalState(file);
|
||||
this.ReadInternalState(file);
|
||||
}
|
||||
|
||||
private void ReadInternalState(StreamReader file)
|
||||
{
|
||||
var line = file.ReadLine();
|
||||
var tokens = line.Split(new char[] { ' ', '\t' });
|
||||
|
||||
this.Halted = Convert.ToInt32(tokens[0]) == 1;
|
||||
this.TStates = Convert.ToInt32(tokens[1]);
|
||||
}
|
||||
|
||||
private void ReadExternalState(StreamReader file)
|
||||
{
|
||||
var line = file.ReadLine();
|
||||
foreach (var token in line.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
this.Registers.Add(new Register16(Convert.ToUInt16(token, 16)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
45
LR35902/LR35902.FuseTest/Test.cs
Normal file
45
LR35902/LR35902.FuseTest/Test.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
namespace Fuse
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
public class Test
|
||||
{
|
||||
public bool Valid => !string.IsNullOrEmpty(this.Description);
|
||||
|
||||
public string Description { get; private set; }
|
||||
|
||||
public RegisterState RegisterState { get; } = new RegisterState();
|
||||
|
||||
public List<MemoryDatum> MemoryData { get; } = new List<MemoryDatum>();
|
||||
|
||||
public void Read(StreamReader file)
|
||||
{
|
||||
while ((string.IsNullOrWhiteSpace(this.Description) || this.Description.StartsWith(";")) && !file.EndOfStream)
|
||||
{
|
||||
this.Description = file.ReadLine();
|
||||
}
|
||||
|
||||
if (!this.Valid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.RegisterState.Read(file);
|
||||
|
||||
var finished = false;
|
||||
do
|
||||
{
|
||||
var line = file.ReadLine();
|
||||
finished = line == "-1";
|
||||
if (!finished)
|
||||
{
|
||||
var datum = new MemoryDatum();
|
||||
datum.Parse(line);
|
||||
this.MemoryData.Add(datum);
|
||||
}
|
||||
}
|
||||
while (!finished);
|
||||
}
|
||||
}
|
||||
}
|
||||
65
LR35902/LR35902.FuseTest/TestEvent.cs
Normal file
65
LR35902/LR35902.FuseTest/TestEvent.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
namespace Fuse
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
public class TestEvent
|
||||
{
|
||||
public bool Valid { get; private set; } = false;
|
||||
|
||||
public int Cycles { get; private set; } = -1;
|
||||
|
||||
public string Specifier { get; private set; }
|
||||
|
||||
public ushort Address { get; private set; } = (ushort)EightBit.Mask.Mask16;
|
||||
|
||||
public ushort Value { get; private set; } = (byte)EightBit.Mask.Mask8;
|
||||
|
||||
public void Read(StreamReader file)
|
||||
{
|
||||
var prior = file.BaseStream.Position;
|
||||
this.ParseLine(file.ReadLine());
|
||||
if (!this.Valid)
|
||||
{
|
||||
file.BaseStream.Seek(prior, SeekOrigin.Begin);
|
||||
}
|
||||
}
|
||||
|
||||
private void ParseLine(string line)
|
||||
{
|
||||
var split = line.Split(new char[] { ' ', '\t' });
|
||||
this.ParseLine(split);
|
||||
}
|
||||
|
||||
private void ParseLine(string[] tokens)
|
||||
{
|
||||
this.Cycles = int.Parse(tokens[0]);
|
||||
this.Specifier = tokens[1];
|
||||
|
||||
this.Valid = true;
|
||||
switch (this.Specifier)
|
||||
{
|
||||
case "MR":
|
||||
case "MW":
|
||||
this.Address = Convert.ToUInt16(tokens[2], 16);
|
||||
this.Value = Convert.ToByte(tokens[3], 16);
|
||||
break;
|
||||
|
||||
case "MC":
|
||||
case "PC":
|
||||
this.Address = Convert.ToUInt16(tokens[2], 16);
|
||||
break;
|
||||
|
||||
case "PR":
|
||||
case "PW":
|
||||
this.Address = Convert.ToUInt16(tokens[2], 16);
|
||||
this.Value = Convert.ToByte(tokens[3], 16);
|
||||
break;
|
||||
|
||||
default:
|
||||
this.Valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
26
LR35902/LR35902.FuseTest/TestEvents.cs
Normal file
26
LR35902/LR35902.FuseTest/TestEvents.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
namespace Fuse
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
public class TestEvents
|
||||
{
|
||||
public List<TestEvent> Events { get; } = new List<TestEvent>();
|
||||
|
||||
public void Read(StreamReader file)
|
||||
{
|
||||
var complete = false;
|
||||
do
|
||||
{
|
||||
var e = new TestEvent();
|
||||
e.Read(file);
|
||||
complete = !e.Valid;
|
||||
if (!complete)
|
||||
{
|
||||
this.Events.Add(e);
|
||||
}
|
||||
}
|
||||
while (!complete);
|
||||
}
|
||||
}
|
||||
}
|
||||
204
LR35902/LR35902.FuseTest/TestRunner.cs
Normal file
204
LR35902/LR35902.FuseTest/TestRunner.cs
Normal file
@@ -0,0 +1,204 @@
|
||||
namespace Fuse
|
||||
{
|
||||
public class TestRunner : EightBit.GameBoy.Bus
|
||||
{
|
||||
private readonly Test test;
|
||||
private readonly ExpectedTestResult expected;
|
||||
private readonly EightBit.Ram ram = new EightBit.Ram(0x10000);
|
||||
|
||||
public TestRunner(Test test, ExpectedTestResult expected)
|
||||
{
|
||||
this.test = test;
|
||||
this.expected = expected;
|
||||
}
|
||||
|
||||
public bool Failed { get; private set; } = false;
|
||||
|
||||
public bool Unimplemented { get; private set; } = false;
|
||||
|
||||
public override EightBit.MemoryMapping Mapping(ushort address) => new EightBit.MemoryMapping(this.ram, 0, EightBit.Mask.Mask8, EightBit.AccessLevel.ReadWrite);
|
||||
|
||||
public void Run()
|
||||
{
|
||||
this.RaisePOWER();
|
||||
this.Initialize();
|
||||
var allowedCycles = this.test.RegisterState.TStates;
|
||||
try
|
||||
{
|
||||
this.CPU.Run(allowedCycles);
|
||||
this.Check();
|
||||
}
|
||||
catch (System.InvalidOperationException error)
|
||||
{
|
||||
this.Unimplemented = true;
|
||||
System.Console.Error.WriteLine($"**** Error: {error.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public override void RaisePOWER()
|
||||
{
|
||||
base.RaisePOWER();
|
||||
this.CPU.RaisePOWER();
|
||||
this.CPU.RaiseRESET();
|
||||
this.CPU.RaiseINT();
|
||||
this.InitialiseRegisters();
|
||||
this.InitialiseMemory();
|
||||
}
|
||||
|
||||
public override void LowerPOWER()
|
||||
{
|
||||
this.CPU.LowerPOWER();
|
||||
base.LowerPOWER();
|
||||
}
|
||||
|
||||
public override void Initialize() => this.DisableGameRom();
|
||||
|
||||
private void InitialiseRegisters()
|
||||
{
|
||||
var testState = this.test.RegisterState;
|
||||
var inputRegisters = testState.Registers;
|
||||
|
||||
this.CPU.AF.Word = inputRegisters[(int)RegisterState.Register.AF].Word;
|
||||
this.CPU.BC.Word = inputRegisters[(int)RegisterState.Register.BC].Word;
|
||||
this.CPU.DE.Word = inputRegisters[(int)RegisterState.Register.DE].Word;
|
||||
this.CPU.HL.Word = inputRegisters[(int)RegisterState.Register.HL].Word;
|
||||
|
||||
this.CPU.SP.Word = inputRegisters[(int)RegisterState.Register.SP].Word;
|
||||
this.CPU.PC.Word = inputRegisters[(int)RegisterState.Register.PC].Word;
|
||||
}
|
||||
|
||||
private void InitialiseMemory()
|
||||
{
|
||||
foreach (var memoryDatum in this.test.MemoryData)
|
||||
{
|
||||
var address = memoryDatum.Address;
|
||||
var bytes = memoryDatum.Bytes;
|
||||
for (var i = 0; i < bytes.Count; ++i)
|
||||
{
|
||||
this.Poke((ushort)(address + i), bytes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Check()
|
||||
{
|
||||
this.Checkregisters();
|
||||
this.CheckMemory();
|
||||
}
|
||||
|
||||
private void Checkregisters()
|
||||
{
|
||||
var expectedState = this.expected.RegisterState;
|
||||
var expectedRegisters = expectedState.Registers;
|
||||
|
||||
var af = this.CPU.AF.Word == expectedRegisters[(int)RegisterState.Register.AF].Word;
|
||||
var bc = this.CPU.BC.Word == expectedRegisters[(int)RegisterState.Register.BC].Word;
|
||||
var de = this.CPU.DE.Word == expectedRegisters[(int)RegisterState.Register.DE].Word;
|
||||
var hl = this.CPU.HL.Word == expectedRegisters[(int)RegisterState.Register.HL].Word;
|
||||
|
||||
var sp = this.CPU.SP.Word == expectedRegisters[(int)RegisterState.Register.SP].Word;
|
||||
var pc = this.CPU.PC.Word == expectedRegisters[(int)RegisterState.Register.PC].Word;
|
||||
|
||||
var success = af && bc && de && hl && sp && pc;
|
||||
if (!success)
|
||||
{
|
||||
this.Failed = true;
|
||||
System.Console.Error.WriteLine($"**** Failed test (Register): {this.test.Description}");
|
||||
|
||||
if (!af)
|
||||
{
|
||||
var expectedWord = expectedRegisters[(int)RegisterState.Register.AF];
|
||||
var actualWord = this.CPU.AF;
|
||||
DumpDifference("A", "F", expectedWord, actualWord);
|
||||
}
|
||||
|
||||
if (!bc)
|
||||
{
|
||||
var expectedWord = expectedRegisters[(int)RegisterState.Register.BC];
|
||||
var actualWord = this.CPU.BC;
|
||||
DumpDifference("B", "C", expectedWord, actualWord);
|
||||
}
|
||||
|
||||
if (!de)
|
||||
{
|
||||
var expectedWord = expectedRegisters[(int)RegisterState.Register.DE];
|
||||
var actualWord = this.CPU.DE;
|
||||
DumpDifference("D", "E", expectedWord, actualWord);
|
||||
}
|
||||
|
||||
if (!hl)
|
||||
{
|
||||
var expectedWord = expectedRegisters[(int)RegisterState.Register.HL];
|
||||
var actualWord = this.CPU.HL;
|
||||
DumpDifference("H", "L", expectedWord, actualWord);
|
||||
}
|
||||
|
||||
if (!sp)
|
||||
{
|
||||
var expectedWord = expectedRegisters[(int)RegisterState.Register.SP];
|
||||
var actualWord = this.CPU.SP;
|
||||
DumpDifference("SPH", "SPL", expectedWord, actualWord);
|
||||
}
|
||||
|
||||
if (!pc)
|
||||
{
|
||||
var expectedWord = expectedRegisters[(int)RegisterState.Register.PC];
|
||||
var actualWord = this.CPU.PC;
|
||||
DumpDifference("PCH", "PCL", expectedWord, actualWord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckMemory()
|
||||
{
|
||||
var first = true;
|
||||
|
||||
foreach (var memoryDatum in this.expected.MemoryData)
|
||||
{
|
||||
var bytes = memoryDatum.Bytes;
|
||||
for (var i = 0; i < bytes.Count; ++i)
|
||||
{
|
||||
var expected = bytes[i];
|
||||
var address = (ushort)(memoryDatum.Address + i);
|
||||
var actual = this.Peek(address);
|
||||
if (expected != actual)
|
||||
{
|
||||
this.Failed = true;
|
||||
if (first)
|
||||
{
|
||||
first = false;
|
||||
System.Console.Error.WriteLine($"**** Failed test (Memory): {this.test.Description}");
|
||||
}
|
||||
|
||||
System.Console.Error.WriteLine($"**** Difference: Address: {address:x4} Expected: {expected:x2} Actual: {actual:x2}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void DumpDifference(string description, byte expected, byte actual)
|
||||
{
|
||||
var output = $"**** {description}, Expected: {expected:x2}, Got {actual:x2}";
|
||||
System.Console.Error.WriteLine(output);
|
||||
}
|
||||
|
||||
private static void DumpDifference(string highDescription, string lowDescription, EightBit.Register16 expected, EightBit.Register16 actual)
|
||||
{
|
||||
var expectedHigh = expected.High;
|
||||
var expectedLow = expected.Low;
|
||||
|
||||
var actualHigh = actual.High;
|
||||
var actualLow = actual.Low;
|
||||
|
||||
if (expectedHigh != actualHigh)
|
||||
{
|
||||
DumpDifference(highDescription, actualHigh, expectedHigh);
|
||||
}
|
||||
|
||||
if (expectedLow != actualLow)
|
||||
{
|
||||
DumpDifference(lowDescription, actualLow, expectedLow);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
42
LR35902/LR35902.FuseTest/TestSuite.cs
Normal file
42
LR35902/LR35902.FuseTest/TestSuite.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
namespace Fuse
|
||||
{
|
||||
public class TestSuite
|
||||
{
|
||||
private readonly Tests tests = new Tests();
|
||||
private readonly ExpectedTestResults results = new ExpectedTestResults();
|
||||
|
||||
public TestSuite(string path)
|
||||
{
|
||||
this.tests.Read(path + ".in");
|
||||
this.results.Read(path + ".expected");
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
var failedCount = 0;
|
||||
var unimplementedCount = 0;
|
||||
foreach (var test in this.tests.Container)
|
||||
{
|
||||
var key = test.Key;
|
||||
System.Console.Out.WriteLine($"** Checking: {key}");
|
||||
|
||||
var input = test.Value;
|
||||
var result = this.results.Results[key];
|
||||
var runner = new TestRunner(input, result);
|
||||
|
||||
runner.Run();
|
||||
if (runner.Failed)
|
||||
{
|
||||
++failedCount;
|
||||
}
|
||||
|
||||
if (runner.Unimplemented)
|
||||
{
|
||||
++unimplementedCount;
|
||||
}
|
||||
}
|
||||
System.Console.Out.WriteLine($"+++ Failed test count: {failedCount}");
|
||||
System.Console.Out.WriteLine($"+++ Unimplemented test count: {unimplementedCount}");
|
||||
}
|
||||
}
|
||||
}
|
||||
31
LR35902/LR35902.FuseTest/Tests.cs
Normal file
31
LR35902/LR35902.FuseTest/Tests.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
namespace Fuse
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
public class Tests
|
||||
{
|
||||
public void Read(string path)
|
||||
{
|
||||
using (var file = new StreamReader(path))
|
||||
{
|
||||
this.Read(file);
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<string, Test> Container { get; } = new Dictionary<string, Test>();
|
||||
|
||||
public void Read(StreamReader file)
|
||||
{
|
||||
while (!file.EndOfStream)
|
||||
{
|
||||
var test = new Test();
|
||||
test.Read(file);
|
||||
if (test.Valid)
|
||||
{
|
||||
this.Container.Add(test.Description, test);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
79
LR35902/LR35902.FuseTest/fuse-tests/README
Normal file
79
LR35902/LR35902.FuseTest/fuse-tests/README
Normal file
@@ -0,0 +1,79 @@
|
||||
File formats
|
||||
============
|
||||
|
||||
tests.in
|
||||
--------
|
||||
|
||||
Each test has the format:
|
||||
|
||||
<arbitrary test description>
|
||||
AF BC DE HL SP PC
|
||||
<halted> <tstates>
|
||||
|
||||
<halted> specifies whether the Z80 is halted.
|
||||
<tstates> specifies the number of tstates to run the test for, in
|
||||
decimal; the number actually executed may be higher, as the final
|
||||
instruction is allowed to complete.
|
||||
|
||||
Then followed by lines specifying the initial memory setup. Each has
|
||||
the format:
|
||||
|
||||
<start address> <byte1> <byte2> ... -1
|
||||
|
||||
eg
|
||||
|
||||
1234 56 78 9a -1
|
||||
|
||||
says to put 0x56 at 0x1234, 0x78 at 0x1235 and 0x9a at 0x1236.
|
||||
|
||||
Finally, -1 to end the test. Blank lines may follow before the next test.
|
||||
|
||||
tests.expected
|
||||
--------------
|
||||
|
||||
Each test output starts with the test description, followed by a list
|
||||
of 'events': each has the format
|
||||
|
||||
<time> <type> <address> <data>
|
||||
|
||||
<time> is simply the time at which the event occurs.
|
||||
<type> is one of MR (memory read), MW (memory write), MC (memory
|
||||
contend), PR (port read), PW (port write) or PC (port contend).
|
||||
<address> is the address (or IO port) affected.
|
||||
<data> is the byte written or read. Missing for contentions.
|
||||
|
||||
After that, lines specifying AF, BC etc as for .in files. <tstates>
|
||||
now specifies the final time.
|
||||
|
||||
After that, lines specifying which bits of memory have changed since
|
||||
the initial setup. Same format as for .in files.
|
||||
|
||||
Why some specific tests are here
|
||||
================================
|
||||
|
||||
{02,0a,32}_1,edb[012389ab]_[12],d3_4:
|
||||
check MEMPTR is set correctly after various instructions.
|
||||
|
||||
37_{1,2,3}: check the behaviour of SCF with respect to bits 3 and 5
|
||||
(bug fixed on 20040225).
|
||||
|
||||
cb46_{1,2,3,4,5}: check the correct bits of MEMPTR are copied to bits 3
|
||||
and 5 of the flags register after a BIT n,(HL) instruction.
|
||||
|
||||
cb{4,5,6,7}{7,f}_1: designed to check that bits 3 and 5 are copied to
|
||||
F only for BIT 3,<arg> and BIT 5,<arg> respectively
|
||||
(bug fixed on 20040225).
|
||||
|
||||
However, later research has revealed the bits 3
|
||||
and 5 are copied on all BIT instructions, so these
|
||||
tests are now essentially redundant.
|
||||
|
||||
d{3,b}_{1,2,3}: check for correct port contention on IO in the four
|
||||
relevant states (port high byte in 0x40 to 0x7f or not,
|
||||
port low bit set or reset).
|
||||
|
||||
dd00.in, ddfd00.in: test timings of "extended NOP" opcodes DD 00 and
|
||||
DD FD 00; the extra 00 at the end is to check the
|
||||
next opcode executes at the right time (bug fixed
|
||||
on 20060722).
|
||||
|
||||
5011
LR35902/LR35902.FuseTest/fuse-tests/tests.expected
Normal file
5011
LR35902/LR35902.FuseTest/fuse-tests/tests.expected
Normal file
File diff suppressed because it is too large
Load Diff
3653
LR35902/LR35902.FuseTest/fuse-tests/tests.in
Normal file
3653
LR35902/LR35902.FuseTest/fuse-tests/tests.in
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user