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/clock 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
- type AudioMixer
- type FrameTrigger
- type PauseTrigger
- type PixelRenderer
- type State
- type Television
- func (tv *Television) AddAudioMixer(m AudioMixer)
- func (tv *Television) AddFrameTrigger(f FrameTrigger)
- func (tv *Television) AddPauseTrigger(p PauseTrigger)
- func (tv *Television) AddPixelRenderer(r PixelRenderer)
- func (tv *Television) AttachVCS(vcs VCSReturnChannel)
- func (tv *Television) End() error
- func (tv *Television) GetActualFPS() float32
- func (tv *Television) GetLastSignal() signal.SignalAttributes
- func (tv *Television) GetReqFPS() float32
- func (tv *Television) GetReqSpecID() string
- func (tv *Television) GetSpec() specification.Spec
- func (tv *Television) GetState(request signal.StateReq) int
- func (tv *Television) InstructionBoundary()
- func (tv *Television) IsStable() bool
- func (tv *Television) Pause(pause bool) error
- func (tv *Television) PauseRendering(pause bool)
- func (tv *Television) PlumbState(vcs VCSReturnChannel, s *State)
- func (tv *Television) ReqAdjust(request signal.StateAdj, adjustment int, reset bool) (int, int, int, error)
- func (tv *Television) Reset(keepFrameNum bool) error
- func (tv *Television) SetFPS(fps float32)
- func (tv *Television) SetFPSCap(limit bool) bool
- func (tv *Television) SetSpec(spec string) error
- func (tv *Television) Signal(sig signal.SignalAttributes) error
- func (tv *Television) Snapshot() *State
- func (tv *Television) String() string
- type VCSReturnChannel
Constants ¶
const MaxScanlinesAbsolute = 400
the maximum number of scanlines allowed by the television implementation.
const MaxSignalHistory = specification.ClksScanline * MaxScanlinesAbsolute
the number of entries in signal history.
const (
ThreshVisual float32 = 3.0
)
there's no science behind when we flip from scales these values are based simply on what looks effective and what seems to be useable.
Variables ¶
This section is empty.
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 // Reset buffered audio and anything else that might need doing on, for // example, a cartridge change. Reset() }
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 FrameTrigger ¶
FrameTrigger implementations listen for NewFrame events. FrameTrigger is a subset of PixelRenderer.
type PauseTrigger ¶ added in v0.10.1
FrameTrigger implementations listen for Pause events.
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. // // Renderers must be prepared to resize to either a smaller of larger size. Resize(spec specification.Spec, topScanline, bottomScanline int) error // NewFrame and NewScanline are called at the start of the frame/scanline NewFrame(isStable bool) error NewScanline(scanline int) error // Mark the start and end of an update event from the television. // SetPixel() should only be called between calls of UpdatingPixels(true) // and UpdatingPixels(false) UpdatingPixels(updating bool) // SetPixel sends an instance of SignalAttributes to the Renderer. The // current flag states that this pixel should be considered to be the most // recent outputted by the television for this frame. In most instances, // this will always be true. // // things to consider: // // o the x argument is measured from zero so renderers should decide how to // handle pixels of during the HBLANK (x < ClksHBlank) // // 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(sig signal.SignalAttributes, current bool) error // Reset all pixels. Called when TV is reset. Reset() // 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 State ¶
type State struct {
// contains filtered or unexported fields
}
State encapsulates the television values that can change from moment to moment. Used by the rewind system when recording the current television state.
func (*State) GetState ¶
Returns state information. Not that ReqClock counts from "-specifcation.ClksHblank" and not zero as you might expect.
type Television ¶
type Television struct {
// contains filtered or unexported fields
}
Television is a Television implementation of the Television interface. In all honesty, it's most likely the only implementation required.
func NewTelevision ¶
func NewTelevision(spec string) (*Television, error)
NewReference creates a new instance of the reference television type, satisfying the Television interface.
func (*Television) AddAudioMixer ¶
func (tv *Television) AddAudioMixer(m AudioMixer)
AddAudioMixer registers an implementation of AudioMixer. Multiple implemntations can be added.
func (*Television) AddFrameTrigger ¶
func (tv *Television) AddFrameTrigger(f FrameTrigger)
AddFrameTrigger registers an implementation of FrameTrigger. Multiple implemntations can be added.
func (*Television) AddPauseTrigger ¶ added in v0.10.1
func (tv *Television) AddPauseTrigger(p PauseTrigger)
AddPauseTrigger registers an implementation of PauseTrigger.
func (*Television) AddPixelRenderer ¶
func (tv *Television) AddPixelRenderer(r PixelRenderer)
AddPixelRenderer registers an implementation of PixelRenderer. Multiple implemntations can be added.
func (*Television) AttachVCS ¶ added in v0.8.0
func (tv *Television) AttachVCS(vcs VCSReturnChannel)
AttachVCS attaches an implementation of the VCSReturnChannel.
func (*Television) End ¶
func (tv *Television) End() error
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.
func (*Television) GetActualFPS ¶
func (tv *Television) GetActualFPS() float32
The current number of frames per second. Note that FPS measurement still works even when frame capping is disabled.
IS goroutine safe.
func (*Television) GetLastSignal ¶
func (tv *Television) GetLastSignal() signal.SignalAttributes
Returns a copy of SignalAttributes for reference.
func (*Television) GetReqFPS ¶
func (tv *Television) GetReqFPS() float32
The requested number of frames per second. Compare with GetActualFPS() to check for accuracy.
IS goroutine safe.
func (*Television) GetReqSpecID ¶
func (tv *Television) GetReqSpecID() string
GetReqSpecID returns the specification that was requested on creation.
func (*Television) GetSpec ¶
func (tv *Television) GetSpec() specification.Spec
Returns the television's current specification. Renderers should use GetSpec() rather than keeping a private pointer to the specification.
func (*Television) GetState ¶
func (tv *Television) GetState(request signal.StateReq) int
Returns state information.
func (*Television) InstructionBoundary ¶ added in v0.10.1
func (tv *Television) InstructionBoundary()
InstructionBoudary implements the cpu.BoundaryTrigger interface.
func (*Television) IsStable ¶
func (tv *Television) IsStable() bool
IsStable returns true if the television thinks the image being sent by the VCS is stable.
func (*Television) Pause ¶
func (tv *Television) Pause(pause bool) error
Pause indicates that emulation has been paused. All unpushed pixels will be pushed to immeditately. Not the same as PauseRendering(). Pause() should be used when emulation is stopped. In this case, paused rendering is implied.
func (*Television) PauseRendering ¶ added in v0.8.0
func (tv *Television) PauseRendering(pause bool)
PauseRendering halts all forwarding to attached pixel renderers. Not the same as Pause(). PauseRendering() should be used when emulation is running but no rendering is to take place.
func (*Television) PlumbState ¶ added in v0.8.0
func (tv *Television) PlumbState(vcs VCSReturnChannel, s *State)
PlumbState attaches an existing television state.
func (*Television) ReqAdjust ¶ added in v0.10.1
func (tv *Television) ReqAdjust(request signal.StateAdj, adjustment int, reset bool) (int, int, int, error)
ReqAdjust requests the frame, scanline and clock values where the requested StateReq has been adjusted by the specified value. All values will be adjusted as required.
The reset argument instructs the function to return values that have been reset to zero as appropriate. So when request is ReqFramenum, the scanline and clock values will be zero; when request is ReqScanline, the clock value will be zero. It has no affect when request is ReqClock.
In the case of a StateAdj of AdjCPUCycle the only allowed adjustment value is -1. Any other value will return an error.
func (*Television) Reset ¶
func (tv *Television) Reset(keepFrameNum bool) error
Reset the television to an initial state.
func (*Television) SetFPS ¶
func (tv *Television) SetFPS(fps float32)
Request the number frames per second. This overrides the frame rate of the specification. A negative value restores the spec's frame rate.
func (*Television) SetFPSCap ¶
func (tv *Television) SetFPSCap(limit bool) bool
SetFPSCap whether the emulation should wait for FPS limiter. Returns the setting as it was previously.
func (*Television) SetSpec ¶
func (tv *Television) SetSpec(spec string) error
Set the television's specification.
func (*Television) Signal ¶
func (tv *Television) Signal(sig signal.SignalAttributes) error
Signal updates the current state of the television.
func (*Television) Snapshot ¶
func (tv *Television) Snapshot() *State
Snapshot makes a copy of the television state.
func (*Television) String ¶
func (tv *Television) String() string
type VCSReturnChannel ¶ added in v0.8.0
VCSReturnChannel is used to send information from the TV back to the parent console. Named because I think of it as being similar to the Audio Return Channel (ARC) present in modern TVs.
Directories ¶
Path | Synopsis |
---|---|
Package signal exposes the interface between the VCS and the television implementation.
|
Package signal exposes the interface between the VCS and the television implementation. |
Package specification contains the definitions, including colour, of the PAL and NTSC television protocols supported by the emulation.
|
Package specification contains the definitions, including colour, of the PAL and NTSC television protocols supported by the emulation. |