mirror of
https://github.com/JetSetIlly/Gopher2600.git
synced 2024-06-02 20:18:20 -04:00
removed emulation package. moved types to debugger/govern package
the emulation package has been unecessary since the amalgamation of the debugger and play modes. in order to allow switching between the two modes it was necessary to remove the playmode package and to move all playmode loops and other considerations into the debugger package. as a result the abstraction offered by the emulation package is uncessary
This commit is contained in:
parent
faddd7dfb9
commit
28ffedbf11
|
@ -24,7 +24,7 @@ import (
|
||||||
|
|
||||||
"github.com/jetsetilly/gopher2600/cartridgeloader"
|
"github.com/jetsetilly/gopher2600/cartridgeloader"
|
||||||
"github.com/jetsetilly/gopher2600/curated"
|
"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"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/instance"
|
"github.com/jetsetilly/gopher2600/hardware/instance"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/mapper"
|
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/mapper"
|
||||||
|
@ -207,14 +207,14 @@ func (cmp *Comparison) CreateFromLoader(cartload cartridgeloader.Loader) error {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = cmp.VCS.Run(func() (emulation.State, error) {
|
err = cmp.VCS.Run(func() (govern.State, error) {
|
||||||
select {
|
select {
|
||||||
case <-cmp.emulationQuit:
|
case <-cmp.emulationQuit:
|
||||||
return emulation.Ending, nil
|
return govern.Ending, nil
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
return emulation.Running, nil
|
return govern.Running, nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmp.driver.quit <- err
|
cmp.driver.quit <- err
|
||||||
|
|
|
@ -27,12 +27,12 @@ import (
|
||||||
"github.com/jetsetilly/gopher2600/coprocessor/developer"
|
"github.com/jetsetilly/gopher2600/coprocessor/developer"
|
||||||
"github.com/jetsetilly/gopher2600/curated"
|
"github.com/jetsetilly/gopher2600/curated"
|
||||||
"github.com/jetsetilly/gopher2600/debugger/dbgmem"
|
"github.com/jetsetilly/gopher2600/debugger/dbgmem"
|
||||||
|
"github.com/jetsetilly/gopher2600/debugger/govern"
|
||||||
"github.com/jetsetilly/gopher2600/debugger/script"
|
"github.com/jetsetilly/gopher2600/debugger/script"
|
||||||
"github.com/jetsetilly/gopher2600/debugger/terminal"
|
"github.com/jetsetilly/gopher2600/debugger/terminal"
|
||||||
"github.com/jetsetilly/gopher2600/debugger/terminal/commandline"
|
"github.com/jetsetilly/gopher2600/debugger/terminal/commandline"
|
||||||
"github.com/jetsetilly/gopher2600/disassembly"
|
"github.com/jetsetilly/gopher2600/disassembly"
|
||||||
"github.com/jetsetilly/gopher2600/disassembly/symbols"
|
"github.com/jetsetilly/gopher2600/disassembly/symbols"
|
||||||
"github.com/jetsetilly/gopher2600/emulation"
|
|
||||||
"github.com/jetsetilly/gopher2600/gui"
|
"github.com/jetsetilly/gopher2600/gui"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/cpu/registers"
|
"github.com/jetsetilly/gopher2600/hardware/cpu/registers"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/plusrom"
|
"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)
|
coords = dbg.vcs.TV.AdjCoords(adj, adjAmount)
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg.setState(emulation.Rewinding)
|
dbg.setState(govern.Rewinding)
|
||||||
dbg.unwindLoop(func() error {
|
dbg.unwindLoop(func() error {
|
||||||
// update catchupQuantum before starting rewind process
|
// update catchupQuantum before starting rewind process
|
||||||
dbg.catchupQuantum = dbg.stepQuantum
|
dbg.catchupQuantum = dbg.stepQuantum
|
||||||
|
@ -380,13 +380,13 @@ func (dbg *Debugger) processTokens(tokens *commandline.Tokens) error {
|
||||||
dbg.runUntilHalt = false
|
dbg.runUntilHalt = false
|
||||||
|
|
||||||
if arg == "LAST" {
|
if arg == "LAST" {
|
||||||
dbg.setState(emulation.Rewinding)
|
dbg.setState(govern.Rewinding)
|
||||||
dbg.unwindLoop(dbg.Rewind.GotoLast)
|
dbg.unwindLoop(dbg.Rewind.GotoLast)
|
||||||
} else if arg == "SUMMARY" {
|
} else if arg == "SUMMARY" {
|
||||||
dbg.printLine(terminal.StyleInstrument, dbg.Rewind.String())
|
dbg.printLine(terminal.StyleInstrument, dbg.Rewind.String())
|
||||||
} else {
|
} else {
|
||||||
frame, _ := strconv.Atoi(arg)
|
frame, _ := strconv.Atoi(arg)
|
||||||
dbg.setState(emulation.Rewinding)
|
dbg.setState(govern.Rewinding)
|
||||||
dbg.unwindLoop(func() error {
|
dbg.unwindLoop(func() error {
|
||||||
err := dbg.Rewind.GotoFrame(frame)
|
err := dbg.Rewind.GotoFrame(frame)
|
||||||
if err != nil {
|
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 {
|
dbg.unwindLoop(func() error {
|
||||||
err := dbg.Rewind.GotoCoords(coords)
|
err := dbg.Rewind.GotoCoords(coords)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -30,11 +30,11 @@ import (
|
||||||
coprocDisasm "github.com/jetsetilly/gopher2600/coprocessor/disassembly"
|
coprocDisasm "github.com/jetsetilly/gopher2600/coprocessor/disassembly"
|
||||||
"github.com/jetsetilly/gopher2600/curated"
|
"github.com/jetsetilly/gopher2600/curated"
|
||||||
"github.com/jetsetilly/gopher2600/debugger/dbgmem"
|
"github.com/jetsetilly/gopher2600/debugger/dbgmem"
|
||||||
|
"github.com/jetsetilly/gopher2600/debugger/govern"
|
||||||
"github.com/jetsetilly/gopher2600/debugger/script"
|
"github.com/jetsetilly/gopher2600/debugger/script"
|
||||||
"github.com/jetsetilly/gopher2600/debugger/terminal"
|
"github.com/jetsetilly/gopher2600/debugger/terminal"
|
||||||
"github.com/jetsetilly/gopher2600/debugger/terminal/commandline"
|
"github.com/jetsetilly/gopher2600/debugger/terminal/commandline"
|
||||||
"github.com/jetsetilly/gopher2600/disassembly"
|
"github.com/jetsetilly/gopher2600/disassembly"
|
||||||
"github.com/jetsetilly/gopher2600/emulation"
|
|
||||||
"github.com/jetsetilly/gopher2600/gui"
|
"github.com/jetsetilly/gopher2600/gui"
|
||||||
"github.com/jetsetilly/gopher2600/hardware"
|
"github.com/jetsetilly/gopher2600/hardware"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/cpu/execution"
|
"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
|
// CreateUserInterface is used to initialise the user interface used by the
|
||||||
// emulation. It returns an instance of both the GUI and Terminal interfaces
|
// emulation. It returns an instance of both the GUI and Terminal interfaces
|
||||||
// in the repsective packages.
|
// 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
|
// NewDebugger creates and initialises everything required for a new debugging
|
||||||
// session.
|
// 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
|
// 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
|
// 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)
|
// anyone has a change to call State() or Mode() from another thread)
|
||||||
dbg.state.Store(emulation.EmulatorStart)
|
dbg.state.Store(govern.EmulatorStart)
|
||||||
dbg.mode.Store(emulation.ModeNone)
|
dbg.mode.Store(govern.ModeNone)
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
@ -449,17 +449,17 @@ func NewDebugger(opts CommandLineOptions, create CreateUserInterface) (*Debugger
|
||||||
}
|
}
|
||||||
|
|
||||||
// VCS implements the emulation.Emulation interface.
|
// VCS implements the emulation.Emulation interface.
|
||||||
func (dbg *Debugger) VCS() emulation.VCS {
|
func (dbg *Debugger) VCS() *hardware.VCS {
|
||||||
return dbg.vcs
|
return dbg.vcs
|
||||||
}
|
}
|
||||||
|
|
||||||
// TV implements the emulation.Emulation interface.
|
// TV implements the emulation.Emulation interface.
|
||||||
func (dbg *Debugger) TV() emulation.TV {
|
func (dbg *Debugger) TV() *television.Television {
|
||||||
return dbg.vcs.TV
|
return dbg.vcs.TV
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debugger implements the emulation.Emulation interface.
|
// Debugger implements the emulation.Emulation interface.
|
||||||
func (dbg *Debugger) Debugger() emulation.Debugger {
|
func (dbg *Debugger) Debugger() *Debugger {
|
||||||
return dbg
|
return dbg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -469,13 +469,13 @@ func (dbg *Debugger) UserInput() chan userinput.Event {
|
||||||
}
|
}
|
||||||
|
|
||||||
// State implements the emulation.Emulation interface.
|
// State implements the emulation.Emulation interface.
|
||||||
func (dbg *Debugger) State() emulation.State {
|
func (dbg *Debugger) State() govern.State {
|
||||||
return dbg.state.Load().(emulation.State)
|
return dbg.state.Load().(govern.State)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mode implements the emulation.Emulation interface.
|
// Mode implements the emulation.Emulation interface.
|
||||||
func (dbg *Debugger) Mode() emulation.Mode {
|
func (dbg *Debugger) Mode() govern.Mode {
|
||||||
return dbg.mode.Load().(emulation.Mode)
|
return dbg.mode.Load().(govern.Mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the emulation state
|
// set the emulation state
|
||||||
|
@ -484,7 +484,7 @@ func (dbg *Debugger) Mode() emulation.Mode {
|
||||||
// debugger.SetFeature(ReqSetPause) even from within the debugger package
|
// debugger.SetFeature(ReqSetPause) even from within the debugger package
|
||||||
// (SetFeature() puts the request on the RawEvent Queue meaning it will be
|
// (SetFeature() puts the request on the RawEvent Queue meaning it will be
|
||||||
// inserted in the input loop correctly)
|
// inserted in the input loop correctly)
|
||||||
func (dbg *Debugger) setState(state emulation.State) {
|
func (dbg *Debugger) setState(state govern.State) {
|
||||||
dbg.setStateQuiet(state, false)
|
dbg.setStateQuiet(state, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,8 +493,8 @@ func (dbg *Debugger) setState(state emulation.State) {
|
||||||
//
|
//
|
||||||
// * see setState() comment, although debugger.SetFeature(ReqSetPause) will
|
// * see setState() comment, although debugger.SetFeature(ReqSetPause) will
|
||||||
// always be "noisy"
|
// always be "noisy"
|
||||||
func (dbg *Debugger) setStateQuiet(state emulation.State, quiet bool) {
|
func (dbg *Debugger) setStateQuiet(state govern.State, quiet bool) {
|
||||||
if state == emulation.Rewinding {
|
if state == govern.Rewinding {
|
||||||
dbg.vcs.Mem.Cart.BreakpointsDisable(true)
|
dbg.vcs.Mem.Cart.BreakpointsDisable(true)
|
||||||
dbg.endPlayback()
|
dbg.endPlayback()
|
||||||
dbg.endRecording()
|
dbg.endRecording()
|
||||||
|
@ -533,15 +533,15 @@ func (dbg *Debugger) setStateQuiet(state emulation.State, quiet bool) {
|
||||||
prevState := dbg.State()
|
prevState := dbg.State()
|
||||||
dbg.state.Store(state)
|
dbg.state.Store(state)
|
||||||
|
|
||||||
if !quiet && dbg.Mode() == emulation.ModePlay {
|
if !quiet && dbg.Mode() == govern.ModePlay {
|
||||||
switch state {
|
switch state {
|
||||||
case emulation.Initialising:
|
case govern.Initialising:
|
||||||
dbg.gui.SetFeature(gui.ReqEmulationEvent, emulation.EventInitialising)
|
dbg.gui.SetFeature(gui.ReqEmulationEvent, govern.EventInitialising)
|
||||||
case emulation.Paused:
|
case govern.Paused:
|
||||||
dbg.gui.SetFeature(gui.ReqEmulationEvent, emulation.EventPause)
|
dbg.gui.SetFeature(gui.ReqEmulationEvent, govern.EventPause)
|
||||||
case emulation.Running:
|
case govern.Running:
|
||||||
if prevState > emulation.Initialising {
|
if prevState > govern.Initialising {
|
||||||
dbg.gui.SetFeature(gui.ReqEmulationEvent, emulation.EventRun)
|
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
|
// * consider using debugger.SetFeature(ReqSetMode) even from within the
|
||||||
// debugger package (SetFeature() puts the request on the RawEvent Queue
|
// debugger package (SetFeature() puts the request on the RawEvent Queue
|
||||||
// meaning it will be inserted in the input loop correctly)
|
// 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 {
|
if dbg.Mode() == mode {
|
||||||
return nil
|
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
|
// however, because the user has asked to switch to playmode we should
|
||||||
// cause the debugger mode to run until the halting condition is matched
|
// cause the debugger mode to run until the halting condition is matched
|
||||||
// (which we know will occur in the almost immediate future)
|
// (which we know will occur in the almost immediate future)
|
||||||
if mode == emulation.ModePlay && !dbg.halting.allowPlaymode() {
|
if mode == govern.ModePlay && !dbg.halting.allowPlaymode() {
|
||||||
if dbg.Mode() == emulation.ModeDebugger {
|
if dbg.Mode() == govern.ModeDebugger {
|
||||||
dbg.runUntilHalt = true
|
dbg.runUntilHalt = true
|
||||||
dbg.continueEmulation = true
|
dbg.continueEmulation = true
|
||||||
}
|
}
|
||||||
|
@ -601,26 +601,26 @@ func (dbg *Debugger) setMode(mode emulation.Mode) error {
|
||||||
// screen.go)
|
// screen.go)
|
||||||
|
|
||||||
switch dbg.Mode() {
|
switch dbg.Mode() {
|
||||||
case emulation.ModePlay:
|
case govern.ModePlay:
|
||||||
dbg.vcs.TV.AddFrameTrigger(dbg.Rewind)
|
dbg.vcs.TV.AddFrameTrigger(dbg.Rewind)
|
||||||
dbg.vcs.TV.AddFrameTrigger(dbg.counter)
|
dbg.vcs.TV.AddFrameTrigger(dbg.counter)
|
||||||
|
|
||||||
// simple detection of whether cartridge is ejected when switching to
|
// simple detection of whether cartridge is ejected when switching to
|
||||||
// playmode. if it is ejected then open ROM selected.
|
// 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()
|
err = dbg.forceROMSelector()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return curated.Errorf("debugger: %v", err)
|
return curated.Errorf("debugger: %v", err)
|
||||||
}
|
}
|
||||||
} else {
|
} 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.Rewind)
|
||||||
dbg.vcs.TV.AddFrameTrigger(dbg.ref)
|
dbg.vcs.TV.AddFrameTrigger(dbg.ref)
|
||||||
dbg.vcs.TV.AddFrameTrigger(dbg.counter)
|
dbg.vcs.TV.AddFrameTrigger(dbg.counter)
|
||||||
dbg.setState(emulation.Paused)
|
dbg.setState(govern.Paused)
|
||||||
|
|
||||||
// debugger needs knowledge about previous frames (via the reflector)
|
// debugger needs knowledge about previous frames (via the reflector)
|
||||||
// if we're moving from playmode. also we want to make sure we end on
|
// 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
|
// catchupEndAdj we will always enter the debugger on the last cycle of
|
||||||
// an instruction. although correct in terms of coordinates, is
|
// an instruction. although correct in terms of coordinates, is
|
||||||
// confusing.
|
// confusing.
|
||||||
if prevMode == emulation.ModePlay {
|
if prevMode == govern.ModePlay {
|
||||||
dbg.catchupEndAdj = true
|
dbg.catchupEndAdj = true
|
||||||
dbg.RerunLastNFrames(2)
|
dbg.RerunLastNFrames(2)
|
||||||
}
|
}
|
||||||
|
@ -692,7 +692,7 @@ func (dbg *Debugger) StartInDebugMode(filename string) error {
|
||||||
return curated.Errorf("debugger: %v", err)
|
return curated.Errorf("debugger: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = dbg.setMode(emulation.ModeDebugger)
|
err = dbg.setMode(govern.ModeDebugger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return curated.Errorf("debugger: %v", err)
|
return curated.Errorf("debugger: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -808,7 +808,7 @@ func (dbg *Debugger) StartInPlayMode(filename string) error {
|
||||||
return curated.Errorf("debugger: %v", err)
|
return curated.Errorf("debugger: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = dbg.setMode(emulation.ModePlay)
|
err = dbg.setMode(govern.ModePlay)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return curated.Errorf("debugger: %v", err)
|
return curated.Errorf("debugger: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -842,7 +842,7 @@ func (dbg *Debugger) run() error {
|
||||||
// inputloop will continue until debugger is to be terminated
|
// inputloop will continue until debugger is to be terminated
|
||||||
for dbg.running {
|
for dbg.running {
|
||||||
switch dbg.Mode() {
|
switch dbg.Mode() {
|
||||||
case emulation.ModePlay:
|
case govern.ModePlay:
|
||||||
err := dbg.playLoop()
|
err := dbg.playLoop()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// if we ever encounter a cartridge ejected error in playmode
|
// 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)
|
return curated.Errorf("debugger: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case emulation.ModeDebugger:
|
case govern.ModeDebugger:
|
||||||
switch dbg.State() {
|
switch dbg.State() {
|
||||||
case emulation.Running:
|
case govern.Running:
|
||||||
dbg.runUntilHalt = true
|
dbg.runUntilHalt = true
|
||||||
dbg.continueEmulation = true
|
dbg.continueEmulation = true
|
||||||
case emulation.Paused:
|
case govern.Paused:
|
||||||
dbg.haltImmediately = true
|
dbg.haltImmediately = true
|
||||||
case emulation.Rewinding:
|
case govern.Rewinding:
|
||||||
default:
|
default:
|
||||||
return curated.Errorf("emulation state not supported on *start* of debugging loop: %s", dbg.State())
|
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)
|
return curated.Errorf("debugger: %v", err)
|
||||||
}
|
}
|
||||||
dbg.unwindLoopRestart = nil
|
dbg.unwindLoopRestart = nil
|
||||||
} else if dbg.State() == emulation.Ending {
|
} else if dbg.State() == govern.Ending {
|
||||||
dbg.running = false
|
dbg.running = false
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -948,19 +948,19 @@ func (dbg *Debugger) attachCartridge(cartload cartridgeloader.Loader) (e error)
|
||||||
dbg.bots.Quit()
|
dbg.bots.Quit()
|
||||||
|
|
||||||
// attching a cartridge implies the initialise state
|
// attching a cartridge implies the initialise state
|
||||||
dbg.setState(emulation.Initialising)
|
dbg.setState(govern.Initialising)
|
||||||
|
|
||||||
// set state after initialisation according to the emulation mode
|
// set state after initialisation according to the emulation mode
|
||||||
defer func() {
|
defer func() {
|
||||||
switch dbg.Mode() {
|
switch dbg.Mode() {
|
||||||
case emulation.ModeDebugger:
|
case govern.ModeDebugger:
|
||||||
if dbg.runUntilHalt && e == nil {
|
if dbg.runUntilHalt && e == nil {
|
||||||
dbg.setState(emulation.Running)
|
dbg.setState(govern.Running)
|
||||||
} else {
|
} else {
|
||||||
dbg.setState(emulation.Paused)
|
dbg.setState(govern.Paused)
|
||||||
}
|
}
|
||||||
case emulation.ModePlay:
|
case govern.ModePlay:
|
||||||
dbg.setState(emulation.Running)
|
dbg.setState(govern.Running)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -1224,12 +1224,12 @@ func (dbg *Debugger) endComparison() {
|
||||||
|
|
||||||
func (dbg *Debugger) hotload() (e error) {
|
func (dbg *Debugger) hotload() (e error) {
|
||||||
// tell GUI that we're in the initialistion phase
|
// tell GUI that we're in the initialistion phase
|
||||||
dbg.setState(emulation.Initialising)
|
dbg.setState(govern.Initialising)
|
||||||
defer func() {
|
defer func() {
|
||||||
if dbg.runUntilHalt && e == nil {
|
if dbg.runUntilHalt && e == nil {
|
||||||
dbg.setState(emulation.Running)
|
dbg.setState(govern.Running)
|
||||||
} else {
|
} else {
|
||||||
dbg.gui.SetFeature(gui.ReqEmulationEvent, emulation.EventPause)
|
dbg.gui.SetFeature(gui.ReqEmulationEvent, govern.EventPause)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@ import (
|
||||||
|
|
||||||
"github.com/jetsetilly/gopher2600/debugger"
|
"github.com/jetsetilly/gopher2600/debugger"
|
||||||
"github.com/jetsetilly/gopher2600/debugger/terminal"
|
"github.com/jetsetilly/gopher2600/debugger/terminal"
|
||||||
"github.com/jetsetilly/gopher2600/emulation"
|
|
||||||
"github.com/jetsetilly/gopher2600/gui"
|
"github.com/jetsetilly/gopher2600/gui"
|
||||||
"github.com/jetsetilly/gopher2600/prefs"
|
"github.com/jetsetilly/gopher2600/prefs"
|
||||||
)
|
)
|
||||||
|
@ -143,7 +142,7 @@ func TestDebugger_withNonExistantInitScript(t *testing.T) {
|
||||||
|
|
||||||
var trm *mockTerm
|
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)
|
trm = newMockTerm(t)
|
||||||
return &mockGUI{}, trm, nil
|
return &mockGUI{}, trm, nil
|
||||||
}
|
}
|
||||||
|
@ -166,7 +165,7 @@ func TestDebugger(t *testing.T) {
|
||||||
|
|
||||||
var trm *mockTerm
|
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)
|
trm = newMockTerm(t)
|
||||||
return &mockGUI{}, trm, nil
|
return &mockGUI{}, trm, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/jetsetilly/gopher2600/curated"
|
"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/instructions"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/cpu/registers"
|
"github.com/jetsetilly/gopher2600/hardware/cpu/registers"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/memory"
|
"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.PushRawEventImmediate(func() {
|
||||||
dbg.setStateQuiet(emulation.Rewinding, true)
|
dbg.setStateQuiet(govern.Rewinding, true)
|
||||||
dbg.unwindLoop(doDeepPoke)
|
dbg.unwindLoop(doDeepPoke)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -13,14 +13,11 @@
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Gopher2600. If not, see <https://www.gnu.org/licenses/>.
|
// along with Gopher2600. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
// Package emulation is an abstraction of the various modes Gopher2600 can
|
// Package govern defines the types that define the current condition of the
|
||||||
// operate in, principally play-mode and the debugger.
|
// emulation. The three conditions are Mode, State and Event.
|
||||||
//
|
//
|
||||||
// It is useful when linking packages/types that require a *passive* knowledge
|
// Also defined is the method of requesting a state change from the GUI. Most
|
||||||
// of the emulation. For example, a GUI might want to know what the current
|
// often state change comes from the emulation but in some intances it is
|
||||||
// state of the emulation is.
|
// necessary to instruct the emulation to change mode or state - for example,
|
||||||
//
|
// from the GUI as a result of the a user request.
|
||||||
// Some package types might still need an active knowledge of the emulation
|
package govern
|
||||||
// however. In which case, simply relying on the Emulation interface is
|
|
||||||
// probably not enough.
|
|
||||||
package emulation
|
|
|
@ -13,54 +13,10 @@
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Gopher2600. If not, see <https://www.gnu.org/licenses/>.
|
// along with Gopher2600. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package emulation
|
package govern
|
||||||
|
|
||||||
import (
|
// Mode inidicates the broad features of the emulation. Currently defined to be
|
||||||
"github.com/jetsetilly/gopher2600/userinput"
|
// debugger and play.
|
||||||
)
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
type Mode int
|
type Mode int
|
||||||
|
|
||||||
func (m Mode) String() string {
|
func (m Mode) String() string {
|
||||||
|
@ -112,9 +68,9 @@ const (
|
||||||
Ending
|
Ending
|
||||||
)
|
)
|
||||||
|
|
||||||
// Event describes an event that might occur in the emulation which is outside
|
// Event is something that happens to change the state of the emulation. For
|
||||||
// of the scope of the VCS. For example, when the emulation is paused an
|
// example, the user presses the pause while playing game. This will cause the
|
||||||
// EventPause can be sent to the GUI (see FeatureReq type in the gui package).
|
// GUI to send an EventPause event to the emulation.
|
||||||
type Event int
|
type Event int
|
||||||
|
|
||||||
// List of defined events.
|
// List of defined events.
|
||||||
|
@ -130,3 +86,30 @@ const (
|
||||||
EventMute
|
EventMute
|
||||||
EventUnmute
|
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"
|
||||||
|
)
|
|
@ -16,7 +16,7 @@
|
||||||
package debugger
|
package debugger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/jetsetilly/gopher2600/emulation"
|
"github.com/jetsetilly/gopher2600/debugger/govern"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/television/coords"
|
"github.com/jetsetilly/gopher2600/hardware/television/coords"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -26,25 +26,25 @@ import (
|
||||||
// required for catchupLoop().
|
// required for catchupLoop().
|
||||||
func (dbg *Debugger) CatchUpLoop(tgt coords.TelevisionCoords) error {
|
func (dbg *Debugger) CatchUpLoop(tgt coords.TelevisionCoords) error {
|
||||||
switch dbg.Mode() {
|
switch dbg.Mode() {
|
||||||
case emulation.ModePlay:
|
case govern.ModePlay:
|
||||||
fpscap := dbg.vcs.TV.SetFPSCap(false)
|
fpscap := dbg.vcs.TV.SetFPSCap(false)
|
||||||
defer dbg.vcs.TV.SetFPSCap(fpscap)
|
defer dbg.vcs.TV.SetFPSCap(fpscap)
|
||||||
|
|
||||||
dbg.vcs.Run(func() (emulation.State, error) {
|
dbg.vcs.Run(func() (govern.State, error) {
|
||||||
dbg.userInputHandler_catchUpLoop()
|
dbg.userInputHandler_catchUpLoop()
|
||||||
|
|
||||||
coords := dbg.vcs.TV.GetCoords()
|
coords := dbg.vcs.TV.GetCoords()
|
||||||
if coords.Frame >= tgt.Frame {
|
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
|
// turn off TV's fps frame limiter
|
||||||
fpsCap := dbg.vcs.TV.SetFPSCap(false)
|
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 {
|
dbg.catchupContinue = func() bool {
|
||||||
newCoords := dbg.vcs.TV.GetCoords()
|
newCoords := dbg.vcs.TV.GetCoords()
|
||||||
|
@ -69,7 +69,7 @@ func (dbg *Debugger) CatchUpLoop(tgt coords.TelevisionCoords) error {
|
||||||
dbg.vcs.TV.SetFPSCap(fpsCap)
|
dbg.vcs.TV.SetFPSCap(fpsCap)
|
||||||
dbg.catchupContinue = nil
|
dbg.catchupContinue = nil
|
||||||
dbg.catchupEnd = nil
|
dbg.catchupEnd = nil
|
||||||
dbg.setState(emulation.Paused)
|
dbg.setState(govern.Paused)
|
||||||
dbg.runUntilHalt = false
|
dbg.runUntilHalt = false
|
||||||
dbg.continueEmulation = dbg.catchupEndAdj
|
dbg.continueEmulation = dbg.catchupEndAdj
|
||||||
dbg.catchupEndAdj = false
|
dbg.catchupEndAdj = false
|
||||||
|
|
|
@ -19,9 +19,9 @@ import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/jetsetilly/gopher2600/curated"
|
"github.com/jetsetilly/gopher2600/curated"
|
||||||
|
"github.com/jetsetilly/gopher2600/debugger/govern"
|
||||||
"github.com/jetsetilly/gopher2600/debugger/script"
|
"github.com/jetsetilly/gopher2600/debugger/script"
|
||||||
"github.com/jetsetilly/gopher2600/debugger/terminal"
|
"github.com/jetsetilly/gopher2600/debugger/terminal"
|
||||||
"github.com/jetsetilly/gopher2600/emulation"
|
|
||||||
"github.com/jetsetilly/gopher2600/hardware/cpu"
|
"github.com/jetsetilly/gopher2600/hardware/cpu"
|
||||||
"github.com/jetsetilly/gopher2600/logger"
|
"github.com/jetsetilly/gopher2600/logger"
|
||||||
)
|
)
|
||||||
|
@ -35,7 +35,7 @@ import (
|
||||||
// function is being called.
|
// function is being called.
|
||||||
//
|
//
|
||||||
// note that the debugger state is not changed by this function. it is up to
|
// 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) {
|
func (dbg *Debugger) unwindLoop(onRestart func() error) {
|
||||||
dbg.unwindLoopRestart = onRestart
|
dbg.unwindLoopRestart = onRestart
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ func (dbg *Debugger) catchupLoop(inputter terminal.Input) error {
|
||||||
if !dbg.vcs.CPU.LastResult.Final {
|
if !dbg.vcs.CPU.LastResult.Final {
|
||||||
// if we're in the rewinding state then a new rewind event has
|
// if we're in the rewinding state then a new rewind event has
|
||||||
// started and we must return immediately so that it can continue
|
// started and we must return immediately so that it can continue
|
||||||
if dbg.State() == emulation.Rewinding {
|
if dbg.State() == govern.Rewinding {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ func (dbg *Debugger) inputLoop(inputter terminal.Input, isVideoStep bool) error
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
for dbg.running {
|
for dbg.running {
|
||||||
if dbg.Mode() != emulation.ModeDebugger {
|
if dbg.Mode() != govern.ModeDebugger {
|
||||||
return nil
|
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
|
// emulation has been put into a different mode. exit loop immediately
|
||||||
if dbg.Mode() != emulation.ModeDebugger {
|
if dbg.Mode() != govern.ModeDebugger {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,7 +278,7 @@ func (dbg *Debugger) inputLoop(inputter terminal.Input, isVideoStep bool) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// set pause emulation state
|
// 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
|
// take note of current machine state if the emulation was in a running
|
||||||
// state and is halting just now
|
// 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
|
// emulation has been put into a different mode. exit loop immediately
|
||||||
if dbg.Mode() != emulation.ModeDebugger {
|
if dbg.Mode() != govern.ModeDebugger {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,10 +351,10 @@ func (dbg *Debugger) inputLoop(inputter terminal.Input, isVideoStep bool) error
|
||||||
// stepping.
|
// stepping.
|
||||||
if dbg.halting.volatileTraps.isEmpty() {
|
if dbg.halting.volatileTraps.isEmpty() {
|
||||||
if inputter.IsInteractive() {
|
if inputter.IsInteractive() {
|
||||||
dbg.setState(emulation.Running)
|
dbg.setState(govern.Running)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dbg.setState(emulation.Stepping)
|
dbg.setState(govern.Stepping)
|
||||||
}
|
}
|
||||||
|
|
||||||
// update comparison point before execution continues
|
// update comparison point before execution continues
|
||||||
|
@ -362,7 +362,7 @@ func (dbg *Debugger) inputLoop(inputter terminal.Input, isVideoStep bool) error
|
||||||
dbg.Rewind.SetComparison()
|
dbg.Rewind.SetComparison()
|
||||||
}
|
}
|
||||||
} else if inputter.IsInteractive() {
|
} else if inputter.IsInteractive() {
|
||||||
dbg.setState(emulation.Stepping)
|
dbg.setState(govern.Stepping)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,8 @@ package debugger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/jetsetilly/gopher2600/curated"
|
"github.com/jetsetilly/gopher2600/curated"
|
||||||
|
"github.com/jetsetilly/gopher2600/debugger/govern"
|
||||||
"github.com/jetsetilly/gopher2600/debugger/terminal"
|
"github.com/jetsetilly/gopher2600/debugger/terminal"
|
||||||
"github.com/jetsetilly/gopher2600/emulation"
|
|
||||||
"github.com/jetsetilly/gopher2600/gui"
|
"github.com/jetsetilly/gopher2600/gui"
|
||||||
"github.com/jetsetilly/gopher2600/hardware"
|
"github.com/jetsetilly/gopher2600/hardware"
|
||||||
"github.com/jetsetilly/gopher2600/userinput"
|
"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())
|
dbg.liveBankInfo = dbg.vcs.Mem.Cart.GetBank(dbg.vcs.CPU.PC.Address())
|
||||||
|
|
||||||
// run and handle events
|
// 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
|
// 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
|
// 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 {
|
if dbg.halting.halt {
|
||||||
// set debugging mode. halting messages will be preserved and
|
// set debugging mode. halting messages will be preserved and
|
||||||
// shown when entering debugging mode
|
// shown when entering debugging mode
|
||||||
dbg.setMode(emulation.ModeDebugger)
|
dbg.setMode(govern.ModeDebugger)
|
||||||
return emulation.Ending, nil
|
return govern.Ending, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if dbg.Mode() != emulation.ModePlay {
|
if dbg.Mode() != govern.ModePlay {
|
||||||
return emulation.Ending, nil
|
return govern.Ending, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// return without checking interface unless we exceed the
|
// return without checking interface unless we exceed the
|
||||||
|
@ -113,12 +113,12 @@ func (dbg *Debugger) playLoop() error {
|
||||||
case <-dbg.eventCheckPulse.C:
|
case <-dbg.eventCheckPulse.C:
|
||||||
err := dbg.readEventsHandler()
|
err := dbg.readEventsHandler()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return emulation.Ending, err
|
return govern.Ending, err
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
if dbg.state.Load().(emulation.State) == emulation.Running {
|
if dbg.state.Load().(govern.State) == govern.Running {
|
||||||
dbg.Rewind.RecordState()
|
dbg.Rewind.RecordState()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,50 +17,49 @@ package debugger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/jetsetilly/gopher2600/curated"
|
"github.com/jetsetilly/gopher2600/curated"
|
||||||
"github.com/jetsetilly/gopher2600/emulation"
|
"github.com/jetsetilly/gopher2600/debugger/govern"
|
||||||
"github.com/jetsetilly/gopher2600/logger"
|
"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 {
|
if len(args) != expectedLen {
|
||||||
return curated.Errorf("wrong number of arguments (%d instead of %d)", len(args), expectedLen)
|
return curated.Errorf("wrong number of arguments (%d instead of %d)", len(args), expectedLen)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReqFeature implements the emulation.Emulation interface.
|
// ReqFeature implements the govern.Emulation interface.
|
||||||
func (dbg *Debugger) SetFeature(request emulation.FeatureReq, args ...emulation.FeatureReqData) error {
|
func (dbg *Debugger) SetFeature(request govern.FeatureReq, args ...govern.FeatureReqData) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
switch request {
|
switch request {
|
||||||
case emulation.ReqSetPause:
|
case govern.ReqSetPause:
|
||||||
err = argLen(args, 1)
|
err = argLen(args, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return curated.Errorf("debugger: %v", err)
|
return curated.Errorf("debugger: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch dbg.Mode() {
|
switch dbg.Mode() {
|
||||||
case emulation.ModePlay:
|
case govern.ModePlay:
|
||||||
dbg.PushRawEvent(func() {
|
dbg.PushRawEvent(func() {
|
||||||
// Pause implements the emulation.Emulation interface.
|
|
||||||
if args[0].(bool) {
|
if args[0].(bool) {
|
||||||
dbg.setState(emulation.Paused)
|
dbg.setState(govern.Paused)
|
||||||
} else {
|
} 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)
|
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)
|
err = argLen(args, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return curated.Errorf("debugger: %v", err)
|
return curated.Errorf("debugger: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg.PushRawEventImmediate(func() {
|
dbg.PushRawEventImmediate(func() {
|
||||||
err := dbg.setMode(args[0].(emulation.Mode))
|
err := dbg.setMode(args[0].(govern.Mode))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Logf("debugger", err.Error())
|
logger.Logf("debugger", err.Error())
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/jetsetilly/gopher2600/curated"
|
"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/gui"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/television/coords"
|
"github.com/jetsetilly/gopher2600/hardware/television/coords"
|
||||||
)
|
)
|
||||||
|
@ -34,30 +34,30 @@ func (dbg *Debugger) RewindByAmount(amount int) bool {
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Rewind: unsupported mode (%v)", dbg.Mode()))
|
panic(fmt.Sprintf("Rewind: unsupported mode (%v)", dbg.Mode()))
|
||||||
|
|
||||||
case emulation.ModePlay:
|
case govern.ModePlay:
|
||||||
coords := dbg.vcs.TV.GetCoords()
|
coords := dbg.vcs.TV.GetCoords()
|
||||||
tl := dbg.Rewind.GetTimeline()
|
tl := dbg.Rewind.GetTimeline()
|
||||||
|
|
||||||
if amount < 0 && coords.Frame-1 <= tl.AvailableStart {
|
if amount < 0 && coords.Frame-1 <= tl.AvailableStart {
|
||||||
dbg.setStateQuiet(emulation.Paused, true)
|
dbg.setStateQuiet(govern.Paused, true)
|
||||||
dbg.gui.SetFeature(gui.ReqEmulationEvent, emulation.EventRewindAtStart)
|
dbg.gui.SetFeature(gui.ReqEmulationEvent, govern.EventRewindAtStart)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if amount > 0 && coords.Frame+1 >= tl.AvailableEnd {
|
if amount > 0 && coords.Frame+1 >= tl.AvailableEnd {
|
||||||
dbg.setStateQuiet(emulation.Paused, true)
|
dbg.setStateQuiet(govern.Paused, true)
|
||||||
dbg.gui.SetFeature(gui.ReqEmulationEvent, emulation.EventRewindAtEnd)
|
dbg.gui.SetFeature(gui.ReqEmulationEvent, govern.EventRewindAtEnd)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg.setStateQuiet(emulation.Rewinding, true)
|
dbg.setStateQuiet(govern.Rewinding, true)
|
||||||
dbg.Rewind.GotoFrame(coords.Frame + amount)
|
dbg.Rewind.GotoFrame(coords.Frame + amount)
|
||||||
dbg.setStateQuiet(emulation.Paused, true)
|
dbg.setStateQuiet(govern.Paused, true)
|
||||||
|
|
||||||
if amount < 0 {
|
if amount < 0 {
|
||||||
dbg.gui.SetFeature(gui.ReqEmulationEvent, emulation.EventRewindBack)
|
dbg.gui.SetFeature(gui.ReqEmulationEvent, govern.EventRewindBack)
|
||||||
} else {
|
} else {
|
||||||
dbg.gui.SetFeature(gui.ReqEmulationEvent, emulation.EventRewindFoward)
|
dbg.gui.SetFeature(gui.ReqEmulationEvent, govern.EventRewindFoward)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
@ -72,8 +72,8 @@ func (dbg *Debugger) RewindToFrame(fn int, last bool) bool {
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("RewindToFrame: unsupported mode (%v)", dbg.Mode()))
|
panic(fmt.Sprintf("RewindToFrame: unsupported mode (%v)", dbg.Mode()))
|
||||||
|
|
||||||
case emulation.ModeDebugger:
|
case govern.ModeDebugger:
|
||||||
if dbg.State() == emulation.Rewinding {
|
if dbg.State() == govern.Rewinding {
|
||||||
return false
|
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
|
// how we push the doRewind() function depends on what kind of inputloop we
|
||||||
// are currently in
|
// are currently in
|
||||||
dbg.PushRawEventImmediate(func() {
|
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)
|
// remembering that we must do it in the debugger goroutine)
|
||||||
dbg.setState(emulation.Rewinding)
|
dbg.setState(govern.Rewinding)
|
||||||
dbg.unwindLoop(doRewind)
|
dbg.unwindLoop(doRewind)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -118,8 +118,8 @@ func (dbg *Debugger) GotoCoords(coords coords.TelevisionCoords) bool {
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("GotoCoords: unsupported mode (%v)", dbg.Mode()))
|
panic(fmt.Sprintf("GotoCoords: unsupported mode (%v)", dbg.Mode()))
|
||||||
|
|
||||||
case emulation.ModeDebugger:
|
case govern.ModeDebugger:
|
||||||
if dbg.State() == emulation.Rewinding {
|
if dbg.State() == govern.Rewinding {
|
||||||
return false
|
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
|
// how we push the doRewind() function depends on what kind of inputloop we
|
||||||
// are currently in
|
// are currently in
|
||||||
dbg.PushRawEventImmediate(func() {
|
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)
|
// remembering that we must do it in the debugger goroutine)
|
||||||
dbg.setState(emulation.Rewinding)
|
dbg.setState(govern.Rewinding)
|
||||||
dbg.unwindLoop(doRewind)
|
dbg.unwindLoop(doRewind)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -157,8 +157,8 @@ func (dbg *Debugger) RerunLastNFrames(frames int) bool {
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("RerunLastNFrames: unsupported mode (%v)", dbg.Mode()))
|
panic(fmt.Sprintf("RerunLastNFrames: unsupported mode (%v)", dbg.Mode()))
|
||||||
|
|
||||||
case emulation.ModeDebugger:
|
case govern.ModeDebugger:
|
||||||
if dbg.State() == emulation.Rewinding {
|
if dbg.State() == govern.Rewinding {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,9 +194,9 @@ func (dbg *Debugger) RerunLastNFrames(frames int) bool {
|
||||||
// upate catchupQuantum before starting rewind process
|
// upate catchupQuantum before starting rewind process
|
||||||
dbg.catchupQuantum = QuantumClock
|
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)
|
// remembering that we must do it in the debugger goroutine)
|
||||||
dbg.setState(emulation.Rewinding)
|
dbg.setState(govern.Rewinding)
|
||||||
dbg.unwindLoop(doRewind)
|
dbg.unwindLoop(doRewind)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,8 @@ package debugger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/jetsetilly/gopher2600/curated"
|
"github.com/jetsetilly/gopher2600/curated"
|
||||||
|
"github.com/jetsetilly/gopher2600/debugger/govern"
|
||||||
"github.com/jetsetilly/gopher2600/debugger/terminal"
|
"github.com/jetsetilly/gopher2600/debugger/terminal"
|
||||||
"github.com/jetsetilly/gopher2600/emulation"
|
|
||||||
"github.com/jetsetilly/gopher2600/userinput"
|
"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)
|
// mode specific special input (not passed to the VCS as controller input)
|
||||||
switch dbg.Mode() {
|
switch dbg.Mode() {
|
||||||
case emulation.ModePlay:
|
case govern.ModePlay:
|
||||||
switch ev := ev.(type) {
|
switch ev := ev.(type) {
|
||||||
case userinput.EventMouseWheel:
|
case userinput.EventMouseWheel:
|
||||||
amount := int(ev.Delta) + dbg.rewindMouseWheelAccumulation
|
amount := int(ev.Delta) + dbg.rewindMouseWheelAccumulation
|
||||||
|
@ -73,7 +73,7 @@ func (dbg *Debugger) userInputHandler(ev userinput.Event) error {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dbg.rewindKeyboardAccumulation = 0
|
dbg.rewindKeyboardAccumulation = 0
|
||||||
if dbg.State() != emulation.Running {
|
if dbg.State() != govern.Running {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ func (dbg *Debugger) userInputHandler(ev userinput.Event) error {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dbg.rewindKeyboardAccumulation = 0
|
dbg.rewindKeyboardAccumulation = 0
|
||||||
if dbg.State() != emulation.Running {
|
if dbg.State() != govern.Running {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,18 +106,18 @@ func (dbg *Debugger) userInputHandler(ev userinput.Event) error {
|
||||||
if ev.Down {
|
if ev.Down {
|
||||||
switch ev.Button {
|
switch ev.Button {
|
||||||
case userinput.GamepadButtonBack:
|
case userinput.GamepadButtonBack:
|
||||||
if dbg.State() != emulation.Paused {
|
if dbg.State() != govern.Paused {
|
||||||
dbg.SetFeature(emulation.ReqSetPause, true)
|
dbg.SetFeature(govern.ReqSetPause, true)
|
||||||
} else {
|
} else {
|
||||||
dbg.SetFeature(emulation.ReqSetPause, false)
|
dbg.SetFeature(govern.ReqSetPause, false)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
case userinput.GamepadButtonGuide:
|
case userinput.GamepadButtonGuide:
|
||||||
switch dbg.Mode() {
|
switch dbg.Mode() {
|
||||||
case emulation.ModePlay:
|
case govern.ModePlay:
|
||||||
dbg.SetFeature(emulation.ReqSetMode, emulation.ModeDebugger)
|
dbg.SetFeature(govern.ReqSetMode, govern.ModeDebugger)
|
||||||
case emulation.ModeDebugger:
|
case govern.ModeDebugger:
|
||||||
dbg.SetFeature(emulation.ReqSetMode, emulation.ModePlay)
|
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
|
// direction). unpause if the emulation is currently paused
|
||||||
//
|
//
|
||||||
// * we're only allowing this for playmode
|
// * we're only allowing this for playmode
|
||||||
if dbg.Mode() == emulation.ModePlay && dbg.State() == emulation.Paused && handled {
|
if dbg.Mode() == govern.ModePlay && dbg.State() == govern.Paused && handled {
|
||||||
dbg.SetFeature(emulation.ReqSetPause, false)
|
dbg.SetFeature(govern.ReqSetPause, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
// This file is part of Gopher2600.
|
|
||||||
//
|
|
||||||
// Gopher2600 is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// Gopher2600 is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with Gopher2600. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package emulation
|
|
||||||
|
|
||||||
// FeatureReq is used to request the setting of an emulation attribute
|
|
||||||
// eg. a pause request from the GUI
|
|
||||||
type FeatureReq string
|
|
||||||
|
|
||||||
// FeatureReqData represents the information associated with a FeatureReq. See
|
|
||||||
// commentary for the defined FeatureReq values for the underlying type.
|
|
||||||
type FeatureReqData interface{}
|
|
||||||
|
|
||||||
// List of valid feature requests. argument must be of the type specified or
|
|
||||||
// else the interface{} type conversion will fail and the application will
|
|
||||||
// probably crash.
|
|
||||||
//
|
|
||||||
// Note that, like the name suggests, these are requests, they may or may not
|
|
||||||
// be satisfied depending on other conditions in the GUI.
|
|
||||||
const (
|
|
||||||
// notify gui of the underlying emulation mode.
|
|
||||||
ReqSetPause FeatureReq = "ReqSetPause" // bool
|
|
||||||
|
|
||||||
// change emulation mode
|
|
||||||
ReqSetMode FeatureReq = "ReqSetMode" // emulation.Mode
|
|
||||||
)
|
|
||||||
|
|
||||||
// Sentinal error returned if emulation does no support requested feature.
|
|
||||||
const (
|
|
||||||
UnsupportedEmulationFeature = "unsupported emulation feature: %v"
|
|
||||||
)
|
|
|
@ -27,11 +27,11 @@ import (
|
||||||
"github.com/jetsetilly/gopher2600/cartridgeloader"
|
"github.com/jetsetilly/gopher2600/cartridgeloader"
|
||||||
"github.com/jetsetilly/gopher2600/curated"
|
"github.com/jetsetilly/gopher2600/curated"
|
||||||
"github.com/jetsetilly/gopher2600/debugger"
|
"github.com/jetsetilly/gopher2600/debugger"
|
||||||
|
"github.com/jetsetilly/gopher2600/debugger/govern"
|
||||||
"github.com/jetsetilly/gopher2600/debugger/terminal"
|
"github.com/jetsetilly/gopher2600/debugger/terminal"
|
||||||
"github.com/jetsetilly/gopher2600/debugger/terminal/colorterm"
|
"github.com/jetsetilly/gopher2600/debugger/terminal/colorterm"
|
||||||
"github.com/jetsetilly/gopher2600/debugger/terminal/plainterm"
|
"github.com/jetsetilly/gopher2600/debugger/terminal/plainterm"
|
||||||
"github.com/jetsetilly/gopher2600/disassembly"
|
"github.com/jetsetilly/gopher2600/disassembly"
|
||||||
"github.com/jetsetilly/gopher2600/emulation"
|
|
||||||
"github.com/jetsetilly/gopher2600/gui"
|
"github.com/jetsetilly/gopher2600/gui"
|
||||||
"github.com/jetsetilly/gopher2600/gui/sdlimgui"
|
"github.com/jetsetilly/gopher2600/gui/sdlimgui"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/riot/ports"
|
"github.com/jetsetilly/gopher2600/hardware/riot/ports"
|
||||||
|
@ -236,10 +236,10 @@ func launch(sync *mainSync) {
|
||||||
fallthrough
|
fallthrough
|
||||||
|
|
||||||
case "PLAY":
|
case "PLAY":
|
||||||
err = emulate(emulation.ModePlay, md, sync)
|
err = emulate(govern.ModePlay, md, sync)
|
||||||
|
|
||||||
case "DEBUG":
|
case "DEBUG":
|
||||||
err = emulate(emulation.ModeDebugger, md, sync)
|
err = emulate(govern.ModeDebugger, md, sync)
|
||||||
|
|
||||||
case "DISASM":
|
case "DISASM":
|
||||||
err = disasm(md)
|
err = disasm(md)
|
||||||
|
@ -267,7 +267,7 @@ const defaultInitScript = "debuggerInit"
|
||||||
|
|
||||||
// emulate is the main emulation launch function, shared by play and debug
|
// emulate is the main emulation launch function, shared by play and debug
|
||||||
// modes. the other modes initialise and run the emulation differently.
|
// 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
|
// 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
|
// 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
|
// 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")
|
opts.Profile = md.AddString("profile", "none", "run performance check with profiling: command separated CPU, MEM, TRACE or ALL")
|
||||||
|
|
||||||
// playmode specific arguments
|
// playmode specific arguments
|
||||||
if emulationMode == emulation.ModePlay {
|
if emulationMode == govern.ModePlay {
|
||||||
opts.ComparisonROM = md.AddString("comparisonROM", "", "ROM to run in parallel for comparison")
|
opts.ComparisonROM = md.AddString("comparisonROM", "", "ROM to run in parallel for comparison")
|
||||||
opts.ComparisonPrefs = md.AddString("comparisonPrefs", "", "preferences for comparison emulation")
|
opts.ComparisonPrefs = md.AddString("comparisonPrefs", "", "preferences for comparison emulation")
|
||||||
opts.Record = md.AddBool("record", false, "record user input to a file")
|
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
|
// debugger specific arguments
|
||||||
if emulationMode == emulation.ModeDebugger {
|
if emulationMode == govern.ModeDebugger {
|
||||||
opts.InitScript = md.AddString("initscript", defInitScript, "script to run on debugger start")
|
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")
|
opts.TermType = md.AddString("term", "IMGUI", "terminal type to use in debug mode: IMGUI, COLOR, PLAIN")
|
||||||
} else {
|
} else {
|
||||||
|
@ -348,7 +348,7 @@ func emulate(emulationMode emulation.Mode, md *modalflag.Modes, sync *mainSync)
|
||||||
// prepare new debugger, supplying a debugger.CreateUserInterface function.
|
// prepare new debugger, supplying a debugger.CreateUserInterface function.
|
||||||
// this function will be called by NewDebugger() and in turn will send a
|
// this function will be called by NewDebugger() and in turn will send a
|
||||||
// GUI create message to the main goroutine
|
// 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 term terminal.Terminal
|
||||||
var scr gui.GUI
|
var scr gui.GUI
|
||||||
|
|
||||||
|
@ -402,13 +402,13 @@ func emulate(emulationMode emulation.Mode, md *modalflag.Modes, sync *mainSync)
|
||||||
// a call to performance.RunProfiler()
|
// a call to performance.RunProfiler()
|
||||||
dbgLaunch := func() error {
|
dbgLaunch := func() error {
|
||||||
switch emulationMode {
|
switch emulationMode {
|
||||||
case emulation.ModeDebugger:
|
case govern.ModeDebugger:
|
||||||
err := dbg.StartInDebugMode(md.GetArg(0))
|
err := dbg.StartInDebugMode(md.GetArg(0))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
case emulation.ModePlay:
|
case govern.ModePlay:
|
||||||
err := dbg.StartInPlayMode(md.GetArg(0))
|
err := dbg.StartInPlayMode(md.GetArg(0))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -435,9 +435,9 @@ func emulate(emulationMode emulation.Mode, md *modalflag.Modes, sync *mainSync)
|
||||||
// filename argument for RunProfiler
|
// filename argument for RunProfiler
|
||||||
s := ""
|
s := ""
|
||||||
switch emulationMode {
|
switch emulationMode {
|
||||||
case emulation.ModeDebugger:
|
case govern.ModeDebugger:
|
||||||
s = "debugger"
|
s = "debugger"
|
||||||
case emulation.ModePlay:
|
case govern.ModePlay:
|
||||||
s = "play"
|
s = "play"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ package sdlimgui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/go-gl/gl/v3.2-core/gl"
|
"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/gui/sdlimgui/shaders"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/television/specification"
|
"github.com/jetsetilly/gopher2600/hardware/television/specification"
|
||||||
)
|
)
|
||||||
|
@ -90,14 +90,14 @@ func (attr *dbgScrHelper) set(img *SdlImgui) {
|
||||||
// end of critical section
|
// end of critical section
|
||||||
|
|
||||||
// show cursor
|
// show cursor
|
||||||
switch img.emulation.State() {
|
switch img.dbg.State() {
|
||||||
case emulation.Paused:
|
case govern.Paused:
|
||||||
gl.Uniform1i(attr.showCursor, 1)
|
gl.Uniform1i(attr.showCursor, 1)
|
||||||
case emulation.Running:
|
case govern.Running:
|
||||||
gl.Uniform1i(attr.showCursor, 0)
|
gl.Uniform1i(attr.showCursor, 0)
|
||||||
case emulation.Stepping:
|
case govern.Stepping:
|
||||||
gl.Uniform1i(attr.showCursor, 1)
|
gl.Uniform1i(attr.showCursor, 1)
|
||||||
case emulation.Rewinding:
|
case govern.Rewinding:
|
||||||
gl.Uniform1i(attr.showCursor, 1)
|
gl.Uniform1i(attr.showCursor, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,8 @@ import (
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/jetsetilly/gopher2600/debugger"
|
"github.com/jetsetilly/gopher2600/debugger"
|
||||||
|
"github.com/jetsetilly/gopher2600/debugger/govern"
|
||||||
"github.com/jetsetilly/gopher2600/disassembly"
|
"github.com/jetsetilly/gopher2600/disassembly"
|
||||||
"github.com/jetsetilly/gopher2600/emulation"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// LazyDebugger lazily accesses Debugger information.
|
// LazyDebugger lazily accesses Debugger information.
|
||||||
|
@ -31,18 +31,18 @@ type LazyDebugger struct {
|
||||||
liveDisasmEntry atomic.Value // disassembly.Entry
|
liveDisasmEntry atomic.Value // disassembly.Entry
|
||||||
breakpoints atomic.Value // debugger.BreakpointsQuery
|
breakpoints atomic.Value // debugger.BreakpointsQuery
|
||||||
hasChanged atomic.Value // bool
|
hasChanged atomic.Value // bool
|
||||||
state atomic.Value // emulation.State
|
state atomic.Value // govern.State
|
||||||
|
|
||||||
Quantum debugger.Quantum
|
Quantum debugger.Quantum
|
||||||
LiveDisasmEntry disassembly.Entry
|
LiveDisasmEntry disassembly.Entry
|
||||||
Breakpoints debugger.BreakpointsQuery
|
Breakpoints debugger.BreakpointsQuery
|
||||||
HasChanged bool
|
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
|
// 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
|
// system) when synchronisation is important
|
||||||
State emulation.State
|
State govern.State
|
||||||
}
|
}
|
||||||
|
|
||||||
func newLazyDebugger(val *LazyValues) *LazyDebugger {
|
func newLazyDebugger(val *LazyValues) *LazyDebugger {
|
||||||
|
@ -78,5 +78,5 @@ func (lz *LazyDebugger) update() {
|
||||||
// load current hasChanged value and unlatch (see push() function)
|
// load current hasChanged value and unlatch (see push() function)
|
||||||
lz.HasChanged = lz.hasChanged.Load().(bool)
|
lz.HasChanged = lz.hasChanged.Load().(bool)
|
||||||
lz.hasChanged.Store(false)
|
lz.hasChanged.Store(false)
|
||||||
lz.State, _ = lz.state.Load().(emulation.State)
|
lz.State, _ = lz.state.Load().(govern.State)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ import (
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/jetsetilly/gopher2600/debugger"
|
"github.com/jetsetilly/gopher2600/debugger"
|
||||||
"github.com/jetsetilly/gopher2600/emulation"
|
|
||||||
"github.com/jetsetilly/gopher2600/hardware"
|
"github.com/jetsetilly/gopher2600/hardware"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/television"
|
"github.com/jetsetilly/gopher2600/hardware/television"
|
||||||
)
|
)
|
||||||
|
@ -28,12 +27,9 @@ import (
|
||||||
// thread to the emulation. Use these values rather than directly accessing
|
// thread to the emulation. Use these values rather than directly accessing
|
||||||
// those exposed by the emulation.
|
// those exposed by the emulation.
|
||||||
type LazyValues struct {
|
type LazyValues struct {
|
||||||
emulation emulation.Emulation
|
dbg *debugger.Debugger
|
||||||
|
|
||||||
// vcs and dbg are taken from the emulation supplied to SetEmulation()
|
|
||||||
tv *television.Television
|
tv *television.Television
|
||||||
vcs *hardware.VCS
|
vcs *hardware.VCS
|
||||||
dbg *debugger.Debugger
|
|
||||||
|
|
||||||
// pointers to these instances. non-pointer instances trigger the race
|
// pointers to these instances. non-pointer instances trigger the race
|
||||||
// detector for some reason.
|
// detector for some reason.
|
||||||
|
@ -67,16 +63,12 @@ type LazyValues struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewLazyValues is the preferred method of initialisation for the Values type.
|
// 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 := &LazyValues{}
|
||||||
|
|
||||||
val.emulation = e
|
val.dbg = dbg
|
||||||
val.tv = e.TV().(*television.Television)
|
val.tv = val.dbg.TV()
|
||||||
val.vcs = e.VCS().(*hardware.VCS)
|
val.vcs = val.dbg.VCS()
|
||||||
switch dbg := e.Debugger().(type) {
|
|
||||||
case *debugger.Debugger:
|
|
||||||
val.dbg = dbg
|
|
||||||
}
|
|
||||||
|
|
||||||
val.Debugger = newLazyDebugger(val)
|
val.Debugger = newLazyDebugger(val)
|
||||||
val.CPU = newLazyCPU(val)
|
val.CPU = newLazyCPU(val)
|
||||||
|
@ -107,7 +99,7 @@ func NewLazyValues(e emulation.Emulation) *LazyValues {
|
||||||
|
|
||||||
// Refresh lazy values.
|
// Refresh lazy values.
|
||||||
func (val *LazyValues) Refresh() {
|
func (val *LazyValues) Refresh() {
|
||||||
if val.emulation == nil {
|
if val.dbg == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +161,7 @@ func (val *LazyValues) Refresh() {
|
||||||
|
|
||||||
// FastRefresh lazy values. Updates only the values that are needed in playmode.
|
// FastRefresh lazy values. Updates only the values that are needed in playmode.
|
||||||
func (val *LazyValues) FastRefresh() {
|
func (val *LazyValues) FastRefresh() {
|
||||||
if val.emulation == nil {
|
if val.dbg == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/inkyblackness/imgui-go/v4"
|
"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.
|
// manager handles windows and menus in the system.
|
||||||
|
@ -209,13 +209,13 @@ func (wm *manager) draw() {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch wm.img.mode {
|
switch wm.img.mode {
|
||||||
case emulation.ModePlay:
|
case govern.ModePlay:
|
||||||
// playmode draws the screen and other windows that have been listed
|
// playmode draws the screen and other windows that have been listed
|
||||||
// as being safe to draw in playmode
|
// as being safe to draw in playmode
|
||||||
for _, w := range wm.playmodeWindows {
|
for _, w := range wm.playmodeWindows {
|
||||||
w.playmodeDraw()
|
w.playmodeDraw()
|
||||||
}
|
}
|
||||||
case emulation.ModeDebugger:
|
case govern.ModeDebugger:
|
||||||
// see commentary for screenPos in windowManager declaration
|
// see commentary for screenPos in windowManager declaration
|
||||||
wm.screenPos = imgui.WindowPos()
|
wm.screenPos = imgui.WindowPos()
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ import (
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
"github.com/inkyblackness/imgui-go/v4"
|
"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/gui/fonts"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ func (wm *manager) drawMenu() {
|
||||||
wdth -= rightJustText(wdth, fmt.Sprintf("%.2fHz", wm.img.lz.TV.Hz), true)
|
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 {
|
if wm.img.lz.TV.ReqFPS < 1.0 {
|
||||||
wdth -= rightJustText(wdth, "< 1 fps", true)
|
wdth -= rightJustText(wdth, "< 1 fps", true)
|
||||||
} else if math.IsInf(float64(wm.img.lz.TV.ActualFPS), 0) {
|
} else if math.IsInf(float64(wm.img.lz.TV.ActualFPS), 0) {
|
||||||
|
|
|
@ -22,7 +22,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/jetsetilly/gopher2600/curated"
|
"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/prefs"
|
||||||
"github.com/jetsetilly/gopher2600/resources"
|
"github.com/jetsetilly/gopher2600/resources"
|
||||||
"github.com/jetsetilly/gopher2600/resources/fs"
|
"github.com/jetsetilly/gopher2600/resources/fs"
|
||||||
|
@ -77,7 +77,7 @@ func (wm *manager) saveManagerState() (rerr error) {
|
||||||
continue
|
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)
|
n, err := fmt.Fprint(f, s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return curated.Errorf("manager state: %v", err)
|
return curated.Errorf("manager state: %v", err)
|
||||||
|
@ -94,7 +94,7 @@ func (wm *manager) saveManagerState() (rerr error) {
|
||||||
continue
|
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)
|
n, err := fmt.Fprint(f, s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return curated.Errorf("manager state: %v", err)
|
return curated.Errorf("manager state: %v", err)
|
||||||
|
@ -159,13 +159,13 @@ func (wm *manager) loadManagerState() (rerr error) {
|
||||||
k := spt[1]
|
k := spt[1]
|
||||||
v := spt[2]
|
v := spt[2]
|
||||||
|
|
||||||
if m == emulation.ModeDebugger.String() {
|
if m == govern.ModeDebugger.String() {
|
||||||
if w, ok := wm.debuggerWindows[k]; ok {
|
if w, ok := wm.debuggerWindows[k]; ok {
|
||||||
w.debuggerSetOpen(strings.ToUpper(v) == "TRUE")
|
w.debuggerSetOpen(strings.ToUpper(v) == "TRUE")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if m == emulation.ModePlay.String() {
|
if m == govern.ModePlay.String() {
|
||||||
if w, ok := wm.playmodeWindows[k]; ok {
|
if w, ok := wm.playmodeWindows[k]; ok {
|
||||||
w.playmodeSetOpen(strings.ToUpper(v) == "TRUE")
|
w.playmodeSetOpen(strings.ToUpper(v) == "TRUE")
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,7 @@ func newPlayScr(img *SdlImgui) *playScr {
|
||||||
rightAlign: true,
|
rightAlign: true,
|
||||||
},
|
},
|
||||||
emulationEvent: emulationEventNotification{
|
emulationEvent: emulationEventNotification{
|
||||||
emulation: img.emulation,
|
emulation: img.dbg,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/inkyblackness/imgui-go/v4"
|
"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/gui/fonts"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/mapper"
|
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/mapper"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/riot/ports/plugging"
|
"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
|
// emulationEventNotification is used to draw an indicator on the screen for
|
||||||
// events defined in the emulation package.
|
// events defined in the emulation package.
|
||||||
type emulationEventNotification struct {
|
type emulationEventNotification struct {
|
||||||
emulation emulation.Emulation
|
emulation *debugger.Debugger
|
||||||
open bool
|
open bool
|
||||||
currentEvent emulation.Event
|
currentEvent govern.Event
|
||||||
frames int
|
frames int
|
||||||
|
|
||||||
// audio mute is handled differently to other events. we want the icon for
|
// audio mute is handled differently to other events. we want the icon for
|
||||||
|
@ -130,18 +131,18 @@ type emulationEventNotification struct {
|
||||||
mute bool
|
mute bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ee *emulationEventNotification) set(event emulation.Event) {
|
func (ee *emulationEventNotification) set(event govern.Event) {
|
||||||
ee.currentEvent = event
|
ee.currentEvent = event
|
||||||
ee.open = true
|
ee.open = true
|
||||||
ee.frames = notificationDurationEvent
|
ee.frames = notificationDurationEvent
|
||||||
switch event {
|
switch event {
|
||||||
case emulation.EventRun:
|
case govern.EventRun:
|
||||||
ee.frames = notificationDurationEventRun
|
ee.frames = notificationDurationEventRun
|
||||||
case emulation.EventScreenshot:
|
case govern.EventScreenshot:
|
||||||
ee.frames = notificationDurationScreenshot
|
ee.frames = notificationDurationScreenshot
|
||||||
case emulation.EventMute:
|
case govern.EventMute:
|
||||||
ee.mute = true
|
ee.mute = true
|
||||||
case emulation.EventUnmute:
|
case govern.EventUnmute:
|
||||||
ee.mute = false
|
ee.mute = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,16 +156,16 @@ func (ee *emulationEventNotification) tick() {
|
||||||
|
|
||||||
if ee.frames == 0 {
|
if ee.frames == 0 {
|
||||||
// if emulation is paused then force the current event to EventPause
|
// if emulation is paused then force the current event to EventPause
|
||||||
if ee.emulation.State() == emulation.Paused {
|
if ee.emulation.State() == govern.Paused {
|
||||||
ee.currentEvent = emulation.EventPause
|
ee.currentEvent = govern.EventPause
|
||||||
}
|
}
|
||||||
|
|
||||||
// special handling of open when current event is EventPause or if mute
|
// special handling of open when current event is EventPause or if mute
|
||||||
// is enabled
|
// is enabled
|
||||||
if ee.currentEvent != emulation.EventPause {
|
if ee.currentEvent != govern.EventPause {
|
||||||
if ee.mute {
|
if ee.mute {
|
||||||
ee.open = true
|
ee.open = true
|
||||||
ee.currentEvent = emulation.EventMute
|
ee.currentEvent = govern.EventMute
|
||||||
} else {
|
} else {
|
||||||
ee.open = false
|
ee.open = false
|
||||||
}
|
}
|
||||||
|
@ -196,23 +197,23 @@ func (ee *emulationEventNotification) draw(win *playScr, hosted bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ee.currentEvent {
|
switch ee.currentEvent {
|
||||||
case emulation.EventInitialising:
|
case govern.EventInitialising:
|
||||||
imgui.Text("")
|
imgui.Text("")
|
||||||
case emulation.EventPause:
|
case govern.EventPause:
|
||||||
imgui.Text(string(fonts.EmulationPause))
|
imgui.Text(string(fonts.EmulationPause))
|
||||||
case emulation.EventRun:
|
case govern.EventRun:
|
||||||
imgui.Text(string(fonts.EmulationRun))
|
imgui.Text(string(fonts.EmulationRun))
|
||||||
case emulation.EventRewindBack:
|
case govern.EventRewindBack:
|
||||||
imgui.Text(string(fonts.EmulationRewindBack))
|
imgui.Text(string(fonts.EmulationRewindBack))
|
||||||
case emulation.EventRewindFoward:
|
case govern.EventRewindFoward:
|
||||||
imgui.Text(string(fonts.EmulationRewindForward))
|
imgui.Text(string(fonts.EmulationRewindForward))
|
||||||
case emulation.EventRewindAtStart:
|
case govern.EventRewindAtStart:
|
||||||
imgui.Text(string(fonts.EmulationRewindAtStart))
|
imgui.Text(string(fonts.EmulationRewindAtStart))
|
||||||
case emulation.EventRewindAtEnd:
|
case govern.EventRewindAtEnd:
|
||||||
imgui.Text(string(fonts.EmulationRewindAtEnd))
|
imgui.Text(string(fonts.EmulationRewindAtEnd))
|
||||||
case emulation.EventScreenshot:
|
case govern.EventScreenshot:
|
||||||
imgui.Text(string(fonts.Camera))
|
imgui.Text(string(fonts.Camera))
|
||||||
case emulation.EventMute:
|
case govern.EventMute:
|
||||||
if hosted || win.img.prefs.audioMuteNotification.Get().(bool) {
|
if hosted || win.img.prefs.audioMuteNotification.Get().(bool) {
|
||||||
imgui.Text(string(fonts.AudioMute))
|
imgui.Text(string(fonts.AudioMute))
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ package sdlimgui
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jetsetilly/gopher2600/emulation"
|
"github.com/jetsetilly/gopher2600/debugger/govern"
|
||||||
"github.com/veandco/go-sdl2/sdl"
|
"github.com/veandco/go-sdl2/sdl"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ func (pol *polling) wait() sdl.Event {
|
||||||
} else {
|
} else {
|
||||||
working := pol.awake ||
|
working := pol.awake ||
|
||||||
pol.img.lz.Debugger.HasChanged ||
|
pol.img.lz.Debugger.HasChanged ||
|
||||||
pol.img.emulation.State() != emulation.Paused ||
|
pol.img.dbg.State() != govern.Paused ||
|
||||||
pol.img.wm.dbgScr.crtPreview
|
pol.img.wm.dbgScr.crtPreview
|
||||||
|
|
||||||
if working {
|
if working {
|
||||||
|
|
|
@ -17,7 +17,7 @@ package sdlimgui
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/jetsetilly/gopher2600/emulation"
|
"github.com/jetsetilly/gopher2600/debugger/govern"
|
||||||
"github.com/jetsetilly/gopher2600/prefs"
|
"github.com/jetsetilly/gopher2600/prefs"
|
||||||
"github.com/jetsetilly/gopher2600/resources"
|
"github.com/jetsetilly/gopher2600/resources"
|
||||||
)
|
)
|
||||||
|
@ -236,11 +236,11 @@ func (p *preferences) loadWindowPreferences() error {
|
||||||
var group string
|
var group string
|
||||||
|
|
||||||
switch p.img.mode {
|
switch p.img.mode {
|
||||||
case emulation.ModeNone:
|
case govern.ModeNone:
|
||||||
p.img.plt.window.Hide()
|
p.img.plt.window.Hide()
|
||||||
case emulation.ModeDebugger:
|
case govern.ModeDebugger:
|
||||||
group = "sdlimgui.debugger"
|
group = "sdlimgui.debugger"
|
||||||
case emulation.ModePlay:
|
case govern.ModePlay:
|
||||||
group = "sdlimgui.playmode"
|
group = "sdlimgui.playmode"
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("cannot set window mode for unsupported emulation mode (%v)", p.img.mode))
|
panic(fmt.Sprintf("cannot set window mode for unsupported emulation mode (%v)", p.img.mode))
|
||||||
|
|
|
@ -20,7 +20,7 @@ import (
|
||||||
|
|
||||||
"github.com/jetsetilly/gopher2600/bots"
|
"github.com/jetsetilly/gopher2600/bots"
|
||||||
"github.com/jetsetilly/gopher2600/curated"
|
"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/gui"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/mapper"
|
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/mapper"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/riot/ports/plugging"
|
"github.com/jetsetilly/gopher2600/hardware/riot/ports/plugging"
|
||||||
|
@ -54,7 +54,7 @@ func (img *SdlImgui) serviceSetFeature(request featureRequest) {
|
||||||
case gui.ReqSetEmulationMode:
|
case gui.ReqSetEmulationMode:
|
||||||
err = argLen(request.args, 1)
|
err = argLen(request.args, 1)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
img.setEmulationMode(request.args[0].(emulation.Mode))
|
img.setEmulationMode(request.args[0].(govern.Mode))
|
||||||
}
|
}
|
||||||
|
|
||||||
case gui.ReqEnd:
|
case gui.ReqEnd:
|
||||||
|
@ -106,7 +106,7 @@ func (img *SdlImgui) serviceSetFeature(request featureRequest) {
|
||||||
if img.isPlaymode() {
|
if img.isPlaymode() {
|
||||||
err = argLen(request.args, 1)
|
err = argLen(request.args, 1)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
img.playScr.emulationEvent.set(request.args[0].(emulation.Event))
|
img.playScr.emulationEvent.set(request.args[0].(govern.Event))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ import (
|
||||||
"image/color"
|
"image/color"
|
||||||
"sync"
|
"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/memory/cartridge/mapper"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/television"
|
"github.com/jetsetilly/gopher2600/hardware/television"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/television/signal"
|
"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 {
|
if scr.crit.monitorSync && scr.crit.monitorSyncInRange {
|
||||||
switch scr.img.emulation.State() {
|
switch scr.img.dbg.State() {
|
||||||
case emulation.Rewinding:
|
case govern.Rewinding:
|
||||||
fallthrough
|
fallthrough
|
||||||
case emulation.Paused:
|
case govern.Paused:
|
||||||
scr.crit.renderIdx = scr.crit.plotIdx
|
scr.crit.renderIdx = scr.crit.plotIdx
|
||||||
scr.crit.prevRenderIdx = scr.crit.plotIdx
|
scr.crit.prevRenderIdx = scr.crit.plotIdx
|
||||||
scr.crit.bufferUsed = len(scr.crit.bufferPixels)
|
scr.crit.bufferUsed = len(scr.crit.bufferPixels)
|
||||||
case emulation.Running:
|
case govern.Running:
|
||||||
if scr.crit.bufferUsed > 0 {
|
if scr.crit.bufferUsed > 0 {
|
||||||
scr.crit.bufferUsed--
|
scr.crit.bufferUsed--
|
||||||
}
|
}
|
||||||
|
@ -622,7 +622,7 @@ func (scr *screen) copyPixelsPlaymode() {
|
||||||
// poor results for one frame kernels (depending on the ROM and what is
|
// 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
|
// happening on the screen at the time of the pause ) and will be
|
||||||
// sub-optimal for three frame kernels in almost all cases.
|
// 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)
|
activePause := scr.img.prefs.activePause.Get().(bool)
|
||||||
if scr.crit.pauseFrame || !activePause {
|
if scr.crit.pauseFrame || !activePause {
|
||||||
copy(scr.crit.pixels.Pix, scr.crit.bufferPixels[scr.crit.renderIdx].Pix)
|
copy(scr.crit.pixels.Pix, scr.crit.bufferPixels[scr.crit.renderIdx].Pix)
|
||||||
|
|
|
@ -21,8 +21,8 @@ import (
|
||||||
|
|
||||||
"github.com/jetsetilly/gopher2600/curated"
|
"github.com/jetsetilly/gopher2600/curated"
|
||||||
"github.com/jetsetilly/gopher2600/debugger"
|
"github.com/jetsetilly/gopher2600/debugger"
|
||||||
|
"github.com/jetsetilly/gopher2600/debugger/govern"
|
||||||
"github.com/jetsetilly/gopher2600/debugger/terminal"
|
"github.com/jetsetilly/gopher2600/debugger/terminal"
|
||||||
"github.com/jetsetilly/gopher2600/emulation"
|
|
||||||
"github.com/jetsetilly/gopher2600/gui/crt"
|
"github.com/jetsetilly/gopher2600/gui/crt"
|
||||||
"github.com/jetsetilly/gopher2600/gui/sdlaudio"
|
"github.com/jetsetilly/gopher2600/gui/sdlaudio"
|
||||||
"github.com/jetsetilly/gopher2600/gui/sdlimgui/lazyvalues"
|
"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
|
// allow sufficient time to close the font size selector combo box
|
||||||
resetFonts int
|
resetFonts int
|
||||||
|
|
||||||
// parent emulation. should be set via setEmulation() only
|
|
||||||
emulation emulation.Emulation
|
|
||||||
|
|
||||||
// the current mode of the underlying
|
// the current mode of the underlying
|
||||||
mode emulation.Mode
|
mode govern.Mode
|
||||||
|
|
||||||
// taken from the emulation field and assigned in the setEmulation() function
|
// taken from the emulation field and assigned in the setEmulation() function
|
||||||
|
dbg *debugger.Debugger
|
||||||
tv *television.Television
|
tv *television.Television
|
||||||
vcs *hardware.VCS
|
vcs *hardware.VCS
|
||||||
dbg *debugger.Debugger
|
|
||||||
userinput chan userinput.Event
|
userinput chan userinput.Event
|
||||||
|
|
||||||
// lazy value system allows safe access to the debugger/emulation from the
|
// 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
|
// NewSdlImgui is the preferred method of initialisation for type SdlImgui
|
||||||
//
|
//
|
||||||
// MUST ONLY be called from the gui thread.
|
// MUST ONLY be called from the gui thread.
|
||||||
func NewSdlImgui(e emulation.Emulation) (*SdlImgui, error) {
|
func NewSdlImgui(dbg *debugger.Debugger) (*SdlImgui, error) {
|
||||||
img := &SdlImgui{
|
img := &SdlImgui{
|
||||||
context: imgui.CreateContext(nil),
|
context: imgui.CreateContext(nil),
|
||||||
io: imgui.CurrentIO(),
|
io: imgui.CurrentIO(),
|
||||||
postRenderFunctions: make(chan func(), 100),
|
postRenderFunctions: make(chan func(), 100),
|
||||||
}
|
}
|
||||||
|
|
||||||
img.emulation = e
|
img.dbg = dbg
|
||||||
img.tv = e.TV().(*television.Television)
|
img.tv = img.dbg.TV()
|
||||||
img.vcs = e.VCS().(*hardware.VCS)
|
img.vcs = img.dbg.VCS()
|
||||||
switch dbg := e.Debugger().(type) {
|
img.userinput = img.dbg.UserInput()
|
||||||
case *debugger.Debugger:
|
|
||||||
img.dbg = dbg
|
|
||||||
}
|
|
||||||
img.userinput = e.UserInput()
|
|
||||||
|
|
||||||
// path to dear imgui ini file
|
// path to dear imgui ini file
|
||||||
iniPath, err := resources.JoinPath(imguiIniFile)
|
iniPath, err := resources.JoinPath(imguiIniFile)
|
||||||
|
@ -163,7 +156,7 @@ func NewSdlImgui(e emulation.Emulation) (*SdlImgui, error) {
|
||||||
return nil, curated.Errorf("sdlimgui: %v", err)
|
return nil, curated.Errorf("sdlimgui: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
img.lz = lazyvalues.NewLazyValues(img.emulation)
|
img.lz = lazyvalues.NewLazyValues(img.dbg)
|
||||||
img.screen = newScreen(img)
|
img.screen = newScreen(img)
|
||||||
img.term = newTerm()
|
img.term = newTerm()
|
||||||
|
|
||||||
|
@ -298,18 +291,18 @@ func (img *SdlImgui) end() {
|
||||||
|
|
||||||
// draw gui. called from service loop.
|
// draw gui. called from service loop.
|
||||||
func (img *SdlImgui) draw() {
|
func (img *SdlImgui) draw() {
|
||||||
if img.mode == emulation.ModeNone {
|
if img.mode == govern.ModeNone {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if img.emulation.State() == emulation.EmulatorStart {
|
if img.dbg.State() == govern.EmulatorStart {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
imgui.PushFont(img.glsl.fonts.defaultFont)
|
imgui.PushFont(img.glsl.fonts.defaultFont)
|
||||||
defer imgui.PopFont()
|
defer imgui.PopFont()
|
||||||
|
|
||||||
if img.mode == emulation.ModePlay {
|
if img.mode == govern.ModePlay {
|
||||||
img.playScr.draw()
|
img.playScr.draw()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,14 +313,14 @@ func (img *SdlImgui) draw() {
|
||||||
// is the gui in playmode or not. thread safe. called from emulation thread
|
// is the gui in playmode or not. thread safe. called from emulation thread
|
||||||
// and gui thread.
|
// and gui thread.
|
||||||
func (img *SdlImgui) isPlaymode() bool {
|
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
|
// set emulation and handle the changeover gracefully. this includes the saving
|
||||||
// and loading of preference groups.
|
// and loading of preference groups.
|
||||||
//
|
//
|
||||||
// should only be called from gui thread.
|
// 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
|
// 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
|
// 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
|
// 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()
|
img.prefs.loadWindowPreferences()
|
||||||
|
|
||||||
switch mode {
|
switch mode {
|
||||||
case emulation.ModeDebugger:
|
case govern.ModeDebugger:
|
||||||
img.screen.clearTextureRenderers()
|
img.screen.clearTextureRenderers()
|
||||||
img.screen.addTextureRenderer(img.wm.dbgScr)
|
img.screen.addTextureRenderer(img.wm.dbgScr)
|
||||||
img.plt.window.Show()
|
img.plt.window.Show()
|
||||||
|
|
||||||
case emulation.ModePlay:
|
case govern.ModePlay:
|
||||||
img.screen.clearTextureRenderers()
|
img.screen.clearTextureRenderers()
|
||||||
img.screen.addTextureRenderer(img.playScr)
|
img.screen.addTextureRenderer(img.playScr)
|
||||||
img.plt.window.Show()
|
img.plt.window.Show()
|
||||||
|
@ -379,9 +372,9 @@ func (img *SdlImgui) setAudioMute() {
|
||||||
if img.isPlaymode() {
|
if img.isPlaymode() {
|
||||||
mute = img.prefs.audioMutePlaymode.Get().(bool)
|
mute = img.prefs.audioMutePlaymode.Get().(bool)
|
||||||
if mute {
|
if mute {
|
||||||
img.playScr.emulationEvent.set(emulation.EventMute)
|
img.playScr.emulationEvent.set(govern.EventMute)
|
||||||
} else {
|
} else {
|
||||||
img.playScr.emulationEvent.set(emulation.EventUnmute)
|
img.playScr.emulationEvent.set(govern.EventUnmute)
|
||||||
}
|
}
|
||||||
img.vcs.RIOT.Ports.MutePeripherals(mute)
|
img.vcs.RIOT.Ports.MutePeripherals(mute)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -18,7 +18,7 @@ package sdlimgui
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jetsetilly/gopher2600/emulation"
|
"github.com/jetsetilly/gopher2600/debugger/govern"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/riot/ports/plugging"
|
"github.com/jetsetilly/gopher2600/hardware/riot/ports/plugging"
|
||||||
"github.com/jetsetilly/gopher2600/logger"
|
"github.com/jetsetilly/gopher2600/logger"
|
||||||
"github.com/jetsetilly/gopher2600/userinput"
|
"github.com/jetsetilly/gopher2600/userinput"
|
||||||
|
@ -43,9 +43,9 @@ func (img *SdlImgui) Service() {
|
||||||
|
|
||||||
// refresh lazy values
|
// refresh lazy values
|
||||||
switch img.mode {
|
switch img.mode {
|
||||||
case emulation.ModeDebugger:
|
case govern.ModeDebugger:
|
||||||
img.lz.Refresh()
|
img.lz.Refresh()
|
||||||
case emulation.ModePlay:
|
case govern.ModePlay:
|
||||||
img.lz.FastRefresh()
|
img.lz.FastRefresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ func (img *SdlImgui) Service() {
|
||||||
}
|
}
|
||||||
img.io.AddMouseWheelDelta(deltaX/4, deltaY/4)
|
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 {
|
select {
|
||||||
case img.userinput <- userinput.EventMouseWheel{Delta: deltaY}:
|
case img.userinput <- userinput.EventMouseWheel{Delta: deltaY}:
|
||||||
default:
|
default:
|
||||||
|
@ -386,9 +386,9 @@ func (img *SdlImgui) serviceKeyboard(ev *sdl.KeyboardEvent) {
|
||||||
|
|
||||||
case sdl.SCANCODE_GRAVE:
|
case sdl.SCANCODE_GRAVE:
|
||||||
if img.isPlaymode() {
|
if img.isPlaymode() {
|
||||||
img.emulation.SetFeature(emulation.ReqSetMode, emulation.ModeDebugger)
|
img.dbg.SetFeature(govern.ReqSetMode, govern.ModeDebugger)
|
||||||
} else {
|
} else {
|
||||||
img.emulation.SetFeature(emulation.ReqSetMode, emulation.ModePlay)
|
img.dbg.SetFeature(govern.ReqSetMode, govern.ModePlay)
|
||||||
}
|
}
|
||||||
|
|
||||||
case sdl.SCANCODE_F8:
|
case sdl.SCANCODE_F8:
|
||||||
|
@ -413,7 +413,7 @@ func (img *SdlImgui) serviceKeyboard(ev *sdl.KeyboardEvent) {
|
||||||
img.glsl.shaders[playscrShaderID].(*playscrShader).scheduleScreenshot(modeSingle)
|
img.glsl.shaders[playscrShaderID].(*playscrShader).scheduleScreenshot(modeSingle)
|
||||||
}
|
}
|
||||||
|
|
||||||
img.playScr.emulationEvent.set(emulation.EventScreenshot)
|
img.playScr.emulationEvent.set(govern.EventScreenshot)
|
||||||
|
|
||||||
case sdl.SCANCODE_F14:
|
case sdl.SCANCODE_F14:
|
||||||
fallthrough
|
fallthrough
|
||||||
|
@ -425,16 +425,16 @@ func (img *SdlImgui) serviceKeyboard(ev *sdl.KeyboardEvent) {
|
||||||
case sdl.SCANCODE_PAUSE:
|
case sdl.SCANCODE_PAUSE:
|
||||||
if img.isPlaymode() {
|
if img.isPlaymode() {
|
||||||
var err error
|
var err error
|
||||||
if img.emulation.State() == emulation.Paused {
|
if img.dbg.State() == govern.Paused {
|
||||||
err = img.emulation.SetFeature(emulation.ReqSetPause, false)
|
err = img.dbg.SetFeature(govern.ReqSetPause, false)
|
||||||
} else {
|
} else {
|
||||||
err = img.emulation.SetFeature(emulation.ReqSetPause, true)
|
err = img.dbg.SetFeature(govern.ReqSetPause, true)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Logf("sdlimgui", err.Error())
|
logger.Logf("sdlimgui", err.Error())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if img.emulation.State() == emulation.Paused {
|
if img.dbg.State() == govern.Paused {
|
||||||
img.term.pushCommand("RUN")
|
img.term.pushCommand("RUN")
|
||||||
} else {
|
} else {
|
||||||
img.term.pushCommand("HALT")
|
img.term.pushCommand("HALT")
|
||||||
|
|
|
@ -21,7 +21,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jetsetilly/gopher2600/debugger"
|
"github.com/jetsetilly/gopher2600/debugger"
|
||||||
"github.com/jetsetilly/gopher2600/emulation"
|
"github.com/jetsetilly/gopher2600/debugger/govern"
|
||||||
"github.com/jetsetilly/gopher2600/gui/fonts"
|
"github.com/jetsetilly/gopher2600/gui/fonts"
|
||||||
|
|
||||||
"github.com/inkyblackness/imgui-go/v4"
|
"github.com/inkyblackness/imgui-go/v4"
|
||||||
|
@ -120,7 +120,7 @@ func (win *winControl) draw() {
|
||||||
|
|
||||||
func (win *winControl) drawRunButton() {
|
func (win *winControl) drawRunButton() {
|
||||||
runDim := imgui.Vec2{X: imguiRemainingWinWidth(), Y: imgui.FrameHeight()}
|
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) {
|
if imguiColourButton(win.img.cols.False, fmt.Sprintf("%c Halt", fonts.Halt), runDim) {
|
||||||
win.img.term.pushCommand("HALT")
|
win.img.term.pushCommand("HALT")
|
||||||
}
|
}
|
||||||
|
@ -229,7 +229,7 @@ func (win *winControl) drawFPS() {
|
||||||
}
|
}
|
||||||
|
|
||||||
imgui.Spacing()
|
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 {
|
if win.img.lz.TV.ActualFPS <= win.img.lz.TV.ReqFPS*0.95 {
|
||||||
imgui.Text("running below requested FPS")
|
imgui.Text("running below requested FPS")
|
||||||
} else if win.img.lz.TV.ActualFPS > win.img.lz.TV.ReqFPS*1.05 {
|
} 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 {
|
if win.img.wm.dbgScr.isCaptured {
|
||||||
imgui.AlignTextToFramePadding()
|
imgui.AlignTextToFramePadding()
|
||||||
label := "RMB to release input"
|
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"
|
label = "RMB to halt & release input"
|
||||||
}
|
}
|
||||||
imgui.Text(label)
|
imgui.Text(label)
|
||||||
} else {
|
} else {
|
||||||
label := "Capture input & run"
|
label := "Capture input & run"
|
||||||
if win.img.emulation.State() == emulation.Running {
|
if win.img.dbg.State() == govern.Running {
|
||||||
label = "Capture input & continue"
|
label = "Capture input & continue"
|
||||||
}
|
}
|
||||||
if imgui.Button(label) {
|
if imgui.Button(label) {
|
||||||
|
|
|
@ -20,7 +20,7 @@ import (
|
||||||
|
|
||||||
"github.com/inkyblackness/imgui-go/v4"
|
"github.com/inkyblackness/imgui-go/v4"
|
||||||
"github.com/jetsetilly/gopher2600/coprocessor/disassembly"
|
"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/gui/fonts"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/arm"
|
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/arm"
|
||||||
)
|
)
|
||||||
|
@ -114,7 +114,7 @@ func (win *winCoProcDisasm) draw() {
|
||||||
if imgui.Checkbox("Disassembly Enabled", &isEnabled) {
|
if imgui.Checkbox("Disassembly Enabled", &isEnabled) {
|
||||||
win.img.dbg.PushRawEvent(func() {
|
win.img.dbg.PushRawEvent(func() {
|
||||||
win.img.dbg.CoProcDisasm.Enable(isEnabled)
|
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
|
// rerun the last two frames in order to gather as much disasm
|
||||||
// information as possible.
|
// information as possible.
|
||||||
win.img.dbg.RerunLastNFrames(2)
|
win.img.dbg.RerunLastNFrames(2)
|
||||||
|
|
|
@ -21,8 +21,8 @@ import (
|
||||||
|
|
||||||
"github.com/go-gl/gl/v3.2-core/gl"
|
"github.com/go-gl/gl/v3.2-core/gl"
|
||||||
"github.com/inkyblackness/imgui-go/v4"
|
"github.com/inkyblackness/imgui-go/v4"
|
||||||
|
"github.com/jetsetilly/gopher2600/debugger/govern"
|
||||||
"github.com/jetsetilly/gopher2600/disassembly"
|
"github.com/jetsetilly/gopher2600/disassembly"
|
||||||
"github.com/jetsetilly/gopher2600/emulation"
|
|
||||||
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/mapper"
|
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/mapper"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/memory/vcs"
|
"github.com/jetsetilly/gopher2600/hardware/memory/vcs"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/television/coords"
|
"github.com/jetsetilly/gopher2600/hardware/television/coords"
|
||||||
|
@ -254,7 +254,7 @@ func (win *winDbgScr) draw() {
|
||||||
if imgui.IsWindowFocused() && imageHovered {
|
if imgui.IsWindowFocused() && imageHovered {
|
||||||
// mouse click will cause the rewind goto coords to run only when the
|
// mouse click will cause the rewind goto coords to run only when the
|
||||||
// emulation is paused
|
// emulation is paused
|
||||||
if win.img.emulation.State() == emulation.Paused {
|
if win.img.dbg.State() == govern.Paused {
|
||||||
if imgui.IsMouseDown(0) {
|
if imgui.IsMouseDown(0) {
|
||||||
coords := coords.TelevisionCoords{
|
coords := coords.TelevisionCoords{
|
||||||
Frame: win.img.lz.TV.Coords.Frame,
|
Frame: win.img.lz.TV.Coords.Frame,
|
||||||
|
@ -464,7 +464,7 @@ func (win *winDbgScr) drawReflectionTooltip() {
|
||||||
imguiSeparator()
|
imguiSeparator()
|
||||||
|
|
||||||
// if mouse is over a pixel from the previous frame then show nothing except a note
|
// 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 ||
|
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) {
|
(win.mouse.scanline == win.img.screen.crit.lastScanline && win.mouse.clock > win.img.screen.crit.lastClock) {
|
||||||
imgui.Text("From previous frame")
|
imgui.Text("From previous frame")
|
||||||
|
|
|
@ -18,8 +18,8 @@ package sdlimgui
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/jetsetilly/gopher2600/debugger/govern"
|
||||||
"github.com/jetsetilly/gopher2600/disassembly"
|
"github.com/jetsetilly/gopher2600/disassembly"
|
||||||
"github.com/jetsetilly/gopher2600/emulation"
|
|
||||||
"github.com/jetsetilly/gopher2600/gui/fonts"
|
"github.com/jetsetilly/gopher2600/gui/fonts"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/memory/memorymap"
|
"github.com/jetsetilly/gopher2600/hardware/memory/memorymap"
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ type winDisasm struct {
|
||||||
img *SdlImgui
|
img *SdlImgui
|
||||||
|
|
||||||
// more recently seen emulation state
|
// more recently seen emulation state
|
||||||
lastSeenState emulation.State
|
lastSeenState govern.State
|
||||||
lastSeenPC uint16
|
lastSeenPC uint16
|
||||||
|
|
||||||
// height of options line at bottom of window. valid after first frame
|
// 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
|
// followCPU is set; or the PC has changed (this is because the state
|
||||||
// change might be missed)
|
// 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
|
// live state can cause synchronisation problems meaning focus is lost
|
||||||
if win.followCPU {
|
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.img.lz.CPU.PC.Address() != win.lastSeenPC {
|
||||||
|
|
||||||
win.focusOnAddr = true
|
win.focusOnAddr = true
|
||||||
|
|
|
@ -17,7 +17,7 @@ package sdlimgui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/inkyblackness/imgui-go/v4"
|
"github.com/inkyblackness/imgui-go/v4"
|
||||||
"github.com/jetsetilly/gopher2600/emulation"
|
"github.com/jetsetilly/gopher2600/debugger/govern"
|
||||||
"github.com/jetsetilly/gopher2600/logger"
|
"github.com/jetsetilly/gopher2600/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ func (win *winLog) draw() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// very simple conditions to scroll to the bottom
|
// 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
|
win.scrollToBottom = false
|
||||||
imgui.SetScrollHereY(0.0)
|
imgui.SetScrollHereY(0.0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/inkyblackness/imgui-go/v4"
|
"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/gui/fonts"
|
||||||
"github.com/jetsetilly/gopher2600/logger"
|
"github.com/jetsetilly/gopher2600/logger"
|
||||||
)
|
)
|
||||||
|
@ -106,7 +106,7 @@ func (win *winPrefs) draw() {
|
||||||
imgui.EndTabItem()
|
imgui.EndTabItem()
|
||||||
}
|
}
|
||||||
|
|
||||||
if win.img.mode == emulation.ModeDebugger {
|
if win.img.mode == govern.ModeDebugger {
|
||||||
if imgui.BeginTabItem("Debugger") {
|
if imgui.BeginTabItem("Debugger") {
|
||||||
win.drawDebuggerTab()
|
win.drawDebuggerTab()
|
||||||
imgui.EndTabItem()
|
imgui.EndTabItem()
|
||||||
|
@ -418,9 +418,9 @@ func (win *winPrefs) drawVCS() {
|
||||||
var warning bool
|
var warning bool
|
||||||
|
|
||||||
switch win.img.mode {
|
switch win.img.mode {
|
||||||
case emulation.ModePlay:
|
case govern.ModePlay:
|
||||||
warning = win.img.prefs.audioMutePlaymode.Get().(bool)
|
warning = win.img.prefs.audioMutePlaymode.Get().(bool)
|
||||||
case emulation.ModeDebugger:
|
case govern.ModeDebugger:
|
||||||
warning = win.img.prefs.audioMuteDebugger.Get().(bool)
|
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)
|
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()
|
err = win.img.dbg.Disasm.Prefs.Save()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Logf("sdlimgui", "could not save (disasm) preferences: %v", err)
|
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)
|
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()
|
err = win.img.dbg.Disasm.Prefs.Load()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Logf("sdlimgui", "could not restore (disasm) preferences: %v", err)
|
logger.Logf("sdlimgui", "could not restore (disasm) preferences: %v", err)
|
||||||
|
|
|
@ -20,8 +20,8 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/jetsetilly/gopher2600/debugger/govern"
|
||||||
"github.com/jetsetilly/gopher2600/debugger/terminal"
|
"github.com/jetsetilly/gopher2600/debugger/terminal"
|
||||||
"github.com/jetsetilly/gopher2600/emulation"
|
|
||||||
"github.com/jetsetilly/gopher2600/gui/fonts"
|
"github.com/jetsetilly/gopher2600/gui/fonts"
|
||||||
"github.com/jetsetilly/gopher2600/logger"
|
"github.com/jetsetilly/gopher2600/logger"
|
||||||
"github.com/jetsetilly/gopher2600/resources/unique"
|
"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
|
// the prompt in the terminal should show the disassembly for the
|
||||||
// instruction the PC is *currently* on. in other words, the
|
// instruction the PC is *currently* on. in other words, the
|
||||||
// disassembly for the inesturction to be executed *next*
|
// 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
|
res := win.img.lz.Debugger.LiveDisasmEntry
|
||||||
imgui.Text(res.String())
|
imgui.Text(res.String())
|
||||||
if !win.img.lz.Debugger.LiveDisasmEntry.Result.Final {
|
if !win.img.lz.Debugger.LiveDisasmEntry.Result.Final {
|
||||||
|
|
|
@ -19,7 +19,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/inkyblackness/imgui-go/v4"
|
"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/gui/fonts"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/television/coords"
|
"github.com/jetsetilly/gopher2600/hardware/television/coords"
|
||||||
"github.com/jetsetilly/gopher2600/tracker"
|
"github.com/jetsetilly/gopher2600/tracker"
|
||||||
|
@ -265,7 +265,7 @@ func (win *winTracker) draw() {
|
||||||
|
|
||||||
imgui.EndTable()
|
imgui.EndTable()
|
||||||
|
|
||||||
if win.img.emulation.State() == emulation.Running {
|
if win.img.dbg.State() == govern.Running {
|
||||||
imgui.SetScrollHereY(1.0)
|
imgui.SetScrollHereY(1.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
package gui
|
package gui
|
||||||
|
|
||||||
|
// Stub is a type of convenience that implements the GUI interface.
|
||||||
type Stub struct{}
|
type Stub struct{}
|
||||||
|
|
||||||
// SetFeature implements the GUI interface.
|
// SetFeature implements the GUI interface.
|
||||||
|
|
|
@ -17,7 +17,7 @@ package hardware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/jetsetilly/gopher2600/curated"
|
"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
|
// While the continueCheck() function only runs at the end of a CPU instruction
|
||||||
|
@ -32,19 +32,19 @@ import (
|
||||||
// if performanceFilter >= hardware.PerfomrmanceBrake {
|
// if performanceFilter >= hardware.PerfomrmanceBrake {
|
||||||
// performanceFilter = 0
|
// performanceFilter = 0
|
||||||
// if end_condition == true {
|
// if end_condition == true {
|
||||||
// return emulation.Ending, nill
|
// return govern.Ending, nill
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// return emulation.Running, nill
|
// return govern.Running, nill
|
||||||
//
|
//
|
||||||
const PerformanceBrake = 100
|
const PerformanceBrake = 100
|
||||||
|
|
||||||
// Run sets the emulation running as quickly as possible. continuteCheck()
|
// Run sets the emulation running as quickly as possible. continuteCheck()
|
||||||
// should return false when an external event (eg. a GUI event) indicates that
|
// should return false when an external event (eg. a GUI event) indicates that
|
||||||
// the emulation should stop.
|
// 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 {
|
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
|
// 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
|
var err error
|
||||||
|
|
||||||
state := emulation.Running
|
state := govern.Running
|
||||||
|
|
||||||
for state != emulation.Ending {
|
for state != govern.Ending {
|
||||||
switch state {
|
switch state {
|
||||||
case emulation.Running:
|
case govern.Running:
|
||||||
err := vcs.CPU.ExecuteInstruction(videoCycle)
|
err := vcs.CPU.ExecuteInstruction(videoCycle)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case emulation.Paused:
|
case govern.Paused:
|
||||||
default:
|
default:
|
||||||
return curated.Errorf("vcs: unsupported emulation state (%d) in Run() function", state)
|
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.
|
// RunForFrameCount sets emulator running for the specified number of frames.
|
||||||
// Useful for FPS and regression tests. Not used by the debugger because traps
|
// Useful for FPS and regression tests. Not used by the debugger because traps
|
||||||
// (and volatile traps) are more flexible.
|
// (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 {
|
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
|
frameNum := vcs.TV.GetCoords().Frame
|
||||||
targetFrame := frameNum + numFrames
|
targetFrame := frameNum + numFrames
|
||||||
|
|
||||||
state := emulation.Running
|
state := govern.Running
|
||||||
for frameNum != targetFrame && state != emulation.Ending {
|
for frameNum != targetFrame && state != govern.Ending {
|
||||||
err := vcs.Step(nil)
|
err := vcs.Step(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -20,7 +20,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/jetsetilly/gopher2600/curated"
|
"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/coords"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/television/signal"
|
"github.com/jetsetilly/gopher2600/hardware/television/signal"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/television/specification"
|
"github.com/jetsetilly/gopher2600/hardware/television/specification"
|
||||||
|
@ -174,7 +174,7 @@ type Television struct {
|
||||||
prevSignalFirst int
|
prevSignalFirst int
|
||||||
|
|
||||||
// state of emulation
|
// state of emulation
|
||||||
emulationState emulation.State
|
emulationState govern.State
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTelevision creates a new instance of the television type, satisfying the
|
// 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
|
// check for realtime mixing requirements. if it is required then
|
||||||
// immediately push the audio data from the previous frame to the mixer
|
// 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() {
|
if tv.realtimeMixer.MoreAudio() {
|
||||||
err := tv.realtimeMixer.SetAudio(tv.prevSignals[:tv.prevSignalLastIdx])
|
err := tv.realtimeMixer.SetAudio(tv.prevSignals[:tv.prevSignalLastIdx])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -669,7 +669,7 @@ func (tv *Television) newFrame(fromVsync bool) error {
|
||||||
// renderers and audio mixers.
|
// renderers and audio mixers.
|
||||||
func (tv *Television) renderSignals() error {
|
func (tv *Television) renderSignals() error {
|
||||||
// do not render pixels if emulation is in the rewinding state
|
// 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 {
|
for _, r := range tv.renderers {
|
||||||
err := r.SetPixels(tv.signals, tv.currentSignalIdx)
|
err := r.SetPixels(tv.signals, tv.currentSignalIdx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -768,23 +768,23 @@ func (tv *Television) SetSpec(spec string) error {
|
||||||
|
|
||||||
// SetEmulationState is called by emulation whenever state changes. How we
|
// SetEmulationState is called by emulation whenever state changes. How we
|
||||||
// handle incoming signals depends on the current state.
|
// 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
|
prev := tv.emulationState
|
||||||
tv.emulationState = state
|
tv.emulationState = state
|
||||||
|
|
||||||
switch prev {
|
switch prev {
|
||||||
case emulation.Paused:
|
case govern.Paused:
|
||||||
// start off the unpaused state by measuring the current framerate.
|
// start off the unpaused state by measuring the current framerate.
|
||||||
// this "clears" the ticker channel and means the feedback from
|
// this "clears" the ticker channel and means the feedback from
|
||||||
// GetActualFPS() is less misleading
|
// GetActualFPS() is less misleading
|
||||||
tv.lmtr.measureActual()
|
tv.lmtr.measureActual()
|
||||||
|
|
||||||
case emulation.Rewinding:
|
case govern.Rewinding:
|
||||||
tv.renderSignals()
|
tv.renderSignals()
|
||||||
}
|
}
|
||||||
|
|
||||||
switch state {
|
switch state {
|
||||||
case emulation.Paused:
|
case govern.Paused:
|
||||||
err := tv.renderSignals()
|
err := tv.renderSignals()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -22,11 +22,10 @@ import (
|
||||||
|
|
||||||
"github.com/jetsetilly/gopher2600/cartridgeloader"
|
"github.com/jetsetilly/gopher2600/cartridgeloader"
|
||||||
"github.com/jetsetilly/gopher2600/curated"
|
"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"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/television"
|
"github.com/jetsetilly/gopher2600/hardware/television"
|
||||||
"github.com/jetsetilly/gopher2600/setup"
|
"github.com/jetsetilly/gopher2600/setup"
|
||||||
"github.com/jetsetilly/gopher2600/userinput"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// sentinal error returned by Run() loop.
|
// sentinal error returned by Run() loop.
|
||||||
|
@ -100,7 +99,7 @@ func Check(output io.Writer, profile Profile, cartload cartridgeloader.Loader, s
|
||||||
performanceBrake := 0
|
performanceBrake := 0
|
||||||
|
|
||||||
// run until specified time elapses
|
// run until specified time elapses
|
||||||
err = vcs.Run(func() (emulation.State, error) {
|
err = vcs.Run(func() (govern.State, error) {
|
||||||
for {
|
for {
|
||||||
performanceBrake++
|
performanceBrake++
|
||||||
if performanceBrake >= hardware.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
|
// period has finished, return false to cause vcs.Run() to
|
||||||
// return
|
// return
|
||||||
if v {
|
if v {
|
||||||
return emulation.Ending, curated.Errorf(timedOut)
|
return govern.Ending, curated.Errorf(timedOut)
|
||||||
}
|
}
|
||||||
|
|
||||||
// timerChan has returned false which indicates that the
|
// timerChan has returned false which indicates that the
|
||||||
|
@ -121,11 +120,11 @@ func Check(output io.Writer, profile Profile, cartload cartridgeloader.Loader, s
|
||||||
// frame.
|
// frame.
|
||||||
startFrame = tv.GetCoords().Frame
|
startFrame = tv.GetCoords().Frame
|
||||||
default:
|
default:
|
||||||
return emulation.Running, nil
|
return govern.Running, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return emulation.Running, nil
|
return govern.Running, nil
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
|
@ -148,38 +147,3 @@ func Check(output io.Writer, profile Profile, cartload cartridgeloader.Loader, s
|
||||||
|
|
||||||
return nil
|
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ package reflection
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/jetsetilly/gopher2600/curated"
|
"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"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/mapper"
|
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/mapper"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/television"
|
"github.com/jetsetilly/gopher2600/hardware/television"
|
||||||
|
@ -30,7 +30,7 @@ import (
|
||||||
type Reflector struct {
|
type Reflector struct {
|
||||||
vcs *hardware.VCS
|
vcs *hardware.VCS
|
||||||
renderer Renderer
|
renderer Renderer
|
||||||
emulationState emulation.State
|
emulationState govern.State
|
||||||
|
|
||||||
history []ReflectedVideoStep
|
history []ReflectedVideoStep
|
||||||
|
|
||||||
|
@ -57,17 +57,17 @@ func (ref *Reflector) Clear() {
|
||||||
|
|
||||||
// SetEmulationState is called by emulation whenever state changes. How we
|
// SetEmulationState is called by emulation whenever state changes. How we
|
||||||
// handle reflections depends on the current state.
|
// handle reflections depends on the current state.
|
||||||
func (ref *Reflector) SetEmulationState(state emulation.State) {
|
func (ref *Reflector) SetEmulationState(state govern.State) {
|
||||||
prev := ref.emulationState
|
prev := ref.emulationState
|
||||||
ref.emulationState = state
|
ref.emulationState = state
|
||||||
|
|
||||||
switch prev {
|
switch prev {
|
||||||
case emulation.Rewinding:
|
case govern.Rewinding:
|
||||||
ref.render()
|
ref.render()
|
||||||
}
|
}
|
||||||
|
|
||||||
switch state {
|
switch state {
|
||||||
case emulation.Paused:
|
case govern.Paused:
|
||||||
err := ref.render()
|
err := ref.render()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Logf("reflection", "%v", err)
|
logger.Logf("reflection", "%v", err)
|
||||||
|
@ -125,7 +125,7 @@ func (ref *Reflector) Step(bank mapper.BankInfo) error {
|
||||||
|
|
||||||
// push history to reflection renderer
|
// push history to reflection renderer
|
||||||
func (ref *Reflector) render() error {
|
func (ref *Reflector) render() error {
|
||||||
if ref.emulationState != emulation.Rewinding {
|
if ref.emulationState != govern.Rewinding {
|
||||||
if ref.renderer != nil {
|
if ref.renderer != nil {
|
||||||
if err := ref.renderer.Reflect(ref.history); err != nil {
|
if err := ref.renderer.Reflect(ref.history); err != nil {
|
||||||
return curated.Errorf("reflection: %v", err)
|
return curated.Errorf("reflection: %v", err)
|
||||||
|
|
|
@ -26,7 +26,7 @@ import (
|
||||||
"github.com/jetsetilly/gopher2600/cartridgeloader"
|
"github.com/jetsetilly/gopher2600/cartridgeloader"
|
||||||
"github.com/jetsetilly/gopher2600/curated"
|
"github.com/jetsetilly/gopher2600/curated"
|
||||||
"github.com/jetsetilly/gopher2600/database"
|
"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"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/television"
|
"github.com/jetsetilly/gopher2600/hardware/television"
|
||||||
"github.com/jetsetilly/gopher2600/logger"
|
"github.com/jetsetilly/gopher2600/logger"
|
||||||
|
@ -160,7 +160,7 @@ func (reg *LogRegression) regress(newRegression bool, output io.Writer, msg stri
|
||||||
logOutput := &strings.Builder{}
|
logOutput := &strings.Builder{}
|
||||||
|
|
||||||
// run emulation
|
// 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
|
// display progress meter every 1 second
|
||||||
select {
|
select {
|
||||||
case <-tck.C:
|
case <-tck.C:
|
||||||
|
@ -170,7 +170,7 @@ func (reg *LogRegression) regress(newRegression bool, output io.Writer, msg stri
|
||||||
|
|
||||||
logger.WriteRecent(logOutput)
|
logger.WriteRecent(logOutput)
|
||||||
|
|
||||||
return emulation.Running, nil
|
return govern.Running, nil
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -25,8 +25,8 @@ import (
|
||||||
|
|
||||||
"github.com/jetsetilly/gopher2600/curated"
|
"github.com/jetsetilly/gopher2600/curated"
|
||||||
"github.com/jetsetilly/gopher2600/database"
|
"github.com/jetsetilly/gopher2600/database"
|
||||||
|
"github.com/jetsetilly/gopher2600/debugger/govern"
|
||||||
"github.com/jetsetilly/gopher2600/digest"
|
"github.com/jetsetilly/gopher2600/digest"
|
||||||
"github.com/jetsetilly/gopher2600/emulation"
|
|
||||||
"github.com/jetsetilly/gopher2600/hardware"
|
"github.com/jetsetilly/gopher2600/hardware"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/riot/ports"
|
"github.com/jetsetilly/gopher2600/hardware/riot/ports"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/television"
|
"github.com/jetsetilly/gopher2600/hardware/television"
|
||||||
|
@ -150,13 +150,13 @@ func (reg *PlaybackRegression) regress(newRegression bool, output io.Writer, msg
|
||||||
tck := time.NewTicker(dur)
|
tck := time.NewTicker(dur)
|
||||||
|
|
||||||
// run emulation
|
// run emulation
|
||||||
err = vcs.Run(func() (emulation.State, error) {
|
err = vcs.Run(func() (govern.State, error) {
|
||||||
hasEnded, err := plb.EndFrame()
|
hasEnded, err := plb.EndFrame()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return emulation.Ending, curated.Errorf("playback: %v", err)
|
return govern.Ending, curated.Errorf("playback: %v", err)
|
||||||
}
|
}
|
||||||
if hasEnded {
|
if hasEnded {
|
||||||
return emulation.Ending, curated.Errorf("playback: ended unexpectedly")
|
return govern.Ending, curated.Errorf("playback: ended unexpectedly")
|
||||||
}
|
}
|
||||||
|
|
||||||
// display progress meter every 1 second
|
// 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)))
|
output.Write([]byte(fmt.Sprintf("\r%s [%s]", msg, plb)))
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
return emulation.Running, nil
|
return govern.Running, nil
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -27,8 +27,8 @@ import (
|
||||||
"github.com/jetsetilly/gopher2600/cartridgeloader"
|
"github.com/jetsetilly/gopher2600/cartridgeloader"
|
||||||
"github.com/jetsetilly/gopher2600/curated"
|
"github.com/jetsetilly/gopher2600/curated"
|
||||||
"github.com/jetsetilly/gopher2600/database"
|
"github.com/jetsetilly/gopher2600/database"
|
||||||
|
"github.com/jetsetilly/gopher2600/debugger/govern"
|
||||||
"github.com/jetsetilly/gopher2600/digest"
|
"github.com/jetsetilly/gopher2600/digest"
|
||||||
"github.com/jetsetilly/gopher2600/emulation"
|
|
||||||
"github.com/jetsetilly/gopher2600/hardware"
|
"github.com/jetsetilly/gopher2600/hardware"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/television"
|
"github.com/jetsetilly/gopher2600/hardware/television"
|
||||||
"github.com/jetsetilly/gopher2600/setup"
|
"github.com/jetsetilly/gopher2600/setup"
|
||||||
|
@ -232,7 +232,7 @@ func (reg *VideoRegression) regress(newRegression bool, output io.Writer, msg st
|
||||||
tck := time.NewTicker(dur)
|
tck := time.NewTicker(dur)
|
||||||
|
|
||||||
// run emulation
|
// 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
|
// display progress meter every 1 second
|
||||||
select {
|
select {
|
||||||
case <-tck.C:
|
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 {
|
if err != nil {
|
||||||
|
|
|
@ -20,7 +20,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/jetsetilly/gopher2600/curated"
|
"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"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/cpu"
|
"github.com/jetsetilly/gopher2600/hardware/cpu"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/memory"
|
"github.com/jetsetilly/gopher2600/hardware/memory"
|
||||||
|
@ -32,6 +32,13 @@ import (
|
||||||
"github.com/jetsetilly/gopher2600/logger"
|
"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.
|
// Runner provides the rewind package the opportunity to run the emulation.
|
||||||
type Runner interface {
|
type Runner interface {
|
||||||
// CatchupLoop should loop until the frame/scanline/clock coordinates are
|
// 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.
|
// Rewind contains a history of machine states for the emulation.
|
||||||
type Rewind struct {
|
type Rewind struct {
|
||||||
emulation emulation.Emulation
|
emulation Emulation
|
||||||
vcs *hardware.VCS
|
vcs *hardware.VCS
|
||||||
runner Runner
|
runner Runner
|
||||||
|
|
||||||
|
@ -145,10 +152,10 @@ type Rewind struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRewind is the preferred method of initialisation for the Rewind type.
|
// 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{
|
r := &Rewind{
|
||||||
emulation: emulation,
|
emulation: emulation,
|
||||||
vcs: emulation.VCS().(*hardware.VCS),
|
vcs: emulation.VCS(),
|
||||||
runner: runner,
|
runner: runner,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,7 +450,7 @@ type findResults struct {
|
||||||
// the one that is requested.
|
// the one that is requested.
|
||||||
func (r *Rewind) findFrameIndex(frame int) findResults {
|
func (r *Rewind) findFrameIndex(frame int) findResults {
|
||||||
searchFrame := frame - 1
|
searchFrame := frame - 1
|
||||||
if r.emulation.Mode() == emulation.ModeDebugger {
|
if r.emulation.Mode() == govern.ModeDebugger {
|
||||||
searchFrame--
|
searchFrame--
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ package rewind
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/jetsetilly/gopher2600/curated"
|
"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"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/television/specification"
|
"github.com/jetsetilly/gopher2600/hardware/television/specification"
|
||||||
)
|
)
|
||||||
|
@ -160,7 +160,7 @@ func (r *Rewind) GetTimeline() Timeline {
|
||||||
|
|
||||||
func (r *Rewind) addTimelineEntry(frameInfo television.FrameInfo) {
|
func (r *Rewind) addTimelineEntry(frameInfo television.FrameInfo) {
|
||||||
// do not alter the timeline information if we're in the rewinding state
|
// 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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ import (
|
||||||
|
|
||||||
"github.com/jetsetilly/gopher2600/cartridgeloader"
|
"github.com/jetsetilly/gopher2600/cartridgeloader"
|
||||||
"github.com/jetsetilly/gopher2600/curated"
|
"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"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/instance"
|
"github.com/jetsetilly/gopher2600/hardware/instance"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/mapper"
|
"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
|
tgtFrame := thmb.vcs.TV.GetCoords().Frame + numFrames
|
||||||
|
|
||||||
err = thmb.vcs.Run(func() (emulation.State, error) {
|
err = thmb.vcs.Run(func() (govern.State, error) {
|
||||||
select {
|
select {
|
||||||
case <-thmb.emulationQuit:
|
case <-thmb.emulationQuit:
|
||||||
return emulation.Ending, nil
|
return govern.Ending, nil
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
if numFrames != UndefinedNumFrames && thmb.vcs.TV.GetCoords().Frame >= tgtFrame {
|
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 {
|
if err != nil {
|
||||||
logger.Logf("thumbnailer", err.Error())
|
logger.Logf("thumbnailer", err.Error())
|
||||||
|
@ -235,17 +235,17 @@ func (thmb *Thumbnailer) SingleFrameFromRewindState(state *rewind.State) {
|
||||||
// run until target frame has been generated
|
// run until target frame has been generated
|
||||||
tgtFrame := thmb.vcs.TV.GetCoords().Frame + 1
|
tgtFrame := thmb.vcs.TV.GetCoords().Frame + 1
|
||||||
|
|
||||||
err := thmb.vcs.Run(func() (emulation.State, error) {
|
err := thmb.vcs.Run(func() (govern.State, error) {
|
||||||
select {
|
select {
|
||||||
case <-thmb.emulationQuit:
|
case <-thmb.emulationQuit:
|
||||||
return emulation.Ending, nil
|
return govern.Ending, nil
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
if thmb.vcs.TV.GetCoords().Frame >= tgtFrame {
|
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 {
|
if err != nil {
|
||||||
|
|
|
@ -16,12 +16,18 @@
|
||||||
package tracker
|
package tracker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/jetsetilly/gopher2600/emulation"
|
"github.com/jetsetilly/gopher2600/debugger/govern"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/television"
|
"github.com/jetsetilly/gopher2600/hardware/television"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/television/coords"
|
"github.com/jetsetilly/gopher2600/hardware/television/coords"
|
||||||
"github.com/jetsetilly/gopher2600/hardware/tia/audio"
|
"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 {
|
type Entry struct {
|
||||||
Coords coords.TelevisionCoords
|
Coords coords.TelevisionCoords
|
||||||
Channel int
|
Channel int
|
||||||
|
@ -35,7 +41,7 @@ type Entry struct {
|
||||||
// Tracker implements the audio.Tracker interface and keeps a history of the
|
// Tracker implements the audio.Tracker interface and keeps a history of the
|
||||||
// audio registers over time.
|
// audio registers over time.
|
||||||
type Tracker struct {
|
type Tracker struct {
|
||||||
emulation emulation.Emulation
|
emulation Emulation
|
||||||
|
|
||||||
entries []Entry
|
entries []Entry
|
||||||
|
|
||||||
|
@ -49,7 +55,7 @@ type Tracker struct {
|
||||||
const maxTrackerEntries = 1024
|
const maxTrackerEntries = 1024
|
||||||
|
|
||||||
// NewTracker is the preferred method of initialisation for the Tracker type.
|
// NewTracker is the preferred method of initialisation for the Tracker type.
|
||||||
func NewTracker(emulation emulation.Emulation) *Tracker {
|
func NewTracker(emulation Emulation) *Tracker {
|
||||||
return &Tracker{
|
return &Tracker{
|
||||||
emulation: emulation,
|
emulation: emulation,
|
||||||
entries: make([]Entry, 0, maxTrackerEntries),
|
entries: make([]Entry, 0, maxTrackerEntries),
|
||||||
|
@ -63,7 +69,7 @@ func (tr *Tracker) Reset() {
|
||||||
|
|
||||||
// Tick implements the audio.Tracker interface
|
// Tick implements the audio.Tracker interface
|
||||||
func (tr *Tracker) Tick(channel int, reg audio.Registers) {
|
func (tr *Tracker) Tick(channel int, reg audio.Registers) {
|
||||||
if tr.emulation.State() == emulation.Rewinding {
|
if tr.emulation.State() == govern.Rewinding {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +77,7 @@ func (tr *Tracker) Tick(channel int, reg audio.Registers) {
|
||||||
tr.prevRegister[channel] = reg
|
tr.prevRegister[channel] = reg
|
||||||
|
|
||||||
if changed {
|
if changed {
|
||||||
tv := tr.emulation.TV().(*television.Television)
|
tv := tr.emulation.TV()
|
||||||
|
|
||||||
e := Entry{
|
e := Entry{
|
||||||
Coords: tv.GetCoords(),
|
Coords: tv.GetCoords(),
|
||||||
|
|
Loading…
Reference in a new issue