izapple2/screen/superHiRes.go

98 lines
2.3 KiB
Go
Raw Normal View History

2020-10-16 18:41:34 +00:00
package screen
2019-11-11 21:58:42 +00:00
import (
"image"
"image/color"
)
const (
shrWidth = 640
shrWidthBytes = 640 / 4
shrHeight = 200
palettesCount = 256
2020-10-16 18:41:34 +00:00
shrScanLineControlOffset = uint16(0x7d00)
shrColorPalettesOffset = uint16(0x7e00)
2019-11-11 21:58:42 +00:00
)
2020-10-16 18:41:34 +00:00
func snapshotSuperHiRes(vs VideoSource) *image.RGBA {
data := vs.GetSuperVideoMemory()
return renderSuperHiRes(data)
}
func renderSuperHiRes(data []uint8) *image.RGBA {
2019-11-11 21:58:42 +00:00
// See "Apple IIGS Hardware Reference", chapter 4, page 91
// http://www.applelogic.org/files/GSHARDWAREREF.pdf
size := image.Rect(0, 0, shrWidth, shrHeight)
img := image.NewRGBA(size)
2020-08-09 15:06:02 +00:00
// Load the palettes
2019-11-11 21:58:42 +00:00
colors := make([]color.Color, palettesCount)
2020-10-16 18:41:34 +00:00
iMem := uint16(0)
2019-11-11 21:58:42 +00:00
for i := 0; i < palettesCount; i++ {
2020-10-16 18:41:34 +00:00
b0 := data[iMem+shrColorPalettesOffset]
2019-11-11 21:58:42 +00:00
iMem++
2020-10-16 18:41:34 +00:00
b1 := data[iMem+shrColorPalettesOffset]
2019-11-11 21:58:42 +00:00
iMem++
2019-11-11 22:49:48 +00:00
red := (b1 & 0x0f) << 4
green := b0 & 0xf0
blue := (b0 & 0x0f) << 4
2019-11-11 21:58:42 +00:00
colors[i] = color.RGBA{red, green, blue, 255}
}
// See "Apple IIGS Hardware Reference", table 4-21
palettesSelectionTable := []uint8{0x4, 0x0, 0xc, 0x8}
// Build the lines
for y := 0; y < shrHeight; y++ {
2020-10-16 18:41:34 +00:00
controlByte := data[uint16(y)+shrScanLineControlOffset]
2019-11-11 21:58:42 +00:00
is640Wide := (controlByte & 0x80) != 0
isColorFill := (controlByte & 0x20) != 0
2020-08-09 15:06:02 +00:00
paletteIndex := (controlByte & 0x0f) << 4
2019-11-11 21:58:42 +00:00
2020-10-16 18:41:34 +00:00
lineAddress := uint16(shrWidthBytes * y)
lineBytes := data[lineAddress : lineAddress+shrWidthBytes]
2019-11-11 21:58:42 +00:00
if is640Wide {
// Line is 640 pixels, two bits per pixel
x := 0
for i := 0; i < shrWidthBytes; i++ {
b := lineBytes[i]
for j := 3; j >= 0; j-- {
p := (b >> (uint(j) * 2)) & 0x03
offset := palettesSelectionTable[j]
2020-08-09 15:06:02 +00:00
color := colors[paletteIndex+offset+p]
2019-11-11 21:58:42 +00:00
img.Set(x, y, color)
x++
}
}
} else {
// Line is 320 pixels, two pixels per byte
x := 0
previousColor := uint8(0)
for i := 0; i < shrWidthBytes; i++ {
p0 := (lineBytes[i] & 0xf0) >> 4
if isColorFill && p0 == 0 {
p0 = previousColor
} else {
previousColor = p0
}
p1 := lineBytes[i] & 0x0f
if isColorFill && p1 == 0 {
p1 = previousColor
} else {
previousColor = p1
}
2020-08-09 15:06:02 +00:00
img.Set(x, y, colors[paletteIndex+p0])
img.Set(x+1, y, colors[paletteIndex+p0])
img.Set(x+2, y, colors[paletteIndex+p1])
img.Set(x+3, y, colors[paletteIndex+p1])
2019-11-11 21:58:42 +00:00
x += 4
}
}
}
return img
}