;-----------------------------------------------------------------
;
; mylib.asm -- example library code
;
; Example of how a user system library is constructed.
;
; © Copyright 1988 Steve Simpson
;
; History:
;    90-05-06  created
;
; assemble:   as mylib.asm
; link:       ln -o mylib.library mylib.o _myfunc2.o c.lib
;
;-----------------------------------------------------------------

 SECTION     section

 NOLIST
 INCLUDE "exec/types.i"
 INCLUDE "exec/nodes.i"
 INCLUDE "exec/lists.i"
 INCLUDE "exec/libraries.i"
 INCLUDE "exec/alerts.i"
 INCLUDE "exec/resident.i"
 INCLUDE "exec/initializers.i"
 INCLUDE "libraries/dos.i"
 INCLUDE "libsupp.i"
 INCLUDE "mylib_def.i"
 LIST


;-------------------------------------------------------------------
; external definitions and references
;-------------------------------------------------------------------
 XDEF     Init
 XDEF     Open
 XDEF     Close
 XDEF     Expunge
 XDEF     Null
 XDEF     myName
 XDEF     MyFunc0
 XDEF     MyFunc1
 XDEF     __MyFunc2

 XREF     _AbsExecBase

 XLIB     OpenLibrary
 XLIB     CloseLibrary
 XLIB     Alert
 XLIB     FreeMem
 XLIB     Remove

;-----------------------------------------------------------------------
;The first executable location.  This returns an error in case someone
;tried to run the library as a program.
;-----------------------------------------------------------------------

LibStart:
         CLEAR    d0
         rts

;-----------------------------------------------------------------------
; various definitions and equates
;-----------------------------------------------------------------------
    ;library priority
MYPRI    EQU      0
    ;a major version number
VERSION  EQU      1
    ;a particular revision.  This should uniqley identify the library
REVISION EQU      1

;----------------------------------------------------------------------
;A romtag structure.
;´exec´ and ´ramlib´ look for this structure during the loading operation
;to discover such as where to start running it, for example.
;In C this would be equivalent to the Resident structure
;---------------------------------------------------------------------
initLibDescrip:           ;structure RT,0
         dc.w     RTC_MATCHWORD        ;UWORD RT_MATCHWORD
         dc.l     initLibDescrip       ;APTR  RT_MATCHTAG
         dc.l     EndLibCode           ;APTR  RT_ENDSKIP
         dc.b     RTF_AUTOINIT         ;UBYTE RT_FLAGS
         dc.b     VERSION              ;UBYTE RT_VERSION
         dc.b     NT_LIBRARY           ;UBYTE RT_TYPE
         dc.b     MYPRI                ;UBYTE RT_PRI
         dc.l     myName               ;APTR  RT_NAME
         dc.l     libIdString          ;APTR  RT_IDSTRING
         dc.l     libInit              ;APRT  RT_INIT
                                       ;LABEL RT_SIZE

    ;my library name
myName         MYLIBNAME

;---------------------------------------------------------------------
;library identifier tag used in supporting the library
;format is 'name version.revision (dd mon yyyy)',<cr>,<lf>,<null>
;---------------------------------------------------------------------
libIdString    dc.b     'mylib 1.0 (06 May 1988)',13,10,0

    ;name of dos library to open
dosName        DOSNAME

    ;we need word alignmemt
         ds.w     0

;---------------------------------------------------------------------
;the romtag specifies "RTF_AUTOINIT".  The RT_INIT structure field
;points to the following table.  If RTF_AUTOINIT was not set, then
;RT_INIT would point to a initialisation routine to run.
;These data are used by the loading program as parameters to
;AddLibrary() library initialisation.
;---------------------------------------------------------------------
libInit:
         dc.l     MyLib_Sizeof         ;data space size
         dc.l     funcTable            ;pointer to function initialisers
         dc.l     dataTable            ;pointer to data initialisers
         dc.l     initRoutine          ;routine to run

;---------------------------------------------------------------------
;table of addresses of mylib functions
;---------------------------------------------------------------------
funcTable:
    ;standard system routines - these MUST always be included
         dc.l     Open
         dc.l     Close
         dc.l     Expunge
         dc.l     ExtFunc
    ;my library´s definitions
         dc.l     MyFunc0
         dc.l     MyFunc1
         dc.l     __MyFunc2
    ;function table end marker
         dc.l     -1

;---------------------------------------------------------------------
;this data table initialises static data structures.  The format is
;specified in exec/InitStruct routine´s manual pages.
;The first argument is the offset from the library base for this
;byte/word/long.  The second argument is the value to put in that cell.
;The table is null terminated.
;---------------------------------------------------------------------
dataTable:
         INITBYTE    LH_TYPE,NT_LIBRARY
         INITLONG    LN_NAME,myName
         INITBYTE    LIB_FLAGS,LIBF_SUMUSED!LIBF_CHANGED
         INITWORD    LIB_VERSION,VERSION
         INITWORD    LIB_REVISION,REVISION
         INITLONG    LIB_IDSTRING,idString
         dc.l        0


