/*----------------------------------------------------------------


                   Copyright (c) IBM Corporation 1981, 1992
                             All Rights Reserved

  SOURCE FILE NAME:  SWVRCAPT.C


  DESCRIPTION:

 This module contains the ring 3 logic for controlling video capture
 hardware.  This logic will migrate into MCD's for video capture hardware.

 ----------------------------------------------------------------------*/

#define INCL_DOS
#define INCL_GPI
#define INCL_DOSMEMMGR
#include <os2.h>
#include <os2me.h>
#include <stdlib.h>
#include <stdio.h>
#include <vidvci.h>   /* Capture device driver info structure */

#include <vsdcmds.h>   // Command interfcae for Video VSD
#include <swvridll.h>
#include <string.h>
#define INCL_DBCSCRT_NOSTRINGS
//#include <mmiocrt.h>                /* 7/xx/92 Other DBCS string manip. not in C/2...PJR */
#include <rgbconv.h>                /* RBG conversion Routines             */
#include <pcvideo.h>
#include <vsdini.h>

extern HVSD_INSTANCE * HVSD_LIST[MAX_NUM_HVSDS]; // List of Valid HVSDs
extern PDD_INSTANCE  PDD_Info[MAX_NUM_PDDS]  ; // List of Active PDDs
extern BYTE            The784Palette[256][3];    // Pallet RGB24 values

//DWORD dBank_RO;                  // Offset to Bank Register Offset (different

// INI File Stuff
CHAR    pszINIFile[260];

BYTE   SviaTable_bank[240];
USHORT SviaTable_b_offset[240];

#define  x_res  640              // bytes in X cord SVIA scanline

// local function prototypes
VOID GetSviaBank ( BYTE scanline, USHORT xres, BYTE *bank, USHORT *b_offset);
VOID BuildSviaTable (USHORT xres);
ULONG vsdOPEN (PVOID pRequest);
ULONG vsdCLOSE (HVSD_INSTANCE * hVSD);
ULONG vsdCaptureImage(HVSD_INSTANCE * hVSD, PVOID pRequest);
ULONG vsdGetDevCaps(HVSD_INSTANCE * hVSD, PVOID pRequest);
ULONG vsdSET (HVSD_INSTANCE * hVSD, ULONG ulSubFunc, PVOID pRequest);
ULONG vsdQUERY (HVSD_INSTANCE * hVSD, ULONG ulSubFunc, PVOID pRequest);
ULONG vsdSetVideoAttributes   (HVSD_INSTANCE * hVSD, PVOID pRequest);
ULONG vsdSetVideoRect         (HVSD_INSTANCE * hVSD, PVOID pRequest);
ULONG vsdSetImageFormat       (HVSD_INSTANCE * hVSD, PVOID pRequest);
ULONG vsdSetFPS               (HVSD_INSTANCE * hVSD, PVOID pRequest);
ULONG vsdSetColorKey          (HVSD_INSTANCE * hVSD, PVOID pRequest);
ULONG vsdSetTransparentColor  (HVSD_INSTANCE * hVSD, PVOID pRequest);
ULONG vsdSetViewPort          (HVSD_INSTANCE * hVSD, PVOID pRequest);
ULONG vsdQueryVideoAttributes (HVSD_INSTANCE * hVSD, PVOID pRequest);
ULONG vsdQueryVideoRect       (HVSD_INSTANCE * hVSD, PVOID pRequest);
ULONG vsdQueryImageFormat     (HVSD_INSTANCE * hVSD, PVOID pRequest);
ULONG vsdQueryFPS             (HVSD_INSTANCE * hVSD, PVOID pRequest);
ULONG vsdQueryIExtents        (HVSD_INSTANCE * hVSD, PVOID pRequest);
ULONG vsdQueryVExtents        (HVSD_INSTANCE * hVSD, PVOID pRequest);
ULONG vsdQueryOExtents        (HVSD_INSTANCE * hVSD, PVOID pRequest);
ULONG vsdQueryPRODINFO        (HVSD_INSTANCE * hVSD, PVOID pRequest);
ULONG vsdQueryTransparentColor(HVSD_INSTANCE * hVSD, PVOID pRequest);
ULONG vsdQueryColorKey        (HVSD_INSTANCE * hVSD, PVOID pRequest);
ULONG vsdQueryViewPort        (HVSD_INSTANCE * hVSD, PVOID pRequest);
ULONG vsdFreeze(HVSD_INSTANCE * hVSD, ULONG ulSubFunc);
ULONG vsdRestore(HVSD_INSTANCE * hVSD);
ULONG vsdSave(HVSD_INSTANCE * hVSD);
ULONG FreezeImage(HVSD_INSTANCE * hVSD);
ULONG UnfreezeImage(HVSD_INSTANCE * hVSD);
ULONG Read_INI(PSZ, PVOID *, ULONG *, HFILE *);
BOOL  Valid_HVSD (HVSD hVSD, HVSD_INSTANCE ** phVSD);
BOOL  Valid_ParmBlock (PVOID pRequest);
BOOL  Valid_IFormat (HVSD_INSTANCE * phVSD, VSD_SETIMAGEFORMAT_PARMS * SetFormat);
BOOL  Add_HVSD (HVSD_INSTANCE * pHVSD, ULONG * Index);
BOOL  Remove_PDD (PSZ PDD_NAME, ULONG * Count);
BOOL  Add_PDD (PSZ PDD_NAME, ULONG * Count);
ULONG VCA_LoadConfiguration (PSZ, PVOID *, ULONG *, HFILE  *);
ULONG SVIA_LoadConfiguration(PSZ, PVOID *, ULONG *, HFILE  *);
ULONG QVIA_LoadConfiguration(PSZ, PVOID *, ULONG *, HFILE  *);

ULONG VSD_Entry(HVSD hVSD, ULONG ulFunc, ULONG ulSubFunc, PVOID pRequest)
{
ULONG ulRC;
HVSD_INSTANCE * phVSD;
ULONG stop;

 ulRC = VSDERR_SUCCESS;                                   /* Assume good return code  */

 /* Does This Function Require A valid HVSD? if so validate the HVSD */
 switch (ulFunc) {
    case  VSD_OPEN:
       break;
    case  VSD_QUERYPRODINFO:
       break;
    default:                                              /* Valid HVSD is Requires */
       if (!Valid_HVSD(hVSD, &phVSD)) {                   /* Is this a Valid HVSD?  */
          return VSDERR_INVALID_HVSD;                     /* If Not Return Error    */
       } /* endif */
       break ;
    } /* endswitch */

 /* Does This Function Require A valid Parm Block? if so validate  */
 switch (ulFunc) {
    case  VSD_CLOSE:
       break;
    case VSD_SAVE:
       break;
    case VSD_RESTORE:
       break;
    case  VSD_USER:
       break;
    case  VSD_FREEZE:
       break;
    default:                               /* Check for Valid Parm Block Addr */
       if (!Valid_ParmBlock(pRequest)) {   /* Is this a Valid Address & Length*/
          return VSDERR_INVALID_BUFF;      /* If Not Return Error             */
       } /* endif */
       break ;
    } /* endswitch */

 switch (ulFunc) {
    case  VSD_DEVUNITS:
       break;
    case  VSD_QUERYPRODINFO:
       ulRC=vsdQueryPRODINFO(hVSD, pRequest);
       break;
    case VSD_OPEN:
       ulRC =vsdOPEN (pRequest);
       break;
    case  VSD_CLOSE:
       ulRC = vsdCLOSE(phVSD);
       break;
    case  VSD_RESOUCRCE:
       break;
    case VSD_SAVE:
       ulRC = vsdSave(phVSD);
       break;
    case VSD_RESTORE:
       ulRC = vsdRestore (phVSD);
       break;
    case  VSD_GETDEVCAPS:
       ulRC=vsdGetDevCaps(phVSD, pRequest);
       break;
    case  VSD_ESCAPE:
       break;
    case  VSD_RECORD:
       break;
    case  VSD_READ:
       break;
    case  VSD_LOAD:
       break;
    case  VSD_RESET:
       break;
    case  VSD_CAPTUREIMAGE:
       ulRC=vsdCaptureImage(phVSD, pRequest);
       break;
    case  VSD_RESTOREIMAGE:
       break;
    case  VSD_FREEZE:
       ulRC = vsdFreeze(phVSD, ulSubFunc);
       break;
    case VSD_SET:
       ulRC = vsdSET(phVSD, ulSubFunc, pRequest);
       break;
    case  VSD_QUERY:
       ulRC = vsdQUERY(phVSD, ulSubFunc, pRequest);
       break;
    case  VSD_USER:
       break;
    default:                                /* UNKNOWN Command/Function Code */
       ulRC = VSDERR_UNSUPPORTED_COMMAND;
       break ;
   } /* endswitch */

   if (ulRC != VSDERR_SUCCESS) {
      stop = 1;
   } /* endif */
   return ulRC;
}

ULONG vsdFreeze(HVSD_INSTANCE * phVSD, ULONG ulSubFunc)
{
ULONG ulRC;

 switch (ulSubFunc) {
    case  VSD_FREEZE_ENABLE:
       ulRC=FreezeImage(phVSD);
       break;
    case  VSD_FREEZE_DISABLE:
       ulRC=UnfreezeImage(phVSD);
       break;
    default:                                /* UNKNOWN Command/Function Code */
       ulRC = VSDERR_UNSUPPORTED_COMMAND;
       break ;
   } /* endswitch */

   return ulRC;
}


ULONG vsdQUERY(HVSD_INSTANCE * phVSD, ULONG ulSubFunc, PVOID pRequest)
{
ULONG ulRC;

 ulRC = VSDERR_SUCCESS;                                   /* Assume good return code  */

 switch (ulSubFunc) {
    case  VSD_QUERYVIDEOATTRIBUTES:
       ulRC=vsdQueryVideoAttributes(phVSD, pRequest);
       break;
    case  VSD_QUERYVIDEORECT:
       ulRC=vsdQueryVideoRect(phVSD, pRequest);
       break;
    case  VSD_QUERYIMAGEFORMAT:
       ulRC=vsdQueryImageFormat(phVSD, pRequest);
       break;
    case  VSD_QUERYFPS:
       ulRC=vsdQueryFPS(phVSD, pRequest);
       break;
    case  VSD_QUERYIMAGEEXTENTS:
       ulRC=vsdQueryIExtents(phVSD, pRequest);
       break;
    case  VSD_QUERYVIDEOEXTENTS:
       ulRC=vsdQueryVExtents(phVSD, pRequest);
       break;
    case  VSD_QUERYOVERLAYEXTENTS:
       ulRC=vsdQueryOExtents(phVSD, pRequest);
       break;
    case  VSD_QUERYTRANSPARENTCOLOR:
       ulRC=vsdQueryTransparentColor(phVSD, pRequest);
       break;
    case  VSD_QUERYCOLORKEYING:
       ulRC=vsdQueryColorKey(phVSD, pRequest);
       break;
    case  VSD_QUERYVIEWPORT:
       ulRC=vsdQueryViewPort(phVSD, pRequest);
       break;
    default:                                /* UNKNOWN Command/Function Code */
       ulRC = VSDERR_UNSUPPORTED_COMMAND;
       break ;
   } /* endswitch */

   return ulRC;
}

ULONG vsdSET(HVSD_INSTANCE * phVSD, ULONG ulSubFunc, PVOID pRequest)
{
ULONG ulRC;

 ulRC = VSDERR_SUCCESS;                                   /* Assume good return code  */

 switch (ulSubFunc) {
    case  VSD_SETVIDEOATTRIBUTES:
       ulRC=vsdSetVideoAttributes(phVSD, pRequest);
       break;
    case  VSD_SETVIDEORECT:
       ulRC=vsdSetVideoRect(phVSD, pRequest);
       break;
    case  VSD_SETIMAGEFORMAT:
       ulRC=vsdSetImageFormat(phVSD, pRequest);
       break;
    case  VSD_SETFPS:
       ulRC=vsdSetFPS(phVSD, pRequest);
       break;
    case  VSD_SETTRANSPARENTCOLOR:
       ulRC=vsdSetTransparentColor(phVSD, pRequest);
       break;
    case  VSD_SETCOLORKEYING:
       ulRC=vsdSetColorKey(phVSD, pRequest);
       break;
    case  VSD_SETVIEWPORT:
       ulRC=vsdSetViewPort(phVSD, pRequest);
       break;
    default:                                /* UNKNOWN Command/Function Code */
       ulRC = VSDERR_UNSUPPORTED_COMMAND;
       break ;
   } /* endswitch */

   return ulRC;
}

int Main( )
{
 return 0;
}

/*----------------------------------------------------------------------
 vsdSetVideoAttributes

 Set Video adjustments on the device
 ----------------------------------------------------------------------*/

ULONG vsdSetVideoAttributes(HVSD_INSTANCE * phVSD, PVOID pRequest)
{
 VCASETVIDEO vcaset;
 VSD_VIDEOATTRIBUTES_PARMS * SetVideo;                    // Set Video Attrubutes packet
 ULONG BytesRead = 0;
 ULONG ulRC;

 SetVideo = (VSD_VIDEOATTRIBUTES_PARMS *)pRequest;        // Point to Set Video Attributes packet


 // Adjust Brightness
 switch (SetVideo->ulBrightness) {
    case  SETVIDEO_NoChange:                                      // No Change
       break;
    case  SETVIDEO_ToDefault:                                     // Set To Default
       phVSD->VIDEOATTRIB.ulBrightness = phVSD->VIDEOATTRIB_Defaults.ulBrightness;
       break;
    default:                                                      // Set to New Value
       phVSD->VIDEOATTRIB.ulBrightness = SetVideo->ulBrightness;
       break ;
   } /* endswitch */

 // Adjust Hue?
 switch (SetVideo->ulHue) {
    case  SETVIDEO_NoChange:                                      // No Change
       break;
    case  SETVIDEO_ToDefault:                                     // Set To Default
       phVSD->VIDEOATTRIB.ulHue = phVSD->VIDEOATTRIB_Defaults.ulHue;
       break;
    default:                                                      // Set to New Value
       phVSD->VIDEOATTRIB.ulHue = SetVideo->ulHue;
       break ;
   } /* endswitch */

 // Adjust Satuartion?
 switch (SetVideo->ulSaturation) {
    case  SETVIDEO_NoChange:                                      // No Change
       break;
    case  SETVIDEO_ToDefault:                                     // Set To Default
       phVSD->VIDEOATTRIB.ulSaturation = phVSD->VIDEOATTRIB_Defaults.ulSaturation;
       break;
    default:                                                      // Set to New Value
       phVSD->VIDEOATTRIB.ulSaturation =  SetVideo->ulSaturation;
       break ;
   } /* endswitch */

 // Adjust Contrast?
 switch (SetVideo->ulContrast) {
    case  SETVIDEO_NoChange:                                      // No Change
       break;
    case  SETVIDEO_ToDefault:                                     // Set To Default
       phVSD->VIDEOATTRIB.ulContrast = phVSD->VIDEOATTRIB_Defaults.ulContrast;
       break;
    default:                                                      // Set to New Value
       phVSD->VIDEOATTRIB.ulContrast = SetVideo->ulContrast;
       break ;
   } /* endswitch */


 // If hVSD is currently active tell the PDD
 if (phVSD->ulState == VSD_ulState_Restored) {

    // Build Set Video Request packet for the PDD
    vcaset.set_brightness = phVSD->VIDEOATTRIB.ulBrightness;
    vcaset.set_hue        = phVSD->VIDEOATTRIB.ulHue;
    vcaset.set_saturation = phVSD->VIDEOATTRIB.ulSaturation;
    vcaset.set_contrast   = phVSD->VIDEOATTRIB.ulContrast;

    // Send Set Video Packet to the PDD
    ulRC = DosDevIOCtl(phVSD->CaptureDevHandle,  // device handle
                      (ULONG) 140,               // category
                      (ULONG) 0x75,              // function
                      0,                         // parm list  ???
                      0,                         // parm length max
                      0,                         // parm length in/out
                      &vcaset,                   // function data area
                      sizeof (VCASETVIDEO),      // data area size
                      &BytesRead);               // data area size !!!

     // Did the Device Driver Accept the command?
     if (ulRC) {
        return VSDERR_DEVICE_REJECTED;
     } /* endif */


 } /* endif */

   return VSDERR_SUCCESS;
}

/*----------------------------------------------------------------------
 vsdSetVideoRect

 Set Video Rectangles portion/size of source from capture card and size of
 destination rectangle. Size and portion of the Image to be captured
 The Destination Rectangle values for X_Left and  Y_Top are only used by
 overlay cards, they tell the overlay card where to start the video
 on the computer monitor (note: 0,0 is the top left of the screen).
 ----------------------------------------------------------------------*/

ULONG vsdSetVideoRect(HVSD_INSTANCE * phVSD, PVOID pRequest)
{
 VSD_VIDEORECT_PARMS * SetVideo;                 // Set Video Rectangles packet
 ULONG ulRC;
 ULONG rc;
 ULONG ReturnSize = 0;                           // Size of Data Returned
 VCACAPISIZE       info; // OLD WAY!!!!!         // Info image postion/scale
 VCASETCAPTURERECT info2;                        // Info image postion/scale

 SetVideo = (VSD_VIDEORECT_PARMS *)pRequest;     // Point to Set Video Rectangle packet

/* Stop Devide By Zero if bad value is passed in */
if ((SetVideo->irectSource.X_width  == 0)|
    (SetVideo->irectDest.X_width    == 0)|
    (SetVideo->irectSource.Y_height == 0)|
    (SetVideo->irectDest.Y_height   == 0)) {
 {
 return VSDERR_OUTOFRANGE;
 }
} /* endif */

/* Is the Source Rectange in the Valid Range */
if (( SetVideo->irectSource.X_left    > (phVSD->VExtents.ulX_Extent - 8)) |
    ( SetVideo->irectSource.Y_top     > (phVSD->VExtents.ulY_Extent - 8)) |
    ((SetVideo->irectSource.X_width  +  SetVideo->irectSource.X_left)  > phVSD->VExtents.ulX_Extent) |
    ((SetVideo->irectSource.Y_height +  SetVideo->irectSource.Y_top )  > phVSD->VExtents.ulY_Extent) ) {
    {
    return VSDERR_OUTOFRANGE;
    }
} /* endif */


/* Is the Destination Rectange in the Valid Range */
if (( SetVideo->irectDest.X_left    > (phVSD->IExtents.ulX_Extent - 8)) |
    ( SetVideo->irectDest.Y_top     > (phVSD->IExtents.ulY_Extent - 8)) |
    ((SetVideo->irectDest.X_width  +  SetVideo->irectDest.X_left)  > phVSD->IExtents.ulX_Extent) |
    ((SetVideo->irectDest.Y_height +  SetVideo->irectDest.Y_top )  > phVSD->IExtents.ulY_Extent) )  {
    {
    return VSDERR_OUTOFRANGE;
    }
} /* endif */
/* Is this an Overlay if not size must be on 4/4 boundary */
if (phVSD->DC.bSupports[DC_HASVIEWPORT] = FALSE) {
   /* Output Size must be a multiple of 4 in X and Y */
   if (((SetVideo->irectDest.X_width  % 4) != 0) |
       ((SetVideo->irectDest.Y_height % 4) != 0 ))  {
       {
       return VSDERR_OUTOFRANGE;
       }
   } /* endif */
} /* endif */

/* Does the card support distoring */
if (phVSD->DC.bSupports[DC_CANDISTORT]==FALSE) {
   /* Card does not support strecting X and Y must be scaled the same */
   if (( (SetVideo->irectSource.X_width/SetVideo->irectDest.X_width) !=
         (SetVideo->irectSource.Y_height/SetVideo->irectDest.Y_height)) |
        ((SetVideo->irectSource.X_width%SetVideo->irectDest.X_width)   != 0) |
        ((SetVideo->irectSource.Y_height%SetVideo->irectDest.Y_height) != 0)){
    {
    return VSDERR_OUTOFRANGE;
    }
   } /* endif */
} /* endif */

/* Save Video Rectangle info in the HVSD Instance info structure */
phVSD->SourceRect.X_left    = SetVideo->irectSource.X_left;
phVSD->SourceRect.Y_top     = SetVideo->irectSource.Y_top;
phVSD->SourceRect.X_width   = SetVideo->irectSource.X_width;
phVSD->SourceRect.Y_height  = SetVideo->irectSource.Y_height;
phVSD->DestRect.X_left      = SetVideo->irectDest.X_left;
phVSD->DestRect.Y_top       = SetVideo->irectDest.Y_top;
phVSD->DestRect.X_width     = SetVideo->irectDest.X_width;
phVSD->DestRect.Y_height    = SetVideo->irectDest.Y_height;
phVSD->ulScaleFactor        = SetVideo->irectSource.X_width/SetVideo->irectDest.X_width;

// If hVSD is currently active tell the PDD the new Image Info
if (phVSD->ulState == VSD_ulState_Restored) {

   info.X_Left      =  phVSD->SourceRect.X_left;
   info.Y_Top       =  phVSD->SourceRect.Y_top;
   info.Y_Height    =  phVSD->SourceRect.Y_height;
   info.X_Width     =  phVSD->SourceRect.X_width;
   info.ScaleFactor =  phVSD->ulScaleFactor;

   // Set up the size/postion/scale of image to capture from the video capture board
   ulRC = DosDevIOCtl(phVSD->CaptureDevHandle,   // device handle
                    (ULONG) 140,                // category
                    (ULONG) 0x6E,               // function
                    0,                          // parm list
                    0,                          // parm length max
                    0,                          // parm length in/out
                    &info,                      // function data area
                    sizeof (info),              // data area size
                    &ReturnSize);               // data area size returned

   info2.Source_X_Left    = SetVideo->irectSource.X_left;
   info2.Source_Y_Top     = SetVideo->irectSource.Y_top;
   info2.Source_X_Width   = SetVideo->irectSource.X_width;
   info2.Source_Y_Height  = SetVideo->irectSource.Y_height;
   info2.Dest_X_Left      = SetVideo->irectDest.X_left;
   info2.Dest_Y_Top       = SetVideo->irectDest.Y_top;
   info2.Dest_X_Width     = SetVideo->irectDest.X_width;
   info2.Dest_Y_Height    = SetVideo->irectDest.Y_height;

   // Set up the size/postion/scale of image to capture from the video capture board
   rc = DosDevIOCtl(phVSD->CaptureDevHandle,   // device handle
                  (ULONG) 140,                // category
                  (ULONG) VCAI_SETCAPTRECT,   // function
                  0,                          // parm list
                  0,                          // parm length max
                  0,                          // parm length in/out
                  &info2,                     // function data area
                  sizeof (info2),             // data area size
                  &ReturnSize);               // data area size returned

   if ((rc != 0) & (ulRC != 0)) {
      return 1;  // Error = Addressability IOCTL Failed
   } /* endif */

} /* endif */

return VSDERR_SUCCESS;
}

/*----------------------------------------------------------------------
 vsdSetImageFormat

 Set Image Data Format to one of the supported formats
 This will be the format of the image data returned on VSD_CaptureImage
 ----------------------------------------------------------------------*/

ULONG vsdSetImageFormat(HVSD_INSTANCE * phVSD, PVOID pRequest)
{
 VSD_SETIMAGEFORMAT_PARMS * SetFormat;               // Set Image Data Format packet
 ULONG ulRC;

 SetFormat = (VSD_SETIMAGEFORMAT_PARMS *)pRequest;   // Point to Set Image Format packet


// Is request for a Valid Image Format
if (!Valid_IFormat(phVSD, SetFormat))
    return  VSDERR_INVALID_INPUT;


/* Switch to/mark new Format                                  */
phVSD->ulImageFormat                        = SetFormat->SetFormat.ulFormat;
phVSD->usBitsPerPEL                         = SetFormat->SetFormat.usBitsPerPEL;
phVSD->pImg_Formats->CurFormat.ulFormat     = SetFormat->SetFormat.ulFormat;
phVSD->pImg_Formats->CurFormat.usBitsPerPEL = SetFormat->SetFormat.usBitsPerPEL;

/* if this is an OS/2 Bit Map Format add in size of Header + pallet */
if (SetFormat->SetFormat.ulFormat==VSD_IMAGEFORMAT_OS2_BITMAP2) {
   switch (SetFormat->SetFormat.usBitsPerPEL) {
      case  VSD_BITSPERPEL_8:
         // Add in Bitmap header plud  pallet info
         phVSD->ulImgHSize = sizeof (BITMAPFILEHEADER2) + (sizeof(RGB2) * 256);
         break;

      default:                                              /* Valid HVSD is Requires */
         // Add in Bitmap header with no pallet
         phVSD->ulImgHSize = sizeof (BITMAPFILEHEADER2);
         break ;

      } /* endswitch */
 } else {

      phVSD->ulImgHSize = 0;
 } /* endif */


return VSDERR_SUCCESS;
}

/*----------------------------------------------------------------------
 vsdSetFPS

 Set Frames Per Second for image streaming.
 This set the number of frames to second to send to the Stream Handler once streaming
 is activated by SSM
 ----------------------------------------------------------------------*/

ULONG vsdSetFPS(HVSD_INSTANCE * phVSD, PVOID pRequest)
{
 VSD_SETFPS_PARMS * SetFPS;               // Set Frames Per Second packet
 ULONG ulRC;
 VCASETFPS info;                          // Information on image capture Rate
 ULONG ReturnSize = 0;                    // Size of Data Returned

 SetFPS = (VSD_SETFPS_PARMS *)pRequest;   // Point to Set Frames Pers Second packet

 /* Save Video Rectangle info in the HVSD Instance info structure */
 phVSD->ulFPS        = SetFPS->ulFPS;

// If hVSD is currently active tell the PDD
 if (phVSD->ulState == VSD_ulState_Restored) {
    info.set_FPS     =  phVSD->ulFPS;
    info.resv1       =  0;

    // Set up the size/postion/scale of image to capture from the video capture board
    ulRC = DosDevIOCtl(phVSD->CaptureDevHandle,   // device handle
                     (ULONG) 140,                // category
                     (ULONG) 0x76,               // function
                     0,                          // parm list
                     0,                          // parm length max
                     0,                          // parm length in/out
                     &info,                      // function data area
                     sizeof (info),              // data area size
                     &ReturnSize);               // data area size returned


 } /* endif */


return VSDERR_SUCCESS;
}

/*----------------------------------------------------------------------
 vsdSetTransparentColor

 Set the Transparent Color for the Overlay Card
 The Transparent color when enabled thru VSD_SETCOLORKEY will allow
 video from the capture card to show thru any where the Transparent color
 is present on the Computer Monitor
 ----------------------------------------------------------------------*/

ULONG vsdSetTransparentColor(HVSD_INSTANCE * phVSD, PVOID pRequest)
{
 VSD_TRANSPARENTCOLOR_PARMS * SetTC;      // Set Transparent Color packet
 ULONG ulRC;
 VCASETCOLORKEY info;                     // Information to the PDD
 ULONG ReturnSize = 0;                    // Size of Data Returned

 SetTC = (VSD_TRANSPARENTCOLOR_PARMS *)pRequest; // Point to packet

 /* Save Transparent Color in the HVSD Instance info structure */
 phVSD->ulColor = SetTC->ulTransparentColor;

// If hVSD is currently active tell the PDD
 if (phVSD->ulState == VSD_ulState_Restored) {
    info.ulColorKey  = phVSD->ulColor;

    // Set up the size/postion/scale of image to capture from the video capture board
    ulRC = DosDevIOCtl(phVSD->CaptureDevHandle,   // device handle
                     (ULONG) 140,                // category
                     (ULONG) VCAI_SETCOLORKEY,   // function
                     0,                          // parm list
                     0,                          // parm length max
                     0,                          // parm length in/out
                     &info,                      // function data area
                     sizeof (info),              // data area size
                     &ReturnSize);               // data area size returned


 } /* endif */

return VSDERR_SUCCESS;
}

/*----------------------------------------------------------------------
 vsdSetColorKey

 when enabled it allow video from the Overlay Card to show thru to the
 computer monitor any where the Transparent Color is present.
 The Transparent color is set thru VSD_SETTRANSPARENTCOLOR.
 When the Color Key is disable the Video will alway show thru (cover up
 anything that might be on the screen) if the View Port is Enabled.
 ----------------------------------------------------------------------*/

ULONG vsdSetColorKey (HVSD_INSTANCE * phVSD, PVOID pRequest)
{
 VSD_COLORKEYING_PARMS * SetCK;           // Set Color Keying packet
 ULONG ulRC;
 VCAEDCOLORKEY info;                      // Information to the PDD
 ULONG ReturnSize = 0;                    // Size of Data Returned

 SetCK = (VSD_COLORKEYING_PARMS *)pRequest; // Point to packet

 /* Save Color Keying State in the HVSD Instance info structure */
 phVSD->bColorKeying = SetCK->bColorKeying;

// If hVSD is currently active tell the PDD
 if (phVSD->ulState == VSD_ulState_Restored) {
    info.bColorKeying  = phVSD->bColorKeying;

    // Set up the size/postion/scale of image to capture from the video capture board
    ulRC = DosDevIOCtl(phVSD->CaptureDevHandle,   // device handle
                     (ULONG) 140,                // category
                     (ULONG) VCAI_EDCOLORKEY,   // function
                     0,                          // parm list
                     0,                          // parm length max
                     0,                          // parm length in/out
                     &info,                      // function data area
                     sizeof (info),              // data area size
                     &ReturnSize);               // data area size returned


 } /* endif */


return VSDERR_SUCCESS;
}

/*----------------------------------------------------------------------
 vsdSetViewPort

 Turn on the Overlay Card's overlay function.
 this allow video to show thru to the computer monitor.
 See VSD_SETCOLORKEYING, VSD_SETTRANSPARENTCOLOR and VSD_SETVIDEORECT
 for more details.
 ----------------------------------------------------------------------*/

ULONG vsdSetViewPort (HVSD_INSTANCE * phVSD, PVOID pRequest)
{
 VSD_VIEWPORT_PARMS * SetVP;              // Set View Port packet
 ULONG ulRC;
 VCASETMONITOR info;                      // Information to the PDD
 ULONG ReturnSize = 0;                    // Size of Data Returned

 SetVP = (VSD_VIEWPORT_PARMS *)pRequest; // Point to packet

 /* Save Color Keying State in the HVSD Instance info structure */
 phVSD->bViewPort = SetVP->bViewPort;

// If hVSD is currently active tell the PDD
 if (phVSD->ulState == VSD_ulState_Restored) {
    info.bMonitor    = phVSD->bViewPort;

    // Set up the size/postion/scale of image to capture from the video capture board
    ulRC = DosDevIOCtl(phVSD->CaptureDevHandle,   // device handle
                     (ULONG) 140,                // category
                     (ULONG) VCAI_SETMONITOR,   // function
                     0,                          // parm list
                     0,                          // parm length max
                     0,                          // parm length in/out
                     &info,                      // function data area
                     sizeof (info),              // data area size
                     &ReturnSize);               // data area size returned


 } /* endif */


return VSDERR_SUCCESS;
}


/*----------------------------------------------------------------------
 vsdQueryTransparentColor

 Query the Transparent Color for the Overlay Card
 ----------------------------------------------------------------------*/

ULONG vsdQueryTransparentColor(HVSD_INSTANCE * phVSD, PVOID pRequest)
{
 VSD_TRANSPARENTCOLOR_PARMS * SetTC;      // Set Transparent Color packet

 SetTC = (VSD_TRANSPARENTCOLOR_PARMS *)pRequest; // Point to packet

 /* Get Transparent Color from the HVSD Instance info structure */
 SetTC->ulTransparentColor= phVSD->ulColor;


return VSDERR_SUCCESS;
}

/*----------------------------------------------------------------------
 vsdQuerytColorKey

 Query if Color Keying is enabled
 ----------------------------------------------------------------------*/

ULONG vsdQueryColorKey (HVSD_INSTANCE * phVSD, PVOID pRequest)
{
 VSD_COLORKEYING_PARMS * SetCK;                // Set Color Keying packet
 ULONG ulRC;

 SetCK = (VSD_COLORKEYING_PARMS *)pRequest; // Point to packet

 /* Get Color Keying State from the HVSD Instance info structure */
 SetCK->bColorKeying  = phVSD->bColorKeying;

return VSDERR_SUCCESS;
}

/*----------------------------------------------------------------------
 vsdQueryViewPort

 Query If View Port is enabled
 ----------------------------------------------------------------------*/

ULONG vsdQueryViewPort (HVSD_INSTANCE * phVSD, PVOID pRequest)
{
 VSD_VIEWPORT_PARMS * SetVP;                // Set View Port packet
 ULONG ulRC;

 SetVP = (VSD_VIEWPORT_PARMS *)pRequest; // Point to packet

 /* Save Color Keying State in the HVSD Instance info structure */
 SetVP->bViewPort = phVSD->bViewPort;

return VSDERR_SUCCESS;
}


/*----------------------------------------------------------------------
 vsdQueryPRODINFO

 Query Product Info for VSD and PDD
 ----------------------------------------------------------------------*/

ULONG vsdQueryPRODINFO(HVSD_INSTANCE * hVSD, PVOID pRequest)
{
 VCADEVINFO info;
 VSD_GETPRODINFO_PARMS * ProdInfo;                        // Product Info
 ULONG BytesRead = 0;
 ULONG rc;
 HVSD_INSTANCE * phVSD;
 HVSD_INSTANCE * Curr;                      // Current  HVSD in list

 ProdInfo = (VSD_GETPRODINFO_PARMS *)pRequest;        // Point to Product Info Request


 // Is the Parmater List The Correct Size
 if (ProdInfo->ulLength < sizeof(VSD_GETPRODINFO_PARMS)) {
     return VSDERR_REQUEST_BUF_TOO_SMALL;      // If Not Return Error
 } /* endif */

 if (Valid_HVSD(hVSD, &phVSD)) {               // Is this a Valid HVSD?

    // Build Query For Device Info
    info.Length        = sizeof(VSD_GETPRODINFO_PARMS);

    // Get Device Info from the Device
    rc = DosDevIOCtl(phVSD->CaptureDevHandle,  // device handle
                    (ULONG) 140,               // category
                    (ULONG) 0x6D,              // function
                    0,                         // parm list  ???
                    0,                         // parm length max
                    0,                         // parm length in/out
                    &info,                     // function data area
                    sizeof (VCADEVINFO),       // data area size
                    &BytesRead);               // data area size !!!

    if (rc) {
       return VSDERR_DEVICE_REJECTED;         // Error = device Drive Failed
    } /* endif */

     // Copy in Information About The PDD
     memcpy (ProdInfo->PDD.szProdInfo,    info.ProdInfo, sizeof(info.ProdInfo));
     memcpy (ProdInfo->PDD.szManufacture, info.ManInfo,  sizeof(info.ManInfo ));
     memcpy (ProdInfo->PDD.szVersion,     info.Version,  sizeof(info.Version ));

 /* Only VSD Info Requested/Valid*/
 } else {

    info.Length        = sizeof(VSD_GETPRODINFO_PARMS)- sizeof(VSD_PRODINFO);

 } /* endif */


 // Fill In Info About The VSD
 /*                                123456789012345678901234567890 */
 ProdInfo->VSD.szProdInfo[0]    = 'Default Digital Video VSD     ';
 ProdInfo->VSD.szManufacture[0] = 'IBM                           ';
 ProdInfo->VSD.szVersion[0]     = '0.1       ';


 return VSDERR_SUCCESS;
}

/*----------------------------------------------------------------------
 vsdQueryVideoRect

 Query Video Rectangles portion/size of source from capture card and size of
 destination rectangle.
 ----------------------------------------------------------------------*/

ULONG vsdQueryVideoRect(HVSD_INSTANCE * phVSD, PVOID pRequest)
{
 VSD_VIDEORECT_PARMS * SetVideo;                 // Set Video Rectangles packet
 ULONG ulRC;
 ULONG ReturnSize = 0;                           // Size of Data Returned
 VCACAPISIZE info;                               // Information on image postion/scale

SetVideo = (VSD_VIDEORECT_PARMS *)pRequest;      // Point to Set Video Rectangle packet


SetVideo->irectSource.X_left   = phVSD->SourceRect.X_left;
SetVideo->irectSource.Y_top    = phVSD->SourceRect.Y_top;
SetVideo->irectSource.X_width  = phVSD->SourceRect.X_width;
SetVideo->irectSource.Y_height = phVSD->SourceRect.Y_height;
SetVideo->irectDest.X_left     = phVSD->DestRect.X_left;
SetVideo->irectDest.Y_top      = phVSD->DestRect.Y_top;
SetVideo->irectDest.X_width    = phVSD->DestRect.X_width;
SetVideo->irectDest.Y_height   = phVSD->DestRect.Y_height;


return VSDERR_SUCCESS;
}


/*----------------------------------------------------------------------
 vsdQueryVideoAttributes

 Query Video adjustments on the device
 ----------------------------------------------------------------------*/

ULONG vsdQueryVideoAttributes(HVSD_INSTANCE * phVSD, PVOID pRequest)
{
 VCASETVIDEO vcaset;
 VSD_VIDEOATTRIBUTES_PARMS * SetVideo;                    // Set Video Attrubutes packet
 ULONG BytesRead = 0;
 ULONG ulRC;

 SetVideo = (VSD_VIDEOATTRIBUTES_PARMS *)pRequest;        // Point to Set Video Attributes packet

 // Is the Parmater List The Correct Size
 if (SetVideo->ulLength < sizeof(VSD_VIDEOATTRIBUTES_PARMS)) {
     return VSDERR_REQUEST_BUF_TOO_SMALL;      // If Not Return Error
 } /* endif */

 // Get the Current Settings
 SetVideo->ulLength      = VSD_VIDEOATTRIBUTES_Len;
 SetVideo->ulBrightness  = phVSD->VIDEOATTRIB.ulBrightness;
 SetVideo->ulHue         = phVSD->VIDEOATTRIB.ulHue;
 SetVideo->ulSaturation  = phVSD->VIDEOATTRIB.ulSaturation;
 SetVideo->ulContrast    = phVSD->VIDEOATTRIB.ulContrast;



   return VSDERR_SUCCESS;
}


/*----------------------------------------------------------------------
 vsdQueryImageFormat

 Query Image Data Format to one of the supported formats
 This will be the format of the image data returned on VSD_CaptureImage
 ----------------------------------------------------------------------*/

ULONG vsdQueryImageFormat(HVSD_INSTANCE * phVSD, PVOID pRequest)
{
 VSD_QUERYIMAGEFORMAT_PARMS * QFormat;           // Query Image Data Format packet
 ULONG ulRC;
 ULONG Info_Length;                                  // Length of Full Query Info

 QFormat = (VSD_QUERYIMAGEFORMAT_PARMS *)pRequest;   // Point to Set Image Format packet

 // Size of data to be returned on the Query
 Info_Length = VSD_QUERYIMAGEFORMAT_Len + ((phVSD->ulNumFormats-1)* sizeof(VSD_IMAGEFORMAT));

 // Is this A Request for Actual Size
 if (QFormat->ulLength==0) {
    QFormat->ulLength = Info_Length;
    return VSDERR_REQUEST_BUF_TOO_SMALL;
 } /* endif */


 ulRC = VSDERR_SUCCESS;                                            // Assume all is well

 // Copy Partial Info
 if (Info_Length > QFormat->ulLength) {
    Info_Length = QFormat->ulLength;
    ulRC = VSDERR_REQUEST_BUF_TOO_SMALL;
 } /* endif */


/* Get Video Image Foramt info from the HVSD Instance info structure */
 memcpy (QFormat, phVSD->pImg_Formats, Info_Length);




return ulRC;
}

/*----------------------------------------------------------------------
 vsdQueryFPS

 Query Frames Per Second for image streaming.
 This Querys the number of frames per second are to be sent to the Stream Handler once streaming
 is activated by SSM
 ----------------------------------------------------------------------*/

ULONG vsdQueryFPS(HVSD_INSTANCE * phVSD, PVOID pRequest)
{
 VSD_SETFPS_PARMS * SetFPS;               // Set Frames Per Second packet
 ULONG ulRC;
 VCASETFPS info;                          // Information on image capture Rate
 ULONG ReturnSize = 0;                    // Size of Data Returned

 SetFPS = (VSD_SETFPS_PARMS *)pRequest;   // Point to Set Frames Pers Second packet

 /* Save Video Rectangle info in the HVSD Instance info structure */
 SetFPS->ulFPS = phVSD->ulFPS;

return VSDERR_SUCCESS;
}


/*----------------------------------------------------------------------
 vsdQueryIExtents

 Query Maximum Image size this device is capable of.
 This means the maximum size of the Destination Rectangle
 on VSD_SETVIDEORECT or the maximum size VSD_CAPTUREIMAGE is able
 to return.

 ----------------------------------------------------------------------*/

ULONG vsdQueryIExtents(HVSD_INSTANCE * phVSD, PVOID pRequest)
{
 VSD_QUERYIMAGEEXTENTS_PARMS * QIE;          // Query Image Extents packet
 ULONG ulRC;

 QIE = (VSD_QUERYIMAGEEXTENTS_PARMS *) pRequest; // Point to Query Packet

 /* Get Image Rectangle info in the HVSD Instance info structure */
 QIE->ulX_Extent = phVSD->IExtents.ulX_Extent;
 QIE->ulY_Extent = phVSD->IExtents.ulY_Extent;
 QIE->ulLength   = VSD_QUERYIMAGEEXTENTS_Len;

return VSDERR_SUCCESS;
}

/*----------------------------------------------------------------------
 vsdQueryOExtents

 Query Maximum Overlay size this device is capable of.
 This means the maximum size of the Overlay Rectangle/Window
 on VSD_SETOVERLAYRECT

 ----------------------------------------------------------------------*/

ULONG vsdQueryOExtents(HVSD_INSTANCE * phVSD, PVOID pRequest)
{
 VSD_QUERYOVERLAYEXTENTS_PARMS * QIE;          // Query Overlay Extents packet
 ULONG ulRC;

 QIE = (VSD_QUERYOVERLAYEXTENTS_PARMS *) pRequest; // Point to Query Packet

 /* Get Overlay Rectangle info in the HVSD Instance info structure */
 QIE->ulX_Extent = phVSD->OExtents.ulX_Extent;
 QIE->ulY_Extent = phVSD->OExtents.ulY_Extent;
 QIE->ulLength   = VSD_QUERYOVERLAYEXTENTS_Len;

return VSDERR_SUCCESS;
}

/*----------------------------------------------------------------------
 vsdQueryVExtents

 Query Maximum Image size this device is capable of.
 This means the maximum size of Source Rectangle
 on VSD_SETVIDEORECT or the size of digitized incoming Video Signal

 ----------------------------------------------------------------------*/

ULONG vsdQueryVExtents(HVSD_INSTANCE * phVSD, PVOID pRequest)
{
 VSD_QUERYVIDEOEXTENTS_PARMS * QVE;              // Query Video Extents
 ULONG ulRC;

 QVE = (VSD_QUERYVIDEOEXTENTS_PARMS *) pRequest; // Point to Query Packet

 /* Get Video Rectangle info in the HVSD Instance info structure */
 QVE->ulX_Extent = phVSD->VExtents.ulX_Extent;
 QVE->ulY_Extent = phVSD->VExtents.ulY_Extent;
 QVE->ulLength   = VSD_QUERYVIDEOEXTENTS_Len;

return VSDERR_SUCCESS;
}

/*----------------------------------------------------------------------
 vsdOPEN

 Open to the device driver and return a HVSD (not a file handle). This call should not change
 the state of the device.
 ----------------------------------------------------------------------*/

ULONG vsdOPEN(PVOID pRequest)

