[Back to EGAVGA SWAG index] [Back to Main SWAG index] [Original]

    {
         Hi Kai.  I read your message about 360x256x256 and saw you were using
    Tweak.  This is message 1/2 which includes Pascal versions of Twkuser.c
    and Tweak2c.  Thought they might be helpful to you.

    Maurice L. Marvin
    maurice@cs.pdx.edu
    }

    {$I-}
    UNIT TWKUSER;

    {=========================================================================
      TWKUSER.PAS is a Borland Pascal 7.0 compatible unit for using Robert
      Schmidt's TWEAK generated files.

      Ported to Pascal from Robert Schmidt's original C code.

      Donated to public domain.

      Maurice L. Marvin
      maurice@cs.pdx.edu
     ==========================================================================}

    INTERFACE

     CONST

        { xxxxADDR defines the base port number used to access VGA
          component xxxx, and is defined for xxxx =
               ATTRCON    -   Attribute Controller
               MISC       -   Miscellaneous Register
               VGAENABLE  -   VGA Enable Register
               SEQ        -   Sequencer
               GRACON     -   Graphics Controller
               CRTC       -   Cathode Ray Tube Controller
               STATUS     -   Status Register }

        ATTRCON_ADDR        = $3C0;
        MISC_ADDR           = $3C2;
        VGAENABLE_ADDR      = $3C3;
        SEQ_ADDR            = $3C4;
        GRACON_ADDR         = $3CE;
        CRTC_ADDR           = $3D4;
        STATUS_ADDR         = $3DA;

     TYPE

        Register = RECORD
                      port   : WORD;
                      index  : BYTE;
                      value  : BYTE;
                   END;

        RegisterPtr = ^Register;

    PROCEDURE ReadyVgaRegs;
    PROCEDURE OutReg(r : Register);
    PROCEDURE OutRegArray(r : RegisterPtr;
                          n : INTEGER);
    FUNCTION  LoadRegArray(fpath        : STRING;
                           VAR RegArray : RegisterPtr) : INTEGER;

    IMPLEMENTATION

    {--------------------------------------------------------------------------
      ReadyVGARegs does the initialization to make the VGA ready to accept
      any combination of configuration register settings.

      This involves enabling writes to index 0 to 7 of the CRT controller
      (port $3d4), by clearing the most significant bit (bit 7) of index
      $11.
     --------------------------------------------------------------------------}

    PROCEDURE ReadyVGARegs;

     VAR

        v : BYTE;

     BEGIN {*** Begin procedure ReadyVGARegs ***}
        Port[$3d4] := $11;
        v := Port[$3d5] AND $7f;
        Port[$3d4] := $11;
        Port[$3d5] := v;
     END;  {*** End procedure ReadyVGARegs ***}

    {--------------------------------------------------------------------------
      OutReg sets a single register according to the contents of the passed
      Register structure.
     --------------------------------------------------------------------------}

    PROCEDURE OutReg(r : Register);

     VAR

        v : BYTE;

     BEGIN {*** Begin procedure OutReg ***}
        CASE (r.port) OF
           ATTRCON_ADDR   : BEGIN
                               v := Port[STATUS_ADDR]; { Reset read/write flip flop
    }                           Port[ATTRCON_ADDR] := r.index OR $20;
                               { Ensure VGA output is enabled }
                               Port[ATTRCON_ADDR] := r.value;
                            END;
           MISC_ADDR,
           VGAENABLE_ADDR : BEGIN
                               Port[r.port] := r.value; { Directly to the port }
                            END;
           ELSE { Default method }
                            BEGIN
                               Port[r.port] := r.index; { Index to port }
                               Port[r.port + 1] := r.value; { Value to port + 1}
                            END;
        END;
     END;  {*** End procedure OutReg ***}

    {--------------------------------------------------------------------------
      OutRegArray sets n registers according to the array pointed to by r.
      First, indexes 0-7 of the CRT controller are enabled for writing.
     --------------------------------------------------------------------------}

    PROCEDURE OutRegArray(r : RegisterPtr;
                          n : INTEGER);

     VAR

        s : WORD;

     BEGIN {*** Begin procedure OutRegArray ***}
        s := SizeOf(Register);
        ReadyVGARegs;
        WHILE (n > 0) DO
           BEGIN
              OutReg(r^);
              ASM { Increment pointer to next record }
                 MOV DX,s
                 ADD WORD PTR [r],DX
              END;
              DEC(n);
           END;
     END;  {*** End procedure OutRegArray ***}

    {--------------------------------------------------------------------------
      LoadRegArray opens the given file, does some validity checking, then
      reads the entire file into an array of Registers, which is returned
      via the RegArray parameter.

      You will probably want to provide your own error handling code in this
      function, as it never aborts the program, rather than just printing
      an error message and returning NULL.

      The returned value is the number of registers read.  The RegArray
      parameter is set to the allocated register array.

      If you use this function, remember to dispose the returned array pointer,
      as it was allocated dynamically using GetMem (unless NULL is returned,
      which designates an error).
     --------------------------------------------------------------------------}

    FUNCTION LoadRegArray(fpath        : STRING;
                          VAR RegArray : RegisterPtr) : INTEGER;

     VAR

        handle : FILE;
        fsize  : LONGINT;

     BEGIN {*** Begin function LoadRegArray ***}
        LoadRegArray := 0;
        RegArray := NIL;
        ASSIGN(handle,fpath);
        RESET(handle,1);
        IF (IOResult <> 0) THEN { error opening file ? }
           BEGIN
              { include error handling code here }
              Exit;
           END;
        fsize := FileSize(handle);
        IF (IOResult <> 0) THEN { error acquiring file size ? }
           BEGIN
              CLOSE(handle);
              Exit;
           END;
        IF (fsize MOD SizeOf(Register) <> 0) THEN { Is filesize multiple of record
    ? }       BEGIN
              WriteLn('Illegal TWEAK file size: ',fpath);
              CLOSE(handle);
              Exit;
           END;
        IF (MaxAvail < fsize) THEN { Is there enough memory ? }
           BEGIN
              WriteLn('Out of memory allocating buffer for ',fpath);
              CLOSE(handle);
              Exit;
           END;
        GetMem(RegArray,fsize);
        BlockRead(handle,RegArray^,fsize);
        IF (IOResult <> 0) THEN { Error reading file ? }
           BEGIN
              CLOSE(handle);
              Dispose(RegArray);
              RegArray := NIL;
              Exit;
           END;
        CLOSE(handle);
        IF (IOResult <> 0) THEN { Error closing file ? }
           BEGIN
              Dispose(RegArray);
              RegArray := NIL;
              Exit;
           END;
        LoadRegArray := fsize DIV SizeOf(Register);
     END;  {*** End function LoadRegArray ***}

    END.

    {$I-}
    PROGRAM TWEAK2P;

    USES TWKUSER;

    {=========================================================================
      TWEAK2P version 1.0

      Ported to Pascal from Robert Schmidt's original C code.

      Converts a TWEAK version 1.0 file to an include-able Pascal file,
      defining the equivalent register array, which is passable
      to the OutRegArray function defined in the TWKUSER unit.

      Maurice L. Marvin
      maurice@cs.pdx.edu
     =========================================================================}

    VAR

       table   : RegisterPtr;
       btable  : RegisterPtr;
       regsize : INTEGER;
       handle  : TEXT;
       b1      : BYTE;
       b2      : BYTE;
       s       : WORD;

    BEGIN {*** Begin program TWEAK2P ***}
       { Check command line arguments. }
       IF (ParamCount < 3) THEN
          BEGIN
             WriteLn;
             WriteLn('TWEAK2P version 1.0');
             WriteLn('Converts a TWEAK version 1.x file to an include-able Pascal
    file.');         WriteLn;
             WriteLn('SYNTAX: TWEAK2P <TWEAK-File> <Pascal File to Create> <Array
    Name>');         WriteLn('All Parameters are required.');
             Halt(1);
          END;
       { Load the register file. }
       regsize := LoadRegArray(ParamStr(1),table);
       { Save a pointer to the start of the table.  The pointer 'table' will
         be corrupted due to pointer arithmetic. }
       btable := table;
       { Check if we loaded the table successfully. }
       IF (Table = NIL) THEN
          BEGIN
             WriteLn;
             WriteLn('ERROR : Unable to load register file.');
             Halt(1);
          END;
       { Open the destination file. }
       ASSIGN(handle,ParamStr(2));
       REWRITE(handle);
       IF (IOResult <> 0) THEN { Check if error creating file. }
          BEGIN
             WriteLn;
             WriteLn('ERROR : Unable to create destination file.');
             Halt(1);
          END;
       { Write data structure }
       WriteLn(handle,'{ Tweaked include file generated by TWEAK2P } ');
       WriteLn(handle,'');
       WriteLn(handle,'CONST');
       WriteLn(handle);
       Write(handle,'   ',ParamStr(3),' : ARRAY[1..',RegSize);
       WriteLn(handle,'] OF Register = (');
       Write(handle,'       ');
       s := SizeOf(Register);
       { Write register values }
       WHILE (RegSize > 0) DO
          BEGIN
             Write(handle,'(Port : ',table^.port);
             Write(handle,'; Index : ',table^.index);
             Write(handle,'; Value : ',table^.value,')');
             DEC(RegSize);
             IF (RegSize = 0) THEN
                WriteLn(handle,');')
             ELSE
                WriteLn(handle,',');
             ASM { move to next record }
                MOV DX,s
                ADD WORD PTR [table],DX
             END;
             Write(handle,'       ');
          END;
       CLOSE(handle);
       Dispose(btable);
    END. {*** End program Tweak2P ***}

[Back to EGAVGA SWAG index] [Back to Main SWAG index] [Original]