television

package
v0.3.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 4, 2020 License: GPL-3.0, GPL-3.0 Imports: 5 Imported by: 0

Documentation

Overview

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.

Note that the television implementation no longer attempts to report the same frame/scanline/horizpos information as Stella. Early versions of the implementation did because it facilitated A/B testing but since we're now confident that the TIA emulation is correct the need to keep in "sync" with Stella is no longer required.

The reference implementation also handles framerate limiting according to the current TV specification (ie. PAL or NTSC) or an aribitrary value, using the SetFPSCap() function.

Framesize adaptation is also handled by the reference implementation and is currently functional but rudimentary.

Index

Constants

View Source
const (
	HorizClksHBlank   = 68
	HorizClksVisible  = 160
	HorizClksScanline = 228
)

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 specifications. Vertical information should be accessed via SpecNTSC or SpecPAL.

Variables

View Source
var PaletteNTSC = []color.RGBA{}

PaletteNTSC is the collection of NTSC colours

View Source
var PalettePAL = []color.RGBA{}

PalettePAL is the collection of PAL colours

View Source
var SpecificationList = []string{"NTSC", "PAL"}

SpecificationList is the list of specifications that the television may adopt

Functions

This section is empty.

Types

type AudioMixer

type AudioMixer interface {
	SetAudio(audioData uint8) error

	// some mixers may need to conclude and/or dispose of resources gently.
	// for simplicity, the AudioMixer should be considered unusable after
	// EndMixing() has been called
	EndMixing() error
}

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 ColorSignal

type ColorSignal int

ColorSignal represents the signal that is sent from the VCS to the

const VideoBlack ColorSignal = -1

VideoBlack is the PixelSignal value that indicates no VCS pixel is to be shown

type FrameResizeID added in v0.3.1

type FrameResizeID string

FrameResizeID identifies the resizing method

const (
	FrameResizerNone   FrameResizeID = "FrameResizerNone"
	FrameResizerSimple FrameResizeID = "FrameResizerSimple"
)

List of valid values for FrameResizeID

type PixelRenderer

type PixelRenderer interface {
	// Resize is called when the television implementation detects that extra
	// scanlines are required in the display.
	//
	// It may be called when television specification has changed. As a point
	// of convenience a reference to the currently selected specification is
	// provided. However, renderers should call GetSpec() rather than keeping a
	// private pointer to the specification, if knowledge of the spec is
	// required after the Resize() event.
	//
	// Renderers should use the values sent by the Resize() function, rather
	// than the equivalent values in the specification. Unless of course, the
	// renderer is intended to be strict about specification accuracy.
	//
	// Renderers should make sure that any data structures that depend on the
	// specification being used are still adequate.
	Resize(spec *Specification, topScanline, visibleScanlines int) error

	// NewFrame and NewScanline are called at the start of the frame/scanline
	NewFrame(frameNum int, isStable bool) error
	NewScanline(scanline int) error

	// setPixel() is called every cycle regardless of the state of VBLANK and
	// HBLANK.
	//
	// things to consider:
	//
	// o the x argument is measured from zero so renderers should decide how to
	//	handle pixels of during the HBLANK (x < ClocksPerHBLANK)
	//
	// o the y argument is also measured from zero but because VBLANK can be
	//	turned on at any time there's no easy test. the VBLANK flag is sent to
	//	help renderers decide what to do.
	//
	// o for renderers that are producing an accurate visual image, the pixel
	//	should always be set to video black if VBLANK is on.
	//
	//	some renderers however, may find it useful to set the pixel to the RGB
	//	value regardless of VBLANK. for example, DigestTV does this.
	//
	//	a vey important note is that some ROMs use VBLANK to control pixel
	//	color within the visible display area. ROMs affected:
	//
	//	* Custer's Revenge
	//	* Ladybug
	//	* ET (turns VBLANK off late on scanline 40)
	//
	SetPixel(x, y int, red, green, blue byte, vblank bool) error

	// some renderers may need to conclude and/or dispose of resources gently.
	// for simplicity, the PixelRenderer should be considered unusable after
	// EndRendering() has been called
	EndRendering() error
}

PixelRenderer implementations displays, or otherwise works with, visual information from a television. For example digest.Video.

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 {
	television.Television
	...
}

type SignalAttributes

type SignalAttributes struct {
	VSync     bool
	VBlank    bool
	CBurst    bool
	HSync     bool
	Pixel     ColorSignal
	AudioData uint8

	// which equates to 30Khz
	AudioUpdate bool
}

SignalAttributes represents the data sent to the television

func (SignalAttributes) String added in v0.2.1

func (a SignalAttributes) String() string

type Specification

type Specification struct {
	ID     string
	Colors []color.RGBA

	// the number of scanlines the 2600 Programmer's guide recommends for the
	// top/bottom parts of the screen:
	//
	// "A typical frame will consists of 3 vertical sync (VSYNC) lines*, 37 vertical
	// blank (VBLANK) lines, 192 TV picture lines, and 30 overscan lines. Atari’s
	// research has shown that this pattern will work on all types of TV sets."
	//
	// the above figures are in reference to the NTSC protocol
	ScanlinesVSync int

	ScanlinesVisible  int
	ScanlinesOverscan int

	// the total number of scanlines for the entire frame is the sum of the
	// four individual portions
	ScanlinesTotal int

	// the scanline at which the VBLANK should be turned off (Top) and
	// turned back on again (Bottom). the period between the top and bottom
	// scanline is the visible portion of the screen.
	//
	// in practice, the VCS can turn VBLANK on and off at any time; what the
	// two values below represent what "Atari's research" has shown to be safe.
	// by definition this means that:
	//
	//	Top = VSync + Vblank
	//
	//	Bottom = Top + Visible
	//
	// or
	//
	//	Bottom = Total - Overscan
	ScanlineTop    int
	ScanlineBottom int

	// AaspectBias transforms the scaling factor for the X axis.
	// values taken from Stella emualtor. useful for A/B testing
	AspectBias float32

	// the number of frames per second required by the specification
	FramesPerSecond float32
	// contains filtered or unexported fields
}

Specification is used to define the two television specifications

var SpecNTSC *Specification

SpecNTSC is the specification for NTSC television types

var SpecPAL *Specification

SpecPAL is the specification for PAL television types

type StateReq

type StateReq int

StateReq is used to identify which television attribute is being asked with the GetState() function

const (
	ReqFramenum StateReq = iota
	ReqScanline
	ReqHorizPos
)

List of valid state requests

type Television

type Television interface {
	String() string

	// Reset the television to an initial state
	Reset() error

	// AddPixelRenderer registers an (additional) implementation of PixelRenderer
	AddPixelRenderer(PixelRenderer)

	// AddAudioMixer registers an (additional) implementation of AudioMixer
	AddAudioMixer(AudioMixer)

	Signal(SignalAttributes) error

	// Returns the value of the requested state. eg. the current scanline.
	GetState(StateReq) (int, error)

	// Set the television's specification
	SetSpec(spec string) error

	// Returns the television's current specification. Renderers should use
	// GetSpec() rather than keeping a private pointer to the specification.
	GetSpec() (*Specification, bool)

	// IsStable returns true if the television thinks the image being sent by
	// the VCS is stable
	IsStable() bool

	// some televisions may need to conclude and/or dispose of resources
	// gently. implementations of End() should call EndRendering() and
	// EndMixing() on each PixelRenderer and AudioMixer that has been added.
	//
	// for simplicity, the Television should be considered unusable
	// after EndRendering() has been called
	End() error

	// SpecIDOnCreation() returns the string that was to ID the television
	// type/spec on creation. because the actual spec can change, the ID field
	// of the Specification type can not be used for things like regression
	// test recreation etc.
	//
	// we use this to help recreate the television that was used to make a
	// playback recording. we may need to expand on this (and maybe replace
	// with a more generalised function) if we ever add another television
	// implementation.
	SpecIDOnCreation() string

	// Set whether the emulation should wait for FPS limiter
	SetFPSCap(set bool)

	// Request the number frames per second. This overrides the frame rate of
	// the specification. A negative FPS value restores the specifcications
	// frame rate.
	//
	// Note that this is only a request, the emulation may not be able to
	// achieve that rate.
	SetFPS(fps float32)

	// The requested number of frames per second. Compare with GetActualFPS()
	// to check for accuracy
	GetReqFPS() float32

	// The current number of frames per second
	GetActualFPS() float32

	// Returns a copy of SignalAttributes for reference
	GetLastSignal() SignalAttributes
}

Television defines the operations that can be performed on the conceptual television. Note that the television implementation itself does not present any information, either visually or sonically. Instead, PixelRenderers and AudioMixers are added to perform those tasks.

func NewTelevision

func NewTelevision(spec string) (Television, error)

NewTelevision creates a new instance of the television type, satisfying the Television interface.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL