From f80b635ff16e8abb631b1d927fe9da56734fb944 Mon Sep 17 00:00:00 2001 From: Ivan Izaguirre Date: Fri, 3 May 2019 21:45:29 +0200 Subject: [PATCH] Support for mixed graph mode --- apple2/screen.go | 67 ++++++++++++++++++++++++++++++++++++-------- apple2/screenHgr.go | 61 ++++++++++++++++++++++++++++++---------- apple2/screenText.go | 34 +++++++++++----------- 3 files changed, 117 insertions(+), 45 deletions(-) diff --git a/apple2/screen.go b/apple2/screen.go index 82fbe08..970671d 100644 --- a/apple2/screen.go +++ b/apple2/screen.go @@ -19,32 +19,75 @@ References: func Snapshot(a *Apple2) *image.RGBA { isTextMode := a.io.isSoftSwitchActive(ioFlagText) isHiResMode := a.io.isSoftSwitchActive(ioFlagHiRes) + isMixMode := a.io.isSoftSwitchActive(ioFlagMixed) // Todo: isMixMode pageIndex := 0 if a.io.isSoftSwitchActive(ioFlagSecondPage) { pageIndex = 1 } + var snap *image.RGBA if isTextMode { - //return snapshotTextMode(a, pageIndex) - return linesSeparatedFilter(snapshotTextMode(a, pageIndex)) + // Color for typical Apple ][ period green phosphor monitors + // See: https://superuser.com/questions/361297/what-colour-is-the-dark-green-on-old-fashioned-green-screen-computer-displays + p1GreenPhosphorColor := color.RGBA{65, 255, 0, 255} + + snap = snapshotTextMode(a, pageIndex, false, p1GreenPhosphorColor) + snap = linesSeparatedFilter(snap) } else { if isHiResMode { - //return snapshotHiResModeReferenceMono(a, pageIndex) - //return linesSeparatedFilter(snapshotHiResModeMonoShift(a, pageIndex)) - return linesSeparatedFilter(filterNTSCColorMoving(false, snapshotHiResModeMonoShift(a, pageIndex))) - //return linesSeparatedFilter(filterNTSCColorStatic(snapshotHiResModeMonoShift(a, pageIndex))) - - //return snapshotHiResModeReferenceColor(a, pageIndex) - //return snapshotHiResModeReferenceColorSolid(a, pageIndex) + //snap = snapshotHiResModeReferenceMono(a, pageIndex, isMixMode) + //snap = snapshotHiResModeReferenceColor(a, pageIndex, isMixMode) + //snap = snapshotHiResModeReferenceColorSolid(a, pageIndex, isMixMode) + snap = snapshotHiResModeMonoShift(a, pageIndex, isMixMode) } else { // Lo res mode not supported + return nil + } + if isMixMode { + snapText := snapshotTextMode(a, pageIndex, isHiResMode, color.White) + snap = mixSnapshots(snap, snapText) + } + //snap = filterNTSCColorStatic(snap) + snap = filterNTSCColorMoving(false /*blacker*/, snap) + snap = linesSeparatedFilter(snap) + } + return snap +} + +func mixSnapshots(top, bottom *image.RGBA) *image.RGBA { + topBounds := top.Bounds() + topWidth := topBounds.Dx() + topHeight := topBounds.Dy() + + bottomBounds := bottom.Bounds() + bottomWidth := bottomBounds.Dx() + bottomHeight := bottomBounds.Dy() + + factor := topWidth / bottomWidth + + size := image.Rect(0, 0, topWidth, topHeight+bottomHeight) + out := image.NewRGBA(size) + + // Copy top + for y := topBounds.Min.Y; y < topBounds.Max.Y; y++ { + for x := topBounds.Min.X; x < topBounds.Max.X; x++ { + c := top.At(x, y) + out.Set(x, y, c) } } - //fmt.Printf("g: %v, h: %v\n", isTextMode, isHiResMode) - return nil - //panic("Screen mode not supported") + // Copy bottom, applyng the factor + for y := bottomBounds.Min.Y; y < bottomBounds.Max.Y; y++ { + for x := bottomBounds.Min.X; x < bottomBounds.Max.X; x++ { + c := bottom.At(x, y) + for f := 0; f < factor; f++ { + out.Set(x*factor+f, topHeight+y, c) + } + } + } + + return out } func saveSnapshot(a *Apple2) { diff --git a/apple2/screenHgr.go b/apple2/screenHgr.go index c45b725..6460d4c 100644 --- a/apple2/screenHgr.go +++ b/apple2/screenHgr.go @@ -5,6 +5,14 @@ import ( "image/color" ) +const ( + graphWidth = 280 + graphHeight = 192 + graphHeightMixed = 160 + graphPage1Address = uint16(0x2000) + graphPage2Address = uint16(0x4000) +) + func getGraphLineOffset(line int) uint16 { // See "Understanding the Apple II", page 5-14 @@ -29,12 +37,18 @@ func getGraphLine(a *Apple2, line int, page int) []uint8 { return memPage[lo : lo+40] } -func snapshotHiResModeReferenceMono(a *Apple2, page int) *image.RGBA { +func snapshotHiResModeReferenceMono(a *Apple2, page int, mixedMode bool) *image.RGBA { // As defined on "Apple II Reference Manual", page 19 - size := image.Rect(0, 0, graphWidth, graphHeight) + + height := graphHeight + if mixedMode { + height = graphHeightMixed + } + + size := image.Rect(0, 0, graphWidth, height) img := image.NewRGBA(size) - for y := 0; y < graphHeight; y++ { + for y := 0; y < height; y++ { bytes := getGraphLine(a, y, page) x := 0 for _, b := range bytes { @@ -53,12 +67,18 @@ func snapshotHiResModeReferenceMono(a *Apple2, page int) *image.RGBA { return img } -func snapshotHiResModeMonoShift(a *Apple2, page int) *image.RGBA { +func snapshotHiResModeMonoShift(a *Apple2, page int, mixedMode bool) *image.RGBA { // As described in "Undertanding the Apple II", with half pixel shifts - size := image.Rect(0, 0, 2*graphWidth, graphHeight) + + height := graphHeight + if mixedMode { + height = graphHeightMixed + } + + size := image.Rect(0, 0, 2*graphWidth, height) img := image.NewRGBA(size) - for y := 0; y < graphHeight; y++ { + for y := 0; y < height; y++ { bytes := getGraphLine(a, y, page) x := 0 previousColour := color.Black @@ -85,9 +105,15 @@ func snapshotHiResModeMonoShift(a *Apple2, page int) *image.RGBA { return img } -func snapshotHiResModeReferenceColor(a *Apple2, page int) *image.RGBA { +func snapshotHiResModeReferenceColor(a *Apple2, page int, mixedMode bool) *image.RGBA { // As defined on "Apple II Reference Manual", page 19 - size := image.Rect(0, 0, graphWidth, graphHeight) + + height := graphHeight + if mixedMode { + height = graphHeightMixed + } + + size := image.Rect(0, 0, graphWidth, height) img := image.NewRGBA(size) // RGB values from https://mrob.com/pub/xapple2/colors.html @@ -112,7 +138,7 @@ func snapshotHiResModeReferenceColor(a *Apple2, page int) *image.RGBA { }, } - for y := 0; y < graphHeight; y++ { + for y := 0; y < height; y++ { bytes := getGraphLine(a, y, page) x := 0 previous := uint8(0) @@ -136,10 +162,16 @@ func snapshotHiResModeReferenceColor(a *Apple2, page int) *image.RGBA { return img } -func snapshotHiResModeReferenceColorSolid(a *Apple2, page int) *image.RGBA { +func snapshotHiResModeReferenceColorSolid(a *Apple2, page int, mixedMode bool) *image.RGBA { // As defined on "Apple II Reference Manual", page 19 - // but with more solid colors - size := image.Rect(0, 0, graphWidth, graphHeight) + // but with more solid colors and half the resolution + + height := graphHeight + if mixedMode { + height = graphHeightMixed + } + + size := image.Rect(0, 0, graphWidth/2, height) img := image.NewRGBA(size) // RGB values from https://mrob.com/pub/xapple2/colors.html @@ -164,7 +196,7 @@ func snapshotHiResModeReferenceColorSolid(a *Apple2, page int) *image.RGBA { }, } - for y := 0; y < graphHeight; y++ { + for y := 0; y < height; y++ { bytes := getGraphLine(a, y, page) x := 0 previous := uint8(0) @@ -177,8 +209,7 @@ func snapshotHiResModeReferenceColorSolid(a *Apple2, page int) *image.RGBA { previous = bit } else { colour := colorMap[shift][(previous<<1)+bit] - img.Set(x-1, y, colour) - img.Set(x, y, colour) + img.Set(x/2, y, colour) } x++ } diff --git a/apple2/screenText.go b/apple2/screenText.go index 7f83f8e..b0cbb5e 100644 --- a/apple2/screenText.go +++ b/apple2/screenText.go @@ -7,16 +7,13 @@ import ( ) const ( - charWidth = 7 - charHeight = 8 - textColumns = 40 - textLines = 24 - textPage1Address = uint16(0x0400) - textPage2Address = uint16(0x0800) - graphWidth = 280 - graphHeight = 192 - graphPage1Address = uint16(0x2000) - graphPage2Address = uint16(0x4000) + charWidth = 7 + charHeight = 8 + textColumns = 40 + textLines = 24 + textLinesMix = 4 + textPage1Address = uint16(0x0400) + textPage2Address = uint16(0x0800) ) func getTextCharOffset(col int, line int) uint16 { @@ -37,22 +34,23 @@ func getTextChar(a *Apple2, col int, line int, page int) uint8 { return a.mmu.internalPeek(address) } -func snapshotTextMode(a *Apple2, page int) *image.RGBA { - // Color for typical Apple ][ period green phosphor monitors - // See: https://superuser.com/questions/361297/what-colour-is-the-dark-green-on-old-fashioned-green-screen-computer-displays - p1GreenPhosphorColor := color.RGBA{65, 255, 0, 255} - +func snapshotTextMode(a *Apple2, page int, mixMode bool, light color.Color) *image.RGBA { // Flash mode is 2Hz isFlashedFrame := time.Now().Nanosecond() > (1 * 1000 * 1000 * 1000 / 2) + lineStart := 0 + if mixMode { + lineStart = textLines - textLinesMix + } + width := textColumns * charWidth - height := textLines * charHeight + height := (textLines - lineStart) * charHeight size := image.Rect(0, 0, width, height) img := image.NewRGBA(size) for x := 0; x < width; x++ { for y := 0; y < height; y++ { - line := y / charHeight + line := y/charHeight + lineStart col := x / charWidth rowInChar := y % charHeight colInChar := x % charWidth @@ -65,7 +63,7 @@ func snapshotTextMode(a *Apple2, page int) *image.RGBA { pixel = pixel != (isInverse || (isFlash && isFlashedFrame)) var colour color.Color if pixel { - colour = p1GreenPhosphorColor + colour = light } else { colour = color.Black }