From 8233b99e4334009006ebb5b3f1fe5b8fe64e651b Mon Sep 17 00:00:00 2001 From: Ivan Izaguirre Date: Sat, 18 May 2019 23:40:59 +0200 Subject: [PATCH] Experimental cards: Logger and InOut --- apple2/apple2.go | 23 +++++- apple2/apple2Setup.go | 10 +++ apple2/cardInOut.go | 147 +++++++++++++++++++++++++++++++++++++++ apple2/cardLogger.go | 43 ++++++++++++ apple2sdl/sdlKeyboard.go | 2 + main.go | 4 ++ 6 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 apple2/cardInOut.go create mode 100644 apple2/cardLogger.go diff --git a/apple2/apple2.go b/apple2/apple2.go index bd8f791..edf7263 100644 --- a/apple2/apple2.go +++ b/apple2/apple2.go @@ -39,9 +39,10 @@ func (a *Apple2) Run(log bool) { // Start the processor a.cpu.Reset() referenceTime := time.Now() + for { // Run a 6502 step - a.cpu.ExecuteInstruction(log) + a.cpu.ExecuteInstruction(log && a.cycleDurationNs != 0) // Execute meta commands commandsPending := true @@ -80,6 +81,8 @@ const ( CommandSaveState // CommandLoadState reload the last state CommandLoadState + // CommandDumpDebugInfo dumps usefull info + CommandDumpDebugInfo ) // SendCommand enqueues a command to the emulator thread @@ -105,6 +108,8 @@ func (a *Apple2) executeCommand(command int) { case CommandLoadState: fmt.Println("Loading state") a.load("apple2.state") + case CommandDumpDebugInfo: + a.dumpDebugInfo() } } @@ -172,3 +177,19 @@ func (a *Apple2) load(filename string) { } } } + +func (a *Apple2) dumpDebugInfo() { + // See "Apple II Monitors Peeled" + pageZeroSymbols := map[int]string{ + 0x36: "CSWL", + 0x37: "CSWH", + 0x38: "KSWL", + 0x39: "KSWH", + } + + fmt.Printf("Page zero values:\n") + for _, k := range []int{0x36, 0x37, 0x38, 0x39} { + d := a.mmu.physicalMainRAM.data[k] + fmt.Printf(" %v(0x%x): 0x%02x\n", pageZeroSymbols[k], k, d) + } +} diff --git a/apple2/apple2Setup.go b/apple2/apple2Setup.go index 0ff4ec5..4ab0bf7 100644 --- a/apple2/apple2Setup.go +++ b/apple2/apple2Setup.go @@ -60,6 +60,16 @@ func (a *Apple2) AddSaturnCard(slot int) { a.insertCard(&cardSaturn{}, slot) } +// AddCardLogger inserts a fake card that logs accesses +func (a *Apple2) AddCardLogger(slot int) { + a.insertCard(&cardLogger{}, slot) +} + +// AddCardInOut inserts a fake card that interfaces with the emulator host +func (a *Apple2) AddCardInOut(slot int) { + a.insertCard(&cardInOut{}, slot) +} + // ConfigureStdConsole uses stdin and stdout to interface with the Apple2 func (a *Apple2) ConfigureStdConsole(stdinKeyboard bool, stdoutScreen bool) { if !stdinKeyboard && !stdoutScreen { diff --git a/apple2/cardInOut.go b/apple2/cardInOut.go new file mode 100644 index 0000000..e9170c3 --- /dev/null +++ b/apple2/cardInOut.go @@ -0,0 +1,147 @@ +package apple2 + +import ( + "fmt" +) + +/* +In out card experiment to interface with the emulator host. + +See: + "Apple II Monitors peeled." + http://mysite.du.edu/~etuttle/math/acia.htm + +*/ + +type cardInOut struct { + cardBase + i int +} + +func (c *cardInOut) assign(a *Apple2, slot int) { + for i := 0x0; i <= 0xf; i++ { + iCopy := i + c.ssr[i] = func(*ioC0Page) uint8 { + value := []uint8{0xc1, 0xc1, 0x93, 0x0}[c.i%4] + c.i++ + fmt.Printf("[cardInOut] Read access to softswith 0x%x for slot %v, value %x.\n", iCopy, slot, value) + //return 0x41 + 0x80 + return []uint8{0x41, 0x41, 0x13}[i%3] + 0x80 + } + c.ssw[i] = func(_ *ioC0Page, value uint8) { + fmt.Printf("[cardInOut] Write access to softswith 0x%x for slot %v, value 0x%x.\n", iCopy, slot, value) + } + } + + in := true + out := false + + data := [256]uint8{ + // Register + 0xA9, 0xC2, + 0x85, 0x37, + 0x85, 0x39, + 0xA9, 0x10, + 0x85, 0x36, + 0xA9, 0x15, + 0x85, 0x38, + 0x60, 0xEA, + + // Out char + 0x8D, 0xA1, 0xC0, + 0x60, 0xEA, + + // Get char + 0x91, 0x28, + 0xAD, 0xA0, 0xC0, + 0x60, + } + + if !out { + // NOP the CSWL,H change + for _, v := range []uint8{2, 3, 8, 9} { + data[v] = 0xEA + } + } + + if !in { + // NOP the KSWL,H change + for _, v := range []uint8{4, 5, 12, 13} { + data[v] = 0xEA + } + } + + c.rom = newMemoryRange(0xC200, data[0:255]) + + if slot != 2 { + // To make ifwork on other slots, patch C2, A0 and A1 + panic("Only slot 2 supported for the InOut card") + } + c.cardBase.assign(a, slot) +} + +/* +The ROM code was assembled using https://www.masswerk.at/6502/assembler.html + +src: + BASL = $28 + CSWL = $36 + CSWH = $37 + KSWL = $38 + KSWH = $39 + + * = $C200 + Register: + LDA #$C2 + STA *CSWH + STA *KSWH + LDA #$10 + STA *CSWL + LDA #$15 + STA *KSWL + RTS + NOP + OutChar: + STA $C0A1 + RTS + NOP + GetChar: + STA (BASL),Y + LDA $C0A0 + RTS + + +assembled as: +0000 BASL = 0028 +0000 CSWL = 0036 +0000 CSWH = 0037 +0000 KSWL = 0038 +0000 KSWH = 0039 + +* = $C200 +C200 REGIST +C200 LDA #$C2 A9 C2 +C202 STA *CSWH 85 37 +C204 STA *KSWH 85 39 +C206 LDA #$10 A9 10 +C208 STA *CSWL 85 36 +C20A LDA #$15 A9 15 +C20C STA *KSWL 85 38 +C20E RTS 60 +C20F NOP EA +C210 OUTCHA +C210 STA $C0A1 8D A1 C0 +C213 RTS 60 +C214 NOP EA +C215 GETCHA +C215 STA (BASL),Y 91 28 +C217 LDA $C0A0 AD A0 C0 +C21A RTS + +object code: +A9 C2 85 37 85 39 A9 10 +85 36 A9 15 85 38 60 EA +8D A1 C0 60 EA 91 28 AD +A0 C0 60 + +*/ diff --git a/apple2/cardLogger.go b/apple2/cardLogger.go new file mode 100644 index 0000000..eadf445 --- /dev/null +++ b/apple2/cardLogger.go @@ -0,0 +1,43 @@ +package apple2 + +import ( + "fmt" +) + +/* +Logger card. It never existed, I use it to trace accesses to the card. +*/ + +type cardLogger struct { + cardBase +} + +func (c *cardLogger) assign(a *Apple2, slot int) { + for i := 0x0; i <= 0xf; i++ { + iCopy := i + c.ssr[i] = func(*ioC0Page) uint8 { + fmt.Printf("[cardLogger] Read access to softswith 0x%x for slot %v.\n", iCopy, slot) + return 0 + } + c.ssw[i] = func(_ *ioC0Page, value uint8) { + fmt.Printf("[cardLogger] Write access to softswith 0x%x for slot %v, value 0x%v.\n", iCopy, slot, value) + } + } + + if slot != 0 { + a.mmu.setPagesRead(uint8(0xc0+slot), uint8(0xc0+slot), c) + } + c.cardBase.assign(a, slot) +} + +// MemoryHandler implementation +func (c *cardLogger) peek(address uint16) uint8 { + fmt.Printf("[cardLogger] Read in %x.\n", address) + c.a.dumpDebugInfo() + + return 0xf3 +} + +func (*cardLogger) poke(address uint16, value uint8) { + fmt.Printf("[cardLogger] Write %x in %x.\n", value, address) +} diff --git a/apple2sdl/sdlKeyboard.go b/apple2sdl/sdlKeyboard.go index 9b5146a..e608b87 100644 --- a/apple2sdl/sdlKeyboard.go +++ b/apple2sdl/sdlKeyboard.go @@ -97,6 +97,8 @@ func (k *sdlKeyboard) putKey(keyEvent *sdl.KeyboardEvent) { k.a.SendCommand(apple2.CommandSaveState) case sdl.K_F8: k.a.SendCommand(apple2.CommandLoadState) + case sdl.K_F9: + k.a.SendCommand(apple2.CommandDumpDebugInfo) } // Missing values 91 to 95. Usually control for [\]^_ diff --git a/main.go b/main.go index 47c06e0..73c8d49 100644 --- a/main.go +++ b/main.go @@ -87,6 +87,10 @@ func main() { if *disk2Slot >= 0 { a.AddDisk2(*disk2Slot, *disk2RomFile, *diskImage) } + + //a.AddCardInOut(2) + //a.AddCardLogger(4) + if *useSdl { a.ConfigureStdConsole(false, *stdoutScreen) apple2sdl.SDLRun(a)