SubHunter: Underwater Adventure
ECE 291 Final Project Write Up
Jason Makulec
Greg Muthler
Vadim Tokarskiy
Robert Wheeler
Mentor: Joshua Scheid
May 29, 1999

 
 

Table of Contents

Team Members *
Introduction *
Problem Description *
    General *
    Graphics *
    3D Engine *
    Networking *
    Sound *
Implementation *
    General *
    Graphics *
    3D Engine *
    Networking *
    Sound *
Procedures *
    Common *
        Abbreviations *
        Segments *
        Constants *
        Structures *
            Vector STRUC *
            Object STRUC *
            NCB STRUC *
            WaveHdr STRUC *
        Variables *
    Graphics *
        DrawPCX PROC  NEAR *
        StorePCX PROC  NEAR *
        LoadPCX PROC  NEAR *
        DrawView PROC  NEAR *
        DrawRadarPt PROC  NEAR *
        DrawScreen PROC  NEAR *
    3D Engine *
        CheckDistance PROC NEAR *
        CheckInView PROC NEAR *
        GetVector PROC NEAR *
        CopyVector PROC NEAR * 
        DotVector PROC NEAR *
        CrossVector PROC NEAR *
        MagVector PROC NEAR *
        MoveObject PROC NEAR  *
        TurnObjectLeft PROC NEAR   *
        TurnObjectLeft PROC NEAR  * 
        CalcScreenVectors PROC NEAR  *
    Networking *
        Post PROC NEAR *
        NetPost PROC NEAR *
        NetINIT PROC NEAR *
        SendPacket PROC NEAR *
        NetRelease PROC NEAR *
        ObjectsPositionUpdate PROC NEAR *
    Sound *
        SoundHandler PROC FAR *
        OpenWav PROC NEAR *
        MixBuffers PROC NEAR *
        LoadHalfBuffer PROC NEAR *
        MainSound PROC NEAR *
        ResetControlWav PROC NEAR *
        StopWav PROC NEAR *
        StartSound PROC NEAR *
        SetDMAVars PROC NEAR *
External Routines *
Screen Shot *
 

Team Members

Each team member on the development team for SubHunter shares in all aspects of the design while maintaining areas of expertise. The following chart shows the development separation by expertise with italics denoting areas of secondary expertise:
 
Team Members Expertise
Robert Jon Wheeler: 3-D Engine  
Graphics
Vadim Tokarskiy Networking  
Game Loop  
Menu  
Mouse/Key Handlers
Jason Makulec Sound  
Game Loop  
Menu
Greg Muthler Graphics  
3-D Engine
  Back to index

Introduction

    SubHunter is an underwater action adventure game where the player commands a submarine against other players across a network connection. The object of the game is to hunt down and torpedo enemy submarines. The main goal of the project is to code a game in assembly that provides real-time play action and includes multi-dimensional views and the ability to play over a network.
    Two views of the surrounding waters will be provided. The first will be a flat, overhead, two-dimensional radar, which displays the location of all players within in a limited range. The second will be a three-dimensional view port looking ahead. This second display will make use of a three-dimensional scaling and movement.
    Dangerous marine life and torpedoes will automatically track a locked-on opponent. The autotracking will have a dangerous aspect in that it will lock onto anything that moves into the field of view of the torpedo or monster. If the torpedo is tracking a target and the target moves behind another submarine, the lock will shift to the closer ship.
    An instrument panel will show speed, direction, and coordinates of the submarine as well as the status of weapon, a locked-on light and an exit game button.
    Sound files will play specific to action; torpedo explosions, sonar, speed changes, etc.
    Each player will see the same game from the network; active weapons, ships, and hostile creatures.
 Back to index

 Problem Description

General

    The introduction and menu screens provide a simple interface to game play.  The menu provides instructions, sound settings and credit information. The main loop will use the primary functions from each main area.
    Inputs from the keyboard and the mouse will be used for game play and menu selection.
    The weapons and torpedoes will be able to autotrack targets.  As a secondary goal, the same AI will be used to generate computer opponents.
 Back to index

Graphics

    The general goal of the graphics subroutine is to draw images in 320x200 graphics mode. The fundamental routines must robustly draw any size bit map at a given screen position at a given scale factor. Graphic routines will be used to draw object images to the viewscreen and the radar and to redraw other images used for the instrument panel. General routines will be used to draw the introduction and menu screens.
    The viewscreen routines will accept x and y coordinates centered on the viewscreen, the relative orientation, and the distance to the object. The routines will translate the coordinates to the necessary linear screen coordinates and draw the required image scaled for distance.
    Routines to update the radar and the instrument panel will change each based on current status.
 Back to index

 3D Engine

    A three dimensional engine is used to perform all movements and interactions between objects in the virtual world.
    The challenges faced developing a three dimensional engine are interfacing a virtual world of objects in real dimensions to a two dimensional screen in a moving plane using integer dimensions.  Interfaces allow player input to effect objects.
 Back to index

Networking

    The networking routines have to be able to transmit to, receive from and process the updated information fast enough so that it doesn’t disrupt the game play. Also the routines have to make sure the information is available often enough so that everything significant happening during the game like collisions, explosion, etc. are know to all players within reasonable amount of time.
