mirror of
https://github.com/ivanizag/izapple2.git
synced 2026-10-25 03:02:24 +00:00
The screen modes mixed two independent things. Green, plain and NTSC read as three points on one scale, but plain and NTSC are the same colour rendering and differ in whether the gaps between the scan lines are drawn, while green is a phosphor that happened to always get them. They are now the four combinations of the two: ScreenModeGreen, ScreenModeColor, ScreenModeGreenScanlines and ScreenModeColorScanlines, built from a bit for each property. isColor and hasScanlines read them, so each place says what it means, and NextScreenMode rotates through the four. The old modes map onto the new ones exactly, green to green with scan lines, plain to color, NTSC to color with scan lines, and the frontends are moved over so nothing they show changes. The scenarios of the tests now cover all four, and their images are renamed after the modes. The three that already existed render byte for byte as they did.
126 lines
3.1 KiB
Go
126 lines
3.1 KiB
Go
package screen
|
|
|
|
import (
|
|
"fmt"
|
|
"image"
|
|
"image/color"
|
|
)
|
|
|
|
/*
|
|
See:
|
|
|
|
https://mrob.com/pub/xapple2/colors.html
|
|
https://archive.org/details/IIgs_2523063_Master_Color_Values
|
|
*/
|
|
var ntscColorMap = [16]color.Color{
|
|
color.RGBA{0, 0, 0, 255}, // Black
|
|
color.RGBA{227, 30, 96, 255}, // Magenta
|
|
color.RGBA{96, 78, 189, 255}, // Dark Blue
|
|
color.RGBA{255, 68, 253, 255}, // Purple
|
|
color.RGBA{0, 163, 96, 255}, // Dark Green
|
|
color.RGBA{156, 156, 156, 255}, // Grey 1
|
|
color.RGBA{20, 207, 253, 255}, // Medium Blue
|
|
color.RGBA{208, 195, 255, 255}, // Light Blue
|
|
color.RGBA{96, 114, 3, 255}, // Brown
|
|
color.RGBA{255, 106, 60, 255}, // Orange
|
|
color.RGBA{156, 156, 156, 255}, // Grey 2
|
|
color.RGBA{255, 160, 208, 255}, // Pink
|
|
color.RGBA{20, 245, 60, 255}, // Green
|
|
color.RGBA{208, 221, 141, 255}, // Yellow
|
|
color.RGBA{114, 255, 208, 255}, // Aquamarine
|
|
color.RGBA{255, 255, 255, 255}, // White
|
|
}
|
|
|
|
var attenuatedColorMap = buildAttenuatedColorMap(ntscColorMap)
|
|
|
|
func buildAttenuatedColorMap(colorMap [16]color.Color) [16]color.Color {
|
|
colors := [16]color.Color{}
|
|
for i := range len(colorMap) {
|
|
r, g, b, _ := colorMap[i].RGBA()
|
|
colors[i] = color.RGBA64{
|
|
uint16(4 * r / 5), uint16(4 * g / 5), uint16(4 * b / 5),
|
|
65535,
|
|
}
|
|
}
|
|
return colors
|
|
}
|
|
|
|
/*
|
|
var rgbColorMap = [16]color.Color{
|
|
color.RGBA{0, 0, 0, 255}, // Black
|
|
color.RGBA{221, 0, 51, 255}, // Magenta
|
|
color.RGBA{0, 0, 153, 255}, // Dark Blue
|
|
color.RGBA{221, 34, 221, 255}, // Purple
|
|
color.RGBA{0, 119, 34, 255}, // Dark Green
|
|
color.RGBA{85, 85, 85, 255}, // Grey 1
|
|
color.RGBA{34, 34, 255, 255}, // Medium Blue
|
|
color.RGBA{102, 170, 255, 255}, // Light Blue
|
|
color.RGBA{136, 85, 0, 255}, // Brown
|
|
color.RGBA{255, 102, 0, 255}, // Orange
|
|
color.RGBA{170, 170, 170, 255}, // Grey 2
|
|
color.RGBA{255, 153, 136, 255}, // Pink
|
|
color.RGBA{17, 221, 0, 255}, // Green
|
|
color.RGBA{255, 255, 0, 255}, // Yellow
|
|
color.RGBA{68, 255, 153, 255}, // Aquamarine
|
|
color.RGBA{255, 255, 255, 255}, // White
|
|
}
|
|
*/
|
|
|
|
func filterNTSCColor(in *image.RGBA, mask *image.Alpha, screenMode int) *image.RGBA {
|
|
colorMap := ntscColorMap // or rgbColorMap
|
|
colorMapLow := ntscColorMap
|
|
if hasScanlines(screenMode) {
|
|
colorMapLow = attenuatedColorMap
|
|
}
|
|
|
|
b := in.Bounds()
|
|
width := b.Dx()
|
|
height := b.Dy()
|
|
size := image.Rect(0, 0, width+4, height)
|
|
out := image.NewRGBA(size)
|
|
|
|
if width < 2*hiResWidth {
|
|
panic(fmt.Sprintf("The image has width %v. We can't apply the NTSC filter.", width))
|
|
}
|
|
|
|
for y := range height {
|
|
// We store the last four bits. We start with 0000
|
|
v := 0
|
|
for x := range width {
|
|
cIn := in.At(x, y)
|
|
r, _, _, _ := cIn.RGBA()
|
|
|
|
pos := 1 << uint(x%4)
|
|
if r != 0 {
|
|
v |= pos
|
|
} else {
|
|
v &^= pos
|
|
}
|
|
|
|
var cOut color.Color
|
|
if r != 0 {
|
|
cOut = colorMap[v]
|
|
} else {
|
|
cOut = colorMapLow[v]
|
|
}
|
|
if mask != nil {
|
|
// RGB mode7
|
|
_, _, _, a := mask.At(x, y).RGBA()
|
|
if a > 0 {
|
|
cOut = cIn
|
|
}
|
|
}
|
|
|
|
out.Set(x, y, cOut)
|
|
}
|
|
|
|
// We fade for the last three positions
|
|
for x := width; x < width+4; x++ {
|
|
v >>= 1
|
|
cOut := colorMap[v]
|
|
out.Set(x, y, cOut)
|
|
}
|
|
}
|
|
return out
|
|
}
|