A.D.A. Amiga Demoscene Archive

  Welcome guest! Please register a new account or log in

  

  

  

log in with SceneID

  

Demos Amiga Demoscene Archive Forum / Coding / coding tutorial: sprites
 Page:  1  2  »» 
Author Message
z5_
Member
#1 - Posted: 24 Nov 2004 12:41
Reply Quote
Let's talk about sprites in here :)

Let's start with two questions:
- to which address should i point the sprite pointers of the unused sprites?
- i have the impression that sprites aren't that much used in modern demos anymore. Is that correct? When thinking about sprites, i especially think about starfields and such... Can somebody give some ideas on where to use sprites and give some examples of effects/demos where sprites are used. Just so i can get a general idea because i don't see as much use in them (with the very little knowledge i have)
Cyf
Member
#2 - Posted: 24 Nov 2004 13:52 - Edited
Reply Quote
to which address should i point the sprite pointers of the unused sprites?

point to a NullSprite defined in chip :
NullSprite: dc.l 0,0,0,0

if not use sprites, disable DMA sprite ($dff096=$20)

sprites are used for many things in games/demos
hmm...some examples...
- vertical Logos, little logo like Melon cracktros, or name of coder in some cracktros
- more impressive in TEK Rampage demo : in lot of parts, the "background picture" is a fake made of sprites and copper lines (!) for lets all bitplans free.
- and other not-really-visible effects...

sprites could be used for
- Text effect (wellknown skidrow cracktro)
- starfields
- multiplex sprites or 16 colors sprites by mixing the 8 sprites : 1-2,3-4,5-6,7-8 ...
- 3d object spining on a HAM picture (Silents ICE demo) or 3d cube in front and back of a picture (hoodlum cracktro)...

other difficult effect where sprites are used : some Rotozoom/plasma "onepixel" (Aspartam/Silicon intro). this effect use colors change (56/lines) but only 8 pix. to obtain 4 pix. width, sprites 16 colors interlaced between bitplan : (rotozoom width=128 pixels)
* sprites 1-2/3-4 (left) -> 32 pixels (4 stripes bitplan/sprites - 4 stripes background color)
* picture pattern (7 cols) -> 64 pixels (8 stripes bitplan/sprites - 8 stripes back color)
* sprites 5-6/7-8 (right) -> 32 pixels (4 stripes bitplan/sprites - 4 stripes back color)
(much better to see the coplist :))

Jim POwer or Shadow of the beast use all sprites possibilities (multiplex, 16 colors...) : take a look to the coplist : here

...many many things to say about sprites!

@anybody: feel free to add or correct infos
kufa
Member
#3 - Posted: 25 Nov 2004 05:22
Reply Quote
Jim POwer or Shadow of the beast use all sprites possibilities (multiplex, 16 colors...) : take a look to the coplist : here

Wow you have the source code of shadow of the beasts/jimpower? Just saw french comments in there :)
Cyf
Member
#4 - Posted: 25 Nov 2004 11:00 - Edited
Reply Quote
@kufa:
a simple disassembling with AR3 during level1
perhaps some errors in comments

same thing with Jim Power : sprites used for the mountains in the background !
it's possible to define 8 sprites 16 pix. width and 4 colors, so, with 2 sprites of 16 pix. repeat left to right = illusion of a new playfield !
and it's possible to change the 4 colors of sprites each line !

...very interesting to see copperlist : for example, Battle Squadron.
or in "Disposable Hero" a very impressive effect - only Amiga make it possible :) : start/End screen using 2 differents resolutions...but Vertically, not Horiz. !! 640 to left and 320 to right !
difficult to do (it doesnt work with WinUae)
z5_
Member
#5 - Posted: 28 Nov 2004 16:49
Reply Quote
ok, i've got another question. i nearly finished coding my first sprite routine, but i still have one problem: my sprites are moving to fast :)

what i have done:
- i jump to my spriteroutine in my main loop
- in the spriteroutine, i just add #1 to the hstart

What i'm thinking: how fast does my main loop 'loop'? I guess that this depends on the amount of code that is in the main loop (more code => more time needed to finish), so that with the method i'm using, the sprite speed will depend on this. Is that correct? And if yes, that isn't a reliable way to define a scrolling speed, so what is the alternative?
Cyf
Member
#6 - Posted: 28 Nov 2004 17:52 - Edited
Reply Quote
put animation routine in VBI, not in main loop