Back to index

Sound

    The sound for SubHunter will rely entirely on the wav sound format. The background music as well as the sound effects will be implemented in this way. The sounds need to be mixed in real time without loading the processor excessively. Moving the wav files to the sound card will be handled via a dma transfer. To decrease the processing time required for wave mixing, the wav files were sampled in the 11kHz 8-bit mono format.
Back to index

Implementation

General

    The introduction and menu screens will be drawn using the base routines provided in the graphics section. The screens will be pre-drawn bit maps loaded from PCX files. Selections will be made using the mouse or the keyboard. The keyboard input source will use a custom interrupt routine which will be loaded in place of the existing interrupt routine. The mouse will operate using a chained interrupt.   The keyboard interrupt will update the speed, weapon control, and turns.
    The main loop will have two main sections: the menu loop and the game loop. While in the menu loop, program will wait for inputs (menu selections) and update menu screens appropriately or move  to the game loop. The game loop will call the necessary networking and graphics routines and move objects with MoveObject.
    The weapon and monster will be identical in all functional aspects.  Each player will control and update a weapon and a monster.  The weapon is launched when the player commands.  The monster is randomly generated and randomly placed inside the game world.  When a player exits the game, the associated weapon and monster are terminated if active. All players’, monsters’, and torpedoes’ attributes are stored in the ObjectArray. The ObjectArray is updated each time a packet is received over the network.
 Back to index

Graphics

    Graphics will be implemented using 320x200 video mode with 256 colors using double buffering with a common buffered palette.  Image files will be PCX encoded image files.
    Positioning of objects will be accomplished using an array of twenty five 64x40 images, each a different rotation.  Objects will be drawn with an invisible background palette color to allow images to be drawn over a given background.
    The ReDrawPlayScreen routine will initially repaint the view screen background and then call DrawRadar, DrawPanel, and ScaleImage for each object that is in view.
    The DrawRadar routine will simple draw a point on the radar screen using the real x and y coordinates of the object. The DrawPanel updates panel information, including location, direction, and speed. The ScaleImage routine will accept the image offset, the desired scale factor and a screen coordinate position and draw a scaled bit map at that location.
 Back to index

3D Engine

    The play area implemented using virtual space with predefined limits. The space will be defined using xyz coordinates with the origin such that all positions are positive. Each object will have a xyz coordinate position and a unit vector that describes the object orientation relative to the virtual world.
    Each cycle the CheckDistance routine will update the relative distance of all active objects in the array. The CheckDistance routine will call CheckInView routine which updates the inview field for each active opponent object in the array.  If the object is inview, the CheckInView routine calculates the relative orientation of the object and updates the image index for the object. 
    The CheckDistance routine first calls CalcScreenVectors which calculates two orthogonal vectors used by following procedures.  The distance is calculated using the common two point distance formula.  After the distance is calculated, collisions are detected by adding the two radii from each object and comparing with the distance.  CheckInView is then called.
    The CheckInView routine calculates whether each object is in the field of view by using the angle between the player direction vector and the vector from the player to the object. The maximum allowable angle for both the horizontal and vertical dimensions will define the field of view and will be set with predefined constants. If the object is in the field of view, the CheckInView routine will then calculate the corresponding coordinates of the object on the viewscreen relative to the center of the screen. The viewscreen will be defined in virtual space as the plane described by the normal direction vector and the position of the player. The image index will be updated by CheckInView using the relative position of the two objects.  Specifically, the real angle between the two objects will be mapped to one of the predefined orientation images.
    The CalcScreenVectors routine updates the X and YScreenVectors with unit vectors along the x and y axis of the virtual screen of the view port.  The plane of the screen is defined by the unit direction vector and the xyz coordinate of the object.
    DotVector, CopyVector, CrossVector, and MagVector are helper functions that perform necessary mathmatical operations.
    MoveObject updates the xyz coordinates of an object.  This routine will be called at a set period based on time, making object movement non-dependant on processor speed.  Shift is proportional to speed.
    TurnObjectLeft/Right updates the direction vector of an object.  This routine will be called when the keyboard handler detects a turn command.  Turn rate is proportional to speed. Translation of the coordinates is made using matrix math.

 Back to index

Networking

    Main networking routines such as NetInit, Post, and NetRealease are just modified library routines provided in Netlib.asm and Netex.asm. Computers will be able to communicate to each other through datagrams. Each player’s program will periodically send messages to everyone in the network group with that players information. Such information will include the updated status and position of all player’s controlled objects such as sub and torpedo(s).
    The object array entries will be updated when the update packets are received.
 Back to index

