;alternate software for power play ;2020 scidleman ;uses stern pigs' (modified) software as proof of concept ;2.21.20 α ;rough in of operating system and pigs interpretor ;fast react solenoid code changed to match PP hardware ;elimination of most routines not relevant (sound, etc.) ;change pigs routines to make blink overflow available ;added new pigs routines ; clearb equivalent to loadb $00, saves a byte ; [loadbz] loadbmem from zero page, saves a byte (auto filled in by macros) ; [storebz] storebmem to zero page, saved a byte (auto filled in by macros) ; VERSION=$00 ;alpha α SUBVERSION=$00 MAXCREDITS=$99 ;c512=1 ;compile rom for weebly board use include "..\common\stern13exp.asm" clearb macro db $5a endm if trip=1 trip_switch macro bval db $23,bval+$80 endm endif ;trip switch if c512=1 org $0000 db VERSION,SUBVERSION," BOBBY ORR POWER PIGS - WEEBLY BOARD" endif org $1000 ;switch matrix vectors ;add $8000 to the routine if it should be ignored in game over mode L1000: ;col0 dw outhole ;row7 outhole dw tilt +$8000 ;row6 tilt dw credit ;row5 credit button dw br_rob +$8000 ;row4 bottom right rollover button dw bl_rob +$8000 ;row3 bottom left rollover button dw rebound +$8000 ;row2 10 point rebounds dw rebound50 +$8000 ;row1 50 point rebounds dw inlane +$8000 ;row0 inlanes L1010: ;col1 dw slam ;row7 slam dw notused ;row6 dw notused ;row5 dw notused ;row4 dw notused ;row3 dw coin2 ;row2 dw coin1 ;row1 dw coin3 ;row0 L1020: ;col2 dw ldropA +$8000 ;row7 left drop A (top) dw ldropB +$8000 ;row6 dw ldropC +$8000 ;row5 dw ldropD +$8000 ;row4 left drop D (bottom) dw rdropA +$8000 ;row3 right drop A (top) dw rdropB +$8000 ;row2 dw rdropC +$8000 ;row1 dw rdropD +$8000 ;row0 right drop D (bottom) L1030: ;col3 dw saucer ;row7 top saucer dw notused ;row6 dw tl_rob +$8000 ;row5 top left rollover button dw tr_rob +$8000 ;row4 top right rollover button dw loutlane +$8000 ;row3 left outlane dw routlane +$8000 ;row2 right outlane dw center_rob +$8000 ;row1 center rollover button dw downpost_rob +$8000 ;row0 down post rollover button L1040: ;col4 dw lpop +$8000 ;row7 left pop bumper dw rpop +$8000 ;row6 right pop bumper dw bpop +$8000 ;row5 lower pop bumper dw lsling +$8000 ;row4 left slingshot dw rsling +$8000 ;row3 right slingshot dw lc_rob +$8000 ;row2 left center rollover button dw rc_rob +$8000 ;row1 right center rollover button dw top_rob +$8000 ;row0 top rollover button and center target L1050: ;timed virtual column 5 $49 dw notused ;row7 timer $54 dw notused ;row6 timer $55 dw notused ;row5 timer $56 dw notused ;row4 timer $57 dw attract_mode_display ;row3 timer $58 attract mode display dw attract_mode_lamps ;row2 timer $59 attract mode lamps dw notused ;row1 timer $5a dw notused ;row0 timer $5b L1060: ;timed virtual column 6 $4a dw notused ;row7 timer $5c dw notused ;row6 timer $5d dw notused ;row5 timer $5e dw notused ;row4 timer $5f dw notused ;row3 timer $60 dw notused ;row2 timer $61 dw notused ;row1 timer $62 dw notused ;row0 timer $63 L1070: ;direct activated virtual column 7 $4b dw award1 ;/80 row7 award replay level 1 dw award2 ;/40 row6 award replay level 2 dw award3 ;/20 row5 award replay level 3 dw notused ;/10 row4 n/u dw notused ;/08 row3 n/u dw ball_start ;/04 row2 ball start dw game_start ;/02 row1 game start dw set_active_ball ;/01 row0 set active ball status ;switch routines follow notused: return slam: reboot ;col0 row4 bottom right rollover button br_rob: return ;col0 row3 bottom left rollover button bl_rob: return ;col0 row2 10 point rebounds rebound: return ;col0 row1 50 point rebounds rebound50: return ;col0 row0 inlanes inlane: return ;col2 row7 left drop A (top) ldropA: return ;col2 row6 left drop B ldropB: return ;col2 row5 left drop C ldropC: return ;col2 row4 left drop D (bottom) ldropD: return ;col2 row3 right drop A (top) rdropA: return ;col2 row2 right drop B rdropB: return ;col2 row1 right drop C rdropC: return ;col2 row0 right drop D (bottom) rdropD: return ;col4 row7 top saucer saucer: return ;col4 row5 top left rollover button tl_rob: return ;col4 row4 top right rollover button tr_rob: return ;col4 row3 left outlane loutlane: return ;col4 row2 right outlane routlane: return ;col4 row1 center rollover button center_rob: return ;col4 row0 down post rollover button downpost_rob: return ;col5 row7 left pop bumper lpop: return ;col5 row6 right pop bumper rpop: return ;col5 row5 lower pop bumper bpop: return ;col5 row4 left sling lsling: return ;col5 row3 right sling rsling: return ;col5 row2 left center rollover button lc_rob: return ;col5 row1 right center rollover button rc_rob: return ;col5 row0 top rollover button/center standup target top_rob: return ;virtual c5r3 attract mode display thread attract_mode_display: checklampvalue $32 ;game over ifclearreturn ;not lit, abort checklampvalue $31 ;hstd ifsetgoto show_prev_scores ;lit, hstd must be currently showing, reset to scores show_hstd ;not lit, show the hstd loadb $3c ;setup timer for this routine goto save_disp_timer ;save timer and finish up show_prev_scores: xfer_scores_to_displays ;put the score back onto the displays loadb $5a ;setup timer for this routine save_disp_timer: storebmem $0058 ;save in virtual switch timer return ;virtual c5r2 attract mode lamp thread attract_mode_lamps: ila ;clear pigs multiprocessing flag/return to assembly lda #$05 ;setup timer for this routine sta $0059 ;save timer ldx #at_lamp_data ;attract mode lamp data jmp L141E L1416: inx inx inx inx inx inx inx inx L141E: ldb $001A ;2nd byte of the lamp columns is unique use as an indentifier for step cmpb $01,x ;test dataset bne L1416 ;not this one, branch to advance X to next set ;found set current set of data, copy the the next lamp set to the displays lda $08,x ;1st element lamps 0-7 sta $0019 ;save ldb $09,x ;2nd element lamps 8-f stb $001A ;save lda $0A,x ;3rd element lamps 10-17 sta $001B ;save lda $0B,x ;4th element lamps 18-1f sta $001C ;save lda $0C,x ;5th element lamps 20-27 sta $001D ;save lda $0D,x ;6th element lamps 28-2f sta $001E ;save lda $0E,x ;7th element lamps 30-37 ldb $001F ;get current lamps 30-37 andb #$0D ;preserve game over, tilt, and hstd lamps aba ;combine with the 7th element lamps sta $001F ;save lda $0F,x ;8th element lamps 38-3b ldb $0020 ;get current lamps 38-3b andb #$FC ;clear outlane specials aba ;combine with the 8th element lamps sta $0020 ;save rts ;return ;attract mode lamp data at_lamp_data: ; 19 1a 1b 1c 1d 1e 1f 20 db $00,$00,$00,$00,$87,$0e,$c0,$03 db $10,$ac,$c4,$ff,$40,$80,$c2,$00 db $ab,$d5,$23,$ff,$27,$ee,$20,$00 db $44,$7e,$94,$ff,$10,$f0,$12,$00 db $00,$80,$08,$00,$0f,$80,$00,$03 db $00,$00,$00,$00,$87,$0e,$c0,$03 awardspecial: bcdinc $02,$02e6 ;increase audit 14, total specials awarded checklampvalue $87 ;dip 32, part of special award ifsetgoto L1353 ;dip 32 on, special is either extra ball or replay, branch addtoscoreq $45 ;score 50,000 for special return ;return L1353: checklampvalue $86 ;dip 31, part of special award ifsetgoto L5894 ;dip 31 on, special awards replay, branch awardextraball: lampbvalueon $28 ;shoot again ila ;clear pigs multiprocessing flag/return to assembly lda #$01 ;possible # of add a balls swi ;start pigs checklampvalue $6c ;dip 5, add a ball control beq L136B ;dip 5 off, 1 extra ball at a time only lda #$05 ;possible # of add a balls depending on dip 8 swi ;start pigs checklampvalue $6f ;dip 8, add a ball limit off=3, on=5 bne L136B ;it's on, use 5 lda #$03 ;it's off, use 3 L136B: tab ;transfer upper limit to B for comparison lda $0079 ;get add a balls waiting inca ;increase cba ;compare to add a ball limit bhi L137C ;you're over the limit, branch swi ;start pigs bcdinc $02,$02e4 ;increase audit 13, extra balls awarded tab ;transfer new added ball count to B for saving L137C: stb $0079 ;save new added ball count rts ;return ;coin 2 coin2: bcdinc $03,$02da ;increase coin 2 audit ila ;clear pigs multiprocessing flag/return to assembly ldb $0026 ;use dips 1-5 bra L1756 ;branch to process ;coin 1 coin1: bcdinc $03,$02dd ;increase coin 1 audit ila ;clear pigs multiprocessing flag/return to assembly ldb $27 ;use dips 9-12 bra L1756 ;branch to process ;coin 3 coin3: bcdinc $03,$02e0 ;increase coin 3 audit ila ;clear pigs multiprocessing flag/return to assembly ldb $0029 ;use dips 25-28 ;process coin switches L1756: tba ;copy dips from B to A ldx #L17A4 ;setup coin data eorb $0026 ;dips 1-8 andb #$0F ;isolate dips 1-4 beq L176B inx inx ;advance coin data pointer tab eorb $0027 ;dips 9-16 andb #$0F ;isolate dips 9-12 beq L176B inx inx ;advance coin data pointer L176B: ldb $01,x pshb ldb $00,x pshb ldb $01,x anda #$0F asla swi ;start pigs checklampregbon beq L177B inca L177B: ldx #L17A9 L177E: inx deca bpl L177E lda $00,x pulb swi checklampregbon bne L178D asra asra asra asra L178D: swi ;start pigs altlampregb swi ;start pigs checklampregbon bne L1797 pulb pshb swi ;start pigs altlampregb L1797: pulb anda #$0F beq L17A3 L179C: swi ;start pigs gosub add_credit ;add credit deca ;credit counter-- bne L179C ;not done, keep adding credits L17A3: rts ;return L17A4: db $41,$48,$42,$49,$43 L17A9: db $4a db $11,$11,$22,$22,$33,$33,$44,$44 db $55,$55,$66,$66,$77,$77,$aa,$aa db $ee,$ee,$01,$01,$12,$12,$05,$05 db $07,$07,$01,$02,$11,$12,$12,$13 L17CA: lda $008B ;check for zero cross bpl L17D8 ;not zero cross, branch to check for self test ldb #$34 stb $008B ;save lda $008A ;clear interrupt cli ;allow [other] interrupts jmp L5EAB ;process zero cross interrupt L17D8: lda $0089 ;check for self test bpl system_reset_vector ;not zero cross, reboot lda $0050 ;check self-test switch debounce timer bne L17E7 ;already timing coma ;flip flag to $ff sta $0064 ;save in self test flag lda #$24 ;setup debounce timer sta $0050 ;save in timer L17E7: lda $0088 ;clear interrupt L17E9: rti ;return from interrupt system_reset_vector: jmp system_reset ;restart ;nmi nmi: lda #$FF ;setup flag sta $0066 ;save nmi (s33/clear) flag rti ;return from interrupt ;irq interrupt: lda $0091 ;check interrupt bpl L17CA ;not display, branch ;display interrupt lda $0090 lda $008B psha lda $0088 psha lda $0065 bne L180F coma ldb #$30 stb $008B sta $008A ldb #$34 stb $008B sta $008A L180F: sta $0088 ldb #$3C stb $008B ldb #$35 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 L182B ;not zero (should never be zero) jmp L18B9 ;reset digit index L182B: dex ;move to next data to display (offset from player display 3, 2, 1, 0) asla ;move the digit index bcs L1833 ;digit ok, branch, you're working with the lower nibble asla ;move the digit index again bcc L182B ;still clear, keep searching for the digits' data clc ;ensure upper nibble is the salient nibble L1833: lda #$35 sta $0089 lda $00,x ;get p1 bcd data for this digit ora $0068 ;p1 blank control (ff=blank, 00=show) bcs L1841 ;you're working with the lower nibble, branch anda #$F0 ;clear the lower nibble bra L1846 ;branch to save upper nibble data to display ;lower nibble of A is digit data to send L1841: asla asla asla asla ;move the lower nibble to the upper nibble sec ;make sure the lower nibble is flagged for p2 data L1846: ora #$0E ;setup blank for p1 sta $0088 ;blank p1 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 bcs L1858 ;you're working with the lower nibble, branch andb #$F0 ;clear the lower nibble bra L185D ;branch to save upper nibble data to display L1858: aslb aslb aslb aslb ;move the lower nibble to the upper nibble sec ;make sure the lower nibble is flagged for p3 data L185D: orb #$0D ;setup blank for p3 stb $0088 ;blank p3 lda $08,x ;get p3 bcd data for this digit ora $006A ;p3 blank control (ff=blank, 00=show) orb #$0F ;setup blanking for p4 stb $0088 ;blank p4 bcs L186F ;you're working with the lower nibble, branch anda #$F0 ;clear the lower nibble bra L1874 ;branch to save upper nibble data to display L186F: asla asla asla asla ;move the lower nibble to the upper nibble sec ;make sure the lower nibble is flagged for p4 data L1874: ora #$0B ;setup blank for p4 sta $0088 ;blank p4 ldb $0C,x ;get p4 bcd data for this digit orb $006B ;p4 blank control (ff=blank, 00=show) ora #$0F ; sta $0088 lda $0014 ;get digit index sta $0090 ;strobe digit index bcs L188A ;working with lower nibble, branch andb #$F0 bra L188F L188A: aslb aslb aslb aslb sec ;make sure the lower nibble is flagged for credit/match/ball in play display L188F: orb #$07 stb $0088 lda $10,x ;get credit/match/ball in play data for this digit ora $006C ;credit/match/ball in play display blanking control orb #$0F stb $0088 bcc L18A2 asla asla asla asla sec L18A2: ora #$0F sta $0088 ldb $0090 andb #$FE stb $0090 orb #$01 stb $0090 lda #$3D sta $0089 lda $0014 ;get digit index asla ;move to next digit [80=1 40=10 20=100 10=1K 08=10K 04=100K 02=1M] bcc L18BB ;check for overflow from $80 (1's digit) - branch if ok L18B9: lda #$02 ;reset digit index to 1m digit L18BB: sta $0014 ;save new digit index pula sta $0088 lda $0065 bne L18D4 ldb #$30 stb $008B sta $008A ldb #$34 stb $008B ldb #$23 L18D0: decb bne L18D0 coma L18D4: sta $008A pula tab lsra bcs L18DD lda $008A L18DD: stb $008B lda $0053 ;timer bne L18E6 ;not ready for sound ; jmp L1C52 ;start reprocessing sounds L18E6: dec $0053 ;sound timer-- rti ;return from interrupt ;bootup finishes finishsysteminit: lds #$027F ;set stack ldx #$007F ;setup to clear u7 6810 ram L18F0: clr $00,x ;clear this byte dex ;index-- bne L18F0 ;not done, keep going dex ;make X #$ffff stx $003A stx $003C stx $003E stx $0040 stx $0042 ;lists entire switch matrix as 'stuck' so any actual stuck switches do not activate stx $0068 ;p1/p2 blank masks stx $006A ;p3/p4 blank masks ;read dip switches lda #$20 ;use A as an index, 20=1-8, 40=9-16, 80=17-24, 00=25-32 ldx #$0026 ;base address of dips L1909: sta $0088 ;strobe ldb #$22 ;setup propagation delay L190D: decb ;delay-- bne L190D ;not done, keep going ldb $008A ;get dip return stb $00,x ;save dip byte inx ;move to next dip asla ;shift index bne L1909 ;not done with 1-24, keep going sta $0088 ;clear strobe lda #$3D ;setup alternate strobe sta $008B ;strobe the other line for dips 25-32 ldb #$22 ;setu propagation delay L1920: decb ;delay-- bne L1920 ;not done, keep going ldb $008A ;get dip return stb $00,x ;save dip cli ;allow interrupts lda #$0C ;setup to start attract mode threads sta $0049 ;starts attract mode threads ;check for all dips off to start self test ldx $0026 ;dips 1-16 bne L1937 ;some are on, branch ldx $0028 ;dips 17-32 bne L1937 ;some are on, branch jmp self_test ;all dips off, start self test L1937: swi ;start pigs rcflagset ;set pigs multiprocessing flag lampbvalueon $32 ;game over show_hstd loadb $ff ;setup blank mask storebmem $006c ;blank credit/match/ball in play display enable_solenoid_0f $02 ;short pause enable_solenoid_0f $00 ila ;clear pigs multiprocessing flag/return to assembly L1966: swi ;start pigs update_match ;show match swi ;start pigs show_credits ;show current credits ila ;clear pigs multiprocessing flag lda #VERSION ;get version # sta $13 ;save in match display lda #$0C ;setup to start attract mode threads sta $0049 ;starts attract mode threads clra ;setup to clear action registers sta $0044 ;clear column 0 (coin/credit/tilts) sta $0045 ;clear column 1 (kickbigs) sta $0048 ;clear column 4 (trough) sta $006C ;clear credit/ball in play display blanking lda #$05 ;setup timers for attract mode threads sta $0059 ;save timer for lamp thread sta $0058 ;save timer for display thread main_loop: lds #$027F ;reset stack to the top jsr switch_dispatch ;switch dispatch/process score/process sound script bra main_loop ;keep doing it ;reset system_reset: sei ;prevent interrupts lds #$007F ;set stack to top of u7 lda #$04 sta $0089 sta $0093 ldx #$FF00 stx $0088 stx $008A stx $0090 stx $0092 lda #$30 sta $0091 L1F01: dex ;delay loop bne L1F01 ;not done, keep going ;self test start, rom checksum clra ldx #$1000 checksum_u1u5: adda $00,x inx cpx #$2000 bne checksum_u1u5 ldx #$5000 checksum_u2u6: adda $00,x inx cpx #$6000 bne checksum_u2u6 tsta rom_bad: ; bne rom_bad ;rom checksum bad, hang nop nop bsr flashled ;flash led, 1st time for correct rom checksum ;test u7 6810 ram test_6810: clra ram6810_test: inca sta $00,x ;X starts at $0000 because of the end of the flash LED routine cmpa $00,x ram6810_bad: bne ram6810_bad ;ram bad, hang tsta bne ram6810_test inx cpx #$0080 ;done? bne test_6810 ;no, keep going bsr flashled ;flash led, 2nd time for u7 6810 ram test pass ;test u8 (hi nibble)/u13 (lo nibble) 5101 nvrams ldx #$0200 ;start at $200 ram5101_test: ldb $00,x ;get byte clra ;test is the same as the 6810 test, but saves the original byte at the end test_all_5101_values: inca sta $00,x cmpa $00,x ram5101_bad: bne ram5101_bad ;ram bad, hang tsta bne test_all_5101_values stb $00,x inx cpx #$0300 ;done? bne ram5101_test ;no, keep going bsr flashled ;flash led, 3rd time for u8/u13 5101 rams test pass ;test u10 6821 pia ldx #$008B ;base address of u10 pia bsr testpia ;test pia bsr flashled ;flash led, 4th time for u10 6821 pia test pass ;test u11 6821 pia ldx #$0093 ;base adddress of u11 pia bsr testpia ;test pia bsr flashled ;flash led, 5th time for u11 6821 pia test pass ;test for display timer interrupt lda $0090 wait_for_disp_int: lda $0091 bpl wait_for_disp_int ;wait for interrupt bsr flashled ;flash led, 6th time for 555 display timer interrupt pass ;test for zero crossing interrupt lda $008A wait_for_zero_int: lda $008B bpl wait_for_zero_int ;wait for interrupt bsr flashled ;flash led, 7th time for zero crossing interrupt pass bra bootup_continues ;7 flashes passed, continue system initialization ;flash LED ;note that X returns from this routine as #$0000, which some of the routines take advantage of flashled: lda #$38 sta $0091 ldx #$E530 ;setup delay loop L1F93: dex ;delay-- bne L1F93 ;not done, keep going lda #$30 sta $0091 ldx #$A5F0 ;setup delay loop L1F9D: dex ;delay-- bne L1F9D ;not done, keep going rts ;return ;test pia testpia: bsr L1FA3 L1FA3: lda #$31 bsr L1FBC lda #$39 bsr L1FBC dex bsr L1FC6 inx lda #$35 bsr L1FBC lda #$3D bsr L1FBC dex bsr L1FC6 dex rts L1FBC: sta $00,x ldb $00,x andb #$3F cba pia_test_bad: bne pia_test_bad ;pia test bad, hang rts L1FC6: clra L1FC7: sta $00,x ldb #$03 L1FCB: decb bne L1FCB cmpa $00,x pia_test_still_bad: bne pia_test_still_bad ;pia test bad, hang inca bne L1FC7 rts bootup_continues: 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 finishsysteminit ;finish system init org $2000 db $ff org $5000 ;Stern pigs function table L5000: dw fire_solenoid_in_a ;$00 enable_solenoid_00 dw fire_solenoid_in_a ;$01 enable_solenoid_01 dw fire_solenoid_in_a ;$02 enable_solenoid_02 dw fire_solenoid_in_a ;$03 enable_solenoid_03 dw fire_solenoid_in_a ;$04 enable_solenoid_04 dw fire_solenoid_in_a ;$05 enable_solenoid_05 dw fire_solenoid_in_a ;$06 enable_solenoid_06 dw fire_solenoid_in_a ;$07 enable_solenoid_07 dw fire_solenoid_in_a ;$08 enable_solenoid_08 dw fire_solenoid_in_a ;$09 enable_solenoid_09 dw fire_solenoid_in_a ;$0a enable_solenoid_0a dw fire_solenoid_in_a ;$0b enable_solenoid_0b dw fire_solenoid_in_a ;$0c enable_solenoid_0c dw fire_solenoid_in_a ;$0d enable_solenoid_0d dw fire_solenoid_in_a ;$0e enable_solenoid_0e dw fire_solenoid_in_a ;$0f enable_solenoid_0f dw continuous_sol_in_A_on ;$10 continuous_solenoid_on_7f dw continuous_sol_in_A_on ;$11 continuous_solenoid_on_flipper dw continuous_sol_in_A_on ;$12 continuous_solenoid_on_bf dw continuous_sol_in_A_on ;$13 continuous_solenoid_on_ef dw continuous_sol_in_A_off ;$14 continuous_solenoid_off_7f dw continuous_sol_in_A_off ;$15 continuous_solenoid_off_flipper dw continuous_sol_in_A_off ;$16 continuous_solenoid_off_bf dw continuous_sol_in_A_off ;$17 continuous_solenoid_off_ef dw L5D5C ;$18 set pigs multiprocessing flag dw L5D62 ;$19 clear pigs multiprocessing flag (return to assembly) dw lamp_in_B_on ;$1a lamp in register B on dw next_lamp_in_script_on ;$1b lamp on dw lamp_in_B_off ;$1c lamp in register B off dw next_lamp_in_script_off ;$1d lamp off dw lamp_in_B_alternate ;$1e flip lamp in register B dw flip_next_lamp_in_script ;$1f flip lamp dw check_lamp_in_B ;$20 check lamp/flag in register B dw check_next_lamp_in_script;$21 check lamp/flag dw lamp_in_B_blink ;$22 lamp in register B blink dw next_lamp_in_script_blink;$23 blink lamp dw L531E ;$24 clear play flags dw delay_script ;$25 delay dw switch_dispatch ;$26 switch dispatch/score/sound processing dw unconditional_goto ;$27 unconditional goto dw L53EA ;$28 if set/not equal, goto dw L53E2 ;$29 if clear/equal, goto dw save_player_status ;$2a save current player status dw L552B ;$2b restore current player status dw L53F7 ;$2c unconditional gosub dw L541C ;$2d if set/not equal gosub dw L5413 ;$2e if clear/equal gosub dw unconditional_return ;$2f unconditional return dw L543D ;$30 if set/not equal return dw L5436 ;$31 if clear/equal return dw tilted_return ;$32 if tilted, return dw gameover_return ;$33 if game over, return dw notactive_return ;$34 return if not in an active game dw L54A6 ;$35 increment B dw L54B0 ;$36 increment memory pointed to by X dw L54AB ;$37 decrement B dw L54B6 ;$38 decrement memory pointed to by X dw L54BC ;$39 load B direct dw L54C0 ;$3a load B from memory location dw L54C9 ;$3b store B in memory location dw L54CF ;$3c compare A to B dw L54D4 ;$3d compare B to memory location in X dw L54E2 ;$3e OR A,B dw L54EE ;$3f EOR A,B dw L54FA ;$40 AND A,B dw L5401 ;$41 dw L5456 ;$42 dw push_data_silo ;$43 push data silo dw pull_data_silo ;$44 pull data silo dw L55D1 ;$45 update current player dw L55BC ;$46 blank current player dw L55C8 ;$47 show current player dw L559A ;$48 update match dw L55AF ;$49 show ball in play dw L554F ;$4a show credits dw L563B ;$4b show hstd dw L5668 ;$4c all displays valid dw L5675 ;$4d all displays invalid dw L567A ;$4e transfer scores to display dw L56F7 ;$4f score directly dw L53FC ;$50 spawn thread at X dw L5778 ;$51 clear variables dw bcd_increment ;$52 bcd increment dw bcd_decrement ;$53 bcd decrement dw system_reset ;$54 restart dw L53F2 ;$55 gosub assembly dw L578F ;$56 enqueue score dw L57CA ;$57 play primary sound dw L57D5 ;$58 play secondary sound dw L57BD ;$59 play speech 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) clearbee: clrb tsx stb 6,x rts ;functions $00-$0f enable solenoid fire_solenoid_in_a: lsra L5240: cli ;allow interrupts so the timer can expire L5241: ldb $004D ;check momentary solenoid timer bne L5241 ;wait for slot to open sei ;block interrupts ldb $004D ;check timer again bne L5240 ;something else still occupying dec $004D ;make timer #$ff so nothing else can grab solenoid ldb #$F0 andb $0092 aba sta $0092 cli ;allow interrupts jsr next_in_a ;get next script parameter in A sta $004D ;save solenoid time parameter rts ;return ;functions $10-$13 continuous solenoid on continuous_sol_in_A_on: ldb #$80 lsra anda #$03 beq L5266 L5262: lsrb deca bne L5262 L5266: comb sei ;block interrupts andb $0092 stb $0092 cli ;allow interrupts rts ;return ;functions $14-$17 continuous solenoid off continuous_sol_in_A_off: ldb #$80 lsra anda #$03 beq L5279 L5275: lsrb deca bne L5275 L5279: sei ;block interrupts orb $0092 stb $0092 cli ;allow interrupts rts ;return ;function $1b lamp on next_lamp_in_script_on: jsr next_in_b ;get next script parameter in B ;function $1a lamp in B on lamp_in_B_on: pshb ;save original B tstb ;test for sign bit bpl nomorelampon ;it's clear, this is the last/only lamp in the string andb #$7f ;clear sign bit nomorelampon: bsr x2lamp_a2mask ;set X to lamp column and make lamp mask in A psha ;save lamp mask ora 0,x ;set lamp bit sta 0,x ;save lamp byte pula ;restore lamp mask cmpb #$3c ;flag? bcc L5290 ;yes, branch coma ;flip for blink clear anda $11,x ;clear in blink matrix sta $11,x ;save blink matrix L5290: pulb ;get original B back tstb ;test for sign bit bmi lamp_in_B_on ;it's set, there's more lamps in the string rts ;return ;function $1d lamp off next_lamp_in_script_off: jsr next_in_b ;get next script parameter in B ;function $1c lamp in B off lamp_in_B_off: pshb ;save original B tstb ;test for sign bit bpl nomorelampoff ;it's clear, this is the last/only lamp in the string andb #$7f ;clear sign bit nomorelampoff: bsr x2lamp_a2mask ;set X to lamp column and make lamp mask in A coma ;flip for clear mask psha ;save flipped mask anda 0,x ;clear normal lamp sta 0,x ;save lamp byte pula ;restore flipped mask cmpb #$3c ;flag? bcc L52A1 ;yes, branch anda $11,x ;clear blink sta $11,x ;save blink matrix L52A1: pulb ;get original B back tstb ;test for sign bit bmi lamp_in_B_off ;it's set, there's more lamps in the string rts ;return ;function $1f alternate lamp flip_next_lamp_in_script: jsr next_in_b ;get next script parameter in B ;function $1e alternate lamp in B lamp_in_B_alternate: bsr x2lamp_a2mask ;set X to lamp column and make lamp mask in A eora $00,x ;flip lamp sta $00,x ;save lamp rts ;return ;function $23 blink lamp next_lamp_in_script_blink: jsr next_in_b ;get next script parameter in B ;function $22 blink lamp in B lamp_in_B_blink: bsr x2lamp_a2mask ;set X to lamp column and make lamp mask in A ora $11,x ;set blink lamp sta $11,x ;save blink lamp L52B5: rts ;return ;function $21 check lamp check_next_lamp_in_script: jsr next_in_b ;get next script parameter in B ;function $20 check lamp in B check_lamp_in_B: bsr x2lamp_a2mask ;set X to lamp column and make lamp mask in A pshb ;save lamp/flag psha ;save lamp mask tba ;transfer lamp to A ldb $00,x ;get lamp column under test cmpa #$3c ;flag? bcc L52C6 ;yes, branch orb $11,x ;get the blink status added in L52C6: pula ;restore lamp mask pshb ;save column for comparison tsx ;get stack pointer anda $00,x ;use the mask against the status tpa ;transfer the condition register sta $05,x ;save the condition register pulb ;waste the comparison byte pulb ;get the lamp/flag byte back rts ;return ;set X to lamp column and make lamp mask in A x2lamp_a2mask: tba if trip=1 anda #$7f ;clear sign bit if set for switch endif ;+2 lsra lsra lsra adda #$19 ;lamp offset, starts at $19 if trip=1 tstb bpl notswitch andb #$7f ;clear sign bit adda #$19 ;add to get action register offset notswitch: endif ;+7, 9 total psha ;save to make lsb clra ;set msb to 0 psha ;save to make msb tsx ;get stack pointer ldx $00,x ;get the newly formed lamp column in X ins ins ;waste the top 2 bytes of the stack ;set A to mask pshb ;save B lda #$01 ;set A to bit 0 for mask andb #$07 beq L52EA ;happened to be first lamp, branch L52E6: asla decb bne L52E6 L52EA: pulb ;restore B rts ;return ;use next script parameter to set X to zero page XZERO: tsx ;get current data silo pointer ldx $a,x ;get script location 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 L52FC ;advance script once ;get next 2 script parameters into X next2_in_x: tsx ;get current data silo pointer ldx $0A,x ;get current script pointer lda $01,x ;get lsb of X psha ;save lda $00,x ;get msb of X psha ;save tsx ;get stack pointer inc $0D,x ;increase script lsb bne L52FC ;no carry, branch inc $0C,x ;add carry to script msb L52FC: inc $0D,x ;increase script lsb bne L5302 ;no carry, branch inc $0C,x ;add carry to script msb L5302: ldx $00,x ;get X pula pula ;waste the temporary parameters rts ;return ;get next script parameter into A/doesn't touch B next_in_a: tsx ;get current data silo pointer ldx $0A,x ;get script pointer lda $00,x ;get next parameter in A tsx ;get current data silo pointer L530D: inc $0B,x ;increase script pointer lsb bne L5313 ;no carry, branch inc $0A,x ;increase script pointer msb L5313: rts ;get next script parameter in B next_in_b: tsx ;get current data silo pointer ldx $0A,x ;get current script pointer ldb $00,x ;get B tsx ;get current data silo pointer stb $06,x ;save B in data silo bra L530D ;increment script pointer and return ;function $24 clear play flags ;clears $19-$25 and $2a-$36 L531E: clra ;setup clear ldx #$0019 ;start at $19 L5322: sta $11,x ;clear starting at $2a sta $00,x ;clear starting at $19 inx ;move to next byte cpx #$0026 ;done? bne L5322 ;no, keep going rts ;return ;function $25 delay delay_script: bsr next_in_a ;get next script byte in A L5330: psha ;save delay factor bsr switch_dispatch ;process switches pula ;restore delay factor ldx #$0A00 ;delay is $a00/dex L5337: dex ;delay-- bne L5337 ;not done, keep going deca ;delay factor bne L5330 ;not done, keep going rts ;return ;function $26 switch dispatch switch_dispatch: pshb ;save B ldx #L1000 ;switch matrix table stx $02EF ;save clrb ;setup B as a counter ldx #$0044 ;start with switch column 0 action register L5349: lda $00,x ;get action register bne L53A5 ;at least one closed row, branch inx ;move to next action register addb #$10 ;move to next counter bpl L5349 ;sign bit will be set going #$70->#$80 L5354: lda $64 ;check self-test switch flag beq L535B ;not set, branch jmp self_test ;start self-test ;no closed switches, no self-test - process score queues and sound queues L535B: pulb ;restore B lda $0051 ;check score timer beq L5364 ;it's zero, branch to check score queues ;check sound queue ldx $0074 ;check sound queue pointer bne L537B ;sound queue active, branch L5364: lda #$0C ;reset score timer sta $0051 ;save score timer lda #$51 ;setup score byte ldx #$0072 ;start with 100k queue L5372: tst $00,x ;score queue empty? bne L537C ;no, process this score queue dex ;move to next score queue suba #$10 ;adjust score byte bpl L5372 ;not done, branch L537B: rts ;return ;found a populated score queue, process L537C: dec $00,x ;decrement this score queue stx $02F1 ;save score queue jsr L5700 ;actually score if system=0 lda $001F ;lamps 30-37 anda #$08 ;isolate lamp 33, tilt else swi ;start pigs checklampvalue $33 ;check for tilt endif ;system, save a byte bne L537B ;tilted, branch to return lda $02F2 ;contains lsb of current score queue if system=0 suba #$6D ;subtract to get offset for default sound table asla ;double for indexing else suba #$6e ;there will never be a 'score queue 1's' so eliminate the default sound ldx #L1981 endif ;system if system=0 ; adda #$81 ;default score sound table lsb ; adda #lo L1981 ;default score sound table lsb ; sta $02F2 ;save ; lda #$19 ;default score sound table msb ; lda #hi L1981 ;default score sound table msb ; adca #$00 ;handle any carries ; sta $02F1 ;save ; ldx $02F1 ;get sound pointer ; ldx $00,x ;get sound script else find_sound_addr: deca bmi found_sound_addr inx inx bra find_sound_addr found_sound_addr: ldx 0,x ;get sound script pointer endif ;system, save 5 bytes ; jsr L57B8 ;play sound rts ;return ;found switch column, process L53A5: stb $02F0 ;save the lsb of the switch column vector ldb #$80 ;setup B as a row mask L53AA: asla ;shift the switch column bcs L53B6 ;found the row inc $02F0 inc $02F0 ;adjust the switch vector lsb lsrb ;shift the row mask bra L53AA ;keep adjusting the mask and switch vector ;found the switch row L53B6: sei ;prevent interrupts eorb $00,x ;flip the switch row stb $00,x ;save the switch column cli ;allow interrupts ldx $02EF ;get the switch routine pointer ldx $00,x ;get the switch routine bpl not_in_game tst $25 bpl L5354 ;not in an active game, do not process this switch stx $0200 ;save X lda $200 ;get the MSB of the switch routine anda #$7f ;clear the active game bit sta $200 ldx $200 ;get the corrected switch routine not_in_game: swi ;start pigs spawn_thread ;start a thread at X bra L5354 ;process more switches ;function $27 unconditional goto unconditional_goto: tsx ;get current data silo pointer ldx $08,x ;get script pointer lda $00,x ;get msb of goto pshb ;save B ldb $01,x ;get lsb of goto tsx ;get current data silo pointer back stb $0A,x ;store the lsb as the new script pointer lsb sta $09,x ;store the msb as the new script pointer msb pulb ;restore B rts ;return ;double script increase L53D4: tsx ;get current data silo pointer inc $09,x ;increase lsb of script pointer bne L53DB ;no carry, branch inc $08,x ;increase msb of script pointer L53DB: inc $09,x ;increase lsb of script pointer bne L53E1 ;no carry, branch inc $08,x ;increase msb of script pointer L53E1: rts ;return ;function $29 equal/if clear goto L53E2: if system=0 tsx ;get current data silo pointer lda $03,x ;get saved condition register tap ;transfer A to condition register else bsr LTSXLDATAP endif ;system beq unconditional_goto ;goto bra L53D4 ;function $28 not equal/if set goto L53EA: if system=0 tsx ;get current data silo pointer lda $03,x ;get saved condition register tap ;transfer A to condition register else bsr LTSXLDATAP endif ;system bne unconditional_goto ;goto bra L53D4 if system=1 LTSXLDATAP: tsx ;get current data silo pointer lda $05,x ;get saved condition register (taking into account the return address of this routine) tap rts endif ;shave some bytes ;function $55 gosub assembly routine L53F2: jsr next2_in_x ;get next 2 script parameters into X jmp 0,x ;execute assembly routine L53F7: jsr next2_in_x L53FA: swi ;start pigs func41 L53FC: tsx ldx $06,x swi ;start pigs func41 L5401: tsx lda $06,x sta $08,x lda $07,x sta $09,x lda #$FF ;set pigs multiprocessing flag in this data silo sta $02,x lda $0D,x sta $03,x rts ;function $2e equal/if clear gosub L5413: if system=0 tsx ;get current data silo pointer lda $03,x ;get saved condition register tap ;transfer A to condition register else bsr LTSXLDATAP endif ;system beq L53F7 ;equal/clear, branch to gosub if system=0 JUMP L53D4 else bra L53D4 endif ;system, shave a byte ;function $2d not equal/if set gosub L541C: if system=0 tsx ;get current data silo pointer lda $03,x ;get saved condition register tap ;transfer A to condition register else bsr LTSXLDATAP endif ;system bne L53F7 if system=0 JUMP L53D4 else bra L53D4 endif ;system, shave a byte ;function $2f unconditional return unconditional_return: ins ins ins ins ins ins ins ins ins ins ;clear data silo tpa ;get current condition register into A tsx ;get [previous] data silo pointer stb $04,x ;save B sta $03,x ;save condition register rts ;return ;function $31 eqreturn/if clear return L5436: if system=0 tsx ;get current data silo pointer lda $03,x ;get saved condition register tap ;transfer A to condition register else bsr LTSXLDATAP endif ;system beq unconditional_return ;equal to zero, branch to return rts ;return ;function $30 notereturn/if set return L543D: if system=0 tsx ;get current data silo pointer lda $03,x ;get saved condition register tap ;transfer A to condition register else bsr LTSXLDATAP endif ;system bne unconditional_return ;not equal, branch to return rts ;return ;function $32 if tilted, return tilted_return: lda #$08 ;lamp to check bra L544A ;finish in other routine ;function $33 if game over, return gameover_return: lda #$04 ;lamp to check L544A: anda $001F ;lamps 30-37 bne unconditional_return ;lamp is on, branch to unconditional return rts ;return ;function $34 check active game notactive_return: lda $0025 ;flags 60-67 bpl unconditional_return ;flag clear, not in an active game, branch to pigs unconditional return $2f rts ;return ;function $43 push data silo push_data_silo: swi ;start pigs func42 L5456: tsx lda $0E,x sta $04,x lda $12,x sta $08,x lda $13,x sta $09,x lda #$FF ;set pigs mutiprocessing flag sta $02,x ;save in this data silo rts ;return ;function $44 pull data silo pull_data_silo: tsx 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 ;move stack pointer from silo rts ;return ;function $52 bcd increment memory location bcd_increment: jsr next_in_b ;get next script parameter in B (width of memory) jsr next2_in_x ;get next 2 script parameters in X (location of memory+1) L5484: lda #$01 ;setup to add one dex ;move to next set of digits adda $00,x ;add daa ;correct for humans sta $00,x ;save bcc L5491 ;done, branch decb ;width-- bne L5484 ;not done, keep going L5491: rts ;return ;function $53 bcd decrement memory location - only used once to decrement credits! bcd_decrement: jsr next_in_b ;get next script parameter in B (width of memory) jsr next2_in_x ;get next 2 script parameters in X (location of memory+1) L5498: lda #$99 ;setup to subtract one dex ;move to next set of digits adda $00,x daa ;correct for humans sta $00,x ;save bcs L54A5 ;done decb ;width-- bne L5498 ;not done, keep going L54A5: rts ;return ;function $35 increment B L54A6: tsx ;get current data silo pointer incb ;increment bra L54C6 ;save in other routine ;function $37 decrement B L54AB: tsx ;get current data silo pointer decb ;decrement bra L54C6 ;save in other routine ;function $36 increment memory in X L54B0: jsr next2_in_x ;use next 2 script parameters to set X inc $00,x ;increment memory rts ;return ;function $38 decrement memory in X L54B6: jsr next2_in_x ;use next 2 script parameters to set X dec $00,x ;decrement memory rts ;return ;function $39 load B immediate L54BC: jsr next_in_b ;get next script parameter in B rts ;return ;function $3a load B from memory location L54C0: jsr next2_in_x ;use next 2 script parameters to set X L54C3: ldb $00,x ;get B tsx ;get current data silo pointer L54C6: stb $04,x ;save B rts ;return ;function $3b storebmem L54C9: jsr next2_in_x ;use next 2 script parameters to set X L54CC: stb $00,x ;save B rts ;return ;function $5b loadb from zeropage loadbz: jsr XZERO bra L54C3 ;finish in loadbmem routine ;function $5c storeb to zeropage storebz: jsr XZERO bra L54CC ;finish in storebmem routine ;function $3c compare A to B L54CF: jsr next_in_a ;get next script parameter in A bra L54D9 ;function $3d compare B to memory location in X L54D4: jsr next2_in_x ;use next 2 script parameters to set X lda $00,x ;get memory location into A L54D9: psha ;save A for comparison tsx ;current data silo cmpb $00,x ;compare B to pushed A bra L5501 ;finish in other routine ;function $3e OR A,B L54E2: jsr next_in_a ;get next script parameter in A psha ;save A for comparison tsx ;current data silo orb $00,x ;or B with pushed A bra L5501 ;finish in other routine ;function $3f EOR A,B L54EE: jsr next_in_a ;get next script parameter in A psha ;save A for comparison tsx ;current data silo eorb $00,x ;eor B with pushed A bra L5501 ;save in other routine ;function $40 AND A,B L54FA: jsr next_in_a ;get next script parameter in A psha ;save A for comparison tsx ;current data silo andb $00,x ;and B with pushed A L5501: pula ;waste A tpa ;put the condition register in A sta $04,x ;save the condition register rts ;return ;function $2a save current player status save_player_status: bsr set_X2_current_player ;set X to currently up player save location stx $02F1 ;save X as the destination pointer ldx #$0015 ;set X to source pointer L550E: stx $02EF ;save X as the source pointer L5511: pshb ;save B ldb #$11 ;setup counter for the # of bytes to copy L5514: ldx $02EF ;get source pointer lda $00,x ;get source byte inx ;goose source pointer stx $02EF ;save source pointer ldx $02F1 ;get destination pointer sta $00,x ;save byte inx ;goose destination pointer stx $02F1 ;save destination pointer decb ;decrement the byte counter bne L5514 ;not done, keep going pulb ;restore B rts ;return ;function $2b restore curent player status L552B: ldx #$0015 ;destination pointer stx $02f1 ;save bsr set_X2_current_player ;get current player save location into X bra L550E ;finish in other routine ;set X to current player save location set_X2_current_player: lda $38 ldx #$0280 PLOOP: deca beq PSETX ; jsr xby11 inx inx inx inx inx inx inx inx inx inx inx bra PLOOP PSETX: rts ;function $4a show credits L554F: pshb ;save B ;check if credits for apron lamp (independant of dip 20) lda $2ce ;audit 5, current credits beq no_credits swi ;start pigs lampon $2b ;apron credit lamp bra skip_no_credits no_credits: swi ;start pigs lampoff $2b ;apron credit lamp skip_no_credits: lda #$FF ;setup blank as default swi checklampvalue $7b ;dip 20, show credits beq dont_show_credits ;it's off, don't show credits lda $02CE ;audit 5, current credits dont_show_credits: 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 ;calculate max credits ldb $0028 ;dips 17-24 andb #$07 ;isolate dips 17/18/19 (max credits) incb ;ensure a minimum of 1 clra ;A will be the max # of credits calculate_max_credits: adda #$05 ;minimum # of credits is 5 if all 3 dips were off daa ;correct for humans decb ;dip counter bne calculate_max_credits ;not done, keep going ;max credits in A cmpa $02CE ;compare calculated max to current credits pulb ;restore B bhi lockout_on ;still credits, branch lockout_off: swi ;start pigs cont_solenoid_off_coin ;turn off coin lockout rts ;return lockout_on: swi ;start pigs cont_solenoid_on_coin ;turn on coin lockout rts ;return ;function $48 update match L559A: swi ;start pigs checklampvalue $7c ;dip 21, match bne L55A4 ;it's on, branch to show match lda #$EE ;dip 21 off, no match, setup blanking digit bra save_match_disp ;save in match display and return ;match ok L55A4: swi ;start pigs lampbvalueon $29 ;turn on match lamp lda $0039 ;get match # bra save_match_disp ;save in match display and return ;function $49 show ball in play L55AF: swi ;start pigs lampbvalueoff $29 ;turn off match lamp lda $0037 ;current ball in play ora #$F0 ;blank the first digit save_match_disp: sta $0013 ;save on ball in play display rts ;return ;function $46 blank current player L55BC: bsr X2blankmask_A2validplay ;set X to current player blanking mask and A to valid player bit L55BE: 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 L55C8: bsr X2blankmask_A2validplay ;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 current player ;copies information from scratch ram $15-$18 to currently up player display, blanking leading zeros L55D1: pshb ;save B lda #$FC ;p1 score display-4 ldb $0038 ;currently up player L55D6: adda #$04 ;move to next player decb ;currently up player as a counter bne L55D6 ;not done, keep going psha ;save player location lsb pshb ;save player location msb (will be zero because of loop at 55d6) tsx ;get stack pointer ldx $00,x ;get player display location from stack pulb pulb ;waste the ephemeral bytes lda $0015 ;player x-1m digit bsr blank_lead_zero_save_atX;blank leading zero lda $0016 ;player 100k-10k digit ldb $0017 ;player 1k-100 digit bsr L5612 ;blank leading zero if previous digits blank lda $0018 ;player 10-1 digit sta $00,x ;this digit always ok to display both since 00 is ok, and 0[1-9] can't exist pulb ;restore B bsr X2blankmask_A2validplay ;set X to current player blanking mask and A to valid player bit bsr L55BE ;subroutine does the same as this except also puts $ff in x... clr $00,x ;...which is cleared right here anyway rts ;return ;set X to current player blanking mask location and A to valid player bit ;1xxx xxxx p1 ;x1xx xxxx p2 ;xx1x xxxx p3 ;xxx1 xxxx p4 ;xxxx 1xxx p5 (credit/match/ball in play) X2blankmask_A2validplay: lda #$80 ;player 1 valid bit ldx #$0068 ;start of blanking masks pshb ;save B ldb $0038 ;currently up player L5603: decb ;decrement beq L560A ;found, X and A set inx ;move to next player blank mask location lsra ;shift valid player bit bra L5603 ;keep searching L560A: pulb ;restore B rts ;return ;blank leading byte if zero and save at X blank_lead_zero_save_atX: bne L560F deca ;make 00 #$ff (blank) L560F: sta $00,x rts L5612: psha lda $00,x inx inca pula bne L5626 tsta bne L5620 deca bra L562D L5620: bita #$F0 bne L5626 ora #$F0 L5626: sta $00,x inx stb $00,x inx rts L562D: tstb bne L5633 decb bra L5626 L5633: bitb #$F0 bne L5626 orb #$F0 bra L5626 ;function $4b show high score to date L563B: ldx #$0000 ;destination display pshb lda $02CA ;x-1m hstd bsr blank_lead_zero_save_atX ;blank if zero lda $02CB ;100k-10k hstd ldb $02CC ;1k-100 hstd bsr L5612 ;blank if leading zeros lda $02CD ;10-1 hstd sta $00,x ;always ok to display 00 pulb ;restore B ;copy hstd onto all 4 displays ldx $0000 stx $0004 stx $0008 stx $000C ldx $0002 stx $0006 stx $000A stx $000E swi ;start pigs lampbvalueon $31 ;hstd lamp ;function $4c all displays valid L5668: ldx #$0000 ;setup clear blanking mask L566B: clr $0067 ;clear valid players register stx $006B ;save blanking mask for p4/p5 stx $0068 ;save blanking mask for p1/p2 stx $006A ;save blanking mask for p3/p4 rts ;return ;function $4d all displays invalid L5675: ldx #$FFFF ;setup blanking mask bra L566B ;branch to save mask ;function $4e transfer scores to display L567A: ldx #$0000 pshb lda $0280 bsr blank_lead_zero_save_atX lda $0281 ldb $0282 bsr L5612 lda $0283 sta $00,x inx lda $0291 bsr blank_lead_zero_save_atX lda $0292 ldb $0293 bsr L5612 lda $0294 sta $00,x inx lda $02A2 bsr blank_lead_zero_save_atX lda $02A3 ldb $02A4 bsr L5612 lda $02A5 sta $00,x inx lda $02B3 bsr blank_lead_zero_save_atX lda $02B4 ldb $02B5 bsr L5612 lda $02B6 sta $00,x pulb clr $0067 swi lampbvalueoff $31 ;hstd lda $02EE ;# of players in current game deca anda #$03 inca ldx #$0068 L56E5: clr $00,x inx deca bne L56E5 deca L56EC: cpx #$006C beq L56F6 sta $00,x inx bra L56EC L56F6: rts ;return ;function $4f score directly L56F7: lda #$01 ;setup row 0 trip (set active ball status) ora $004B sta $004B jsr next_in_a ;get next script parameter into A ;actually score L5700: psha ;save score byte ; swi ; trip_switch 71 L5701: lda $001F anda #$08 pula ;get score byte back bne L56F6 ;tilted, branch to return ;add score pshb ;save B tab anda #$0F lsrb lsrb lsrb lsrb lsrb bcc L5717 asla asla asla asla L5717: ldx #$0019 ;player score location L571A: dex decb bpl L571A L571E: adda $00,x daa sta $00,x bcc L572D lda #$01 dex cpx #$0014 bne L571E L572D: lda #$FF ;setup score blink timer sta $004E ;save score blink timeout swi ;start pigs rcflagset ;set pigs multiprocessing flag update_current_player show_current_player ila ;clear pigs multiprocessing flag/return to assembly ;check for replay score surpassed ldx #$02C4 ;audit 1, replay level 1 clr $02EF ldb #$80 L573E: lda $00,x anda #$0F ora $01,x beq L575C lda $00,x anda #$0F cmpa $0015 bhi L575C lda $01,x cmpa $0016 bhi L575C tba orb $02EF stb $02EF tab L575C: lsrb inx inx ;move to next replay level cpx #$02CA ;done with all replay levels? bne L573E ;no, keep checking lda $0020 anda #$E0 coma ;flip for mask anda $02EF ;this is holding the replay level surpassed tab ;put in B temporarily ora $004B ;add to direct virtual column 7 action register sta $004B ;save action register orb $20 ;set flag for replay level passed stb $20 ;save flag pulb ;restore B rts ;return ;function $51 clear variables $2a-$36 and $15-$25 L5778: ldx #$0015 ldb #$04 loop51: clr 0,x decb bpl skip_offset clr $11,x skip_offset: inx cpx #$0026 bne loop51 rts ;function $56 add to score queue L578F: lda #$01 ;setup row 0 trip (set active ball status) ora $004B ;add to virtual column 7 action register sta $004B ;save virtual column 7 action register jsr next_in_a ;get next script parameter into A ldx #$006D ;score queue pointer L579B: cmpa #$10 ;found queue bcs L57A4 ;yes, branch inx ;move to next queue suba #$10 ;adjust marker to next score queue bra L579B ;keep searching L57A4: adda $00,x ;add steps to score queue sta $00,x bcc L57B4 inx cpx #$0074 beq L57B4 ;you lose score overflow from 100k! lda #$01 bra L57A4 ;add to next higher score queue if the lower one overflowed L57B4: rts ;return ;function $59 play speech L57BD: jsr next2_in_x ;get next 2 script parameters into X ; bsr L57EC ;cannot encapsulate these into another subroutine as will mess up script offset sei lda #$78 sta $02FF bra L57CF ;function $57 play primary sound L57CA: jsr next2_in_x ;get next 2 script parameters into X ; bsr L57EC L57CF: lda #$FF sta $0051 bra L57E4 ;function $58 play secondary sound L57D5: jsr next2_in_x ;get next 2 script parameters into X ; bsr L57EC lda $0051 cmpa #$40 bhi L57EB lda #$40 sta $0051 L57E4: sei stx $0074 L57E7: clr $0053 cli L57EB: rts ;do game over game_over: lampoff $33,$67 ;tilt, active game cont_solenoid_off_flipper ;flippers off lampbvalueon $32 ;game over lampbvalueoff $40 ;outhole reentrancy flag update_match ;process match ila ;clear pigs multiprocessing flag/return to assembly ;check match ldx #$0003 L5805: lda $0013 pshb cmpa $00,x swi ;start pigs ifcleargosub award_a_credit ;award a credit pulb inx inx inx inx ;move to next player's 10-1s digits decb dec $2ee bne L5805 jsr L58CF L5819: jsr switch_dispatch ;switch dispatch ldx $0074 ;sound script pointer bne L5819 ;wait until sound from game done swi ;start pigs rcflagset ;set pigs multiprocessing flag delay $46 ;short wait gosub attract_mode_lamps ;initialize attract mode lamp thread ;check score queues and process switches L5846: jsr switch_dispatch ;switch dispatch L5849: lda $006D ;1s queue ora $006E ;10s ora $006F ;100s ora $0070 ;1k ora $0071 ;10k ora $0072 ;100k ora $004B ;anything in the virtual column 7 action register? bne L5846 ;keep processing switches/score, sound queues rts ;return ;clear all virtual switch timers L585A: ila ;clear pigs multiprocessing flag/return to assembly ldx #$0053 ;start right below virtual column 5 timers clrb ;value to save in timers L585F: inx ;move to next timer stb $00,x ;clear timer cpx #$0063 ;done? bne L585F ;no, keep going stb $0049 ;clear timed virtual column 5 action register stb $004A ;clear timed virtual column 6 aciton register stb $004B ;clear direct virtual column 7 action register rts ;return add_credit: loadbmem $0092 ;pia solenoid register aandb $20 ;isolate coin lockout notereturn ;it's off, max credits reached goto increment_credit ;increase credit ;virtual column 7 row 7, replay level 1 surpassed award1: bcdinc $02,$02ea ;increment audit 16, replay level 1 surpassed goto award_replay ;branch to replay award ;virtual column 7 row 6, replay level 2 surpassed award2: bcdinc $02,$02ec ;increment audit 17, replay level 2 surpassed goto award_replay ;branch to replay award ;virtual column 7 row 5, replay level 3 surpassed award3: bcdinc $02,$02ee ;increment audit 18, replay level 3 surpassed award_replay: checklampvalue $6d ;check dip 6, replay award on=replay off=extra ball ifcleargoto awardextraball ;dip 6 off, set to extra ball, branch to award extra ball award_a_credit: ;sound_play_primary L1B52 ;play replay sound effect L5894: tiltreturn ;return if tilted loadbmem $0092 ;pia solenoid register aandb $20 ;isolate coin lockout notereturn ;it's off, max credits reached, just return bcdinc $03,$02d5 ;increase audit 7, total replays enable_solenoid_05 $05 ;knocker enable_solenoid_0f $05 ;time waster increment_credit: bcdinc $01,$02cf ;increase # of credits show_credits ;ensure displayed credits match stored credits return ;return ;c0r6 tilt tilt: tiltreturn ;if already tilted, return cont_solenoid_off_flipper ;kill flipper relay lampbvalueon $33 ;tilt lamp ; clearb ; storebmem $0079 lampbvalueoff $67 ;clear active game flag gameoverreturn ;return if game over enable_solenoid_0f $fa ;use solenoid F as a delay enable_solenoid_0f $00 ; xloadgosub L1650 ;set timers $62 and $5a return ;check hstd L58CF: ldx $02ca ;x-1m-100k-10k of hstd stx $15 ;save in scratch ram upper word ldx $02CC ;1k-100-10-1 of hstd stx $0017 ;save in scratch ram lower word ldx #$0280 ;player 1 score location bsr L58E2 ;check p1 bsr L58E2 ;check p2 bsr L58E2 ;check p3 ;check p4 L58E2: lda $0015 anda #$0F ldb $00,x andb #$0F stb $00,x cmpa $00,x bcs award_hstd bne L5959 lda $0016 cmpa $01,x bcs award_hstd bne L5959 lda $0017 cmpa $02,x bcs award_hstd bne L5959 lda $0018 cmpa $03,x bcs award_hstd bra L5959 ;award hstd award_hstd: swi ;start pigs rcflagset ;set pigs multiprocessing flag bcdinc $02,$02d7 ;increase audit 8, # of times hstd beaten checklampvalue $6d ;check dip 6, part of hstd award ifsetgosub award_a_credit ;award a credit checklampvalue $6e ;check dip 7, part of hstd award ifcleargoto L5920 ;it's off gosub award_a_credit ;award a credit gosub award_a_credit ;award a credit L5920: ila ;clear pigs multiprocessing flag/return to assembly ;store the hstd L5921: lda $02CA cmpa $00,x bcs L5945 bne L5959 lda $02CB cmpa $01,x bcs L5945 bne L5959 lda $02CC cmpa $02,x bcs L5945 bne L5959 lda $02CD cmpa $03,x bcs L5945 bra L5959 L5945: lda $00,x sta $02CA lda $01,x sta $02CB lda $02,x sta $02CC lda $03,x sta $02CD L5959: stx $02EF ;save X lda #$11 ;offset to next player save area adda $02F0 ;add to lsb of X (never a carry) sta $02F0 ;save new lsb ldx $02EF ;get X rts ;return self_test: ldx #system_reset ;setup reboot instead of debug stx $0078 clra sta $0064 swi clearplayflags jsr L5AC8 swi ;start pigs all_displays_invalid ;make sure all displays off jsr L5AC8 L5993: bsr L59F7 ;invert all lamps bsr L5A03 ;delay and test self-test switch beq L5993 ;self-test flag clear, keep up lamp test swi ;start pigs clearplayflags ;clear all lamps ;display test swi ;start pigs all_displays_valid ;make sure all displays on lda #$FF sta $0076 L59A1: jsr L5A2F bsr L5A03 ;delay and test self-test switch beq L59A1 ;self-test flag clear, keep running display test ;solenoid test lda #$FF sta $0077 L59AC: jsr L5A77 jsr L5A9C bsr L5A03 ;delay and test self-test switch beq L59AC ;self-test flag clear, keep running solenoid test ;switch test jsr L5AC8 L59B9: clr $0077 ;setup switch counter ldx #$003F L59BF: ldb #$08 lda $00,x L59C3: inc $0077 lsra bcs L59EA decb bne L59C3 inx cpx #$0044 bne L59BF ldx #$FFFF ;setup mask stx $0068 ;p1-p2 displays invalid stx $006A ;p3-p4 displays invalid ldb #$F0 ;setup up match display for no switches closed stb $0013 ;save in match/ball in play display ldx #$FFFF ;ensure rest of credit/match display is blank stx $0010 ;save in credit display stx $0011 ;save in credit display lda #$08 ;setup credit/match display as active sta $0067 ;set credit/match display as only valid player bra L59F0 L59EA: dec $0077 ;get correct switch # jsr L5A9C ;put on displays L59F0: bsr L5A03 ;delay and test self-test switch beq L59B9 ;self-test flag clear, keep running switch test jmp L5AD1 ;go to audits/adjustments ;invert all lamps L59F7: ldx #$0019 ;lamp start L59FA: com $00,x ;flip inx ;move to next lamp set cpx #$0021 ;done? bne L59FA ;no, keep going rts ;return ;delay and test self-test switch L5A03: bsr L5A1D ;delay bsr L5A1D ;delay bsr L5A1D ;delay bsr L5A1D ;delay lda $0066 ;check mni flag beq L5A13 ;it's clear ldx $0078 ;get nmi jump address jsr 0,x ;execute L5A13: clr $0066 ;clear mni flag lda $0064 ;get self-test switch flag clr $0064 ;clear self-test switch flag tsta ;test self-test switch flag rts ;return L5A1D: lda #$0E sta $004D L5A21: lda $004D bne L5A21 deca sta $0092 rts ;return L5A29: dex L5A2A: inx deca bpl L5A2A rts L5A2F: lda $0076 inca cmpa #$11 bcs L5A37 clra ;reset to 0 L5A37: sta $0076 ldx #L5BC5 ;self-test display data bsr L5A29 lda $00,x cmpa #$9A bcc L5A4E ;blank sta $0000 sta $0001 sta $0002 sta $0003 bra L5A6C L5A4E: ldx #$FFFF ;setup blank stx $0000 ;save in p1 display left word stx $0002 ;save in p1 display right word suba #$A0 tab asrb ldx #$0000 L5A5C: tstb beq L5A63 inx decb bra L5A5C ;walk 8 across displays L5A63: ldb #$8F asra bcc L5A6A ldb #$F8 L5A6A: stb $00,x ;save walking 8 L5A6C: bsr L5AB6 ;copy p1 display to p2, p3, p4 ldx $0000 ;copy p1 display to credit/ball in play display stx $0010 ldx $0002 stx $0012 rts ;return L5A77: lda $0077 ;get current solenoid step inca ;move to next step cmpa #$1D ;29, done with sound test? bcs L5A7F ;no clra ;reset solenoid test to start L5A7F: sta $0077 ;save current solenoid step cmpa #$13 ;test step 19? bge L5A8F ;yes, test sound ldx #L5BB1 ;self-test solenoid data bsr L5A29 ;set X to correct solenoid index lda $00,x ;get solenoid data sta $0092 ;save rts ;return L5A8F: suba #$13 ldx #L5BE9 asla ;double for indexing bsr L5A29 ;set X based on X and A ldx $00,x ;get sound pointer stx $0074 rts L5A9C: swi all_displays_valid lda #$FF sta $006C lda $0077 tab clra incb L5AA7: adda #$01 daa decb bne L5AA7 sta $0003 ldx #$FFFF stx $0000 stx $0001 L5AB6: ldx #$0000 L5AB9: lda $00,x sta $04,x sta $08,x sta $0C,x inx cpx #$0004 bne L5AB9 rts L5AC8: lda #$01 sta $00A1 sta $00A0 sta $00C0 rts ;audits/adjustments L5AD1: ldx #L5B9F ;setup S33/NMI routine for audits/adjustments (zero) stx $0078 ;save lda #$01 ;setup audit #/display sta $0038 ;save audit # sta $0013 ;put audit # on ball in play display swi ;start pigs all_displays_valid ;make sure all displays on ldx #$FFFF stx $0010 stx $0011 ldx #L5BD6 ;audit/adjustment data table stx $007A ldx #$02C4 ;adjustment #1 location stx $02F1 ;save as source L5AF0: bsr L5B4D ;pull data from nvram for displays swi ;start pigs update_current_player bsr L5AB6 ;copy p1 display to p2, p3, p4 ldx $007A ;pointer for width list ldb $00,x bgt L5B32 ;sign bit clear, disallow setting lda $003F ;switch matrix col 0 history register anda #$20 ;isolate credit button beq L5B32 ;not pressed, branch swi ;start pigs score $41 ;increase adjustment by 10k ldx $007A ;get pointer for width list ldb $00,x ;get width if system=0 tstb bgt L5B0E endif ;system - you don't need to test the width again because only ones that were set like this are modifiable negb ;negate the width to get the counter L5B0E: ldx $02F1 ;get audit pointer back lda $0015 sta $00,x decb beq L5B2A lda $0016 sta $01,x decb beq L5B2A lda $0017 sta $02,x decb beq L5B2A lda $0018 sta $03,x L5B2A: bsr L5AB6 ;copy p1 display to p2, p3, p4 L5B2D: jsr L5A1D L5B30: bra L5AF0 ;put same audit back on display L5B32: jsr L5A03 ;delay and test self-test switch beq L5AF0 bsr L5B4D ;pull data from nvram for displays stx $02F1 ldx $007A inx stx $007A lda $0013 ;get current audit/adjustment adda #$01 ;move to next audit/adjustment daa ;correct for humans sta $0013 ;put on match display bra L5AF0 ;keep going L5B4A: jmp system_reset ;reboot L5B4D: ldx #$0000 stx $0015 stx $0017 ;clear scratch ram in anticipation of copying varying widths of data ldx $007A ;get width pointer back ldb $00,x ;get audit width beq L5B4A ;end of self test, go reboot if system=0 bgt L5B5D ;sign bit clear, branch negb ;negate B L5B5D: ldx $02F1 ;source location cpx #$02C4 ;audit 1, replay level 1 beq L5B94 cpx #$02C6 ;audit 2, replay level 2 beq L5B94 cpx #$02C8 ;audit 3, replay level 3 beq L5B94 cmpb #$04 ;width 4? beq L5B7F cmpb #$03 ;width 3? beq L5B84 cmpb #$02 ;width 2? beq L5B89 cmpb #$01 ;width 1? beq L5B8E L5B7F: lda $00,x sta $0015 inx else ldx $2f1 ;source location tstb bmi L5B94 ;sign bit set, it's audit 1, 2, 3, or 4 decb beq L5B8E ;it was 1 decb beq L5B89 ;width was 2 ;assume width 3 for all other entries (hstd is 4, but handled in other routine) endif L5B84: lda $00,x sta $0016 inx L5B89: lda $00,x sta $0017 inx L5B8E: lda $00,x sta $0018 inx rts ;copy replay adjustment levels down, only first 2 bytes L5B94: if system=1 negb ;negate B endif ;system lda $00,x sta $0015 inx lda $00,x sta $0016 inx if system=1 decb decb bne L5B89 ;it was the hstd - do the last 2 digits endif rts ;routine for clear in audits/adjustments L5B9F: ldx $007A ;get pointer for audit width ldb $00,x ;get width ldx $02F1 ;get pointer to audit tstb ;test width bgt L5BAA ;sign bit clear, branch negb ;negate B L5BAA: clr $00,x inx decb ;width-- bne L5BAA rts ;return ;self-test solenoid data L5BB1: db $f1,$f0,$f5,$f6,$f2,$f3,$f4,$f7 db $fa,$fb,$fd,$fc,$f8,$f9,$bf,$fe db $ef,$7f,$df,$ff ;self-test display data L5BC5: db $00,$11,$22,$33,$44,$55,$66,$77 db $88,$99,$a1,$a2,$a3,$a4,$a5,$a6,$a7 ;self-test audit data, type/width - sign bit set=can modify (10k increments only) L5BD6: db $fe,$fe,$fe,$fc,$01,$03,$03 db $02,$03,$03,$03,$02,$02,$02,$02 db $02,$02,$02,$00 L5BE9: dw L5BFD dw L5C19 dw L5C34 dw L5C3B dw L5C3E dw L5C41 dw L5C44 dw L5C47 dw L5C4A dw L5C4D L5BFD: db $13,$22,$00,$80,$04,$08 db $18,$22,$01,$00,$08 db $18,$22,$02,$00,$08 db $18,$22,$04,$00,$08 db $18,$22,$08,$00,$08 db $18,$00 L5C19: db $24,$00,$80,$02,$08 db $18,$24,$01,$00,$08 db $18,$24,$02,$00,$08 db $18,$24,$04,$00,$08 db $18,$24,$08,$00,$08 db $18,$00 L5C34: db $26,$60,$00,$01,$0d,$08 db $09 L5C3B: db $0d,$19,$09 L5C3E: db $0d,$2a,$09 L5C41: db $0d db $3b,$09 L5C44: db $0d,$4c,$09 L5C47: db $0d db $5d,$09 L5C4A: db $0d,$6e,$09 L5C4D: db $0d,$7f,$08 db $ff ;speech data test L5C51: db $1a,$40,$80,$d4,$41,$81,$d4,$42 L5C59: db $82,$d4,$44,$83,$d4,$4a,$84,$d4 L5C61: db $52,$85,$d4,$62,$86,$d4,$7a,$87 db $d4,$1b,$00 ;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 $2ee ;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 ;c0r5 credit button credit: loadbmem $02ce ;check for credits bacomp $00 ;any credits? eqgoto cb4 ;no credits, see if freeplay lampbvalueoff $3b ;blank match lamp checklampvalue $32 ;game over ifsetgoto L5CBB ;it's game over, always ok to start a new game ;in a game - check if on ball one loadbmem $0037 ;ball in play bacomp $01 ;on ball one? notegoto L5CBB ;>ball one, [re]start a new game ;on ball one - check if max players loadbmem $02ee ;# of players, current game bacomp $04 ;already at 4? eqreturn ;yes, return ;add a player L5C85: lxiw $02ee ;increase # of players gosub L5CB1 ;decrease credits/add to total plays save_current_player xfer_scores_to_displays show_current_player ila ;clear pigs multiprocessing flag/return to assembly lda $02EE ;# of players in current game deca deca bne L5C9A ;not player 2 swi ;start pigs ;sound_play_speech L1998 ;speech 'player 2 stand by' L5C9A: deca bne L5CA1 ;not player 3 swi ;start pigs ;sound_play_speech L19A1 ;speech 'player 3 stand by' L5CA1: deca bne L5CA8 ;not player 4 swi ;start pigs ;sound_play_speech L19AA ;speech 'player 4 stand by' L5CA8: ;debounce credit button sei ;prevent interrupts lda $0044 anda #$DF sta $0044 cli ;allow interrupts rts L5CB1: bcddec $01,$02cf ;decrease credits show_credits ;ensure displayed credits match stored credits bcdinc $03,$02d2 ;increase audit 6, total plays return ;return L5CBB: checklampvalue $66 ;ball walker re-entrancy flag ifsetreturn ;set, return gosub L585A ;clear all virtual switch timers ila ;clear pigs multprocessing flag/return to assembly clra ;setup to clear score queues ldx #$0073 L5CCC: sta $00,x dex ;move to next queue cpx #$006C ;done? bne L5CCC ;no, keep going sta $0079 ;banked add a balls inca ;setup values of 1 sta $02EE ;# of players in current game sta $0037 ;current ball in play lda #$04 ;ensure player up rolls over sta $0038 ;currently up player swi ;start pigs L5CE1: rcflagset ;set pigs multiprocessing flag show_ball_in_play ;get current ball in play on display gosub L5CB1 ;decrease credits/add to total plays clear_var ;clears $15-$25 and $2a-$36 if exp=0 lampbvalueon $00 ;bonus 1k lampbvalueon $0b ;release next rocket lampbvalueon $29 ;right spinner 500 lampbvalueon $27 ;drop 5 else lampon $00,$0b,$29,$27 endif ;exp ila L5D08: swi save_current_player ;save current player dec $38 ;current player-- bne L5D08 ;not done, save the rest inc $0038 ;back to player 1 up swi ;start pigs xfer_scores_to_displays ;put player 1 score up lda #$5A ;setup timer for switch re-scanning sta $0062 ;save in timer swi ;start pigs gosub game_start ;game start routine bra L5D2F L5D2B: swi ;start pigs gosub L5E6D ;5 bank housekeeping L5D2F: jsr L5CA8 ;debounce credit button jmp main_loop ;jump to main loop ;swi pigs engine start_pigs: clra ;set a stop marker psha ;save tsx ;get current data silo pointer lda 0,x ;get saved zero tap ;clear the condition register L5D3B: ldx $06,x ;get current script pointer lda $00,x ;get pigs command asla ;double for indexing psha ;save as the lsb lda #hi L5000 ;pigs function table msb adca #$00 ;get any carries (should not be until pigs functions >$7f if function table stays on page boundry) psha ;save the msb tsx ;get the stack pointer inc 9,x ;advance script lsb bne L5D4D ;no carry, branch inc 8,x ;advance script msb L5D4D: ldx $00,x ;get pigs function pointer ldx $00,x ;get pigs function ins ;clear the stack pula ;clear the stack jsr 0,x ;execute function tsx ;get data silo pointer back lda $00,x ;get pigs mutiprocessing flag bne L5D3B ;it's set, keep processing script pula ;waste 00 rti ;return from interrupt ;function $18 set pigs multiprocessing flag L5D5C: lda #$FF ;setup flag L5D5E: tsx ;get data silo pointer sta $02,x ;save flag rts ;return ;function $19 clear pigs multiprocessing flag L5D62: clra bra L5D5E outhole: gameoverreturn ;return if not in an active game checklampvalue $40 ;trough reentrancy flag ifsetreturn ;set, return lampregbon ;set flag $40 lampbvalueoff $67 ;clear active ball ; xloadgosub L1101 ;check queues for emptiness ; xloadgosub L10E8 ;safe blinking lamps gosub L585A ;clear all virtual switch timers checklampvalue $3c ;check score flag ifcleargoto launch_ball ;no score, relaunch ball ; goto L5D8E ;progress to next ball/player/game over/etc. ; goto L50B5 ;count bonus and progress to next ball ;end ball L5D8E: xloadgosub L5849 ;check score queues and timers lampbvalueoff $33 ;clear tilt lamp before saving save_current_player ;copy player status update_current_player checklampvalue $28 ;shoot again ifcleargoto L5DB5 lampregbblinkon ;blink shoot again ila ;clear pigs multiprocessing flag/return to assembly lda $0079 anda #$07 beq L5DA3 deca sta $0079 L5DA3: swi ;start pigs rcflagset ;set pigs multiprocessing flag goto L5DE2 ;ball start ball_start: gameoverreturn ;return if game over bcdinc $02,$02e2 ;audit 12 total balls played blinklampbvalueon $28 ;shoot again goto L5E4E L5DB5: loadbmem $0038 ;currently up player bxcomp $02ee ;# of players in current game notegoto L5DD9 checklampvalue $6e ; ifsetgoto L5DC8 ;set to 5 balls per game, branch loadb $03 ;set to 3 balls per game goto L5DCA L5DC8: loadb $05 L5DCA: bxcomp $0037 ;current ball in play eqgoto game_over ;go do game over lxiw $0037 show_ball_in_play clearb storebmem $0038 ;currently up player L5DD9: lxiw $0038 ;advance currently up player restore_current_player game_start: clearb storebmem $0079 L5DE2: xfer_scores_to_displays bcdinc $02,$02e2 ;audit 12, total balls played lampbvalueon $00 ;1k bonus checklampvalue $84 ;check dip 29, # of specials, on=1/game, off=1/ball ifsetgoto L5DFE ;dip 29 on, set to 1 a game checklampvalue $60 ;standup special already colleced flag ifcleargoto L5DF6 lampregboff ;clear flag 60 lampbvalueoff $62 ;clear flag 62 L5DF6: checklampvalue $61 ifcleargoto L5DFE lampregboff ;clear flag 61 lampbvalueoff $63 ;clear flag 63 L5DFE: ila ;clear pigs multiprocessing flag/return to assembly clra ;setup clear sta $0024 ;clear flags 58-5f swi ;start pigs checklampvalue $85 ;check dip 30, bonus multiplier, on=reset (conservative), off=leave (liberal) beq L5E0B ;dip 30 off, leave bonus multiplier, branch lda #$08 ;dip 30 on, reset bonus mutliplier - 1x bit sta $001A ;save 1x lit (cannot crunch because other lamps might be lit and not get cleared....) L5E0B: swi ;start pigs checklampvalue $7d ;dip 22, right spinner, on=reset (conservative), off=leave (liberal) beq L5E18 ;dip 22, off leave right spinner value, branch lda $001E ;lamps 28-2f anda #$E1 ;clear right spinner lamps ora #$02 ;set lamp 29, right spinner 500 sta $001E ;save lamps 28-2f L5E18: lda $0209 anda $0021 ;flags 40-47 anda #$30 ;isolate (flags 44,45) AND $209 register /10, /20 (lock status) asla asla ;shift to match lamps ora $001F ;add to lamps 30-37 (specifically 36, lock 2, and 37, lock 1) sta $001F ;save lamps 30-37 anda $0022 ;flags 48-4f anda #$E0 ;can only possibly have set/flow through 36-37/4e-4f ora $001E ;add to lamps 28-2f sta $001E ;save lamps 28-2f lda $001B ;field BLAST OFF swi ;start pigs rcflagset ;set pigs multiprocessing flag ; eqgosub L5222 ;blast off all lit, branch to test if 'all systems go' ready save_current_player ;save corrected player status checklampvalue $6e ;check dip 7, balls per game, on=5, off=3 ifsetgoto L5E3F ;dip on, set to 5 balls per game, branch loadb $03 ;dip off, set to 3 balls per game goto L5E41 ;branch L5E3F: loadb $05 ;set to 5 balls per game L5E41: bxcomp $0037 ;compare to current ball in play notegoto launch_ball ;not last ball, branch show_hstd ;show the high score to date at the start of the last ball delay $1e ;wait a short while xfer_scores_to_displays ;put player scores back launch_ball: gosub L5E6D ;5 bank housekeeping L5E4E: lampoff $3c,$40 save_current_player enable_solenoid_06 $08 ;launch ball enable_solenoid_0f $00 L5E57: ila ;clear pigs multiprocessing flag/return to assembly lda #$FE ;setup clear active ball direct activation anda $004B ;clear /01 sta $004B ;save c7 action sei ;prevent interrupts lda $0048 anda #$F8 sta $0048 lda $003F anda #$BF sta $003F cli ;allow interrupts rts ;return L5E6D: show_current_player ; xloadgosub L120C ;reset 5 bank ; gosub L113E ;reset 3 bank ; if exp=0 ; lampbvalueon $67 ;set active game flag ; lampbvalueoff $40 ; lampbvalueon $46 ;set spinner score allow flag ; lampbvalueoff $33 ;tilt ; else lampon $67,$46 lampoff $33,$40 ; endif ;exp ; xloadgosub L1086 ;start background sound cont_solenoid_on_flipper ;enable flipper relay return ;return ;virtual c7r0 validate playfield set_active_ball: checkactivegame ;return if not in an active game lampoff $41,$42,$43,$48,$49,$4a lampbvalueon $3c ;set playfield validated flag checklampvalue $28 ;shoot again ifclearreturn ;not lit, return lampregbon ;turn on shoot again loadbmem $0079 ;check for banked add a balls aandb $07 ;limit to 7 notereturn ;balls waiting - return lampbvalueoff $28 ;shoot again return ;return update_timers: asla ;shift the row for virtual switch timer usage sei ;prevent other interrupts tst $00,x ;timing? beq L5EA8 ;no, branch to return dec $00,x ;decrement this timer bne L5EA8 ;still timing, do not increase A inca ;A++ L5EA8: cli ;allow other interrupts inx ;increase timer rts ;return ;zero-cross interrupt ;update timers L5EAB: ldx #$004C ; L5EAE: bsr update_timers ;update settable timers $4c-$51 cpx #$0052 ;done? bne L5EAE ;no, keep going dec $00,x ;$52, 4-3-2-1 step timer bgt L5ED5 ;ok, branch (only update virtual switch timers on reset of step timer) lda #$04 ;reset to 4 sta $0052 ;save inx inx ;move to virtual column timers L5EBF: bsr update_timers ;update timers $54-5b cpx #$005C ;done? bne L5EBF ;no, keep going ora $0049 ;add row in A to virtual column 5 action register sta $0049 ;save virtual column 5 action register L5ECA: bsr update_timers ;update timers $5c-63 cpx #$0064 ;done? bne L5ECA ;no, keep going ora $004A ;add row in A to virtual column 6 action register sta $004A ;save virtual column 6 action register ;update match L5ED5: lda $0039 ;match anda #$F0 ;clear lsn adda #$10 ;add daa ;correct for humans sta $0039 ;save clrb ;setup B to not turn off any solenoids lda $004D ;check solenoid timer bne L5EE5 ldb #$0F ;setup to safe all momentary solenoids L5EE5: orb $0092 ;add solenoids to PIA port stb $0092 ;save port lda #$0A ;setup short delay L5EEB: deca ;delay-- bne L5EEB ;not done, keep going ;update lamps ldx #$0019 ;start at lamp matrix col 0 ldb #$F0 ;setup B as a shift register L5EF3: cli ;allow interrupts stb $0088 lda #$3C sei sta $008B lda #$34 sta $008B lda $00,x coma ;flip as lamps are actually active low bitb #$01 bne L5F0B asla asla asla asla dex L5F0B: sta $0088 inx incb bne L5EF3 ;lamp nibble updated, now execute lamp strobe - do the speech one first sei L5F56: clrb lda #$30 stb $0065 sta $008B stb $008A ldb #$34 stb $008B cli ;read switch matrix ldx #$003F lda #$20 L5F69: dex lsra sta $0088 beq L5F8C ldb #$1E L5F71: decb bne L5F71 psha lda $00,x eora $05,x anda $05,x ldb $05,x stb $00,x ldb $008A stb $05,x anda $05,x ora $0A,x sta $0A,x pula bra L5F69 L5F8C: coma ldb #$30 sei stb $008B sta $008A sta $0065 ldb #$35 lda $008A stb $008B cli lda $0067 beq L5FB5 ldb $004E bne L5FB5 ldb #$18 stb $004E ldx #$0068 tsta L5FAD: bpl L5FB1 com $00,x L5FB1: inx asla bne L5FAD ;handle blinking lamps L5FB5: lda $004F ;check blink timer bne fast_react ;not time to blink, branch lda #$0C ;setup blink timer sta $004F ;save blink timer ldx #$0019 ldb #$08 L5FC2: lda $00,x eora $11,x sta $00,x inx decb bne L5FC2 ;fast react solenoids fast_react: lda $0025 ;check flags 60-67 bpl L5FF2 ;not in an active game, exit ldb #$08 ;setup to fire left pop lda $0043 ;fast reacts in col 4 eora $003e ;col 4 anda $0043 ;col 4 anda #$f8 ;limit to top 5 beq L5FF2 ;none closed, exit L5FDE: bpl not_left_pop bra fire_fast_react not_left_pop: incb ;setup right pop $09 asla ;test right pop bpl not_right_pop bra fire_fast_react not_right_pop: incb ;setup bottom pop $0a asla ;test bottom pop bpl not_bottom_pop bra fire_fast_react not_bottom_pop: incb ;setup left sling $0b asla ;test left sling bpl not_left_sling bra fire_fast_react not_left_sling: incb incb ;setup right sling $0d ;it has to have been the right sling that was closed, fire it fire_fast_react: lda $004D bne L5FF2 lda #$F0 anda $0092 aba sta $0092 lda #$05 sta $004D L5FF2: rti ;return from interrupt ;vectors org $5ff8 dw interrupt ;irq dw start_pigs ;swi dw nmi ;nmi dw system_reset ;reset if c512=1 org $fff8 dw interrupt ;irq dw start_pigs ;swi dw nmi ;nmi dw system_reset ;reset endif