01

Copper Bars: Palette Cycling 101

Wandering local BBSs I found examples that kicked off my adventure. Here you have three loaders for CENTERPOINT! BBS, and my take on one of the effects. A loader was what ran before your terminal program connected: fifteen seconds of someone showing off, with a phone number in it.

the 256 DAC registers - 1..180 are the 180 rows of the backdrop

The CENTERPOINT! BBS Loaders

These three came as a collection with an instructional text file VGAINTRO.TXT that you can read in the source section below. I also found what seems to be the same set on defacto2.net.

PALETTE2.PAS Four sinusoidal copper bars (they get this name from Amiga coprocessors nicknamed "coppers") over a 180-row backdrop, a scrolling BBS advert along the bottom, and the whole bar engine in one hand-written BASM block synced to the vertical retrace. Everything you see move is DAC register writes; video memory is written once at startup and once per frame for the scroller's single new column. Two things in here that turn up again. The bounce is not a bounce - Locs[] is a 200-entry sine table and each bar just walks it at a different starting offset, wrapping at 200. And the bars erase before they draw, in that order, per bar, so when two bars cross, the trailing one's 45 zero bytes eat the leading one's gradient. Watch bars 1 and 4 pass and you can see them bite. The scroller has a genuine off-by-one, and it is visible if you look: the glyph index steps on CurrLine div 8 while the bit column steps on (CurrLine-1) mod 8, so column 8 of every character is taken from the next character along. Every letter is missing its last slice.

PALETTE4.PAS Similar to PALETTE2, but with portions in Pascal instead of Assembly. Based on the timestamps, this is the earlier one, suggesting he wrote the Pascal first and then later ported to Assembly, but it's impossible to know for sure. This version also has a shorter scroll text ("...LOADER BY FRED NIETZCHE......ALBERT IS A WEENIE!......"), and 13,776 bytes of embedded picture. The picture is a logo for TRSI (Tristar + Red Sector Incorporated) and TDT (The Dream Team). One bug: PicPalette is declared Array[1..22*4] - 88 bytes - and the upload loop runs For Count := 1 To 23, reading to byte 92.

CYLINDER.PAS Same author, same board, same phone number, and a completely different program. No copper bars at all: a dot scroller wrapped around a horizontal cylinder. How it is built. A 600-entry table ScreenPath holds one screen offset per (column, row) pair: 75 columns four pixels apart, and for each column eight y positions taken from eight successive points on a sine of radius 30 about y=80. The next column then starts one step further along - advance 8, step back 7 - so the phase slides across the screen. The glyph's vertical axis is mapped onto the circumference, which is why the text squashes to a line where the sine turns over and stretches where it is steep. The 600 positions span y 50–110 and x 1–297, against a cleared band of rows 50–111. It fits exactly. Every frame the whole 600-position table is repainted from a different starting offset in the message, and that offset advances by one glyph column. And the text is enciphered. 149 bytes of DispStr, decoded by subtracting the repeating key 'Esselete', one byte per character, wrapping mod 256 because the temporary is a Byte. Eight characters of key, and that is the whole protection. It is not there to stop you reading it; it is there to stop the next sysop pulling the strings out with a hex editor and dropping his own board's number in, which tells you what happened to loaders that were not encrypted. Decoded, in full:



Two off-by-ones, both visible if you wait. CurrentLine wraps at 1184 = (149−1)×8, but there are 149×8 = 1192 glyph columns, so the last character never fully comes round. And the inner loop's wrap zeroes both its index and its base, so when the message rolls over, the tail restarts at screen column 1 and overlaps the head for one pass, a stutter, once per loop. CurrentArrayLoc is incremented, bounds-checked at 73, and never read: everything that used it sits inside the commented-out block in the middle of Cycle. The static credit lines at the bottom are drawn once, outside the cleared band, and are the only thing here that is not moving.

My Version

You'll probably want to expand JBARS.PAS below to see my unfortunate teenage coding style. JBARS is a transcription of PALETTE2's DoCycle, instruction for instruction, with the labels Wait / Retr / BarLoop / PrevIsLast / Continue1 / Rep1 renamed to k / n / o / j / d / p. Identifiers go to single letters, hex is converted to decimal ($3C8Port[968], MOV DX,3DAhMOV DX,986, VideoMode($13)r(19)), and every constant expression is folded by hand: Locs[(NumCycles-1)*2] becomes l[398], MOV CX,15*3 becomes MOV CX,45, and Round(Radius*Sin((2*Pi/NumCycles)*Count))+Radius+1 becomes Round(g*Sin(0.0314*b)+81).

That last one is the only substantive change in the file. 2π/200 is 0.031416, and I had 0.0314, a truncation, so the sine table drifts about half a row short of a full period over its 200 entries. You cannot see it; it is just the one place where the transcription stopped being exact.

VGAINTRO.TXT

6,180 bytes · A tutorial that came with the source.

     Oh well, might as well write a text file on this since I'd be explaining 
this to more than one person sooner or later.  Here goes -


                     Writing (Graphic) VGA Intros/Loaders
                                     By
                                Fred Nietzche
                                  07/30/91


     I'm assuming that you don't understand the concept of video memory, so 
I'll start off from the basics then.  Video memory is defined (for our own 
purposes) as the memory that the video board scans in determining what signals
(analog) to send to the monitor.  In graphics mode, the segment of the location
of this is determined by what type of video mode you are on -
VGA/EGA modes = $A000 ($=hex), CGA modes = $B800, and Herc = $B000.  The
offsets always start off at $0.

     Now, what type of organization are the pixels (since we're in graphics 
mode) stored in?  Because of the simplicity of Mode $13 (320x200x256), most
VGA intros are written using this.  I'm not about to go ahead and explain to
you the other VGA modes dealing in the color planes, EGA/VGA registers,etc in
the higher resolution modes, there are a couple of good books out there that
can handle those of you interested in that.  Try your local bookstores and look 
for Power Graphics Programming by Michael Abrash, which contains his articles 
about higher resolution VGA programming from Programmer's Journal.  HIGHLY 
recommendable.  In any case, in this mode, each pixel on the screen 
corresponds to exactly 1 byte on the video memory.  For example, location
(0,0) = Mem[$A000:0], (1,0) = Mem[$A000:1], (2,0) = Mem[A000:2], and so on.
Fairly easy eh?  Because the memory map is linear, the next line would just be
the next byte AFTER the previous line's last pixel.  For example, location
(0,319) = Mem[$A000:319], AND THEN location (1,0) = Mem[$A000:320].  And the 
formula for determining the video memory location is

     Video Mem Offset = YPos*320 + XPos

     The actual color of the byte values stored in the video memory is
flexible and can be changed to any color of the 256,000 palette of the VGA.
This can be accomplished by altering the VGA Video DAC registers at port
addresses $3C6 through $3C9.  To read the current settings, set the Table
Read Index (port $3C7) to the color value you want, and then read the three
values from the Table Data Register (port $3C9) (one each for Red, Green, and
Blue).  Once three values have been read from that port, the current read
index is incremented by one and the next three 6 bit (range of 2^6, or 0 to 63)
values read are for the next color value.  Writing the to the Video DAC is
similar, except the Table Write Index is port $3C8.  Again, after writing
three successive 6 bit values to the Table Data Registers increments the Write
Index by one.  By the way, all the reference information about the Video DAC's
can be obtained from any EGA/VGA reference book.  I recommend getting
Advanced Programmer's Guide to the EGA/VGA by George Sutty and Steve Blair.

     Waiting for the vertical retrace start signal before updating the video
memory is the key to smooth animation (with a quick memory update too of
course).  The idea is to have the screen changes "pop up" before your eyes, and
to do this, you need to make your changes just before the the screen trace
of the video memory occurs.  For this reason, updating the video memory had
better fast enough, and generally this is the part done in assembly.  The
important port and bit locations, and a sample implementation are as follows:

       In Pascal:

         Repeat Until (Port[$3DA] And $08) = 0;
         Repeat Until (Port[$3DA] And $08) <> 0;

       And in Assembly:

                   MOV   DX,3DAh
         Wait:     IN    AL,DX
                   TEST  AL,08h
                   JZ    Wait
         Retr:     IN    AL,DX
                   TEST  AL,08h
                   JNZ   Retr


     And finally, how to get the characters on the screen.  I used the old
