Simplify softswitches

This commit is contained in:
Iván Izaguirre 2022-08-05 19:43:17 +02:00
parent f2bc9f21aa
commit 9feded23f8
22 changed files with 196 additions and 190 deletions

View File

@ -58,33 +58,27 @@ func loadBase64aRom(a *Apple2) error {
func addBase64aSoftSwitches(io *ioC0Page) {
// Other softswitches, not implemented but called from the ROM
io.addSoftSwitchW(0x0C, notImplementedSoftSwitchW, "80COLOFF")
io.addSoftSwitchW(0x0E, notImplementedSoftSwitchW, "ALTCHARSETOFF")
// Write on the speaker. That is a double access and should do nothing
// but works somehow on the BASE64A
io.addSoftSwitchW(0x30, func(io *ioC0Page, value uint8) {
speakerSoftSwitch(io)
}, "SPEAKER")
io.addSoftSwitchW(0x0C, buildNotImplementedSoftSwitchW(io), "80COLOFF")
io.addSoftSwitchW(0x0E, buildNotImplementedSoftSwitchW(io), "ALTCHARSETOFF")
// ROM pagination softswitches. They use the annunciator 0 and 1
mmu := io.apple2.mmu
io.addSoftSwitchRW(0x58, func(*ioC0Page) uint8 {
io.addSoftSwitchRW(0x58, func() uint8 {
p := mmu.getActiveROMPage()
mmu.setActiveROMPage(p & 2)
return 0
}, "ANN0OFF-ROM")
io.addSoftSwitchRW(0x59, func(*ioC0Page) uint8 {
io.addSoftSwitchRW(0x59, func() uint8 {
p := mmu.getActiveROMPage()
mmu.setActiveROMPage(p | 1)
return 0
}, "ANN0ON-ROM")
io.addSoftSwitchRW(0x5A, func(*ioC0Page) uint8 {
io.addSoftSwitchRW(0x5A, func() uint8 {
p := mmu.getActiveROMPage()
mmu.setActiveROMPage(p & 1)
return 0
}, "ANN1OFF-ROM")
io.addSoftSwitchRW(0x5B, func(*ioC0Page) uint8 {
io.addSoftSwitchRW(0x5B, func() uint8 {
p := mmu.getActiveROMPage()
mmu.setActiveROMPage(p | 2)
return 0

View File

@ -118,23 +118,23 @@ func (c *cardBase) addCardSoftSwitchRW(address uint8, ss softSwitchR, name strin
c._ssr[address] = ss
c._ssrName[address] = name
c._ssw[address] = func(p *ioC0Page, _ uint8) {
ss(p)
c._ssw[address] = func(uint8) {
ss()
}
c._sswName[address] = name
}
type softSwitches func(io *ioC0Page, address uint8, data uint8, write bool) uint8
type softSwitches func(address uint8, data uint8, write bool) uint8
func (c *cardBase) addCardSoftSwitches(sss softSwitches, name string) {
for i := uint8(0x0); i <= 0xf; i++ {
address := i
c.addCardSoftSwitchR(address, func(io *ioC0Page) uint8 {
return sss(io, address, 0, false)
c.addCardSoftSwitchR(address, func() uint8 {
return sss(address, 0, false)
}, fmt.Sprintf("%v%XR", name, address))
c.addCardSoftSwitchW(address, func(io *ioC0Page, value uint8) {
sss(io, address, value, true)
c.addCardSoftSwitchW(address, func(value uint8) {
sss(address, value, true)
}, fmt.Sprintf("%v%XW", name, address))
}
}

View File

@ -80,7 +80,7 @@ func (c *CardDisk2) assign(a *Apple2, slot int) {
// Q1, Q2, Q3 and Q4 phase control soft switches,
for i := uint8(0); i < 4; i++ {
phase := i
c.addCardSoftSwitchR(phase<<1, func(_ *ioC0Page) uint8 {
c.addCardSoftSwitchR(phase<<1, func() uint8 {
// Update magnets and position
drive := &c.drive[c.selected]
drive.phases &^= (1 << phase)
@ -93,7 +93,7 @@ func (c *CardDisk2) assign(a *Apple2, slot int) {
return c.dataLatch // All even addresses return the last dataLatch
}, fmt.Sprintf("PHASE%vOFF", phase))
c.addCardSoftSwitchR((phase<<1)+1, func(_ *ioC0Page) uint8 {
c.addCardSoftSwitchR((phase<<1)+1, func() uint8 {
// Update magnets and position
drive := &c.drive[c.selected]
drive.phases |= (1 << phase)
@ -108,21 +108,21 @@ func (c *CardDisk2) assign(a *Apple2, slot int) {
}
// Q4, power switch
c.addCardSoftSwitchR(0x8, func(_ *ioC0Page) uint8 {
c.addCardSoftSwitchR(0x8, func() uint8 {
c.softSwitchQ4(false)
return c.dataLatch
}, "Q4DRIVEOFF")
c.addCardSoftSwitchR(0x9, func(_ *ioC0Page) uint8 {
c.addCardSoftSwitchR(0x9, func() uint8 {
c.softSwitchQ4(true)
return 0
}, "Q4DRIVEON")
// Q5, drive selecion
c.addCardSoftSwitchR(0xA, func(_ *ioC0Page) uint8 {
c.addCardSoftSwitchR(0xA, func() uint8 {
c.softSwitchQ5(0)
return c.dataLatch
}, "Q5SELECT1")
c.addCardSoftSwitchR(0xB, func(_ *ioC0Page) uint8 {
c.addCardSoftSwitchR(0xB, func() uint8 {
c.softSwitchQ5(1)
return 0
}, "Q5SELECT2")
@ -130,10 +130,10 @@ func (c *CardDisk2) assign(a *Apple2, slot int) {
// Q6, Q7
for i := uint8(0xC); i <= 0xF; i++ {
iCopy := i
c.addCardSoftSwitchR(iCopy, func(_ *ioC0Page) uint8 {
c.addCardSoftSwitchR(iCopy, func() uint8 {
return c.softSwitchQ6Q7(iCopy, 0)
}, "Q6Q7")
c.addCardSoftSwitchW(iCopy, func(_ *ioC0Page, value uint8) {
c.addCardSoftSwitchW(iCopy, func(value uint8) {
c.softSwitchQ6Q7(iCopy, value)
}, "Q6Q7")
}

View File

@ -80,7 +80,7 @@ func (c *CardDisk2Sequencer) reset() {
}
func (c *CardDisk2Sequencer) assign(a *Apple2, slot int) {
c.addCardSoftSwitches(func(_ *ioC0Page, address uint8, data uint8, write bool) uint8 {
c.addCardSoftSwitches(func(address uint8, data uint8, write bool) uint8 {
/*
Slot card pins to SN74LS259 latch mapping:
slot_address[3,2,1] => latch_address[2,1,0]

View File

@ -42,7 +42,7 @@ const (
func (c *CardFastChip) assign(a *Apple2, slot int) {
// The softswitches are outside the card reserved ss
// Only writes are implemented to avoid conflicts with the joysticks
a.io.addSoftSwitchW(0x6a, func(_ *ioC0Page, value uint8) {
a.io.addSoftSwitchW(0x6a, func(value uint8) {
if value == fastChipUnlockToken {
c.unlockCounter++
if c.unlockCounter >= fastChipUnlockRepeats {
@ -55,25 +55,25 @@ func (c *CardFastChip) assign(a *Apple2, slot int) {
}
}, "FASTCHIP-LOCK")
a.io.addSoftSwitchW(0x6b, func(_ *ioC0Page, _ uint8) {
a.io.addSoftSwitchW(0x6b, func(uint8) {
if c.unlocked {
c.enabled = true
}
}, "FASTCHIP-ENABLE")
a.io.addSoftSwitchW(0x6d, func(_ *ioC0Page, value uint8) {
a.io.addSoftSwitchW(0x6d, func(value uint8) {
if c.enabled {
c.setSpeed(a, value)
}
}, "FASTCHIP-SPEED")
a.io.addSoftSwitchW(0x6e, func(_ *ioC0Page, value uint8) {
a.io.addSoftSwitchW(0x6e, func(value uint8) {
if c.enabled {
c.configRegister = value
}
}, "FASTCHIP-CONFIG")
a.io.addSoftSwitchW(0x6f, func(_ *ioC0Page, value uint8) {
a.io.addSoftSwitchW(0x6f, func(value uint8) {
if c.enabled && c.configRegister == 0 {
c.setSpeed(a, value)
}

View File

@ -73,7 +73,7 @@ const (
func (c *CardHardDisk) assign(a *Apple2, slot int) {
c.loadRom(buildHardDiskRom(slot))
c.addCardSoftSwitchR(0, func(*ioC0Page) uint8 {
c.addCardSoftSwitchR(0, func() uint8 {
// Prodos entry point
command := a.mmu.Peek(0x42)
unit := a.mmu.Peek(0x43)
@ -95,16 +95,16 @@ func (c *CardHardDisk) assign(a *Apple2, slot int) {
return proDosDeviceErrorIO
}
}, "HDCOMMAND")
c.addCardSoftSwitchR(1, func(*ioC0Page) uint8 {
c.addCardSoftSwitchR(1, func() uint8 {
// Blocks available, low byte
return uint8(c.disk.GetSizeInBlocks())
}, "HDBLOCKSLO")
c.addCardSoftSwitchR(2, func(*ioC0Page) uint8 {
c.addCardSoftSwitchR(2, func() uint8 {
// Blocks available, high byte
return uint8(c.disk.GetSizeInBlocks() >> 8)
}, "HDBLOCKHI")
c.addCardSoftSwitchR(3, func(*ioC0Page) uint8 {
c.addCardSoftSwitchR(3, func() uint8 {
// Smart port entry point
command := c.a.mmu.Peek(c.mliParams + 1)
paramsAddress := uint16(c.a.mmu.Peek(c.mliParams+2)) + uint16(c.a.mmu.Peek(c.mliParams+3))<<8
@ -127,13 +127,13 @@ func (c *CardHardDisk) assign(a *Apple2, slot int) {
return proDosDeviceErrorIO
}
}, "HDSMARTPORT")
c.addCardSoftSwitchW(4, func(_ *ioC0Page, value uint8) {
c.addCardSoftSwitchW(4, func(value uint8) {
c.mliParams = (c.mliParams & 0xff00) + uint16(value)
if c.trace {
fmt.Printf("[CardHardDisk] Smart port LO: 0x%x.\n", c.mliParams)
}
}, "HDSMARTPORTLO")
c.addCardSoftSwitchW(5, func(_ *ioC0Page, value uint8) {
c.addCardSoftSwitchW(5, func(value uint8) {
c.mliParams = (c.mliParams & 0x00ff) + (uint16(value) << 8)
if c.trace {
fmt.Printf("[CardHardDisk] Smart port HI: 0x%x.\n", c.mliParams)

View File

@ -32,7 +32,7 @@ func NewCardInOut() *CardInOut {
}
func (c *CardInOut) assign(a *Apple2, slot int) {
c.addCardSoftSwitchR(0, func(*ioC0Page) uint8 {
c.addCardSoftSwitchR(0, func() uint8 {
if c.reader == nil {
c.reader = bufio.NewReader(os.Stdin)
}
@ -48,7 +48,7 @@ func (c *CardInOut) assign(a *Apple2, slot int) {
//fmt.Printf("[cardInOut] Read access to softswith 0x%x for slot %v, value %x.\n", 0, slot, value)
return value
}, "INOUTR")
c.addCardSoftSwitchW(1, func(_ *ioC0Page, value uint8) {
c.addCardSoftSwitchW(1, func(value uint8) {
//fmt.Printf("[cardInOut] Write access to softswith 0x%x for slot %v, value 0x%x: %v, %v.\n", 1, slot, value, value&0x7f, string(value&0x7f))
if value&0x7f == 13 {
fmt.Printf("\n")

View File

@ -68,11 +68,11 @@ func (c *CardLanguage) assign(a *Apple2, slot int) {
a.mmu.initLanguageRAM(1)
for i := uint8(0x0); i <= 0xf; i++ {
iCopy := i
c.addCardSoftSwitchR(iCopy, func(*ioC0Page) uint8 {
c.addCardSoftSwitchR(iCopy, func() uint8 {
c.ssAction(iCopy, false)
return 0
}, "LANGCARDR")
c.addCardSoftSwitchW(iCopy, func(*ioC0Page, uint8) {
c.addCardSoftSwitchW(iCopy, func(uint8) {
c.ssAction(iCopy, true)
}, "LANGCARDW")
}

View File

@ -21,7 +21,7 @@ func NewCardLogger() *CardLogger {
}
func (c *CardLogger) assign(a *Apple2, slot int) {
c.addCardSoftSwitches(func(_ *ioC0Page, address uint8, data uint8, write bool) uint8 {
c.addCardSoftSwitches(func(address uint8, data uint8, write bool) uint8 {
if write {
fmt.Printf("[cardLogger] Write access to softswith 0x%x for slot %v, value 0x%02x.\n", address, slot, data)
} else {

View File

@ -65,31 +65,31 @@ func (c *CardMemoryExpansion) GetInfo() map[string]string {
func (c *CardMemoryExpansion) assign(a *Apple2, slot int) {
// Read pointer position
c.addCardSoftSwitchR(0, func(*ioC0Page) uint8 {
c.addCardSoftSwitchR(0, func() uint8 {
return uint8(c.index)
}, "MEMORYEXLOR")
c.addCardSoftSwitchR(1, func(*ioC0Page) uint8 {
c.addCardSoftSwitchR(1, func() uint8 {
return uint8(c.index >> 8)
}, "MEMORYEXMIR")
c.addCardSoftSwitchR(2, func(*ioC0Page) uint8 {
c.addCardSoftSwitchR(2, func() uint8 {
// Top nibble returned is 0xf
return uint8(c.index>>16) | 0xf0
}, "MEMORYEXHIR")
// Set pointer position
c.addCardSoftSwitchW(0, func(_ *ioC0Page, value uint8) {
c.addCardSoftSwitchW(0, func(value uint8) {
c.index = (c.index &^ 0xff) + int(value)
}, "MEMORYEXLOW")
c.addCardSoftSwitchW(1, func(_ *ioC0Page, value uint8) {
c.addCardSoftSwitchW(1, func(value uint8) {
c.index = (c.index &^ 0xff00) + int(value)<<8
}, "MEMORYEXMIW")
c.addCardSoftSwitchW(2, func(_ *ioC0Page, value uint8) {
c.addCardSoftSwitchW(2, func(value uint8) {
// Only lo nibble is used
c.index = (c.index &^ 0xff0000) + int(value&0x0f)<<16
}, "MEMORYEXHIW")
// Read data
c.addCardSoftSwitchR(3, func(*ioC0Page) uint8 {
c.addCardSoftSwitchR(3, func() uint8 {
var value uint8
if c.index < len(c.ram) {
value = c.ram[c.index]
@ -101,7 +101,7 @@ func (c *CardMemoryExpansion) assign(a *Apple2, slot int) {
}, "MEMORYEXR")
// Write data
c.addCardSoftSwitchW(3, func(_ *ioC0Page, value uint8) {
c.addCardSoftSwitchW(3, func(value uint8) {
if c.index < len(c.ram) {
c.ram[c.index] = value
}
@ -110,7 +110,7 @@ func (c *CardMemoryExpansion) assign(a *Apple2, slot int) {
// The rest of the softswitches return 255, at least on //e and //c
for i := uint8(4); i < 16; i++ {
c.addCardSoftSwitchR(i, func(*ioC0Page) uint8 {
c.addCardSoftSwitchR(i, func() uint8 {
return 255
}, "MEMORYEXUNUSEDR")
}

View File

@ -92,7 +92,7 @@ func (c *CardMouse) readMouse() (uint16, uint16, bool) {
}
func (c *CardMouse) assign(a *Apple2, slot int) {
c.addCardSoftSwitchR(0, func(*ioC0Page) uint8 {
c.addCardSoftSwitchR(0, func() uint8 {
if c.iOut == 0 {
// Create a new response
x, y, pressed := c.readMouse()
@ -126,7 +126,7 @@ func (c *CardMouse) assign(a *Apple2, slot int) {
return value
}, "MOUSEOUT")
c.addCardSoftSwitchW(1, func(_ *ioC0Page, value uint8) {
c.addCardSoftSwitchW(1, func(value uint8) {
if c.trace {
fmt.Printf("[cardMouse] PR#%v <- %02x\n", slot, value)
}
@ -140,21 +140,21 @@ func (c *CardMouse) assign(a *Apple2, slot int) {
}
}, "MOUSEIN")
c.addCardSoftSwitchW(2, func(_ *ioC0Page, value uint8) {
c.addCardSoftSwitchW(2, func(value uint8) {
if c.trace {
fmt.Printf("[cardMouse] SetMouse(0x%02v)\n", value)
}
c.setMode(value & 0x0f)
}, "SETMOUSE")
c.addCardSoftSwitchW(3, func(_ *ioC0Page, value uint8) {
c.addCardSoftSwitchW(3, func(value uint8) {
if c.trace {
fmt.Printf("[cardMouse] ServeMouse() NOT IMPLEMENTED\n")
}
panic("Mouse interrupts not implemented")
}, "SERVEMOUSE")
c.addCardSoftSwitchW(4, func(_ *ioC0Page, value uint8) {
c.addCardSoftSwitchW(4, func(value uint8) {
if c.mode&mouseModeEnabled == 1 {
x, y, pressed := c.readMouse()
@ -186,7 +186,7 @@ func (c *CardMouse) assign(a *Apple2, slot int) {
}
}, "READMOUSE")
c.addCardSoftSwitchW(5, func(_ *ioC0Page, value uint8) {
c.addCardSoftSwitchW(5, func(value uint8) {
if c.trace {
fmt.Printf("[cardMouse] ClearMouse() NOT IMPLEMENTED\n")
}
@ -195,13 +195,13 @@ func (c *CardMouse) assign(a *Apple2, slot int) {
c.set(mouseXLo, 0)
c.set(mouseYLo, 0)
}, "CLEARMOUSE")
c.addCardSoftSwitchW(6, func(_ *ioC0Page, value uint8) {
c.addCardSoftSwitchW(6, func(value uint8) {
if c.trace {
fmt.Printf("[cardMouse] PosMouse() NOT IMPLEMENTED\n")
}
}, "POSMOUSE")
c.addCardSoftSwitchW(7, func(_ *ioC0Page, value uint8) {
c.addCardSoftSwitchW(7, func(value uint8) {
if c.trace {
fmt.Printf("[cardMouse] ClampMouse(%v)\n", value)
}
@ -219,13 +219,13 @@ func (c *CardMouse) assign(a *Apple2, slot int) {
}
}, "CLAMPMOUSE")
c.addCardSoftSwitchW(8, func(_ *ioC0Page, value uint8) {
c.addCardSoftSwitchW(8, func(value uint8) {
if c.trace {
fmt.Printf("[cardMouse] HomeMouse() NOT IMPLEMENTED\n")
}
}, "HOMEMOUSE")
c.addCardSoftSwitchW(0xc, func(_ *ioC0Page, value uint8) {
c.addCardSoftSwitchW(0xc, func(value uint8) {
if c.trace {
fmt.Printf("[cardMouse] InitMouse()\n")
}
@ -236,7 +236,7 @@ func (c *CardMouse) assign(a *Apple2, slot int) {
c.mode = 0
}, "INITMOUSE")
c.addCardSoftSwitchW(8, func(_ *ioC0Page, value uint8) {
c.addCardSoftSwitchW(8, func(value uint8) {
if c.trace {
fmt.Printf("[cardMouse] TimeData(%v) NOT IMPLEMENTED\n", value)
}

View File

@ -33,7 +33,7 @@ func (c *CardParallelPrinter) assign(a *Apple2, slot int) {
}
c.file = f
c.addCardSoftSwitchW(0, func(_ *ioC0Page, value uint8) {
c.addCardSoftSwitchW(0, func(value uint8) {
c.printByte(value)
}, "PARALLELDEVW")

View File

@ -38,17 +38,17 @@ func setupRGBCard(a *Apple2) *cardRGB {
a.io.softSwitchesData[ioFlagRGBCardActive] = ssOn
// Does not have ROM or private softswitches. It spies on the softswitches
a.io.addSoftSwitchRW(0x50, func(io *ioC0Page) uint8 {
io.softSwitchesData[ioFlagText] = ssOff
a.io.addSoftSwitchRW(0x50, func() uint8 {
a.io.softSwitchesData[ioFlagText] = ssOff
// Reset RGB modes when entering graphics mode
c.step = 0
io.softSwitchesData[ioFlag1RGBCard] = ssOn
io.softSwitchesData[ioFlag2RGBCard] = ssOn
a.io.softSwitchesData[ioFlag1RGBCard] = ssOn
a.io.softSwitchesData[ioFlag2RGBCard] = ssOn
return 0
}, "TEXTOFF")
a.io.addSoftSwitchRW(0x5e, func(io *ioC0Page) uint8 {
io.softSwitchesData[ioFlagAnnunciator3] = ssOff
a.io.addSoftSwitchRW(0x5e, func() uint8 {
a.io.softSwitchesData[ioFlagAnnunciator3] = ssOff
switch c.step {
case 0:
c.step++
@ -59,14 +59,14 @@ func setupRGBCard(a *Apple2) *cardRGB {
return 0
}, "ANN3OFF-RGB")
a.io.addSoftSwitchRW(0x5f, func(io *ioC0Page) uint8 {
io.softSwitchesData[ioFlagAnnunciator3] = ssOn
a.io.addSoftSwitchRW(0x5f, func() uint8 {
a.io.softSwitchesData[ioFlagAnnunciator3] = ssOn
switch c.step {
case 1:
io.softSwitchesData[ioFlag1RGBCard] = io.softSwitchesData[ioFlag80Col]
a.io.softSwitchesData[ioFlag1RGBCard] = a.io.softSwitchesData[ioFlag80Col]
c.step++
case 3:
io.softSwitchesData[ioFlag2RGBCard] = io.softSwitchesData[ioFlag80Col]
a.io.softSwitchesData[ioFlag2RGBCard] = a.io.softSwitchesData[ioFlag80Col]
c.step++
}

View File

@ -14,11 +14,11 @@ It's is like the extra 64kb on an Apple IIe 80col 64kb card, but with up to 256
func setupRAMWorksCard(a *Apple2, banks int) {
a.mmu.initExtendedRAM(banks)
ssr := func(_ *ioC0Page) uint8 {
ssr := func() uint8 {
return a.mmu.extendedRAMBlock
}
ssw := func(_ *ioC0Page, value uint8) {
ssw := func(value uint8) {
a.mmu.setExtendedRAMActiveBlock(value)
}

View File

@ -37,11 +37,11 @@ func (c *CardSaturn) assign(a *Apple2, slot int) {
// TODO: use addCardSoftSwitches()
for i := uint8(0x0); i <= 0xf; i++ {
iCopy := i
c.addCardSoftSwitchR(iCopy, func(*ioC0Page) uint8 {
c.addCardSoftSwitchR(iCopy, func() uint8 {
c.ssAction(iCopy)
return 0
}, "SATURNR")
c.addCardSoftSwitchW(iCopy, func(*ioC0Page, uint8) {
c.addCardSoftSwitchW(iCopy, func(uint8) {
c.ssAction(iCopy)
}, "SATURNW")
}

View File

@ -81,19 +81,19 @@ func (c *CardSwyft) assign(a *Apple2, slot int) {
}
c.rom = data
c.addCardSoftSwitchRW(0, func(*ioC0Page) uint8 {
c.addCardSoftSwitchRW(0, func() uint8 {
a.mmu.inhibitROM(c)
c.bank2 = false
return 0x55
}, "SWYFTONBANK1")
c.addCardSoftSwitchRW(1, func(*ioC0Page) uint8 {
c.addCardSoftSwitchRW(1, func() uint8 {
a.mmu.inhibitROM(nil)
c.bank2 = false
return 0x55
}, "SWYFTOFFBANK1")
c.addCardSoftSwitchRW(2, func(*ioC0Page) uint8 {
c.addCardSoftSwitchRW(2, func() uint8 {
a.mmu.inhibitROM(c)
c.bank2 = true
return 0x55

View File

@ -37,7 +37,7 @@ func NewCardThunderClockPlus() *CardThunderClockPlus {
}
func (c *CardThunderClockPlus) assign(a *Apple2, slot int) {
c.addCardSoftSwitchR(0, func(*ioC0Page) uint8 {
c.addCardSoftSwitchR(0, func() uint8 {
bit := c.upd1990.Out()
// Get the next data bit from uPD1990AC on the MSB
if bit {
@ -46,7 +46,7 @@ func (c *CardThunderClockPlus) assign(a *Apple2, slot int) {
return 0
}, "THUNDERCLOCKR")
c.addCardSoftSwitchW(0, func(_ *ioC0Page, value uint8) {
c.addCardSoftSwitchW(0, func(value uint8) {
dataIn := (value & 0x01) == 1
clock := ((value >> 1) & 0x01) == 1
strobe := ((value >> 2) & 0x01) == 1

View File

@ -37,14 +37,14 @@ const (
func (c *CardVidHD) assign(a *Apple2, slot int) {
// The softswitches are outside the card reserved ss
a.io.addSoftSwitchR(0x22, notImplementedSoftSwitchR, "VIDHD-TBCOLOR")
a.io.addSoftSwitchW(0x22, notImplementedSoftSwitchW, "VIDHD-TBCOLOR")
a.io.addSoftSwitchR(0x29, getStatusSoftSwitch(ioDataNewVideo), "VIDHD-NEWVIDEO")
a.io.addSoftSwitchW(0x29, setStatusSoftSwitch(ioDataNewVideo), "VIDHD-NEWVIDEO")
a.io.addSoftSwitchR(0x34, notImplementedSoftSwitchR, "VIDHD-CLOCKCTL")
a.io.addSoftSwitchW(0x34, notImplementedSoftSwitchW, "VIDHD-CLOCKCTL")
a.io.addSoftSwitchR(0x35, notImplementedSoftSwitchR, "VIDHD-SHADOW")
a.io.addSoftSwitchW(0x35, notImplementedSoftSwitchW, "VIDHD-SHADOW")
a.io.addSoftSwitchR(0x22, buildNotImplementedSoftSwitchR(a.io), "VIDHD-TBCOLOR")
a.io.addSoftSwitchW(0x22, buildNotImplementedSoftSwitchW(a.io), "VIDHD-TBCOLOR")
a.io.addSoftSwitchR(0x29, getStatusSoftSwitch(a.io, ioDataNewVideo), "VIDHD-NEWVIDEO")
a.io.addSoftSwitchW(0x29, setStatusSoftSwitch(a.io, ioDataNewVideo), "VIDHD-NEWVIDEO")
a.io.addSoftSwitchR(0x34, buildNotImplementedSoftSwitchR(a.io), "VIDHD-CLOCKCTL")
a.io.addSoftSwitchW(0x34, buildNotImplementedSoftSwitchW(a.io), "VIDHD-CLOCKCTL")
a.io.addSoftSwitchR(0x35, buildNotImplementedSoftSwitchR(a.io), "VIDHD-SHADOW")
a.io.addSoftSwitchW(0x35, buildNotImplementedSoftSwitchW(a.io), "VIDHD-SHADOW")
c.cardBase.assign(a, slot)
}

View File

@ -77,11 +77,11 @@ func (c *CardVidex) assign(a *Apple2, slot int) {
ssName += "ADDRESS"
}
c.addCardSoftSwitchR(i, func(*ioC0Page) uint8 {
c.addCardSoftSwitchR(i, func() uint8 {
c.sramPage = sramPage
return c.mc6845.Read(rsPin)
}, ssName+"R")
c.addCardSoftSwitchW(i, func(_ *ioC0Page, value uint8) {
c.addCardSoftSwitchW(i, func(value uint8) {
c.sramPage = sramPage
c.mc6845.Write(rsPin, value)
}, ssName+"W")

View File

@ -21,8 +21,8 @@ type ioC0Page struct {
panicNotImplemented bool
}
type softSwitchR func(io *ioC0Page) uint8
type softSwitchW func(io *ioC0Page, value uint8)
type softSwitchR func() uint8
type softSwitchW func(value uint8)
// SpeakerProvider provides a speaker implementation
type SpeakerProvider interface {
@ -69,8 +69,8 @@ func (p *ioC0Page) setPanicNotImplemented(value bool) {
func (p *ioC0Page) addSoftSwitchRW(address uint8, ss softSwitchR, name string) {
p.addSoftSwitchR(address, ss, name)
p.addSoftSwitchW(address, func(p *ioC0Page, _ uint8) {
ss(p)
p.addSoftSwitchW(address, func(uint8) {
ss()
}, name)
}
@ -122,7 +122,7 @@ func (p *ioC0Page) peek(address uint16) uint8 {
}
return 0
}
value := ss(p)
value := ss()
if p.trace && address != 0xc000 {
name := p.softSwitchesRName[pageAddress]
fmt.Printf("Softswitch peek on $%04x %v: $%02x\n", address, name, value)
@ -146,7 +146,7 @@ func (p *ioC0Page) poke(address uint16, value uint8) {
name := p.softSwitchesWName[pageAddress]
fmt.Printf("Softswitch poke on $%04x %v with $%02x\n", address, name, value)
}
ss(p, value)
ss(value)
}
func (p *ioC0Page) setBase(_ uint16) {

View File

@ -29,81 +29,86 @@ const (
func addApple2SoftSwitches(io *ioC0Page) {
io.addSoftSwitchRW(0x00, keySoftSwitch, "KEYBOARD") // Keyboard
io.addSoftSwitchRW(0x10, strobeKeyboardSoftSwitch, "AKD") // Keyboard Strobe
io.addSoftSwitchR(0x20, notImplementedSoftSwitchR, "TAPEOUT") // Cassette Output
io.addSoftSwitchRW(0x30, speakerSoftSwitch, "SPEAKER") // Speaker
io.addSoftSwitchR(0x40, notImplementedSoftSwitchR, "STROBE") // Game connector Strobe
io.addSoftSwitchRW(0x00, buildKeySoftSwitch(io), "KEYBOARD") // Keyboard
io.addSoftSwitchRW(0x10, buildStrobeKeyboardSoftSwitch(io), "AKD") // Keyboard Strobe
io.addSoftSwitchR(0x20, buildNotImplementedSoftSwitchR(io), "TAPEOUT") // Cassette Output
io.addSoftSwitchRW(0x30, buildSpeakerSoftSwitch(io), "SPEAKER") // Speaker
io.addSoftSwitchR(0x40, buildNotImplementedSoftSwitchR(io), "STROBE") // Game connector Strobe
// Note: Some sources indicate that all these cover 16 positions
// for read and write. But the Apple2e takes over some of them, with
// the prevention on acting only on writes.
io.addSoftSwitchRW(0x50, getSoftSwitch(ioFlagText, false), "TEXTOFF")
io.addSoftSwitchRW(0x51, getSoftSwitch(ioFlagText, true), "TEXTON")
io.addSoftSwitchRW(0x52, getSoftSwitch(ioFlagMixed, false), "MIXEDOFF")
io.addSoftSwitchRW(0x53, getSoftSwitch(ioFlagMixed, true), "MIXEDON")
io.addSoftSwitchRW(0x54, getSoftSwitch(ioFlagSecondPage, false), "PAGE2OFF")
io.addSoftSwitchRW(0x55, getSoftSwitch(ioFlagSecondPage, true), "PAGE2ON")
io.addSoftSwitchRW(0x56, getSoftSwitch(ioFlagHiRes, false), "HIRESOFF")
io.addSoftSwitchRW(0x57, getSoftSwitch(ioFlagHiRes, true), "HIRESON")
io.addSoftSwitchRW(0x50, getSoftSwitch(io, ioFlagText, false), "TEXTOFF")
io.addSoftSwitchRW(0x51, getSoftSwitch(io, ioFlagText, true), "TEXTON")
io.addSoftSwitchRW(0x52, getSoftSwitch(io, ioFlagMixed, false), "MIXEDOFF")
io.addSoftSwitchRW(0x53, getSoftSwitch(io, ioFlagMixed, true), "MIXEDON")
io.addSoftSwitchRW(0x54, getSoftSwitch(io, ioFlagSecondPage, false), "PAGE2OFF")
io.addSoftSwitchRW(0x55, getSoftSwitch(io, ioFlagSecondPage, true), "PAGE2ON")
io.addSoftSwitchRW(0x56, getSoftSwitch(io, ioFlagHiRes, false), "HIRESOFF")
io.addSoftSwitchRW(0x57, getSoftSwitch(io, ioFlagHiRes, true), "HIRESON")
io.addSoftSwitchRW(0x58, getSoftSwitch(ioFlagAnnunciator0, false), "ANN0OFF")
io.addSoftSwitchRW(0x59, getSoftSwitch(ioFlagAnnunciator0, true), "ANN0ON")
io.addSoftSwitchRW(0x5a, getSoftSwitch(ioFlagAnnunciator1, false), "ANN1OFF")
io.addSoftSwitchRW(0x5b, getSoftSwitch(ioFlagAnnunciator1, true), "ANN1ON")
io.addSoftSwitchRW(0x5c, getSoftSwitch(ioFlagAnnunciator2, false), "ANN2OFF")
io.addSoftSwitchRW(0x5d, getSoftSwitch(ioFlagAnnunciator2, true), "ANN2ON")
io.addSoftSwitchRW(0x5e, getSoftSwitch(ioFlagAnnunciator3, false), "ANN3OFF")
io.addSoftSwitchRW(0x5f, getSoftSwitch(ioFlagAnnunciator3, true), "ANN3ON")
io.addSoftSwitchRW(0x58, getSoftSwitch(io, ioFlagAnnunciator0, false), "ANN0OFF")
io.addSoftSwitchRW(0x59, getSoftSwitch(io, ioFlagAnnunciator0, true), "ANN0ON")
io.addSoftSwitchRW(0x5a, getSoftSwitch(io, ioFlagAnnunciator1, false), "ANN1OFF")
io.addSoftSwitchRW(0x5b, getSoftSwitch(io, ioFlagAnnunciator1, true), "ANN1ON")
io.addSoftSwitchRW(0x5c, getSoftSwitch(io, ioFlagAnnunciator2, false), "ANN2OFF")
io.addSoftSwitchRW(0x5d, getSoftSwitch(io, ioFlagAnnunciator2, true), "ANN2ON")
io.addSoftSwitchRW(0x5e, getSoftSwitch(io, ioFlagAnnunciator3, false), "ANN3OFF")
io.addSoftSwitchRW(0x5f, getSoftSwitch(io, ioFlagAnnunciator3, true), "ANN3ON")
io.addSoftSwitchR(0x60, notImplementedSoftSwitchR, "CASSETTE") // Cassette Input
io.addSoftSwitchR(0x61, getButtonSoftSwitch(0), "PB0")
io.addSoftSwitchR(0x62, getButtonSoftSwitch(1), "PB1")
io.addSoftSwitchR(0x63, getButtonSoftSwitch(2), "PB2")
io.addSoftSwitchR(0x64, getPaddleSoftSwitch(0), "PDL0")
io.addSoftSwitchR(0x65, getPaddleSoftSwitch(1), "PDL1")
io.addSoftSwitchR(0x66, getPaddleSoftSwitch(2), "PDL2")
io.addSoftSwitchR(0x67, getPaddleSoftSwitch(3), "PDL3")
io.addSoftSwitchR(0x60, buildNotImplementedSoftSwitchR(io), "CASSETTE") // Cassette Input
io.addSoftSwitchR(0x61, buildButtonSoftSwitch(io, 0), "PB0")
io.addSoftSwitchR(0x62, buildButtonSoftSwitch(io, 1), "PB1")
io.addSoftSwitchR(0x63, buildButtonSoftSwitch(io, 2), "PB2")
io.addSoftSwitchR(0x64, buildPaddleSoftSwitch(io, 0), "PDL0")
io.addSoftSwitchR(0x65, buildPaddleSoftSwitch(io, 1), "PDL1")
io.addSoftSwitchR(0x66, buildPaddleSoftSwitch(io, 2), "PDL2")
io.addSoftSwitchR(0x67, buildPaddleSoftSwitch(io, 3), "PDL3")
// The previous 8 softswitches are repeated
io.addSoftSwitchR(0x68, notImplementedSoftSwitchR, "CASSETTE") // Cassette Input
io.addSoftSwitchR(0x69, getButtonSoftSwitch(0), "PB0")
io.addSoftSwitchR(0x6A, getButtonSoftSwitch(1), "PB1")
io.addSoftSwitchR(0x6B, getButtonSoftSwitch(2), "PB2")
io.addSoftSwitchR(0x6C, getPaddleSoftSwitch(0), "PDL0")
io.addSoftSwitchR(0x6D, getPaddleSoftSwitch(1), "PDL1")
io.addSoftSwitchR(0x6E, getPaddleSoftSwitch(2), "PDL2")
io.addSoftSwitchR(0x6F, getPaddleSoftSwitch(3), "PDL3")
io.addSoftSwitchR(0x68, buildNotImplementedSoftSwitchR(io), "CASSETTE") // Cassette Input
io.addSoftSwitchR(0x69, buildButtonSoftSwitch(io, 0), "PB0")
io.addSoftSwitchR(0x6A, buildButtonSoftSwitch(io, 1), "PB1")
io.addSoftSwitchR(0x6B, buildButtonSoftSwitch(io, 2), "PB2")
io.addSoftSwitchR(0x6C, buildPaddleSoftSwitch(io, 0), "PDL0")
io.addSoftSwitchR(0x6D, buildPaddleSoftSwitch(io, 1), "PDL1")
io.addSoftSwitchR(0x6E, buildPaddleSoftSwitch(io, 2), "PDL2")
io.addSoftSwitchR(0x6F, buildPaddleSoftSwitch(io, 3), "PDL3")
io.addSoftSwitchR(0x70, strobePaddlesSoftSwitch, "RESETPDL") // Game controllers reset
io.addSoftSwitchR(0x70, buildStrobePaddlesSoftSwitch(io), "RESETPDL") // Game controllers reset
// For RGB screen modes. Default to NTSC artifacts
io.softSwitchesData[ioFlag1RGBCard] = ssOn
io.softSwitchesData[ioFlag2RGBCard] = ssOn
}
func notImplementedSoftSwitchR(io *ioC0Page) uint8 {
// Return random info. Some games (Serpentine) used CASSETTE and get stuck if not changing.
return uint8(io.apple2.cpu.GetCycles())
func buildNotImplementedSoftSwitchR(io *ioC0Page) softSwitchR {
return func() uint8 {
// Return random info. Some games (Serpentine) used CASSETTE and get stuck if not changing.
return uint8(io.apple2.cpu.GetCycles())
}
}
func notImplementedSoftSwitchW(*ioC0Page, uint8) {
func buildNotImplementedSoftSwitchW(io *ioC0Page) softSwitchW {
return func(uint8) {
// Do nothing
}
}
func setStatusSoftSwitch(ioFlag uint8) softSwitchW {
return func(io *ioC0Page, value uint8) {
func setStatusSoftSwitch(io *ioC0Page, ioFlag uint8) softSwitchW {
return func(value uint8) {
io.softSwitchesData[ioFlag] = value
}
}
func getStatusSoftSwitch(ioFlag uint8) softSwitchR {
return func(io *ioC0Page) uint8 {
func getStatusSoftSwitch(io *ioC0Page, ioFlag uint8) softSwitchR {
return func() uint8 {
return io.softSwitchesData[ioFlag]
}
}
func getSoftSwitch(ioFlag uint8, isSet bool) softSwitchR {
return func(io *ioC0Page) uint8 {
func getSoftSwitch(io *ioC0Page, ioFlag uint8, isSet bool) softSwitchR {
return func() uint8 {
if isSet {
io.softSwitchesData[ioFlag] = ssOn
} else {
@ -113,35 +118,40 @@ func getSoftSwitch(ioFlag uint8, isSet bool) softSwitchR {
}
}
func speakerSoftSwitch(io *ioC0Page) uint8 {
if io.speaker != nil {
io.speaker.Click(io.apple2.cpu.GetCycles())
}
return 0
}
func keySoftSwitch(io *ioC0Page) uint8 {
strobed := (io.softSwitchesData[ioDataKeyboard] & (1 << 7)) == 0
if io.keyboard != nil {
if key, ok := io.keyboard.GetKey(strobed); ok {
io.softSwitchesData[ioDataKeyboard] = key + (1 << 7)
func buildSpeakerSoftSwitch(io *ioC0Page) softSwitchR {
return func() uint8 {
if io.speaker != nil {
io.speaker.Click(io.apple2.cpu.GetCycles())
}
return 0
}
value := io.softSwitchesData[ioDataKeyboard]
//fmt.Printf("Key $%02x, %v\n", value, strobed)
return value
}
func strobeKeyboardSoftSwitch(io *ioC0Page) uint8 {
result := io.softSwitchesData[ioDataKeyboard]
//fmt.Printf("Strobe $%02x\n", result)
io.softSwitchesData[ioDataKeyboard] &^= 1 << 7
return result
func buildKeySoftSwitch(io *ioC0Page) softSwitchR {
return func() uint8 {
strobed := (io.softSwitchesData[ioDataKeyboard] & (1 << 7)) == 0
if io.keyboard != nil {
if key, ok := io.keyboard.GetKey(strobed); ok {
io.softSwitchesData[ioDataKeyboard] = key + (1 << 7)
}
}
value := io.softSwitchesData[ioDataKeyboard]
//fmt.Printf("Key $%02x, %v\n", value, strobed)
return value
}
}
func getButtonSoftSwitch(i int) softSwitchR {
return func(io *ioC0Page) uint8 {
func buildStrobeKeyboardSoftSwitch(io *ioC0Page) softSwitchR {
return func() uint8 {
result := io.softSwitchesData[ioDataKeyboard]
//fmt.Printf("Strobe $%02x\n", result)
io.softSwitchesData[ioDataKeyboard] &^= 1 << 7
return result
}
}
func buildButtonSoftSwitch(io *ioC0Page, i int) softSwitchR {
return func() uint8 {
if io.joysticks != nil && io.joysticks.ReadButton(i) {
return 128
}
@ -161,8 +171,8 @@ func getButtonSoftSwitch(i int) softSwitchR {
const paddleToCyclesFactor = 11
func getPaddleSoftSwitch(i int) softSwitchR {
return func(io *ioC0Page) uint8 {
func buildPaddleSoftSwitch(io *ioC0Page, i int) softSwitchR {
return func() uint8 {
if io.joysticks == nil {
return 255 // Capacitors never discharge if there is not joystick
}
@ -180,8 +190,10 @@ func getPaddleSoftSwitch(i int) softSwitchR {
}
}
func strobePaddlesSoftSwitch(io *ioC0Page) uint8 {
// On the real machine this discharges the capacitors.
io.paddlesStrobeCycle = io.apple2.cpu.GetCycles()
return 0
func buildStrobePaddlesSoftSwitch(io *ioC0Page) softSwitchR {
return func() uint8 {
// On the real machine this discharges the capacitors.
io.paddlesStrobeCycle = io.apple2.cpu.GetCycles()
return 0
}
}

View File

@ -31,19 +31,19 @@ func addApple2ESoftSwitches(io *ioC0Page) {
addSoftSwitchesIou(io, 0x0e, 0x0f, 0x1e, ioFlagAltChar, "ALTCHARSET")
// Previous read softswithes
io.addSoftSwitchR(0x1A, getStatusSoftSwitch(ioFlagText), "TEXT")
io.addSoftSwitchR(0x1B, getStatusSoftSwitch(ioFlagMixed), "MIXED")
io.addSoftSwitchR(0x1C, getStatusSoftSwitch(ioFlagSecondPage), "PAGE2")
io.addSoftSwitchR(0x1D, getStatusSoftSwitch(ioFlagHiRes), "HIRES")
io.addSoftSwitchR(0x1A, getStatusSoftSwitch(io, ioFlagText), "TEXT")
io.addSoftSwitchR(0x1B, getStatusSoftSwitch(io, ioFlagMixed), "MIXED")
io.addSoftSwitchR(0x1C, getStatusSoftSwitch(io, ioFlagSecondPage), "PAGE2")
io.addSoftSwitchR(0x1D, getStatusSoftSwitch(io, ioFlagHiRes), "HIRES")
io.addSoftSwitchR(0x11, func(_ *ioC0Page) uint8 {
io.addSoftSwitchR(0x11, func() uint8 {
return ssFromBool(mmu.lcAltBank)
}, "BSRBANK2")
io.addSoftSwitchR(0x12, func(_ *ioC0Page) uint8 {
io.addSoftSwitchR(0x12, func() uint8 {
return ssFromBool(mmu.lcActiveRead)
}, "BSRREADRAM")
io.addSoftSwitchR(0x19, func(_ *ioC0Page) uint8 {
io.addSoftSwitchR(0x19, func() uint8 {
// See "Inside Apple IIe", page 268
// See http://rich12345.tripod.com/aiivideo/vbl.html
// For each screen draw:
@ -62,29 +62,29 @@ func addApple2ESoftSwitches(io *ioC0Page) {
}
func addSoftSwitchesMmu(io *ioC0Page, addressClear uint8, addressSet uint8, AddressGet uint8, flag *bool, name string) {
io.addSoftSwitchW(addressClear, func(_ *ioC0Page, _ uint8) {
io.addSoftSwitchW(addressClear, func(uint8) {
*flag = false
}, name+"OFF")
io.addSoftSwitchW(addressSet, func(_ *ioC0Page, _ uint8) {
io.addSoftSwitchW(addressSet, func(uint8) {
*flag = true
}, name+"ON")
io.addSoftSwitchR(AddressGet, func(_ *ioC0Page) uint8 {
io.addSoftSwitchR(AddressGet, func() uint8 {
return ssFromBool(*flag)
}, name)
}
func addSoftSwitchesIou(io *ioC0Page, addressClear uint8, addressSet uint8, AddressGet uint8, ioFlag uint8, name string) {
io.addSoftSwitchW(addressClear, func(_ *ioC0Page, _ uint8) {
io.addSoftSwitchW(addressClear, func(uint8) {
io.softSwitchesData[ioFlag] = ssOff
}, name+"OFF")
io.addSoftSwitchW(addressSet, func(_ *ioC0Page, _ uint8) {
io.addSoftSwitchW(addressSet, func(uint8) {
io.softSwitchesData[ioFlag] = ssOn
}, name+"ON")
io.addSoftSwitchR(AddressGet, func(_ *ioC0Page) uint8 {
io.addSoftSwitchR(AddressGet, func() uint8 {
return io.softSwitchesData[ioFlag]
}, name)
}