1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 23:52:26 +00:00

Merge pull request #49 from TomHarte/Xcode8

Migrated to Swift 3.
This commit is contained in:
Thomas Harte 2016-09-17 18:10:43 -04:00 committed by GitHub
commit 788df09f71
16 changed files with 243 additions and 241 deletions

View File

@ -1708,11 +1708,12 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 0700;
LastUpgradeCheck = 0800;
ORGANIZATIONNAME = "Thomas Harte";
TargetAttributes = {
4BB73E9D1B587A5100552FC2 = {
CreatedOnToolsVersion = 7.0;
LastSwiftMigration = 0800;
SystemCapabilities = {
com.apple.Sandbox = {
enabled = 1;
@ -1721,10 +1722,12 @@
};
4BB73EB11B587A5100552FC2 = {
CreatedOnToolsVersion = 7.0;
LastSwiftMigration = 0800;
TestTargetID = 4BB73E9D1B587A5100552FC2;
};
4BB73EBC1B587A5100552FC2 = {
CreatedOnToolsVersion = 7.0;
LastSwiftMigration = 0800;
TestTargetID = 4BB73E9D1B587A5100552FC2;
};
};
@ -2207,8 +2210,10 @@
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
@ -2251,8 +2256,10 @@
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
@ -2271,6 +2278,7 @@
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
};
name = Release;
};
@ -2289,6 +2297,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Clock Signal/ClockSignal-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
@ -2306,6 +2315,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "TH.Clock-Signal";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Clock Signal/ClockSignal-Bridging-Header.h";
SWIFT_VERSION = 3.0;
};
name = Release;
};
@ -2321,6 +2331,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Clock SignalTests/Bridges/Clock SignalTests-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Clock Signal.app/Contents/MacOS/Clock Signal";
};
name = Debug;
@ -2336,6 +2347,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "TH.Clock-SignalTests";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Clock SignalTests/Bridges/Clock SignalTests-Bridging-Header.h";
SWIFT_VERSION = 3.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Clock Signal.app/Contents/MacOS/Clock Signal";
};
name = Release;
@ -2348,6 +2360,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "TH.Clock-SignalUITests";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
TEST_TARGET_NAME = "Clock Signal";
USES_XCTRUNNER = YES;
};
@ -2361,6 +2374,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "TH.Clock-SignalUITests";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
TEST_TARGET_NAME = "Clock Signal";
USES_XCTRUNNER = YES;
};

View File

