Subject: copying data real fast...code to do it
From: [email-masked] (albert chin)
Date: 29 Jul 91 09:09:08 GMT
Newsgroups: comp.sys.apple2

the following routine copies data from an off-screen grafport to an
on-screen window. as far as i am aware, this is the fastest possible
method to do the copy. the off-screen grafport is guaranteed to remain
in a bank. the destination is bank $01.

this copy routine handles several copies. the only one this routine deals
with is routine #1 which copies the entire off-screen grafport.

things you need to know:
        1. variables of the form ']'<name> are direct page variables
        2. variables of the form '@'<name> are global variables
        3. variables of the form '~'<name> are constant variables
        4. @grafport is the pointer to the on-screen window
        5. @off_grafport is the pointer to the off-screen grafport
        6. ~shr contains a table of pointers to the beginning of screen lines
        7. VSCROLL_WIDTH is the length of the vertical scroll bar
        8. cg is a macro that
                lda     ]1,x
                pha
                lda     ]1-2,x
                pha
                lda     ]1-4,x
                pha
                lda     ]1-6,x
                pha
                lda     ]1-8,x
                pha

if anyone has questions, feel free to email me. i hope the code is clear.

albert chin

---------------------------- snip snip -------------------------------

**************************************************
* copy off-screen grafport to on-screen window   *
* content region. main entry point for copy      *
* routine.                                       *
* #1 copies entire grafport                      *
* #2 copies grafport starting at x-register      *
* #3 copies grafport starting at x, ending in y  *
**************************************************
copy_grafport   ent                     
]grafport       =      $c0              ;current grafport
]off_grafport   =      $c4              ;off-screen grafport
]rect           =      $c8              ;window port rectangle
]rect_global    =      $d0              ;global window port rectangle
]off_rect       =      $d8              ;off-screen port rectangle
]image          =      $e0              ;pointer to window pixel image
]off_image      =      $e4              ;pointer to off-screen pixel image
]x              =      $e8              ;number of bytes to copy
]height         =      $ea              ;number of lines to copy
]vis_region     =      $ec              ;handle/pointer to visible region
]which_copy     =      $f0              ;which copy_grafport routine to use
]begin_y        =      $f2              ;beginning coordinate to copy
]end_y          =      $f4              ;ending coordinate to copy
]max_x          =      $f6              ;max x value for on-screen window
]qd_MinRect     =      $00              
]qd_ImageRef    =      $0e              
]qd_BoundsRect  =      $14              

                sta    ]which_copy      ;which copy_grafport routine to use
                stx    ]begin_y         ;where to begin copy (for 2, 3)
                sty    ]end_y           ;where to end copy (for 3)

                ldx    @grafport        
                ldy    @grafport+2      
                stx    ]grafport        
                sty    ]grafport+2      
                phy                     ;long - pointer to grafport
                phx                     
                _SetPort                

                ldx    @off_grafport    
                ldy    @off_grafport+2  
                stx    ]off_grafport    
                sty    ]off_grafport+2  
                phy                     
                phx                     

                ldy    #$1c             ;get handle to visible region
                lda    []grafport],y    
                sta    ]vis_region      
                ldy    #$1e             
                lda    []grafport],y    
                sta    ]vis_region+2    

                ldy    #2               ;convert vis_region handle to pointer
                lda    []vis_region],y  
                tay                     
                lda    []vis_region]    
                sta    ]vis_region      
                sty    ]vis_region+2    

                sec                     
                ldy    #$16             ;if leftmost byte to copy begins
                lda    []grafport],y    ;at scroll bar, end
                sbc    #VSCROLL_WIDTH   
                sta    ]max_x           
                ldy    #4               ;test leftmost byte
                lda    []vis_region],y  
                cmp    ]max_x           
                blt   :1               
                brl    :rts             

:1              lda    ]which_copy      ;copy routines here only setup
                cmp    #COPY_GRAFPORT_3 ;parameters
                bne    :copy_2          
                jsr    copy_grafport_3  ;copy grafport from ]begin_y to ]end_y
                bra    :continue        
:copy_2         cmp    #COPY_GRAFPORT_2 
                bne    :copy_1          
                jsr    copy_grafport_2  ;copy grafport starting at ]begin_y
                bra    :continue        
:copy_1         jsr    copy_grafport_1  ;copy entire grafport

:continue       bcc    :2               
                brl    :rts             
:2              ldy    #$16             ;leftmost coordinate for on-screen
                lda    []grafport],y    ;window
                sbc    #VSCROLL_WIDTH   
                sta    ]max_x           
                sec                     
                ldy    #8               
                lda    []vis_region],y  
                cmp    ]max_x           
                blt    :3               
                sec                     
                ldy    #$16             ;leftmost coordinate for on-screen
                lda    []grafport],y    ;window
                ldy    #8               
                sbc    []vis_region],y  
                sta    ]max_x           
                sec                     
                lda    #VSCROLL_WIDTH   
                sbc    ]max_x           
                sta    ]max_x           
                sec                     
                ldy    #8               
                lda    []vis_region],y  
                sbc    ]max_x           
                bra    :4               
:3              ldy    #8               
                lda    []vis_region],y  
