From 8dd9e9c9be67458289976a2abb5cbc21c8ba9c26 Mon Sep 17 00:00:00 2001 From: Sergey Stepanov Date: Wed, 20 Sep 2023 18:16:36 +0300 Subject: [PATCH] Use buffered file writer --- pkg/os/os.go | 39 ++++++++++++++++ .../caged/libretro/nanoarch/nanoarch.go | 45 ++++++++++--------- pkg/worker/caged/libretro/storage.go | 2 +- pkg/worker/cloud/cloudstore.go | 3 +- 4 files changed, 67 insertions(+), 22 deletions(-) diff --git a/pkg/os/os.go b/pkg/os/os.go index 117e41ad..142ffcc1 100644 --- a/pkg/os/os.go +++ b/pkg/os/os.go @@ -1,7 +1,10 @@ package os import ( + "bufio" + "bytes" "errors" + "io" "io/fs" "os" "os/signal" @@ -9,6 +12,8 @@ import ( "syscall" ) +const ReadChunk = 1024 + var ErrNotExist = os.ErrNotExist func Exists(path string) bool { @@ -45,3 +50,37 @@ func GetUserHome() (string, error) { func WriteFile(name string, data []byte, perm os.FileMode) error { return os.WriteFile(name, data, perm) } + +func ReadFile(name string) (dat []byte, err error) { + f, err := os.Open(name) + if err != nil { + return nil, err + } + defer func() { _ = f.Close() }() + + r := bufio.NewReader(f) + buf := bytes.NewBuffer(make([]byte, 0)) + chunk := make([]byte, ReadChunk) + + c := 0 + for { + if c, err = r.Read(chunk); err != nil { + break + } + buf.Write(chunk[:c]) + } + + if err == io.EOF { + err = nil + } + + return buf.Bytes(), err +} + +func StatSize(path string) (int64, error) { + fi, err := os.Stat(path) + if err != nil { + return 0, err + } + return fi.Size(), nil +} diff --git a/pkg/worker/caged/libretro/nanoarch/nanoarch.go b/pkg/worker/caged/libretro/nanoarch/nanoarch.go index d75f2c96..a8105e25 100644 --- a/pkg/worker/caged/libretro/nanoarch/nanoarch.go +++ b/pkg/worker/caged/libretro/nanoarch/nanoarch.go @@ -3,7 +3,6 @@ package nanoarch import ( "errors" "fmt" - "os" "runtime" "strings" "sync/atomic" @@ -11,6 +10,7 @@ import ( "unsafe" "github.com/giongto35/cloud-game/v3/pkg/logger" + "github.com/giongto35/cloud-game/v3/pkg/os" "github.com/giongto35/cloud-game/v3/pkg/worker/caged/libretro/graphics" "github.com/giongto35/cloud-game/v3/pkg/worker/caged/libretro/image" "github.com/giongto35/cloud-game/v3/pkg/worker/caged/libretro/repo/arch" @@ -115,10 +115,9 @@ func init() { Nan0.reserved <- struct{}{} } func NewNano(localPath string) *Nanoarch { nano := &Nan0 - nano.cSaveDirectory = C.CString(localPath + string(os.PathSeparator) + "legacy_save") - nano.cSystemDirectory = C.CString(localPath + string(os.PathSeparator) + "system") + nano.cSaveDirectory = C.CString(localPath + "/legacy_save") + nano.cSystemDirectory = C.CString(localPath + "/system") nano.cUserName = C.CString("retro") - return nano } @@ -209,29 +208,33 @@ func (n *Nanoarch) CoreLoad(meta Metadata) { } func (n *Nanoarch) LoadGame(path string) error { - fi, err := os.Stat(path) - if err != nil { - return err - } - fileSize := fi.Size() + game := C.struct_retro_game_info{} - n.log.Debug().Msgf("ROM size: %v", byteCountBinary(fileSize)) - - fPath := C.CString(path) - defer C.free(unsafe.Pointer(fPath)) - gi := C.struct_retro_game_info{path: fPath, size: C.size_t(fileSize)} - - if !bool(n.sysInfo.need_fullpath) { + big := bool(n.sysInfo.need_fullpath) // big ROMs are loaded by cores later + if big { + size, err := os.StatSize(path) + if err != nil { + return err + } + game.size = C.size_t(size) + } else { bytes, err := os.ReadFile(path) if err != nil { return err } - dataPtr := unsafe.Pointer(C.CBytes(bytes)) - gi.data = dataPtr - defer C.free(dataPtr) + // !to pin in 1.21 + ptr := unsafe.Pointer(C.CBytes(bytes)) + game.data = ptr + game.size = C.size_t(len(bytes)) + defer C.free(ptr) } + fp := C.CString(path) + defer C.free(unsafe.Pointer(fp)) + game.path = fp - if ok := C.bridge_retro_load_game(retroLoadGame, &gi); !ok { + n.log.Debug().Msgf("ROM - big: %v, size: %v", big, byteCountBinary(int64(game.size))) + + if ok := C.bridge_retro_load_game(retroLoadGame, &game); !ok { return fmt.Errorf("core failed to load ROM: %v", path) } @@ -467,6 +470,7 @@ func SaveRAM() State { func RestoreSaveRAM(st State) { if len(st) > 0 { if memory := ptSaveRAM(); memory != nil { + //noinspection GoRedundantConversion copy(unsafe.Slice((*byte)(memory.ptr), memory.size), st) } } @@ -573,6 +577,7 @@ func coreVideoRefresh(data unsafe.Pointer, width, height uint, packed uint) { var data_ []byte if data != C.RETRO_HW_FRAME_BUFFER_VALID { + //noinspection GoRedundantConversion data_ = unsafe.Slice((*byte)(data), bytes) } else { // if Libretro renders frame with OpenGL context diff --git a/pkg/worker/caged/libretro/storage.go b/pkg/worker/caged/libretro/storage.go index 9f3691d6..e7c488a0 100644 --- a/pkg/worker/caged/libretro/storage.go +++ b/pkg/worker/caged/libretro/storage.go @@ -1,10 +1,10 @@ package libretro import ( - "os" "path/filepath" "strings" + "github.com/giongto35/cloud-game/v3/pkg/os" "github.com/giongto35/cloud-game/v3/pkg/worker/compression/zip" ) diff --git a/pkg/worker/cloud/cloudstore.go b/pkg/worker/cloud/cloudstore.go index 76d0f616..2413a7a5 100644 --- a/pkg/worker/cloud/cloudstore.go +++ b/pkg/worker/cloud/cloudstore.go @@ -8,8 +8,9 @@ import ( "fmt" "io" "net/http" - "os" "time" + + "github.com/giongto35/cloud-game/v3/pkg/os" ) // !to replace all with unified s3 api