home *** CD-ROM | disk | FTP | other *** search
/ Black Box 4 / BlackBox.cdr / os2 / ati256c1.arj / ATIPAT2.C < prev    next >
Encoding:
Text File  |  1992-05-18  |  27.2 KB  |  729 lines

  1. /*************************************************************************
  2.  * File  ATIPAT2.C                       v1.00
  3.  *
  4.  * Date:  1992/05/18
  5.  *
  6.  * Author:      Joel Armengaud
  7.  *
  8.  * This file is the source code of ATIPAT2.EXE, the utility to
  9.  * patch the 256c PM video driver for ATI Wonder video adapter.
  10.  * I included this source because some customers reported problems
  11.  * with some Wonder models. So a hacker will be able with this
  12.  * source code to see what happens... and eventually report to
  13.  * me how to modify it! I can be reached at the following
  14.  * e-mail address:
  15.  *
  16.  *              ARMENGAU@FRECP12.BITNET
  17.  *
  18.  * How it works:
  19.  *
  20.  *   The ATI Wonder cards have special extended registers to access hi-res
  21.  * modes. These registers can be accessed using I/O ports 1BEh/1BFh.
  22.  * When the PM driver must switch to the 256-color mode, it has to initialize
  23.  * both standard VGA registers and ATI extended registers to the values
  24.  * required for 256c. When you leave the PM screen (switching
  25.  * to a full-screen session), the OS/2 base video handler (BVHVGA.DLL)
  26.  * will only initialize the standard VGA registers, because it does not
  27.  * know about the ATI extended registers. Therefore we must restore
  28.  * the ATI extended registers when leaving the PM session.
  29.  *
  30.  *   So I have declared, at the beginning of this file, 2 data
  31.  * structures:
  32.  *
  33.  *   Data1      To completely initialize the video registers for
  34.  *              for the 256c mode (both standard and extended registers)
  35.  *   Data2      To restore to standard VGA.
  36.  *
  37.  *   These 2 data structures are used to patch 2 areas in the
  38.  * driver .DLL file. I use two special strings to find the offset
  39.  * of the areas in the file ("Magic1" and "Magic2").
  40.  * These strings just precede the actual area. Let me describe the
  41.  * 2 areas:
  42.  *
  43.  *      Area 1 (Precede by string "Magic1"):
  44.  *             (To initialize to 256-color mode)
  45.  *  Offset      Value (hex)     Comment
  46.  *     00        64             *do not patch*
  47.  *     01        29             *do not patch*
  48.  *     02        0E             *do not patch*
  49.  *     03        00             *do not patch*
  50.  *     04        F0             *do not patch*
  51.  *     05        01             Sequencer register index 1
  52.  *     06        0F             Sequencer register index 2
  53.  *     07        00             Sequencer register index 3
  54.  *     08        5A             Sequencer register index 4
  55.  *     09        23             Miscellaneous output register
  56.  *     0A        7F             CRT register index 0
  57.  *     0B        63             CRT register index 1
  58.  *     0C        65             CRT register index 2
  59.  *     0D        9D             CRT register index 3
  60.  *     0E        66             CRT register index 4
  61.  *     0F        9C             CRT register index 5
  62.  *     10        38             CRT register index 6
  63.  *     11        1F             CRT register index 7
  64.  *     12        00             CRT register index 8
  65.  *     13        00             CRT register index 9
  66.  *     14        00             CRT register index 10
  67.  *     15        00             CRT register index 11
  68.  *     16        00             CRT register index 12
  69.  *     17        00             CRT register index 13
  70.  *     18        00             CRT register index 14
  71.  *     19        00             CRT register index 15
  72.  *     1A        2C             CRT register index 16
  73.  *     1B        8E             CRT register index 17
  74.  *     1C        2B             CRT register index 18
  75.  *     1D        32             CRT register index 19
  76.  *     1E        0F             CRT register index 20
  77.  *     1F        32             CRT register index 21
  78.  *     20        34             CRT register index 22
  79.  *     21        E7             CRT register index 23
  80.  *     22        FF             CRT register index 24
  81.  *     23        00             Attribute Controller register 0
  82.  *     24        01             Attribute Controller register 1
  83.  *     25        02             Attribute Controller register 2
  84.  *     26        03             Attribute Controller register 3
  85.  *     27        04             Attribute Controller register 4
  86.  *     28        05             Attribute Controller register 5
  87.  *     29        14             Attribute Controller register 6
  88.  *     2A        07             Attribute Controller register 7
  89.  *     2B        38             Attribute Controller register 8
  90.  *     2C        39             Attribute Controller register 9
  91.  *     2D        3A             Attribute Controller register 10
  92.  *     2E        3B             Attribute Controller register 11
  93.  *     2F        3C             Attribute Controller register 12
  94.  *     30        3D             Attribute Controller register 13
  95.  *     31        3E             Attribute Controller register 14
  96.  *     32        3F             Attribute Controller register 15
  97.  *     33        01             Attribute Controller register 16
  98.  *     34        00             Attribute Controller register 17
  99.  *     35        0F             Attribute Controller register 18
  100.  *     36        00             Attribute Controller register 19
  101.  *     37        80             Graphics Controller register 0
  102.  *     38        00             Graphics Controller register 1
  103.  *     39        00             Graphics Controller register 2
  104.  *     3A        00             Graphics Controller register 3
  105.  *     3B        00             Graphics Controller register 4
  106.  *     3C        00             Graphics Controller register 5
  107.  *     3D        05             Graphics Controller register 6
  108.  *     3E        0F             Graphics Controller register 7
  109.  *     3F        FF             Graphics Controller register 8
  110.  *     40        B0             Index of ATI extended register
  111.  *     41        29             Value for extended register B0
  112.  *     42        B1             Index of ATI extended register
  113.  *     43        00             Value for extended register B1
  114.  *     44        B3             Index of ATI extended register
  115.  *     45        00             Value for extended register B3
  116.  *     46        B5             Index of ATI extended register
  117.  *     47        08             Value for extended register B5
  118.  *     48        B6             Index of ATI extended register
  119.  *     49        04             Value for extended register B6
  120.  *     4A        B8             Index of ATI extended register
  121.  *     4B        00             Value for extended register B8
  122.  *     4C        B9             Index of ATI extended register
  123.  *     4D        33             Value for extended register B9
  124.  *     4E        BE             Index of ATI extended register
  125.  *     4F        00             Value for extended register BE
  126.  *     50        A7             Index of ATI extended register
  127.  *     51        00             Value for extended register A7
  128.  *
  129.  *      Area 2 (Precede by string "Magic2"):
  130.  *             (To restore to VGA standard mode)
  131.  *  Offset      Value (hex)     Comment
  132.  *     00        50             *do not patch*
  133.  *     01        18             *do not patch*
  134.  *     02        10             *do not patch*
  135.  *     03        00             *do not patch*
  136.  *     04        10             *do not patch*
  137.  *     05        00             Sequencer register index 1
  138.  *     06        03             Sequencer register index 2
  139.  *     07        00             Sequencer register index 3
  140.  *     08        02             Sequencer register index 4
  141.  *     09        67             Miscellaneous output register
  142.  *     0A        5F             CRT register index 0
  143.  *     0B        4F             CRT register index 1
  144.  *     0C        50             CRT register index 2
  145.  *     0D        82             CRT register index 3
  146.  *     0E        55             CRT register index 4
  147.  *     0F        81             CRT register index 5
  148.  *     10        BF             CRT register index 6
  149.  *     11        1F             CRT register index 7
  150.  *     12        00             CRT register index 8
  151.  *     13        00             CRT register index 9
  152.  *     14        00             CRT register index 10
  153.  *     15        00             CRT register index 11
  154.  *     16        00             CRT register index 12
  155.  *     17        00             CRT register index 13
  156.  *     18        00             CRT register index 14
  157.  *     19        00             CRT register index 15
  158.  *     1A        9C             CRT register index 16
  159.  *     1B        8E             CRT register index 17
  160.  *     1C        8F             CRT register index 18
  161.  *     1D        28             CRT register index 19
  162.  *     1E        1F             CRT register index 20
  163.  *     1F        96             CRT register index 21
  164.  *     20        B9             CRT register index 22
  165.  *     21        A3             CRT register index 23
  166.  *     22        FF             CRT register index 24
  167.  *     23        00             Attribute Controller register 0
  168.  *     24        01             Attribute Controller register 1
  169.  *     25        02             Attribute Controller register 2
  170.  *     26        03             Attribute Controller register 3
  171.  *     27        04             Attribute Controller register 4
  172.  *     28        05             Attribute Controller register 5
  173.  *     29        14             Attribute Controller register 6
  174.  *     2A        07             Attribute Controller register 7
  175.  *     2B        38             Attribute Controller register 8
  176.  *     2C        39             Attribute Controller register 9
  177.  *     2D        3A             Attribute Controller register 10
  178.  *     2E        3B             Attribute Controller register 11
  179.  *     2F        3C             Attribute Controller register 12
  180.  *     30        3D             Attribute Controller register 13
  181.  *     31        3E             Attribute Controller register 14
  182.  *     32        3F             Attribute Controller register 15
  183.  *     33        0C             Attribute Controller register 16
  184.  *     34        00             Attribute Controller register 17
  185.  *     35        0F             Attribute Controller register 18
  186.  *     36        08             Attribute Controller register 19
  187.  *     37        00             Graphics Controller register 0
  188.  *     38        00             Graphics Controller register 1
  189.  *     39        00             Graphics Controller register 2
  190.  *     3A        00             Graphics Controller register 3
  191.  *     3B        00             Graphics Controller register 4
  192.  *     3C        10             Graphics Controller register 5
  193.  *     3D        0E             Graphics Controller register 6
  194.  *     3E        00             Graphics Controller register 7
  195.  *     3F        FF             Graphics Controller register 8
  196.  *     40        B0             Index of ATI extended register
  197.  *     41        08             Value for extended register B0
  198.  *     42        B1             Index of ATI extended register
  199.  *     43        00             Value for extended register B1
  200.  *     44        B3             Index of ATI extended register
  201.  *     45        00             Value for extended register B3
  202.  *     46        B5             Index of ATI extended register
  203.  *     47        08             Value for extended register B5
  204.  *     48        B6             Index of ATI extended register
  205.  *     49        00             Value for extended register B6
  206.  *     4A        B8             Index of ATI extended register
  207.  *     4B        40             Value for extended register B8
  208.  *     4C        B9             Index of ATI extended register
  209.  *     4D        33             Value for extended register B9
  210.  *     4E        BE             Index of ATI extended register
  211.  *     4F        10             Value for extended register BE
  212.  *     50        A7             Index of ATI extended register
  213.  *     51        00             Value for extended register A7
  214.  *
  215.  *  The following program tries to switch to 256c mode (bios
  216.  * mode 63h or 64h), read the video registers in this mode, goes back to
  217.  * standard VGA mode (bios mode 03, color text), and read extended
  218.  * register values in this mode.
  219.  *  Then it tries to apply patches to the file.
  220.  *
  221.  *  The Data1 and Data2 structures determine the video registers
  222.  * we want to patch.
  223.  *
  224.  *  On some configurations, switching to hires bios video modedoes not
  225.  * work (why??). That's why I test the CRT registers in this mode
  226.  * to determine if the hardware number of video lines is correct.
  227.  * If it is not, I print a warning message.
  228.  *
  229.  *  This file is compiled with Microsoft C6.00A, as a DOS program.
  230.  * No special considerations to compile it.
  231.  *
  232.  *  Now I let you dig into the code to understand it!
  233.  *
  234.  *              -Joel Armengaud
  235.  *
  236.  */
  237.  
  238. #include <stdio.h>
  239. #include <dos.h>
  240.  
  241. typedef unsigned short USHORT ;
  242. typedef unsigned char  BYTE ;
  243.  
  244. #define INDEXE    0x0001
  245. #define DIRECT    0x0002
  246. #define ATTR_TYPE 0x0003
  247. #define ATI_TYPE  0x0004
  248. #define THEEND    0x8000
  249.  
  250. /***********************/
  251. /* Video i/o addresses */
  252.  
  253. #define CRT    0x3D4                    /* CRT address on color board */
  254. #define SEQ    0x3C4                    /* Sequencer                  */
  255. #define GRC    0x3CE                    /* Graphics Controller        */
  256. #define MISC   0x3CC                    /* Misc Output Reg (read addr)*/
  257. #define ATT    0x3C0                    /* Attribute Controller       */
  258. #define ATI    0x1CE                    /* ATI extended registers     */
  259.  
  260. #define NB_MAGIC_STRINGS        2
  261. #define MAX_STRUCT           0x52
  262.  
  263.  
  264. typedef struct _DATASTRUCT {
  265.        BYTE    Data ;                   /* Data read from hardware */
  266.        USHORT  Flag ;                   /* Type of video register */
  267.        USHORT  Port ;                   /* I/O port */
  268.        BYTE    Index ;                  /* Register index */
  269.        long    FileOffset ;             /* Offset from Magic string */
  270.        } DATASTRUCT ;
  271.  
  272.  
  273. DATASTRUCT Data1 [] = {                         // Hires mode
  274.        {0x00,  DIRECT,  MISC, 0x00, 0x09},     /* We patch the misc register */
  275.        {0x00,  INDEXE,  CRT,  0x00, 0x0A},     /* And so on... */
  276.        {0x00,  INDEXE,  CRT,  0x01, 0x0B},
  277.        {0x00,  INDEXE,  CRT,  0x02, 0x0C},
  278.        {0x00,  INDEXE,  CRT,  0x03, 0x0D},
  279.        {0x00,  INDEXE,  CRT,  0x04, 0x0E},
  280.        {0x00,  INDEXE,  CRT,  0x05, 0x0F},
  281.        {0x00,  INDEXE,  CRT,  0x06, 0x10},
  282.        {0x00,  INDEXE,  CRT,  0x07, 0x11},     // Needed for CRT lines
  283.        {0x00,  INDEXE,  CRT,  0x08, 0x12},
  284.        {0x00,  INDEXE,  CRT,  0x09, 0x13},
  285.        {0x00,  INDEXE,  CRT,  0x10, 0x1A},
  286.        {0x00,  INDEXE,  CRT,  0x11, 0x1B},
  287.        {0x00,  INDEXE,  CRT,  0x12, 0x1C},     // Needed for CRT lines
  288.        {0x00,  INDEXE,  CRT,  0x13, 0x1D},
  289.        {0x00,  INDEXE,  CRT,  0x14, 0x1E},
  290.        {0x00,  INDEXE,  CRT,  0x15, 0x1F},
  291.        {0x00,  INDEXE,  CRT,  0x16, 0x20},
  292.        {0x00,  INDEXE,  CRT,  0x17, 0x21},
  293.        {0x09,  ATI_TYPE, ATI, 0xB0, 0x41},
  294.        {0x00,  ATI_TYPE, ATI, 0xB1, 0x43},
  295.        {0x00,  ATI_TYPE, ATI, 0xB3, 0x45},
  296.        {0x08,  ATI_TYPE, ATI, 0xB5, 0x47},
  297.        {0x00,  ATI_TYPE, ATI, 0xB6, 0x49},
  298.        {0x00,  ATI_TYPE, ATI, 0xB8, 0x4B},
  299.        {0x33,  ATI_TYPE, ATI, 0xB9, 0x4D},
  300.        {0x00,  ATI_TYPE, ATI, 0xBE, 0x4F},
  301.        {0x00,  ATI_TYPE, ATI, 0xA7, 0x51},
  302.        {0x00,  THEEND,  CRT,  0x00},
  303.        } ;
  304.  
  305. DATASTRUCT Data2 [] = {                         // Lowres mode (mode 3)
  306.        {0x00,  DIRECT,  MISC, 0x00, 0x09},
  307.        {0x00,  INDEXE,  CRT,  0x00, 0x0A},
  308.        {0x00,  INDEXE,  CRT,  0x01, 0x0B},
  309.        {0x00,  INDEXE,  CRT,  0x02, 0x0C},
  310.        {0x00,  INDEXE,  CRT,  0x03, 0x0D},
  311.        {0x00,  INDEXE,  CRT,  0x04, 0x0E},
  312.        {0x00,  INDEXE,  CRT,  0x05, 0x0F},
  313.        {0x00,  INDEXE,  CRT,  0x06, 0x10},
  314.        {0x00,  INDEXE,  CRT,  0x07, 0x11},
  315.        {0x00,  INDEXE,  CRT,  0x10, 0x1A},
  316.        {0x00,  INDEXE,  CRT,  0x11, 0x1B},
  317.        {0x00,  INDEXE,  CRT,  0x12, 0x1C},
  318.        {0x00,  INDEXE,  CRT,  0x15, 0x1F},
  319.        {0x00,  INDEXE,  CRT,  0x16, 0x20},
  320.        {0x09,  ATI_TYPE, ATI, 0xB0, 0x41},
  321.        {0x00,  ATI_TYPE, ATI, 0xB1, 0x43},
  322.        {0x00,  ATI_TYPE, ATI, 0xB3, 0x45},
  323.        {0x08,  ATI_TYPE, ATI, 0xB5, 0x47},
  324.        {0x00,  ATI_TYPE, ATI, 0xB6, 0x49},
  325.        {0x00,  ATI_TYPE, ATI, 0xB8, 0x4B},
  326.        {0x33,  ATI_TYPE, ATI, 0xB9, 0x4D},
  327.        {0x00,  ATI_TYPE, ATI, 0xBE, 0x4F},
  328.        {0x00,  ATI_TYPE, ATI, 0xA7, 0x51},
  329.        {0x00,  THEEND,  CRT,  0x00},
  330.        } ;
  331.  
  332. typedef struct _PATCH {
  333.      char       *pszMagicString ;
  334.      DATASTRUCT *psData ;
  335.      } PATCH ;
  336.  
  337. PATCH Patch [NB_MAGIC_STRINGS] = {
  338.      {"Magic1", Data1 },
  339.      {"Magic2", Data2 }
  340.      } ;
  341.  
  342. #define MAGIC_STRING_RESOLUTION  "MagicResolution"
  343.  
  344.  
  345. /*************************************************************************
  346.  * Locate a string in a file (case sensitive...)
  347.  * Return seek position of the first char following the string
  348.  *  or LONG_ERROR
  349.  *  or LONG_NOT_FOUND        (both are negative values)
  350.  *
  351.  * Limitation: string size should be less  than SIZE_BUFFER
  352.  */
  353.  
  354. #define STAGE_0 0
  355. #define STAGE_1 1
  356. #define STAGE_2 2
  357. #define STAGE_3 3
  358.  
  359. #define LONG_ERROR      -2L
  360. #define LONG_NOT_FOUND  -1L
  361. #define SIZE_BUFFER     512
  362.  
  363. BYTE achBuffer [2 * SIZE_BUFFER] ;
  364.  
  365.  
  366. long FindString (FILE *hFile, char *szString)
  367.    {
  368.    BYTE    fStage ;
  369.    size_t  cRead ;
  370.    size_t  cCharInFirstPartBuffer ;
  371.    size_t  cSizeString ;
  372.    USHORT  i ;
  373.    long    lFilePos ;
  374.  
  375.    /* Return to begining of file */
  376.    if (fseek (hFile, 0L, SEEK_SET))
  377.       return LONG_ERROR ;               /* fseek failed */
  378.  
  379.    cSizeString = strlen (szString) ;
  380.    lFilePos = 0L ;
  381.    fStage   = STAGE_0 ;
  382.    do
  383.       {
  384.       if (fStage == STAGE_0)
  385.          {
  386.          cRead = fread (achBuffer, 1, SIZE_BUFFER, hFile) ;
  387.          if (cRead == SIZE_BUFFER)
  388.             fStage = STAGE_1 ;
  389.          else
  390.             fStage = STAGE_2 ;
  391.          }
  392.  
  393.       if (fStage == STAGE_1)
  394.          {
  395.          cRead = fread (&achBuffer[SIZE_BUFFER], 1, SIZE_BUFFER, hFile) ;
  396.          }
  397.  
  398.       /***********************************************/
  399.       /* Try to find first char in first part buffer */
  400.       cCharInFirstPartBuffer = (fStage == STAGE_2 ? cRead : SIZE_BUFFER) ;
  401.       for (i = 0; i < cCharInFirstPartBuffer; i++)
  402.          {
  403.          if (achBuffer[i] == *szString)
  404.             {
  405.             /*********************************/
  406.             /* Then compare the whole string */
  407.             if (   strncmp (&achBuffer[i], szString, cSizeString) == 0
  408.                 && (i + cSizeString <=
  409.                     cCharInFirstPartBuffer
  410.                     + (fStage == STAGE_1 ? cRead : 0) ))
  411.                {
  412.                /* String found! */
  413.                return (lFilePos + i + cSizeString) ;
  414.                }
  415.             }
  416.          }
  417.  
  418.       /* Copy second part into first part */
  419.       memcpy (achBuffer, &achBuffer[SIZE_BUFFER], SIZE_BUFFER) ;
  420.  
  421.       lFilePos += SIZE_BUFFER ;
  422.  
  423.       if (fStage == STAGE_1 && cRead < SIZE_BUFFER)
  424.          fStage = STAGE_2 ;
  425.       else if (fStage == STAGE_2)
  426.          fStage = STAGE_3 ;
  427.       }
  428.    while (fStage != STAGE_3) ;
  429.  
  430.    return LONG_NOT_FOUND ;
  431.    }
  432.  
  433.  
  434. /*************************************************************************
  435.  *
  436.  *  Patch file with new video register values
  437.  */
  438.  
  439. void PatchFile (char *szFileName)
  440.    {
  441.    USHORT i, j ;
  442.    long   lFilePos ;
  443.    BYTE   achTempBuffer[MAX_STRUCT+1] ;         /* Room for all registers */
  444.    FILE  *hFile ;
  445.  
  446.  
  447.    hFile =  fopen (szFileName, "rb+") ;   /* Both read and write */
  448.    if (hFile == NULL)
  449.       {
  450.       printf ("Error: cannot open file %s\n", szFileName) ;
  451.       exit (1) ;
  452.       }
  453.  
  454.    /* For each magic strings */
  455.    for (i = 0; i < NB_MAGIC_STRINGS; i++)
  456.       {
  457.       /* Locate magic string in file */
  458.       lFilePos = FindString (hFile, Patch[i].pszMagicString) ;
  459.       if (lFilePos < 0)
  460.          {
  461.          if (lFilePos == LONG_NOT_FOUND)
  462.            printf ("Error: incorrect file\n") ;
  463.          else
  464.            printf ("Error: cannot read file\n") ;
  465.          exit (1) ;
  466.          }
  467.  
  468.       /* Read zone to patch */
  469.       if (fseek (hFile, lFilePos, SEEK_SET))
  470.          {
  471.          printf ("Error: cannot read file\n") ;
  472.          exit (1) ;
  473.          }
  474.       if (fread (achTempBuffer, 1, MAX_STRUCT, hFile)
  475.           != MAX_STRUCT)
  476.          {
  477.          printf ("Error: cannot read file\n") ;
  478.          exit (1) ;
  479.          }
  480.  
  481.       /* Now patch the buffer */
  482.       for (j = 0; Patch[i].psData[j].Flag != THEEND; j++)
  483.          {
  484.          if (achTempBuffer[ (USHORT)Patch[i].psData[j].FileOffset ]
  485.              != Patch[i].psData[j].Data)
  486.             {
  487. #ifdef DEBUG
  488.             printf ("File patched at offset %08lX  %02X->%02X\n",
  489.                     lFilePos+Patch[i].psData[j].FileOffset,
  490.                     achTempBuffer[ (USHORT)Patch[i].psData[j].FileOffset ],
  491.                     Patch[i].psData[j].Data) ;
  492. #endif
  493.             achTempBuffer[ (USHORT)Patch[i].psData[j].FileOffset ]
  494.                = Patch[i].psData[j].Data ;
  495.             }
  496.          }
  497.  
  498.       /* And write back to the file */
  499.       if (fseek (hFile, lFilePos, SEEK_SET))
  500.          {
  501.          printf ("Error: cannot read file\n") ;
  502.          exit (1) ;
  503.          }
  504.       if (fwrite (achTempBuffer, 1, MAX_STRUCT, hFile)
  505.           != MAX_STRUCT)
  506.          {
  507.          printf ("Error: cannot write to file\n") ;
  508.          exit (1) ;
  509.          }
  510.       }
  511.  
  512.    fclose (hFile) ;             /* Done! */
  513.    }
  514.  
  515.  
  516. /*************************************************************************
  517.  *
  518.  *  Find driver resolution. The resolution is encoded in the .DLL
  519.  *   file immediately after the string "MagicResolution".
  520.  */
  521. BYTE FindBiosVideoMode (char *szFileName, USHORT *pusHiresLines)
  522.    {
  523.    long   lFilePos ;
  524.    FILE  *hFile ;
  525.  
  526.    hFile =  fopen (szFileName, "rb") ;    /* Read a binary file */
  527.    if (hFile == NULL)
  528.       {
  529.       printf ("Error: cannot open file %s\n", szFileName) ;
  530.       exit (1) ;
  531.       }
  532.  
  533.    /* Locate magic string */
  534.    lFilePos = FindString (hFile, MAGIC_STRING_RESOLUTION) ;
  535.    if (lFilePos < 0)
  536.       {
  537.       if (lFilePos == LONG_NOT_FOUND)
  538.          printf ("Error: incorrect file\n") ;
  539.       else
  540.          printf ("Error: cannot read file\n") ;
  541.       exit (1) ;
  542.       }
  543.  
  544.    /* Read zone to patch */
  545.    if (fseek (hFile, lFilePos, SEEK_SET))
  546.       {
  547.       printf ("Error: cannot read file\n") ;
  548.       exit (1) ;
  549.       }
  550.    if (fread (pusHiresLines, 1, 2, hFile) /* Read 2 bytes */
  551.        != 2)
  552.       {
  553.       printf ("Error: cannot read file\n") ;
  554.       exit (1) ;
  555.       }
  556.    fclose (hFile) ;
  557.  
  558.    /* Now return bios video mode  */
  559.    /* 600 lines -> 0x63           */
  560.    /* 768 lines -> 0x64           */
  561.    return (*pusHiresLines == 600 ? 0x63 : 0x64) ;
  562.    }
  563.  
  564. /*************************************************************************
  565.  *
  566.  *  Read video registers, and fill the data structure.
  567.  */
  568.  
  569. void ReadRegisters (DATASTRUCT *psData)
  570.    {
  571.    USHORT Port ;
  572.    USHORT i ;
  573.    BYTE   Index ;
  574.    BYTE   bResult ;
  575.  
  576.    for (i = 0; psData[i].Flag != THEEND; i++)
  577.       {
  578.       switch (psData[i].Flag)
  579.          {
  580.          case INDEXE:
  581.             {
  582.             Port  = psData[i].Port ;
  583.             Index = psData[i].Index ;
  584.             _asm {                      /* Dirty, but efficient... */
  585.                 mov  dx, Port
  586.                 mov  al, Index
  587.                 cli
  588.                 out  dx, al
  589.                 inc  dx
  590.                 in   al, dx
  591.                 sti
  592.                 mov  bResult, al
  593.                 } ;
  594.             }
  595.             break ;
  596.          case ATTR_TYPE:
  597.             {
  598.             Port  = psData[i].Port ;
  599.             Index = psData[i].Index ;
  600.             _asm {
  601.                 cli
  602.                 mov  dx, 03BAh          /* Reset flip-flop */
  603.                 in   al, dx
  604.                 mov  dx, 03DAh
  605.                 in   al, dx
  606.                 mov  dx, Port
  607.                 mov  al, Index
  608.                 or   al, 20H
  609.                 out  dx, al
  610.                 inc  dx
  611.                 in   al, dx
  612.                 sti
  613.                 mov  bResult, al
  614.                 } ;
  615.             }
  616.             break ;
  617.          case ATI_TYPE:               /* How to access ATI registers... */
  618.             {
  619.             Port  = psData[i].Port ;
  620.             Index = psData[i].Index ;
  621.             _asm {
  622.                 mov  dx, Port
  623.                 mov  al, Index
  624.                 cli
  625.                 out  dx, al
  626.                 inc  dx
  627.                 in   al, dx
  628.                 sti
  629.                 mov  bResult, al
  630.                 } ;
  631.             }
  632.             break ;
  633.          case DIRECT:
  634.             {
  635.             Port  = psData[i].Port ;
  636.             _asm {
  637.                 mov  dx, Port
  638.                 in   al, dx
  639.                 mov  bResult, al
  640.                 } ;
  641.             }
  642.             break ;
  643.          }
  644.       psData[i].Data = bResult ;
  645.       }
  646.    }
  647.  
  648. int SelectMode (BYTE Mode)               /* Switch to a BIOS video mode */
  649.    {
  650.    BYTE ActualMode ;
  651.  
  652.    _asm {
  653.         mov  al, Mode
  654.         xor  ah, ah
  655.         int  10H
  656.         mov  ah, 0Fh
  657.         int  10H
  658.         mov  ActualMode, al
  659.         }
  660.    if (ActualMode == Mode)
  661.       return 1 ;
  662.    else return 0 ;
  663.    }
  664.  
  665. main (argc, argv)
  666. int   argc ;
  667. char *argv[] ;
  668.    {
  669.    BYTE   bCrt07 ;
  670.    BYTE   bCrt12 ;
  671.    BYTE   bHires ;
  672.    USHORT i ;
  673.    USHORT usNumLines ;
  674.    USHORT usHiresLines ;
  675.  
  676.    if (argc != 2)
  677.       {
  678.       printf ("Usage:  ATIPAT2 <file_name>\n"
  679.               "Where file_name is the name of the driver file\n") ;
  680.       exit (1) ;
  681.       }
  682.  
  683.    /**********************************************************/
  684.    /* Find hires bios video mode, using the driver file.     */
  685.    /* That is:                                               */
  686.    /*    0x63 for 800x600x256                                */
  687.    /*    0x64 for 1024x768x256                               */
  688.    bHires = FindBiosVideoMode (argv[1], &usHiresLines) ;
  689.  
  690.    SelectMode (bHires) ;                /* Enable 256c mode  */
  691.    ReadRegisters (Patch[0].psData) ;    /* Fill Data1 structure */
  692.    SelectMode (0x03) ;                  /* Back to 80x25 color text */
  693.    ReadRegisters (Patch[1].psData) ;    /* Fill Data2 structure */
  694.  
  695. #ifdef DEBUG
  696.    printf ("Number of lines: %d\n", usHiresLines) ;
  697. #endif
  698.  
  699.    /**********************************************/
  700.    /* Find index for CRT registers 0x07 and 0x12 */
  701.    for (i = 0; Patch[0].psData[i].Flag != THEEND; i++)
  702.       {
  703.       if (Patch[0].psData[i].Port == CRT)
  704.          {
  705.          if (Patch[0].psData[i].Index == 0x07)
  706.             bCrt07 = Patch[0].psData[i].Data ;
  707.          else if (Patch[0].psData[i].Index == 0x12)
  708.             bCrt12 = Patch[0].psData[i].Data ;
  709.          }
  710.       }
  711.    /***************************************************************/
  712.    /* Find actual number of video lines using registers 07 and 12 */
  713.    usNumLines =   (bCrt12 + ((USHORT)(bCrt07 & 0x02) << 7)
  714.                           + ((USHORT)(bCrt07 & 0x40) << 3))
  715.                    + 1 ;
  716.  
  717.    /******************/
  718.    /* Patch the file */
  719.    PatchFile (argv[1]) ;
  720.  
  721.    /**************************/
  722.    /* Check number of lines. */
  723.    if (usNumLines != usHiresLines && usNumLines != usHiresLines/2)
  724.       printf ("*** Warning *** Problem initializing VGA Wonder in 256-color mode!\n"
  725.               "Driver will probably not work!\n") ;
  726.    else
  727.       printf ("\n File %s successfully patched!\n", argv[1]) ;
  728.    }
  729.