it runs Integer BASIC! (but can't load cassettes so it's just hardcoded to load it at $E000)

This commit is contained in:
Luigi Thirty 2017-07-29 22:48:37 -04:00
parent 76e8801611
commit 447b39a2d0
8 changed files with 54 additions and 25 deletions

View File

@ -23,7 +23,7 @@ class AppleI: NSObject {
]
let emulatorViewDelegate = AppleScreenViewDelegate()
let emulatorView = AppleScreenView(frame: NSMakeRect(0, 0, 400, 384))
let emulatorView = AppleScreenView(frame: NSMakeRect(0, 0, 640, 384))
let emuScreenLayer = CALayer()
static let CPU_FREQUENCY = 1000000
@ -49,7 +49,8 @@ class AppleI: NSObject {
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.memoryInterface.loadBinary(path: "/Users/luigi/apple1/apple1.rom", offset: 0xFF00, length: 0x100)
CPU.sharedInstance.memoryInterface.loadBinary(path: "/Users/luigi/apple1/basic.bin", offset: 0xE000, length: 0x1000)
CPU.sharedInstance.performReset()
}

View File

@ -9,8 +9,8 @@
import Cocoa
class AppleScreenViewDelegate: NSObject, CALayerDelegate {
let PIXEL_WIDTH = 200
let PIXEL_HEIGHT = 192
static let PIXEL_WIDTH = 320
static let PIXEL_HEIGHT = 192
/* Pixel data stuff. */
struct PixelData {
@ -19,6 +19,7 @@ class AppleScreenViewDelegate: NSObject, CALayerDelegate {
var g: UInt8
var b: UInt8
}
let bitsPerComponent: UInt = 8
let bitsPerPixel: UInt = 32
let colorSpace = CGColorSpaceCreateDeviceRGB()
@ -28,17 +29,17 @@ class AppleScreenViewDelegate: NSObject, CALayerDelegate {
var indexedPixels: [UInt8]
var colorValues: [PixelData]
var rgbPixels = [PixelData](repeating: PixelData(a: 255, r: 0, g: 0, b: 0), count: AppleScreenViewDelegate.PIXEL_WIDTH*AppleScreenViewDelegate.PIXEL_HEIGHT)
override init()
{
indexedPixels = [UInt8](repeating: 0x00, count: 200*192)
indexedPixels = [UInt8](repeating: 0x00, count: AppleScreenViewDelegate.PIXEL_WIDTH*AppleScreenViewDelegate.PIXEL_HEIGHT)
colorValues = [PixelData](repeating: PixelData(a: 255, r: 0, g: 0, b: 0), count: 256)
colorValues[1] = PixelData(a: 0, r: 200, g: 200, b: 200
)
}
func convertIndexedPixelsToRGB(pixels: [UInt8]) -> [PixelData] {
var rgbPixels = [PixelData](repeating: PixelData(a: 255, r: 0, g: 0, b: 0), count: 200*192)
for (num, colorIndex) in pixels.enumerated() {
rgbPixels[num] = colorValues[Int(colorIndex)]
}
@ -48,17 +49,18 @@ class AppleScreenViewDelegate: NSObject, CALayerDelegate {
func putCharacterPixels(charPixels: [UInt8], pixelPosition: CGPoint) {
//Calculate the offset to reach the desired position.
let baseOffset = (Int(pixelPosition.y) * PIXEL_WIDTH) + Int(pixelPosition.x)
let baseOffset = (Int(pixelPosition.y) * AppleScreenViewDelegate.PIXEL_WIDTH) + Int(pixelPosition.x)
for charY in 0..<CharacterGenerator.CHAR_HEIGHT {
for charX in 0..<CharacterGenerator.CHAR_WIDTH {
indexedPixels[baseOffset + (PIXEL_WIDTH * charY) + CharacterGenerator.CHAR_WIDTH - charX - 1] = (charPixels[charY] & UInt8(1 << charX)) > 0 ? 1 : 0
//for charX in 0..<CharacterGenerator.CHAR_WIDTH {
for charX in 0..<8 {
indexedPixels[baseOffset + (AppleScreenViewDelegate.PIXEL_WIDTH * charY) + 7 - charX] = (charPixels[charY] & UInt8(1 << charX)) > 0 ? 1 : 0
}
}
}
func getPixelOffset(charCellX: Int, charCellY: Int) -> CGPoint {
return CGPoint(x: charCellX * 5, y: charCellY * 8)
return CGPoint(x: charCellX * 8, y: charCellY * 8)
}
func getPixelOffset(charCellIndex: Int) -> CGPoint {
@ -68,12 +70,21 @@ class AppleScreenViewDelegate: NSObject, CALayerDelegate {
/* Draw the screen. */
func draw(_ layer: CALayer, in ctx: CGContext) {
let bounds = layer.bounds
ctx.interpolationQuality = CGInterpolationQuality.none
var pixels = convertIndexedPixelsToRGB(pixels: indexedPixels)
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)
let renderedImage = CGImage(width: AppleScreenViewDelegate.PIXEL_WIDTH,
height: AppleScreenViewDelegate.PIXEL_HEIGHT,
bitsPerComponent: Int(bitsPerComponent),
bitsPerPixel: Int(bitsPerPixel),
bytesPerRow: AppleScreenViewDelegate.PIXEL_WIDTH * Int(MemoryLayout<PixelData>.size),
space: colorSpace,
bitmapInfo: bitmapInfo,
provider: pixelProvider!,
decode: nil,
shouldInterpolate: false,
intent: CGColorRenderingIntent.defaultIntent)
ctx.draw(renderedImage!, in: bounds)
}

View File

@ -16,6 +16,7 @@ struct Cell {
class Terminal: NSObject {
static let CELLS_WIDTH = 40
static let CELLS_HEIGHT = 24
static let CELLS_COUNT = CELLS_WIDTH * CELLS_HEIGHT
var cursorPosition: Cell
var characters: [UInt8]
@ -45,8 +46,9 @@ class Terminal: NSObject {
if(cursorPosition.x == Terminal.CELLS_WIDTH) {
cursorPosition.x = 0
cursorPosition.y += 1
if(cursorPosition.y == Terminal.CELLS_HEIGHT) {
cursorPosition.y = 0 //TODO: scrolling
if(cursorPosition.y >= Terminal.CELLS_HEIGHT) {
cursorPosition.y = Terminal.CELLS_HEIGHT - 1
scrollUp(lines: 1)
}
}
}
@ -54,8 +56,15 @@ class Terminal: NSObject {
func carriageReturn() {
cursorPosition.x = 0
cursorPosition.y += 1
if(cursorPosition.y == Terminal.CELLS_HEIGHT) {
cursorPosition.y = 0
if(cursorPosition.y >= Terminal.CELLS_HEIGHT) {
cursorPosition.y = Terminal.CELLS_HEIGHT - 1
scrollUp(lines: 1)
}
}
func scrollUp(lines: Int) {
let scrolled = characters[Terminal.CELLS_WIDTH ..< Terminal.CELLS_COUNT]
characters = [UInt8](scrolled)
characters.append(contentsOf: [UInt8](repeating: 0x00, count: Terminal.CELLS_WIDTH))
}
}

View File

@ -698,7 +698,7 @@
<windowController id="0Wh-dg-gsU" sceneMemberID="viewController">
<window key="window" title="Fruit Machine" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" frameAutosaveName="" animationBehavior="default" id="O0r-h6-7La">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<rect key="contentRect" x="293" y="264" width="480" height="360"/>
<rect key="contentRect" x="293" y="264" width="640" height="360"/>
<rect key="screenRect" x="0.0" y="0.0" width="1916" height="936"/>
<connections>
<outlet property="delegate" destination="0Wh-dg-gsU" id="tmJ-Ae-YJP"/>
@ -717,7 +717,7 @@
<objects>
<viewController id="gw1-M7-9Je" customClass="MainViewController" customModule="FruitMachine" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" id="DiY-xb-Usb">
<rect key="frame" x="0.0" y="0.0" width="400" height="384"/>
<rect key="frame" x="0.0" y="0.0" width="640" height="384"/>
<autoresizingMask key="autoresizingMask"/>
</view>
</viewController>

View File

@ -47,6 +47,7 @@ class DebuggerViewController: NSViewController {
text_CPU_Flags.stringValue = String(cpuInstance.status_register.asString())
disassembly = cpuInstance.disassemble(fromAddress: CPU.sharedInstance.program_counter, length: 256)
debuggerTableView.reloadData()
highlightCurrentInstruction()
}

View File

@ -60,10 +60,10 @@ class MemoryInterface: NSObject {
return (UInt16(high) << 8) | UInt16(low)
}
func loadBinary(path: String, offset: UInt16) {
func loadBinary(path: String, offset: UInt16, length: Int) {
do {
let fileContent: NSData = try NSData(contentsOfFile: path)
fileContent.getBytes(&memory[Int(offset)], range: NSRange(location: 0, length: 256))
fileContent.getBytes(&memory[Int(offset)], range: NSRange(location: 0, length: length))
} catch {
print(error)
}

View File

@ -173,7 +173,7 @@ class Opcodes: NSObject {
static func SBC(state: CPU, addressingMode: AddressingMode) -> Void {
let operand = UInt8(getOperandByteForAddressingMode(state: state, mode: addressingMode))
var t16: UInt16 = UInt16(state.accumulator &- operand) - UInt16((state.status_register.carry ? UInt8(0) : UInt8(1)))
var t16: UInt16 = UInt16(state.accumulator &- operand) &- UInt16((state.status_register.carry ? UInt8(0) : UInt8(1)))
let t8: UInt8 = UInt8(t16 & 0xFF)
state.cyclesInBatch = 0
@ -182,7 +182,7 @@ class Opcodes: NSObject {
if(state.status_register.decimal == true) {
t16 = UInt16(hex2bcd(hex: state.accumulator) + hex2bcd(hex: operand) + (state.status_register.carry ? UInt8(1) : UInt8(0)))
} else {
state.status_register.carry = (t16 >> 8) == 0 ? false : true
state.status_register.carry = t8 <= 127 ? true : false
}
state.accumulator = t8

View File

@ -28,18 +28,25 @@ class MainViewController: NSViewController {
self.view.addSubview(computer.emulatorView)
self.frameTimer = Timer.scheduledTimer(timeInterval: 1/60, target: self, selector: #selector(runEmulation), userInfo: nil, repeats: true)
//runEmulation()
}
@objc func runEmulation() {
computer.runFrame()
if(!CPU.sharedInstance.isRunning) {
self.frameTimer?.invalidate()
}
}
override func keyDown(with event: NSEvent) {
let c = returnChar(theEvent: event)
computer.pia["keyboard"]?.data = UInt8((c?.asciiValue)! & 0x000000FF)
guard let ascii32 = c?.asciiValue else {
return
}
computer.pia["keyboard"]?.data = UInt8(ascii32 & 0x000000FF)
computer.pia["keyboard"]?.control |= 0x80
}
private func returnChar(theEvent: NSEvent) -> Character?{