{
ULONG    Action;
ULONG    ulIoctldatasize = sizeof (VCABUFFER);   // data area size
ULONG    rc;                                     // return code for random usage
VSD_OPEN_PARMS * OPEN_Packet;                    // Open packet
HVSD_INSTANCE *  phVSD;                          // Pointer to HVSD Instance Info
PDD_INSTANCE  *  pPDD;                           // Pointer to PDD Instance Info
HFILE    CaptureDevHandle;                       // Handle to the PDD
VCASETVIDEO vcaset;                              // Set Video Attributes for PDD
VCADEVINFO Info;                                 // Device Info
ULONG       BytesRead = 0;                       // Data Read Size
ULONG       NumFormats = 0;                      // Number of Image Formats Supported
ULONG       Size_hVSD;
ULONG       Index;
BYTE *      pTemp;
PVOID       pINI_Parms;                          // .INI File Info
ULONG       Len_INI_Parms;                       // Length of Info from .INI file
HFILE       hfINI_PDD;                           // INI file Handle
ULONG       Count;                               // Number of HVSD on this PDD
PSZ         pszYUVLOOK;                          // !!! T E M P   C O D E
VSD_QUERYIMAGEFORMAT_PARMS * QFormat;            // list of Image Formats Supported

OPEN_Packet = (VSD_OPEN_PARMS *)pRequest;        // Open packet


rc = DosOpen( (PSZ) OPEN_Packet->szPDDName,      // OPEN the PDD
               &CaptureDevHandle,
               &Action,
               0L,    // file size ignored on open for read
               0L,    // file attributes ignord on open for read
               0x01,  // open only if file exists
               0x21C0, // just open for read, nothing fancy
               0L);   // no extended attributes

if (rc) {
   return VSDERR_NO_DEVICE_DRIVER;  // Error = Open Failed
} /* endif */

Add_PDD((PSZ) OPEN_Packet->szPDDName, &Count);

// Load Card Specific Default Info from INI file
rc = Read_INI((PSZ) OPEN_Packet->szPDDName, &pINI_Parms, &Len_INI_Parms, &hfINI_PDD);
IniFileClose(hfINI_PDD);

if (rc==VSDERR_SUCCESS) {

   // Get Device Info from the Device
   rc = DosDevIOCtl(CaptureDevHandle,         // device handle
                   (ULONG) 140,               // category
                   (ULONG) 0x60,              // function
                   0,                         // parm list  ???
                   0,                         // parm length max
                   0,                         // parm length in/out
                   pINI_Parms,                // function data area
                   Len_INI_Parms,             // data area size
                   &BytesRead);               // data area size !!!

   if (rc != 0) {
      DosClose(CaptureDevHandle);
      return VSDERR_NO_DEVICE_DRIVER;  // Error = Open Failed
   } /* endif */
} /* endif */

// Build Query For Device Info
Info.Length        = sizeof(VCADEVINFO);

// Get Device Info from the Device
rc = DosDevIOCtl(CaptureDevHandle,         // device handle
                (ULONG) 140,               // category
                (ULONG) 0x6D,              // function
                0,                         // parm list  ???
                0,                         // parm length max
                0,                         // parm length in/out
                &Info,                     // function data area
                sizeof (VCADEVINFO),       // data area size
                &BytesRead);               // data area size !!!

if (rc) {
   DosClose(CaptureDevHandle);
   return VSDERR_NO_DEVICE_DRIVER;  // Error = Open Failed
} /* endif */

// !!! Needs work to check how many we can support if Native is RGB or YUV or ....
// Number of Image Formats Supported
NumFormats = 2;      /* Raw RGB16/YUV411 form the card and OS/2 2.0 24 bit bitmap)*/

// Size if a HVSD instance plus Image Format Data
Size_hVSD  = sizeof(HVSD_INSTANCE) + sizeof(VSD_QUERYIMAGEFORMAT_PARMS) +
             ((NumFormats-1)* sizeof(VSD_IMAGEFORMAT));

/* Get a buffer for HVSD state Information                                */
rc = DosAllocMem ( (PVOID *) &phVSD, (ULONG) Size_hVSD,
                  PAG_COMMIT | PAG_READ | PAG_WRITE);

if (rc) {
   DosClose(CaptureDevHandle);
   return VSDERR_INSUFFICIENT_MEMORY;
} /* endif */

/* Add new HVSD Instance to the List */
if (!Add_HVSD (phVSD, &Index)) {                                 // IF Add fails Release Resource

   // Close the PDD
   DosClose(CaptureDevHandle);

   /* Free the a buffer used for HVSD state Information                   */
   DosFreeMem (phVSD);

   return VSDERR_INSUFFICIENT_MEMORY;
} /* endif */


OPEN_Packet->hvsd = phVSD;

/* Fill in new HVSD Instance Information */
phVSD->pNextHVSD                = NULL;
phVSD->pPrevHVSD                = NULL;
phVSD->hVSD_ID                  = (PVOID) Index;
phVSD->pPDD                     = pPDD;
phVSD->ulFlags                  = 0;
phVSD->SourceRect.X_left        = Info.S_X_Left;
phVSD->SourceRect.Y_top         = Info.S_Y_Top;
phVSD->SourceRect.X_width       = Info.S_X_Width;
phVSD->SourceRect.Y_height      = Info.S_Y_Height;
phVSD->DestRect.X_left          = Info.D_X_Left;
phVSD->DestRect.Y_top           = Info.D_Y_Top;
phVSD->DestRect.X_width         = Info.D_X_Width;
phVSD->DestRect.Y_height        = Info.D_Y_Height;
phVSD->VExtents.ulX_Extent      = Info.S_X_MAX;
phVSD->VExtents.ulY_Extent      = Info.S_Y_MAX;
phVSD->IExtents.ulX_Extent      = Info.D_X_MAX;
phVSD->IExtents.ulY_Extent      = Info.D_Y_MAX;
phVSD->ulScaleFactor            = Info.D_ScaleFactor;
phVSD->ulImageFormat            = Info.ImgFormat;
phVSD->usBitsPerPEL             = Info.BitsPerPEL;
phVSD->ulFreeze                 = FALSE;
phVSD->ulNTSC                   = TRUE;
phVSD->ulVSource                = 0;
phVSD->CaptureDevHandle         = CaptureDevHandle;
phVSD->ulState                  = VSD_ulState_Saved;
phVSD->ulImgHSize               = 0;
phVSD->pINI_Parms               = pINI_Parms;
phVSD->Len_INI_Parms            = Len_INI_Parms;
phVSD->ulFileNum                = Info.ulFileNum;
phVSD->VideoMode                = Info.unused1;



// !!! Needs work to check which one we can support if Native is RGB or YUV or ....
/* Build List of Image Formats we support on VSD_CaptureImage */
phVSD->ulNumFormats = NumFormats;
pTemp = (BYTE *)phVSD + sizeof(HVSD_INSTANCE);
phVSD->pImg_Formats = (VSD_QUERYIMAGEFORMAT_PARMS *)pTemp;
QFormat = phVSD->pImg_Formats;
QFormat->CurFormat.ulFormat        = Info.ImgFormat;
QFormat->CurFormat.usBitsPerPEL    = Info.BitsPerPEL;
QFormat->NativeFormat.ulFormat     = Info.ImgFormat;
QFormat->NativeFormat.usBitsPerPEL = Info.BitsPerPEL;
QFormat->ulNumFormats              = phVSD->ulNumFormats;
QFormat->Format[0].ulFormat        = Info.ImgFormat;
QFormat->Format[0].usBitsPerPEL    = Info.BitsPerPEL;
QFormat->Format[1].ulFormat        = VSD_IMAGEFORMAT_OS2_BITMAP2;
QFormat->Format[1].usBitsPerPEL    = 24;
//QFormat->Format[2].ulFormat        = VSD_IMAGEFORMAT_OS2_BITMAP2;
//QFormat->Format[2].usBitsPerPEL    = 8;

/* Set Initial settings to the Defaults  */
phVSD->VIDEOATTRIB.ulBrightness = Info.Brightness;
phVSD->VIDEOATTRIB.ulHue        = Info.hue;
phVSD->VIDEOATTRIB.ulSaturation = Info.saturation;
phVSD->VIDEOATTRIB.ulContrast   = Info.contrast;

/* Save Defaults for the Card */
phVSD->VIDEOATTRIB_Defaults.ulBrightness = Info.Brightness;
phVSD->VIDEOATTRIB_Defaults.ulHue        = Info.hue;
phVSD->VIDEOATTRIB_Defaults.ulSaturation = Info.saturation;
phVSD->VIDEOATTRIB_Defaults.ulContrast   = Info.contrast;


/* Fill in Device Capabilties */
phVSD->DC.ulLength   =  VSD_GETDEVCAPS_Len;
phVSD->DC.ulMax_Caps =  DC_MAX_DEVCAP;
phVSD->DC.ulNum_Caps =  DC_MAX_DEVCAP;
phVSD->DC.ulResv01   =  0;
phVSD->DC.ulResv02   =  0;
phVSD->DC.ulResv03   =  0;
phVSD->DC.ulResv04   =  Info.unused1;
phVSD->DC.bSupports[DC_HASAUDIO]               = FALSE;
phVSD->DC.bSupports[DC_HASVIDEO]               = FALSE;
phVSD->DC.bSupports[DC_HASVOLUME]              = FALSE;
phVSD->DC.bSupports[DC_HASDISPLAY]             = FALSE;
phVSD->DC.bSupports[DC_HASAUDIOATTRIBUTES]     = FALSE;
phVSD->DC.bSupports[DC_HASAUDIOCAPABILITIES]   = FALSE;
phVSD->DC.bSupports[DC_HASVIDEOATTRIBUTES]     = TRUE;
phVSD->DC.bSupports[DC_HASIMAGEATTRIBUTES]     = FALSE;
phVSD->DC.bSupports[DC_HASTTSATTRIBUTES]       = FALSE;
phVSD->DC.bSupports[DC_HASCDCAPS]              = FALSE;
phVSD->DC.bSupports[DC_HASESCAPE]              = FALSE;
phVSD->DC.bSupports[DC_CANPLAY]                = FALSE;
phVSD->DC.bSupports[DC_CANRECORD]              = FALSE;
phVSD->DC.bSupports[DC_HASINPUTLEVEL]          = FALSE;
phVSD->DC.bSupports[DC_HASSTATUSLEVEL]         = FALSE;
phVSD->DC.bSupports[DC_HASMONITOR]             = FALSE;
phVSD->DC.bSupports[DC_CANREAD]                = FALSE;
phVSD->DC.bSupports[DC_CANWRITE]               = FALSE;
phVSD->DC.bSupports[DC_HASDATATYPES]           = FALSE;
phVSD->DC.bSupports[DC_CANEJECT]               = FALSE;
phVSD->DC.bSupports[DC_CANLOAD]                = FALSE;
phVSD->DC.bSupports[DC_HASDOOR]                = FALSE;
phVSD->DC.bSupports[DC_HASTRACKS]              = FALSE;
phVSD->DC.bSupports[DC_HASMEDIA]               = FALSE;
phVSD->DC.bSupports[DC_HASCOMMSETTINGS]        = FALSE;
phVSD->DC.bSupports[DC_HASMEDIATYPE]           = FALSE;
phVSD->DC.bSupports[DC_HASKEYLOCK]             = FALSE;
phVSD->DC.bSupports[DC_HASVARIABLERATES]       = FALSE;
phVSD->DC.bSupports[DC_CANCUE]                 = FALSE;
phVSD->DC.bSupports[DC_HASCOUNTER]             = FALSE;
phVSD->DC.bSupports[DC_CANRESET]               = FALSE;
phVSD->DC.bSupports[DC_HASPOSITION]            = FALSE;
phVSD->DC.bSupports[DC_HASLENGTH]              = FALSE;
phVSD->DC.bSupports[DC_CANPARK]                = FALSE;
phVSD->DC.bSupports[DC_HASCONNECTOR]           = FALSE;
phVSD->DC.bSupports[DC_HASEVENTS]              = FALSE;
phVSD->DC.bSupports[DC_HASDIRECTION]           = FALSE;
phVSD->DC.bSupports[DC_HASVIEWPORT]            = Info.Overlay;
phVSD->DC.bSupports[DC_CANCAPTUREIMAGE]        = TRUE;
phVSD->DC.bSupports[DC_CANRESTOREIMAGE]        = Info.Overlay;
phVSD->DC.bSupports[DC_HASRAM]                 = FALSE;
phVSD->DC.bSupports[DC_AUDIOSETTINGS]          = FALSE;
phVSD->DC.bSupports[DC_IMAGESETTINGS]          = FALSE;
phVSD->DC.bSupports[DC_QUERYMINSEEKTIME]       = FALSE;
phVSD->DC.bSupports[DC_QUERYTIME]              = FALSE;
phVSD->DC.bSupports[DC_SEEK]                   = FALSE;
phVSD->DC.bSupports[DC_STEP]                   = FALSE;
phVSD->DC.bSupports[DC_CAN_MIX]                = FALSE;
phVSD->DC.bSupports[DC_HASCLOCK]               = FALSE;
phVSD->DC.bSupports[DC_HASPOWER]               = FALSE;
phVSD->DC.bSupports[DC_HASZOOM]                = FALSE;
phVSD->DC.bSupports[DC_HASEDIT]                = FALSE;
phVSD->DC.bSupports[DC_HASFOCUS]               = FALSE;
phVSD->DC.bSupports[DC_HASCHANNELS]            = FALSE;
phVSD->DC.bSupports[DC_HASTEXTTOSPEECH]        = FALSE;
phVSD->DC.bSupports[DC_CANSTREAM]              = Info.CanStream;
phVSD->DC.bSupports[DC_CANSCALE]               = Info.CanScale;
phVSD->DC.bSupports[DC_CANSTRETCH]             = Info.CanStretch;
phVSD->DC.bSupports[DC_CANDISTORT]             = Info.CanDistort;

// New Parameter only fill in if space allows
if (OPEN_Packet->ulLength == VSD_OPEN_Len)
   OPEN_Packet->ulDDStream = phVSD->ulFileNum; // Handle for the PDD

// !!! ........ T E M P    C O D E ..................................!!!
// !!! ........ T E M P    C O D E ..................................!!!
/* Is this a RGB card that we want to look like a YUV Card */
if ((pszYUVLOOK = getenv("YUVLOOK")) != NULL) {
   phVSD->DC.bSupports[DC_HASTEXTTOSPEECH]     = TRUE;
   }
// !!! ........ T E M P    C O D E ..................................!!!
// !!! ........ T E M P    C O D E ..................................!!!


return VSDERR_SUCCESS;
}


/*----------------------------------------------------------------------
 vsdCLOSE

 CLOSE to the device driver for the  specified HVSD. This call should not change
 the state of the device.
 ----------------------------------------------------------------------*/

ULONG vsdCLOSE(HVSD_INSTANCE * phVSD)
{

/* Save the INI file */
//PCV_SaveConfiguration(phVSD->pINI_Parms,phVSD->Len_INI_Parms);

/* Remove HVSD Instance from the list of HVSDs */
HVSD_LIST[(ULONG) phVSD->hVSD_ID] = NULL;

DosClose(phVSD->CaptureDevHandle);

/* Free the a buffer used for HVSD state Information                   */
DosFreeMem (phVSD);

return VSDERR_SUCCESS;
}

/*----------------------------------------------------------------------
 vsdRestore

 Initialize the card for the specific HVSD
 ----------------------------------------------------------------------*/

ULONG vsdRestore(HVSD_INSTANCE * phVSD)
{
ULONG       Action;
ULONG       ulIoctldatasize = sizeof (VCABUFFER);   // data area size
ULONG       rc;                                     // return code for random usage
ULONG       ReturnSize = 0;                         // Size of Data Returned
VCACAPISIZE info;                                   // Information on image postion/scale
VCASETVIDEO vcaset;
VCASETCAPTURERECT info2;                            // Info image postion/scale

    // Mark As Restored HVSD as Restored..
    phVSD->ulState = VSD_ulState_Restored;

//!!!! Need code here and in the PDD to just do Card Set up to certian parms

//!!! !!! !!!  Remove next IOCTL does this...............
   info.X_Left      =  phVSD->SourceRect.X_left;
   info.Y_Top       =  phVSD->SourceRect.Y_top;
   info.Y_Height    =  phVSD->SourceRect.Y_height;
   info.X_Width     =  phVSD->SourceRect.X_width;
   info.ScaleFactor =  phVSD->ulScaleFactor;

   // Set up the size/postion/scale of image to capture from the video capture board
   rc = DosDevIOCtl(phVSD->CaptureDevHandle,   // device handle
                   (ULONG) 140,                // category
                   (ULONG) 0x6E,               // function
                   0,                          // parm list
                   0,                          // parm length max
                   0,                          // parm length in/out
                   &info,                      // function data area
                   sizeof (info),              // data area size
                   &ReturnSize);               // data area size returned

   if (rc) {
      return 1;  // Error = Addressability IOCTL Failed
    } /* endif */

   info2.Source_X_Left    = phVSD->SourceRect.X_left;
   info2.Source_Y_Top     = phVSD->SourceRect.Y_top;
   info2.Source_X_Width   = phVSD->SourceRect.X_width;
   info2.Source_Y_Height  = phVSD->SourceRect.Y_height;
   info2.Dest_X_Left      = phVSD->DestRect.X_left;
   info2.Dest_Y_Top       = phVSD->DestRect.Y_top;
   info2.Dest_X_Width     = phVSD->DestRect.X_width;
   info2.Dest_Y_Height    = phVSD->DestRect.Y_height;

   // Set up the size/postion/scale of image to capture from the video capture board
   rc = DosDevIOCtl(phVSD->CaptureDevHandle,   // device handle
                  (ULONG) 140,                // category
                  (ULONG) VCAI_SETCAPTRECT,   // function
                  0,                          // parm list
                  0,                          // parm length max
                  0,                          // parm length in/out
                  &info2,                     // function data area
                  sizeof (info2),             // data area size
                  &ReturnSize);               // data area size returned


   // Build Set Video Request packet for the PDD
   vcaset.set_brightness = phVSD->VIDEOATTRIB.ulBrightness;
   vcaset.set_hue        = phVSD->VIDEOATTRIB.ulHue;
   vcaset.set_saturation = phVSD->VIDEOATTRIB.ulSaturation;
   vcaset.set_contrast   = phVSD->VIDEOATTRIB.ulContrast;

   // Send Set Video Packet to the PDD
   rc = DosDevIOCtl(phVSD->CaptureDevHandle,  // device handle
                   (ULONG) 140,               // category
                   (ULONG) 0x75,              // function
                   0,                         // parm list  ???
                   0,                         // parm length max
                   0,                         // parm length in/out
                   &vcaset,                   // function data area
                   sizeof (VCASETVIDEO),      // data area size
                   &ReturnSize);               // data area size !!!

    // Did the Device Driver Accept the command?
    if (rc) {
       return VSDERR_NO_DEVICE_DRIVER;
    } /* endif */


    // Make Sure the PDD Freeze/UnFreeze is correct
    if (phVSD->ulFreeze == TRUE) {
       rc=FreezeImage(phVSD);
    } else {
       rc=UnfreezeImage(phVSD);
    } /* endif */



return rc;
}

/*----------------------------------------------------------------------
 vsdSave

 Save information about the card's\HVSD's state so it can be Restored later
 ----------------------------------------------------------------------*/

ULONG vsdSave(HVSD_INSTANCE * phVSD)
{

phVSD->ulState = VSD_ulState_Saved;             // Mark State as Saved

return VSDERR_SUCCESS;
}


/*----------------------------------------------------------------------
 CaptureImage

 This function is called to capture a single vide image from the video
 capture device.  The image is left in the block of memory pointed to by
 "capturebuf". For speed the image is not locked into the H/W buffer, instead
 it is only copied (this may produce a minimal amount of image tears,
 but for speed this seems to be the only way until the conversion to ring 0
 stream handler with capture at interrupt time).

 Two rectangle structures are passed: a source rectangle and a destination
 rectangle.  The source rectangle specifies the area to be captured in
 "video coordinates" for the type of video input signal.  Video coordinates
 are based on the generally accepted number of active video lines in the
 signal (the Y extent) and an analog sampling rate that produces square
 pixels in a 4:3 ratio in the X extent.

    NTSC : 640x480
    PAL  : 640x560

 The destination rectangle specifies the resultant image capture size.  For
 framegrabber boards, the destination rectangle position is not used.

 Scaling is performed to produce an image of the size specified by the
 destination rectangle.  The scaling is determined by the ratio of the
 source rectangle size to the destination rectangle size.  For speed,
 scaling is performed by simple decimation, and only in whole number
 ratios.  The scaling ratio used is the minimum required to produce an
 image that fills the destination rectangle.  This is computed as follows
 (using integer division):

   scaling ratio = min (src X / dest X , src Y / dest Y)

 The scaled image from the source rectangle is clipped to the destination
 rectangle size.

   !!! Need to add this.  For now, assume dest rectangle is integer multiple
        of src rectangle size.

 ----------------------------------------------------------------------*/

