Skip to content

Commit f78bcf3

Browse files
committed
Allow config for the remote Libretro core repos
1 parent 535e725 commit f78bcf3

File tree

15 files changed

+219
-282
lines changed

15 files changed

+219
-282
lines changed

Diff for: pkg/config/config.yaml

+26
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,32 @@ emulator:
160160
sync: true
161161
# external cross-process mutex lock
162162
extLock: "{user}/.cr/cloud-game.lock"
163+
map:
164+
darwin:
165+
amd64:
166+
arch: x86_64
167+
ext: .dylib
168+
os: osx
169+
vendor: apple
170+
arm64:
171+
arch: arm64
172+
ext: .dylib
173+
os: osx
174+
vendor: apple
175+
linux:
176+
amd64:
177+
arch: x86_64
178+
ext: .so
179+
os: linux
180+
arm:
181+
arch: armv7-neon-hf
182+
ext: .so
183+
os: linux
184+
windows:
185+
amd64:
186+
arch: x86_64
187+
ext: .dll
188+
os: windows
163189
main:
164190
type: buildbot
165191
url: https://buildbot.libretro.com/nightly

Diff for: pkg/config/emulator.go

+33-6
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package config
22

33
import (
4+
"errors"
45
"path"
56
"path/filepath"
7+
"runtime"
68
"strings"
79
)
810

@@ -19,12 +21,7 @@ type LibretroConfig struct {
1921
Paths struct {
2022
Libs string
2123
}
22-
Repo struct {
23-
Sync bool
24-
ExtLock string
25-
Main LibretroRepoConfig
26-
Secondary LibretroRepoConfig
27-
}
24+
Repo LibretroRemoteRepo
2825
List map[string]LibretroCoreConfig
2926
}
3027
DebounceMs int
@@ -33,12 +30,42 @@ type LibretroConfig struct {
3330
LogLevel int
3431
}
3532

33+
type LibretroRemoteRepo struct {
34+
Sync bool
35+
ExtLock string
36+
Map map[string]map[string]LibretroRepoMapInfo
37+
Main LibretroRepoConfig
38+
Secondary LibretroRepoConfig
39+
}
40+
41+
// LibretroRepoMapInfo contains Libretro core lib platform info.
42+
// And the cores are just C-compiled libraries.
43+
// See: https://buildbot.libretro.com/nightly.
44+
type LibretroRepoMapInfo struct {
45+
Arch string // bottom: x86_64, x86, ...
46+
Ext string // platform dependent library file extension (dot-prefixed)
47+
Os string // middle: windows, ios, ...
48+
Vendor string // top level: apple, nintendo, ...
49+
}
50+
3651
type LibretroRepoConfig struct {
3752
Type string
3853
Url string
3954
Compression string
4055
}
4156

57+
// Guess tries to map OS + CPU architecture to the corresponding remote URL path.
58+
// See: https://gist.github.com/asukakenji/f15ba7e588ac42795f421b48b8aede63.
59+
func (lrp LibretroRemoteRepo) Guess() (LibretroRepoMapInfo, error) {
60+
if os, ok := lrp.Map[runtime.GOOS]; ok {
61+
if arch, ok2 := os[runtime.GOARCH]; ok2 {
62+
return arch, nil
63+
}
64+
}
65+
return LibretroRepoMapInfo{},
66+
errors.New("core mapping not found for " + runtime.GOOS + ":" + runtime.GOARCH)
67+
}
68+
4269
type LibretroCoreConfig struct {
4370
AltRepo bool
4471
AutoGlContext bool // hack: keep it here to pass it down the emulator

Diff for: pkg/worker/caged/libretro/frontend.go

+9
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,14 @@ func NewFrontend(conf config.Emulator, log *logger.Logger) (*Frontend, error) {
142142

143143
func (f *Frontend) LoadCore(emu string) {
144144
conf := f.conf.GetLibretroCoreConfig(emu)
145+
146+
libExt := ""
147+
if ar, err := f.conf.Libretro.Cores.Repo.Guess(); err == nil {
148+
libExt = ar.Ext
149+
} else {
150+
f.log.Warn().Err(err).Msg("system arch guesser failed")
151+
}
152+
145153
meta := nanoarch.Metadata{
146154
AutoGlContext: conf.AutoGlContext,
147155
FrameDup: f.conf.Libretro.Dup,
@@ -155,6 +163,7 @@ func (f *Frontend) LoadCore(emu string) {
155163
UsesLibCo: conf.UsesLibCo,
156164
CoreAspectRatio: conf.CoreAspectRatio,
157165
KbMouseSupport: conf.KbMouseSupport,
166+
LibExt: libExt,
158167
}
159168
f.mu.Lock()
160169
f.SaveStateFs = conf.SaveStateFs

Diff for: pkg/worker/caged/libretro/frontend_test.go

+8
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ type TestFrontend struct {
2626
*Frontend
2727

2828
corePath string
29+
coreExt string
2930
gamePath string
3031
system string
3132
}
@@ -78,6 +79,11 @@ func EmulatorMock(room string, system string) *TestFrontend {
7879
nano := nanoarch.NewNano(conf.Emulator.LocalPath)
7980
nano.SetLogger(l2)
8081

82+
arch, err := conf.Emulator.Libretro.Cores.Repo.Guess()
83+
if err != nil {
84+
panic(err)
85+
}
86+
8187
// an emu
8288
emu := &TestFrontend{
8389
Frontend: &Frontend{
@@ -92,6 +98,7 @@ func EmulatorMock(room string, system string) *TestFrontend {
9298
SaveOnClose: false,
9399
},
94100
corePath: expand(conf.Emulator.GetLibretroCoreConfig(system).Lib),
101+
coreExt: arch.Ext,
95102
gamePath: expand(conf.Library.BasePath),
96103
system: system,
97104
}
@@ -133,6 +140,7 @@ func (emu *TestFrontend) loadRom(game string) {
133140
Options4rom: conf.Options4rom,
134141
UsesLibCo: conf.UsesLibCo,
135142
CoreAspectRatio: conf.CoreAspectRatio,
143+
LibExt: emu.coreExt,
136144
}
137145

138146
emu.nano.CoreLoad(meta)

Diff for: pkg/worker/caged/libretro/manager/http.go

+11-13
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,14 @@ import (
44
"github.com/giongto35/cloud-game/v3/pkg/config"
55
"github.com/giongto35/cloud-game/v3/pkg/logger"
66
"github.com/giongto35/cloud-game/v3/pkg/os"
7-
"github.com/giongto35/cloud-game/v3/pkg/worker/caged/libretro/repo"
8-
"github.com/giongto35/cloud-game/v3/pkg/worker/caged/libretro/repo/arch"
97
)
108

119
type Manager struct {
1210
BasicManager
1311

14-
arch arch.Info
15-
repo repo.Repository
16-
altRepo repo.Repository
12+
arch ArchInfo
13+
repo Repository
14+
altRepo Repository
1715
client Downloader
1816
fmu *os.Flock
1917
log *logger.Logger
@@ -29,24 +27,24 @@ func NewRemoteHttpManager(conf config.LibretroConfig, log *logger.Logger) Manage
2927
log.Error().Err(err).Msgf("couldn't make file lock")
3028
}
3129

32-
ar, err := arch.Guess()
30+
arch, err := conf.Cores.Repo.Guess()
3331
if err != nil {
3432
log.Error().Err(err).Msg("couldn't get Libretro core file extension")
3533
}
3634

3735
m := Manager{
3836
BasicManager: BasicManager{Conf: conf},
39-
arch: ar,
37+
arch: ArchInfo(arch),
4038
client: NewDefaultDownloader(log),
4139
fmu: flock,
4240
log: log,
4341
}
4442

4543
if repoConf.Type != "" {
46-
m.repo = repo.New(repoConf.Type, repoConf.Url, repoConf.Compression, "buildbot")
44+
m.repo = NewRepo(repoConf.Type, repoConf.Url, repoConf.Compression, "buildbot")
4745
}
4846
if altRepoConf.Type != "" {
49-
m.altRepo = repo.New(altRepoConf.Type, altRepoConf.Url, altRepoConf.Compression, "")
47+
m.altRepo = NewRepo(altRepoConf.Type, altRepoConf.Url, altRepoConf.Compression, "")
5048
}
5149

5250
return m
@@ -81,7 +79,7 @@ func (m *Manager) Sync() error {
8179
}
8280
}()
8381

84-
installed, err := m.GetInstalled(m.arch.LibExt)
82+
installed, err := m.GetInstalled(m.arch.Ext)
8583
if err != nil {
8684
return err
8785
}
@@ -92,9 +90,9 @@ func (m *Manager) Sync() error {
9290
return nil
9391
}
9492

95-
func (m *Manager) getCoreUrls(names []string, repo repo.Repository) (urls []Download) {
93+
func (m *Manager) getCoreUrls(names []string, repo Repository) (urls []Download) {
9694
for _, c := range names {
97-
urls = append(urls, Download{Key: c, Address: repo.GetCoreUrl(c, m.arch)})
95+
urls = append(urls, Download{Key: c, Address: repo.CoreUrl(c, m.arch)})
9896
}
9997
return
10098
}
@@ -137,7 +135,7 @@ func (m *Manager) download(cores []config.CoreInfo) (failed []string) {
137135
return
138136
}
139137

140-
func (m *Manager) down(cores []string, repo repo.Repository) (failed []string) {
138+
func (m *Manager) down(cores []string, repo Repository) (failed []string) {
141139
if len(cores) == 0 || repo == nil {
142140
return
143141
}

Diff for: pkg/worker/caged/libretro/manager/repository.go

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package manager
2+
3+
import "strings"
4+
5+
type ArchInfo struct {
6+
Arch string
7+
Ext string
8+
Os string
9+
Vendor string
10+
}
11+
12+
type Data struct {
13+
Url string
14+
Compression string
15+
}
16+
17+
type Repository interface {
18+
CoreUrl(file string, info ArchInfo) (url string)
19+
}
20+
21+
// Repo defines a simple zip file containing all the cores that will be extracted as is.
22+
type Repo struct {
23+
Address string
24+
Compression string
25+
}
26+
27+
func (r Repo) CoreUrl(_ string, _ ArchInfo) string { return r.Address }
28+
29+
type Buildbot struct{ Repo }
30+
31+
func (r Buildbot) CoreUrl(file string, info ArchInfo) string {
32+
var sb strings.Builder
33+
sb.WriteString(r.Address + "/")
34+
if info.Vendor != "" {
35+
sb.WriteString(info.Vendor + "/")
36+
}
37+
sb.WriteString(info.Os + "/" + info.Arch + "/latest/" + file + info.Ext)
38+
if r.Compression != "" {
39+
sb.WriteString("." + r.Compression)
40+
}
41+
return sb.String()
42+
}
43+
44+
type Github struct{ Buildbot }
45+
46+
func (r Github) CoreUrl(file string, info ArchInfo) string {
47+
return r.Buildbot.CoreUrl(file, info) + "?raw=true"
48+
}
49+
50+
func NewRepo(kind string, url string, compression string, defaultRepo string) Repository {
51+
var repository Repository
52+
switch kind {
53+
case "buildbot":
54+
repository = Buildbot{Repo{Address: url, Compression: compression}}
55+
case "github":
56+
repository = Github{Buildbot{Repo{Address: url, Compression: compression}}}
57+
case "raw":
58+
repository = Repo{Address: url, Compression: "zip"}
59+
default:
60+
if defaultRepo != "" {
61+
repository = NewRepo(defaultRepo, url, compression, "")
62+
}
63+
}
64+
return repository
65+
}

Diff for: pkg/worker/caged/libretro/manager/repository_test.go

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package manager
2+
3+
import "testing"
4+
5+
func TestCoreUrl(t *testing.T) {
6+
testAddress := "https://test.me"
7+
tests := []struct {
8+
arch ArchInfo
9+
compress string
10+
f string
11+
repo string
12+
result string
13+
}{
14+
{
15+
arch: ArchInfo{Arch: "x86_64", Ext: ".so", Os: "linux"},
16+
f: "uber_core",
17+
repo: "buildbot",
18+
result: testAddress + "/" + "linux/x86_64/latest/uber_core.so",
19+
},
20+
{
21+
arch: ArchInfo{Arch: "x86_64", Ext: ".so", Os: "linux"},
22+
compress: "zip",
23+
f: "uber_core",
24+
repo: "buildbot",
25+
result: testAddress + "/" + "linux/x86_64/latest/uber_core.so.zip",
26+
},
27+
{
28+
arch: ArchInfo{Arch: "x86_64", Ext: ".dylib", Os: "osx", Vendor: "apple"},
29+
f: "uber_core",
30+
repo: "buildbot",
31+
result: testAddress + "/" + "apple/osx/x86_64/latest/uber_core.dylib",
32+
},
33+
{
34+
arch: ArchInfo{Os: "linux", Arch: "x86_64", Ext: ".so"},
35+
f: "uber_core",
36+
repo: "github",
37+
result: testAddress + "/" + "linux/x86_64/latest/uber_core.so?raw=true",
38+
},
39+
{
40+
arch: ArchInfo{Os: "linux", Arch: "x86_64", Ext: ".so"},
41+
compress: "zip",
42+
f: "uber_core",
43+
repo: "github",
44+
result: testAddress + "/" + "linux/x86_64/latest/uber_core.so.zip?raw=true",
45+
},
46+
{
47+
arch: ArchInfo{Os: "osx", Arch: "x86_64", Vendor: "apple", Ext: ".dylib"},
48+
f: "uber_core",
49+
repo: "github",
50+
result: testAddress + "/" + "apple/osx/x86_64/latest/uber_core.dylib?raw=true",
51+
},
52+
}
53+
54+
for _, test := range tests {
55+
r := NewRepo(test.repo, testAddress, test.compress, "")
56+
url := r.CoreUrl(test.f, test.arch)
57+
if url != test.result {
58+
t.Errorf("seems that expected link address is incorrect (%v) for file %s %+v", url, test.f, test.arch)
59+
}
60+
}
61+
}

0 commit comments

Comments
 (0)