Created
October 18, 2011 02:06
-
-
Save tjake/1294446 to your computer and use it in GitHub Desktop.
Final project for college assember
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; T Jake Luciani -- pong.asm | |
; CSC 209 Final Exemption Program (1997) | |
; | |
; This program is an implementation of the arcade game PONG written in | |
; 808386 assembly language. The game has one paddle and the ball has 8 | |
; degrees of fredom the user can move the paddle up and down with the | |
; up and down arrow. The user has 4 balls per game, and the user can | |
; exit the game by hitting the ESC key. Please Enjoy! | |
.386 ; give access to EAX, etc. | |
.model use16 small ; still in real mode (with near addressing) | |
.stack 1024 ; initialize stack | |
.data ; data segment begins... | |
BUF db ' WALL PONG! Ball:3 ','$' | |
ENDBUF db 'GAME OVER!','$' | |
level db 12 ; contains a value from 1 to 22 | |
ncount equ 22 ; max value for level | |
totrow equ 25 ; total # of rows on screen | |
startx equ 66 ; default x position of ball | |
starty equ 12 ; default y position of ball | |
startmom equ 1 ; default direction of ball | |
status db 1 ; 1 play game ; 0 end game | |
ballnum db '3' ; number of balls | |
ballx db startx ; variable for balls x pos | |
bally db starty ; variable for balls y pos | |
oldx db ? ; keep track of balls last pos | |
oldy db ? ; and use them to clean up char | |
ballmom db startmom ; variable for balls direction | |
oldvec dd ? ; saved timer interrupt handler address | |
.code ; code segment begins... | |
main proc far ; program... | |
startupcode ; establish addressability | |
; clear screen p.141 | |
mov ax,0600h | |
mov bh,1Ah ; blue background (1), bright green foreground (A) | |
mov cx,0000h ; top right corner | |
mov dx,184fh ; bottom left corner | |
int 10h ; call interupt | |
push si ; save si before calling disp | |
mov ax,0 ; put line on top | |
lea si,BUF ; Title line | |
call disp ; show line | |
pop si | |
; initialize all counters, and "level" | |
; just use the static inits for the moment | |
; hook interrupt handler | |
; save old p.471-2 | |
cli ; turn off interrupts | |
push 0 | |
pop es | |
mov eax,dword ptr es:32 ; save old interrupt handler | |
mov oldvec,eax | |
; establish new interrupt handler | |
mov word ptr es:34,cs | |
mov word ptr es:32,offset handler | |
sti ; turn interrupts back on | |
; enter main loop to read up and down arrows for paddle | |
; and esc, and set "level" or exit accordingly | |
mainloop: | |
mov eax,0 | |
mov ah,08h ; keyboard input without echo | |
int 21h ; p.188 | |
cmp al,00 ; extended? | |
jnz asciichar ; no, ascii | |
int 21h ; repeat for scancode | |
cmp al,48h ; up-arrow? | |
je uparrow | |
cmp al,50h ; down-arrow? | |
je downarrow | |
; otherwise ignore | |
jmp mainloop | |
asciichar: | |
cmp al,1bh ; esc? if so quit | |
je quit | |
jmp mainloop | |
downarrow: | |
mov al,level ; get current level | |
cmp al,ncount ; check to make sure not at bottom | |
je mainloop | |
inc al ; else go down a level | |
mov level,al ; save new level | |
jmp mainloop ; return | |
uparrow: | |
mov al,level ; get current level | |
cmp al,1 ; make sure not at top | |
je mainloop | |
dec al ; else go up a level | |
mov level,al ; save new level | |
jmp mainloop ; return | |
; before exiting, restore old interrupt handler | |
quit: | |
cli ; turn off interupts | |
push 0 | |
pop es | |
mov eax,oldvec ; get addr of old interrupt | |
mov dword ptr es:32,eax ; put back old interrupt | |
sti ; turn back on interrupts | |
mov ax,0600h ; clear screen and put back orig colors | |
mov bh,07h ; white on black | |
mov cx,0000h | |
mov dx,184fh | |
int 10h | |
exitcode 0 | |
main endp | |
; interrupt handler for program | |
handler proc near | |
pushad ; save everything | |
push ds | |
push es | |
mov ax,@data ; initialize data segment | |
mov ds,ax | |
mov dh,status ; check to make sure handler should run | |
cmp dh,0 | |
je endint ; if not exit from handler | |
mov dh,1 ; serves as row number | |
mov dl,0 ; servers as index for paddle length | |
handloop: | |
cmp dh,level ; check to see if at level | |
je drawpaddle ; if so draw the paddle | |
cmp dh,totrow ; check to see if at bottom of row | |
je moveball ; if so goto next step, moving the ball | |
mov ax,0b800h ; load address of screen memory | |
mov es,ax ; put it in extra segment | |
movzx di,dh ; zero extend row level | |
imul di,160 ; goto first column | |
mov al,' ' ; put a scace there | |
mov es:[di],al | |
inc dh ; do this for entire column exept for paddle | |
jmp handloop | |
drawpaddle: | |
cmp dl,3 ; check to see if 3 chars were drawn | |
je handloop ; if so, clear rest of column | |
mov ax,0b800h ; if not load address of screen memory | |
mov es,ax ; put it into extra segment | |
movzx di,dh ; zero extend row num | |
imul di,160 ; goto first column | |
mov al,0dbh ; put a solid block there | |
mov es:[di],al | |
inc dl ; increment paddle length counter | |
inc dh ; increment row num | |
jmp drawpaddle ; draw next block | |
moveball: | |
mov al,ballx ; get current xpos | |
mov ah,bally ; get current ypos | |
mov oldx,al ; save those for removal of old ball char | |
mov oldy,ah | |
mov dl,ballmom ; get current ball direction | |
;first determine if the direction is goin to change | |
cmp al,158 ; check to see if ball is against right wall | |
je go_left ; if so change direction to left | |
cmp al,0 ; check to see if ball is against left wall | |
je where_paddle ; if so check to see if it is touching paddle | |
cmp ah,1 ; check to see if ball is against top | |
je go_down ; if so change direction to down | |
cmp ah,24 ; check to see if ball is against bottom | |
je go_up ; if so chang direction to up | |
jmp rdy ; if no dir changes are needed we are ready | |
; to move the ball | |
go_left: | |
cmp ah,1 ; if ball is in top right corner reverse dir | |
je l_op2 | |
cmp ah,24 ; if ball is in bottom right corner reverse dir | |
je l_op3 | |
cmp dl,1 ; if direction is up-right | |
je chdir_6 ; change to up-left | |
cmp dl,7 ; if direction is up-right-right | |
je chdir_6 ; change to up-left | |
cmp dl,2 ; if direction is right | |
je chdir_5 ; change to left | |
cmp dl,3 ; if direction is down-right | |
je chdir_4 ; change to down-left | |
cmp dl,8 ; if direction is down-right-right | |
je chdir_4 ; change to down-left | |
l_op2: ; top right corner option | |
cmp dl,1 ; if direction is up-right | |
je chdir_4 ; opposite is down left | |
cmp dl,7 ; if direction is up-right-right | |
je chdir_4 ; opposite is down left | |
cmp dl,2 ; if direction is right | |
je chdir_5 ; opposite is left | |
l_op3: ; bottom right corner option | |
cmp dl,2 ; if direction is right | |
je chdir_5 ; opposite is left | |
cmp dl,3 ; if direction is down-right | |
je chdir_6 ; opposite is up-left | |
cmp dl,8 ; if direction is down-right-right | |
je chdir_6 ; opposite is up-left | |
where_paddle: ; routine for checking if paddle is | |
; hitting the ball | |
mov ch,level ; get current paddle row | |
cmp ah,ch ; check to see if top 1/3 is hitting ball | |
je padthere1 ; if so deflect using specified rules | |
inc ch ; go to middle 1/3 of paddle | |
cmp ah,ch ; if hitting ball deflect using other rules | |
je padthere2 | |
inc ch ; goto bottom 1/3 of paddle | |
cmp ah,ch ; if hitting ball deflect using same | |
je padthere1 ; rules as top 1/3 | |
; if at this point the ball missed the paddle | |
mov dl,ballnum ; get the current ball # | |
cmp dl,'0' ; if last ball then set end game status | |
je endgame | |
dec dl ; else lose one ball | |
mov ballnum,dl ; save | |
mov dl,138 ; proper column for ball number on screen | |
mov ax,0b800h ; get address for screen memory | |
mov es,ax ; put in extra segment | |
movzx ax,dl ; sign extend the column number | |
mov di,0 ; specify the first row | |
imul di,160 ; goto the first column | |
add di,ax ; move to the specified column | |
mov al,ballnum | |
mov es:[di],al ; replace the ball number | |
inc di ; goto the attribute byte | |
mov al,0A1h ; set it to blue background and | |
; bright green forground | |
mov es:[di],al | |
mov al,startx ; restart the game at the default x,y position | |
mov ballx,al | |
mov al,starty | |
mov bally,al | |
mov al,startmom ; use the default direction | |
mov ballmom,al | |
jmp endint ; end the interrupt handler | |
endgame: | |
push si ; save the stack index | |
mov al,12 ; want the 12th row | |
mov ah,66 ; the 33rd col | |
lea si,ENDBUF ; specify the game over message | |
call disp ; display it | |
pop si | |
mov dl,0 ; tell the interrupt handler to stop working | |
mov status,dl ; set status to 0 | |
jmp endint | |
padthere1: ; rules for deflecting the ball off the paddle | |
cmp ah,1 ; if top left corner then deflect in opposite dir | |
je r1_op2 | |
cmp ah,24 ; if bottom left corner deflect in opposite | |
je r1_op3 | |
cmp dl,6 ; if direction is up-left | |
je chdir_3_5 ; deflect down-right-right | |
cmp dl,5 ; if direction is left | |
je chdir_2 ; deflect right | |
cmp dl,4 ; if direction is down-left | |
je chdir_1_5 ; deflect up-right-right | |
r1_op2: ; rules for upper left corner | |
cmp dl,6 ; if direction is up-left | |
je chdir_3 ; opposite is down-right | |
cmp dl,5 ; if direction is left | |
je chdir_2 ; opposite is rules | |
r1_op3: ; rules for lower left corner | |
cmp dl,4 ; if direction is down-left | |
je chdir_1 ; opposite is up-right | |
cmp dl,5 ; if direction is left | |
je chdir_2 ; opposite is right | |
padthere2: ; other rules for deflecting ball | |
cmp ah,1 ; if top right corner deflect opposite dir | |
je r_op2 | |
cmp ah,24 ; if bottom right corner deflect opposite dir | |
je r_op3 | |
cmp dl,6 ; if direction is up-left | |
je chdir_1 ; deflect up-right | |
cmp dl,5 ; if direction is left | |
je chdir_2 ; deflect right | |
cmp dl,4 ; if direction is down-left | |
je chdir_3 ; deflect down-right | |
r_op2: ; rules for ball in upper left corner | |
cmp dl,6 ; if direction is up-left | |
je chdir_3 ; opposite is down-right | |
cmp dl,5 ; is direction is left | |
je chdir_2 ; opposite is right | |
r_op3: ; rules for ball in bottom left corner | |
cmp dl,4 ; if direction is down-left | |
je chdir_1 ; opposite is up-right | |
cmp dl,5 ; if direction is left | |
je chdir_2 ; opposite right | |
go_down: | |
cmp dl,1 ; if direction is up-right | |
je chdir_3 ; deflect down right | |
cmp dl,7 ; if direction is up-right-right | |
je chdir_3 ; deflect down-right | |
cmp dl,6 ; if direction is up-left | |
je chdir_4 ; deflect down-left | |
go_up: | |
cmp dl,4 ; if direction is down-left | |
je chdir_6 ; deflect up-left | |
cmp dl,3 ; if direction is down-right | |
je chdir_1 ; deflect up-right | |
cmp dl,8 ; if direction is down-right-right | |
je chdir_1 ; deflect up-right | |
chdir_1: | |
mov dl,1 ; change ball direction to up-right | |
jmp rdy ; ready to display new position | |
chdir_1_5: | |
mov dl,7 ; change ball direction to up-right-right | |
jmp rdy ; ready to display new position | |
chdir_2: | |
mov dl,2 ; change ball direction to left | |
jmp rdy ; ready to display new position | |
chdir_3: | |
mov dl,3 ; change ball direction to down-right | |
jmp rdy ; ready to display new position | |
chdir_3_5: | |
mov dl,8 ; change ball direction to down-right-right | |
jmp rdy ; ready to display new position | |
chdir_4: | |
mov dl,4 ; change ball direction to down-left | |
jmp rdy ; ready to display new ball position | |
chdir_5: | |
mov dl,5 ; change ball direction to left | |
jmp rdy ; ready to display new ball position | |
chdir_6: | |
mov dl,6 ; change ball direction to up-left | |
jmp rdy ; ready to display new ball position | |
rdy: ; once direction is taken care of we move | |
; the ball in the proper dirction and remove | |
; the old ball char | |
mov ballmom,dl ; first save the direction | |
mov dh,oldy ; get the old xpos | |
mov dl,oldx ; get the old ypos | |
mov ax,0b800h ; get address of screen memory | |
mov es,ax ; put it into th extra segment | |
movzx ax,dl ; zero extend the x position | |
movzx di,dh ; zero extend the y position | |
imul di,160 ; goto the first column of y row | |
add di,ax ; move over x columns | |
mov al,' ' | |
mov es:[di],al ; cover up old ball char | |
mov dh,bally ; put xpos into dh | |
mov dl,ballx ; put ypos into dl | |
mov cl,ballmom ; put direction in cl | |
cmp cl,1 ; if direction is 1 move up-right | |
je do_1 | |
cmp cl,2 ; if direction is 2 move right | |
je do_2 | |
cmp cl,3 ; if direction is 3 move down-right | |
je do_3 | |
cmp cl,4 ; if direction is 4 move down-left | |
je do_4 | |
cmp cl,5 ; if direction is 5 move left | |
je do_5 | |
cmp cl,6 ; if direction is 6 move up-left | |
je do_6 | |
cmp cl,7 ; if direction is 7 move up-right-right | |
je do_1_5 | |
cmp cl,8 ; if direction is 8 move down-right-right | |
je do_3_5 | |
do_1: | |
add dl,2 ; move x right 1 | |
sub dh,1 ; move y up 1 | |
jmp show_ball ; put ball on screen | |
do_1_5: | |
add dl,4 ; move x right 2 | |
sub dh,1 ; move y up 1 | |
jmp show_ball ; put ball on screen | |
do_2: | |
add dl,2 ; move x right 1 | |
jmp show_ball ; put ball on screen | |
do_3: | |
add dl,2 ; move x right 1 | |
add dh,1 ; move y down 1 | |
jmp show_ball ; put ball on screen | |
do_3_5: | |
add dl,4 ; move x right 2 | |
add dh,1 ; move y down 1 | |
jmp show_ball ; put ball on screen | |
do_4: | |
sub dl,2 ; move x left 1 | |
add dh,1 ; move y down 1 | |
jmp show_ball ; put ball on screen | |
do_5: | |
sub dl,2 ; move x left 1 | |
jmp show_ball ; put ball on screen | |
do_6: | |
sub dl,2 ; move x left 1 | |
sub dh,1 ; move y up 1 | |
jmp show_ball ; put ball on screen | |
show_ball: ; displays new ball | |
mov ballx,dl ; save new x pos | |
mov bally,dh ; save new y pos | |
mov ax,0b800h ; get address of screen mem | |
mov es,ax ; put it in extra segment | |
movzx ax,dl ; zero extend x pos | |
movzx di,dh ; zero extend y pos | |
imul di,160 ; goto first column of y row | |
add di,ax ; move x cols | |
mov al,02h ; ball is smiley face | |
mov es:[di],al ; put it in screen | |
jmp endint ; end interrupt handler | |
endint: | |
pushf ; save flags | |
call oldvec ; run the orig interrupt handler | |
pop es | |
pop ds | |
popad | |
iret ; return from interrupt handler | |
handler endp | |
; | |
; Name: disp | |
; | |
; Purpose: Display the string pointed to by the address in SI. | |
; | |
; Input: AL should contain the line number, starting with 0 as the | |
; top line. AH should hold the the column. | |
; | |
disp proc near | |
push es ; save registers.. | |
push di | |
push dx | |
push ax | |
mov dx,0b800h ; seg addr of video page | |
mov es,dx | |
movzx di,al ; DI := AL zero-extended to 16 bits | |
movzx dx,ah ; zero extend the column number | |
imul di,160 ; compute offset of beginning of line | |
add di,dx ; move to the column specified in dx | |
disploop: ; copy characters until a '$' is seen | |
mov al,[si] ; grab source byte | |
cmp al,'$' ; test for ender | |
je dispdone ; done if yes | |
mov es:[di],al ; store byte at destination | |
inc di ; bump destination ptr | |
mov al,0A1h ; associated attribute byte | |
mov es:[di],al ; store that too | |
inc di ; bump destination ptr again | |
inc si ; bump source ptr | |
jmp disploop ; round we go again | |
dispdone: ; the vicious cycle is broken | |
pop ax ; restore registers.. | |
pop dx | |
pop di | |
pop es | |
ret ; return to caller | |
disp endp | |
end main | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment