Skip to content

Commit

Permalink
Allow config for the remote Libretro core repos
Browse files Browse the repository at this point in the history
  • Loading branch information
sergystepanov committed Dec 19, 2024
1 parent 535e725 commit f78bcf3
Show file tree
Hide file tree
Showing 15 changed files with 219 additions and 282 deletions.
26 changes: 26 additions & 0 deletions pkg/config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,32 @@ emulator:
sync: true
# external cross-process mutex lock
extLock: "{user}/.cr/cloud-game.lock"
map:
darwin:
amd64:
arch: x86_64
ext: .dylib
os: osx
vendor: apple
arm64:
arch: arm64
ext: .dylib
os: osx
vendor: apple
linux:
amd64:
arch: x86_64
ext: .so
os: linux
arm:
arch: armv7-neon-hf
ext: .so
os: linux
windows:
amd64:
arch: x86_64
ext: .dll
os: windows
main:
type: buildbot
url: https://buildbot.libretro.com/nightly
Expand Down
39 changes: 33 additions & 6 deletions pkg/config/emulator.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package config

import (
"errors"
"path"
"path/filepath"
"runtime"
"strings"
)

Expand All @@ -19,12 +21,7 @@ type LibretroConfig struct {
Paths struct {
Libs string
}
Repo struct {
Sync bool
ExtLock string
Main LibretroRepoConfig
Secondary LibretroRepoConfig
}
Repo LibretroRemoteRepo
List map[string]LibretroCoreConfig
}
DebounceMs int
Expand All @@ -33,12 +30,42 @@ type LibretroConfig struct {
LogLevel int
}

type LibretroRemoteRepo struct {
Sync bool
ExtLock string
Map map[string]map[string]LibretroRepoMapInfo
Main LibretroRepoConfig
Secondary LibretroRepoConfig
}

// LibretroRepoMapInfo contains Libretro core lib platform info.
// And the cores are just C-compiled libraries.
// See: https://buildbot.libretro.com/nightly.
type LibretroRepoMapInfo struct {
Arch string // bottom: x86_64, x86, ...
Ext string // platform dependent library file extension (dot-prefixed)
Os string // middle: windows, ios, ...
Vendor string // top level: apple, nintendo, ...
}

type LibretroRepoConfig struct {
Type string
Url string
Compression string
}

// Guess tries to map OS + CPU architecture to the corresponding remote URL path.
// See: https://gist.github.com/asukakenji/f15ba7e588ac42795f421b48b8aede63.
func (lrp LibretroRemoteRepo) Guess() (LibretroRepoMapInfo, error) {
if os, ok := lrp.Map[runtime.GOOS]; ok {
if arch, ok2 := os[runtime.GOARCH]; ok2 {
return arch, nil
}
}
return LibretroRepoMapInfo{},
errors.New("core mapping not found for " + runtime.GOOS + ":" + runtime.GOARCH)
}

