diff --git a/app.go b/app.go
index 337f1c2..5588f2d 100644
--- a/app.go
+++ b/app.go
@@ -63,3 +63,7 @@ func (a *App) LoadGames() []models.Game {
games = provider.GetConjureGameInfo()
return games
}
+
+func (a *App) LoadImage(gameId string, imageSrc string) provider.FileBlob {
+ return *provider.LoadImage(gameId, imageSrc)
+}
diff --git a/frontend/src/components/GameCard.vue b/frontend/src/components/GameCard.vue
new file mode 100644
index 0000000..1c8f515
--- /dev/null
+++ b/frontend/src/components/GameCard.vue
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/components/GameCarousel.vue b/frontend/src/components/GameCarousel.vue
index 93bf1c2..c8fd827 100644
--- a/frontend/src/components/GameCarousel.vue
+++ b/frontend/src/components/GameCarousel.vue
@@ -2,21 +2,12 @@
-
-
![]()
-
+ />
@@ -36,6 +27,7 @@
import { models } from "../../wailsjs/go/models";
import Game = models.Game;
+import GameCard from "./GameCard.vue";
defineProps<{
games: Game[],
diff --git a/frontend/src/components/LocalImage.vue b/frontend/src/components/LocalImage.vue
new file mode 100644
index 0000000..c81de79
--- /dev/null
+++ b/frontend/src/components/LocalImage.vue
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/utils/image-manager.ts b/frontend/src/utils/image-manager.ts
new file mode 100644
index 0000000..aea3939
--- /dev/null
+++ b/frontend/src/utils/image-manager.ts
@@ -0,0 +1,21 @@
+import {LoadImage} from "../../wailsjs/go/main/App";
+import * as path from "node:path";
+
+export class ImageManager {
+
+ static Dictionary: {[key: string]: string} = {}
+
+ public static async getImage(gameId: string, src: string): Promise {
+ const id = path.join(gameId, src);
+ if (this.Dictionary[id])
+ return this.Dictionary[id]
+
+ const fileBlob = await LoadImage(gameId, src);
+ const bytes = new Uint8Array(fileBlob.Data);
+ const blob = new Blob([bytes], {type: fileBlob.MimeType });
+ const url = URL.createObjectURL(blob);
+ this.Dictionary[id] = url
+ return url;
+ }
+
+}
\ No newline at end of file
diff --git a/frontend/wailsjs/go/main/App.d.ts b/frontend/wailsjs/go/main/App.d.ts
index 6deff79..5b27953 100755
--- a/frontend/wailsjs/go/main/App.d.ts
+++ b/frontend/wailsjs/go/main/App.d.ts
@@ -1,7 +1,10 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
import {models} from '../models';
+import {provider} from '../models';
export function LoadGames():Promise>;
+export function LoadImage(arg1:string,arg2:string):Promise;
+
export function StartGame(arg1:string):Promise;
diff --git a/frontend/wailsjs/go/main/App.js b/frontend/wailsjs/go/main/App.js
index 76e728c..2b66092 100755
--- a/frontend/wailsjs/go/main/App.js
+++ b/frontend/wailsjs/go/main/App.js
@@ -6,6 +6,10 @@ export function LoadGames() {
return window['go']['main']['App']['LoadGames']();
}
+export function LoadImage(arg1, arg2) {
+ return window['go']['main']['App']['LoadImage'](arg1, arg2);
+}
+
export function StartGame(arg1) {
return window['go']['main']['App']['StartGame'](arg1);
}
diff --git a/frontend/wailsjs/go/models.ts b/frontend/wailsjs/go/models.ts
index afc1457..5ec11da 100755
--- a/frontend/wailsjs/go/models.ts
+++ b/frontend/wailsjs/go/models.ts
@@ -45,3 +45,24 @@ export namespace models {
}
+export namespace provider {
+
+ export class FileBlob {
+ Name: string;
+ MimeType: string;
+ Data: number[];
+
+ static createFrom(source: any = {}) {
+ return new FileBlob(source);
+ }
+
+ constructor(source: any = {}) {
+ if ('string' === typeof source) source = JSON.parse(source);
+ this.Name = source["Name"];
+ this.MimeType = source["MimeType"];
+ this.Data = source["Data"];
+ }
+ }
+
+}
+
diff --git a/frontend/wailsjs/runtime/package.json b/frontend/wailsjs/runtime/package.json
old mode 100644
new mode 100755
diff --git a/frontend/wailsjs/runtime/runtime.d.ts b/frontend/wailsjs/runtime/runtime.d.ts
old mode 100644
new mode 100755
diff --git a/frontend/wailsjs/runtime/runtime.js b/frontend/wailsjs/runtime/runtime.js
old mode 100644
new mode 100755
diff --git a/go.mod b/go.mod
index 2b841fc..a42c190 100644
--- a/go.mod
+++ b/go.mod
@@ -5,6 +5,7 @@ go 1.22.0
toolchain go1.23.5
require (
+ github.com/karalabe/hid v1.0.0
github.com/wailsapp/wails/v2 v2.9.2
gopkg.in/yaml.v3 v3.0.1
)
diff --git a/go.sum b/go.sum
index ec6ad85..9690a5f 100644
--- a/go.sum
+++ b/go.sum
@@ -11,6 +11,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck=
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
+github.com/karalabe/hid v1.0.0 h1:+/CIMNXhSU/zIJgnIvBD2nKHxS/bnRHhhs9xBryLpPo=
+github.com/karalabe/hid v1.0.0/go.mod h1:Vr51f8rUOLYrfrWDFlV12GGQgM5AT8sVh+2fY4MPeu8=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
diff --git a/lib/inputs/joystick.go b/lib/inputs/joystick.go
index c06a11f..04f1271 100644
--- a/lib/inputs/joystick.go
+++ b/lib/inputs/joystick.go
@@ -1,10 +1,9 @@
package inputs
import (
- "encoding/binary"
"fmt"
- "os"
- "time"
+
+ "github.com/karalabe/hid"
)
type JoystickEvent struct {
@@ -21,29 +20,84 @@ const (
)
func Start() {
- // Open the joystick device file
- file, err := os.Open("/dev/input/js0")
- if err != nil {
- fmt.Println("Error opening joystick:", err)
+ return
+ fmt.Println("Opening devices")
+ const vendorID = 0x0079
+ const productID = 0x0006
+
+ // Enumerate all matching devices
+ devices := hid.Enumerate(vendorID, productID)
+ if len(devices) == 0 {
+ fmt.Printf("Device with VID:PID %04X:%04X not found", vendorID, productID)
return
}
- defer file.Close()
- // Continuously read joystick events
+ for _, d := range devices {
+ fmt.Printf("Found: %s - VID:%04X PID:%04X\n", d.Product, d.VendorID, d.ProductID)
+ }
+
+ // Open the first matching device
+ device, err := devices[0].Open()
+ if err != nil {
+ fmt.Printf("Failed to open device: %v", err)
+ return
+ }
+ defer device.Close()
+
+ fmt.Println("Reading data... Press Ctrl+C to exit")
+
+ buf := make([]byte, 32) // Adjust size if needed
for {
- var e JoystickEvent
- err := binary.Read(file, binary.LittleEndian, &e)
+ _, err := device.Read(buf)
if err != nil {
- fmt.Println("Error reading joystick event:", err)
+ fmt.Printf("Read error: %v", err)
return
}
- // Handle the event
- handleJoystickEvent(e)
+ // For debugging: print raw data
+ // fmt.Printf("Raw: % X\n", buf[:n])
- // Sleep to avoid flooding output
- time.Sleep(10 * time.Millisecond)
+ // Example: decode joystick + button state
+ x := buf[0] // Horizontal axis (0–255)
+ y := buf[1] // Vertical axis (0–255)
+ buttons := buf[6] // Buttons as bitfield
+
+ // fmt.Printf("Joystick X: %d, Y: %d, Buttons: %08b\n", x, y, buttons)
+
+ if buttons != 0 {
+ fmt.Printf("Button was pressed! %d\n", buttons)
+ }
+
+ if x != 127 || y != 127 {
+ fmt.Printf("Joystick moved! %d - %d\n", x, y)
+ }
}
+
+ fmt.Println("Out")
+
+ // Open the joystick device file
+ // file, err := os.Open("/dev/input/js0")
+ // if err != nil {
+ // fmt.Println("Error opening joystick:", err)
+ // return
+ // }
+ // defer file.Close()
+
+ // // Continuously read joystick events
+ // for {
+ // var e JoystickEvent
+ // err := binary.Read(file, binary.LittleEndian, &e)
+ // if err != nil {
+ // fmt.Println("Error reading joystick event:", err)
+ // return
+ // }
+
+ // // Handle the event
+ // handleJoystickEvent(e)
+
+ // // Sleep to avoid flooding output
+ // time.Sleep(10 * time.Millisecond)
+ // }
}
// handleJoystickEvent processes joystick events.
diff --git a/lib/provider/file-provider.go b/lib/provider/file-provider.go
new file mode 100644
index 0000000..3e08406
--- /dev/null
+++ b/lib/provider/file-provider.go
@@ -0,0 +1,53 @@
+package provider
+
+import (
+ "conjure-os/lib/config"
+ "mime"
+ "net/http"
+ "os"
+ "path/filepath"
+)
+
+func LoadImage(gameId string, imageSrc string) *FileBlob {
+ imagePath := filepath.Join(config.GetDefaultConjureGamesDirectory(), gameId, imageSrc)
+ blob, err := GetFileBlob(imagePath)
+ if err != nil {
+ panic(err)
+ }
+
+ return blob
+}
+
+type FileBlob struct {
+ Name string
+ MimeType string
+ Data []byte
+}
+
+func GetFileBlob(path string) (*FileBlob, error) {
+ data, err := os.ReadFile(path)
+ if err != nil {
+ return nil, err
+ }
+
+ // Try to guess MIME type from content
+ mimeType := http.DetectContentType(data)
+
+ // Fallback to extension-based detection
+ if mimeType == "application/octet-stream" {
+ ext := filepath.Ext(path)
+ if ext != "" {
+ if t := mime.TypeByExtension(ext); t != "" {
+ mimeType = t
+ }
+ }
+ }
+
+ name := filepath.Base(path)
+
+ return &FileBlob{
+ Name: name,
+ MimeType: mimeType,
+ Data: data,
+ }, nil
+}
diff --git a/lib/provider/provider.go b/lib/provider/provider.go
index 4dc97d6..aeb356a 100644
--- a/lib/provider/provider.go
+++ b/lib/provider/provider.go
@@ -206,8 +206,6 @@ func GetConjureGameInfo() []models.Game {
metadata, err := io.ReadAll(rc)
game := parseGameInfo([]byte(escapeBackslashes(string(metadata))))
fmt.Println(game.ThumbnailPath)
- game.ThumbnailPath = filepath.Join(conjBase, game.ThumbnailPath)
- game.ImagePath = filepath.Join(conjBase, game.ImagePath)
games = append(games, game)
check(err)
}