duke3d/buildengine/dos_drvr.c

952 lines
23 KiB
C
Executable File

// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
// Ken Silverman's official web site: "http://www.advsys.net/ken"
// See the included license file "BUILDLIC.TXT" for license info.
// This file has been modified from Ken Silverman's original release
// (Actually, most of it was moved here from original BUILD source.)
#ifndef PLATFORM_DOS
#error Please do not compile this if PLATFORM_DOS is not defined.
#endif
// !!! check these includes against original engine.c !!!
#include <string.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include "pragmas.h"
#include <io.h>
#include <conio.h>
#include <i86.h>
#include <dos.h>
#include "platform.h"
#include "display.h"
#include "build.h"
#include "cache1d.h"
#include "ves2.h"
#include "engine.h"
static unsigned char tempbuf[MAXWALLS];
extern long transarea;
extern long totalarea;
extern long beforedrawrooms;
extern long stereowidth, stereopixelwidth, ostereopixelwidth;
extern volatile long stereomode, visualpage, activepage, whiteband, blackband;
extern volatile char oa1, o3c2, ortca, ortcb, overtbits, laststereoint;
extern char pow2char[8];
extern long pow2long[32];
extern char kensmessage[128];
static short capturecount = 0;
static char screenalloctype = 255;
static char pcxheader[128] =
{
0xa,0x5,0x1,0x8,0x0,0x0,0x0,0x0,0x3f,0x1,0xc7,0x0,
0x40,0x1,0xc8,0x0,0x0,0x0,0x0,0x8,0x8,0x8,0x10,0x10,
0x10,0x18,0x18,0x18,0x20,0x20,0x20,0x28,0x28,0x28,0x30,0x30,
0x30,0x38,0x38,0x38,0x40,0x40,0x40,0x48,0x48,0x48,0x50,0x50,
0x50,0x58,0x58,0x58,0x60,0x60,0x60,0x68,0x68,0x68,0x70,0x70,
0x70,0x78,0x78,0x78,0x0,0x1,0x40,0x1,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
};
static char vgapal16[48] =
{
00,00,00,00,00,42,00,42,00,00,42,42,42,00,00,42,00,42,42,21,00,42,42,42,
21,21,21,21,21,63,21,63,21,21,63,63,63,21,21,63,21,63,63,63,21,63,63,63,
};
static void (__interrupt __far *oldtimerhandler)(void);
static void (__interrupt __far *oldkeyhandler)(void);
extern long setvlinebpl(long);
#pragma aux setvlinebpl parm [eax];
void *kkmalloc(size_t size);
#pragma aux kkmalloc =\
"call kmalloc",\
parm [eax]\
void kkfree(void *buffer);
#pragma aux kkfree =\
"call kfree",\
parm [eax]\
unsigned char _readlastkeyhit(void)
{
return(kinp(0x60));
} // _readlastkeyhit
void _uninitengine(void)
{
long i;
if (vidoption == 1) uninitvesa();
if (stereomode) setstereo(0L);
if (screen != NULL)
{
if (screenalloctype == 0) kkfree((void *)screen);
//if (screenalloctype == 1) suckcache(screen); //Cache already gone
screen = NULL;
}
for(i=0;i<MAXPALOOKUPS;i++)
if (palookup[i] != NULL) { kkfree(palookup[i]); palookup[i] = NULL; }
}
long readpixel16(long p)
{
long mask, dat;
mask = pow2long[(p&7)^7];
if ((qsetmode == 480) && (ydim16 <= 336) && (p >= 640*336))
p -= 640*336;
else
p += pageoffset;
p >>= 3;
koutp(0x3ce,0x4);
koutp(0x3cf,0); dat = ((readpixel(p+0xa0000)&mask)>0);
koutp(0x3cf,1); dat += (((readpixel(p+0xa0000)&mask)>0)<<1);
koutp(0x3cf,2); dat += (((readpixel(p+0xa0000)&mask)>0)<<2);
koutp(0x3cf,3); dat += (((readpixel(p+0xa0000)&mask)>0)<<3);
return(dat);
}
int screencapture(char *filename, char inverseit)
{
char *ptr;
long fil, i, bufplc, p, col, ncol, leng, numbytes, xres;
filename[4] = ((capturecount/1000)%10)+48;
filename[5] = ((capturecount/100)%10)+48;
filename[6] = ((capturecount/10)%10)+48;
filename[7] = (capturecount%10)+48;
if ((fil=open(filename,O_BINARY|O_CREAT|O_TRUNC|O_WRONLY,S_IWRITE))==-1)
return(-1);
if (qsetmode == 200)
{
pcxheader[8] = ((xdim-1)&255); pcxheader[9] = (((xdim-1)>>8)&255);
pcxheader[10] = ((ydim-1)&255); pcxheader[11] = (((ydim-1)>>8)&255);
pcxheader[12] = (xdim&255); pcxheader[13] = ((xdim>>8)&255);
pcxheader[14] = (ydim&255); pcxheader[15] = ((ydim>>8)&255);
pcxheader[66] = (xdim&255); pcxheader[67] = ((xdim>>8)&255);
}
else
{
pcxheader[8] = ((640-1)&255); pcxheader[9] = (((640-1)>>8)&255);
pcxheader[10] = ((qsetmode-1)&255); pcxheader[11] = (((qsetmode-1)>>8)&255);
pcxheader[12] = (640&255); pcxheader[13] = ((640>>8)&255);
pcxheader[14] = (qsetmode&255); pcxheader[15] = ((qsetmode>>8)&255);
pcxheader[66] = (640&255); pcxheader[67] = ((640>>8)&255);
}
write(fil,&pcxheader[0],128);
if (qsetmode == 200)
{
ptr = (char *)frameplace;
numbytes = xdim*ydim;
xres = xdim;
}
else
{
numbytes = (mul5(qsetmode)<<7);
xres = 640;
}
bufplc = 0; p = 0;
while (p < numbytes)
{
koutp(97,kinp(97)|3);
if (qsetmode == 200) { col = *ptr; p++; ptr++; }
else
{
col = readpixel16(p);
p++;
if ((inverseit == 1) && (((col&7) == 0) || ((col&7) == 7))) col ^= 15;
}
leng = 1;
if (qsetmode == 200) ncol = *ptr;
else
{
ncol = readpixel16(p);
if ((inverseit == 1) && (((ncol&7) == 0) || ((ncol&7) == 7))) ncol ^= 15;
}
while ((ncol == col) && (p < numbytes) && (leng < 63) && ((p%xres) != 0))
{
leng++;
if (qsetmode == 200) { p++; ptr++; ncol = *ptr; }
else
{
p++;
ncol = readpixel16(p);
if ((inverseit == 1) && (((ncol&7) == 0) || ((ncol&7) == 7))) ncol ^= 15;
}
}
koutp(97,kinp(97)&252);
if ((leng > 1) || (col >= 0xc0))
{
tempbuf[bufplc++] = (leng|0xc0);
if (bufplc == 4096) { bufplc = 0; if (write(fil,&tempbuf[0],4096) < 4096) { close(fil); return(-1); } }
}
tempbuf[bufplc++] = col;
if (bufplc == 4096) { bufplc = 0; if (write(fil,&tempbuf[0],4096) < 4096) { close(fil); return(-1); } }
}
tempbuf[bufplc++] = 0xc;
if (bufplc == 4096) { bufplc = 0; if (write(fil,&tempbuf[0],4096) < 4096) { close(fil); return(-1); } }
if (qsetmode == 200)
{
VBE_getPalette(0,256,&tempbuf[4096]);
for(i=0;i<256;i++)
{
tempbuf[bufplc++] = (tempbuf[(i<<2)+4096+2]<<2);
if (bufplc == 4096) { bufplc = 0; if (write(fil,&tempbuf[0],4096) < 4096) { close(fil); return(-1); } }
tempbuf[bufplc++] = (tempbuf[(i<<2)+4096+1]<<2);
if (bufplc == 4096) { bufplc = 0; if (write(fil,&tempbuf[0],4096) < 4096) { close(fil); return(-1); } }
tempbuf[bufplc++] = (tempbuf[(i<<2)+4096+0]<<2);
if (bufplc == 4096) { bufplc = 0; if (write(fil,&tempbuf[0],4096) < 4096) { close(fil); return(-1); } }
}
}
else
{
for(i=0;i<768;i++)
{
if (i < 48)
tempbuf[bufplc++] = (vgapal16[i]<<2);
else
tempbuf[bufplc++] = 0;
if (bufplc == 4096) { bufplc = 0; if (write(fil,&tempbuf[0],4096) < 4096) { close(fil); return(-1); } }
}
}
if (bufplc > 0)
if (write(fil,&tempbuf[0],bufplc) < bufplc) { close(fil); return(-1); }
close(fil);
capturecount++;
return(0);
}
void printscreeninterrupt(void)
{
int5();
}
void drawline16(long x1, long y1, long x2, long y2, char col)
{
long i, dx, dy, p, pinc, d;
char lmask, rmask;
dx = x2-x1; dy = y2-y1;
if (dx >= 0)
{
if ((x1 > 639) || (x2 < 0)) return;
if (x1 < 0) { if (dy) y1 += scale(0-x1,dy,dx); x1 = 0; }
if (x2 > 639) { if (dy) y2 += scale(639-x2,dy,dx); x2 = 639; }
}
else
{
if ((x2 > 639) || (x1 < 0)) return;
if (x2 < 0) { if (dy) y2 += scale(0-x2,dy,dx); x2 = 0; }
if (x1 > 639) { if (dy) y1 += scale(639-x1,dy,dx); x1 = 639; }
}
if (dy >= 0)
{
if ((y1 >= ydim16) || (y2 < 0)) return;
if (y1 < 0) { if (dx) x1 += scale(0-y1,dx,dy); y1 = 0; }
if (y2 >= ydim16) { if (dx) x2 += scale(ydim16-1-y2,dx,dy); y2 = ydim16-1; }
}
else
{
if ((y2 >= ydim16) || (y1 < 0)) return;
if (y2 < 0) { if (dx) x2 += scale(0-y2,dx,dy); y2 = 0; }
if (y1 >= ydim16) { if (dx) x1 += scale(ydim16-1-y1,dx,dy); y1 = ydim16-1; }
}
setcolor16((long)col);
if (x1 == x2)
{
if (y2 < y1) i = y1, y1 = y2, y2 = i;
koutpw(0x3ce,0x8+(256<<((x1&7)^7))); //bit mask
vlin16((((mul5(y1)<<7)+x1+pageoffset)>>3)+0xa0000,y2-y1+1);
return;
}
if (y1 == y2)
{
if (x2 < x1) i = x1, x1 = x2, x2 = i;
lmask = (0x00ff>>(x1&7));
rmask = (0xff80>>(x2&7));
p = (((mul5(y1)<<7)+x1+pageoffset)>>3)+0xa0000;
dx = (x2>>3)-(x1>>3);
if (dx == 0)
{
koutpw(0x3ce,0x8+((lmask&rmask)<<8)); drawpixel(p,readpixel(p));
return;
}
dx--;
koutpw(0x3ce,0x8+(lmask<<8)); drawpixel(p,readpixel(p)); p++;
if (dx > 0) { koutp(0x3cf,0xff); clearbufbyte((void *)p,dx,0L); p += dx; }
koutp(0x3cf,rmask); drawpixel(p,readpixel(p));
return;
}
dx = klabs(x2-x1)+1; dy = klabs(y2-y1)+1;
if (dx >= dy)
{
if (x2 < x1)
{
i = x1; x1 = x2; x2 = i;
i = y1; y1 = y2; y2 = i;
}
p = (mul5(y1)<<7)+x1+pageoffset;
d = 0;
if (y2 > y1) pinc = 640; else pinc = -640;
for(i=dx;i>0;i--)
{
drawpixel16(p);
d += dy;
if (d >= dx) { d -= dx; p += pinc; }
p++;
}
return;
}
if (y2 < y1)
{
i = x1; x1 = x2; x2 = i;
i = y1; y1 = y2; y2 = i;
}
p = (mul5(y1)<<7)+x1+pageoffset;
d = 0;
if (x2 > x1) pinc = 1; else pinc = -1;
for(i=dy;i>0;i--)
{
drawpixel16(p);
d += dx;
if (d >= dy) { d -= dy; p += pinc; }
p += 640;
}
}
void qsetmode640350(void)
{
if (qsetmode != 350)
{
stereomode = 0;
setvmode(0x10);
pageoffset = 0;
ydim16 = 350;
koutpw(0x3d4,0xc+((pageoffset>>11)<<8));
koutpw(0x3ce,0x0f00); //set/reset
koutpw(0x3ce,0x0f01); //enable set/reset
fillscreen16(0L,0L,640L*350L);
}
qsetmode = 350;
}
void qsetmode640480(void)
{
short i;
if (qsetmode != 480)
{
stereomode = 0;
setvmode(0x12);
i = 479-144;
koutpw(0x3d4,0x18+((i&255)<<8)); //line compare
koutp(0x3d4,0x7); koutp(0x3d5,(kinp(0x3d5)&239)|((i&256)>>4));
koutp(0x3d4,0x9); koutp(0x3d5,(kinp(0x3d5)&191)|((i&512)>>3));
pageoffset = 92160;
koutpw(0x3d4,0xc+((pageoffset>>11)<<8));
koutpw(0x3ce,0x0f00); //set/reset
koutpw(0x3ce,0x0f01); //enable set/reset
fillscreen16(0L,8L,640L*144L);
fillscreen16((640L*144L)>>3,0L,640L*336L);
pageoffset = 92160; ydim16 = 336;
}
qsetmode = 480;
}
void printext16(long xpos, long ypos, short col, short backcol, char name[82], char fontsize)
{
long p, z, zz, charxsiz, daxpos;
char ch, dat, mask, *fontptr;
daxpos = xpos;
koutp(0x3ce,0x5); koutp(0x3cf,(kinp(0x3cf)&(255-3))+2);
koutp(0x3ce,0x8);
if (fontsize == 1)
{
fontptr = smalltextfont;
charxsiz = 4;
}
else
{
fontptr = textfont;
charxsiz = 8;
}
z = 0;
while (name[z] != 0)
{
ch = name[z];
z++;
mask = pow2char[8-(daxpos&7)]-1;
p = ypos*80 + (daxpos>>3)+0xa0000; //Do not make ylookup!
if ((daxpos&7) == 0)
{
for(zz=0;zz<8;zz++)
{
if (backcol >= 0)
{
koutp(0x3cf,0xff);
if (charxsiz == 4) koutp(0x3cf,0x7c);
readpixel(p), drawpixel(p,(long)backcol);
}
koutp(0x3cf,fontptr[(((long)ch)<<3)+zz]);
if (charxsiz == 4) koutp(0x3cf,0x7c&fontptr[(((long)ch)<<3)+zz]);
readpixel(p), drawpixel(p,col);
p += 80;
}
}
else
{
for(zz=0;zz<8;zz++)
{
if (backcol >= 0)
{
if (charxsiz == 8)
{
koutp(0x3cf,mask);
readpixel(p), drawpixel(p,backcol);
koutp(0x3cf,~mask);
readpixel(p+1), drawpixel(p+1,backcol);
}
else
{
koutp(0x3cf,0x7c>>(daxpos&7));
readpixel(p), drawpixel(p,backcol);
koutp(0x3cf,0x7c<<(8-(daxpos&7)));
readpixel(p+1), drawpixel(p+1,backcol);
}
}
dat = fontptr[(((long)ch)<<3)+zz];
if (charxsiz == 8)
{
koutp(0x3cf,mask&(dat>>(daxpos&7)));
readpixel(p), drawpixel(p,col);
koutp(0x3cf,(~mask)&(dat<<(8-(daxpos&7))));
readpixel(p+1), drawpixel(p+1,col);
}
else
{
koutp(0x3cf,(0x7c&dat)>>(daxpos&7));
readpixel(p), drawpixel(p,col);
koutp(0x3cf,(0x7c&dat)<<(8-(daxpos&7)));
readpixel(p+1), drawpixel(p+1,col);
}
p += 80; //Do not make bytesperline!
}
}
daxpos += charxsiz;
}
koutp(0x3ce,0x5); koutp(0x3cf,(kinp(0x3cf)&(255-3))+0);
}
void _nextpage(void)
{
switch(qsetmode)
{
case 200:
switch(vidoption)
{
case 1:
if (stereomode)
{
stereonextpage();
if (!origbuffermode) buffermode = transarea = totalarea = 0;
}
else
{
visualpage = activepage;
setvisualpage(visualpage);
if (!origbuffermode)
{
buffermode = ((transarea<<3) > totalarea);
transarea = totalarea = 0;
}
activepage++; if (activepage >= numpages) activepage = 0;
setactivepage(activepage);
}
break;
case 2:
copybuf((void *)frameplace,(void *)0xa0000,64000>>2);
break;
case 6:
if (!activepage) redblueblit(screen,&screen[65536],64000L);
activepage ^= 1;
break;
}
break;
case 350:
koutpw(0x3d4,0xc+((pageoffset>>11)<<8));
limitrate();
pageoffset = 225280-pageoffset; //225280 is 352(multiple of 16)*640
break;
case 480:
koutpw(0x3d4,0xc+((pageoffset>>11)<<8));
limitrate();
pageoffset = 399360-pageoffset;
break;
}
} // _nextpage
void interrupt stereohandler1(void)
{
//VR flag
if (kinp(0x3c2)&128)
{
laststereoint = 0;
koutpw(0x3d4,((long)(overtbits)<<8)+0x11);
koutp(0x3d5,overtbits+16);
}
if (laststereoint == 1)
{
visualpage ^= 1;
setvisualpage(visualpage|0x80000000); //0x80000000 to ignore qlimitrate
}
laststereoint++;
koutp(0x70,0xc); kinp(0x71);
koutp(0xa0,0x20);
koutp(0x20,0x20);
}
void interrupt stereohandler2(void)
{
//VR flag
if (kinp(0x3c2)&128)
{
laststereoint = 0;
koutp(0x378,0xfb+((visualpage&1^1)<<2));
koutpw(0x3d4,((long)overtbits<<8)+0x11);
koutp(0x3d5,overtbits+16);
}
if (laststereoint == 1)
{
visualpage ^= 1;
setvisualpage(visualpage|0x80000000); //0x80000000 to ignore qlimitrate
}
laststereoint++;
koutp(0x70,0xc); kinp(0x71);
koutp(0xa0,0x20);
koutp(0x20,0x20);
}
void stereonextpage(void)
{
koutp(0x70,0xc); kinp(0x71);
//koutpw(0x70,0x420b);
if ((activepage&1) == 0)
{
if (stereomode == 1)
{
clearbuf((void *)(ylookup[ydim-1]+frameplace),xdim>>4,whiteband);
clearbuf((void *)(ylookup[ydim-1]+frameplace+(xdim>>2)),(xdim>>2)-(xdim>>4),blackband);
}
activepage++;
setactivepage(activepage);
return;
}
if (stereomode == 1)
{
clearbuf((void *)(ylookup[ydim-1]+frameplace),(xdim>>2)-(xdim>>4),whiteband);
clearbuf((void *)(ylookup[ydim-1]+frameplace+xdim-(xdim>>2)),xdim>>4,blackband);
}
if (visualpage < (numpages&~1)-2) visualpage += 2; else visualpage &= 1;
if (activepage < (numpages&~1)-1) activepage++; else activepage = 0;
setactivepage(activepage);
}
void setstereo(long dastereomode)
{
//long i, dist, blackdist, whitedist, t1, t2, numlines;
//char c1, c2;
long i, dist, blackdist, whitedist;
if ((vidoption != 1) || (numpages < 2)) return;
if (stereomode) //---------------Uninitialize old stereo mode
{
if ((xdim == 320) && (ydim == 200))
{
//back to 70 hz
koutp(0x3c2,o3c2);
}
//Uninit VR flag
koutpw(0x3d4,(((long)overtbits+32)<<8)+0x11);
//Uninit RTC
_disable();
koutp(0xa1,(kinp(0xa1)&~1)|(oa1&1));
koutp(0x70,0xa); koutp(0x71,ortca);
koutp(0x70,0xb); koutp(0x71,ortcb);
uninstallbistereohandlers();
_enable();
stereomode = 0;
ostereopixelwidth = -1;
setview(windowx1,windowy1,windowx2,windowy2);
if (stereomode == 1)
{
for(i=0;i<numpages;i++)
{
setactivepage(i);
clearbuf((void *)(ylookup[ydim-1]+frameplace),xdim>>2,blackband);
}
setactivepage(activepage);
}
}
//------------------------------------- Initialize new stereo mode
stereomode = dastereomode; if (!stereomode) return;
activepage = (visualpage & ~1)+2;
if (activepage >= numpages-1) activepage = 0;
if (stereomode == 1)
{
blackdist = 0x7fffffff; whitedist = 0x80000000;
koutp(0x3c7,0);
for(i=0;i<256;i++)
{
dist = (kinp(0x3c9)&255)+(kinp(0x3c9)&255)+(kinp(0x3c9)&255);
if (dist < blackdist) { blackdist = dist; blackband = i; }
if (dist > whitedist) { whitedist = dist; whiteband = i; }
}
blackband += (blackband<<8); blackband += (blackband<<16);
whiteband += (whiteband<<8); whiteband += (whiteband<<16);
}
if ((xdim == 320) && (ydim == 200))
{
//80 hz
o3c2 = kinp(0x3cc);
koutp(0x3c2,(o3c2&0xf3)+4);
}
//Init RTC
_disable();
if (stereomode == 1) installbistereohandlers(stereohandler1);
if (stereomode == 2) installbistereohandlers(stereohandler2);
koutp(0x70,0xa); ortca = kinp(0x71);
if (stereomode == 1) koutp(0x71,0x28); //+8 = 256hz
if (stereomode == 2) koutp(0x71,0x26); //+6 = 1024hz
koutp(0x70,0xb); ortcb = kinp(0x71); koutp(0x71,0x42);
koutp(0x70,0xc); kinp(0x71);
oa1 = kinp(0xa1); koutp(0xa1,oa1&~1);
_enable();
//Init VR flag
koutp(0x3d4,0x11);
overtbits = kinp(0x3d5) & ~(16+32);
koutp(0x3d5,overtbits);
koutp(0x3d5,overtbits+16);
}
#define RTCBUFSIZ 16
static unsigned short rtcopmsel, rtcormseg, rtcormoff;
static unsigned long rtcopmoff;
//Use bicomc.asm as a template if this asm code needs re-writing
static char rtcrmbuffer[RTCBUFSIZ] =
{
0x50, //push ax
0xb0,0x0c, //mov al, 0ch
0xe6,0x70, //out 70h, al
0xe4,0x71, //in al, 71h
0xb0,0x20, //mov al, 20h
0xe6,0xa0, //out 0a0h, al
0xe6,0x20, //out 20h, al
0x58, //pop ax
0xcf //iret
};
void *engconvalloc32 (unsigned long size)
{
union REGS r;
r.x.eax = 0x0100; //DPMI allocate DOS memory
r.x.ebx = ((size+15)>>4); //Number of paragraphs requested
int386(0x31,&r,&r);
if (r.x.cflag != 0) //Failed
return ((unsigned long)0);
return ((void *)((r.x.eax&0xffff)<<4)); //Returns full 32-bit offset
}
void installbistereohandlers(void far *stereohan)
{
//char *ptr;
union REGS r;
struct SREGS sr;
void *lowp;
//int c;
//Get old protected mode handler
r.x.eax = 0x3500+0x70; /* DOS get vector (INT 0Ch) */
sr.ds = sr.es = 0;
int386x(0x21,&r,&r,&sr);
rtcopmsel = (unsigned short)sr.es;
rtcopmoff = r.x.ebx;
//Get old real mode handler
r.x.eax = 0x0200; /* DPMI get real mode vector */
r.h.bl = 0x70;
int386(0x31,&r,&r);
rtcormseg = (unsigned short)r.x.ecx;
rtcormoff = (unsigned short)r.x.edx;
//Allocate memory in low memory to store real mode handler
if ((lowp = engconvalloc32(RTCBUFSIZ)) == 0)
{
printf("Couldn't allocate conventional memory.\n");
exit(1);
}
memcpy(lowp,(void *)rtcrmbuffer,RTCBUFSIZ);
//Set new protected mode handler
r.x.eax = 0x2500+0x70; /* DOS set vector (INT 0Ch) */
r.x.edx = FP_OFF(stereohan);
sr.ds = FP_SEG(stereohan); //DS:EDX == &handler
sr.es = 0;
int386x(0x21,&r,&r,&sr);
//Set new real mode handler (must be after setting protected mode)
r.x.eax = 0x0201;
r.h.bl = 0x70; //CX:DX == real mode &handler
r.x.ecx = ((((long)lowp)>>4)&0xffff); //D32realseg
r.x.edx = (((long)lowp)&0xf); //D32realoff
int386(0x31,&r,&r);
}
void uninstallbistereohandlers(void)
{
union REGS r;
struct SREGS sr;
//restore old protected mode handler
r.x.eax = 0x2500+0x70; /* DOS set vector (INT 0Ch) */
r.x.edx = rtcopmoff;
sr.ds = rtcopmsel; /* DS:EDX == &handler */
sr.es = 0;
int386x(0x21,&r,&r,&sr);
//restore old real mode handler
r.x.eax = 0x0201; /* DPMI set real mode vector */
r.h.bl = 0x70;
r.x.ecx = (unsigned long)rtcormseg; //CX:DX == real mode &handler
r.x.edx = (unsigned long)rtcormoff;
int386(0x31,&r,&r);
}
void inittimer(void)
{
outp(0x43,0x34); outp(0x40,(1193181/120)&255); outp(0x40,(1193181/120)>>8);
oldtimerhandler = _dos_getvect(0x8);
_disable(); _dos_setvect(0x8, timerhandler); _enable();
}
void uninittimer(void)
{
outp(0x43,0x34); outp(0x40,0); outp(0x40,0); //18.2 times/sec
_disable(); _dos_setvect(0x8, oldtimerhandler); _enable();
}
void initkeys(void)
{
oldkeyhandler = _dos_getvect(0x9);
_disable(); _dos_setvect(0x9, keyhandler); _enable();
}
void uninitkeys(void)
{
short *ptr;
_dos_setvect(0x9, oldkeyhandler);
//Turn off shifts to prevent stucks with quitting
ptr = (short *)0x417; *ptr &= ~0x030f;
}
int _setgamemode(char davidoption, long daxdim, long daydim)
{
long i, j, ostereomode;
if ((qsetmode == 200) && (vidoption == davidoption) && (xdim == daxdim) && (ydim == daydim))
return(0);
vidoption = davidoption; xdim = daxdim; ydim = daydim;
strcpy(kensmessage,"!!!! BUILD engine&tools programmed by Ken Silverman of E.G. RI. (c) Copyright 1995 Ken Silverman. Summary: BUILD = Ken. !!!!");
if (getkensmessagecrc(FP_OFF(kensmessage)) != 0x56c764d4)
{ setvmode(0x3); printf("Nice try.\n"); exit(0); }
ostereomode = stereomode; if (stereomode) setstereo(0L);
activepage = visualpage = 0;
switch(vidoption)
{
case 1: i = xdim*ydim; break;
case 2: xdim = 320; ydim = 200; i = xdim*ydim; break;
case 6: xdim = 320; ydim = 200; i = 131072; break;
default: return(-1);
}
j = ydim*4*sizeof(long); //Leave room for horizlookup&horizlookup2
if (screen != NULL)
{
if (screenalloctype == 0) kkfree((void *)screen);
if (screenalloctype == 1) suckcache((long *)screen);
screen = NULL;
}
screenalloctype = 0;
if ((screen = (char *)kkmalloc(i+(j<<1))) == NULL)
{
allocache((long *)&screen,i+(j<<1),&permanentlock);
screenalloctype = 1;
}
frameplace = FP_OFF(screen);
horizlookup = (long *)(frameplace+i);
horizlookup2 = (long *)(frameplace+i+j);
horizycent = ((ydim*4)>>1);
switch(vidoption)
{
case 1:
//bytesperline is set in this function
if (setvesa(xdim,ydim) < 0) return(-1);
break;
case 2:
horizycent = ((ydim*4)>>1); //HACK for switching to this mode
case 6:
bytesperline = xdim;
setvmode(0x13);
break;
default: return(-1);
}
//Force drawrooms to call dosetaspect & recalculate stuff
oxyaspect = oxdimen = oviewingrange = -1;
setvlinebpl(bytesperline);
j = 0;
for(i=0;i<=ydim;i++) ylookup[i] = j, j += bytesperline;
numpages = 1;
if (vidoption == 1) numpages = min(maxpages,8);
setview(0L,0L,xdim-1,ydim-1);
clearallviews(0L);
setbrightness(curbrightness, &palette[0]);
if (searchx < 0) { searchx = halfxdimen; searchy = (ydimen>>1); }
if (ostereomode) setstereo(ostereomode);
qsetmode = 200;
return(0);
}
void _platform_init(int argc, char **argv, const char *title, const char *icon)
{
// no op in DOS, currently. --ryan.
}
void clear2dscreen(void)
{
if (qsetmode == 350)
fillscreen16(pageoffset>>3,0L,640L*350L);
else if (qsetmode == 480)
{
if (ydim16 <= 336) fillscreen16(pageoffset>>3,0L,640L*336L);
else fillscreen16(pageoffset>>3,0L,640L*480L);
}
}
void _idle(void)
{
// no-op in DOS, which is non-multitasking. However, if someone were to
// add Desqview/win95/OS2/etc support, timeslicing would be good.
}
void *_getVideoBase(void)
{
return((void *) 0xa0000);
}
void _updateScreenRect(long x, long y, long w, long h)
{
}
int using_opengl(void)
{
return(0);
}
// end of dos_driver.c ...