character set that's stored in BIOS because it saves time and space (instead
of capturing a graphical message).  The memory address for this is
$F000:$FA6E.  Because the character set is 8 bits by 8 bits, each character
takes up 8 bytes, each byte representing a horizontal slice of the character.
It's really not that confusing after fiddling around with it.

     There's also the special effect that palette cycling can do.  For
example, the color bars seen on Amiga and ST programs, although on the IBM,
it's more laborous.  What you do is simply fill each and every horizontal line
along the width of the movement of the bars with a separate color value.
Then blank out (with whatever color you desire) all of those values using the
DAC registers.  To move the bars, just change the color of the values that
need to be blanked out and the ones that need to be "filled in" with the bar
colors (again, through the DAC registers).  That's about it.  You may want to
make the movement of the bars in some pattern, like in the motion of a sine
function for effects.

     Another neat idea that palette cycling can accomplish is a shifting
checkerboard.  This one is a little bit more difficult, and I'll let you go
and figure it out on your own.

     That's all there is to it in terms of the basics and effects.  I wrote
for myself a screen capturing TSR (very crude, but what it does is dump the
video memory and palette to a file, and that's all I need.  I couldn't find
any PD programs which stored their captured screens in this format,
surprisingly!) to add painted pictures to the loaders, so that may be
something you might want to pursue for yourself.  Compress the executable
you've just created and you're done.

     Oh, I've included some sample intros (of my own board) with the ZIP.
I haven't really optimized them fully, but they'll do.  And the TDT/TRSI logo
was captured from one of their loaders.  I've got to admit, they've got some
nice artists working over there.

     About a good five minutes of reading eh?  Hope it was some help...


No greets, just trying to advertise my board around more..  Give it a ring.
CenterPoint! BBS (301) 309-0144, 9600+ only, Sysop - Fred Nietzche.
PALETTE2.PAS

1991-07-30 06:54 · 5,208 bytes · The bars, the scroller, and the assembly that ends up in JBARS.

Program PaletteTricks;

  Uses Crt;


  Const CGA_CharSet_Seg = $0F000;
        CGA_CharSet_Ofs = $0FA6E;
        CharLength      = 8;
        NumChars        = 256;
        VGA_Segment     = $0A000;
        NumCycles       = 200;
        Radius          = 80;

        DispStr         : String =
'...LOADER BY FRED NIETZCHE     CALL CENTERPOINT! (301) 309-0144, 9600+ ONLY  NUP: TERMINEX'+
'           WHATEVER ELSE YOU WANT HERE...                         ';

        Colors : Array[1..15*3] Of Byte =
                 (  7,  7, 63,
                   15, 15, 63,
                   23, 23, 63,
                   31, 31, 63,
                   39, 39, 63,
                   47, 47, 63,
                   55, 55, 63,
                   63, 63, 63,
                   55, 55, 63,
                   47, 47, 63,
                   39, 39, 63,
                   31, 31, 63,
                   23, 23, 63,
                   15, 15, 63,
                    7,  7, 63  );


Type  OneChar =Array[1..CharLength] Of Byte;


Var   CharSet : Array[1..NumChars] Of OneChar;
      Locs    : Array[1..NumCycles] Of Integer;
      BarLocs : Array[1..4] Of Integer;


  Procedure GetChars;

    Var NumCounter,
        ByteCounter,
        MemCounter   :Integer;
  
    Begin { GetChars }
      MemCounter:=0;
      For NumCounter:=1 To NumChars Do
        For ByteCounter:=1 To CharLength Do
          Begin
            CharSet[NumCounter][ByteCounter]:=Mem[CGA_CharSet_Seg:CGA_CharSet_Ofs+MemCounter];
            Inc(MemCounter);
          End;
    End;  { GetChars }


  Procedure VideoMode ( Mode : Byte );

    Begin { VideoMode }
      Asm
        Mov  AH,00
        Mov  AL,Mode
        Int  10h
      End;
    End;  { VideoMode }


  Procedure SetColor ( Color, Red, Green, Blue : Byte );

    Begin { SetColor }
      Port[$3C8] := Color;
      Port[$3C9] := Red;
      Port[$3C9] := Green;
      Port[$3C9] := Blue;
    End;  { SetColor }


  Procedure DispVert ( Var CurrLine : Integer );

    Var Letter : OneChar;
        VertLine,
        Count  : Integer;

    Begin { DispVert }
      Letter := CharSet[Ord(DispStr[(CurrLine Div 8)+1])+1];
      VertLine := (CurrLine-1) Mod 8;
      For Count := 1 To 8 Do
        If Letter[Count] And ($80 Shr VertLine) = 0
          Then Mem[VGA_Segment:185*320+(Count-1)*320+319] := 0
          Else Mem[VGa_Segment:185*320+(Count-1)*320+319] := 181;
    End;  { DispVert }


  Procedure CalcLocs;

    Var Count : Integer;

    Begin { CalcLocs }
      For Count := 1 To NumCycles Do
        Locs[Count] := Round(Radius*Sin((2*Pi/NumCycles)*Count))+Radius+1;
    End;  { CalcLocs }


    Procedure DoCycle;

      Label Wait,Retr,BarLoop,PrevIsLast,Continue1,Continue2,Rep1,Rep2;

      Begin { DoCycle }
        Asm

          MOV   DX,3DAh
Wait:     IN    AL,DX
          TEST  AL,08h
          JZ    Wait
Retr:     IN    AL,DX
          TEST  AL,08h
          JNZ   Retr

{ Do Bars... }

           MOV   BX,0
BarLoop:
           PUSH  BX
           MOV   AX,Word Ptr BarLocs[BX]
           MOV   BX,AX
           DEC   BX
           SHL   BX,1
           MOV   AX,Word Ptr Locs[BX]
           PUSH  AX
           CMP   BX,0
           JE    PrevIsLast
           DEC   BX
           DEC   BX
           MOV   AX,Word Ptr Locs[BX]
           JMP   Continue1

PrevIsLast:
           MOV   AX,Word Ptr Locs[(NumCycles-1)*2]

Continue1:
           MOV   DX,03C8h
           OUT   DX,AL
           INC   DX
           MOV   CX,15*3
           MOV   AL,0
Rep1:
           OUT   DX,AL
           LOOP  Rep1

           DEC   DX
           POP   AX
           OUT   DX,AL
           INC   DX
           MOV   CX,15*3
           XOR   BX,BX
Rep2:
           MOV   AL,Byte Ptr Colors[BX]
           OUT   DX,AL
           INC   BX
           LOOP  Rep2

           POP   BX
           INC   Word Ptr BarLocs[BX]
           CMP   Word Ptr BarLocs[BX],NumCycles
           JNG   Continue2

           Mov   Word Ptr BarLocs[BX],1
Continue2:
           INC   BX
           INC   BX
           CMP   BX,8
           JNE   BarLoop

        End;
      End;  { DoCycle }


  Var CurrVert,
      Count     : Integer;
      Key       : Char;
      MemPos    : Word;

  Begin { PaletteTricks }

    VideoMode($13);
    Port[$3C8] := 1;
    For Count := 1 To 180 Do
      SetColor(Count,0,0,0);
    MemPos := 0;
    For Count := 1 To 180 Do
      Begin
        FillChar(Mem[VGA_Segment:MemPos],320,Chr(Count));
        MemPos := MemPos + 320;
      End;
    SetColor(181,63,63,0);
    CalcLocs;
    For Count := 1 To 4 Do
      BarLocs[Count] := Count*10;

    GetChars;
    CurrVert := 1;
    Repeat
      DoCycle;
      For Count := 1 To 8 Do
        Move(Mem[VGA_Segment:185*320+(Count-1)*320+1],
             Mem[VGA_Segment:185*320+(Count-1)*320],319);
      DispVert(CurrVert);
      Inc(CurrVert);
      If CurrVert > Length(DispStr) * 8
        Then CurrVert := 1;

    Until Keypressed;
    Key := ReadKey;
    VideoMode(3);
  End.  { PaletteTricks }
PALETTE4.PAS

1991-06-01 00:18 · 45,340 bytes · Same program plus the TRSI/TDT logo. The logo is a 287×48 byte array.

