Documentation ¶
Overview ¶
Package video implements pixel generation for the emulated TIA. Pixel generation is conceptually divided into six areas, implemented as types. These are:
Playfield Player 0 and Player 1 Missile 0 and Missile 1 Ball
Collectively we can refer to these as the playfield and sprites (even though the VCS sprites are nothing like what we now think of sprites, it is a useful appellation none-the-less).
The video subsystem is ticked along with the TIA every video cycle. The playfield is closely related to the TIA's HSYNC and is not ticked separately. The sprites are ticked depending on the state of the TIA's HBLANK signal; it also depends on whether HMOVE has been recently latched in the TIA and whether the sprite has completed any horizontal movement. For this reason the video sub-system and the sprites are initialised with references to the HBLANK signal and the HMOVE latch.
Reading of TIA memory is divided into six different Update*() functions. The timing of when TIA memory is read and registers updated is important and dividing the update functions in this manner helps. The TIA package handles these timings.
The three sprite categories, player, missile and ball, all have common features but have been implemented to be completely separate from one another. The exception is the enclockifier type used by both missiles and the ball.
All sprites keep track of their own phase clocks and position counters. Delayed side effects only occur when the sprite itself is ticked and so each sprite also has an instance of Ticker from the future package.
A significant difference to the description in Andrew Towers' document, "Atari 2600 TIA Hardware Notes", is how HMOVE counters are handled. In Towers' description of the hardware, the HMOVE latch, the counters and the signal line to the sprite are all intertwined. In the emulation this is almost turned inside out with the sprite maintaining its own counter and ticking (include HMOVE stuffing ticks) only when required.
Somewhere during the cycle the video sub-system will decide on what the pixel output should be (in this context we mean VCS clock-wide pixels). That is, we're deciding what the colour of all TV pixels for the duration of the video cycle should be.
The timing of this decision is critical: it must happen before some register updates but after others. Note that the pixel color decision is distinct from sending the color signal to the TV (which is handled by the TIA) package). Sending of the color signal always happens at the very end of the video cycle.
To effectively make the pixel color decision, the video sub-system at the same time processes the pixel "priority". For convenience, pixel collisions are also set at this time.
Index ¶
- Variables
- type ScreenRegion
- type Video
- func (vd *Video) Pixel() (uint8, colors.AltColor)
- func (vd *Video) PrepareSpritesForHMOVE()
- func (vd *Video) RSYNC(adjustment int)
- func (vd *Video) Tick(visible, hmove bool, hmoveCt uint8)
- func (vd *Video) UpdateCTRLPF()
- func (vd *Video) UpdateColor(data bus.ChipData) bool
- func (vd *Video) UpdateNUSIZ(num int, fromMissile bool)
- func (vd *Video) UpdatePlayfield(tiaDelay future.Scheduler, data bus.ChipData) bool
- func (vd *Video) UpdateSpriteHMOVE(tiaDelay future.Scheduler, data bus.ChipData) bool
- func (vd *Video) UpdateSpritePixels(data bus.ChipData) bool
- func (vd *Video) UpdateSpritePositioning(data bus.ChipData) bool
- func (vd *Video) UpdateSpriteVariations(data bus.ChipData) bool
Constants ¶
This section is empty.
Variables ¶
var BallSizes = []string{
"single size",
"double size",
"quad size",
"double-quad size",
}
BallSizes maps ball size values to descriptions of those sizes
var MissileCopies = []string{
"one copy",
"two copies [close]",
"two copies [med]",
"three copies [close]",
"two copies [wide]",
"one copy",
"three copies [med]",
"one copy",
}
MissileCopies maps missile copies values to descriptions of those values
var MissileSizes = []string{
"single width",
"double width",
"quadruple width",
"doub-quad width",
}
MissileSizes maps missile sizes values to descriptions of those values
var PlayerSizes = []string{
"one copy",
"two copies [close]",
"two copies [med]",
"three copies [close]",
"two copies [wide]",
"double size",
"three copies [med]",
"quad size",
}
PlayerSizes maps player size and copies values to descriptions of those values
Functions ¶
This section is empty.
Types ¶
type ScreenRegion ¶
type ScreenRegion int
ScreenRegion notes which part of the screen is currently being drawn
const ( RegionOffScreen ScreenRegion = iota RegionLeft RegionRight )
List of valid ScreenRegions
type Video ¶
type Video struct { // playfield Playfield *playfield // sprite objects Player0 *playerSprite Player1 *playerSprite Missile0 *missileSprite Missile1 *missileSprite Ball *ballSprite // contains filtered or unexported fields }
Video contains all the components of the video sub-system of the VCS TIA chip
func NewVideo ¶
func NewVideo(mem bus.ChipBus, pclk *phaseclock.PhaseClock, hsync *polycounter.Polycounter, tv television.Television, hblank, hmoveLatch *bool) (*Video, error)
NewVideo is the preferred method of initialisation for the Video structure.
The playfield type requires access access to the TIA's phaseclock and polyucounter and is used to decide which part of the playfield is to be drawn.
The sprites meanwhile require access to the television. This is for generating information about the sprites reset position - a debugging only requirement but of minimal performance related consequeunce.
The references to the TIA's HBLANK state and whether HMOVE is latched, are required to tune the delays experienced by the various sprite events (eg. reset position).
func (*Video) Pixel ¶
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 (*Video) PrepareSpritesForHMOVE ¶
func (vd *Video) PrepareSpritesForHMOVE()
PrepareSpritesForHMOVE should be called whenever HMOVE is triggered
func (*Video) RSYNC ¶
RSYNC adjusts the debugging information of the sprites when an RSYNC is triggered
func (*Video) Tick ¶
Tick moves all video elements forward one video cycle. This is the conceptual equivalent of the hardware MOTCK line.
func (*Video) UpdateCTRLPF ¶
func (vd *Video) UpdateCTRLPF()
UpdateCTRLPF should be called whenever any of the individual components of the CTRPF are altered. For example, if Playfield.Reflected is altered, then this function should be called so that the CTRLPF value is set to reflect the alteration.
This is only of use to debuggers. It's never required in normal operation of the emulator.
func (*Video) UpdateColor ¶
UpdateColor checks TIA memory for changes to color registers.
Returns true if memory.ChipData has not been serviced.
func (*Video) UpdateNUSIZ ¶
UpdateNUSIZ should be called whenever the player/missile size/copies information is altered. This function updates the NUSIZ value to reflect the changes whilst maintaining the other NUSIZ bits.
This is only of use to debuggers. It's never required in normal operation of the emulator.
func (*Video) UpdatePlayfield ¶
UpdatePlayfield checks TIA memory for new playfield data. Note that CTRLPF is serviced in UpdateSpriteVariations().
Returns true if ChipData has *not* been serviced.
func (*Video) UpdateSpriteHMOVE ¶
UpdateSpriteHMOVE checks TIA memory for changes in sprite HMOVE settings.
Returns true if ChipData has *not* been serviced.
func (*Video) UpdateSpritePixels ¶
UpdateSpritePixels checks TIA memory for attribute changes that *must* occur after a call to Pixel().
Returns true if memory.ChipData has not been serviced.
func (*Video) UpdateSpritePositioning ¶
UpdateSpritePositioning checks TIA memory for strobing of reset registers.
Returns true if memory.ChipData has not been serviced.
func (*Video) UpdateSpriteVariations ¶
UpdateSpriteVariations checks TIA memory for writes to registers that affect how sprite pixels are output. Note that CTRLPF is serviced here rather than in UpdatePlayfield(), because it affects the ball sprite.
Returns true if memory.ChipData has not been serviced.