+icons
[www.jankratochvil.net.git] / project / LaserGame / LaserGun.a51
1 // 11.0592MHz=>921600 T0 clk=>112.5 ops=2.27`5s time
2 // Code is big-endian!
3 public BaudRate equ 2400        // Communication speed
4 public StackSiz51       equ 24  // LaserGun stack size required
5        MagicRAMw        equ 0x53AC      // RAM-check
6        TestChar equ 't' // For Ph_Test
7
8 MaxDecimal      equ     99      // If dec>99
9 BauDiv  equ     28800/BaudRate // 3=9600, 6=4800, 12=2400 (PCON=0)
10
11 /*
12 Init display:
13 Pn-Player ID
14 Gx-Game mode: A=Anarchy, G=Green team, R=Red team
15 Display:
16 Lt-Loading
17 Fn-Shot from friend detected
18 En-Shot from enemy detected but already dead
19 Sn-Shot down by enemy
20 dt-Currently dead
21 Left dot-reloading
22 Right dot-dead
23 */
24
25 /******************************/
26         seg     data
27         org     0x00
28 DataStart:
29         rb      4 // r0-r3
30 #define DispL r4
31 #define DispR r5
32 #define Timer r6
33 #define XMitPhase r7
34         // 0='s';1=PktType;2=SwConfigX;3=PktData;4=XSumH;5=XSumL;6='e'
35         rb      4
36
37 TimPhase:       rb      1 // Timer for current phase
38 TimLED4:        rb      1 // 4-LED period
39 TimScroll:      rb      1 // Scroll advance to next char
40
41        ScrollPtr:       rb 1 // Scroll-text start rel. ScrBase
42        SeriCnt: rb 1 // Shots in current series
43        CAPktEnd:        rb 1 // End of ConfigReq being answered (or 0)
44        WDogCnt: rb 1 // WatchDog timer count-down
45        Phase:   rb 1 // Current phase # (see below)
46 Ph_CfgDump      equ     0 // Configuration to display dump [Phase1=sub-phase]
47 Ph_Ammo equ     1 // Normal Ammo display
48 Ph_Laser        equ     2 // Laser on
49 Ph_Delay        equ     3 // Laser off, laser button disabled
50 Ph_First        equ     4 // Additional first-in-series delay
51         // Laser allowed boundary
52 Ph_Reload       equ     5 // Reload countdown period [Phase1=cdown]
53 Ph_Dead equ     6 // Dead-state countdown period [Phase1=cdown]
54 Ph_Test equ     7 // Test mode with transmit/receive of 'T'
55        Phase1:  rb 1 // Sub-phase
56 // Ph_CfgDump:
57 CD_Bootup       equ     0  // Right after boot-up
58 CD_PNum equ     1  // Player no. (P#)
59 CD_GMode        equ     2  // Game mode  (G#: Anarchy, Green, Red)
60 CD_LEDs equ     3  // BBS_QuietL [Ld]
61 CD_Sound        equ     4  // BBS_QuietS [Sd]
62 CD_WDogs        equ     5  // WDogsCnt   (dr, TU)
63 CD_WDogsN       equ     6  // {TU}
64 CD_RSwChg       equ     7  // RSwChgs    (SC, TU)
65 CD_RSwChgN      equ     8  // {TU}
66 CD_TotSh        equ     9  // TotShotsW  (FS, [TH], TU)
67 CD_TotShM       equ     10 // {[TH]}
68 CD_TotShN       equ     11 // {TU}
69 CD_Grave0       equ     12 // GraveW #0  (d#, [TH], TU)
70 CD_GraveL       equ     60 // GraveW #++F(d#, [TH], TU)
71 CD_Last equ     60
72 // Ph_Reload: Reload cycles countdown
73 // Ph_Dead:   Dead cycles countdown
74
75        CurPktE: rb 1 // +1 of last L2 packet byte received
76        XMitNib: rb 1 // Transmit-remaining nibble (or 0)
77        PktNibble:       rb 1 // Recevied L2 packet hex nibble
78        CurPktS: rb 1 // Addr of size of L2 packet being received
79        UserPktS:        rb 1 // Addr of size of 1st L2 packet in user queue
80        TimedL:  rb 1 // Left digit of TimedDisp
81        TimedR:  rb 1 // Right digit of TimedDisp
82        ConvDecW1:       // For use by ConvDecW
83        RxChkXSumW:      rw 1 // Computed xsum of incoming L2 packet
84        XMitXSumW:       rw 1 // XSum being computed during XMit
85        XMitType:        rb 1 // Actual XMit L3 Pkt type - One of PktN_* below
86
87 ClearTop:
88
89 public TotShotsW:       rw 1  // Fire statistics
90 public RSwChgs: rb 1  // Run-Time switch configuration change #
91 public WDogsCnt:        rb 1  // # of gurus-WatchDog restarts since power-on
92
93 public SwConfigXA       equ $-DataStart // Address of SwConfigX
94        SwConfigX:       rb 1 // Copy of SwitchP
95        SysFlagsX:       rb 1 // [XMittedN|XMitByte|XMit1stNib|XMitHaveP|TimedDisp|XMitting|PktGotNib|PktRcvng]
96 PktRcvng        bit     SysFlagsX.0     // Currently receiving packet (after 's')
97 PktGotNib       bit     SysFlagsX.1     // Already got one hex nibble in PktNibble
98 XMitting        bit     SysFlagsX.2     // Background packet transmit in progress
99 TimedDisp       bit     SysFlagsX.3 // Generated 2-digit display override
100 XMitHaveP       bit     SysFlagsX.4     // XMitNib is prepared and filled
101 XMit1stNib      bit     SysFlagsX.5     // Transmit 1st nibble from XMitNib
102 XMitByte        bit     SysFlagsX.6     // Transmitting byte instead of two nibbles
103 XMittedN        bit     SysFlagsX.7     // Sth was already xmitted this round
104 public UsrFlagsX:       rb 1 // [RFU:2|FastFireRD|FullFireT|DisRSwChg|DispDotTR|DispDotRD|UnConfig]
105 UnConfig        bit     UsrFlagsX.0     // Ignore all further configuration attempts
106 DispDotRD       bit     UsrFlagsX.1     // Display LDot & RDot when [R]eload/[D]ead
107 DispDotTR       bit     UsrFlagsX.2     // Display LDot & RDot when [T]ransmit/[R]eceive
108 DisRSwChg       bit     UsrFlagsX.3     // Disable run-time switch reconfiguration
109 FullFireT       bit     UsrFlagsX.4     // Transmit full 10B packets for fires (safer)
110 FastFireRD      bit     UsrFlagsX.5     // Receive disable for FastFires (see FullFireT)
111
112 /******************************/
113 public Mark_Start       equ 's' // L1 layer packet start
114 public Mark_End equ 'e' // L1 layer packet end
115 public XSum_Base        equ 0xB3A7      // L2 packet xsumming base number
116 public XSum_Mul equ 13  // L2 packet xsumming advance multiply
117 public PktN_Fire        equ 'S' // L3 packet ID for fire
118 public PktN_CfgR        equ 'R' // L3 packet ID for configuration request
119 public PktN_CfgA        equ 'A' // L3 packet ID for configuration answer
120
121 DispP   equ     P0
122 BMD_U   equ     0x01
123 BMD_UR  equ     0x02
124 BMD_UL  equ     0x04
125 BMD_M   equ     0x08
126 BMD_BR  equ     0x10
127 BND_DOT equ     5
128 BBD_DOT equ     DispP.BND_DOT
129 BMD_DOT equ     1<<BND_DOT
130 BMD_B   equ     0x40
131 BMD_BL  equ     0x80
132
133 MiscP   equ     P1
134 BPM_DispR       equ     P1.0
135 BMM_DispR       equ     0x01
136 BPM_DispL       equ     P1.1
137 BMM_DispL       equ     0x02
138 BPM_Laser       equ     P1.2
139 BMM_Laser       equ     0x04
140 BMM_LED0        equ     0x08 // RED    ^ - cable up
141 BMM_LED1        equ     0x10 // GREEN  <
142 BMM_LED2        equ     0x20 // RED    >
143 BNM_LED3        equ     6
144 BMM_LED3        equ     1<<BNM_LED3 // GREEN v
145 BMM_LEDM        equ     BMM_LED0|BMM_LED1|BMM_LED2|BMM_LED3
146 BPM_Sound       equ     P1.7
147 BMM_Sound       equ     0x80
148
149 SwitchP equ     P2
150 BMS_IdentM      equ     0x0F // However defined, hard-coded
151 BNS_IsTeam      equ     4
152 BBS_IsTeam      equ     SwConfigX.BNS_IsTeam
153 BNS_TeamN       equ     5       // 1=Green
154 BBS_TeamN       equ     SwConfigX.BNS_TeamN
155 BBS_QuietL      equ     SwConfigX.6     // 1=LEDs off
156 BBS_QuietS      equ     SwConfigX.7     // 1=Disable
157
158 IfaceP  equ     P3
159 BPI_Fire        equ     P3.2
160 BPI_Status      equ     P3.4
161
162 /******************************/
163 Font__  equ     low~(0                                              )
164 Font_0  equ     low~(0|BMD_U|BMD_UL|BMD_UR      |BMD_BL|BMD_BR|BMD_B)
165 Font_1  equ     low~(0             |BMD_UR             |BMD_BR      )
166 Font_2  equ     low~(0|BMD_U       |BMD_UR|BMD_M|BMD_BL       |BMD_B)
167 Font_3  equ     low~(0|BMD_U       |BMD_UR|BMD_M       |BMD_BR|BMD_B)
168 Font_4  equ     low~(0      |BMD_UL|BMD_UR|BMD_M       |BMD_BR      )
169 Font_5  equ     low~(0|BMD_U|BMD_UL       |BMD_M       |BMD_BR|BMD_B)
170 Font_6  equ     low~(0|BMD_U|BMD_UL       |BMD_M|BMD_BL|BMD_BR|BMD_B)
171 Font_7  equ     low~(0|BMD_U       |BMD_UR             |BMD_BR      )
172 Font_8  equ     low~(0|BMD_U|BMD_UL|BMD_UR|BMD_M|BMD_BL|BMD_BR|BMD_B)
173 Font_9  equ     low~(0|BMD_U|BMD_UL|BMD_UR|BMD_M       |BMD_BR|BMD_B)
174 Font_A  equ     low~(0|BMD_U|BMD_UL|BMD_UR|BMD_M|BMD_BL|BMD_BR      )
175 Font_B  equ     low~(0      |BMD_UL       |BMD_M|BMD_BL|BMD_BR|BMD_B)
176 Font_C  equ     low~(0|BMD_U|BMD_UL             |BMD_BL       |BMD_B)
177 Font_c_ equ     low~(0                    |BMD_M|BMD_BL       |BMD_B)
178 Font_D  equ     low~(0             |BMD_UR|BMD_M|BMD_BL|BMD_BR|BMD_B)
179 Font_E  equ     low~(0|BMD_U|BMD_UL       |BMD_M|BMD_BL       |BMD_B)
180 Font_F  equ     low~(0|BMD_U|BMD_UL       |BMD_M|BMD_BL             )
181 Font_G  equ     low~(0|BMD_U|BMD_UL             |BMD_BL|BMD_BR|BMD_B)
182 Font_H  equ     low~(0      |BMD_UL|BMD_UR|BMD_M|BMD_BL|BMD_BR      )
183 Font_I  equ     low~(0      |BMD_UL             |BMD_BL             )
184 Font_L  equ     low~(0      |BMD_UL             |BMD_BL       |BMD_B)
185 Font_N  equ     low~(0                    |BMD_M|BMD_BL|BMD_BR      )
186 Font_O  equ     low~(0|BMD_U|BMD_UL|BMD_UR      |BMD_BL|BMD_BR|BMD_B)
187 Font_P  equ     low~(0|BMD_U|BMD_UL|BMD_UR|BMD_M|BMD_BL             )
188 Font_R  equ     low~(0                    |BMD_M|BMD_BL             )
189 Font_S  equ     low~(0|BMD_U|BMD_UL       |BMD_M       |BMD_BR|BMD_B)
190 Font_T  equ     low~(0      |BMD_UL       |BMD_M|BMD_BL       |BMD_B)
191 Font_U  equ     low~(0      |BMD_UL|BMD_UR      |BMD_BL|BMD_BR|BMD_B)
192 Font_Y  equ     low~(0      |BMD_UL|BMD_UR|BMD_M       |BMD_BR|BMD_B)
193 Font_MIN        equ     low~(0                    |BMD_M                    )
194 Font_   equ     low~(0|BMD_U|BMD_UL|BMD_UR|BMD_M|BMD_BL|BMD_BR|BMD_B)
195
196 /******************************/
197 public GraveWA  equ     $-DataStart // GraveW address
198 public GraveW:  rw 16 // Kills by players #0..#F
199 // Config:
200 LoadPart:
201 public ReloadN: rb 1  // Reload countdown
202 public DeadN:   rb 1  // Dead state countdown
203 public SeriC_Max:       rb 1  // Maximum # of shots per one series
204 public Ammo_Max:        rb 1  // Ammo # in one clip
205 public Ammo:    rb 1  // Remaining ammo in the current clip
206 public DeadDivN:        rb 1  // 4LED-Dead -> Dead cycle divisor
207 public T_Start: rb 1  // Startup info cycle delay
208 public T_Reload:        rb 1  // Reload cycle delay
209 public T_Laser: rb 1  // Laser firing
210 public T_Delay: rb 1  // Inter-Laser delay
211 public T_First: rb 1  // Additional series start delay period
212 public T_LED4:  rb 1  // 1 of RY-LED switch period
213 public T_Scroll:        rb 1  // Scroll of one letter
214 public T_ScrollF:       rb 1  // Scroll of 1st two letters
215 public T_Dead:  rb 1  // 4LED-Dead (and Dead) cycle delay
216 public T_TimedD:        rb 1  // TimedDisp delay (temporary, non-scrolling)
217 public AddrSpace        equ $-DataStart // +1 of remote configurable address space
218 LoadPartS       equ     $-LoadPart
219        MagicRAM:        rw 1  // Contains MagicRAMw for RAM-check
220 public RxBufSiz equ 0x80+DataStart-$-StackSiz51 // Receive buffer size
221 RxBuf:  rb      RxBufSiz                // Receive buffer
222 StackBtm:                               // Start of stack
223
224 /******************************/
225         seg     code
226
227         org     0x0     // Reset, SUsage=6
228 Reset:
229         jb      BPI_Fire,BadRAM
230         mov     a,#high MagicRAMw
231         xrl     a,MagicRAM
232         jnz     BadRAM
233         sjmp    ResCont
234
235         org     0xB     // T0, SUsage=4
236 T0Int:  push    psw
237         push    acc
238         inc     Timer
239         dec     WDogCnt
240         mov     a,WDogCnt
241         jnz     NWDogFail
242         inc     WDogsCnt                // Failing!
243 WarmBoot:       mov     r0,#ClearTop-1  // Mustn't reset RAM
244         sjmp    ContBoot
245
246 NWDogFail:      pop     acc
247         pop     psw
248         reti
249
250         org     0x23    // Ser, SUsage=14
251 SerInt: ajmp    SerICont
252
253 SwRConfig:      inc     RSwChgs
254         sjmp    WarmBoot
255
256 ResCont:        mov     a,#low MagicRAMw
257         xrl     a,MagicRAM+1
258         jz      SwRConfig
259 BadRAM: mov     MagicRAM,#high MagicRAMw
260         mov     MagicRAM+1,#low MagicRAMw
261         mov     r0,#LoadPart
262         mov     dptr,#LoadContn
263         mov     r2,#LoadPartS
264 FillMem:        clr     a
265         movc    a,@a+dptr
266         mov     @r0,a
267         inc     r0
268         inc     dptr
269         djnz    r2,FillMem
270 ColdBoot:       mov     r0,#LoadPart-1
271
272 ContBoot:       clr     a
273         mov     IE,a
274         mov     TCON,a
275         mov     sp,#StackBtm-1
276
277 ClearMem:       mov     @r0,a
278         djnz    r0,ClearMem
279
280         mov     SwConfigX,SwitchP
281         mov     SysFlagsX,a
282
283         mov     Timer,#1
284         mov     CurPktS,#RxBuf
285         mov     UserPktS,#RxBuf
286
287         mov     DispP,a
288         jb      BPI_Fire,0f
289         mov     MiscP,#~(BMM_DispL|BMM_DispR)
290         jnb     BPI_Fire,$
291         mov     a,SwitchP
292         xch     a,SwConfigX
293         xrl     a,SwConfigX
294         jz      0f
295         mov     Phase,#Ph_Test
296         setb    DispDotTR
297 0:      mov     MiscP,#~BMM_DispR
298
299         mov     UsrFlagsX,#0x03 //DEBUG!!!
300
301         clr     a
302         mov     IP,#0x10        // Pri: Ser=1
303         mov     TCON,a
304         mov     TL1,#-BauDiv
305         mov     TH1,#-BauDiv
306         mov     TL0,a
307         mov     TH0,a
308         mov     TMOD,#0x20      // T1=m2, T0=m0
309         mov     PCON,a  // SerSpd=normal
310         mov     SCON,#0x50      // 8N1, T1, clr
311         mov     TCON,#0x50      // T1+T0=run, clr
312
313         mov     IE,#0x92        // Int: Ser+T0
314
315         mov     r0,#TimPhase
316         acall   StartTim
317         acall   InitLED4
318 MainLoop:       mov     WDogCnt,#0      // Reset WatchDog
319 // Check run-time change of configuration
320         jb      DisRSwChg,1f
321         mov     a,SwConfigX
322         xrl     a,SwitchP
323         jz      1f
324         ajmp    SwRConfig
325 1:
326 // Display refresh
327         mov     DispP,#0xFF
328         xrl     MiscP,#BMM_DispL|BMM_DispR
329         mov     a,Phase
330         jnb     BPM_DispR,0f
331         jnb     DispDotTR,6f
332         jb      Xmitting,7f
333 6:      jnb     DispDotRD,1f
334         xrl     a,#Ph_Reload
335         jnz     1f
336 7:      clr     BBD_DOT
337 1:      mov     a,ScrollPtr
338         jnz     4f
339         mov     a,DispL
340         jnb     TimedDisp,2f
341         mov     a,TimedL
342         sjmp    2f
343
344 0:      jnb     DispDotTR,8f
345         jb      PktRcvng,9f
346 8:      jnb     DispDotRD,3f
347         xrl     a,#Ph_Dead
348         jnz     3f
349 9:      clr     BBD_DOT
350 3:      mov     a,ScrollPtr
351         jz      5f
352         inc     a
353 4:      mov     dptr,#ScrBase
354         movc    a,@a+dptr
355         sjmp    2f
356
357 5:      mov     a,DispR
358         jnb     TimedDisp,2f
359         mov     a,TimedR
360 2:      anl     DispP,a
361 // 4-LED cycle
362         jb      BBS_QuietL,NoLED4Fr
363         mov     a,Phase
364         xrl     a,#Ph_Dead
365         jz      NoLED4Fr
366         mov     r0,#TimLED4
367         acall   QueryTim
368         jnc     NoLED4Fr
369         jnb     BBS_IsTeam,1f
370         mov     a,#BMM_LED0|BMM_LED2
371         jnb     BBS_TeamN,5f
372         mov     a,#BMM_LED1|BMM_LED3
373 5:      xrl     MiscP,a
374         sjmp    2f
375
376 1:      mov     a,#~BMM_LEDM
377         orl     a,MiscP
378         rl      a
379         jb      acc.(BNM_LED3+1),4f
380         mov     a,#~BMM_LED0
381 4:      orl     MiscP,#BMM_LEDM
382         anl     MiscP,a
383 2:      mov     r0,#TimLED4
384         mov     a,T_LED4
385         acall   StartTim
386 NoLED4Fr:
387 // Fire series maintenance
388         jnb     BPI_Fire,0f
389         mov     SeriCnt,#0
390 0:
391 /*** Here end mandatory MainLoop routines ***/
392         mov     r0,#TimPhase
393         acall   QueryTim
394         jnc     NoPhases
395         mov     dptr,#PhaseTab
396         mov     r1,#Phase1
397         mov     a,Phase
398         acall   JmpByTab
399 NoPhases:
400 // Fire check
401         mov     a,Phase
402         jz      1f
403         dec     a
404         jnz     2f
405 1:      jb      BPI_Status,0f
406         clr     a
407         mov     Phase,a
408         mov     Phase1,a
409         mov     r0,#TimPhase
410         acall   StartTim
411         sjmp    CantFire
412
413 2:      cjne    a,#Ph_First-Ph_Ammo,CantFire
414         mov     a,SeriCnt
415         dec     a
416         jz      CantFire
417 0:      jb      BPI_Fire,CantFire
418         mov     a,SeriCnt
419         subb    a,SeriC_Max
420         jnc     CantFire
421         mov     a,Ammo
422         jz      CantFire
423         jb      XMitting,CantFire
424 // Fire one shot NOW!
425         inc     SeriCnt
426         mov     Phase,#Ph_Laser
427         dec     Ammo
428         clr     BPM_Laser
429         mov     c,BBS_QuietS
430         mov     BPM_Sound,c
431         inc     TotShotsW+1
432         mov     a,TotShotsW+1
433         jnz     1f
434         inc     TotShotsW
435 1:      mov     a,#PktN_Fire
436         acall   StartXMiX
437         mov     ScrollPtr,#0
438         acall   DispAmmo
439         mov     a,T_Laser
440         mov     r0,#TimPhase
441         acall   StartTim
442 CantFire:
443 // Scroll Update
444         mov     r0,#TimScroll
445         acall   QueryTim
446         jnc     6f
447         clr     TimedDisp
448         mov     a,ScrollPtr
449         jz      6f
450         mov     dptr,#ScrBase+2
451         movc    a,@a+dptr
452         jnz     0f
453         mov     ScrollPtr,a
454         sjmp    6f
455
456 0:      inc     ScrollPtr
457         mov     a,ScrollPtr
458         movc    a,@a+dptr
459         jnz     1f
460         mov     a,T_ScrollF
461         sjmp    2f
462
463 1:      mov     a,T_Scroll
464 2:      acall   StartTim
465 6:
466 // Packet received?
467         mov     a,UserPktS
468         mov     r0,a
469         xrl     a,CurPktS
470         jnz     0f
471 GotNoSerS:      ajmp    GotNoSer
472
473 ShortPkt:       mov     a,r0
474         acall   RxBufInc
475         push    0 //r0
476         mov     r0,a
477         sjmp    ProcSPkt
478
479 0:      mov     a,@r0
480 ;       jb      acc.7,ShortPkt
481         jb      XMitting,GotNoSerS
482         inc     a
483         add     a,r0
484         subb    a,#RxBuf+RxBufSiz
485         jnc     1f
486         add     a,#RxBufSiz
487 1:      add     a,#RxBuf
488         push    acc
489         mov     a,@r0
490         clr     c
491         subb    a,#3
492         jc      FailRPktN
493         mov     @r0,a
494         push    0 //r0
495         inc     a
496         mov     r2,a
497         acall   RxBufInc
498         mov     r1,#RxChkXSumW+1
499         mov     @r1,#low XSum_Base
500         dec     r1
501         mov     @r1,#high XSum_Base
502 0:      mov     a,@r0
503         acall   AddXSum
504         acall   RxBufInc
505         djnz    r2,0b
506         pop     2 //r2
507         mov     a,@r0
508         xrl     a,@r1
509 FailRPktN:      jnz     FailRPktS
510         acall   RxBufInc
511         mov     a,@r0
512         inc     r1
513         xrl     a,@r1
514         jnz     FailRPktS
515 // XSum is correct
516         mov     a,r2
517         mov     r0,a
518         mov     a,@r0
519         mov     r2,a
520         acall   RxBufInc
521         mov     a,@r0
522         mov     r3,a
523         acall   RxBufInc
524         cjne    r3,#PktN_Fire,NoPFire
525         cjne    r2,#1,FailRPktS
526 // Fire packet received, @R0=remote SwConfigX
527 ProcSPkt:       mov     a,@r0
528         jnb     BBS_IsTeam,ShotDown // We're anarchy
529         jnb     acc.BNS_IsTeam,ShotDown // From anarchy one
530         xrl     a,SwConfigX
531         jnb     acc.BNS_TeamN,FriendS // One of our team
532         mov     a,@r0
533 ShotDown:       xrl     a,SwConfigX
534         anl     a,#BMS_IdentM
535         jz      FriendS
536 // Really shot by enemy
537         mov     TimedL,#Font_E
538         mov     a,Phase
539         xrl     a,#Ph_Dead
540         jz      PrintIDR
541         mov     a,@r0
542         anl     a,#0x0F
543         rl      a
544         add     a,#GraveW+1
545         mov     r1,a
546         inc     @r1
547         mov     a,@r1
548         jnz     0f
549         dec     r1
550         inc     @r1
551 0:      mov     TimedL,#Font_S
552         mov     Phase,#Ph_Dead
553         mov     Phase1,DeadN
554         anl     MiscP,#~BMM_LEDM
555         push    0 //r0
556         acall   NxtDead
557         pop     0 //r0
558         sjmp    PrintIDR
559
560 FriendS:        mov     TimedL,#Font_F
561 PrintIDR:       mov     a,@r0
562         anl     a,#0x0F
563         mov     dptr,#FontHex
564         movc    a,@a+dptr
565         mov     TimedR,a
566         setb    TimedDisp
567         mov     ScrollPtr,#0
568         mov     a,T_TimedD
569         mov     r0,#TimScroll
570         acall   StartTim
571 FailRPktS:      sjmp    FailRPkt
572
573 NoPFire:        cjne    r3,#PktN_CfgR,NoPCfgR
574         jnb     XMitting,0f
575         dec     sp
576         sjmp    GotNoSer
577
578 0:      mov     a,@r0
579         xrl     a,SwConfigX
580         anl     a,#BMS_IdentM
581         jnz     FailRPkt
582         acall   RxBufInc2
583 CfgNBlock:      mov     a,r2
584         jz      FailRPkt
585         mov     a,@r0
586         acall   RxBufInc2
587         jz      CRRepRes
588         mov     r3,a
589         mov     a,r2
590         jz      FailRPkt
591         mov     a,@r0
592         acall   RxBufInc2
593         mov     r1,a
594 CfgBlock:       mov     a,r2
595         jz      FailRPkt
596         mov     a,@r0
597         acall   RxBufInc2
598         push    acc
599         mov     a,r1
600         clr     c
601         subb    a,#AddrSpace
602         pop     acc
603         jnc     SkipWrite
604         jb      UnConfig,SkipWrite
605         mov     @r1,a
606 SkipWrite:      inc     r1
607         djnz    r3,CfgBlock
608         sjmp    CfgNBlock
609
610 CRRepRes:       pop     acc
611         clr     c
612         subb    a,#RxBuf+2
613         jnc     0f
614         add     a,#RxBufSiz
615 0:      add     a,#RxBuf
616         mov     CAPktEnd,a
617         mov     a,r0
618         mov     UserPktS,a
619         mov     a,#CfgRS-ScrBase
620         acall   DoScroll
621         mov     a,#PktN_CfgA
622         acall   StartXMiX
623         sjmp    GotNoSer
624
625 NoPCfgR:        cjne    r3,#PktN_CfgA,FailRPkt
626         mov     a,#CfgAS-ScrBase
627 ScrRPkt:        acall   DoScroll
628 FailRPkt:       pop     UserPktS
629
630 GotNoSer:
631
632         ajmp    MainLoop
633
634 /******************************/
635 PhaseTab:
636         db      PhCfgDump-PhaseTab
637         db      PhAmmo   -PhaseTab
638         db      PhLaser  -PhaseTab
639         db      PhDelay  -PhaseTab
640         db      PhFirst  -PhaseTab
641         db      PhReload -PhaseTab
642         db      PhDead   -PhaseTab
643         db      PhTest   -PhaseTab
644
645 PhCfgDump:      mov     a,T_TimedD
646         acall   StartTim
647 SkpCDump:       inc     @r1
648         mov     dptr,#CfgDTab
649         mov     a,@r1
650         clr     c
651         subb    a,#CD_Grave0
652         jnc     CDGrave
653         mov     a,@r1
654 JmpByTab:       movc    a,@a+dptr
655         jmp     @a+dptr
656
657 PhLaser:        orl     MiscP,#BMM_Laser|BMM_Sound
658         inc     Phase
659         mov     a,T_Delay
660         sjmp    StartTimS
661
662 PhDelay:        inc     Phase
663         mov     a,Ammo
664         jz      PD_Reload       // Do Reload
665         mov     a,T_First
666         sjmp    StartTimS
667
668 PhTest: jb      XMitting,PT_WaitTI
669         mov     a,#TestChar
670         acall   StartXMiX
671 PT_WaitTI:
672         mov     a,SwConfigX
673         swap    a
674         rr      a
675         anl     a,#0x78
676         sjmp    StartTimS
677
678 PD_Reload:      inc     Phase
679         mov     Phase1,ReloadN
680         mov     Ammo,Ammo_Max
681         mov     a,#ReloadS-ScrBase
682         acall   DoScroll
683 PhReload:       dec     Phase1
684         mov     a,Phase1
685         jz      NormAmmo
686         mov     DispL,#Font_L
687         mov     a,Phase1
688         acall   PutHexFnR
689         mov     a,T_Reload
690         sjmp    StartTimP
691
692 PhDead: xrl     MiscP,#BMM_LEDM
693         dec     Phase1
694         mov     a,Phase1
695         jz      RAmmonLED
696 NxtDead:        mov     B,DeadDivN
697         div     aB
698         xch     a,B
699         jnz     0f
700         mov     DispL,#Font_D
701         mov     a,B
702         acall   PutHexFnR
703 0:      mov     a,T_Dead
704 StartTimP:      mov     r0,#TimPhase
705 StartTimS:      ajmp    StartTim
706
707 RAmmonLED:      acall   InitLED4
708 PhFirst:
709 NormAmmo:       mov     Phase,#Ph_Ammo
710 PhAmmo: // PhAmmo shouldn't happen <= no timer
711         ajmp    DispAmmo
712
713 CDGrave:        cjne    a,#CD_Last-CD_Grave0,1f
714         sjmp    NormAmmo
715
716 1:      mov     B,#3
717         div     aB
718         mov     r2,a
719         rl      a
720         add     a,#GraveW
721         mov     r0,a
722         mov     a,@r0
723         inc     r0
724         orl     a,@r0
725         jz      SkpCDump2
726         mov     a,B
727         cjne    a,#0,0f
728         mov     DispL,#Font_D
729         mov     a,r2
730 PutHexFnR:      mov     dptr,#FontHex
731         ajmp    PutFontR
732
733 0:      dec     r0
734         mov     r3,a
735         acall   ConvDecW
736         cjne    r3,#1,DispHexS
737         mov     a,@r0
738         sjmp    DispHexS
739
740 CfgDTab equ     $-1
741         db      CDPNum   -CfgDTab
742         db      CDGMode  -CfgDTab
743         db      CDLEDs   -CfgDTab
744         db      CDSound  -CfgDTab
745         db      CDWDogs  -CfgDTab
746         db      CDWDogsN -CfgDTab
747         db      CDRSwChg -CfgDTab
748         db      CDRSwChgN-CfgDTab
749         db      CDTotSh  -CfgDTab
750         db      CDTotShM -CfgDTab
751         db      CDTotShN -CfgDTab
752
753 CDPNum: mov     DispL,#Font_P
754         mov     a,SwConfigX
755         anl     a,#0x0F
756         sjmp    PutHexFnR
757
758 CDGMode:        mov     DispL,#Font_G
759         mov     a,#Font_A
760         jnb     BBS_IsTeam,DoGaMode
761         mov     a,#Font_R
762         jnb     BBS_TeamN,DoGaMode
763         mov     a,#Font_G
764 DoGaMode:       mov     DispR,a
765         ret
766
767 CDLEDs: jnb     BBS_QuietL,SkpCDumpS
768         mov     DispL,#Font_L
769         mov     DispR,#Font_D
770         ret
771
772 CDSound:        jnb     BBS_QuietS,SkpCDumpS
773         mov     DispL,#Font_S
774         mov     DispR,#Font_D
775         ret
776
777 CDWDogs:        mov     a,WDogsCnt
778         jz      SkpCDump1
779         mov     DispL,#Font_D
780         mov     DispR,#Font_R
781         ret
782
783 SkpCDump2:      inc     @r1
784 SkpCDump1:      inc     @r1
785 SkpCDumpS:      ajmp    SkpCDump
786
787 CDWDogsN:       mov     a,WDogsCnt
788         sjmp    DispDecS
789
790 CDRSwChg:       mov     a,RSwChgs
791         jz      SkpCDump1
792         mov     DispL,#Font_S
793         mov     DispR,#Font_C
794         ret
795
796 CDRSwChgN:      mov     a,RSwChgs
797 DispDecS:       ajmp    DispDec
798
799 CDTotSh:        mov     a,TotShotsW
800         orl     a,TotShotsW+1
801         jz      SkpCDump2
802         mov     DispL,#Font_F
803         mov     DispR,#Font_S
804         ret
805
806 CDTotShM:       mov     r0,#TotShotsW
807         acall   ConvDecW
808         mov     a,@r0
809         sjmp    DispHexS
810
811 CDTotShN:       mov     r0,#TotShotsW
812         acall   ConvDecW
813 DispHexS:       ajmp    DispHex
814 /******************************/
815 SerICont:       push    psw
816         push    acc
817         push    0 //r0
818         push    2 //r2
819 RetryRI:        jbc     RI,GotRI
820 RetryTI:        jbc     TI,GotTI
821         pop     2 //r2
822         pop     0 //r0
823         pop     acc
824         pop     psw
825         reti
826 /******************************/
827 GotRI:  mov     a,SBUF
828         jnb     acc.7,5f
829         jb      FastFireRD,ScratchRI
830         jb      acc.6,ScratchRI
831         mov     r0,CurPktS
832         mov     @r0,a
833         acall   RxBufInc
834         mov     a,r0
835         xrl     a,UserPktS
836         jz      ScratchRI
837         mov     a,r0
838         mov     CurPktS,a
839         sjmp    ScratchRI
840
841 5:      cjne    a,#Mark_Start,0f
842         mov     r0,CurPktS
843         acall   RxBufInc
844         mov     a,r0
845         xrl     a,UserPktS
846         jz      ScratchRI
847         mov     CurPktE,r0
848         setb    PktRcvng
849         clr     PktGotNib
850         sjmp    RetryRI
851
852 0:      cjne    a,#Mark_End,1f
853         jnb     PktRcvng,RetryRI
854         jb      PktGotNib,ScratchRI
855         clr     PktRcvng
856         mov     a,CurPktE
857         mov     r0,CurPktS
858         clr     c
859         subb    a,r0
860         jnc     3f
861         add     a,#RxBufSiz
862 3:      dec     a
863         jz      RetryRI
864         mov     @r0,a
865         mov     a,CurPktE
866         mov     CurPktS,a
867 // Successfuly received packet
868         sjmp    RetryRI
869
870 1:      jnb     PktRcvng,RetryRI
871         clr     c
872         subb    a,#'0'
873         jc      ScratchRI
874         subb    a,#10
875         jc      GotRITen
876         subb    a,#'A'-('9'+1)
877         jc      ScratchRI
878         subb    a,#6
879         jc      GotRISix
880 ScratchRI:      clr     PktRcvng
881 RetryRIS:       sjmp    RetryRI
882 /******************************/
883 GotTI:  jnb     XMitting,RetryTI
884         clr     XMittedN
885         jnb     XMitHaveP,PrepXMit
886         mov     a,XMitNib
887 SendPrepd:      jb      XMittedN,RetryTIS
888         jbc     XMitByte,XMitByteC
889         jnb     XMit1stNib,Have2ndN
890         swap    a
891 Have2ndN:       anl     a,#0x0F
892         add     a,#'0'
893         mov     r2,a
894         clr     c
895         subb    a,#'9'+1
896         mov     a,r2
897         jc      XMitByteC
898         add     a,#'A'-('9'+1)
899 XMitByteC:      mov     SBUF,a
900         setb    XMittedN
901         mov     c,XMit1stNib
902         clr     XMit1stNib
903         mov     XMitHaveP,c
904         jnc     PrepXMit
905 RetryTIS:       ajmp    RetryTI
906 /******************************/
907 GotRISix:       add     a,#6
908 GotRITen:       add     a,#10
909         jb      PktGotNib,2f
910         swap    a
911         mov     PktNibble,a
912         sjmp    DoneFNRI
913
914 2:      orl     a,PktNibble
915         mov     r2,a
916         mov     r0,CurPktE
917         acall   RxBufInc
918         mov     a,UserPktS
919         xrl     a,r0
920         jz      ScratchRI
921         mov     a,r0
922         xch     a,CurPktE
923         mov     r0,a
924         mov     a,r2
925         mov     @r0,a
926 DoneFNRI:       cpl     PktGotNib
927         sjmp    RetryRIS
928 /******************************/
929 PrepXMit:       mov     a,XMitPhase
930         mov     dptr,#PhXMitTab
931         movc    a,@a+dptr
932         jmp     @a+dptr
933
934 PhXMitTab:      db      XPStart -PhXMitTab
935         db      XPType  -PhXMitTab
936         db      XPSwCfg -PhXMitTab
937         db      XPData  -PhXMitTab
938         db      XPXSumH -PhXMitTab
939         db      XPXSumL -PhXMitTab
940         db      XPEnd   -PhXMitTab
941         db      XPFinish-PhXMitTab
942
943 InvalCR:        mov     CAPktEnd,a
944 XPFinish:       clr     XMitting
945         sjmp    RetryTIS
946
947 XPStart:        mov     a,XMitType
948         xrl     a,#TestChar
949         jnz     1f
950         mov     a,#TestChar
951         sjmp    2f
952
953 1:      xrl     a,#TestChar^PktN_Fire
954         jnz     0f
955         jb      FullFireT,0f
956         mov     a,SwConfigX
957         clr     acc.6
958         setb    acc.7
959 2:      mov     XMitPhase,#6    //XPFinish-1
960         sjmp    ContXMitB
961
962 0:      mov     a,#Mark_Start
963 ContXMitB:      setb    XMitByte
964         inc     XMitPhase
965         clr     XMit1stNib
966 ContXMit:       setb    XMitHaveP
967         mov     XMitNib,a
968         ajmp    SendPrepd
969
970 XPType: mov     XMitXSumW  ,#high XSum_Base
971         mov     XMitXSumW+1,#low  XSum_Base
972         mov     a,XMitType
973 XMitXHexP:      inc     XMitPhase
974 XMitXHex:       push    1 //r1
975         push    3 //r3
976         push    B
977         mov     r1,#XMitXSumW
978         push    acc
979         acall   AddXSum
980         pop     acc
981         pop     B
982         pop     3 //r3
983         pop     1 //r1
984 XMitHex:        clr     XMitByte
985         setb    XMit1stNib
986         sjmp    ContXMit
987
988 XPSwCfg:        mov     a,SwConfigX
989         sjmp    XMitXHexP
990
991 XPData: mov     a,XMitType
992         xrl     a,#PktN_CfgA
993         jnz     XPDatDone
994         mov     r0,UserPktS
995 NxtBlock:       mov     a,r0
996         xrl     a,CAPktEnd
997         jz      DoneAns
998         mov     a,@r0
999         dec     @r0
1000         mov     r2,a
1001         acall   RxBufInc
1002         mov     a,r0
1003         xrl     a,CAPktEnd
1004         jz      InvalCR // Invalid CfgReq
1005         mov     a,r2
1006         jz      DoneBlock
1007         mov     a,@r0
1008         inc     @r0
1009         mov     r0,a
1010         mov     a,@r0
1011         sjmp    XMitXHex
1012
1013 DoneBlock:      acall   RxBufInc
1014         mov     UserPktS,r0
1015         mov     a,r0
1016         xrl     a,CAPktEnd
1017         jnz     NxtBlock
1018 DoneAns:        mov     CAPktEnd,a      // Cancel CfgA pending alert
1019         acall   RxBufInc
1020         acall   RxBufInc
1021         mov     UserPktS,r0
1022 XPDatDone:      inc     XMitPhase
1023 XPXSumH:        mov     a,XMitXSumW
1024 XMitHexP:       inc     XMitPhase
1025         sjmp    XMitHex
1026
1027 XPXSumL:        mov     a,XMitXSumW+1
1028         sjmp    XMitHexP
1029
1030 XPEnd:  mov     a,#Mark_End
1031         sjmp    ContXMitB
1032
1033 /******************************/
1034 StartXMiX:      mov     XMitType,a
1035         clr     a
1036         mov     XMitPhase,a
1037         clr     XMitHaveP
1038         setb    XMitting
1039         setb    TI      // Start XMit now!
1040         ret
1041 /******************************/
1042 // I: A=text offset, O: Filled DispL+DispR, D: A,R0,R2
1043 DoScroll:       mov     ScrollPtr,a
1044         mov     r0,#TimScroll
1045         mov     a,T_ScrollF
1046         sjmp    StartTim
1047 /******************************/
1048 // O: Filled DispL+DispR, D: A,B,R2
1049 DispAmmo:       mov     a,Ammo
1050 // I: A=decimal, O: Filled DispL+DispR, D: A,B,R2
1051 DispDec:        mov     R2,a
1052         clr     c
1053         subb    a,#100
1054         jnc     0f
1055         mov     a,MaxDecimal
1056 0:      mov     a,R2
1057         mov     B,#10
1058         div     aB
1059         swap    a
1060         orl     a,B
1061 // I: A=hexadecimal, O: Filled DispL+DispR, D: A,R2
1062 DispHex:        mov     dptr,#FontHex
1063         mov     R2,a
1064         swap    a
1065         anl     a,#0x0F
1066         movc    a,@a+dptr
1067         mov     DispL,a
1068         mov     a,R2
1069         anl     a,#0x0F
1070 PutFontR:       movc    a,@a+dptr
1071         mov     DispR,a
1072 Ret1:   ret
1073 /******************************/
1074 InitLED4:       orl     MiscP,#BMM_LEDM
1075         jb      BBS_QuietL,Ret1
1076         anl     MiscP,#~BMM_LED0
1077         jnb     BBS_IsTeam,0f
1078         jnb     BBS_TeamN,0f
1079         xrl     MiscP,#BMM_LED0|BMM_LED1
1080 0:      mov     r0,#TimLED4
1081         mov     a,T_LED4
1082 /******************************/
1083 // I: R0=addr of byte, A=min time, O: @R0!=0, D:A
1084 StartTim:       add     a,Timer
1085         jnz     0f
1086         inc     a
1087 0:      mov     @R0,a
1088         ret
1089 /******************************/
1090 // I: R0=addr of byte, C=1->success, D:A
1091 QueryTim:       mov     a,@R0
1092         clr     c
1093         jz      0f
1094         subb    a,Timer
1095         mov     c,acc.7
1096         jnc     0f
1097         clr     a
1098         mov     @R0,a
1099 0:      ret
1100 /******************************/
1101 RxBufInc2:      dec     r2
1102 // I: R0=RxAddr, O: R0=RxAddr+1
1103 RxBufInc:       inc     r0
1104         cjne    r0,#RxBuf+RxBufSiz,0f
1105         mov     r0,#RxBuf
1106 0:      ret
1107 /******************************/
1108 // I: @R1/W=xsum, A=Byte, O: @R1/W=xsum+Byte, D:A,B,R3
1109 AddXSum:        push    2 //r2
1110         push    acc
1111         inc     r1
1112         inc     @r1
1113         mov     a,@r1
1114         dec     r1
1115         jnz     0f
1116         inc     @r1
1117 0:      mov     B,#XSum_Mul
1118         mul     aB
1119         mov     r2,a
1120         mov     r3,B
1121         mov     a,@r1
1122         mov     B,#XSum_Mul
1123         mul     aB
1124         add     a,r3
1125         mov     r3,a
1126         pop     acc
1127         add     a,r2
1128         inc     r1
1129         mov     @r1,a
1130         dec     r1
1131         mov     a,r3
1132         addc    a,#0
1133         mov     @r1,a
1134         pop     2 //r2
1135         ret
1136 // I: R0=SrcWord, O: R0=ConvDecW1, A=LOW [R0/W], D:R1,R2
1137 ConvDecW:
1138         inc     sp
1139         mov     r1,sp
1140         inc     sp
1141         mov     a,@r0
1142         mov     @r1,a
1143         inc     r0
1144         inc     r1
1145         mov     a,@r0
1146         mov     @r1,a
1147         mov     dptr,#CDW_Tab
1148         mov     r2,#4
1149         mov     r0,#ConvDecW1
1150 3:      xchd    a,@r0
1151         swap    a
1152         mov     @r0,a
1153         inc     r0
1154         clr     a
1155         xchd    a,@r0
1156         swap    a
1157         mov     @r0,a
1158 2:      mov     a,#1
1159         movc    a,@a+dptr
1160         mov     B,a
1161         mov     a,@r1
1162         clr     c
1163         subb    a,B
1164         push    acc
1165         dec     r1
1166         clr     a
1167         movc    a,@a+dptr
1168         mov     B,a
1169         mov     a,@r1
1170         subb    a,B
1171         jc      1f
1172         mov     @r1,a
1173         pop     acc
1174         inc     r1
1175         mov     @r1,a
1176         inc     @r0
1177         sjmp    2b
1178
1179 1:      dec     sp
1180         inc     dptr
1181         inc     dptr
1182         inc     r1
1183         mov     a,@r0
1184         dec     r0
1185         djnz    r2,3b
1186         dec     sp
1187         dec     sp
1188         ret
1189 /******************************/
1190
1191 ScrBase:        // Every text offset must >0 !!!
1192 FontHex:        db      Font_0,Font_1,Font_2,Font_3,Font_4,Font_5,Font_6,Font_7
1193         db      Font_8,Font_9,Font_A,Font_B,Font_C,Font_D,Font_E,Font_F
1194 ReloadS:        db      Font_R,Font_E,Font_L,Font_O,Font_A,Font_D,0
1195 CfgAS:  db      Font_C,Font_O,Font_N,Font_F,Font_I,Font_G
1196         db      Font_A,Font_N,Font_S,0
1197 CfgRS:  db      Font_C,Font_O,Font_N,Font_F,Font_I,Font_G
1198         db      Font_U,Font_R,Font_E,Font_D,0
1199         if      ($-ScrBase>=0x100) ScrBase equ 0
1200 /******************************/
1201 CDW_Tab:        dw      1000,100,10,1
1202
1203 LoadContn:
1204         db      12      // Reload countdown
1205         db      40      // Dead state countdown
1206         db      15      // Maximum # of shots per one series
1207         db      40      // Ammo # in one clip
1208         db      40      // Remaining ammo in the current clip
1209         db      4       // 4LED-Dead -> Dead cycle divisor
1210         db      100     // Startup info cycle delay
1211         db      48      // Reload cycle delay
1212         db      8       // Laser firing
1213         db      2       // Inter-Laser delay
1214         db      24      // Additional series start delay period
1215         db      32      // 1 of RY-LED switch period
1216         db      25      // Scroll of one letter
1217         db      50      // Scroll of 1st two letters
1218         db      24      // 4LED-Dead (and Dead) cycle delay
1219         db      110     // TimedDisp delay (temporary, non-scrolling)
1220         if      ($-LoadContn!=LoadPartS) LoadPartS equ 0