138 lines
3.8 KiB
C#
138 lines
3.8 KiB
C#
using Xunit;
|
|
|
|
namespace GameBoy.Tests
|
|
{
|
|
public sealed class Mbc3RtcTests
|
|
{
|
|
private const byte Mbc3TimerRamBattery = 0x10;
|
|
|
|
private static Emulator NewTimerCartridge()
|
|
{
|
|
return new Emulator(TestRoms.BuildCartridge(Mbc3TimerRamBattery, 0x03));
|
|
}
|
|
|
|
private static void EnableRtc(Emulator emulator)
|
|
{
|
|
emulator.WriteMemory(0x0000, 0x0A);
|
|
}
|
|
|
|
private static void SelectRtcRegister(Emulator emulator, byte register)
|
|
{
|
|
emulator.WriteMemory(0x4000, register);
|
|
}
|
|
|
|
private static void Latch(Emulator emulator)
|
|
{
|
|
emulator.WriteMemory(0x6000, 0x00);
|
|
emulator.WriteMemory(0x6000, 0x01);
|
|
}
|
|
|
|
private static byte ReadLatched(Emulator emulator, byte register)
|
|
{
|
|
SelectRtcRegister(emulator, register);
|
|
return emulator.ReadMemory(0xA000);
|
|
}
|
|
|
|
private static void WriteRtc(Emulator emulator, byte register, byte value)
|
|
{
|
|
SelectRtcRegister(emulator, register);
|
|
emulator.WriteMemory(0xA000, value);
|
|
}
|
|
|
|
[Fact]
|
|
public void CartridgeReportsRtcAndBattery()
|
|
{
|
|
var emulator = NewTimerCartridge();
|
|
Assert.True(emulator.HasRtc);
|
|
Assert.True(emulator.HasBattery);
|
|
}
|
|
|
|
[Fact]
|
|
public void SecondsRollIntoMinutes()
|
|
{
|
|
var emulator = NewTimerCartridge();
|
|
EnableRtc(emulator);
|
|
|
|
WriteRtc(emulator, 0x08, 58);
|
|
WriteRtc(emulator, 0x09, 0);
|
|
|
|
emulator.AdvanceRtcSeconds(5);
|
|
Latch(emulator);
|
|
|
|
Assert.Equal(3, ReadLatched(emulator, 0x08));
|
|
Assert.Equal(1, ReadLatched(emulator, 0x09));
|
|
}
|
|
|
|
[Fact]
|
|
public void LatchFreezesTheReadableTime()
|
|
{
|
|
var emulator = NewTimerCartridge();
|
|
EnableRtc(emulator);
|
|
|
|
WriteRtc(emulator, 0x08, 10);
|
|
Latch(emulator);
|
|
Assert.Equal(10, ReadLatched(emulator, 0x08));
|
|
|
|
emulator.AdvanceRtcSeconds(20);
|
|
Assert.Equal(10, ReadLatched(emulator, 0x08));
|
|
|
|
Latch(emulator);
|
|
Assert.Equal(30, ReadLatched(emulator, 0x08));
|
|
}
|
|
|
|
[Fact]
|
|
public void HaltStopsTheClock()
|
|
{
|
|
var emulator = NewTimerCartridge();
|
|
EnableRtc(emulator);
|
|
|
|
WriteRtc(emulator, 0x08, 0);
|
|
WriteRtc(emulator, 0x0C, 0x40);
|
|
|
|
emulator.AdvanceRtcSeconds(30);
|
|
Latch(emulator);
|
|
Assert.Equal(0, ReadLatched(emulator, 0x08));
|
|
|
|
WriteRtc(emulator, 0x0C, 0x00);
|
|
emulator.AdvanceRtcSeconds(30);
|
|
Latch(emulator);
|
|
Assert.Equal(30, ReadLatched(emulator, 0x08));
|
|
}
|
|
|
|
[Fact]
|
|
public void DayCounterOverflowSetsCarry()
|
|
{
|
|
var emulator = NewTimerCartridge();
|
|
EnableRtc(emulator);
|
|
|
|
WriteRtc(emulator, 0x08, 0);
|
|
WriteRtc(emulator, 0x09, 0);
|
|
WriteRtc(emulator, 0x0A, 0);
|
|
WriteRtc(emulator, 0x0B, 0xFF);
|
|
WriteRtc(emulator, 0x0C, 0x01);
|
|
|
|
emulator.AdvanceRtcSeconds(86400);
|
|
Latch(emulator);
|
|
|
|
Assert.Equal(0x00, ReadLatched(emulator, 0x0B));
|
|
byte dayHigh = ReadLatched(emulator, 0x0C);
|
|
Assert.Equal(0x00, dayHigh & 0x01);
|
|
Assert.Equal(0x80, dayHigh & 0x80);
|
|
}
|
|
|
|
[Fact]
|
|
public void ClockAdvancesFromEmulatedCycles()
|
|
{
|
|
var emulator = NewTimerCartridge();
|
|
EnableRtc(emulator);
|
|
WriteRtc(emulator, 0x08, 0);
|
|
|
|
for (long i = 0; i < 4194304 / 4 * 3; i++)
|
|
emulator.Tick4();
|
|
|
|
Latch(emulator);
|
|
Assert.Equal(3, ReadLatched(emulator, 0x08));
|
|
}
|
|
}
|
|
}
|