precision of horizontal position in the first control word : 2 pixels
for "one pixel" move, use bit 0 of second control word

nota: I talk about ECS system sprites ! no AGA for the moment
z5_
Member
#7 - Posted: 28 Nov 2004 22:40
Reply Quote
@cyf

For now, i have inserted a wait until the vbl bit is high (which is the same thing, i guess...).
z5_
Member
#8 - Posted: 28 Nov 2004 22:47 - Edited by Admin
Reply Quote
I still got one problem. My horizontal sprites work, but now i'm trying a vertical move. This is a little routine i wrote but it doesn't work. So if anybody can give me some info on what i'm doing wrong,... :)

lea sprite2,a1
move.w (a1),d1
;remove hstart from word => only vstart in d1
asr.w #$8,d1
;vertical movement => increment my vstart
addq.b #1,d1

;calculate vstop, which is vstart + sprite is 5 lines high
move.w d1,d2
add.w #5,d2
;put vstop in the high 8 bits again
asl.w #$8,d2

;we need to make the word vstart,hstart again
;so we put vstart in the high 8 bits
asl.w #$8,d1
move.w (a1),d0
;filter out hstart from our word at the start
and.w %0000000011111111,d0
;and combine them again
or.w d0,d1

move.w d1,sprite2
move.w d2,sprite2+2
Cyf
Member
#9 - Posted: 29 Nov 2004 12:03 - Edited
Reply Quote
difficult with combination of vstart and hstart in a word
more simple to use byte, I think...no risk of errors :)

strange, this routine works (with "and.w #%11111111,d0")

try with a simple increment : add.b #1,sprite2

brief explanation:
sprite: dc.w YYXX,(YY+h sprite)00
YY= VSTART
XX= HSTART
YY+h=VSTOP

simple code :
horizontal move :
add.b #1,sprite+1 ; incr Hstart

vertical move:
add.b #1,sprite ; incr Vstart
add.b #1,sprite+2 ; incr Vstop

;---------------
; example 1
move:
... compute x-y here (if complex mov)...
move.w x(pc),d0 ;pos x sprite
move.w y(pc),d1 ;pos y sprite
move.w #5,d2 ;h sprite
lea sprite,a0 ; sprite to move
bsr MoveSprite
rts
* ---------
MoveSprite:
neg.w d0 ;-x
neg.w d1 ;-y
addi.w #hposstart,d0 ; hpos start-x
addi.w #vposstart,d1 ; vpos start-y

moveq #0,d3 ; if vert pos > 256

move.b d1,(a0) ; vpos to Vstart
move.b d0,1(a0) ; put hpos to Hstart

; optional tests
; test for vertical limit and one pixel move
btst #8,d1 ; word #1 vert pos >256 ?
beq.s .noE8
bset #2,d3 ; yes. set bit 2 of control word 2
.noE8:
add.w d2,d1 ; y+h
move.b d1,2(a0) ; put y+h in Vstop

btst #8,d1 ; word #2 vert pos >256 ?
beq.s .noL8
bset #1,d3 ; yes. set bit 1 of control word 2
.noL8:
lsr.w #1,d0 ; x pos
bcc.s .noH0
bset #0,d3 ; one pixel move

.noH0:
move.b d3,3(a0) ; vert limit & on pix move
rts

;------------------------------
second control word bits :
15-8 : Y+H
7 : attach
2 : E8 word 1 vertical pos >256
1 : L8 word 2 vertical pos >256
0 : H0 one pixel move
z5_
Member
#10 - Posted: 2 Dec 2004 12:17
Reply Quote
I have the impression that disabling the sprite DMA isn't enough to disable sprites completely. Because i sometimes get garbage on the screen or even the mouse pointer.

