diff --git a/pkg/worker/caged/libretro/frontend_test.go b/pkg/worker/caged/libretro/frontend_test.go index f2b108ee..fda0ecbe 100644 --- a/pkg/worker/caged/libretro/frontend_test.go +++ b/pkg/worker/caged/libretro/frontend_test.go @@ -48,6 +48,7 @@ var ( alwa = game{system: "nes", rom: "nes/Alwa's Awakening (Demo).nes"} sushi = game{system: "gba", rom: "gba/Sushi The Cat.gba"} angua = game{system: "gba", rom: "gba/anguna.gba"} + rogue = game{system: "dos", rom: "dos/rogue.zip"} ) // TestMain runs all tests in the main thread in macOS. @@ -176,6 +177,13 @@ func (emu *TestFrontend) dumpState() (cur string, prev string) { return } +func (emu *TestFrontend) save() ([]byte, error) { + emu.mu.Lock() + defer emu.mu.Unlock() + + return nanoarch.SaveState() +} + func BenchmarkEmulators(b *testing.B) { log.SetOutput(io.Discard) os.Stdout, _ = os.Open(os.DevNull) @@ -204,6 +212,7 @@ func TestSavePersistence(t *testing.T) { tests := []testRun{ {system: sushi.system, rom: sushi.rom, frames: 100}, {system: angua.system, rom: angua.rom, frames: 100}, + {system: rogue.system, rom: rogue.rom, frames: 200}, } for _, test := range tests { @@ -215,14 +224,12 @@ func TestSavePersistence(t *testing.T) { test.frames-- } - _, _ = front.dumpState() - if err := front.Save(); err != nil { - t.Error(err) - } - - hash1, hash2 := front.dumpState() - if hash1 != hash2 { - t.Errorf("%v != %v", hash1, hash2) + for range 10 { + v, _ := front.save() + if v == nil || len(v) == 0 { + t.Errorf("couldn't persist the state") + t.Fail() + } } front.Shutdown() diff --git a/pkg/worker/caged/libretro/nanoarch/nanoarch.go b/pkg/worker/caged/libretro/nanoarch/nanoarch.go index 1748ec15..1aca8506 100644 --- a/pkg/worker/caged/libretro/nanoarch/nanoarch.go +++ b/pkg/worker/caged/libretro/nanoarch/nanoarch.go @@ -495,32 +495,42 @@ const ( // SaveState returns emulator internal state. func SaveState() (State, error) { - data := make([]byte, uint(Nan0.serializeSize)) + size := C.bridge_retro_serialize_size(retroSerializeSize) + data := make([]byte, uint(size)) rez := false + if Nan0.LibCo && !Nan0.hackSkipSameThreadSave { - rez = *(*bool)(C.same_thread_with_args2(retroSerialize, C.int(CallSerialize), unsafe.Pointer(&data[0]), unsafe.Pointer(&Nan0.serializeSize))) + rez = *(*bool)(C.same_thread_with_args2(retroSerialize, C.int(CallSerialize), unsafe.Pointer(&data[0]), unsafe.Pointer(&size))) } else { - rez = bool(C.bridge_retro_serialize(retroSerialize, unsafe.Pointer(&data[0]), Nan0.serializeSize)) + rez = bool(C.bridge_retro_serialize(retroSerialize, unsafe.Pointer(&data[0]), size)) } + if !rez { return nil, errors.New("retro_serialize failed") } + return data, nil } // RestoreSaveState restores emulator internal state. func RestoreSaveState(st State) error { - if len(st) > 0 { - rez := false - if Nan0.LibCo { - rez = *(*bool)(C.same_thread_with_args2(retroUnserialize, C.int(CallUnserialize), unsafe.Pointer(&st[0]), unsafe.Pointer(&Nan0.serializeSize))) - } else { - rez = bool(C.bridge_retro_unserialize(retroUnserialize, unsafe.Pointer(&st[0]), Nan0.serializeSize)) - } - if !rez { - return errors.New("retro_unserialize failed") - } + if len(st) <= 0 { + return errors.New("empty load state") } + + size := C.bridge_retro_serialize_size(retroSerializeSize) + rez := false + + if Nan0.LibCo { + rez = *(*bool)(C.same_thread_with_args2(retroUnserialize, C.int(CallUnserialize), unsafe.Pointer(&st[0]), unsafe.Pointer(&size))) + } else { + rez = bool(C.bridge_retro_unserialize(retroUnserialize, unsafe.Pointer(&st[0]), size)) + } + + if !rez { + return errors.New("retro_unserialize failed") + } + return nil }