; ASCR  - Advanced Sprite Clipping Routines
;
;       by Jimmy M†rdell        970304   Last update 970803
;
; TI83 port by Florent Dhordain 16/04/98 DD/MM/YY
;
; TI83/TI83+ Ion port by James Vernon 06/08/00 DD/MM/YY
;   Changed '$8E29' to 'gbuf' to make both routines compatible
;   with the 83+ :)
;
; Temporary variables needed:
;  clipmask  : Byte
;  rows2put  : Byte
;  bitmask       : Byte
;
;
; PutSprite_MSB:
;  Puts an 8x8 sprite at coordinates B,C. HL should point to a bitmapped
;  sprite followed by a bitmapped mask, total 16 bytes. DE should point
;  to an a memory location where the background will be stored as a
;  bitmap (8 bytes). The sprite will be clipped.
;
; PutSprite:
;  Puts an 8x8 sprite at B,C. HL = pointer to sprite. No mask and no
;  background storage, just clipping.

#ifndef ASCR_BOTCLIP
#define ASCR_BOTCLIP 64
#endif


PutSprite_MSB:          ; BC = x,y      DE = background storage  HL = sprite + mask
 ld a,c
 cp 150
 jr nc,PMSB_NoBotClip
 cp ASCR_BOTCLIP
_bottomClip1            = $-1
 ret nc
PMSB_NoBotClip:
 push bc
 push de
 push hl
 push ix
 ld a,$FF
 ld (clipmask),a
 bit 7,b
 jr z,PMSB_CheckRightClip
 ld a,b
 cp 249
 jr c,EndPMSB
 neg
 push bc
 ld b,a
 ld a,$FF
PMSB_LeftClip:
 srl a
 djnz PMSB_LeftClip
; -----> Flo <-----
 ld (clipmask),a
 pop bc
 ld a,b
 add a,96
 ld b,a
 dec c
; ----->     <-----
 jr PMSB_CheckBotClip
PMSB_CheckRightClip
 ld a,b
 sub 96-7                                       ; -----> Flo <-----
 jr c,PMSB_CheckBotClip
 push bc
 ld b,a
 inc b
 ld a,$FF
PMSB_RightClip:
 add a,a
 djnz PMSB_RightClip
 ld (clipmask),a
 pop bc
PMSB_CheckBotClip:
 ld a,8
 ld (rows2put),a
 bit 7,c
 jr nz,PMSB_CheckTopClip
; bit 6,c         Not necessary - has already be checked
; jp nz,EndMSB
 ld a, ASCR_BOTCLIP-1
_bottomClip2            = $-1
 sub c
 jp c, EndMSB                                   ; Exit if nothing to show
 inc a
 cp 8
 jr nc,PMSB_ClippingDone
 ld (rows2put),a
 jr PMSB_ClippingDone
PMSB_CheckTopClip:
 ld a,c
 cp 249
EndPMSB:
 jr c,EndMSB
; -----> Flo <----- Code not reachable ??? ret c
 push bc
 neg
 ld b,a
 sub 8
 neg
 ld (rows2put),a
PMSB_TopClip:
 inc hl
 inc de
 djnz PMSB_TopClip
 pop bc
 ld c,0
PMSB_ClippingDone:
 di
 push iy
 push hl
 pop iy                                         ; iy points on the sprite
 push de
 pop ix                                         ; ix on the BG
 ld a,(rows2put)
 push af
 call FIND_PIXEL
Modify_5:
; ld de,$8E29                                    ; -----> Flo <-----
; add hl,de
 ld (bitmask),a
 pop bc
PMSB_PutRow:
 push bc
 push hl
 ld a,(clipmask)
 ld e,a
 ld a,(iy+8)                                    ; iy+8 is the mask
 and e
 ld e,a          ; e = mask for this row
 ld d,0          ; d = background for this row
 ld b,8          ; b = pixels left to put
 ld c,(iy) ; c = sprite row
 inc iy
PMSB_PutCol:
 push bc
 sla d
 ld a,(bitmask)
 and (hl)
 jr z,PMSB_NPH
 inc d
PMSB_NPH:
 rlc e
 jr nc,PMSB_NextBit
 ld a,(bitmask)
 rlc c
 jr c,PMSB_BitOn
 cpl
 and (hl)
 ld (hl),a
 jr PMSB_NextBit
PMSB_BitOn:
 or (hl)
 ld (hl),a
PMSB_NextBit:
 ld a,(bitmask)
 rrca
 ld (bitmask),a
 jr nc,PMSB_SSB
 inc hl