Am i right in saying that the spritepointers should always be defined, even if not used. In that case, they just need to be pointed to a nul-address only once at the startup of the demo (don't use a copperlist for that because it only has to be done once). Is that correct?
z5_
Member
#11 - Posted: 2 Dec 2004 17:55 - Edited by Admin
Reply Quote
Here is a little routine i'm trying to disable sprites. (i have disabled my sprite dma in dff040. I only do the routine once at startup.
;disable sprite dma
move.w #%0000000000100000,$dff040

;initialise all sprite pointers to a dummy sprite address
lea $dff120,a1
lea nulsprite,a0
;8 sprites
moveq #7,d1
.spriteempty:
move.l a0,a1
addq.l #4,a1
dbra d1,.spriteempty

In my chip ram, i have defined the following label (as Cyf told me)
nulsprite:
dc.l 0,0,0,0

However, it doesn't work. What am i doing wrong. Also some general code questions:
- am i allowed to do addq.l (i have understood that addq is a faster addition with a maximum of 8 to be added).
- with addq, do i have to define .l,.b,.w? I mean, it is maximum 8 so maximum a byte??
- adding something to an address pointer (here addq.l #4,a1): is that always in bytes?
- is it $dff120 or $dff0120
- what exactly does dc.l 0,0,0,0 do? Is that the same as dc.l 0?
TheDarkCoder
Member
#12 - Posted: 2 Dec 2004 18:07
Reply Quote
@z5_ no, if you correctly disable sprite DMA you don't need to point sprites to NULL. But I think I know your problem. The issue is that IF you disable sprites DMA in the exact moment that one sprite is being displayed, it will continue to be displayed in non-DMA mode. You should see a vertical stripe.
How to avoid this? Simple, be sure to disable sprite DMA during the VBlank, better at the start. By the way this is the best to do also when you need to disable Bitplanes DMA, for some reason. So wait for line 1 of the beam (reading VPOSR) and then disable. Beware, it is better not to wait for line 0, because line 256 could be erroneusly got. It happens that VPOSR is really composed by a pair of 16 bit registers, one of wich contains bits 0-7 and the other bits 8-?? (I don't remember the number of bits, maybe 11 for AGA,check docs). What happens is that when the beam reaches line $100, there is a short amount of time where bits 0-7 are reset to 0 but bit 8-?? are still not set to $1 . So the CPU think to be at line 0.
Hope this solve your problem. If not, then you do some other mistake in clearing the sprite DMA, but for sure if you do it correclty you don't need to initialize SPRxPT

darky
TheDarkCoder
Member
#13 - Posted: 2 Dec 2004 18:27 - Edited
Reply Quote
@z5: I suggest you to use names for registers instead of adresses.
I really don't remember numbers.
***I suppose that $dff040 is DMACON.***EDITED: OH NO, THAT IS THE PROBLEM, SEE CYF'S post. Anyway, give a look to rest of this posting, it may help you!!*****

Then, as I told, clearing the bit during the VBlank is enough.
if you want I can post the very simple code to syncronize the Video Beam.

By the way, the code to initialize sprite pointers is uncorrect.:

lea spr0pt,a0
lea nullsprite,a1
moveq #8-1,d0
.loop
move.l a1,(a0)+
dbra d0,.loop

For every assembler instruction, the suffix (.b, .w, .l) refer to the size of the destination operand. The exeption is when the destination is Ax. In that case the destination is always .l. So addq.w #4,d0 and addq.l #4,d0 are different, while addq.w #4,a and addq.l #4,a0 are the same.
the right adress is $dff120, but this exactly the reason why I suggest you to use labels instead of numbers: if you mispell the label (name) of a register, the assembler gives an error. But if you mispell a number, the assmbler just produce wrong code, and then it's hard to find the bug. After spending days to find a buf which was only that I wrote $ddf040 instead of $dff040 (for example) I started using always names!!

***EDITED: sorry I didn't understand your question, now I do, see other post and Cyf's post****

Anyway, for questions related to 680x0 assembly, maybe it is better to first study the manuals. Is not that I don't want to help!! :-)
No problem for me :-) but for 680x0 there are very good books, simpler ones and more detailed ones. For example the official Motorola reference manuals, which are freely available on the web. You will learn more by studing them than asking in the forum. For Amiga-hardware or effects, it's a different story, the documentation is often obscure, you'd better ask!! :)
Cyf
Member
#14 - Posted: 2 Dec 2004 18:59 - Edited
Reply Quote
$dff040 ? err...no, this register is BLTCON0 : blitter control register

DMACON=$dff096 (see first post in this thread)

D_setclr=$8000
D_priB=$400 ; blitter priority
D_All=$200
D_Btpl=$100 ; dma bitplane
D_Copp=$80 ; dma copper
D_Blit=$40 ; dma blitter
D_sprt=$20 ; dma sprite
D_disk=$10 ; dma disk
D_aud=$f : ; dma audio (4 channels)

what exactly does dc.l 0,0,0,0 do?
first and second word control of sprite set to 0 (pos x/y and height) dc.w 0,0 and the end of sprite structure dc.w 0,0 => dc.l 0,0 + empty data word.
the 4 long words of 0 are with Aga
TheDarkCoder
Member
#15 - Posted: 2 Dec 2004 20:11
Reply Quote
@z5_: ehehe!!! that's why tou continue see garbage!
see what Cyf write? :

$dff040 ? err...no, this register is BLTCON0 : blitter control register

DMACON=$dff096 (see first post in this thread)

D_setclr=$8000
D_priB=$400 ; blitter priority
D_All=$200
D_Btpl=$100 ; dma bitplane
D_Copp=$80 ; dma copper
D_Blit=$40 ; dma blitter
D_sprt=$20 ; dma sprite
D_disk=$10 ; dma disk


one more reason to use names instead of numbers!
The source is also much more elegant and readable!
It is also nice to use labels for the value to be put inside registers,
as the D_xxx things that Cyf suggests!!

Anyway, follow also my suggestion in my previous post, disable DMA during Vertical Blank, otherwise you seldom get garbage (depending on the position of the mouse pointer before the demo starts!! :-)

regarding the dc.l 0,0,0,0 sorry, in the previous post I misundestood your question!! If I remember right, with OCS/ECS or even AGA when the sprites fetch mode is 0 (i.e. 16 pixel sprites) dc.w 0,0 is enough.
With 32 pixel sprites you have to put 4 words to 0 and with 64 pixel sprite
you need 8 words to 0. You can check on the AGA.guide, do you have such a document? It's part of the ASM-One distribution.

p.s. names for the registers are already provided in standard include files, for example Commodore's custom.i . But there are more in the public domain.
Cyf
Member
#16 - Posted: 2 Dec 2004 20:42
Reply Quote
yes, it's better to use the custom.i for all chip registers $dffxxx (or you know registers or like me, you have a book with a all registers in a table, and other informations about amiga hardware, for example all libraries functions with parameters...)

you can also create your own include file with all values you use (e.g. D_xxx)

example here
z5_
Member
#17 - Posted: 2 Dec 2004 21:09
Reply Quote
@Cyf and TDC (which is TheDarkCoder from now on :))