:4              sta    ]rect_global+6   
                sta    ]rect+6          
                sbc    ]rect+2          
                dec                     
                dec                     
                dec                     
                lsr                     
                lsr                     
                sta    ]x               ;length in words to copy

                clc                     ;convert window port rectangle to
                tdc                     ;global coordinates
                adc    #]rect_global    
                pea    #0               
                pha                     
                _LocalToGlobal          
                clc                     
                tdc                     
                adc    #]rect_global+4  
                pea    #0               
                pha                     
                _LocalToGlobal          

                phd                     
                lda    qd_dp            ;set quickdraw direct page
                tcd                     
                ldx    @grafport        ;temp location to retrieve bounds
                ldy    @grafport+2      ;rectangle
                stx    ]qd_MinRect      
                sty    ]qd_MinRect+2    
                ldy    #8               ;set up bounds rectangle of window
                lda    []qd_MinRect],y  ;grafport
                sta    ]qd_BoundsRect   
                ldy    #10              
                lda    []qd_MinRect],y  
                sta    ]qd_BoundsRect+2 
                ldy    #12              
                lda    []qd_MinRect],y  
                sta    ]qd_BoundsRect+4 
                ldy    #14              
                lda    []qd_MinRect],y  
                sta    ]qd_BoundsRect+6 
                ldx    ]rect            ;set up rectangle cursor might be in
                ldy    ]rect+2          
                stx    ]qd_MinRect      
                sty    ]qd_MinRect+2    
                ldx    ]rect+4          
                ldy    ]rect+6          
                stx    ]qd_MinRect+4    
                sty    ]qd_MinRect+6    
                ldx    #$2000           ;set up screen image where cursor
                ldy    #$e1             ;exists
                stx    ]qd_ImageRef     
                sty    ]qd_ImageRef+2   
                jsl    ShieldCursor     
                pld                     

                lsr    ]rect+2          
                lsr    ]rect+2          
                lsr    ]rect_global+2   
                lsr    ]rect_global+2   

                stz    :off_left        
                ldy    #4               ;if window off left of screen,
                lda    []vis_region],y  ;adjust copy
                beq    :right           
                lda    #TRUE            
                sta    :off_left        
:right          sec                     ;if window off right of screen,
                ldy    #$16             ;adjust copy
                lda    []grafport],y    
                sbc    #VSCROLL_WIDTH   
                ldy    #8               
                cmp    []vis_region],y  
                blt    :on_screen       
                inc    ]rect+2          

:on_screen      lda    ]rect+4          
                inc                     
                asl                     
                tax                     
                clc                     
                ldy    #2               
                lda    []off_grafport],y 
                adc    ~shr,x           
                adc    ]rect+2          
                dec                     
                sta    ]off_image       
                ldy    #4               
                lda    []off_grafport],y 
                sta    ]off_image+2     

                lda    ]rect_global+4   
                inc                     
                asl                     
                tax                     
                clc                     
                ldy    #2               
                lda    []grafport],y    
                adc    ~shr,x           
                adc    ]rect_global+2   
                adc    ]x               
                sta    ]image           
                ldy    #4               
                lda    []grafport],y    
                sta    ]image+2         

                sei                     
                tsc                     
                sta    :stack           ;save copy of stack pointer
                tdc                     
                sta    :dp              ;save copy of direct-page pointer
                inc    ]x               
                inc    ]x               
                lsr    ]x               ;number of bytes -> number of words
                sec                     
                lda    #80              
                sbc    ]x               ;each word copy takes 4 bytes
                asl                     
                asl                     
                clc                     
                adc    #:copy           
                sta    :copy_addr       
                lda    ]height          
                sta    :height          
                ldy    ]image           
                ldx    ]off_image       
                shorta                  
                phb                     ;save copy of data bank register
                pla                     
                sta    :db              
                lda    ]off_image+2     ;map data bank register to off-screen
                pha                     ;image
                plb                     
                stal   WrCardRam        ;map stack to aux memory
                longa                   

:5              sec                     
                tya                     
                sbc    #160             
                tay                     
                tcs                     

                sec                     
                txa                     
                sbc    #160             
                tax                     ;index into copy routine

                hex    4c               ;jmp
:copy_addr      dw     0                

:6              ldal   :height          
                dec                     
                stal   :height          
                bpl    :5               

                shorta                  
                stal   WrMainRam        ;map stack back to bank 00
                longa                   
                ldal   :stack           ;restore stack pointer
                tcs                     
                ldal   :dp              ;restore direct-page register
                tcd                     
                shorta                  
                ldal   :db              ;restore data bank register
                pha                     
                plb                     
                longa                   
                cli                     

                phd                     
                lda    qd_dp            ;set quickdraw direct page
                tcd                     
                jsl    UnshieldCursor   
                pld                     

:rts            _SetPort                
                jsr    init_tick        ;reset tick counter
                rts                     
:stack          dw     0                ;stack pointer
:dp             dw     0                ;direct-page pointer
:db             db     0                ;data bank register
:height         dw     0                
:off_left       dw     0                ;if window on outside left of screen

:copy           cg     158              
                cg     148              
                cg     138              
                cg     128              
                cg     118              
                cg     108              
                cg     98               
                cg     88               
                cg     78               
                cg     68               
                cg     58               
                cg     48               
                cg     38               
                cg     28               
                cg     18               
                lda:   8,x              
                pha                     
                lda:   6,x              
                pha                     
                lda:   4,x              
                pha                     
                lda:   2,x              
                pha                     
                ldal   :off_left        
                beq    :end             
                shorta                  
                lda:   1,x              
                pha                     
                longa                   
:end            brl    :6