Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Stack Bug in ZXB 1.2.5-r1489 ?
#14
Sprite.bas: This is a sprite shifting routine by Johnatan Cauldwell. I modified it a bit so it could not only XOR graphics, but also AND, OR and stright PRINT. I only use the AND and XOR because I love masked graphics.

It's too slow ATM, so it flickers a lot (which is good for a game made for the crap games compo). I want to make a version that works in a backbuffer and then copy the buffer to screen. In fact that's what I am doing at the moment (the transfer routine), but it's my first ever assembler routine and I'm having problems Smile I'll post it when it's finished Smile

Code:
SUB psprite (xd as ubyte,yd as ubyte,gfx as uinteger)
POKE @esprite,xd: POKE @esprite+1,yd: POKE Uinteger (@esprite+2),gfx
POKE @xor1,121:POKE @xor2,122:POKE @xor3,123
gosub printsprite
END SUB

SUB xorsprite (xd as ubyte,yd as ubyte,gfx as uinteger)
POKE @esprite,xd: POKE @esprite+1,yd: POKE Uinteger (@esprite+2),gfx
POKE @xor1,169:POKE @xor2,170:POKE @xor3,171:POKE @mask+1,0: POKE @carry,167':POKE @esprite+5,7:'POKE @esprite+4,255':POKE @esprite+6,60
gosub printsprite
END SUB

SUB andsprite (xd as ubyte,yd as ubyte,gfx as uinteger)
POKE @esprite,xd: POKE @esprite+1,yd: POKE Uinteger (@esprite+2),gfx
POKE @xor1,161:POKE @xor2,162:POKE @xor3,163:POKE @mask+1,255:POKE @carry,0':POKE @esprite+5,0:POKE @esprite+4,246'230':POKE @esprite+6,0
gosub printsprite
END SUB

SUB orsprite (xd as ubyte,yd as ubyte,gfx as uinteger)
POKE @esprite,xd: POKE @esprite+1,yd: POKE Uinteger (@esprite+2),gfx
POKE @xor1,177:POKE @xor2,178:POKE @xor3,179
gosub printsprite
END SUB

SUB spriteh (h as ubyte)
POKE @altura+1,h
END SUB



esprite:
ASM
xp: defb 0
yp: defb 0
gfxdir: defw 0




; This is the sprite routine and expects coordinates in (c ,b) form,
; where c is the vertical coord from the top of the screen (0-176), and
; b is the horizontal coord from the left of the screen (0 to 240).
; Sprite data is stored as you'd expect in its unshifted form as this
; routine takes care of all the shifting itself.  This means that sprite
; handling isn't particularly fast but the graphics only take 1/8th of the
; space they would require in pre-shifted form.

; On entry HL must point to the unshifted sprite data.

sprit7: xor 7               ; complement last 3 bits.
       inc a               ; add one for luck!
sprit3: rl d                ; rotate left...
       rl c                ; ...into middle byte...
       rl e                ; ...and finally into left character cell.
       dec a               ; count shifts we've done.
       jr nz,sprit3        ; return until all shifts complete.

; Line of sprite image is now in e + c + d, we need it in form c + d + e.

       ld a,e              ; left edge of image is currently in e.
       ld e,d              ; put right edge there instead.
       ld d,c              ; middle bit goes in d.
       ld c,a              ; and the left edge back into c.
       jr sprit0           ; we've done the switch so transfer to screen.
END ASM
printsprite:
ASM
sprite:
       ld hl,(gfxdir)
       ld bc,(xp)
       ld (dispx),bc       ; store coords in dispx for now.
       call scadd          ; calculate screen address.
END ASM
altura:
ASM
       ld a,16             ; height of sprite in pixels.
sprit1: ex af,af'           ; store loop counter.
       push de             ; store screen address.
       ld c,(hl)           ; first sprite graphic.
       inc hl              ; increment poiinter to sprite data.
       ld d,(hl)           ; next bit of sprite image.
       inc hl              ; point to next row of sprite data.
       ld (sprtmp),hl      ; store it for later.
