home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / msdos / asm / 3dvect25 / xscale.inc < prev    next >
Encoding:
Text File  |  1993-07-04  |  25.4 KB  |  561 lines

  1. ;=========================================================================
  2. ; XSCALE1.ASM by John A. Slagel, jas37876@uxa.cso.uiuc.edu
  3. ; This is some code to do bitmap scaling in VGA Mode X.  It can scale a
  4. ; bitmap of any size down to 2 pixels wide, or up to thousands of pixels
  5. ; wide.  It performs complete clipping, with only a small constant amount
  6. ; of time to clip, no matter how huge the image is.  It draws column by
  7. ; column to reduce the number of plane switches, which are slow. The inner
  8. ; column loop has been optimized for no memory accesses, except to read or
  9. ; write a pixel.  This uses MASM 5.1 features, and can be compiled in any
  10. ; memory model by changing the .MODEL line, but make sure that you always
  11. ; pass a far pointer to the bitmap data, regardless of memory model.
  12. ; C-callable as:
  13. ;   void XSCALE1( int X, int Y, int DW, int DY,
  14. ;                     int SW, int SH, void far * Bitmap );
  15. ; X,Y   are the upper left-hand coordinates of where to draw the bitmap.
  16. ; DW,DH are the width and height of the SCALEed bitmap
  17. ; SW,SH are the width and height of the source bitmap.
  18. ; Bitmap is a pointer to the bitmap bits.
  19. ;
  20. ; Routine has been modified for 32 bit protected mode by John McCarthy.
  21. ; John McCarthy thanks John A. Slagel for providing this code, and hopes
  22. ; John A. Slagel is not offended by the changes.
  23. ;
  24. ;==========================================================================
  25.  
  26.             public draw_scale
  27.             public tdraw_scale
  28.             public xscale1
  29.             public xscale2
  30.             public repeat_bitmap
  31.  
  32. ; uses edi esi, destx:word, desty:word,
  33. ; destwidth:word, destheight:word,
  34. ; sourcewidth:word, sourceheight:word,
  35. ; bitmap:far ptr
  36.  
  37. draw_scale:
  38.         mov bitmap,esi
  39.         mov destwidth,ax
  40.         mov destheight,bx
  41.         mov destx,cx
  42.         mov desty,dx
  43.  
  44. xscale1:
  45.         cmp     destwidth, 2        ; if destination width is less than 2
  46.         jl      done                ;     then don't draw it.
  47.  
  48.         cmp     destheight, 2       ; if destination height is less than 2
  49.         jl      done                ;     then don't draw it.
  50.  
  51.         mov     ax, desty           ; if it is completely below the
  52.         cmp     ax, clipbt          ; lower clip bondry,
  53.         jg      done                ;     then don't draw it.
  54.  
  55.         add     ax, destheight      ; if it is above clip boundries
  56.         dec     ax                  ;     then don't draw it.
  57.         cmp     ax, cliptp
  58.         jl      done
  59.  
  60.         mov     ax, destx           ; if it is to the right of the
  61.         mov     cx, cliprt          ; right clip boundry
  62.         cmp     ax, cliprt          ;     then don't draw it.
  63.         jg      done
  64.  
  65.         add     ax, destwidth       ; if it is completely to the left
  66.         dec     ax                  ; of the left clip boundry,
  67.         cmp     ax, cliplt          ;     then don't draw it.
  68.         jl      done
  69.  
  70.         mov     esi, bitmap         ; make esi point to bitmap data
  71.         lodsw                       ; get source x width
  72.         mov     sourcewidth,ax
  73.         lodsw                       ; get source y height
  74.         mov     sourceheight,ax
  75.  
  76.         mov     ax, destwidth       ; clippedwidth is initially set to
  77.         mov     clippedwidth, ax    ; the requested dest width.
  78.  
  79.         shl     ax,1                ; initialize the x decision var
  80.         neg     ax                  ; to be -2*destwidth
  81.         mov     decisionx, ax       ;
  82.  
  83.         mov     ax, destheight      ; clippedheight is initially set to
  84.         mov     clippedheight, ax   ; the requested dest size.
  85.  
  86.         shl     ax,1                ; initialize the y decision var
  87.         neg     ax                  ; to be -2*destheight
  88.         mov     decisiony, ax       ;
  89.  
  90.         movsx   eax, cliptp         ; if y is below the top
  91.         mov     edx, eax            ; clipping boundry, then we don't
  92.         sub     dx, desty           ; need to clip the top, so we can
  93.         js      s notopclip         ; jump over the clipping stuff.
  94.  
  95.         mov     desty, ax           ; this block performs clipping on the
  96.         sub     clippedheight, dx   ; top of the bitmap.  i have heavily
  97.         movsx   ecx, sourceheight   ; optimized this block to use only 4
  98.         imul    ecx, edx            ; 32-bit registers, so i'm not even
  99.         mov     eax, ecx            ; gonna try to explain what it's doing.
  100.         cdq                         ; but i can tell you what results from
  101.         movsx   ebx, destheight     ; this:  the decisiony var is updated
  102.         idiv    ebx                 ; to start at the right clipped row.
  103.         movsx   edx, sourcewidth    ; y is moved to the top clip
  104.         imul    edx, eax            ; boundry. clippedheight is lowered since
  105.         add     esi, edx            ; we won't be drawing all the requested
  106.         imul    eax, ebx            ; rows. esi is changed to point over
  107.         sub     ecx, eax            ; the bitmap data that is clipped off.
  108.         sub     ecx, ebx            ;
  109.         shl     ecx, 1              ;
  110.         mov     decisiony, cx       ; <end of top clipping block >
  111.  
  112. notopclip:
  113.         mov     ax, desty           ; if the bitmap doesn't extend over the
  114.         add     ax, clippedheight   ; bottom clipping boundry, then we
  115.         dec     ax                  ; don't need to clip the bottom, so we
  116.         cmp     ax, clipbt          ; can jump over the bottom clip code.
  117.         jle     s nobottomclip      ;
  118.  
  119.         mov     ax, clipbt          ; clip off the bottom by reducing the
  120.         sub     ax, desty           ; clippedheight so that the bitmap won't
  121.         inc     ax                  ; extend over the lower clipping
  122.         mov     clippedheight, ax   ; boundry.
  123.  
  124. nobottomclip:
  125.         movsx   eax, cliplt         ; if x is to the left of the
  126.         mov     edx, eax            ; top clipping boundry, then we don't
  127.         sub     dx, destx           ; need to clip the left, so we can
  128.         js      s noleftclip        ; jump over the clipping stuff.
  129.  
  130.         mov     destx, ax           ; this block performs clipping on the
  131.         sub     clippedwidth, dx    ; left of the bitmap.  i have heavily
  132.         movsx   ecx, sourcewidth    ; optimized this block to use only 4
  133.         imul    ecx, edx            ; 32-bit registers, so i'm not even
  134.         mov     eax, ecx            ; gonna try to explain what it's doing.
  135.         cdq                         ; but i can tell you what results from
  136.         movsx   ebx, destwidth      ; this:  the decisionx var is updated
  137.         idiv    ebx                 ; to start at the right clipped column.
  138.         add     esi, eax            ; x is moved to the left clip
  139.         imul    eax, ebx            ; boundry. clippedwidth is reduced since
  140.         sub     ecx, eax            ; we won't be drawing all the requested
  141.         sub     ecx, ebx            ; cols. esi is changed to point over
  142.         shl     ecx, 1              ; the bitmap data that is clipped off.
  143.         mov     decisionx, cx       ; <end of left clipping block >
  144.  
  145. noleftclip:
  146.         mov     ax, destx           ; if the bitmap doesn't extend over the
  147.         add     ax, clippedwidth    ; right clipping boundry, then we
  148.         dec     ax                  ; don't need to clip the right, so we
  149.         cmp     ax, cliprt          ; can jump over the right clip code.
  150.         jle     s noclipright       ;
  151.  
  152.         mov     ax, cliprt          ; clip off the right by reducing the
  153.         sub     ax, destx           ; clippedwidth so that the bitmap won't
  154.         inc     ax                  ; extend over the right clipping
  155.         mov     clippedwidth, ax    ; boundry.
  156.  
  157.         ;calculate starting video address
  158. noclipright:
  159.         movzx   edi, desty          ; we are going to set edi to start point
  160.         imul    edi, xactual/4
  161.         movzx   eax, destx          ; the offset edi is
  162.         mov     cx, ax              ; calculated by:
  163.         shr     ax, 2               ;     di = y*80+x/2
  164.         add     eax, current_page
  165.         add     edi,eax             ; edi is ready!
  166.  
  167.         mov     dx, sc_index        ; point the vga sequencer to the map
  168.         mov     al, map_mask        ; mask register, so that we only need
  169.         out     dx, al              ; to send out 1 byte per column.
  170.  
  171.         inc     dx                  ; move to the sequencer's data register.
  172.         and     cx, 3               ; calculate the starting plane. this is
  173.         mov     al, 11h             ; just:
  174.         shl     al, cl              ; plane =  (11h << (x and 3))
  175.         out     dx, al              ; select the first plane.
  176.  
  177.         movzx   ecx, sourcewidth     ; use cx for source width
  178.         mov     xad, ecx
  179.  
  180.         align   4                   ; since this point gets jumped to a lot,
  181.                                     ; make sure that it is dword aligned.
  182. rowloop:
  183.         push    esi                 ; save the starting source index
  184.         push    edi                 ; save the starting dest index
  185.         push    ax                  ; save the current plane mask
  186.         push    bp                  ; save the current base pointer
  187.  
  188.         mov     cx, clippedheight   ; use al for row counter (0-239)
  189.         mov     bx, decisiony       ; use bx for decision variable
  190.         mov     dx, sourceheight    ; use dx for source height * 2
  191.         shl     dx, 1
  192.         mov     bp, destheight      ; use bp for dest height * 2
  193.         shl     bp, 1
  194.         mov     ah, [esi]           ; get the first source pixel
  195.  
  196.         align   4                   ; common jump point... align for speed.
  197. columnloop:
  198.         mov     [edi], ah           ; draw a pixel
  199.         dec     cx                  ; decrement line counter
  200.         jz      s donewithcol       ; see if we're done with this column
  201.         add     edi, xactual/4      ; go on to the next screen row
  202.         add     bx, dx              ; increment the decision variable
  203.         js      s columnloop        ; draw this source pixel again
  204.  
  205. incsourcerow:
  206.         add     esi, xad            ; move to the next source pixel
  207.         sub     bx, bp              ; decrement the decision variable
  208.         jns     s incsourcerow      ; see if we need to skip another source pixel
  209.         mov     ah, [esi]           ; get the next source pixel
  210.         jmp     s columnloop        ; start drawing this pixel
  211.  
  212. donewithcol:
  213.         pop     bp                  ; restore bp to access variables
  214.         pop     ax                  ; restore al = plane mask
  215.         pop     edi                 ; restore di to top row of screen
  216.         pop     esi                 ; restore si to top row of source bits
  217.  
  218.         rol     al, 1               ; move to next plane
  219.         adc     edi, 0              ; go on to next screen column
  220.         mov     dx, sc_data         ; tell the vga what column we're in
  221.         out     dx, al              ; by updating the map mask register
  222.  
  223.         mov     bx, decisionx       ; use bx for the x decision variable
  224.         add     bx, sourcewidth     ; increment the x decision variable
  225.         add     bx, sourcewidth
  226.         js      s nextcol           ; jump if we're still in the same source col.
  227.         mov     dx, destwidth       ; dx = w * 2
  228.         shl     dx, 1
  229. incsourcecol:
  230.         inc     esi                 ; move to next source column
  231.         sub     bx, dx              ; decrement x decision variable
  232.         jns     s incsourcecol      ; see if we skip another source column
  233. nextcol:
  234.         mov     decisionx, bx       ; free up bx for colloop
  235.         dec     clippedwidth        ; if we're not at last column
  236.         jnz     rowloop             ;    then do another column
  237. done:
  238.         ret                         ; we're done!
  239.  
  240. ; draw transparent bitmap.  any bytes that = 0 are skipped
  241.  
  242. tdraw_scale:
  243.         mov bitmap,esi
  244.         mov destwidth,ax
  245.         mov destheight,bx
  246.         mov destx,cx
  247.         mov desty,dx
  248.  
  249. xscale2:
  250.         cmp     destwidth, 2        ; if destination width is less than 2
  251.         jl      s done              ;     then don't draw it.
  252.  
  253.         cmp     destheight, 2       ; if destination height is less than 2
  254.         jl      s done              ;     then don't draw it.
  255.  
  256.         mov     ax, desty           ; if it is completely below the
  257.         cmp     ax, clipbt          ; lower clip bondry,
  258.         jg      s done              ;     then don't draw it.
  259.  
  260.         add     ax, destheight      ; if it is above clip boundries
  261.         dec     ax                  ;     then don't draw it.
  262.         cmp     ax, cliptp
  263.         jl      s done
  264.  
  265.         mov     ax, destx           ; if it is to the right of the
  266.         mov     cx, cliprt          ; right clip boundry
  267.         cmp     ax, cliprt          ;     then don't draw it.
  268.         jg      s done
  269.  
  270.         add     ax, destwidth       ; if it is completely to the left
  271.         dec     ax                  ; of the left clip boundry,
  272.         cmp     ax, cliplt          ;     then don't draw it.
  273.         jl      s done
  274.  
  275.         mov     esi, bitmap         ; make esi point to bitmap data
  276.         lodsw                       ; get source x width
  277.         mov     sourcewidth,ax
  278.         lodsw                       ; get source y height
  279.         mov     sourceheight,ax
  280.  
  281.         mov     ax, destwidth       ; clippedwidth is initially set to
  282.         mov     clippedwidth, ax    ; the requested dest width.
  283.  
  284.         shl     ax,1                ; initialize the x decision var
  285.         neg     ax                  ; to be -2*destwidth
  286.         mov     decisionx, ax       ;
  287.  
  288.         mov     ax, destheight      ; clippedheight is initially set to
  289.         mov     clippedheight, ax   ; the requested dest size.
  290.  
  291.         shl     ax,1                ; initialize the y decision var
  292.         neg     ax                  ; to be -2*destheight
  293.         mov     decisiony, ax       ;
  294.  
  295.         movsx   eax, cliptp         ; if y is below the top
  296.         mov     edx, eax            ; clipping boundry, then we don't
  297.         sub     dx, desty           ; need to clip the top, so we can
  298.         js      s notopclip2        ; jump over the clipping stuff.
  299.  
  300.         mov     desty, ax           ; this block performs clipping on the
  301.         sub     clippedheight, dx   ; top of the bitmap.  i have heavily
  302.         movsx   ecx, sourceheight   ; optimized this block to use only 4
  303.         imul    ecx, edx            ; 32-bit registers, so i'm not even
  304.         mov     eax, ecx            ; gonna try to explain what it's doing.
  305.         cdq                         ; but i can tell you what results from
  306.         movsx   ebx, destheight     ; this:  the decisiony var is updated
  307.         idiv    ebx                 ; to start at the right clipped row.
  308.         movsx   edx, sourcewidth    ; y is moved to the top clip
  309.         imul    edx, eax            ; boundry. clippedheight is lowered since
  310.         add     esi, edx            ; we won't be drawing all the requested
  311.         imul    eax, ebx            ; rows. esi is changed to point over
  312.         sub     ecx, eax            ; the bitmap data that is clipped off.
  313.         sub     ecx, ebx            ;
  314.         shl     ecx, 1              ;
  315.         mov     decisiony, cx       ; <end of top clipping block >
  316.  
  317. notopclip2:
  318.         mov     ax, desty           ; if the bitmap doesn't extend over the
  319.         add     ax, clippedheight   ; bottom clipping boundry, then we
  320.         dec     ax                  ; don't need to clip the bottom, so we
  321.         cmp     ax, clipbt          ; can jump over the bottom clip code.
  322.         jle     s nobottomclip2
  323.  
  324.         mov     ax, clipbt          ; clip off the bottom by reducing the
  325.         sub     ax, desty           ; clippedheight so that the bitmap won't
  326.         inc     ax                  ; extend over the lower clipping
  327.         mov     clippedheight, ax   ; boundry.
  328.  
  329. nobottomclip2:
  330.         movsx   eax, cliplt         ; if x is to the left of the
  331.         mov     edx, eax            ; top clipping boundry, then we don't
  332.         sub     dx, destx           ; need to clip the left, so we can
  333.         js      s noleftclip2       ; jump over the clipping stuff.
  334.  
  335.         mov     destx, ax           ; this block performs clipping on the
  336.         sub     clippedwidth, dx    ; left of the bitmap.  i have heavily
  337.         movsx   ecx, sourcewidth    ; optimized this block to use only 4
  338.         imul    ecx, edx            ; 32-bit registers, so i'm not even
  339.         mov     eax, ecx            ; gonna try to explain what it's doing.
  340.         cdq                         ; but i can tell you what results from
  341.         movsx   ebx, destwidth      ; this:  the decisionx var is updated
  342.         idiv    ebx                 ; to start at the right clipped column.
  343.         add     esi, eax            ; x is moved to the left clip
  344.         imul    eax, ebx            ; boundry. clippedwidth is reduced since
  345.         sub     ecx, eax            ; we won't be drawing all the requested
  346.         sub     ecx, ebx            ; cols. esi is changed to point over
  347.         shl     ecx, 1              ; the bitmap data that is clipped off.
  348.         mov     decisionx, cx       ; <end of left clipping block >
  349.  
  350. noleftclip2:
  351.         mov     ax, destx           ; if the bitmap doesn't extend over the
  352.         add     ax, clippedwidth    ; right clipping boundry, then we
  353.         dec     ax                  ; don't need to clip the right, so we
  354.         cmp     ax, cliprt          ; can jump over the right clip code.
  355.         jle     s noclipright2
  356.  
  357.         mov     ax, cliprt          ; clip off the right by reducing the
  358.         sub     ax, destx           ; clippedwidth so that the bitmap won't
  359.         inc     ax                  ; extend over the right clipping
  360.         mov     clippedwidth, ax    ; boundry.
  361.  
  362.         ;calculate starting video address
  363. noclipright2:
  364.         movsx   edi, desty          ; we are going to set edi to start point
  365.         imul    edi, xactual/4
  366.         movsx   eax, destx          ; the offset edi is
  367.         mov     cx, ax              ; calculated by:
  368.         shr     eax, 2              ; edi = y*80+x/2
  369.         add     eax, current_page
  370.         add     edi,eax             ; edi is ready!
  371.  
  372.         mov     dx, sc_index        ; point the vga sequencer to the map
  373.         mov     al, map_mask        ; mask register, so that we only need
  374.         out     dx, al              ; to send out 1 byte per column.
  375.  
  376.         inc     dx                  ; move to the sequencer's data register.
  377.         and     cx, 3               ; calculate the starting plane. this is
  378.         mov     al, 11h             ; just:
  379.         shl     al, cl              ; plane =  (11h << (x and 3))
  380.         out     dx, al              ; select the first plane.
  381.  
  382.         movzx   ecx, sourcewidth     ; use cx for source width
  383.         mov     xad, ecx
  384.  
  385.         align   4                   ; since this point gets jumped to a lot,
  386.                                     ; make sure that it is dword aligned.
  387. rowloop2:
  388.         push    esi                 ; save the starting source index
  389.         push    edi                 ; save the starting dest index
  390.         push    ax                  ; save the current plane mask
  391.         push    bp                  ; save the current base pointer
  392.  
  393.         mov     cx, clippedheight   ; use al for row counter (0-239)
  394.         mov     bx, decisiony       ; use bx for decision variable
  395.         mov     dx, sourceheight    ; use dx for source height * 2
  396.         shl     dx, 1
  397.         mov     bp, destheight      ; use bp for dest height * 2
  398.         shl     bp, 1
  399.         mov     ah, [esi]           ; get the first source pixel
  400.         cmp     ah,0
  401.         je      s null_loop         ; if zero, perform null loop
  402.  
  403.         align   4                   ; common jump point... align for speed.
  404. columnloop2:
  405.         mov     [edi], ah           ; draw a pixel
  406.         dec     cx                  ; decrement line counter
  407.         jz      s donewithcol2      ; see if we're done with this column
  408.         add     edi, xactual/4      ; go on to the next screen row
  409.         add     bx, dx              ; increment the decision variable
  410.         js      s columnloop2       ; draw this source pixel again
  411.  
  412. incsourcerow2:
  413.         add     esi, xad            ; move to the next source pixel
  414.         sub     bx, bp              ; decrement the decision variable
  415.         jns     s incsourcerow2     ; see if we need to skip another source pixel
  416.         mov     ah, [esi]           ; get the next source pixel
  417.         cmp     ah,0
  418.         jz      s null_loop
  419.         jmp     s columnloop2       ; start drawing this pixel
  420.  
  421. donewithcol2:
  422.         pop     bp                  ; restore bp to access variables
  423.         pop     ax                  ; restore al = plane mask
  424.         pop     edi                 ; restore di to top row of screen
  425.         pop     esi                 ; restore si to top row of source bits
  426.  
  427.         rol     al, 1               ; move to next plane
  428.         adc     edi, 0              ; go on to next screen column
  429.         mov     dx, sc_data         ; tell the vga what column we're in
  430.         out     dx, al              ; by updating the map mask register
  431.  
  432.         mov     bx, decisionx       ; use bx for the x decision variable
  433.         add     bx, sourcewidth     ; increment the x decision variable
  434.         add     bx, sourcewidth
  435.         js      s nextcol2          ; jump if we're still in the same source col.
  436.         mov     dx, destwidth       ; dx = w * 2
  437.         shl     dx, 1
  438. incsourcecol2:
  439.         inc     esi                 ; move to next source column
  440.         sub     bx, dx              ; decrement x decision variable
  441.         jns     s incsourcecol2     ; see if we skip another source column
  442. nextcol2:
  443.         mov     decisionx, bx       ; free up bx for colloop
  444.         dec     clippedwidth        ; if we're not at last column
  445.         jnz     rowloop2            ;    then do another column
  446. done2:
  447.         ret                         ; we're done!
  448.  
  449.         align   4                   ; common jump point... align for speed.
  450. null_loop:
  451.         dec     cx                  ; decrement line counter
  452.         jz      s donewithcol2      ; see if we're done with this column
  453.         add     edi, xactual/4      ; go on to the next screen row
  454.         add     bx, dx              ; increment the decision variable
  455.         js      s null_loop         ; perform more increments
  456.         jmp     s incsourcerow2
  457.  
  458. ; draw repeated bit map.  good for backgrounds in menus and title screens.
  459. ; routine is NOT intended for animation because it is slow. uses scale routine
  460. ; because scale routine clips bitmaps.  sloppy routine just draws all over the
  461. ; place and lets the scale clip borders handle the rest.
  462. ;
  463. ; repeat_bitmap (seg bitmap, x1%, y1%, x2%, y2%)
  464. ;
  465. ; remember: first two words of bitmap define width and height
  466.  
  467. rb_stack   struc
  468.      rb_wide    dw  ?   ; height and width of bitmap
  469.      rb_height  dw  ?
  470.      rb_curx    dw  ?   ; current bitmap location
  471.      rb_cury    dw  ?
  472.      rb_oldy2   dw  ?   ; old cliping borders save
  473.      rb_oldx2   dw  ?
  474.      rb_oldy1   dw  ?
  475.      rb_oldx1   dw  ?
  476.                 dd  ?x3 ; edi, esi, ebp
  477.                 dd  ?   ; caller
  478.      rb_y2      dw  ?   ; y2
  479.      rb_x2      dw  ?   ; x2
  480.      rb_y1      dw  ?   ; y1
  481.      rb_x1      dw  ?   ; x1
  482.      rb_bitmap  dd  ?   ; offset to bitmap
  483. rb_stack   ends
  484.  
  485. repeat_bitmap:
  486.            push ebp esi edi        ; preserve important registers
  487.            sub esp, 16             ; allocate workspace
  488.            mov ebp, esp            ; set up stack frame
  489.  
  490.            mov ax,cliplt           ; save old borders just in case
  491.            mov [ebp].rb_oldx1,ax
  492.            mov ax,cliprt
  493.            mov [ebp].rb_oldx2,ax
  494.            mov ax,cliptp
  495.            mov [ebp].rb_oldy1,ax
  496.            mov ax,clipbt
  497.            mov [ebp].rb_oldy2,ax
  498.  
  499.            mov x1,4
  500.  
  501.            mov ax,[ebp].rb_x1      ; set new borders for clipping
  502.            mov cliplt,ax
  503.            mov ax,[ebp].rb_x2
  504.            mov cliprt,ax
  505.            mov ax,[ebp].rb_y1
  506.            mov cliptp,ax
  507.            mov ax,[ebp].rb_y2
  508.            mov clipbt,ax
  509.  
  510.            mov [ebp].rb_curx,0     ; we could start at x1,y1 but this
  511.            mov [ebp].rb_cury,0     ; will make offset backgrounds
  512.  
  513.            mov esi,[ebp].rb_bitmap
  514.            mov bitmap,esi
  515.            lodsw                   ; set destination width same as original
  516.            mov [ebp].rb_wide,ax
  517.            lodsw
  518.            mov [ebp].rb_height,ax
  519. nextline:
  520.            mov ax,[ebp].rb_wide
  521.            mov destwidth,ax
  522.            mov ax,[ebp].rb_height
  523.            mov destheight,ax
  524.  
  525.            mov ax,[ebp].rb_curx
  526.            mov destx,ax
  527.            mov ax,[ebp].rb_cury
  528.            mov desty,ax
  529.  
  530.            push ebp
  531.            call xscale2            ; draw a transparent bitmap
  532.            pop ebp
  533.  
  534.            mov ax,[ebp].rb_curx
  535.            add ax,[ebp].rb_wide
  536.            mov [ebp].rb_curx,ax
  537.            cmp ax,[ebp].rb_x2
  538.            jle s nextline
  539.  
  540.            mov [ebp].rb_curx,0
  541.  
  542.            mov ax,[ebp].rb_cury
  543.            add ax,[ebp].rb_height
  544.            mov [ebp].rb_cury,ax
  545.            cmp ax,[ebp].rb_y2
  546.            jle s nextline
  547.  
  548.            mov ax,[ebp].rb_oldx1
  549.            mov cliplt,ax
  550.            mov ax,[ebp].rb_oldx2
  551.            mov cliprt,ax
  552.            mov ax,[ebp].rb_oldy1
  553.            mov cliptp,ax
  554.            mov ax,[ebp].rb_oldy2
  555.            mov clipbt,ax
  556.  
  557.            add esp, 16
  558.            pop edi esi ebp
  559.            ret 12
  560.  
  561.