Skip to content
Closed
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
71 changes: 67 additions & 4 deletions src/common/backends/imgui/launcher_imgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2376,6 +2376,7 @@ static const char* elide_left(const char* s, float max_w, char* out, size_t cap)
bool any_deep_display(const LauncherModel* m) {
return m->has_window_size || m->has_renderer || m->has_supersampling ||
m->has_antialiasing || m->has_texture_filter || m->has_screen_kind ||
m->has_scanlines ||
m->has_fmv_filter ||
m->has_frame_interp || m->has_skip_fmv ||
m->has_geometry_precision ||
Expand Down Expand Up @@ -2705,6 +2706,30 @@ void draw_display_controls(LauncherModel* m, const LauncherTheme& th) {
launcher_model_cycle_screen_kind(m);
}

// Scanlines: darken every other display line for a CRT look. Independent of
// the Screen model colour filter above — the two compose. The strength row
// only appears once it is on.
if (m->has_scanlines) {
row_label("Scanlines", th);
bool sl = m->s.scanlines != 0;
if (ImGui::Checkbox("##scanlines", &sl))
launcher_model_toggle_scanlines(m);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal))
ImGui::SetTooltip("Darkens the gaps between display lines for a CRT "
"look.\nApplied at the console's own scanline "
"pitch; cleanest when the\nwindow is at least twice "
"the console's line count tall.");
if (m->s.scanlines) {
row_label("Scanline strength", th);
int p = launcher_model_scanline_strength_pct(m);
ImGui::PushID("scanline_strength");
ImGui::SetNextItemWidth(px(150));
if (ImGui::SliderInt("##scanline_strength", &p, 1, 100, "%d%%"))
launcher_model_set_scanline_strength_pct(m, p);
ImGui::PopID();
}
}

// Frame interpolation is only meaningful under OpenGL (Software has no
// interpolation pass); Presentation target only matters once frame
// interpolation is actually on.
Expand Down Expand Up @@ -3491,6 +3516,42 @@ void settings_pad_label(int binding, char* out, size_t capacity) {
snprintf(out, capacity, "%s", text);
}

/* PSX's runtime matches a host shortcut bound to ONE button or ONE trigger
* direction only while Select is also held (hotkey_pad_binding_down): the
* implicit chord keeps a lone face button from firing Rewind mid-game. A
* two-button capture is stored as an explicit chord and replaces that
* implicit Select. Show the requirement in the label so a player who binds
* "righttrigger+" is not left pressing R2 alone and seeing nothing. */
static bool assist_pad_bind_implies_select(const LauncherModel* m, int binding) {
const SystemProfile* prof = m ? (const SystemProfile*)m->profile : nullptr;
const bool psx = prof && prof->id && std::strcmp(prof->id, "psx") == 0;
return psx && (RECOMP_LAUNCHER_PAD_IS_BUTTON(binding) ||
RECOMP_LAUNCHER_PAD_IS_AXIS(binding));
}

static void assist_pad_label(const LauncherModel* m, int binding,
char* out, size_t capacity) {
char text[96];
settings_pad_label(binding, text, sizeof text);
if (assist_pad_bind_implies_select(m, binding))
snprintf(out, capacity, "select + %s", text);
else
snprintf(out, capacity, "%s", text);
}

static void draw_assist_pad_chord_hint(const LauncherModel* m,
const LauncherTheme& th) {
if (!m) return;
for (int action = 0; action < m->assist_binding_count; ++action) {
if (assist_pad_bind_implies_select(m, m->s.assist_pad_bind[action])) {
ImGui::TextColored(col(th.text_muted),
"Single-button shortcuts fire with Select held; capture two"
" buttons together for a chord without Select.");
return;
}
}
}

