Use the save state size before each save/load call

This commit is contained in:
sergystepanov 2025-05-03 15:55:26 +03:00
parent 9d4256306e
commit 37a4a80996
2 changed files with 38 additions and 21 deletions

View file

@ -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()

View file

@ -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
}