Clear dirty rect during map updates

Previous solution to replace squares was destructive in nature and
could possibly lead to unexpected things (especially with mods where
tile 0x293 might not be opaque black).

New solution follows mapper refresh routines where entire dirty rect
is reset to black as a preparation step.
This commit is contained in:
Alexander Batalov 2023-01-03 21:10:20 +03:00
parent d040ea814a
commit a5cefd6c8b
2 changed files with 34 additions and 30 deletions

View File

@ -1503,36 +1503,44 @@ static void isoWindowRefreshRect(Rect* rect)
// 0x483EE4
static void isoWindowRefreshRectGame(Rect* rect)
{
Rect clampedDirtyRect;
if (rectIntersection(rect, &gIsoWindowRect, &clampedDirtyRect) == -1) {
Rect rectToUpdate;
if (rectIntersection(rect, &gIsoWindowRect, &rectToUpdate) == -1) {
return;
}
tileRenderFloorsInRect(&clampedDirtyRect, gElevation);
_grid_render(&clampedDirtyRect, gElevation);
_obj_render_pre_roof(&clampedDirtyRect, gElevation);
tileRenderRoofsInRect(&clampedDirtyRect, gElevation);
_obj_render_post_roof(&clampedDirtyRect, gElevation);
// CE: Clear dirty rect to prevent most of the visual artifacts near map
// edges.
bufferFill(gIsoWindowBuffer + rectToUpdate.top * rectGetWidth(&gIsoWindowRect) + rectToUpdate.left,
rectGetWidth(&rectToUpdate),
rectGetHeight(&rectToUpdate),
rectGetWidth(&gIsoWindowRect),
0);
tileRenderFloorsInRect(&rectToUpdate, gElevation);
_obj_render_pre_roof(&rectToUpdate, gElevation);
tileRenderRoofsInRect(&rectToUpdate, gElevation);
_obj_render_post_roof(&rectToUpdate, gElevation);
}
// 0x483F44
static void isoWindowRefreshRectMapper(Rect* rect)
{
Rect clampedDirtyRect;
if (rectIntersection(rect, &gIsoWindowRect, &clampedDirtyRect) == -1) {
Rect rectToUpdate;
if (rectIntersection(rect, &gIsoWindowRect, &rectToUpdate) == -1) {
return;
}
bufferFill(gIsoWindowBuffer + clampedDirtyRect.top * (_scr_size.right - _scr_size.left + 1) + clampedDirtyRect.left,
clampedDirtyRect.right - clampedDirtyRect.left + 1,
clampedDirtyRect.bottom - clampedDirtyRect.top + 1,
_scr_size.right - _scr_size.left + 1,
bufferFill(gIsoWindowBuffer + rectToUpdate.top * rectGetWidth(&gIsoWindowRect) + rectToUpdate.left,
rectGetWidth(&rectToUpdate),
rectGetHeight(&rectToUpdate),
rectGetWidth(&gIsoWindowRect),
0);
tileRenderFloorsInRect(&clampedDirtyRect, gElevation);
_grid_render(&clampedDirtyRect, gElevation);
_obj_render_pre_roof(&clampedDirtyRect, gElevation);
tileRenderRoofsInRect(&clampedDirtyRect, gElevation);
_obj_render_post_roof(&clampedDirtyRect, gElevation);
tileRenderFloorsInRect(&rectToUpdate, gElevation);
_grid_render(&rectToUpdate, gElevation);
_obj_render_pre_roof(&rectToUpdate, gElevation);
tileRenderRoofsInRect(&rectToUpdate, gElevation);
_obj_render_post_roof(&rectToUpdate, gElevation);
}
// NOTE: Inlined.
@ -1721,18 +1729,6 @@ static int _square_load(File* stream, int flags)
}
}
// CE: Replace null tiles with a solid black tiles. This prevents copying
// buffer contents of nearby tiles during scrolling and repeating hex
// pointer when hovering mouse over null tiles.
for (int elevation = 0; elevation < ELEVATION_COUNT; elevation++) {
for (int tileIndex = 0; tileIndex < SQUARE_GRID_SIZE; tileIndex++) {
int tile = _square[elevation]->field_0[tileIndex];
if (tile == 0x00010001) {
_square[elevation]->field_0[tileIndex] = 0x00010293;
}
}
}
return 0;
}

View File

@ -631,6 +631,14 @@ static void tileRefreshGame(Rect* rect, int elevation)
return;
}
// CE: Clear dirty rect to prevent most of the visual artifacts near map
// edges.
bufferFill(gTileWindowBuffer + rectToUpdate.top * gTileWindowPitch + rectToUpdate.left,
rectGetWidth(&rectToUpdate),
rectGetHeight(&rectToUpdate),
gTileWindowPitch,
0);
tileRenderFloorsInRect(&rectToUpdate, elevation);
_obj_render_pre_roof(&rectToUpdate, elevation);
tileRenderRoofsInRect(&rectToUpdate, elevation);