Created: 13th November 1999
Last Modified: 5th December 1999
This page will show how the most popular aligned sprite routine works.
The fastest and most popular routine was posted on the assembly-86 mailing list in 1997 by Dan Eble. It takes three inputs:
It destroys af, bc, de, hl and ix (ix is one of the two index registers - it has some useful instructions associated with it, such as offsets. I'll explain more later).
;=========================================================== ; GridPutSprite: [Dan Eble] ; Puts an aligned sprite at (E, D), where HL -> Sprite ;=========================================================== ; IN : D = y (0-7 inclusive) ; E = x (0-15 inclusive) ; HL-> sprite ; ; OUT: AF, BC, DE, HL, IX modified ; Current total : 28b/567t (not counting ret) ;=========================================================== GridPutSprite: push hl ; push hl to stack... pop ix ; ...and pop it into ix srl d ; de = (128 * y) + x rra ; carry flag -≶ msb of a and $80 ; a is either $00 or $80 or e ; add x offset (remember x <= 15) ld e,a ; de = (128 * y) + (x * 8) ld hl,$fc00 ; hl-> video memory add hl,de ; hl-> video memory + offset ld b,8 ; initialize loop counter ld de,16 ; screen is 16 bytes wide GPS_Loop: ld a,(ix + 0) ; get byte from sprite ld (hl),a ; put byte on screen inc ix ; move to next byte in sprite add hl,de ; move to next line on screen djnz GPS_Loop ; loop until sprite is drawn ret ; return
This routine is quite complicated - I've commented it (the original comments were
a bit cryptic) but it is still hard to understand, in particular the usage of
rra. This and the and $80 are used to calculate the
offset correctly. Leaving these out would prevent certain coordinates from being
drawn correctly.
Now we'll look at a (very) simple program that uses sprites. It will draw a picture of a smiley face in the top left of the screen and a sad face in the bottom right.
Source: faces.asm
Compiled: faces.86p
#include "ti86asm.inc" .org _asm_exec_ram call _clrScrn ; Clear screen call _homeup ; Cursor to top left ld hl,SmileySprite ; hl points to start of sprite ld de,$0000 ; d contains y, e contains x ; so coordinate is (0, 0) call GridPutSprite ; Draw smiley in top left ld hl,SadSprite ; hl points to start of sprite ld de,$070f ; d contains y, e contains x ; so coordinate is (15, 7) call GridPutSprite ; Draw smiley in top left call _pause ; Pause calc call _clrScrn ; Clear screen call _homeup ; Cursor to top left ret ; Exit GridPutSprite: push hl ; push hl to stack... pop ix ; ...and pop it into iy srl d ; de = (128 * y) + x rra ; carry flag -< msb of a and $80 ; a is either $00 or $80 or e ; add x offset (remember x <= 15) ld e,a ; de = (128 * y) + (x * 8) ld hl,$fc00 ; hl-> video memory add hl,de ; hl-> video memory + offset ld b,8 ; initialize loop counter ld de,16 ; screen is 16 bytes wide GPS_Loop: ld a,(ix + 0) ; get byte from sprite ld (hl),a ; put byte on screen inc ix ; move to next byte in sprite add hl,de ; move to next line on screen djnz GPS_Loop ; loop until sprite is drawn ret ; return SadSprite: .db %01111110 .db %10000001 .db %10100101 .db %10000001 .db %10011001 .db %10100101 .db %10000001 .db %01111110 SmileySprite: .db %01111110 .db %10000001 .db %10100101 .db %10000001 .db %10100101 .db %10011001 .db %10000001 .db %01111110 .end
As you can see, it's writing the routine that's difficult, using it is dead easy. Next we'll take a look at non-aligned sprites.