Program PaletteTricks;

  Uses Crt;


  Const CGA_CharSet_Seg = $0F000;
        CGA_CharSet_Ofs = $0FA6E;
        CharLength      = 8;
        NumChars        = 256;
        VGA_Segment     = $0A000;
        NumCycles       = 200;
        Radius          = 80;

        DispStr         : String =
                              '...LOADER BY FRED NIETZCHE......ALBERT IS A WEENIE!......CALL CENTERPOINT! (301) 309-0144...';

        Colors : Array[1..15*3] Of Byte =
                 (  7,  7, 63,
                   15, 15, 63,
                   23, 23, 63,
                   31, 31, 63,
                   39, 39, 63,
                   47, 47, 63,
                   55, 55, 63,
                   63, 63, 63,
                   55, 55, 63,
                   47, 47, 63,
                   39, 39, 63,
                   31, 31, 63,
                   23, 23, 63,
                   15, 15, 63,
                    7,  7, 63  );


Picture : Array[1..13776] Of Byte = 
(* Size is 287 by 48 *)
(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,241,245,245,245,245,
245,246,246,247,247,248,248,249,249,250,250,249,249,248,248,247,247,246,246,
245,245,244,244,243,243,242,242,241,241,242,242,243,244,244,245,245,246,246,
247,247,248,248,249,249,250,250,251,251,252,252,251,250,249,248,247,246,245,
246,247,251,239,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,250,246,244,244,245,245,246,246,247,247,248,248,249,249,249,249,249,
248,248,247,247,247,246,246,246,245,245,245,245,242,0,0,0,244,247,248,
248,249,248,247,246,245,242,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,244,246,
245,245,244,244,243,243,243,242,242,241,241,242,242,243,243,243,243,244,243,
244,244,245,245,246,246,247,247,248,248,249,249,250,250,251,251,250,250,249,
249,248,248,248,249,254,239,0,0,0,0,0,0,0,249,249,244,244,246,
246,247,247,248,248,249,249,250,250,251,251,250,249,248,248,247,247,246,246,
245,245,244,244,243,243,243,243,243,243,242,242,241,241,242,242,242,243,243,
243,244,244,245,245,246,244,0,0,0,0,0,0,0,0,0,242,241,245,
245,245,245,245,246,246,247,247,248,248,249,249,250,250,249,249,248,248,247,
247,246,246,245,245,244,244,243,243,242,242,241,241,242,243,244,244,245,245,
246,246,247,248,248,249,249,250,250,251,251,252,252,251,250,249,248,247,246,
245,244,244,244,245,248,251,239,0,0,0,0,0,0,0,0,0,0,0,
0,0,250,246,243,243,243,244,244,245,245,246,246,247,247,248,248,249,249,
249,249,249,248,248,247,247,247,246,246,246,245,245,243,244,0,0,0,243,
244,247,248,249,248,246,245,243,244,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
247,244,246,245,245,244,244,243,243,243,242,242,241,241,242,242,243,243,244,
244,244,244,245,245,246,246,247,247,248,248,249,249,250,250,251,251,250,250,
249,249,248,248,245,246,247,247,248,249,251,254,239,239,249,249,245,243,243,
244,245,246,246,247,247,248,248,249,249,250,250,251,251,249,249,248,248,247,
247,246,246,245,245,244,244,244,244,243,243,242,242,241,241,242,242,243,243,
243,243,244,244,245,245,246,244,247,0,0,0,0,0,0,0,0,0,243,
242,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,248,248,248,248,247,247,246,246,246,
246,246,246,246,246,246,246,246,246,246,246,246,246,247,247,248,248,248,248,
249,249,249,249,248,247,245,246,246,249,239,0,0,0,0,0,0,0,0,
0,0,0,247,242,242,244,246,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,244,246,0,0,
0,242,243,249,249,249,249,249,249,244,246,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,246,245,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,248,248,248,247,247,246,246,246,246,246,246,
246,246,246,247,247,248,248,249,249,249,249,249,249,247,247,247,251,251,249,
249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,248,247,
247,247,247,246,246,246,246,246,246,245,246,0,0,0,0,0,0,0,0,
0,244,243,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,249,248,248,248,248,247,247,246,
246,246,246,246,246,246,246,246,246,246,246,246,246,246,247,247,248,248,248,
248,249,249,249,249,249,249,249,249,248,247,247,250,239,0,0,0,0,0,
0,0,0,0,245,242,243,246,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,246,246,
0,0,0,241,242,249,249,249,249,249,249,246,246,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,246,246,249,249,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,248,248,248,247,247,246,246,246,246,246,
246,246,246,246,246,246,247,247,248,248,249,249,249,249,249,249,249,247,247,
248,251,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
248,247,247,247,247,247,246,246,246,246,246,246,246,0,0,0,0,0,0,
0,0,0,245,245,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,249,249,249,248,248,248,248,247,
247,246,246,246,246,246,246,246,246,246,246,246,246,246,246,247,247,248,248,
248,248,249,249,249,249,249,249,249,249,249,249,249,248,248,251,239,0,0,
0,0,0,0,0,248,243,245,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
246,247,0,0,0,242,241,249,249,249,249,249,249,246,247,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,246,246,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,248,248,248,247,247,246,246,246,
246,246,246,246,246,246,246,246,247,247,248,248,249,249,249,249,249,249,249,
249,249,247,248,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
249,249,248,247,247,247,247,247,246,246,246,246,246,246,246,0,0,0,0,
0,0,0,0,0,246,247,249,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,248,248,248,248,
247,247,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,247,247,
248,248,248,248,249,249,249,249,249,249,249,249,249,249,249,249,249,249,254,
0,0,0,0,0,0,251,245,244,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
249,249,247,247,0,0,0,243,242,249,249,249,249,249,249,247,247,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,247,246,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,249,249,248,248,248,247,247,246,
246,246,246,246,246,246,246,246,246,246,246,247,247,248,248,249,249,249,249,
249,249,249,249,249,247,247,248,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,248,248,247,247,247,247,246,246,246,246,247,0,0,
0,0,0,0,0,0,0,247,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,248,248,
248,248,247,247,246,246,246,246,246,246,246,246,246,246,246,246,246,246,247,
247,248,248,248,248,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
250,250,0,0,0,0,0,0,247,246,248,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,247,248,0,0,0,244,243,249,249,249,249,249,249,247,248,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,247,247,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,248,248,248,247,
247,246,246,246,246,246,246,246,246,246,246,246,246,246,247,248,248,249,249,
249,249,249,249,249,249,249,249,247,247,248,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,248,248,248,247,247,247,245,246,246,247,247,
0,0,0,0,0,0,0,0,0,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
248,248,248,248,247,247,246,246,246,246,246,246,246,246,246,246,246,246,246,
246,247,247,248,248,248,248,249,249,249,249,249,249,249,249,249,249,249,249,
249,249,250,250,239,0,0,0,0,251,247,247,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,248,248,0,0,0,245,244,249,249,249,249,249,249,
248,248,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,248,247,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,248,248,248,
247,247,246,246,246,246,246,246,246,246,246,246,246,246,246,246,247,248,248,
248,249,249,249,249,249,249,249,249,249,249,249,247,248,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,249,248,247,247,245,245,245,246,
247,248,0,0,0,0,0,0,0,0,0,249,238,237,237,236,236,235,235,
234,234,233,233,234,234,248,249,249,249,249,249,249,247,232,232,232,232,232,
232,232,236,236,235,235,234,234,233,233,234,234,235,235,236,236,237,238,239,
238,237,237,236,236,235,235,234,234,233,234,235,235,236,236,235,249,249,249,
249,249,249,249,249,249,251,0,0,0,0,248,248,237,237,237,237,237,237,
237,237,236,236,236,235,235,234,234,233,234,235,236,237,238,239,238,237,237,
236,236,235,235,234,234,234,233,233,249,0,0,0,245,245,249,249,249,249,
249,249,248,249,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,248,238,238,237,237,
236,236,235,235,234,234,233,233,234,234,234,249,249,249,249,249,249,249,238,
238,237,237,236,236,235,235,234,233,233,235,235,236,239,239,238,238,237,237,
236,236,232,235,235,249,249,249,249,249,249,249,249,249,249,247,248,247,235,
235,234,234,235,235,235,235,235,234,234,235,235,236,236,237,237,238,238,249,
249,249,249,249,249,249,234,234,234,233,233,234,234,234,235,235,236,236,237,
237,238,238,248,0,0,0,0,0,0,0,0,0,238,237,237,236,236,235,
235,234,234,233,233,234,234,248,248,249,249,249,249,249,249,247,247,232,232,
232,232,232,232,232,236,236,235,235,234,234,233,233,234,234,235,235,236,237,
238,239,238,237,236,236,235,235,234,234,233,234,235,235,236,236,235,235,232,
249,249,249,249,249,249,249,248,248,0,0,0,0,248,237,237,237,237,237,
237,237,237,237,237,236,236,236,235,235,234,234,233,234,235,236,237,238,239,
238,237,237,236,236,235,235,234,234,234,233,233,0,0,0,246,245,249,249,
249,249,249,249,249,249,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,237,237,238,
238,237,237,236,236,235,235,234,234,233,233,234,252,249,249,249,249,249,249,
249,245,238,237,236,236,235,235,234,233,233,235,235,236,239,239,238,238,237,
237,236,236,235,235,235,234,234,235,249,249,249,249,249,249,249,249,249,247,
247,249,234,235,235,235,236,235,236,236,235,233,234,235,235,236,236,237,238,
245,249,249,249,249,249,249,249,252,234,233,233,234,234,235,235,235,236,236,
237,237,238,238,237,237,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,247,248,249,249,249,249,249,249,247,247,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
232,232,232,249,249,249,249,249,249,246,246,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,246,246,
249,249,249,249,249,249,249,248,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,252,252,249,249,249,249,
249,249,249,245,245,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,245,243,250,250,250,249,249,249,233,233,233,249,249,249,249,249,249,249,
249,249,247,247,249,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,245,245,249,249,249,249,249,249,249,252,252,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,246,247,249,249,249,249,249,249,
247,248,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,232,232,249,249,249,249,249,249,232,232,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
247,246,249,249,249,249,249,249,248,248,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,252,252,249,249,
249,249,249,249,249,246,245,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,248,243,250,249,249,249,249,249,249,249,249,233,233,249,249,249,249,
249,249,249,249,249,247,247,249,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,245,246,249,249,249,249,249,249,249,252,252,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,245,246,249,249,249,249,
249,249,248,249,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,243,244,232,249,249,249,249,249,249,232,232,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,247,247,249,249,249,249,249,249,248,247,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,252,252,
249,249,249,249,249,249,249,246,246,0,0,0,0,0,0,0,0,0,0,
0,0,0,251,245,244,249,249,249,249,249,249,249,249,249,249,234,234,249,
249,249,249,249,249,249,249,249,247,247,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,246,246,249,249,249,249,249,249,249,252,252,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,245,245,249,249,
249,249,249,249,249,250,0,0,0,0,0,0,0,0,0,0,0,0,0,
241,247,247,246,246,245,245,244,244,245,246,247,248,249,250,251,252,251,250,
249,249,248,247,246,245,244,242,248,249,249,249,249,249,249,235,232,0,0,
0,0,241,242,243,243,244,244,245,245,246,246,247,247,248,248,247,247,246,
246,245,245,244,244,243,243,244,244,245,249,252,0,0,0,0,0,0,0,
0,0,0,0,248,247,249,249,249,249,249,249,247,247,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
252,252,249,249,249,249,249,249,249,247,246,0,0,0,0,0,0,0,0,
0,0,0,0,0,247,246,248,249,249,249,249,249,249,249,249,251,251,0,
234,234,249,249,249,249,249,249,249,249,249,246,247,0,0,0,0,0,0,
0,0,0,0,0,0,0,246,247,249,249,249,249,249,249,249,252,252,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,244,245,
249,249,249,249,249,249,250,250,0,0,0,0,0,0,0,0,0,0,0,
0,0,242,241,246,246,245,245,244,244,245,246,247,248,248,249,250,251,252,
251,250,250,249,249,248,247,246,245,247,249,249,249,249,249,249,249,235,237,
0,0,0,0,232,242,242,243,243,244,244,245,245,246,246,247,247,248,248,
247,246,246,245,244,244,243,243,244,244,245,245,246,246,249,254,0,0,0,
0,0,0,0,0,0,248,248,249,249,249,249,249,249,246,246,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,252,251,249,249,249,249,249,249,249,247,247,0,0,0,0,0,0,
0,0,0,0,0,0,0,247,247,249,249,249,249,249,249,249,249,251,251,
0,0,0,237,235,249,249,249,249,249,249,249,249,248,244,246,0,0,0,
0,0,0,0,0,0,0,0,0,247,247,249,249,249,249,249,249,249,251,
252,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
243,244,249,249,249,249,249,249,250,251,0,0,0,0,0,0,0,0,0,
0,0,0,0,243,242,246,246,246,246,246,246,247,247,248,248,248,248,249,
249,247,246,246,246,246,246,246,246,247,248,249,249,249,249,249,249,249,234,
235,239,0,0,0,0,238,232,232,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,249,249,249,248,247,247,248,251,
0,0,0,0,0,0,0,0,249,248,249,249,249,249,249,249,247,247,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,251,251,249,249,249,249,249,249,249,248,247,0,0,0,0,
0,0,0,0,0,0,0,0,0,248,249,249,249,249,249,249,249,249,251,
251,0,0,0,0,0,236,236,249,249,249,249,249,249,249,249,248,244,247,
0,0,0,0,0,0,0,0,0,0,0,247,248,249,249,249,249,249,249,
249,251,251,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,243,243,249,249,249,249,249,249,251,251,0,0,0,0,0,0,0,
0,0,0,0,0,0,244,243,246,246,246,246,246,246,247,247,248,248,248,
248,249,249,248,247,246,246,246,246,246,246,246,247,248,249,249,249,249,249,
249,234,236,0,0,0,0,0,0,232,232,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
248,248,250,0,0,0,0,0,0,0,249,249,249,249,249,249,249,249,248,
247,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,250,250,249,249,249,249,249,249,249,248,248,0,0,
0,0,0,0,0,0,0,0,0,0,0,248,249,249,249,249,249,249,249,
249,251,0,0,0,0,0,0,0,236,237,249,249,249,249,249,249,249,249,
248,245,248,0,0,0,0,0,0,0,0,0,0,248,248,249,249,249,249,
249,249,249,250,250,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,242,242,249,249,249,249,249,249,251,251,0,0,0,0,0,
0,0,0,0,0,0,0,0,245,244,246,246,246,246,246,246,247,247,248,
248,248,248,249,249,249,248,247,246,246,246,246,246,246,246,247,248,249,249,
249,249,233,233,239,0,0,0,0,0,0,239,235,235,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,248,250,251,0,0,0,0,0,0,250,250,249,249,249,249,249,
249,248,248,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,250,250,249,249,249,249,249,249,249,248,248,
0,0,0,0,0,0,0,0,0,0,0,0,0,248,249,249,249,249,249,
249,249,249,251,0,0,0,0,0,0,0,0,237,237,249,249,249,249,249,
249,249,248,245,248,0,0,0,0,0,0,0,0,0,0,248,248,249,249,
249,249,249,249,249,250,250,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,241,241,249,249,249,249,249,249,251,250,0,0,0,
0,0,0,0,0,0,0,0,0,0,246,245,246,246,246,246,246,247,247,
248,248,248,248,249,249,249,249,248,248,247,247,246,246,246,246,246,246,247,
248,248,249,232,234,236,0,0,0,0,0,0,0,0,238,235,232,249,249,
249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,251,251,239,0,0,0,0,0,250,250,249,249,249,
249,249,249,249,248,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,250,250,249,249,249,249,249,249,249,
249,248,0,0,0,0,0,0,0,0,0,0,0,0,0,249,249,249,249,
249,249,249,249,250,250,0,0,0,0,0,0,0,0,0,238,238,249,249,
249,249,249,249,249,247,245,251,0,0,0,0,0,0,0,0,0,248,249,
249,249,249,249,249,249,249,250,250,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,242,242,249,249,249,249,249,249,250,250,0,
0,0,0,0,0,0,0,0,0,0,0,0,247,246,246,246,246,246,246,
247,247,248,248,248,248,249,249,249,249,249,249,248,248,247,246,246,246,246,
246,246,247,232,236,235,236,239,0,0,0,0,0,0,0,0,0,238,236,
236,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,250,250,0,0,0,0,0,251,251,249,
249,249,249,249,249,249,249,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,249,249,249,249,249,249,249,
249,249,250,249,0,0,0,0,0,0,0,0,0,0,0,0,0,249,250,
249,249,249,249,249,249,250,249,0,0,0,0,0,0,0,0,0,239,238,
237,249,249,249,249,249,249,249,246,249,0,0,0,0,0,0,0,0,0,
249,250,249,249,249,249,249,249,249,249,249,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,243,243,249,249,249,249,249,249,250,
249,0,0,0,0,0,0,0,0,0,0,0,0,0,247,247,246,246,246,
246,247,247,248,248,248,248,249,249,249,249,249,249,249,249,248,248,247,246,
246,246,246,232,237,237,237,238,239,0,0,0,0,0,0,0,0,0,0,
0,238,236,237,237,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,250,250,239,0,0,0,0,251,
251,249,249,249,249,249,249,250,249,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,249,249,249,249,249,
249,249,249,249,250,250,0,0,0,0,0,0,0,0,0,0,0,0,0,
250,250,249,249,249,249,249,249,249,249,0,0,0,0,0,0,0,0,0,
0,239,237,235,249,249,249,249,249,249,248,246,253,0,0,0,0,0,0,
0,0,250,250,249,249,249,249,249,249,249,249,249,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,243,244,249,249,249,249,249,
249,249,249,0,0,0,0,0,0,0,0,0,0,0,0,0,248,248,246,
246,246,246,247,247,248,248,248,248,249,249,249,249,249,249,249,249,249,248,
248,232,236,236,236,236,237,237,239,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,239,238,237,238,238,238,239,238,238,237,237,236,236,237,237,
236,236,235,235,234,234,232,249,249,249,249,249,249,249,249,251,0,0,0,
0,250,250,249,249,249,249,249,249,250,250,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,248,248,249,
249,249,249,249,249,249,249,249,0,0,0,0,0,0,0,0,0,0,0,
0,0,250,251,249,249,249,249,249,249,249,247,0,0,0,0,0,0,0,
0,0,0,0,239,235,249,249,249,249,249,249,249,247,250,0,0,0,0,
0,0,0,0,249,249,249,249,249,249,249,249,249,248,248,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,244,245,249,249,249,
249,249,249,248,248,0,0,0,0,0,0,0,0,0,0,0,0,0,249,
249,246,246,246,246,247,247,251,251,235,235,249,249,249,249,249,249,249,249,
236,236,236,236,236,236,236,238,239,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,239,238,238,239,238,238,237,237,236,236,236,
236,237,237,236,236,235,235,234,234,248,249,249,249,249,249,249,249,248,0,
0,0,0,250,249,249,249,248,248,249,249,251,250,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,248,
248,249,249,249,249,249,249,249,248,248,0,0,0,0,0,0,0,0,0,
0,0,0,0,251,251,249,249,249,249,249,249,247,247,0,0,0,0,0,
0,0,0,0,0,0,0,237,249,249,249,249,249,249,249,247,247,0,0,
0,0,0,0,0,0,248,248,249,249,249,249,249,249,249,248,248,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,245,245,249,
249,249,249,249,249,247,247,0,0,0,0,0,0,0,0,0,0,0,0,
0,249,249,246,246,246,247,247,248,251,251,235,236,236,249,249,249,249,249,
249,249,249,249,249,249,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,236,233,233,248,249,249,249,249,249,248,
248,0,0,0,0,249,249,248,248,248,247,247,248,251,251,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,248,248,249,249,249,249,249,249,249,248,248,0,0,0,0,0,0,0,
0,0,0,0,0,0,251,251,249,249,249,249,249,249,247,247,0,0,0,
0,0,0,0,0,0,0,0,0,237,249,249,249,249,249,249,249,247,247,
0,0,0,0,0,0,0,0,248,248,249,249,249,249,249,249,249,248,248,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,245,
246,249,249,249,249,249,249,246,246,0,0,0,0,0,0,0,0,0,0,
0,0,0,248,248,246,246,246,247,247,248,250,250,0,236,237,237,249,249,
249,249,249,249,249,249,249,248,247,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,244,244,249,249,249,249,249,
249,248,232,0,0,0,0,249,248,246,246,246,247,247,247,252,251,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,247,248,249,249,249,249,249,249,249,247,247,0,0,0,0,0,
0,0,0,0,0,0,0,0,251,250,250,249,249,249,249,249,247,246,0,
0,0,0,0,0,0,0,0,0,0,0,254,249,249,249,249,249,249,249,
248,247,254,0,0,0,0,0,0,0,247,247,249,249,249,249,249,249,249,
248,247,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,246,246,249,249,249,249,249,249,245,246,0,0,0,0,0,0,0,0,
0,0,0,0,0,247,247,246,246,246,247,247,248,250,250,0,0,237,238,
238,249,249,249,249,249,249,249,249,247,246,246,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,249,245,245,247,248,249,
249,249,249,232,232,0,0,0,0,248,248,246,246,246,246,246,246,252,252,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,247,247,249,249,249,249,249,249,249,246,246,0,0,0,
0,0,0,0,0,0,0,0,0,0,250,250,249,249,249,248,249,249,246,
246,0,0,0,0,0,0,0,0,0,0,0,0,0,248,248,249,249,249,
249,249,249,248,250,0,0,0,0,0,0,0,246,246,249,249,249,249,249,
249,249,247,247,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,246,247,249,249,249,249,249,249,245,245,0,0,0,0,0,0,
0,0,0,0,0,0,0,247,246,246,246,247,247,248,248,249,249,0,0,
0,238,237,237,249,249,249,249,249,249,249,249,246,245,245,0,0,0,0,
0,0,0,0,0,0,0,0,246,247,247,246,246,245,245,244,244,243,243,
242,241,241,242,242,243,243,244,244,245,245,246,246,247,247,247,246,247,247,
248,249,249,249,249,232,232,0,0,0,0,248,247,246,246,246,246,246,246,
252,249,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,246,247,249,249,249,249,249,249,249,245,245,0,
0,0,0,0,0,0,0,0,0,0,0,0,250,249,249,248,248,248,247,
248,246,245,0,0,0,0,0,0,0,0,0,0,0,0,0,249,247,249,
249,249,249,249,249,248,250,0,0,0,0,0,0,0,245,245,249,249,249,
249,249,249,249,247,246,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,247,247,249,249,249,249,249,249,246,245,0,0,0,0,
0,0,0,0,0,0,0,0,0,246,245,246,246,247,247,248,248,248,248,
0,0,0,0,237,236,236,249,249,249,249,249,249,249,249,245,246,246,0,
0,0,0,0,0,0,0,0,0,0,247,246,246,246,245,245,244,244,243,
243,242,242,241,241,241,242,242,243,243,244,244,245,245,246,246,247,247,246,
246,247,247,248,248,249,249,236,238,0,0,0,0,247,247,246,246,246,246,
246,246,249,249,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,246,246,249,249,249,249,249,249,249,244,
245,0,0,0,0,0,0,0,0,0,0,0,0,0,249,249,248,246,246,
246,247,247,245,245,0,0,0,0,0,0,0,0,0,0,0,0,0,246,
246,249,249,249,249,249,249,248,250,0,0,0,0,0,0,0,245,244,249,
249,249,249,249,249,248,246,246,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,247,248,249,249,249,249,249,249,246,246,0,0,
0,0,0,0,0,0,0,0,0,0,0,245,244,246,246,247,246,247,247,
247,248,0,0,0,0,0,236,235,235,249,249,249,249,249,249,249,249,246,
247,247,0,0,0,0,0,0,0,0,0,0,246,246,248,248,249,249,249,
249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,247,
247,246,247,247,247,247,247,248,237,236,239,0,0,0,0,247,246,246,246,
246,246,246,246,249,247,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,246,246,249,249,248,248,249,248,
249,244,244,0,0,0,0,0,0,0,0,0,0,0,0,0,249,247,247,
246,246,246,246,246,245,244,0,0,0,0,0,0,0,0,0,0,0,0,
0,246,247,249,249,249,249,249,249,248,250,0,0,0,0,0,0,0,244,
244,249,248,248,249,249,248,248,246,246,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,248,248,249,249,249,249,249,249,247,246,
0,0,0,0,0,0,0,0,0,0,0,0,0,244,245,246,246,247,245,
246,246,246,247,0,0,0,0,0,0,235,235,232,249,249,249,249,249,249,
249,249,247,247,247,0,0,0,0,0,0,0,0,0,246,245,248,248,249,
249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
249,249,247,246,246,247,247,247,247,248,237,238,0,0,0,0,0,246,246,
246,246,246,246,246,246,247,247,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,245,246,248,248,248,247,
248,248,248,243,244,0,0,0,0,0,0,0,0,0,0,0,0,0,247,
247,247,246,246,246,246,246,244,247,247,246,246,246,245,246,246,247,247,248,
248,249,248,247,248,249,249,249,249,249,249,249,254,0,0,0,0,0,0,
0,244,243,248,248,247,248,248,248,248,246,245,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,248,249,249,249,249,249,249,249,
247,247,0,0,0,0,0,0,0,0,0,0,0,0,0,245,246,246,247,
246,246,245,245,246,246,0,0,0,0,0,0,0,232,232,232,248,249,249,
249,249,249,249,249,247,248,248,0,0,0,0,0,0,0,0,245,245,248,
248,248,248,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,248,246,246,246,246,247,247,236,236,239,0,0,0,0,0,
246,245,246,246,246,246,246,246,247,246,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,245,246,248,248,
248,247,248,248,248,243,244,0,0,0,0,0,0,0,0,0,0,0,0,
0,247,247,247,246,246,246,246,246,244,247,247,246,246,246,245,246,246,247,
247,248,248,249,248,247,248,249,249,249,249,249,249,249,254,0,0,0,0,
0,0,0,244,243,248,248,247,248,248,248,248,246,245,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,249,249,249,249,249,249,
249,249,248,247,0,0,0,0,0,0,0,0,0,0,0,0,0,246,247,
246,247,247,247,245,246,245,246,0,0,0,0,0,0,0,0,232,232,235,
248,248,249,249,249,249,248,248,248,249,249,0,0,0,0,0,0,0,245,
244,247,248,248,248,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,247,246,246,246,247,232,235,238,0,0,0,0,
0,0,245,245,246,246,246,246,246,246,246,246,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,245,245,
248,248,247,247,247,247,248,242,243,0,0,0,0,0,0,0,0,0,0,
0,0,0,247,246,246,246,246,246,246,246,246,246,246,247,247,247,248,248,
249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,0,0,0,
0,0,0,0,0,243,242,248,247,247,247,247,248,248,245,245,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,249,249,249,249,
249,249,249,249,248,248,0,0,0,0,0,0,0,0,0,0,0,0,0,
247,248,246,247,246,247,246,246,245,245,0,0,0,0,0,0,0,0,0,
232,232,235,248,248,248,248,248,248,248,248,249,250,250,0,0,0,0,0,
0,244,244,247,248,248,249,249,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,248,249,249,249,249,248,247,246,246,234,235,237,0,0,0,
0,0,0,0,245,246,246,246,246,246,246,246,246,247,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
245,245,247,247,247,246,247,247,247,241,242,0,0,0,0,0,0,0,0,
0,0,0,0,0,246,246,246,246,246,246,246,246,246,246,246,247,247,247,
248,248,249,249,249,249,249,249,249,249,249,249,249,249,249,249,236,237,0,
0,0,0,0,0,0,0,242,241,247,247,246,247,247,247,247,245,245,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,249,249,
249,249,249,249,249,249,249,248,0,0,0,0,0,0,0,0,0,0,0,
0,0,248,249,246,247,247,248,247,247,246,245,0,0,0,0,0,0,0,
0,0,0,232,232,235,248,248,248,248,248,249,248,248,250,250,249,0,0,
0,0,0,244,243,248,248,248,249,249,249,249,249,249,249,249,249,249,249,
249,249,249,249,249,249,249,248,248,248,249,248,248,233,234,234,237,0,0,
0,0,0,0,0,0,246,247,246,246,246,246,246,247,247,248,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,244,245,246,246,246,246,246,246,246,242,241,0,0,0,0,0,0,
0,0,0,0,0,0,0,246,245,245,246,246,246,246,246,246,246,246,246,
247,247,248,248,248,248,249,249,249,249,249,249,249,249,249,249,249,235,236,
238,0,0,0,0,0,0,0,0,241,242,246,246,246,246,246,246,246,245,
244,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
249,234,234,235,236,237,238,238,237,249,0,0,0,0,0,0,0,0,0,
0,0,0,0,249,235,234,233,235,236,237,237,246,246,0,0,0,0,0,
0,0,0,0,0,0,232,232,235,248,248,249,249,249,249,249,248,249,249,
249,0,0,0,0,243,243,238,237,237,236,236,235,235,234,234,233,233,234,
234,235,235,236,236,237,237,236,236,235,235,234,234,233,233,233,236,239,0,
0,0,0,0,0,0,0,0,247,233,233,234,234,235,235,236,236,248,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,244,244,246,246,246,246,246,246,246,243,242,0,0,0,0,
0,0,0,0,0,0,0,0,0,245,245,246,246,246,246,246,246,246,247,
247,247,247,247,247,248,248,249,249,249,249,249,249,249,249,249,249,249,234,
233,237,0,0,0,0,0,0,0,0,0,242,243,246,246,246,246,246,246,
246,244,244,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,234,234,235,235,236,237,238,239,238,237,0,0,0,0,0,0,0,
0,0,0,0,0,0,235,234,233,234,235,236,236,237,237,246,0,0,0,
0,0,0,0,0,0,0,0,0,232,235,234,248,249,249,249,248,249,249,
247,249,249,248,0,0,0,243,239,237,237,236,236,235,235,234,234,234,233,
233,234,234,234,235,235,236,236,237,237,236,236,235,235,234,234,236,239,0,
0,0,0,0,0,0,0,0,0,0,233,233,234,234,235,235,236,236,237,
237,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,244,244,246,246,246,246,246,246,246,244,243,0,0,
0,0,0,0,0,0,0,0,0,0,0,245,245,247,246,246,246,246,247,
247,248,248,248,248,248,248,248,248,249,249,249,249,249,249,249,249,249,249,
236,235,237,0,0,0,0,0,0,0,0,0,0,243,244,246,246,246,246,
246,246,246,244,244,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,232,235,234,248,249,248,249,
248,248,248,247,248,248,248,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,244,244,246,246,246,246,246,246,246,244,243,
0,0,0,0,0,0,0,0,0,0,0,0,0,245,245,247,246,246,246,
246,247,247,248,248,248,248,248,248,248,248,249,249,249,249,249,249,249,249,
237,237,236,235,237,0,0,0,0,0,0,0,0,0,0,243,244,246,246,
246,246,246,246,246,244,244,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,235,235,234,248,
248,248,248,248,248,248,247,248,248,247,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,244,233,234,235,236,237,237,238,238,
239,244,0,0,0,0,0,0,0,0,0,0,0,0,0,245,234,234,235,
235,236,236,237,237,238,238,239,238,238,237,237,236,236,237,238,238,239,239,
238,238,238,237,238,239,0,0,0,0,0,0,0,0,0,0,0,244,244,
239,238,237,237,236,235,234,233,244,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,235,
234,233,248,248,248,248,247,247,247,247,247,247,247,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,233,234,234,235,236,236,237,
237,238,238,239,0,0,0,0,0,0,0,0,0,0,0,0,0,234,234,
235,235,236,236,237,237,238,238,239,238,238,238,237,237,236,236,237,237,238,
238,239,239,238,239,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
244,239,238,237,237,236,236,235,234,234,233,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,235,234,233,247,247,247,247,247,247,247,247,246,246,246,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,234,234,233,246,246,246,246,247,247,247,247,245,245,245,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,233,233,238,239,238,237,236,235,234,233,234,
235,245,245,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,238,239,238,237,236,236,235,234,
233,234,234,235,235,245,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);


