From 28ffedbf11e5c4d97fb42c2bb1f1f58068d25038 Mon Sep 17 00:00:00 2001 From: JetSetIlly Date: Sat, 27 Aug 2022 22:14:58 +0100 Subject: [PATCH] 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 --- comparison/comparison.go | 8 +- debugger/commands.go | 10 +- debugger/debugger.go | 96 +++++++++---------- debugger/debugger_test.go | 5 +- debugger/deeppoke.go | 4 +- {emulation => debugger/govern}/doc.go | 17 ++-- .../emulation.go => debugger/govern/govern.go | 83 +++++++--------- debugger/loop_catchup.go | 16 ++-- debugger/loop_debugger.go | 20 ++-- debugger/loop_playmode.go | 16 ++-- debugger/requests.go | 23 +++-- debugger/rewind.go | 44 ++++----- debugger/userinput.go | 26 ++--- emulation/requests.go | 43 --------- gopher2600.go | 22 ++--- gui/sdlimgui/glsl_dbgscr.go | 12 +-- gui/sdlimgui/lazyvalues/debugger.go | 12 +-- gui/sdlimgui/lazyvalues/lazy.go | 22 ++--- gui/sdlimgui/manager.go | 6 +- gui/sdlimgui/manager_menu.go | 4 +- gui/sdlimgui/manager_state.go | 10 +- gui/sdlimgui/playscr.go | 2 +- gui/sdlimgui/playscr_notifications.go | 43 +++++---- gui/sdlimgui/polling.go | 4 +- gui/sdlimgui/preferences.go | 8 +- gui/sdlimgui/requests.go | 6 +- gui/sdlimgui/screen.go | 12 +-- gui/sdlimgui/sdlimgui.go | 43 ++++----- gui/sdlimgui/service.go | 22 ++--- gui/sdlimgui/win_control.go | 10 +- gui/sdlimgui/win_coproc_disasm.go | 4 +- gui/sdlimgui/win_dbgscr.go | 6 +- gui/sdlimgui/win_disasm.go | 8 +- gui/sdlimgui/win_log.go | 4 +- gui/sdlimgui/win_prefs.go | 12 +-- gui/sdlimgui/win_terminal.go | 4 +- gui/sdlimgui/win_tracker.go | 4 +- gui/stub.go | 1 + hardware/run.go | 26 ++--- hardware/television/television.go | 16 ++-- performance/performance.go | 46 +-------- reflection/reflector.go | 12 +-- regression/log.go | 6 +- regression/playback.go | 10 +- regression/video.go | 6 +- rewind/rewind.go | 17 +++- rewind/timeline.go | 4 +- thumbnailer/thumbnailer.go | 18 ++-- tracker/tracker.go | 16 +++- 49 files changed, 384 insertions(+), 485 deletions(-) rename {emulation => debugger/govern}/doc.go (57%) rename emulation/emulation.go => debugger/govern/govern.go (56%) delete mode 100644 emulation/requests.go diff --git a/comparison/comparison.go b/comparison/comparison.go index 6a9ebf69..a63f74e8 100644 --- a/comparison/comparison.go +++ b/comparison/comparison.go @@ -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 diff --git a/debugger/commands.go b/debugger/commands.go index 5ab5c736..3f602861 100644 --- a/debugger/commands.go +++ b/debugger/commands.go @@ -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 { diff --git a/debugger/debugger.go b/debugger/debugger.go index d79f7956..50bbdf06 100644 --- a/debugger/debugger.go +++ b/debugger/debugger.go @@ -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) } }() diff --git a/debugger/debugger_test.go b/debugger/debugger_test.go index eb21c610..3be0bc63 100644 --- a/debugger/debugger_test.go +++ b/debugger/debugger_test.go @@ -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 } diff --git a/debugger/deeppoke.go b/debugger/deeppoke.go index 862f0a60..3f7c9ff7 100644 --- a/debugger/deeppoke.go +++ b/debugger/deeppoke.go @@ -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) }) diff --git a/emulation/doc.go b/debugger/govern/doc.go similarity index 57% rename from emulation/doc.go rename to debugger/govern/doc.go index f81da9f9..6f848eed 100644 --- a/emulation/doc.go +++ b/debugger/govern/doc.go @@ -13,14 +13,11 @@ // You should have received a copy of the GNU General Public License // along with Gopher2600. If not, see . -// 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 diff --git a/emulation/emulation.go b/debugger/govern/govern.go similarity index 56% rename from emulation/emulation.go rename to debugger/govern/govern.go index cfa59870..e1112c9f 100644 --- a/emulation/emulation.go +++ b/debugger/govern/govern.go @@ -13,54 +13,10 @@ // You should have received a copy of the GNU General Public License // along with Gopher2600. If not, see . -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" +) diff --git a/debugger/loop_catchup.go b/debugger/loop_catchup.go index 1c0671e2..d095058d 100644 --- a/debugger/loop_catchup.go +++ b/debugger/loop_catchup.go @@ -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 diff --git a/debugger/loop_debugger.go b/debugger/loop_debugger.go index bb1d5fe8..247a12f4 100644 --- a/debugger/loop_debugger.go +++ b/debugger/loop_debugger.go @@ -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) } } diff --git a/debugger/loop_playmode.go b/debugger/loop_playmode.go index 18228dc8..f22d91f5 100644 --- a/debugger/loop_playmode.go +++ b/debugger/loop_playmode.go @@ -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() } diff --git a/debugger/requests.go b/debugger/requests.go index 5fe66300..3562aef2 100644 --- a/debugger/requests.go +++ b/debugger/requests.go @@ -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()) } diff --git a/debugger/rewind.go b/debugger/rewind.go index dff29904..3f69d695 100644 --- a/debugger/rewind.go +++ b/debugger/rewind.go @@ -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) }) diff --git a/debugger/userinput.go b/debugger/userinput.go index 90687b74..947e4f69 100644 --- a/debugger/userinput.go +++ b/debugger/userinput.go @@ -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 diff --git a/emulation/requests.go b/emulation/requests.go deleted file mode 100644 index bf47299c..00000000 --- a/emulation/requests.go +++ /dev/null @@ -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 . - -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" -) diff --git a/gopher2600.go b/gopher2600.go index 5a0abce1..9712f735 100644 --- a/gopher2600.go +++ b/gopher2600.go @@ -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" } diff --git a/gui/sdlimgui/glsl_dbgscr.go b/gui/sdlimgui/glsl_dbgscr.go index 99c597e8..613a9a23 100644 --- a/gui/sdlimgui/glsl_dbgscr.go +++ b/gui/sdlimgui/glsl_dbgscr.go @@ -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) } } diff --git a/gui/sdlimgui/lazyvalues/debugger.go b/gui/sdlimgui/lazyvalues/debugger.go index 5fef71ce..472900c1 100644 --- a/gui/sdlimgui/lazyvalues/debugger.go +++ b/gui/sdlimgui/lazyvalues/debugger.go @@ -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) } diff --git a/gui/sdlimgui/lazyvalues/lazy.go b/gui/sdlimgui/lazyvalues/lazy.go index b03d138a..bf043a7c 100644 --- a/gui/sdlimgui/lazyvalues/lazy.go +++ b/gui/sdlimgui/lazyvalues/lazy.go @@ -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 } diff --git a/gui/sdlimgui/manager.go b/gui/sdlimgui/manager.go index 6404a6e1..f9a154df 100644 --- a/gui/sdlimgui/manager.go +++ b/gui/sdlimgui/manager.go @@ -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() diff --git a/gui/sdlimgui/manager_menu.go b/gui/sdlimgui/manager_menu.go index d4161493..550d1864 100644 --- a/gui/sdlimgui/manager_menu.go +++ b/gui/sdlimgui/manager_menu.go @@ -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) { diff --git a/gui/sdlimgui/manager_state.go b/gui/sdlimgui/manager_state.go index 9f5c1a17..92e26468 100644 --- a/gui/sdlimgui/manager_state.go +++ b/gui/sdlimgui/manager_state.go @@ -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") } diff --git a/gui/sdlimgui/playscr.go b/gui/sdlimgui/playscr.go index 6b653d29..427edc08 100644 --- a/gui/sdlimgui/playscr.go +++ b/gui/sdlimgui/playscr.go @@ -88,7 +88,7 @@ func newPlayScr(img *SdlImgui) *playScr { rightAlign: true, }, emulationEvent: emulationEventNotification{ - emulation: img.emulation, + emulation: img.dbg, }, } diff --git a/gui/sdlimgui/playscr_notifications.go b/gui/sdlimgui/playscr_notifications.go index b4934454..51a90f25 100644 --- a/gui/sdlimgui/playscr_notifications.go +++ b/gui/sdlimgui/playscr_notifications.go @@ -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)) } diff --git a/gui/sdlimgui/polling.go b/gui/sdlimgui/polling.go index 66921efb..d2a94fa2 100644 --- a/gui/sdlimgui/polling.go +++ b/gui/sdlimgui/polling.go @@ -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 { diff --git a/gui/sdlimgui/preferences.go b/gui/sdlimgui/preferences.go index 98a39025..fdd3a435 100644 --- a/gui/sdlimgui/preferences.go +++ b/gui/sdlimgui/preferences.go @@ -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)) diff --git a/gui/sdlimgui/requests.go b/gui/sdlimgui/requests.go index 02c75737..4a1e727f 100644 --- a/gui/sdlimgui/requests.go +++ b/gui/sdlimgui/requests.go @@ -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)) } } diff --git a/gui/sdlimgui/screen.go b/gui/sdlimgui/screen.go index ad117a9e..025b6190 100644 --- a/gui/sdlimgui/screen.go +++ b/gui/sdlimgui/screen.go @@ -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) diff --git a/gui/sdlimgui/sdlimgui.go b/gui/sdlimgui/sdlimgui.go index 112fa412..910cff66 100644 --- a/gui/sdlimgui/sdlimgui.go +++ b/gui/sdlimgui/sdlimgui.go @@ -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 { diff --git a/gui/sdlimgui/service.go b/gui/sdlimgui/service.go index 713c4a42..8cead1b8 100644 --- a/gui/sdlimgui/service.go +++ b/gui/sdlimgui/service.go @@ -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") diff --git a/gui/sdlimgui/win_control.go b/gui/sdlimgui/win_control.go index bf1a5468..0eca7249 100644 --- a/gui/sdlimgui/win_control.go +++ b/gui/sdlimgui/win_control.go @@ -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) { diff --git a/gui/sdlimgui/win_coproc_disasm.go b/gui/sdlimgui/win_coproc_disasm.go index 24b3f68b..77890217 100644 --- a/gui/sdlimgui/win_coproc_disasm.go +++ b/gui/sdlimgui/win_coproc_disasm.go @@ -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) diff --git a/gui/sdlimgui/win_dbgscr.go b/gui/sdlimgui/win_dbgscr.go index 34aa6bdf..41ebae7e 100644 --- a/gui/sdlimgui/win_dbgscr.go +++ b/gui/sdlimgui/win_dbgscr.go @@ -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") diff --git a/gui/sdlimgui/win_disasm.go b/gui/sdlimgui/win_disasm.go index f44b492a..50e8a36b 100644 --- a/gui/sdlimgui/win_disasm.go +++ b/gui/sdlimgui/win_disasm.go @@ -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 diff --git a/gui/sdlimgui/win_log.go b/gui/sdlimgui/win_log.go index 68eaf409..153cc85c 100644 --- a/gui/sdlimgui/win_log.go +++ b/gui/sdlimgui/win_log.go @@ -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) } diff --git a/gui/sdlimgui/win_prefs.go b/gui/sdlimgui/win_prefs.go index 3731937a..5e228ecd 100644 --- a/gui/sdlimgui/win_prefs.go +++ b/gui/sdlimgui/win_prefs.go @@ -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) diff --git a/gui/sdlimgui/win_terminal.go b/gui/sdlimgui/win_terminal.go index 4c43efc7..647ba61b 100644 --- a/gui/sdlimgui/win_terminal.go +++ b/gui/sdlimgui/win_terminal.go @@ -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 { diff --git a/gui/sdlimgui/win_tracker.go b/gui/sdlimgui/win_tracker.go index 53d31b2c..6103664a 100644 --- a/gui/sdlimgui/win_tracker.go +++ b/gui/sdlimgui/win_tracker.go @@ -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) } } diff --git a/gui/stub.go b/gui/stub.go index 5351f787..077c27cb 100644 --- a/gui/stub.go +++ b/gui/stub.go @@ -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. diff --git a/hardware/run.go b/hardware/run.go index 3192086b..cc67cebb 100644 --- a/hardware/run.go +++ b/hardware/run.go @@ -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 diff --git a/hardware/television/television.go b/hardware/television/television.go index 4954fa91..f45bdb34 100644 --- a/hardware/television/television.go +++ b/hardware/television/television.go @@ -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 diff --git a/performance/performance.go b/performance/performance.go index 55424090..96bd314a 100644 --- a/performance/performance.go +++ b/performance/performance.go @@ -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 -} diff --git a/reflection/reflector.go b/reflection/reflector.go index e29fb9af..7e31b9aa 100644 --- a/reflection/reflector.go +++ b/reflection/reflector.go @@ -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) diff --git a/regression/log.go b/regression/log.go index 7f44e194..9d0c565a 100644 --- a/regression/log.go +++ b/regression/log.go @@ -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 { diff --git a/regression/playback.go b/regression/playback.go index 7c241461..d08bb198 100644 --- a/regression/playback.go +++ b/regression/playback.go @@ -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 { diff --git a/regression/video.go b/regression/video.go index 36dd3a2a..3672b1ba 100644 --- a/regression/video.go +++ b/regression/video.go @@ -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 { diff --git a/rewind/rewind.go b/rewind/rewind.go index 859179af..0630014b 100644 --- a/rewind/rewind.go +++ b/rewind/rewind.go @@ -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-- } diff --git a/rewind/timeline.go b/rewind/timeline.go index 91a44ef5..5c22cb5c 100644 --- a/rewind/timeline.go +++ b/rewind/timeline.go @@ -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 } diff --git a/thumbnailer/thumbnailer.go b/thumbnailer/thumbnailer.go index 2a4fb720..bfc4cb18 100644 --- a/thumbnailer/thumbnailer.go +++ b/thumbnailer/thumbnailer.go @@ -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 { diff --git a/tracker/tracker.go b/tracker/tracker.go index 2dc7f4e6..ed622df5 100644 --- a/tracker/tracker.go +++ b/tracker/tracker.go @@ -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(),