Difference between revisions of "Z80 Routines:Graphic:largesprite"

From WikiTI
Jump to: navigation, search
 
Line 1: Line 1:
 
[[Category:Z80 Routines:Graphic|largesprite]][[Category:Z80 Routines|largesprite]]
 
[[Category:Z80 Routines:Graphic|largesprite]][[Category:Z80 Routines|largesprite]]
 
+
The '''Largesprite''' routine is used to copy the content of a sprite to the Graph Buffer. The sprite can be of any size (max. 96x64), so the input of the largesprite routine is quite big.
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.
 
Here is Joe Wingbermuehle's version, which is the one used in ION.
Line 78: Line 77:
 
   pop  af                          ;pop because we dont want a stack problem :)
 
   pop  af                          ;pop because we dont want a stack problem :)
 
   ret                                ;return</nowiki>
 
   ret                                ;return</nowiki>
 +
 +
===Example===
 +
-----
 +
<nowiki>
 +
  ;...
 +
  ld  a,8  ;y
 +
  ld  l,a
 +
  ld  a,16  ;x
 +
  ld  b,8  ;height
 +
  ld  c,2  ;width in bytes
 +
  ld  ix,sprite
 +
  call largesprite
 +
  call fastcopy
 +
  ;...
 +
sprite:
 +
  .db %11111111,%11111111
 +
  .db %10000000,%00000001
 +
  .db %10000000,%00000001
 +
  .db %10000000,%00000001
 +
  .db %10000000,%00000001
 +
  .db %10000000,%00000001
 +
  .db %10000000,%00000001
 +
  .db %11111111,%11111111</nowiki>
 +
 +
===Macro===
 +
-----
 +
This macro can be used with Tasm or Spasm.
 +
#define lsprite(lsprite_down,lsprite_right,lsprite_size_down,lsprite_size_right,lsprite_address) ld a,lsprite_down \ ld l,a \ ld a,lsprite_right \ ld b,lsprite_size_down \ ld c,lsprite_size_right \ ld ix,lsprite_address \ call largesprite
 +
 +
'''[→How do you do a line break in this Wiki?]'''
 +
 +
The above example would be:
 +
<nowiki>
 +
  ;...
 +
  lsprite(16, 8, 8, 2,sprite)
 +
  call fastcopy
 +
  ;...
 +
sprite:
 +
  .db %11111111,%11111111
 +
  .db %10000000,%00000001
 +
  .db %10000000,%00000001
 +
  .db %10000000,%00000001
 +
  .db %10000000,%00000001
 +
  .db %10000000,%00000001
 +
  .db %10000000,%00000001
 +
  .db %11111111,%11111111</nowiki>
  
 
===Differences between the 83+ and the 83 in Largesprite===
 
===Differences between the 83+ and the 83 in Largesprite===
 +
-----
 
You need to define 'gbuf' which is [[83Plus:RAM:9340|$9340]] on the Ti83+ and [[83:RAM:8E29|$8E29]] on the Ti83 before you include the largesprite routine.
 
You need to define 'gbuf' which is [[83Plus:RAM:9340|$9340]] on the Ti83+ and [[83:RAM:8E29|$8E29]] on the Ti83 before you include the largesprite routine.
 
  <nowiki>
 
  <nowiki>

Revision as of 05:18, 17 May 2007

The Largesprite routine is used to copy the content of a sprite to the Graph Buffer. The sprite can be of any size (max. 96x64), so the input of the largesprite routine is quite big.

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

Example


   ;...
   ld   a,8   ;y
   ld   l,a
   ld   a,16  ;x
   ld   b,8   ;height
   ld   c,2   ;width in bytes
   ld   ix,sprite
   call largesprite
   call fastcopy
   ;...
sprite:
   .db %11111111,%11111111
   .db %10000000,%00000001
   .db %10000000,%00000001
   .db %10000000,%00000001
   .db %10000000,%00000001
   .db %10000000,%00000001
   .db %10000000,%00000001
   .db %11111111,%11111111

Macro


This macro can be used with Tasm or Spasm.

#define lsprite(lsprite_down,lsprite_right,lsprite_size_down,lsprite_size_right,lsprite_address) ld a,lsprite_down \ ld l,a \ ld a,lsprite_right \ ld b,lsprite_size_down \ ld c,lsprite_size_right \ ld ix,lsprite_address \ call largesprite

[→How do you do a line break in this Wiki?]

The above example would be:

   ;...
   lsprite(16, 8, 8, 2,sprite)
   call fastcopy
   ;...
sprite:
   .db %11111111,%11111111
   .db %10000000,%00000001
   .db %10000000,%00000001
   .db %10000000,%00000001
   .db %10000000,%00000001
   .db %10000000,%00000001
   .db %10000000,%00000001
   .db %11111111,%11111111

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