graphics... sort of

This commit is contained in:
Luigi Thirty 2017-07-27 19:22:13 -04:00
parent dd8301ccab
commit 0c75e6f75e
18 changed files with 316 additions and 76 deletions

View File

@ -7,10 +7,14 @@
objects = {
/* Begin PBXBuildFile section */
2A2126841F2A9FA300E43DC1 /* DebuggerWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A2126831F2A9FA300E43DC1 /* DebuggerWindowController.swift */; };
2A22EBFB1F21A7A700A36A61 /* IntegerExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A22EBFA1F21A7A700A36A61 /* IntegerExtensions.swift */; };
2A5BC5191F29A28D008C03BE /* AppleScreenView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A5BC5181F29A28D008C03BE /* AppleScreenView.swift */; };
2A5BC51C1F29A2EB008C03BE /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2A5BC51B1F29A2EB008C03BE /* QuartzCore.framework */; };
2A5BC51E1F29A4C3008C03BE /* AppleScreenViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A5BC51D1F29A4C3008C03BE /* AppleScreenViewDelegate.swift */; };
2AA8B5F81F2A8889002B350F /* AppleI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AA8B5F71F2A8889002B350F /* AppleI.swift */; };
2AA8B5FC1F2A8EAD002B350F /* Terminal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AA8B5FB1F2A8EAD002B350F /* Terminal.swift */; };
2AA8B5FE1F2A942C002B350F /* PIAOverrides.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AA8B5FD1F2A942C002B350F /* PIAOverrides.swift */; };
2AD458CE1F205EB700F05121 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458CD1F205EB700F05121 /* AppDelegate.swift */; };
2AD458D01F205EB700F05121 /* DebuggerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458CF1F205EB700F05121 /* DebuggerViewController.swift */; };
2AD458D21F205EB700F05121 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2AD458D11F205EB700F05121 /* Assets.xcassets */; };
@ -31,10 +35,14 @@
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
2A2126831F2A9FA300E43DC1 /* DebuggerWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebuggerWindowController.swift; sourceTree = "<group>"; };
2A22EBFA1F21A7A700A36A61 /* IntegerExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegerExtensions.swift; sourceTree = "<group>"; };
2A5BC5181F29A28D008C03BE /* AppleScreenView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleScreenView.swift; sourceTree = "<group>"; };
2A5BC51B1F29A2EB008C03BE /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
2A5BC51D1F29A4C3008C03BE /* AppleScreenViewDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleScreenViewDelegate.swift; sourceTree = "<group>"; };
2AA8B5F71F2A8889002B350F /* AppleI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleI.swift; sourceTree = "<group>"; };
2AA8B5FB1F2A8EAD002B350F /* Terminal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Terminal.swift; sourceTree = "<group>"; };
2AA8B5FD1F2A942C002B350F /* PIAOverrides.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PIAOverrides.swift; sourceTree = "<group>"; };
2AD458CA1F205EB700F05121 /* FruitMachine.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FruitMachine.app; sourceTree = BUILT_PRODUCTS_DIR; };
2AD458CD1F205EB700F05121 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
2AD458CF1F205EB700F05121 /* DebuggerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebuggerViewController.swift; sourceTree = "<group>"; };
@ -77,6 +85,17 @@
name = Frameworks;
sourceTree = "<group>";
};
2AA8B5F61F2A8844002B350F /* AppleI */ = {
isa = PBXGroup;
children = (
2AE42E411F28663600C4900E /* Video */,
2A5BC5181F29A28D008C03BE /* AppleScreenView.swift */,
2A5BC51D1F29A4C3008C03BE /* AppleScreenViewDelegate.swift */,
2AA8B5F71F2A8889002B350F /* AppleI.swift */,
);
path = AppleI;
sourceTree = "<group>";
};
2AD458C11F205EB700F05121 = {
isa = PBXGroup;
children = (
@ -97,11 +116,9 @@
2AD458CC1F205EB700F05121 /* FruitMachine */ = {
isa = PBXGroup;
children = (
2AA8B5F61F2A8844002B350F /* AppleI */,
2AD458DD1F205F0D00F05121 /* M6502 */,
2AE42E411F28663600C4900E /* Video */,
2AD458CD1F205EB700F05121 /* AppDelegate.swift */,
2A5BC5181F29A28D008C03BE /* AppleScreenView.swift */,
2A5BC51D1F29A4C3008C03BE /* AppleScreenViewDelegate.swift */,
2AE42E381F28628300C4900E /* MainViewController.swift */,
2AE42E3F1F28638100C4900E /* FruitMachine.storyboard */,
2AD458D11F205EB700F05121 /* Assets.xcassets */,
@ -139,6 +156,7 @@
children = (
2AD458D31F205EB700F05121 /* Debugger.storyboard */,
2AD458CF1F205EB700F05121 /* DebuggerViewController.swift */,
2A2126831F2A9FA300E43DC1 /* DebuggerWindowController.swift */,
2AD6D5831F26E6BF008F3CF5 /* DebuggerCommands.swift */,
2AE5BA031F23DE4400FAA343 /* Disassembly.swift */,
);
@ -167,6 +185,8 @@
isa = PBXGroup;
children = (
2AE42E421F28665300C4900E /* CharacterGenerator.swift */,
2AA8B5FB1F2A8EAD002B350F /* Terminal.swift */,
2AA8B5FD1F2A942C002B350F /* PIAOverrides.swift */,
);
path = Video;
sourceTree = "<group>";
@ -242,8 +262,10 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
2A2126841F2A9FA300E43DC1 /* DebuggerWindowController.swift in Sources */,
2AD458E31F20661300F05121 /* CPUInstructions.swift in Sources */,
2AD458D01F205EB700F05121 /* DebuggerViewController.swift in Sources */,
2AA8B5FC1F2A8EAD002B350F /* Terminal.swift in Sources */,
2A5BC51E1F29A4C3008C03BE /* AppleScreenViewDelegate.swift in Sources */,
2AD458CE1F205EB700F05121 /* AppDelegate.swift in Sources */,
2AE42E431F28665300C4900E /* CharacterGenerator.swift in Sources */,
@ -254,10 +276,12 @@
2AE42E3A1F28628300C4900E /* MainViewController.swift in Sources */,
2AD458E51F2070DF00F05121 /* Opcodes.swift in Sources */,
2AE42E081F2850F400C4900E /* ReadOverride.swift in Sources */,
2AA8B5FE1F2A942C002B350F /* PIAOverrides.swift in Sources */,
2AE5BA061F2469EB00FAA343 /* AddressConversions.swift in Sources */,
2AE42E0A1F28521E00C4900E /* WriteOverride.swift in Sources */,
2A5BC5191F29A28D008C03BE /* AppleScreenView.swift in Sources */,
2AD458E11F2064CB00F05121 /* MemoryInterface.swift in Sources */,
2AA8B5F81F2A8889002B350F /* AppleI.swift in Sources */,
2AD458DF1F205F4500F05121 /* CPU.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;

View File

@ -10,6 +10,7 @@ import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
let AppleScreenNotifications = Notification.Name("com.luigithirty.appleScreenNotifications")
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
@ -19,5 +20,12 @@ class AppDelegate: NSObject, NSApplicationDelegate {
// Insert code here to tear down your application
}
@IBAction func view_scale_1x(_ sender: Any) {
NotificationCenter.default.post(Notification(name: AppleScreenNotifications, object: "scaleFactor", userInfo: ["scaleFactor": 1]))
}
@IBAction func view_scale_2x(_ sender: Any) {
NotificationCenter.default.post(Notification(name: AppleScreenNotifications, object: "scaleFactor", userInfo: ["scaleFactor": 2]))
}
}

View File

@ -0,0 +1,67 @@
//
// AppleI.swift
// FruitMachine
//
// Created by Christopher Rohl on 7/27/17.
// Copyright © 2017 Christopher Rohl. All rights reserved.
//
import Cocoa
class AppleI: NSObject {
static let sharedInstance = AppleI()
let cg = CharacterGenerator(romPath: "/Users/luigi/apple1/apple1.vid");
let terminal = Terminal()
let emulatorViewDelegate = AppleScreenViewDelegate()
let emulatorView = AppleScreenView(frame: NSMakeRect(0, 0, 400, 384))
let emuScreenLayer = CALayer()
static let CPU_FREQUENCY = 1000000
static let FRAMES_PER_SECOND = 60
static let CYCLES_PER_BATCH = CPU_FREQUENCY / FRAMES_PER_SECOND
override init() {
super.init()
emulatorView.wantsLayer = true
emuScreenLayer.delegate = emulatorViewDelegate
emuScreenLayer.frame = emulatorView.bounds
emuScreenLayer.setNeedsDisplay()
emulatorView.layer?.addSublayer(emuScreenLayer)
installOverrides()
for (cellNum, character) in terminal.characters.enumerated() {
emulatorViewDelegate.putCharacterPixels(charPixels: cg.getCharacterPixels(charIndex: character), pixelPosition: emulatorViewDelegate.getPixelOffset(charCellIndex: cellNum))
}
CPU.sharedInstance.memoryInterface.loadBinary(path: "/Users/luigi/apple1/apple1.rom", offset: 0xFF00)
CPU.sharedInstance.performReset()
}
func installOverrides() {
CPU.sharedInstance.memoryInterface.write_overrides.append(PIAOverrides.writeDSP)
CPU.sharedInstance.memoryInterface.read_overrides.append(PIAOverrides.readDSP)
}
func runFrame() {
CPU.sharedInstance.cycles = 0
CPU.sharedInstance.cyclesInBatch = AppleI.CYCLES_PER_BATCH
CPU.sharedInstance.runCyclesBatch()
//update the video display
for (cellNum, character) in terminal.characters.enumerated() {
if(character == 0x8D) //CR
{
continue //ignore for now
}
emulatorViewDelegate.putCharacterPixels(charPixels: cg.getCharacterPixels(charIndex: character), pixelPosition: emulatorViewDelegate.getPixelOffset(charCellIndex: cellNum))
}
emulatorView.display()
}
}

View File

@ -10,10 +10,6 @@ import Cocoa
class AppleScreenView: NSView {
//In characters
static let TERMINAL_WIDTH = 40
static let TERMINAL_HEIGHT = 24
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
// Drawing code here.

View File

@ -52,7 +52,7 @@ class AppleScreenViewDelegate: NSObject, CALayerDelegate {
for charY in 0..<CharacterGenerator.CHAR_HEIGHT {
for charX in 0..<CharacterGenerator.CHAR_WIDTH {
indexedPixels[baseOffset + (PIXEL_WIDTH * charY) + CharacterGenerator.CHAR_WIDTH - charX] = (charPixels[charY] & UInt8(1 << charX)) > 0 ? 1 : 0
indexedPixels[baseOffset + (PIXEL_WIDTH * charY) + CharacterGenerator.CHAR_WIDTH - charX - 1] = (charPixels[charY] & UInt8(1 << charX)) > 0 ? 1 : 0
}
}
}
@ -61,6 +61,10 @@ class AppleScreenViewDelegate: NSObject, CALayerDelegate {
return CGPoint(x: charCellX * 5, y: charCellY * 8)
}
func getPixelOffset(charCellIndex: Int) -> CGPoint {
return getPixelOffset(charCellX: charCellIndex % Terminal.CELLS_WIDTH, charCellY: charCellIndex / Terminal.CELLS_WIDTH)
}
/* Draw the screen. */
func draw(_ layer: CALayer, in ctx: CGContext) {
let bounds = layer.bounds
@ -70,8 +74,8 @@ class AppleScreenViewDelegate: NSObject, CALayerDelegate {
let pixelProvider = CGDataProvider(data: NSData(bytes: &pixels, length: pixels.count * MemoryLayout<PixelData>.size))
let renderedImage = CGImage(width: PIXEL_WIDTH, height: PIXEL_HEIGHT, bitsPerComponent: Int(bitsPerComponent), bitsPerPixel: Int(bitsPerPixel), bytesPerRow: PIXEL_WIDTH * Int(MemoryLayout<PixelData>.size), space: colorSpace, bitmapInfo: bitmapInfo, provider: pixelProvider!, decode: nil, shouldInterpolate: true, intent: CGColorRenderingIntent.defaultIntent)
ctx.draw(renderedImage!, in: bounds)
//draw stuff here
}
}

View File

@ -35,8 +35,26 @@ class CharacterGenerator: NSObject {
func getCharacterPixels(charIndex: UInt8) -> [UInt8] {
var pixelArray = [UInt8](repeating: 0x00, count: CharacterGenerator.CHAR_HEIGHT)
/* Instead of ignoring ASCII bit b6, we ignore bit b5. At the same time ASCII bit b6 must be inverted before it is fed to the character ROM. This way the entire character range from $40 to $7F will end up in the range $00 to $1F (twice of course). Now lower case characters are automatically translated into their corresponding upper case bit maps.
*/
var convertedCharIndex = charIndex & 0x7F
convertedCharIndex = convertedCharIndex & ~(0x20)
convertedCharIndex = convertedCharIndex & ~(0x40)
/*
if((convertedCharIndex & 0x40) == 0x40)
{
convertedCharIndex = convertedCharIndex & ~(0x40)
}
else
{
convertedCharIndex = convertedCharIndex | 0x40
}
*/
for scanlineIndex in 0..<CharacterGenerator.CHAR_HEIGHT {
pixelArray[scanlineIndex] = ROM[scanlineIndex + (Int(charIndex) * CharacterGenerator.CHAR_HEIGHT)]
pixelArray[scanlineIndex] = ROM[scanlineIndex + (Int(convertedCharIndex) * CharacterGenerator.CHAR_HEIGHT)]
}
return pixelArray

View File

@ -0,0 +1,23 @@
//
// Overrides.swift
// FruitMachine
//
// Created by Christopher Rohl on 7/27/17.
// Copyright © 2017 Christopher Rohl. All rights reserved.
//
import Cocoa
class PIAOverrides: NSObject {
static let writeDSP = WriteOverride(start: 0xD012, end: 0xD012, writeValue: false, action: PIAOverrides.actionWriteDSP)
static func actionWriteDSP(terminal: AnyObject, byte: UInt8?) -> Void {
//(terminal as! Terminal).putCharacter(charIndex: byte!)
AppleI.sharedInstance.terminal.putCharacter(charIndex: byte!)
}
static let readDSP = ReadOverride(start: 0xD012, end: 0xD012, writeValue: false, action: PIAOverrides.actionReadDSP)
static func actionReadDSP(terminal: AnyObject, byte: UInt8?) -> Void {
CPU.sharedInstance.memoryInterface.writeByte(offset: 0xD012, value: CPU.sharedInstance.memoryInterface.readByte(offset: 0xD012, bypassOverrides: true) & 0x7F, bypassOverrides: true) //the display is always ready
}
}

View File

@ -0,0 +1,47 @@
//
// Terminal.swift
// FruitMachine
//
// Created by Christopher Rohl on 7/27/17.
// Copyright © 2017 Christopher Rohl. All rights reserved.
//
import Cocoa
struct Cell {
var x: Int
var y: Int
}
class Terminal: NSObject {
static let CELLS_WIDTH = 40
static let CELLS_HEIGHT = 24
var cursorPosition: Cell
var characters: [UInt8]
override init() {
cursorPosition = Cell(x: 0, y: 0)
characters = [UInt8](repeating: 0x40, count: Terminal.CELLS_WIDTH * Terminal.CELLS_HEIGHT)
}
func cellToIndex(cell: Cell) -> Int {
return (cell.y * Terminal.CELLS_WIDTH) + (cell.x % Terminal.CELLS_WIDTH)
}
func putCharacter(charIndex: UInt8) {
characters[cellToIndex(cell: cursorPosition)] = charIndex
advanceCursor()
}
func advanceCursor() {
cursorPosition.x += 1
if(cursorPosition.x == Terminal.CELLS_WIDTH) {
cursorPosition.x = 0
cursorPosition.y += 1
if(cursorPosition.y == Terminal.CELLS_HEIGHT) {
cursorPosition.y = 0 //TODO: scrolling
}
}
}
}

View File

@ -629,6 +629,17 @@
<action selector="toggleFullScreen:" target="Ady-hI-5gd" id="dU3-MA-1Rq"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="Lvb-d5-deQ"/>
<menuItem title="Scale 1x" keyEquivalent="1" id="nfL-VA-aet">
<connections>
<action selector="view_scale_1x:" target="Voe-Tx-rLC" id="QA5-yc-5zm"/>
</connections>
</menuItem>
<menuItem title="Scale 2x" keyEquivalent="2" id="FYi-S6-fCx">
<connections>
<action selector="view_scale_2x:" target="Voe-Tx-rLC" id="rxd-VR-X3F"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>

View File

@ -116,7 +116,9 @@ class CPU: NSObject {
let RESET_VECTOR: UInt16 = 0xFFFC
let IRQ_VECTOR: UInt16 = 0xFFFE
static var sharedInstance = CPU()
static let sharedInstance = CPU()
var isRunning: Bool
var cycles: Int
var cyclesInBatch: Int
@ -138,6 +140,8 @@ class CPU: NSObject {
var breakpoints: [UInt16]
override init() {
isRunning = false
cycles = 0
cyclesInBatch = 0
@ -216,7 +220,7 @@ class CPU: NSObject {
}
}
func checkOutOfCycles() -> Bool {
func outOfCycles() -> Bool {
if(cycles > cyclesInBatch) {
return true
} else {
@ -238,4 +242,28 @@ class CPU: NSObject {
status_register.zero = (value == 0)
}
/* Running */
func cpuStep() {
do {
try executeNextInstruction()
} catch CPUExceptions.invalidInstruction {
isRunning = false
} catch {
print(error)
}
}
func runCyclesBatch() {
isRunning = true
while(!outOfCycles() && isRunning) {
cpuStep()
if (breakpoints.contains(program_counter)) {
isRunning = false
}
}
}
}

View File

@ -9,7 +9,7 @@
<!--Window Controller-->
<scene sceneID="R2V-B0-nI4">
<objects>
<windowController id="B8D-0N-5wS" sceneMemberID="viewController">
<windowController id="B8D-0N-5wS" customClass="DebuggerWindowController" customModule="FruitMachine" customModuleProvider="target" sceneMemberID="viewController">
<window key="window" title="Debugger" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="IQv-IB-iLA">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>

View File

@ -46,7 +46,7 @@ class DebuggerViewController: NSViewController {
text_CPU_SR.stringValue = String(format:"%02X", cpuInstance.stack_pointer)
text_CPU_Flags.stringValue = String(cpuInstance.status_register.asString())
disassembly = cpuInstance.disassemble(fromAddress: 0, length: 65535)
disassembly = cpuInstance.disassemble(fromAddress: CPU.sharedInstance.program_counter, length: 256)
highlightCurrentInstruction()
}
@ -56,15 +56,10 @@ class DebuggerViewController: NSViewController {
debuggerTableView.delegate = self
debuggerTableView.dataSource = self
cpuInstance.memoryInterface.loadBinary(path: "/Users/luigi/6502/test.bin")
cpuInstance.performReset()
cpuInstance.program_counter = 0x400 //entry point for the test program
updateCPUStatusFields()
disassembly = cpuInstance.disassemble(fromAddress: 0, length: 65535)
disassembly = cpuInstance.disassemble(fromAddress: CPU.sharedInstance.program_counter, length: 256)
debuggerTableView.reloadData()
cpuInstance.breakpoints.append(0x34E8) //failing at $34FD SBC test
// Do any additional setup after loading the view.
}
@ -74,25 +69,14 @@ class DebuggerViewController: NSViewController {
}
}
func cpuStep() {
do {
try cpuInstance.executeNextInstruction()
} catch CPUExceptions.invalidInstruction {
isRunning = false
} catch {
print(error)
}
}
func cpuRun() {
func debugRun() {
isRunning = true
cpuInstance.cycles = 0
cpuInstance.cyclesInBatch = 1000000
while(!cpuInstance.checkOutOfCycles() && isRunning) {
cpuStep()
while(!cpuInstance.outOfCycles() && isRunning) {
cpuInstance.cpuStep()
if (cpuInstance.breakpoints.contains(cpuInstance.program_counter)) {
isRunning = false
@ -105,12 +89,12 @@ class DebuggerViewController: NSViewController {
func queueCPUStep(queue: DispatchQueue) {
queue.async {
self.cpuStep()
self.cpuInstance.cpuStep()
}
}
@IBAction func btn_CPUStep(_ sender: Any) {
cpuStep()
cpuInstance.cpuStep()
updateCPUStatusFields()
}
@ -120,7 +104,7 @@ class DebuggerViewController: NSViewController {
}
@IBAction func btn_CPURun(_ sender: Any) {
cpuRun()
debugRun()
}
@IBAction func btn_CPU_Restart(_ sender: Any) {
@ -155,6 +139,11 @@ extension DebuggerViewController: NSTableViewDelegate {
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
var cellText: String = ""
var cellIdentifier: String = ""
if(row >= disassembly.count) {
return nil //no cell
}
let operation = disassembly[row]
if(tableColumn == tableView.tableColumns[0]) {

View File

@ -0,0 +1,19 @@
//
// DebuggerWindowController.swift
// FruitMachine
//
// Created by Christopher Rohl on 7/27/17.
// Copyright © 2017 Christopher Rohl. All rights reserved.
//
import Cocoa
class DebuggerWindowController: NSWindowController {
override func windowDidLoad() {
super.windowDidLoad()
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
}
}

View File

@ -74,7 +74,7 @@ extension CPU {
var disassembly: [Disassembly] = [Disassembly]()
var currentAddress: UInt16 = fromAddress
let endAddress: UInt16 = fromAddress + length
let endAddress: UInt16 = max(fromAddress &+ length, 0xFFFF)
while(currentAddress < endAddress) {
let instruction = memoryInterface.readByte(offset: currentAddress)

View File

@ -21,10 +21,13 @@ class MemoryInterface: NSObject {
write_overrides = [WriteOverride]()
}
func readByte(offset: UInt16) -> UInt8 {
for override in read_overrides {
if case override.rangeStart ... override.rangeEnd = offset {
override.action(CPU.sharedInstance, nil)
func readByte(offset: UInt16, bypassOverrides: Bool = false) -> UInt8 {
if(!bypassOverrides) {
for override in read_overrides {
if case override.rangeStart ... override.rangeEnd = offset {
override.action(CPU.sharedInstance, nil)
}
}
}
@ -32,10 +35,16 @@ class MemoryInterface: NSObject {
return memory[Int(offset)]
}
func writeByte(offset: UInt16, value: UInt8) {
for override in read_overrides {
if case override.rangeStart ... override.rangeEnd = offset {
override.action(CPU.sharedInstance, value)
func writeByte(offset: UInt16, value: UInt8, bypassOverrides: Bool = false) {
if(!bypassOverrides) {
for override in write_overrides {
if case override.rangeStart ... override.rangeEnd = offset {
override.action(CPU.sharedInstance, value)
if(!override.writeValue) {
return
}
}
}
}
@ -48,10 +57,10 @@ class MemoryInterface: NSObject {
return (UInt16(high) << 8) | UInt16(low)
}
func loadBinary(path: String) {
func loadBinary(path: String, offset: UInt16) {
do {
let fileContent: NSData = try NSData(contentsOfFile: path)
fileContent.getBytes(&memory, range: NSRange(location: 0, length: 65536))
fileContent.getBytes(&memory[Int(offset)], range: NSRange(location: 0, length: 256))
} catch {
print(error)
}

View File

@ -11,12 +11,14 @@ import Cocoa
class MemoryOverride: NSObject {
let rangeStart: UInt16
let rangeEnd: UInt16
let writeValue: Bool
let action: (CPU, UInt8?) -> Void
init(start: UInt16, end: UInt16, action: @escaping (CPU, UInt8?) -> Void) {
init(start: UInt16, end: UInt16, writeValue: Bool, action: @escaping (AnyObject, UInt8?) -> Void) {
rangeStart = start
rangeEnd = end
self.writeValue = writeValue
self.action = action
}

View File

@ -10,36 +10,23 @@ import Cocoa
import CoreGraphics
class MainViewController: NSViewController {
var windowController: NSWindowController?
var debuggerViewController = DebuggerViewController()
let emuScreenLayer = CALayer()
let cg = CharacterGenerator(romPath: "/Users/luigi/apple1/apple1.vid");
var appleScreenView: AppleScreenView = AppleScreenView(frame: NSMakeRect(0, 0, 400, 384))
let appleScreenViewDelegate = AppleScreenViewDelegate()
let computer = AppleI.sharedInstance
var debuggerWindowController: DebuggerWindowController!
override func viewDidLoad() {
super.viewDidLoad()
let debuggerStoryboard = NSStoryboard(name: NSStoryboard.Name(rawValue: "Debugger"), bundle: nil)
debuggerWindowController = debuggerStoryboard.instantiateInitialController() as! DebuggerWindowController
debuggerWindowController.showWindow(self)
// Do view setup here.
self.view.addSubview(appleScreenView)
self.view.addSubview(computer.emulatorView)
computer.emulatorView.display()
appleScreenView.wantsLayer = true
emuScreenLayer.delegate = appleScreenViewDelegate
emuScreenLayer.frame = appleScreenView.bounds
emuScreenLayer.setNeedsDisplay()
appleScreenView.layer?.addSublayer(emuScreenLayer)
appleScreenViewDelegate.putCharacterPixels(charPixels: cg.getCharacterPixels(charIndex: 0x00), pixelPosition: appleScreenViewDelegate.getPixelOffset(charCellX: 0, charCellY: 0))
appleScreenViewDelegate.putCharacterPixels(charPixels: cg.getCharacterPixels(charIndex: 0x01), pixelPosition: appleScreenViewDelegate.getPixelOffset(charCellX: 1, charCellY: 1))
appleScreenViewDelegate.putCharacterPixels(charPixels: cg.getCharacterPixels(charIndex: 0x02), pixelPosition: appleScreenViewDelegate.getPixelOffset(charCellX: 2, charCellY: 2))
appleScreenViewDelegate.putCharacterPixels(charPixels: cg.getCharacterPixels(charIndex: 0x03), pixelPosition: appleScreenViewDelegate.getPixelOffset(charCellX: 3, charCellY: 3))
appleScreenViewDelegate.putCharacterPixels(charPixels: cg.getCharacterPixels(charIndex: 0x04), pixelPosition: appleScreenViewDelegate.getPixelOffset(charCellX: 4, charCellY: 4))
appleScreenViewDelegate.putCharacterPixels(charPixels: cg.getCharacterPixels(charIndex: 0x05), pixelPosition: appleScreenViewDelegate.getPixelOffset(charCellX: 5, charCellY: 5))
appleScreenViewDelegate.putCharacterPixels(charPixels: cg.getCharacterPixels(charIndex: 0x06), pixelPosition: appleScreenViewDelegate.getPixelOffset(charCellX: 6, charCellY: 6))
appleScreenViewDelegate.putCharacterPixels(charPixels: cg.getCharacterPixels(charIndex: 0x07), pixelPosition: appleScreenViewDelegate.getPixelOffset(charCellX: 7, charCellY: 7))
appleScreenViewDelegate.putCharacterPixels(charPixels: cg.getCharacterPixels(charIndex: 0x08), pixelPosition: appleScreenViewDelegate.getPixelOffset(charCellX: 8, charCellY: 8))
appleScreenView.display()
computer.runFrame()
}
}

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="13168.3" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13168.3"/>
</dependencies>
<scenes/>
</document>