Author Topic: Help understanding axe's sprite routine?  (Read 3383 times)

0 Members and 1 Guest are viewing this topic.

Offline c4ooo

  • LV5 Advanced (Next: 300)
  • *****
  • Posts: 252
  • Rating: +10/-1
  • The impossible chemical compound.
    • View Profile
Help understanding axe's sprite routine?
« on: September 18, 2015, 03:56:35 pm »
Hello, as you might know, I am fairly new to asm. I would appreciate if someone could explain how an 8*8 sprite routine works, or axe's sprite routine in particular. 

Axe's sprite routine: I would presume that the stack stuff in the middle is just to load the function's params (ie pt-off(x,y,p)) into certain registers.
Spoiler For Spoiler:

p_DrawOff:
   push   hl
   pop   ix         ;Input ix = Sprite
   ld   hl,plotSScreen      ;Input hl = Buffer
x_DrawOffEntry:
   pop   af
   pop   de         ;Input e = Sprite Y Position
   pop   bc         ;Input c = Sprite X Position
   push   af
   ld   b,7
   ld   a,63
   sub   e
   jr   nc,__DrawOffNoClipTop
   ld   a,e
   add   a,b
   ret   nc
__DrawOffClipTop:
;   xor   b
;   ld   e,a
;   add   ix,de
;   ld   e,d
;   xor   b
   inc   ix
   inc   e
   jr   nz,__DrawOffClipTop
__DrawOffNoClipTop:
   cp   b
   jr   nc,__DrawOffNoClipBot
   ld   b,a
__DrawOffNoClipBot:
   inc   b
   ld   a,c
   add   a,7
   cp   96+7
   ret   nc
   ld   d,0
   sla   e
   sla   e
   add   hl,de
   rra
   add   hl,de
   rra
   add   hl,de
   rra
   ld   e,a
   add   hl,de
   ld   a,c
   and   7
   jr   z,__DrawOffAligned
   ld   e,c
   ld   c,a
   ld   a,e
   cp   -7
   jr   nc,__DrawOffLoop
   inc   d
   cp   96-7
   jr   nc,__DrawOffLoop
   inc   d
__DrawOffLoop:
   push   bc
   ld   b,c
   ld   c,(ix+0)
   xor   a
   ld   e,$FF
__DrawOffShift:
   srl   c
   rr   e
   rra
   djnz   __DrawOffShift
   dec   d
   jr   z,__DrawOffSkipRight
   ld   b,a
   or   (hl)
   and   e
   ld   (hl),a
   ld   a,b
__DrawOffSkipRight:
   dec   hl
   inc   d
   jr   z,__DrawOffSkipLeft
   and   (hl)
   or   c
   ld   (hl),a
__DrawOffSkipLeft:
   ld   bc,13
   add   hl,bc
   inc   ix
   pop   bc
   djnz   __DrawOffLoop
   ret
__DrawOffAligned:
   ld   e,12
__DrawOffAlignedLoop:
   ld   a,(ix)
   ld   (hl),a
   inc   ix
   add   hl,de
   djnz   __DrawOffAlignedLoop
   ret

-German Kuznetsov
The impossible chemical compound.

Offline Runer112

  • Project Author
  • LV11 Super Veteran (Next: 3000)
  • ***********
  • Posts: 2289
  • Rating: +639/-31
    • View Profile
Re: Help understanding axe's sprite routine?
« Reply #1 on: September 18, 2015, 04:57:32 pm »
I've commented the routine. Let me know if you have any other questions.

Spoiler For Spoiler:
p_DrawOr:
        .db __DrawOrEnd-1-$

;; hl=sprite, (sp)=ret, (sp+2)=y, (sp+4)=x
;; Rearrange inputs.
        push    hl
        pop     ix
        ld      hl,plotSScreen
x_DrawOrEntry:
        pop     af
        pop     de
        pop     bc
        push    af

;; c=x, e=y, hl=buff, ix=sprite, (sp)=ret
;; Check if the top of the sprite is offscreen.
        ld      b,7
        ld      a,63
        sub     e
        jr      nc,__DrawOrNoClipTop

;; a=63-y, b=7, c=x, e=y, hl=buff, ix=sprite
;; If the top of the sprite is offscreen, abort if the bottom is also offscreen.
        ld      a,e
        add     a,b
        ret     nc

