-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathcardLanguage.go
128 lines (106 loc) · 2.99 KB
/
cardLanguage.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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)
}