END ASM
mask:
ASM
       ld e,0              ; blank right byte for now.
       ld a,b              ; b holds y position.
       and 7               ; how are we straddling character cells?
       jr z,sprit0         ; we're not straddling them, don't bother shifting.
       cp 8                ; 5 or more right shifts needed?
       jr nc,sprit7        ; yes, shift from left as it's quicker.
end asm
carry:
asm
       and a               ; oops, carry flag is set so clear it.
sprit2: rr c                ; rotate left byte right...
       rr d                ; ...through middle byte...
       rr e                ; ...into right byte.
       dec a               ; one less shift to do.
       jr nz,sprit2        ; return until all shifts complete.
sprit0: pop hl              ; pop screen address from stack.
       ld a,(hl)           ; what's there already.
END ASM
xor1:
ASM
       xor c               ; merge in image data.   a9 169             a1  161               79 121           b1  177
       ld (hl),a           ; place onto screen.
       inc l               ; next character cell to right please.
       ld a,(hl)           ; what's there already.
END ASM
xor2:
ASM
       xor d               ; merge with middle bit of image.    aa  170           a2 162            7a 122      b2  178
       ld (hl),a           ; put back onto screen.
       inc l               ; next bit of screen area.
       ld a,(hl)           ; what's already there.
END ASM
xor3:
ASM
       xor e               ; right edge of sprite image data.     ab 171            a3 163             7b 123         b3    179
       ld (hl),a           ; plonk it on screen.
       ld a,(dispx)        ; vertical coordinate.
       inc a               ; next line down.
       ld (dispx),a        ; store new position.
       and 63              ; are we moving to next third of screen?
       jr z,sprit4         ; yes so find next segment.
       and 7               ; moving into character cell below?
       jr z,sprit5         ; yes, find next row.
       dec l               ; left 2 bytes.
       dec l               ; not straddling 256-byte boundary here.
       inc h               ; next row of this character cell.
sprit6: ex de,hl            ; screen address in de.
       ld hl,(sprtmp)      ; restore graphic address.
       ex af,af'           ; restore loop counter.
       dec a               ; decrement it.
       jp nz,sprit1        ; not reached bottom of sprite yet to repeat.
       ret                 ; job done.
sprit4: ld de,30            ; next segment is 30 bytes on.
       add hl,de           ; add to screen address.
       jp sprit6           ; repeat.
sprit5: ld de,63774         ; minus 1762.
       add hl,de           ; subtract 1762 from physical screen address.
       jp sprit6           ; rejoin loop.


; This routine returns a screen address for (c, b) in de.

scadd:  ld a,c              ; get vertical position.
       and 7               ; line 0-7 within character square.
       add a,64            ; 64 * 256 = 16384 (Start of screen display)
       ld d,a              ; line * 256.
       ld a,c              ; get vertical again.
       rrca                ; multiply by 32.
       rrca
       rrca
       and 24              ; high byte of segment displacement.
       add a,d             ; add to existing screen high byte.
       ld d,a              ; that's the high byte sorted.
       ld a,c              ; 8 character squares per segment.
       rlca                ; 8 pixels per cell, mulplied by 4 = 32.
       rlca                ; cell x 32 gives position within segment.
       and 224             ; make sure it's a multiple of 32.
       ld e,a              ; vertical coordinate calculation done.
       ld a,b              ; y coordinate.
       rrca                ; only need to divide by 8.
       rrca
       rrca
       and 31              ; squares 0 - 31 across screen.
       add a,e             ; add to total so far.
       ld e,a              ; hl = address of screen.
       ret


dispx: defb 0        ; general-use coordinates.
dispy: defb 0
sprtmp: defw 0          ; sprite temporary address.

END ASM
Reply


Messages In This Thread

Forum Jump:


Users browsing this thread: 4 Guest(s)