1012 lines
18 KiB
C++
1012 lines
18 KiB
C++
#include "ted5.h"
|
|
#pragma hdrstop
|
|
|
|
extern char far TEDCHAR,far VGAPAL;
|
|
|
|
void Quit(char *string);
|
|
void drawchar(int x,int y,int chr);
|
|
void centerwindow (int width, int height);
|
|
|
|
int win_xl,win_yl,win_xh,win_yh;
|
|
int screencenterx = 19,screencentery = 11;
|
|
unsigned char keydown[256];
|
|
unsigned leftedge,yshift,xormask,MouseStatus,sx,sy;
|
|
void interrupt (*oldint9) ()=NULL;
|
|
enum {false,true} boolean;
|
|
memptr CGAfont,VGAfont;
|
|
unsigned doubled[256];
|
|
//
|
|
// Special vars to handle EGA3 mouse mode
|
|
//
|
|
int EGA3mx,EGA3my;
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Return a file's length
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
long filelen(char *filename)
|
|
{
|
|
long size;
|
|
int handle;
|
|
|
|
if ((handle=open(filename,O_BINARY))==-1)
|
|
return 0;
|
|
|
|
size=filelength(handle);
|
|
close(handle);
|
|
return size;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// WaitVBL
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
void WaitVBL(int times)
|
|
{
|
|
asm mov cx,times
|
|
asm mov dx,crtcaddr
|
|
asm add dx,6
|
|
|
|
waitvbl1:
|
|
asm in al,dx
|
|
asm test al,00001000b //;look for vbl
|
|
asm jnz waitvbl1
|
|
|
|
waitvbl2:
|
|
asm in al,dx
|
|
asm test al,00001000b //;look for vbl
|
|
asm jz waitvbl2
|
|
|
|
asm loop waitvbl1
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Int9ISR
|
|
// Called for every keypress. Keeps track of which keys are down, and passes
|
|
// the key on to DOS after clearing the dos buffer (max 1 char in buffer).
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
void interrupt Int9ISR ()
|
|
{
|
|
int key = inportb (0x60); /* get the key pressed */
|
|
|
|
if (key>127)
|
|
keydown [key-128] = false; /* break scan code */
|
|
else
|
|
{
|
|
keydown [key] = true; /* make scan code */
|
|
poke (0x40,0x1c,peek(0x40,0x1a)); /* clear the bios key buffer */
|
|
}
|
|
asm {
|
|
push ax
|
|
push bx
|
|
push cx
|
|
push dx
|
|
push si
|
|
push di
|
|
push bp
|
|
}
|
|
oldint9 (); /* give it to DOS */
|
|
asm {
|
|
pop bp
|
|
pop di
|
|
pop si
|
|
pop dx
|
|
pop cx
|
|
pop bx
|
|
pop ax
|
|
}
|
|
outport (0x20,0x20); /* tell the int manager we got it */
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// SetupKBD
|
|
// Clears the keydown array and installs the INT 9 ISR if it isn't already
|
|
// hooked up.
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
void SetupKBD ()
|
|
{
|
|
void far *vect = getvect (9);
|
|
int i;
|
|
|
|
for (i=0;i<128;i++) /* clear our key down table */
|
|
keydown[i]= false;
|
|
|
|
poke (0x40,0x1c,peek(0x40,0x1a)); /* clear the bios key buffer */
|
|
|
|
if ( &Int9ISR != vect ) /* is our handler allready set up? */
|
|
{
|
|
oldint9 = vect;
|
|
setvect (9,Int9ISR);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ShutdownKBD
|
|
// Sets the int 9 vector back to oldint 9
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
void ShutdownKBD ()
|
|
{
|
|
if (oldint9 != NULL)
|
|
setvect (9,oldint9);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// clearkeys
|
|
// Clears out the bios buffer and zeros out the keydown array
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
void clearkeys (void)
|
|
{
|
|
int i;
|
|
while (bioskey (1))
|
|
bioskey(0);
|
|
|
|
for (i=0;i<128;i++)
|
|
keydown [i]=0;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Mouse Routines
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
int MouseInit(void)
|
|
{
|
|
union REGS regs;
|
|
unsigned char far *vector;
|
|
|
|
if ((vector=MK_FP(peek(0,0x33*4+2),peek(0,0x33*4)))==NULL) return 0;
|
|
|
|
if (*vector == 207)
|
|
return MouseStatus = 0;
|
|
|
|
_AX=0;
|
|
geninterrupt(0x33);
|
|
EGA3mx=800/2;
|
|
EGA3my=600/2;
|
|
|
|
//
|
|
// Set CGA mouse cursor (normal one sucks)
|
|
//
|
|
if (videomode==CGA)
|
|
{
|
|
static unsigned CGAcursor[]=
|
|
{
|
|
0x0fff,0x03ff,0x00ff,0x003f,0x000f,0x0003,0x0000,0x000f,0x0c03,0x3c03,
|
|
0xff03,0xffff,0xffff,0xffff,0xffff,0xffff,
|
|
|
|
0xf000,0xcc00,0xc300,0xc0c0,0xc030,0xc00c,0xc03f,0xcc30,0xf30c,0xc30c,
|
|
0x00fc,0x0000,0x0000,0x0000,0x0000,0x0000
|
|
};
|
|
|
|
_BX=0;
|
|
_CX=0;
|
|
_DX=FP_OFF(CGAcursor);
|
|
_ES=_DS;
|
|
_AX=9;
|
|
geninterrupt(0x33);
|
|
}
|
|
|
|
return MouseStatus = 1;
|
|
}
|
|
|
|
|
|
void MouseOrigin(int x,int y)
|
|
{
|
|
if (!MouseStatus) return;
|
|
|
|
_CX=x;
|
|
_DX=y;
|
|
_AX=4;
|
|
geninterrupt(0x33);
|
|
}
|
|
|
|
|
|
void MouseLimits(int xmin,int xmax,int ymin,int ymax)
|
|
{
|
|
if (!MouseStatus) return;
|
|
|
|
_CX=xmin;
|
|
_DX=xmax;
|
|
_AX=7;
|
|
geninterrupt(0x33);
|
|
_CX=ymin;
|
|
_DX=ymax;
|
|
_AX=8;
|
|
geninterrupt(0x33);
|
|
}
|
|
|
|
|
|
void MouseHide(void)
|
|
{
|
|
if (!MouseStatus) return;
|
|
|
|
_AX=2;
|
|
geninterrupt(0x33);
|
|
}
|
|
|
|
|
|
|
|
void MouseShow(void)
|
|
{
|
|
if (!MouseStatus) return;
|
|
|
|
_AX=1;
|
|
geninterrupt(0x33);
|
|
}
|
|
|
|
|
|
|
|
int MouseButton(void)
|
|
{
|
|
union REGS regs;
|
|
|
|
if (!MouseStatus) return 0;
|
|
|
|
regs.x.ax=3;
|
|
int86(0x33,®s,®s);
|
|
return(regs.x.bx);
|
|
}
|
|
|
|
|
|
|
|
void MouseCoords(int *x,int *y)
|
|
{
|
|
union REGS regs;
|
|
|
|
if (!MouseStatus)
|
|
return;
|
|
|
|
regs.x.ax=3;
|
|
int86(0x33,®s,®s);
|
|
*x=regs.x.cx;
|
|
*y=regs.x.dx;
|
|
|
|
*x/=2;
|
|
if (videomode==EGA2)
|
|
*x*=2;
|
|
}
|
|
|
|
/////////////////////////
|
|
//
|
|
// print
|
|
// Prints a string at sx,sy. No clipping!!!
|
|
//
|
|
/////////////////////////
|
|
|
|
void print (const char *str)
|
|
{
|
|
char ch;
|
|
|
|
while ((ch=*str++) != 0)
|
|
if (ch == '\n')
|
|
{
|
|
sy++;
|
|
sx=leftedge;
|
|
}
|
|
else if (ch == '\r')
|
|
sx=leftedge;
|
|
else
|
|
drawchar (sx++,sy,ch);
|
|
}
|
|
void fprint (const char huge *str)
|
|
{
|
|
char ch;
|
|
|
|
while ((ch=*str++) != 0)
|
|
if (ch == '\n')
|
|
{
|
|
sy++;
|
|
sx=leftedge;
|
|
}
|
|
else if (ch == '\r')
|
|
sx=leftedge;
|
|
else
|
|
drawchar (sx++,sy,ch);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// print hex byte
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
void printhexb(unsigned char value)
|
|
{
|
|
int loop;
|
|
char hexstr[16]="0123456789ABCDEF",str[2]="";
|
|
|
|
for (loop=0;loop<2;loop++)
|
|
{
|
|
str[0]=hexstr[(value>>(1-loop)*4)&15];
|
|
print(str);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// print hex
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
void printhex(unsigned value)
|
|
{
|
|
print("$");
|
|
printhexb(value>>8);
|
|
printhexb(value&0xff);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// print int
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
void printint(unsigned value)
|
|
{
|
|
char temp[10];
|
|
|
|
ultoa((unsigned long)value,temp,10);
|
|
print(temp);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// print bin
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
void printbin(unsigned value)
|
|
{
|
|
int loop;
|
|
|
|
print("%");
|
|
for (loop=0;loop<16;loop++)
|
|
if ((value>>15-loop)&1) print("1"); else print("0");
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// input unsigned
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
unsigned inputint(int numchars)
|
|
{
|
|
char string[18]="",digit,hexstr[16]="0123456789ABCDEF";
|
|
unsigned value,loop,loop1;
|
|
|
|
if (!input(string,numchars))
|
|
return ESCOUT;
|
|
|
|
if (string[0]=='$')
|
|
{
|
|
int digits;
|
|
|
|
digits=strlen(string)-2;
|
|
if (digits<0) return 0;
|
|
|
|
for (value=0,loop1=0;loop1<=digits;loop1++)
|
|
{
|
|
digit=toupper(string[loop1+1]);
|
|
for (loop=0;loop<16;loop++)
|
|
if (digit==hexstr[loop])
|
|
{
|
|
value|=(loop<<(digits-loop1)*4);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (string[0]=='%')
|
|
{
|
|
int digits;
|
|
|
|
digits=strlen(string)-2;
|
|
if (digits<0) return 0;
|
|
|
|
for (value=0,loop1=0;loop1<=digits;loop1++)
|
|
{
|
|
if (string[loop1+1]<'0' || string[loop1+1]>'1') return 0;
|
|
value|=(string[loop1+1]-'0')<<(digits-loop1);
|
|
}
|
|
}
|
|
else value=atoi(string);
|
|
return value;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// line input routine
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
int input(char *string,int max)
|
|
{
|
|
char key;
|
|
int count=0,loop;
|
|
|
|
do {
|
|
key=get()&0xff;
|
|
if ((key==127 || key==8)&&count>0)
|
|
{
|
|
count--;
|
|
drawchar(sx,sy,' ');
|
|
sx--;
|
|
}
|
|
|
|
if (key>=' ' && key<='z' && count<max)
|
|
{
|
|
*(string+count++)=key;
|
|
drawchar(sx++,sy,key);
|
|
}
|
|
|
|
} while (key!=27 && key!=13);
|
|
|
|
for (loop=count;loop<max;loop++) *(string+loop)=0;
|
|
|
|
while(keydown[1]); // don't let ESC repeat
|
|
|
|
if (key==13)
|
|
{
|
|
while(keydown[0x1c]);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void bar (int xl, int yl, int xh, int yh, int ch)
|
|
{
|
|
int x,y;
|
|
|
|
for (y=yl;y<=yh;y++)
|
|
for (x=xl;x<=xh;x++)
|
|
drawchar (x,y,ch);
|
|
}
|
|
|
|
/////////////////////////
|
|
//
|
|
// get
|
|
// Flash a cursor at sx,sy and waits for a user bioskey
|
|
//
|
|
/////////////////////////
|
|
|
|
int get (void)
|
|
{
|
|
int cycle,key;
|
|
|
|
do
|
|
{
|
|
cycle = 9;
|
|
while (!(key = bioskey(1)) && cycle<11)
|
|
{
|
|
drawchar (sx,sy,cycle++);
|
|
WaitVBL (5);
|
|
}
|
|
} while (key == 0);
|
|
drawchar (sx,sy,' ');
|
|
return bioskey(0); // take it out of the buffer
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// drawchar
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
void drawchar(int x,int y,int chr)
|
|
{
|
|
switch(videomode)
|
|
{
|
|
case CGA: CGAcharout(x,y,chr); break;
|
|
case EGA1:
|
|
case EGA2: EGAcharout(x,y,chr,videomode); break;
|
|
case VGA: VGAcharout(x,y,chr);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Set a video mode
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
void setvideo(video vid)
|
|
{
|
|
//
|
|
// create CGA font (if not already created)
|
|
//
|
|
if (vid==CGA && !CGAfont)
|
|
{
|
|
unsigned char huge *oldfont=MK_FP(FP_SEG(&TEDCHAR),FP_OFF(&TEDCHAR));
|
|
unsigned i,j,huge *newfont;
|
|
|
|
centerwindow(20,1);
|
|
print("Creating CGA font...");
|
|
|
|
MMAllocate(&CGAfont,2048);
|
|
newfont=MK_FP(CGAfont,0);
|
|
|
|
for(i=0;i<127;i++)
|
|
for(j=0;j<8;j++)
|
|
(unsigned)*(newfont+i*8+j)=doubled[*(oldfont+i*8+j)]; //color=|0xaaaa;
|
|
}
|
|
else
|
|
//
|
|
// OR create VGA font (if not already created)
|
|
//
|
|
if (vid==VGA && !VGAfont)
|
|
{
|
|
unsigned char huge *oldfont=MK_FP(FP_SEG(&TEDCHAR),FP_OFF(&TEDCHAR)),
|
|
huge *newfont;
|
|
unsigned i,j,k;
|
|
unsigned char bitbyte[2]={0,0xff}; // colors={0x7e,0x78};
|
|
|
|
centerwindow(20,1);
|
|
print("Creating VGA font...");
|
|
|
|
MMAllocate(&VGAfont,0x2000);
|
|
newfont=MK_FP(VGAfont,0);
|
|
|
|
for(i=0;i<128;i++)
|
|
for(j=0;j<8;j++)
|
|
for(k=0;k<8;k++)
|
|
*(newfont+i*64+j*8+k)=bitbyte[(*(oldfont+i*8+j)>>(7-k))&1];
|
|
}
|
|
//
|
|
// Now, change video modes!
|
|
//
|
|
switch(vid)
|
|
{
|
|
case TEXT: _AX=3; break;
|
|
case CGA:
|
|
screencenterx=19;
|
|
screencentery=11;
|
|
scrnbot=199;
|
|
scrnrgt=319;
|
|
_AX=4;
|
|
break;
|
|
case EGA1:
|
|
screencenterx=19;
|
|
screencentery=11;
|
|
scrnbot=199;
|
|
scrnrgt=319;
|
|
_AX=0x0d;
|
|
break;
|
|
case EGA2:
|
|
screencenterx=39;
|
|
screencentery=29;
|
|
scrnbot=479;
|
|
scrnrgt=638;
|
|
_AX=0x12;
|
|
break;
|
|
case VGA:
|
|
_AX=0x13;
|
|
screencenterx=19;
|
|
screencentery=11;
|
|
scrnbot=199;
|
|
scrnrgt=319;
|
|
}
|
|
geninterrupt(0x10);
|
|
videomode=vid;
|
|
|
|
//
|
|
// Set CGA mouse cursor (normal one sucks)
|
|
//
|
|
if (vid==CGA)
|
|
{
|
|
static unsigned CGAcursor[]=
|
|
{
|
|
0x0fff,0x03ff,0x00ff,0x003f,0x000f,0x0003,0x0000,0x000f,0x0c03,0x3c03,
|
|
0xff03,0xffff,0xffff,0xffff,0xffff,0xffff,
|
|
|
|
0xf000,0xcc00,0xc300,0xc0c0,0xc030,0xc00c,0xc03f,0xcc30,0xf30c,0xc30c,
|
|
0x00fc,0x0000,0x0000,0x0000,0x0000,0x0000
|
|
};
|
|
|
|
_BX=0;
|
|
_CX=0;
|
|
_DX=FP_OFF(CGAcursor);
|
|
_ES=_DS;
|
|
_AX=9;
|
|
geninterrupt(0x33);
|
|
}
|
|
else
|
|
//
|
|
// Move EGA font into LATCH memory!
|
|
//
|
|
if (vid==EGA1 || vid==EGA2)
|
|
{
|
|
unsigned i,s=FP_SEG(&TEDCHAR),o=FP_OFF(&TEDCHAR);
|
|
|
|
outport(GCindex,GCmode);
|
|
for (i=0;i<4;i++)
|
|
{
|
|
outport(SCindex,SCmapmask | (1<<i)*256);
|
|
movedata(s,o+i*0x400,0xaf00,0,0x400);
|
|
}
|
|
}
|
|
else
|
|
//
|
|
// OR set the VGA palette
|
|
//
|
|
if (vid==VGA) // set VGA palette
|
|
{
|
|
_BX=0;
|
|
_CX=0x100;
|
|
_DX=FP_OFF(&VGAPAL);
|
|
_ES=FP_SEG(&VGAPAL);
|
|
_AX=0x1012;
|
|
geninterrupt(0x10);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Quit the fuck outta here!
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
void Quit(char *string)
|
|
{
|
|
Unhook();
|
|
setvideo(TEXT);
|
|
poke(0,0x41a,peek(0,0x41c)); // clear keyboard
|
|
if (string[0])
|
|
{
|
|
printf("TED5 ERROR: %s",string);
|
|
exit(1);
|
|
}
|
|
printf("Thanks for using TED5!");
|
|
nosound();
|
|
exit(0);
|
|
}
|
|
|
|
|
|
//////////////////////////
|
|
//
|
|
// drawwindow
|
|
// draws a bordered window and homes the cursor
|
|
//
|
|
//////////////////////////
|
|
|
|
void drawwindow (int xl, int yl, int xh, int yh)
|
|
{
|
|
int x,y;
|
|
win_xl=xl;
|
|
win_yl=yl;
|
|
win_xh=xh;
|
|
win_yh=yh; // so the window can be erased
|
|
|
|
drawchar (xl,yl,1);
|
|
for (x=xl+1;x<xh;x++)
|
|
drawchar (x,yl,2);
|
|
drawchar (xh,yl,3);
|
|
for (y=yl+1;y<yh;y++)
|
|
{
|
|
drawchar (xl,y,4);
|
|
for (x=xl+1;x<xh;x++)
|
|
drawchar (x,y,' ');
|
|
drawchar (xh,y,5);
|
|
}
|
|
drawchar (xl,yh,6);
|
|
for (x=xl+1;x<xh;x++)
|
|
drawchar (x,yh,7);
|
|
drawchar (xh,yh,8);
|
|
|
|
sx = leftedge = xl+1;
|
|
sy = yl+1;
|
|
}
|
|
|
|
////////////////////////////
|
|
//
|
|
// erasewindow
|
|
// clears out the last window and it's border to spaces
|
|
//
|
|
///////////////////////////
|
|
|
|
void erasewindow (void)
|
|
{
|
|
bar (win_xl,win_yl,win_xh,win_yh,' ');
|
|
}
|
|
|
|
/////////////////////////////
|
|
//
|
|
// centerwindow
|
|
// Centers a drawwindow of the given size
|
|
//
|
|
/////////////////////////////
|
|
|
|
void centerwindow (int width, int height)
|
|
{
|
|
int xl = screencenterx-width/2;
|
|
int yl = screencentery-height/2;
|
|
|
|
drawwindow (xl,yl,xl+width+1,yl+height+1);
|
|
}
|
|
|
|
///////////////////////////////
|
|
//
|
|
// expwin {h / v}
|
|
// Grows the window outward
|
|
//
|
|
///////////////////////////////
|
|
void expwinh (int width, int height)
|
|
{
|
|
if (width > 2)
|
|
expwinh (width-2,height);
|
|
|
|
WaitVBL (1);
|
|
centerwindow (width,height);
|
|
}
|
|
|
|
void expwinv (int width, int height)
|
|
{
|
|
if (height >2)
|
|
expwinv (width,height-2);
|
|
|
|
WaitVBL (1);
|
|
centerwindow (width,height);
|
|
}
|
|
void expwin (int width, int height)
|
|
{
|
|
if (width > 2)
|
|
{
|
|
if (height >2)
|
|
expwin (width-2,height-2);
|
|
else
|
|
expwinh (width-2,height);
|
|
}
|
|
else
|
|
if (height >2)
|
|
expwinv (width,height-2);
|
|
|
|
WaitVBL (1);
|
|
centerwindow (width,height);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//
|
|
// Save a *LARGE* file from a FAR buffer!
|
|
// by John Romero (C) 1990 Gamer's Edge
|
|
//
|
|
////////////////////////////////////////////////////////////
|
|
void SaveFile(char *filename,char huge *buffer,long offset,long size)
|
|
{
|
|
unsigned int handle,buf1,buf2,offlo,offhi,sizelo,sizehi;
|
|
|
|
buf1=FP_OFF(buffer);
|
|
buf2=FP_SEG(buffer);
|
|
offlo=offset&0xffff;
|
|
offhi=offset>>16;
|
|
sizelo=size&0xffff;
|
|
sizehi=size>>16;
|
|
|
|
asm mov ax,offlo
|
|
asm or ax,offhi
|
|
asm jz CREATEIT
|
|
|
|
asm mov dx,filename
|
|
asm mov ax,3d02h // OPEN w/handle (read only)
|
|
asm int 21h
|
|
asm jnc L0
|
|
|
|
return;
|
|
|
|
L0:
|
|
|
|
asm mov handle,ax
|
|
|
|
asm mov bx,handle
|
|
asm mov dx,offlo
|
|
asm mov cx,offhi
|
|
asm mov ax,4200h
|
|
asm int 21h // SEEK (to file offset)
|
|
asm jc out
|
|
|
|
asm jmp DOSAVE
|
|
|
|
CREATEIT:
|
|
|
|
asm mov dx,filename
|
|
asm mov ax,3c00h // CREATE w/handle (read only)
|
|
asm xor cx,cx
|
|
asm int 21h
|
|
asm jc out
|
|
|
|
asm mov handle,ax
|
|
|
|
DOSAVE:
|
|
|
|
asm cmp WORD PTR sizehi,0 // larger than 1 segment?
|
|
asm je L2
|
|
|
|
L1:
|
|
|
|
asm push ds
|
|
asm mov bx,handle
|
|
asm mov cx,8000h
|
|
asm mov dx,buf1
|
|
asm mov ax,buf2
|
|
asm mov ds,ax
|
|
asm mov ah,40h // WRITE w/handle
|
|
asm int 21h
|
|
asm pop ds
|
|
|
|
asm add WORD PTR buf2,800h // bump ptr up 1/2 segment
|
|
asm sub WORD PTR sizelo,8000h // done yet?
|
|
asm sbb WORD PTR sizehi,0
|
|
asm cmp WORD PTR sizehi,0
|
|
asm ja L1
|
|
asm cmp WORD PTR sizelo,8000h
|
|
asm jae L1
|
|
|
|
L2:
|
|
|
|
asm push ds
|
|
asm mov bx,handle
|
|
asm mov cx,sizelo
|
|
asm mov dx,buf1
|
|
asm mov ax,buf2
|
|
asm mov ds,ax
|
|
asm mov ah,40h // WRITE w/handle
|
|
asm int 21h
|
|
asm pop ds
|
|
|
|
out:
|
|
|
|
asm mov bx,handle // CLOSE w/handle
|
|
asm mov ah,3eh
|
|
asm int 21h
|
|
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//
|
|
// Load a *LARGE* file into a FAR buffer!
|
|
// by John Romero (C) 1990 Gamer's Edge
|
|
//
|
|
////////////////////////////////////////////////////////////
|
|
unsigned long LoadFile(char *filename,char huge *buffer,long offset,long size)
|
|
{
|
|
unsigned handle,flength1=0,flength2=0,buf1,buf2,len1,len2,
|
|
rsize1,rsize2,roffset1,roffset2;
|
|
|
|
rsize1=size&0xffff;
|
|
rsize2=size>>16;
|
|
roffset1=offset&0xffff;
|
|
roffset2=offset>>16;
|
|
buf1=FP_OFF(buffer);
|
|
buf2=FP_SEG(buffer);
|
|
|
|
asm mov dx,filename
|
|
asm mov ax,3d00h // OPEN w/handle (read only)
|
|
asm int 21h
|
|
asm jnc L_0
|
|
|
|
return 0;
|
|
|
|
L_0:
|
|
|
|
asm mov handle,ax
|
|
asm mov bx,ax
|
|
asm xor cx,cx
|
|
asm xor dx,dx
|
|
asm mov ax,4202h
|
|
asm int 21h // SEEK (find file length)
|
|
asm jc out
|
|
|
|
asm mov flength1,ax
|
|
asm mov len1,ax
|
|
asm mov flength2,dx
|
|
asm mov len2,dx
|
|
|
|
asm mov ax,rsize1 // was a size specified?
|
|
asm or ax,rsize1
|
|
asm jz LOADALL
|
|
|
|
asm mov ax,rsize1 // only load size requested
|
|
asm mov len1,ax
|
|
asm mov ax,rsize2
|
|
asm mov len2,ax
|
|
|
|
LOADALL:
|
|
|
|
asm mov bx,handle
|
|
asm mov dx,roffset1
|
|
asm mov cx,roffset2
|
|
asm mov ax,4200h
|
|
asm int 21h // SEEK (to file offset)
|
|
asm jc out
|
|
|
|
asm cmp WORD PTR len2,0 // MULTI-SEGMENTAL?
|
|
asm je L_2
|
|
|
|
L_1:
|
|
|
|
asm push ds
|
|
asm mov bx,handle
|
|
asm mov cx,8000h // read 32K chunks
|
|
asm mov dx,buf1
|
|
asm mov ax,buf2
|
|
asm mov ds,ax
|
|
asm mov ah,3fh // READ w/handle
|
|
asm int 21h
|
|
asm pop ds
|
|
asm jc out
|
|
|
|
asm add WORD PTR buf2,800h
|
|
asm sub WORD PTR len1,8000h
|
|
asm sbb WORD PTR len2,0
|
|
asm cmp WORD PTR len2,0
|
|
asm ja L_1
|
|
asm cmp WORD PTR len1,8000h
|
|
asm jae L_1
|
|
|
|
L_2:
|
|
|
|
asm push ds
|
|
asm mov bx,handle
|
|
asm mov cx,len1
|
|
asm mov dx,buf1
|
|
asm mov ax,buf2
|
|
asm mov ds,ax
|
|
asm mov ah,3fh // READ w/handle
|
|
asm int 21h
|
|
asm pop ds
|
|
asm jmp exit
|
|
|
|
out:
|
|
|
|
asm mov WORD PTR flength2,0
|
|
asm mov WORD PTR flength1,0
|
|
|
|
exit:
|
|
|
|
asm mov bx,handle // CLOSE w/handle
|
|
asm mov ah,3eh
|
|
asm int 21h
|
|
|
|
return (flength2*0x10000+flength1);
|
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////
|
|
//
|
|
// Allocate memory and load file in
|
|
//
|
|
////////////////////////////////////////////////////////////
|
|
void LoadIn(char *filename,void _seg **baseptr)
|
|
{
|
|
char errstr[80];
|
|
int handle;
|
|
long len;
|
|
|
|
if ((handle=open(filename,O_BINARY))==-1)
|
|
{
|
|
strcpy(errstr,"Error loading file ");
|
|
strcat(errstr,filename);
|
|
Quit(errstr);
|
|
}
|
|
|
|
len=filelength(handle);
|
|
close(handle);
|
|
MMAllocate((memptr *)baseptr,len);
|
|
LoadFile(filename,MK_FP(*baseptr,0),0,0);
|
|
}
|
|
|
|
|