mirror of
https://github.com/ivanizag/izapple2.git
synced 2025-01-03 11:30:29 +00:00
186 lines
4.2 KiB
Go
186 lines
4.2 KiB
Go
package screen
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"image"
|
|
"image/color"
|
|
"image/png"
|
|
"io/ioutil"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
// TestScenario is the computer video state
|
|
type TestScenario struct {
|
|
VideoMode uint16 `json:"mode"`
|
|
VideoModeName string `json:"name"`
|
|
ScreenModes []int `json:"screens"`
|
|
TextPages [4][]uint8 `json:"text"`
|
|
VideoPages [4][]uint8 `json:"video"`
|
|
SVideoPage []uint8 `json:"svideo"`
|
|
}
|
|
|
|
func grabTestScenario(vs VideoSource) *TestScenario {
|
|
textPages := [4][]uint8{
|
|
cloneSlice(vs.GetTextMemory(false, false)),
|
|
cloneSlice(vs.GetTextMemory(false, true)),
|
|
cloneSlice(vs.GetTextMemory(true, false)),
|
|
cloneSlice(vs.GetTextMemory(true, true)),
|
|
}
|
|
videoPages := [4][]uint8{
|
|
cloneSlice(vs.GetVideoMemory(false, false)),
|
|
cloneSlice(vs.GetVideoMemory(false, true)),
|
|
cloneSlice(vs.GetVideoMemory(true, false)),
|
|
cloneSlice(vs.GetVideoMemory(true, true)),
|
|
}
|
|
|
|
knownModes := []int{
|
|
ScreenModeGreen,
|
|
ScreenModeNTSC,
|
|
ScreenModePlain,
|
|
}
|
|
|
|
return &TestScenario{
|
|
vs.GetCurrentVideoMode(),
|
|
VideoModeName(vs),
|
|
knownModes,
|
|
textPages,
|
|
videoPages,
|
|
cloneSlice(vs.GetSuperVideoMemory()),
|
|
}
|
|
}
|
|
|
|
func cloneSlice(src []uint8) []uint8 {
|
|
dst := make([]uint8, len(src))
|
|
copy(dst, src)
|
|
return dst
|
|
}
|
|
|
|
func loadTestScenario(filename string) (*TestScenario, error) {
|
|
bytes, err := ioutil.ReadFile(filename)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var ts TestScenario
|
|
err = json.Unmarshal(bytes, &ts)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &ts, nil
|
|
}
|
|
|
|
func (ts *TestScenario) save(dir string) (string, error) {
|
|
bytes, err := json.Marshal(ts)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
pattern := fmt.Sprintf("%v_*.json", strings.ToLower(ts.VideoModeName))
|
|
file, err := ioutil.TempFile(dir, pattern)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer file.Close()
|
|
|
|
_, err = file.Write(bytes)
|
|
return file.Name(), err
|
|
}
|
|
|
|
// GetCurrentVideoMode returns the active video mode
|
|
func (ts *TestScenario) GetCurrentVideoMode() uint16 {
|
|
return ts.VideoMode
|
|
}
|
|
|
|
func optionsToIndex(secondPage bool, ext bool) int {
|
|
index := 0
|
|
if secondPage {
|
|
index += 2
|
|
}
|
|
if ext {
|
|
index++
|
|
}
|
|
return index
|
|
}
|
|
|
|
// GetTextMemory returns a slice to the text memory pages
|
|
func (ts *TestScenario) GetTextMemory(secondPage bool, ext bool) []uint8 {
|
|
return ts.TextPages[optionsToIndex(secondPage, ext)]
|
|
}
|
|
|
|
// GetVideoMemory returns a slice to the video memory pages
|
|
func (ts *TestScenario) GetVideoMemory(secondPage bool, ext bool) []uint8 {
|
|
return ts.VideoPages[optionsToIndex(secondPage, ext)]
|
|
}
|
|
|
|
// GetCharacterPixel returns the pixel as output by the character generator
|
|
func (ts *TestScenario) GetCharacterPixel(char uint8, rowInChar int, colInChar int, isAltText bool, isFlashedFrame bool) bool {
|
|
// We don't have a character generator. We will return a square or blank for spaces
|
|
if char&0x3f == 0x20 {
|
|
return false // Space char
|
|
}
|
|
|
|
return !(rowInChar == 0 || rowInChar == 7 || colInChar == 0 || colInChar == 6)
|
|
}
|
|
|
|
// GetSuperVideoMemory returns a slice to the SHR video memory
|
|
func (ts *TestScenario) GetSuperVideoMemory() []uint8 {
|
|
return ts.SVideoPage
|
|
}
|
|
|
|
// GetCardImage returns an image provided by a card, like the videx card
|
|
func (ts *TestScenario) GetCardImage(light color.Color) *image.RGBA {
|
|
return nil
|
|
}
|
|
|
|
func buildImageName(name string, screenMode int, altSet bool) string {
|
|
var screenName string
|
|
switch screenMode {
|
|
case ScreenModeGreen:
|
|
screenName = "green"
|
|
case ScreenModeNTSC:
|
|
screenName = "ntsc"
|
|
case ScreenModePlain:
|
|
screenName = "plain"
|
|
default:
|
|
screenName = "unknown"
|
|
}
|
|
|
|
if altSet {
|
|
screenName += "_new"
|
|
}
|
|
|
|
return strings.TrimSuffix(name, ".json") +
|
|
screenName + ".png"
|
|
}
|
|
|
|
func (ts *TestScenario) generateSnapshots(baseName string, altSet bool) error {
|
|
for _, screen := range ts.ScreenModes {
|
|
image := Snapshot(ts, screen)
|
|
imageName := buildImageName(baseName, screen, altSet)
|
|
f, err := os.Create(imageName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer f.Close()
|
|
|
|
png.Encode(f, image)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// AddScenario Generate a new video scenario
|
|
func AddScenario(vs VideoSource, dir string) error {
|
|
// Get memory contents
|
|
ts := grabTestScenario(vs)
|
|
|
|
name, err := ts.save(dir)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return ts.generateSnapshots(name, false)
|
|
}
|