A82: sprite routine
[Prev][Next][Index][Thread]
A82: sprite routine
I recieved a few emails asking to see this routine so i decided to post it. .
.
If anyone wants it you can have it, also if anybody wants to optomize I would
appreciate seeing how you did it.
I have commented this as much as possible in order for it to be easy to
understand. See ya,
Gerad
===================here is the start of the important stuff!!!!!!!!
;This file contains three (eventually) sprite routines all written by Gerad
Suyderhoud
;for use in Galaga, written for ASH 3.0
;Thanks to Dines Justesen for showing me how the display port works
;and for writing ASH and all those nifty information files that helped me
;with higher level assembly programming
;make sure to set the rom page by doing this (or else the file won't work):
; ld a, $8C
; out (2), a
;+++++++++++
;Routine1- Puts a sprite stored at sprite
;(make a label like this after the end of your program)
;sprite:
; .db 00000000
; .db 00000000
;do the .db's 8 times (0 is a pixel off 1 is a pixel on)
; directly on to the display port
;input h= x location, the y location is set at the last 8 lines
;+++++++++++
;af, bc, de, hl, ix destroyed
; this is very badly coded, and could be optimized a lot, but I am not a good
;enough asm programmer to do it (plus I am just too lazy)
;to use this in your program write call galagasp when you want a sprite put
; and before the .end directive type in #include "galaga.inc"
;alright I've decided to comment this to help others
;anybody that wants to tell me how to optimize this routine
;or that has questions, e-mail me at GeradS711@aol.com
;=======START OF PROGRAM======
galagasp:
ld a, $B7
ld c, a ;sets the row to the last four rows
ld a, 5
call $7F3
out (10h), a ;sets the rom page so you can write to the display port
ld ix, sprite ;loads the sprite's location in the mem to ix (a reg
draw: ;like hl except that it is two bytes bigger)
call mover ;calls the routine that shifts the bytes at ix
call $7F3 ; calls the display delay, you have to do this before
out (10h), a ; all writes to the display port, loads the column to a
inc a ;increases the column and saves it into the stack
push af
ld a, c ; loads the row to write the bytes
call $7F3 ;display delay
out (10h), a ;writes the row to the display port
ld a, d ;loads the first set of bytes (will be explained more at
call $7F3 ;the end of the program) Disp delay
out (11h), a ;writes the bytes
ld a, c ; reloads the row (for some reason it gets destroyed
call $7F3 ;when you write bytes) Disp delay
out (10h), a ;tells the display controller where to write
pop af ;loads a (the column pos) from the stack
push af ;and saves it again
call $7F3 ;Disp Delay
out (10h), a ;tells the display controller where to write
ld a, e ;lds the second bytes to write
call $7F3 ;Disp Delay
out (11h), a ;out (11h), a
ld a, c ;loads a with the row again
call $7F3 ;disp delay
out (10h), a ;this part of the routine simply over writes the residue
pop af ;from the sprite
dec a
dec a
cp $20
jr c, drawend
call $7F3
out (10h), a
ld a, $00
call $7F3
out (11h), a
drawend:
inc ix ;goes to the next 8-bits of the sprite
inc c ;goes to the next row
ld a, c ;if it is the last row quit
cp $BF ; you can only use cp with the a reg
jr nz, draw ;if not do it again
ret
mover: ;this routine moves the bytes over because there are only 12
ld l, h ;rows in the 82 display, in order to write to a different row
ld a, h ;you must shift the byte
push af ;the previous lines just stored the x-pos to 3 different locs
srl l ;divide the x-pos by 8
srl l
srl l ;shift right logically divides l by 2(^3 = 8)
ld a, l
add a, $20
ld e, a
sla l ;shift right logically multiplies l by 2(^3)=8
sla l
sla l ; mulitply the rounded result of the divide by 8
ld b, l
pop af
sub b ;a= column between 0 and 12
ld b, a ;b= number of shift rights to do.
ld a, e
push af ;save the column for the earlier routine
ld a, (ix) ;load the sprite's row to a
ld d, a ;load d with a
ld e, 0 ; loads e with 0
ld a, b ;checks to see if b is zero
or a
jr z, extra ;if it is go to extra so the sprite doesn't shift
shifter:
srl d ;shifts d and e the number of times that it needs to so that
rr e ;displays right
djnz shifter ;decrease b, jump to shifter if not zero
extra:
pop af
ret ;return to draw
;Alright this is the end of the program, and I admit that it is a little
;complicated, however if you take it one section at a time it is
;relatively simple to understand in comparison with other sprite routines
;plus this is hella fast. :-)
;The first section of the routine (up to draw) initializes the vars
;loading the row and the location in the mem of the sprite
;the next section is the mover routine. This is the really complicated
;part. Since there are 12 columns in the 82 display and 96 pixels
;in the x-row you must write bytes that have been shifted. The first
;part of mover (up to shifter) does this, if you pardon the ti-basic
;analogy: the pos you want to put the cursor is x
;int x/8 sto-> a
;x-8Ans sto-> b
;now the row is stored in a
;and the remainder of the divide is stored in b
;here is a nice picture to help you understand
;The ti-82 display
;__________________________________________
;|
;|
;|
;|Columns:
;|0 1 2 3 4 5 6 7 8 9 10 11 12
;------------------------------------------
;Pixels:
;1 to 96 pixels (actually it 0 to 95)
;row 0 starts at 1 row 2 starts at 8, row 3 at 16
;so if you want to put a pixel at 9 you would have to write a byte
;at row 1 that looks like this
;%01000000
;at pixel 10
;%00100000
;at pixel 2 you would have to set the column to 0
;and write this byte
;%01000000
;at pixel 1
;%10000000
;one thing that you must know is that to change the column you have to
;add $20 to the row number
;so column 1 is actually $21
;the next part is at shifter, if you fully understand the last part
;then this should be easy to understand :-)
;the shifter makes sure that the line is at the right pixel
;say one line of your sprite looks like this
; .db %10101010
;if you wanted to write the byte to the second pixel you would have to
;make the column 0 and move everything one right. Luckily there is a
;command that does this
;srl makes 10101010 into 01010101
;say you did this twice
;what happens to that last bit, it is pushed off the end of the byte
;and it sets the carry flag
;in order to make sure that you still write the bit you stor it to e
;using rr e which does this
; c->bit 0 -> bit 1 -> bit 2 etc
; then you write both bytes to the display port
;as an example say that you want to write %01101101 to the display port
;starting at pixel 5
;store the byte to d
;then do this five times
; srl d
; rr e
; so the first time the byte looks like this
; d = %00110110
; e = %10000000
;by the fifth time it looks like this
; d = %00000011
; e = %01101000
;so if you were to put this to the display with d at row 0
;and e at row 1 like the disp routine does it would look right
;well everything else is pretty much self explanitory
;email me at GeradS711@aol.com if you've got questions