void draw_assist_binding_editor(LauncherModel* m, const LauncherTheme& th,
const char* table_id, int action_limit,
bool show_reset) {
Expand Down Expand Up @@ -3533,8 +3594,8 @@ void draw_assist_binding_editor(LauncherModel* m, const LauncherTheme& th,
ImGui::TableSetColumnIndex(2);
bool capture_pad = m->capturing && m->capture_assist &&
m->capture_pad && m->capture_btn == action;
char pad[48];
settings_pad_label(m->s.assist_pad_bind[action], pad, sizeof pad);
char pad[112];
assist_pad_label(m, m->s.assist_pad_bind[action], pad, sizeof pad);
if (ImGui::Button(
capture_pad ? "[ press a button... ]" : pad,
ImVec2(px(170), 0)))
Expand All @@ -3543,6 +3604,7 @@ void draw_assist_binding_editor(LauncherModel* m, const LauncherTheme& th,
}
ImGui::EndTable();
}
draw_assist_pad_chord_hint(m, th);
if (show_reset && ImGui::Button(m->has_assist_tools
? "Reset Assist Controls"
: "Reset Host Shortcuts"))
Expand Down Expand Up @@ -3588,15 +3650,16 @@ void draw_controller_assist_shortcuts(LauncherModel* m,
ImGui::TableSetColumnIndex(2);
bool capture_pad = m->capturing && m->capture_assist &&
m->capture_pad && m->capture_btn == action;
char pad[48];
settings_pad_label(m->s.assist_pad_bind[action], pad, sizeof pad);
char pad[112];
assist_pad_label(m, m->s.assist_pad_bind[action], pad, sizeof pad);
if (ImGui::Button(capture_pad ? "[ button... ]" : pad,
ImVec2(-FLT_MIN, 0)))
launcher_model_begin_assist_capture(m, action, true);
ImGui::PopID();
}
ImGui::EndTable();
}
draw_assist_pad_chord_hint(m, th);
if (m->capturing && m->capture_assist)
ImGui::TextColored(col(th.warn), "Listening... (Esc cancels)");
}
Expand Down
4 changes: 2 additions & 2 deletions src/common/launcher_binds.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ static const char* kHotkeyKey[LNG_HK_COUNT] = {
"WindowBigger", "WindowSmaller", "VolumeUp", "VolumeDown",
"DisplayPerf", "ToggleRenderer",
"SolarBrighter", "SolarDimmer", "SolarLive",
"Rewind", "SaveStateMenu"
"Rewind", "SaveStateMenu", "TurboToggle"
};
// Built-in defaults (shown when config.ini has no line; "" = unbound).
static const char* kHotkeyDef[LNG_HK_COUNT] = {
Expand All @@ -189,7 +189,7 @@ static const char* kHotkeyDef[LNG_HK_COUNT] = {
* (psxrecomp host_keymap reads these from [KeyMap]). */
"", "", "Keypad +", "Keypad -", "F", "R",
"", "", "",
"F8", "F7"
"F8", "F7", "F9"
};

static void copy_str(char* d, size_t cap, const char* s) {
Expand Down
23 changes: 22 additions & 1 deletion src/common/launcher_model.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ static const char* kHotkeyNames[LNG_HK_COUNT] = {
"Window bigger", "Window smaller", "Volume up", "Volume down",
"FPS readout", "Toggle renderer",
"Solar level up", "Solar level down", "Resume live solar",
"Rewind", "Save states menu"
"Rewind", "Save states menu", "Fast-forward toggle"
};
static const char* kViewNames[7] = {
"Dashboard", "Settings", "Controller", "Netplay", "Mods",
Expand Down Expand Up @@ -268,6 +268,7 @@ void launcher_model_init(LauncherModel* m,
m->has_texture_filter = game->has_texture_filter != 0;
m->has_fmv_filter = game->has_fmv_filter != 0;
m->has_screen_kind = game->has_screen_kind != 0;
m->has_scanlines = game->has_scanlines != 0;
m->has_frame_interp = game->has_frame_interp != 0;
m->has_spu_hq = game->has_spu_hq != 0;
m->has_rewind_depth = game->has_rewind_depth != 0;
Expand Down Expand Up @@ -1613,6 +1614,26 @@ const char* launcher_model_screen_kind_label(const LauncherModel* m) {
return names[clampi(m->s.screen_kind, 0, n - 1)];
}

void launcher_model_toggle_scanlines(LauncherModel* m) {
if (!m || !m->has_scanlines) return;
m->s.scanlines = !m->s.scanlines;
/* First time on with no persisted strength: seed the default so the slider
* has a value to show (and the effect is visible). */
if (m->s.scanlines && m->s.scanline_strength_pct == 0)
m->s.scanline_strength_pct = 50;
}

void launcher_model_set_scanline_strength_pct(LauncherModel* m, int pct) {
if (!m || !m->has_scanlines) return;
m->s.scanline_strength_pct = clampi(pct, 1, 100);
}

int launcher_model_scanline_strength_pct(const LauncherModel* m) {
if (!m) return 50;
int p = m->s.scanline_strength_pct;
return (p >= 1 && p <= 100) ? p : 50; /* 0 = unset -> default 50 */
}

void launcher_model_toggle_frame_interp(LauncherModel* m) {
m->s.frame_interp = !m->s.frame_interp;
}
Expand Down
5 changes: 5 additions & 0 deletions src/common/launcher_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ typedef enum {
LNG_HK_SOLAR_BRIGHTER, LNG_HK_SOLAR_DIMMER, LNG_HK_SOLAR_LIVE,
LNG_HK_REWIND, /* PSX local rewind filmstrip → [KeyMap] Rewind */
LNG_HK_SAVE_STATE_MENU, /* PSX save-state slot menu → [KeyMap] SaveStateMenu */
LNG_HK_TURBO_TOGGLE, /* PSX press-to-latch fast-forward → [KeyMap] TurboToggle */
LNG_HK_COUNT
} LngHotkey;

Expand Down Expand Up @@ -370,6 +371,7 @@ typedef struct {
bool has_texture_filter;
bool has_fmv_filter;
bool has_screen_kind;
bool has_scanlines; // present-time scanline post-process (PSX)
bool has_frame_interp;
bool has_spu_hq;
bool has_rewind_depth;
Expand Down Expand Up @@ -733,6 +735,9 @@ void launcher_model_toggle_perspective_texturing(LauncherModel* m);
bool launcher_model_geometry_correction_inert(const LauncherModel* m);
void launcher_model_cycle_screen_kind(LauncherModel* m); // Raw/CRT/Composite/Trinitron
const char* launcher_model_screen_kind_label(const LauncherModel* m);
void launcher_model_toggle_scanlines(LauncherModel* m);
void launcher_model_set_scanline_strength_pct(LauncherModel* m, int pct); // clamps 1..100
int launcher_model_scanline_strength_pct(const LauncherModel* m); // effective (seeds 50)
void launcher_model_toggle_frame_interp(LauncherModel* m);
void launcher_model_cycle_interp_fps(LauncherModel* m); // {0,90,120,144,165,240} wrap
const char* launcher_model_interp_fps_label(const LauncherModel* m); // "Display refresh"/"90 fps"
Expand Down
4 changes: 3 additions & 1 deletion src/consoles/psx/psx_profile.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ static const SystemProfile kSystemProfilePsx = {
(1u << LNG_HK_VOLUME_DOWN) |
(1u << LNG_HK_DISPLAY_PERF) |
RUI_PSX_REWIND_HOTKEY_MASK |
(1u << LNG_HK_SAVE_STATE_MENU)),
(1u << LNG_HK_SAVE_STATE_MENU) |
(1u << LNG_HK_TURBO_TOGGLE)),
/* panels_dashboard */ kPanelsDashboardPsx,
/* panels_settings */ kPanelsSettingsPsx,
/* panels_controller */ kPanelsControllerCommon,
Expand Down Expand Up @@ -160,6 +161,7 @@ static inline void launcher_profile_apply_psx(RecompLauncherCGameInfo* gi) {
gi->has_fmv_filter = 1; /* MDEC decodes video at native res; how it is
* scaled to the window is a player choice. */
gi->has_frame_interp = 0; gi->has_spu_hq = 1; gi->has_skip_fmv = 0;
gi->has_scanlines = 1; /* present-time CRT scanline post-process */
gi->has_turbo_loads = 1; gi->has_bios = 1;
gi->has_deadzone_pct = 1;
gi->has_rewind_depth = RECOMP_UI_PSX_HAS_REWIND ? 1 : 0;
Expand Down
19 changes: 19 additions & 0 deletions src/recomp_launcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,15 @@ struct RecompLauncherCSettings {
* against the roster, falling back to disc 1. Appended additively. */
int disc_index;

/* Scanline post-process on/off (GameInfo.has_scanlines consoles). 0 = off
* (also the unset default, like rewind_enabled — the host default is off, so
* a zero-initialized host predating this field gets the right answer), 1 =
* on. Appended additively. */
int scanlines;
/* Scanline dark-gap depth as a percent. 0 = unset -> the model seeds 50; the
* effective range is 1..100. Stored as a percent (not 0..1) so the whole
* settings struct stays plain-int. Appended additively. */
int scanline_strength_pct;
/* NDS virtual stylus overlay. 0 is unset and means the launcher default
* for the console, which is enabled; 1 is explicitly enabled, -1 is
* explicitly disabled. Bindings live in assist_key_bind/assist_pad_bind so
Expand All @@ -828,6 +837,11 @@ struct RecompLauncherCSettings {
/* Hosts can #ifdef on this to stay source-compatible with older recomp-ui. */
#define RECOMP_LAUNCHER_HAS_FMV_FILTER 1

/* Scanline post-process (Settings.scanlines / scanline_strength_pct,
* GameInfo.has_scanlines). Hosts #ifdef on this to stay source-compatible with
* older recomp-ui that lacks the fields. */
#define RECOMP_LAUNCHER_HAS_SCANLINES 1

// ---- host verification/inspection results (filled by the callbacks below) ----
// Plain-C structs so a host can implement the callbacks with zero launcher
// internal types. Mirror what the legacy launcher computed inline.
Expand Down Expand Up @@ -1390,6 +1404,11 @@ typedef struct RecompLauncherCGameInfo {
int (*persist_setup_discs)(void* ctx, const char* const* disc_paths,
int disc_count, const char* bios_path);

/* Display row for Settings.scanlines / scanline_strength_pct: a present-time
* scanline post-process (a checkbox plus a strength slider). Only meaningful
* for a console whose runtime implements it (PSX); everything else leaves
* this 0 and the rows are absent. Appended for ABI stability. */
int has_scanlines;
/* NDS input convenience setting. When set, Settings shows a Virtual Stylus
* opt-out and the Controller page may expose host-owned bindings for it. */
int has_virtual_stylus;
Expand Down