wormy 0.93.1411
[wormy.git] / wormy.z80
index e76ab019faa03442085b7a3e463ad982207bd73d..3dbe7ee4306fe26af268bd5d50b4510d6f505b68 100644 (file)
--- a/wormy.z80
+++ b/wormy.z80
@@ -40,7 +40,8 @@
 ;-----------------------------
 
 #define buffer      ;use display buffer (otherwise write directly to screen)
-#define readymask   ;"grays" out the field before starting a level
+#define readymask   ;"greys" out the field before starting a level
+;#define hlines     ;horizontal-line routine for more speed drawing boxes
 
 ;#define readytext  ;displays "prepare" before level starts
 ;#define invincible ;worms cannot die =)
@@ -81,6 +82,7 @@ _load_ram_ahl      = $462F ;ahl->page+hl
 _writeb_inc_ahl    = $5567 ;ld (ahl),c
 _jforce            = $409C ;TI-OS stack restored
 _EXLP              = $4493 ;swap (hl),(de) b times
+_GETB_AHL         = $46C3 ;a=(ahl) \ hl=ahl
 
 ;-----------------------------
 ;------- data  storage -------
@@ -134,7 +136,7 @@ start:
   .dw WormIcon
 
 WormTxt:
-  .db "WORMY by SHIAR -- alpha 93%",0
+  .db "WORMY by SHIAR -- beta 93%",0
 WormIcon:
   .db 9,2
   .db %10010110,%01101111
@@ -187,7 +189,7 @@ Start:
 
   cal _RAM_PAGE_7
   ld  hl,$BFFF ;VAT start
-  ld  bc,templevels
+  ld  ix,templevels
 searchloop:
   ld  de,(_PTEMP_END+1) ;VAT end
   or  a ;nc
@@ -199,20 +201,17 @@ searchloop:
   cp  $0C ;string
   jr  z,stringfound
 searchnext:
- cal _RAM_PAGE_7
   pop hl
   dec hl ;5x
   dec hl
   dec hl
   dec hl
   dec hl
- psh bc
   ld  b,(hl) ;name size
   inc b
 skipname:
   dec hl
   dnz skipname
- pop bc
   jr  searchloop
 
 stringfound:
@@ -225,23 +224,23 @@ stringfound:
   ex  de,hl ;ld ahl,(hl)
   cal _AHL_PLUS_2_PG3 ;string id
   cal _Get_Word_ahl ;ld de,(ahl)
- cal _RAM_PAGE_1
- ld (bc),a
+  ld (ix),a
   ld  a,levelhead
   cp  e
-  jr  nz,searchnext ;not worm
+  jr  nz,_searchnext ;not worm
   ld  a,levelhead2
   cp  d
-  jr  nz,searchnext
-
- inc bc
- ld a,h
- ld (bc),a
- inc bc
- ld a,l
- ld (bc),a
- inc bc
- jr searchnext
+  jr  nz,_searchnext
+  inc ix ;save level's ahl
+  ld a,h
+  ld (ix),a
+  inc ix
+  ld a,l
+  ld (ix),a
+  inc ix
+_searchnext:
+  cal _RAM_PAGE_7
+  jr searchnext
 
 loadgametype:
   psh de
@@ -266,70 +265,115 @@ defaultlevels:
   ret
 
 searchcomplete:
-  cal _RAM_PAGE_1
   ld  a,255
-  ld  (bc),a ;end mark
+  ld  (ix),a ;end mark
+
+  cal _clrWindow
   ld  hl,templevels-3
-dispnextlevel:
-  cal _RAM_PAGE_1
   psh hl
-  cal _clrWindow
-  ld  a,2
-  ld  (_curRow),a
+  ld  hl,$0020
+  ld  (_penCol),hl
   ld  hl,txtLevsel
-  cal _puts ;"< Select levels: >"
-  ld  hl,$0004
-  ld  (_curRow),hl
+  cal _vputs ;"< Select levels: >"
+  ld  hl,$0601 ;x=1
+  ld  (_penCol),hl
   pop hl
+dispnextlevel:
   ld  a,(hl)
-  cp  255 ;&&
-  jr  nz,displevel
-  ld  hl,templevels-3
-  ld  a,(hl)
+  inc a ;cp 255
+  jr  z,_levselect
+  ld  a,(hl) ;ade=(hl)
 displevel:
   inc hl
   ld  d,(hl)
   inc hl
   ld  e,(hl)
-  inc hl  ;ade=(hl)
-  psh hl  ;HL
-  ld  c,a
-  ld  h,d
-  ld  l,e ;cde=ahl=(hl)
+  inc hl
+  psh hl
+  ex  de,hl ;ahl=ade=(hl)
   cal _load_ram_ahl ;hl=ahl
   ld  b,(hl) ;b=title size
