📄 id_vl.c
字号:
// ID_VL.C
#include <dos.h>
#include <alloc.h>
#include <mem.h>
#include <string.h>
#include "ID_HEAD.H"
#include "ID_VL.H"
#pragma hdrstop
//
// SC_INDEX is expected to stay at SC_MAPMASK for proper operation
//
unsigned bufferofs;
unsigned displayofs,pelpan;
unsigned screenseg=SCREENSEG; // set to 0xa000 for asm convenience
unsigned linewidth;
unsigned ylookup[MAXSCANLINES];
boolean screenfaded;
unsigned bordercolor;
boolean fastpalette; // if true, use outsb to set
byte far palette1[256][3],far palette2[256][3];
//===========================================================================
// asm
int VL_VideoID (void);
void VL_SetCRTC (int crtc);
void VL_SetScreen (int crtc, int pelpan);
void VL_WaitVBL (int vbls);
//===========================================================================
/*
=======================
=
= VL_Startup
=
=======================
*/
#if 0
void VL_Startup (void)
{
if ( !MS_CheckParm ("HIDDENCARD") && VL_VideoID () != 5)
MS_Quit ("You need a VGA graphics card to run this!");
asm cld; // all string instructions assume forward
}
#endif
/*
=======================
=
= VL_Startup // WOLFENSTEIN HACK
=
=======================
*/
static char *ParmStrings[] = {"HIDDENCARD",""};
void VL_Startup (void)
{
int i,videocard;
asm cld;
videocard = VL_VideoID ();
for (i = 1;i < _argc;i++)
if (US_CheckParm(_argv[i],ParmStrings) == 0)
{
videocard = 5;
break;
}
if (videocard != 5)
Quit ("Improper video card! If you really have a VGA card that I am not \n"
"detecting, use the -HIDDENCARD command line parameter!");
}
/*
=======================
=
= VL_Shutdown
=
=======================
*/
void VL_Shutdown (void)
{
VL_SetTextMode ();
}
/*
=======================
=
= VL_SetVGAPlaneMode
=
=======================
*/
void VL_SetVGAPlaneMode (void)
{
asm mov ax,0x13
asm int 0x10
VL_DePlaneVGA ();
VGAMAPMASK(15);
VL_SetLineWidth (40);
}
/*
=======================
=
= VL_SetTextMode
=
=======================
*/
void VL_SetTextMode (void)
{
asm mov ax,3
asm int 0x10
}
//===========================================================================
/*
=================
=
= VL_ClearVideo
=
= Fill the entire video buffer with a given color
=
=================
*/
void VL_ClearVideo (byte color)
{
asm mov dx,GC_INDEX
asm mov al,GC_MODE
asm out dx,al
asm inc dx
asm in al,dx
asm and al,0xfc // write mode 0 to store directly to video
asm out dx,al
asm mov dx,SC_INDEX
asm mov ax,SC_MAPMASK+15*256
asm out dx,ax // write through all four planes
asm mov ax,SCREENSEG
asm mov es,ax
asm mov al,[color]
asm mov ah,al
asm mov cx,0x8000 // 0x8000 words, clearing 8 video bytes/word
asm xor di,di
asm rep stosw
}
/*
=============================================================================
VGA REGISTER MANAGEMENT ROUTINES
=============================================================================
*/
/*
=================
=
= VL_DePlaneVGA
=
=================
*/
void VL_DePlaneVGA (void)
{
//
// change CPU addressing to non linear mode
//
//
// turn off chain 4 and odd/even
//
outportb (SC_INDEX,SC_MEMMODE);
outportb (SC_INDEX+1,(inportb(SC_INDEX+1)&~8)|4);
outportb (SC_INDEX,SC_MAPMASK); // leave this set throughought
//
// turn off odd/even and set write mode 0
//
outportb (GC_INDEX,GC_MODE);
outportb (GC_INDEX+1,inportb(GC_INDEX+1)&~0x13);
//
// turn off chain
//
outportb (GC_INDEX,GC_MISCELLANEOUS);
outportb (GC_INDEX+1,inportb(GC_INDEX+1)&~2);
//
// clear the entire buffer space, because int 10h only did 16 k / plane
//
VL_ClearVideo (0);
//
// change CRTC scanning from doubleword to byte mode, allowing >64k scans
//
outportb (CRTC_INDEX,CRTC_UNDERLINE);
outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1)&~0x40);
outportb (CRTC_INDEX,CRTC_MODE);
outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1)|0x40);
}
//===========================================================================
/*
====================
=
= VL_SetLineWidth
=
= Line witdh is in WORDS, 40 words is normal width for vgaplanegr
=
====================
*/
void VL_SetLineWidth (unsigned width)
{
int i,offset;
//
// set wide virtual screen
//
outport (CRTC_INDEX,CRTC_OFFSET+width*256);
//
// set up lookup tables
//
linewidth = width*2;
offset = 0;
for (i=0;i<MAXSCANLINES;i++)
{
ylookup[i]=offset;
offset += linewidth;
}
}
/*
====================
=
= VL_SetSplitScreen
=
====================
*/
void VL_SetSplitScreen (int linenum)
{
VL_WaitVBL (1);
linenum=linenum*2-1;
outportb (CRTC_INDEX,CRTC_LINECOMPARE);
outportb (CRTC_INDEX+1,linenum % 256);
outportb (CRTC_INDEX,CRTC_OVERFLOW);
outportb (CRTC_INDEX+1, 1+16*(linenum/256));
outportb (CRTC_INDEX,CRTC_MAXSCANLINE);
outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1) & (255-64));
}
/*
=============================================================================
PALETTE OPS
To avoid snow, do a WaitVBL BEFORE calling these
=============================================================================
*/
/*
=================
=
= VL_FillPalette
=
=================
*/
void VL_FillPalette (int red, int green, int blue)
{
int i;
outportb (PEL_WRITE_ADR,0);
for (i=0;i<256;i++)
{
outportb (PEL_DATA,red);
outportb (PEL_DATA,green);
outportb (PEL_DATA,blue);
}
}
//===========================================================================
/*
=================
=
= VL_SetColor
=
=================
*/
void VL_SetColor (int color, int red, int green, int blue)
{
outportb (PEL_WRITE_ADR,color);
outportb (PEL_DATA,red);
outportb (PEL_DATA,green);
outportb (PEL_DATA,blue);
}
//===========================================================================
/*
=================
=
= VL_GetColor
=
=================
*/
void VL_GetColor (int color, int *red, int *green, int *blue)
{
outportb (PEL_READ_ADR,color);
*red = inportb (PEL_DATA);
*green = inportb (PEL_DATA);
*blue = inportb (PEL_DATA);
}
//===========================================================================
/*
=================
=
= VL_SetPalette
=
= If fast palette setting has been tested for, it is used
= (some cards don't like outsb palette setting)
=
=================
*/
void VL_SetPalette (byte far *palette)
{
int i;
// outportb (PEL_WRITE_ADR,0);
// for (i=0;i<768;i++)
// outportb(PEL_DATA,*palette++);
asm mov dx,PEL_WRITE_ADR
asm mov al,0
asm out dx,al
asm mov dx,PEL_DATA
asm lds si,[palette]
asm test [ss:fastpalette],1
asm jz slowset
//
// set palette fast for cards that can take it
//
asm mov cx,768
asm rep outsb
asm jmp done
//
// set palette slowly for some video cards
//
slowset:
asm mov cx,256
setloop:
asm lodsb
asm out dx,al
asm lodsb
asm out dx,al
asm lodsb
asm out dx,al
asm loop setloop
done:
asm mov ax,ss
asm mov ds,ax
}
//===========================================================================
/*
=================
=
= VL_GetPalette
=
= This does not use the port string instructions,
= due to some incompatabilities
=
=================
*/
void VL_GetPalette (byte far *palette)
{
int i;
outportb (PEL_READ_ADR,0);
for (i=0;i<768;i++)
*palette++ = inportb(PEL_DATA);
}
//===========================================================================
/*
=================
=
= VL_FadeOut
=
= Fades the current palette to the given color in the given number of steps
=
=================
*/
void VL_FadeOut (int start, int end, int red, int green, int blue, int steps)
{
int i,j,orig,delta;
byte far *origptr, far *newptr;
VL_WaitVBL(1);
VL_GetPalette (&palette1[0][0]);
_fmemcpy (palette2,palette1,768);
//
// fade through intermediate frames
//
for (i=0;i<steps;i++)
{
origptr = &palette1[start][0];
newptr = &palette2[start][0];
for (j=start;j<=end;j++)
{
orig = *origptr++;
delta = red-orig;
*newptr++ = orig + delta * i / steps;
orig = *origptr++;
delta = green-orig;
*newptr++ = orig + delta * i / steps;
orig = *origptr++;
delta = blue-orig;
*newptr++ = orig + delta * i / steps;
}
VL_WaitVBL(1);
VL_SetPalette (&palette2[0][0]);
}
//
// final color
//
VL_FillPalette (red,green,blue);
screenfaded = true;
}
/*
=================
=
= VL_FadeIn
=
=================
*/
void VL_FadeIn (int start, int end, byte far *palette, int steps)
{
int i,j,delta;
VL_WaitVBL(1);
VL_GetPalette (&palette1[0][0]);
_fmemcpy (&palette2[0][0],&palette1[0][0],sizeof(palette1));
start *= 3;
end = end*3+2;
//
// fade through intermediate frames
//
for (i=0;i<steps;i++)
{
for (j=start;j<=end;j++)
{
delta = palette[j]-palette1[0][j];
palette2[0][j] = palette1[0][j] + delta * i / steps;
}
VL_WaitVBL(1);
VL_SetPalette (&palette2[0][0]);
}
//
// final color
//
VL_SetPalette (palette);
screenfaded = false;
}
/*
=================
=
= VL_TestPaletteSet
=
= Sets the palette with outsb, then reads it in and compares
= If it compares ok, fastpalette is set to true.
=
=================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -