mirror of
https://github.com/JetSetIlly/Gopher2600.git
synced 2024-05-20 13:48:02 -04:00
Compare commits
3 commits
545caefbfa
...
d7b8f19c21
Author | SHA1 | Date | |
---|---|---|---|
d7b8f19c21 | |||
578e2a846a | |||
8e4838d582 |
|
@ -17,6 +17,7 @@ package sdlimgui
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/inkyblackness/imgui-go/v4"
|
||||
|
@ -68,6 +69,9 @@ type playscrOverlay struct {
|
|||
fps string
|
||||
hz string
|
||||
|
||||
// memory stats are updated along with the fpsPulse
|
||||
memStats runtime.MemStats
|
||||
|
||||
// top-left corner of the overlay includes emulation state. if the
|
||||
// "fpsOverlay" is active then these will be drawn alongside the FPS
|
||||
// information
|
||||
|
@ -195,6 +199,7 @@ func (oly *playscrOverlay) drawTopLeft() {
|
|||
fps, hz := oly.playscr.img.dbg.VCS().TV.GetActualFPS()
|
||||
oly.fps = fmt.Sprintf("%03.2f fps", fps)
|
||||
oly.hz = fmt.Sprintf("%03.2fhz", hz)
|
||||
runtime.ReadMemStats(&oly.memStats)
|
||||
default:
|
||||
}
|
||||
|
||||
|
@ -234,6 +239,14 @@ func (oly *playscrOverlay) drawTopLeft() {
|
|||
imgui.Text(string(fonts.Nudge))
|
||||
}
|
||||
|
||||
if oly.playscr.img.prefs.memoryUsageInOverlay.Get().(bool) {
|
||||
imguiSeparator()
|
||||
imgui.Text(fmt.Sprintf("Alloc = %v MB\n", oly.memStats.Alloc/1048576))
|
||||
imgui.Text(fmt.Sprintf(" TotalAlloc = %v MB\n", oly.memStats.TotalAlloc/1048576))
|
||||
imgui.Text(fmt.Sprintf(" Sys = %v MB\n", oly.memStats.Sys/1048576))
|
||||
imgui.Text(fmt.Sprintf(" NumGC = %v", oly.memStats.NumGC))
|
||||
}
|
||||
|
||||
// create space in the window for any icons that we might want to draw.
|
||||
// what's good about this is that it makes sure that the window is large
|
||||
// enough from frame-to-frame. without this, there will be a visble
|
||||
|
|
|
@ -60,6 +60,7 @@ type preferences struct {
|
|||
superchargerNotifications prefs.Bool
|
||||
audioMuteNotification prefs.Bool
|
||||
notificationVisibility prefs.Float
|
||||
memoryUsageInOverlay prefs.Bool
|
||||
|
||||
// fonts
|
||||
guiFontSize prefs.Int
|
||||
|
@ -98,6 +99,7 @@ func newPreferences(img *SdlImgui) (*preferences, error) {
|
|||
p.superchargerNotifications.Set(true)
|
||||
p.audioMuteNotification.Set(true)
|
||||
p.notificationVisibility.Set(0.75)
|
||||
p.memoryUsageInOverlay.Set(false)
|
||||
p.guiFontSize.Set(13)
|
||||
p.terminalFontSize.Set(12)
|
||||
p.codeFontSize.Set(15)
|
||||
|
@ -166,6 +168,10 @@ func newPreferences(img *SdlImgui) (*preferences, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = p.dsk.Add("sdlimgui.playmode.memoryUsageInOverlay", &p.memoryUsageInOverlay)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// playmode audio mute options later
|
||||
|
||||
|
|
|
@ -216,7 +216,7 @@ a television image that is sympathetic to the display kernel
|
|||
of the ROM.`)
|
||||
|
||||
imgui.Spacing()
|
||||
if imgui.CollapsingHeader("Notification Icons") {
|
||||
if imgui.CollapsingHeader("Notification Overlay") {
|
||||
controllerNotifications := win.img.prefs.controllerNotifcations.Get().(bool)
|
||||
if imgui.Checkbox("Controller Changes", &controllerNotifications) {
|
||||
win.img.prefs.controllerNotifcations.Set(controllerNotifications)
|
||||
|
@ -241,6 +241,11 @@ of the ROM.`)
|
|||
if imgui.SliderFloatV("Visibility", &visibility, 0.0, 100.0, "%.0f%%", imgui.SliderFlagsNone) {
|
||||
win.img.prefs.notificationVisibility.Set(visibility / 100)
|
||||
}
|
||||
|
||||
memoryUsageInOverlay := win.img.prefs.memoryUsageInOverlay.Get().(bool)
|
||||
if imgui.Checkbox("Memory Usage in FPS Overlay", &memoryUsageInOverlay) {
|
||||
win.img.prefs.memoryUsageInOverlay.Set(memoryUsageInOverlay)
|
||||
}
|
||||
}
|
||||
|
||||
imgui.Spacing()
|
||||
|
|
|
@ -106,7 +106,7 @@ func (cart *Ace) PlumbFromDifferentEmulation(env *environment.Environment) {
|
|||
}
|
||||
cart.arm = arm.NewARM(cart.env, cart.mem.model, cart.mem, cart)
|
||||
cart.mem.Plumb(cart.arm)
|
||||
cart.arm.Plumb(cart.armState, cart.mem, cart)
|
||||
cart.arm.Plumb(cart.env, cart.armState, cart.mem, cart)
|
||||
cart.armState = nil
|
||||
cart.yieldHook = coprocessor.StubCartYieldHook{}
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ func (cart *Ace) Plumb(env *environment.Environment) {
|
|||
panic("cannot plumb this ELF instance because the ARM state is nil")
|
||||
}
|
||||
cart.mem.Plumb(cart.arm)
|
||||
cart.arm.Plumb(cart.armState, cart.mem, cart)
|
||||
cart.arm.Plumb(cart.env, cart.armState, cart.mem, cart)
|
||||
cart.armState = nil
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@ import (
|
|||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/jetsetilly/gopher2600/coprocessor"
|
||||
"github.com/jetsetilly/gopher2600/coprocessor/developer/faults"
|
||||
|
@ -190,12 +189,18 @@ type ARMState struct {
|
|||
instruction32bitOpcodeHi uint16
|
||||
}
|
||||
|
||||
// Snapshort makes a copy of the ARMState.
|
||||
// Snapshot implements the mapper.CartMapper interface.
|
||||
func (s *ARMState) Snapshot() *ARMState {
|
||||
n := *s
|
||||
return &n
|
||||
}
|
||||
|
||||
// Plumb implements the mapper.CartMapper interface.
|
||||
func (s *ARMState) Plumb(env *environment.Environment) {
|
||||
s.mam.Plumb(env)
|
||||
s.rng.Plumb(env)
|
||||
}
|
||||
|
||||
// ARM implements the ARM7TDMI-S LPC2103 processor.
|
||||
type ARM struct {
|
||||
env *environment.Environment
|
||||
|
@ -214,12 +219,7 @@ type ARM struct {
|
|||
// state of the ARM. saveable and restorable
|
||||
state *ARMState
|
||||
|
||||
// updating the preferences every time run() is executed can be slow
|
||||
// (because the preferences need to be synchronised between tasks). the
|
||||
// prefsPulse ticker slows the rate at which updatePrefs() is called
|
||||
prefsPulse *time.Ticker
|
||||
|
||||
// read from ARM.prefs every prefsPulse tick
|
||||
// updated on every call to run()
|
||||
abortOnMemoryFault bool
|
||||
misalignedAccessIsFault bool
|
||||
|
||||
|
@ -261,7 +261,8 @@ type ARM struct {
|
|||
// interface to an option development package
|
||||
dev coprocessor.CartCoProcDeveloper
|
||||
|
||||
// whether cycle count or not. set from ARM.prefs at the start of every arm.Run()
|
||||
// immediateMode controls whether cycle count or not. value updated from
|
||||
// updatePrefs()
|
||||
//
|
||||
// used to cut out code that is required only for cycle counting. See
|
||||
// Icycle, Scycle and Ncycle fields which are called so frequently we
|
||||
|
@ -294,12 +295,7 @@ func NewARM(env *environment.Environment, mmap architecture.Map, mem SharedMemor
|
|||
hook: hook,
|
||||
byteOrder: binary.LittleEndian,
|
||||
executionCache: make(map[uint32][]decodeFunction),
|
||||
|
||||
// updated on every updatePrefs(). these are reasonable defaults
|
||||
Clk: 70.0,
|
||||
clklenFlash: 4.0,
|
||||
|
||||
state: &ARMState{},
|
||||
state: &ARMState{},
|
||||
}
|
||||
|
||||
// disassembly printed to stdout
|
||||
|
@ -307,9 +303,6 @@ func NewARM(env *environment.Environment, mmap architecture.Map, mem SharedMemor
|
|||
arm.disasm = &coprocessor.CartCoProcDisassemblerStdout{}
|
||||
}
|
||||
|
||||
// slow prefs update by 100ms
|
||||
arm.prefsPulse = time.NewTicker(time.Millisecond * 100)
|
||||
|
||||
switch arm.mmap.ARMArchitecture {
|
||||
case architecture.ARM7TDMI:
|
||||
arm.stepFunction = arm.stepARM7TDMI
|
||||
|
@ -366,7 +359,7 @@ func (arm *ARM) SetDeveloper(dev coprocessor.CartCoProcDeveloper) {
|
|||
arm.dev = dev
|
||||
}
|
||||
|
||||
// Snapshort makes a copy of the ARM state.
|
||||
// Snapshot implements the mapper.CartMapper interface.
|
||||
func (arm *ARM) Snapshot() *ARMState {
|
||||
return arm.state.Snapshot()
|
||||
}
|
||||
|
@ -377,25 +370,32 @@ func (arm *ARM) Snapshot() *ARMState {
|
|||
// The ARMState argument can be nil as a special case. If it is nil then the
|
||||
// existing state does not change. For some cartridge mappers this is acceptable
|
||||
// and more convenient
|
||||
func (arm *ARM) Plumb(state *ARMState, mem SharedMemory, hook CartridgeHook) {
|
||||
//
|
||||
// Plumb implements the mapper.CartMapper interface.
|
||||
func (arm *ARM) Plumb(env *environment.Environment, state *ARMState, mem SharedMemory, hook CartridgeHook) {
|
||||
arm.env = env
|
||||
arm.mem = mem
|
||||
arm.hook = hook
|
||||
|
||||
// always clear caches on a plumb event
|
||||
arm.ClearCaches()
|
||||
|
||||
if state != nil {
|
||||
arm.state = state
|
||||
arm.state.Plumb(env)
|
||||
}
|
||||
|
||||
// if we're plumbing in a new state then we *must* reevaluate the
|
||||
// pointer the program memory
|
||||
// any more plumbing work is superfluous unless we're dealing with the main
|
||||
// emulation environment
|
||||
if !arm.env.IsEmulation(environment.MainEmulation) {
|
||||
return
|
||||
}
|
||||
|
||||
// if we're plumbing in a new state then we *must* reevaluate the
|
||||
// pointer the program memory
|
||||
if state != nil {
|
||||
arm.checkProgramMemory(true)
|
||||
}
|
||||
}
|
||||
|
||||
// ClearCaches should be used very rarely. It empties the instruction and
|
||||
// disassembly caches.
|
||||
func (arm *ARM) ClearCaches() {
|
||||
// execution cache must be cleared because the old cache will be pointing to
|
||||
// functions in another instance of ARM
|
||||
arm.executionCache = make(map[uint32][]decodeFunction)
|
||||
}
|
||||
|
||||
|
@ -436,8 +436,7 @@ func (arm *ARM) resetRegisters() {
|
|||
}
|
||||
|
||||
// updatePrefs should be called periodically to ensure that the current
|
||||
// preference values are being used in the ARM emulation. see also the
|
||||
// prefsPulse ticker
|
||||
// preference values are being used in the ARM emulation
|
||||
func (arm *ARM) updatePrefs() {
|
||||
// update clock value from preferences
|
||||
arm.Clk = float32(arm.env.Prefs.ARM.Clock.Get().(float64))
|
||||
|
@ -756,11 +755,7 @@ func (arm *ARM) checkProgramMemory(force bool) {
|
|||
}
|
||||
|
||||
func (arm *ARM) run() (coprocessor.CoProcYield, float32) {
|
||||
select {
|
||||
case <-arm.prefsPulse.C:
|
||||
arm.updatePrefs()
|
||||
default:
|
||||
}
|
||||
arm.updatePrefs()
|
||||
|
||||
// number of iterations. only used when in immediate mode
|
||||
var iterations int
|
||||
|
|
|
@ -59,7 +59,8 @@ func newMam(env *environment.Environment, mmap architecture.Map) mam {
|
|||
}
|
||||
}
|
||||
|
||||
func (m *mam) Reset() {
|
||||
func (m *mam) Plumb(env *environment.Environment) {
|
||||
m.env = env
|
||||
}
|
||||
|
||||
func (m *mam) updatePrefs() {
|
||||
|
|
|
@ -57,6 +57,10 @@ func NewRNG(env *environment.Environment, mmap architecture.Map) RNG {
|
|||
}
|
||||
}
|
||||
|
||||
func (r *RNG) Plumb(env *environment.Environment) {
|
||||
r.env = env
|
||||
}
|
||||
|
||||
func (r *RNG) Reset() {
|
||||
r.control = 0x0
|
||||
}
|
||||
|
|
|
@ -170,7 +170,7 @@ func (cart *cdf) Plumb(env *environment.Environment) {
|
|||
if cart.armState == nil {
|
||||
panic("cannot plumb this ELF instance because the ARM state is nil")
|
||||
}
|
||||
cart.arm.Plumb(cart.armState, cart.state.static, cart)
|
||||
cart.arm.Plumb(cart.env, cart.armState, cart.state.static, cart)
|
||||
cart.armState = nil
|
||||
}
|
||||
|
||||
|
@ -181,7 +181,7 @@ func (cart *cdf) PlumbFromDifferentEmulation(env *environment.Environment) {
|
|||
panic("cannot plumb this ELF instance because the ARM state is nil")
|
||||
}
|
||||
cart.arm = arm.NewARM(cart.env, cart.version.mmap, cart.state.static, cart)
|
||||
cart.arm.Plumb(cart.armState, cart.state.static, cart)
|
||||
cart.arm.Plumb(cart.env, cart.armState, cart.state.static, cart)
|
||||
cart.armState = nil
|
||||
cart.yieldHook = &coprocessor.StubCartYieldHook{}
|
||||
}
|
||||
|
|
|
@ -155,7 +155,7 @@ func (cart *dpcPlus) Plumb(env *environment.Environment) {
|
|||
if cart.armState == nil {
|
||||
panic("cannot plumb this ELF instance because the ARM state is nil")
|
||||
}
|
||||
cart.arm.Plumb(cart.armState, cart.state.static, cart)
|
||||
cart.arm.Plumb(cart.env, cart.armState, cart.state.static, cart)
|
||||
cart.armState = nil
|
||||
}
|
||||
|
||||
|
@ -166,7 +166,7 @@ func (cart *dpcPlus) PlumbFromDifferentEmulation(env *environment.Environment) {
|
|||
panic("cannot plumb this ELF instance because the ARM state is nil")
|
||||
}
|
||||
cart.arm = arm.NewARM(cart.env, cart.version.mmap, cart.state.static, cart)
|
||||
cart.arm.Plumb(cart.armState, cart.state.static, cart)
|
||||
cart.arm.Plumb(cart.env, cart.armState, cart.state.static, cart)
|
||||
cart.armState = nil
|
||||
cart.yieldHook = &coprocessor.StubCartYieldHook{}
|
||||
}
|
||||
|
|
|
@ -192,7 +192,7 @@ func (cart *Elf) PlumbFromDifferentEmulation(env *environment.Environment) {
|
|||
panic("cannot plumb this ELF instance because the ARM state is nil")
|
||||
}
|
||||
cart.arm = arm.NewARM(cart.env, cart.mem.model, cart.mem, cart)
|
||||
cart.arm.Plumb(cart.armState, cart.mem, cart)
|
||||
cart.arm.Plumb(cart.env, cart.armState, cart.mem, cart)
|
||||
cart.armState = nil
|
||||
cart.mem.Plumb(cart.arm)
|
||||
cart.yieldHook = &coprocessor.StubCartYieldHook{}
|
||||
|
@ -205,7 +205,7 @@ func (cart *Elf) Plumb(env *environment.Environment) {
|
|||
panic("cannot plumb this ELF instance because the ARM state is nil")
|
||||
}
|
||||
cart.mem.Plumb(cart.arm)
|
||||
cart.arm.Plumb(cart.armState, cart.mem, cart)
|
||||
cart.arm.Plumb(cart.env, cart.armState, cart.mem, cart)
|
||||
cart.armState = nil
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue