Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 141 additions & 0 deletions docs/analog-input.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# Analog Input Architecture

This document explains how LessUI handles analog stick input and the challenges for devices with limited controls.

## How Analog Input Works

LessUI has two separate input paths:

```
┌─────────────────────┐ ┌──────────────────┐
│ Config File │ │ Hardware │
│ (digital only) │ │ (if present) │
│ │ │ │
│ bind A = B │ │ Analog stick │
│ bind Up = UP │ │ events │
└─────────┬───────────┘ └────────┬─────────┘
│ │
▼ ▼
┌──────────────┐ ┌──────────────┐
│ buttons │ │ pad.laxis │
│ bitmask │ │ pad.raxis │
└──────┬───────┘ └──────┬───────┘
│ │
└──────────┬───────────────┘
input_state_callback()
Core
```

**Digital buttons** (d-pad, face buttons, triggers) flow through the config system. The `.cfg` files map core buttons to device buttons.

**Analog sticks** bypass the config system entirely. Hardware events write directly to `pad.laxis` and `pad.raxis`, which are returned to cores when they request `RETRO_DEVICE_ANALOG` input.

### Supported Config Mappings

The config file syntax only supports digital buttons:

```
bind <core_button> = <device_button>
```

Available device buttons:

```
UP, DOWN, LEFT, RIGHT, A, B, X, Y, START, SELECT, L1, R1, L2, R2, L3, R3
```

Plus modifier variants: `MENU+A`, `MENU+B`, etc.

There is no config syntax for analog stick mapping (e.g., no `L_STICK_UP`).

## Device Categories

### No Analog Sticks

**Devices:** miyoomini, trimuismart, rg35xx, my355, tg5040, zero28

These devices have no hardware analog sticks. The `pad.laxis` and `pad.raxis` values remain at zero, meaning cores receive no analog input.

| System | Impact |
| ---------- | ----------------------------------------------- |
| N64 | Unplayable - analog stick required for 3D games |
| PSP | Unplayable - analog nub required for many games |
| Dreamcast | Degraded - d-pad works but analog preferred |
| Atari 5200 | May have issues - original used analog joystick |
| All others | Fine - d-pad based systems |

### One Analog Stick

**Devices:** rgb30, my282

These devices have a single (left) analog stick. The left stick works automatically for cores that need it.

| System | Impact |
| -------------- | ------------------------------------------ |
| N64 | Works - left stick maps to N64 analog |
| PSP | Works - left stick maps to PSP nub |
| Dreamcast | Partial - left stick works, no right stick |
| PS (DualShock) | Partial - only left stick available |

### Two Analog Sticks

**Devices:** rg35xxplus, m17, magicmini

These devices have full analog capability. Both sticks pass through to cores automatically.

| System | Impact |
| -------------- | ------------ |
| N64 | Full support |
| PSP | Full support |
| Dreamcast | Full support |
| PS (DualShock) | Full support |

## The Problem

The current architecture assumes hardware capability matches core requirements. There is no translation layer.

- **Have the hardware?** Analog sticks automatically work. No config needed.
- **Missing the hardware?** Cores receive zeros. No workaround exists.

This means N64 and PSP are effectively broken on devices without analog sticks.

## Proposed Solution

Add a d-pad to analog emulation option:

```
dpad_to_analog = left # d-pad simulates left stick
dpad_to_analog = right # d-pad simulates right stick
dpad_to_analog = none # default, current behavior
```

When enabled, `input_state_callback` would return full-deflection analog values (±32767) when d-pad directions are pressed.

This provides digital-only control (no gradual movement) but makes analog-dependent games **playable** rather than broken.

### Implementation Location

The change would be in `workspace/all/player/player.c` in the `input_state_callback` function, which currently returns raw `pad.laxis`/`pad.raxis` values for `RETRO_DEVICE_ANALOG` requests.

## Platform Analog Support Reference

Platforms define analog axes in their `platform.h`:

| Platform | AXIS_LX/LY | AXIS_RX/RY | Analog Support |
| ----------- | ---------- | ---------- | ---------------------------------- |
| miyoomini | AXIS_NA | AXIS_NA | None |
| trimuismart | AXIS_NA | AXIS_NA | None |
| rg35xx | AXIS_NA | AXIS_NA | None |
| rg35xxplus | Defined | Defined | 2 sticks |
| my355 | Defined | Defined | Hardware present but not wired |
| tg5040 | Defined | Defined | Hardware present but not wired |
| zero28 | Defined | Defined | Hardware present but not wired |
| rgb30 | Defined | Defined | 1 stick (left only in practice) |
| m17 | Defined | Defined | 2 sticks (currently commented out) |
| my282 | Defined | AXIS_NA | 1 stick |
| magicmini | Defined | Defined | 2 sticks |

`AXIS_NA = -1` means the axis is not available. When an axis equals `AXIS_NA`, the comparison in `api.c` never matches, so `pad.laxis`/`pad.raxis` stay at zero.
79 changes: 38 additions & 41 deletions docs/cores-research.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@
| Sega CD | SEGACD | SEGACD.pak | picodrive | `picodrive_libretro.so` |
| Sega 32X | 32X | 32X.pak | picodrive | `picodrive_libretro.so` |
| SG-1000 | SG1000 | SG1000.pak | picodrive | `picodrive_libretro.so` |
| Atari 2600 | ATARI | ATARI.pak | stella | `stella_libretro.so` |
| Atari 5200 | A5200 | A5200.pak | atari800 | `atari800_libretro.so` |
| Atari 2600 | A2600 | A2600.pak | stella2014 | `stella2014_libretro.so` |
| Atari 5200 | A5200 | A5200.pak | a5200 | `a5200_libretro.so` |
| Atari 7800 | A7800 | A7800.pak | prosystem | `prosystem_libretro.so` |
| Atari Lynx | LYNX | LYNX.pak | mednafen_lynx | `mednafen_lynx_libretro.so` |
| WonderSwan & Color | WS | WS.pak | mednafen_wswan | `mednafen_wswan_libretro.so` |
Expand Down Expand Up @@ -73,41 +73,38 @@

## LessUI-Cores (Cores we currently build)

1. atari800 - libretro/libretro-atari800 - atari800_libretro.so
1. a5200 - libretro/a5200 - a5200_libretro.so
2. beetle-lynx - libretro/beetle-lynx-libretro - mednafen_lynx_libretro.so
3. beetle-pce-fast - libretro/beetle-pce-fast-libretro - mednafen_pce_fast_libretro.so
4. beetle-supergrafx - libretro/beetle-supergrafx-libretro - mednafen_supergrafx_libretro.so
5. beetle-vb - libretro/beetle-vb-libretro - mednafen_vb_libretro.so
6. beetle-wswan - libretro/beetle-wswan-libretro - mednafen_wswan_libretro.so
7. bluemsx - libretro/blueMSX-libretro - bluemsx_libretro.so
8. dosbox-pure - libretro/dosbox-pure - dosbox_pure_libretro.so
9. fake08 - jtothebell/fake-08 - fake08_libretro.so
10. fbneo - libretro/FBNeo - fbneo_libretro.so
11. fceumm - libretro/libretro-fceumm - fceumm_libretro.so
12. flycast - flyinghead/flycast - flycast_libretro.so
13. fuse - libretro/fuse-libretro - fuse_libretro.so
14. gambatte - libretro/gambatte-libretro - gambatte_libretro.so
15. gpsp - libretro/gpsp - gpsp_libretro.so
16. gw - libretro/gw-libretro - gw_libretro.so
17. mame2003-plus - libretro/mame2003-plus-libretro - mame2003_plus_libretro.so
18. melonds - libretro/melonds - melonds_libretro.so
19. mgba - libretro/mgba - mgba_libretro.so
20. mupen64plus-next - libretro/mupen64plus-libretro-nx - mupen64plus_next_libretro.so
21. neocd - libretro/neocd_libretro - neocd_libretro.so
22. pcsx - libretro/pcsx_rearmed - pcsx_rearmed_libretro.so
23. picodrive - libretro/picodrive - picodrive_libretro.so
24. pokemini - libretro/PokeMini - pokemini_libretro.so
25. ppsspp - hrydgard/ppsspp - ppsspp_libretro.so
26. prosystem - libretro/prosystem-libretro - prosystem_libretro.so
27. puae - libretro/libretro-uae - puae_libretro.so
28. race - libretro/RACE - race_libretro.so
29. scummvm - libretro/scummvm - scummvm_libretro.so
30. snes9x2005 - libretro/snes9x2005 - snes9x2005_plus_libretro.so
31. stella - stella-emu/stella - stella_libretro.so
32. supafaust - libretro/supafaust - mednafen_supafaust_libretro.so
33. tic80 - libretro/TIC-80 - tic80_libretro.so
34. vecx - libretro/libretro-vecx - vecx_libretro.so
35. vice - libretro/vice-libretro - vice_x64_libretro.so
4. beetle-vb - libretro/beetle-vb-libretro - mednafen_vb_libretro.so
5. beetle-wswan - libretro/beetle-wswan-libretro - mednafen_wswan_libretro.so
6. bluemsx - libretro/blueMSX-libretro - bluemsx_libretro.so
7. dosbox-pure - libretro/dosbox-pure - dosbox_pure_libretro.so
8. fake08 - jtothebell/fake-08 - fake08_libretro.so
9. fbneo - libretro/FBNeo - fbneo_libretro.so
10. fceumm - libretro/libretro-fceumm - fceumm_libretro.so
11. flycast - flyinghead/flycast - flycast_libretro.so
12. fuse - libretro/fuse-libretro - fuse_libretro.so
13. gambatte - libretro/gambatte-libretro - gambatte_libretro.so
14. gpsp - libretro/gpsp - gpsp_libretro.so
15. mame2003-plus - libretro/mame2003-plus-libretro - mame2003_plus_libretro.so
16. melonds - libretro/melonds - melonds_libretro.so
17. mgba - libretro/mgba - mgba_libretro.so
18. mupen64plus-next - libretro/mupen64plus-libretro-nx - mupen64plus_next_libretro.so
19. neocd - libretro/neocd_libretro - neocd_libretro.so
20. pcsx - libretro/pcsx_rearmed - pcsx_rearmed_libretro.so
21. picodrive - libretro/picodrive - picodrive_libretro.so
22. pokemini - libretro/PokeMini - pokemini_libretro.so
23. ppsspp - hrydgard/ppsspp - ppsspp_libretro.so
24. prosystem - libretro/prosystem-libretro - prosystem_libretro.so
25. puae - libretro/libretro-uae - puae_libretro.so
26. race - libretro/RACE - race_libretro.so
27. scummvm - libretro/scummvm - scummvm_libretro.so
28. snes9x2005 - libretro/snes9x2005 - snes9x2005_plus_libretro.so
29. stella - stella-emu/stella - stella_libretro.so
30. supafaust - libretro/supafaust - mednafen_supafaust_libretro.so
31. tic80 - libretro/TIC-80 - tic80_libretro.so
32. vice - libretro/vice-libretro - vice_x64_libretro.so

## Launcher Cores

Expand Down Expand Up @@ -264,12 +261,12 @@ The SG-1000 is the exception, using **gearsystem** as its default rather than pi

### Atari systems span multiple generations

| System | Folder | Default Core |
| ---------- | ------------------- | -------------- |
| Atari 2600 | ATARI | **stella2014** |
| Atari 5200 | FIFTYTWOHUNDRED | **atari800** |
| Atari 7800 | SEVENTYEIGHTHUNDRED | **prosystem** |
| Atari Lynx | LYNX | **handy** |
| System | Folder | Default Core |
| ---------- | ------------------- | ----------------- |
| Atari 2600 | ATARI | **stella2014** |
| Atari 5200 | FIFTYTWOHUNDRED | **a5200** |
| Atari 7800 | SEVENTYEIGHTHUNDRED | **prosystem** |
| Atari Lynx | LYNX | **mednafen_lynx** |

### NEC PC Engine family uses Mednafen cores

Expand Down
2 changes: 1 addition & 1 deletion docs/cores.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ The main LessUI Makefile downloads cores during the build:

```makefile
# Pre-built cores from LessUI-Cores repository (versioned releases)
PLAYER_CORES_VERSION ?= 20251218-0
PLAYER_CORES_VERSION ?= 20251220-2
CORES_BASE = https://github.com/lessui-hq/LessUI-Cores/releases/download/$(PLAYER_CORES_VERSION)

cores-download:
Expand Down
2 changes: 1 addition & 1 deletion scripts/calculate-buffer-scale.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"NGP/NGPC (race)": (160, 152),
# Atari
"A2600 (stella)": (160, 192),
"A5200 (atari800)": (336, 240),
"A5200 (a5200)": (336, 240),
"A7800 (prosystem)": (320, 225),
"LYNX (mednafen_lynx)": (160, 102),
# Arcade
Expand Down
35 changes: 24 additions & 11 deletions scripts/generate-scaling-configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
# =============================================================================

# Minimum fill percentage to recommend Native scaling
FILL_THRESHOLD_LARGE_SCREEN = 90 # Screens >= 3"
FILL_THRESHOLD_LARGE_SCREEN = 94 # Screens >= 3"
FILL_THRESHOLD_SMALL_SCREEN = 100 # Screens < 3" (must be perfect fit)

# Screen size threshold (inches)
Expand All @@ -33,7 +33,7 @@

# Format: (width, height, diagonal_inches)
PLATFORMS = {
"miyoomini": (640, 480, 2.8), # Under 3" - strict threshold
# miyoomini excluded: has 480p/560p and 2.8"/3.5" variants we can't detect yet
"rg35xxplus": (640, 480, 3.5),
"rgb30": (720, 720, 4.0), # Square
"m17": (480, 272, 4.3), # Miyoo A30 / similar
Expand All @@ -60,32 +60,45 @@
# =============================================================================

# From workspace/all/paks/Emus/cores.json
# Skip MAME/FBN which have "varies" resolution
# Skip MAME/FBN/GW which have "varies" resolution
# Skip PS - always uses aspect scaling (many games use non-native resolutions)
CORES = {
# Nintendo
"GB": (160, 144),
"GBC": (160, 144),
"GBA": (240, 160),
"MGBA": (240, 160),
"SGB": (256, 224),
"FC": (256, 240),
"SFC": (256, 224),
"SUPA": (256, 224),
"VB": (384, 224),
# Sega
"MD": (320, 224),
"GG": (160, 144),
"SMS": (256, 192),
# NEC
"PCE": (512, 243),
"PCECD": (512, 243),
"VB": (384, 224),
# SNK
"NGP": (160, 152),
"NGPC": (160, 152),
"PKM": (96, 64),
"PICO": (128, 128),
"TIC": (240, 136),
"SGB": (256, 224),
"MGBA": (240, 160),
"SUPA": (256, 224),
"NG": (320, 224),
"NEOCD": (320, 224),
"CPS1": (384, 224),
"CPS2": (384, 224),
"CPS3": (384, 224),
"NG": (320, 224),
# Atari
"A2600": (160, 192),
"A5200": (336, 240),
"A7800": (320, 240),
"LYNX": (160, 102),
# Bandai
"WS": (224, 144),
"WSC": (224, 144),
# Other
"PKM": (96, 64),
"PICO": (128, 128),
}

# =============================================================================
Expand Down
7 changes: 7 additions & 0 deletions skeleton/BASE/Bios/A5200/about.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Atari 5200

Core: a5200

BIOS (required):
5200.rom - Atari 5200 BIOS
MD5: 281f20ea4320404ec820fb7ec0693b38
7 changes: 7 additions & 0 deletions skeleton/BASE/Bios/A7800/about.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Atari 7800

Core: prosystem

BIOS (optional but recommended):
7800 BIOS (U).rom - NTSC/US BIOS
7800 BIOS (E).rom - PAL/EU BIOS
7 changes: 7 additions & 0 deletions skeleton/BASE/Bios/LYNX/about.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Atari Lynx

Core: mednafen_lynx

BIOS (required):
lynxboot.img - Lynx boot ROM
MD5: fcd403db69f54290b51035d82f835e7b
9 changes: 9 additions & 0 deletions skeleton/BASE/Bios/NEOCD/about.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Neo Geo CD

Core: neocd

BIOS (required):
neocd_z.rom - CDZ BIOS (recommended)
MD5: 11526d58d4c524daef7d5d677dc6b004
neocd_f.rom - Front Loader BIOS (optional)
MD5: 8834880c33164ccbe6476b559f3e37de
8 changes: 8 additions & 0 deletions skeleton/BASE/Roms/Atari 2600 (A2600)/about.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Atari 2600

Core: stella

Supported file types:
.a26, .bin, .zip, .7z

No BIOS required.
11 changes: 11 additions & 0 deletions skeleton/BASE/Roms/Atari 5200 (A5200)/about.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Atari 5200

Core: a5200

Supported file types:
.a52, .bin, .zip, .7z

BIOS (required):
5200.rom - Atari 5200 BIOS

Place BIOS files in: /Bios/A5200/
Loading