This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git


The following commit(s) were added to refs/heads/master by this push:
     new 922cf5979 games/NXDoom: support RGB565 and loadable modules
922cf5979 is described below

commit 922cf59799f274b620b60778fb10913668838b51
Author: aviralgarg05 <[email protected]>
AuthorDate: Sun Aug 16 21:02:53 2026 +0530

    games/NXDoom: support RGB565 and loadable modules
    
    Add RGB565 framebuffer output and module builds. Harden configuration 
parsing and renderer bounds, support supervised SIGTERM shutdown, and notify 
framebuffer drivers after drawing.
    
    Assisted-by: Codex:gpt-5
    Signed-off-by: aviralgarg05 <[email protected]>
---
 games/NXDoom/Kconfig             |   9 +-
 games/NXDoom/src/d_iwad.c        |   9 +-
 games/NXDoom/src/doom/d_main.c   | 340 ++++++++++++++++++++++++++-------------
 games/NXDoom/src/doom/r_draw.c   | 116 ++++++++++---
 games/NXDoom/src/doom/r_main.c   | 134 +++++++++++----
 games/NXDoom/src/doom/r_plane.c  | 103 +++++++++---
 games/NXDoom/src/doom/statdump.c |  32 ++--
 games/NXDoom/src/i_main.c        |   2 +
 games/NXDoom/src/i_system.c      | 107 ++++++++++--
 games/NXDoom/src/i_system.h      |  20 +++
 games/NXDoom/src/i_video.c       |  64 ++++++--
 11 files changed, 706 insertions(+), 230 deletions(-)

diff --git a/games/NXDoom/Kconfig b/games/NXDoom/Kconfig
index a95d0a19f..6f716217d 100644
--- a/games/NXDoom/Kconfig
+++ b/games/NXDoom/Kconfig
@@ -4,7 +4,7 @@
 #
 
 config GAMES_NXDOOM
-       bool "NXDoom"
+       tristate "NXDoom"
        default n
        depends on ALLOW_GPL_COMPONENTS
        depends on VIDEO_FB
@@ -252,6 +252,13 @@ config GAMES_NXDOOM_MAXDRAWSEGS
                memory, so you may reduce the number. However, too few will 
cause
                rendering issues (overflow is checked to avoid crashes).
 
+config GAMES_NXDOOM_STATDUMP_MAX_CAPTURES
+       int "Maximum statdump capture buffer entries"
+       default 32
+       range 1 1024
+       ---help---
+               Number of diagnostic playtime-statistics capture slots.
+
 config GAMES_NXDOOM_RANGECHECK
        bool "Perform range checks"
        default y
diff --git a/games/NXDoom/src/d_iwad.c b/games/NXDoom/src/d_iwad.c
index a6f1cd945..62dbf2b6b 100644
--- a/games/NXDoom/src/d_iwad.c
+++ b/games/NXDoom/src/d_iwad.c
@@ -194,7 +194,10 @@ static gamemission_t identify_iwad_by_name(const char 
*name, int mask)
        * Only use supported missions:
        */
 
-      if (((1 << g_iwads[i].mission) & mask) == 0) continue;
+      if (((1 << g_iwads[i].mission) & mask) == 0)
+        {
+          continue;
+        }
 
       /* Check if it ends in this IWAD name. */
 
@@ -271,6 +274,10 @@ static void buld_iwad_dir_list(void)
 
   add_iwad_dir(m_dir_name(myargv[0]));
 
+  /* Add the configured DOOM data directory */
+
+  add_iwad_dir(CONFIG_GAMES_NXDOOM_PREFDIR);
+
   /* Add DOOMWADDIR if it is in the environment */
 
   env = getenv("DOOMWADDIR");
diff --git a/games/NXDoom/src/doom/d_main.c b/games/NXDoom/src/doom/d_main.c
index 52df6eda1..153ad957d 100644
--- a/games/NXDoom/src/doom/d_main.c
+++ b/games/NXDoom/src/doom/d_main.c
@@ -598,43 +598,50 @@ static boolean d_display(void)
 
   switch (gamestate)
     {
-    case GS_LEVEL:
-
-      if (!gametic)
+      case GS_LEVEL:
         {
+          if (!gametic)
+            {
+              break;
+            }
+
+          if (automapactive)
+            {
+              am_drawer();
+            }
+
+          if (wipe || (viewheight != SCREENHEIGHT && d_fullscreen))
+            {
+              redrawsbar = true;
+            }
+
+          if (inhelpscreensstate && !inhelpscreens)
+            {
+              redrawsbar = true; /* just put away the help screen */
+            }
+
+          st_drawer(viewheight == SCREENHEIGHT, redrawsbar);
+          d_fullscreen = viewheight == SCREENHEIGHT;
           break;
         }
 
-      if (automapactive)
+      case GS_INTERMISSION:
         {
-          am_drawer();
+          wi_drawer();
+          break;
         }
 
-      if (wipe || (viewheight != SCREENHEIGHT && d_fullscreen))
+      case GS_FINALE:
         {
-          redrawsbar = true;
+          f_drawer();
+          break;
         }
 
-      if (inhelpscreensstate && !inhelpscreens)
+      case GS_DEMOSCREEN:
         {
-          redrawsbar = true; /* just put away the help screen */
+          d_page_drawer();
+          break;
         }
-
-      st_drawer(viewheight == SCREENHEIGHT, redrawsbar);
-      d_fullscreen = viewheight == SCREENHEIGHT;
-      break;
-
-    case GS_INTERMISSION:
-      wi_drawer();
-      break;
-
-    case GS_FINALE:
-      f_drawer();
-      break;
-
-    case GS_DEMOSCREEN:
-      d_page_drawer();
-      break;
     }
 
   /* draw buffered stuff to screen */
@@ -656,7 +663,9 @@ static boolean d_display(void)
   /* clean up border stuff */
 
   if (gamestate != oldgamestate && gamestate != GS_LEVEL)
-    i_set_palette(w_cache_lump_name(("PLAYPAL"), PU_CACHE));
+    {
+      i_set_palette(w_cache_lump_name(("PLAYPAL"), PU_CACHE));
+    }
 
   /* see if the border needs to be initially drawn */
 
@@ -672,7 +681,10 @@ static boolean d_display(void)
       scaledviewwidth != SCREENWIDTH)
     {
       if (g_menuactive || g_menuactivestate || !viewactivestate)
-        borderdrawcount = 3;
+        {
+          borderdrawcount = 3;
+        }
+
       if (borderdrawcount)
         {
           r_draw_view_border(); /* erase old menu stuff */
@@ -697,11 +709,16 @@ static boolean d_display(void)
   if (paused)
     {
       if (automapactive)
-        y = 4;
+        {
+          y = 4;
+        }
       else
-        y = viewwindowy + 4;
+        {
+          y = viewwindowy + 4;
+        }
+
       v_draw_patch_direct(viewwindowx + (scaledviewwidth - 68) / 2, y,
-                          w_cache_lump_name(("M_PAUSE"), PU_CACHE));
+        w_cache_lump_name(("M_PAUSE"), PU_CACHE));
     }
 
   /* menus go directly to the screen */
@@ -725,12 +742,18 @@ static boolean d_grab_mouse_callback(void)
   /* Drone players don't need mouse focus */
 
 #ifdef CONFIG_GAMES_NXDOOM_NET
-  if (drone) return false;
+  if (drone)
+    {
+      return false;
+    }
 #endif
 
   /* when menu is active or game is paused, release the mouse */
 
-  if (g_menuactive || paused) return false;
+  if (g_menuactive || paused)
+    {
+      return false;
+    }
 
   /* only grab mouse when playing levels (but not demos) */
 
@@ -1144,28 +1167,45 @@ static void init_game_version(void)
                   status = true;
                   switch (demoversion)
                     {
-                    case 0:
-                    case 1:
-                    case 2:
-                    case 3:
-                    case 4:
-                      gameversion = exe_doom_1_2;
-                      break;
-                    case 106:
-                      gameversion = exe_doom_1_666;
-                      break;
-                    case 107:
-                      gameversion = exe_doom_1_7;
-                      break;
-                    case 108:
-                      gameversion = exe_doom_1_8;
-                      break;
-                    case 109:
-                      gameversion = exe_doom_1_9;
-                      break;
-                    default:
-                      status = false;
-                      break;
+                      case 0:
+                      case 1:
+                      case 2:
+                      case 3:
+                      case 4:
+                        {
+                          gameversion = exe_doom_1_2;
+                          break;
+                        }
+
+                      case 106:
+                        {
+                          gameversion = exe_doom_1_666;
+                          break;
+                        }
+
+                      case 107:
+                        {
+                          gameversion = exe_doom_1_7;
+                          break;
+                        }
+
+                      case 108:
+                        {
+                          gameversion = exe_doom_1_8;
+                          break;
+                        }
+
+                      case 109:
+                        {
+                          gameversion = exe_doom_1_9;
+                          break;
+                        }
+
+                      default:
+                        {
+                          status = false;
+                          break;
+                        }
                     }
 
                   if (status)
@@ -1245,11 +1285,18 @@ void d_process_events(void)
 
   /* IF STORE DEMO, DO NOT ACCEPT INPUT */
 
-  if (storedemo) return;
+  if (storedemo)
+    {
+      return;
+    }
 
   while ((ev = d_pop_event()) != NULL)
     {
-      if (m_responder(ev)) continue; /* menu ate the event */
+      if (m_responder(ev))
+        {
+          continue;                  /* menu ate the event */
+        }
+
       g_responder(ev);
     }
 }
@@ -1294,6 +1341,7 @@ void d_doomloop(void)
 
   while (1)
     {
+      i_poll_quit_signal();
       d_run_frame();
     }
 }
@@ -1304,7 +1352,10 @@ void d_doomloop(void)
 
 void d_page_ticker(void)
 {
-  if (--pagetic < 0) d_advance_demo();
+  if (--pagetic < 0)
+    {
+      d_advance_demo();
+    }
 }
 
 /****************************************************************************
@@ -1357,72 +1408,104 @@ void d_do_advance_demo(void)
    */
 
   if (gameversion == exe_ultimate || gameversion == exe_final)
-    demosequence = (demosequence + 1) % 7;
+    {
+      demosequence = (demosequence + 1) % 7;
+    }
   else
