Difference between revisions of "Z80 Routines:Graphic:put8x8sprite"
m |
(input of routine added) |
||
(3 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
− | [[Category:Z80 Routines:Graphic| | + | [[Category:Z80 Routines:Graphic|Put8xBsprite]][[Category:Z80 Routines|Put8xBsprite]] |
− | The ''' | + | |
− | + | The '''put8xBsprite''' routine is used to plot a 8xB sized sprite. | |
== Code == | == Code == | ||
− | === Version | + | === Basic Version === |
<nowiki> | <nowiki> | ||
+ | ;-----> 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 | ||
+ | </nowiki> | ||
+ | |||
+ | === Masked Version === | ||
+ | <nowiki> | ||
+ | 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 | ||
</nowiki> | </nowiki> | ||
− | === | + | === Full Clipping (vertical and horizontal) Version === |
<nowiki> | <nowiki> | ||
+ | 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 | ||
</nowiki> | </nowiki> | ||
+ | |||
+ | == 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 == | == Example == | ||
+ | |||
+ | A example using the basic version of PutSprite8xB. | ||
<nowiki> | <nowiki> | ||
;... | ;... |
Latest revision as of 05:01, 16 May 2010
The put8xBsprite routine is used to plot a 8xB sized sprite.
Contents
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