diff --git a/frontend/desktop/.gitignore b/frontend/desktop/.gitignore index fe08cbe..84c1e55 100644 --- a/frontend/desktop/.gitignore +++ b/frontend/desktop/.gitignore @@ -2,4 +2,5 @@ __debug_bin* imgui.ini spiflash.bin -.vscode \ No newline at end of file +.vscode +state.bin \ No newline at end of file diff --git a/frontend/desktop/emulator/emulator.go b/frontend/desktop/emulator/emulator.go index d262afe..829c3f3 100644 --- a/frontend/desktop/emulator/emulator.go +++ b/frontend/desktop/emulator/emulator.go @@ -5,6 +5,7 @@ package emulator #cgo LDFLAGS: -L.. -linfiniemu -lm -lstdc++ #include +#include #define ENABLE_RUNLOG 1 @@ -472,9 +473,9 @@ func (e *Emulator) RunIterations(iterations uint64, iterations_per_us uint64) in return fault } -func (e *Emulator) Stop() { +func (e *Emulator) Stop() RunMode { if !e.isRunning.CompareAndSwap(true, false) { - return + return e.currentRunMode } e.perfLoopCancel() @@ -491,6 +492,8 @@ func (e *Emulator) Stop() { } time.Sleep(100 * time.Millisecond) // TODO: Properly wait for loop or scheduler to stop + + return e.currentRunMode } func (e *Emulator) InstructionsPerSecond() uint64 { @@ -720,6 +723,20 @@ func (e *Emulator) CloseRunlog() { C.runlog_free(e.runlog) } +func (e *Emulator) SaveState() []byte { + var size C.size_t + state := C.pinetime_save_state(e.pt, &size) + + return C.GoBytes(unsafe.Pointer(state), C.int(size)) +} + +func (e *Emulator) LoadState(state []byte) bool { + cstate := C.CBytes(state) + defer C.free(cstate) + + return bool(C.pinetime_load_state(e.pt, (*C.uchar)(cstate), C.size_t(len(state)))) +} + func ConvertImage(raw []byte) *image.RGBA { img := image.NewRGBA(image.Rect(0, 0, DisplayWidth, DisplayHeight)) diff --git a/frontend/desktop/gui/gui.go b/frontend/desktop/gui/gui.go index 0791f09..b2b78a9 100644 --- a/frontend/desktop/gui/gui.go +++ b/frontend/desktop/gui/gui.go @@ -382,6 +382,7 @@ func RunGUI(e *emulator.Emulator, analyzeHeap, runGDB, noScheduler bool) error { } imgui.LabelText(strconv.FormatUint(e.InstructionsPerSecond(), 10), "Instructions per second") + imgui.LabelText(fmt.Sprintf("%d%%", int(100*float64(e.InstructionsPerSecond())/float64(emulator.BaseFrequencyHZ))), "Effective speed") imgui.BeginDisabled(runGDB) { @@ -408,6 +409,19 @@ func RunGUI(e *emulator.Emulator, analyzeHeap, runGDB, noScheduler bool) error { if imgui.Button("Heap") { e.FindFreeHeapBlocks() } + imgui.SameLine() + if imgui.Button("Save") { + os.WriteFile("state.bin", e.SaveState(), 0777) + } + imgui.SameLine() + if imgui.Button("Load") { + state, err := os.ReadFile("state.bin") + if err == nil { + runMode := e.Stop() + e.LoadState(state) + e.Start(runMode) + } + } } imgui.End()