@@ -45,7 +45,7 @@ const UCHAR PixelMask[8] =
4545 (1 << 1 ),
4646 (1 << 0 ),
4747};
48- static const ULONG lookup [16 ] =
48+ static const ULONG ReverseAndUnpackMonochromePixels [16 ] =
4949{
5050 0x0000 ,
5151 0x0100 ,
@@ -337,25 +337,22 @@ VidScreenToBufferBlt(
337337 _In_ ULONG Height ,
338338 _In_ ULONG Stride )
339339{
340- ULONG Plane ;
341340 ULONG LineStart , LineEnd , LineWidth ;
342- ULONG LeftDelta , RightDelta ;
343- ULONG PixelOffset ;
344- PUCHAR PixelPosition ;
345- PUCHAR k , i ;
346- PULONG m ;
347- UCHAR Value , Value2 ;
348- UCHAR a ;
349- ULONG b ;
350- ULONG x , y ;
341+ ULONG LeftShift , RightShift ;
342+ PUCHAR PixelPtr ;
343+ ULONG Plane , X , Y ;
351344
352345 /* Clear the destination buffer */
353346 RtlZeroMemory (Buffer , Height * Stride );
354347
355348 if (Height == 0 )
356349 return ;
357350
358- /* Calculate total distance to copy on X */
351+ /*
352+ * The VGA bootvid does not read pixels
353+ * that do not fall into a byte block (i.e. Width % 8 != 0).
354+ * This is by design.
355+ */
359356 LineStart = Left / 8 ;
360357 LineEnd = (Left + Width - 1 ) / 8 ;
361358 if (LineStart > LineEnd )
@@ -369,62 +366,47 @@ VidScreenToBufferBlt(
369366 LeftShift = Left & 7 ;
370367 RightShift = 8 - LeftShift ;
371368
372- /* Set Mode 0 */
369+ /* Select read mode 0 */
373370 ReadWriteMode (0 );
374371
375- /* Calculate the pixel offset and convert the X distance into byte form */
376- PixelOffset = Top * (SCREEN_WIDTH / 8 ) + (Left >> 3 );
377-
378- /* Loop the 4 planes */
372+ PixelPtr = (PUCHAR )(VgaBase + (Left / 8 ) + Top * (SCREEN_WIDTH / 8 ));
379373 for (Plane = 0 ; Plane < 4 ; ++ Plane )
380374 {
381- /* Set the current pixel position and reset buffer loop variable */
382- PixelPosition = (PUCHAR )(VgaBase + PixelOffset );
383- i = Buffer ;
375+ PUCHAR OutputBuffer = Buffer ;
376+ PUCHAR PixelPosition = PixelPtr ;
384377
385- /* Set the current plane */
378+ /* Select the current plane to read the pixels */
386379 __outpw (VGA_BASE_IO_PORT + GRAPH_ADDRESS_PORT , (Plane << 8 ) | IND_READ_MAP );
387380
388- /* Start the outer Y height loop */
389- for (y = Height ; y > 0 ; -- y )
381+ for (Y = 0 ; Y < Height ; ++ Y )
390382 {
391- /* Read the current value */
392- m = ( PULONG ) i ;
393- Value = READ_REGISTER_UCHAR ( PixelPosition ) ;
383+ PULONG Destination = ( PULONG ) OutputBuffer ;
384+ UCHAR CurrPixels ;
385+ PUCHAR NextPosition ;
394386
395- /* Set Pixel Position loop variable */
396- k = PixelPosition + 1 ;
387+ CurrPixels = READ_REGISTER_UCHAR ( PixelPosition );
388+ NextPosition = PixelPosition ;
397389
398- /* Start the X inner loop */
399- for (x = LineWidth ; x > 0 ; -- x )
390+ for (X = 0 ; X < LineWidth ; ++ X )
400391 {
401- /* Read the current value */
402- Value2 = READ_REGISTER_UCHAR (k );
403-
404- /* Increase pixel position */
405- k ++ ;
392+ UCHAR NextPixels , Px ;
393+ ULONG Result ;
406394
407- /* Do the blt */
408- a = Value2 >> (UCHAR )RightDelta ;
409- a |= Value << (UCHAR )LeftDelta ;
410- b = lookup [a & 0xF ];
411- a >>= 4 ;
412- b <<= 16 ;
413- b |= lookup [a ];
395+ NextPixels = READ_REGISTER_UCHAR (++ NextPosition );
414396
415- /* Save new value to buffer */
416- * m |= (b << Plane );
397+ /* Store 8 pixels at once */
398+ Px = CurrPixels << LeftShift ;
399+ Px |= NextPixels >> RightShift ;
400+ Result = ReverseAndUnpackMonochromePixels [Px >> 4 ];
401+ Result |= ReverseAndUnpackMonochromePixels [Px & 0x0F ] << 16 ;
417402
418- /* Move to next destination location */
419- m ++ ;
403+ * Destination ++ |= Result << Plane ;
420404
421- /* Write new value */
422- Value = Value2 ;
405+ CurrPixels = NextPixels ;
423406 }
424407
425- /* Update pixel position */
426408 PixelPosition += (SCREEN_WIDTH / 8 );
427- i += Stride ;
409+ OutputBuffer += Stride ;
428410 }
429411 }
430412}
0 commit comments