PicPalette : Array[1..22*4] Of Byte = 
(232,31,25,23,
233,28,22,19,
234,25,19,16,
235,22,16,12,
236,19,14,9,
237,16,12,7,
238,13,10,5,
239,10,8,3,
241,46,47,63,
242,40,42,60,
243,35,38,56,
244,30,34,53,
245,25,30,50,
246,21,28,47,
247,17,25,44,
248,14,22,41,
249,11,20,38,
250,8,19,34,
251,5,16,31,
252,3,15,28,
253,1,13,25,
254,0,12,22);


Type  OneChar =Array[1..CharLength] Of Byte;


Var   CharSet : Array[1..NumChars] Of OneChar;
      Locs    : Array[1..NumCycles] Of Integer;
      BarLocs : Array[1..4] Of Integer;


  Procedure GetChars;

    Var NumCounter,
        ByteCounter,
        MemCounter   :Integer;
  
    Begin { GetChars }
      MemCounter:=0;
      For NumCounter:=1 To NumChars Do
        For ByteCounter:=1 To CharLength Do
          Begin
            CharSet[NumCounter][ByteCounter]:=Mem[CGA_CharSet_Seg:CGA_CharSet_Ofs+MemCounter];
            Inc(MemCounter);
          End;
    End;  { GetChars }


  Procedure VideoMode ( Mode : Byte );

    Begin { VideoMode }
      Asm
        Mov  AH,00
        Mov  AL,Mode
        Int  10h
      End;
    End;  { VideoMode }


  Procedure SetColor ( Color, Red, Green, Blue : Byte );

    Begin { SetColor }
      Port[$3C8] := Color;
      Port[$3C9] := Red;
      Port[$3C9] := Green;
      Port[$3C9] := Blue;
    End;  { SetColor }


  Procedure DispVert ( Var CurrLine : Integer );

    Var Letter : OneChar;
        VertLine,
        Count  : Integer;

    Begin { DispVert }
      Letter := CharSet[Ord(DispStr[(CurrLine Div 8)+1])+1];
      VertLine := (CurrLine-1) Mod 8;
      For Count := 1 To 8 Do
        If Letter[Count] And ($80 Shr VertLine) = 0
          Then Mem[VGA_Segment:185*320+(Count-1)*320+319] := 0
          Else Mem[VGa_Segment:185*320+(Count-1)*320+319] := 181;
    End;  { DispVert }


  Procedure CalcLocs;

    Var Count : Integer;

    Begin { CalcLocs }
      For Count := 1 To NumCycles Do
        Locs[Count] := Round(Radius*Sin((2*Pi/NumCycles)*Count))+Radius+1;
    End;  { CalcLocs }


  Procedure DrawBar ( Var Bar : Integer );

    Var Count,
        PrevBar : Integer;

    Begin { DrawBar }
      If BarLocs[Bar] = 1
        Then PrevBar := Locs[NumCycles]
        Else PrevBar := Locs[BarLocs[Bar]-1];
      Port[$3C8] := PrevBar;
      For Count := 1 To 15*3 Do
        Port[$3C9] := 0;
      Port[$3C8] := Locs[BarLocs[Bar]];
      For Count := 1 To 15*3 Do
        Port[$3C9] := Colors[Count];
      Inc(BarLocs[Bar]);
    End;  { DrawBar }


  Var CurrVert,
      XCount,
      Count     : Integer;
      Key       : Char;
      MemPos    : Word;

  Begin { PaletteTricks }

    VideoMode($13);
    Port[$3C8] := 1;
    For Count := 1 To 180 Do
      SetColor(Count,0,0,0);
    For Count := 1 To 23 Do
      Begin
        Port[$3C8] := PicPalette[(Count-1)*4+1];
        Port[$3C9] := PicPalette[(Count-1)*4+2];
        Port[$3C9] := PicPalette[(Count-1)*4+3];
        Port[$3C9] := PicPalette[(Count-1)*4+4];
      End;
    MemPos := 0;
    For Count := 1 To 180 Do
      Begin
        FillChar(Mem[VGA_Segment:MemPos],320,Chr(Count));
        MemPos := MemPos + 320;
      End;

    For Count := 1 To 48 Do
      For XCount := 1 To 287 Do
        If Picture[(Count-1)*287+XCount] <> 0
          Then Mem[VGA_Segment:50*320+(Count-1)*320+20+XCount] := Picture[(Count-1)*287+XCount];

    SetColor(181,63,63,0);
    CalcLocs;
    For Count := 1 To 4 Do
      BarLocs[Count] := Count*10;

    GetChars;
    CurrVert := 1;
    Repeat
      Repeat Until (Port[$3DA] And $08) = 0;
      Repeat Until (Port[$3DA] And $08) <> 0;
      For Count := 1 To 4 Do
        Begin
          DrawBar(Count);
          If BarLocs[Count] > NumCycles Then BarLocs[Count] := 1;
        End;

      For Count := 1 To 8 Do
        Move(Mem[VGA_Segment:185*320+(Count-1)*320+1],
             Mem[VGA_Segment:185*320+(Count-1)*320],319);
      DispVert(CurrVert);
      Inc(CurrVert);
      If CurrVert > Length(DispStr) * 8
        Then CurrVert := 1;

    Until Keypressed;
    Key := ReadKey;
    VideoMode(3);
  End.  { PaletteTricks }

