Nanmed sotfswitches for easier traces.

This commit is contained in:
Ivan Izaguirre 2019-10-21 00:00:42 +02:00 committed by Iván Izaguirre
parent 61dae23726
commit d5433ad8d9
13 changed files with 181 additions and 137 deletions

View File

@ -26,15 +26,15 @@ func newBase64a() *Apple2 {
} }
func addBase64aSoftSwitches(io *ioC0Page) { func addBase64aSoftSwitches(io *ioC0Page) {
// Other softswitches // Other softswitches, not implemented but called from the ROM
io.addSoftSwitchW(0x0C, notImplementedSoftSwitchW) // 80 columns off? io.addSoftSwitchW(0x0C, notImplementedSoftSwitchW, "80COLOFF")
io.addSoftSwitchW(0x0E, notImplementedSoftSwitchW) // Alt char off? io.addSoftSwitchW(0x0E, notImplementedSoftSwitchW, "ALTCHARSETOFF")
// Write on the speaker. That is a double access and should do nothing // Write on the speaker. That is a double access and should do nothing
// but works somehow on the BASE64A // but works somehow on the BASE64A
io.addSoftSwitchW(0x30, func(io *ioC0Page, value uint8) { io.addSoftSwitchW(0x30, func(io *ioC0Page, value uint8) {
speakerSoftSwitch(io) speakerSoftSwitch(io)
}) }, "SPEAKER")
} }
func charGenColumnsMapBase64a(column int) int { func charGenColumnsMapBase64a(column int) int {

View File

@ -55,19 +55,19 @@ func loadBase64aRom(a *Apple2) error {
a.io.addSoftSwitchRW(0x58, func(*ioC0Page) uint8 { a.io.addSoftSwitchRW(0x58, func(*ioC0Page) uint8 {
r.changeBank(a.mmu, r.romBank&2) r.changeBank(a.mmu, r.romBank&2)
return 0 return 0
}) }, "ANN0OFF-ROM")
a.io.addSoftSwitchRW(0x59, func(*ioC0Page) uint8 { a.io.addSoftSwitchRW(0x59, func(*ioC0Page) uint8 {
r.changeBank(a.mmu, r.romBank|1) r.changeBank(a.mmu, r.romBank|1)
return 0 return 0
}) }, "ANN0ON-ROM")
a.io.addSoftSwitchRW(0x5A, func(*ioC0Page) uint8 { a.io.addSoftSwitchRW(0x5A, func(*ioC0Page) uint8 {
r.changeBank(a.mmu, r.romBank&1) r.changeBank(a.mmu, r.romBank&1)
return 0 return 0
}) }, "ANN1OFF-ROM")
a.io.addSoftSwitchRW(0x5B, func(*ioC0Page) uint8 { a.io.addSoftSwitchRW(0x5B, func(*ioC0Page) uint8 {
r.changeBank(a.mmu, r.romBank|2) r.changeBank(a.mmu, r.romBank|2)
return 0 return 0
}) }, "ANN1ON-ROM")
return nil return nil
} }

View File

@ -15,8 +15,10 @@ type cardBase struct {
rom *memoryRange rom *memoryRange
romExtra *memoryRange romExtra *memoryRange
slot int slot int
ssr [16]softSwitchR _ssr [16]softSwitchR
ssw [16]softSwitchW _ssw [16]softSwitchW
_ssrName [16]string
_sswName [16]string
} }
func (c *cardBase) loadRom(data []uint8) { func (c *cardBase) loadRom(data []uint8) {
@ -45,11 +47,21 @@ func (c *cardBase) assign(a *Apple2, slot int) {
} }
for i := 0; i < 0x10; i++ { for i := 0; i < 0x10; i++ {
a.io.addSoftSwitchR(uint8(0xC80+slot*0x10+i), c.ssr[i]) a.io.addSoftSwitchR(uint8(0xC80+slot*0x10+i), c._ssr[i], c._ssrName[i])
a.io.addSoftSwitchW(uint8(0xC80+slot*0x10+i), c.ssw[i]) a.io.addSoftSwitchW(uint8(0xC80+slot*0x10+i), c._ssw[i], c._sswName[i])
} }
} }
func (c *cardBase) addCardSoftSwitchR(address uint8, ss softSwitchR, name string) {
c._ssr[address] = ss
c._ssrName[address] = name
}
func (c *cardBase) addCardSoftSwitchW(address uint8, ss softSwitchW, name string) {
c._ssw[address] = ss
c._sswName[address] = name
}
func (c *cardBase) save(w io.Writer) error { func (c *cardBase) save(w io.Writer) error {
// Empty // Empty
return nil return nil

View File

@ -2,6 +2,7 @@ package apple2
import ( import (
"encoding/binary" "encoding/binary"
"fmt"
"io" "io"
) )
@ -33,7 +34,7 @@ type cardDisk2 struct {
type cardDisk2Drive struct { type cardDisk2Drive struct {
diskette *diskette16sector diskette *diskette16sector
currentPhase int currentPhase uint8
power bool // q4 power bool // q4
halfTrack int halfTrack int
position int position int
@ -50,12 +51,13 @@ const (
func (c *cardDisk2) assign(a *Apple2, slot int) { func (c *cardDisk2) assign(a *Apple2, slot int) {
// Q1, Q2, Q3 and Q4 phase control soft switches, // Q1, Q2, Q3 and Q4 phase control soft switches,
for i := 0; i < 4; i++ { for i := uint8(0); i < 4; i++ {
phase := i phase := i
c.ssr[phase<<1] = func(_ *ioC0Page) uint8 { c.addCardSoftSwitchR(phase<<1, func(_ *ioC0Page) uint8 {
return c.dataLatch // All even addresses return the last dataLatch return c.dataLatch // All even addresses return the last dataLatch
} }, fmt.Sprintf("PHASE%vOFF", phase))
c.ssr[(phase<<1)+1] = func(_ *ioC0Page) uint8 {
c.addCardSoftSwitchR((phase<<1)+1, func(_ *ioC0Page) uint8 {
// Move the head up or down depending on the previous phase. // Move the head up or down depending on the previous phase.
drive := &c.drive[c.selected] drive := &c.drive[c.selected]
delta := (phase - drive.currentPhase + 4) % 4 delta := (phase - drive.currentPhase + 4) % 4
@ -79,50 +81,50 @@ func (c *cardDisk2) assign(a *Apple2, slot int) {
drive.currentPhase = phase drive.currentPhase = phase
//fmt.Printf("DISKII: Current halftrack is %v\n", drive.halfTrack) //fmt.Printf("DISKII: Current halftrack is %v\n", drive.halfTrack)
return 0 return 0
} }, fmt.Sprintf("PHASE%vOFF", phase))
} }
// Q4, power switch // Q4, power switch
c.ssr[0x8] = func(_ *ioC0Page) uint8 { c.addCardSoftSwitchR(0x8, func(_ *ioC0Page) uint8 {
if c.drive[c.selected].power { if c.drive[c.selected].power {
c.drive[c.selected].power = false c.drive[c.selected].power = false
c.a.releaseFastMode() c.a.releaseFastMode()
} }
return c.dataLatch return c.dataLatch
} }, "Q4DRIVEOFF")
c.ssr[0x9] = func(_ *ioC0Page) uint8 { c.addCardSoftSwitchR(0x9, func(_ *ioC0Page) uint8 {
if !c.drive[c.selected].power { if !c.drive[c.selected].power {
c.drive[c.selected].power = true c.drive[c.selected].power = true
c.a.requestFastMode() c.a.requestFastMode()
} }
return 0 return 0
} }, "")
// Q5, drive selecion // Q5, drive selecion
c.ssr[0xA] = func(_ *ioC0Page) uint8 { c.addCardSoftSwitchR(0xA, func(_ *ioC0Page) uint8 {
c.selected = 0 c.selected = 0
return c.dataLatch return c.dataLatch
} }, "Q5SELECT1")
c.ssr[0xB] = func(_ *ioC0Page) uint8 { c.addCardSoftSwitchR(0xB, func(_ *ioC0Page) uint8 {
c.selected = 1 c.selected = 1
return 0 return 0
} }, "Q5SELECT2")
// Q6, Q7 // Q6, Q7
for i := 0xC; i <= 0xF; i++ { for i := uint8(0xC); i <= 0xF; i++ {
iCopy := i iCopy := i
c.ssr[iCopy] = func(_ *ioC0Page) uint8 { c.addCardSoftSwitchR(iCopy, func(_ *ioC0Page) uint8 {
return c.softSwitchQ6Q7(iCopy, 0) return c.softSwitchQ6Q7(iCopy, 0)
} }, "Q6Q7")
c.ssw[iCopy] = func(_ *ioC0Page, value uint8) { c.addCardSoftSwitchW(iCopy, func(_ *ioC0Page, value uint8) {
c.softSwitchQ6Q7(iCopy, value) c.softSwitchQ6Q7(iCopy, value)
} }, "Q6Q7")
} }
c.cardBase.assign(a, slot) c.cardBase.assign(a, slot)
} }
func (c *cardDisk2) softSwitchQ6Q7(index int, in uint8) uint8 { func (c *cardDisk2) softSwitchQ6Q7(index uint8, in uint8) uint8 {
switch index { switch index {
case 0xC: // Q6L case 0xC: // Q6L
c.q6 = false c.q6 = false

View File

@ -77,7 +77,7 @@ const (
) )
func (c *cardHardDisk) assign(a *Apple2, slot int) { func (c *cardHardDisk) assign(a *Apple2, slot int) {
c.ssr[0] = func(*ioC0Page) uint8 { c.addCardSoftSwitchR(0, func(*ioC0Page) uint8 {
// Prodos entry point // Prodos entry point
command := a.mmu.Peek(0x42) command := a.mmu.Peek(0x42)
@ -99,15 +99,15 @@ func (c *cardHardDisk) assign(a *Apple2, slot int) {
// Prodos device command not supported // Prodos device command not supported
return proDosDeviceErrorIO return proDosDeviceErrorIO
} }
} }, "HDCOMMAND")
c.ssr[1] = func(*ioC0Page) uint8 { c.addCardSoftSwitchR(1, func(*ioC0Page) uint8 {
// Blocks available, low byte // Blocks available, low byte
return uint8(c.disk.header.Blocks) return uint8(c.disk.header.Blocks)
} }, "HDBLOCKSLO")
c.ssr[2] = func(*ioC0Page) uint8 { c.addCardSoftSwitchR(2, func(*ioC0Page) uint8 {
// Blocks available, high byte // Blocks available, high byte
return uint8(c.disk.header.Blocks >> 8) return uint8(c.disk.header.Blocks >> 8)
} }, "HDBLOCKHI")
c.cardBase.assign(a, slot) c.cardBase.assign(a, slot)
} }

View File

@ -19,18 +19,18 @@ type cardInOut struct {
} }
func (c *cardInOut) assign(a *Apple2, slot int) { func (c *cardInOut) assign(a *Apple2, slot int) {
for i := 0x0; i <= 0xf; i++ { for i := uint8(0x0); i <= 0xf; i++ {
iCopy := i iCopy := i
c.ssr[i] = func(*ioC0Page) uint8 { c.addCardSoftSwitchR(i, func(*ioC0Page) uint8 {
value := []uint8{0xc1, 0xc1, 0x93, 0x0}[c.i%4] value := []uint8{0xc1, 0xc1, 0x93, 0x0}[c.i%4]
c.i++ c.i++
fmt.Printf("[cardInOut] Read access to softswith 0x%x for slot %v, value %x.\n", iCopy, slot, value) fmt.Printf("[cardInOut] Read access to softswith 0x%x for slot %v, value %x.\n", iCopy, slot, value)
//return 0x41 + 0x80 //return 0x41 + 0x80
return []uint8{0x41, 0x41, 0x13}[i%3] + 0x80 return []uint8{0x41, 0x41, 0x13}[i%3] + 0x80
} }, "INOUTR")
c.ssw[i] = func(_ *ioC0Page, value uint8) { c.addCardSoftSwitchW(i, func(_ *ioC0Page, value uint8) {
fmt.Printf("[cardInOut] Write access to softswith 0x%x for slot %v, value 0x%x.\n", iCopy, slot, value) fmt.Printf("[cardInOut] Write access to softswith 0x%x for slot %v, value 0x%x.\n", iCopy, slot, value)
} }, "INOUTW")
} }
in := true in := true

View File

@ -31,8 +31,8 @@ and selects the second 4K bank to map $D000-$DFFF."
type cardLanguage struct { type cardLanguage struct {
cardBase cardBase
readState bool readState bool
writeState int writeState uint8
activeBank int activeBank uint8
ramBankA *memoryRange // First 4kb to map in 0xD000-0xDFFF ramBankA *memoryRange // First 4kb to map in 0xD000-0xDFFF
ramBankB *memoryRange // Second 4kb to map in 0xD000-0xDFFF ramBankB *memoryRange // Second 4kb to map in 0xD000-0xDFFF
ramUpper *memoryRange // Upper 8kb to map in 0xE000-0xFFFF ramUpper *memoryRange // Upper 8kb to map in 0xE000-0xFFFF
@ -54,22 +54,22 @@ func (c *cardLanguage) assign(a *Apple2, slot int) {
c.ramBankB = newMemoryRange(0xd000, make([]uint8, 0x1000)) c.ramBankB = newMemoryRange(0xd000, make([]uint8, 0x1000))
c.ramUpper = newMemoryRange(0xe000, make([]uint8, 0x2000)) c.ramUpper = newMemoryRange(0xe000, make([]uint8, 0x2000))
for i := 0x0; i <= 0xf; i++ { for i := uint8(0x0); i <= 0xf; i++ {
iCopy := i iCopy := i
c.ssr[iCopy] = func(*ioC0Page) uint8 { c.addCardSoftSwitchR(iCopy, func(*ioC0Page) uint8 {
c.ssAction(iCopy, false) c.ssAction(iCopy, false)
return 0 return 0
} }, "LANGCARDR")
c.ssw[iCopy] = func(*ioC0Page, uint8) { c.addCardSoftSwitchW(iCopy, func(*ioC0Page, uint8) {
c.ssAction(iCopy, true) c.ssAction(iCopy, true)
} }, "LANGCARDW")
} }
c.cardBase.assign(a, slot) c.cardBase.assign(a, slot)
c.applyState() c.applyState()
} }
func (c *cardLanguage) ssAction(ss int, write bool) { func (c *cardLanguage) ssAction(ss uint8, write bool) {
c.activeBank = (ss >> 3) & 1 c.activeBank = (ss >> 3) & 1
action := ss & 0x3 action := ss & 0x3
switch action { switch action {

View File

@ -13,15 +13,15 @@ type cardLogger struct {
} }
func (c *cardLogger) assign(a *Apple2, slot int) { func (c *cardLogger) assign(a *Apple2, slot int) {
for i := 0x0; i <= 0xf; i++ { for i := uint8(0x0); i <= 0xf; i++ {
iCopy := i iCopy := i
c.ssr[i] = func(*ioC0Page) uint8 { c.addCardSoftSwitchR(i, func(*ioC0Page) uint8 {
fmt.Printf("[cardLogger] Read access to softswith 0x%x for slot %v.\n", iCopy, slot) fmt.Printf("[cardLogger] Read access to softswith 0x%x for slot %v.\n", iCopy, slot)
return 0 return 0
} }, "LOGGERR")
c.ssw[i] = func(_ *ioC0Page, value uint8) { c.addCardSoftSwitchW(i, func(_ *ioC0Page, value uint8) {
fmt.Printf("[cardLogger] Write access to softswith 0x%x for slot %v, value 0x%v.\n", iCopy, slot, value) fmt.Printf("[cardLogger] Write access to softswith 0x%x for slot %v, value 0x%v.\n", iCopy, slot, value)
} }, "LOGGERW")
} }
if slot != 0 { if slot != 0 {

View File

@ -16,9 +16,9 @@ http://www.applelogic.org/files/SATURN128MAN.pdf
type cardSaturn struct { type cardSaturn struct {
cardBase cardBase
readState bool readState bool
writeState int writeState uint8
activeBank int activeBank uint8
activeBlock int activeBlock uint8
ramBankA [saturnBlocks]*memoryRange // First 4kb to map in 0xD000-0xDFFF ramBankA [saturnBlocks]*memoryRange // First 4kb to map in 0xD000-0xDFFF
ramBankB [saturnBlocks]*memoryRange // Second 4kb to map in 0xD000-0xDFFF ramBankB [saturnBlocks]*memoryRange // Second 4kb to map in 0xD000-0xDFFF
ramUpper [saturnBlocks]*memoryRange // Upper 8kb to map in 0xE000-0xFFFF ramUpper [saturnBlocks]*memoryRange // Upper 8kb to map in 0xE000-0xFFFF
@ -45,21 +45,21 @@ func (c *cardSaturn) assign(a *Apple2, slot int) {
c.ramBankB[i] = newMemoryRange(0xd000, make([]uint8, 0x1000)) c.ramBankB[i] = newMemoryRange(0xd000, make([]uint8, 0x1000))
c.ramUpper[i] = newMemoryRange(0xe000, make([]uint8, 0x2000)) c.ramUpper[i] = newMemoryRange(0xe000, make([]uint8, 0x2000))
} }
for i := 0x0; i <= 0xf; i++ { for i := uint8(0x0); i <= 0xf; i++ {
iCopy := i iCopy := i
c.ssr[iCopy] = func(*ioC0Page) uint8 { c.addCardSoftSwitchR(iCopy, func(*ioC0Page) uint8 {
c.ssAction(iCopy, false) c.ssAction(iCopy, false)
return 0 return 0
} }, "SATURNR")
c.ssw[iCopy] = func(*ioC0Page, uint8) { c.addCardSoftSwitchW(iCopy, func(*ioC0Page, uint8) {
c.ssAction(iCopy, true) c.ssAction(iCopy, true)
} }, "SATURNW")
} }
c.cardBase.assign(a, slot) c.cardBase.assign(a, slot)
c.applyState() c.applyState()
} }
func (c *cardSaturn) ssAction(ss int, write bool) { func (c *cardSaturn) ssAction(ss uint8, write bool) {
switch ss { switch ss {
case 0: case 0:
// RAM read, no writes // RAM read, no writes

View File

@ -25,16 +25,16 @@ type cardThunderClockPlus struct {
} }
func (c *cardThunderClockPlus) assign(a *Apple2, slot int) { func (c *cardThunderClockPlus) assign(a *Apple2, slot int) {
c.ssr[0] = func(*ioC0Page) uint8 { c.addCardSoftSwitchR(0, func(*ioC0Page) uint8 {
bit := c.microPD1990ac.out() bit := c.microPD1990ac.out()
// Get the next data bit from uPD1990AC on the MSB // Get the next data bit from uPD1990AC on the MSB
if bit { if bit {
return 0x80 return 0x80
} }
return 0 return 0
} }, "THUNDERCLOCKR")
c.ssw[0] = func(_ *ioC0Page, value uint8) { c.addCardSoftSwitchW(0, func(_ *ioC0Page, value uint8) {
dataIn := (value & 0x01) == 1 dataIn := (value & 0x01) == 1
clock := ((value >> 1) & 0x01) == 1 clock := ((value >> 1) & 0x01) == 1
strobe := ((value >> 2) & 0x01) == 1 strobe := ((value >> 2) & 0x01) == 1
@ -43,7 +43,7 @@ func (c *cardThunderClockPlus) assign(a *Apple2, slot int) {
dataIn, clock, strobe, command) */ dataIn, clock, strobe, command) */
c.microPD1990ac.in(clock, strobe, command, dataIn) c.microPD1990ac.in(clock, strobe, command, dataIn)
} }, "THUNDERCLOCKW")
c.cardBase.assign(a, slot) c.cardBase.assign(a, slot)
} }

View File

@ -9,6 +9,8 @@ import (
type ioC0Page struct { type ioC0Page struct {
softSwitchesR [256]softSwitchR softSwitchesR [256]softSwitchR
softSwitchesW [256]softSwitchW softSwitchesW [256]softSwitchW
softSwitchesRName [256]string
softSwitchesWName [256]string
softSwitchesData [128]uint8 softSwitchesData [128]uint8
keyboard KeyboardProvider keyboard KeyboardProvider
speaker SpeakerProvider speaker SpeakerProvider
@ -69,25 +71,27 @@ func (p *ioC0Page) load(r io.Reader) error {
return binary.Read(r, binary.BigEndian, &p.softSwitchesData) return binary.Read(r, binary.BigEndian, &p.softSwitchesData)
} }
func (p *ioC0Page) addSoftSwitchRW(address uint8, ss softSwitchR) { func (p *ioC0Page) addSoftSwitchRW(address uint8, ss softSwitchR, name string) {
p.addSoftSwitchR(address, ss) p.addSoftSwitchR(address, ss, name)
p.addSoftSwitchW(address, func(p *ioC0Page, _ uint8) { p.addSoftSwitchW(address, func(p *ioC0Page, _ uint8) {
ss(p) ss(p)
}) }, name)
} }
func (p *ioC0Page) addSoftSwitchR(address uint8, ss softSwitchR) { func (p *ioC0Page) addSoftSwitchR(address uint8, ss softSwitchR, name string) {
//if p.softSwitchesR[address] != nil { //if p.softSwitchesR[address] != nil {
// fmt.Printf("Addresss 0x0c%02x is already assigned for read\n", address) // fmt.Printf("Addresss 0x0c%02x is already assigned for read\n", address)
//} //}
p.softSwitchesR[address] = ss p.softSwitchesR[address] = ss
p.softSwitchesRName[address] = name
} }
func (p *ioC0Page) addSoftSwitchW(address uint8, ss softSwitchW) { func (p *ioC0Page) addSoftSwitchW(address uint8, ss softSwitchW, name string) {
//if p.softSwitchesW[address] != nil { //if p.softSwitchesW[address] != nil {
// fmt.Printf("Addresss 0x0c%02x is already assigned for write\n", address) // fmt.Printf("Addresss 0x0c%02x is already assigned for write\n", address)
//} //}
p.softSwitchesW[address] = ss p.softSwitchesW[address] = ss
p.softSwitchesWName[address] = name
} }
func (p *ioC0Page) isSoftSwitchActive(ioFlag uint8) bool { func (p *ioC0Page) isSoftSwitchActive(ioFlag uint8) bool {
@ -116,16 +120,14 @@ func (p *ioC0Page) peek(address uint16) uint8 {
return 0 return 0
} }
value := ss(p) value := ss(p)
if p.trace { if p.trace && address != 0xc000 {
fmt.Printf("Softswitch peek on $%04x: $%02x\n", address, value) name := p.softSwitchesRName[pageAddress]
fmt.Printf("Softswitch peek on $%04x %v: $%02x\n", address, name, value)
} }
return value return value
} }
func (p *ioC0Page) poke(address uint16, value uint8) { func (p *ioC0Page) poke(address uint16, value uint8) {
if p.trace {
fmt.Printf("Softswtich poke on $%04x with %02x\n", address, value)
}
pageAddress := uint8(address) pageAddress := uint8(address)
ss := p.softSwitchesW[pageAddress] ss := p.softSwitchesW[pageAddress]
if ss == nil { if ss == nil {
@ -134,5 +136,9 @@ func (p *ioC0Page) poke(address uint16, value uint8) {
} }
return return
} }
if p.trace && address != 0xc000 {
name := p.softSwitchesWName[pageAddress]
fmt.Printf("Softswitch poke on $%04x %v with $%02x\n", address, name, value)
}
ss(p, value) ss(p, value)
} }

View File

@ -24,53 +24,53 @@ const (
func addApple2SoftSwitches(io *ioC0Page) { func addApple2SoftSwitches(io *ioC0Page) {
io.addSoftSwitchRW(0x00, keySoftSwitch) // Keyboard io.addSoftSwitchRW(0x00, keySoftSwitch, "KEYBOARD") // Keyboard
io.addSoftSwitchRW(0x10, strobeKeyboardSoftSwitch) // Keyboard Strobe io.addSoftSwitchRW(0x10, strobeKeyboardSoftSwitch, "AKD") // Keyboard Strobe
io.addSoftSwitchR(0x20, notImplementedSoftSwitchR) // Cassette Output io.addSoftSwitchR(0x20, notImplementedSoftSwitchR, "TAPEOUT") // Cassette Output
io.addSoftSwitchR(0x30, speakerSoftSwitch) // Speaker io.addSoftSwitchR(0x30, speakerSoftSwitch, "SPEAKER") // Speaker
io.addSoftSwitchR(0x40, notImplementedSoftSwitchR) // Game connector Strobe io.addSoftSwitchR(0x40, notImplementedSoftSwitchR, "STROBE") // Game connector Strobe
// Note: Some sources indicate that all these cover 16 positions // Note: Some sources indicate that all these cover 16 positions
// for read and write. But the Apple2e take over some of them, with // for read and write. But the Apple2e take over some of them, with
// the prevention on acting only on writes. // the prevention on acting only on writes.
io.addSoftSwitchRW(0x50, getSoftSwitch(ioFlagText, false)) io.addSoftSwitchRW(0x50, getSoftSwitch(ioFlagText, false), "TEXTOFF")
io.addSoftSwitchRW(0x51, getSoftSwitch(ioFlagText, true)) io.addSoftSwitchRW(0x51, getSoftSwitch(ioFlagText, true), "TEXTON")
io.addSoftSwitchRW(0x52, getSoftSwitch(ioFlagMixed, false)) io.addSoftSwitchRW(0x52, getSoftSwitch(ioFlagMixed, false), "MIXEDOFF")
io.addSoftSwitchRW(0x53, getSoftSwitch(ioFlagMixed, true)) io.addSoftSwitchRW(0x53, getSoftSwitch(ioFlagMixed, true), "MIXEDON")
io.addSoftSwitchRW(0x54, getSoftSwitch(ioFlagSecondPage, false)) io.addSoftSwitchRW(0x54, getSoftSwitch(ioFlagSecondPage, false), "PAGE2OFF")
io.addSoftSwitchRW(0x55, getSoftSwitch(ioFlagSecondPage, true)) io.addSoftSwitchRW(0x55, getSoftSwitch(ioFlagSecondPage, true), "PAGE2ON")
io.addSoftSwitchRW(0x56, getSoftSwitch(ioFlagHiRes, false)) io.addSoftSwitchRW(0x56, getSoftSwitch(ioFlagHiRes, false), "HIRESOFF")
io.addSoftSwitchRW(0x57, getSoftSwitch(ioFlagHiRes, true)) io.addSoftSwitchRW(0x57, getSoftSwitch(ioFlagHiRes, true), "HIRESON")
io.addSoftSwitchRW(0x58, getSoftSwitch(ioFlagAnnunciator0, false)) io.addSoftSwitchRW(0x58, getSoftSwitch(ioFlagAnnunciator0, false), "ANN0OFF")
io.addSoftSwitchRW(0x59, getSoftSwitch(ioFlagAnnunciator0, true)) io.addSoftSwitchRW(0x59, getSoftSwitch(ioFlagAnnunciator0, true), "ANN0ON")
io.addSoftSwitchRW(0x5a, getSoftSwitch(ioFlagAnnunciator1, false)) io.addSoftSwitchRW(0x5a, getSoftSwitch(ioFlagAnnunciator1, false), "ANN1OFF")
io.addSoftSwitchRW(0x5b, getSoftSwitch(ioFlagAnnunciator1, true)) io.addSoftSwitchRW(0x5b, getSoftSwitch(ioFlagAnnunciator1, true), "ANN1ON")
io.addSoftSwitchRW(0x5c, getSoftSwitch(ioFlagAnnunciator2, false)) io.addSoftSwitchRW(0x5c, getSoftSwitch(ioFlagAnnunciator2, false), "ANN2OFF")
io.addSoftSwitchRW(0x5d, getSoftSwitch(ioFlagAnnunciator2, true)) io.addSoftSwitchRW(0x5d, getSoftSwitch(ioFlagAnnunciator2, true), "ANN2ON")
io.addSoftSwitchRW(0x5e, getSoftSwitch(ioFlagAnnunciator3, false)) io.addSoftSwitchRW(0x5e, getSoftSwitch(ioFlagAnnunciator3, false), "ANN3OFF")
io.addSoftSwitchRW(0x5f, getSoftSwitch(ioFlagAnnunciator3, true)) io.addSoftSwitchRW(0x5f, getSoftSwitch(ioFlagAnnunciator3, true), "ANN3ON")
io.addSoftSwitchR(0x60, notImplementedSoftSwitchR) // Cassette Input io.addSoftSwitchR(0x60, notImplementedSoftSwitchR, "CASSETTE") // Cassette Input
io.addSoftSwitchR(0x61, getButtonSoftSwitch(0)) io.addSoftSwitchR(0x61, getButtonSoftSwitch(0), "PB0")
io.addSoftSwitchR(0x62, getButtonSoftSwitch(1)) io.addSoftSwitchR(0x62, getButtonSoftSwitch(1), "PB1")
io.addSoftSwitchR(0x63, getButtonSoftSwitch(2)) io.addSoftSwitchR(0x63, getButtonSoftSwitch(2), "PB2")
io.addSoftSwitchR(0x64, getPaddleSoftSwitch(0)) io.addSoftSwitchR(0x64, getPaddleSoftSwitch(0), "PDL0")
io.addSoftSwitchR(0x65, getPaddleSoftSwitch(1)) io.addSoftSwitchR(0x65, getPaddleSoftSwitch(1), "PDL1")
io.addSoftSwitchR(0x66, getPaddleSoftSwitch(2)) io.addSoftSwitchR(0x66, getPaddleSoftSwitch(2), "PDL2")
io.addSoftSwitchR(0x67, getPaddleSoftSwitch(3)) io.addSoftSwitchR(0x67, getPaddleSoftSwitch(3), "PDL3")
// The previous 8 softswitches are repeated // The previous 8 softswitches are repeated
io.addSoftSwitchR(0x68, notImplementedSoftSwitchR) // Cassette Input io.addSoftSwitchR(0x68, notImplementedSoftSwitchR, "CASSETTE") // Cassette Input
io.addSoftSwitchR(0x69, getButtonSoftSwitch(0)) io.addSoftSwitchR(0x69, getButtonSoftSwitch(0), "PB0")
io.addSoftSwitchR(0x6A, getButtonSoftSwitch(1)) io.addSoftSwitchR(0x6A, getButtonSoftSwitch(1), "PB1")
io.addSoftSwitchR(0x6B, getButtonSoftSwitch(2)) io.addSoftSwitchR(0x6B, getButtonSoftSwitch(2), "PB2")
io.addSoftSwitchR(0x6C, getPaddleSoftSwitch(0)) io.addSoftSwitchR(0x6C, getPaddleSoftSwitch(0), "PDL0")
io.addSoftSwitchR(0x6D, getPaddleSoftSwitch(1)) io.addSoftSwitchR(0x6D, getPaddleSoftSwitch(1), "PDL1")
io.addSoftSwitchR(0x6E, getPaddleSoftSwitch(2)) io.addSoftSwitchR(0x6E, getPaddleSoftSwitch(2), "PDL2")
io.addSoftSwitchR(0x6F, getPaddleSoftSwitch(3)) io.addSoftSwitchR(0x6F, getPaddleSoftSwitch(3), "PDL3")
io.addSoftSwitchR(0x70, strobePaddlesSoftSwitch) // Game controllers reset io.addSoftSwitchR(0x70, strobePaddlesSoftSwitch, "RESETPDL") // Game controllers reset
} }
func notImplementedSoftSwitchR(*ioC0Page) uint8 { func notImplementedSoftSwitchR(*ioC0Page) uint8 {

View File

@ -1,38 +1,62 @@
package apple2 package apple2
/*
See:
https://www.apple.asimov.net/documentation/hardware/machines/APPLE%20IIe%20Auxiliary%20Memory%20Softswitches.pdf
*/
const ( const (
ioFlagRamRd uint8 = 0x13
ioFlagRamWrt uint8 = 0x14
ioFlagIntCxRom uint8 = 0x15 ioFlagIntCxRom uint8 = 0x15
ioFlagAltZp uint8 = 0x16
ioFlagSlotC3Rom uint8 = 0x17 ioFlagSlotC3Rom uint8 = 0x17
ioFlag80Store uint8 = 0x18 ioFlag80Store uint8 = 0x18
ioFlagAltChar uint8 = 0x19 ioFlagAltChar uint8 = 0x1E
ioFlag80Col uint8 = 0x1F ioFlag80Col uint8 = 0x1F
// ??? ioVertBlank uin8 = 0x19
) )
func addApple2ESoftSwitches(io *ioC0Page) { func addApple2ESoftSwitches(io *ioC0Page) {
// New MMU read softswithes // New MMU read softswithes
io.addSoftSwitchW(0x06, getSoftSwitchExt(ioFlagIntCxRom, ssOff, softSwitchIntCxRomOff)) io.addSoftSwitchW(0x02, getSoftSwitchExt(ioFlagRamRd, ssOff, nil), "RAMRDOFF")
io.addSoftSwitchW(0x07, getSoftSwitchExt(ioFlagIntCxRom, ssOn, softSwitchIntCxRomOn)) io.addSoftSwitchW(0x03, getSoftSwitchExt(ioFlagRamWrt, ssOn, nil), "RAMRDON")
io.addSoftSwitchR(0x15, getStatusSoftSwitch(ioFlagIntCxRom)) io.addSoftSwitchR(0x13, getStatusSoftSwitch(ioFlagRamWrt), "RAMRD")
io.addSoftSwitchW(0x0A, getSoftSwitchExt(ioFlagSlotC3Rom, ssOff, softSwitchSlotC3RomOff))
io.addSoftSwitchW(0x0B, getSoftSwitchExt(ioFlagSlotC3Rom, ssOn, softSwitchSlotC3RomOn)) io.addSoftSwitchW(0x04, getSoftSwitchExt(ioFlagRamWrt, ssOff, nil), "RAMWRTOFF")
io.addSoftSwitchR(0x17, getStatusSoftSwitch(ioFlagSlotC3Rom)) io.addSoftSwitchW(0x05, getSoftSwitchExt(ioFlagRamWrt, ssOn, nil), "RAMWRTON")
io.addSoftSwitchR(0x14, getStatusSoftSwitch(ioFlagRamWrt), "RAMWRT")
io.addSoftSwitchW(0x06, getSoftSwitchExt(ioFlagIntCxRom, ssOff, softSwitchIntCxRomOff), "INTCXROMOFF")
io.addSoftSwitchW(0x07, getSoftSwitchExt(ioFlagIntCxRom, ssOn, softSwitchIntCxRomOn), "INTCXROMON")
io.addSoftSwitchR(0x15, getStatusSoftSwitch(ioFlagIntCxRom), "INTCXROM")
io.addSoftSwitchW(0x08, getSoftSwitchExt(ioFlagAltZp, ssOff, nil), "ALTZPOFF")
io.addSoftSwitchW(0x09, getSoftSwitchExt(ioFlagAltZp, ssOn, nil), "ALTZPON")
io.addSoftSwitchR(0x16, getStatusSoftSwitch(ioFlagAltZp), "ALTZP")
io.addSoftSwitchW(0x0A, getSoftSwitchExt(ioFlagSlotC3Rom, ssOff, softSwitchSlotC3RomOff), "SLOTC3ROMOFF")
io.addSoftSwitchW(0x0B, getSoftSwitchExt(ioFlagSlotC3Rom, ssOn, softSwitchSlotC3RomOn), "SLOTC3ROMON")
io.addSoftSwitchR(0x17, getStatusSoftSwitch(ioFlagSlotC3Rom), "SLOTC3ROM")
// Previous read softswithes // Previous read softswithes
io.addSoftSwitchR(0x1A, getStatusSoftSwitch(ioFlagText)) io.addSoftSwitchR(0x1A, getStatusSoftSwitch(ioFlagText), "TEXT")
io.addSoftSwitchR(0x1B, getStatusSoftSwitch(ioFlagMixed)) io.addSoftSwitchR(0x1B, getStatusSoftSwitch(ioFlagMixed), "MIXED")
io.addSoftSwitchR(0x1C, getStatusSoftSwitch(ioFlagSecondPage)) io.addSoftSwitchR(0x1C, getStatusSoftSwitch(ioFlagSecondPage), "PAGE2")
io.addSoftSwitchR(0x1D, getStatusSoftSwitch(ioFlagHiRes)) io.addSoftSwitchR(0x1D, getStatusSoftSwitch(ioFlagHiRes), "HIRES")
// New IOU read softswithes // New IOU read softswithes
io.addSoftSwitchW(0x00, getSoftSwitchExt(ioFlag80Store, ssOff, nil)) io.addSoftSwitchW(0x00, getSoftSwitchExt(ioFlag80Store, ssOff, nil), "80STOREOFF")
io.addSoftSwitchW(0x01, getSoftSwitchExt(ioFlag80Store, ssOn, nil)) io.addSoftSwitchW(0x01, getSoftSwitchExt(ioFlag80Store, ssOn, nil), "80STOREON")
io.addSoftSwitchR(0x18, getStatusSoftSwitch(ioFlag80Store)) io.addSoftSwitchR(0x18, getStatusSoftSwitch(ioFlag80Store), "80STORE")
io.addSoftSwitchW(0x0C, getSoftSwitchExt(ioFlag80Col, ssOff, nil))
io.addSoftSwitchW(0x0D, getSoftSwitchExt(ioFlag80Col, ssOn, nil)) io.addSoftSwitchW(0x0C, getSoftSwitchExt(ioFlag80Col, ssOff, nil), "80COLOFF")
io.addSoftSwitchR(0x1F, getStatusSoftSwitch(ioFlag80Col)) io.addSoftSwitchW(0x0D, getSoftSwitchExt(ioFlag80Col, ssOn, nil), "80COLON")
io.addSoftSwitchW(0x0E, getSoftSwitchExt(ioFlagAltChar, ssOff, nil)) io.addSoftSwitchR(0x1F, getStatusSoftSwitch(ioFlag80Col), "80COL")
io.addSoftSwitchW(0x0F, getSoftSwitchExt(ioFlagAltChar, ssOn, nil))
io.addSoftSwitchR(0x1E, getStatusSoftSwitch(ioFlagAltChar)) io.addSoftSwitchW(0x0E, getSoftSwitchExt(ioFlagAltChar, ssOff, nil), "ALTCHARSETOFF")
io.addSoftSwitchW(0x0F, getSoftSwitchExt(ioFlagAltChar, ssOn, nil), "ALTCHARSETON")
io.addSoftSwitchR(0x1E, getStatusSoftSwitch(ioFlagAltChar), "ALTCHARSET")
// TOOD: // TOOD:
// AKD read on 0x10 // AKD read on 0x10