
;-----------------------------------------------------------------------
; This file contains library handling routines and entry functions, 
; which push arguments into stack and call the actual C language routines 
; contained in the file hrcode.c. If you want to use this example when 
; creating a new interface library, change the library name strings to 
; match the new library name and reassemble the file:
;
;   'asm  hr_r3d.library.asm'


   SECTION   code

   NOLIST
   INCLUDE "exec/types.i"
   INCLUDE "exec/initializers.i"
   INCLUDE "exec/libraries.i"
   INCLUDE "exec/lists.i"
   INCLUDE "exec/alerts.i"
   INCLUDE "exec/resident.i"
   INCLUDE "libraries/dos.i"

   INCLUDE "asmsupp.i"
   INCLUDE "dspdrvbase.i"

   LIST

   ;------ These don't have to be external, but it helps some
   ;------ debuggers to have them globally visible
   XDEF   Init
   XDEF   Open
   XDEF   Close
   XDEF   Expunge
   XDEF   Null
   XDEF   libraryName

   XREF   _R3DInitDspDrv
   XREF   _R3DFreeDspDrv
   XREF   _R3DSetMode
   XREF   _R3DGetSize
   XREF   _R3DWriteLine
   XREF   _R3DReadLine
   XREF   _R3DClsScr
   XREF   _R3DCustomSave
	    
   XREF   _AbsExecBase
   XREF   _R3DDspDrvBase

   XLIB   OpenLibrary
   XLIB   CloseLibrary
   XLIB   Alert
   XLIB   FreeMem
   XLIB   Remove



   ; The first executable location.  This should return an error
   ; in case someone tried to run you as a program (instead of
   ; loading you as a library).
Start:
   MOVEQ   #-1,d0
   rts

;-----------------------------------------------------------------------
; A romtag structure.  Both "exec" and "ramlib" look for
; this structure to discover magic constants about you
; (such as where to start running you from...).
;-----------------------------------------------------------------------

   ; Most people will not need a priority and should leave it at zero.
   ; the RT_PRI field is used for configuring the roms.  Use "mods" from
   ; wack to look at the other romtags in the system
MYPRI   EQU   0

initDDescrip:
               ;STRUCTURE RT,0
     DC.W    RTC_MATCHWORD      ; UWORD RT_MATCHWORD
     DC.L    initDDescrip       ; APTR  RT_MATCHTAG
     DC.L    EndCode            ; 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              ; BYTE  RT_PRI
     DC.L    libraryName        ; APTR  RT_NAME
     DC.L    idString           ; APTR  RT_IDSTRING
     DC.L    Init               ; APTR  RT_INIT


   ; this is the name that the library will have
libraryName:   dc.b   'hr_r3d.library',0

   ; a major version number.
VERSION:   EQU   34

   ; A particular revision.  This should uniquely identify the bits in the
   ; library.  I use a script that advances the revision number each time
   ; I recompile.  That way there is never a question of which library
   ; that really is.
REVISION:   EQU  1

   ; this is an identifier tag to help in supporting the library
   ; format is 'name version.revision (dd MON yyyy)',<cr>,<lf>,<null>
idString:   dc.b   'hr_r3d.library 1.0 (10 Jan 1992)',13,10,0

dosName:   DOSNAME

   ; force word alignment
   ds.w   0


   ; The romtag specified that we were "RTF_AUTOINIT".  This means
   ; that the RT_INIT structure member points to one of these
   ; tables below.  If the AUTOINIT bit was not set then RT_INIT
   ; would point to a routine to run.

Init:
   DC.L   R3DDspDrvBase_SIZEOF ; size of library base data space
   DC.L   funcTable            ; pointer to function initializers
   DC.L   dataTable            ; pointer to data initializers
   DC.L   initRoutine          ; routine to run


funcTable:

   ;------ standard system routines
   dc.l   Open
   dc.l   Close
   dc.l   Expunge
   dc.l   Null

   ;------ my library functions
   dc.l   R3DInitDspDrv
   dc.l   R3DFreeDspDrv
   dc.l   R3DSetMode
   dc.l   R3DGetSize
   dc.l   R3DWriteLine
   dc.l   R3DReadLine
   dc.l   R3DClsScr
   dc.l   R3DCustomSave

   ;------ function table end marker
   dc.l   -1


   ; The data table initializes static data structures.
   ; The format is specified in exec/InitStruct routine's
   ; manual pages.  The INITBYTE/INITWORD/INITLONG routines
   ; are in the file "exec/initializers.i".  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	LN_TYPE,NT_LIBRARY
	INITLONG	LN_NAME,libraryName
	INITBYTE	LIB_FLAGS,LIBF_SUMUSED!LIBF_CHANGED
	INITWORD	LIB_VERSION,VERSION
	INITWORD	LIB_REVISION,REVISION
	INITLONG	LIB_IDSTRING,idString
	DC.L   0


   ; This routine gets called after the library has been allocated.
   ; The library pointer is in D0.  The segment list is in A0.
   ; If it returns non-zero then the library will be linked into
   ; the library list.
initRoutine:

   ;------ get the library pointer into a convenient A register
   move.l   a5,-(sp)
   move.l   d0,a5
   move.l   d0,_R3DDspDrvBase

   ;------ save a pointer to exec
   move.l   a6,sb_SysLib(a5)

   ;------ save a pointer to our loaded code
   move.l   a0,sb_SegList(a5)

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

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

   ;------ can't open the dos!  what gives
   ALERT   AG_OpenLib!AO_DOSLib

1$:
   ;------ now build the static data that we need
   ;
   ; put your initialization here...
   ;

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

;----------------------------------------------------------------------
;
; here begins the system interface commands.  When the user calls
; OpenLibrary/CloseLibrary/RemoveLibrary, this eventually gets translated
; into a call to the following routines (Open/Close/Expunge).  Exec
; has already put our library pointer in A6 for us.  Exec has turned
; off task switching while in these routines (via Forbid/Permit), so
; we should not take too long in them.
;
;----------------------------------------------------------------------

   ; Open returns the library pointer in d0 if the open
   ; was successful.  If the open failed then null is returned.
   ; It might fail if we allocated memory on each open, or
   ; if only open application could have the library open
   ; at a time...

Open:      ; ( libptr:a6, version:d0 )

   ;------ mark us as having another opener
   addq.w   #1,LIB_OPENCNT(a6)

   ;------ prevent delayed expunges
   bclr   #LIBB_DELEXP,sb_Flags(a6)

   move.l   a6,d0
   rts

   ; There are two different things that might be returned from
   ; the Close routine.  If the library is no longer open and
   ; there is a delayed expunge then Close should return the
   ; segment list (as given to Init).  Otherwise close should
   ; return NULL.

Close:      ; ( libptr:a6 )
    
   ;------ set the return value
   CLEAR   d0

   ;------ mark us as having one fewer openers
   subq.w   #1,LIB_OPENCNT(a6)

   ;------ see if there is anyone left with us open
   bne.s   1$

   ;------ see if we have a delayed expunge pending
   btst   #LIBB_DELEXP,sb_Flags(a6)
   beq.s   1$

   ;------ do the expunge
   bsr   Expunge
1$:
   rts


   ; There are two different things that might be returned from
   ; the Expunge routine.  If the library is no longer open
   ; then Expunge should return the segment list (as given to
   ; Init).  Otherwise Expunge should set the delayed expunge
   ; flag and return NULL.
   ;
   ; One other important note: because Expunge is called from
   ; the memory allocator, it may NEVER Wait() or otherwise
   ; take long time to complete.

Expunge:   ; ( libptr: a6 )

   movem.l   d2/a5/a6,-(sp)
   move.l   a6,a5
   move.l   sb_SysLib(a5),a6
   
   ;------ see if anyone has us open
   tst.w   LIB_OPENCNT(a5)
   beq   1$

   ;------ it is still open.  set the delayed expunge flag
   bset   #LIBB_DELEXP,sb_Flags(a5)
   CLEAR   d0
   bra.s   Expunge_End

1$:
   ;------ go ahead and get rid of us.  Store our seglist in d2
   move.l   sb_SegList(a5),d2

   ;------ unlink from library list
   move.l   a5,a1
   CALLSYS   Remove
   
   ;
   ; device specific closings here...
   ;

   ;------ close the dos library
   move.l   sb_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

   ;------ set up our return value
   move.l   d2,d0

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


Null:
   CLEAR   d0
   rts

;----------------------------------------------------------------------
; Here begins the library functions.
;
; These simple assembler functions are only entries to actual functions
; written in C and contained in the C module hrcode.c. The purpose of these
; entry functions is to push the arguments into stack and then call C code.
;
;----------------------------------------------------------------------


*----- R3DInitDspDrv( )
R3DInitDspDrv:
    jsr    _R3DInitDspDrv
    rts

*----- R3DFreeDspDrv(a0)
R3DFreeDspDrv:
    move.l a0,-(sp)
    jsr    _R3DFreeDspDrv
    addq   #4,sp
    rts

*----- R3DSetMode(a0)
R3DSetMode:
    move.l a0,-(sp)
    jsr    _R3DSetMode
    addq   #4,sp
    rts

*----- R3DGetSize(a0,a1,d0)
R3DGetSize:
    move.l d0,-(sp)
    move.l a1,-(sp)
    move.l a0,-(sp)
    jsr    _R3DGetSize
    addq   #8,sp
    addq   #4,sp
    rts

*----- R3DWriteLine(a0,a1,a2,d0,d1)
R3DWriteLine:
    move.l d1,-(sp)
    move.l d0,-(sp)
    move.l a2,-(sp)
    move.l a1,-(sp)
    move.l a0,-(sp)
    jsr    _R3DWriteLine
    addq   #8,sp
    addq   #8,sp
    addq   #4,sp
    rts

*----- R3DReadLine(a0,a1,a2,d0,d1)
R3DReadLine:
    move.l d1,-(sp)
    move.l d0,-(sp)
    move.l a2,-(sp)
    move.l a1,-(sp)
    move.l a0,-(sp)
    jsr    _R3DReadLine
    addq   #8,sp
    addq   #8,sp
    addq   #4,sp
    rts

*----- R3DClsScr(a0,a1)
R3DClsScr:
    move.l a1,-(sp)
    move.l a0,-(sp)
    jsr    _R3DClsScr
    addq   #8,sp
    rts

*----- R3DCustomSave(a0,a1,a2,d0,d1,d2)
R3DCustomSave:
    move.l d2,-(sp)
    move.l d1,-(sp)
    move.l d0,-(sp)
    move.l a2,-(sp)
    move.l a1,-(sp)
    move.l a0,-(sp)
    jsr    _R3DCustomSave
    addq   #8,sp
    addq   #8,sp
    addq   #8,sp
    rts


EndCode:

   END
