izapple2/screen/text.go

131 lines
3.4 KiB
Go
Raw Permalink Normal View History

2020-10-16 18:41:34 +00:00
package screen
2019-05-03 18:09:53 +00:00
import (
"image"
"image/color"
2021-03-01 23:19:18 +00:00
"time"
2019-05-03 18:09:53 +00:00
)
const (
2020-10-04 17:21:49 +00:00
charWidth = 7
charHeight = 8
text40Columns = 40
textLines = 24
2019-05-03 18:09:53 +00:00
)
2021-03-01 23:19:18 +00:00
func snapshotText40(vs VideoSource, isSecondPage bool, isAltText bool, light color.Color) *image.RGBA {
2020-10-16 18:41:34 +00:00
text := getTextFromMemory(vs, isSecondPage, false)
2021-03-01 23:19:18 +00:00
return renderText(vs, text, isAltText, nil /*colorMap*/, light)
}
2019-05-03 18:09:53 +00:00
2021-03-01 23:19:18 +00:00
func snapshotText80(vs VideoSource, isSecondPage bool, isAltText bool, light color.Color) *image.RGBA {
2020-10-16 18:41:34 +00:00
text := getText80FromMemory(vs, isSecondPage)
2021-03-01 23:19:18 +00:00
return renderText(vs, text, isAltText, nil /*colorMap*/, light)
}
2021-03-01 23:19:18 +00:00
func snapshotText40RGB(vs VideoSource, isSecondPage bool, isAltText bool) *image.RGBA {
2020-10-16 18:41:34 +00:00
text := getTextFromMemory(vs, isSecondPage, false)
colorMap := getTextFromMemory(vs, isSecondPage, true)
2021-03-01 23:19:18 +00:00
return renderText(vs, text, isAltText, colorMap, nil)
}
2020-10-16 18:41:34 +00:00
func snapshotText40RGBColors(vs VideoSource, isSecondPage bool) *image.RGBA {
colorMap := getTextFromMemory(vs, isSecondPage, true)
2021-03-01 23:19:18 +00:00
return renderText(vs, nil /*text*/, false, colorMap, nil)
}
2020-10-16 18:41:34 +00:00
func getText80FromMemory(vs VideoSource, isSecondPage bool) []uint8 {
text40Columns := getTextFromMemory(vs, isSecondPage, false)
text40ColumnsAlt := getTextFromMemory(vs, isSecondPage, true)
2019-11-08 22:56:54 +00:00
// Merge the two 40 cols to return 80 cols
text80Columns := make([]uint8, 2*len(text40Columns))
for i := 0; i < len(text40Columns); i++ {
text80Columns[2*i] = text40ColumnsAlt[i]
text80Columns[2*i+1] = text40Columns[i]
}
return text80Columns
2019-11-08 22:56:54 +00:00
}
2019-05-03 18:09:53 +00:00
2020-10-16 18:41:34 +00:00
func getTextFromMemory(vs VideoSource, isSecondPage bool, isExt bool) []uint8 {
data := vs.GetTextMemory(isSecondPage, isExt)
2019-11-08 22:56:54 +00:00
2020-10-04 17:21:49 +00:00
text := make([]uint8, textLines*text40Columns)
for l := 0; l < textLines; l++ {
2020-10-04 17:21:49 +00:00
for c := 0; c < text40Columns; c++ {
char := data[getTextCharOffset(c, l)]
2020-10-04 17:21:49 +00:00
text[text40Columns*l+c] = char
2019-11-08 22:56:54 +00:00
}
}
return text
}
2020-10-16 18:41:34 +00:00
func getTextCharOffset(col int, line int) uint16 {
// See "Understanding the Apple II", page 5-10
// http://www.applelogic.org/files/UNDERSTANDINGTHEAII.pdf
section := line / 8 // Top, middle and bottom
eighth := line % 8
return uint16(section*40 + eighth*0x80 + col)
}
func getRGBTextColor(pixel bool, colorKey uint8) color.Color {
if pixel {
colorKey >>= 4
}
colorKey &= 0x0f
2020-08-09 15:42:47 +00:00
return ntscColorMap[colorKey]
}
2021-03-01 23:19:18 +00:00
func renderText(vs VideoSource, text []uint8, isAltText bool, colorMap []uint8, light color.Color) *image.RGBA {
// Flash mode is 2Hz (host time)
isFlashedFrame := time.Now().Nanosecond() > (1 * 1000 * 1000 * 1000 / 2)
columns := len(text) / textLines
if text == nil {
2020-10-04 17:21:49 +00:00
columns = text40Columns
}
2019-11-08 22:56:54 +00:00
width := columns * charWidth
height := textLines * charHeight
2020-10-04 17:21:49 +00:00
size := image.Rect(0, 0, 2*hiResWidth, hiResHeight)
2019-05-03 18:09:53 +00:00
img := image.NewRGBA(size)
for x := 0; x < width; x++ {
for y := 0; y < height; y++ {
2019-11-08 22:56:54 +00:00
line := y / charHeight
2019-05-03 18:09:53 +00:00
col := x / charWidth
rowInChar := y % charHeight
colInChar := x % charWidth
charIndex := line*columns + col
var char uint8
if text != nil {
char = text[charIndex]
} else {
char = 79 + 128 // Debug screen filed with O
}
2021-03-01 23:19:18 +00:00
pixel := vs.GetCharacterPixel(char, rowInChar, colInChar, isAltText, isFlashedFrame)
2019-05-03 18:09:53 +00:00
var colour color.Color
if colorMap != nil {
colour = getRGBTextColor(pixel, colorMap[charIndex])
} else if pixel {
2019-05-03 19:45:29 +00:00
colour = light
2019-05-03 18:09:53 +00:00
} else {
colour = color.Black
}
2020-10-04 17:21:49 +00:00
if columns == text40Columns {
img.Set(x*2, y, colour)
img.Set(x*2+1, y, colour)
} else {
img.Set(x, y, colour)
}
2019-05-03 18:09:53 +00:00
}
}
return img
}