03-09-2010, 03:36 PM
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
I'll post it when it's finished 
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


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