removed emulation package. moved types to debugger/govern package

the emulation package has been unecessary since the amalgamation of the
debugger and play modes. in order to allow switching between the two
modes it was necessary to remove the playmode package and to move all
playmode loops and other considerations into the debugger package. as a
result the abstraction offered by the emulation package is uncessary
This commit is contained in:
JetSetIlly 2022-08-27 22:14:58 +01:00
parent faddd7dfb9
commit 28ffedbf11
49 changed files with 384 additions and 485 deletions

View file

@ -24,7 +24,7 @@ import (
"github.com/jetsetilly/gopher2600/cartridgeloader"
"github.com/jetsetilly/gopher2600/curated"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/hardware"
"github.com/jetsetilly/gopher2600/hardware/instance"
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/mapper"
@ -207,14 +207,14 @@ func (cmp *Comparison) CreateFromLoader(cartload cartridgeloader.Loader) error {
return
}
err = cmp.VCS.Run(func() (emulation.State, error) {
err = cmp.VCS.Run(func() (govern.State, error) {
select {
case <-cmp.emulationQuit:
return emulation.Ending, nil
return govern.Ending, nil
default:
}
return emulation.Running, nil
return govern.Running, nil
})
if err != nil {
cmp.driver.quit <- err

View file

@ -27,12 +27,12 @@ import (
"github.com/jetsetilly/gopher2600/coprocessor/developer"
"github.com/jetsetilly/gopher2600/curated"
"github.com/jetsetilly/gopher2600/debugger/dbgmem"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/debugger/script"
"github.com/jetsetilly/gopher2600/debugger/terminal"
"github.com/jetsetilly/gopher2600/debugger/terminal/commandline"
"github.com/jetsetilly/gopher2600/disassembly"
"github.com/jetsetilly/gopher2600/disassembly/symbols"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/gui"
"github.com/jetsetilly/gopher2600/hardware/cpu/registers"
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/plusrom"
@ -266,7 +266,7 @@ func (dbg *Debugger) processTokens(tokens *commandline.Tokens) error {
coords = dbg.vcs.TV.AdjCoords(adj, adjAmount)
}
dbg.setState(emulation.Rewinding)
dbg.setState(govern.Rewinding)
dbg.unwindLoop(func() error {
// update catchupQuantum before starting rewind process
dbg.catchupQuantum = dbg.stepQuantum
@ -380,13 +380,13 @@ func (dbg *Debugger) processTokens(tokens *commandline.Tokens) error {
dbg.runUntilHalt = false
if arg == "LAST" {
dbg.setState(emulation.Rewinding)
dbg.setState(govern.Rewinding)
dbg.unwindLoop(dbg.Rewind.GotoLast)
} else if arg == "SUMMARY" {
dbg.printLine(terminal.StyleInstrument, dbg.Rewind.String())
} else {
frame, _ := strconv.Atoi(arg)
dbg.setState(emulation.Rewinding)
dbg.setState(govern.Rewinding)
dbg.unwindLoop(func() error {
err := dbg.Rewind.GotoFrame(frame)
if err != nil {
@ -411,7 +411,7 @@ func (dbg *Debugger) processTokens(tokens *commandline.Tokens) error {
}
}
dbg.setState(emulation.Rewinding)
dbg.setState(govern.Rewinding)
dbg.unwindLoop(func() error {
err := dbg.Rewind.GotoCoords(coords)
if err != nil {

View file

@ -30,11 +30,11 @@ import (
coprocDisasm "github.com/jetsetilly/gopher2600/coprocessor/disassembly"
"github.com/jetsetilly/gopher2600/curated"
"github.com/jetsetilly/gopher2600/debugger/dbgmem"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/debugger/script"
"github.com/jetsetilly/gopher2600/debugger/terminal"
"github.com/jetsetilly/gopher2600/debugger/terminal/commandline"
"github.com/jetsetilly/gopher2600/disassembly"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/gui"
"github.com/jetsetilly/gopher2600/hardware"
"github.com/jetsetilly/gopher2600/hardware/cpu/execution"
@ -290,7 +290,7 @@ type Debugger struct {
// CreateUserInterface is used to initialise the user interface used by the
// emulation. It returns an instance of both the GUI and Terminal interfaces
// in the repsective packages.
type CreateUserInterface func(emulation.Emulation) (gui.GUI, terminal.Terminal, error)
type CreateUserInterface func(*Debugger) (gui.GUI, terminal.Terminal, error)
// NewDebugger creates and initialises everything required for a new debugging
// session.
@ -312,8 +312,8 @@ func NewDebugger(opts CommandLineOptions, create CreateUserInterface) (*Debugger
// emulator is starting in the "none" mode (the advangatge of this is that
// we get to set the underlying type of the atomic.Value early before
// anyone has a change to call State() or Mode() from another thread)
dbg.state.Store(emulation.EmulatorStart)
dbg.mode.Store(emulation.ModeNone)
dbg.state.Store(govern.EmulatorStart)
dbg.mode.Store(govern.ModeNone)
var err error
@ -449,17 +449,17 @@ func NewDebugger(opts CommandLineOptions, create CreateUserInterface) (*Debugger
}
// VCS implements the emulation.Emulation interface.
func (dbg *Debugger) VCS() emulation.VCS {
func (dbg *Debugger) VCS() *hardware.VCS {
return dbg.vcs
}
// TV implements the emulation.Emulation interface.
func (dbg *Debugger) TV() emulation.TV {
func (dbg *Debugger) TV() *television.Television {
return dbg.vcs.TV
}
// Debugger implements the emulation.Emulation interface.
func (dbg *Debugger) Debugger() emulation.Debugger {
func (dbg *Debugger) Debugger() *Debugger {
return dbg
}
@ -469,13 +469,13 @@ func (dbg *Debugger) UserInput() chan userinput.Event {
}
// State implements the emulation.Emulation interface.
func (dbg *Debugger) State() emulation.State {
return dbg.state.Load().(emulation.State)
func (dbg *Debugger) State() govern.State {
return dbg.state.Load().(govern.State)
}
// Mode implements the emulation.Emulation interface.
func (dbg *Debugger) Mode() emulation.Mode {
return dbg.mode.Load().(emulation.Mode)
func (dbg *Debugger) Mode() govern.Mode {
return dbg.mode.Load().(govern.Mode)
}
// set the emulation state
@ -484,7 +484,7 @@ func (dbg *Debugger) Mode() emulation.Mode {
// debugger.SetFeature(ReqSetPause) even from within the debugger package
// (SetFeature() puts the request on the RawEvent Queue meaning it will be
// inserted in the input loop correctly)
func (dbg *Debugger) setState(state emulation.State) {
func (dbg *Debugger) setState(state govern.State) {
dbg.setStateQuiet(state, false)
}
@ -493,8 +493,8 @@ func (dbg *Debugger) setState(state emulation.State) {
//
// * see setState() comment, although debugger.SetFeature(ReqSetPause) will
// always be "noisy"
func (dbg *Debugger) setStateQuiet(state emulation.State, quiet bool) {
if state == emulation.Rewinding {
func (dbg *Debugger) setStateQuiet(state govern.State, quiet bool) {
if state == govern.Rewinding {
dbg.vcs.Mem.Cart.BreakpointsDisable(true)
dbg.endPlayback()
dbg.endRecording()
@ -533,15 +533,15 @@ func (dbg *Debugger) setStateQuiet(state emulation.State, quiet bool) {
prevState := dbg.State()
dbg.state.Store(state)
if !quiet && dbg.Mode() == emulation.ModePlay {
if !quiet && dbg.Mode() == govern.ModePlay {
switch state {
case emulation.Initialising:
dbg.gui.SetFeature(gui.ReqEmulationEvent, emulation.EventInitialising)
case emulation.Paused:
dbg.gui.SetFeature(gui.ReqEmulationEvent, emulation.EventPause)
case emulation.Running:
if prevState > emulation.Initialising {
dbg.gui.SetFeature(gui.ReqEmulationEvent, emulation.EventRun)
case govern.Initialising:
dbg.gui.SetFeature(gui.ReqEmulationEvent, govern.EventInitialising)
case govern.Paused:
dbg.gui.SetFeature(gui.ReqEmulationEvent, govern.EventPause)
case govern.Running:
if prevState > govern.Initialising {
dbg.gui.SetFeature(gui.ReqEmulationEvent, govern.EventRun)
}
}
}
@ -552,7 +552,7 @@ func (dbg *Debugger) setStateQuiet(state emulation.State, quiet bool) {
// * consider using debugger.SetFeature(ReqSetMode) even from within the
// debugger package (SetFeature() puts the request on the RawEvent Queue
// meaning it will be inserted in the input loop correctly)
func (dbg *Debugger) setMode(mode emulation.Mode) error {
func (dbg *Debugger) setMode(mode govern.Mode) error {
if dbg.Mode() == mode {
return nil
}
@ -566,8 +566,8 @@ func (dbg *Debugger) setMode(mode emulation.Mode) error {
// however, because the user has asked to switch to playmode we should
// cause the debugger mode to run until the halting condition is matched
// (which we know will occur in the almost immediate future)
if mode == emulation.ModePlay && !dbg.halting.allowPlaymode() {
if dbg.Mode() == emulation.ModeDebugger {
if mode == govern.ModePlay && !dbg.halting.allowPlaymode() {
if dbg.Mode() == govern.ModeDebugger {
dbg.runUntilHalt = true
dbg.continueEmulation = true
}
@ -601,26 +601,26 @@ func (dbg *Debugger) setMode(mode emulation.Mode) error {
// screen.go)
switch dbg.Mode() {
case emulation.ModePlay:
case govern.ModePlay:
dbg.vcs.TV.AddFrameTrigger(dbg.Rewind)
dbg.vcs.TV.AddFrameTrigger(dbg.counter)
// simple detection of whether cartridge is ejected when switching to
// playmode. if it is ejected then open ROM selected.
if dbg.Mode() == emulation.ModePlay && dbg.vcs.Mem.Cart.IsEjected() {
if dbg.Mode() == govern.ModePlay && dbg.vcs.Mem.Cart.IsEjected() {
err = dbg.forceROMSelector()
if err != nil {
return curated.Errorf("debugger: %v", err)
}
} else {
dbg.setState(emulation.Running)
dbg.setState(govern.Running)
}
case emulation.ModeDebugger:
case govern.ModeDebugger:
dbg.vcs.TV.AddFrameTrigger(dbg.Rewind)
dbg.vcs.TV.AddFrameTrigger(dbg.ref)
dbg.vcs.TV.AddFrameTrigger(dbg.counter)
dbg.setState(emulation.Paused)
dbg.setState(govern.Paused)
// debugger needs knowledge about previous frames (via the reflector)
// if we're moving from playmode. also we want to make sure we end on
@ -630,7 +630,7 @@ func (dbg *Debugger) setMode(mode emulation.Mode) error {
// catchupEndAdj we will always enter the debugger on the last cycle of
// an instruction. although correct in terms of coordinates, is
// confusing.
if prevMode == emulation.ModePlay {
if prevMode == govern.ModePlay {
dbg.catchupEndAdj = true
dbg.RerunLastNFrames(2)
}
@ -692,7 +692,7 @@ func (dbg *Debugger) StartInDebugMode(filename string) error {
return curated.Errorf("debugger: %v", err)
}
err = dbg.setMode(emulation.ModeDebugger)
err = dbg.setMode(govern.ModeDebugger)
if err != nil {
return curated.Errorf("debugger: %v", err)
}
@ -808,7 +808,7 @@ func (dbg *Debugger) StartInPlayMode(filename string) error {
return curated.Errorf("debugger: %v", err)
}
err = dbg.setMode(emulation.ModePlay)
err = dbg.setMode(govern.ModePlay)
if err != nil {
return curated.Errorf("debugger: %v", err)
}
@ -842,7 +842,7 @@ func (dbg *Debugger) run() error {
// inputloop will continue until debugger is to be terminated
for dbg.running {
switch dbg.Mode() {
case emulation.ModePlay:
case govern.ModePlay:
err := dbg.playLoop()
if err != nil {
// if we ever encounter a cartridge ejected error in playmode
@ -856,14 +856,14 @@ func (dbg *Debugger) run() error {
return curated.Errorf("debugger: %v", err)
}
}
case emulation.ModeDebugger:
case govern.ModeDebugger:
switch dbg.State() {
case emulation.Running:
case govern.Running:
dbg.runUntilHalt = true
dbg.continueEmulation = true
case emulation.Paused:
case govern.Paused:
dbg.haltImmediately = true
case emulation.Rewinding:
case govern.Rewinding:
default:
return curated.Errorf("emulation state not supported on *start* of debugging loop: %s", dbg.State())
}
@ -880,7 +880,7 @@ func (dbg *Debugger) run() error {
return curated.Errorf("debugger: %v", err)
}
dbg.unwindLoopRestart = nil
} else if dbg.State() == emulation.Ending {
} else if dbg.State() == govern.Ending {
dbg.running = false
}
default:
@ -948,19 +948,19 @@ func (dbg *Debugger) attachCartridge(cartload cartridgeloader.Loader) (e error)
dbg.bots.Quit()
// attching a cartridge implies the initialise state
dbg.setState(emulation.Initialising)
dbg.setState(govern.Initialising)
// set state after initialisation according to the emulation mode
defer func() {
switch dbg.Mode() {
case emulation.ModeDebugger:
case govern.ModeDebugger:
if dbg.runUntilHalt && e == nil {
dbg.setState(emulation.Running)
dbg.setState(govern.Running)
} else {
dbg.setState(emulation.Paused)
dbg.setState(govern.Paused)
}
case emulation.ModePlay:
dbg.setState(emulation.Running)
case govern.ModePlay:
dbg.setState(govern.Running)
}
}()
@ -1224,12 +1224,12 @@ func (dbg *Debugger) endComparison() {
func (dbg *Debugger) hotload() (e error) {
// tell GUI that we're in the initialistion phase
dbg.setState(emulation.Initialising)
dbg.setState(govern.Initialising)
defer func() {
if dbg.runUntilHalt && e == nil {
dbg.setState(emulation.Running)
dbg.setState(govern.Running)
} else {
dbg.gui.SetFeature(gui.ReqEmulationEvent, emulation.EventPause)
dbg.gui.SetFeature(gui.ReqEmulationEvent, govern.EventPause)
}
}()

View file

@ -22,7 +22,6 @@ import (
"github.com/jetsetilly/gopher2600/debugger"
"github.com/jetsetilly/gopher2600/debugger/terminal"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/gui"
"github.com/jetsetilly/gopher2600/prefs"
)
@ -143,7 +142,7 @@ func TestDebugger_withNonExistantInitScript(t *testing.T) {
var trm *mockTerm
create := func(e emulation.Emulation) (gui.GUI, terminal.Terminal, error) {
create := func(dbg *debugger.Debugger) (gui.GUI, terminal.Terminal, error) {
trm = newMockTerm(t)
return &mockGUI{}, trm, nil
}
@ -166,7 +165,7 @@ func TestDebugger(t *testing.T) {
var trm *mockTerm
create := func(e emulation.Emulation) (gui.GUI, terminal.Terminal, error) {
create := func(dbg *debugger.Debugger) (gui.GUI, terminal.Terminal, error) {
trm = newMockTerm(t)
return &mockGUI{}, trm, nil
}

View file

@ -19,7 +19,7 @@ import (
"fmt"
"github.com/jetsetilly/gopher2600/curated"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/hardware/cpu/instructions"
"github.com/jetsetilly/gopher2600/hardware/cpu/registers"
"github.com/jetsetilly/gopher2600/hardware/memory"
@ -48,7 +48,7 @@ func (dbg *Debugger) PushDeepPoke(addr uint16, value uint8, newValue uint8, valu
}
dbg.PushRawEventImmediate(func() {
dbg.setStateQuiet(emulation.Rewinding, true)
dbg.setStateQuiet(govern.Rewinding, true)
dbg.unwindLoop(doDeepPoke)
})

View file

@ -13,14 +13,11 @@
// You should have received a copy of the GNU General Public License
// along with Gopher2600. If not, see <https://www.gnu.org/licenses/>.
// Package emulation is an abstraction of the various modes Gopher2600 can
// operate in, principally play-mode and the debugger.
// Package govern defines the types that define the current condition of the
// emulation. The three conditions are Mode, State and Event.
//
// It is useful when linking packages/types that require a *passive* knowledge
// of the emulation. For example, a GUI might want to know what the current
// state of the emulation is.
//
// Some package types might still need an active knowledge of the emulation
// however. In which case, simply relying on the Emulation interface is
// probably not enough.
package emulation
// Also defined is the method of requesting a state change from the GUI. Most
// often state change comes from the emulation but in some intances it is
// necessary to instruct the emulation to change mode or state - for example,
// from the GUI as a result of the a user request.
package govern

View file

@ -13,54 +13,10 @@
// You should have received a copy of the GNU General Public License
// along with Gopher2600. If not, see <https://www.gnu.org/licenses/>.
package emulation
package govern
import (
"github.com/jetsetilly/gopher2600/userinput"
)
// TV is a minimal abstraction of the TV hardware. Exists mainly to avoid a
// circular import to the hardware package.
//
// The only likely implementation of this interface is the
// television.Television type.
type TV interface {
}
// VCS is a minimal abstraction of the VCS hardware. Exists mainly to avoid a
// circular import to the hardware package.
//
// The only likely implementation of this interface is the hardware.VCS type.
type VCS interface {
}
// VCS is a minimal abstraction of the Gopher2600 debugger. Exists mainly to
// avoid a circular import to the debugger package.
//
// The only likely implementation of this interface is the debugger.Debugger
// type.
type Debugger interface {
}
// Emulation defines the public functions required for a GUI implementation
// (and possibly other things) to interface with the underlying emulator.
type Emulation interface {
TV() TV
VCS() VCS
Debugger() Debugger
UserInput() chan userinput.Event
// Send a request to set an emulation feature
SetFeature(request FeatureReq, args ...FeatureReqData) error
// Immediate request for the state and mode of the emulation
State() State
Mode() Mode
}
// Mode inidicates the broad features of the emulation. For example, Debugger
// indicates that the emulation is capable or is willing to handle debugging
// features.
// Mode inidicates the broad features of the emulation. Currently defined to be
// debugger and play.
type Mode int
func (m Mode) String() string {
@ -112,9 +68,9 @@ const (
Ending
)
// Event describes an event that might occur in the emulation which is outside
// of the scope of the VCS. For example, when the emulation is paused an
// EventPause can be sent to the GUI (see FeatureReq type in the gui package).
// Event is something that happens to change the state of the emulation. For
// example, the user presses the pause while playing game. This will cause the
// GUI to send an EventPause event to the emulation.
type Event int
// List of defined events.
@ -130,3 +86,30 @@ const (
EventMute
EventUnmute
)
// FeatureReq is used to request the setting of an emulation attribute
// eg. a pause request from the GUI
type FeatureReq string
// FeatureReqData represents the information associated with a FeatureReq. See
// commentary for the defined FeatureReq values for the underlying type.
type FeatureReqData interface{}
// List of valid feature requests. argument must be of the type specified or
// else the interface{} type conversion will fail and the application will
// probably crash.
//
// Note that, like the name suggests, these are requests, they may or may not
// be satisfied depending on other conditions in the GUI.
const (
// notify gui of the underlying emulation mode.
ReqSetPause FeatureReq = "ReqSetPause" // bool
// change emulation mode
ReqSetMode FeatureReq = "ReqSetMode" // emulation.Mode
)
// Sentinal error returned if emulation does no support requested feature.
const (
UnsupportedEmulationFeature = "unsupported emulation feature: %v"
)

View file

@ -16,7 +16,7 @@
package debugger
import (
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/hardware/television/coords"
)
@ -26,25 +26,25 @@ import (
// required for catchupLoop().
func (dbg *Debugger) CatchUpLoop(tgt coords.TelevisionCoords) error {
switch dbg.Mode() {
case emulation.ModePlay:
case govern.ModePlay:
fpscap := dbg.vcs.TV.SetFPSCap(false)
defer dbg.vcs.TV.SetFPSCap(fpscap)
dbg.vcs.Run(func() (emulation.State, error) {
dbg.vcs.Run(func() (govern.State, error) {
dbg.userInputHandler_catchUpLoop()
coords := dbg.vcs.TV.GetCoords()
if coords.Frame >= tgt.Frame {
return emulation.Ending, nil
return govern.Ending, nil
}
return emulation.Running, nil
return govern.Running, nil
})
case emulation.ModeDebugger:
case govern.ModeDebugger:
// turn off TV's fps frame limiter
fpsCap := dbg.vcs.TV.SetFPSCap(false)
// we've already set emulation state to emulation.Rewinding
// we've already set emulation state to govern.Rewinding
dbg.catchupContinue = func() bool {
newCoords := dbg.vcs.TV.GetCoords()
@ -69,7 +69,7 @@ func (dbg *Debugger) CatchUpLoop(tgt coords.TelevisionCoords) error {
dbg.vcs.TV.SetFPSCap(fpsCap)
dbg.catchupContinue = nil
dbg.catchupEnd = nil
dbg.setState(emulation.Paused)
dbg.setState(govern.Paused)
dbg.runUntilHalt = false
dbg.continueEmulation = dbg.catchupEndAdj
dbg.catchupEndAdj = false

View file

@ -19,9 +19,9 @@ import (
"io"
"github.com/jetsetilly/gopher2600/curated"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/debugger/script"
"github.com/jetsetilly/gopher2600/debugger/terminal"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/hardware/cpu"
"github.com/jetsetilly/gopher2600/logger"
)
@ -35,7 +35,7 @@ import (
// function is being called.
//
// note that the debugger state is not changed by this function. it is up to
// the caller of the function to set emulation.State appropriately.
// the caller of the function to set govern.State appropriately.
func (dbg *Debugger) unwindLoop(onRestart func() error) {
dbg.unwindLoopRestart = onRestart
}
@ -65,7 +65,7 @@ func (dbg *Debugger) catchupLoop(inputter terminal.Input) error {
if !dbg.vcs.CPU.LastResult.Final {
// if we're in the rewinding state then a new rewind event has
// started and we must return immediately so that it can continue
if dbg.State() == emulation.Rewinding {
if dbg.State() == govern.Rewinding {
return nil
}
@ -140,7 +140,7 @@ func (dbg *Debugger) inputLoop(inputter terminal.Input, isVideoStep bool) error
var err error
for dbg.running {
if dbg.Mode() != emulation.ModeDebugger {
if dbg.Mode() != govern.ModeDebugger {
return nil
}
@ -186,7 +186,7 @@ func (dbg *Debugger) inputLoop(inputter terminal.Input, isVideoStep bool) error
}
// emulation has been put into a different mode. exit loop immediately
if dbg.Mode() != emulation.ModeDebugger {
if dbg.Mode() != govern.ModeDebugger {
return nil
}
@ -278,7 +278,7 @@ func (dbg *Debugger) inputLoop(inputter terminal.Input, isVideoStep bool) error
}
// set pause emulation state
dbg.setState(emulation.Paused)
dbg.setState(govern.Paused)
// take note of current machine state if the emulation was in a running
// state and is halting just now
@ -324,7 +324,7 @@ func (dbg *Debugger) inputLoop(inputter terminal.Input, isVideoStep bool) error
}
// emulation has been put into a different mode. exit loop immediately
if dbg.Mode() != emulation.ModeDebugger {
if dbg.Mode() != govern.ModeDebugger {
return nil
}
@ -351,10 +351,10 @@ func (dbg *Debugger) inputLoop(inputter terminal.Input, isVideoStep bool) error
// stepping.
if dbg.halting.volatileTraps.isEmpty() {
if inputter.IsInteractive() {
dbg.setState(emulation.Running)
dbg.setState(govern.Running)
}
} else {
dbg.setState(emulation.Stepping)
dbg.setState(govern.Stepping)
}
// update comparison point before execution continues
@ -362,7 +362,7 @@ func (dbg *Debugger) inputLoop(inputter terminal.Input, isVideoStep bool) error
dbg.Rewind.SetComparison()
}
} else if inputter.IsInteractive() {
dbg.setState(emulation.Stepping)
dbg.setState(govern.Stepping)
}
}

View file

@ -17,8 +17,8 @@ package debugger
import (
"github.com/jetsetilly/gopher2600/curated"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/debugger/terminal"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/gui"
"github.com/jetsetilly/gopher2600/hardware"
"github.com/jetsetilly/gopher2600/userinput"
@ -65,7 +65,7 @@ func (dbg *Debugger) playLoop() error {
dbg.liveBankInfo = dbg.vcs.Mem.Cart.GetBank(dbg.vcs.CPU.PC.Address())
// run and handle events
return dbg.vcs.Run(func() (emulation.State, error) {
return dbg.vcs.Run(func() (govern.State, error) {
// update counters. because of the way LastResult works we need to make
// sure we only use it in the event that the CPU RdyFlag is set
//
@ -93,12 +93,12 @@ func (dbg *Debugger) playLoop() error {
if dbg.halting.halt {
// set debugging mode. halting messages will be preserved and
// shown when entering debugging mode
dbg.setMode(emulation.ModeDebugger)
return emulation.Ending, nil
dbg.setMode(govern.ModeDebugger)
return govern.Ending, nil
}
if dbg.Mode() != emulation.ModePlay {
return emulation.Ending, nil
if dbg.Mode() != govern.ModePlay {
return govern.Ending, nil
}
// return without checking interface unless we exceed the
@ -113,12 +113,12 @@ func (dbg *Debugger) playLoop() error {
case <-dbg.eventCheckPulse.C:
err := dbg.readEventsHandler()
if err != nil {
return emulation.Ending, err
return govern.Ending, err
}
default:
}
if dbg.state.Load().(emulation.State) == emulation.Running {
if dbg.state.Load().(govern.State) == govern.Running {
dbg.Rewind.RecordState()
}

View file

@ -17,50 +17,49 @@ package debugger
import (
"github.com/jetsetilly/gopher2600/curated"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/logger"
)
func argLen(args []emulation.FeatureReqData, expectedLen int) error {
func argLen(args []govern.FeatureReqData, expectedLen int) error {
if len(args) != expectedLen {
return curated.Errorf("wrong number of arguments (%d instead of %d)", len(args), expectedLen)
}
return nil
}
// ReqFeature implements the emulation.Emulation interface.
func (dbg *Debugger) SetFeature(request emulation.FeatureReq, args ...emulation.FeatureReqData) error {
// ReqFeature implements the govern.Emulation interface.
func (dbg *Debugger) SetFeature(request govern.FeatureReq, args ...govern.FeatureReqData) error {
var err error
switch request {
case emulation.ReqSetPause:
case govern.ReqSetPause:
err = argLen(args, 1)
if err != nil {
return curated.Errorf("debugger: %v", err)
}
switch dbg.Mode() {
case emulation.ModePlay:
case govern.ModePlay:
dbg.PushRawEvent(func() {
// Pause implements the emulation.Emulation interface.
if args[0].(bool) {
dbg.setState(emulation.Paused)
dbg.setState(govern.Paused)
} else {
dbg.setState(emulation.Running)
dbg.setState(govern.Running)
}
})
case emulation.ModeDebugger:
case govern.ModeDebugger:
err = curated.Errorf("not reacting to %s in debug mode (use terminal input instead)", request)
}
case emulation.ReqSetMode:
case govern.ReqSetMode:
err = argLen(args, 1)
if err != nil {
return curated.Errorf("debugger: %v", err)
}
dbg.PushRawEventImmediate(func() {
err := dbg.setMode(args[0].(emulation.Mode))
err := dbg.setMode(args[0].(govern.Mode))
if err != nil {
logger.Logf("debugger", err.Error())
}

View file

@ -22,7 +22,7 @@ import (
"fmt"
"github.com/jetsetilly/gopher2600/curated"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/gui"
"github.com/jetsetilly/gopher2600/hardware/television/coords"
)
@ -34,30 +34,30 @@ func (dbg *Debugger) RewindByAmount(amount int) bool {
default:
panic(fmt.Sprintf("Rewind: unsupported mode (%v)", dbg.Mode()))
case emulation.ModePlay:
case govern.ModePlay:
coords := dbg.vcs.TV.GetCoords()
tl := dbg.Rewind.GetTimeline()
if amount < 0 && coords.Frame-1 <= tl.AvailableStart {
dbg.setStateQuiet(emulation.Paused, true)
dbg.gui.SetFeature(gui.ReqEmulationEvent, emulation.EventRewindAtStart)
dbg.setStateQuiet(govern.Paused, true)
dbg.gui.SetFeature(gui.ReqEmulationEvent, govern.EventRewindAtStart)
return false
}
if amount > 0 && coords.Frame+1 >= tl.AvailableEnd {
dbg.setStateQuiet(emulation.Paused, true)
dbg.gui.SetFeature(gui.ReqEmulationEvent, emulation.EventRewindAtEnd)
dbg.setStateQuiet(govern.Paused, true)
dbg.gui.SetFeature(gui.ReqEmulationEvent, govern.EventRewindAtEnd)
return false
}
dbg.setStateQuiet(emulation.Rewinding, true)
dbg.setStateQuiet(govern.Rewinding, true)
dbg.Rewind.GotoFrame(coords.Frame + amount)
dbg.setStateQuiet(emulation.Paused, true)
dbg.setStateQuiet(govern.Paused, true)
if amount < 0 {
dbg.gui.SetFeature(gui.ReqEmulationEvent, emulation.EventRewindBack)
dbg.gui.SetFeature(gui.ReqEmulationEvent, govern.EventRewindBack)
} else {
dbg.gui.SetFeature(gui.ReqEmulationEvent, emulation.EventRewindFoward)
dbg.gui.SetFeature(gui.ReqEmulationEvent, govern.EventRewindFoward)
}
return true
@ -72,8 +72,8 @@ func (dbg *Debugger) RewindToFrame(fn int, last bool) bool {
default:
panic(fmt.Sprintf("RewindToFrame: unsupported mode (%v)", dbg.Mode()))
case emulation.ModeDebugger:
if dbg.State() == emulation.Rewinding {
case govern.ModeDebugger:
if dbg.State() == govern.Rewinding {
return false
}
@ -100,9 +100,9 @@ func (dbg *Debugger) RewindToFrame(fn int, last bool) bool {
// how we push the doRewind() function depends on what kind of inputloop we
// are currently in
dbg.PushRawEventImmediate(func() {
// set state to emulation.Rewinding as soon as possible (but
// set state to govern.Rewinding as soon as possible (but
// remembering that we must do it in the debugger goroutine)
dbg.setState(emulation.Rewinding)
dbg.setState(govern.Rewinding)
dbg.unwindLoop(doRewind)
})
@ -118,8 +118,8 @@ func (dbg *Debugger) GotoCoords(coords coords.TelevisionCoords) bool {
default:
panic(fmt.Sprintf("GotoCoords: unsupported mode (%v)", dbg.Mode()))
case emulation.ModeDebugger:
if dbg.State() == emulation.Rewinding {
case govern.ModeDebugger:
if dbg.State() == govern.Rewinding {
return false
}
@ -139,9 +139,9 @@ func (dbg *Debugger) GotoCoords(coords coords.TelevisionCoords) bool {
// how we push the doRewind() function depends on what kind of inputloop we
// are currently in
dbg.PushRawEventImmediate(func() {
// set state to emulation.Rewinding as soon as possible (but
// set state to govern.Rewinding as soon as possible (but
// remembering that we must do it in the debugger goroutine)
dbg.setState(emulation.Rewinding)
dbg.setState(govern.Rewinding)
dbg.unwindLoop(doRewind)
})
@ -157,8 +157,8 @@ func (dbg *Debugger) RerunLastNFrames(frames int) bool {
default:
panic(fmt.Sprintf("RerunLastNFrames: unsupported mode (%v)", dbg.Mode()))
case emulation.ModeDebugger:
if dbg.State() == emulation.Rewinding {
case govern.ModeDebugger:
if dbg.State() == govern.Rewinding {
return false
}
@ -194,9 +194,9 @@ func (dbg *Debugger) RerunLastNFrames(frames int) bool {
// upate catchupQuantum before starting rewind process
dbg.catchupQuantum = QuantumClock
// set state to emulation.Rewinding as soon as possible (but
// set state to govern.Rewinding as soon as possible (but
// remembering that we must do it in the debugger goroutine)
dbg.setState(emulation.Rewinding)
dbg.setState(govern.Rewinding)
dbg.unwindLoop(doRewind)
})

View file

@ -17,8 +17,8 @@ package debugger
import (
"github.com/jetsetilly/gopher2600/curated"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/debugger/terminal"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/userinput"
)
@ -45,7 +45,7 @@ func (dbg *Debugger) userInputHandler(ev userinput.Event) error {
// mode specific special input (not passed to the VCS as controller input)
switch dbg.Mode() {
case emulation.ModePlay:
case govern.ModePlay:
switch ev := ev.(type) {
case userinput.EventMouseWheel:
amount := int(ev.Delta) + dbg.rewindMouseWheelAccumulation
@ -73,7 +73,7 @@ func (dbg *Debugger) userInputHandler(ev userinput.Event) error {
}
} else {
dbg.rewindKeyboardAccumulation = 0
if dbg.State() != emulation.Running {
if dbg.State() != govern.Running {
return nil
}
}
@ -93,7 +93,7 @@ func (dbg *Debugger) userInputHandler(ev userinput.Event) error {
}
} else {
dbg.rewindKeyboardAccumulation = 0
if dbg.State() != emulation.Running {
if dbg.State() != govern.Running {
return nil
}
}
@ -106,18 +106,18 @@ func (dbg *Debugger) userInputHandler(ev userinput.Event) error {
if ev.Down {
switch ev.Button {
case userinput.GamepadButtonBack:
if dbg.State() != emulation.Paused {
dbg.SetFeature(emulation.ReqSetPause, true)
if dbg.State() != govern.Paused {
dbg.SetFeature(govern.ReqSetPause, true)
} else {
dbg.SetFeature(emulation.ReqSetPause, false)
dbg.SetFeature(govern.ReqSetPause, false)
}
return nil
case userinput.GamepadButtonGuide:
switch dbg.Mode() {
case emulation.ModePlay:
dbg.SetFeature(emulation.ReqSetMode, emulation.ModeDebugger)
case emulation.ModeDebugger:
dbg.SetFeature(emulation.ReqSetMode, emulation.ModePlay)
case govern.ModePlay:
dbg.SetFeature(govern.ReqSetMode, govern.ModeDebugger)
case govern.ModeDebugger:
dbg.SetFeature(govern.ReqSetMode, govern.ModePlay)
}
}
}
@ -133,8 +133,8 @@ func (dbg *Debugger) userInputHandler(ev userinput.Event) error {
// direction). unpause if the emulation is currently paused
//
// * we're only allowing this for playmode
if dbg.Mode() == emulation.ModePlay && dbg.State() == emulation.Paused && handled {
dbg.SetFeature(emulation.ReqSetPause, false)
if dbg.Mode() == govern.ModePlay && dbg.State() == govern.Paused && handled {
dbg.SetFeature(govern.ReqSetPause, false)
}
return nil

View file

@ -1,43 +0,0 @@
// 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 emulation
// FeatureReq is used to request the setting of an emulation attribute
// eg. a pause request from the GUI
type FeatureReq string
// FeatureReqData represents the information associated with a FeatureReq. See
// commentary for the defined FeatureReq values for the underlying type.
type FeatureReqData interface{}
// List of valid feature requests. argument must be of the type specified or
// else the interface{} type conversion will fail and the application will
// probably crash.
//
// Note that, like the name suggests, these are requests, they may or may not
// be satisfied depending on other conditions in the GUI.
const (
// notify gui of the underlying emulation mode.
ReqSetPause FeatureReq = "ReqSetPause" // bool
// change emulation mode
ReqSetMode FeatureReq = "ReqSetMode" // emulation.Mode
)
// Sentinal error returned if emulation does no support requested feature.
const (
UnsupportedEmulationFeature = "unsupported emulation feature: %v"
)

View file

@ -27,11 +27,11 @@ import (
"github.com/jetsetilly/gopher2600/cartridgeloader"
"github.com/jetsetilly/gopher2600/curated"
"github.com/jetsetilly/gopher2600/debugger"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/debugger/terminal"
"github.com/jetsetilly/gopher2600/debugger/terminal/colorterm"
"github.com/jetsetilly/gopher2600/debugger/terminal/plainterm"
"github.com/jetsetilly/gopher2600/disassembly"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/gui"
"github.com/jetsetilly/gopher2600/gui/sdlimgui"
"github.com/jetsetilly/gopher2600/hardware/riot/ports"
@ -236,10 +236,10 @@ func launch(sync *mainSync) {
fallthrough
case "PLAY":
err = emulate(emulation.ModePlay, md, sync)
err = emulate(govern.ModePlay, md, sync)
case "DEBUG":
err = emulate(emulation.ModeDebugger, md, sync)
err = emulate(govern.ModeDebugger, md, sync)
case "DISASM":
err = disasm(md)
@ -267,7 +267,7 @@ const defaultInitScript = "debuggerInit"
// emulate is the main emulation launch function, shared by play and debug
// modes. the other modes initialise and run the emulation differently.
func emulate(emulationMode emulation.Mode, md *modalflag.Modes, sync *mainSync) error {
func emulate(emulationMode govern.Mode, md *modalflag.Modes, sync *mainSync) error {
// start new commandline mode. to this we'll add the command line arguments
// that are specific to the emulation mode (it's unfortunate that mode is
// used to describe two separate concepts but they really have nothing to
@ -297,7 +297,7 @@ func emulate(emulationMode emulation.Mode, md *modalflag.Modes, sync *mainSync)
opts.Profile = md.AddString("profile", "none", "run performance check with profiling: command separated CPU, MEM, TRACE or ALL")
// playmode specific arguments
if emulationMode == emulation.ModePlay {
if emulationMode == govern.ModePlay {
opts.ComparisonROM = md.AddString("comparisonROM", "", "ROM to run in parallel for comparison")
opts.ComparisonPrefs = md.AddString("comparisonPrefs", "", "preferences for comparison emulation")
opts.Record = md.AddBool("record", false, "record user input to a file")
@ -308,7 +308,7 @@ func emulate(emulationMode emulation.Mode, md *modalflag.Modes, sync *mainSync)
}
// debugger specific arguments
if emulationMode == emulation.ModeDebugger {
if emulationMode == govern.ModeDebugger {
opts.InitScript = md.AddString("initscript", defInitScript, "script to run on debugger start")
opts.TermType = md.AddString("term", "IMGUI", "terminal type to use in debug mode: IMGUI, COLOR, PLAIN")
} else {
@ -348,7 +348,7 @@ func emulate(emulationMode emulation.Mode, md *modalflag.Modes, sync *mainSync)
// prepare new debugger, supplying a debugger.CreateUserInterface function.
// this function will be called by NewDebugger() and in turn will send a
// GUI create message to the main goroutine
dbg, err := debugger.NewDebugger(opts, func(e emulation.Emulation) (gui.GUI, terminal.Terminal, error) {
dbg, err := debugger.NewDebugger(opts, func(e *debugger.Debugger) (gui.GUI, terminal.Terminal, error) {
var term terminal.Terminal
var scr gui.GUI
@ -402,13 +402,13 @@ func emulate(emulationMode emulation.Mode, md *modalflag.Modes, sync *mainSync)
// a call to performance.RunProfiler()
dbgLaunch := func() error {
switch emulationMode {
case emulation.ModeDebugger:
case govern.ModeDebugger:
err := dbg.StartInDebugMode(md.GetArg(0))
if err != nil {
return err
}
case emulation.ModePlay:
case govern.ModePlay:
err := dbg.StartInPlayMode(md.GetArg(0))
if err != nil {
return err
@ -435,9 +435,9 @@ func emulate(emulationMode emulation.Mode, md *modalflag.Modes, sync *mainSync)
// filename argument for RunProfiler
s := ""
switch emulationMode {
case emulation.ModeDebugger:
case govern.ModeDebugger:
s = "debugger"
case emulation.ModePlay:
case govern.ModePlay:
s = "play"
}

View file

@ -17,7 +17,7 @@ package sdlimgui
import (
"github.com/go-gl/gl/v3.2-core/gl"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/gui/sdlimgui/shaders"
"github.com/jetsetilly/gopher2600/hardware/television/specification"
)
@ -90,14 +90,14 @@ func (attr *dbgScrHelper) set(img *SdlImgui) {
// end of critical section
// show cursor
switch img.emulation.State() {
case emulation.Paused:
switch img.dbg.State() {
case govern.Paused:
gl.Uniform1i(attr.showCursor, 1)
case emulation.Running:
case govern.Running:
gl.Uniform1i(attr.showCursor, 0)
case emulation.Stepping:
case govern.Stepping:
gl.Uniform1i(attr.showCursor, 1)
case emulation.Rewinding:
case govern.Rewinding:
gl.Uniform1i(attr.showCursor, 1)
}
}

View file

@ -19,8 +19,8 @@ import (
"sync/atomic"
"github.com/jetsetilly/gopher2600/debugger"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/disassembly"
"github.com/jetsetilly/gopher2600/emulation"
)
// LazyDebugger lazily accesses Debugger information.
@ -31,18 +31,18 @@ type LazyDebugger struct {
liveDisasmEntry atomic.Value // disassembly.Entry
breakpoints atomic.Value // debugger.BreakpointsQuery
hasChanged atomic.Value // bool
state atomic.Value // emulation.State
state atomic.Value // govern.State
Quantum debugger.Quantum
LiveDisasmEntry disassembly.Entry
Breakpoints debugger.BreakpointsQuery
HasChanged bool
// the emulation.State below is taken at the same time as the reset of the
// the govern.State below is taken at the same time as the reset of the
// lazy values. this value should be used in preference to the live
// emulation.State() value (which is safe to obtain outside of the lazy
// govern.State() value (which is safe to obtain outside of the lazy
// system) when synchronisation is important
State emulation.State
State govern.State
}
func newLazyDebugger(val *LazyValues) *LazyDebugger {
@ -78,5 +78,5 @@ func (lz *LazyDebugger) update() {
// load current hasChanged value and unlatch (see push() function)
lz.HasChanged = lz.hasChanged.Load().(bool)
lz.hasChanged.Store(false)
lz.State, _ = lz.state.Load().(emulation.State)
lz.State, _ = lz.state.Load().(govern.State)
}

View file

@ -19,7 +19,6 @@ import (
"sync/atomic"
"github.com/jetsetilly/gopher2600/debugger"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/hardware"
"github.com/jetsetilly/gopher2600/hardware/television"
)
@ -28,12 +27,9 @@ import (
// thread to the emulation. Use these values rather than directly accessing
// those exposed by the emulation.
type LazyValues struct {
emulation emulation.Emulation
// vcs and dbg are taken from the emulation supplied to SetEmulation()
dbg *debugger.Debugger
tv *television.Television
vcs *hardware.VCS
dbg *debugger.Debugger
// pointers to these instances. non-pointer instances trigger the race
// detector for some reason.
@ -67,16 +63,12 @@ type LazyValues struct {
}
// NewLazyValues is the preferred method of initialisation for the Values type.
func NewLazyValues(e emulation.Emulation) *LazyValues {
func NewLazyValues(dbg *debugger.Debugger) *LazyValues {
val := &LazyValues{}
val.emulation = e
val.tv = e.TV().(*television.Television)
val.vcs = e.VCS().(*hardware.VCS)
switch dbg := e.Debugger().(type) {
case *debugger.Debugger:
val.dbg = dbg
}
val.dbg = dbg
val.tv = val.dbg.TV()
val.vcs = val.dbg.VCS()
val.Debugger = newLazyDebugger(val)
val.CPU = newLazyCPU(val)
@ -107,7 +99,7 @@ func NewLazyValues(e emulation.Emulation) *LazyValues {
// Refresh lazy values.
func (val *LazyValues) Refresh() {
if val.emulation == nil {
if val.dbg == nil {
return
}
@ -169,7 +161,7 @@ func (val *LazyValues) Refresh() {
// FastRefresh lazy values. Updates only the values that are needed in playmode.
func (val *LazyValues) FastRefresh() {
if val.emulation == nil {
if val.dbg == nil {
return
}

View file

@ -19,7 +19,7 @@ import (
"sort"
"github.com/inkyblackness/imgui-go/v4"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
)
// manager handles windows and menus in the system.
@ -209,13 +209,13 @@ func (wm *manager) draw() {
}
switch wm.img.mode {
case emulation.ModePlay:
case govern.ModePlay:
// playmode draws the screen and other windows that have been listed
// as being safe to draw in playmode
for _, w := range wm.playmodeWindows {
w.playmodeDraw()
}
case emulation.ModeDebugger:
case govern.ModeDebugger:
// see commentary for screenPos in windowManager declaration
wm.screenPos = imgui.WindowPos()

View file

@ -20,7 +20,7 @@ import (
"math"
"github.com/inkyblackness/imgui-go/v4"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/gui/fonts"
)
@ -172,7 +172,7 @@ func (wm *manager) drawMenu() {
wdth -= rightJustText(wdth, fmt.Sprintf("%.2fHz", wm.img.lz.TV.Hz), true)
}
if wm.img.emulation.State() == emulation.Running {
if wm.img.dbg.State() == govern.Running {
if wm.img.lz.TV.ReqFPS < 1.0 {
wdth -= rightJustText(wdth, "< 1 fps", true)
} else if math.IsInf(float64(wm.img.lz.TV.ActualFPS), 0) {

View file

@ -22,7 +22,7 @@ import (
"strings"
"github.com/jetsetilly/gopher2600/curated"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/prefs"
"github.com/jetsetilly/gopher2600/resources"
"github.com/jetsetilly/gopher2600/resources/fs"
@ -77,7 +77,7 @@ func (wm *manager) saveManagerState() (rerr error) {
continue
}
s := fmt.Sprintf("%s%s%s%s%v\n", emulation.ModeDebugger.String(), prefs.KeySep, key, prefs.KeySep, win.debuggerIsOpen())
s := fmt.Sprintf("%s%s%s%s%v\n", govern.ModeDebugger.String(), prefs.KeySep, key, prefs.KeySep, win.debuggerIsOpen())
n, err := fmt.Fprint(f, s)
if err != nil {
return curated.Errorf("manager state: %v", err)
@ -94,7 +94,7 @@ func (wm *manager) saveManagerState() (rerr error) {
continue
}
s := fmt.Sprintf("%s%s%s%s%v\n", emulation.ModePlay.String(), prefs.KeySep, key, prefs.KeySep, win.playmodeIsOpen())
s := fmt.Sprintf("%s%s%s%s%v\n", govern.ModePlay.String(), prefs.KeySep, key, prefs.KeySep, win.playmodeIsOpen())
n, err := fmt.Fprint(f, s)
if err != nil {
return curated.Errorf("manager state: %v", err)
@ -159,13 +159,13 @@ func (wm *manager) loadManagerState() (rerr error) {
k := spt[1]
v := spt[2]
if m == emulation.ModeDebugger.String() {
if m == govern.ModeDebugger.String() {
if w, ok := wm.debuggerWindows[k]; ok {
w.debuggerSetOpen(strings.ToUpper(v) == "TRUE")
}
}
if m == emulation.ModePlay.String() {
if m == govern.ModePlay.String() {
if w, ok := wm.playmodeWindows[k]; ok {
w.playmodeSetOpen(strings.ToUpper(v) == "TRUE")
}

View file

@ -88,7 +88,7 @@ func newPlayScr(img *SdlImgui) *playScr {
rightAlign: true,
},
emulationEvent: emulationEventNotification{
emulation: img.emulation,
emulation: img.dbg,
},
}

View file

@ -19,7 +19,8 @@ import (
"fmt"
"github.com/inkyblackness/imgui-go/v4"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/gui/fonts"
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/mapper"
"github.com/jetsetilly/gopher2600/hardware/riot/ports/plugging"
@ -118,9 +119,9 @@ func (pn *peripheralNotification) draw(win *playScr) {
// emulationEventNotification is used to draw an indicator on the screen for
// events defined in the emulation package.
type emulationEventNotification struct {
emulation emulation.Emulation
emulation *debugger.Debugger
open bool
currentEvent emulation.Event
currentEvent govern.Event
frames int
// audio mute is handled differently to other events. we want the icon for
@ -130,18 +131,18 @@ type emulationEventNotification struct {
mute bool
}
func (ee *emulationEventNotification) set(event emulation.Event) {
func (ee *emulationEventNotification) set(event govern.Event) {
ee.currentEvent = event
ee.open = true
ee.frames = notificationDurationEvent
switch event {
case emulation.EventRun:
case govern.EventRun:
ee.frames = notificationDurationEventRun
case emulation.EventScreenshot:
case govern.EventScreenshot:
ee.frames = notificationDurationScreenshot
case emulation.EventMute:
case govern.EventMute:
ee.mute = true
case emulation.EventUnmute:
case govern.EventUnmute:
ee.mute = false
}
}
@ -155,16 +156,16 @@ func (ee *emulationEventNotification) tick() {
if ee.frames == 0 {
// if emulation is paused then force the current event to EventPause
if ee.emulation.State() == emulation.Paused {
ee.currentEvent = emulation.EventPause
if ee.emulation.State() == govern.Paused {
ee.currentEvent = govern.EventPause
}
// special handling of open when current event is EventPause or if mute
// is enabled
if ee.currentEvent != emulation.EventPause {
if ee.currentEvent != govern.EventPause {
if ee.mute {
ee.open = true
ee.currentEvent = emulation.EventMute
ee.currentEvent = govern.EventMute
} else {
ee.open = false
}
@ -196,23 +197,23 @@ func (ee *emulationEventNotification) draw(win *playScr, hosted bool) {
}
switch ee.currentEvent {
case emulation.EventInitialising:
case govern.EventInitialising:
imgui.Text("")
case emulation.EventPause:
case govern.EventPause:
imgui.Text(string(fonts.EmulationPause))
case emulation.EventRun:
case govern.EventRun:
imgui.Text(string(fonts.EmulationRun))
case emulation.EventRewindBack:
case govern.EventRewindBack:
imgui.Text(string(fonts.EmulationRewindBack))
case emulation.EventRewindFoward:
case govern.EventRewindFoward:
imgui.Text(string(fonts.EmulationRewindForward))
case emulation.EventRewindAtStart:
case govern.EventRewindAtStart:
imgui.Text(string(fonts.EmulationRewindAtStart))
case emulation.EventRewindAtEnd:
case govern.EventRewindAtEnd:
imgui.Text(string(fonts.EmulationRewindAtEnd))
case emulation.EventScreenshot:
case govern.EventScreenshot:
imgui.Text(string(fonts.Camera))
case emulation.EventMute:
case govern.EventMute:
if hosted || win.img.prefs.audioMuteNotification.Get().(bool) {
imgui.Text(string(fonts.AudioMute))
}

View file

@ -18,7 +18,7 @@ package sdlimgui
import (
"time"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/veandco/go-sdl2/sdl"
)
@ -128,7 +128,7 @@ func (pol *polling) wait() sdl.Event {
} else {
working := pol.awake ||
pol.img.lz.Debugger.HasChanged ||
pol.img.emulation.State() != emulation.Paused ||
pol.img.dbg.State() != govern.Paused ||
pol.img.wm.dbgScr.crtPreview
if working {

View file

@ -17,7 +17,7 @@ package sdlimgui
import (
"fmt"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/prefs"
"github.com/jetsetilly/gopher2600/resources"
)
@ -236,11 +236,11 @@ func (p *preferences) loadWindowPreferences() error {
var group string
switch p.img.mode {
case emulation.ModeNone:
case govern.ModeNone:
p.img.plt.window.Hide()
case emulation.ModeDebugger:
case govern.ModeDebugger:
group = "sdlimgui.debugger"
case emulation.ModePlay:
case govern.ModePlay:
group = "sdlimgui.playmode"
default:
panic(fmt.Sprintf("cannot set window mode for unsupported emulation mode (%v)", p.img.mode))

View file

@ -20,7 +20,7 @@ import (
"github.com/jetsetilly/gopher2600/bots"
"github.com/jetsetilly/gopher2600/curated"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/gui"
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/mapper"
"github.com/jetsetilly/gopher2600/hardware/riot/ports/plugging"
@ -54,7 +54,7 @@ func (img *SdlImgui) serviceSetFeature(request featureRequest) {
case gui.ReqSetEmulationMode:
err = argLen(request.args, 1)
if err == nil {
img.setEmulationMode(request.args[0].(emulation.Mode))
img.setEmulationMode(request.args[0].(govern.Mode))
}
case gui.ReqEnd:
@ -106,7 +106,7 @@ func (img *SdlImgui) serviceSetFeature(request featureRequest) {
if img.isPlaymode() {
err = argLen(request.args, 1)
if err == nil {
img.playScr.emulationEvent.set(request.args[0].(emulation.Event))
img.playScr.emulationEvent.set(request.args[0].(govern.Event))
}
}

View file

@ -20,7 +20,7 @@ import (
"image/color"
"sync"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/mapper"
"github.com/jetsetilly/gopher2600/hardware/television"
"github.com/jetsetilly/gopher2600/hardware/television/signal"
@ -360,14 +360,14 @@ func (scr *screen) NewFrame(frameInfo television.FrameInfo) error {
}
if scr.crit.monitorSync && scr.crit.monitorSyncInRange {
switch scr.img.emulation.State() {
case emulation.Rewinding:
switch scr.img.dbg.State() {
case govern.Rewinding:
fallthrough
case emulation.Paused:
case govern.Paused:
scr.crit.renderIdx = scr.crit.plotIdx
scr.crit.prevRenderIdx = scr.crit.plotIdx
scr.crit.bufferUsed = len(scr.crit.bufferPixels)
case emulation.Running:
case govern.Running:
if scr.crit.bufferUsed > 0 {
scr.crit.bufferUsed--
}
@ -622,7 +622,7 @@ func (scr *screen) copyPixelsPlaymode() {
// poor results for one frame kernels (depending on the ROM and what is
// happening on the screen at the time of the pause ) and will be
// sub-optimal for three frame kernels in almost all cases.
if scr.img.emulation.State() == emulation.Paused {
if scr.img.dbg.State() == govern.Paused {
activePause := scr.img.prefs.activePause.Get().(bool)
if scr.crit.pauseFrame || !activePause {
copy(scr.crit.pixels.Pix, scr.crit.bufferPixels[scr.crit.renderIdx].Pix)

View file

@ -21,8 +21,8 @@ import (
"github.com/jetsetilly/gopher2600/curated"
"github.com/jetsetilly/gopher2600/debugger"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/debugger/terminal"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/gui/crt"
"github.com/jetsetilly/gopher2600/gui/sdlaudio"
"github.com/jetsetilly/gopher2600/gui/sdlimgui/lazyvalues"
@ -63,16 +63,13 @@ type SdlImgui struct {
// allow sufficient time to close the font size selector combo box
resetFonts int
// parent emulation. should be set via setEmulation() only
emulation emulation.Emulation
// the current mode of the underlying
mode emulation.Mode
mode govern.Mode
// taken from the emulation field and assigned in the setEmulation() function
dbg *debugger.Debugger
tv *television.Television
vcs *hardware.VCS
dbg *debugger.Debugger
userinput chan userinput.Event
// lazy value system allows safe access to the debugger/emulation from the
@ -127,21 +124,17 @@ type SdlImgui struct {
// NewSdlImgui is the preferred method of initialisation for type SdlImgui
//
// MUST ONLY be called from the gui thread.
func NewSdlImgui(e emulation.Emulation) (*SdlImgui, error) {
func NewSdlImgui(dbg *debugger.Debugger) (*SdlImgui, error) {
img := &SdlImgui{
context: imgui.CreateContext(nil),
io: imgui.CurrentIO(),
postRenderFunctions: make(chan func(), 100),
}
img.emulation = e
img.tv = e.TV().(*television.Television)
img.vcs = e.VCS().(*hardware.VCS)
switch dbg := e.Debugger().(type) {
case *debugger.Debugger:
img.dbg = dbg
}
img.userinput = e.UserInput()
img.dbg = dbg
img.tv = img.dbg.TV()
img.vcs = img.dbg.VCS()
img.userinput = img.dbg.UserInput()
// path to dear imgui ini file
iniPath, err := resources.JoinPath(imguiIniFile)
@ -163,7 +156,7 @@ func NewSdlImgui(e emulation.Emulation) (*SdlImgui, error) {
return nil, curated.Errorf("sdlimgui: %v", err)
}
img.lz = lazyvalues.NewLazyValues(img.emulation)
img.lz = lazyvalues.NewLazyValues(img.dbg)
img.screen = newScreen(img)
img.term = newTerm()
@ -298,18 +291,18 @@ func (img *SdlImgui) end() {
// draw gui. called from service loop.
func (img *SdlImgui) draw() {
if img.mode == emulation.ModeNone {
if img.mode == govern.ModeNone {
return
}
if img.emulation.State() == emulation.EmulatorStart {
if img.dbg.State() == govern.EmulatorStart {
return
}
imgui.PushFont(img.glsl.fonts.defaultFont)
defer imgui.PopFont()
if img.mode == emulation.ModePlay {
if img.mode == govern.ModePlay {
img.playScr.draw()
}
@ -320,14 +313,14 @@ func (img *SdlImgui) draw() {
// is the gui in playmode or not. thread safe. called from emulation thread
// and gui thread.
func (img *SdlImgui) isPlaymode() bool {
return img.mode == emulation.ModePlay
return img.mode == govern.ModePlay
}
// set emulation and handle the changeover gracefully. this includes the saving
// and loading of preference groups.
//
// should only be called from gui thread.
func (img *SdlImgui) setEmulationMode(mode emulation.Mode) error {
func (img *SdlImgui) setEmulationMode(mode govern.Mode) error {
// release captured mouse before switching emulation modes. if we don't do
// this then the capture state will remain if we flip back to the emulation
// mode later. at this point the captured mouse can cause confusion
@ -337,12 +330,12 @@ func (img *SdlImgui) setEmulationMode(mode emulation.Mode) error {
img.prefs.loadWindowPreferences()
switch mode {
case emulation.ModeDebugger:
case govern.ModeDebugger:
img.screen.clearTextureRenderers()
img.screen.addTextureRenderer(img.wm.dbgScr)
img.plt.window.Show()
case emulation.ModePlay:
case govern.ModePlay:
img.screen.clearTextureRenderers()
img.screen.addTextureRenderer(img.playScr)
img.plt.window.Show()
@ -379,9 +372,9 @@ func (img *SdlImgui) setAudioMute() {
if img.isPlaymode() {
mute = img.prefs.audioMutePlaymode.Get().(bool)
if mute {
img.playScr.emulationEvent.set(emulation.EventMute)
img.playScr.emulationEvent.set(govern.EventMute)
} else {
img.playScr.emulationEvent.set(emulation.EventUnmute)
img.playScr.emulationEvent.set(govern.EventUnmute)
}
img.vcs.RIOT.Ports.MutePeripherals(mute)
} else {

View file

@ -18,7 +18,7 @@ package sdlimgui
import (
"time"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/hardware/riot/ports/plugging"
"github.com/jetsetilly/gopher2600/logger"
"github.com/jetsetilly/gopher2600/userinput"
@ -43,9 +43,9 @@ func (img *SdlImgui) Service() {
// refresh lazy values
switch img.mode {
case emulation.ModeDebugger:
case govern.ModeDebugger:
img.lz.Refresh()
case emulation.ModePlay:
case govern.ModePlay:
img.lz.FastRefresh()
}
@ -141,7 +141,7 @@ func (img *SdlImgui) Service() {
}
img.io.AddMouseWheelDelta(deltaX/4, deltaY/4)
if img.mode != emulation.ModePlay || !img.wm.playmodeWindows[winSelectROMID].playmodeIsOpen() {
if img.mode != govern.ModePlay || !img.wm.playmodeWindows[winSelectROMID].playmodeIsOpen() {
select {
case img.userinput <- userinput.EventMouseWheel{Delta: deltaY}:
default:
@ -386,9 +386,9 @@ func (img *SdlImgui) serviceKeyboard(ev *sdl.KeyboardEvent) {
case sdl.SCANCODE_GRAVE:
if img.isPlaymode() {
img.emulation.SetFeature(emulation.ReqSetMode, emulation.ModeDebugger)
img.dbg.SetFeature(govern.ReqSetMode, govern.ModeDebugger)
} else {
img.emulation.SetFeature(emulation.ReqSetMode, emulation.ModePlay)
img.dbg.SetFeature(govern.ReqSetMode, govern.ModePlay)
}
case sdl.SCANCODE_F8:
@ -413,7 +413,7 @@ func (img *SdlImgui) serviceKeyboard(ev *sdl.KeyboardEvent) {
img.glsl.shaders[playscrShaderID].(*playscrShader).scheduleScreenshot(modeSingle)
}
img.playScr.emulationEvent.set(emulation.EventScreenshot)
img.playScr.emulationEvent.set(govern.EventScreenshot)
case sdl.SCANCODE_F14:
fallthrough
@ -425,16 +425,16 @@ func (img *SdlImgui) serviceKeyboard(ev *sdl.KeyboardEvent) {
case sdl.SCANCODE_PAUSE:
if img.isPlaymode() {
var err error
if img.emulation.State() == emulation.Paused {
err = img.emulation.SetFeature(emulation.ReqSetPause, false)
if img.dbg.State() == govern.Paused {
err = img.dbg.SetFeature(govern.ReqSetPause, false)
} else {
err = img.emulation.SetFeature(emulation.ReqSetPause, true)
err = img.dbg.SetFeature(govern.ReqSetPause, true)
}
if err != nil {
logger.Logf("sdlimgui", err.Error())
}
} else {
if img.emulation.State() == emulation.Paused {
if img.dbg.State() == govern.Paused {
img.term.pushCommand("RUN")
} else {
img.term.pushCommand("HALT")

View file

@ -21,7 +21,7 @@ import (
"time"
"github.com/jetsetilly/gopher2600/debugger"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/gui/fonts"
"github.com/inkyblackness/imgui-go/v4"
@ -120,7 +120,7 @@ func (win *winControl) draw() {
func (win *winControl) drawRunButton() {
runDim := imgui.Vec2{X: imguiRemainingWinWidth(), Y: imgui.FrameHeight()}
if win.img.emulation.State() == emulation.Running {
if win.img.dbg.State() == govern.Running {
if imguiColourButton(win.img.cols.False, fmt.Sprintf("%c Halt", fonts.Halt), runDim) {
win.img.term.pushCommand("HALT")
}
@ -229,7 +229,7 @@ func (win *winControl) drawFPS() {
}
imgui.Spacing()
if win.img.emulation.State() == emulation.Running {
if win.img.dbg.State() == govern.Running {
if win.img.lz.TV.ActualFPS <= win.img.lz.TV.ReqFPS*0.95 {
imgui.Text("running below requested FPS")
} else if win.img.lz.TV.ActualFPS > win.img.lz.TV.ReqFPS*1.05 {
@ -253,13 +253,13 @@ func (win *winControl) drawMouseCapture() {
if win.img.wm.dbgScr.isCaptured {
imgui.AlignTextToFramePadding()
label := "RMB to release input"
if win.img.emulation.State() == emulation.Running {
if win.img.dbg.State() == govern.Running {
label = "RMB to halt & release input"
}
imgui.Text(label)
} else {
label := "Capture input & run"
if win.img.emulation.State() == emulation.Running {
if win.img.dbg.State() == govern.Running {
label = "Capture input & continue"
}
if imgui.Button(label) {

View file

@ -20,7 +20,7 @@ import (
"github.com/inkyblackness/imgui-go/v4"
"github.com/jetsetilly/gopher2600/coprocessor/disassembly"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/gui/fonts"
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/arm"
)
@ -114,7 +114,7 @@ func (win *winCoProcDisasm) draw() {
if imgui.Checkbox("Disassembly Enabled", &isEnabled) {
win.img.dbg.PushRawEvent(func() {
win.img.dbg.CoProcDisasm.Enable(isEnabled)
if win.img.emulation.State() != emulation.Running {
if win.img.dbg.State() != govern.Running {
// rerun the last two frames in order to gather as much disasm
// information as possible.
win.img.dbg.RerunLastNFrames(2)

View file

@ -21,8 +21,8 @@ import (
"github.com/go-gl/gl/v3.2-core/gl"
"github.com/inkyblackness/imgui-go/v4"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/disassembly"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/mapper"
"github.com/jetsetilly/gopher2600/hardware/memory/vcs"
"github.com/jetsetilly/gopher2600/hardware/television/coords"
@ -254,7 +254,7 @@ func (win *winDbgScr) draw() {
if imgui.IsWindowFocused() && imageHovered {
// mouse click will cause the rewind goto coords to run only when the
// emulation is paused
if win.img.emulation.State() == emulation.Paused {
if win.img.dbg.State() == govern.Paused {
if imgui.IsMouseDown(0) {
coords := coords.TelevisionCoords{
Frame: win.img.lz.TV.Coords.Frame,
@ -464,7 +464,7 @@ func (win *winDbgScr) drawReflectionTooltip() {
imguiSeparator()
// if mouse is over a pixel from the previous frame then show nothing except a note
if win.img.emulation.State() == emulation.Paused {
if win.img.dbg.State() == govern.Paused {
if win.mouse.scanline > win.img.screen.crit.lastScanline ||
(win.mouse.scanline == win.img.screen.crit.lastScanline && win.mouse.clock > win.img.screen.crit.lastClock) {
imgui.Text("From previous frame")

View file

@ -18,8 +18,8 @@ package sdlimgui
import (
"fmt"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/disassembly"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/gui/fonts"
"github.com/jetsetilly/gopher2600/hardware/memory/memorymap"
@ -42,7 +42,7 @@ type winDisasm struct {
img *SdlImgui
// more recently seen emulation state
lastSeenState emulation.State
lastSeenState govern.State
lastSeenPC uint16
// height of options line at bottom of window. valid after first frame
@ -130,10 +130,10 @@ func (win *winDisasm) draw() {
// followCPU is set; or the PC has changed (this is because the state
// change might be missed)
//
// using the lazy emulation.State value rather than the live state - the
// using the lazy govern.State value rather than the live state - the
// live state can cause synchronisation problems meaning focus is lost
if win.followCPU {
if (win.img.lz.Debugger.State == emulation.Paused && win.lastSeenState != emulation.Paused) ||
if (win.img.lz.Debugger.State == govern.Paused && win.lastSeenState != govern.Paused) ||
win.img.lz.CPU.PC.Address() != win.lastSeenPC {
win.focusOnAddr = true

View file

@ -17,7 +17,7 @@ package sdlimgui
import (
"github.com/inkyblackness/imgui-go/v4"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/logger"
)
@ -76,7 +76,7 @@ func (win *winLog) draw() {
}
// very simple conditions to scroll to the bottom
if win.scrollToBottom || win.img.emulation.State() == emulation.Running {
if win.scrollToBottom || win.img.dbg.State() == govern.Running {
win.scrollToBottom = false
imgui.SetScrollHereY(0.0)
}

View file

@ -19,7 +19,7 @@ import (
"fmt"
"github.com/inkyblackness/imgui-go/v4"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/gui/fonts"
"github.com/jetsetilly/gopher2600/logger"
)
@ -106,7 +106,7 @@ func (win *winPrefs) draw() {
imgui.EndTabItem()
}
if win.img.mode == emulation.ModeDebugger {
if win.img.mode == govern.ModeDebugger {
if imgui.BeginTabItem("Debugger") {
win.drawDebuggerTab()
imgui.EndTabItem()
@ -418,9 +418,9 @@ func (win *winPrefs) drawVCS() {
var warning bool
switch win.img.mode {
case emulation.ModePlay:
case govern.ModePlay:
warning = win.img.prefs.audioMutePlaymode.Get().(bool)
case emulation.ModeDebugger:
case govern.ModeDebugger:
warning = win.img.prefs.audioMuteDebugger.Get().(bool)
}
@ -587,7 +587,7 @@ func (win *winPrefs) drawDiskButtons() {
logger.Logf("sdlimgui", "could not save (rewind) preferences: %v", err)
}
if win.img.mode == emulation.ModeDebugger {
if win.img.mode == govern.ModeDebugger {
err = win.img.dbg.Disasm.Prefs.Save()
if err != nil {
logger.Logf("sdlimgui", "could not save (disasm) preferences: %v", err)
@ -636,7 +636,7 @@ func (win *winPrefs) drawDiskButtons() {
logger.Logf("sdlimgui", "could not restore (rewind) preferences: %v", err)
}
if win.img.mode == emulation.ModeDebugger {
if win.img.mode == govern.ModeDebugger {
err = win.img.dbg.Disasm.Prefs.Load()
if err != nil {
logger.Logf("sdlimgui", "could not restore (disasm) preferences: %v", err)

View file

@ -20,8 +20,8 @@ import (
"os"
"strings"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/debugger/terminal"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/gui/fonts"
"github.com/jetsetilly/gopher2600/logger"
"github.com/jetsetilly/gopher2600/resources/unique"
@ -175,7 +175,7 @@ func (win *winTerm) debuggerDraw() {
// the prompt in the terminal should show the disassembly for the
// instruction the PC is *currently* on. in other words, the
// disassembly for the inesturction to be executed *next*
if win.img.emulation.State() == emulation.Running {
if win.img.dbg.State() == govern.Running {
res := win.img.lz.Debugger.LiveDisasmEntry
imgui.Text(res.String())
if !win.img.lz.Debugger.LiveDisasmEntry.Result.Final {

View file

@ -19,7 +19,7 @@ import (
"fmt"
"github.com/inkyblackness/imgui-go/v4"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/gui/fonts"
"github.com/jetsetilly/gopher2600/hardware/television/coords"
"github.com/jetsetilly/gopher2600/tracker"
@ -265,7 +265,7 @@ func (win *winTracker) draw() {
imgui.EndTable()
if win.img.emulation.State() == emulation.Running {
if win.img.dbg.State() == govern.Running {
imgui.SetScrollHereY(1.0)
}
}

View file

@ -15,6 +15,7 @@
package gui
// Stub is a type of convenience that implements the GUI interface.
type Stub struct{}
// SetFeature implements the GUI interface.

View file

@ -17,7 +17,7 @@ package hardware
import (
"github.com/jetsetilly/gopher2600/curated"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
)
// While the continueCheck() function only runs at the end of a CPU instruction
@ -32,19 +32,19 @@ import (
// if performanceFilter >= hardware.PerfomrmanceBrake {
// performanceFilter = 0
// if end_condition == true {
// return emulation.Ending, nill
// return govern.Ending, nill
// }
// }
// return emulation.Running, nill
// return govern.Running, nill
//
const PerformanceBrake = 100
// Run sets the emulation running as quickly as possible. continuteCheck()
// should return false when an external event (eg. a GUI event) indicates that
// the emulation should stop.
func (vcs *VCS) Run(continueCheck func() (emulation.State, error)) error {
func (vcs *VCS) Run(continueCheck func() (govern.State, error)) error {
if continueCheck == nil {
continueCheck = func() (emulation.State, error) { return emulation.Running, nil }
continueCheck = func() (govern.State, error) { return govern.Running, nil }
}
// see the equivalient videoCycle() in the VCS.Step() function for an
@ -83,16 +83,16 @@ func (vcs *VCS) Run(continueCheck func() (emulation.State, error)) error {
var err error
state := emulation.Running
state := govern.Running
for state != emulation.Ending {
for state != govern.Ending {
switch state {
case emulation.Running:
case govern.Running:
err := vcs.CPU.ExecuteInstruction(videoCycle)
if err != nil {
return err
}
case emulation.Paused:
case govern.Paused:
default:
return curated.Errorf("vcs: unsupported emulation state (%d) in Run() function", state)
}
@ -109,16 +109,16 @@ func (vcs *VCS) Run(continueCheck func() (emulation.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) (emulation.State, error)) error {
func (vcs *VCS) RunForFrameCount(numFrames int, continueCheck func(frame int) (govern.State, error)) error {
if continueCheck == nil {
continueCheck = func(frame int) (emulation.State, error) { return emulation.Running, nil }
continueCheck = func(frame int) (govern.State, error) { return govern.Running, nil }
}
frameNum := vcs.TV.GetCoords().Frame
targetFrame := frameNum + numFrames
state := emulation.Running
for frameNum != targetFrame && state != emulation.Ending {
state := govern.Running
for frameNum != targetFrame && state != govern.Ending {
err := vcs.Step(nil)
if err != nil {
return err

View file

@ -20,7 +20,7 @@ import (
"strings"
"github.com/jetsetilly/gopher2600/curated"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/hardware/television/coords"
"github.com/jetsetilly/gopher2600/hardware/television/signal"
"github.com/jetsetilly/gopher2600/hardware/television/specification"
@ -174,7 +174,7 @@ type Television struct {
prevSignalFirst int
// state of emulation
emulationState emulation.State
emulationState govern.State
}
// NewTelevision creates a new instance of the television type, satisfying the
@ -535,7 +535,7 @@ func (tv *Television) newScanline() error {
// check for realtime mixing requirements. if it is required then
// immediately push the audio data from the previous frame to the mixer
if tv.realtimeMixer != nil && tv.emulationState == emulation.Running && tv.state.frameInfo.Stable {
if tv.realtimeMixer != nil && tv.emulationState == govern.Running && tv.state.frameInfo.Stable {
if tv.realtimeMixer.MoreAudio() {
err := tv.realtimeMixer.SetAudio(tv.prevSignals[:tv.prevSignalLastIdx])
if err != nil {
@ -669,7 +669,7 @@ func (tv *Television) newFrame(fromVsync bool) error {
// renderers and audio mixers.
func (tv *Television) renderSignals() error {
// do not render pixels if emulation is in the rewinding state
if tv.emulationState != emulation.Rewinding {
if tv.emulationState != govern.Rewinding {
for _, r := range tv.renderers {
err := r.SetPixels(tv.signals, tv.currentSignalIdx)
if err != nil {
@ -768,23 +768,23 @@ func (tv *Television) SetSpec(spec string) error {
// SetEmulationState is called by emulation whenever state changes. How we
// handle incoming signals depends on the current state.
func (tv *Television) SetEmulationState(state emulation.State) error {
func (tv *Television) SetEmulationState(state govern.State) error {
prev := tv.emulationState
tv.emulationState = state
switch prev {
case emulation.Paused:
case govern.Paused:
// start off the unpaused state by measuring the current framerate.
// this "clears" the ticker channel and means the feedback from
// GetActualFPS() is less misleading
tv.lmtr.measureActual()
case emulation.Rewinding:
case govern.Rewinding:
tv.renderSignals()
}
switch state {
case emulation.Paused:
case govern.Paused:
err := tv.renderSignals()
if err != nil {
return err

View file

@ -22,11 +22,10 @@ import (
"github.com/jetsetilly/gopher2600/cartridgeloader"
"github.com/jetsetilly/gopher2600/curated"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/hardware"
"github.com/jetsetilly/gopher2600/hardware/television"
"github.com/jetsetilly/gopher2600/setup"
"github.com/jetsetilly/gopher2600/userinput"
)
// sentinal error returned by Run() loop.
@ -100,7 +99,7 @@ func Check(output io.Writer, profile Profile, cartload cartridgeloader.Loader, s
performanceBrake := 0
// run until specified time elapses
err = vcs.Run(func() (emulation.State, error) {
err = vcs.Run(func() (govern.State, error) {
for {
performanceBrake++
if performanceBrake >= hardware.PerformanceBrake {
@ -112,7 +111,7 @@ func Check(output io.Writer, profile Profile, cartload cartridgeloader.Loader, s
// period has finished, return false to cause vcs.Run() to
// return
if v {
return emulation.Ending, curated.Errorf(timedOut)
return govern.Ending, curated.Errorf(timedOut)
}
// timerChan has returned false which indicates that the
@ -121,11 +120,11 @@ func Check(output io.Writer, profile Profile, cartload cartridgeloader.Loader, s
// frame.
startFrame = tv.GetCoords().Frame
default:
return emulation.Running, nil
return govern.Running, nil
}
}
return emulation.Running, nil
return govern.Running, nil
}
})
return err
@ -148,38 +147,3 @@ func Check(output io.Writer, profile Profile, cartload cartridgeloader.Loader, s
return nil
}
// stubEmulation is handed to the GUI through ReqSetEmulation. Provides the
// minimum implementation for the Emulation interface.
type stubEmulation struct {
vcs emulation.VCS
tv emulation.TV
}
func (e *stubEmulation) TV() emulation.TV {
return e.tv
}
func (e *stubEmulation) VCS() emulation.VCS {
return e.vcs
}
func (e *stubEmulation) Debugger() emulation.Debugger {
return nil
}
func (e *stubEmulation) UserInput() chan userinput.Event {
return nil
}
func (e *stubEmulation) SetFeature(request emulation.FeatureReq, args ...emulation.FeatureReqData) error {
return nil
}
func (e *stubEmulation) State() emulation.State {
return emulation.Running
}
func (e *stubEmulation) Mode() emulation.Mode {
return emulation.ModePlay
}

View file

@ -17,7 +17,7 @@ package reflection
import (
"github.com/jetsetilly/gopher2600/curated"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/hardware"
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/mapper"
"github.com/jetsetilly/gopher2600/hardware/television"
@ -30,7 +30,7 @@ import (
type Reflector struct {
vcs *hardware.VCS
renderer Renderer
emulationState emulation.State
emulationState govern.State
history []ReflectedVideoStep
@ -57,17 +57,17 @@ func (ref *Reflector) Clear() {
// SetEmulationState is called by emulation whenever state changes. How we
// handle reflections depends on the current state.
func (ref *Reflector) SetEmulationState(state emulation.State) {
func (ref *Reflector) SetEmulationState(state govern.State) {
prev := ref.emulationState
ref.emulationState = state
switch prev {
case emulation.Rewinding:
case govern.Rewinding:
ref.render()
}
switch state {
case emulation.Paused:
case govern.Paused:
err := ref.render()
if err != nil {
logger.Logf("reflection", "%v", err)
@ -125,7 +125,7 @@ func (ref *Reflector) Step(bank mapper.BankInfo) error {
// push history to reflection renderer
func (ref *Reflector) render() error {
if ref.emulationState != emulation.Rewinding {
if ref.emulationState != govern.Rewinding {
if ref.renderer != nil {
if err := ref.renderer.Reflect(ref.history); err != nil {
return curated.Errorf("reflection: %v", err)

View file

@ -26,7 +26,7 @@ import (
"github.com/jetsetilly/gopher2600/cartridgeloader"
"github.com/jetsetilly/gopher2600/curated"
"github.com/jetsetilly/gopher2600/database"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/hardware"
"github.com/jetsetilly/gopher2600/hardware/television"
"github.com/jetsetilly/gopher2600/logger"
@ -160,7 +160,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) (emulation.State, error) {
err = vcs.RunForFrameCount(reg.NumFrames, func(frame int) (govern.State, error) {
// display progress meter every 1 second
select {
case <-tck.C:
@ -170,7 +170,7 @@ func (reg *LogRegression) regress(newRegression bool, output io.Writer, msg stri
logger.WriteRecent(logOutput)
return emulation.Running, nil
return govern.Running, nil
})
if err != nil {

View file

@ -25,8 +25,8 @@ import (
"github.com/jetsetilly/gopher2600/curated"
"github.com/jetsetilly/gopher2600/database"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/digest"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/hardware"
"github.com/jetsetilly/gopher2600/hardware/riot/ports"
"github.com/jetsetilly/gopher2600/hardware/television"
@ -150,13 +150,13 @@ func (reg *PlaybackRegression) regress(newRegression bool, output io.Writer, msg
tck := time.NewTicker(dur)
// run emulation
err = vcs.Run(func() (emulation.State, error) {
err = vcs.Run(func() (govern.State, error) {
hasEnded, err := plb.EndFrame()
if err != nil {
return emulation.Ending, curated.Errorf("playback: %v", err)
return govern.Ending, curated.Errorf("playback: %v", err)
}
if hasEnded {
return emulation.Ending, curated.Errorf("playback: ended unexpectedly")
return govern.Ending, curated.Errorf("playback: ended unexpectedly")
}
// display progress meter every 1 second
@ -165,7 +165,7 @@ func (reg *PlaybackRegression) regress(newRegression bool, output io.Writer, msg
output.Write([]byte(fmt.Sprintf("\r%s [%s]", msg, plb)))
default:
}
return emulation.Running, nil
return govern.Running, nil
})
if err != nil {

View file

@ -27,8 +27,8 @@ import (
"github.com/jetsetilly/gopher2600/cartridgeloader"
"github.com/jetsetilly/gopher2600/curated"
"github.com/jetsetilly/gopher2600/database"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/digest"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/hardware"
"github.com/jetsetilly/gopher2600/hardware/television"
"github.com/jetsetilly/gopher2600/setup"
@ -232,7 +232,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) (emulation.State, error) {
err = vcs.RunForFrameCount(reg.NumFrames, func(frame int) (govern.State, error) {
// display progress meter every 1 second
select {
case <-tck.C:
@ -259,7 +259,7 @@ func (reg *VideoRegression) regress(newRegression bool, output io.Writer, msg st
}
}
return emulation.Running, nil
return govern.Running, nil
})
if err != nil {

View file

@ -20,7 +20,7 @@ import (
"strings"
"github.com/jetsetilly/gopher2600/curated"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/hardware"
"github.com/jetsetilly/gopher2600/hardware/cpu"
"github.com/jetsetilly/gopher2600/hardware/memory"
@ -32,6 +32,13 @@ import (
"github.com/jetsetilly/gopher2600/logger"
)
// Emulation defines as much of the emulation we require access to.
type Emulation interface {
Mode() govern.Mode
State() govern.State
VCS() *hardware.VCS
}
// Runner provides the rewind package the opportunity to run the emulation.
type Runner interface {
// CatchupLoop should loop until the frame/scanline/clock coordinates are
@ -106,7 +113,7 @@ const overhead = 2
// Rewind contains a history of machine states for the emulation.
type Rewind struct {
emulation emulation.Emulation
emulation Emulation
vcs *hardware.VCS
runner Runner
@ -145,10 +152,10 @@ type Rewind struct {
}
// NewRewind is the preferred method of initialisation for the Rewind type.
func NewRewind(emulation emulation.Emulation, runner Runner) (*Rewind, error) {
func NewRewind(emulation Emulation, runner Runner) (*Rewind, error) {
r := &Rewind{
emulation: emulation,
vcs: emulation.VCS().(*hardware.VCS),
vcs: emulation.VCS(),
runner: runner,
}
@ -443,7 +450,7 @@ type findResults struct {
// the one that is requested.
func (r *Rewind) findFrameIndex(frame int) findResults {
searchFrame := frame - 1
if r.emulation.Mode() == emulation.ModeDebugger {
if r.emulation.Mode() == govern.ModeDebugger {
searchFrame--
}

View file

@ -17,7 +17,7 @@ package rewind
import (
"github.com/jetsetilly/gopher2600/curated"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/hardware/television"
"github.com/jetsetilly/gopher2600/hardware/television/specification"
)
@ -160,7 +160,7 @@ func (r *Rewind) GetTimeline() Timeline {
func (r *Rewind) addTimelineEntry(frameInfo television.FrameInfo) {
// do not alter the timeline information if we're in the rewinding state
if r.emulation.State() == emulation.Rewinding {
if r.emulation.State() == govern.Rewinding {
return
}

View file

@ -24,7 +24,7 @@ import (
"github.com/jetsetilly/gopher2600/cartridgeloader"
"github.com/jetsetilly/gopher2600/curated"
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/hardware"
"github.com/jetsetilly/gopher2600/hardware/instance"
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/mapper"
@ -193,17 +193,17 @@ func (thmb *Thumbnailer) CreateFromLoader(cartload cartridgeloader.Loader, numFr
tgtFrame := thmb.vcs.TV.GetCoords().Frame + numFrames
err = thmb.vcs.Run(func() (emulation.State, error) {
err = thmb.vcs.Run(func() (govern.State, error) {
select {
case <-thmb.emulationQuit:
return emulation.Ending, nil
return govern.Ending, nil
default:
}
if numFrames != UndefinedNumFrames && thmb.vcs.TV.GetCoords().Frame >= tgtFrame {
return emulation.Ending, nil
return govern.Ending, nil
}
return emulation.Running, nil
return govern.Running, nil
})
if err != nil {
logger.Logf("thumbnailer", err.Error())
@ -235,17 +235,17 @@ func (thmb *Thumbnailer) SingleFrameFromRewindState(state *rewind.State) {
// run until target frame has been generated
tgtFrame := thmb.vcs.TV.GetCoords().Frame + 1
err := thmb.vcs.Run(func() (emulation.State, error) {
err := thmb.vcs.Run(func() (govern.State, error) {
select {
case <-thmb.emulationQuit:
return emulation.Ending, nil
return govern.Ending, nil
default:
}
if thmb.vcs.TV.GetCoords().Frame >= tgtFrame {
return emulation.Ending, nil
return govern.Ending, nil
}
return emulation.Running, nil
return govern.Running, nil
})
if err != nil {

View file

@ -16,12 +16,18 @@
package tracker
import (
"github.com/jetsetilly/gopher2600/emulation"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/hardware/television"
"github.com/jetsetilly/gopher2600/hardware/television/coords"
"github.com/jetsetilly/gopher2600/hardware/tia/audio"
)
// Emulation defines as much of the emulation we require access to.
type Emulation interface {
State() govern.State
TV() *television.Television
}
type Entry struct {
Coords coords.TelevisionCoords
Channel int
@ -35,7 +41,7 @@ type Entry struct {
// Tracker implements the audio.Tracker interface and keeps a history of the
// audio registers over time.
type Tracker struct {
emulation emulation.Emulation
emulation Emulation
entries []Entry
@ -49,7 +55,7 @@ type Tracker struct {
const maxTrackerEntries = 1024
// NewTracker is the preferred method of initialisation for the Tracker type.
func NewTracker(emulation emulation.Emulation) *Tracker {
func NewTracker(emulation Emulation) *Tracker {
return &Tracker{
emulation: emulation,
entries: make([]Entry, 0, maxTrackerEntries),
@ -63,7 +69,7 @@ func (tr *Tracker) Reset() {
// Tick implements the audio.Tracker interface
func (tr *Tracker) Tick(channel int, reg audio.Registers) {
if tr.emulation.State() == emulation.Rewinding {
if tr.emulation.State() == govern.Rewinding {
return
}
@ -71,7 +77,7 @@ func (tr *Tracker) Tick(channel int, reg audio.Registers) {
tr.prevRegister[channel] = reg
if changed {
tv := tr.emulation.TV().(*television.Television)
tv := tr.emulation.TV()
e := Entry{
Coords: tv.GetCoords(),