PMSB_SSB:
 pop bc
 rlc c
 djnz PMSB_PutCol
 ld (ix),d
 inc ix
 pop hl
 ld de,12                                       ; -----> Flo <-----
 add hl,de
 pop bc
 djnz PMSB_PutRow
 pop iy
 ei
EndMSB:
 pop ix
 pop hl
 pop de
 pop bc
 ret


PutSprite:               ; BC = x,y  HL = sprite
 push bc
 push de
 push hl
 push ix
 ld a,$FF
 ld (clipmask),a
 bit 7,b                                ; is x negative ?
 jr z,PSC_CheckRightClip                ; no ==> no left clip
 ld a,b
 cp 249                                 ; 249 = 256 - 7
 jr c,EndPPS                            ; if x < 256-7 then nothing to display
 neg                                    ; get -x
 push bc
 ld b,a                                 ; b = -x
 ld a,$FF                               ; a = mask
PSC_LeftClip:
 srl a                                  ; a = 0xFF >> (-x)
 djnz PSC_LeftClip
 ld (clipmask),a
 pop bc
 ld  a, b
 add a,96                               ; hint : will be displayed on next line
 ld  b, a
 dec c                                  ; so, go one line upper !

 jr PSC_CheckBotClip
PSC_CheckRightClip                      ; if x is positive :
 ld a,b
 sub (96-7)                             ; is x < 96-7 ?
 jr c,PSC_CheckBotClip                  ; ==> no right clip !
 push bc
 ld b,a                                 
 inc b                                  ; b = bits to clip
 ld a,$FF
PSC_RightClip:
 add a,a                                ; faster way to shift left
 djnz PSC_RightClip
 ld (clipmask),a                        ; a = newmask
 pop bc
PSC_CheckBotClip:
 ld a,8
 ld (rows2put),a
 bit 7,c                                ; y < 0 ?
 jr nz,PSC_CheckTopClip                 ; yeah ==> top clipping
;; bit 6,c                                ; y > 0 and y > 63
;; jr nz,EndPS                            ; yeah ==> nothing to show
 ld a,ASCR_BOTCLIP-1
_bottomClip3            = $-1
 sub c                                  ; a = 64-y : dist from bottom
 jr c, EndPs                            ; exit if nothing to show
 inc a
 cp 8                                   ; 64-y-8 : y <= 64-8 ?
 jr nc,PSC_ClippingDone                 ; yeah : nothing to clip
 ld (rows2put),a                        ; else store what to disp
 jr PSC_ClippingDone
PSC_CheckTopClip:
 ld a,c
 cp 249                                 ; y < 256-7 ?
EndPPS:
 jr c,EndPS                             ; yeah ==> nothing to display
 push bc
 neg                                    ; a = y rows up than top
 ld b,a
 sub 8
 neg                                    ; a = lines to disp
 ld (rows2put),a
PSC_TopClip:
 inc hl
 inc de
 djnz PSC_TopClip                       ; go to first line to disp
 pop bc
 ld c,0
PSC_ClippingDone:
 push hl
 pop ix                                 ; ix = pointer to sprite dta
 ld a,(rows2put)
 push af
 call FIND_PIXEL                        ; get dest offset
Modify_6:
; ld de,$8E29                            ; add destination address
; add hl,de
 ld d,a                                 ; d = shiftval
 pop bc
PSC_PutRow:
 push bc
 push hl
 ld a,(clipmask)
 ld e,a                                 ; e = mask
 ld b,8
 ld c,(ix)                              ; c = what to disp
 inc ix                                 ; next sprite row
PSC_PutCol:
 push bc
 rlc e                                  ; rotate lt mask
 jr nc,PSC_NextBit
 ld a,d                                 ; if one bit has gone :
 rlc c                                  ; also rol dta
 jr c,PSC_BitOn                         ; if =1, put the bit
 cpl                                    ; a=~shiftval
 and (hl)                               ; clear this bit
 ld (hl),a
 jr PSC_NextBit
PSC_BitOn:
 or (hl)                                ; set the bit
 ld (hl),a
PSC_NextBit:
 rrc d                                  ; shift shiftval : next bit
 jr nc,PSC_SSB
 inc hl
PSC_SSB:                                ; one row has been drawn
 pop bc
 rlc c
 djnz PSC_PutCol                        ; next one
 pop hl
 ld bc,12
 add hl,bc
 pop bc
 djnz PSC_PutRow
EndPS:
 pop ix
 pop hl
 pop de
 pop bc
 ret

FIND_PIXEL:
 push bc
 push de
 ld a,b
 ld e,c
 call ionGetPixel
 pop de
 pop bc
 ret

;;ExpTable:
;;        .byte $01, $80, $40, $20, $10, $08, $04, $02, $01
;; This is defined in tests3.z80

