Z80 Routines:Graphic:largesprite
From WikiTI
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