SAUCEU.PAS

10 KB de851919cb584633…
{$I DIRECT.INC}
UNIT SAUCEu;

INTERFACE


{ Types of datafiles implemented }
TYPE  DataTypes      = (None, Character, GFX, Vector, Sounds);

{ Character/Text Files }
TYPE  CharacterFiles = (ASCII, ANSi, ANSiMation, RIP, PCBoard, AVATAR_);

{ Graphics files BITMAP }
TYPE  GFXFiles       = (GIF, PCX, LBM, TGA, FLI, FLC, BMP, GL, DL, WPG);

{ Graphics files Vector }
TYPE  VectorFiles    = (DXF, ACAD_DWG, DrawPerfect);

{ Sound Files }
TYPE  SoundFiles     = (_MOD, _669, _STM, _S3M, _MTM, _FAR, _ULT, _AMF, _DMF,
                        _OKT, _ROL, _CMF, _MIDI, _SADT, _VOC, _WAV,
                        _Sample8, _Sample8Stereo, _Sample16, _Sample16Stereo);

      Char2    = Array [0..1]  of Char;
      Char5    = Array [0..4]  of Char;
      Char8    = Array [0..7]  of Char;
      Char20   = Array [0..19] of Char;
      Char35   = Array [0..34] of Char;
      Char64   = Array [0..63] of Char;

Const SAUCE_ID      : Char5 = 'SAUCE';
      SAUCE_Version : Char2 = '00';
      CMT_ID        : Char5 = 'COMNT';
      MaxCMT        = 10;

TYPE  SAUCERec = RECORD                { ┌── Implemented in Version ?        }
                   ID       : Char5;   { 00  'SAUCE'                         }
                   Version  : Char2;   { 00  '00'                            }
                   Title    : Char35;  { 00  Title of the file               }
                   Author   : Char20;  { 00  Creator of the file             }
                   Group    : Char20;  { 00  Group creator belongs to        }
                   Date     : Char8;   { 00  CCYYMMDD                        }
                   FileSize : Longint; { 00  Original FileSize               }
                   DataType : Byte;    { 00  Type of Data                    }
                   FileType : Byte;    { 00  What type of file is it ?       }
                   TInfo1   : Word;    { 00  \                               }
                   TInfo2   : Word;    { 00   \ Type Info Zone            *2*}
                   TInfo3   : Word;    { 00   /                              }
                   TInfo4   : Word;    { 00  /                               }
                   Comments : Byte;    { 00  Number of Comment lines      *1*}
                   Filler   : Array[1..23] of Char;
                 END;
      CMTRec   = Char64;
      CMTBlock = RECORD
                   ID       : Char5;
                   Comment  : Array[1..MaxCMT] of CMTRec;
                 END;

CONST SAUCE_SIZ= Sizeof(SAUCEREC);
      CMTR_SIZ = Sizeof(CMTRec);
      CMTB_SIZ = Sizeof(CMTBlock);

VAR   SAUCE    : SAUCERec;
      CMT      : CMTBlock;


PROCEDURE ClearSAUCE;

FUNCTION GetSAUCE(FileName : String) : BOOLEAN;


{▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀}
IMPLEMENTATION
{▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄}

