wormy 0.93.1415
[wormy.git] / wormy.z80
1 ; Title                      : Wormy
2 ; Version                    : 93%
3 ; Release Date               : summer 2001
4 ; Filename                   : wormy.86p (5kb)
5 ; Author(s)                  : Shiar
6 ; Email Address              : shiar0@hotmail.com
7 ; ICQ UIN                    : #43840958
8 ; Web Page                   : www.shiar.org
9 ; Description                : ruling Nibbles-like game 1-4 players
10 ; Where to get this game     : www.shiar.org (home of Wormy)
11 ; Other games by author(s)   : Nemesis beta
12 ; Additional Credits to      : Matthew Shepcar (wrote original Peaworm, end'98)
13 ;                              Jonah Cohen (helped writing worm)
14
15 ;-----------------------------
16 ;----------- TO-DO -----------
17 ;-----------------------------
18
19 ; 93% = DONE
20
21 ;     * internal levels
22 ;       * check levels/gametype
23 ;       * enough hiscore saves!
24 ;     * complete readme
25 ;  1% * misc (pollish, bugs, &&&)
26 ;   * LINK
27 ;  2% * fix deaths linkplay and transmit game/level data
28 ;  2% * make linkplay available for all gametypes (not just deathmatch)
29 ;   * CTF
30 ;  1% * fix pea XOR problem in ctf (+dom?)
31 ;     * fix wormstop
32 ;  1% * domination?: take control points by running over them and hold them
33
34 ;100% = bugs fixed + levels done
35
36 ;-----------------------------
37 ;-----------------------------
38 ;---------  W O R M  ---------
39 ;-----------------------------
40 ;-----------------------------
41
42 #define buffer      ;use display buffer (otherwise write directly to screen)
43 #define readymask   ;"greys" out the field before starting a level
44 ;#define hlines     ;horizontal-line routine for more speed drawing boxes
45                         ;(doesn't work properly)
46
47 ;#define readytext  ;displays "prepare" before level starts
48 ;#define invincible ;worms cannot die =)
49
50 #define cal call
51 #define psh push
52 #define dnz djnz
53
54 #include "asm86.h"
55 #include "ti86asm.inc"
56
57 _SHRACC            = $4383 ;4x srl a
58 _SHLACC            = $438B ;4x sll a
59 _divHLby10         = $4044 ;hl=hl/10
60 _divAby10          = $4DAF ;a=a/10
61 _HLTIMES10         = $41BF ;hl=hl*10
62 _cphlde            = $403C ;cp hl,de
63 _clrWindow         = $4A86 ;clear screen
64 _asapvar           = $D6FC ;own name (worm)
65 _MOV4B             = $429B ;4x ld (de),(hl)
66 _MOV5B             = $4297 ;5x ld (de),(hl)
67 _mov9b             = $4283 ;9x ld (de),(hl)
68 _ldHLind           = $4010 ;ld hl,(hl)
69 _swapt_            = $45F3 ;ex_ahl_bde
70 _Get_Word_ahl      = $521D ;ld de,(ahl)
71 _Set_Word_ahl      = $5221 ;ld (ahl),de
72 _INC_PTR_AHL       = $4637 ;ahl=ahl+1
73 _AHL_PLUS_2_PG3    = $4C3F ;ahl=ahl+2
74 _SET_ABS_SRC_ADDR  = $4647 ;set source for mm.ldir =ahl
75 _LOAD_ABS_SRC_ADDR = $5209 ;ahl = mm.ldir source
76 _SET_ABS_DEST_ADDR = $5285 ;set destination for mm.ldir = ahl
77 _SET_MM_NUM_BYTES  = $464F ;number of bytes for mm.ldir = ahl
78 _mm_ldir           = $52ED ;24bit ldir
79 _RAM_PAGE_1        = $47E3 ;set $8000+ to page 1
80 _RAM_PAGE_7        = $47F3 ;"""" 7
81 _PTEMP_END         = $D29A ;end of VAT
82 _load_ram_ahl      = $462F ;ahl->page+hl
83 _writeb_inc_ahl    = $5567 ;ld (ahl),c
84 _jforce            = $409C ;TI-OS stack restored
85 _EXLP              = $4493 ;swap (hl),(de) b times
86 _GETB_AHL          = $46C3 ;a=(ahl) \ hl=ahl
87
88 ;-----------------------------
89 ;------- data  storage -------
90 ;-----------------------------
91
92 ;--- permanent
93
94 ScrBuffer   = $8820 ;-A7FF (20*FF=1FE0)
95 worm2p      = $A800 ;-ABFF (400)      %10101O00
96 worm1       = $AC00 ;-AC1D (31d)
97 worm2       = $AC1F ;-AC3B (1F)
98 worm3       = $AC3E ;-AC59 (1F)
99 worm4       = $AC5D ;-AC77 (1F)
100 balls       = $AC7C ;-ACFF (3x43d)
101 SinCosTable = $AD00 ;-AE00 (4x40)
102         ;free $AE01 ;-AFFF (1FF)
103 worm1p      = $B000 ;-B7FF (800)      %1011O000
104 worm3p      = $B800 ;-BBFF (400)      %10111O00
105         ;free $BF91 ;-BFFF (6F)
106
107      ;program $D748 ;-E7FF (106D+4A)
108         ;free $E800 ;-EFFF (800)
109 worm4p      = $F000 ;-F3FF (400)      %11110O00
110 leveldata   = $F400 ;-FA70 (<=671)
111
112 turn10  = $AE01
113 peaspos = $AE02
114
115 ;--- temporary
116
117 namelength  = $BC00 ;(1)         @menu
118 #ifdef buffer
119 DispBuffer  = $BC00 ;(10x57d)    @game
120 #else
121 DispBuffer  = $FC70
122 #endif
123
124 ;-----------------------------
125 ;------- program start -------
126 ;-----------------------------
127
128 .org _asm_exec_ram
129
130 wormVhost   = 093
131 wormVclient = 193
132
133 start:
134   nop
135   jp Start
136   .dw 1
137   .dw WormTxt
138   .dw WormIcon
139
140 WormTxt:
141   .db "WORMY by SHIAR -- beta 93%",0
142 WormIcon:
143   .db 9,2
144   .db %10010110,%01101111
145   .db %10110101,%01001011
146   .db %01110011,%01001001
147   .db %00000011,%10000000
148   .db %00000001,%11100000
149   .db %00111000,%11111000
150   .db %01111110,%00111111
151   .db %11101111,%00001111
152   .db %11000011,%10000000
153
154 levelhead  = 'w'
155 levelhead2 = 93 ;wormy levels header = "93"
156
157 int_handler:
158   ex af,af'
159   in a,($03)
160   bit 3,a
161   jp z,$0039
162   res 0,a
163   out ($03),a
164   jp $0039
165 int_end:
166
167 Start:
168   ld  (SpSave),sp
169   cal _runindicoff
170   cal _flushallmenus
171
172   im  1
173   ld  a,$D4
174   ld  h,a
175   ld  l,0     ;ld hl,$D400
176   ld  d,a
177   ld  e,1     ;ld de,$D401
178   ld  b,e
179   ld  c,l     ;ld bc,$0100
180   dec a       ;ld a,$D3
181   ld  (hl),a
182   ldir
183   ld  hl,int_handler
184   ld  d,a
185   ld  e,a     ;ld de,$D3D3
186   ld  bc,int_end-int_handler
187   ldir
188   inc a       ;ld a,$D4
189   ld  i,a
190   im  2
191
192   cal _RAM_PAGE_7
193   ld  hl,$BFFF ;VAT start
194   ld  ix,templevels
195 searchloop:
196   ld  de,(_PTEMP_END+1) ;VAT end
197   or  a ;nc
198   sbc hl,de ;hl<de?
199   jr  c,searchcomplete
200   add hl,de
201   psh hl
202   ld  a,(hl)
203   cp  $0C ;string
204   jr  z,stringfound
205 searchnext:
206   pop hl
207   dec hl ;5x
208   dec hl
209   dec hl
210   dec hl
211   dec hl
212   ld  b,(hl) ;name size
213   inc b
214 skipname:
215   dec hl
216   dnz skipname
217   jr  searchloop
218
219 stringfound:
220   dec hl
221   ld  e,(hl)
222   dec hl
223   ld  d,(hl)
224   dec hl
225   ld  a,(hl)
226   ex  de,hl ;ld ahl,(hl)
227   cal _AHL_PLUS_2_PG3 ;string id
228   cal _Get_Word_ahl ;ld de,(ahl)
229   ld (ix),a
230   ld  a,levelhead
231   cp  e
232   jr  nz,_searchnext ;not worm
233   ld  a,levelhead2
234   cp  d
235   jr  nz,_searchnext
236   inc ix ;save level's ahl
237   ld a,h
238   ld (ix),a
239   inc ix
240   ld a,l
241   ld (ix),a
242   inc ix
243 _searchnext:
244   cal _RAM_PAGE_7
245   jr searchnext
246
247 loadgametype:
248   psh de
249   inc bc
250   inc bc
251   cal _Get_Word_ahl ;ld de,(ahl++)
252   psh af
253   ld  a,d
254   or  e
255   jr  z,defaultlevels
256   ld  a,e ;set new level
257   ld  (bc),a
258   inc bc
259   ld  a,d
260   ld  (bc),a
261   dec bc
262 defaultlevels:
263   pop af
264   pop de ;counter
265   dec d ;8x
266   jr  nz,loadgametype
267   ret
268
269 searchcomplete:
270   ld  a,255
271   ld  (ix),a ;end mark
272
273   cal _clrWindow
274   ld  hl,templevels-3
275   psh hl
276   ld  hl,$0020
277   ld  (_penCol),hl
278   ld  hl,txtLevsel
279   cal _vputs ;"< Select levels: >"
280   ld  hl,$0601 ;x=1
281   ld  (_penCol),hl
282   pop hl
283 dispnextlevel:
284   ld  a,(hl)
285   inc a ;cp 255
286   jr  z,_levselect
287   ld  a,(hl) ;ade=(hl)
288 displevel:
289   inc hl
290   ld  d,(hl)
291   inc hl
292   ld  e,(hl)
293   inc hl
294   psh hl
295   ex  de,hl ;ahl=ade=(hl)
296   cal _load_ram_ahl ;hl=ahl
297   ld  b,(hl) ;b=title size
298   cal _vputs
299   ld  hl,_penCol
300   ld  (hl),$01 ;x=1
301   inc hl
302   ld  a,(hl)
303   add a,6
304   ld  (hl),a ;y+6
305   ld  hl,availevels
306   inc (hl)
307   pop hl
308   jr  dispnextlevel
309
310 levup:
311   cal menupos
312   dec b ;up
313   ld  a,b
314   cp  -4
315   jr  nz,levselected
316   inc b ;undo
317   jr  levselected
318 levdown:
319   cal menupos
320   inc b ;down
321   ld  a,b
322   cp  -3
323 availevels =$-1
324   jr  nz,levselected
325   dec b ;back up
326 levselected:
327   jp  menupos
328
329 _levselect:
330   ld  b,-3 ;level selected
331   cal menupos
332 levselect:
333   halt \ halt
334   psh bc
335   cal GET_KEY
336   pop bc ;GET_KEY destr. b
337   cp  K_UP
338   cal z,levup
339   dec a ;K_DOWN
340   cal z,levdown
341   cp  K_SECOND-1
342   jr  z,loadlevel
343   cp  K_EXIT-1
344   ret z
345   cp  K_ENTER-1
346   jr  nz,levselect
347 ; jr  z,loadlevel
348
349 loadlevel:
350   ld  a,b
351   add a,3 ;sellev+3 (#0==-3)
352   ld  e,a
353   add a,a ;*2
354   add a,e ;*3
355   ld  e,a
356   ld  d,0 ;de=sellev*3
357   ld  hl,templevels-3
358   add hl,de
359   ld  a,(hl) ;ade=(hl)
360   or  a ;levelfile on page 0 (=internal)
361   jr  z,levelloaded
362
363   inc hl
364   ld  d,(hl)
365   inc hl
366   ld  e,(hl)
367   ex  de,hl ;ahl=ade
368 skiptitle:
369   ld  b,a ;psh ahl
370   psh hl
371   cal _GETB_AHL ;ld a,(ahl)
372   pop hl
373   or  a
374   ld  a,b ;pop ahl
375   psh af
376   cal _INC_PTR_AHL ;ahl++
377   pop af ;cp 0
378   jr  nz,skiptitle ;goto #0-terminator
379
380   cal _Get_Word_ahl
381   ld  (leveldataSize),de
382   ld  d,8 ;counter
383   ld  bc,datalevels-2
384   cal loadgametype
385   ld  (hilvlposa),a
386   ld  (hilvlposhl),hl
387   ld  d,4
388   cal loadgametype
389
390   cal _SET_ABS_SRC_ADDR ;levelsstart
391   xor a
392   ld  hl,leveldata
393   cal _SET_ABS_DEST_ADDR ;store in mem.
394   ld  hl,0
395 leveldataSize =$-2
396   cal _SET_MM_NUM_BYTES
397   cal _mm_ldir
398
399   cal _LOAD_ABS_SRC_ADDR ;->ahl
400   ld  (hiscrposa),a
401   ld  (hiscrposhl),hl
402   cal _RAM_PAGE_1
403
404   ld  hl,leveldata
405   ld  de,defsprsize
406   ldi ;(de),(hl)\inc hl
407   ld  (defsprite),hl
408 levelloaded:
409   cal _RAM_PAGE_1
410
411   res 2,(iy+13) ;appAutoScroll
412   ld  a,r
413   ld  (Seed),a
414
415   ld  hl,datasingle+3
416   ld  b,8
417   ld  de,8
418 setdeflevels:
419   ld  (hl),1 ;def=level#1
420   add hl,de ;next
421   dnz setdeflevels
422
423 ;-----------------------------
424 ;----- build trig tables -----
425 ;-----------------------------
426
427   ld  hl,TrigPrecalc
428   ld  de,SinCosTable
429   psh de                        ; >> 1
430   ld  bc,65
431   ldir
432   dec hl
433   ld  b,63
434 MirrorSineWave:
435   dec hl
436   ld  a,(hl)
437   ld  (de),a
438   inc de
439   dnz MirrorSineWave
440   pop hl                         ; << 0k
441   ld  b,128+64
442 NegativeSineWave:
443   xor a
444   sub (hl)
445   ld  (de),a
446   inc hl
447   inc de
448   dnz NegativeSineWave
449
450 ;-----------------------------
451 ;---------- menu -------------
452 ;-----------------------------
453
454 DisplayMenu: ;---draw menu---
455   cal linkok
456   cal _clrWindow
457   ld  de,$FC40 ;(0,4)
458   ld  hl,wtPicture
459   ld  bc,16*16
460   ldir
461   ld  hl,$FC00+$160
462   cal hr
463   ld  hl,$FC00+$3E0
464   cal hr
465 dispmainmenu:
466   ld  hl,dispmenusets ;mainMenu
467   psh hl ;jump here after ret
468   ld  hl,txtMenu
469   ld  ix,posMenu
470 ;Mode|Level|Limit|Worms|worm #|controls
471 ; jr  dispmenucommon ;cal
472
473 dispmenucommon:
474   ld  de,$FD80 ;begin pos
475   ld  b,36*16/3
476   xor a
477 clroldmenuloop:
478   ld  (de),a
479   inc de
480   ld  (de),a
481   inc de
482   ld  (de),a
483   inc de
484   dnz clroldmenuloop
485
486   ld  b,6
487 dispmenuloop:
488   ld  d,(ix)
489   inc ix
490   ld  e,(ix)
491   inc ix
492   ld  (_penCol),de
493   cal _vputs
494   dnz dispmenuloop
495 ; ld  b,0 ;b=menu#
496   ret
497
498 hr: ;draw horizontal line at hl
499   ld  b,16
500   jp  menuinvloop
501
502 ;--- menu loop ---
503
504 dispoptionmenu:
505   ld  hl,txtoMenu
506   ld  ix,posoMenu
507 ;Back|Lives|Limit|Speed|Rotation|Growth
508   cal dispmenucommon
509
510 dispomenusets:
511   cal clrold
512
513   ld  hl,$1E3E
514   ld  (_penCol),hl
515   cal loadgamecar
516   psh hl
517   cal cshowA ;lives
518
519   ld  hl,$2A3E
520   ld  (_penCol),hl
521   pop hl ;loadgamecar
522   inc hl \ inc hl \ inc hl
523   psh hl
524   ld  a,(hl) ;(Speed)
525   inc a ;1..99
526   jr  nz,dispspeed
527   ld  hl,txtDef
528   cal _vputs
529   jr  dispspeeddone
530 dispspeed:
531   cal cshowA
532 dispspeeddone:
533
534   ld  hl,$363E
535   ld  (_penCol),hl
536   pop hl ;loadgamecar
537   inc hl
538   psh hl
539   ld  a,(hl) ;(growth)
540   inc a ;-1=None; 0..98->1..99
541   cal cshowA
542
543   ld  hl,$303E
544   ld  (_penCol),hl
545   pop hl ;loadgamecar
546   inc hl
547   psh hl
548   ld  a,(hl)
549   cp  8
550   jr  nz,dispturn
551   ld  hl,txtDef
552   cal _vputs
553   jr  dispturndone
554 dispturn:
555   cal cshowA ;turn speed
556 dispturndone:
557
558   ld  hl,$243E
559   ld  (_penCol),hl
560   pop hl ;loadgamecar
561   inc hl
562   ld  a,(hl) ;(scorelimit)
563   or  a
564   psh af
565   cal cshowA ;limit
566   pop af ;a==0?
567   jr  z,optionMenu ;do not display 0 behind 'None'
568   ld  a,'0'
569   cal _vputmap ;x10
570
571 optionMenu:
572   cal menupos
573   cal menucall
574   jr  nz,notoselect
575 oselect:
576   cal menupos
577   ld  a,b
578   or  a ;1st item?
579   jp  z,dispmainmenu ;mainMenu
580   jr  optionMenu
581 notoselect
582   cp  K_EXIT
583   jp  z,dispmainmenu
584   psh af
585   cal menupos
586   cal loadgamecar
587   inc hl
588   pop af
589   cp  K_LEFT
590   jr  z,seloleft
591   cp  K_RIGHT
592   ld  a,b
593   jr  nz,optionMenu
594
595 seloright:
596   dec a
597   jr  z,changelives
598   dec a
599   jr  z,changelimit
600   dec a
601   jr  z,changespeed
602   dec a
603   jr  z,changeturn
604   dec a
605   jr  z,changegrowth
606
607 seloleft:
608   ld  a,b
609   dec a
610   jr  z,bchangelives
611   dec a
612   jr  z,bchangelimit
613   dec a
614   jr  z,bchangespeed
615   dec a
616   jr  z,bchangeturn
617   dec a
618   jr  z,bchangegrowth
619 _optionMenu:
620   jr  optionMenu
621
622 changelives:
623   cal loadgamecar ;a=(hl)
624   inc a
625   cp  100
626   jr  nc,optionMenu ;>99
627 changedlives:
628   ld  (hl),a
629 _dispomenusets:
630   jp  dispomenusets ;optionMenu
631 bchangelives:
632   cal loadgamecar
633   sub 1 ;dec does not set cf
634   jr  c,optionMenu ;<0
635   jr  changedlives
636
637 changelimit:
638   cal changelimitInit
639   inc a
640   cp  100
641   jr  nc,optionMenu ;>99
642 changedlimit:
643   ld  (hl),a
644   jr  _dispomenusets ;optionMenu
645 bchangelimit:
646   cal changelimitInit
647   sub 1 ;dec does not set cf
648   jr  c,optionMenu ;<0
649   jr  changedlimit
650 changelimitInit:
651   cal loadgamecar
652   ld  de,6
653   add hl,de
654   ld  a,(hl) ;(scorelimit)
655   ret
656
657 changespeed:
658   cal changespeedInit
659   inc a
660   cp  99
661   jr  nc,_optionMenu ;>98
662 changedspeed:
663   dec hl ;(Speed)
664   ld  (hl),a
665   jr  _dispomenusets ;optionMenu
666 bchangespeed:
667   cal changespeedInit
668   dec a
669   cp  -2
670 __optionMenu: ;w/ zf
671   jr  z,_optionMenu ;<-1
672   jr  changedspeed
673 changespeedInit:
674   cal loadgamecar
675   ld  de,3
676   add hl,de
677   ld  a,(hl) ;(Speed)
678   inc hl ;=saves 2 bytes :P
679   ret
680
681 changeturn:
682   cal changespeedInit
683   inc hl ;(turnspeed)
684   ld  a,(hl)
685   inc a
686   cp  26
687   jr  nc,_optionMenu ;>25
688 changedturn:
689   ld  (hl),a
690   jr  _dispomenusets ;optionMenu
691 bchangeturn:
692   cal changespeedInit
693   inc hl
694   ld  a,(hl)
695   dec a
696   cp  3
697   jr  c,_optionMenu ;<3
698   jr  changedturn
699
700 changegrowth:
701   cal changespeedInit
702   ld  a,(hl)
703   inc a
704   cp  99
705   jr  nc,_optionMenu ;>98
706 changedgrowth:
707   ld  (hl),a
708   jr  _dispomenusets ;optionMenu
709 bchangegrowth:
710   cal changespeedInit
711   ld  a,(hl)
712   dec a
713   cp  -2
714   jr  z,__optionMenu ;<-1
715   jr  changedgrowth
716
717 ;---
718
719 mainMenu:
720   cal menupos
721   cal menucall
722   jr  nz,notselect
723 select:   ;2nd/enter
724   cal menupos
725   ld  a,b
726   dec a ;2nd item: level
727   jp  z,dispoptionmenu
728   sub 3 ;5th item: wormname
729   jp  z,changeworms
730   dec a ;6th: controls
731   jp  z,changekeys
732   jp  LetsGetThisPartyOn ;otherwise
733 notselect
734   cp  K_EXIT
735   jp  z,ExitNoStats
736   psh af
737   cal menupos
738   cal loadgamecar
739   inc hl
740   pop af
741   cp  K_LEFT
742   jr  z,selleft
743   cp  K_RIGHT
744   ld  a,b
745   jr  nz,mainMenu
746
747 selright:
748   or  a
749   jr  z,changegame
750   dec a
751   jr  z,changelevel
752   dec a
753   jr  z,changelink
754   dec a
755   jr  z,changenrworms
756 ; dec a
757 ; jr  z,changecurworm
758
759 changecurworm:
760 ; hl=nrworms
761   ld  a,(curworm)
762   cp  (hl)
763   jr  nc,mainMenu ;may not become >(nrworms)
764   inc a
765 changedcurworm:
766   ld  (curworm),a
767   jr  _dispmenusets ;mainMenu
768
769 selleft:
770   ld  a,b
771   or  a
772   jr  z,bchangegame
773   dec a
774   jr  z,bchangelevel
775   dec a
776   jr  z,bchangelink
777   dec a
778   jr  z,bchangenrworms
779 ; dec a
780 ; jr  z,bchangecurworm
781
782 bchangecurworm:
783   ld  a,(curworm)
784   dec a ;0-3
785   jr  nz,changedcurworm ;save >0
786   jr  mainMenu
787
788 changenrworms:
789   cal change4spOnly
790   ld  a,(hl) ;hl=nrworms
791   inc a
792   cp  5
793   jr  nc,mainMenu ;may not be >4
794 changednrworms:
795   ld  (hl),a
796 _dispmenusets:
797   jr  dispmenusets ;mainMenu
798 changenrwormsInit:
799   ld  a,(Gametype)
800   cp  3
801   ld  a,(hl) ;hl=nrworms
802   ret
803 bchangenrworms:
804   cal change4spOnly
805   ld  a,(hl) ;hl=nrworms
806   dec a ;0-3
807   cp  2
808   jr  nc,changednrworms ;save >=2
809 _mainMenu:
810   jr  mainMenu
811
812 change4spOnly:
813   ld  a,(Gametype)
814   cp  3
815   ret nc
816   pop hl ;cal
817   jr  _mainMenu ;don't change for singleplayer
818
819 changelink:
820 bchangelink:
821   cal change4spOnly
822   dec hl ;inced earlier
823   dec hl ;gameCar
824   ld  a,1 ;change LS-bit (=link)
825   xor (hl) ;0=1; 1=0
826   ld  (hl),a
827   jr  dispmenusets ;mainMenu
828
829 changegame:
830   ld  a,0
831 Gametype =$-1
832   inc a
833 changedgame:
834   and 7 ;mod 8
835   ld  (Gametype),a
836   jr  dispmenusets ;mainMenu
837 bchangegame:
838   ld  a,(Gametype)
839   dec a
840   jr  changedgame
841
842 changelevel:
843   inc hl ;hl=loadgamecar+2
844   psh hl
845   ld  a,(hl) ;(curlevel)
846   ld  hl,Gametype
847   ld  d,0
848   ld  e,(hl)
849   ld  hl,nrlevels
850   add hl,de
851   cp  (hl) ;max level for sel.game
852   pop hl
853   jr  z,_mainMenu
854   inc a
855 changedlevel:
856   ld  (hl),a
857   jr  dispmenusets ;mainMenu
858 bchangelevel:
859   inc hl
860   ld  a,(hl) ;(curlevel)
861   dec a
862   jr  nz,changedlevel
863   jr  _mainMenu
864
865 getcustomkey:
866   cal _vputs
867   dec ix
868 waitcustomkey:
869   halt \ halt
870   psh hl
871   cal GET_KEY
872   pop hl
873   or  a
874   jr  z,waitcustomkey
875   cp  K_EXIT
876   ret z
877   cp  K_MORE
878   jr  z,waitcustomkey
879   ld  (ix),a
880   ret
881
882 changekeys:
883   cal getwormname
884   ld  hl,txtKeyleft
885   cal getcustomkey ;left
886   cal getcustomkey ;right
887 ; jr  dispmenusets
888
889 ;---display current settings---
890
891 dispmenusets:
892   cal clrold
893   ld  de,$183E
894   ld  (_penCol),de
895   ld  d,0
896   ld  a,(Gametype)
897   ld  e,a
898   ld  hl,posGame
899   add hl,de ;hl=posGame+(Gametype)
900   ld  a,(hl) ;str.offset
901   ld  e,a ;^d=0^
902   ld  hl,txtGame
903   add hl,de ;txtGameX
904   ld  (CURtxtGame),hl ;save for g/o
905   cal _vputs ;Singleplayer
906
907   ld  hl,$2A3E ;worms
908   ld  (_penCol),hl
909   cal loadgamecar
910   inc hl
911   psh hl
912   ld  a,(hl)
913   add a,'0'
914   cal _vputmap
915
916   ld  hl,$243E
917   ld  (_penCol),hl
918   rr  c ;(gameCar)
919   ld  hl,txtNo
920   jr  nc,displink
921   ld  hl,txtYes
922 displink:
923   cal _vputs
924
925   ld  hl,$1E3E ;level
926   ld  (_penCol),hl
927   pop hl ;loadgamecar; hl++
928   inc hl
929   ld  a,(hl) ;(curlevel)
930   cal cshowA
931
932   ld  hl,$3032
933   ld  (_penCol),hl
934   ld  a,1
935 curworm =$-1
936   add a,'0'
937   cal _vputmap
938   ld  hl,$303E
939   ld  (_penCol),hl
940   cal getwormname
941   ld  hl,worm1name-18
942   add hl,de
943   cal _vputs
944   ld  hl,$363E ;controls
945   ld  (_penCol),hl
946   ld  hl,txtMenuR
947   cal _vputs
948   jp  mainMenu
949
950 ;--- handle menukeys ---
951
952 menucall:
953   psh bc
954 menuwaitkey:
955   halt \ halt
956   cal GET_KEY
957   or  a
958   jr  z,menuwaitkey
959   pop bc ;GET_KEY destr. b
960   cp  K_UP
961   cal z,menuup
962   cp  K_DOWN
963   cal z,menudown
964   cp  K_ENTER
965   ret z
966   cp  K_SECOND
967   ret ;z=select
968
969 menupos: ;highlight #b
970   ld  c,b ;psh b
971   ld  a,b
972   add a,3
973   add a,a
974   add a,a
975   sub b
976   add a,a
977   add a,a
978   add a,a ;*24
979   ld  h,$FC/4
980   ld  l,a
981   add hl,hl
982   add hl,hl ;$FD20+item*96
983   ld  b,16*7
984 menuinvloop:
985   ld  a,(hl)
986   cpl
987   ld  (hl),a
988   inc hl
989   dnz menuinvloop
990   ld  b,c ;pop b
991   ret ;a=-1
992 menudown:
993   cal menupos
994   inc b
995   jr  menuupdown
996 menuup:
997   cal menupos
998   dec b
999 menuupdown:
1000   ld  a,b
1001   cp  6
1002   jr  nz,menunewchk
1003   xor a ;6=0
1004 menunewchk:
1005   inc b
1006   jr  nz,menunewok
1007   ld  a,5 ;-1=5
1008 menunewok:
1009   ld  b,a
1010   jr  menupos
1011
1012 ;--- change name ---
1013 ; of worm#(curworm)
1014
1015 getwormname: ;of (curworm)
1016   ld  a,(curworm)
1017   add a,a  ;2x
1018   ld  e,a
1019   add a,a  ;4x
1020   add a,a  ;8x
1021   add a,a ;16x
1022   add a,e ;18x
1023   ld  e,a
1024   ld  d,0 ;de=a
1025
1026   ld  ix,worm1name-18
1027   add ix,de
1028   ret
1029
1030 changeworms:
1031   cal _clrWindow
1032   ld  hl,txtEName
1033   cal _puts ;"Enter name player "
1034   ld  a,(curworm)
1035   add a,'0'
1036   cal _putc
1037
1038   cal getwormname
1039   ld  a,maxnamelength
1040   cal entername
1041   ld  (ix),0 ;end mark
1042   jp  DisplayMenu
1043
1044 entername:
1045   ld  h,1
1046   ld  l,h ;)
1047   ld  (_curRow),hl
1048   ld  (namelength),a
1049 enternameloop:
1050   ld  a,'_'
1051   cal _putc
1052   ld  hl,_curCol
1053   dec (hl)
1054 nokeypressed:
1055   halt
1056   cal GET_KEY
1057   or  a
1058   jr  z,nokeypressed
1059
1060   cp  K_DEL
1061   jr  nz,continue
1062 backspace:
1063   ld  hl,namelength
1064   ld  a,(hl)
1065   cp  maxnamelength
1066   jr  nc,nokeypressed
1067   inc (hl)
1068
1069   dec ix
1070   ld  a,' '
1071   ld  (ix),a
1072   cal _putc
1073   ld  hl,_curCol
1074   dec (hl)
1075   dec (hl)
1076   jr  enternameloop
1077 continue:
1078   cp  K_ENTER
1079   ret z
1080   cp  K_EXIT
1081   ret z
1082
1083   ld  hl,namelength
1084   dec (hl)
1085   ret z
1086
1087   ld  hl,chartable
1088   ld  e,a
1089   ld  d,0
1090   add hl,de
1091   ld  a,(hl)
1092   or  a
1093   jr  z,nokeypressed
1094
1095   ld  (ix),a
1096   cal _putc
1097   inc ix
1098   cal releasekeys
1099   jr  enternameloop
1100
1101
1102 chartable:
1103   .db 0,".<>!",0,0,0,0  ;down,L,R,up
1104   .db 0,"XTOJE0",0      ;enter..clear
1105   .db " WSNID9",0       ;(-)..custom
1106   .db "ZVRMHC8",0       ;dot..del
1107   .db "YUQLGB7#"        ;0..xvar
1108   .db $D9,"-PKFA6'"     ;on..alpha
1109   .db "54321*",0,$D0    ;F5..more
1110
1111 ;--proc
1112
1113 clrold:
1114   ld  hl,$FD97 ;begin pos
1115   ld  de,7 ;bytes to add
1116   ld  a,35 ;nr of lines
1117 clroldsettings:
1118   ld  c,9 ;bytes to clear
1119 clroldsetsloop:
1120   ld  (hl),d ;=0
1121   inc hl
1122   dec c
1123   jr  nz,clroldsetsloop
1124   add hl,de
1125   dec a
1126   jr  nz,clroldsettings
1127   ret
1128
1129 skiplevel: ;@hl - destr:ab - alter:hl
1130   inc hl
1131   inc hl
1132   inc hl
1133   inc hl ;skip 4
1134   ld  b,(hl) ;spritesize
1135   inc b
1136 skipsprite:
1137   inc hl
1138   dnz skipsprite
1139   ld  b,(hl) ;balls
1140   inc b
1141   inc b ;skip 6
1142   ld  a,c
1143   cp  _datasingle
1144   jr  z,skipworms
1145   inc b ;multiplayer lvl
1146   inc b
1147   inc b ;skip other 3 worms (9 bytes)
1148 skipworms:
1149   ld  a,b
1150   add a,a
1151   add a,b
1152   ld  b,a ;3x(balls+2)
1153 skipballs:
1154   inc hl
1155   dnz skipballs
1156
1157 skipflags:
1158   ld  a,(Gametype)
1159   cp  gamectf
1160   jr  nz,noflagstoskip
1161   inc hl
1162   inc hl
1163   inc hl
1164   inc hl
1165 noflagstoskip:
1166
1167 skipobjects:
1168   ld  a,(hl)
1169   inc hl
1170   or  a
1171   ret z ;0=end
1172   inc hl
1173   inc hl
1174   inc hl
1175   inc hl
1176   jr  skipobjects
1177
1178 loadgamecar:
1179 ;in:    (Gametype)
1180 ;out:   hl=dataTYPE
1181 ;build: c=(gameCar)=(hl-1)
1182 ;       a=(wormbeglives)=(hl)
1183 ;destr: acdehl
1184   ld  hl,datasingle
1185   ld  a,(Gametype)
1186   add a,a
1187   add a,a
1188   add a,a ;8 bytes per mode
1189   ld  e,a
1190   ld  d,0
1191   add hl,de
1192   ld  a,(hl)
1193   ld  (gameCar),a
1194   ld  c,a
1195   inc hl
1196   ld  a,(hl)
1197   ld  (wormbeglives),a
1198   ret
1199
1200 ;-----------------------------
1201 ;-------- start game ---------
1202 ;-----------------------------
1203
1204 LetsGetThisPartyOn:
1205   ld  a,$17 ;no exit
1206   ld  (CheckExit),a ;set exit state
1207
1208   cal loadgamecar
1209   psh hl
1210   ld  (wormbeglives),a
1211   inc hl ;nrworms
1212   ld  a,(hl)
1213   ld  (nrworms),a
1214   inc hl ;level
1215   inc hl
1216   ld  a,(hl)
1217   ld  (customspeed),a
1218   inc hl
1219   ld  a,(hl)
1220   ld  (growspeed),a
1221   inc hl
1222   ld  a,(hl)
1223   ld  (turnleft),a
1224   ld  (turnright),a ;more efficient
1225   inc hl
1226   ld  l,(hl)
1227   ld  h,0
1228   cal _HLTIMES10        ;hl=10*(hl)
1229   ld  (scorelimit),hl
1230
1231   pop hl ;loadgamecar
1232   psh hl
1233   ld  a,(Gametype) ;8bytes -> 7bytes
1234   ld  e,a
1235   add a,a ;nc
1236   add a,e
1237   add a,a ;8->2bytes
1238   add a,24+1 ;go to datalevels
1239   ld  e,a ;=de
1240   sbc hl,de ;datalevels
1241
1242   cal _ldHLind ;ld hl,(hl)
1243   pop de ;de=loadgamecar
1244   inc de \ inc de
1245   ld  a,(de) ;(curlevel)
1246   ld  (Level),a
1247   ld  d,a ;begin level
1248 skiplevelloop:
1249   dec d ;levels to skip
1250   jr  z,levelsskipped
1251   cal skiplevel
1252   jr  skiplevelloop
1253 levelsskipped:
1254
1255   psh hl  ;1st level
1256   ld  a,(gameCar)
1257   rra ;and _datalink
1258   jr  nc,GameOver
1259
1260 linkmatch:
1261   cal _clrWindow
1262   ld  c,wormVhost
1263   cal Qsend
1264   ld  hl,txtWaiting
1265   cal _puts
1266   cal Crecv
1267   ld  a,c
1268   cp  wormVclient
1269   jr  z,client
1270   cp  wormVhost
1271   jr  z,host
1272   pop hl ;error
1273   jp  DisplayMenu ;return to menu
1274
1275 host:
1276   ld  c,wormVclient
1277   cal Qsend
1278   ld  a,$18
1279   jr  multiplayer
1280 client:
1281   ld  hl,txtReceive
1282   cal _puts
1283   ld  a,$E6
1284 multiplayer:
1285 ;  cal linkok
1286 ;  ld a,D0LD1L
1287 ;  out (7),a
1288   ld  (SwapPos),a
1289   ld  a,2
1290   ld  (nrworms),a
1291
1292 ;-----------------------------
1293 ;--------- game over ---------
1294 ;-----------------------------
1295
1296 GameOver:
1297   cal _clrLCD
1298   ld  hl,worm1set
1299   ld  de,worm1
1300   ld  a,4 ;4x (all worms)
1301 createwormsloop:
1302   ex  de,hl
1303   ld  bc,died
1304   add hl,bc
1305   ld  b,0
1306   ld  (hl),b ;died=0
1307   inc hl
1308   ld  (hl),b ;score=0
1309   inc hl
1310   ld  (hl),b ;score+1=0
1311   inc hl
1312   ld  (hl),2 ;delay=2
1313   inc hl
1314   ld  (hl),3 ;lives=x
1315 wormbeglives =$-1
1316   inc hl
1317   ex  de,hl  ;de=wormX+head
1318   ld  bc,18
1319   ldir       ;copy 18 bytes
1320   dec a      ;loop
1321   jr  nz,createwormsloop
1322
1323   pop hl ;begin of current level
1324 StartLevel:
1325   ld  de,Left
1326   ld  a,(hl)
1327   inc a ;=255?
1328   jp  nz,nextlevel
1329
1330   psh hl
1331   ld  hl,Level
1332   dec (hl) ;curlevel-- (not beyond last lvl)
1333   cal releasekeys
1334   cal _clrWindow
1335   pop hl
1336 ;show end msg or smtn
1337   ld  bc,Exit
1338   psh bc   ;where to go afterwards
1339   inc hl   ;location of ending-code
1340   jp  (hl) ;go there ("call")
1341 nextlevel:
1342   ldi
1343   ld  a,0
1344 customspeed =$-1
1345   inc a ;$FF=def
1346   jr  z,defspeed
1347   dec a
1348   ld  (hl),a ;store new speed
1349 defspeed:
1350   ld  de,Speed
1351   ldi
1352   ld  de,peagrowth
1353   ldi
1354   ld  a,(hl)
1355   ld  (worm1+grow),a
1356   ld  (worm2+grow),a
1357   ld  (worm3+grow),a
1358   ld  (worm4+grow),a
1359   ld  (beginsize),a
1360   inc hl
1361
1362   ld  a,(hl)
1363   inc hl
1364   or  a
1365   jr  z,defaultsprite
1366   ld  d,h
1367   ld  e,l ;ld de,hl
1368   ld  c,a
1369   ld  b,0 ;bc=sprite size
1370   add hl,bc ;hl=behind sprite
1371   jr  setsprite
1372 defaultsprite:
1373   ld  a,defspritesz
1374 defsprsize =$-1
1375 defsprite  =$+1
1376   ld  de,defspriteimg
1377 setsprite: ;de=@sprite ;a=sprsize
1378   ld  (sprsize),a
1379   ld  (spritepos),de
1380
1381   ld  a,(hl)
1382   inc hl
1383   ld  (nrballs),a
1384   or  a
1385   jr  z,toobad_noballs
1386   ld  c,a
1387   add a,a
1388   add a,c
1389   ld  c,a
1390   ld  b,0
1391   ld  de,balls
1392   ldir
1393 toobad_noballs:
1394
1395   ex  de,hl
1396 #ifndef invincible
1397   ld  (thislevel),de
1398 #endif
1399
1400   ld  hl,worm1
1401   ld  a,(Gametype)
1402   cp  gamesingle
1403   ld  b,1
1404   jr  z,worminit
1405   ld  b,4
1406 worminit:
1407   psh bc ;>1
1408   ex  de,hl
1409   ldi        ;d
1410   ld  a,SinCosTable/256
1411   ld  (de),a
1412   inc de
1413   ldi        ;y
1414   ldi        ;x
1415   ex  de,hl
1416   xor a
1417   ld  (hl),a ;y2
1418   inc hl
1419   ld  (hl),a ;x2
1420
1421   ld  bc,(worm2-worm1)-5
1422   add hl,bc
1423   pop bc ;<0
1424   dnz worminit
1425
1426   inc a ;ld a,1
1427   ld  (turn10),a
1428   ld  a,2
1429   ld  (flashtime),a
1430
1431 ;-------- draw level ---------
1432
1433   ld  a,(de)
1434   inc de
1435   sub 128
1436   jr  nc,setfieldx
1437   xor a ;fieldx<128
1438 setfieldx:
1439   ld  (FieldWidth),a
1440   ld  a,(de)
1441   inc de
1442   ld  l,a
1443   sub 57
1444   jr  nc,setfieldy
1445   xor a ;fieldy<57
1446 setfieldy:
1447   ld  (FieldHeight),a
1448   psh de                        ; >> levelp
1449   ld  a,l ;pop
1450   sub 5
1451   ld  l,a
1452   ld  h,0
1453   add hl,hl
1454   add hl,hl
1455   add hl,hl
1456   add hl,hl
1457   add hl,hl ;32=scr.width
1458   ex  de,hl
1459
1460   ld  hl,ScrBuffer
1461   psh hl                        ; >> 1
1462   psh de                        ; >> 2
1463   ld  de,ScrBuffer+1
1464   ld  bc,63
1465   ld  (hl),%11111111
1466   ldir
1467   inc hl
1468   ld  (hl),%11000000
1469   inc hl
1470   ld  b,31
1471 ClearLine:
1472   ld  (hl),c
1473   inc hl
1474   dnz ClearLine
1475   psh hl                        ; >> 3
1476
1477   ld  a,(FieldWidth)
1478   add a,126
1479   psh af                        ; >> 4
1480   and %11111000
1481   rra
1482   rra
1483   rra
1484   ld  l,a
1485   ld  h,0
1486   add hl,de
1487   pop af                         ; << 3
1488   and %00000111
1489   ld  b,a
1490   ld  c,0
1491   ld  a,%11000000
1492   jr  z,NoVertShift
1493 VertShift:
1494   rra
1495   rr  c
1496   dnz VertShift
1497 NoVertShift:
1498   ld  (hl),a
1499   inc hl
1500   ld  (hl),c
1501
1502   ex  de,hl
1503   pop de                         ; << 2
1504   pop bc                         ; << 1
1505   ldir
1506   pop hl                         ; << 0k
1507   ld  c,64
1508   ldir
1509
1510
1511   pop hl                         ; << levelp
1512   ld  a,(Gametype)
1513   cp  gamectf
1514   jr  nz,noctf
1515   ld  de,peaspos
1516   ld  bc,4
1517   ldir
1518   psh hl
1519   cal DrawAllPeas
1520   pop hl
1521 noctf:
1522
1523   cal drawstuff
1524
1525 ;-----------------------------
1526
1527   psh hl                        ; >> levelp new
1528   cal forceshowstats
1529   ld  a,(gameCar)
1530   and _datafood
1531   jr  z,nofood
1532   cal NewPea
1533 nofood:
1534   ld  bc,(worm1+pos)
1535   cal DisplayField
1536
1537 #ifdef readymask
1538   ld  hl,$FC70
1539   ld  d,%10101010
1540   ld  c,56
1541 maskloop:
1542   ld  a,d
1543   xor %11111111
1544   ld  d,a
1545   ld  b,$10
1546 maskline:
1547   ld  a,(hl)
1548   or  d
1549   ld  (hl),a
1550   inc hl
1551   dnz maskline
1552   dec c
1553   jr  nz,maskloop
1554 #endif
1555
1556 #ifdef readytext
1557   ld  hl,$FDE0
1558   ld  de,$FDE1
1559   ld  (hl),%11111111
1560   ld  bc,$BF
1561   ldir
1562   ld  hl,4+(txtposReady*256)
1563   ld  (_curRow),hl
1564   set 3,(iy+5)
1565   ld  hl,txtReady
1566   cal _puts
1567   res 3,(iy+5)
1568 #endif
1569
1570   ld  a,0
1571 gameCar =$-1
1572   rra ;and _datalink
1573   jr  nc,initfinished ;no link
1574   xor a
1575 SwapPos: ;$18 xx -> $E6 xx
1576          ; jr xx -> and xx
1577   jr  sethost
1578 setclient:
1579   ld  (worm1+left),a ;worm 1...
1580   ld  (worm3+left),a ;and worm 3 via link
1581   cal Qrecv
1582   ld  a,c
1583   ld  (worm2+name+0),a
1584   cal Qrecv
1585   ld  a,c
1586   ld  (worm2+name+1),a
1587   cal Qrecv
1588   ld  a,c
1589   ld  (worm2+name+2),a
1590   cal Qrecv
1591   ld  a,c
1592   ld  (worm2+name+3),a
1593   cal Qrecv
1594   ld  a,c
1595   ld  (worm2+name+4),a
1596   jr  initfinished
1597 sethost:
1598   ld  (worm2+left),a ;worm 2+4..
1599   ld  (worm4+left),a ;..over link
1600   ld  c,'T'
1601   cal Qsend
1602   ld  c,'e'
1603   cal Qsend
1604   ld  c,'s'
1605   cal Qsend
1606   ld  c,'t'
1607   cal Qsend
1608   ld  c,0
1609   cal Qsend
1610 initfinished:
1611
1612   ld  b,startdelay
1613 ReadyDelay:
1614   halt
1615   dnz ReadyDelay
1616   cal releasekeys
1617
1618 ;-----------------------------
1619 ;----------- LOOP ------------
1620 ;-----------------------------
1621
1622 GameLoop:
1623   ld  bc,(worm1+pos) ;camera worm #1
1624   ld  a,(worm1+left)
1625   or  a ;if #1 not over link
1626   jr  nz,showfield
1627   ld  bc,(worm2+pos) ;otherwise view from #2
1628 showfield:
1629   cal DisplayField ;display piece of level
1630
1631   ld  a,1
1632 flashtime =$-1
1633   dec a
1634   jr  z,noflash
1635   ld  (flashtime),a
1636   ld  hl,$fc00+(16*7)
1637 screeninvertloop:
1638   ld  a,(hl)
1639   cpl
1640   ld  (hl),a
1641   inc hl
1642   xor a
1643   cp  h ;end at >$FFFF
1644   jr  nz,screeninvertloop
1645 noflash:
1646
1647   ld  a,0
1648 Speed =$-1
1649   or  a
1650   jr  z,NoDelay
1651 Delay:
1652   halt
1653   dec a
1654   jr  nz,Delay
1655 NoDelay:
1656
1657   ld  (handledworm),a ;reset
1658
1659   ld  hl,turn
1660   ld  a,(hl)
1661   inc a ;-1
1662   jr  z,nextturnok
1663   dec (hl)
1664   dec a ;0 (now <0)
1665   jr  nz,nextturnok
1666 growspeed =$+1
1667   ld  (hl),$FF
1668 nextturnok:
1669
1670   ld  a,(gameCar)
1671   and _datatime
1672   jr  z,nodispupdate
1673   ld  hl,turn10
1674   dec (hl)
1675   jr  nz,nodispupdate ;just once every 10 turns
1676   ld  (hl),10 ;reset counter
1677   cal forceshowstats ;update score
1678 nodispupdate:
1679
1680
1681   ld  a,0
1682 nrballs =$-1
1683   or  a
1684   cal nz,handlethoseneatlittleballs
1685
1686   ld  ix,worm1
1687   ld  a,1
1688 nrworms =$-1
1689   ld  b,a
1690 handleworms:
1691   psh bc
1692   cal HandleWorm
1693   ld  bc,worm2-worm1
1694   add ix,bc
1695   pop bc
1696   ld  hl,handledworm
1697   inc (hl) ;1..nrworms
1698   dnz handleworms
1699
1700 ;-----------------------------
1701 ;---------- keys -------------
1702 ;-----------------------------
1703
1704 HandleKeys:
1705   ld  a,%10111111
1706   out (1),a
1707   in  a,(1)
1708   rla ;MORE?
1709   jr  c,CheckExit
1710   ld  bc,$0103
1711   out (c),b
1712   halt ;pause/off
1713   ld  b,11
1714   out (c),b
1715
1716 CheckExit:
1717   rla  ;=$17 (c=EXIT-key)
1718       ;or$A7 (c=0)
1719   jp  c,GameLoop
1720   jr  Exit
1721
1722 WormDead:
1723 #ifdef invincible
1724   jp  stopworm
1725 #else
1726   ld  a,2
1727   ld  (flashtime),a
1728   ld  (ix+delay),respawndelay
1729
1730 thislevel =$+1
1731   ld  hl,0
1732   ld  de,0
1733 handledworm =$-2
1734   add hl,de
1735   add hl,de
1736   add hl,de
1737   ld  a,(hl)
1738   inc hl
1739   ld  (ix+heading),a
1740   ld  a,(hl)
1741   ld  (ix+pos),a ;y
1742   inc hl
1743   ld  a,(hl)
1744   ld  (ix+pos+1),a ;x
1745   xor a
1746   ld  (ix+pos2),a ;y2
1747   ld  (ix+pos2+1),a ;x2
1748
1749   inc (ix+died)
1750   dec (ix+lives)
1751   psh af
1752   ld  de,10
1753   cal DecScore
1754   pop af
1755   ret nz ;HandleWorm done
1756   ld  a,(wormbeglives)
1757   or  a ;0=no live limit
1758   ret z ;don't end game
1759   ld  a,(gameCar)
1760   and _datatime
1761   jr  z,anyworm ;quit at any worm's death
1762   ld  a,(nrworms) ;livematch: all worms must've died
1763   ld  b,a ;# of worms
1764   ld  hl,worm1+lives-(worm2-worm1)
1765   ld  de,worm2-worm1
1766   xor a ;check for 0 lives
1767 checklives:
1768   add hl,de ;next worm
1769   cp  (hl) ;lives==0?
1770   ret nz ;any >0: don't exit
1771   dnz checklives
1772 anyworm:
1773   ld  a,$A7 ;exit@end of turn
1774   ld  (CheckExit),a ;set exit state
1775   ret ;finish turn
1776 #endif
1777
1778 Exit:
1779   cal releasekeys
1780   ld  sp,0 ;pop all
1781 SpSave = $-2
1782   ld  a,D0LD1L
1783   out (7),a     ;both wires low = game over signal
1784   cal _clrWindow
1785   ld  hl,txtGO
1786   cal _puts
1787   ld  hl,$FC00
1788   ld  b,16*8
1789   cal menuinvloop ;invert
1790   inc h ;$FD80
1791   cal hr ;menuinvloop w/ b=16
1792   ld  hl,$FCE0
1793   cal hr
1794 ; ld  l,$74
1795 ; ld  b,8
1796 ; cal menuinvloop
1797   ld  hl,_curRow
1798   inc (hl)
1799   ld  hl,txtGame
1800 CURtxtGame =$-2
1801   cal _puts
1802   ld  a,$0D ;$0D02
1803   ld  (_curCol),a
1804   cal showLevel
1805
1806   ld  de,$1901
1807   ld  (_penCol),de
1808   ld  hl,txtName
1809   cal _vputs ;Name
1810   ld  a,$3D
1811   ld  (_penCol),a
1812   cal _vputs ;Died    Score
1813   ld  de,$0004
1814   ld  (_curRow),de
1815
1816 findwinner:
1817   ld  hl,(worm1+score)
1818   ld  (winnerscore),hl
1819   ld  b,3 ;(nrworms)-1
1820   ld  hl,worm2+score
1821 findwinnerloop:
1822   psh hl
1823   cal _ldHLind
1824   ld  de,(winnerscore)
1825   ld  a,h
1826   cp  d
1827   jr  c,nonewwinner ;h<d
1828   jr  nz,newwinner  ;h>d
1829   ld  a,e
1830   cp  l
1831   jr  nc,nonewwinner ;l<e
1832 newwinner:
1833   ld  (winnerscore),hl
1834 nonewwinner:
1835   pop hl
1836   ld  de,worm2-worm1
1837   add hl,de
1838   dnz findwinnerloop
1839
1840   ld  a,(nrworms)
1841   ld  b,a
1842   cpl ;high value (>$FB)
1843   ld  hl,worm1+died
1844 finddmwinner:
1845   cp  (hl)
1846   jr  c,nonewdmwinner
1847   ld  a,(hl) ;less deaths
1848 nonewdmwinner:
1849   ld  de,worm2-worm1
1850   add hl,de
1851   dnz finddmwinner
1852   ld  (dmwinner),a
1853
1854 ;---display worms---
1855
1856   ld  a,(nrworms)
1857   ld  b,a
1858   ld  hl,worm1+died
1859 displayWormStats:
1860   psh bc
1861
1862   psh hl
1863   ld  bc,left-died
1864   add hl,bc ;+left
1865   xor a
1866   cp  (hl)  ;input=0 = link
1867   jr  nz,NoLinkIndic
1868   ld  a,9
1869   ld  (_curCol),a
1870   ld  a,$DC ;-O
1871   cal _putc
1872   xor a
1873   ld  (_curCol),a
1874 NoLinkIndic:
1875   inc hl
1876   inc hl ;+name
1877   cal _puts
1878   pop hl
1879
1880   psh hl
1881   ld  a,13
1882   ld  (_curCol),a
1883   ld  a,(hl) ;worm+died
1884   cal showA
1885   pop hl
1886
1887   psh hl
1888   ld  a,10
1889   ld  (_curCol),a
1890   ld  a,(Gametype)
1891   cp  gamedeathm
1892   jr  nz,nodmwinner ;deathmatch?
1893   ld  a,0 ;winner's deaths
1894 dmwinner =$-1
1895   cp  (hl) ;equals this worm?
1896   jr  nz,notwinner
1897   jr  iswinner
1898 nodmwinner:
1899   jr  c,notwinner ;no singleplayer winners
1900   inc hl ;worm+score
1901   cal _ldHLind ;ld hl,(hl)
1902   ld  de,0
1903 winnerscore =$-2
1904   cal _cphlde ;==highest score..
1905   jr  nz,notwinner
1906 iswinner:
1907   ld  a,'*'
1908   cal _putc ;..then put *
1909 notwinner:
1910   ld  a,16
1911   ld  (_curCol),a
1912   pop hl
1913   psh hl
1914   inc hl ;worm+score
1915   cal _ldHLind
1916   cal showHL
1917   pop hl
1918
1919   ld  bc,worm2-worm1
1920   add hl,bc
1921   pop bc
1922   dnz displayWormStats
1923
1924   ld  a,(Gametype)
1925   or  a ;singleplayer (0) only
1926   jr  nz,hilevelcheckdone
1927 checkhilevel:
1928   ld  hl,nrlevels
1929   ld  a,(Level)
1930   cp  (hl)
1931   jr  c,hilevelcheckdone
1932   ld  (hl),a ;save local
1933   ld  c,a
1934   ld  a,0
1935 hilvlposa =$-1
1936   ld  hl,nrlevels
1937 hilvlposhl =$-2 ;save external
1938   cal _writeb_inc_ahl ;ld (ahl),c
1939 hilevelcheckdone:
1940
1941   ld  a,(gameCar)
1942   and _datasingl
1943   jr  z,hiscorecheckdone ;no SP
1944 checkhiscore:
1945   cal loadhiscoreposinahl
1946   cal _Get_Word_ahl ;de=old_hi
1947  psh de
1948  cal _RAM_PAGE_1 ;&&
1949  pop de
1950   ld  hl,(worm1+score)
1951
1952   ld  a,h           ;New
1953   cp  d             ;Old
1954   jr  c,NotNewHigh  ;New<Old
1955   jr  nz,newhigh    ;New>Old
1956
1957   ld  a,e           ;old
1958   cp  l             ;new
1959   jr  nc,NotNewHigh ;new<old
1960
1961 newhigh:            ;New>=Old
1962   ex  de,hl
1963   cal loadhiscoreposinahl
1964   cal _Set_Word_ahl ;de->(ahl)
1965  cal _RAM_PAGE_1
1966
1967 NotNewHigh: ;de=current hiscore
1968   ld  hl,$0807
1969   ld  (_curRow),hl
1970   ld  hl,txthiscore
1971   cal _puts
1972   ex  de,hl ;pop
1973   cal showHL
1974 hiscorecheckdone:
1975
1976 waitkey:
1977   halt
1978   halt
1979   cal GET_KEY
1980   cp  K_ENTER
1981   jp  z,DisplayMenu
1982   cp  K_SECOND
1983   jp  z,DisplayMenu
1984   cp  K_EXIT
1985   jr  nz,waitkey
1986
1987 ;x123456789012345678901
1988 ;>>>>>> GAME OVER <<<<<
1989 ;2Multiplayer
1990 ;3Level 01
1991 ;4           Died Score:
1992 ;5NameName     03 00070
1993 ;6Worm#02 @    05 00120
1994 ;7Worm#03      15 00030
1995 ;8Snaky   @    00 04820
1996
1997 ExitNoStats:
1998   cal linkok
1999   ld  hl,_asapvar
2000   rst 20h ;_ABS_MOV10TOOP1
2001   rst 10h ;_FINDSYM
2002   ld  hl,savestart-_asm_exec_ram+4
2003   xor a
2004   add hl,de
2005   adc a,b ;ahl=bde+4
2006   cal _SET_ABS_DEST_ADDR
2007
2008   xor a
2009   ld  hl,savestart
2010   cal _SET_ABS_SRC_ADDR
2011   ld  hl,saveend-savestart
2012   cal _SET_MM_NUM_BYTES
2013   cal _mm_ldir
2014
2015   cal releasekeys
2016   res 4,(iy+9)
2017   set 2,(iy+13)
2018   im  1 ;remove keyfix
2019   jp  _clrWindow
2020
2021 loadhiscoreposinahl:
2022   ld  h,0
2023   ld  a,(Gametype)
2024   cp  2
2025   ld  l,h ;hl=0 for peaworm and singleplayer
2026   jr  nz,hi_
2027   ld  a,(nrlevels+1)
2028   ld  l,a ;skip peaworm slots for tron mode
2029 hi_:
2030   or  a ;Singleplayer?
2031   ld  b,0 ;offset 0 for SP
2032   jr  z,hi__
2033   ld  a,(Level)
2034   ld  b,a ;levels to skip (including 1 for singleplayer)
2035 addlevelposition:
2036   inc hl ;add one word per level
2037   dnz addlevelposition
2038 hi__:
2039   add hl,hl ;one WORD per hiscore
2040   xor a ;ahl=0(+hl)
2041   ld  bc,defhiscrpos
2042 hiscrposhl =$-2
2043   add hl,bc
2044 hiscrposa =$+1
2045   adc a,0 ;ahl=saveloc
2046   ret
2047
2048 ;-----------------------------
2049 ;----------- worm ------------
2050 ;-----------------------------
2051
2052 respawncheck:
2053   cp  respawndelay-1
2054   jr  nz,unnamedlabel
2055   cal saverespawncounter
2056 removeworm:
2057   ld  h,(ix+tail+1)
2058   ld  l,(ix+tail)
2059   ld  d,(ix+head+1)
2060   ld  e,(ix+head)
2061   jr  DoesWormTailEqualsWormHead ;chk4 size=0
2062 removewormloop:
2063   ld  c,(hl)
2064   inc hl
2065   ld  b,(hl)
2066   inc hl
2067   cal resbit
2068   psh hl
2069   cal res4pixels
2070   pop hl
2071   inc (ix+grow)
2072 DoesWormTailEqualsWormHead:
2073   cal _cphlde
2074   jr  nz,removewormloop
2075
2076   ld  a,(gameCar)
2077   and _datasingl
2078   jr  nz,safewormsizedone
2079   ld  a,0
2080 beginsize =$-1
2081   ld  (ix+grow),a
2082 safewormsizedone:
2083
2084   ;de=ix+head
2085   ld  (ix+tail+1),d
2086   ld  (ix+tail),e ;head=tail/size=0
2087   ret
2088
2089 unnamedlabel:
2090   cp  1
2091   ld  h,a
2092   jr  nz,saverespawncounter
2093 respawndue:
2094   ld  l,a
2095   cal inputcall
2096   ld  a,h ;previous
2097   cp  l   ;changed?
2098   ret z
2099   ld  (ix+delay),a ;=0
2100   ret
2101 saverespawncounter:
2102   ld  (ix+delay),a
2103   jr  inputcall
2104
2105 chkkey: ;key=a
2106   dec a
2107   ld  b,a
2108   srl b
2109   srl b
2110   srl b ;b=a/8
2111   and 7 ;a=a\8
2112   ld  c,a ;push keybit
2113   ld  a,-1
2114   out (1),a
2115   inc b
2116   ld  a,%01111111 ;default
2117 bitmask:
2118   rlca ;rotate left
2119   dnz bitmask ;a/8 times
2120   out (1),a ;send bitmask
2121   in  a,(1) ;input keys
2122   ld  b,c ;pop keybit
2123   inc b
2124 keybit:
2125   rra
2126   dnz keybit ;check match (cf set)
2127   ret
2128
2129 inkeys: ;use jp not call!
2130   cal chkkey
2131   jr  nc,notright
2132   ld  a,l
2133   add a,8
2134 turnright =$-1
2135   ld  l,a
2136 notright:
2137   ld  a,(ix+right)
2138   cal chkkey
2139   ret nc
2140   ld  a,l
2141   sub 8
2142 turnleft =$-1
2143   ld  l,a
2144   ret
2145 inputcall:
2146   ld  a,(ix+left)
2147   or  a
2148   jr  z,inlink ;input by link
2149   cal inkeys ;input by keys
2150   ld  a,(gameCar)
2151   rra ;and _datalink
2152   ret nc ;no link
2153   ld  c,l ;send our keys
2154   jp  Qsend
2155 inlink:
2156   cal Qrecv ;Crecv
2157   ld  l,c
2158   ret
2159
2160 ;------- handle worm ---------
2161
2162 HandleWorm:
2163   xor a
2164   cp  (ix+lives)
2165   jr  nz,alive
2166   ld  a,(wormbeglives)
2167   or  a
2168   ret nz ;live limit
2169 alive:
2170   ld  a,(ix+delay)
2171   dec a
2172   jp  nz,respawncheck
2173
2174   xor a
2175   cp  0
2176 turn =$-1
2177   jr  nz,nogrow
2178   inc (ix+grow)
2179 nogrow:
2180
2181   ld  a,(gameCar)
2182   and _datatime
2183   jr  z,notimescore
2184   ld  de,1
2185   cal IncScore
2186 notimescore:
2187
2188   ld  l,(ix+heading)
2189   cal inputcall
2190 donediddelydone:
2191   ld  (ix+heading),l
2192   ld  h,(ix+heading+1)
2193
2194   ld  c,(ix+pos)
2195   ld  b,(ix+pos+1)
2196   ld  e,(ix+pos2)
2197   ld  d,(ix+pos2+1)
2198
2199   psh hl
2200   ld  hl,previouspos
2201   ld  (hl),c
2202   inc hl
2203   ld  (hl),b
2204   inc hl
2205   inc hl
2206   ld  (hl),e
2207   inc hl
2208   ld  (hl),d
2209   pop hl
2210
2211 ;-------- move worm ----------
2212
2213 Wormmove:
2214   psh bc                        ; >> pos
2215   ld  a,(hl)
2216   add a,a
2217   add a,d
2218   ld  d,a
2219   bit 7,(hl)
2220   jr  z,notnegX
2221   dec b
2222 notnegX:
2223   jr  nc,notmoveX
2224   inc b
2225 notmoveX:
2226   ld  a,l
2227   add a,$40
2228   ld  l,a
2229   ld  a,(hl)
2230   add a,a
2231   add a,e
2232   ld  e,a
2233   bit 7,(hl)
2234   jr  z,notnegY
2235   dec c
2236 notnegY:
2237   jr  nc,notmoveY
2238   inc c
2239 notmoveY: ;bc=newpos
2240   ld  (ix+pos2),e
2241   ld  (ix+pos2+1),d
2242   ld  (ix+pos),c
2243   ld  (ix+pos+1),b
2244
2245 ;-check-
2246   pop hl                         ; << pos (old)
2247   ld  a,h
2248   sub b
2249   and 1
2250   ld  h,a
2251   ld  a,l
2252   sub c
2253   and 1
2254   add a,h
2255   ld  d,4
2256   jr  z,GotFour
2257   xor 3
2258   ld  d,a
2259 GotFour:
2260   cal chk4pixels
2261   rl  d
2262   jp  nc,Drawworm
2263
2264 ;--------- worm hit ----------
2265
2266 Hitworm:
2267   ld  a,(gameCar)
2268   ld  h,a
2269   and _datadie
2270   cal z,checkhitotherworm
2271   ld  a,h
2272   and _datamultpeas ;&&bit
2273   jr  nz,multiple_peas
2274   ld  a,h
2275   and _datafood
2276   jp  z,WormDead ;no food
2277
2278   ld  hl,0
2279 PeaY =$-2
2280 PeaX =$-1
2281   cal chkpeahit
2282   jp  nc,WormDead
2283   cal DrawPea ;remove pea
2284   ld  a,(ix+grow)
2285   add a,15
2286 peagrowth =$-1
2287   ld  (ix+grow),a
2288   cal NewPea
2289   ld  hl,Left
2290   dec (hl)
2291   psh af
2292   ld  de,10
2293   cal IncScore
2294   pop af
2295   jp  nz,Drawworm ;continue
2296   ld  a,(gameCar)
2297   and _datafoodl
2298   jp  z,Drawworm
2299   ld  a,(Gametype)
2300   or  a
2301   jp  nz,Exit ;stack restored
2302
2303   ld  hl,Level
2304   ld  a,(hl)
2305   inc (hl)
2306   ld  l,a ;hl=Level
2307   ld  h,0
2308   add hl,hl
2309   add hl,hl
2310   cal _HLTIMES10
2311   ex  de,hl
2312   cal IncScore ;score+(40*level)
2313   cal removeworm
2314   pop hl                         ; << call
2315   pop hl                         ; << call
2316   pop hl                         ; << levelp new
2317   ld  (ix+delay),2
2318   jp  StartLevel
2319
2320 chkpeahit: ;hl=peapos
2321   ld  a,(sprsize)
2322   inc a
2323   ld  d,a
2324   ld  a,b
2325   sub h
2326   inc a
2327   cp  d ;=(sprsize)+1
2328   ret nc ;nc=no pea
2329   ld  a,c
2330   sub l
2331   inc a
2332   cp  d
2333   ret ;c=pea
2334
2335 flagcaptured:
2336   psh hl
2337   ld  de,30
2338   cal IncScore
2339   pop hl
2340 sillylabel:
2341   cal WormDead
2342 DrawAllPeas:
2343   ld  hl,(peaspos)
2344   cal DrawPea
2345   ld  hl,(peaspos+2)
2346   jp  DrawPea
2347
2348 multiple_peas:
2349   ld  hl,(peaspos) ;1st pea
2350   psh hl
2351   ld  a,(ix+reserv)
2352   ld  e,a ;push a
2353   and %01
2354   jr  nz,sel_ownpea
2355   ld  hl,(peaspos+2) ;2nd pea
2356 sel_ownpea:
2357   cal chkpeahit
2358   pop hl ;(peapos) 1st pea
2359   jp  c,WormDead ;stopworm ;own pea hit
2360
2361   ld  a,e ;peek a (that's x86 asm for pop\push ;)
2362   and %01
2363   jr  z,sel_otherpea
2364   ld  hl,(peaspos+2) ;2nd pea
2365 sel_otherpea:
2366   cal chkpeahit
2367   jp  c,hitflag
2368
2369 ;no peas hit
2370   ld  a,e
2371   cal flagtoken
2372   jp  z,WormDead
2373   ld  b,a ;%10
2374   srl b   ;%01
2375   add a,b ;%11
2376   ld  (ix+reserv),a
2377   cal DrawPea ;restore own flag
2378   jr  sillylabel ;inv both\die
2379
2380 hitflag: ;correct pea hit
2381   ld  a,e ;pop a
2382   xor %01 ;0=1;1=0
2383   ld  (ix+reserv),a
2384   cal flagtoken
2385   psh af ;safe z-flag
2386   cal DrawPea ;remove
2387   pop af
2388   jr  z,flagcaptured
2389   jr  stopworm
2390
2391 flagtoken:
2392   and %01 ;current
2393   add a,a ;<< for cp
2394   ld  b,a ;in b
2395   ld  a,e
2396   and %10 ;own
2397   cp  b   ;same?
2398   ret ;Z=yes: no flag taken
2399
2400 ;-----------------------------
2401
2402 nextotherwormbit:
2403   ld  a,c
2404   sub (hl)
2405   inc hl
2406   inc a
2407   cp  4
2408   jr  nc,nothit1 ;no
2409   ld  a,b
2410   sub (hl)
2411   inc a
2412   cp  4
2413   ret c ;nz ;yes
2414 nothit1:
2415   inc hl
2416   cal resbit
2417 ChkWorm:
2418   cal _cphlde
2419   jr  nz,nextotherwormbit
2420   ret ;z
2421
2422 checkhitlapline:
2423   ld  a,63
2424   sub b
2425   jr  z,nextlaphalf
2426   inc a
2427   ret nz
2428 nextlaphalf:
2429   ld  a,c
2430   and 32 ;y>=32?
2431   jr  nz,nolap
2432   cp  (ix+reserv)
2433   jr  z,nolap
2434   psh bc
2435   ld  de,20
2436   cal IncScore
2437   pop bc
2438   xor a
2439 nolap:
2440   ld  (ix+reserv),a
2441   ret
2442
2443 checkhitotherworm:
2444  .db  $dd,$7d ;ld a,lx
2445   cp  worm2&255
2446  psh ix
2447  jr nz,chkworm2 ; ret nz
2448   ld  ix,worm1
2449  jr chkworm
2450 chkworm2:
2451  ld ix,worm2
2452
2453 chkworm:
2454  ld h,(ix+tail+1)
2455  ld l,(ix+tail)
2456  ld e,(ix+head)
2457  ld d,(ix+head+1)
2458   cal ChkWorm
2459  pop ix
2460   ret z ;not hit
2461   pop bc ;call
2462 stopworm:
2463   ld  bc,0
2464 previouspos =$-2
2465   ld  de,0
2466   ld  (ix+pos),c
2467   ld  (ix+pos+1),b
2468   ld  (ix+pos2),e
2469   ld  (ix+pos2+1),d
2470   ret
2471
2472 ;-------- draw worm ----------
2473
2474 Drawworm:
2475   ld  c,(ix+pos)
2476   ld  b,(ix+pos+1)
2477
2478   ld  a,(Gametype)
2479   cp  gamerace
2480   cal z,checkhitlapline
2481
2482   cal set4pixels
2483   dec c
2484   ld  a,(growspeed)
2485   or  a ;0=tron
2486   ret z ;keep tail in "Tron"
2487
2488   ld  l,(ix+head)
2489   ld  h,(ix+head+1)
2490   ld  (hl),c
2491   inc hl
2492   ld  (hl),b
2493   inc hl
2494   cal resbit
2495   ld  (ix+head),l
2496   ld  (ix+head+1),h
2497
2498   ld  a,(ix+grow)
2499   dec a
2500   jr  z,removetail
2501   ld  (ix+grow),a
2502   ret
2503
2504 removetail:
2505   ld  l,(ix+tail)
2506   ld  h,(ix+tail+1)
2507   ld  c,(hl)
2508   inc hl
2509   ld  b,(hl)
2510   inc hl
2511   cal resbit
2512   ld  (ix+tail),l
2513   ld  (ix+tail+1),h
2514
2515 res4pixels:
2516   cal ResPixel
2517   inc b
2518   cal ResPixel
2519   inc c
2520   cal ResPixel
2521   dec b
2522 ResPixel:
2523   cal FindPixel
2524   cpl
2525   and (hl)
2526   ld  (hl),a
2527   ret
2528
2529 ;-----------------------------
2530 ;---------- ball -------------
2531 ;-----------------------------
2532
2533 handlethoseneatlittleballs:
2534   ld  hl,balls
2535   ld  b,a ;a=(nrballs)
2536 handleballs
2537   psh bc
2538   psh hl
2539   ld  c,(hl)
2540   inc hl
2541   ld  b,(hl)
2542   inc hl
2543   ld  d,(hl)
2544   cal handleball
2545   dec c
2546   pop hl
2547   ld  (hl),c
2548   inc hl
2549   ld  (hl),b
2550   inc hl
2551   ld  (hl),d
2552   inc hl
2553   pop bc
2554   dnz handleballs
2555   ret
2556
2557 handleball:
2558   cal res4pixels
2559   dec c
2560
2561 ballxmove:
2562   bit 0,d ;1=L; 0=R
2563   jr  z,ballright
2564 ballleft:
2565   dec b
2566   cal checkballhit
2567   jr  z,ballymove
2568   inc b ;undo
2569   res 0,d ;go right
2570   jr  ballymove
2571 ballright:
2572   inc b
2573   cal checkballhit
2574   jr  z,ballymove
2575   dec b ;back
2576   set 0,d ;>left
2577
2578 ballymove:
2579   bit 1,d ;1=up; 0=down
2580   jr  z,balldown
2581 ballup:
2582   dec c
2583   cal checkballhit
2584   jr  z,balldone
2585   inc c
2586   res 1,d ;go down
2587   jr  balldone
2588 balldown:
2589   inc c
2590   cal checkballhit
2591   jr  z,balldone
2592   dec c
2593   set 1,d ;up
2594 balldone:
2595
2596 set4pixels: ;@(b,c)
2597   cal SetPixel
2598   inc b
2599   cal SetPixel
2600   inc c
2601   cal SetPixel
2602   dec b
2603 SetPixel: ;at bc
2604   cal FindPixel
2605   or  (hl)
2606   ld  (hl),a
2607   ret
2608
2609 letsmovetheotherway:
2610   ld  a,1
2611   xor (hl)
2612   ld  (hl),a
2613   ret
2614
2615 checkballhit:
2616   psh de
2617   ld  d,0
2618   cal chk4pixels
2619   xor a
2620   cp  d
2621   pop de
2622   ret
2623
2624 ;-----------------------------
2625 ;----------- procs -----------
2626 ;-----------------------------
2627
2628 releasekeys:
2629   halt
2630   ld  a,%10000000    ;all key-masks
2631   out (1),a
2632   in  a,(1)
2633   inc a              ;cp %11111111 (no keys pressed)
2634   jr  nz,releasekeys ;keep waitin
2635   cal GET_KEY        ;clear buffer
2636   ret
2637
2638 resbit:
2639   ld  a,h
2640   and (ix+storepos)
2641   ld  h,a
2642   ret
2643
2644 randompos:
2645   ld  b,a
2646 Random: ;(2..b+2)
2647   ld  a,r
2648 Seed =$+1
2649   add a,0
2650   ld  (Seed),a
2651   and %01111110
2652   cp  b
2653   jr  nc,Random
2654   add a,2
2655   ret
2656
2657 NewPea:
2658   ld  a,(FieldWidth)
2659   add a,127-4
2660   cal randompos
2661   ld  h,a
2662   ld  a,(FieldHeight)
2663   add a,56-4
2664   cal randompos
2665   ld  l,a
2666   ld  (PeaY),hl
2667
2668 CheckPea:
2669   ld  c,l
2670   ld  a,(sprsize)
2671   ld  e,a
2672 chkloopy:
2673   ld  b,h
2674   ld  a,(sprsize)
2675   ld  d,a
2676 chkloopx:
2677   psh hl
2678   cal FindPixel
2679   and (hl)
2680   pop hl
2681   jr  nz,NewPea ;pixel found
2682   inc b
2683   dec d
2684   jr  nz,chkloopx
2685   inc c
2686   dec e
2687   jr  nz,chkloopy
2688 ;all ok; empty space
2689
2690 DrawPea: ;hl=(PeaY)
2691   ld  b,h
2692   ld  c,l
2693   ld  de,0
2694 spritepos =$-2
2695   jp  PutSprite ;||-ed
2696
2697 ;----------- score -----------
2698
2699 _divHLby1000:
2700   psh hl
2701   ld  b,3
2702 divideagain: ;3x
2703   cal _divHLby10
2704   dnz divideagain
2705   ld  a,l ;a=hl/1000
2706   pop hl
2707   ret
2708
2709 IncScore:
2710   ld  h,(ix+score+1)
2711   ld  l,(ix+score)
2712   cal _divHLby1000
2713   ld  c,a
2714   add hl,de
2715   cal _divHLby1000
2716   cp  c
2717   jr  z,scorecommon ;hl/1000 not increased
2718   inc (ix+lives)
2719   jr  scorecommon
2720 DecScore: ;&&&
2721   ld  h,(ix+score+1)
2722   ld  l,(ix+score)
2723   or  a
2724   sbc hl,de
2725   jr  c,showstats ;<0=0
2726 scorecommon:
2727   ld  (ix+score+1),h
2728   ld  (ix+score),l
2729   ld  de,0
2730 scorelimit =$-2
2731   ld  a,d
2732   or  e
2733   jr  z,showstats ;de=0=no limit
2734   cal _cphlde
2735   jp  nc,Exit
2736
2737 showstats:
2738   ld  a,(gameCar)
2739   and _datatime
2740   ret nz ;no disp for timematches
2741 forceshowstats:
2742   psh ix
2743   ld  h,0
2744   ld  l,h
2745   ld  (_penCol),hl
2746   ld  a,(nrworms)
2747   ld  b,a
2748   ld  ix,worm1
2749   ld  a,(gameCar)
2750   and _datasingl
2751   jr  nz,showstatsS
2752 showstatloop:
2753   psh bc
2754 #ifdef longnames
2755   ld  b,3
2756   psh ix
2757 shownameloop: ;1st 3 chars
2758   ld  a,(ix+name)
2759   or  a
2760   jr  z,nameshown
2761   cal __vputmap
2762   inc ix
2763   dnz shownameloop
2764 nameshown:
2765   ld  a,':'
2766   cal _vputmap
2767   pop ix
2768 #else
2769   ld  a,(ix+name)
2770   cal __vputmap
2771   ld  a,':'
2772   cal __vputmap
2773 #endif
2774   cal showstat
2775   ld  de,worm2-worm1
2776   add ix,de ;next
2777   ld  hl,_penCol
2778   ld  a,(hl)
2779   add a,4 ;div
2780   ld  (hl),a
2781   pop bc
2782   dnz showstatloop
2783   pop ix
2784   ret
2785
2786 showstat: ;(multiplayer)
2787   ld  a,(Gametype)
2788   cp  gamedeathm
2789   jr  z,showlives
2790 showscore:
2791   ld  h,(ix+score+1)
2792   ld  l,(ix+score)
2793   cal _D_HL_DECI
2794   jr  __vputs
2795 showlives:
2796   ld  a,(ix+lives)
2797   add a,'0'
2798 __vputmap:
2799   psh ix
2800   cal _vputmap
2801   pop ix
2802   ret
2803
2804 showstatsS: ;(singleplayer)
2805   ld  hl,txtLevel
2806   cal __vputs
2807   ld  a,0
2808 Level =$-1
2809   cp  10
2810   jr  c,tilllevel9
2811   ld  l,a
2812   ld  h,0
2813   cal _divHLby10
2814   psh af
2815   ld  a,l
2816   add a,'0'
2817   cal __vputmap
2818   pop af
2819 tilllevel9:
2820   add a,'0'
2821   cal __vputmap
2822
2823   ld  a,98
2824   ld  (_penCol),a
2825   cal showscore
2826   ld  a,123
2827   ld  (_penCol),a
2828   cal showlives
2829   ld  a,(gameCar)
2830   and _datafoodl
2831   pop ix
2832   ret z
2833 showleft:
2834   ld  a,31
2835   ld  (_penCol),a
2836   ld  a,0
2837 Left =$-1
2838   cal cshowA
2839
2840   ld  hl,txtLeft
2841 __vputs:
2842   psh ix
2843   cal _vputs
2844   pop ix
2845   ret
2846
2847 showLevel:
2848   ld  hl,txtLevel
2849   cal _puts
2850   ld  a,(Level)
2851 showA:
2852   ld  l,a
2853   ld  h,0
2854   cal _divHLby10
2855   psh af
2856   ld  a,l
2857   add a,'0'
2858   cal _putc
2859   pop af
2860   add a,'0'
2861   jp  _putc
2862
2863 cshowA:
2864   or  a
2865   jr  nz,cshowavalue
2866   ld  hl,txtNone
2867   jp  _vputs
2868 cshowavalue:
2869   ld  l,a
2870   ld  h,0
2871   cal _divHLby10
2872   psh af
2873   ld  a,l
2874   add a,'0'
2875   cal __vputmap
2876   pop af
2877   add a,'0'
2878   jp  __vputmap
2879
2880 showHL:
2881   cal _D_HL_DECI
2882   jp  _puts
2883
2884 _D_HL_DECI:
2885   ld  de,savestr+4
2886   ld  b,5
2887 ldhld:
2888   cal _divHLby10
2889   add a,'0'
2890   ld  (de),a
2891   dec de
2892   dnz ldhld
2893   ld  hl,savestr
2894   ret
2895 savestr:
2896   .db "00000",0
2897
2898 ;-----------------------------
2899
2900 DisplayField:
2901   ld  a,c
2902   sub 29
2903   jr  nc,NotMinYScroll
2904   xor a
2905 NotMinYScroll:
2906   cp  43
2907 FieldHeight =$-1
2908   jr  c,NotMaxYScroll
2909   ld  a,(FieldHeight)
2910 NotMaxYScroll:
2911   ld  l,a
2912   ld  h,0
2913   add hl,hl
2914   add hl,hl
2915   add hl,hl
2916   add hl,hl
2917   add hl,hl
2918   psh bc                        ; >> 1
2919   psh de                        ; >> 2
2920   ld  de,ScrBuffer
2921   add hl,de
2922   ld  a,b
2923   sub 64
2924   jr  nc,NotMinXScroll
2925   xor a
2926 NotMinXScroll:
2927   cp  128
2928 FieldWidth = $-1
2929   jr  c,NotMaxXScroll
2930   ld  a,(FieldWidth)
2931 NotMaxXScroll:
2932   psh af                        ; >> 3
2933   and %11111000
2934   rra
2935   rra
2936   rra
2937   ld  c,a
2938   ld  b,0
2939   ld  de,DispBuffer
2940   pop af                         ; << 2
2941   and %00000111
2942   psh af                        ; >> 3
2943   cp  6
2944   jr  c,CopyScreen
2945   inc c
2946 CopyScreen:
2947   add hl,bc
2948   ld  b,57
2949 CopyScreenLoop:
2950   psh bc                        ; >> 4
2951   ld  bc,16
2952   ldir
2953   ld  c,16
2954   add hl,bc
2955   pop bc                         ; << 3
2956   dnz CopyScreenLoop
2957   pop af                         ; << 2
2958   ld  c,$b7 ;or a
2959 Bit0:
2960   jr  nz,Bit1
2961   halt
2962   halt
2963   jr  AfterShiftDelay
2964 Bit1:
2965   dec a
2966   jr  nz,Bit2
2967   cal ShiftRight1
2968   jr  AfterShiftDelay
2969 Bit2:
2970   dec a
2971   jr  nz,Bit3
2972   ld  a,2
2973   cal ShiftRight
2974   jr  AfterShiftDelay
2975 Bit3:
2976   dec a
2977   jr  nz,Bit4
2978   cal Chunk
2979   cal ShiftLeft1
2980   jr  AfterShift
2981 Bit4:
2982   dec a
2983   jr  nz,Bit5
2984   cal Chunk
2985   jr  AfterShiftDelay
2986 Bit5:
2987   dec a
2988   jr  nz,Bit6
2989   cal Chunk
2990   cal ShiftRight1
2991   jr  AfterShift
2992 Bit6:
2993   dec a
2994   jr  nz,Bit7
2995   ld  a,2
2996   cal ShiftLeft
2997   jr  AfterShift
2998 Bit7:
2999   cal ShiftLeft
3000 AfterShiftDelay:
3001   halt
3002 AfterShift:
3003 #ifdef buffer
3004   ld  hl,DispBuffer
3005   ld  de,$fc00+$70
3006   ld  bc,1024-$70
3007   ldir
3008 #endif
3009   pop de                         ; << 1
3010   pop bc                         ; << 0k
3011   ret
3012
3013 ShiftRight1:
3014   ld  a,1
3015 ShiftRight:
3016   ld  (ShiftRightCounter),a
3017   ld  a,c
3018   ld  (ShiftRightChunk),a
3019   ld  c,16
3020   add hl,bc
3021   ld  b,57
3022 ShiftRightLoop:
3023   psh bc
3024   ld  bc,-32
3025   add hl,bc
3026   ex  de,hl
3027   ld  a,(de)
3028 ShiftRightChunk:
3029   or  a
3030   cal c,_SHLACC
3031   ld  c,0
3032 ShiftRightCounter = $-1
3033 ShiftRowsLeft:
3034   psh hl
3035   rla
3036   ld  b,16
3037 ShiftRowLeft:
3038   dec hl
3039   rl  (hl)
3040   dnz ShiftRowLeft
3041   pop hl
3042   dec c
3043   jr  nz,ShiftRowsLeft
3044   ld  bc,-16
3045   add hl,bc
3046   ex  de,hl
3047   pop bc
3048   dnz ShiftRightLoop
3049   ret
3050
3051 ShiftLeft1:
3052   ld  a,1
3053 ShiftLeft:
3054   ld  (ShiftLeftCounter),a
3055   ld  a,c
3056   ld  (ShiftLeftChunk),a
3057   rla
3058   jr  nc,ShiftLeftSameByte
3059   dec hl
3060 ShiftLeftSameByte:
3061   ex  de,hl
3062   ld  bc,-16
3063   add hl,bc
3064 NewSprite:
3065   ex  de,hl
3066   ld  b,57
3067 ShiftLeftLoop:
3068   psh bc                        ; >> 1
3069   ld  bc,-32
3070   add hl,bc
3071   ex  de,hl
3072   ld  a,(de)
3073 ShiftLeftChunk:
3074   or  a
3075   cal c,_SHRACC
3076   ld  c,0
3077 ShiftLeftCounter = $-1
3078 ShiftRowsRight:
3079   psh hl                        ; >> 2
3080   rra
3081   ld  b,16
3082 ShiftRowRight:
3083   rr  (hl)
3084   inc hl
3085   dnz ShiftRowRight
3086   pop hl                         ; << 1
3087   dec c
3088   jr  nz,ShiftRowsRight
3089   ld  bc,-16
3090   add hl,bc
3091   ex  de,hl
3092   pop bc                         ; << 0k
3093   dnz ShiftLeftLoop
3094   ret
3095
3096 Chunk:
3097   psh hl                        ; >> 1
3098   psh de                        ; >> 2
3099   ld  c,16
3100   add hl,bc
3101   ld  b,57
3102 ChunkScreen:
3103   psh bc                        ; >> 3
3104   ld  bc,-32
3105   add hl,bc
3106   ex  de,hl
3107   ld  a,(de)
3108   cal _SHRACC
3109   ld  b,16
3110 ChunkRow:
3111   dec hl
3112   rld
3113   dnz ChunkRow
3114   ex  de,hl
3115   pop bc                         ; << 2
3116   dnz ChunkScreen
3117   pop de                         ; << 1
3118   pop hl                         ; << 0k
3119   ld  c,$37 ;scf
3120   ret
3121
3122 ;----------- draw ------------
3123
3124 ;--- pixel ---
3125
3126 chk4pixels: ;&&
3127   cal CheckPixel
3128   inc b
3129   cal CheckPixel
3130   inc c
3131   cal CheckPixel
3132   dec b
3133   cal CheckPixel
3134   dec c
3135   ret
3136 CheckPixel: ;at bc in d
3137   cal FindPixel
3138   and (hl)
3139   ret z
3140   dec d
3141   ret
3142
3143 ;CLEM's FIND_PIXEL (131+? cycles; 28+4 bytes)
3144 ;(b,c) to hl:a; "destroyes" ahl
3145
3146 FindPixel: ;(b,c) to hl:a
3147   ld  h,0
3148   ld  l,c    ;hl=y
3149   add hl,hl
3150   add hl,hl
3151   ld  a,b    ;a=x
3152   rra
3153   add hl,hl
3154   rra
3155   add hl,hl
3156   add hl,hl  ;hl=32*y
3157   rra        ;a=x/8
3158   or  l
3159   ld  l,a
3160   ld  a,b
3161   and 7
3162   cpl
3163   rlca
3164   rlca
3165   rlca
3166   ld  (FP_Bit),a
3167   xor a
3168 FP_Bit =$+1
3169   set 0,a
3170
3171   psh de ;&&&
3172   ld  de,ScrBuffer
3173   add hl,de
3174   pop de
3175   ret
3176
3177 ;--- sprite ---
3178
3179 PutSprite:  ;||@(b,c)
3180   ;by SHIAR  only ix saved
3181   cal FindPixel
3182 putspr:
3183   ld  (beginbit),a
3184   ld  a,0
3185 sprsize =$-1
3186   ld  b,a ;rows
3187 sprloopy:
3188   psh bc ;rows
3189   psh hl
3190   ld  a,(de)
3191   ld  c,a
3192   inc de
3193   ld  a,(sprsize)
3194   ld  b,a ;width
3195 beginbit =$+1
3196   ld  a,1
3197 sprloopx:
3198   sla c ;draw?
3199   jr  nc,sprnodraw
3200   psh af
3201   xor (hl)
3202   ld  (hl),a
3203   pop af
3204 sprnodraw:
3205   rrca ;next bit
3206   jp  nc,nextbitok
3207   inc hl ;next byte
3208 nextbitok:
3209   dnz sprloopx
3210
3211   pop hl
3212   ld  bc,32 ;next line
3213   add hl,bc
3214   pop bc
3215   dnz sprloopy
3216   ret
3217
3218 ;--- objects ---
3219
3220 drawstuff:
3221   ld  a,(hl)
3222   inc hl
3223   or  a ;0 =
3224   ret z ;no more
3225
3226   ld  d,(hl)
3227   inc hl
3228   ld  e,(hl)
3229   inc hl
3230   ld  b,(hl)
3231   inc hl
3232   psh hl
3233   ld  l,(hl)
3234   ld  h,b
3235
3236   dec a ;1 = line
3237   cal z,drawline
3238   dec a ;2 = fatline
3239   cal z,drawfatline
3240   dec a ;3 = box
3241   cal z,drawbox
3242   dec a ;4 = circle
3243   cal z,drawcircle
3244   dec a ;5 = hline
3245 #ifdef hlines
3246   cal z,drawhline
3247 #else
3248   cal z,drawline
3249 #endif
3250
3251   pop hl
3252   inc hl
3253   jr  drawstuff
3254
3255 drawbox: ;(d,e)-(h,l)
3256   ld  b,l ;Delta-y
3257 #ifdef hlines
3258 boxloop:
3259   cal drawhline
3260   inc e
3261   dnz boxloop
3262   ret
3263 drawhline: ;(d,e)-(h,e)
3264   psh bc
3265   ld  b,d
3266   ld  c,e
3267   psh hl
3268   cal FindPixel
3269   ld  c,a ;starting mask
3270   ld  a,h
3271   sub b
3272   ld  b,a
3273   inc b ;1+x2-x1
3274 hlineloop:
3275   ld  a,(hl)
3276   or  c
3277   ld  (hl),a
3278   rrc c ;mask >>
3279   jr  nc,hlinenext
3280   inc hl ;next byte
3281 hlinenext:
3282   dnz hlineloop
3283   pop hl
3284   pop bc
3285   ret
3286 #else
3287   ld  l,e
3288 boxloop:
3289   cal drawline
3290   inc l
3291   inc e
3292   dnz boxloop
3293   ret
3294 #endif
3295
3296 drawfatline:
3297   cal drawline
3298   inc d
3299   inc h
3300   cal drawline
3301   inc e
3302   inc l
3303   cal drawline
3304   dec d
3305   dec h
3306   jp  drawline
3307
3308 ;LINE (d,e)-(h,l)
3309 ;destroyes a
3310
3311 drawline: ;(d,e)-(h,l)
3312   psh bc  ;destr: a
3313   psh hl
3314   psh de
3315   ld  a,d
3316   cp  h
3317   jr  c,lineOrdered
3318   ex  de,hl
3319 lineOrdered:
3320   ld  b,d
3321   ld  c,e
3322   psh hl
3323   psh bc
3324   cal FindPixel
3325   pop bc
3326   pop de
3327 connectedLine:
3328   psh hl
3329   ld  h,c
3330   ld  c,a
3331   ld  a,d
3332   sub b
3333   ld  b,a
3334   ld  a,e
3335   jr  nz,LineNotPoint
3336   cp  h
3337   jr  nz,LineNotPoint
3338   pop hl
3339   jr  DoneLine
3340 LineNotPoint:
3341   sub h
3342   ld  de,32
3343   jr  nc,LinePositiveY
3344   neg
3345   ld  de,-32
3346 LinePositiveY:
3347   cp  b
3348   jr  nc,SteepLine
3349   add a,a
3350   ld  (line2sm+1),a
3351   ld  h,a
3352   xor a
3353   sub b
3354   add a,a
3355   ld  (line1sm+1),a
3356   ld  a,h
3357   sub b
3358   pop hl
3359 LineLoopGentle:
3360   psh af
3361   ld  a,(hl)
3362   or  c
3363   ld  (hl),a
3364   rrc c
3365   jr  nc,$+3
3366   inc hl
3367   pop af
3368   jp  m,line2sm
3369 line1sm:
3370   add a,0
3371   add hl,de
3372 line2sm:
3373   add a,0
3374   dnz LineLoopGentle
3375 DoneLine:
3376   ld  a,(hl)
3377   or  c
3378   ld  (hl),a
3379   pop de
3380   pop hl
3381   pop bc
3382   ret
3383 SteepLine:
3384   ld  h,a
3385   neg
3386   add a,a
3387   ld  (line3sm+1),a
3388   ld  a,b
3389   add a,a
3390   ld  (line4sm+1),a
3391   sub h
3392   ld  b,h
3393   pop hl
3394 LineLoopSteep:
3395   psh af
3396   ld  a,(hl)
3397   or  c
3398   ld  (hl),a
3399   add hl,de
3400   pop af
3401   jp  m,line4sm
3402 line3sm:
3403   add a,0
3404   rrc c
3405   jr  nc,$+3
3406   inc hl
3407 line4sm:
3408   add a,0
3409   dnz LineLoopSteep
3410   jr  DoneLine
3411
3412 drawcircle: ;(d,e),h    ;de=x,y; h=z
3413   ld  c,h               ;c=yy=z
3414   ld  a,h
3415   neg
3416   ld  l,a               ;l=-z
3417   xor a
3418   ld  b,a               ;b=xx=0
3419   dec a                 ;-$00**
3420   ld  h,a               ;hl=zz=-z
3421 circloop:
3422   psh de                ;x,y
3423   ex  (sp),hl           ;push zz \ pop x,y
3424   cal circledraw        ;(x-xx,y+yy)-(x+xx,y+yy)
3425                         ;(x-xx,y-yy)-(x+xx,y-yy)
3426   cal circledraw        ;(x-yy,y+xx)-(x+yy,y+xx)
3427                         ;(x-yy,y-xx)-(x+yy,y-xx)
3428
3429   ex  (sp),hl           ;push x,y \ pop zz
3430   xor a
3431   ld  d,a               ;d=0
3432   dec a                 ;-256<h<0 = $FF**
3433   cp  h                 ;h<0?
3434   jr  z,circlenext      ;jump if zz<0
3435
3436   ld  a,c               ;yy
3437   dec a                 ;89<a<128
3438   add a,a               ;a=2yy-2 ;nc
3439   ld  e,a               ;de=a
3440   sbc hl,de             ;zz=zz-2yy+2
3441   dec c                 ;yy--
3442 circlenext:
3443   ld  a,b               ;xx
3444   inc a                 ;0<a<92
3445   add a,a               ;2xx+2
3446   inc a
3447   ld  e,a               ;de=a
3448   add hl,de             ;zz=zz+2xx+3
3449
3450   pop de                ;x,y
3451   ld  a,b
3452   cp  c
3453   ret nc                ;xx>=yy
3454   inc b                 ;xx++
3455   jr  circloop
3456
3457 circledraw:             ;destr:de
3458   psh hl
3459   ld  a,h               ;hl=x,y
3460   sub b                 ;bc=xx,yy
3461   ld  d,a               ;d=x-xx
3462   add hl,bc             ;h=x+xx; l=y+yy
3463   ld  e,l               ;e=y+yy
3464   cal drawline          ;(h-b,l+c)-(h+b,l+c)
3465   ld  a,l
3466   sub c                 ;a=y again
3467   sub c
3468   ld  l,a               ;l=y-yy
3469   ld  e,l               ;e=l=y-yy
3470   cal drawline          ;(h-b,l-c)-(h+b,l-c)
3471   ld  a,b               ;swap xx and yy
3472   ld  b,c
3473   ld  c,a               ;ex b,c
3474   pop hl
3475   ret
3476
3477
3478
3479
3480
3481
3482
3483
3484 ;-----------------------------
3485 ;----------- link ------------
3486 ;-----------------------------
3487
3488 linkok:
3489   ld  a,D0HD1H
3490   out (7),a     ;raise both wires = link ok
3491   ret
3492
3493 timeout = $8000
3494 lossout = 20
3495
3496 checklink:              ;load wires in A and check for timeout
3497   dec de                ;decrease timer
3498   ld  a,d
3499   or  e
3500   jr  nz,linkfine       ;ok if de>0
3501 ;de==0 = timeout
3502   cal linkok
3503   ld a,0                ;losses so far
3504 linklosses =$-1
3505   inc a                 ;and this is another one
3506   ld (linklosses),a
3507   pop de                ;return from link
3508   cp  lossout           ;quit if too many errors
3509   ret c                 ;otherwise just continue
3510 linkerr:
3511   jp  Exit
3512 linkfine:
3513   in  a,(7)
3514   and %11
3515   ret
3516
3517 ;--------------
3518 ;---- SEND ----
3519 ;--------------
3520
3521 Csend:
3522   ld  b,32
3523 csendwait:
3524   nop
3525   dnz csendwait
3526   cal Qsend
3527   jr  c,Csend
3528   ret
3529
3530 Qsend:          ;try to send 8 bits in C; CF=error --- destr:abcde
3531   nop \ nop
3532   in  a,(7)
3533   and %11               ;both wires low = exit signal
3534   jr  z,linkerr         ;error otherwise
3535   ld  b,8               ;bits to send
3536 sendloop:
3537   ld  de,timeout
3538   rl  c                 ;bit to send in cf
3539   ld  a,D0LD1H          ;0: lower white
3540   jr  nc,sendbit
3541   ld  a,D0HD1L          ;1: lower red
3542 sendbit:
3543   out (7),a             ;lower one (send bit)
3544 sendwaitack:
3545   cal checklink         ;other calc must lower other wire
3546   jr  nz,sendwaitack
3547   ld  a,D0HD1H          ;raise one, ok to raise other
3548   out (7),a
3549 sendfinish:
3550   cal checklink
3551   cp  %11               ;both raised (by other calc)
3552   jr  nz,sendfinish
3553 ; nop \ nop
3554   dnz sendloop          ;repeat for all bits
3555   xor a                 ;nc...
3556   ld (linklosses),a     ;reset number of losses
3557   ret                   ;=ok
3558
3559 ;--------------
3560 ;---- RECV ----
3561 ;--------------
3562
3563 Crecv:          ;--- receive 8 bits into A/C --- destr:abcdehl ---
3564   cal Qrecv
3565   ret nc                ;return if all went ok
3566   jr  Crecv             ;and try again
3567
3568 Qrecv:          ;--- receive 8 bits into A/C; CF=error --- destr:abcde ---
3569   in  a,(7)
3570   and %11
3571   jr  z,linkerr         ;both low = error, quit
3572   ld  b,8               ;bits to receive
3573 recvloop:
3574   ld  de,timeout
3575 recvwait:
3576   cal checklink
3577   cp  %11
3578   jr  z,recvwait        ;both high = nothing sent (yet)
3579   rra                   ;received bit in cf
3580   ld  a,D0LD1H
3581   jr  c,received        ;lower white wire as well
3582   ld  a,D0HD1L          ;lower red
3583 received:
3584   rl  c                 ;save bit in c
3585   out (7),a             ;both wires low
3586 recvwaitack:
3587   cal checklink
3588   jr  z,recvwaitack     ;same wire will be raised again by other calc
3589   ld  a,D0HD1H
3590   out (7),a             ;raise both
3591 recvfinish:
3592   dnz recvloop          ;repeat for all bits
3593   xor a                 ;nc=no error
3594   ld (linklosses),a     ;reset number of losses
3595   ret
3596
3597
3598 ;-----------------------------
3599 ;---------- levels -----------
3600 ;-----------------------------
3601
3602 LevelDef:
3603   .db 5,4,15,15,0,0     ;peas,speed,growth,begin_size,sprite,balls
3604   .db 0,2,63            ;start d, y, x
3605   .db 128,57            ;field width (128-255), height (57-255)
3606   .db 0                 ;no additional lines, boxes
3607   .db 255
3608    ret
3609
3610 LevelDefM:
3611   .db 8,4,15,15,0,0
3612   .db $40,30,2,$C0,30,125, $00,2,64,$80,54,64
3613   .db 128,57
3614   .db 0
3615
3616   .db 8,0,18,12,5
3617   .db %1110000,%10001000,%10001000,%10001000,%1110000,0
3618   .db $40,30,2,$C0,30,125, $00,2,64,$80,54,64
3619   .db 128,57
3620   .db 0
3621
3622   .db 8,5,18,12,0,0
3623   .db $40,30,2,$C0,30,125, $00,2,64,$80,54,64
3624   .db 128,57
3625  .db 4,40,26,20,0
3626  .db 4,90,40,11,0,0
3627
3628 LevelDefT: ;tron=no delay
3629   .db 8,4,18,12,5
3630   .db %1110000,%10001000,%10001000,%10001000,%1110000,0
3631   .db $40,30,64,$C0,30,64, $00,30,64,$80,30,64
3632   .db 128,57
3633   .db 0
3634
3635 LevelDefC: ;ctf
3636   .db 8,4,18,12,5
3637   .db %1110000,%10001000,%10001000,%10001000,%1110000,0
3638   .db $40,30,64,$C0,30,64, $00,30,64,$80,30,64
3639   .db 128,57
3640   .db 10,10,50,50
3641   .db 0
3642
3643 ;-----------------------------
3644 ;---------- data -------------
3645 ;-----------------------------
3646
3647 wdPicture = 16
3648 wtPicture:
3649 .db %00000000,%00000000,%00000111,%10000000,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000,%01110000,%00000000,%00000000,%00000000,%00000000,%00000000
3650 .db %00000000,%00000000,%00001111,%10000000,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000,%01111000,%00000000,%00000000,%00000110,%01111011,%00100000
3651 .db %00000000,%00000000,%00011100,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000,%00011100,%00001110,%00000000,%00001001,%00010011,%01000000
3652 .db %00000000,%00000000,%00011000,%00011111,%00000000,%01111111,%11000000,%00111100,%00011110,%01111000,%00001100,%00011111,%00000000,%10100111,%00110000,%10000000
3653 .db %00000000,%00000000,%00111000,%00111111,%10000000,%11111111,%11100000,%11111110,%00111111,%11111100,%00001100,%00111011,%00000000,%10100001,%00001001,%01100000
3654 .db %00000000,%00000000,%00110000,%01110001,%11000001,%11000000,%01110001,%11100110,%01110011,%11001110,%00001100,%00110001,%10000000,%01001110,%01110010,%01100000
3655 .db %00000000,%00000000,%00110000,%01100000,%11000001,%10000000,%00111001,%10000000,%01100111,%11100110,%00001110,%01110001,%10000000,%00000000,%00000000,%00000000
3656 .db %00000000,%00000000,%00110000,%01100000,%11000001,%10110000,%00011011,%10000000,%11101110,%01110111,%00001110,%01110001,%10000000,%00000000,%00000000,%00000000
3657 .db %00000000,%00000000,%00110000,%01110001,%11000001,%10110000,%00011011,%00000000,%11001100,%00110011,%00000111,%11100001,%10000000,%00000000,%00000000,%00000000
3658 .db %00000000,%00000000,%00110000,%00110001,%10000001,%10110000,%00011011,%00000000,%11001100,%00110011,%00000011,%11000011,%10000000,%00000000,%00000000,%00000000
3659 .db %00000000,%00000000,%00111000,%00111011,%10000011,%10110000,%00011011,%00000000,%11001110,%01110011,%00000000,%00000011,%00110101,%01001001,%10000000,%00000000
3660 .db %00000000,%00000000,%00011000,%00011111,%00000011,%00110000,%00011011,%00000000,%11000111,%11100011,%10000000,%00000011,%01000101,%00010101,%01000011,%01100011
3661 .db %00000000,%00000000,%00011100,%00001110,%00000111,%00111000,%00111011,%10000000,%11000011,%11000001,%10000000,%00000111,%01100101,%01010101,%01000101,%01010100
3662 .db %00000000,%00000000,%00001110,%00111111,%10001110,%00011100,%01110001,%10000000,%11100000,%00000001,%11100000,%00001110,%00110111,%01011101,%10010101,%01100101
3663 .db %00000000,%00000000,%00000111,%11111011,%11111100,%00001111,%11100001,%11000000,%01100000,%00000000,%11111111,%11111100,%00010101,%01010101,%01000101,%01010101
3664 .db %00000000,%00000000,%00000011,%11100000,%11111000,%00000111,%11000000,%11000000,%01100000,%00000000,%00111111,%11111000,%01100101,%01010101,%01000110,%01010011
3665
3666 txtMenu:  .db "Mode",0  ;1st menu item
3667           .db "Level",0 ;2nd
3668           .db "Link",0  ;...
3669           .db "Worms",0
3670           .db "worm #",0
3671           .db 0
3672 posMenu:  .dw $2418,$231E,$2824,$1F2A,$1730,$1936
3673 txtMenuR: .db "controls",0
3674 txtoMenu: .db "Back",0  ;1st menu item
3675           .db "Lives",0 ;2nd
3676           .db "Limit",0 ;...
3677           .db "Speed",0
3678           .db "Rotation",0
3679           .db "Growth",0
3680 posoMenu: .dw $2618,$251E,$2524,$222A,$1A30,$1C36
3681 txtGame:  .db "Singleplayer",0
3682 txtGame1: .db "Peaworm",0
3683 txtGame2: .db "Tron",0
3684 txtGame3: .db "Deathmatch",0
3685 txtGame4: .db "Foodmatch",0
3686 txtGame5: .db "Timematch",0
3687 txtGame6: .db "Race",0
3688 txtGame7: .db "CTF" ;,0
3689
3690 posGame:  .db 0,txtGame1-txtGame
3691           .db txtGame2-txtGame
3692           .db txtGame3-txtGame
3693           .db txtGame4-txtGame
3694           .db txtGame5-txtGame
3695           .db txtGame6-txtGame
3696           .db txtGame7-txtGame
3697
3698 txtNone:   .db "None",0
3699 txtDef:    .db "Default",0
3700 txtYes:    .db "Yes",0
3701 txtNo:     .db "No",0
3702 txtKeyleft: .db ":left",0
3703 txtKeyright:.db "/right",0
3704 txtLevsel:  .db $CF," Select levels ",5,0
3705 txtEName:   .db "Enter name player ",0
3706 txtWaiting: .db "Waiting...",0
3707 txtReceive: .db "Receiving..." ;,0
3708
3709 TrigPrecalc:
3710 .db   0,  3,  6,  9, 12, 15, 18, 21
3711 .db  24, 27, 30, 33, 36, 39, 42, 45
3712 .db  48, 51, 54, 57, 59, 62, 65, 67
3713 .db  70, 73, 75, 78, 80, 82, 85, 87
3714 .db  89, 91, 94, 96, 98,100,102,103
3715 .db 105,107,108,110,112,113,114,116
3716 .db 117,118,119,120,121,122,123,123
3717 .db 124,125,125,126,126,126,126,126
3718 .db 127
3719
3720 txtLevel:  .db "Level ",0
3721 txtWorms:  .db "Worms: 0",0     ;follows txtLevel
3722 txtName:   .db "Name",0
3723 txtWinner: .db "Wins   "        ;follows txtName
3724 txtDied:   .db "Died    "       ;follows txtWinner
3725 txtScore:  .db "Score",0        ;follows txtDied
3726 txtLeft:   .db " left",0        ;follows txtScore
3727 txthiscore:.db "HiScore:",0
3728 txtReady:  .db "Prepare!",0
3729 txtposReady = 7
3730 txtGO:     .db 5,5,5,5,5," GAME OVER ",$CF,$CF,$CF,$CF,$CF,0
3731
3732 datalevels: .dw LevelDef, LevelDefM
3733             .dw LevelDefT,LevelDefM
3734             .dw LevelDefM,LevelDefM
3735             .dw LevelDefM,LevelDefC
3736 nrlevels:   .db 1,3,1,3,3,3,3,1     ;=defaults
3737
3738 _datalink       = %0000001 ;linkplay
3739 _datafoodl      = %0000010 ;left=0 limit
3740 _datasingl      = %0000100 ;singleplayer=1 (=hiscore+keep_length+nextlevel)
3741 _datamultpeas   = %0001000 ;multiple peas=1
3742 _datatime       = %0010000 ;time incs score (timematch)
3743 _datafood       = %0100000 ;food present
3744 _datadie        = %1000000 ;worm dies on impact
3745 ;reserved        %10000000 ;for future use
3746
3747 savestart:        ;     �game info (see above)
3748                   ;     | �lives (0=unlimited)
3749                   ;     | | �nrworms (can be altered by user)
3750                   ;     | | | �level (reset to 1 at startup)
3751                   ;     | | | |  �speed/delay (-1=def)
3752                   ;     | | | |  |  �grow speed (-1=none; 0=continuous)
3753                   ;     | | | |  |  |  �turn speed (8=def)
3754                   ;     | | | |  |  |  |  �score limit (0=none)
3755 gamesingle   =  0 ;used | | | |  |  |  |  |
3756 datasingle: .db  %1100110,3,1,1,-1,-1, 8, 0 ;Singleplayer (SP; 3 lives)
3757 gamepeas     =  1
3758 datapeas:   .db  %1100100,1,1,1,-1,-1, 8, 0 ;Peaworm (SP; 1 live)
3759 gametron     =  2
3760 datatron:   .db  %1010100,1,1,1,-1, 0, 8, 0 ;Tron (SP; 1 live, cont.growth)
3761 gamedeathm   =  3 ;used
3762 datadeathm: .db  %1000001,3,2,1,-1,49, 8, 0 ;Deathmatch (3 lives, 50 growth)
3763 gamefoodm    =  4
3764 datafoodm:  .db  %1100000,0,2,1,-1,-1, 8,10 ;Foodmatch (100 score)
3765 gametimem    =  5
3766 datatimem:  .db  %1010000,1,2,1,-1, 0, 8, 0 ;Timematch (tron, 100 score)
3767 gamerace     =  6 ;used
3768 datarace:   .db  %0000000,0,2,1,-1,-1, 8,10 ;Race (100 score, no collision)
3769 gamectf      =  7 ;used
3770 datactf:    .db  %1001000,0,4,1,-1,-1, 8, 9 ;CTF (90 score)
3771 _datasingle    = %1100110 ;(datasingle) usable like gamesingle
3772
3773 worm1set:  .dw worm1p,worm1p
3774            .db %11110111,%00,-01,K_RIGHT,K_LEFT
3775 worm1name: .db "Wormy   ",0
3776 worm2set:  .dw worm2p,worm2p
3777            .db %11111011,%11,-01,K_F2,K_F1
3778 worm2name: .db "Viper   ",0
3779 worm3set:  .dw worm3p,worm3p
3780            .db %11111011,%00,-01,K_COMMA,K_STO
3781 worm3name: .db "Nibbler ",0
3782 worm4set:  .dw worm4p,worm4p
3783            .db %11111011,%00,-01,K_PLUS,K_ENTER
3784 worm4name: .db "Jim     ",0
3785
3786 defhiscrpos:
3787   .dw 0,0,0,0,0,0
3788
3789 saveend:
3790
3791                ;set:
3792 heading  = 0   ;level*
3793 pos      = 2   ;level*
3794 pos2     = 4   ;level
3795 grow     = 6   ;level
3796 died     = 8   ;game
3797 score    = 9   ;game
3798 delay    = 11  ;game
3799                ;19B @game
3800 lives    = 12
3801 head     = 13  ;4B (head=tail)
3802 tail     = 15  ;also@next level
3803 storepos = 17
3804 reserv   = 18  ;loop (race:lap|ctf:pea)
3805 input    = 19
3806 left     = 20
3807 right    = 21
3808 name     = 22
3809 wormsize = 31
3810
3811 startdelay    = 30
3812 respawndelay  = 30
3813 maxnamelength = 8+1
3814
3815 .db "WWW.SHIAR.ORG  WWW.SHIAR.ORG  "
3816 .db "WWW.SHIAR.ORG  WWW.SHIAR.ORG  "
3817 .db "WWW.SHIAR.ORG  WWW.SHIAR.ORG  "
3818 .db "WWW.SHIAR.ORG  WWW.SHIAR.ORG  "
3819 .db "WWW.SHIAR.ORG  WWW.SHIAR.ORG  "
3820 .db "WWW.SHIAR.ORG  WWW.SHIAR.ORG  "
3821 .db "WWW.SHIAR.ORG  WWW.SHIAR.ORG  "
3822 .db "WWW.SHIAR.ORG  WWW.SHIAR.ORG  "
3823 .db "WWW.SHIAR.ORG  WWW.SHIAR.ORG  "
3824 .db "   shiar0@hotmail.com",0
3825
3826 defspritesz = 4
3827 defspriteimg:   .db %01100000
3828                 .db %11110000
3829                 .db %11110000
3830                 .db %01100000
3831
3832 deflevels:
3833   .db "Internal Levels" ;,0
3834
3835   .db 0,deflevels/256,deflevels&255
3836 templevels:
3837
3838 ;-----------------------------
3839 ;----------- end -------------
3840 ;-----------------------------
3841
3842   .end
3843
3844 .end