I've written several masked sprite routines which you're welcome to use if you'd like. The basic concept is that you'll need to rotate both your sprite and your mask. Then, instead of:
Code: xor (hl) ;hl = position in gbuf, a = rotated sprite byte
ld (hl),a ;save xor'd byte to gbuf
..you do:
Code: and (hl) ;a = rotated mask, hl = gbuf byte
or d ;d = rotated sprite byte
ld (hl),a ;save masked byte into gbuf
Here's a sample 16x16 masked sprite routine:
Code: ;ix = player sprite
;ix+32 = player sprite mask
;b = x
;e = y
;c = sprite height
dibSprite:
; y * 12
ld l,e ;hl=de
add hl, hl ; 2
add hl, de ; 3
add hl, hl ; 6
add hl, hl ;x12
; x / 8
ld a,b
srl b
srl b
srl b
ld e,b
add hl, de ; A present on a le décalage dans hl
ld de,gbuf+2 ; Prendre le début du graphbuffer
add hl, de ; Puis ajouter le décalage
and $07
ld b,a
;b=xoff
drawPlayerSprite:
drawPlayerSpriteLoop:
push bc
drawPlayerRow:
ld d,(ix+32) ;sprite mask
ld e,(ix+33)
ld a,$ff
dec b \ inc b \ jr z,skipMaskClip ;si b=0
scf \ rr d \ rr e \ rra \ djnz $-6 ;rotate mask
skipMaskClip:
and (hl)
ld (hl),a
dec hl
ld a,(hl)
and e
ld (hl),a
dec hl
ld a,(hl)
and d
ld (hl),a
pop bc
inc hl
inc hl
push bc
ld d,(ix) ;sprite
ld e,(ix+1)
xor a
cp b
jp z,skipSpriteClip
srl d \ rr e \ rra \ djnz $-5 ;rotate sprite
skipSpriteClip:
or (hl)
ld (hl),a
dec hl
ld a,(hl)
or e
ld (hl),a
dec hl
ld a,(hl)
or d
ld (hl),a
inc ix
inc ix
ld de,16
add hl,de
pop bc
dec c
jp nz, drawPlayerSpriteLoop
ret
What we do is:
1. Find the location in the gbuf to draw the sprite.
2. Load the sprite mask into de and set a to $FF (a will hold the overflow)
3. Rotate the mask (de) to the right 0-7 times, depending on the location of the sprite. Rotate the carry into a.
4. AND the rotated mask with the gbuf, and save.
5. Repeat 2-4 with the sprite, only this time ORing (you could also XOR, it doesn't make a difference) it with the gbuf
6. Repeat for all 16 rows (or whatever number is in c).
EDIT: You'll also need to clear what you've drawn on the screen afterwards, you can do this a couple of ways. You can either save what's under the sprite you draw before you draw over it or have your tilemap routine update the whole gbuf every frame. I personally tend to do the second one (have my tilemap update the whole screen), as i think overall it's much easier than copying what's in the gbuf and restoring it. For the CSE i don't think you've really got much choice, though.