-  psh bc
-  cal _putps ;destr=abchl
-  pop bc  ;cde=hl
-  pop hl  ;HL
+  cal _vputs
+  ld  hl,_penCol
+  ld  (hl),$01 ;x=1
+  inc hl
+  ld  a,(hl)
+  add a,6
+  ld  (hl),a ;y+6
+  ld  hl,availevels
+  inc (hl)
+  pop hl
+  jr  dispnextlevel
+
+levup:
+  cal menupos
+  dec b ;up
+  ld  a,b
+  cp  -4
+  jr  nz,levselected
+  inc b ;undo
+  jr  levselected
+levdown:
+  cal menupos
+  inc b ;down
+  ld  a,b
+  cp  -3
+availevels =$-1
+  jr  nz,levselected
+  dec b ;back up
+levselected:
+  jp  menupos
+
+_levselect:
+  ld  b,-3 ;level selected
+  cal menupos
 levselect:
-  halt
-  psh hl
-  psh de
+  halt \ halt
   psh bc
   cal GET_KEY
-  pop bc
-  pop de
-  pop hl
-  cp  K_RIGHT
-  jr  z,dispnextlevel
-  sub K_SECOND
+  pop bc ;GET_KEY destr. b
+  cp  K_UP
+  cal z,levup
+  dec a ;K_DOWN
+  cal z,levdown
+  cp  K_SECOND-1
   jr  z,loadlevel
-  dec a ;K_EXIT
+  cp  K_EXIT-1
   ret z
-  cp  K_ENTER-K_EXIT+256
+  cp  K_ENTER-1
   jr  nz,levselect
+; jr  z,loadlevel
 
 loadlevel:
