First Commit
[subs.git] / SUBCN1.XX
1 ;        .TITLE SUBCN1- COIN & CREDIT ACCRUER\r
2         .SBTTL *********************************\r
3         .SBTTL * PROGRAMERS: DOWNEND & ALBAUGH *\r
4         .SBTTL *                               *\r
5         .SBTTL * CHECKER:                      *\r
6         .SBTTL *                               *\r
7         .SBTTL *********************************\r
8         .SBTTL EXPLANATION\r
9         .RADIX 16\r
10         .ENABL LC\r
11         .LIST MEB\r
12 ;COIN ROUTINE FOR 16-OPTION STANDARD AS PER MEMO\r
13 ;FROM STEVE BRISTOW DATED 9.27.77 OR 4-OPTION STANDARD\r
14 ;PER MEMO FROM FRANK BALLOUZ 4/20/78\r
15 ;\r
16         .SBTTL DEFAULT ASSIGNMENTS\r
17 ;THESE DEFAULTS CONFIGURE FOR SPRINT4 HARDWARE\r
18         .LIST CND\r
19         .IIF NDF,MODES,MODES=4          ;FOUR COIN MODES STANDARD\r
20         .IIF NDF,OFFSET,OFFSET=2        ;SWITCHES AND STATUS BYTES TWO-APART\r
21         .IIF NDF,COIN,COIN=0            ;COIN IS LOW-TRUE\r
22         .IIF NDF,CNTINT,CNTINT=1        ;COUNT INTERRUPTS (IN $INTCT)\r
23         .IIF NDF,SLAM,SLAM=1            ;SLAM IS HIGH-TRUE\r
24         .IIF NDF,CMZP,CMZP=1            ;COIN MODE IS IN ZERO-PAGE\r
25         .IIF NDF,SHRCMD,SHRCMD=1        ;SHARE A BYTE FOR CMODE, FIRST\r
26         .IIF NDF,LONGST,LONGST=1        ;USE LONG (1/2 SEC) STRINGTIMER\r
27         .IIF NDF,COIN67,COIN67=0        ;COINS NOT IN D7,D6 OF SAME BYTE\r
28         .IIF NDF,PRST,PRST=30.          ;PRE-COIN SLAM KILLS COINS FOR 30 FRAMES\r
29         .IIF NDF,POST,POST=30.          ;POST-COIN SLAM KILLS COINS WITHIN 30 FRAMES\r
30         .IIF NDF,CTCOIN,CTCOIN=0        ;SET TO ONE TO COUNT TOTAL COINS\r
31         .IIF NDF,CTCRED,CTCRED=0        ;SET TO ONE TO COUNT TOTAL CREDITS\r
32         .IIF NDF,PULSE,PULSE=4          ;4 FRAME (66 MS.) PULSE FOR COIN-COUNTER\r
33         .IF NE,CMZP\r
34         .MACRO GCM\r
35         LDA Z,$CMODE            ;GET COIN MODE FROM ZERO-PAGE\r
36         .IIF NE,SHRCMD, AND I,MODES-1&0FF       ;STRIP "FIRST"\r
37         .ENDM\r
38         .ENDC\r
39         .NLIST CND\r
40 ;ENTRY POINT\r
41         .GLOBL MOOLAH\r
42 ;\r
43 ;EXTERNAL REFERENCES\r
44         .IF NE,MODES\r
45         .IF NE,CMZP\r
46         .GLOBL $CMODE                   ;INPUT COIN MODE\r
47         .ENDC\r
48         .ENDC\r
49         .GLOBL $COINA,$LAM              ;SWITCH LOCATIONS (COIN & SLAM)\r
50         .GLOBL $LMBIT                   ;MASK WITH 1 IN BIT WHERE SLAM SW. IS\r
51         .GLOBL $CNSTT,$PSTSL            ;INTERNAL LOCATIONS\r
52         .IF NE,LONGST!PULSE-2           ;IF LONG STRING-TIMER OR PULSES, WE NEED\r
53         .GLOBL $INTCT                   ;INTERRUPT COUNTER\r
54         .ENDC\r
55         .IF EQ,MODES-16\r
56         .GLOBL $FIRST                   ;COULD SHARE BYTE WITH CMODE\r
57         .ENDC\r
58         .GLOBL $LMTIM,$CNCT             ;SLAM-TIMER, COINCOUNT\r
59         .IF NE,MODES\r
60         .GLOBL $$CRDT                   ;RESULT OF ALL THIS\r
61         .ENDC\r
62         .IF NE,CTCOIN!CTCRED\r
63         .GLOBL $CCTIM\r
64         .ENDC\r
65         .IF NE,MODES&<MODES-4>&<MODES-16.>\r
66         .ERROR                  ;3 FLAVORS-0,4, OR 16 MODES\r
67         .ENDC\r
68         .IF NE,<PULSE-2>&<PULSE-4>&<PULSE-8>    ;CHECK PULSE LENGTH SPEC'D\r
69         .ERROR                  ;2,4,OR 8 FRAME PULSES ONLY\r
70         .ENDC\r
71         .IIF GT,PRST-31.,PRST=31.\r
72         .IIF GT,POST-63.,POST=63.\r
73         .IF EQ,MODES-16\r
74         .REPT 0\r
75 When a coin is detected, the coin-count ($CNCT) is incremented.  Then the  "price"  of  "x\r
76 credits" is fetched from CPTAB.  If the coin-count.GE.price, then credit is incremented as\r
77 indicated in CPTAB.\r
78 An entry in CPTAB looks like:\r
79 \r
80         (XXXXFAAA)=1 BYTE\r
81         XXXX = CREDIT, I.E., no. of plays\r
82         F    = 1 IF later coins count one more credit than first coin\r
83         AAA = PRICE, I.E., no. of coins for XXXX CREDITS\r
84 \r
85 Thus any variation from 1 PLAY/7 COINS to 16 PLAYS/1 COIN is possible\r
86 \r
87 The index into CPTAB is created as follows:\r
88         (XXXACCCC)=1 BYTE\r
89         X : ALWAYS ZERO\r
90         A : 0 = LEFT coin mech\r
91             1 = RIGHT coin mech\r
92         cccc:   coin mode (0000-1111)\r
93         .endr\r
94         .endc\r
95         .rept 0\r
96         The coin routine assumes the presence of the following .GLOBL variables:\r
97    1) $$CRDT:   base page byte initialized to 0 on restart.  This is where accrued  credit\r
98         is  kept.   Should  be  decremented  for each player-start.  Note that a DECREMENT\r
99         instruction must be used to insure  mutual  exclusion  between  the  main  program\r
100         accessing  $$CRDT  and  the  interrupt-driven coin routine accessing $$CRDT".  Not\r
101         used if MODES=0\r
102    2) $CMODE:   base page byte that contains the coin option  switches  in  its  low-order\r
103         nybble  (high true).  You must put it there.  this is not used if flag CMZP=0.  In\r
104         this case you must define a macro to get the coin mode in the lsb's  of  the  ACC,\r
105         clearing the msb's, not disturbing carry\r
106    3) $CNSTT:   Two base page bytes ($CNSTT, $CNSTT+OFFSET) which should be initialized to\r
107         00 (the timers for coin detection).\r
108    4) $COINA:   Two locations containing coin switches in D7 Left mech  at  $COINA,  Right\r
109         mech  at  $COINA+OFFSET.   If  COIN67=1,  Switches  are  both in $COINA, D7-Right,\r
110         D6-Left.\r
111    5) $FIRST:   Base page byte.  Flag indicating whether first  coin  has  been  accepted.\r
112         Must  be initialized to plus (or zero, if SHRCMD=0) and reset to plus (or zero) at\r
113         the end of a game.  All other bits are ignored/maintained if the  flag  SHRCMD  is\r
114         set non-zero.  Used only if MODES=16\r
115    6) $CNCT:    2 base page bytes ($CNCT, $CNCT+OFFSET) which must be initialized to  zero\r
116         on pwron - coin counters (only one is used if MODES = 0 or 4)\r
117    7) $PSTSL:   Pair of base page bytes  ($PSTSL,  $PSTSL+OFFSET)used  to  time  post-coin\r
118         slam.\r
119    8) $LAM:     Address of the SLAM switch.  the bit position inside $LAM is specified  by\r
120         $LMBIT (see below)\r
121    9) $LMTIM:   Base  page  byte  used  as  a  timer  for  pre-slam  protection.   May  be\r
122         initialized  to  FF  at  pwron  to  disallow  coin input for 4 seconds.  Coins are\r
123         disallowed for two frames anyway.\r
124    10) $INTCT:  Interrupt counter for  long  string-timer.   If  CNTINT=1,  this  will  be\r
125         incremented  (default  case).   If CNTINT=0, this should be equated to an existing\r
126         counter.\r
127    11) $LMBIT:  Mask used to select which bit in the slam switch  byte  should  be  tested\r
128         (used as I,$LMBIT).  NOT A LOCATION, JUST A VALUE!!\r
129    12) $CCTIM:  TIMER FOR PULSES OUTPUT TO ELECTRO-MECHANICAL COUNTER. IF CTCOIN\r
130         OR CTCRED IS NON-ZERO, ROUTINE WILL RETURN WITH CARRY SET IF COIN\r
131         COUNTER SHOULD BE TURNED ON, CLEARED FOR OFF.\r
132 Space requirements:\r
133                 RAM: 9 bytes (8 if CMZP=0 or SHRCMD=1)\r
134                 ROM: About 200 bytes\r
135 The coin routine also assumes it will be called 4 times  a  frame,  where  one  frame=1/60\r
136 second.   In  most  cases  this may be accomplished by making the coin routine part of the\r
137 interrupt routine.\r
138 SAMPLE BASE PAGE ALLOCATION:  (WHERE OFFSET=2)\r
139         $FIRST: .BLKB 1\r
140         $CCTIM: .BLKB 1         ;COIN COUNTER TIMER (IF USED)\r
141         $$CRDT: .BLKB 1\r
142         $CMODE: .BLKB 1         ;OR CMODE=FIRST\r
143         $PSTSL: .BLKB 1\r
144         $LMTIM: .BLKB 1\r
145                 .BLKB 1         ;$PSTSL FOR SECOND MECH\r
146         $CNCT:  .BLKB 4\r
147         $CNSTT  =$CNCT+1\r
148         .ENDR\r
149         .IF EQ,MODES-16\r
150         .REPT 0\r
151 THE COIN MODES ARE:\r
152   0:    2 COINS/PLAY-LEFT AND RIGHT\r
153   1:    1 COIN/PLAY-LEFT AND RIGHT\r
154   2:    2 PLAYS/COIN-LEFT AND RIGHT\r
155   3:    3 PLAYS/COIN-LEFT AND RIGHT\r
156   4:    4 PLAYS/COIN-LEFT AND RIGHT\r
157   5:    FIRST COIN-1 PLAY; SECOND AND EXTRA COINS-2 PLAYS/COIN\r
158   6:    FIRST COIN-2 PLAYS; SECOND AND EXTRA COINS-3 PLAYS/COIN\r
159   7:    LEFT=2 COINS/PLAY\r
160         RIGHT=1 COIN/PLAY\r
161   8:    LEFT=1 COIN/PLAY\r
162         RIGHT=1 COIN/2 PLAYS\r
163   9:    LEFT=2 PLAYS/COIN\r
164         RIGHT=4 PLAYS/COIN\r
165   A:    LEFT=FIRST COIN-1 PLAY; SECOND AND EXTRA COINS-2 PLAYS/COIN\r
166         RIGHT=FIRST COIN-3 PLAYS; SECOND AND EXTRA COINS-4 PLAYS/COIN\r
167   B:    LEFT=FIRST COIN-2 PLAYS; SECOND AND EXTRA COINS-3 PLAYS/COIN\r
168         RIGHT=FIRST COIN-5 PLAYS; SECOND AND EXTRA COINS-6 PLAYS/COIN\r
169   C:    LEFT=FIRST COIN-3 PLAYS; SECOND AND EXTRA COINS-4 PLAYS/COIN\r
170         RIGHT=FIRST COIN-7 PLAYS; SECOND AND EXTRA COINS-8 PLAYS/COIN\r
171   D:    LEFT=3 COINS/PLAY\r
172         RIGHT=1 COIN/PLAY\r
173   E:    LEFT=1 COIN/PLAY\r
174         RIGHT=3 PLAYS/COIN\r
175   F:    LEFT=3 PLAYS/COIN\r
176         RIGHT=6 PLAYS/COIN\r
177         .ENDR\r
178         .ENDC\r
179         .IF EQ,MODES-4\r
180         .REPT 0\r
181 THE COIN MODES ARE:\r
182   0:    FREE PLAY- $CNCT is zeroed, $$CRDT is not changed\r
183   1:    2 PLAYS PER COIN\r
184   2:    1 PLAY PER COIN\r
185   3:    2 COINS PER PLAY\r
186         .ENDR\r
187         .ENDC\r
188         .REPT 0\r
189                    *** COIN DETECTION ***\r
190 Coin detection, courtesy of Mike Albaugh, uses two counters in one  byte  ($CNSTT).   This\r
191 byte  is  used to remember the condition of the coin switch.  The upper counter (D7,D6,D5)\r
192 runs when the coin is absent and is reset when the coin is  present.   The  lower  counter\r
193 (D4-D0)  runs  when  the  coin is present and is reset when the coin is absent, unless the\r
194 coin was present for 5 successive samples.  This "unless"  enables  $CNSTT  to  "remember"\r
195 that a coin has been VALID-HIGH while waiting for VALID-LOW.\r
196 Basically, a valid coin is defined as between 16 and 800 ms of coin present, preceded  and\r
197 followed  by  33 ms of coin absent.  The 33 ms lows need not immediately precede or follow\r
198 the high.  The lower five bits count  down  from  31  when  the  coin  is  present.   This\r
199 countdown  is  fast  (once  per  interupt)  for the first five samples (31-26, about 16-20\r
200 milliseconds) then slow (once per EIGHT interrupts) for the remaining counts (26-0,  about\r
201 800  ms).   The  count  then  stops  at zero.  This counter is reset if the coin goes away\r
202 during the first five counts, I.E., the coin must be present for at least  16  ms.   After\r
203 that  the coin must go away for eight counts to reset it.  This is because after the first\r
204 five counts a coin is VALID HIGH and must not be reset until VALID LOW occurs  to  prevent\r
205 mid-coin glitches from making a valid coin into 0 or 2 (or more) coins.\r
206 \r
207 The upper three bits count up from zero when the coin is absent.  The count  is  reset  if\r
208 coin  is  ever  found  present.   When  the  count  finally wraps (8 samples, 33 ms).  The\r
209 coin-present counter is checked.  A count from 27-31 (less than 16-20 ms) is too short.  A\r
210 count of 0 (more than 800 ms) is too long.  Both of these cases are simply reset to 31.  A\r
211 count of 1-26 is a (tentatively) valid coin.  The counter is again set to 31, but  another\r
212 counter ($PSTSL) is started.\r
213 \r
214 $PSTSL is the POST-COIN-SLAM timer.  Initially  set  to  120,  it  counts  down  once  per\r
215 interrupt  (4  times per frame) to give a nominal 1/2 second delay.  If the slam switch is\r
216 seen during this time, $PSTSL is cleared, invalidating the coin.  The length of the  delay\r
217 (in  frames)  is  defined by POST which defaults to 30.  It may be set as high as 63 (1.05\r
218 seconds) by definition E.G.\r
219 \r
220         POST=50         ;POST-SLAM=50 FRAMES\r
221 \r
222 SIMILARY A SLAM IS "REMEMBERED" FOR PRST frames (default=30, max=31) and no  coin  can  be\r
223 "seen" during this time.\r
224 \r
225 Note that the proper initial  state  of  all  these  counters  etc  is  0,  therefore  the\r
226 traditional power-on clear does the trick.  Since coins "transit" from $CNSTT to $PSTSL to\r
227 $CNCT to $$CRDT, locations should be cleared in that order, I.E.   $$CRDT  should  be  the\r
228 last location cleared.\r
229         .ENDR\r
230 \f        .SBTTL MAINLOOP\r
231 ;INSTRUCTIONS IN BRACKETS( "[" AND "]" ) ARE FOR ILLUSTRATION ONLY, AND ARE NOT\r
232 ;ACTUALLY ASSEMBLED.\r
233 MOOLAH:\r
234         LDX I,OFFSET            ;X IS USED TO INDEX FROM RIGHT TO LEFT COIN MECH\r
235         .IF EQ,COIN67\r
236 DETECT: LDA AX,$COINA\r
237         ASL\r
238         .IFF\r
239         LDA A,$COINA            ;GET COIN SWITCHES\r
240 DETECT: ASL\r
241         .ENDC\r
242         LDA ZX,$CNSTT\r
243         AND I,31.               ;SHARED INST. SEE BELOW IN BRACKETS []\r
244         .IF EQ,COIN\r
245         BCS 5$                  ;BRANCH IF INPUT HIGH (COIN ABSENT)\r
246         .IFF\r
247         BCC 5$                  ;BRANCH IF INPUT LOW (COIN ABSENT)\r
248         .ENDC\r
249 ;       [AND I,31.]             ISOLATE COIN-ON DOWN-COUNTER, RESET COIN-OFF UP-CTR.\r
250         BEQ 1$                  ;STICK AT 0 (TERMINAL COUNT)\r
251         .IF NE,LONGST\r
252         CMP I,27.               ;IN FIRST FIVE SAMPLES\r
253         BCS 10$                 ;YES, RUN FAST\r
254         TAY                     ;ELSE SAVE STATUS\r
255         LDA Z,$INTCT            ;CHECK INTERUPT CTR\r
256         AND I,7                 ;ARE D0-D2 ALL ONES?\r
257         CMP I,7\r
258         TYA                     ;STATUS BACK INTO ACC\r
259         BCC 1$                  ;SKIP IF NOT BOTH ONES\r
260 10$:    SBC I,1                 ;CARRY SET\r
261         .IFF\r
262         .IF EQ,COIN\r
263         SBC I,0                 ;CARRY CLEAR, THIS SUBTRACTS ONE\r
264         .IFF\r
265         SBC I,1                 ;CARRY SET OR WE WOULDN'T BE HERE\r
266         .ENDC                   ;COIN CONDITIONAL\r
267         .ENDC                   ;LONGST CONDITIONAL\r
268 1$:     STA ZX,$CNSTT           ;SAVE UPDATED STATUS\r
269         LDA A,$LAM              ;CHECK SLAM SWITCH\r
270         AND I,$LMBIT\r
271         .IF NE,SLAM\r
272         BEQ 2$                  ;BRANCH IF BIT LO (SWITCH OFF)\r
273         .IFF\r
274         BNE 2$                  ;BRANCH IF BIT HI (SWITCH OFF)\r
275         .ENDC\r
276         LDA I,PRST*8            ;ELSE SET PRE-COIN SLAM TIMER\r
277         STA Z,$LMTIM            ;DECR. 8 TIMES/FRAME=PRST FRAMES\r
278 2$:     LDA Z,$LMTIM            ;CHECK PRE-COIN SLAM TIMER\r
279         BEQ 3$                  ;O.K.\r
280         DEC Z,$LMTIM            ;ELSE RUN TIMER\r
281         LDA I,0\r
282         STA ZX,$CNSTT           ;CLEAR COIN STATUS\r
283         STA ZX,$PSTSL           ;CLEAR POST-COIN SLAM-TIMER\r
284 3$:     CLC                     ;DEFAULT "NO COIN DETECTED"\r
285         LDA ZX,$PSTSL           ;CHECK POST-COIN SLAM-TIMER\r
286         BEQ 8$                  ;EMPTY, RETURN\r
287         DEC ZX,$PSTSL           ;RUN TIMER\r
288         BNE 8$                  ;NOT DONE, RETURN\r
289         SEC                     ;WHEN IT BECOMES ZERO, INDICATE A COIN\r
290         BCS 8$                  ;*** ALWAYS\r
291 5$:;    [AND I,31.]             GET COIN-ON DOWN-CTR (ACTUALLY DONE BEFORE)\r
292         CMP I,27.               ;IS COIN VALID YET (ON FOR >4 SAMPLES)\r
293         BCS 6$                  ;NO, RESET IT\r
294         LDA ZX,$CNSTT           ;GET STATUS AGAIN\r
295         ADC I,32.               ;BUMP COIN-OFF UP-CTR.\r
296         BCC 1$                  ;IF IT DIDN'T WRAP, JUST STORE STATUS\r
297         BEQ 6$                  ;IT WRAPPED BUT COIN WAS ON TOO LONG, JUST RESET\r
298         CLC                     ;SET "VALIDITY" AGAIN\r
299 6$:     LDA I,31.               ;RESET DOWN-COUNTER\r
300         BCS 1$                  ;BRANCH IF COIN TOO LONG OR TOO SHORT\r
301         STA ZX,$CNSTT           ;SAVE RESET STATUS\r
302 ;       [CLC]                   DEFAULT TO "NO COIN" (CARRY IS ALREADY CLEAR)\r
303         LDA ZX,$PSTSL           ;CHECK HOWIES ASSUMPTION\r
304         BEQ 7$                  ;BRANCH IF $PSTSL VACANT\r
305         SEC                     ;ELSE GIVE CREDIT A LITTLE EARLY\r
306 7$:     LDA I,POST*4            ;/(4 COUNTS/FRAME)="POST" FRAMES\r
307         STA ZX,$PSTSL           ;DELAY ACCEPTANCE FOR POST 60 SEC.\r
308         \r
309 8$:                             ;CARRY=1 IF COIN FALLS OUT\r
310         .IF EQ,MODES-4&MODES    ;IF MODES=0 OR 4\r
311         BCC 9$                  ;INC COIN CNT IF CARRY SET\r
312         INC $CNCT\r
313         .IF NE,CTCOIN           ;IF COIN COUNTER USED\r
314         INC $CCTIM              ;INIT COIN PULSE\r
315         .ENDC\r
316 9$:\r
317         .IFF                    ;IF MODES=16\r
318 CONVRT:                         ;CONVERT COINS TO CREDITS\r
319         GCM                     ;GET COIN MODE IN ACC 0-3\r
320         BCC 20$                 ;CARRY=1 IF COIN WAS DETECTED ELSE ZERO\r
321         .IF NE,CTCOIN           ;IF COIN COUNTER USED\r
322         INC $CCTIM              ;INIT COIN PULSE\r
323         .ENDC\r
324         CMP I,7                 ;MODES 0-6 ARE SPECIAL IN THAT BOTH MECHS COUNT\r
325                                 ;THE SAME WAY SO USE ONLY ONE COIN COUNTER\r
326         BPL 10$\r
327         INC Z,$CNCT             ;INCREMENT COMMON COUNTER\r
328         JMP 20$\r
329 10$:    INC ZX,$CNCT            ;ELSE INCREMENT APPROPRIATE COUNTER\r
330                                 ;CREATE INDEX\r
331 20$:\r
332         CPX I,0                 ;IS IT FIRST (LEFT) MECH\r
333         BEQ 40$\r
334         ORA I,10                ;PUT 0,1 AT BIT POITION "A"\r
335 40$:    TAY                     ;ACC=INDEX INTO CPTAB\r
336         LDA AY,CPTAB            ;GET NO. OF COINS NEEDED FOR "X" CREDITS FROM CPTAB\r
337         AND I,07                ;  OF COINS IN 3 LSB\r
338         EOR I,0FF\r
339         SEC                     ;NEGATE\r
340         ADC ZX,$CNCT            ;ACC <- COINCT-CPTAP(Y)\r
341         BCC 100$                ;BRANCH ON BORROW\r
342         STA ZX,$CNCT            ;ELSE STORE REDUCED COINCT\r
343         LDA AY,CPTAB            ;GET BACK TABLE ENTRY\r
344         LSR\r
345         LSR\r
346         LSR\r
347         LSR                     ;GET   OF CREDITS IN ACC 0-3, "F" IN CARRY\r
348         LDY Z,$FIRST            ;CHECK FOR FIRST COIN\r
349         .IF NE,SHRCMD\r
350         BMI 50$\r
351         .IFF\r
352         BNE 50$\r
353         .ENDC                   ;SHRCMD CONDITIONAL\r
354         CLC                     ;IF FIRST COIN, CLEAR CARRY\r
355 50$:    ADC Z,$$CRDT\r
356         .IF NE,CTCRED           ;IF COUNTING CREDITS\r
357         TAY                     ;SAVE NEW CREDIT\r
358         SEC\r
359         SBC $$CRDT              ;SUB OLD\r
360         CLC\r
361         ADC $CCTIM              ;ADD OFFSET\r
362         STA $CCTIM              ;TO COIN PULSE TIMER\r
363         STY $$CRDT              ;STORE NEW CREDIT\r
364         .IFF\r
365         STA Z,$$CRDT            ;CREDIT=CREDIT+CPTAB(Y)/16.+"F"&(NOT FIRST)\r
366         .ENDC                   ;CTCRED COND.\r
367         .IF NE,SHRCMD\r
368         LDA I,80\r
369         ORA Z,$FIRST\r
370         STA Z,$FIRST\r
371         .IFF\r
372         INC Z,$FIRST            ;A COIN IN EITHER COUNTS AS THE FIRST COIN\r
373         .ENDC                   ;SHRCMD CONDITIONAL\r
374 100$:   .IFTF                   ;NO MATTER WHAT NMODES IS\r
375         .IF NE,COIN67\r
376         LDA A,$COINA            ;GET SWITCHES AGAIN\r
377         ASL                     ;D6 INTO SIGN\r
378         .ENDC\r
379         .REPT OFFSET\r
380         DEX\r
381         .ENDR\r
382         .IFF                    ;ONLY FOR MODES=16\r
383         BMI EXIT\r
384         JMP DETECT              ;LOOP FOR SECOND MECH\r
385 CPTAB:                                  ;TABLE OF CREDIT/PRICE VALUES\r
386 ;I.E. FIRST ENTRY (12) READS: 1 CREDIT FOR 2 COINS\r
387         .BYTE 12,11,21,31,41,19,29,12   ;LEFT MECH\r
388         .BYTE 11,21,19,29,39,13,11,31\r
389         .BYTE 12,11,21,31,41,19,29,11   ;RIGHT MECH\r
390         .BYTE 21,41,39,59,79,11,31,61\r
391         .IFT                    ;THAT IS, IF MODES=0 OR 4\r
392         BPL DETECT\r
393         .ENDC\r
394         .IF EQ,MODES-4          ;ONLY IF MODES=4\r
395 CONVRT: GCM                     ;GET COIN MODE IN ACC 0,1\r
396         TAY                     ;SAVE IT & TEST IT\r
397         BEQ 2$                  ;IF FREE PLAY, KEEP CREDIT CLEAR\r
398         LSR\r
399         ADC I,0                 ;FORM PRICE (0,1,1,2)\r
400         EOR I,0FF\r
401         SEC                     ;NEGATE\r
402         ADC $CNCT               ;ACC <- COINCT - PRICE\r
403         BCC EXIT                ;BRANCH ON BORROW\r
404         CPY I,2                 ;COIN MODE 2 OR 3?\r
405         BCS 1$                  ;YES, JUST ONE CREDIT\r
406         INC $$CRDT              ;ELSE GIVE TWO FOR MODES 0,1\r
407 1$:     .IF NE,CTCRED           ;IF COUNTING CREDITS\r
408         INC $CCTIM              ;INIT COIN PULSE\r
409         .IFTF\r
410         INC $$CRDT\r
411         .IFT\r
412         INC $CCTIM\r
413         .ENDC\r
414 2$:     STA $CNCT               ;STORE REDUCED (OR CLEARED) COINCT\r
415         .ENDC\r
416 EXIT:   .IF NE,LONGST!<PULSE-2>         ;IF LONG STRING TIMER, OR PULSE>2 FRAMES\r
417         .IIF NE,CNTINT, INC Z,$INTCT            ;COUNT INTERUPTS WHEN REQUESTED\r
418         .ENDC\r
419         .IF NE,CTCRED!CTCOIN            ;INCLUDE PULSER\r
420         .IIF NE,PULSE-2,        LDA Z,$INTCT            ;NEED $INTCT IF PULSE>2\r
421         .IIF EQ,PULSE-4,        LSR                     ;USE LSB IF PULSE=4\r
422         .IF EQ,PULSE-8.\r
423         AND I,3                         ;ISOLATE 2 LSB'S\r
424         CMP I,1                         ;CLEAR CARRY IF 00\r
425         .ENDC\r
426         LDA Z,$CCTIM                    ;GET COIN-COUNTER TIMER\r
427         .IIF NE,PULSE-2,        BCS 2$\r
428         BEQ 2$                          ;BRANCH IF IDLE\r
429         CMP I,10                        ;MSB'S CLEAR?\r
430         BCS 1$                          ;NO,SKIP\r
431         ADC I,-1                        ;ELSE INIT PULSE, SET CARRY\r
432 1$:     ADC I,0EF               ;(ONE LESS CUZ CARRY SET) DEC MSB'S OF TIMER\r
433         STA Z,$CCTIM                    ;STORE UPDATED TIMER\r
434 2$:     ASL                             ;SET CARRY PER D7 OF TIMER\r
435         .ENDC\r
436         RTS\r
437 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0