Z80 Routines:Graphic:largesprite

From WikiTI
Revision as of 04:58, 17 May 2007 by NanoWar (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search


The Largesprite routine is used to copy the content of a sprite to the Graph Buffer.

Here is Joe Wingbermuehle's version, which is the one used in ION.

;=======================
;LargeSprite
;by Joe Wingbermuehle
;=======================
;Does:   Copy a sprite to the gbuf
;Input:  ix=sprite address, a='x', l='y', b='height' (in pixels), c='width' (in bytes, e.g. 2 would be 16)
;Output: The sprite is copied to the gbuf
;-----------------------
largeSprite:
   di                                 ;turn interrupts off (we want to use shadow registers)
   ex   af,af'
                                      ;exchange af with af'     \
   ld   a,c                           ;ld c in a (a = 'width')  | for not destroying a ('x')
   push   af                          ;push a                   |
      ex   af,af'
                                      ;exchange back            | and 'width' is now in a' (saved)
      ld   e,l                        ;e = 'y'
      ld   h,$00                      ;h =  0
      ld   d,h                        ;d =  0
      add   hl,de                     ;'y' *2  \
      add   hl,de                     ;    *3  | calculate 'y' *12 because 'y' is 'in rows'
      add   hl,hl                     ;    *6  |   (screen is 12 bytes in length)
      add   hl,hl                     ;    *12 /
      ld   e,a                        ;e = 'x'
      and   $07                       ;and %00000111
      ld   c,a                        ;last 3 bits in c (amount of bits to shift all bytes)
      srl   e                         ;e/2   | shifting e ('x') 3 bits to the right
      srl   e                         ; /4   |   %11111111 becomes %00011111 for example
      srl   e                         ; /8   /
      add   hl,de                     ;hl = 'y'; de = 'x' (rounded) | add them
      ld   de, gbuf                   ;de = the adress of graph buffer
      add   hl,de                     ;add hl to the adress of the gbuf
largeSpriteLoop1:
      push   hl                       ;save adress
largeSpriteLoop2:
         ld   d,(ix)                  ;first sprite data in d
         ld   e,$00                   ;e = 0
         ld   a,c                     ;a = c (to not destroy c)
         or   a                       ;is a = 0? (same as cp 0)
         jr   z,largeSpriteSkip1      ;if theres nothing to shift (a = 0) loop it
largeSpriteLoop3:
         srl   d                      ;shift one bit to the right; put the destroyed bit in the carry flag
         rr   e                       ;put the carry flag in e (%00000000 becomes %10000000 if carry flag = 1)
         dec   a                      ;decrease counter (with was 'the amount of bits to shift')
         jr   nz,largeSpriteLoop3     ;if the counter is not 0 loop back
largeSpriteSkip1:
         ld   a,(hl)                  ;graphbyte in a
         xor   d                      ;xor first byte of sprite (that can be changed to 'or d' if you want a OR-routine)
         ld   (hl),a                  ;back to buffer
         inc   hl                     ;increase pointer
         ld   a,(hl)                  ;graphbyte in a
         xor   e                      ;xor with shifted sprite byte (change to 'or e' for OR-routine)
         ld   (hl),a                  ;back to buffer
         inc   ix                     ;increase sprite adress
         ex   af,af'
                                      ;exchange af with af' ( a is now the 'width' from the first line)
         dec   a                      ;decrease 'width'
         push   af                    ;push the 'width'
            ex   af,af'
                                      ;exchange back
         pop   af                     ;pop the 'width'
         jr   nz,largeSpriteLoop2     ;if a is not 0 (if a = 0 then we would be done) loop it
      pop   hl                        ;pop gbuf adress (search the last push hl!)
   pop   af                           ;pop  | to restore the real 'width'
   push   af                          ;push /
      ex   af,af'
                                      ;af' must be the original 'width' when loop 'largeSpriteLoop1'
      ld   de,$0C                     ;ld de,12
      add   hl,de                     ;next line
      djnz   largeSpriteLoop1         ;if not b = 0 loop (b = height of sprite)
   pop   af                           ;pop because we dont want a stack problem :)
   ret                                ;return

Differences between the 83+ and the 83 in Largesprite

You need to define 'gbuf' which is $9340 on the Ti83+ and $8E29 on the Ti83 before you include the largesprite routine.

#ifdef TI83P
#define gbuf $9340
#else
#define gbuf $8E29
#endif