****************************************************************************
****************************************************************************
**                                                               
**  Phoenix (Collision detection)
**
**  Copyright 2004 by Patrick Davidson.  This software may be freely
**  modified and/or copied with no restrictions.  There is no warranty.
**
**  by Patrick Davidson (pad@calc.org, http://pad.calc.org/)
**
**  Last updated August 9, 2004
**
****************************************************************************
****************************************************************************

******************************************** TEST FOR COLLISIONS
*
* This routine tests two objects for collisions.  It returns with the zero
* flag set (and D0 = 0) if there is no collision, and the zero flag clear
* (and D1 = -1) if there is a collision.  It first checks whether the
* rectangular boundaries of the objects overlap.  If they do, it then draws
* the images themselves to test for overlap of actual images.
*
* This routine is guaranteed to preserve A3-A6 and D3-D7.  All other
* registers may be changed.
*
* Parameters:
*
* A3 -> Bullet, enemy, or enemy bullet structure of one object
* A4 -> Bullet, enemy, or enemy bullet structure of the other
*
* The overlap testing is done by drawing the objects into a special buffer
* for testing.  The buffer is 8 bytes (64 pixels) wide.  The first step in
* the test is to clear the area that object A3 would be in, which is the
* center longword (the object will always start at X coordinate of 24).
* Next, object A4 is drawn into this buffer (at an adjusted X-coordinate)
* and the object in A3 is tested against it by ANDing its data with anything
* that may have been written in the test area.
*
********

Test_Collision:
        move.w  e_y(a4),d0              ; Test Y-coord overlap
        blt     no_collision    
        add.w   e_h(a4),d0      
        sub.w   b_y(a3),d0      
        ble.s   no_collision    
        sub.w   e_h(a4),d0      
        sub.w   b_h(a3),d0      
        bge.s   no_collision    

        move.w  e_x(a4),d0              ; Test X-coord overlap
        add.w   e_w(a4),d0      
        sub.w   b_x(a3),d0      
        ble.s   no_collision    
        sub.w   e_w(a4),d0      
        sub.w   b_w(a3),d0      
        bge.s   no_collision    

        lea     cdt+2(a5),a0            ; Clear temp buffer for A3
        moveq   #0,d1                   ; D1 = 0
        lea     image_table(pc),a2      ; A2 -> image table
        move.w  e_y(a3),d0      
        lsl.w   #3,d0   
        add.w   d0,a0                   ; A0 = A3's pos in temp buffer
        move.l  a0,-(sp)                ; D3 = A3's pos in temp buffer
        move.w  e_h(a3),d0      
        subq.w  #1,d0                   ; D0 = # lines to clear - 1
lclr:   move.l  d1,(a0)                 ; Clear a line
        addq.l  #8,a0                   ; A0 -> next line
        dbra    d0,lclr 

        move.w  e_x(a4),d0              ; Draw first sprite (A4)
        sub.w   b_x(a3),d0      
        add.w   #24,d0                  ; D0 = X4 - X3 + 24
        move.w  e_y(a4),d1              ; A1 = Y4
        move.w  e_image(a4),d2  
        bsr.s   Move_Sprite     

        move.l  (sp)+,a1                ; Test image (A3) with it
        move.w  e_h(a3),d0      
        subq.w  #1,d0                   ; D0 = # lines to clear - 1
        move.w  e_image(a3),d1          ; D1 = image handle from (A3)
        lea     2(a2,d1.w),a0           ; A2 -> (A3) image data
loop_col_det:
        move.l  (a0)+,d1                ; D1 = line's image data
        and.l   (a1),d1                 ; D1 = collision mask
        bne.s   collision               ; if nonzero, collision
        addq.l  #8,a1                   ; A1 -> next line
        dbra    d0,loop_col_det 
no_collision:
        moveq   #0,d0   
        rts     

collision:
        moveq   #-1,d0  
        rts     

******************************************** PUT SPRITE VIA MOVE
*
* This routine draws a sprite in the collision-detection testing buffer.
* The sprite is done simply by copying its sprite data over the screen;
* saving any original image is not important.
*
********

Move_Sprite:
        lea     0(a2,d2.w),a0   
        tst.w   d1      
        blt.s   no_collision    
        move.w  d0,d2                   ;D0 = X coordinate
        and.w   #15,d0  
        lsl.w   #3,d1                   ;D1 = Y coordinate
        lea     0(a5,d1.w),a1   
        add.w   #cdt,a1 
        lsr.w   #4,d2   
        add.w   d2,d2   
        add.w   d2,a1   

        move.w  (a0)+,d2                ;A0 -> Sprite data
        subq.w  #8,d0   
        bgt.s   ms_ShiftRight   
        beq.s   ms_alignedOK    

ms_ShiftLeft:
        neg.w   d0      
ms_ShiftLeft_:
        move.l  (a0)+,d1        
        lsl.l   d0,d1   
        eor.l   d1,(a1) 
        addq.l  #8,a1   
        dbra    d2,ms_ShiftLeft_        
        rts     

ms_alignedOK:
        move.l  (a0)+,d1        
        move.l  d1,(a1) 
        addq.l  #8,a1   
        dbra    d2,ms_alignedOK 
        rts     

ms_ShiftRight:
        move.l  (a0)+,d1        
        lsr.l   d0,d1   
        move.l  d1,(a1) 
        addq.l  #8,a1   
        dbra    d2,ms_ShiftRight        
        rts