Add Z80 interrupt and pin tests

This commit is contained in:
Adrian Conlon committed 2026-05-17 20:48:22 +01:00
1 parent 1876a0d1f0
commit e9603b0e08
9 files changed
+644 -2

No files matched your search

+8 -2
View File
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34902.65
# Visual Studio Version 18
VisualStudioVersion = 18.5.11801.241 oobstable
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EightBit", "EightBit\EightBit.csproj", "{B9DB62BA-F1C6-41B4-BE0F-85A1D4E64A33}"
EndProject
@@ -45,6 +45,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Z80.HarteTest", "Z80\Z80.Ha
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EightBit.UnitTest", "EightBit\EightBit.UnitTest\EightBit.UnitTest.csproj", "{A8B3D819-0E84-4586-ADB1-D57AB1A8165B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Z80.UnitTests", "Z80\Z80.UnitTests\Z80.UnitTests.csproj", "{DB313D5B-9DC3-4844-9916-925678967112}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -135,6 +137,10 @@ Global
{A8B3D819-0E84-4586-ADB1-D57AB1A8165B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A8B3D819-0E84-4586-ADB1-D57AB1A8165B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A8B3D819-0E84-4586-ADB1-D57AB1A8165B}.Release|Any CPU.Build.0 = Release|Any CPU
{DB313D5B-9DC3-4844-9916-925678967112}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DB313D5B-9DC3-4844-9916-925678967112}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DB313D5B-9DC3-4844-9916-925678967112}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DB313D5B-9DC3-4844-9916-925678967112}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
+43
View File
@@ -0,0 +1,43 @@
// <copyright file="Board.cs" company="Adrian Conlon">
// Copyright (c) Adrian Conlon. All rights reserved.
// </copyright>
namespace Z80.UnitTests
{
using EightBit;
public sealed class Board : Bus
{
private readonly Ram ram = new(0x10000);
private readonly InputOutput ports = new();
private readonly MemoryMapping mapping;
public Board()
{
this.CPU = new(this, this.ports);
this.mapping = new(this.ram, 0x0000, (ushort)Mask.Sixteen, AccessLevel.ReadWrite);
}
public Z80 CPU { get; }
public override void Initialize()
{
}
public override MemoryMapping Mapping(ushort absolute) => this.mapping;
public override void RaisePOWER()
{
base.RaisePOWER();
this.CPU.RaisePOWER();
this.CPU.RaiseRESET();
this.CPU.RaiseINT();
this.CPU.RaiseNMI();
}
public override void LowerPOWER()
{
this.CPU.LowerPOWER();
base.LowerPOWER();
}
}
}
+88
View File
@@ -0,0 +1,88 @@
// <copyright file="HaltTests.cs" company="Adrian Conlon">
// Copyright (c) Adrian Conlon. All rights reserved.
// </copyright>
namespace Z80.UnitTests
{
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class HaltTests
{
private readonly Board board = new();
private readonly Z80 cpu;
public HaltTests() => this.cpu = this.board.CPU;
[TestInitialize]
public void Initialise()
{
this.board.RaisePOWER();
this.cpu.PC.Joined = 0x0000;
this.cpu.SP.Joined = 0xFF00;
}
[TestCleanup]
public void Cleanup() => this.board.LowerPOWER();
[TestMethod]
public void Halt_Instruction_Lowers_Halt_Pin()
{
this.board.Poke(0x0000, 0x76); // HALT
Assert.IsTrue(this.cpu.HALT.Raised(), "HALT pin should be inactive before HALT instruction");
this.cpu.Step();
Assert.IsTrue(this.cpu.HALT.Lowered(), "HALT pin should be active after HALT instruction");
}
[TestMethod]
public void Halt_State_Does_Not_Advance_PC()
{
this.board.Poke(0x0000, 0x76); // HALT
this.board.Poke(0x0001, 0x00); // NOP (should not execute while halted)
this.cpu.Step(); // execute HALT — PC advances to 0x0001
var pcAfterHalt = this.cpu.PC.Joined;
this.cpu.Step(); // CPU is halted — PC must not advance
Assert.AreEqual(pcAfterHalt, this.cpu.PC.Joined, "PC must not advance while CPU is halted");
}
[TestMethod]
public void Halt_Nmi_Raises_Halt_Pin()
{
this.board.Poke(0x0000, 0x76); // HALT
this.cpu.Step(); // enter HALT
Assert.IsTrue(this.cpu.HALT.Lowered(), "CPU must be halted before NMI test");
this.cpu.LowerNMI();
this.cpu.Step(); // NMI exits HALT and jumps to 0x0066
Assert.IsTrue(this.cpu.HALT.Raised(), "HALT pin must be raised after NMI");
}
[TestMethod]
public void Halt_Int_Raises_Halt_Pin_When_IFF1_Enabled()
{
this.board.Poke(0x0000, 0x76); // HALT
this.cpu.IFF1 = true;
this.cpu.IM = 1;
this.cpu.Step(); // enter HALT
Assert.IsTrue(this.cpu.HALT.Lowered(), "CPU must be halted before INT test");
this.cpu.LowerINT();
this.cpu.Step(); // INT exits HALT (IM1 → jumps to 0x0038)
Assert.IsTrue(this.cpu.HALT.Raised(), "HALT pin must be raised after INT with IFF1 enabled");
}
[TestMethod]
public void Halt_Int_Does_Not_Exit_When_IFF1_Disabled()
{
this.board.Poke(0x0000, 0x76); // HALT
this.cpu.IFF1 = false;
this.cpu.Step(); // enter HALT
var pcAfterHalt = this.cpu.PC.Joined;
Assert.IsTrue(this.cpu.HALT.Lowered(), "CPU must be halted before INT test");
this.cpu.LowerINT(); // INT pending, but IFF1=false so it will be dismissed
this.cpu.Step();
Assert.IsTrue(this.cpu.HALT.Lowered(), "CPU must remain halted when IFF1 is disabled");
Assert.AreEqual(pcAfterHalt, this.cpu.PC.Joined, "PC must not change when INT is masked");
}
}
}
+116
View File
@@ -0,0 +1,116 @@
// <copyright file="IffTests.cs" company="Adrian Conlon">
// Copyright (c) Adrian Conlon. All rights reserved.
// </copyright>
namespace Z80.UnitTests
{
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class IffTests
{
private readonly Board board = new();
private readonly Z80 cpu;
public IffTests() => this.cpu = this.board.CPU;
[TestInitialize]
public void Initialise()
{
this.board.RaisePOWER();
this.cpu.PC.Joined = 0x0000;
this.cpu.SP.Joined = 0xFF00;
}
[TestCleanup]
public void Cleanup() => this.board.LowerPOWER();
[TestMethod]
public void DI_Clears_IFF1_And_IFF2()
{
this.cpu.IFF1 = true;
this.cpu.IFF2 = true;
this.board.Poke(0x0000, 0xF3); // DI
this.cpu.Step();
Assert.IsFalse(this.cpu.IFF1, "DI must clear IFF1");
Assert.IsFalse(this.cpu.IFF2, "DI must clear IFF2");
}
[TestMethod]
public void EI_Sets_IFF1_And_IFF2()
{
this.cpu.IFF1 = false;
this.cpu.IFF2 = false;
this.board.Poke(0x0000, 0xFB); // EI
this.cpu.Step();
Assert.IsTrue(this.cpu.IFF1, "EI must set IFF1");
Assert.IsTrue(this.cpu.IFF2, "EI must set IFF2");
}
[TestMethod]
public void DI_Prevents_INT()
{
this.board.Poke(0x0000, 0x00); // NOP
this.cpu.IFF1 = false;
this.cpu.IM = 1;
this.cpu.LowerINT();
this.cpu.Step(); // pending cleared (IFF1=false), then NOP executes
Assert.AreEqual(0x0001, this.cpu.PC.Joined, "INT must be blocked when IFF1 is clear");
}
[TestMethod]
public void EI_Followed_By_INT_Fires_On_Next_LowerINT()
{
// After EI, the previous INT pending was already consumed without firing
// (because IFF1 was false when it was checked). INT must produce a new
// falling edge to retrigger. The INT pin is still low, so raise it first.
this.board.Poke(0x0000, 0xFB); // EI
this.board.Poke(0x0001, 0x00); // NOP
this.cpu.IFF1 = false;
this.cpu.IM = 1;
this.cpu.LowerINT(); // pending=true, but IFF1=false
this.cpu.Step(); // pending cleared (IFF1=false), EI runs → IFF1=true
Assert.IsTrue(this.cpu.IFF1, "IFF1 must be true after EI");
Assert.AreEqual(0x0001, this.cpu.PC.Joined, "No interrupt must fire during EI step");
this.cpu.Step(); // NOP at 0x0001 — still no interrupt (pending was cleared)
Assert.AreEqual(0x0002, this.cpu.PC.Joined, "No interrupt must fire on instruction after EI");
// Produce a new falling edge on INT (raise then lower) to retrigger
this.cpu.RaiseINT();
this.cpu.LowerINT();
this.cpu.Step();
Assert.AreEqual(0x0038, this.cpu.PC.Joined, "INT must fire after new falling edge post-EI");
}
[TestMethod]
public void Im_Set_Mode_0()
{
this.cpu.IM = 2;
this.board.Poke(0x0000, 0xED); // IM 0 prefix
this.board.Poke(0x0001, 0x46); // IM 0 (ED 46)
this.cpu.Step();
Assert.AreEqual(0, this.cpu.IM, "IM 0 instruction must set interrupt mode to 0");
}
[TestMethod]
public void Im_Set_Mode_1()
{
this.cpu.IM = 0;
this.board.Poke(0x0000, 0xED); // IM 1 prefix
this.board.Poke(0x0001, 0x56); // IM 1 (ED 56)
this.cpu.Step();
Assert.AreEqual(1, this.cpu.IM, "IM 1 instruction must set interrupt mode to 1");
}
[TestMethod]
public void Im_Set_Mode_2()
{
this.cpu.IM = 0;
this.board.Poke(0x0000, 0xED); // IM 2 prefix
this.board.Poke(0x0001, 0x5E); // IM 2 (ED 5E)
this.cpu.Step();
Assert.AreEqual(2, this.cpu.IM, "IM 2 instruction must set interrupt mode to 2");
}
}
}
+147
View File
@@ -0,0 +1,147 @@
// <copyright file="IntTests.cs" company="Adrian Conlon">
// Copyright (c) Adrian Conlon. All rights reserved.
// </copyright>
namespace Z80.UnitTests
{
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class IntTests
{
private readonly Board board = new();
private readonly Z80 cpu;
public IntTests() => this.cpu = this.board.CPU;
[TestInitialize]
public void Initialise()
{
this.board.RaisePOWER();
this.cpu.PC.Joined = 0x0200;
this.cpu.SP.Joined = 0xFF00;
this.cpu.IFF1 = true;
}
[TestCleanup]
public void Cleanup() => this.board.LowerPOWER();
// ── IM 1 ─────────────────────────────────────────────────────────────
[TestMethod]
public void Int_IM1_Jumps_To_0x0038()
{
this.cpu.IM = 1;
this.cpu.LowerINT();
this.cpu.Step();
Assert.AreEqual(0x0038, this.cpu.PC.Joined, "IM 1 INT must jump to 0x0038");
}
[TestMethod]
public void Int_IM1_Saves_PC_On_Stack()
{
this.cpu.PC.Joined = 0x1234;
this.cpu.IM = 1;
this.cpu.LowerINT();
this.cpu.Step();
var low = this.board.Peek(this.cpu.SP.Joined);
var high = this.board.Peek((ushort)(this.cpu.SP.Joined + 1));
var savedPc = (ushort)((high << 8) | low);
Assert.AreEqual(0x1234, savedPc, "IM 1 INT must save PC on the stack");
}
[TestMethod]
public void Int_IM1_Clears_IFF1_And_IFF2()
{
this.cpu.IFF2 = true;
this.cpu.IM = 1;
this.cpu.LowerINT();
this.cpu.Step();
Assert.IsFalse(this.cpu.IFF1, "INT must clear IFF1");
Assert.IsFalse(this.cpu.IFF2, "INT must clear IFF2");
}
[TestMethod]
public void Int_Blocked_When_IFF1_Disabled()
{
this.board.Poke(0x0200, 0x00); // NOP
this.cpu.IFF1 = false;
this.cpu.IM = 1;
this.cpu.LowerINT(); // INT pending, but IFF1 = false
this.cpu.Step();
Assert.AreEqual(0x0201, this.cpu.PC.Joined, "INT must not fire when IFF1 is disabled");
}
// ── IM 2 ─────────────────────────────────────────────────────────────
[TestMethod]
public void Int_IM2_Jumps_Via_Vector_Table()
{
// Vector table: address = (IV << 8) | bus_data_byte
// IV = 0x10, bus byte = 0x20 → table entry at 0x1020
// Table entry (little-endian) = 0x5678
this.cpu.IV = 0x10;
this.board.Poke(0x1020, 0x78);
this.board.Poke(0x1021, 0x56);
this.cpu.IM = 2;
this.board.Data = 0x20; // interrupt device places vector byte on data bus
this.cpu.LowerINT();
this.cpu.Step();
Assert.AreEqual(0x5678, this.cpu.PC.Joined, "IM 2 INT must read jump address from vector table");
}
[TestMethod]
public void Int_IM2_Saves_PC_On_Stack()
{
this.cpu.PC.Joined = 0xABCD;
this.cpu.IV = 0x10;
this.board.Poke(0x1020, 0x78);
this.board.Poke(0x1021, 0x56);
this.cpu.IM = 2;
this.board.Data = 0x20;
this.cpu.LowerINT();
this.cpu.Step();
var low = this.board.Peek(this.cpu.SP.Joined);
var high = this.board.Peek((ushort)(this.cpu.SP.Joined + 1));
var savedPc = (ushort)((high << 8) | low);
Assert.AreEqual(0xABCD, savedPc, "IM 2 INT must save PC on the stack");
}
// ── IM 0 ─────────────────────────────────────────────────────────────
[TestMethod]
public void Int_IM0_Executes_Instruction_From_Data_Bus()
{
// RST 7 (0xFF) placed on data bus by interrupt device → jumps to 0x0038
this.cpu.PC.Joined = 0x0200;
this.cpu.IM = 0;
this.board.Data = 0xFF; // RST 7
this.cpu.LowerINT();
this.cpu.Step();
Assert.AreEqual(0x0038, this.cpu.PC.Joined, "IM 0 INT must execute RST 7 from data bus");
}
// ── RETI ─────────────────────────────────────────────────────────────
[TestMethod]
public void Reti_Restores_PC_From_Stack()
{
// RETI (ED 4D) at 0x0038 — return to saved PC
this.board.Poke(0x0038, 0xED);
this.board.Poke(0x0039, 0x4D);
this.cpu.PC.Joined = 0x0200;
this.cpu.IM = 1;
this.cpu.LowerINT();
this.cpu.Step(); // handles INT, jumps to 0x0038, saves 0x0200
Assert.AreEqual(0x0038, this.cpu.PC.Joined);
this.cpu.Step(); // executes RETI
Assert.AreEqual(0x0200, this.cpu.PC.Joined, "RETI must restore PC from stack");
}
}
}
+110
View File
@@ -0,0 +1,110 @@
// <copyright file="NmiTests.cs" company="Adrian Conlon">
// Copyright (c) Adrian Conlon. All rights reserved.
// </copyright>
namespace Z80.UnitTests
{
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class NmiTests
{
private readonly Board board = new();
private readonly Z80 cpu;
public NmiTests() => this.cpu = this.board.CPU;
[TestInitialize]
public void Initialise()
{
this.board.RaisePOWER();
this.cpu.PC.Joined = 0x0100;
this.cpu.SP.Joined = 0xFF00;
}
[TestCleanup]
public void Cleanup() => this.board.LowerPOWER();
[TestMethod]
public void Nmi_Jumps_To_0x0066()
{
this.cpu.LowerNMI();
this.cpu.Step();
Assert.AreEqual(0x0066, this.cpu.PC.Joined, "NMI must jump to 0x0066");
}
[TestMethod]
public void Nmi_Saves_PC_On_Stack()
{
this.cpu.PC.Joined = 0x1234;
this.cpu.LowerNMI();
this.cpu.Step();
// PushShort pushes High first then Low, so:
// mem[SP-1] = PC.High, mem[SP-2] = PC.Low
var low = this.board.Peek(this.cpu.SP.Joined); // mem[SP] = PC.Low
var high = this.board.Peek((ushort)(this.cpu.SP.Joined + 1)); // mem[SP+1] = PC.High
var savedPc = (ushort)((high << 8) | low);
Assert.AreEqual(0x1234, savedPc, "NMI must save PC on the stack");
}
[TestMethod]
public void Nmi_Clears_IFF1()
{
this.cpu.IFF1 = true;
this.cpu.LowerNMI();
this.cpu.Step();
Assert.IsFalse(this.cpu.IFF1, "NMI must clear IFF1");
}
[TestMethod]
public void Nmi_Preserves_IFF1_In_IFF2()
{
this.cpu.IFF1 = true;
this.cpu.IFF2 = false;
this.cpu.LowerNMI();
this.cpu.Step();
Assert.IsTrue(this.cpu.IFF2, "NMI must copy IFF1 into IFF2 before clearing IFF1");
Assert.IsFalse(this.cpu.IFF1, "NMI must clear IFF1");
}
[TestMethod]
public void Nmi_Fires_Even_When_IFF1_Disabled()
{
this.cpu.IFF1 = false;
this.cpu.LowerNMI();
this.cpu.Step();
Assert.AreEqual(0x0066, this.cpu.PC.Joined, "NMI must fire regardless of IFF1");
}
[TestMethod]
public void Nmi_Exits_Halt_State()
{
this.board.Poke(0x0100, 0x76); // HALT
this.cpu.Step(); // enter HALT
Assert.IsTrue(this.cpu.HALT.Lowered(), "CPU must be halted before NMI test");
this.cpu.LowerNMI();
this.cpu.Step(); // NMI exits HALT
Assert.IsTrue(this.cpu.HALT.Raised(), "NMI must raise HALT pin");
Assert.AreEqual(0x0066, this.cpu.PC.Joined, "NMI must jump to 0x0066 from HALT state");
}
[TestMethod]
public void Retn_Restores_IFF1_From_IFF2()
{
// RETN (ED 45) at 0x0066
this.board.Poke(0x0066, 0xED);
this.board.Poke(0x0067, 0x45);
this.cpu.IFF1 = true;
this.cpu.LowerNMI();
this.cpu.Step(); // handles NMI: IFF2=true, IFF1=false, jumps to 0x0066
Assert.IsFalse(this.cpu.IFF1, "IFF1 must be false after NMI");
Assert.IsTrue(this.cpu.IFF2, "IFF2 must be true after NMI");
this.cpu.Step(); // executes RETN at 0x0066: IFF1 = IFF2 = true
Assert.IsTrue(this.cpu.IFF1, "RETN must restore IFF1 from IFF2");
}
}
}
+86
View File
@@ -0,0 +1,86 @@
// <copyright file="ResetTests.cs" company="Adrian Conlon">
// Copyright (c) Adrian Conlon. All rights reserved.
// </copyright>
namespace Z80.UnitTests
{
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class ResetTests
{
private readonly Board board = new();
private readonly Z80 cpu;
public ResetTests() => this.cpu = this.board.CPU;
[TestInitialize]
public void Initialise()
{
this.board.RaisePOWER();
this.cpu.PC.Joined = 0x1234;
this.cpu.SP.Joined = 0x8000;
}
[TestCleanup]
public void Cleanup() => this.board.LowerPOWER();
[TestMethod]
public void Reset_Sets_PC_To_Zero()
{
this.cpu.LowerRESET();
this.cpu.Step();
Assert.AreEqual(0x0000, this.cpu.PC.Joined, "RESET must set PC to 0x0000");
}
[TestMethod]
public void Reset_Clears_IFF1_And_IFF2()
{
this.cpu.IFF1 = true;
this.cpu.IFF2 = true;
this.cpu.LowerRESET();
this.cpu.Step();
Assert.IsFalse(this.cpu.IFF1, "RESET must clear IFF1");
Assert.IsFalse(this.cpu.IFF2, "RESET must clear IFF2");
}
[TestMethod]
public void Reset_Sets_IM_To_Zero()
{
this.cpu.IM = 2;
this.cpu.LowerRESET();
this.cpu.Step();
Assert.AreEqual(0, this.cpu.IM, "RESET must set interrupt mode to 0");
}
[TestMethod]
public void Reset_Clears_I_And_R_Registers()
{
this.cpu.IV = 0xAB;
this.cpu.REFRESH = 0xCD;
this.cpu.LowerRESET();
this.cpu.Step();
Assert.AreEqual(0x00, this.cpu.IV, "RESET must clear I register");
Assert.AreEqual(0x00, (byte)this.cpu.REFRESH, "RESET must clear R register");
}
[TestMethod]
public void Reset_Deasserts_Reset_Pin()
{
this.cpu.LowerRESET(); // asserts RESET — fires LoweredRESET event
Assert.IsTrue(this.cpu.RESET.Lowered(), "RESET pin must be asserted before step");
this.cpu.Step();
Assert.IsTrue(this.cpu.RESET.Raised(), "HandleRESET must deassert the RESET pin");
}
[TestMethod]
public void Reset_Has_Priority_Over_NMI()
{
// Assert both RESET and NMI simultaneously; RESET is checked first in PoweredStep
this.cpu.LowerRESET();
this.cpu.LowerNMI();
this.cpu.Step();
// RESET handler runs, sets PC=0 — NMI (0x0066) must not win
Assert.AreEqual(0x0000, this.cpu.PC.Joined, "RESET must take priority over pending NMI");
}
}
}
+43
View File
@@ -0,0 +1,43 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<EnableMSTestRunner>true</EnableMSTestRunner>
<GenerateDocumentationFile>False</GenerateDocumentationFile>
<SignAssembly>False</SignAssembly>
<OutputType>Exe</OutputType>
<TestingPlatformDotnetTestSupport>true</TestingPlatformDotnetTestSupport>
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
<AnalysisLevel>latest-all</AnalysisLevel>
<TestingPlatformShowTestsFailure>true</TestingPlatformShowTestsFailure>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<WarningLevel>9999</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<WarningLevel>9999</WarningLevel>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="Microsoft.Testing.Extensions.CodeCoverage" Version="17.12.6" />
<PackageReference Include="Microsoft.Testing.Extensions.TrxReport" Version="1.4.3" />
<PackageReference Include="MSTest" Version="3.6.4" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\EightBit\EightBit.csproj" />
<ProjectReference Include="..\Z80.csproj" />
</ItemGroup>
<ItemGroup>
<Using Include="EightBit" />
<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
</ItemGroup>
</Project>
+3
View File
@@ -22,12 +22,15 @@
<Compile Remove="Z80.FuseTest\**" />
<Compile Remove="Z80.HarteTest\**" />
<Compile Remove="Z80.Test\**" />
<Compile Remove="Z80.UnitTests\**" />
<EmbeddedResource Remove="Z80.FuseTest\**" />
<EmbeddedResource Remove="Z80.HarteTest\**" />
<EmbeddedResource Remove="Z80.Test\**" />
<EmbeddedResource Remove="Z80.UnitTests\**" />
<None Remove="Z80.FuseTest\**" />
<None Remove="Z80.HarteTest\**" />
<None Remove="Z80.Test\**" />
<None Remove="Z80.UnitTests\**" />
</ItemGroup>
<ItemGroup>