-  ld  a,c
+  ld  a,b
+  add a,3 ;sellev+3 (#0==-3)
+  ld  e,a
+  add a,a ;*2
+  add a,e ;*3
+  ld  e,a
+  ld  d,0 ;de=sellev*3
+  ld  hl,templevels-3
+  add hl,de
+  ld  a,(hl) ;ade=(hl)
   or  a ;levelfile on page 0 (=internal)
   jr  z,levelloaded
 
-  ex  de,hl ;ahl=cde
-  inc b ;b=titlesize+1
+  inc hl
+  ld  d,(hl)
+  inc hl
+  ld  e,(hl)
+  ex  de,hl ;ahl=ade
 skiptitle:
-  cal _INC_PTR_AHL
-  dnz skiptitle
+  ld  b,a ;psh ahl
+  psh hl
+  cal _GETB_AHL ;ld a,(ahl)
+  pop hl
+  or  a
+  ld  a,b ;pop ahl
+  psh af
+  cal _INC_PTR_AHL ;ahl++
+  pop af ;cp 0
+  jr  nz,skiptitle ;goto #0-terminator
 
   cal _Get_Word_ahl
   ld  (leveldataSize),de
@@ -366,6 +410,16 @@ levelloaded:
   ld  a,r
   ld  (Seed),a
 
+  ld  hl,datasingle+3
+  ld  b,8
+setdeflevels:
+  ld  (hl),1 ;def=level#1
+  inc hl
+  inc hl
+  inc hl
+  inc hl
+  dnz setdeflevels
+
 ;-----------------------------
 ;----- build trig tables -----
 ;-----------------------------
@@ -398,11 +452,16 @@ NegativeSineWave:
 ;-----------------------------
 
 DisplayMenu: ;---draw menu---
+  cal linkok
   cal _clrWindow
   ld  de,$FC40 ;(0,4)
   ld  hl,wtPicture
   ld  bc,16*16
   ldir
+  ld  hl,$FC00+$160
+  cal hr
+  ld  hl,$FC00+$3E0
+  cal hr
 
   ld  hl,txtMenu
   ld  ix,posMenu
@@ -417,7 +476,15 @@ dispmenuloop:
   dnz dispmenuloop
 
   ld  b,0 ;b=menu#
-  jr  setgame ;> dispmenusets > mainMenu
+  jr  _dispmenusets ;mainMenu
+
+hr: ;draw horizontal line at hl
+  ld  b,16
+hrloop:
+  ld  (hl),-1
+  inc hl
+  dnz hrloop
+  ret
 
 ;--- menu loop ---
 
@@ -467,7 +534,7 @@ changecurworm:
   inc a
 changedcurworm:
   ld  (curworm),a
-  jp  dispmenusets ;mainMenu
+  jr  _dispmenusets ;mainMenu
 
 selleft:
   ld  a,b
@@ -499,6 +566,7 @@ changenrworms:
   jr  nc,mainMenu ;may not be >4
 changednrworms:
   ld  (hl),a
+_dispmenusets:
   jr  dispmenusets ;mainMenu
 bchangenrworms:
   ;hl=nrworms
@@ -515,9 +583,6 @@ Gametype =$-1
 changedgame:
   and 7 ;mod 8
   ld  (Gametype),a
-setgame:
-  ld  a,1
-  ld  (curlevel),a ;reset level#
   jr  dispmenusets ;mainMenu
 bchangegame:
   ld  a,(Gametype)
@@ -548,22 +613,24 @@ changelivesInit:
   jr  _mainMenu ;singleplayer (no limit)
 
 changelevel:
+  inc hl ;hl=loadgamecar+2
+  psh hl
+  ld  a,(hl) ;(curlevel)
   ld  hl,Gametype
   ld  d,0
   ld  e,(hl)
   ld  hl,nrlevels
   add hl,de
-  ld  d,(hl) ;max level for sel.game
-curlevel =$+1
-  ld  a,1
-  cp  d
+  cp  (hl) ;max level for sel.game
+  pop hl
   jr  z,_mainMenu
   inc a
 changedlevel:
-  ld  (curlevel),a
+  ld  (hl),a
   jr  dispmenusets ;mainMenu
 bchangelevel:
-  ld  a,(curlevel)
+  inc hl
+  ld  a,(hl) ;(curlevel)
   dec a
   jr  nz,changedlevel
   jr  _mainMenu
@@ -623,11 +690,6 @@ clroldsetsloop:
   ld  (CURtxtGame),hl ;save for g/o
   cal _vputs ;Singleplayer
 
-  ld  hl,$1E3E ;level
-  ld  (_penCol),hl
-  ld  a,(curlevel)
-  cal cshowA
-
   cal loadgamecar
   psh hl
   ld  hl,$243E
@@ -647,10 +709,18 @@ limitok:
   ld  (_penCol),hl
   pop hl ;cal loadgamecar
   inc hl
+  psh hl
   ld  a,(hl)
   add a,'0'
   cal _vputmap
 
+  ld  hl,$1E3E ;level
+  ld  (_penCol),hl
+  pop hl ;loadgamecar; hl++
+  inc hl
+  ld  a,(hl) ;(curlevel)
+  cal cshowA
+
   ld  hl,$3032
   ld  (_penCol),hl
   ld  a,1
@@ -889,9 +959,8 @@ loadgamecar:
 ;destr: acdehl
   ld  hl,datasingle
   ld  a,(Gametype)
-  ld  e,a
   add a,a
-  add a,e
+  add a,a
   ld  e,a
   ld  d,0
   add hl,de
@@ -922,7 +991,9 @@ LetsGetThisPartyOn:
   ld  (scorelimit),hl ;set limit
 
   cal loadgamecar ;nc
-  ld  a,(Gametype) ;3bytes -> 2bytes
+  psh hl
+  ld  a,(Gametype) ;4bytes -> 3bytes
+  add a,a ;3->2bytes
   add a,24+1 ;go to datalevels
   ld  e,a ;=de
   sbc hl,de ;datalevels
@@ -935,7 +1006,9 @@ LetsGetThisPartyOn:
 scorelimitset:
 
   cal _ldHLind ;ld hl,(hl)
-  ld  a,(curlevel)
+  pop de ;de=loadgamecar
+  inc de \ inc de
+  ld  a,(de) ;(curlevel)
   ld  (Level),a
   ld  d,a ;begin level
 skiplevelloop:
@@ -961,22 +1034,23 @@ linkmatch:
   cp  wormVclient
   jr  z,client
   cp  wormVhost
-  jr  nz,linkiniterror
+  jr  z,host
+  pop hl ;error
+  jp  DisplayMenu ;return to menu
+
 host:
   ld  c,wormVclient
   cal Qsend
   ld  a,$18
   jr  multiplayer
-
-linkiniterror:
-  pop hl
-  jp  DisplayMenu
-
 client:
   ld  hl,txtReceive
   cal _puts
   ld  a,$E6
 multiplayer:
+;  cal linkok
+  ld a,D0LD1L
+  out (7),a
   ld  (SwapPos),a
   ld  a,2
   ld  (nrworms),a
@@ -986,8 +1060,6 @@ multiplayer:
 ;-----------------------------
 
 GameOver:
-  ld  a,%11000000
-  out (7),a ;link normal
   cal _clrLCD
   ld  hl,worm1set
   ld  de,worm1
@@ -1021,6 +1093,8 @@ StartLevel:
   inc a ;=255?
   jp  nz,nextlevel
 
+  ld  hl,Level
+  dec (hl) ;curlevel-- (not beyond last lvl)
   psh hl
   cal releasekeys
   cal _clrWindow
@@ -1114,13 +1188,21 @@ worminit:
   ld  a,(de)
   inc de
   sub 128
+  jr  nc,setfieldx
+  xor a ;fieldx<128
+setfieldx:
   ld  (FieldWidth),a
   ld  a,(de)
   inc de
+  ld  l,a
   sub 57
+  jr  nc,setfieldy
+  xor a ;fieldy<57
+setfieldy:
   ld  (FieldHeight),a
-  add a,57-5
   psh de                        ; >> levelp
+  ld  a,l ;pop
+  sub 5
   ld  l,a
   ld  h,0
   add hl,hl
@@ -1245,15 +1327,41 @@ gameCar =$-1
   and _datalink
   jr  z,initfinished ;no link
   xor a
-  ld  (Speed),a ;max.speed
 SwapPos: ;$18 xx -> $E6 xx
          ; jr xx -> and xx
   jr  sethost
 setclient:
-  ld  (worm1+left),a ;worm 1 via link
+  ld  (worm1+left),a ;worm 1...
+  ld  (worm3+left),a ;and worm 3 via link
+  cal Crecv
+  ld  a,c
+  ld  (worm2+name+0),a
+  cal Crecv
+  ld  a,c
+  ld  (worm2+name+1),a
+  cal Crecv
+  ld  a,c
+  ld  (worm2+name+2),a
+  cal Crecv
+  ld  a,c
+  ld  (worm2+name+3),a
+  cal Crecv
+  ld  a,c
+  ld  (worm2+name+4),a
   jr  initfinished
 sethost:
-  ld  (worm2+left),a ;worm 2 via link
+  ld  (worm2+left),a ;worm 2+4..
+  ld  (worm4+left),a ;..over link
+  ld  c,'T'
+  cal Qsend
+  ld  c,'e'
+  cal Qsend
+  ld  c,'s'
+  cal Qsend
+  ld  c,'t'
+  cal Qsend
+  ld  c,0
+  cal Qsend
 initfinished:
 
   ld  b,startdelay
@@ -1296,6 +1404,12 @@ Delay:
   jr  nz,Delay
 NoDelay:
 
+  ld  hl,turn
+  dec (hl)
+  jr  nz,nextturnok
+  ld  (hl),3 ;2
+nextturnok:
+
   ld  (handledworm),a ;=0
 
   ld  a,0
@@ -1372,7 +1486,21 @@ handledworm =$-2
   ret nz ;HandleWorm done
   ld  a,(gameCar)
   and _datalivel
-  ret z
+  ret z ;don't end game
+  ld  a,(Gametype)
+  cp  gametron
+  jr  nz,anyworm ;if not Tron, quit at any worm's death
+  ld  a,(nrworms)
+  ld  b,a ;# of worms
+  ld  hl,worm1+lives-(worm2-worm1)
+  ld  de,worm2-worm1
+  xor a ;check for 0 lives
+checklives:
+  add hl,de ;next worm
+  cp  (hl) ;lives==0?
+  ret nz ;any >0: don't exit
+  dnz checklives
+anyworm:
   ld  a,$A7 ;exit@end of turn
   ld  (CheckExit),a ;set exit state
   ret ;finish turn
@@ -1381,8 +1509,8 @@ handledworm =$-2
 Exit:
   ld  sp,0 ;pop all
 SpSave = $-2
-  ld  a,D0HD1H
-  out (7),a
+  ld  a,D0LD1L
+  out (7),a    ;both wires low = game over signal
   cal _clrWindow
   ld  hl,txtGO
   cal _puts
@@ -1469,7 +1597,7 @@ checkhilevel:
   ld  a,(Level)
   cp  (hl)
   jr  c,hilevelcheckdone
-  ld  (hl),a    ;save local
+  ld  (hl),a ;save local
   ld  c,a
   ld  a,0
 hilvlposa =$-1
@@ -1537,6 +1665,7 @@ waitkey:
 ;8Snaky   @    00 04820
 
 ExitNoStats:
+  cal linkok
   ld  hl,_asapvar
   rst 20h ;_ABS_MOV10TOOP1
   rst 10h ;_FINDSYM
@@ -1648,10 +1777,6 @@ respawndue:
 saverespawncounter:
   ld  (ix+delay),a
   jr  inputcall
-;  ld  a,(ix+input)
-;  or  a
-;  jr  z,inlink
-;  ret
 
 chkkey: ;key=a
   dec a
@@ -1677,18 +1802,19 @@ keybit:
   dnz keybit ;check match (cf set)
   ret
 
+turnspeed = 8
 inkeys: ;use jp not call!
   cal chkkey
   jr  nc,notright
   ld  a,l
-  add a,8
+  add a,turnspeed
   ld  l,a
 notright:
   ld  a,(ix+right)
   cal chkkey
   ret nc
   ld  a,l
-  sub 8
+  sub turnspeed
   ld  l,a
   ret
 inputcall:
@@ -1700,25 +1826,35 @@ inputcall:
   and _datalink
   ret z ;no link
   ld  c,l ;send our keys
-  psh hl
-  cal Qsend ;Csend
-  pop hl
-  ret
+  jp  Qsend
 inlink:
-  psh hl
   cal Qrecv ;Crecv
-  pop hl
   ld  l,c
   ret
 
 ;------- handle worm ---------
 
 HandleWorm:
+  ld  a,(gameCar)
+  cpl
+  and _datalivel
+  add a,(ix+lives)
+  or  a
+  ret z ;dead
   ld  a,(ix+delay)
   dec a
   jp  nz,respawncheck
 
   ld  a,(Gametype)
+  cp  gamedeathm ;&&&sub
+  jr  nz,nogrow
+  ld a,1 ;xor a
+  cp  0 ;a=0
+turn =$-1
+  jr  nz,nogrow
+  inc (ix+grow)
+nogrow:
+
   cp  gametron
   jr  nz,notron
   ld  de,1
@@ -2760,7 +2896,13 @@ drawstuff:
   dec a ;3 = box
   cal z,drawbox
   dec a ;4 = circle
-  cal z,circle
+  cal z,drawcircle
+  dec a ;5 = hline
+#ifdef hlines
+  cal z,drawhline
+#else
+  cal z,drawline
+#endif
 
   pop hl
   inc hl
@@ -2768,6 +2910,36 @@ drawstuff:
 
 drawbox: ;(d,e)-(h,l)
   ld  b,l ;Delta-y
+#ifdef hlines
+boxloop:
+  cal drawhline
+  inc e
+  dnz boxloop
+  ret
+drawhline: ;(d,e)-(h,e)
+  psh bc
+  ld  b,d
+  ld  c,e
+  psh hl
+  cal FindPixel
+  ld  c,a ;starting mask
+  ld  a,h
+  sub b
+  ld  b,a
+  inc b ;1+x2-x1
+hlineloop:
+  ld  a,(hl)
+  or  c
+  ld  (hl),a
+  rrc c ;mask >>
+  jr  nc,hlinenext
+  inc hl ;next byte
+hlinenext:
+  dnz hlineloop
+  pop hl
+  pop bc
+  ret
+#else
   ld  l,e
 boxloop:
   cal drawline
@@ -2775,6 +2947,7 @@ boxloop:
   inc e
   dnz boxloop
   ret
+#endif
 
 drawfatline:
   cal drawline
@@ -2791,8 +2964,8 @@ drawfatline:
 ;LINE (d,e)-(h,l)
 ;destroyes a
 
-drawline:
-  psh bc
+drawline: ;(d,e)-(h,l)
+  psh bc  ;destr: a
   psh hl
   psh de
   ld  a,d
@@ -2892,10 +3065,7 @@ line4sm:
   dnz LineLoopSteep
   jr  DoneLine
 
-;CIRCLE (d,e),h
-;destroyes ?
-
-circle:                ;de=x,y; h=z
+drawcircle: ;(d,e),h   ;de=x,y; h=z
   ld  c,h              ;c=yy=z
   ld  a,h
   neg
@@ -2964,170 +3134,59 @@ circledraw:            ;destr:de
 
 
 
-;**** link routines ****
-;these are identical in concept to the routines used in ZTetris, ZPong, and probably
-;every other link game out there.  However, these are commented :)
-losses: .dw 0
-Csend:
-  cal Qsend
-  jr  c,Csend
-  ret
-Qsend:
-send:
-;inputs: c=byte to send, both wires must be high by default
-;outputs: b=8-number of bits sent, both wires high, goes to game over on certain conditions
-;destroys: af,bc,de
-       in a,(7)
-       and %00000011
-       jr z,killlink           ;if both lines low, get out of here (game over signal)
-       ld b,8                          ;sending 8 bits
-sendloop:
-       ld de,$8000                     ;error timer
-       rl c                            ;force high bit into carry
-       ld a,%11010100          ;lower the red wire by default (sending 0) ($d4)
-       jr nc,selected          ;if high bit was 0, use above value
-       ld a,%11101000          ;if 1, lower the white wire instead ($e8)
-selected:
-       out (7),a                       ;put it out the link port
-waitconfirm:
-       call linktimer
-       in a,(7)                        ;see what the wires are doing
-       and %00000011           ;check lower 2 bits
-       jr nz,waitconfirm       ;if both bits 0, data was received ok (both wires low)
-       ld a,%11000000
-       out (7),a                       ;give the ok to raise both wires (one will be done automatically) ($c0)
-waitconfirm2:
-       call linktimer
-       in a,(7)
-       and %00000011
-       cp 3
-       jr nz,waitconfirm2      ;wait for other calc to raise the other wire
-       djnz sendloop           ;continue sending
-       xor a                           ;reset c; ld a,0
-       ld (losses),a           ;reset number of losses
-       ret
-
-
-Crecv:
-  cal receive
-  jr  c,Crecv
-  ret
-Qrecv:
-receive:
-;inputs: both wires must be high by default
-;outputs: c=byte received, b=8-number of bits received, both wires high
-;      goes to game over on certain conditions
-;destroys: af,bc,de
-       in a,(7)
-       and %00000011
-       jr z,killlink           ;game over signal applies to receiving too
-       ld b,8                          ;receiving 8 bits
-receiveloop:
-       ld de,$8000                     ;error timer
-waitreceive:
-       call linktimer
-       in a,(7)
-       and %00000011
-       cp 3                            ;if bits 0 and 1 set, both wires are high
-       jr z,waitreceive        ;wait for one of the wires to go low
-       rra                                     ;check red wire status
-       rl c                            ;if set, red is high (thus white is low), so put the correct bit into c
-       rra                                     ;now check white wire (since the flags are destroyed)
-       ld a,%11010100          ;$d4
-       jr nc,selected2         ;if white is low, lower red and vice versa              
-       ld a,%11101000          ;$e8
-selected2:
-       out (7),a                       ;so now both wires are low
-waitreceive2:
-       call linktimer
-       in a,(7)
-       and %00000011
-       jr z,waitreceive2       ;wait for the wire we didn't lower to go high again (the other will remain low)
-       ld a,%11000000          ;$c0
-       out (7),a                       ;raise both wires since the other calc will have given the ok sign
-       djnz receiveloop        ;if not done, wait for next bit
-       xor a                           ;reset c
-       ld (losses),a           ;reset number of losses
-       ret
-
-linktimer:                             ;leave if we have to wait too long (and return an error)
-       dec de
-       ld a,d
-       or e                            ;see if de is 0
-       ret nz                          ;if not, keep going as usual
-                                               ;otherwise we have to deal with a link failure
-       ld a,%11000000          ;$c0
-       out (7),a                       ;reset link status (both high)
-       ld a,(losses)           ;see how many consecutive losses we have
-       inc a
-       ld (losses),a           ;add this loss to it
-       pop de                          ;fix the stack to leave the link routine (de is ok to destroy)
-       cp 20                           ;see if this is the 20th consecutive failure
-       ret c                           ;if not, keep playing
-                                               ;otherwise, all is probably lost...
-
-killlink2:
-       jr linkend
-killlink:
-linkend:
-  jp  z,Exit
-
-
-
-
-
-
-
-
-
-#ifdef 0
+
+
+
 ;-----------------------------
 ;----------- link ------------
 ;-----------------------------
 
