@@ -68,8 +68,10 @@ uint16_t alt_launcher_fb_terminal_key(uint32_t mask, bool osd_button)
6868static pid_t s_pid = 0 ;
6969static int s_crash_count = 0 ;
7070static unsigned long s_respawn_timer = 0 ;
71+ static unsigned long s_tty_deadline = 0 ;
7172static unsigned long s_native_status_timer = 0 ;
7273static unsigned long s_native_fb_mode_timer = 0 ;
74+ static unsigned long s_native_crt_finish_timer = 0 ;
7375static bool s_gave_up = false ;
7476static bool s_init_pending = false ;
7577static bool s_native_crt = false ;
@@ -228,21 +230,29 @@ static void disable_native_crt_path(void)
228230 video_fb_enable (0 );
229231 set_vga_fb (0 );
230232 set_launcher_fb_mode (8888 , 1 , 960 , 720 , 3840 );
233+ s_tty_deadline = 0 ;
231234 s_native_status_timer = 0 ;
232235 s_native_fb_mode_timer = 0 ;
236+ s_native_crt_finish_timer = 0 ;
233237}
234238
235- static void enable_native_crt_path (void )
239+ static void prepare_native_crt_path (void )
236240{
237241 set_vga_fb (0 );
238242 video_fb_enable (0 );
239243
240- // Double-write with a settle window so the kernel module's 320x240 layout
241- // is live before status[9] flips. Without this, the frontend renders for
242- // up to a second under stale dims (the post-fork retry timer used to be
243- // what eventually fixed the picture).
244244 set_native_crt_fb_mode (false );
245- usleep (100000 );
245+ s_native_crt_finish_timer = GetTimer (100 );
246+ if (!s_native_crt_finish_timer) s_native_crt_finish_timer = 1 ;
247+ }
248+
249+ static void finish_native_crt_path (void )
250+ {
251+ // Double-write with a settle window so the kernel module's 320x240 layout
252+ // is live before status[9] flips. The child is already execing/loading,
253+ // but the FPGA keeps scanning the stock path until the native buffer is
254+ // blanked below.
255+ s_native_crt_finish_timer = 0 ;
246256 set_native_crt_fb_mode ();
247257
248258 blank_native_crt_fb ();
@@ -254,16 +264,6 @@ static void enable_native_crt_path(void)
254264 if (!s_native_fb_mode_timer) s_native_fb_mode_timer = 1 ;
255265}
256266
257- static void wait_launcher_tty_ready (pid_t pid)
258- {
259- for (int i = 0 ; i < 100 ; i++)
260- {
261- if (launcher_tty_ready (pid))
262- return ;
263- usleep (10000 );
264- }
265- }
266-
267267static void return_to_normal_mode (void )
268268{
269269 user_io_osd_key_enable (1 );
@@ -282,6 +282,10 @@ static void reset_launcher_state(void)
282282{
283283 s_pid = 0 ;
284284 s_respawn_timer = 0 ;
285+ s_tty_deadline = 0 ;
286+ s_native_status_timer = 0 ;
287+ s_native_fb_mode_timer = 0 ;
288+ s_native_crt_finish_timer = 0 ;
285289 s_crash_count = 0 ;
286290 s_gave_up = false ;
287291 s_init_pending = false ;
@@ -337,34 +341,71 @@ static void release_launcher_video(void)
337341 }
338342}
339343
344+ static void exec_launcher_child (const char *path)
345+ {
346+ setenv (" LC_ALL" , " en_US.UTF-8" , 1 );
347+ setenv (" HOME" , " /root" , 1 );
348+
349+ cpu_set_t set;
350+ CPU_ZERO (&set);
351+ CPU_SET (0 , &set);
352+ sched_setaffinity (0 , sizeof (set), &set);
353+
354+ setsid ();
355+
356+ int tty_fd = open (s_tty_path, O_RDWR );
357+ if (tty_fd >= 0 )
358+ {
359+ ioctl (tty_fd, TIOCSCTTY , 0 );
360+ dup2 (tty_fd, STDIN_FILENO );
361+ dup2 (tty_fd, STDOUT_FILENO );
362+ dup2 (tty_fd, STDERR_FILENO );
363+ if (tty_fd > STDERR_FILENO )
364+ close (tty_fd);
365+ }
366+
367+ static const char clear[] = " \033 [0m\033 [?25l\033 [37m\033 [40m\033 [2J\033 [H" ;
368+ if (write (STDOUT_FILENO , clear, sizeof (clear) - 1 ) < 0 ) {}
369+
370+ if (s_native_crt)
371+ execl (path, path, " --crt" , NULL );
372+ else
373+ execl (path, path, NULL );
374+ _exit (1 );
375+ }
376+
377+ static void finalize_spawn (void )
378+ {
379+ s_tty_deadline = 0 ;
380+ video_chvt (s_vt);
381+ if (!s_native_crt)
382+ video_fb_enable (1 );
383+ else
384+ {
385+ input_switch (0 );
386+ user_io_status_set (" [9]" , 1 );
387+ }
388+
389+ // The frontend grabs input as soon as it starts. If the OSD is still
390+ // up (e.g. user toggled CRT mode or hit Reboot from System Settings),
391+ // it would trap input with no way to dismiss it — drop it now.
392+ if (menu_present ()) MenuHide ();
393+ }
394+
340395static void spawn (void )
341396{
342397 char path[2100 ];
343398 strncpy (path, getFullPath (s_launcher_path), sizeof (path) - 1 );
344399 path[sizeof (path) - 1 ] = ' \0 ' ;
345400
346- static const char cmd[] =
347- " #!/bin/bash\n "
348- " export LC_ALL=en_US.UTF-8\n "
349- " export HOME=/root\n "
350- " printf '\\ 033[0m\\ 033[?25l\\ 033[37m\\ 033[40m\\ 033[2J\\ 033[H'\n "
351- " if [ \" $ALT_LAUNCHER_CRT\" = \" 1\" ]; then\n "
352- " exec \" $ALT_LAUNCHER_PATH\" --crt\n "
353- " fi\n "
354- " exec \" $ALT_LAUNCHER_PATH\"\n " ;
355-
356- unlink (" /tmp/alt_launcher" );
357- if (!FileSave (" /tmp/alt_launcher" , (void *)cmd, strlen (cmd)))
358- return ;
359-
360401 user_io_osd_key_enable (0 );
361402 clear_launcher_tty ();
362403
363404 printf (" alt_launcher: native_crt=%d\n " , s_native_crt);
364405 if (s_native_crt)
365406 {
366- enable_native_crt_path ();
367- printf (" alt_launcher: native CRT path enabled \n " );
407+ prepare_native_crt_path ();
408+ printf (" alt_launcher: native CRT path prepared \n " );
368409 }
369410 else
370411 {
@@ -384,39 +425,23 @@ static void spawn(void)
384425 printf (" alt_launcher: spawned pid=%d path=%s\n " , s_pid, path);
385426 if (!s_pid)
386427 {
387- setenv (" ALT_LAUNCHER_PATH" , path, 1 );
388- setenv (" ALT_LAUNCHER_CRT" , s_native_crt ? " 1" : " 0" , 1 );
389- cpu_set_t set;
390- CPU_ZERO (&set);
391- CPU_SET (0 , &set);
392- sched_setaffinity (0 , sizeof (set), &set);
393- setsid ();
394- execl (" /sbin/agetty" , " /sbin/agetty" , " -a" , " root" , " -l" ,
395- " /tmp/alt_launcher" , " -i" , " --nohostname" , " -L" , s_tty, " linux" , NULL );
396- _exit (1 );
428+ exec_launcher_child (path);
397429 }
398430
399- wait_launcher_tty_ready (s_pid);
400- video_chvt (s_vt);
401- if (!s_native_crt)
402- video_fb_enable (1 );
403- else
404- {
405- input_switch (0 );
406- user_io_status_set (" [9]" , 1 );
407- }
408-
409- // The frontend grabs input as soon as it starts. If the OSD is still
410- // up (e.g. user toggled CRT mode or hit Reboot from System Settings),
411- // it would trap input with no way to dismiss it — drop it now.
412- if (menu_present ()) MenuHide ();
431+ s_tty_deadline = GetTimer (1000 );
432+ if (!s_tty_deadline) s_tty_deadline = 1 ;
413433}
414434
415435bool alt_launcher_active (void )
416436{
417437 return s_pid != 0 ;
418438}
419439
440+ bool alt_launcher_scheduler_sleep_enabled (void )
441+ {
442+ return s_pid || s_init_pending || s_respawn_timer || s_tty_deadline || s_native_crt_finish_timer;
443+ }
444+
420445bool alt_launcher_native_crt (void )
421446{
422447 return s_native_crt && s_pid != 0 ;
@@ -469,6 +494,7 @@ void alt_launcher_init(bool native_crt)
469494 return ;
470495 s_crash_count = 0 ;
471496 s_respawn_timer = 0 ;
497+ s_tty_deadline = 0 ;
472498 s_native_crt = native_crt;
473499 s_init_pending = true ;
474500}
@@ -486,6 +512,7 @@ void alt_launcher_prepare_for_script(void)
486512 wait_launcher_stopped (pid);
487513 user_io_osd_key_enable (1 );
488514 s_respawn_timer = 0 ;
515+ s_tty_deadline = 0 ;
489516 s_crash_count = 0 ;
490517 s_init_pending = false ;
491518 s_gave_up = false ;
@@ -514,6 +541,12 @@ void alt_launcher_poll(void)
514541{
515542 if (s_pid)
516543 {
544+ if (s_native_crt && s_native_crt_finish_timer && CheckTimer (s_native_crt_finish_timer))
545+ {
546+ finish_native_crt_path ();
547+ printf (" alt_launcher: native CRT path enabled\n " );
548+ }
549+
517550 if (s_native_crt && s_native_status_timer && CheckTimer (s_native_status_timer))
518551 {
519552 user_io_status_set (" [9]" , 1 );
@@ -531,6 +564,7 @@ void alt_launcher_poll(void)
531564 if (waitpid (s_pid, &status, WNOHANG ) == s_pid)
532565 {
533566 s_pid = 0 ;
567+ s_tty_deadline = 0 ;
534568 user_io_osd_key_enable (1 );
535569 bool exited = WIFEXITED (status);
536570 int exit_status = exited ? WEXITSTATUS (status) : 0 ;
@@ -565,7 +599,11 @@ void alt_launcher_poll(void)
565599 s_crash_count = 0 ;
566600 s_respawn_timer = GetTimer (1000 );
567601 if (!s_respawn_timer) s_respawn_timer = 1 ;
602+ return ;
568603 }
604+
605+ if (s_tty_deadline && !s_native_crt_finish_timer && (launcher_tty_ready (s_pid) || CheckTimer (s_tty_deadline)))
606+ finalize_spawn ();
569607 return ;
570608 }
571609
0 commit comments