From 08b1a94dcd8a50bfcd9e256c74910010888a6056 Mon Sep 17 00:00:00 2001 From: JetSetIlly Date: Mon, 9 Sep 2024 19:50:42 +0100 Subject: [PATCH] simplified RunForFrameCount() --- hardware/run.go | 32 +++++++++++++++++-------------- hardware/television/television.go | 4 ++++ preview/preview.go | 2 +- regression/log.go | 3 ++- regression/video.go | 3 ++- 5 files changed, 27 insertions(+), 17 deletions(-) diff --git a/hardware/run.go b/hardware/run.go index 87cfb67a0..beee6b61f 100644 --- a/hardware/run.go +++ b/hardware/run.go @@ -100,32 +100,36 @@ func (vcs *VCS) Run(continueCheck func() (govern.State, error)) error { // RunForFrameCount sets emulator running for the specified number of frames. // Useful for FPS and regression tests. Not used by the debugger because traps // (and volatile traps) are more flexible. -func (vcs *VCS) RunForFrameCount(numFrames int, continueCheck func(frame int) (govern.State, error)) error { +// +// continueCheck can be used to instruct the emulation to end before the +// specified number of frames has elapsed. +func (vcs *VCS) RunForFrameCount(numFrames int, continueCheck func() (govern.State, error)) error { if continueCheck == nil { - continueCheck = func(frame int) (govern.State, error) { return govern.Running, nil } + continueCheck = func() (govern.State, error) { return govern.Running, nil } } - frameNum := vcs.TV.GetCoords().Frame - targetFrame := frameNum + numFrames + targetFrame := vcs.TV.GetCoords().Frame + numFrames state := govern.Running - for frameNum != targetFrame && state != govern.Ending { + for state != govern.Ending { // check if CPU has been killed. emulation will run forever if we don't // check for this if vcs.CPU.Killed { return nil } - err := vcs.Step(nil) - if err != nil { - return err - } - - frameNum = vcs.TV.GetCoords().Frame + if vcs.TV.IsFrameNum(targetFrame) { + state = govern.Ending + } else { + err := vcs.Step(nil) + if err != nil { + return err + } - state, err = continueCheck(frameNum) - if err != nil { - return err + state, err = continueCheck() + if err != nil { + return err + } } } diff --git a/hardware/television/television.go b/hardware/television/television.go index ff60e6d1a..9889b476d 100644 --- a/hardware/television/television.go +++ b/hardware/television/television.go @@ -1063,6 +1063,10 @@ func (tv *Television) GetCoords() coords.TelevisionCoords { return tv.state.GetCoords() } +func (tv *Television) IsFrameNum(frame int) bool { + return tv.state.frameNum == frame +} + // SetRotation instructs the television to a different orientation. In truth, // the television just forwards the request to the pixel renderers. func (tv *Television) SetRotation(rotation specification.Rotation) { diff --git a/preview/preview.go b/preview/preview.go index a1f8000d9..0803519f1 100644 --- a/preview/preview.go +++ b/preview/preview.go @@ -63,7 +63,7 @@ func (em *Emulation) RunN(loader cartridgeloader.Loader, N int) error { return fmt.Errorf("preview: %w", err) } - err = em.vcs.RunForFrameCount(N, func(_ int) (govern.State, error) { + err = em.vcs.RunForFrameCount(N, func() (govern.State, error) { select { case <-timeout: return govern.Ending, nil diff --git a/regression/log.go b/regression/log.go index fa65f3e5c..7706c4d43 100644 --- a/regression/log.go +++ b/regression/log.go @@ -165,7 +165,7 @@ func (reg *LogRegression) regress(newRegression bool, output io.Writer, msg stri logOutput := &strings.Builder{} // run emulation - err = vcs.RunForFrameCount(reg.NumFrames, func(frame int) (govern.State, error) { + err = vcs.RunForFrameCount(reg.NumFrames, func() (govern.State, error) { // if the CPU is in the KIL state then the test will never end normally if vcs.CPU.Killed { return govern.Ending, fmt.Errorf("CPU in KIL state") @@ -174,6 +174,7 @@ func (reg *LogRegression) regress(newRegression bool, output io.Writer, msg stri // display progress meter every 1 second select { case <-tck.C: + frame := vcs.TV.GetCoords().Frame output.Write([]byte(fmt.Sprintf("\r%s [%d/%d (%.1f%%)]", msg, frame, reg.NumFrames, 100*(float64(frame)/float64(reg.NumFrames))))) default: } diff --git a/regression/video.go b/regression/video.go index 487673f63..d6a1373c3 100644 --- a/regression/video.go +++ b/regression/video.go @@ -239,7 +239,7 @@ func (reg *VideoRegression) regress(newRegression bool, output io.Writer, msg st tck := time.NewTicker(dur) // run emulation - err = vcs.RunForFrameCount(reg.NumFrames, func(frame int) (govern.State, error) { + err = vcs.RunForFrameCount(reg.NumFrames, func() (govern.State, error) { // if the CPU is in the KIL state then the test will never end normally if vcs.CPU.Killed { return govern.Ending, fmt.Errorf("CPU in KIL state") @@ -248,6 +248,7 @@ func (reg *VideoRegression) regress(newRegression bool, output io.Writer, msg st // display progress meter every 1 second select { case <-tck.C: + frame := vcs.TV.GetCoords().Frame output.Write([]byte(fmt.Sprintf("\r%s [%d/%d (%.1f%%)]", msg, frame, reg.NumFrames, 100*(float64(frame)/float64(reg.NumFrames))))) default: }