home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / spezial / 19 / snap / savepcx.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1990-08-01  |  16.5 KB  |  611 lines

  1. (* ------------------------------------------------------ *)
  2. (*                    SavePCX.PAS                         *)
  3. (*                    Unit SavePCX                        *)
  4. (*                 Turbo Pascal ab 5.0                    *)
  5. (*       (c) 1990 Gerald Arend, G. Huber & TOOLBOX        *)
  6. (* ------------------------------------------------------ *)
  7. {$R-,S-,I-,V-,B-,N-,D-,F-,L-}
  8.  
  9. UNIT SavePCX;
  10.  
  11. INTERFACE
  12.  
  13. USES Dos, Graph, Crt;
  14.  
  15. TYPE
  16.   PCX_HEADER = RECORD
  17.                  Creator    : BYTE; { Immer 10 für ZSoft   }
  18.                  Version    : BYTE; { PCX-Version:         }
  19.                              { 0 = Version 2.5 o. Palette  }
  20.                              { 2 = Version 2.8 m. Palette  }
  21.                              {     oder Version 3.0 o. Pal.}
  22.                              { 3 = Version 2.8/3.0  o. Pal.}
  23.                              { 5 = Version 3.0 mit Pal.    }
  24.                  Encoding   : BYTE;
  25.                              { 1 = Run-Length-Encoded      }
  26.                  Bits       : BYTE; { Pixel pro Bit        }
  27.                              { für CGA 320x200 2 Bits,     }
  28.                  XMin, YMin,
  29.                  XMax, YMax : INTEGER;
  30.                  Hres, VRes : INTEGER;
  31.                  Palette    : ARRAY[0..15, 0..2] OF BYTE;
  32.                  VMode      : BYTE;     { Reserviert       }
  33.                  Planes     : BYTE;     { Farbebenen       }
  34.                  BytePerLine: INTEGER;  { Bytes/Scanzeile  }
  35.                  PaletteInfo: INTEGER;
  36.                                  { 1 = Farbe/Schwarz-Weiß  }
  37.                                  { 2 = Grauwerte           }
  38.                  dummy      : ARRAY[0..57] OF BYTE;
  39.                END;
  40.  
  41.   PlaneType = ARRAY[0..90] OF BYTE;
  42.   plane     = ^Planetype;
  43.   ScanLine  = ARRAY[0..3] OF plane;
  44.  
  45. CONST
  46.   ActivePage : WORD = 0;
  47.   EGAOnly: BOOLEAN = FALSE;
  48.   DOSFehler: BOOLEAN = FALSE;
  49.   MaxColors = 15;
  50.   numpic     : WORD = 1;
  51.   AttrScreen : BOOLEAN = FALSE;
  52.  
  53. VAR
  54.   Xmin, Xmax, Ymin, Ymax, vmodus : WORD;
  55.   Screen: BYTE;
  56.   gd, gm: INTEGER;
  57.   z: ScanLine;
  58.  
  59.   PROCEDURE WritePCXHeader(VAR PCXH : PCX_Header;
  60.                                name : STRING);
  61.   PROCEDURE WritePCXByte(VAR F : FILE; wert, counter : BYTE);
  62.   PROCEDURE WritePCXLine(VAR F     : FILE;
  63.                          VAR buf   : plane;
  64.                          count: BYTE);
  65.   PROCEDURE BGIToPCX(gd, gm : INTEGER;
  66.                      name   : STRING);
  67.   FUNCTION HGCGrafik: BOOLEAN;
  68.   PROCEDURE Screen2PCX(Name: STRING);  { speichert Bildschirm als
  69.       PCX-Datei ab. Der Name muß OHNE Endung angegeben werden ! }
  70.  
  71. IMPLEMENTATION
  72.  
  73. CONST
  74.   HercBase = $B000;
  75.   EgaBase  = $A000;
  76.   CgaBase  = $B800;
  77.   BLOCKSIZE: WORD = 512;
  78.  
  79. VAR
  80.   PCXbuf : ARRAY[1..512] OF BYTE;
  81.   I, J   : WORD;
  82.   SPtr   : POINTER;
  83.   PCXH   : PCX_Header;
  84.  
  85. PROCEDURE ErrorSound;
  86. VAR
  87.   i, n: BYTE;
  88. BEGIN
  89.   FOR i:=1 TO 3 DO
  90.   BEGIN
  91.     FOR n:=1 TO 100 DO
  92.     BEGIN
  93.       Sound(440);
  94.       Delay(1);
  95.       Sound(480);
  96.       Delay(1);
  97.     END;
  98.     NoSound;
  99.     Delay(300);
  100.   END;
  101. END;
  102.  
  103. PROCEDURE ErrorCheck;
  104. BEGIN
  105.   DOSFehler:=(IOResult<>0);
  106.   IF DOSFehler THEN
  107.     ErrorSound;
  108. END;
  109.  
  110. PROCEDURE EGA2PCX(VAR Header: PCX_Header; Farben: PaletteType);
  111. VAR
  112.   i, j, c: BYTE;
  113. CONST
  114.    PCXDefaultPalette : ARRAY[0..15, 0..2] OF BYTE =
  115.          ((0, 0, 0), (0, 0, 170), (0, 170, 0), (0, 170, 170),
  116.          (170, 0, 0), (170, 0, 170), (170, 170, 0),
  117.          (170, 170, 170),
  118.          (85, 85, 85), (85, 85, 255), (85, 255, 85),
  119.          (85, 255, 255),
  120.          (255, 85, 85), (255, 85, 255), (255, 255, 85),
  121.          (255, 255, 255));
  122. BEGIN
  123.   IF EGAOnly THEN
  124.     { Die Farbregister der EGA-Karte können nicht gelesen
  125.       werden! Snapshot muß daher immer die Standard-EGA-Palette
  126.       in den PCX-Header schreiben }
  127.     Move(PCXDefaultPalette, PCXH.Palette, 48)
  128.   ELSE               { VGA emuliert EGA: Farbregister werden gelesen }
  129.     FOR i:=0 TO MaxColors DO
  130.     BEGIN
  131.       WITH Header DO
  132.       BEGIN
  133.         c:=BYTE(Farben.Colors[i]);
  134.         Palette[i, 0]:=
  135.           ((c AND 32) SHR 5) OR ((c AND 4) SHR 1);
  136.         Palette[i, 1]:=
  137.           ((c AND 16) SHR 4) OR (c AND 2);
  138.         Palette[i, 2]:=
  139.           ((c AND 8) SHR 3) OR ((c AND 1) SHL 1);
  140.       END;
  141.       FOR j:=0 TO 2 DO
  142.         CASE Header.Palette[i, j] OF
  143.           1: Header.Palette[i, j]:=85;
  144.           2: Header.Palette[i, j]:=170;
  145.           3: Header.Palette[i, j]:=225;
  146.         END;
  147.     END;
  148. END;
  149.  
  150. PROCEDURE VGA2PCX(VAR Header: PCX_Header);
  151. VAR
  152.   R: Registers;
  153.   j: BYTE;
  154.   VGAFarbNr: ARRAY[0..MaxColors] OF BYTE;
  155. BEGIN
  156.   R.AH:=$10;    { Alle Paletteneinträge lesen }
  157.   R.AL:=$09;
  158.   R.ES:=Seg(VGAFarbNr);
  159.   R.DX:=Ofs(VGAFarbNr);
  160.   Intr($10, R);
  161.   FOR J:=0 TO 15 DO
  162.   BEGIN
  163.     R.AH:=$10;
  164.     R.AL:=$15;
  165.     R.BX:=VGAFarbNr[J];
  166.     Intr($10, R);
  167.     PCXH.Palette[J, 0]:=R.DH SHL 2;
  168.     PCXH.Palette[J, 1]:=R.CH SHL 2;
  169.     PCXH.Palette[J, 2]:=R.CL SHL 2;
  170.   END;
  171. END;
  172.  
  173. PROCEDURE DefPCXPalette(VAR PCXH : PCX_Header;
  174.                         ColTYPE : BYTE);
  175. VAR
  176.   I, J : INTEGER;
  177.   R: Registers;
  178.   EGAFarben: PaletteType;
  179. BEGIN
  180.   CASE ColType OF
  181.     0 : BEGIN
  182.           FillChar(PCXH.Palette, 48, 255);
  183.           FillChar(PCXH.Palette,  3, 0);
  184.         END;
  185.     1 : FOR I := 0 TO 15 DO BEGIN
  186.           IF Odd(I) THEN
  187.             FOR J := 0 TO 2 DO
  188.               PCXH.Palette[I, J] := 240
  189.           ELSE
  190.             FOR J := 0 TO 2 DO
  191.               PCXH.Palette[I, J] := 0;
  192.         END;
  193.     2 : IF EGAOnly THEN
  194.         BEGIN
  195.           GetPalette(EGAFarben);
  196.           EGA2PCX(PCXH, EGAFarben);
  197.         END
  198.         ELSE
  199.           VGA2PCX(PCXH);
  200.   END;
  201. END;
  202.  
  203. PROCEDURE SetReadPlane(Nr : BYTE);
  204. BEGIN
  205.   Port[$3CE] := 4;
  206.   Port[$3CF] := Nr;
  207. END;
  208.  
  209. PROCEDURE WritePCXHeader(VAR PCXH : PCX_Header;
  210.                          name : STRING);
  211. VAR
  212.   F: FILE;
  213. BEGIN
  214.   Assign(F, name);
  215. {$I-}
  216.   Rewrite(F, 1);
  217.   ErrorCheck;
  218.   IF DOSFehler THEN
  219.     Exit;
  220.   BlockWrite(F, PCXH, 128);
  221.   ErrorCheck;
  222.   IF DOSFehler THEN
  223.     Exit;
  224.   Close(F);
  225. {$I+}
  226. END;
  227.  
  228. PROCEDURE WritePCXByte(VAR F : FILE;
  229.                        wert, counter: BYTE);
  230. BEGIN
  231.   IF (counter = 1) AND ($C0 <> $C0 AND wert) THEN
  232.     BlockWrite(F, wert, 1)
  233.   ELSE
  234.   BEGIN
  235.     counter := $C0 OR counter;
  236.     BlockWrite(F, counter, 1);
  237.     BlockWrite(F, wert, 1);
  238.   END;
  239. END;
  240.  
  241. PROCEDURE WritePCXLine(VAR F     : FILE;
  242.                        VAR buf   : plane;
  243.                        count : BYTE);
  244. VAR
  245.   n, OldByte, Zaehler: BYTE;
  246. BEGIN
  247.   n:=0;
  248.   OldByte:=buf^[0];
  249.   Zaehler:=1;
  250.   REPEAT
  251.     Inc(n);
  252.     IF buf^[n]=OldByte THEN    { gleiches Byte }
  253.       Inc(Zaehler)
  254.     ELSE
  255.     BEGIN
  256.       WHILE Zaehler>63 DO      { neues Byte: Alten Wert schreiben }
  257.       BEGIN                    { nur 63 Wiederholungen maximal möglich }
  258.         WritePCXByte(F, OldByte, 63);
  259.         Dec(Zaehler, 63);
  260.       END;
  261.       IF Zaehler>0 THEN
  262.         WritePCXByte(F, OldByte, Zaehler);
  263.       Zaehler:=1;
  264.       OldByte:=buf^[n];
  265.     END;
  266.   UNTIL n=count-1;
  267.   WHILE Zaehler>63 DO      { neues Byte: Alten Wert schreiben }
  268.   BEGIN                    { nur 63 Wiederholungen maximal möglich }
  269.     WritePCXByte(F, OldByte, 63);
  270.     Dec(Zaehler, 63);
  271.   END;
  272.   IF Zaehler>0 THEN
  273.     WritePCXByte(F, OldByte, Zaehler);
  274. END;
  275.  
  276. PROCEDURE BGIToPCX(gd, gm : INTEGER;
  277.                    name : STRING);
  278. VAR
  279.   F    : FILE;
  280.   Page : INTEGER;
  281.  
  282.  
  283.   PROCEDURE ReOpenFile;
  284.   BEGIN
  285.     Assign(F, name);
  286.     {$I-}
  287.     Reset(f,1);
  288.     {$I+}
  289.     ErrorCheck;
  290.     IF DOSFehler THEN
  291.       Exit;
  292.     Seek(F, 128);
  293.   END;
  294.  
  295. BEGIN
  296.   FillChar(PCXH, 128, 0);
  297.   PCXH.creator     := 10;
  298.   PCXH.version     := 3;
  299.   PCXH.encoding    := 1;
  300.   PCXH.bits        := 1;
  301.   PCXH.xmin        := Xmin;
  302.   PCXH.ymin        := Ymin;
  303.   PCXH.xmax        := XMax;
  304.   PCXH.ymax        := YMax;
  305.   PCXH.PaletteInfo := 1;
  306.   CASE gd OF
  307.     3,4,5,9:
  308.       BEGIN
  309.         CASE gm OF
  310.           0 : BEGIN
  311.                 PCXH.HRes:=640;
  312.                 PCXH.VRes:=200;
  313.                 PCXH.Planes := 4;
  314.                 PCXH.BytePerLine := 80;
  315.                 DefPCXPalette(PCXH, 2);
  316.                 WritePCXHeader(PCXH, name);
  317.                 IF DOSFehler THEN
  318.                   Exit;
  319.                 ReOpenFile;
  320.                 FOR I := 0 TO 199 DO BEGIN
  321.                   SPTR := Ptr(EgaBase +
  322.                               $400 * ActivePage, I*80);
  323.                   FOR Page := 0 TO 3 DO BEGIN
  324.                     SetReadPlane(Page);
  325.                     Move(SPtr^, Z[0]^, 80);
  326.                     WritePCXLine(F, Z[0], 80);
  327.                     ErrorCheck;
  328.                     IF DOSFehler THEN
  329.                       Exit;
  330.                   END;
  331.                 END;
  332.               END;
  333.           1 : BEGIN
  334.                 PCXH.HRes:=640;
  335.                 PCXH.VRes:=350;
  336.                 PCXH.Planes := 4;
  337.                 PCXH.BytePerLine := 80;
  338.                 DefPCXPalette(PCXH, 2);
  339.                 WritePCXHeader(PCXH, name);
  340.                 IF DOSFehler THEN
  341.                   Exit;
  342.                 ReOpenFile;
  343.                 FOR I := 0 TO 349 DO BEGIN
  344.                   SPTR := Ptr(EgaBase +
  345.                               $800 * ActivePage, I*80);
  346.                   FOR Page := 0 TO 3 DO BEGIN
  347.                     SetReadPlane(Page);
  348.                     Move(SPtr^, Z[0]^, 80);
  349.                     WritePCXLine(F, Z[0], 80);
  350.                     ErrorCheck;
  351.                     IF DOSFehler THEN
  352.                       Exit;
  353.                   END;
  354.                 END;
  355.               END;
  356.           2 : BEGIN
  357.                 PCXH.HRes:=640;
  358.                 PCXH.VRes:=480;
  359.                 PCXH.Planes := 4;
  360.                 PCXH.BytePerLine := 80;
  361.                 DefPCXPalette(PCXH, 2);
  362.                 WritePCXHeader(PCXH, name);
  363.                 IF DOSFehler THEN
  364.                   Exit;
  365.                 ReOpenFile;
  366.                 FOR I := 0 TO 479 DO BEGIN
  367.                   SPTR := Ptr(EgaBase +
  368.                               $960 * ActivePage, I*80);
  369.                   FOR Page := 0 TO 3 DO BEGIN
  370.                     SetReadPlane(Page);
  371.                     Move(SPtr^, Z[0]^, 80);
  372.                     WritePCXLine(F, Z[0], 80);
  373.                     ErrorCheck;
  374.                     IF DOSFehler THEN
  375.                       Exit;
  376.                   END;
  377.                 END;
  378.               END;
  379.           3 : BEGIN
  380.                 PCXH.HRes:=640;
  381.                 PCXH.VRes:=350;
  382.                 PCXH.Planes := 1;
  383.                 PCXH.BytePerLine := 80;
  384.                 PCXH.Version := 2;
  385.                 DefPCXPalette(PCXH, 0);
  386.                 WritePCXHeader(PCXH, name);
  387.                 IF DOSFehler THEN
  388.                   Exit;
  389.                 ReOpenFile;
  390.                 SetReadPlane(0);
  391.                 FOR I := 0 TO 349 DO BEGIN
  392.                   SPTR := Ptr(EgaBase +
  393.                               $800 * ActivePage, I*80);
  394.                   Move(SPtr^, Z[0]^, 80);
  395.                   WritePCXLine(F, Z[0], 80);
  396.                   ErrorCheck;
  397.                   IF DOSFehler THEN
  398.                     Exit;
  399.                 END;
  400.               END;
  401.             END;
  402.           END;
  403.      7 :  BEGIN  { CASE gd OF 7 }
  404.             PCXH.HRes:=720;
  405.             PCXH.VRes:=348;
  406.             PCXH.Planes := 1;
  407.             PCXH.BytePerLine := 90;
  408.             PCXH.Version := 2;
  409.             DefPCXPalette(PCXH, 0);
  410.             WritePCXHeader(PCXH, name);
  411.             IF DOSFehler THEN
  412.               Exit;
  413.             ReOpenFile;
  414.             FOR I := 0 TO 347 DO BEGIN
  415.               SPtr := Ptr(HercBase, WORD((I AND 3) SHL 13
  416.                                          + 90*(I SHR 2)));
  417.               Move(SPtr^, Z[0]^, 90);
  418.               WritePCXLine(F, Z[0], 90);
  419.               ErrorCheck;
  420.               IF DOSFehler THEN
  421.                 Exit;
  422.             END;
  423.           END;
  424.  
  425.    1,2 :  BEGIN  { CASE gd OF 1, 2 }
  426.             PCXH.HRes:=320;
  427.             PCXH.VRes:=200;
  428.             PCXH.Planes      := 1;
  429.             PCXH.Bits        := 2;
  430.             PCXH.BytePerLine := 80;
  431.             IF (gd = 2) AND (gm = 5) THEN BEGIN
  432.               J := 479;
  433.               PCXH.Bits := 1;
  434.             END ELSE J := 199;
  435.             IF gm = 4 THEN PCXH.Bits := 1;
  436.             PCXH.Version := 5;
  437.             DefPCXPalette(PCXH, 1);
  438.             WritePCXHeader(PCXH, name);
  439.             IF DOSFehler THEN
  440.               Exit;
  441.             ReOpenFile;
  442.             FOR I := 0 TO J DO BEGIN
  443.               SPtr := Ptr(CgaBase, WORD((I AND 1)
  444.                       SHL 13 + 80*(I SHR 1)));
  445.               Move(SPtr^, Z[0]^, 80);
  446.               WritePCXLine(F, Z[0], 80);
  447.               ErrorCheck;
  448.               IF DOSFehler THEN
  449.                 Exit;
  450.             END;
  451.          END;
  452.   END;
  453.   Close(F);
  454. END;
  455.  
  456. FUNCTION HGCGrafik: BOOLEAN;
  457. VAR
  458.   LP: RECORD
  459.         CASE INTEGER OF
  460.           0 : (LB, HB : BYTE);           { Pos. 2 Bytes }
  461.           1 : (LW     : INTEGER);        { Pos. 1 Word  }
  462.         END;
  463. BEGIN
  464.   Port[$3BB] := 0;         { Reset des Light-Pen-Latch-Reg.}
  465.   WHILE(Port[$3BA] AND $80 <> 0)  DO {};           { Start }
  466.   WHILE(Port[$3BA] AND $80 = 0) DO {};             { Ende  }
  467.   INLINE ($FA);             { cli, Interrupts unterdrücken }
  468.   WHILE(Port[$3BA] AND $80 <> 0 ) DO {};
  469.   Port[$3B9]:=0;               { Light-Pen-Position merken }
  470.   INLINE ($FB);         { sti, Interrupts wieder zulassen  }
  471.   Port[$3B4]:=$10;     { Hi-Byte Light-Pen-Pos.   auslesen }
  472.   LP.HB:=Port[$3B5];
  473.   Port[$3B4]:=$11;           { Lo-Byte Light-Pen-Pos.lesen }
  474.   LP.LB:=Port[$3B5];
  475.   HGCGrafik:=(LP.LW)>(45*87);
  476. END;
  477.  
  478. PROCEDURE TXTScreen(Name: STRING; Base: WORD);
  479. VAR
  480.   S         : STRING[160];
  481.   R         : STRING[80];
  482.   i, J, Seg : WORD;
  483.   P         : POINTER;
  484.   F         : TEXT;
  485. BEGIN
  486.   Assign(F, Name+'.TXT');
  487.   {$I-}
  488.   Rewrite(F);
  489.   {$I+}
  490.   ErrorCheck;
  491.   IF DOSFehler THEN
  492.     Exit;
  493.   Seg:=Base+$100*ActivePage;
  494.   FOR i:=0 TO 24 DO
  495.   BEGIN
  496.     P:=Ptr(Seg, i*160);
  497.     S[0]:=#160;
  498.     Move(P^, S[1], 160);
  499.     R:='';
  500.     J:=1;
  501.     WHILE J<=160 DO
  502.     BEGIN
  503.       R:=R+S[J];
  504.       Inc(J, 2);
  505.     END;
  506.     WriteLn(F, R);
  507.   END;
  508.   Close(F);
  509. END;
  510.  
  511. PROCEDURE ATTScreen(Name: STRING; Base: WORD);
  512. VAR
  513.   P: POINTER;
  514.   F: FILE;
  515. BEGIN
  516.   Assign(F, Name+ '.ATT');
  517.   {$I-}
  518.   Rewrite(F, 1);
  519.   {$I+}
  520.   ErrorCheck;
  521.   IF DOSFehler THEN
  522.     Exit;
  523.   P:=Ptr(WORD(Base+$100*ActivePage), 0);
  524.   BlockWrite(F, P^, 4000);
  525.   Close(F);
  526. END;
  527.  
  528. PROCEDURE Screen2PCX(Name: STRING);
  529. VAR
  530.   Regs: Registers;
  531. BEGIN
  532.   Regs.AH:=$0F;
  533.   Intr($10, Regs);
  534.   vmodus:=Regs.AL;
  535.   ActivePage:=Regs.BH;
  536.   XMin:=0;
  537.   YMin:=0;
  538.   Write(^G);
  539.   CASE vmodus OF
  540.     $3, $83:                 { Text-Modi 40x25 und 80x25   }
  541.         IF AttrScreen THEN ATTScreen(Name, $B800)
  542.                       ELSE TXTScreen(Name, $B800);
  543.     $10, $90:
  544.         BEGIN                                   { EGA-Modi }
  545.           Xmax:=639;
  546.           YMax:=349;
  547.           BGIToPCX(3, 1, Name+'.PCX');
  548.         END;
  549.     $0F, $8F:
  550.         BEGIN                                  { EGA-Mono: }
  551.           Xmax:=639;
  552.           YMax:=349;
  553.           BGIToPCX(3, 3, Name+'.PCX');
  554.         END;
  555.     $0E, $8E:
  556.         BEGIN                                     { EGA-Lo }
  557.           Xmax:=639;
  558.           YMax:=199;
  559.           BGIToPCX(3, 0, Name+'.PCX');
  560.         END;
  561.     $06, $86:
  562.         BEGIN                                        { CGA }
  563.           Xmax:=639;
  564.           YMax:=199;
  565.           BGIToPCX(1, 4, Name+'.PCX');
  566.         END;
  567.     $4, $5,
  568.     $84, $85:
  569.         BEGIN                   { CGA-Modi mit 320 x 200   }
  570.           Xmax:=319;
  571.           YMax:=199;
  572.           BGIToPCX(1, 1, Name+'.PCX');
  573.         END;
  574.     $11, $91,
  575.     $12, $92:
  576.         BEGIN                       { VGA-Grafik-Modi      }
  577.           XMax:=639;
  578.           YMax:=479;
  579.           BGIToPCX(9, 2, Name+'.PCX');
  580.         END;
  581.     $07,$87:
  582.         BEGIN
  583.           IF HGCGrafik THEN
  584.           BEGIN                             { Grafik-Modus }
  585.             Xmax:=719;
  586.             YMax:=347;
  587.             BGIToPCX(7, 0, Name+'.PCX');
  588.           END
  589.           ELSE
  590.           BEGIN                               { Text-Modus }
  591.             ActivePage:=0;
  592.             IF AttrScreen THEN ATTScreen(Name, $B000)
  593.                           ELSE TXTScreen(Name, $B000);
  594.           END;
  595.         END;
  596.   END;
  597.   IF NOT DOSFehler THEN
  598.     Write(^G^G);
  599. END;
  600.  
  601. BEGIN
  602.   GetMem(z[0], 90);
  603.   GetMem(z[1], 90);
  604.   GetMem(z[2], 90);
  605.   GetMem(z[3], 90);
  606.   { ein Plane für CGA/EGA/VGA/Hercules: max 90 Bytes }
  607. END.
  608. (* ------------------------------------------------------ *)
  609. (*                 Ende von SAVEPCX.PAS                   *)
  610.  
  611.