-    demosequence = (demosequence + 1) % 6;
+    {
+      demosequence = (demosequence + 1) % 6;
+    }
 
   switch (demosequence)
     {
-    case 0:
-      if (gamemode == commercial)
-        pagetic = TICRATE * 11;
-      else
-        pagetic = 170;
-      gamestate = GS_DEMOSCREEN;
-      pagename = ("TITLEPIC");
+      case 0:
+        {
+          if (gamemode == commercial)
+            {
+              pagetic = TICRATE * 11;
+            }
+          else
+            {
+              pagetic = 170;
+            }
+
+          gamestate = GS_DEMOSCREEN;
+          pagename = ("TITLEPIC");
 
 #ifdef CONFIG_GAMES_NXDOOM_SOUND
-      if (gamemode == commercial)
+          if (gamemode == commercial)
+            {
+              s_start_music(MUS_DM2TTL);
+            }
+          else
+            {
+              s_start_music(MUS_INTRO);
+            }
+#endif
+
+          break;
+        }
+
+      case 1:
         {
-          s_start_music(MUS_DM2TTL);
+          g_defered_play_demo(("demo1"));
+          break;
         }
-      else
+
+      case 2:
         {
-          s_start_music(MUS_INTRO);
+          pagetic = 200;
+          gamestate = GS_DEMOSCREEN;
+          pagename = ("CREDIT");
+          break;
         }
-#endif
 
-      break;
-    case 1:
-      g_defered_play_demo(("demo1"));
-      break;
-    case 2:
-      pagetic = 200;
-      gamestate = GS_DEMOSCREEN;
-      pagename = ("CREDIT");
-      break;
-    case 3:
-      g_defered_play_demo(("demo2"));
-      break;
-    case 4:
-      gamestate = GS_DEMOSCREEN;
-      if (gamemode == commercial)
+      case 3:
         {
-          pagetic = TICRATE * 11;
-          pagename = ("TITLEPIC");
+          g_defered_play_demo(("demo2"));
+          break;
+        }
+
+      case 4:
+        {
+          gamestate = GS_DEMOSCREEN;
+          if (gamemode == commercial)
+            {
+              pagetic = TICRATE * 11;
+              pagename = ("TITLEPIC");
 #ifdef CONFIG_GAMES_NXDOOM_SOUND
-          s_start_music(MUS_DM2TTL);
+              s_start_music(MUS_DM2TTL);
 #endif
+            }
+          else
+            {
+              pagetic = 200;
+
+              if (gameversion >= exe_ultimate)
+                {
+                  pagename = ("CREDIT");
+                }
+              else
+                {
+                  pagename = ("HELP2");
+                }
+            }
+          break;
         }
-      else
-        {
-          pagetic = 200;
 
-          if (gameversion >= exe_ultimate)
-            pagename = ("CREDIT");
-          else
-            pagename = ("HELP2");
+      case 5:
+        {
+          g_defered_play_demo(("demo3"));
+          break;
         }
-      break;
-    case 5:
-      g_defered_play_demo(("demo3"));
-      break;
 
       /* THE DEFINITIVE DOOM Special Edition demo */
 
-    case 6:
-      g_defered_play_demo(("demo4"));
-      break;
+      case 6:
+        {
+          g_defered_play_demo(("demo4"));
+          break;
+        }
     }
 
   /* The Doom 3: BFG Edition version of doom2.wad does not have a
@@ -1565,7 +1648,10 @@ void d_doom_main(void)
    *
    */
 
-  if (m_check_parm("-deathmatch")) deathmatch = 1;
+  if (m_check_parm("-deathmatch"))
+    {
+      deathmatch = 1;
+    }
 
   /* @category net
    * @vanilla
@@ -1575,7 +1661,10 @@ void d_doom_main(void)
    *
    */
 
-  if (m_check_parm("-altdeath")) deathmatch = 2;
+  if (m_check_parm("-altdeath"))
+    {
+      deathmatch = 2;
+    }
 
   if (devparm)
     {
@@ -1601,9 +1690,21 @@ void d_doom_main(void)
     {
       int scale = 200;
 
-      if (p < myargc - 1) scale = atoi(myargv[p + 1]);
-      if (scale < 10) scale = 10;
-      if (scale > 400) scale = 400;
+      if (p < myargc - 1)
+        {
+          scale = atoi(myargv[p + 1]);
+        }
+
+      if (scale < 10)
+        {
+          scale = 10;
+        }
+
+      if (scale > 400)
+        {
+          scale = 400;
+        }
+
       printf("turbo scale: %i%%\n", scale);
       forwardmove[0] = forwardmove[0] * scale / 100;
       forwardmove[1] = forwardmove[1] * scale / 100;
@@ -1815,6 +1916,7 @@ void d_doom_main(void)
   if (p)
     {
       char *uc_filename = strdup(myargv[p + 1]);
+
       m_force_uppercase(uc_filename);
 
       /* With Vanilla you have to specify the file without extension,
@@ -1906,8 +2008,10 @@ void d_doom_main(void)
       int i;
 
       if (gamemode == shareware)
-        i_error(("\nYou cannot -file with the shareware "
-                 "version. Register!"));
+        {
+          i_error(("\nYou cannot -file with the shareware "
+                   "version. Register!"));
+        }
 
       /* Check for fake IWAD with right name,
        * but w/o all the lumps of the registered version.
@@ -2041,7 +2145,9 @@ void d_doom_main(void)
   if (p)
     {
       if (gamemode == commercial)
-        startmap = atoi(myargv[p + 1]);
+        {
+          startmap = atoi(myargv[p + 1]);
+        }
       else
         {
           startepisode = myargv[p + 1][0] - '0';
@@ -2128,7 +2234,9 @@ void d_doom_main(void)
    */
 
   if (gamemode == commercial && w_check_num_for_name("map01") < 0)
-    storedemo = true;
+    {
+      storedemo = true;
+    }
 
   if (m_check_parm_with_args("-statdump", 1))
     {
@@ -2175,9 +2283,13 @@ void d_doom_main(void)
   if (gameaction != ga_loadgame)
     {
       if (autostart || netgame)
-        g_init_new(startskill, startepisode, startmap);
+        {
+          g_init_new(startskill, startepisode, startmap);
+        }
       else
-        d_start_title(); /* start up intro loop */
+        {
+          d_start_title(); /* start up intro loop */
+        }
     }
 
   d_doomloop(); /* never returns */
diff --git a/games/NXDoom/src/doom/r_draw.c b/games/NXDoom/src/doom/r_draw.c
index ff243912a..7bee0deff 100644
--- a/games/NXDoom/src/doom/r_draw.c
+++ b/games/NXDoom/src/doom/r_draw.c
@@ -168,11 +168,16 @@ void r_draw_column(void)
 
   /* Zero length, column does not exceed a pixel. */
 
-  if (count < 0) return;
+  if (count < 0)
+    {
+      return;
+    }
 
 #ifdef CONFIG_GAMES_NXDOOM_RANGECHECK
   if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
-    i_error("r_draw_column: %i to %i at %i", dc_yl, dc_yh, dc_x);
+    {
+      i_error("r_draw_column: %i to %i at %i", dc_yl, dc_yh, dc_x);
+    }
 #endif
 
   /* Framebuffer destination address.
@@ -277,7 +282,10 @@ void r_draw_column_low(void)
 
   /* Zero length. */
 
-  if (count < 0) return;
+  if (count < 0)
+    {
+      return;
+    }
 
 #ifdef CONFIG_GAMES_NXDOOM_RANGECHECK
   if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
@@ -324,17 +332,26 @@ void r_draw_fuzz_column(void)
 
   /* Adjust borders. Low... */
 
-  if (!dc_yl) dc_yl = 1;
+  if (!dc_yl)
+    {
+      dc_yl = 1;
+    }
 
   /* .. and high. */
 
-  if (dc_yh == viewheight - 1) dc_yh = viewheight - 2;
+  if (dc_yh == viewheight - 1)
+    {
+      dc_yh = viewheight - 2;
+    }
 
   count = dc_yh - dc_yl;
 
   /* Zero length. */
 
-  if (count < 0) return;
+  if (count < 0)
+    {
+      return;
+    }
 
 #ifdef CONFIG_GAMES_NXDOOM_RANGECHECK
   if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
@@ -360,7 +377,10 @@ void r_draw_fuzz_column(void)
 
       /* Clamp table lookup index. */
 
-      if (++fuzzpos == FUZZTABLE) fuzzpos = 0;
+      if (++fuzzpos == FUZZTABLE)
+        {
+          fuzzpos = 0;
+        }
 
       dest += SCREENWIDTH;
     }
@@ -378,17 +398,26 @@ void r_draw_fuzz_column_low(void)
 
   /* Adjust borders. Low... */
 
-  if (!dc_yl) dc_yl = 1;
+  if (!dc_yl)
+    {
+      dc_yl = 1;
+    }
 
   /* .. and high. */
 
-  if (dc_yh == viewheight - 1) dc_yh = viewheight - 2;
+  if (dc_yh == viewheight - 1)
+    {
+      dc_yh = viewheight - 2;
+    }
 
   count = dc_yh - dc_yl;
 
   /* Zero length. */
 
-  if (count < 0) return;
+  if (count < 0)
+    {
+      return;
+    }
 
   /* low detail mode, need to multiply by 2 */
 
@@ -419,7 +448,10 @@ void r_draw_fuzz_column_low(void)
 
       /* Clamp table lookup index. */
 
-      if (++fuzzpos == FUZZTABLE) fuzzpos = 0;
+      if (++fuzzpos == FUZZTABLE)
+        {
+          fuzzpos = 0;
+        }
 
       dest += SCREENWIDTH;
       dest2 += SCREENWIDTH;
@@ -444,7 +476,10 @@ void r_draw_translated_column(void)
   fixed_t fracstep;
 
   count = dc_yh - dc_yl;
-  if (count < 0) return;
+  if (count < 0)
+    {
+      return;
+    }
 
 #ifdef CONFIG_GAMES_NXDOOM_RANGECHECK
   if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
@@ -490,7 +525,10 @@ void r_draw_translated_column_low(void)
   int x;
 
   count = dc_yh - dc_yl;
-  if (count < 0) return;
+  if (count < 0)
+    {
+      return;
+    }
 
   /* low detail, need to scale by 2 */
 
@@ -597,7 +635,7 @@ void r_draw_span(void)
 
 #ifdef CONFIG_GAMES_NXDOOM_RANGECHECK
   if (ds_x2 < ds_x1 || ds_x1 < 0 || ds_x2 >= SCREENWIDTH ||
-      (unsigned)ds_y > SCREENHEIGHT)
+      ds_y < 0 || ds_y >= viewheight)
     {
       i_error("r_draw_span: %i to %i at %i", ds_x1, ds_x2, ds_y);
     }
@@ -724,7 +762,7 @@ void r_draw_span_low(void)
 
 #ifdef CONFIG_GAMES_NXDOOM_RANGECHECK
   if (ds_x2 < ds_x1 || ds_x1 < 0 || ds_x2 >= SCREENWIDTH ||
-      (unsigned)ds_y > SCREENHEIGHT)
+      ds_y < 0 || ds_y >= viewheight)
     {
       i_error("r_draw_span: %i to %i at %i", ds_x1, ds_x2, ds_y);
     }
@@ -783,19 +821,27 @@ void r_init_buffer(int width, int height)
   /* Column offset. For windows. */
 
   for (i = 0; i < width; i++)
-    columnofs[i] = viewwindowx + i;
+    {
+      columnofs[i] = viewwindowx + i;
+    }
 
   /* Samw with base row offset. */
 
   if (width == SCREENWIDTH)
-    viewwindowy = 0;
+    {
+      viewwindowy = 0;
+    }
   else
-    viewwindowy = (SCREENHEIGHT - SBARHEIGHT - height) >> 1;
+    {
+      viewwindowy = (SCREENHEIGHT - SBARHEIGHT - height) >> 1;
+    }
 
   /* Preclaculate all row offsets. */
 
   for (i = 0; i < height; i++)
-    ylookup[i] = i_video_buffer + (i + viewwindowy) * SCREENWIDTH;
+    {
+      ylookup[i] = i_video_buffer + (i + viewwindowy) * SCREENWIDTH;
+    }
 }
 
 /* r_fill_back_screen
@@ -847,9 +893,13 @@ void r_fill_back_screen(void)
     }
 
   if (gamemode == commercial)
-    name = name2;
+    {
+      name = name2;
+    }
   else
-    name = name1;
+    {
+      name = name1;
+    }
 
   src = w_cache_lump_name(name, PU_CACHE);
   dest = background_buffer;
@@ -876,19 +926,30 @@ void r_fill_back_screen(void)
   patch = w_cache_lump_name(("brdr_t"), PU_CACHE);
 
   for (x = 0; x < scaledviewwidth; x += 8)
-    v_draw_patch(viewwindowx + x, viewwindowy - 8, patch);
+    {
+      v_draw_patch(viewwindowx + x, viewwindowy - 8, patch);
+    }
+
   patch = w_cache_lump_name(("brdr_b"), PU_CACHE);
 
   for (x = 0; x < scaledviewwidth; x += 8)
-    v_draw_patch(viewwindowx + x, viewwindowy + viewheight, patch);
+    {
+      v_draw_patch(viewwindowx + x, viewwindowy + viewheight, patch);
+    }
+
   patch = w_cache_lump_name(("brdr_l"), PU_CACHE);
 
   for (y = 0; y < viewheight; y += 8)
-    v_draw_patch(viewwindowx - 8, viewwindowy + y, patch);
+    {
+      v_draw_patch(viewwindowx - 8, viewwindowy + y, patch);
+    }
+
   patch = w_cache_lump_name(("brdr_r"), PU_CACHE);
 
   for (y = 0; y < viewheight; y += 8)
-    v_draw_patch(viewwindowx + scaledviewwidth, viewwindowy + y, patch);
+    {
+      v_draw_patch(viewwindowx + scaledviewwidth, viewwindowy + y, patch);
+    }
 
   /* Draw beveled edge. */
 
@@ -934,7 +995,10 @@ void r_draw_view_border(void)
   int ofs;
   int i;
 
-  if (scaledviewwidth == SCREENWIDTH) return;
+  if (scaledviewwidth == SCREENWIDTH)
+    {
+      return;
+    }
 
   top = ((SCREENHEIGHT - SBARHEIGHT) - viewheight) / 2;
   side = (SCREENWIDTH - scaledviewwidth) / 2;
diff --git a/games/NXDoom/src/doom/r_main.c b/games/NXDoom/src/doom/r_main.c
index b50cdc337..bb5b953c7 100644
--- a/games/NXDoom/src/doom/r_main.c
+++ b/games/NXDoom/src/doom/r_main.c
@@ -31,6 +31,7 @@
 
 #include "d_loop.h"
 #include "doomdef.h"
+#include "i_system.h"
 
 #include "m_bbox.h"
 #include "m_menu.h"
@@ -142,10 +143,25 @@ int setdetail;
 #if 0 /* UNUSED */
 static void r_add_point_to_box(int x, int y, fixed_t *box)
 {
-  if (x < box[BOXLEFT]) box[BOXLEFT] = x;
-  if (x > box[BOXRIGHT]) box[BOXRIGHT] = x;
-  if (y < box[BOXBOTTOM]) box[BOXBOTTOM] = y;
-  if (y > box[BOXTOP]) box[BOXTOP] = y;
+  if (x < box[BOXLEFT])
+    {
+      box[BOXLEFT] = x;
+    }
+
+  if (x > box[BOXRIGHT])
+    {
+      box[BOXRIGHT] = x;
+    }
+
+  if (y < box[BOXBOTTOM])
+    {
+      box[BOXBOTTOM] = y;
+    }
+
+  if (y > box[BOXTOP])
+    {
+      box[BOXTOP] = y;
+    }
 }
 #endif
 
@@ -177,10 +193,14 @@ static void r_setup_frame(player_t *player)
       walllights = scalelightfixed;
 
       for (i = 0; i < MAXLIGHTSCALE; i++)
-        scalelightfixed[i] = fixedcolormap;
+        {
+          scalelightfixed[i] = fixedcolormap;
+        }
     }
   else
