'
' Template.BAS - Basic shell for programs using Brent's QBasic toolkit
'
DEFINT A-Z
DECLARE FUNCTION ColorAttr% (Fore%, Back%)
DECLARE FUNCTION LoadBin$ (BinFileName$)
DECLARE SUB BlockCopy (FromSeg%, FromOfs%, ToSeg%, ToOfs%, Count%)
DECLARE SUB SLBox (Top%, Lft%, Bot%, Rgt%, Attr%, Shad%)
TYPE RegTypeX
  AX    AS INTEGER
  BX    AS INTEGER
  CX    AS INTEGER
  DX    AS INTEGER
  BP    AS INTEGER
  SI    AS INTEGER
  DI    AS INTEGER
  Flags AS INTEGER
  DS    AS INTEGER
  ES    AS INTEGER
END TYPE
DIM SHARED Regs AS RegTypeX
DECLARE SUB Interrupt (IntNum%, Regs AS RegTypeX)

'
' Your Code Here
'

SUB BlockCopy (FromSeg, FromOfs, ToSeg, ToOfs, Count)
  STATIC MemCopy$
  IF NOT LEN(MemCopy$) THEN MemCopy$ = LoadBin("MemCopy.BIN")
  DEF SEG = VARSEG(MemCopy$)
  CALL Absolute(FromSeg, FromOfs, ToSeg, ToOfs, Count, SADD(MemCopy$))
END SUB

FUNCTION ColorAttr (Fore, Back)
  ColorAttr = (Fore AND 16) * 8 + (Back AND 7) * 16 + (Fore AND 15)
END FUNCTION

SUB Interrupt (IntNum, Regs AS RegTypeX) STATIC
  STATIC FileNum, IntOffset, Loaded
  ' use fixed-length string to fix its position in memory
  ' and so we don't mess up string pool before routine
  ' gets its pointers from caller
  DIM IntCode AS STRING * 200
  IF NOT Loaded THEN                        ' loaded will be 0 first time
    IntCode = LoadBin("IntCode.BIN")        ' load routine and determine
    IntOffset = INSTR(IntCode$, CHR$(&HCD) + CHR$(&H21)) + 1 ' int # offset
    Loaded = -1
  END IF
  SELECT CASE IntNum
    CASE &H25, &H26, IS > 255               ' ignore these interrupts
    CASE ELSE
      DEF SEG = VARSEG(IntCode)             ' poke interrupt number into
      POKE VARPTR(IntCode) * 1& + IntOffset - 1, IntNum' code block
      CALL Absolute(Regs, VARPTR(IntCode$)) ' call routine
  END SELECT
END SUB

FUNCTION LoadBin$ (BinFileName$)
  ' Loads a binary file as a string
  STATIC FileNum, Buf$
  FileNum = FREEFILE
  OPEN BinFileName$ FOR BINARY AS FileNum
  IF LOF(FileNum) = 0 THEN
    CLOSE FileNum
    KILL BinFileName$
    CLS : PRINT "Can't find "; BinFileName$; " - aborting."
    END
  END IF
  Buf$ = SPACE$(LOF(FileNum)) ' size buffer
  GET FileNum, , Buf$
  CLOSE #FileNum
  LoadBin$ = Buf$
END FUNCTION

SUB SLBox (Top, Lft, Bot, Rgt, Attr, Shad)
  STATIC SLB$
  IF NOT LEN(SLB$) THEN SLB$ = LoadBin("SLBox.BIN")
  DEF SEG = VARSEG(SLB$)
  CALL Absolute(Top, Lft, Bot, Rgt, Attr, Shad, SADD(SLB$))
END SUB