ULONG vsdCaptureImage(HVSD_INSTANCE * phVSD,PVOID pRequest)
{
ULONG    rc;                     // return code for random usage
ULONG    ulIoctldatasize = 0;    // data area size
DWORD    i;                      // index
USHORT * capbufptr;              // capture buffer pointer (advances each bank)
ULONG  SizeDwords;               // Number of Pixels / 2 (dwords in image to copy)
BYTE   * Control_Reg;            // Bank Select Register on SVIA
VCASELECTBANK vcasb;             // VCA bank selection parm struct
#define  control_reg_offset 0x402// Offset to Control register on SVIA
ULONG    BytesRead = 0;          // Data Read Size
ULONG    SizeBytes = 0;          // Size of image to copy in bytes
ULONG    ISize;                  // Size of buffer to read image into
ULONG    Size_BMI;               // Size of bitmap image
ULONG    Min_Size;               // Minimum size of buffer need by caller
ULONG    Callers_Size;           // size of buffer provided by caller
VCAGETIMAGESCALE   GetImage;     // Information for PDD to get Image
VSD_CAPIMAGE_PARMS * CIP            ;             // Capture Image packet
BITMAPFILEHEADER2  * bmf_hdr;    // File Header for BitMap
PBITMAPINFO2       * pbminfo;
RGB2               * pPAL;
BYTE               * bitmapbuf;  // pointer to buffer to hold bitmap converted
HFILE        hBMP;               // Temp !!! Handle for bitmap file
ULONG        ulAction;           // Temp !!!Action from DOS Open
ULONG        cBytes;             // Temp !!!Bytes Written on DOS WRITE
ULONG        Off_BM;             // Offset To Image in Bitmap


CIP = (VSD_CAPIMAGE_PARMS *)pRequest; // Capture Image packet



// Make sure HVSD is active otherwise invalid to issue CaptureImage
if (phVSD->ulState != VSD_ulState_Restored) {
   return VSDERR_INSTANCE_INACTIVE;
} /* endif */

/* Is the Source Rectange in the Valid Range */
if (( CIP->irectSource.X_left    > (phVSD->VExtents.ulX_Extent - 8)) |
    ( CIP->irectSource.Y_top     > (phVSD->VExtents.ulY_Extent - 8)) |
    ((CIP->irectSource.X_width  +  CIP->irectSource.X_left)  > phVSD->VExtents.ulX_Extent) |
    ((CIP->irectSource.Y_height +  CIP->irectSource.Y_top )  > phVSD->VExtents.ulY_Extent) ) {
    return VSDERR_OUTOFRANGE;
} /* endif */


/* Is the Destination Rectange in the Valid Range */
if (( CIP->irectDest.X_left    > (phVSD->IExtents.ulX_Extent - 8)) |
    ( CIP->irectDest.Y_top     > (phVSD->IExtents.ulY_Extent - 8)) |
    ((CIP->irectDest.X_width  +  CIP->irectDest.X_left)  > phVSD->IExtents.ulX_Extent) |
    ((CIP->irectDest.Y_height +  CIP->irectDest.Y_top )  > phVSD->IExtents.ulY_Extent) )  {
    return VSDERR_OUTOFRANGE;
} /* endif */



/* Output Size must be a multiple of 8 in X and Y */
if (((CIP->irectDest.X_width  % 8) != 0) |
    ((CIP->irectDest.Y_height % 8) != 0 ))  {
    {
    return VSDERR_OUTOFRANGE;
    }
} /* endif */

/* Does the card support distoring */
if (phVSD->DC.bSupports[DC_CANDISTORT]==FALSE) {
   /* Card does not support strecting X and Y must be scaled the same */
   if (( (CIP->irectSource.X_width/CIP->irectDest.X_width) !=
         (CIP->irectSource.Y_height/CIP->irectDest.Y_height)) |
        ((CIP->irectSource.X_width%CIP->irectDest.X_width)   != 0) |
        ((CIP->irectSource.Y_height%CIP->irectDest.Y_height) != 0)){
       return VSDERR_INVALID_INPUT;
   } /* endif */
} /* endif */


// Minimum Size of Image in Bytes need to capture the image
Min_Size = (((CIP->irectDest.X_width  * CIP->irectDest.Y_height *
             phVSD->pImg_Formats->CurFormat.usBitsPerPEL)+7)/8) +
             phVSD->ulImgHSize;
Callers_Size = CIP->ulImg_Buff_Size;

// Return Actual Size need to caller
CIP->ulImg_Buff_Size = Min_Size;

// Make Sure Buffer is Large Enough to copy image into
if (Callers_Size < Min_Size) {
   return VSDERR_INVALID_BUFF;
} /* endif */


// If Convert to OS/2 Bit Maps format is required
if ((phVSD->pImg_Formats->CurFormat.ulFormat == VSD_IMAGEFORMAT_OS2_BITMAP2) |
    // !!! ............. T E M P   C O D E ................!!!
    // ..................Make RGB image into YUV24 Image
    // ..................when SET YUVLOOK=YES is issued at OS/2 command prompt
    (phVSD->DC.bSupports[DC_HASTEXTTOSPEECH] == TRUE)) {
    // !!! ............. T E M P   C O D E ................!!!

   // Size of Raw Image Buffer from the card
   ISize = ((CIP->irectDest.X_width  * CIP->irectDest.Y_height *
             phVSD->pImg_Formats ->NativeFormat.usBitsPerPEL)+7)/8;

   // Get an intermidiate buffer for raw image from the card
   rc = DosAllocMem ( (PVOID *) &capbufptr, (ULONG) ISize,
                    PAG_COMMIT | PAG_READ | PAG_WRITE);

   if (rc)
      return VSDERR_INSUFFICIENT_MEMORY;

 } else {

   capbufptr = (USHORT *)CIP->pImg_Buff;        // Destimation for Image
   ISize     = CIP->ulImg_Buff_Size;            // Image buff size

} /* endif */

// Get Image from the Hardware
GetImage.Capture_Buf_Len = ISize;               // Length of image buff in bytes
GetImage.Capture_Buf_Ptr = (DWORD) capbufptr;   // Destimation for Image
GetImage.Source_X_Left   = CIP->irectSource.X_left;
GetImage.Source_Y_Top    = CIP->irectSource.Y_top;
GetImage.Source_Y_Height = CIP->irectSource.Y_height;
GetImage.Source_X_Width  = CIP->irectSource.X_width;
GetImage.Dest_X_Left     = CIP->irectDest.X_left;
GetImage.Dest_Y_Top      = CIP->irectDest.Y_top;
GetImage.Dest_Y_Height   = CIP->irectDest.Y_height;
GetImage.Dest_X_Width    = CIP->irectDest.X_width;

rc = DosDevIOCtl(phVSD->CaptureDevHandle,       // device handle
                (ULONG) 140,                    // category
                (ULONG) 0x6C,                   // function - Get Image & Scale
                0,                              // parm list
                0,                              // parm length max
                0,                              // parm length in/out
                &GetImage,                      // function data area
                sizeof (GetImage),              // data area size
                &BytesRead);                    // data area size returned


// Make Sure Image was copied into the Buffer
 switch (rc) {
    case  VCAERR_SUCCESS:
       break;

    case  VCAERR_INVALID_BUFFER:
       return VSDERR_INVALID_BUFF;
       break;

    case  VCAERR_INVALID_RECT:
       return VSDERR_INVALID_INPUT;
       break;

    default:
       return VSDERR_DEVICE_REJECTED;
       break ;
    } /* endswitch */

///Commenented out code below to let the Image Comeback in YUV411 ------
/// !!! !!! !!!!! Temp Code !!! !!! !!!!!!
/* If YUV411 turn it in to RGB16 */
//if ((phVSD->pImg_Formats->NativeFormat.ulFormat == VSD_IMAGEFORMAT_YUV_411) &
//    (phVSD->pImg_Formats->CurFormat.ulFormat != VSD_IMAGEFORMAT_OS2_BITMAP2)){
//
//  _YUV411_to_RGB16 ((USHORT *)capbufptr,
//                    (BYTE   *)capbufptr,
//                    (ULONG)CIP->irectDest.X_width,
//                    (ULONG)CIP->irectDest.Y_height);
//} /* endif */




// !!! ............. T E M P   C O D E ................!!!
// ..................Make RGB image into YUV24 Image
// ..................when SET YUVLOOK=YES is issued at OS/2 command prompt
if (phVSD->DC.bSupports[DC_HASTEXTTOSPEECH] == TRUE) {

   // Pointer to were image starts in the bitmap buffer
   bitmapbuf = (BYTE *)((ULONG)(CIP->pImg_Buff));

   // Convert from RGB16 to 24 bit YUV image
   _RGB16_to_YUV24((USHORT *)capbufptr,
                   (BYTE *)bitmapbuf,
                   (ULONG)phVSD->DestRect.X_width,
                   (ULONG)phVSD->DestRect.Y_height);

   // Free intermidiate buffer for raw image from the card
   DosFreeMem ( (PVOID)capbufptr);

} /* endif */
// !!! ............. T E M P   C O D E ................!!!

// If Convert to OS/2 Bit Maps
if (phVSD->pImg_Formats->CurFormat.ulFormat == VSD_IMAGEFORMAT_OS2_BITMAP2) {


   Size_BMI = ((CIP->irectDest.X_width * CIP->irectDest.Y_height *
                phVSD->pImg_Formats->CurFormat.usBitsPerPEL)+7)/8;

   // Offset to Bitmap image
   switch (phVSD->pImg_Formats->CurFormat.usBitsPerPEL) {
      case  VSD_BITSPERPEL_8:

          /* Fill Pallet to be used with this bitmap.               */
          pPAL = (RGB2 *)((ULONG)CIP->pImg_Buff +
                          sizeof(BITMAPFILEHEADER2));
          for ( i=0; i<256; i++ )
             {
             pPAL->bRed= The784Palette  [i][0];
             pPAL->bGreen= The784Palette[i][1];
             pPAL->bBlue= The784Palette [i][2];
             pPAL++;
             }

          // Offset =  Bitmap header plus  pallet info
          Off_BM = sizeof (BITMAPFILEHEADER2) + (sizeof(RGB2) * 256);

          // Pointer to were image starts in the bitmap buffer
          bitmapbuf = (BYTE *)((ULONG)(CIP->pImg_Buff) + Off_BM);

          // Convert from RGB16 to 8 bit for OS/2 Bitmap
          _RGB16_to_IPAL8((USHORT *)capbufptr,
                         (BYTE *)bitmapbuf,
                         (ULONG)((phVSD->DestRect.X_width)),
                         (ULONG)phVSD->DestRect.X_width,
                         (ULONG)phVSD->DestRect.Y_height,
                         0);
           break;

      case  VSD_BITSPERPEL_24:

        // Offset = Bitmap header with no pallet
        Off_BM = sizeof (BITMAPFILEHEADER2);

        // Pointer to were image starts in the bitmap buffer
        bitmapbuf = (BYTE *)((ULONG)(CIP->pImg_Buff) + Off_BM);

        /// !!! !!! !!!!! Temp Code !!! !!! !!!!!!
        /* If YUV411 turn it in to RGB24 Inverted Else RGB16 to RGB 24 Inverted */
        if (phVSD->pImg_Formats->NativeFormat.ulFormat == VSD_IMAGEFORMAT_YUV_411) {

          // Convert YUV411 to RGB 24 inverted for OS/2 Bitmap
          _YUV411_to_IRGB24 ((USHORT *)capbufptr,
                             (BYTE   *)bitmapbuf,
                            (ULONG)CIP->irectDest.X_width,
                            (ULONG)CIP->irectDest.Y_height);
        } else {
           // Convert from RGB16 to RGB24 for OS/2 Bitmap
           _RGB16_to_IRGB24((USHORT *)capbufptr,
                            (BYTE *)bitmapbuf,
                            (ULONG)CIP->irectDest.X_width,
                            (ULONG)CIP->irectDest.Y_height,
                            0);
        } /* endif */
        break ;

     default:                                              /* Valid HVSD is Requires */
        break ;

      } /* endswitch */

   // Fill in BitMap file header info
   bmf_hdr = (BITMAPFILEHEADER2 *)CIP->pImg_Buff;
   bmf_hdr->usType        = BFT_BMAP;
   bmf_hdr->cbSize        = sizeof(BITMAPFILEHEADER2);
   bmf_hdr->xHotspot      = 0;
   bmf_hdr->yHotspot      = 0;
   bmf_hdr->offBits       = Off_BM;
   bmf_hdr->bmp2.cbFix           = sizeof (BITMAPINFOHEADER2);
   bmf_hdr->bmp2.cx              = CIP->irectDest.X_width;
   bmf_hdr->bmp2.cy              = CIP->irectDest.Y_height;
   bmf_hdr->bmp2.cPlanes         = 1;
   bmf_hdr->bmp2.cBitCount       = phVSD->pImg_Formats->CurFormat.usBitsPerPEL;
   bmf_hdr->bmp2.ulCompression   = BCA_UNCOMP;
   bmf_hdr->bmp2.cbImage         = Size_BMI;
   bmf_hdr->bmp2.cxResolution    = CIP->irectDest.X_width;
   bmf_hdr->bmp2.cyResolution    = CIP->irectDest.Y_height;
   bmf_hdr->bmp2.cclrUsed        = 0;
   bmf_hdr->bmp2.cclrImportant   = 0;
   bmf_hdr->bmp2.usUnits         = BRU_METRIC;
   bmf_hdr->bmp2.usReserved      = 0;
   bmf_hdr->bmp2.usRecording     = BRA_BOTTOMUP;
   bmf_hdr->bmp2.usRendering     = BRH_NOTHALFTONED;
   bmf_hdr->bmp2.cSize1          = 0;
   bmf_hdr->bmp2.cSize2          = 0;
   bmf_hdr->bmp2.ulColorEncoding = BCE_RGB;
   bmf_hdr->bmp2.ulIdentifier    = 0;



//////////// Temp Code Below ..... Test Only /////////////////
//           rc = DosOpen ( (PSZ)"MOVIE.BMP", &hBMP, &ulAction, 0, FILE_NORMAL,
//                           FILE_CREATE,
//                           OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYWRITE,
//                           0L);
//
//            rc = DosWrite (hBMP, (PVOID)CIP->pImg_Buff,
//                           Min_Size,
//                           &cBytes);
//
//            rc = DosClose (hBMP);
//////////// Temp Code Above ..... Test Only /////////////////

   // Free intermidiate buffer for raw image from the card
   DosFreeMem ( (PVOID)capbufptr);

} /* endif */





return VSDERR_SUCCESS;
}


/*----------------------------------------------------------------------
 GetDevCaps

 This function returns the capabilities of the Device

 ----------------------------------------------------------------------*/

ULONG vsdGetDevCaps(HVSD_INSTANCE * phVSD,PVOID pRequest)
{
ULONG    rc;                     // return code for random usage
DWORD    i;                      // bank index
ULONG    c_entries;              // Callers entry count
ULONG    entries_to_copy;        // Byte to copy for capabilities
ULONG    org_length;             // Orignal size of Parms
VSD_GETDEVCAPS_PARMS * DC_Packet;// Caller Dev Caps packet
VSD_GETDEVCAPS_PARMS  GDC;       // Dev Caps packet just for size info



DC_Packet = (VSD_GETDEVCAPS_PARMS *)pRequest; // Capabilities packet


// Make sure Callers Packet is Large Enough to return actual Length needed
if (sizeof(GDC.ulLength) > DC_Packet->ulLength) {
   return VSDERR_INVALID_BUFF;
} /* endif */


org_length = DC_Packet->ulLength;               /* Save size of PArms List */
DC_Packet->ulLength   = phVSD->DC.ulLength;     /* Actual Size Needed      */

// Make sure Callers Packet is Large Enough to copy capabilities header into
if ((ULONG)((ULONG)&GDC.bSupports[0] -(ULONG)&GDC) > org_length) {
   return VSDERR_REQUEST_BUF_TOO_SMALL;
} /* endif */

// Copy header Info for Device capabilities
DC_Packet->ulMax_Caps = phVSD->DC.ulMax_Caps;
DC_Packet->ulNum_Caps = 0;                      /* 0 capabilities filled in   */
DC_Packet->ulResv01   = 0;
DC_Packet->ulResv02   = 0;
DC_Packet->ulResv03   = 0;
DC_Packet->ulResv04   = phVSD->VideoMode;

// Find Number of capabilities to copy
c_entries = (org_length - (ULONG)((ULONG)&GDC.bSupports -(ULONG)&GDC)) /
             sizeof(GDC.bSupports[0]);
entries_to_copy = min(c_entries,phVSD->DC.ulMax_Caps);

// Fill in capabilites (until source or destination runs out)
for (i = 0;i < entries_to_copy; i++) {
   DC_Packet->bSupports[i] = phVSD->DC.bSupports[i];
} /* endfor */

// Tell the caller how many are valid
DC_Packet->ulNum_Caps = entries_to_copy;

// Fill in any extra space is caller list with not Supported
for (i = entries_to_copy;i < c_entries; i++) {
   DC_Packet->bSupports[i] = FALSE;
} /* endfor */

return VSDERR_SUCCESS;
}

/*----------------------------------------------------------------------

    FreezeImage

    Turn off the digitizer and freeze the image in capture memory

 ----------------------------------------------------------------------*/

ULONG FreezeImage(HVSD_INSTANCE * phVSD)
{
ULONG    rc;                     // return code for random usage
ULONG    ulIoctldatasize = 0;    // data area size

   // Mark State as Freeze
   phVSD->ulFreeze                 = TRUE;

 // If hVSD is currently active tell the PDD
 if (phVSD->ulState == VSD_ulState_Restored) {

    // turn off the digitizer to freeze the image in capture memory

    ulIoctldatasize = 0;      // data area size

    rc = DosDevIOCtl(phVSD->CaptureDevHandle,   // device handle
                 (ULONG) 140,         // category
                 (ULONG) 0x73,        // set live mode (freeze)
                 0,                   // parm list
                 0,                   // parm length max
                 0,                   // parm length in/out
                 0,                   // function data area
                 0,                   // data area size
                 &ulIoctldatasize);   // data area size returned

    // Did the Device Driver Accept the command?
    if (rc) {
       return VSDERR_NO_DEVICE_DRIVER;
    } /* endif */
} /* endif */

   return VSDERR_SUCCESS;
}

/*----------------------------------------------------------------------

    unfreezeimage

    Turn on the digitizer and allow it to continuously update the image
    in capture memory.

 ----------------------------------------------------------------------*/

ULONG UnfreezeImage(HVSD_INSTANCE * phVSD)
{
ULONG    rc;                     // return code for random usage
ULONG    ulIoctldatasize = 0;    // data area size

   // Mark State as unFreeze
   phVSD->ulFreeze                 = FALSE;

 // If hVSD is currently active tell the PDD
 if (phVSD->ulState == VSD_ulState_Restored) {

    // set live/capture mode and let the digitizer free-run

    ulIoctldatasize = 0;      // data area size

    rc = DosDevIOCtl(phVSD->CaptureDevHandle,   // device handle
                 (ULONG) 140,         // category
                 (ULONG) 0x72,        // set live/capture mode (unfreeze)
                 0,                   // parm list
                 0,                   // parm length max
                 0,                   // parm length in/out
                 0,                   // function data area
                 0,                   // data area size
                 &ulIoctldatasize);   // data area size returned

    // Did the Device Driver Accept the command?
    if (rc) {
       return VSDERR_NO_DEVICE_DRIVER;
    } /* endif */
 } /* endif */

   return VSDERR_SUCCESS;
}

