;stern 9 ball ;original software robert quinn ;stern electronics 1980 ;disassembly 2019-20 idleman ;enhancements 2019-20 shiftybitz ;if there are zero credits, game never boots up ;audit 2 and 3 can't adjust ;fixed both, error in labels! Bhi $ still in game! ;andrews. reported that after lock a ball, next ball drain causes repeated resets of 8 bank and top bank ;looks like it was trying to reset the single drop ;fixed, switch test cannot be used if you need to preserve accumulators ;crunchtest5, after borrowing johnp's playfield 1-19-20 test ok ;v06 added switch test for single drop so it might not need to be reset ==>TEST OK ; added free play, set with dip switch 19=on ==>NEEDS TEST IN GAME ;v07 debugging - lock 2f3 register tracks ins and outs, not the actual switch status ;v08 added the ever-popular spinner counter ==>NEEDS TEST IN GAME ; added a 'slow' switch matrix column for the trough switches ==>FAILED ;v09 added a master thread to decide if ball over (nothing added for locks, yet) ;v11 added tests on drop bank spotting for switches already closed/try a couple times, then move on ; andrews. reported when bootup with 2 in the lock won't start game or end ball. ;v12 added test for saucer at game over, will eject ; added test for correct trough switches for new game start (3 or 2+shooter) ; added test for drop targets down to reset at ball start ; added reset single drop at ball start (if never set, this could stay down and be stuck until power cycle) ; started roughing in 2x/3x score multiplier - set $33 to 2 for 3x, 1 for 2x, 00 for 1x ;v13 changed code for master switch thread - never made it into machine, no archive in BIN ;v14 party test 1-25-2020, master switch removed, in game for test ;notes: ; something went 'south' on the game, no longer can start a game. don't think it's the solenoid fuse. ;switchtest=1 ;troubleshooting switch test function ;v16 ;stock=1 if stock=0 andrew=1 ;Andrew's test results spigs=1 ;new scottspigs functions switch=1 ;test switch credit=1 ;free play fix=1 ;uncomment to add switch fix coding exp=1 ;uncomment for experimental crunching exp5=1 ;for crunchtest 5, change to exp after verification that it's working spinnerblit=1 ;spinner count on ball in play display ;matrix=1 ;new switch matrix processing for c4 ;multi=1 ;2x/3x scoring during multiball ;debug=1 ;debugger functions endif ;stock c512=1 ;uncomment for 512 rom VERSION=$18 ;include files if exp=0 include "..\common\stern13.asm" else include "..\common\stern13exp.asm" endif ;experimental ;macros check_switch macro switch db $59,switch endm clearb macro db $5a endm matchpattern macro lamp ;minimum two parameters + pattern if \0=3 db $5d,\1,\2,\3+$80 endif if \0=4 db $5d,\1,\2,\3,\4+$80 endif if \0=5 db $5d,\1,\2,\3,\4,\5+$80 endif if \0=6 db $5d,\1,\2,\3,\4,\5,\6+$80 endif if \0=7 db $5d,\1,\2,\3,\4,\5,\6,\7+$80 endif if \0=8 db $5d,\1,\2,\3,\4,\5,\6,\7,\8+$80 endif endm if c512=1 org $0000 db VERSION," STERN NINE BALL WEEBLY BOARD" endif ;c512 org $1000 ;stern pigs routines jump table L1000: dw L10B2 ;enable solenoid 0 if exp=0 dw L10B2 ;enable solenoid 1 dw L10B2 ;enable solenoid 2 dw L10B2 ;enable solenoid 3 dw L10B2 ;enable solenoid 4 dw L10B2 ;enable solenoid 5 dw L10B2 ;enable solenoid 6 dw L10B2 ;enable solenoid 7 dw L10B2 ;enable solenoid 8 dw L10B2 ;enable solenoid 9 dw L10B2 ;enable solenoid a dw L10B2 ;enable solenoid b dw L10B2 ;enable solenoid c dw L10B2 ;enable solenoid d dw L10B2 ;enable solenoid e dw L10B2 ;enable solenoid f dw L10C7 ;$10 cont_solenoid_on_7f (single drop) dw L10C7 ;$11 cont_solenoid_on_flipper dw L10C7 ;$12 cont_solenoid_on_coin dw L10C7 ;$13 cont_solenoid_on_ef dw L10DA ;$14 cont_solenoid_off_7f (single drop) dw L10DA ;$15 cont_solenoid_off_flipper dw L10DA ;$16 cont_solenoid_off_coin dw L10DA ;$17 cont_solenoid_off_ef else dw L10C7 ;$10-$13 continuous solenoid on dw L10DA ;$14-$17 continuous solenoid off endif ;exp dw L50A7 ;$18 set pigs multiprocessing flag dw L50AD ;$19 clear pigs multiprocessing flag dw L10EF ;$1a lamp in register B on dw L10EC ;$1b lamp on dw L1100 ;$1c lamp in register B off dw L10FD ;$1d lamp off dw L1111 ;$1e alternate lamp in register B dw L110E ;$1f alternate lamp dw L1125 ;$20 check lamp/flag in register B dw L1122 ;$21 check lamp/flag dw L111B ;$22 lamp in register B blink dw L1118 ;$23 lamp blink if exp=0 dw L118A ;$24 clear play flags else dw L15FF ;$51 clear variables endif ;exp dw L1199 ;$25 delay dw L11AA ;$26 switch dispatch dw L1236 ;$27 unconditional goto dw L125B ;$28 not equal, goto dw L1253 ;$29 equal, goto dw L1377 ;$2a save current player status dw L139C ;$2b restore current player status dw L1268 ;$2c unconditional gosub dw L128D ;$2d not equal, gosub dw L1284 ;$2e equal, gosub dw L1296 ;$2f unconditional return dw L12AE ;$30 not equal, return dw L12A7 ;$31 equal, return dw L12B5 ;$32 if tilted, return dw L12B9 ;$33 if game over, return dw L12C0 ;$34 return if not in active game dw L1317 ;$35 increment B dw L1321 ;$36 increment memory pointed to by X dw L131C ;$37 decrement B dw L1327 ;$38 decrement memory pointed to by X dw L132D ;$39 load B direct dw L1331 ;$3a load B from memory location dw L133A ;$3b store B in memory location dw L1340 ;$3c compare A to B dw L1345 ;$3d compare B to memory location in X dw L1353 ;$3e OR A,B dw L135F ;$3f EOR A,B dw L136B ;$40 AND A,B dw L1272 ;$41 dw L12C7 ;$42 dw L12C5 ;$43 push data silo dw L12D9 ;$44 pull data silo dw L1444 ;$45 update current player dw L142F ;$46 blank current player dw L143B ;$47 show current player dw L140D ;$48 update match dw L1422 ;$49 show ball in play dw L13C0 ;$4a show credits dw L14AE ;$4b show hstd dw L14DB ;$4c all displays valid dw L14E8 ;$4d all displays invalid dw L14ED ;$4e transfer scores to display dw L156A ;$4f score directly dw L126D ;$50 spawn thread dw L15FF ;$51 clear variables dw L12EF ;$52 bcd increase memory location dw L1303 ;$53 bcd decrease memory location dw L1E45 ;$54 reboot dw L1263 ;$55 gosub assembly routine dw L1616 ;$56 enqueue score dw L163C ;$57 play primary sound dw L1642 ;$58 play secondary sound if fix=1 dw test_switch ;$59 test for switch closed endif ;fix if exp=1 dw clearbee ;$5a - loadb $00 dw loadbz ;$5b - loadbmem from zero page (macro auto fills in) dw storebz ;$5c - storebmem to zero page (macro auto fills in) endif ;experimental swi if spigs=1 dw match_pattern ;$5d - match pattern in up to 7 bits endif ;spigs ;fire solenoid ;expects A to contain the solenoid address from table L10B2: if exp=0 lsra ;shift the doubled parameter back endif ;exp ldb #$F0 andb $0092 aba L10B8: ldb $004D ;solenoid pulse timer bne L10B8 ;some other solenoid is firing, wait dec $004D ;decrement the solenoid timer to prevent the irq from killing it on first run sta $0092 ;fire the solenoid jsr L1173 ;get the time parameter from script into A sta $004D ;save time parameter rts ;return ;function $10-$13 continuous solenoid on L10C7: ldb #$80 if exp=0 lsra ;shift the doubled parameter back endif ;exp anda #$03 beq L10D2 L10CE: lsrb deca bne L10CE L10D2: comb sei andb $0092 stb $0092 cli rts ;function $14-$17 continuous solenoids off L10DA: ldb #$80 if exp=0 lsra ;shift the doubled parameter back endif ;exp anda #$03 beq L10E5 L10E1: lsrb deca bne L10E1 L10E5: sei orb $0092 stb $0092 cli rts ;function $1b, lamp on L10EC: jsr L1180 ;function $1a, lamp in register B on L10EF: if exp=1 pshb ;save original B tstb ;see if the sign bit set indicating more to follow bpl nomorelampon ;this is the only or last lamp andb #$7f ;strip the more bit nomorelampon: endif ;exp bsr L113D ;make mask in A and set X to lamp column if fix=1 cmpb #$3b bhi L10F8 ;don't mess with the overflow area endif ;fix psha coma anda $11,x sta $11,x pula L10F8: ora $00,x sta $00,x if exp=1 pulb ;get original B back tstb ;see if sign bit set bmi L10EC ;there's more lamps, start with next script step endif ;exp rts ;function $1d, lamp off L10FD: jsr L1180 ;get next script command in B ;function $1c, lamp off in register B L1100: if exp=1 pshb ;save original B tstb ;see if the sign bit set indicating more to follow bpl nomorelampoff ;this is the only or last lamp andb #$7f ;strip the more bit nomorelampoff: endif ;exp bsr L113D L1102: coma ;flip for mask if fix=1 cmpb #$3b bhi L1109 endif ;fix psha ;save mask anda $11,x ;get blinker first sta $11,x ;save blinker pula ;get mask back L1109: anda $00,x ;get lamp sta $00,x ;save lamp if exp=1 pulb ;get original B back tstb ;see if sign bit set bmi L10FD ;there's more lamps, start with next script step endif ;exp rts ;return ;function $1f, alternate lamp L110E: if fix=0 GOSUB L1180 else bsr L1180 ;shave a byte endif ;fix ;function $1e, alternate lamp in register B L1111: bsr L113D ;make lamp mask and set X to lamp column eora $00,x ;flip lamp sta $00,x ;save lamp column rts ;return ;function $23, lamp blink L1118: if fix=0 GOSUB L1180 else bsr L1180 ;shave a byte endif ;fix ;function $22, lamp blink in register B L111B: if fix=1 cmpb #$3b ;top lamp bhi L1121 ;not a visible lamp, exit endif ;system bsr L113D ;make lamp mask and set X to lamp column ora $11,x ;set in blink matrix sta $11,x ;save blink column L1121: rts ;return ;function $21, check lamp value L1122: if fix=0 GOSUB L1180 ;get next script byte into B else bsr L1180 ;shave a byte endif ;fix ;function $20, check lamp value in B L1125: ; if fix=1 ; clr $36 ;zero the switch factor ; endif ;fix bsr L113D ;set X to correct lamp address and A to correct lamp mask pshb psha tba ldb $00,x if fix=0 cmpa #$68 ;see if dip switch else cmpa #$3c ;see if flag endif ;fix L112E: bcc L1132 ;yes, branch orb $11,x ;no, capture the blink status as well L1132: if fix=1 bra more_common_ground ;finish in switch routine else pula pshb tsx anda $00,x tpa sta $05,x ;save status pulb pulb rts endif ;fix ;use B to set correct lamp address column address ;then set A to the correct bit mask for the lamp in question L113D: tba ;lamp # lsra ;/2 lsra ;/4 lsra ;/8 adda #$19 ;add lamp offset if fix=1 adda $36 ;add switch factor, if present clr $36 ;clear the switch factor for next time whatever routine uses this endif ;fix psha ;save calculated lsb of lamp address clra ;setup $00 as msb of lamp address psha ;save $00 for msb of lamp address tsx ;get the stack pointer ldx 0,x ;get the newly calculated address in X ins ins ;clear the stack ;X is set to correct lamp address byte ;now use B's offset to make A a mask for correct lamp bit pshb ;save B lda #$01 ;start with bit 0 andb #$07 ;only want bit offset beq L1156 ;bit 0 it is, branch L1152: asla ;shift the mask bit decb ;lamp row decrement bne L1152 ;keep looking and shifting the mask L1156: pulb rts if exp=1 ;use next script parameter to set X to zero page XZERO: tsx ;get current data silo pointer ldx $a,x ;get script pointer lda 0,x ;get lsb of memory location psha ;save for reload clra ;set msb of memory location to zeropage psha ;save for reload tsx ;get the stack pointer back bra L1168 ;advance script once endif ;experimental zero page functionality ;use next 2 script parameters to set X L1158: tsx ;get current data silo ldx $0A,x ;get script pointer lda $01,x ;get lsb of memory location psha ;save for reload lda $00,x ;get msb of memory location psha ;save for reload tsx ;get the data silo pointer back inc $0D,x ;advance the lsb of the script bne L1168 ;no overflow, branch inc $0C,x ;lsb went to $00, advance the msb of the script L1168: inc $0D,x ;advance the lsb of the script bne L116E ;no overflow, branch inc $0C,x ;lsb went to $00, advance the msb of the script L116E: ldx $00,x ;get the pointer from the stack pula ;waste the msb pula ;waste the lsb rts ;return ;get next script step into A L1173: tsx ;get current data silo pointer ldx $0A,x ;get script pointer lda $00,x ;get next script value into A tsx ;get current data silo pointer back ;advance script step L1179: inc $0B,x ;advance script pointer lsb bne L117F ;no overflow, branch to return inc $0A,x ;advance script pointer msb L117F: rts ;return ;get next script parameter in B L1180: tsx ;get current data silo pointer ldx $0A,x ;get script pointer ldb $00,x ;get next script value in B tsx ;get current data silo pointer back stb $06,x ;save B bra L1179 ;advance script pointer and return if fix=1 ;function $59, check switch value test_switch: lda #$21 ;offset factor for switch matrix checking sta $36 ;save in offset factor bsr L1180 ;get next script parameter in B bsr L113D ;set A to mask and X to location pshb psha tba ldb 0,x ; orb 5,x ;get the switch offset as well andb 5,x more_common_ground: pula pshb tsx anda 0,x more_common_ground2: tpa sta 5,x pulb pulb rts endif ;system if spigs=1 ;$5f match pattern (new to spigs) ;takes up to 7 bytes for lamp/flag parameters, checks each one, then the last byte ;designated by sign bit set (1xxx xxxx) is a pattern for the first 7 to match match_pattern: clr $32 ;or other safe spot mp0: bsr L1180 ;get first B and advance script tstb bmi mp_compare ;here's the pattern swi checklampregbon beq not_set sec ;lamp set, ensure carry set bra set32 not_set: clc ;lamp not set, ensure carry clear set32: rol $32 ;preserve carry bit in temp register bra mp0 ;get more parameters mp_compare: andb #$7f ;strip the sign bit cmpb $32 ;compare to the created byte tsx tpa sta $3,x ;save the result in the data silo rts endif ;spigs ;function $24, clear play flags if exp=0 L118A: clra ;setup clear ldx #$0019 ;start with lamp column 0 L118E: sta $11,x ;get the blink columns as well (*and blink overflow... should be ok here) sta $00,x ;save lamp/flag column inx ;move to next index cpx #$0026 ;done? bne L118E ;no, keep going rts ;return endif ;exp shave bytes ;function $25 delay (NOT UTILIZED IN 9 BALL) L1199: if fix=0 GOSUB L1173 ;get next script parameter into A else bsr L1173 ;shave a byte endif ;fix L119C: psha ;save # of iterations of delay bsr L11AA ;keep checking switches during delay pula ;restore # of iterations of delay ldx #$0A00 ;delay factor L11A3: dex ;delay-- bne L11A3 ;not done, keep going deca ;delay factor-- bne L119C ;not done, keep going rts ;return ;function $26 switch dispatch L11AA: pshb ;save B ldx #$5000 ;switch matrix table stx $02ED clrb ldx #$0044 ;start with action register for column 0 L11B5: lda $00,x ;look at action register bne L1216 ;closed switches, branch inx addb #$10 cmpb #$80 bne L11B5 L11C0: lda $0064 ;check self-test switch flag beq L11C7 ;not set, branch jmp L1B64 ;burn-in/self-test L11C7: pulb ;restore B lda $0051 ;look at score timer beq L11D0 ;it's zero, time to process enqueued scores ldx $0074 ;get sound script pointer bne L11E2 ;sound set L11D0: lda #$0C ;setup score interval timer sta $0051 ;save lda #$51 ;setup score byte, 100,000k ldx #$0072 ;setup index to score queues L11D9: tst $00,x ;look at score queue bne L11E3 ;score queue populated, branch dex ;move to next lowest score queue suba #$10 ;adjust the score byte bpl L11D9 ;not done, keep going L11E2: rts ;return L11E3: dec $00,x ;decrement the current score queue stx $02EF ;save X jsr L1573 ;add the score byte in B to the current player's score lda $001F ;lamps 30-37 anda #$08 ;see if tilted bne L11E2 ;tilt lit, branch to return lda $02F0 ;get the score queue lsb suba #$6D ;get offset from score queues asla ;double for indexing ldx #L5E4B ;default sound table stx $02EF ;save X adda $02F0 ;add the doubled offset sta $02F0 ;save lda $02EF ;get the sound table msb adca #$00 ;add any carries from the above (*might not be needed depending on location) sta $02EF ;save the msb ldx $02EF ;get the sound table pointer ldx $00,x ;get the sound stx $0074 ;save sound script clr $0053 ;clear sound waiting flag rts ;return ;found a closed switch L1216: stb $02EE ;save what will become the lsb of the switch routine ldb #$80 L121B: asla bcs L1227 inc $02EE inc $02EE ;move the switch pointer up lsrb ;move the pointer back one bra L121B ;keep looking for closed row L1227: sei ;prevent interrupts if exp=1 pshb ;save row endif ;exp eorb $00,x ;clear row from action column stb $00,x ;save action column if exp=1 pulb ;get row back for switch procesing endif ;exp cli ;allow interrupts ldx $02ED ;get switch pointer ldx $00,x ;get switch routine swi ;start pigs spawn_thread ;add switch thread using X bra L11C0 ;go back and process more switches ;function $27 unconditional goto L1236: tsx ;get current data silo pointer ldx $08,x ;get current script pointer lda $00,x ;get msb of destination script pshb ;save B for later ldb $01,x ;get lsb of destination script tsx ;get current data silo pointer stb $0A,x ;save lsb of script sta $09,x ;save msb of script pulb ;restore B rts ;return ;advance script pointer twice L1245: tsx ;get current data silo pointer inc $09,x ;increase script lsb bne L124C ;no carry, branch inc $08,x ;went to $00, increase script msb L124C: inc $09,x ;increase script lsb bne L1252 ;no carry, branch inc $08,x ;went to $00, increase script msb L1252: rts ;return ;function $29 if equal (z flag set) goto L1253: tsx ;get current data silo pointer lda $03,x ;get saved condition register tap ;copy to condition register beq L1236 ;it's zero, branch to goto bra L1245 ;advance script pointer twice ;function $28 not equal (z flag clear) goto L125B: tsx ;get current data silo pointer lda $03,x ;get saved condition register tap ;copy to condition register bne L1236 ;it's not zero, branch to goto bra L1245 ;advance script pointer twice ;function $55 gosub assembly routine L1263: jsr L1158 ;use next 2 script parameters to set X jmp 0,x ;execute assembly and return ;function $2c unconditional gosub L1268: jsr L1158 ;use next 2 script parameters to set X swi ;start pigs func41 L126D: tsx ldx $06,x swi ;start pigs func41 L1272: tsx lda $06,x sta $08,x lda $07,x sta $09,x lda #$FF ;set the pigs multiprocessing flag sta $02,x ;save in data silo lda $0D,x sta $03,x rts ;return ;function $2e if equal (z flag set) gosub L1284: tsx ;get current data silo pointer lda $03,x ;get saved condition register tap ;copy to condition register beq L1268 ;it's zero, branch to gosub if exp=0 JUMP L1245 ;advance script pointer twice else bra L1245 ;advance script pointer twice endif ;exp ;function $2d not equal (z flag clear) gosub L128D: tsx ;get current data silo pointer lda $03,x ;get saved condition register tap ;copy to condition register bne L1268 ;it's not zero, branch to gosub if exp=0 JUMP L1245 ;advance script pointer twice else bra L1245 ;advance script pointer twice endif ;exp ;function $2f unconditional return L1296: ins ins ins ins ins ins ins ins ins ins ;clear the data silo tpa ;copy the condition register for storage tsx ;get the (next) data silo pointer stb $04,x ;pass B along to the next data silo sta $03,x ;pass the condition register along to the next data silo rts ;return ;function $31 if equal (z flag set) return L12A7: tsx ;get current data silo pointer lda $03,x ;get saved condition register tap ;copy to condition register beq L1296 ;if zero branch to unconditional return rts ;return ;function $30 if not equal (z flag clear) return L12AE: tsx ;get current data silo pointer lda $03,x ;get saved condition register tap ;copy to condition register bne L1296 ;if not zero branch to unconditional return rts ;return ;function $32 if tilted, return L12B5: lda #$08 ;lamp mask to check bra L12BB ;function $33 if game over, return L12B9: lda #$04 ;lamp mask to check L12BB: anda $001F ;check lamp mask against lamps 30-37 bne L1296 ;lamp is on, branch to unconditional return rts ;return ;function $34 return if not in an active game (flag 67) L12C0: lda $0025 ;flags 60-67 bpl L1296 ;flag clear, not in an active game, branch to unconditional return rts ;return ;function $43 push data silo L12C5: swi ;start pigs func42 L12C7: tsx lda $0E,x sta $04,x lda $12,x sta $08,x lda $13,x sta $09,x lda #$FF ;set pigs multiprocessing flag sta $02,x ;save pigs multiprocessing flag rts ;return ;function $44 pull data silo L12D9: tsx ;get current data silo pointer ldb $0E,x lda $08,x sta $12,x lda $09,x sta $13,x ins ins ins ins ins ins ins ins ins ins ;clear data silo rts ;return ;function $52 bcd increase memory location L12EF: jsr L1180 ;get next script parameter into B (width of memory location) jsr L1158 ;use next 2 script parameters to set X L12F5: lda #$01 ;amount to add L12F7: dex ;move to next digits adda $00,x ;increase daa ;correct for humans sta $00,x ;save digits bcc L1302 ;no carry, done decb ;width-- bne L12F5 ;more digits, keep going L1302: rts ;return ;function $53 bcd decrease memory location L1303: if exp=0 jsr L1180 ;get next script parameter into B (width of memory location) jsr L1158 ;use next 2 script parameters to set X L1309: lda #$99 ;setup decrement L130B: dex ;move to next digits adda $00,x ;decrease daa ;correct for humans sta $00,x ;save digits bcs L1316 ;no borrow, done decb ;width-- bne L1309 ;more digits, keep going L1316: rts ;return else lda #$99 adda $2ce daa sta $2ce rts endif ;exp, save some bytes ;function $35 increment B L1317: tsx ;get current data silo pointer incb ;increment B stb $04,x ;save B in current data silo rts ;return ;function $37 decrement B L131C: tsx ;get current data silo pointer decb ;decrement B stb $04,x ;save B in current data silo rts ;return ;function $36 increment memory location L1321: jsr L1158 ;use next 2 script parameters to set X inc $00,x ;increment memory location rts ;return ;function $38 decrement memory location L1327: jsr L1158 ;use next 2 script parameters to set X dec $00,x ;decrement memory location rts ;return ;function $39 load B direct L132D: jsr L1180 ;get next script parameter into B rts ;return ;function $3a load B from memory location L1331: jsr L1158 ;use next 2 script parameters to set X L1334: ldb $00,x ;get B from memory location tsx ;get data silo pointer stb $04,x ;save B in data silo rts ;return ;function $3b store B in memory location L133A: jsr L1158 ;use next 2 script parameters to set X L133D: stb $00,x ;save B in memory location rts ;return if exp=1 ;function $5b load B from zero page loadbz: bsr XZERO ;use next script parameter to set X bra L1334 ;finish in function $3a ;function $5c store B in zero page storebz: bsr XZERO ;use next script parameter to set X bra L133D ;finish in function $3b endif ;exp ;function $3c compare B to A L1340: jsr L1173 ;get next script parameter into A bra L134A ;finish below ;function $3d compare B to memory location in X L1345: jsr L1158 ;use next 2 script parameters to set X lda $00,x ;load memory location to compare into A L134A: psha ;save A for comparison tsx ;get current data silo pointer cmpb $00,x ;compare B to [saved] A L134E: pula ;waste A tpa ;copy condition register to A sta $04,x ;save the condition register in the current data silo rts ;return ;function $3e OR A,B L1353: jsr L1173 ;get next script parameter into A psha ;save A for processing tsx ;get current stack pointer orb $00,x ;effectively OR A,B if exp=0 pula ;waste A tpa ;copy condition register to A sta $04,x ;save the condition register in the current data silo rts ;return else bra L134E ;shave 3 bytes endif ;exp ;function $3f EOR A,B L135F: jsr L1173 ;get next script parameter into A psha ;save A for processing tsx ;get current stack pointer eorb $00,x ;effectively EOR A,B if exp=0 pula ;waste A tpa ;copy condition register to A sta $04,x ;save the condition register in the current data silo rts ;return else bra L134E ;shave 3 bytes endif ;exp ;function $40 AND A,B L136B: jsr L1173 ;get next script parameter into A psha ;save A for processing tsx ;get current stack pointer andb $00,x ;effectively AND A,B if exp=0 pula ;waste A tpa ;copy condition register to A sta $04,x ;save the condition register in the current data silo rts ;return else bra L134E ;shave 3 bytes endif ;exp ;function $2a save current player status L1377: bsr L13A9 ;set X to current player save location stx $02EF ;save as destination pointer ldx #$0015 ;setup source pointer stx $02ED ;save as source pointer L1382: pshb ldb #$11 ;# of bytes to copy L1385: ldx $02ED ;get source pointer lda $00,x ;get source byte inx ;advance source pointer stx $02ED ;save source pointer ldx $02EF ;get destination pointer sta $00,x ;save byte in destination inx ;advance destination pointer stx $02EF ;save destination pointer decb ;counter-- bne L1385 ;not done, keep going pulb ;restore B rts ;return ;function $2b restore current player status L139C: bsr L13A9 ;set X to current player save location stx $02ED ;save as source pointer ldx #$0015 ;set X to destination stx $02EF ;save X as destination pointer bra L1382 ;finish in save player routine ;set X to current save location L13A9: pshb if exp=0 lda $0038 endif ;redundant lda ldb #$6F ;p1 storage area $280-$11 lda $0038 ;currently up player L13B0: addb #$11 ;adjust address deca ;currently up player-- bne L13B0 ;not done, keep going pshb ;save lsb of player storage area ldb #$02 ;setup msb of player storage area $02xx pshb ;save msb of player storage area tsx ;get the stack pointer ldx $00,x ;get the player storage area in X pulb ;waste the ephemeral msb pulb ;waste the ephemeral lsb pulb ;restore B rts ;return ;function $4a show credits L13C0: pshb lda #$FF ;setup default to not show credits sta $0010 ;blank the leftmost part of the credit display if exp=0 ldb $0028 ;dips 17-24 andb #$08 ;isolate dip 20, show credits on/off else swi ;start pigs checklampvalue $7b ;dip 20, show credits endif ;exp, shave a byte beq L13CE ;dip 20 off, don't show credits lda $02CE ;audit 5, current credits L13CE: if exp=0 psha ;save # of credits lsra lsra lsra lsra ;format the msn of credits for display ora #$F0 ;blank the upper digit sta $0011 ;save in credit display pula ;restore # of credits asla asla asla asla ;format the lsn of credits for display ora #$0F ;blank the lower digit sta $0012 ;save in credit display else tab ;transfer # of credits to B lsra lsra lsra lsra ;format the lsn of the credits aslb aslb aslb aslb ;format the msn of the credits ora #$f0 ;blank the upper digit orb #$0f ;blank the lower digit sta $11 ;save in credit display stb $12 ;save in credit display endif ;system, shave a byte ;calculate max credits if exp=0 ldb $0028 andb #$06 lda #$10 asrb beq L13F5 lda #$15 decb beq L13F5 lda #$25 decb beq L13F5 lda #$40 else lda #$99 ;max credits always 99 endif ;exp shave a lotta bytes L13F5: cmpa $02CE ;compare to max credits pulb bhi L1404 if exp=0 sei lda #$20 ora $0092 sta $0092 cli rts else swi cont_solenoid_off_coin rts endif ;exp, save 6 bytes L1404: if exp=0 sei lda #$DF anda $0092 sta $0092 cli rts else swi cont_solenoid_on_coin rts endif ;exp, save 6 bytes ;function $48 update match L140D: if exp=0 lda $0028 ;dips 17-24 anda #$10 ;check dip 21, match else swi checklampvalue $7c ;dip 21, match endif ;exp, shave a byte bne L1417 lda #$EE ;setup blank bra L141F L1417: if exp=0 lda #$08 ;match lamp ora $0020 sta $0020 else swi lampbvalueon $3b endif ;exp, shave a byte lda $0039 ;get match L141F: sta $0013 ;put on match display rts ;return ;function $49 show ball in play L1422: lda $0037 ora #$F0 sta $0013 if exp=0 lda #$F7 ;setup to blank match lamp anda $0020 ;add to lamps 38-3b sta $0020 ;save lamps 38-3b else swi ;start pigs lampbvalueoff $3b ;blank match lamp endif ;exp, shave 3 bytes rts ;function $46 blank current player L142F: bsr L146E ;set X to current player blanking mask and A to valid player bit L1431: coma ;flip for clear anda $0067 ;valid player sta $0067 ;save lda #$FF ;setup blank sta $00,x ;save player blanking mask rts ;return ;function $47 show current player L143B: bsr L146E ;set X to current player blanking mask and A to valid player bit ora $0067 ;set valid player bit sta $0067 ;save clr $00,x ;clear blanking mask rts ;return ;function $45 update curent player L1444: pshb lda #$FC ldb $0038 L1449: adda #$04 decb bne L1449 psha pshb tsx ldx $00,x pulb pulb lda $0015 bsr L147F lda $0016 ldb $0017 bsr L1485 lda $0018 sta $00,x pulb bsr L146E ;set X to current player blanking mask and A to valid player bit if exp=0 coma anda $0067 sta $0067 else bsr L1431 ;routine does same exact thing but puts an $ff in the mask endif ;exp, save 3 bytes clr $00,x ;...which gets cleared here anyway rts ;return L146E: lda #$80 ldx #$0068 pshb ldb $0038 L1476: decb beq L147D inx lsra bra L1476 L147D: pulb rts ;blank leading byte if zero and save in X L147F: bne L1482 deca L1482: sta $00,x rts L1485: psha lda $00,x inx inca pula bne L1499 tsta bne L1493 deca bra L14A0 L1493: bita #$F0 bne L1499 ora #$F0 L1499: sta $00,x inx stb $00,x inx rts ;return L14A0: tstb bne L14A6 decb bra L1499 L14A6: bitb #$F0 bne L1499 orb #$F0 bra L1499 ;function $4b show hstd to date L14AE: ldx #$0000 ;destination pshb ;save B lda $02CA ;hstd x-1m digit bsr L147F ;blank leading zero and save in X lda $02CB ;hstd 100k-10k digits ldb $02CC ;hstd 1k-100 digits bsr L1485 ;blank leading zero and save in X lda $02CD ;hstd 10-1 digits sta $00,x ;save at X pulb ;restore B ;copy hstd to all 4 displays L14C5: if debug=0 ldx $0000 stx $0004 stx $0008 stx $000C ldx $0002 stx $0006 stx $000A stx $000E endif ;debug, don't hose displays if exp=0 lda #$01 ora $001F sta $001F else swi ;start pigs lampbvalueon $30 ;turn on hstd lamp endif ;exp, shave a byte ;function $4c all displays valid L14DB: ldx #$0000 ;setup all displays valid L14DE: clr $0067 ;valid players in game stx $006B ;p4-p5 display masks stx $0068 ;p1-p2 display masks stx $006A ;p3-p4 display masks rts ;return ;function $4d all display invalid L14E8: ldx #$FFFF ;setup all displays invalid bra L14DE ;finish in function $4c ;function $4e transfer scores to display L14ED: ldx #$0000 pshb lda $0280 if fix=0 GOSUB L147F else bsr L147F ;shave a byte endif ;fix lda $0281 ldb $0282 if fix=0 GOSUB L1485 else bsr L1485 ;shave a byte endif ;fix lda $0283 sta $00,x inx lda $0291 jsr L147F lda $0292 ldb $0293 jsr L1485 lda $0294 sta $00,x inx lda $02A2 jsr L147F lda $02A3 ldb $02A4 jsr L1485 lda $02A5 sta $00,x inx lda $02B3 jsr L147F lda $02B4 ldb $02B5 jsr L1485 lda $02B6 sta $00,x pulb clr $0067 lda #$FE anda $001F sta $001F lda $02EC deca anda #$03 inca ldx #$0068 L1558: clr $00,x inx deca bne L1558 deca L155F: cpx #$006C ;done with all player display masks? beq L1569 ;yes, branch to return sta $00,x ;save inx ;move to next player display mask location bra L155F ;keep clearing L1569: rts ;return ;function $4f score directly L156A: if exp=0 lda #$01 ;setup row 0, handle multiple extra balls ora $004B ;add to virtual c7 action register sta $004B ;save virtual c7 action register endif ;move jsr L1173 ;get next script value in A ;actually score L1573: psha ;save A if exp=1 lda #$01 ;setup row 0, handle multiple extra balls ora $004B ;add to virtual c7 action register sta $004B ;save virtual c7 action register endif ;move to handle both functions $56 and $4f to save 6 bytes lda $001F ; anda #$08 ;tilt lit? pula ;restore A if fix=0 beq L157C ;tilt clear, branch rts ;tilted, return without scoring else bne L1569 ;tilted, return without scoring endif ;fix ;add score L157C: pshb ;save B if multi=1 ldb $33 ;display setup, 3F=3x, 2F=2x, 00=nothing! beq m1 lsrb lsrb lsrb lsrb decb m1: stb $32 multiplier: psha ;save score byte endif ;multi tab ;A contains score byte anda #$0F ;clear power of 2, A is now the count lsrb lsrb lsrb lsrb lsrb bcc L158B asla asla asla asla L158B: ldx #$0018 tstb beq L1595 L1591: dex decb bne L1591 L1595: adda $00,x daa sta $00,x L159A: dex cpx #$0015 beq L15A9 lda $00,x adca #$00 daa sta $00,x bra L159A L15A9: bcc L15B2 lda $00,x adda #$01 daa sta $00,x L15B2: lda #$FF ;setup score blink timeout sta $004E ;save score blink timer if multi=1 pula ldb $32 ;multiplier factor, 02=3x, 01=2x, 00=1x beq mx ;zero decb stb $32 bra multiplier ;process until 0 - resets later mx: endif ;multi swi ;start pigs rcflagset ;set pigs multiprocessing flag update_current_player show_current_player lampbvalueon $3c ;set score flag ila ;clear pigs multiprocessing flag ;check for replay level passed ldx #$02C4 clr $02ED ldb #$80 L15C5: lda $00,x anda #$0F ora $01,x beq L15E3 lda $00,x anda #$0F cmpa $0015 bhi L15E3 lda $01,x cmpa $0016 bhi L15E3 tba orb $02ED stb $02ED tab L15E3: lsrb inx inx cpx #$02CA bne L15C5 lda $0020 anda #$E0 coma anda $02ED tab ora $004B sta $004B if exp=0 tba ora $0020 sta $0020 else orb $20 stb $20 endif ;exp, shave a byte pulb ;restore B rts ;return ;function $51 clear variables if exp=0 L15FF: ldx #$002A L1602: clr $00,x inx cpx #$0037 bne L1602 ldx #$0015 L160D: clr $00,x inx cpx #$0026 bne L160D rts else L15FF: ldx #$0015 ldb #$04 loop51: clr 0,x decb bpl skip_offset clr $11,x skip_offset: inx cpx #$0026 bne loop51 rts endif ;exp, save 4 bytes here plus entire function $24 routine ;function $56 add to score queue L1616: if exp=0 lda #$01 ;setup virtual c7r0 ora $004B sta $004B endif ;exp, rearrange in score directly jsr L1173 ldx #$006D ;1's score queue L1622: cmpa #$10 bcs L162B inx suba #$10 bra L1622 L162B: adda $00,x sta $00,x bcc L163B inx cpx #$0074 ;done with all score queues? beq L163B ;yes, branch to return lda #$01 bra L162B L163B: rts ;return ;function $57 play primary sound L163C: lda #$FF ;sound priority sta $0051 ;save in sound timer bra L164D ;load sound ;function $58 play secondary sound L1642: jsr L1158 ;use next 2 script parameters to set X lda $0051 ;check sound timer cmpa #$20 ;decayed far enough to allow secondary sound to be played? bcc L1655 ;no, currently loaded sound script still has priority - branch to return bra L1650 ;save sound script and trigger sound reload L164D: jsr L1158 ;use next 2 script parameters to set X L1650: stx $0074 ;save sound script pointer clr $0053 ;sound script engine timer L1655: rts ;return ;c0r2 right coin L1656: bcdinc $03,$02d8 ;increase audit 9 # of coins in right chute ila ;clear pigs multiprocessing flag/return to assembly ldb $0029 ;use dips 25-32 bra L166F ;branch into coin routine ;c0r1 center coin L165F: bcdinc $03,$02db ;increase audit 10 # of coins in center chute ila ;clear pigs multiprocessing flag/return to assembly ldb $0027 ;use dips 9-16 bra L166F ;branch into coin routine ;c0r0 left coin L1668: bcdinc $03,$02de ;increase audit 11 # of coins in left chute ila ;clear pigs multiprocessing flag/return to assembly ldb $0026 ;use dips 1-8 L166F: tba ldx #L16C4 eora $0029 anda #$0F beq L1686 ldx #L16C8 tba eora $0026 anda #$0F beq L1686 ldx #L16CC L1686: lda $00,x ldb $01,x ldx $02,x pshb psha lda $00,x anda #$0F asla swi ;start pigs checklampregbon beq L1698 inca L1698: ldx #L16CF inca L169C: inx deca bne L169C lda $00,x pulb pshb swi ;start pigs checklampregbon bne L16AC asra asra asra asra L16AC: anda #$0F beq L16B7 L16B0: swi ;start pigs gosub L570E deca bne L16B0 L16B7: pulb swi ;start pigs altlampregb swi ;start pigs checklampregbon bne L16C2 pulb pshb swi ;start pigs altlampregb L16C2: pulb rts ;coin ratio data L16C4: db $47,$44,$00,$29 ;$0029 is dip location L16C8: db $46,$43,$00,$26 ;$0026 is dip location L16CC: db $45,$42,$00 L16CF: db $27 ;$0027 is dip location db $11,$11,$22,$22,$33,$33,$44 db $44,$55,$55,$66,$66,$77,$77,$aa db $aa,$ee,$ee,$01,$01,$12,$12,$05 db $05,$07,$07,$01,$02,$11,$12,$12 db $13 ;match L16F0: ila ;clear pigs multiprocessing flag if exp=0 ldb $02EC ;# of players in current game endif ldx #$0003 ;p1 10-1 L16F7: ; lda $0013 ;get match # if exp=0 LOADA $0013 pshb ;save # of players else lda $13 ;get match # endif ;exp, shave a byte cmpa $00,x ;did this player match? swi ;start pigs eqgosub L5718 ;award match if exp=0 pulb ;get # of players counter back endif inx inx inx inx ;advance to next player if exp=0 decb ;# of players-- else dec $02ec ;# of players as counter endif bne L16F7 ;not done, keep going rts ;return ;check hstd L170A: ldx $02CA ;1m-100k-10k of audit 4, current hstd stx $0015 ;save in scratch ram ldx $02CC ;1k-100-10-1 of audit 4, current hstd stx $0017 ;save in scratch ram ldx #$0280 ;start with player 1 save area bsr L171D ;check p1 bsr L171D ;check p2 bsr L171D ;check p3 ;check p4 L171D: lda $0015 ;1m of hstd anda #$0F ;clear the non-extant 10m digit ldb $00,x ;get player score 1m andb #$0F ;clear the non-extant 10m digit stb $00,x ;save the player score cmpa $00,x ;compare the 1m score bcs L1745 ;it's higher, branch to award hstd bne L1794 ;not equal (i.e. it's lower), branch ;1m score was equal, keep checking lda $0016 ;100k-10k of hstd cmpa $01,x ;compare to player score 100k-10k bcs L1745 ;it's higher, branch to award hstd bne L1794 ;not equal (i.e. it's lower), branch ;1m, 100k-10k, were equal, keep checking lda $0017 ;1k-100 of hstd cmpa $02,x ;compare to player score 1k-100 bcs L1745 ;it's higher, branch to award hstd bne L1794 ;not equal (i.e. it's lower), branch ;1m, 100k-10k, 1k-100, were equal, keep checking (however unlikely....) lda $0018 ;10-1 of hstd cmpa $03,x ;compare to player score 10-1 bcs L1745 ;it's higher, branch to award hstd bra L1794 ;even if it's equal, you don't get the hstd, branch ;award hstd L1745: swi ;start pigs rcflagset ;set pigs multiprocessing flag bcdinc $01,$02d5 ;increase audit checklampvalue $76 ;check dip 31 ifsetgosub L5718 ;set, award at least one credit checklampvalue $77 ;check dip 32 ifcleargoto L175B ;clear, no more credits gosub L5718 ;award credit gosub L5718 ;award credit ;find highest score to store as hstd L175B: ila ;clear pigs multiprocessing flag lda $02CA cmpa $00,x bcs L1780 bne L1794 lda $02CB cmpa $01,x bcs L1780 bne L1794 lda $02CC cmpa $02,x bcs L1780 bne L1794 lda $02CD cmpa $03,x bcs L1780 bra L1794 ;store highest score as hstd L1780: lda $00,x sta $02CA lda $01,x sta $02CB lda $02,x sta $02CC lda $03,x sta $02CD ;move to next player L1794: stx $02ED ;save X lda #$11 ;interval between player save area adda $02EE ;move to next player sta $02EE ;save lsb ldx $02ED ;get next player save area rts ;return L17A3: lda $008B bpl L17B1 ldb #$34 stb $008B lda $008A cli JUMP L18D2 ;jump to zero cross interrupt, process timers L17B1: lda $0089 bpl L17C3 ;spurious interrupt, jump to reset lda $0050 bne L17C0 coma sta $0064 lda #$24 sta $0050 L17C0: lda $0088 rti L17C3: jmp L1E45 ;reset ;nmi (s33/clear) L17C6: lda #$FF ;set flag sta $0066 ;save rti ;return from interrupt ;irq L17CB: lda $0091 bpl L17A3 lda $0090 lda $008B psha lda $0088 psha lda $0065 bne L17E8 coma ldb #$30 stb $008B sta $008A ldb #$34 stb $008B sta $008A L17E8: sta $0088 ldb #$3C stb $008B ldb #$3D stb $0091 ldb #$34 stb $008B ldb #$35 stb $0091 ldx #$0004 ;setup digits lda $0014 ;digit index [80=1 40=10 20=100 10=1K 08=10K 04=100K 02=1M] bne L1804 ;not zero (should never be zero) jmp L1892 ;reset digit index L1804: dex ;move to next data to display (offset from player display 3, 2, 1, 0) asla ;move the digit index bcs L180C ;digit ok, branch, you're working with the lower nibble asla ;move the digit index again bcc L1804 ;still clear, keep searching for the digits' data clc ;ensure upper nibble is the salient nibble L180C: lda #$35 sta $0089 lda $00,x ;get p1 bcd data for this digit ora $0068 ;p1 blank control ($ff=blank, $00=show) bcs L181A ;you're working with the lower nibble, branch anda #$F0 ;clear the lower nibble bra L181F ;branch to save upper nibble data to display ;lower nibble of A is data to send L181A: asla asla asla asla ;move the lower nibble to the upper nibble sec ;make sure the lower nibble is flagged for p2 data L181F: ora #$0E ;setup blank for p1 sta $0088 ;blank p1/save bcd ldb $04,x ;get p2 bcd data for this digit orb $0069 ;p2 blank control (ff=blank, 00=show) ora #$0F ;setup blank for p2 sta $0088 ;blank p2/save bcd bcs L1831 ;you're working with the lower nibble, branch andb #$F0 ;clear the lower nibble bra L1836 ;branch to save upper nibble data to display ;lower nibble of B is data to send L1831: aslb aslb aslb aslb ;move the lower nibble to the upper nibble sec ;make sure the lower nibble is flagged for p3 data L1836: orb #$0D ;setup blank for p2 stb $0088 ;blank p2/save bcd lda $08,x ;get p3 bcd data for this digit ora $006A ;p3 blank control (ff=blank, 00=show) orb #$0F ;setup blank for p3 stb $0088 ;blank p3/save bcd bcs L1848 ;you're working with th elower nibble, branch anda #$F0 ;clear the lower nibble bra L184D ;branch to save upper nibble data to display L1848: asla asla asla asla sec L184D: ora #$0B sta $0088 if debug=0 ldb $0C,x orb $006B else ldb $c,x endif ;debug, always show p4 ora #$0F sta $0088 lda $0014 ;digit index sta $0090 bcs L1863 andb #$F0 bra L1868 L1863: aslb aslb aslb aslb sec L1868: orb #$07 stb $0088 if multi=0 lda $10,x ;get data for display ora $006C else lda $34 bmi normx ;don't display multiplier lda $33 beq normx ;multiplier not set, branch lda $14 ;check digit index bita #$c0 ;either 1's or 10's? beq normx lda $30,x bra altx normx: lda $10,x ;get data for display altx: ora $006C endif ;multi orb #$0F stb $0088 bcc L187B asla asla asla asla sec L187B: ora #$0F sta $0088 ldb $0090 andb #$FE stb $0090 orb #$01 stb $0090 lda #$3D sta $0089 lda $0014 asla bcc L1894 L1892: lda #$02 ;reset digit index L1894: sta $0014 L1896: pula L1897: sta $0088 L1899: lda $0065 L189B: bne L18AD L189D: ldb #$30 L189F: stb $008B L18A1: sta $008A L18A3: ldb #$34 L18A5: stb $008B L18A7: ldb #$23 L18A9: decb L18AA: bne L18A9 L18AC: coma L18AD: sta $008A L18AF: pula L18B0: tab L18B1: lsra L18B2: bcs L18B6 L18B4: lda $008A L18B6: stb $008B L18B8: dec $004C if multi=1 bne L18BB com $34 endif ;multiplier L18BB: lda $0053 L18BD: bne L18C2 L18BF: jmp L1A28 L18C2: dec $0053 L18C5: rti ;return from interrupt ;process timers L18C6: asla tst $00,x beq L18D0 dec $00,x bne L18D0 inca L18D0: inx rts L18D2: ldx #$004C ;start with continuous timer dec $00,x if multi=1 bne L18D7 com $34 endif ;multiplier L18D7: inx L18D8: lda $00,x L18DA: beq L18DE L18DC: dec $00,x L18DE: inx L18DF: cpx #$0052 L18E2: bne L18D8 L18E4: dec $00,x L18E6: bne L1906 L18E8: lda #$04 L18EA: sta $0052 L18EC: inx L18ED: inx L18EE: clra L18EF: bsr L18C6 L18F1: cpx #$005C L18F4: bne L18EF L18F6: ora $0049 L18F8: sta $0049 L18FA: clra L18FB: bsr L18C6 L18FD: cpx #$0064 L1900: bne L18FB L1902: ora $004A L1904: sta $004A ;process match L1906: lda $0039 ;current match adda #$10 ;next match # daa ;correct for humans sta $0039 ;save match # L190D: lda $004D ;check momentary solenoid timer bne L1917 ;still timing, branch ;momentary solenoid timer expired - turn off all momentary solenoids L1911: lda #$0F ora $0092 sta $0092 L1917: lda #$0A L1919: deca bne L1919 ;short delay ;update lamp matrix ldx #$0019 ldb #$F0 L1921: cli stb $0088 lda #$3C sei sta $008B lda #$34 sta $008B lda $00,x coma bitb #$01 bne L1939 asla asla asla asla dex L1939: sta $0088 inx incb bne L1921 cli L1940: lda #$30 L1942: sei L1943: stb $0065 L1945: sta $008B L1947: stb $008A L1949: ldb #$34 L194B: stb $008B L194D: cli ;read switch matrix ldx #$003F ;starting address lda #$20 ;index for # of columns to read L1953: dex ;move to next initial column lsra ;shift the index/strobe sta $0088 ;save strobe beq L1976 ;done, branch ldb #$1E ;setup delay for propagation L195B: decb ;propagate bne L195B ;propagation for the switch strobe psha ;save column index lda $00,x ; eora $05,x anda $05,x ldb $05,x stb $00,x ldb $008A ;get column results stb $05,x anda $05,x ora $0A,x sta $0A,x ;populate action register pula ;restore column index if matrix=1 ;add code to clear action register of col 4 events except for adv. spinner (/04) cmpa #$10 ;was it the first column read (4)? bne L1953 ;no, branch for more ldb $a,x ; andb #$04 ;only allow row for advance spinner standup andb #$66 ;allow locks and advance spinner standup stb $a,x endif ;matrix bra L1953 ;move to next column L1976: coma ;flip A to #$ff ldb #$30 sei stb $008B sta $008A sta $0065 ldb #$35 lda $008A stb $008B cli lda $0067 ;valid players in game (p1=b7 p2=b6 p3=b5 p4=b4) beq L199F ;none, skip ldb $004E ;score blink timer bne L199F ;still timing, branch ldb #$18 ;reset score blink timer stb $004E ;save score blink timer ldx #$0068 ;setup to look at player masks tsta ;valid players L1997: bpl L199B ;don't flip this player com $00,x ;flip the player mask L199B: inx ;move to next player asla ;move to next player bne L1997 ;players left, keep searching ;handle blinking lamps L199F: lda $004F ;check blink timer bne L19B6 ;not time to blink, branch lda #$0C ;reset blink timer sta $004F ;save blink timer ldx #$0019 ;lamp address base ldb #$08 ;# of lamp columns to blink L19AC: lda $00,x ;get lamp column eora $11,x ;see if blink column set sta $00,x ;save lamp column inx ;move to next column decb ;counter-- bne L19AC ;not done, keep going ; if matrix=1 ;update the 'new' switch matrix registers here (slower reacting lock/outhole) ; lda $33 ; eora $34 ; anda $34 ; ldb $34 ; stb $33 ; ldb $32 ;history results from switch matrix read ; stb $34 ; anda $34 ; anda #$fb ;not trying to duplicate the standup here ; ora $48 ;add to col 4 action register ; sta $48 ; ;original switch code copy ; lda $00,x ; eora $05,x ; anda $05,x ; ldb $05,x ; stb $00,x ; ldb $008A ;get column results ; stb $05,x ; anda $05,x ; ora $0A,x ; sta $0A,x ;populate action register ; endif ;matrix L19B6: if exp=0 jmp L1F5B ;finish zero cross interrupt by firing fast react solenoids else ;fast react solenoids L1F5B: lda $25 bpl L1F8A lda $0042 eora $003D anda $0042 anda #$70 ;limit to pops and slings beq L1F8A asla ldb #$04 ;pop bumper asla bcs L1F7B ldb #$01 ;left sling asla bcs L1F7B ldb #$00 ;right sling asla bcs L1F7B L1F7B: lda $004D ;check solenoid timer bne L1F8A ;already timing, THUD! lda #$F0 anda $0092 aba sta $0092 lda #$05 ;solenoid timeout sta $004D ;save in solenoid timer L1F8A: rti ;return from zero cross interrupt endif ;exp, save 3 bytes ;bootup continues, read dip switches L19B9: lds #$027F bsr L1A0A lda #$20 ldx #$0026 L19C3: sta $0088 ldb #$22 L19C7: decb bne L19C7 ;dip strobe propagation delay ldb $008A ;get return stb $00,x ;save dips inx asla bne L19C3 sta $0088 lda #$3D sta $008B ldb #$22 L19DA: decb bne L19DA ldb $008A stb $00,x cli lda #$01 sta $0058 sta $0059 if exp=0 lda #$17 ;get the 17 sta $0039 ;put it in the match display ;bootup and initialization completed, check dips ;all off=go into burn in/self-test ldx $0026 ;dips 1-16 bne L19F7 ;some are set, branch ldx $0028 ;dips 17-32 bne L19F7 ;some are set, branch jmp L1B64 ;all dips were off, branch to burn in/self-test endif ;exp L19F7: swi ;start pigs rcflagset ;set pigs multiprocessing flag lampbvalueon $32 ;game over show_credits ;get credits on display show_hstd ;get hstd on all 4 displays update_match ;do match/game over ila ;clear pigs multiprocessing flag if exp=0 clr $0039 ;get the 17 out of the match # else lda #VERSION sta $13 endif ;exp ;main loop L1A02: lds #$027F ;reset to top of stack jsr L11AA ;switch dispatch if debug=1 lda $52 cmpa #$03 bne L1A02 jsr debugger endif bra L1A02 ;keep it going L1A0A: ldx #$0000 clra L1A0E: sta $00,x inx cpx #$0080 bne L1A0E ldx #$FFFF stx $003A stx $003C stx $003E stx $0040 stx $0042 stx $0068 stx $006A rts L1A28: ldx $0074 L1A2A: bne L1A4D L1A2C: lda $02FB L1A2F: eora #$00 L1A31: if exp=1 sta $A2 else STOREA $00a2 endif ;save a byte L1A34: lda $02FC L1A37: eora #$00 L1A39: if exp=1 sta $A3 else STOREA $00a3 endif ;save a byte L1A3C: lda $02FD L1A3F: eora #$00 L1A41: if exp=1 sta $A4 else STOREA $00a4 endif ;save a byte L1A44: lda $02FE L1A47: eora #$00 L1A49: if exp=1 sta $A5 else STOREA $00a5 endif ;save a byte L1A4C: rti L1A4D: lda $00,x L1A4F: inx L1A50: ldb $00,x L1A52: tsta L1A53: bpl L1A7F L1A55: psha L1A56: clra L1A57: psha L1A58: lda $01,x L1A5A: inx L1A5B: inx L1A5C: stx $0074 L1A5E: tsx L1A5F: ldx $00,x L1A61: ins L1A62: ins L1A63: stb $00,x L1A65: sta $01,x L1A67: cpx #$00A2 L1A6A: bne L1A72 L1A6C: stb $02FB L1A6F: sta $02FC L1A72: cpx #$00A4 L1A75: bne L1A28 L1A77: stb $02FD L1A7A: sta $02FE L1A7D: bra L1A28 L1A7F: bne L1A89 L1A81: inx L1A82: ; stb $0053 if exp=0 STOREB $0053 else stb $53 endif ;exp L1A85: stx $0074 L1A87: bra L1A2C L1A89: deca L1A8A: bne L1A91 L1A8C: ldx #$0000 L1A8F: bra L1A85 L1A91: deca L1A92: bne L1A9A L1A94: inx L1A95: stb $02F1 L1A98: bra L1A4D L1A9A: deca L1A9B: bne L1AA6 L1A9D: dec $02F1 L1AA0: bne L1AA9 L1AA2: inx L1AA3: inx L1AA4: bra L1A4D L1AA6: deca L1AA7: bne L1AAD L1AA9: ldx $00,x L1AAB: bra L1A4D L1AAD: deca L1AAE: bne L1AB6 L1AB0: inx L1AB1: ; stb $00C0 if exp=0 STOREB $00c0 else stb $c0 endif ;exp L1AB4: bra L1A4D L1AB6: deca L1AB7: bne L1ADC L1AB9: lda $01,x L1ABB: adda $02FC L1ABE: adcb $02FB L1AC1: stb $02FB L1AC4: sta $02FC L1AC7: lda $02FD L1ACA: ldb $02FE L1ACD: addb $01,x L1ACF: adca $00,x L1AD1: sta $02FD L1AD4: stb $02FE L1AD7: inx L1AD8: inx L1AD9: JUMP L1A4D L1ADC: deca L1ADD: bne L1AE5 L1ADF: lda $01,x L1AE1: inx L1AE2: inx L1AE3: bra L1ABB L1AE5: deca L1AE6: bne L1B23 L1AE8: lda #$00 L1AEA: ldb #$01 L1AEC: sta $00A1 L1AEE: sta $00A0 L1AF0: stb $00A1 L1AF2: stb $00A0 L1AF4: sta $00C0 L1AF6: sta $0051 L1AF8: ldx #$0000 L1AFB: stx $0074 L1AFD: lda $0025 L1AFF: bge L1B04 L1B01: JUMP L1F8B L1B04: JUMP L1A2C L1B07: suba #$08 L1B09: bne L1B47 L1B0B: stb $02FB L1B0E: lda $01,x L1B10: sta $02FC L1B13: lda $02,x L1B15: sta $02FD L1B18: lda $03,x L1B1A: sta $02FE L1B1D: inx L1B1E: inx L1B1F: inx L1B20: inx L1B21: lda #$06 L1B23: cmpa #$08 L1B25: bcc L1B07 L1B27: clrb L1B28: stb $00A1 L1B2A: stb $00A0 L1B2C: ldb #$92 L1B2E: asra L1B2F: bcc L1B33 L1B31: stb $00A0 L1B33: asra L1B34: bcs L1B37 L1B36: clrb L1B37: incb L1B38: stb $00A1 L1B3A: clr $00A0 L1B3D: asra L1B3E: bcc L1B44 L1B40: ldb #$92 L1B42: stb $00A0 L1B44: JUMP L1A4D L1B47: deca L1B48: bne L1B50 L1B4A: inx L1B4B: stb $02F2 L1B4E: bra L1B44 L1B50: deca L1B51: bne L1B59 L1B53: dec $02F2 L1B56: JUMP L1AA0 L1B59: deca L1B5A: bne L1B44 L1B5C: lda $02F1 L1B5F: sta $0053 L1B61: JUMP L1A85 ;burn-in/self-test L1B64: if exp=0 ldx #L1E45 ;setup reset stx $0078 clra sta $0074 sta $0075 sta $0077 sta $0076 sta $0064 sta $0066 deca sta $0028 jsr L1CC7 swi ;start pigs all_displays_valid swi ;start pigs clearplayflags L1B80: bsr L1BF6 jsr L1C2E jsr L1C76 if fix=0 GOSUB L1C02 else bsr L1C02 ;shave a byte endif ;fix beq L1B80 else ldx #L1E45 ;setup reset stx $0078 clra sta $0064 swi clearplayflags jsr L1CC7 endif ;save some, eliminate the burn in part of the self test L1B8D: swi ;start pigs L1B8E: all_displays_invalid L1B8F: jsr L1CC7 L1B92: bsr L1BF6 L1B94: bsr L1C02 L1B96: beq L1B92 L1B98: swi ;start pigs L1B99: clearplayflags swi ;start pigs L1B9B: all_displays_valid L1B9C: lda #$FF L1B9E: sta $0076 L1BA0: jsr L1C2E L1BA3: bsr L1C02 L1BA5: beq L1BA0 L1BA7: lda #$FF L1BA9: sta $0077 L1BAB: jsr L1C76 L1BAE: jsr L1C9B L1BB1: bsr L1C02 L1BB3: beq L1BAB L1BB5: jsr L1CC7 L1BB8: clr $0077 L1BBB: ldx #$003F L1BBE: ldb #$08 L1BC0: lda $00,x L1BC2: inc $0077 L1BC5: lsra L1BC6: bcs L1BE9 L1BC8: decb L1BC9: bne L1BC2 L1BCB: inx L1BCC: cpx #$0044 L1BCF: bne L1BBE L1BD1: ldx #$FFFF L1BD4: stx $0068 L1BD6: stx $006A L1BD8: ldb #$F0 L1BDA: stb $0013 L1BDC: ldx #$FFFF L1BDF: stx $0010 L1BE1: stx $0011 L1BE3: lda #$08 L1BE5: sta $0067 L1BE7: bra L1BEF L1BE9: dec $0077 L1BEC: jsr L1C9B L1BEF: bsr L1C02 L1BF1: beq L1BB8 L1BF3: JUMP L1CD0 L1BF6: ldx #$0019 L1BF9: com $00,x L1BFB: inx L1BFC: cpx #$0021 L1BFF: bne L1BF9 L1C01: rts ;delay and self-test switch status L1C02: bsr L1C1C ;delay bsr L1C1C ;delay bsr L1C1C ;delay bsr L1C1C ;delay lda $0066 ;test nmi flag beq L1C12 ;not pressed, branch ldx $0078 ;get s33 pointer jsr 0,x ;execute L1C12: clr $0066 ;clear nmi flag lda $0064 ;get self-test switch flag clr $0064 ;clear self-test switch flag tsta ;test self-test switch flag rts ;return ;delay L1C1C: lda #$0E ;delay factor (same as solenoid test period) sta $004D ;save in solenoid timer L1C20: lda $004D ;solenoid timer bne L1C20 ;still timing, branch deca ;make it #$ff sta $0092 ;all solenoids off rts ;return L1C28: dex L1C29: inx deca bpl L1C29 rts L1C2E: lda $0076 inca cmpa #$11 bcs L1C36 clra L1C36: sta $0076 ldx #L1DC3 ;display digits bsr L1C28 lda $00,x cmpa #$9A bcc L1C4D sta $0000 sta $0001 sta $0002 sta $0003 bra L1C6B L1C4D: ldx #$FFFF stx $0000 stx $0002 suba #$A0 tab asrb ldx #$0000 L1C5B: tstb beq L1C62 inx decb bra L1C5B L1C62: ldb #$8F asra bcc L1C69 ldb #$F8 L1C69: stb $00,x L1C6B: bsr L1CB5 ldx $0000 stx $0010 ldx $0002 stx $0012 rts L1C76: lda $0077 inca cmpa #$1D bcs L1C7E clra L1C7E: sta $0077 cmpa #$13 bge L1C8E ldx #L1DAF ;solenoid list bsr L1C28 lda $00,x sta $0092 rts L1C8E: suba #$13 ;adjust index ldx #L1DE7 ;list of test sounds asla ;double for indexing bsr L1C28 ;adjust X based on A ldx $00,x ;get sound stx $0074 ;self-test sound rts ;return L1C9B: swi all_displays_valid lda #$FF sta $006C ;blank credit/ball in play display lda $0077 tab clra incb L1CA6: adda #$01 daa decb bne L1CA6 sta $0003 ldx #$FFFF stx $0000 stx $0001 L1CB5: ldx #$0000 L1CB8: lda $00,x sta $04,x sta $08,x sta $0C,x inx cpx #$0004 bne L1CB8 rts L1CC7: lda #$01 sta $00A1 sta $00A0 sta $00C0 rts ;adjustments/audits L1CD0: ldx #L1D9D ;routine to branch to when s33 pressed stx $0078 lda #$01 ;set audit 1 sta $0038 sta $0013 swi ;start pigs all_displays_valid ldx #$FFFF ;setup blank stx $0010 ;blank left side of credit/ball in play display stx $0011 ;blank right side of credit/ball in play display L1CE4: ldx #L1DD4 ;audit width table stx $007A ldx #$02C4 ;start of audits/adjustments stx $02EE ;save pointer L1CEF: bsr L1D4B swi ;start pigs update_current_player if fix=0 GOSUB L1CB5 else bsr L1CB5 ;shave a byte endif ;fix ldx $007A ;audit width pointer ldb $00,x ;get width bgt L1D30 ;don't allow adjustment for negated widths lda $003F ;switch matrix colum 0 history anda #$20 ;isolate the credit button beq L1D30 ;not pressing, don't advance value swi ;start pigs score $41 ;advance adjustment by 10k steps ldx $007A ;get audit width ldb $00,x ;get width if exp=0 tstb ;you wouldn't need to even do this anyway because flags were set at the ldb! bgt L1D0D endif ;exp negb ;always negate the width because only negated widths allow the setting of an adjustment ;copy the new adjustment value to nvram ;B is holding the width of the audit, used as a counter L1D0D: ldx $02EE ;get pointer to audit lda $0015 ;get 1m digit sta $00,x ;save decb ;width-- beq L1D29 ;done, branch lda $0016 ;get 100k/10k digits sta $01,x ;save decb ;width-- beq L1D29 ;done, branch lda $0017 ;get 1k/100 digits (this is only valid for HSTD setting) sta $02,x ;save decb ;width-- beq L1D29 ;done, branch lda $0018 ;get 10/1 digits (only valid for hstd setting) sta $03,x ;save L1D29: bsr L1CB5 jsr L1C1C ;delay bra L1CEF L1D30: jsr L1C02 beq L1CEF bsr L1D4B stx $02EE ldx $007A inx stx $007A lda $0013 adda #$01 daa sta $0013 bra L1CEF L1D48: jmp L1E45 ;reboot ;display audit L1D4B: ldx #$0000 stx $0015 stx $0017 ;clear scratch ram in antipation of copying varying widths of data from nvram ldx $007A ;get width pointer back ldb $00,x ;get width beq L1D48 ;audit '19', reboot if exp=0 bgt L1D5B ;audit negated=one of the first 4, branch if not negb ;negate the width L1D5B: ldx $02EE ;audit location cpx #$02C4 beq L1D92 cpx #$02C6 beq L1D92 cpx #$02C8 beq L1D92 cmpb #$04 beq L1D7D cmpb #$03 beq L1D82 cmpb #$02 beq L1D87 cmpb #$01 beq L1D8C L1D7D: lda $00,x sta $0015 inx else ldx $2ee ;source location tstb bmi L1D92 ;sign bit set, it's audit 1, 2, 3, or 4 decb beq L1D8C ;it was 1 decb beq L1D87 ;width was 2 ;assume width 3 for all other entries (hstd is 4, but handled in other routine) endif ;exp L1D82: lda $00,x sta $0016 inx L1D87: lda $00,x sta $0017 inx L1D8C: lda $00,x sta $0018 inx rts ;audit is a replay level, only populate the 10m-1m-100k-10k spots L1D92: if exp=1 negb endif ;exp lda $00,x sta $0015 inx lda $00,x sta $0016 inx if exp=1 decb decb ;width, hstd will be 4 bne L1D87 ;must be hstd, branch to finish in previous routine endif ;exp rts ;clear audit L1D9D: ldx $007A ;get audit width pointer back ldb $00,x ;get width ldx $02EE ;get audit back tstb bgt L1DA8 negb ;flip the width to get the counter L1DA8: clr $00,x inx decb bne L1DA8 rts ;return ;solenoid list L1DAF: db $f1,$f0,$f5,$f6,$f2,$f3,$f4,$f7 db $fa,$fb,$fd,$fc,$f8,$f9,$bf,$fe db $ef,$7f,$df,$ff ;display digits L1DC3: db $00,$11,$22,$33,$44,$55,$66,$77 db $88,$99,$a1,$a2,$a3,$a4,$a5,$a6 db $a7 ;width of audits ;1st 4 are negated to mark that they copy down differently (2 bytes instead of 4 for the replay levels) L1DD4: db $fe,$fe,$fe,$fc db $01,$03,$02,$01 db $03,$03,$03,$02 db $02,$02,$02,$02 db $02,$02,$00 ;test sound list L1DE7: dw L1DFB dw L1E11 dw L1E27 dw L1E2E dw L1E31 dw L1E34 dw L1E37 dw L1E3A dw L1E3D dw L1E40 L1DFB: db $22,$01,$00,$0c,$00,$0c,$22,$02 db $00,$00,$0c,$22,$04,$00,$00,$0c db $22,$08,$00,$00,$0c,$08 L1E11: db $24,$01,$00,$0a,$00,$0c,$24,$02 db $00,$00,$0c,$24,$04,$00,$00,$0c db $24,$08,$00,$00,$0c,$08 L1E27: db $26,$60,$00,$09,$05,$08,$01 L1E2E: db $05,$19,$01 L1E31: db $05,$2a,$01 L1E34: db $05,$3b,$01 L1E37: db $05,$4c,$01 L1E3A: db $05,$5d,$01 L1E3D: db $05,$6e,$01 L1E40: db $05,$7f,$00,$ff,$08 ;reset L1E45: sei lds #$007F lda #$04 sta $0089 sta $0093 ldx #$FF00 stx $0088 stx $008A stx $0090 stx $0092 lda #$30 sta $0091 L1E5E: dex bne L1E5E clra sta $00A1 lda #$92 sta $00A0 inca sta $00A1 clr $00A0 ldx #$8000 stx $00A6 ldx #$0200 stx $00A4 lda #$02 sta $00C0 ;rom checksum clra ldx #$1000 L1E80: adda $00,x inx cpx #$2000 bne L1E80 ldx #$5000 L1E8B: adda $00,x inx cpx #$6000 bne L1E8B tsta ;rom must sum to $00 L1E94: if fix=0 bne L1E94 ;bad checksum, hang else nop nop endif ;fix bsr L1EE5 ;1st flash ;test 6810 ram L1E98: clra L1E99: inca sta $00,x cmpa $00,x L1E9E: bne L1E9E ;ram bad, hang tsta bne L1E99 inx cpx #$0080 bne L1E98 bsr L1EE5 ;2nd flash ;test u8/u13 5101 ram ldx #$0200 L1EAE: ldb $00,x clra L1EB1: inca sta $00,x cmpa $00,x L1EB6: bne L1EB6 ;ram bad, hang tsta bne L1EB1 stb $00,x inx cpx #$0300 bne L1EAE bsr L1EE5 ;3rd flash ;pia u10 test ldx #$008B ;base address of u10 bsr L1EFE ;test pia in X bsr L1EE5 ;4th flash ;pia u11 test ldx #$0093 ;base address of u11 bsr L1EFE ;test pia in X bsr L1EE5 ;5th flash ;display interrupt test lda $0090 ;reset PIA L1ED5: lda $0091 ;test input port bpl L1ED5 ;wait for display interrupt pulse bsr L1EE5 ;6th flash ;zero crossing interrupt test lda $008A ;reset PIA L1EDD: lda $008B ;test input port bpl L1EDD ;wait for zero crossing interrupt pulse bsr L1EE5 ;7th flash bra L1F33 ;branch to continue initilization ;flash LED L1EE5: lda #$38 sta $0091 lda #$02 sta $00C0 ldx #$E530 L1EF0: dex bne L1EF0 lda #$30 sta $0091 ldx #$A5F0 L1EFA: dex bne L1EFA rts ;test pia sent in X L1EFE: bsr L1F00 L1F00: lda #$31 bsr L1F19 lda #$39 bsr L1F19 dex bsr L1F23 inx lda #$35 bsr L1F19 lda #$3D bsr L1F19 dex bsr L1F23 dex rts L1F19: sta $00,x ldb $00,x andb #$3F cba L1F20: bne L1F20 ;pia bad, hang rts L1F23: clra L1F24: sta $00,x ldb #$03 L1F28: decb bne L1F28 cmpa $00,x L1F2D: bne L1F2D ;pia bad, hang inca bne L1F24 rts ;bootup continues L1F33: lda #$38 sta $0089 sta $008B sta $0091 sta $0093 ldb #$FF stb $0088 stb $0090 stb $0092 comb stb $008A lda #$34 sta $0093 lda #$35 sta $0089 sta $008B sta $0091 lda #$FF sta $0092 jmp L19B9 ;continue bootup if exp=0 ;fast react solenoids L1F5B: lda $0025 ;flags 60-67 anda #$80 ;isolate flag 67, active game beq L1F8A ;clear - branch (efficiency - lda $25, bpl L1f8a, save 2bytes lda $0042 eora $003D anda $0042 anda #$70 ;limit to pops and slings beq L1F8A asla ldb #$04 ;pop bumper asla bcs L1F7B ldb #$01 ;left sling asla bcs L1F7B ldb #$00 ;right sling asla bcs L1F7B L1F7B: lda $004D ;check solenoid timer bne L1F8A ;already timing, THUD! lda #$F0 anda $0092 aba sta $0092 lda #$05 ;solenoid timeout sta $004D ;save in solenoid timer L1F8A: rti ;return from zero cross interrupt endif ;exp, move fast react to zero interrupt end saves 3 bytes (big whoop) L1F8B: lda $0026 bpl L1F91 bsr L1FA4 L1F91: jmp L1A2C L1F94: lda $0026 ;dips 1-8 bpl L1FDB ;dip 8, background sound - if off branch to return ldx #$1800 stx $02F7 ldx #$1C00 stx $02F9 L1FA4: ldx $02F7 stx $02FB ldx $02F9 stx $02FD ldx #L5E57 stx $0074 clr $0053 dec $02FF rts ;return L1FBC: ila lda $02F8 ldb $02F7 cmpb #$14 beq L1FDB suba #$FF sbcb #$00 blt L1F94 ;handle background sound sta $02F8 stb $02F7 addb #$04 sta $02FA stb $02F9 L1FDB: rts if fix=0 L1FDC: ;(short) filler 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,$ff db $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff db $ff,$ff,$ff db $1b ;checksum correction endif ;fix org $2000 db $ff org $5000 ;switch matrix jump table L5000: ;col0 if exp=0 dw L5732 ;row7 slam else dw L56E5-1 ;row7 sneaky slam endif ;exp dw L5733 ;row6 tilt dw L50B1 ;row5 credit button dw L5480 ;row4 spinner dw L5370 ;row3 loop rollunder dw L1656 ;row2 right coin dw L165F ;row1 center coin dw L1668 ;row0 left coin ;col1 if exp=0 dw L5133 ;row7 drop 8 dw L5138 ;row6 drop 7 dw L513D ;row5 drop 6 dw L5142 ;row4 drop 5 dw L5147 ;row3 drop 4 dw L514C ;row2 drop 3 dw L5151 ;row1 drop 2 dw L5156 ;row0 drop 1 else dw L5158 ;row7 drop 8 dw L5158 ;row6 drop 7 dw L5158 ;row5 drop 6 dw L5158 ;row4 drop 5 dw L5158 ;row3 drop 4 dw L5158 ;row2 drop 3 dw L5158 ;row1 drop 2 dw L5158 ;row0 drop 1 endif ;exp ;col2 dw L5545 ;row7 r 3 bank bottom dw L5538 ;row6 r 3 bank middle dw L5526 ;row5 r 3 bank top dw L53CF ;row4 single drop dw L55AA ;row3 top 3 bank right dw L559D ;row2 top 3 bank middle dw L558B ;row1 top 3 bank left dw L5582 ;row0 top dead bumper ;col3 dw L5370 ;r7 lock lane lower switch dw L5510 ;r6 pop bumper dw L562C ;r5 left sling dw L562C ;r4 right sling dw L5623 ;r3 left inlane dw L561A ;r2 right inlane dw L5611 ;r1 left outlane dw L5608 ;r0 right outlane ;col4 if matrix=0 dw L5B83 ;40:80/r7 shooter lane else dw L5AF0 ;no activation endif ;matrix dw L5B89 ;39:40/r6 lock lane top dw L5B96 ;38:20/r5 lock lane middle if exp=0 dw L5BAC ;37:10/r4 left outhole [not directly activated] dw L5BAD ;36:08/r3 middle outhole [not directly activated] else dw L5AF0 ;37:10/r4 left outhole [not directly activated] dw L5AF0 ;36:08/r3 middle outhole [not directly activated] endif ;exp dw L5363 ;35:04/r2 advance spinner standup dw L5BA3 ;34:02/r1 lock lane saucer if matrix=0 dw L5BAE ;33:01/r0 outhole else dw L5AF0 ;outhole, never directly activated endif ;matrix ;col5 virtual dw L538C ;row7 uses timer $54, advance loop value one step dw L58BA ;row6 uses timer $55, spinner timeout dw L577C ;row5 uses timer $56, kill multiplier blinking, check if 3 bank wow should light dw L5A92 ;row4 uses timer $57, saucer decisions dw L568A ;row3 uses timer $58, attract mode display thread dw L56A5 ;row2 uses timer $59, attract mode lamp thread dw L5852 ;row1 uses timer $5a, add bonus ?? dw L5D71 ;row0 uses timer $5b, walk 8 bank wow ;col6 virtual dw L57DA ;row7 uses timer $5c, 8 bank reset, decide if memory drops dw L5D49 ;row6 uses timer $5d, determine if switches were missed dw L5BD6 ;row5 uses timer $5e, ball end decisions dw L5435 ;row4 uses timer $5f, collect loop value dw L5990 ;row3 uses timer $60, turn off flashing wow dw L541C ;row2 uses timer $61, collect loop value dw L5AD5 ;row1 uses timer $62, release balls for multiball if matrix=0 dw L5B3E ;row0 uses timer $63, eject ball into shooter lane else dw master_switch ;row0 uses timer $63 - monitor switch threads endif ;matrix ;col7 virtual dw L56F4 ;row7 replay 1 surpassed dw L56FB ;row6 replay 2 surpassed dw L5702 ;row5 replay 3 surpassed dw L5132 ;row4 n/u dw L5132 ;row3 n/u dw L5132 ;row2 n/u dw L5C78 ;row1 launch ball dw L5D40 ;row0 handle multiple extra balls/set active score flag ;swi ;pigs engine ;note that the pigs table must start on a page boundry ;currently, $1000 L5080: clra ;setup marker byte psha ;save tsx ;get current data silo pointer lda $00,x ;get the zero tap ;clear the condition register L5086: ldx $06,x ;get current script location lda $00,x ;get pigs command if exp=1 psha ;save the undoulbed pigs command for later suba #$18 ;clear all solenoid commands 0-17 bpl not_solenoid ;commands 0-17 become negative, works until pigs functions >$8f lda 0,x ;get a fresh copy of the command back cmpa #$0f ;test for momentary solenoid bhi ten217 ;it's not, it's continuous on or off, branch clra ;set function to first entry in table bra its_solenoid ;branch to process ten217: tab ;copy for processing lda #$fe ;base function cmpb #$14 ;see if continuous on bcs not_solenoid ;it is, branch to process inca ;must be continuous off, increase function index not_solenoid: adda #$03 ;get correct function index for all commands $10-$58 its_solenoid: endif ;exp L508A: asla ;double for indexing ; adda #lo L1000 ;this would allow the pigs table to reside anywhere in memory psha ;save doubled value [plus the low byte offset of the pigs table in the mod rom] ;(this will become the lsb of the table entry) L508C: ; lda #$10 lda #hi L1000 ;pigs table starts at $1000 if fix=0 adca #$00 ;handle any carry from the doubling operation endif ;fix, not needed if pigs table <$80 L5090: psha ;save the msb of the table entry tsx if exp=0 inc $09,x ;advance current script location lsb bne L5098 ;no carry, branch inc $08,x ;increase current script location msb else inc $0a,x ;advance current script location lsb bne L5098 ;no carry, branch inc $09,x ;increase current script location msb endif ;exp L5098: ldx $00,x ;get offset in stern pigs table ldx $00,x ;get routine ins pula if exp=1 pula ;get the undoubled pigs command back endif ;exp jsr 0,x tsx lda $00,x L50A3: bne L5086 pula rti if exp=1 clearbee: clrb tsx stb 6,x rts endif ;exp ;function $18 set pigs multiprocessing flag L50A7: lda #$FF ;setup flag tsx ;get data silo pointer sta $02,x ;save flag rts ;return ;function $19 clear multiprocessing flag (clear pigs multiprocessing flag) L50AD: tsx ;get data silo pointer clr $02,x ;clear multiprocessing flag rts ;return ;COMEHERE - all game switch logic, etc. below, all system logic above if credit=1 ;we know there's 0 credits - check for freeplay cb4: checklampvalue $7a ;dip 19, now freeplay on/off eqreturn ;not freeplay, gimmee 25¢ checklampvalue $32 ;is it game over? notegoto cb5 ;yes, always ok to add a credit ;not game over check ball in play and number of players loadbmem $37 ;get current ball in play bacomp $01 ;on first ball? notegoto cb5 ;no, always ok to add a credit and restart game ;you're on ball 1 - make sure players not maxed (which erroneously adds a credit) loadbmem $2ec ;get current number of players bacomp $04 ;already at 4? eqreturn ;yes, return ;ok to add a credit and reprocess switch cb5: loadb $01 ;gimmee a credit storebmem $02ce ;store credit, flow into the credit button routine again endif ;credit ;credit button L50B1: checklampvalue $40 ;game flag marker ?? ifclearreturn ;not set, return loadbmem $02ce ;current credits bacomp $00 ;>0? if credit=0 eqreturn ;no, return else eqgoto cb4 ;check for free play endif ;credit checklampvalue $32 ;game over lamp ifsetgoto L50D7 ;lit, branch to start a new game ;game is in progress, see if ok to add a player or restart game loadbmem $0037 ;current ball in play bacomp $01 ;on ball 1? notegoto L50D7 ;>ball 1, branch to start new game ;game is in progress, on ball 1 loadbmem $02ec ;current # of players bacomp $04 ;already at 4 players? eqreturn ;yes, do not start new game, just return lxiw $02ec ;increase # of players gosub L511C ;add a player save_current_player ;save up player progress xfer_scores_to_displays ;get score back show_current_player ;show score if exp=1 L5132: ;re-use return for switch matrix endif ;exp return ;return ;start new game L50D7: if fix=1 check_switch $20 ;outhole ifclearreturn check_switch $23 ;mid outhole ifclearreturn check_switch $24 ;left outhole ifcleargoto checkshooterlane goto startgame checkshooterlane: check_switch $27 ;shooter lane ifclearreturn startgame: endif loadb $01 ;bytes initialized to one storebmem $02ec ;current # of players storebmem $0038 ;currently up player storebmem $0037 ;current ball in play show_ball_in_play ;show current ball in play on display, turn off game over/match gosub L511C ;add a player clear_var ;clear game memory locations xfer_scores_to_displays ;update scores xloadgoto L56E1 ;clear all virtual switch column timers $54-$63 and $49-$4a ila ;clear pigs multiprocessing flag ldx #$0000 ;words initizalied to zero stx $004A ;clears 4b as well as 4a stx $006D ;score queue 1, 10 stx $0071 ;score queue 10k, 100k stx $006F ;score queue 100, 1k clr $02F6 ;? swi ;start pigs rcflagset ;set pigs multiprocessing flag if exp=0 lampbvalueon $40 ;set credit button flag lampbvalueon $18 ;multipler 1x lampbvalueon $1b ;loop 10k else lampon $40,$18,$1b ;credit button flag, multiplier 1x, loop 10k endif ;exp save_current_player ;save initial lamps/flags for player 1 lxiw $0038 ;increase currently up player save_current_player ;save initial lamps/flags for player 2 lxiw $0038 ;increase currently up player save_current_player ;save initial lamps/flags for player 3 lxiw $0038 ;increase currently up player save_current_player ;save initial lamps/flags for player 4 loadb $01 ;setup to put currently up player back to player 1 storebmem $0038 ;currently up player if exp=0 loadb $02 ;setup to fire ball release solenoid else binc ;save a byte endif ;exp storebmem $004b ;virtual col 7 action register xloadgoto L1A02 ;goto main loop (discards return address) ;add a player L511C: if exp=0 bcddec $01,$02cf ;decrease current credits by 1 else db $53 ;bcd decrement is always credits endif ;exp show_credits ;update credits on display bcdinc $03,$02d2 ;increase audit 6, # of games started sound_play_primary L5F1F ;play add player sound ila ;clear pigs multiprocessing flag sei ;prevent interrupts lda $0044 ;col 0 action register anda #$DF ;clear credit button sta $0044 ;save cli ;allow interrupts L5131: rts ;return if exp=0 L5132: return endif ;exp, shave a byte if exp=0 ;drop 8 L5133: loadb $80 ;drop 8 row 7 goto L5158 ;process drop ;drop 7 L5138: loadb $40 ;drop 7 row 6 goto L5158 ;process drop ;drop 6 L513D: loadb $20 ;drop 6 row 5 goto L5158 ;process drop ;drop 5 L5142: loadb $10 ;drop 5 row 4 goto L5158 ;process drop ;drop 4 L5147: loadb $08 ;drop 4 row 3 goto L5158 ;process drop ;drop 3 L514C: loadb $04 ;drop 3 row 2 goto L5158 ;process drop ;drop 2 L5151: loadb $02 ;drop 2 row 1 goto L5158 ;process drop ;drop 1 L5156: loadb $01 ;drop 1 row 0 endif ;exp ;process drops L5158: storebmem $0076 ;save drop row checkactivegame ;return if not in an active game checklampvalue $57 ;8 bank flag ifsetreturn ;flag set, return ila ;clear pigs multiprocessing flag lda $0076 ;get drop row anda $02F5 ;and with drop register if exp=0 bne L51D0 ;already down, branch to return else bne L5131 ;convenient return endif ;shave byte later lda $0076 ;get drop row again ora $02F5 ;add to drop register sta $02F5 ;save drop register lda $001B ;lamps 10-17 anda #$FE ;isolate wow beq L5178 ;none are lit, branch to check specials jmp L5297 ;wow are lit on 8 bank, branch to check L5178: lda $001A ;lamps 8-f beq L517F ;none of the wows are lit, branch jmp L52B3 ;branch to award wow L517F: lda $002E ;blink 20-27 anda #$01 ;bonus 8 beq L5188 ;not blinking, branch jmp L52CD ;bonus 8 was blinking L5188: ldb $002A ;blink 0-7 andb $0076 ;drop row bne L5198 ;got the blinking one, branch ldb $0076 ;get drop row comb ;flip for mask andb $0019 ;clear lamp from drop stb $0019 ;save lamp 0-7 (extinguishes drop lamp) jmp L5230 ;score drop based on row L5198: lda $0025 ;flags 60-67 anda #$20 ;isolate flag 65, lock ready beq L51A4 ;flag 65 clear, branch lda $02F5 ;8 bank drop register coma ;flip if exp=0 bne L51D0 ;not complete, branch else bne L5131 ;convenient return endif ;shave a byte later L51A4: lda $0023 ;flags 50-57 ora #$80 ;set flag 57, 8 bank completed sta $0023 ;save flags 50-57 cmpb #$80 ;was it drop row #$80 (8 ball)? bne L51B1 ;no, branch jmp L523F ;yes, branch to handle 8 ball ;get correct bonus lamp lit L51B1: lda $002A ;blink 0-7 clrb ;setup B as the bonus lamp clc ldx #$0008 ;use X as a counter L51B8: rora ;A is holding the blink rolb ;this will get the blink from A to corresponding in B dex ;counter-- bne L51B8 ;not done, keep going orb $001D ;add the blink into lamps 20-27 stb $001D ;save lamps 20-27 (bonus) inc $007A ;increase bonus level if fix=0 GOSUB L51D1 ;do something with lamps/bonus levels ?? else bsr L51D1 ;shave a byte endif ;fix swi ;start pigs sound_play_primary L5FC8 bsr L5230 ;score drop based on row jmp L57C5 if exp=0 L51D0: rts ;return endif ;shave a byte ;light random inlanes/top bumper depending on bonus level and random results L51D1: swi ;start pigs checklampvalue $62 ;?? bne L522E ;flag 62 set, branch to return lda $004C ;continuously decrementing counter anda #$3F ;cap at 63 ldb $007A ;bonus level cmpb #$08 ;maxed? bge L520A cmpb #$06 bge L51FC cmpb #$04 bge L51EC ldb #$07 bra L520B L51EC: ldb #$06 cmpa #$15 ble L520B ldb #$05 cmpa #$2A ble L520B ldb #$03 bra L520B L51FC: ldb #$04 cmpa #$15 ble L520B lsrb cmpa #$2A ble L520B lsrb bra L520B L520A: clrb L520B: aslb aslb aslb aslb aslb lda $001F ;lamps 30-37 anda #$1F ;clear top bumper, left/right inlanes sta $001F ;save lamps 30-37 orb $001F ;add lamp in stb $001F ;save lamps 30-37 swi ;start pigs checklampvalue $6e ;check dip 7, balls per game, on=5 off=3 beq L522E ;off, 3 balls per game, branch lda $004C ;continuously decrementing timer bmi L522E ;b7 set, branch asla asla asla asla asla ora #$1F ;setup to preserve lamps 30-34 anda $001F ;pseudo-random lighting of top bumper and inlanes sta $001F ;save lamps 30-37 L522E: rts ;return if exp=0 ;unreferenced L522F: rts endif ;exp ;score drop based on switch row ;drop score is ball number*1k (3=3000, 5=5000, 8=8000, etc) L5230: lda #$01 ;setup row 0 ora $004B ;add to virtual col7 action register sta $004B ;save vc7 action register lda $0076 ;get saved row of drop L5238: inc $0070 ;1k score queue lsra ;keep adding score bne L5238 ;not done, keep going rts ;return L523F: lda #$80 ;setup 8000 bsr L5230 ;score 8000 swi ;start pigs rcflagset ;set pigs multiprocessing flag lampbvalueon $20 ;bonus target 8/left bank lampbvalueoff $07 ;drop target 8 loadb $33 ;setup bonus 3/4/7/8 blink storebmem $001d ;save lamps 20-27 loadb $ff ;setup all blink storebmem $002e ;save blink 20-27 checklampvalue $85 ;check dip 30, super bonus lites with 8 ball hit (on) or 9 ball hit (off) ifcleargoto L525A ;set to 9 ball, branch lampbvalueon $5e ;set super 77k lit flag L525A: loadb $01 ;set bonus level back to 1 storebmem $007a ;save bonus level lampbvalueon $62 ;completed 1-8 ila ;clear pigs multiprocessing flag ldx #$0019 ;light a drop jsr L5346 ;light a drop, wow, or special depending on X swi ;start pigs rcflagset ;set pigs multiprocessing flag checklampvalue $84 ;check dip 29, light wow on 8 bank, on=8 ball off=9 ball ifcleargoto L5286 ;set to lite wow with 9 ball, branch blinklampbvalueon $2b ;1-8 lites special checklampvalue $63 ;check wow inhibit flag ifsetgoto L5286 ;set, branch loadb $16 ;setup timer storebmem $005b ;walk wow routine lampbvalueon $66 ;set walk wow flag ila ;clear pigs multiprocessing flag ldx #$001A ;light a wow jsr L5346 ;light a drop, wow, or special depending on X swi ;start pigs rcflagset ;set pigs multiprocessing flag L5286: cont_solenoid_on_ef ;8 bank reset enable_solenoid_0f $0f ;time waster/controls 8 bank reset pulse enable_solenoid_0f $00 ;time waster cont_solenoid_off_ef ;8 bank reset if exp=0 loadb $00 ;clear b else clearb ;loadb $00 endif ;exp storebmem $0045 ;clear column 1 action register storebmem $02f5 ;clear 8 bank drop register lampbvalueoff $57 ;clear 8 bank completed flag return ;return ;check wow on 8 bank L5297: lda $2c ;blink 10-17 anda #$fe ;isolate specials bne L52B3 ;one is blinking, branch lda $001B ;lamps 10-17 anda #$FE ;clear specials anda $0076 ;saved drop row beq L52B3 ;no match, branch ora #$01 ;setup bonus 9 blink sta $002C ;save in blink 10-17 lda #$5A ;setup time factor sta $0060 ;save in vc6r3, timeout flashing wows/specials/9 ball swi ;start pigs rcflagset ;set pigs multiprocessing flag gosub L5A3D ;check if wow should be awarded ila ;clear pigs multiprocessing flag L52B3: lda $002B ;blink 10-17 bne L52CD ;some are blinking, branch lda $001A ;lamps 8-f anda $0076 ;saved drop row beq L52CD ;no match, branch sta $002B ;save hit row in blink 8-f lda #$5A ;setup time factor sta $0060 ;save in vc6r3, timeout flashing wows/specials/9 ball swi ;start pigs rcflagset ;set pigs multiprocessing flag lampbvalueon $63 ;set (special) flag ?? gosub L59DF ;collect wow ila ;clear pigs multiprocessing flag bra L5318 L52CD: lda $002A ;blink 0-7 bne L5318 ;none lit for 9 ball, branch lda $0019 ;lamps 0-7 anda $0076 ;saved drop row beq L5318 ;no match, branch sta $002A ;save hit row in blink 0-7 lda #$5A ;setup time factor sta $0060 ;save in vc6r3, timeout flashing wows/specials/9 ball swi ;start pigs rcflagset ;set pigs multiprocessing flag sound_play_primary L5F69 ;play 9 ball hit sound lampbvalueon $5c ;set 9 ball flag loadb $0a ;setup time factor storebmem $0062 ;save in vc6r1, launch balls for multiball checklampvalue $84 ;check dip 29, bank wow lites with 8 ball hit (on) or 9 ball hit (off) ifsetgoto L5304 ;light with 8 ball hit blinklampbvalueon $2b ;blink the light special lamp checklampvalue $63 ;check wow inhibit flag ?? ifsetgoto L5304 ;set, skip lighting wow lampbvalueon $66 ;set 8 bank wow lit ila ;clear pigs multiprocessing flag lda #$16 ;setup time factor sta $005B ;save in vc5r0, walk 8 bank wow ldx #$001A ;lamps 8-f, light a wow if fix=0 GOSUB L5346 ;light a drop, wow, or special depending on X else bsr L5346 ;light a drop, wow, or special depending on X endif ;fix, shave a byte swi ;start pigs rcflagset ;set pigs multiprocessing flag L5304: blinklampbvalueon $10 ;bonus 9 checklampvalue $85 ;check dip 30, super bonus 77k lites with 8 ball (on) or 9 ball (off) ifsetgoto L530D ;8 ball, branch lampbvalueon $5e ;set super 77k lit L530D: ila ;clear pigs multiprocessing flag jsr L5230 ;score drop based on row lda $02F5 ;8 bank drop register coma ;flip beq L5336 ;they're all down, branch rts ;return L5318: jsr L5230 ;score drop based on row lda $02F5 ;8 bank drop register coma ;flip beq L5322 ;they're all down, branch rts ;return L5322: lda $001B ;lamps 10-17 anda #$FE ;clear bonus 9 bne L5336 ;some special is lit, branch swi ;start pigs checklampvalue $2b ;1-8 lites special beq L5336 ;not lit, branch ldx #$001B ;light a special if fix=0 GOSUB L5346 ;light a drop, wow, or special depending on X else bsr L5346 ;light a drop, wow, or special depending on X endif ;fix, shave a byte swi ;start pigs lampbvalueoff $2b ;1-8 light special L5336: inc $7a lda $7a cmpa #$09 bne L5343 lda #$02 sta $007A L5343: jmp L57C5 ;light a drop, wow, or special lamp depending on X L5346: lda #$01 ;ensure at least one lamp set ldb $004C ;get rolling counter andb #$07 ;cap to 7 beq L5352 ;it happens to be 0, use #$01 L534E: asla ;shift lamp decb ;counter-- bne L534E ;not done, keep going L5352: cpx #$001B ;are you setting the special lamps? bne L5360 ;no, branch to save the wow directly cmpa #$01 ;is the factor #$01 (which cannot light on the special lamps) beq L5346 ;bad factor, find another one ldb $001B ;lamps 10-17 andb #$01 ;preserve bonus 9 lamp aba ;add in factor L5360: sta $00,x ;save lamps rts ;return ;c4r2 advance spinner standup L5363: checkactivegame ;return if not in an active game addtoscoreq $37 ;score enqueue 7000 ila ;clear pigs multiprocessing flag L5367: jsr L589E ;advance spinner swi ;start pigs checklampvalue $2f ;spinner 1600 beq L5367 ;not lit, keep going until lit rts ;return ;loop rollunder, lock lane exit L5370: checkactivegame ;return if not in an active game checklampvalue $5d ;running collect routine from single drop or this routine? ifsetreturn ;yes, return lampregbon ;set flag 5d addtoscoreq $33 ;enqueue score 3000 ila ;clear pigs multiprocessing flag lda $001C ;lamps 18-1f tab ;save lamps anda #$F8 ;clear all but loop lamps cmpa #$F8 ;all loop lamps lit? bne L5382 ;no clra ;all loop lamps were lit, clear them all L5382: ora #$07 ;make sure byte shift has filled bits ?? sta $007F ;save in temp loop storage andb #$07 ;clear loop lamps from saved lamp byte stb $001C ;save bra L53A5 ;virtual c5r7 advance loop value one step L538C: ila ;clear pigs multiprocessing flag lda $001C ;lamps 18-1f tab ;save lamp byte andb #$07 ;clear all loop values, preserve multipliers orb $002D ;capture any blinking values anda #$F8 ;clear multipliers beq L53AA ;no loop lamps lit blt L53B1 pshb ;save multiplier byte on stack swi ;start pigs checklampvalue $5f ; pulb ;restore B bne L53B1 asla ;advance loop value aba ;combine with multipliers sta $001C ;save in lamps 18-1f L53A5: lda #$04 ;wind timer for sta $0054 ;virtual col5 row 7 rts ;return L53AA: ora #$08 ;set loop lamp 1b 10k lit aba ;combine with multipliers sta $001C ;save in lamps 18-1f bra L53A5 ;exit L53B1: pshb ;save B swi ;start pigs lampbvalueon $5f ;set flag pulb ;restore B asla ;move the loop lamp ora #$08 ;set the 10k lamp aba ;combine with multipliers sta $001C ;save in lamps 18-1f lda $001C ;lamps 18-1f anda #$F8 ;clear multipliers cmpa #$F8 ;all loop lamps lit? beq L53C8 ;yes, branch cmpa $007F ;compare to saved bls L53A5 ;exit L53C8: swi ;start pigs rcflagset ;set pigs multiprocessing flag if exp=0 lampbvalueoff $5f ;clear flag 5f lampbvalueoff $5d ;clear flag 5d else lampoff $5f,$5d endif ;exp return ;return ;c2r4 upper left loop single drop L53CF: checkactivegame ;return if not in an active game checklampvalue $5d ;test single drop/outlane/loop collection processing ifsetreturn ;return if flag 5d set lampregbon ;set flag 5d, single drop processing sound_play_primary L5E9D ;single drop ila ;clear pigs multiprocessing flag clra ;setup 00 psha ;save swi ;start pigs checklampvalue $1f ;loop 173k bne L53F6 ;it's lit, branch to collect 173k swi ;start pigs checklampvalue $1e ;loop 40k bne L53FA ;it's lit, branch to collect 40k swi ;start pigs checklampvalue $1d ;loop 30k bne L53FE ;it's lit, branch to collect 30k swi ;start pigs checklampvalue $1c ;loop 20k bne L5402 ;it's lit, branch to collect 20k swi ;start pigs checklampvalue $1b ;loop 10k bne L5406 ;it's lit, branch to collect 10k if exp=0 JUMP L540A ;none were lit, collect 5k else bra L540A ;none were lit, collect 5k endif ;exp, shave a byte! ;setup collect 173k L53F6: pula ;restore A lda #$85 ;setup score 133k psha ;save A ;setup collect 40k L53FA: pula ;restore A adda #$0A ;add 10k psha ;save A ;setup collect 30k L53FE: pula ;restore A adda #$0A ;add 10k psha ;save A ;setup collect 20k L5402: pula ;restore A adda #$0A ;add 10k psha ;save A ;setup collect 10k L5406: pula ;restore A adda #$05 ;add 5k psha ;save A ;setup collect 5k L540A: pula ;restore A adda #$05 ;add 5k sta $007E ;save # of lda $001C ;lamps 18-1f anda #$F8 ;clear all but loop lamps ora $002D ;set all lit loop lamps to blink sta $002D ;save blinking lamps 18-1f lda #$2D ;wind timer sta $0061 ;set virtual col6 row2 rts ;return ;virtual c6r2, collect loop value L541C: ila ;clear pigs multiprocessing flag lda $001C ;lamps $18-$1f ora $002D ;add them to blink lamps $18-$1f sta $001C ;save lamps $18-$1f clr $002D ;clear all blink lamps $18-$1f L5426: lda $001C ;lamps $18-$1f anda #$07 ;clear loop lamps ora $002D ;add any multipliers back from blink lamps ora #$80 ;set 173k lamp sta $001C ;save lamps $18-$1f L5430: lda #$02 ;wind timer sta $005F ;set virtual col6 row4 (routine below) rts ;return ;virtual c6r4 collect loop value stored in $7e L5435: loadbmem $007e ;get stored value bacomp $00 ;is it zero? eqgoto L5445 ;yes ixdw $007e ;reduce stored value score $31 ;score 1000 sound_play_primary L5F0D ;loop score sound L5445: ila ;clear pigs multiprocessing flag lda $001C ;lamps $18-$1f anda #$F8 ;clear multipliers cmpa #$08 ;is only 10k loop lit? bne L5460 ;no tst $007E ;see if any stored value left bne L5426 ;there is, go score it swi ;start pigs rcflagset ;set pigs multiprocessing flag if exp=0 lampbvalueoff $5f ;advance loop flag lampbvalueoff $5d ;single drop flag else lampoff $5f,$5d endif ;exp if switch=1 reset_single_drop: check_switch $14 ;single drop - no need to reset it if it's not down! ifclearreturn ;not down, return endif ;switch cont_solenoid_on_7f ;reset single drop enable_solenoid_0f $08 ;use this as a timer for the continuous solenoid enable_solenoid_0f $00 ;time waster cont_solenoid_off_7f ;finish resetting single drop (this might need to be longer) return ;return L5460: clc ;ensure clear bit gets shifted into loop value lamps rora ;contains $1c loop value lamps ldb $001C ;get lamps 18-1f andb #$07 ;get multiplier lamps orb $002D ;add in blinking lamps aba ;combine sta $001C ;save lamps 18-1f bra L5430 ;branch to reset timer to collect loop value L546D: gosub L588A ;flip outlanes and 3 bank 7k if pseudo-random number is odd xloadgoto L51D1 gosub L5929 gosub L58DA ;swap top 3 bank wows if lit gosub L595C gosub L58FB return ;spinner L5480: checkactivegame ;return if not in an active game gosub L546D ; lampbvalueoff $5b ;clear flag that 546d routine done checklampvalue $51 ;spinner active ifsetgoto L549F ;spinner lamps active, branch lampregbon ;set flag 51 ila ;clear pigs multiprocessing flag lda $001E ;lamps 28-2f anda #$F0 ;preserve spinner lamps 2c-2f sta $007B ;save beq L54D8 ;none lit, branch lda $001E ;lamps 28-2f anda #$0F ;clear spinner lamps 2c-2f ora #$10 ;set spinner lamp 2c sta $001E ;save in lamps 28-2f bra L54D8 ;branch L549F: ila ;clear pigs multiprocessing flag lda $007B ;get saved lamps beq L54D8 ;no lamps, branh ldb $001E ;lamps 28-2f andb #$F0 ;preserve spinner lamps 28-2f bitb #$10 ;lamp 2c lit? beq L54B3 ;no, branch cba ;compare current lamps to saved lamps bls L54B3 bsr L54CA ;animate the spinner lamps bra L54D8 ;score the spinner L54B3: swi ;start pigs rcflagset ;set pigs multiprocessing flag loadb $2c ;start with spinner 1 lamp L54B7: checklampregbon ;lamp on? ifsetgoto L54C6 ;yes, branch binc ;move to next spinner lamp bacomp $30 ;done with spinner lamps? notegoto L54B7 ;no, keep going ila ;revert to assembly bsr L54CA ;animate the spinner lamps bra L54D8 ;score the spinner L54C6: lampregboff ila ;clear pigs multiprocessing flag bra L54D8 ;score the spinner ;animate the spinner lamps L54CA: lda $001E ;lamps 28-2f tab ;save anda #$F0 ;preserve spinner lamps 2c-2f andb #$0F ;preserve lamps 28-2b asla ;shift the spinner lamp one up ora #$10 ;set spinner lamp 28 aba ;combine the nibbles sta $001E ;save lamps 28-2f rts ;return ;score spinner L54D8: if spinnerblit=1 blit: lda $13 anda #$f0 cmpa #$f0 bne already_blitting setup_blit: clra sta $13 already_blitting: lda $13 adda #$01 daa sta $13 endif ;spinnerblit lda #$16 ;wind spinner timeout timer sta $0055 ;virt col5 row 6 timer L54DC: swi ;start pigs rcflagset ;set pigs multiprocessing flag score $21 ;score 100 sound_play_primary L5ECF ;spinner 100 sound loadbmem $007b ;look at saved spinner lamps bacomp $00 ;none? eqreturn ;no spinner lamps lit - return score $23 ;score additional 300 (400 total) sound_play_primary L5F37 ;spinner 400/1600 sound loadbmem $007b ;look at saved spinner lamps bacomp $10 ;look at spinner 1, 400 eqreturn ;that was the only one lit, return score $25 ;score additional 800 (900 total) sound_play_primary L5EF1 ;spinner 900 sound loadbmem $007b ;look at saved spinner lamps bacomp $30 ;look at spinner 1 and 2, (400, 900) eqreturn ;those were the only ones lit, return score $27 ;score additional 700 (1600 total) sound_play_primary L5F37 ;spinner 400/1600 sound loadbmem $007b ;look at saved spinner lamps bacomp $70 ;look at spinner 1, 2, and 3 (400, 900, 1600) eqreturn ;those were the only ones lit, return score $29 ;score additional 900 (2500 total) sound_play_primary L5F7B ;spinner 2500 sound return ;return ;c3r6 pop bumper - score 100 when nothing lit on spinner or spinner value L5510: checkactivegame ;return if not in an active game xloadgoto L51D1 ;move lit lamps gosub L588A ;flip outlanes and 3 bank 7k if pseudo-random number is odd checklampvalue $51 ;spinner active flag ifsetgoto L54DC ;score spinner ila ;clear pigs multiprocessing flag lda $001E ;lamps 28-2f anda #$F0 ;isolate spinner lamps sta $007B ;save original lamps if exp=0 JUMP L54DC ;score spinner else bra L54DC ;score spinner endif ;exp, shave a byte! ;right 3 bank top L5526: checkactivegame ;return if not in an active game checklampvalue $4f ;check drop flag ifsetreturn ;already downed, return lampregbon ;set flag 4f checklampvalue $39 ;right bank top WOW ifsetgosub L59DF ;wow was lit, collect checklampvalue $78 ;check dip 17, advance spinner off=center only, on=outside 2 (manual backwards) ifsetgosub L589E ;dip 17 on, branch to subroutine to advance spinner goto L5554 ;process right 3 bank ;right 3 bank middle L5538: checkactivegame ;return if not in an active game checklampvalue $4e ;check drop flag ifsetreturn ;already downed, return lampregbon ;set flag 4e checklampvalue $78 ;check dip 17, advance spinner off=center only, on=outside 2 (manual backwards) ifcleargosub L589E ;dip 17 off, branch to subroutine to advance spinner goto L5554 ;right 3 bank bottom L5545: checkactivegame ;return if not in an active game checklampvalue $4d ;check drop flag ifsetreturn ;already downed, return lampregbon ;set flag 4d checklampvalue $38 ;rt bank bottom wow ifsetgosub L59DF ;wow was lit, go collect checklampvalue $78 ;check dip 17, advance spinner off=center only, on=outside 2 (manual backwards) ifsetgosub L589E ;dip 17 on, branch to subroutine to advance spinner L5554: checklampvalue $28 ;left bank 7k/l outlane ifcleargoto L555B ;not lit, branch addtoscoreq $36 ;score 6000 L555B: addtoscoreq $31 ;score 1000 ;see if all 3 drop flags set (bank down) L555D: if spigs=0 checklampvalue $4f ;rt 3 bank top flag ifclearreturn ;not set, return checklampvalue $4e ;rt 3 bank middle flag ifclearreturn ;not set, return checklampvalue $4d ;rt 3 bank bottom flag ifclearreturn ;not set, return else matchpattern $4f,$4e,$4d,$07 notereturn endif ;spigs checklampvalue $75 ;dip 14, off=both banks required, on=one bank required ifsetgosub L5749 ;dip 14 on, only only 1 bank down required L556B: goto L55E7 ;reset right 3 bank L556E: enable_solenoid_02 $0a ;reset right 3 bank enable_solenoid_0f $00 ;time waster ;clear right 3 bank drop flags if exp=0 lampbvalueoff $4f ;top lampbvalueoff $4e ;middle lampbvalueoff $4d ;bottom else lampoff $4f,$4e,$4d ;t/m/b endif ;exp ila ;clear pigs multiprocessing flag sei ;prevent interrupts lda $0046 ;switch col2 action register anda #$F8 ;clear rt 3 bank switches sta $0046 ;save switch col2 action register cli ;allow interrupts rts ;return ;top dead bumper L5582: checkactivegame ;return if not in an active game addtoscoreq $25 ;add 500 to score queue checklampvalue $35 ;top bumper lit for spot number target? ifsetgosub L5639 ;yes, go spot number target return ;[unecessary] return ;top 3 bank left L558B: checkactivegame ;return if not in an active game checklampvalue $4c ;check drop flag ifsetreturn ;already downed, return lampregbon ;set flag $4c checklampvalue $2a ;top bank wow ifsetgosub L59DF ;wow was lit, go collect checklampvalue $78 ;check dip 17, advance spinner off=center only, on=outside 2 (manual backwards) ifsetgosub L589E ;dip 17 on, branch to subroutine to advance spinner goto L55B9 ;top 3 bank middle L559D: checkactivegame ;return if not in an active game checklampvalue $4b ;check drop flag ifsetreturn ;already downed, return lampregbon ;set flag $4b checklampvalue $78 ;check dip 17, advance spinner off=center only, on=outside 2 (manual backwards) ifcleargosub L589E ;dip 17 off, branch to subroutine to advance spinner goto L55B9 ;top 3 bank right L55AA: checkactivegame ;return if not in an active game checklampvalue $4a ;check drop flag ifsetreturn ;already downed, return lampregbon ;set flag $4c checklampvalue $3a ;top bank right wow ifsetgosub L59DF ;wow was lit, go collect checklampvalue $78 ;check dip 17, advance spinner off=center only, on=outside 2 (manual backwards) ifsetgosub L589E ;dip 17 on, branch to subroutine to advance spinner L55B9: checklampvalue $31 ;right bank 7k/right outlane ifcleargoto L55C0 ;not lit, branch addtoscoreq $36 ;score 6000 L55C0: addtoscoreq $31 ;score 1000 ;see if all 3 drop bank flags set (bank down) L55C2: if spigs=0 checklampvalue $4c ;left ifclearreturn ;not set, return checklampvalue $4b ;middle ifclearreturn ;not set, return checklampvalue $4a ;right ifclearreturn ;not set, return else matchpattern $4c,$4b,$4a,$07 notereturn endif ;spigs checklampvalue $75 ;dip 14, off=both banks required, on=one bank required ifsetgosub L5749 ;dip 14 on, one bank required goto L55E7 ;reset top 3 bank L55D3: enable_solenoid_03 $0a ;reset top 3 bank enable_solenoid_0f $00 ;time waster if exp=0 lampbvalueoff $4c lampbvalueoff $4b lampbvalueoff $4a else lampoff $4c,$4b,$4a endif ;exp ila ;clear pigs multiprocessing flag sei ;prevent interrupts lda $0046 anda #$8F sta $0046 cli ;allow interrupts rts ;return L55E7: loadbmem $0022 ;flags 48-4f aandb $fc ;isolate flags 4b-4f bacomp $fc ;flags 4b-4f set? notereturn ;no, return L55EF: checklampvalue $75 ;check dip 14 ifcleargoto L55FF ;dip 14 off, only one bank needed loadbmem $004c ;continuously decrementing counter aandb $01 ;look for odd number eqgoto L556E ;it's even, branch to reset right 3 bank goto L55D3 ;it's odd, branch to reset top 3 bank L55FF: gosub L5749 gosub L55D3 goto L556E ;reset right 3 bank ;right outlane L5608: checkactivegame ;return if not in an active game addtoscoreq $33 ;enqueue score 3000 checklampvalue $31 ;right outlane if exp=0 ifsetgoto L53CF ;score single drop return ;return else goto L5616 ;branch to score single drop & return endif ;exp, shave a byte! ;left outlane L5611: checkactivegame ;return if not in an active game addtoscoreq $33 ;enqueue score 3000 checklampvalue $28 ;left outlane L5616: ifsetgoto L53CF ;score single drop return ;return ;right inlane L561A: checkactivegame ;return if not in an active game if fix=0 addtoscoreq $25 ;score 500 endif ;fix checklampvalue $36 ;right inlane if fix=0 ifsetgosub L5639 ;spot number return ;return else goto L5628 ;shave a byte endif ;fix ;left inlane L5623: checkactivegame ;return if not in an active game if fix=0 addtoscoreq $25 ;score 500 endif ;fix checklampvalue $37 ;left inlane L5628: ifsetgosub L5639 ;spot number if fix=1 addtoscoreq $25 ;score 500 endif return ;return ;left sling ;right sling L562C: checkactivegame ;return if not in an active game addtoscoreq $11 ;enqueue score 10 L562F: xloadgoto L51D1 gosub L58DA ;swap top 3 bank wows if lit gosub L588A ;flip outlanes and 3 bank 7k if pseudo-random number is odd return ;return ;spot number target L5639: gosub L546D ;move some lamps around the playfield ?? ila ;clear pigs multiprocessing flag ldb $007A ;bonus level subb #$0A ;subtract to get drop target to fell comb ;flip jmp L585F ;trigger number drop ;game over L5645: if exp=0 lampbvalueoff $40 ;clear game starting flag cont_solenoid_off_flipper ;flipper relay ($bf) lampbvalueoff $33 ;tilt else cont_solenoid_off_flipper lampoff $40,$33 endif ;exp lampbvalueon $32 ;game over update_match sound_play_primary L5E74 ;game over sound gosub L16F0 ;check for match xloadgoto L170A ;check for hstd enable_solenoid_0f $ff ;time waster (did stern EVER use their own 'delay' function?) L5658: gosub L5B53 ;eject ball from saucer enable_solenoid_0f $3c ;time waster enable_solenoid_0f $00 ;time waster ila ;clear pigs multiprocessing flag if exp=0 lda #$00 ;setup to clear action register else clra endif ;shave a byte sta $0048 ;save col 4 action register L5664: lda $0043 ;col 4 history register anda #$10 ;isolate left outhole bne L5672 ;branch if set swi ;start pigs dispatch ;process switches lda $43 ;col 4 history register if exp=0 anda #$80 ;shooter lane switch beq L5664 ;not set, branch else bpl L5664 endif ;exp shave 2 bytes L5672: sei ;prevent interrupts lda $0044 ;col 0 action register anda #$DF ;isolate the credit button sta $0044 ;clear cli ;allow interrupts swi ;start pigs rcflagset ;set pigs multiprocessing flag clearplayflags ;remove the playfield status lamps at the end of the game if exp=0 lampbvalueon $32 ;game over lampbvalueon $40 ;set credit button flag else lampon $32,$40 ;game over, credit button flag endif ;exp loadb $05 ;setup attract mode timers storebmem $0058 ;attract mode display thread storebmem $0059 ;attract mode lamp thread return ;return ;attract mode display thread L568A: checklampvalue $40 ;credit button flag ifcleargoto L5658 loadb $5a ;setup timer L5691: storebmem $0058 ;save attract mode display thread timer checklampvalue $30 ;hstd ifsetgoto L569D ;currently showing hstd, branch to restore scores show_hstd ;show the hstd goto L569E ;finish up L569D: xfer_scores_to_displays ;put the scores from the previous game back on the displays L569E: ;comehere - add saucer eject code if fix=1 check_switch $21 ifcleargoto saucerx enable_solenoid_07 $0a ;saucer enable_solenoid_0f $64 ;time waster enable_solenoid_0f $00 ;time waster saucerx: endif ;fix checklampvalue $67 ;active ball ifclearreturn ;not set, return gosub L56E1 ;clear all virtual switch column timers $54-$63 and $49-$4a return ;return ;attract mode lamp thread L56A5: ila ;clear pigs multiprocessing flag lda #$04 ;setup timer sta $0059 ;save timer for this thread ldx #$0019 ;start with lamps 0-7 lda $0019 ;use the first lamps for the other columns lsra ;shift bne L56B4 ;ok to save, branch lda #$80 ;make sure one lamp set L56B4: sta $00,x ;save lamp inx ;next lamp cpx #$001F ;done with all lamps 0-2f? bne L56B4 ;no, keep going swi ;start pigs rcflagset ;set pigs multiprocessing flag goto L569E ;check for active game and kill timers ;check score queues, pending switches, and timed switch events L56C1: lda $6d ;1's queue ora $6e ;10's queue ora $6f ;100's queue ora $70 ;1k queue ora $71 ;10k queue ora $72 ;100k queue ora $56 ;virtual column 5 row 5 timer ora $5F ora $61 ora $49 ora $4A ora $4B beq L56E0 ;no pending events jsr L11AA ;process switches and score queues bra L56C1 ;keep going until all processed L56E0: rts ;return ;clear all virtual switch column timers $54-$63 and $49-$4a L56E1: ila ;clear pigs multiprocessing flag ldx #$0054 ;start at $54 L56E5: clr $00,x ;clear inx ;index++ cpx #$0064 ;done? bne L56E5 ;no, keep going clr $0049 ;clear virtual column 5 action register clr $004A ;clear virtual column 6 action register rts ;retrn ;virtual c7r7 replay 1 surpassed L56F4: bcdinc $02,$02e8 ;advance audit 16 goto L5706 ;award replay ;virtual c7r6 replay 2 surpassed L56FB: bcdinc $02,$02ea ;advance audit 17 goto L5706 ;award replay ;virtual c7r5 replay 3 surpassed L5702: bcdinc $02,$02ec ;advance audit 18 L5706: checklampvalue $6d ;dip 6, on=pay replays, off=don't ifsetgoto L5718 ;pay replay goto L5A77 ;branch to check if replay levels pay extra ball instead L570E: sound_play_secondary L5F37 ;spinner 400/1600 sound goto L5726 L5714: bcdinc $02,$02e6 ;audit 16 ; L5718: if exp=0 loadbmem $0092 aandb $20 ;check coin lockout notereturn ;it's set, max credits reached endif ;let the game knock even if no credit due, saves 6 bytes L571E: bcdinc $02,$02d4 enable_solenoid_05 $0a ;knocker L5724: enable_solenoid_0f $0a ;time waster L5726: loadbmem $0092 aandb $20 notereturn L572C: bcdinc $01,$02cf ;increase audit 5, current credits show_credits ;make sure credit display matches stored credits return ;return if exp=0 ;slam L5732: reboot ;reboot immediately endif ;exp ;tilt L5733: checkactivegame ;return if not in an active game cont_solenoid_off_flipper ;kill flippers ($bf) if exp=0 lampbvalueoff $67 ;clear active game flag lampbvalueon $33 ;tilt lampbvalueoff $55 ;spsa flag lampbvalueoff $29 ;kill shoot again (boo!) lampbvalueoff $34 ;kill 77k super bonus (boo!) lampbvalueoff $52 ;tilted ? else lampoff $67,$55,$29,$34,$52 lampon $33 ;tilt endif ;exp sound_play_primary L5EDF ;tilt sound ila ;clear pigs multiprocessing flag clr $02F6 ;? rts ;return ;bank down, advance multiplier L5749: sound_play_primary L5FAA ;advance multiplier sound ila ;clear pigs multiprocessing flag lda $001C ; ora $002D ;add in blinkers sta $001C ;save ldb $002D ;blink 18-1f andb #$07 ;isolate multipliers beq L5762 ;none are blinking, branch L5759: clr $002D ;clear blinkers 18-1f ldb #$20 orb $0049 ;setup col5 row2 action register directly stb $0049 ;save action register for row 5, safe multiplier/check wow L5762: anda #$07 ;isolate multipliers cmpa #$07 ;7x? bne L5769 ;no, advance multiplier rts ;return ;advance multiplier L5769: inca ;increase multiplier ldb $001C ;lamps 18-1f andb #$F8 ;clear multipliers aba ;combine with lamps 1b-1f sta $001C ;save if exp=0 lda $001C ;lamps 18-1f endif ;exp save 2 bytes - A currently contains the byte, why reload it? anda #$07 ;isolate multipliers sta $002D ;setup blink ldb #$5A ;setup timer to clear blink stb $0056 ;save rts ;return ;virtual c5r5 $56 clear blinking multiplier L577C: ila ;clear pigs multiprocessing flag lda $002D ;blink lamps 18-1f ora $001C ;lamps 18-1f sta $001C ;save in lamps 18-1f clr $002D ;clear all blink lamps 18-1f if exp=0 JUMP L5789 ;inefficient! endif ;exp, save 3 bytes! ;light 3 bank wows if dip 17 off @7x if exp5=0 L5789: swi ;start pigs checklampvalue $86 ;dip 31, 3 bank wow lites @6x (on) or 7x (off) bne L5797 ;dip 31 on, branch lda $001C ;lamps 18-1f anda #$07 ;isolate multipliers cmpa #$07 ;all 3 on? (1x + 2x + 4x = 7x) beq L57A0 ;yes, branch to light wow rts ;return ;light wows if dip 17 on @6x L5797: lda $001C ;lamps 18-1f anda #$07 ;isolate multipliers cmpa #$06 ;at least 6x? (2x + 4x = 6x) bge L57A0 ;yes (why not do it the same way as above but anda #$06?) rts else ;A contains $1c right now inca ;if the multiplier was 6x, it's now 7x, if it was 7x, it will become zero anda #$07 ;isolate multipliers ldb $29 ;dips 25-32 aslb ;dip 31 bpl sevenx ;it's off, test for zero cmpa #$07 ;this would be 6x beq L57A0 rts sevenx: tsta beq L57A0 ;it was zero, so the multiplier was 7x before the inca rts endif ;exp5 save some bytes for same functionality 23 vs. 17 ;light wows on 3 banks L57A0: swi ;start pigs rcflagset ;set pigs multiprocessing flag checklampvalue $56 ;wow flag ? ifsetreturn ;set, return lampregbon ;set flag 56 checklampvalue $63 ;wow inhibit ? ifsetreturn ;set, return lampbvalueon $3a ;light top bank rt wow return ;decrement multiplier L57AC: ila ;clear pigs multiprocessing flag lda $001C ;lamps 18-1f ora $002D ;get blinkers too sta $001C ;save lamps 18-1f clr $002D ;clear blinkers 18-1f anda #$07 ;isolate multipliers deca ;multiplier-- ldb $001C ;lamps 18-1f andb #$F8 ;clear multipliers aba ;add multipliers to lamp byte sta $001C ;save lamps 18-1f lda $001C ;get lamps 18-1f anda #$07 ;isolate multipliers rts ;return L57C5: jsr L1FBC swi ;start pigs rcflagset ;set pigs multiprocessing flag checklampvalue $65 ;lock ready? ifsetgoto L5849 lampbvalueon $57 ;set flag 57 lampbvalueoff $41 ;ensure flag 41 is off cont_solenoid_on_ef ;8 bank loadb $02 ;wind timer for eject hole on/off (this is a BAD way to do this) storebmem $005c ;save timer for virtual col6 row7 return ;return ;virtual c6r7 L57DA: cont_solenoid_off_ef ;8 bank checklampvalue $41 ;check re-entrant value notegoto L57E7 ;41 set, goto to next phase lampregbon ;set flag 41 loadb $05 ;wind timer storebmem $005c ;save timer for THIS routine return ;return L57E7: ila ;clear pigs multiprocessing flag if exp=0 lda #$00 else clra endif ;shave a byte! sta $0045 ;c1 action register sta $02F5 ;8 bank drop register lda $002E ;blink 20-27 cmpa #$FF ;all bonus lamps 1-8 blinking? beq L5811 ;yes, branch ldb #$01 ; tba ;put in A for comparison cmpa $007A ;bonus level beq L5802 ;level is 1, branch L57FC: aslb ;move the drop lamp inca ;increase test cmpa $007A ;compare to bonus level bne L57FC ;not there, keep going L5802: stb $002A ;save B as drop to blink clr $0019 ;clear all drop lamps ;correct lamp is blinking clra ;start fresh L5808: sec rola cmpa $002A bcs L5808 coma sta $0019 L5811: lda #$01 sta $007C L5815: swi ;start pigs lampbvalueoff $50 lda $007C cmpa $007A beq L583E lda #$01 tab cmpb $007C beq L582B L5825: asla incb cmpb $007C bne L5825 L582B: ora $02F5 ;add to 8 bank drop register sta $02F5 ;save 8 bank drop register inc $007C subb #$0A comb bsr L585F ;trigger number drop lda #$03 ;setup time factor sta $005A ;save in timer rts ;return L583E: lda $002A ;blink 0-7 coma ;flip anda $02F5 ;combine with drop register sta $02F5 ;save swi ;start pigs rcflagset ;set pigs multiprocessing flag L5849: lampbvalueoff $57 ;clear 8 bank complete flag checklampvalue $52 ;check tilt flag ifclearreturn ;not set, return goto L5B06 if exp=0 L5851: rts ;return endif ;unreferenced return ;vc5r1 add bonus ?? L5852: ila ;clear pigs multiprocessing flag lda $0023 ;flags 50-57 anda #$01 ;isolate flag 50 bne L5815 ;flag 50 set, branch dec $007C bra L5815 ;branch if exp=0 L585E: rts ;return endif ;unreferenced return ;trigger number drop, expects B to contain ball ;01=8, 02=7, 03=6, 04=5, 05=4, 06=3, 07=02, 08=01 L585F: if fix=1 stb $35 endif addb #$06 ;setup drop trigger solenoid cmpb #$07 ;is it the 8 ball? bne L5871 ;no, branch sei ;prevent interrupts lda $0045 ;col 1 action register ora #$80 ;virtually trip row 7, drop target 8 sta $0045 ;save col 1 action register cli ;allow interrupts clr $004D ;momentary solenoid timer rts ;return L5871: lda $004D ;momentary solenoid timer bne L5889 ;still timing, branch dec $004D ;momentary solenoid timer-- lda $0023 ;flags 50-57 ora #$01 ;set flag 50 sta $0023 ;save flags 50-57 lda #$F0 ;setup solenoid drop anda $0092 ;preserve continuous solenoids in A aba ;add the drop trigger solenoid sta $0092 ;save solenoids lda #$08 ;solenoid period sta $004D ;save in timer if fix=1 lda $35 ;get original ball # back ldb #$80 ;setup mask ball_loop: ;comehere deca beq mask_is_set lsrb bra ball_loop mask_is_set: sei ; andb $40 ;should get ones that are down already orb $45 ;add to action register stb $45 ;save action register - 1-7 no longer depend on solenoid working correctly cli endif ;fix L5889: rts ;return ;flip outlanes and 3 bank 7k if pseudo-random number is odd L588A: loadbmem $004c ;continuous decrementing counter aandb $01 ;odd number bacomp $00 ;no eqgoto L5899 ;branch lampbvalueon $31 ;right bank 7k/right outlane lampbvalueoff $28 ;left bank 7k/left outlane return ;return L5899: lampbvalueoff $31 ;right bank 7k/right outlane lampbvalueon $28 ;left bank 7k/left outlane return ;return ;advance spinner L589E: ila ;clear pigs multiprocessing flag swi ;start pigs checklampvalue $51 ;spinner active flag beq L58AA ;not active, branch lda $007B ;temp storage for spinner lamps ldb $001E ;lamps 28-2f bra L58AD L58AA: lda $001E ;lamps 28-2f tab ;save byte L58AD: anda #$F0 ;preserve spinner lamps asla ;move to next lamp ora #$10 ;ensure spin 1 lit sta $007B ;save andb #$0F ;clear spinner lamps aba ;combine sta $001E ;save lamps 28-2f rts ;return ;spinner timeout virt c5r6 L58BA: checklampvalue $5b ;check if restore needed ifcleargoto L58CB ;it is, branch if exp=0 lampbvalueoff $5b ;setup restore lampbvalueoff $51 ;clear spinner flag else lampoff $5b,$51 endif ;exp if spinnerblit=1 show_ball_in_play endif ;spinnerblit ila ;return to asssembly lda $001E ;lamps 28-2f anda #$0F ;clear spinner lamps 2c-2f sta $001E ;save lamps 28-2f rts ;return L58CB: lampregbon ila ;clear pigs multiprocessing flag lda $001E ;lamps 28-2f anda #$0F ;clear spinner lamps 2c-2f ora $007B ;add in the saved spinner lamps sta $001E ;save lamps 28-2f lda #$26 ;wind spinner timeout timer sta $0055 ;save in virtual c5r6 timer rts ;return ;swap top 3 bank wows if lit L58DA: checklampvalue $63 ;check wow inhibit flag ifsetreturn ;set, just return checklampvalue $2a ;top 3 bank left wow ifcleargoto L58E6 ;not lit, branch lampregboff ;clear top 3 bank wow lampbvalueon $3a ;light right 3 bank wow return ;return L58E6: checklampvalue $3a ;top 3 bank right wow ifsetgoto L58F0 ;lit, branch checklampvalue $39 ;right 3 bank top wow ifcleargoto L58F4 ;not lit, branch L58F0: lampregboff ;clear recently checked wow lamp bdec ;decrement B to next wow lamp lampregbon ;turn it on return ;return L58F4: checklampvalue $38 ;right 3 bank bottom wow ifclearreturn ;not lit, return lampregboff ;clear right 3 bank bottom wow lampbvalueon $2a ;light top 3 bank left wow return ;return L58FB: checklampvalue $62 ifclearreturn ila ;clear pigs multiprocessing flag L58FF: ldb $0019 beq L5928 lda $002A bne L5928 ldx #L595B L590A: lda $00,x cba beq L5912 dex bra L590A L5912: dex cpx #L5953 bne L591B ldx #L595B L591B: lda $00,x sta $0019 clrb L5920: incb lsra bne L5920 cmpb $007A blt L58FF L5928: rts ;return L5929: ila ;clear pigs multiprocessing flag L592A: ldb $001A ;lamps 08-0f (wow 1-8) beq L5953 ;none lit, branch to return lda $002B ;blink lamps 08-0f bne L5953 ;there's already some blinking ldx #L595B ;list of lamps L5935: lda $00,x cba beq L593D dex bra L5935 L593D: dex cpx #L5953 bne L5946 ldx #L595B L5946: lda $00,x sta $001A clrb L594B: incb lsra L594D: bne L594B cmpb $007A blt L592A L5953: rts L5954: db $04,$10,$40,$80,$20,$08 L595A: db $02 L595B: db $01 L595C: ila ;revert to assembly L595D: ldb $001B ;lamps 10-17 andb #$FE ;isolate lamps 11-17 (specials) beq L5953 ;none lit, branch lda $002C ;blink 10-17 anda #$FE ;isolate lamps 11-17 bne L5953 ;it's set already, branch ldx #L595A L596C: lda $00,x cba beq L5974 dex bra L596C L5974: dex cpx #L5953 bne L597D ldx #L595A L597D: lda $00,x ldb $001B ;lamps 10-17 andb #$01 ;isolate lamp 10, bonus 9 aba ;combine data with bonus 9 sta $001B ;save in lamps 10-17 clrb L5987: incb lsra bne L5987 cmpb $007A blt L595D rts L5990: checklampvalue $62 ifcleargoto L59A2 ila ;clear pigs multiprocessing flag lda $002A ;blink 0-7 beq L59A0 ;none (drops 1-8) clr $0019 ;make sure none of drops 1-8 are lit clr $002A ;clear blink 0-7 as well L59A0: swi ;start pigs rcflagset ;set pigs multiprocessing flag L59A2: checklampvalue $63 ;check flag 63 wow inhibit? ifcleargoto L59B8 ;flag 63 clear, branch if exp=0 lampbvalueoff $2a ;top bank right wow lampbvalueoff $3a ;top bank left wow lampbvalueoff $39 ;rt bank top wow lampbvalueoff $38 ;rt bank bottom wow else lampoff $2a,$3a,$39,$38 endif ;exp ila ;clear pigs multiprocessing flag clr $001A ;clear lamps 8-f (drop wows) clr $002B ;clear blink 8-f (drop wows) swi ;start pigs rcflagset ;set pigs multiprocessing flag L59B8: checklampvalue $64 ;? ifsetgoto L59CB ;blink bonus 9 clear all specials 2-8 ila ;clear pigs multiprocessing flag lda $001B ;lamps 10-17 ora $002C ;get blink 10-17 sta $001B ;save all lda $002C ;get blink 10-17 anda #$01 ;clear all but ball 1 sta $002C ;save blink 10-17 rts ;blink bonus 9 clear all specials 2-8 L59CB: ila ;clear pigs multiprocessing flag lda $001B ;lamps 10-17 anda #$01 ;isolate lamp 10, bonus 9 sta $001B ;save lamps 10-17 lda $002C ;blink lamps 10-17 anda #$01 ;isolate lamp 10, bonus 9 sta $002C ;save blink lamp rts ;return if exp=0 ;unreferenced L59D9: eqreturn ;if equal return ila ;clear pigs multiprocessing flag clr $001B ;clear all lamps 10-17 rts ;return endif ;exp, unreferenced routine, excise ;collect WOW L59DF: sound_play_primary L5ECF ;spinner 100 sound checklampvalue $63 ;wow inhibit flag? ifsetgoto L59FF bcdinc $02,$02e2 checklampvalue $2a ifsetgoto L5A10 checklampvalue $3a ifsetgoto L5A10 checklampvalue $39 ifsetgoto L5A10 checklampvalue $38 ifsetgoto L5A10 L59FF: bcdinc $02,$02e4 loadb $0f L5A05: checklampregbon ifsetgoto L5A10 bdec bacomp $07 notegoto L5A05 L5A0F: return ;wow being awarded, blink wow that is the award L5A10: lampregbblinkon loadb $5a ;wind timer storebmem $0060 ;save timer for virtual col6 row3 (turn off blinking wows) lampbvalueon $63 ;set flag, wow inhibit ? checklampvalue $7f ;dip 24, part of wow awards if exp=0 ifcleargoto $5A2A ;note error!!, probably supposed to be 5a2b else ifcleargoto L5A2B endif ;exp, correct error checklampvalue $7e ;dip 23, part of wow awards ifsetgoto L5A77 checklampvalue $7d ;dip 22, part of wow awards ifsetgoto L5A38 goto L5A77 L5A2B: checklampvalue $7e ;dip 23, part of wow awards ifsetgoto L5A38 goto L5A3A L5A32: addtoscoreq $44 ;40k L5A34: addtoscoreq $42 ;20k enable_solenoid_05 $0d ;knocker L5A38: addtoscoreq $43 ;20k L5A3A: addtoscoreq $44 ;40k return L5A3D: checklampvalue $87 ;dip 32, part of wow awards ifsetgoto L5A44 L5A42: lampbvalueon $64 L5A44: checklampvalue $7d ;dip 22, part of wow awards ifsetgoto L5A57 checklampvalue $7e ;dip 23, part of wow awards ifcleargoto L5A51 L5A4E: goto L5A32 L5A51: checklampvalue $7f ;dip 24, part of wow awards ifclearreturn L5A54: goto L5A34 L5A57: checklampvalue $7e ;dip 23, part of wow awards ifcleargoto L5A73 checklampvalue $87 ;dip 32, part of wow awards ifcleargoto L5714 L5A61: lxiw $0025 loadbmem $0025 aandb $03 bacomp $02 L5A6B: notegoto L5714 L5A6E: lampbvalueon $64 goto L5714 L5A73: lampbvalueon $63 enable_solenoid_05 $0a ;knocker L5A77: if exp=0 lampbvalueon $29 ;shoot again lampbvalueon $55 ;shoot again flag else lampon $29,$55 endif ;exp checklampvalue $6c ;dip 5, part of wow/replay awards ifsetgoto L5A85 loadb $01 goto L5A8E L5A85: loadbmem $02f6 bacomp $03 eqgoto L5A8E binc L5A8E: storebmem $02f6 return ;virtual c5r4 saucer decisions L5A92: checklampvalue $67 ;active game flag ifcleargoto L5B53 ;not in an active game, branch to eject ball from saucer checklampvalue $65 ;re-entry flag ifcleargoto L5AA4 ;not set, branch loadbmem $02f5 ;8 bank drop register bacomp $00 ;none collected/all up? eqgoto L5AB6 ;yes, branch L5AA4: lampbvalueon $65 ;set re-entry flag ;count # of set bits in 8 bank drop register ila ;clear pigs multiprocessing flag clc ;ensure an extra bit doesn't sneak in lda $02F5 ;8 bank drop register clrb ;clear bit count L5AAC: ;comehere incb ;count at least one bit asla ;shift 8 bank drop register bcc L5ABF ;found ball to spot, branch cmpb #$08 ;all 8 bits tested? bne L5AAC ;no swi ;start pigs rcflagset ;set pigs multiprocessing flag L5AB6: sound_play_primary L5F37 ;spinner 400/1600 sound lampbvalueoff $65 ;clear re-entry flag ila ;clear pigs multiprocessing flag jmp L57C5 L5ABF: jsr L56C1 ;check score queues, pending switches, and timed switch events jsr L585F ;trigger number drop lda #$14 ;wind timer sta $0057 ;set virtual column 5 row 4 timer (saucer decisions L5A92) rts ;return L5ACA: sound_play_primary L5F69 ;9 ball hit sound lampbvalueon $5c ;multiball starting flag loadb $3c ;wind timer for multiball eject storebmem $0062 ;save for multiball eject L5AD4: return ;return ;vc6r1 release balls for multiball L5AD5: checklampvalue $65 ;saucer flag ifsetgoto L5AE8 ;occupied, branch loadbmem $02f3 ;ball count in lock lane bacomp $00 ;none waiting? eqgoto L5AEE ;no, branch sound_play_primary L5F69 ;9 ball hit sound gosub L5B53 ;eject ball from saucer L5AE8: loadb $1e ;wind timer storebmem $0062 ;save return ;return L5AEE: lampbvalueoff $5c L5AF0: return ;add a ball to lock lane status - assumes that the count in 2f3 is actually correct! L5AF1: lda $02f3 ;ball count in lock lane sec ;ball in top rola ;rotate in anda #$07 ;limit to first 3 bits sta $02F3 ;save rts ;return ;remove a ball from lock lane status L5AFC: lda $02F3 ;ball count in lock lane anda #$07 ;limit to first 3 bits and ensure a clear bit rotates in lsra ;rotate sta $02F3 ;save rts ;return ;lock lane/trough decisions L5B06: lampbvalueoff $52 checklampvalue $23 ;bonus 5/capture ifsetgoto L5B15 ;capture lit, branch loadbmem $02f3 ;ball count in lock lane bacomp $00 ;none? notegoto L5B53 ;eject ball from saucer L5B15: loadbmem $02f3 ;ball count in lock lane bacomp $07 ;all 3 there? eqgoto L5ACA ;yep, setup eject bacomp $03 ;saucer and mid switch? notegoto L5B2A ;no ;comehere loadbmem $0043 ;col 4 history register aandb $01 ;isolate row 0, outhole notegoto L5B32 ;ball in outhole, branch L5B2A: loadbmem $0043 ;col 4 history register aandb $09 ;isolate outhole and mid trough L5B2F: bacomp $09 ;both closed? notereturn ;no L5B32: blinklampbvalueon $29 ;shoot again lampbvalueoff $3c ;clear score flag checklampvalue $5c ifsetreturn L5B39: goto L5B3E ;put ball into shooter lane L5B3C: swi ;start pigs rcflagset ;set pigs multiprocessing flag L5B3E: enable_solenoid_06 $14 ;outhole enable_solenoid_0f $3c ;time waster enable_solenoid_0f $00 ;time waster ; if matrix=0 loadb $ff ;wind timer for this routine storebmem $0063 ;save in timer for virtual col6 row0 ; endif ;no relaunching! ila ;clear pigs multiprocessing flag sei ;prevent interrupts lda $0048 ;get current col 4 action register anda #$E6 ;clears 3 outhole switches sta $0048 ;col 4 action register cli ;allow interrupts rts ;return L5B53: if exp=0 lampbvalueoff $65 lampbvalueoff $52 else lampoff $65,$52 ;clear reentrancy flags for top lock and saucer endif ;exp xloadgoto L5AFC enable_solenoid_07 $0a ;saucer enable_solenoid_0f $64 ;time waster enable_solenoid_0f $00 ;time waster ila ;clear pigs multiprocessing flag sei ;prevent interrupts lda $0048 ;virtual column 6 action register anda #$9D ;clear spinner timeout, kill x blink, $5a routine sta $0048 ;save vc6 action register cli ;allow interrupts rts ;return if switchtest=0 ;see if a ball is in middle outhole (sw 36) L5B6A: lda $0043 anda #$08 rts ;return ;see if ball is in right outhole (sw 33) unreferenced! L5B6F: lda $0043 anda #$01 rts ;return ;see if a ball is in the top lock lane (sw 39) L5B74: lda $0043 anda #$40 rts ;see if a ball is in middle lock lane (sw 38) L5B79: lda $0043 anda #$20 rts ;see if a ball is in the lock saucer (sw 34) L5B7E: lda $0043 anda #$02 rts endif ;exp, replaced all switch tests with function check_switch ;c4r7 shooter lane if matrix=0 L5B83: if exp=0 loadb $00 else clearb endif ;exp storebmem $0063 ;clear the outhole virtual switch timer return endif ;matrix ;c4r6 lock lane top L5B89: checklampvalue $57 ;8 ball complete ifsetreturn ;leave the ball here for now L5B8C: checklampvalue $52 ;lock lane top re-entrant? ifsetreturn ;yes, return lampregbon ;set flag 52 xloadgoto L5AF1 ;add a ball to the lock goto L5A92 ;saucer decisions L5B96: ila ;clear pigs multiprocessing flag lda $02F3 ;lock lane register cmpa #$03 ;saucer and mid switch? bge L5BCE ;comehere - question the usage of BGE again (This is Pfutz's influence on this code I believe) swi ;start pigs rcflagset ;set pigs multiprocessing flag goto L5B89 ;top lock lane ;lock lane saucer L5BA3: loadbmem $02f3 ;lock lane register bacomp $00 ;empty? notereturn ;no, return goto L5B89 ;top lock lane if exp=0 ;left outhole L5BAC: return ;middle outhole L5BAD: return endif ;save 2 bytes use 5AF0 instead ;outhole L5BAE: ; if spigs=0 checklampvalue $65 ifsetreturn checklampvalue $52 ifsetreturn checklampvalue $57 ifsetreturn ; else ; matchpattern $65,$52,$57,$00 ; notereturn ; endif ;spigs loadbmem $0048 ;switch column 4 action register aandb $62 ;isolate lock lane switches: saucer (02), mid (20), top (40) notereturn ;some of these switches have pending events, just return ila ;clear pigs multiprocessing flag clrb ;setup B to account for balls lda $0043 ;switch column 4 initial register anda #$3B ;isolate lock mid(20),left outhole(10),mid outhole(08),saucer (02),outhole (01) ;actually count the switches L5BC3: asla ;shift looking for bits adcb #$00 ;add just the (shifted) carry bit cmpa #$00 ;exhausted the byte? bne L5BC3 ;no, keep shifting and adding cmpb #$03 ;found 3 balls? beq L5BCF ;yes, branch to end ball L5BCE: rts ;return ;outhole valid, process end of ball L5BCF: swi ;start pigs rcflagset ;set pigs multiprocessing flag gameoverreturn ;ignore if game over checklampvalue $49 ;check outhole routine rentrancy flag ifsetreturn ;already running, return lampregbon ;set flag $49, outhole routine already running ;virtual c6r5 ball end delay L5BD6: xloadgoto L56C1 ;check score queues, pending switches, and timed switch events checklampvalue $5d ;single drop processing ifsetgoto L5BE8 ;set, set timer to allow that to end/reenter this routine checklampvalue $51 ;spinner active ifsetgoto L5BE8 ;set, set timer to allow that to end/reenter this routine checklampvalue $57 ;8 bank processing ifcleargoto L5BEE ;not set, branch to ball end L5BE8: ila ;clear pigs multiprocessing flag lda #$05 ;wind timer sta $005E ;setup virtual c6r5 $5bd6 rts ;return L5BEE: xloadgoto L1F94 ;handle background sound checklampvalue $3c ;check score flag ifcleargoto L5C84 ;no score, relaunch ball lampbvalueoff $67 ;clear active game flag gosub L56E1 ;clear all virtual switch column timers $54-$63 and $49-$4a checklampvalue $29 ;shoot again ifcleargoto L5C01 ;not lit, move to next player/ball/game over lampregbblinkon ;blink shoot again L5C01: checklampvalue $56 ;wow flag ? ifsetgoto L5C0E loadbmem $001c ;lamps 18-1f aandb $07 ;isolate bonus mutipliers goto L5C1A ;advance to next player/ball L5C0E: checklampvalue $6e ;dip 7, balls per game ifsetgoto L5C18 ;set on, 5 balls per game, branch L5C13: loadb $02 ;reset multiplier to 2x goto L5C1A L5C18: loadb $01 ;reset multiplier to 1x L5C1A: storebmem $007e gosub L5D7A sound_play_primary L5E74 ;game over sound ila ;clear pigs multiprocessing flag lda $7e ;get multiplier ora $1c ;lamps 18-1f sta $001C ;save lamps 18-1f swi ;start pigs rcflagset ;set pigs multiprocessing flag save_current_player update_current_player checklampvalue $55 ;spsa waiting flag ifcleargoto L5C4E ;not set blinklampbvalueon $29 ;spsa loadbmem $02f6 bacomp $00 eqgoto L5C4E ixdw $02f6 loadbmem $02f6 bacomp $00 notegoto L5C78 lampbvalueoff $55 save_current_player goto L5C78 L5C4E: loadbmem $0038 ;currently up player bxcomp $02ec ;compare to current # of players in game notegoto L5C75 ;branch to stay on same ball, move to next player checklampvalue $6e ;dip 7, balls per game ifsetgoto L5C64 ;dip 7, 5 balls per game, branch loadbmem $0037 ;current ball in play bacomp $03 ;on ball 3? goto L5C69 ;branch L5C64: loadbmem $0037 ;current ball in play bacomp $05 ;on ball 5? L5C69: eqgoto L5645 ;if end of last ball, branch to game over lxiw $0037 ;increase ball in play show_ball_in_play ;ensure ball in play correct on display if exp=0 loadb $00 ;reset currently up player to 'player 0' (advances to p1 below) else clearb endif ;exp storebmem $0038 ;currently up player L5C75: lxiw $0038 ;increase currently up player ;launch ball virtual c7r1 L5C78: restore_current_player bcdinc $02,$02e0 ;increase audit 12, # of balls played checklampvalue $5e ;super bonus lit flag? ifcleargoto L5C84 ;flag not set, branch lampbvalueon $34 ;77k super bonus L5C84: ila ;clear pigs multiprocessing flag clra ;setup initialization bytes of $00 ldx #$0000 ;setup initialization words of $0000 sta $001D ;blank lamps 20-2f stx $001A ;blank lamps 08-17 stx $002A ;blank blink 00-0f sta $002C ;blank blink 10-1f sta $002E ;blank blink 20-2f stx $0024 ;clear flags 58-67 deca ;setup initialization bytes of $ff sta $0019 ;light all lamps 0-7 (drops 1-8) sta $005D ;wind timer for virtual col6 row6 lda $0020 ;lamps/flags 38-3f anda #$F8 ;clear lamps 38-3a sta $0020 ;save lamps/flags 38-3f lda $0021 ;flags 40-47 anda #$03 ;clear all but flags 40/41 sta $0021 ;save flags 40-47 clrb ;setup B to determine where balls are if switchtest=0 jsr L5B7E ;check if ball is in the lock saucer else swi check_switch 34 endif ;exp beq L5CBC ;not in saucer, branch (this makes an assumption that balls can't be stuck above) sec ;ensure bit set rolb ;march it over if switchtest=0 jsr L5B79 ;see if a ball is in middle lock lane else swi check_switch 38 endif ;exp beq L5CBC sec rolb if switchtest=0 jsr L5B74 ;see if a ball is in the top lock lane else swi check_switch 39 endif ;exp beq L5CBC sec rolb L5CBC: stb $02F3 ;save the lock count L5CBF: swi ;start pigs rcflagset ;set pigs multiprocessing flag if exp=0 lampbvalueon $35 ;top bumper lampbvalueon $37 ;left inlane spot # lampbvalueon $36 ;right inlane spot # lampbvalueoff $2b ;1-8 lites special lampbvalueoff $2a ;top bank wow blinklampbvalueon $00 ;drop 1 lampbvalueoff $56 ;wow flag ? lampbvalueoff $57 ;8 bank flag ? lampbvalueoff $53 ;? else lampoff $35,$37,$36,$2b,$2a,$56,$57,$53 blinklampbvalueon $00 ;drop 1 endif ;exp checklampvalue $6e ;dip 7, balls per game ifsetgoto L5CE3 ;on, set to 5 balls per game, branch loadbmem $0037 ;current ball in play bacomp $03 ;on ball 3? notegoto L5CF5 ;no, branch goto L5CEB ;skip 5 ball test L5CE3: loadbmem $0037 ;current ball in play bacomp $05 ;on ball 5? notegoto L5CF5 ;no, branch L5CEB: show_hstd ;put hstd on all 4 displays enable_solenoid_0f $8c ;use as a timer enable_solenoid_0f $00 ;time waster if fix=0 goto L5CF5 ;unreferenced L5CF3: blinklampbvalueon $29 ;shoot again endif ;fix shave 5 bytes L5CF5: if exp=0 lampbvalueoff $33 ;tilt lampbvalueoff $3c ;? else lampoff $33,$3c endif ;exp xfer_scores_to_displays ;put scores back on displays update_current_player show_current_player if fix=0 gosub L5286 ;reset 8 bank gosub L556E ;reset right bank gosub L55D3 ;reset top bank else ;START loadbmem $0040 ;try 3 times to reset the bank bacomp $00 notegosub L5286 ;reset 8 bank loadbmem $0040 bacomp $00 notegosub L5286 ;reset 8 bank ;END loadbmem $0040 bacomp $00 notegosub L5286 ;reset 8 bank check_switch $17 ifsetgoto reset_right_bank check_switch $16 ifsetgoto reset_right_bank check_switch $15 ifcleargoto skip_right_bank reset_right_bank: gosub L556E ;reset right bank skip_right_bank: check_switch $13 ifsetgoto reset_left_bank check_switch $12 ifsetgoto reset_left_bank check_switch $11 ifcleargoto skip_left_bank reset_left_bank: gosub L55D3 ;reset top bank skip_left_bank: gosub reset_single_drop ;this is never done anywhere else except the routine and once it's marked stuck, it's stuck endif ;fix loadb $01 storebmem $007a cont_solenoid_on_flipper ;$bf lampbvalueon $67 ;set active game flag lampbvalueoff $49 sound_play_secondary L5EF1 ;spinner 900 sound ila ;clear pigs multiprocessing flag if switchtest=0 jsr L5B6A ;see if a ball is in middle outhole else swi check_switch 36 endif ;exp bne L5D24 if switchtest=0 jsr L5B7E ;check if ball is in the lock saucer else swi check_switch 34 endif ;exp beq L5D33 if switchtest=0 jsr L5B79 ;see if a ball is in middle lock lane else swi check_switch 38 endif ;exp beq L5D33 bra L5D2F L5D24: lda $0043 ;col 4 history anda #$10 ;isolate left outhole switch bne L5D2F ;ball is in left outhole if switchtest=0 jsr L5B7E ;check if ball is in the lock saucer else swi check_switch 34 endif ;exp beq L5D33 ;it isn't, branch L5D2F: jsr L5B3C ;fire outhole solenoid L5D32: ila ;clear pigs multiprocessing flag L5D33: lda $0043 ;col 4 history register anda #$E6 ;clear sta $0043 lda $003F anda #$BF sta $003F rts ;return L5D40: checkactivegame lampbvalueon $3c ; checklampvalue $55 ;spsa waiting flag ifsetreturn L5D46: lampbvalueoff $29 ;spsa return ;virtual c6r6 - reactive switches to try and catch misses based on flags L5D49: gosub L595C altlampbvalueon $59 checklampregbon ifsetgosub L58FB loadb $0f ;wind timer storebmem $005d ;setup this routine to re-run if spigs=0 checklampvalue $57 ifsetreturn checklampvalue $52 ifsetreturn checklampvalue $5c ifsetreturn else matchpattern $57,$52,$5c,$00 notereturn endif ;spigs ila ;clear pigs multiprocessing flag clr $0040 ;column 1 history register (drops 1-8) (reactivate if missed) lda $0041 ;column 2 history register anda #$01 ;isolate top dead bumper sta $0041 ;reactivates all 3 bank drops and single drop in case they were missed if matrix=0 lda $0043 ;column 4 history register anda #$84 ;reactivates all lock and trough switches in case they were missed sta $0043 ;save endif ;not needed rts ;return ;monitors switches and is the sole arbiter if the ball should end if matrix=1 master_switch: loadb $80 storebmem $63 ;reset this routine ; check_switch $25 ;mid lock ; check_switch $21 ;lock saucer check_all_3: check_switch $24 ;left outhole ifclearreturn check_2: check_switch $23 ;middle outhole ifclearreturn check_1: check_switch $20 ;right outhole ifclearreturn goto L5BAE ;end of ball endif ;matrix ;virtual c5r0 walk 8 bank wow L5D71: gosub L5929 ;check/move wow lamps loadb $16 ;wind timer storebmem $005b ;save timer for virtual column5 row0 (this routine) return ;return L5D7A: tiltreturn ;if tilted, return checklampvalue $34 ;77k super bonus ifcleargoto L5D9D ;not lit, branch lampregbblinkon ;blink 77k super bonus ila ;clear pigs multiprocessing flag lda #$4D ;setup to score 77k ldb #$09 ;delay between score L5D86: psha ;save score pshb ;save delay stb $004D ;use momentary solenoid timer for this function swi ;start pigs score $31 ;score 1000 swi ;start pigs sound_play_primary L5F1F ;77k score sound jsr L5E42 ;delay pulb pula deca bne L5D86 swi ;start pigs rcflagset ;set pigs multiprocessing flag lampbvalueoff $34 ;77k super bonus ;count down ball bonus L5D9D: loadb $09 storebmem $0077 sound_play_primary L5F4F L5DA5: loadbmem $001c ;lamps 18-1f aandb $07 ;isolate multipliers bacomp $00 ;at 0x? eqreturn ;yes, return L5DAD: checklampvalue $10 ;bonus 9 ifcleargoto L5DC0 ;not lit loadb $09 ; L5DB4: storebmem $0078 loadb $10 L5DB9: gosub L5E15 L5DBC: lampbvalueoff $10 lampbvalueon $58 L5DC0: gosub L5DE9 L5DC3: checklampvalue $58 L5DC5: ifcleargoto L5DCA L5DC8: lampbvalueon $10 ;bonus 9 L5DCA: gosub L57AC ;decrement multiplier L5DCD: loadbmem $02f1 L5DD0: bacomp $01 L5DD2: eqgoto L5DD8 ixdw $02f1 L5DD8: loadbmem $0077 bacomp $01 eqgoto L5DA5 ixdw $0077 ixdw $0077 goto L5DA5 L5DE9: ila ;clear pigs multiprocessing flag lda $001D ;lamps 20-27, bonus balls ora $002E ;get the blinkers as well sta $001D ;save lamps 20-27 sta $007D ;also save in temporary location lda #$00 ;setup to clear lamp blinkers (why not clra??) sta $002E ;save blink lamps 20-27 lda #$08 sta $0078 swi ;start pigs rcflagset ;set pigs multiprocessing flag loadb $20 ;bonus 8 L5DFE: push ;save data silo checklampregbon ;is the ball on? ifsetgosub L5E15 ;score the bonus ixdw $0078 ;move to next ball pop ;restore data silo lampregboff ;turn lamp off binc ;move to next ball bacomp $28 ;all ball lamps accounted for? notegoto L5DFE ;no, keep going loadbmem $007d ;get saved ball lamps storebmem $001d ;restore the ball lamps return ;return L5E15: lampregbblinkon ;blink lamp loadbmem $0078 storebmem $0079 L5E1C: score $31 ;score 1000 L5E1E: loadbmem $0078 bacomp $01 notegoto L5E2A enable_solenoid_0f $1e ;delay between countdown enable_solenoid_0f $00 ;time waster L5E2A: loadbmem $0077 ;delay factor storebmem $004d ;use momentary solenoid timer for delay if fix=0 ila ;clear pigs multiprocessing flag GOSUB L5E42 swi ;start pigs rcflagset ;set pigs multiprocessing flag else xloadgosub L5E42 ;saves 3 bytes endif ;fix ixdw $0079 loadbmem $0079 bacomp $00 notegoto L5E1C return L5E42: jsr L11AA ;switch dispatch tst $004d ;timer bne L5E42 ;still timing, branch rts ;return ;default sound table L5E4B: dw L5E86 dw L5E86 dw L5EF1 dw L5EB3 dw L5F7B dw L5F7B L5E57: db $05,$02,$11,$4a L5E5B: db $02,$08 L5E5D: db $0C,$00,$01,$0a,$00,$02,$07,$ff db $58,$00,$98,$03 dw L5E5D L5E6B: db $07,$04,$ec,$fa,$ec,$12 dw L5E5B db $08 ;sound game over L5E74: db $10,$30,$00,$30,$80,$02,$fa L5E7B: db $00,$02,$07,$ff,$e0,$ff,$de,$03 dw L5E7B db $08 L5E86: db $11,$08 L5E88: db $10,$00,$40,$00,$11,$02,$12 L5E8F: db $00,$01,$07,$00,$b5,$00,$30,$03 dw L5E8F db $12 dw L5E88 db $08 ;sound single drop L5E9D: db $10,$10,$00,$04,$00,$02,$64 L5EA4: db $0c,$00,$01,$0a,$00,$01,$07,$ff db $ef,$00,$10,$03 dw L5EA4 db $08 L5EB3: db $11,$0a,$10,$00,$a0,$00,$f0 L5EBA: db $02,$0a L5EBC: db $00,$01,$07,$00,$30,$01,$00,$03 dw L5EBC db $07,$fe,$b0,$f9,$00,$12 dw L5EBA db $08 ;spinner 100 sound L5ECF: db $10,$01,$60,$02,$60,$02,$19 L5ED6: db $00,$01,$06,$00,$30,$03 dw L5ED6 db $08 ;tilt sound L5EDF: db $10,$0a,$00,$08,$00,$02,$fa L5EE6: db $06,$00,$20,$00,$03,$03 dw L5EE6 db $00,$14,$08 ;spinner 900 sound L5EF1: db $11,$08,$10,$00,$30,$01,$e0 L5EF8: db $02,$08 L5EFA: db $00,$01,$07,$00,$10,$01,$00,$03 dw L5EFA db $07,$ff,$b8,$f8,$00,$12 dw L5EF8 db $08 ;loop value score sound L5F0D: db $10,$01,$00,$04,$00,$02,$40 L5F14: db $00,$02,$07,$00,$80,$01,$00,$03 dw L5F14 db $08 ;sound add player, 77k score, start multiball L5F1F: db $10,$00,$30,$00,$89,$11,$32 L5F26: db $02,$19 L5F28: db $00,$01,$06,$00,$30,$03 dw L5F28 db $06,$fb,$80,$12 dw L5F26 db $08 ;spinner 400/1600 sound L5F37: db $10,$01,$70,$01,$80,$11,$09 L5F3E: db $02,$14 L5F40: db $00,$01,$06,$00,$50,$03 dw L5F40 L5F48: db $06,$fa,$00,$12 dw L5F3E db $08 L5F4F: db $02,$05,$10,$0b,$80,$07,$80 L5F56: db $11,$08 L5F58: db $13,$07,$ff,$60,$00,$a0,$12 dw L5F58 db $07,$04,$f8,$fa,$f8,$04 dw L5F56 ;9 ball hit sound L5F69: db $10,$00,$20,$00,$23,$02,$0c L5F70: db $00,$01,$06,$00,$40,$03 dw L5F70 db $04 dw L5F69 L5F7B: db $a6,$a0,$00,$a0,$01,$00,$a0,$92 db $01,$05,$4a,$00,$0a,$05,$5a,$00 db $24,$05,$6a,$00,$30,$05,$7a,$00 db $48,$05,$8a,$00,$60,$05,$9a,$00 db $90,$05,$aa,$00,$a8,$05,$ba,$a0 db $00,$01,$00,$ff,$05,$00,$08 ;sound advance multiplier L5FAA: db $11,$1b,$10,$00,$30,$00,$80,$05,$06 L5FB3: db $02,$07 L5FB5: db $00,$02,$07,$00,$20,$00,$22,$03 dw L5FB5 db $07,$ff,$65,$ff,$5b,$12 dw L5FB3 db $08 L5FC8: db $11,$0a L5FCA: db $10,$02,$30,$01,$50,$02,$06 L5FD1: db $0c,$00,$02,$0a,$00,$02,$07,$ff db $f8,$00,$37,$03 dw L5FD1 db $12 dw L5FCA db $08 if fix=0 L5FE3: ;filler (and very little of it) db $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff db $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff db $ff,$ff,$ff,$ff,$ff endif ;fix if debug=1 debugger: lda #$ff sta $0c sta $0e ldb $34 pshb bsr xform_nibble sta $0f ;store in p4 pulb bsr shift_nibble sta $0d rts shift_nibble: lsrb lsrb lsrb lsrb xform_nibble: andb #$0f clra dbloop: decb bmi dbx adda #$01 daa bra dbloop dbx: rts endif ;debug org $5ff8 dw L17CB ;irq dw L5080 ;swi dw L17C6 ;nmi dw L1E45 ;reset if c512=1 org $fff8 dw L17CB ;irq dw L5080 ;swi dw L17C6 ;nmi dw L1E45 ;reset endif ;c512