diff --git a/src/ui/windows/console_tab.cpp b/src/ui/windows/console_tab.cpp index d594354..118fdad 100644 --- a/src/ui/windows/console_tab.cpp +++ b/src/ui/windows/console_tab.cpp @@ -836,6 +836,14 @@ void ConsoleTab::drawVisibleLines(float padX, float lineHeight, bool hasTextFilt // mid-draw. -1 = none. int pendingFoldToggle = -1; + // CRT scanline parity is a true per-visual-row counter (each drawn sub-row = one row). + // Deriving it from cumulativeY/lineHeight drifted (cumulativeY includes the inter-line + // gap) and skipped rows, breaking the alternation. Seed it with the sub-row ordinal of + // the first on-screen line so the shading stays stable across scrolling. + int scanRowOrdinal = 0; + for (int k = 0; k < first_visible && k < static_cast(layout_.segments.size()); k++) + scanRowOrdinal += static_cast(layout_.segments[k].size()); + int last_rendered_vi = first_visible - 1; for (int vi = first_visible; vi < visible_count; vi++) { if (vi < static_cast(layout_.cumulativeY.size()) && @@ -917,9 +925,9 @@ void ConsoleTab::drawVisibleLines(float padX, float lineHeight, bool hasTextFilt const char* segEnd = line.text.c_str() + seg.byteEnd; if (s_scanline_enabled && lineHeight > 0.0f) { - int rowIndex = static_cast(std::floor((layout_.cumulativeY[vi] + seg.yOffset) / lineHeight + 0.5f)); - scanline_rows_.push_back({rowY, rowY + seg.height, rowIndex}); + scanline_rows_.push_back({rowY, rowY + seg.height, scanRowOrdinal}); } + ++scanRowOrdinal; // one per visual sub-row, so parity always alternates // Selection highlight for this sub-row if (lineSelected && selByteStart < seg.byteEnd && selByteEnd > seg.byteStart) {