-timeout = $800
+linkok:
+  ld  a,D0HD1H
+  out (7),a    ;raise both wires = link ok
+  ret
+
+timeout = $8000
+lossout = 20
 
-checklink:
-  dec de
+checklink:             ;load wires in A and check for timeout
+  dec de               ;decrease timer
   ld  a,d
   or  e
-  jr  z,linkerror
-
-  ld  a,$BF
-  out (1),a
-  in  a,(1)
-  bit 6,a
-  jp  z,Exit
-
+  jr  nz,linkfine      ;ok if de>0
+;de==0 = timeout
+  cal linkok
+  ld a,0               ;losses so far
+linklosses =$-1
+  inc a                ;and this is another one
+  ld (linklosses),a
+  pop de               ;return from link
+  cp  lossout          ;quit if too many errors
+  ret c                ;otherwise just continue
+linkerr:
+  jp  Exit
+linkfine:
   in  a,(7)
   and %11
   ret
 
-linkerror:
-  scf
-  ld  a,%11
-  pop hl
-  ret
-
 ;--------------
 ;---- SEND ----
 ;--------------
 
-Csend:         ;--- send 8 bits in A --- destr:abcdehl ---
-  ld  c,a
-Csendloop:
+Csend:
+  ld  b,32
+csendwait:
+  nop
+  dnz csendwait
   cal Qsend