type LibretroCoreConfig struct {
AltRepo bool
AutoGlContext bool // hack: keep it here to pass it down the emulator
Expand Down
9 changes: 9 additions & 0 deletions pkg/worker/caged/libretro/frontend.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,14 @@ func NewFrontend(conf config.Emulator, log *logger.Logger) (*Frontend, error) {

func (f *Frontend) LoadCore(emu string) {
conf := f.conf.GetLibretroCoreConfig(emu)

libExt := ""
if ar, err := f.conf.Libretro.Cores.Repo.Guess(); err == nil {
libExt = ar.Ext
} else {
f.log.Warn().Err(err).Msg("system arch guesser failed")
}

meta := nanoarch.Metadata{
AutoGlContext: conf.AutoGlContext,
FrameDup: f.conf.Libretro.Dup,
Expand All @@ -155,6 +163,7 @@ func (f *Frontend) LoadCore(emu string) {
UsesLibCo: conf.UsesLibCo,
CoreAspectRatio: conf.CoreAspectRatio,
KbMouseSupport: conf.KbMouseSupport,
LibExt: libExt,
}
f.mu.Lock()
f.SaveStateFs = conf.SaveStateFs
Expand Down
8 changes: 8 additions & 0 deletions pkg/worker/caged/libretro/frontend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type TestFrontend struct {
*Frontend

corePath string
coreExt string
gamePath string
system string
}
Expand Down Expand Up @@ -78,6 +79,11 @@ func EmulatorMock(room string, system string) *TestFrontend {
nano := nanoarch.NewNano(conf.Emulator.LocalPath)
nano.SetLogger(l2)

arch, err := conf.Emulator.Libretro.Cores.Repo.Guess()
if err != nil {
panic(err)
}

// an emu
emu := &TestFrontend{
Frontend: &Frontend{
Expand All @@ -92,6 +98,7 @@ func EmulatorMock(room string, system string) *TestFrontend {
SaveOnClose: false,
},
corePath: expand(conf.Emulator.GetLibretroCoreConfig(system).Lib),
coreExt: arch.Ext,
gamePath: expand(conf.Library.BasePath),
system: system,
}
Expand Down Expand Up @@ -133,6 +140,7 @@ func (emu *TestFrontend) loadRom(game string) {
Options4rom: conf.Options4rom,
UsesLibCo: conf.UsesLibCo,
CoreAspectRatio: conf.CoreAspectRatio,
LibExt: emu.coreExt,
}

emu.nano.CoreLoad(meta)
Expand Down
24 changes: 11 additions & 13 deletions pkg/worker/caged/libretro/manager/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@ import (
"github.com/giongto35/cloud-game/v3/pkg/config"
"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/repo"
"github.com/giongto35/cloud-game/v3/pkg/worker/caged/libretro/repo/arch"
)

type Manager struct {
BasicManager

arch arch.Info
repo repo.Repository
altRepo repo.Repository
arch ArchInfo
repo Repository
altRepo Repository
client Downloader
fmu *os.Flock
log *logger.Logger
Expand All @@ -29,24 +27,24 @@ func NewRemoteHttpManager(conf config.LibretroConfig, log *logger.Logger) Manage
log.Error().Err(err).Msgf("couldn't make file lock")
}

ar, err := arch.Guess()
arch, err := conf.Cores.Repo.Guess()
if err != nil {
log.Error().Err(err).Msg("couldn't get Libretro core file extension")
}

m := Manager{
BasicManager: BasicManager{Conf: conf},
arch: ar,
arch: ArchInfo(arch),
client: NewDefaultDownloader(log),
fmu: flock,
log: log,
}

if repoConf.Type != "" {
m.repo = repo.New(repoConf.Type, repoConf.Url, repoConf.Compression, "buildbot")
m.repo = NewRepo(repoConf.Type, repoConf.Url, repoConf.Compression, "buildbot")
}
if altRepoConf.Type != "" {
m.altRepo = repo.New(altRepoConf.Type, altRepoConf.Url, altRepoConf.Compression, "")
m.altRepo = NewRepo(altRepoConf.Type, altRepoConf.Url, altRepoConf.Compression, "")
}

return m
Expand Down Expand Up @@ -81,7 +79,7 @@ func (m *Manager) Sync() error {
}
}()

installed, err := m.GetInstalled(m.arch.LibExt)
installed, err := m.GetInstalled(m.arch.Ext)
if err != nil {
return err
}
Expand All @@ -92,9 +90,9 @@ func (m *Manager) Sync() error {
return nil
}

func (m *Manager) getCoreUrls(names []string, repo repo.Repository) (urls []Download) {
func (m *Manager) getCoreUrls(names []string, repo Repository) (urls []Download) {
for _, c := range names {
urls = append(urls, Download{Key: c, Address: repo.GetCoreUrl(c, m.arch)})
urls = append(urls, Download{Key: c, Address: repo.CoreUrl(c, m.arch)})
}
return
}
Expand Down Expand Up @@ -137,7 +135,7 @@ func (m *Manager) download(cores []config.CoreInfo) (failed []string) {
return
}

func (m *Manager) down(cores []string, repo repo.Repository) (failed []string) {
func (m *Manager) down(cores []string, repo Repository) (failed []string) {
if len(cores) == 0 || repo == nil {
return
}
Expand Down
65 changes: 65 additions & 0 deletions pkg/worker/caged/libretro/manager/repository.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package manager

import "strings"

type ArchInfo struct {
Arch string
Ext string
Os string
Vendor string
}

type Data struct {
Url string
Compression string
}

type Repository interface {
CoreUrl(file string, info ArchInfo) (url string)
}

// Repo defines a simple zip file containing all the cores that will be extracted as is.
type Repo struct {
Address string
Compression string
}

func (r Repo) CoreUrl(_ string, _ ArchInfo) string { return r.Address }

type Buildbot struct{ Repo }

func (r Buildbot) CoreUrl(file string, info ArchInfo) string {
var sb strings.Builder
sb.WriteString(r.Address + "/")
if info.Vendor != "" {
sb.WriteString(info.Vendor + "/")
}
sb.WriteString(info.Os + "/" + info.Arch + "/latest/" + file + info.Ext)
if r.Compression != "" {
sb.WriteString("." + r.Compression)
}
return sb.String()
}

type Github struct{ Buildbot }

func (r Github) CoreUrl(file string, info ArchInfo) string {
return r.Buildbot.CoreUrl(file, info) + "?raw=true"
}

func NewRepo(kind string, url string, compression string, defaultRepo string) Repository {
var repository Repository
switch kind {
case "buildbot":
repository = Buildbot{Repo{Address: url, Compression: compression}}
case "github":
repository = Github{Buildbot{Repo{Address: url, Compression: compression}}}
case "raw":
repository = Repo{Address: url, Compression: "zip"}
default:
if defaultRepo != "" {
repository = NewRepo(defaultRepo, url, compression, "")
}
}
return repository
}
61 changes: 61 additions & 0 deletions pkg/worker/caged/libretro/manager/repository_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package manager

import "testing"

func TestCoreUrl(t *testing.T) {
testAddress := "https://test.me"
tests := []struct {
arch ArchInfo
compress string
f string
repo string
result string
}{
{
arch: ArchInfo{Arch: "x86_64", Ext: ".so", Os: "linux"},
f: "uber_core",
repo: "buildbot",
result: testAddress + "/" + "linux/x86_64/latest/uber_core.so",
},
{
arch: ArchInfo{Arch: "x86_64", Ext: ".so", Os: "linux"},
compress: "zip",
f: "uber_core",
repo: "buildbot",
result: testAddress + "/" + "linux/x86_64/latest/uber_core.so.zip",
},
{
arch: ArchInfo{Arch: "x86_64", Ext: ".dylib", Os: "osx", Vendor: "apple"},
f: "uber_core",
repo: "buildbot",
result: testAddress + "/" + "apple/osx/x86_64/latest/uber_core.dylib",
},
{
arch: ArchInfo{Os: "linux", Arch: "x86_64", Ext: ".so"},
f: "uber_core",
repo: "github",
result: testAddress + "/" + "linux/x86_64/latest/uber_core.so?raw=true",
},
{
arch: ArchInfo{Os: "linux", Arch: "x86_64", Ext: ".so"},
compress: "zip",
f: "uber_core",
repo: "github",
result: testAddress + "/" + "linux/x86_64/latest/uber_core.so.zip?raw=true",
},
{
arch: ArchInfo{Os: "osx", Arch: "x86_64", Vendor: "apple", Ext: ".dylib"},
f: "uber_core",
repo: "github",
result: testAddress + "/" + "apple/osx/x86_64/latest/uber_core.dylib?raw=true",
},
}

for _, test := range tests {
r := NewRepo(test.repo, testAddress, test.compress, "")
url := r.CoreUrl(test.f, test.arch)
if url != test.result {
t.Errorf("seems that expected link address is incorrect (%v) for file %s %+v", url, test.f, test.arch)
}
}
}
Loading

0 comments on commit f78bcf3

Please sign in to comment.