izapple2/ioC0Page.go

162 lines
3.8 KiB
Go
Raw Normal View History

2020-10-03 21:38:26 +00:00
package izapple2
2019-02-17 23:01:48 +00:00
import (
"fmt"
)
type ioC0Page struct {
softSwitchesR [256]softSwitchR
softSwitchesW [256]softSwitchW
2019-10-20 22:00:42 +00:00
softSwitchesRName [256]string
softSwitchesWName [256]string
softSwitchesData [128]uint8
keyboard KeyboardProvider
speaker SpeakerProvider
paddlesStrobeCycle uint64
joysticks JoysticksProvider
2021-01-24 22:25:52 +00:00
mouse MouseProvider
apple2 *Apple2
trace bool
2020-08-30 19:11:43 +00:00
traceRegistrations bool
panicNotImplemented bool
}
2022-08-05 17:43:17 +00:00
type softSwitchR func() uint8
type softSwitchW func(value uint8)
2019-08-05 22:37:27 +00:00
// SpeakerProvider provides a speaker implementation
2019-05-09 22:09:15 +00:00
type SpeakerProvider interface {
// Click receives a speaker click. The argument is the CPU cycle when it is generated
Click(cycle uint64)
}
2021-01-24 22:25:52 +00:00
// JoysticksProvider abstracts the joysticks
2019-08-05 22:37:27 +00:00
type JoysticksProvider interface {
ReadButton(i int) bool
ReadPaddle(i int) (uint8, bool)
2019-08-05 22:37:27 +00:00
}
2021-01-24 22:25:52 +00:00
// MouseProvider abstracts the mouse
type MouseProvider interface {
ReadMouse() (x uint16, y uint16, pressed bool)
}
// See https://www.kreativekorp.com/miscpages/a2info/iomemory.shtml
// See https://stason.org/TULARC/pc/apple2/programmer/004-I-d-like-to-do-some-serious-Apple-II-programming-Whe.html
const (
ssOn uint8 = 0x80
ssOff uint8 = 0x00
)
func newIoC0Page(a *Apple2) *ioC0Page {
2019-02-24 14:05:50 +00:00
var io ioC0Page
io.apple2 = a
2019-02-24 14:05:50 +00:00
return &io
}
func (p *ioC0Page) setTrace(trace bool) {
p.trace = trace
}
2020-08-30 19:11:43 +00:00
func (p *ioC0Page) setTraceRegistrations(traceRegistrations bool) {
p.traceRegistrations = traceRegistrations
}
func (p *ioC0Page) setPanicNotImplemented(value bool) {
p.panicNotImplemented = value
}
2019-10-20 22:00:42 +00:00
func (p *ioC0Page) addSoftSwitchRW(address uint8, ss softSwitchR, name string) {
p.addSoftSwitchR(address, ss, name)
2022-08-05 17:43:17 +00:00
p.addSoftSwitchW(address, func(uint8) {
ss()
2019-10-20 22:00:42 +00:00
}, name)
}
2019-10-20 22:00:42 +00:00
func (p *ioC0Page) addSoftSwitchR(address uint8, ss softSwitchR, name string) {
2020-08-30 19:11:43 +00:00
if p.traceRegistrations {
fmt.Printf("Softswitch registered in $c0%02x for reads as %s\n", address, name)
}
p.softSwitchesR[address] = ss
2019-10-20 22:00:42 +00:00
p.softSwitchesRName[address] = name
}
2019-10-20 22:00:42 +00:00
func (p *ioC0Page) addSoftSwitchW(address uint8, ss softSwitchW, name string) {
2020-08-30 19:11:43 +00:00
if p.traceRegistrations {
fmt.Printf("Softswitch registered in $c0%02x for writes as %s\n", address, name)
}
p.softSwitchesW[address] = ss
2019-10-20 22:00:42 +00:00
p.softSwitchesWName[address] = name
}
2019-04-21 19:04:02 +00:00
func (p *ioC0Page) isSoftSwitchActive(ioFlag uint8) bool {
2019-02-24 14:05:50 +00:00
return (p.softSwitchesData[ioFlag] & ssOn) == ssOn
}
2019-04-13 18:29:31 +00:00
func (p *ioC0Page) setKeyboardProvider(kb KeyboardProvider) {
p.keyboard = kb
}
2019-05-09 22:09:15 +00:00
func (p *ioC0Page) setSpeakerProvider(s SpeakerProvider) {
p.speaker = s
}
2019-08-05 22:37:27 +00:00
func (p *ioC0Page) setJoysticksProvider(j JoysticksProvider) {
p.joysticks = j
}
2021-01-24 22:25:52 +00:00
func (p *ioC0Page) setMouseProvider(m MouseProvider) {
p.mouse = m
}
func (p *ioC0Page) peek(address uint16) uint8 {
pageAddress := uint8(address)
ss := p.softSwitchesR[pageAddress]
if ss == nil {
if p.trace {
fmt.Printf("Unknown softswitch on read to $%04x\n", address)
}
if p.panicNotImplemented {
panic(fmt.Sprintf("Unknown softswitch on read to $%04x", address))
2019-04-15 21:13:05 +00:00
}
2019-03-04 23:00:12 +00:00
return 0
}
2022-08-05 17:43:17 +00:00
value := ss()
2019-10-20 22:00:42 +00:00
if p.trace && address != 0xc000 {
name := p.softSwitchesRName[pageAddress]
fmt.Printf("Softswitch peek on $%04x %v: $%02x\n", address, name, value)
}
return value
}
func (p *ioC0Page) poke(address uint16, value uint8) {
pageAddress := uint8(address)
ss := p.softSwitchesW[pageAddress]
if ss == nil {
if p.trace {
fmt.Printf("Unknown softswitch on write to $%04x\n", address)
}
if p.panicNotImplemented {
panic(fmt.Sprintf("Unknown softswitch on write to $%04x", address))
2019-04-15 21:13:05 +00:00
}
2019-03-04 23:00:12 +00:00
return
}
2019-10-20 22:00:42 +00:00
if p.trace && address != 0xc000 {
name := p.softSwitchesWName[pageAddress]
fmt.Printf("Softswitch poke on $%04x %v with $%02x\n", address, name, value)
}
2022-08-05 17:43:17 +00:00
ss(value)
}
2019-11-05 23:02:03 +00:00
func (p *ioC0Page) setBase(_ uint16) {
// Ignore
}
2019-11-05 23:02:03 +00:00
func ssFromBool(value bool) uint8 {
if value {
return ssOn
}
return ssOff
}