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