************************************************************************
************************************************************************
*  travail.asm                                                         *
*                                                                      *
*     An assembly language look-alike replacement for AVAIL,           *
*  the Commodore SW Toolkit utility for showing current memory         *
*  in-use and available.  Reentrant and "pure."                        *
*                                                                      *
*     Dr. Gerald Hull                                                  *
*     CREATIVE FOCUS                                                   *
*     12 White Street                                                  *
*     Binghamton, New York  13901                                      *
*     (607) 648-4082                                                   *
*                                                                      *
************************************************************************
************************************************************************


************************************************************************
*  Global register usage

REGS     reg      d2-d7/a2-a4,a6

OUT      equr     a2                   output handle
DOS      equr     a3                   Doslib handle
FP       equr     a5                   local frame pointer
LVP      equr     a6                   library vector pointer
SP       equr     a7                   stack pointer


************************************************************************
*  Include files

         nolist
         include  'exec/types.i'
         include  'exec/lists.i'
         include  'exec/memory.i'
         include  'exec/execbase.i'
         list


************************************************************************
*  Library vector offsets

         xref     _LVOOpenLibrary
         xref     _LVOCloseLibrary
         xref     _LVOOutput
         xref     _LVOWrite
         xref     _LVOAvailMem
         xref     _LVOPermit
         xref     _LVOForbid


************************************************************************
*  Equates, macros, etc.

EB       equ      4                    _AbsEcecBase
                              
MIN_LIB  equ      $1f                  minimum library acceptable
LF       equ      $0a                  line feed
BASE     equ      $0a                  ints to ascii in base 10
PREC     equ      $08                  maximum digits per number

LOKE     equ      -62                  local frame memory needed

LOKEVAR  macro                         allocates local frame space
\1       equ      LOKI+\2                 (based on a suggestion by
LOKI     set      \1                       Wesley Howe)
         endm

LOKI     set      0
         LOKEVAR  CMAX,-4              maximum CHIP memory
         LOKEVAR  FMAX,-4                 "    FAST   "
         LOKEVAR  TAVAIL,-4            total available memory
         LOKEVAR  LARGE,-4             largest block available

LOKI     set      LOKE+5
         LOKEVAR  AVAIL,10             ->  end+1 for Avail  numbers
         LOKEVAR  INUSE,10             "     "    "  In-Use    "
         LOKEVAR  MAX,10               "     "    "  Maximum   "
         LOKEVAR  LRGST,10             "     "    "  Largest   "


************************************************************************
*  Program starts here

START    link     FP,#LOKE             allocate local frame
         clr.l    TAVAIL(FP)           initialize 
         clr.l    LARGE(FP)               variables
         movem.l  REGS,-(SP)           save needed registers
         move.l   EB,LVP               _AbsExecBase
         lea      DOSNAME(pc),a1       prepare registers for
         moveq    #MIN_LIB,d0             OpenLibrary call
         jsr      _LVOOpenLibrary(LVP) do it
         tst.l    d0                   did it work?
         bne.s    CONT                 yes!
BAD      moveq    #20,d0               no!
         movem.l  (SP)+,REGS           restore registers
         rts                           go home in tears

CONT     move.l   d0,DOS               save DosLib handle
         movea.l  DOS,LVP                 and
         jsr      _LVOOutput(LVP)      go for Output handle
         move.l   d0,OUT               save it

         movea.l  EB,LVP               _AbsExecBase
         jsr      _LVOForbid(LVP)      lock out all other tasks
         movea.l  LVP,a1
         move.l   MemList(a1),d3       get MemList header
         moveq    #0,d4                for summing CHIP blocks
         moveq    #0,d5                 "     "    FAST   "

SCAN:    move.l   d3,a1                            get node pointer
         move.l   LN_SUCC(a1),d3                   lookahead
         beq.s    DUN                              found last node
         btst     #MEMB_CHIP,MH_ATTRIBUTES+1(a1)   test for CHIP
         beq.s    FST                              skip to FAST if not
         add.l    MH_UPPER(a1),d5                  calculate size
         sub.l    MH_LOWER(a1),d5                     of CHIP block
FST      btst     #MEMB_FAST,MH_ATTRIBUTES+1(a1)   test for FAST too!
         beq.s    SCAN                             nope
         add.l    MH_UPPER(a1),d4                  calculate size
         sub.l    MH_LOWER(a1),d4                     of FAST block
         bra.s    SCAN                             repeat

