From d644057a1365b2856fa782ca336fada3adfcfccf Mon Sep 17 00:00:00 2001 From: Tamas Rudnai Date: Mon, 9 Sep 2019 00:27:31 -0700 Subject: [PATCH] Added basic keyboard functionality Added Soft Reset support Fixed few minor bugs --- A2Mac/6502.c | 27 ++++++- A2Mac/6502.h | 14 +++- A2Mac/Apple2_mmio.h | 83 +++++++++++---------- A2Mac/Base.lproj/Main.storyboard | 55 ++++++++++++-- A2Mac/ViewController.swift | 124 ++++++++++++++++++++++--------- 5 files changed, 217 insertions(+), 86 deletions(-) diff --git a/A2Mac/6502.c b/A2Mac/6502.c index 267dfe8..0d2a633 100644 --- a/A2Mac/6502.c +++ b/A2Mac/6502.c @@ -13,6 +13,9 @@ #include "common.h" #include "Apple2_mmio.h" + +#define SOFTRESET_VECTOR 0x3F2 + /** Instruction Implementations !!!! `his has to be here!!! @@ -25,7 +28,7 @@ ///// unsigned long long int clktime = 0; -m6502_s m6502 = {0}; +m6502_t m6502 = {0}; static inline int m6502_step() { @@ -327,8 +330,28 @@ static inline void m6502_run() { // unsigned long long s = rdtsc(); unsigned long long e = (unsigned long long)-1LL; - for ( unsigned long long int i = 0; i < iterations ; i++ ) { +// for ( unsigned long long int i = 0; i < iterations ; i++ ) { // for ( ; m6502.pc ; ) { + for ( ; ; ) { + if ( m6502.interrupt_flag ) { + switch (m6502.interrupt) { + case NMI: + break; + + case HARDRESET: + break; + + case SOFTRESET: + m6502.pc = memread16(SOFTRESET_VECTOR); + break; + + default: + break; + } + + m6502.interrupt_flag = 0; + } + dbgPrintf("%04u %04X: ", clktime, m6502.pc); clk = m6502_step(); clktime += clk; diff --git a/A2Mac/6502.h b/A2Mac/6502.h index 18a5d49..bd8939a 100644 --- a/A2Mac/6502.h +++ b/A2Mac/6502.h @@ -17,6 +17,11 @@ #define dbgPrintf(format, ...) #endif +typedef enum { + NMI, + HARDRESET, + SOFTRESET, +} interrupt_t; typedef struct m6502_s { uint8_t A; // Accumulator @@ -45,10 +50,15 @@ typedef struct m6502_s { uint16_t pc; // Program Counter uint16_t sp; // Stack Pointer unsigned clk; // Clock Counter -} m6502_s; + + union { + int interrupt_flag; + interrupt_t interrupt; + }; +} m6502_t; -extern m6502_s m6502; +extern m6502_t m6502; extern uint8_t RAM[ 64 * 1024 ]; extern void tst6502(); diff --git a/A2Mac/Apple2_mmio.h b/A2Mac/Apple2_mmio.h index 1a692d0..e087f55 100644 --- a/A2Mac/Apple2_mmio.h +++ b/A2Mac/Apple2_mmio.h @@ -14,51 +14,51 @@ enum mmio { - ioSomething = 0xC000, + io_KBD = 0xC000, + io_KBDSTRB = 0xC010, }; uint8_t RAM[ 64 * KB ] = {0}; - #define PAGESIZE 256 #define PAGES 16 -uint8_t ram_0[PAGESIZE]; -uint8_t ram_1[PAGESIZE]; -uint8_t ram_2[PAGESIZE]; -uint8_t ram_3[PAGESIZE]; -uint8_t ram_4[PAGESIZE]; -uint8_t ram_5[PAGESIZE]; -uint8_t ram_6[PAGESIZE]; -uint8_t ram_7[PAGESIZE]; -uint8_t ram_8[PAGESIZE]; -uint8_t ram_9[PAGESIZE]; -uint8_t ram_A[PAGESIZE]; -uint8_t ram_B[PAGESIZE]; -uint8_t aui_C[PAGESIZE]; -uint8_t rom_D[PAGESIZE]; -uint8_t rom_E[PAGESIZE]; -uint8_t rom_F[PAGESIZE]; - -uint8_t * ram[PAGES] = { - ram_0, - ram_1, - ram_2, - ram_3, - ram_4, - ram_5, - ram_6, - ram_7, - ram_8, - ram_9, - ram_A, - ram_B, - aui_C, - rom_D, - rom_E, - rom_F, -}; +//uint8_t ram_0[PAGESIZE]; +//uint8_t ram_1[PAGESIZE]; +//uint8_t ram_2[PAGESIZE]; +//uint8_t ram_3[PAGESIZE]; +//uint8_t ram_4[PAGESIZE]; +//uint8_t ram_5[PAGESIZE]; +//uint8_t ram_6[PAGESIZE]; +//uint8_t ram_7[PAGESIZE]; +//uint8_t ram_8[PAGESIZE]; +//uint8_t ram_9[PAGESIZE]; +//uint8_t ram_A[PAGESIZE]; +//uint8_t ram_B[PAGESIZE]; +//uint8_t aui_C[PAGESIZE]; +//uint8_t rom_D[PAGESIZE]; +//uint8_t rom_E[PAGESIZE]; +//uint8_t rom_F[PAGESIZE]; +// +//uint8_t * ram[PAGES] = { +// ram_0, +// ram_1, +// ram_2, +// ram_3, +// ram_4, +// ram_5, +// ram_6, +// ram_7, +// ram_8, +// ram_9, +// ram_A, +// ram_B, +// aui_C, +// rom_D, +// rom_E, +// rom_F, +//}; //uint8_t ( * mmio_read [ 64 * KB ] )( uint16_t addr ); @@ -74,9 +74,12 @@ typedef union address16_u { static inline uint8_t ioRead( uint16_t addr ) { // printf("mmio:%04X\n", addr); switch (addr) { - case ioSomething: - return 123; + case io_KBD: + return RAM[addr]; + case io_KBDSTRB: + return RAM[io_KBD] &= 0x7F; + default: break; } @@ -86,7 +89,7 @@ static inline uint8_t ioRead( uint16_t addr ) { static inline void ioWrite( uint16_t addr ) { // printf("mmio:%04X\n", addr); switch (addr) { - case ioSomething: + case io_KBD: return; default: diff --git a/A2Mac/Base.lproj/Main.storyboard b/A2Mac/Base.lproj/Main.storyboard index 0f86f92..3f97ada 100644 --- a/A2Mac/Base.lproj/Main.storyboard +++ b/A2Mac/Base.lproj/Main.storyboard @@ -686,7 +686,7 @@ - + @@ -705,19 +705,60 @@ - - + + - - - - + + + + + + + + + + + + + + + + + + + + + diff --git a/A2Mac/ViewController.swift b/A2Mac/ViewController.swift index b1d8dd3..38f3142 100644 --- a/A2Mac/ViewController.swift +++ b/A2Mac/ViewController.swift @@ -25,6 +25,92 @@ class ViewController: NSViewController { 0x228, 0x2A8, 0x328, 0x3A8, 0x050, 0x0D0, 0x150, 0x1D0, 0x250, 0x2D0, 0x350, 0x3D0 ] + @IBAction func Power(_ sender: Any) { + DispatchQueue.global(qos: .userInitiated).async { + tst6502() + } + } + + @IBAction func Reset(_ sender: Any) { +// let resetPointer = UnsafeRawBufferPointer(start: &RAM + 0x3F2, count: 2) +// let ral = UInt16(resetPointer[0]) +// let rah = UInt16(resetPointer[1]) +// let resetAddr = rah << 8 + ral +// +// let hex = String(resetAddr, radix: 16, uppercase: true) +// print("reset to:\(hex)\n") +// m6502.pc = resetAddr + + m6502.interrupt = SOFTRESET; + } + + + override func keyDown(with event: NSEvent) { + switch event.modifierFlags.intersection(.deviceIndependentFlagsMask) { + case [.command] where event.characters == "l", + [.command, .shift] where event.characters == "l": + print("command-l or command-shift-l") + default: + break + } + print( "key = " + (event.charactersIgnoringModifiers ?? "")) + print( "\ncharacter = " + (event.characters ?? "")) + + if let chars = event.characters { + let char = chars[chars.startIndex] + if let code = char.asciiValue { + var A2code = code + 0x60 + + if ( code == 13 ) { + A2code = 141 + } + print("keycode: \(code) --> \(A2code)") + + let resetPointer = UnsafeMutableRawBufferPointer(start: &RAM + 0xC000, count: 1) + resetPointer[0] = A2code + } + } + + } + + override func flagsChanged(with event: NSEvent) { + switch event.modifierFlags.intersection(.deviceIndependentFlagsMask) { + case [.shift]: + print("shift key is pressed") + case [.control]: + print("control key is pressed") + case [.option] : + print("option key is pressed") + case [.command]: + print("Command key is pressed") + case [.control, .shift]: + print("control-shift keys are pressed") + case [.option, .shift]: + print("option-shift keys are pressed") + case [.command, .shift]: + print("command-shift keys are pressed") + case [.control, .option]: + print("control-option keys are pressed") + case [.control, .command]: + print("control-command keys are pressed") + case [.option, .command]: + print("option-command keys are pressed") + case [.shift, .control, .option]: + print("shift-control-option keys are pressed") + case [.shift, .control, .command]: + print("shift-control-command keys are pressed") + case [.control, .option, .command]: + print("control-option-command keys are pressed") + case [.shift, .command, .option]: + print("shift-command-option keys are pressed") + case [.shift, .control, .option, .command]: + print("shift-control-option-command keys are pressed") + default: + print("no modifier keys are pressed") + } + } + + func update() { while true { @@ -34,7 +120,7 @@ class ViewController: NSViewController { let textLines = 24 let textCols = 40 - var txt : String = "|" + var txt : String = "" for y in 0...textLines-1 { let textAddr = textBaseAddr + textLineOfs[y] @@ -44,10 +130,10 @@ class ViewController: NSViewController { let idx = Int(byte); let chr = ViewController.charConvTbl[idx] // print("byte \(index): \(chr)") - txt = txt + [chr] + txt = txt + " \(chr)" } - txt = txt + "|\n|" + txt = txt + " |\n" } @@ -74,38 +160,6 @@ class ViewController: NSViewController { override func viewDidLoad() { super.viewDidLoad() - display.stringValue = "lll" - - // emulate in he background -// DispatchQueue.global(qos: .background).async { - DispatchQueue.global(qos: .userInitiated).async { - tst6502() - } - -// let r = RAM.1 - -// let r = UnsafeMutablePointer(RAM) - -// let r = withUnsafeBytes(of: &RAM) { (rawPtr) -> Array in -// let ptr = rawPtr.baseAddress!.assumingMemoryBound(to: uint8.self) -// return Array(ptr) -// } - - // This seem to work: -// var ram: [UInt8] = [] -// withUnsafeBytes(of: &RAM) { -// ram.append(contentsOf: $0) -// } -// let string = String(bytes: ram, encoding: .utf8) - - // ...but this does not: -// let text = "" -// while(true) { -// for i in 0x400...0x7FF { -// text += screenBuffer[i] -// } -// } - // DispatchQueue.main.asyncAfter(deadline: .now() + 1/30, execute: { // self.update()