]> 4ch.mooo.com Git - 16.git/blob - 16/ted5/LIB.C
ted5 added
[16.git] / 16 / ted5 / LIB.C
1 #include "ted5.h"
2 #pragma hdrstop
3
4 extern char far TEDCHAR,far VGAPAL;
5
6 void Quit(char *string);
7 void drawchar(int x,int y,int chr);
8 void centerwindow (int width, int height);
9
10 int win_xl,win_yl,win_xh,win_yh;
11 int screencenterx = 19,screencentery = 11;
12 unsigned char keydown[256];
13 unsigned leftedge,yshift,xormask,MouseStatus,sx,sy;
14 void interrupt (*oldint9) ()=NULL;
15 enum {false,true} boolean;
16 memptr CGAfont,VGAfont;
17 unsigned doubled[256];
18 //
19 // Special vars to handle EGA3 mouse mode
20 //
21 int EGA3mx,EGA3my;
22
23
24 ////////////////////////////////////////////////////////////////////
25 //
26 // Return a file's length
27 //
28 ////////////////////////////////////////////////////////////////////
29 long filelen(char *filename)
30 {
31  long size;
32  int handle;
33
34  if ((handle=open(filename,O_BINARY))==-1)
35    return 0;
36
37  size=filelength(handle);
38  close(handle);
39  return size;
40 }
41
42 ////////////////////////////////////////////////////////////////////
43 //
44 // WaitVBL
45 //
46 ////////////////////////////////////////////////////////////////////
47 void WaitVBL(int times)
48 {
49 asm     mov     cx,times
50 asm     mov     dx,crtcaddr
51 asm     add     dx,6
52
53 waitvbl1:
54 asm     in      al,dx
55 asm     test    al,00001000b    //;look for vbl
56 asm     jnz     waitvbl1
57
58 waitvbl2:
59 asm     in      al,dx
60 asm     test    al,00001000b    //;look for vbl
61 asm     jz      waitvbl2
62
63 asm     loop    waitvbl1
64 }
65
66
67 ////////////////////////////////////////////////////////////////////
68 //
69 // Int9ISR
70 // Called for every keypress.  Keeps track of which keys are down, and passes
71 // the key on to DOS after clearing the dos buffer (max 1 char in buffer).
72 //
73 ////////////////////////////////////////////////////////////////////
74 void interrupt Int9ISR ()
75 {
76  int key = inportb (0x60);              /* get the key pressed */
77
78  if (key>127)
79    keydown [key-128] = false;           /* break scan code */
80  else
81  {
82    keydown [key] = true;                /* make scan code */
83    poke (0x40,0x1c,peek(0x40,0x1a));    /* clear the bios key buffer */
84  }
85 asm {
86    push ax
87    push bx
88    push cx
89    push dx
90    push si
91    push di
92    push bp
93  }
94  oldint9 ();                            /* give it to DOS */
95 asm {
96    pop  bp
97    pop  di
98    pop  si
99    pop  dx
100    pop  cx
101    pop  bx
102    pop  ax
103  }
104  outport (0x20,0x20);                   /* tell the int manager we got it */
105 }
106
107
108 ////////////////////////////////////////////////////////////////////
109 //
110 // SetupKBD
111 // Clears the keydown array and installs the INT 9 ISR if it isn't already
112 // hooked up.
113 //
114 ////////////////////////////////////////////////////////////////////
115 void SetupKBD ()
116 {
117  void far *vect = getvect (9);
118  int i;
119
120  for (i=0;i<128;i++)                    /* clear our key down table */
121    keydown[i]= false;
122
123  poke (0x40,0x1c,peek(0x40,0x1a));      /* clear the bios key buffer */
124
125  if ( &Int9ISR != vect )                /* is our handler allready set up? */
126  {
127    oldint9 = vect;
128    setvect (9,Int9ISR);
129  }
130 }
131
132
133 ////////////////////////////////////////////////////////////////////
134 //
135 // ShutdownKBD
136 // Sets the int 9 vector back to oldint 9
137 //
138 ////////////////////////////////////////////////////////////////////
139 void ShutdownKBD ()
140 {
141  if (oldint9 != NULL)
142    setvect (9,oldint9);
143 }
144
145
146 ////////////////////////////////////////////////////////////////////
147 //
148 // clearkeys
149 // Clears out the bios buffer and zeros out the keydown array
150 //
151 ////////////////////////////////////////////////////////////////////
152 void clearkeys (void)
153 {
154   int i;
155   while (bioskey (1))
156     bioskey(0);
157
158   for (i=0;i<128;i++)
159     keydown [i]=0;
160 }
161
162
163 ////////////////////////////////////////////////////////////////////
164 //
165 // Mouse Routines
166 //
167 ////////////////////////////////////////////////////////////////////
168 int MouseInit(void)
169 {
170  union REGS regs;
171  unsigned char far *vector;
172
173  if ((vector=MK_FP(peek(0,0x33*4+2),peek(0,0x33*4)))==NULL) return 0;
174
175  if (*vector == 207)
176    return MouseStatus = 0;
177
178  _AX=0;
179  geninterrupt(0x33);
180  EGA3mx=800/2;
181  EGA3my=600/2;
182
183  //
184  // Set CGA mouse cursor (normal one sucks)
185  //
186  if (videomode==CGA)
187    {
188     static unsigned CGAcursor[]=
189       {
190        0x0fff,0x03ff,0x00ff,0x003f,0x000f,0x0003,0x0000,0x000f,0x0c03,0x3c03,
191        0xff03,0xffff,0xffff,0xffff,0xffff,0xffff,
192
193        0xf000,0xcc00,0xc300,0xc0c0,0xc030,0xc00c,0xc03f,0xcc30,0xf30c,0xc30c,
194        0x00fc,0x0000,0x0000,0x0000,0x0000,0x0000
195       };
196
197     _BX=0;
198     _CX=0;
199     _DX=FP_OFF(CGAcursor);
200     _ES=_DS;
201     _AX=9;
202     geninterrupt(0x33);
203    }
204
205  return MouseStatus = 1;
206 }
207
208
209 void MouseOrigin(int x,int y)
210 {
211  if (!MouseStatus) return;
212
213  _CX=x;
214  _DX=y;
215  _AX=4;
216  geninterrupt(0x33);
217 }
218
219
220 void MouseLimits(int xmin,int xmax,int ymin,int ymax)
221 {
222  if (!MouseStatus) return;
223
224  _CX=xmin;
225  _DX=xmax;
226  _AX=7;
227  geninterrupt(0x33);
228  _CX=ymin;
229  _DX=ymax;
230  _AX=8;
231  geninterrupt(0x33);
232 }
233
234
235 void MouseHide(void)
236 {
237  if (!MouseStatus) return;
238
239  _AX=2;
240  geninterrupt(0x33);
241 }
242
243
244
245 void MouseShow(void)
246 {
247  if (!MouseStatus) return;
248
249  _AX=1;
250  geninterrupt(0x33);
251 }
252
253
254
255 int MouseButton(void)
256 {
257  union REGS regs;
258
259  if (!MouseStatus) return 0;
260
261  regs.x.ax=3;
262  int86(0x33,&regs,&regs);
263  return(regs.x.bx);
264 }
265
266
267
268 void MouseCoords(int *x,int *y)
269 {
270  union REGS regs;
271
272  if (!MouseStatus)
273    return;
274
275  regs.x.ax=3;
276  int86(0x33,&regs,&regs);
277  *x=regs.x.cx;
278  *y=regs.x.dx;
279
280  *x/=2;
281  if (videomode==EGA2)
282    *x*=2;
283 }
284
285 /////////////////////////
286 //
287 // print
288 // Prints a string at sx,sy.  No clipping!!!
289 //
290 /////////////////////////
291
292 void print (const char *str)
293 {
294   char ch;
295
296   while ((ch=*str++) != 0)
297     if (ch == '\n')
298     {
299       sy++;
300       sx=leftedge;
301     }
302     else if (ch == '\r')
303       sx=leftedge;
304     else
305       drawchar (sx++,sy,ch);
306 }
307 void fprint (const char huge *str)
308 {
309   char ch;
310
311   while ((ch=*str++) != 0)
312     if (ch == '\n')
313     {
314       sy++;
315       sx=leftedge;
316     }
317     else if (ch == '\r')
318       sx=leftedge;
319     else
320       drawchar (sx++,sy,ch);
321 }
322
323 ////////////////////////////////////////////////////////////////////
324 //
325 // print hex byte
326 //
327 ////////////////////////////////////////////////////////////////////
328 void printhexb(unsigned char value)
329 {
330  int loop;
331  char hexstr[16]="0123456789ABCDEF",str[2]="";
332
333  for (loop=0;loop<2;loop++)
334    {
335     str[0]=hexstr[(value>>(1-loop)*4)&15];
336     print(str);
337    }
338 }
339
340 ////////////////////////////////////////////////////////////////////
341 //
342 // print hex
343 //
344 ////////////////////////////////////////////////////////////////////
345 void printhex(unsigned value)
346 {
347  print("$");
348  printhexb(value>>8);
349  printhexb(value&0xff);
350 }
351
352
353 ////////////////////////////////////////////////////////////////////
354 //
355 // print int
356 //
357 ////////////////////////////////////////////////////////////////////
358 void printint(unsigned value)
359 {
360  char temp[10];
361
362  ultoa((unsigned long)value,temp,10);
363  print(temp);
364 }
365
366
367 ////////////////////////////////////////////////////////////////////
368 //
369 // print bin
370 //
371 ////////////////////////////////////////////////////////////////////
372 void printbin(unsigned value)
373 {
374  int loop;
375
376  print("%");
377  for (loop=0;loop<16;loop++)
378     if ((value>>15-loop)&1) print("1"); else print("0");
379 }
380
381
382 ////////////////////////////////////////////////////////////////////
383 //
384 // input unsigned
385 //
386 ////////////////////////////////////////////////////////////////////
387 unsigned inputint(int numchars)
388 {
389  char string[18]="",digit,hexstr[16]="0123456789ABCDEF";
390  unsigned value,loop,loop1;
391
392  if (!input(string,numchars))
393    return ESCOUT;
394
395  if (string[0]=='$')
396    {
397     int digits;
398
399     digits=strlen(string)-2;
400     if (digits<0) return 0;
401
402     for (value=0,loop1=0;loop1<=digits;loop1++)
403       {
404        digit=toupper(string[loop1+1]);
405        for (loop=0;loop<16;loop++)
406           if (digit==hexstr[loop])
407             {
408              value|=(loop<<(digits-loop1)*4);
409              break;
410             }
411       }
412    }
413  else if (string[0]=='%')
414    {
415     int digits;
416
417     digits=strlen(string)-2;
418     if (digits<0) return 0;
419
420     for (value=0,loop1=0;loop1<=digits;loop1++)
421       {
422        if (string[loop1+1]<'0' || string[loop1+1]>'1') return 0;
423        value|=(string[loop1+1]-'0')<<(digits-loop1);
424       }
425    }
426  else value=atoi(string);
427  return value;
428 }
429
430
431 ////////////////////////////////////////////////////////////////////
432 //
433 // line input routine
434 //
435 ////////////////////////////////////////////////////////////////////
436 int input(char *string,int max)
437 {
438  char key;
439  int count=0,loop;
440
441  do {
442      key=get()&0xff;
443      if ((key==127 || key==8)&&count>0)
444        {
445         count--;
446         drawchar(sx,sy,' ');
447         sx--;
448        }
449
450      if (key>=' ' && key<='z' && count<max)
451        {
452         *(string+count++)=key;
453         drawchar(sx++,sy,key);
454        }
455
456     } while (key!=27 && key!=13);
457
458  for (loop=count;loop<max;loop++) *(string+loop)=0;
459
460  while(keydown[1]);     // don't let ESC repeat
461
462  if (key==13)
463    {
464     while(keydown[0x1c]);
465     return 1;
466    }
467  return 0;
468 }
469
470 void bar (int xl, int yl, int xh, int yh, int ch)
471 {
472   int x,y;
473
474   for (y=yl;y<=yh;y++)
475     for (x=xl;x<=xh;x++)
476       drawchar (x,y,ch);
477 }
478
479 /////////////////////////
480 //
481 // get
482 // Flash a cursor at sx,sy and waits for a user bioskey
483 //
484 /////////////////////////
485
486 int get (void)
487 {
488  int cycle,key;
489
490  do
491  {
492    cycle = 9;
493    while (!(key = bioskey(1)) && cycle<11)
494    {
495      drawchar (sx,sy,cycle++);
496      WaitVBL (5);
497    }
498  } while (key == 0);
499  drawchar (sx,sy,' ');
500  return bioskey(0);             // take it out of the buffer
501 }
502
503
504 ////////////////////////////////////////////////////////////////////
505 //
506 // drawchar
507 //
508 ////////////////////////////////////////////////////////////////////
509 void drawchar(int x,int y,int chr)
510 {
511  switch(videomode)
512  {
513   case CGA: CGAcharout(x,y,chr); break;
514   case EGA1:
515   case EGA2: EGAcharout(x,y,chr,videomode); break;
516   case VGA: VGAcharout(x,y,chr);
517  }
518 }
519
520 ////////////////////////////////////////////////////////////////////
521 //
522 // Set a video mode
523 //
524 ////////////////////////////////////////////////////////////////////
525 void setvideo(video vid)
526 {
527  //
528  // create CGA font (if not already created)
529  //
530  if (vid==CGA && !CGAfont)
531    {
532     unsigned char huge *oldfont=MK_FP(FP_SEG(&TEDCHAR),FP_OFF(&TEDCHAR));
533     unsigned i,j,huge *newfont;
534
535     centerwindow(20,1);
536     print("Creating CGA font...");
537
538     MMAllocate(&CGAfont,2048);
539     newfont=MK_FP(CGAfont,0);
540
541     for(i=0;i<127;i++)
542       for(j=0;j<8;j++)
543         (unsigned)*(newfont+i*8+j)=doubled[*(oldfont+i*8+j)]; //color=|0xaaaa;
544    }
545  else
546  //
547  // OR create VGA font (if not already created)
548  //
549  if (vid==VGA && !VGAfont)
550    {
551     unsigned char huge *oldfont=MK_FP(FP_SEG(&TEDCHAR),FP_OFF(&TEDCHAR)),
552         huge *newfont;
553     unsigned i,j,k;
554     unsigned char bitbyte[2]={0,0xff}; // colors={0x7e,0x78};
555
556     centerwindow(20,1);
557     print("Creating VGA font...");
558
559     MMAllocate(&VGAfont,0x2000);
560     newfont=MK_FP(VGAfont,0);
561
562     for(i=0;i<128;i++)
563       for(j=0;j<8;j++)
564         for(k=0;k<8;k++)
565           *(newfont+i*64+j*8+k)=bitbyte[(*(oldfont+i*8+j)>>(7-k))&1];
566    }
567  //
568  // Now, change video modes!
569  //
570  switch(vid)
571  {
572   case TEXT: _AX=3; break;
573   case CGA:
574     screencenterx=19;
575     screencentery=11;
576     scrnbot=199;
577     scrnrgt=319;
578     _AX=4;
579     break;
580   case EGA1:
581     screencenterx=19;
582     screencentery=11;
583     scrnbot=199;
584     scrnrgt=319;
585     _AX=0x0d;
586     break;
587   case EGA2:
588     screencenterx=39;
589     screencentery=29;
590     scrnbot=479;
591     scrnrgt=638;
592     _AX=0x12;
593     break;
594   case VGA:
595     _AX=0x13;
596     screencenterx=19;
597     screencentery=11;
598     scrnbot=199;
599     scrnrgt=319;
600  }
601  geninterrupt(0x10);
602  videomode=vid;
603
604  //
605  // Set CGA mouse cursor (normal one sucks)
606  //
607  if (vid==CGA)
608    {
609     static unsigned CGAcursor[]=
610       {
611        0x0fff,0x03ff,0x00ff,0x003f,0x000f,0x0003,0x0000,0x000f,0x0c03,0x3c03,
612        0xff03,0xffff,0xffff,0xffff,0xffff,0xffff,
613
614        0xf000,0xcc00,0xc300,0xc0c0,0xc030,0xc00c,0xc03f,0xcc30,0xf30c,0xc30c,
615        0x00fc,0x0000,0x0000,0x0000,0x0000,0x0000
616       };
617
618     _BX=0;
619     _CX=0;
620     _DX=FP_OFF(CGAcursor);
621     _ES=_DS;
622     _AX=9;
623     geninterrupt(0x33);
624    }
625  else
626  //
627  // Move EGA font into LATCH memory!
628  //
629  if (vid==EGA1 || vid==EGA2)
630    {
631     unsigned i,s=FP_SEG(&TEDCHAR),o=FP_OFF(&TEDCHAR);
632
633     outport(GCindex,GCmode);
634     for (i=0;i<4;i++)
635       {
636        outport(SCindex,SCmapmask | (1<<i)*256);
637        movedata(s,o+i*0x400,0xaf00,0,0x400);
638       }
639    }
640  else
641  //
642  // OR set the VGA palette
643  //
644  if (vid==VGA)  // set VGA palette
645    {
646     _BX=0;
647     _CX=0x100;
648     _DX=FP_OFF(&VGAPAL);
649     _ES=FP_SEG(&VGAPAL);
650     _AX=0x1012;
651     geninterrupt(0x10);
652    }
653 }
654
655
656 ////////////////////////////////////////////////////////////////////
657 //
658 // Quit the fuck outta here!
659 //
660 ////////////////////////////////////////////////////////////////////
661 void Quit(char *string)
662 {
663  Unhook();
664  setvideo(TEXT);
665  poke(0,0x41a,peek(0,0x41c));   // clear keyboard
666  if (string[0])
667    {
668     printf("TED5 ERROR: %s",string);
669     exit(1);
670    }
671  printf("Thanks for using TED5!");
672  nosound();
673  exit(0);
674 }
675
676
677 //////////////////////////
678 //
679 // drawwindow
680 // draws a bordered window and homes the cursor
681 //
682 //////////////////////////
683
684 void drawwindow (int xl, int yl, int xh, int yh)
685 {
686  int x,y;
687  win_xl=xl;
688  win_yl=yl;
689  win_xh=xh;
690  win_yh=yh;             // so the window can be erased
691
692  drawchar (xl,yl,1);
693  for (x=xl+1;x<xh;x++)
694    drawchar (x,yl,2);
695  drawchar (xh,yl,3);
696  for (y=yl+1;y<yh;y++)
697  {
698    drawchar (xl,y,4);
699    for (x=xl+1;x<xh;x++)
700      drawchar (x,y,' ');
701    drawchar (xh,y,5);
702  }
703  drawchar (xl,yh,6);
704  for (x=xl+1;x<xh;x++)
705    drawchar (x,yh,7);
706  drawchar (xh,yh,8);
707
708  sx = leftedge = xl+1;
709  sy = yl+1;
710 }
711
712 ////////////////////////////
713 //
714 // erasewindow
715 // clears out the last window and it's border to spaces
716 //
717 ///////////////////////////
718
719 void erasewindow (void)
720 {
721   bar (win_xl,win_yl,win_xh,win_yh,' ');
722 }
723
724 /////////////////////////////
725 //
726 // centerwindow
727 // Centers a drawwindow of the given size
728 //
729 /////////////////////////////
730
731 void centerwindow (int width, int height)
732 {
733   int xl = screencenterx-width/2;
734   int yl = screencentery-height/2;
735
736   drawwindow (xl,yl,xl+width+1,yl+height+1);
737 }
738
739 ///////////////////////////////
740 //
741 // expwin {h / v}
742 // Grows the window outward
743 //
744 ///////////////////////////////
745 void expwinh (int width, int height)
746 {
747   if (width > 2)
748     expwinh (width-2,height);
749
750   WaitVBL (1);
751   centerwindow (width,height);
752 }
753
754 void expwinv (int width, int height)
755 {
756   if (height >2)
757     expwinv (width,height-2);
758
759   WaitVBL (1);
760   centerwindow (width,height);
761 }
762 void expwin (int width, int height)
763 {
764   if (width > 2)
765   {
766     if (height >2)
767       expwin (width-2,height-2);
768     else
769       expwinh (width-2,height);
770   }
771   else
772     if (height >2)
773       expwinv (width,height-2);
774
775   WaitVBL (1);
776   centerwindow (width,height);
777 }
778
779
780 ////////////////////////////////////////////////////////////
781 //
782 // Save a *LARGE* file from a FAR buffer!
783 // by John Romero (C) 1990 Gamer's Edge
784 //
785 ////////////////////////////////////////////////////////////
786 void SaveFile(char *filename,char huge *buffer,long offset,long size)
787 {
788  unsigned int handle,buf1,buf2,offlo,offhi,sizelo,sizehi;
789
790  buf1=FP_OFF(buffer);
791  buf2=FP_SEG(buffer);
792  offlo=offset&0xffff;
793  offhi=offset>>16;
794  sizelo=size&0xffff;
795  sizehi=size>>16;
796
797 asm             mov     ax,offlo
798 asm             or      ax,offhi
799 asm             jz      CREATEIT
800
801 asm             mov     dx,filename
802 asm             mov     ax,3d02h                // OPEN w/handle (read only)
803 asm             int     21h
804 asm             jnc     L0
805
806  return;
807
808 L0:
809
810 asm             mov     handle,ax
811
812 asm             mov     bx,handle
813 asm             mov     dx,offlo
814 asm             mov     cx,offhi
815 asm             mov     ax,4200h
816 asm             int     21h                     // SEEK (to file offset)
817 asm             jc      out
818
819 asm             jmp     DOSAVE
820
821 CREATEIT:
822
823 asm             mov     dx,filename
824 asm             mov     ax,3c00h                // CREATE w/handle (read only)
825 asm             xor     cx,cx
826 asm             int     21h
827 asm             jc      out
828
829 asm             mov     handle,ax
830
831 DOSAVE:
832
833 asm             cmp     WORD PTR sizehi,0               // larger than 1 segment?
834 asm             je      L2
835
836 L1:
837
838 asm             push    ds
839 asm             mov     bx,handle
840 asm             mov     cx,8000h
841 asm             mov     dx,buf1
842 asm             mov     ax,buf2
843 asm             mov     ds,ax
844 asm             mov     ah,40h                  // WRITE w/handle
845 asm             int     21h
846 asm             pop     ds
847
848 asm             add     WORD PTR buf2,800h              // bump ptr up 1/2 segment
849 asm             sub     WORD PTR sizelo,8000h           // done yet?
850 asm             sbb     WORD PTR sizehi,0
851 asm             cmp     WORD PTR sizehi,0
852 asm             ja      L1
853 asm             cmp     WORD PTR sizelo,8000h
854 asm             jae     L1
855
856 L2:
857
858 asm             push    ds
859 asm             mov     bx,handle
860 asm             mov     cx,sizelo
861 asm             mov     dx,buf1
862 asm             mov     ax,buf2
863 asm             mov     ds,ax
864 asm             mov     ah,40h                  // WRITE w/handle
865 asm             int     21h
866 asm             pop     ds
867
868 out:
869
870 asm             mov     bx,handle               // CLOSE w/handle
871 asm             mov     ah,3eh
872 asm             int     21h
873
874 }
875
876 ////////////////////////////////////////////////////////////
877 //
878 // Load a *LARGE* file into a FAR buffer!
879 // by John Romero (C) 1990 Gamer's Edge
880 //
881 ////////////////////////////////////////////////////////////
882 unsigned long LoadFile(char *filename,char huge *buffer,long offset,long size)
883 {
884  unsigned handle,flength1=0,flength2=0,buf1,buf2,len1,len2,
885           rsize1,rsize2,roffset1,roffset2;
886
887  rsize1=size&0xffff;
888  rsize2=size>>16;
889  roffset1=offset&0xffff;
890  roffset2=offset>>16;
891  buf1=FP_OFF(buffer);
892  buf2=FP_SEG(buffer);
893
894 asm             mov     dx,filename
895 asm             mov     ax,3d00h                // OPEN w/handle (read only)
896 asm             int     21h
897 asm             jnc     L_0
898
899  return 0;
900
901 L_0:
902
903 asm             mov     handle,ax
904 asm             mov     bx,ax
905 asm             xor     cx,cx
906 asm             xor     dx,dx
907 asm             mov     ax,4202h
908 asm             int     21h                     // SEEK (find file length)
909 asm             jc      out
910
911 asm             mov     flength1,ax
912 asm             mov     len1,ax
913 asm             mov     flength2,dx
914 asm             mov     len2,dx
915
916 asm             mov     ax,rsize1               // was a size specified?
917 asm             or      ax,rsize1
918 asm             jz      LOADALL
919
920 asm             mov     ax,rsize1               // only load size requested
921 asm             mov     len1,ax
922 asm             mov     ax,rsize2
923 asm             mov     len2,ax
924
925 LOADALL:
926
927 asm             mov     bx,handle
928 asm             mov     dx,roffset1
929 asm             mov     cx,roffset2
930 asm             mov     ax,4200h
931 asm             int     21h                     // SEEK (to file offset)
932 asm             jc      out
933
934 asm             cmp     WORD PTR len2,0                 // MULTI-SEGMENTAL?
935 asm             je      L_2
936
937 L_1:
938
939 asm             push    ds
940 asm             mov     bx,handle
941 asm             mov     cx,8000h                // read 32K chunks
942 asm             mov     dx,buf1
943 asm             mov     ax,buf2
944 asm             mov     ds,ax
945 asm             mov     ah,3fh                  // READ w/handle
946 asm             int     21h
947 asm             pop     ds
948 asm             jc      out
949
950 asm             add     WORD PTR buf2,800h
951 asm             sub     WORD PTR len1,8000h
952 asm             sbb     WORD PTR len2,0
953 asm             cmp     WORD PTR len2,0
954 asm             ja      L_1
955 asm             cmp     WORD PTR len1,8000h
956 asm             jae     L_1
957
958 L_2:
959
960 asm             push    ds
961 asm             mov     bx,handle
962 asm             mov     cx,len1
963 asm             mov     dx,buf1
964 asm             mov     ax,buf2
965 asm             mov     ds,ax
966 asm             mov     ah,3fh                  // READ w/handle
967 asm             int     21h
968 asm             pop     ds
969 asm             jmp     exit
970
971 out:
972
973 asm             mov     WORD PTR flength2,0
974 asm             mov     WORD PTR flength1,0
975
976 exit:
977
978 asm             mov     bx,handle               // CLOSE w/handle
979 asm             mov     ah,3eh
980 asm             int     21h
981
982  return (flength2*0x10000+flength1);
983
984 }
985
986
987 ////////////////////////////////////////////////////////////
988 //
989 // Allocate memory and load file in
990 //
991 ////////////////////////////////////////////////////////////
992 void LoadIn(char *filename,void _seg **baseptr)
993 {
994  char errstr[80];
995  int handle;
996  long len;
997
998  if ((handle=open(filename,O_BINARY))==-1)
999    {
1000     strcpy(errstr,"Error loading file ");
1001     strcat(errstr,filename);
1002     Quit(errstr);
1003    }
1004
1005  len=filelength(handle);
1006  close(handle);
1007  MMAllocate((memptr *)baseptr,len);
1008  LoadFile(filename,MK_FP(*baseptr,0),0,0);
1009 }
1010
1011