The article describing this program appears on a separate page.
MNYHNGRY.ASM is available in ATASCII format.
; MONEY HUNGRY
;
; BY DONALD MURPHY
;
; ANALOG COMPUTING
;
;VARIABLES
;
LEVEL = $80 ;LEVEL #
DELAY = $81 ;DELAY INDEX
HERE = $82
NOX = $83 ;HORIZ. MOVE FLAG
NOY = $84 ;VERT. MOVE FLAG
TX = $85 ;X HOLD AREA
DM = $86 ;MISC. VARIABLE
XM = $87 ;HORIZ. FLAG
YM = $88 ;VERT. FLAG
DIRC = $89 ;ENMY CUR DIRECTION
DIRN = $8C ;NEXT ENMY DIRECTION
NDOOR = $8F ;# OF DOORS
TF3 = $90
TF4 = $91
POINTL = $B0 ;GENERAL POINTER
POINTH = $B1
TABPTL = $B2 ;TABLE POINTER
TABPTH = $B3
VBPNTL = $B4 ;VBLANK POINTER
VBPNTH = $B5
EDELAY = $B6 ;ENEMY DELAY
ELEVEL = $B7 ;ENEMY LEVEL
XPOSP0 = $B8 ;HORIZ. POS. PLR 0
XPOSP1 = $B9 ;HORIZ. POS. PLR 1
XPOSP2 = $BA ;HORIZ. POS. PLR 2
XPOSP3 = $BB ;HORIZ. POS. PLR 3
SCOUNT = $BC ;SCORE COUNT TO ADD
YPOSP0 = $BD ;VERT. POS. PLR 0
YPOSP1 = $BE ;VERT. POS. PLR 1
YPOSP2 = $BF ;VERT. POS. PLR 2
YPOSP3 = $C0 ;VERT. POS. PLR 3
TEMPX = $C1 ;VERT. POS. PLR 4(?)
DRES = $C2 ;DIVISION RESULT
LDIV = $C3 ;LOW DIVIDEND
DIVS = $C4 ;DIVISOR
XPOSSC = $C5 ;HOR. POS. ON SCRN
YPOSSC = $C6 ;VERT POS. ON SCRN
MUPL = $C7 ;LO MULTIPLIER
MUCN = $C8 ;MULTIPLICAND
RESL = $C9 ;RESULT
RESH = $CA
STICKC = $CB ;STICK VALUE
STICKN = $CC ;NEXT STICK VALUE
NDOTS = $CD ;#DOTS EATEN
;
;HADWARE & SHADOW LOCATIONS
;
COLOR0 = $02C4 ;PLAYFIELD COLORS
COLOR1 = $02C5
COLOR2 = $02C6
SDLSTL = $0230 ;DISP LIST POINTER
SDLSTH = $0231
CHBAS = $02F4 ;CHAR BASE ADDR
GRACTL = $D01D ;GRAPHICS CONTROL
SDMCTL = $022F ;DMA CONTROL
COLPM0 = $D012 ;P/M COLORS
COLPM1 = $D013
COLPM2 = $D014
COLPM3 = $D015
HPOSP0 = $D000 ;PLAYER HOR. POS.
HPOSP1 = $D001
HPOSP2 = $D002
HPOSP3 = $D003
PMBASE = $D407 ;P/M BASE ADDRESS
VCOUNT = $D40B ;VERT. LINE COUNTER
WSYNC = $D40A ;WAIT FOR SYN
P0PF = $D004 ;COLLISION REGISTERS
P0PL = $D00C
P1PF = $D005
HITCLR = $D01E ;COLLISION CLEAR
RANDOM = $D20A ;RANDOM #
NMIST = $D40F ;NMI STATUS
AUDCTL = $D208 ;AUDIO CONTROL
AUDC1 = $D201 ;AUD. CHANNELS
AUDC2 = $D203
AUDF1 = $D200 ;AUD. FREQUENCIES
AUDF2 = $D202
CONSOL = $D01F ;CONSOLE KEYS
SKCTL = $0232 ;SERIAL PORT CTRL
GPRIOR = $026F ;P/M PRIORITY
STICK0 = $0278 ;SITCK 0
STRIG0 = $0284 ;BUTTON 0
;
;TABLES AND RAM ASSIGNMENTS
;
CTAB0 = $1800 ;PL.0 COLORS
CTAB1 = $1900 ;PL.1 COLORS
CTAB2 = $1A00 ;PL.2 COLORS
CTAB3 = $1B00 ;PL.3 COLORS
CHSET = $3800 ;CHARACTER SET
SCRAM = $3A00 ;SCREEN ADDRESS
PMRAM = $1C00 ;P/M ADDRESS
;
;PROGRAM START
;
*= $209E
;
;TITLE SCREEN DISPLAY LIST
;
TSCRD .BYTE 112,112,112,112,112
.BYTE 112,112,$47
.WORD TSCRW
.BYTE 112,6,112,7,112,112,112
.BYTE 112,6,$41
.WORD TSCRD
;
;TITLE SCREEN DATA
;
TSCRW .BYTE 0,0,0,0,45,47,46,37
.BYTE 57,0,40,53,46,39,50,57
.BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0
.BYTE 226,249,0,0,0,0,0,0,0,0,0
.BYTE 0,0,0,100,111,110,97
.BYTE 108,100,0,0,109,117,114
.BYTE 112,104,121,0,0,0,240,242
.BYTE 229,243,243,0,243,244,225
.BYTE 242,244,0,244,239,0,226
.BYTE 229,231,233,238
;
;GAME BOARD DISPLAY LIST
;
DLIST .BYTE 112,112,112,$45
.WORD SCRAM
.BYTE 5,5,5,5,5,5,5
.BYTE 5,5,5,7,65
.WORD DLIST
;
;PLAYER COLORS & BIT MAPS
;
ENBMAP .BYTE 54,20,127,54
.BYTE 42,127,28,62,0
ENCMAP .BYTE $FA,$8A,$8A,$BA
.BYTE $E6,$E6,$FF,$BA,$FF
PLBMAP .BYTE 119,28,8,20,62
.BYTE 28,28,62,0
PLCMAP .BYTE $38,$88,$88,$EA
.BYTE $EA,$38,$EA,$EA,$38
GAME .BYTE $A7,$A1,$AD,$A5
OVER .BYTE $AF,$B6,$A5,$B2
;
;GAME EXECUTION STARTS HERE!
;
INIT LDX #0
INILP LDA CHDAT,X ;SET UP
STA CHSET,X ;CHAR SET
LDA CHDAT+256,X
STA CHSET+256,X
LDA SCDAT,X ;AND SCREEN
STA SCRAM,X
LDA SCDAT+256,X
STA SCRAM+256,X
DEX
BNE INILP
LDA # >TSCRD ;SHOW...
STA SDLSTH ;TITLE SCREEN
LDA # <TSCRD
STA SDLSTL
LDA #$22
STA SDMCTL
PROG LDA CONSOL ;GET CONSOLE
CMP #6 ;START PRESSED?
BEQ GO ;YES!
LDA STRIG0 ;TRIGGER PRESSED?
BNE PROG ;NO!
GO LDA #DLIST&255 ;SHOW...
STA SDLSTL ;GAME SCREEN
LDA #DLIST/256
STA SDLSTH
LDA #CHSET/256 ;POINT TO
STA CHBAS ;CHAR SET
LDA #$88 ;SET COLORS
STA COLOR0
LDA #$FC
STA COLOR1
LDA #$36
STA COLOR2
LDA #0 ;SET...
STA GPRIOR ;PRIORITY
STA AUDCTL ;AND AUDIO
LDA #3 ;RESET SOUNDS
STA SKCTL
JSR SETSC ;SETUP SCREEN
JSR SETPM ;SETUP P/M
JSR SETPL ;SET YOU
JSR SETEM ;SET ENEMIES
STA HITCLR ;CLEAR COLLISIONS
JSR INT ;MISC. INIT.
JSR SETVB ;START VBLANK
JSR PRIZE ;INIT MONEY BAG
LDX #0 ;ZERO X REG
;
;MAINLINE COLOR LOOP
;
COLOR LDA P0PL ;HIT ANYTHING?
BEQ CONT ;NO, CONTINUE
JMP DEATH ;YOU'RE DEAD!
CONT STA WSYNC ;WAIT FOR SYNC
LDY VCOUNT ;GET VERT LINE#
LDA CTAB0,Y ;GET COLOR FOR
STA COLPM0 ;PLAYER 0
LDA CTAB1,Y ;GET COLOR FOR
STA COLPM1 ;PLAYER 1
LDA CTAB2,Y ;GET COLOR FOR
STA COLPM2 ;PLAYER 2
LDA CTAB3,Y ;GET COLOR FOR
STA COLPM3 ;PLAYER 3
LDA NDOTS ;# OF DOTS...
CMP #107 ;=107?
BCC COLOR ;NO, GET NEXT COLOR
JMP NEXTL ;NEW LEVEL!
;
;DEFERRED VBLANK
;
DVBL DEC EDELAY ;TIME FOR EN. MOVE?
BEQ EDO ;YES!
JMP END ;NO, EXIT
EDO LDA ELEVEL ;RESET MOVE TIMER
STA EDELAY
LDA #PMRAM/256+2 ;POINT TO
STA POINTH ;PLAYERS
LDA #$80
STA POINTL
LDA #CTAB1/256 ;GET COLOR...
STA TABPTH ;TABLE OFFSET
LDA #0
STA TABPTL
TAX ;ZERO X
MAIN LDA P1PF,X ;HIT ANYTHING?
AND #4 ;GET COLL. BITS
BEQ NHDR ;NO COLLISIONS
STA HITCLR ;RESET COLLISIONS
LDA DIRN,X ;NEXT DIRECTION
CMP DIRC,X ;= CURRENT DIR?
BNE EOR1 ;NO, CHANGE IT.
EOR #1 ;REVERSE IT,
STA DIRN,X ;STORE IT.
EOR1 LDA DIRC,X ;GET CURRENT
EOR #1 ;REVERSE IT,
STA DIRC,X ;AND STORE.
NHDR STX TEMPX ;SAVE X
LDA XPOSP1,X ;GET PLAYER X'S
CLC ;HORIZ. POS,
ADC #1 ;ADD 1
LDY YPOSP1,X ;GET VERT POS,
INY ;ADD 1
JSR PMOVE ;MOVE PLAYER
LDX TEMPX ;GET X AGAIN
LDA DIRN,X ;GET NEXT DIRECTION
AND #2 ;GET 1ST 2 BITS
BEQ TXM ;TRY HORIZ. MOVE
LDA YM ;OK TO MOVE VERT?
BEQ CCHD ;YES, CHANGE DIR
JMP KCD ;NO, KEEP CURRENT
TXM LDA XM ;HORIZ MOVE OK?
BNE KCD ;NO, KEEP CURRENT
CCHD LDA DIRN,X ;CHANGE DIRECTION
STA DIRC,X ;STORE NEXT DIR
LDA RANDOM ;GET RANDOM #
AND #3 ;MASK TO 0-3
STA DIRN,X ;SAVE FOR NEXT
KCD LDA DIRC,X ;GET CURRENT DIR
BNE TA1 ;NOT RIGHT
JMP MPXR ;MOVE RIGHT!
TA1 CMP #1 ;IS IT LEFT?
BNE TA2 ;NO!
JMP MPXL ;MOVE LEFT!
TA2 CMP #2 ;IS IT UP?
BNE TA3 ;NO!
JMP MPXU ;MOVE UP!
TA3 JMP MPXD ;MOVE DOWN!
;
;SET UP SCREEN
;
SETSC LDA #0 ;ERASE MONEY BAG
STA SCRAM+219
STA SCRAM+220
LDA #SCRAM&255 ;POINT...
STA POINTL ;TO SCREEN
LDA #SCRAM/256
STA POINTH
LDY #6 ;SCRN BORDER OFFSET
L1 LDA (POINTL),Y ;GET SCRN BYTE
BEQ NFL ;EMPTY-PLOT DOT!
CMP #30 ;IS IT DOT?
BEQ NFL ;YES, PLOT AGAIN!
CMP #31 ;WALL?
BNE PL1 ;YES, DON'T PLOT
DEY ;PREVIOUS POS.
LDA #0 ;ZERO IT!
STA (POINTL),Y
INY ;BACK TO THIS POS.
NFL LDA #17 ;PLOT A DOT.
STA (POINTL),Y
PL1 INY ;NEXT POSITION
INY
CPY #36 ;END OF LINE?
BCC L1 ;NO!
LDA POINTL ;INCREMENT...
CLC ;POINTER...
ADC #40 ;TO NEXT LINE
STA POINTL
LDA POINTH
ADC #0
STA POINTH
LDY #6 ;LAST LINE?
CMP #SCRAM/256+1
BCC L1 ;NO!
LDA POINTL ;LAST LINE?
CMP #144
BNE L1 ;NO!
LDA #0 ;RESET...
STA NDOTS ;# OF DOTS
STA SCOUNT ;AND SCORE COUNT
LDA #5 ;RESET # DOORS
STA NDOOR
RTS ;ALL DONE!
;
;INIT PLAYER-MISSILE GRAPHICS
;
SETPM LDA #PMRAM/256+2 ;POINT...
STA POINTH ;TO...
LDA #0 ;PLAYER MEMORY
STA POINTL
TAY ;ZERO Y REG.
L3 STA (POINTL),Y ;ZERO P/M AREA
INY
BNE L3
INC POINTH
LDX POINTH ;DONE CLEARING?
CPX #PMRAM/256+4
BNE L3 ;NO!
LDA #CTAB0/256 ;POINT...
STA POINTH ;TO...
LDA #0 ;COLOR TABLES
STA POINTL
TAY ;ZERO Y REG.
Q1 STA (POINTL),Y ;ZERO COLOR TABLES
INY
BNE Q1
INC POINTH
LDX POINTH ;DONE CLEARING?
CPX #CTAB3/256+1
BNE Q1 ;NO!
LDA #46 ;TURN ON P/M
STA SDMCTL
LDA #3
STA GRACTL
LDA #PMRAM/256 ;POINT TO...
STA PMBASE ;P/M AREA
RTS ;ALL DONE!
;
;RUN VBLANK ROUTINES
;
SETVB LDA #6 ;SET IMMEDIATE!
LDX #VBLANK/256
LDY #VBLANK&255
JSR $E45C
LDA #64 ;TURN ON
STA NMIST
LDA #7 ;SET DEFERRED!
LDX #DVBL/256
LDY #DVBL&255
JMP $E45C ;ALL DONE!
;
;DRAW ENEMIES ON SCREEN
;
SETEM LDA #$80 ;POINT TO P/M
STA POINTL
LDA #PMRAM/256+2
STA POINTH
LDA #0 ;POINT TO COLORS
STA TABPTL
LDA #CTAB1/256
STA TABPTH
L4 LDY #23 ;P/M VERT OFFSET
LDX #8 ;P/M HEIGHT
L5 LDA ENBMAP,X ;DRAW ONE!
STA (POINTL),Y
LDA ENCMAP,X
STA (TABPTL),Y
INY
DEX
BPL L5
INC TABPTH ;NEXT COLOR TABLE
LDA POINTL ;NEXT PLAYER
CLC
ADC #$80
STA POINTL
LDA POINTH
ADC #0
STA POINTH
CMP #PMRAM/256+4 ;LAST PLAYER?
BCC L4 ;NO!
LDA #$43 ;PL 1 HORIZONTAL
STA XPOSP1
STA HPOSP1
LDA #$84 ;PL 2 HORIZONTAL
STA XPOSP2
STA HPOSP2
LDA #$B3 ;PL 3 HORIZONTAL
STA XPOSP3
STA HPOSP3
LDA #23 ;ALL VERTICAL
STA YPOSP1
STA YPOSP2
STA YPOSP3
LDA #3 ;P1&3 GOING DOWN
STA DIRC
STA DIRC+2
LDA #1 ;P2 GOING LEFT
STA DIRC+1
RTS ;ALL DONE!
;
;SET UP YOUR PLAYER
;
SETPL LDX #8 ;8 BYTES TALL
LDY #55 ;GET VERT OFFSET
L6 LDA PLBMAP,X ;DRAW HIM!
STA PMRAM+512,Y
LDA PLCMAP,X
STA CTAB0,Y
INY
DEX
BPL L6
LDA #124 ;SET HORIZ POS
STA XPOSP0
STA HPOSP0
LDA #55 ;AND VERT POS
STA YPOSP0
LDA #11 ;GOING LEFT!
STA STICKC
STA STICKN
RTS ;BYE!
;
;IMMEDIATE VBLANK
;
VBLANK LDA #0 ;TURN OFF...
STA AUDC1 ;SOUND 1
STA AUDC2 ;SOUND 2
LDX XPOSP0 ;GET PLAYER X
INX ;OFFSET FOR SCRN
LDY YPOSP0 ;GET PLAYER Y
INY ;OFFSET IT TOO
JSR PMTGR ;CONVERT TO SCRN LOC
JSR XYTOME ;THEN TO ADDRESS
DEC DELAY ;OK TO MOVE?
BEQ DO ;YUP!
JMP ENDVB ;NO, EXIT.
DO LDA LEVEL ;RESET TIMER
STA DELAY
LDA STICKN ;GET NEXT DIRECTION
AND #3 ;MASK IT,
CMP #3 ;HORIZ MOVEMENT?
BEQ TNM ;YES!
LDA NOY ;CHECK IF VERT CLEAR
BEQ CHD ;IT'S CLEAR!
JMP CD ;KEEP CURRENT DIR
TNM LDA NOX ;HORIZ CLEAR?
BNE CD ;NO! KEEP CURRENT
CHD LDA STICKN ;GET NEXT MOVE
STA STICKC ;SAVE IN CURRENT
CD LDA STICK0 ;GET STICK
CMP #15 ;MOVED?
BEQ NC ;NO!
STA STICKN ;SAVE NEW MOVE
NC LDA STICKC ;GET CURRENT
CMP #15 ;MOVED?
BNE N15 ;YES!
JMP ENDVB ;NO, EXIT.
N15 CMP #10 ;UP?
BEQ MU ;YES!
CMP #6 ;UP?
BEQ MU ;YES!
CMP #14 ;UP?
BNE VBP1 ;NO!
MU LDX #$0A ;10 BYTES TO MOVE
LDY YPOSP0 ;GET VERT OFFSET
CPY #24 ;AT TOP?
BCS VBL1 ;NO, MOVE IT!
JMP ENDVB ;BYE!
VBL1 LDA PMRAM+512,Y ;MOVE PLAYER
STA PMRAM+511,Y
LDA CTAB0,Y
STA CTAB0-1,Y
INY
DEX
BNE VBL1
DEC YPOSP0 ;DEC VERT POS.
MUE JMP ENDVB ;BYE!
VBP1 CMP #9 ;DOWN?
BEQ MD ;YES!
CMP #5 ;DOWN?
BEQ MD ;YES!
CMP #13 ;DOWN?
BNE VBP2 ;NO!
MD LDA YPOSP0 ;AT BOTTOM?
CMP #87
BCC OKMD ;NO, MOVE IT!
JMP ENDVB ;BYE!
OKMD ADC #9 ;GET LAST PLAYER BYTE
TAY ;PUT IN Y
LDX #$0A ;10 BYTES TO MOVE
VBL2 LDA PMRAM+511,Y ;MOVE PLAYER
STA PMRAM+512,Y
LDA CTAB0-1,Y
STA CTAB0,Y
DEY
DEX
BNE VBL2
INC YPOSP0 ;INC VERT POS.
MDE JMP ENDVB ;BYE!
VBP2 CMP #11 ;LEFT?
BNE VBP3 ;NO!
LDX XPOSP0 ;TOO FAR LEFT?
CPX #68
BCS OKML ;NO!
JMP ENDVB ;BYE!
OKML DEX ;DEC HORIZ POS
STX XPOSP0
STX HPOSP0
MLE JMP ENDVB ;BYE!
VBP3 LDX XPOSP0 ;TOO FAR RIGHT?
CPX #179
BCC OKMR ;NO!
JMP ENDVB ;BYE!
OKMR INX ;INC HORIZ POS
STX XPOSP0
STX HPOSP0
ENDVB JMP $E45F ;LEAVE VBLANK!
;
;P/M TO SCREEN COORDS SUBROUTINE
;
PMTGR STX XPOSSC ;SAVE HORIZ
STY YPOSSC ;SAVE VERT
TYA ;GET VERT IN A
SEC ;SUB SCREEN OFFSET
SBC #16
STA LDIV ;SAVE IN DIVIDER
LDA #8 ;DIV. BY 8
STA DIVS
LDA #0 ;ZERO RESULT
STA DRES
JSR DIVIDE ;DIVIDE IT!
STA NOX ;STORE REMAINDER
LDA DRES ;GET RESULT
STA YPOSSC ;SAVE SCREEN Y
AND #1 ;EVEN OR ODD?
BNE OD1 ;ODD!
LDA #1 ;PROHIBIT ANY
STA NOX ;HORIZONTAL MOVE
OD1 LDA XPOSSC ;GET HORIZ.
SEC ;SUB SCREEN OFFSET
SBC #48
STA LDIV ;PUT IN DIVIDER
LDA #4 ;DIVIDE BY 4
STA DIVS
LDA #0 ;ZERO RESULT
STA DRES
JSR DIVIDE ;DIVIDE IT!
STA NOY ;SAVE REMAINDER
LDA DRES ;GET RESULT
STA XPOSSC ;SAVE SCREEN X
AND #3 ;IS VERT MOVE OK?
EOR #1
BEQ OD2 ;YES!
LDA #1 ;PROHIBIT ALL
STA NOY ;VERTICAL MOVES
OD2 LDA DRES ;GET RESULT
STA XPOSSC ;SAVE SCREEN X
RTS ;ALL DONE!
;
;X&Y COORDS TO MEMORY ADDRESS
;
XYTOME LDA #0 ;ZERO...
STA VBPNTL ;VBLANK POINTER
STA RESH ;AND RESULT
LDA STICKC ;GET CURRENT DIR.
AND #1 ;LEFT?
BNE NI ;NO!
LDA STICKN ;GET NEXT DIR
CMP #11 ;LEFT?
BNE INCY ;NO!
DEC YPOSSC ;CANCEL NEXT INC
INCY INC YPOSSC ;INC VERT POS
NI LDA YPOSSC ;GET VERT
STA MUPL ;SAVE MULTIPLIER
LDA #40 ;TIMES 40
STA MUCN
JSR MULT ;MULTIPLY IT!
INC XPOSSC ;INC HORIZ POS
LDA XPOSSC ;GET IT,
CLC ;ADD RESULT
ADC RESL
STA VBPNTL ;SAVE IN POINTER
LDA RESH
ADC #SCRAM/256 ;ADD SCRN BASE
STA VBPNTH
LDY #0 ;ZERO Y
LDA (VBPNTL),Y ;GET BYTE
CMP #30 ;IS IT DOOR?
BNE DHCD ;NO!
LDA #38 ;MAKE DOOR SOUND
STA AUDC1
LDA #20
STA AUDF1
LDA #0
TAY
STA (VBPNTL),Y ;ERASE DOOR
INC NDOOR ;1 MORE DOOR
DHCD CMP #31 ;IS IT DOOR?
BNE CVDA ;NO!
LDA #38 ;MAKE DOOR SOUND
STA AUDC1
LDA #20
STA AUDF1
LDA #0
TAY
STA (VBPNTL),Y ;ERASE DOOR
DEC VBPNTL ;(2 BYTES)
STA (VBPNTL),Y
INC VBPNTL
INC NDOOR ;1 MORE DOOR
CVDA CMP #17 ;IS IT A DOT?
BEQ CC ;YES!
CMP #29 ;MONEY BAG?
BNE R ;NO!
LDA #166 ;MAKE SOUND
STA AUDC1
LDA #220
STA AUDF1
LDX #100 ;ADD 100 TO SCORE
STX SCOUNT
DEC VBPNTL ;ERASE MONEY BAG
TYA
STA (VBPNTL),Y
INC VBPNTL
STA (VBPNTL),Y
RTS ;AND EXIT!
CC TYA ;ERASE DOT
STA (VBPNTL),Y
INC NDOTS ;1 MORE DOT TAKEN
LDX #1 ;ADD 1 POINT
STX SCOUNT
LDA #95 ;MAKE SOUND
STA AUDC1
LDA #185
STA AUDF1
R RTS ;AND EXIT!
;
;GENERAL-PURPOSE DIVIDE ROUTINE
;
DIVIDE LDY #8 ;GET # OF BITS
SEC ;SUBTRACT DIVISOR
SBC DIVS
DILO PHP ;SAVE PROC. STATUS
ROL DRES ;ROTATE RESULT
ASL LDIV ;SHIFT DIVIDER
ROL A ;ROTATE DIVIDER
PLP ;GET STATUS BACK
BCC ADD ;BRANCH IF CLEAR
SBC DIVS ;SUBTRACT DIVISOR
JMP NEXT ;CONTINUE
ADD ADC DIVS ;ADD DIVISOR
NEXT DEY ;LAST BIT?
BNE DILO ;NO!
BCS LAST ;BRANCH IF LAST
ADC DIVS ;ADD DIVISOR
CLC ;CLEAR CARRY
LAST ROL DRES ;ROTATE RESULT
RTS ;AND EXIT.
;
;MULTIPLY SUBROUTINE
;
MULT LDA #0 ;ZERO RESULT
STA RESL
LDX #8 ;8 BITS
MLOP LSR MUPL ;SHIFT MULTIPLIER
BCC NOADD ;HI BIT EMPTY
CLC ;ADD MULTIPLICAND
ADC MUCN
NOADD ROR A ;ROTATE RESULT
ROR RESL ;AND LOW RESULT
DEX ;1 MORE BIT
BNE MLOP ;MORE TO COME!
STA RESH ;SAVE RESULT HI
RTS ;AND EXIT
;
;SCOREKEEPING SUBROUTINE
;
SCORE LDY #5 ;6TH SCORE DIGIT
CPX #1 ;ANY INCREASE
BCS GET ;YES!
RTS ;NO, RETURN
GET LDA SCRAM+447,Y ;GET SCORE
CMP #27 ;>=9?
BCC NOB ;NO
LDA #18 ;WRAP TO ZERO
STA SCRAM+447,Y
DEY ;NEXT CHARACTER
BPL GET
RTS ;ALL DONE!
NOB CLC ;INCREMENT THE
ADC #1 ;SCORE
STA SCRAM+447,Y
DEX ;NEXT ADD
BNE SCORE ;GO ADD IT!
RTS ;ALL DONE!
;
;PLAYER MOVEMENT
;
PMOVE STA YM ;SAVE ACCUM
TYA ;MOVE VERT TO A
SEC ;SCREEN OFFSET
SBC #16
STA LDIV ;PUT IN DIVIDER
LDA #8 ;DIV BY 8
STA DIVS
LDA #0 ;CLEAR RESULT
STA DRES
JSR DIVIDE ;DIVIDE IT!
STA XM ;SAVE REMAINDER
LDA DRES ;GET RESULT
AND #1 ;ODD?
BNE OD1M ;YES!
LDA #1 ;DON'T PERMIT
STA XM ;HORIZ. MOVE
OD1M LDA YM ;GET VERT
SEC ;SUB SCREEN OFFSET
SBC #48
STA LDIV ;STORE IN DIVIDER
LDA #4 ;DIV BY 4
STA DIVS
LDA #0 ;CLEAR RESULT
STA DRES
JSR DIVIDE ;DIVIDE IT!
STA YM ;SAVE REMAINDER
LDA DRES ;GET RESULT
AND #3 ;VERT MOVE OK?
EOR #1
BEQ OD2M ;YES!
LDA #1 ;DON'T ALLOW
STA YM ;VERT MOVEMENT
OD2M RTS ;EXIT!
MPXR LDY XPOSP1,X ;CAN PLAYER
CPY #179 ;MOVE RIGHT?
BCC CMR ;YES!
JMP END ;NO!
CMR INY ;INCREMENT HORIZ
TYA ;PUT IN ACCUM
STA XPOSP1,X ;SET THE POS
STA HPOSP1,X
JMP END ;ALL DONE!
MPXL LDY XPOSP1,X ;CAN PLAYER
CPY #68 ;MOVE LEFT?
BCS CML ;YES!
JMP END ;NO!
CML DEY ;DEC HORIZ
TYA ;PUT IN ACCUM
STA XPOSP1,X ;CHANGE POS
STA HPOSP1,X
JMP END ;ALL DONE
MPXU LDY YPOSP1,X ;GET VERT
LDX #$0A ;10 BYTES TO MOVE
CPY #24 ;AT TOP?
BCS CMU ;NO, CAN MOVE
JMP END ;CAN'T GO UP!
CMU LDA (POINTL),Y ;MOVE UP!
DEY
STA (POINTL),Y
INY
LDA (TABPTL),Y ;MOVE COLORS
DEY
STA (TABPTL),Y
INY
INY
DEX
BNE CMU
LDX TEMPX ;RESTORE X
DEC YPOSP1,X ;DEC VERT POS
JMP END ;ALL DONE
MPXD LDX TEMPX ;GET PLAYER #
LDA YPOSP1,X ;CAN HE...
CMP #87 ;GO DOWN?
BCC CMD ;YES!
JMP END ;NO!
CMD ADC #9 ;GET OFFSET...
TAY ;TO PLAYER END
LDX #$0A ;10 BYTES
L DEY
LDA (POINTL),Y ;MOVE HIM!
INY
STA (POINTL),Y
DEY
LDA (TABPTL),Y ;MOVE COLOR
INY
STA (TABPTL),Y
DEY
DEX
BNE L
LDX TEMPX ;RESTORE X
INC YPOSP1,X ;INC VERT POS
JMP END ;ALL DONE
;
;VBLANK FINISH
;
END LDA POINTL ;ADD 128 TO
CLC ;P/M POINTER
ADC #$80 ;TO INDICATE
STA POINTL ;NEXT PLAYER
LDA POINTH
ADC #0
STA POINTH
INC TABPTH
LDX TEMPX ;GET PLAYER #
INX ;INCREMENT IT
CPX #3 ;ALL DONE?
BCS ENDDVB ;YES!
JMP MAIN ;NO, LOOP BACK!
ENDDVB LDX SCOUNT ;GET SCORE ADD
LDA #0 ;ZERO IT
STA SCOUNT
JSR SCORE ;ADD TO SCORE
LDA STRIG0 ;BUTTON PRESSED?
BNE PQW ;NO!
JSR DOOR ;PLACE A DOOR
PQW JMP $E462 ;VBLANK DONE!
;
;INITIALIZATION SEQUENCE
;
INT LDA #3 ;SET UP...
STA LEVEL ;INITIAL SPEEDS
STA ELEVEL
STA DELAY
STA EDELAY
LDY #19 ;CLEAR SCORE LINE
LDA #0
CG STA SCRAM+440,Y
DEY
BNE CG
LDA #$57 ;RESET # MEN
STA SCRAM+442
LDY #0 ;ZERO SCORE
LDA #18
L2 STA SCRAM+447,Y
INY
CPY #6
BNE L2
RTS ;ALL DONE!
;
;CHANGE LEVELS
;
NEXTL LDA ELEVEL ;GET ENEMY SPEED
CMP LEVEL ;SAME AS PLAYER?
BEQ NDS ;YES!
DEC LEVEL ;SPEED UP PLAYER
BNE NOC ;BUT DON'T ALLOW
LDA #1 ;LEVEL < 1
STA LEVEL
NDS DEC ELEVEL ;SPEED UP ENEMY
BNE NOC ;BUT DON'T ALLOW
LDA #1 ;ELEVEL < 1
STA ELEVEL
NOC JSR CLRVB ;CLEAR VBLANK
JSR SOUND2 ;MAKE A SOUND
JSR SETSC ;SET UP SCREEN
JSR SETPM ;SET UP P/M
JSR SETEM ;SET ENEMIES
JSR SETPL ;SET UP PLAYER
JSR SETVB ;SET VBLANK
JSR PRIZE ;SET UP MONEYBAGS
JMP COLOR ;DISPLAY COLORS
;
;CLEAR VBLANK VECTORS
;
CLRVB LDA #6 ;IMMEDIATE OFF
LDX #$E4
LDY #$5F
JSR $E45C
LDA #7 ;DEFERRED OFF
LDX #$E4
LDY #$62
JMP $E45C ;AND EXIT
;
;MONEY BAG HANDLER
;
PRIZE LDA #MONEY/256 ;SET UP...
STA $0227 ;TIMER 1 VECTOR...
LDA #MONEY&255 ;TO POINT TO...
STA $0226 ;BAG PRINTER
SETT1 LDA #1 ;SET UP TIMER!
LDY #0
LDX #4
JMP $E45C ;ALL DONE!
;
;MONEY BAG DISPLAY ROUTINE
;
MONEY LDA #28 ;PUT BAG CHAR 1
STA SCRAM+219 ;ON SCREEN
LDA #29 ;PUT BAG CHAR 2
STA SCRAM+220 ;ON SCREEN
LDA #MGONE/256 ;REPOINT TIMER
STA $0227 ;TO BAG ERASE
LDA #MGONE&255 ;ROUTINE
STA $0226
JMP SETT1 ;GO SET IT
MGONE LDA #0 ;ERASE BAG
STA SCRAM+219
STA SCRAM+220
RTS ;AND EXIT
DEATH JSR CLRVB ;TURN OFF VBLANK
JSR SOUND1 ;DO DEATH SOUND
LDX SCRAM+442 ;1 LESS LIFE
DEX
CPX #$52 ;MORE LIVES?
BCS STILL ;YES!
JMP GOVER ;GAME OVER!
STILL STX SCRAM+442 ;ZERO LIVES
JSR SETPM ;SET UP P/M
JSR SETPL ;AND PLAYER
JSR SETEM ;AND ENEMIES
JSR SETVB ;AND VBLANK
STA HITCLR ;CLEAR COLLISIONS
JMP COLOR ;AND RESTART!
;
;GAME OVER ROUTINE
;
GOVER LDX #0 ;SHOW MESSAGE:
PR1 LDA GAME,X ;'GAME'
STA SCRAM+442,X
INX
CPX #4
BNE PR1
LDX #0
PR2 LDA OVER,X ;'OVER'
STA SCRAM+454,X
INX
CPX #4
BNE PR2
JMP PROG ;AND RESTART!
;
;OPEN DOOR
;
DOOR DEC NDOOR ;1 LESS DOOR
BNE RED ;DOORS LEFT
INC NDOOR ;NO DOORS!
RTS ;EXIT
RED LDA NOY ;VERTICAL DOOR?
BEQ VD ;YES!
LDA XPOSSC ;OK FOR HOR. DOOR?
AND #3
BNE ENDD ;NO!
LDA #$C0 ;MAKE DOOR SOUND
STA AUDF2
LDA #$A3
STA AUDC2
LDY #0 ;DRAW DOOR
LDA #30
STA (VBPNTL),Y
RTS ;AND EXIT
VD LDA YPOSSC ;VERT DOOR OK?
AND #1
BNE ENDD ;NO!
LDA #$C0 ;MAKE DOOR SOUND
STA AUDF2
LDA #$A3
STA AUDC2
DEC VBPNTL ;BACK 1 CHAR
LDY #1 ;DRAW DOOR
LDA #31
STA (VBPNTL),Y
DEY
STA (VBPNTL),Y
RTS ;AND EXIT
ENDD INC NDOOR ;NO DOOR DISPLAYED,
RTS ;RESET & RETURN
;
;SOUND SUBROUTINES
;
SOUND1 LDA #168 ;INIT SOUND
STA AUDC2
LDA #100 ;INIT FREQ
STA TF3
LDX #$FF ;LOW DELAY COUNT
LDY #20 ;HI DELAY COUNT
SL1 LDA TF3 ;GET FREQ
STA AUDF2 ;STORE IT
DEX ;DELAY 1
BNE SL1 ;LOOP IF NOT READY
DEY ;DELAY 2
BNE SL1 ;LOOP AGAIN
INC TF3 ;INC FREQUENCY
INC TF3
LDY #20 ;RESET HI DELAY
LDA TF3 ;GET FREQ
CMP #$A0 ;LAST FREQ?
BNE SL1 ;NO!
LDA #136 ;END OF SOUND
STA AUDC2
LDA #50
STA AUDF2
LDX #255 ;LO DELAY COUNT
LDY #255 ;HI DELAY COUNT
SL2 DEX ;DELAY LOOP
BNE SL2
DEY
BNE SL2
LDA #0 ;SOUND OFF
STA AUDF2
STA AUDC2
RTS ;BYE!
SOUND2 LDA #168 ;INITIAL SOUND
STA AUDC1
LDA #$40 ;INITIAL FREQ
STA TF4
LDX #$FF ;LO DELAY COUNT
LDY #20
SL3 LDA TF4 ;GET FREQ
STA AUDF1 ;STORE IT
DEX ;DELAY 1
BNE SL3
DEY ;DELAY 2
BNE SL3
DEC TF4 ;NEXT FREQ
DEC TF4
LDY #20 ;RESET DELAY
LDA TF4 ;LAST FREQ?
BNE SL3 ;NO!
LDA #0 ;TURN OFF SOUND
STA AUDF1
STA AUDC1
RTS ;AND EXIT
;
;CHARACTER SET DATA
;
CHDAT
.BYTE 0,0,0,0,0,0,0,0,85,85
.BYTE 85,170,85,85,85,85,149,149,149,170
.BYTE 85,85,85,85,85,85,85,170,149,149
.BYTE 149,149,149,149,149,149,149,149,149,149
.BYTE 21,21,21,21,21,21,21,21,149,149
.BYTE 149,170,149,149,149,149,86,86,86,170
.BYTE 86,86,86,86,85,85,85,170,86,86
.BYTE 86,86,86,86,86,170,85,85,85,85
.BYTE 84,84,84,84,84,84,84,84,86,86
.BYTE 86,86,86,86,86,86,85,85,85,85
.BYTE 85,85,85,85,149,149,149,149,85,85
.BYTE 85,85,86,86,86,86,85,85,85,85
.BYTE 85,85,85,149,149,149,149,149,85,85
.BYTE 85,86,86,86,86,86,0,0,0,128
.BYTE 0,0,0,0,0,60,102,110,118,102
.BYTE 60,0,0,24,56,24,24,24,126,0
.BYTE 0,60,102,12,24,48,126,0,0,126
.BYTE 12,24,12,102,60,0,0,12,28,60
.BYTE 108,126,12,0,0,126,96,124,6,102
.BYTE 60,0,0,60,96,124,102,102,60,0
.BYTE 0,126,6,12,24,48,48,0,0,60
.BYTE 102,60,102,102,60,0,0,60,102,62
.BYTE 6,12,56,0,34,10,42,160,162,160
.BYTE 42,10,136,160,40,10,42,10,40,160
.BYTE 192,192,192,192,192,192,192,192,0,0
.BYTE 0,255,0,0,0,0,0,60,102,110
.BYTE 110,96,62,0,0,24,60,102,102,126
.BYTE 102,0,0,124,102,124,102,102,124,0
.BYTE 0,60,102,96,96,102,60,0,0,120
.BYTE 108,102,102,108,120,0,0,126,96,124
.BYTE 96,96,126,0,0,126,96,124,96,96
.BYTE 96,0,0,62,96,96,110,102,62,0
.BYTE 0,102,102,126,102,102,102,0,0,126
.BYTE 24,24,24,24,126,0,0,6,6,6
.BYTE 6,102,60,0,0,102,108,120,120,108
.BYTE 102,0,0,96,96,96,96,96,126,0
.BYTE 0,99,119,127,107,99,99,0,0,102
.BYTE 118,126,126,110,102,0,0,60,102,102
.BYTE 102,102,60,0,0,124,102,102,124,96
.BYTE 96,0,0,60,102,102,102,108,54,0
.BYTE 0,124,102,102,124,108,102,0,0,60
.BYTE 96,60,6,6,60,0,0,126,24,24
.BYTE 24,24,24,0,0,102,102,102,102,102
.BYTE 126,0,0,102,102,102,102,60,24,0
.BYTE 0,99,99,107,127,119,99,0,0,102
.BYTE 102,60,60,102,102,0,0,102,102,60
.BYTE 24,24,24,0,0,126,12,24,48,96
.BYTE 126,0,0,30,24,24,24,24,30,0
.BYTE 0,64,96,48,24,12,6,0,0,120
.BYTE 24,24,24,24,120,0,0,8,28,54
.BYTE 99,0,0,0,0,0,0,0,0,0
.BYTE 255,0,0
;
;SCREEN DATA
;
SCDAT
.BYTE 0,0,0,5,3,1,1,1,3,1
.BYTE 1,1,3,1,1,1,3,1,1,1
.BYTE 3,1,1,1,3,1,1,1,3,1
.BYTE 1,1,3,1,1,8,10,0,0,0
.BYTE 0,0,0,5,4,0,17,0,17,0
.BYTE 17,0,17,0,17,0,17,0,17,0
.BYTE 17,0,17,0,17,0,17,0,17,0
.BYTE 17,0,17,0,17,11,10,0,0,0
.BYTE 0,0,0,5,4,0,17,1,6,0
.BYTE 17,1,6,0,17,1,6,0,17,1
.BYTE 6,0,17,1,6,0,17,1,6,0
.BYTE 17,1,6,0,17,11,10,0,0,0
.BYTE 0,0,0,5,4,0,17,0,17,0
.BYTE 17,0,17,0,17,0,17,0,17,0
.BYTE 17,0,17,0,17,0,17,0,17,0
.BYTE 17,0,17,0,17,11,10,0,0,0
.BYTE 0,0,0,5,4,0,17,1,6,0
.BYTE 17,1,6,0,17,1,6,0,17,1
.BYTE 6,0,17,1,6,0,17,1,6,0
.BYTE 17,1,6,0,17,11,10,0,0,0
.BYTE 0,0,0,5,4,0,0,0,0,0
.BYTE 0,0,0,0,0,0,0,0,0,0
.BYTE 0,0,17,0,17,0,17,0,17,0
.BYTE 17,0,17,0,17,11,10,0,0,0
.BYTE 0,0,0,5,4,0,17,1,6,0
.BYTE 17,1,6,0,17,1,6,0,17,1
.BYTE 6,0,17,1,6,0,17,1,6,0
.BYTE 17,1,6,0,17,11,10,0,0,0
.BYTE 0,0,0,5,4,0,17,0,17,0
.BYTE 17,0,17,0,17,0,17,0,17,0
.BYTE 17,0,17,0,17,0,17,0,17,0
.BYTE 17,0,17,0,17,11,10,0,0,0
.BYTE 0,0,0,5,4,0,17,1,6,0
.BYTE 17,1,6,0,17,1,6,0,17,1
.BYTE 6,0,17,1,6,0,17,1,6,0
.BYTE 17,1,6,0,17,11,10,0,0,0
.BYTE 0,0,0,5,4,0,17,0,17,0
.BYTE 17,0,17,0,17,0,17,0,17,0
.BYTE 17,0,17,0,17,0,17,0,17,0
.BYTE 17,0,17,0,17,11,10,0,0,0
.BYTE 0,0,0,5,2,1,1,1,2,1
.BYTE 1,1,2,1,1,1,2,1,1,1
.BYTE 2,1,1,1,2,1,1,1,2,1
.BYTE 1,1,2,1,1,9,10,0,0,0
.BYTE 0,0,87,0,0,0,0,18,18,18
.BYTE 18,18,26,0,0,0,0,0,0,0
.BYTE 0,0,0,0,0,0,0,0,0,0
.BYTE 0,0,0,0,0,0,0,0,0,0
.BYTE 0,0,0,0,0,0,0,0,0,0
.BYTE 0,0,0,0,0,0,0,0,0,0
.BYTE 0,0,0,0,0,0,0,0,0,0
.BYTE 0,0,0
;
;RUN ADDRESS
;
*= $02E0
.WORD INIT
.END