1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-10-02 19:54:35 +00:00

Introduces a first unit test for line interrupts and corrects backup behaviour.

This commit is contained in:
Thomas Harte 2018-10-09 21:49:21 -04:00
parent dccf17e770
commit c128ddb549
3 changed files with 81 additions and 4 deletions

View File

@ -560,10 +560,14 @@ uint8_t TMS9918::get_register(int address) {
}
// Figure out the number of internal cycles until the next line interrupt.
const int local_cycles_until_line_interrupt = ((mode_timing_.line_interrupt_position - column_ + 342) % 342) + (next_line_interrupt_row - row_) * 342;
int local_cycles_until_line_interrupt = ((mode_timing_.line_interrupt_position - column_ + 342) % 342) + (next_line_interrupt_row - row_) * 342;
local_cycles_until_line_interrupt <<= 2;
local_cycles_until_line_interrupt -= cycles_error_;
// Map that to input cycles by multiplying by 2/3 (and incrementing on any carry).
auto time_until_line_interrupt = HalfCycles( (local_cycles_until_line_interrupt * 6 + 7) / 4);
// Map that to input cycles by multiplying by 2/3 (and incrementing on any carry, TODO: allowing for current error).
auto time_until_line_interrupt = HalfCycles(local_cycles_until_line_interrupt / 3);
if(!generate_interrupts_) return time_until_line_interrupt;
// Return whichever interrupt is closer.
return std::min(time_until_frame_interrupt, time_until_line_interrupt);

View File

@ -315,6 +315,7 @@
4B9BE401203A0C0600FFAE60 /* MultiSpeaker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B9BE3FE203A0C0600FFAE60 /* MultiSpeaker.cpp */; };
4BA0F68E1EEA0E8400E9489E /* ZX8081.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BA0F68C1EEA0E8400E9489E /* ZX8081.cpp */; };
4BA61EB01D91515900B3C876 /* NSData+StdVector.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BA61EAF1D91515900B3C876 /* NSData+StdVector.mm */; };
4BA91E1D216D85BA00F79557 /* MasterSystemVDPTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BA91E1C216D85BA00F79557 /* MasterSystemVDPTests.mm */; };
4BAD13441FF709C700FD114A /* MSX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0E61051FF34737002A9DBD /* MSX.cpp */; };
4BAE49582032881E004BE78E /* CSZX8081.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B14978E1EE4B4D200CE2596 /* CSZX8081.mm */; };
4BAE495920328897004BE78E /* ZX8081OptionsPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B95FA9C1F11893B0008E395 /* ZX8081OptionsPanel.swift */; };
@ -1041,6 +1042,7 @@
4BA141C12073100800A31EC9 /* Target.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Target.hpp; sourceTree = "<group>"; };
4BA61EAE1D91515900B3C876 /* NSData+StdVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+StdVector.h"; sourceTree = "<group>"; };
4BA61EAF1D91515900B3C876 /* NSData+StdVector.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSData+StdVector.mm"; sourceTree = "<group>"; };
4BA91E1C216D85BA00F79557 /* MasterSystemVDPTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MasterSystemVDPTests.mm; sourceTree = "<group>"; };
4BA9C3CF1D8164A9002DDB61 /* MediaTarget.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MediaTarget.hpp; sourceTree = "<group>"; };
4BAA167B21582B1D008A3276 /* Target.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Target.hpp; sourceTree = "<group>"; };
4BAB62AC1D3272D200DF5BA0 /* Disk.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Disk.hpp; sourceTree = "<group>"; };
@ -2818,10 +2820,11 @@
4BB73EB51B587A5100552FC2 /* Clock SignalTests */ = {
isa = PBXGroup;
children = (
4B98A0601FFADCDE00ADF63B /* MSXStaticAnalyserTests.mm */,
4B5073091DDFCFDF00C48FBD /* ArrayBuilderTests.mm */,
4B924E981E74D22700B76AF1 /* AtariStaticAnalyserTests.mm */,
4BB2A9AE1E13367E001A5C23 /* CRCTests.mm */,
4BA91E1C216D85BA00F79557 /* MasterSystemVDPTests.mm */,
4B98A0601FFADCDE00ADF63B /* MSXStaticAnalyserTests.mm */,
4B121F9A1E06293F00BFDA12 /* PCMSegmentEventSourceTests.mm */,
4BD4A8CF1E077FD20020D856 /* PCMTrackTests.mm */,
4B2AF8681E513FC20027EE29 /* TIATests.mm */,
@ -4000,6 +4003,7 @@
4BB73EB71B587A5100552FC2 /* AllSuiteATests.swift in Sources */,
4B01A6881F22F0DB001FD6E3 /* Z80MemptrTests.swift in Sources */,
4B121F9B1E06293F00BFDA12 /* PCMSegmentEventSourceTests.mm in Sources */,
4BA91E1D216D85BA00F79557 /* MasterSystemVDPTests.mm in Sources */,
4B98A0611FFADCDE00ADF63B /* MSXStaticAnalyserTests.mm in Sources */,
4BEF6AAC1D35D1C400E73575 /* DPLLTests.swift in Sources */,
4B3BA0CF1D318B44005DD7A7 /* MOS6522Bridge.mm in Sources */,

View File

@ -0,0 +1,69 @@
//
// MasterSystemVDPTests.m
// Clock SignalTests
//
// Created by Thomas Harte on 09/10/2018.
// Copyright © 2018 Thomas Harte. All rights reserved.
//
#import <XCTest/XCTest.h>
#import <OpenGL/OpenGL.h>
#include "9918.hpp"
@interface MasterSystemVDPTests : XCTestCase
@end
@implementation MasterSystemVDPTests {
NSOpenGLContext *_openGLContext;
}
- (void)setUp {
[super setUp];
// Create a valid OpenGL context, so that a VDP can be constructed.
NSOpenGLPixelFormatAttribute attributes[] =
{
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
0
};
NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
_openGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil];
[_openGLContext makeCurrentContext];
}
- (void)tearDown {
// Put teardown code here. This method is called after the invocation of each test method in the class.
_openGLContext = nil;
[super tearDown];
}
- (void)testLineInterrupt {
TI::TMS::TMS9918 vdp(TI::TMS::Personality::SMSVDP);
// Disable end-of-frame interrupts, enable line interrupts.
vdp.set_register(1, 0x00);
vdp.set_register(1, 0x81);
vdp.set_register(1, 0x10);
vdp.set_register(1, 0x80);
// Set a line interrupt to occur in five lines.
vdp.set_register(1, 5);
vdp.set_register(1, 0x8a);
// Get time until interrupt.
int time_until_interrupt = vdp.get_time_until_interrupt().as_int() - 1;
// Check interrupt flag isn't set prior to the reported time.
vdp.run_for(HalfCycles(time_until_interrupt));
NSAssert(!vdp.get_interrupt_line(), @"Interrupt line went active early");
// Check interrupt flag is set at the reported time.
vdp.run_for(HalfCycles(1));
NSAssert(vdp.get_interrupt_line(), @"Interrupt line wasn't set when promised");
}
@end