2 ; Version : 96% (0.96.C24)
3 ; Release Date : UUHHhhh... soon?!?
4 ; Filename : wormy.86p (5kb)
6 ; Email Address : wormy@shiar.org
7 ; Web Page : www.shiar.org
8 ; Description : ruling Nibbles-like game 1-4 players
9 ; Where to get this game : www.shiar.org (home of Wormy)
10 ; Other games by author(s) : Nemesis beta
11 ; Additional Credits to : Matthew Shepcar (wrote original Peaworm, end'98)
12 ; Jonah Cohen (helped writing worm)
14 ;-----------------------------
15 ;----------- TO-DO -----------
16 ;-----------------------------
20 ; 1% * misc (bugs, &&&, pollish, &&, &)
21 ; * mem at worm #4 (still 12 bytes or so.. or more? or less?)
22 ; * look at init-z in line routine again
24 ; 1% * fix transmit game/level data (?)
25 ; * >Somehow do a lot of testing with 2 calcs< *sigh*
27 ;100% = bugs fixed + levels done
29 ;>110%: sound, startpos (?)
30 ;>120%: coop (DON'T COUNT ON IT)
32 ;-----------------------------
33 ;-----------------------------
34 ;------- W O R M Y ---------
35 ;-----------------------------
36 ;-----------------------------
39 ;* Use for LEARNING practises ONLY!
40 ; Don't ever release altered code w/o permission!
41 ;* Code was originally by Scabby (Matthew Shepcar),
42 ; a few lines by Jonah Cohen,
43 ; and everything else by me - Shiar (Mischa Poslawsky).
44 ;* Although I've commented quite some stuff, I can't guarantee
45 ; everybody will understand it. This is probably not the best source
46 ; to learn z80 from. w00t the Shyer Way (tm).
47 ;* Don't scroll down if you get scared easily.
49 #define buffer ;use display buffer (otherwise write directly to screen)
50 #define readymask ;"greys" out the field before starting a level
51 #define coolzgfx ;nice graphics for game over screen
53 ;#define intlevels ;internal levels
54 ;#define readytext ;displays "prepare" before level starts
55 ;#define invincible ;worms cannot die =)
56 ;#define optdie ;in race games worms don't die when they run into each other
63 #include "ti86asm.inc"
64 _SHRACC = $4383 ;4x srl a
65 _SHLACC = $438B ;4x sll a
66 _divHLby10 = $4044 ;hl=hl/10
67 _divAby10 = $4DAF ;a=a/10
68 _HLTIMES10 = $41BF ;hl=hl*10
69 _cphlde = $403C ;cp hl,de
70 _clrWindow = $4A86 ;clear screen
71 _asapvar = $D6FC ;own name (worm)
72 _MOV4B = $429B ;4x ld (de),(hl)
73 _MOV5B = $4297 ;5x ld (de),(hl)
74 _mov9b = $4283 ;9x ld (de),(hl)
75 _ldHLind = $4010 ;ld hl,(hl)
76 _swapt_ = $45F3 ;ex_ahl_bde
77 _Get_Word_ahl = $521D ;ld de,(ahl)
78 _Set_Word_ahl = $5221 ;ld (ahl),de
79 _INC_PTR_AHL = $4637 ;ahl=ahl+1
80 _AHL_PLUS_2_PG3 = $4C3F ;ahl=ahl+2
81 _SET_ABS_SRC_ADDR = $4647 ;set source for mm.ldir =ahl
82 _LOAD_ABS_SRC_ADDR = $5209 ;ahl = mm.ldir source
83 _SET_ABS_DEST_ADDR = $5285 ;set destination for mm.ldir = ahl
84 _SET_MM_NUM_BYTES = $464F ;number of bytes for mm.ldir = ahl
85 _mm_ldir = $52ED ;24bit ldir
86 _MM_LDIR_SET_SIZE = $524D ;_SET_MM_NUM_BYTES + _mm_ldir
87 _RAM_PAGE_1 = $47E3 ;set $8000+ to page 1
88 _RAM_PAGE_7 = $47F3 ;"""" 7
89 _PTEMP_END = $D29A ;end of VAT
90 _load_ram_ahl = $462F ;ahl->page+hl
91 _writeb_inc_ahl = $5567 ;ld (ahl++),c
92 _jforce = $409C ;TI-OS stack restored
93 _EXLP = $4493 ;swap (hl),(de) b times
94 _GETB_AHL = $46C3 ;a=(ahl) \ hl=ahl
96 ;-----------------------------
97 ;------- data storage -------
98 ;-----------------------------
102 ScrBuffer = $8820 ;-A7FF (20*FF=1FE0)
103 worm2p = $A800 ;-ABFF (400) %10101O00
104 worm1 = $AC00 ;-AC1D (31d)
105 worm2 = $AC1F ;-AC3B (1F)
106 worm3 = $AC3E ;-AC59 (1F)
107 worm4 = $AC5D ;-AC77 (1F)
108 balls = $AC7C ;-ACFF (3x43d)
109 SinCosTable = $AD00 ;-AE00 (4*40)
110 turn10 = $AE01 ;-AE01 (1) (counter)
111 peaspos = $AE02 ;-AE05 (4) (peas)
112 ;free = $AE06 ;-AFFF (1FA)
113 worm1p = $B000 ;-B7FF (800) %1011O000
114 worm3p = $B800 ;-BBFF (400) %10111O00
115 ;free = $BF91 ;-BFFF (6F)
116 ;program = $D748 ;-EFFF (186D+4A)
117 worm4p = $F000 ;-F3FF (400) %11110O00
118 leveldata = $F400 ;-FA70 (<=671)
119 ;can you believe i actually left $269 bytes of memory unused?!?
121 ;MEM|8---9---A---B---C---D---E---F---| ;there's something wrong
122 ; |..[------]||[]|......[-----]|[].| ;if you still understand
123 ; | SCREEN 2* 13 PRGM 4LV | ;after looking at this
127 namelength = $BC00 ;(1) @menu
128 datalink = $BC00 ;(8) @init
130 DispBuffer = $BC00 ;(10x57d) @game
135 ;-----------------------------
136 ;------- program start -------
137 ;-----------------------------
139 .org %1101011101001000
141 start: ;turn back NOW!
142 nop ;and so it begins...
145 .org $-1 ;3y3 M 1337!
165 .db %00000000,%00111100
166 .db %00000000,%01010010
167 .db %00000000,%01100001
168 .db %01100011,%10011001
169 .db %10010100,%01101001
170 .db %10011001,%00011001
171 .db %01000010,%11000001
172 .db %00111100,%00111110
175 levelhead2 = 95 ;wormy levels header = "95"
206 ld bc,int_end-int_handler
210 im 2 ;...it *does* work ;)
213 ld hl,$BFFF ;VAT start
216 ld de,(_PTEMP_END+1) ;VAT end
246 ex de,hl ;ld ahl,(hl)
247 cal _AHL_PLUS_2_PG3 ;string id
248 cal _Get_Word_ahl ;ld de,(ahl)
252 jr nz,_searchnext ;not worm
256 inc ix ;save level's ahl
269 cal _Get_Word_ahl ;ld de,(ahl++)
271 ld a,e ;set new level
293 jp z,ExitNoStats ;->no lvls
296 jr z,loadlevel1 ;->1 lvl
297 levelselectmenu: ;load next page
304 cal _vputs ;"< SELECT LEVELS >"
326 cp 49 ;bottom of screen
332 ld l,(ix+2) ;ahl=(ix)
333 cal _load_ram_ahl ;hl=ahl
342 readylevelfile: ;selected level at ahl
343 ; ld hl,templevels-3/0
345 add a,3 ;sellev+3 (#0==-3)
361 cal _GETB_AHL ;ld a,(ahl)
366 cal _INC_PTR_AHL ;ahl++
368 jr nz,skiptitle ;goto #0-terminator
394 cal _load_ram_ahl ;hl=ahl
395 ld de,$FFA0 ;desc.text
400 cp d ;de>$FFFF (offscreen)
401 jr nz,levdescclearloop
406 ld ix,templevels-6 ;reset 2 1st page
411 ld b,-2 ;level selected
417 pop bc ;GET_KEY destr. b
435 or a ;levelfile on page 0 (=internal)
437 cal skiptitle ;skip description
440 ld (leveldataSize),de
445 ld (hilvlposa),a ;singleplayer levels
450 cal _SET_ABS_SRC_ADDR ;levelsstart
453 cal _SET_ABS_DEST_ADDR ;store in mem.
456 cal _MM_LDIR_SET_SIZE
458 cal _LOAD_ABS_SRC_ADDR ;->ahl
465 ldi ;(de),(hl)\inc hl
470 res 2,(iy+13) ;appAutoScroll
478 ld (hl),1 ;def=level#1
482 ;-----------------------------
483 ;----- build trig tables -----
484 ;-----------------------------
486 ld hl,TrigPrecalc ;I believe this
487 ld de,SinCosTable ;is one of the few
488 psh de ;pieces of original
489 ld bc,65 ;Peaworm code still
509 ;-----------------------------
510 ;---------- menu -------------
511 ;-----------------------------
513 DisplayMenu: ;---draw menu---
520 ld hl,$FC00+$010 ;(*,01)
522 ld hl,$FC00+$160 ;(*,22)
524 ld hl,$FC00+$3E0 ;(*,62)
529 dec a ;will be inced @changegame
532 ld hl,changegame ;dispmenusets ;mainMenu
533 psh hl ;jump here after ret
536 ;Mode|Level|Limit|Worms|worm #|controls
537 ; jr dispmenucommon ;cal
542 ld de,$FD80 ;begin pos
567 hr: ;draw horizontal line at hl
569 ; jp menuinvloop ;shorter but not good for pausescreen
581 ;Back|Lives|Limit|Speed|Rotation|Growth
596 inc hl \ inc hl \ inc hl
614 inc a ;-1=None; 0..98->1..99
629 cal cshowA0 ;turn speed
636 ld a,(hl) ;(scorelimit)
641 jr z,optionMenu ;do not display 0 behind 'None'
653 jp z,dispmainmenu ;mainMenu
697 cal loadgamecar ;a=(hl)
700 jr nc,optionMenu ;>99
704 jp dispomenusets ;optionMenu
707 sub 1 ;dec does not set cf
715 jr nc,optionMenu ;>99
718 jr _dispomenusets ;optionMenu
721 sub 1 ;dec does not set cf
728 ld a,(hl) ;(scorelimit)
735 jr nc,_optionMenu ;>98
739 jr _dispomenusets ;optionMenu
745 jr z,_optionMenu ;<-1
752 inc hl ;=saves 2 bytes :P
761 jr nc,_optionMenu ;>25
764 jr _dispomenusets ;optionMenu
779 jr nc,_optionMenu ;>98
782 jr _dispomenusets ;optionMenu
788 jr z,__optionMenu ;<-1
800 dec a ;2nd item: level
802 sub 3 ;5th item: wormname
806 jp LetsGetThisPartyOn ;otherwise
837 jr nc,mainMenu ;may not become >(nrworms)
841 jr _dispmenusets ;mainMenu
854 ; jr z,bchangecurworm
859 jr nz,changedcurworm ;save >0
864 ld a,(hl) ;hl=nrworms
867 jr nc,mainMenu ;may not be >4
870 jr _dispmenusets ;mainMenu
874 ld a,(hl) ;hl=nrworms
878 ld a,(hl) ;hl=nrworms
881 jr nc,changednrworms ;save >=2
890 jr _mainMenu ;don't change for singleplayer
895 dec hl ;inced earlier
897 ld a,1 ;change LS-bit (=link)
901 jr dispmenusets ;mainMenu
908 jr dispmenusets ;mainMenu
921 jr dispmenusets ;mainMenu
924 inc hl ;hl=loadgamecar+2
926 ld a,(hl) ;(curlevel)
928 cp (hl) ;max level for sel.game
934 jr dispmenusets ;mainMenu
937 ld a,(hl) ;(curlevel)
942 getnrlevels: ;for current gametype at hl
969 cal getcustomkey ;left
970 cal getcustomkey ;right
973 ;---display current settings---
983 add hl,de ;hl=posGame+(Gametype)
984 ld a,(hl) ;str.offset
988 ld (CURtxtGame),hl ;save for g/o
989 cal _vputs ;Singleplayer
1038 ld hl,$363E ;controls
1044 ;--- handle menukeys ---
1052 pop bc ;GET_KEY destr. b
1062 menupos: ;highlight #b
1075 add hl,hl ;$FD20+item*96
1105 ;--- change name ---
1108 getwormname: ;of (curworm)
1136 ld hl,$FF07 ;begin pos
1169 dec (hl) ;(namelength)
1184 .db 0,".<>!",0,0,0,0 ;down,L,R,up
1185 .db 0,"XTOJE0",0 ;enter..clear
1186 .db " WSNID9",0 ;(-)..custom
1187 .db "ZVRMHC8",0 ;dot..del
1188 .db "YUQLGB7#" ;0..xvar
1189 .db $D9,"-PKFA6'" ;on..alpha
1190 .db "54321*",0,$D0 ;F5..more
1194 ld (ix+8),0 ;end mark
1197 ;-----------------------------
1198 ;------- procs-n-stuff -------
1199 ;-----------------------------
1203 halt ;save them batteries! yeah!
1207 ld hl,$FD97 ;begin pos
1208 ld a,35 ;nr of lines
1210 ld de,7 ;bytes to add
1212 ld c,9 ;bytes to clear
1217 jr nz,clroldsetsloop
1220 jr nz,clroldsettings
1223 hlatlevel: ;d must be 0
1225 ld a,(Gametype) ;8bytes -> 7bytes
1230 add a,24+1 ;go to datalevels
1232 sbc hl,de ;datalevels
1233 cal _ldHLind ;ld hl,(hl)
1234 pop de ;de=loadgamecar
1236 ld a,(de) ;(curlevel)
1240 dec d ;levels to skip
1244 ret ;hl=begin of correct level
1246 skiplvltitle: ;zf=singleplayer
1248 or a ;null-terminator
1253 skiplevel: ;@hl - destr:ab - alter:hl
1262 ld b,(hl) ;spritesize
1270 pop af ;cp (Gametype),0
1272 inc b ;multiplayer lvl
1274 inc b ;skip other 3 worms (9 bytes)
1311 ;build: c=(gameCar)=(hl-1)
1312 ; a=(wormbeglives)=(hl)
1318 add a,a ;8 bytes per mode
1330 ;-----------------------------
1331 ;-------- start game ---------
1332 ;-----------------------------
1336 ld (CheckExit),a ;set exit state
1341 ld a,4 ;4x (all worms)
1351 ld (hl),b ;score+1=0
1358 ex de,hl ;de=wormX+head
1362 jr nz,createwormsloop
1364 OhMyGodItsALabel: ;pj34r my coding skillz
1368 ex (sp),hl ;pop \ psh leveldata
1369 psh hl ;psh loadgamecar
1373 jp nc,StartLevel ;&&&jr
1375 ;--------- link ------------
1393 jp DisplayMenu ;return to menu
1403 ;name/keys: wormy#1 = link = 0 + link (name1)
1404 ; 2 = worm #1 = #1 + local(name1)
1405 ; 3 = link = 0 + link (name2)
1406 ; 4 = worm #2 = #2 + local(name2)
1409 ldi ;keys worm#2 = worm#1
1412 ldi ;keys worm#4 = worm#2
1415 ld (worm1+left),a ;worm 1...
1416 ld (worm3+left),a ;and worm 3 via link
1462 ;name/keys: wormy#1 = worm #1 = ok
1463 ; 2 = link = 0 + link (name1)
1464 ; 3 = worm #2 = #2 + local(name2)
1465 ; 4 = link = 0 + link (name2)
1468 ldi ;keys worm#3 = worm#2
1471 ld (worm2+left),a ;worm 2+4..
1472 ld (worm4+left),a ;..over link
1481 ld hl,templevels ;&&&&&&&
1497 ;-------- load level ---------
1516 ld (turnright),a ;more efficient
1520 cal _HLTIMES10 ;hl=10*(hl)
1525 pop hl ;begin of current level
1532 dec (hl) ;curlevel-- (not beyond last lvl)
1535 ;show end msg or smtn
1537 psh bc ;where to go afterwards
1538 inc hl ;location of ending-code
1539 jp (hl) ;go there ("call")
1552 ld a,(hl) ;speed from level
1556 ld (de),a ;custom speed
1575 ld b,0 ;bc=sprite size
1576 add hl,bc ;hl=behind sprite
1583 setsprite: ;de=@sprite ;a=sprsize
1607 pop af ;cp (Gametype),0
1615 ld a,SinCosTable/256
1629 ld bc,(worm2-worm1)-7
1639 ;-------- draw level ---------
1666 add hl,hl ;32=scr.width
1673 ld bc,63 ;first 2 rows
1675 ldir ;draw upper border
1677 ld (hl),%11000000 ;first left border
1682 inc hl ;clear rest of line
1722 cp gamerace ;or gamectf
1723 jr c,levelhasbeensetup
1725 ld c,2 ;ld bc,2 (2 bytes)
1726 jr z,loadextralevelstuff ;cp gamerace
1727 ld c,4 ;ld bc,4 (2nd flag in ctf)
1728 loadextralevelstuff:
1737 ;--------- prepare -----------
1740 psh hl ; >> levelp new
1767 ld hl,4+(txtposReady*256)
1790 ;-----------------------------
1791 ;----------- LOOP ------------
1792 ;-----------------------------
1795 ld bc,(worm1+pos) ;camera worm #1
1797 or a ;if #1 not over link
1799 ld bc,(worm2+pos) ;otherwise view from #2
1801 cal DisplayField ;display piece of level
1816 jr nz,screeninvertloop
1829 ld (handledworm),a ;reset
1847 jr nz,nodispupdate ;just once every 10 turns
1848 ld (hl),10 ;reset counter
1849 cal forceshowstats ;update score
1854 jr nz,noctfpeas2draw
1857 cal tryDrawPea ;pea#1
1860 cal tryDrawPea ;pea#2
1867 cal nz,handlethoseneatlittleballs
1880 inc (hl) ;0..nrworms-1
1883 ;-----------------------------
1884 ;---------- keys -------------
1885 ;-----------------------------
1894 rla ;=$17 (c=EXIT-key)
1899 ;------- pause menu -------
1904 ;Resume|Turn Off|Contrast|Exit||
1907 ld hl,$FC00+$170 ;(*,23)
1909 ld hl,$FC00+$310 ;(*,49)
1985 out (7),a ;both wires low = game over signal
1994 cal menuinvloop ;invert
1996 cal hr ;menuinvloop w/ b=16
2006 cal menuinvloop ;invert
2008 cal hr ;menuinvloop w/ b=16
2027 cal _vputs ;Died Score
2042 jr c,nonewwinner ;h<d
2043 jr nz,newwinner ;h>d
2046 jr nc,nonewwinner ;l<e
2057 cpl ;high value (>$FB)
2062 ld a,(hl) ;less deaths
2069 ;---display worms---
2081 cp (hl) ;input=0 = link
2098 ld a,(hl) ;worm+died
2105 jr nz,nodmwinner ;deathmatch?
2106 ld a,0 ;winner's deaths
2108 cp (hl) ;equals this worm?
2109 scf ;jr nz,notwinner
2112 jr c,notwinner ;no singleplayer winners
2114 cal _ldHLind ;ld hl,(hl)
2117 cal _cphlde ;==highest score..
2132 dnz displayWormStats
2135 or a ;singleplayer (0) only
2136 jr nz,hilevelcheckdone
2141 jr c,hilevelcheckdone
2142 ld (hl),a ;save local
2147 hilvlposhl =$-2 ;save external
2148 cal _writeb_inc_ahl ;ld (ahl),c
2153 jr z,hiscorecheckdone ;no SP
2155 cal loadhiscoreposinahl
2156 cal _SET_ABS_SRC_ADDR ;from ahl (lvlfile)
2159 cal _SET_ABS_DEST_ADDR ;to local
2161 cal _MM_LDIR_SET_SIZE ;get old score+name
2164 ld de,(highsave) ;de=prev. hiscore
2165 ld hl,(worm1+score) ;hl=worm1's score
2166 cal _cphlde ;sub hl,de
2167 jr c,NotNewHigh ;new<old
2168 jr z,NotNewHigh ;new<=old
2170 ld (highsave),hl ;store new hiscore
2171 ld de,highsave+2 ;to
2172 ld hl,worm1+name ;from
2174 ldir ;store new hiname
2175 cal loadhiscoreposinahl
2176 cal _SET_ABS_DEST_ADDR ;to ahl
2179 cal _SET_ABS_SRC_ADDR ;from local
2181 cal _MM_LDIR_SET_SIZE ;save new
2209 ;x123456789012345678901
2210 ;>>>>>> GAME OVER <<<<<
2215 ;6Worm#02 @ 05 00120
2222 rst 20h ;_ABS_MOV10TOOP1
2224 ld hl,savestart-_asm_exec_ram+4
2228 cal _SET_ABS_DEST_ADDR
2232 cal _SET_ABS_SRC_ADDR
2233 ld hl,saveend-savestart
2234 cal _MM_LDIR_SET_SIZE
2242 loadhiscoreposinahl:
2243 ld hl,0 ;for peaworm and singleplayer
2249 ld a,(nrlevels+1) ;skip peaworm slots if tron mode
2253 ld b,a ;levels to skip (including 1 for singleplayer)
2254 ld de,5 ;to add per level
2256 add hl,de ;one word+3 bytes for name
2257 dnz addlevelposition
2264 adc a,0 ;ahl=saveloc
2273 jp _putc ;..then put *
2275 ;-----------------------------
2276 ;----------- worm ------------
2277 ;-----------------------------
2282 cal saverespawncounter
2288 jr DoesWormTailEqualsWormHead ;chk4 size=0
2299 jr nz,DoesWormTailEqualsWormHead
2300 inc (ix+grow+1) ;+256
2301 DoesWormTailEqualsWormHead:
2303 jr nz,removewormloop
2307 jr nz,safewormsizedone
2311 ld (ix+grow+1),0 ;high
2316 ld (ix+tail),e ;head=tail/size=0
2322 jr nz,saverespawncounter
2346 ld a,%01111111 ;default
2349 dnz bitmask ;a/8 times
2350 out (1),a ;send bitmask
2351 in a,(1) ;input keys
2356 dnz keybit ;check match (cf set)
2359 inkeys: ;use jp not call!
2378 jr z,inlink ;input by link
2379 cal inkeys ;input by keys
2383 ld c,l ;send our keys
2390 ;-----------------------------
2391 ;------- handle worm ---------
2392 ;-----------------------------
2445 ;-------- move worm ----------
2473 notmoveY: ;bc=newpos
2480 pop hl ; << pos (old)
2498 ;--------- worm hit ----------
2505 cal z,checkhitotherworm
2508 and _datamultpeas ;&&bit
2512 jp z,WormDead ;no food
2519 cal DrawPea ;remove pea
2534 jp nz,Drawworm ;continue
2540 jp nz,Exit ;stack restored
2551 cal _IncScore ;score+(40*level)
2558 chkpeahit: ;bc=ownpos;hl=peapos (destr:ad)
2574 ld hl,(peaspos) ;1st pea
2577 and %01 ;ourpea (0|1)
2579 ld hl,(peaspos+2) ;2nd pea ;&&&ex de,hl?
2584 ld a,e ;peek a (that's x86asm for pop\push ;)
2585 bit 1,a ;%10 = carrying flag?
2586 jp z,WormDead ;if not just die
2591 pop af ;which flag? (=and %1)
2592 ld hl,drawctfpea1 ;restore #1
2593 jr z,nottheotherflag
2594 ld hl,drawctfpea2 ;restore #2
2596 ld (hl),3 ;draw delay 3 turns
2602 hitflag: ;correct pea hit
2604 xor %11 ;invert flag taken + ownflag
2606 and %10 ;just returned?
2610 jr nz,Drawworm ;flag taken, continue game
2612 ld e,20 ;flag captured+returned
2616 ld (drawctfpea1),a ;redraw..
2617 ld (drawctfpea2),a ;..both flags
2620 ;-----------------------------
2639 jr nz,nextotherwormbit
2649 ld a,(peaspos+1) ;yline
2652 jr nc,checklap ;y>yline -> a=1
2653 xor a ;y<yline -> a=0
2656 ret z ;same as before
2657 ld (ix+reserv),a ;1st time
2660 and 1 ;group 0 (1,3) or 1 (2,4)
2662 ret z ;(group 0 and y<yline) or (group 1 and y>yline)
2669 ;-------- draw worm ----------
2677 cal z,checkhitlapline
2683 ret z ;keep tail in "Tron"
2737 ;-----------------------------
2738 ;---------- ball -------------
2739 ;-----------------------------
2741 handlethoseneatlittleballs:
2787 bit 1,d ;1=up; 0=down
2817 letsmovetheotherway:
2832 ;-----------------------------
2833 ;----------- procs -----------
2834 ;-----------------------------
2838 ld a,%10000000 ;all key-masks
2841 inc a ;cp %11111111 (no keys pressed)
2842 jr nz,releasekeys ;keep waitin
2843 cal GET_KEY ;clear buffer
2871 ld (ix+delay),respawndelay
2890 ld (ix+pos2+1),a ;x2
2897 cp gamectf ;ctf no death penalty
2900 ret nz ;HandleWorm done
2902 or a ;0=no live limit
2903 ret z ;don't end game
2906 jr z,anyworm ;quit at any worm's death
2907 ld a,(nrworms) ;timematch: all worms must've died
2909 ld hl,worm1+lives-(worm2-worm1)
2911 xor a ;check for 0 lives
2913 add hl,de ;next worm
2915 ret nz ;any >0: don't exit
2918 ld a,$A7 ;exit@end of turn
2919 ld (CheckExit),a ;set exit state
2924 .db $dd,$7d ;ld a,lx
2927 jr nz,chkworm2 ; ret nz
2954 CheckPea: ;@hl; destr:abcde
2967 ret nz ;nz=pixel found
2976 tryDrawPea: ;hl=peapos;bc=dopea
2985 dec (hl) ;hl=appeartime
2986 ex de,hl ;hl=peaspos
3001 cal sendnewpeaoverlink
3010 PutSprite: ;||@(b,c)
3011 ;by SHIAR only ix saved
3048 ;----------- score -----------
3051 ;piece of crap checking whether you've already won in timematch
3063 jr z,nneexxtt ;yourself
3065 ret nz ;someone else still alive
3070 jr c,nneexxtt_ ;you>him
3083 dnz chktimematchover
3099 add hl,de ;increase score
3102 jr z,scorecommon ;hl/1000 not increased
3111 jr c,showstats ;<0=0
3114 IncScore: ;inc score by e
3116 _IncScore ; inc by de
3120 or a ;if singleplayer...
3122 add hl,de ;score+=de
3125 ld (ix+score),l ;save
3130 jr z,showstats ;de=0=no limit
3137 jr nz,timematchscore ;no disp for timematches
3138 ld hl,$FC00 ;&&&only necessary in deathmatch
3160 shownameloop: ;1st 3 chars
3189 showstat: ;(multiplayer)
3200 showA: ;small w/o leading 0 (&&&combine w/ cshowA0??)
3219 showstatsS: ;(singleplayer)
3254 showA0: ;big w/ leading 0
3266 cshowA0: ;small w/ leading 0
3301 ;-----------------------------
3303 DisplayField: ;all done by Jonah Cohen iirc. (-scrolling is scary-)
3304 ld a,c ;not the fastest routine outthere, but it does get the job done.
3305 sub 29 ;if something doesn't work, I probably _did_ alter it ;)
3419 ld (ShiftRightCounter),a
3421 ld (ShiftRightChunk),a
3435 ShiftRightCounter = $-1
3457 ld (ShiftLeftCounter),a
3459 ld (ShiftLeftChunk),a
3461 jr nc,ShiftLeftSameByte
3480 ShiftLeftCounter = $-1
3491 jr nz,ShiftRowsRight
3525 ;----------- draw ------------
3539 CheckPixel: ;at bc in d
3546 ;CLEM's FIND_PIXEL (131+? cycles; 28+4 bytes)
3547 ;(b,c) to hl:a; "destroyes" ahl
3549 FindPixel: ;(b,c) to hl:a
3574 psh de ;&&& C`MON! THIS IS UGLY! *hit myself*
3612 ;IMHO, one weery nice routine. Oh lemme be proud just *once*.
3613 ;Not perfect since it uses a screwy lineroutine to draw stuff
3614 ;but, just _look_ at it. Ain't it grand? Z80 at its best.
3615 ;Nice comments, also. So here we go: Shiar's Circle Routine:
3616 ;(using the Bresenham method)
3618 drawcircle: ;(d,e),h ;de=x,y; h=z
3629 ex (sp),hl ;push zz \ pop x,y
3630 cal circledraw ;(x-xx,y+yy)-(x+xx,y+yy)
3631 ;(x-xx,y-yy)-(x+xx,y-yy)
3632 cal circledraw ;(x-yy,y+xx)-(x+yy,y+xx)
3633 ;(x-yy,y-xx)-(x+yy,y-xx)
3635 ex (sp),hl ;push x,y \ pop zz
3638 dec a ;-256<h<0 = $FF**
3640 jr z,circlenext ;jump if zz<0
3644 add a,a ;a=2yy-2 ;nc
3646 sbc hl,de ;zz=zz-2yy+2
3654 add hl,de ;zz=zz+2xx+3
3663 circledraw: ;destr:de
3668 add hl,bc ;h=x+xx; l=y+yy
3670 cal drawline ;(h-b,l+c)-(h+b,l+c)
3676 cal drawline ;(h-b,l-c)-(h+b,l-c)
3677 ld a,b ;swap xx and yy
3683 drawbox: ;(d,e)-(h,l)
3705 ;A lot like Scabby's line routine in Wonderworm (dunno whether he wrote it
3706 ;himself.) I did make a few optimizations and commented the thing.
3707 ;A nice routine (also Bresenham), but for Wormy not perfect since really
3708 ;large lines (>128 pixels in length or something) won't be flawless.
3710 drawline: ;(d,e)-(h,l)
3716 jr c,lineXincs ;if x>xx
3718 lineXincs: ;deltax=|deltax|
3722 cal FindPixel ; (ahl=x+y)
3724 ld c,a ;c=mask (always)
3727 ld b,a ;b=deltax (always>0)
3729 jr nz,lineexists ;deltax!=0
3731 jr nz,lineexists ;deltay!=0
3733 jr DoneLine ;line is 1 pixel
3736 ld de,32 ;go down (def)
3737 jr nc,lineYincs ;cf = deltay<0
3740 lineYincs: ;lets assume y incs as well
3742 jr nc,SteepLine ;deltay<deltax?
3743 ld (line2sm+1),a ;a=deltay
3747 ld (line1sm+1),a ;a=-deltax
3749 add a,h ;a=deltay-deltax/2
3753 psh af ;init z=dy-dx
3767 dnz linedrawxloop ;|deltax| times
3783 ld (line4sm+1),a ;a=deltax
3784 sub h ;a=deltax-deltay
3788 psh af ;init z=2(dx-dy)
3802 dnz linedrawyloop ;|deltay| times
3808 receivenewpeaoverlink:
3820 jr z,receivenewpeaoverlink
3821 ld c,l ;send pea's pos
3824 ; jr Qsend ;that's why it's here
3826 ;..and last but not least..:
3827 ;-----------------------------
3828 ;----------- link ------------
3829 ;-----------------------------
3836 Qsend: ;--- try to send 8 bits in C; CF=error --- destr:abcde ---
3839 jr z,linkerr ;both wires low = exit signal
3840 ld b,8 ;bits to send
3843 rl c ;bit to send in cf
3844 ld a,D0LD1H ;0: lower white
3846 ld a,D0HD1L ;1: lower red
3848 out (7),a ;lower one (send bit)
3850 cal checklink ;other calc must lower other wire
3852 cal linkok ;raise one, ok to raise other (out (7),D0HD1H)
3855 cp %11 ;both raised (by other calc)
3858 dnz sendloop ;repeat for all bits
3860 ld (linklosses),a ;reset number of losses
3865 Crecv: ;--- receive 8 bits into A/C --- destr:abCde ---
3867 ret nc ;return if all went ok
3868 jr Crecv ;and try again
3870 Qrecv: ;--- receive 8 bits into A/C; CF=error --- destr:abCde ---
3872 jr z,linkerr ;both low = error, quit
3873 ld b,8 ;bits to receive
3877 cal linktest ;checklink
3879 jr z,recvwait ;both high = nothing sent (yet)
3881 rra ;received bit in cf
3883 jr c,received ;lower white wire as well
3884 ld a,D0HD1L ;lower red
3887 out (7),a ;both wires low
3890 jr z,recvwaitack ;same wire will be raised again by other calc
3891 cal linkok ;raise both
3893 dnz recvloop ;repeat for all bits
3895 ld (linklosses),a ;reset number of losses
3902 out (7),a ;raise both wires = link ok
3905 checklink: ;load wires in A and check for timeout
3906 dec de ;decrease timer
3909 jr z,linktimeout ;timeout if de==0
3912 out (1),a ;select keys
3922 ld a,0 ;losses so far
3924 inc a ;and this is another one
3926 pop de ;return from link
3927 cp lossout ;quit if too many errors
3928 ret c ;otherwise just continue
3934 ;-----------------------------
3935 ;---------- levels -----------
3936 ;-----------------------------
3939 .db 5,4,15,15,0,0 ;peas,speed,growth,begin_size,sprite,balls
3940 .db 0,2,63 ;start d, y, x
3941 .db 128,57 ;field width (128-255), height (57-255)
3942 .db 0 ;no additional lines, boxes
3950 .db $40,30,2,$C0,30,125, $00,2,64,$80,54,64
3954 .db "Fast Fun :))",0
3956 .db %1110000,%10001000,%10001000,%10001000,%1110000,0
3957 .db $40,30,2,$C0,30,125, $00,2,64,$80,54,64
3963 .db $40,30,2,$C0,30,125, $00,2,64,$80,54,64
3968 LevelDefT: ;tron=no delay
3969 .db "Empty Tron Level",0
3971 .db %1110000,%10001000,%10001000,%10001000,%1110000,0
3972 .db $40,30,64,$C0,30,64, $00,30,64,$80,30,64
3977 .db "Round and Round",0
3979 .db %1110000,%10001000,%10001000,%10001000,%1110000,0
3980 .db $40,23,2,$C0,23,125, $40,35,2,$C0,35,125
3988 .db %1110000,%10001000,%10001000,%10001000,%1110000,0
3989 .db $40,23,2,$C0,23,125, $40,35,2,$C0,35,125
3996 ;-----------------------------
3997 ;---------- data -------------
3998 ;-----------------------------
4001 .db %00011110,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000,%00000001,%11000000,%00000000,%00000000,%00000001,%10000000,%00000000,%00001111,%10000000
4002 .db %00111110,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000,%00000001,%11100000,%00000000,%00000011,%11000010,%01000011,%10011100,%00110000,%01100000
4003 .db %01110000,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000,%01110000,%00111000,%00001100,%00110001,%00110100,%01100011,%01000000,%00010000
4004 .db %01100000,%01111100,%00000001,%11111111,%00000000,%11110000,%01111001,%11100000,%00110000,%01111100,%00010001,%11001001,%00001000,%00100000,%10000010,%00010000
4005 .db %11100000,%11111110,%00000011,%11111111,%10000011,%11111000,%11111111,%11110000,%00110000,%11101100,%00010001,%11000100,%10000001,%00000100,%10001110,%00001000
4006 .db %11000001,%11000111,%00000111,%00000001,%11000111,%10011001,%11001111,%00111000,%00110000,%11000110,%00001100,%00000010,%01100010,%10011100,%00010001,%00001000
4007 .db %11000001,%10000011,%00000110,%00000000,%11100110,%00000001,%10011111,%10011000,%00111001,%11000110,%00000011,%11000010,%00011100,%01100010,%00100001,%01101000
4008 .db %11000001,%10000011,%00000110,%11000000,%01101110,%00000011,%10111001,%11011100,%00111001,%11000110,%01111000,%00100001,%00000000,%00000001,%11000001,%01101000
4009 .db %11000001,%11000111,%00000110,%11000000,%01101100,%00000011,%00110000,%11001100,%00011111,%10000110,%10000101,%11100001,%00000000,%00000000,%00000001,%00010000
4010 .db %11000000,%11000110,%00000110,%11000000,%01101100,%00000011,%00110000,%11001100,%00001111,%00001110,%10010110,%00010001,%00000000,%00000000,%00000000,%11100000
4011 .db %11100000,%11101110,%00001110,%11000000,%01101100,%00000011,%00111001,%11001100,%00000000,%00001100,%01100100,%00001001,%00111111,%11111111,%11000000,%00000000
4012 .db %01100000,%01111100,%00001100,%11000000,%01101100,%00000011,%00011111,%10001110,%00000000,%00001100,%01000000,%10000001,%01000000,%00000000,%00000000,%00000000
4013 .db %01110000,%00111000,%00011100,%11100000,%11101110,%00000011,%00001111,%00000110,%00000000,%00011100,%01000000,%11000001,%01100101,%01001001,%10000011,%01100011
4014 .db %00111000,%11111110,%00111000,%01110001,%11000110,%00000011,%10000000,%00000111,%10000000,%00111000,%01000001,%00100001,%00110101,%00010101,%01000101,%01010100
4015 .db %00011111,%11101111,%11110000,%00111111,%10000111,%00000001,%10000000,%00000011,%11111111,%11110000,%00111110,%00011110,%00010111,%01011101,%10010101,%01100101
4016 .db %00001111,%10000011,%11100000,%00011111,%00000011,%00000001,%10000000,%00000000,%11111111,%11100000,%00000000,%00000000,%11100101,%01010101,%01000110,%01010011
4019 .db %00000110,%00111000,%00000000,%00111100,%00001111,%10001110,%00111100,%01111000,%00001100,%11011000,%11100011,%10000000,%00000000,%11111100,%00111000,%00000000
4020 .db %00011001,%01000110,%11100000,%11000010,%00011100,%11011111,%01111110,%11111000,%00011110,%11011101,%11110111,%11000000,%00111111,%00000011,%01000110,%11100000
4021 .db %00100000,%10000011,%00010001,%00110010,%00011000,%00010011,%01101010,%11000000,%00111011,%01001101,%10000110,%01000000,%11000000,%00000000,%10000001,%00010000
4022 .db %00100000,%00000000,%00001110,%00110010,%00011001,%10011011,%01101010,%11100000,%00110011,%01101101,%11000111,%10000001,%00011100,%00000000,%00000000,%00001100
4023 .db %01001100,%00011000,%00000000,%00000100,%00011000,%11011111,%01100010,%11001100,%00110011,%01101101,%10000111,%11000001,%00011100,%00111000,%00011000,%10000010
4024 .db %01010010,%00100100,%01100000,%00011000,%00011111,%11011011,%11101110,%11111100,%00011111,%01111000,%11110110,%11100000,%11000000,%11000110,%00101001,%10000010
4025 .db %01100001,%11000011,%10011111,%11100000,%00001111,%10001001,%11001100,%01111000,%00001110,%00110000,%01100110,%01100000,%00111111,%00000001,%11000110,%01111100
4027 ;.db %00000000,%00000001,%10000000,%00000000,%00001111,%10000000
4029 txtMenu: .db "Mode",0 ;1st menu item
4035 .dw $2418,$231E,$2824,$1F2A,$1730
4036 txtMenuR: .db "controls",0
4037 txtoMenu: .db "Back",0 ;1st menu item
4044 .dw $2618,$251E,$2524,$222A,$1A30,$1C36
4045 txtpMenu: .db "Resume",0 ;1st menu item
4046 .db "Turn Off",0 ;2nd
4047 .db "Contrast",$CF,5,0 ;...
4050 .dw $3418,$331E,$2F24,$3A2A
4051 txtGame: .db "Singleplayer",0
4052 txtGame1: .db "Peaworm",0
4053 txtGame2: .db "Tron",0
4054 txtGame3: .db "Deathmatch",0
4055 txtGame4: .db "Foodmatch",0
4056 txtGame5: .db "Timematch",0
4057 txtGame6: .db "Race",0
4058 txtGame7: .db "CTF" ;,0
4061 .db txtGame1-txtGame
4062 .db txtGame2-txtGame
4063 .db txtGame3-txtGame
4064 .db txtGame4-txtGame
4065 .db txtGame5-txtGame
4066 .db txtGame6-txtGame
4067 .db txtGame7-txtGame
4069 txtNone: .db "None",0
4070 txtDef: .db "Default",0
4073 txtKeyleft: .db ":left",0
4074 txtKeyright:.db "/right",0
4076 txtLevsel: .db $CF," SELECT LEVELS ",5,0
4077 txtWaiting: .db "Waiting...",0
4078 txtReceive: .db "Receiving..." ;,0
4081 .db 0, 3, 6, 9, 12, 15, 18, 21
4082 .db 24, 27, 30, 33, 36, 39, 42, 45
4083 .db 48, 51, 54, 57, 59, 62, 65, 67
4084 .db 70, 73, 75, 78, 80, 82, 85, 87
4085 .db 89, 91, 94, 96, 98,100,102,103
4086 .db 105,107,108,110,112,113,114,116
4087 .db 117,118,119,120,121,122,123,123
4088 .db 124,125,125,126,126,126,126,126
4091 txtLevel: .db "Level ",0
4092 txtWorms: .db "Worms: 0",0 ;follows txtLevel
4093 txtName: .db "Name",0
4094 txtWinner: .db "Wins " ;follows txtName
4095 txtDied: .db "Died " ;follows txtWinner
4096 txtScore: .db "Score",0 ;follows txtDied
4097 txtLeft: .db " left",0 ;follows txtScore
4098 txthiscore:.db "HiScore:",0
4100 txtReady: .db "Prepare!",0
4104 txtGO: .db 5,5,5,5,5," GAME OVER ",$CF,$CF,$CF,$CF,$CF,0
4108 datalevels: .dw LevelDef, LevelDefM
4109 .dw LevelDefT,LevelDefM
4110 .dw LevelDefM,LevelDefM
4111 .dw LevelDefR,LevelDefC
4112 nrlevels: .db 0,3,1,3,3,3,3,1 ;=defaults
4114 datalevels: .dw 0,0,0,0,0,0,0,0
4115 nrlevels: .dw 0,0,0,0
4118 _datalink = %0000001 ;linkplay
4119 _datafoodl = %0000010 ;left=0 limit
4120 _datasingl = %0000100 ;singleplayer=1 (=hiscore+keep_length+nextlevel)
4121 _datamultpeas = %0001000 ;multiple peas=1
4122 _datatime = %0010000 ;time incs score (timematch)
4123 _datafood = %0100000 ;food present
4124 _datadie = %1000000 ;worm dies on impact
4125 ;reserved %10000000 ;for future use
4127 savestart: ; �game info (see above)
4128 ; | �lives (0=unlimited)
4129 ; | | �nrworms (can be altered by user)
4130 ; | | | �level (reset to 1 at startup)
4131 ; | | | | �speed/delay (-1=def)
4132 ; | | | | | �grow speed (-1=none; 0=continuous)
4133 ; | | | | | | �turn speed (8=def)
4134 ; | | | | | | | �score limit (0=none)
4135 gamesingle = 0 ;used | | | | | | | |
4136 datasingle: .db %1100110,3,1,1,-1,-1, 8, 0 ;Singleplayer (SP; 3 lives)
4138 datapeas: .db %1100100,1,1,1,-1,-1, 8, 0 ;Peaworm (SP; 1 live)
4140 datatron: .db %1010100,1,1,1,-1, 0, 8, 0 ;Tron (SP; 1 live, cont.growth)
4141 gamedeathm = 3 ;used
4142 datadeathm: .db %1000000,3,2,1,-1,49, 8, 0 ;Deathmatch (3 lives, 50 growth)
4144 datafoodm: .db %1100000,0,2,1,-1,-1, 8,10 ;Foodmatch (100 score)
4146 datatimem: .db %1010000,1,2,1,-1, 0, 8, 0 ;Timematch (tron, 100 score)
4148 datarace: .db %0000000,0,2,1,-1,-1, 8,10 ;Race (100 score, no collision)
4150 datactf: .db %1001000,0,4,1,-1,-1, 8,10 ;CTF (100 score)
4152 worm1set: .dw worm1p,worm1p
4153 .db %11110111,1,-01,K_RIGHT,K_LEFT
4154 worm1name: .db "WORMY ",0
4155 worm2set: .dw worm2p,worm2p
4156 .db %11111011,0,-01,K_F2,K_F1
4157 worm2name: .db "VIPER ",0
4158 worm3set: .dw worm3p,worm3p
4159 .db %11111011,1,-01,K_COMMA,K_STO
4160 worm3name: .db "NIBBLER ",0
4161 worm4set: .dw worm4p,worm4p
4162 .db %11111011,0,-01,K_PLUS,K_ENTER
4163 worm4name: .db "JIM ",0
4174 Gametype: .db 0 ;last gamemode
4188 head = 13 ;4B (head=tail)
4189 tail = 15 ;also@next level
4191 reserv = 18 ;loop (race:lap|ctf:pea)
4192 input = 19 ;---currently unused afaik---
4203 defspriteimg: .db %01100000
4210 .db "Internal Levels",0
4213 .db 0,deflevels/256,deflevels&255
4217 ;-----------------------------
4218 ;----------- end -------------
4219 ;-----------------------------