Skip to content

Commit 58d3e6c

Browse files
dc: live VMU LCD preview in options + dt-based screensaver + label rename
- VMU options: when the icon row is selected and the user scrolls L/R through the BIOS presets, the picked shape is pushed to the physical VMU's LCD in real time. B (cancel) reverts the LCD to the VMU's committed icon (custom ICONDATA if any, else the preset); A on any other row (commit) leaves the previewed shape in place since the staged icon_shape gets written to the VMU anyway. Removing a custom icon also pushes the now-active preset shape so the LCD matches the card's new state immediately. - Screensaver: motion was per-frame (x += dx) with dt ignored, so when the host frame rate climbed (e.g. Flycast without throttle) the logo flew across the screen. Switch to float position + pixel/sec velocity driven by dt in tick(), and convert the idle threshold to seconds. The original 2 px/frame at 60fps becomes a constant 120 px/s. - VMU options label: "Custom BIOS color:" -> "VMU Color:" with the value column still aligned to "Real Mode (3D BIOS):".
1 parent 0658c10 commit 58d3e6c

2 files changed

Lines changed: 72 additions & 31 deletions

File tree

dc/src/modes/browser.c

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,26 @@ static void push_icons_to_vmus(void)
579579
}
580580
}
581581

582+
/* Live LCD preview while the user navigates the icon-shape selector or
583+
* deletes a custom icon. Shape >= 124 falls back to our bundled icon. */
584+
static void push_preset_to_vmu_lcd(int port, int slot, uint8_t shape)
585+
{
586+
if (!jt_ports[port].slots[slot].has_lcd) return;
587+
const uint8_t *mono = (shape < 124) ? &bios_icons_mono[shape * 128]
588+
: fallback_vmu_icon_mono;
589+
jt_vmu_show_mono_bits(port, slot, mono);
590+
}
591+
592+
/* Push the VMU's committed icon (custom ICONDATA if any, else preset
593+
* shape) to its LCD. Used to undo the in-options live preview on cancel. */
594+
static void push_vmu_committed_to_lcd(const vmu_info_t *v)
595+
{
596+
if (!jt_ports[v->port].slots[v->slot].has_lcd) return;
597+
jt_icon_t icon;
598+
build_base_icon(&icon, v);
599+
jt_vmu_show_mono_bits(v->port, v->slot, icon.mono_bits);
600+
}
601+
582602
/* Begin "change/set custom icon": stash the editor base, commit staged
583603
* option edits (so they survive the mode switch), set the apply target,
584604
* and open the Icon Library to pick -- or, if empty, the editor seeded
@@ -753,7 +773,13 @@ static void update_save_delete_confirm(uint32_t edges)
753773

754774
static void update_options(uint32_t edges)
755775
{
756-
if (edges & CONT_B) { view = VIEW_VMUS; return; }
776+
if (edges & CONT_B) {
777+
/* Cancel: revert the LCD to the committed icon so any preview
778+
* pushed by the icon-shape selector goes away. */
779+
push_vmu_committed_to_lcd(&vmus[vmu_sel]);
780+
view = VIEW_VMUS;
781+
return;
782+
}
757783
if (edges & CONT_DPAD_UP) if (opt_sel > 0) opt_sel--;
758784
if (edges & CONT_DPAD_DOWN) if (opt_sel < OPT_COUNT - 1) opt_sel++;
759785

@@ -781,6 +807,11 @@ static void update_options(uint32_t edges)
781807
if (n < 0) n = 123; /* wrap through the 124 shapes */
782808
if (n > 123) n = 0;
783809
staged_icon_shape = (uint8_t)n;
810+
/* Live preview: push the picked shape onto the VMU's LCD
811+
* so the user can see it on the physical card. Reverted
812+
* on B (cancel); persisted on A-elsewhere (commit). */
813+
vmu_info_t *v = &vmus[vmu_sel];
814+
push_preset_to_vmu_lcd(v->port, v->slot, staged_icon_shape);
784815
break;
785816
}
786817
}
@@ -834,6 +865,8 @@ static void update_icon_actions(uint32_t edges)
834865
} else if (action == 1) { /* Remove */
835866
commit_staged_options();
836867
remove_custom_icon();
868+
/* Card is now on its preset shape -- mirror that to the LCD. */
869+
push_preset_to_vmu_lcd(v->port, v->slot, v->icon_shape);
837870
view = VIEW_OPTIONS;
838871
} else { /* Back */
839872
view = VIEW_OPTIONS;
@@ -1060,7 +1093,7 @@ static void draw_options(void)
10601093
int ly = row_y[OPT_CUSTOM_COLOR];
10611094
uint16_t fg = (opt_sel == OPT_CUSTOM_COLOR) ? JT_COL_YELLOW : JT_COL_WHITE;
10621095
jt_text(x + 12, ly, fg, JT_COL_BLACK,
1063-
"Custom BIOS color: %s", staged_custom_color ? "ON " : "off");
1096+
"VMU Color: %s", staged_custom_color ? "ON " : "off");
10641097
}
10651098

