home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / PROG_PAS / XLIB_TP5.ZIP / UNITS / X_RECT.PAS < prev    next >
Pascal/Delphi Source File  |  1993-12-19  |  37KB  |  789 lines

  1. unit X_Rect;
  2.  
  3. interface
  4.  
  5. (* rectangle solid colour fill routine.                                     *)
  6. procedure x_rect_fill(X1,Y1,X2,Y2,Color:Word);
  7. procedure x_rect_fill_clipped(X1,Y1,X2,Y2,Color:Word);
  8.  
  9. procedure Box(x1,y1,x2,y2,Color:Word);
  10. procedure Shadow_Box(x1,y1,x2,y2,C1,C2,C3:Word);
  11.  
  12. (* rectangle 4x4 pattern fill routine.         *)
  13. procedure x_rect_pattern(X1,Y1,X2,Y2:Word;Var Pattern);
  14. procedure x_rect_pattern_clipped(X1,Y1,X2,Y2:Word;Var Pattern);
  15.  
  16. (* Display memory to display memory copy routine. Left edge of source       *)
  17. (* rectangle modulo 4 must equal left edge of destination rectangle modulo 4*)
  18. (* Works on all VGAs.  Ignoring activ_screen->absolute Pos.                 *)
  19. procedure x_cp_vid_rect(SrcX1,SrcY1,SrcX2,ScrY2,DestX1,DestY1:Word);
  20.  
  21. (* Copy a rectangular region of a VGA screen, with x coordinates            *)
  22. (* rounded to the nearest byte -- source and destination may overlap.       *)
  23. procedure x_shift_rect(ScrX1,ScrY1,ScrX2,ScrY2,DestX1,DestY1:Word);
  24.  
  25. implementation
  26. uses X_Const,X_Main;
  27.  
  28. (* Plane masks for clipping left and right edges of rectangle.      *)
  29.  
  30. const LeftClipPlaneMask :Array[0..3] of Byte = ($0f,$0e,$0c,$08);
  31.       RightClipPlaneMask:Array[0..3] of Byte = ($0f,$01,$03,$07);
  32.  
  33.  
  34.  
  35.  
  36. (* Mode X (320x240, 256 colors) rectangle solid colour fill routine. *)
  37.  
  38. procedure x_rect_fill(X1,Y1,X2,Y2,Color:Word);  assembler;
  39. asm
  40.         cld
  41.     mov  ax,ScrnLogicalByteWidth
  42.     mul  Y1                  (* offset in page of top rectangle scan line *)
  43.     mov  di,X1
  44.     shr  di,1                (*X/4 = offset of first rectangle pixel in scan *)
  45.     shr  di,1                (* line                                    *)
  46.     add  di,ax               (*offset of first rectangle pixel in page  *)
  47.     add  di,ScreenOfs        (*offset of first rectangle pixel in       *)
  48.                      (* display memory                          *)
  49.     mov  ax,SCREEN_SEG       (*point ES:DI to the first rectangle       *)
  50.     mov  es,ax               (* pixel's address                         *)
  51.     mov  dx,SC_INDEX         (*set the Sequence Controller Index to     *)
  52.     mov  al,MAP_MASK         (* point to the Map Mask register          *)
  53.     out  dx,al
  54.     inc  dx                  (*point DX to the SC Data register         *)
  55.     mov  si,X1
  56.     and  si,0003h                    (*look up left edge plane mask     *)
  57.     mov  bh,[offset LeftClipPlaneMask+si]    (* to clip & put in BH             *)
  58.     mov  si,X2
  59.         and  si,0003h                    (*look up right edge plane         *)
  60.     mov  bl,[offset RightClipPlaneMask+si]   (* mask to clip & put in BL        *)
  61.  
  62.     mov  cx,X2                   (*calculate # of addresses across rect *)
  63.     mov  si,X1
  64.     cmp  cx,si
  65.     jle  @@FillDone                  (*skip if 0 or negative width      *)
  66.     dec  cx
  67.     and  si,not 011b
  68.     sub  cx,si
  69.     shr  cx,1
  70.     shr  cx,1                 (*# of addresses across rectangle to fill - 1 *)
  71.     jnz  @@MasksSet           (*there's more than one byte to draw      *)
  72.     and  bh,bl                (*there's only one byte, so combine the left *)
  73.                                   (* and right edge clip masks              *)
  74. @@MasksSet:
  75.     mov  si,Y2
  76.     sub  si,Y1                (* BX = height of rectangle               *)
  77.     jle  @@FillDone             (*skip if 0 or negative height          *)
  78.     mov  ah,byte ptr [Color]    (*color with which to fill              *)
  79.     mov  bp,ScrnLogicalByteWidth(*stack frame isn't needed any more     *)
  80.     sub  bp,cx                  (*distance from end of one scan line to start *)
  81.     dec  bp                     (* of next                              *)
  82. @@FillRowsLoop:
  83.     push cx                     (*remember width in addresses - 1       *)
  84.     mov  al,bh                  (*put left-edge clip mask in AL         *)
  85.     out  dx,al                  (*set the left-edge plane (clip) mask   *)
  86.     mov  al,ah                  (*put color in AL                       *)
  87.         stosb                       (*draw the left edge                    *)
  88.     dec  cx                     (*count off left edge byte              *)
  89.     js   @@FillLoopBottom       (*that's the only byte                  *)
  90.     jz   @@DoRightEdge          (*there are only two bytes              *)
  91.     mov  al,00fh                (*middle addresses drawn 4 pixels at a pop *)
  92.     out  dx,al                  (*set the middle pixel mask to no clip  *)
  93.     mov  al,ah                  (*put color in AL                       *)
  94.     rep  stosb                  (*draw middle addresses four pixels apiece *)
  95. @@DoRightEdge:
  96.     mov  al,bl                  (*put right-edge clip mask in AL        *)
  97.     out  dx,al                  (*set the right-edge plane (clip) mask  *)
  98.     mov  al,ah                  (*put color in AL                       *)
  99.         stosb                       (*draw the right edge                   *)
  100. @@FillLoopBottom:
  101.     add  di,bp                  (*point to start of the next scan line of *)
  102.                                     (* the rectangle                        *)
  103.     pop  cx                     (*retrieve width in addresses - 1       *)
  104.     dec  si                     (*count down scan lines                 *)
  105.     jnz  @@FillRowsLoop
  106. @@FillDone:
  107. end;
  108.  
  109. procedure Box(x1,y1,x2,y2,Color:Word);
  110. begin;
  111.   x_rect_fill(X1,Y1,X2,Y2,Color);
  112. end;
  113.  
  114. procedure Shadow_Box(x1,y1,x2,y2,C1,C2,C3:Word);
  115. var L_X:Word;
  116. begin;
  117.   Box(x1,y1,x2,y2,C2);
  118.   Line(x1,  y1,  x2,y1,C1);
  119.   Line(x1,  y1,  x1,y2,C1);
  120.   Line(x1+1,y2,  x2,y2,C3);
  121.   Line(x2,  y1+1,x2,y2,C3);
  122. end;
  123.  
  124.  
  125. (*------------------------------------------------------------------------- *)
  126. (* Mode X rectangle solid colour fill routine.                              *)
  127. (*                                                                          *)
  128. (* Based on code originally published in DDJ Mag by M. Abrash               *)
  129. (*                                                                          *)
  130.  
  131.  
  132. procedure x_rect_fill_clipped(X1,Y1,X2,Y2,Color:Word); assembler;
  133. (* StartX:word,StartY:word,EndX:word,EndY:word,ScreenOfs:word,Color:word *)
  134. asm
  135.     push si              (*preserve caller's register variables         *)
  136.     push di
  137.  
  138.     mov   dx,[TopClip]           (* Compare u.l. Y coord with Top       *)
  139.     mov   cx,[BottomClip]
  140.     mov   ax,[Y1]
  141.     mov   bx,[Y2]
  142.         cmp   dx,ax
  143.         jle   @@CheckBottomClip
  144.     cmp   dx,bx
  145.     jg    @@NotVisible
  146.     mov   [Y1],dx
  147.  
  148. @@CheckBottomClip:
  149.     cmp   cx,bx
  150.     jg    @@CheckLeftClip
  151.     cmp   cx,ax
  152.     jl    @@NotVisible
  153.     mov   [Y2],cx
  154.  
  155. @@CheckLeftClip:
  156.     mov   dx,[LeftClip]           (* Compare u.l. Y coord with Top      *)
  157.     mov   cx,[RightClip]
  158.     mov   ax,[X1]
  159.     mov   bx,[X2]
  160.     sal   dx,1
  161.     sal   dx,1
  162.     sal   cx,1
  163.     sal   cx,1
  164.     cmp   dx,ax
  165.     jle   @@CheckRightClip
  166.     cmp   dx,bx
  167.     jg    @@NotVisible
  168.     mov   [X1],dx
  169.  
  170. @@CheckRightClip:
  171.     cmp   cx,bx
  172.     jg    @RFClipDone
  173.     cmp   cx,ax
  174.     jl    @@NotVisible
  175.     mov   [X2],cx
  176.  
  177. @RFClipDone:
  178.      cld
  179.     mov  ax,[ScrnLogicalByteWidth]
  180.     mul  [Y1]                (*offset in page of top rectangle scan line*)
  181.     mov  di,[X1]
  182.     sar  di,1                (*X/4 = offset of first rectangle pixel in scan *)
  183.     sar  di,1
  184.     add  di,ax               (*offset of first rectangle pixel in page  *)
  185.     add  di,[ScreenOfs]      (*offset of first rectangle pixel in       *)
  186.                      (* display memory                          *)
  187.     mov  ax,SCREEN_SEG       (*point ES:DI to the first rectangle       *)
  188.     mov  es,ax               (* pixel's address                         *)
  189.     mov  dx,SC_INDEX         (*set the Sequence Controller Index to     *)
  190.     mov  al,MAP_MASK         (* point to the Map Mask register          *)
  191.     out  dx,al
  192.     inc  dx                  (*point DX to the SC Data register         *)
  193.     mov  si,[X1]
  194.     and  si,0003h                    (*look up left edge plane mask     *)
  195.     mov  bh,[offset LeftClipPlaneMask+si]    (* to clip & put in BH             *)
  196.     mov  si,[X1]
  197.     and  si,0003h                    (*look up right edge plane         *)
  198.     mov  bl,[offset RightClipPlaneMask+si]   (* mask to clip & put in BL        *)
  199.  
  200.     mov  cx,[X1]                   (*calculate # of addresses across rect *)
  201.     mov  si,[X1]
  202.     cmp  cx,si
  203.     jle  @@FillDone                  (*skip if 0 or negative width      *)
  204.     dec  cx
  205.     and  si,not 011b
  206.     sub  cx,si
  207.     sar  cx,1                 (*# of addresses across rectangle to fill - 1 *)
  208.     sar  cx,1
  209.     jnz  @@MasksSet           (*there's more than one byte to draw          *)
  210.     and  bh,bl                (*there's only one byte, so combine the left  *)
  211.                                   (* and right edge clip masks              *)
  212. @@MasksSet:
  213.     mov  si,[Y2]
  214.     sub  si,[Y1]            (*BX = height of rectangle                  *)
  215.     jle  @@FillDone             (*skip if 0 or negative height          *)
  216.     mov  ah,byte ptr [Color]    (*color with which to fill              *)
  217.     mov  bp,[ScrnLogicalByteWidth]  (*stack frame isn't needed any more *)
  218.     sub  bp,cx                  (*distance from end of one scan line to start *)
  219.     dec  bp                     (* of next                              *)
  220. @@FillRowsLoop:
  221.     push cx                     (*remember width in addresses - 1       *)
  222.     mov  al,bh                  (*put left-edge clip mask in AL         *)
  223.     out  dx,al                  (*set the left-edge plane (clip) mask   *)
  224.     mov  al,ah                  (*put color in AL                       *)
  225.     stosb                       (*draw the left edge                    *)
  226.     dec  cx                     (*count off left edge byte              *)
  227.     js   @@FillLoopBottom       (*that's the only byte                  *)
  228.     jz   @@DoRightEdge          (*there are only two bytes              *)
  229.     mov  al,00fh                (*middle addresses drawn 4 pixels at a pop *)
  230.     out  dx,al                  (*set the middle pixel mask to no clip  *)
  231.     mov  al,ah                  (*put color in AL                       *)
  232.     rep  stosb                  (*draw middle addresses four pixels apiece *)
  233. @@DoRightEdge:
  234.     mov  al,bl                  (*put right-edge clip mask in AL        *)
  235.     out  dx,al                  (*set the right-edge plane (clip) mask  *)
  236.     mov  al,ah                  (*put color in AL                       *)
  237.         stosb                       (*draw the right edge                   *)
  238. @@FillLoopBottom:
  239.     add  di,bp                  (*point to start of the next scan line of *)
  240.                                     (* the rectangle                        *)
  241.     pop  cx                     (*retrieve width in addresses - 1       *)
  242.     dec  si                     (*count down scan lines                 *)
  243.     jnz  @@FillRowsLoop
  244. @@FillDone:
  245.  
  246. @@NotVisible:
  247.     mov   ax,1
  248.     pop   di                          (* restore registers              *)
  249.     pop   si
  250. end;
  251.  
  252.  
  253.  
  254. (* ------------------------------------------------------------------------ *)
  255. (* Mode X (320x240, 256 colors) rectangle 4x4 pattern fill routine.         *)
  256. (* Upper left corner of pattern is always aligned to a multiple-of-4        *)
  257. (* row and column. Works on all VGAs. Uses approach of copying the          *)
  258. (* pattern to off-screen display memory, then loading the latches with      *)
  259. (* the pattern for each scan line and filling each scan line four           *)
  260. (* pixels at a time. Fills up to but not including the column at X2         *)
  261. (* and the row at Y2. No clipping is performed. All ASM code tested         *)
  262. (*                                                                          *)
  263.  
  264. procedure x_rect_pattern(X1,Y1,X2,Y2:Word;Var Pattern); assembler;
  265. var NextScanOffset,RectAddrWidth,Height:Word;
  266. asm
  267.         push ds
  268.         cld
  269.     mov  ax,SCREEN_SEG            (*point ES to display memory          *)
  270.     mov  es,ax
  271.                       (*copy pattern to display memory buffer*)
  272.     lds  si,dword ptr [Pattern]   (*point to pattern to fill with       *)
  273.     mov  di,PATTERN_BUFFER        (*point ES:DI to pattern buffer       *)
  274.     mov  dx,SC_INDEX              (*point Sequence Controller Index to  *)
  275.     mov  al,MAP_MASK              (* Map Mask                           *)
  276.     out  dx,al
  277.     inc  dx                       (*point to SC Data register           *)
  278.     mov  cx,4                     (*4 pixel quadruplets in pattern      *)
  279. @@DownloadPatternLoop:
  280.     mov  al,1                     (*                                    *)
  281.     out  dx,al                    (*select plane 0 for writes           *)
  282.         movsb                         (*copy over next plane 0 pattern pixel*)
  283.     dec  di                       (*stay at same address for next plane *)
  284.     mov  al,2                     (*                                    *)
  285.     out  dx,al                    (*select plane 1 for writes           *)
  286.         movsb                         (*copy over next plane 1 pattern pixel*)
  287.     dec  di                       (*stay at same address for next plane *)
  288.     mov  al,4                     (*                                    *)
  289.     out  dx,al                    (*select plane 2 for writes           *)
  290.         movsb                         (*copy over next plane 2 pattern pixel*)
  291.     dec  di                       (*stay at same address for next plane *)
  292.     mov  al,8                     (*                                    *)
  293.     out  dx,al                    (*select plane 3 for writes           *)
  294.         movsb                         (*copy over next plane 3 pattern pixel*)
  295.                                       (* and advance address                *)
  296.         loop @@DownloadPatternLoop
  297.         pop  ds
  298.  
  299.     mov  dx,GC_INDEX              (*set the bit mask to select all bits *)
  300.     mov  ax,00000h+BIT_MASK       (* from the latches and none from     *)
  301.     out  dx,ax                    (* the CPU, so that we can write the  *)
  302.                                       (* latch contents directly to memory  *)
  303.     mov  ax,Y1              (*top rectangle scan line                   *)
  304.     mov  si,ax
  305.     and  si,011b                  (*top rect scan line modulo 4         *)
  306.     add  si,PATTERN_BUFFER        (*point to pattern scan line that     *)
  307.                                       (* maps to top line of rect to draw   *)
  308.     mov  dx,ScrnLogicalByteWidth
  309.     mul  dx                       (*offset in page of top rect scan line*)
  310.     mov  di,X1
  311.     mov  bx,di
  312.     shr  di,1             (*X/4 = offset of first rectangle pixel in scan*)
  313.     shr  di,1             (* line                                       *)
  314.     add  di,ax                    (*offset of first rectangle pixel in page *)
  315.     add  di,ScreenOfs            (*offset of first rectangle pixel in   *)
  316.                                       (* display memory                     *)
  317.     and  bx,0003h                 (*look up left edge plane mask        *)
  318.     mov  ah,[offset LeftClipPlaneMask+bx] (* to clip                    *)
  319.     mov  bx,[X2]
  320.     and  bx,0003h                  (*look up right edge plane           *)
  321.     mov  al,[offset RightClipPlaneMask+bx] (* mask to clip              *)
  322.     mov  bx,ax                     (*put the masks in BX                *)
  323.  
  324.     mov  cx,X2                 (*calculate # of addresses across rect   *)
  325.     mov  ax,X1
  326.     cmp  cx,ax
  327.     jle  @@FillDone                (*skip if 0 or negative width        *)
  328.     dec  cx
  329.     and  ax,not 011b
  330.     sub  cx,ax
  331.     shr  cx,1
  332.     shr  cx,1                 (*# of addresses across rectangle to fill - 1*)
  333.     jnz  @@MasksSet           (*there's more than one pixel to draw     *)
  334.     and  bh,bl                (*there's only one pixel, so combine the left*)
  335.                                   (* and right edge clip masks              *)
  336. @@MasksSet:
  337.     mov  ax,Y2
  338.     sub  ax,Y1          (*AX = height of rectangle                      *)
  339.     jle  @@FillDone           (*skip if 0 or negative height            *)
  340.     mov  Height,ax
  341.     mov  ax,ScrnLogicalByteWidth
  342.     sub  ax,cx                (*distance from end of one scan line to start*)
  343.     dec  ax                   (* of next                                *)
  344.     mov  NextScanOffset,ax
  345.     mov  RectAddrWidth,cx     (*remember width in addresses - 1         *)
  346.     mov  dx,SC_INDEX+1        (*point to Sequence Controller Data reg   *)
  347.                                   (* (SC Index still points to Map Mask)    *)
  348. @@FillRowsLoop:
  349.     mov  cx,RectAddrWidth     (*width across - 1                        *)
  350.     mov  al,es:[si]           (*read display memory to latch this scan  *)
  351.                                   (* line's pattern                         *)
  352.     inc  si                   (*point to the next pattern scan line, wrapping*)
  353.     jnz  @@NoWrap             (* back to the start of the pattern if    *)
  354.     sub  si,4                 (* we've run off the end                  *)
  355. @@NoWrap:
  356.     mov  al,bh                (*put left-edge clip mask in AL           *)
  357.     out  dx,al                (*set the left-edge plane (clip) mask     *)
  358.         stosb                     (*draw the left edge (pixels come from latches *)
  359.                                   (* value written by CPU doesn't matter)   *)
  360.     dec  cx                   (*count off left edge address             *)
  361.     js   @@FillLoopBottom     (*that's the only address                 *)
  362.     jz   @@DoRightEdge        (*there are only two addresses            *)
  363.     mov  al,00fh              (*middle addresses drawn 4 pixels at a pop*)
  364.     out  dx,al                (*set middle pixel mask to no clip        *)
  365.     rep  stosb                (*draw middle addresses four pixels apiece*)
  366.                                   (* (from latches(* value written doesn't matter)*)
  367. @@DoRightEdge:
  368.     mov  al,bl                (*put right-edge clip mask in AL          *)
  369.     out  dx,al                (*set the right-edge plane (clip) mask    *)
  370.         stosb                     (*draw the right edge (from latches(* value*)
  371.                                   (* written doesn't matter)                *)
  372. @@FillLoopBottom:
  373.     add  di,NextScanOffset    (*point to the start of the next scan     *)
  374.                   (* line of the rectangle                  *)
  375.     dec  word ptr Height      (*count down scan lines                   *)
  376.     jnz  @@FillRowsLoop
  377. @@FillDone:
  378.     mov  dx,GC_INDEX+1        (*restore the bit mask to its default,    *)
  379.     mov  al,0ffh              (* which selects all bits from the CPU    *)
  380.     out  dx,al                (* and none from the latches (the GC      *)
  381. end;
  382.  
  383. procedure x_rect_pattern_clipped(X1,Y1,X2,Y2:Word;Var Pattern); assembler;
  384. var NextScanOffset,RectAddrWidth,Height:Word;
  385. asm
  386. {ARG     StartX:word,StartY:word,EndX:word,EndY:word,PageBase:word,Pattern:dword}
  387.     push si                      (*preserve caller's register variables *)
  388.     push di
  389.     push ds
  390.  
  391.     mov   dx,[TopClip]           (* Compare u.l. Y coord with Top       *)
  392.     mov   cx,[BottomClip]
  393.     mov   ax,[Y1]
  394.     mov   bx,[Y2]
  395.     cmp   dx,ax
  396.     jle   @@CheckBottomClip
  397.     cmp   dx,bx
  398.     jg    @@NotVisible
  399.     mov   [Y1],dx
  400.  
  401. @@CheckBottomClip:
  402.     cmp   cx,bx
  403.     jg    @@CheckLeftClip
  404.     cmp   cx,ax
  405.     jl    @@NotVisible
  406.     mov   [Y2],cx
  407.  
  408. @@CheckLeftClip:
  409.     mov   dx,[LeftClip]           (* Compare u.l. Y coord with Top     *)
  410.     mov   cx,[RightClip]
  411.     mov   ax,[X2]
  412.     mov   bx,[X2]
  413.     sal   dx,1
  414.     sal   dx,1
  415.     sal   cx,1
  416.     sal   cx,1
  417.     cmp   dx,ax
  418.     jle   @@CheckRightClip
  419.     cmp   dx,bx
  420.     jg    @@NotVisible
  421.     mov   [X1],dx
  422.  
  423. @@CheckRightClip:
  424.     cmp   cx,bx
  425.     jg    @RPClipDone
  426.     cmp   cx,ax
  427.     jl    @@NotVisible
  428.     mov   [X2],cx
  429.     jmp   @RPClipDone
  430.  
  431. @RPClipDone:
  432.     cld
  433.     mov  ax,SCREEN_SEG            (*point ES to display memory          *)
  434.     mov  es,ax
  435.                       (*copy pattern to display memory buffer *)
  436.     lds  si,dword ptr [Pattern]   (*point to pattern to fill with       *)
  437.     mov  di,PATTERN_BUFFER        (*point ES:DI to pattern buffer       *)
  438.     mov  dx,SC_INDEX              (*point Sequence Controller Index to  *)
  439.     mov  al,MAP_MASK              (* Map Mask                           *)
  440.     out  dx,al
  441.     inc  dx                       (*point to SC Data register           *)
  442.     mov  cx,4                     (*4 pixel quadruplets in pattern      *)
  443. @@DownloadPatternLoop:
  444.     mov  al,1                     (*                                    *)
  445.     out  dx,al                    (*select plane 0 for writes           *)
  446.         movsb                         (*copy over next plane 0 pattern pixel*)
  447.     dec  di                       (*stay at same address for next plane *)
  448.     mov  al,2                     (*                                    *)
  449.     out  dx,al                    (*select plane 1 for writes           *)
  450.     movsb                         (*copy over next plane 1 pattern pixel*)
  451.     dec  di                       (*stay at same address for next plane *)
  452.     mov  al,4                     (*                                    *)
  453.     out  dx,al                    (*select plane 2 for writes           *)
  454.         movsb                         (*copy over next plane 2 pattern pixel*)
  455.     dec  di                       (*stay at same address for next plane *)
  456.     mov  al,8                     (*                                    *)
  457.     out  dx,al                    (*select plane 3 for writes           *)
  458.         movsb                         (*copy over next plane 3 pattern pixel*)
  459.                                       (* and advance address                *)
  460.         loop @@DownloadPatternLoop
  461.         pop  ds
  462.  
  463.     mov  dx,GC_INDEX              (*set the bit mask to select all bits *)
  464.     mov  ax,00000h+BIT_MASK       (* from the latches and none from     *)
  465.     out  dx,ax                    (* the CPU, so that we can write the  *)
  466.                                       (* latch contents directly to memory  *)
  467.     mov  ax,[Y1]              (*top rectangle scan line             *)
  468.     mov  si,ax
  469.     and  si,011b                  (*top rect scan line modulo 4         *)
  470.     add  si,PATTERN_BUFFER        (*point to pattern scan line that     *)
  471.                       (* maps to top line of rect to draw   *)
  472.     mov  dx,[ScrnLogicalByteWidth]
  473.     mul  dx                       (*offset in page of top rect scan line*)
  474.     mov  di,[X1]
  475.     mov  bx,di
  476.     sar  di,1             (*X/4 = offset of first rectangle pixel in scan *)
  477.     sar  di,1
  478.     add  di,ax                    (*offset of first rectangle pixel in page *)
  479.     add  di,[ScreenOfs]            (*offset of first rectangle pixel in  *)
  480.                                       (* display memory                     *)
  481.     and  bx,0003h                 (*look up left edge plane mask        *)
  482.     mov  ah,[offset LeftClipPlaneMask+bx] (* to clip                            *)
  483.     mov  bx,[X2]
  484.     and  bx,0003h                  (*look up right edge plane           *)
  485.     mov  al,[offset RightClipPlaneMask+bx] (* mask to clip                      *)
  486.     mov  bx,ax                     (*put the masks in BX                *)
  487.  
  488.     mov  cx,[X2]                 (*calculate # of addresses across rect *)
  489.     mov  ax,[X1]
  490.     cmp  cx,ax
  491.     jle  @@FillDone                (*skip if 0 or negative width        *)
  492.     dec  cx
  493.     and  ax,not 011b
  494.     sub  cx,ax
  495.     sar  cx,1                 (*# of addresses across rectangle to fill - 1 *)
  496.     sar  cx,1
  497.     jnz  @@MasksSet           (*there's more than one pixel to draw     *)
  498.     and  bh,bl                (*there's only one pixel, so combine the left *)
  499.                                   (* and right edge clip masks              *)
  500. @@MasksSet:
  501.     mov  ax,[Y2]
  502.     sub  ax,[Y1]              (*AX = height of rectangle                *)
  503.     jle  @@FillDone           (*skip if 0 or negative height            *)
  504.     mov  [Height],ax
  505.     mov  ax,[ScrnLogicalByteWidth]
  506.     sub  ax,cx                (*distance from end of one scan line to start *)
  507.     dec  ax                   (* of next                                *)
  508.     mov  [NextScanOffset],ax
  509.     mov  [RectAddrWidth],cx   (*remember width in addresses - 1         *)
  510.     mov  dx,SC_INDEX+1        (*point to Sequence Controller Data reg   *)
  511.                                   (* (SC Index still points to Map Mask)    *)
  512. @@FillRowsLoop:
  513.     mov  cx,[RectAddrWidth]   (*width across - 1                        *)
  514.     mov  al,es:[si]           (*read display memory to latch this scan  *)
  515.                                   (* line's pattern                         *)
  516.     inc  si                   (*point to the next pattern scan line, wrapping *)
  517.     jnz  @@NoWrap             (* back to the start of the pattern if    *)
  518.     sub  si,4                 (* we've run off the end                  *)
  519. @@NoWrap:
  520.     mov  al,bh                (*put left-edge clip mask in AL           *)
  521.     out  dx,al                (*set the left-edge plane (clip) mask     *)
  522.         stosb                     (*draw the left edge (pixels come from latches; *)
  523.                                   (* value written by CPU doesn't matter)   *)
  524.     dec  cx                   (*count off left edge address             *)
  525.     js   @@FillLoopBottom     (*that's the only address                 *)
  526.     jz   @@DoRightEdge        (*there are only two addresses            *)
  527.     mov  al,00fh              (*middle addresses drawn 4 pixels at a pop*)
  528.     out  dx,al                (*set middle pixel mask to no clip        *)
  529.     rep  stosb                (*draw middle addresses four pixels apiece*)
  530.                                   (* (from latches; value written doesn't matter) *)
  531. @@DoRightEdge:
  532.     mov  al,bl                (*put right-edge clip mask in AL          *)
  533.     out  dx,al                (*set the right-edge plane (clip) mask    *)
  534.         stosb                     (*draw the right edge (from latches(* value *)
  535.                                   (* written doesn't matter)                *)
  536. @@FillLoopBottom:
  537.     add  di,[NextScanOffset]  (*point to the start of the next scan     *)
  538.                   (* line of the rectangle                  *)
  539.     dec  word ptr [Height]    (*count down scan lines                   *)
  540.     jnz  @@FillRowsLoop
  541. @@FillDone:
  542.     mov  dx,GC_INDEX+1        (*restore the bit mask to its default,    *)
  543.     mov  al,0ffh              (* which selects all bits from the CPU    *)
  544.     out  dx,al                (* and none from the latches (the GC      *)
  545.                   (* Index still points to Bit Mask)        *)
  546.  
  547. @@NotVisible:
  548.     mov   ax,1
  549.     pop   ds
  550.     pop   di                          (* restore registers             *)
  551.     pop   si
  552. end;
  553.  
  554. (* ----------------------------------------------------------------------- *)
  555. (* Mode X (320x240, 256 colors) display memory to display memory copy      *)
  556. (* routine. Left edge of source rectangle modulo 4 must equal left edge    *)
  557. (* of destination rectangle modulo 4. Works on all VGAs. Uses approach     *)
  558. (* of reading 4 pixels at a time from the source into the latches, then    *)
  559. (* writing the latches to the destination. Copies up to but not            *)
  560. (* including the column at SrcX2 and the row at SrcY2. No clipping is      *)
  561. (* performed. Results are not guaranteed if the source and destination     *)
  562. (* overlap.                                                                *)
  563. (*                                                                         *)
  564. (* ! All X,Y-Values are not at active_screen, they are absolut !           *)
  565. {
  566. (*C near-callable as:
  567. (*    void x_cp_vid_rect(int SrcStartX, int SrcStartY,
  568. (*       int SrcEndX, int SrcEndY, int DestStartX,
  569. (*       int DestStartY, unsigned int SrcPageBase,
  570. (*       unsigned int DestPageBase, int SrcBitmapWidth,
  571. (*       int DestBitmapWidth);
  572.  }
  573. procedure x_cp_vid_rect(SrcX1,SrcY1,SrcX2,ScrY2,DestX1,DestY1:Word);
  574.                       { SrcBitmapW,DestBitmapW:word);} assembler;
  575. {ARG SrcStartX:word,SrcStartY:word,SrcEndX:word,SrcEndY:word,DestStartX:word,DestStartY:word,SrcPageBase:word,DestPageBase:word
  576.  ,SrcBitmapW:word,DestBitmapW:word}
  577. var SrcNextOffs,DestNextOffs,RectAddrW,Height:Word;
  578. asm
  579.         push    ds
  580.  
  581.         cld
  582.     mov     dx,GC_INDEX         (*set the bit mask to select all bits   *)
  583.     mov     ax,00000h+BIT_MASK  (* from the latches and none from       *)
  584.     out dx,ax                   (* the CPU, so that we can write the    *)
  585.                     (* latch contents directly to memory    *)
  586.     mov     ax,SCREEN_SEG       (*point ES to display memory            *)
  587.         mov     es,ax
  588.     mov     ax,ScrnLogicalPixelWidth
  589.     shr     ax,1;shr ax,1       (*convert to width in addresses         *)
  590.     mul     DestY1              (*top dest rect scan line               *)
  591.     mov     di,DestX1
  592.     shr     di,1;shr di,1       (*X/4 = offset of first dest rect pixel in *)
  593.                     (* scan line                            *)
  594.     add     di,ax               (*offset of first dest rect pixel       *)
  595.                     (* in display memory                    *)
  596.     mov     ax,ScrnLogicalPixelWidth
  597.     shr     ax,1;shr ax,1       (*convert to width in addresses         *)
  598.     mul     SrcY1         (*top source rect scan line                   *)
  599.     mov     si,SrcX1
  600.         mov     bx,si
  601.     shr     si,1;shr si,1     (*X/4 = offset of first source rect pixel in *)
  602.                   (* scan line                              *)
  603.     add     si,ax             (*offset of first source rect             *)
  604.                   (* pixel in display memory                *)
  605.     and     bx,0003h                     (*look up left edge plane mask *)
  606.     mov     ah,[offset LeftClipPlaneMask+bx]  (* to clip                *)
  607.     mov     bx,[SrcX2]
  608.     and     bx,0003h                     (*look up right edge plane     *)
  609.     mov     al,[offset RightClipPlaneMask+bx] (* mask to clip           *)
  610.     mov     bx,ax                        (*put the masks in BX          *)
  611.  
  612.     mov     cx,SrcX2              (*calculate # of addresses across     *)
  613.     mov     ax,SrcX1            (* rect                                 *)
  614.         cmp     cx,ax
  615.     jle     @@CopyDone                   (*skip if 0 or negative width  *)
  616.         dec     cx
  617.         and     ax,not 011b
  618.         sub     cx,ax
  619.     shr     cx,1;shr cx,1    (*# of addresses across rectangle to copy - 1*)
  620.     jnz     @@MasksSet       (*there's more than one address to draw    *)
  621.     and     bh,bl            (*there's only one address, so combine the left*)
  622.                  (* and right edge clip masks               *)
  623. @@MasksSet:
  624.     mov     ax,ScrY2
  625.     sub     ax,SrcY1         (* AX = height of rectangle                *)
  626.     jle     @@CopyDone       (*skip if 0 or negative height             *)
  627.     mov     Height,ax
  628.     mov     ax,ScrnLogicalPixelWidth
  629.     shr     ax,1;shr ax,1    (*convert to width in addresses            *)
  630.     sub     ax,cx            (*distance from end of one dest scan line  *)
  631.     dec     ax               (* to start of next                        *)
  632.     mov     DestNextOffs,ax
  633.     mov     ax,ScrnLogicalPixelWidth
  634.     shr     ax,1;shr ax,1    (*convert to width in addresses            *)
  635.     sub     ax,cx            (*distance from end of one source scan line*)
  636.     dec     ax               (* to start of next                        *)
  637.     mov     SrcNextOffs,ax
  638.     mov     RectAddrW,cx     (*remember width in addresses - 1          *)
  639.     mov     dx,SC_INDEX+1    (*point to Sequence Controller Data reg    *)
  640.                  (* (SC Index still points to Map Mask)     *)
  641.     mov     ax,es            (*DS=ES=screen segment for MOVS            *)
  642.         mov     ds,ax
  643. @@CopyRowsLoop:
  644.     mov     cx,RectAddrW       (*width across - 1                       *)
  645.     mov     al,bh              (*put left-edge clip mask in AL          *)
  646.     out     dx,al              (*set the left-edge plane (clip) mask    *)
  647.     movsb                      (*copy the left edge (pixels go through  *)
  648.                    (* latches)                              *)
  649.     dec     cx                 (*count off left edge address            *)
  650.     js      @@CopyLoopBottom   (*that's the only address                *)
  651.     jz      @@DoRightEdge      (*there are only two addresses           *)
  652.     mov     al,00fh            (*middle addresses are drawn 4 pix per go*)
  653.     out     dx,al              (*set the middle pixel mask to no clip   *)
  654.     rep     movsb              (*draw the middle addresses four pix per go *)
  655.                    (* (pixels copied through latches)       *)
  656. @@DoRightEdge:
  657.         mov     al,bl   (*put right-edge clip mask in AL                    *)
  658.         out     dx,al   (*set the right-edge plane (clip) mask              *)
  659.         movsb           (*draw the right edge (pixels copied through        *)
  660.                         (* latches)                                         *)
  661. @@CopyLoopBottom:
  662.     add     si,SrcNextOffs   (*point to the start of                    *)
  663.     add     di,DestNextOffs  (* next source & dest lines                *)
  664.     dec     word ptr Height  (*count down scan lines                    *)
  665.     jnz     @@CopyRowsLoop
  666. @@CopyDone:
  667.     mov     dx,GC_INDEX+1   (*restore the bit mask to its default,      *)
  668.         mov     al,0ffh         (* which selects all bits from the CPU      *)
  669.         out     dx,al           (* and none from the latches (the GC        *)
  670.                                 (* Index still points to Bit Mask)          *)
  671.         pop     ds
  672. end;
  673. (*                                                                          *)
  674. (* Copy a rectangular region of a VGA screen, with x coordinates            *)
  675. (* rounded to the nearest byte -- source and destination may overlap.       *)
  676. (*                                                                          *)
  677. (*                                                                          *)
  678. (* SrcRight is rounded up, and the left edges are rounded down, to ensure   *)
  679. (* that the pixels pointed to by the arguments are inside the rectangle.    *)
  680. (*                                                                          *)
  681. (* The width of the rectangle in bytes (width in pixels / 4)                *)
  682. (* cannot exceed 255.                                                       *)
  683. (*                                                                          *)
  684.  
  685. procedure x_shift_rect(ScrX1,ScrY1,ScrX2,ScrY2,DestX1,DestY1:Word);assembler;
  686. {ARG     SrcLeft,SrcTop,SrcRight,SrcBottom,DestLeft,DestTop,ScreenOffs:word}
  687. var width_temp:Word;
  688. asm
  689.     push ds
  690.  
  691. (* find values for width & x motion                                         *)
  692.     mov si, ScrX1       (* source x in bytes                            *)
  693.     shr si, 1
  694.         shr si, 1
  695.  
  696.     mov di, DestX1      (* destination x in bytes                       *)
  697.     shr di, 1
  698.     shr di, 1
  699.  
  700.     mov bx, ScrX2       (* right edge of source in bytes, rounded up    *)
  701.     add bx, 3
  702.     shr bx, 1
  703.     shr bx, 1
  704.     sub bx, si
  705.     mov ax, bx          (* width - 1                                    *)
  706.     inc bx              (* we'll use this as an offset for moving up or down *)
  707.     mov width_temp, bx
  708.  
  709.     cld                 (* by default, strings increment                *)
  710.  
  711.     cmp si, di
  712.     jge @@MovingLeft
  713.  
  714. (* we're moving our rectangle right, so we copy it from right to left       *)
  715.     add si, ax          (* source & destination will start on the right edge *)
  716.     add di, ax
  717.     neg bx
  718.     std                 (* strings decrement                            *)
  719.  
  720. @@MovingLeft:
  721.  
  722. (* find values for height & y motion                                        *)
  723.     mov cx, ScrnLogicalByteWidth (* bytes to move to advance one line   *)
  724.     mov ax, ScrY1
  725.     mov dx, DestY1      (* default destination y                        *)
  726.     cmp ax, dx
  727.     jge @@MovingUp
  728.  
  729. (* we're moving our rectangle down, so we copy it from bottom to top        *)
  730.     mov ax, ScrY2       (* source starts at bottom                      *)
  731.     add dx, ax          (* add (height - 1) to destination y            *)
  732.     sub dx, ScrY1
  733.     neg cx              (* advance up screen rather than down           *)
  734.  
  735. @@MovingUp:
  736.     push dx             (* save destination y during multiply           *)
  737.     mul ScrnLogicalByteWidth
  738.     add si, ax          (* add y in bytes to source                     *)
  739.     pop ax              (* restore destination y                        *)
  740.     mul ScrnLogicalByteWidth
  741.     add di, ax          (* add y in bytes to destination                *)
  742.  
  743.     sub cx, bx          (* final value for moving up or down            *)
  744.  
  745.     add si, ScreenOfs   (* source & destination are on the same screen  *)
  746.     add di, ScreenOfs
  747.  
  748.     mov dx, SC_INDEX    (* set map mask to all four planes              *)
  749.     mov ax, 00f02h
  750.     out dx, ax
  751.  
  752.     mov dx, GC_INDEX    (* set bit mask to take data from latches       *)
  753.     mov ax, BIT_MASK    (*  rather than CPU                             *)
  754.     out dx, ax
  755.  
  756.     mov ax, SCREEN_SEG  (* source and destination are VGA memory        *)
  757.     mov es, ax
  758.     mov ds, ax
  759.  
  760.     mov ah, byte ptr width_temp (* width in bytes should fit in 8 bits  *)
  761.  
  762.     mov bx, ScrY2       (* height - 1                                   *)
  763.     sub bx, ScrY1
  764.  
  765.     mov dx, cx          (* bytes to add to advance one line             *)
  766.  
  767.     xor ch, ch          (* ready to rock                                *)
  768.  
  769. @@LineLoop:
  770.     mov cl, ah          (* load width in bytes                          *)
  771.     rep movsb           (* move 4 pixels at a time using latches (YOW!) *)
  772.  
  773.     add si, dx          (* advance source by one line                   *)
  774.     add di, dx          (* advance destination by one line              *)
  775.  
  776.     dec bx              (* line counter                                 *)
  777.     jge @@LineLoop      (* 0 still means one more to go                 *)
  778.  
  779.     mov dx, GC_INDEX + 1(* set bit mask to take data from CPU (normal setting) *)
  780.     mov al, 0ffh
  781.     out dx, al
  782.  
  783. (* kick *)
  784.     pop ds
  785. end;
  786.  
  787. end.
  788.  
  789.