mirror of
https://github.com/ivanizag/izapple2.git
synced 2024-12-26 20:29:50 +00:00
129 lines
3.0 KiB
Go
129 lines
3.0 KiB
Go
package izapple2
|
|
|
|
/*
|
|
Language card with 16 extra kb for the Apple ][ and ][+
|
|
Manual: http://www.applelogic.org/files/LANGCARDMAN.pdf
|
|
|
|
The language card doesn't have ROM for Cx00. It would not
|
|
be used in slot 0 anyway.
|
|
|
|
Note also that language cards for the Apple ][ had ROM on
|
|
board to replace the main board F8 ROM with Autostart. That
|
|
was not used/needed on the Apple ][+. As this emulates the
|
|
Apple ][+, it is not considered. For the Plus it is often
|
|
referred as Language card but it is really a 16 KB Ram card,
|
|
|
|
|
|
"When RAM is deselected, the ROM on the Language card is selected for
|
|
the top 2K ($F800-$FFFF), and the ROM on the main board is selected
|
|
for $D000-$F7FF.
|
|
|
|
Power on RESET initializes ROM to read mode and RAM to write mode,
|
|
and selects the second 4K bank to map $D000-$DFFF."
|
|
|
|
Writing to the softswitch disables writing in LC? Saw that
|
|
somewhere but doing so fails IIe self check.
|
|
|
|
|
|
*/
|
|
|
|
// CardLanguage is an Language Card
|
|
type CardLanguage struct {
|
|
cardBase
|
|
readState bool
|
|
writeState uint8
|
|
altBank bool // false is bank1, true is bank2
|
|
}
|
|
|
|
func newCardLanguageBuilder() *cardBuilder {
|
|
return &cardBuilder{
|
|
name: "16 KB Language Card",
|
|
description: "Language card with 16 extra KB for the Apple ][ and ][+",
|
|
buildFunc: func(params map[string]string) (Card, error) {
|
|
return &CardLanguage{}, nil
|
|
},
|
|
}
|
|
}
|
|
|
|
const (
|
|
// Write enabling requires two softswitch accesses
|
|
lcWriteDisabled = 0
|
|
lcWriteHalfEnabled = 1
|
|
lcWriteEnabled = 2
|
|
)
|
|
|
|
func (c *CardLanguage) reset() {
|
|
if c.a.isApple2e {
|
|
// UtA2e 1-3, 5-23
|
|
c.readState = false
|
|
c.writeState = lcWriteEnabled
|
|
c.altBank = true // Start on bank2
|
|
c.applyState()
|
|
}
|
|
|
|
}
|
|
|
|
func (c *CardLanguage) assign(a *Apple2, slot int) {
|
|
c.readState = false
|
|
c.writeState = lcWriteEnabled
|
|
c.altBank = true // Start on bank2
|
|
|
|
a.mmu.initLanguageRAM(1)
|
|
for i := uint8(0x0); i <= 0xf; i++ {
|
|
iCopy := i
|
|
c.addCardSoftSwitchR(iCopy, func() uint8 {
|
|
c.ssAction(iCopy, false)
|
|
return 0
|
|
}, "LANGCARDR")
|
|
c.addCardSoftSwitchW(iCopy, func(uint8) {
|
|
c.ssAction(iCopy, true)
|
|
}, "LANGCARDW")
|
|
}
|
|
|
|
c.cardBase.assign(a, slot)
|
|
c.applyState()
|
|
}
|
|
|
|
func (c *CardLanguage) ssAction(ss uint8, write bool) {
|
|
c.altBank = ((ss >> 3) & 1) == 0
|
|
action := ss & 0x3
|
|
switch action {
|
|
case 0:
|
|
// RAM read, no writes
|
|
c.readState = true
|
|
c.writeState = lcWriteDisabled
|
|
case 1:
|
|
// ROM read, RAM write
|
|
c.readState = false
|
|
if !write {
|
|
c.writeState++
|
|
}
|
|
case 2:
|
|
// ROM read, no writes
|
|
c.readState = false
|
|
c.writeState = lcWriteDisabled
|
|
case 3:
|
|
//RAM read, RAM write
|
|
c.readState = true
|
|
if !write {
|
|
c.writeState++
|
|
}
|
|
}
|
|
|
|
if write && c.writeState == lcWriteHalfEnabled {
|
|
// UtA2e, 5-23. It is reset by even read access or any write acccess in the $C08x range
|
|
// And https://github.com/zellyn/a2audit/issues/3
|
|
c.writeState = lcWriteDisabled
|
|
}
|
|
|
|
if c.writeState > lcWriteEnabled {
|
|
c.writeState = lcWriteEnabled
|
|
}
|
|
|
|
c.applyState()
|
|
}
|
|
|
|
func (c *CardLanguage) applyState() {
|
|
c.a.mmu.setLanguageRAM(c.readState, c.writeState == lcWriteEnabled, c.altBank)
|
|
}
|