* STERN DRACULA, WILD FYRE * (C) 1978 STERN ELECTRONICS * COMMENTS, NOTES, (C) 2011,2022 SC * * QUESTIONS/COMMENTS TO @SLOCHAR ON PINSIDE.COM * * NOTES: * * THERE APPEARS TO BE A FACTORY BUG IN THE LEFT INLANE SPECIAL - THE PLAYFIELD * STATES "5000 & SPECIAL WHEN LIT" HOWEVER THERE IS NO CODE TO AWARD THE 5000 * POINTS WHEN THE SPECIAL IS LIT - ONLY THE SPECIAL. IT PAYS ONLY 500 IN EITHER * CASE (SPECIAL LIT OR NOT) * MEMORY MAP * * ICS * * $0000-$007F U7 6810 SCRATCHPAD MEMORY * $0088-$008B U10 6821 PIA * $0090-$0093 U11 6821 PIA * $0200-$02FF U8 5101 BATTERY BACKED RAM (HIGH NIBBLE ONLY) * $1000-$17FF U2 ROM * $1800-$1FFF U6 ROM * * $0000 DISPLAY DIGIT INDEX * $0001-$0003 SCRATCH RAM * $0004-$0006 ADDEND RAM * $0008-$0009 CHIME TUNE DATA LOCATION * $000A SOUND QUEUE FLAG 00=CLEAR FF=SET * $000B NOT USED * $000C EXTRA BALLS WAITING * $000D REPLAY THRESHOLD PASSED COUNTER * $000E ADDEND MULTIPLIER * $000F-$0010 SAVE X FOR AUDIT * $0011 NOT USED * $0012 BONUS MULTIPLIER DURING BONUS COLLECT * $0013 CURRENT BALL IN PLAY * $0014 # OF PLAYERS IN GAME * $0015 CURRENTLY UP PLAYER * $0016 CONTINUOUSLY DECREMENTING REGISTER * $0017 SOLENOID DECAY TIMER * $0018 GENERAL PURPOSE TIMER * $0019 SCORE/SOUND QUEUE TIMER * $001A GENERAL PURPOSE TIMER * $001B GENERAL PURPOSE TIMER * $001C-$001D 16 BIT TIMER * $001E-$001F DROP TARGETS CALC. * $0020 MATCH # * $0021 SCORE FLAG !00=NO SCORE 00=SCORE * $0022 FLAG FOR SWITCH READ INTERRUPTED IN ZERO CROSS BY DISPLAY INTERRUPT * $0023 COIN ALTERNATOR * $0024 COIN ALTERNATOR * $0025 SELF TEST DEBOUNCE TIMER * $0026 SELF TEST PRESS FLAG * $0027 S33 PRESS FLAG * $0028 EXTRA BALL COUNTER * * $0031-$0032 GAME OVER COL0/COL1 SWITCH PRESERVATION * $0031-$0032 IN GAME TEMP X SAVE * $0035 10 POINT QUEUE * $0036 1K POINT QUEUE * $0037 10K POINT QUEUE * $0038 DISPLAY DIGIT IN SELF TEST * $003B X-Y-Z STANDUP COMPLETION STATUS * $003C INDEX IN SELF TEST * * $003E COL0 ACTION REGISTER * $003F COL1 ACTION REGISTER * $0040 COL2 ACTION REGISTER * $0041 COL3 ACTION REGISTER * $0042 COL4 ACTION REGISTER * * $0043 COL0 INITIAL REGISTER * $0044 COL1 INITIAL REGISTER * $0045 COL2 INITIAL REGISTER * $0046 COL3 INITIAL REGISTER * $0047 COL4 INITIAL REGISTER * * $0048 COL0 HISTORY REGISTER * $0049 COL1 HISTORY REGISTER * $004A COL2 HISTORY REGISTER * $004B COL3 HISTORY REGISTER * $004C COL4 HISTORY REGISTER * * $004D DIPS 1-8 REGISTER * $004E DIPS 9-16 REGISTER * $004F DIPS 17-24 REGISTER * $0050 DIPS 25-32 REGISTER * * $0051 100 POINT QUEUE * $0052-$007F STACK * * $0200-$020E LAMPS (HIGH NIBBLE ONLY) * $020F-$021D UNUSED * $021E-$0223 P1 DISPLAY * $0224-$0229 P2 DISPLAY * $022A-$022F P3 DISPLAY * $0230-$0235 P4 DISPLAY * $0236-$023B CREDIT/MATCH DISPLAY * $023C-$0259 SAVE AREA DURING ATTRACT FOR PLAYER SCORES * * $025A-$026F UNUSED * * $0270-$0271 SAVE BONUS AREA FOR 2X/5X COUNTDOWNS * $0272-$02BC UNUSED * * $02BD-$02C3 AUDIT 1 REPLAY 1 * $02C4-$02C9 AUDIT 2 REPLAY 2 * $02CA-$02CE AUDIT 3 REPLAY 3 * $02CF-$02D4 AUDIT 4 HSTD * $02D5-$02DA AUDIT 5 CREDITS ($2D5-$2D6 ONLY, $2D7-$2DA IGNORED) * $02DB-$02E0 AUDIT 6 # OF GAMES STARTED * $02E1-$02E6 AUDIT 7 # OF REPLAYS AWARDED * $02E7-$02EC AUDIT 8 # OF TIMES HSTD BEATEN * $02ED-$02F2 AUDIT 9 COIN CHUTE 2 * $02F3-$02F8 AUDIT 10 COIN CHUTE 1 * $02F9-$02FE AUDIT 11 COIN CHUTE 3 * $02FF UNUSED * LAMP MAP * * $200 * BONUS 2K $10 * BONUS 4K $20 * BONUS 6K $40 * BONUS 8K $80 * * $201 * BONUS 10K $10 * BONUS 20K $20 * N/U $40 * N/U $80 * * $202 * ARROW #1 (WF) * STAR #1 (DRAC) $10 * ARROW #2 (WF) * STAR #2 (DRAC) $20 * ARROW #3 (WF) * STAR #3 (DRAC) $40 * 10K ROLLOVER $80 * * $203 * N/U $10 * F (WF) * BAT #1 (DRAC) $20 * W (WF) * CAT #1 (DRAC) $40 * CENTER SAUC. SP (WF) * Y STANDUP SP (DRAC) $80 * * $204 * N/U $10 * Y (WF) * BAT #2 (DRAC) $20 * I (WF) * CAT #2 (DRAC) $40 * 5X BONUS $80 * * $205 * N/U $10 * R (WF) * BAT #3 (DRAC) $20 * L (WF) * CAT #3 (DRAC) $40 * DOUBLE BONUS $80 * * $206 * N/U $10 * E (WF) * BAT #4 (DRAC) $20 * D (WF) * CAT #4 (DRAC) $40 * SPINNER $80 * * $207 * 1 SAUCER (WF) * Y STANDUP (DRAC) $10 * 2 SAUCER (WF) * X STANDUP (DRAC) $20 * 3 SAUCER (WF) * Z STANDUP (DRAC) $40 * +4000 (SAUCER) $80 * * $208 * N/U -ALL- * * $209 * N/U -ALL- * * $20A * SHOOT AGAIN (PF) $10 * MATCH (BB) $20 * +4000 3 BANK $40 * +DOUBLE BONUS $80 * * $20B * N/U $10 * N/U $20 * LEFT INLANE SPECIAL $40 * RIGHT INLANE EXBALL $80 * * $020C * TILT $80 * GAME OVER $40 * HSTD $20 * BALL IN PLAY $10 * * $020D * # PLAYERS 1 $80 * # PLAYERS 2 $40 * # PLAYERS 3 $20 * # PLAYERS 4 $10 * * $020E * PLAYER 1 UP $80 * PLAYER 2 UP $40 * PLAYER 3 UP $20 * PLAYER 4 UP $10 * * CONSTANTS * * AUDITS AUDITBASE = $02B7 AUDIT1 = AUDITBASE+$6 ; replay 1 AUDIT2 = AUDIT1+$6 ; replay 2 AUDIT3 = AUDIT2+$6 ; replay 3 AUDIT4 = AUDIT3+$6 ; HSTD AUDIT5 = AUDIT4+$6 ; current credits AUDIT6 = AUDIT5+$6 ; # of games started AUDIT7 = AUDIT6+$6 ; # of replays AUDIT8 = AUDIT7+$6 ; # of times HSTD beat AUDIT9 = AUDIT8+$6 ; COIN chute 2 AUDIT10 = AUDIT9+$6 ; COIN chute 1 AUDIT11 = AUDIT10+$6 ; COIN chute 3 org $1000 * * SWITCH COLUMN 0 $3E/$43/$48 * L1000: dw OUTHOLE ; row 7 dw TILT ; row 6 dw CREDIT ; row 5 dw STARROLLOVER ; row 4 dw LEFTINLANE ; row 3 dw LEFTOUTLANE ; row 2 dw RIGHTINLANE ; row 1 dw RIGHTOUTLANE ; row 0 * * SWITCH COLUMN 1 $3F/$44/$49 * L1010: dw SLAM ; row 7 dw SPINNER ; row 6 dw DONOTHING ; row 5 dw WFSRINNERLANE ; row 4 dw DROP1UPPER ; row 3 dw COIN2 ; row 2 dw COIN1 ; row 1 dw COIN3 ; row 0 * * SWITCH COLUMN 2 $40/$45/$4A * L1020: dw YSTANDUP ; row 7 dw XSTANDUP ; row 6 dw ZSTANDUP ; row 5 dw DROP2LOWER ; row 4 dw DROP2UPPER ; row 3 dw REBOUND ; row 2 dw ADVBONUS1K ; row 1 dw ROLLOVERS ; row 0 * * SWITCH COLUMN 3 $41/$46/$4B * L1030: dw ROLLOVERSTAR ; row 7 dw DONOTHING ; row 6 dw DONOTHING ; row 5 dw DROP3LOWER ; row 4 dw DROP3UPPER ; row 3 dw WFSLINNERLANE ; row 2 dw DONOTHING ; row 1 dw DONOTHING ; row 0 * * SWITCH COLUMN 4 $42/$47/$4C * L1040: dw SAUCER ; row 7 dw LEFTSLING ; row 6 dw RIGHTSLING ; row 5 dw DROP1LOWER ; row 4 dw DROP4UPPER ; row 3 dw LEFTPOP ; row 2 dw RIGHTPOP ; row 1 dw BOTTOMPOP ; row 0 * * SOLENOID LIST * L1050: db $0A,$0B,$0C,$06,$0D,$08,$04,$07,$09,$0E,$05,$BF,$DF,$7F,$EF * * SWITCH DO NOTHING * DONOTHING: rts ; return * * START OF MAIN LOOP HOOK * L1060: jmp L1515 * * LAUNCH BALL VECTOR * L1063: jmp L14EA ; launch ball * * BONUS COUNTDOWN * L1066: jmp L145C L1069: jmp L1083 L106C: jmp L14FA * * FAST REACT SOLENOID VECTOR * L106F: jmp L1565 L1072: jmp L150D L1075: lda $50 ; dips 25-32 anda #$C0 ; dips 31-32 special award cmpa #$40 ; set to extra ball (31+) bne L1083 lda $4F ; dips 17-24 ora #$A0 ; auto set dips 24/22 ON (1 special, i.e. extra ball per ball) sta $4F L1083: bsr L1087 bra L10B8 L1087: ldb $0A bne L1087 clra sta $0A sta $3B sta $28 coma sta $21 sta $020B ; blanks inlanes ldx #$0209 L109B: sta 0,x ;blanks lamps from 209-200 dex cpx #$01FF bne L109B lda #$10 ;bonus 2k jsr LAMPON lda #$86 ;SPINNER jsr LAMPON lda #$12 ;arrow #1 (wf) jsr LAMPON lda #$CA ;+4000 3 bank (wf), +double bonus jsr LAMPOFF rts L10B8: lda #$CC ;tilt/game over lamps jsr LAMPOFF bsr L10E3 bsr L10CA bsr L1126 bsr L10EE lda #$BF ;flipper relay jmp CONTSOLON L10CA: ;SAUCER ldx #$0042 ;checks SAUCER ($47,bit $80) lda #$08 ;SAUCER solenoid ldb 5,x andb #$80 L10D3: beq L10E2 ldb #$20 jsr SETDELAY jsr PULSESOLENOID jsr SLIGHTDELAY stb 0,x ;leaves SAUCER showing as 'closed' to avoid double firing L10E2: rts L10E3: ;10 point ROLLOVERS/10 point+change ldx #$0040 lda #$07 ldb 5,x andb #$E0 bra L10D3 L10EE: ;3 bank drops down check ldx #$10EF ;pattern to check, bit $10, $ef switch preservation mask stx $1E lda #$04 ;3 bank solenoid ldx #$0040 stx $31 L10FA: ldb 5,x andb $1E ;holding bit to check bne L1107 inx cpx #$0043 bne L10FA rts L1107: jsr PULSESOLENOID lda #$0E ;longer activation for drop RESETs sta $17 ;solenoid delay timer ldx $31 L1110: ;sets switches using preservation mask to prevent scoring (they clear auto. after debouncing) lda 0,x anda $1F sta 0,x inx cpx #$0043 bne L1110 ldb #$10 ;sets delay for switches to clear jmp SETDELAY WFSLINNERLANE: ;unique to Wild Fyre, not in dracula lda #$25 ;score 500 jsr L1764 ; add to score queue vector L1126: ;4 bank drops down check ldx #$08F7 ;pattern to check, bit $08, $f7 switch preservation mask stx $1E lda #$09 ;4 bank solenoid ldx #$003F ;start with col1 stx $31 bra L10FA ;reuses code from 3 bank check LEFTPOP: RIGHTPOP: BOTTOMPOP: lda #$21 ;score 100 (5 ball) ldb $4D ;dips 1-8 andb #$40 ;dip 7 3/5 ball bne L113E ;set to 5 ball lda #$41 ;score 1000 (3 ball) L113E: jmp L1764 ;add to score queue vector ;determine if all drops are down ;expects $1e-$1f to contain conditions ;$1e is drop row mask ($10 for 3 bank, $08 for 4 bank) ;expects $31-$32 to contain switch column base address to start checking ;a is # of drops L1141: clra L1142: ldb 5,x ;load initial switch column register andb $1E ;holds mask for row beq L1149 inca ;found a drop down L1149: inx cpx #$0043 ;keep checking through "col5" bne L1142 ;check next row cmpa $1F ;a holds # of drops down, $1f holds # of drop for entire bank down bne L1162 ;whole bank is not down clra ;RESET # of drops down ldx $31 ;switch col to start checking L1156: ldb 0,x ;switch col action register andb $1E aba inx cpx #$0043 bne L1156 aba L1162: rts DROP1LOWER: DROP2LOWER: DROP3LOWER: ldx #$1003 ;mask for drop row, # of drops in bank stx $1E ldx #$0040 ;switch col to start checking rows at stx $31 bsr L1141 ;determine if drop bank complete bne L11B3 ;not complete, just score target lda $020A bita #$40 ;lit for +4000? beq L11AA tsta bpl L118D lda #$8A ;+double bonus lamp jsr LAMPON lda #$25 ;score 500 jsr L1764 ; add to score queue vector lda #$43 ;score 3k L1187: jsr L1764 ; add to score queue vector jmp L10EE L118D: lda #$8A ;+double bonus jsr LAMPOFF lda $0204 ;5x bonus bpl L119C ;on lda #$85 ;double bonus jsr LAMPON L119C: lda #$4A ;+4k 3 bank jsr LAMPON lda #$25 ;score 500 jsr L1764 ; add to score queue vector lda #$43 ;score 3k bra L1187 L11AA: lda #$25 ;score 500 jsr L1764 ;add to score queue vector lda #$47 ;score 7k bra L1187 L11B3: lda #$25 ;score 500 jmp L1764 ;add to score queue vector L11B8: ldx #$0804 ;row mask 08, # of drops 04 stx $1E ldx #$003F ;switch col to start checking stx $31 jsr L1141 ;see if 4 bank complete bne L1162 ;it isn't ldx #$0203 clra L11CB: ldb 0,x andb #$20 aba inx cpx #$0207 bne L11CB tab lda #$43 ;score 3k tstb bne L11DE lda #$45 ;score 5k L11DE: jsr L1764 ;add to score queue vector jmp L1126 YSTANDUP: lda #$17 ;y standup jsr LAMPON lda $0203 bmi L11F3 ;lit for special? jsr L1247 ;yes, pay special bra L1205 L11F3: lda $0207 bmi L120C ;y only scores (3k+4k) lamp on? anda #$70 ;look at x-y-z standups bne L1205 ;at least one is off lda $3B ;?? bne L1205 lda #$83 ;light y standup special/center SAUCER spec (wf) jsr LAMPON L1205: lda #$47 ;score 7k jsr L1764 ;add to score queue vector bra L1224 L120C: anda #$70 ;look at x-y-z standups bne L121F ;at least one is off ldb #$20 ;all on jsr SETDELAY lda #$77 ;y x z standups jsr LAMPOFF ;turn them off lda #$87 ;relights y scores 7k jsr LAMPON L121F: lda #$43 ;score 3k jsr L1764 ;add to score queue vector L1224: jmp L10E3 XSTANDUP: lda #$27 ;x standup jsr LAMPON bra L1233 ZSTANDUP: lda #$47 ;z standup jsr LAMPON L1233: lda $0207 bmi L120C ;+4000 on? anda #$70 ;x-y-z complete? bne L121F ;no lda $3B ;x-y-z status bne L121F ; lda #$83 ;light y special/ctr sauc sp (wf) jsr LAMPON bra L121F L1247: bsr L1254 lda $4F anda #$20 ;dip 22 side specials-1/unlimited beq L1280 lda #$83 ;y special/ctr sauc sp (wf) jmp LAMPOFF L1254: lda $4F anda #$20 ;dip 22 side specials-1/unlimited beq L1263 lda #$FF sta $3B lda #$83 ;y sp/ctr sauc sp (wf) jsr LAMPOFF L1263: lda $50 ;dips 25-32 bpl L126A ;dip 32 off jsr L1B1B ;pay free game L126A: lda $50 ;dips 25-32 asla ;dip 31 bmi L1273 ;on? bcc L127B ;was dip 32 on? bra L1280 L1273: ;pay extra ball jsr L1890 ;award extra ball lda #$AB ;extra ball off jmp LAMPOFF L127B: ;dip 31 off, 32 off lda #$8A ;special pays 100k jmp L1764 ;add to score queue vector L1280: rts DROP4UPPER: inca DROP3UPPER: inca DROP2UPPER: inca DROP1UPPER: L1284: inca ;a is zero from main loop L1285: ldx #$0203 L1288: ;set x index 203-207 to determine which cats and bats to light deca beq L128E inx bra L1288 L128E: lda 0,x anda #$60 stx $1E ldx #L12F8 jsr L1942 ldb 1,x ldx $1E lda 0,x anda #$80 aba sta 0,x stb $1E lda $020C anda #$40 beq L1280 clrb ldx #$0203 L12B2: orb 0,x andb #$60 inx cpx #$0207 bne L12B2 tstb bne L12CD lda $020B anda #$10 beq L12D7 lda #$4B ;inlane special jsr LAMPON bra L12D7 L12CD: lda $50 ;dips 25-32 anda #$01 ;dip 25, extra ball lit for 4 cats (off) 4 cats and bats (on) bne L12F0 andb #$40 bne L12F0 L12D7: lda $4E ;dips 17-24 anda #$20 ;dip 22, Y target special single (on) unlimited (off) beq L12F0 ;set to unlimited lda $020A anda #$10 beq L12F0 lda $020B anda #$20 beq L12F0 lda #$8B ;inlane extra ball jsr LAMPON L12F0: lda #$25 ;score 500 jsr L1764 ;add to score queue vector jmp L11B8 L12F8: ;data for cats and bats $60, cats, $20, bats, $0 both db $60,$20,$20,$00,$00,$00 WFSRINNERLANE: ;unique to wild fyre, not in dracula bsr addbonus bsr addbonus lda $50 ;dips 25-32 anda #$02 ;dip 26, # of advances 2 (off), 3 (on) beq L130A bsr addbonus L130A: lda #$25 ;score 500 jmp L1764 ;add to score queue vector LEFTINLANE: lda $020B anda #$40 ;inlane special lit? bne L1327 ;no jsr L1263 ;pay special lda $4F ;dips 17-24 bpl L1327 ;dip 24, bottom lane special - off unlimited, on 1 per ball lda #$4B ;left inlane special jsr LAMPOFF lda #$1B ;?? (not on WF) jsr LAMPON L1327: lda #$25 ;score 500 jmp L1764 ;add to score queue vector RIGHTINLANE: lda $020B anda #$80 ;extra ball lit? bne L1327 ;no, just pay 500 points lda #$8B ;yes, turn extra ball when lit off jsr LAMPOFF jsr L1890 ;award extra ball lda #$45 ;score 5k jmp L1764 ;add to score queue vector LEFTOUTLANE: RIGHTOUTLANE: lda #$43 ;score 3k jsr L1764 ;add to score queue vector clrb ldx #$0203 L1349: lda 0,x anda #$40 ;w (wf), i (wf), d (wf) bne L1355 stx $1E bsr addbonus ldx $1E L1355: lda 0,x anda #$20 ;f (wf), y (wf), e (wf) bne L1361 stx $1E bsr addbonus ldx $1E L1361: inx cpx #$0207 bne L1349 rts addbonus: jsr ACTIVEGAME bne L137A lda $0201 anda #$20 ;lit for 20k already? (maxed) beq L137A ;yes, do not increase ldx #L17D2 ;add bonus sound jsr ADD2SOUNDQ L137A: ldx #L13A3 ;bonus lamp data lda $0200 anda #$F0 ;bonus 2k, 4k, 6k, 8k lamps ldb $0201 andb #$30 ;bonus 10k, 20k lamps lsrb lsrb ;move status of 10k/20k over aba ;calculates bonus steps jsr L1942 ;set x index based on # of bonus steps in a ldb 1,x stb $0200 aslb aslb stb $0201 lda #$86 ;SPINNER andb #$04 ;SPINNER on at 2k,8k,14k,20k beq L13A0 jmp LAMPON L13A0: jmp LAMPOFF L13A3: ;bonus lamp data - high nibble $200, low nibble $201 + 2x right shift db $EC,$DC,$DC,$BC,$BC,$7D,$7C,$F8,$F8 db $E8,$E8,$D9,$D8,$B8,$B8,$78,$78 * * BONUS LAMP DATA * L13B4: db $F5,$F4,$F5 ; LEFTSLING: RIGHTSLING: REBOUND: ldx #$204 lda $13 ;ball in play ldb $4D ;dips 1-8 aslb ;dip 7, 3 (off) 5 (on) balls per game bmi L13C5 ;set to 5 balls ldb #$03 ;3 balls bra L13C7 L13C5: ldb #$05 ;5 balls L13C7: cba ;on last ball? bcs L13DE ;no lda 1,x bpl L13D2 ;look at $205/$80 lda 0,x bmi L13DE L13D2: lda 1,x eora #$80 sta 1,x lda 0,x eora #$80 sta 0,x L13DE: lda $50 ;dips 25-32 anda #$04 ;dip 27, alternate extra ball (on/off) beq L13F3 ;do not alternate lda $020B tab anda #$A0 cmpa #$A0 beq L13F3 eorb #$A0 stb $020B L13F3: lda #$11 ;score 10 jmp L1764 ;add to score queue vector ADVBONUS1K: L13F8: lda #$41 ;score 1k L13FA: jsr L1764 ;add to score queue vector jmp addbonus ROLLOVERS: lda #$11 ;score 10 bra L13FA ROLLOVERSTAR: lda $0202 bmi L1418 lda #$82 ;10k r/o (wF) jsr LAMPOFF lda #$12 ;bonus 10k jsr LAMPON lda #$81 ;score 10k jmp L1764 ;add to score queue vector L1418: bsr L1432 lda #$41 ;score 1000 jmp L1764 ;add to score queue vector SPINNER: lda #$21 ;scores 100 ldb $0206 ;lit for 1k? bmi L1428 ;no lda #$41 ;yes, score 1000 L1428: jmp ADD2SCOREQ ;score directly (?) STARROLLOVER: bsr L1432 lda #$41 ;score 1000 jmp L1764 ;add to score queue vector L1432: lda $0202 anda #$F0 ldx #L144F jsr L1942 lda 1,x sta $0202 bmi L144E lda $0204 ;5x bonus bpl L144E lda #$85 ;double bonus jsr LAMPON L144E: rts L144F: ;rotating values for arrows (wf), bonus stars (drac) db $E0,$D0,$D0,$B0,$B0,$70,$70,$70 SAUCER: bsr L145C jmp L10CA * * COLLECT BONUS * L145C: ldx #$0200 ; start at lamp base ldb 0,x ; get first bonus lamp nibble 2k-8k, 2k increments stb $70,x ; save ldb 1,x ; get second bonus lamp nibble 10k-20k stb $71,x ; save lda #$01 ; initial bonus 1x ldb $0205 ; check for double bonus lit bmi L146F ; not lit inca ; yes, double lit, increase to 2x L146F: ldb $0204 ; check for 5x bonus lit bmi L1476 ; not lit adda #$04 ; increase bonus from 1x to 5x - double AND 5x can't be lit simultaneously L1476: sta $12 ; save multiplier * * CHECK FOR SLAM DURING BONUS COUNTDOWN * L1478: lda $3F ; get switch column 1 bpl L147D ; not slammed, branch swi ; SLAM tilted during bonus collect, use software interrupt to reboot * * CHECK FOR TILT DURING BONUS COUNTDOWN * L147D: lda $3E ; get switch column 0 asla ; shift to look at tilt switch bpl L1485 ; not tilted, branch jsr L1D60 ; tilt during bonus collect, process L1485: lda $12 ; bonus multiplier beq L14AE ; all bonus collected bsr L14B3 ; restore saved bonus * * ACTUALLY SCORE THE BONUS * L148B: jsr ACTIVEGAME ; check if in an active game bne L149B ; not active/tilted, branch inc $0036 ; add bonus step to 1k queue inc $0036 ; each step is worth 2k jsr L176A ; service score queue bra L14A0 ; decrease bonus L149B: ldb #$0A ; setup delay $0A jsr SETDELAY ; do it L14A0: bsr L14BF ; decrease bonus bne L148B ; more bonus to countdown dec $0012 ; multiplier ldb #$30 ; setup delay between multipliers jsr SETDELAY ; do it bra L1478 ; count down the next multiplier's bonus L14AE: ldb #$10 jmp SETDELAY * * RESTORE SAVED BONUS * L14B3: ldx #$0200 ; setup baes ldb $70,x ; get saved 2k-8k stb 0,x ; restore ldb $71,x ; get saved 10k-20k stb 1,x ; restore rts ; return * * DECREASE BONUS * L14BF: lda $0200 ; get 2k-8k nibble anda #$F0 ; clear lower nibble ldb $0201 ; get 10k-20k nibble andb #$30 ; isolate bonus lsrb lsrb ; shift twice to put in one byte instead of two nibbles aba ; combine into a byte cmpa #$EC ; bonus lit 4k-6k-8k-10k-20k, 2k unlit? beq L14E9 ; yes, branch to return ldx #L13B4 L14D3: ldb 0,x andb #$FC cba beq L14DE dex dex bra L14D3 L14DE: dex ldb 0,x ; get bonus lamps stb $0200 ; save 2k-8k nibble aslb aslb ; get the decade lamps into the upper nibble stb $0201 ; save 10k-20k nibble L14E9: rts ; return * * LAUNCH BALL * L14EA: lda $43 ; get switch column 0 anda #$BF ; clear tilt sta $43 ; save switch column 0 ldb #$30 ; setup delay between tilt bob clear and ball launch jsr SETDELAY ; wait lda #$06 ; outhole solenoid jsr PULSESOLENOID ; fire it L14FA: ldb #$30 ; setup delay jsr SETDELAY ; wait lda $3E ; switch column 0 action register anda #$7F ; clear outhole sta $3E ; save switch column 0 action register lda $43 anda #$7F ; clear outhole sta $43 rts ; return rts ; spurious return L150D: ldb #$20 jsr SETDELAY jsr L1087 L1515: jsr ACTIVEGAME ; return if not in an active game beq L1520 jsr L10E3 jsr L10CA L1520: lda $020C asla bmi L1564 ; branch to return lda $18 bne L1564 ; branch to return lda $0C cmpa #$21 beq L155C inca cmpa #$09 bpl L1544 deca anda #$03 inca jsr L1285 L153C: inc $000C ; increment extra balls waiting * * DELAY 25 * L153F: ldb #$25 ; setup delay stb $18 ; save general delay timer rts ; return L1544: cmpa #$12 bpl L1553 cmpa #$0C bne L153C lda #$8B ; inlane extra ball jsr LAMPON ; lamp on bra L153C L1553: cmpa #$1A bpl L153C jsr L1432 bra L153C L155C: jsr L1087 clr $000C ; clear extra balls waiting bra L153F L1564: rts ; return * * FAST REACT SOLENOIDS * L1565: lda $47 eora $4C anda $47 asla bpl L1572 lda #$0E ; left sling bra L1597 L1572: asla bpl L1579 lda #$0D ; right sling bra L1597 L1579: asla asla ; skip drops asla bpl L1584 lda #$0A ; left pop bsr L1597 ; fire solenoid bra L159A ; branch to do fancy sound effect L1584: asla bpl L158D lda #$0B ; right pop bsr L1597 ; fire solenoid bra L159A ; branch to do fancy sound effect L158D: asla bpl L1596 ; no switches closed, branch to return lda #$0C ; bottom pop bsr L1597 ; fire solenoid bra L159A ; branch to do fancy sound effect L1596: rts ; return * * PULSE SOLENOID VECTOR * L1597: jmp PULSESOLENOID * * DO POP FANCY SOUND * L159A: ldx #L17D4 jsr L17BF lda $16 L15A2: ldb $16 cba beq L15A2 rts * * FILLER & CHECKSUM * db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$65 * * RESET * RESET: sei ; prevent interrupts lds #$007F ; set stack clra ; setup clear sta $A0 ; mute soundboard coma ; flip $00-$FF sta $C0 ; mute soundboard lda #$30 ; setup led off sta $91 ; save in PIA ldx #$55F0 ; delay L15D1: dex ; delay-- bne L15D1 ; not done, keep going * * ROM CHECKSUM * clra ; start checksum at 0 ldx #$1000 ; start with u2 L15D8: adda 0,x ; running total, no carries inx ; next cpx #$2000 ; done? bne L15D8 ; no, keep going tsta ; test checksum L15E1: bne L15E1 ; checksum doesn't sum to 0, hang bsr L162C ; flash led ! * * U7 6810 RAM TEST * ldx #$0000 ; start L15E8: lda #$01 ; test byte L15EA: sta 0,x ; save cmpa 0,x ; match? L15EE: bne L15EE ; no match, u7 bad, hang inca ; next test byte cmpa #$01 ; did all $FF patterns for this byte? bne L15EA ; no, keep going inx ; move to next byte cpx #$0080 ; done? bne L15E8 ; no bsr L162C ; flash led !! * * U8 5101 TEST - ONLY UPPER NIBBLE * ldx #$0200 ; start L1600: ldb 0,x ; get current value pshb ; use stack to save 5101 values clra ; test byte L1604: sta 0,x ; save tab ; transfer eorb 0,x ; flip andb #$F0 ; clear L160B: bne L160B ; any nibble that's not 00 = 5101 bad adda #$10 ; next test nibble bne L1604 ; not done, keep going pulb ; restore original byte stb 0,x ; resave inx ; move to next nibble cpx #$0300 ; done? bne L1600 ; no bsr L162C ; flash led !!! * * U10 6821 PIA TEST * ldx #$008B ; base address of U10 bsr L1641 ; PIA test bsr L162C ; flash led !!!! * * U11 6821 PIA TEST * ldx #$0093 ; base address of U11 bsr L1641 ; PIA test bsr L162C ; flash led !!!!! bra L1676 ; continue bootup * * FLASH LED * L162C: lda #$38 ; led on sta $91 ; save in PIA ldx #$7530 ; delay L1633: dex ; delay-- bne L1633 ; not done, keep going lda #$30 ; led off sta $91 ; save in PIA ldx #$55F0 ; delay L163D: dex ; delay-- bne L163D ; not done, keep going rts ; return * * PIA TEST * EXPECTS BASE ADDRESS OF PIA IN X * L1641: bsr L1643 ; do first half L1643: ; do second half lda #$31 ; bsr L165C ; subtest lda #$39 bsr L165C dex bsr L1666 inx lda #$35 bsr L165C lda #$3D bsr L165C dex bsr L1666 dex rts ; return * * PIA SUB-TESTS * L165C: sta 0,x ldb 0,x andb #$3F cba L1663: bne L1663 ; bad PIA, hang rts ; return L1666: clra L1667: sta 0,x ldb #$03 L166B: decb bne L166B cmpa 0,x L1670: bne L1670 ; bad PIA, hang inca bne L1667 ; not done, keep going rts ; return * * BOOTUP CONTINUES * * INTERRUPT TESTS * L1676: lda $90 * * DISPLAY * L1678: lda $91 ; get int bpl L1678 ; keep waiting bsr L162C ; flash led !!!!!! lda $8A * * ZERO CROSS * L1680: lda $8B ; get int bpl L1680 ; keep waiting bsr L162C ; flash led !!!!!!! * * STARTUP OK, INITIALIZE GAME * ldb #$FF lda #$38 sta $89 sta $8B sta $91 sta $93 stb $88 stb $90 stb $92 comb stb $8A lda #$34 sta $93 lda #$35 sta $89 sta $8B sta $91 lda #$FF sta $92 lda #$04 ; digit index sta $00 * * READ DIP SWITCHES 1-24 * lda #$20 ; set strobe/shift counter ldx #$004D ; set base address to store dips L16B4: sta $88 ; strobe ldb #$22 ; set propagation delay L16B8: decb ; delay-- bne L16B8 ; not done, keep going ldb $8A ; get dip results stb 0,x ; save inx ; next asla ; shift bne L16B4 ; not done, keep going sta $88 ; strobe 00 * * READ DIPS 25-32 * lda #$3D ; set strobe sta $8B ; strobe ldb #$22 ; set propagation delay L16CB: decb ; delay-- bne L16CB ; not done, keep going ldb $8A ; get dip results stb 0,x ; save * * SET ALL SWITCH REGISTERS CLOSED TO PREVENT ACTIVATION OF ANY CLOSED SWITCHES * ldx #$FFFF stx $43 stx $45 stx $47 stx $49 stx $4B cli ; allow interrupts jsr L18F8 ; setup memory and displays 4x00 jsr L1075 ; set dips virtually depending on other dips ldx #L17E2 ; startup tune jsr ADD2SOUNDQ ; queue tune jsr L1D25 ; sets initial attract timer, lamps * * MAIN LOOP * L16EF: jsr L1060 ; execute main loop hook * * WALK THROUGH ALL SWITCH COLUMN ACTION REGISTERS * * PROCESSES SWITCHES FROM ROWS 0-7 * LOSES MULTIPLE SWITCH CLOSURES PER COLUMN * clrb ; setup clear register lda $3E ; column 0 action register sta $31 ; save action register beq L1700 ; empty, branch ldx #L1000 ; column 0 vector table stb $3E ; clear entire action register bra L172C ; search for closed row * * COLUMN 1 * L1700: lda $3F ; get column 1 action register sta $32 ; save action register beq L170D ; empty, branch ldx #L1010 ; column 1 vector table stb $3F ; clear action register bra L172C ; search for closed row * * COLUMN 2 * L170D: lda $40 ; get column 2 action register beq L1718 ; empty, branch ldx #L1020 ; column 2 vector table stb $40 ; clear action register bra L172C ; search for closed row * * COLUMN 3 * L1718: lda $41 ; get column 3 action register beq L1723 ; empty, branch ldx #L1030 ; column 3 vector table stb $41 ; clear action register bra L172C ; search for closed row * * COLUMN 4 * L1723: lda $42 ; get column 4 action register beq L1748 ; empty, branch ldx #L1040 ; column 4 vector table stb $42 ; clear action register * * FIND CLOSED ROW, SET X TO SWITCH VECTOR * L172C: asla ; shift column bcs L1733 ; found closed row inx inx ; not closed, increase switch vector bra L172C ; keep searching * * PROCESS SWITCH VECTOR * * IGNORES VECTORS IN GAME OVER UNLESS COLUMNS 1 OR 2 * L1733: bsr ACTIVEGAME ; check if in an active game beq L1743 ; active game, branch * * IN GAME OVER OR TILTED * * CHECK IF COLUMNS 1, ROWS 0,1,2 OR COLUMM 2, ROWS 3,4 * lda $31 ; preserved rows from column 0, cached in game over mode anda #$E0 ; check if rows 0-2 bne L1743 ; yes, branch to process lda $32 ; preserved rows from column 1, cached in game over mode anda #$87 ; check if rows 3-4 beq L1748 ; no, branch to not process * * PROCESS SWITCH EVENT * L1743: clra ; reset A ldx 0,x ; get switch vector jsr 0,x ; process switch routine * * CONTINUE MAIN LOOP * L1748: bsr L1756 ; fast react switches in game bsr L17A8 ; service score queues jsr L189E ; attract mode servicing lda $26 ; self-test flag beq L16EF ; go back to main loop * * SELF TEST PRESSED * jmp L19E4 ; self test * * PROCESS FAST REACT SWITCHES * L1756: bsr ACTIVEGAME ; check if in an active game bne L1763 ; not active, branch to return jmp L106F ; fast react switch vector * * CHECK IF IN AN ACTIVE GAME * * RETURNS WITH Z FLAG SET IF IN AN ACTIVE, UNTILTED GAME * ACTIVEGAME: ldb $020C ; get lamp set 12 comb ; flip andb #$C0 ; isolate game over/tilt lamps L1763: rts ; return * * ADD TO SCORE QUEUE VECTOR, THEN SCORE * L1764: bsr ADD2SCOREQ bra L176A L1768: bsr L17A8 ; service score queues L176A: ldb #$07 bsr L177B ;sets a slight delay between scoring ldx $35 ;checks 10,1k score queues bne L1768 lda $37 ;checks 10k score queue bne L1768 lda $51 ;check 100 score queue bne L1768 rts L177B: stb $18 L177D: bsr L1756 ldb $18 bne L177D rts * * ADD CONTENTS OF A TO SCORE QUEUE * * A UPPER NIBBLE IS PLACE TO ADD * A LOWER NIBBLE IS # OF STEPS TO ADD (MAX 15) * ADD2SCOREQ: tab ; put in B for steps anda #$0F ; isolate steps * * TEST 10K QUEUE * tstb ; test if 10k bpl L1790 ; not 10k queue, branch * * INCREASE 10K QUEUE * ldb $37 ; get 10k queue aba ; add steps sta $37 ; save 10k queue rts ; return * * TEST 1K QUEUE * L1790: aslb ; shift place bpl L1799 ; not 1k queue, branch * * INCREASE 1K QUEUE * ldb $36 ; get 1k queue aba ; add steps sta $36 ; save 1k queue rts ; return * * TEST 100 QUEUE * L1799: aslb ; shift place bpl L17A2 ; not 100 queue, branch to assume 10 queue * * INCREASE 100 QUEUE * ldb $51 ; get 100 queue aba ; add steps sta $51 ; save 100 queue rts ; return * * INCREASE 10 QUEUE * L17A2: ldb $35 ; get 10 queue aba ; add steps sta $35 ; save 10 queue rts ; return * * PROCESS SCORE QUEUES * L17A8: lda $1B ; get ?? timer ora $19 ; add in score timer bne L17BB ; currently scoring/??, branch bsr ACTIVEGAME ; see if in an active game beq ACTUALLYSCORE ; in active game, branch * * GAME OVER OR TILTED * CLEAR ALL SCORE QUEUES * clra ; setup clear sta $35 ; clear 10 sta $51 ; clear 100 sta $36 ; clear 1k sta $37 ; clear 10k L17BB: rts ; return * * ADD SOUND TUNE IN X TO SOUND QUEUE * ADD2SOUNDQ: jsr L106F ; processfast react switches L17BF: ldb $0A ; get sound flag bne L17BF ; set, wait for clear stx $08 ; save sound tune pointer lda #$FF ; set sound flag sta $0A ; save rts ; return * * 10 QUEUE SOUND * L17CA: db $01,$FF * * 100 QUEUE SOUND * L17CC: db $02,$FF * * 1K QUEUE SOUND * L17CE: db $04,$FF * * 10K QUEUE SOUND * L17D0: db $08,$FF * * * L17D2: db $10,$FF L17D4: db $20,$FF L17D6: db $08,$84,$FF L17D9: db $08,$04,$02,$81,$08,$04,$02,$81,$FF L17E2: ;bootup/gameover tune db $01,$02,$04,$88,$01,$02,$04,$88,$FF * * ADD SCORE QUEUES TO PLAYER SCORE * ACTUALLYSCORE: lda $35 ; get 10s queue beq L17FC ; empty, branch dec $0035 ; one less ldx #L17CA ; get 10s sound bsr ADD2SOUNDQ ; process sound ldx #$0010 ; score 10 bra L182D ; add contents of X to current player score * * ADD 100S QUEUE * L17FC: lda $51 ; get 100s queue beq L180D ; empty, branch dec $0051 ; one less ldx #L17CC ; get 100s sound bsr ADD2SOUNDQ ; process sound ldx #$0100 ; score 100 bra L182D ; add contents of X to current player score * * ADD 1K QUEUE * L180D: lda $36 ; get 1k queue beq L181E ; empty, branch dec $0036 ; one less ldx #L17CE ; get 1k sound bsr ADD2SOUNDQ ; process sound ldx #$0A00 ; score 1000 bra L182D ; add contents of X to current player score * * ADD 10K QUEUE * L181E: lda $37 ; get 10k queue beq L1884 ; empty, branch to return dec $0037 ; one less ldx #L17D0 ; get 10k sound bsr ADD2SOUNDQ ; process sound ldx #$A000 ; score 10k * * ADD CONTENTS OF X TO CURRENTLY UP PLAYER SCORE * L182D: clr $0004 ; clear highest addend score byte stx $05 ; save amount to add ldx $2D ; get currently up player score pointer jsr L196C ; copy and format 6 nvram nibbles in X to scratch ram $01-$03 lda $01 ; get the player score 100k-10k before adding byte psha ; save for replay score surpass check jsr L1B35 ; bcd add addend ram $04-$06 to scratch ram $01-$03 lda $01 ; get player score 100k-10k after adding psha ; save ldx $2D ; get currently up player score pointer jsr L194A ; format scratch ram $01-$03 into 6 nvram nibbles at X, blanking leading zeros lda #$0C ; setup score timer sta $19 ; save score timer lda $21 ; get score flag beq L1859 ; not set, branch * * * lda $020A ; get lamp set 10 bita #$10 ; see if extra ball lit bne L1859 ; no, branch ora #$10 ; extra ball was lit, clear sta $020A ; save lamp set 10 L1859: clra sta $24 sta $21 pula ; get player score 100k-10k after pulb ; get player score 100k-10k before cba ; compare beq L1884 ; same, branch to return * * PLAYER SCORE 100K-10K CHANGED CHECK FOR REPLAY * SCRATCH RAM $01-$03 CONTAINS PLAYER SCORE * jsr L1ACB ; copy scratch ram $01-$03 to addend ram $04-$06 clr $000D ; replays to be awarded ldx #AUDIT1 ; setup replay threshold 1 bsr L1878 ; check replay threshold 1 bsr L1878 ; check replay threshold 2 bsr L1878 ; check replay threshold 3 lda $0D ; check replay flag beq L1884 ; none to be awarded bra L1885 ; award replay(s) * * GET REPLAY THRESHOLD INTO SCRATCH RAM * COMPARE SCRATCH RAM TO ADDEND RAM * IF ADDEND RAM GREATER INCREASE REPLAY DUE COUNTER * L1878: jsr L196C ; copy and format 6 nvram nibbles in X to scratch ram $01-$03 lda $01 ; get player score 100k-10k cmpa $04 ; compare to replay score 100k-10k bne L1884 ; not equal, no replay due, branch inc $000D ; increase replays due L1884: rts ; return * * AWARD REPLAYS * L1885: lda $4D ; dips 1-8 anda #$20 ; dip 6, replay=on, extra ball=off bne L1898 ; award replay jsr ACTIVEGAME ; check if in an active game bne L1884 ; not in an active game, branch to return * * THRESHOLD AWARDS EXTRA BALL * L1890: inc $0028 ; increase extra balls due lda #$1A ; setup shoot again lamp jmp LAMPON ; lamp on & return * * THRESHOLD AWARDS REPLAY * L1898: jsr L1CB1 ; increase credit jmp L1B1B ; knock & return * * ATTRACT MODE * L189E: ldx $1C ; get 16 bit timer bmi L18B8 ; in a game, return beq L18B9 ; timer at zero, restore saved scores, RESET timer cpx #$0186 ; time to save scores? beq L18EA ; save scores cpx #$00D2 ; time to clear displays? beq L18CC ; clear displays, turn off hstd lamp cpx #$0096 ; time to display hstd? beq L18DC ; display hstd, turn on hstd lamp cpx #$003C ; time to clear displays? beq L18CC ; clear displays, turn off hstd lamp L18B8: rts ; return * * RESTORE SCORES TO DISPLAYS * RESET ATTRACT TIMER * L18B9: ldx #$021E ; setup destination L18BC: lda $1E,x ; source sta 0,x ; destination inx ; next cpx #$0236 ; done? bne L18BC ; no, keep going ldx #$0190 ; reset timer stx $1C ; save rts ; return * * CLEAR DISPLAYS * TURN OFF HSTD LAMP * L18CC: lda #$AA ; setup blank sta $01 sta $02 sta $03 ; save in scratch ram $01-$03 jsr L1993 ; contents of scratch ram $01-$03 to all 4 player displays lda #$2C ; setup hstd lamp jmp LAMPOFF ; lamp off & return * * HSTD TO ALL 4 PLAYER DISPLAYS * TURN ON HSTD LAMP * L18DC: lda #$2C ; setup hstd lamp jsr LAMPON ; lamp on ldx #AUDIT4 ; setup source as audit 4, hstd jsr L196C ; copy and format 6 nvram nibbles in X to scratch ram $01-$03 jmp L1993 ; contents of scratch ram $01-$03 to all 4 player displays & return * * SAVE PLAYER SCORES * L18EA: ldx #$021E ; setup source L18ED: lda 0,x ; source sta $1E,x ; destination inx ; next cpx #$0236 ; done? bne L18ED ; no, keep going rts ; return * * CLEAR RAM AND INIT DISPLAYS TO 4X00 * L18F8: ldx #$0015 ; start L18FB: clr 0,x ; clear dex ; next bne L18FB ; not done, keep going jsr L19FF ; clear nvram $0200-$02A0 sta $1C ; $FF from clear, makes 16 bit timer invalid (ingame) ldx #$021E ; player 1 score jsr L1991 ; setup 4 player scores for display jsr L1D46 ; setup # of players lamp jsr L1D4E jsr L1D72 ; display current ball in play bsr L1925 ; setup currently up player lamp jsr L1AB7 ; clear scratch ram $01-$03 ldx #$024E ; saved score area jsr L1996 ; copy contents of scratch ram to all 4 player score saved areas jmp L1CB1 * * ADD A PLAYER * L1922: inc $0014 ; increase # of players * * SHOW # OF PLAYERS IN GAME ON LAMPS * L1925: lda $14 ; get # of players ldx #$020D ; destination lamps L192A: stx $2F ; save ldx #L1938 ; get player lamps bsr L1942 ; set X to correct lamp pair lda 1,x ; get lamp mask ldx $2F ; get destination lamps sta 0,x ; save lamp L1937: rts ; return * * PLAYER LAMP DATA * L1938: db $00,$FF,$01,$EF,$02,$DF,$03,$BF,$04,$7F * * SET X TO MATCHING INDEX INTO PLAYER LAMP DATA * L1942: cmpa 0,x ; test against A beq L1937 ; X ok, branch to return inx inx ; next index bra L1942 ; keep searching * * FORMAT SCRATCH RAM $01-$03 INTO 6 NVRAM NIBBLES AND STORE AT X, BLANKING LEADING ZEROES * L194A: clrb ; flag to test for blank lda $01 ; 100k-10k bsr L1956 ; format for display lda $02 ; 1k-100 bsr L1956 ; format for display incb ; do not test for blank lda $03 ; 10-1 * * FORMAT FOR DISPLAY * L1956: bsr L195C ; do lower nibble first asla asla asla asla ; shift lower nibble to upper nibble * * TEST FOR LEADING ZERO, BLANK IF B=0, SAVE AT X * L195C: tstb ; test blanking flag bne L1968 ; do not test for leading zero, branch bita #$F0 ; test for zero beq L1966 ; zero, branch to blank incb ; not blank, set blank flag bra L1968 ; skip blaking L1966: ora #$F0 ; set blank L1968: sta 5,x ; save in reverse order at X dex ; next rts ; return * * COPY AND FORMAT 6 NVRAM NIBBLES IN X TO SCRATCH RAM $01-$03 * L196C: bsr L1979 ; get 2 nibbles sta $03 ; save 10-1 bsr L1979 ; get 2 nibbles sta $02 ; save 1k-100 bsr L1979 ; get 2 nibbles sta $01 ; save 100k-10k rts ; return * * GET NIBBLES, CHANGE NON-BCD TO ZERO * L1979: lda 0,x ; get nibble lsra lsra lsra lsra ; shift to lower cmpa #$09 ; valid bcd? bls L1984 ; yes, branch clra ; invalid bcd, make zero L1984: inx ; next ldb 0,x ; get nibble andb #$F0 ; clear lower cmpb #$90 ; valid bcd? bls L198E ; yes, branch clrb ; invalid bcd, make zero L198E: inx ; next aba ; combine nibbles into byte rts ; return * * SETUP PLAYER SCORES FOR DISPLAY * L1991: bsr L196C ; copy and format 6 nvram nibbles in X to scratch ram $01-$03 * * COPY CONTENTS OF SCRATCH RAM $01-$03 TO ALL 4 PLAYER DISPLAYS * L1993: ldx #$0230 L1996: bsr L194A ; format scratch ram $01-$03 into 6 nvram nibbles at X, blanking leading zeros bsr L194A ; format scratch ram $01-$03 into 6 nvram nibbles at X, blanking leading zeros bsr L194A ; format scratch ram $01-$03 into 6 nvram nibbles at X, blanking leading zeros bra L194A ; format scratch ram $01-$03 into 6 nvram nibbles at X, blanking leading zeros LAMPON: clc ; set function on bra L19A2 ; process LAMPOFF: sec ; set function off L19A2: ldx #$0200 ; lamp base tab ; put in B andb #$0F ; clear lamp, leave nibble offset * * FIND CORRECT NIBBLE TO UPDATE * L19A8: beq L19AE ; ok, branch inx ; next decb ; offset-- bra L19A8 ; keep going * * TEST FUNCTION * L19AE: bcc L19B4 ; set to turn lamp on, branch ora 0,x ; turn lamp bit off bra L19B7 ; branch to save lamp set * * TURN LAMP ON * L19B4: coma ; flip for mask anda 0,x ; clear from lamp nibble * * SAVE LAMP SET * L19B7: sta 0,x ; save lamp set rts ; return * * CONTINUOUS SOLENOID ON * CONTSOLON: anda $92 ; sink bra L19C1 ; branch to save * * CONTINUOUS SOLENOID OFF * CONTSOLOFF: coma ; flip ora $92 ; bring high * * SAVE SOLENOID REGISTER * L19C1: sta $92 ; save solenoid register rts ; return * * FIRE MOMENTARY SOLENOID * PULSESOLENOID: ldb #$34 tsta bpl L19CB orb #$08 L19CB: stb $93 anda #$0F ldb $92 andb #$F0 aba sta $92 ldb #$05 stb $17 rts * * SHORT DELAYS * DELAY TIMER DECAYS IN ZERO CROSS IRQ * SLIGHTDELAY: ldb #$03 ; delay factor SETDELAY: stb $18 ; save L19DF: ldb $18 ; delay bne L19DF ; keep delaying rts ; return * * SELF TEST * L19E4: clra sta $27 sta $26 sta $1E coma ; make 00-$FF sta $1C ; save in timer to prevent attract mode updates ldx #$2000 ; setup address for AID2 module (or SEI equivalent) stx $2B ; save vector * * LAMP TEST * L19F3: clra ; setup to light lamps ldx #$021D ; starting address bsr L1A04 ; save A in $0200-$021D (lights all lamps) bsr L1A16 ; self test pressed? beq L19F3 ; no, branch to continue lamp test bra L1A39 ; branch to display test * * INITIALIZE $0200-$02A0 WITH $FF * L19FF: lda #$FF ; nibble L1A01: ldx #$02A0 ; start L1A04: sta 0,x ; save dex ; next cpx #$01FF ; done? bne L1A04 ; no, keep going rts ; return * * INITIALIZE $0200-$02A0 WITH $FF AND SAFE SOLENOIDS * L1A0D: bsr L19FF ; init sta $92 ; safe rts ; return * * DELAY 30 * L1A12: ldb #$30 ; setup delay bra SETDELAY ; delay & return * * TEST SELF TEST PRESS * L1A16: bsr L1A12 ; delay stx $29 ; save X bsr L1A0D ; clear ram $0200-$02A0 and safe solenoids ldx $29 ; restore X L1A1E: bsr L1A24 bne L1A38 bsr L1A12 L1A24: stx $2F ; save X lda $27 ; get S33 flag beq L1A2E ; not pressed, branch * * S33 PRESSED * ldx $2B ; get AID2 vector jsr 0,x ; execute L1A2E: clra ; setup clear flags sta $27 ; clear S33 flag ldb $26 ; get self-test flag sta $26 ; clear self-test flag ldx $2F ; restore X tstb ; test self-test flag L1A38: rts ; return * * DISPLAY TEST * L1A39: lda $38 ; get digit adda #$10 ; next digit cmpa #$9F ; overflow? bls L1A42 ; no, branch clra ; reset digit to zero L1A42: sta $38 ; save digit bsr L1A01 ; save digit in $0200-$02A0 * * BLANK LAMPS * lda #$FF ; setup to blank lamps ldx #$021D ; start bsr L1A04 ; save A in $0200-$021D bsr L1A16 ; self test pressed? beq L1A39 ; no, continue display test * * SOLENOID TEST * clr $003C ; reset solenoid counter L1A54: bsr L1A5B beq L1A54 jmp L1B44 ; branch to switch test L1A5B: inc $003C ; next solenoid lda $3C ; get solenoid under test cmpa #$07 ; see if sound bpl L1A73 ; no, coil, branch * * TESTING FIRST SIX ARE SOUNDS * ldx #L17CA ; setup sound index, each sound tested is 2 bytes L1A67: deca ; adjust offset beq L1A6E ; X ok, branch inx inx ; move to next sound bra L1A67 ; keep going * * SEND SOUND TO SOUND BOARD * L1A6E: jsr ADD2SOUNDQ ; send sound in X bra L1A9A ; wait for sound to end * * TEST COIL IN A * L1A73: suba #$06 ; adjust offset tab ; put offset in B ldx #L1050-1 ; list of solenoids L1A79: inx ; index++ deca ; offset-- bne L1A79 ; not done, keep going * * X IS SET TO SOLENOID TO TEST * tba ; put solenoid offset in A cmpa #$0C ; is it momentary or continuous? bpl L1A8D ; continuous, branch * * PULSE SOLENOID * lda 0,x ; get solenoid to pulse jsr PULSESOLENOID ; do so lda #$0E ; make dwell time longer sta $17 ; save solenoid timer bra L1A9A * * CONTINUOUS SOLENOID TEST * L1A8D: cmpa #$0E ; done? bne L1A96 ; no, branch clr $003C ; reset solenoid index bra L1A5B ; continue solenoid test L1A96: lda 0,x ; get continuous solenoid sta $92 ; save directly - also turns off the previous solenoid * * SOUND TIMER * L1A9A: lda $1E ; get flag bne L1AA0 ; ok to proceed bsr L1AA4 ; put solenoid # on all 4 player displays * * CHECK FOR TEST ADVANCE * L1AA0: jsr L1A16 ; self test pressed? rts ; return * * PUT BCD # ON PLAYER DISPLAYS * L1AA4: stx $33 ; save X lda $3C ; get solenoid # sta $0E ; save on ball in play bsr L1AB7 ; clear scratch ram $01-$03 inc $0003 ; increase bsr L1ABF ; BCD add one to contents of scratch ram jsr L1993 ; contents of scratch ram $01-$03 to all 4 player displays ldx $33 ; restore X rts ; return * * CLEAR SCRATCH RAM $01-$03 * L1AB7: clra ; zero sta $01 ; clear sta $02 ; clear sta $03 ; clear rts ; return * * BCD ADD 1 TO CONTENTS OF SCRATCH RAM * L1ABF: bsr L1ACB ; copy scratch ram $01-$03 to addend ram $04-$06 bsr L1AB7 ; clear scratch ram $01-$03 L1AC3: bsr L1B35 ; bcd add addend ram $04-$06 to scratch ram $01-$03 dec $000E ; multiplier bne L1AC3 ; not done, keep going rts ; return * * COPY SCRATCH RAM $01-$03 TO ADDEND RAM $04-$06 * L1ACB: ldx $01 ; first word stx $04 ; save lda $03 ; last byte sta $06 ; save rts ; return * * SUBTRACT ADDEND RAM $04-$06 FROM SCRATCH RAM $01-$03 * L1AD4: ldx #$0003 ; set index L1AD7: lda #$99 ; setup subtract 1 suba 3,x ; first byte sta 3,x ; save dex ; move index bne L1AD7 ; not done, keep going sec ; set borrow bra L1B36 ; do 2's complement * * HSTD BEATEN * L1AE3: stx $29 ; save X jsr L196C ; copy and format 6 nvram nibbles in X to scratch ram $01-$03 bsr L1ACB ; copy scratch ram $01-$03 to addend ram $04-$06 ldx #AUDIT4 ; get hstd jsr L196C ; copy and format 6 nvram nibbles in X to scratch ram $01-$03 bsr L1AD4 ; subtract addend ram $04-$06 from scratch ram $01-$03 bcs L1B16 ldx $29 ; restore X jsr L196C ; copy and format 6 nvram nibbles in X to scratch ram $01-$03 ldx #AUDIT4 ; get hstd jsr L194A ; format scratch ram $01-$03 into 6 nvram nibbles at X, blanking leading zeros ldx #AUDIT8 jsr L1C2A ; advance audit in X lda $4E ; get dips 9-16 anda #$C0 ; isolate dips 15/16 hstd awards psha ; save A bpl L1B10 ; dip 16 off, branch * * DIP 16 ON, AWARD MINIMUM OF 2 CREDITS * bsr L1B1B ; award credit bsr L1B1B ; award credit L1B10: pula ; restore dips 15/16 status asla ; shift bpl L1B16 ; dip 15 was off, no more credits bsr L1B1B ; dip 15 was on, award one more credit L1B16: ldx $29 ; restore X jmp L1C1C ; inx*6 & return * * AWARD CREDIT IF NOT MAX * L1B1B: lda $92 ; get solenoid register anda #$20 ; isolate coin lockout beq L1B22 ; on, max credits not reached, branch rts ; off, max credits reached, return * * FIRE KNOCKER FOR FREE GAME * L1B22: lda #$05 ; knocker jsr PULSESOLENOID ; fire knocker ldx #AUDIT7 ; setup audit 7, # of replays awarded jsr L1C2A ; advance audit in X jsr L1CAB lda #$10 ; setup delay jmp SETDELAY ; delay & return * * ADD ADDEND RAM $04-$06 TO SCRATCH RAM $01-$03, CORRECTING TO BCD * L1B35: clc * * BCD ADD SCRATCH RAM TO ADDEND RAM * L1B36: ldx #$0003 ; index L1B39: lda 0,x ; scratch adca 3,x ; addend daa ; correct sta 0,x ; save dex ; next bne L1B39 ; not done, keep going rts ; return * * SWITCH TEST * L1B44: clr $003C ; clear switch counter ldx #$0043 ; start with column 0 L1B4A: ldb #$08 ; # of rows lda 0,x ; get switch column L1B4E: inc $003C ; increase switch # lsra ; shift column, looking for first closed row bcs L1B62 ; found, branch to display * * NO CLOSED ROW YET * decb ; row-- bne L1B4E ; not done, keep going * * NO CLOSED SWITCHES IN THIS COLUMN * inx ; next column cpx #$0048 ; done? bne L1B4A ; no, keep going clr $0236 ; put a zero on the ball in play display to indicate no closed switches bra L1B65 ; check self-test press L1B62: jsr L1AA4 ; put contents of $3C corrected to BCD on player displays L1B65: jsr L1A16 ; self test pressed? beq L1B44 ; not pressed, branch to continue switch test * * DISPLAY ADJUSTMENTS/AUDITS * * SETUP * ldx #L1C11 ; setup clear routine for S33 press stx $2B ; save in vector jsr L1AB7 ; clear scratch ram $01-$03 ldx #$0236 ; use credit display as counter jsr L194A ; format scratch ram $01-$03 into 6 nvram nibbles at X, blanking leading zeros clr $0038 ; audit immutable flag 00=ok to change, !00=reset only ldx #AUDITBASE ; setup audit pointer stx $2D ; save audit pointer * * DISPLAY AUDIT LOOP * L1B80: ldx $2D ; get audit pointer jsr L1C1C ; inx*6 stx $2D ; save next audit pointer ldx #$0236 ; setup to display audit # jsr L1C2A ; advance audit in X lda $03 ; get audit # cmpa #$05 ; last mutable audit? bne L1B95 ; no sta $38 ; yes, make all following audits clear only L1B95: ldx $2D ; get audit pointer jsr L1991 ; copy contents of audit to display ram lda $38 ; get mutability flag bne L1BC2 ; set, no change possible * * AUDIT IS MUTABLE * L1B9E: lda $43 ; get switch column 0 anda #$20 ; isolate credit button beq L1BC2 ; not pressed, branch * * CREDIT BUTTON PRESSED TO ADVANCE AUDIT * ldx $2D ; get audit pointer jsr L196C ; copy and format 6 nvram nibbles in X to scratch ram $01-$03 ldx #$0100 ; setup to add 10K stx $04 ; save in addend ram clr $0006 ; clear the final byte bsr L1B35 ; bcd add addend ram $04-$06 to scratch ram $01-$03 ldx $2D ; get audit pointer jsr L194A ; format scratch ram $01-$03 into 6 nvram nibbles at X, blanking leading zeros ldx $2D ; get audit pointer jsr L1991 ; display on all 4 player displays jsr L1A12 ; delay between adds 30 ticks bra L1B9E ; branch to displaying/advancing audit if you are holding the credit button down * * AUDIT CONTINUED * L1BC2: jsr L1A1E ; self test pressed? beq L1B95 ; no, loop back to start of audit to keep displaying current audit * * SELF TEST PRESSED IN ADJUSTMENTS/AUDITS * ldx $2D ; get current audit cpx #AUDIT11 ; done? bne L1B80 ; no, branch back to advance to next audit * * END OF AUDITS * clrb ; setup counter ldx #$004D ; start with dips 1-8 L1BD2: lda 0,x ; get dip register bne L1BD7 ; some are on, branch incb ; count dip banks that are all off L1BD7: inx ; next cpx #$0051 ; done? bne L1BD2 ; no, keep going * * B CONTAINS COUNT OF DIPS BANKS THAT ARE ALL OFF * cmpb #$04 ; all off? bne L1C10 ; no, branch to reboot * * ALL 4 DIP BANKS ARE OFF, DO BURN IN TEST * lda #$FF sta $1E clr $003C clra L1BE9: ldx #$021D jsr L1A04 lda $38 adda #$10 cmpa #$9F bls L1BF8 clra L1BF8: sta $38 ldx #$02A0 L1BFD: sta 0,x dex cpx #$021D bne L1BFD jsr L1A5B ; test switch bne L1C10 ; pressed, branch to reboot lda $0200 coma bra L1BE9 L1C10: swi ; reboot * * CLEAR AUDIT * L1C11: jsr L1AB7 ; clear scratch ram $01-$03 jsr L1993 ; contents of scratch ram $01-$03 to all 4 player displays ldx $2D ; get current audit jmp L194A ; format scratch ram $01-$03 into 6 nvram nibbles at X, blanking leading zeros * * INX*6 * L1C1C: inx inx inx inx inx inx rts ; return * * SUBTRACT ONE FROM AUDIT IN X * L1C23: bsr L1C34 ; setup scratch & addend ram jsr L1AD4 ; subtract addend ram $04-$06 from scratch ram $01-$03 bra L1C2F ; branch to save * * ADD ONE TO AUDIT IN X * L1C2A: bsr L1C34 ; setup scratch & addend ram jsr L1B35 ; bcd add addend ram $04-$06 to scratch ram $01-$03 * * SAVE AUDIT * L1C2F: ldx $0F ; restore X jmp L194A ; format scratch ram $01-$03 into 6 nvram nibbles at X, blanking leading zeros * * SETUP SCRATCH RAM AS AUDIT CONTENTS * SETUP ADDEND RAM AS 1 * L1C34: stx $0F ; save X jsr L196C ; copy and format 6 nvram nibbles in X to scratch ram $01-$03 ldx #$0001 ; setup to add 1 stx $05 ; save clr $0004 ; ensure first byte in addend ram clear rts ; return * * SWITCH COIN2 * COIN2: ldx #AUDIT10 bsr L1C2A ; advance audit in X lda $50 ; dips 25-32 anda #$38 ; dips 28-30 lsra lsra lsra cmpa #$07 bne L1C54 lda #$08 L1C54: adda #$02 ldb #$C0 bra L1C6E * * SWITCH COIN1 * COIN1: ldx #AUDIT9 bsr L1C2A ; advance audit in X lda $4D ldb #$30 bra L1C6E * * SWITCH COIN3 * COIN3: ldx #AUDIT11 bsr L1C2A ; advance audit in X lda $4E ldb #$0F L1C6E: lsra anda #$0F bne L1C75 bra L1C95 L1C75: bcc L1C8C bitb $23 ; check coin alternator bne L1C87 orb $23 stb $23 ldx #L17D6 jmp ADD2SOUNDQ * * THIS COULD NEVER RUN! * jmp 0,x * * HANDLE COIN ALTERNATOR * L1C87: comb andb $23 stb $23 L1C8C: psha jsr L1C9C pula deca bne L1C8C rts L1C95: com $0024 bmi L1C9C bsr L1C9C L1C9C: lda $4D bmi L1CA5 ldx #L17D6 bra L1CA8 L1CA5: ldx #L17D9 L1CA8: jsr ADD2SOUNDQ L1CAB: ldx #AUDIT5 ; setup to add credit jsr L1C2A ; advance audit in X L1CB1: lda #$DF jsr CONTSOLON bsr L1CF0 ; returns current credits in A beq L1CCD ; no credits, branch * * CALCULATE MAX CREDITS * ldb $4F ; get dips 17-24 andb #$07 ; isolate dips 17-19, max credits incb ; add one for calc clra ; clear running total * * MULTIPLY DIP COUNTER * 5 TO GET MAX CREDITS * L1CC0: adda #$05 ; each step is 5 daa ; correct for humans decb ; counter-- bne L1CC0 ; not done, keep going psha ; save calculated max bsr L1CF0 ; get current credits in A pulb ; restore calculated max cba ; compare bcc L1CDF ; current > max, branch to coin lockout * * CURRENT CREDITS < MAX * L1CCD: lda $4F ; get dips 17-24 anda #$08 ; isolate dip 20, display credits bne L1CD8 ; yes ldx #$FFFF ; no, load blank mask bra L1CDB ; save in credit display L1CD8: ldx AUDIT5 ; get current credits * * POPULATE CREDIT DISPLAY * L1CDB: stx $0239 ; save rts ; return * * CREDITS >= MAX, HANDLE COIN LOCKOUT * L1CDF: stb $02D6 ; save msb of max as current credits aslb aslb aslb aslb ; shift stb AUDIT5 ; save lsb of max as current credits lda #$DF ; coin lockout jsr CONTSOLOFF ; turn it off bra L1CCD ; branch back to determine display * * RETURN CURRENT CREDITS IN A * L1CF0: ldx #AUDIT5 ; current credits jsr L196C ; copy and format 6 nvram nibbles in X to scratch ram $01-$03 lda $03 ; get combined credits rts ; return * * MATCH * L1CF9: lda $4F ; get dips 17-24 anda #$10 ; isolate dip 21, match beq L1D1C ; match off, branch lda $20 ; get match # sta $0237 ; save msb of match on display clr $0236 ; lsb of match is always zero lda #$9C ; ball in play, tilt lamps jsr LAMPOFF ; lamps off lda #$2A ; match lamp jsr LAMPON ; lamp on ldx #$021E ; setup player 1 score * * CHECK PLAYERS' MATCH * L1D14: jsr L1D2D ; check for match dec $0014 ; do next player bne L1D14 ; still going, loop * * GAME OVER * L1D1C: jsr L1D25 ldx #L17D9 jmp ADD2SOUNDQ L1D25: lda #$03 sta $1C lda #$4C bra L1D67 * * DETERMINE IF PLAYER IN X MATCHED * L1D2D: stx $29 ; save X, player score pointer lda 1,x ; get player 10's digit anda #$F0 ; clear trash ldb $0237 ; get match msb andb #$F0 ; clear trash cba ; match? bne L1D3E ; no, match jsr L1B1B ; yes, award credit L1D3E: ldx $29 ; restore X jmp L1C1C ; inx*6 & return L1D43: inc $0015 * * SETUP CURRENTLY UP PLAYER LAMP * L1D46: lda $15 ; get currently up player ldx #$020E ; set lamp index jmp L192A ; finish in player up routine * * SET X TO CURRENTLY UP PLAYER SCORE POINTER * L1D4E: ldx #$021E ; base lda $15 ; get currently up player beq L1D5D ; branch to save L1D55: deca ; currently up player-- beq L1D5D ; found, branch to save jsr L1C1C ; inx*6 bra L1D55 ; keep searching * * SAVE CURRENTLY UP PLAYER SCORE POINTER * L1D5D: stx $2D ; save player score pointer rts ; return * * SWITCH TILT * L1D60: TILT: lda #$1A ; shoot again lamp jsr LAMPOFF ; remove shoot again on tilt (boooooooooo) lda #$8C ; setup tilt lamp L1D67: jsr LAMPON ; lamp on lda #$BF ; flipper relay jmp CONTSOLOFF ; kill flippers & return * * ADVANCE BALL IN PLAY * L1D6F: inc $0013 ; advance ball in play * * DISPLAY CURRENT BALL IN PLAY * L1D72: lda $13 ; get current ball in play asla asla asla asla ; shift for display sta $0236 ; save on display lda #$FF ; setup leading blank sta $0237 ; save on display lda #$1C ; setup ball in play lamp jmp LAMPON ; lamp on & return * * SWITCH OUTHOLE * OUTHOLE: lda $020C ; get lamp set 12 asla ; shift to test game over lamp bpl L1DCF ; game over lamp on, branch * * INGAME * ldb #$3C ; setup delay jsr SETDELAY ; delay lda $21 ; check score flag bne L1DBD ; no score, branch * * PROCESS OUTHOLE * jsr L1066 ; collect bonus due lda $020A ; get lamp set 10 anda #$10 ; isolate shoot again lamp beq L1DBD ; lit, branch * * BALL END * lda $15 ; get currently up player cmpa $14 ; compare to # of players in game bne L1DBA ; not last player, branch to advance player * * ADVANCE TO NEXT BALL * lda $13 ; get ball in play ldb $4D ; get dips 1-8 aslb ; shift for dip 7 bmi L1DAF ; set to 5 balls per game, branch ldb #$03 ; set to 3 balls per game bra L1DB1 ; branch to check balls vs. current ball L1DAF: ldb #$05 ; use 5 as balls per game * * CHECK IF LAST BALL * L1DB1: cba ; compare bcc L1DD2 ; branch to do game over ; jsr L1D6F ; advance ball in play db $bd dw L1D6F clr $0015 ; reset currently up player * * ADVANCE TO NEXT PLAYER * L1DBA: ; jsr L1D43 db $bd dw L1D43 L1DBD: jsr L1069 ; jsr L1D4E db $bd dw L1D4E lda $48 anda #$40 beq L1DCC ; jsr L1D60 db $bd dw L1D60 L1DCC: jmp L1063 ; launch ball vector L1DCF: jmp L106C * * GAME OVER * L1DD2: jsr L18EA jsr L1CF9 ldx #$021E jsr L1AE3 jsr L1AE3 jsr L1AE3 jsr L1AE3 ldb #$90 jsr SETDELAY jmp L1072 * * SWITCH CREDIT * CREDIT: jsr L1CF0 ; returns # of credits in a bne L1DF5 ; there are credits, branch * * NO CREDITS, RETURN * L1DF4: rts ; return * * CREDITS, CHECK FOR GAME IN PROGRESS * L1DF5: lda $020C ; get lamp set 12 asla ; shift game over lamp into sign bit bmi L1E0E ; game over off, game in progress - check if ok to add player * * GAME STATE = GAME OVER, START NEW GAME * L1DFB: jsr L18F8 jsr L1D6F ; advance ball in play jsr L1922 ; add player jsr L1D43 jsr L1075 bsr L1E1D bra L1DCC * * GAME STATE = IN PROGRESS, DETERMINE IF ABLE TO ADD PLAYER, OR JUST RESTART GAME * L1E0E: lda $13 ; get currently ball in play cmpa #$01 ; on ball 1? bhi L1DFB ; no, branch to start new game instead of adding a player * * IN GAME, BALL 1 * lda $14 ; get current # of players in game cmpa #$04 ; max? bcc L1DF4 ; yes, branch to return jsr L1922 ; add player L1E1D: ldx #AUDIT5 ; setup audit 5, current credits jsr L1C23 ; subract one from audit ldx #AUDIT6 ; setup audit 6, # of games started jsr L1C2A ; advance audit in X lda $4D ; get dips 1-8 bmi L1E32 ; dip 8 on, branch ldx #L17D6 ; dip 8 off, simple tones/no melody bra L1E35 ; branch * * DIP 8 ON, MELODY * L1E32: ldx #L17E2 ; L1E35: jsr ADD2SOUNDQ * * CREDIT BUTTON DEBOUNCE * lda $3E ; get switch action column 0 anda #$DF ; clear credit button sta $3E ; save switch action column 0 jmp L1CB1 ; increase credit * * IRQ * * DETERMINE WHAT GENERATED THE INTERRUPT * INTERRUPT: lda $91 bpl L1E4A lda $90 jmp L1E70 L1E4A: lda $8B bpl L1E58 ldb #$34 stb $8B lda $8A cli jmp L1F18 ; do zero cross L1E58: lda $89 bpl L1E6A ; spuriously generated interrupt, branch to reboot lda $25 bne L1E67 coma sta $26 lda #$48 sta $25 L1E67: lda $88 rti ; return from interrupt * * SWITCH SLAM * SLAM: L1E6A: swi ; reboot * * S33 (CLEAR) PRESS * NMI: lda #$FF ; set clear flag sta $27 ; save flag rti ; return from interrupt * * DISPLAY INTERRUPT * L1E70: lda $8B psha lda $88 psha lda $22 bne L1E87 coma ldb #$30 stb $8B sta $8A ldb #$34 stb $8B sta $8A L1E87: sta $88 ldb #$3C stb $8B ldb #$3D stb $91 ldb #$34 stb $8B ldb #$35 stb $91 lda $00 ldx #$021D L1E9E: inx asla bcc L1E9E lda #$35 sta $89 lda 0,x anda #$FE sta $88 ldb 6,x ora #$0F sta $88 orb #$0F andb #$FD stb $88 lda $c,x orb #$0F stb $88 ora #$0F anda #$FB sta $88 ldb $12,x ora #$0F sta $88 lda $00 sta $90 orb #$0F andb #$F7 stb $88 lda $18,x orb #$0F stb $88 ora #$0F sta $88 ldb $90 andb #$FE stb $90 orb #$01 stb $90 lda #$3D sta $89 lda $00 asla bcc L1EF3 lda #$04 ; reset digit index L1EF3: sta $00 ; save digit index pula sta $88 lda $22 ; get switch matrix read flag bne L1F0C ; not set, branch * * RESTROBE THE SWITCH MATRIX * ldb #$30 stb $8B sta $8A ldb #$34 stb $8B ldb #$16 ; setup propagation delay L1F08: decb ; delay-- bne L1F08 ; not done, keep going coma L1F0C: sta $8A pula tab lsra bcs L1F15 lda $8A L1F15: stb $8B rti ; return from interrupt * * ZERO CROSS INTERRUPT * L1F18: dec $0016 ; continuously decrementing timer * * SERVICE TIMERS $18-$1B * ldx #$0018 ; start with $18 L1F1E: tst 0,x ; timing? beq L1F24 ; no, branch dec 0,x ; yes, decrement L1F24: inx ; next cpx #$001C ; done? bne L1F1E ; no, keep going * * SERVICE 16 BIT TIMER $1C-$1D * ldx $1C ; get timer bmi L1F31 ; in game, branch beq L1F31 ; zero, branch dex ; timer-- L1F31: stx $1C ; save timer * * SERVICE MATCH * lda $20 ; get match adda #$10 ; add 10 cmpa #$A0 ; overflow? bcs L1F3C ; no, branch clra ; reset to 00 L1F3C: sta $20 ; save match * * SERVICE SOLENOID TIMER * lda $17 ; get solenoid timer beq L1F47 ; not timing, branch dec $0017 ; timer-- bra L1F4D ; skip safe * * SAFE ALL MOMENTARY SOLENOIDS * L1F47: lda #$0F ; setup to bring momentaries high ora $92 ; add to PIA solenoid register sta $92 ; save PIA solenoid register L1F4D: lda $25 ; get ?? timer beq L1F52 ; not timing, branch deca ; timer-- L1F52: sta $25 ; save * * SERVICE LAMPS * lda #$14 ; setup propagation delay L1F56: deca ; delay-- bne L1F56 ; not done, keep going ldx #$0200 ; lamp base address ldb #$F0 ; setup strobe/shift counter L1F5E: cli ; allow (other) interrupts stb $88 ; strobe lda #$3C sei ; prevent interrupts sta $8B lda #$34 sta $8B lda 0,x sta $88 inx incb bne L1F5E cli * * SETUP TO READ SWITCH MATRIX * FLAGS SET TO ALLOW DISPLAY MULTIPLEXING ON PIA U10 * clrb lda #$30 ; setup flag that switch matrix is about to be read sei ; prevent interrupts stb $22 sta $8B stb $8A ldb #$34 stb $8B cli ; allow interrupts * * READ SWITCH MATRIX * lda #$10 ; setup strobe/shift counter ldx #$0043 ; setup base address of switches bra L1FA6 L1F89: lsra ; shift strobe psha ; save dex ; next switch column lda $a,x eora $5,x anda $5,x ldb $5,x stb $a,x ldb #$0F ; setup propagation delay L1F98: decb ; delay-- bne L1F98 ; not done, keep going ldb $8A ; get switch column stb $5,x ; save anda $5,x ora $0,x sta $0,x pula ; restore switch strobe/shift counter L1FA6: sta $88 ; save switch strobe bne L1F89 ; still reading, branch * * DONE READING SWITCH MATRIX * coma ldb #$30 sei ; prevent interrupts stb $8B sta $8A sta $22 ldb #$35 lda $8A stb $8B * * PROCESS SOUND QUEUE * lda $0A ; get sound flag beq L1FEF ; no sound, branch to return from interrupt lda $1B ; get sound timer bne L1FEF ; still timing, branch to return from interrupt clra ; 00 sta $A0 ; save coma ; ->FF sta $C0 ; save ldx $08 ; get sound script cmpa 0,x ; ff=end of script beq L1FEC ; script over, branch lda 0,x ; get sound script byte ldb $4F ; get dips 17-24 andb #$40 ; isolate dip 23, computer type sounds bne L1FDB ; coma ; dip 23 off, flip sound byte sta $C0 bra L1FDD L1FDB: sta $A0 ; dip 23 on L1FDD: ldb #$0D ; default delay lda 0,x ; script beq L1FE5 ; delay ok, branch ldb #$10 ; script has a 00, slightly longer delay L1FE5: stb $1B ; save timer inx ; goose sound script pointer stx $08 ; save sound script pointer bra L1FEF ; return from interrupts L1FEC: clr $000A ; clear sound flag L1FEF: rti ; return from interrupt * WHAT'S YOUR VECTOR, VICTOR? org $1FF8 dw INTERRUPT ; irq dw RESET ; swi dw NMI ; nmi - test switch dw RESET ; reset vector