more disk drives
This commit is contained in:
parent
0fa0393050
commit
37bb5990fd
|
@ -54,7 +54,7 @@ final class AppleII: NSObject, EmulatedSystem {
|
||||||
|
|
||||||
emuScreenLayer.setNeedsDisplay()
|
emuScreenLayer.setNeedsDisplay()
|
||||||
emulatorView.layer?.addSublayer(emuScreenLayer)
|
emulatorView.layer?.addSublayer(emuScreenLayer)
|
||||||
|
|
||||||
installOverrides()
|
installOverrides()
|
||||||
|
|
||||||
doReset()
|
doReset()
|
||||||
|
@ -150,7 +150,6 @@ final class AppleII: NSObject, EmulatedSystem {
|
||||||
|
|
||||||
|
|
||||||
CVPixelBufferUnlockBaseAddress(emulatorViewDelegate.pixels!, CVPixelBufferLockFlags(rawValue: 0))
|
CVPixelBufferUnlockBaseAddress(emulatorViewDelegate.pixels!, CVPixelBufferLockFlags(rawValue: 0))
|
||||||
//emulatorView.display()
|
|
||||||
emulatorView.setNeedsDisplay(emulatorView.frame)
|
emulatorView.setNeedsDisplay(emulatorView.frame)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,4 +203,8 @@ final class AppleII: NSObject, EmulatedSystem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc func debuggerBreak() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,7 +169,7 @@ class DiskII: NSObject, Peripheral {
|
||||||
NotificationCenter.default.post(name: DiskII.N_Drive1MotorOff, object: nil)
|
NotificationCenter.default.post(name: DiskII.N_Drive1MotorOff, object: nil)
|
||||||
motor1OffTimer = Timer.scheduledTimer(timeInterval: 1.0,
|
motor1OffTimer = Timer.scheduledTimer(timeInterval: 1.0,
|
||||||
target: self,
|
target: self,
|
||||||
selector: #selector(disableDrive2Motor),
|
selector: #selector(disableDrive1Motor),
|
||||||
userInfo: nil,
|
userInfo: nil,
|
||||||
repeats: false)
|
repeats: false)
|
||||||
print("Drive 1 Motor will turn off in 1 second")
|
print("Drive 1 Motor will turn off in 1 second")
|
||||||
|
@ -201,11 +201,30 @@ class DiskII: NSObject, Peripheral {
|
||||||
print("Drive 2 selected")
|
print("Drive 2 selected")
|
||||||
case 12:
|
case 12:
|
||||||
softswitches.Q6 = false
|
softswitches.Q6 = false
|
||||||
if(softswitches.Q7 == false) {
|
if(softswitches.Q7 == false && byte == nil) {
|
||||||
//in read mode and a read was requested. get the next byte
|
//in read mode and a read was requested. get the next byte
|
||||||
let trk = CPU.sharedInstance.memoryInterface.readByte(offset: 0xB7EC, bypassOverrides: true)
|
let trk = CPU.sharedInstance.memoryInterface.readByte(offset: 0xB7EC, bypassOverrides: true)
|
||||||
let sec = CPU.sharedInstance.memoryInterface.readByte(offset: 0xB7ED, bypassOverrides: true)
|
let sec = CPU.sharedInstance.memoryInterface.readByte(offset: 0xB7ED, bypassOverrides: true)
|
||||||
print("Reading byte \(mediaPosition) of track \(currentTrack). Controller is accessing T\(trk) S\(sec)")
|
let mode = CPU.sharedInstance.memoryInterface.readByte(offset: 0xB7F4, bypassOverrides: true)
|
||||||
|
if(trk == 2 && sec == 4 && mode == 1)
|
||||||
|
{
|
||||||
|
_ = 1
|
||||||
|
}
|
||||||
|
let modeString: String
|
||||||
|
switch (mode) {
|
||||||
|
case 0:
|
||||||
|
modeString = "seeking"
|
||||||
|
case 1:
|
||||||
|
modeString = "reading"
|
||||||
|
case 2:
|
||||||
|
modeString = "writing"
|
||||||
|
case 4:
|
||||||
|
modeString = "formatting"
|
||||||
|
default:
|
||||||
|
modeString = "???"
|
||||||
|
}
|
||||||
|
|
||||||
|
print("Reading byte \(mediaPosition) of track \(currentTrack). DOS is \(modeString) T\(trk) S\(sec).")
|
||||||
return readByteOfTrack(track: currentTrack, advance: softswitches.MotorPowered ? 1 : 0)
|
return readByteOfTrack(track: currentTrack, advance: softswitches.MotorPowered ? 1 : 0)
|
||||||
}
|
}
|
||||||
case 13:
|
case 13:
|
||||||
|
@ -224,7 +243,7 @@ class DiskII: NSObject, Peripheral {
|
||||||
}
|
}
|
||||||
|
|
||||||
func readByteOfTrack(track: Int, advance: Int) -> UInt8 {
|
func readByteOfTrack(track: Int, advance: Int) -> UInt8 {
|
||||||
let trackData = diskImage.encodedTracks[currentTrack]
|
let trackData = diskImage.encodedTracks[track]
|
||||||
|
|
||||||
let result = trackData[mediaPosition]
|
let result = trackData[mediaPosition]
|
||||||
//Advance the drive to the next byte
|
//Advance the drive to the next byte
|
||||||
|
@ -263,11 +282,11 @@ class DiskII: NSObject, Peripheral {
|
||||||
|
|
||||||
@objc func disableDrive1Motor() {
|
@objc func disableDrive1Motor() {
|
||||||
softswitches.MotorPowered = false
|
softswitches.MotorPowered = false
|
||||||
print("Drive 1 motor is disabled")
|
print("Drive 1 Motor is now off")
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func disableDrive2Motor() {
|
@objc func disableDrive2Motor() {
|
||||||
softswitches.MotorPowered = false
|
softswitches.MotorPowered = false
|
||||||
print("Drive 2 motor is disabled")
|
print("Drive 2 Motor is now off")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ class DiskImage: NSObject {
|
||||||
encodedTracks.append(encodeDos33Track(imageData: rawData!, index: track, volumeNumber: Int(catalogSector[0x06])))
|
encodedTracks.append(encodeDos33Track(imageData: rawData!, index: track, volumeNumber: Int(catalogSector[0x06])))
|
||||||
}
|
}
|
||||||
|
|
||||||
let pointer = UnsafeBufferPointer(start:encodedTracks[2], count:encodedTracks[2].count)
|
let pointer = UnsafeBufferPointer(start:encodedTracks[0], count:encodedTracks[0].count)
|
||||||
let data = Data(buffer:pointer)
|
let data = Data(buffer:pointer)
|
||||||
try! data.write(to: URL(fileURLWithPath: "/Users/luigi/apple2/master.dmp"))
|
try! data.write(to: URL(fileURLWithPath: "/Users/luigi/apple2/master.dmp"))
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ class DiskImage: NSObject {
|
||||||
let dataOffset = index * Dos33Image.BYTES_PER_TRACK
|
let dataOffset = index * Dos33Image.BYTES_PER_TRACK
|
||||||
|
|
||||||
//Prologue: add 48 self-syncing bytes
|
//Prologue: add 48 self-syncing bytes
|
||||||
for _ in 1..<0x30 { encodedData.append(selfSync) }
|
for _ in 1..<0x31 { encodedData.append(selfSync) }
|
||||||
|
|
||||||
for sectorNum in 0 ..< Dos33Image.SECTORS_PER_TRACK {
|
for sectorNum in 0 ..< Dos33Image.SECTORS_PER_TRACK {
|
||||||
//Address Field
|
//Address Field
|
||||||
|
@ -134,11 +134,12 @@ class DiskImage: NSObject {
|
||||||
|
|
||||||
//Data Field
|
//Data Field
|
||||||
encodedData.append(contentsOf: dataPrologue)
|
encodedData.append(contentsOf: dataPrologue)
|
||||||
|
//343 bytes: 342-byte sector + 1-byte checksum
|
||||||
encodedData.append(contentsOf: EncodeSectorSixAndTwo(sector: Dos33Image.readTrackAndSector(imageData: imageData, trackNum: index, sectorNum: sectorNum)))
|
encodedData.append(contentsOf: EncodeSectorSixAndTwo(sector: Dos33Image.readTrackAndSector(imageData: imageData, trackNum: index, sectorNum: sectorNum)))
|
||||||
encodedData.append(contentsOf: dataEpilogue)
|
encodedData.append(contentsOf: dataEpilogue)
|
||||||
|
|
||||||
//Gap2 - 20 bytes
|
//Gap2 - 20 bytes
|
||||||
for _ in 0..<20 { encodedData.append(selfSync) }
|
for _ in 0..<27 { encodedData.append(selfSync) }
|
||||||
}
|
}
|
||||||
|
|
||||||
return encodedData
|
return encodedData
|
||||||
|
@ -158,12 +159,12 @@ class DiskImage: NSObject {
|
||||||
|
|
||||||
//We have a prepared buffer.
|
//We have a prepared buffer.
|
||||||
writtenData[0] = SixAndTwoTranslationTable[Int(0 ^ encodedBuffer[0x155])]
|
writtenData[0] = SixAndTwoTranslationTable[Int(0 ^ encodedBuffer[0x155])]
|
||||||
writtenData[86] = SixAndTwoTranslationTable[Int(encodedBuffer[0x100] ^ encodedBuffer[0x00])]
|
writtenData[0x56] = SixAndTwoTranslationTable[Int(encodedBuffer[0x100] ^ encodedBuffer[0x000])]
|
||||||
|
|
||||||
for index in 0x00 ... 0xFE {
|
for index in 0x00 ... 0xFE {
|
||||||
writtenData[87 + index] = SixAndTwoTranslationTable[Int(encodedBuffer[index] ^ encodedBuffer[index + 1])]
|
writtenData[0x57 + index] = SixAndTwoTranslationTable[Int(encodedBuffer[index] ^ encodedBuffer[index + 1])]
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i, index) in (0x100 ... 0x154).enumerated() {
|
for (i, index) in (0x100 ... 0x154).enumerated() {
|
||||||
writtenData[85-i] = SixAndTwoTranslationTable[Int(encodedBuffer[index] ^ encodedBuffer[index + 1])]
|
writtenData[85-i] = SixAndTwoTranslationTable[Int(encodedBuffer[index] ^ encodedBuffer[index + 1])]
|
||||||
}
|
}
|
||||||
|
@ -175,35 +176,38 @@ class DiskImage: NSObject {
|
||||||
|
|
||||||
private func SixAndTwoPrenibblize(sector: [UInt8]) -> [UInt8] {
|
private func SixAndTwoPrenibblize(sector: [UInt8]) -> [UInt8] {
|
||||||
//Create a 342-byte buffer from a 256-byte sector.
|
//Create a 342-byte buffer from a 256-byte sector.
|
||||||
var nibblized: [UInt8] = [UInt8](repeating: 0x00, count: 342)
|
|
||||||
|
|
||||||
for byte in 0x00...0x55 {
|
//TODO: Where does the checksum byte fit? I broke the low bit encoding trying to figure that out, need to fix that.
|
||||||
|
var nibblized: [UInt8] = [UInt8](repeating: 0x00, count: 343)
|
||||||
|
|
||||||
|
for byte in 0x00..<0x55 {
|
||||||
nibblized[byte] = sector[byte] >> 2
|
nibblized[byte] = sector[byte] >> 2
|
||||||
let b0 = (sector[byte] & 0b00000001)
|
let b0 = (sector[byte] & 0b00000001)
|
||||||
let b1 = (sector[byte] & 0b00000010)
|
let b1 = (sector[byte] & 0b00000010)
|
||||||
let low = 0x00 | (b0 << 1 | b1 >> 1)
|
let low = 0x00 | (b0 << 1 | b1 >> 1)
|
||||||
|
|
||||||
nibblized[0x155 - byte] |= low
|
nibblized[0x156 - byte] |= low
|
||||||
}
|
}
|
||||||
|
|
||||||
for byte in 0x56...0xAA {
|
for (i, byte) in (0x55..<0xAA).enumerated() {
|
||||||
nibblized[byte] = sector[byte] >> 2
|
nibblized[byte] = sector[byte] >> 2
|
||||||
let b0 = (sector[byte] & 0b00000001)
|
let b0 = (sector[byte] & 0b00000001)
|
||||||
let b1 = (sector[byte] & 0b00000010)
|
let b1 = (sector[byte] & 0b00000010)
|
||||||
let low = (b0 << 1 | b1 >> 1)
|
let low = 0x00 | (b0 << 1 | b1 >> 1)
|
||||||
|
|
||||||
nibblized[0x155 - (byte % 0x56)] |= (low << 2)
|
nibblized[0x156 - i] |= (low << 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
for byte in 0xAB...0xFF {
|
for (i, byte) in (0xAA..<0x100).enumerated() {
|
||||||
nibblized[byte] = sector[byte] >> 2
|
nibblized[byte] = sector[byte] >> 2
|
||||||
let b0 = (sector[byte] & 0b00000001)
|
let b0 = (sector[byte] & 0b00000001)
|
||||||
let b1 = (sector[byte] & 0b00000010)
|
let b1 = (sector[byte] & 0b00000010)
|
||||||
let low = (b0 << 1 | b1 >> 1)
|
let low = 0x00 | (b0 << 1 | b1 >> 1)
|
||||||
|
|
||||||
//Now we have a full six bits.
|
//Now we have a full six bits.
|
||||||
let completeLow: UInt8 = nibblized[0x155 - (byte % 0x56)] | (low << 4)
|
let completeLow: UInt8 = nibblized[0x156 - i] | (low << 4)
|
||||||
nibblized[0x155 - (byte % 0x56)] = completeLow
|
nibblized[0x156 - i] |= completeLow
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nibblized
|
return nibblized
|
||||||
|
@ -242,11 +246,11 @@ class DiskImage: NSObject {
|
||||||
private let dataEpilogue: [UInt8] = [0xDE, 0xAA, 0xEB]
|
private let dataEpilogue: [UInt8] = [0xDE, 0xAA, 0xEB]
|
||||||
|
|
||||||
private 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,
|
0xA7, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb2, 0xb3,
|
||||||
0xb4, 0xb5, 0xb6, 0xb7, 0xb9, 0xba, 0xbb, 0xbc,
|
0xb4, 0xb5, 0xb6, 0xb7, 0xb9, 0xba, 0xbb, 0xbc,
|
||||||
0xbd, 0xbe, 0xbf, 0xcb, 0xcd, 0xce, 0xcf, 0xd3,
|
0xbd, 0xbe, 0xbf, 0xcb, 0xcd, 0xce, 0xcf, 0xd3,
|
||||||
0xd6, 0xd7, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde,
|
0xd6, 0xd7, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde,
|
||||||
0xdf, 0xe5, 0xe6, 0xe7, 0xe9, 0xea, 0xeb, 0xec,
|
0xdf, 0xe5, 0xe6, 0xe7, 0xe9, 0xea, 0xeb, 0xec,
|
||||||
0xed, 0xee, 0xef, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,
|
0xed, 0xee, 0xef, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,
|
||||||
0xf7, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff]
|
0xf7, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff]
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@ class AppleIIViewController: NSViewController {
|
||||||
|
|
||||||
setupDriveNotifications()
|
setupDriveNotifications()
|
||||||
|
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(self.debuggerBreak), name: DebuggerNotifications.Break, object: nil)
|
||||||
|
|
||||||
self.frameTimer = Timer.scheduledTimer(timeInterval: 1.0/60.0,
|
self.frameTimer = Timer.scheduledTimer(timeInterval: 1.0/60.0,
|
||||||
target: self,
|
target: self,
|
||||||
selector: #selector(runEmulation),
|
selector: #selector(runEmulation),
|
||||||
|
@ -44,6 +46,11 @@ class AppleIIViewController: NSViewController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc func debuggerBreak() {
|
||||||
|
frameTimer?.invalidate()
|
||||||
|
CPU.sharedInstance.isRunning = false
|
||||||
|
}
|
||||||
|
|
||||||
@IBAction func showDebugger(_ sender: Any) {
|
@IBAction func showDebugger(_ sender: Any) {
|
||||||
let debuggerStoryboard = NSStoryboard(name: NSStoryboard.Name(rawValue: "Debugger"), bundle: nil)
|
let debuggerStoryboard = NSStoryboard(name: NSStoryboard.Name(rawValue: "Debugger"), bundle: nil)
|
||||||
debuggerWindowController = debuggerStoryboard.instantiateInitialController() as! DebuggerWindowController
|
debuggerWindowController = debuggerStoryboard.instantiateInitialController() as! DebuggerWindowController
|
||||||
|
@ -94,6 +101,7 @@ class AppleIIViewController: NSViewController {
|
||||||
|
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(self.drive1TrackChanged), name: DiskII.N_Drive1TrackChanged, 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)
|
NotificationCenter.default.addObserver(self, selector: #selector(self.drive2TrackChanged), name: DiskII.N_Drive2TrackChanged, object: nil)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* drive lights */
|
/* drive lights */
|
||||||
|
|
|
@ -8,6 +8,10 @@
|
||||||
|
|
||||||
import Cocoa
|
import Cocoa
|
||||||
|
|
||||||
|
class DebuggerNotifications {
|
||||||
|
static let Break = NSNotification.Name(rawValue: "DebuggerBreak")
|
||||||
|
}
|
||||||
|
|
||||||
class DebuggerViewController: NSViewController {
|
class DebuggerViewController: NSViewController {
|
||||||
@IBOutlet weak var text_CPU_A: NSTextField!
|
@IBOutlet weak var text_CPU_A: NSTextField!
|
||||||
@IBOutlet weak var text_CPU_X: NSTextField!
|
@IBOutlet weak var text_CPU_X: NSTextField!
|
||||||
|
|
Loading…
Reference in New Issue