Sound

    The sound for SubHunter is based entirely on the wav format. This requires that multiple wav files be mixed in real-time. One of these wav files is designated as background music in the game. This file controls how the dma on the sound card is programmed. All other wav files are mixed into the memory buffer the dma is reading from. All files are read from disk into a memory buffer as the game requests them. This disk read and buffer system is based on the sbtest.asm given with the sound library code. The mixing process is conceptually fairly simple. The wavs to be mixed are loaded into a separate buffer at the same time the sound card produces an interrupt to refill the dma transfer buffer. After the next wav portion is loaded, the waveform samples are merely added together. Before this addition occurs, however, the voltage values of the samples must be divided by the number of active wav files. If this is not done, the waveform will be clipped which results in distortion. This is especially critical for 8-bit samples. Since there are only 256 available voltage levels, successive division results in an overall loss of quality in the sound of the wav. This did not seem to be a problem in the two or three active wav files that were tested. A final note on the mixing process: the div opcode was not used for the division. Shifting provided a much faster way to achieve approximately the same result. Obviously, for three active wave files the output will be slightly softer with the shifting method, since the values will be approximated and shifted by two.
Back to index

Procedures

Common

 Abbreviations

        WCS: World Coordinate System.
        FOV: Field Of View.

 Segments

stkseg  segment stack                 ; *** STACK SEGMENT ***
        db      64 dup ('STACK   ')   ; Allocate bytes of stack memory
stkseg  ends

SBSeg segment PUBLIC 'DATA1'
    ScreenBuffer DB 65535 dup(?)  ; Buffered Screen Segment
SBSeg ENDS

SISeg segment PUBLIC 'DATA2'
    ShipImages   DB 65535 dup(?)  ; Image Buffer
SISeg ENDS

TISeg segment PUBLIC 'DATA3'
    TorpImages   DB 65535 dup(?)  ; Image Buffer
TISeg ENDS

BGSeg segment PUBLIC 'DATA4'
    Background   DB 65535 dup(?)  ; Background Graphics Buffer
BGSeg ENDS

PNSeg segment PUBLIC 'DATA5'
    Panel   DB 65535 dup(?)           ; Panel Graphics Buffer
PNSeg ENDS

SNDSEG SEGMENT
sndbuf   db 2048 dup (0,0,0,0,0,0,0,0) ; 16k of sine wav - buffer for the control wav
tempbuf db  2048 dup (0,0,0,0,0,0,0,0) ;16k fo sine wave -  buffer for the rest of the wavs
SNDSEG   ENDS

CSEG SEGMENT PUBLIC 'CODE''

 Constants

GMODESEG EQU 0A000h
TMODESEG EQU 0B800h

INTROSCREEN EQU 0
MAINMENU EQU 1
OPTIONS EQU 2
PLAYSCREEN EQU 3
EXITSCREEN EQU 4
CREDITS EQU 5
INSTRUCTIONS EQU 6

SPEEDUP             EQU  2
SLOWDOWN        EQU  1
ABANDONSHIP     EQU  0
MINSPEED           EQU  -7
MAXSPEED          EQU  29

LEFT EQU 75
RIGHT EQU 77
UP EQU 72
DOWN EQU 80
RETURN EQU 28
ESCAPE EQU 01

SUBMARINE EQU 0                 ; object type for submarine
TORPEDO EQU 1                   ; object type for torpedo
MONSTER EQU 2                   ; object type for monster
SIZEOFOBJECT EQU 48             ; size of object structure in bytes
 
ACTIVE EQU 1                    ; object status
INACTIVE EQU 0                  ; object status
DEAD EQU 2                      ; object status

YES EQU 1                       ; boolean true
NO EQU 0                        ; boolean false

XLIMIT EQU 10000                ; x coordinate limit of world
YLIMIT EQU 10000                ; y coordinate limit of world
ZLIMIT EQU 10000                ; z coordinate limit of world

PI EQU 3.14159265359

MAXNUMOFOBJECTS EQU 20          ; max number of objects allowed in game

RADOFMONSTER EQU 5              ; radius of monsters
RADOFSUBMARINE EQU 5            ; radius of submarine
RADOFTORPEDO EQU 5              ; radius of torpedo

MAXRUNMONSTER EQU 15            ; maximum running time of monster in seconds
MAXRUNTORPEDO EQU 20            ; maximum running time of torpedo in seconds
MAXSPEEDOFSUBMARINE EQU 5       ; max speed of sub in units of WCS/s
MAXSPEEDOFTORPEDO EQU 5         ; max speed of torpedo in units of WCS/s
MAXSPEEDOFMONSTER EQU 5         ; max speed of monster in units of WCS/s

RESET EQU 032h                  ; NetBIOS command constants
CANCEL EQU 035h
NET_STATUS EQU 0B3h
STATUS_WAIT EQU 034h
TRACE EQU 0F9h
UNLINK EQU 070h
ADD_NAME EQU 0B0h
ADD_NAME_WAIT EQU 030h
ADD_GROUP_NAME EQU 0B6h
ADD_GROUP_NAME_WAIT EQU 036h
DELETE_NAME EQU 0B1h
DELETE_NAME_WAIT EQU 031h
CALL_ EQU 090h
LISTEN EQU 091h
HANG_UP EQU 092h
SEND EQU 094h
CHAIN_SEND EQU 097h
RECEIVE EQU 095h
RECEIVE_ANY EQU 096h
SESSION_STATUS EQU 0B4h
SEND_DATAGRAM EQU 0A0h
SEND_BCST EQU 0A2h
RECEIVE_DATA EQU 0A1h
RECEIVE_BCST_DATA EQU 0A3h