-    fixedcolormap = 0;
+    {
+      fixedcolormap = 0;
+    }
 
   framecount++;
   validcount++;
@@ -216,9 +236,15 @@ static void r_init_light_tables(void)
           scale >>= LIGHTSCALESHIFT;
           level = startmap - scale / DISTMAP;
 
-          if (level < 0) level = 0;
+          if (level < 0)
+            {
+              level = 0;
+            }
 
-          if (level >= NUMCOLORMAPS) level = NUMCOLORMAPS - 1;
+          if (level >= NUMCOLORMAPS)
+            {
+              level = NUMCOLORMAPS - 1;
+            }
 
           zlight[i][j] = colormaps + level * 256;
         }
@@ -307,18 +333,26 @@ static void r_init_texture_mapping(void)
   for (i = 0; i < FINEANGLES / 2; i++)
     {
       if (finetangent[i] > FRACUNIT * 2)
-        t = -1;
+        {
+          t = -1;
+        }
       else if (finetangent[i] < -FRACUNIT * 2)
-        t = viewwidth + 1;
+        {
+          t = viewwidth + 1;
+        }
       else
         {
           t = fixed_mul(finetangent[i], focallength);
           t = (centerxfrac - t + FRACUNIT - 1) >> FRACBITS;
 
           if (t < -1)
-            t = -1;
+            {
+              t = -1;
+            }
           else if (t > viewwidth + 1)
-            t = viewwidth + 1;
+            {
+              t = viewwidth + 1;
+            }
         }
 
       viewangletox[i] = t;
@@ -333,7 +367,10 @@ static void r_init_texture_mapping(void)
     {
       i = 0;
       while (viewangletox[i] > x)
-        i++;
+        {
+          i++;
+        }
+
       xtoviewangle[x] = (i << ANGLETOFINESHIFT) - ANG90;
     }
 
@@ -345,9 +382,13 @@ static void r_init_texture_mapping(void)
       t = centerx - t;
 
       if (viewangletox[i] == -1)
-        viewangletox[i] = 0;
+        {
+          viewangletox[i] = 0;
+        }
       else if (viewangletox[i] == viewwidth + 1)
-        viewangletox[i] = viewwidth;
+        {
+          viewangletox[i] = viewwidth;
+        }
     }
 
   clipangle = xtoviewangle[0];