10661099
/* RGBA sliders. Bar = 16 cells x 14px = 224px wide. Each cell

dc/src/ui/screensaver.c

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,19 @@
2222
#include "gen_logo.h"
2323
#include "../ports/ports.h"
2424

25-
/* 30 seconds at 60 fps -- matches the PCE tester's threshold. */
26-
#define IDLE_FRAMES 1800
27-
28-
static int idle_counter = 0;
29-
static bool active = false;
30-
static int x, y, dx, dy;
31-
static int color_idx = 0;
25+
/* 30 seconds of idle before the screensaver kicks in. dt-based so the
26+
* threshold doesn't depend on framerate (was IDLE_FRAMES = 30 * 60). */
27+
#define IDLE_SECONDS 30.0f
28+
29+
static float idle_time = 0.0f;
30+
static bool active = false;
31+
/* Position + velocity are dt-based: x/y in pixels (float so subpixel
32+
* accumulation doesn't drop frames at high fps), vx/vy in pixels/sec.
33+
* 120 px/s == the original 2 px/frame at 60 fps, but now constant regardless
34+
* of the actual frame rate (which can spike on Flycast without throttle
35+
* and was making the logo fly across the screen). */
36+
static float x, y, vx, vy;
37+
static int color_idx = 0;
3238
static int last_x = -1000;
3339
static int last_y = -1000;
3440
/* Pending-wake flag: set the single frame we deactivate, consumed by
@@ -49,13 +55,13 @@ static const uint16_t cycle[7] = {
4955

5056
void jt_screensaver_init(void)
5157
{
52-
idle_counter = 0;
58+
idle_time = 0.0f;
5359
active = false;
5460
color_idx = 0;
55-
/* Start in the upper-left quadrant with a velocity that puts the
56-
* logo on a diagonal trajectory at ~2 px/frame. */
57-
x = 64; y = 80;
58-
dx = 2; dy = 2;
61+
/* Upper-left start; diagonal at 120 px/s (matches the previous
62+
* 2 px/frame at 60 fps). */
63+
x = 64.0f; y = 80.0f;
64+
vx = 120.0f; vy = 120.0f;
5965
last_x = -1000;
6066
last_y = -1000;
6167
}
@@ -116,38 +122,40 @@ static void blit_logo(int px, int py, uint16_t color)
116122

117123
void jt_screensaver_tick(float dt)
118124
{
119-
(void)dt;
120125
bool input = any_user_input();
121126

122127
if (input) {
123128
if (active) {
124129
active = false;
125-
idle_counter = 0;
130+
idle_time = 0.0f;
126131
wake_pending = true;
127132
}
128-
idle_counter = 0;
133+
idle_time = 0.0f;
129134
return;
130135
}
131136

132-
idle_counter++;
133-
if (!active && idle_counter >= IDLE_FRAMES) {
137+
idle_time += dt;
138+
if (!active && idle_time >= IDLE_SECONDS) {
134139
active = true;
135140
}
141+
142+
/* Step + bounce in tick so motion is dt-based: at any frame rate the
143+
* logo moves at vx/vy pixels per second instead of vx/vy per frame.
144+
* Each wall hit flips the relevant component and advances the cycle
145+
* index. The back buffer is cleared every frame by main.c, so the
146+
* draw side just blits at the current position. */
147+
if (active) {
148+
x += vx * dt;
149+
y += vy * dt;
150+
if (x < 0) { x = 0; vx = -vx; color_idx = (color_idx + 1) % 7; }
151+
if (x + LOGO_W > 640) { x = 640 - LOGO_W; vx = -vx; color_idx = (color_idx + 1) % 7; }
152+
if (y < 0) { y = 0; vy = -vy; color_idx = (color_idx + 1) % 7; }
153+
if (y + LOGO_H > 480) { y = 480 - LOGO_H; vy = -vy; color_idx = (color_idx + 1) % 7; }
154+
}
136155
}
137156

138157
void jt_screensaver_draw(void)
139158
{
140159
if (!active) return;
141-
142-
/* Step + bounce. Each wall hit flips the relevant component and
143-
* advances the cycle index. The back buffer is cleared every frame
144-
* by main.c, so we just draw the logo at its new position. */
145-
x += dx;
146-
y += dy;
147-
if (x < 0) { x = 0; dx = -dx; color_idx = (color_idx + 1) % 7; }
148-
if (x + LOGO_W > 640) { x = 640 - LOGO_W; dx = -dx; color_idx = (color_idx + 1) % 7; }
149-
if (y < 0) { y = 0; dy = -dy; color_idx = (color_idx + 1) % 7; }
150-
if (y + LOGO_H > 480) { y = 480 - LOGO_H; dy = -dy; color_idx = (color_idx + 1) % 7; }
151-
152-
blit_logo(x, y, cycle[color_idx]);
160+
blit_logo((int)x, (int)y, cycle[color_idx]);
153161
}

0 commit comments

Comments
 (0)