home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
POINT Software Programming
/
PPROG1.ISO
/
misc
/
vfwdk
/
samples
/
bravado
/
ctdev.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-31
|
15KB
|
571 lines
/****************************************************************************
*
* ctdev.c
*
* Hardware specific routines.
*
* Microsoft Video for Windows Sample Capture Driver
* Chips & Technologies 9001 based frame grabbers.
*
* Copyright (c) 1992-1993 Microsoft Corporation. All Rights Reserved.
*
* You have a royalty-free right to use, modify, reproduce and
* distribute the Sample Files (and/or any modified version) in
* any way you find useful, provided that you agree that
* Microsoft has no warranty obligations or liability for any
* Sample Application Files which are modified.
*
***************************************************************************/
#include <windows.h>
#include <mmsystem.h>
#include <conio.h>
#include <msvideo.h>
#include <msviddrv.h>
#include "ct.h" // General include
#include "ctdev.h" // Device specific include
#include "debug.h"
#ifdef _VBLASTER
#include "pcvideo.h"
char gszDriverName[] = "VBlaster.drv";
#endif
#ifdef _BRAVADO
#include "vwproto.h"
VWCFG VWConfigBuf;
char gszDriverName[] = "Bravado.drv";
#endif
#define KEY_COLOR_INDEX 5
WORD FAR PASCAL GetProfileHex(LPSTR szApp, LPSTR szEntry, WORD wDef);
static HBRUSH hOverlayBrush; // Overlay brush used to paint window
static RECT rcLastScreen; // Last screen coords of overlay window
static BOOL fOverlayEnabled; // Is overlay showing?
/*========================================================
Low level read/write routines
=========================================================*/
// Write a byte to a PCVideo Chip register
void FAR PASCAL CT_WritePCVideo (int nIndex, int nValue)
{
outp (wPCVideoAddress, nIndex);
outp (wPCVideoAddress + 1, nValue);
}
// Read a byte from a PC Video chip register
int FAR PASCAL CT_ReadPCVideo (int nIndex)
{
outp (wPCVideoAddress, nIndex);
return (inp (wPCVideoAddress + 1));
}
/*========================================================
Initialization and Fini
=========================================================*/
// Initialization routine called only once at driver load time.
// Returns TRUE on success
BOOL FAR PASCAL CT_Init ()
{
WORD wRet;
WORD wLuma;
#pragma message("Try reducing luma bandwidth!!!")
wLuma = GetProfileHex(gszDriverName, "9051Reg6", 0x6c );
#ifdef _BRAVADO
VW_SetConfigBuf (&VWConfigBuf);
VW_SetDefaultConfiguration (0);
CT_SetPortAddress (wPCVideoAddress);
wRet = (VW_Init (0) == 1); // returns 1 on success
VW_Set9051Reg (6, wLuma); // Lower luma bandwidth to reduce noise!!!
#endif
#ifdef _VBLASTER
wRet = vbcInitialize ();
vbcSetRegister (0x8a06, (BYTE) wLuma);
#endif
if (wRet) {
wPCVideoAddress = CT_GetPortAddress ();
// Create the overlay brush
hOverlayBrush = CT_SetKeyColor ();
CT_OverlayEnable (FALSE); // Initially disable the overlay
CT_Acquire (FALSE); // Turn off acquisition so we can test memory
}
return wRet;
}
// Called during shutdown of the driver.
void FAR PASCAL CT_Fini ()
{
if (hOverlayBrush) {
DeleteObject (hOverlayBrush);
hOverlayBrush = NULL;
}
#ifdef _BRAVADO
VW_CleanUp ();
#endif
#ifdef _VBLASTER
vbcExit ();
#endif
}
/*========================================================
Ports and addresses
=========================================================*/
// Set the Base I/O port used by the device
void FAR PASCAL CT_SetPortAddress (int nPort)
{
#ifdef _BRAVADO
VW_SetIOAddr (nPort);
#endif
#ifdef _VBLASTER
PCV_SetPortAddress (nPort); // This doesn't work!!!
#endif
wPCVideoAddress = CT_GetPortAddress ();
}
// Get the Base I/O port used by the device
int FAR PASCAL CT_GetPortAddress ()
{
#ifdef _BRAVADO
return VW_GetIOAddr ();
#endif
#ifdef _VBLASTER
// VBlaster uses the address set in the Creative Labs setup app.
return vbcGetPortAddress ();
#endif
}
// Get Linear memory address of frame buffer
// Returns value in the range 1 to 15 (meg)
int FAR PASCAL CT_GetFrameAddress ()
{
#ifdef _BRAVADO
return VW_GetVidAddr ();
#endif
#ifdef _VBLASTER
return vbcGetVideoAddress ();
#endif
}
// Set Linear memory address of frame buffer
// nVidAddr is linear address div. 0x100000 (ie. 1-15)
int FAR PASCAL CT_SetFrameAddress (int nVidAddr)
{
#ifdef _BRAVADO
return VW_SetVidAddr (nVidAddr);
#endif
#ifdef _VBLASTER
return vbcSetVideoAddress (nVidAddr);
#endif
}
/*========================================================
Configuration
=========================================================*/
// Load configuration from a file.
// Returns TRUE on success, FALSE on failure
BOOL FAR PASCAL CT_LoadConfiguration (LPSTR lpszFile)
{
#ifdef _BRAVADO
return (VW_LoadConfiguration (lpszFile));
#endif
#ifdef _VBLASTER
return vbcLoadConfiguration (); // Does not support file name!!!
#endif
}
// Save configuration to a file.
// Returns TRUE on success, FALSE on failure
BOOL FAR PASCAL CT_SaveConfiguration (LPSTR lpszFile)
{
#ifdef _BRAVADO
return (VW_SaveConfiguration (lpszFile));
#endif
#ifdef _VBLASTER
return vbcSaveConfiguration (); // Does not support file name!!!
#endif
}
// Set the video source
// nSource ranges from 0 to ...
void FAR PASCAL CT_SetVideoSource (int nSource)
{
#ifdef _BRAVADO
VW_SetVidSource (nSource);
#endif
#ifdef _VBLASTER
vbcSetVideoSource ((WORD) nSource);
#endif
}
// Get the number of video input channels available.
int FAR PASCAL CT_GetVideoChannelCount (void)
{
#ifdef _BRAVADO
return 3; // Some cables only have 1 input, but always allow 3
#endif
#ifdef _VBLASTER
return 3;
#endif
}
// Set the video standard
// 0 = NTSC, 1 = PAL
void FAR PASCAL CT_SetVideoStandard (int nStandard)
{
#ifdef _BRAVADO
VW_SetVidStandard (nStandard == 0 ? 1 : 0);
#endif
#ifdef _VBLASTER
vbcSetInputFormat (nStandard == 0 ? CF_NTSC : CF_PAL);
#endif
}
// Return TRUE if the device can accept SVideo
BOOL FAR PASCAL CT_HasSVideo ()
{
#ifdef _BRAVADO
return TRUE;
#endif
#ifdef _VBLASTER
return FALSE;
#endif
}
// Set the selected input channel format to:
// 0 = composite
// 1 = SVideo
// 2 = RGB (someday?)
BOOL FAR PASCAL CT_SetVideoCableFormat (int nInputMode)
{
#ifdef _BRAVADO
VW_SetSVid (nInputMode);
return TRUE;
#endif
#ifdef _VBLASTER
return FALSE; // Can't do SVideo
#endif
}
// Set the Color control registers
// nVal on input ranges from 0 to 0x3f
void FAR PASCAL CT_SetColor(int nReg, int nVal)
{
#ifdef _BRAVADO
// All Bravado values EXCEPT hue range 0-0x3f, hue goes from 0-0xff
if (nReg == 0)
nVal *= 4;
VW_SetColor (nReg, nVal);
#endif
#ifdef _VBLASTER
// All Video Blaster color values range 0-0xff
nVal *= 4;
switch (nReg) {
case CT_COLOR_HUE: nReg = 3; break;
case CT_COLOR_BRIGHTNESS: nReg = 0; break;
case CT_COLOR_SAT: nReg = 1; break;
case CT_COLOR_CONTRAST: nReg = 2; break;
}
vbcSetColor (nReg, (BYTE) nVal);
#endif
}
/*========================================================
Rectangles
=========================================================*/
// Create and Position the overlay window
void FAR PASCAL CT_SetDisplayRect (LPRECT lpRectangle)
{
RECT rR = *lpRectangle;
OffsetRect (&rR, rcLastScreen.left, rcLastScreen.top);
#ifdef _BRAVADO
VW_SetVidWindow (rR.left, rR.top, WidthRect(rR), HeightRect(rR), 1);
#endif
#ifdef _VBLASTER
vbcCreateWindow (rR.left, rR.top, WidthRect(rR), HeightRect(rR), 1);
#endif
}
void FAR PASCAL CT_SetPanAndScroll (LPRECT lpRectangle)
{
RECT rR = *lpRectangle;
#ifdef _BRAVADO
VW_SetVidPan (rR.left, rR.top);
#endif
#ifdef _VBLASTER
vbcPanWindow (rR.left, rR.top);
#endif
}
/*========================================================
Overlay keying and Painting
=========================================================*/
// Set the overlay key color
// Returns a brush which is used to paint the key color
HBRUSH FAR PASCAL CT_SetKeyColor ()
{
#ifdef _BRAVADO
{
HWND hWnd;
HDC hDC;
int iColors;
hWnd = GetDesktopWindow ();
hDC = GetDC (hWnd);
iColors = GetDeviceCaps (hDC, NUMCOLORS);
ReleaseDC (hWnd, hDC);
// Bravado16 only uses high byte for key, so create a special brush
if (iColors > 256) {
COLORREF cref = RGB (0x7f, 0, 0x7f);
VW_SetRGBKeyColor (cref);
return (CreateSolidBrush (cref));
}
else {
VW_SetKeyColor (KEY_COLOR_INDEX);
return (CreateSolidBrush (PALETTEINDEX (KEY_COLOR_INDEX)));
}
hDC = GetDC (hWnd);
}
#endif
#ifdef _VBLASTER
vbcSetColorKey ((WORD) KEY_COLOR_INDEX);
return (CreateSolidBrush (PALETTEINDEX (KEY_COLOR_INDEX)));
#endif
}
// Turn overlay display on or off
void FAR PASCAL CT_OverlayEnable (BOOL fDisplay)
{
fOverlayEnabled = fDisplay;
#ifdef _BRAVADO
VW_SetVidShow (fDisplay);
#endif
#ifdef _VBLASTER
if (fDisplay)
vbcEnableVideo ();
else
vbcDisableVideo ();
#endif
}
// Update the overlay window rectangle and paint the key color
void FAR PASCAL CT_Update (HWND hWnd, HDC hDC)
{
RECT rcScreen, rcClient;
HBRUSH hbrOld;
rcScreen = grcDestExtOut;
rcScreen.right = rcScreen.left + gwWidth -1;
rcScreen.bottom = rcScreen.top + gwHeight -1;
#ifdef _BRAVADO
if (!EqualRect (&rcScreen, &rcLastScreen)) {
VW_SetVidWindow (rcScreen.left, rcScreen.top,
WidthRect(rcScreen), HeightRect(rcScreen), 1);
}
#endif
#ifdef _VBLASTER
if (!EqualRect (&rcScreen, &rcLastScreen)) {
vbcSetWindowPosition (rcScreen.left, rcScreen.top);
vbcSetWindowSize (WidthRect(rcScreen), HeightRect(rcScreen), 1);
}
#endif
CT_SetPanAndScroll (&grcSourceExtOut);
// Paint the key color into grcDestExtOut (which is in screen coords)
rcClient = grcDestExtOut;
ScreenToClient (hWnd, (LPPOINT) &rcClient);
ScreenToClient (hWnd, (LPPOINT) &rcClient+1);
hbrOld = SelectObject (hDC, hOverlayBrush);
PatBlt (hDC, rcClient.left, rcClient.top,
rcClient.right - rcClient.left,
rcClient.bottom - rcClient.top,
PATCOPY);
SelectObject (hDC, hbrOld);
rcLastScreen = rcScreen;
}
/*========================================================
Image acquistion and grabbing
=========================================================*/
// Turn acquisition of images into frame buffer on or off
// Not interrupt callable, since it enters the client DLL.
void FAR PASCAL CT_Acquire (BOOL fAcquire)
{
#ifdef _BRAVADO
VW_SetFreezeVid (fAcquire ? 0 : 1); // Backwards
#endif
#ifdef _VBLASTER
if (fAcquire)
vbcUnFreezeVideo ();
else
vbcFreezeVideo ();
#endif
}
// This routine is interrupt callable, and bypasses
// the client DLL.
void FAR PASCAL CT_PrivateAcquire (BOOL fAcquire)
{
CT_WritePCVideo (0x20, ((CT_ReadPCVideo (0x20) & 0xfe)
| (fAcquire ? 1 : 0)));
// On a FREEZE, wait for acquisition to complete
// otherwise PCVIDEO asserts the READY line for 20mS.
// when the first video memory read occurs!!!
// This behavior violates PC bus specs.
if (!fAcquire)
while (CT_ReadPCVideo (0x20) & 1);
}
// Capture a single frame
// Return frozen
void FAR PASCAL CT_GrabFrame (void)
{
CT_Acquire (TRUE);
CT_WaitVSync (0); // Wait Even
CT_WaitVSync (1); // Wait Odd
CT_Acquire (FALSE);
}
/*========================================================
Interrupts and Sync
=========================================================*/
// Set the IRQ used by the device.
// Returns the IRQ actually set.
int FAR PASCAL CT_SetIRQUsed (int nIRQ)
{
#ifdef _BRAVADO
return 9; // only 9 is available from this card
#endif
#ifdef _VBLASTER
{
int nTemp;
switch (nIRQ) {
case 5: nTemp = 1; break;
case 10: nTemp = 2; break;
case 11: nTemp = 4; break;
case 12: nTemp = 8; break;
default: return (CT_GetIRQUsed ()); // illegal value, return default
}
CT_WritePCVideo (0x82, nTemp);
return nIRQ;
}
#endif
}
// Returns the IRQ used by the device
int FAR PASCAL CT_GetIRQUsed ()
{
#ifdef _BRAVADO
return 9; // only 9 is available from this card
#endif
#ifdef _VBLASTER
return vbcGetIntrNo();
#endif
}
#define EVEN_VSYNC_INTERRUPT 0x01
#define ODD_VSYNC_INTERRUPT 0x02
// Enable the PCVideo chip to create odd and even interrupts
void FAR PASCAL CT_IRQEnable (void)
{
#if FRAME_INTERRUPT
CT_WritePCVideo (0x09, EVEN_VSYNC_INTERRUPT);
#else
CT_WritePCVideo (0x09, EVEN_VSYNC_INTERRUPT | ODD_VSYNC_INTERRUPT);
#endif
}
void FAR PASCAL CT_IRQDisable (void)
{
CT_WritePCVideo (0x09, 0); // Disable Interrupts
}
// Clear PCVideo chip interrupts
void FAR PASCAL CT_IRQClear (void)
{
CT_WritePCVideo (0x09, 0); // Clear the interrupt
#if FRAME_INTERRUPT
CT_WritePCVideo (0x09, EVEN_VSYNC_INTERRUPT); // Re-enable it
#else
CT_WritePCVideo (0x09, ODD_VSYNC_INTERRUPT | EVEN_VSYNC_INTERRUPT); // Re-enable it
#endif
}
// Wait for Vertical Sync
// nSync = 0, wait even
// nSync = 1, wait odd
// nSync = 2, wait either
void FAR PASCAL CT_WaitVSync (int nSync)
{
WORD wRegVal;
BOOL bOdd;
DWORD dwStartTime = timeGetTime();
while (timeGetTime () - dwStartTime < 33) {
wRegVal = CT_ReadPCVideo (9);
bOdd = wRegVal & 0x08;
if (wRegVal & 0x04) { // if VSync
if ((nSync == 2) ||
((nSync == 1) && bOdd) ||
((nSync == 0) && !bOdd))
break;
}
}
}