Documentation
¶
Index ¶
- Constants
- Variables
- func ApplyMissingDefaults(config *Config, presentKeys map[string]bool)
- func AspectRatioDisplayName(mode string) string
- func AtomicWriteJSON(path string, data interface{}) error
- func CorrectInputConfig(config *Config, isValidKey, isValidPad func(string) bool)
- func CreateConfigIfMissing() error
- func CreateLibraryIfMissing() error
- func DeleteConfig() error
- func DeleteLibrary() error
- func EnsureDirectories() error
- func GetArtworkDir() (string, error)
- func GetBaseDir() (string, error)
- func GetConfigPath() (string, error)
- func GetGameArtworkPath(gameCRC string) (string, error)
- func GetGameCHTRumblePath(gameCRC string) (string, error)
- func GetGameRumblePath(gameID string) (string, error)
- func GetGameSaveDir(gameCRC string) (string, error)
- func GetLibraryPath() (string, error)
- func GetMetadataDir() (string, error)
- func GetRumbleDir() (string, error)
- func GetSavesDir() (string, error)
- func GetScreenshotDir() (string, error)
- func Init(dataDirName string)
- func ReadJSON(path string, data interface{}) error
- func SanitizeLibraryEntries(lib *Library)
- func SaveConfig(config *Config) error
- func SaveLibrary(library *Library) error
- func ValidFontSize(size int) int
- func ValidPadMapping(guid, line string) bool
- func ValidateConfig(config *Config, validThemes []string) []string
- func ValidateInputConfig(config *Config, isValidKey, isValidPad func(string) bool) []string
- func ValidateLibrary(lib *Library) []string
- type AudioConfig
- type BIOSConfig
- type Config
- type ControllerProfile
- type GameDisc
- type GameEntry
- type GameSettings
- type InputConfig
- type Library
- func (lib *Library) AddExcludedPath(path string)
- func (lib *Library) AddGame(entry *GameEntry)
- func (lib *Library) AddScanDirectory(path string, recursive bool)
- func (lib *Library) GameCount() int
- func (lib *Library) GetGame(gameCRC string) *GameEntry
- func (lib *Library) GetGamesSorted(sortBy string, favoritesOnly bool) []*GameEntry
- func (lib *Library) GetGamesSortedFiltered(sortBy string, favoritesOnly bool, searchText string) []*GameEntry
- func (lib *Library) IsPathExcluded(path string) bool
- func (lib *Library) RemoveExcludedPath(path string)
- func (lib *Library) RemoveGame(gameCRC string)
- func (lib *Library) RemoveScanDirectory(path string)
- func (lib *Library) UpdatePlayTime(gameCRC string, secondsPlayed int64)
- type LibraryView
- type PlayerConfig
- type RetroAchievementsConfig
- type RewindConfig
- type ScanDirectory
- type ShaderConfig
- type VideoConfig
- type WindowConfig
Constants ¶
const DefaultRumbleScale = 1.0
DefaultRumbleScale is the rumble intensity assigned to new profiles.
const MaxInputPlayers = 2
MaxInputPlayers is the maximum number of player slots stored in config.
Variables ¶
var FontSizePresets = []int{10, 12, 14, 16, 18, 20, 24, 28, 32}
FontSizePresets lists the available font size options
var ValidAspectRatios = []string{"dar", "4:3", "1:1", "stretch"}
ValidAspectRatios lists the allowed aspect ratio mode values
Functions ¶
func ApplyMissingDefaults ¶
ApplyMissingDefaults sets default values for config fields that are absent from the JSON file. This replaces ensureConfigDefaults with key-presence awareness: only truly missing fields get defaults, preserving intentional zero values (e.g., volume=0).
func AspectRatioDisplayName ¶
AspectRatioDisplayName returns a user-facing label for the given mode.
func AtomicWriteJSON ¶
AtomicWriteJSON writes data to a JSON file atomically. It writes to a temporary file first, then renames to the target path. This ensures the file is never in a partially-written state.
func CorrectInputConfig ¶
CorrectInputConfig removes invalid entries from input override maps and profile/player configuration. Profiles missing identity fields are dropped, duplicate IDs and duplicate names per controller model are dropped, invalid bindings are removed, out-of-range rumble scales are reset to the default, the players list is clamped, and dangling player profile references are cleared. isValidKey checks if a key name is valid, isValidPad checks if a pad name is valid.
func CreateConfigIfMissing ¶
func CreateConfigIfMissing() error
CreateConfigIfMissing creates a default config.json if it doesn't exist
func CreateLibraryIfMissing ¶
func CreateLibraryIfMissing() error
CreateLibraryIfMissing creates a default library.json if it doesn't exist
func EnsureDirectories ¶
func EnsureDirectories() error
EnsureDirectories creates all necessary directories for the application
func GetArtworkDir ¶
GetArtworkDir returns the full path to the artwork directory
func GetBaseDir ¶
GetBaseDir returns the base directory for application data. The directory name is set by Init(). Example paths: - macOS: ~/Library/Application Support/<appName> - Linux: ~/.local/share/<appName> - Windows: %APPDATA%/<appName>
func GetConfigPath ¶
GetConfigPath returns the full path to config.json
func GetGameArtworkPath ¶
GetGameArtworkPath returns the path to a game's box art
func GetGameCHTRumblePath ¶ added in v0.5.0
GetGameCHTRumblePath returns the path to a game's rumble CHT file
func GetGameRumblePath ¶
GetGameRumblePath returns the path to a game's .erumble file
func GetGameSaveDir ¶
GetGameSaveDir returns the save directory for a specific game (by CRC32)
func GetLibraryPath ¶
GetLibraryPath returns the full path to library.json
func GetMetadataDir ¶
GetMetadataDir returns the full path to the metadata directory
func GetRumbleDir ¶
GetRumbleDir returns the full path to the rumble directory
func GetSavesDir ¶
GetSavesDir returns the full path to the saves directory
func GetScreenshotDir ¶
GetScreenshotDir returns the full path to the screenshots directory
func Init ¶
func Init(dataDirName string)
Init sets the application data directory name. Must be called before any storage operations.
func SanitizeLibraryEntries ¶
func SanitizeLibraryEntries(lib *Library)
SanitizeLibraryEntries silently corrects invalid game entry fields. This runs on load so invalid values never reach the UI or emulator.
func SaveConfig ¶
SaveConfig saves the configuration to config.json atomically
func SaveLibrary ¶
SaveLibrary saves the library to library.json atomically
func ValidFontSize ¶
ValidFontSize returns the nearest valid preset font size.
func ValidPadMapping ¶ added in v0.5.0
ValidPadMapping reports whether guid and line form a well-formed pad mapping entry: the GUID is 32 lowercase hex characters, the line starts with the GUID, and the line is a single line.
func ValidateConfig ¶
ValidateConfig checks all config fields against valid ranges and returns human-readable error descriptions. An empty slice means the config is valid. validThemes should be the list of known theme names.
func ValidateInputConfig ¶
ValidateInputConfig checks input config overrides using the provided validators. Returns error descriptions for invalid entries. isValidKey checks if a key name is valid, isValidPad checks if a pad name is valid.
func ValidateLibrary ¶
ValidateLibrary checks library-level fields against valid ranges and returns human-readable error descriptions. An empty slice means the library is valid.
Types ¶
type AudioConfig ¶
type AudioConfig struct {
Volume float64 `json:"volume"`
Muted bool `json:"muted"`
FastForwardMute bool `json:"fastForwardMute"` // Mute audio during fast-forward (default: true)
}
AudioConfig contains audio-related settings
type BIOSConfig ¶
type BIOSConfig struct {
Active string `json:"active,omitempty"` // Active variant label, empty = none
Files map[string]string `json:"files,omitempty"` // variant label -> file path
}
BIOSConfig stores the user's BIOS configuration for one BIOSOption.
type Config ¶
type Config struct {
Version int `json:"version"`
Theme string `json:"theme"` // Theme name: "Default", "Dark", "Light", "Retro"
FontSize int `json:"fontSize"` // 10-32, default 14
Video VideoConfig `json:"video"`
Audio AudioConfig `json:"audio"`
Window WindowConfig `json:"window"`
Library LibraryView `json:"library"`
Shaders ShaderConfig `json:"shaders"`
Rewind RewindConfig `json:"rewind"`
Input InputConfig `json:"input"`
CoreOptions map[string]string `json:"coreOptions,omitempty"`
BIOS map[string]BIOSConfig `json:"bios,omitempty"`
RetroAchievements RetroAchievementsConfig `json:"retroAchievements"`
}
Config represents the application configuration stored in config.json
func CorrectConfig ¶
CorrectConfig resets any invalid fields to their defaults from DefaultConfig(). Valid fields are preserved. validThemes should be the list of known theme names.
func DefaultConfig ¶
func DefaultConfig() *Config
DefaultConfig returns a new Config with default values
func LoadConfig ¶
LoadConfig loads the configuration from config.json. If the file doesn't exist, it returns default configuration. If the file is corrupted, it returns an error. Missing fields (absent from JSON) are silently defaulted.
type ControllerProfile ¶ added in v0.5.0
type ControllerProfile struct {
ID string `json:"id"`
SDLID string `json:"sdlId"`
Controller string `json:"controller"`
Name string `json:"name"`
RumbleScale float64 `json:"rumbleScale"` // intensity multiplier 0.0-3.0 in 0.05 steps, 0=off
Bindings map[string]string `json:"bindings,omitempty"` // button name -> pad button name override
}
ControllerProfile is a named controller button mapping for a controller model. The model is identified by SDLID+Controller; multiple profiles can exist for the same model (e.g. third-party pads reported as the same device). ID is immutable and referenced by PlayerConfig; Name is the user-editable display name, unique per model.
func (*ControllerProfile) MatchesPad ¶ added in v0.5.0
func (p *ControllerProfile) MatchesPad(sdlID, name string) bool
MatchesPad reports whether this profile's controller model matches the given pad identity (SDL ID and name).
func (*ControllerProfile) UnmarshalJSON ¶ added in v0.5.0
func (p *ControllerProfile) UnmarshalJSON(data []byte) error
UnmarshalJSON decodes a profile with RumbleScale pre-set to the default, so a profile saved without the key loads at the default intensity instead of 0 (off). An explicit 0 in the file is preserved.
type GameDisc ¶ added in v0.3.0
type GameDisc struct {
Index int `json:"index"` // 0-based disc index (DiscNumber-1)
File string `json:"file"` // Path to this disc's image on disk
Name string `json:"name"` // Per-disc display name
}
GameDisc is one disc of a multi-disc disc-based game.
type GameEntry ¶
type GameEntry struct {
CRC32 string `json:"crc32"`
File string `json:"file,omitempty"` // Cartridge ROM/archive path; disc games leave this empty and use Discs
Name string `json:"name"` // Full No-Intro name from RDB
DisplayName string `json:"displayName"` // Cleaned name for display (region info removed)
Region string `json:"region"` // "us", "eu", "jp" (from RDB)
Serial string `json:"serial,omitempty"` // Disc/product serial (game ID), when known
Developer string `json:"developer,omitempty"`
Publisher string `json:"publisher,omitempty"`
Genre string `json:"genre,omitempty"`
Franchise string `json:"franchise,omitempty"`
ESRBRating string `json:"esrbRating,omitempty"`
ReleaseDate string `json:"releaseDate,omitempty"` // "Month / Year" format
System string `json:"system,omitempty"` // Variant name (e.g. "Neo Geo Pocket") - set when >1 RDB variant
ConsoleID int `json:"consoleID,omitempty"` // RetroAchievements console ID; 0 = use system default
Favorite bool `json:"favorite"` // User marked as favorite
Missing bool `json:"missing"` // true if ROM file not found
PlayTimeSeconds int64 `json:"playTimeSeconds"` // Total play time
LastPlayed int64 `json:"lastPlayed"` // Unix timestamp
Added int64 `json:"added"` // Unix timestamp when added to library
Settings GameSettings `json:"settings"` // Per-game settings
// Discs lists the discs of a disc-based game (one entry even for a
// single-disc game), ordered by Index. Empty for cartridge games,
// which use File.
Discs []GameDisc `json:"discs,omitempty"`
// SelectedDisc is the 0-based slice index into Discs to launch.
// Persisted so the chosen disc is remembered. Ignored when Discs is
// empty.
SelectedDisc int `json:"selectedDisc,omitempty"`
}
GameEntry represents a single game in the library
type GameSettings ¶
type GameSettings struct {
SaveSlot int `json:"saveSlot,omitempty"` // Last-used save state slot (0-9)
}
GameSettings contains per-game configuration overrides
type InputConfig ¶
type InputConfig struct {
P1Keyboard map[string]string `json:"p1Keyboard,omitempty"` // button name -> key name override
DisableAnalogStick bool `json:"disableAnalogStick,omitempty"` // disable analog stick mirroring d-pad
Profiles []ControllerProfile `json:"profiles,omitempty"` // named controller mappings, in creation order
Players []PlayerConfig `json:"players,omitempty"` // player slot -> profile assignment
PadMappings map[string]string `json:"padMappings,omitempty"` // SDL GUID -> generated standard-layout mapping line
}
InputConfig contains input binding overrides and controller configuration. Empty/nil maps mean "use adaptor defaults." Only user overrides are stored.
func (*InputConfig) NewProfileID ¶ added in v0.5.0
func (c *InputConfig) NewProfileID() string
NewProfileID returns a random 8-hex-char profile ID unique within this input config.
func (*InputConfig) PlayerProfile ¶ added in v0.5.0
func (c *InputConfig) PlayerProfile(player int) *ControllerProfile
PlayerProfile returns the profile assigned to the given player slot, or nil if the slot is unassigned or the reference is dangling.
func (*InputConfig) PlayerRumbleScale ¶ added in v0.5.0
func (c *InputConfig) PlayerRumbleScale(player int) float64
PlayerRumbleScale returns the rumble intensity for the given player slot from the assigned profile, or 0 (off) when the slot has no profile.
func (*InputConfig) ProfileByID ¶ added in v0.5.0
func (c *InputConfig) ProfileByID(id string) *ControllerProfile
ProfileByID returns the profile with the given ID, or nil if not found.
func (*InputConfig) RumbleEnabled ¶ added in v0.5.0
func (c *InputConfig) RumbleEnabled() bool
RumbleEnabled reports whether any player slot has a profile with a non-zero rumble intensity.
type Library ¶
type Library struct {
Version int `json:"version"`
ScanDirectories []ScanDirectory `json:"scanDirectories"`
ExcludedPaths []string `json:"excludedPaths"`
Games map[string]*GameEntry `json:"games"` // CRC32 hex string -> entry
}
Library represents the game library stored in library.json
func CorrectLibrary ¶
CorrectLibrary resets any invalid library-level fields to their defaults.
func DefaultLibrary ¶
func DefaultLibrary() *Library
DefaultLibrary returns a new Library with default values
func LoadLibrary ¶
LoadLibrary loads the library from library.json. If the file doesn't exist, it returns an empty library. If the file is corrupted, it returns an error.
func (*Library) AddExcludedPath ¶
AddExcludedPath adds a path to the exclusion list
func (*Library) AddScanDirectory ¶
AddScanDirectory adds a directory to scan for ROMs
func (*Library) GetGamesSorted ¶
GetGamesSorted returns a sorted slice of game entries
func (*Library) GetGamesSortedFiltered ¶
func (lib *Library) GetGamesSortedFiltered(sortBy string, favoritesOnly bool, searchText string) []*GameEntry
GetGamesSortedFiltered returns a sorted slice of game entries filtered by search text. Search is case-insensitive and matches against DisplayName and Name fields. Empty searchText returns all games (same as GetGamesSorted).
func (*Library) IsPathExcluded ¶
IsPathExcluded checks if a path is in the exclusion list
func (*Library) RemoveExcludedPath ¶
RemoveExcludedPath removes a path from the exclusion list
func (*Library) RemoveGame ¶
RemoveGame removes a game from the library
func (*Library) RemoveScanDirectory ¶
RemoveScanDirectory removes a directory from the scan list
func (*Library) UpdatePlayTime ¶
UpdatePlayTime adds play time to a game and updates last played
type LibraryView ¶
type LibraryView struct {
ViewMode string `json:"viewMode"` // "icon" or "list"
SortBy string `json:"sortBy"` // "title", "lastPlayed", "playTime"
FavoritesFilter bool `json:"favoritesFilter"` // Show only favorites
}
LibraryView contains library display preferences
type PlayerConfig ¶ added in v0.5.0
type PlayerConfig struct {
Profile string `json:"profile,omitempty"` // ControllerProfile.ID
}
PlayerConfig holds the controller assignment for one player slot. An empty Profile means no controller is assigned to that player.
type RetroAchievementsConfig ¶
type RetroAchievementsConfig struct {
Enabled bool `json:"enabled"`
EncoreMode bool `json:"encoreMode"` // Allow re-triggering unlocked achievements
UnlockSound bool `json:"unlockSound"` // Play sound on achievement unlock
ShowNotification bool `json:"showNotification"` // Show popup notification on achievement unlock
AutoScreenshot bool `json:"autoScreenshot"` // Take screenshot on achievement unlock
SuppressHardcoreWarning bool `json:"suppressHardcoreWarning"` // Hide "Unknown Emulator" hardcore warning
SpectatorMode bool `json:"spectatorMode"` // Watch achievements without submitting unlocks
Username string `json:"username,omitempty"`
Token string `json:"token,omitempty"` // Auth token (password is never stored)
}
RetroAchievementsConfig contains RetroAchievements integration settings
type RewindConfig ¶
type RewindConfig struct {
Enabled bool `json:"enabled"` // Default: false (off due to RAM usage)
BufferSizeMB int `json:"bufferSizeMB"` // Default: 40
FrameStep int `json:"frameStep"` // Default: 1 (capture every frame)
}
RewindConfig contains rewind feature settings
type ScanDirectory ¶
ScanDirectory represents a directory to scan for ROMs
type ShaderConfig ¶
type ShaderConfig struct {
UIShaders []string `json:"uiShaders"` // Ordered list of shader IDs for UI context
GameShaders []string `json:"gameShaders"` // Ordered list of shader IDs for Game context
}
ShaderConfig contains shader effect settings
type VideoConfig ¶
type VideoConfig struct {
AspectRatio string `json:"aspectRatio"`
}
VideoConfig contains video-related settings