@@ -70,7 +70,7 @@ static int s_crash_count = 0;
7070static unsigned long s_respawn_timer = 0 ;
7171static unsigned long s_tty_deadline = 0 ;
7272static unsigned long s_native_status_timer = 0 ;
73- static unsigned long s_native_fb_mode_timer = 0 ;
73+ static unsigned long s_native_crt_finish_timer = 0 ;
7474static bool s_gave_up = false ;
7575static bool s_init_pending = false ;
7676static bool s_native_crt = false ;
@@ -82,6 +82,8 @@ static const char s_tty_path[] = "/dev/tty2";
8282static const char s_fb_mode_path[] = " /sys/module/MiSTer_fb/parameters/mode" ;
8383static const char s_crt_state_file[] = " zaparoo_launcher_crt.bin" ;
8484static const char s_offsets_file[] = " zaparoo_video_offsets.bin" ;
85+ static char s_saved_fb_mode[64 ];
86+ static bool s_saved_fb_mode_valid = false ;
8587
8688static int8_t s_h_offset = 0 ;
8789static int8_t s_v_offset = 0 ;
@@ -135,6 +137,50 @@ static void set_launcher_fb_mode(int fmt, int rb, int width, int height, int str
135137 printf (" alt_launcher: fb mode set to %dx%d fmt=%d stride=%d\n " , width, height, fmt, stride);
136138}
137139
140+ static void save_current_fb_mode (void )
141+ {
142+ if (s_saved_fb_mode_valid)
143+ return ;
144+
145+ FILE *fp = fopen (s_fb_mode_path, " rt" );
146+ if (!fp)
147+ {
148+ printf (" alt_launcher: unable to read fb mode: %s\n " , strerror (errno));
149+ return ;
150+ }
151+
152+ if (fgets (s_saved_fb_mode, sizeof (s_saved_fb_mode), fp))
153+ {
154+ size_t len = strlen (s_saved_fb_mode);
155+ while (len && (s_saved_fb_mode[len - 1 ] == ' \n ' || s_saved_fb_mode[len - 1 ] == ' \r ' ))
156+ s_saved_fb_mode[--len] = 0 ;
157+ s_saved_fb_mode_valid = len != 0 ;
158+ if (s_saved_fb_mode_valid)
159+ printf (" alt_launcher: saved fb mode '%s'\n " , s_saved_fb_mode);
160+ }
161+ fclose (fp);
162+ }
163+
164+ static void restore_saved_fb_mode (void )
165+ {
166+ if (!s_saved_fb_mode_valid)
167+ {
168+ set_launcher_fb_mode (8888 , 1 , 960 , 720 , 3840 );
169+ return ;
170+ }
171+
172+ FILE *fp = fopen (s_fb_mode_path, " wt" );
173+ if (!fp)
174+ {
175+ printf (" alt_launcher: unable to restore fb mode: %s\n " , strerror (errno));
176+ return ;
177+ }
178+
179+ fprintf (fp, " %s\n " , s_saved_fb_mode);
180+ fclose (fp);
181+ printf (" alt_launcher: restored fb mode '%s'\n " , s_saved_fb_mode);
182+ }
183+
138184static void set_native_crt_fb_mode (bool log = true )
139185{
140186 set_launcher_fb_mode (8888 , 1 , 320 , 240 , 1280 , log);
@@ -228,31 +274,34 @@ static void disable_native_crt_path(void)
228274 user_io_status_set (" [9]" , 0 );
229275 video_fb_enable (0 );
230276 set_vga_fb (0 );
231- set_launcher_fb_mode (8888 , 1 , 960 , 720 , 3840 );
277+ restore_saved_fb_mode ();
278+ s_tty_deadline = 0 ;
232279 s_native_status_timer = 0 ;
233- s_native_fb_mode_timer = 0 ;
280+ s_native_crt_finish_timer = 0 ;
234281}
235282
236- static void enable_native_crt_path (void )
283+ static void prepare_native_crt_path (void )
237284{
238285 set_vga_fb (0 );
239286 video_fb_enable (0 );
240-
241- // Double-write with a settle window so the kernel module's 320x240 layout
242- // is live before status[9] flips. Without this, the frontend renders for
243- // up to a second under stale dims (the post-fork retry timer used to be
244- // what eventually fixed the picture).
287+ save_current_fb_mode ();
245288 set_native_crt_fb_mode (false );
246- usleep (100000 );
247- set_native_crt_fb_mode ();
289+ s_native_crt_finish_timer = GetTimer (1 );
290+ if (!s_native_crt_finish_timer) s_native_crt_finish_timer = 1 ;
291+ }
292+
293+ static void finish_native_crt_path (void )
294+ {
295+ // The frontend repeats the 320x240 linuxfb `vmode` while it starts. This
296+ // side does not rewrite the mode again; it only blanks the native DDR
297+ // scan-out buffer before status[9] routes the FPGA to it.
298+ s_native_crt_finish_timer = 0 ;
248299
249300 blank_native_crt_fb ();
250301
251302 user_io_status_set (" [9]" , 1 );
252303 s_native_status_timer = GetTimer (500 );
253304 if (!s_native_status_timer) s_native_status_timer = 1 ;
254- s_native_fb_mode_timer = GetTimer (1000 );
255- if (!s_native_fb_mode_timer) s_native_fb_mode_timer = 1 ;
256305}
257306
258307static void return_to_normal_mode (void )
@@ -274,6 +323,8 @@ static void reset_launcher_state(void)
274323 s_pid = 0 ;
275324 s_respawn_timer = 0 ;
276325 s_tty_deadline = 0 ;
326+ s_native_status_timer = 0 ;
327+ s_native_crt_finish_timer = 0 ;
277328 s_crash_count = 0 ;
278329 s_gave_up = false ;
279330 s_init_pending = false ;
@@ -392,8 +443,8 @@ static void spawn(void)
392443 printf (" alt_launcher: native_crt=%d\n " , s_native_crt);
393444 if (s_native_crt)
394445 {
395- enable_native_crt_path ();
396- printf (" alt_launcher: native CRT path enabled \n " );
446+ prepare_native_crt_path ();
447+ printf (" alt_launcher: native CRT path prepared \n " );
397448 }
398449 else
399450 {
@@ -427,7 +478,7 @@ bool alt_launcher_active(void)
427478
428479bool alt_launcher_scheduler_sleep_enabled (void )
429480{
430- return s_pid || s_init_pending || s_respawn_timer || s_tty_deadline;
481+ return s_pid || s_init_pending || s_respawn_timer || s_tty_deadline || s_native_crt_finish_timer ;
431482}
432483
433484bool alt_launcher_native_crt (void )
@@ -529,19 +580,19 @@ void alt_launcher_poll(void)
529580{
530581 if (s_pid)
531582 {
583+ if (s_native_crt && s_native_crt_finish_timer && CheckTimer (s_native_crt_finish_timer))
584+ {
585+ finish_native_crt_path ();
586+ printf (" alt_launcher: native CRT path enabled\n " );
587+ }
588+
532589 if (s_native_crt && s_native_status_timer && CheckTimer (s_native_status_timer))
533590 {
534591 user_io_status_set (" [9]" , 1 );
535592 s_native_status_timer = GetTimer (500 );
536593 if (!s_native_status_timer) s_native_status_timer = 1 ;
537594 }
538595
539- if (s_native_crt && s_native_fb_mode_timer && CheckTimer (s_native_fb_mode_timer))
540- {
541- set_native_crt_fb_mode ();
542- s_native_fb_mode_timer = 0 ;
543- }
544-
545596 int status;
546597 if (waitpid (s_pid, &status, WNOHANG ) == s_pid)
547598 {
@@ -584,7 +635,7 @@ void alt_launcher_poll(void)
584635 return ;
585636 }
586637
587- if (s_tty_deadline && (launcher_tty_ready (s_pid) || CheckTimer (s_tty_deadline)))
638+ if (s_tty_deadline && !s_native_crt_finish_timer && (launcher_tty_ready (s_pid) || CheckTimer (s_tty_deadline)))
588639 finalize_spawn ();
589640 return ;
590641 }
0 commit comments