mirror of
https://github.com/weiju/amiga-stuff
synced 2026-09-12 19:51:24 +00:00
added the libraries subproject
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
CC = vc +aos68k
|
||||
CFLAGS = -O2 -+ -I$(NDK_INC) -DVBCC -c
|
||||
LDFLAGS = -nostdlib -lamiga
|
||||
LDLIBS =
|
||||
|
||||
OBJS = startup.o libinit.o libfuncs.o
|
||||
|
||||
all: example.library
|
||||
|
||||
clean:
|
||||
rm -f *.o example.library
|
||||
|
||||
example.library: $(OBJS)
|
||||
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS)
|
||||
|
||||
startup.o: startup.c
|
||||
$(CC) $(CFLAGS) $^
|
||||
|
||||
libinit.o: libinit.c
|
||||
$(CC) $(CFLAGS) $^
|
||||
|
||||
libfuncs.o: libfuncs.c
|
||||
$(CC) $(CFLAGS) $^
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef COMPILER_H
|
||||
#define COMPILER_H
|
||||
|
||||
#define SEGLISTPTR APTR
|
||||
|
||||
#define __d0 __reg("d0")
|
||||
#define __d1 __reg("d1")
|
||||
#define __d2 __reg("d2")
|
||||
#define __d3 __reg("d3")
|
||||
#define __d4 __reg("d4")
|
||||
#define __d5 __reg("d5")
|
||||
#define __d6 __reg("d6")
|
||||
#define __d7 __reg("d7")
|
||||
#define __a0 __reg("a0")
|
||||
#define __a1 __reg("a1")
|
||||
#define __a2 __reg("a2")
|
||||
#define __a3 __reg("a3")
|
||||
#define __a4 __reg("a4")
|
||||
#define __a5 __reg("a5")
|
||||
#define __a6 __reg("a6")
|
||||
#define __a7 __reg("a7")
|
||||
|
||||
#endif /* COMPILER_H */
|
||||
@@ -0,0 +1,4 @@
|
||||
#ifndef EXAMPLE_EXAMPLE_H
|
||||
#define EXAMPLE_EXAMPLE_H
|
||||
|
||||
#endif /* EXAMPLE_EXAMPLE_H */
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef EXAMPLE_EXAMPLEBASE_H
|
||||
#define EXAMPLE_EXAMPLEBASE_H
|
||||
|
||||
#ifndef EXEC_LIBRARIES
|
||||
#include <exec/libraries.h>
|
||||
#endif /* EXEC_LIBRARIES_H */
|
||||
|
||||
struct ExampleBase
|
||||
{
|
||||
struct Library exb_LibNode;
|
||||
SEGLISTPTR exb_SegList;
|
||||
struct ExecBase *exb_SysBase;
|
||||
struct IntuitionBase *exb_IntuitionBase;
|
||||
struct GfxBase *exb_GfxBase;
|
||||
};
|
||||
|
||||
#endif /* EXAMPLE_EXAMPLEBASE_H */
|
||||
@@ -0,0 +1,36 @@
|
||||
#include <exec/types.h>
|
||||
#include <exec/memory.h>
|
||||
|
||||
#include <proto/exec.h>
|
||||
#include <proto/intuition.h>
|
||||
#include <intuition/intuition.h>
|
||||
|
||||
#include "compiler.h"
|
||||
|
||||
/* Please note, that &ExampleBase always resides in register __a6 as well,
|
||||
but if we don't need it, we need not reference it here.
|
||||
|
||||
Also note, that registers a0, a1, d0, d1 always are scratch registers,
|
||||
so you usually should only *pass* parameters there, but make a copy
|
||||
directly after entering the function. To avoid problems of kind
|
||||
"implementation defined behaviour", you should make a copy of A6 too,
|
||||
when it is actually used.
|
||||
|
||||
In this example case, scratch register saving would not have been necessary
|
||||
(since there are no other function calls inbetween), but we did it nevertheless.
|
||||
*/
|
||||
|
||||
ULONG EXF_TestRequest(register __d1 UBYTE *title_d1, register __d2 UBYTE *body,
|
||||
register __d3 UBYTE *gadgets)
|
||||
{
|
||||
UBYTE *title = title_d1;
|
||||
struct EasyStruct estr;
|
||||
|
||||
estr.es_StructSize = sizeof(struct EasyStruct);
|
||||
estr.es_Flags = NULL;
|
||||
estr.es_Title = title;
|
||||
estr.es_TextFormat = body;
|
||||
estr.es_GadgetFormat = gadgets;
|
||||
|
||||
return (ULONG) EasyRequestArgs(NULL, &estr, NULL, NULL);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
#include "compiler.h"
|
||||
|
||||
extern ULONG EXF_TestRequest(register __d1 UBYTE *title_d1, register __d2 UBYTE *body,
|
||||
register __d3 UBYTE *gadgets);
|
||||
@@ -0,0 +1,127 @@
|
||||
#include <exec/types.h>
|
||||
#include <exec/memory.h>
|
||||
#include <exec/libraries.h>
|
||||
#include <exec/execbase.h>
|
||||
#include <exec/resident.h>
|
||||
#include <exec/initializers.h>
|
||||
|
||||
#include <proto/exec.h>
|
||||
#include "compiler.h"
|
||||
#include "include/example/examplebase.h"
|
||||
|
||||
ULONG L_OpenLibs(struct ExampleBase *ExampleBase);
|
||||
void L_CloseLibs(void);
|
||||
|
||||
struct ExecBase *SysBase = NULL;
|
||||
struct IntuitionBase *IntuitionBase = NULL;
|
||||
struct GfxBase *GfxBase = NULL;
|
||||
|
||||
#define VERSION 37
|
||||
#define REVISION 32
|
||||
|
||||
#define EXLIBNAME "example"
|
||||
#define EXLIBVER " 37.32 (2.3.99)"
|
||||
|
||||
char ExLibName [] = EXLIBNAME ".library";
|
||||
char ExLibID [] = EXLIBNAME EXLIBVER;
|
||||
char Copyright [] = "(C)opyright 1996-99 by Andreas R. Kleinert. All rights reserved.";
|
||||
char VERSTRING [] = "\0$VER: " EXLIBNAME EXLIBVER;
|
||||
|
||||
/* ----------------------------------------------------------------------------------------
|
||||
! ROMTag and Library initialization structure:
|
||||
!
|
||||
! Below you find the ROMTag, which is the most important "magic" part of a library
|
||||
! (as for any other resident module). You should not need to modify any of the
|
||||
! structures directly, since all the data is referenced from constants from somewhere else.
|
||||
!
|
||||
! You may place the ROMTag directly after the LibStart (-> StartUp.c) function as well.
|
||||
!
|
||||
! Note, that the data initialization structure may be somewhat redundant - it's
|
||||
! for demonstration purposes.
|
||||
!
|
||||
! EndResident can be placed somewhere else - but it must follow the ROMTag and
|
||||
! it must not be placed in a different SECTION.
|
||||
---------------------------------------------------------------------------------------- */
|
||||
|
||||
extern ULONG InitTab[];
|
||||
extern APTR EndResident; /* below */
|
||||
|
||||
struct Resident ROMTag = /* do not change */
|
||||
{
|
||||
RTC_MATCHWORD,
|
||||
&ROMTag,
|
||||
&EndResident,
|
||||
RTF_AUTOINIT,
|
||||
VERSION,
|
||||
NT_LIBRARY,
|
||||
0,
|
||||
&ExLibName[0],
|
||||
&ExLibID[0],
|
||||
&InitTab[0]
|
||||
};
|
||||
|
||||
APTR EndResident;
|
||||
|
||||
struct MyDataInit /* do not change */
|
||||
{
|
||||
UWORD ln_Type_Init; UWORD ln_Type_Offset; UWORD ln_Type_Content;
|
||||
UBYTE ln_Name_Init; UBYTE ln_Name_Offset; ULONG ln_Name_Content;
|
||||
UWORD lib_Flags_Init; UWORD lib_Flags_Offset; UWORD lib_Flags_Content;
|
||||
UWORD lib_Version_Init; UWORD lib_Version_Offset; UWORD lib_Version_Content;
|
||||
UWORD lib_Revision_Init; UWORD lib_Revision_Offset; UWORD lib_Revision_Content;
|
||||
UBYTE lib_IdString_Init; UBYTE lib_IdString_Offset; ULONG lib_IdString_Content;
|
||||
ULONG ENDMARK;
|
||||
} DataTab = {
|
||||
0xe000, 8, NT_LIBRARY,
|
||||
0x0080, 10, (ULONG) &ExLibName[0],
|
||||
0xe000, 14, LIBF_SUMUSED|LIBF_CHANGED,
|
||||
0xd000, 20, VERSION,
|
||||
0xd000, 22, REVISION,
|
||||
0x80, 24, (ULONG) &ExLibID[0],
|
||||
(ULONG) 0
|
||||
};
|
||||
|
||||
/* ----------------------------------------------------------------------------------------
|
||||
! L_OpenLibs:
|
||||
!
|
||||
! Since this one is called by InitLib, libraries not shareable between Processes or
|
||||
! libraries messing with RamLib (deadlock and crash) may not be opened here.
|
||||
!
|
||||
! You may bypass this by calling this function fromout LibOpen, but then you will
|
||||
! have to a) protect it by a semaphore and b) make sure, that libraries are only
|
||||
! opened once (when using global library bases).
|
||||
---------------------------------------------------------------------------------------- */
|
||||
|
||||
ULONG L_OpenLibs(struct ExampleBase *ExampleBase)
|
||||
{
|
||||
SysBase = (*((struct ExecBase **) 4));
|
||||
|
||||
IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 37);
|
||||
if(!IntuitionBase) return FALSE;
|
||||
|
||||
GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 37);
|
||||
if (!GfxBase) return FALSE;
|
||||
|
||||
ExampleBase->exb_IntuitionBase = IntuitionBase;
|
||||
ExampleBase->exb_GfxBase = GfxBase;
|
||||
ExampleBase->exb_SysBase = SysBase;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------------------
|
||||
! L_CloseLibs:
|
||||
!
|
||||
! This one by default is called by ExpungeLib, which only can take place once
|
||||
! and thus per definition is single-threaded.
|
||||
!
|
||||
! When calling this fromout LibClose instead, you will have to protect it by a
|
||||
! semaphore, since you don't know whether a given CloseLibrary(foobase) may cause a Wait().
|
||||
! Additionally, there should be protection, that a library won't be closed twice.
|
||||
---------------------------------------------------------------------------------------- */
|
||||
|
||||
void L_CloseLibs(void)
|
||||
{
|
||||
if (GfxBase) CloseLibrary((struct Library *) GfxBase);
|
||||
if (IntuitionBase) CloseLibrary((struct Library *) IntuitionBase);
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
#include <exec/types.h>
|
||||
#include <exec/memory.h>
|
||||
#include <exec/libraries.h>
|
||||
#include <exec/execbase.h>
|
||||
#include <exec/resident.h>
|
||||
#include <exec/initializers.h>
|
||||
|
||||
#include <proto/exec.h> // all other compilers
|
||||
#include "compiler.h"
|
||||
|
||||
#include "include/example/examplebase.h"
|
||||
#include "libfuncs.h"
|
||||
|
||||
extern ULONG L_OpenLibs(struct ExampleBase *ExampleBase);
|
||||
extern void L_CloseLibs(void);
|
||||
|
||||
struct ExampleBase *InitLib(register __a6 struct ExecBase *sysbase,
|
||||
register __a0 SEGLISTPTR seglist,
|
||||
register __d0 struct ExampleBase *exb);
|
||||
struct ExampleBase *OpenLib(register __a6 struct ExampleBase *ExampleBase);
|
||||
SEGLISTPTR CloseLib(register __a6 struct ExampleBase *ExampleBase);
|
||||
SEGLISTPTR ExpungeLib(register __a6 struct ExampleBase *exb);
|
||||
ULONG ExtFuncLib(void);
|
||||
|
||||
extern APTR FuncTab[];
|
||||
extern DataTab;
|
||||
|
||||
struct InitTable /* do not change */
|
||||
{
|
||||
ULONG LibBaseSize;
|
||||
APTR *FunctionTable;
|
||||
struct MyDataInit *DataTable;
|
||||
APTR InitLibTable;
|
||||
};
|
||||
|
||||
/* ----------------------------------------------------------------------------------------
|
||||
! LibStart:
|
||||
!
|
||||
! If someone tries to start a library as an executable, it must return (LONG) -1
|
||||
! as result. That's what we are doing here.
|
||||
---------------------------------------------------------------------------------------- */
|
||||
|
||||
LONG LibStart(void) { return -1; }
|
||||
|
||||
/* ----------------------------------------------------------------------------------------
|
||||
! Function and Data Tables:
|
||||
!
|
||||
! The function and data tables have been placed here for traditional reasons.
|
||||
! Placing the RomTag structure before (-> LibInit.c) would also be a good idea,
|
||||
! but it depends on whether you would like to keep the "version" stuff separately.
|
||||
---------------------------------------------------------------------------------------- */
|
||||
|
||||
struct InitTable InitTab = {
|
||||
(ULONG) sizeof(struct ExampleBase),
|
||||
(APTR *) &FuncTab[0],
|
||||
(struct MyDataInit *) &DataTab,
|
||||
(APTR) InitLib
|
||||
};
|
||||
|
||||
APTR FuncTab[] = {
|
||||
(APTR) OpenLib,
|
||||
(APTR) CloseLib,
|
||||
(APTR) ExpungeLib,
|
||||
(APTR) ExtFuncLib,
|
||||
|
||||
(APTR) EXF_TestRequest, /* add your own functions here */
|
||||
(APTR) ((LONG)-1)
|
||||
};
|
||||
|
||||
extern struct ExampleBase *ExampleBase;
|
||||
|
||||
/* ----------------------------------------------------------------------------------------
|
||||
! InitLib:
|
||||
!
|
||||
! This one is single-threaded by the Ramlib process. Theoretically you can do, what
|
||||
! you like here, since you have full exclusive control over all the library code and data.
|
||||
! But due to some bugs in Ramlib V37-40, you can easily cause a deadlock when opening
|
||||
! certain libraries here (which open other libraries, that open other libraries, that...)
|
||||
!
|
||||
---------------------------------------------------------------------------------------- */
|
||||
|
||||
struct ExampleBase *InitLib(register __a6 struct ExecBase *sysbase,
|
||||
register __a0 SEGLISTPTR seglist,
|
||||
register __d0 struct ExampleBase *exb)
|
||||
{
|
||||
ExampleBase = exb;
|
||||
ExampleBase->exb_SysBase = sysbase;
|
||||
ExampleBase->exb_SegList = seglist;
|
||||
|
||||
if (L_OpenLibs(ExampleBase)) return ExampleBase;
|
||||
|
||||
L_CloseLibs();
|
||||
|
||||
{
|
||||
ULONG negsize, possize, fullsize;
|
||||
UBYTE *negptr = (UBYTE *) ExampleBase;
|
||||
|
||||
negsize = ExampleBase->exb_LibNode.lib_NegSize;
|
||||
possize = ExampleBase->exb_LibNode.lib_PosSize;
|
||||
fullsize = negsize + possize;
|
||||
negptr -= negsize;
|
||||
|
||||
FreeMem(negptr, fullsize);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------------------
|
||||
! OpenLib:
|
||||
!
|
||||
! This one is enclosed within a Forbid/Permit pair by Exec V37-40. Since a Wait() call
|
||||
! would break this Forbid/Permit(), you are not allowed to start any operations that
|
||||
! may cause a Wait() during their processing. It's possible, that future OS versions
|
||||
! won't turn the multi-tasking off, but instead use semaphore protection for this
|
||||
! function.
|
||||
!
|
||||
! Currently you only can bypass this restriction by supplying your own semaphore
|
||||
! mechanism.
|
||||
---------------------------------------------------------------------------------------- */
|
||||
|
||||
struct ExampleBase *OpenLib(register __a6 struct ExampleBase *ExampleBase)
|
||||
{
|
||||
ExampleBase->exb_LibNode.lib_OpenCnt++;
|
||||
ExampleBase->exb_LibNode.lib_Flags &= ~LIBF_DELEXP;
|
||||
return ExampleBase;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------------------
|
||||
! CloseLib:
|
||||
!
|
||||
! This one is enclosed within a Forbid/Permit pair by Exec V37-40. Since a Wait() call
|
||||
! would break this Forbid/Permit(), you are not allowed to start any operations that
|
||||
! may cause a Wait() during their processing. It's possible, that future OS versions
|
||||
! won't turn the multi-tasking off, but instead use semaphore protection for this
|
||||
! function.
|
||||
!
|
||||
! Currently you only can bypass this restriction by supplying your own semaphore
|
||||
! mechanism.
|
||||
---------------------------------------------------------------------------------------- */
|
||||
|
||||
SEGLISTPTR CloseLib(register __a6 struct ExampleBase *ExampleBase)
|
||||
{
|
||||
ExampleBase->exb_LibNode.lib_OpenCnt--;
|
||||
|
||||
if (!ExampleBase->exb_LibNode.lib_OpenCnt) {
|
||||
if (ExampleBase->exb_LibNode.lib_Flags & LIBF_DELEXP) {
|
||||
return ExpungeLib(ExampleBase);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------------------
|
||||
! ExpungeLib:
|
||||
!
|
||||
! This one is enclosed within a Forbid/Permit pair by Exec V37-40. Since a Wait() call
|
||||
! would break this Forbid/Permit(), you are not allowed to start any operations that
|
||||
! may cause a Wait() during their processing. It's possible, that future OS versions
|
||||
! won't turn the multi-tasking off, but instead use semaphore protection for this
|
||||
! function.
|
||||
!
|
||||
! Currently you only could bypass this restriction by supplying your own semaphore
|
||||
! mechanism - but since expunging can't be done twice, one should avoid it here.
|
||||
---------------------------------------------------------------------------------------- */
|
||||
|
||||
SEGLISTPTR ExpungeLib(register __a6 struct ExampleBase *exb)
|
||||
{
|
||||
struct ExampleBase *ExampleBase = exb;
|
||||
SEGLISTPTR seglist;
|
||||
|
||||
if (!ExampleBase->exb_LibNode.lib_OpenCnt) {
|
||||
ULONG negsize, possize, fullsize;
|
||||
UBYTE *negptr = (UBYTE *) ExampleBase;
|
||||
|
||||
seglist = ExampleBase->exb_SegList;
|
||||
Remove((struct Node *)ExampleBase);
|
||||
L_CloseLibs();
|
||||
|
||||
negsize = ExampleBase->exb_LibNode.lib_NegSize;
|
||||
possize = ExampleBase->exb_LibNode.lib_PosSize;
|
||||
fullsize = negsize + possize;
|
||||
negptr -= negsize;
|
||||
|
||||
FreeMem(negptr, fullsize);
|
||||
return seglist;
|
||||
}
|
||||
|
||||
ExampleBase->exb_LibNode.lib_Flags |= LIBF_DELEXP;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------------------
|
||||
! ExtFunct:
|
||||
!
|
||||
! This one is enclosed within a Forbid/Permit pair by Exec V37-40. Since a Wait() call
|
||||
! would break this Forbid/Permit(), you are not allowed to start any operations that
|
||||
! may cause a Wait() during their processing. It's possible, that future OS versions
|
||||
! won't turn the multi-tasking off, but instead use semaphore protection for this
|
||||
! function.
|
||||
!
|
||||
! Currently you only can bypass this restriction by supplying your own semaphore
|
||||
! mechanism - but since this function currently is unused, you should not touch
|
||||
! it, either.
|
||||
---------------------------------------------------------------------------------------- */
|
||||
|
||||
ULONG ExtFuncLib(void) { return NULL; }
|
||||
|
||||
struct ExampleBase *ExampleBase = NULL;
|
||||
Reference in New Issue
Block a user