'===========================================================================
' Subject: EXE FILE SPEC                      Date: 04-05-88 (00:00)       
'  Author: Ronny Ong                          Code: QB, PDS                
'  Origin: Rolf@ice.prima.ruhr.de           Packet: DOS.ABC
'===========================================================================
' FILESPEC.BAS by Ronny Ong, April 5, 1988 - 100% Public Domain
' Example of how to create FILESPEC.EXE:
'   BC FILESPEC/O;
'   LINK /E/NOE FILESPEC,,,QB.LIB;

'$INCLUDE: 'QB.BI'

DIM InRegs AS RegType, OutRegs AS RegType
DIM EnvBlkSeg AS INTEGER, EnvBlkPtr AS INTEGER, Char AS INTEGER
DIM Filespec AS STRING

' The Program Segment Prefix is a 256-byte block which DOS
' creates below all normal transient programs loaded.  The PSP
' contains many important pieces of information about the
' transient program, including the location of its "environment
' block" in memory.

LET InRegs.AX = &H6200 ' Int 21H, Function 62H is Get PSP.
CALL INTERRUPT(&H21, InRegs, OutRegs)
DEF SEG = OutRegs.BX ' Select the segment containing the PSP.

' Get the segment of the environment block, stored at offset 2CH
' in the PSP.

LET EnvBlkSeg = CVI(CHR$(PEEK(&H2C)) + CHR$(PEEK(&H2D)))

' Now select the segment of the environment block itself.
' Environment blocks are always paragraph-aligned.  That is, they
' begin only on even 16-byte address boundaries.  Offset 0,
' therefore, is always the start of the block as long as the
' segment is set properly.

DEF SEG = EnvBlkSeg

' Initialize a pointer to search forward sequentially through
' memory, looking for the double zero bytes which mark the end of
' the environment strings.

LET EnvBlkPtr = 0

DO
  IF PEEK(EnvBlkPtr) = 0 THEN
    IF PEEK(EnvBlkPtr + 1) = 0 THEN
      EXIT DO
    END IF
  END IF
  IF EnvBlkPtr = &H7FFF THEN ' Environment blocks are max of 32K.
    PRINT "End of environment block not found!"
    STOP
  ELSE
    LET EnvBlkPtr = EnvBlkPtr + 1
  END IF
LOOP

' Skip over the double zeroes and the 2-byte word count which
' precedes the filespec.

LET EnvBlkPtr = EnvBlkPtr + 4

LET Filespec = "" ' Initialize filespec.

' Assemble Filespec, ensuring that it does not get too long.

DO
  LET Char = PEEK(EnvBlkPtr)
  IF Char THEN
    LET Filespec = Filespec + CHR$(Char)
    LET EnvBlkPtr = EnvBlkPtr + 1
  END IF
LOOP WHILE Char > 0 AND LEN(Filespec) < 80

' At this point, Filespec could be used in an OPEN statement to
' read/write the EXE file, but for this demonstration, it is
' simply displayed.

PRINT "This program was loaded as "; Filespec

DEF SEG ' Restore BASIC's default data segment.
END
