Z80 Routines:Graphic:put8x8sprite

From WikiTI
Jump to: navigation, search


The put8xBsprite routine is used to plot a 8xB sized sprite.

Code

Basic Version

;-----> Draw a sprite
; input:	a=x	e=y
;		b=height of sprite
;		ix holds pointer
; output:	
; destroys de,hl
putSprite8xb:
	ld	h,$00
	ld	d,h
#ifdef	faster
	sla e			;*2
	sla e			;*4
#endif
	ld	l,e
	add	hl,de		;*2	faster:*8
	add	hl,de		;*3	faster:*12
#ifndef	faster
	add	hl,hl		;*6
	add	hl,hl		;*12
#endif
	ld e,a
	srl	e
	srl	e
	srl	e
	add	hl,de
	ld	de,gbuf
	add	hl,de
	and 7
	ld c,a
putSpriteLoop1:
	ld	d,(ix)
	ld	e,$00
	ld a,c
	or a
	jr	z,putSpriteSkip1
putSpriteLoop2:
	srl	d
	rr	e
	dec	a
	jr	nz,putSpriteLoop2
putSpriteSkip1:
	ld	a,(hl)
	xor	d
	ld	(hl),a
	inc	hl
	ld	a,(hl)
	xor	e
	ld	(hl),a
	ld	de,$0B
	add	hl,de
	inc	ix
	djnz	putSpriteLoop1
	ret
 

Masked Version

PutSpriteMask:
; Displays an 8x8 masked sprite
; A = x coordinate
; E = y coordinate
; IX = address of sprite
; IX + 8 = address of mask
    LD     H, 0
    LD     D, H
    LD     E, L
    ADD    HL, HL
    ADD    HL, DE
    ADD    HL, HL
    ADD    HL, HL

    LD     E, A
    SRL    E
    SRL    E
    SRL    E
    ADD    HL, DE

    LD     DE, PlotSScreen
    ADD    HL, DE

    AND    7
    JR     Z, _Aligned
    LD     C, A
    LD     B,8

_RowLoop:
    PUSH   BC
    LD     B, C
    LD     D, (IX)
    LD     A, (IX + 8)
    LD     C, 0
    LD     E, C

_ShiftLoop:
    SRL    A
    RR     C
    SRL    D
    RR     E
    DJNZ   _ShiftLoop

    CPL
    AND    (HL)
    XOR    D
    LD     (HL), A

    INC    HL
    LD     A, C

    CPL
    AND    (HL)
    XOR    E
    LD     (HL), A

    LD     DE, 12
    ADD    HL, DE
    INC    IX
    POP    BC
    DJNZ   _RowLoop
    RET

_Aligned:
    LD     DE, 12

_PutLoop
    LD     A, (IX + 8)
    AND    (HL)
    XOR    (IX)
    LD     (HL), A
    INC    IX
    ADD    HL, DE
    DJNZ   _PutLoop
    RET

 

Full Clipping (vertical and horizontal) Version

ClipSprXOR:
; D = xpos
; E = ypos
; B = height
; IX = image address
; Start by doing vertical clipping
    LD     A, %11111111         ; Reset clipping mask
    LD     (clip_mask), A
    LD     A, E                 ; If ypos is negative
    OR     A                    ; try clipping the top
    JP     M, ClipTop           ;
 
    SUB    64                   ; If ypos is >= 64
    RET    NC                   ; sprite is off-screen

    NEG                         ; If (64 - ypos) > height
    CP     B                    ; don't need to clip
    JR     NC, VertClipDone     ; 

    LD     B, A                 ; Do bottom clipping by
    JR     VertClipDone         ; setting height to (64 - ypos)

ClipTop:
    LD     A, B                 ; If ypos <= -height
    NEG                         ; sprite is off-screen
    SUB    E                    ;
    RET    NC                   ;

    PUSH   AF
    ADD    A, B                 ; Get the number of clipped rows
    LD     E, 0                 ; Set ypos to 0 (top of screen)
    LD     B, E                 ; Advance image data pointer
    LD     C, A                 ;
    ADD    IX, BC               ;
    POP    AF
    NEG                         ; Get the number of visible rows
    LD     B, A                 ; and set as height

