home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / grafik / vgakit / gif / source / gifmini.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1991-08-20  |  14.0 KB  |  501 lines

  1.  
  2. PROGRAM GIFMINI;
  3. {
  4.   LESEN VON GIF- FILES   MINIMALPROGRAMM
  5.  
  6.   NUR VIDEOMODUS 13H ( 320 * 200 / 256 )
  7.   KEIN ABFANGEN VON IO- FEHLERN
  8.   KEINE FILESELEKTORBOX USW.
  9.  
  10.   Paul Schubert, Rottweiler Str. 8, D6000 Frankfurt /M 1, 069 / 231145
  11.  
  12.   DER GIF- LESEALGORITHMUS WURDE ENTNOMMEN AUS DEM ARTIKEL
  13.   'Heiße Pixel', Zeitschrift mc, Mai 1991, S. 106
  14.   Autor Dietmar Bückart
  15. }
  16. {$R-}
  17. {$S-}
  18.  
  19. USES  CRT,DOS,TPERSATZ;
  20.  
  21.  
  22. CONST GIFHDLEN = 13;    { LÄNGE GIF HEADER - NICHT VERÄNDERN !!! }
  23.       GIFPDLEN = 10;    { LÄNGE GIF PICTURE DESCRIPTOR - NICHT VERÄNDERN !!! }
  24.       LINLEN   = 1024;  { MAXIMALE LÄNGE EINER BILDZEILE IN PIXELN }
  25.  
  26.  
  27. CONST POWERSOF2 : ARRAY[0..8] OF WORD = (1,2,4,8,16,32,64,128,256);
  28.       MAXCODES  : ARRAY[0..9] OF WORD = (4,8,$10,$20,$40,$80,$100,$200,$400,$800);
  29.       CODEMASK  : ARRAY[1..8] OF BYTE = (1,3,7,$F,$1F,$3F,$7F,$FF);
  30.       MASKS     : ARRAY[0..9] OF WORD = (7,$F,$1F,$3F,$7F,$FF,$1FF,$3FF,$7FF,$FFF);
  31.  
  32.  
  33. TYPE  HDRTYP = RECORD { GIF FILEHEADER }
  34.         SIGNUM   : ARRAY[0..5] OF CHAR;
  35.         SCRWID   : WORD;
  36.         SCRHIG   : WORD;
  37.         INFO     : BYTE;
  38.         BKCOL    : BYTE;
  39.         TERM     : BYTE;
  40.         GLOBPAL  : BOOLEAN;
  41.         BPP      : BYTE;
  42.         RGBBITS  : BYTE;
  43.         CMAPSIZ  : WORD;
  44.       END;
  45.  
  46.       PICDESCTYP = RECORD { GIF PICTURE DESCRIPTOR }
  47.         SIGNUM1  : CHAR;
  48.         LEFT     : WORD;
  49.         TOP      : WORD;
  50.         WID      : WORD;
  51.         HIG      : WORD;
  52.         FLAGS    : BYTE;
  53.         INTERL   : BOOLEAN;
  54.         LOCMAP   : BOOLEAN;
  55.         PIXSIZ   : BYTE;
  56.       END;
  57.  
  58. TYPE  COLORVALUE = RECORD R,G,B : BYTE END;
  59.       VGAPALETTE = ARRAY[0..255] OF COLORVALUE;
  60.       CMAPTYP    = ARRAY[0..256,0..2] OF BYTE;
  61.  
  62. TYPE  BATYP      = ARRAY[0..2] OF BYTE;
  63.       PBATYP     = ^BATYP;
  64.  
  65.  
  66. VAR   I                    : INTEGER;
  67.       FN                   : STRING;
  68.       F                    : FILE;
  69.       HDR                  : HDRTYP;
  70.       GCMAP,LCMAP          : CMAPTYP;
  71.       PAL                  : VGAPALETTE ABSOLUTE GCMAP;
  72.       PICDESC              : PICDESCTYP;
  73.  
  74.       CLEARCODE,EOFCODE,
  75.       FIRSTFREE,FREECODE,
  76.       INICODSIZ,MAXCODE,
  77.       READMASK,OUTCOUNT,
  78.       CURCODE,
  79.       OLDCODE,XP,YP        : WORD;
  80.       CODESIZE,BITMASK,
  81.       FINCHAR,PASS         : BYTE;
  82.  
  83.       BITOFFSET,BITSIZ     : WORD;
  84.       BITBUF               : LONGINT;
  85.       BITBF                : BATYP ABSOLUTE BITBUF;
  86.       CODE                 : WORD  ABSOLUTE BITBUF;
  87.       B                    : WORD;
  88.  
  89.       PREFIX               : ARRAY[0..4095] OF WORD;
  90.       SUFFIX               : ARRAY[0..4095] OF BYTE;
  91.       OUTCODE              : ARRAY[0..LINLEN] OF BYTE;
  92.       VLINE                : ARRAY[0..LINLEN] OF BYTE;
  93.       BUF                  : ARRAY[0.. 260] OF BYTE;
  94.  
  95.  
  96. { FÜR VGA- INITIALISIERUNG }
  97. VAR   VMOD                 : BYTE;
  98.       XWID,YWID,MAXX,MAXY  : WORD;
  99.  
  100.  
  101. {#####################################################################}
  102. { HIER IST DER HARDWARE- ABHÄNGIGE TEIL DES PROGRAMMS }
  103.  
  104. PROCEDURE SET320X200;
  105. BEGIN
  106.   VMOD := $13;   { DIESEN VIDEO- MODUS KENNT JEDE VGA- KARTE }
  107.   XWID := 320;
  108.   YWID := 200;
  109.   MAXX := PRED(XWID);
  110.   MAXY := PRED(YWID);
  111. END; { SET320X200 }
  112.  
  113. { EINSTELLEN DES 64k SEGMENTS FÜR SUPER- VGA- MODI }
  114. PROCEDURE SETSEG(SEGMENT:BYTE);
  115. BEGIN
  116. END; { SETSEG }
  117.  
  118. { ENDE HARDWARE- ABHÄNGIGER PROGRAMMTEIL }
  119. {#####################################################################}
  120.  
  121. {---------------------------------------------------------------------}
  122. { DIESER PROGRAMMTEIL IST FÜR VGA / SUPER- VGA }
  123.  
  124. PROCEDURE RAMTOVGA(VON:POINTER;BIS:LONGINT;WID:WORD);
  125. TYPE  SOF    = RECORD O,S : WORD; END;
  126. TYPE  VADDR  = RECORD
  127.         A    : WORD; { ADRESSE IM 64K- SEGMENT }
  128.         S    : BYTE; { SEGMENT- NUMMER }
  129.         DUM  : BYTE; { FÜLLBYTE }
  130.       END;
  131. VAR   J,K,AWID  : WORD;
  132.       B2        : LONGINT;
  133.       V2        : POINTER;
  134. BEGIN
  135. { NICHT MEHR PIXEL ALS BILDSCHIRMBREITE AUSGEBEN }
  136.   IF WID > XWID THEN AWID := XWID ELSE AWID := WID;
  137.  
  138.   B2 := BIS + LONGINT(AWID);
  139.   SETSEG(VADDR(BIS).S);
  140.   IF VADDR(BIS).S = VADDR(B2).S THEN BEGIN
  141.     MOVE(VON^,MEM[$A000:BIS],AWID);
  142.   END ELSE BEGIN
  143.     J := VADDR(B2).A;
  144.     K := AWID - J;
  145.     MOVE(VON^,MEM[$A000:BIS],K);
  146.     SETSEG(VADDR(B2).S);
  147.     V2 := VON; INC(SOF(V2).O,K);
  148.     MOVE(V2^,MEM[$A000:0],J);
  149.   END;
  150. END; { RAMTOVGA }
  151.  
  152.  
  153. PROCEDURE VGASETPALETTE(VON,BIS:BYTE;VAR P : VGAPALETTE);
  154. VAR   R  : REGISTERS;
  155. BEGIN
  156.   R.AX := $1012;
  157.   R.BX := VON;
  158.   R.CX := SUCC(BIS - VON);
  159.   R.ES := SEG(P);
  160.   R.DX := OFS(P[VON]);
  161.   INTR($10,R);
  162. END; { VGASETPALETTE }
  163.  
  164.  
  165. PROCEDURE OVERSCAN(FARBE:BYTE);
  166. VAR   R  : REGISTERS;
  167. BEGIN
  168.   R.AX := $1001;
  169.   R.BH := FARBE;
  170.   INTR($10,R);
  171. END;
  172.  
  173.  
  174. PROCEDURE SETMODUS(MODE:BYTE);
  175. VAR   R  : REGISTERS;
  176. BEGIN
  177.   R.AH := 0;
  178.   R.AL := VMOD;
  179.   INTR($10,R);
  180. END; { SETMODUS }
  181.  
  182. {---------------------------------------------------------------------}
  183.  
  184.  
  185. { ES IST SCHNELLER, ZUERST ALLE PIXEL EINER ZEILE AUFZUSAMMELN UND DANN DIE
  186.   ZEILE AUF VIDEO AUSZUGEBEN, ALS EINZELNE PIXEL AUF DEN BILDSCHIRM ZU
  187.   SCHREIBEN
  188. }
  189. PROCEDURE PUTPIXEL(B:BYTE);
  190. VAR   I  : INTEGER;
  191. BEGIN
  192.   VLINE[XP] := B;
  193.   INC(XP);
  194.   IF XP >= PICDESC.WID THEN BEGIN
  195.  
  196. { NICHT MEHR ZEILEN AUSGEBEN ALS DIE BILDSCHIRMHÖHE }
  197.     IF YP < YWID THEN
  198.       RAMTOVGA(@VLINE,LONGINT(YP)*LONGINT(XWID),PICDESC.WID);
  199.  
  200. { HIER FINDET DAS HANDLING VON INTERLACED- GIF STATT }
  201.     CASE PASS OF
  202.       0 : INC(YP);
  203.       1 : INC(YP,8);
  204.       2 : INC(YP,8);
  205.       3 : INC(YP,4);
  206.       4 : INC(YP,2);
  207.     END; { CASE PASS }
  208.     XP := 0;
  209.     IF YP >= PICDESC.HIG THEN BEGIN
  210.       IF PASS > 0 THEN INC(PASS);
  211.       CASE PASS OF
  212.         2 : YP := 4;
  213.         3 : YP := 2;
  214.         4 : YP := 1;
  215.       END; { CASE PASS }
  216.     END;
  217.   END;
  218. END; { PUTPIXEL }
  219.  
  220.  
  221. PROCEDURE AUS;
  222. BEGIN
  223.   TEXTMODE(CO80);
  224.   HALT;
  225. END; { AUS }
  226.  
  227.  
  228. PROCEDURE GRAPHEIN;
  229. BEGIN
  230. { HIER SOLLTE NATÜRLICH EIGENTLICH NACH ART UND GRÖßE DES BILDES DER
  231.   PASSENDE VIDEO- MODUS EINGESTELLT WERDEN
  232. }
  233.   SET320X200;                             { GRAPHIK- MODUS AUSWÄHLEN }
  234.   SETMODUS(VMOD);                         { GRAPHIK- MODUS EINSTELLEN }
  235.   VGASETPALETTE(0,PRED(HDR.CMAPSIZ),PAL); { PALETTE EINSTELLE }
  236.   OVERSCAN(HDR.BKCOL);                    { HINTERGRUNDFARBE SETZEN }
  237.   DIRECTVIDEO := FALSE;                   { FALLS MIT 'WRITE' AUF'S BILD
  238.                                             GESCHRIEBEN WERDEN SOLL }
  239. END; { GRAPHEIN }
  240.  
  241.  
  242. { PROCEDURE ZEIGEHDR DIENT NUR ZUM DEBUGGEN UND FÜR NEUGIERIGE }
  243. PROCEDURE ZEIGEHDR;
  244. BEGIN
  245.   TEXTMODE(CO80);
  246.   WRITELN;
  247.   WRITELN;
  248.   WRITELN(FN);
  249.   WITH HDR DO BEGIN
  250.     WRITELN('>',SIGNUM,'<   ',SCRWID,' * ',SCRHIG,' * ',POWERSOF2[BPP]);
  251.     WRITELN('INFO : ',HEXB(INFO),'   BACKGROUND :',BKCOL:4,'  TERMINATOR :',TERM:3,' >',CHAR(TERM),'<');
  252.     WRITELN('GLOBALE PALETTE : ',GLOBPAL,'   BITS PER PIXEL :',BPP:4);
  253.     WRITELN('RGBSIZE :',RGBBITS:4,'   CMAPSIZE :',CMAPSIZ:6);
  254.     WITH PICDESC DO BEGIN
  255.       WRITELN('XOFF  = ',LEFT:4,'      YOFF = ',TOP:4);
  256.       WRITELN('WIDTH = ',WID:4, '    HEIGTH = ',HIG:4);
  257.       WRITELN('FLAGS : ',HEXB(FLAGS),'   PIXEL- SIZE = ',PIXSIZ);
  258.       WRITELN('INTERLACE : ',INTERL,'   LOCAL COLORMAP : ',LOCMAP);
  259.       WRITELN;
  260.       WRITE  ('Filegröße : ',FILESIZE(F),',   ');
  261.       WRITELN(LONGINT(LONGINT(WID)*LONGINT(HIG)*LONGINT(BPP))SHR 3,' Bytes Bilddaten');
  262.     END; { WITH PICDESC }
  263.   END; { WITH HDR }
  264.   IF READKEY = ^[ THEN;
  265. END; { ZEIGEHDR }
  266.  
  267.  
  268. {---------------------------------------------------------------------}
  269. { HIER FOLGT DER KERN DES GIF- DECODERS }
  270.  
  271.  
  272. FUNCTION LIESHDR:INTEGER;
  273. VAR   I,J  : INTEGER;
  274. BEGIN
  275.   LIESHDR := -1;
  276.  
  277.   FILLCHAR(HDR,SIZEOF(HDR),#0);
  278.   BLOCKREAD(F,HDR,GIFHDLEN,I);
  279.   J := IORESULT;
  280.   IF (J <> 0) OR (I <> GIFHDLEN) THEN EXIT;
  281.   WITH HDR DO BEGIN
  282.     LIESHDR := -2;
  283.     IF (SIGNUM[0] <> 'G') OR
  284.        (SIGNUM[1] <> 'I') OR
  285.        (SIGNUM[2] <> 'F') THEN EXIT;
  286. { HIER KANN NOCH AUF 'GIF87a' UND 'GIF89a' GETESTET WERDEN }
  287.     GLOBPAL  := (INFO AND $80) <> 0;
  288.     BPP      := SUCC(INFO AND 7);
  289.     RGBBITS  := SUCC( (INFO SHR 4) AND 7);
  290.     CMAPSIZ  := 1 SHL BPP;
  291.     IF GLOBPAL THEN BEGIN
  292.       LIESHDR := -3;
  293.       BLOCKREAD(F,GCMAP,3 * CMAPSIZ,I);
  294.       J := IORESULT;
  295.       IF (J <> 0) OR (I <> 3 * CMAPSIZ) THEN EXIT;
  296.       FOR I := 0 TO PRED(HDR.CMAPSIZ) DO BEGIN
  297.         FOR J := 0 TO 2 DO GCMAP[I][J] := GCMAP[I][J] SHR 2;
  298.       END;
  299.     END;
  300.   END; { WITH HDR }
  301.   LIESHDR := -4;
  302.   BLOCKREAD(F,PICDESC,GIFPDLEN,I);
  303.   J := IORESULT;
  304.   IF (J <> 0) OR (I <> GIFPDLEN) THEN EXIT;
  305.   WITH PICDESC DO BEGIN
  306.     LIESHDR := -5;
  307.     IF SIGNUM1 <> ',' THEN EXIT;
  308.     INTERL := (FLAGS AND $40) <> 0;
  309.     LOCMAP := (FLAGS AND $80) <> 0;
  310.     PIXSIZ := SUCC(FLAGS AND 7);
  311.  
  312.     IF LOCMAP THEN BEGIN
  313.       LIESHDR := -5;
  314.       BLOCKREAD(F,LCMAP,3 * HDR.CMAPSIZ,I);
  315.       J := IORESULT;
  316.       IF (J <> 0) OR (I <> 3 * HDR.CMAPSIZ) THEN EXIT;
  317.       FOR I := 0 TO PRED(HDR.CMAPSIZ) DO BEGIN
  318.         FOR J := 0 TO 2 DO LCMAP[I][J] := LCMAP[I][J] SHR 2;
  319.       END;
  320.     END;
  321.   END; { WITH PICDESC }
  322.   LIESHDR := 0;
  323. END; { LIESHDR }
  324.  
  325.  
  326. PROCEDURE GIFDOCLEAR;
  327. BEGIN
  328.   CODESIZE  := INICODSIZ;
  329.   MAXCODE   := MAXCODES[CODESIZE - 2];
  330.   FREECODE  := FIRSTFREE;
  331.   READMASK  := MASKS[CODESIZE - 3];
  332. END; { GIFDOCLEAR }
  333.  
  334.  
  335. { ICH HOFFE, DIE FUNCTION READCODE MÖGLICHST SCHNELLGÄNGIG PROGRAMMIERT
  336.   ZU HABEN
  337. }
  338. { MAN KANN NATÜRLICH GRÖßERE 'BROCKEN' ALS DIE GIF- BLÖCKE AUF EINMAL
  339.   EINLESEN, DAS WIRD VERMUTLICH SOGAR SICHTBAR SCHNELLER, ABER ES WIDERSTREBT
  340.   MIR, WIE IM PROGRAMM VON HERRN BÜCKART GANZE 64k BYTES FILEBUFFER ZU
  341.   VERSCHWENDEN.
  342.   WENN BILDER VON 1024 * 768 IN 256 FARBEN IM HINTERGRUND EINGELESEN WERDEN
  343.   SOLLEN, REICHT DER ARBEITSSPEICHER SOWIESO NICHT - DANN BRAUCHT'S EBEN EMS.
  344. }
  345. FUNCTION READCODE:BOOLEAN;
  346. VAR   I  : WORD;
  347. BEGIN
  348.   IF (BITOFFSET+CODESIZE) > BITSIZ THEN BEGIN
  349.     I := BITSIZ - BITOFFSET;
  350.     IF (I AND 7) <> 0 THEN I := SUCC(I SHR 3) ELSE I := I SHR 3;
  351.     IF I > 0 THEN MOVE(BUF[(BITSIZ SHR 3)-I],BUF[0],I);
  352.     BITOFFSET := BITOFFSET AND 7;
  353.     BLOCKREAD(F,B,1);
  354.     BITSIZ := (B + I) SHL 3;
  355.     IF B > 0 THEN BLOCKREAD(F,BUF[I],B)
  356.              ELSE WRITE(#7);
  357.     IF EOF(F) THEN BEGIN
  358.       READCODE := FALSE;
  359.       EXIT;
  360.     END;
  361.   END;
  362.   MOVE(BUF[BITOFFSET SHR 3],BITBUF,3);
  363.   CODE := WORD( BITBUF SHR (BITOFFSET AND 7) ) AND READMASK;
  364.   INC(BITOFFSET,CODESIZE);
  365.   READCODE := (CODE <> EOFCODE);
  366. END; { READCODE }
  367.  
  368.  
  369. { ES HEIßT DESHALB 'LADEBILD', WEIL IM KOMPLETTEN PROGRAMM EIN UNTERSCHIED
  370.   ZWISCHEN LADEN UND ANZEIGEN DES BILDES BESTEHT
  371. }
  372. { MEINE OPTIMIERUNGSVERSUCHE AN DIESER PROZEDUR SIND KLÄGLICH GESCHEITERT.
  373.   LEDIGLICH DAS WEGLASSEN DER EOF- PRÜFUNG NACH JEDEM READCODE HAT EINE
  374.   SICHTBARE VERSCHNELLERUNG ERGEBEN.
  375.   UM AUF LADEGESCHWINDIGKEITEN ZU KOMMEN, WIE SIE Z.B. VPIC.EXE ERREICHT,
  376.   IST ES VERMUTLICH UNUMGÄNGLICH, IN ASSEMBLER ZU PROGRAMMIEREN
  377. }
  378. PROCEDURE LADEBILD;
  379. BEGIN
  380.   BLOCKREAD(F,CODESIZE,1);
  381.   CLEARCODE := POWERSOF2[CODESIZE];
  382.   EOFCODE   := SUCC(CLEARCODE);
  383.   FIRSTFREE := SUCC(EOFCODE);
  384.  
  385.   INC(CODESIZE);
  386.   INICODSIZ := CODESIZE;
  387.   BITMASK   := CODEMASK[HDR.BPP];
  388.  
  389.   GIFDOCLEAR;
  390.   B         := 0;
  391.   BITSIZ    := 0;
  392.   BITOFFSET := 0;
  393.   OUTCOUNT  := 0;
  394.  
  395.   XP        := 0; {PICDESC.LEFT}
  396.   YP        := 0; {PICDESC.TOP}
  397.   IF PICDESC.INTERL THEN PASS := 1 ELSE PASS := 0;
  398.  
  399.   WHILE READCODE DO BEGIN
  400.     IF CODE = CLEARCODE THEN BEGIN
  401.       GIFDOCLEAR;
  402.       IF READCODE THEN;
  403.       OLDCODE := CODE;
  404.       FINCHAR := BYTE(CODE);
  405.       OUTCODE[OUTCOUNT] := CODE;
  406.       INC(OUTCOUNT);
  407.     END ELSE BEGIN
  408.       CURCODE := CODE;
  409.       IF CODE >= FREECODE THEN BEGIN
  410.         CURCODE := OLDCODE;
  411.         OUTCODE[OUTCOUNT] := FINCHAR;
  412.         INC(OUTCOUNT);
  413.       END;
  414.  
  415.       IF CURCODE > EOFCODE THEN REPEAT
  416.     OUTCODE[OUTCOUNT] := SUFFIX[CURCODE];
  417.     INC(OUTCOUNT);
  418.         CURCODE := PREFIX[CURCODE];
  419.       UNTIL CURCODE < EOFCODE;
  420.  
  421.       FINCHAR := BYTE(CURCODE);
  422.       OUTCODE[OUTCOUNT] := CURCODE;
  423.       FOR I := OUTCOUNT DOWNTO 0 DO PUTPIXEL(OUTCODE[I]);
  424.       OUTCOUNT := 0;
  425.  
  426.       PREFIX[FREECODE] := OLDCODE;
  427.       SUFFIX[FREECODE] := FINCHAR;
  428.       OLDCODE          := CODE;
  429.       INC(FREECODE);
  430.       IF FREECODE >= MAXCODE THEN BEGIN
  431.         IF CODESIZE < 12 THEN BEGIN
  432.           INC(CODESIZE);
  433.           MAXCODE := MAXCODE SHL 1;
  434.           READMASK := MASKS[CODESIZE-3];
  435.         END;
  436.       END;
  437.     END;
  438. (*
  439. { HIERDURCH WIRD'S ETWAS LANGSAMER, ABER DER LADEVORGANG KANN JEDERZEIT
  440.   ABGEBROCHEN WERDEN
  441. }
  442.     IF KEYPRESSED THEN IF READKEY = ^[ THEN AUS;
  443. *)
  444.   END; { WHILE READCODE }
  445.   IF CODE = EOFCODE THEN BEGIN
  446.     SOUND(3000);
  447.     DELAY(100);
  448.     NOSOUND;
  449.   END ELSE WRITE(#7);
  450. END; { LADEBILD }
  451.  
  452. { ENDE DES KERNS DES GIF- DECODERS }
  453. {---------------------------------------------------------------------}
  454.  
  455.  
  456. BEGIN { MAIN }
  457.   IF PARAMCOUNT = 0 THEN BEGIN
  458.     WRITELN('Eingabe : GIFMINI Filename[.GIF]');
  459.     HALT;
  460.   END;
  461.  
  462.   FN := PARAMSTR(1);
  463.   IF POS('.',FN) = 0 THEN FN := FN + '.GIF';
  464.  
  465.   ASSIGN(F,FN);
  466. { MIT FILEMODE := 0 KÖNNEN AUCH READ- ONLY- FILES GELESEN WERDEN ! }
  467.   FILEMODE := 0; { FILE F ÖFFNEN NUR LESEN }
  468.   RESET(F,1);
  469.   I := LIESHDR;
  470.   IF I >= 0 THEN BEGIN
  471.     ZEIGEHDR; { KANN NATÜRLICH ENTFALLEN }
  472.     GRAPHEIN;
  473.     LADEBILD;
  474.     CLOSE(F); { NUR NÖTIG, WENN MEHRERE BILDER NACHEINANDER GELESEN WERDEN }
  475.   END ELSE BEGIN
  476.     WRITELN('Fehler ',I,' im GIF- Header');
  477.     HALT;
  478.   END;
  479.  
  480.   IF READKEY = ^[ THEN;
  481.   AUS;
  482. END.
  483. {
  484.   WENN SIE DAS PROGRAMM GUT FINDEN, KÖNNEN SIE AUCH DAS KOMPLETTE PROGRAMM
  485.   KOSTENLOS BEKOMMEN.
  486.   DIES VERFÜGT ÜBER EINE FILESELECTOR- BOX,
  487.   EINE MÖGLICHKEIT, SLIDESHOWS ZU MACHEN,
  488.   MIT DEM ADLIB- SYNTHESIZER LIEDER ZU SPIELEN, ES LÄDT SOGAR BEI BEDARF
  489.   DEN ADLIB- TREIBER AUTOMATISCH ( SOUND.COM UND PLAYROL.EXE WERDEN ALS
  490.   EXTERNE PROGRAMME BENÖTIGT ),
  491.   AUCH EINE ZUFALLSGESTEUERTE AUSWAHL VON BILDERN UND LIEDERN IST MÖGLICH.
  492.  
  493.   ----- A B E R -----
  494.  
  495.   DAS KOMPLETTE PROGRAMM FUNKTIONERT NUR MIT VGA'S, DIE MIT DEM TSENG- LABS
  496.   CHIP ET 3000 ODER ET 4000 BESTÜCKT SIND, UND SIE BRAUCHEN ZUM COMPILIEREN
  497.   DES PROGRAMMS DIE TOOLBOX TURBO PROFESSIONAL
  498. }
  499.  
  500.  
  501.