-  ret nc               ;NC = all ok
-  ld  a,D0HD1H
-  out (7),a            ;both high
-  jr  Csendloop        ;CF = error
+  jr  c,Csend
+  ret
 
-Qsend:         ;--- try to send 8 bits in C; CF=error --- destr:abcdehl ---
-  ld  de,timeout
-  cal checklink
-  cp  %11              ;are they?
-  scf
-  ret nz               ;nope, wait
+Qsend:         ;try to send 8 bits in C; CF=error --- destr:abcde
+  in  a,(7)
+  and %11              ;both wires low = exit signal
+  jr  z,linkerr        ;error otherwise
   ld  b,8              ;bits to send
 sendloop:
   ld  de,timeout
@@ -3146,9 +3205,10 @@ sendfinish:
   cal checklink
   cp  %11              ;both raised (by other calc)
   jr  nz,sendfinish
-  nop \ nop
+; nop \ nop
   dnz sendloop         ;repeat for all bits
   xor a                        ;nc...
+  ld (linklosses),a    ;reset number of losses
   ret                  ;=ok
 
 ;--------------
@@ -3158,17 +3218,12 @@ sendfinish:
 Crecv:         ;--- receive 8 bits into A/C --- destr:abcdehl ---
   cal Qrecv
   ret nc               ;return if all went ok
