diff --git a/bots/chess/videochess.go b/bots/chess/videochess.go index 9f1d25efd..8e7cde049 100644 --- a/bots/chess/videochess.go +++ b/bots/chess/videochess.go @@ -131,9 +131,10 @@ func (obs *observer) SetPixels(sig []signal.SignalAttributes, last int) error { var offset int for i := range sig { - // handle VBLANK by setting pixels to black - if sig[i].VBlank { - col = color.RGBA{R: 0, G: 0, B: 0} + // handle VBLANK by setting pixels to black. we also manually handle + // NoSignal in the same way + if sig[i].VBlank || sig[i].Index == signal.NoSignal { + col = obs.frameInfo.Spec.GetColor(signal.VideoBlack) } else { col = obs.frameInfo.Spec.GetColor(sig[i].Color) } diff --git a/bots/spacejockey/spacejockey.go b/bots/spacejockey/spacejockey.go index 815ede508..de44e51be 100644 --- a/bots/spacejockey/spacejockey.go +++ b/bots/spacejockey/spacejockey.go @@ -100,9 +100,10 @@ func (obs *observer) SetPixels(sig []signal.SignalAttributes, last int) error { var offset int for i := range sig { - // handle VBLANK by setting pixels to black - if sig[i].VBlank { - col = color.RGBA{R: 0, G: 0, B: 0} + // handle VBLANK by setting pixels to black. we also manually handle + // NoSignal in the same way + if sig[i].VBlank || sig[i].Index == signal.NoSignal { + col = obs.frameInfo.Spec.GetColor(signal.VideoBlack) } else { col = obs.frameInfo.Spec.GetColor(sig[i].Color) } diff --git a/comparison/comparison.go b/comparison/comparison.go index 8ff76824a..dbaa2a2b7 100644 --- a/comparison/comparison.go +++ b/comparison/comparison.go @@ -353,9 +353,10 @@ func (cmp *Comparison) SetPixels(sig []signal.SignalAttributes, last int) error var offset int for i := range sig { - // handle VBLANK by setting pixels to black - if sig[i].VBlank { - col = color.RGBA{R: 0, G: 0, B: 0} + // handle VBLANK by setting pixels to black. we also manually handle + // NoSignal in the same way + if sig[i].VBlank || sig[i].Index == signal.NoSignal { + col = cmp.frameInfo.Spec.GetColor(signal.VideoBlack) } else { col = cmp.frameInfo.Spec.GetColor(sig[i].Color) } diff --git a/comparison/driver.go b/comparison/driver.go index d75571808..9cda8865d 100644 --- a/comparison/driver.go +++ b/comparison/driver.go @@ -109,9 +109,10 @@ func (drv *driver) SetPixels(sig []signal.SignalAttributes, last int) error { } for i := range sig { - // handle VBLANK by setting pixels to black - if sig[i].VBlank { - col = color.RGBA{R: 0, G: 0, B: 0} + // handle VBLANK by setting pixels to black. we also manually handle + // NoSignal in the same way + if sig[i].VBlank || sig[i].Index == signal.NoSignal { + col = drv.frameInfo.Spec.GetColor(signal.VideoBlack) } else { col = drv.frameInfo.Spec.GetColor(sig[i].Color) } diff --git a/digest/video.go b/digest/video.go index f3b9fc424..9a3b1529d 100644 --- a/digest/video.go +++ b/digest/video.go @@ -18,6 +18,7 @@ package digest import ( "crypto/sha1" "fmt" + "image/color" "github.com/jetsetilly/gopher2600/hardware/television" "github.com/jetsetilly/gopher2600/hardware/television/signal" @@ -108,13 +109,18 @@ func (dig *Video) SetPixels(sig []signal.SignalAttributes, _ int) error { offset := len(dig.digest) for _, s := range sig { - // ignore invalid signals + // ignore invalid signals. this has a consequence that shrunken screen + // sizes will have pixel values left over from previous frames. but for + // the purposes of the digest this is okay if s.Index == signal.NoSignal { continue } - // ignore VBLANK and extract the color signal in all situations - col := dig.spec.GetColor(s.Color) + var col color.RGBA + + // signal processing is unlike other SetPixel() implementations in that + // we set the underlying color even if VBLANK is set + col = dig.spec.GetColor(s.Color) // setting every pixel regardless of vblank value p := dig.pixels[offset : offset+3 : offset+3] diff --git a/gui/sdlimgui/screen.go b/gui/sdlimgui/screen.go index 13999ceca..3a1fd2d00 100644 --- a/gui/sdlimgui/screen.go +++ b/gui/sdlimgui/screen.go @@ -488,9 +488,10 @@ func (scr *screen) SetPixels(sig []signal.SignalAttributes, last int) error { return nil } - // handle VBLANK by setting pixels to black - if sig[i].VBlank { - col = color.RGBA{R: 0, G: 0, B: 0} + // handle VBLANK by setting pixels to black. we also manually handle + // NoSignal in the same way + if sig[i].VBlank || sig[i].Index == signal.NoSignal { + col = scr.crit.frameInfo.Spec.GetColor(signal.VideoBlack) } else { col = scr.crit.frameInfo.Spec.GetColor(sig[i].Color) } diff --git a/hardware/television/protocol.go b/hardware/television/protocol.go index 8f2a88f36..dfd1fccb5 100644 --- a/hardware/television/protocol.go +++ b/hardware/television/protocol.go @@ -61,17 +61,9 @@ type PixelRenderer interface { // Every signal from SetPixels() therefore corresponds to a pixel in the // bitmap - the first entry always referes to the top-left pixel // - // Setting the color of a pixel can be done by extracting the ColorSignal - // from the SignalAttributes (see signal package) - // - // The last parameter indicates the index of the array entry that was most - // recently set. This is useful to know when showing televison images when - // the emulation is paused. All entries upto and including last are from - // teh *current* frame. All entries afterwards are from the *previous* - // frame - // - // If the entry contains signal.NoSignal then that screen pixel has not - // been written to recently + // If the entry contains signal.NoSignal then that screen pixel has not been + // written to recently. However, the bitmap may still need to be updated + // with "nil" information if the size of the screen has reduced // // For renderers that are producing an accurate visual image, the pixel // should always be set to video black if VBLANK is on. Some renderers diff --git a/hardware/television/signal/signal.go b/hardware/television/signal/signal.go index c9cfeb047..4c6e5f9ae 100644 --- a/hardware/television/signal/signal.go +++ b/hardware/television/signal/signal.go @@ -30,7 +30,10 @@ const VideoBlack ColorSignal = 0xff // Index value to indicate that the signal is invalid const NoSignal = -1 -// SignalAttributes represents the data sent to the television. +// SignalAttributes represents the data sent to the television +// +// When reset the Index field should be set to NoSignal and the Color field +// should be set to VideoBlack type SignalAttributes struct { Index int VSync bool diff --git a/hardware/television/television.go b/hardware/television/television.go index e5e3f5c68..7a9c6ad2a 100644 --- a/hardware/television/television.go +++ b/hardware/television/television.go @@ -844,6 +844,7 @@ func (tv *Television) newFrame() error { // the entire entry tv.signals[i] = signal.SignalAttributes{ Index: signal.NoSignal, + Color: signal.VideoBlack, } } diff --git a/thumbnailer/anim.go b/thumbnailer/anim.go index b58c21655..37a519e56 100644 --- a/thumbnailer/anim.go +++ b/thumbnailer/anim.go @@ -317,8 +317,6 @@ func (thmb *Anim) NewScanline(scanline int) error { // SetPixels implements the television.PixelRenderer interface func (thmb *Anim) SetPixels(sig []signal.SignalAttributes, last int) error { - var col color.RGBA - // this adhoc "monitor" system looks for changes in pixels and uses that // information to insert input into the emulation var monitorChanges bool @@ -328,10 +326,12 @@ func (thmb *Anim) SetPixels(sig []signal.SignalAttributes, last int) error { var offset int for i := range sig { + var col color.RGBA - // handle VBLANK by setting pixels to black - if sig[i].VBlank { - col = color.RGBA{R: 0, G: 0, B: 0} + // handle VBLANK by setting pixels to black. we also manually handle + // NoSignal in the same way + if sig[i].VBlank || sig[i].Index == signal.NoSignal { + col = thmb.frameInfo.Spec.GetColor(signal.VideoBlack) } else { col = thmb.frameInfo.Spec.GetColor(sig[i].Color) } diff --git a/thumbnailer/image.go b/thumbnailer/image.go index 4871f8e18..de80e1d53 100644 --- a/thumbnailer/image.go +++ b/thumbnailer/image.go @@ -206,13 +206,14 @@ func (thmb *Image) NewScanline(scanline int) error { // SetPixels implements the television.PixelRenderer interface func (thmb *Image) SetPixels(sig []signal.SignalAttributes, last int) error { - var col color.RGBA var offset int - for i := range sig { - // handle VBLANK by setting pixels to black - if sig[i].VBlank { - col = color.RGBA{R: 0, G: 0, B: 0} + var col color.RGBA + + // handle VBLANK by setting pixels to black. we also manually handle + // NoSignal in the same way + if sig[i].VBlank || sig[i].Index == signal.NoSignal { + col = thmb.frameInfo.Spec.GetColor(signal.VideoBlack) } else { col = thmb.frameInfo.Spec.GetColor(sig[i].Color) }