From 645c37049f866f0d4767777f0ba0f5f9d2cdce0b Mon Sep 17 00:00:00 2001 From: Ivan Izaguirre Date: Sun, 24 Feb 2019 14:37:10 +0100 Subject: [PATCH] Apple IIe rom boots with all the ROM shadowing in place. --- apple2/ansiConsoleFrontend.go | 10 +++++++ apple2/ioC0Page.go | 56 +++++++++++++++++++++++++++++++---- apple2/pagedMemory.go | 7 +---- apple2/softSwitches2e.go | 41 ++++++++++++------------- 4 files changed, 82 insertions(+), 32 deletions(-) diff --git a/apple2/ansiConsoleFrontend.go b/apple2/ansiConsoleFrontend.go index 4f85d1d..b7e4d8a 100644 --- a/apple2/ansiConsoleFrontend.go +++ b/apple2/ansiConsoleFrontend.go @@ -8,6 +8,15 @@ import ( "time" ) +/* +Uses the console standard input and output to interface with the machine. +Input is buffered until the next CR. This avoids working in place, a line +for input is added at the end. +Outut is done in place using ANSI escape sequences. + +Those tricks do not work with the Apple2e ROM +*/ + type ansiConsoleFrontend struct { keyChannel chan uint8 extraLineFeeds chan int @@ -100,6 +109,7 @@ func (fe *ansiConsoleFrontend) textModeGoRoutine(tp *textPages) { func textMemoryByteToString(value uint8) string { // See https://en.wikipedia.org/wiki/Apple_II_character_set // Only ascii from 0x20 to 0x5F is visible + // Does not support the new lowercase characters in the Apple2e topBits := value >> 6 isInverse := topBits == 0 isFlash := topBits == 1 diff --git a/apple2/ioC0Page.go b/apple2/ioC0Page.go index 6e2587c..ace87c8 100644 --- a/apple2/ioC0Page.go +++ b/apple2/ioC0Page.go @@ -22,7 +22,13 @@ type keyboardProvider interface { // See https://stason.org/TULARC/pc/apple2/programmer/004-I-d-like-to-do-some-serious-Apple-II-programming-Whe.html const ( - ioDataKeyboard uint8 = 0x10 + ssOn uint8 = 0x80 + ssOff uint8 = 0x00 +) + +const ( + ioDataKeyboard uint8 = 0x10 + ioFlagGraphics uint8 = 0x50 ioFlagMixed uint8 = 0x52 ioFlagSecondPage uint8 = 0x54 @@ -31,10 +37,19 @@ const ( ioFlagAnnunciator1 uint8 = 0x5a ioFlagAnnunciator2 uint8 = 0x5c ioFlagAnnunciator3 uint8 = 0x5e + + ioDataCassette uint8 = 0x60 + ioFlagButton0 uint8 = 0x61 + ioFlagButton1 uint8 = 0x62 + ioFlagButton2 uint8 = 0x63 + ioDataPaddle0 uint8 = 0x64 + ioDataPaddle1 uint8 = 0x65 + ioDataPaddle2 uint8 = 0x66 + ioDataPaddle3 uint8 = 0x67 ) func (p *ioC0Page) isSoftSwitchExtActive(ioFlag uint8) bool { - return (p.softSwitchesData[ioFlag] & 0x08) == 0x80 + return (p.softSwitchesData[ioFlag] & ssOn) == ssOn } func newIoC0Page(mmu *memoryManager) *ioC0Page { @@ -44,7 +59,12 @@ func newIoC0Page(mmu *memoryManager) *ioC0Page { ss[0x00] = getKeySoftSwitch // Keyboard ss[0x10] = strobeKeyboardSoftSwitch // Keyboard Strobe + ss[0x20] = notImplementedSoftSwitch // Cassette Output ss[0x30] = notImplementedSoftSwitch // Speaker + ss[0x40] = notImplementedSoftSwitch // Game connector Strobe + // Note: Some sources indicate that all these cover 16 positions + // for read and write. But the Apple2e take over some of them, with + // the prevention on acting only on writes. ss[0x50] = getSoftSwitch(ioFlagGraphics, false) ss[0x51] = getSoftSwitch(ioFlagGraphics, true) @@ -63,6 +83,24 @@ func newIoC0Page(mmu *memoryManager) *ioC0Page { ss[0x5e] = getSoftSwitch(ioFlagAnnunciator3, false) ss[0x5f] = getSoftSwitch(ioFlagAnnunciator3, true) + ss[0x60] = notImplementedSoftSwitch // Cassetter Input + ss[0x61] = getStatusSoftSwitch(ioFlagButton0) + ss[0x62] = getStatusSoftSwitch(ioFlagButton1) + ss[0x63] = getStatusSoftSwitch(ioFlagButton2) + ss[0x64] = getStatusSoftSwitch(ioDataPaddle0) + ss[0x65] = getStatusSoftSwitch(ioDataPaddle1) + ss[0x66] = getStatusSoftSwitch(ioDataPaddle2) + ss[0x67] = getStatusSoftSwitch(ioDataPaddle3) + ss[0x68] = ss[0x60] + ss[0x69] = ss[0x61] + ss[0x6A] = ss[0x62] + ss[0x6B] = ss[0x63] + ss[0x6C] = ss[0x64] + ss[0x6D] = ss[0x65] + ss[0x6E] = ss[0x66] + ss[0x6F] = ss[0x67] + ss[0x70] = notImplementedSoftSwitch // Game controllers reset + return &p } @@ -81,8 +119,8 @@ func (p *ioC0Page) Poke(address uint8, value uint8) { } func (p *ioC0Page) access(address uint8, isWrite bool, value uint8) uint8 { - // The second hals of the pages is reserved for slots - if address >= 0x80 { + // The second half of the pages is reserved for slots + if address >= 0x90 { // TODO reserved slots data return 0 } @@ -95,12 +133,18 @@ func (p *ioC0Page) access(address uint8, isWrite bool, value uint8) uint8 { return ss(p, isWrite, value) } +func getStatusSoftSwitch(ioFlag uint8) softSwitch { + return func(io *ioC0Page, isWrite bool, value uint8) uint8 { + return io.softSwitchesData[ioFlag] + } +} + func getSoftSwitch(ioFlag uint8, isSet bool) softSwitch { return func(io *ioC0Page, isWrite bool, value uint8) uint8 { if isSet { - io.softSwitchesData[ioFlag] = 0x80 + io.softSwitchesData[ioFlag] = ssOn } else { - io.softSwitchesData[ioFlag] = 0 + io.softSwitchesData[ioFlag] = ssOff } return 0 } diff --git a/apple2/pagedMemory.go b/apple2/pagedMemory.go index e3f6903..5b87160 100644 --- a/apple2/pagedMemory.go +++ b/apple2/pagedMemory.go @@ -1,10 +1,5 @@ package apple2 -import ( - "fmt" - "reflect" -) - // memoryPage is a data page of 256 bytes type memoryPage interface { Peek(uint8) uint8 @@ -32,6 +27,6 @@ func (m *pagedMemory) Poke(address uint16, value uint8) { // SetPage assigns a MemoryPage implementation on the page given func (m *pagedMemory) SetPage(index uint8, page memoryPage) { - fmt.Printf("Assigning page 0x%02x type %s\n", index, reflect.TypeOf(page)) + //fmt.Printf("Assigning page 0x%02x type %s\n", index, reflect.TypeOf(page)) m.data[index] = page } diff --git a/apple2/softSwitches2e.go b/apple2/softSwitches2e.go index 9805fbe..b61f5ee 100644 --- a/apple2/softSwitches2e.go +++ b/apple2/softSwitches2e.go @@ -1,45 +1,46 @@ package apple2 -import "fmt" - const ( ioFlagIntCxRom uint8 = 0x15 ioFlagSlotC3Rom uint8 = 0x17 + ioFlag80Store uint8 = 0x18 + ioFlag80Col uint8 = 0x1F ) func addApple2ESoftSwitches(mmu *memoryManager) { ss := &mmu.ioPage.softSwitches - ss[0x06] = getSoftSwitchExt(ioFlagIntCxRom, 0x00, softSwitchIntCxRomOff) - ss[0x07] = getSoftSwitchExt(ioFlagIntCxRom, 0x80, softSwitchIntCxRomOn) - ss[0x15] = getStatusSoftSwitchExt(ioFlagIntCxRom) - ss[0x0A] = getSoftSwitchExt(ioFlagSlotC3Rom, 0x00, softSwitchSlotC3RomOff) - ss[0x0B] = getSoftSwitchExt(ioFlagSlotC3Rom, 0x80, softSwitchSlotC3RomOn) - ss[0x17] = getStatusSoftSwitchExt(ioFlagSlotC3Rom) - - ss[0x1c] = getStatusSoftSwitchExt(ioFlagSecondPage) + ss[0x00] = getSoftSwitchExt(ioFlag80Store, ssOff, nil) + ss[0x01] = getSoftSwitchExt(ioFlag80Store, ssOn, nil) + ss[0x06] = getSoftSwitchExt(ioFlagIntCxRom, ssOff, softSwitchIntCxRomOff) + ss[0x07] = getSoftSwitchExt(ioFlagIntCxRom, ssOn, softSwitchIntCxRomOn) + ss[0x0A] = getSoftSwitchExt(ioFlagSlotC3Rom, ssOff, softSwitchSlotC3RomOff) + ss[0x0B] = getSoftSwitchExt(ioFlagSlotC3Rom, ssOn, softSwitchSlotC3RomOn) + ss[0x0C] = getSoftSwitchExt(ioFlag80Col, ssOff, nil) + ss[0x0D] = getSoftSwitchExt(ioFlag80Col, ssOn, nil) + ss[0x15] = getStatusSoftSwitch(ioFlagIntCxRom) + ss[0x17] = getStatusSoftSwitch(ioFlagSlotC3Rom) + ss[0x18] = getStatusSoftSwitch(ioFlag80Store) + ss[0x1C] = getStatusSoftSwitch(ioFlagSecondPage) + ss[0x1F] = getStatusSoftSwitch(ioFlag80Col) } type softSwitchExtAction func(io *ioC0Page) -func getStatusSoftSwitchExt(ioFlag uint8) softSwitch { - return func(io *ioC0Page, isWrite bool, value uint8) uint8 { - return io.softSwitchesData[ioFlag] - } -} - func getSoftSwitchExt(ioFlag uint8, dstValue uint8, action softSwitchExtAction) softSwitch { return func(io *ioC0Page, isWrite bool, value uint8) uint8 { - fmt.Printf("Softswitch 0x%02x %v %v\n", ioFlag, isWrite, dstValue) + //fmt.Printf("Softswitch 0x%02x %v %v\n", ioFlag, isWrite, dstValue) if !isWrite { - return 0 // Ignore reads + return 0 // New Apple2e softswitches ignore reads } currentValue := io.softSwitchesData[ioFlag] if currentValue == dstValue { return 0 // Already switched, ignore } - action(io) + if action != nil { + action(io) + } io.softSwitchesData[ioFlag] = value return 0 } @@ -53,7 +54,7 @@ func softSwitchIntCxRomOn(io *ioC0Page) { func softSwitchIntCxRomOff(io *ioC0Page) { // TODO restore all the ROM from the slot for 0xc1 to 0xc7 - for i := 1; i <= 16; i++ { + for i := 1; i < 16; i++ { io.mmu.activeMemory.SetPage(uint8(0xc0+i), &io.mmu.unassignedExpansionROM[i]) } }