You can’t let a broken CRT monitor stand in your way
Many moons ago, my CRT monitor&#x27;s red gun went kaput. It&#x27;s easy to imagine what that must have looked like. Anything red appeared as, well, black. Everything else was a shade of cyan, blue, or green. The solution? A TSR, like in the article.<p>The TSR I wrote was simple in comparison: it constantly refreshed the palette. A palette entry with a red value greater than zero had its blue and green values increased accordingly. The red component was then zeroed out.<p>Necessity is a powerful impetus for spurring creativity in frugal college students.<p>This looks to be an earlier version, as it doesn&#x27;t increase the blue and green values, but gives an idea of how it worked:<p><pre><code>    {$M 1024,0,0 }   { 1K stack, no heap }

    USES Crt, DOS;

    CONST
      MAX_COUNT = 384;
      READ_PAL  = $3C7;
      WRIT_PAL  = $3C8;
      RED       = 1;
      GRN       = 2;
      BLU       = 3;

    VAR
      OldIntVec : PROCEDURE;
      NoRed     : ARRAY[ RED..BLU, 0..255 ] OF BYTE;
      Count     : INTEGER;
      Colour    : BYTE; 

    PROCEDURE ReadPalette;
    Begin
      FOR Colour := 0 TO 255 DO
      Begin
        Port[ $3C7 ] := Colour;
        NoRed[ RED, Colour ] := Port[ $3C9 ];
        NoRed[ GRN, Colour ] := Port[ $3C9 ];
        NoRed[ BLU, Colour ] := Port[ $3C9 ];
      End;
    End;

    PROCEDURE ChngPalette;
    Begin
      FOR Colour := 0 TO 255 DO
        IF NoRed[ RED, Colour ] &lt;&gt; 0 THEN
          NoRed[ RED, Colour ] := 0;
    End;

    PROCEDURE WritePalette;
    Begin
      FOR Colour := 0 TO 255 DO
      Begin
        Port[ $3C8 ] := Colour;
        Port[ $3C9 ] := NoRed[ RED, Colour ];
        Port[ $3C9 ] := NoRed[ GRN, Colour ];
        Port[ $3C9 ] := NoRed[ BLU, Colour ];
      End;
    End;

    {$F+}
    PROCEDURE NewTimer; INTERRUPT;
    Begin
      InLine( $9C ); { PUSHF -- Push flags }
      OldIntVec;

      IF Count = MAX_COUNT THEN
      Begin
        Count := 0;

        ReadPalette;
        ChngPalette;
        WritePalette;
      End
      ELSE
        INC( Count );
    End;
    {$F-}

    BEGIN
      Count := MAX_COUNT;

      GetIntVec( $1C, @OldIntVec );
      SetIntVec( $1C, Addr( NewTimer ) );
      Keep( 0 );
    END.</code></pre>