Gopher2600/hardware/snapshot.go
JetSetIlly 58315e5182 added VCS.Snapshot() function. simplifies the rewind package
also allows easy access to the VCS snapshot process when there is no
need to use the rewind package
2024-02-05 11:41:17 +00:00

85 lines
2.7 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 hardware
import (
"github.com/jetsetilly/gopher2600/hardware/cpu"
"github.com/jetsetilly/gopher2600/hardware/memory"
"github.com/jetsetilly/gopher2600/hardware/riot"
"github.com/jetsetilly/gopher2600/hardware/tia"
)
// State stores the VCS sub-systems. It is produced by the Snapshot() function
// and can be restored with the Plumb() function
//
// Note in particular that the TV is not part of the snapshot process
type State struct {
CPU *cpu.CPU
Mem *memory.Memory
RIOT *riot.RIOT
TIA *tia.TIA
}
// Snapshot creates a copy of a previously snapshotted VCS State
func (s *State) Snapshot() *State {
return &State{
CPU: s.CPU.Snapshot(),
Mem: s.Mem.Snapshot(),
RIOT: s.RIOT.Snapshot(),
TIA: s.TIA.Snapshot(),
}
}
// Snapshot the state of the VCS sub-systems
func (vcs *VCS) Snapshot() *State {
return &State{
CPU: vcs.CPU.Snapshot(),
Mem: vcs.Mem.Snapshot(),
RIOT: vcs.RIOT.Snapshot(),
TIA: vcs.TIA.Snapshot(),
}
}
// Plumb a previously snapshotted system
//
// The fromDifferentEmulation indicates that the State has been created by a
// different VCS emulation than the one being plumbed into
func (vcs *VCS) Plumb(state *State, fromDifferentEmulation bool) {
if state == nil {
panic("vcs: cannot plumb in a nil state")
}
// take another snapshot of the state before plumbing. we don't want the
// machine to change what we have stored in our state array (we learned
// that lesson the hard way :-)
vcs.CPU = state.CPU.Snapshot()
vcs.Mem = state.Mem.Snapshot()
vcs.RIOT = state.RIOT.Snapshot()
vcs.TIA = state.TIA.Snapshot()
vcs.CPU.Plumb(vcs.Env, vcs.Mem)
vcs.Mem.Plumb(vcs.Env, fromDifferentEmulation)
vcs.RIOT.Plumb(vcs.Env, vcs.Mem.RIOT, vcs.Mem.TIA)
vcs.TIA.Plumb(vcs.Env, vcs.TV, vcs.Mem.TIA, vcs.RIOT.Ports, vcs.CPU)
// reset peripherals after new state has been plumbed. without this,
// controllers can feel odd if the newly plumbed state has left RIOT memory
// in a latched state
vcs.RIOT.Ports.ResetPeripherals()
vcs.Input.Plumb(vcs.TV, vcs.RIOT.Ports)
}