DUN      move.l   d4,FMAX(FP)          save FAST totals
         move.l   d5,CMAX(FP)            "  CHIP   "
         jsr      _LVOPermit(LVP)

         lea      WRDZ(pc),a0          output column
         bsr      WRITES                  headings

         moveq    #MEMF_CHIP,d6        load registers
         lea      CHIP(pc),a4             for CHIP values
         bsr.s    DOTYPE               calc & output CHIP values

         moveq    #MEMF_FAST,d6        load registers
         move.l   FMAX(FP),d5             for FAST
         lea      FAST(pc),a4             values
         bsr.s    DOTYPE               calc & output FAST values

         lea      TOTL(pc),a4          load
         move.l   TAVAIL(FP),d0           registers
         move.l   CMAX(FP),d6
         add.l    FMAX(FP),d6             for total
         move.l   d6,d5
         sub.l    d0,d5                   values
         move.l   LARGE(FP),d7
         bsr.s    DOSTR                output totals

         move.l   LVP,a1               get DosLib handle
         movea.l  EB,LVP                  and
         jsr      _LVOCloseLibrary(LVP)   close it up
                  
         movem.l  (SP)+,REGS
         unlk     FP                   release local frame
         rts


************************************************************************
*  DOTYPE:  calculates and outputs memory values per type
*
*     in:   d6  = memtype
*           d5  = Maximum
*           a4 -> type string

DOTYPE   move.l   EB,LVP               _AbsExecBase

         move.l   d6,d1                CHIP or FAST
         ori.l    #MEMF_LARGEST,d1     look
         moveq    #0,d0                   for
         jsr      _LVOAvailMem(LVP)       biggest chunk
         cmp.l    LARGE(FP),d0         biggest so far?
         ble.s    NOTL                    nope
         move.l   d0,LARGE(FP)         yup; stuff it
NOTL     move.l   d0,d7                save for DOSTR

         move.l   d6,d1
         moveq    #0,d0                memtype again
         jsr      _LVOAvailMem(LVP)    available aggregate
         add.l    d0,TAVAIL(FP)        add to total

         move.l   d5,d6                Maximum in d6
         sub.l    d0,d5                In-Use in d5
*                                      fall into DOSTR


************************************************************************
*  DOSTR:   outputs type string and values
*
*     in:   a4 -> type string
*           d0  = Available
*           d5  = In-Use
*           d6  = Maximum
*           d7  = Largest

DOSTR    move.b   #' ',d1              fill string
         lea      LOKE(FP),a1             buffer
         moveq    #WRDZLEN-2,d2           with
REP      move.b   d1,(a1)+                blanks
         dbra     d2,REP                  and
         move.b   #LF,(a1)                linefeed

         lea      LOKE(FP),a1          beginning of str buf
         moveq    #TYPELEN-1,d1        insert
TXT      move.b   (a4)+,(a1)+             type
         dbra     d1,TXT                  string

         lea      AVAIL(FP),a0         insert Available
         bsr.s    MAKEDEC                 number

         move.l   d5,d0                insert
         lea      INUSE(FP),a0            In-Use
         bsr.s    MAKEDEC                 number

         move.l   d6,d0                insert
         lea      MAX(FP),a0              Maximum
         bsr.s    MAKEDEC                 number

         move.l   d7,d0                insert
         lea      LRGST(FP),a0            Largest
         bsr.s    MAKEDEC                 number


         lea      LOKE(FP),a0          prepare
WRITES   move.l   OUT,d1                  registers
         move.l   a0,d2                   for
         moveq    #WRDZLEN,d3             Write
         movea.l  DOS,LVP                 call
         jsr      _LVOWrite(LVP)       do it
         rts


************************************************************************
*  MAKEDEC: converts an integer to its decimal representation
*
*     in:   d0  = value to output
*           a0 -> end+1 of string dest

MAKEDEC  moveq    #PREC-1,d2           set max digits
LDIV     moveq    #BASE,d1             base for digits
         move.w   d0,d4                save Z
         clr.w    d0                   d1 from YZ to Y0
         swap     d0                   d1 from Y0 to 0Y
         divu     d1,d0                d0 = 0Y / X = R1Q1
         move.w   d0,d3                save Q1
         move.w   d4,d0                d0 from R1Q1 to R1Z
         divu     d1,d0                d0 = R1Z / X = R0Q0

SMALL    swap     d0                   d0 = QR or Q0R0
         move.l   d0,d1                d1 = QR or Q0R0
         move.w   d3,d0                d0 = Q0 or Q0Q1
         swap     d0                   d0 = 0Q or Q1Q0

         add.b    #'0',d1              make d1.b ascii
         move.b   d1,-(a0)             put it out
         tst.l    d0                   no more digits?
         dbeq     d2,LDIV              or PREC reached?
         rts


************************************************************************
*  Data constants

WRDZ     dc.b     'Type  Available    In-Use'      column
         dc.b     '   Maximum   Largest',LF           headings
WRDZLEN  equ      *-WRDZ

CHIP     dc.b     'chip '                          strings
FAST     dc.b     'fast '                             for
TOTL     dc.b     'total'                             types
TYPELEN  equ      *-TOTL

DOSNAME  dc.b     'dos.library',0                  DosLibrary card

         END

