rewind

package
v0.30.0 Latest Latest
Warning

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

Go to latest
Published: Apr 17, 2024 License: GPL-3.0 Imports: 11 Imported by: 0

Documentation

Overview

Package rewind coordinates the periodic snapshotting of the emulation state. A previously seen frame can be returned to with the GotoFrame() function. If the requested frame is not in the history then the nearest frame that is will be used. The GotoLast() function will move the emulation to the last frame, whatever that might be.

The frequency at which snapshots are made is definable. Frames that are in between the snapshots can still be plumbed in, the rewind package handling the interleaving by running the emulation for the missing period.

In fact, the emulation is run even when the rewind package is set to snapshot every frame (a frequency of one) in order to generate the image data (storing the image data is memory wasteful). For this to work, the Rewind type is initialised with a reference to to the Runner interface. Implementations of the Runner interface should loop until frame, scanline, clock are matched (or the nearest point, depending on use case).

Regular emulation loops (ie. not catch-up loop of the Runner interface) must call RecordFrameState() after every CPU instruction to catch frame boundaries as early as possible. The rewind package will take the snapshot when it notices a new frame has started.

The RecordExecutionState() function can be called to force a snapshot to be taken at any time. This should probably only ever be used when the emulation is paused. The rewind package will delete an execution snapshot when the next snapshot is taken (meaning that there is only ever one execution state in the history at any one time and that it will be at the end).

Snapshots are stored in frame order from the splice point. The splice point will be wherever the snapshot history has been rewound to. For example, in a history of length 100 frames: the emulation has rewound back to frame 50. When the emulation is resumed, snapshots will be added at this point. The previous history of frames 51 to 100 will be lost.

Reset and Boundary snapshots are special splice points that only ever occur once and at the beginning of the history. Reset occurs only when the Reset() function is called and is intended to be called whenver the VCS is power cycled (not the reset switch).

The Boundary snapshot occurs when history has been cleared for some other reason. This was added to better support PlusROM cartridges and to ensure that network events are not replayed. The rewind package will add the boundary snapshot (to an empty history) automatically whenever the RewindBoundary() function from the attached cartridge returns true.

One of the weaknesses of the rewind package currently is the absence of any input replay. This might be particularly noticeable with large snapshot frequencies. Future versions of the package will record and replay input.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Plumb added in v0.15.0

func Plumb(vcs *hardware.VCS, state *State, fromDifferentEmulation bool)

Plumb state into VCS. The fromDifferentEmulation indicates that the State has been created by a different VCS instance than the one being plumbed into.

Types

type ComparisonState added in v0.24.0

type ComparisonState struct {
	State  *State
	Locked bool
}

ComparisonState is returned by GetComparisonState()

type Emulation added in v0.19.3

type Emulation interface {
	Mode() govern.Mode
	State() govern.State
	VCS() *hardware.VCS
}

Emulation defines as much of the emulation we require access to.

type PokeHook added in v0.10.1

type PokeHook func(res *State) error

type Preferences

type Preferences struct {

	// whether to apply the high mirror bits to the displayed address
	MaxEntries prefs.Int
	Freq       prefs.Int
	// contains filtered or unexported fields
}

func (*Preferences) Load

func (p *Preferences) Load() error

Load disassembly preferences and apply to the current disassembly.

func (*Preferences) Save

func (p *Preferences) Save() error

Save current disassembly preferences to disk.

func (*Preferences) SetDefaults added in v0.16.0

func (p *Preferences) SetDefaults()

SetDefaults reverts all settings to default values.

func (*Preferences) String

func (p *Preferences) String() string

type Rewind

type Rewind struct {

	// prefs for the rewind system
	Prefs *Preferences
	// contains filtered or unexported fields
}

Rewind contains a history of machine states for the emulation.

func NewRewind

func NewRewind(emulation Emulation, runner Runner) (*Rewind, error)

NewRewind is the preferred method of initialisation for the Rewind type.

func (*Rewind) AddTimelineCounter added in v0.15.0

func (r *Rewind) AddTimelineCounter(ctr TimelineCounter)

AddTimelineCounter to the rewind system. Augments Timeline information that would otherwisde be awkward to gather.

Only one timeline counter can be used at any one time (ie. subsequent calls to AddTimelineCounter() will override previous calls.)

func (*Rewind) GetComparisonState added in v0.15.0

func (r *Rewind) GetComparisonState() ComparisonState

GetComparisonState gets a reference to current comparison point. This is not a copy of the state but the actual state. Also returns the

func (*Rewind) GetCurrentState added in v0.10.1

func (r *Rewind) GetCurrentState() *State

GetCurrentState returns a temporary snapshot of the current state.

func (*Rewind) GetState added in v0.15.0

func (r *Rewind) GetState(frame int) *State

GetState returns a copy for the nearest state for the indicated frame.

func (*Rewind) GetTimeline added in v0.15.0

func (r *Rewind) GetTimeline() Timeline

GetTimeline returns a copy of the current Timeline. Checks integrity of the timeline and will cause the program to panic if it is insane.

func (*Rewind) GotoCoords added in v0.15.0

func (r *Rewind) GotoCoords(toCoords coords.TelevisionCoords) error

GotoCoords moves emulation to specified frame/scanline/clock "coordinates".

func (*Rewind) GotoFrame

func (r *Rewind) GotoFrame(frame int) error