@@ -376,14 +417,20 @@ int r_point_on_side(fixed_t x, fixed_t y, node_t *node)
 
   if (!node->dx)
     {
-      if (x <= node->x) return node->dy > 0;
+      if (x <= node->x)
+        {
+          return node->dy > 0;
+        }
 
       return node->dy < 0;
     }
 
   if (!node->dy)
     {
-      if (y <= node->y) return node->dx < 0;
+      if (y <= node->y)
+        {
+          return node->dx < 0;
+        }
 
       return node->dx > 0;
     }
@@ -437,14 +484,20 @@ int r_point_on_seg_side(fixed_t x, fixed_t y, seg_t *line)
 
   if (!ldx)
     {
-      if (x <= lx) return ldy > 0;
+      if (x <= lx)
+        {
+          return ldy > 0;
+        }
 
       return ldy < 0;
     }
 
   if (!ldy)
     {
-      if (y <= ly) return ldx < 0;
+      if (y <= ly)
+        {
+          return ldx < 0;
+        }
 
       return ldx > 0;
     }
@@ -491,7 +544,10 @@ angle_t r_point_to_angle(fixed_t x, fixed_t y)
   x -= viewx;
   y -= viewy;
 
-  if ((!x) && (!y)) return 0;
+  if ((!x) && (!y))
+    {
+      return 0;
+    }
 
   if (x >= 0)
     {
@@ -664,12 +720,18 @@ fixed_t r_scale_from_global_angle(angle_t visangle)
       scale = fixed_div(num, den);
 
       if (scale > 64 * FRACUNIT)
-        scale = 64 * FRACUNIT;
+        {
+          scale = 64 * FRACUNIT;
+        }
       else if (scale < 256)
-        scale = 256;
+        {
+          scale = 256;
+        }
     }
   else
-    scale = 64 * FRACUNIT;
+    {
+      scale = 64 * FRACUNIT;
+    }
 
   return scale;
 }
@@ -685,6 +747,13 @@ fixed_t r_scale_from_global_angle(angle_t visangle)
 
 void r_set_view_size(int blocks, int detail)
 {
+  /* Reject invalid screen sizes before calculating view geometry. */
+
+  if (blocks < 3 || blocks > 11)
+    {
+      i_error("r_set_view_size: screenblocks=%d out of range", blocks);
+    }
+
   setsizeneeded = true;
   setblocks = blocks;
   setdetail = detail;
@@ -752,7 +821,9 @@ void r_execute_set_view_size(void)
   /* thing clipping */
 
   for (i = 0; i < viewwidth; i++)
-    screenheightarray[i] = viewheight;
+    {
+      screenheightarray[i] = viewheight;
+    }
 
   /* planes */
 
@@ -779,9 +850,15 @@ void r_execute_set_view_size(void)
           level = startmap -
                   j * SCREENWIDTH / (viewwidth << detailshift) / DISTMAP;
 
-          if (level < 0) level = 0;
+          if (level < 0)
+            {
+              level = 0;
+            }
 
-          if (level >= NUMCOLORMAPS) level = NUMCOLORMAPS - 1;
+          if (level >= NUMCOLORMAPS)
+            {
+              level = NUMCOLORMAPS - 1;
+            }
 
           scalelight[i][j] = colormaps + level * 256;
         }
