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