GotoFrame is a special case of GotoCoords that requires the frame number only.

func (*Rewind) GotoLast

func (r *Rewind) GotoLast() error

GotoLast goes to the last entry in the rewind history. It handles situations when the last entry is an execution state.

func (*Rewind) LockComparison added in v0.24.0

func (r *Rewind) LockComparison(locked bool)

LockComparison stops the comparison point from being updated

func (*Rewind) NewFrame

func (r *Rewind) NewFrame(frameInfo television.FrameInfo) error

NewFrame is in an implementation of television.FrameTrigger.

func (*Rewind) Peephole added in v0.23.1

func (r *Rewind) Peephole() string

Peephole outputs a short summary of the state of the rewind system centered on the current splice value

func (*Rewind) RecordExecutionCoords added in v0.15.0

func (r *Rewind) RecordExecutionCoords()

RecordExecutionCoords records the coordinates of the current execution state.

func (*Rewind) RecordState added in v0.15.0

func (r *Rewind) RecordState()

RecordState should be called after every CPU instruction. A new state will be recorded if the current rewind policy agrees.

func (*Rewind) RerunLastNFrames added in v0.15.0

func (r *Rewind) RerunLastNFrames(frames int) error

RerunLastNFrames runs the emulation from the a point N frames in the past to the current state.

func (*Rewind) Reset

func (r *Rewind) Reset()

Reset rewind system removes all entries and takes a snapshot of the execution state. Resets timeline too.

This should be called whenever a new cartridge is attached to the emulation.

func (*Rewind) RunPoke added in v0.15.0

func (r *Rewind) RunPoke(from *State, to *State, poke PokeHook) error

RunPoke will the run the VCS from one state to another state applying the supplied PokeHook to the from State

func (*Rewind) SearchMemoryWrite added in v0.10.1

func (r *Rewind) SearchMemoryWrite(tgt *State, addr uint16, value uint8, valueMask uint8) (*State, error)

SearchMemoryWrite runs an emulation between two states looking for the instance when the address is written to with the value (valueMask is applied to mask specific bits)

The supplied target state is the upper limit of the search. The lower limit of the search is one frame before the target State.

The supplied address will be normalised.

Returns the most recent State at which the memory write was found. If a more recent address write is found but not the correct value, then no state is returned.

func (*Rewind) SearchRegisterWrite added in v0.10.1

func (r *Rewind) SearchRegisterWrite(tgt *State, reg rune, value uint8, valueMask uint8) (*State, error)

SearchMemoryWrite runs an emulation between two states looking for the instance when the register is written to with the value (valueMask is applied to mask specific bits)

The supplied target state is the upper limit of the search. The lower limit of the search is one frame before the target State.

Returns the most recent State at which the register write was found. If a more recent register write is found but not the correct value, then no state is returned.

func (*Rewind) SetComparison

func (r *Rewind) SetComparison(frame int)

SetComparison points comparison to the supplied state

func (*Rewind) String

func (r *Rewind) String() string

String outputs the entry information for the entire rewind history. The Peephole() funcion is probably a better option.

func (*Rewind) UpdateComparison added in v0.24.0

func (r *Rewind) UpdateComparison()

UpdateComparison points comparison to the current state

type Runner

type Runner interface {
	// CatchupLoop should loop until the frame/scanline/clock coordinates are
	// met. f should be called periodically, ideally every video cycle.
	//
	// When implementating the CatchupLoop(), care should be takan about what
	// to do for example, if the scaline/clock coordinates do no exist on the
	// specified frame. Either stop when the frame becomes too large or don't
	// request the rewind in the first place. Such details are outside the
	// scope of the rewind package however.
	CatchUpLoop(coords.TelevisionCoords) error
}

Runner provides the rewind package the opportunity to run the emulation.

type State

type State struct {
	VCS *hardware.State
	TV  *television.State
	// contains filtered or unexported fields
}

State contains pointers to areas of the VCS emulation. They can be read for reference.

func (*State) String

func (s *State) String() string

type Timeline added in v0.15.0

type Timeline struct {
	FrameNum       []int
	TotalScanlines []int
	Counts         []TimelineCounts
	Ratios         []TimelineRatios

	// peripheral input (including the panel). entry is true if the peripheral
	// was "active" at the end of a frame
	LeftPlayerInput  []bool
	RightPlayerInput []bool
	PanelInput       []bool

	// These two "available" fields state the earliest and latest frames that
	// are available in the rewind history.
	//
	// The earliest information in the Timeline array fields may be different.
	AvailableStart int
	AvailableEnd   int
}

Timeline provides a summary of the current state of the rewind system.

Useful for GUIs for example, to present the range of frame numbers that are available in the rewind history.

type TimelineCounter added in v0.15.0

type TimelineCounter interface {
	TimelineCounts() TimelineCounts
}

TimelineCounter implementations provide system information for the timeline that would otherwise be awkward to collate.

Implementations should reset counts in time for the next call to TimelineCounts().

type TimelineCounts added in v0.15.0

type TimelineCounts struct {
	WSYNC  int
	CoProc int
}

TimelineCounts is returned by a TimelineCounter implementation. The value should be updated every *video* cycle. Users can divide by three to get the color-clock count.

type TimelineRatios added in v0.15.0

type TimelineRatios struct {
	WSYNC  float32
	CoProc float32
}

Jump to

Keyboard shortcuts

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