CYLINDER.PAS

1995-09-16 16:05 · 7,807 bytes · The cylinder scroller, with the enciphered DispStr near the top.

Program Cylinder_Scroll;

  Const CGA_CharSet_Seg = $0F000;
        CGA_CharSet_Ofs = $0FA6E;
        VGA_Segment = $A000;
        
        ScrollYPos = 80;
        Radius = 30;
        NumSlices = 90;
        AngleInc = 2*Pi / NumSlices;

        Spacing = 4;

        PW = 'Esselete';

        NumXCoords = 300 Div Spacing;
        CharColor = 1;


DispStr : Array[1..149] Of Byte =
(101,147,147,133,140,133,148,133,101,147,191,180,173,169,185,183,101,181,
204,133,178,183,185,169,101,193,188,170,192,191,183,173,138,147,147,133,
140,133,148,133,101,147,147,147,154,147,183,170,147,199,184,183,188,180,
189,179,153,148,147,167,174,184,148,141,120,163,164,142,140,152,164,158,
114,163,164,153,160,147,162,147,101,147,147,133,140,133,198,186,147,193,
188,179,179,133,195,179,101,200,198,183,140,150,168,147,121,147,183,186,
173,177,160,133,126,169,163,149,151,133,195,179,145,204,147,133,140,133,
148,133,152,204,198,180,188,159,148,171,151,184,183,133,186,174,185,185,
159,182,187,170,140 );

