izapple2/apple2/textPages.go

99 lines
2.0 KiB
Go

package apple2
import "fmt"
type textPages struct {
pages [4]textPage
}
type textPage struct {
dirty bool
data [256]uint8
}
func (p *textPage) Peek(address uint8) uint8 {
return p.data[address]
}
func (p *textPage) Poke(address uint8, value uint8) {
p.data[address] = value
// Note: we could avoid setting dirty on the 16 blocks of 8 hidden bytes
p.dirty = true
}
func textMemoryByteToString(value uint8) string {
value = value & 0x7F
if value < ' ' {
return "@"
}
return string(value)
}
func textMemoryByteToStringHex(value uint8) string {
return fmt.Sprintf("%02x ", value)
}
func (tp *textPages) prepare() {
fmt.Printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n")
}
func (tp *textPages) dump() {
// See "Understand the Apple II", page 5-10
// http://www.applelogic.org/files/UNDERSTANDINGTHEAII.pdf
fmt.Print("\033[26A")
fmt.Println("------------------------------------------")
var i, j, h uint8
// Top, middle and botton screen
for i = 0; i < 120; i = i + 40 {
// Memory pages
for _, p := range tp.pages {
// The two half pages
for _, h = range []uint8{0, 128} {
line := ""
for j = i + h; j < i+h+40; j++ {
line += textMemoryByteToString(p.Peek(j))
}
fmt.Printf("| %v |\n", line)
}
}
}
fmt.Println("------------------------------------------")
}
func (tp *textPages) dumpIfDirty() {
dirty := false
for i := 0; i < 4; i++ {
if tp.pages[i].dirty {
dirty = true
tp.pages[i].dirty = false
}
}
if !dirty {
return
}
tp.dump()
}
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
}
func (tp *textPages) read(column uint8, line uint8) uint8 {
page, address := tp.charAddress(column, line)
return tp.pages[page].Peek(address)
}
func (tp *textPages) write(column uint8, line uint8, value uint8) {
page, address := tp.charAddress(column, line)
tp.pages[page].Poke(address, value)
}