From e29b94ccbe032f3e28102bb9355019c85cc5a142 Mon Sep 17 00:00:00 2001 From: Luigi Thirty Date: Fri, 4 Aug 2017 03:20:17 -0400 Subject: [PATCH] more disk drive work --- FruitMachine/AppleII/AppleII.swift | 2 +- .../AppleII/Peripherals/DiskII/DiskII.swift | 53 +++++++++++++++---- .../Peripherals/DiskII/DiskImage.swift | 43 ++++++++------- FruitMachine/AppleIIViewController.swift | 12 +++++ 4 files changed, 81 insertions(+), 29 deletions(-) diff --git a/FruitMachine/AppleII/AppleII.swift b/FruitMachine/AppleII/AppleII.swift index e9d3c22..3202a28 100644 --- a/FruitMachine/AppleII/AppleII.swift +++ b/FruitMachine/AppleII/AppleII.swift @@ -44,7 +44,7 @@ final class AppleII: NSObject, EmulatedSystem { super.init() loadROMs() - setupMemory(ramConfig: .sixteenK) + setupMemory(ramConfig: .fortyeightK) emuScreenLayer.shouldRasterize = true emuScreenLayer.delegate = emulatorViewDelegate diff --git a/FruitMachine/AppleII/Peripherals/DiskII/DiskII.swift b/FruitMachine/AppleII/Peripherals/DiskII/DiskII.swift index 4a627cc..51196d7 100644 --- a/FruitMachine/AppleII/Peripherals/DiskII/DiskII.swift +++ b/FruitMachine/AppleII/Peripherals/DiskII/DiskII.swift @@ -48,6 +48,9 @@ class DiskII: NSObject, Peripheral { static let N_Drive1MotorOff = NSNotification.Name(rawValue: "Drive1MotorOff") static let N_Drive2MotorOff = NSNotification.Name(rawValue: "Drive2MotorOff") + static let N_Drive1TrackChanged = NSNotification.Name(rawValue: "Drive1TrackChanged") + static let N_Drive2TrackChanged = NSNotification.Name(rawValue: "Drive2TrackChanged") + /* Softswitches */ struct Softswitches { var Phase0 = false @@ -68,10 +71,12 @@ class DiskII: NSObject, Peripheral { var softswitches = Softswitches() var currentTrack: Int = 0 + var mediaPosition: Int = 0 var motorPhase: MotorPhase = .Phase0 var diskImage = DiskImage(diskPath: "/Users/luigi/apple2/master.dsk") + init(slot: Int, romPath: String) { slotNumber = slot romManager = ROMManager(path: romPath, atAddress: 0x0, size: 256) @@ -108,14 +113,17 @@ class DiskII: NSObject, Peripheral { softswitches.Phase0 = true if(motorPhase == .Phase1) { motorPhase = .Phase0 - if(currentTrack % 2 == 0) { - if(currentTrack >= 0) { currentTrack -= 1 } + if(currentTrack % 2 == 0 && currentTrack > 0) + { + currentTrack -= 1 } + updateCurrentTrackDisplay(drive: softswitches.DriveSelect) } else if(motorPhase == .Phase3) { motorPhase = .Phase0 - if(currentTrack % 2 == 1) { - if(currentTrack <= 34) { currentTrack += 1 } + if(currentTrack % 2 == 1 && currentTrack < 34) { + currentTrack += 1 } + updateCurrentTrackDisplay(drive: softswitches.DriveSelect) } case 2: softswitches.Phase1 = false @@ -130,14 +138,16 @@ class DiskII: NSObject, Peripheral { softswitches.Phase2 = true if(motorPhase == .Phase3) { motorPhase = .Phase2 - if(currentTrack % 2 == 0) { - if(currentTrack >= 0) { currentTrack -= 1 } + if(currentTrack % 2 == 0 && currentTrack > 0) { + currentTrack -= 1 } + updateCurrentTrackDisplay(drive: softswitches.DriveSelect) } else if(motorPhase == .Phase1) { motorPhase = .Phase2 - if(currentTrack % 2 == 0) { - if(currentTrack <= 34) { currentTrack += 1 } + if(currentTrack % 2 == 0 && currentTrack < 34) { + currentTrack += 1; } + updateCurrentTrackDisplay(drive: softswitches.DriveSelect) } case 6: softswitches.Phase3 = false @@ -166,12 +176,16 @@ class DiskII: NSObject, Peripheral { softswitches.DriveSelect = true case 12: softswitches.Q6 = false - if(byte == nil) { //read - //write to Q6L -> read byte + if(softswitches.Q7 == false) { + //in read mode and a read was requested. get the next byte + print("Reading byte \(mediaPosition) of track \(currentTrack)") + return readByteOfTrack(track: currentTrack, advance: softswitches.MotorPowered ? 1 : 0) } case 13: + //WRITE PROTECT SENSE MODE softswitches.Q6 = true case 14: + //READ MODE softswitches.Q7 = false case 15: softswitches.Q7 = true @@ -182,6 +196,25 @@ class DiskII: NSObject, Peripheral { return 0x00 } + func readByteOfTrack(track: Int, advance: Int) -> UInt8 { + let trackData = diskImage.encodedTracks[currentTrack] + + let result = trackData[mediaPosition] + //Advance the drive to the next byte. + mediaPosition = (mediaPosition + advance) % trackData.count + + return result + } + + func updateCurrentTrackDisplay(drive: Bool) { + if(drive == false) { + NotificationCenter.default.post(name: DiskII.N_Drive1TrackChanged, object: currentTrack) + } + else { + NotificationCenter.default.post(name: DiskII.N_Drive2TrackChanged, object: currentTrack) + } + } + func installOverrides() { CPU.sharedInstance.memoryInterface.read_overrides.append(readMemoryOverride!) CPU.sharedInstance.memoryInterface.read_overrides.append(readIOOverride!) diff --git a/FruitMachine/AppleII/Peripherals/DiskII/DiskImage.swift b/FruitMachine/AppleII/Peripherals/DiskII/DiskImage.swift index d6fc632..70a39a1 100644 --- a/FruitMachine/AppleII/Peripherals/DiskII/DiskImage.swift +++ b/FruitMachine/AppleII/Peripherals/DiskII/DiskImage.swift @@ -50,7 +50,7 @@ class Dos33Image: DiskImageFormat { //Find the track in our disk. let trackOffset = trackNum * Dos33Image.BYTES_PER_TRACK //Find the sector in this track. - let sectorOffset = sectorOrder.index(of: sectorNum)! * Dos33Image.BYTES_PER_SECTOR + let sectorOffset = sectorNum * Dos33Image.BYTES_PER_SECTOR let offset = trackOffset + sectorOffset return Array(imageData[offset ..< offset + Dos33Image.BYTES_PER_SECTOR]) @@ -64,7 +64,7 @@ class DiskImage: NSObject { case Raw } - var encodedTracks = [UInt8]() + var encodedTracks = [[UInt8]]() var fileSize: UInt64 = 0 var image: DiskImageFormat? @@ -87,10 +87,16 @@ class DiskImage: NSObject { //Is this a DOS 3.3 format image? Read one sector from track $11. let catalogSector: [UInt8] = Dos33Image.readTrackAndSector(imageData: rawData!, trackNum: 0x11, sectorNum: 0) - encodeDos33Track(imageData: rawData!, index: 0, volumeNumber: Int(catalogSector[0x06])) + for track in 0.. [UInt8]? { + private func loadImageBytes(path: String, size: Int) -> [UInt8]? { do { var data = [UInt8](repeating: 0xCC, count: Int(fileSize)) @@ -105,12 +111,12 @@ class DiskImage: NSObject { return nil } - func encodeDos33Track(imageData: [UInt8], index: Int, volumeNumber: Int) { + private func encodeDos33Track(imageData: [UInt8], index: Int, volumeNumber: Int) -> [UInt8] { var encodedData = [UInt8]() let dataOffset = index * Dos33Image.BYTES_PER_TRACK //Prologue: add 48 self-syncing bytes - for _ in 0..<0x30 { encodedData.append(selfSync) } + for _ in 1..<0x30 { encodedData.append(selfSync) } for sectorNum in 0 ..< Dos33Image.SECTORS_PER_TRACK { //Address Field @@ -123,7 +129,7 @@ class DiskImage: NSObject { encodedData.append(contentsOf: addressEpilogue) //Gap2 - 5 bytes - for _ in 0..<5 { encodedData.append(selfSync) } + for _ in 0..<6 { encodedData.append(selfSync) } //Data Field encodedData.append(contentsOf: dataPrologue) @@ -131,12 +137,13 @@ class DiskImage: NSObject { encodedData.append(contentsOf: dataEpilogue) //Gap2 - for _ in 0..<5 { encodedData.append(selfSync) } + for _ in 0..<20 { encodedData.append(selfSync) } } + return encodedData } - func UInt16toUInt8Array(word: UInt16) -> [UInt8] { + private func UInt16toUInt8Array(word: UInt16) -> [UInt8] { var r = [UInt8]() r.append(UInt8((word & 0xFF00) >> 8)) r.append(UInt8(word & 0x00FF)) @@ -144,7 +151,7 @@ class DiskImage: NSObject { return r } - func EncodeSectorSixAndTwo(sector: [UInt8]) -> [UInt8] { + private func EncodeSectorSixAndTwo(sector: [UInt8]) -> [UInt8] { let encodedBuffer = SixAndTwoPrenibblize(sector: sector) var writtenData = [UInt8](repeating: 0x00, count: 343) @@ -165,7 +172,7 @@ class DiskImage: NSObject { return writtenData } - func SixAndTwoPrenibblize(sector: [UInt8]) -> [UInt8] { + private func SixAndTwoPrenibblize(sector: [UInt8]) -> [UInt8] { //Create a 342-byte buffer from a 256-byte sector. var nibblized: [UInt8] = [UInt8](repeating: 0x00, count: 342) @@ -206,7 +213,7 @@ class DiskImage: NSObject { } //Convert bytes to the different encoding schemes. - func FourAndFourEncode(byte: UInt8) -> UInt16 { + private func FourAndFourEncode(byte: UInt8) -> UInt16 { /* 4 and 4 encoded bytes require two bytes (by splitting actual bits evenly between two bytes) and have the following format: @@ -229,15 +236,15 @@ class DiskImage: NSObject { //A group of self-syncing bytes. This pattern can be repeated as long as required. //let selfSyncFive: [UInt8] = [0b11111111, 0b00111111, 0b11001111, 0b11110011, 0b11111100] - let selfSync: UInt8 = 0xFF + private let selfSync: UInt8 = 0xFF - let addressPrologue: [UInt8] = [0xD5, 0xAA, 0x96] - let addressEpilogue: [UInt8] = [0xDE, 0xAA, 0xEB] + private let addressPrologue: [UInt8] = [0xD5, 0xAA, 0x96] + private let addressEpilogue: [UInt8] = [0xDE, 0xAA, 0xEB] - let dataPrologue: [UInt8] = [0xD5, 0xAA, 0xAD] - let dataEpilogue: [UInt8] = [0xDE, 0xAA, 0xEB] + private let dataPrologue: [UInt8] = [0xD5, 0xAA, 0xAD] + private let dataEpilogue: [UInt8] = [0xDE, 0xAA, 0xEB] - let SixAndTwoTranslationTable: [UInt8] = [0x96, 0x97, 0x9A, 0x9B, 0x9D, 0x9E, 0x9F, 0xA6, + private let SixAndTwoTranslationTable: [UInt8] = [0x96, 0x97, 0x9A, 0x9B, 0x9D, 0x9E, 0x9F, 0xA6, 0xA7, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xcb, 0xcd, 0xce, 0xcf, 0xd3, diff --git a/FruitMachine/AppleIIViewController.swift b/FruitMachine/AppleIIViewController.swift index 98cadb7..6f88d4f 100644 --- a/FruitMachine/AppleIIViewController.swift +++ b/FruitMachine/AppleIIViewController.swift @@ -91,9 +91,21 @@ class AppleIIViewController: NSViewController { NotificationCenter.default.addObserver(self, selector: #selector(self.drive2MotorOn), name: DiskII.N_Drive2MotorOn, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(self.drive1MotorOff), name: DiskII.N_Drive1MotorOff, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(self.drive2MotorOff), name: DiskII.N_Drive2MotorOff, object: nil) + + NotificationCenter.default.addObserver(self, selector: #selector(self.drive1TrackChanged), name: DiskII.N_Drive1TrackChanged, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(self.drive2TrackChanged), name: DiskII.N_Drive2TrackChanged, object: nil) } /* drive lights */ + @objc func drive1TrackChanged(notification: NSNotification) { + let num = notification.object as? Int + lbl_Drive1.stringValue = "D1 \(num!)" + } + @objc func drive2TrackChanged(notification: NSNotification) { + let num = notification.object as? Int + lbl_Drive2.stringValue = "D2 \(num!)" + } + @objc func drive1MotorOff(notification: NSNotification) { lbl_Drive1.textColor = NSColor.textColor }