wormedit 0.92.0618
authorMischa Poslawsky <wormy@shiar.org>
Sun, 18 Jun 2000 14:50:26 +0000 (16:50 +0200)
committerMischa Poslawsky <wormy@shiar.org>
Mon, 2 Mar 2009 21:30:54 +0000 (22:30 +0100)
Replaces the need for level source example.

example1.z80 [deleted file]
makelvl.bat [deleted file]
wormedit.pas [new file with mode: 0644]

diff --git a/example1.z80 b/example1.z80
deleted file mode 100644 (file)
index 6bf86fe..0000000
+++ /dev/null
@@ -1,230 +0,0 @@
-; *** WORM LEVELFILE ***
-;       example #1
-;        by SHIAR
-
-;Sample levelfile with everything commented.
-;Teaches you everything to build your own level.
-
-
-;-----------------------------------------------------------------------------
-
-;Standard 128x57 FIELD:
-;       +-----------------+
-;(0,0)> |####(BORDER)#####|
-;       |#*(2,2)         #|
-;       |#               #|
-;       |#(63,28)*(64,28)#|
-;       |#               #|
-;       |#      (125,54)*#|
-;       |#################| <(127,56)
-;       +-----------------+
-;Drawable screen is (2,2)-(125,54); center is (63.5,28)
-;
-;Screen will scroll with screensizes above 128x57 (max.256x256)
-;Example 256x80 FIELD (use 0,80):
-;       +-----------------------------------+
-;(0,0)> |#############(BORDER)##############|
-;       |#*(2,2)          :                #|
-;       |#                :                #|
-;       |#                :                #|
-;       |#                :                #|
-;       |#       (125,54)*:                #|
-;       |#"""""""""""""""":""""""""""""""""#|
-;       |#                :      (253,253)*#|
-;       |###################################| <(255,255)
-;       +-----------------------------------+
-
-
-;-----------------------------------------------------------------------------
-
-;DOUBLE CHECK THE FOLLOWING THINGS:
-; * correct name size at .org
-; * max. choosable level doesn't exeed actual levels present
-; * enough hiscore space (two bytes for each peaworm level!)
-
-
-;------------------------------- HEADER --------------------------------------
-
-;#include "asm86.h"            ;use include files to make your own
-;#include "ti86asm.inc"        ;singleplayer ending (just like normal asm)
-
-
-  .org $F3E3-10                ;$F3E3-[name size]
-            ;^^ <-MUST EQUAL NAME SIZE BELOW!!! If not, Worm will crash!
-
-  .db 'w',91                   ;wormLevel header (version .91)
-  .db 10,"Example #1"          ;name size (UPDATE .ORG!!!); level name
-  .dw hiscore-single           ;leveldata size
-
-
-levelsdata:
-
-  .dw single          ;points to singleplayer levels below
-  .dw peaworm         ;...peaworm level
-  .dw deathmatch      ;...deathmatch
-  .dw foodmatch       ;...foodmatch
-  .dw linkmatch       ;...linkmatch
-  .dw race            ;...race
-  .dw ctf             ;...capture the flag
-  .dw domination      ;...domination
-
-;note: use <.dw 0> if no levels present (empty level will be used).
-
-  .db 1,2,3,1         ;max. choosable level for each gametype
-  .db 1,1,1,1         ;so: 1 = level 1 only; 3 = level 1 to 3 available
-
-;again .db 0 indicates no levels present.
-
-
-;------------------------------- LEVELS --------------------------------------
-
-;LEVEL-FORMAT:
-;------------
-; .db 5               ;nr. of peas in level
-; .db 4               ;delay (0=fastest, 4=normal)
-; .db 15              ;growth per pea
-; .db 15              ;begin size
-; .db 4               ;sprite size (1-8; 0=use default sprite)
-; .db %01100000       ;the sprite
-; .db %11110000
-; .db %11110000
-; .db %01100000
-; .db 2               ;bouncing balls (0-40)
-; .db 2               ;BALL #1: begin y-position
-; .db 4               ;         begin-x
-; .db %00             ;         direction (%00=right+down, %11=left+up)
-; .db 2,7,%00         ;BALL #2: y,x,direction
-; .db 0               ;your start direction (0=down,$40=right,$80=up,$C0=left)
-; .db 2               ;your y-position (2=at top)
-; .db 63              ;your x-position (63=center)
-;                     ;IN MULTIPLAYER LEVELS also set positions for worm 2-4:
-;(.db $C0,28,125 )    ;player 2 moves left
-;(.db $00, 2, 63 )    ;player 3 moves down
-;(.db $80,54, 63 )    ;player 4 moves up
-;
-; .db 128,57          ;field size: width (128-255), height (57-255)
-;                     ; screen will SCROLL if size is more than 128,57
-;                     ;IN CTF LEVELS also set flag-positions:
-;(.db 10,117 )        ;flag #1 y-position, x-position
-;(.db 46,10  )        ;flag #2 y-pos, x-pos.
-;
-; .db 2               ;number of lines:
-; .db 28,14,100,41    ;LINE #1 coordinates: (x1,y1)-(x2,y2)
-; .db 28,41,100,14    ;LINE #2: the same
-; .db 1               ;number of boxes:
-; .db 16,12,48,12     ;BOX #1: x1,y1,x2,ysize(y2-y1)
-;------------         ;THAT'S ALL; repeat for all levels
-
-
-single:               ;singleplayer levels start here
-
-  .db 5,4,15
-  .db 15,5
-  .db %01110000
-  .db %10001000
-  .db %10001000
-  .db %10001000
-  .db %01110000
-  .db 0
-  .db 0,2,63
-  .db 128,57
-  .db 0,0             ;no lines/boxes
-
-  .db 8,4,15,15,0
-  .db 0
-  .db $40,14,2
-  .db 128,57
-  .db 1               ;one horizontal line
-  .db 28,28,100,28
-  .db 0
-
-  .db 255             ;end marker: no more levels
-
-;Code to run when all levels are done:
-;Worm waits a second, then screen is cleared and this code will be run.
-
-   ret                ;no end, quit and continue with stats-screen
-
-;This is a sample ending displaying "Congratulations!!" to use instead of RET:
-;  ld hl,endtext
-;  call _puts         ;display text
-;  jp _getkey         ;wait for a key and return (jp = call+ret)
-;endtext:
-; .db "  Congratulations!!",0
-
-
-peaworm:              ;peaworm levels (2)
-  .db 5,4,15
-  .db 15,5
-  .db %01110000
-  .db %10001000
-  .db %10001000
-  .db %10001000
-  .db %01110000
-  .db 0
-  .db 0,2,63
-  .db 128,57
-  .db 0,0
-
-  .db 5,4,15,15,0,0
-  .db 0,2,63
-  .db 128,57
-  .db 0,0
-
-
-deathmatch:           ;deathmatch levels
-  .db 8,5,15,31,0,0
-  .db $40,28,2        ;begin stats for each player
-  .db $C0,28,125
-  .db $00,2,63
-  .db $80,54,63
-  .db 128,57          ;field size
-  .db 0
-  .db 4               ;4 boxes
-  .db 16,12,48,12
-  .db 80,12,112,12
-  .db 16,34,48,12
-  .db 80,34,112,12
-
-
-foodmatch:
-domination:
-  .db 8,5,18,15,0,0
-  .db $40,30,2,$C0,30,125, $00,2,64,$80,54,64
-  .db 128,57
-  .db 0,0
-
-
-linkmatch:
-  .db 8,0,15,15,0,0
-  .db $40,30,2,$C0,30,125, $00,2,64,$80,54,64
-  .db 228,157
-  .db 0,0
-
-
-race:
-  .db 8,4,15,10,0,0
-  .db $40,3,2,$40,6,2, $40,9,2,$40,12,2
-  .db 128,57
-  .db 0
-  .db 2
-  .db 22,21,104,15
-  .db 52,10,74,37
-
-
-ctf:
-  .db 8,5,18,15,0,0
-  .db $20,2,2,$A0,54,125, $20,2,7,$A0,54,120
-  .db 128,57
-  .db 10,117,46,10
-  .db 0,0
-
-
-
-hiscore:              ;space reserved to store hi-scores
-  .dw 0               ;singleplayer hiscore will be saved here
-  .dw 0,0             ;peaworm hiscore for each peaworm-level
-
-
-  .end
-.end
\ No newline at end of file
diff --git a/makelvl.bat b/makelvl.bat
deleted file mode 100644 (file)
index be95897..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-@echo off\r
-echo Use MAKELVL to compile your Worm levelfile.\r
-echo Format for LEVEL.Z80 is: (always leave .z80)\r
-echo   MAKELVL LEVEL\r
-echo Needs TASM86.EXE and BIN2STR.EXE to compile.\r
-echo.\r
-tasm86 -80 -b %1.z80\r
-bin2str %1.obj 86 Levelfile for Worm .90 by Shiar\r
-del %1.obj\r
-del %1.lst
\ No newline at end of file
diff --git a/wormedit.pas b/wormedit.pas
new file mode 100644 (file)
index 0000000..ee61c0d
--- /dev/null
@@ -0,0 +1,763 @@
+USES CRT;
+
+CONST GAMETYPE:ARRAY[1..8]OF STRING[12] =
+        ('SINGLEPLAYER','PEAWORM','TRON','DEATHMATCH',
+         'FOODMATCH','LINKPLAY','RACE','CTF');
+
+      OBJTYPE:ARRAY[0..3]OF STRING[8] =
+        ('NONE','LINE','FAT LINE','BAR');
+
+      ENDTYPE:ARRAY[-1..0]OF STRING[8] =
+        ('MESSAGE','NONE');
+
+      HEAD86S:STRING[53] =
+        ('**TI86**'+#$1A+#$A+#0+ {HEADER}
+        'Levelfile for Worm 0�92 made with WormEdit'); {COMMENT}
+
+      HEADEDIT = ('WormEdit�92'+#0+'LVL');
+      HEADVERSION = 92;
+
+      B:RECORD
+        HEAD:ARRAY[1..15]OF CHAR;
+        VERSION:BYTE;
+        NAME:STRING[32];
+        LSINGLE,LMULTI,LCTF,LTOTAL:BYTE;
+        LFROM:ARRAY[1..8]OF BYTE;
+        LTO:ARRAY[1..8]OF BYTE;
+        SPRSIZE:BYTE;
+        SPRITE:ARRAY[1..8]OF BYTE;
+       ENDTYPE:INTEGER;
+        ENDDATA:STRING[255];
+      END {B} =
+        (HEAD:HEADEDIT;
+         VERSION:HEADVERSION;
+        NAME:'Custom Worm Level';
+         LSINGLE:0; LMULTI:0; LCTF:0; LTOTAL:0;
+        LFROM:(0,0,0,0,0,0,0,0);
+        LTO:(0,0,0,0,0,0,0,0);
+        SPRSIZE:4;
+        SPRITE:(6*16,15*16,15*16,6*16,0,0,0,0);
+           {01100000
+            11110000
+            11110000
+            01100000}
+         ENDTYPE:0);
+
+
+VAR I,I2:WORD;
+    II,III,I4:SHORTINT;
+    C:CHAR;
+    S:STRING;
+    F,FF:FILE;
+
+    L:ARRAY[1..64]OF RECORD
+      NAME:STRING[32];
+      SIZE:BYTE;
+      PEAS,DELAY:BYTE;
+      GROWTH,BSIZE:BYTE;
+      SPRSIZE:BYTE;
+      SPRITE:ARRAY[1..8]OF BYTE;
+      NRBALLS:BYTE;
+      BALLS:ARRAY[1..32]OF RECORD
+        Y,X,D:BYTE; {Z:%00=right+down, %11=left+up}
+      END; {BALLS}
+      W:ARRAY[1..4]OF RECORD
+        D,Y,X:BYTE;
+      END; {W(ORMS)}
+      FIELDX,FIELDY:BYTE;
+      FLAG1Y,FLAG1X:BYTE;
+      FLAG2Y,FLAG2X:BYTE;
+      NROBJ:BYTE;
+      OBJ:ARRAY[1..32]OF RECORD
+        TYP,X1,Y1,X2,Y2:BYTE;
+      END; {OBJ}
+    END; {L}
+
+    FILENAME:STRING[8];
+
+FUNCTION NR(VALUE:INTEGER):STRING;
+VAR NRSTR:STRING;
+BEGIN
+  STR(VALUE,NRSTR); NR:=NRSTR;
+END; {NR}
+
+FUNCTION EDITMENU(EDITMENUMAX:BYTE):SHORTINT;
+BEGIN
+  REPEAT
+    REPEAT C:=READKEY;
+    UNTIL(C>='1')AND(C<=CHR(EDITMENUMAX+48))OR(C=#27);
+    IF C=#27THEN EDITMENU:=-1 ELSE EDITMENU:=ORD(C)-48;
+  UNTIL ORD(C)<>0;
+END; {EDITMENU}
+
+FUNCTION COMPSIZE:WORD;
+BEGIN
+  I:=$32+B.SPRSIZE+ORD(B.NAME[0])+
+     2*(1+(B.LTO[2]-B.LFROM[2])+(B.LTO[3]-B.LFROM[3]));
+  FOR II:=1TO B.LTOTAL DO INC(I,L[II].SIZE);
+  COMPSIZE:=I;
+END; {COMPSIZE}
+
+PROCEDURE EDITTITLE(BAR:SHORTINT;TITLNAME:STRING);
+BEGIN
+  WINDOW(41,2,80,20); CLRSCR; TEXTCOLOR(15); TEXTBACKGROUND(1);
+  CASE BAR OF
+    1:BEGIN
+      WRITE('LEVELS',' ':40-6); TEXTCOLOR(7); TEXTBACKGROUND(0);
+      IF B.LTOTAL<1THEN WRITELN('NONE PRESENT')ELSE
+        FOR II:=1TO B.LTOTAL DO BEGIN
+          WRITE(II); TEXTCOLOR(3); WRITELN(': '+L[II].NAME); TEXTCOLOR(7);
+        END; {DISP LEVELS}
+    END; {1:SINGLVLS}
+    2:BEGIN
+      WRITE('LEVEL OBJECTS',' ':40-13); TEXTCOLOR(7); TEXTBACKGROUND(0);
+      IF L[II].NROBJ<1THEN WRITELN('NONE')ELSE
+        FOR I:=1TO L[II].NROBJ DO BEGIN
+         WRITE(I); TEXTCOLOR(3); WRITE(': ',OBJTYPE[L[II].OBJ[I].TYP]);
+          WRITE(' (',L[II].OBJ[I].X1,',',L[II].OBJ[I].Y1,')-(');
+          IF L[II].OBJ[I].TYP=3THEN
+            WRITELN(L[II].OBJ[I].X2,',',L[II].OBJ[I].Y1+L[II].OBJ[I].Y2,')')
+            ELSE WRITELN(L[II].OBJ[I].X2,',',L[II].OBJ[I].Y2,')');
+         TEXTCOLOR(7);
+        END; {DISP OBJS}
+    END; {2:SINGLVLS}
+    3:BEGIN
+      WRITE('LEVEL INFO',' ':40-10); TEXTCOLOR(7); TEXTBACKGROUND(0);
+      WRITELN('LEVEL #',II,' MP #',II-B.LSINGLE);
+      WRITELN('LEVEL SIZE: ',L[II].SIZE);
+      IF II<=B.LSINGLE THEN WRITELN('SINGLEPLAYER')ELSE FOR I:=2TO 7DO
+        IF(II-B.LSINGLE>=B.LFROM[I])AND(II-B.LSINGLE<=B.LTO[I])THEN
+         WRITELN(GAMETYPE[I]);
+    END; {3:LEVEL}
+    4:BEGIN
+      WRITE(FILENAME,'.LVL',' ':36-ORD(FILENAME[0])); TEXTCOLOR(7);
+      TEXTBACKGROUND(0); WRITE('FILE VERSION: '); TEXTCOLOR(3);
+      WRITELN(B.VERSION); TEXTCOLOR(7); WRITE('FILE SIZE: '); TEXTCOLOR(3);
+      WRITE(FILESIZE(F)SHR 10); TEXTCOLOR(7); WRITELN('kB');
+      WRITE('COMPILED: '); TEXTCOLOR(3); WRITE(COMPSIZE); TEXTCOLOR(7);
+      WRITE(' BYTES');
+    END; {4:FILE}
+  END; {BAR}
+  WINDOW(1,2,40,20);
+  TEXTBACKGROUND(1); TEXTCOLOR(15); WRITE(TITLNAME,' ':40-ORD(TITLNAME[0]));
+  WINDOW(1,3,40,20); TEXTBACKGROUND(0); CLRSCR;
+END; {EDITTITLE}
+
+PROCEDURE EDITGAME;
+LABEL EDITGAME1,EDITGAME2;
+BEGIN
+  REPEAT
+    EDITTITLE(1,'EDIT GAMETYPES'); TEXTCOLOR(7); WRITE('1: SINGLEPLAYER ');
+    TEXTCOLOR(3); IF B.LSINGLE=0THEN WRITELN('(NO LEVELS)')
+      ELSE WRITELN('(',B.LSINGLE,')');
+    FOR II:=2TO 7DO BEGIN
+      TEXTCOLOR(14); WRITE(II); TEXTCOLOR(7); WRITE(': '+GAMETYPE[II],' ');
+      TEXTCOLOR(3); IF B.LFROM[II]=0THEN WRITELN('(NO LEVELS)')
+        ELSE WRITELN('(',B.LFROM[II]+B.LSINGLE,'-',B.LTO[II]+B.LSINGLE,')');
+    END; {MULTIP}
+    TEXTCOLOR(7); WRITE('8: CTF '); TEXTCOLOR(3);
+    IF B.LCTF=0THEN WRITELN('(NO LEVELS)')ELSE WRITELN('(',B.LCTF,')');
+     TEXTCOLOR(7); WRITELN;III:=EDITMENU(8);
+
+    IF III>1THEN BEGIN
+EDITGAME1:
+      WRITELN('ENTER NEW STARTING LEVEL FOR '+GAMETYPE[III]); WRITE('> ');
+      READLN(B.LFROM[III]); IF B.LFROM[III]>B.LMULTI THEN BEGIN
+        TEXTCOLOR(15); WRITE('THAT LEVEL DOES NOT EXIST! ');
+        TEXTCOLOR(7); WRITELN('JUST ',B.LMULTI,' LEVELS PRESENT.');
+        GOTO EDITGAME1;
+      END; {TOO MUCH}
+      IF B.LFROM[III]=0THEN WRITELN('NO LEVELS FOR THIS GAMETYPE.') {NO LVLS}
+      ELSE BEGIN
+EDITGAME2:
+        WRITE('ENTER LAST LEVEL #> '); READLN(B.LTO[III]);
+        IF B.LTO[III]<B.LFROM[III]THEN BEGIN
+          WRITELN('LAST LEVEL MUST BE BEHIND THE FIRST LEVEL.'); GOTO EDITGAME2;
+        END; {ERROR}
+        IF B.LTO[III]>B.LMULTI THEN BEGIN
+          TEXTCOLOR(15); WRITE('THAT LEVEL DOES NOT (YET) EXIST! ');
+          TEXTCOLOR(7); WRITELN('JUST ',B.LMULTI,' LEVELS PRESENT.');
+          GOTO EDITGAME2;
+        END; {TOO MUCH}
+      END; {ASK LTO}
+    END; {HANDLE}
+  UNTIL III=-1; III:=0;
+END; {EDITGAME}
+
+PROCEDURE EDITOBJ;
+LABEL EDITOBJ1;
+BEGIN
+  REPEAT
+    EDITTITLE(2,'EDIT OBJECT #'+NR(I)+' IN LEVEL '+NR(II));
+    TEXTCOLOR(14); WRITE('1'); TEXTCOLOR(7); WRITE(': OBJECT TYPE ');
+    III:=L[II].OBJ[I].TYP; TEXTCOLOR(3); WRITELN('(',III,')');
+    IF III<>0THEN BEGIN
+      TEXTCOLOR(14); WRITE('2'); TEXTCOLOR(7); WRITE(': OBJECT BEGIN ');
+      TEXTCOLOR(3); WRITELN('(',L[II].OBJ[I].X1,',',L[II].OBJ[I].Y1,')');
+      TEXTCOLOR(14); WRITE('3'); TEXTCOLOR(7); WRITE(': OBJECT END ');
+      TEXTCOLOR(3); IF L[II].OBJ[I].TYP=3THEN
+        WRITELN('(',L[II].OBJ[I].X2,',',L[II].OBJ[I].Y1+L[II].OBJ[I].Y2,')')
+        ELSE WRITELN('(',L[II].OBJ[I].X2,',',L[II].OBJ[I].Y2,')');
+    END; {OBJECT PROPERTIES}
+    WRITELN; TEXTCOLOR(7); IF III<>0THEN III:=EDITMENU(3)ELSE III:=EDITMENU(1);
+    CASE III OF
+      1:BEGIN
+EDITOBJ1:
+        WRITELN('ENTER OBJECT TYPE');
+        TEXTCOLOR(8); FOR I4:=0TO 3DO WRITE(I4,': ',OBJTYPE[I4],'    ');
+        TEXTCOLOR(7); WRITELN; WRITE('> '); READLN(L[II].OBJ[I].TYP);
+        IF L[II].OBJ[I].TYP>3THEN BEGIN
+         WRITELN('INVALID TYPE!'); GOTO EDITOBJ1;
+       END; {INVALID}
+        TEXTCOLOR(8); WRITELN('SCREEN=(2,2)-(',L[II].FIELDX-2,',',L[II].FIELDY-2,
+         '); CENTER=(',(L[II].FIELDX-1)SHR 1,',',(L[II].FIELDY-1)SHR 1,')');
+       TEXTCOLOR(7); WRITE('ENTER X1> '); READLN(L[II].OBJ[I].X1);
+        WRITE('ENTER Y1> '); READLN(L[II].OBJ[I].Y1);
+        WRITE('ENTER X2> '); READLN(L[II].OBJ[I].X2);
+        WRITE('ENTER Y2> '); READLN(L[II].OBJ[I].Y2);
+        IF L[II].OBJ[I].TYP=3THEN
+         L[II].OBJ[I].Y2:=L[II].OBJ[I].Y2-L[II].OBJ[I].Y1;
+      END; {TYPE}
+      2:BEGIN
+        TEXTCOLOR(8); WRITELN('SCREEN=(2,2)-(',L[II].FIELDX-2,',',L[II].FIELDY-2,
+         '); CENTER=(',(L[II].FIELDX-1)SHR 1,',',(L[II].FIELDY-1)SHR 1,')');
+       TEXTCOLOR(7); WRITE('ENTER BEGIN X> '); READLN(L[II].OBJ[I].X1);
+        WRITE('ENTER BEGIN Y> '); READLN(L[II].OBJ[I].Y1);
+      END; {BEGIN}
+      3:BEGIN
+        TEXTCOLOR(8); WRITELN('SCREEN=(2,2)-(',L[II].FIELDX-2,',',L[II].FIELDY-2,
+         '); CENTER=(',(L[II].FIELDX-1)SHR 1,',',(L[II].FIELDY-1)SHR 1,')');
+       TEXTCOLOR(7); WRITE('ENTER END X> '); READLN(L[II].OBJ[I].X2);
+        WRITE('ENTER END Y> '); READLN(L[II].OBJ[I].Y2);
+        IF L[II].OBJ[I].TYP=3THEN
+         L[II].OBJ[I].Y2:=L[II].OBJ[I].Y2-L[II].OBJ[I].Y1;
+      END; {END}
+    END; {HANDLE}
+  UNTIL III=-1; III:=0;
+END; {EDITOBJ}
+
+PROCEDURE EDITOBJS;
+LABEL EDITOBJS1,EDITOBJS2;
+BEGIN
+  REPEAT
+    EDITTITLE(2,'EDIT LEVEL OBJECTS');
+    TEXTCOLOR(14); WRITE('1'); TEXTCOLOR(7); WRITELN(': CREATE OBJECT');
+    TEXTCOLOR(14); WRITE('2'); TEXTCOLOR(7); WRITELN(': EDIT OBJECT');
+    TEXTCOLOR(14); WRITE('3'); TEXTCOLOR(7); WRITELN(': DELETE OBJECT');
+    WRITELN;
+    III:=EDITMENU(3);
+
+    CASE III OF
+      1:BEGIN
+        INC(L[II].NROBJ); I:=L[II].NROBJ; EDITOBJ;
+      END; {CREATE}
+      2:BEGIN
+EDITOBJS1:
+        WRITE('EDIT WHICH OBJECT> '); READLN(I);
+       IF I>L[II].NROBJ THEN BEGIN
+          WRITELN('JUST ',L[II].NROBJ,' OBJECTS PRESENT!');
+          GOTO EDITOBJS1;
+        END; {DNOT EXIST}
+        IF I<>0THEN EDITOBJ;
+      END; {PEAS}
+      3:BEGIN
+EDITOBJS2:
+        WRITE('DELETE WHICH OBJECT> '); READLN(I);
+        IF I>L[II].NROBJ THEN BEGIN
+          WRITELN('I''M SORRY BUT THAT OBJECT DOES NOT EXIST');
+          GOTO EDITOBJS2;
+        END; {ERROR}
+        IF I<>0THEN BEGIN
+          WRITE('PLEASE CONFIRM OBJECT TO '); TEXTCOLOR(15); WRITE('REMOVE');
+          TEXTCOLOR(7); WRITE('> '); READLN(I4);
+          IF I=I4 THEN BEGIN
+           DEC(L[II].NROBJ); FOR I:=I4 TO L[II].NROBJ DO L[II].OBJ[I]:=L[II].OBJ[I+1];
+          END; {OK}
+        END; {SMTN}
+      END; {DELETE}
+    END; {HANDLE}
+  UNTIL III=-1; III:=0;
+END; {EDITOBJS}
+
+FUNCTION BYTE2STR(SPRITE,SPRSIZE:BYTE):STRING;
+VAR SPRTEMP:STRING[8];
+    SPRTEMP2:BYTE;
+BEGIN
+  SPRTEMP:='';
+  FOR SPRTEMP2:=1TO 8-SPRSIZE DO SPRITE:=SPRITE SHR 1;
+  FOR SPRTEMP2:=9-SPRSIZE TO 8DO BEGIN
+    IF SPRITE MOD 2=1THEN SPRTEMP:='X'+SPRTEMP ELSE SPRTEMP:='�'+SPRTEMP;
+    SPRITE:=SPRITE SHR 1;
+  END;
+  BYTE2STR:=SPRTEMP;
+END; {BYTE2STR}
+
+FUNCTION STR2BYTE(SPRITE:STRING):BYTE;
+VAR SPRTEMP,SPRTEMP2:BYTE;
+BEGIN
+  SPRTEMP:=0; SPRTEMP2:=1;
+  FOR SPRTEMP2:=1TO LENGTH(SPRITE)DO
+    IF SPRITE[SPRTEMP2]='1'THEN INC(SPRTEMP,1SHL(8-SPRTEMP2));
+  STR2BYTE:=SPRTEMP;
+END; {STR2BYTE}
+
+PROCEDURE EDITSPR;
+BEGIN
+  REPEAT
+    EDITTITLE(0,'EDIT SPRITE');
+    TEXTCOLOR(14); WRITE('1'); TEXTCOLOR(7); WRITE(': SPRITE SIZE ');
+      TEXTCOLOR(3); IF L[II].SPRSIZE=0THEN WRITELN('(DEFAULT)')
+        ELSE WRITELN('(',L[II].SPRSIZE,')');
+    IF L[II].SPRSIZE=0THEN BEGIN
+      TEXTCOLOR(14); WRITE('2'); TEXTCOLOR(7); WRITE(': EDIT SPRITE');
+      TEXTCOLOR(3); WRITELN(' (DEFAULT)');
+    END {DEF SPR} ELSE FOR I:=1TO L[II].SPRSIZE DO BEGIN
+      TEXTCOLOR(14); WRITE(I+1); TEXTCOLOR(7); WRITE(': EDIT '); TEXTCOLOR(3);
+      WRITELN(BYTE2STR(L[II].SPRITE[I],L[II].SPRSIZE));
+    END; {DISP SPRITE}
+    TEXTCOLOR(7); WRITELN; III:=EDITMENU(1+L[II].SPRSIZE);
+
+    IF III=1THEN BEGIN
+      WRITE('ENTER NEW SPRITE SIZE (MAX.HEIGHT/WIDTH)> '); READLN(I);
+      IF I>L[II].SPRSIZE THEN FOR I4:=L[II].SPRSIZE+1TO I DO
+       L[II].SPRITE[I4]:=0;
+      L[II].SPRSIZE:=I;
+    END {SIZE} ELSE IF III>1THEN BEGIN
+      WRITELN('ENTER NEW LINE #',III-1,' OF SPRITE'); TEXTCOLOR(8);
+      WRITE('(ex: 100101 = X��X�X)'); TEXTCOLOR(7); WRITE('> ');
+      READLN(S); L[II].SPRITE[III-1]:=STR2BYTE(S);
+    END; {APP}
+  UNTIL III=-1; III:=0;
+END; {EDITSPR}
+
+PROCEDURE EDITWORMS;
+BEGIN
+  REPEAT
+    EDITTITLE(0,'EDIT WORMS IN LEVEL #'+NR(II));
+    IF II>B.LSINGLE THEN III:=4 ELSE III:=1;
+    FOR III:=1TO III DO BEGIN
+      TEXTCOLOR(14); WRITE(III SHL 1-1); TEXTCOLOR(7);
+      WRITE(': WORM #',III,' DIRECTION '); TEXTCOLOR(3);
+      WRITELN('(',L[II].W[III].D,')');
+      TEXTCOLOR(14); WRITE(III SHL 1); TEXTCOLOR(7);
+      WRITE(': WORM #',III,' POSITION '); TEXTCOLOR(3);
+      WRITELN('(',L[II].W[III].X,',',L[II].W[III].Y,')');
+    END; {}
+    TEXTCOLOR(7); WRITELN;
+    IF III=4THEN III:=EDITMENU(8)ELSE III:=EDITMENU(2);
+
+    CASE III OF
+      1,3,5,7:BEGIN
+        WRITELN('ENTER WORM #',(III+1)SHR 1,' STARTING DIRECTION'); TEXTCOLOR(8);
+       WRITELN('(0=down; 64=right; 128=up; 192=left)');
+       TEXTCOLOR(7); WRITE('> '); READLN(I); L[II].W[(III+1)SHR 1].D:=I;
+      END; {DIR}
+      2,4,6,8:BEGIN
+        WRITELN('ENTER WORM #',III SHR 1,' BEGIN X-POSITION'); TEXTCOLOR(8);
+       WRITELN('(screen = 2-',L[II].FIELDX-2,'; center = ',L[II].FIELDX DIV 2);
+       TEXTCOLOR(7); WRITE('> '); READLN(I); L[II].W[III SHR 1].X:=I;
+        WRITELN('ENTER WORM #',III SHR 1,' BEGIN Y-POSITION'); TEXTCOLOR(8);
+       WRITELN('(screen = 2-',L[II].FIELDY-2,'; center = ',L[II].FIELDY DIV 2);
+       TEXTCOLOR(7); WRITE('> '); READLN(I); L[II].W[III SHR 1].Y:=I;
+      END; {POS}
+    END; {HANDLE}
+  UNTIL III=-1; III:=0;
+END; {EDITWORMS}
+
+PROCEDURE EDITLEVEL;
+BEGIN
+  REPEAT
+    L[II].SIZE:=12+L[II].NRBALLS+L[II].SPRSIZE+L[II].NROBJ*5;
+      IF II>B.LSINGLE THEN INC(L[II].SIZE,9);
+    EDITTITLE(3,'EDIT LEVEL #'+NR(II));
+    TEXTCOLOR(14); WRITE('1'); TEXTCOLOR(7); WRITE(': DESCRIPTION ');
+      TEXTCOLOR(3); WRITELN('(',L[II].NAME,')');
+    TEXTCOLOR(14); WRITE('2'); TEXTCOLOR(7); WRITE(': NUMBER OF PEAS ');
+      TEXTCOLOR(3); WRITELN('(',L[II].PEAS,')');
+    TEXTCOLOR(14); WRITE('3'); TEXTCOLOR(7); WRITE(': GAME DELAY ');
+      TEXTCOLOR(3); WRITELN('(',L[II].DELAY,')');
+    TEXTCOLOR(14); WRITE('4'); TEXTCOLOR(7); WRITE(': GROWTH ');
+      TEXTCOLOR(3); WRITELN('(',L[II].GROWTH,'+',L[II].BSIZE,')');
+    TEXTCOLOR(14); WRITE('5'); TEXTCOLOR(7); WRITE(': SPRITE ');
+      TEXTCOLOR(3); IF L[II].SPRSIZE=0THEN WRITELN('(DEFAULT)')
+                    ELSE WRITELN('(',L[II].SPRSIZE,')');
+    TEXTCOLOR(14); WRITE('6'); TEXTCOLOR(7); WRITE(': BOUNCY BALLS ');
+      TEXTCOLOR(3); WRITELN('(',L[II].NRBALLS,')');
+    TEXTCOLOR(14); WRITE('7'); TEXTCOLOR(7); WRITE(': WORMS '); TEXTCOLOR(3);
+      IF II>B.LSINGLE THEN BEGIN
+        WRITELN('(',L[II].W[1].D,';',L[II].W[2].D,';',L[II].W[3].D,';',L[II].W[4].D,')');
+      END {FOUR WORMS} ELSE
+       WRITELN('(',L[II].W[1].X,',',L[II].W[1].Y,':',L[II].W[1].D,')');
+    TEXTCOLOR(14); WRITE('8'); TEXTCOLOR(7); WRITE(': FIELD SIZE ');
+      TEXTCOLOR(3); WRITELN('(',L[II].FIELDX,',',L[II].FIELDY,')');
+    TEXTCOLOR(14); WRITE('9'); TEXTCOLOR(7); WRITE(': OBJECTS ');
+      TEXTCOLOR(3); WRITELN('(',L[II].NROBJ,')');
+    TEXTCOLOR(7); WRITELN;
+    III:=EDITMENU(9);
+
+    CASE III OF
+      1:BEGIN
+        WRITELN('ENTER DESCRIPTION FOR THIS LEVEL'); WRITE('> ');
+       READLN(S); IF S<>''THEN L[II].NAME:=S;
+      END; {DESCR}
+      2:BEGIN
+        WRITE('ENTER TOTAL NUMBER OF PEAS> ');
+       READLN(I); L[II].PEAS:=I;
+      END; {PEAS}
+      3:BEGIN
+        WRITE('ENTER NEW DELAY '); TEXTCOLOR(8); WRITE('(0=fastest; 4=def.)');
+       TEXTCOLOR(7); WRITE('> '); READLN(I); L[II].DELAY:=I;
+      END; {DELAY}
+      4:BEGIN
+        WRITE('ENTER GROWTH PER PEA '); TEXTCOLOR(8); WRITE('(15=default)');
+       TEXTCOLOR(7); WRITE('> '); READLN(I); L[II].GROWTH:=I;
+        WRITE('ENTER WORM BEGIN SIZE '); TEXTCOLOR(8); WRITE('(15=default)');
+       TEXTCOLOR(7); WRITE('> '); READLN(I); L[II].BSIZE:=I;
+      END; {GROWTH}
+      5:EDITSPR;
+      7:EDITWORMS;
+      8:BEGIN
+        WRITELN('ENTER FIELD WIDTH'); TEXTCOLOR(8);
+       WRITE('(128=screen-width; 255=max.)');
+       TEXTCOLOR(7); WRITE('> '); READLN(I); L[II].FIELDX:=BYTE(I);
+        WRITELN('ENTER FIELD HEIGHT'); TEXTCOLOR(8);
+       WRITE('(57=screen-height 255=max.)');
+       TEXTCOLOR(7); WRITE('> '); READLN(I); L[II].FIELDY:=BYTE(I);
+      END; {FIELD}
+      9:EDITOBJS;
+    END; {HANDLE}
+  UNTIL III=-1; III:=0;
+END; {EDITLEVEL}
+
+PROCEDURE EDITLVL;
+LABEL EDITHLVL1,EDITHLVL2;
+BEGIN
+  REPEAT
+    EDITTITLE(1,'EDIT LEVELS');
+    TEXTCOLOR(14); WRITE('1'); TEXTCOLOR(7); WRITELN(': EDIT LEVEL');
+    TEXTCOLOR(14); WRITE('2'); TEXTCOLOR(7); WRITELN(': DELETE LEVEL');
+    TEXTCOLOR(14); WRITE('3'); TEXTCOLOR(7); WRITELN(': CREATE SINGLEPLAYER LEVEL');
+    TEXTCOLOR(14); WRITE('4'); TEXTCOLOR(7); WRITELN(': CREATE MULTIPLAYER LEVEL');
+    TEXTCOLOR(7); WRITE('5'); TEXTCOLOR(7); WRITELN(': CREATE CTF LEVEL');
+    TEXTCOLOR(7); WRITELN; III:=EDITMENU(4);
+
+    CASE III OF
+      1:BEGIN
+EDITHLVL1:
+        WRITE('EDIT WHICH LEVEL> '); READLN(II);
+        IF II>B.LTOTAL THEN BEGIN
+          WRITELN('THAT LEVEL DOES NOT EXIST!'); GOTO EDITHLVL1;
+        END; {ERROR}
+       IF II<>0THEN EDITLEVEL;
+      END; {EDIT}
+      2:BEGIN
+EDITHLVL2:
+        WRITE('DELETE WHICH LEVEL> '); READLN(II);
+        IF II>B.LTOTAL THEN BEGIN
+          WRITELN('YOU CANNOT DELETE A LEVEL THAT DOES NOT EXIST!');
+          GOTO EDITHLVL2;
+       END; {ERROR}
+       IF II<>0THEN BEGIN
+         WRITE('PLEASE CONFIRM LEVEL TO '); TEXTCOLOR(15); WRITE('DELETE');
+         TEXTCOLOR(7); WRITE('> '); READLN(I);
+         IF I=II THEN BEGIN
+           IF I<=B.LSINGLE THEN DEC(B.LSINGLE)ELSE
+             IF I<=B.LMULTI+B.LSINGLE THEN DEC(B.LMULTI)ELSE
+               DEC(B.LCTF);
+           DEC(B.LTOTAL); FOR I:=II TO B.LTOTAL DO L[I]:=L[I+1];
+           FOR I:=2TO 7DO BEGIN
+             IF B.LTO[I]>B.LMULTI THEN B.LTO[I]:=B.LMULTI;
+             IF B.LFROM[I]>B.LTO[I]THEN B.LFROM[I]:=B.LTO[I];
+            END; {CHECK}
+         END; {OK}
+       END; {SMTN}
+      END; {DELETE}
+
+      3:BEGIN
+        INC(B.LSINGLE); INC(B.LTOTAL); II:=B.LSINGLE;
+       FOR I:=B.LTOTAL DOWNTO II+1DO L[I]:=L[I-1];
+       L[II].NAME:='Level #'+NR(II);
+       L[II].PEAS:=8; L[II].DELAY:=4; L[II].GROWTH:=15; L[II].BSIZE:=15;
+        L[II].SPRSIZE:=0; L[II].NRBALLS:=0; L[II].W[1].D:=0; L[II].W[1].X:=63;
+       L[II].W[1].Y:=2; L[II].FIELDX:=128; L[II].FIELDY:=57; L[II].NROBJ:=0;
+       EDITLEVEL;
+      END; {CREATE SP}
+      4:BEGIN
+        FOR I:=2TO 7DO IF B.LTO[I]=B.LMULTI THEN BEGIN
+         INC(B.LTO[I]); IF B.LFROM[I]=0THEN INC(B.LFROM[I]);
+        END; {}
+       INC(B.LTOTAL); INC(B.LMULTI); II:=B.LSINGLE+B.LMULTI;
+       FOR I:=B.LTOTAL DOWNTO II+1DO L[I]:=L[I-1];
+       L[II].NAME:='Arena #'+NR(B.LMULTI);
+       L[II].DELAY:=4; L[II].GROWTH:=15; L[II].BSIZE:=15; L[II].SPRSIZE:=0;
+       L[II].W[1].D:=$40; L[II].W[1].Y:=28; L[II].W[1].X:=2;
+       L[II].W[2].D:=$C0; L[II].W[2].Y:=28; L[II].W[2].X:=125;
+       L[II].W[3].D:=$00; L[II].W[3].Y:=02; L[II].W[3].X:=63;
+       L[II].W[4].D:=$80; L[II].W[4].Y:=54; L[II].W[4].X:=63;
+       L[II].NRBALLS:=0; L[II].FIELDX:=128; L[II].FIELDY:=57;
+       L[II].NROBJ:=0; EDITLEVEL;
+      END; {CREATE MP}
+    END; {HANDLE}
+  UNTIL III=-1; III:=0;
+END; {EDITLVL}
+
+PROCEDURE EDITDSPR;
+BEGIN
+  REPEAT
+    EDITTITLE(0,'EDIT DEFAULT SPRITE');
+    TEXTCOLOR(14); WRITE('1'); TEXTCOLOR(7); WRITE(': SPRITE SIZE ');
+      TEXTCOLOR(3); WRITELN('(',B.SPRSIZE,')');
+    FOR I:=1TO B.SPRSIZE DO BEGIN
+      TEXTCOLOR(14); WRITE(I+1); TEXTCOLOR(7); WRITE(': EDIT '); TEXTCOLOR(3);
+      WRITELN(BYTE2STR(B.SPRITE[I],B.SPRSIZE));
+    END; {DISP SPRITE}
+    TEXTCOLOR(7); WRITELN; III:=EDITMENU(1+B.SPRSIZE);
+
+    IF III=1THEN BEGIN
+      WRITELN('ENTER THE DEFAULT SPRITE SIZE'); TEXTCOLOR(8);
+      WRITE('(1-8; can be changed per level)'); TEXTCOLOR(7); WRITE('> ');
+      READLN(I); IF(I>0)AND(I<=8)THEN BEGIN
+        IF I>B.SPRSIZE THEN FOR I4:=B.SPRSIZE+1TO I DO B.SPRITE[I4]:=0;
+        B.SPRSIZE:=I;
+      END; {OK}
+    END {SIZE} ELSE IF III>1THEN BEGIN
+      WRITELN('ENTER NEW LINE #',III-1,' OF SPRITE'); TEXTCOLOR(8);
+      WRITE('(ex: 100101 = X��X�X)'); TEXTCOLOR(7); WRITE('> ');
+      READLN(S); B.SPRITE[III-1]:=STR2BYTE(S);
+    END; {APP}
+  UNTIL III=-1; III:=0;
+END; {EDITDSPR}
+
+PROCEDURE EDITSPEND;
+BEGIN
+  REPEAT
+    EDITTITLE(0,'SINGLEPLAYER ENDING');
+    TEXTCOLOR(14); WRITE('1'); TEXTCOLOR(7); WRITE(': END TYPE ');
+      TEXTCOLOR(3); WRITELN(' (',ENDTYPE[B.ENDTYPE],')'); TEXTCOLOR(14);
+    CASE B.ENDTYPE OF
+      -1:BEGIN
+        WRITE('2'); TEXTCOLOR(7); WRITE(': EDIT MESSAGE');
+        TEXTCOLOR(3); WRITE(' (',COPY(B.ENDDATA,1,18));
+        IF LENGTH(B.ENDDATA)>18THEN WRITELN('...)')ELSE WRITELN(')');
+      END; {MSG}
+    END; {TYPE} TEXTCOLOR(7); WRITELN; III:=EDITMENU(2);
+    CASE III OF
+      1:BEGIN
+        WRITELN('ENTER NEW END TYPE:'); TEXTCOLOR(8);
+        FOR II:=0TO 1DO WRITE(II,': ',ENDTYPE[-II],'  '); WRITELN; TEXTCOLOR(7);
+       WRITE('> '); READLN(II); IF(II<=1)AND(II>=0)THEN B.ENDTYPE:=-II;
+        IF II=1THEN B.ENDDATA:='Congratulations!!';
+      END; {TITLE}
+      2:BEGIN
+        CASE B.ENDTYPE OF
+          -1:BEGIN
+            WRITE('ENTER NEW END MESSAGE '); TEXTCOLOR(8);
+           WRITELN('(max 255 chars)'); WRITE('> ');
+            READLN(S); IF S<>''THEN B.ENDDATA:=S;
+          END; {MSG}
+        END; {TYPE}
+      END; {EDIT}
+    END; {HANDLE}
+  UNTIL III=-1; III:=0;
+END; {EDITSPEND}
+
+
+PROCEDURE EDITMAIN;
+BEGIN
+  REPEAT
+    S:=''; FOR II:=1TO LENGTH(B.NAME)DO S:=S+UPCASE(B.NAME[II]); EDITTITLE(4,S);
+    TEXTCOLOR(14); WRITE('1'); TEXTCOLOR(7); WRITELN(': EDIT TITLE');
+    TEXTCOLOR(14); WRITE('2'); TEXTCOLOR(7); WRITE(': DEFAULT SPRITE');
+      TEXTCOLOR(3); WRITELN(' (',B.SPRSIZE,')');
+    TEXTCOLOR(14); WRITE('3'); TEXTCOLOR(7); WRITELN(': GAME TYPES');
+    TEXTCOLOR(14); WRITE('4'); TEXTCOLOR(7); WRITE(': SP ENDING');
+      TEXTCOLOR(3); WRITELN(' (',ENDTYPE[B.ENDTYPE],')');
+    TEXTCOLOR(14); WRITE('5'); TEXTCOLOR(7); WRITE(': LEVELS');
+      TEXTCOLOR(3); WRITELN(' (',B.LTOTAL,')');
+    TEXTCOLOR(7); WRITELN; III:=EDITMENU(5);
+    CASE III OF
+      1:BEGIN
+        WRITELN('ENTER NEW TITLE FOR THIS LEVELFILE ');
+       TEXTCOLOR(8); WRITE('enter=don''t alter; max. length 32 chars ');
+       TEXTCOLOR(7); WRITE('> '); READLN(S); IF S<>''THEN B.NAME:=S;
+      END; {TITLE}
+      2:EDITDSPR;
+      3:EDITGAME;
+      4:EDITSPEND;
+      5:EDITLVL;
+    END; {HANDLE}
+  UNTIL III=-1; III:=0;
+END; {EDITMAIN}
+
+PROCEDURE OPENFILE;
+BEGIN
+  ASSIGN(F,FILENAME+'.LVL'); {$I-} RESET(F,1); {$I+} IF IORESULT=0THEN BEGIN
+    {$I-} BLOCKREAD(F,B,SIZEOF(B)); BLOCKREAD(F,L,SIZEOF(L)); {$I+}
+    IF(IORESULT<>0)OR(B.HEAD<>HEADEDIT)THEN BEGIN
+      TEXTCOLOR(15); WRITE('WARNING!! '); TEXTCOLOR(7);
+      WRITELN('ERROR READING LEVEL FILE!');
+      CLOSE(F); HALT;
+    END; {ERROR}
+    IF B.VERSION<>HEADVERSION THEN BEGIN
+      WRITELN('CAN''T READ FILE VERSION ',B.VERSION,'.'); CLOSE(F); HALT;
+    END; {VERSION}
+  END; {OPEN EXISTING FILE}
+END; {OPENFILE}
+
+PROCEDURE FILESAVE;
+BEGIN
+  ASSIGN(F,FILENAME+'.LVL'); REWRITE(F,1);
+  BLOCKWRITE(F,B,SIZEOF(B)); BLOCKWRITE(F,L,SIZEOF(L)); CLOSE(F);
+END; {FILESAVE}
+
+PROCEDURE FILECOMP;
+VAR ISTACK:WORD;
+BEGIN
+  ASSIGN(FF,FILENAME+'.86S'); REWRITE(FF,1);
+
+  BLOCKWRITE(FF,HEAD86S[1],ORD(HEAD86S[0])); {86S-HEADER}
+  ISTACK:=$12+6+B.SPRSIZE+ORD(B.NAME[0])+24+2+
+    2*(1+(B.LTO[2]-B.LFROM[2])+(B.LTO[3]-B.LFROM[3]));
+  FOR II:=1TO B.LTOTAL DO INC(ISTACK,L[II].SIZE);
+  BLOCKWRITE(FF,ISTACK,2); {FILE LENGTH (x+$12)}
+  I:=$000C; BLOCKWRITE(FF,I,2); {STRING ID}
+  DEC(ISTACK,$10); BLOCKWRITE(FF,ISTACK,2); {DATA LENGTH (x+2)}
+
+  I:=$080C; BLOCKWRITE(FF,I,2); {STRING ID}
+  S:='wormlvl1'; BLOCKWRITE(FF,S[1],8); {PRGNAME}
+  BLOCKWRITE(FF,ISTACK,2); {DATA LENGTH (x+2)}
+  DEC(ISTACK,2); BLOCKWRITE(FF,ISTACK,2); {PROG LENGTH (x)}
+
+  C:='w'; BLOCKWRITE(FF,C,1); {WORM ID}
+  I:=92; BLOCKWRITE(FF,I,1); {VERSION}
+  BLOCKWRITE(FF,B.NAME[0],ORD(B.NAME[0])+1); {TITLE}
+  I:=1+B.SPRSIZE+2; FOR II:=1TO B.LTOTAL DO I:=I+L[II].SIZE;
+  BLOCKWRITE(FF,I,2); {SIZE}
+
+  I2:=0; I:=$F401+B.SPRSIZE;
+  IF B.LSINGLE=0THEN BLOCKWRITE(FF,I2,2)ELSE BEGIN
+    BLOCKWRITE(FF,I,2); FOR II:=1TO B.LSINGLE DO INC(I,L[II].SIZE);
+  END; {SINGLLVLS} INC(I,2);
+  ISTACK:=I; FOR II:=2TO 7DO BEGIN
+    I:=ISTACK; IF B.LFROM[II]=0THEN I:=0 ELSE
+      FOR III:=B.LSINGLE TO B.LSINGLE+B.LFROM[II]-2DO
+       INC(I,L[III].SIZE);
+    BLOCKWRITE(FF,I,2);
+  END; {LOC}
+  FOR II:=B.LSINGLE+B.LMULTI+1TO B.LTOTAL DO INC(ISTACK,L[II].SIZE);
+  I:=0; IF B.LCTF=0THEN BLOCKWRITE(FF,I,2)ELSE BLOCKWRITE(FF,ISTACK,2);
+
+  BLOCKWRITE(FF,B.LSINGLE,1);
+  FOR II:=2TO 7DO BEGIN
+    IF B.LFROM[II]=0THEN I:=0 ELSE I:=B.LTO[II]-B.LFROM[II]+1;
+    BLOCKWRITE(FF,I,1);
+  END; {NR}
+  BLOCKWRITE(FF,B.LCTF,1);
+
+  BLOCKWRITE(FF,B.SPRSIZE,1);
+  BLOCKWRITE(FF,B.SPRITE,B.SPRSIZE);
+
+  FOR II:=1TO B.LSINGLE DO BEGIN
+    BLOCKWRITE(FF,L[II].PEAS,1);
+    BLOCKWRITE(FF,L[II].DELAY,1);
+    BLOCKWRITE(FF,L[II].GROWTH,1);
+    BLOCKWRITE(FF,L[II].BSIZE,1);
+    BLOCKWRITE(FF,L[II].SPRSIZE,1);
+    BLOCKWRITE(FF,L[II].SPRITE,L[II].SPRSIZE);
+    BLOCKWRITE(FF,L[II].NRBALLS,1);
+    BLOCKWRITE(FF,L[II].BALLS,L[II].NRBALLS*3);
+    BLOCKWRITE(FF,L[II].W[1].D,3); {D,X,Y}
+    BLOCKWRITE(FF,L[II].FIELDX,2); {FIELDX,FIELDY}
+    FOR I:=1TO L[II].NROBJ DO BEGIN
+      BLOCKWRITE(FF,L[II].OBJ[I].TYP,5);
+    END; {OBJS}
+    I:=0; BLOCKWRITE(FF,I,1); {LVL END}
+  END; {LEVELS SINGLEPL}
+
+  I:=255; BLOCKWRITE(FF,I,1); {END}
+  I:=$C9; BLOCKWRITE(FF,I,1); {RET}
+
+  FOR II:=B.LSINGLE+1TO B.LSINGLE+B.LMULTI DO BEGIN
+    BLOCKWRITE(FF,L[II].PEAS,1);
+    BLOCKWRITE(FF,L[II].DELAY,1);
+    BLOCKWRITE(FF,L[II].GROWTH,1);
+    BLOCKWRITE(FF,L[II].BSIZE,1);
+    BLOCKWRITE(FF,L[II].SPRSIZE,1);
+    BLOCKWRITE(FF,L[II].SPRITE,L[II].SPRSIZE);
+    BLOCKWRITE(FF,L[II].NRBALLS,1);
+    BLOCKWRITE(FF,L[II].BALLS,L[II].NRBALLS*3);
+    BLOCKWRITE(FF,L[II].W[1].D,3*4); {D,X,Y}
+    BLOCKWRITE(FF,L[II].FIELDX,2); {FIELDX,FIELDY}
+    FOR I:=1TO L[II].NROBJ DO BEGIN
+      BLOCKWRITE(FF,L[II].OBJ[I].TYP,5);
+    END; {OBJS}
+    I:=0; BLOCKWRITE(FF,I,1); {LVL END}
+  END; {LEVELS MULTIPL}
+
+  I:=0; FOR II:=1TO 1+(B.LTO[2]-B.LFROM[2])+(B.LTO[3]-B.LFROM[3])DO
+    BLOCKWRITE(FF,I,2); {HI}
+
+  SEEK(FF,$37); I2:=0; I:=0;
+  REPEAT INC(I,I2); BLOCKREAD(FF,I2,1,ISTACK); UNTIL ISTACK<>1;
+  BLOCKWRITE(FF,I,2); {CHECKSUM}
+END; {FILECOMP}
+
+PROCEDURE EDITQUIT;
+BEGIN
+  REPEAT
+    EDITTITLE(0,'CHOOSE LEVELFILE');
+    TEXTCOLOR(14); WRITE('1'); TEXTCOLOR(7); WRITELN(': COMPILE, SAVE AND QUIT');
+    TEXTCOLOR(14); WRITE('2'); TEXTCOLOR(7); WRITE(': SAVE ');
+      TEXTCOLOR(3); WRITELN(FILENAME,'.LVL');
+    TEXTCOLOR(14); WRITE('3'); TEXTCOLOR(7); WRITELN(': QUIT');
+    TEXTCOLOR(14); WRITE('4'); TEXTCOLOR(7); WRITELN(': CONTINUE EDITING');
+    WRITELN; III:=EDITMENU(4);
+    CASE III OF
+      1:BEGIN
+        FILESAVE; FILECOMP; HALT;
+      END; {COMPILE}
+      2:FILESAVE;
+      3:BEGIN
+        WRITE('REALLY QUIT '); TEXTCOLOR(8); WRITE('[Y/N]'); TEXTCOLOR(7);
+       WRITE('> '); REPEAT C:=READKEY; UNTIL(UPCASE(C)='Y')OR(UPCASE(C)='N');
+        IF UPCASE(C)='N'THEN III:=0;
+      END; {QUIT}
+      4:EDITMAIN;
+    END; {HANDLE}
+  UNTIL III=3; HALT;
+END; {EDITQUIT}
+
+PROCEDURE EDITFILE;
+BEGIN
+  REPEAT
+    EDITTITLE(0,'CHOOSE LEVELFILE');
+    TEXTCOLOR(14); WRITE('1'); TEXTCOLOR(7); WRITELN(': CREATE NEW FILE');
+    TEXTCOLOR(14); WRITE('2'); TEXTCOLOR(7); WRITELN(': EDIT EXISTING');
+    TEXTCOLOR(14); WRITE('3'); TEXTCOLOR(7); WRITE(': EDIT'); TEXTCOLOR(3);
+    WRITELN(' WORMLVL1.LVL'); TEXTCOLOR(7); WRITELN; III:=EDITMENU(3);
+    CASE III OF
+      1:BEGIN
+        WRITE('ENTER FILENAME '); TEXTCOLOR(8); WRITE('(max.8 chars)');
+       TEXTCOLOR(7); WRITE('> '); READLN(FILENAME); EDITMAIN; EDITQUIT;
+      END; {NEW}
+      2:BEGIN
+        WRITE('ENTER LEVELNAME '); TEXTCOLOR(8); WRITE('(w/o extension)');
+       TEXTCOLOR(7); WRITE('> '); READLN(FILENAME); OPENFILE; EDITMAIN;
+       EDITQUIT;
+      END; {EDIT}
+      3:BEGIN
+        FILENAME:='WORMLVL1'; OPENFILE; EDITMAIN; EDITQUIT;
+      END; {WORMLVL1}
+    END; {HANDLE}
+  UNTIL III=-1;
+END; {EDITFILE}
+
+
+BEGIN
+  CLRSCR;
+  TEXTCOLOR(1); WRITE('���������������������������<');
+  TEXTCOLOR(14); WRITE(' WormEdit � ');
+  TEXTCOLOR(15); WRITE(' by SHIAR ');
+  TEXTCOLOR(1); WRITE('>�����������������������������');
+  EDITFILE;
+END.
\ No newline at end of file