/*----------------------------------------------------------------------

    lockstillimage

    Perform a synchronous image capture, which may include a wait for
    vertical blanking and capture complete

 ----------------------------------------------------------------------*/

VOID lockstillimage(HVSD_INSTANCE * phVSD)
{
ULONG    rc;                     // return code for random usage
ULONG    ulIoctldatasize = 0;    // data area size

   // do a synchronous single frame capture

   ulIoctldatasize = 0;      // data area size

   rc = DosDevIOCtl(phVSD->CaptureDevHandle,   // device handle
                (ULONG) 140,         // category
                (ULONG) 0x74,        // single frame capture synchronous
                0,                   // parm list
                0,                   // parm length max
                0,                   // parm length in/out
                0,                   // function data area
                0,                   // data area size
                &ulIoctldatasize);   // data area size returned

}


VOID GetSviaBank ( BYTE scanline, USHORT xres, BYTE *bank, USHORT *b_offset)
{
BYTE     x;
BYTE     quo;
BYTE     remain;


  quo    = scanline/(BYTE)4;               // which of 4 lines in then bank group
  remain = scanline%(BYTE)4;               // which bank group

  * bank     = 0;
  * b_offset = 0;


  for (x = 0;x < quo-(BYTE)1;x++ ) {       // calculate bank and offset

     * b_offset = * b_offset + xres;

     if (*b_offset >= 1024) {           // wrap offset into next bank

        * bank = * bank + (BYTE) 1;              // move to next bank in group
        * b_offset = * b_offset - (USHORT) 1024; // wrap offset

     } /* endif */

  } /* endfor */

   *bank = (*bank * (BYTE) 4) + remain;        // group * 4 + remain = bank

}

/************************************************************************/
/* Build lookup table for bank and offset in the bank for scanlines     */
/************************************************************************/
VOID BuildSviaTable (USHORT xres)
{
BYTE     x;
BYTE     quo;
BYTE     remain;
BYTE     scanline;
BYTE     bank;
USHORT   b_offset;


 for (scanline = 0;scanline < 240; scanline++ ) {

  quo    = scanline/(BYTE)4;               // which of 4 lines in then bank group
  remain = scanline%(BYTE)4;               // which bank group

  bank     = 0;
  b_offset = 0;


  for (x = 0; x < quo; x++ ) {       // calculate bank and offset

     b_offset = b_offset + xres;

     if (b_offset >= 1024) {           // wrap offset into next bank

        bank = bank + (BYTE) 1;              // move to next bank in group
        b_offset = b_offset - (USHORT) 1024; // wrap offset

     } /* endif */

  } /* endfor */

  bank = (bank * (BYTE) 4) + remain;        // group * 4 + remain = bank

  SviaTable_bank[scanline]     = bank;      // Save info in Table
  SviaTable_b_offset[scanline] = b_offset;

 } /* endfor */

}

/*----------------------------------------------------------------------------------------
  Valid_HVSD

     Verify that the HVSD passed in is a Valid HVSD then pass back the pointer to the HSVD_INSTANCE
  ------------------------------------------------------------------------------------------*/

BOOL  Valid_HVSD (HVSD hVSD, HVSD_INSTANCE ** phVSD)
{
HVSD_INSTANCE * Curr;                       // Current  HVSD in list
ULONG  i;



for (i=0; i < MAX_NUM_HVSDS ; i++ ) {
   if ((HVSD_LIST[i] == hVSD) & (HVSD_LIST[i] != NULL)) {
      *phVSD = HVSD_LIST[i];                // Return Pointer to HVSD_INSTANCE to caller
      return TRUE;
   } /* endif */
} /* endfor */


return FALSE;                               // HVSD wasn't found in the list

}


/*----------------------------------------------------------------------------------------
  Valid_IFormat

     Verify that the HVSD passed in supports the Image Format and Bits per PEL
  ------------------------------------------------------------------------------------------*/

BOOL  Valid_IFormat (HVSD_INSTANCE * phVSD, VSD_SETIMAGEFORMAT_PARMS * SetFormat)
{
ULONG  i;
VSD_QUERYIMAGEFORMAT_PARMS * QFormat;           // Formats HVSD Supports


QFormat = phVSD->pImg_Formats;
for (i = 0;i < phVSD->ulNumFormats; i++) {

   if ((QFormat->Format[i].ulFormat == SetFormat->SetFormat.ulFormat) &
      (QFormat->Format[i].usBitsPerPEL == SetFormat->SetFormat.usBitsPerPEL))
      return TRUE;

} /* endfor */

return FALSE;                               // Format wasn't found in the list

}


/*----------------------------------------------------------------------------------------
  Valid_ParmBlock

     Verify that the Parms Block Passed in is addressable
  ------------------------------------------------------------------------------------------*/

BOOL  Valid_ParmBlock (PVOID pRequest)
{
VSD_OPEN_PARMS * Packet;                    // Request Packet
ULONG    flags;
ULONG    rc;

Packet = (VSD_OPEN_PARMS *)pRequest;        // Addressablitiy to the packet

rc =DosQueryMem (Packet, &Packet->ulLength, &flags);

if (rc != 0)
   return FALSE;

if ((flags & PAG_WRITE)!= PAG_WRITE)
   return FALSE;

return TRUE;                               // HVSD wasn't found in the list

}

/*----------------------------------------------------------------------------------------
  Add_HVSD

     Add a HSVD to the List of Valid HVSD
  ------------------------------------------------------------------------------------------*/

BOOL  Add_HVSD (HVSD_INSTANCE * pHVSD, ULONG * Index)
{
ULONG i;

for (i=0; i < MAX_NUM_HVSDS ; i++ ) {
   if (HVSD_LIST[i] == NULL) {
      HVSD_LIST[i] = pHVSD;                 // Add to List
      *Index = i;
      return TRUE;
   } /* endif */
} /* endfor */


return FALSE;                               // HVSD wasn't found in the list

}

/*----------------------------------------------------------------------------------------
  Add_PDD

     Add a PDD  to the List of Valid PDDs
  ------------------------------------------------------------------------------------------*/

BOOL Add_PDD (PSZ PDD_NAME, ULONG * Count)
{
ULONG i;
ULONG Free_Index;

Free_Index = MAX_NUM_PDDS+10;

// Check if PDD is already OPEN
for (i=0; i < MAX_NUM_PDDS ; i++ ) {
   if (PDD_Info[i].Use_Count != 0) {
      if ( strcmp(PDD_Info[i].szPDDName,PDD_NAME) == 0) {
         PDD_Info[i].Use_Count++;;            // Increment use count for this PDD
         *Count = PDD_Info[i].Use_Count;
         return TRUE;
      } /* endif */
   } else {
     if (Free_Index == (MAX_NUM_PDDS+10))     // Save Index to First Free Entry
        Free_Index = i;
   } /* endif */
} /* endfor */

if (Free_Index != (MAX_NUM_PDDS+10)) {        // Use Free Entry
   PDD_Info[i].Use_Count++;;                  // Increment use count for this PDD
   strcpy(PDD_Info[i].szPDDName,PDD_NAME);    // Fill in PDD Name
   return TRUE;
} /* endif */

return FALSE;                                 // NO Free Entries

}

/*----------------------------------------------------------------------------------------
  Remove_PDD

     Remove a PDD from the List of Valid PDDs
  ------------------------------------------------------------------------------------------*/

BOOL Remove_PDD (PSZ PDD_NAME, ULONG * Count )
{
ULONG i;

// Find PDD in the List And Decrement Use Count
for (i=0; i < MAX_NUM_PDDS ; i++ ) {
   if (PDD_Info[i].Use_Count != 0) {
      if ( strcmp(PDD_Info[i].szPDDName,PDD_NAME) == 0) {
         PDD_Info[i].Use_Count--;            // Decrement use count for this PDD
         *Count = PDD_Info[i].Use_Count;
         return TRUE;
      } /* endif */
   } /* endif */
} /* endfor */

return FALSE;                                 // PDD not found in the List

}

/*----------------------------------------------------------------------------------------
  Read_INI

     Read the .INI file info for a Device
  ------------------------------------------------------------------------------------------*/

ULONG Read_INI (PSZ PDD_NAME, PVOID * INI_Info, ULONG * Len_INI_Info, HFILE * hfINI_PDD)
{
CHAR szFail[20];
ULONG rc;


*INI_Info     = NULL;
*Len_INI_Info = 0;

 // Read in cards INI if one exists
 if (strncmp(PDD_NAME,"VIDVBC",6) == 0) {
    rc = PCV_LoadConfiguration(PDD_NAME, INI_Info, Len_INI_Info, hfINI_PDD);
    return(rc);
    } /* endif */

 if (strncmp(PDD_NAME,"VIDVCI",6) == 0){
    rc = VCA_LoadConfiguration(PDD_NAME, INI_Info, Len_INI_Info, hfINI_PDD);
    return(rc);
    } /* endif */

 if (strncmp(PDD_NAME,"VIDSVJ",6) == 0){
    rc = SVIA_LoadConfiguration(PDD_NAME, INI_Info, Len_INI_Info, hfINI_PDD);
    return(rc);
    } /* endif */

 if (strncmp(PDD_NAME,"VIDQVJ",6) == 0){
    rc = QVIA_LoadConfiguration(PDD_NAME, INI_Info, Len_INI_Info, hfINI_PDD);
    return(rc);
    } /* endif */


// strncpy( szFail, PDD_NAME,6 );        // First 7 Char of PDD Name = DLL Name
// strcat( szFail, "I.DLL" );            //  Turn into a INI file DLL name
// rc = DosLoadModule( (PSZ) szFail, CCHMAXPATH, (PSZ) szFail, &hmodVVSD );
// if (rc != NO_ERROR) {
//   return(1);                                 // No DLL to read Ini File
// } else {
//     strcpy( szFail, "Main_Entry" );         // Cards INI file dll Entry Point
//     rc = DosQueryProcAddr(hmodVVSD, 0, (PSZ) szFail, (PFN *)&VSDProcI);
//
//     if (rc != NO_ERROR) {
//        return(1);                           // Bad DLL Entry Point Not Found
// }
// } /* endif */
//
//
//  // Read In the INI File
//  RINI_request.ulLength = VSD_OPEN_Len;              // length of the structure
//
//  rc = VSDProcI ((PSZ) PDD_NAME, (PVOID) &RINI_request);
//  if (!rc) {
//     INI_Info     = RINI_request.INI_Info;
//     Len_INI_Info =RINI_request.ulLength;
//  } /* endif */
//
 return (VSDERR_NO_DEVICE_DRIVER);                 // Device Not Supported

}


PSZ  pszKey, pszValue, pszLineFound, pszData, pszChips;
//PSZ  pszINIBuffer;
char szKey[20], szChips[20],szData[200];
char szBuffer[120];
char *szToken, *stop;
WORD XCutPoint0, XCutPoint1, YCutPoint0, YCutPoint1;
WORD wMinFilter, wMedFilter, wMaxFilter;
char    szCfgFileSpec[256];
BYTE bHZoomFactor;      /* Current horizontal zoom factor (0-3) */
BYTE bVZoomFactor;      /* Current vertical zoom factor (0-3) */
BYTE bHZoomAdjust;
BYTE bVZoomAdjust;
WORD wBoardType;
WORD wImageWidth;
WORD wImageHeight;
WORD wImageType;
int  iVideoMode;        /* Current graphics mode */
//CFGSTRUCT config;
ACQUISITIONRECT AcquisitionWindow[2] = {
                {0x00, 0x1C, 0x2F8, 0x21C},
                {0x00, 0x1C, 0x278, 0x1F4}
                };
BYTE    aDefColorTbl[NO_COLOR_CONTROLS];        /* Defaults color table */
MODE    aDefMode[NO_VIDEO_MODES+1];             /* Defaults mode dependent parameters */
WORD    aModeRange[NO_SKEW_FACTORS] = {DISPWINSKEWXRANGE,DISPWINSKEWYRANGE,
        DISPADDRSKEWXRANGE,DISPADDRSKEWYRANGE,SHIFTCLOCKSTARTRANGE,
        PALETTESKEWRANGE,PLLDIVISORRANGE};
char    aDevString[16][80];     /* for saving platform specific */
                                /* initialization data.  Support up to */
                                /* 16 different platforms and each platform */
                                /* 80 characters */
int     DevCnt=0;               /* number of valid platform entries found */
                                /* in the initialization file */

