<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>http://learn.cemetech.net/index.php?action=history&amp;feed=atom&amp;title=Z80%3ASprite_Routines</id>
	<title>Z80:Sprite Routines - Revision history</title>
	<link rel="self" type="application/atom+xml" href="http://learn.cemetech.net/index.php?action=history&amp;feed=atom&amp;title=Z80%3ASprite_Routines"/>
	<link rel="alternate" type="text/html" href="http://learn.cemetech.net/index.php?title=Z80:Sprite_Routines&amp;action=history"/>
	<updated>2026-07-26T18:48:07Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.3</generator>
	<entry>
		<id>http://learn.cemetech.net/index.php?title=Z80:Sprite_Routines&amp;diff=104&amp;oldid=prev</id>
		<title>KermMartian: Created page with &quot;=== Sprite Routines ===  The routine below is a routine that takes your 8 wide * X high sprite and then puts it in the screen buffer. It is commonly known as Ion PutSprite, by...&quot;</title>
		<link rel="alternate" type="text/html" href="http://learn.cemetech.net/index.php?title=Z80:Sprite_Routines&amp;diff=104&amp;oldid=prev"/>
		<updated>2016-02-03T21:30:00Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;=== Sprite Routines ===  The routine below is a routine that takes your 8 wide * X high sprite and then puts it in the screen buffer. It is commonly known as Ion PutSprite, by...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;=== Sprite Routines ===&lt;br /&gt;
&lt;br /&gt;
The routine below is a routine that takes your 8 wide * X high sprite and then puts it in the screen buffer. It is commonly known as Ion PutSprite, by Joe Wingbermuehle. More routines can be found on [*http://ticalc.org TiCalc] (see links to your left), [http://www.unitedti.org/index.php?showtopic=1279 United Ti] and [http://www.cemetech.net/forum/viewtopic.php?t=1449 Cemetech].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    putSprite:&lt;br /&gt;
    	ld	e,l&lt;br /&gt;
    	ld	h,$00&lt;br /&gt;
    	ld	d,h&lt;br /&gt;
    	add	hl,de&lt;br /&gt;
    	add	hl,de&lt;br /&gt;
    	add	hl,hl&lt;br /&gt;
    	add	hl,hl               ;Find the Y displacement offset &lt;br /&gt;
    	ld	e,a&lt;br /&gt;
    	and	$07               ;Find the bit number&lt;br /&gt;
    	ld	c,a&lt;br /&gt;
    	srl	e&lt;br /&gt;
    	srl	e&lt;br /&gt;
    	srl	e&lt;br /&gt;
    	add	hl,de             ;Find the X displacement offset&lt;br /&gt;
    	ld	de,gbuf&lt;br /&gt;
    	add	hl,de&lt;br /&gt;
    putSpriteLoop1:&lt;br /&gt;
    sl1:	ld	d,(ix)             ;loads image byte into D&lt;br /&gt;
    	ld	e,$00&lt;br /&gt;
    	ld	a,c&lt;br /&gt;
    	or	a&lt;br /&gt;
    	jr	z,putSpriteSkip1&lt;br /&gt;
    putSpriteLoop2:&lt;br /&gt;
    	srl	d                  ;rotate to give out smooth moving&lt;br /&gt;
    	rr	e&lt;br /&gt;
    	dec	a&lt;br /&gt;
    	jr	nz,putSpriteLoop2&lt;br /&gt;
    putSpriteSkip1:&lt;br /&gt;
    	ld	a,(hl)&lt;br /&gt;
    	xor	d&lt;br /&gt;
    	ld	(hl),a&lt;br /&gt;
    	inc	hl&lt;br /&gt;
    	ld	a,(hl)&lt;br /&gt;
    	xor	e&lt;br /&gt;
    	ld	(hl),a              ;copy to buffer using XOR logic&lt;br /&gt;
    	ld	de,$0B&lt;br /&gt;
    	add	hl,de&lt;br /&gt;
    	inc	ix                   ;Set for next byte of image&lt;br /&gt;
    	djnz	putSpriteLoop1 &lt;br /&gt;
    	ret&lt;br /&gt;
&lt;br /&gt;
As is probably apparent, this routine can be modified to not only XOR sprites, but also AND and OR.  All you have to do is change the two XOR&amp;#039;s to the appropriate function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Animating Sprites ===&lt;br /&gt;
&lt;br /&gt;
The routine below will animate two sprites by simply displaying the first sprite, erasing it, then displaying the second sprite, erasing it and finally repeat the loop.  Remember that this code is for only 2 sprites.  More can be added though.  Note that this routine uses ion calls and will not function unless you are using the ion header.  See [[Z80:Shells|Shells]] for more information.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    loop:&lt;br /&gt;
    ld ix,Sprite_address&lt;br /&gt;
    ld a,X_coordinate&lt;br /&gt;
    ld l,Y_coordinate&lt;br /&gt;
    ld b,Sprite_height&lt;br /&gt;
    call iputsprite8          ;Assuming your sprite is 8x8&lt;br /&gt;
    call ifastcopy&lt;br /&gt;
    &lt;br /&gt;
    ld ix,Sprite_address&lt;br /&gt;
    ld a,X_coordinate&lt;br /&gt;
    ld l,Y_coordinate&lt;br /&gt;
    ld b,Sprite_height&lt;br /&gt;
    call iputsprite8               ;erase&lt;br /&gt;
    &lt;br /&gt;
    ld ix,Sprite_address&lt;br /&gt;
    ld a,X_coordinate+1&lt;br /&gt;
    ld l,Y_coordinate&lt;br /&gt;
    ld b,Sprite_height&lt;br /&gt;
    call iputsprite8                ;draw and display your second sprite&lt;br /&gt;
    call ifastcopy&lt;br /&gt;
    &lt;br /&gt;
    ld ix,Sprite_address&lt;br /&gt;
    ld a,X_coordinate+1&lt;br /&gt;
    ld l,Y_coordinate&lt;br /&gt;
    ld b,Sprite_height&lt;br /&gt;
    call iputsprite8               ;erase&lt;br /&gt;
    jp loop&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Thank you Fallen Ghost for your help with this code!&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
==== Another look at Animated Sprites ====&lt;br /&gt;
&lt;br /&gt;
If you want to cut down on size or increase speed, there is another way to create animated sprites. Instead of having to erase each time, what you could do is add an extra sprite that&amp;#039;s an XOR of two sprites: the layer previously displayed, and the next layer. Note that the first and last layers must be intact (what they would look like without XOR-ing to another layer).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    loop:&lt;br /&gt;
     ld ix,Layer1				;draw first layer as is everytime&lt;br /&gt;
     ld a,0&lt;br /&gt;
     ld l,0&lt;br /&gt;
     ld b,8&lt;br /&gt;
     call ionputsprite&lt;br /&gt;
     call ionfastcopy&lt;br /&gt;
      &lt;br /&gt;
     ld ix,XORLayer				;move onto next layer. Since it has the XORed part, no need to erase (&amp;quot;already done&amp;quot;)&lt;br /&gt;
     ld a,0&lt;br /&gt;
     ld l,0&lt;br /&gt;
     ld b,8&lt;br /&gt;
     call ionputsprite&lt;br /&gt;
     call ionfastcopy&lt;br /&gt;
    &lt;br /&gt;
    ;... any other layers would look similar to the few lines of code above&lt;br /&gt;
    &lt;br /&gt;
     ld ix,Layer2				;Just need to erase last layer&lt;br /&gt;
     ld a,0&lt;br /&gt;
     ld l,0&lt;br /&gt;
     ld b,8&lt;br /&gt;
     call ionputsprite&lt;br /&gt;
    &lt;br /&gt;
     jr loop&lt;br /&gt;
     &lt;br /&gt;
    Layer1:&lt;br /&gt;
    .db $00,$7E,$B9,$CF,$CF,$B9,$7E,$00&lt;br /&gt;
    &lt;br /&gt;
    Layer2:&lt;br /&gt;
    .db $FC,$72,$9E,$9E,$72,$FC,$00,$00&lt;br /&gt;
    &lt;br /&gt;
    XORLayer:							;XOR of Layer1 and Layer2&lt;br /&gt;
    .db $FC,$0C,$27,$51,$BD,$45,$7E,$00&lt;br /&gt;
    &lt;br /&gt;
    ;... extra XORed layers, if necessary&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Calculating from above, having to erase each time took 13 bytes/extra layer, and some time (usually insignificant, but sometimes crucial). By having the XOR layer, it only adds 8 more bytes (assuming you have 8*8 sprites), and takes less time (if time is crucial). That&amp;#039;s a saving of 5 bytes/extra layer!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
------&lt;br /&gt;
&lt;br /&gt;
{{lowercase}}&lt;br /&gt;
[[Category:Z80 Assembly]]&lt;br /&gt;
[[Category:Z80 Heaven]]&lt;/div&gt;</summary>
		<author><name>KermMartian</name></author>
	</entry>
</feed>