]> 4ch.mooo.com Git - 16.git/blob - 16/ted5/TED5-4.C
ted5 added
[16.git] / 16 / ted5 / TED5-4.C
1 ////////////////////////////////////////////////////
2 ////////////////////////////////////////////////////
3 //
4 // TED5-4
5 //
6 ////////////////////////////////////////////////////
7 ////////////////////////////////////////////////////
8 #include "ted5.h"
9 #pragma hdrstop
10
11
12 void SignalSound(void)
13 {
14  int i;
15
16  for(i=0;i<10;i++)
17  {
18   sound(500+i*500);
19   delay(5);
20   nosound();
21  }
22 }
23
24
25 ////////////////////////////////////////////////////
26 //
27 // Create an OBJ linkable file from any type of datafile
28 //
29 // Exit:
30 //  0 = everything's a-ok!
31 // -1 = file not found
32 // -2 = file >64K
33 //
34 ////////////////////////////////////////////////////
35 int MakeOBJ(char *filename,char *destfilename,char *public,segtype whichseg,char *farname)
36 {
37  char THEADR[17]={0x80,14,0,12,32,32,32,32,32,32,32,32,32,32,32,32,0},
38       COMENT[18]={0x88,0,0,0,0,'M','a','k','e','O','B','J',' ','v','1','.','1',0},
39       LNAMES[42]={0x96,0,0,
40                   6,'D','G','R','O','U','P',
41                   5,'_','D','A','T','A',
42                   4,'D','A','T','A',
43                   0,
44                   5,'_','T','E','X','T',
45                   4,'C','O','D','E',
46                   8,'F','A','R','_','D','A','T','A'},
47       SEGDEF[9]={0x98,7,0,0x48,0,0,2,3,4},      // for .DATA
48       SEGDEF1[9]={0x98,7,0,0x48,0,0,5,6,4},     // for .CODE
49       SEGDEF2[9]={0x98,7,0,0x60,0,0,8,7,4},     // for .FARDATA
50       GRPDEF[7]={0x9a,4,0,1,0xff,1,0x61},
51       MODEND[5]={0x8a,2,0,0,0x74};
52
53  unsigned i,j,flag,handle;
54  long fsize,offset,loffset,temp,amtleft,amount,offset1;
55  char _seg *dblock,*block;
56
57
58  //
59  // Need to compute the CHECKSUM in the COMENT field
60  // (so if the "MakeOBJ..." string is modified, the CHECKSUM
61  //  will be correct).
62  //
63  COMENT[1]=sizeof(COMENT)-3;
64  for (flag=i=0;i<sizeof(COMENT);i++)
65     flag+=COMENT[i];
66  COMENT[sizeof(COMENT)-1]=(flag^0xff)+1;
67
68  if ((handle=open(filename,O_BINARY))==NULL)
69    return -1;
70
71  fsize=filelength(handle);
72  close(handle);
73  if (fsize>0x10000L)            // BIGGER THAN 1 SEG = ERROR!
74    return -2;
75
76  LoadIn(filename,(memptr *)&block);     // LOAD FILE IN
77  offset=0;
78
79  MMAllocate((memptr *)&dblock,0x10000L);
80
81  ////////////////////////////////////////////////////
82  //
83  // INSERT HEADER RECORD
84  //
85  movedata(_DS,FP_OFF(&THEADR),(unsigned)dblock,offset,sizeof(THEADR));
86  movedata(FP_SEG(filename),FP_OFF(filename),
87           (unsigned)dblock,offset+4,strlen(filename));
88  offset+=sizeof(THEADR);
89
90
91  ////////////////////////////////////////////////////
92  //
93  // INSERT COMMENT RECORD
94  //
95  movedata(_DS,FP_OFF(COMENT),(unsigned)dblock,offset,sizeof(COMENT));
96  offset+=sizeof(COMENT);
97
98
99  ////////////////////////////////////////////////////
100  //
101  // INSERT START OF LIST-OF-NAMES RECORD
102  //
103  loffset=offset;
104  movedata(_DS,FP_OFF(LNAMES),(unsigned)dblock,offset,sizeof(LNAMES));
105  offset+=sizeof(LNAMES);
106
107  // If it's a .FARDATA segment, we need to insert the segment name!
108  if (whichseg==FARDATA)
109    {
110     *(dblock+offset)=strlen(farname);
111     movedata(FP_SEG(farname),FP_OFF(farname),
112         (unsigned)dblock,offset+1,strlen(farname));
113     offset+=strlen(farname)+1;
114    }
115
116  // Now, finish the List-Of-Names record by creating
117  // the CHECKSUM and LENGTH
118  temp=offset;
119  offset=offset-loffset-2;
120  *(int huge *)(dblock+loffset+1)=offset;
121  offset=temp;
122
123  // Now, figure out the CHECKSUM of the record
124  for (flag=i=0;i<(offset-loffset);i++)
125    flag+=*(dblock+i+loffset);
126  *(dblock+offset)=(flag^0xff)+1;
127  offset++;
128
129
130  ////////////////////////////////////////////////////
131  //
132  // CREATE SEGMENT DEFINITION RECORD
133  //
134  loffset=offset;
135  temp=fsize;
136  switch(whichseg)
137  {
138   case DATA:
139     movedata(FP_SEG(&SEGDEF),FP_OFF(&SEGDEF),
140              (unsigned)dblock,offset,sizeof(SEGDEF));
141     *(int huge *)(dblock+offset+4)=temp;
142     offset+=sizeof(SEGDEF);
143     break;
144   case CODE:
145     movedata(FP_SEG(&SEGDEF1),FP_OFF(&SEGDEF1),
146              (unsigned)dblock,offset,sizeof(SEGDEF1));
147     *(int huge *)(dblock+offset+4)=temp;
148     offset+=sizeof(SEGDEF1);
149     break;
150   case FARDATA:
151     movedata(FP_SEG(&SEGDEF2),FP_OFF(&SEGDEF2),
152              (unsigned)dblock,offset,sizeof(SEGDEF2));
153     *(int huge *)(dblock+offset+4)=temp;
154     offset+=sizeof(SEGDEF2);
155     break;
156  }
157
158  // CHECKSUM
159  for (flag=0,i=loffset;i<offset;i++)
160    flag+=*(dblock+i);
161  *(dblock+offset)=(flag^0xff)+1;
162  offset++;
163
164
165  ////////////////////////////////////////////////////
166  //
167  // CREATE GROUP DEFINITION RECORD
168  //
169  switch(whichseg)
170  {
171   case DATA:
172   case CODE:
173     movedata(FP_SEG(&GRPDEF),FP_OFF(&GRPDEF),
174              (unsigned)dblock,offset,sizeof(GRPDEF));
175     offset+=sizeof(GRPDEF);
176  }
177
178
179  ////////////////////////////////////////////////////
180  //
181  // CREATE PUBLIC DEFINITION RECORD
182  //
183  loffset=offset;
184  *(dblock+offset)=0x90;         // PUBDEF ID
185  offset+=3;                     // point to public base, skip length
186  *(dblock+offset)=1;            // group index=1
187  *(dblock+offset+1)=1;          // segment index=1
188  offset+=2;                     // point to public name
189
190  temp=0;
191  movedata(FP_SEG(public),FP_OFF(public),
192           (unsigned)dblock,offset+1,strlen(public));
193  *(dblock+offset)=strlen(public);
194  offset+=strlen(public)+1;
195  *(int huge *)(dblock+offset)=0;        // public offset within segment
196  offset+=2;
197  *(dblock+offset)=0;            // type index
198  offset++;
199
200  // LENGTH
201  temp=offset-loffset-2;
202  *(int huge *)(dblock+loffset+1)=temp;
203  offset++;
204
205  // CHECKSUM
206  for (flag=0,i=loffset;i<offset;i++)
207    flag+=*(dblock+i);
208  *(dblock+offset)=(flag^0xff)+1;
209
210
211  ////////////////////////////////////////////////////
212  //
213  // DATA RECORD(S). YUCK.
214  //
215
216  amtleft=fsize;
217  amount=1024;
218  for (i=0;i<(fsize+1023)/1024;i++)
219    {
220     offset1=offset;
221     if (amtleft<1024)
222       amount=amtleft;
223     //
224     // RECORD HEADER
225     //
226     *(dblock+offset)=0xa0;                      // LEDATA ID
227     *(int huge *)(dblock+offset+1)=amount+4;    // length of record
228     offset+=3;
229     *(dblock+offset)=1;                         // segment index
230     *(int huge *)(dblock+offset+1)=i*1024;      // index into segment
231     offset+=3;
232     //
233     // LOAD DATA IN
234     //
235     LoadFile(filename,(char huge *)dblock+offset,i*1024,amount);
236     offset+=amount;
237     //
238     // CHECKSUM!
239     //
240     for (flag=0,j=offset1;j<offset;j++)
241       flag+=*(dblock+j);
242     *(dblock+offset)=(flag^0xff)+1;
243     offset++;
244
245     amtleft-=1024;
246    }
247
248  ////////////////////////////////////////////////////
249  //
250  // MODULE END! YES!
251  //
252  movedata(FP_SEG(&MODEND),FP_OFF(&MODEND),(unsigned)dblock,offset,sizeof(MODEND));
253  offset+=sizeof(MODEND);
254
255  //
256  // Save the little puppy out!
257  //
258  SaveFile(destfilename,(char huge *)dblock,0,offset);
259  MMFreePtr((memptr *)&dblock);
260  MMFreePtr((memptr *)&block);
261  return 0;
262 }
263
264
265 ////////////////////////////////////////////////////
266 //
267 // DUMP THE PASTE BUFFER OUT TO EITHER AN
268 // "APPLE PREFERRED" OR "ILBM" GRAPHICS FORMAT FILE
269 //
270 // NOTE: THIS IS ONLY AVAILABLE IN EGA, BECAUSE I
271 // DON'T FEEL LIKE WRITING A CGA ILBM PIXEL-SPLICER --
272 // AND APPLE PREFERRED ONLY HANDLES 4-BIT COLOR ANYWAY!
273 // (YES, I KNOW, I COULD ONLY USE 4 OUT OF 16 COLORS...SHUT UP!)
274 //
275 ////////////////////////////////////////////////////
276 btype dumpB[]={{" DeluxePaint II ILBM ",4,2,2},
277                {"   Apple Preferred   ",4,5,1}},
278       fnameB={"         ",4,3,1};
279 DialogDef dumpD={" Which format do you require?",30,7,2,&dumpB[0],NULL},
280           fnameD={"Enter filename to\nsave (no suffix)",17,5,1,&fnameB,NULL};
281
282 void Item_GraphicDump(void)
283 {
284  char filename[14],ext[5],_seg *block,_seg *block1;
285  ApPrefStr PrefHeader;
286  int which,i,j,k,m,n,pwidth,lwidth,dx,dy;
287  long tilelen,fsize=0,bufsize;
288
289  if (!PasteOK)
290    {
291     ErrDialog("You need to use the Copy command\n"
292               "to copy part of the map or tiles\n"
293               "so I know what I need to dump!"," OK ");
294     return;
295    }
296
297  switch(videomode)
298  {
299   case CGA:
300   case VGA:
301     ErrDialog("Sorry, but this function is only\n"
302               "available for EGA mode.  If you\n"
303               "have a REAL NEED for this to work\n"
304               "in CGA or VGA, talk to Id Software!"," OK ");
305     return;
306  }
307
308  if (!(which=DoDialog(&dumpD)))
309    return;
310
311  //
312  // SET TILE LENGTH
313  //
314  switch(tsize)
315  {
316   case 1: tilelen=32L; break;
317   case 2: tilelen=128L; break;
318   case 3: tilelen=512L;
319  }
320
321  //
322  // GET FILENAME TO SAVE UNDER
323  //
324  DrawDialog(&fnameD,1);
325  MouseHide();
326  GetButtonXY(&fnameD,0,&sx,&sy);
327  if (!input(filename,8))
328    {
329     RestoreBackground();
330     MouseShow();
331     return;
332    }
333  for (i=0;i<strlen(filename);i++)
334    if (filename[i]=='.')
335      {
336       filename[i]=0;
337       break;
338      }
339  RestoreBackground();
340  MouseShow();
341
342  //
343  // SETUP FOR EACH TYPE
344  //
345  switch(which)
346  {
347   case 1:       // ILBM
348     {
349      long size;
350      char form[5]="FORM",ilbm[9]="ILBMBMHD",body[5]="BODY";
351
352
353      size=48L;
354      MMAllocate((memptr *)&block,size);
355
356      movedata(FP_SEG(form),FP_OFF(form),(unsigned)block,fsize,4);
357      fsize+=4;
358      size=40L+tilelen*TileCopy.w*TileCopy.h;
359      *(block+fsize)=(size>>24)&0xff;
360      *(block+fsize+1)=(size>>16)&0xff;
361      *(block+fsize+2)=(size>>8)&0xff;
362      *(block+fsize+3)=size&0xff;
363      fsize+=4;
364      movedata(FP_SEG(ilbm),FP_OFF(ilbm),(unsigned)block,fsize,8);
365      fsize+=8;
366      *(block+fsize)=0;
367      *(block+fsize+1)=0;
368      *(block+fsize+2)=0;
369      *(block+fsize+3)=20;
370      fsize+=4;
371      *(block+fsize)=(TileCopy.w<<(tsize+2))/256;   // pixel width
372      *(block+fsize+1)=(TileCopy.w<<(tsize+2))&0xff;
373      *(block+fsize+2)=(TileCopy.h<<(tsize+2))/256; // pixel height
374      *(block+fsize+3)=(TileCopy.h<<(tsize+2))&0xff;
375      *(int huge *)(block+fsize+4)=0;            // Xorg
376      *(int huge *)(block+fsize+6)=0;            // Yorg
377      *(block+fsize+8)=4;                        // planes
378      *(block+fsize+9)=0;                        // mask (stencil!)
379      *(block+fsize+10)=0;                       // compression (none)
380      *(block+fsize+11)=0;                       // pad (?)
381      *(int huge *)(block+fsize+12)=0;           // trans (?)
382      *(int huge *)(block+fsize+14)=0x101;       // aspt (aspect?)
383      *(int huge *)(block+fsize+16)=0x4001;      // page width
384      *(int huge *)(block+fsize+18)=0xc800;      // page height
385      fsize+=20;
386      movedata(FP_SEG(body),FP_OFF(body),(unsigned)block,fsize,4);
387      fsize+=4;
388      size=tilelen*TileCopy.w*TileCopy.h;
389      *(block+fsize)=(size>>24)&0xff;
390      *(block+fsize+1)=(size>>16)&0xff;
391      *(block+fsize+2)=(size>>8)&0xff;
392      *(block+fsize+3)=size&0xff;
393      fsize+=4;
394
395      strcpy(ext,".LBM");
396     }
397     break;
398
399   case 2:       // APPLE PREFERRED
400     {
401      int Ctable[16]={0x0000,0x000a,0x00a0,0x00aa,0x0a00,0x0a0a,0x0a50,0x0aaa,
402                      0x0555,0x055f,0x05f5,0x05ff,0x0f55,0x0f5f,0x0ff5,0x0fff};
403      long size,pixwid;
404
405
406      PrefHeader.length=sizeof(ApPrefStr)+4L*(TileCopy.h<<(tsize+2))+
407         TileCopy.w*TileCopy.h*tilelen+(((TileCopy.w*TileCopy.h*tilelen)+63)/64);
408      strncpy(PrefHeader.Kind,"\x4MAIN",5);
409      PrefHeader.MasterMode=0;
410      PrefHeader.PixelsPerLine=TileCopy.w<<(tsize+2);
411      PrefHeader.NumColorTables=1;
412      for (i=0;i<16;i++)
413        PrefHeader.ColorTable[i]=Ctable[i];
414      PrefHeader.NumScanLines=TileCopy.h<<(tsize+2);
415
416      size=sizeof(ApPrefStr)+4L*(TileCopy.h<<(tsize+2));
417      MMAllocate((memptr *)&block,size);
418      movedata(FP_SEG(&PrefHeader),FP_OFF(&PrefHeader),(unsigned)block,fsize,sizeof(ApPrefStr));
419      fsize+=sizeof(ApPrefStr);
420
421      pixwid=TileCopy.w*(2<<tsize);
422      for (i=0;i<(TileCopy.h<<(tsize+2));i++)
423        {
424         *(int huge *)(block+fsize)=pixwid+(pixwid+63)/64;
425         *(int huge *)(block+fsize+2)=0;
426         fsize+=4;
427        }
428
429      strcpy(ext,".APP");
430      MMAllocate((memptr *)&block1,tilelen*TileCopy.w);
431     }
432  }
433
434  //
435  // SAVE HEADER OUT
436  //
437  strcat(filename,ext);
438  SaveFile(filename,(char huge *)block,0,fsize);
439  MMFreePtr((memptr *)&block);
440
441  //
442  // NOW, WRITE THE DATA OUT! EEEE!
443  //
444  bufsize=tilelen*TileCopy.w;
445  MMAllocate((memptr *)&block,bufsize);
446
447  pwidth=(1<<(tsize-1))*TileCopy.w;
448  lwidth=pwidth*4;
449
450  ErrDialog("One moment. I am busy.\n     Countdown:","");
451  dx=sx;
452  dy=sy;
453
454  for (j=0;j<TileCopy.h;j++)
455    {
456     sx=dx;
457     sy=dy;
458     printint(TileCopy.h-j);
459     print(" ");
460
461     for (i=0;i<TileCopy.w;i++)
462       {
463        unsigned tilet,tilem,tilei,loc;
464
465        //
466        // ESC out?
467        //
468        if (keydown[1])
469          {
470           RestoreBackground();
471           while(keydown[1]);
472           ErrDialog("You aborted out of the\n"
473                     "graphic dump conversion!"," Yes, I know ");
474
475           if (which==2)
476             MMFreePtr((memptr *)&block1);
477           return;
478          }
479        //
480        // GET THE CORRECT TILE MOVED INTO "TDATA"
481        //
482        switch(TileCopy.MapOrTileSelect)
483        {
484         case 0: // MAP COPY
485           loc=(j+TileCopy.y)*mapwidth+TileCopy.x+i;
486           tilet=(TileCopy.PlanesCopied&BPLANE)?CutBkgnd[loc]:-BkgndColor;
487           tilem=(TileCopy.PlanesCopied&FPLANE)?CutFrgnd[loc]+tilenum:0;
488           tilei=(TileCopy.PlanesCopied&IPLANE)?CutInfoPl[loc]+tilenum:0;
489           CombineTiles(tilet,tilem,tilei,tsize);
490           break;
491         case 1: // BKGND TILE COPY
492           loc=(TileCopy.y+j)*selectcols+TileCopy.x+i;
493           CombineTiles(loc,0,0,tsize);
494           break;
495         case 2: // FRGND TILE COPY
496           loc=(TileCopy.y+j)*selectcols+TileCopy.x+i+tilenum;
497           CombineTiles(-BkgndColor,loc,0,tsize);
498        }
499
500        //
501        // NOW, MUNGE "TDATA" INTO BIT-PLANES!
502        //
503        // INTERNAL:             P0      P1      P2      P3
504        //       SCANLINE x      ......  ......  ......  ......
505        //
506        for (k=0;k<8<<(tsize-1);k++)
507          for (m=0;m<4;m++)
508            movedata(FP_SEG(&tdata),FP_OFF(&tdata)+(m*tsize*(8<<(tsize-1)))+k*(1<<(tsize-1)),
509                 (unsigned)block,k*lwidth+m*pwidth+i*(1<<(tsize-1)),1<<(tsize-1));
510       }
511     //
512     // ALRIGHT. NOW SAVE THIS CHUNK OUT IN THE CORRECT FORMAT
513     //
514     switch(which)
515     {
516      case 1:    // ILBM
517        SaveFile(filename,MK_FP(block,0),fsize,bufsize);
518        fsize+=bufsize;
519        break;
520      case 2:    // APPLE PREFERRED
521        {
522         int len,clen;
523
524         //
525         // FIRST, I NEED TO CONVERT THE ILBM PLANAR FORMAT
526         // TO SUPER-RES NIBBLES
527         //
528         for (k=0;k<8<<(tsize-1);k++)
529           for (m=0;m<(1<<(tsize-1))*TileCopy.w;m++)
530             {
531              unsigned char src[4],dest[4]={0,0,0,0};
532
533              for (n=0;n<4;n++)
534                src[n]=block[k*lwidth+pwidth*n+m];
535
536              asm        mov     al,[BYTE PTR src+0]
537              asm        mov     ah,[BYTE PTR src+1]
538              asm        mov     bl,[BYTE PTR src+2]
539              asm        mov     bh,[BYTE PTR src+3]
540
541              // dest[0]
542              asm        shl     bh,1
543              asm        rcl     cl,1
544              asm        shl     bl,1
545              asm        rcl     cl,1
546              asm        shl     ah,1
547              asm        rcl     cl,1
548              asm        shl     al,1
549              asm        rcl     cl,1
550
551              asm        shl     bh,1
552              asm        rcl     cl,1
553              asm        shl     bl,1
554              asm        rcl     cl,1
555              asm        shl     ah,1
556              asm        rcl     cl,1
557              asm        shl     al,1
558              asm        rcl     cl,1
559
560              // dest[1]
561              asm        shl     bh,1
562              asm        rcl     ch,1
563              asm        shl     bl,1
564              asm        rcl     ch,1
565              asm        shl     ah,1
566              asm        rcl     ch,1
567              asm        shl     al,1
568              asm        rcl     ch,1
569
570              asm        shl     bh,1
571              asm        rcl     ch,1
572              asm        shl     bl,1
573              asm        rcl     ch,1
574              asm        shl     ah,1
575              asm        rcl     ch,1
576              asm        shl     al,1
577              asm        rcl     ch,1
578
579              // dest[2]
580              asm        shl     bh,1
581              asm        rcl     dl,1
582              asm        shl     bl,1
583              asm        rcl     dl,1
584              asm        shl     ah,1
585              asm        rcl     dl,1
586              asm        shl     al,1
587              asm        rcl     dl,1
588
589              asm        shl     bh,1
590              asm        rcl     dl,1
591              asm        shl     bl,1
592              asm        rcl     dl,1
593              asm        shl     ah,1
594              asm        rcl     dl,1
595              asm        shl     al,1
596              asm        rcl     dl,1
597
598              // dest[3]
599              asm        shl     bh,1
600              asm        rcl     dh,1
601              asm        shl     bl,1
602              asm        rcl     dh,1
603              asm        shl     ah,1
604              asm        rcl     dh,1
605              asm        shl     al,1
606              asm        rcl     dh,1
607
608              asm        shl     bh,1
609              asm        rcl     dh,1
610              asm        shl     bl,1
611              asm        rcl     dh,1
612              asm        shl     ah,1
613              asm        rcl     dh,1
614              asm        shl     al,1
615              asm        rcl     dh,1
616
617              asm        mov     [BYTE PTR dest+0],cl
618              asm        mov     [BYTE PTR dest+1],ch
619              asm        mov     [BYTE PTR dest+2],dl
620              asm        mov     [BYTE PTR dest+3],dh
621
622              movedata(FP_SEG(&dest),FP_OFF(&dest),
623                 (unsigned)block1,k*lwidth+m*4,4);
624             }
625
626         //
627         // NOW, TIME TO WRITE THE DATA OUT IN 64-BYTE CHUNKS! YUCK!
628         //
629         for (k=0;k<8<<(tsize-1);k++)
630           {
631            char clen;
632            int off=k*lwidth;;
633
634            len=4*pwidth;
635            while(len>0)
636            {
637             if (len>64)
638               clen=64;
639             else
640               clen=len;
641
642             clen--;
643             SaveFile(filename,(char huge *)&clen,fsize++,1);
644             clen++;
645
646             SaveFile(filename,MK_FP(block1,off),fsize,clen);
647             fsize+=clen;
648             off+=clen;
649             len-=clen;
650            }
651           }
652        }
653     }
654    }
655
656  if (which==2)
657    MMFreePtr((memptr *)&block1);
658
659  MMFreePtr((memptr *)&block);
660  RestoreBackground();
661
662  ErrDialog("Graphic successfully dumped!"," Yeah! ");
663 }
664
665
666 ////////////////////////////////////////////////////
667 //
668 // Item - Edit TILEINFO/M values
669 //
670 ////////////////////////////////////////////////////
671 btype ETVb[]={{" Tileinfo ",2,21,1},
672               {" TileinfoM ",16,21,1},
673               {" Exit ",30,21,2}};
674 DialogDef ETVd={"       Edit TILEINFO/M values",38,23,3,&ETVb[0],NULL};
675 int CurTIvalue;
676
677 void Item_EditTinfoValues(void)
678 {
679  int max,i,which,exitok=0,mx,my,b0,b1,CTRLdown;
680  static int whichtinfo=0;
681
682  //
683  // IS THE "CTRL" KEY DOWN?
684  //
685  CTRLdown=keydown[0x1d];
686  if (CTRLdown)
687    {
688     if (planeton)
689       whichtinfo=0;
690     else
691       whichtinfo=1;
692    }
693
694  switch(whichtinfo)
695  {
696   case 0: max=tilenum; break;
697   case 1: max=tilemnum;
698  }
699
700  switch(videomode)
701  {
702   case CGA:
703   case EGA1:
704   case VGA:
705     ETVd.height=23;
706     for(i=0;i<3;i++)
707       ETVb[i].yoff=21;
708     break;
709   case EGA2:
710     ETVd.height=58;
711     for(i=0;i<3;i++)
712       ETVb[i].yoff=56;
713  }
714
715  //
716  // DRAW THE SCREEN
717  //
718  DrawDialog(&ETVd,1);
719  if (CTRLdown)
720    {
721     DrawTinfoScreen(whichtinfo,0,-max); // ALIGN TO TOP
722     switch(whichtinfo)
723     {
724      case 0: DrawTinfoScreen(whichtinfo,0,whicht); break;
725      case 1: DrawTinfoScreen(whichtinfo,0,whichtm-tilenum);
726     }
727    }
728  else
729    DrawTinfoScreen(whichtinfo,0,0);
730
731
732  do
733  {
734   which=CheckButtonsRet(&ETVd);
735   if (which>=0)
736     switch(which)
737     {
738      case 0:
739        RestoreBackground();
740        return;
741      case 1:
742        if (whichtinfo)
743          {
744           max=tilenum;
745           whichtinfo=0;
746           DrawDialog(&ETVd,0);
747           DrawTinfoScreen(whichtinfo,0,0);
748          }
749        else
750          {
751           GetButtonXY(&ETVd,0,&sx,&sy);
752           MouseHide();
753           print(ETVb[0].text);
754           MouseShow();
755           errsound();
756          }
757        break;
758      case 2:
759        if (!tilemnum)
760          {
761           GetButtonXY(&ETVd,1,&sx,&sy);
762           MouseHide();
763           print(ETVb[1].text);
764           MouseShow();
765           errsound();
766           break;
767          }
768
769        if (!whichtinfo)
770          {
771           max=tilemnum;
772           whichtinfo=1;
773           DrawDialog(&ETVd,0);
774           DrawTinfoScreen(whichtinfo,0,0);
775          }
776        else
777          {
778           GetButtonXY(&ETVd,1,&sx,&sy);
779           MouseHide();
780           print(ETVb[1].text);
781           MouseShow();
782           errsound();
783          }
784        break;
785
786      case 3:
787        exitok=1;
788     }
789   else
790     {
791      MouseCoords(&mx,&my);
792      mx/=8;
793      my/=8;
794      b0=MouseButton()&1;
795      b1=MouseButton()&2;
796
797      //
798      // CHECK FOR BUTTON PRESSES
799      //
800      if (b0)
801        UseTinfoValue(whichtinfo,mx,my,1);
802      else
803      if (b1)
804        UseTinfoValue(whichtinfo,mx,my,0);
805
806      //
807      // SPACE = ENTER VALUES HORIZONTALLY
808      //
809      if (keydown[0x39])
810      {
811       while(keydown[0x39]);
812       clearkeys();
813       EnterTinfoValue(whichtinfo,mx,my,0);
814      }
815
816      //
817      // CHECK FOR SCROLLING
818      //
819      if (keydown[0x48])         // UP
820        {
821         DrawTinfoScreen(whichtinfo,0,-1);
822         if (keydown[0x1d])
823           while(keydown[0x48]);
824        }
825      else
826      if (keydown[0x50])         // DOWN
827        {
828         DrawTinfoScreen(whichtinfo,0,1);
829         if (keydown[0x1d])
830           while(keydown[0x50]);
831        }
832      else
833      if (keydown[0x49])         // PGUP
834        {
835         DrawTinfoScreen(whichtinfo,0,-8);
836         if (!keydown[0x1d])
837           while(keydown[0x49]);
838        }
839      else
840      if (keydown[0x51])         // PGDN
841        {
842         DrawTinfoScreen(whichtinfo,0,8);
843         if (!keydown[0x1d])
844           while(keydown[0x51]);
845        }
846      else
847      if (keydown[0x47])         // HOME
848        {
849         DrawTinfoScreen(whichtinfo,0,-max);
850         while(keydown[0x47]);
851        }
852      else
853      if (keydown[0x4f])         // END
854        {
855         DrawTinfoScreen(whichtinfo,0,max);
856         while(keydown[0x4f]);
857        }
858      else
859      if (keydown[0x4d])         // RIGHT
860        {
861         DrawTinfoScreen(whichtinfo,1,0);
862         if (!keydown[0x1d])
863           while(keydown[0x4d]);
864        }
865      else
866      if (keydown[0x4b])         // LEFT
867        {
868         DrawTinfoScreen(whichtinfo,-1,0);
869         if (!keydown[0x1d])
870           while(keydown[0x4b]);
871        }
872
873     }
874
875  } while(!exitok);
876
877  RestoreBackground();
878 }
879
880
881 //
882 // PICKUP/DROP TILEINFO VALUE AT CURSOR
883 //
884 void UseTinfoValue(int whichtinfo,int mx,int my,int PickupOrDrop)
885 {
886  int whichx=-1,whichy=-1;
887  unsigned dialogx,dialogy;
888
889
890  GetDialogXY(&ETVd,&dialogx,&dialogy);
891
892  if (mx>=dialogx+10 && mx<=dialogx+45)
893    whichx=(mx-(dialogx+10))/7;
894
895  if (my>=4 && my<=((videomode==EGA2)?55:19))
896    whichy=(my-4)>>(tsize-1);
897
898  switch(whichtinfo)
899  {
900   case 0:
901     if (whichx>=numtplanes)
902       whichx=-1;
903     if (whichy>=tilenum)
904       whichy=-1;
905     break;
906
907   case 1:
908     if (whichx>=numtmplanes)
909       whichx=-1;
910     if (whichy>=tilemnum)
911       whichy=-1;
912  }
913
914  if (whichx>=0 && whichy>=0)
915  {
916   if (!PickupOrDrop)
917     switch(whichtinfo)
918     {
919      case 0:    // TILE
920        CurTIvalue=*(Tinfo[whichx+TIxbase]+whichy+TIybase);
921        break;
922      case 1:    // MASKED
923        CurTIvalue=*(TMinfo[whichx+TIxmbase]+whichy+TIymbase);
924     }
925   else
926     switch(whichtinfo)
927     {
928      case 0:    // TILE
929        *(Tinfo[whichx+TIxbase]+whichy+TIybase)=CurTIvalue;
930        DirtyFlag=1;
931        break;
932      case 1:    // MASKED
933        *(TMinfo[whichx+TIxmbase]+whichy+TIymbase)=CurTIvalue;
934        DirtyFlag=1;
935     }
936
937   DrawTinfoScreen(whichtinfo,0,0);
938  }
939  while(MouseButton());
940 }
941
942
943 //
944 // ENTER TILEINFO/M CELL VALUES
945 //
946 void EnterTinfoValue(int whichtinfo,int mx,int my,int H_or_V)
947 {
948  int whichx=-1,whichy=-1,val,outok=0,tempx,tempy,maxx,maxy;
949  unsigned dialogx,dialogy;
950
951
952  GetDialogXY(&ETVd,&dialogx,&dialogy);
953
954  if (mx>=dialogx+10 && mx<=dialogx+45)
955    whichx=(mx-(dialogx+10))/7;
956
957  if (my>=4 && my<=((videomode==EGA2)?55:19))
958    whichy=(my-4)>>(tsize-1);
959
960  switch(whichtinfo)
961  {
962   case 0:
963     if (whichx>=numtplanes)
964       whichx=-1;
965     if (whichy>=tilenum)
966       whichy=-1;
967     break;
968
969   case 1:
970     if (whichx>=numtmplanes)
971       whichx=-1;
972     if (whichy>=tilemnum)
973       whichy=-1;
974  }
975
976  MouseHide();
977
978  if (whichx>=0 && whichy>=0)
979    do
980    {
981     //
982     // INPUT VALUE
983     //
984     sx=whichx*7+dialogx+10;
985     sy=(whichy<<(tsize-1))+4;
986     print("    ");
987     sx-=4;
988     if ((val=inputint(3))!=(int)ESCOUT)
989       switch(whichtinfo)
990       {
991        case 0:  // TILE
992          *(Tinfo[whichx+TIxbase]+whichy+TIybase)=val&0xff;
993          DirtyFlag=1;
994          break;
995        case 1:  // MASKED
996          *(TMinfo[whichx+TIxmbase]+whichy+TIymbase)=val&0xff;
997          DirtyFlag=1;
998       }
999     else
1000       outok=1;
1001
1002     //
1003     // INPUT INTO THE NEXT FIELD!
1004     //
1005     if (!outok)
1006       {
1007        tempx=(whichtinfo?TIxmbase:TIxbase);
1008        tempy=(whichtinfo?TIymbase:TIybase);
1009        maxx=(whichtinfo?numtmplanes:numtplanes);
1010        maxy=(whichtinfo?tilemnum:tilenum);
1011
1012        switch(H_or_V)
1013        {
1014         case 0: // HORIZONTAL
1015           whichx++;
1016           if (tempx+whichx>=maxx)
1017             outok=1;
1018           else
1019           if (whichx>TINFOWIDTH)
1020             {
1021              whichx=TINFOWIDTH;
1022              tempx++;
1023              if (tempx>=maxx)
1024                outok=1;
1025             }
1026
1027           switch(whichtinfo)
1028           {
1029            case 0: TIxbase=tempx; break;
1030            case 1: TIxmbase=tempx;
1031           }
1032           break;
1033
1034         case 1: // VERTICAL
1035           whichy++;
1036           if (tempy+whichy>=maxy)
1037             outok=1;
1038           else
1039           if (whichy>(videomode==EGA2?TINFOHEIGHTEGA2:TINFOHEIGHT))
1040             {
1041              whichy=(videomode==EGA2?TINFOHEIGHTEGA2:TINFOHEIGHT);
1042              tempy++;
1043              if (tempy>=maxy)
1044                outok=1;
1045             }
1046
1047           switch(whichtinfo)
1048           {
1049            case 0: TIybase=tempy; break;
1050            case 1: TIymbase=tempy;
1051           }
1052        }
1053       }
1054
1055     DrawTinfoScreen(whichtinfo,0,0);
1056
1057    } while (!outok);
1058
1059  MouseShow();
1060 }
1061
1062
1063
1064 //
1065 // Draw the Tileinfo screen
1066 //
1067 void DrawTinfoScreen(int thescreen,int deltax,int deltay)
1068 {
1069  int temp,temp1,i,j,width,height,dialogx;
1070  char _seg *Values[10];
1071
1072
1073  MouseHide();
1074  switch(videomode)
1075  {
1076   case CGA:
1077   case EGA1:
1078   case VGA:
1079     dialogx=1;
1080     height=16>>(tsize-1); break;
1081   case EGA2:
1082     dialogx=21;
1083     height=52>>(tsize-1);
1084  }
1085
1086  switch(thescreen)
1087  {
1088   case 0:       // TILEINFO
1089     if (height>tilenum)
1090       height=tilenum;
1091     else
1092       {
1093        TIybase+=deltay;
1094        if (TIybase<0)
1095          TIybase=0;
1096        else
1097        if (TIybase+height>tilenum)
1098          TIybase=tilenum-height;
1099       }
1100     temp=TIybase;
1101     break;
1102
1103   case 1:       // TILEINFOM
1104     if (height>tilemnum)
1105       height=tilemnum;
1106     else
1107       {
1108        TIymbase+=deltay;
1109        if (TIymbase<0)
1110          TIymbase=0;
1111        else
1112        if (TIymbase+height>tilemnum)
1113          TIymbase=tilemnum-height;
1114       }
1115     temp=TIymbase;
1116  }
1117
1118  //
1119  // DRAW TILES AND THEIR VALUES
1120  //
1121  for (i=0;i<height;i++)
1122    {
1123     sx=dialogx;
1124     sy=(i<<(tsize-1))+4;
1125     printhex(i+temp);
1126     sx=dialogx;
1127     sy++;
1128     print("    ");
1129     sx-=4;
1130     printint(i+temp);
1131
1132     switch(thescreen)
1133     {
1134      case 0:
1135        CombineTiles(temp+i,0,0,tsize);
1136        break;
1137      case 1:
1138        CombineTiles(-BkgndColor,temp+i+tilenum,0,tsize);
1139     }
1140
1141     DrawTile(dialogx+5,(i+2)<<(3+(tsize-1)),tsize);
1142    }
1143
1144  //
1145  // DRAW TILEINFO ARRAYS
1146  //
1147  width=4;
1148
1149  switch(thescreen)
1150  {
1151   case 0:
1152     if (width>numtplanes)
1153       width=numtplanes;
1154     else
1155       {
1156        TIxbase+=deltax;
1157        if (TIxbase<0)
1158          TIxbase=0;
1159        else
1160        if (TIxbase+width>numtplanes)
1161          TIxbase=numtplanes-width;
1162       }
1163     temp1=TIxbase;
1164     for (i=0;i<10;i++)
1165       Values[i]=Tinfo[i];
1166
1167     break;
1168
1169   case 1:
1170     if (width>numtmplanes)
1171       width=numtmplanes;
1172     else
1173       {
1174        TIxmbase+=deltax;
1175        if (TIxmbase<0)
1176          TIxmbase=0;
1177        else
1178        if (TIxmbase+width>numtmplanes)
1179          TIxmbase=numtmplanes-width;
1180       }
1181     temp1=TIxmbase;
1182     for (i=0;i<10;i++)
1183       Values[i]=TMinfo[i];
1184  }
1185
1186  for (j=0;j<width;j++)
1187    {
1188     sx=(dialogx+10)+j*7;
1189     sy=3;
1190     switch(thescreen)
1191     {
1192      case 0:
1193        print("       ");
1194        sx-=7;
1195        fprint(MapFileHeader->tnames[j+TIxbase]);
1196        break;
1197      case 1:
1198        print("       ");
1199        sx-=7;
1200        fprint(MapFileHeader->tmnames[j+TIxmbase]);
1201     }
1202     for (i=0;i<height;i++)
1203       {
1204        sx=(dialogx+10)+j*7;
1205        sy=(i<<(tsize-1))+4;
1206        print("$");
1207        printhexb(Values[j+temp1][i+temp]);
1208        sx=(dialogx+10)+j*7;
1209        sy++;
1210        print("   ");
1211        sx-=3;
1212        printint(Values[j+temp1][i+temp]&0xff);
1213       }
1214    }
1215  MouseShow();
1216 }
1217
1218
1219
1220 ////////////////////////////////////////////////////
1221 //
1222 // Item - Add or Delete TILEINFO/M planes
1223 //
1224 ////////////////////////////////////////////////////
1225 btype AODb[]={{" Add ",1,3,1},
1226               {" Delete ",8,3,1},
1227               {" Exit ",18,3,2}},
1228       TOMb[]={{" Tileinfo  ",1,2,1},
1229               {" TileinfoM ",1,5,1}},
1230       AreSureB2[]={{" Yes ",1,2,1},
1231                    {" No ",8,2,2}},
1232       TINb2={" Done ",8,15,1};;
1233 DialogDef AODd={"       TILEINFO/M\n     Pick a function",25,5,3,&AODb[0],NULL},
1234           TOMd={"Add to what?",13,7,2,&TOMb[0],NULL},
1235           NId={"Gimme a name!",13,4,0,NULL,NULL},
1236           AreSureD2={"Are you sure?",13,4,2,&AreSureB2[0],NULL},
1237           TINd2={"   Which to delete?\n"
1238                 " TILEINFO   TILEINFOM",
1239                 22,17,1,&TINb2,NULL};
1240
1241 void Item_AddDelTinfo(void)
1242 {
1243  char temp[16];
1244  int which,i;
1245  unsigned dx,dy;
1246
1247  while(1)
1248  {
1249   which=DoDialog(&AODd);
1250   switch(which)
1251   {
1252    case 0:      // ESC or EXIT
1253    case 3:
1254      return;
1255    //
1256    // ADD
1257    //
1258    case 1:
1259      which=DoDialog(&TOMd);
1260      if (!which)
1261        break;
1262
1263      switch(which)
1264      {
1265       case 1:
1266         if (numtplanes==10)
1267           {
1268            ErrDialog("You already have 10 TILEINFO\n"
1269                      "planes defined!"," OK ");
1270            return;
1271           }
1272         break;
1273
1274       case 2:
1275         if (!tilemnum)
1276           {
1277            ErrDialog("You crazy shit! You don't\n"
1278                      "have any masked tiles!"," Duh! ");
1279            return;
1280           }
1281
1282         if (numtmplanes==10)
1283           {
1284            ErrDialog("You already have 10 TILEINFOM\n"
1285                      "planes defined!"," OK ");
1286            return;
1287           }
1288         break;
1289      }
1290
1291      DrawDialog(&NId,1);
1292      MouseHide();
1293      GetDialogXY(&NId,&dx,&dy);
1294      sx=dx+1;
1295      sy=dy+1;
1296      DrawBorder(sx,sy,9,2,1);
1297      sx=dx+2;
1298      sy=dy+2;
1299      if (!input(temp,7))
1300        {
1301         RestoreBackground();
1302         MouseShow();
1303         break;
1304        }
1305
1306      //
1307      // MOVE THE NAME AND ALLOCATE THE MEMORY!
1308      //
1309      switch(which)
1310      {
1311       case 1:
1312         movedata(FP_SEG(temp),FP_OFF(temp),
1313                  (unsigned)MapFileHeader,FP_OFF(MapFileHeader->tnames[numtplanes]),8);
1314         MMAllocate((memptr *)&Tinfo[numtplanes],tilenum);
1315         for (i=0;i<tilenum;i++)
1316           *(Tinfo[numtplanes]+i)=0;
1317         MapFileHeader->numtplanes=++numtplanes;
1318         writeH=DirtyFlag=1;
1319         break;
1320
1321       case 2:
1322         movedata(FP_SEG(temp),FP_OFF(temp),
1323                  (unsigned)MapFileHeader,FP_OFF(MapFileHeader->tmnames[numtmplanes]),8);
1324         MMAllocate((memptr *)&TMinfo[numtmplanes],tilemnum);
1325         for (i=0;i<tilemnum;i++)
1326           *(TMinfo[numtmplanes]+i)=0;
1327         MapFileHeader->numtmplanes=++numtmplanes;
1328         writeH=DirtyFlag=1;
1329      }
1330
1331      RestoreBackground();
1332      MouseShow();
1333      break;
1334
1335    //
1336    // DELETE
1337    //
1338    case 2:
1339      {
1340       unsigned ox,oy,i,oktoexit=0;
1341       int which;
1342
1343       redo:
1344
1345       MouseHide();
1346       DrawDialog(&TINd2,1);
1347       GetDialogXY(&TINd2,&sx,&sy);
1348       ox=sx;
1349       oy=sy;
1350       DrawBorder(sx,sy+2,10,11,1);
1351       sx=ox;
1352       sy=oy;
1353       DrawBorder(sx+11,sy+2,10,11,1);
1354
1355       for (i=0;i<10;i++)
1356       {
1357        sx=ox+1;
1358        sy=oy+i+3;
1359        fprint(MapFileHeader->tnames[i]);
1360        sx=ox+12;
1361        sy=oy+i+3;
1362        fprint(MapFileHeader->tmnames[i]);
1363       }
1364       MouseShow();
1365
1366       do
1367       {
1368        if ((which=CheckList(ox+1,oy+3,8,numtplanes,TInfoNon,TInfoNoff,0))>=0)
1369          {
1370           int reply;
1371
1372           RestoreBackground();
1373           reply=DoDialog(&AreSureD2);
1374           switch(reply)
1375           {
1376            case 0:
1377            case 2:
1378              goto redo;
1379           }
1380
1381           if (which!=numtplanes-1)
1382             {
1383              for (i=0;i<8;i++)
1384                {
1385                 MapFileHeader->tnames[which][i]=MapFileHeader->tnames[numtplanes-1][i];
1386                 MapFileHeader->tnames[numtplanes-1][i]=0;
1387                }
1388              for (i=0;i<tilenum;i++)
1389                *(Tinfo[which]+i)=*(Tinfo[numtplanes-1]+i);
1390              MMFreePtr((memptr *)&Tinfo[numtplanes-1]);
1391             }
1392           else
1393             {
1394              MMFreePtr((memptr *)&Tinfo[which]);
1395              for (i=0;i<8;i++)
1396                MapFileHeader->tnames[which][i]=0;
1397             }
1398           writeH=DirtyFlag=1;
1399           MapFileHeader->numtplanes=--numtplanes;
1400           goto redo;
1401          }
1402
1403        if ((which=CheckList(ox+12,oy+3,8,numtmplanes,TInfoMNon,TInfoMNoff,0))>=0)
1404          {
1405           int reply;
1406
1407           RestoreBackground();
1408           reply=DoDialog(&AreSureD2);
1409           switch(reply)
1410           {
1411            case 0:
1412            case 2:
1413              goto redo;
1414           }
1415
1416           if (which!=numtmplanes-1)
1417             {
1418              for (i=0;i<8;i++)
1419                {
1420                 MapFileHeader->tmnames[which][i]=MapFileHeader->tmnames[numtplanes-1][i];
1421                 MapFileHeader->tmnames[numtmplanes-1][i]=0;
1422                }
1423              for (i=0;i<tilemnum;i++)
1424                *(TMinfo[which]+i)=*(TMinfo[numtmplanes-1]+i);
1425              MMFreePtr((memptr *)&TMinfo[numtmplanes-1]);
1426             }
1427           else
1428             {
1429              MMFreePtr((memptr *)&TMinfo[which]);
1430              for (i=0;i<8;i++)
1431                MapFileHeader->tmnames[which][i]=0;
1432             }
1433           writeH=DirtyFlag=1;
1434           MapFileHeader->numtmplanes=--numtmplanes;
1435           goto redo;
1436          }
1437
1438        GetButtonXY(&TINd2,0,&sx,&sy);
1439        if (!CheckList(sx,sy,6,1,TIDoneOn,TIDoneOff,1))
1440          oktoexit++;
1441
1442        if (keydown[1])
1443          {
1444           while(keydown[1]);
1445           oktoexit++;
1446          }
1447       }while(!oktoexit);
1448
1449       RestoreBackground();
1450      }
1451   }
1452  }
1453 }
1454
1455
1456
1457 ////////////////////////////////////////////////////
1458 //
1459 // Item - Project Re-Select
1460 //
1461 ////////////////////////////////////////////////////
1462 btype NGBb[]={{" Do It! ",1,4,2},
1463               {" No! Help! ",16,4,1}};
1464 DialogDef NGBd={"Are you sure you want to\n"
1465                 "switch projects? Abort now\n"
1466                 "or forever hold your peace!",
1467                 28,6,2,&NGBb[0],NULL};
1468
1469 void Item_ProjectReSelect(void)
1470 {
1471  int i,which;
1472
1473  //
1474  // ARE YOU SURE?!
1475  //
1476  which=DoDialog(&NGBd);
1477  if (!which || which==2)
1478    return;
1479
1480
1481  TEDInfo->lastvid=videomode;
1482  TEDInfo->level=whichmap;
1483  SaveTEDInfo();
1484  SaveOutputHeader();
1485
1486  if (!CheckForMapSave())
1487    return;
1488
1489  //
1490  // RELEASE ALL MEMORY
1491  //         ---
1492  if (MapBkgnd)
1493    {
1494     MMFreePtr((memptr *)&MapBkgnd);
1495     MMFreePtr((memptr *)&CutBkgnd);
1496    }
1497  if (MapFrgnd)
1498    {
1499     MMFreePtr((memptr *)&MapFrgnd);
1500     MMFreePtr((memptr *)&CutFrgnd);
1501    }
1502  if (MapInfoPl)
1503    {
1504     MMFreePtr((memptr *)&MapInfoPl);
1505     MMFreePtr((memptr *)&CutInfoPl);
1506    }
1507
1508  MMFreePtr((memptr *)&TEDInfo);
1509  MMFreePtr((memptr *)&MapFileHeader);
1510
1511  if (CgaXMS)
1512    {
1513     MMFreePtr((memptr *)&CgaXMSlookup);
1514     XMSFreeMem(CgaXMS);
1515    }
1516  if (EgaXMS)
1517    {
1518     MMFreePtr((memptr *)&EgaXMSlookup);
1519     XMSFreeMem(EgaXMS);
1520    }
1521  if (VgaXMS)
1522    {
1523     MMFreePtr((memptr *)&VgaXMSlookup);
1524     XMSFreeMem(VgaXMS);
1525    }
1526  if (XMSmaps)
1527    XMSFreeMem(XMSmaps);
1528
1529  XMSmaps=CgaXMS=EgaXMS=VgaXMS=xmshandle=0;
1530
1531
1532  for (i=0;i<numtplanes;i++)
1533    if (Tinfo[i])
1534      MMFreePtr((memptr *)&Tinfo[i]);
1535  for (i=0;i<numtmplanes;i++)
1536    if (TMinfo[i])
1537      MMFreePtr((memptr *)&TMinfo[i]);
1538
1539  //
1540  // FORCE RE-INIT
1541  //
1542  writeH=TIxbase=TIxmbase=TIybase=TIymbase=PasteOK=DirtyFlag=ext[0]=0;
1543  lastmap=-1;
1544
1545  FindGraphFile();
1546  LoadInfoFile();
1547  LoadMapHeader();
1548  LoadGraphStuff(0,videomode);
1549  MouseHide();
1550  RedrawDesktop();
1551  MouseShow();
1552  DrawInfoBar();
1553  DrawMap();
1554 }
1555
1556
1557 ////////////////////////////////////////////////////
1558 //
1559 // Item - Toggle GRIDMODE on/off
1560 //
1561 ////////////////////////////////////////////////////
1562 void Item_GridMode(void)
1563 {
1564  GridMode^=1;
1565
1566  if (PasteMode)
1567    DrawFloatPaste();
1568
1569  DrawMap();
1570  DrawInfoBar();
1571 }
1572
1573
1574 ////////////////////////////////////////////////////
1575 //
1576 // Item - Toggle SNAP-PASTE on/off
1577 //
1578 ////////////////////////////////////////////////////
1579 void Item_SnapTog(void)
1580 {
1581  if (!PasteMode)
1582    return;
1583
1584  EraseFloatPaste();
1585  SnapMode^=1;
1586
1587  snapx=(pixelx>>(tsize+2))+xbase;
1588  snapy=((pixely-8)>>(tsize+2))+ybase;
1589  snapxsize=TileCopy.w;
1590  snapysize=TileCopy.h;
1591
1592  snapx=snapx-(snapx/snapxsize)*snapxsize;
1593  snapy=snapy-(snapy/snapysize)*snapysize;
1594
1595  DrawInfoBar();
1596  DrawFloatPaste();
1597 }
1598
1599
1600 ////////////////////////////////////////////////////
1601 //
1602 // Item - View Map & Goto
1603 //
1604 ////////////////////////////////////////////////////
1605 void Item_ViewMap(void)
1606 {
1607  Do_ViewMap(0);
1608 }
1609
1610
1611 ////////////////////////////////////////////////////
1612 //
1613 // Item - Review Map & Goto
1614 //
1615 ////////////////////////////////////////////////////
1616 void Item_ReviewMap(void)
1617 {
1618  Do_ViewMap(1);
1619 }
1620
1621
1622 ////////////////////////////////////////////////////
1623 //
1624 // Code to actually do the ViewMap (and save it in
1625 // EGA memory when finished).
1626 // Entry:
1627 // 0 = ViewMap, as normal & save when done (but only
1628 //      if a full map was viewed)
1629 // 1 = RestoreMap for GOTO
1630 //
1631 ////////////////////////////////////////////////////
1632 void Do_ViewMap(int how)
1633 {
1634  int _seg *a_bg,_seg *a_fg,_seg *a_in,CopyArea,bl_width,bl_height,bl_x,bl_y,p_info;
1635
1636  char huge *EGA=MK_FP(0xa000,0);
1637  char _seg *block,_seg *gblock[4];
1638  int i,j,k,m,n,pwidth,lwidth,maptype,step,pixnum[4]={0,8,16,32},curpix,
1639           maxpack,curline,lybase,t8=8<<(tsize-1),t1=1<<(tsize-1),scrn_h,scrn_w;
1640  long tilelen,bufsize;
1641  int savevideo;
1642
1643
1644
1645  savevideo=videomode;
1646  MouseHide();
1647  setvideo(EGA1);
1648  MouseShow();
1649  if (videomode!=EGA1 && videomode!=EGA2)
1650  {
1651   ErrDialog("This function is currently\n"
1652                  "only usable in EGA mode!"," OK ");
1653   return;
1654  }
1655
1656  //
1657  // SCREEN DIMENSIONS
1658  //
1659  scrn_w=320;
1660  scrn_h=200;
1661
1662
1663  bl_x=bl_y=0;
1664  bl_width=mapwidth;
1665  bl_height=mapheight;
1666  a_bg=MapBkgnd;
1667  a_fg=MapFrgnd;
1668  a_in=MapInfoPl;
1669  p_info=MapFileHeader->maptype;
1670  CopyArea=0;
1671
1672  if ((TileCopy.w>screenw || TileCopy.h>screenh) && !how)
1673         if (Message("\"Yes\" to display full map,\n"
1674                          "\"No\" to display COPY buffer.")==1)
1675         {
1676          bl_x=TileCopy.x;
1677          bl_y=TileCopy.y;
1678          bl_width=TileCopy.w;
1679          bl_height=TileCopy.h;
1680          a_bg=CutBkgnd;
1681          a_fg=CutFrgnd;
1682          a_in=CutInfoPl;
1683          p_info=TileCopy.PlanesCopied;
1684          CopyArea=1;
1685         }
1686
1687  //
1688  // VALIDATE WIDTH & HEIGHT
1689  //
1690  if (bl_height<screenh && bl_width<screenw)
1691  {
1692   ErrDialog("The area fits within the\n"
1693                  "screen! Forget it!"," Wah! ");
1694   return;
1695  }
1696
1697
1698  //
1699  // FIGURE OUT THE BEST RATIO FOR CONVERSION
1700  //
1701  if (!how)
1702         switch(bl_width>=bl_height)
1703         {
1704          case 1: // WIDTH > HEIGHT
1705                 step=(float)(pixnum[tsize]*bl_width)/scrn_w+.5;
1706                 if (pixnum[tsize]*bl_width/step>scrn_w)
1707         step++;
1708                 if ((float)(pixnum[tsize]*bl_height)/step+.5<scrn_h)
1709         break;
1710
1711          case 0: // HEIGHT > WIDTH
1712                 step=(float)(pixnum[tsize]*bl_height)/scrn_h+.5;
1713                 if (pixnum[tsize]*bl_height/step>scrn_h)
1714         step++;
1715         }
1716  else
1717         step=VMapData.step;
1718
1719
1720  //
1721  // POP LAST MAP ON SCREEN
1722  //
1723  if (how)
1724  {
1725   unsigned EGAseg=VMapData.EGAseg;
1726
1727   if (!VMapData.built_flag)
1728   {
1729         ErrDialog("You haven't previously\n"
1730                   "VIEWed a map!"," OK ");
1731         return;
1732   }
1733
1734   //
1735   // RESTORE MAP IN MEMORY!
1736   //
1737   MouseHide();
1738   outport(GCindex,GCmode | 0x100);
1739   outport(SCindex,SCmapmask | 0xf00);
1740   asm   push    ds
1741   asm   mov     ax,[EGAseg]
1742   asm   mov     ds,ax
1743   asm   mov     ax,0xa000
1744   asm   mov     es,ax
1745   asm   xor     si,si
1746   asm   xor     di,di
1747   asm   mov     cx,0x2000
1748   asm   rep movsb
1749   asm   pop     ds
1750   step=VMapData.step;
1751   maxpack=VMapData.maxpack;
1752   MouseShow();
1753  }
1754  //
1755  // BUILD MAP
1756  //
1757  else
1758  {
1759   //
1760   // CLEAR EGA SCREEN
1761   //
1762   outport(GCindex,GCmode);
1763   outport(SCindex,SCmapmask | 0xf00);
1764   _fmemset(MK_FP(0xa000,0),0,0x2000);
1765
1766   //
1767   // SET TILE LENGTH
1768   //
1769   switch(tsize)
1770   {
1771         case 1: tilelen=32L; break;
1772         case 2: tilelen=128L; break;
1773         case 3: tilelen=512L;
1774   }
1775
1776   //
1777   // ALLOCATE TEMP BUFFERS & BEGIN!
1778   //
1779   bufsize=tilelen*bl_width;
1780   pwidth=t1*bl_width;
1781   lwidth=pwidth*4;
1782   MMAllocate((memptr *)&block,bufsize);
1783   maxpack=pwidth/step+1;
1784   for (i=0;i<4;i++)
1785          MMAllocate((memptr *)&gblock[i],maxpack);
1786
1787   outport(GCindex,GCmode);
1788   curline=0;
1789   for (j=bl_y;j<bl_y+bl_height;j++)
1790   {
1791         lybase=j*t8;
1792         for (i=bl_x;i<bl_x+bl_width;i++)
1793         {
1794          unsigned tilet,tilem,tilei,loc;
1795
1796          //
1797          // ESC out?
1798          //
1799          if (keydown[1])
1800          {
1801           while(keydown[1]);
1802           setvideo(savevideo);
1803           RedrawDesktop();
1804           DrawMap();
1805           DrawInfoBar();
1806           return;
1807          }
1808          //
1809          // GET THE CORRECT TILE MOVED INTO "TDATA"
1810          //
1811          loc=j*mapwidth+i;
1812          tilet=viewton?((p_info&BPLANE)?a_bg[loc]:-BkgndColor):-BkgndColor;
1813          tilem=viewmon?((p_info&FPLANE)?a_fg[loc]+tilenum:0):0;
1814          tilei=viewion?((p_info&IPLANE)?a_in[loc]+tilenum:0):0;
1815          CombineTiles(tilet,tilem,tilei,tsize);
1816
1817          //
1818          // NOW, MUNGE "TDATA" INTO BIT-PLANES!
1819          //
1820          // INTERNAL:           P0      P1      P2      P3
1821          //     SCANLINE x      ......  ......  ......  ......
1822          //
1823          for (k=0;k<t8;k++)
1824                 if (!((lybase+k)%step))
1825         for (m=0;m<4;m++)
1826           movedata(FP_SEG(&tdata),FP_OFF(&tdata)+(m*tsize*t8)+k*t1,
1827                          (unsigned)block,k*lwidth+m*pwidth+(i-bl_x)*t1,t1);
1828         }
1829
1830         //
1831         // CONVERT BIT-PLANE LINES TO COMPRESSED FORM...
1832         //
1833         for (k=0;k<8<<(tsize-1);k++)
1834         {
1835          if (!((lybase+k)%step))
1836          {
1837           int midx=k*lwidth;
1838
1839
1840           curpix=0;
1841           _fmemset(gblock[0],0,maxpack);
1842           _fmemset(gblock[1],0,maxpack);
1843           _fmemset(gblock[2],0,maxpack);
1844           _fmemset(gblock[3],0,maxpack);
1845           for (m=0;m<pwidth*8;m++)
1846           {
1847                 if (!(m%step))
1848                 {
1849                  int temp=curpix/8,
1850                 temp1=7-(curpix%8),
1851                 temp2=7-(m%8),
1852                 idx;
1853
1854
1855                  idx=midx+m/8;
1856
1857                  #if 1
1858                  asm    push    ds
1859
1860                  asm    mov     ds,[block]
1861                  asm    mov     si,[idx]
1862                  asm    mov     cl,[BYTE PTR temp2]
1863                  asm    mov     ch,[BYTE PTR temp1]
1864                  asm    mov     di,[temp]
1865                  asm    mov     dx,[pwidth]
1866                  asm    dec     dx
1867
1868                  asm    mov     es,[WORD PTR gblock]
1869
1870                  asm    lodsb
1871                  asm    shr     al,cl
1872                  asm    and     al,1
1873                  asm    xchg    ch,cl
1874                  asm    shl     al,cl
1875                  asm    xchg    ch,cl
1876                  asm    or      [es:di],al
1877
1878                  asm    add     si,dx
1879
1880                  asm    mov     es,[WORD PTR gblock+2]
1881
1882                  asm    lodsb
1883                  asm    shr     al,cl
1884                  asm    and     al,1
1885                  asm    xchg    ch,cl
1886                  asm    shl     al,cl
1887                  asm    xchg    ch,cl
1888                  asm    or      [es:di],al
1889
1890                  asm    add     si,dx
1891
1892                  asm    mov     es,[WORD PTR gblock+4]
1893
1894                  asm    lodsb
1895                  asm    shr     al,cl
1896                  asm    and     al,1
1897                  asm    xchg    ch,cl
1898                  asm    shl     al,cl
1899                  asm    xchg    ch,cl
1900                  asm    or      [es:di],al
1901
1902                  asm    add     si,dx
1903
1904                  asm    mov     es,[WORD PTR gblock+6]
1905
1906                  asm    lodsb
1907                  asm    shr     al,cl
1908                  asm    and     al,1
1909                  asm    xchg    ch,cl
1910                  asm    shl     al,cl
1911                  asm    xchg    ch,cl
1912                  asm    or      [es:di],al
1913
1914                  asm    add     si,dx
1915
1916                  asm    pop     ds
1917
1918                  #else
1919                  *(gblock[0]+temp)|=((block[idx]>>temp2)&1)<<temp1;
1920                  *(gblock[1]+temp)|=((block[idx+pwidth]>>temp2)&1)<<temp1;
1921                  *(gblock[2]+temp)|=((block[idx+pwidth*2]>>temp2)&1)<<temp1;
1922                  *(gblock[3]+temp)|=((block[idx+pwidth*3]>>temp2)&1)<<temp1;
1923                  #endif
1924
1925                  curpix++;
1926                 }
1927           }
1928
1929           //
1930           // BLAST ONTO THE SCREEN
1931           //
1932
1933           MouseHide();
1934           for (n=0;n<4;n++)
1935           {
1936                 outport(SCindex,SCmapmask | (0x100<<n));
1937                 for (m=0;m<maxpack;m++)
1938         *(EGA+EGA1lookup[curline]+m)=*(gblock[n]+m);
1939      }
1940      MouseShow();
1941
1942      curline++;
1943     }
1944    }
1945   }
1946
1947   MMFreePtr((memptr *)&block);
1948   for(m=0;m<4;m++)
1949     MMFreePtr((memptr *)&gblock[m]);
1950
1951
1952   //
1953   // SAVE MAP IN MEMORY!
1954   //
1955   if (!CopyArea)
1956   {
1957    unsigned EGAseg=0xa800;
1958
1959
1960    MouseHide();
1961    outport(GCindex,GCmode | 0x100);
1962    outport(SCindex,SCmapmask | 0xf00);
1963    asm  push    ds
1964    asm  mov     ax,[EGAseg]
1965    asm  mov     es,ax
1966    asm  mov     ax,0xa000
1967    asm  mov     ds,ax
1968    asm  xor     si,si
1969    asm  xor     di,di
1970    asm  mov     cx,0x2000
1971    asm  rep movsb
1972    asm  pop     ds
1973    VMapData.step=step;
1974    VMapData.built_flag=1;
1975    VMapData.EGAseg=EGAseg;
1976    VMapData.maxpack=maxpack;
1977    MouseShow();
1978   }
1979  }
1980
1981
1982  //
1983  // DONE WITH MAP BUILD-N-DISPLAY
1984  //
1985  SignalSound();
1986  clearkeys();
1987
1988  //
1989  // IF MOUSE BUTTON PRESSED WITHIN REGION, GO THERE!
1990  //
1991  while(!bioskey(1))
1992    if (MouseButton())
1993    {
1994     int x,y;
1995
1996     MouseCoords(&x,&y);
1997     if (x<maxpack*8 && y<(mapheight*t8/step) && !CopyArea)
1998     {
1999      xbase=(x*step)/t8-screenw/2;
2000      ybase=(y*step)/t8-screenh/2;
2001      if (xbase+screenw>mapwidth)
2002        xbase=mapwidth-screenw;
2003      if (ybase+screenh>mapheight)
2004        ybase=mapheight-screenh;
2005      if (xbase<0)
2006        xbase=0;
2007      if (ybase<0)
2008        ybase=0;
2009     }
2010     while(MouseButton());
2011     break;
2012    }
2013
2014  clearkeys();
2015  MouseHide();
2016  setvideo(savevideo);
2017  RedrawDesktop();
2018  DrawMap();
2019  DrawInfoBar();
2020  MouseShow();
2021 }
2022
2023
2024 ////////////////////////////////////////////////////
2025 //
2026 // MAP IMPORTING FUNCTIONS FOLLOW:
2027 //
2028 ////////////////////////////////////////////////////
2029 char _seg *oldnames,oldmapname[64],oldmapheadname[64],
2030         oldSM_name[64],oldSM_loadname[64];
2031
2032 int IM_swapin(void)
2033 {
2034  int i;
2035
2036
2037  _fstrcpy(mapheadname,TEDInfo->ImportPath);
2038  strcat(mapheadname,oldmapheadname);
2039  if (access(mapheadname,0))
2040    {
2041     strcpy(mapheadname,oldmapheadname);
2042     return 0;
2043    }
2044
2045  _fstrcpy(mapname,TEDInfo->ImportPath);
2046  strcat(mapname,oldmapname);
2047
2048
2049  _fstrcpy(SM_name,TEDInfo->ImportPath);
2050  strcat(SM_name,oldSM_name);
2051
2052  _fstrcpy(SM_loadname,TEDInfo->ImportPath);
2053  strcat(SM_loadname,oldSM_loadname);
2054
2055  MMAllocate((memptr *)&oldnames,100*16);
2056  movedata(FP_SEG(MapNames),FP_OFF(MapNames),(unsigned)oldnames,0,100*16);
2057
2058  MMFreePtr((memptr *)&MapFileHeader);
2059
2060  LoadIn(mapheadname,(memptr *)&MapFileHeader);
2061
2062  for (i=0;i<100;i++)
2063    if (MapFileHeader->dataoffsets[i]>=0)
2064    {
2065     MapHeaderStr TempHead;
2066
2067     LoadFile(mapname,(char huge *)&TempHead,MapFileHeader->dataoffsets[i],sizeof(MapHeaderStr));
2068     strcpy(MapNames[i],TempHead.name);
2069    }
2070  return 1;
2071 }
2072
2073
2074 void IM_swapout(void)
2075 {
2076  if (oldnames)          // GET RID OF MAPNAMES
2077  {
2078   strcpy(mapname,oldmapname);
2079   strcpy(mapheadname,oldmapheadname);
2080   strcpy(SM_name,oldSM_name);
2081   strcpy(SM_loadname,oldSM_loadname);
2082
2083   movedata((unsigned)oldnames,0,FP_SEG(MapNames),FP_OFF(MapNames),100*16);
2084   MMFreePtr((memptr *)&oldnames);
2085   MMFreePtr((memptr *)&MapFileHeader);
2086   LoadIn(mapheadname,(memptr *)&MapFileHeader);
2087
2088  }
2089 }
2090
2091 void IM_LoadMap(void)
2092 {
2093  unsigned long csize,size=0;
2094  memptr block;
2095
2096  //
2097  // DEALLOCATE ALL CURRENT MAP MEMORY
2098  //
2099  if (MapBkgnd)
2100    {
2101     MMFreePtr((memptr *)&MapBkgnd);
2102     MMFreePtr((memptr *)&CutBkgnd);
2103    }
2104  if (MapFrgnd)
2105    {
2106     MMFreePtr((memptr *)&MapFrgnd);
2107     MMFreePtr((memptr *)&CutFrgnd);
2108    }
2109  if (MapInfoPl)
2110    {
2111     MMFreePtr((memptr *)&MapInfoPl);
2112     MMFreePtr((memptr *)&CutInfoPl);
2113    }
2114
2115  //
2116  // LOAD MAP HEADER
2117  //
2118  LoadFile(mapname,(char huge *)&MapHeader,MapFileHeader->dataoffsets[whichmap],sizeof(MapHeaderStr));
2119
2120  //
2121  // LOAD & DECOMPRESS MAP PLANES
2122  //
2123  if (MapFileHeader->maptype & BPLANE)
2124    {
2125     LoadFile(mapname,(char huge *)&size,MapHeader.mapbkgndpl,2);
2126
2127     MMAllocate((memptr *)&MapBkgnd,size);
2128     MMAllocate((memptr *)&CutBkgnd,size);
2129     csize=MapHeader.mapbkgndlen-2;
2130     MMAllocate(&block,csize);
2131
2132     LoadFile(mapname,MK_FP(block,0),MapHeader.mapbkgndpl+2,csize);
2133
2134     RLEWExpand(MK_FP(block,0),MK_FP(MapBkgnd,0),size,MapFileHeader->RLEWtag);
2135     MMFreePtr(&block);
2136    }
2137  if (MapFileHeader->maptype & FPLANE)
2138    {
2139     LoadFile(mapname,(char huge *)&size,MapHeader.mapfrgndpl,2);
2140
2141     MMAllocate((memptr *)&MapFrgnd,size);
2142     MMAllocate((memptr *)&CutFrgnd,size);
2143     csize=MapHeader.mapfrgndlen-2;
2144     MMAllocate(&block,csize);
2145
2146     LoadFile(mapname,MK_FP(block,0),MapHeader.mapfrgndpl+2,csize);
2147
2148     RLEWExpand(MK_FP(block,0),MK_FP(MapFrgnd,0),size,MapFileHeader->RLEWtag);
2149     MMFreePtr(&block);
2150    }
2151  if (MapFileHeader->maptype & IPLANE)
2152    {
2153     LoadFile(mapname,(char huge *)&size,MapHeader.mapinfopl,2);
2154
2155     MMAllocate((memptr *)&MapInfoPl,size);
2156     MMAllocate((memptr *)&CutInfoPl,size);
2157     csize=MapHeader.mapinfolen-2;
2158     MMAllocate(&block,csize);
2159
2160     LoadFile(mapname,MK_FP(block,0),MapHeader.mapinfopl+2,csize);
2161
2162     RLEWExpand(MK_FP(block,0),MK_FP(MapInfoPl,0),size,MapFileHeader->RLEWtag);
2163     MMFreePtr(&block);
2164    }
2165 }
2166
2167
2168 void IM_SaveMap(void)
2169 {
2170  memptr block;
2171  long fsize,size,nsize,change;
2172  MapHeaderStr TempHeader;
2173  int i,XMStemp;
2174  char string[100],TEDid[]=IDSTRING;
2175
2176
2177
2178  strcpy(string,"Saving Map, '");
2179  strcat(string,MapHeader.name);
2180
2181  strcat(string,"'.");
2182  ErrDialog(string,"");
2183
2184  //
2185  // SAVE MAP FILE HEADER
2186  //
2187  SaveFile(mapheadname,MK_FP(MapFileHeader,0),0,sizeof(MapFileHeaderStr));
2188  fsize=sizeof(MapFileHeaderStr);
2189
2190  //
2191  // COMPRESS & SAVE TILEINFOS
2192  //
2193  for (i=0;i<numtplanes;i++)
2194    {
2195     MMAllocate(&block,tilenum);
2196     MapFileHeader->tileinfooff[i]=fsize;
2197     nsize=RLEBCompress(MK_FP(Tinfo[i],0),tilenum,MK_FP(block,0),MapFileHeader->RLEWtag);
2198     MapFileHeader->tileinfolen[i]=nsize;
2199     SaveFile(mapheadname,MK_FP(block,0),fsize,nsize);
2200     fsize+=nsize;
2201     MMFreePtr(&block);
2202    }
2203
2204  for (i=0;i<numtmplanes;i++)
2205    {
2206     MMAllocate(&block,tilemnum);
2207     MapFileHeader->tileinfomoff[i]=fsize;
2208     nsize=RLEBCompress(MK_FP(TMinfo[i],0),tilemnum,MK_FP(block,0),MapFileHeader->RLEWtag);
2209     MapFileHeader->tileinfomlen[i]=nsize;
2210     SaveFile(mapheadname,MK_FP(block,0),fsize,nsize);
2211     fsize+=nsize;
2212     MMFreePtr(&block);
2213    }
2214
2215  MapFileHeader->oldtilenum=tilenum;
2216  MapFileHeader->oldtilemnum=tilemnum;
2217
2218  SaveFile(mapheadname,MK_FP(MapFileHeader,2),2,sizeof(MapFileHeaderStr)-2);
2219  //
2220  // SAVE ALREADY COMPRESSED MAPS
2221  //
2222
2223  //
2224  // NOTE: I AM STORING "TED5" AT THE START OF THE FILE BECAUSE
2225  // SAVING THE FILE AT OFFSET 0 WILL TRASH IT (I HAVE TO RE-SAVE THE HEADER!)
2226  //
2227  SaveFile(SM_name,(char huge *)TEDid,0,strlen(TEDid));
2228  fsize=strlen(TEDid);
2229
2230  for (i=0;i<100;i++)
2231  {
2232   long oldoff;
2233
2234   if (MapFileHeader->dataoffsets[i]==-1 || i==whichmap)
2235     continue;
2236
2237   oldoff=MapFileHeader->dataoffsets[i];
2238
2239   LoadFile(SM_loadname,(char huge *)&TempHeader,oldoff,sizeof(MapHeaderStr));
2240
2241   strcpy(TempHeader.name,MapNames[i]);
2242   MapFileHeader->dataoffsets[i]=fsize;
2243   size=TempHeader.mapbkgndlen+TempHeader.mapfrgndlen+TempHeader.mapinfolen;
2244   change=TempHeader.mapbkgndpl-fsize-sizeof(MapHeaderStr);
2245   TempHeader.mapbkgndpl-=change;
2246   TempHeader.mapfrgndpl-=change;
2247   TempHeader.mapinfopl-=change;
2248
2249   SaveFile(SM_name,(char huge *)&TempHeader,fsize,sizeof(MapHeaderStr));
2250   fsize+=sizeof(MapHeaderStr);
2251
2252   MMAllocate(&block,size);
2253   LoadFile(SM_loadname,MK_FP(block,0),oldoff+sizeof(MapHeaderStr),size);
2254   SaveFile(SM_name,MK_FP(block,0),fsize,size);
2255   fsize+=size;
2256   SaveFile(SM_name,"!ID!",fsize,4);
2257   fsize+=4;
2258   MMFreePtr(&block);
2259  }
2260
2261  //
2262  // SAVE CURRENT MAP AT END OF FILE
2263  //
2264  MapFileHeader->dataoffsets[whichmap]=fsize;
2265  MapFileHeader->datalengths[whichmap]=sizeof(MapHeaderStr);
2266  SaveFile(SM_name,(char huge *)&MapHeader,fsize,sizeof(MapHeaderStr));
2267  fsize+=sizeof(MapHeaderStr);
2268
2269  size=MapHeader.width*MapHeader.height*sizeof(int);
2270  MMAllocate(&block,size);
2271  if (MapFileHeader->maptype & BPLANE)
2272    {
2273     MapHeader.mapbkgndpl=fsize;
2274     nsize=RLEWCompress(MK_FP(MapBkgnd,0),size,MK_FP(block,0),MapFileHeader->RLEWtag);
2275     MapHeader.mapbkgndlen=nsize+2;
2276
2277     SaveFile(SM_name,(char huge *)&size,fsize,2);
2278     fsize+=2;
2279     SaveFile(SM_name,MK_FP(block,0),fsize,nsize);
2280     fsize+=nsize;
2281    }
2282  else
2283    MapHeader.mapbkgndlen=0;
2284
2285  if (MapFileHeader->maptype & FPLANE)
2286    {
2287     MapHeader.mapfrgndpl=fsize;
2288     nsize=RLEWCompress(MK_FP(MapFrgnd,0),size,MK_FP(block,0),MapFileHeader->RLEWtag);
2289     MapHeader.mapfrgndlen=nsize+2;
2290
2291     SaveFile(SM_name,(char huge *)&size,fsize,2);
2292     fsize+=2;
2293     SaveFile(SM_name,MK_FP(block,0),fsize,nsize);
2294     fsize+=nsize;
2295    }
2296  else
2297    MapHeader.mapfrgndlen=0;
2298
2299  if (MapFileHeader->maptype & IPLANE)
2300    {
2301     MapHeader.mapinfopl=fsize;
2302     nsize=RLEWCompress(MK_FP(MapInfoPl,0),size,MK_FP(block,0),MapFileHeader->RLEWtag);
2303     MapHeader.mapinfolen=nsize+2;
2304
2305     SaveFile(SM_name,(char huge *)&size,fsize,2);
2306     fsize+=2;
2307     SaveFile(SM_name,MK_FP(block,0),fsize,nsize);
2308     fsize+=nsize;
2309    }
2310  else
2311    MapHeader.mapinfolen=0;
2312
2313  SaveFile(SM_name,"!ID!",fsize,4);
2314
2315  fsize+=4;
2316
2317  MMFreePtr(&block);
2318
2319  // RE-SAVE HEADER
2320  SaveFile(SM_name,(char huge *)&MapHeader,
2321      MapFileHeader->dataoffsets[whichmap],sizeof(MapHeaderStr));
2322
2323  //
2324  // RE-SAVE FILE HEADER
2325  // NOTE: The "2" is so MSDOS doesn't truncate the fucking file!
2326  //
2327  SaveFile(mapheadname,MK_FP(MapFileHeader,2),2,sizeof(MapFileHeaderStr)-2);
2328
2329  unlink(SM_loadname);
2330  rename(SM_name,SM_loadname);
2331
2332  RestoreBackground();
2333 }
2334
2335
2336 ////////////////////////////////////////////////////
2337 //
2338 // Item - Import Maps
2339 //
2340 ////////////////////////////////////////////////////
2341 btype IMPMb[]={{"New Path",3,2,1},
2342                {" Import ",3,5,1},
2343                {"  Exit  ",3,8,2}};
2344 DialogDef IMPMd={"Map Importing",13,11,3,&IMPMb[0],NULL};
2345 btype NPb={"                                    ",1,3,1};
2346 DialogDef NPd={"Current Path:",38,5,1,&NPb,NULL};
2347
2348
2349 void Item_ImportMaps(void)
2350 {
2351  char imfile[64],tempstr[40],impath[64];
2352  int oldwhichmap,which,mapnum,i;
2353  int oldxb,oldyb;
2354
2355
2356  CheckForMapSave();
2357
2358  //
2359  // THE IMPORT FUNCTION WILL RID THE SYSTEM OF XMSMAPS
2360  //
2361  if (XMSmaps)
2362  {
2363   XMSFreeMem(XMSmaps);
2364   XMSmaps=0;
2365  }
2366
2367  //
2368  // SAVE PATHS
2369  //
2370  _fstrcpy(impath,TEDInfo->ImportPath);
2371
2372  strcpy(oldmapname,mapname);
2373  strcpy(oldmapheadname,mapheadname);
2374  strcpy(oldSM_name,SM_name);
2375  strcpy(oldSM_loadname,SM_loadname);
2376
2377  oldxb=xbase;
2378  oldyb=ybase;
2379  #pragma warn -sus
2380  oldnames=0;
2381  #pragma warn +sus
2382  oldwhichmap=whichmap;
2383
2384  DrawDialog(&IMPMd,1);
2385  while(1)
2386  {
2387   which=CheckButtons(&IMPMd);
2388   switch(which)
2389   {
2390    //
2391    // NEW PATH
2392    //
2393    case 1:
2394      MouseHide();
2395      DrawDialog(&NPd,1);
2396      GetDialogXY(&NPd,&sx,&sy);
2397      sy++;
2398      sx++;
2399      if (!impath[0])
2400        print("- current dir -");
2401      else
2402        print(impath);
2403      GetButtonXY(&NPd,0,&sx,&sy);
2404      if (input(tempstr,36))
2405        {
2406         strcpy(impath,tempstr);
2407         if (impath[strlen(impath)-1]!='\\')
2408           strcat(impath,"\\");
2409
2410         MouseShow();
2411         if (access(mapheadname,0))
2412         {
2413          ErrDialog("Can't find any TED5\n"
2414                    "map files at that path."," OK ");
2415         }
2416         else
2417         {
2418          RestoreBackground();
2419          ErrDialog("Verifying path...","");
2420          _fstrcpy(TEDInfo->ImportPath,impath);
2421          DirtyFlag=1;
2422         }
2423
2424         MouseHide();
2425        }
2426      MouseShow();
2427      RestoreBackground();
2428      break;
2429
2430    //
2431    // IMPORT
2432    //
2433    case 2:
2434      if (!oldnames)
2435      {
2436       ErrDialog("Loading File Info...","");
2437       if (!IM_swapin())
2438       {
2439        RestoreBackground();
2440        ErrDialog("Having problems with your path!"," OK ");
2441        break;
2442       }
2443       RestoreBackground();
2444      }
2445
2446      mapnum=SelectMap(1,CREATED,"TO IMPORT");
2447      if (mapnum>=0)
2448      {
2449       char check[100]="Are you SURE you want to\n"
2450                       "Import ";
2451
2452       strcat(check,MapNames[mapnum]);
2453       strcat(check,"?");
2454       if (Message(check)<2)
2455         break;
2456
2457       whichmap=mapnum;
2458       ErrDialog("Importing. One moment.","");
2459       IM_LoadMap();
2460       IM_swapout();
2461       IM_SaveMap();
2462       IM_swapin();
2463       RestoreBackground();
2464      }
2465      break;
2466
2467    //
2468    // EXIT
2469    //
2470    case 0:
2471    case 3:
2472      RestoreBackground();
2473      whichmap=oldwhichmap;
2474      IM_swapout();
2475
2476      LoadMap(whichmap);
2477      xbase=oldxb;
2478      ybase=oldyb;
2479      DrawMap();
2480
2481      return;
2482   }
2483  }
2484 }
2485
2486
2487 ////////////////////////////////////////////////////
2488 //
2489 // Item - Visit DOS
2490 //
2491 ////////////////////////////////////////////////////
2492 int olddisk;
2493 char oldpath[64]="\\";
2494
2495 void Item_VisitDOS(void)
2496 {
2497  TempStruct LaunchInfo;
2498  char ename[64],temp[40],tiname[14]="TEDINFO.TMP";
2499
2500  long size;
2501
2502
2503  //
2504  // Save the handles for all XMS memory so we don't
2505  // have to re-install this shit!
2506  //
2507  TEDInfo->OldCgaXMS=CgaXMS;
2508  TEDInfo->OldEgaXMS=EgaXMS;
2509  TEDInfo->OldVgaXMS=VgaXMS;
2510
2511  TEDInfo->OldCgaXMSsize=CgaXMSsize;
2512  TEDInfo->OldEgaXMSsize=EgaXMSsize;
2513  TEDInfo->OldVgaXMSsize=VgaXMSsize;
2514
2515  size=4L*(tilenum+tilemnum);
2516  if (CgaXMS)
2517    {
2518     if (1024L*XMSTotalFree()<size)
2519       {
2520        XMSFreeMem(CgaXMS);
2521        TEDInfo->OldCgaXMS=TEDInfo->OldCgaXMSsize=0;
2522       }
2523     else
2524       {
2525        TEDInfo->CgaXMSlook=XMSAllocate(size);
2526        XMSmove(0,(long)MK_FP(CgaXMSlookup,0),TEDInfo->CgaXMSlook,0,size);
2527       }
2528    }
2529
2530  if (EgaXMS)
2531    {
2532     if (1024L*XMSTotalFree()<size)
2533       {
2534        XMSFreeMem(EgaXMS);
2535        TEDInfo->OldEgaXMS=TEDInfo->OldEgaXMSsize=0;
2536       }
2537     else
2538       {
2539        TEDInfo->EgaXMSlook=XMSAllocate(size);
2540        XMSmove(0,(long)MK_FP(EgaXMSlookup,0),TEDInfo->EgaXMSlook,0,size);
2541       }
2542    }
2543
2544  if (VgaXMS)
2545    {
2546     if (1024L*XMSTotalFree()<size)
2547       {
2548        XMSFreeMem(VgaXMS);
2549        TEDInfo->OldVgaXMS=TEDInfo->OldVgaXMSsize=0;
2550       }
2551     else
2552       {
2553        TEDInfo->VgaXMSlook=XMSAllocate(size);
2554        XMSmove(0,(long)MK_FP(VgaXMSlookup,0),TEDInfo->VgaXMSlook,0,size);
2555       }
2556    }
2557
2558  //
2559  // SAVE CURRENT VIDEOMODE FOR LAUNCH RETURN
2560  //
2561  LaunchInfo.lastmode=videomode;
2562  strcpy(LaunchInfo.ext,ext);
2563  SaveFile(tiname,(char huge *)&LaunchInfo,0,sizeof(TempStruct));
2564
2565  TEDInfo->oscrx=xbase;
2566  TEDInfo->oscry=ybase;
2567  _fmemcpy((void far *)TEDInfo->parmstring,(void far *)parmstring,64);
2568
2569  Item_SaveMap();
2570  SaveTEDInfo();
2571  SaveOutputHeader();
2572
2573  if (XMSmaps)
2574    XMSFreeMem(XMSmaps);
2575
2576  strcpy(temp,"Launching ");
2577  _fstrcat((char far *)temp,(char far *)TEDInfo->launchname);
2578  strcat(temp,"...");
2579  ErrDialog(temp,"");
2580  clearkeys();
2581  nosound();
2582  MouseHide();
2583
2584  _fmemcpy((char far *)ename,(char far *)TEDInfo->launchname,14);
2585
2586  RemoveUndoBuffers();
2587  ShutdownKBD();
2588
2589  //
2590  // ARE WE EXITING WITH A BATCH FILE?
2591  //
2592
2593  setvideo(TEXT);
2594  printf("The TED5 DOS shell. Type 'EXIT' to return to TED5.");
2595
2596  //
2597  // SAVE CURRENT DRIVE & PATH
2598  //
2599  olddisk=getdisk();
2600  getcurdir(0,oldpath+1);
2601
2602  MMShutdown();
2603  fcloseall();
2604  spawnlp(P_WAIT,"COMMAND",NULL);
2605
2606  //
2607  // RESET OLD PATH
2608  //
2609  setdisk(olddisk);
2610  chdir(oldpath);
2611
2612  execlp("TED5.EXE","TED5.EXE","/LAUNCH",NULL);
2613
2614  printf("Can't find TED5 for some reason!");
2615  exit(1);
2616 }
2617
2618
2619 ////////////////////////////////////////////////////
2620 //
2621 // Item - Paste Overlay toggle
2622 //
2623 ////////////////////////////////////////////////////
2624 void Item_POtog(void)
2625 {
2626  F3_flag^=1;
2627
2628  if (PasteMode)
2629  {
2630   EraseFloatPaste();
2631   DrawFloatPaste();
2632  }
2633 }