]> 4ch.mooo.com Git - 16.git/blob - 16/ted5/TED5.C
ted5 added
[16.git] / 16 / ted5 / TED5.C
1 ////////////////////////////////////////////////////
2 //
3 // TED 5
4 // MultiVideo mode, MultiTile size, MultiMap editor
5 // by John Romero (C) 1991 Id Software
6 //
7 // Development Log:
8 // -------------------------------------------------
9 // Mar 19 91 - Starting this thing! Getting it to
10 //      compile with the JHUFF and MEM stuff.
11 //
12 // Mar 20 91 - Got the whole deal compiling and wrote
13 //      the EGA drawchar routine and got most of
14 //      Dialogs written!
15 //
16 // Mar 25 91 - Forgot some days in there! Got the XMS
17 //      stuff going and started the big initialization
18 //      part. Past init will be lots easier!
19 //
20 // Mar 30 91 - Got map selection and dimensioning and
21 //      allocation done. Added more MENU abilities to
22 //      allow more flexible dialogs.
23 //
24 // Apr  7 91 - Got project initialization done. Got
25 //      tiles into XMS. Wrote XMS routines for all
26 //      memory functions needed.
27 //
28 // Apr 12 91 - FINALLY got the maps loading and saving
29 //      correctly - NO THANKS TO MR.C OVER THERE! You
30 //      see, he can't remember whether his expansion
31 //      routines use the compressed or expanded length
32 //      and that was causing me quite a problem. Got
33 //      it solved and the map shuffling shit works
34 //      PERFECTLY now!  Got tile select in, map stats,
35 //      and other stuff...
36 //
37 // Apr 19 91 - Got all 3 planes working (drawing,etc.)
38 //      TileSelect screens jam...lots of little options
39 //      thrown in... !!! I got my '75 Cougar !!!
40 //
41 // Apr 25 91 - Got map dimension changing done! Fixed
42 //      some small bugs...had a WHOPPER of a fucking
43 //      bug today ... I was overwriting the stack
44 //      when the first background save happened. I'm SURE
45 //      I allocated enough memory -- I don't know...
46 //
47 // Apr 27 91 - Map Edge Select works (for Copy) & now I
48 //      draw a frame around the entire region.
49 //
50 // May 01 91 - Added a nice feature - retaining the Copy
51 //      buffer wherever it may get toasted. Used XMS so
52 //      I didn't chew mainmem. Also made it so you can
53 //      turn the plane READ/WRITEs ON/OFF (obvious advantage).
54 //      Got Copy/Paste from everywhere with FloatingPaste!
55 //
56 // May 03 91 - Got entering values for infoplane stuff & all
57 //      that shit encompasses. Trying to get a cursor drawn
58 //      (with backgrnd save/restore) in CGA & EGA3 modes.
59 //      Wish me luck! ... FUCK IT! I removed EGA3 mode -- it
60 //      was too much shit & kludgery to get a cursor going.
61 //
62 // May 08 91 - Well! Let's see...I got Huffman map compression
63 //      done; wrote a MakeOBJ function that can be used within
64 //      the Memory Manager or Standard Borland C. Added .OBJ
65 //      generation to IGRAB. Started the function to generate
66 //      graphic map dumps. Modified the MapHeader stuff more
67 //      when John needed "extras".
68 //
69 // May 09 91 - Finished ILBM & Apple Preferred map dumps!
70 //      Fixed a couple hidden bugs, made some things nicer,
71 //      started on Flood Fill...
72 //
73 // May 11 91 - Got the TILEINFO/M stuff structured and loading
74 //      and saving (with compression). Putting all the "hidden"
75 //      commands in the menus...
76 //
77 // May 13 91 - Stuck in a PROJECT SELECT option (for the Keen2
78 //      trilogy, it'll be nice).
79 //
80 // May 16 91 - Got all of TILEINFO stuff finished. Tom and
81 //      Jason's first day! Tom BETAed IGRAB & TED5 big time.
82 //      Had to basically dump the GraphHeaderStr and just
83 //      make the ?GAHEAD.ext file all dataoffsets! (The simpler,
84 //      the better!)
85 //
86 // May 19 91 - Almost got the Flood Fill mode working...Tom
87 //      started drawing maps a little early & now I need to add
88 //      a little kludge-fix to reformat his old maps...
89 //
90 // May 22 91 - Got AWESOME UNDO working ... fixed the nagging little
91 //      paste/scrolling bug fixed (separated the PasteErase
92 //      & PasteDraw routines) ... finished Block Fill ... fixed
93 //      the floating paste/tile showthru bug ...
94 //
95 // May 27 91 - Basically finished up. Tom is BETAing now. I need
96 //      to make SelectMap accept the arrows & make an array for
97 //      the map names instead of the sorry way I'm doing it now.
98 //
99 // Jun 2  91 - Got level launching working!  Been working on
100 //      TED5 and IGRAB docs and MUSE most of the time.
101 //
102 // Jun 18 91 - v0.13 because John C.'s system didn't have
103 //      the SCmapmask set to 15 in CopyEGA!
104 //
105 // Jun 20 91 - v0.14: It's annoying to LAUNCH the game and come
106 //      back at the top-left corner!
107 //
108 // Jun 26 91 - v0.17: Made LAUNCH with ICON CHANGE ctrl-alt-L
109 //      because Tomshit was having problems...adding Unused Tile
110 //      Scan...fixing a couple minor Tom-irritants...
111 //
112 // Jul 12 91 - v0.23: Made VGA & CGA work! Fixed a small
113 //      bug with plane-on starting...added a GridMode for the
114 //      FloatingPaste...XMS Map-Cache...now saves the Launchname
115 //      in TEDINFO? so user program doesn't need to send anything
116 //      back but /LAUNCHED...finally fixed nagging FloatingPaste
117 //      multi-plane viewing bug...
118 //
119 // Jul 19 91 - v0.24: Changed TEDINFO structure and added GFXINFO
120 //      to IGRAB. Got most all bugs out...lowercase input now...
121 //
122 // Jul 23 91 - v0.26: Only write out .H if it needs to...got the
123 //      SnapPaste feature in that Tom wanted...
124 //
125 // Aug 08 91 - v0.28: I can't believe this shit! Mr. Tom decided
126 //      to enter the value "0xF00D" into the map, which was my secret
127 //      value for passing an ESC press back from "inputint". I made
128 //      it a #define now!
129 //
130 // Aug 09 91 - v0.29: I FUCKING FRIED THE LIB_A.ASM & LIB.C FILES!
131 //      THESE USED TO HOLD TED5'S TILE-DRAWING AND CGA/VGA ROUTINES!
132 //      AAAARRRRGGGG!!!! Trying to recontruct the program. It'll
133 //      take a bit (I was trying to fix a bug in EditMapNames).
134 //
135 // Aug 14 91 - v0.30: Just got finished fixing the FRIED SOURCE HELL!
136 //
137 // Aug 16 91 - v0.31: Heh heh, I added the ViewMap function!
138 //
139 // Aug 19 91 - v0.32: Added the MapImport function and it works! YES!
140 //
141 // Aug 22-23 - v0.35: Fixed a WHOLE BUNCH of little things and added
142 //      some cool features like easier TILEINFO entering, default
143 //      Import drive, F3 to toggle Paste Overlay, etc. Very nice now.
144 //
145 // Aug 24 91 - v0.38: Fixed a bug in passing multiple command-line
146 //      parameters to LAUNCHed program. Let user enter new parms and
147 //      a new launch name while in TED5.  Added the CarmackCompression
148 //      and trashed the Huffman shit.
149 //
150 // Sep 07 91 - v0.40: Only ViewMap planes viewable instead of all; flag
151 //      currently loaded map in SelectMap dialog; check NumIconRows for
152 //      a bogus value for old TED5 compatibility; show map dimensions in
153 //      ChangeMapEdges dialog; CTRL-ALT-arrows will go to map edges.
154 //
155 // Sep 12 91 - v0.41: Let user PERMANENTLY change the Launch icon. Also,
156 //      the plane flags are always saved!
157 //
158 // Sep 27 91 - v0.43: Added REVIEW_MAP function. Fixed a hard-to-find bug
159 //      in the BlockFill-with-pattern function.
160 //
161 // Sep 29 91 - v0.44: Fixed small annoying bug w/Flood-fill w/pattern.
162 //
163 // Oct 12 91 - v0.45: Added the PrintReport feature after Carmacizing
164 //      all the maps.
165 //
166 // Nov 24 91 - v0.48: Saving the Import Path, added TILEINFOM copying
167 //      from one area to another, getting rid of the "turning the plane
168 //      viewing ON automatically sets it for writing."
169 //
170 // May 22 92 - v0.49: Added graphics-select switch to get rid of a dialog.
171 //
172 // Oct 20 95 - v0.50: Fixed EGA scrolling bug, added screensaver which comes
173 //                    on automatically after 2 minutes.  Timelimit adjustable
174 //                    through TIMELIMIT command line MED
175 //
176 ////////////////////////////////////////////////////
177 #include "ted5.h"
178 #pragma hdrstop
179
180 extern unsigned _stklen=0x2000;
181
182 ////////////////////////////////////////////////////
183 //
184 // Variables
185 //
186 ////////////////////////////////////////////////////
187 extern char far TEDCHAR,far VGAPAL,tdata;
188 extern unsigned doubled[256];
189
190 UndoStr UndoRegion;
191 CopyStr TileCopy;
192 MapFileHeaderStr _seg *MapFileHeader;
193 char _seg *Tinfo[10],_seg *TMinfo[10],_seg *GraphHeader;
194 long _seg *XMSlookup,_seg *EgaXMSlookup,_seg *CgaXMSlookup,_seg *VgaXMSlookup;
195 int _seg *MapBkgnd,_seg *MapFrgnd,_seg *MapInfoPl,
196     _seg *CutBkgnd,_seg *CutFrgnd,_seg *CutInfoPl;
197 MapHeaderStr MapHeader;
198
199 TempStruct LaunchInfo;
200 InfoStruct _seg *TEDInfo;
201 GfxStruct _seg *GFXInfo;
202 video lastvideo,videomode;
203 screentype whichscreen=TILES;
204 VMapStr VMapData;
205
206 char launchname[64],ext[4],format[2],projname[64],mapname[64],planes,
207         infoname[64],mapheadname[64],MapNames[100][16],parmstring[64];
208 char SM_name[64],SM_loadname[64],BkgndColor,GfxToUse;
209
210 unsigned temp,whichmap,numtplanes,tilenum,tilemnum,numtmplanes,left,
211         DirtyFlag,tilelen,tilemlen,whicht,whichtm,whichi,
212         tsize,infoy,infomaxw,mapwidth,mapheight,screenw,usingbat,
213         screenh,planeton,planemon,planeion,maxiconrows,lasticon,firsticon,
214         viewton,viewmon,viewion,XMSundoB,XMSundoF,XMSundoI,launched,
215         XMSmaps,EgaXMS,CgaXMS,VgaXMS,xmshandle,GridMode,SnapMode,snapx,
216         snapy,snapxsize,snapysize,writeH,NoAbout,F3_flag;
217 int tilebase=0,tilembase=0,infobaron=1,xbase,ybase,scrnbot,scrnrgt,
218         FillMode=0,PasteMode=0,SelectMode=0,SelX1=-1,SelY1=-1,PasteOK=0,SelX2=-1,
219         SelY2=-1,pixelx,pixely,selectcols,px,py,lastmap=-1,TIybase,TIymbase,TIxbase,
220         TIxmbase,BfillMode,Plotting,TsearchMode,NoXMSFlag;
221 long CgaXMSsize,EgaXMSsize,VgaXMSsize;
222 long tics, tictime=1092L*2L;
223
224
225 //
226 // harderr-called routine
227 //
228 int ignore(void)
229 {
230  hardresume(0);
231  return 0;
232 }
233
234 ////////////////////////////////////////////////////
235 //
236 // Start of The Beast From Hell
237 //
238 ////////////////////////////////////////////////////
239 void main(void)
240 {
241  ParseCmdline();
242  SetupKBD();
243  MMStartup();
244  setvideo(EGA1);
245  lastvideo=EGA1;
246  InitTed5();
247  harderr(ignore);
248  tics=biostime(0,0);
249  DeskEventLoop(HandleEvent,Continuous);
250 }
251
252 ////////////////////////////////////////////////////
253 //
254 // Parse the commandline
255 //
256 ////////////////////////////////////////////////////
257 void ParseCmdline(void)
258 {
259  int i;
260
261  for (i=1;i<_argc;i++)
262  {
263   _argv[i]=strupr(_argv[i]);
264
265   if (_argv[i][0]=='-' || _argv[i][0]=='/')
266         _argv[i]++;
267
268   if (!strcmp(_argv[i],"?"))
269         {
270          printf(TITLESTR" by John Romero (C) 1991 Id Software, Inc.\n\n");
271          printf("Command Line parameters:\n");
272          printf("/?              : gets this stuff\n");
273          printf("/EXT=???        : set the project extension\n");
274          printf("<filename>      : set the Launch filename\n");
275          printf("/PARMS=<string> : set parms to Launch with\n");
276          printf("/NOXMSMAPS      : don't cache maps in XMS\n");
277     printf("/GFX=???        : set gfx to use - E,C,V\n");
278          printf("/TIME=???       : half-minutes until screenblanker (default 2 minutes)\n");
279     exit(0);
280         }
281   else
282   if (!strncmp(_argv[i],"EXT=",4))
283         strcpy(ext,&_argv[i][4]);
284   else
285   if (!strncmp(_argv[i],"GFX=",4))
286         GfxToUse = _argv[i][4];
287   else
288   if (!strcmp(_argv[i],"LAUNCH"))
289         launched=1;
290   else
291   if (!strcmp(_argv[i],"BAT"))
292         usingbat=1;
293   else
294   if (!strncmp(_argv[i],"PARMS=",6))
295         strcpy(parmstring,&_argv[i][6]);
296   else
297   if (!strncmp(_argv[i],"TIME=",5))
298           tictime=(atol(&_argv[i][5]))*546L;
299   else
300   if (!strcmp(_argv[i],"NOXMSMAPS"))
301         NoXMSFlag=1;
302   else
303   if (!strcmp(_argv[i],"NOABOUT"))
304         NoAbout=1;
305   else
306         strcpy(launchname,_argv[i]);
307  }
308 }
309
310
311 ////////////////////////////////////////////////////
312 //
313 // Event handler - called when button is pressed
314 // outside menu bar
315 //
316 ////////////////////////////////////////////////////
317 void HandleEvent(void)
318 {
319  int pixelx,pixely,mx,my,b0,b1;
320  unsigned loc;
321
322  b0=MouseButton()&1;
323  b1=(MouseButton()>>1)&1;
324
325  MouseCoords(&mx,&my);
326  pixely=my;
327  pixelx=mx;
328
329  //
330  // PLOT OR PICK-UP TILE
331  //
332  if (my>=8 && my<infoy*8 && (b0 || b1))
333    {
334         mx=xbase+(mx>>(tsize+2));
335     my=ybase+((my-8)>>(tsize+2));
336
337     loc=my*mapwidth+mx;
338
339     if (mx>=mapwidth || my>=mapheight)
340       errsound();
341     else
342       {
343        if (b1)
344          {
345           //
346           // SELECT BOTTOM-RIGHT EDGE
347           //
348           if (SelectMode || BfillMode)
349             {
350              SelX2=mx;
351              SelY2=my;
352              if ((SelX1==-1 && SelY1==-1) ||
353                  (SelX2<SelX1 || SelY2<SelY1))
354                {
355                 SelX1=mx;
356                 SelY1=my;
357                }
358              DrawMap();
359              sound(2000);
360             }
361           //
362           // FLOOD FILL!
363           //
364           else
365           if (FillMode)
366             {
367              while(MouseButton());
368              DoFloodFill(mx,my,1);
369             }
370           //
371           // PICK UP TILE(S)
372           //
373           else
374             {
375              if (planeton)
376                whicht=*(MapBkgnd+loc);
377              if (planemon)
378                whichtm=*(MapFrgnd+loc)+tilenum;
379                  if (planeion)
380                whichi=*(MapInfoPl+loc)+tilenum;
381              DrawInfoBar();
382
383              //
384              // IF WE'RE IN TILESEARCH MODE, SHOW IT!
385              //
386              if (TsearchMode)
387                DrawMap();
388             }
389           while(MouseButton()>>1);
390           nosound();
391          }
392        if (b0)
393          {
394           //
395           // SELECT TOP-LEFT EDGE
396           //
397           if (SelectMode || BfillMode)
398             {
399              SelX1=mx;
400              SelY1=my;
401              if ((SelX2==-1 && SelY2==-1) ||
402                  (SelX1>SelX2 || SelY1>SelY2))
403                {
404                 SelX2=mx;
405                 SelY2=my;
406                }
407
408              DrawMap();
409              sound(2000);
410              while(MouseButton());
411             }
412           //
413           // FLOOD FILL!
414           //
415           else
416           if (FillMode)
417             {
418              while(MouseButton());
419              DoFloodFill(mx,my,0);
420             }
421           //
422           // PASTE A CHUNK O' TILES/MAP
423           //
424           else
425           if (PasteMode)
426             {
427              if (TileCopy.MapOrTileSelect)      // TILE-SELECT AREA?
428                {
429                 int i,j;
430
431                 if (SnapMode)
432                   {
433                    mx=(mx/snapxsize)*snapxsize+snapx;
434                    my=(my/snapysize)*snapysize+snapy;
435                   }
436
437                 if (mx+TileCopy.w>mapwidth ||
438                     my+TileCopy.h>mapheight)
439                 sound(500);
440                 else
441                   {
442                    CopyUndoRegion();
443                    UndoRegion.x=mx;
444                    UndoRegion.y=my;
445                    UndoRegion.w=TileCopy.w;
446                    UndoRegion.h=TileCopy.h;
447
448                    sound(500);
449                    switch(TileCopy.MapOrTileSelect)
450                    {
451                     case 1: // TILES
452                       for (j=0;j<TileCopy.h;j++)
453                         for (i=0;i<TileCopy.w;i++)
454                           {
455                            int val=(j+TileCopy.y)*selectcols+TileCopy.x+i;
456                            if (XMSlookup[val]!=-1)
457                              MapBkgnd[(my+j)*mapwidth+mx+i]=val;
458                           }
459                       break;
460                     case 2: // MASKED
461                       for (j=0;j<TileCopy.h;j++)
462                         for (i=0;i<TileCopy.w;i++)
463                           {
464                            int val=(j+TileCopy.y)*selectcols+TileCopy.x+i+tilenum+maxiconrows*selectcols;
465                            if (XMSlookup[val]!=-1)
466                              MapFrgnd[(my+j)*mapwidth+mx+i]=val-tilenum;
467                           }
468                    }
469                    nosound();
470                    DrawMap();
471                    DirtyFlag=1;
472                   }
473                 while(MouseButton());
474                 nosound();
475                }
476              else
477                {
478                 int i,j;
479
480                 if (SnapMode)
481                   {
482                    mx=(mx/snapxsize)*snapxsize+snapx;
483                    my=(my/snapysize)*snapysize+snapy;
484                   }
485
486                 if (mx+TileCopy.w-1<mapwidth && my+TileCopy.h-1<mapheight)
487                   {
488                    sound(500);
489                    CopyUndoRegion();
490                    UndoRegion.x=mx;
491                    UndoRegion.y=my;
492                    UndoRegion.w=TileCopy.w;
493                    UndoRegion.h=TileCopy.h;
494
495                    for (j=0;j<TileCopy.h;j++)
496                      for (i=0;i<TileCopy.w;i++)
497                        {
498                         int theM,theI;
499
500
501                         if (TileCopy.PlanesCopied&BPLANE)
502                           MapBkgnd[(j+my)*mapwidth+mx+i]=
503                             CutBkgnd[(j+TileCopy.y)*mapwidth+TileCopy.x+i];
504                         if (TileCopy.PlanesCopied&FPLANE)
505                           {
506                            theM=CutFrgnd[(j+TileCopy.y)*mapwidth+TileCopy.x+i];
507                            if (theM || F3_flag)
508                              MapFrgnd[(j+my)*mapwidth+mx+i]=theM;
509                           }
510                         if (TileCopy.PlanesCopied&IPLANE)
511                           {
512                            theI=CutInfoPl[(j+TileCopy.y)*mapwidth+TileCopy.x+i];
513                            if (theI || F3_flag)
514                                  MapInfoPl[(j+my)*mapwidth+mx+i]=theI;
515                           }
516                        }
517                    nosound();
518                    DrawMap();
519                    DirtyFlag=1;
520                   }
521                 else
522                   sound(500);
523
524                 while(MouseButton());
525                }
526             }
527           //
528           // PLOT TILE(S)
529           //
530           else
531             {
532              unsigned oldt,oldm,oldi;
533
534              //
535              // ARE WE STARTING THE PLOTTING REGION?
536              //
537              if (!Plotting)
538                {
539                 CopyUndoRegion();
540                 UndoRegion.x=mx;
541                 UndoRegion.y=my;
542                 UndoRegion.w=UndoRegion.h=1;
543                 Plotting=1;
544                }
545
546              //
547              // FLOAT THE PLOTTING REGION
548              //
549              if (mx<UndoRegion.x)
550                UndoRegion.x=mx;
551              if (my<UndoRegion.y)
552                UndoRegion.y=my;
553              if (mx+1>UndoRegion.x+UndoRegion.w)
554                UndoRegion.w=mx-UndoRegion.x+1;
555              if (my+1>UndoRegion.y+UndoRegion.h)
556                UndoRegion.h=my-UndoRegion.y+1;
557
558              if (planeton)
559                    *(MapBkgnd+loc)=whicht;
560              if (planemon)
561                *(MapFrgnd+loc)=whichtm-tilenum;
562              if (planeion)
563                *(MapInfoPl+loc)=whichi-tilenum;
564
565              oldt=MapBkgnd[loc];
566              oldm=MapFrgnd[loc]+tilenum;
567              oldi=MapInfoPl[loc]+tilenum;
568
569              CombineTiles(viewton?oldt:-BkgndColor,viewmon*oldm,oldi*viewion,tsize);
570              if (GridMode)
571                Overlay(tsize);
572              MouseHide();
573              DrawTile((mx-xbase)<<(tsize-1),(my-ybase)*(4<<tsize)+8,tsize);
574              CheckInfoValues(mx-xbase,my-ybase,oldi);
575              MouseShow();
576              DirtyFlag=1;
577             }
578          }
579        nosound();
580       }
581    }
582
583  //
584  // CLICK ON TILES
585  //
586  if (b0 && pixely>infoy*8)
587    {
588     if (pixelx<7*8)
589       SelectTiles(1);
590     else
591     if (pixelx<8*14 && tilemnum)
592       SelectTiles(2);
593     else
594     if (pixelx<8*20 && tilemnum)
595       SelectTiles(3);
596    }
597
598 }
599
600 #define PEL_WRITE_ADR   0x3c8
601 #define PEL_READ_ADR    0x3c7
602 #define PEL_DATA        0x3c9
603 #define PEL_MASK        0x3c6
604
605 void ScreenBlank ( void )
606 {
607   int done;
608   int x;
609   int y;
610   int r;
611   int g;
612   int b;
613   int c;
614   int oldx,oldy;
615   int i, j;
616   int xdir,ydir;
617   int cury;
618   int size;
619   int type;
620   struct {
621           int x,y;
622           } snake[256];
623
624   unsigned char far * screen=(unsigned char far *)0xa0000000l;
625
626
627   randomize();
628   _AX=0x13;
629   asm int 10h
630   done=0;
631   size=random(10)+2;
632   clearkeys();
633
634   for (i=255;i>=0;i--)
635           {
636           snake[i].x=160;
637           snake[i].y=100;
638           }
639   type=random(11);
640   r=random(200)+56;
641   g=random(200)+56;
642   b=random(200)+56;
643   outp (PEL_WRITE_ADR,0);
644   for (i=0;i<=255;i++)
645                 {
646                 outp (PEL_DATA, (unsigned char)((i*r)>>10));
647                 outp (PEL_DATA, (unsigned char)((i*g)>>10));
648                 outp (PEL_DATA, (unsigned char)((i*b)>>10));
649                 }
650   xdir=0;
651   while (!xdir)
652           xdir=random(size<<1)-size;
653   ydir=0;
654   while (!ydir)
655           ydir=random(size<<1)-size;
656   while (!done)
657           {
658           if ((random(100)-80)>0)
659                   {
660                   xdir+=random(3)-1;
661                   ydir+=random(3)-1;
662                   }
663           for (i=255;i>0;i--)
664                   snake[i]=snake[i-1];
665           snake[0].x+=xdir;
666           snake[0].y+=ydir;
667           if ((snake[0].x<size+1) || (snake[0].x>320-(size+1)))
668                   {
669                   xdir=-xdir;
670                   snake[0].x+=xdir<<1;
671                   }
672           else if (abs(xdir)>size-1)
673                   xdir=-(xdir>>1);
674           if ((snake[0].y<size+1) || (snake[0].y>200-(size+1)))
675                   {
676                   ydir=-ydir;
677                   snake[0].y+=ydir<<1;
678                   }
679           else if (abs(ydir)>size-1)
680                   ydir=-(ydir>>1);
681           for (x=255;x>=0;x--)
682                   {
683                   if (type<7)
684                           {
685                           for (j=snake[x].y,cury=320*snake[x].y;j<snake[x].y+size;j++,cury+=320)
686                                   _fmemset((screen+cury+snake[x].x),255-x,size);
687                           }
688                   else
689                           {
690                           _fmemset((screen+(320*snake[x].y)+snake[x].x),255-x,size);
691                           }
692                   }
693           oldx=pixelx;
694           oldy=pixely;
695           MouseCoords(&pixelx,&pixely);
696           if ((oldx!=pixelx) || (oldy!=pixely))
697                   done=1;
698           for (x=0;x<127;x++)
699                   if (keydown[x])
700                           done=1;
701           }
702 }
703
704 ////////////////////////////////////////////////////
705 //
706 // Routine called continuously by DeskEventLoop
707 //
708 ////////////////////////////////////////////////////
709 void Continuous(void)
710 {
711  static int oldx, oldy;
712  if (biostime(0,0)-tics>tictime)
713          {
714          MouseHide();
715          ScreenBlank();
716          clearkeys();
717          videomode=lastvideo;
718          Item_ModeSwitch();
719          RedrawDesktop();
720          DrawMap();
721          DrawInfoBar();
722          MouseShow();
723          tics=biostime(0,0);
724          }
725  oldx=pixelx;
726  oldy=pixely;
727  MouseCoords(&pixelx,&pixely);
728  if ((oldx!=pixelx) || (oldy!=pixely))
729          {
730          tics=biostime(0,0);
731          PrintCoords();
732          }
733
734  if (!MouseButton())
735    Plotting=0;
736
737  //
738  // PLANE "WRITE" SELECTION
739  //
740  if (keydown[2] && viewton)
741    {
742     planeton^=1;
743     DrawInfoBar();
744     DrawMap();
745     PrintCoords();
746     tics=biostime(0,0);
747     while(keydown[2]);
748    }
749  if (keydown[3] && tilemnum && (MapFileHeader->maptype&FPLANE) && viewmon)
750    {
751     planemon^=1;
752     DrawInfoBar();
753     DrawMap();
754     PrintCoords();
755     tics=biostime(0,0);
756     while(keydown[3]);
757    }
758  if (keydown[4] && (MapFileHeader->maptype&IPLANE) && viewion)
759    {
760     planeion^=1;
761     DrawInfoBar();
762     DrawMap();
763     PrintCoords();
764     tics=biostime(0,0);
765     while(keydown[4]);
766    }
767
768  //
769  // PLANE "VIEW" SELECTION
770  //
771  if (keydown[5])
772    {
773     viewton^=1;
774     if (!viewton)
775           planeton=0;
776     DrawInfoBar();
777     DrawMap();
778     PrintCoords();
779     tics=biostime(0,0);
780     while(keydown[5]);
781    }
782  if (keydown[6] && tilemnum && (MapFileHeader->maptype&FPLANE))
783    {
784     viewmon^=1;
785     if (!viewmon)
786       planemon=0;
787     DrawInfoBar();
788     DrawMap();
789     PrintCoords();
790     tics=biostime(0,0);
791     while(keydown[6]);
792    }
793  if (keydown[7] && (MapFileHeader->maptype&IPLANE))
794    {
795     viewion^=1;
796     if (!viewion)
797       planeion=0;
798     DrawInfoBar();
799     DrawMap();
800     PrintCoords();
801     tics=biostime(0,0);
802     while(keydown[7]);
803    }
804
805  //
806  // Cancel COPY or PASTE or FLOOD FILL or BLOCK FILL
807  //
808  if (keydown[1] && (PasteMode || SelectMode || FillMode ||
809          BfillMode || TsearchMode))
810    {
811     while(keydown[1]);
812
813     if (PasteMode)
814       {
815        EraseFloatPaste();
816        px=py=-1;
817       }
818
819     SnapMode=TsearchMode=BfillMode=FillMode=PasteMode=SelectMode=0;
820     SelX1=SelX2=SelY1=SelY2=-1;
821     DrawMap();
822     DrawInfoBar();
823     tics=biostime(0,0);
824    }
825
826  //
827  // END OF COPY || BLOCK FILL
828  //
829  if (keydown[0x1c] && (SelectMode || BfillMode))
830    {
831     int temp,j,i;
832
833     tics=biostime(0,0);
834     while(keydown[0x1c]);
835
836     if (SelX2<SelX1)
837       {
838        temp=SelX1;
839        SelX1=SelX2;
840        SelX2=temp;
841       }
842     if (SelY2<SelY1)
843       {
844        temp=SelY1;
845        SelY1=SelY2;
846        SelY2=temp;
847       }
848
849     //
850     // BLOCK FILL?
851     //
852     if (BfillMode)
853       {
854        BfillMode=0;
855        DrawInfoBar();
856        DoBlockFill();
857        SelX1=SelX2=SelY1=SelY2=-1;
858       }
859     else
860     //
861     // COPY MODE?
862     //
863     if (SelectMode)
864       {
865        SelectMode=0;
866
867        TileCopy.x=SelX1;
868        TileCopy.y=SelY1;
869        TileCopy.w=SelX2-SelX1+1;
870            TileCopy.h=SelY2-SelY1+1;
871        TileCopy.MapOrTileSelect=0;
872        TileCopy.PlanesCopied=planeton*BPLANE | planemon*FPLANE | planeion*IPLANE;
873
874        //
875        // DO THE COPY!
876        //
877        sound(600);
878        for (j=SelY1;j<=SelY2;j++)
879          for (i=SelX1;i<=SelX2;i++)
880            {
881             if (planeton)
882               CutBkgnd[j*mapwidth+i]=MapBkgnd[j*mapwidth+i];
883             if (planemon)
884               CutFrgnd[j*mapwidth+i]=MapFrgnd[j*mapwidth+i];
885             if (planeion)
886               CutInfoPl[j*mapwidth+i]=MapInfoPl[j*mapwidth+i];
887            }
888
889        DrawInfoBar();
890        SelX1=SelX2=SelY1=SelY2=-1;
891        PasteOK=1;
892        px=py=-1;
893        nosound();
894        DrawMap();
895       }
896     clearkeys();
897    }
898
899  //
900  // See if we want to scroll the map!
901  //
902  CheckMapScroll();
903  CheckFloatPaste((pixelx>>(tsize+2))+xbase,((pixely-8)>>(tsize+2))+ybase);
904 }
905
906 ////////////////////////////////////////////////////
907 //
908 // Draw the current map on the screen at xbase,ybase
909 //
910 ////////////////////////////////////////////////////
911 void DrawMap(void)
912 {
913  int i,j,imax,jmax;
914
915
916  EraseFloatPaste();
917  jmax=screenh;
918  if (jmax>mapheight)
919    jmax=mapheight;
920
921  imax=screenw;
922  if (imax>mapwidth)
923    imax=mapwidth;
924
925  MouseHide();
926  for(j=0;j<jmax;j++)
927    for(i=0;i<imax;i++)
928      {
929       unsigned tilet,tilem,tilei,loc;
930
931       loc=(ybase+j)*mapwidth+xbase+i;
932
933       tilet=*(MapBkgnd+loc);
934       tilem=*(MapFrgnd+loc)+tilenum;
935       tilei=*(MapInfoPl+loc)+tilenum;
936
937       CombineTiles(tilet*viewton-BkgndColor*(!viewton),tilem*viewmon,tilei*viewion,tsize);
938       if (GridMode)
939         Overlay(tsize);
940       DrawTile(i<<(tsize-1),j*(4<<tsize)+8,tsize);
941       CheckInfoValues(i,j,tilei);
942       CheckSelectEdges(i+xbase,j+ybase,i,j);
943      }
944  MouseShow();
945  DrawFloatPaste();
946 }
947
948
949 ////////////////////////////////////////////////////
950 //
951 // Figure out SCREENW,SCREENH from videomode & tsize
952 //
953 ////////////////////////////////////////////////////
954 void FigureScreenEdges(void)
955 {
956  switch(videomode)
957  {
958   case CGA:
959   case EGA1:
960   case VGA:
961     screenw=40>>(tsize-1);
962     screenh=22>>(tsize-1);
963     break;
964   case EGA2:
965     screenw=80>>(tsize-1);
966     screenh=57>>(tsize-1);
967     break;
968  }
969  if (!infobaron)
970    {
971     infoy=100;  // WAY OFF THE BOTTOM!
972     screenh+=2*(tsize==1)+(tsize==2);
973    }
974 }
975
976
977 ////////////////////////////////////////////////////
978 //
979 // Print the coords on the INFOBAR
980 //
981 ////////////////////////////////////////////////////
982 void PrintCoords(void)
983 {
984  static zeroed=0;
985  int mx,my;
986
987  if (!infobaron)
988    return;
989
990  xormask=0;
991  MouseCoords(&mx,&my);
992  if (my<8 || my>=infoy*8)
993    {
994     if (zeroed)
995       return;
996     sx=infomaxw-9;
997     sy=infoy;
998     print("??? ?????");
999     sx=infomaxw-9;
1000     sy=infoy+1;
1001     print("??? ?????");
1002     zeroed=1;
1003     return;
1004    }
1005
1006  zeroed=0;
1007  mx=mx>>(tsize+2);
1008  sx=infomaxw-9;
1009  sy=infoy;
1010  printint(mx+xbase);
1011  print("  ");
1012  sx=infomaxw-5;
1013  printhex(mx+xbase);
1014
1015  my=(my-8)>>(tsize+2);
1016  sx=infomaxw-9;
1017  sy=infoy+1;
1018  printint(my+ybase);
1019  print("  ");
1020  sx=infomaxw-5;
1021  printhex(my+ybase);
1022 }
1023
1024
1025 ////////////////////////////////////////////////////
1026 //
1027 // Draw the INFOBAR
1028 //
1029 ////////////////////////////////////////////////////
1030 void DrawInfoBar(void)
1031 {
1032  int ox,oy;
1033
1034
1035  if (PasteMode)
1036    {
1037     px=py=-1;
1038     CheckFloatPaste((pixelx>>(tsize+2))+xbase,((pixely-8)>>(tsize+2))+ybase);
1039    }
1040
1041  if (!infobaron)
1042    return;
1043
1044  EraseFloatPaste();
1045
1046  ox=sx=0;
1047  switch(videomode)
1048  {
1049   case CGA:
1050   case EGA1:
1051   case VGA:
1052     oy=sy=23-2*(tsize==3);
1053     infomaxw=40;
1054     break;
1055   case EGA2:
1056     oy=sy=58-2*(tsize==3)-1*(tsize==2);
1057     infomaxw=80;
1058  }
1059
1060  MouseHide();
1061  infoy=oy;
1062  bar(0,infoy,infomaxw-1,infoy+1,' ');
1063
1064  if (SelectMode)
1065    {
1066     sx=leftedge=1;
1067     sy=infoy;
1068     print("Copy Mode\nESC to exit");
1069    }
1070  else
1071  if (TsearchMode)
1072    {
1073     sx=leftedge=1;
1074     sy=infoy;
1075     print("Tile Search Mode\nESC to exit");
1076    }
1077  else
1078  if (BfillMode)
1079    {
1080     sx=leftedge=1;
1081     sy=infoy;
1082     print("Block Fill Mode\nESC to exit");
1083    }
1084  else
1085  if (PasteMode)
1086    {
1087     sx=leftedge=1;
1088     sy=infoy;
1089     print("Paste Mode\nESC to exit");
1090    }
1091  else
1092  if (FillMode)
1093    {
1094     sx=leftedge=1;
1095         sy=infoy;
1096     print("Flood Fill Mode\nESC to exit");
1097    }
1098  else
1099    {
1100     CombineTiles(whicht,0,0,tsize);
1101     DrawTile(ox,oy*8+8*(tsize==1),tsize);
1102     sx=ox+2+2*(tsize==3);
1103     sy=oy;
1104     printhex(whicht);
1105     sx-=5;
1106     sy++;
1107     printint(whicht);
1108     print("    ");
1109
1110     if (tilemnum)
1111       {
1112        ox+=7;
1113        CombineTiles(-BkgndColor,whichtm,0,tsize);
1114        DrawTile(ox,oy*8+8*(tsize==1),tsize);
1115        sx=ox+2+2*(tsize==3);
1116        sy=oy;
1117        (whichtm==tilenum)?print(" No  "):printhex(whichtm-tilenum);
1118        sx-=5;
1119        sy++;
1120        (whichtm==tilenum)?print("Tile"):printint(whichtm-tilenum);
1121        print("    ");
1122
1123        ox+=7;
1124        CombineTiles(-ICONBACK,(whichi>lasticon)?firsticon:whichi,0,tsize);
1125        DrawTile(ox,oy*8+8*(tsize==1),tsize);
1126        sx=ox+2+2*(tsize==3);
1127        sy=oy;
1128        (whichi==tilenum)?print(" No  "):printhex(whichi-tilenum);
1129        sx-=5;
1130        sy++;
1131        (whichi==tilenum)?print("Icon"):printint(whichi-tilenum);
1132        print("    ");
1133       }
1134    }
1135
1136
1137  sx=infomaxw-11;
1138  sy=infoy;
1139  print("X=");
1140  sy++;
1141  sx-=2;
1142  print("Y=");
1143
1144  sx=infomaxw-((videomode==EGA2)?19:18);
1145  sy=infoy+1;
1146  print("123");
1147  if (SnapMode)
1148    {
1149     sx=infomaxw-((videomode==EGA2)?21:20);
1150     sy=infoy+1;
1151     print("S");
1152    }
1153  if (GridMode)
1154    {
1155     sx=infomaxw-((videomode==EGA2)?20:19);
1156     sy=infoy+1;
1157     print("G");
1158    }
1159  sx=infomaxw-((videomode==EGA2)?19:18);
1160  sy=infoy;
1161  (planeton)?print("B"):print(" ");
1162  (planemon)?print("F"):print(" ");
1163  (planeion)?print("I"):print(" ");
1164
1165  sx=infomaxw-15;
1166  sy=infoy+1;
1167  print("456");
1168  sx=infomaxw-15;
1169  sy=infoy;
1170  (viewton)?print("b"):print(" ");
1171  (viewmon)?print("f"):print(" ");
1172  (viewion)?print("i"):print(" ");
1173
1174  if (videomode==EGA2)
1175    {
1176     sx=screencenterx-strlen(MapHeader.name)/2;
1177     sy=infoy;
1178     print(MapHeader.name);
1179    }
1180
1181  DrawFloatPaste();
1182  MouseShow();
1183 }
1184
1185
1186 ////////////////////////////////////////////////////
1187 ////////////////////////////////////////////////////
1188 ////////////////////////////////////////////////////
1189 //
1190 // Initialize TED5:
1191 //
1192 // * Project Select if multiple projects
1193 // * If Project has NO LEVELS:
1194 //   * Init Level 1
1195 //   * Init TILEINFO
1196 //   * Init TEDINFO file
1197 // * Load TILES into XMS
1198 //
1199 ////////////////////////////////////////////////////
1200 ////////////////////////////////////////////////////
1201 ////////////////////////////////////////////////////
1202 char bstrings[10][15];
1203 btype ProjButns[10];
1204 DialogDef ProjSelect={"Select the project to work on:",
1205                       30,0,0,&ProjButns[0],DrawProjBord};
1206
1207 void InitTed5(void)
1208 {
1209  char pname[15];
1210  unsigned i,loop,which;
1211
1212  MouseInit();
1213  MouseShow();
1214  if (!MouseStatus)
1215    {
1216         ErrDialog("Sorry, but TED5 will NOT\n"
1217                   "operate without a mouse!\n"," Press ENTER ");
1218         Quit("Only REAL developers have a mouse!");
1219    }
1220  MouseOrigin(0,0);
1221
1222  ErrDialog("Initializing. One moment.","");
1223  //
1224  // Create bit-doubling lookup table
1225  // for CGA font creation
1226  //
1227  for (loop=0;loop<256;loop++)
1228    {
1229         unsigned result,temp=loop;
1230
1231         asm         mov     ax,temp
1232         asm         mov     ah,al
1233         asm         mov     cx,8
1234         LOOP0:
1235         asm         shl     al,1
1236         asm         rcl     bx,1
1237         asm         shl     ah,1
1238         asm         rcl     bx,1
1239         asm         loop    LOOP0
1240
1241         asm         xchg    bh,bl
1242         asm         mov     result,bx
1243
1244         doubled[loop]=result;
1245    }
1246
1247  //
1248  // Init everything!
1249  //
1250  InitXMS();
1251  FindGraphFile();
1252  LoadInfoFile();
1253  LoadMapHeader();
1254
1255  RestoreBackground();
1256
1257  LoadGraphStuff(0,TEDInfo->lastvid);
1258  DrawInfoBar();
1259  DrawMap();
1260  if (!launched && !NoAbout)
1261    Item_About();
1262  launched=0;
1263 }
1264
1265
1266 ////////////////////////////////////////////////////
1267 ////////////////////////////////////////////////////
1268 //
1269 // Load the MAPTEMP.ext header in...
1270 //
1271 ////////////////////////////////////////////////////
1272 ////////////////////////////////////////////////////
1273 btype SelectTsizeb[]={{"  8x8  ",1,2,1},
1274                       {" 16x16 ",1,5,1},
1275                           {" 32x32 ",1,8,1}};
1276 DialogDef SelectTsize={" Which tile size to use?"
1277                        ,26,10,3,&SelectTsizeb[0],STnot};
1278
1279 void LoadMapHeader(void)
1280 {
1281  unsigned size,i,j,pflag;
1282  char types=0;
1283
1284
1285  strcpy(mapheadname,"MAPTHEAD.");
1286  strcat(mapheadname,ext);
1287  strcpy(mapname,"MAPTEMP.");
1288  strcat(mapname,ext);
1289  strcpy(SM_name,"MAPTEMP1.");
1290  strcat(SM_name,ext);
1291  strcpy(SM_loadname,"MAPTEMP.");
1292  strcat(SM_loadname,ext);
1293
1294  if (access(mapheadname,0))
1295    {
1296     int i;
1297     //
1298     // Gotta create a new map file!
1299     //
1300     MMAllocate((memptr *)&MapFileHeader,sizeof(MapFileHeaderStr));
1301     for (i=0;i<sizeof(MapFileHeaderStr);i++)
1302       *((char _seg *)MapFileHeader+i)=0;
1303
1304     MapFileHeader->RLEWtag=0xabcd;
1305     for (i=0;i<100;i++)
1306       {
1307        MapFileHeader->dataoffsets[i]=-1;
1308        MapFileHeader->datalengths[i]=0;
1309        memset(MapNames[i],0,16);
1310       }
1311
1312     if (!GFXInfo->num8 &&
1313         !GFXInfo->num8m &&
1314         !GFXInfo->num16 &&
1315         !GFXInfo->num16m &&
1316         !GFXInfo->num32 &&
1317         !GFXInfo->num32m)
1318       {
1319        ErrDialog("Uhh...you 'neglected' to\n"
1320                  "grab tiles to use. Running\n"
1321                  "TED5 is quite useless at\n"
1322                  "this point, I'm afraid.","Duh!");
1323        Quit("Get some tiles ... quick! Me hungry!");
1324       }
1325
1326     if (!GFXInfo->num8 &&
1327         !GFXInfo->num16 &&
1328         !GFXInfo->num32)
1329       {
1330        ErrDialog("You may have grabbed some\n"
1331                  "MASKED tiles, but I require\n"
1332                  "NON-MASKED tiles as a\n"
1333                  "minimum requirement!","Geez...");
1334        Quit("Please grab some normal tiles!");
1335       }
1336
1337     types+=(GFXInfo->num8>0)+(GFXInfo->num16>0)+(GFXInfo->num32>0);
1338
1339     redo:
1340
1341     if (types>1)
1342       {
1343        int which;
1344
1345        which=DoDialog(&SelectTsize);
1346        switch(which)
1347        {
1348         case 0:
1349           Quit("");
1350         case 1:
1351           if (!GFXInfo->num8)
1352             which=0;
1353           break;
1354         case 2:
1355           if (!GFXInfo->num16)
1356             which=0;
1357           break;
1358         case 3:
1359           if (!GFXInfo->num32)
1360             which=0;
1361           break;
1362        }
1363
1364        MapFileHeader->tsize=TEDInfo->tsize=tsize=which;
1365           }
1366     else
1367       {
1368        if (GFXInfo->num8)
1369          TEDInfo->tsize=1;
1370        else
1371        if (GFXInfo->num16)
1372          TEDInfo->tsize=2;
1373        else
1374        if (GFXInfo->num32)
1375          TEDInfo->tsize=3;
1376
1377        MapFileHeader->tsize=tsize=TEDInfo->tsize;
1378       }
1379
1380     //
1381     // pick the planes that all maps will use
1382     //
1383     if (PickMorePlanes())
1384       goto redo;
1385
1386     //
1387     // initialize TILEINFO/TILEINFOM
1388     //
1389     switch(tsize)
1390     {
1391      case 1:
1392        tilenum=GFXInfo->num8;
1393        tilemnum=GFXInfo->num8m;
1394        break;
1395      case 2:
1396        tilenum=GFXInfo->num16;
1397        tilemnum=GFXInfo->num16m;
1398        break;
1399      case 3:
1400        tilenum=GFXInfo->num32;
1401        tilemnum=GFXInfo->num32m;
1402     }
1403     InitTileinfo();
1404     if (numtplanes || numtmplanes)      // only input if applicable
1405       Item_EditTinfoNames();            // void where prohibited
1406     //
1407     // now create a map!
1408     //
1409     CreateMap(0);
1410         FigureScreenEdges();
1411     MapFileHeader->NumIconRows=maxiconrows=InputIconAmount();
1412    }
1413  //
1414  // MAP FILE ALREADY IN PLACE. LOAD STUFF IN...
1415  //
1416  else
1417    {
1418     memptr block,tempblock;
1419
1420     LoadIn(mapheadname,(memptr *)&MapFileHeader);
1421
1422     //
1423     // See if the NumIconRows is toasty (old TED5 compatibility)
1424     //
1425     if (MapFileHeader->NumIconRows>50)
1426       MapFileHeader->NumIconRows=4;
1427
1428     //
1429     // has the TEDINFO?.ext file been changed?
1430     // if so, reconstruct pertinent data...
1431     //
1432     if (!TEDInfo->tsize)
1433       {
1434        tsize=TEDInfo->tsize=MapFileHeader->tsize;
1435        switch(tsize)
1436        {
1437         case 1:
1438           tilenum=GFXInfo->num8;
1439           tilemnum=GFXInfo->num8m;
1440           break;
1441         case 2:
1442           tilenum=GFXInfo->num16;
1443           tilemnum=GFXInfo->num16m;
1444           break;
1445         case 3:
1446           tilenum=GFXInfo->num32;
1447           tilemnum=GFXInfo->num32m;
1448        }
1449       }
1450
1451     maxiconrows=MapFileHeader->NumIconRows;
1452
1453     //
1454     // Read-in all the Map Names
1455         //
1456     for (i=0;i<100;i++)
1457       if (MapFileHeader->dataoffsets[i]!=-1)
1458         {
1459          MapHeaderStr TempHead;
1460
1461          LoadFile(mapname,(char huge *)&TempHead,
1462            MapFileHeader->dataoffsets[i],sizeof(MapHeaderStr));
1463          strcpy(MapNames[i],TempHead.name);
1464         }
1465
1466     FigureScreenEdges();
1467
1468     if (!TEDInfo->level)
1469       {
1470        for(i=0;i<100;i++)
1471          if (MapFileHeader->dataoffsets[i]!=-1)
1472            {
1473             whichmap=TEDInfo->level=i;
1474             break;
1475            }
1476       }
1477     else
1478       whichmap=TEDInfo->level;
1479
1480     LoadMap(TEDInfo->level);
1481
1482     //
1483     // IF WE WERE LAUNCHED AND CHARACTER POSITION WAS CHANGED,
1484     // PUT IT BACK!
1485     //
1486     if (launched && (TEDInfo->lastx || TEDInfo->lasty))
1487       {
1488        int i;
1489
1490        for (i=0;i<mapwidth*mapheight;i++)
1491          if (MapInfoPl[i]==TEDInfo->permicon)
1492            {
1493             MapInfoPl[i]=0;
1494             MapInfoPl[TEDInfo->lasty*mapwidth+TEDInfo->lastx]=TEDInfo->permicon;
1495             TEDInfo->lastx=TEDInfo->lasty=0;
1496             DirtyFlag=1;
1497             break;
1498            }
1499       }
1500
1501     //
1502     // POSITION SCREEN
1503     //
1504     xbase=TEDInfo->oscrx;
1505     ybase=TEDInfo->oscry;
1506     if (xbase+screenw>mapwidth)
1507       xbase=mapwidth-screenw;
1508     if (ybase+screenh>mapheight)
1509       ybase=mapheight-screenh;
1510
1511     if (launched)
1512       _fmemcpy((void far *)parmstring,(void far *)TEDInfo->parmstring,64);
1513
1514     //
1515     // LOAD TILEINFO/M AND ADJUST IF IT CHANGED
1516     //
1517     numtplanes=MapFileHeader->numtplanes;
1518     numtmplanes=MapFileHeader->numtmplanes;
1519
1520     pflag=0;
1521     for (i=0;i<numtplanes;i++)
1522       {
1523        //
1524        // SPACE FOR OLD TILEINFO TO DECOMPRESS INTO
1525        //
1526        MMAllocate(&tempblock,MapFileHeader->oldtilenum);
1527        //
1528        // SPACE FOR OLD TILEINFO TO LOAD INTO
1529        //
1530        MMAllocate(&block,MapFileHeader->tileinfolen[i]);
1531        LoadFile(mapheadname,MK_FP(block,0),MapFileHeader->tileinfooff[i],MapFileHeader->tileinfolen[i]);
1532        //
1533        // DECOMPRESS FROM "BLOCK" TO "TEMPBLOCK"
1534        //
1535        RLEBExpand(MK_FP(block,0),MK_FP(tempblock,0),
1536            MapFileHeader->oldtilenum,MapFileHeader->RLEWtag);
1537        MMFreePtr(&block);
1538        //
1539        // ALLOCATE TINFO ARRAY
1540        //
1541        MMAllocate((memptr *)&Tinfo[i],tilenum);
1542        //
1543        // MOVE FROM "TEMPBLOCK" TO "TINFO[I]" ARRAY
1544        //
1545            if (MapFileHeader->oldtilenum<tilenum)
1546          {
1547           movedata((unsigned)tempblock,0,(unsigned)Tinfo[i],0,MapFileHeader->oldtilenum);
1548           //
1549           // IF NEW TILEINFO IS MORE, FILL END WITH 0s
1550           //
1551           for (j=MapFileHeader->oldtilenum;j<tilenum;j++)
1552             *(Tinfo[i]+j)=0;
1553           DirtyFlag=pflag=1;
1554          }
1555        else
1556          {
1557           movedata((unsigned)tempblock,0,(unsigned)Tinfo[i],0,tilenum);
1558           if (MapFileHeader->oldtilenum>tilenum)
1559             DirtyFlag=pflag=2;
1560          }
1561
1562        MMFreePtr(&tempblock);
1563       }
1564
1565     switch(pflag)
1566     {
1567      case 1:
1568        ErrDialog("The new TILEINFO data has\n"
1569                  "been expanded to accomodate\n"
1570                  "the newly grabbed tiles."," OK ");
1571        break;
1572      case 2:
1573        ErrDialog("The new TILEINFO data has\n"
1574                  "been shrunk due to a reduced\n"
1575                  "amount of tiles."," OK ");
1576     }
1577
1578     pflag=0;
1579     if (tilemnum && (MapFileHeader->maptype&FPLANE))
1580       for (i=0;i<numtmplanes;i++)
1581         {
1582          MMAllocate(&tempblock,MapFileHeader->oldtilemnum);
1583          MMAllocate(&block,MapFileHeader->tileinfomlen[i]);
1584          LoadFile(mapheadname,MK_FP(block,0),MapFileHeader->tileinfomoff[i],MapFileHeader->tileinfomlen[i]);
1585          RLEBExpand(MK_FP(block,0),MK_FP(tempblock,0),
1586              MapFileHeader->oldtilemnum,MapFileHeader->RLEWtag);
1587          MMFreePtr(&block);
1588          MMAllocate((memptr *)&TMinfo[i],tilemnum);
1589          if (MapFileHeader->oldtilemnum<tilemnum)
1590            {
1591             movedata((unsigned)tempblock,0,(unsigned)TMinfo[i],0,MapFileHeader->oldtilemnum);
1592             for (j=MapFileHeader->oldtilemnum;j<tilemnum;j++)
1593               *(TMinfo[i]+j)=0;
1594             DirtyFlag=pflag=1;
1595            }
1596          else
1597            {
1598             movedata((unsigned)tempblock,0,(unsigned)TMinfo[i],0,tilemnum);
1599             if (MapFileHeader->oldtilemnum>tilemnum)
1600               DirtyFlag=pflag=2;
1601            }
1602
1603          MMFreePtr(&tempblock);
1604         }
1605
1606     switch(pflag)
1607     {
1608      case 1:
1609        ErrDialog("The new TILEINFOM data has\n"
1610                  "been expanded to accomodate\n"
1611                  "the newly grabbed masked tiles."," OK ");
1612        break;
1613      case 2:
1614        ErrDialog("The new TILEINFOM data has\n"
1615                  "been shrunk due to a reduced\n"
1616                  "amount of tiles."," OK ");
1617     }
1618
1619     #if 0
1620     //
1621     // TURN ON PLANES
1622     //
1623     viewton=planeton=1;
1624     if (MapFileHeader->maptype&FPLANE)
1625       viewmon=1;
1626     if (MapFileHeader->maptype&IPLANE)
1627       viewion=1;
1628     planemon=planeion=0;
1629     #endif
1630
1631    }
1632
1633  //
1634  // LOAD THE MAPFILE INTO XMS IF ENOUGH ROOM
1635  //
1636  if (1024L*XMSTotalFree()>2L*filelen(mapname) && !NoXMSFlag)
1637    {
1638     #define LBCSIZE     0x4000
1639     memptr block;
1640     long size,clen,coff;
1641
1642
1643     size=filelen(mapname);
1644     MMAllocate(&block,LBCSIZE);
1645     XMSmaps=XMSAllocate(size);
1646
1647     //
1648     // LOAD ENTIRE MAPFILE FROM DISK TO XMS!
1649     //
1650     coff=0;
1651     do
1652     {
1653      clen=LBCSIZE;
1654      if (size<LBCSIZE)
1655        clen=size;
1656
1657      LoadFile(mapname,MK_FP(block,0),coff,clen);
1658      XMSmove(0,(long)MK_FP(block,0),XMSmaps,coff,clen);
1659      size-=LBCSIZE;
1660      coff+=clen;
1661     } while(size>0);
1662
1663     MMFreePtr(&block);
1664    }
1665
1666 }
1667
1668 void STnot(int x,int y)
1669 {
1670  sx=x+10;
1671  sy=y+2;
1672  if (!GFXInfo->num8)
1673    print("<-Not available");
1674  else
1675    {
1676     printint(GFXInfo->num8);
1677     print(" total tiles");
1678    }
1679  sx=x+10;
1680  sy=y+5;
1681  if (!GFXInfo->num16)
1682    print("<-Not available");
1683  else
1684    {
1685     printint(GFXInfo->num16);
1686     print(" total tiles");
1687    }
1688  sx=x+10;
1689  sy=y+8;
1690  if (!GFXInfo->num32)
1691    print("<-Not available");
1692  else
1693    {
1694     printint(GFXInfo->num32);
1695     print(" total tiles");
1696    }
1697 }
1698
1699
1700 ////////////////////////////////////////////////////
1701 ////////////////////////////////////////////////////
1702 //
1703 // Load the graphheader file & ?GAGRAPH.ext file and stick it in XMS!
1704 //
1705 ////////////////////////////////////////////////////
1706 ////////////////////////////////////////////////////
1707 int LoadGraphStuff(int rtn,video newvid)
1708 {
1709  #define NUMFASTDECOMP  100     // # of tiles in fast decompress buffer
1710
1711  char gname[14]="?GAHEAD.",gname1[14]="?GAGRAPH.",_seg *packed,_seg *unpack,
1712       dictname[14]="?GADICT.",hufftable[1020],_seg *CacheBlock;
1713  unsigned index,indexm,num,numm,i,realnum,realnumm,ox,oy,cacheon=0,_seg *tile_len,
1714       _seg *tilem_len,cacheon_h;
1715  long expsize,expmsize,xmsoff=0,unpackoff,unpackmax,unpacksize,
1716       unpackxms;
1717  video tempvid,pickedvid;
1718
1719  char huge *offsets;
1720
1721
1722
1723  strcat(gname,ext);
1724  strcat(gname1,ext);
1725  strcat(dictname,ext);
1726  gname[0]=format[0];
1727  gname1[0]=format[0];
1728  dictname[0]=format[0];
1729
1730  if (!launched)
1731    switch(format[0])
1732    {
1733         case 'C': pickedvid=CGA; break;
1734         case 'E': pickedvid=EGA1; break;
1735         case 'V': pickedvid=VGA;
1736    }
1737  else
1738    pickedvid=TEDInfo->lastvid;
1739
1740  //
1741  // VALIDATE GRAPHICS MODE
1742  //
1743  tempvid=rtn?newvid:pickedvid;
1744  switch(tempvid)
1745  {
1746   case CGA:
1747         gname[0]='C';
1748         if (access(gname,0))
1749           {
1750            if (rtn)
1751                  return 0;
1752           }
1753         else
1754           {
1755            TEDInfo->lastvid=CGA;
1756            dictname[0]=format[0]=gname1[0]='C';
1757            setvideo(CGA);
1758            InitDesktop(TED5MenuBar,1);
1759            MouseShow();
1760            break;
1761           }
1762   case EGA1:
1763   case EGA2:
1764         gname[0]='E';
1765         if (access(gname,0))
1766           {
1767            if (rtn)
1768          return 0;
1769           }
1770         else
1771           {
1772            TEDInfo->lastvid=tempvid;
1773            dictname[0]=format[0]=gname1[0]='E';
1774            setvideo(tempvid);
1775            InitDesktop(TED5MenuBar,1);
1776            MouseShow();
1777            break;
1778           }
1779   case VGA:
1780         gname[0]='V';
1781         if (access(gname,0))
1782           {
1783            if (rtn)
1784          return 0;
1785
1786        gname[0]=format[0];
1787       }
1788     else
1789       {
1790        TEDInfo->lastvid=VGA;
1791        dictname[0]=format[0]=gname1[0]='V';
1792        setvideo(VGA);
1793        InitDesktop(TED5MenuBar,1);
1794        MouseShow();
1795        break;
1796       }
1797  }
1798
1799
1800  //
1801  // FIND HEADER & LOAD IT
1802  //
1803  if (access(gname,0))
1804    {
1805     char errstr[100]="Can't find the ";
1806
1807     strcat(errstr,format);
1808     strcat(errstr,"GAHEAD.");
1809     strcat(errstr,ext);
1810     strcat(errstr,"\nfile! Maybe you didn't\n"
1811                   "copy it from the graphics\n"
1812                   "subdirectory?");
1813
1814     ErrDialog(errstr," OK ");
1815     if (rtn)
1816       return 0;
1817     Quit("You're stupid! Copy the damn file!");
1818    }
1819
1820  LoadIn(gname,(memptr *)&GraphHeader);
1821
1822  switch(MapFileHeader->tsize)
1823  {
1824   case 1:
1825     index=GFXInfo->off8;
1826     indexm=GFXInfo->off8m;
1827     num=GFXInfo->num8;
1828     numm=GFXInfo->num8m;
1829     if (indexm==index+1)
1830       {
1831        ErrDialog("I'm sorry, but you need to\n"
1832                  "capture your 8x8 tiles\n"
1833                  "individually, and not in a\n"
1834                  "big chunk."," Alright ");
1835        if (rtn)
1836          return 0;
1837        Quit("Regrab-time, bag o' shit!");
1838       }
1839
1840     switch(tempvid)
1841     {
1842      case CGA: expsize=16; expmsize=32; break;
1843      case EGA1:
1844      case EGA2: expsize=32; expmsize=40; break;
1845          case VGA: expsize=64; expmsize=128;
1846     }
1847     break;
1848   case 2:
1849     index=GFXInfo->off16;
1850     indexm=GFXInfo->off16m;
1851     num=GFXInfo->num16;
1852     numm=GFXInfo->num16m;
1853     switch(tempvid)
1854     {
1855      case CGA: expsize=64; expmsize=128; break;
1856      case EGA1:
1857      case EGA2: expsize=128; expmsize=128+32; break;
1858      case VGA: expsize=256; expmsize=512;
1859     }
1860     break;
1861   case 3:
1862     index=GFXInfo->off32;
1863     indexm=GFXInfo->off32m;
1864     num=GFXInfo->num32;
1865     numm=GFXInfo->num32m;
1866     switch(tempvid)
1867         {
1868      case CGA: expsize=256; expmsize=512; break;
1869      case EGA1:
1870      case EGA2: expsize=512; expsize=512+4*32; break;
1871      case VGA: expsize=1024; expmsize=2048;
1872     }
1873  }
1874
1875  //
1876  // MOVE TILES INTO XMS MEMORY!
1877  //
1878
1879  MMAllocate((memptr *)&packed,expmsize);
1880  unpackmax=expmsize*NUMFASTDECOMP;
1881  MMAllocate((memptr *)&unpack,unpackmax);
1882
1883
1884  tilelen=expsize;
1885  tilemlen=expmsize;
1886  offsets=MK_FP(GraphHeader,0);
1887
1888  //
1889  // LOAD DICTIONARY IN & INITIALIZE IT
1890  //
1891  if (!launched)
1892    {
1893     char _seg *block;
1894
1895     if (access(dictname,0))
1896       {
1897        char errst[200]="I can't find the \n";
1898
1899        strcat(errst,dictname);
1900        strcat(errst," file!");
1901
1902        ErrDialog(errst," OK ");
1903        if (rtn)
1904          return 0;
1905        Quit("Look in the graphics grab directory!");
1906       }
1907
1908     LoadIn(dictname,(memptr *)&block);
1909     movedata((unsigned)block,0,FP_SEG(hufftable),FP_OFF(hufftable),1020);
1910     MMFreePtr((memptr *)&block);
1911     OptimizeNodes((huffnode *)hufftable);
1912    }
1913
1914  //
1915  // Count up the REAL number of tiles there are!
1916  // Build tables for tile lengths
1917  //
1918  MMAllocate((memptr *)&tile_len,num*2);
1919  for (realnum=i=0;i<num;i++)
1920  {
1921   int j;
1922
1923
1924
1925   if (OFF3(offsets,i+index)!=0xffffff)
1926   {
1927    realnum++;
1928    if (OFF3(offsets,i+index+1)!=0xffffff)
1929      tile_len[i]=OFF3(offsets,i+index+1)-OFF3(offsets,i+index);
1930    else
1931      for (j=i+1;j<num+numm;j++)
1932        if (OFF3(offsets,j+index)!=0xffffff)
1933        {
1934         tile_len[i]=OFF3(offsets,j+index)-OFF3(offsets,i+index);
1935         break;
1936        }
1937   }
1938   else
1939     tile_len[i]=0;
1940
1941  }
1942  MMAllocate((memptr *)&tilem_len,numm*2);
1943  for (realnumm=i=0;i<numm;i++)
1944  {
1945   int j;
1946
1947
1948   if (OFF3(offsets,i+indexm)!=0xffffff)
1949   {
1950    realnumm++;
1951    if (OFF3(offsets,i+indexm+1)!=0xffffff)
1952      tilem_len[i]=OFF3(offsets,i+indexm+1)-OFF3(offsets,i+indexm);
1953    else
1954      for (j=i+1;j<numm+1;j++)
1955        if (OFF3(offsets,j+indexm)!=0xffffff)
1956        {
1957         tilem_len[i]=OFF3(offsets,j+indexm)-OFF3(offsets,i+indexm);
1958         break;
1959        }
1960   }
1961   else
1962     tilem_len[i]=0;
1963  }
1964
1965  //
1966  // DON'T REALLOCATE THIS IF WE'RE COMING BACK FROM A LAUNCH!
1967  //
1968  if (!launched)
1969    {
1970     long size=expsize*realnum+expmsize*realnumm,savings=0;
1971
1972
1973     if (1024L*XMSTotalFree()<size)
1974       {
1975        savings=CgaXMSsize+EgaXMSsize+VgaXMSsize;
1976        if (1024L*XMSTotalFree()<size-savings)
1977          {
1978           MouseShow();
1979           ErrDialog("Not enough memory to load\n"
1980                     "requested graphics.\n"," OK ");
1981
1982           MMFreePtr((memptr *)&GraphHeader);
1983           MMFreePtr((memptr *)&packed);
1984           MMFreePtr((memptr *)&unpack);
1985
1986           if (rtn)
1987             return -1;
1988           else
1989             Quit("Get more Extended memory!");
1990          }
1991
1992        if (CgaXMS)
1993          {
1994           XMSFreeMem(CgaXMS);
1995           MMFreePtr((memptr *)&CgaXMSlookup);
1996          }
1997        if (EgaXMS)
1998          {
1999           XMSFreeMem(EgaXMS);
2000           MMFreePtr((memptr *)&EgaXMSlookup);
2001          }
2002            if (VgaXMS)
2003          {
2004           XMSFreeMem(VgaXMS);
2005           MMFreePtr((memptr *)&VgaXMSlookup);
2006          }
2007        CgaXMSsize=EgaXMSsize=VgaXMSsize=CgaXMS=EgaXMS=VgaXMS=0;
2008       }
2009
2010     switch(tempvid)
2011     {
2012      case CGA:
2013        xmshandle=CgaXMS=XMSAllocate(size);
2014        CgaXMSsize=size;
2015        break;
2016      case EGA1:
2017      case EGA2:
2018        xmshandle=EgaXMS=XMSAllocate(size);
2019        EgaXMSsize=size;
2020        break;
2021      case VGA:
2022        xmshandle=VgaXMS=XMSAllocate(size);
2023        VgaXMSsize=size;
2024     }
2025
2026     ErrDialog("GRAPHICS INSTALLATION\n"
2027               "Decompressing and\n"
2028               "moving tiles into\n"
2029               "Extended memory:","");
2030    }
2031  else
2032    {
2033     long size;
2034
2035
2036     CgaXMS=TEDInfo->OldCgaXMS;
2037     EgaXMS=TEDInfo->OldEgaXMS;
2038     VgaXMS=TEDInfo->OldVgaXMS;
2039
2040     CgaXMSsize=TEDInfo->OldCgaXMSsize;
2041     EgaXMSsize=TEDInfo->OldEgaXMSsize;
2042     VgaXMSsize=TEDInfo->OldVgaXMSsize;
2043
2044     size=(num+numm)*4;
2045     if (CgaXMS)
2046       {
2047            MMAllocate((memptr *)&CgaXMSlookup,size);
2048        XMSmove(TEDInfo->CgaXMSlook,0,0,(long)MK_FP(CgaXMSlookup,0),size);
2049        XMSFreeMem(TEDInfo->CgaXMSlook);
2050        TEDInfo->CgaXMSlook=0;
2051       }
2052     if (EgaXMS)
2053       {
2054        MMAllocate((memptr *)&EgaXMSlookup,size);
2055        XMSmove(TEDInfo->EgaXMSlook,0,0,(long)MK_FP(EgaXMSlookup,0),size);
2056        XMSFreeMem(TEDInfo->EgaXMSlook);
2057        TEDInfo->EgaXMSlook=0;
2058       }
2059     if (VgaXMS)
2060       {
2061        MMAllocate((memptr *)&VgaXMSlookup,size);
2062        XMSmove(TEDInfo->VgaXMSlook,0,0,(long)MK_FP(VgaXMSlookup,0),size);
2063        XMSFreeMem(TEDInfo->VgaXMSlook);
2064        TEDInfo->VgaXMSlook=0;
2065       }
2066
2067     switch(tempvid)
2068     {
2069      case CGA:
2070        xmshandle=CgaXMS;
2071        XMSlookup=CgaXMSlookup;
2072        break;
2073      case EGA1:
2074      case EGA2:
2075        xmshandle=EgaXMS;
2076        XMSlookup=EgaXMSlookup;
2077        break;
2078      case VGA:
2079        xmshandle=VgaXMS;
2080        XMSlookup=VgaXMSlookup;
2081     }
2082
2083     ErrDialog("RE-INITIALIZING...","");
2084    }
2085
2086  ox=sx;
2087  oy=sy;
2088
2089  //
2090  // INSTALL GRAPHICS IF NOT A LAUNCH...
2091  //
2092  if (!launched)
2093  {
2094   switch(tempvid)
2095   {
2096    case CGA:
2097      MMAllocate((memptr *)&CgaXMSlookup,(num+numm)*4);
2098      XMSlookup=CgaXMSlookup;
2099      break;
2100    case EGA1:
2101    case EGA2:
2102      MMAllocate((memptr *)&EgaXMSlookup,(num+numm)*4);
2103      XMSlookup=EgaXMSlookup;
2104      break;
2105    case VGA:
2106      MMAllocate((memptr *)&VgaXMSlookup,(num+numm)*4);
2107      XMSlookup=VgaXMSlookup;
2108   }
2109
2110
2111   //
2112   // SET UP MEMORY CACHE IF ENOUGH IS AVAILABLE...
2113   //
2114   cacheon_h=0;
2115   if (filelen(gname1)<16L*MMTotalFree())
2116   {
2117    LoadIn(gname1,(memptr *)&CacheBlock);
2118    cacheon=1;
2119   }
2120   else
2121   //
2122   // DAMN! TRY XMS AS A LAST RESORT...
2123   //
2124   if (filelen(gname1)<1024l*XMSTotalFree())
2125   {
2126    #define TMPBUFSIZE 32000l
2127    long amtleft,tmpoff=0,tmpsize;
2128    memptr tblock;
2129
2130
2131    amtleft=filelen(gname1);
2132    MMAllocate(&tblock,TMPBUFSIZE);
2133    cacheon_h=XMSAllocate(amtleft);
2134    tmpsize=TMPBUFSIZE;
2135    while(amtleft>0)
2136    {
2137         LoadFile(gname1,MK_FP(tblock,0),tmpoff,tmpsize);
2138     XMSmove(0,(long)MK_FP(tblock,0),cacheon_h,tmpoff,tmpsize);
2139     amtleft-=TMPBUFSIZE;
2140     tmpoff+=TMPBUFSIZE;
2141     tmpsize=(amtleft>TMPBUFSIZE)?TMPBUFSIZE:amtleft;
2142    }
2143
2144    MMFreePtr(&tblock);
2145    cacheon=2;
2146   }
2147
2148   clearkeys();
2149
2150   //
2151   // MOVE NONMASKED TILES INTO XMS MEMORY!
2152   //      ---------
2153   unpacksize=unpackoff=0;
2154   unpackxms=xmsoff;
2155   for (i=0;i<num;i++)
2156   {
2157    long size,off;
2158
2159
2160    off=OFF3(offsets,index+i);
2161    if (off==0xffffff)   // SPARSE TILE?
2162      {
2163       *(XMSlookup+i)=-1;
2164       continue;
2165      }
2166
2167    size=tile_len[i];
2168
2169    //
2170    // GET COMPRESSED TILE DATA FROM CACHE OR DISK
2171    //
2172    if (cacheon==1)
2173    {
2174     //
2175     // HUFFMAN DECOMPRESS
2176     //
2177     HuffExpand((unsigned char huge *)CacheBlock+off,(unsigned char huge *)unpack+unpackoff,
2178           expsize,(huffnode *)hufftable);
2179    }
2180    else
2181    if (cacheon==2)
2182    {
2183     XMSmove(cacheon_h,off,0,(long)packed,size);
2184     //
2185     // HUFFMAN DECOMPRESS
2186     //
2187     HuffExpand((unsigned char huge *)packed,(unsigned char huge *)unpack+unpackoff,
2188           expsize,(huffnode *)hufftable);
2189    }
2190    else
2191    {
2192     LoadFile(gname1,(char huge *)packed,off,size);
2193     //
2194     // HUFFMAN DECOMPRESS
2195     //
2196     HuffExpand((unsigned char huge *)packed,(unsigned char huge *)unpack+unpackoff,
2197           expsize,(huffnode *)hufftable);
2198    }
2199
2200    unpacksize+=expsize;
2201    unpackoff+=expsize;
2202
2203    *(XMSlookup+i)=xmsoff;
2204    xmsoff+=expsize;
2205
2206    if (unpacksize>unpackmax-expsize)
2207    {
2208     XMSmove(0,(long)MK_FP(unpack,0),xmshandle,unpackxms,unpacksize);
2209     unpacksize=unpackoff=0;
2210     unpackxms=xmsoff;
2211
2212     sx=ox;
2213     sy=oy;
2214     printint(num+numm-i);
2215     print(" ");
2216    }
2217
2218    //
2219    // ESC will exit!
2220    //
2221    if (keydown[1])
2222      if (rtn)
2223      {
2224       switch(tempvid)
2225       {
2226        case CGA:
2227          XMSFreeMem(CgaXMS);
2228          MMFreePtr((memptr *)&CgaXMSlookup);
2229          CgaXMS=0;
2230          break;
2231        case EGA1:
2232        case EGA2:
2233          XMSFreeMem(EgaXMS);
2234          MMFreePtr((memptr *)&EgaXMSlookup);
2235          EgaXMS=0;
2236          break;
2237        case VGA:
2238          XMSFreeMem(VgaXMS);
2239          MMFreePtr((memptr *)&VgaXMSlookup);
2240          VgaXMS=0;
2241       }
2242
2243       switch(videomode)
2244       {
2245        case CGA:
2246          xmshandle=CgaXMS;
2247          XMSlookup=CgaXMSlookup;
2248          break;
2249        case EGA1:
2250        case EGA2:
2251          xmshandle=EgaXMS;
2252          XMSlookup=EgaXMSlookup;
2253          break;
2254        case VGA:
2255          xmshandle=VgaXMS;
2256          XMSlookup=VgaXMSlookup;
2257       }
2258
2259       MMFreePtr((memptr *)&GraphHeader);
2260       MMFreePtr((memptr *)&packed);
2261       MMFreePtr((memptr *)&unpack);
2262
2263       if (cacheon)
2264         MMFreePtr((memptr *)&CacheBlock);
2265
2266       return 0;
2267      }
2268      else
2269        Quit("XMS LOADING ABORTED!");
2270   }
2271
2272   //
2273   // FLUSH THE FAST(?)-CACHE
2274   //
2275   if (unpacksize)
2276   {
2277    XMSmove(0,(long)MK_FP(unpack,0),xmshandle,unpackxms,unpacksize);
2278    unpacksize=unpackoff=0;
2279    unpackxms=xmsoff;
2280   }
2281
2282   //
2283   // MOVE MASKED TILES INTO XMS MEMORY!
2284   //      ------
2285   for (i=0;i<numm;i++)
2286   {
2287    long size,off;
2288
2289    off=OFF3(offsets,indexm+i);
2290    if (off==0xffffff)   // SPARSE TILE?
2291          {
2292           *(XMSlookup+i+num)=-1;
2293           continue;
2294      }
2295
2296    size=tilem_len[i];
2297
2298    //
2299    // GET COMPRESSED TILE DATA FROM CACHE OR DISK
2300    //
2301    if (cacheon==1)
2302    {
2303     //
2304     // HUFFMAN DECOMPRESS
2305     //
2306     HuffExpand((unsigned char huge *)CacheBlock+off,(unsigned char huge *)unpack+unpackoff,
2307           expmsize,(huffnode *)hufftable);
2308    }
2309    else
2310    if (cacheon==2)
2311    {
2312     XMSmove(cacheon_h,off,0,(long)packed,size);
2313     //
2314     // HUFFMAN DECOMPRESS
2315     //
2316     HuffExpand((unsigned char huge *)packed,(unsigned char huge *)unpack+unpackoff,
2317           expmsize,(huffnode *)hufftable);
2318    }
2319    else
2320    {
2321     LoadFile(gname1,(char huge *)packed,off,size);
2322     //
2323     // HUFFMAN DECOMPRESS
2324     //
2325     HuffExpand((unsigned char huge *)packed,(unsigned char huge *)unpack+unpackoff,
2326           expmsize,(huffnode *)hufftable);
2327    }
2328
2329    unpacksize+=expmsize;
2330    unpackoff+=expmsize;
2331
2332    *(XMSlookup+i+num)=xmsoff;
2333    xmsoff+=expmsize;
2334
2335    if (unpacksize>unpackmax-expmsize)
2336    {
2337     XMSmove(0,(long)MK_FP(unpack,0),xmshandle,unpackxms,unpacksize);
2338         unpacksize=unpackoff=0;
2339     unpackxms=xmsoff;
2340
2341     sx=ox;
2342     sy=oy;
2343     printint(numm-i);
2344     print(" ");
2345    }
2346
2347
2348    //
2349    // ESC will exit!
2350    //
2351    if (keydown[1])
2352      if (rtn)
2353      {
2354       switch(tempvid)
2355       {
2356        case CGA:
2357          XMSFreeMem(CgaXMS);
2358          MMFreePtr((memptr *)&CgaXMSlookup);
2359          CgaXMS=0;
2360          break;
2361        case EGA1:
2362        case EGA2:
2363          XMSFreeMem(EgaXMS);
2364          MMFreePtr((memptr *)&EgaXMSlookup);
2365          EgaXMS=0;
2366          break;
2367        case VGA:
2368          XMSFreeMem(VgaXMS);
2369          MMFreePtr((memptr *)&VgaXMSlookup);
2370          VgaXMS=0;
2371       }
2372
2373       switch(videomode)
2374       {
2375        case CGA:
2376          xmshandle=CgaXMS;
2377          XMSlookup=CgaXMSlookup;
2378          break;
2379        case EGA1:
2380        case EGA2:
2381          xmshandle=EgaXMS;
2382          XMSlookup=EgaXMSlookup;
2383          break;
2384        case VGA:
2385          xmshandle=VgaXMS;
2386          XMSlookup=VgaXMSlookup;
2387       }
2388
2389       MMFreePtr((memptr *)&GraphHeader);
2390       MMFreePtr((memptr *)&packed);
2391       MMFreePtr((memptr *)&unpack);
2392
2393       if (cacheon)
2394         MMFreePtr((memptr *)&CacheBlock);
2395
2396       return 0;
2397      }
2398      else
2399        Quit("XMS LOADING ABORTED!");
2400   }
2401   //
2402   // FLUSH THE FAST-CACHE
2403   //
2404   if (unpacksize)
2405   {
2406    XMSmove(0,(long)MK_FP(unpack,0),xmshandle,unpackxms,unpacksize);
2407    unpacksize=unpackoff=0;
2408    unpackxms=xmsoff;
2409   }
2410
2411   if (cacheon==1)
2412     MMFreePtr((memptr *)&CacheBlock);
2413   else
2414   if (cacheon==2)
2415     XMSFreeMem(cacheon_h);
2416  }
2417
2418  //
2419  // GET RID OF TILE-FILE CACHE MEMORY (OR WE'RE TOASTY)
2420  //
2421  MMFreePtr((memptr *)&GraphHeader);
2422  MMFreePtr((memptr *)&packed);
2423  MMFreePtr((memptr *)&unpack);
2424
2425  MMFreePtr((memptr *)&tile_len);
2426  MMFreePtr((memptr *)&tilem_len);
2427
2428  whicht=0;
2429  whichi=tilenum;
2430  whichtm=tilenum;
2431
2432  switch(tsize)
2433  {
2434   case 1: lasticon=tilenum+36*maxiconrows;
2435           break;
2436   case 2: lasticon=tilenum+18*maxiconrows;
2437           break;
2438   case 3: lasticon=tilenum+7*maxiconrows;
2439  }
2440  firsticon=tilenum;
2441
2442  RestoreBackground();
2443  return 1;
2444 }
2445
2446
2447 ////////////////////////////////////////////////////
2448 ////////////////////////////////////////////////////
2449 //
2450 // Load TEDINFO.ext file
2451 //
2452 ////////////////////////////////////////////////////
2453 ////////////////////////////////////////////////////
2454 void LoadInfoFile(void)
2455 {
2456  char pname[14]="TEDINFO.",gfxname[14]="GFXINFO";
2457
2458
2459  //
2460  // Load the TEDINFO.ext file!
2461  //
2462  strcat(pname,ext);
2463  strcpy(infoname,pname);
2464
2465  if (access(pname,0))
2466    {
2467     MMAllocate((memptr *)&TEDInfo,sizeof(InfoStruct));
2468     _fmemset(TEDInfo,0,sizeof(InfoStruct));
2469                                 //  BFI  BFI
2470     TEDInfo->pflags=0x27;       // 0010 0111
2471    }
2472  else
2473    LoadIn(pname,(memptr *)&TEDInfo);
2474
2475  tsize=TEDInfo->tsize;
2476  if (launchname[0])
2477    _fmemcpy((char far *)TEDInfo->launchname,(char far *)launchname,14);
2478
2479  //
2480  // LOAD THE "GFXINFO?.EXT" FILE
2481  //
2482  strcat(gfxname,format);
2483  strcat(gfxname,".");
2484  strcat(gfxname,ext);
2485  LoadIn(gfxname,(memptr *)&GFXInfo);
2486
2487  switch(tsize)
2488  {
2489   case 1:
2490     tilenum=GFXInfo->num8;
2491     tilemnum=GFXInfo->num8m;
2492     break;
2493   case 2:
2494     tilenum=GFXInfo->num16;
2495     tilemnum=GFXInfo->num16m;
2496     break;
2497   case 3:
2498     tilenum=GFXInfo->num32;
2499     tilemnum=GFXInfo->num32m;
2500  }
2501
2502  _fstrcpy((char far *)launchname,(char far *)TEDInfo->launchname);
2503
2504  if (launched)
2505    TEDInfo->lastvid=LaunchInfo.lastmode;
2506
2507  //
2508  // SET PLANE FLAGS BACK TO NORMAL
2509  //
2510  planeton=(TEDInfo->pflags>>6)&1;
2511  planemon=(TEDInfo->pflags>>5)&1;
2512  planeion=(TEDInfo->pflags>>4)&1;
2513  viewton=(TEDInfo->pflags>>2)&1;
2514  viewmon=(TEDInfo->pflags>>1)&1;
2515  viewion=(TEDInfo->pflags)&1;
2516
2517  //
2518  // SET BACKGROUND COLOR
2519  //
2520  BkgndColor=TEDInfo->BackgndColor;
2521  if (BkgndColor>16)
2522    TEDInfo->BackgndColor=BkgndColor=O_FGNDBACK;
2523 }
2524
2525
2526 ////////////////////////////////////////////////////
2527 ////////////////////////////////////////////////////
2528 //
2529 // Find ?GAGRAPH.ext file
2530 //
2531 ////////////////////////////////////////////////////
2532 ////////////////////////////////////////////////////
2533 void FindGraphFile(void)
2534 {
2535  struct ffblk ffblk;
2536  char pname[15]="?GAGRAPH.*",*tempstr,tiname[13]="TEDINFO.TMP";
2537  int i,which;
2538
2539
2540  //
2541  // RETURNING FROM LAUNCH...GET INFO BACK
2542  //
2543  if (launched)
2544    {
2545         LoadFile(tiname,(char huge *)&LaunchInfo,0,0);
2546         unlink(tiname);
2547         videomode=LaunchInfo.lastmode;
2548         switch(videomode)
2549         {
2550          case CGA:
2551            format[0]='C';
2552            break;
2553          case EGA1:
2554          case EGA2:
2555            format[0]='E';
2556            break;
2557          case VGA:
2558            format[0]='V';
2559         }
2560
2561         strcpy(ext,LaunchInfo.ext);
2562         projname[0]=format[0];
2563         strcat(projname,"GAGRAPH.");
2564         strcat(projname,ext);
2565         return;
2566    }
2567
2568  //
2569  // Find ?GAGRAPH.ext
2570  //
2571  if (ext[0])
2572    {
2573         strcpy(pname,"?GAGRAPH.");
2574         strcat(pname,ext);
2575    }
2576
2577  if (findfirst(pname,&ffblk,FA_ARCH))
2578    {
2579         ErrDialog("I can't find a graphics\nfile! (ex:?GAGRAPH.ext)"," Alright ");
2580         Quit("Can't work without graphics ya know!");
2581    }
2582
2583
2584  if (GfxToUse)
2585    format[0] = GfxToUse;
2586  else
2587  {
2588   // setup the dialog
2589
2590   strcpy(bstrings[0],ffblk.ff_name);
2591   ProjButns[0].xoff=9;
2592   ProjButns[0].yoff=2;
2593   ProjButns[0].border=0;
2594   ProjButns[0].text=bstrings[0];
2595   for (i=1;i<10;i++)
2596         {
2597          if (findnext(&ffblk))
2598            break;
2599          strcpy(bstrings[i],ffblk.ff_name);
2600          ProjButns[i].xoff=9;
2601          ProjButns[i].yoff=2+i;
2602          ProjButns[i].border=0;
2603          ProjButns[i].text=bstrings[i];
2604         }
2605   ProjSelect.numbuttons=i;
2606   ProjSelect.height=i+3;
2607
2608   which=1;
2609   if (i>1)
2610         do
2611         {
2612          which=DoDialog(&ProjSelect);
2613         } while(!which);
2614   which--;
2615
2616   tempstr=strpbrk(bstrings[which],".")+1;
2617   strcpy(ext,tempstr);
2618   format[0]=bstrings[which][0];
2619  }
2620
2621  strcpy(projname,bstrings[which]);
2622 }
2623
2624 //
2625 // draw border for project window
2626 //
2627 void DrawProjBord(int x,int y)
2628 {
2629  DrawBorder(x+8,y+1,13,ProjSelect.height-2,1);
2630 }
2631
2632
2633 ////////////////////////////////////////////////////
2634 //
2635 // Input amount of icons to reserve
2636 // Returns maximum # of icon rows to reserve
2637 //
2638 ////////////////////////////////////////////////////
2639 btype ICb={"    ",8,3,1};
2640 DialogDef ICd={"Enter maximum amount\nof icons to reserve:",20,5,1,&ICb,NULL};
2641
2642 int InputIconAmount(void)
2643 {
2644  char tempstr[4];
2645  int value;
2646
2647
2648  if (!(MapFileHeader->maptype&IPLANE))
2649    return 4;
2650
2651  MouseHide();
2652  DrawDialog(&ICd,1);
2653  while(1)
2654  {
2655   GetDialogXY(&ICd,&sx,&sy);
2656   GetButtonXY(&ICd,0,&sx,&sy);
2657   if (input(tempstr,3))
2658   {
2659    value=atoi(tempstr);
2660    if (value>0)
2661    {
2662     MouseShow();
2663     RestoreBackground();
2664     return (value+17)/18;
2665    }
2666   }
2667  }
2668 }
2669
2670
2671 ////////////////////////////////////////////////////
2672 ////////////////////////////////////////////////////
2673 //
2674 // Unhook everything
2675 //
2676 ////////////////////////////////////////////////////
2677 ////////////////////////////////////////////////////
2678 void Unhook(void)
2679 {
2680  ShutdownKBD();
2681  if (CgaXMS)
2682    XMSFreeMem(CgaXMS);
2683  if (EgaXMS)
2684    XMSFreeMem(EgaXMS);
2685  if (VgaXMS)
2686    XMSFreeMem(VgaXMS);
2687  if (XMSundoB)
2688    XMSFreeMem(XMSundoB);
2689  if (XMSundoF)
2690    XMSFreeMem(XMSundoF);
2691  if (XMSundoI)
2692    XMSFreeMem(XMSundoI);
2693  if (XMSmaps)
2694    XMSFreeMem(XMSmaps);
2695 }
2696
2697 void PatchPointers(void)
2698 {
2699 }
2700
2701
2702 ////////////////////////////////////////////////////
2703 ////////////////////////////////////////////////////
2704 //
2705 // Menu Definitions
2706 //
2707 ////////////////////////////////////////////////////
2708 ////////////////////////////////////////////////////
2709 MenuDef AboutMenu[]=
2710   {{"About...",Item_About,0,0},
2711    {"Video Mode Switch",Item_ModeSwitch,0,0x43},
2712    {"Last Video Mode",Item_LastVideo,ALT,0x2c},
2713    {"Memory Available",Item_PrintMem,0,0x44},
2714    {"Launch Project",Item_Launch,ALT,0x26},
2715    {"--------------------",NULL,0,0},
2716 //   {"Display Unused Tiles",Item_CountTiles,0,0},
2717    {"Project Re-Select",Item_ProjectReSelect,0,0},
2718    {"Visit DOS",Item_VisitDOS,0,0}
2719   };
2720
2721 MenuDef FileMenu[]=
2722   {{"Edit New Map",Item_EditMap,ALT,0x18},
2723    {"Save Map",Item_SaveMap,ALT,0x1f},
2724    {"Create Map",Item_CreateMap,ALT,0x2e},
2725    {"Delete Map",Item_DeleteMap,ALT,0x20},
2726    {"Switch Map",Item_SwitchMap,ALT,0x11},
2727    {"Amputate Maps",Item_Amputate},
2728    {"---------------",NULL,0,0},
2729    {"Import Maps",Item_ImportMaps,0,0},
2730    {"Change ICON Rows",Item_ChangeIconRows,0,0},
2731    {"Carmacize Maps",Item_Huffman,0,0},
2732    {"Quit TED5",Item_Quit,ALT,0x2d}};
2733
2734 MenuDef EditMenu[]=
2735   {{"Switch to Last Map",Item_LastMap,ALT,0x32},
2736    {"Edit TILEINFO/M Values",Item_EditTinfoValues,ALT,0x14},
2737    {"Change LAUNCH name",Item_LAUNCHname,0,0},
2738    {"Change PARM string",Item_PARMstring,0,0},
2739    {"Edit TILEINFO/M Names",Item_EditTinfoNames,0,0},
2740    {"Add/Del TILEINFO/M Planes",Item_AddDelTinfo,0,0},
2741    {"Edit MAP Names",Item_EditMapNames,0,0},
2742    {"Change MAP Edges",Item_EditMapEdges,0,0}};
2743
2744 MenuDef ModeMenu[]=
2745 {
2746  {"Copy Mode",Item_Copy,0,0x2e},
2747  {"Paste Mode",Item_Paste,0,0x19},
2748  {"Block Fill",Item_BlockFill,0,0x30},
2749  {"Flood Fill",Item_FloodFill,0,0x21},
2750  {"Undo last action",Item_Undo,0,0x16},
2751  {"Tile Search",Item_TileSearch,0,0x14},
2752  {"GridMode toggle",Item_GridMode,0,0x22},
2753  {"Snap-Paste toggle",Item_SnapTog,0,0x1f},
2754  {"Paste Overlay toggle",Item_POtog,0,0x3d}
2755 };
2756
2757
2758 MenuDef MiscMenu[]=
2759 {
2760  {"Select Tile",Item_SelectTile,0,0x39},
2761  {"Map Stats",Item_MapStats,0,0x17},
2762  {"Toggle INFOBAR",Item_ToggleInfo,0,0x42},
2763  {"New INFOPLANE value",Item_InputInfoplane,0,0x1c},
2764  {"View Map & Goto",Item_ViewMap,ALT,0x2f},
2765  {"ReView Map & Goto",Item_ReviewMap,0,0xe},
2766  {"Change LAUNCH icon",Item_ChangeLaunchIcon,0,0},
2767  {"Change bkgnd color",Item_ChangeBkgndColor,0,0},
2768  {"TILEINFOM Copy",Item_TINFOCopy,0,0},
2769  {"Graphic Map Dump",Item_GraphicDump,0,0}
2770 };
2771
2772
2773 MBarDef TED5MenuBar[]=
2774   {{9,AboutMenu," ? "},
2775    {11,FileMenu,"File"},
2776    {8,EditMenu,"Edit"},
2777    {9,ModeMenu,"Modes"},
2778    {10,MiscMenu,"Misc"},
2779    {0,0,""}};