From 4f9adbce9c344dbf06cdd23197e74a7688e80c8e Mon Sep 17 00:00:00 2001 From: aviralgarg05 Date: Sun, 16 Aug 2026 21:02:53 +0530 Subject: [PATCH] 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 --- 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 a95d0a19fe3..6f716217d6a 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 a6f1cd9453d..62dbf2b6b00 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 52df6eda110..153ad957dde 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 ff243912aed..7bee0deff8f 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 b50cdc33773..bb5b953c7e0 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 65a2c2fa78b..b16c15b9511 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 1db5657ab6c..fcd1d5576f3 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 bd9dab60910..1961b873446 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 b3867e0add9..a13fbd36c3c 100644 --- a/games/NXDoom/src/i_system.c +++ b/games/NXDoom/src/i_system.c @@ -22,6 +22,8 @@ * Included Files ****************************************************************************/ +#include +#include #include #include #include @@ -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 ae1c568068b..82138da593e 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 d9a76a65144..a8cd836c4ab 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 =