;; a=y+7, b=7, c=x, e=y, hl=buff, ix=sprite
;; The top of the sprite is offscreen (negative) but the bottom is not
;;   (nonnegative), so clip y to 0 and advance the sprite pointer past the
;;   clipped off data.
__DrawOrClipTop:
;       xor     b
;       ld      e,a
;       add     ix,de
;       ld      e,d
;       xor     b
        inc     ix
        inc     e
        jr      nz,__DrawOrClipTop

;; a=(y<0 ? y+7 : 63-y), b=7, c=x, e=clipped y, hl=buff, ix=sprite start
;; Calculate the clipped height.
__DrawOrNoClipTop:
        cp      b
        jr      nc,__DrawOrNoClipBot
        ld      b,a
__DrawOrNoClipBot:
        inc     b

;; a=(y<0 ? y+7 : 63-y), b=clipped height, c=x, e=clipped y, hl=buff,
;; ix=sprite start
;; Abort if the sprite is fully offscreen horizontally.
        ld      a,c
        add     a,7
        cp      96+7
        ret     nc

;; a=x+7, b=clipped height, c=x, e=clipped y, hl=buff, ix=sprite start
;; Calculate the pointer to which to draw the top-right of the (clipped) sprite:
;;   buff+((clipped y)*12)+((x+7)/8).
        ld      d,0
        sla     e
        sla     e
        add     hl,de
        rra
        add     hl,de
        rra
        add     hl,de
        rra
        ld      e,a
        add     hl,de

;; a=(x+7)/8, b=clipped height, c=x, de=clipped y*4, hl=draw start,
;; ix=sprite start
;; Use the aligned drawing code if possible.
        ld      a,c
        and     7
        jr      z,__DrawOrAligned

;; a=x&7, b=clipped height, c=x, de=clipped y*4, hl=draw start, ix=sprite start
;; Calculate masks for whether or not to draw the left and right bytes of the
;;   unaligned sprite.
        ld      e,c
        ld      c,a
        ld      a,e
        cp      -7
        sbc     a,a
        ld      d,a
        and     e
        cp      96-7
        sbc     a,a
        ld      e,a

;; b=height remaining, c=x&7, d=(x<0 ? $FF : 0), e=(x>88 ? $FF : 0),
;; hl=draw current, ix=sprite current
;; Read a sprite byte and rotate it into the correct alignment.
__DrawOrLoop:
        push    bc
        ld      b,c
        ld      c,(ix)
        xor     a
__DrawOrShift:
        srl     c
        rra
        djnz    __DrawOrShift

;; b=0, ca=(sprite byte<<8)>>(x&7), d=(x<0 ? $FF : 0), e=(x>88 ? $FF : 0),
;; hl=draw current, ix=sprite current, (sp)=(height remaining<<8)+(x&7)
;; Draw the rotated sprite byte, clipping horizontally as necessary by writing
;;   back unchanged data.
        and     e
        or      (hl)
        ld      (hl),a
        dec     hl
        ld      a,c
        and     d
        or      (hl)
        ld      (hl),a

;; b=0, c=sprite byte>>(x&7), d=(x<0 ? $FF : 0), e=(x>88 ? $FF : 0),
;; hl=draw current-1, ix=sprite current, (sp)=(height remaining<<8)+(x&7)
;; Advance the draw and sprite pointers.
        ld      c,13
        add     hl,bc
        inc     ix

;; bc=13, d=(x<0 ? $FF : 0), e=(x>88 ? $FF : 0), hl=draw next,
;; ix=sprite next, (sp)=(height remaining<<8)+(x&7)
;; Decrement the height remaining and continue drawing if it's nonzero.
        pop     bc
        djnz    __DrawOrLoop
        ret

;; ALIGNED SPRITE DRAWING

;; a=0, b=clipped height, c=x, de=clipped y*4, hl=draw start, ix=sprite start
;; Prepare.
__DrawOrAligned:
        ld      e,12

;; a=0, b=height remaining, c=x, de=12, hl=draw current, ix=sprite current
;; Read and draw a sprite byte, advance the sprite and draw pointers, and
;;   decrement the height remaining and continue drawing if it's nonzero.
__DrawOrAlignedLoop:
        ld      a,(ix)
        or      (hl)
        ld      (hl),a
        inc     ix
        add     hl,de
        djnz    __DrawOrAlignedLoop
        ret

__DrawOrEnd:
« Last Edit: September 18, 2015, 08:35:54 pm by Runer112 »