VertClipDone:
; Now we're doing horizontal clipping
    LD     C, 0                 ; Reset correction factor
    LD     A, D

    CP     -7                   ; If 0 > xpos >= -7
    JR     NC, ClipLeft         ; clip the left side

    CP     96                   ; If xpos >= 96
    RET    NC                   ; sprite is off-screen

    CP     89                   ; If 0 <= xpos < 89
    JR     C, HorizClipDone     ; don't need to clip

ClipRight:
    AND    7                    ; Determine the clipping mask
    LD     C, A
    LD     A, %11111111
FindRightMask:
    ADD    A, A
    DEC    C
    JR     NZ, FindRightMask
    LD     (clip_mask), A
    LD     A, D
    JR     HorizClipDone

ClipLeft:
    AND    7                    ; Determine the clipping mask
    LD     C, A
    LD     A, %11111111
FindLeftMask:
    ADD    A, A
    DEC    C
    JR     NZ, FindLeftMask
    CPL
    LD     (clip_mask), A
    LD     A, D
    ADD    A, 96                ; Set xpos so sprite will "spill over"
    LD     C, 12                ; Set correction

HorizClipDone:
; A = xpos
; E = ypos
; B = height
; IX = image address

; Now we can finally display the sprite.
    LD     H, 0
    LD     D, H
    LD     L, E
    ADD    HL, HL
    ADD    HL, DE
    ADD    HL, HL
    ADD    HL, HL

    LD     E, A
    SRL    E
    SRL    E
    SRL    E
    ADD    HL, DE

    LD     DE, PlotSScreen
    ADD    HL, DE

    LD     D, 0                 ; Correct graph buffer address
    LD     E, C                 ; if clipping the left side
    SBC    HL, DE               ;

    AND    7
    JR     Z, _Aligned

    LD     C, A
    LD     DE, 11

_RowLoop:
    PUSH   BC
    LD     B, C
    LD     A, (clip_mask)       ; Mask out the part of the sprite
    AND    (IX)                 ; to be horizontally clipped
    LD     C, 0

_ShiftLoop:
    SRL    A
    RR     C
    DJNZ   _ShiftLoop

    XOR    (HL)
    LD     (HL), A

    INC    HL
    LD     A, C
    XOR    (HL)
    LD     (HL), A

    ADD    HL, DE
    INC    IX
    POP    BC
    DJNZ   _RowLoop
    RET

_Aligned:
    LD     DE, 12

_PutLoop:
    LD     A, (IX)
    XOR    (HL)
    LD     (HL), A
    INC    IX
    ADD    HL, DE
    DJNZ   _PutLoop
    RET

clip_mask:      .DB     0

 

Customization

You can suit these routines to your needs by following the following suggestions: - change the input in e to l - replace the logic ("xor" intructions to "or" or "cpl \ and ") - instead of 8xB, you can put a ld b,8 - adapt for each sprite its height/width

.db 3				; height
.db %11111111
.db %11111111
.db %11111111

- take out horizontal/vertical clipping if you don't need it

You will need to change the code yourself. If you understand well assembly it will be a quick task.

Define faster to get more speed with size costs. To use these routines in the TI-85 or TI-86, you need to change not only the address of the graphics buffer but also the multiplication of the x coordinates. (TI-83+ screen is 96x64 instead of 128x64) Later we can provide a TI-85/86 version.


Example

A example using the basic version of PutSprite8xB.

   ;...
   ld   e,8   ;y
   ld   a,16  ;x
   ld   b,8   ;height
   ld   ix,sprite
   call putsprite
   call fastcopy
   ;...
sprite:
   .db %11111111
   .db %10000001
   .db %10000001
   .db %10000001
   .db %10000001
   .db %10000001
   .db %10000001
   .db %11111111