PROCEDURE ClearSAUCE;
BEGIN
  FillChar(SAUCE,sizeof(SAUCE),#0);
  FillChar(CMT,sizeof(CMT),#0);
END;


VAR Name0 : Array [0..80] of CHAR;

FUNCTION GetSAUCE(FileName : String) : BOOLEAN; ASSEMBLER;
{ Function returns TRUE if we have a SAUCE record                            }
{ It will continue to try reading a COMMENT block if it's there.  You should }
{ check the SAUCE ID to assure a commentblock was succesfully read           }
VAR           RetVal : BOOLEAN;

ASM
              MOV    [RetVal],FALSE    { Assume theer's gonna be no SAUCE    }
              PUSH   DS                { Save DS                             }
              CALL   ClearSAUCE        {                                     }
              CLD

              MOV    AX,Seg Name0      { \                                   }
              MOV    ES,AX             {  > ES:DI -> Name0 (asciiz filename) }
              MOV    DI,Offset Name0   { /                                   }
              LDS    SI,[FileName]     { DS:SI -> Filename (Pascal String)   }
              LODSB                    { Get Length of String                }
              MOV    CL,AL             { \ Length in CX                      }
              XOR    CH,CH             { /                                   }
              JCXZ   @FinishPatch      { Length == 0 ?                       }
              REP    MOVSB             { Copy Filename                       }
              MOV    AL,0              { \ Store NULL Terminator             }
              STOSB                    { /                                   }

              MOV    AH,03Dh           { Open a file (using a handle)        }
              MOV    AL,000h           { Filemode = Non shared, Read only.   }
              PUSH   ES                { \                                   }
              POP    DS                {  > DS:DX = Filename                 }
              MOV    DX,Offset Name0   { /                                   }
              INT    21h               { And open the File..                 }
              JNC    @FileOpenOK       { IF CF=0 then file is correctly open }

@FinishPatch: JMP    @Finish           { Patch to jump to @Finish label, but }
                                       { too far away for a conditional jump }
                                       { like the JCXZ a couple lines above  }

@FileOpenOk:  MOV    BX,AX             { Handle in BX !! DO NOT CHANGE BX !! }

              MOV    AH,042h           { Move file pointer (LSEEK)           }
              MOV    AL,2              { Move from end of file               }
              MOV    CX,0FFFFh         { \ Seek from EOF -128 bytes          }
              MOV    DX,-SAUCE_SIZ     { /                                   }
              INT    21h               { Do LSEEK ! BX has handle !          }
              JC     @Close            { Seek Failed, Stop reading           }

              MOV    AH,03Fh           { Read from File                      }
              MOV    CX,SAUCE_SIZ      { Read 128 Bytes                      }
              MOV    DX,Seg SAUCE      { \                                   }
              MOV    DS,DX             {  > DS:DX -> Buffer for read         }
              MOV    DX,Offset SAUCE   { /                                   }
              INT    21h               { Read file ! BX has handle !         }
              JC     @Close            { Read Failed, Stop reading           }
              CMP    AX,CX             { \ Stop if we didn't read what we    }
              JNE    @Close            { / wanted.                           }

              MOV    DI,Offset SAUCE
              CMP    Word PTR DS:[DI],'AS'   { \   ID = SAUCE ???            }
              JNE    @Close                  {  \  Note, Intel big-endian    }
              CMP    Word PTR DS:[DI+2],'CU' {   >                           }
              JNE    @Close                  {  /                            }
              CMP    Byte PTR DS:[DI+4],'E'  { /                             }
              JNE    @Close
              { If we get here, we have a valid SAUCE record                 }
              { DS Still points to Segment of SAUCE record                   }
              MOV    [RetVal],TRUE     { We have SAUCE                       }

              MOV    AL,SAUCE.Comments
              OR     AL,AL
              JZ     @Close            { No Comment Block, our work is done  }
              { Comment block is here.  Check it out                         }
              XOR    AH,AH             { # of lines in AX                    }
              MOV    DX,CMTR_SIZ       { DX = Size fo Comment line           }
              MUL    DX                { AX, has size of Comment block.      }
                                       { Max size CMT block: 64*256 = 16K    }
              ADD    AX,5              { Add size of Comment ID              }
              ADD    AX,128            { Add size of SAUCE                   }
              MOV    DI,AX             { DI = Loc from EOF for CMT rec       }

              MOV    AH,042h           { Move file pointer (LSEEK)           }
              MOV    AL,2              { Move from end of file               }
              MOV    CX,0FFFFh         { \  Seek from EOF to start of CMT    }
              MOV    DX,DI             {  > Record                           }
              NEG    DX                { /                                   }
              INT    21h               { Do LSEEK ! BX has handle !          }
              JC     @Close            { Seek Failed, Stop reading           }

              CMP    DI,CMTB_SIZ
              JB     @CMT_OK
              { CMT record in file is bigger than the one we support         }
              { Some Data will be clipped away.                              }
              MOV    DI,CMTB_SIZ       { Read maximum we support             }
@CMT_OK:      MOV    AH,03Fh           { Read from File                      }
              MOV    CX,DI             { Read DI Bytes                       }
              MOV    DX,Seg CMT        { \                                   }
              MOV    DS,DX             {  > DS:DX -> Buffer for read         }
              MOV    DX,Offset CMT     { /                                   }
              INT    21h               { Read file ! BX has handle !         }
              JC     @Close            { Read Failed, Stop reading           }
              CMP    AX,CX             { \ Stop if we didn't read what we    }
              JNE    @Close            { / wanted                            }

              { FUTURE add-ons to SAUCE will be processed here               }

@Close:       MOV    AH,3Eh            { Close Handle                        }
              INT    21h               { And do the close, !BX has handle !! }

@Finish:      MOV    AL,[RetVal]       { Return Value                        }
              POP    DS
END;


BEGIN
  If Sizeof(SAUCE)<>128 THEN RUNERROR(255);
  ClearSAUCE;
END.