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

From WikiTI
Redirect page
Jump to: navigation, search
(Adding a clipping large sprite routine.)
m (redirect)
 
(5 intermediate revisions by 2 users not shown)
Line 1: Line 1:
−
[[Category:Z80 Routines:Graphic|largesprite]][[Category:Z80 Routines|largesprite]]
+
#REDIRECT [[Z80_Routines:Graphic:putLargeSprite]]
−
The '''Largesprite''' routine is used to copy the contents of a variable sized sprite to the Graph Buffer.
+
−
 
+
−
 
+
−
== Code ==
+
−
Here is Joe Wingbermuehle's version, which is the one used in ION. Gbuf must be defined before its use.
+
−
 
+
−
<nowiki>
+
−
;=======================
+
−
;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</nowiki>
+
−
 
+
−
== Example ==
+
−
<nowiki>
+
−
  ;...
+
−
  ld  l,8  ;y
+
−
  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>
+
−
 
+
−
 
+
−
== Version without shadow registers ==
+
−
 
+
−
by Tijl Coosemans, made for Venus. Compatible with ION's routine. screenBuf must be defined.
+
−
 
+
−
<nowiki>
+
−
iLargeSprite
+
−
ld h,0
+
−
ld d,h
+
−
ld e,l
+
−
add hl,de
+
−
add hl,de
+
−
add hl,hl
+
−
add hl,hl
+
−
ld e,a
+
−
srl e
+
−
srl e
+
−
srl e
+
−
add hl,de
+
−
ld de,screenBuf
+
−
add hl,de
+
−
and 7
+
−
ld e,a
+
−
iLargeSpriteLoop1
+
−
push bc
+
−
push hl
+
−
ld b,c
+
−
iLargeSpriteLoop2
+
−
ld c,(ix)
+
−
ld d,0
+
−
inc ix
+
−
ld a,e
+
−
or a
+
−
jr z,iLargeSprite1
+
−
iLargeSpriteLoop3
+
−
srl c
+
−
rr d
+
−
dec a
+
−
jr nz,iLargeSpriteLoop3
+
−
iLargeSprite1
+
−
ld a,c
+
−
xor (hl)
+
−
ld (hl),a
+
−
inc hl
+
−
ld a,d
+
−
xor (hl)
+
−
ld (hl),a
+
−
djnz iLargeSpriteLoop2
+
−
pop hl
+
−
ld c,12
+
−
add hl,bc
+
−
pop bc
+
−
djnz iLargeSpriteLoop1
+
−
ret
+
−
</nowiki>
+
−
 
+
−
 
+
−
 
+
−
== Version with Clipping ==
+
−
This is a version that supports clipping the large sprite.  It's considerable larger and requires Self modifying code.  The SMC can be removed without to much difficulty. It has different inputs than ION's.
+
−
 
+
−
<nowiki>;--------------------------------
+
−
;Clip Big Sprite
+
−
;by James Montelongo
+
−
;MAX SIZE: 64x64
+
−
;ix - Sprite
+
−
;b  - height
+
−
;c  - width in bytes
+
−
;d  - x
+
−
;e  - y
+
−
 
+
−
ClipBigSprite:
+
−
; Early out, Check if its even remotely on screen
+
−
ld a,e
+
−
cp 64
+
−
ret p
+
−
add a,b
+
−
ret m
+
−
ret z
+
−
ld a,d
+
−
cp 96
+
−
ret p
+
−
ld a,c
+
−
add a,a
+
−
add a,a
+
−
add a,a
+
−
add a,d
+
−
ret m
+
−
ret z
+
−
 
+
−
ld a,e
+
−
or a
+
−
jp p,Check_clip_bottom
+
−
neg
+
−
push de
+
−
ld hl,0
+
−
ld d,l
+
−
ld e,a
+
−
bit 2,c
+
−
jr z,$+2+1
+
−
add hl,de
+
−
add hl,hl
+
−
bit 1,c
+
−
jr z,$+2+1
+
−
add hl,de
+
−
add hl,hl
+
−
bit 0,c
+
−
jr z,$+2+1
+
−
add hl,de
+
−
pop de
+
−
ex de,hl
+
−
add ix,de ;Here you can save the top offset
+
−
ex de,hl
+
−
ld e,0
+
−
neg
+
−
add a,b
+
−
ld b,a
+
−
Check_clip_bottom:
+
−
 
