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

    {
      If  you are ready to delve into pure VGA-register programming, you can
      realize  graphic  modes  up  to  400x600x256 pixels on any vanilla-VGA
      card;  watch  out  for  TWEAK*.*  for a cute tool to create such modes
      yourself easily.

      Here's  a  small example for a 360x256x256 mode, give it a try on your
      system:
    }

    {Purpose  : Demonstrate 360x256x256 graphics resolution              }
    {Author   : Kai Rohrbacher, kai.rohrbacher@logo.ka.sub.org           }
    {Language : TurboPascal 6.0   }
    {Date     : 17.07.1994        }
    {Remarks  : Register set generated with Robert Schmidt's TWEAK1.6beta}
    {           adopted to Pascal by myself. No guarantees, use on your  }
    {           own risk!}
    {           If you directly want to play around with Bob's TWEAK,    }
    {           here is the original register file:
    begin 644 360x256b.256
    MP@,`Y]0#`&O4`P%9U`,"6M0#`X[4`P1>U`,%BM0#!B/4`P>RU`,(`-0#"6'4
    M`Q`*U`,1K-0#$O_4`Q,MU`,4`-0#%0?4`Q8:U`,7X\0#`0'$`P0&S@,%0,X#
    *!@7``Q!!P`,3````
    `
    end
    }

    USES Dos;
    CONST ATTRCON_ADDR = $3c0;
          MISC_ADDR = $3c2;
          VGAENABLE_ADDR = $3c3;
          SEQ_ADDR = $3c4;
          GRACON_ADDR = $3ce;
          CRTC_ADDR = $3d4;
          STATUS_ADDR = $3da;

    TYPE Register=RECORD
          prt:WORD;
          index:BYTE;
          value:BYTE
         END;
        RegisterPtr=^Register;
    CONST Mode360x256: ARRAY[0..24] OF Register =
     (
      ( prt:$3c2; index:$0; value:$e7),
      ( prt:$3d4; index:$0; value:$6b),
      ( prt:$3d4; index:$1; value:$59),
      ( prt:$3d4; index:$2; value:$5a),
      ( prt:$3d4; index:$3; value:$8e),
      ( prt:$3d4; index:$4; value:$5e),
      ( prt:$3d4; index:$5; value:$8a),
      ( prt:$3d4; index:$6; value:$23),
      ( prt:$3d4; index:$7; value:$b2),
      ( prt:$3d4; index:$8; value:$0),
      ( prt:$3d4; index:$9; value:$61),
      ( prt:$3d4; index:$10; value:$a),
      ( prt:$3d4; index:$11; value:$ac),
      ( prt:$3d4; index:$12; value:$ff),
      ( prt:$3d4; index:$13; value:$2d),
      ( prt:$3d4; index:$14; value:$0),
      ( prt:$3d4; index:$15; value:$7),
      ( prt:$3d4; index:$16; value:$1a),
      ( prt:$3d4; index:$17; value:$e3),
      ( prt:$3c4; index:$1; value:$1),
      ( prt:$3c4; index:$4; value:$6),
      ( prt:$3ce; index:$5; value:$40),
      ( prt:$3ce; index:$6; value:$5),
      ( prt:$3c0; index:$10; value:$41),
      ( prt:$3c0; index:$13; value:$0)
     );

    {
       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:INTEGER;
    BEGIN
      port[$3d4]:=$11;
      v:=port[$3d5] AND $7f;
      port[$3d4]:=$11;
      port[$3d5]:=v;
    END;

    {
      outReg sets a single register according to the contents of the
      passed Register structure.
    }
    PROCEDURE outReg(r:Register);
    VAR dummy:BYTE;
    BEGIN
     IF r.prt=ATTRCON_ADDR
      THEN BEGIN
            dummy:=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
     ELSE IF (r.prt=MISC_ADDR) OR (r.prt=VGAENABLE_ADDR)
      THEN port[r.prt]:=r.value   {  directly to the port }
     ELSE BEGIN
           port[r.prt]:=r.index;  {  index to port        }
           port[r.prt+1]:=r.value;{  value to port+1        }
          END;
    END;

    {
      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);
    BEGIN
     readyVgaRegs;
     WHILE n>0 DO
      BEGIN
       DEC(n);
       outReg(r^);
       ASM
        LES DI,r
        ADD DI,TYPE Register
        MOV WORD PTR [r],DI
       END;
      END;
    END;

    VAR y,lastMode:INTEGER;
        regs:REGISTERS;
    BEGIN
     {Save old BIOS mode}
     regs.AH := $0f; INTR($10,regs); lastMode := regs.AL;

     {Set mode 13h to make sure the EGA palette set is correct for a }
     {256color mode}
     regs.AX := $13; INTR($10,regs);

      { Note that no initialization is neccessary now.  The Register array
          is linked in as global data, and is directly accessible.  Take
          note of the way the number of Register elements in the array is
         calculated: }

     outRegArray(@Mode360x256, sizeof(Mode360x256) DIV sizeof(Register));
     portw[$3c4]:=$0f02; { Enable all 4 planes }

      { Fill the screen with a blend of red and blue lines, defining the
         palette on the fly. }

      port[$3c8]:=0;         { start with color 0 }
      FOR y:=0 TO 255 DO
       BEGIN
        port[$3c9]:= y SHR 2;        { red component }
        port[$3c9]:= 0;              { green component }
        port[$3c9]:= (256-y) SHR 2;  { blue component }
        FillChar(Mem[SegA000:y*90],90,y);
       END;

     y:=0;
     WHILE y<256 DO
      BEGIN
       MEM[SegA000:y*90]:=255;
       inc(y,8)
      END;
      readln;

      { The picture is drawn, so wait for user to get tired of it. }

      { Restore the saved mode number.  Borland's textmode() won't work, as the
          C library still thinks we're in the mode it detected at startup.
         The palette will be set to the BIOS mode's default. }

      regs.AX := lastMode; INTR($10,regs);

    END.

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