Skip to content

Instantly share code, notes, and snippets.

@tjake
Created October 18, 2011 02:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tjake/1294446 to your computer and use it in GitHub Desktop.
Save tjake/1294446 to your computer and use it in GitHub Desktop.
Final project for college assember
; 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