Outils pour utilisateurs

Outils du site


back2root:archives:denthor:part-05

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révisionLes deux révisions suivantes
back2root:archives:denthor:part-05 [2021/09/02 10:27] – [In closing] fraterback2root:archives:denthor:part-05 [2021/09/05 13:46] frater
Ligne 147: Ligne 147:
 Cheers, Cheers,
 Denthor Denthor
 +
 +==== Code Source ====
 +
 +=== PASCAL ===
 +
 +<code pascal>
 +(*****************************************************************************)
 +(*                                                                           *)
 +(* TUT3.PAS - VGA Trainer Program 5 (in Pascal)                              *)
 +(*                                                                           *)
 +(* "The VGA Trainer Program" is written by Denthor of Asphyxia.  However it  *)
 +(* was limited to Pascal only in its first run.  All I have done is taken    *)
 +(* his original release, translated it to C++, and touched up a few things.  *)
 +(* I take absolutely no credit for the concepts presented in this code, and  *)
 +(* am NOT the person to ask for help if you are having trouble.              *)
 +(*                                                                           *)
 +(* Program Notes : This program presents the basic demo scroller.            *)
 +(*                                                                           *)
 +(* Author        : Grant Smith (Denthor)  - denthor@beastie.cs.und.ac.za     *)
 +(*                                                                           *)
 +(*****************************************************************************)
 +
 +{$X+} {$R-}
 +Uses Crt;
 +
 +CONST VGA = $a000;
 +      XSize = 16;
 +      YSize = 16;
 +
 +TYPE
 +        Letter = Array[1..xsize,1..ysize] of Byte;
 +        Letters = Array[' '..']'] of Letter;
 +
 +VAR Font : ^Letters;
 +
 +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 +Procedure SetMCGA;  { This procedure gets you into 320x200x256 mode. }
 +BEGIN
 +  asm
 +     mov        ax,0013h
 +     int        10h
 +  end;
 +END;
 +
 +
 +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 +Procedure SetText;  { This procedure returns you to text mode.  }
 +BEGIN
 +  asm
 +     mov        ax,0003h
 +     int        10h
 +  end;
 +END;
 +
 +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 +procedure WaitRetrace; assembler;
 +  { This waits until you are in a Verticle Retrace }
 +
 +label
 +  l1, l2;
 +asm
 +    mov dx,3DAh
 +l1:
 +    in al,dx
 +    and al,08h
 +    jnz l1
 +l2:
 +    in al,dx
 +    and al,08h
 +    jz  l2
 +end;
 +
 +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 +Procedure Pal(ColorNo : Byte; R,G,B : Byte);
 +  { This sets the Red, Green and Blue values of a certain color }
 +Begin
 +   Port[$3c8] := ColorNo;
 +   Port[$3c9] := R;
 +   Port[$3c9] := G;
 +   Port[$3c9] := B;
 +End;
 +
 +
 +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 +Procedure PutPixel (X,Y : Integer; Col : Byte; Where : Word);
 +   { This puts a pixel at X,Y using color col, on VGA or the Virtual Screen}
 +BEGIN
 +  Mem [Where:X+(Y*320)]:=col;
 +END;
 +
 +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 +procedure LoadPal (FileName : string);
 +   { This loads the Pallette file and puts it on screen }
 +type DACType = array [0..255] of record
 +                                R, G, B : byte;
 +                              end;
 +var DAC : DACType;
 +    Fil : file of DACType;
 +    I : integer;
 +BEGIN
 +  assign (Fil, FileName);
 +  reset (Fil);
 +  read (Fil, DAC);
 +  close (Fil);
 +  for I := 0 to 255 do Pal(I,Dac[I].R,Dac[I].G,Dac[I].B);
 +end;
 +
 +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 +function Exist(FileName: string): Boolean;
 +    { Checks to see if filename exits or not }
 +var f: file;
 +begin
 +  {$I-}
 +  Assign(f, FileName);
 +  Reset(f);
 +  Close(f);
 +  {$I+}
 +  Exist := (IOResult = 0) and
 +   (FileName <> '');
 +end;
 +
 +
 +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 +Procedure Setup;
 +  { This loads the font and the pallette }
 +VAR f:file;
 +    loop1:char;
 +    loop2,loop3:integer;
 +BEGIN
 +  getmem (font,sizeof (font^));
 +  If exist ('softrock.fnt') then BEGIN
 +    Assign (f,'softrock.fnt');
 +    reset (f,1);
 +    blockread (f,font^,sizeof (font^));
 +    close (f);
 +    Writeln ('SoftRock.FNT from TEXTER5 found in current directory. Using.');
 +  END
 +  ELSE BEGIN
 +    Writeln ('SoftRock.FNT from TEXTER5 not found in current directory.');
 +    For loop1:=' ' to ']' do
 +      For loop2:=1 to 16 do
 +        for loop3:=1 to 16 do
 +          font^[loop1,loop2,loop3]:=loop2;
 +  END;
 +  If exist ('pallette.col') then
 +    Writeln ('Pallette.COL from TEXTER5 found in current directory. Using.')
 +  ELSE
 +    Writeln ('Pallette.COL from TEXTER5 not found in current directory.');
 +  Writeln;
 +  Writeln;
 +  Write ('Hit any key to continue ...');
 +  readkey;
 +  setmcga;
 +  If exist ('pallette.col') then loadpal ('pallette.col');
 +END;
 +
 +
 +{ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
 +Procedure ScrollMsg (Msg : String);
 +  { This scrolls the string in MSG across the screen }
 +Var Loop1,loop2,loop3 : Integer;
 +Begin
 +  For loop1:=1 to length (msg) do BEGIN
 +    For loop2:=1 to xsize do BEGIN
 +
 +      { This bit scrolls the screen by one then puts in the new row of
 +        letters }
 +
 +      waitretrace;
 +      For Loop3 := 100 to 99+ysize do
 +        move (mem[vga:1+(loop3*320)],mem[vga:(loop3*320)],319);
 +      for loop3:=100 to 99+ysize do
 +        putpixel (319,loop3,font^[msg[loop1],loop2,loop3-99],vga);
 +           { Change the -99 above to the minimum of loop3-1, which you
 +             will change in order to move the position of the scrolly }
 +    END;
 +
 +    {This next bit scrolls by one pixel after each letter so that there
 +      are gaps between the letters }
 +
 +    waitretrace;
 +    For Loop3 := 100 to 99+ysize do
 +      move (mem[vga:1+(loop3*320)],mem[vga:(loop3*320)],319);
 +      for loop3:=100 to 99+ysize do
 +        putpixel (319,loop3,0,vga);
 +  END;
 +End;
 +
 +
 +BEGIN
 +  ClrScr;
 +  Writeln ('This program will give you an example of a scrolly. If the file');
 +  Writeln ('SOFTROCK.FNT is in the current directory, this program will scroll');
 +  Writeln ('letters, otherwise it will only scroll bars. It also searches for');
 +  Writeln ('PALLETTE.COL, which it uses for it''s pallette. Both SOFTROCK.FNT');
 +  Writeln ('and PALLETTE.COL come with TEXTER5.ZIP, at a BBS near you.');
 +  Writeln;
 +  Writeln ('You will note that you can change what the scrolly says merely by');
 +  Writeln ('changing the string in the program.');
 +  Writeln;
 +  Setup;
 +  repeat
 +    ScrollMsg ('ASPHYXIA RULZ!!!   ');
 +  until keypressed;
 +  Settext;
 +  freemem (font, sizeof (font^));
 +  Writeln ('All done. This concludes the fifth sample program in the ASPHYXIA');
 +  Writeln ('Training series. You may reach DENTHOR under the name of GRANT');
 +  Writeln ('SMITH on the MailBox BBS, or leave a message to ASPHYXIA on the');
 +  Writeln ('ASPHYXIA BBS. Get the numbers from Roblist, or write to :');
 +  Writeln ('             Grant Smith');
 +  Writeln ('             P.O. Box 270');
 +  Writeln ('             Kloof');
 +  Writeln ('             3640');
 +  Writeln ('I hope to hear from you soon!');
 +  Writeln; Writeln;
 +  Write   ('Hit any key to exit ...');
 +  Readkey;
 +END.
 +</code>
 +
 +=== C ===
 +
 +<code c>
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// TUTPROG5.CPP - VGA Trainer Program 5 (in Turbo C++ 3.0)                 //
 +//                                                                         //
 +// "The VGA Trainer Program" is written by Denthor of Asphyxia. However it //
 +// was limited to Pascal only in its first run.  All I have done is taken  //
 +// his original release, translated it to C++ and touched up a few things. //
 +// I take absolutely no credit for the concepts presented in this code and //
 +// am NOT the person to ask for help if you are having trouble.            //
 +//                                                                         //
 +// Program Notes : This program presents the basic demo scroller.          //
 +//                                                                         //
 +//                 If you are compiling this code command line, be sure to //
 +//                 use the "-ml" parameter (large memory model).           //
 +//                 Otherwise, the program will compile and link, but will  //
 +//                 lock up your system.                                    //
 +//                                                                         //
 +// Author        : Grant Smith (Denthor) - denthor@beastie.cs.und.ac.za    //
 +// Translator    : Christopher G. Mann   - r3cgm@dax.cc.uakron.edu         //
 +//                                                                         //
 +// Last Modified : December 27, 1994                                       //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +//               //
 +// INCLUDE FILES //
 +//               //
 +
 +  #include <conio.h>
 +    // clrscr(), getch(), kbhit()
 +  #include <dos.h>
 +    // MK_FP, geninterrupt()
 +  #include <iostream.h>
 +    // cout
 +  #include <stdio.h>
 +    // fopen(), fread(), fclose(), FILE
 +  #include <stdlib.h>
 +    // calloc(), free(), exit()
 +
 +//           //
 +// CONSTANTS //
 +//           //
 +
 +  const XSize = 16;        // the width  of our font
 +  const YSize = 16;        // the height of our font
 +  const NumLetters = 62;   // the number of characters in our font
 +
 +//                     //
 +// FUNCTION PROTOTYPES //
 +//                     //
 +
 +  // MODE SETTING FUNCTIONS
 +  void SetMCGA();
 +  void SetText();
 +
 +  // UTILITY FUNCTIONS
 +  void Pal(unsigned char ColorNo, unsigned char R,
 +    unsigned char G,       unsigned char B);
 +  void LoadPal(char *FileName);
 +  void Putpixel(int x, int y, unsigned char Col, unsigned char *Where);
 +  void WaitRetrace();
 +  int  Exist(char *FileName);
 +
 +  // MID-LEVEL FUNCTIONS
 +  void Setup();
 +  void ScrollMsg (char *Msg, int SizeMsg);
 +
 +//                 //
 +// GLOBAL TYPEDEFs //
 +//                 //
 +
 +  typedef unsigned char Letter[XSize][YSize];
 +
 +//                              //
 +// GLOBAL VARIABLE DECLARATIONS //
 +//                              //
 +
 +  // pointer to the offset of the VGA memory
 +  unsigned char *vga = (unsigned char *) MK_FP(0xA000, 0);
 +
 +  // pointer to our index of font data
 +  Letter *Font;
 +
 +
 +///////////////////////////////////////////////////////////////////////////////
 +//                                                                           //
 +//                                MAIN FUNCTION                              //
 +//                                                                           //
 +///////////////////////////////////////////////////////////////////////////////
 +
 +void main() {
 +
 +  clrscr();
 +  cout
 +    << "This program will give you an example of a scrolly. If the file\n"
 +    << "SOFTROCK.FNT is in the current directory, this program will scroll\n"
 +    << "letters, otherwise it will only scroll bars. It also searches for\n"
 +    << "PALLETTE.COL, which it uses for it''s pallette. Both SOFTROCK.FNT\n"
 +    << "and PALLETTE.COL come with TEXTER5.ZIP, at a BBS near you.\n\n";
 +  cout
 +    << "You will note that you can change what the scrolly says merely by\n"
 +    << "changing the string in the program.\n\n";
 +
 +  Setup();
 +
 +  do ScrollMsg ("ASPHYXIA RULZ!!!   ",19); while (!kbhit());
 +  getch();
 +
 +  SetText();
 +  free(Font);
 +
 +  cout
 +    << "All done. This concludes the fifth sample program in the ASPHYXIA\n"
 +    << "Training series. You may reach DENTHOR under the name of GRANT\n"
 +    << "SMITH on the MailBox BBS, or leave a message to ASPHYXIA on the\n"
 +    << "ASPHYXIA BBS. Get the numbers from Roblist, or write to :\n"
 +    << "             Grant Smith\n"
 +    << "             P.O. Box 270\n"
 +    << "             Kloof\n"
 +    << "             3640\n"
 +    << "I hope to hear from you soon!\n\n";
 +  cout
 +    << "Hit any key to exit ...";
 +  getch();
 +
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// SetMCGA() - This function gets you into 320x200x256 mode.               //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +void SetMCGA() {
 +  _AX = 0x0013;
 +  geninterrupt (0x10);
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// SetText() - This function gets you into text mode.                      //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +void SetText() {
 +  _AX = 0x0003;
 +  geninterrupt (0x10);
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// Pal() - This sets the Red, Green, and Blue values of a certain color.   //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +void Pal(unsigned char ColorNo, unsigned char R,
 + unsigned char G,       unsigned char B) {
 +
 +  outp (0x03C8,ColorNo); // here is the pallette color I want to set
 +  outp (0x03C9,R);
 +  outp (0x03C9,G);
 +  outp (0x03C9,B);
 +
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// LoadPal() - This loads the Pallette file and puts it on screen.         //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +void LoadPal(char *FileName) {
 +
 +  typedef unsigned char DACType[256][3]; // [256] colors, [3] types (R,G,B)
 +  DACType DAC;
 +  FILE *fp;
 +  int loop1;
 +
 +  fp = fopen(FileName,"rb");
 +  fread(DAC,sizeof(DACType),1,fp);
 +  fclose(fp);
 +
 +  for (loop1=0; loop1<256; loop1++)
 +    Pal(loop1, DAC[loop1][0], DAC[loop1][1], DAC[loop1][2]);
 +
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// Putpixel() - This puts a pixel at X,Y using color Col, on VGA or the    //
 +//              Virtual Screen;                                            //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +void Putpixel (int x, int y, unsigned char Col, unsigned char *Where) {
 +  memset(Where+(x+(y*320)),Col,1);
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// WaitRetrace() - This waits until you are in a Verticle Retrace.         //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +void WaitRetrace() {
 +
 +  _DX = 0x03DA;
 +
 +  l1: asm {
 + in  al,dx;
 + and al,0x08;
 + jnz l1;
 +      }
 +
 +  l2: asm {
 + in  al,dx;
 + and al,0x08;
 + jz  l2;
 +      }
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// Exist() - Checks to see if file exists or not.                          //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +int Exist (char *FileName) {
 +
 +  FILE *fp;
 +
 +  if ((fp = fopen(FileName,"rb")) != NULL) {
 +    fclose(fp);
 +    return 1;
 +  }
 +  else
 +    return 0;
 +
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// Setup() - This loads the font and the pallette.                         //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +void Setup() {
 +
 +  FILE *fp;
 +  int loop1, loop2, loop3;
 +
 +  Font = (Letter *) calloc(NumLetters,sizeof(Letter));
 +
 +    if (Font == NULL) { // always check to make sure you have enough memory!
 +      SetText();
 +      cout << "Not enough memory available, exiting program...";
 +      exit(1);
 +    }
 +
 +  if (Exist("SOFTROCK.FNT\0")) { // don't forget the "\0" null terminator
 +    fp = fopen("SOFTROCK.FNT","rb");
 +    fread(Font,sizeof(Letter),NumLetters,fp);
 +    cout << "SoftRock.FNT from TEXTER5 found in current directory. Using.\n";
 +    fclose(fp);
 +  }
 +  else {
 +    cout << "SoftRock.FNT from TEXTER5 not found in current directory.\n";
 +    for     (loop1=0; loop1<NumLetters; loop1++)
 +      for   (loop2=0; loop2<XSize;      loop2++)
 + for (loop3=0; loop3<YSize;      loop3++)
 +   Font[loop1][loop2][loop3] = loop2;
 +  }
 +
 +  if (Exist("PALLETTE.COL\0")) // don't forget the \0 null terminator
 +    cout << "Pallette.COL from TEXTER5 found in current directory. Using.\n";
 +  else
 +    cout << "Pallette.COL from TEXTER5 not found in current directory.\n";
 +
 +  cout << "\n\nHit any key to continue ...";
 +  getch();
 +
 +  SetMCGA();
 +
 +  if (Exist("PALLETTE.COL\0")) LoadPal("PALLETTE.COL\0");
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////
 +//                                                                         //
 +// ScrollMsg() - This scrolls the string in Msg across the screen.         //
 +//                                                                         //
 +/////////////////////////////////////////////////////////////////////////////
 +
 +void ScrollMsg (char *Msg, int SizeMsg) {
 +
 +  int loop1, loop2, loop3;
 +  int Location = 100; // specify how far from the top of the screen we want
 +       // the scroller to appear
 +
 +  // MAIN LOOP - do every letter in Msg
 +  for (loop1 = 0; loop1 < SizeMsg; loop1++) {
 +
 +    // Do this loop <n> number of times where <n> = the width of a letter
 +    for (loop2 = 0; loop2 < XSize; loop2++) {
 +
 +    // There are two loops here.
 +    //
 +    // 1. Copy YSize rows to the left by 1.  In effect, this frees up a
 +    //    blank column of vertical pixels on the right side of the screen.
 +    // 2. Replace that new blank column with pixels from our Font[] table.
 +
 +    WaitRetrace();
 +
 +    for (loop3=Location; loop3<Location+YSize; loop3++)
 +      // move each row to the left by 1
 +      memcpy(vga+(0+(loop3*320)), vga+(1+(loop3*320)), 320);
 +
 +    for (loop3=Location; loop3<Location+YSize; loop3++)
 +      // Replace the new column on the right with information from Font[].
 +      // In the following statement:
 +      //   (320,         - y location (the rightmost column)
 +      //   loop3,        - x location (the current row we are working with)
 +      //   Font[...      - Get information from our Font table.  All of this
 +      //                   complex indexing really just gives us the pallette
 +      //                   number we are putting to the screen at a given
 +      //                   location.
 +      //    [(Msg[loop1]-32)] - Access the correct letter from our Font
 +      //                        table.  The (Msg[loop1]) would give us the
 +      //                        ASCII value of the letter we want to display,
 +      //                        but we need to subtract 32 to coordinate the
 +      //                        ASCII value with our Font table.
 +      //    [loop2]           - the column index of the letter we are using
 +      //    [loop3-Location]  - the row    index of the letter we are using
 +      Putpixel (319,loop3,Font[(Msg[loop1]-32)][loop2][loop3-Location],vga);
 +
 +    } // we have now inserted a new letter on the right side of the screen
 +
 +  // This next bit scrolls by one pixel after each letter so that there
 +  // are gaps between the letters
 +
 +  WaitRetrace();
 +
 +  for (loop3=Location; loop3<Location+YSize; loop3++)
 +    // move each row to the left by 1 (same as above)
 +    memcpy( vga+(loop3*320), vga+(1+(loop3*320)), 320);
 +
 +  for (loop3 = 100; loop3 < 100 + YSize; loop3++)
 +    // put a blank column of pixels
 +    Putpixel(319,loop3,0,vga);
 +
 +  } // we have now scrolled the entire message once
 +
 +}
 +</code>
  
 <nspages back2root/archives/denthor -simpleList -title -h1 -exclude:start -textPages="Denthor VGA Trainer"> <nspages back2root/archives/denthor -simpleList -title -h1 -exclude:start -textPages="Denthor VGA Trainer">
back2root/archives/denthor/part-05.txt · Dernière modification : 2023/05/18 21:06 de frater