diff --git a/src/tile.cc b/src/tile.cc index a7e98aa..dd8ef19 100644 --- a/src/tile.cc +++ b/src/tile.cc @@ -18,6 +18,7 @@ #include "platform_compat.h" #include "settings.h" #include "svga.h" +#include namespace fallout { @@ -52,8 +53,6 @@ typedef struct UpsideDownTriangle { static void tileSetBorder(int windowWidth, int windowHeight, int hexGridWidth, int hexGridHeight); static void tileRefreshMapper(Rect* rect, int elevation); static void tileRefreshGame(Rect* rect, int elevation); -static void roof_fill_on(int x, int y, int elevation); -static void roof_fill_off(int x, int y, int elevation); static void tileRenderRoof(int fid, int x, int y, Rect* rect, int light); static void _draw_grid(int tile, int elevation, Rect* rect); static void tileRenderFloor(int fid, int x, int y, Rect* rect); @@ -1258,63 +1257,59 @@ void tileRenderRoofsInRect(Rect* rect, int elevation) } } -// 0x4B22D0 -static void roof_fill_on(int x, int y, int elevation) + +struct roof_fill_task { + int x; + int y; +}; + +void roof_fill_push_task_if_in_bounds(std::stack &tasks_stack, int x, int y) { + if (x >= 0 && x < gSquareGridWidth && y >= 0 && y < gSquareGridHeight) { + tasks_stack.push(roof_fill_task{x,y}); + }; +}; + +static void roof_fill_off_process_task(std::stack &tasks_stack, int elevation, bool on) { - if (x >= 0 && x < gSquareGridWidth && y >= 0 && y < gSquareGridHeight) { - int squareTileIndex = gSquareGridWidth * y + x; - int squareTile = gTileSquares[elevation]->field_0[squareTileIndex]; - int roof = (squareTile >> 16) & 0xFFFF; - int id = roof & 0xFFF; - if (buildFid(OBJ_TYPE_TILE, id, 0, 0, 0) != buildFid(OBJ_TYPE_TILE, 1, 0, 0, 0)) { - int flag = (roof & 0xF000) >> 12; - if ((flag & 0x01) != 0) { + auto [x, y] = tasks_stack.top(); + tasks_stack.pop(); + + int squareTileIndex = gSquareGridWidth * y + x; + int squareTile = gTileSquares[elevation]->field_0[squareTileIndex]; + int roof = (squareTile >> 16) & 0xFFFF; + + int id = roof & 0xFFF; + if (buildFid(OBJ_TYPE_TILE, id, 0, 0, 0) != buildFid(OBJ_TYPE_TILE, 1, 0, 0, 0)) { + int flag = (roof & 0xF000) >> 12; + + if (on ? ((flag & 0x01) != 0) : ((flag & 0x03) == 0)) { + if (on) { flag &= ~0x01; - - gTileSquares[elevation]->field_0[squareTileIndex] = (squareTile & 0xFFFF) | (((flag << 12) | id) << 16); - - roof_fill_on(x - 1, y, elevation); - roof_fill_on(x + 1, y, elevation); - roof_fill_on(x, y - 1, elevation); - roof_fill_on(x, y + 1, elevation); + } else { + flag |= 0x01; } + + gTileSquares[elevation]->field_0[squareTileIndex] = (squareTile & 0xFFFF) | (((flag << 12) | id) << 16); + + roof_fill_push_task_if_in_bounds(tasks_stack, x - 1, y); + roof_fill_push_task_if_in_bounds(tasks_stack, x + 1, y); + roof_fill_push_task_if_in_bounds(tasks_stack, x, y - 1); + roof_fill_push_task_if_in_bounds(tasks_stack, x, y + 1); } } } + // 0x4B23D4 void tile_fill_roof(int x, int y, int elevation, bool on) -{ - if (on) { - roof_fill_on(x, y, elevation); - } else { - roof_fill_off(x, y, elevation); - } -} +{ + std::stack tasks_stack; + + roof_fill_push_task_if_in_bounds(tasks_stack, x, y); -// 0x4B23DC -static void roof_fill_off(int x, int y, int elevation) -{ - if (x >= 0 && x < gSquareGridWidth && y >= 0 && y < gSquareGridHeight) { - int squareTileIndex = gSquareGridWidth * y + x; - int squareTile = gTileSquares[elevation]->field_0[squareTileIndex]; - int roof = (squareTile >> 16) & 0xFFFF; - - int id = roof & 0xFFF; - if (buildFid(OBJ_TYPE_TILE, id, 0, 0, 0) != buildFid(OBJ_TYPE_TILE, 1, 0, 0, 0)) { - int flag = (roof & 0xF000) >> 12; - if ((flag & 0x03) == 0) { - flag |= 0x01; - - gTileSquares[elevation]->field_0[squareTileIndex] = (squareTile & 0xFFFF) | (((flag << 12) | id) << 16); - - roof_fill_off(x - 1, y, elevation); - roof_fill_off(x + 1, y, elevation); - roof_fill_off(x, y - 1, elevation); - roof_fill_off(x, y + 1, elevation); - } - } + while(!tasks_stack.empty()) { + roof_fill_off_process_task(tasks_stack, elevation, on); } }