From eff418eaeebfb82dff169af89da355701e704231 Mon Sep 17 00:00:00 2001 From: Ralf Grillenberger Date: Mon, 4 Oct 2010 21:46:23 +0000 Subject: [PATCH] - Use temporary storage for linear scanline, fixes corruption in Fractint SVGA modes - Implement wrapping on lower-order bit, fixes black line in Titan Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@3648 --- src/hardware/vga_draw.cpp | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/hardware/vga_draw.cpp b/src/hardware/vga_draw.cpp index 494a2b34..72c7df35 100644 --- a/src/hardware/vga_draw.cpp +++ b/src/hardware/vga_draw.cpp @@ -175,12 +175,28 @@ static Bit8u * VGA_Draw_Changes_Line(Bitu vidstart, Bitu line) { #endif static Bit8u * VGA_Draw_Linear_Line(Bitu vidstart, Bitu /*line*/) { -// There is guaranteed extra memory past the wrap boundary. So, instead of using temporary -// storage just copy appropriate chunk from the beginning to the wrap boundary when needed. Bitu offset = vidstart & vga.draw.linear_mask; - if (vga.draw.linear_mask-offset < vga.draw.line_length) - memcpy(vga.draw.linear_base+vga.draw.linear_mask+1, vga.draw.linear_base, vga.draw.line_length); - Bit8u *ret = &vga.draw.linear_base[ offset ]; + Bit8u* ret = &vga.draw.linear_base[offset]; + + // in case (vga.draw.line_length + offset) has bits set that + // are not set in the mask: ((x|y)!=y) equals (x&~y) + if (GCC_UNLIKELY((vga.draw.line_length + offset)& ~vga.draw.linear_mask)) { + // this happens, if at all, only once per frame (1 of 480 lines) + // in some obscure games + Bitu end = (offset + vga.draw.line_length) & vga.draw.linear_mask; + + // assuming lines not longer than 4096 pixels + Bitu wrapped_len = end & 0xFFF; + Bitu unwrapped_len = vga.draw.line_length-wrapped_len; + + // unwrapped chunk: to top of memory block + memcpy(TempLine, &vga.draw.linear_base[offset], unwrapped_len); + // wrapped chunk: from base of memory block + memcpy(&TempLine[unwrapped_len], vga.draw.linear_base, wrapped_len); + + ret = TempLine; + } + #if !defined(C_UNALIGNED_MEMORY) if (GCC_UNLIKELY( ((Bitu)ret) & (sizeof(Bitu)-1)) ) { memcpy( TempLine, ret, vga.draw.line_length );