2019-02-16 19:15:41 +00:00
|
|
|
package apple2
|
2019-02-12 23:03:43 +00:00
|
|
|
|
|
|
|
type textPages struct {
|
2019-02-21 23:21:17 +00:00
|
|
|
pages [4]textPage
|
2019-02-12 23:03:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type textPage struct {
|
2019-02-14 23:41:56 +00:00
|
|
|
dirty bool
|
|
|
|
data [256]uint8
|
2019-02-12 23:03:43 +00:00
|
|
|
}
|
|
|
|
|
2019-02-16 19:15:41 +00:00
|
|
|
func (p *textPage) Peek(address uint8) uint8 {
|
2019-02-12 23:03:43 +00:00
|
|
|
return p.data[address]
|
|
|
|
}
|
|
|
|
|
2019-02-16 19:15:41 +00:00
|
|
|
func (p *textPage) Poke(address uint8, value uint8) {
|
2019-02-12 23:03:43 +00:00
|
|
|
p.data[address] = value
|
|
|
|
// Note: we could avoid setting dirty on the 16 blocks of 8 hidden bytes
|
2019-02-14 23:41:56 +00:00
|
|
|
p.dirty = true
|
|
|
|
}
|
|
|
|
|
2019-02-21 23:21:17 +00:00
|
|
|
func (tp *textPages) read(column uint8, line uint8) uint8 {
|
|
|
|
page, address := tp.charAddress(column, line)
|
|
|
|
return tp.pages[page].Peek(address)
|
2019-02-14 23:41:56 +00:00
|
|
|
}
|
|
|
|
|
2019-02-21 23:21:17 +00:00
|
|
|
func (tp *textPages) write(column uint8, line uint8, value uint8) {
|
|
|
|
page, address := tp.charAddress(column, line)
|
|
|
|
tp.pages[page].Poke(address, value)
|
2019-02-16 19:32:50 +00:00
|
|
|
}
|
|
|
|
|
2019-02-21 23:21:17 +00:00
|
|
|
func (tp *textPages) charAddress(column uint8, line uint8) (page uint8, address uint8) {
|
|
|
|
page = (line % 8) / 2
|
|
|
|
address = column + (line/8)*40 + (line%2)*128
|
|
|
|
return
|
2019-02-12 23:03:43 +00:00
|
|
|
}
|
|
|
|
|
2019-02-21 23:21:17 +00:00
|
|
|
func (tp *textPages) strobe() bool {
|
|
|
|
// Thread safe. May just mark more dirties than needed.
|
2019-02-14 23:41:56 +00:00
|
|
|
dirty := false
|
|
|
|
for i := 0; i < 4; i++ {
|
|
|
|
if tp.pages[i].dirty {
|
|
|
|
dirty = true
|
|
|
|
tp.pages[i].dirty = false
|
|
|
|
}
|
2019-02-12 23:03:43 +00:00
|
|
|
}
|
2019-02-21 23:21:17 +00:00
|
|
|
return dirty
|
2019-02-12 23:03:43 +00:00
|
|
|
}
|