From play@playsoft.co.uk Tue May 27 23:25:32 2003
Return-Path: <play@playsoft.co.uk>
Received: from cmailm5.svr.pol.co.uk (cmailm5.svr.pol.co.uk [195.92.193.21])
	by mail25.nsc.no (8.9.3p2/8.9.3) with ESMTP id XAA09911
	for <frelling@online.no>; Tue, 27 May 2003 23:25:32 +0200 (CEST)
Received: from modem-1036.gazelle.dialup.pol.co.uk ([81.78.68.12] helo=playsoftpc)
	by cmailm5.svr.pol.co.uk with esmtp (Exim 4.14)
	id 19Klwo-0001ap-Or
	for frelling@online.no; Tue, 27 May 2003 22:25:31 +0100
From: "Paul Lay" <play@playsoft.co.uk>
To: <frelling@online.no>
Subject: RE: pixies..
Date: Tue, 27 May 2003 22:25:32 +0100
Message-ID: <000001c32496$851f9640$0c444e51@playsoftpc>
MIME-Version: 1.0
Content-Type: text/plain;
  charset="us-ascii"
Content-Transfer-Encoding: 7bit
X-Priority: 3 (Normal)
X-MSMail-Priority: Normal
X-Mailer: Microsoft Outlook, Build 10.0.2627
Importance: Normal
In-Reply-To: <200305262310.45105.frelling@online.no>
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1106
Status: R 
X-Status: N

Hi Kristoffer,

Your assumption is correct, the graphics for the sprites are animated in
the vertical blank interrupt.

Another example is the explosion graphics - this is just a single
sprite, which is updated with different frames to achieve the animation.

The advantage of doing this is that it makes more efficient use of VRAM.
In the case of the explosions, I use 1 sprite and update its graphics
rather than having all frames permanently occupying VRAM. The
disadvantage is that you use more CPU time doing the copying, but as
long as you're not copying too much it shouldn't be a problem,
especially as you can use DMA to make the copying very fast.

You can also use this technique to animate tiles as well as sprites, but
I don't think I used any tile animation in Astrohawk.

This is the animation code which I execute during the vertical blank
interrupt.

animationData is an array of frames which are to be copied to VRAM. The
data for each frame occupies 7 bytes and has the following format:

bytes 0, 1: 16-bit VRAM destination address

bytes 2, 3, 4: 24-bit source address - typically this would point to
data in ROM, although for the radar (which had to be dynamically
calculated) this was RAM

bytes 5, 6: number of bytes to copy (16-bits)


animationIndex is a 16-bit values which indexes the end of the
animationData array (i.e. when animationIndex is 0 the array is empty,
when it is 7 there is a single frame etc...)


The following code uses DMA to copy all the frames held in animationData
to VRAM and then resets animationIndex. Note A is 8-bits, X & Y 16-bits.

; copy animation data to VRAM
    ldx.w #$0000

animateLoop

    cpx.w animationIndex
    beq doneAnimation

    lda.l animationData,x ; get VRAM destination
    inx
    sta $2116
    lda.l animationData,x
    inx
    sta $2117

    ldy.w #$1801          ; dma to $2118
    sty $4300

    lda.l animationData,x ; get source
    inx
    sta $4302
    lda.l animationData,x
    inx
    sta $4303
    lda.l animationData,x
    inx
    sta $4304

    lda.l animationData,x ; get number of bytes
    inx
    sta $4305
    lda.l animationData,x
    inx
    sta $4306

    lda #$01              ; do dma
    sta $420B

    bra animateLoop

doneAnimation

    ldx.w #$0000
    stx animationIndex


Here's the code I use to animate the explosions. Note all registers are
16-bits.

The variable twelveFrameIndex is updated elsewhere and counts from 0 to
20 in steps of 2 which provides the index into the source frames in
zapFrameOffset.

Note that the sprite is animated in two parts - that's because a 16x16
sprite doesn't occupy a contiguous area of VRAM.

animateZap
    ldx animationIndex
    ldy twelveFrameIndex

    lda.w #$0280
    sta.l animationData,x
    lda zapFrameOffset,y
    sta.l animationData+$02,x
    lda.w #expl16_data/$10000
    sta.l animationData+$04,x
    lda.w #$0040
    sta.l animationData+$05,x

    lda.w #$0380
    sta.l animationData+$07,x
    lda zapFrameOffset,y
    clc
    adc.w #$0200
    sta.l animationData+$09,x
    lda.w #expl16_data/$10000
    sta.l animationData+$0B,x
    lda.w #$0040
    sta.l animationData+$0C,x

    txa
    clc
    adc.w #$000E
    sta animationIndex

    rts

zapFrameOffset
    dc.w expl16_data&$FFFF
    dc.w expl16_data+$40&$FFFF
    dc.w expl16_data+$80&$FFFF
    dc.w expl16_data+$C0&$FFFF
    dc.w expl16_data+$100&$FFFF
    dc.w expl16_data+$140&$FFFF
    dc.w expl16_data+$180&$FFFF
    dc.w expl16_data+$1C0&$FFFF
    dc.w expl16_data+$400&$FFFF
    dc.w expl16_data+$440&$FFFF
    dc.w expl16_data+$480&$FFFF
    dc.w expl16_data+$4C0&$FFFF


I hope this makes some kind of sense. It's really simple, just not that
easy to explain.

Paul

> -----Original Message-----
> From: Kristoffer Relling [mailto:frelling@online.no]
> Sent: 26 May 2003 22:11
> To: Paul Lay
> Subject: pixies..
> 
> I'm sorry for disturbing you, Paul!
> 
> I was wondering on how you did the radar in ahawk..
> I feel very limited in the way I'm currently using the
> sprites/tiles! I understand that you are directly modifiying
> the sprites/tiles on the fly. Could you please demonstrate/
> explain me how you do it?
> 
> I do believe that this can greatly assist me in being able to
> use the rest of my Angel(a)'s ship-sprites (smooth animtions :)
> Thinking of the quite limited sprite-memory makes me believe
> that the nintendo game-developers pulled off something like this
> to be able to have more animations for their player+enemy sprites
> at the same time!
> 
> Please forgive me for this horrendous e-mail, but I'm in a hurry :-)
> 
> 
> Sincerely,
> 
> /Kristoffer





