mirror of
https://github.com/Luigi30/FruitMachine-Swift.git
synced 2024-11-23 02:33:00 +00:00
attached the Disk II ROM
peripherals
This commit is contained in:
parent
d0c22b09eb
commit
ab3c32af3d
@ -15,6 +15,11 @@
|
||||
2A5C5BBC1F304C3A00ED351D /* A2CharacterGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A5C5BBB1F304C3A00ED351D /* A2CharacterGenerator.swift */; };
|
||||
2A5C5BBE1F304D4B00ED351D /* Glyph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A5C5BBD1F304D4B00ED351D /* Glyph.swift */; };
|
||||
2A60851E1F2AFAE900E05B64 /* PIA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A60851D1F2AFAE900E05B64 /* PIA.swift */; };
|
||||
2A63C2331F32C39300D4F4F8 /* TextMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A63C2321F32C39300D4F4F8 /* TextMode.swift */; };
|
||||
2A63C2351F32C4F700D4F4F8 /* LoresMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A63C2341F32C4F700D4F4F8 /* LoresMode.swift */; };
|
||||
2A63C2371F32C55100D4F4F8 /* VideoHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A63C2361F32C55100D4F4F8 /* VideoHelpers.swift */; };
|
||||
2A63C23A1F32CCE900D4F4F8 /* DiskII.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A63C2391F32CCE900D4F4F8 /* DiskII.swift */; };
|
||||
2A63C23C1F32CD4800D4F4F8 /* Peripheral.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A63C23B1F32CD4800D4F4F8 /* Peripheral.swift */; };
|
||||
2A6C2D171F31216700B8DC60 /* SoftswitchOverrides.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A6C2D161F31216700B8DC60 /* SoftswitchOverrides.swift */; };
|
||||
2A6DC7E91F3045280066FE0D /* AppleIIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A6DC7E81F3045280066FE0D /* AppleIIViewController.swift */; };
|
||||
2A6DC7EB1F3045C90066FE0D /* EmulatedSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A6DC7EA1F3045C90066FE0D /* EmulatedSystem.swift */; };
|
||||
@ -38,6 +43,7 @@
|
||||
2AD458E31F20661300F05121 /* CPUInstructions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458E21F20661300F05121 /* CPUInstructions.swift */; };
|
||||
2AD458E51F2070DF00F05121 /* Opcodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458E41F2070DF00F05121 /* Opcodes.swift */; };
|
||||
2AD6D5841F26E6BF008F3CF5 /* DebuggerCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD6D5831F26E6BF008F3CF5 /* DebuggerCommands.swift */; };
|
||||
2AE3BB971F32CEB100C11060 /* ROMManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AE3BB961F32CEB100C11060 /* ROMManager.swift */; };
|
||||
2AE42E081F2850F400C4900E /* ReadOverride.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AE42E071F2850F400C4900E /* ReadOverride.swift */; };
|
||||
2AE42E0A1F28521E00C4900E /* WriteOverride.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AE42E091F28521E00C4900E /* WriteOverride.swift */; };
|
||||
2AE42E0C1F28522D00C4900E /* MemoryOverride.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AE42E0B1F28522D00C4900E /* MemoryOverride.swift */; };
|
||||
@ -57,6 +63,11 @@
|
||||
2A5C5BBB1F304C3A00ED351D /* A2CharacterGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = A2CharacterGenerator.swift; sourceTree = "<group>"; };
|
||||
2A5C5BBD1F304D4B00ED351D /* Glyph.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Glyph.swift; sourceTree = "<group>"; };
|
||||
2A60851D1F2AFAE900E05B64 /* PIA.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PIA.swift; sourceTree = "<group>"; };
|
||||
2A63C2321F32C39300D4F4F8 /* TextMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextMode.swift; sourceTree = "<group>"; };
|
||||
2A63C2341F32C4F700D4F4F8 /* LoresMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoresMode.swift; sourceTree = "<group>"; };
|
||||
2A63C2361F32C55100D4F4F8 /* VideoHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoHelpers.swift; sourceTree = "<group>"; };
|
||||
2A63C2391F32CCE900D4F4F8 /* DiskII.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiskII.swift; sourceTree = "<group>"; };
|
||||
2A63C23B1F32CD4800D4F4F8 /* Peripheral.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Peripheral.swift; sourceTree = "<group>"; };
|
||||
2A6C2D161F31216700B8DC60 /* SoftswitchOverrides.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftswitchOverrides.swift; sourceTree = "<group>"; };
|
||||
2A6DC7E81F3045280066FE0D /* AppleIIViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleIIViewController.swift; sourceTree = "<group>"; };
|
||||
2A6DC7EA1F3045C90066FE0D /* EmulatedSystem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmulatedSystem.swift; sourceTree = "<group>"; };
|
||||
@ -83,6 +94,7 @@
|
||||
2AD458E21F20661300F05121 /* CPUInstructions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CPUInstructions.swift; sourceTree = "<group>"; };
|
||||
2AD458E41F2070DF00F05121 /* Opcodes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Opcodes.swift; sourceTree = "<group>"; };
|
||||
2AD6D5831F26E6BF008F3CF5 /* DebuggerCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebuggerCommands.swift; sourceTree = "<group>"; };
|
||||
2AE3BB961F32CEB100C11060 /* ROMManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ROMManager.swift; sourceTree = "<group>"; };
|
||||
2AE42E071F2850F400C4900E /* ReadOverride.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadOverride.swift; sourceTree = "<group>"; };
|
||||
2AE42E091F28521E00C4900E /* WriteOverride.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WriteOverride.swift; sourceTree = "<group>"; };
|
||||
2AE42E0B1F28522D00C4900E /* MemoryOverride.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryOverride.swift; sourceTree = "<group>"; };
|
||||
@ -113,9 +125,29 @@
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2A63C2311F32C38400D4F4F8 /* Modes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2A86FB981F32694A00AD0C68 /* VideoModes.swift */,
|
||||
2A63C2321F32C39300D4F4F8 /* TextMode.swift */,
|
||||
2A63C2341F32C4F700D4F4F8 /* LoresMode.swift */,
|
||||
);
|
||||
path = Modes;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2A63C2381F32CCDB00D4F4F8 /* Peripherals */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2A63C2391F32CCE900D4F4F8 /* DiskII.swift */,
|
||||
2A63C23B1F32CD4800D4F4F8 /* Peripheral.swift */,
|
||||
);
|
||||
path = Peripherals;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2A6DC7E51F3043DB0066FE0D /* Common */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2AE3BB981F32D24D00C11060 /* Memory */,
|
||||
2A6DC7E71F3044080066FE0D /* Peripherals */,
|
||||
2A6DC7E61F3043E10066FE0D /* Video */,
|
||||
2A6DC7EA1F3045C90066FE0D /* EmulatedSystem.swift */,
|
||||
@ -143,10 +175,11 @@
|
||||
2A6DC7EE1F30492E0066FE0D /* Video */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2A63C2311F32C38400D4F4F8 /* Modes */,
|
||||
2A5C5BBB1F304C3A00ED351D /* A2CharacterGenerator.swift */,
|
||||
2A63C2361F32C55100D4F4F8 /* VideoHelpers.swift */,
|
||||
2A6DC7EC1F30492C0066FE0D /* ScreenDelegate.swift */,
|
||||
2A6DC7EF1F30495D0066FE0D /* ScreenView.swift */,
|
||||
2A86FB981F32694A00AD0C68 /* VideoModes.swift */,
|
||||
);
|
||||
path = Video;
|
||||
sourceTree = "<group>";
|
||||
@ -166,6 +199,7 @@
|
||||
2AB6CAC71F30407200DECAC0 /* AppleII */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2A63C2381F32CCDB00D4F4F8 /* Peripherals */,
|
||||
2A6DC7EE1F30492E0066FE0D /* Video */,
|
||||
2AB6CACC1F3041A200DECAC0 /* AppleII.swift */,
|
||||
2A86FB961F316CB500AD0C68 /* KeyboardController.swift */,
|
||||
@ -223,6 +257,14 @@
|
||||
path = M6502;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2AE3BB981F32D24D00C11060 /* Memory */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2AE3BB961F32CEB100C11060 /* ROMManager.swift */,
|
||||
);
|
||||
path = Memory;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2AE42E061F2850E100C4900E /* Memory */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -362,22 +404,28 @@
|
||||
2AE42E0C1F28522D00C4900E /* MemoryOverride.swift in Sources */,
|
||||
2A22EBFB1F21A7A700A36A61 /* IntegerExtensions.swift in Sources */,
|
||||
2AD6D5841F26E6BF008F3CF5 /* DebuggerCommands.swift in Sources */,
|
||||
2AE3BB971F32CEB100C11060 /* ROMManager.swift in Sources */,
|
||||
2AE5BA041F23DE4400FAA343 /* Disassembly.swift in Sources */,
|
||||
2A6DC7EB1F3045C90066FE0D /* EmulatedSystem.swift in Sources */,
|
||||
2A86FB971F316CB500AD0C68 /* KeyboardController.swift in Sources */,
|
||||
2A63C2351F32C4F700D4F4F8 /* LoresMode.swift in Sources */,
|
||||
2AE42E3A1F28628300C4900E /* AppleIViewController.swift in Sources */,
|
||||
2AD458E51F2070DF00F05121 /* Opcodes.swift in Sources */,
|
||||
2AE42E081F2850F400C4900E /* ReadOverride.swift in Sources */,
|
||||
2AA8B5FE1F2A942C002B350F /* PIAOverrides.swift in Sources */,
|
||||
2AB6CACD1F3041A200DECAC0 /* AppleII.swift in Sources */,
|
||||
2A63C2331F32C39300D4F4F8 /* TextMode.swift in Sources */,
|
||||
2AE5BA061F2469EB00FAA343 /* AddressConversions.swift in Sources */,
|
||||
2AE42E0A1F28521E00C4900E /* WriteOverride.swift in Sources */,
|
||||
2A6DC7ED1F30492C0066FE0D /* ScreenDelegate.swift in Sources */,
|
||||
2A5BC5191F29A28D008C03BE /* AppleIScreenView.swift in Sources */,
|
||||
2A63C2371F32C55100D4F4F8 /* VideoHelpers.swift in Sources */,
|
||||
2A63C23A1F32CCE900D4F4F8 /* DiskII.swift in Sources */,
|
||||
2AD458E11F2064CB00F05121 /* MemoryInterface.swift in Sources */,
|
||||
2AA8B5F81F2A8889002B350F /* AppleI.swift in Sources */,
|
||||
2AD458DF1F205F4500F05121 /* CPU.swift in Sources */,
|
||||
2A86FB991F32694A00AD0C68 /* VideoModes.swift in Sources */,
|
||||
2A63C23C1F32CD4800D4F4F8 /* Peripheral.swift in Sources */,
|
||||
2A6DC7E91F3045280066FE0D /* AppleIIViewController.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -12,7 +12,7 @@ extension AppleI {
|
||||
|
||||
class PIAOverrides: NSObject {
|
||||
static let writeDSP = WriteOverride(start: 0xD012, end: 0xD012, writeAnyway: false, action: PIAOverrides.actionWriteDSP)
|
||||
static func actionWriteDSP(terminal: AnyObject, byte: UInt8?) -> UInt8? {
|
||||
static func actionWriteDSP(terminal: AnyObject, address: UInt16, byte: UInt8?) -> UInt8? {
|
||||
|
||||
let pia = AppleI.sharedInstance.pia["display"]!
|
||||
|
||||
@ -29,13 +29,13 @@ extension AppleI {
|
||||
}
|
||||
|
||||
static let writeDSPCR = WriteOverride(start: 0xD013, end: 0xD013, writeAnyway: false, action: PIAOverrides.actionWriteDSPCR)
|
||||
static func actionWriteDSPCR(terminal: AnyObject, byte: UInt8?) -> UInt8? {
|
||||
static func actionWriteDSPCR(terminal: AnyObject, address: UInt16, byte: UInt8?) -> UInt8? {
|
||||
AppleI.sharedInstance.pia["display"]?.control = byte!
|
||||
return nil
|
||||
}
|
||||
|
||||
static let readDSP = ReadOverride(start: 0xD012, end: 0xD012, readAnyway: false, action: PIAOverrides.actionReadDSP)
|
||||
static func actionReadDSP(terminal: AnyObject, byte: UInt8?) -> UInt8? {
|
||||
static func actionReadDSP(terminal: AnyObject, address: UInt16, byte: UInt8?) -> UInt8? {
|
||||
|
||||
//DSP.7 is unset when the character is accepted by the terminal
|
||||
return AppleI.sharedInstance.pia["display"]!.data
|
||||
@ -43,13 +43,13 @@ extension AppleI {
|
||||
/* */
|
||||
|
||||
static let readKBDCR = ReadOverride(start: 0xD011, end: 0xD011, readAnyway: false, action: PIAOverrides.actionReadKBDCR)
|
||||
static func actionReadKBDCR(terminal: AnyObject, byte: UInt8?) -> UInt8? {
|
||||
static func actionReadKBDCR(terminal: AnyObject, address: UInt16, byte: UInt8?) -> UInt8? {
|
||||
return AppleI.sharedInstance.pia["keyboard"]!.control
|
||||
}
|
||||
|
||||
/* */
|
||||
static let readKBD = ReadOverride(start: 0xD010, end: 0xD010, readAnyway: false, action: PIAOverrides.actionReadKBD)
|
||||
static func actionReadKBD(terminal: AnyObject, byte: UInt8?) -> UInt8? {
|
||||
static func actionReadKBD(terminal: AnyObject, address: UInt16, byte: UInt8?) -> UInt8? {
|
||||
//Reading KBD clears KBDCR.7
|
||||
AppleI.sharedInstance.pia["keyboard"]!.control = AppleI.sharedInstance.pia["keyboard"]!.control & ~(0x80)
|
||||
|
||||
|
@ -16,29 +16,19 @@ extension AppleI {
|
||||
static let CHAR_WIDTH = 5
|
||||
static let CHAR_HEIGHT = 8
|
||||
|
||||
var ROM: [UInt8]
|
||||
var glyphs: [Glyph]
|
||||
var romManager: ROMDelegate
|
||||
|
||||
init(romPath: String) {
|
||||
ROM = [UInt8](repeating: 0xCC, count: 512)
|
||||
glyphs = [Glyph](repeating: Glyph(inPixels: [BitmapPixelsLE555.PixelData]()), count: 64)
|
||||
romManager = ROMManager(path: romPath, atAddress: 0x00, size: 512)
|
||||
|
||||
super.init()
|
||||
loadROM(path: romPath)
|
||||
|
||||
for index in 0..<64 {
|
||||
glyphs[index] = Glyph(inPixels: getCharacterPixels(charIndex: UInt8(index)))
|
||||
}
|
||||
}
|
||||
|
||||
private func loadROM(path: String) {
|
||||
do {
|
||||
let fileContent: NSData = try NSData(contentsOfFile: path)
|
||||
fileContent.getBytes(&ROM, range: NSRange(location: 0, length: 512))
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
|
||||
private func getCharacterPixels(charIndex: UInt8) -> [BitmapPixelsLE555.PixelData] {
|
||||
var pixelArray = [UInt8](repeating: 0x00, count: A1CharacterGenerator.CHAR_HEIGHT)
|
||||
@ -48,7 +38,7 @@ extension AppleI {
|
||||
|
||||
//Don't convert the character indexes if we're populating the glyphs array.
|
||||
for scanlineIndex in 0..<A1CharacterGenerator.CHAR_HEIGHT {
|
||||
pixelArray[scanlineIndex] = ROM[scanlineIndex + (Int(charIndex) * A1CharacterGenerator.CHAR_HEIGHT)]
|
||||
pixelArray[scanlineIndex] = romManager.ROM[scanlineIndex + (Int(charIndex) * A1CharacterGenerator.CHAR_HEIGHT)]
|
||||
}
|
||||
|
||||
var glyphPixels = [BitmapPixelsLE555.PixelData]()
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
import Cocoa
|
||||
|
||||
class AppleII: NSObject, EmulatedSystem {
|
||||
final class AppleII: NSObject, EmulatedSystem {
|
||||
static let sharedInstance = AppleII(cpuFrequency: (14.31818 / 7 / 2) * 1000000, fps: 60.0)
|
||||
|
||||
var frameCounter: Int = 0
|
||||
@ -18,6 +18,9 @@ class AppleII: NSObject, EmulatedSystem {
|
||||
var videoSoftswitches = VideoSoftswitches()
|
||||
var videoMode: VideoMode
|
||||
|
||||
//Peripherals
|
||||
var backplane = [Int: Peripheral?]()
|
||||
|
||||
var CPU_FREQUENCY: Double
|
||||
var FRAMES_PER_SECOND: Double
|
||||
var CYCLES_PER_BATCH: Int
|
||||
@ -33,10 +36,15 @@ class AppleII: NSObject, EmulatedSystem {
|
||||
|
||||
videoMode = .Text
|
||||
|
||||
for i in 1...7 {
|
||||
backplane[i] = nil
|
||||
}
|
||||
|
||||
super.init()
|
||||
|
||||
loadROMs()
|
||||
setupMemory(ramConfig: .sixteenK)
|
||||
backplane[6] = DiskII(slot: 6, romPath: "/Users/luigi/apple2/341-0027-a.p5")
|
||||
|
||||
emuScreenLayer.shouldRasterize = true
|
||||
emuScreenLayer.delegate = emulatorViewDelegate
|
||||
@ -66,6 +74,12 @@ class AppleII: NSObject, EmulatedSystem {
|
||||
}
|
||||
|
||||
func installOverrides() {
|
||||
for (slotNum, peripheral) in backplane {
|
||||
if(peripheral != nil) {
|
||||
peripheral!.installOverrides()
|
||||
}
|
||||
}
|
||||
|
||||
CPU.sharedInstance.memoryInterface.read_overrides.append(SoftswitchOverrides.readKeyboard)
|
||||
CPU.sharedInstance.memoryInterface.read_overrides.append(SoftswitchOverrides.clearKeypressStrobeR)
|
||||
CPU.sharedInstance.memoryInterface.write_overrides.append(SoftswitchOverrides.clearKeypressStrobeW)
|
||||
@ -143,7 +157,7 @@ class AppleII: NSObject, EmulatedSystem {
|
||||
for address in start ..< end {
|
||||
let pixelData = CPU.sharedInstance.memoryInterface.readByte(offset: UInt16(address), bypassOverrides: true)
|
||||
|
||||
emulatorViewDelegate.putLoresPixel(buffer: buffer,
|
||||
LoresMode.putLoresPixel(buffer: buffer,
|
||||
pixel: pixelData,
|
||||
address: UInt16(address))
|
||||
}
|
||||
@ -153,10 +167,10 @@ class AppleII: NSObject, EmulatedSystem {
|
||||
for address in start ... end {
|
||||
let charCode = CPU.sharedInstance.memoryInterface.readByte(offset: UInt16(address), bypassOverrides: true)
|
||||
|
||||
emulatorViewDelegate.putGlyph(buffer: buffer,
|
||||
glyph: cg.glyphs[Int(charCode & 0x3F)],
|
||||
attributes: charCode & 0xC0, //d6 and d7
|
||||
pixelPosition: emulatorViewDelegate.getPixelOffset(memoryOffset: Int(address - 0x400)))
|
||||
TextMode.putGlyph(buffer: buffer,
|
||||
glyph: cg.glyphs[Int(charCode & 0x3F)],
|
||||
attributes: charCode & 0xC0, //d6 and d7
|
||||
pixelPosition: VideoHelpers.getPixelOffset(memoryOffset: Int(address - 0x400)))
|
||||
}
|
||||
}
|
||||
|
||||
|
45
FruitMachine/AppleII/Peripherals/DiskII.swift
Normal file
45
FruitMachine/AppleII/Peripherals/DiskII.swift
Normal file
@ -0,0 +1,45 @@
|
||||
//
|
||||
// DiskII.swift
|
||||
// FruitMachine
|
||||
//
|
||||
// Created by Christopher Rohl on 8/2/17.
|
||||
// Copyright © 2017 Christopher Rohl. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
||||
class DiskII: NSObject, Peripheral {
|
||||
let slotNumber: Int
|
||||
let romManager: ROMManager
|
||||
var readMemoryOverride: ReadOverride? = nil
|
||||
var writeMemoryOverride: WriteOverride? = nil
|
||||
|
||||
init(slot: Int, romPath: String) {
|
||||
slotNumber = slot
|
||||
romManager = ROMManager(path: romPath, atAddress: 0x0, size: 256)
|
||||
|
||||
super.init()
|
||||
|
||||
readMemoryOverride = ReadOverride(start: UInt16(0xC000 + (0x100 * slotNumber)),
|
||||
end: UInt16(0xC0FF + (0x100 * slotNumber)),
|
||||
readAnyway: false,
|
||||
action: actionReadMemory)
|
||||
}
|
||||
|
||||
func actionReadMemory(something: AnyObject, address: UInt16, byte: UInt8?) -> UInt8? {
|
||||
let offset: UInt16 = 0xC000 + UInt16(slotNumber*0x100)
|
||||
let local = address - offset
|
||||
|
||||
return getMemoryMappedByte(address: local)
|
||||
}
|
||||
|
||||
private func getMemoryMappedByte(address: UInt16) -> UInt8 {
|
||||
//Disk II just maps its ROM to the memory addressed by the slot.
|
||||
|
||||
return romManager.ROM[Int(address)]
|
||||
}
|
||||
|
||||
func installOverrides() {
|
||||
CPU.sharedInstance.memoryInterface.read_overrides.append(readMemoryOverride!)
|
||||
}
|
||||
}
|
14
FruitMachine/AppleII/Peripherals/Peripheral.swift
Normal file
14
FruitMachine/AppleII/Peripherals/Peripheral.swift
Normal file
@ -0,0 +1,14 @@
|
||||
//
|
||||
// Peripheral.swift
|
||||
// FruitMachine
|
||||
//
|
||||
// Created by Christopher Rohl on 8/2/17.
|
||||
// Copyright © 2017 Christopher Rohl. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
||||
protocol Peripheral {
|
||||
var slotNumber: Int { get }
|
||||
func installOverrides()
|
||||
}
|
@ -13,7 +13,7 @@ extension AppleII {
|
||||
class SoftswitchOverrides: NSObject {
|
||||
/* Keyboard port */
|
||||
static let readKeyboard = ReadOverride(start: 0xC000, end: 0xC000, readAnyway: false, action: SoftswitchOverrides.actionReadKeyboard)
|
||||
static func actionReadKeyboard(dummy: AnyObject, byte: UInt8?) -> UInt8? {
|
||||
static func actionReadKeyboard(dummy: AnyObject, address: UInt16, byte: UInt8?) -> UInt8? {
|
||||
//let b = CPU.sharedInstance.memoryInterface.readByte(offset: 0xC000, bypassOverrides: true)
|
||||
//CPU.sharedInstance.memoryInterface.writeByte(offset: 0xC000, value: b)
|
||||
//return b
|
||||
@ -22,7 +22,7 @@ extension AppleII {
|
||||
|
||||
static let clearKeypressStrobeR = ReadOverride(start: 0xC010, end: 0xC010, readAnyway: false, action: SoftswitchOverrides.actionClearKeypressStrobe)
|
||||
static let clearKeypressStrobeW = WriteOverride(start: 0xC010, end: 0xC010, writeAnyway: false, action: SoftswitchOverrides.actionClearKeypressStrobe)
|
||||
static func actionClearKeypressStrobe(dummy: AnyObject, byte: UInt8?) -> UInt8? {
|
||||
static func actionClearKeypressStrobe(dummy: AnyObject, address: UInt16, byte: UInt8?) -> UInt8? {
|
||||
//Clears b7 of $C000 on write.
|
||||
|
||||
//let b = CPU.sharedInstance.memoryInterface.readByte(offset: 0xC000, bypassOverrides: true)
|
||||
@ -39,56 +39,56 @@ extension AppleII {
|
||||
/* Video settings */
|
||||
static let switchC050R = ReadOverride(start: 0xC050, end: 0xC050, readAnyway: false, action: SoftswitchOverrides.actionSwitchC050)
|
||||
static let switchC050W = WriteOverride(start: 0xC050, end: 0xC050, writeAnyway: false, action: SoftswitchOverrides.actionSwitchC050)
|
||||
static func actionSwitchC050(dummy: AnyObject, byte: UInt8?) -> UInt8? {
|
||||
static func actionSwitchC050(dummy: AnyObject, address: UInt16, byte: UInt8?) -> UInt8? {
|
||||
AppleII.sharedInstance.videoSoftswitches.TEXT_MODE = false
|
||||
return 0x00
|
||||
}
|
||||
|
||||
static let switchC051R = ReadOverride(start: 0xC051, end: 0xC051, readAnyway: false, action: SoftswitchOverrides.actionSwitchC051)
|
||||
static let switchC051W = WriteOverride(start: 0xC051, end: 0xC051, writeAnyway: false, action: SoftswitchOverrides.actionSwitchC051)
|
||||
static func actionSwitchC051(dummy: AnyObject, byte: UInt8?) -> UInt8? {
|
||||
static func actionSwitchC051(dummy: AnyObject, address: UInt16, byte: UInt8?) -> UInt8? {
|
||||
AppleII.sharedInstance.videoSoftswitches.TEXT_MODE = true
|
||||
return 0x00
|
||||
}
|
||||
|
||||
static let switchC052R = ReadOverride(start: 0xC052, end: 0xC052, readAnyway: false, action: SoftswitchOverrides.actionSwitchC052)
|
||||
static let switchC052W = WriteOverride(start: 0xC052, end: 0xC052, writeAnyway: false, action: SoftswitchOverrides.actionSwitchC052)
|
||||
static func actionSwitchC052(dummy: AnyObject, byte: UInt8?) -> UInt8? {
|
||||
static func actionSwitchC052(dummy: AnyObject, address: UInt16, byte: UInt8?) -> UInt8? {
|
||||
AppleII.sharedInstance.videoSoftswitches.MIX_MODE = false
|
||||
return 0x00
|
||||
}
|
||||
|
||||
static let switchC053R = ReadOverride(start: 0xC053, end: 0xC053, readAnyway: false, action: SoftswitchOverrides.actionSwitchC053)
|
||||
static let switchC053W = WriteOverride(start: 0xC053, end: 0xC053, writeAnyway: false, action: SoftswitchOverrides.actionSwitchC053)
|
||||
static func actionSwitchC053(dummy: AnyObject, byte: UInt8?) -> UInt8? {
|
||||
static func actionSwitchC053(dummy: AnyObject, address: UInt16, byte: UInt8?) -> UInt8? {
|
||||
AppleII.sharedInstance.videoSoftswitches.MIX_MODE = true
|
||||
return 0x00
|
||||
}
|
||||
|
||||
static let switchC054R = ReadOverride(start: 0xC054, end: 0xC054, readAnyway: false, action: SoftswitchOverrides.actionSwitchC054)
|
||||
static let switchC054W = WriteOverride(start: 0xC054, end: 0xC054, writeAnyway: false, action: SoftswitchOverrides.actionSwitchC054)
|
||||
static func actionSwitchC054(dummy: AnyObject, byte: UInt8?) -> UInt8? {
|
||||
static func actionSwitchC054(dummy: AnyObject, address: UInt16, byte: UInt8?) -> UInt8? {
|
||||
AppleII.sharedInstance.videoSoftswitches.PAGE_2 = false
|
||||
return 0x00
|
||||
}
|
||||
|
||||
static let switchC055R = ReadOverride(start: 0xC055, end: 0xC055, readAnyway: false, action: SoftswitchOverrides.actionSwitchC055)
|
||||
static let switchC055W = WriteOverride(start: 0xC055, end: 0xC055, writeAnyway: false, action: SoftswitchOverrides.actionSwitchC055)
|
||||
static func actionSwitchC055(dummy: AnyObject, byte: UInt8?) -> UInt8? {
|
||||
static func actionSwitchC055(dummy: AnyObject, address: UInt16, byte: UInt8?) -> UInt8? {
|
||||
AppleII.sharedInstance.videoSoftswitches.MIX_MODE = true
|
||||
return 0x00
|
||||
}
|
||||
|
||||
static let switchC056R = ReadOverride(start: 0xC056, end: 0xC056, readAnyway: false, action: SoftswitchOverrides.actionSwitchC056)
|
||||
static let switchC056W = WriteOverride(start: 0xC056, end: 0xC056, writeAnyway: false, action: SoftswitchOverrides.actionSwitchC056)
|
||||
static func actionSwitchC056(dummy: AnyObject, byte: UInt8?) -> UInt8? {
|
||||
static func actionSwitchC056(dummy: AnyObject, address: UInt16, byte: UInt8?) -> UInt8? {
|
||||
AppleII.sharedInstance.videoSoftswitches.HIRES_MODE = false
|
||||
return 0x00
|
||||
}
|
||||
|
||||
static let switchC057R = ReadOverride(start: 0xC057, end: 0xC057, readAnyway: false, action: SoftswitchOverrides.actionSwitchC057)
|
||||
static let switchC057W = WriteOverride(start: 0xC057, end: 0xC057, writeAnyway: false, action: SoftswitchOverrides.actionSwitchC057)
|
||||
static func actionSwitchC057(dummy: AnyObject, byte: UInt8?) -> UInt8? {
|
||||
static func actionSwitchC057(dummy: AnyObject, address: UInt16, byte: UInt8?) -> UInt8? {
|
||||
AppleII.sharedInstance.videoSoftswitches.HIRES_MODE = true
|
||||
return 0x00
|
||||
}
|
||||
|
@ -12,19 +12,18 @@ extension AppleII {
|
||||
|
||||
//The Apple II character generator is a clone of the Signetics 2513 from the Apple I.
|
||||
|
||||
class A2CharacterGenerator: NSObject {
|
||||
class A2CharacterGenerator: NSObject, HasROM {
|
||||
static let CHAR_WIDTH = 5
|
||||
static let CHAR_HEIGHT = 8
|
||||
|
||||
var ROM: [UInt8]
|
||||
var glyphs: [Glyph]
|
||||
var romManager: ROMManager
|
||||
|
||||
init(romPath: String) {
|
||||
ROM = [UInt8](repeating: 0xCC, count: 0x800)
|
||||
romManager = ROMManager(path: romPath, atAddress: 0x00, size: 0x800)
|
||||
glyphs = [Glyph](repeating: Glyph(inPixels: [BitmapPixelsLE555.PixelData]()), count: 64)
|
||||
|
||||
super.init()
|
||||
loadROM(path: romPath)
|
||||
|
||||
for index in 0..<64 {
|
||||
glyphs[index] = Glyph(inPixels: getCharacterPixels(charIndex: UInt8(index)))
|
||||
@ -39,7 +38,7 @@ extension AppleII {
|
||||
|
||||
//Don't convert the character indexes if we're populating the glyphs array.
|
||||
for scanlineIndex in 0..<A2CharacterGenerator.CHAR_HEIGHT {
|
||||
pixelArray[scanlineIndex] = ROM[scanlineIndex + (Int(charIndex) * A2CharacterGenerator.CHAR_HEIGHT)]
|
||||
pixelArray[scanlineIndex] = romManager.ROM[scanlineIndex + (Int(charIndex) * A2CharacterGenerator.CHAR_HEIGHT)]
|
||||
}
|
||||
|
||||
var glyphPixels = [BitmapPixelsLE555.PixelData]()
|
||||
@ -56,15 +55,6 @@ extension AppleII {
|
||||
func asciiToAppleCharIndex(ascii: UInt8) -> UInt8 {
|
||||
return (ascii & 0x1f) | (((ascii ^ 0x40) & 0x40) >> 1)
|
||||
}
|
||||
|
||||
private func loadROM(path: String) {
|
||||
do {
|
||||
let fileContent: NSData = try NSData(contentsOfFile: path)
|
||||
fileContent.getBytes(&ROM, range: NSRange(location: 0, length: 0x800))
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
48
FruitMachine/AppleII/Video/Modes/LoresMode.swift
Normal file
48
FruitMachine/AppleII/Video/Modes/LoresMode.swift
Normal file
@ -0,0 +1,48 @@
|
||||
//
|
||||
// LoresMode.swift
|
||||
// FruitMachine
|
||||
//
|
||||
// Created by Christopher Rohl on 8/2/17.
|
||||
// Copyright © 2017 Christopher Rohl. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
||||
extension AppleII {
|
||||
|
||||
class LoresMode: NSObject {
|
||||
static func putLoresPixel(buffer: UnsafeMutablePointer<BitmapPixelsLE555.PixelData>?, pixel: UInt8, address: UInt16) {
|
||||
let pageOffset = address - 0x400
|
||||
let pixelPosition = VideoHelpers.getPixelOffset(memoryOffset: Int(pageOffset))
|
||||
if(pixelPosition.x == -1 && pixelPosition.y == -1) {
|
||||
return
|
||||
}
|
||||
|
||||
let pixelNybbleHi = pixel & 0x0F
|
||||
let pixelNybbleLo = (pixel & 0xF0) >> 4
|
||||
|
||||
let colorHi = AppleII.LoresColors.getColor(index: pixelNybbleHi)
|
||||
let colorLo = LoresColors.getColor(index: pixelNybbleLo)
|
||||
|
||||
//One lores pixel is 7px wide and 4px tall for a resolution of 40x48.
|
||||
let baseOffset = AppleII.sharedInstance.emulatorViewDelegate.scanlineOffsets[Int(pixelPosition.y)] + Int(pixelPosition.x)
|
||||
|
||||
for charY in 0..<5 {
|
||||
let offsetHi = baseOffset + (AppleII.ScreenDelegate.PIXEL_WIDTH * charY)
|
||||
|
||||
for charX in 0..<7 {
|
||||
buffer![offsetHi + 6 - charX] = colorHi
|
||||
}
|
||||
}
|
||||
for charY in 4..<8 {
|
||||
let offsetLo = baseOffset + (AppleII.ScreenDelegate.PIXEL_WIDTH * charY)
|
||||
|
||||
for charX in 0..<7 {
|
||||
buffer![offsetLo + 6 - charX] = colorLo
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
53
FruitMachine/AppleII/Video/Modes/TextMode.swift
Normal file
53
FruitMachine/AppleII/Video/Modes/TextMode.swift
Normal file
@ -0,0 +1,53 @@
|
||||
//
|
||||
// TextMode.swift
|
||||
// FruitMachine
|
||||
//
|
||||
// Created by Christopher Rohl on 8/2/17.
|
||||
// Copyright © 2017 Christopher Rohl. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
||||
extension AppleII {
|
||||
|
||||
class TextMode: NSObject {
|
||||
static func putGlyph(buffer: UnsafeMutablePointer<BitmapPixelsLE555.PixelData>?, glyph: Glyph, attributes: UInt8, pixelPosition: CGPoint) {
|
||||
//You better have locked the buffer before getting here...
|
||||
if(pixelPosition.x == -1 && pixelPosition.y == -1) { return }
|
||||
|
||||
let ca: CharacterAttributes
|
||||
if(attributes == 0x00) {
|
||||
ca = .inverse
|
||||
} else if(attributes == 0x40) {
|
||||
ca = .flashing
|
||||
} else {
|
||||
ca = .normal
|
||||
}
|
||||
|
||||
//Calculate the offset to reach the desired position.
|
||||
let baseOffset = AppleII.sharedInstance.emulatorViewDelegate.scanlineOffsets[Int(pixelPosition.y)] + Int(pixelPosition.x)
|
||||
|
||||
for charY in 0..<AppleII.A2CharacterGenerator.CHAR_HEIGHT {
|
||||
let offset = baseOffset + (AppleII.ScreenDelegate.PIXEL_WIDTH * charY)
|
||||
let glyphOffsetY = (charY * 8)
|
||||
|
||||
for charX in 0..<7 {
|
||||
switch(ca) {
|
||||
case .normal:
|
||||
buffer![offset + 6 - charX] = glyph.pixels[glyphOffsetY + charX]
|
||||
case .inverse:
|
||||
buffer![offset + 6 - charX] = BitmapPixelsLE555.PixelData(data: ~glyph.pixels[glyphOffsetY + charX].data)
|
||||
case .flashing:
|
||||
if(!AppleII.sharedInstance.emulatorViewDelegate.flashIsInverse) {
|
||||
buffer![offset + 6 - charX] = glyph.pixels[glyphOffsetY + charX]
|
||||
} else {
|
||||
buffer![offset + 6 - charX] = BitmapPixelsLE555.PixelData(data: ~glyph.pixels[glyphOffsetY + charX].data)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -29,6 +29,7 @@ extension AppleII {
|
||||
/* Pixel data stuff. */
|
||||
let bitmapInfo: CGBitmapInfo = [.byteOrder16Little, CGBitmapInfo(rawValue: CGImageAlphaInfo.noneSkipFirst.rawValue)]
|
||||
|
||||
var scanlineOffsets: [Int]
|
||||
var pixels: CVPixelBuffer?
|
||||
|
||||
let sourceRowBytes: Int
|
||||
@ -36,8 +37,6 @@ extension AppleII {
|
||||
let bufferHeight: Int
|
||||
|
||||
var renderedImage: CGImage?
|
||||
|
||||
var scanlineOffsets: [Int]
|
||||
|
||||
override init() {
|
||||
_ = CVPixelBufferCreate(kCFAllocatorDefault, AppleII.ScreenDelegate.PIXEL_WIDTH, AppleII.ScreenDelegate.PIXEL_HEIGHT, OSType(k16BE555PixelFormat), nil, &pixels)
|
||||
@ -54,114 +53,6 @@ extension AppleII {
|
||||
}
|
||||
}
|
||||
|
||||
func putGlyph(buffer: UnsafeMutablePointer<BitmapPixelsLE555.PixelData>?, glyph: Glyph, attributes: UInt8, pixelPosition: CGPoint) {
|
||||
//You better have locked the buffer before getting here...
|
||||
if(pixelPosition.x == -1 && pixelPosition.y == -1) { return }
|
||||
|
||||
let ca: CharacterAttributes
|
||||
if(attributes == 0x00) {
|
||||
ca = .inverse
|
||||
} else if(attributes == 0x40) {
|
||||
ca = .flashing
|
||||
} else {
|
||||
ca = .normal
|
||||
}
|
||||
|
||||
//Calculate the offset to reach the desired position.
|
||||
let baseOffset = scanlineOffsets[Int(pixelPosition.y)] + Int(pixelPosition.x)
|
||||
|
||||
for charY in 0..<AppleII.A2CharacterGenerator.CHAR_HEIGHT {
|
||||
let offset = baseOffset + (AppleII.ScreenDelegate.PIXEL_WIDTH * charY)
|
||||
let glyphOffsetY = (charY * 8)
|
||||
|
||||
for charX in 0..<7 {
|
||||
switch(ca) {
|
||||
case .normal:
|
||||
buffer![offset + 6 - charX] = glyph.pixels[glyphOffsetY + charX]
|
||||
case .inverse:
|
||||
buffer![offset + 6 - charX] = BitmapPixelsLE555.PixelData(data: ~glyph.pixels[glyphOffsetY + charX].data)
|
||||
case .flashing:
|
||||
if(!flashIsInverse) {
|
||||
buffer![offset + 6 - charX] = glyph.pixels[glyphOffsetY + charX]
|
||||
} else {
|
||||
buffer![offset + 6 - charX] = BitmapPixelsLE555.PixelData(data: ~glyph.pixels[glyphOffsetY + charX].data)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func putLoresPixel(buffer: UnsafeMutablePointer<BitmapPixelsLE555.PixelData>?, pixel: UInt8, address: UInt16) {
|
||||
let pageOffset = address - 0x400
|
||||
let pixelPosition = getPixelOffset(memoryOffset: Int(pageOffset))
|
||||
if(pixelPosition.x == -1 && pixelPosition.y == -1) {
|
||||
return
|
||||
}
|
||||
|
||||
let pixelNybbleHi = pixel & 0x0F
|
||||
let pixelNybbleLo = (pixel & 0xF0) >> 4
|
||||
|
||||
let colorHi = LoresColors.getColor(index: pixelNybbleHi)
|
||||
let colorLo = LoresColors.getColor(index: pixelNybbleLo)
|
||||
|
||||
//One lores pixel is 7px wide and 4px tall for a resolution of 40x48.
|
||||
let baseOffset = scanlineOffsets[Int(pixelPosition.y)] + Int(pixelPosition.x)
|
||||
|
||||
for charY in 0..<5 {
|
||||
let offsetHi = baseOffset + (AppleII.ScreenDelegate.PIXEL_WIDTH * charY)
|
||||
|
||||
for charX in 0..<7 {
|
||||
buffer![offsetHi + 6 - charX] = colorHi
|
||||
}
|
||||
}
|
||||
for charY in 4..<8 {
|
||||
let offsetLo = baseOffset + (AppleII.ScreenDelegate.PIXEL_WIDTH * charY)
|
||||
|
||||
for charX in 0..<7 {
|
||||
buffer![offsetLo + 6 - charX] = colorLo
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func getPixelOffset(charCellX: Int, charCellY: Int) -> CGPoint {
|
||||
return CGPoint(x: charCellX * 7, y: charCellY * 8)
|
||||
}
|
||||
|
||||
func getPixelOffset(memoryOffset: Int) -> CGPoint {
|
||||
//Offset is between 0x000 and 0x3FF.
|
||||
//If offset & 0x28, second batch.
|
||||
//If offset & 0x50, third batch.
|
||||
//Else, first batch.
|
||||
|
||||
var rowNumber = memoryOffset / 0x80
|
||||
let lowByte = memoryOffset & 0x0FF
|
||||
let cellX: Int
|
||||
|
||||
if(0x28 ... 0x4F ~= lowByte || 0xA8 ... 0xCF ~= lowByte) {
|
||||
//Middle third.
|
||||
rowNumber += 8
|
||||
cellX = (lowByte & ~(0x80)) - 0x28
|
||||
}
|
||||
else if(0x50 ... 0x77 ~= lowByte || 0xD0 ... 0xF7 ~= lowByte) {
|
||||
//Bottom third.
|
||||
rowNumber += 16
|
||||
cellX = (lowByte & ~(0x80)) - 0x50
|
||||
}
|
||||
else if(0x78 ... 0x7F ~= lowByte || 0xF8 ... 0xFF ~= lowByte) {
|
||||
//Discard.
|
||||
return CGPoint(x: -1, y: -1)
|
||||
}
|
||||
else {
|
||||
//Top third.
|
||||
rowNumber += 0
|
||||
cellX = (lowByte & ~(0x80))
|
||||
}
|
||||
|
||||
return getPixelOffset(charCellX: cellX, charCellY: rowNumber)
|
||||
}
|
||||
|
||||
/* Draw the screen. */
|
||||
func draw(_ layer: CALayer, in ctx: CGContext) {
|
||||
CVPixelBufferLockBaseAddress(pixels!, CVPixelBufferLockFlags.readOnly)
|
||||
|
50
FruitMachine/AppleII/Video/VideoHelpers.swift
Normal file
50
FruitMachine/AppleII/Video/VideoHelpers.swift
Normal file
@ -0,0 +1,50 @@
|
||||
//
|
||||
// VideoHelpers.swift
|
||||
// FruitMachine
|
||||
//
|
||||
// Created by Christopher Rohl on 8/2/17.
|
||||
// Copyright © 2017 Christopher Rohl. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
||||
extension AppleII {
|
||||
class VideoHelpers: NSObject {
|
||||
static func getPixelOffset(charCellX: Int, charCellY: Int) -> CGPoint {
|
||||
return CGPoint(x: charCellX * 7, y: charCellY * 8)
|
||||
}
|
||||
|
||||
static func getPixelOffset(memoryOffset: Int) -> CGPoint {
|
||||
//Offset is between 0x000 and 0x3FF.
|
||||
//If offset & 0x28, second batch.
|
||||
//If offset & 0x50, third batch.
|
||||
//Else, first batch.
|
||||
|
||||
var rowNumber = memoryOffset / 0x80
|
||||
let lowByte = memoryOffset & 0x0FF
|
||||
let cellX: Int
|
||||
|
||||
if(0x28 ... 0x4F ~= lowByte || 0xA8 ... 0xCF ~= lowByte) {
|
||||
//Middle third.
|
||||
rowNumber += 8
|
||||
cellX = (lowByte & ~(0x80)) - 0x28
|
||||
}
|
||||
else if(0x50 ... 0x77 ~= lowByte || 0xD0 ... 0xF7 ~= lowByte) {
|
||||
//Bottom third.
|
||||
rowNumber += 16
|
||||
cellX = (lowByte & ~(0x80)) - 0x50
|
||||
}
|
||||
else if(0x78 ... 0x7F ~= lowByte || 0xF8 ... 0xFF ~= lowByte) {
|
||||
//Discard.
|
||||
return CGPoint(x: -1, y: -1)
|
||||
}
|
||||
else {
|
||||
//Top third.
|
||||
rowNumber += 0
|
||||
cellX = (lowByte & ~(0x80))
|
||||
}
|
||||
|
||||
return getPixelOffset(charCellX: cellX, charCellY: rowNumber)
|
||||
}
|
||||
}
|
||||
}
|
@ -54,8 +54,17 @@ class AppleIIViewController: NSViewController {
|
||||
}
|
||||
|
||||
override func keyDown(with event: NSEvent) {
|
||||
let leftArrowKeyCode = 123
|
||||
let rightArrowKeyCode = 124
|
||||
|
||||
let c = returnChar(theEvent: event)
|
||||
|
||||
if(event.keyCode == leftArrowKeyCode) {
|
||||
computer.keyboardController.KEYBOARD = UInt8((0x08 | 0x80) & 0x000000FF)
|
||||
} else if(event.keyCode == rightArrowKeyCode) {
|
||||
computer.keyboardController.KEYBOARD = UInt8((0x15 | 0x80) & 0x000000FF)
|
||||
}
|
||||
|
||||
guard let ascii32 = c?.asciiValue else {
|
||||
return
|
||||
}
|
||||
|
33
FruitMachine/Common/Memory/ROMManager.swift
Normal file
33
FruitMachine/Common/Memory/ROMManager.swift
Normal file
@ -0,0 +1,33 @@
|
||||
//
|
||||
// HasROM.swift
|
||||
// FruitMachine
|
||||
//
|
||||
// Created by Christopher Rohl on 8/2/17.
|
||||
// Copyright © 2017 Christopher Rohl. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol HasROM {
|
||||
var romManager: ROMManager { get }
|
||||
}
|
||||
|
||||
protocol ROMDelegate {
|
||||
var ROM: [UInt8] { get }
|
||||
init(path: String, atAddress: UInt16, size: Int)
|
||||
}
|
||||
|
||||
class ROMManager: ROMDelegate {
|
||||
var ROM: [UInt8]
|
||||
|
||||
required init(path: String, atAddress: UInt16, size: Int) {
|
||||
ROM = [UInt8](repeating: 0xCC, count: size)
|
||||
|
||||
do {
|
||||
let fileContent: NSData = try NSData(contentsOfFile: path)
|
||||
fileContent.getBytes(&ROM, range: NSRange(location: Int(atAddress), length: size))
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
}
|
@ -37,7 +37,7 @@ final class MemoryInterface: NSObject {
|
||||
if(!bypassOverrides) {
|
||||
for override in read_overrides {
|
||||
if case override.rangeStart ... override.rangeEnd = offset {
|
||||
let readValue = override.action(CPU.sharedInstance, nil)
|
||||
let readValue = override.action(CPU.sharedInstance, offset, nil)
|
||||
if(!override.doRead) {
|
||||
return readValue!
|
||||
}
|
||||
@ -59,7 +59,7 @@ final class MemoryInterface: NSObject {
|
||||
if(!bypassOverrides) {
|
||||
for override in write_overrides {
|
||||
if case override.rangeStart ... override.rangeEnd = offset {
|
||||
_ = override.action(CPU.sharedInstance, value)
|
||||
_ = override.action(CPU.sharedInstance, offset, value)
|
||||
if(!override.doWrite) {
|
||||
return
|
||||
}
|
||||
|
@ -12,9 +12,9 @@ class MemoryOverride: NSObject {
|
||||
let rangeStart: UInt16
|
||||
let rangeEnd: UInt16
|
||||
|
||||
let action: (CPU, UInt8?) -> UInt8?
|
||||
let action: (CPU, UInt16, UInt8?) -> UInt8?
|
||||
|
||||
init(start: UInt16, end: UInt16, action: @escaping (AnyObject, UInt8?) -> UInt8?) {
|
||||
init(start: UInt16, end: UInt16, action: @escaping (AnyObject, UInt16, UInt8?) -> UInt8?) {
|
||||
rangeStart = start
|
||||
rangeEnd = end
|
||||
|
||||
|
@ -14,7 +14,7 @@ import Cocoa
|
||||
final class ReadOverride: MemoryOverride {
|
||||
let doRead: Bool //do we write anyway?
|
||||
|
||||
init(start: UInt16, end: UInt16, readAnyway: Bool, action: @escaping (AnyObject, UInt8?) -> UInt8?) {
|
||||
init(start: UInt16, end: UInt16, readAnyway: Bool, action: @escaping (AnyObject, UInt16, UInt8?) -> UInt8?) {
|
||||
doRead = readAnyway
|
||||
super.init(start: start, end: end, action: action)
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ import Cocoa
|
||||
final class WriteOverride: MemoryOverride {
|
||||
let doWrite: Bool //do we write anyway?
|
||||
|
||||
init(start: UInt16, end: UInt16, writeAnyway: Bool, action: @escaping (AnyObject, UInt8?) -> UInt8?) {
|
||||
init(start: UInt16, end: UInt16, writeAnyway: Bool, action: @escaping (AnyObject, UInt16, UInt8?) -> UInt8?) {
|
||||
doWrite = writeAnyway
|
||||
super.init(start: start, end: end, action: action)
|
||||
}
|
||||
|
@ -142,9 +142,6 @@ fileprivate func hex2bcd(hex: UInt8) -> UInt8 {
|
||||
final class Opcodes: NSObject {
|
||||
|
||||
static func _Add(state: CPU, operand: UInt8, isSubtract: Bool) {
|
||||
if((state.accumulator == 0xFF) && operand == 0x01 && state.status_register.carry == false) {
|
||||
_ = 1
|
||||
}
|
||||
var t16: UInt16 = UInt16(state.accumulator) &+ UInt16(operand) + UInt16((state.status_register.carry ? UInt8(1) : UInt8(0)))
|
||||
let t8: UInt8 = UInt8(t16 & 0xFF)
|
||||
|
||||
|
@ -32,12 +32,12 @@
|
||||
<tabViewItems>
|
||||
<tabViewItem label="General" identifier="1" id="nQU-pA-pvF">
|
||||
<view key="view" id="iK8-x4-ay0">
|
||||
<rect key="frame" x="10" y="33" width="137" height="0.0"/>
|
||||
<rect key="frame" x="10" y="33" width="554" height="208"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
</view>
|
||||
</tabViewItem>
|
||||
<tabViewItem label="Paths" identifier="2" id="zXY-01-Th8">
|
||||
<view key="view" ambiguous="YES" id="tiQ-eh-pdD">
|
||||
<view key="view" id="tiQ-eh-pdD">
|
||||
<rect key="frame" x="10" y="33" width="554" height="208"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
@ -131,6 +131,18 @@
|
||||
</subviews>
|
||||
</view>
|
||||
</tabViewItem>
|
||||
<tabViewItem label="Apple I" identifier="" id="0ak-CP-2BL">
|
||||
<view key="view" id="BGQ-27-4EP">
|
||||
<rect key="frame" x="10" y="33" width="554" height="208"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
</view>
|
||||
</tabViewItem>
|
||||
<tabViewItem label="Apple II" identifier="" id="aVa-m9-VEl">
|
||||
<view key="view" ambiguous="YES" id="mjS-Jn-KXO">
|
||||
<rect key="frame" x="10" y="33" width="554" height="208"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
</view>
|
||||
</tabViewItem>
|
||||
</tabViewItems>
|
||||
</tabView>
|
||||
</subviews>
|
||||
|
Loading…
Reference in New Issue
Block a user