ECE291 Computer Engineering II Lockwood, Fall 1998

Machine Problem 3: LiteCycles

Purpose Text-mode graphics, keyboard and timer interrupts.
Points 50
Due Date Wednesday 10/21/98 (25/50 points) - Checkpoint 1 
Wednesday 10/28/98 (50/50 points) - Checkpoint 2 

Introduction

In this MP, you will be implementing a game based on the famous litecycles scene from the great science fiction movie, TRON!. In this game, each of the two players drive hi-tech cycles within a game grid, generating colored walls behind them.  The object of the game is to force your opponent into one of the walls (either yours or theirs) while staying alive yourself.  With each round, the pace of play is increased and the players starting positions are varied. A view of the screen is shown below.

Text-mode Video

The display will be implemented using text-mode video. For maximum speed, your code will write directly to video memory (beginning at address B8000h).  Each character block on the screen represents an ASCII character and its corresponding attributes.  The attributes include the foreground color,  background color, and whether the character blinks or not.  A suitable set of attributes are given to you in MP3CONST.ASM.

Keyboard Control

This MP uses the keyboard to control movement. If a player is controlled via the keyboard, its direction is kept the same until a different direction is requested.  Since we do not want to stop the game while waiting for a keypress that may not occur, we need an asynchronous method for accessing keyboard input.  We will replace the default keyboard handler with our own code so that we don't have to wait for a keypress. We will instead just check a variable. The InstKey routine is called to install a new handler into the vector table. The DeInstKey routine is used to remove it (and restore the DOS default routine).

The topic of interrupts was discussed in great detail during the Lecture 14 class period. The operation of the keyboard controller was discussed during Lecture 16.

Timer Control

In many applications, it is important that events happen at the same rate, regardless of the speed of the machine. It wouldn't be very easy to play a version of PacMan written for a 8086 on a PPro without a timer, PacMan would perish before you could decide your first move!  We will write our own timer interrupt handler for this MP, which will allow us to specify the relative delay between events (which in our case will be updates of the state of the game).

The default timer interrupt rate is 18.2 times per second.  Unfortunately, this is not fast enough for this MP, as action can occur more frequently than that.  One of the jobs of InstTimer will be to increase the interrupt rate up to 72.8 times per second. See the lab notes for details.

Data Structures

Procedures

Preliminary Procedure

Revision History

Final Steps

  1. Print a copy of the MP3 grading sheet.
  2. Demonstrate the first checkpoint of MP3.EXE to a TA or to the instructor.
  3. Demonstrate the second checkpoint of MP3.EXE to a TA or to the instructor.
  4. Handin in your program by running:
  5. Staple the MP3 grading sheet to the front of your MP2.ASM file and give both to the same TA that approved your demonstration.

MP3.ASM

TITLE ECE291:MP3-LiteCycles - Your Name - Date

COMMENT % TRON LiteCycle Game with AI players.

          ECE291: Machine Problem 3
          Prof. John W. Lockwood
          Guest Author: Josh Scheid
          University of Illinois
          Dept. of Electrical & Computer Engineering
          Fall 1998
          
          Ver. 1.0
        %

;====== Constants =========================================================

INCLUDE mp3const.asm    ; MP3 constants file

;====== Externals =========================================================

; -- LIB291 Routines (Free) ---
extrn binasc:near, dspmsg:near
extrn rsave:near, rrest:near
extrn mp3xit:near               ; Exit program with a call to this procedure

; -- LIBMP3 Routines (Replace these with your own code) ---

extrn DrawScreen:near           ; display initial game grid on screen
extrn ResetGrid:near            ; initialize game grid
extrn DrawCycles:near           ; place cycles at new position and
                                ; check for collisions
extrn SetPlayerPos:near         ; determine player starting positions
extrn SetGameSpeed:near         ; determine new game speed
extrn InstTimer:near            ; install 'MyTimerHandler in place of default
                                ; handler and speed up timer rate
extrn DeInstTimer:near          ; deinstall 'MyTimerHandler'; reinstall
                                ; default handler and restore normal timer rate
extrn MyTimerHandler:near       ; handle timer interrupt
extrn InstKey:near              ; install 'MyKeyHandler' in place of default
extrn DeInstKey:near            ; deinstall 'MyKeyHandler'; reinstall default
extrn MyKeyHandler:near         ; handle keyboard interrupt

extrn GameMain:near             ; executes game loop and inner round loop

extrn P1Control:near            ; get next direction that player one will go
extrn P2Control:near            ; get next direction that player two will go

;====== SECTION 3: Define stack segment ===================================
stkseg  segment stack                   ; *** STACK SEGMENT ***
        db      64 dup ('STACK   ')     ; 64*8 = 512 Bytes of Stack
stkseg  ends

;====== SECTION 4: Define code segment ====================================
cseg    segment public  'CODE'    ; *** CODE SEGMENT ***
        assume  cs:cseg, ds:cseg, ss:stkseg, es:nothing

;====== SECTION 5: Variables ==============================================
PUBLIC StartMsg, CrashedMsg, WonRoundMsg, CrashedMsg, WonRoundMsg, AndMsg
PUBLIC BothCrashedMsg, CollidedMsg, SpaceMsg, Blank8Msg, RoundInfoMsg
PUBLIC grid, p1X, p1Y, p2X, p2Y 
PUBLIC playerPosState, p1Score, p2Score, p1Name, p2Name, escPressed, spcPressed      
PUBLIC p1KeyDir, p2KeyDir, p1Dir, p2Dir, round, pbuf 
PUBLIC oldTimerV, oldKeyV, timerCount, gameSpeed      

StartMsg        db CR,LF
  db '----------------------- MP3: LiteCycles ----------------------',CR,LF
  db CR,LF
  db 'Controls:  Player 1 (blue)    Player 2 (red)                 ',CR,LF
  db CR,LF
  db '   UP         W               8 (numpad)                  ',CR,LF
  db '   DOWN       S               2 (numpad)                  ',CR,LF
  db '   LEFT       A               4 (numpad)                  ',CR,LF
  db '   RIGHT      D               6 (numpad)                  ',CR,LF
  db CR,LF
  db 'Press the escape key  at any time to end the game.      ',CR,LF
  db CR,LF
  db 'Press the space bar now to begin!!!                          ',CR,LF,'$'

CrashedMsg      db ' crashed!','$'
WonRoundMsg     db ' won round ','$'
AndMsg          db ' and ','$'
BothCrashedMsg  db ' both crashed!','$'
CollidedMsg     db ' collided!','$'
SpaceMsg        db '(press the space bar to start next round)','$'
Blank8Msg       db '        ','$'

RoundInfoMsg    db      '    Round:','$'

grid            db      (GRIDSIZE_X * GRIDSIZE_Y) dup(?)
                        ;allocates memory for game grid

p1X             db      ?      ;player 1 X coord
p1Y             db      ?      ;         Y coord
p2X             db      ?      ;player 2 X coord
p2Y             db      ?      ;         Y coord

playerPosState  db      0       ;player position state

p1Score         dw      0       ;number of rounds that player 1 has won
p2Score         dw      0       ;number of rounds that player 2 has won

; Eight-character strings for player names
p1Name     db      'Player1 ','$'
p2Name     db      'Player2 ','$'

escPressed      db      0       ;flag set if ESC key pressed
spcPressed      db      0       ;flag set if SPC key pressed

; for controlling players through kbd
p1KeyDir        db      UP      ;set by MyKeyHandler
p2KeyDir        db      UP

p1Dir           db      UP      ;direction specified by P1Control
p2Dir           db      UP      ;direction specified by P2Control

round           dw      1       ;current round of game play

pbuf            db      7 dup (?) ;buffer for BINASC

oldTimerV       dd      ?       ;far pointer to default 08h
                                ;  interrupt function
oldKeyV         dd      ?       ;far pointer to default key
                                ;  interrupt function                                
timerCount      db      0       ;counter (to be incremented every 1/72 sec) 

gameSpeed       db      24      ;value that TimerCount should reach before
                                ;advancing game state
                                ;initial speed should be 1/3 sec. (24/72)                                
                                   
;====== Procedures ========================================================


; Your Subroutines go here !
; ---- ----------- -- ----


;====== Main procedure ====================================================

MAIN    PROC    FAR

        MOV     AX, CSEG
        MOV     DS, AX

        ; Put display into 80x50 text mode
        MOV     AX, 1202h               ; Sets to 400 line scan mode
        MOV     BL, 30h
        int     10h
        MOV     AX, 3                   ; Sets to 8x8 font
        INT     10h
        MOV     AX, 1112h               ; Enter text mode
        MOV     BL, 0
        INT     10h
        
        CALL    GameMain                ; Where all the action happens!
        
        CALL    MP3XIT                  ; Exit to DOS

MAIN    ENDP

CSEG    ENDS
        END     MAIN

MP3CONST.ASM

TITLE ECE291:MP3-Constants

COMMENT % TRON LiteCycle Game Constant Declarations
        %
        
;====== Constants =========================================================

;ASCII values for common characters
BEEP    EQU 7
CR      EQU 13
LF      EQU 10
ESCKEY  EQU 27
SPACE   EQU 32

;Player 1 keyboard control scan codes (not ASCII)
P1_U    EQU 17  ;'W'
P1_D    EQU 31  ;'S'
P1_L    EQU 30  ;'A'
P1_R    EQU 32  ;'D'

;Player 2 keyboard control scan codes (not ASCII)
P2_U    EQU 72  ;'8' on num. pad
P2_D    EQU 80  ;'2' "
P2_L    EQU 75  ;'4' "
P2_R    EQU 77  ;'6' "

;Constant values for specifying player direction
;  (used in variables p1NextDir and p2NextDir)
UP      EQU 0
DOWN    EQU 1
LEFT    EQU 2
RIGHT   EQU 3

;Constant values for use in Grid array
GRIDSPACE       EQU     0       ; a point with no walls
P1WALL          EQU     1       ; a point with a wall made by player 1
P2WALL          EQU     2       ; a point with a wall made by player 2
GRIDWALL        EQU     3       ; a point along the outside grid wallkk

;Dimension definitions
SCREENSIZE_X    EQU 80  ;Size of dos screen in x direction
SCREENSIZE_Y    EQU 50  ;Size of dos screen in y direction
GRIDSIZE_X      EQU 80  ;Size of game grid in x direction
GRIDSIZE_Y      EQU 49  ;Size of game grid in y direction

TEXTATTR        EQU 02h ;TxtVid attribute byte for game text
                        ;Currently green on black
GRIDATTR        EQU 01h ;TxtVid attribute byte for game grid
                        ;Currently blue on black
CRASHATTR       EQU 0Eh ;TxtVid attribute byte for crash symbol
                        ;Currently yellow on black
P1ATTR          EQU 79h ;TxtVid attribute byte for player 1 cycle & walls
P2ATTR          EQU 74h ;TxtVid attribute byte for player 2 cycle & walls

CRASHSYMBOL     EQU 0Fh ;ASCII value of symbol to draw at crash site.
PLAYERSYMBOL    EQU 0DBh;ASCII value of symbol to draw for player wall.