mirror of
https://github.com/JetSetIlly/Gopher2600.git
synced 2024-05-20 13:48:02 -04:00
96ad0797b4
this helps force the environment.Label to be set to something meaningful
90 lines
2.8 KiB
Go
90 lines
2.8 KiB
Go
// This file is part of Gopher2600.
|
|
//
|
|
// Gopher2600 is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// Gopher2600 is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Gopher2600. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
package tracker
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/jetsetilly/gopher2600/debugger/govern"
|
|
"github.com/jetsetilly/gopher2600/environment"
|
|
"github.com/jetsetilly/gopher2600/hardware"
|
|
"github.com/jetsetilly/gopher2600/hardware/television"
|
|
"github.com/jetsetilly/gopher2600/logger"
|
|
"github.com/jetsetilly/gopher2600/rewind"
|
|
)
|
|
|
|
const replayLabel = environment.Label("tracker_replay")
|
|
|
|
// create replay emulation if it has not been created already
|
|
func (tr *Tracker) createReplayEmulation(mixer television.AudioMixer) error {
|
|
if tr.replayEmulation != nil {
|
|
return nil
|
|
}
|
|
|
|
tv, err := television.NewTelevision("AUTO")
|
|
if err != nil {
|
|
return fmt.Errorf("tracker: create replay emulation: %w", err)
|
|
}
|
|
tv.AddAudioMixer(mixer)
|
|
|
|
tr.replayEmulation, err = hardware.NewVCS(replayLabel, tv, nil, nil)
|
|
if err != nil {
|
|
return fmt.Errorf("tracker: create replay emulation: %w", err)
|
|
}
|
|
tr.replayEmulation.TIA.Audio.SetTracker(tr)
|
|
|
|
return nil
|
|
}
|
|
|
|
// Replay audio from start to end indexes
|
|
//
|
|
// The onEnd argument is a function to run when the replay has concluded
|
|
func (tr *Tracker) Replay(start int, end int, mixer television.AudioMixer, onEnd func()) {
|
|
// the replay will run even if the master emulation is running. this may
|
|
// cause audible issues with the hardware audio mixing
|
|
|
|
tr.createReplayEmulation(mixer)
|
|
|
|
tr.crit.section.Lock()
|
|
defer tr.crit.section.Unlock()
|
|
|
|
startState := tr.rewind.GetState(tr.crit.Entries[start].Coords.Frame)
|
|
if startState == nil {
|
|
logger.Logf(logger.Allow, "tracker", "replay: can't find rewind state for frame %d", tr.crit.Entries[start].Coords.Frame)
|
|
return
|
|
}
|
|
|
|
rewind.Plumb(tr.replayEmulation, startState, true)
|
|
|
|
// get copy of end frame number so that we don't have to acquire the
|
|
// criticial section in the replay emulation
|
|
endFrame := tr.crit.Entries[end].Coords.Frame
|
|
|
|
go func() {
|
|
defer onEnd()
|
|
|
|
err := tr.replayEmulation.Run(func() (govern.State, error) {
|
|
if tr.replayEmulation.TV.GetCoords().Frame > endFrame {
|
|
return govern.Ending, nil
|
|
}
|
|
return govern.Running, nil
|
|
})
|
|
if err != nil {
|
|
logger.Logf(logger.Allow, "tracker", "replay: %s", err.Error())
|
|
}
|
|
}()
|
|
}
|