-  ld  a,D0HD1H
-  out (7),a            ;raise both on error
   jr  Crecv            ;and try again
 
-Qrecv:         ;--- receive 8 bits into A/C; CF=error --- destr:abcdehl ---
-  ld  de,timeout
-  cal checklink
-  jp  z,Exit           ;both low = error, quit
-  cp  %11
-  scf
-  ret z                        ;both high = nothing yet, wait
+Qrecv:         ;--- receive 8 bits into A/C; CF=error --- destr:abcde ---
+  in  a,(7)
+  and %11
+  jr  z,linkerr        ;both low = error, quit
   ld  b,8              ;bits to receive
 recvloop:
   ld  de,timeout
@@ -3191,9 +3246,9 @@ recvwaitack:
 recvfinish:
   dnz recvloop         ;repeat for all bits
   xor a                        ;nc=no error
-  ld  a,c              ;result in a
+  ld (linklosses),a    ;reset number of losses
   ret
-#endif
+
 
 ;-----------------------------
 ;---------- levels -----------
@@ -3246,22 +3301,22 @@ LevelDefC: ;ctf
 
 wdPicture = 16
 wtPicture:
-.db %01001010,%00101001,%00000111,%10000000,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000,%01110000,%00000000,%00000000,%00000000,%01000000,%00000000
-.db %10001010,%10101000,%10001111,%10000000,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000,%01111000,%00000000,%00000000,%00000000,%10100100,%01000000
-.db %10101010,%10101010,%10011100,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000,%00011100,%00001110,%00000000,%00000000,%10101010,%10100000
-.db %01010001,%01000101,%00011000,%00011111,%00000000,%01111111,%11000000,%00111100,%00011110,%01111000,%00001100,%00011111,%00000000,%00000000,%11001001,%10100000
-.db %00000000,%00000000,%00111000,%00111111,%10000000,%11111111,%11100000,%11111110,%00111111,%11111100,%00001100,%00111011,%10000000,%00000011,%10001000,%00100000
-.db %01101010,%10010011,%00110000,%01110001,%11000001,%11000000,%01110001,%11100110,%01110011,%11001110,%00001100,%00110001,%10000000,%00000000,%10010000,%00100000
-.db %10001010,%00101010,%10110000,%01100000,%11000001,%10000000,%00111001,%10000000,%01100111,%11100110,%00001110,%01110001,%10000000,%00000000,%01100000,%01000000
-.db %11101110,%10111011,%00110000,%01100000,%11000001,%10110000,%00011011,%10000000,%11101110,%01110111,%00001110,%01110001,%10000011,%11100000,%00000011,%10000000
-.db %00101010,%10101010,%10110000,%01110001,%11000001,%10110000,%00011011,%00000000,%11001100,%00110011,%00000111,%11100001,%10001100,%00011000,%00010000,%00000000
-.db %11001010,%10101010,%10110000,%00110001,%10000001,%10110000,%00011011,%00000000,%11001100,%00110011,%00000011,%11000011,%10010000,%00000100,%00100011,%00001100
-.db %00000000,%00000000,%00111000,%00111011,%10000011,%10110000,%00011011,%00000000,%11001110,%01110011,%00000000,%00000011,%00010011,%00000100,%00100100,%10010010
-.db %00111001,%11000111,%00011000,%00011111,%00000011,%00110000,%00011011,%00000000,%11000111,%11100011,%10000000,%00000011,%00001100,%10000100,%00101000,%10010100
-.db %01100101,%00101000,%00011100,%00001110,%00000111,%00111000,%00111011,%10000000,%11000011,%11000001,%10000000,%00000111,%00000000,%01001110,%00101000,%10011000
-.db %01001101,%11001011,%00001110,%00111111,%10001110,%00011100,%01110001,%10000000,%11100000,%00000001,%11100000,%00001110,%00000000,%01010101,%00101000,%10011000
-.db %00111001,%01100111,%00000111,%11111011,%11111100,%00001111,%11100001,%11000000,%01100000,%00000000,%11111111,%11111100,%00000000,%10010101,%00100110,%00010100
-.db %00000000,%00000000,%00000011,%11100000,%11111000,%00000111,%11000000,%11000000,%01100000,%00000000,%00111111,%11111000,%11111111,%00001000,%11000001,%11100011
+.db %00000000,%00000000,%00000111,%10000000,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000,%01110000,%00000000,%00000000,%00000000,%00000000,%00000000
+.db %00000000,%00000000,%00001111,%10000000,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000,%01111000,%00000000,%00000000,%00000110,%01111011,%00100000
+.db %00000000,%00000000,%00011100,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000,%00011100,%00001110,%00000000,%00001001,%00010011,%01000000
+.db %00000000,%00000000,%00011000,%00011111,%00000000,%01111111,%11000000,%00111100,%00011110,%01111000,%00001100,%00011111,%00000000,%10100111,%00110000,%10000000
+.db %00000000,%00000000,%00111000,%00111111,%10000000,%11111111,%11100000,%11111110,%00111111,%11111100,%00001100,%00111011,%00000000,%10100001,%00001001,%01100000
+.db %00000000,%00000000,%00110000,%01110001,%11000001,%11000000,%01110001,%11100110,%01110011,%11001110,%00001100,%00110001,%10000000,%01001110,%01110010,%01100000
+.db %00000000,%00000000,%00110000,%01100000,%11000001,%10000000,%00111001,%10000000,%01100111,%11100110,%00001110,%01110001,%10000000,%00000000,%00000000,%00000000
+.db %00000000,%00000000,%00110000,%01100000,%11000001,%10110000,%00011011,%10000000,%11101110,%01110111,%00001110,%01110001,%10000000,%00000000,%00000000,%00000000
+.db %00000000,%00000000,%00110000,%01110001,%11000001,%10110000,%00011011,%00000000,%11001100,%00110011,%00000111,%11100001,%10000000,%00000000,%00000000,%00000000
+.db %00000000,%00000000,%00110000,%00110001,%10000001,%10110000,%00011011,%00000000,%11001100,%00110011,%00000011,%11000011,%10000000,%00000000,%00000000,%00000000
+.db %00000000,%00000000,%00111000,%00111011,%10000011,%10110000,%00011011,%00000000,%11001110,%01110011,%00000000,%00000011,%00110101,%01001001,%10000000,%00000000
+.db %00000000,%00000000,%00011000,%00011111,%00000011,%00110000,%00011011,%00000000,%11000111,%11100011,%10000000,%00000011,%01000101,%00010101,%01000011,%01100011
+.db %00000000,%00000000,%00011100,%00001110,%00000111,%00111000,%00111011,%10000000,%11000011,%11000001,%10000000,%00000111,%01100101,%01010101,%01000101,%01010100
+.db %00000000,%00000000,%00001110,%00111111,%10001110,%00011100,%01110001,%10000000,%11100000,%00000001,%11100000,%00001110,%00110111,%01011101,%10010101,%01100101
+.db %00000000,%00000000,%00000111,%11111011,%11111100,%00001111,%11100001,%11000000,%01100000,%00000000,%11111111,%11111100,%00010101,%01010101,%01000101,%01010101
+.db %00000000,%00000000,%00000011,%11100000,%11111000,%00000111,%11000000,%11000000,%01100000,%00000000,%00111111,%11111000,%01100101,%01010101,%01000110,%01010011
 
 txtMenu:  .db "Mode",0  ;1st menu item
          .db "Level",0 ;2nd
