mirror of
https://github.com/Luigi30/FruitMachine-Swift.git
synced 2024-11-23 02:33:00 +00:00
working on language card support, Apple II+ support (Applesoft BASIC ROMs), disk writing support
This commit is contained in:
parent
26549c7737
commit
c91c1cb4e5
@ -8,6 +8,7 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
2A044E2C1F37D65A000E8085 /* LanguageCard16K.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A044E2B1F37D65A000E8085 /* LanguageCard16K.swift */; };
|
||||
2A044E2E1F382CA9000E8085 /* AppleIIPlus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A044E2D1F382CA9000E8085 /* AppleIIPlus.swift */; };
|
||||
2A16ADBB1F33C341004A0333 /* DiskImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A16ADBA1F33C341004A0333 /* DiskImage.swift */; };
|
||||
2A2126841F2A9FA300E43DC1 /* DebuggerWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A2126831F2A9FA300E43DC1 /* DebuggerWindowController.swift */; };
|
||||
2A22EBFB1F21A7A700A36A61 /* IntegerExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A22EBFA1F21A7A700A36A61 /* IntegerExtensions.swift */; };
|
||||
@ -24,7 +25,7 @@
|
||||
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 */; };
|
||||
2A6DC7EB1F3045C90066FE0D /* AppleIIBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A6DC7EA1F3045C90066FE0D /* AppleIIBase.swift */; };
|
||||
2A6DC7ED1F30492C0066FE0D /* ScreenDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A6DC7EC1F30492C0066FE0D /* ScreenDelegate.swift */; };
|
||||
2A6DC7F01F30495D0066FE0D /* ScreenView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A6DC7EF1F30495D0066FE0D /* ScreenView.swift */; };
|
||||
2A7665781F2F05F600135518 /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A7665761F2F05F600135518 /* PreferencesWindowController.swift */; };
|
||||
@ -58,6 +59,7 @@
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
2A044E2B1F37D65A000E8085 /* LanguageCard16K.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LanguageCard16K.swift; sourceTree = "<group>"; };
|
||||
2A044E2D1F382CA9000E8085 /* AppleIIPlus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleIIPlus.swift; sourceTree = "<group>"; };
|
||||
2A16ADBA1F33C341004A0333 /* DiskImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiskImage.swift; sourceTree = "<group>"; };
|
||||
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>"; };
|
||||
@ -74,7 +76,7 @@
|
||||
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>"; };
|
||||
2A6DC7EA1F3045C90066FE0D /* AppleIIBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleIIBase.swift; sourceTree = "<group>"; };
|
||||
2A6DC7EC1F30492C0066FE0D /* ScreenDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenDelegate.swift; sourceTree = "<group>"; };
|
||||
2A6DC7EF1F30495D0066FE0D /* ScreenView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenView.swift; sourceTree = "<group>"; };
|
||||
2A7665761F2F05F600135518 /* PreferencesWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesWindowController.swift; sourceTree = "<group>"; };
|
||||
@ -164,7 +166,6 @@
|
||||
2AE3BB981F32D24D00C11060 /* Memory */,
|
||||
2A6DC7E71F3044080066FE0D /* Peripherals */,
|
||||
2A6DC7E61F3043E10066FE0D /* Video */,
|
||||
2A6DC7EA1F3045C90066FE0D /* EmulatedSystem.swift */,
|
||||
);
|
||||
path = Common;
|
||||
sourceTree = "<group>";
|
||||
@ -215,7 +216,9 @@
|
||||
children = (
|
||||
2A63C2381F32CCDB00D4F4F8 /* Peripherals */,
|
||||
2A6DC7EE1F30492E0066FE0D /* Video */,
|
||||
2A6DC7EA1F3045C90066FE0D /* AppleIIBase.swift */,
|
||||
2AB6CACC1F3041A200DECAC0 /* AppleII.swift */,
|
||||
2A044E2D1F382CA9000E8085 /* AppleIIPlus.swift */,
|
||||
2A86FB961F316CB500AD0C68 /* KeyboardController.swift */,
|
||||
2A6C2D161F31216700B8DC60 /* SoftswitchOverrides.swift */,
|
||||
);
|
||||
@ -408,6 +411,7 @@
|
||||
2AD458E31F20661300F05121 /* CPUInstructions.swift in Sources */,
|
||||
2A5C5BBC1F304C3A00ED351D /* A2CharacterGenerator.swift in Sources */,
|
||||
2AD458D01F205EB700F05121 /* DebuggerViewController.swift in Sources */,
|
||||
2A044E2E1F382CA9000E8085 /* AppleIIPlus.swift in Sources */,
|
||||
2A7665781F2F05F600135518 /* PreferencesWindowController.swift in Sources */,
|
||||
2AA8B5FC1F2A8EAD002B350F /* Terminal.swift in Sources */,
|
||||
2A5BC51E1F29A4C3008C03BE /* AppleIBitmapDisplay.swift in Sources */,
|
||||
@ -421,7 +425,7 @@
|
||||
2AD6D5841F26E6BF008F3CF5 /* DebuggerCommands.swift in Sources */,
|
||||
2AE3BB971F32CEB100C11060 /* ROMManager.swift in Sources */,
|
||||
2AE5BA041F23DE4400FAA343 /* Disassembly.swift in Sources */,
|
||||
2A6DC7EB1F3045C90066FE0D /* EmulatedSystem.swift in Sources */,
|
||||
2A6DC7EB1F3045C90066FE0D /* AppleIIBase.swift in Sources */,
|
||||
2A86FB971F316CB500AD0C68 /* KeyboardController.swift in Sources */,
|
||||
2A63C2351F32C4F700D4F4F8 /* LoresMode.swift in Sources */,
|
||||
2AE42E3A1F28628300C4900E /* AppleIViewController.swift in Sources */,
|
||||
@ -491,7 +495,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
@ -509,7 +513,7 @@
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.12;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
@ -553,7 +557,9 @@
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = s;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
@ -572,6 +578,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_USE_OPTIMIZATION_PROFILE = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = FruitMachine/FruitMachine.entitlements;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
GENERATE_PROFILING_CODE = YES;
|
||||
@ -588,6 +595,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_USE_OPTIMIZATION_PROFILE = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = FruitMachine/FruitMachine.entitlements;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
GENERATE_PROFILING_CODE = YES;
|
||||
|
@ -4,6 +4,11 @@
|
||||
<dict>
|
||||
<key>SchemeUserState</key>
|
||||
<dict>
|
||||
<key>FruitMachine Release.xcscheme</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
<key>FruitMachine.xcscheme</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
import Cocoa
|
||||
|
||||
class AppleI: NSObject, EmulatedSystem {
|
||||
class AppleI: NSObject {
|
||||
var CPU_FREQUENCY: Double
|
||||
var FRAMES_PER_SECOND: Double
|
||||
var CYCLES_PER_BATCH: Int
|
||||
|
@ -8,80 +8,35 @@
|
||||
|
||||
import Cocoa
|
||||
|
||||
final class AppleII: NSObject, EmulatedSystem {
|
||||
static let sharedInstance = AppleII(cpuFrequency: (14.31818 / 7 / 2) * 1000000, fps: 60.0)
|
||||
|
||||
var frameCounter: Int = 0
|
||||
|
||||
let cg = A2CharacterGenerator(romPath: "/Users/luigi/apple2/a2.chr");
|
||||
let keyboardController = KeyboardController()
|
||||
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
|
||||
|
||||
let emulatorViewDelegate = AppleII.ScreenDelegate()
|
||||
let emulatorView = AppleII.ScreenView(frame: NSMakeRect(0, 16, 560, 384))
|
||||
let emuScreenLayer = CALayer()
|
||||
class AppleII: AppleIIBase {
|
||||
static let sharedInstance = AppleII(cpuFrequency: 1000000, fps: 60.0)
|
||||
|
||||
required init(cpuFrequency: Double, fps: Double) {
|
||||
CPU_FREQUENCY = cpuFrequency
|
||||
FRAMES_PER_SECOND = fps
|
||||
CYCLES_PER_BATCH = Int(cpuFrequency / fps)
|
||||
super.init(cpuFrequency: cpuFrequency,
|
||||
fps: fps,
|
||||
delegate: ScreenDelegate(),
|
||||
view: ScreenView(frame: NSMakeRect(0, 16, 560, 384)))
|
||||
|
||||
videoMode = .Text
|
||||
|
||||
for i in 0...7 {
|
||||
backplane[i] = nil
|
||||
}
|
||||
|
||||
super.init()
|
||||
|
||||
setupMemory(ramConfig: .fortyeightK)
|
||||
setupPeripherals()
|
||||
loadROMs()
|
||||
|
||||
emuScreenLayer.shouldRasterize = true
|
||||
emuScreenLayer.delegate = emulatorViewDelegate
|
||||
emuScreenLayer.frame = emulatorView.bounds
|
||||
|
||||
emulatorView.wantsLayer = true
|
||||
|
||||
//emuScreenLayer.setNeedsDisplay()
|
||||
emulatorView.layer?.addSublayer(emuScreenLayer)
|
||||
|
||||
installOverrides()
|
||||
|
||||
doReset()
|
||||
}
|
||||
|
||||
func doReset() {
|
||||
videoSoftswitches.reset()
|
||||
videoMode = .Text
|
||||
CPU.sharedInstance.performReset()
|
||||
required init(cpuFrequency: Double, fps: Double, delegate: ScreenDelegate, view: ScreenView) {
|
||||
fatalError("init(cpuFrequency:fps:delegate:view:) has not been implemented")
|
||||
}
|
||||
|
||||
func loadROMs() {
|
||||
override func loadROMs() {
|
||||
|
||||
/* Integer BASIC */
|
||||
CPU.sharedInstance.memoryInterface.loadBinary(path: "/Users/luigi/apple2/341-0001-00.e0", offset: 0xE000, length: 0x800)
|
||||
CPU.sharedInstance.memoryInterface.loadBinary(path: "/Users/luigi/apple2/341-0002-00.e8", offset: 0xE800, length: 0x800)
|
||||
CPU.sharedInstance.memoryInterface.loadBinary(path: "/Users/luigi/apple2/341-0003-00.f0", offset: 0xF000, length: 0x800)
|
||||
|
||||
//Hardware handles this, really.
|
||||
if(backplane[0] is LanguageCard16K) {
|
||||
//Language Card ROM
|
||||
CPU.sharedInstance.memoryInterface.loadBinary(path: "/Users/luigi/apple2/341-0020-00.f8", offset: 0xF800, length: 0x800)
|
||||
} else {
|
||||
//Integer BASIC ROM
|
||||
CPU.sharedInstance.memoryInterface.loadBinary(path: "/Users/luigi/apple2/341-0004-00.f8", offset: 0xF800, length: 0x800)
|
||||
}
|
||||
/* Monitor */
|
||||
CPU.sharedInstance.memoryInterface.loadBinary(path: "/Users/luigi/apple2/341-0004-00.f8", offset: 0xF800, length: 0x800)
|
||||
}
|
||||
|
||||
func installOverrides() {
|
||||
override func installOverrides() {
|
||||
for (_, peripheral) in backplane {
|
||||
if(peripheral != nil) {
|
||||
peripheral!.installOverrides()
|
||||
@ -111,124 +66,6 @@ final class AppleII: NSObject, EmulatedSystem {
|
||||
CPU.sharedInstance.memoryInterface.write_overrides.append(SoftswitchOverrides.switchC057W)
|
||||
}
|
||||
|
||||
func runFrame() {
|
||||
frameCounter = (frameCounter + 1) % 60
|
||||
if(frameCounter % 15) == 0 {
|
||||
emulatorViewDelegate.flashIsInverse = !emulatorViewDelegate.flashIsInverse
|
||||
}
|
||||
|
||||
CPU.sharedInstance.cycles = 0
|
||||
CPU.sharedInstance.cyclesInBatch = CYCLES_PER_BATCH
|
||||
CPU.sharedInstance.runCyclesBatch()
|
||||
|
||||
//update the video display
|
||||
CVPixelBufferLockBaseAddress(emulatorViewDelegate.pixels!, CVPixelBufferLockFlags(rawValue: 0))
|
||||
let pixelBase = CVPixelBufferGetBaseAddress(emulatorViewDelegate.pixels!)
|
||||
let buf = pixelBase?.assumingMemoryBound(to: BitmapPixelsLE555.PixelData.self)
|
||||
|
||||
videoMode = getCurrentVideoMode(switches: videoSoftswitches)
|
||||
|
||||
if(videoMode == .Text)
|
||||
{
|
||||
//Text mode: Get character codes from $0400-$07FF
|
||||
putGlyphs(buffer: buf!, start: 0x400, end: 0x7F8)
|
||||
}
|
||||
else if(videoMode == .Lores)
|
||||
{
|
||||
putLoresPixels(buffer: buf!, start: 0x400, end: 0x7F8)
|
||||
}
|
||||
else if(videoMode == .MixedLores) {
|
||||
//Draw the lores pixel rows.
|
||||
putLoresPixels(buffer: buf!, start: 0x400, end: 0x650)
|
||||
putLoresPixels(buffer: buf!, start: 0x680, end: 0x6A8)
|
||||
putLoresPixels(buffer: buf!, start: 0x700, end: 0x728)
|
||||
putLoresPixels(buffer: buf!, start: 0x780, end: 0x7A8)
|
||||
putLoresPixels(buffer: buf!, start: 0x6A8, end: 0x6D0)
|
||||
putLoresPixels(buffer: buf!, start: 0x728, end: 0x750)
|
||||
putLoresPixels(buffer: buf!, start: 0x7A8, end: 0x7D0)
|
||||
|
||||
//Draw the bottom 4 text rows.
|
||||
putGlyphs(buffer: buf!, start: 0x650, end: 0x678)
|
||||
putGlyphs(buffer: buf!, start: 0x6D0, end: 0x6F8)
|
||||
putGlyphs(buffer: buf!, start: 0x750, end: 0x778)
|
||||
putGlyphs(buffer: buf!, start: 0x7D0, end: 0x7F8)
|
||||
} else {
|
||||
print("Unimplemented video mode!")
|
||||
}
|
||||
|
||||
|
||||
CVPixelBufferUnlockBaseAddress(emulatorViewDelegate.pixels!, CVPixelBufferLockFlags(rawValue: 0))
|
||||
emulatorView.setNeedsDisplay(emulatorView.frame)
|
||||
}
|
||||
|
||||
func putLoresPixels(buffer: UnsafeMutablePointer<BitmapPixelsLE555.PixelData>, start: UInt16, end: UInt16) {
|
||||
for address in start ..< end {
|
||||
let pixelData = CPU.sharedInstance.memoryInterface.readByte(offset: UInt16(address), bypassOverrides: true)
|
||||
|
||||
LoresMode.putLoresPixel(buffer: buffer,
|
||||
pixel: pixelData,
|
||||
address: UInt16(address))
|
||||
}
|
||||
}
|
||||
|
||||
func putGlyphs(buffer: UnsafeMutablePointer<BitmapPixelsLE555.PixelData>, start: UInt16, end: UInt16) {
|
||||
for address in start ... end {
|
||||
let charCode = CPU.sharedInstance.memoryInterface.readByte(offset: UInt16(address), bypassOverrides: true)
|
||||
|
||||
TextMode.putGlyph(buffer: buffer,
|
||||
glyph: cg.glyphs[Int(charCode & 0x3F)],
|
||||
attributes: charCode & 0xC0, //d6 and d7
|
||||
pixelPosition: VideoHelpers.getPixelOffset(memoryOffset: Int(address - 0x400)))
|
||||
}
|
||||
}
|
||||
|
||||
enum MemoryConfiguration {
|
||||
case fourK
|
||||
case sixteenK
|
||||
case fortyeightK
|
||||
}
|
||||
|
||||
func setupMemory(ramConfig: MemoryConfiguration) {
|
||||
let ramPages: Int
|
||||
|
||||
switch ramConfig {
|
||||
case .fourK:
|
||||
ramPages = 4096 / 256
|
||||
case .sixteenK:
|
||||
ramPages = 16384 / 256
|
||||
case .fortyeightK:
|
||||
ramPages = 49152 / 256
|
||||
}
|
||||
|
||||
for page in 0 ..< ramPages {
|
||||
CPU.sharedInstance.memoryInterface.pages[page] = MemoryInterface.pageMode.rw //RAM
|
||||
}
|
||||
for page in ramPages ..< 192 {
|
||||
CPU.sharedInstance.memoryInterface.pages[page] = MemoryInterface.pageMode.null //not connected
|
||||
}
|
||||
for page in 224 ..< 256 {
|
||||
CPU.sharedInstance.memoryInterface.pages[page] = MemoryInterface.pageMode.ro //ROM
|
||||
}
|
||||
}
|
||||
|
||||
func setupPeripherals() {
|
||||
let defaults = UserDefaults.standard
|
||||
|
||||
let slot0 = defaults.string(forKey: "a2_Peripherals_Slot0")
|
||||
if(slot0 == "Language Card (16K)") {
|
||||
backplane[0] = LanguageCard16K(slot: 0, romPath: "/Users/luigi/apple2/341-0020-00.f8")
|
||||
}
|
||||
|
||||
let slot6 = defaults.string(forKey: "a2_Peripherals_Slot6")
|
||||
if(slot6 == "Disk II") {
|
||||
backplane[6] = DiskII(slot: 6, romPath: "/Users/luigi/apple2/341-0027-a.p5")
|
||||
|
||||
let drive = backplane[6]! as! DiskII
|
||||
drive.attachDiskImage(imagePath: "/Users/luigi/apple2/Apex II - Apple II Diagnostic (v4.7-1986).DSK")
|
||||
//drive.attachDiskImage(imagePath: "/Users/luigi/apple2/clean332sysmas.do")
|
||||
}
|
||||
}
|
||||
|
||||
@objc func debuggerBreak() {
|
||||
|
||||
}
|
||||
|
69
FruitMachine/AppleII/AppleIIPlus.swift
Normal file
69
FruitMachine/AppleII/AppleIIPlus.swift
Normal file
@ -0,0 +1,69 @@
|
||||
//
|
||||
// AppleIIPlus.swift
|
||||
// FruitMachine
|
||||
//
|
||||
// Created by Christopher Rohl on 8/7/17.
|
||||
// Copyright © 2017 Christopher Rohl. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
||||
class AppleIIPlus: AppleIIBase {
|
||||
static let sharedInstance = AppleIIPlus(cpuFrequency: 1000000, fps: 60.0)
|
||||
|
||||
required init(cpuFrequency: Double, fps: Double) {
|
||||
super.init(cpuFrequency: cpuFrequency,
|
||||
fps: fps,
|
||||
delegate: ScreenDelegate(),
|
||||
view: ScreenView(frame: NSMakeRect(0, 16, 560, 384)))
|
||||
|
||||
loadROMs()
|
||||
doReset()
|
||||
}
|
||||
|
||||
required init(cpuFrequency: Double, fps: Double, delegate: ScreenDelegate, view: ScreenView) {
|
||||
fatalError("init(cpuFrequency:fps:delegate:view:) has not been implemented")
|
||||
}
|
||||
|
||||
override func loadROMs() {
|
||||
//Applesoft BASIC
|
||||
CPU.sharedInstance.memoryInterface.loadBinary(path: "/Users/luigi/apple2p/341-0011.d0", offset: 0xD000, length: 0x800)
|
||||
CPU.sharedInstance.memoryInterface.loadBinary(path: "/Users/luigi/apple2p/341-0012.d8", offset: 0xD800, length: 0x800)
|
||||
CPU.sharedInstance.memoryInterface.loadBinary(path: "/Users/luigi/apple2p/341-0013.e0", offset: 0xE000, length: 0x800)
|
||||
CPU.sharedInstance.memoryInterface.loadBinary(path: "/Users/luigi/apple2p/341-0014.e8", offset: 0xE800, length: 0x800)
|
||||
CPU.sharedInstance.memoryInterface.loadBinary(path: "/Users/luigi/apple2p/341-0015.f0", offset: 0xF000, length: 0x800)
|
||||
|
||||
//Monitor
|
||||
CPU.sharedInstance.memoryInterface.loadBinary(path: "/Users/luigi/apple2p/341-0020-00.f8", offset: 0xF800, length: 0x800)
|
||||
}
|
||||
|
||||
override func installOverrides() {
|
||||
for (_, 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)
|
||||
|
||||
CPU.sharedInstance.memoryInterface.read_overrides.append(SoftswitchOverrides.switchC050R)
|
||||
CPU.sharedInstance.memoryInterface.read_overrides.append(SoftswitchOverrides.switchC051R)
|
||||
CPU.sharedInstance.memoryInterface.read_overrides.append(SoftswitchOverrides.switchC052R)
|
||||
CPU.sharedInstance.memoryInterface.read_overrides.append(SoftswitchOverrides.switchC053R)
|
||||
CPU.sharedInstance.memoryInterface.read_overrides.append(SoftswitchOverrides.switchC054R)
|
||||
CPU.sharedInstance.memoryInterface.read_overrides.append(SoftswitchOverrides.switchC055R)
|
||||
CPU.sharedInstance.memoryInterface.read_overrides.append(SoftswitchOverrides.switchC056R)
|
||||
CPU.sharedInstance.memoryInterface.read_overrides.append(SoftswitchOverrides.switchC057R)
|
||||
|
||||
CPU.sharedInstance.memoryInterface.write_overrides.append(SoftswitchOverrides.switchC050W)
|
||||
CPU.sharedInstance.memoryInterface.write_overrides.append(SoftswitchOverrides.switchC051W)
|
||||
CPU.sharedInstance.memoryInterface.write_overrides.append(SoftswitchOverrides.switchC052W)
|
||||
CPU.sharedInstance.memoryInterface.write_overrides.append(SoftswitchOverrides.switchC053W)
|
||||
CPU.sharedInstance.memoryInterface.write_overrides.append(SoftswitchOverrides.switchC054W)
|
||||
CPU.sharedInstance.memoryInterface.write_overrides.append(SoftswitchOverrides.switchC055W)
|
||||
CPU.sharedInstance.memoryInterface.write_overrides.append(SoftswitchOverrides.switchC056W)
|
||||
CPU.sharedInstance.memoryInterface.write_overrides.append(SoftswitchOverrides.switchC057W)
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@
|
||||
|
||||
import Cocoa
|
||||
|
||||
extension AppleII {
|
||||
extension AppleIIBase {
|
||||
|
||||
class SoftswitchOverrides: NSObject {
|
||||
/* Keyboard port */
|
||||
@ -17,7 +17,7 @@ extension AppleII {
|
||||
//let b = CPU.sharedInstance.memoryInterface.readByte(offset: 0xC000, bypassOverrides: true)
|
||||
//CPU.sharedInstance.memoryInterface.writeByte(offset: 0xC000, value: b)
|
||||
//return b
|
||||
return AppleII.sharedInstance.keyboardController.KEYBOARD
|
||||
return EmulatedSystemInstance!.keyboardController.KEYBOARD
|
||||
}
|
||||
|
||||
static let clearKeypressStrobeR = ReadOverride(start: 0xC010, end: 0xC010, readAnyway: false, action: SoftswitchOverrides.actionClearKeypressStrobe)
|
||||
@ -30,9 +30,9 @@ extension AppleII {
|
||||
//CPU.sharedInstance.memoryInterface.writeByte(offset: 0xC010, value: b & 0x7F, bypassOverrides: true)
|
||||
|
||||
//return b
|
||||
let b = AppleII.sharedInstance.keyboardController.KEYBOARD
|
||||
AppleII.sharedInstance.keyboardController.KEYBOARD = b & 0x7F
|
||||
AppleII.sharedInstance.keyboardController.STROBE = b & 0x7F
|
||||
let b = EmulatedSystemInstance!.keyboardController.KEYBOARD
|
||||
EmulatedSystemInstance!.keyboardController.KEYBOARD = b & 0x7F
|
||||
EmulatedSystemInstance!.keyboardController.STROBE = b & 0x7F
|
||||
return b
|
||||
}
|
||||
|
||||
@ -40,56 +40,56 @@ extension AppleII {
|
||||
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, address: UInt16, byte: UInt8?) -> UInt8? {
|
||||
AppleII.sharedInstance.videoSoftswitches.TEXT_MODE = false
|
||||
EmulatedSystemInstance!.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, address: UInt16, byte: UInt8?) -> UInt8? {
|
||||
AppleII.sharedInstance.videoSoftswitches.TEXT_MODE = true
|
||||
EmulatedSystemInstance!.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, address: UInt16, byte: UInt8?) -> UInt8? {
|
||||
AppleII.sharedInstance.videoSoftswitches.MIX_MODE = false
|
||||
EmulatedSystemInstance!.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, address: UInt16, byte: UInt8?) -> UInt8? {
|
||||
AppleII.sharedInstance.videoSoftswitches.MIX_MODE = true
|
||||
EmulatedSystemInstance!.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, address: UInt16, byte: UInt8?) -> UInt8? {
|
||||
AppleII.sharedInstance.videoSoftswitches.PAGE_2 = false
|
||||
EmulatedSystemInstance!.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, address: UInt16, byte: UInt8?) -> UInt8? {
|
||||
AppleII.sharedInstance.videoSoftswitches.MIX_MODE = true
|
||||
EmulatedSystemInstance!.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, address: UInt16, byte: UInt8?) -> UInt8? {
|
||||
AppleII.sharedInstance.videoSoftswitches.HIRES_MODE = false
|
||||
EmulatedSystemInstance!.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, address: UInt16, byte: UInt8?) -> UInt8? {
|
||||
AppleII.sharedInstance.videoSoftswitches.HIRES_MODE = true
|
||||
EmulatedSystemInstance!.videoSoftswitches.HIRES_MODE = true
|
||||
return 0x00
|
||||
}
|
||||
}
|
||||
|
@ -7,11 +7,10 @@
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
//The Apple II character generator is an AY-5-3600.
|
||||
|
||||
extension AppleIIBase {
|
||||
|
||||
extension AppleII {
|
||||
|
||||
//The Apple II character generator is a clone of the Signetics 2513 from the Apple I.
|
||||
|
||||
class A2CharacterGenerator: NSObject, HasROM {
|
||||
static let CHAR_WIDTH = 5
|
||||
static let CHAR_HEIGHT = 8
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
import Cocoa
|
||||
|
||||
extension AppleII {
|
||||
extension AppleIIBase {
|
||||
|
||||
class LoresMode: NSObject {
|
||||
static func putLoresPixel(buffer: UnsafeMutablePointer<BitmapPixelsLE555.PixelData>?, pixel: UInt8, address: UInt16) {
|
||||
@ -25,7 +25,7 @@ extension AppleII {
|
||||
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)
|
||||
let baseOffset = EmulatedSystemInstance!.emulatorViewDelegate.scanlineOffsets[Int(pixelPosition.y)] + Int(pixelPosition.x)
|
||||
|
||||
for charY in 0..<5 {
|
||||
let offsetHi = baseOffset + (AppleII.ScreenDelegate.PIXEL_WIDTH * charY)
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
import Cocoa
|
||||
|
||||
extension AppleII {
|
||||
extension AppleIIBase {
|
||||
|
||||
class TextMode: NSObject {
|
||||
static func putGlyph(buffer: UnsafeMutablePointer<BitmapPixelsLE555.PixelData>?, glyph: Glyph, attributes: UInt8, pixelPosition: CGPoint) {
|
||||
@ -25,7 +25,7 @@ extension AppleII {
|
||||
}
|
||||
|
||||
//Calculate the offset to reach the desired position.
|
||||
let baseOffset = AppleII.sharedInstance.emulatorViewDelegate.scanlineOffsets[Int(pixelPosition.y)] + Int(pixelPosition.x)
|
||||
let baseOffset = EmulatedSystemInstance!.emulatorViewDelegate.scanlineOffsets[Int(pixelPosition.y)] + Int(pixelPosition.x)
|
||||
|
||||
for charY in 0..<AppleII.A2CharacterGenerator.CHAR_HEIGHT {
|
||||
let offset = baseOffset + (AppleII.ScreenDelegate.PIXEL_WIDTH * charY)
|
||||
@ -38,7 +38,7 @@ extension AppleII {
|
||||
case .inverse:
|
||||
buffer![offset + 6 - charX] = BitmapPixelsLE555.PixelData(data: ~glyph.pixels[glyphOffsetY + charX].data)
|
||||
case .flashing:
|
||||
if(!AppleII.sharedInstance.emulatorViewDelegate.flashIsInverse) {
|
||||
if(!EmulatedSystemInstance!.emulatorViewDelegate.flashIsInverse) {
|
||||
buffer![offset + 6 - charX] = glyph.pixels[glyphOffsetY + charX]
|
||||
} else {
|
||||
buffer![offset + 6 - charX] = BitmapPixelsLE555.PixelData(data: ~glyph.pixels[glyphOffsetY + charX].data)
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
import Cocoa
|
||||
|
||||
extension AppleII {
|
||||
extension AppleIIBase {
|
||||
|
||||
typealias Softswitch = Bool
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
import Cocoa
|
||||
|
||||
extension AppleII {
|
||||
extension AppleIIBase {
|
||||
|
||||
enum CharacterAttributes {
|
||||
case normal
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
import Cocoa
|
||||
|
||||
extension AppleII {
|
||||
extension AppleIIBase {
|
||||
|
||||
class ScreenView: NSView {
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
import Cocoa
|
||||
|
||||
extension AppleII {
|
||||
extension AppleIIBase {
|
||||
class VideoHelpers: NSObject {
|
||||
static func getPixelOffset(charCellX: Int, charCellY: Int) -> CGPoint {
|
||||
return CGPoint(x: charCellX * 7, y: charCellY * 8)
|
||||
|
@ -8,12 +8,10 @@
|
||||
|
||||
import Cocoa
|
||||
|
||||
class AppleIIViewController: NSViewController {
|
||||
|
||||
class AppleIIViewController: NSViewController {
|
||||
@IBOutlet weak var lbl_Drive1: NSTextField!
|
||||
@IBOutlet weak var lbl_Drive2: NSTextField!
|
||||
|
||||
let computer = AppleII.sharedInstance
|
||||
var debuggerWindowController: DebuggerWindowController!
|
||||
var preferencesWindowController: PreferencesWindowController!
|
||||
|
||||
@ -23,9 +21,10 @@ class AppleIIViewController: NSViewController {
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
// Do view setup here.
|
||||
EmulatedSystemInstance = AppleII.sharedInstance
|
||||
|
||||
preferencesWindowController = PreferencesWindowController()
|
||||
self.view.addSubview(computer.emulatorView)
|
||||
self.view.addSubview(EmulatedSystemInstance!.emulatorView)
|
||||
|
||||
preferencesWindowController.setupDefaultsIfRequired()
|
||||
setupDriveNotifications()
|
||||
@ -39,7 +38,7 @@ class AppleIIViewController: NSViewController {
|
||||
}
|
||||
|
||||
@objc func runEmulation() {
|
||||
computer.runFrame()
|
||||
EmulatedSystemInstance!.runFrame()
|
||||
if(!CPU.sharedInstance.isRunning) {
|
||||
self.frameTimer?.invalidate()
|
||||
}
|
||||
@ -62,7 +61,7 @@ class AppleIIViewController: NSViewController {
|
||||
}
|
||||
|
||||
@IBAction func doReset(_ sender: Any) {
|
||||
computer.doReset()
|
||||
EmulatedSystemInstance!.doReset()
|
||||
}
|
||||
|
||||
override func keyDown(with event: NSEvent) {
|
||||
@ -72,9 +71,9 @@ class AppleIIViewController: NSViewController {
|
||||
let c = returnChar(theEvent: event)
|
||||
|
||||
if(event.keyCode == leftArrowKeyCode) {
|
||||
computer.keyboardController.KEYBOARD = UInt8((0x08 | 0x80) & 0x000000FF)
|
||||
EmulatedSystemInstance!.keyboardController.KEYBOARD = UInt8((0x08 | 0x80) & 0x000000FF)
|
||||
} else if(event.keyCode == rightArrowKeyCode) {
|
||||
computer.keyboardController.KEYBOARD = UInt8((0x15 | 0x80) & 0x000000FF)
|
||||
EmulatedSystemInstance!.keyboardController.KEYBOARD = UInt8((0x15 | 0x80) & 0x000000FF)
|
||||
}
|
||||
|
||||
guard let ascii32 = c?.asciiValue else {
|
||||
@ -82,7 +81,7 @@ class AppleIIViewController: NSViewController {
|
||||
}
|
||||
|
||||
//Set the keyboard input register accordingly. Set b7 so the OS knows there's a keypress waiting
|
||||
computer.keyboardController.KEYBOARD = UInt8((ascii32 | 0x80) & 0x000000FF)
|
||||
EmulatedSystemInstance!.keyboardController.KEYBOARD = UInt8((ascii32 | 0x80) & 0x000000FF)
|
||||
}
|
||||
|
||||
private func returnChar(theEvent: NSEvent) -> Character?{
|
||||
|
@ -1,18 +0,0 @@
|
||||
//
|
||||
// EmulatedSystem.swift
|
||||
// FruitMachine
|
||||
//
|
||||
// Created by Christopher Rohl on 8/1/17.
|
||||
// Copyright © 2017 Christopher Rohl. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
||||
protocol EmulatedSystem {
|
||||
var CPU_FREQUENCY: Double { get }
|
||||
var FRAMES_PER_SECOND: Double { get }
|
||||
var CYCLES_PER_BATCH: Int { get }
|
||||
|
||||
init(cpuFrequency: Double, fps: Double)
|
||||
func installOverrides()
|
||||
}
|
@ -188,19 +188,19 @@
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Xl9-rO-Y9T">
|
||||
<rect key="frame" x="478" y="0.0" width="64" height="17"/>
|
||||
<rect key="frame" x="478" y="0.0" width="71" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Drive 2" id="Kaf-uu-AhW">
|
||||
<font key="font" metaFont="system"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="D2 T00 S00" id="Kaf-uu-AhW">
|
||||
<font key="font" metaFont="fixedUser" size="11"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="jaO-yO-mV1">
|
||||
<rect key="frame" x="410" y="0.0" width="64" height="17"/>
|
||||
<rect key="frame" x="403" y="0.0" width="71" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Drive 1" id="Yaa-0g-KnI">
|
||||
<font key="font" metaFont="system"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="D1 T00 S00" id="Yaa-0g-KnI">
|
||||
<font key="font" metaFont="fixedUser" size="11"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
|
Loading…
Reference in New Issue
Block a user