From: eker@loria.crin.fr (Steven Eker)
Newsgroups: comp.sys.atari.st.tech
Subject: Re: Sprite code (Re: Second&last time: Hacking Contest)
Date: 19 Aug 92 18:21:54 GMT
Organization: CRIN (CNRS) Nancy - INRIA Lorraine

In article <9817@uqcspe.cs.uq.oz.au>, warwick@cs.uq.oz.au (Warwick Allison) writes:

|> Complicated?  All you do is push them onto a stack when you draw then,
|> and pull them off to get the wiping order.  Usually, it is sufficient
|> to just do it with code, rather than doing it dynamically:
|> 
|>     while (1) {
|> 	Sprite1.Wipe();
|> 	Sprite2.Wipe();
|> 	Sprite3.Wipe();
|> 
|> 	Sprite3.Draw();
|> 	Sprite2.Draw();
|> 	Sprite1.Draw();
|> 
|> 	Pages->Flip();
|>     }

This is fine. but is a previous post you mentioned that sprites could be updated
at different speeds which made me think you were using some arbitrary interleaving
of draws & wipes. 

|> >How about:
|> >	4. Wipe all sprites, Save under new positions, draw all sprites etc.
|> 
|> This is exactly my #1 method, except mine is encapsulated.
|> 
|> You are saying:
|> 	for each sprite 1..n { sprite.Wipe }
|> 	for each sprite 1..n { sprite.SaveUnder }
|> 	for each sprite 1..n { sprite.Draw }
|> 
|> I am saying:
|> 	for each sprite 1..n { sprite.Wipe }
|> 	for each sprite n..1 { sprite.DrawAndSaveUnder }
|> 
|> My method is superior, simply because I get the sprite.SaveUnder almost
|> for free:  YOU ALREADY HAVE TO READ THE SCREEN IN ORDER TO DRAW THE SPRITE,
|> so you may as well store that read data as you draw, saves reading twice.

Maybe, maybe not - it depends on your sprite drawing method. The code I originally
posted only read the screen implicity with
	or.w	d0,(a0)+
type instructions. Now if you do it explicity you need an extra 4cy (canceling out any saving combining your save under code) and you need and an extra reg
which could slow down the rest of your code.

BTW the code I posted is (slightly) faster than the 32x32 sprite code in
your GNUchess port even under the most pessimistic assumptions (you did a great
job on the port though...).

|> Which reminds me - was this a competition?  I wrote some VERY fast 
|> sprite routines in a furious discussion with Dave B. - 60 or so
|> single-bitplane 16x16 sprites at arbitrary positions on an arbitrary
|> background was I believe my limit...

No, it was just a sugestion for a better competition goal than the rather
pointless TOS hacking in Nat!'s competion.
60 sprites at 50Hz is quite amazing on a non-blitter ST. At 25Hz rather less so.
Still I can't resist the challenge...

Steven


*	One plane 16x16 sprites (draw code only)
*
*	Entry:
*		a0	pointer to sprite
*		a1	pointer to where to draw it
*		d7	shift (0 - 15)
*

	moveq	#4,d6		; (4+1)*3+1 = 16 lines
loop:
	moveq	#0,d0
	moveq	#0,d1
	moveq	#0,d2
	moveq	#0,d3
	moveq	#0,d4
	moveq	#0,d5
	movem.w	(a0)+,d0-d5	; get three lines of mask & sprite

	ror.l	d7,d0		; rotate mask
	and.w	(a1),d0		; combine with bgnd
	ror.l	d7,d1		; rotate sprite
	or.w	d1,d0		; combine
	move.w	d0,(a1)		; replace
	addq.w	#8,a1		; next word
	swap	d0		; low part of mask
	and.w	(a1),d0		; combine with bgnd
	swap	d1		; low part of sprite
	or.w	d1,d0		; combine
	move.w	d0,(a1)		; replace
	lea	152(a1),a1	; next line

	ror.l	d7,d2		; rotate mask
	and.w	(a1),d2		; combine with bgnd
	ror.l	d7,d3		; rotate sprite
	or.w	d3,d2		; combine
	move.w	d2,(a1)		; replace
	addq.w	#8,a1		; next word
	swap	d2		; low part of mask
	and.w	(a1),d2		; combine with bgnd
	swap	d3		; low part of sprite
	or.w	d3,d2		; combine
	move.w	d2,(a1)		; replace
	lea	152(a1),a1	; next line

	ror.l	d7,d4		; rotate mask
	and.w	(a1),d4		; combine with bgnd
	ror.l	d7,d5		; rotate sprite
	or.w	d5,d4		; combine
	move.w	d4,(a1)		; replace
	addq.w	#8,a1		; next word
	swap	d4		; low part of mask
	and.w	(a1),d4		; combine with bgnd
	swap	d5		; low part of sprite
	or.w	d5,d4		; combine
	move.w	d4,(a1)		; replace
	lea	152(a1),a1	; next line

	dbra	d6,loop
	moveq	#0,d0
	moveq	#0,d1

	ror.l	d7,d0		; rotate mask
	and.w	(a1),d0		; combine with bgnd
	ror.l	d7,d1		; rotate sprite
	or.w	d1,d0		; combine
	move.w	d0,(a1)		; replace
	addq.w	#8,a1		; next word
	swap	d0		; low part of mask
	and.w	(a1),d0		; combine with bgnd
	swap	d1		; low part of sprite
	or.w	d1,d0		; combine
	move.w	d0,(a1)		; replace

Come to think of it, if the sprites are only one pixel deep why not preshift
the blighters???