@@ -828,7 +905,10 @@ subsector_t *r_point_in_subsector(fixed_t x, fixed_t y)
 
   /* single subsector is a special case */
 
-  if (!numnodes) return subsectors;
+  if (!numnodes)
+    {
+      return subsectors;
+    }
 
   nodenum = numnodes - 1;
 
diff --git a/games/NXDoom/src/doom/r_plane.c b/games/NXDoom/src/doom/r_plane.c
index 65a2c2fa7..b16c15b95 100644
--- a/games/NXDoom/src/doom/r_plane.c
+++ b/games/NXDoom/src/doom/r_plane.c
@@ -58,11 +58,11 @@ planefunction_t ceilingfunc;
 /* Here comes the obnoxious "visplane". */
 
 visplane_t visplanes[CONFIG_GAMES_NXDOOM_MAXVISPLANES];
+short openings[MAXOPENINGS];
 visplane_t *lastvisplane;
 visplane_t *floorplane;
 visplane_t *ceilingplane;
 
-short openings[MAXOPENINGS];
 short *lastopening;
 
 /* Clip values are the solid pixel bounding the range. floorclip starts out
@@ -114,12 +114,21 @@ static void r_map_plane(int y, int x1, int x2)
   fixed_t length;
   unsigned index;
 
-#ifdef CONFIG_GAMES_NXDOOM_RANGECHECK
-  if (x2 < x1 || x1 < 0 || x2 >= viewwidth || y > viewheight)
+  /* Ensure array indices are in range before access. */
+
+  if (x2 < x1 || x1 < 0 || x2 >= viewwidth)
     {
-      i_error("R_MapPlane: %i, %i at %i", x1, x2, y);
+      return;
+    }
+
+  if (y < 0)
+    {
+      y = 0;
+    }
+  else if (y >= viewheight)
+    {
+      y = viewheight - 1;
     }
-#endif
 
   if (planeheight != cachedheight[y])
     {
@@ -141,12 +150,17 @@ static void r_map_plane(int y, int x1, int x2)
   ds_yfrac = -viewy - fixed_mul(finesine[angle], length);
 
   if (fixedcolormap)
-    ds_colormap = fixedcolormap;
+    {
+      ds_colormap = fixedcolormap;
+    }
   else
     {
       index = distance >> LIGHTZSHIFT;
 
-      if (index >= MAXLIGHTZ) index = MAXLIGHTZ - 1;
+      if (index >= MAXLIGHTZ)
+        {
+          index = MAXLIGHTZ - 1;
+        }
 
       ds_colormap = planezlight[index];
     }
@@ -160,27 +174,42 @@ static void r_map_plane(int y, int x1, int x2)
   spanfunc();
 }
 
+static inline boolean r_row_in_range(int row)
+{
+  return row >= 0 && row < SCREENHEIGHT;
+}
+
 static void r_make_spans(int x, int t1, int b1, int t2, int b2)
 {
+  /* Check that row is in range before indexing arrays. */
+
   while (t1 < t2 && t1 <= b1)
     {
-      r_map_plane(t1, spanstart[t1], x - 1);
+      r_map_plane(t1, r_row_in_range(t1) ? spanstart[t1] : 0, x - 1);
       t1++;
     }
   while (b1 > b2 && b1 >= t1)
     {
-      r_map_plane(b1, spanstart[b1], x - 1);
+      r_map_plane(b1, r_row_in_range(b1) ? spanstart[b1] : 0, x - 1);
       b1--;
     }
 
   while (t2 < t1 && t2 <= b2)
     {
-      spanstart[t2] = x;
+      if (r_row_in_range(t2))
+        {
+          spanstart[t2] = x;
+        }
+
       t2++;
     }
   while (b2 > b1 && b2 >= t2)
     {
-      spanstart[b2] = x;
+      if (r_row_in_range(b2))
+        {
+          spanstart[b2] = x;
+        }
+
       b2--;
     }
 }
@@ -251,10 +280,15 @@ visplane_t *r_find_plane(fixed_t height, int picnum, int 
lightlevel)
         }
     }
 
-  if (check < lastvisplane) return check;
+  if (check < lastvisplane)
+    {
+      return check;
+    }
 
   if (lastvisplane - visplanes == CONFIG_GAMES_NXDOOM_MAXVISPLANES)
-    i_error("r_find_plane: no more visplanes");
+    {
+      i_error("r_find_plane: no more visplanes");
+    }
 
   lastvisplane++;
 
@@ -301,7 +335,10 @@ visplane_t *r_check_plane(visplane_t *pl, int start, int 
stop)
 
   for (x = intrl; x <= intrh; x++)
     {
-      if (pl->top[x] != 0xff) break;
+      if (pl->top[x] != 0xff)
+        {
+          break;
+        }
     }
 
   if (x > intrh)
@@ -314,13 +351,15 @@ visplane_t *r_check_plane(visplane_t *pl, int start, int 
stop)
 
   /* make a new visplane */
 
+  if (lastvisplane - visplanes == CONFIG_GAMES_NXDOOM_MAXVISPLANES)
+    {
+      i_error("r_check_plane: no more visplanes");
+    }
+
   lastvisplane->height = pl->height;
   lastvisplane->picnum = pl->picnum;
   lastvisplane->lightlevel = pl->lightlevel;
 
-  if (lastvisplane - visplanes == CONFIG_GAMES_NXDOOM_MAXVISPLANES)
-    i_error("r_check_plane: no more visplanes");
-
   pl = lastvisplane++;
   pl->minx = start;
   pl->maxx = stop;
@@ -343,19 +382,29 @@ void r_draw_planes(void)
 
 #ifdef CONFIG_GAMES_NXDOOM_RANGECHECK
   if (ds_p - drawsegs > CONFIG_GAMES_NXDOOM_MAXDRAWSEGS)
-    i_error("r_draw_planes: drawsegs overflow (%td)", ds_p - drawsegs);
+    {
+      i_error("r_draw_planes: drawsegs overflow (%td)", ds_p - drawsegs);
+    }
 
   if (lastvisplane - visplanes > CONFIG_GAMES_NXDOOM_MAXVISPLANES)