@@ -3328,7 +3383,7 @@ _datascore = %10000000 ;score>=100 limit
 _datamultpeas = %00100000
 _datasp    = %01011110
 
-datalevels: .dw LevelDef, LevelDefT
+datalevels: .dw LevelDef, LevelDefM
             .dw LevelDefT,LevelDefM
             .dw LevelDefM,LevelDefM
             .dw LevelDefM,LevelDefC
@@ -3337,36 +3392,36 @@ nrlevels:   .db 1,3,1,3,3,3,3,1     ;=defaults
 savestart:
 
 gamesingle   =  0
-datasingle: .db %01011110,3,1 ;3 lives (<must b unique)
+datasingle: .db %01011110,3,1,1 ;3 lives (<must b unique)
 gamepeas     =  1
-datapeas:   .db %01011010,1,1 ;1 "
+datapeas:   .db %01011010,1,1,1 ;1 "
 gametron     =  2
-datatron:   .db %01000010,1,2
+datatron:   .db %01000010,1,1,1
 gamedeathm   =  3
-datadeathm: .db %01000010,3,2
+datadeathm: .db %01000010,3,2,1
 gamefoodm    =  4
-datafoodm:  .db %11010000,10,2 ;10 score limit (=100)
+datafoodm:  .db %11010000,10,2,1 ;10 score limit (=100)
 gamelinkm    =  5
