gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Coding > Animations

#171955 - zodiacdagreat - Mon Jan 04, 2010 10:22 am

I've been coding a titlescreen in asm and wanted to add in some animations. Does anyone know proper ways to do animations? According to Tonc, swi 0x5 is better than WaitForVBlank. So, I did something like this:

.WaitVBlank:
push {r2-r3, lr}
mov r3, #0x10 @ Amount of calls
mov r2, #0x0
.Loop:
swi 0x5
add r2, r2, #0x1
cmp r2, r3
ble .Loop
pop {r2-r3, pc}

Is that way, correct or preferable? I also found that another method works better:

swi 0x5
swi 0x5
swi 0x5
...

But according to my friends it's ugly and not good. Anywho, really need some help and guidance here :D

#171968 - Ruben - Tue Jan 05, 2010 8:16 am

Well, calling "swi 5" 3x is a bit untidy but it will be faster and will still get the job done. The other way with the loop would be something similar to this...

Code:
    push {r4}
    ldr  r4, =iterations @ if < 0x100 it will compile into a mov
1:  swi  5
    sub  r4, #1
    bne  1b
    pop  {r4}
    bx   lr


Note that I pushed and used r4 rather than r0-r3; r0-r3 are usually destroyed by BIOS calls. Also note that I used 'bx lr' to return rather than 'pop {pc}' as this may return you in the wrong mode (ARM/THUMB).

(edited thrice for formatting and a small errors)

#171969 - zodiacdagreat - Tue Jan 05, 2010 9:12 am

Uh, yes. bx lr returns to the previous call, especially if I'm using a branch link. You know the 'swi 0x5' 3x part wasn't actually 3 :P I meant to say that its repeated until I get the animation in the right speed.

So, I take it that what I'm doing is correct? :P

Edit: BTW, I just noticed this now XD My keypress loop that checks for keys becomes a lot slower... I take it as it is because of the wait for vblank, I wonder if it's possible to speed up only my keypress loop :D Here's my code for anyone interested:
@ Getting keypress
.KeypressLoop:
mov r0, #0xA
bl .WaitVBlank
bl .StartAnimation

mov r0, #0x3
bl .WaitVBlank
bl .HoOhAnimation

ldr r0, .REG_KEYINPUT
ldrh r2, [r0]
mov r1, #0x1 @ A button
and r2, r2, r1
cmp r2, #0x0
beq .Exit
ldrh r2, [r0]
mov r1, #0x8 @ Start button
and r2, r2, r1
cmp r2, #0x0
beq .Exit
b .KeypressLoop

#171970 - Ruben - Tue Jan 05, 2010 10:11 am

Well, this is how I would do it...
Code:
.VBlankWait:
    push {r4}    @ push register on stack
    mov   r4, r0 @ save count
1:  swi   5      @ wait for VBlank
    sub   r4, #1 @ if(--waitLeft)
    bhi   1b     @   continue
    pop  {r4}    @ pop register
    bx    lr     @ return

.MainLoop:
    mov  r0, #10           @ |
    bl  .VBlankWait        @  wait 10 V-Blanks
    bl  .StartAnim         @ start animation[s]
   
    mov  r0, #3            @ |
    bl  .VBlankWait        @  wait 3 V-Blanks
    bl  .HoOhAnimation     @ ???
   
    ldr  r0, =REG_KEYINPUT @ |
    ldrh r1, [r0]          @  read keys
    mov  r2, #0x09         @ |
    tst  r1, r2            @  if(!(keys() & KEY_A+KEY_START))
    bne .MainLoop          @    continue
    beq .Exit              @  else return


(edited for VBlankWait function; edited again for mistake)

EDIT:
Oh and yes, your key checking will only be done every 10+3 frames, in other words, every 13/60 frames as opposed to once every 1/60 frames. A way around this would be to use the key reading in an interrupt, save a variable somewhere in RAM and read this all the time.

#171971 - elwing - Tue Jan 05, 2010 11:04 am

you could also have your mainloop run every VBlank, and perform your animation every 13 frame while performing your key check at everyframe:
without taking care of details (like avoiding the % or managing the framecounter overflow...) that would look like
Code:

while(1){
  wait for VBLANK (swi 5)
  framecounter++
  if((framecounter % 13)==0){
    perform your animation
  }
  perform your key reading
}