I will gladly use names but i don't know how to. I have all the necessary includes files, i have already included hardware/custom.i in my source and i am already using names in my copperlist. However, i don't know how to get the base address ($dff000) offset for stuff not in my copperlist.

In the commodore includes, they are mentioning that i should use XREF _custom to get the base address. But what do i do with it? Where do i put it?

Suppose that i want to do the following:

move.w #%0000000000100000,$dff096

How do i do that with names and with that XREF stuff?
Cyf
Member
#18 - Posted: 2 Dec 2004 21:23 - Edited
Reply Quote
you can also write :
lea custom,a5
move.w #$20,dmacon(a5)
or
move.w #$20,custom+dmacon

p.s : the Nullsprite can be used if you use only 1,2...sprites. set unused sprite with NullSprite.
z5_
Member
#19 - Posted: 2 Dec 2004 21:38
Reply Quote
@cyf:
so each time i need to use a name, i first have to do get the base address with custom,a5? Because, my a5 could have been filled in with some other value during execution of the program?

Also, asm-one doesn't understand the word custom when i compile. Which file do i need to include to get asm-one to recognise the custom command?
Cyf
Member
#20 - Posted: 2 Dec 2004 21:41 - Edited
Reply Quote
custom in Ax, you have choice
or (custom+name) if you can't use register Ax
or save base register in stack :
lea custom,ax
...
movem.l ax,-(sp)
...
movem.l ax,(sp)+

custom is not a command, but set with EQU or =

custom EQU $dff000
custom = $dff000
TheDarkCoder
Member
#21 - Posted: 3 Dec 2004 18:03
Reply Quote
@z5:
You can define your own names. Es, you put in the beginning of your source:

MyOwnDMACON =$dff096

and then in the code you use
MOVE #xxxx,MyOwnDMACON.

