diff --git a/tests/Chip8.Tests/XoChipTests.cs b/tests/Chip8.Tests/XoChipTests.cs new file mode 100644 index 0000000..2cbd7d9 --- /dev/null +++ b/tests/Chip8.Tests/XoChipTests.cs @@ -0,0 +1,170 @@ +using System; +using Chip8.Core; +using Xunit; + +namespace Chip8.Tests; + +public class XoChipTests +{ + [Fact] + public void planeSelectStoresMask() + { + var machine = TestHarness.withOpcode(0xF201, Platform.XoChip); + machine.step(); + Assert.Equal(2, machine.planeMask); + } + + [Fact] + public void drawToSecondPlaneProducesColorTwo() + { + var machine = TestHarness.withProgram(Platform.XoChip, 0xF201, 0xD011); + machine.i = 0x300; + machine.memory[0x300] = 0x80; + machine.step(); + machine.step(); + Assert.Equal(2, machine.video.colorAt(0, 0)); + } + + [Fact] + public void drawToBothPlanesProducesColorThree() + { + var machine = TestHarness.withProgram(Platform.XoChip, 0xF301, 0xD011); + machine.i = 0x300; + machine.memory[0x300] = 0x80; + machine.memory[0x301] = 0x80; + machine.step(); + machine.step(); + Assert.Equal(3, machine.video.colorAt(0, 0)); + Assert.Equal(0, machine.video.colorAt(1, 0)); + } + + [Fact] + public void clearAffectsOnlySelectedPlane() + { + var machine = TestHarness.withProgram(Platform.XoChip, 0xF301, 0xD011, 0xF101, 0x00E0); + machine.i = 0x300; + machine.memory[0x300] = 0x80; + machine.memory[0x301] = 0x80; + machine.step(); + machine.step(); + machine.step(); + machine.step(); + Assert.Equal(2, machine.video.colorAt(0, 0)); + } + + [Fact] + public void longLoadSetsIndexToSixteenBitAddress() + { + var machine = TestHarness.withProgram(Platform.XoChip, 0xF000, 0x1234); + machine.step(); + Assert.Equal(0x1234, machine.i); + Assert.Equal(0x204, machine.pc); + } + + [Fact] + public void takenSkipJumpsOverLongLoad() + { + var machine = TestHarness.withProgram(Platform.XoChip, 0x3000, 0xF000, 0x1234, 0x00E0); + machine.step(); + Assert.Equal(0x206, machine.pc); + } + + [Fact] + public void takenSkipOverNormalInstructionAdvancesTwo() + { + var machine = TestHarness.withProgram(Platform.XoChip, 0x3000, 0x6042); + machine.step(); + Assert.Equal(0x204, machine.pc); + } + + [Fact] + public void storeAndLoadRegisterRange() + { + var machine = TestHarness.withProgram(Platform.XoChip, 0x5132, 0x5463); + machine.i = 0x400; + machine.v[1] = 0xAA; + machine.v[2] = 0xBB; + machine.v[3] = 0xCC; + + machine.step(); + Assert.Equal(0xAA, machine.memory[0x400]); + Assert.Equal(0xBB, machine.memory[0x401]); + Assert.Equal(0xCC, machine.memory[0x402]); + Assert.Equal(0x400, machine.i); + + machine.step(); + Assert.Equal(0xAA, machine.v[4]); + Assert.Equal(0xBB, machine.v[5]); + Assert.Equal(0xCC, machine.v[6]); + } + + [Fact] + public void storeRangeInReverseOrder() + { + var machine = TestHarness.withProgram(Platform.XoChip, 0x5312); + machine.i = 0x400; + machine.v[1] = 0x11; + machine.v[2] = 0x22; + machine.v[3] = 0x33; + + machine.step(); + + Assert.Equal(0x33, machine.memory[0x400]); + Assert.Equal(0x22, machine.memory[0x401]); + Assert.Equal(0x11, machine.memory[0x402]); + } + + [Fact] + public void audioPatternBufferLoadsFromMemory() + { + var machine = TestHarness.withProgram(Platform.XoChip, 0xF002); + machine.i = 0x400; + for (int offset = 0; offset < 16; offset++) + { + machine.memory[0x400 + offset] = (byte)offset; + } + + machine.step(); + + Assert.Equal(0, machine.audioPattern[0]); + Assert.Equal(15, machine.audioPattern[15]); + } + + [Fact] + public void pitchSetsPlaybackFrequency() + { + var machine = TestHarness.withOpcode(0xF03A, Platform.XoChip); + machine.v[0] = 112; + machine.step(); + Assert.Equal(112, machine.audioPitch); + Assert.True(Math.Abs(machine.audioFrequency - 8000.0) < 0.001); + } + + [Fact] + public void extendedMemoryIsSixtyFourKilobytes() + { + var machine = new Machine(null, 1, Platform.XoChip); + Assert.Equal(65536, machine.memory.Length); + + var rom = new byte[5000]; + rom[0] = 0xAB; + rom[4999] = 0xCD; + machine.loadRom(rom); + Assert.Equal(0xAB, machine.memory[0x200]); + Assert.Equal(0xCD, machine.memory[0x200 + 4999]); + } + + [Fact] + public void scrollUpOpcodeMovesContent() + { + var machine = TestHarness.withProgram(Platform.XoChip, 0x00D4); + machine.memory[0x300] = 0x80; + machine.video.drawSprite(machine.memory, 0x300, 5, 10, 1, 1, false); + Assert.True(machine.video.pixel(0, 5, 10)); + + machine.step(); + + Assert.False(machine.video.pixel(0, 5, 10)); + Assert.True(machine.video.pixel(0, 5, 6)); + } +}