MAXWAVS EQU 2                   ; maximum simultaneous waves

VMINX                 EQU 6          ; ViewPort restrictions
VMINY                 EQU 6
VMAXX                EQU 193
VMAXY                EQU 193
IMAGESIZEX       EQU 64       ; Object image size
IMAGESIZEY       EQU 40
RMIDX                EQU 257      ; Radar offset
RMIDY                EQU 141
RADARCOLOR   EQU 0Fh

 Back to index

 Structures

 Vector STRUC

    Vector STRUC
        xdir REAL4 1.0                ; x direction
        ydir REAL4 0.0                ; y direction
        zdir REAL4 0.0                ; z direction
    Vector ENDS

Object STRUC

        Object STRUC
            status DB INACTIVE
            objectype DB 0              ; object type:0-sub(default),1-torpedo,2-monster
            number DB ?                 ; object number, assigned by NETBIOS
            inview DB NO                ; is the object in field of view, default to NO
            distance REAL4 ?         ; distance from me to object, must initialize
            radius REAL4 ?             ; radius of object, defaults to 5
            xpos REAL4 0.0            ; x coordinate in WCS, default to center
            ypos REAL4 0.0            ; y coordinate in WCS, default to center
            zpos REAL4 0.0            ; z coordinate in WCS, default to center
            direction Vector <>        ; unit vector indicating direction
            speed DW 0                  ; speed of object in units of WCS per sec
            xscreen DW ?               ; x coordinate on screen
            yscreen DW ?               ; y coordinate on screen
            image DW 0                  ; image index
            runtime DW 0                ; running time of torpedo
            score DW 0                  ; score of player
        Object ENDS

 WaveHdr STRUC

        WaveHdr STRUC
           format   db 'RIFF'
           filelen dd  ?
           wavefmt db  'WAVEfmt_'
           fmt_len dd  ?
           fmt_tag dw  ?
           channel dw  ?
           samples dd  ?
           bytesps dd  ?
           bkalign dw  ?
           bitsps   dw ?
           data  db 'data'
           datalen dd  ?
        WaveHdr Ends

 NCB Structure

        NCB struc
                ncb_command             db ?    ; command code
                ncb_retcode             db ?    ; error return code
                ncb_lsn                 db ?    ; session number
                ncb_num                 db ?    ; name number
                ncb_buf_off             dw ?    ; ptr to send/receive data offset
                ncb_buf_seg             dw ?    ; ptr to send/receive data segment
                ncb_buflen              dw ?    ; length of data
                ncb_callname    db 16 dup (?) ; remote name
                ncb_name                db 16 dup (?) ; local name
                ncb_rto                 db 0    ; receive timeout
                ncb_sto                 db 0    ; send timeout
                ncb_post_off    dw ?    ; async command complete post offset
                ncb_post_seg    dw ?    ; async command complete post segment
                ncb_lana_num    db ?    ; adapter number
                ncb_cmd_done    db ?    ; 0FFh until command completed
                ncb_res                 db 14 dup (?) ; reserved
        NCB ends
        Back to index

 Variables

 
ObjectArray Object MaxNumOfObjects dup(<>)   ; array of all objects in playing area
PUBLIC ObjectArray

MySub Object <>                 ; my submarine object
PUBLIC MySub

MyWeapon Object <>              ; my weapon object
PUBLIC MyWeapon

MyMonster Object <>             ; my monster object
PUBLIC MyMonster

SizeObject DW SIZEOF Object     ; total number of objects in array
XScreenVector Vector <>              ; x direction vector for screen
YScreenVector Vector <>              ; y direction vector for screen

TempVector1 Vector <>           ; vector used by routines to translate position
TempVector2 Vector <>           ; vector used by routines to translate position

RotationInc REAL4 0.2618        ; how far to rotate each click

Hlimit REAL4 0.261799387799     ; horizontal view limit in radians (+/- 15deg)
Vlimit REAL4 0.261799387799     ; vertical view limit in radians (+/- 15deg)

ShipFile      db 'Ship.PCX', 0       ; Ship images file
TorpFile      db 'Torp.PCX', 0       ; Torpedo images file
BackFile     db 'Back.PCX', 0       ; Background image
TitleFile      db 'Title.PCX', 0        ; Title screen image
CreditsFile db 'Credits.PCX', 0   ; Credits screen
InstFile       db 'Inst.PCX', 0        ; Instructions screen
MenuFile    db 'Menu.PCX', 0     ; Menu screen image
PanelFile    db 'Panel.PCX', 0     ; Panel screen image

NumOfImages1 dw 12/2
NumOfImages2 dw 12/4

ScaleFactor  dw  ?                    ; Scaling factors for ScaleImage
ScaleExtra    dw ?
StViewX       dw  ?                     ; Start location of image
StViewY       dw ?
CrViewX       dw  ?                    ; Current cursor location
CrViewY       dw ?
StartDI         dw  ?

IntDistance   dw  ?                    ; Used for panel/radar updates
IntMyX          dw  ?
IntMyY          dw  ?
IntTheirX       dw  ?
IntTheirY       dw  ?