NumDispChars = 149;
        CharLength      = 8;
        NumChars        = 256;


  Type  OneChar =Array[1..CharLength] Of Byte;


  Var   ScreenPath : Array[1..8*80] Of Word;
        CurrentLine,
        CurrentArrayLoc  : Integer;
        DispChars   : Array[1..NumDispChars*64] Of Byte;
        CharSet : Array[1..NumChars] Of OneChar;
        Password : String;

        KeyHit : Boolean;
        Int9Vec : LongInt;


Procedure VideoMode(Mode:Byte);Begin Asm Mov AH,0;Mov AL,Mode;Int 16;End;End;

  Procedure GetChars;

    Var NumCounter,
        ByteCounter,
        MemCounter   :Integer;

    Begin { GetChars }
      MemCounter:=0;
      For NumCounter:=1 To NumChars Do
        For ByteCounter:=1 To CharLength Do
          Begin
            CharSet[NumCounter][ByteCounter]:=Mem[CGA_CharSet_Seg:CGA_CharSet_Ofs+MemCounter];
            Inc(MemCounter);
          End;
    End;  { GetChars }


Procedure SetColor(Color,Red,Green,Blue:Byte);

    Begin { SetColor }
      Port[$3C8] := Color;
      Port[$3C9] := Red;
      Port[$3C9] := Green;
      Port[$3C9] := Blue;
    End;  { SetColor }


  Procedure BuildPath;

    Var YCount,
        XCount,
        ArrayPtr  : Integer;
        CurrAngle : Real;

    Begin { BuildPath }
      CurrAngle := Pi;
      ArrayPtr := 1;
      For XCount := 1 To NumXCoords Do
        Begin
          For YCount := 1 To 8 Do
            Begin
              ScreenPath[ArrayPtr] := (ScrollYPos + Round(Radius*Sin(CurrAngle)))*320
                                      + (XCount-1)*Spacing + 1;
              CurrAngle := CurrAngle + AngleInc;
              Inc(ArrayPtr);
            End;
          CurrAngle := CurrAngle - 7*AngleInc;
        End;
    End;  { BuildPath }


  Procedure BuildCharArray;

    Var ShearYCnt,
        ShearXCnt,
        Count,
        ArrayPtr   : Integer;
        TempByte   : Byte;

    Begin { BuildCharArray }
      ArrayPtr := 1;
      For Count := 1 To NumDispChars Do
        Begin
          TempByte := DispStr[Count] - Ord(Password[((Count-1) Mod Length(Password))+1]);
          For ShearXCnt := 1 To 8 Do
            For ShearYCnt := 1 To 8 Do
              Begin
                If Mem[CGA_CharSet_Seg:CGA_CharSet_Ofs+TempByte*8+ShearYCnt-1] And ($80 Shr (ShearXCnt-1)) = 0
                  Then DispChars[ArrayPtr] := 0
                  Else DispChars[ArrayPtr] := CharColor;
                Inc(ArrayPtr);
              End;
        End;
    End;  { BuildCharArray }


  Procedure Cycle;

    Label Wait,Retr,Loop1,Loop2,Continue1,Continue2,Continue3,Continue4,
          Continue5;

    Begin { Cycle }
      Asm
          MOV   AX,VGA_Segment
          MOV   ES,AX
          MOV   DI,(ScrollYPos-Radius)*320
          MOV   CX,160*Radius*2+320

          MOV   DX,3DAh
Wait:     IN    AL,DX
          TEST  AL,08h
          JZ    Wait
Retr:     IN    AL,DX
          TEST  AL,08h
          JNZ   Retr

          XOR   AX,AX
          REP   STOSW

          MOV   BX,CurrentLine
          MOV   CL,3
          SHL   BX,CL
          MOV   DX,BX

          MOV   AX,NumXCoords
Loop1:
          MOV   CX,8
Loop2:
          CMP   Byte Ptr DispChars[BX],0
          JE    Continue2

          PUSH  BX
          {Put Dot}
          SUB   BX,DX
          SHL   BX,1
          MOV   DI,Word Ptr ScreenPath[BX]
{          PUSH  DX
          MOV   DX,CurrentArrayLoc
          SHL   DX,1
          SHL   DX,1
          SUB   DI,DX
          CMP   DI,NumXCoords*Spacing+ScrollYPos*160
          JLE   Continue1

          ADD   DI,NumXCoords*Spacing
Continue1:
          POP   DX }
          MOV   Byte Ptr ES:[DI],CharColor
          POP   BX

Continue2:
          INC   BX
          CMP   BX,(NumDispChars-1)*8*8
          JNG   Continue3
          XOR   BX,BX
          XOR   DX,DX
Continue3:
          LOOP  Loop2

          DEC   AX
          JNZ   Loop1

          INC   CurrentLine
          CMP   CurrentLine,(NumDispChars-1)*8
          JNG   Continue4
          MOV   CurrentLine,0

Continue4:
          INC   CurrentArrayLoc
          CMP   CurrentArrayLoc,73
          JNG   Continue5
          MOV   CurrentArrayLoc,0

Continue5:

      End;

    End;  { Cycle }


  Procedure SetInt9 ( I9Seg,I9Ofs : Word );

    Begin { SetInt9 }
      Asm
        PUSH    DS

        MOV     AH,35h
        MOV     AL,09h
        INT     21h
        MOV     Word Ptr Int9Vec,BX
        MOV     Word Ptr Int9Vec[2],ES

        MOV     AX,I9Seg
        MOV     DS,AX
        MOV     DX,I9Ofs
        MOV     AH,25h
        MOV     AL,09h
        INT     21h

        POP     DS
      End;
    End;  { SetInt9 }


  Procedure DisInt9;

    Begin { DisInt9 }
      Asm
        PUSH    DS
        MOV     DX,Word Ptr Int9Vec
        MOV     AX,Word Ptr Int9Vec[2]
        MOV     DS,AX
        MOV     AH,25h
        MOV     AL,09h
        INT     21h
        POP     DS
      End;
    End;  { DisInt9 }


  Procedure Int9;

  Interrupt;

    Begin { Int9 }
      Asm
        PUSHF
        CALL    Int9Vec
        INC     KeyHit
      End;
    End;  { Int9 }


  Procedure DrawString ( XPos,YPos,Size : Integer; Color : Byte; Str : String );

    Var TempPos,
        MemPos   : Word;
        XSize,
        YSize,
        Count,
        XCount,
        YCount : Integer;
        Letter : OneChar;

    Begin
      MemPos := (YPos-1)*320+(XPos-1);
      For Count := 1 To Length(Str) Do
        Begin
          Letter := CharSet[Ord(Str[Count])+1];
          For YCount := 1 To 8 Do
            For XCount := 1 To 8 Do
              If Letter[YCount] And ($80 Shr (XCount-1)) <> 0
                Then Begin
                  TempPos := MemPos+(YCount-1)*320*Size+(Count-1)*8*Size+(XCount-1)*Size;
                  For XSize := 1 To Size Do
                    For YSize := 1 To Size Do
                      Mem[VGA_Segment:TempPos+(XSize-1)+(YSize-1)*320] := Color;
                End;
        End;
    End;


  Var   Count,
        XCount : Integer;
        CurrAngle : Real;

  Begin { Cylinder_Scroll }

    SetInt9 (Seg(Int9),Ofs(Int9));
    KeyHit := False;

    Password := PW;
    VideoMode($13);
    GetChars;
    SetColor(CharColor,63,63,63);
    SetColor(4,63,0,0);
    SetColor(5,63,63,63);
    BuildCharArray;
    BuildPath;
    DrawString(64,150,1,4,'Loader by Fred Nietzche');
    DrawString(16,160,1,5,'Call CenterPoint! BBS (301) 309-0144');
    CurrentLine := 0;
    CurrentArrayLoc := 0;
    Repeat
      Cycle;
    Until KeyHit;
    VideoMode($3);

    DisInt9;

  End.  { Cylinder_Scroll }
JBARS.PAS

1995-05-06 14:14 · 1,172 bytes · My take. As on disk. The line breaks are the editor wrapping at 128 columns, not mine.

uses crt;Const e=$A000;f=200;g=80;i:array[1..45]Of Byte=(7,7,63,15,15,63,23,23,63,31,31,63,39,39,63,47,47,63,55,55,63,63,63,63,
55,55,63,47,47,63,39,39,63,31,31,63,23,23,63,15,15,63,7,7,63);Var l:Array[1..f]Of integer;m:Array[1..4]Of integer;Procedure r(s
:Byte);Begin Asm Mov ah,0;Mov AL,s;Int 16 End;End;Var b:Integer;c:Word;Label k,n,o,j,d,h,p,q;begin r(19);Port [968]:=1;For b:=1
To 180Do begin Port[968]:=b;Port[969]:=0;Port[969]:=0;Port[969]:=0 End;c:=0;For b:=1To 180Do Begin FillChar(Mem[e:c],320,Chr(b)
);c:=c+320;End;For b:=1To f Do l[b]:=Round(g*Sin(0.0314*b)+81);For b:=1To 4Do m[b]:=b*10;Repeat Asm MOV DX,986;k:IN AL,DX;
TEST AL,8;JZ k;n:IN AL,DX;TEST AL,8;JNZ n;MOV BX,0;o:PUSH BX;MOV AX,Word Ptr m[BX];MOV BX,AX;DEC BX;SHL BX,1;
MOV AX,Word Ptr l[BX];PUSH AX;CMP BX,0;JE j;DEC BX;DEC BX;MOV AX,Word Ptr l[BX];JMP d;j:MOV AX,Word Ptr l[398];d:MOV DX,968;
OUT DX,AL;INC DX;MOV CX,45;MOV AL,0;p:OUT DX,AL;LOOP p;DEC DX;POP AX;OUT DX,AL;INC DX;MOV CX,45;XOR BX,BX;q:
MOV AL,Byte Ptr i[BX];OUT DX,AL;INC BX;LOOP q;POP BX;INC Word Ptr m[BX];CMP Word Ptr m[BX],f;JNG h;Mov Word Ptr m[BX],1;h:
INC BX;INC BX;CMP BX,8;JNE o;End; Until Keypressed;r(3)End.