From d764ece7407559e5b51f6d2dd632a3d843bd0764 Mon Sep 17 00:00:00 2001 From: steve Date: Wed, 11 Dec 2019 09:58:56 +0000 Subject: [PATCH] o television - commentary and documentation - added DebugColorSignal type o tia/video - changes due to addition of DebugColorSignal --- hardware/tia/step.go | 2 +- hardware/tia/video/video.go | 5 +++-- television/color.go | 17 +++++++++-------- television/doc.go | 23 +++++++++++++++++++++++ television/protocol.go | 27 ++++++++++----------------- television/specifications.go | 5 ++++- television/television.go | 4 ++-- 7 files changed, 52 insertions(+), 31 deletions(-) create mode 100644 television/doc.go diff --git a/hardware/tia/step.go b/hardware/tia/step.go index 5361537f..a71bdb89 100644 --- a/hardware/tia/step.go +++ b/hardware/tia/step.go @@ -187,7 +187,7 @@ func (tia *TIA) Step(serviceMemory bool) (bool, error) { // resolve video pixels. note that we always send the debug color // regardless of hblank pixelColor, debugColor := tia.Video.Pixel() - tia.sig.AltPixel = television.ColorSignal(debugColor) + tia.sig.AltPixel = debugColor if tia.hblank { // if hblank is on then we don't sent the resolved color but the video // black signal instead diff --git a/hardware/tia/video/video.go b/hardware/tia/video/video.go index 1379a1c9..ebcf8bf2 100644 --- a/hardware/tia/video/video.go +++ b/hardware/tia/video/video.go @@ -112,7 +112,7 @@ func (vd *Video) PrepareSpritesForHMOVE() { // Pixel returns the color of the pixel at the current clock and also sets the // collision registers. it will default to returning the background color if no // sprite or playfield pixel is present. -func (vd *Video) Pixel() (uint8, uint8) { +func (vd *Video) Pixel() (uint8, television.DebugColorSignal) { bgc := vd.Playfield.backgroundColor pfu, pfc := vd.Playfield.pixel() p0u, p0c := vd.Player0.pixel() @@ -211,7 +211,8 @@ func (vd *Video) Pixel() (uint8, uint8) { // priorties priority := vd.Playfield.priority || (vd.Playfield.scoremode && vd.Playfield.region == regionLeft) - var col, dcol uint8 + var col uint8 + var dcol television.DebugColorSignal if priority { if pfu { // priority 1 diff --git a/television/color.go b/television/color.go index b7b82398..e176fd30 100644 --- a/television/color.go +++ b/television/color.go @@ -78,10 +78,15 @@ var colorsAltRaw = []uint32{ 0x333333, 0x84c8fc, 0x9246c0, 0x901c00, 0xe8e84a, 0xd5824a, 0x328432, } -// as used in Stella, the colors above are used as below. note that using a -// alt pixel ColorSignal not in the following list may result in a panic +// DebugColorSignal is used by the debugging feature of the television (if +// available). Each signal sent to the televsoin should specify a +// DebugColorSignal, indicating from which video element the pixel was +// generated. +type DebugColorSignal uint16 + +// List of valid DebugColorSignals const ( - AltColBackground = iota + AltColBackground DebugColorSignal = iota AltColBall AltColPlayfield AltColPlayer0 @@ -120,11 +125,7 @@ func getColor(spec *Specification, sig ColorSignal) (byte, byte, byte) { } // getColor translates a color signal to the individual color components -func getAltColor(sig ColorSignal) (byte, byte, byte) { - if sig == VideoBlack { - return videoBlack[red], videoBlack[green], videoBlack[blue] - } - +func getAltColor(sig DebugColorSignal) (byte, byte, byte) { if int(sig) >= len(colorsAlt) { panic("alt color signal too big") } diff --git a/television/doc.go b/television/doc.go new file mode 100644 index 00000000..81f5f6d4 --- /dev/null +++ b/television/doc.go @@ -0,0 +1,23 @@ +// Package television implements the output device of the emulated VCS. The +// television interface is used wherever a television needs to be connected. +// The NewTelevision() function creates a new instance of a reference +// implementation of the Television interface. In truth, it is probably the +// only implementation required but the option is there for alternatives. +// +// It is common for instances of television to be embedded in other type +// structure, thereby extending the "features" of the television and allowing +// the extended type to be used wherever the Television interface is required. +// The digest package is a good example of this idea. +// +// It is important to note that the reference television implementation does +// not render pixels or mix sound itself. Instead, the television interface +// exposes two functions, AddPixelRenderer() and AddAudioMixer(). These can be +// used to add as many renderers and mixers as required. +// +// The main means of communication is the Signal() function. This function +// accepts an instance of SignalAttributes which gives details of how the +// television should be behaving. The SignalAttributes type is meant to emulate +// the electrical signal between the VCS and the television but some +// concessions have been made for easement. The HSyncSimple in particular is a +// large piece of fudge but a necessary one. +package television diff --git a/television/protocol.go b/television/protocol.go index 5672460f..caefc267 100644 --- a/television/protocol.go +++ b/television/protocol.go @@ -38,26 +38,17 @@ type Television interface { End() error } -// PixelRenderer implementations displays, or otherwise works with, visal -// information from a television +// PixelRenderer implementations displays, or otherwise works with, visual +// information from a television. For example digest.Video. // -// examples of renderers that display visual information: -// * SDLPlay -// * ImageTV -// -// examples of renderers that do not display visual information but only work -// with it: -// * DigestTV -// -// PixelRenderer implementations find it convenient to maintain a reference to +// PixelRenderer implementations often find it convenient to maintain a reference to // the parent Television implementation and maybe even embed the Television // interface. ie. // -// type ExampleTV struct { +// type ExampleTV struct { // television.Television -// // ... -// } +// } type PixelRenderer interface { // Resize is called when the television implementation detects that extra // scanlines are required in the display. @@ -111,7 +102,9 @@ type PixelRenderer interface { EndRendering() error } -// AudioMixer implementations work with sound; most probably playing it. +// AudioMixer implementations work with sound; most probably playing it. An +// example of an AudioMixer that does not play sound but otherwise works with +// it is the digest.Audio type. type AudioMixer interface { SetAudio(audioData uint8) error FlushAudio() error @@ -134,7 +127,7 @@ type SignalAttributes struct { // AltPixel allows the emulator to set an alternative color for each pixel // - used to signal the debug color in addition to the regular color // - arguable that this be sent as some sort of meta-signal - AltPixel ColorSignal + AltPixel DebugColorSignal // the HSyncSimple attribute is not part of the real TV spec. The signal // for a real flyback is the HSync signal (held for 8 color clocks). @@ -162,7 +155,7 @@ type SignalAttributes struct { // with the GetState() function type StateReq int -// list of valid state requests +// List of valid state requests const ( ReqFramenum StateReq = iota ReqScanline diff --git a/television/specifications.go b/television/specifications.go index 46873dd1..c93f64c1 100644 --- a/television/specifications.go +++ b/television/specifications.go @@ -52,13 +52,16 @@ type Specification struct { AspectBias float32 } +// From the Stella Programmer's Guide: +// // "Each scan lines starts with 68 clock counts of horizontal blank (not seen on // the TV screen) followed by 160 clock counts to fully scan one line of TV // picture. When the electron beam reaches the end of a scan line, it returns // to the left side of the screen, waits for the 68 horizontal blank clock // counts, and proceeds to draw the next line below." // -// Horizontal clock counts are the same for both TV specificationst +// Horizontal clock counts are the same for both TV specifications. Vertical +// information should be accessed via SpecNTSC or SpecPAL. const ( HorizClksHBlank = 68 HorizClksVisible = 160 diff --git a/television/television.go b/television/television.go index 87a1afce..da161da3 100644 --- a/television/television.go +++ b/television/television.go @@ -69,8 +69,8 @@ type television struct { // before we accept the frame characteristics const stabilityThreshold = 5 -// NewTelevision creates a new instance of StellaTelevision for a -// minimalist implementation of a televsion for the VCS emulation +// NewTelevision creates a new instance of the television type, satisfying the +// Television interface. func NewTelevision(tvType string) (Television, error) { tv := &television{}