@ -11,16 +11,16 @@ import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(aNotification: NSNotification) {
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
}
func applicationWillTerminate(aNotification: NSNotification) {
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
// decline to open a new file unless the user explicitly requests it
func applicationShouldOpenUntitledFile(sender: NSApplication) -> Bool {
func applicationShouldOpenUntitledFile(_ sender: NSApplication) -> Bool {
return false
}
}

View File

@ -9,18 +9,18 @@
import Cocoa
class DocumentController: NSDocumentController {
override func makeDocumentWithContentsOfURL(url: NSURL, ofType typeName: String) throws -> NSDocument {
if let analyser = CSStaticAnalyser(fileAtURL: url) {
override func makeDocument(withContentsOf url: URL, ofType typeName: String) throws -> NSDocument {
if let analyser = CSStaticAnalyser(fileAt: url) {
if let documentClass = analyser.documentClass as? NSDocument.Type {
let document = documentClass.init()
if let machineDocument = document as? MachineDocument {
machineDocument.setDisplayName(analyser.displayName)
machineDocument.displayName = analyser.displayName
machineDocument.configureAs(analyser)
return machineDocument
}
}
}
return try! super.makeDocumentWithContentsOfURL(url, ofType: typeName)
return try! super.makeDocument(withContentsOf: url, ofType: typeName)
}
}

View File

@ -10,7 +10,7 @@ import Cocoa
class Atari2600Document: MachineDocument {
private var atari2600 = CSAtari2600()
fileprivate var atari2600 = CSAtari2600()
override var machine: CSMachine! {
get {
return atari2600
@ -31,7 +31,7 @@ class Atari2600Document: MachineDocument {
return "Atari2600Document"
}
override func windowControllerDidLoadNib(aController: NSWindowController) {
override func windowControllerDidLoadNib(_ aController: NSWindowController) {
super.windowControllerDidLoadNib(aController)
// push whatever settings the switches have in the NIB into the emulation
@ -39,26 +39,28 @@ class Atari2600Document: MachineDocument {
// show the options window but ensure the OpenGL view is key
showOptions(self)
self.openGLView.window?.makeKeyWindow()
self.openGLView.window?.makeKey()
}
// MARK: CSOpenGLViewResponderDelegate
private func inputForKey(event: NSEvent) -> Atari2600DigitalInput? {
fileprivate func inputForKey(_ event: NSEvent) -> Atari2600DigitalInput? {
switch event.keyCode {
case 123: return Atari2600DigitalInputJoy1Left
case 126: return Atari2600DigitalInputJoy1Up
case 124: return Atari2600DigitalInputJoy1Right
case 125: return Atari2600DigitalInputJoy1Down
case 0: return Atari2600DigitalInputJoy1Fire
default: print("\(event.keyCode)"); return nil
default:
Swift.print("\(event.keyCode)")
return nil
}
}
override func keyDown(event: NSEvent) {
override func keyDown(_ event: NSEvent) {
super.keyDown(event)
if let input = inputForKey(event) {
atari2600.setState(true, forDigitalInput: input)
atari2600.setState(true, for: input)
}
if event.keyCode == 36 {
@ -66,11 +68,11 @@ class Atari2600Document: MachineDocument {
}
}
override func keyUp(event: NSEvent) {
override func keyUp(_ event: NSEvent) {
super.keyUp(event)
if let input = inputForKey(event) {
atari2600.setState(false, forDigitalInput: input)
atari2600.setState(false, for: input)
}
if event.keyCode == 36 {
@ -85,21 +87,21 @@ class Atari2600Document: MachineDocument {
@IBOutlet var leftPlayerDifficultyButton: NSButton!
@IBOutlet var rightPlayerDifficultyButton: NSButton!
@IBAction func optionDidChange(sender: AnyObject!) {
@IBAction func optionDidChange(_ sender: AnyObject!) {
pushSwitchValues()
}
private func pushSwitchValues() {
fileprivate func pushSwitchValues() {
atari2600.colourButton = colourButton.state == NSOnState
atari2600.leftPlayerDifficultyButton = leftPlayerDifficultyButton.state == NSOnState
atari2600.rightPlayerDifficultyButton = rightPlayerDifficultyButton.state == NSOnState
}
@IBAction func optionWasPressed(sender: NSButton!) {
@IBAction func optionWasPressed(_ sender: NSButton!) {
if sender == resetButton {
atari2600.pressResetButton()
} else {
atari2600.pressSelectButton()
}
}
}
}

View File

@ -11,7 +11,7 @@ import AudioToolbox
class ElectronDocument: MachineDocument {
private lazy var electron = CSElectron()
fileprivate lazy var electron = CSElectron()
override var machine: CSMachine! {
get {
return electron
@ -27,14 +27,14 @@ class ElectronDocument: MachineDocument {
return NSSize(width: 11.0, height: 10.0)
}
private func rom(name: String) -> NSData? {
fileprivate func rom(_ name: String) -> Data? {
return dataForResource(name, ofType: "rom", inDirectory: "ROMImages/Electron")
}
override func windowControllerDidLoadNib(aController: NSWindowController) {
override func windowControllerDidLoadNib(_ aController: NSWindowController) {
super.windowControllerDidLoadNib(aController)
if let os = rom("os"), basic = rom("basic") {
if let os = rom("os"), let basic = rom("basic") {
self.electron.setOSROM(os)
self.electron.setBASICROM(basic)
}
@ -67,21 +67,21 @@ class ElectronDocument: MachineDocument {
// MARK: IBActions
@IBOutlet var displayTypeButton: NSPopUpButton?
@IBAction func setDisplayType(sender: NSPopUpButton!) {
@IBAction func setDisplayType(_ sender: NSPopUpButton!) {
electron.useTelevisionOutput = (sender.indexOfSelectedItem == 1)
NSUserDefaults.standardUserDefaults().setInteger(sender.indexOfSelectedItem, forKey: self.displayTypeUserDefaultsKey)
UserDefaults.standard.set(sender.indexOfSelectedItem, forKey: self.displayTypeUserDefaultsKey)
}
private let displayTypeUserDefaultsKey = "electron.displayType"
fileprivate let displayTypeUserDefaultsKey = "electron.displayType"
override func establishStoredOptions() {
super.establishStoredOptions()
let standardUserDefaults = NSUserDefaults.standardUserDefaults()
standardUserDefaults.registerDefaults([
let standardUserDefaults = UserDefaults.standard
standardUserDefaults.register(defaults: [
displayTypeUserDefaultsKey: 0,
])
let displayType = standardUserDefaults.integerForKey(self.displayTypeUserDefaultsKey)
let displayType = standardUserDefaults.integer(forKey: self.displayTypeUserDefaultsKey)
electron.useTelevisionOutput = (displayType == 1)
self.displayTypeButton?.selectItemAtIndex(displayType)
self.displayTypeButton?.selectItem(at: displayType)
}
}

View File

@ -43,24 +43,24 @@ class MachineDocument:
}
@IBOutlet weak var optionsPanel: NSPanel!
@IBAction func showOptions(sender: AnyObject!) {
@IBAction func showOptions(_ sender: AnyObject!) {
optionsPanel?.setIsVisible(true)
}
private var audioQueue: CSAudioQueue! = nil
private lazy var bestEffortUpdater: CSBestEffortUpdater = {
fileprivate var audioQueue: CSAudioQueue! = nil
fileprivate lazy var bestEffortUpdater: CSBestEffortUpdater = {
let updater = CSBestEffortUpdater()
updater.delegate = self
return updater
}()
override func windowControllerDidLoadNib(aController: NSWindowController) {
override func windowControllerDidLoadNib(_ aController: NSWindowController) {
super.windowControllerDidLoadNib(aController)
// establish the output aspect ratio and audio
let displayAspectRatio = self.aspectRatio()
aController.window?.contentAspectRatio = displayAspectRatio
openGLView.performWithGLContext({
openGLView.perform(glContext: {
self.machine.setView(self.openGLView, aspectRatio: Float(displayAspectRatio.width / displayAspectRatio.height))
})
@ -69,18 +69,18 @@ class MachineDocument:
establishStoredOptions()
}
func machineDidChangeClockRate(machine: CSMachine!) {
func machineDidChangeClockRate(_ machine: CSMachine!) {
setupClockRate()
}
func machineDidChangeClockIsUnlimited(machine: CSMachine!) {
func machineDidChangeClockIsUnlimited(_ machine: CSMachine!) {
self.bestEffortUpdater.runAsUnlimited = machine.clockIsUnlimited
}
private func setupClockRate() {
fileprivate func setupClockRate() {
// establish and provide the audio queue, taking advice as to an appropriate sampling rate
let maximumSamplingRate = CSAudioQueue.preferredSamplingRate()
let selectedSamplingRate = self.machine.idealSamplingRateFromRange(NSRange(location: 0, length: NSInteger(maximumSamplingRate)))
let selectedSamplingRate = self.machine.idealSamplingRate(from: NSRange(location: 0, length: NSInteger(maximumSamplingRate)))
if selectedSamplingRate > 0 {
audioQueue = CSAudioQueue(samplingRate: Float64(selectedSamplingRate))
audioQueue.delegate = self
@ -103,89 +103,89 @@ class MachineDocument:
}
// MARK: configuring
func configureAs(analysis: CSStaticAnalyser) {
analysis.applyToMachine(self.machine)
func configureAs(_ analysis: CSStaticAnalyser) {
analysis.apply(to: self.machine)
}
// MARK: the pasteboard
func paste(sender: AnyObject!) {
let pasteboard = NSPasteboard.generalPasteboard()
if let string = pasteboard.stringForType(NSPasteboardTypeString) {
func paste(_ sender: AnyObject!) {
let pasteboard = NSPasteboard.general()
if let string = pasteboard.string(forType: NSPasteboardTypeString) {
self.machine.paste(string)
}
}
// MARK: CSBestEffortUpdaterDelegate
final func bestEffortUpdater(bestEffortUpdater: CSBestEffortUpdater!, runForCycles cycles: UInt, didSkipPreviousUpdate: Bool) {
final func bestEffortUpdater(_ bestEffortUpdater: CSBestEffortUpdater!, runForCycles cycles: UInt, didSkipPreviousUpdate: Bool) {
runForNumberOfCycles(Int32(cycles))
}
func runForNumberOfCycles(numberOfCycles: Int32) {
func runForNumberOfCycles(_ numberOfCycles: Int32) {
let cyclesToRunFor = min(numberOfCycles, Int32(bestEffortUpdater.clockRate / 10))
if actionLock.tryLock() {
self.machine.runForNumberOfCycles(cyclesToRunFor)
if actionLock.try() {
self.machine.runForNumber(ofCycles: cyclesToRunFor)
actionLock.unlock()
}
}
// MARK: Utilities for children
func dataForResource(name : String, ofType type: String, inDirectory directory: String) -> NSData? {
if let path = NSBundle.mainBundle().pathForResource(name, ofType: type, inDirectory: directory) {
return NSData(contentsOfFile: path)
func dataForResource(_ name : String, ofType type: String, inDirectory directory: String) -> Data? {
if let path = Bundle.main.path(forResource: name, ofType: type, inDirectory: directory) {
return (try? Data(contentsOf: URL(fileURLWithPath: path)))
}
return nil
}
// MARK: CSAudioQueueDelegate
final func audioQueueDidCompleteBuffer(audioQueue: CSAudioQueue) {
final func audioQueueDidCompleteBuffer(_ audioQueue: CSAudioQueue) {
bestEffortUpdater.update()
}
// MARK: CSOpenGLViewDelegate
final func openGLView(view: CSOpenGLView, drawViewOnlyIfDirty onlyIfDirty: Bool) {
final func openGLView(_ view: CSOpenGLView, drawViewOnlyIfDirty onlyIfDirty: Bool) {
bestEffortUpdater.update()
if drawLock.tryLock() {
self.machine.drawViewForPixelSize(view.backingSize, onlyIfDirty: onlyIfDirty)
if drawLock.try() {
self.machine.drawView(forPixelSize: view.backingSize, onlyIfDirty: onlyIfDirty)
drawLock.unlock()
}
}
// MARK: NSDocument overrides
override func dataOfType(typeName: String) throws -> NSData {
override func data(ofType typeName: String) throws -> Data {
throw NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil)
}
// MARK: Key forwarding
private func withKeyboardMachine(action: (CSKeyboardMachine) -> ()) {
fileprivate func withKeyboardMachine(_ action: (CSKeyboardMachine) -> ()) {
if let keyboardMachine = self.machine as? CSKeyboardMachine {
action(keyboardMachine)
}
}
func windowDidResignKey(notification: NSNotification) {
func windowDidResignKey(_ notification: Notification) {
self.withKeyboardMachine { $0.clearAllKeys() }
}
func keyDown(event: NSEvent) {
func keyDown(_ event: NSEvent) {
self.withKeyboardMachine { $0.setKey(event.keyCode, isPressed: true) }
}
func keyUp(event: NSEvent) {
func keyUp(_ event: NSEvent) {
self.withKeyboardMachine { $0.setKey(event.keyCode, isPressed: false) }
}
func flagsChanged(newModifiers: NSEvent) {
func flagsChanged(_ newModifiers: NSEvent) {
self.withKeyboardMachine {
$0.setKey(VK_Shift, isPressed: newModifiers.modifierFlags.contains(.ShiftKeyMask))
$0.setKey(VK_Control, isPressed: newModifiers.modifierFlags.contains(.ControlKeyMask))
$0.setKey(VK_Command, isPressed: newModifiers.modifierFlags.contains(.CommandKeyMask))
$0.setKey(VK_Option, isPressed: newModifiers.modifierFlags.contains(.AlternateKeyMask))
$0.setKey(VK_Shift, isPressed: newModifiers.modifierFlags.contains(.shift))
$0.setKey(VK_Control, isPressed: newModifiers.modifierFlags.contains(.control))
$0.setKey(VK_Command, isPressed: newModifiers.modifierFlags.contains(.command))
$0.setKey(VK_Option, isPressed: newModifiers.modifierFlags.contains(.option))
}
}
// MARK: IBActions
final func prefixedUserDefaultsKey(key: String) -> String {
final func prefixedUserDefaultsKey(_ key: String) -> String {
return "\(self.name).\(key)"
}
var fastLoadingUserDefaultsKey: String {
@ -195,22 +195,22 @@ class MachineDocument:
}
@IBOutlet var fastLoadingButton: NSButton?
@IBAction func setFastLoading(sender: NSButton!) {
@IBAction func setFastLoading(_ sender: NSButton!) {
if let fastLoadingMachine = machine as? CSFastLoading {
let useFastLoadingHack = sender.state == NSOnState
fastLoadingMachine.useFastLoadingHack = useFastLoadingHack
NSUserDefaults.standardUserDefaults().setBool(useFastLoadingHack, forKey: fastLoadingUserDefaultsKey)
UserDefaults.standard.set(useFastLoadingHack, forKey: fastLoadingUserDefaultsKey)
}
}
func establishStoredOptions() {
let standardUserDefaults = NSUserDefaults.standardUserDefaults()
standardUserDefaults.registerDefaults([
let standardUserDefaults = UserDefaults.standard
standardUserDefaults.register(defaults: [
fastLoadingUserDefaultsKey: true
])
if let fastLoadingMachine = machine as? CSFastLoading {
let useFastLoadingHack = standardUserDefaults.boolForKey(self.fastLoadingUserDefaultsKey)
let useFastLoadingHack = standardUserDefaults.bool(forKey: self.fastLoadingUserDefaultsKey)
fastLoadingMachine.useFastLoadingHack = useFastLoadingHack
self.fastLoadingButton?.state = useFastLoadingHack ? NSOnState : NSOffState
}

View File

@ -10,7 +10,7 @@ import Foundation
class Vic20Document: MachineDocument {
private lazy var vic20 = CSVic20()
fileprivate lazy var vic20 = CSVic20()
override var machine: CSMachine! {
get {
return vic20
@ -41,22 +41,8 @@ class Vic20Document: MachineDocument {
return "Vic20Document"
}
override func readFromURL(url: NSURL, ofType typeName: String) throws {
if let pathExtension = url.pathExtension {
switch pathExtension.lowercaseString {
case "tap": vic20.openTAPAtURL(url)
case "g64": vic20.openG64AtURL(url)
case "d64": vic20.openD64AtURL(url)
case "prg": vic20.openPRGAtURL(url)
default:
let fileWrapper = try NSFileWrapper(URL: url, options: NSFileWrapperReadingOptions(rawValue: 0))
try self.readFromFileWrapper(fileWrapper, ofType: typeName)
}
}
}
// MARK: machine setup
private func rom(name: String) -> NSData? {
fileprivate func rom(_ name: String) -> Data? {
return dataForResource(name, ofType: "bin", inDirectory: "ROMImages/Vic20")
}
@ -66,10 +52,10 @@ class Vic20Document: MachineDocument {
get { return prefixedUserDefaultsKey("autoload") }
}
@IBAction func setShouldLoadAutomatically(sender: NSButton!) {
@IBAction func setShouldLoadAutomatically(_ sender: NSButton!) {
let loadAutomatically = sender.state == NSOnState
vic20.shouldLoadAutomatically = loadAutomatically
NSUserDefaults.standardUserDefaults().setBool(loadAutomatically, forKey: self.autoloadingUserDefaultsKey)
UserDefaults.standard.set(loadAutomatically, forKey: self.autoloadingUserDefaultsKey)
}
// MARK: country selector
@ -78,12 +64,12 @@ class Vic20Document: MachineDocument {
get { return prefixedUserDefaultsKey("country") }
}
@IBAction func setCountry(sender: NSPopUpButton!) {
NSUserDefaults.standardUserDefaults().setInteger(sender.indexOfSelectedItem, forKey: self.countryUserDefaultsKey)
@IBAction func setCountry(_ sender: NSPopUpButton!) {
UserDefaults.standard.set(sender.indexOfSelectedItem, forKey: self.countryUserDefaultsKey)
setCountry(sender.indexOfSelectedItem)
}
private func setCountry(countryID: Int) {
fileprivate func setCountry(_ countryID: Int) {
var charactersROM: String?
var kernelROM: String?
switch countryID {
@ -110,8 +96,8 @@ class Vic20Document: MachineDocument {
default: break
}
if let charactersROM = charactersROM, kernelROM = kernelROM {
if let kernel = rom(kernelROM), basic = rom("basic"), characters = rom(charactersROM) {
if let charactersROM = charactersROM, let kernelROM = kernelROM {
if let kernel = rom(kernelROM), let basic = rom("basic"), let characters = rom(charactersROM) {
vic20.setKernelROM(kernel)
vic20.setBASICROM(basic)
vic20.setCharactersROM(characters)
@ -125,7 +111,7 @@ class Vic20Document: MachineDocument {
get { return prefixedUserDefaultsKey("memorySize") }
}
@IBAction func setMemorySize(sender: NSPopUpButton!) {
@IBAction func setMemorySize(_ sender: NSPopUpButton!) {
var selectedSize: Int?
switch sender.indexOfSelectedItem {
case 0: selectedSize = 5
@ -134,15 +120,15 @@ class Vic20Document: MachineDocument {
default: break
}
if let selectedSize = selectedSize {
NSUserDefaults.standardUserDefaults().setInteger(selectedSize, forKey: self.memorySizeUserDefaultsKey)
UserDefaults.standard.set(selectedSize, forKey: self.memorySizeUserDefaultsKey)
setMemorySize(sender.indexOfSelectedItem)
}
}
private func setMemorySize(sizeIndex: Int) {
fileprivate func setMemorySize(_ sizeIndex: Int) {
switch sizeIndex {
case 2: vic20.memorySize = .Size32Kb
case 1: vic20.memorySize = .Size8Kb
default: vic20.memorySize = .Size5Kb
case 2: vic20.memorySize = .size32Kb
case 1: vic20.memorySize = .size8Kb
default: vic20.memorySize = .size5Kb
}
}
@ -150,19 +136,19 @@ class Vic20Document: MachineDocument {
override func establishStoredOptions() {
super.establishStoredOptions()
let standardUserDefaults = NSUserDefaults.standardUserDefaults()
standardUserDefaults.registerDefaults([
let standardUserDefaults = UserDefaults.standard
standardUserDefaults.register(defaults: [
self.autoloadingUserDefaultsKey: true,
self.memorySizeUserDefaultsKey: 5,
self.countryUserDefaultsKey: 1
])
let loadAutomatically = standardUserDefaults.boolForKey(self.autoloadingUserDefaultsKey)
let loadAutomatically = standardUserDefaults.bool(forKey: self.autoloadingUserDefaultsKey)
vic20.shouldLoadAutomatically = loadAutomatically
self.loadAutomaticallyButton?.state = loadAutomatically ? NSOnState : NSOffState
if !loadAutomatically {
let memorySize = standardUserDefaults.integerForKey(self.memorySizeUserDefaultsKey)
let memorySize = standardUserDefaults.integer(forKey: self.memorySizeUserDefaultsKey)
var indexToSelect: Int?
switch memorySize {
case 32: indexToSelect = 2
@ -170,14 +156,14 @@ class Vic20Document: MachineDocument {
default: indexToSelect = 0
}
if let indexToSelect = indexToSelect {
self.memorySizeButton?.selectItemAtIndex(indexToSelect)
self.memorySizeButton?.selectItem(at: indexToSelect)
setMemorySize(indexToSelect)
}
}
// TODO: this should be part of the configuration
let country = standardUserDefaults.integerForKey(self.countryUserDefaultsKey)
let country = standardUserDefaults.integer(forKey: self.countryUserDefaultsKey)
setCountry(country)
self.countryButton?.selectItemAtIndex(country)
self.countryButton?.selectItem(at: country)
}
}

View File

@ -28,31 +28,31 @@ class MOS6502InterruptTests: XCTestCase {
machine.setValue(0x58, forAddress: 0x4000)
// pick things off at 0x4000
machine.setValue(0x4000, forRegister: CSTestMachineRegister.ProgramCounter)
machine.setValue(0x4000, for: CSTestMachineRegister.programCounter)
}
func testIRQLine() {
// run for six cycles; check that no interrupt has occurred
machine.runForNumberOfCycles(6)
XCTAssert(machine.valueForRegister(.ProgramCounter) == 0x4003, "No interrupt should have occurred with line low")
machine.runForNumber(ofCycles: 6)
XCTAssert(machine.value(for: .programCounter) == 0x4003, "No interrupt should have occurred with line low")
// enable the interrupt line, check that it was too late
machine.irqLine = true
machine.runForNumberOfCycles(2)
XCTAssert(machine.valueForRegister(.ProgramCounter) == 0x4004, "No interrupt should have occurred from interrupt raised between instructions")
machine.runForNumber(ofCycles: 2)
XCTAssert(machine.value(for: .programCounter) == 0x4004, "No interrupt should have occurred from interrupt raised between instructions")
// run for a further 7 cycles, confirm that the IRQ vector was jumped to
machine.runForNumberOfCycles(7)
XCTAssert(machine.valueForRegister(.ProgramCounter) == 0x1234, "Interrupt routine should just have begun")
machine.runForNumber(ofCycles: 7)
XCTAssert(machine.value(for: .programCounter) == 0x1234, "Interrupt routine should just have begun")
}
func testIFlagSet() {
// enable the interrupt line, run for eleven cycles to get past the CLIP and the following NOP and into the interrupt routine
machine.irqLine = true
machine.runForNumberOfCycles(11)
machine.runForNumber(ofCycles: 11)
XCTAssert(machine.valueForRegister(.ProgramCounter) == 0x1234, "Interrupt routine should just have begun")
XCTAssert(machine.valueForRegister(.Flags) & 0x04 == 0x04, "Interrupt status flag should be set")
XCTAssert(machine.value(for: .programCounter) == 0x1234, "Interrupt routine should just have begun")
XCTAssert(machine.value(for: .flags) & 0x04 == 0x04, "Interrupt status flag should be set")
}
func testCLISEIFlagClear() {
@ -61,13 +61,13 @@ class MOS6502InterruptTests: XCTestCase {
machine.irqLine = true
// run for four cycles; the CLI and SEI should have been performed
machine.runForNumberOfCycles(4)
XCTAssert(machine.valueForRegister(.ProgramCounter) == 0x4002, "CLI/SEI pair should have been performed in their entirety")
machine.runForNumber(ofCycles: 4)
XCTAssert(machine.value(for: .programCounter) == 0x4002, "CLI/SEI pair should have been performed in their entirety")
// run for seven more cycles
machine.runForNumberOfCycles(7)
machine.runForNumber(ofCycles: 7)
// interrupt should have taken place despite SEI
XCTAssert(machine.valueForRegister(.ProgramCounter) == 0x1234, "Interrupt routine should just have begun")
XCTAssert(machine.value(for: .programCounter) == 0x1234, "Interrupt routine should just have begun")
}
}

View File

@ -11,7 +11,7 @@ import XCTest
class MOS6502TimingTests: XCTestCase, CSTestMachineJamHandler {
private var endTime: UInt32 = 0
fileprivate var endTime: UInt32 = 0
func testImplied() {
let code: [UInt8] = [
@ -195,12 +195,12 @@ class MOS6502TimingTests: XCTestCase, CSTestMachineJamHandler {
self.runTest(code, expectedRunLength: 43)
}
func runTest(code: [UInt8], expectedRunLength: UInt32) {
func runTest(_ code: [UInt8], expectedRunLength: UInt32) {
let machine = CSTestMachine()
machine.jamHandler = self
let immediateCode = NSData(bytes: code, length: code.count)
let immediateCode = Data(bytes: UnsafePointer<UInt8>(code), count: code.count)
machine.setData(immediateCode, atAddress: 0x200)
machine.setValue(0x00, forAddress: 0x0000)
machine.setValue(0x00, forAddress: 0x0001)
@ -208,19 +208,19 @@ class MOS6502TimingTests: XCTestCase, CSTestMachineJamHandler {
machine.setValue(0x00, forAddress: 0x0003)
machine.setValue(0x08, forAddress: 0x0004)
machine.setValue(0x02, forAddress: 0x0005)
machine.setValue(0x200, forRegister: CSTestMachineRegister.ProgramCounter)
machine.setValue(0xff, forRegister: CSTestMachineRegister.X)
machine.setValue(0xfe, forRegister: CSTestMachineRegister.Y)
machine.setValue(0x200, for: CSTestMachineRegister.programCounter)
machine.setValue(0xff, for: CSTestMachineRegister.X)
machine.setValue(0xfe, for: CSTestMachineRegister.Y)
self.endTime = 0
while self.endTime == 0 {
machine.runForNumberOfCycles(10)
machine.runForNumber(ofCycles: 10)
}
XCTAssert(self.endTime == expectedRunLength, "Took \(self.endTime) cycles to perform")
}
func testMachine(machine: CSTestMachine!, didJamAtAddress address: UInt16) {
func testMachine(_ machine: CSTestMachine!, didJamAtAddress address: UInt16) {
if self.endTime == 0 {
self.endTime = machine.timestamp - 9
}

View File

@ -11,7 +11,7 @@ import Foundation
class MOS6522Tests: XCTestCase {
private func with6522(action: (MOS6522Bridge) -> ()) {
fileprivate func with6522(_ action: (MOS6522Bridge) -> ()) {
let bridge = MOS6522Bridge()
action(bridge)
}
@ -25,11 +25,11 @@ class MOS6522Tests: XCTestCase {
$0.setValue(0, forRegister: 5)
// run for 5 cycles
$0.runForHalfCycles(10)
$0.run(forHalfCycles: 10)
// check that the timer has gone down by 5
XCTAssert($0.valueForRegister(4) == 5, "Low order byte should be 5; was \($0.valueForRegister(4))")
XCTAssert($0.valueForRegister(5) == 0, "High order byte should be 0; was \($0.valueForRegister(5))")
XCTAssert($0.value(forRegister: 4) == 5, "Low order byte should be 5; was \($0.value(forRegister: 4))")
XCTAssert($0.value(forRegister: 5) == 0, "High order byte should be 0; was \($0.value(forRegister: 5))")
}
}
@ -43,15 +43,15 @@ class MOS6522Tests: XCTestCase {
$0.setValue(0x40, forRegister: 8)
// chek that the new latched value hasn't been copied
XCTAssert($0.valueForRegister(8) == 0x10, "Low order byte should be 0x10; was \($0.valueForRegister(8))")
XCTAssert($0.valueForRegister(9) == 0x20, "High order byte should be 0x20; was \($0.valueForRegister(9))")
XCTAssert($0.value(forRegister: 8) == 0x10, "Low order byte should be 0x10; was \($0.value(forRegister: 8))")
XCTAssert($0.value(forRegister: 9) == 0x20, "High order byte should be 0x20; was \($0.value(forRegister: 9))")
// write the low-byte latch
$0.setValue(0x50, forRegister: 9)
// chek that the latched value has been copied
XCTAssert($0.valueForRegister(8) == 0x40, "Low order byte should be 0x50; was \($0.valueForRegister(8))")
XCTAssert($0.valueForRegister(9) == 0x50, "High order byte should be 0x40; was \($0.valueForRegister(9))")
XCTAssert($0.value(forRegister: 8) == 0x40, "Low order byte should be 0x50; was \($0.value(forRegister: 8))")
XCTAssert($0.value(forRegister: 9) == 0x50, "High order byte should be 0x40; was \($0.value(forRegister: 9))")
}
}
@ -64,32 +64,32 @@ class MOS6522Tests: XCTestCase {
$0.setValue(0x40 | 0x80, forRegister: 14)
// run for 16 cycles
$0.runForHalfCycles(32)
$0.run(forHalfCycles: 32)
// check that the timer has gone down to 0 but not yet triggered an interrupt
XCTAssert($0.valueForRegister(4) == 0, "Low order byte should be 0; was \($0.valueForRegister(4))")
XCTAssert($0.valueForRegister(5) == 0, "High order byte should be 0; was \($0.valueForRegister(5))")
XCTAssert($0.value(forRegister: 4) == 0, "Low order byte should be 0; was \($0.value(forRegister: 4))")
XCTAssert($0.value(forRegister: 5) == 0, "High order byte should be 0; was \($0.value(forRegister: 5))")
XCTAssert(!$0.irqLine, "IRQ should not yet be active")
// check that two half-cycles later the timer is $ffff but IRQ still hasn't triggered
$0.runForHalfCycles(2)
XCTAssert($0.valueForRegister(4) == 0xff, "Low order byte should be 0xff; was \($0.valueForRegister(4))")
XCTAssert($0.valueForRegister(5) == 0xff, "High order byte should be 0xff; was \($0.valueForRegister(5))")
$0.run(forHalfCycles: 2)
XCTAssert($0.value(forRegister: 4) == 0xff, "Low order byte should be 0xff; was \($0.value(forRegister: 4))")
XCTAssert($0.value(forRegister: 5) == 0xff, "High order byte should be 0xff; was \($0.value(forRegister: 5))")
XCTAssert(!$0.irqLine, "IRQ should not yet be active")
// check that one half-cycle later the timer is still $ffff and IRQ has triggered...
$0.runForHalfCycles(1)
$0.run(forHalfCycles: 1)
XCTAssert($0.irqLine, "IRQ should be active")
XCTAssert($0.valueForRegister(4) == 0xff, "Low order byte should be 0xff; was \($0.valueForRegister(4))")
XCTAssert($0.valueForRegister(5) == 0xff, "High order byte should be 0xff; was \($0.valueForRegister(5))")
XCTAssert($0.value(forRegister: 4) == 0xff, "Low order byte should be 0xff; was \($0.value(forRegister: 4))")
XCTAssert($0.value(forRegister: 5) == 0xff, "High order byte should be 0xff; was \($0.value(forRegister: 5))")
// ... but that reading the timer cleared the interrupt
XCTAssert(!$0.irqLine, "IRQ should be active")
// check that one half-cycles later the timer has reloaded
$0.runForHalfCycles(1)
XCTAssert($0.valueForRegister(4) == 0x10, "Low order byte should be 0x10; was \($0.valueForRegister(4))")
XCTAssert($0.valueForRegister(5) == 0x00, "High order byte should be 0x00; was \($0.valueForRegister(5))")
$0.run(forHalfCycles: 1)
XCTAssert($0.value(forRegister: 4) == 0x10, "Low order byte should be 0x10; was \($0.value(forRegister: 4))")
XCTAssert($0.value(forRegister: 5) == 0x00, "High order byte should be 0x00; was \($0.value(forRegister: 5))")
}
}
@ -107,7 +107,7 @@ class MOS6522Tests: XCTestCase {
$0.portBInput = 0xda
// test that the result of reading register B is therefore 0x8a
XCTAssert($0.valueForRegister(0) == 0x8a, "Data direction register should mix input and output; got \($0.valueForRegister(0))")
XCTAssert($0.value(forRegister: 0) == 0x8a, "Data direction register should mix input and output; got \($0.value(forRegister: 0))")
}
}
}

View File

@ -11,7 +11,7 @@ import Foundation
class MOS6532Tests: XCTestCase {
private func with6532(action: (MOS6532Bridge) -> ()) {
fileprivate func with6532(_ action: (MOS6532Bridge) -> ()) {
let bridge = MOS6532Bridge()
action(bridge)
}
@ -23,12 +23,12 @@ class MOS6532Tests: XCTestCase {
$0.setValue(128, forRegister:0x14)
// run for one clock and the count should now be 127
$0.runForCycles(1)
XCTAssert($0.valueForRegister(4) == 127, "A single tick should decrease the counter once")
$0.run(forCycles: 1)
XCTAssert($0.value(forRegister: 4) == 127, "A single tick should decrease the counter once")
// run for a further 200 clock counts; timer should reach -73 = 183
$0.runForCycles(200)
XCTAssert($0.valueForRegister(4) == 183, "Timer should underflow and keep counting")
$0.run(forCycles: 200)
XCTAssert($0.value(forRegister: 4) == 183, "Timer should underflow and keep counting")
}
}
@ -39,24 +39,24 @@ class MOS6532Tests: XCTestCase {
$0.setValue(28, forRegister:0x15)
// run for seven clock and the count should still be 28
$0.runForCycles(7)
XCTAssert($0.valueForRegister(4) == 28, "The timer should remain unchanged for seven clocks")
$0.run(forCycles: 7)
XCTAssert($0.value(forRegister: 4) == 28, "The timer should remain unchanged for seven clocks")
// run for a further clock and the count should now be 27
$0.runForCycles(1)
XCTAssert($0.valueForRegister(4) == 27, "The timer should have decremented once after 8 cycles")
$0.run(forCycles: 1)
XCTAssert($0.value(forRegister: 4) == 27, "The timer should have decremented once after 8 cycles")
// run for a further 7 + 27*8 + 5 = 228 clock counts; timer should reach -5 = 0xfb
$0.runForCycles(228)
XCTAssert($0.valueForRegister(4) == 0xfb, "Timer should underflow and start counting at single-clock pace")
$0.run(forCycles: 228)
XCTAssert($0.value(forRegister: 4) == 0xfb, "Timer should underflow and start counting at single-clock pace")
// timer should now resume dividing by eight
$0.runForCycles(7)
XCTAssert($0.valueForRegister(4) == 0xfb, "Timer should remain unchanged for seven cycles")
$0.run(forCycles: 7)
XCTAssert($0.value(forRegister: 4) == 0xfb, "Timer should remain unchanged for seven cycles")
// timer should now resume dividing by eight
$0.runForCycles(1)
XCTAssert($0.valueForRegister(4) == 0xfa, "Timer should decrement after eighth cycle")
$0.run(forCycles: 1)
XCTAssert($0.value(forRegister: 4) == 0xfa, "Timer should decrement after eighth cycle")
}
}
@ -66,23 +66,23 @@ class MOS6532Tests: XCTestCase {
$0.setValue(1, forRegister:0x1c)
// run for one clock and the count should now be zero
$0.runForCycles(1)
$0.run(forCycles: 1)
// interrupt shouldn't be signalled yet, bit should not be set
XCTAssert(!$0.irqLine, "IRQ line should not be set")
XCTAssert($0.valueForRegister(5) == 0x00, "Counter interrupt should not be set")
XCTAssert($0.value(forRegister: 5) == 0x00, "Counter interrupt should not be set")
// run for one more clock
$0.runForCycles(1)
$0.run(forCycles: 1)
// the interrupt line and bit should now be set
XCTAssert($0.irqLine, "IRQ line should be set")
XCTAssert($0.valueForRegister(5) == 0x80, "Counter interrupt should be set")
XCTAssert($0.value(forRegister: 5) == 0x80, "Counter interrupt should be set")
// writing again to the timer should clear both
$0.setValue(1, forRegister:0x1c)
XCTAssert(!$0.irqLine, "IRQ line should be clear")
XCTAssert($0.valueForRegister(5) == 0x00, "Counter interrupt should not be set")
XCTAssert($0.value(forRegister: 5) == 0x00, "Counter interrupt should not be set")
}
}
@ -103,10 +103,10 @@ class MOS6532Tests: XCTestCase {
// confirm that the interrupt flag is set but the line is not
XCTAssert(!$0.irqLine, "IRQ line should not be set")
XCTAssert($0.valueForRegister(5) == 0x40, "Timer interrupt bit should be set")
XCTAssert($0.value(forRegister: 5) == 0x40, "Timer interrupt bit should be set")
// reading the status register should have reset the interrupt flag
XCTAssert($0.valueForRegister(5) == 0x00, "Timer interrupt bit should be reset")
XCTAssert($0.value(forRegister: 5) == 0x00, "Timer interrupt bit should be reset")
}
}
@ -114,7 +114,7 @@ class MOS6532Tests: XCTestCase {
with6532 {
// seed port a is high; ensure interrupt bit is clear
$0.setValue(0x00, forRegister:0)
$0.valueForRegister(5)
$0.value(forRegister: 5)
// enable leading edge detection
$0.setValue(0, forRegister:7)
@ -127,7 +127,7 @@ class MOS6532Tests: XCTestCase {
// confirm that both the interrupt flag are the line are set
XCTAssert($0.irqLine, "IRQ line should be set")
XCTAssert($0.valueForRegister(5) == 0x40, "Timer interrupt bit should be set")
XCTAssert($0.value(forRegister: 5) == 0x40, "Timer interrupt bit should be set")
}
}
@ -135,7 +135,7 @@ class MOS6532Tests: XCTestCase {
with6532 {
// seed port a is high; ensure interrupt bit is clear
$0.setValue(0x80, forRegister:0)
$0.valueForRegister(5)
$0.value(forRegister: 5)
// enable trailing edge detection
$0.setValue(0, forRegister:6)
@ -148,7 +148,7 @@ class MOS6532Tests: XCTestCase {
// confirm that both the interrupt flag are the line are set
XCTAssert($0.irqLine, "IRQ line should be set")
XCTAssert($0.valueForRegister(5) == 0x40, "Timer interrupt bit should be set")
XCTAssert($0.value(forRegister: 5) == 0x40, "Timer interrupt bit should be set")
}
}
}

View File

@ -12,22 +12,22 @@ import XCTest
class AllSuiteATests: XCTestCase {
func testAllSuiteA() {
if let filename = NSBundle(forClass: self.dynamicType).pathForResource("AllSuiteA", ofType: "bin") {
if let allSuiteA = NSData(contentsOfFile: filename) {
if let filename = Bundle(for: type(of: self)).path(forResource: "AllSuiteA", ofType: "bin") {
if let allSuiteA = try? Data(contentsOf: URL(fileURLWithPath: filename)) {
let machine = CSTestMachine()
machine.setData(allSuiteA, atAddress: 0x4000)
machine.setValue(CSTestMachineJamOpcode, forAddress:0x45c0); // end
machine.setValue(0x4000, forRegister: CSTestMachineRegister.ProgramCounter)
machine.setValue(0x4000, for: CSTestMachineRegister.programCounter)
while !machine.isJammed {
machine.runForNumberOfCycles(1000)
machine.runForNumber(ofCycles: 1000)
}
if machine.valueForAddress(0x0210) != 0xff {
NSException(name: "Failed AllSuiteA", reason: "Failed test \(machine.valueForAddress(0x0210))", userInfo: nil).raise()
if machine.value(forAddress: 0x0210) != 0xff {
NSException(name: NSExceptionName(rawValue: "Failed AllSuiteA"), reason: "Failed test \(machine.value(forAddress: 0x0210))", userInfo: nil).raise()
}
}
}
}
}
}

View File

@ -10,32 +10,32 @@ import XCTest
class C1540Tests: XCTestCase {
private func with1540(action: (C1540Bridge) -> ()) {
fileprivate func with1540(_ action: (C1540Bridge) -> ()) {
let bridge = C1540Bridge()
if let path = NSBundle.mainBundle().pathForResource("1541", ofType: "bin", inDirectory: "ROMImages/Commodore1540") {
let data = NSData(contentsOfFile: path)
if let path = Bundle.main.path(forResource: "1541", ofType: "bin", inDirectory: "ROMImages/Commodore1540") {
let data = try? Data(contentsOf: URL(fileURLWithPath: path))
bridge.setROM(data)
}
action(bridge)
}
private func transmit(c1540: C1540Bridge, value: Int) {
fileprivate func transmit(_ c1540: C1540Bridge, value: Int) {
var shiftedValue = value
c1540.dataLine = true
c1540.runForCycles(256)
c1540.run(forCycles: 256)
XCTAssert(c1540.dataLine == false, "Listener should have taken data line low for start of transmission")
c1540.clockLine = true
c1540.runForCycles(256) // this isn't time limited on real hardware
c1540.run(forCycles: 256) // this isn't time limited on real hardware
XCTAssert(c1540.dataLine == true, "Listener should have let data line go high again")
// set up for byte transfer
c1540.clockLine = false
c1540.dataLine = true
c1540.runForCycles(40)
c1540.run(forCycles: 40)
// transmit bits
for _ in 0..<8 {
@ -45,14 +45,14 @@ class C1540Tests: XCTestCase {
// toggle clock
c1540.clockLine = true
c1540.runForCycles(40)
c1540.run(forCycles: 40)
c1540.clockLine = false
c1540.runForCycles(40)
c1540.run(forCycles: 40)
}
// check for acknowledgment
c1540.dataLine = true
c1540.runForCycles(1000)
c1540.run(forCycles: 1000)
XCTAssert(c1540.dataLine == false, "Listener should have acknowledged byte")
}
@ -61,7 +61,7 @@ class C1540Tests: XCTestCase {
func testTransmission() {
with1540 {
// allow some booting time
$0.runForCycles(2000000)
$0.run(forCycles: 2000000)
// I want to be talker, so hold attention and clock low with data high
$0.clockLine = false
@ -69,7 +69,7 @@ class C1540Tests: XCTestCase {
$0.dataLine = true
// proceed 1 ms and check that the 1540 pulled the data line low
$0.runForCycles(1000)
$0.run(forCycles: 1000)
XCTAssert($0.dataLine == false, "Listener should have taken data line low")
// transmit LISTEN #8

View File

@ -10,16 +10,16 @@ import XCTest
class DPLLTests: XCTestCase {
func testRegularNibblesOnPLL(pll: DigitalPhaseLockedLoopBridge, bitLength: UInt) {
func testRegularNibblesOnPLL(_ pll: DigitalPhaseLockedLoopBridge, bitLength: UInt) {
// clock in two 1s, a 0, and a 1, 200 times over
for _ in 0 ..< 200 {
pll.runForCycles(bitLength/2)
pll.run(forCycles: bitLength/2)
pll.addPulse()
pll.runForCycles(bitLength)
pll.run(forCycles: bitLength)
pll.addPulse()
pll.runForCycles(bitLength*2)
pll.run(forCycles: bitLength*2)
pll.addPulse()
pll.runForCycles(bitLength/2)
pll.run(forCycles: bitLength/2)
}
XCTAssert((pll.stream&0xffffffff) == 0xdddddddd, "PLL should have synchronised and clocked repeating 0xd nibbles; got \(String(pll.stream, radix: 16, uppercase: false))")
@ -27,17 +27,17 @@ class DPLLTests: XCTestCase {
func testPerfectInput() {
let pll = DigitalPhaseLockedLoopBridge(clocksPerBit: 100, tolerance: 20, historyLength: 3)
testRegularNibblesOnPLL(pll, bitLength: 100)
testRegularNibblesOnPLL(pll!, bitLength: 100)
}
func testFastButRegular() {
let pll = DigitalPhaseLockedLoopBridge(clocksPerBit: 100, tolerance: 20, historyLength: 3)
testRegularNibblesOnPLL(pll, bitLength: 90)
testRegularNibblesOnPLL(pll!, bitLength: 90)
}
func testSlowButRegular() {
let pll = DigitalPhaseLockedLoopBridge(clocksPerBit: 100, tolerance: 20, historyLength: 3)
testRegularNibblesOnPLL(pll, bitLength: 110)
testRegularNibblesOnPLL(pll!, bitLength: 110)
}
func testTwentyPercentSinePattern() {
@ -48,14 +48,14 @@ class DPLLTests: XCTestCase {
for _ in 0 ..< 200 {
let bitLength: UInt = UInt(100 + 20 * sin(angle))
pll.runForCycles(bitLength/2)
pll.addPulse()
pll.runForCycles((bitLength*3)/2)
pll?.run(forCycles: bitLength/2)
pll?.addPulse()
pll?.run(forCycles: (bitLength*3)/2)
angle = angle + 0.1
}
let endOfStream = pll.stream&0xffffffff;
XCTAssert(endOfStream == 0xaaaaaaaa || endOfStream == 0x55555555, "PLL should have synchronised and clocked repeating 0xa or 0x5 nibbles; got \(String(pll.stream, radix: 16, uppercase: false))")
let endOfStream = (pll?.stream)!&0xffffffff;
XCTAssert(endOfStream == 0xaaaaaaaa || endOfStream == 0x55555555, "PLL should have synchronised and clocked repeating 0xa or 0x5 nibbles; got \(String(pll?.stream, radix: 16, uppercase: false))")
}
}

View File

@ -13,7 +13,7 @@ class KlausDormannTests: XCTestCase {
func testKlausDormann() {
func errorForTrapAddress(address: UInt16) -> String? {
func errorForTrapAddress(_ address: UInt16) -> String? {
let hexAddress = String(format:"%04x", address)
switch address {
case 0x3399: return nil // success!
@ -32,17 +32,17 @@ class KlausDormannTests: XCTestCase {
}
}
if let filename = NSBundle(forClass: self.dynamicType).pathForResource("6502_functional_test", ofType: "bin") {
if let functionalTest = NSData(contentsOfFile: filename) {
if let filename = Bundle(for: type(of: self)).path(forResource: "6502_functional_test", ofType: "bin") {
if let functionalTest = try? Data(contentsOf: URL(fileURLWithPath: filename)) {
let machine = CSTestMachine()
machine.setData(functionalTest, atAddress: 0)
machine.setValue(0x400, forRegister: CSTestMachineRegister.ProgramCounter)
machine.setValue(0x400, for: CSTestMachineRegister.programCounter)
while true {
let oldPC = machine.valueForRegister(CSTestMachineRegister.LastOperationAddress)
machine.runForNumberOfCycles(1000)
let newPC = machine.valueForRegister(CSTestMachineRegister.LastOperationAddress)
let oldPC = machine.value(for: CSTestMachineRegister.lastOperationAddress)
machine.runForNumber(ofCycles: 1000)
let newPC = machine.value(for: CSTestMachineRegister.lastOperationAddress)
if newPC == oldPC {
let error = errorForTrapAddress(oldPC)

View File

@ -186,29 +186,29 @@ class WolfgangLorenzTests: XCTestCase, CSTestMachineJamHandler {
self.runWolfgangLorenzTest("sbcb(eb)")
}
private func runWolfgangLorenzTest(name: String, suffixes: [String]) {
fileprivate func runWolfgangLorenzTest(_ name: String, suffixes: [String]) {
for suffix in suffixes {
let testName = name + suffix
self.runWolfgangLorenzTest(testName)
}
}
private var output: String = ""
private func runWolfgangLorenzTest(name: String) {
fileprivate var output: String = ""
fileprivate func runWolfgangLorenzTest(_ name: String) {
var machine: CSTestMachine!
if let filename = NSBundle(forClass: self.dynamicType).pathForResource(name, ofType: nil) {
if let testData = NSData(contentsOfFile: filename) {
if let filename = Bundle(for: type(of: self)).path(forResource: name, ofType: nil) {
if let testData = try? Data(contentsOf: URL(fileURLWithPath: filename)) {
machine = CSTestMachine()
machine.jamHandler = self
// machine.logActivity = true
output = ""
let dataPointer = UnsafePointer<UInt8>(testData.bytes)
let dataPointer = (testData as NSData).bytes.bindMemory(to: UInt8.self, capacity: testData.count)
let loadAddress = UInt16(dataPointer[0]) | (UInt16(dataPointer[1]) << 8)
let contents = testData.subdataWithRange(NSMakeRange(2, testData.length - 2))
let contents = testData.subdata(in: NSMakeRange(2, testData.count - 2))
machine.setData(contents, atAddress: loadAddress)
@ -220,10 +220,10 @@ class WolfgangLorenzTests: XCTestCase, CSTestMachineJamHandler {
machine.setValue(0x48, forAddress: 0xfffe)
machine.setValue(0xff, forAddress: 0xffff)
let irqHandler = NSData(bytes: [
let irqHandler = Data(bytes: UnsafePointer<UInt8>([
0x48, 0x8a, 0x48, 0x98, 0x48, 0xba, 0xbd, 0x04, 0x01,
0x29, 0x10, 0xf0, 0x03, 0x6c, 0x16, 0x03, 0x6c, 0x14, 0x03
] as [UInt8], length: 19)
] as [UInt8]), count: 19)
machine.setData( irqHandler, atAddress: 0xff48)
machine.setValue(CSTestMachineJamOpcode, forAddress:0xffd2); // print character
@ -232,30 +232,30 @@ class WolfgangLorenzTests: XCTestCase, CSTestMachineJamHandler {
machine.setValue(CSTestMachineJamOpcode, forAddress:0x8000); // exit
machine.setValue(CSTestMachineJamOpcode, forAddress:0xa474); // exit
machine.setValue(0x0801, forRegister: CSTestMachineRegister.ProgramCounter)
machine.setValue(0xfd, forRegister: CSTestMachineRegister.StackPointer)
machine.setValue(0x04, forRegister: CSTestMachineRegister.Flags)
machine.setValue(0x0801, for: CSTestMachineRegister.programCounter)
machine.setValue(0xfd, for: CSTestMachineRegister.stackPointer)
machine.setValue(0x04, for: CSTestMachineRegister.flags)
}
}
if machine == nil {
NSException(name: "Failed Test", reason: "Couldn't load file \(name)", userInfo: nil).raise()
NSException(name: NSExceptionName(rawValue: "Failed Test"), reason: "Couldn't load file \(name)", userInfo: nil).raise()
}
while !machine.isJammed {
machine.runForNumberOfCycles(1000)
machine.runForNumber(ofCycles: 1000)
}
let jammedPC = machine.valueForRegister(CSTestMachineRegister.LastOperationAddress)
let jammedPC = machine.value(for: CSTestMachineRegister.lastOperationAddress)
if jammedPC != 0xe16f {
let hexAddress = String(format:"%04x", jammedPC)
NSException(name: "Failed Test", reason: "Processor jammed unexpectedly at \(hexAddress)", userInfo: nil).raise()
NSException(name: NSExceptionName(rawValue: "Failed Test"), reason: "Processor jammed unexpectedly at \(hexAddress)", userInfo: nil).raise()
}
}
// MARK: MachineJamHandler
func petsciiToString(string: String) -> String {
func petsciiToString(_ string: String) -> String {
let petsciiToCharCommon: [String] = [
"?", "?", "?", "[RUN/STOP]", "?", "[WHT]", "?", "?", "[SHIFT DISABLE]", "[SHIFT ENABLE]", "?", "?", "?", "\r", "[TEXT MODE]", "?",
"?", "\n", "[RVS ON]", "[HOME]", "[DEL]", "?", "?", "?", "?", "?", "?", "?", "[RED]", "[RIGHT]", "[GRN]", "[BLU]",
@ -297,33 +297,33 @@ class WolfgangLorenzTests: XCTestCase, CSTestMachineJamHandler {
return result
}
func testMachine(machine: CSTestMachine!, didJamAtAddress address: UInt16) {
func testMachine(_ machine: CSTestMachine!, didJamAtAddress address: UInt16) {
switch address {
case 0xffd2:
machine.setValue(0x00, forAddress: 0x030c)
let character = machine.valueForRegister(CSTestMachineRegister.A)
output.append(Character(UnicodeScalar(character)))
let character = machine.value(for: CSTestMachineRegister.A)
output.append(Character(UnicodeScalar(character)!))
machine.returnFromSubroutine()
case 0xffe4:
machine.setValue(0x3, forRegister:CSTestMachineRegister.A)
machine.setValue(0x3, for:CSTestMachineRegister.A)
machine.returnFromSubroutine()
case 0x8000, 0xa474:
NSException(name: "Failed test", reason: self.petsciiToString(output), userInfo: nil).raise()
NSException(name: NSExceptionName(rawValue: "Failed test"), reason: self.petsciiToString(output), userInfo: nil).raise()
case 0x0000:
NSException(name: "Failed test", reason: "Execution hit 0000", userInfo: nil).raise()
NSException(name: NSExceptionName(rawValue: "Failed test"), reason: "Execution hit 0000", userInfo: nil).raise()
case 0xe16f: // load next (which we consider to be success)
break;
default:
let hexAddress = String(format:"%04x", address)
NSException(name: "Failed Test", reason: "Processor jammed unexpectedly at \(hexAddress)", userInfo: nil).raise()
NSException(name: NSExceptionName(rawValue: "Failed Test"), reason: "Processor jammed unexpectedly at \(hexAddress)", userInfo: nil).raise()
}
}