home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Hack-Phreak Scene Programs
/
cleanhpvac.zip
/
cleanhpvac
/
INVADR11.ZIP
/
INVADERS
/
INVADERS.ASM
< prev
next >
Wrap
Assembly Source File
|
1995-09-17
|
138KB
|
2,957 lines
;-------------------------------;
; 9k Space Invaders Version 1.1 ;
; ;
; Copyright (c) by Paul S. Reid ;
; All rights reserved. ;
;-------------------------------;
CODE_SEG SEGMENT
ASSUME CS:CODE_SEG,DS:CODE_SEG
ORG 100h
BEGIN:
;----------------------------------------------------------------------------------------------------------------------------------
; 6k Space Invaders
;----------------------------------------------------------------------------------------------------------------------------------
Start PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
MOV AH,0
MOV AL,13h
INT 10h
CALL InstallNewInt9 ; Install game keyboard handler
; Seed random number generator with clock
MOV AX,040h
MOV ES,AX
MOV AX,ES:[06ch]
MOV Seed,AX
; Set color palette
MOV AX,CS ; Segment of palette buffer
MOV ES,AX ; in ES
MOV DX,OFFSET Palette ; Offset of palette buffer in DX
MOV AH,10h ; Function 10h (Get/set palette registers)
MOV AL,12h ; Subfunction 12h (Set block of color registers)
MOV BX,00h ; First color register to set
MOV CX,05bh ; Number of color registers to set (255 = all of them)
INT 10h ; Set registers
; Draw top and bottom borders
MOV AX,0a000h ; Get segment of video memory
MOV ES,AX ; Store it in destination segment register
MOV DI,0 ; Store address in destination register
MOV CX,10240 ; 32 lines
DrawTop: MOV BX,0008fh ; Random number between 0 and 20 in AX
MOV TempStore,CX
CALL Random ; Call random routine
CMP RandomNumber,1
JNZ NoStar
MOV AL,12
JMP DrawTop2
NoStar: MOV AL,8
DrawTop2: STOSB
MOV CX,TempStore
LOOP DrawTop
MOV DI,54400 ; Store address in destination register
MOV CX,9600 ; 32 lines
DrawBottom: MOV BX,0008fh ; Random number between 0 and 20 in AX
MOV TempStore,CX
CALL Random ; Call random routine
CMP RandomNumber,1
JNZ NoStar2
MOV AL,12
JMP DrawBottom2
NoStar2: MOV AL,8
DrawBottom2: STOSB
MOV CX,TempStore
LOOP DrawBottom
;Draw Invaders logo
LEA AX,LogoOutline ; Get address of sprite
MOV BX,74 ; Get X position to draw sprite at
MOV DL,0 ; Get Y position to draw sprite at
MOV DH,10 ; Get color to draw sprite
CALL DrawLogoLayer ; Draw sprite
LEA AX,LogoShadow ; Get address of sprite
MOV BX,74 ; Get X position to draw sprite at
MOV DL,0 ; Get Y position to draw sprite at
MOV DH,9 ; Get color to draw sprite
CALL DrawLogoLayer ; Draw sprite
LEA AX,LogoLetters ; Get address of sprite
MOV BX,74 ; Get X position to draw sprite at
MOV DL,0 ; Get Y position to draw sprite at
MOV DH,11 ; Get color to draw sprite
CALL DrawLogoLayer ; Draw sprite
JMP TitleScreen
; Clear video buffer
StartGame: CALL ResetGame
MOV AX,CS ; Get segment of video memory
MOV ES,AX ; Store it in destination segment register
LEA DI,VideoBuffer ; Store address in destination register
MOV CX,21760 ; 136 lines (160 * 136)
MOV AX,0
ClearAll2: STOSW
LOOP ClearAll2
CALL DisplayStatus
; Outter game loop
RedrawBunkers: CALL DrawBunkers
MOV FirstFrame,1
; Inner game loop
NoExit: LEA AX,PlayersShip ; Get address of sprite
MOV BX,PlayerX ; Get X position to draw sprite at
MOV DL,130 ; Get Y position to draw sprite at
MOV DH,1 ; Get color to draw sprite
CALL DrawSprite ; Draw sprite
CALL CheckPlayerDead
MOV AX,OFFSET Score[0]
MOV ScoreValueOffset,AX
MOV ScoreXOffset,67
CALL DisplayScore
CALL UpdateHighScore
MOV AX,OFFSET HighS[0]
MOV ScoreValueOffset,AX
MOV ScoreXOffset,161
CALL DisplayScore
; Prepare for buffer blit
LEA SI,VideoBuffer
MOV DI,10560 ; Store address in destination register
MOV AX,0a000h ; Get segment of video memory
MOV ES,AX ; Store it in destination segment register
MOV CX,21760 ; 150 lines (136 * 150)
; Check vertical retrace
MOV DX,03DAh ; Get vertical retrace port address in DX
;RetraceStart: IN AL,DX ; Grab retrace information
; TEST AL,8 ; Did it start yet?
; JNZ RetraceStart ; No, wait until it does
RetraceEnd: IN AL,DX ; Grab retrace information again
TEST AL,8 ; Did it end yet?
JZ RetraceEnd ; No, loop until it does
; Blit buffer to video memory
BlitAll: MOVSW
LOOP BlitAll
CMP FirstFrame,1
JNZ NoFirstFrame
CALL DrawInvaders
LEA AX,GetReady
MOV BX,82
MOV DL,20
MOV DH,7
CALL PrintText
MOV AH,0
INT 01ah
ADD DL,18
MOV PauseCounter,DL
Wait1: MOV AH,0
INT 01ah
CMP DL,PauseCounter
JNZ Wait1
LEA AX,GetReady
MOV BX,82
MOV DL,20
MOV DH,0
CALL PrintText
MOV FirstFrame,0
NoFirstFrame: CMP SoundToggle,1
JNZ NoSoundToggle
MOV SoundToggle,0
XOR Sound,080h
NoSoundToggle: CALL EraseInvaders
DEC MoveCount
JNZ NoInvaderMove
CALL MoveInvaders
NoInvaderMove: CMP FireToggle,1
JNZ NoFire
CMP MissileX,0
JNZ NoFire
CALL ShootPlayerMissile
NoFire: CALL DrawInvaders
CMP MissileX,0
JZ NoMissile
CALL MovePlayerMissile
CMP Collision,0
JZ NoMissile
CALL EraseInvaders
MOV AX,OFFSET Score[0]
MOV ScoreValueOffset,AX
MOV ScoreXOffset,67
CALL EraseScore
MOV AX,OFFSET HighS[0]
MOV ScoreValueOffset,AX
MOV ScoreXOffset,161
CALL EraseScore
CALL CheckInvaderKill
CALL DrawInvaders
MOV Collision,0 ; Reset collision flag
NoMissile: CMP NextLevelToggle,0
JZ NoNextLevel
CALL NextLevel
JMP RedrawBunkers
NoNextLevel: CMP PlayerDead,0
JZ NoPlayerDead
JMP KillPlayer
NoPlayerDead: MOV BX,0ffffh ; Random number between 0 and 20 in AX
CALL Random ; Call random routine
CMP RandomNumber[0],1
JNZ NoMakeUFO
CMP UFOX,0
JNZ NoMakeUFO
DEC UFOCounter
CMP UFOCounter,0
JNZ NoMakeUFO
MOV UFOCounter,6
MOV UFOX,50
NoMakeUFO: CMP UFOX,0
JZ NoUFO
CALL MoveUFO
NoUFO: MOV BX,BombFreq ; Random number between 0 and 20 in AX
CALL Random ; Call random routine
CMP RandomNumber[0],1
JNZ NoInvaderBomb
CALL InvaderBomb
NoInvaderBomb: DEC BombMove
CMP BombMove,0
JNZ NoMoveBombs
MOV AL,BombSpeed
MOV BombMove,AL
CALL MoveBombs
NoMoveBombs: LEA AX,PlayersShip ; Get address of sprite
MOV BX,PlayerX ; Get X position to draw sprite at
MOV DL,130 ; Get Y position to draw sprite at
CALL EraseSprite ; Draw sprite
CMP LeftToggle,1
JNZ NoLeft
CALL MovePlayerLeft
NoLeft: CMP RightToggle,1
JNZ NoRight
CALL MovePlayerRight
NoRight: CMP ExitToggle,1
JZ Exit
JMP NoExit
; Clean up and exit
Exit: CALL RemoveNewInt9
MOV AH,0
MOV AL,3
INT 10h
MOV AH,4Ch ; Exit function
INT 21h ; Call DOS for exit
Start ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Update High Score
;----------------------------------------------------------------------------------------------------------------------------------
UpdateHighScore PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
MOV AL,Score[0]
CMP AL,HighS[0]
JZ NextDigit1
JA Update
JMP NoUpdate
NextDigit1: MOV AL,Score[1]
CMP AL,HighS[1]
JZ NextDigit2
JA Update
JMP NoUpdate
NextDigit2: MOV AL,Score[2]
CMP AL,HighS[2]
JZ NextDigit3
JA Update
JMP NoUpdate
NextDigit3: MOV AL,Score[3]
CMP AL,HighS[3]
JZ NextDigit4
JA Update
JMP NoUpdate
NextDigit4: MOV AL,Score[4]
CMP AL,HighS[4]
JA Update
JMP NoUpdate
Update: MOV AL,Score[0]
MOV HighS[0],AL
MOV AL,Score[1]
MOV HighS[1],AL
MOV AL,Score[2]
MOV HighS[2],AL
MOV AL,Score[3]
MOV HighS[3],AL
MOV AL,Score[4]
MOV HighS[4],AL
NoUpdate: RET
UpdateHighScore ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Display Status
;----------------------------------------------------------------------------------------------------------------------------------
DisplayStatus PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
; Display "SCORE"
LEA AX,SCO ; Get address of sprite
MOV BX,30 ; Get X position to draw sprite at
MOV DL,0 ; Get Y position to draw sprite at
MOV DH,5 ; Get color to draw sprite
CALL DrawSprite ; Draw sprite
LEA AX,ORE ; Get address of sprite
MOV BX,46 ; Get X position to draw sprite at
MOV DL,0 ; Get Y position to draw sprite at
MOV DH,5 ; Get color to draw sprite
CALL DrawSprite ; Draw sprite
MOV AX,OFFSET Score[0]
MOV ScoreValueOffset,AX
MOV ScoreXOffset,67
CALL DisplayScore
; Display "HIGH"
LEA AX,HIG ; Get address of sprite
MOV BX,130 ; Get X position to draw sprite at
MOV DL,0 ; Get Y position to draw sprite at
MOV DH,5 ; Get color to draw sprite
CALL DrawSprite ; Draw sprite
LEA AX,GH ; Get address of sprite
MOV BX,146 ; Get X position to draw sprite at
MOV DL,0 ; Get Y position to draw sprite at
MOV DH,5 ; Get color to draw sprite
CALL DrawSprite ; Draw sprite
MOV AX,OFFSET HighS[0]
MOV ScoreValueOffset,AX
MOV ScoreXOffset,161
CALL DisplayScore
; Display lives
LEA AX,PlayersShip ; Get address of sprite
MOV BX,266 ; Get X position to draw sprite at
MOV DL,0 ; Get Y position to draw sprite at
MOV DH,5 ; Get color to draw sprite
CALL DrawSprite ; Draw sprite
LEA AX,Equal ; Get address of sprite
MOV BX,278 ; Get X position to draw sprite at
MOV DL,0 ; Get Y position to draw sprite at
MOV DH,5 ; Get color to draw sprite
CALL DrawSprite ; Draw sprite
MOV AL,Lives
MOV BX,285
MOV DL,0
MOV DH,5
CALL DisplayDigit
RET
DisplayStatus ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Reset Game
;----------------------------------------------------------------------------------------------------------------------------------
ResetGame PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
MOV Frame,0
MOV InvadersX,275
MOV InvadersY,30
MOV InvadersToggle[0],07ff0h
MOV InvadersToggle[2],07ff0h
MOV InvadersToggle[4],07ff0h
MOV InvadersToggle[6],07ff0h
MOV InvadersToggle[8],07ff0h
MOV PlayerX,154
MOV LeftToggle,0
MOV RightToggle,0
MOV FireToggle,0
MOV ExitToggle,0
MOV NextLevelToggle,0
MOV MissileX,0
MOV MissileY,0
MOV UFOX,0
MOV AX,CS ; Get segment of video memory
MOV ES,AX ; Store it in destination segment register
LEA DI,BombX
MOV CX,22
MOV AX,0
ClearLoop1: STOSW
LOOP ClearLoop1
LEA DI,BombY
MOV CX,22
ClearLoop2: STOSB
LOOP ClearLoop2
LEA DI,BombType
MOV CX,22
ClearLoop3: STOSB
LOOP ClearLoop3
MOV BombFreq,010h
MOV MoveCount,1
MOV InvaderSpeed,55
MOV Direction,0
MOV Reversing,0
MOV Collision,0
MOV Score[0],48
MOV Score[1],48
MOV Score[2],48
MOV Score[3],48
MOV Score[4],48
MOV Lives,51
MOV BombMove,2
MOV BombSpeed,2
MOV PlayerDead,0
MOV GameOverToggle,0
MOV CurrentInvaderSpeed,55
MOV CurrentInvaderY,30
MOV CurrentBombFreq,010h
RET
ResetGame ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Print Text
;----------------------------------------------------------------------------------------------------------------------------------
PrintText PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
MOV LetterCounter,AX
MOV LetterXPos,BX
MOV LetterYPos,DL
MOV LetterColor,DH
SUB LetterXPos,6
CMP KeyPress,1
JNZ PrintNext
MOV KeyPress,0
CMP ExitToggle,1
JNZ NotExit2
JMP Exit
NotExit2: CMP SoundToggle,1
JNZ NotSound
MOV SoundToggle,0
XOR Sound,080h
JMP PrintNext
NotSound: CMP GameStart,1
JNZ PrintNext
MOV GameStart,0
JMP StartGame
PrintNext: MOV SI,LetterCounter
LODSB
INC LetterCounter
ADD LetterXPos,6
CMP AL,0
JZ DonePrinting
CMP AL,32
JZ PrintNext
MOV BX,LetterXPos
MOV DL,LetterYPos
MOV DH,LetterColor
CALL DisplayDigit
LEA SI,VideoBuffer
MOV DI,10560 ; Store address in destination register
MOV AX,0a000h ; Get segment of video memory
MOV ES,AX ; Store it in destination segment register
MOV CX,21760 ; 150 lines (136 * 150)
MOV DX,03DAh ; Get vertical retrace port address in DX
RetraceEnd3: IN AL,DX ; Grab retrace information again
TEST AL,8 ; Did it end yet?
JZ RetraceEnd3 ; No, loop until it does
BlitAll3: MOVSW
LOOP BlitAll3
JMP PrintNext
DonePrinting: RET
LetterCounter DW 0
LetterXPos DW 0
LetterYPos DB 0
LetterColor DB 0
PrintText ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Title Screen - Never Returns!
;----------------------------------------------------------------------------------------------------------------------------------
TitleScreen PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
; Clear video buffer
MOV AX,CS ; Get segment of video memory
MOV ES,AX ; Store it in destination segment register
LEA DI,VideoBuffer ; Store address in destination register
MOV CX,21760 ; 136 lines (160 * 136)
MOV AX,0
ClearAll: STOSW
LOOP ClearAll
MOV KeyPress,0
MOV GameStart,1
CALL DisplayStatus
LEA AX,InvadersTitle
MOV BX,40
MOV DL,20
MOV DH,7
CALL PrintText
LEA AX,Copyright
MOV BX,0
MOV DL,30
MOV DH,030h
CALL PrintText
LEA AX,UFO ; Get address of sprite
MOV DL,50 ; Get Y position to draw sprite at
MOV DH,3 ; Get color to draw sprite
MOV BX,100 ; Get X position to draw sprite at
CALL DrawLetter ; Draw sprite
LEA AX,UFOScore
MOV BX,137
MOV DL,50
MOV DH,7
CALL PrintText
LEA AX,TopInvader1 ; Get address of sprite
MOV DL,60 ; Get Y position to draw sprite at
MOV DH,010h ; Get color to draw sprite
MOV BX,103 ; Get X position to draw sprite at
CALL DrawLetter ; Draw sprite
LEA AX,Row1Score
MOV BX,137
MOV DL,60
MOV DH,7
CALL PrintText
LEA AX,MiddleInvader2 ; Get address of sprite
MOV DL,70 ; Get Y position to draw sprite at
MOV DH,020h ; Get color to draw sprite
MOV BX,103 ; Get X position to draw sprite at
CALL DrawLetter ; Draw sprite
LEA AX,Row2Score
MOV BX,137
MOV DL,70
MOV DH,7
CALL PrintText
LEA AX,MiddleInvader1 ; Get address of sprite
MOV DL,80 ; Get Y position to draw sprite at
MOV DH,030h ; Get color to draw sprite
MOV BX,103 ; Get X position to draw sprite at
CALL DrawLetter ; Draw sprite
LEA AX,Row3Score
MOV BX,137
MOV DL,80
MOV DH,7
CALL PrintText
LEA AX,BottomInvader1 ; Get address of sprite
MOV DL,90 ; Get Y position to draw sprite at
MOV DH,040h ; Get color to draw sprite
MOV BX,103 ; Get X position to draw sprite at
CALL DrawLetter ; Draw sprite
LEA AX,Row4Score
MOV BX,137
MOV DL,90
MOV DH,7
CALL PrintText
LEA AX,BottomInvader1 ; Get address of sprite
MOV DL,100 ; Get Y position to draw sprite at
MOV DH,050h ; Get color to draw sprite
MOV BX,103 ; Get X position to draw sprite at
CALL DrawLetter ; Draw sprite
LEA AX,Row5Score
MOV BX,137
MOV DL,100
MOV DH,7
CALL PrintText
LEA AX,StartDocs
MOV BX,0
MOV DL,119
MOV DH,050h
CALL PrintText
LEA AX,Distribution
MOV BX,4
MOV DL,129
MOV DH,7
CALL PrintText
MOV GameStart,0
MOV AH,0
INT 01ah
INC DH
MOV PauseCounter,DH
GetKey: CMP KeyPress,1
JZ KeyWasPressed
MOV AH,0
INT 01ah
CMP DH,PauseCounter
JNZ GetKey
JMP TitleScreen2
KeyWasPressed: CMP ExitToggle,1
JNZ NotExit
JMP Exit
NotExit: CMP SoundToggle,1
JNZ NotSound2
MOV SoundToggle,0
XOR Sound,080h
JMP GetKey
NotSound2: JMP StartGame
TitleScreen ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Title Screen 2 - Never Returns!
;----------------------------------------------------------------------------------------------------------------------------------
TitleScreen2 PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
; Clear video buffer
MOV AX,CS ; Get segment of video memory
MOV ES,AX ; Store it in destination segment register
LEA DI,VideoBuffer ; Store address in destination register
MOV CX,21760 ; 136 lines (160 * 136)
MOV AX,0
ClearAllZ: STOSW
LOOP ClearAllZ
MOV KeyPress,0
MOV GameStart,1
CALL DisplayStatus
LEA AX,InvadersTitle
MOV BX,40
MOV DL,20
MOV DH,7
CALL PrintText
LEA AX,Copyright
MOV BX,0
MOV DL,30
MOV DH,030h
CALL PrintText
LEA AX,Dedication
MOV BX,70
MOV DL,50
MOV DH,010h
CALL PrintText
LEA AX,ThankYou
MOV BX,64
MOV DL,70
MOV DH,010h
CALL PrintText
LEA AX,SoundTog
MOV BX,55
MOV DL,90
MOV DH,7
CALL PrintText
LEA AX,PlayKeys
MOV BX,31
MOV DL,100
MOV DH,7
CALL PrintText
LEA AX,StartDocs
MOV BX,0
MOV DL,119
MOV DH,050h
CALL PrintText
LEA AX,Distribution
MOV BX,4
MOV DL,129
MOV DH,7
CALL PrintText
MOV GameStart,0
MOV AH,0
INT 01ah
INC DH
MOV PauseCounter,DH
GetKey2: CMP KeyPress,1
JZ KeyWasPressed2
MOV AH,0
INT 01ah
CMP DH,PauseCounter
JNZ GetKey2
JMP TitleScreen
KeyWasPressed2: CMP ExitToggle,1
JNZ NotExitZ
JMP Exit
NotExitZ: CMP SoundToggle,1
JNZ NotSound3
MOV SoundToggle,0
XOR Sound,080h
JMP GetKey2
NotSound3: JMP StartGame
TitleScreen2 ENDP
; Draw Letter with pause
DrawLetter PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
CALL DrawSprite ; Draw sprite
; Prepare for buffer blit
LEA SI,VideoBuffer
MOV DI,10560 ; Store address in destination register
MOV AX,0a000h ; Get segment of video memory
MOV ES,AX ; Store it in destination segment register
MOV CX,21760 ; 150 lines (136 * 150)
; Check vertical retrace
MOV DX,03DAh ; Get vertical retrace port address in DX
RetraceEnd2: IN AL,DX ; Grab retrace information again
TEST AL,8 ; Did it end yet?
JZ RetraceEnd2 ; No, loop until it does
; Blit buffer to video memory
BlitAll2: MOVSW
LOOP BlitAll2
NoKey: MOV AH,0
INT 01ah
ADD DL,3
MOV PauseCounter,DL
Wait2: MOV AH,0
INT 01ah
CMP DL,PauseCounter
JNZ Wait2
RET
DrawLetter ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Game Over - Never Returns!
;----------------------------------------------------------------------------------------------------------------------------------
GameOver PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
MOV GameOverToggle,1
LEA AX,GameOverMsg
MOV BX,82
MOV DL,20
MOV DH,7
CALL PrintText
MOV GameOverToggle,0
MOV AH,0
INT 01ah
ADD DL,180
MOV PauseCounter,DL
Wait3: MOV AH,0
INT 01ah
CMP DL,PauseCounter
JNZ Wait3
JMP TitleScreen
GameOver ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Kill Player - Never returns!
;----------------------------------------------------------------------------------------------------------------------------------
KillPlayer PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
MOV AL,Lives
MOV BX,285
MOV DL,0
MOV DH,0
CALL DisplayDigit
DEC Lives
MOV AL,Lives
MOV BX,285
MOV DL,0
MOV DH,5
CALL DisplayDigit
CMP Lives,48
JNZ LifeLeft
; No life left - Wait for key before exiting game
JMP GameOver
; Life left - Pause before continuing
LifeLeft: MOV AH,0
INT 01ah
ADD DL,18
MOV PauseCounter,DL
Wait4: MOV AH,0
INT 01ah
CMP DL,PauseCounter
JNZ Wait4
CALL EraseInvaders
CALL ResetLevel
MOV BX,0
Search3: CMP [BombY+BX],0
JNZ KillBomb2
JMP NoFoundSlot1
KillBomb2: MOV KillBombs,BX
MOV DL,[BombY+BX] ; Get Y position to draw sprite at
CMP [BombType+BX],0
JZ AnimatedBomb4
LEA AX,StraightMissile ; Get address of sprite
JMP AllDone4
AnimatedBomb4: CMP Frame,1
JNZ IsFrame004
LEA AX,TwistedMissile1 ; Get address of sprite
JMP AllDone4
IsFrame004: LEA AX,TwistedMissile2 ; Get address of sprite
AllDone4: SHL BX,1
MOV BX,[BombX+BX] ; Get X position to draw sprite at
CALL EraseSprite ; Draw sprite
MOV BX,KillBombs
MOV [BombY+BX],0 ; Get X position to draw sprite at
NoFoundSlot1: INC BX
CMP BX,22
JZ AllBombsDead
JMP Search3
AllBombsDead: JMP RedrawBunkers
KillBombs DW 0
KillPlayer ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Drop Invader Bomb
;----------------------------------------------------------------------------------------------------------------------------------
InvaderBomb PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
MOV BX,0002h
CALL Random
;------------------------------------------------------------------
; CMP RandomNumber[0],0
; JNZ NoGood
; MOV DL,83
; MOV AH,2
; INT 21h
; JMP Good
;NoGood: MOV DL,32
; MOV AH,2
; INT 21h
;Good: MOV DL,00dh
; MOV AH,2
; INT 21h
;------------------------------------------------------------------
MOV DH,RandomNumber[0]
MOV TempRand,DH
MOV BX,0000bh ; Random number between 0 and 11 in AX
CALL Random ; Call random routine
MOV AX,08000h
MOV CH,0
MOV CL,RandomNumber[0]
INC CX
LoopingZ: SHR AX,1
LOOP LoopingZ
MOV DL,0
TEST InvadersToggle[8],AX
JZ NoRow5Invader
MOV DL,44
JMP FoundY
NoRow5Invader: TEST InvadersToggle[6],AX
JZ NoRow4Invader
MOV DL,34
JMP FoundY
NoRow4Invader: TEST InvadersToggle[4],AX
JZ NoRow3Invader
MOV DL,24
JMP FoundY
NoRow3Invader: TEST InvadersToggle[2],AX
JZ NoRow2Invader
MOV DL,14
JMP FoundY
NoRow2Invader: TEST InvadersToggle[0],AX
JZ NoInvaders
MOV DL,4
FoundY: MOV AL,RandomNumber[0]
MOV AH,0
MOV CL,16
MUL CL
ADD AX,InvadersX
SUB AX,200
ADD DL,InvadersY
; AX Holds X, DL holds Y of bomb start position
MOV BX,0
Search: CMP [BombY+BX],0
JZ FoundSlot
INC BX
CMP BX,22
JNZ Search
JMP NoInvaders
; BX Holds offset (bomb number)
FoundSlot: MOV [BombY+BX],DL
MOV DH,TempRand
MOV [BombType+BX],DH
SHL BX,1
MOV [BombX+BX],AX
NoInvaders: RET
TempRand DB 0
InvaderBomb ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Move Invader Bombs
;----------------------------------------------------------------------------------------------------------------------------------
MoveBombs PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
MOV BX,0
Search2: CMP [BombY+BX],0
JNZ GotSlot
JMP NoFoundSlot
GotSlot: MOV TempCounter,BX
MOV DL,[BombY+BX] ; Get Y position to draw sprite at
CMP [BombType+BX],0
JZ AnimatedBomb1
LEA AX,StraightMissile ; Get address of sprite
JMP AllDone1
AnimatedBomb1: CMP Frame,1
JNZ IsFrame001
LEA AX,TwistedMissile1 ; Get address of sprite
JMP AllDone1
IsFrame001: LEA AX,TwistedMissile2 ; Get address of sprite
AllDone1: SHL BX,1
MOV BX,[BombX+BX] ; Get X position to draw sprite at
CALL EraseSprite ; Draw sprite
MOV BX,TempCounter
INC [BombY+BX]
INC [BombY+BX]
CMP [BombY+BX],130
JNZ DrawNextFrameA
MOV [BombY+BX],0
JMP NoFoundSlot
DrawNextFrameA: MOV DL,[BombY+BX] ; Get Y position to draw sprite at
CMP [BombType+BX],0
JZ AnimatedBomb2
LEA AX,StraightMissile ; Get address of sprite
JMP AllDone2
AnimatedBomb2: CMP Frame,1
JNZ IsFrame002
LEA AX,TwistedMissile1 ; Get address of sprite
JMP AllDone2
IsFrame002: LEA AX,TwistedMissile2 ; Get address of sprite
AllDone2: SHL BX,1
MOV BX,[BombX+BX] ; Get X position to draw sprite at
MOV DH,06h ; Get color to draw sprite
MOV Collision,0
CALL DrawSprite ; Draw sprite
CMP Collision,1
JNZ NoDeadPlayer
JMP KillPlayer
NoDeadPlayer: CMP Collision,2
JZ KillBomb
CMP Collision,4
JNZ NoAction
KillBomb: MOV BX,TempCounter
MOV DL,[BombY+BX] ; Get Y position to draw sprite at
CMP [BombType+BX],0
JZ AnimatedBomb3
LEA AX,StraightMissile ; Get address of sprite
JMP AllDone3
AnimatedBomb3: CMP Frame,1
JNZ IsFrame003
LEA AX,TwistedMissile1 ; Get address of sprite
JMP AllDone3
IsFrame003: LEA AX,TwistedMissile2 ; Get address of sprite
AllDone3: SHL BX,1
MOV BX,[BombX+BX] ; Get X position to draw sprite at
CALL EraseSprite ; Draw sprite
MOV BX,TempCounter
MOV [BombY+BX],0 ; Get X position to draw sprite at
CMP Collision,4
JNZ NoAction
CALL KillMissile
NoAction: MOV Collision,0
MOV BX,TempCounter
NoFoundSlot: INC BX
CMP BX,22
JZ DoneMoveBombs
JMP Search2
DoneMoveBombs: RET
TempCounter DW 0
MoveBombs ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Move UFO
;----------------------------------------------------------------------------------------------------------------------------------
MoveUFO PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
DEC UFOMove
CMP UFOMove,0
JNZ DoneUFO
MOV UFOMove,2
LEA AX,UFO ; Get address of sprite
MOV BX,UFOX ; Get X position to draw sprite at
MOV DL,10 ; Get Y position to draw sprite at
CALL EraseSprite ; Draw sprite
INC UFOX
CMP UFOX,254
JNZ DoNextUFOFrame
MOV UFOX,0
JMP DoneUFO
DoNextUFOFrame: LEA AX,UFO ; Get address of sprite
MOV BX,UFOX ; Get X position to draw sprite at
MOV DL,10 ; Get Y position to draw sprite at
MOV DH,3 ; Get color to draw sprite
CALL DrawSprite ; Draw sprite
; Make sound
TEST Sound,080h
JZ NoSound1
MOV AL,0b6h
OUT 043h,AL
MOV AL,090h
OUT 042h,AL
MOV AL,000h
OUT 042h,AL
IN AL,061h
OR AL,3
OUT 061h,AL
NoSound1: MOV CX,08000h
TimerZ: LOOP TimerZ
IN AL,061h
AND AL,0fch
OUT 061h,AL
DoneUFO: RET
UFOMove DB 2
UFOCounter DB 6
MoveUFO ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Generate Random Number
;----------------------------------------------------------------------------------------------------------------------------------
Random PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
MOV AX,Seed
MUL BX
MOV CX,65531
DIV CX
MOV Seed,DX
MOV RandomNumber[0],AL
RET
Seed DW 0
RandomNumber DB 0
Random ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Next Level
;----------------------------------------------------------------------------------------------------------------------------------
NextLevel PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
DEC CurrentInvaderSpeed
ADD CurrentInvaderY,002h
CMP CurrentBombFreq,002h
JZ NoDecrease
DEC CurrentBombFreq
NoDecrease: CALL ResetLevel
RET
NextLevel ENDP
; Reset Level
ResetLevel PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
MOV PlayerDead,0
MOV NextLevelToggle,0
MOV Frame,0
MOV InvadersX,275
MOV AL,CurrentInvaderY
MOV InvadersY,AL
MOV InvadersToggle[0],07ff0h
MOV InvadersToggle[2],07ff0h
MOV InvadersToggle[4],07ff0h
MOV InvadersToggle[6],07ff0h
MOV InvadersToggle[8],07ff0h
MOV MoveCount,1
MOV AL,CurrentInvaderSpeed
MOV InvaderSpeed,AL
MOV Direction,0
MOV Reversing,0
MOV Collision,0
MOV AX,CurrentBombFreq
MOV BombFreq,AX
RET
CurrentInvaderSpeed DB 55
CurrentInvaderY DB 30
CurrentBombFreq DW 010h
ResetLevel ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Increase Score
;----------------------------------------------------------------------------------------------------------------------------------
IncreaseScore PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
RackScore: CALL ScorePlusOne
LOOP RackScore
RET
IncreaseScore ENDP
; Bump score up by 1
ScorePlusOne PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
INC Score[4]
CMP Score[4],58
JNZ Done
MOV Score[4],48
INC Score[3]
CMP Score[3],58
JNZ Done
MOV Score[3],48
INC Score[2]
CMP Score[2],58
JNZ Done
MOV Score[2],48
INC Score[1]
CMP Score[1],58
JNZ Done
MOV Score[1],48
INC Score[0]
MOV TempCX,CX
MOV AL,Lives
MOV BX,285
MOV DL,0
MOV DH,0
CALL DisplayDigit
INC Lives
MOV AL,Lives
MOV BX,285
MOV DL,0
MOV DH,5
CALL DisplayDigit
MOV CX,TempCX
CMP Score[0],58
JNZ Done
Done: RET
TempCX DW 0
ScorePlusOne ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Display Score
;----------------------------------------------------------------------------------------------------------------------------------
DisplayScore PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
MOV SI,ScoreValueOffset
LODSB
MOV BX,ScoreXOffset
MOV DL,0
MOV DH,5
CALL DisplayDigit
INC ScoreValueOffset
ADD ScoreXOffset,6
MOV SI,ScoreValueOffset
LODSB
MOV BX,ScoreXOffset
MOV DL,0
MOV DH,5
CALL DisplayDigit
INC ScoreValueOffset
ADD ScoreXOffset,6
MOV SI,ScoreValueOffset
LODSB
MOV BX,ScoreXOffset
MOV DL,0
MOV DH,5
CALL DisplayDigit
INC ScoreValueOffset
ADD ScoreXOffset,6
MOV SI,ScoreValueOffset
LODSB
MOV BX,ScoreXOffset
MOV DL,0
MOV DH,5
CALL DisplayDigit
INC ScoreValueOffset
ADD ScoreXOffset,6
MOV SI,ScoreValueOffset
LODSB
MOV BX,ScoreXOffset
MOV DL,0
MOV DH,5
CALL DisplayDigit
RET
ScoreXOffset DW 0
ScoreValueOffset DW 0
DisplayScore ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Erase Score
;----------------------------------------------------------------------------------------------------------------------------------
EraseScore PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
MOV SI,ScoreValueOffset
LODSB
MOV BX,ScoreXOffset
MOV DL,0
MOV DH,0
CALL DisplayDigit
INC ScoreValueOffset
ADD ScoreXOffset,6
MOV SI,ScoreValueOffset
LODSB
MOV BX,ScoreXOffset
MOV DL,0
MOV DH,0
CALL DisplayDigit
INC ScoreValueOffset
ADD ScoreXOffset,6
MOV SI,ScoreValueOffset
LODSB
MOV BX,ScoreXOffset
MOV DL,0
MOV DH,0
CALL DisplayDigit
INC ScoreValueOffset
ADD ScoreXOffset,6
MOV SI,ScoreValueOffset
LODSB
MOV BX,ScoreXOffset
MOV DL,0
MOV DH,0
CALL DisplayDigit
INC ScoreValueOffset
ADD ScoreXOffset,6
MOV SI,ScoreValueOffset
LODSB
MOV BX,ScoreXOffset
MOV DL,0
MOV DH,0
CALL DisplayDigit
RET
EraseScore ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Display / Erase Digit In Decimal
;----------------------------------------------------------------------------------------------------------------------------------
DisplayDigit PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
CALL FindDigit
CALL DrawSprite ; Draw sprite
RET
DisplayDigit ENDP
FindDigit PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
; Find Digit
CMP AL,48
JNZ NotZero
LEA AX,Zero
JMP GotDigit
NotZero: CMP AL,49
JNZ NotOne
LEA AX,One
JMP GotDigit
NotOne: CMP AL,50
JNZ NotTwo
LEA AX,Two
JMP GotDigit
NotTwo: CMP AL,51
JNZ NotThree
LEA AX,Three
JMP GotDigit
NotThree: CMP AL,52
JNZ NotFour
LEA AX,Four
JMP GotDigit
NotFour: CMP AL,53
JNZ NotFive
LEA AX,Five
JMP GotDigit
NotFive: CMP AL,54
JNZ NotSix
LEA AX,Six
JMP GotDigit
NotSix: CMP AL,55
JNZ NotSeven
LEA AX,Seven
JMP GotDigit
NotSeven: CMP AL,56
JNZ NotEight
LEA AX,Eight
JMP GotDigit
NotEight: CMP AL,57
JNZ NotNine
LEA AX,Nine
JMP GotDigit
NotNine: CMP AL,65
JNZ NotA
LEA AX,LetterA
JMP GotDigit
NotA: CMP AL,66
JNZ NotB
LEA AX,LetterB
JMP GotDigit
NotB: CMP AL,67
JNZ NotC
LEA AX,LetterC
JMP GotDigit
NotC: CMP AL,68
JNZ NotD
LEA AX,LetterD
JMP GotDigit
NotD: CMP AL,69
JNZ NotE
LEA AX,LetterE
JMP GotDigit
NotE: CMP AL,70
JNZ NotF
LEA AX,LetterF
JMP GotDigit
NotF: CMP AL,71
JNZ NotG
LEA AX,LetterG
JMP GotDigit
NotG: CMP AL,72
JNZ NotH
LEA AX,LetterH
JMP GotDigit
NotH: CMP AL,73
JNZ NotI
LEA AX,LetterI
JMP GotDigit
NotI: CMP AL,74
JNZ NotJ
LEA AX,LetterJ
JMP GotDigit
NotJ: CMP AL,75
JNZ NotK
LEA AX,LetterK
JMP GotDigit
NotK: CMP AL,76
JNZ NotL
LEA AX,LetterL
JMP GotDigit
NotL: CMP AL,77
JNZ NotM
LEA AX,LetterM
JMP GotDigit
NotM: CMP AL,78
JNZ NotN
LEA AX,LetterN
JMP GotDigit
NotN: CMP AL,79
JNZ NotO
LEA AX,LetterO
JMP GotDigit
NotO: CMP AL,80
JNZ NotP
LEA AX,LetterP
JMP GotDigit
NotP: CMP AL,81
JNZ NotQ
LEA AX,LetterQ
JMP GotDigit
NotQ: CMP AL,82
JNZ NotR
LEA AX,LetterR
JMP GotDigit
NotR: CMP AL,83
JNZ NotS
LEA AX,LetterS
JMP GotDigit
NotS: CMP AL,84
JNZ NotT
LEA AX,LetterT
JMP GotDigit
NotT: CMP AL,85
JNZ NotU
LEA AX,LetterU
JMP GotDigit
NotU: CMP AL,86
JNZ NotV
LEA AX,LetterV
JMP GotDigit
NotV: CMP AL,87
JNZ NotW
LEA AX,LetterW
JMP GotDigit
NotW: CMP AL,88
JNZ NotX
LEA AX,LetterX
JMP GotDigit
NotX: CMP AL,89
JNZ NotY
LEA AX,LetterY
JMP GotDigit
NotY: CMP AL,90
JNZ NotZ
LEA AX,LetterZ
JMP GotDigit
NotZ: CMP AL,61
JNZ NotEqual
LEA AX,Equal
JMP GotDigit
NotEqual: CMP AL,40
JNZ NotCopyright
LEA AX,CopyrightSymbol
JMP GotDigit
NotCopyright: LEA AX,Period
GotDigit: RET
FindDigit ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Check If Player Is Dead
;----------------------------------------------------------------------------------------------------------------------------------
CheckPlayerDead PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
CMP InvadersToggle[8],0
JZ NoRow5Left
CMP InvadersY,84
JNZ NotDead
MOV PlayerDead,1
JMP NotDead
NoRow5Left: CMP InvadersToggle[6],0
JZ NoRow4Left
CMP InvadersY,94
JNZ NotDead
MOV PlayerDead,1
JMP NotDead
NoRow4Left: CMP InvadersToggle[4],0
JZ NoRow3Left
CMP InvadersY,104
JNZ NotDead
MOV PlayerDead,1
JMP NotDead
NoRow3Left: CMP InvadersToggle[2],0
JZ NoRow2Left
CMP InvadersY,114
JNZ NotDead
MOV PlayerDead,1
JMP NotDead
NoRow2Left: CMP InvadersY,124
JNZ NotDead
MOV PlayerDead,1
NotDead: RET
CheckPlayerDead ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Check Invader Killed
;----------------------------------------------------------------------------------------------------------------------------------
CheckInvaderKill PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
MOV AL,Collision
AND AL,0f0h
CMP AL,050h
JNZ NoRow5Kill
CALL SpeedUpInvaders
MOV CH,0
MOV CL,Collision
AND CL,00fh
INC CL
MOV AX,08000h
Shifting1: SHR AX,1
LOOP Shifting1
XOR InvadersToggle[8],AX
MOV CX,5
CALL IncreaseScore
JMP NoRow1Kill
NoRow5Kill: MOV AL,Collision
AND AL,0f0h
CMP AL,040h
JNZ NoRow4Kill
CALL SpeedUpInvaders
MOV CH,0
MOV CL,Collision
AND CL,00fh
INC CL
MOV AX,08000h
Shifting2: SHR AX,1
LOOP Shifting2
XOR InvadersToggle[6],AX
MOV CX,10
CALL IncreaseScore
JMP NoRow1Kill
NoRow4Kill: MOV AL,Collision
AND AL,0f0h
CMP AL,030h
JNZ NoRow3Kill
CALL SpeedUpInvaders
MOV CH,0
MOV CL,Collision
AND CL,00fh
INC CL
MOV AX,08000h
Shifting3: SHR AX,1
LOOP Shifting3
XOR InvadersToggle[4],AX
MOV CX,15
CALL IncreaseScore
JMP NoRow1Kill
NoRow3Kill: MOV AL,Collision
AND AL,0f0h
CMP AL,020h
JNZ NoRow2Kill
CALL SpeedUpInvaders
MOV CH,0
MOV CL,Collision
AND CL,00fh
INC CL
MOV AX,08000h
Shifting4: SHR AX,1
LOOP Shifting4
XOR InvadersToggle[2],AX
MOV CX,20
CALL IncreaseScore
JMP NoRow1Kill
NoRow2Kill: MOV AL,Collision
AND AL,0f0h
CMP AL,010h
JNZ NoRow1Kill
CALL SpeedUpInvaders
MOV CH,0
MOV CL,Collision
AND CL,00fh
INC CL
MOV AX,08000h
Shifting5: SHR AX,1
LOOP Shifting5
XOR InvadersToggle[0],AX
MOV CX,25
CALL IncreaseScore
JMP NoUFOKill
NoRow1Kill: CMP Collision,3
JNZ NoUFOKill
LEA AX,UFO ; Get address of sprite
MOV BX,UFOX ; Get X position to draw sprite at
MOV DL,10 ; Get Y position to draw sprite at
CALL EraseSprite ; Draw sprite
MOV UFOX,0
MOV CX,100
CALL IncreaseScore
NoUFOKill: CMP InvadersToggle[0],00000h
JNZ NotAllDeadYet
CMP InvadersToggle[2],00000h
JNZ NotAllDeadYet
CMP InvadersToggle[4],00000h
JNZ NotAllDeadYet
CMP InvadersToggle[6],00000h
JNZ NotAllDeadYet
CMP InvadersToggle[8],00000h
JNZ NotAllDeadYet
MOV NextLevelToggle,1
NotAllDeadYet: RET
CheckInvaderKill ENDP
; Speed up invaders upon a kill
SpeedUpInvaders PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
CMP InvaderSpeed,1
JZ NoSpeedIncrease
DEC InvaderSpeed
NoSpeedIncrease: RET
SpeedUpInvaders ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Move Invaders
;----------------------------------------------------------------------------------------------------------------------------------
MoveInvaders PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
TEST Reversing,080h
JNZ NoReverse
MOV BX,250
MOV AX,InvadersToggle[0]
OR AX,InvadersToggle[2]
OR AX,InvadersToggle[4]
OR AX,InvadersToggle[6]
OR AX,InvadersToggle[8]
MOV CX,10
FindLeft: SHL AX,1
TEST AX,08000h
JNZ DoneLeft
SUB BX,16
LOOP FindLeft
DoneLeft: MOV DX,298
MOV AX,InvadersToggle[0]
OR AX,InvadersToggle[2]
OR AX,InvadersToggle[4]
OR AX,InvadersToggle[6]
OR AX,InvadersToggle[8]
MOV CX,10
SHR AX,1
SHR AX,1
SHR AX,1
FindRight: SHR AX,1
TEST AX,00001h
JNZ DoneRight
ADD DX,16
LOOP FindRight
DoneRight: CMP InvadersX,DX
JZ Reverse
CMP InvadersX,BX
JNZ NoReverse
Reverse: XOR Direction,080h
ADD InvadersY,2
MOV Reversing,080h
JMP Animate
NoReverse: MOV Reversing,0
TEST Direction,080h
JZ MoveInvadersLeft
INC InvadersX
JMP Animate
MoveInvadersLeft: DEC InvadersX
Animate: XOR Frame,080h
MOV AH,InvaderSpeed
MOV MoveCount,AH
; Make sound
TEST Sound,080h
JZ NoSound2
MOV AL,0b6h
OUT 043h,AL
MOV AL,090h
OUT 042h,AL
MOV AL,00Fh
OUT 042h,AL
IN AL,061h
OR AL,3
OUT 061h,AL
NoSound2: MOV CX,08000h
Timer1: LOOP Timer1
IN AL,061h
AND AL,0fch
OUT 061h,AL
RET
MoveInvaders ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Shoot Player Missile
;----------------------------------------------------------------------------------------------------------------------------------
ShootPlayerMissile PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
MOV AX,PlayerX
MOV MissileX,AX
MOV MissileY,123
; Make sound
TEST Sound,080h
JZ NoSound3
MOV AL,0b6h
OUT 043h,AL
MOV AL,090h
OUT 042h,AL
MOV AL,001h
OUT 042h,AL
IN AL,061h
OR AL,3
OUT 061h,AL
NoSound3: MOV CX,08000h
Timer2: LOOP Timer2
IN AL,061h
AND AL,0fch
OUT 061h,AL
RET
ShootPlayerMissile ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Move Player Missile
;----------------------------------------------------------------------------------------------------------------------------------
MovePlayerMissile PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
LEA AX,StraightMissile ; Get address of sprite
MOV BX,MissileX ; Get X position to draw sprite at
MOV DL,MissileY ; Get Y position to draw sprite at
CALL EraseSprite ; Draw sprite
DEC MissileY
DEC MissileY
CMP MissileY,09
JNZ DrawNextFrame
MOV MissileX,0
JMP MissileDead
DrawNextFrame: LEA AX,StraightMissile ; Get address of sprite
MOV BX,MissileX ; Get X position to draw sprite at
MOV DL,MissileY ; Get Y position to draw sprite at
MOV DH,04h ; Get color to draw sprite
CALL DrawSprite ; Draw sprite
CMP Collision,0
JZ MissileDead
CMP Collision,4
JZ MissileDead
CMP Collision,6
JZ MissileDead
CALL KillMissile
MissileDead: RET
MovePlayerMissile ENDP
; Kill Player Missile
KillMissile PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
LEA AX,StraightMissile ; Get address of sprite
MOV BX,MissileX ; Get X position to draw sprite at
MOV DL,MissileY ; Get Y position to draw sprite at
CALL EraseSprite ; Draw sprite
MOV MissileX,0
RET
KillMissile ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Move Player's Ship Left
;----------------------------------------------------------------------------------------------------------------------------------
MovePlayerLeft PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
CMP PlayerX,50
JZ NoMoreLeft
DEC PlayerX
NoMoreLeft: RET
MovePlayerLeft ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Move Player's Ship Right
;----------------------------------------------------------------------------------------------------------------------------------
MovePlayerRight PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
CMP PlayerX,259
JZ NoMoreRight
INC PlayerX
NoMoreRight: RET
MovePlayerRight ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; New Interrupt 9 Handler - Replaces normal keyboard handler during game play
;
; Interrupt 015h: Calling AH = 04fh (check for this - Int 15 also has other
; subfuctions!)
; Routine will look at AL, where the caller (Int 9) will have
; placed the scan code.
;
; Place any new scan code for int 9 to process into AL and set
; carry flag before return.
;
; Just clear carry flag to have int 9 ignore the keypress.
;----------------------------------------------------------------------------------------------------------------------------------
; Installs new int 9 handler
InstallNewInt9 PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
MOV AH,035h ; Ask for interrupt address function
MOV AL,015h ; Interrupt we're asking for
INT 021h ; Ask for it
MOV Word Ptr OldInt9Address,BX ; Save current segment of interrupt
MOV Word Ptr OldInt9Address[2],ES ; Save current offset of interrupt
MOV AH,025h ; Insert new address for interrupt function
MOV AL,015h ; Interupt we want to change
MOV DX,Offset NewInt9Handler ; New address to point to (this TSR)
INT 021h ; Set it
RET
OldInt9Address DD 0 ; Buffer for original interrupt address
StoreAX DW 0
InstallNewInt9 ENDP
; Removes new int 9 handler
RemoveNewInt9 PROC NEAR
Assume CS:CODE_SEG,DS:NOTHING
MOV AX,Word Ptr OldInt9Address[2]
MOV DS,AX
MOV AH,025h ; Insert new address for interrupt function
MOV AL,015h ; Interupt we want to change
MOV DX,Word Ptr OldInt9Address ; New address to point to (this TSR)
INT 021h ; Set it
RET
RemoveNewInt9 ENDP
; Actual routine to be called when int 9 is tripped
NewInt9Handler PROC FAR
Assume CS:CODE_SEG,DS:Nothing
CMP AH,04fh
JNZ NotIntercept
TEST AL,080h
JNZ NoKeyPress
MOV KeyPress,1
; Check left arrow
NoKeyPress: CMP AL,04Bh ; Has left arrow been pressed?
JNZ NoLeftOn
MOV LeftToggle,1
NoLeftOn: CMP AL,0CBh ; Has left arrow been released?
JNZ NoLeftOff
MOV LeftToggle,0
; Check right arrow
NoLeftOff: CMP AL,04Dh ; Has right arrow been pressed?
JNZ NoRightOn
MOV RightToggle,1
NoRightOn: CMP AL,0CDh ; Has right arrow been released?
JNZ NoRightOff
MOV RightToggle,0
; Check ctrl
NoRightOff: CMP AL,01Dh ; Has ctrl been pressed?
JNZ NoFireOn
MOV FireToggle,1
NoFireOn: CMP AL,09Dh ; Has ctrl been released?
JNZ NoFireOff
MOV FireToggle,0
; Check ESC
NoFireOff: CMP AL,001h ; Has ESC been pressed?
JNZ NoESCOn
MOV ExitToggle,1
NoESCOn: CMP AL,01fh
JNZ NotIntercept
MOV SoundToggle,1
; Clear keyboard buffer (BIOS routine is still called, and it annoyingly beeps when it's buffer is full)
NotIntercept:
MOV StoreAX,AX
MOV AX,40:[01ch]
MOV 40:[01ah],AX
MOV AX,StoreAX
; MOV AX,040h
; MOV ES,AX
; MOV DS,AX
; MOV DI,01ah
; MOV SI,01ch
; MOVSW
CLC
; Call original interrupt routine
; CALL OldInt9Address ; Call normal interrupt routine
IRET
; RET 2 ; Return from TSR
NewInt9Handler ENDP
;---------------------------------------------------------------------
; JMP StartPrint
;CharacterTable DB "0123456789ABCDEF"
;StartPrint: MOV AL,RandomNumber[0]
; MOV CX,04h
;Looper1: SHR AL,1
; LOOP Looper1
; LEA SI,CharacterTable
; MOV AH,0
; ADD SI,AX
; CLD
; LODSB
; MOV DL,AL
; MOV AH,2
; INT 21h
; MOV AL,RandomNumber[0]
; AND AL,0fh
; LEA SI,CharacterTable
; MOV AH,0
; ADD SI,AX
; CLD
; LODSB
; MOV DL,AL
; MOV AH,2
; INT 21h
; MOV DL,00dh
; MOV AH,2
; INT 21h
;---------------------------------------------------------------------
;----------------------------------------------------------------------------------------------------------------------------------
; Draw Bunkers
;----------------------------------------------------------------------------------------------------------------------------------
DrawBunkers PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
MOV BunkerXL,70
MOV BunkerYL,100
CALL DrawBunker
MOV BunkerXL,122
MOV BunkerYL,100
CALL DrawBunker
MOV BunkerXL,174
MOV BunkerYL,100
CALL DrawBunker
MOV BunkerXL,226
MOV BunkerYL,100
CALL DrawBunker
RET
DrawBunkers ENDP
; Draw Single Bunker
DrawBunker PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
LEA AX,BunkerLeftTop ; Get address of sprite
MOV BX,BunkerXL ; Get X position to draw sprite at
MOV DL,BunkerYL ; Get Y position to draw sprite at
MOV DH,2 ; Get color to draw sprite
CALL DrawSprite ; Draw sprite
ADD BunkerYL,7
LEA AX,BunkerLeftMiddle ; Get address of sprite
MOV BX,BunkerXL ; Get X position to draw sprite at
MOV DL,BunkerYL ; Get Y position to draw sprite at
MOV DH,2 ; Get color to draw sprite
CALL DrawSprite ; Draw sprite
ADD BunkerYL,7
LEA AX,BunkerLeftBottom ; Get address of sprite
MOV BX,BunkerXL ; Get X position to draw sprite at
MOV DL,BunkerYL ; Get Y position to draw sprite at
MOV DH,2 ; Get color to draw sprite
CALL DrawSprite ; Draw sprite
ADD BunkerXL,16
SUB BunkerYL,14
LEA AX,BunkerRightTop ; Get address of sprite
MOV BX,BunkerXL ; Get X position to draw sprite at
MOV DL,BunkerYL ; Get Y position to draw sprite at
MOV DH,2 ; Get color to draw sprite
CALL DrawSprite ; Draw sprite
ADD BunkerYL,7
LEA AX,BunkerRightMiddle; Get address of sprite
MOV BX,BunkerXL ; Get X position to draw sprite at
MOV DL,BunkerYL ; Get Y position to draw sprite at
MOV DH,2 ; Get color to draw sprite
CALL DrawSprite ; Draw sprite
ADD BunkerYL,7
LEA AX,BunkerRightBottom; Get address of sprite
MOV BX,BunkerXL ; Get X position to draw sprite at
MOV DL,BunkerYL ; Get Y position to draw sprite at
MOV DH,2 ; Get color to draw sprite
CALL DrawSprite ; Draw sprite
RET ; Done drawing, return to caller
BunkerXL DW 0
BunkerYL DB 0
DrawBunker ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Draw Invaders
;----------------------------------------------------------------------------------------------------------------------------------
DrawInvaders PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
MOV AX,InvadersX
MOV InvadersXL,AX
MOV AL,InvadersY
MOV InvadersYL,AL
LEA SI,InvadersToggle ; Setup source pointer to sprite data
MOV ColorL,010h
TEST Frame,80h
JZ FrameIsZero1
LEA AX,TopInvader2
JMP Skip1
FrameIsZero1: LEA AX,TopInvader1
Skip1: MOV SpriteAddressL,AX
CLD ; Make sure we increment SI
LODSW ; Get 2 bytes from invaders alive toggles
MOV Temporary2L,SI
CALL DrawInvaderRow
MOV ColorL,020h
TEST Frame,80h
JZ FrameIsZero2
LEA AX,MiddleInvader2
JMP Skip2
FrameIsZero2: LEA AX,MiddleInvader1
Skip2: MOV SpriteAddressL,AX
MOV SI,Temporary2L
CLD ; Make sure we increment SI
LODSW ; Get 2 bytes from invaders alive toggles
MOV Temporary2L,SI
CALL DrawInvaderRow
MOV ColorL,030h
TEST Frame,80h
JZ FrameIsZero3
LEA AX,MiddleInvader1
JMP Skip3
FrameIsZero3: LEA AX,MiddleInvader2
Skip3: MOV SpriteAddressL,AX
MOV SI,Temporary2L
CLD ; Make sure we increment SI
LODSW ; Get 2 bytes from invaders alive toggles
MOV Temporary2L,SI
CALL DrawInvaderRow
MOV ColorL,040h
TEST Frame,80h
JZ FrameIsZero4
LEA AX,BottomInvader2
JMP Skip4
FrameIsZero4: LEA AX,BottomInvader1
Skip4: MOV SpriteAddressL,AX
MOV SI,Temporary2L
CLD ; Make sure we increment SI
LODSW ; Get 2 bytes from invaders alive toggles
MOV Temporary2L,SI
CALL DrawInvaderRow
MOV ColorL,050h
MOV SI,Temporary2L
CLD ; Make sure we increment SI
LODSW ; Get 2 bytes from invaders alive toggles
MOV Temporary2L,SI
CALL DrawInvaderRow
MOV Collision,0 ; No collision detection on invaders - Causes problems when invaders get to bunkers
RET ; Done drawing, return to caller
InvadersXL DW 0
InvadersYL DB 0
Temporary2L DW 0
DrawInvaders ENDP
; Draw Row of Invaders
DrawInvaderRow PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
SHL AX,1
MOV CounterL,11
DrawRow: TEST AX,8000h ; Check left most bit
JZ BitIsZero1 ; Jump if bit is 0
MOV Temporary1L,AX
MOV AX,SpriteAddressL ; Get address of sprite
MOV BX,InvadersXL ; Get X position to draw sprite at
SUB BX,200
MOV DL,InvadersYL ; Get Y position to draw sprite at
MOV DH,ColorL ; Get color to draw sprite
CALL DrawSprite ; Draw sprite
MOV AX,Temporary1L
BitIsZero1: SHL AX,1 ; Shift data left for next bit
ADD InvadersXL,16
DEC CounterL
INC ColorL
JNZ DrawRow
ADD InvadersYL,10
MOV AX,InvadersX
MOV InvadersXL,AX
RET ; Done drawing, return to caller
CounterL DB 0
SpriteAddressL DW 0
ColorL DB 0
Temporary1L DW 0
DrawInvaderRow ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Erase Invaders
;----------------------------------------------------------------------------------------------------------------------------------
EraseInvaders PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
MOV AX,InvadersX
MOV InvadersXL,AX
MOV AL,InvadersY
MOV InvadersYL,AL
LEA SI,InvadersToggle ; Setup source pointer to sprite data
TEST Frame,80h
JZ FrameIsZeroA
LEA AX,TopInvader2
JMP SkipA
FrameIsZeroA: LEA AX,TopInvader1
SkipA: MOV SpriteAddressL,AX
CLD ; Make sure we increment SI
LODSW ; Get 2 bytes from invaders alive toggles
MOV Temporary2L,SI
CALL EraseInvaderRow
TEST Frame,80h
JZ FrameIsZeroB
LEA AX,MiddleInvader2
JMP SkipB
FrameIsZeroB: LEA AX,MiddleInvader1
SkipB: MOV SpriteAddressL,AX
MOV SI,Temporary2L
CLD ; Make sure we increment SI
LODSW ; Get 2 bytes from invaders alive toggles
MOV Temporary2L,SI
CALL EraseInvaderRow
TEST Frame,80h
JZ FrameIsZeroC
LEA AX,MiddleInvader1
JMP SkipC
FrameIsZeroC: LEA AX,MiddleInvader2
SkipC: MOV SpriteAddressL,AX
MOV SI,Temporary2L
CLD ; Make sure we increment SI
LODSW ; Get 2 bytes from invaders alive toggles
MOV Temporary2L,SI
CALL EraseInvaderRow
TEST Frame,80h
JZ FrameIsZeroD
LEA AX,BottomInvader2
JMP SkipD
FrameIsZeroD: LEA AX,BottomInvader1
SkipD: MOV SpriteAddressL,AX
MOV SI,Temporary2L
CLD ; Make sure we increment SI
LODSW ; Get 2 bytes from invaders alive toggles
MOV Temporary2L,SI
CALL EraseInvaderRow
MOV SI,Temporary2L
CLD ; Make sure we increment SI
LODSW ; Get 2 bytes from invaders alive toggles
MOV Temporary2L,SI
CALL EraseInvaderRow
RET ; Done drawing, return to caller
EraseInvaders ENDP
; Erase Row of Invaders
EraseInvaderRow PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
SHL AX,1
MOV CounterL,11
DrawRowA: TEST AX,8000h ; Check left most bit
JZ BitIsZeroA ; Jump if bit is 0
MOV Temporary1L,AX
MOV AX,SpriteAddressL ; Get address of sprite
MOV BX,InvadersXL ; Get X position to draw sprite at
SUB BX,200
MOV DL,InvadersYL ; Get Y position to draw sprite at
CALL EraseSprite ; Draw sprite
MOV AX,Temporary1L
BitIsZeroA: SHL AX,1 ; Shift data left for next bit
ADD InvadersXL,16
DEC CounterL
JNZ DrawRowA
ADD InvadersYL,10
MOV AX,InvadersX
MOV InvadersXL,AX
RET ; Done drawing, return to caller
EraseInvaderRow ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Draw Logo Layer
;----------------------------------------------------------------------------------------------------------------------------------
DrawLogoLayer PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
MOV SI,AX ; Setup source pointer to sprite data
MOV AL,DL ; Get Y position of sprite in AL
MOV AH,0 ; Zero high byte of AX for following shifts
SHL AX,1 ; Calculate Y position * 320 (find address of row)
SHL AX,1 ; Y Position shifted left 6 times + Y Position shifted left 8 times
SHL AX,1
SHL AX,1
SHL AX,1
SHL AX,1
MOV CX,AX
SHL CX,1
SHL CX,1
ADD AX,CX
ADD AX,BX ; Add X position to address
MOV DI,AX ; Store address in destination register
MOV AX,0a000h ; Get segment of video memory
MOV ES,AX ; Store it in destination segment register
MOV Row,5
DoNextRow: MOV Column,11
DoNextSprite: MOV DL,7 ; Do 7 lines of sprite
CLD ; Make sure we increment SI and DI
DrawLinesZ: LODSW ; Get 2 bytes from sprite data (16 bits = 1 line of sprite image)
MOV BX,AX ; Transfer data to an unused register
MOV CX,16 ; Scan all 16 bits
DoLineZ: TEST BX,8000h ; Check left most bit
JZ BitIsZeroZ ; Jump if bit is 0
MOV AL,DH ; Bit is 1, get color of sprite
STOSB ; And draw the pixel on the screen
JMP SkipZ ; Skip the bit is 0 stuff
BitIsZeroZ: INC DI ; Bit was 0, increment destination register
SkipZ: SHL BX,1 ; Shift data left for next bit
LOOP DoLineZ ; Keep going until no more bits to check
ADD DI,304 ; Increment address to next screen line (320 - 16 bits)
DEC DL ; Decrease line count
JNZ DrawLinesZ ; Draw lines until no more lines left to draw
SUB DI,2224 ; Do next sprite in row
DEC Column
CMP Column,0
JNZ DoNextSprite
ADD DI,2064 ; Do next sprite in row
DEC Row
CMP Row,0
JNZ DoNextRow
RET ; Done drawing, return to caller
Column DB 0
Row DB 0
DrawLogoLayer ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Draw Sprite
;----------------------------------------------------------------------------------------------------------------------------------
DrawSprite PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
MOV SI,AX ; Setup source pointer to sprite data
MOV AL,DL ; Get Y position of sprite in AL
MOV AH,0 ; Zero high byte of AX for following shifts
SHL AX,1 ; Calculate Y position * 320 (find address of row)
SHL AX,1 ; Y Position shifted left 6 times + Y Position shifted left 8 times
SHL AX,1
SHL AX,1
SHL AX,1
SHL AX,1
MOV CX,AX
SHL CX,1
SHL CX,1
ADD AX,CX
LEA CX,VideoBuffer ; Get address of video buffer
ADD AX,CX ; Add offset to video buffer
ADD AX,BX ; Add X position to address
MOV DI,AX ; Store address in destination register
MOV AX,CS ; Get segment of video memory
MOV ES,AX ; Store it in destination segment register
MOV DL,7 ; Do 7 lines
CLD ; Make sure we increment SI and DI
DrawLines: LODSW ; Get 2 bytes from sprite data (16 bits = 1 line of sprite image)
MOV BX,AX ; Transfer data to an unused register
MOV CX,16 ; Scan all 16 bits
DoLine: TEST BX,8000h ; Check left most bit
JZ BitIsZero ; Jump if bit is 0
CMP Collision,0
JNZ NoCollision
MOV AL,ES:[DI]
CMP AL,0
JZ NoCollision
MOV Collision,AL
NoCollision: MOV AL,DH ; Bit is 1, get color of sprite
STOSB ; And draw the pixel on the screen
JMP Skip ; Skip the bit is 0 stuff
BitIsZero: INC DI ; Bit was 0, increment destination register
Skip: SHL BX,1 ; Shift data left for next bit
LOOP DoLine ; Keep going until no more bits to check
ADD DI,304 ; Increment address to next screen line (320 - 16 bits)
DEC DL ; Decrease line count
JNZ DrawLines ; Draw lines until no more lines left to draw
RET ; Done drawing, return to caller
DrawSprite ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Erase Sprite
;----------------------------------------------------------------------------------------------------------------------------------
EraseSprite PROC NEAR
Assume CS:CODE_SEG,DS:CODE_SEG
MOV SI,AX ; Setup source pointer to sprite data
MOV AL,DL ; Get Y position of sprite in AL
MOV AH,0 ; Zero high byte of AX for following shifts
SHL AX,1 ; Calculate Y position * 320 (find address of row)
SHL AX,1 ; Y Position shifted left 6 times + Y Position shifted left 8 times
SHL AX,1
SHL AX,1
SHL AX,1
SHL AX,1
MOV CX,AX
SHL CX,1
SHL CX,1
ADD AX,CX
LEA CX,VideoBuffer ; Get address of video buffer
ADD AX,CX ; Add offset to video buffer
ADD AX,BX ; Add X position to address
MOV DI,AX ; Store address in destination register
MOV AX,CS ; Get segment of video memory
MOV ES,AX ; Store it in destination segment register
MOV DL,7 ; Do 7 lines
CLD ; Make sure we increment SI and DI
DrawLines2: LODSW ; Get 2 bytes from sprite data (16 bits = 1 line of sprite image)
MOV BX,AX ; Transfer data to an unused register
MOV CX,16 ; Scan all 16 bits
DoLine2: TEST BX,8000h ; Check left most bit
JZ BitIsZero2 ; Jump if bit is 0
MOV AL,0 ; Bit is 1, get color of sprite
STOSB ; And draw the pixel on the screen
JMP SkipAA ; Skip the bit is 0 stuff
BitIsZero2: INC DI ; Bit was 0, increment destination register
SkipAA: SHL BX,1 ; Shift data left for next bit
LOOP DoLine2 ; Keep going until no more bits to check
ADD DI,304 ; Increment address to next screen line (320 - 16 bits)
DEC DL ; Decrease line count
JNZ DrawLines2 ; Draw lines until no more lines left to draw
RET ; Done drawing, return to caller
EraseSprite ENDP
;----------------------------------------------------------------------------------------------------------------------------------
; Sprite data
;----------------------------------------------------------------------------------------------------------------------------------
TopInvader1 DW 0c00h,1e00h,2d00h,3f00h,1200h,2100h,1200h
TopInvader2 DW 0c00h,1e00h,2d00h,3f00h,1200h,2100h,4080h
MiddleInvader1 DW 2100h,9e40h,0ad40h,7f80h,3f00h,2100h,4080h
MiddleInvader2 DW 2100h,1e00h,2d00h,7f80h,0bf40h,0a140h,1200h
BottomInvader1 DW 01e00h,7f80h,0ccc0h,0ffc0h,2100h,4c80h,2100h
BottomInvader2 DW 01e00h,7f80h,0ccc0h,0ffc0h,2100h,4c80h,8040h
TwistedMissile1 DW 0000h,0000h,0000h,0800h,0400h,0800h,0400h
TwistedMissile2 DW 0000h,0000h,0000h,0400h,0800h,0400h,0800h
UFO DW 0ff0h,0ff0h,0ffffh,0ffffh,0ffffh,7ffeh,3ffch
PlayersShip DW 0400h,0e00h,7fc0h,0ffe0h,0ffe0h,0ffe0h,0000h
StraightMissile DW 0000h,0000h,0000h,0400h,0400h,0400h,0400h
BunkerLeftTop DW 0fffh,1fffh,3fffh,7fffh,0ffffh,0ffffh,0ffffh
BunkerLeftMiddle DW 0ffffh,0ffffh,0ffffh,0ffffh,0ffffh,0ffffh,0ffffh
BunkerLeftBottom DW 0ff81h,0fe00h,0fc00h,0f800h,0f800h,0f000h,0000h
BunkerRightTop DW 0f000h,0f800h,0fc00h,0fe00h,0ff00h,0ff00h,0ff00h
BunkerRightMiddle DW 0ff00h,0ff00h,0ff00h,0ff00h,0ff00h,0ff00h,0ff00h
BunkerRightBottom DW 0ff00h,7f00h,3f00h,1f00h,1f00h,0f00h,0000h
SCO DW 071c7h,08a28h,08208h,07208h,00a08h,08a28h,071c7h
ORE DW 03cf8h,0a280h,0a280h,0bcf0h,0a280h,0a280h,022f8h
HIG DW 08be7h,08888h,08888h,0f88bh,08888h,08888h,08be7h
GH DW 02200h,0a200h,02200h,0be00h,0a200h,0a200h,02200h
Zero DW 3800h,4400h,4c00h,5400h,6400h,4400h,3800h
One DW 1000h,3000h,1000h,1000h,1000h,1000h,3800h
Two DW 3800h,4400h,0400h,1800h,2000h,4000h,7c00h
Three DW 3800h,4400h,0400h,1800h,0400h,4400h,3800h
Four DW 4400h,4400h,4400h,7c00h,0400h,0400h,0400h
Five DW 7c00h,4000h,4000h,7800h,0400h,4400h,3800h
Six DW 3800h,4400h,4000h,7800h,4400h,4400h,3800h
Seven DW 7c00h,0400h,0800h,1000h,1000h,1000h,1000h
Eight DW 3800h,4400h,4400h,3800h,4400h,4400h,3800h
Nine DW 3800h,4400h,4400h,3c00h,0400h,4400h,3800h
Equal DW 0000h,0000h,7c00h,0000h,7c00h,0000h,0000h
Period DW 0000h,0000h,0000h,0000h,0000h,0000h,1000h
CopyrightSymbol DW 1e00h,2100h,4c80h,4880h,4c80h,2100h,1e00h
LetterA DW 3800h,4400h,4400h,7c00h,4400h,4400h,4400h
LetterB DW 7800h,4400h,4400h,7800h,4400h,4400h,7800h
LetterC DW 3800h,4400h,4000h,4000h,4000h,4400h,3800h
LetterD DW 7800h,4400h,4400h,4400h,4400h,4400h,7800h
LetterE DW 7c00h,4000h,4000h,7800h,4000h,4000h,7c00h
LetterF DW 7c00h,4000h,4000h,7800h,4000h,4000h,4000h
LetterG DW 3800h,4400h,4000h,5c00h,4400h,4400h,3800h
LetterH DW 4400h,4400h,4400h,7c00h,4400h,4400h,4400h
LetterI DW 7c00h,1000h,1000h,1000h,1000h,1000h,7c00h
LetterJ DW 0400h,0400h,0400h,0400h,0400h,4400h,3800h
LetterK DW 4400h,4800h,5000h,6000h,5000h,4800h,4400h
LetterL DW 4000h,4000h,4000h,4000h,4000h,4000h,7c00h
LetterM DW 4400h,6c00h,5400h,4400h,4400h,4400h,4400h
LetterN DW 4400h,6400h,5400h,4c00h,4400h,4400h,4400h
LetterO DW 3800h,4400h,4400h,4400h,4400h,4400h,3800h
LetterP DW 7800h,4400h,4400h,7800h,4000h,4000h,4000h
LetterQ DW 3800h,4400h,4400h,4400h,4400h,4c00h,3c00h
LetterR DW 7800h,4400h,4400h,7800h,4400h,4400h,4400h
LetterS DW 3800h,4400h,4000h,3800h,0400h,4400h,3800h
LetterT DW 7c00h,1000h,1000h,1000h,1000h,1000h,1000h
LetterU DW 4400h,4400h,4400h,4400h,4400h,4400h,3800h
LetterV DW 4400h,4400h,4400h,4400h,4400h,2800h,1000h
LetterW DW 4400h,4400h,4400h,4400h,5400h,6c00h,4400h
LetterX DW 4400h,4400h,2800h,1000h,2800h,4400h,4400h
LetterY DW 4400h,4400h,2800h,1000h,1000h,1000h,1000h
LetterZ DW 7c00h,0400h,0800h,1000h,2000h,4000h,7c00h
LogoOutline DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,007ffh,01800h,02000h,04000h,040ffh,0403fh
DW 00000h,0e3ffh,01400h,00c00h,00400h,00607h,0fa03h
DW 00000h,0f80fh,00610h,00120h,000a0h,0c0e0h,0c0c1h
DW 00000h,0fc00h,00200h,00101h,00102h,00082h,08084h
DW 00000h,01fffh,06000h,08000h,00060h,000a0h,0011fh
DW 00000h,003ffh,08400h,04800h,04800h,0500fh,0900fh
DW 00000h,0ff80h,00040h,00040h,00080h,0ff00h,0c000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 02000h,01c00h,003fch,00fc3h,0103eh,01000h,00800h
DW 0e200h,01900h,00503h,00301h,00281h,00280h,00440h
DW 00181h,00682h,0f903h,00100h,00200h,08207h,04408h
DW 08044h,04048h,0c028h,00028h,00018h,0e018h,0100ch
DW 00100h,00200h,00200h,0047eh,00381h,00001h,00003h
DW 02000h,02000h,0403fh,04020h,0803fh,08000h,00000h
DW 02000h,02000h,0c000h,00000h,0f000h,00800h,00800h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,01fe0h,02011h,02009h,01009h
DW 00000h,00000h,00000h,0fc0fh,00310h,000d0h,00038h
DW 00700h,000ffh,00000h,0f1feh,00a01h,00600h,00300h
DW 03840h,0c03fh,00000h,00fe0h,01010h,09010h,05010h
DW 04408h,083f0h,00000h,07fe0h,08010h,08008h,08004h
DW 0100bh,00ff0h,00000h,00fffh,01000h,01000h,01000h
DW 0000dh,0fff0h,00000h,0f80fh,00610h,00110h,00090h
DW 00000h,0ffffh,00000h,0fff8h,00005h,00005h,0000ah
DW 01000h,0e000h,00000h,0ffffh,00000h,00000h,00000h
DW 00000h,00000h,00000h,0803fh,060c0h,01100h,00a00h
DW 00000h,00000h,00000h,0ff00h,00080h,00040h,00040h
DW 01005h,00804h,00802h,00402h,00401h,00201h,00200h
DW 00008h,0800ch,08003h,08000h,080c0h,04070h,0c04ch
DW 00280h,00140h,00140h,000a0h,00090h,00048h,00044h
DW 02809h,02809h,01809h,00c0ah,0040ah,00406h,00206h
DW 00002h,00002h,00001h,00600h,00500h,00780h,00000h
DW 0100fh,01009h,0100ah,0900ah,0900ah,0500ch,0300ch
DW 000a0h,000a0h,000a0h,000a0h,000c0h,000c0h,000c0h
DW 03ff2h,03f04h,00084h,00084h,0ff08h,08008h,0ffc8h
DW 001c0h,001c0h,00000h,00000h,003c0h,00240h,00440h
DW 00a07h,00a07h,03100h,040e0h,0201ch,017e6h,00818h
DW 0e040h,09f80h,07000h,00800h,00400h,00400h,00400h
DW 00100h,00100h,00080h,0007fh,00000h,00000h,00000h
DW 0a023h,06020h,06010h,09fe0h,00000h,00000h,00000h
DW 00022h,0c021h,03010h,00fe0h,00000h,00000h,00000h
DW 00004h,00004h,0c004h,03ffbh,00000h,00000h,00000h
DW 00000h,003e0h,00420h,0f81fh,00000h,00000h,00000h
DW 03000h,01000h,01000h,0efffh,00000h,00000h,00000h
DW 00140h,00680h,01880h,0e07fh,00000h,00000h,00000h
DW 00030h,00030h,00050h,0ff8fh,00000h,00000h,00000h
DW 00420h,00410h,00810h,0f00fh,00000h,00000h,00000h
DW 00800h,00800h,00c00h,0f3ffh,00000h,00000h,00000h
DW 00400h,00800h,07000h,08000h,00000h,00000h,00000h
LogoLetters DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,007ffh,01fffh,03fffh,03f00h,03fc0h
DW 00000h,00000h,0e3ffh,0f3ffh,0fbffh,0f9f8h,001fch
DW 00000h,00000h,0f80fh,0fe1fh,0ff1fh,03f3fh,03f3eh
DW 00000h,00000h,0fc00h,0fe00h,0fe01h,0ff01h,07f03h
DW 00000h,00000h,01fffh,07fffh,0ff9fh,0ff1fh,0fe00h
DW 00000h,00000h,003ffh,087ffh,087ffh,08ff0h,00ff0h
DW 00000h,00000h,0ff80h,0ff80h,0ff00h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 01fffh,003ffh,00003h,00000h,00fc1h,00fffh,007ffh
DW 001ffh,0e0ffh,0f8fch,0fcfeh,0fc7eh,0fc7fh,0f83fh
DW 0fe7eh,0f87ch,000fch,000ffh,001ffh,001f8h,083f0h
DW 07f83h,03f87h,03fc7h,0ffc7h,0ffe7h,01fe7h,00ff3h
DW 0fe00h,0fc00h,0fc00h,0f800h,0fc7eh,0fffeh,0fffch
DW 01fffh,01fffh,03fc0h,03fc0h,07fc0h,07fffh,0ffffh
DW 0c000h,0c000h,00000h,00000h,00000h,0f000h,0f000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,01fe0h,01ff0h,00ff0h
DW 00000h,00000h,00000h,00000h,0fc0fh,0ff0fh,0ffc7h
DW 000ffh,00000h,00000h,00000h,0f1feh,0f9ffh,0fcffh
DW 0c03fh,00000h,00000h,00000h,00fe0h,00fe0h,08fe0h
DW 083f0h,00000h,00000h,00000h,07fe0h,07ff0h,07ff8h
DW 00ff0h,00000h,00000h,00000h,00fffh,00fffh,00fffh
DW 0fff0h,00000h,00000h,00000h,0f80fh,0fe0fh,0ff0fh
DW 0ffffh,00000h,00000h,00000h,0fff8h,0fff8h,0fff1h
DW 0e000h,00000h,00000h,00000h,0ffffh,0ffffh,0ffffh
DW 00000h,00000h,00000h,00000h,0803fh,0e0ffh,0f1ffh
DW 00000h,00000h,00000h,00000h,0ff00h,0ff80h,0ff80h
DW 00ff8h,007f8h,007fch,003fch,003feh,001feh,001ffh
DW 0fff7h,07ff3h,07ffch,07fffh,07f3fh,03f8fh,03f83h
DW 0fc7fh,0fe3fh,0fe3fh,0ff1fh,0ff0fh,0ff87h,0ff83h
DW 0c7f0h,0c7f0h,0e7f0h,0f3f1h,0fbf1h,0fbf9h,0fdf9h
DW 0fffch,0fffch,0fffeh,0f9ffh,0f8ffh,0f87fh,0ffffh
DW 00ff0h,00ff0h,00ff1h,00ff1h,00ff1h,08ff3h,0cff3h
DW 0ff1fh,0ff1fh,0ff1fh,0ff1fh,0ff3fh,0ff3fh,0ff3fh
DW 0c001h,0c003h,0ff03h,0ff03h,00007h,00007h,00007h
DW 0fe3fh,0fe3fh,0ffffh,0ffffh,0fc3fh,0fc3fh,0f83fh
DW 0f1f8h,0f1f8h,0c0ffh,0801fh,0c003h,0e001h,0f7e7h
DW 01f80h,00000h,08000h,0f000h,0f800h,0f800h,0f800h
DW 000ffh,000ffh,0007fh,00000h,00000h,00000h,00000h
DW 01fc0h,09fc0h,09fe0h,00000h,00000h,00000h,00000h
DW 0ffc1h,03fc0h,00fe0h,00000h,00000h,00000h,00000h
DW 0fffbh,0fffbh,03ffbh,00000h,00000h,00000h,00000h
DW 0ffffh,0f81fh,0f81fh,00000h,00000h,00000h,00000h
DW 0cfffh,0efffh,0efffh,00000h,00000h,00000h,00000h
DW 0fe3fh,0f87fh,0e07fh,00000h,00000h,00000h,00000h
DW 0ffcfh,0ffcfh,0ff8fh,00000h,00000h,00000h,00000h
DW 0f81fh,0f80fh,0f00fh,00000h,00000h,00000h,00000h
DW 0f7ffh,0f7ffh,0f3ffh,00000h,00000h,00000h,00000h
DW 0f800h,0f000h,08000h,00000h,00000h,00000h,00000h
LogoShadow DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 01fffh,07800h,0e000h,0c000h,08000h,00000h,00000h
DW 087ffh,00400h,00000h,00000h,00000h,00000h,00000h
DW 0f00fh,00410h,00000h,00000h,00000h,00000h,00000h
DW 0fc00h,00200h,00000h,00000h,00000h,00000h,00000h
DW 00fffh,02000h,08000h,00000h,00000h,00000h,00000h
DW 080ffh,0c000h,04000h,00000h,00000h,00000h,00000h
DW 0ffe0h,00060h,00000h,00000h,00000h,00000h,03000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,03c00h,0303ch,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00001h,00000h,00000h,00000h,00000h,00000h
DW 00000h,08000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,0003fh,00381h,00000h,00000h,00000h
DW 00000h,00000h,00000h,0001fh,00000h,00000h,00000h
DW 00000h,00000h,00000h,0fc00h,00c00h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,0ff03h,0e003h,04002h,04002h,02000h
DW 00000h,00000h,0f03fh,00030h,00000h,00000h,00000h
DW 00000h,00000h,0c3fch,00200h,00000h,00000h,00000h
DW 00000h,00000h,01fc0h,01000h,00000h,00000h,00000h
DW 00000h,00000h,07fe0h,00010h,00008h,00004h,00000h
DW 00000h,00000h,00fffh,00000h,00000h,00000h,00000h
DW 00000h,00000h,0f807h,00600h,00100h,00000h,00000h
DW 00000h,00000h,0fffch,00004h,00000h,00000h,00000h
DW 00000h,00000h,03fffh,00000h,00000h,00000h,00000h
DW 00000h,00000h,0e007h,07800h,01c00h,00c00h,00400h
DW 00000h,00000h,0ffe0h,000f0h,00070h,00030h,00000h
DW 02000h,01001h,01001h,00800h,00800h,00400h,00400h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00001h,00000h,00000h,00200h,00000h,00000h
DW 00000h,00000h,00000h,00000h,04000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00080h,00000h,00000h,00000h,07fe0h,00020h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00200h
DW 00000h,00000h,00000h,03800h,01ce0h,00818h,00000h
DW 00000h,06000h,00f00h,00700h,00300h,00300h,00200h
DW 00200h,00000h,00000h,00000h,00000h,00000h,00000h
DW 04000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
DW 00000h,00000h,00000h,00000h,00000h,00000h,00000h
;----------------------------------------------------------------------------------------------------------------------------------
; Variables
;----------------------------------------------------------------------------------------------------------------------------------
PauseCounter DB 0
GameStart DB 0
Frame DB 0
InvadersX DW 275
InvadersY DB 30
InvadersToggle DW 07ff0h,07ff0h,07ff0h,07ff0h,07ff0h
PlayerX DW 154
LeftToggle DB 0
RightToggle DB 0
FireToggle DB 0
ExitToggle DB 0
SoundToggle DB 0
KeyPress DB 0
Sound DB 080h
NextLevelToggle DB 0
MissileX DW 0
MissileY DB 0
UFOX DW 0
BombX DW 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
BombY DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
BombType DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
BombFreq DW 010h
MoveCount DB 1
InvaderSpeed DB 55
Direction DB 0
Reversing DB 0
Collision DB 0
Score DB 48,48,48,48,48
HighS DB 48,48,48,48,48
FirstFrame DB 0
Lives DB 48
BombMove DB 2
BombSpeed DB 2
PlayerDead DB 0
GameOverToggle DB 0
InvadersTitle DB "S P A C E I N V A D E R S",0
Copyright DB "COPYRIGHT ( 1995 BY PAUL S REID. ALL RIGHTS RESERVED",0
UFOScore DB "= 100 POINTS",0
Row1Score DB "= 25 POINTS",0
Row2Score DB "= 20 POINTS",0
Row3Score DB "= 15 POINTS",0
Row4Score DB "= 10 POINTS",0
Row5Score DB "= 5 POINTS",0
StartDocs DB "ANY KEY TO START GAME. ESC AT ANY TIME TO EXIT TO DOS",0
Dedication DB "...DEDICATED TO MY WIFE DEB...",0
ThankYou DB "THANKS TO BRENT KYLE AND TOM SWAN",0
SoundTog DB "PRESS S TO TOGGLE SOUND AT ANY TIME",0
PlayKeys DB "LEFT AND RIGHT CURSOR TO MOVE. CTRL TO FIRE",0
Distribution DB ".THIS GAME AND SOURCE CODE ARE FREELY DISTRIBUTABLE.",0
GameOverMsg DB "G A M E O V E R",0
GetReady DB "G E T R E A D Y",0
TempStore DW 0
Palette DB 00,00,00 ; Background
DB 21,63,63 ; Player's Ship
DB 63,21,21 ; Bunker
DB 63,21,21 ; UFO
DB 63,63,63 ; Missiles
DB 21,63,21 ; Status Letters
DB 63,63,00 ; Bombs
DB 63,63,63 ; DOS text (just for diagnostic printing if required)
DB 12,00,21 ; Top and bottom border backgrounds
DB 33,00,42 ; Logo shadow color
DB 00,00,00 ; Logo outline color
DB 63,63,00 ; Logo letters color
DB 41,41,41 ; Logo stars
DB 00,00,00
DB 00,00,00
DB 00,00,00
DB 21,63,21 ; Row 1 invader 1
DB 21,63,21 ; Row 1 invader 2
DB 21,63,21 ; Row 1 invader 3
DB 21,63,21 ; Row 1 invader 4
DB 21,63,21 ; Row 1 invader 5
DB 21,63,21 ; Row 1 invader 6
DB 21,63,21 ; Row 1 invader 7
DB 21,63,21 ; Row 1 invader 8
DB 21,63,21 ; Row 1 invader 9
DB 21,63,21 ; Row 1 invader 10
DB 21,63,21 ; Row 1 invader 11
DB 00,00,00
DB 00,00,00
DB 00,00,00
DB 00,00,00
DB 00,00,00
DB 21,63,21 ; Row 2 invader 1
DB 21,63,21 ; Row 2 invader 2
DB 21,63,21 ; Row 2 invader 3
DB 21,63,21 ; Row 2 invader 4
DB 21,63,21 ; Row 2 invader 5
DB 21,63,21 ; Row 2 invader 6
DB 21,63,21 ; Row 2 invader 7
DB 21,63,21 ; Row 2 invader 8
DB 21,63,21 ; Row 2 invader 9
DB 21,63,21 ; Row 2 invader 10
DB 21,63,21 ; Row 2 invader 11
DB 00,00,00
DB 00,00,00
DB 00,00,00
DB 00,00,00
DB 00,00,00
DB 21,63,63 ; Row 3 invader 1
DB 21,63,63 ; Row 3 invader 2
DB 21,63,63 ; Row 3 invader 3
DB 21,63,63 ; Row 3 invader 4
DB 21,63,63 ; Row 3 invader 5
DB 21,63,63 ; Row 3 invader 6
DB 21,63,63 ; Row 3 invader 7
DB 21,63,63 ; Row 3 invader 8
DB 21,63,63 ; Row 3 invader 9
DB 21,63,63 ; Row 3 invader 10
DB 21,63,63 ; Row 3 invader 11
DB 00,00,00
DB 00,00,00
DB 00,00,00
DB 00,00,00
DB 00,00,00
DB 21,63,63 ; Row 4 invader 1
DB 21,63,63 ; Row 4 invader 2
DB 21,63,63 ; Row 4 invader 3
DB 21,63,63 ; Row 4 invader 4
DB 21,63,63 ; Row 4 invader 5
DB 21,63,63 ; Row 4 invader 6
DB 21,63,63 ; Row 4 invader 7
DB 21,63,63 ; Row 4 invader 8
DB 21,63,63 ; Row 4 invader 9
DB 21,63,63 ; Row 4 invader 10
DB 21,63,63 ; Row 4 invader 11
DB 00,00,00
DB 00,00,00
DB 00,00,00
DB 00,00,00
DB 00,00,00
DB 63,21,63 ; Row 5 invader 1
DB 63,21,63 ; Row 5 invader 2
DB 63,21,63 ; Row 5 invader 3
DB 63,21,63 ; Row 5 invader 4
DB 63,21,63 ; Row 5 invader 5
DB 63,21,63 ; Row 5 invader 6
DB 63,21,63 ; Row 5 invader 7
DB 63,21,63 ; Row 5 invader 8
DB 63,21,63 ; Row 5 invader 9
DB 63,21,63 ; Row 5 invader 10
DB 63,21,63 ; Row 5 invader 11
VideoBuffer DB 0
CODE_SEG ENDS
END BEGIN