Of course is better to use standards. So C= defined register names not as full adresses, but rather as offsets from the "custom base adress". So:
custom = $dff000
dmacon =$096.
Soyou have to write
MOVE #xxxx,custom+dmacon
Why this? because it's usual to adress registers not by absolute adresses but with indirect mode with displacement (because it's faster).
So the standard habit is to put:
lea custom, Ax (traditionally A5) in the beginning of the part of your code where you write registers. Then you read/write registers like:
MOVE #xxxx,dmacon(ax)

Names so defined are also good for copperlists, since the copper CMOVE adress registers using just the offset. So the copper instruction to write a value in DMACON is:
dc.w dmacon,xxxx
I find much more convenient to define macros for copper instructions (CMOVE, WAIT and also SKIP! yes, I sometimes used it!!!)
So I simply and nicely write
CMOVE xxxx,dmacon
z5_
Member
#22 - Posted: 3 Dec 2004 18:57
Reply Quote
@TDC:
so for example, in any subroutine which has blitter instructions, one should first write lea custom,a5 and then use names in all blitter addresses (bltsize(a5), bltdpt(a5),...)
TheDarkCoder
Member
#23 - Posted: 3 Dec 2004 19:07
Reply Quote
z5: yes. it is not a rule, of course, but it is usually the best thing since
the addresing mode xx(ay) is faster than the absolute adressing mode.
It may be that before the lea you should save a5 in the stack, so it makes sense when you have at least 3/4 accesses to register to do.
korruptor
Member
#24 - Posted: 28 Nov 2006 18:41
Reply Quote
I'm curious about horizontal sprite multiplexing. Can this be done simply with the copper and the usual sprite DMA? Or is it best to poke the sprite registers in manual mode?

I've had a quick play but not quite got it sussed yet.
TheDarkCoder
Member
#25 - Posted: 29 Nov 2006 18:28
Reply Quote
@korruptor

AFAIK, you cannot do hor multiplex with DMA, because there are only 8 DMA channels (i.e., color clock cycles) dedicated to sprite. I think this is the main reason why there are only 8 sprites.
To do that, you have to reload "manually" SPRxDATx, SPRxCTR and SPRxPOS. You can conveniently do that using the copper, which simplifies the syncronization.
Unfortunately, AFAIK, in "manual mode" you can only generate 16 pixel wide sprites. This forbids a 320 pixel wide , 16 color screen made using sprites. It is a pity.

Unless someone found how to use 32 or 64 pixel sprite in "manual mode".
(there is no HRM for AGA)
sp_
Member
#26 - Posted: 30 Nov 2006 12:39
Reply Quote
Don't remember what the "manual mode" is, but in AGA you can easily generate a 256 * 256 4bpl sprite screen (8 sprites 64bit wide)
By setting datefetch mode to 64bit. Using 2 bpl you can get a 320*256 sprite screen.
korruptor
Member
#27 - Posted: 30 Nov 2006 17:03
Reply Quote
DarkCoder: Cool, that makes sense, thanks for the confirmation. I'll give it a whirl next week.

(I've got caught up getting blitter basics working today. :D)
TheDarkCoder
Member
#28 - Posted: 30 Nov 2006 18:22
Reply Quote
Don't remember what the "manual mode" is, but in AGA you can easily generate a 256 * 256 4bpl sprite screen (8 sprites 64bit wide)
By setting datefetch mode to 64bit. Using 2 bpl you can get a 320*256 sprite screen.


sure. you miss a pair of sprites to be able to do a 320*256 4bpl screen.
Using horizontal multiplexing in manual mode you could re-use a pair of sprites, but AFAIK in manual mode you can only have 16bit wide sprites :-(
Kalms
Member
#29 - Posted: 30 Nov 2006 22:25
Reply Quote
Perhaps you could do the first 4x64 pixels using 4 pairs of 64-bit sprites, and the last 4x16 pixels using 4 pairs of fake-16-bit sprites though?

(i.e. what happens if you write SPRxDAT manually when sprites are in 64bit mode? will the remaining 48 bits be cleared, duplicates or left as-is?)
winden
Member
#30 - Posted: 1 Dec 2006 00:52
Reply Quote
i recall "risky woods" game had a pretty interesing copperlist for the scrolling background
 Page:  1  2  »» 

  Please register a new account or log in to comment

  

  

  

 

A.D.A. Amiga Demoscene Archive, Version 3.0