-    i_error("r_draw_planes: visplane overflow (%td)",
-            lastvisplane - visplanes);
+    {
+      i_error("r_draw_planes: visplane overflow (%td)",
+        lastvisplane - visplanes);
+    }
 
   if (lastopening - openings > MAXOPENINGS)
-    i_error("r_draw_planes: opening overflow (%td)", lastopening - openings);
+    {
+      i_error("r_draw_planes: opening overflow (%td)",
+        lastopening - openings);
+    }
 #endif
 
   for (pl = visplanes; pl < lastvisplane; pl++)
     {
-      if (pl->minx > pl->maxx) continue;
+      if (pl->minx > pl->maxx)
+        {
+          continue;
+        }
 
       /* sky flat */
 
@@ -395,9 +444,15 @@ void r_draw_planes(void)
       planeheight = abs(pl->height - viewz);
       light = (pl->lightlevel >> LIGHTSEGSHIFT) + extralight;
 
-      if (light >= LIGHTLEVELS) light = LIGHTLEVELS - 1;
+      if (light >= LIGHTLEVELS)
+        {
+          light = LIGHTLEVELS - 1;
+        }
 
-      if (light < 0) light = 0;
+      if (light < 0)
+        {
+          light = 0;
+        }
 
       planezlight = zlight[light];
 
diff --git a/games/NXDoom/src/doom/statdump.c b/games/NXDoom/src/doom/statdump.c
index 1db5657ab..fcd1d5576 100644
--- a/games/NXDoom/src/doom/statdump.c
+++ b/games/NXDoom/src/doom/statdump.c
@@ -39,7 +39,7 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
-#define MAX_CAPTURES 32
+#define MAX_CAPTURES CONFIG_GAMES_NXDOOM_STATDUMP_MAX_CAPTURES
 
 /****************************************************************************
  * Private Data
@@ -276,17 +276,25 @@ static void print_level_name(FILE *stream, int episode, 
int level)
 
   switch (discovered_gamemission)
     {
-    case doom:
-      fprintf(stream, "E%iM%i\n", episode + 1, level + 1);
-      break;
-    case doom2:
-      fprintf(stream, "MAP%02i\n", level + 1);
-      break;
-    default:
-    case none:
-      fprintf(stream, "E%iM%i / MAP%02i\n", episode + 1, level + 1,
-              level + 1);
-      break;
+      case doom:
+        {
+          fprintf(stream, "E%iM%i\n", episode + 1, level + 1);
+          break;
+        }
+
+      case doom2:
+        {
+          fprintf(stream, "MAP%02i\n", level + 1);
+          break;
+        }
+
+      default:
+      case none:
+        {
+          fprintf(stream, "E%iM%i / MAP%02i\n", episode + 1, level + 1,
+            level + 1);
+          break;
+        }
     }
 
   print_banner(stream);
diff --git a/games/NXDoom/src/i_main.c b/games/NXDoom/src/i_main.c
index bd9dab609..1961b8734 100644
--- a/games/NXDoom/src/i_main.c
+++ b/games/NXDoom/src/i_main.c
@@ -57,6 +57,8 @@ void d_doom_main(void);
 
 int main(int argc, char **argv)
 {
+  i_install_quit_signal();
+
   /* save arguments */
 
   myargc = argc;
diff --git a/games/NXDoom/src/i_system.c b/games/NXDoom/src/i_system.c
index b3867e0ad..a13fbd36c 100644
--- a/games/NXDoom/src/i_system.c
+++ b/games/NXDoom/src/i_system.c
@@ -22,6 +22,8 @@
  * Included Files
  ****************************************************************************/
 
+#include <errno.h>
+#include <signal.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -75,6 +77,10 @@ static atexit_listentry_t *exit_funcs = NULL;
 
 static boolean already_quitting = false;
 
+/* Set by the signal handler and polled from the main loop. */
+
+static volatile sig_atomic_t quit_requested = 0;
+
 /* Read Access Violation emulation.
  *
  * From PrBoom+, by entryway.
@@ -238,7 +244,9 @@ void i_print_banner(const char *msg)
   int spaces = 35 - (strlen(msg) / 2);
 
   for (i = 0; i < spaces; ++i)
-    putchar(' ');
+    {
+      putchar(' ');
+    }
 
   puts(msg);
 }
@@ -320,6 +328,69 @@ void i_quit(void)
   exit(0);
 }
 
+/****************************************************************************
+ * Name: i_quit_signal_handler
+ *
+ * Description:
+ *   Records that a quit was requested.  The work is deferred to
+ *   i_poll_quit_signal() so that no cleanup runs from signal context.
+ *
+ ****************************************************************************/
+
+static void i_quit_signal_handler(int signo)
+{
+  (void)signo;
+  quit_requested = 1;
+}
+
+/****************************************************************************
+ * Name: i_install_quit_signal
+ *
+ * Description:
+ *   Installs the SIGTERM handler used to request a clean exit.
+ *
+ ****************************************************************************/
+
+void i_install_quit_signal(void)
+{
+  struct sigaction sa;
+
+  /* Reset state left by an earlier built-in run. */
+
+  quit_requested = 0;
+  exit_funcs = NULL;
+
+  memset(&sa, 0, sizeof(sa));
+  sa.sa_handler = i_quit_signal_handler;
+  sigemptyset(&sa.sa_mask);
+
+  if (sigaction(SIGTERM, &sa, NULL) < 0)
+    {
+      /* Not fatal: the game runs, it just cannot be asked to exit. */
+
+      printf("nxdoom: failed to install SIGTERM handler: %d\n",
+             errno);
+    }
+}
+
+/****************************************************************************
+ * Name: i_poll_quit_signal
+ *
+ * Description:
+ *   Exits if a quit was requested.  Called from the main loop, where the
+ *   cleanup i_quit() performs is safe to run.
+ *
+ ****************************************************************************/
+
+void i_poll_quit_signal(void)
+{
+  if (quit_requested)
+    {
+      printf("nxdoom: quit signal seen, calling i_quit\n");
+      i_quit();
+    }
+}
+
 void i_error(const char *error, ...)
 {
   char msgbuf[512];
@@ -463,19 +534,27 @@ boolean i_get_memory_value(unsigned int offset, void 
*value, int size)
 
   switch (size)
     {
-    case 1:
-      *((unsigned char *)value) = dos_mem_dump[offset];
-      return true;
-    case 2:
-      *((unsigned short *)value) =
-          dos_mem_dump[offset] | (dos_mem_dump[offset + 1] << 8);
-      return true;
-    case 4:
-      *((unsigned int *)value) =
-          dos_mem_dump[offset] | (dos_mem_dump[offset + 1] << 8) |
-          (dos_mem_dump[offset + 2] << 16) |
-          (dos_mem_dump[offset + 3] << 24);
-      return true;
+      case 1:
+        {
+          *((unsigned char *)value) = dos_mem_dump[offset];
+          return true;
+        }
+
+      case 2:
+        {
+          *((unsigned short *)value) = dos_mem_dump[offset] |
+                                       (dos_mem_dump[offset + 1] << 8);
+          return true;
+        }
+
+      case 4:
+        {
+          *((unsigned int *)value) = dos_mem_dump[offset] |
+                                    (dos_mem_dump[offset + 1] << 8) |
+                                    (dos_mem_dump[offset + 2] << 16) |
+                                    (dos_mem_dump[offset + 3] << 24);
+          return true;
+        }
     }
 
   return false;
diff --git a/games/NXDoom/src/i_system.h b/games/NXDoom/src/i_system.h
index ae1c56806..82138da59 100644
--- a/games/NXDoom/src/i_system.h
+++ b/games/NXDoom/src/i_system.h
@@ -73,6 +73,26 @@ ticcmd_t *i_base_ticcmd(void);
 
 void i_quit(void) NORETURN;
 
+/****************************************************************************
+ * Name: i_install_quit_signal
+ *
+ * Description:
+ *   Install the SIGTERM handler used to request a clean exit.
+ *
+ ****************************************************************************/
+
+void i_install_quit_signal(void);
+
+/****************************************************************************
+ * Name: i_poll_quit_signal
+ *
+ * Description:
+ *   Exit if SIGTERM requested a clean shutdown.
+ *
+ ****************************************************************************/
+
+void i_poll_quit_signal(void);
+
 void i_error(const char *error, ...) NORETURN PRINTF_ATTR(1, 2);
 
 void i_tactile(int on, int off, int total);
diff --git a/games/NXDoom/src/i_video.c b/games/NXDoom/src/i_video.c
index d9a76a651..a8cd836c4 100644
--- a/games/NXDoom/src/i_video.c
+++ b/games/NXDoom/src/i_video.c
@@ -105,6 +105,11 @@ struct graphics_state_s
   unsigned outw;
   unsigned outh;
 
+  /* Scaled image origin in pixels; origin is the byte offset. */
+
+  unsigned outx;
+  unsigned outy;
+
   /* Maps an output column onto the source column it is drawn from, so that
    * the inner loop needs neither a division nor a separate case for
    * fractional scaling.
@@ -487,6 +492,25 @@ static void blit_screen(void)
       prevsy = sy;
       prevrow = out;
     }
+
+#ifdef CONFIG_FB_UPDATE
+  /* Notify cached or DMA-backed frame buffers after drawing. */
+
+  {
+    struct fb_area_s area;
+
+    area.x = g_graphics_state.outx;
+    area.y = g_graphics_state.outy;
+    area.w = outw;
+    area.h = outh;
+
+    if (ioctl(g_graphics_state.fd, FBIO_UPDATE,
+      (unsigned long)((uintptr_t)&area)) < 0)
+      {
+        i_error("ioctl(FBIO_UPDATE) failed: %d\n", errno);
+      }
+  }
+#endif
 }
 
 static void update_grab(void)
@@ -586,9 +610,15 @@ void i_finish_update(void)
   int tics;
   int i;
 
-  if (!g_graphics_state.inited) return;
+  if (!g_graphics_state.inited)
+    {
+      return;
+    }
 
-  if (noblit) return;
+  if (noblit)
+    {
+      return;
+    }
 
   /* draws little dots on the bottom of the screen */
 
@@ -597,12 +627,20 @@ void i_finish_update(void)
       i = i_get_time();
       tics = i - lasttic;
       lasttic = i;
-      if (tics > 20) tics = 20;
+      if (tics > 20)
+        {
+          tics = 20;
+        }
 
       for (i = 0; i < tics * 4; i += 4)
-        i_video_buffer[(SCREENHEIGHT - 1) * SCREENWIDTH + i] = 0xff;
+        {
+          i_video_buffer[(SCREENHEIGHT - 1) * SCREENWIDTH + i] = 0xff;
+        }
+
       for (; i < 20 * 4; i += 4)
-        i_video_buffer[(SCREENHEIGHT - 1) * SCREENWIDTH + i] = 0x0;
+        {
+          i_video_buffer[(SCREENHEIGHT - 1) * SCREENWIDTH + i] = 0x0;
+        }
     }
 
   /* Draw disk icon before blit, if necessary. */
