home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
339.lha
/
M2Lib
/
LibraryStub.mod
< prev
next >
Wrap
Text File
|
1990-02-08
|
8KB
|
208 lines
MODULE LibraryStub;
(*
This program compiles under TDI version 3.00A.
For other Modula-2 systems, you will have to change the IMPORT statements.
*)
(*
A Modula-2 stub for a loadable Exec library. You must compile&link, then
run the object code against program 'm2lib'. ( Ex: m2lib librarystub )
All this is only necessary because Modula-2 does not support static initialization
of global variables.
*)
FROM AMIGAX IMPORT
ExecBase;
FROM Resident IMPORT
RTFColdStart; (* Our library will be self-initializing. The alternative
is RTFAutoInit, which will be initialized by Exec. *)
FROM Libraries IMPORT
LibraryPtr, Library;
FROM Nodes IMPORT
NTLibrary;
FROM SYSTEM IMPORT
ADR, ADDRESS, BYTE, NULL, SETREG, CODE, REGISTER;
CONST
LibName='stub.library';
LibId='stub.library Ver 1.0 (05 Jan 1990) '; (* Trailing 2 spaces necessary *)
JMP=4EF9H; (* JMP machine instruction *)
JSRA6=4EAEH;(* JSR xxx(a6) machine instruction *)
PUSHREGS=48E7H;
POPREGS=4CDFH;
LVOAddLibrary=0FE74H;
D0thruA5=0FFFCH;
A5thruD0=3FFFH;
D0thruA6=0FFFEH;
A6thruD0=7FFFH;
TYPE
JumpEntry=
RECORD
jeJMP:INTEGER; (* Will move JMP to here *)
jeProc:PROC;
END;
VAR
SegList:ADDRESS;
JumpTable:ARRAY[ 1..4 ] OF JumpEntry;
LibraryBase:Library;
(*$P-*) (* This is NOT an executable procedure *)
(*$S-*) (* DO NOT check stack space EVER ! *)
PROCEDURE RomTag;
(*
This procedure does NOT get executed, it just places
a partially initialized Resident structure in the hunk. We have to
change it so that it will be a valid Resident structure at LoadSeg()
time. Program 'm2lib' will search for the characters 'ZXCV', which
will be considered the first 4 bytes BEFORE the Resident structure
begins.
Here is the format for a Resident structure.
Resident=RECORD
rtMatchWord:CARDINAL; (* MUST equal 4AFCH *)
rtMatchTag:ADDRESS (* MUST point at rtMatchWord.
A valid Resident structure MUST have
rtMatchTag=ADR( rtMatchWord ) *)
rtEndSkip:ADDRESS (* Set to NULL *)
rtFlags:BYTE (* Set to RTFColdStart *)
rtVersion:BYTE (* Set to your library version*)
rtType:BYTE (* Set to NTLibrary *)
rtPri:BYTE (* Set to 0 *)
rtName:ADDRESS (* Set to NULL *)
rtIdString:ADDRESS (* Set to NULL *)
rtInit:ADDRESS (* Point at self-initialization routine *)
END;
*)
BEGIN
CODE( 5A58H , 4356H ); (* 'ZXCV' literal. Helps to find this RomTag in RAM *)
RomTag; (* rtMatchWord and rtMatchTag *)
(* This will produce a JSR RomTag, 6 bytes. *)
(* We will change the first 2 bytes to hex 4AFC, *)
(* which is the MatchWord value Exec searches for *)
(* after it LoadSeg()'s this library. *)
(* We will add 4 to the value in the last 4 bytes, *)
(* so that the relative location is bumped past the *)
(* 'ZXCV' literal, and points at rtMatchWord. *)
CODE( 0 , 0 ); (* rtEndSkip *)
CODE( RTFColdStart*256 + 1 ); (* rtFlags and rtVersion *)
CODE( CARDINAL( NTLibrary )*256 + 0 ); (* rtType and rtPri *)
CODE( 0 , 0 ); (* rtName *)
CODE( 0 ); (* First 2 bytes of rtIdString *)
Initialize; (* Second 2 bytes of rtIdString and rtInit *)
(* This produces a JSR Initialize, 6 bytes. *)
(* We will change the first 2 bytes to 0000. *)
END RomTag;
PROCEDURE STRADR(VAR s:ARRAY OF CHAR):ADDRESS;
BEGIN
RETURN(ADR(s));
END STRADR;
(*
Exec will JSR to this routine AFTER it has found the Resident structure.
Register A0 will contain the SegList pointer, which you must save for later.
Be careful what ROM routines you call here. Stick to stuff that does not
cause any Wait() or Forbid() calls. Basically, just do what I have done and
you should be okay.
*)
PROCEDURE Initialize;
VAR
i:INTEGER;
BEGIN
CODE(PUSHREGS,D0thruA5); (* movem.l d0-d7/a0-a5,-(SP) *)
SegList := REGISTER( 8 ); (* save SegList for later *)
FOR i := 1 TO 4 DO
JumpTable[ i ].jeJMP := JMP; (* Setup LVO jump table *)
END;
JumpTable[ 4 ].jeProc := Open; (* These 4 vectors are REQUIRED and must *)
JumpTable[ 3 ].jeProc := Close; (* be in THIS order. *)
JumpTable[ 2 ].jeProc := Expunge; (* Note the subscripts are DESCENDING. *)
JumpTable[ 1 ].jeProc := Reserved;
WITH LibraryBase DO
libNode.lnType := BYTE( NTLibrary ); (* We are a LIBRARY, of course! *)
libNode.lnName := STRADR( LibName ); (* This is how subsequent OpenLibrary()
calls will find us *)
libNegSize := 24; (* LVO jump table size *)
libPosSize := 0; (* Size of variables AFTER Library *)
libVersion := 1; (* Our current Version *)
libRevision := 0; (* Our current Revision *)
libIdString := STRADR( LibId ); (* A formal ID for the library *)
libOpenCnt := 0; (* We are unused right now *)
END;
CODE(POPREGS,A5thruD0); (* movem.l (SP)+,d0-d7/a0-a5 *)
CODE(PUSHREGS,D0thruA6); (* movem.l d0-d7/a0-a6,-(SP) *)
SETREG(9,ADR(LibraryBase)); (* lea a1,LibraryBase *)
SETREG(14,ExecBase); (* movea.l 4,a6 *)
CODE(JSRA6,LVOAddLibrary); (* jsr _LVOAddLibrary(a6) *)
CODE(POPREGS,A6thruD0); (* movem.l (SP)+,d0-d7/a0-a6 *)
END Initialize;
(*
Exec will JSR to this immediately after you return from your
self-initialization routine.
Do whatever you want in it, but be quick.
*)
PROCEDURE Open;
BEGIN
INC( LibraryBase.libOpenCnt );
END Open;
(*
Exec calls this when someone does a CloseLibrary().
Again, do whatever you want in it.
Exec expects 2 possible return values in D0:
NULL - Exec does nothing.
non-NULL - Exec assumes that D0 contains the SegList it passed you
in the initialization routine. If Exec sees this, it will
UnloadSeg() you! A GURU is assured if you pass a non-valid
SegList pointer in D0!!!
*)
PROCEDURE Close;
BEGIN
DEC( LibraryBase.libOpenCnt );
IF LibraryBase.libOpenCnt # 0 THEN
SETREG( 0 , NULL ); (* Leave us in RAM *)
ELSE
SETREG( 0 , SegList ); (* UnloadSeg() us now *)
END;
END Close;
(*
Exec calls this from the memory allocation routine when Exec needs
to free up some memory.
Exec expects 2 possible return values in D0:
NULL - Exec does nothing. ( You stay loaded in RAM )
non-NULL - Exec assumes that D0 contains the SegList it passed you
in the initialization routine. If Exec sees this, it will
UnloadSeg() you! A GURU is assured if you pass a non-valid
SegList pointer in D0!!!
*)
PROCEDURE Expunge;
BEGIN
SETREG( 0 , SegList ); (* UnloadSeg() us now *)
END Expunge;
PROCEDURE Reserved;
BEGIN
SETREG( 0 , NULL ); (* ALWAYS return NULL *)
END Reserved;
BEGIN
RomTag; (* Place these references so that the linkage optimizer *)
(* leaves the procedure RomTag in the code. *)
END LibraryStub.