DistArray       dw MAXNUMOFOBJECTS DUP (?)
IndexArray     dw MAXNUMOFOBJECTS DUP (?)
NumInArray    db  ?

grpsnd  NCB <>                  ; Send Network Control Block
grprcv  NCB <>                  ; Receive Network Control Block
Public grpsnd, grprcv
RXBuffer db 512 dup('?')        ; Receive Data Buffer
TXBuffer db SizeOf Object dup('?') ; Transmit Data Buffer

;-- 16 Byte NCB Group and Player names and numbers --
grp_name db 'SubHunterGrpp$$$'  ; Change this name for your own use!
grp_num  db ?                   ; Determined by NetBIOS at runtime
my_name  db 'SubHunterPlr00$$'  ; No not move '00'
my_num   db ?                   ; Determined by NetBIOS at runtime
PUBLIC grp_name, my_name
; Packet counters
rcvcnt     dw   0
sndcnt     dw   0
rcvbadpost dw   0

 ; Misc Formatting characters
pbuf               db 7 dup(?)
crlf               db CR,LF,'$'

UpdateTime dw 0                 ; Timing Variables

ScreenSelect dw 0
InitialPosition REAL4 0.0,50.0, 0.0           ; Initial xyz position of the players
                REAL4 1.0, 0.0, 0.0                    ; SETS INITIAL DIRECTION
                REAL4 50.0, 100.0, 0.0
                REAL4 0.0, -1.0, 0.0
                REAL4 100.0, 50.0, 0.0
                REAL4 -1.0, 0.0, 0.0
                REAL4 50.0, 0.0, 0.0
                REAL4 0.0, 1.0, 0.0
 SpeedScaler    REAL4 3.132
 DistanceTraveled   REAL4 0.0
 LastTime dw 0
 
OldMouseMask   dw    ?          ; Old values from Mouse and Keyboard handlers
OldMouseV       dd    ?

; Jump Tables for MainGameLoop, Mouse and KeyboardHandlers
MainMenuMouseJump     dw  offset Mouse_Intro
                        dw  offset Mouse_MainMenu
                        dw  offset Mouse_Options
                        dw  offset Mouse_PlayScreen
                        dw  offset Mouse_ExitScreen
                        dw  offset Mouse_Credits
                        dw  offset Mouse_Instructions
;LMainMenuKbrdJump  dw  offset Kbrd_Intro
                        ;dw  offset Kbrd_MainMenu
                        ;dw  offset Kbrd_Options
                        ;dw  offset Kbrd_PlayScreen
                        ;dw  offset Kbrd_ExitScreen
                        ;dw  offset Kbrd_Credits
PlayScreenJump     dw  offset Speed_Up
                       dw  offset Slow_Down
                        dw  offset Abandon_Ship
                        dw  offset Exit_SPEED_UPDATE

; Other variables used by the Handlers
sbuf_page   db ?
sbuf_offset dw ?
sbuf_length dw 8192     ; 8 k - all that is guaranteed to not
                                     ; cross a DMA Page.
finalbuffersize dw   ?
mycounter   dw -1
needrefill  dw 0
loadbuf WaveHdr MAXWAVS dup(< >)

ActiveWavs  db MAXWAVS dup(0)  ;0 is inactive 1 is active

IntroMusic      db  'intro.wav',0
MainGame     db  'maingame.wav',0

fileno                 dw  MAXWAVS dup(0)
wavremaining    dd  MAXWAVS dup(0)
wavlength          dd  MAXWAVS dup(0)
wavdone            db  MAXWAVS dup(0)
NumActiveWavs  db 0
sioffset  dw  0

INCLUDE MouseLookUpTables.dat

InputValid      db  0       ; 0: InputBuffer is not ready
                                    ; 1: InputBuffer is ready
oldKbdV         dd  ?       ;far pointer to default keyboard
                                    ;  interrupt function
InputBuffer     db  ?       ; Contains one chara of user input

ScanTable      dw OFFSET DONE
               dw OFFSET Code1
               dw OFFSET Code2
               dw OFFSET Code3
               dw OFFSET Code4
               dw OFFSET Code5
               dw OFFSET Code6
               dw OFFSET Code7
               dw OFFSET Code8
               dw OFFSET Code9
               dw OFFSET Code10
               dw OFFSET Code11
               dw OFFSET Code12
               dw OFFSET Code13
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET Code16
               dw OFFSET DONE
               dw OFFSET Code18
               dw OFFSET Code19
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET Code22
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET Code28
               dw OFFSET DONE
               dw OFFSET Code30
               dw OFFSET DONE
               dw OFFSET Code32
               dw OFFSET Code33
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET Code46
               dw OFFSET DONE
               dw OFFSET Code48
               dw OFFSET Code49
               dw OFFSET Code50
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET Code57
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET Code72
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET Code75
               dw OFFSET DONE
               dw OFFSET Code77
               dw OFFSET DONE
               dw OFFSET DONE
               dw OFFSET Code80
 

                Tempxpos1 REAL4 0.0
                Tempypos1 REAL4 0.0
                Tempzpos1 REAL4 0.0
                Tempxpos2 REAL4 0.0
                Tempypos2 REAL4 0.0
                Tempzpos2 REAL4 0.0
 
                TempVec1 Vector <>
                TempVec2 Vector <>
 Back to index

General

KbdInstall PROC NEAR

Inputs: None
Output: Variables: oldKbdV – stores the segment:offset of the original keyboard interupt handler.
Purpose: Installs custom interrupt handler for the keyboard interrupt.
Author: Tokarskiy
Back to index
 

KbdUninstall PROC NEAR

Inputs: Variables: oldKbdV – segment:offset values of the original keyboard handling routine
Purpose: Reinstalls the original keyboard interrupt handler routine.
Author: Tokarskiy
Back to index
 

KbdHandler PROC NEAR

Inputs: None
Outputs: Variables: InputValid – valid input flag, InputBuffer – puts the valid character in a buffer.
Purpose: Processes keyboard interrupts. Updates InputValid variable and InputBuffer for all valid inputs.
Author: Wheeler, Tokarskiy
Back to index
 

MouseInstall PROC NEAR

Inputs: None
Outputs: None
Purpose: Installs custom masked interrupt handler for the mouse.
MouseUnInstall PROC NEAR
Inputs: None
Outputs: None
Purpose: Resets the mouse handler pointer to the original value
Author: Tokarskiy
Back to index
 

MouseHandler PROC NEAR

Inputs: AX=Event mask (same as cx in MouseInstall proc)
BX=Mouse Button Status (should be equal to 0002h)
CX=Horizontal Mouse Position
DX=Vertical Mouse Position
SI, DI horz/vert movements of the mouse
DS=Data Segment of the mouse driver
Variables: ScreenSelect – keeps track of which screen the program is displaying
Outputs: InputValid – flag that gets set for all valid inputs. SreenSelect – screen number the user wants to display.
Author: Tokarskiy
Back to index
 

SpeedUpdate Proc Near USES BX

Inputs: BX=index in PlayScreenJump array |
Outputs: MySub.Speed |
Purpose: This routine is called from Mouse and KeyBoard interrupts whenever a user tries to change the speed of the submarine or quit the game. Updates speed or abandon's ship.
Author: Tokarskiy
Back to index
 

MainGamePlay Proc Near

Inputs: None
Outputs: None
Purpose: Controls the game play
Description:  First the Intro is played, followed by the credits screen.  After that the Main Menu is displayed. At the same time the wave file starts playing.  The user can select from the following options: Hunt, Credits, instructions, and Quit. These options are controlled by the mouse handler and keyboard handler. Once the user chooses to enter the game the program goes into a main game loop.  In the main game loop all the 3-D engine and graphics functions a called periodically to update and refresh the viewing screen. Also network packets are sent out every .5 second to let everyone know about users ‘ update status and position. The users can exit the game by pressing ESC or Q key on the keyboard. The game exits to the main menu.
Author: Tokarskiy/Wheeler/Makulec/Muthler
Back to index
 

Graphics

InitGraphics PROC  NEAR

Input:    None
Output: Updates image segments.
Descpt: Puts the screen into video mode 13h (320x200x256colors). Also stores menu, title, and credits screen into image segments for easy access.
Author: Muthler
 Back to index

RunIntro PROC  NEAR

Input:    None
Output: Writes directly to the video screen
Descpt: Displays the title and credits screen with a two second pause after each.
Author: Muthler
 Back to index

DisplayScreen PROC  NEAR

Input:    AX= Screen to display.
Output: Writes directly to the screen
Descpt: Displays the appropriate screen on the monitor. Simply sets up the transfer from the correct image segment to the video screen.
Author: Muthler
 Back to index

InitPlayGraphics PROC  NEAR

Input:    None
Output: Updates image segments
Descpt: Loads the image segments with the PCX files needed for gameplay.
Author: Muthler
 Back to index

LoadPCX PROC NEAR

Input:  ES = Destination segment address
           DX = Pointer to null terminated string with FileName
Output: Fills destination segment with image
Descpt:  Loads a PCX file into an appropriate segment. This procedure is taken mainly from the lab manual, with a few modifications to fit our purposes. Mainly where the image is stored has been changed.
Author: Muthler/ LabManual
Back to index

TransferScreen PROC NEAR

Input:  ES:DI = Destination segment address
           DS:SI = Source segment
Output: Transfers from one area of memory to another.
Descpt: Transfers any full size(320x200) image from one segment to another. This includes the video screen segment. Can be used to transfer from the BufferedScreen to the video very quickly. Uses double string operations for transfer.
Author: Muthler
Back to index

ReDrawPlayScreen PROC NEAR

Input:    MySub array, ObjectArray
Output:  Writes directly to the screen.
Descpt:  Redraws the game screen. The background is first transfered into the buffer segment. The DrawRadar function is then called to draw the radar. The DrawPanel function is then called to draw the panel. The final action is to update the viewport. To do this, the ObjectArray is traversed for any object that is in view. The object is then loaded into a temporary array used for sorting. The array is sorted ascendingly using a simple bubble sort. After sorting, the scale image function is called with the appropriate factors on each object such that the image farthest away is drawn first. The screen buffer is then dumped to the video screen ( double buffering ).
Author: Muthler
Back to index