@@ -830,6 +868,7 @@ void i_graphics_check_commandline(void)
   if (i > 0)
     {
       int display = atoi(myargv[i + 1]);
+
       if (display >= 0)
         {
           video_display = display;
@@ -936,13 +975,12 @@ void i_init_graphics(void)
   g_graphics_state.outh = SCREENHEIGHT * g_graphics_state.scale;
 #endif
 
-  /* Centre the scaled image in the frame buffer */
+  /* Center after the plane stride and pixel size are known. */
 
-  g_graphics_state.origin =
-      (g_graphics_state.vinfo.yres - g_graphics_state.outh) / 2 *
-      g_graphics_state.pinfo.stride +
-      (g_graphics_state.vinfo.xres - g_graphics_state.outw) / 2 *
-      (g_graphics_state.pinfo.bpp >> 3);
+  g_graphics_state.outx =
+      (g_graphics_state.vinfo.xres - g_graphics_state.outw) / 2;
+  g_graphics_state.outy =
+      (g_graphics_state.vinfo.yres - g_graphics_state.outh) / 2;
 
   /* Build the output column to source column map once */
 
@@ -965,6 +1003,10 @@ void i_init_graphics(void)
       i_error("ioctl(FBIOGET_PLANEINFO) failed: %d\n", errno);
     }
 
+  g_graphics_state.origin =
+      g_graphics_state.outy * g_graphics_state.pinfo.stride +
+      g_graphics_state.outx * (g_graphics_state.pinfo.bpp >> 3);
+
   /* Initialize frame buffer memory for actual rendering */
 
   g_graphics_state.fbmem =

Reply via email to