+
−
ld a,e
+
−
add a,b
+
−
sub 64
+
−
jp m,Check_clip_Left
+
−
neg
+
−
add a,b
+
−
ld b,a
+
−
Check_clip_Left:
+
−
; at this point you may want to save b
+
−
xor a
+
−
ld (bigskip),a
+
−
ld a,Clipleftsize
+
−
ld (Do_Clipleft),a
+
−
ld a,d
+
−
or a
+
−
jp p,Check_clip_right
+
−
neg
+
−
and $F8
+
−
rra
+
−
rra
+
−
rra
+
−
ex de,hl ;save the clipped left offset
+
−
ld e,a
+
−
ld d,0
+
−
add ix,de
+
−
ld (bigskip),a
+
−
ex de,hl
+
−
inc a
+
−
neg
+
−
add a,c
+
−
ld c,a
+
−
xor a
+
−
ld (Do_Clipleft),a
+
−
ld a,d
+
−
and $07
+
−
ld d,a
+
−
Check_clip_right:
+
−
 
+
−
ld a,Cliprightsize
+
−
ld (Do_Clipright),a
+
−
ld a,c
+
−
add a,a
+
−
add a,a
+
−
add a,a
+
−
add a,d
+
−
sub 96
+
−
jp m,Check_clip_middle
+
−
and $F8
+
−
rra
+
−
rra
+
−
rra
+
−
ld l,a
+
−
ld a,(bigskip)
+
−
add a,l
+
−
inc a
+
−
ld (bigskip),a
+
−
neg
+
−
add a,c
+
−
ld c,a
+
−
xor a
+
−
ld (Do_Clipright),a
+
−
Check_clip_middle:
+
−
; This is where C should be saved.
+
−
xor a
+
−
ld (Do_ClipMiddle),a
+
−
ld a,c
+
−
or a
+
−
jp nz,dontskipmiddle
+
−
ld a,ClipMiddlesize
+
−
ld (Do_ClipMiddle),a
+
−
dontskipmiddle:
+
−
ld l,e
+
−
ld a,d
+
−
ld h,0
+
−
ld d,h
+
−
add hl,hl
+
−
add hl,de
+
−
add hl,hl
+
−
add hl,hl
+
−
ld e,a
+
−
and $07
+
−
xor 7
+
−
ld (BigRot1),a
+
−
ld (BigRot2),a
+
−
ld (BigRot3),a
+
−
add a,a
+
−
ld (clipbigrot1),a
+
−
ld a,$ff
+
−
clipbigrot1 = $+1
+
−
jr $
+
−
srl a
+
−
srl a
+
−
srl a
+
−
srl a
+
−
srl a
+
−
srl a
+
−
srl a
+
−
srl e
+
−
srl e
+
−
srl e
+
−
add hl,de
+
−
ld de,gbuf
+
−
add hl,de
+
−
; This is where gbuf offset should be saved.
+
−
ld d,a
+
−
cpl
+
−
ld e,a
+
−
;masks should be saved to
+
−
BigSpriteRow:
+
−
push bc
+
−
push hl
+
−
ld b,c
+
−
Do_Clipleft = $+1
+
−
jr Clipleft
+
−
ld a,(ix)
+
−
inc ix
+
−
BigRot1 = $+1
+
−
jr $
+
−
rrca
+
−
rrca
+
−
rrca
+
−
rrca
+
−
rrca
+
−
rrca
+
−
rrca
+
−
BigMask0:
+
−
and e
+
−
or (hl)
+
−
ld (hl),a
+
−
Clipleft:
+
−
Clipleftsize = Clipleft-(Do_Clipleft+1)
+
−
 
+
−
Do_ClipMiddle = $+1
+
−
jr $+2
+
−
BigSpriteloop:
+
−
ld a,(ix)
+
−
inc ix
+
−
BigRot2 = $+1
+
−
jr $
+
−
rrca
+
−
rrca
+
−
rrca
+
−
rrca
+
−
rrca
+
−
rrca
+
−
rrca
+
−
ld c,a
+
−
BigMask1:
+
−
and d
+
−
or (hl)
+
−
ld (hl),a
+
−
inc hl
+
−
ld a,c
+
−
BigMask2:
+
−
and e
+
−
or (hl)
+
−
ld (hl),a
+
−
djnz BigSpriteloop
+
−
ClipMiddle:
+
−
ClipMiddlesize = ClipMiddle-(Do_ClipMiddle+1)
+
−
 
+
−
Do_ClipRight = $+1
+
−
jr ClipRight
+
−
ld a,(ix)
+
−
BigRot3 = $+1
+
−
jr $
+
−
rrca
+
−
rrca
+
−
rrca
+
−
rrca
+
−
rrca
+
−
rrca
+
−
rrca
+
−
BigMask3:
+
−
and d
+
−
or (hl)
+
−
ld (hl),a
+
−
ClipRight:
+
−
Cliprightsize = ClipRight-(Do_ClipRight+1)
+
−
pop hl
+
−
 
+
−
ld bc,12 ;width of the screen
+
−
add hl,bc
+
−
 
+
−
bigskip = $+1
+
−
ld bc,0
+
−
add ix,bc
+
−
pop bc
+
−
djnz BigSpriteRow
+
−
ret
+
−
</nowiki>
+

Latest revision as of 02:13, 25 June 2010