/************************************************************************
* PCV_LoadConfiguration                                                 *
*                                                                       *
* Reads in the PC Video configuration file.                             *
*                                                                       *
* Exit: return code                                                     *
*       = TRUE     Success                                              *
*       = FALSE    File does not exist or is Invalid                    *
************************************************************************/
ULONG PCV_LoadConfiguration(PSZ PDD_NAME, PVOID * INIBuffer,
                           ULONG * ulINIFileSize, HFILE  * hfINIHandle)
{
int   fd, i, j;
int   iRegCount, iChipsCount, iRegIndex=0;
WORD  *Ptr;             /* Word pointer */
BYTE  *bPtr;            /* Byte pointer */
WORD  wTemp;
PSZ     p, pszEnv;
PSZ     pszINIBuffer;
ULONG   rc=MCIERR_SUCCESS;
CFGSTRUCT * config;

/* Get a buffer for HVSD state Information                                */
rc = DosAllocMem ( (PVOID *) &config, (ULONG) sizeof(CFGSTRUCT),
                  PAG_COMMIT | PAG_READ | PAG_WRITE);

if (rc) {
   return VSDERR_INSUFFICIENT_MEMORY;
} /* endif */

*INIBuffer     = config;
*ulINIFileSize = sizeof(CFGSTRUCT);

  /******************************************/
  /* Open and read in VBLASTER.ini file     */
  /******************************************/
  if (!DosScanEnv("MMBASE", &pszEnv))
    {
      strcpy(pszINIFile, pszEnv);

      if (p = strchr(pszINIFile, ';')) *p = 0;

      strcat(pszINIFile, "\\");
    }
  else
    {
      strcpy(pszINIFile, "c:\\");
    }

   strcat(pszINIFile, PDD_NAME);
   strcat(pszINIFile, ".INI");

   rc = ReadFileToBuffer(pszINIFile,
                        (ULONG)OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE,
                        &pszINIBuffer,
                        ulINIFileSize,
                        hfINIHandle);
  if (rc)
     return(MCIERR_INI_FILE);


//  pszINIBuffer = *INIBuffer;

////#ifdef DOSLIB
//        getcwd((LPSTR) &szCfgFileSpec,144);
//        strcpy (szCfgFileSpec,"D:\\MMOS2");
//        i = strlen(szCfgFileSpec)-1;
//        if ( szCfgFileSpec[i] == '\\')
//           strcat(szCfgFileSpec,"pcvideo.ini");
//        else
//           strcat(szCfgFileSpec,"\\pcvideo.ini");
////#else
////        GetWindowsDirectory((LPSTR) &szCfgFileSpec,144);
////        wsprintf((LPSTR) &szCfgFileSpec,"%s\\pcvideo.ini",(LPSTR) &szCfgFileSpec);
////#endif
//        if((fd = fileopen((LPSTR) &szCfgFileSpec, "r")) == -1)
//            return(FALSE);                      /* File does not exist. */
//        fileclose(fd);

  if (IniQuery(pszINIBuffer, "pcvideo", "BufferType",
           &pszLineFound, (PSZ)szData))
     {
     return(MCIERR_INI_FILE);
     }
  else
     {
     if (stricmp(szData,"RGB16")==0)
          wBoardType=BT_RGB16;               /* RGB16 */
     else if (stricmp(szData,"RGB24")==0)
          wBoardType=BT_RGB24;               /* RGB24 */
     else if (stricmp(szData,"YUV411")==0)   /* YUV411 */
          wBoardType=BT_YUV411;
     else return(MCIERR_INI_FILE);           /* Boardtype not support */
     config->wBoardType=wBoardType;
     }

  config->wCfgFlags = 0;                    /* Init to zero */

  if (IniQuery(pszINIBuffer, "pcvideo", "PLL",
           &pszLineFound, (PSZ)szData))
     return(MCIERR_INI_FILE);
  else
     if (stricmp(szData,"Yes")==0)
          config->wCfgFlags |= CF_HASPLL;
     else config->wCfgFlags &= ~CF_HASPLL;

  if (IniQuery(pszINIBuffer, "pcvideo", "PortAddr",
           &pszLineFound, (PSZ)szData))
     return(MCIERR_INI_FILE);
  else
     config->wPortAddr=strtoul(szData, &stop,0);

  if (IniQuery(pszINIBuffer, "pcvideo", "VideoAddr",
           &pszLineFound, (PSZ)szData))
     return(MCIERR_INI_FILE);
  else
     config->wVideoAddr=strtoul(szData, &stop,0);

  if (IniQuery(pszINIBuffer, "pcvideo", "VideoFormat",
           &pszLineFound, (PSZ)szData))
     return(MCIERR_INI_FILE);
  else
     if ( stricmp(szData, "NTSC") == 0 )
          config->wCfgFlags |= CF_NTSC;       /* NTSC */
     else if ( (stricmp(szData, "SECAM") == 0) &&
               (wBoardType != BT_YUV411) )
          config->wCfgFlags |= CF_SECAM;      /* SECAM */
     else
          config->wCfgFlags |= CF_PAL;        /* PAL */

  if (IniQuery(pszINIBuffer, "pcvideo", "VideoSource",
           &pszLineFound, (PSZ)szData))
     return(MCIERR_INI_FILE);
  else
     config->wVideoSource=strtoul(szData, &stop,0);

  if (IniQuery(pszINIBuffer, "pcvideo", "PALAcquisitionWindow",
           &pszLineFound, (PSZ)szData))
     return(MCIERR_INI_FILE);
  else {
     szToken = strtok(szData, " ");
     Ptr = &config->wPALAcqWindow[0];
     while ( szToken !=NULL){
           *Ptr=strtoul(szToken,&stop,0); /* Convert data to value */
           Ptr++;                         /* Increase word pointer */
           szToken=strtok(NULL," ");      /* Get the next token string */
           }
     }

  if (IniQuery(pszINIBuffer, "pcvideo", "NTSCAcquisitionWindow",
           &pszLineFound, (PSZ)szData))
     return(MCIERR_INI_FILE);
  else {
     szToken = strtok(szData, " ");
//   Ptr = &AcquisitionWindow[1].aX1;
     Ptr = &config->wNSTCAcqWindow[0];
     while ( szToken !=NULL){
           *Ptr=strtoul(szToken,&stop,0); /* Convert data to value */
           Ptr++;                         /* Increase word pointer */
           szToken=strtok(NULL," ");      /* Get the next token string */
           }
     }

  if (IniQuery(pszINIBuffer, "pcvideo", "RegCount", &pszLineFound, (PSZ)szData))
     return(MCIERR_INI_FILE);
  else
     iRegCount=config->PCVideoTable.cPCVideoRegs=strtoul(szData, &stop,0);
     for( i=0; i<iRegCount; i++){    /* Loop to get the register value */
         sprintf(szKey,"Reg%X",iRegIndex);
         if( IniQuery(pszINIBuffer,"pcvideo", szKey, &pszLineFound, (PSZ)szData))
            i--;                     /* Skip register does not exist */
         else {
            config->PCVideoTable.aPCVideoRegs[i].rIndex=iRegIndex;
            config->PCVideoTable.aPCVideoRegs[i].rData=strtoul(szData,&stop,0);
            }
         iRegIndex++;                /* Increase register index */
         }

  if (IniQuery(pszINIBuffer, "I2CChips", "ChipsCount", &pszLineFound, (PSZ)szData))
     return(MCIERR_INI_FILE);
  else
     iChipsCount=config->PhixelTable.cPhixelChips=strtoul(szData, &stop,0);
     for(i=0; i<iChipsCount; i++){
         sprintf(szKey,"Chip%d", i+1);
         IniQuery(pszINIBuffer, "I2CChips", szKey, &pszLineFound, (PSZ)szChips);
         strcpy(config->PhixelTable.aPhixelChips[i].aChipID, szChips);
         IniQuery(pszINIBuffer, szChips, "I2CAddr", &pszLineFound, (PSZ)szData);
         config->PhixelTable.aPhixelChips[i].wPhixelAddr=strtoul(szData, &stop,0);
         IniQuery(pszINIBuffer, szChips, "RegCount", &pszLineFound, (PSZ)szData);
         iRegCount=config->PhixelTable.aPhixelChips[i].cPhixelRegs=strtoul(szData,&stop,0);
         for( j=0; j<iRegCount;j++)  {/* Initialize PHIXELCHIP */
              sprintf(szKey,"Reg%X", j);
              IniQuery(pszINIBuffer, szChips, szKey, &pszLineFound, (PSZ)szData);
              config->PhixelTable.aPhixelChips[i].aPhixelRegs[j].rIndex=j;
              config->PhixelTable.aPhixelChips[i].aPhixelRegs[j].rData=strtoul(szData,&stop,0);
              }
         }

  if (IniQuery(pszINIBuffer, "Filter","Min", &pszLineFound, (PSZ)szData))
     wMinFilter = 0x8A;
  else
     wMinFilter = strtoul(szData,&stop,0);

  if (IniQuery(pszINIBuffer, "Filter","Med", &pszLineFound, (PSZ)szData))
     wMedFilter = 0x2A;
  else
     wMedFilter = strtoul(szData,&stop,0);

  if (IniQuery(pszINIBuffer, "Filter","Max", &pszLineFound, (PSZ)szData))
     wMaxFilter = 0x4A;
  else
     wMaxFilter = strtoul(szData,&stop,0);


  if (!(IniQuery(pszINIBuffer, "Filter", "XCutPoint0", &pszLineFound, (PSZ)szData)))
     XCutPoint0 = strtoul(szData,&stop,0);
  if (!(IniQuery(pszINIBuffer, "Filter", "XCutPoint1", &pszLineFound, (PSZ)szData)))
     XCutPoint1 = strtoul(szData,&stop,0);
  if (!(IniQuery(pszINIBuffer, "Filter", "YCutPoint0", &pszLineFound, (PSZ)szData)))
     YCutPoint0 = strtoul(szData,&stop,0);
  if (!(IniQuery(pszINIBuffer, "Filter", "YCutPoint1", &pszLineFound, (PSZ)szData)))
     YCutPoint1 = strtoul(szData,&stop,0);

  /* Initialize aMode */
  for( i=0; i<NO_VIDEO_MODES; i++){
      sprintf(szKey, "Mode%d", i);
      IniQuery(pszINIBuffer, "ModeInfo", szKey, &pszLineFound, (PSZ)szBuffer);
      szToken=strtok(szBuffer," ");       /* Get token string */
      Ptr= &config->aMode[i].DispWinSkewX; /* Get destination pointer */
      while ( szToken !=NULL){
          *Ptr=strtoul(szToken,&stop,0);  /* Convert data to value */
          Ptr++;                          /* Increase word pointer */
          szToken=strtok(NULL," ");       /* Get the next token string */
      }
  }

  if (IniQuery(pszINIBuffer, "ModeInfo", "CurVideoMode", &pszLineFound, (PSZ)szBuffer)==0){
      szToken=strtok(szBuffer," ");       /* Get token string */
      Ptr= &config->aMode[NO_VIDEO_MODES].DispWinSkewX;
                                          /* Get destination pointer */
      while ( szToken !=NULL){
          *Ptr=strtoul(szToken,&stop,0);  /* Convert data to value */
          Ptr++;                          /* Increase word pointer */
          szToken=strtok(NULL," ");       /* Get the next token string */
      }
  }

  /* Initialize mode defaults table */
  for( i=0; i<NO_VIDEO_MODES; i++){
      sprintf(szKey, "Mode%d", i);
      IniQuery(pszINIBuffer, "ModeDef", szKey, &pszLineFound, (PSZ)szBuffer);
      szToken=strtok(szBuffer," ");       /* Get token string */
      Ptr= &aDefMode[i].DispWinSkewX;     /* Get destination pointer */
      while ( szToken !=NULL){
          *Ptr=strtoul(szToken,&stop,0);  /* Convert data to value */
          Ptr++;                          /* Increase word pointer */
          szToken=strtok(NULL," ");       /* Get the next token string */
      }
  }
  Ptr= &aDefMode[NO_VIDEO_MODES].DispWinSkewX;
  for (i=0;i<sizeof(MODE)/2;i++)
     *Ptr++ = (WORD)0;

  /* Initialize color control */
  IniQuery(pszINIBuffer, "ColorCtrl", "Controls", &pszLineFound, (PSZ)szBuffer);
  szToken = strtok(szBuffer," ");     /* Get token string */
  bPtr= config->bColorSettings;
  while ( szToken !=NULL){
      *bPtr=strtoul(szToken,&stop,0); /* Convert data to value */
      bPtr++;                         /* Increase byte pointer */
      szToken=strtok(NULL," ");       /* Get the next token string */
      }

  /* Initialize color defaults table */
  IniQuery(pszINIBuffer, "ColorDef", "Controls", &pszLineFound, (PSZ)szBuffer);
  szToken = strtok(szBuffer," ");     /* Get token string */
  bPtr= &aDefColorTbl[0];
  while ( szToken !=NULL){
      *bPtr=strtoul(szToken,&stop,0); /* Convert data to value */
      bPtr++;                         /* Increase byte pointer */
      szToken=strtok(NULL," ");       /* Get the next token string */
      }

  for (j=0; j < config->PCVideoTable.cPCVideoRegs; j++)
     if (config->PCVideoTable.aPCVideoRegs[j].rIndex == 0x50) {
        config->wCfgFlags |= (config->PCVideoTable.aPCVideoRegs[j].rData & REPLICATE_ON);
      break;
      }

        return(MCIERR_SUCCESS);
}


/************************************************************************
* PCV_SaveConfiguration                                                 *
*                                                                       *
* Saves the system configuration to pcvideo.ini.                        *
*                                                                       *
* Exit: return code                                                     *
*       = 1 TRUE   Success                                              *
*       = 0 FALSE  File does not exist.                                 *
*                                                                       *
* Note:   The configuration structure is given in PCVIDEO.H.            *
************************************************************************/
BOOL PCV_SaveConfiguration(PVOID INI_Parms, ULONG INI_Parms_Len)
{
FILE   *fd;
int     i,j;
int     iRegCount, iChipsCount;
WORD    *Ptr, *Ptr2;            /* Word pointer */
BYTE    *bPtr;                  /* Byte pointer */
char    szData[200], szBuffer[120], szData2[200];
CHAR    pszINIfile[260];
PSZ     pszINIBuffer;
ULONG   ulINIFileSize;
HFILE   hfINIHandle;
ULONG   rc;
CFGSTRUCT * config;

config = (CFGSTRUCT *)INI_Parms;

//remove(pszINIFile);
strcpy(pszINIfile, "c:\\MMOS2\\VBLAST.INI");

   rc = ReadFileToBuffer(pszINIfile,
                        (ULONG)OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE,
                        &pszINIBuffer,
                        &ulINIFileSize,
                        &hfINIHandle);
  if (rc)
     return(MCIERR_INI_FILE);


//if ((fd = fopen("c:\\MMOS2\\VBLAST.INI", "w+")) == NULL)
//    return 0;   /* Could not create file */

for (j=0; j < config->PCVideoTable.cPCVideoRegs; j++)    // Preserve the replicated filed bit
    if (config->PCVideoTable.aPCVideoRegs[j].rIndex == 0x50) {
        config->PCVideoTable.aPCVideoRegs[j].rData |= (config->wCfgFlags & REPLICATE_ON);
    break;
    }

/* Save PCVIDEO info */
rc = IniUpdate (pszINIBuffer, "PCVIDEO","BufferType", "YUV411");

if (wBoardType == BT_RGB16 )        /* RGB16 format */
    IniUpdate (pszINIBuffer, "PCVIDEO","BufferType", "RGB16");
else if (wBoardType == BT_RGB24 )           /* RGB24 format */
    IniUpdate (pszINIBuffer, "PCVIDEO","BufferType", "RGB24");
else                                /* YUV format */
    IniUpdate (pszINIBuffer, "PCVIDEO","BufferType", "YUV411");

if( (config->wCfgFlags & CF_HASPLL) == CF_HASPLL )
    IniUpdate (pszINIBuffer, "PCVIDEO","PLL", "Yes");
else
    IniUpdate (pszINIBuffer, "PCVIDEO","PLL", "No");

sprintf(szData, "0x%X", config->wPortAddr);
IniUpdate (pszINIBuffer, "PCVIDEO","PortAddr", szData);

sprintf(szData, "0x%02X", config->wVideoAddr);
IniUpdate (pszINIBuffer, "PCVIDEO","VideoAddr", szData);

if( (config->wCfgFlags & (CF_NTSC) ) == CF_NTSC ) /* NTSC format */
    IniUpdate (pszINIBuffer, "PCVIDEO","VideoFormat", "NTSC");
else if ((config->wCfgFlags & (CF_SECAM) ) == CF_SECAM)
    IniUpdate (pszINIBuffer, "PCVIDEO","VideoFormat", "SECAM");
else                        /* PAL format */
    IniUpdate (pszINIBuffer, "PCVIDEO","VideoFormat", "PAL");

sprintf(szData, "%d", config->wVideoSource);
IniUpdate (pszINIBuffer, "PCVIDEO","VideoSource", szData);

Ptr= &AcquisitionWindow[0].aX1;         /* Get source pointer */
strcpy(szBuffer, "");
for (i = 0; i<4; i++){
    sprintf(szData, "0x%02X ", *Ptr);
    strcat(szBuffer, szData);
    Ptr++;                              /* Advanced pointer */
    }
IniUpdate (pszINIBuffer, "PCVIDEO","PALAcquisitionWindow", szBuffer);

Ptr= &AcquisitionWindow[1].aX1;         /* Get source pointer */
strcpy(szBuffer, "");
for (i = 0; i<4; i++){
    sprintf(szData, "0x%02X ", *Ptr);
    strcat(szBuffer, szData);
    Ptr++;                              /* Advanced pointer */
    }
IniUpdate (pszINIBuffer, "PCVIDEO","NTSCAcquisitionWindow", szBuffer);

sprintf(szBuffer, "%d", config->PCVideoTable.cPCVideoRegs);
IniUpdate (pszINIBuffer, "PCVIDEO","RegCount", szBuffer);

/* Save PCVIDEO register value */
iRegCount=config->PCVideoTable.cPCVideoRegs;
for( i=0; i<iRegCount; i++){
   sprintf(szBuffer, "REG%X",  config->PCVideoTable.aPCVideoRegs[i].rIndex);
   sprintf(szData,   "0x%02X", config->PCVideoTable.aPCVideoRegs[i].rData);
   IniUpdate (pszINIBuffer, "PCVIDEO", szBuffer, szData);
      }

// **********************************************************************
/* Save Phixel Chips info */
iChipsCount=config->PhixelTable.cPhixelChips;
sprintf(szData, "%d", iChipsCount);
IniUpdate (pszINIBuffer, "I2CChips", "ChipsCount", szData);
for(i=0; i< iChipsCount; i++){
  sprintf(szBuffer, "Chip%d", i+1);
  sprintf(szData, "Chip%d", i+1);
  IniUpdate (pszINIBuffer, "I2CChips", szBuffer, config->PhixelTable.aPhixelChips[i].aChipID);
  }

// ************************************************************************
/* Save Phixel chips registers value */
for(i=0; i< iChipsCount; i++){
  sprintf(szData, "0x%X", config->PhixelTable.aPhixelChips[i].wPhixelAddr);
  IniUpdate (pszINIBuffer, config->PhixelTable.aPhixelChips[i].aChipID, "I2CAddr", szData);
  sprintf(szData, "%d", config->PhixelTable.aPhixelChips[i].cPhixelRegs);
  IniUpdate (pszINIBuffer, config->PhixelTable.aPhixelChips[i].aChipID, "RegCount", szData);

  iRegCount=config->PhixelTable.aPhixelChips[i].cPhixelRegs;
  for( j=0; j<iRegCount; j++){          /* Save register value */
    sprintf(szBuffer, "Reg%X", config->PhixelTable.aPhixelChips[i].aPhixelRegs[j].rIndex);
    sprintf(szData, "0x%02X", config->PhixelTable.aPhixelChips[i].aPhixelRegs[j].rData);
    IniUpdate (pszINIBuffer, config->PhixelTable.aPhixelChips[i].aChipID, szBuffer, szData);
  }
}
//*********************************************************************
/* Save Filter Info */
sprintf(szData, "0x%02X", wMinFilter);
IniUpdate (pszINIBuffer, "Filter", "Min", szData);

sprintf(szData, "0x%02X", wMedFilter);
IniUpdate (pszINIBuffer, "Filter", "Med", szData);

sprintf(szData, "0x%02X", wMaxFilter);
IniUpdate (pszINIBuffer, "Filter", "Max", szData);

sprintf(szData, "%d", XCutPoint0);
IniUpdate (pszINIBuffer, "Filter", "XCutPoint0", szData);

sprintf(szData, "%d", XCutPoint1);
IniUpdate (pszINIBuffer, "Filter", "XCutPoint1", szData);

sprintf(szData, "%d", YCutPoint0);
IniUpdate (pszINIBuffer, "Filter", "YCutPoint0", szData);

sprintf(szData, "%d", YCutPoint1);
IniUpdate (pszINIBuffer, "Filter", "YCutPoint1", szData);

// ***************************************************************
/* Save Mode Info */

sprintf(szData, "%d", NO_VIDEO_MODES);
IniUpdate (pszINIBuffer, "ModeInfo", "ModeCount", szData);

if (iVideoMode != NO_VIDEO_MODES) {
   Ptr2= & config->aMode[NO_VIDEO_MODES].DispWinSkewX;/* Destination ptr */
   Ptr = & config->aMode[iVideoMode].DispWinSkewX;    /* Source ptr      */
   for ( j=0;j<sizeof(MODE)/2;j++)
     *Ptr2++ = *Ptr++;
}

Ptr= & config->aMode[0].DispWinSkewX;    /* Get source pointer */
for(i=0;i< NO_VIDEO_MODES+1;i++){               /* Set Mode table */
   if (i != NO_VIDEO_MODES)
       sprintf(szBuffer, "Mode%d", i);
   else
       sprintf(szBuffer,"CurVideoMode");
   strcpy(szData2,"");
   for ( j=0;j<sizeof(MODE)/2;j++){     /* Formate the mode data */
     if ( *Ptr == (WORD) 0 )
        sprintf(szData, "%d ", *Ptr);
     else
        sprintf(szData, "0x%02X ", *Ptr);
     Ptr++;                             /* Advanced pointer */
     strcat(szData2,szData);
     }
   IniUpdate (pszINIBuffer, "ModeInfo", szBuffer, szData2);
   }

//*********************************************************************
/* Save mode defaults */

sprintf(szData, "%d", NO_VIDEO_MODES);
IniUpdate (pszINIBuffer, "ModeDef", "ModeCount", szData);

Ptr= & aDefMode[0].DispWinSkewX;        /* Get source pointer */
for(i=0;i< NO_VIDEO_MODES;i++){         /* Set Mode table */
   sprintf(szBuffer,"Mode%d",i);
   strcpy(szData2,"");
   for ( j=0;j<sizeof(MODE)/2;j++){     /* Formate the mode data */
     if ( *Ptr == (WORD) 0 )
        sprintf(szData, "%d ", *Ptr);
     else
        sprintf(szData, "0x%02X ", *Ptr);
     strcat(szData2, szData);
     Ptr++;                             /* Advanced pointer */
     }
   IniUpdate (pszINIBuffer, "ModeDef", szBuffer, szData2);
   }

//************************************************************************
/* Save color information */

bPtr= config->bColorSettings;            /* Get source pointer */
strcpy(szData2,"");
for ( i=0; i<7; i++){                   /* Formate the CorlorCtrl data */
     sprintf(szData, "0x%02X ", *bPtr);
     strcat(szData2, szData);
     bPtr++;
     }
IniUpdate (pszINIBuffer, "ColorCtrl", "Controls", szData2);

//************************************************************************
/* Save color defaults table */

bPtr= &aDefColorTbl[0];                 /* Get source pointer */
strcpy(szData2,"");
for ( i=0; i<7; i++){                   /* Formate the CorlorCtrl data */
     sprintf(szData, "0x%02X ", *bPtr);
     strcat(szData2, szData);
     bPtr++;
     }
IniUpdate (pszINIBuffer, "ColorDef", "Controls", szData2);

//************************************************************************
//        /* Save platform specific information */
//        if (DevCnt) {
//            stringf(szBuffer, "[PLATFORM]\r\n");
//            if(filewrite(fd, (LPSTR) szBuffer, strlen(szBuffer))!=
//                strlen(szBuffer))
//                return 0;
//            for(i=0; i<DevCnt; i++) {
//                if(filewrite(fd, (LPSTR)aDevString[i], strlen(aDevString[i]))!=
//                    strlen(aDevString[i]))
//                    return 0;
//            }
//        }
//
rc = WriteBufferToFile(hfINIHandle, pszINIBuffer);
rc = IniFileClose(hfINIHandle);
return(1);
}
//

/************************************************************************
* VCA_LoadConfiguration                                                 *
*                                                                       *
* Reads in the VCA Video configuration .INI file.                       *
*                                                                       *
* Exit: return code                                                     *
*       = TRUE     Success                                              *
*       = FALSE    File does not exist or is Invalid                    *
************************************************************************/
ULONG VCA_LoadConfiguration(PSZ PDD_NAME,
                           PVOID * ParsedInfo, ULONG * ParsedInfo_len,
                           HFILE  * hfINIHandle)
{
int   fd, i, j;
int   iRegCount, iChipsCount, iRegIndex=0;
WORD  *Ptr;             /* Word pointer */
BYTE  *bPtr;            /* Byte pointer */
WORD  wTemp;
PSZ     p, pszEnv;
PSZ     pszINIBuffer;
ULONG   rc=MCIERR_SUCCESS;
VCAINIT * config;
ULONG   ulINIFileSize;


/* Get a buffer for HVSD state Information                                */
rc = DosAllocMem ( (PVOID *) &config, (ULONG) sizeof(VCAINIT),
                  PAG_COMMIT | PAG_READ | PAG_WRITE);

if (rc) {
   return VSDERR_INSUFFICIENT_MEMORY;
} /* endif */

*ParsedInfo      = config;
*ParsedInfo_len = sizeof(VCAINIT);

  /******************************************/
  /* Open and read in VBLASTER.ini file     */
  /******************************************/
  if (!DosScanEnv("MMBASE", &pszEnv))
    {
      strcpy(pszINIFile, pszEnv);

      if (p = strchr(pszINIFile, ';')) *p = 0;

      strcat(pszINIFile, "\\");
    }
  else
    {
      strcpy(pszINIFile, "c:\\");
    }

   strcat(pszINIFile, PDD_NAME);
   strcat(pszINIFile, ".INI");

   rc = ReadFileToBuffer(pszINIFile,
                        (ULONG)OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE,
                        &pszINIBuffer,
                        &ulINIFileSize,
                        hfINIHandle);
  if (rc)
     return(MCIERR_INI_FILE);


  if (IniQuery(pszINIBuffer, "VideoAdj", "Color",
           &pszLineFound, (PSZ)szData))
     return(MCIERR_INI_FILE);
  else
     config->ulSaturation=strtoul(szData, &stop,0);

  if (IniQuery(pszINIBuffer, "VideoAdj", "Contrast",
           &pszLineFound, (PSZ)szData))
     return(MCIERR_INI_FILE);
  else
     config->ulContrast=strtoul(szData, &stop,0);

  if (IniQuery(pszINIBuffer, "VideoAdj", "Brightness",
           &pszLineFound, (PSZ)szData))
     return(MCIERR_INI_FILE);
  else
     config->ulBrightness=strtoul(szData, &stop,0);

  if (IniQuery(pszINIBuffer, "VideoAdj", "Tint",
           &pszLineFound, (PSZ)szData))
     return(MCIERR_INI_FILE);
  else
     config->ulHue=strtoul(szData, &stop,0);

  /* What is the Input Source (composite, RGB, or Y/C) */
  if (IniQuery(pszINIBuffer, "VideoAdj", "VideoSource",
           &pszLineFound, (PSZ)szData))
     config->bControl = (BYTE) VCAC_NTSC_or_YC;
  else
     if (stricmp(szData,"RGB")==0)
          config->bControl = VCAC_RGB;
     else
        if (stricmp(szData,"YC")==0)
           config->bControl = VCAC_YC_DECODE;
        else
             config->bControl = VCAC_NTSC_or_YC;

  /* Image captured in RGB565 format */
  config->bControl |= VCAC_FORMAT_565;

  /* Enable or Disable External Monitor */
  if (IniQuery(pszINIBuffer, "VideoAdj", "DisplayEnable",
           &pszLineFound, (PSZ)szData))
     config->bControl |= VCAC_DISPLAY_ENABLE;
  else
     if (stricmp(szData,"No")!=0)
        config->bControl |= VCAC_DISPLAY_ENABLE;
     else;

  /* Gen Lock  */
  if (IniQuery(pszINIBuffer, "VideoAdj", "GenLock",
           &pszLineFound, (PSZ)szData))
     config->bControl |= VCAC_GEN_LOCK;
  else
     if (stricmp(szData,"No")!=0)
        config->bControl |= VCAC_GEN_LOCK;
     else;

  /* Out to external Monitr Sync on Green  */
  if (IniQuery(pszINIBuffer, "VideoAdj", "OutputSyncGreen",
           &pszLineFound, (PSZ)szData))
      ;
  else
     if (stricmp(szData,"Yes")==0)
        config->bControl |= VCAC_OUTOUT_SYNC_GREEN;
     else;

  /* Sync Lock Position */
  if (IniQuery(pszINIBuffer, "VideoAdj", "CapturePos",
           &pszLineFound, (PSZ)szData))
        config->bCapPos = VCACP_Default_Pos;
  else
     config->bCapPos=(strtoul(szData, &stop,0) & 0x1F);

  /* Lines Per Field */
  if (IniQuery(pszINIBuffer, "VideoAdj", "LinesPerField",
           &pszLineFound, (PSZ)szData))
      ;
  else
     config->bCapPos |=((strtoul(szData, &stop,0) & 0x7)<<5);

  return(MCIERR_SUCCESS);
}

/************************************************************************
* QVIA_LoadConfiguration                                                *
*                                                                       *
* Reads in the Quick VIA configuration .INI file.                       *
*                                                                       *
* Exit: return code                                                     *
*       = TRUE     Success                                              *
*       = FALSE    File does not exist or is Invalid                    *
************************************************************************/
ULONG QVIA_LoadConfiguration(PSZ PDD_NAME,
                           PVOID * ParsedInfo, ULONG * ParsedInfo_len,
                           HFILE  * hfINIHandle)
{
int   fd, i, j;
int   iRegCount, iChipsCount, iRegIndex=0;
WORD  *Ptr;             /* Word pointer */
BYTE  *bPtr;            /* Byte pointer */
WORD  wTemp;
PSZ     p, pszEnv;
PSZ     pszINIBuffer;
ULONG   rc=MCIERR_SUCCESS;
VCAINITG * config;
ULONG   ulINIFileSize;


/* Get a buffer for HVSD state Information                                */
rc = DosAllocMem ( (PVOID *) &config, (ULONG) sizeof(config),
                  PAG_COMMIT | PAG_READ | PAG_WRITE);

if (rc) {
   return VSDERR_INSUFFICIENT_MEMORY;
} /* endif */

*ParsedInfo      = config;
*ParsedInfo_len = sizeof(VCAINIT);

  /******************************************/
  /* Open and read in QuickVIA.ini file     */
  /******************************************/
  if (!DosScanEnv("MMBASE", &pszEnv))
    {
      strcpy(pszINIFile, pszEnv);

      if (p = strchr(pszINIFile, ';')) *p = 0;

      strcat(pszINIFile, "\\");
    }
  else
    {
      strcpy(pszINIFile, "c:\\");
    }

   strcat(pszINIFile, PDD_NAME);
   strcat(pszINIFile, ".INI");

   rc = ReadFileToBuffer(pszINIFile,
                        (ULONG)OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE,
                        &pszINIBuffer,
                        &ulINIFileSize,
                        hfINIHandle);
  if (rc)
     return(MCIERR_INI_FILE);


  if (IniQuery(pszINIBuffer, "VideoAdj", "Color",
           &pszLineFound, (PSZ)szData))
     return(MCIERR_INI_FILE);
  else
     config->ulSaturation=strtoul(szData, &stop,0);

  if (IniQuery(pszINIBuffer, "VideoAdj", "Contrast",
           &pszLineFound, (PSZ)szData))
     return(MCIERR_INI_FILE);
  else
     config->ulContrast=strtoul(szData, &stop,0);

  if (IniQuery(pszINIBuffer, "VideoAdj", "Brightness",
           &pszLineFound, (PSZ)szData))
     return(MCIERR_INI_FILE);
  else
     config->ulBrightness=strtoul(szData, &stop,0);

  if (IniQuery(pszINIBuffer, "VideoAdj", "Tint",
           &pszLineFound, (PSZ)szData))
     return(MCIERR_INI_FILE);
  else
     config->ulHue=strtoul(szData, &stop,0);

  /* What is the Input Source (composite, or Y/C) */
  if (IniQuery(pszINIBuffer, "VideoAdj", "VideoSource",
           &pszLineFound, (PSZ)szData))
     config->bD_Info[0] = 0;
  else
     if (stricmp(szData,"YC")==0)
        config->bD_Info[0] = 1;
     else
        config->bD_Info[0] = 0;


  /* Sync Lock Position Horizontal */
  if (IniQuery(pszINIBuffer, "VideoAdj", "HorizontalPos",
           &pszLineFound, (PSZ)szData))
        config->bD_Info[1] = 0x20;   // Default
  else
     config->bD_Info[1]=(strtoul(szData, &stop,0) & 0x3F);

  /* Sync Lock Position Vertical */
  if (IniQuery(pszINIBuffer, "VideoAdj", "VerticalPos",
           &pszLineFound, (PSZ)szData))
        config->bD_Info[2] = 0x20;   // Default
  else
     config->bD_Info[2]=(strtoul(szData, &stop,0) & 0x3F);

  /* Horizontal low pass Filter */
  if (IniQuery(pszINIBuffer, "VideoAdj", "HFilter",
           &pszLineFound, (PSZ)szData))
        config->bD_Info[3] = 0x20;   // Default
  else
     config->bD_Info[3]=(strtoul(szData, &stop,0) & 0x3F);

  return(MCIERR_SUCCESS);
}

/************************************************************************
* SVIA_LoadConfiguration                                                *
*                                                                       *
* Reads in the SuperVIA Video configuration .INI file.                  *
*                                                                       *
* Exit: return code                                                     *
*       = TRUE     Success                                              *
*       = FALSE    File does not exist or is Invalid                    *
************************************************************************/
ULONG SVIA_LoadConfiguration(PSZ PDD_NAME,
                           PVOID * ParsedInfo, ULONG * ParsedInfo_len,
                           HFILE  * hfINIHandle)
{
int   fd, i, j;
int   iRegCount, iChipsCount, iRegIndex=0;
WORD  *Ptr;             /* Word pointer */
BYTE  *bPtr;            /* Byte pointer */
WORD  wTemp;
PSZ     p, pszEnv;
PSZ     pszINIBuffer;
ULONG   rc=MCIERR_SUCCESS;
VCAINITG * config;
ULONG   ulINIFileSize;


/* Get a buffer for INI Information                                */
rc = DosAllocMem ( (PVOID *) &config, (ULONG) sizeof(VCAINIT),
                  PAG_COMMIT | PAG_READ | PAG_WRITE);

if (rc) {
   return VSDERR_INSUFFICIENT_MEMORY;
} /* endif */

*ParsedInfo     = config;
*ParsedInfo_len = sizeof(VCAINIT);

  /******************************************/
  /* Open and read in VBLASTER.ini file     */
  /******************************************/
  if (!DosScanEnv("MMBASE", &pszEnv))
    {
      strcpy(pszINIFile, pszEnv);

      if (p = strchr(pszINIFile, ';')) *p = 0;

      strcat(pszINIFile, "\\");
    }
  else
    {
      strcpy(pszINIFile, "c:\\");
    }

   strcat(pszINIFile, PDD_NAME);
   strcat(pszINIFile, ".INI");

   rc = ReadFileToBuffer(pszINIFile,
                        (ULONG)OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE,
                        &pszINIBuffer,
                        &ulINIFileSize,
                        hfINIHandle);
  if (rc)
     return(MCIERR_INI_FILE);





  if (IniQuery(pszINIBuffer, "VideoAdj", "Color",
           &pszLineFound, (PSZ)szData))
     return(MCIERR_INI_FILE);
  else
     config->ulSaturation=strtoul(szData, &stop,0);

  config->ulContrast=0;

  if (IniQuery(pszINIBuffer, "VideoAdj", "Brightness",
           &pszLineFound, (PSZ)szData))
     return(MCIERR_INI_FILE);
  else
     config->ulBrightness=strtoul(szData, &stop,0);

  if (IniQuery(pszINIBuffer, "VideoAdj", "Tint",
           &pszLineFound, (PSZ)szData))
     return(MCIERR_INI_FILE);
  else
     config->ulHue=strtoul(szData, &stop,0);

  /* What is the Input Source (composite, RGB, or Y/C) */
  if (IniQuery(pszINIBuffer, "VideoAdj", "VideoSource",
           &pszLineFound, (PSZ)szData))
     config->bD_Info[0] = 0;        /* Default to Composite if None */
  else
     if (stricmp(szData,"RGB")==0)
        config->bD_Info[0] = 2;
     else
        if (stricmp(szData,"YC")==0)
           config->bD_Info[0] = 1;
        else
           config->bD_Info[0] = 0;  /* Default to Composite if Invalid Value */


  return(MCIERR_SUCCESS);
}