ScaleImage PROC NEAR

Input:  ES:SI = Image source
           variables: StViewX, StViewY, ScaleFactor, ScaleExtra
Output: Writes to screen buffer
Descpt: Draws a scaled image at the specified location. To draw the image, each pixel is drawn ScaleFactor times and a counter is updated to keep track of the extra pixel. Once the counter reaches a high enough count to draw a pixel, it draws one, and then subtracts a pixel width off of the counter. The image is also cropped so that it does not draw outside of the viewport. This is accomplished by simply keeping track of the current location and checking to make sure the spot is in the viewport before drawing to the screen.
Author: Muthler
Back to index

DrawRadar PROC NEAR

Input:  MySub
           ObjectArray
Output: Writes to screen buffer
Descpt: Traverses the object array and draws a dot on the radar for each object that is within 400 units of MySub. Takes the current sub location and calculates the x and y difference between the object and then adds that to the center of the radar screen to draw it in the proper location.
Author: Muthler
Back to index

DrawPanel PROC NEAR

Input:  MySub
Output: Writes to screen buffer
Descpt: Updates the panel screen with the current information. The speed bar is first drawn by offsetting the start location by the current speed and the just filling into to the zero mark. The world location is then updated. A seperate segment is used for the numbers. Each position is broken down into its digits then each digit is drawn using an offset into the number segment array and doing a simple transfer to the screen. The compass is then updated. By adding the unit vector (multiplied by pi twice) to the center of the compass, a pixel location is obtained, where we can draw the dot for the compass.
Author: Muthler
Back to index

3D Engine

CheckDistance PROC NEAR

Input: ObjectArray
Output: distance
Descpt: Routine calcs distance between me and all other objects
d=sqrt((x1-x2)^2+(y1-y2)^2+(z1-z2)^2).  Calls CheckInView.
CheckDistance ENDP
Author: Wheeler
 Back to index

CheckInView PROC NEAR

Input: ObjectArray
            SI = index of object
Output:    inview
                xscreen
                yscreen
Descpt: Updates inview field by comparing position of other object to my FOV. FOV is defined by the angle of the direction vector +/- HLIMIT and +/- VLIMIT. If object is inview, then the xscreen yscreen, and image fields are updated by translating the x/y/zpos to screen coordinates.
CheckInView ENDP
Author: Wheeler
 Back to index

GetVector PROC NEAR

Input: SI = index of object to point to
Ouput: TempVector1 = vector to object
Descpt: Calcs the vector from me to object. xdir = x(obj)-x(me), etc.
GetVector ENDP
Author: Wheeler
 Back to index

CopyVector PROC NEAR

Input:  BX = memory offset of souce vector
           DI = memory offset of destination vector
Output: (vector at DI)
Descpt: Overwrites a vector at DI with the values in the
           vector at SI
CopyVector ENDP
Author: Wheeler
 Back to index

CrossVector PROC NEAR

Input:  TempVector1 = first vector
           TempVector2 = second vector
Output: TempVector1 = Cross product of two vectors.
Descpt: Calcs the dot product of two vectors(1X2) using
           x1=(y1*z2)-(y2*z1)
           y1=(x2*z1)-(x1*z2)
           z1=(x1*y2)-(x2*y1)
CrossVector ENDP
Author: Wheeler
 Back to index

DotVector PROC NEAR

Input: TempVector1 = first vector
          TempVector2 = second vector
Output: ST(0) = Dot product of two vectors.
Descpt: Calcs the dot product of two vectors using x1=x1*x2, etc.
DotVector ENDP
Author: Wheeler
 Back to index

MagVector PROC NEAR

Input: TempVector1 = first vector
Output: ST(0) = Magnitude of vector.
Descpt: Calcs magnitude of vector by d=sqrt((x1-x2)^2+(y1-y2)^2+(z1-z2)^2)
MagVector ENDP
Author: Wheeler
 Back to index

MoveObject PROC NEAR

Input:  SI=pointer to object
Output: xpos
             ypos
            zpos
Descpt: When called by main loop, routine moves object in direction given by direction vector with an increment proportional to speed.
MoveObject ENDP
Author: Tokarskiy
Back to index

TurnObjectRight PROC NEAR

Input:  SI=pointer to object
Output: direction
   Descpt: When called indirectly by keyboard handler, routine
           turns object by updating the direction vector with
           an increment.
Author: Wheeler
Back to index

TurnObjectLeft PROC NEAR

Input:  SI=pointer to object
Output: direction
   Descpt: When called indirectly by keyboard handler, routine
           turns object by updating the direction vector with
           an increment.
Author: Wheeler
Back to index

CalcScreenVectors PROC NEAR

Input:  direction = my direction vector
Output: XScreenVector = unit vector in x direction of screen
          YScreenVector = unit vector in y direction of screen
Descpt: Routine update screen vectors used by 2nd lvl routines.
           <X> = (<direction> (cross product) <0,0,1>)/(mag of x)
           for now YScreenVector always = <0,0,1>
Author: Wheeler
 Back to index

Networking

Post PROC NEAR

Inputs: RXBuffer (datagram)
Outputs: None
Descpt: Interrupt handler function. Calls Netpost when a datagram arrives.
Author: Tokarskiy
 Back to index

NetPost PROC NEAR

Inputs: RXBuffer
ObjectArray
Outputs: Update ObjectArray
Descpt: Called from the Post (interrupt handler routine). Updates Object Array with the most current information received from the network.
Author: Tokarskiy
 Back to index

NetINIT PROC NEAR

Inputs: RXBuffer
Outputs:
Descpt: Initializes network communication by registering specified group name on the network. Also, it assignes player name. Prints out error and success messages on the screen.
Author: Tokarskiy
 Back to index

SendPacket PROC NEAR

Inputs: AX: Data Length
            TXBuffer: Data Buffer to Transmit
Outputs: sndcnt
Descpt: Sends datagrams stored in TXBuffer. Keeps track of the number of sent out packets.
Author: Tokarskiy
 Back to index

NetRelease PROC NEAR

Inputs: (None)
Outputs:
Descpt: Takes user’s name off the network. Prints statistics and progress on the screen.
Author: Tokarskiy
 Back to index

ObjectsPositionUpdate PROC NEAR

Inputs: ObjectArray
            TimeOfLastUpdate
Outputs: ObjectArray
                TimeOfLastUpdate
Descpt: Calculates and updates the position of player’s submarine and the released torpedo.
Author: Tokarskiy
 Back to index

Sound

Note: Some of these procedures are based on those given in sbtest.asm with the sound library, but have been modified to allow multiple simultaneous wav files. The LoadHalfBuffer procedure given in sbtest.asm is broken down into smaller sub procedures to increase modularity. These functions are noted below.

SoundHandler PROC FAR

Descpt: SoundHandler is called whenever the DSP generates an interrupt
mycounter - so outside program can know where DMA is. Copied from sbtest.asm
needrefill – flag variable that denotes when the dma has finished reading the current half buffer
Author: Makulec
 Back to index

OpenWav PROC NEAR

Input: dx - offset of the wav filename variable
Output: eax = data length = bytes of Sound Data.
Descpt: OpenWav opens a wav file and advances to the beginning of data. Also checks MAXWAVS to determine if another wav is permissible. Based on sbtest.asm from the sb291lib with modifications to support multiple wav files.
Author: Makulec
 Back to index

MixBuffers PROC NEAR

Inputs: ax - number of bytes to mix
es – segment for sndBuf
            sioffset - offset to use into sndBuf
Descpt: Mixes tempbuf and sndBuf using the method defined in the sound implementation section.
Author: Makulec
 Back to index

LoadHalfBuffer PROC NEAR

Input: ax = secondhalf
Output: CF = 1 if just loaded last buffer
             ax = number of bytes read
Descpt: takes a 1 or 0 in ax, and reads the background music from a file into the appropriate half of sndBuf. Loads other wavs from files into tempbuf. Comprised of part of the LoadHalfBuffer from sbtest.asm.
Author: Makulec
 Back to index
StopWav PROC NEAR
Input: None
Output: None
Descpt: Makes a call to SB_Stop in the sb291lib.asm to stop the dma transfer and closes the control wave file. It also resets entry zero in the ActiveWavs array and decrements NumActiveWavs.
Author: Makulec
Back to index
SetDMAVars PROC NEAR
Input: None
Ouput: None
Descpt: Calculates page offset and sbuf_offset. Taken from the LoadHalfBuffer procedure in the sbtest.asm driver file given with the sound library code.
Author: Makulec
 Back to index
StartSound PROC NEAR
Input: None
Output: None
Descpt: Loads the dma transfer buffer for the first time and begins the dma transfer. Also determines single cycle or auto-init mode for the sound card dma. Copied from section of the LoadHalfBuffer procedure in the sbtest.asm file given with the sound library.
Author: Makulec
Back to index
ResetControlWav PROC NEAR
Input: None
Output: None
Descpt: Called when the wav file has played through it’s entire length. This function needs to reinitialize the control wav parameters when it loops back to the beginning of the wav. It seeks to the beginning of the data chunk in the wav file using a dos interrupt call. It resets wavdone to 0 and reloads wavlegth and wavremaining from the format chunk still resident in memory. It then calls StartSound to load the dma transfer buffer before MainSound is called.
Author: Makulec
 Back to index

MainSound PROC NEAR

Input: None
Output: None
Descpt: Loads dma transfer buffer if necessary based on the status of needrefill and makes the transition from auto-init mode to single-cycle mode when the wav file is on it’s last buffer transfer. Calls ResetControlWav when the wav file needs to loop around to the beginning.
Author: Makulec
 Back to index

External Routines

Sblib291.lib ECE291 Sound Library
Lib291.lib ECE291 General Library
Netlib library
Back to index

Screen Shot

 Back to index
Last modified on 5/30/99 by Robert Jon Wheeler.