;---------------------------------------------------------------------
;This is the initialisation routine ans is called after the library
;has been allocated.
;If it returns non-zero then the library will be linked into the
;library list.
;---------------------------------------------------------------------
initRoutine:       ;( D0: lib. ptr., A0:segment list)
    ;get the library pointer into a A5
         move.l      a5,-(sp)
         move.l      d0,a5

    ;save pointer to exec
         move.l      a6,ml_SysLib(a5)

    ;save a pointer to loaded code segment list
         move.l      a0,ml_SegList(a5)

    ;open the dos.library
         lea         dosName(pc),a1
         CLEAR       d0
         CALLSYS     OpenLibrary

         move.l      d0,ml_DosLib(a5)
         bne.s       1$

    ;can´t open dos
         ALERT       AG_OpenLib!AO_DOSLib

1$:
    ;build the static data that we need
    ;
    ;library specific initialisations go here
    ;

         move.l      a5,d0
         move.l      (sp)+,a5
         rts


;----------------------------------------------------------------------
;System interface commands begin here.  Calling OpenLibrary/CloseLibrary/
;RemoveLibrary, translates into a call to the routines Open/Close/Expunge.
;The library base pointer is in A6.  Task switching has been turned off
;while in these routines (via Forbid/Permit), so don't hang about!
;---------------------------------------------------------------------

;---------------------------------------------------------------------
;Open returns the library pointer in D0 if the open was successful.
;If the open failed then null is returned.
;---------------------------------------------------------------------
Open:     ;(libptr: A6,  version: D0
    ;increment library open counter
         addq.w      #1,LIB_OPENCNT(a6)

    ;prevent delayed expunges
         bclr        #LIBB_DELEXP,ml_Flags(a6)

         move.l      a6,d0
         rts

;---------------------------------------------------------------------
;If the library is no longer open, Close returns the segment list if
;the delayed expunge flag is set.  Otherwise Close return NULL.
;---------------------------------------------------------------------
Close:    ;(libptr: a6)
    ;set the return value
         CLEAR       d0

    ;decrement library open counter
         subq.w      #1,LIB_OPENCNT(a6)

    ;anyone got us open?
         bne.s       1$

    ;any delayed expunge pending?
         btst        #LIBB_DELEXP,ml_Flags(a6)
         beq.s       1$

    ;do the expunge
         bsr         Expunge

1$:
         rts


;---------------------------------------------------------------------
;If the library is no longer open, then Expunge returns the segment
;list for the library code.  Otherwise the delayed expunge flag is
;set and NULL is returned in D0.
;Expunge should never Wait, or take a long time to complete.
;---------------------------------------------------------------------
Expunge:     ;(libptr: A6)
         movem.l     d2/a5/a6,-(sp)
         move.l      a6,a5
         move.l      ml_SysLib(a5),a6

    ;anyone got us open?
         tst.w       LIB_OPENCNT(a5)
         beq         1$

    ;if still open - set delayed expunge flag
         bset        #LIBB_DELEXP,ml_Flags(a5)
         CLEAR       d0
         bra.s       Expunge_End

1$:
    ;we can remove ourselves here
         move.l      ml_SegList(a5),d2

    ;unlink from library list
         move.l      a5,a1
         CALLSYS     Remove

    ;
    ;library specific closings here
    ;

    ;close the dos library
         move.l      ml_DosLib(a5),a1
         CALLSYS     CloseLibrary

    ;free our memory
         CLEAR       d0
         move.l      a5,a1
         move.w      LIB_NEGSIZE(a5),d0

         sub.l       d0,a1
         add.w       LIB_POSSIZE(a5),d0

         CALLSYS     FreeMem

    ;setup our return value - the seglist
         move.l      d2,d0

Expunge_End:
         movem.l     (sp)+,d2/a5/a6
         rts

;---------------------------------------------------------------------
;ExtFunc just returns 0 in D0 register.
;---------------------------------------------------------------------
 ExtFunc:
         CLEAR       d0
         rts


;----------------------------------------------------------------------
;The library specific commands begin here
;In this example library there are 3 library specific routines -
;the third __MyFunc2 is written in C, and is included in the link
;list for the library.
;----------------------------------------------------------------------

;----------------------------------------------------------------------
; MyFunc0 - just returns value 0 in the D0 register
;----------------------------------------------------------------------
 MyFunc0:
         CLEAR       d0
         rts

;----------------------------------------------------------------------
; MyFunc1 - returns contents of register A6 in the D0 register
;----------------------------------------------------------------------
 MyFunc1:
         move.l      a6,d0
         rts


;----------------------------------------------------------------------
;This is the end of our library code
;----------------------------------------------------------------------
 EndLibCode:
         END