-datalinkm:  .db %01000011,3,2
+datalinkm:  .db %11010001,3,2,1
 gamerace     =  6
-datarace:   .db %10000000,10,2
+datarace:   .db %10000000,10,2,1
 gamectf      =  7
-datactf:    .db %11100000,9,4
+datactf:    .db %11100000,9,4,1
 ;gamedomin    =  8
 ;datadomin:  .db %01100000,3 ;==(8 modes)
 
 worm1set:  .dw worm1p,worm1p
-           .db %11110111,%00,%01111110,K_RIGHT,K_LEFT
+           .db %11110111,%00,-01,K_RIGHT,K_LEFT
 worm1name: .db "Wormy   ",0
 worm2set:  .dw worm2p,worm2p
-           .db %11111011,%11,%00111111,K_F2,K_F1
+           .db %11111011,%11,-01,K_F2,K_F1
 worm2name: .db "Viper   ",0
 worm3set:  .dw worm3p,worm3p
-           .db %11111011,0,%01011111,K_COMMA,K_STO
+           .db %11111011,%00,-01,K_COMMA,K_STO
 worm3name: .db "Nibbler ",0
 worm4set:  .dw worm4p,worm4p
-           .db %11111011,0,%01111101,K_PLUS,K_ENTER
-worm4name: .db "Spunky  ",0
+           .db %11111011,%00,-01,K_PLUS,K_ENTER
+worm4name: .db "Jim     ",0
 
 defhiscrpos:
   .dw 0,0,0,0,0,0
@@ -3415,7 +3470,7 @@ defspriteimg:     .db %01100000
                .db %01100000
 
 deflevels:
-  .db 15,"Internal Levels"
+  .db "Internal Levels" ;,0
 
   .db 0,deflevels/256,deflevels&255
 templevels: