📄 vesavcd.c
字号:
//////////////////////////////////////////////////////////
// Soft VCD Player
// These code MUST Compiler by BC3.1,Not others.
// SMALL Mode,386 Instructions,DOS Stack Code,
// FASTEST Optimizations.
// Main Program with Video Control & WndProc.
// Southern.Liang
// 1996.5.25
//////////////////////////////////////////////////////////
#pragma option -zCOTHER_TEXT
#include <windows.h>
#include <mmsystem.h>
#include "DOS.H"
#include "DCI.H"
#include "VCDAPI.H"
#define WM_DEBUG WM_USER+800
#define WM_CDROMOPEN WM_USER+890
#define VIDEONUMBER 30
//////////////// New feature Message ///////////////
#define WM_RESUME WM_USER+900
#define WM_STEPVIDEO WM_USER+901
#define WM_STOPVIDEO WM_USER+902
#define WM_CUTPICTURE WM_USER+903
#define WM_STATEDISPLAY WM_USER+904
#define WM_PLAYNEXTFILE WM_USER+905
#define WM_PLAYPREVFILE WM_USER+906
////////////////////////////////////
void huge TurnOffEscape(void);
void huge TurnOnEscape(void);
////////////////////Screen/////////////////
#define DAC_WRITE_ADDR 0x3C8 // VGA DAC Write Addr Register
#define DAC_READ_ADDR 0x3C7 // VGA DAC Read Addr Register
#define PEL_DATA_REG 0x3C9 // VGA DAC/PEL data Register R/W
static void ReadDAC(void far *DAC,WORD Start,WORD Number)
{
// Determine register #'s, size to copy, etc
asm les DI, dword ptr DAC // ES:DI -> Palette Buffer
asm mov DX, DAC_READ_ADDR // DAC register # selector
asm mov AX, Start // Get Start Register
asm mov BX, Number // BX = # of DAC registers
asm mov CX, BX // CX = # of DAC registers
asm add CX, BX // CX = " " * 2
asm add CX, BX // CX = " " * 3
asm cld // Block INs forward
// Read a block of DAC Registers
asm out DX, AL // set up correct register #
asm mov DX, PEL_DATA_REG// Dac Data Register
asm rep insb // block read DAC registers
}
static void LoadDAC(void far *DAC,WORD Start,WORD Number)
{
asm push ds
Wait:
asm mov dx,0x3DA
asm in al,dx
asm test al,8
asm jz short Wait
asm mov dx,0x3C6
asm mov al,0xFF
asm out dx,al
asm lds SI,dword ptr DAC // DS:SI -> Palette Data
asm mov DX, DAC_WRITE_ADDR // DAC register # selector
asm mov BX, Number // Get Number Register
asm mov cx, Start
asm cld // Block OUTs forward
LOOPOUT:
asm mov al,cl
asm out DX,AL // set up correct register #
asm inc dx
asm outsb // block set DAC registers
asm outsb
asm outsb
asm dec dx
asm inc cx
asm cmp cx,bx
asm jbe short LOOPOUT
asm pop ds
}
BYTE Palette[256*3];
void PASCAL FAR ComputePalette(void)
{
int i;
for(i=0;i<256;i++)
Palette[i*3+2]=Palette[i*3+1]=Palette[i*3]=i/4;
}
static void ReadAllDAC(void)
{
ReadDAC(Palette,0,256);
}
static void SetAllDAC(void)
{ int i;
//LoadDAC(Palette,0,256);//This Load too fast on some fast machine error.
outportb(0x3C6,0xFF);
outportb(0x3C8,0);
for(i=0;i<256*3;i++) //Load Slowly make on fast machine success.
outportb(0x3C9,Palette[i]);
outport(0x3C4,0x0003);
}
///////////////////////////////////////////
void FAR PASCAL Death(HDC hdc);
void FAR PASCAL Resurrection(HDC hdc,WORD,WORD,WORD,WORD,WORD,WORD);
int VESASupportFlags=0;
int VESAColor=0;
HDC DeathhDC;
int Old3CF6;
void RestoreVideoState(void);
static void NormalWindow(void)
{
int Port;
//////// Restore Old ////////
outportb(0x3CE,0x06);
outportb(0x3CF,Old3CF6); //128K Screen Buffer
//////////////////
_AX=3;
geninterrupt(0x10); //This is very importion
RestoreVideoState();
//////////////////
_AX=3;
geninterrupt(0x10); //This is very importion
//////////////////////////////////
Resurrection(DeathhDC,0,0,0,0,0,0);
ReleaseDC(NULL,DeathhDC);
ShowCursor(1);
InvalidateRect(NULL,NULL,0);
}
extern int VideoCardType;
extern int SubType;
extern DWORD VideoPhysBase;
int BankingFlags=0; //No 128K Buffer use banking.
int OtherDecoder=0; //Use internal MPEG decoder.
char OtherDecoderName[24];
void SetVideoBufferBase(DWORD Base);
int LinearFlags=0;
extern WORD Linear;
static int TestNo128KVideo(void)
{
int Ret;
WORD Selector;
DWORD Limit;
DWORD far *Ptr;
DWORD Data,tmp;
if(LinearFlags==0) return 1; //No 128K
//Screen Buffer as B800 Segment.
asm mov es,Linear
_EDI=0x18000;
__emit__(0x26,0x67,0x66,0x8B,0x07);//asm mov eax,es:[edi]
__emit__(0x66,0x26,0x67,0x83,0x37,0xFF);//asm xor es:[edi],0xFFFFFFFF
__emit__(0x26,0x67,0x66,0x3B,0x07);//asm cmp eax,es:[edi]
__emit__(0x26,0x67,0x66,0x89,0x07);//asm mov es:[edi],eax
asm je ROM
return 0;
ROM:
return 1;
}
int GetBankSize(int Mode);
int BankSize=1; //K
int BankGranUnit=64;
void SaveVideoState(void);
void PASCAL FAR GetBankingWay(void)
{
outportb(0x3CE,0x06);outportb(0x3CF,Old3CF6);//64K Screen Buffer
if(VideoCardType==0)
BankGranUnit=GetBankSize(VESAColor==16 ? 0x10E:0x10D);
else BankGranUnit=GetBankSize(0x101);
if(BankGranUnit==0) BankGranUnit=64;
BankSize=64/BankGranUnit;
if(BankSize==0) BankSize=1;
}
static void Set320x20064KC(void)
{
ShowCursor(0);
DeathhDC=GetDC(NULL);
Death(DeathhDC);
////////////////
SaveVideoState();
////////////////
_AX=0x13; //Some VGA card must call this first.
geninterrupt(0x10); //In Graphics mode first.
///////////////////////////
if(VideoCardType==0)
{//VESA Support
if(VESAColor==64)
{//640x480 64KC
_BX=0x111;
_AX=0x4F02;
geninterrupt(0x10);
}
if(VESAColor==32)
{//640x480 32KC
_BX=0x110;
_AX=0x4F02;
geninterrupt(0x10);
}
if(VESAColor==16)//64K Color
{
_BX=0x10E;
_AX=0x4F02;
geninterrupt(0x10);
}
if(VESAColor==15)//32K Color
{
_BX=0x10D;
_AX=0x4F02;
geninterrupt(0x10);
}
if(VESAColor==8)//256 Color
{
_AX=0x13;
geninterrupt(0x10);
}
}
else {//S3 or GD542x,myself support
if(VESAColor==8)
{
_AX=0x13;
geninterrupt(0x10);
}
else SetVideoMode();
}
if(VESASupportFlags)//Set Video Memory Bank & Display start
{
_AX=0x4F05;
_BX=0;_DX=0;//Select Bank 0
geninterrupt(0x10);
_AX=0x4F07;
_BX=0;_CX=0;_DX=0;//Start display at (0,0)
geninterrupt(0x10);
}
if(VESAColor==64 || VESAColor==32)
{//Set 640x240 mode
int Port;
outportb(0x3D4,9);
Port=inportb(0x3D5);
if((Port&1)) Port|=0x80;
else Port|=1;
outportb(0x3D5,Port);
if(VESAColor==64) BankGranUnit=GetBankSize(0x111);
else BankGranUnit=GetBankSize(0x110);
if(BankGranUnit==0) BankGranUnit=64;
BankSize=64/BankGranUnit;
if(BankSize==0) BankSize=1;
}
else {
if(VESAColor==16||VESAColor==15)
{
//////// Set 128K Buffer ////////
outportb(0x3CE,0x06);Old3CF6=inportb(0x3CF);
outportb(0x3CE,0x06);outportb(0x3CF,Old3CF6&0xF3);//128K Screen Buffer
if(BankingFlags==0) //Force use banking
BankingFlags=TestNo128KVideo();
if(BankingFlags)
{//Normal VGA,use banking.
GetBankingWay();
}
}
}
}
///////////////////// VESA //////////////////////
typedef struct VESAtag
{
DWORD VESAFlags;
WORD Version;
char far * OEMPtr;
DWORD Size;
int far * ModePtr;
}VESA;
VESA far *VESAPtr;
WORD DOSSel;
WORD DOSSeg;
typedef struct Stacktag
{
DWORD DI;
DWORD SI;
DWORD BP;
DWORD Resever;//
DWORD BX;
DWORD DX;
DWORD CX;
DWORD AX;
WORD FLAGS;//
WORD ES;
WORD DS;
WORD FS;
WORD GS;
WORD IP;//
WORD CS;//
WORD SP;
WORD SS;
}STACK;
STACK Stack;
////////////////////////////////////////////
WORD VideoStateSel=0;
WORD VideoStateSeg=0;
void PASCAL FAR AllocateVideoStateBuffer(void)
{
DWORD Size;
if(VESASupportFlags==0) return;//VESA Call not support.
// _AX=0x4F04;
// _DL=0;
// _CX=0xFF;
// geninterrupt(0x10); //This call in Win95 & S3 Trio32/64 driver
// if(_AX!=0x004F) return; //will make GDI error.
// Size=_BX; //Always the size = 1024 bytes
// Size*=64;
Size=4096; //Now set 4096 bytes buffer for all Video card
GlobalDosAlloc(Size);
VideoStateSel=_AX;
VideoStateSeg=_DX;
}
void PASCAL FAR FreeVideoStateBuffer(void)
{
if(VideoStateSel==NULL) return;
GlobalDosFree(VideoStateSel);
}
int SupperVESAState=0;
static void SaveVideoState(void)
{
if(VideoStateSel==NULL) return;
Stack.ES=VideoStateSeg;
Stack.AX=0x4F04;
Stack.DX=1; //The Supper VGA state on Windows95 VIEWTOP 64V+ error
Stack.CX=0x7; //VESA Restore Video hardware,BIOS data,DAC state
Stack.CX|=SupperVESAState;
////////// Call Real INT //////////
_ES=FP_SEG(&Stack);
_DI=FP_OFF(&Stack);
_CX=0;
_BH=0;
_BL=0x10;
_AX=0x300;
geninterrupt(0x31);
}
static void RestoreVideoState(void)
{
if(VideoStateSel==NULL) return;
Stack.ES=VideoStateSeg;
Stack.AX=0x4F04;
Stack.DX=2; //The Supper VGA state on Windows95 VIEWTOP 64V+ error
Stack.CX=0x7; //VESA Restore Video hardware,BIOS data,DAC state
Stack.CX|=SupperVESAState;
////////// Call Real INT //////////
_ES=FP_SEG(&Stack);
_DI=FP_OFF(&Stack);
_CX=0;
_BH=0;
_BL=0x10;
_AX=0x300;
geninterrupt(0x31);
}
int far * ModePtr;
static int VESAModeTest(int Mode)
{
////////// Stack Registers ////////
Stack.DI=0;
Stack.ES=0xC000; //BIOS ROM area C000:0
Stack.AX=0x4F01;
Stack.CX=Mode; //VESA Mode;
////////// Call Real INT //////////
_ES=FP_SEG(&Stack);
_DI=FP_OFF(&Stack);
_CX=0;
_BH=0;
_BL=0x10;
_AX=0x300;
geninterrupt(0x31);
asm jnc short NEXT2;
return 0;
NEXT2: //VESA Support 64K Color
if((Stack.AX&0xFF)!=0x4F) return 0;//Not Support VESA
if((Stack.AX&0xFF00)!=0 ) return 0;//Not Success
return 1;
}
int VESACanUse=0;
int M640x48064KC=0;
int M640x48032KC=0;
int PASCAL FAR TestVESASupport(void)
{
int Mode;
/////////// Must be VGA //////////
if((inportb(0x3CC)&1)==0) return 0;
/////////// Allocate DOS Memory //////////
GlobalDosAlloc(256);
DOSSel=_AX;
DOSSeg=_DX;
if(DOSSel==0) //Can't Allocate DOS Memory.
{
if(VESAModeTest(0x111)==1) M640x48064KC=1;
if(VESAModeTest(0x110)==1) M640x48032KC=1;
if(VESAModeTest(0x10E)==1) return 16;
if(VESAModeTest(0x10D)==1) return 15;
return 8;
}
////////////////VESA Info////////////////
Stack.DI=0;
Stack.ES=DOSSeg;
Stack.AX=0x4F00;
////////// Call Real INT //////////
_ES=FP_SEG(&Stack);
_DI=FP_OFF(&Stack);
_CX=0;
_BH=0;
_BL=0x10;
_AX=0x300;
geninterrupt(0x31);
asm jnc short NEXT2;
// DPMI or VESA Call Error,Directly test mode.
DIRTESTMODE:
GlobalDosFree(DOSSel);
if(VESAModeTest(0x10E)==1) return 16;
if(VESAModeTest(0x10D)==1) return 15;
return 8;
NEXT2: //VESA Support 64K Color
if((Stack.AX&0xFF)!=0x4F) goto DIRTESTMODE;//Not Support VESA
if((Stack.AX&0xFF00)!=0 ) goto DIRTESTMODE;//Not Success
VESASupportFlags=VESACanUse=1;
///////////////Read VESA info/////////////
VESAPtr=MK_FP(DOSSel,0);
if(VESAPtr->VESAFlags!=0x41534556) goto DIRTESTMODE;//'VESA'
ModePtr=VESAPtr->ModePtr;
////////// Segment -> Selector ///////////
_BX=FP_SEG(ModePtr);
_AX=2;
geninterrupt(0x31); //DOS Segment to Selector.
asm jnc short NEXT3;
goto DIRTESTMODE;
NEXT3:
*((WORD *)&ModePtr+1)=_AX; //High WORD = Selector.
/////////// Mode Info ////////////
Mode=8;
while(*ModePtr!=-1)
{
if(*ModePtr==0x111) M640x48064KC=1;
if(*ModePtr==0x110) M640x48032KC=1;
if(*ModePtr==0x10E)
{
if(Mode==8||Mode==15)
Mode=16; //64 K Colors
}
if(*ModePtr==0x10D)
{
if(Mode==8) Mode=15; //32 K Colors
}
ModePtr++; //Next VESA mode.
if(*ModePtr==0) break;
}
if(Mode==8) SearchVESAType(VESAPtr->OEMPtr);
///////////////Free DOS Memory ///////////
GlobalDosFree(DOSSel);
//////////////////////////////////////////
return Mode;
}
typedef struct VESAINFOtag
{
WORD ModeAttrib;
BYTE WindowAAttrib;
BYTE WindowBAttrib;
WORD GranUnit;
WORD WinSize;
WORD WindowASegment;
WORD WindowBSegment;
void far *BankSwitchProc;
WORD LineBytes;
WORD WidthBytes;
WORD HeightBytes;
}VESAINFO;
static HadGetBankSize=0;
static int GetBankSize(int Mode)
{
VESAINFO far *Ptr;
if(HadGetBankSize==1) return BankGranUnit;
HadGetBankSize=1;
GlobalDosAlloc(256);
DOSSel=_AX;
DOSSeg=_DX;
if(DOSSel==0) //Can't Allocate DOS Memory.
return 64;
////////////////VESA Info////////////////
Stack.DI=0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -