/* * dynamite.h * * Interface to Dynamite SWIs * * © 1997 Straylight */ /*----- Licensing note ----------------------------------------------------* * * This file is part of Straylight's Dynamite * * Dynamite is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * Dynamite is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Dynamite. If not, write to the Free Software Foundation, * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __dynamite_h #define __dynamite_h /*----- Notes -------------------------------------------------------------* * * The interfaces to Dynamite have been written in assembler. This has the * benefit of making them very small and minimising procedure call overhead. * It also has the disadvantage of not setting _kernel_last_oserror() * properly. If this is important, you should use _kernel_swi() directly. * * The SWI interface routines are safe to call from SVC mode (e.g. in a * C module). */ #ifdef __cplusplus extern "C" { #endif /*------ Important types --------------------------------------------------*/ /* --- dynamite_anchor --- * * * This is the type of a Dynamite anchor. It should only be used within * these declarations, since it exists to keep the compiler happy and make * the declarations look neat. Your actual anchors will have various types * depending on what you want to store in your Dynamite blocks. * * To avoid casts, we cheat horridly, and in the knowledge that we will only * be dealing with the *address* of an anchor we macro dynamite_anchor to * void, so that its address is a void *. */ #define dynamite_anchor void /* --- dynamite_error --- * * * This is the type of error which Dynamite SWIs return. Depending on * whether you're using RISC_OSLib or not, you may want these to return * os_errors or _kernel_oserrors, or its own special type. All these error * structures have the same format and member names -- it's just a matter of * naming the structure. * * The way we sort all this out is by allowing the client to set up a macro * to tell us what to do. */ #if defined(dynamite_USE_OS_ERROR) #ifndef __os_h #include "os.h" #endif typedef os_error dynamite_error; #elif defined(dynamite_USE_KERNEL_OSERROR) #ifndef __kernel_h #include "kernel.h" #endif typedef _kernel_oserror dynamite_error; #elif !defined(dynamite_error) typedef struct dynamite_error { int errnum; /* Error number */ char errmess[252]; /* Error message text */ } dynamite_error; #endif /* --- dynstr_blockInfo --- * * * This structure contains the information dynamite_blockInfo() returns. */ typedef struct dynstr_blockInfo { int size; /* Block size in bytes */ int blockID; /* Block's ID number */ } dynstr_blockInfo; /* --- dynstr_describe --- * * * This structure contains the information dynamite_describe() returns. */ typedef struct dynstr_describe { int area; /* Dynamic area handle, or -1 */ int size; /* Total size of Dynamite area */ int unused; /* Space unused in Dynamite area */ } dynstr_describe; /*----- Interface functions -----------------------------------------------* * * Most of these return a pointer to a dynamite_error structure. If the * call was successful, this pointer will be null. * * However, where errors are unlikely and a value return is more natural, * this is not the case. * * To check for the existance of Dynamite you should check the return value * of dynamite_describe() for an error. */ /* --- dynamite_alloc --- * * * Arguments: anchor == address of the anchor to use * size == the size to allocate, in bytes * id == the id value to give to the block * * Returns: Pointer to possible error * * Use: Allocates memory from the Dynamite heap. If successful, * *anchor on exit contains the address of the block allocated. * Note that the anchor must *not* be in application space -- * use dynamite_claimAnchor to get one from the RMA if you * don't have other RMA data. */ extern dynamite_error *dynamite_alloc(dynamite_anchor */*anchor*/, int /*size*/, int /*id*/); /* --- dynamite_free --- * * * Arguments: anchor == the address of block's anchor * * Returns: Pointer to possible error * * Use: Frees memory in the Dynamite heap. The memory is marked * as being free, but no blocks are moved -- this makes freeing * lots of blocks very fast. */ extern dynamite_error *dynamite_free(dynamite_anchor */*anchor*/); /* --- dynamite_freeWithID --- * * * Arguments: id == the ID of the blocks to free * * Returns: Pointer to possible error * * Use: Frees all blocks with the given ID value. This allows * applications and modules to free all their allocated blocks * when they close down. */ extern dynamite_error *dynamite_freeWithID(int /*id*/); /* --- dynamite_blockInfo --- * * * Arguments: anchor == address of block's anchor * info == address of structure to fill in * * Returns: Pointer to possible error * * Use: Returns information about a Dynamite block. */ extern dynamite_error *dynamite_blockInfo(dynamite_anchor */*anchor*/, dynstr_blockInfo */*info*/); /* --- dynamite_changeID --- * * * Arguments: anchor == address of block's anchor, or 0 for all blocks * newID == new ID to set for block or blocks * oldID == optional old ID of blocks to change, if anchor == 0 * * Returns: Pointer to possible error * * Use: Changes the ID of a block or blocks. If you specify a single * block by passing a nonzero anchor, you don't have to specify * an oldID value. */ extern dynamite_error *dynamite_changeID(dynamite_anchor */*anchor*/, int /*newID*/,... /* int oldID */); /* --- dynamite_resize --- * * * Arguments: anchor == address of block's anchor * size == new size to make block * * Returns: Pointer to possible error * * Use: Changes a block's size. If you make the block larger, the * data will be unchanged. If you reduce the size, data at the * end will be deleted. The block will usually move as a * result of this operation. */ extern dynamite_error *dynamite_resize(dynamite_anchor */*anchor*/, int /*size*/); /* --- dynamite_midExtend --- * * * Arguments: anchor == address of block's anchor * at == offset within block at which to insert or remove bytes * by == (signed) number of bytes to insert * * Returns: Pointer to possible error * * Use: Inserts or removes bytes in a block at a given offset. * See the manual for a complete description of this call. */ extern dynamite_error *dynamite_midExtend(dynamite_anchor */*anchor*/, int /*at*/, int /*by*/); /* --- dynamite_save --- * * * Arguments: value == value to save on the relocation stack * * Returns: Pointer to possible error * * Use: Saves a value on the Dynamite relocation stack. You can * only save one value at a time through this interface. */ extern dynamite_error *dynamite_save(void */*value*/); /* --- dynamite_load --- * * * Arguments: -- * * Returns: The value from the top of the relocation stack. * * Use: Loads a value from Dynamite's relocation stack and returns * it. You can only restore one value at a time through this * interface. */ extern void *dynamite_load(void); /* --- dynamite_reduce --- * * * Arguments: -- * * Returns: 0 if heap couldn't be compacted, non-0 if it could * * Use: Performs a partial compaction of the Dynamite heap. */ extern int dynamite_reduce(void); /* --- dynamite_compact --- * * * Arguments: -- * * Returns: Pointer to possible error. * * Use: Fully compacts the Dynamite heap. This is equivalent to * * while (dynamite_reduce()) * ; */ extern dynamite_error *dynamite_compact(void); /* --- dynamite_lock --- * * * Arguments: -- * * Returns: Pointer to a possible error * * Use: Locks the heap, stopping any blocks not explicitly resized * from being moved -- this basically just disables compaction. * You *must* lock the heap while it is being used within a * callback or SWI handler. */ extern dynamite_error *dynamite_lock(void); /* --- dynamite_unlock --- * * * Arguments: -- * * Returns: Pointer to a possible error * * Use: Unlocks the heap, allowing compaction to take place again. */ extern dynamite_error *dynamite_unlock(void); /* --- dynamite_claimAnchor --- * * * Arguments: ancptr == where to store the address of the anchor * * Returns: Pointer to a possible error * * Use: Allocates an anchor from the RMA and returns its address. */ extern dynamite_error *dynamite_claimAnchor(dynamite_anchor **/*ancptr*/); /* --- dynamite_releaseAnchor --- * * * Arguments: anchor == address of anchor to release * * Returns: Pointer to possible error * * Use: Frees an anchor allocated by dynamite_claimAnchor. */ extern dynamite_error *dynamite_releaseAnchor(dynamite_anchor */*anchor*/); /* --- dynamite_readSpriteSize --- * * * Arguments: -- * * Returns: Actual size of sprite area in bytes * * Use: Returns the real size of the sprite area -- before RISC OS * 3.5, Dynamite has to fake the return value from * OS_ReadDynamicArea so that you can no longer work out how * much memory is free in the system. This call allows you * to find the real sprite area size. */ extern int dynamite_readSpriteSize(void); /* --- dynamite_describe --- * * * Arguments: desc == address of structure to fill in, or 0 * * Returns: Pointer to possible error * * Use: If desc is nonzero, this call will read some useful * information about the Dynamite heap. If desc is 0, it will * return an error if Dynamite is not loaded -- you can * therefore test for Dynamite's presence. */ extern dynamite_error *dynamite_describe(dynstr_describe */*desc*/); /*----- That's all, folks -------------------------------------------------*/ #ifdef __cplusplus } #endif #endif