https://wiki.amigaos.net/w/api.php?action=feedcontributions&user=Costel+Mincea&feedformat=atomAmigaOS Documentation Wiki - User contributions [en]2024-03-29T12:09:42ZUser contributionsMediaWiki 1.34.0https://wiki.amigaos.net/w/index.php?title=Programming_AmigaOS_4:_Transparent_Windows&diff=12332Programming AmigaOS 4: Transparent Windows2022-11-07T07:16:37Z<p>Costel Mincea: Translated source comments to English and fixed a couple of typos on my way (there may be more ;) )</p>
<hr />
<div>''This article was adapted from Amiga Future magazine's series on developing for AmigaOS....''<br />
<br />
With AmigaOS 4.1 a new technology was introduced, which lets you display (partially) transparent windows thus showing the content behind the window. Additionally, with this technology you can create rounded window corners. We will take a closer look today at the programming characteristics behind these options.<br />
<br />
In the first block we will deal with transparent windows, while in the second block we will see how you can create transparent areas within a window or how you can set the window based on the outline of an image.<br />
<br />
= Compositing =<br />
<br />
In order to be able to use compositing you need AmigaOS in the version 4.1 (so, SysBase->lib_Version >= 53). Moreover, your screen must have a colour depth of at least 16 Bit (so Highcolour or Truecolour). The user can also set in the GUI-Prefs whether transparency is allowed. 'Visual effects for layer' must be activated for it. You can certainly check that in the following way:<br />
<br />
<syntaxhighlight><br />
if(( dri = IIntuition->GetScreenDrawInfo(window->WScreen) ))<br />
{<br />
IIntuition->GetGUIAttrs(NULL,dri,GUIA_SpecialEffects,&specialfx,TAG_END);<br />
}<br />
</syntaxhighlight><br />
<br />
If the variable "specialfx" is set as TRUE, the user has activated the setting and the particular screen has at least 16 Bit colour depth.<br />
<br />
= Transparent windows =<br />
<br />
To make a window transparent, three new tags are sufficient. They must be passed as/when the window is opened to IIntuition->OpenWindowTags() or rather, IIntuition->NewObject(IWindow->WINDOW_GetClass(),...).<br />
<br />
With the tag "WA_Opaqueness" you can determine how opaque or transparent the complete window should be. The possible values margin begins with 0 for completely transparent, which means, you cannot see anything from the contents or the window itself and the underlying screen content is fully displayed. There are also value margins up to 255 for completely opaque display, which corresponds to the standard display. In that case, the complete window content is shown and what is behind is not visible. A mean value of 128 would display one half of the window content and one half of the screen behind it. However, if you want to use this setting, you must additionally set the tag "WA_OverrideOpaqueness" to TRUE. Only then will the global settings from the GUI-Prefs program be ignored and a divergent transparency will be possible for the selected window.<br />
<br />
With the third tag "WA_FadeTime" you can set up a delay time, which will be active when you open/close the window as well as when you change the transparent value (WA_Opaqueness). The value is a time span in microseconds (1,000,000 microseconds = 1 second). The standard is 0, which means, no delay. If you enter 1,000,000, it will take one second until the window is completely displayed when opened. Whatever, it's a nice gimmick.<br />
<br />
You can also change all three tags retrospectively:<br />
<br />
<syntaxhighlight><br />
Intuition->SetWindowAttrs(window,WA_Opaqueness,opaqueness,TAG_END);<br />
</syntaxhighlight><br />
<br />
On the other hand, you can request the current tag values with<br />
<br />
<syntaxhighlight><br />
IIntuition->GetAttr(WA_Opaqueness,winobj,&opaqueness)<br />
</syntaxhighlight><br />
<br />
The so far covered details are included in the sample program "OpaquenessExample.c", where you can try them out.<br />
<br />
<syntaxhighlight><br />
/* Michael Christoph<br />
* OpaquenessExample.c<br />
*<br />
* gcc OpaquenessExample.c -o OpaquenessExample -l auto<br />
*/<br />
<br />
/******************************* INCLUDES *************************************/<br />
<br />
#include <intuition/intuition.h><br />
#include <intuition/gui.h><br />
#include <intuition/icclass.h><br />
#include <libraries/gadtools.h><br />
#include <reaction/reaction.h><br />
#include <reaction/reaction_macros.h><br />
#include <classes/window.h><br />
#include <gadgets/slider.h><br />
#include <images/label.h><br />
<br />
#include <proto/exec.h><br />
#include <proto/dos.h><br />
#include <proto/intuition.h><br />
#include <proto/window.h><br />
#include <proto/layout.h><br />
#include <proto/slider.h><br />
#include <proto/label.h><br />
<br />
/******************************************************************************/<br />
<br />
static const char *version USED = "\0$VER: OpaquenessExample 1.0 (06.01.2009) - (c) Jan.2009 by Meicky-Soft\n";<br />
<br />
/******************************************************************************/<br />
<br />
enum<br />
{<br />
OBJ_SLIDER_1,<br />
OBJ_SLIDER_2,<br />
OBJ_MAX<br />
};<br />
<br />
#define OBJ(x) objects[x]<br />
#define GAD(x) (struct Gadget *)objects[x]<br />
<br />
/******************************************************************************/<br />
<br />
int main()<br />
{<br />
struct RDArgs *rda;<br />
struct Window *window;<br />
struct DrawInfo *dri;<br />
Object *win;<br />
Object *objects[OBJ_MAX];<br />
<br />
BOOL canfade = FALSE;<br />
uint32 specialfx = 0;<br />
uint32 fade_time = 50;<br />
uint32 opaqueness = 255;<br />
<br />
uint32 sigmask = 0;<br />
uint32 result = 0;<br />
uint16 code = 0;<br />
BOOL done = FALSE;<br />
<br />
enum { ARG_pubscreen, ARG_MAX };<br />
ULONG args[ARG_MAX]={ 0 };<br />
<br />
/* AmigaOS 4.1 is required */<br />
if(SysBase->lib_Version >= 53)<br />
{<br />
/* Process program arguments */<br />
if((rda = IDOS->ReadArgs("PUBSCREEN/K",(LONG*)args,NULL)))<br />
{<br />
win = WindowObject,<br />
WA_Title, "Transparent window",<br />
WA_DragBar, TRUE,<br />
WA_CloseGadget, TRUE,<br />
WA_SizeGadget, TRUE,<br />
WA_DepthGadget, TRUE,<br />
WA_Activate, TRUE,<br />
WA_Width, 400,<br />
WA_OverrideOpaqueness, TRUE, /* Ignore global settings */<br />
WA_Opaqueness, 255, /* Open opaque */<br />
WA_FadeTime, 500000, /* Delay in microseconds */<br />
(args[ARG_pubscreen] ? WA_PubScreenName : TAG_IGNORE), args[ARG_pubscreen],<br />
WINDOW_Position, WPOS_CENTERSCREEN,<br />
WINDOW_Layout, VLayoutObject,<br />
LAYOUT_SpaceOuter, TRUE,<br />
<br />
LAYOUT_AddChild, OBJ(OBJ_SLIDER_1) = SliderObject,<br />
GA_ID, OBJ_SLIDER_1,<br />
GA_RelVerify, TRUE,<br />
SLIDER_Min, 10,<br />
SLIDER_Max, 100,<br />
SLIDER_Level, 50,<br />
SLIDER_KnobDelta, 10,<br />
SLIDER_Orientation, SLIDER_HORIZONTAL,<br />
SLIDER_Ticks, 11,<br />
SLIDER_ShortTicks, TRUE,<br />
SLIDER_LevelFormat, "%3ld",<br />
SLIDER_LevelPlace, PLACETEXT_IN,<br />
SLIDER_LevelMaxLen, 3,<br />
End,<br />
Label(" Fade Time (1/100s) "),<br />
CHILD_WeightedHeight, 0,<br />
<br />
LAYOUT_AddChild, OBJ(OBJ_SLIDER_2) = SliderObject,<br />
GA_ID, OBJ_SLIDER_2,<br />
GA_RelVerify, TRUE,<br />
SLIDER_Min, 20,<br />
SLIDER_Max, 255,<br />
SLIDER_Level, 255,<br />
SLIDER_KnobDelta, 10,<br />
SLIDER_Orientation, SLIDER_HORIZONTAL,<br />
SLIDER_Ticks, 21,<br />
SLIDER_ShortTicks, TRUE,<br />
SLIDER_LevelFormat, "%3ld",<br />
SLIDER_LevelPlace, PLACETEXT_IN,<br />
SLIDER_LevelMaxLen, 3,<br />
TAG_END),<br />
Label(" Opaqueness "),<br />
CHILD_WeightedHeight, 0,<br />
<br />
TAG_END),<br />
TAG_END);<br />
<br />
<br />
<br />
if((window = RA_OpenWindow(win)))<br />
{<br />
IIntuition->GetAttr(WINDOW_SigMask, win, &sigmask);<br />
<br />
/* Is compositing active and available? */<br />
if((dri = IIntuition->GetScreenDrawInfo(window->WScreen)))<br />
{<br />
IIntuition->GetGUIAttrs(NULL,dri,GUIA_SpecialEffects,&specialfx,TAG_END);<br />
canfade = (BOOL)specialfx;<br />
<br />
if(!canfade)<br />
{<br />
/* deactivated: also disable gadgets, because they don't have any impact */<br />
IIntuition->SetGadgetAttrs(GAD(OBJ_SLIDER_1),window,NULL,<br />
GA_Disabled,TRUE,TAG_END);<br />
IIntuition->SetGadgetAttrs(GAD(OBJ_SLIDER_2),window,NULL,<br />
GA_Disabled,TRUE,TAG_END);<br />
}<br />
}<br />
<br />
while(!done)<br />
{<br />
if(IExec->Wait(sigmask | SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)<br />
{<br />
done = TRUE;<br />
}<br />
<br />
while((result = RA_HandleInput(win,&code)))<br />
{<br />
switch(result & WMHI_CLASSMASK)<br />
{<br />
case WMHI_CLOSEWINDOW:<br />
done = TRUE;<br />
break;<br />
<br />
case WMHI_GADGETUP:<br />
switch(result & WMHI_GADGETMASK)<br />
{<br />
case OBJ_SLIDER_1:<br />
if (canfade)<br />
{<br />
IIntuition->GetAttrs(GAD(OBJ_SLIDER_1), SLIDER_Level, &fade_time, TAG_END);<br />
IIntuition->SetWindowAttrs(window, WA_FadeTime, fade_time * 10000, TAG_END);<br />
}<br />
break;<br />
<br />
case OBJ_SLIDER_2:<br />
if (canfade)<br />
{<br />
IIntuition->GetAttrs(GAD(OBJ_SLIDER_2), SLIDER_Level, &opaqueness, TAG_END);<br />
IIntuition->SetWindowAttrs(window, WA_Opaqueness, opaqueness, TAG_END);<br />
<br />
/* SetWindowAttr() returns immediately, hence we wait briefly */<br />
/* until the windows has finished fading, before starting the next change */<br />
IDOS->Delay(fade_time/2);<br />
}<br />
break;<br />
}<br />
break;<br />
}<br />
}<br />
}<br />
}<br />
<br />
IIntuition->DisposeObject(win);<br />
<br />
IDOS->FreeArgs(rda);<br />
}<br />
else IDOS->PrintFault(IDOS->IoErr(),"OpaquenessExample");<br />
}<br />
else IDOS->Printf("program requires AmigaOS 4.1\n");<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
[[File:AF108_opaqueness_grab.png|frame|center]]<br />
<br />
= Non-square windows =<br />
<br />
The so far mentioned information always relates to complete square windows. In this second block we will see how you can 'remove' parts of a window or see through a hole in the window. These options are more complex, but AmigaOS supports programmers with its new functions. Since the Autodocs in this field are still quite incomplete we tried to compile all the important information.<br />
<br />
= Loading graphics =<br />
<br />
First of all, we need a graphic that will set the form of the window. The intuition.library supports us here with matching new functions that we haven't had a chance to present you yet. The image data is loaded in the memory with IIntuition->ObtainBitMapSource().The tag BMS_DoShade is important here in order to create/provide the alpha-channel data as well. At the moment this is only possible with PNG graphics. Other graphic formats do not provide this information.<br />
<br />
IIntuition->ObtainBitMapInstance() declares a pointer to the image management. To get the actual image data you must request the desired values with IIntuition->BitMapInstanceControl(). Some important tags are here BMICTRL_GetWidth and BMICTRL_GetHeight for the size as well as BMICTRL_GetBitMap and BMICTRL_GetAlphaMap for the image data, i.e., the alpha mask. There is IIntuition->ReleaseBitMapInstance() and Iintuition->ReleaseBitMapSource() for release. The functions that you will need are compiled in the following list. The image data can be drawn with the usual functions such as IGraphics->BltBitMapTags().<br />
<br />
<syntaxhighlight><br />
struct Screen *scr;<br />
APTR source;<br />
APTR instance;<br />
struct BitMap *bitmap;<br />
struct BitMap *alpha;<br />
ULONG width;<br />
ULONG height;<br />
<br />
/* load the graphic in the memory, if necessary (internal via Datatype) */<br />
if((source = IIntuition->ObtainBitMapSource((STRPTR)args[ARG_filename],BMS_DoShade,TRUE,TAG_END)))<br />
{<br />
/* request a bitmap instance for the screen */<br />
if((instance = IIntuition->ObtainBitMapInstance(source,scr,TAG_END)))<br />
{<br />
/* Request image information and bitmap*/<br />
IIntuition->BitMapInstanceControl(instance,<br />
BMICTRL_GetBitMap, &bitmap,<br />
BMICTRL_GetAlphaMap, &alpha,<br />
BMICTRL_GetWidth, &width,<br />
BMICTRL_GetHeight, &height,<br />
TAG_DONE );<br />
<br />
if(bitmap && alpha)<br />
{<br />
/* Image data can be processed /blitted now */<br />
}<br />
else IDOS->Printf("cannot get (alpha) bitmaps\n");<br />
<br />
/* r BitMap Instance */<br />
IIntuition->ReleaseBitMapInstance(instance);<br />
}<br />
else IDOS->Printf("cannot get instance of picture\n");<br />
<br />
/* release graphic file */<br />
IIntuition->ReleaseBitMapSource(source);<br />
}<br />
else IDOS->Printf("loading picture file failed\n");<br />
</syntaxhighlight><br />
<br />
= Define window areas =<br />
<br />
The existing clipping system has been expanded in order to be able to set the areas in a window that display contents, that is, that let the background show through. With ILayers->InstallClipRegion() you could set even earlier rectangular areas in a window, in which a blit operation can draw data. This way, you can, for example, protect separate areas of a window too, if graphic data is larger than the window. However, in order to apply the ClipRect structure to an alpha channel you must use a private function of the layers. library:<br />
<br />
<syntaxhighlight><br />
ILayers->AllocClipRect()<br />
</syntaxhighlight><br />
<br />
This is provided exclusively for this task. The counterpart to it is ILayers->FreeClipRect(), that releases again the structure. The structure is already pre-initialised, so that only a few fields must be adjusted to your needs. On the one hand, you must store the graphic size in "bounds" and enter it in "BitMap". The required memory area for it can be created with IGraphics->AllocBitMap(). Then you must also blit the alpha-channel bitmap with IGraphics->BltBitMapTags(). The only thing you need to keep in mind in this whole procedure is that you automatically de-allocate the entered BitMap when you allocate the ClipRect structure! In case you do not want to do it, you must first set the field on NULL and de-allocate the BitMap with IGraphics->FreeBitMap(). These are the matching code rows for this part of the workshop:<br />
<br />
<syntaxhighlight><br />
struct ClipRect *ac;<br />
<br />
/* allocate and initialise ClipRect structure */<br />
if((ac = ILayers->AllocClipRect(&(scr->LayerInfo))))<br />
{<br />
struct TagItem bmtags[3] = { { BMATags_RGBFormat, RGBFB_ALPHA8 },<br />
{ BMATags_Friend, (ULONG)scr->RastPort.BitMap },<br />
{ TAG_END, 0 } };<br />
<br />
/* allocate Alpha-ClipRect and request memory for Bitmap */<br />
ac->bounds.MinX = 0;<br />
ac->bounds.MinY = 0;<br />
ac->bounds.MaxX = width-1,<br />
ac->bounds.MaxY = height-1;<br />
ac->Next = NULL;<br />
if((ac->BitMap = IGraphics->AllocBitMap(width,height,8,BMF_DISPLAYABLE|BMF_CLEAR|BMF_CHECKVALUE,(struct BitMap *)bmtags)))<br />
{<br />
/* Fill Alpha-ClipRect with Alpha-Bitmap */<br />
IGraphics->BltBitMapTags(BLITA_Source, alpha,<br />
BLITA_SrcType, BLITT_CHUNKY,<br />
BLITA_SrcBytesPerRow, width,<br />
BLITA_Dest, ac->BitMap,<br />
BLITA_Width, width,<br />
BLITA_Height, height,<br />
TAG_DONE );<br />
<br />
/* ... */<br />
}<br />
else IDOS->Printf("cannot allocate alpha mask\n");<br />
<br />
/* ClipRect deallocate; it also deallocates ac->BitMap! */<br />
ILayers->FreeClipRect(&(scr->LayerInfo),ac);<br />
}<br />
else IDOS->Printf("cannot allocate cliprect\n");<br />
</syntaxhighlight><br />
<br />
= Window show yourself =<br />
<br />
What is left is opening the window and blitting the graphic bitmap with IGraphics->BltBitMapRastPort(). You will need for it the following code rows:<br />
<br />
<syntaxhighlight><br />
struct Window *win;<br />
<br />
/* Open window with the Alpha mask */<br />
if((win = IIntuition->OpenWindowTags(NULL,<br />
WA_Width, width,<br />
WA_Height, height,<br />
WA_Borderless, TRUE,<br />
WA_AlphaClips, ac,<br />
...<br />
TAG_DONE)))<br />
{<br />
/* blit the graphic file into the window */<br />
IGraphics->BltBitMapRastPort(bitmap, 0, 0, win->RPort, 0, 0, width, height, MINTERM_ABC|MINTERM_ABNC);<br />
}<br />
</syntaxhighlight><br />
<br />
When you open the window, you must also enter the tag WA_AlphaClips. The window will be opened without a frame and without system symbols. They are not shown, but as soon as you activate the window, the frame elements are drawn with Intuition, at least as far as the alpha mask allows it. You can also target the alpha mask display. Just do not copy any image data into the Rastport after you have opened the window. The alpha mask does not only set the opaque and transparent points, but it can also be created gradually. Thus, even image parts can appear as half-transparent and let the background shine through. The 'partly transparent ball' graphic shows the result.<br />
<br />
You should also keep in mind that the window may not be of the GimmeZeroZero type. In this case there are already internal clipping masks, which cannot be combined with the alpha-clipping.<br />
<br />
The program "BorderlessWindow" serves as a complete example for this topic showing all the mentioned functions in a practical interplay. A matching graphic is also included. Have fun experimenting with the source-code and looking for new possibilities!<br />
<br />
<syntaxhighlight><br />
/* Michael Christoph<br />
* BorderlessWindow.c<br />
*<br />
* gcc BorderlessWindow.c -o BorderlessWindow -l auto<br />
*/<br />
<br />
/******************************* INCLUDES *************************************/<br />
<br />
#include <exec/libraries.h><br />
#include <graphics/blitattr.h><br />
#include <graphics/composite.h><br />
#include <intuition/intuition.h><br />
#include <intuition/bitmapshare.h><br />
#include <intuition/gui.h><br />
<br />
#include <proto/exec.h><br />
#include <proto/dos.h><br />
#include <proto/graphics.h><br />
#include <proto/intuition.h><br />
#include <proto/layers.h><br />
<br />
/******************************************************************************/<br />
<br />
static const char *version USED = "\0$VER: BorderlessWindow 1.1 (22.07.2013) - (c) Jan.2009 by Meicky-Soft\n";<br />
<br />
/******************************************************************************/<br />
<br />
int main(int argc, char *argv[])<br />
{<br />
int res = RETURN_FAIL;<br />
<br />
struct RDArgs *rda;<br />
struct Screen *scr;<br />
struct Window *win;<br />
struct ClipRect *ac;<br />
struct DrawInfo *dri;<br />
struct BitMap *bitmap;<br />
struct BitMap *alpha;<br />
APTR source;<br />
APTR instance;<br />
ULONG width;<br />
ULONG height;<br />
ULONG specialfx;<br />
<br />
enum { ARG_filename, ARG_pubscreen, ARG_MAX };<br />
ULONG args[ARG_MAX]={ (ULONG)"testpic.png",0 };<br />
<br />
/* AmigaOS 4.1 is required */<br />
if(SysBase->lib_Version >= 53)<br />
{<br />
/* Process program arguments */<br />
if((rda = IDOS->ReadArgs("FILENAME,PUBSCREEN/K",(LONG*)args,NULL)))<br />
{<br />
/* Lock screen for display */<br />
if((scr = IIntuition->LockPubScreen((STRPTR)args[ARG_pubscreen])))<br />
{<br />
/* Ensure the screen supports compositing */<br />
if(( dri = IIntuition->GetScreenDrawInfo(scr)))<br />
{<br />
IIntuition->GetGUIAttrs(NULL,dri,GUIA_SpecialEffects,&specialfx,TAG_END);<br />
if(!specialfx) IDOS->Printf("WARNING: screen does not support alpha composing\n");<br />
<br />
IIntuition->FreeScreenDrawInfo(scr,dri);<br />
}<br />
<br />
/* If needed, load the image into memory (internal via Datatype) */<br />
if((source = IIntuition->ObtainBitMapSource((STRPTR)args[ARG_filename],<br />
BMS_DoShade, TRUE,<br />
BMS_DoMask, TRUE,<br />
TAG_END)))<br />
{<br />
/* Request a BitMap for our screen */<br />
if((instance = IIntuition->ObtainBitMapInstance(source,scr,TAG_END)))<br />
{<br />
/* Get BitMap and information about the image */<br />
IIntuition->BitMapInstanceControl(instance,<br />
BMICTRL_GetBitMap, &bitmap,<br />
BMICTRL_GetAlphaMap, &alpha,<br />
BMICTRL_GetWidth, &width,<br />
BMICTRL_GetHeight, &height,<br />
TAG_END );<br />
if(bitmap && alpha)<br />
{<br />
/* Create and init ClipRect structure */<br />
if((ac = ILayers->AllocClipRect(&(scr->LayerInfo))))<br />
{<br />
/* Fill alpha-ClipRect and allocated memory for the BitMap */<br />
ac->bounds.MinX = 0;<br />
ac->bounds.MinY = 0;<br />
ac->bounds.MaxX = width-1,<br />
ac->bounds.MaxY = height-1;<br />
ac->Next = NULL;<br />
if((ac->BitMap = IGraphics->AllocBitMapTags(width, height, 8,<br />
BMATags_Displayable, TRUE,<br />
BMATags_Clear, TRUE,<br />
BMATags_PixelFormat, PIXF_ALPHA8,<br />
BMATags_Friend, scr->RastPort.BitMap,<br />
TAG_END)))<br />
{<br />
/* Fill alpha-ClipRect with alpha-BitMap */<br />
IGraphics->BltBitMapTags(BLITA_Source, alpha,<br />
BLITA_SrcType, BLITT_CHUNKY,<br />
BLITA_SrcBytesPerRow, width,<br />
BLITA_Dest, ac->BitMap,<br />
BLITA_Width, width,<br />
BLITA_Height, height,<br />
TAG_END );<br />
<br />
/* Open borderless window */<br />
if((win = IIntuition->OpenWindowTags(NULL,<br />
WA_Left, 1580,<br />
WA_Top, 120,<br />
WA_Width, width,<br />
WA_Height, height,<br />
WA_CloseGadget, FALSE,<br />
WA_DragBar, FALSE,<br />
WA_DepthGadget, FALSE,<br />
WA_SizeGadget, FALSE,<br />
WA_Borderless, TRUE,<br />
WA_ToolBox, TRUE,<br />
WA_AlphaClips, ac,<br />
WA_CustomScreen,scr,<br />
WA_Title, "Borderless window",<br />
WA_IDCMP, IDCMP_MOUSEBUTTONS,<br />
TAG_END )))<br />
{<br />
/* Define the full windows as draggable */<br />
struct Gadget draggad = { NULL, 0,0, width,height,<br />
GFLG_GADGHNONE, 0, GTYP_WDRAGGING,<br />
NULL,NULL,NULL,0,0,0,NULL };<br />
win->FirstGadget = &draggad;<br />
<br />
/* Blit the image into the window */<br />
IGraphics->BltBitMapRastPort(bitmap, 0, 0, win->RPort,<br />
0, 0, width, height, MINTERM_ABC | MINTERM_ABNC);<br />
<br />
/* Wait for CTRL-C to end the program */<br />
IExec->Wait(SIGBREAKF_CTRL_C);<br />
<br />
res = RETURN_OK;<br />
<br />
/* Close window*/<br />
IIntuition->CloseWindow(win);<br />
}<br />
else IDOS->Printf("can not open window\n");<br />
}<br />
else IDOS->Printf("can not allocate alpha mask\n");<br />
<br />
/* Free ClipRect; also frees ac->BitMap! */<br />
ILayers->FreeClipRect(&(scr->LayerInfo),ac);<br />
}<br />
else IDOS->Printf("can not allocate cliprect\n");<br />
}<br />
else IDOS->Printf("can not get (alpha) bitmaps\n");<br />
<br />
/* Free BitMap instance */<br />
IIntuition->ReleaseBitMapInstance(instance);<br />
}<br />
else IDOS->Printf("can not get instance of picture\n");<br />
<br />
/* Free image source */<br />
IIntuition->ReleaseBitMapSource(source);<br />
}<br />
else IDOS->Printf("loading picture file failed\n");<br />
<br />
/* Unlock screen */<br />
IIntuition->UnlockPubScreen(NULL,scr);<br />
}<br />
else IDOS->Printf("can not lock pubscreen\n");<br />
<br />
IDOS->FreeArgs(rda);<br />
}<br />
else { IDOS->PrintFault(IDOS->IoErr(),"BorderlessWindow"); res = RETURN_ERROR; }<br />
}<br />
else IDOS->Printf("Program requires AmigaOS 4.1\n");<br />
<br />
return res;<br />
}<br />
</syntaxhighlight><br />
<br />
Grab the test graphic here: [[Media:testpic.png|testpic.png]].<br />
<br />
[[File:AF108_borderless_grab.png|frame|center]]<br />
<br />
= Outlook =<br />
<br />
You can look forward to the next issue, in which we will deal with datatypes. Do not expect any novelties regarding the program, but for the sake of completeness we should mention these options as well.<br />
<br />
[[File:AF108_FensterLoch_grab.png|frame|center]]<br />
With a hole in a window you can create funny effects, especially if you move the window around.<br />
<br />
= Authors =<br />
<br />
Written by Michael Christoph and Aleksandra Schmidt-Pendarovska<br/><br />
Copyright (c) 2013 Michael Christoph</div>Costel Minceahttps://wiki.amigaos.net/w/index.php?title=GUI_Programming&diff=12279GUI Programming2022-04-06T10:14:43Z<p>Costel Mincea: /* ASL */</p>
<hr />
<div>== Background ==<br />
<br />
In AmigaOS, the face a program shows you – its [http://en.wikipedia.org/wiki/Graphical_user_interface graphical user interface] (GUI) – is created through a subsystem called [[Intuition_Library|Intuition]]. Older literature sometimes used to refer to Intuition as “the Amiga user interface” but this is really not the case. Despite being responsible for much of what you can ''see'' in the OS (including its windowing desktop environment, the [[UserDoc:Workbench|Workbench]]), Intuition itself remains ''invisible'' to the user. It is merely a system component providing ready-made [[#GUI elements|elements]] to build GUIs from, and a set of functions through which these elements are manipulated. Intuition also interconnects GUIs with the operating system and handles various communications that underlie application usage and control.<br />
<br />
Intuition’s functionality is further extended by a number of auxiliary system components, or [[#GUI toolkits|toolkits]]. Like most AmigaOS subsystems, Intuition and its extensions are implemented as libraries of functions that can be accessed from a higher-level programming language like C, C++, Modula-2 or AmigaE.<br />
<br />
== GUI Elements ==<br />
<br />
Amiga programs do not look or behave very differently from, say, Mac or Windows applications because their user interface is based on shared metaphors and familiar elements. There may be differences in naming conventions or programming techniques but the building blocks are similar. The following table summarizes the building blocks (GUI elements) that are provided by Intuition and its various extensions:<br />
<br />
{| class="wikitable"<br />
|-<br />
! GUI element types<br />
! Description<br />
! System component or toolkit providing this functionality<br />
|-<br />
| [[Intuition_Screens|screens]] || Virtual desktops on which windows are opened. || Intuition Library<br />
|-<br />
| [[Intuition_Windows|windows]] || Rectangular areas containing an interface through which a program communicates with the user, and vice versa. || Intuition Library, ReAction, MUI<br />
|-<br />
| [[Intuition_Menus|menus]] || Programmable sets of commands displayed as a pull-down list of options. || Intuition Library, GadTools Library<br />
|-<br />
| [[Intuition_Gadgets|gadgets]] || Various-purpose GUI controls (buttons, toolbars, gauges, text fields...) with a standardized look and behaviour. Often called “widgets” in other operating systems. || Intuition Library, GadTools Library, ReAction, MUI<br />
|-<br />
| [[Intuition_Images,_Line_Drawing_and_Text#Creating_Images|images]] || Non-selectable elements showing graphics or text. || Intuition Library, ReAction, MUI<br />
|-<br />
| [[Intuition_Requesters|requesters]] || Means for displaying information and for requesting input from the user. They would be called “dialogs”, “dialog boxes” or “dialog windows” in other OSes. || Intuition Library, ASL Library, ReAction, MUI<br />
|-<br />
| [[Intuition_Alerts|alerts]] || A method of emergency communication (such as system errors). || Exec Library, Intuition Library<br />
|-<br />
| [[Application_Library#Pop-up_notifications_(Ringhio_messages)|pop-up notifications]] || Automatic messages informing the user when things happen. Unlike requesters, notifications are “unobtrusive” and do not require any input from the user. || [[Application Library]]<br />
|-<br />
| [[Intuition_Images,_Line_Drawing_and_Text#Creating_Text|IntuiText]] || Formatted text to be placed at a specific position inside an Intuition element (screen, window, menu, gadget or requester). || Intuition Library<br />
|-<br />
| [[Intuition_Images,_Line_Drawing_and_Text#Creating_Borders|borders]] || Graphical structures made of lines that connect a series of defined points.. || Intuition Library<br />
|}<br />
<br />
== The Two Frameworks ==<br />
<br />
GUI programming in AmigaOS does not have to be done within a single framework or [http://en.wikipedia.org/wiki/Application_programming_interface API]. This fact can be confusing to newcomers. There are two frameworks in Intuition representing fundamentally different approaches to GUI programming:<br />
<br />
# The '''data structure-oriented framework''' is the original Intuition API. Within this framework, if you want to create a GUI element, you have to provide dedicated data structures for it; if you want to manipulate the element, you have to use a function designed for the particular action and type of element.<br />
<br />
# The '''object-oriented framework''' (called [[BOOPSI]]: Basic Object-Oriented Programming System for Intuition) is the extendable API. Within this framework, if you want to create a GUI element, you have to instantiate an ''object'' based upon a particular ''class''. Objects are manipulated through a small set of ''methods'' which are really just functions.<br />
<br />
Modern AmigaOS programmers generally do not directly use either of these frameworks. Although it is still possible to do so it also requires a lot more code to achieve even a simple GUI.<br />
<br />
Instead, programmers are encouraged to use one or more of the various toolkits provided.<br />
<br />
== GUI toolkits ==<br />
<br />
While the Intuition Library originally provided a datastructure-based set of basic GUI elements (screens, windows, menus, buttons & string gadgets, etc.) they have been supplanted by more modern tools for user interface programming. Most of the GUI-related functionality is now provided through various extensions to Intuition, or ''toolkits''. The following toolkits are installed by default in AmigaOS:<br />
<br />
=== GadTools ===<br />
<br />
[[GadTools_Library|GadTools]] is a datastructure-based toolkit. It is implemented as a single library and is not easily extensible. What is most useful about GadTools is the [[GadTools_Library#GadTools_Menus|menu building functionality]] (most of the other toolkits still use the menu build aspect of GadTools).<br />
<br />
GadTools was introduced in AmigaOS 2.x as a ready-made toolkit for easier, faster and more consistent GUI design. GadTools extended the original Intuition set with fancy new controls such as the [[GadTools_Library#Cycle_Gadgets|cycle gadget]], the [[GadTools_Library#Mutually-Exclusive_Gadgets|radiobutton]], or the [[GadTools_Library#Listview_Gadgets|listview]]. The gadgets shared similar imagery, thus giving Amiga GUIs a more uniform, standardized look. Apart from improving the gadget set, GadTools also greatly simplified the creation of menus (GadTools uses standard Intuition menus but provides its own build and layout system for them). On the other hand, there is a very limited support for images in GadTools.<br />
<br />
As of AmigaOS 4.1 Final Edition, GadTools is basically a legacy toolkit retained for compatibility.<br />
<br />
=== ASL ===<br />
<br />
[[ASL_Library|ASL]] is a datastructure-based toolkit. It is implemented as a single library and is not extensible.<br />
<br />
The Application Support Library (ASL) is a toolkit designed to ease the programming of common requesters. There are currently three types of requester available: file requester, font requester and screenmode requester.<br />
<br />
=== ReAction ===<br />
<br />
[[ReAction]] is an object-oriented toolkit based on BOOPSI which is highly extensible.<br />
<br />
ReAction is a more modern toolkit which hides much of the complexity. It covers all the functionality of GadTools and ASL and uses and extends the original BOOPSI class set built into Intuition Library. ReAction is considered to be the standard Amiga GUI toolkit. Over the years it has been integrated into the Intuition/BOOPSI framework, and is no longer considered a separate component.<br />
<br />
=== MUI ===<br />
<br />
[http://en.wikipedia.org/wiki/Magic_User_Interface Magic User Interface] is an object-oriented toolkit based on BOOPSI which is highly extensible.<br />
<br />
MUI is a comprehensive third-party toolkit for application GUI design which can also incorporate GadTools menus and ASL. MUI is also available on older AmigaOS systems and various clone systems although the implementation differs so compatibility is not guaranteed.<br />
<br />
=== Qt, REBOL/View and Others ===<br />
<br />
Third party toolkits may also be used on AmigaOS just as well as the built-in toolkits listed above.<br />
<br />
Such toolkits generally work by opening an Intuition Screen and then rendering directly into that screen to create the GUI environment. Toolkits may also incorporate Intuition Windows and use them as a basic element. Native Intuition Menus may or may not be used as well.<br />
<br />
With the use of skinning, 3rd party GUIs can look and feel a lot like Amiga native GUIs. However, they can suffer from reduced speed due to the more intensive use of the CPU. Much of the speed problem can be alleviated through the use of hardware acceleration (e.g. compositing).<br />
<br />
== Choosing Toolkits ==<br />
<br />
* Choose the toolkit that works best for your application and your end users/customers.<br />
<br />
* GadTools gadgets are incompatible with all others and have their own [[GadTools_Library#Function_Reference|set of functions]] to be used with. There is no automatic layout system: GadTools gadgets are not scalable and are at fixed positions and dimensions. Due to its inherent limitations, using GadTools in modern applications can no longer be recommended.<br />
<br />
* If you require modern features like scalability, font sensitivity, automatic (re)layouting, or window iconification (the ability to collapse the program window into an icon on the Workbench screen), then use one of the object-oriented toolkits: ReAction or MUI.<br />
<br />
* The ASL toolkit is utilized by ReAction and MUI through dedicated classes. There is little need to use ASL directly in object-oriented GUIs.<br />
<br />
* The original BOOPSI class set built in Intuition is usable but somewhat limited. Some BOOPSI classes are now actually wrappers for ReAction classes.<br />
<br />
* Prefer not to mix datastructure-oriented and object-oriented GUI programming. Functions designed for Intuition windows, gadgets or images are not meant to be used on GUI objects created via ReAction. BOOPSI objects must solely be manipulated using [[BOOPSI_-_Object_Oriented_Intuition#Function_Reference|BOOPSI functions]] (methods).<br />
<br />
* Many new programmers seem to be confused about window programming. It's fairly easy:<br />
** ReAction elements (objects) must reside in a ''ReAction window'', that is, a window created through the Window Class, which is part of the toolkit. Such a window is manipulated as any other BOOPSI object.<br />
** Intuition or GadTools elements must reside in an ''Intuition window'', that is, a window created through functions OpenWindow() or OpenWindowTags(), which are both part of the Intuition Library. Such windows are manipulated using dedicated functions.<br />
<br />
* Despite both being based on BOOPSI, MUI and ReAction classes are not interchangeable. You cannot extend the functionality of ReAction with MUI classes and vice versa.</div>Costel Minceahttps://wiki.amigaos.net/w/index.php?title=ASL_Library&diff=12278ASL Library2022-04-06T10:14:21Z<p>Costel Mincea: /* ASL Library */</p>
<hr />
<div>{{WIP}}<br />
== ASL Library ==<br />
<br />
A)pplication S)upport L)ibrary<br />
<br />
This article describes the asl.library. The sole purpose of this library is to provide standard file and font requesters for application programs.<br />
<br />
It is easier to understand the asl.library if you are familiar with some basic concepts of the Amiga operating system, especially TagItem arrays (described in [[Utility_Library|Utility Library]]), Intuition screens and windows, graphics library font structures, and AmigaDOS pattern matching.<br />
<br />
== About Requesters ==<br />
<br />
Requesters are temporary sub-windows used for confirming actions or selecting options. The most common type of requester is a file requester which is used to pick a file name for a load or save operation.<br />
<br />
Under earlier versions of the Amiga operating system there was limited support for requesters. Intuition provides simple requesters which can be used to request responses such as OK or Cancel from the user. More elaborate Intuition requesters can be created by adding additional features such as string gadgets, however the result of this is that each application writer develops their own style of requester. With asl.library, requesters are much easier to create and take less memory.<br />
<br />
Requesters are very flexible and can be used for many different purposes. The asl.library supports the three most common type of requesters:<br />
<br />
* File requesters for choosing a file name in a load or save operation<br />
* Font requesters for choosing a font in a text operation<br />
* Screen Mode requesters for choosing a new screen with specific attributes<br />
<br />
== Creating an ASL Requester ==<br />
<br />
Opening an ASL requester requires the use of three functions:<br />
<br />
<syntaxhighlight><br />
APTR request = AllocAslRequest( ULONG type, struct TagItem *tagList );<br />
APTR request = AllocAslRequestTags( uint32 type, Tag Tag1, ... );<br />
BOOL success = AslRequest( APTR request, struct TagItem *tagList );<br />
BOOL success = AslRequestTags( APTR request, Tag Tag1, ... );<br />
VOID FreeAslRequest( APTR request );<br />
</syntaxhighlight><br />
<br />
The first function you should call is AllocAslRequest(). This allocates the main data structure you will use, either a FileRequester structure or a FontRequester structure. You specify the type of requester you want for AllocAslRequest() by setting the type argument. This can be one of two values defined in &lt;libraries/asl.h&gt;: either ASL_FileRequest, to ask for a FileRequester structure, or ASL_FontRequest, to ask for a FontRequester structure.<br />
<br />
Both AllocAslRequest() and AslRequest() accept a TagItem array or tag list as an argument. The tag list is used to initialize or alter the values in the requester data structure.<br />
<br />
A single TagItem consists of a tag name and an associated tag value. Tag items that apply to the asl.library are defined in &lt;libraries/asl.h&gt;.<br />
<br />
Whichever requester type you use, you must allocate the requester structure with the AllocAslRequest() function call. Do not create the data structure yourself. The values in this structure are for ''read access only''. Any changes to them must be performed only through asl.library function calls.<br />
<br />
== Displaying an ASL Requester ==<br />
<br />
Once you have set up a requester structure with AllocAslRequest(), call AslRequest() to make the requester appear on screen. AslRequest() takes the requester data structure as an argument using it as a specification for the requester that it creates on screen.<br />
<br />
AslRequest() is always synchronous to the calling program. That is, control does not return to your program until the user makes a selection or cancels. AslRequest() returns TRUE, if the user selects a file (or a font). In that case the file (or font) name that the user selected is returned in the requester data structure. AslRequest() returns FALSE if the user cancels the requester or the requester failed for some reason.<br />
<br />
The contents of an ASL requester data structure are preserved across calls to AslRequest(). So, until the requester is freed, tag settings and user selections will remain in the data structure unless they are altered by tags in subsequent calls to AslRequest(). This is very useful because it allows the requester to remember and redisplay the user's previous selections. However, this also means that the programmer must assure that any addresses passed in ASL tags remain valid, or are refreshed on each call to AslRequest().<br />
<br />
Generally, options that you wish to specify only once, such as the initial position and size, should be specified as tags when you allocate the requester. Options that you wish to control for each use of the requester should be passed as tags each time the requester is opened with AslRequest().<br />
<br />
=== ASL Requesters and Custom Screens ===<br />
<br />
An application that uses a custom screen normally wants its requesters to open on its screen. Using the ASL_Window tag, a program can associate a requester with a specific window so that the requester appears on the same screen as the window. The ASL_Window tag is followed by a pointer to a window structure. ASL_Window works with both file and font requesters.<br />
<br />
Normally, a requester associated with a window (using ASL_Window) shares that window's IDCMP port for its communication. An application may not want to share an IDCMP port with the requester. Using the ASL_FuncFlags tag, a program can ask for a requester that creates its own IDCMP port. There are two flags that accomplish this. The first, FILF_NEWIDCMP, is used on file requesters. The other, FONF_NEWIDCMP, is used on font requesters.<br />
<br />
== Freeing an ASL Requester ==<br />
<br />
When you have finished with a requester use the FreeAslRequest() function to deallocate the requester data structure.<br />
<br />
== Common Tags Used by All Requester Types ==<br />
<br />
These tags apply to all three types of ASL requesters: the file requester, the font requester and the screen mode requester. Each tag in the<br />
list below is prepended with ASLxx_. The actual tag names used by ASL will be prepended with ASLFR_, ASLFO_ or ASLSM_ depending on what type of requester is being used.<br />
<br />
{| class="wikitable"<br />
! Tag Name<br />
! Used For<br />
|-<br />
| ASLxx_PubScreenName || Name of a public screen on which to open the requester.<br />
|-<br />
| ASLxx_Screen || Pointer to a screen on which to open the requester.<br />
|-<br />
| ASLxx_PrivateIDCMP || Specifies separate IDCMP for the requester window (this replaces the FILF_NEWIDCMP and FONF_NEWIDCMP flags in the ASL_FuncFlags tag used in V37).<br />
|-<br />
| ASLxx_IntuiMsgFunc || Function to call when an unknown message arrives at a shared IDCMP used by the requester window (this replaces the ASL_HookFunc tag and the FILF_DOMSGFUNC and FONF_DOMSGFUNC flags in the ASL_FuncFlags used in V37).<br />
|-<br />
| ASLxx_SleepWindow || Modal requester. Specifies that input should be blocked in the parent window.<br />
|-<br />
| ASLxx_UserData || A 32-bit value copied into the user data field of the requester structure.<br />
|-<br />
| ASLxx_TextAttr || Font to use for requester window gadgets and menus.<br />
|-<br />
| ASLxx_Locale || Locale (and language) to use for the requester window.<br />
|-<br />
| ASLxx_FilterFunc || Function to call for each item (file, font or mode) encountered. If the function returns TRUE, the item is displayed in the list view gadget, otherwise it is rejected and not displayed. (This replaces the ASL_HookFunc tag and the FILF_DOWILDFUNC and FONF_DOWILDFUNC flags in ASL_FuncFLags used in V37.)<br />
|}<br />
<br />
== Calling Custom Functions from a Requester ==<br />
<br />
The ASL_HookFunc tag passes an ASL requester a pointer to a custom function. The requester can use this function for two purposes. The first is to determine if the requester should display a particular file or font name. The other purpose is to process messages that the requester receives at its IDCMP port that are not meant for the requester. Hook functions are set up through flag values used with the ASL_FuncFlags tag:<br />
<br />
{| class="wikitable"<br />
! Hook Function Flag<br />
! Used For<br />
|-<br />
| FILF_DOWILDFUNC<br />
| Call user hook function on each name in a file requester<br />
|-<br />
| FONF_DOWILDFUNC<br />
| Call user hook function on each name in a font requester<br />
|-<br />
| FILF_DOMSGFUNC<br />
| Call user hook function for IDCMP messages not used by a file requester<br />
|-<br />
| FONF_DOMSGFUNC<br />
| Call user hook function for IDCMP messages not used by a font requester<br />
|}<br />
<br />
The FILF_DOWILDFUNC and FONF_DOWILDFUNC flags cause a requester to call the function you specify with the ASL_HookFunc tag for every file or font entry. The requester displays the file or font name only if your hook function tells it to. For a file requester, if your hook function returns a zero, the file requester will display the file name. For a font requester, if your hook function returns anything but zero, the font requester will display the font name and size.<br />
<br />
The FILF_DOMSGFUNC and FONF_DOMSGFUNC flags cause a requester to call your hook function whenever it receives an IntuiMessage that it cannot use at the IDCMP port that it shares with your window. (See the section on [[#ASL Requesters and Custom Screens|ASL Requesters and Custom Screens]] for more information about sharing IDCMP ports.) If the requester receives any messages that are not meant for the requester it will call your hook function (specified with the ASL_HookFunc tag). Your hook function is responsible for returning a pointer to the IntuiMessage. The requester will take care of replying to the message.<br />
<br />
=== Parameters Passed to Custom Hook Functions ===<br />
<br />
A requester always passes three parameters to your custom hook function:<br />
<br />
<syntaxhighlight><br />
ULONG MyHookFunc(ULONG type, CPTR object, CPTR AslRequester)<br />
</syntaxhighlight><br />
<br />
If MyHookFunc() is called from a file requester doing _DOWILDFUNC, the three parameters are:<br />
<br />
; type<br />
: FILF_DOWILDFUNC<br />
<br />
; object<br />
: pointer to an AnchorPath structure (from &lt;dos/dosasl.h&gt;)<br />
<br />
; AslRequester<br />
: pointer to the FileRequester that called the hook function<br />
<br />
The hook custom function should return a zero to display this file.<br />
<br />
The AnchorPath structure is a dos.library structure used in pattern matching. Refer to the ''AmigaDOS Manual, 3rd Edition'' for more information.<br />
<br />
If MyHookFunc() is called from a font requester doing _DOWILDFUNC, the three parameters are:<br />
<br />
; type<br />
: FONF_DOWILDFUNC<br />
<br />
; object<br />
: pointer to a TextAttr structure (from &lt;graphics/text.h&gt;)<br />
<br />
; AslRequester<br />
: pointer to the FontRequester that called the hook function<br />
<br />
The hook custom function should return non-zero to display this particular font size.<br />
<br />
If MyHookFunc() is called from a file or font requester doing _DOMSGFUNC, the three parameters are:<br />
<br />
; type<br />
: FILF_DOMSGFUNC (file requester) or FONF_DOMSGFUNC (font requester)<br />
<br />
; object<br />
: pointer to the IntuiMessage for the function to process<br />
<br />
; AslRequester<br />
: pointer to the FileRequester or FontRequester that called the hook function<br />
<br />
The hook custom function should return a pointer to the IntuiMessage.<br />
<br />
Notice that it is possible for a requester to use both _DOWILDFUNC and _DOMSGFUNC at the same time. Your hook function has to differentiate between the two cases by testing the type passed to it. It is not possible for a font and file requester to share a hook function for a _DOWILDFUNC, because FILF_DOWILDFUNC is defined to be the same value as FONF_DOWILDFUNC, so the hook function cannot tell if the object (from the prototype above) is a pointer to an AnchorPath structure or a pointer to a TextAttr structure. It is possible for font and file requesters to share one hook function for _DOMSGFUNC (even though FILF_DOMSGFUNC and FONF_DOMSGFUNC are equal) because, in this case, font and file requesters both call your hook function in the same manner.<br />
<br />
=== Example ASL Requester With Custom Hook Function ===<br />
<br />
The following example illustrates the use of a hook function for both _DOWILDFUNC and _DOMSGFUNC.<br />
<br />
<syntaxhighlight><br />
/*<br />
** filehook.c<br />
*/<br />
#include <exec/types.h><br />
#include <intuition/intuition.h><br />
#include <dos/dosasl.h><br />
#include <libraries/asl.h><br />
<br />
#include <proto/exec.h><br />
#include <proto/dos.h><br />
#include <proto/asl.h><br />
#include <proto/intuition.h><br />
<br />
#define DESTPATLENGTH 20<br />
<br />
struct AslIFace *IAsl = NULL;<br />
struct IntuitionIFace *IIntuition = NULL;<br />
<br />
struct Window *window = NULL;<br />
<br />
/* this is the pattern matching string that the hook function uses */<br />
CONST_STRPTR sourcepattern = "(#?.info)";<br />
TEXT pat[DESTPATLENGTH];<br />
<br />
uint32 HookFunc(int32 type, APTR obj, struct FileRequester *fr);<br />
<br />
<br />
int main(int argc, char **argv)<br />
{<br />
struct FileRequester *fr;<br />
<br />
struct Library *AslBase = IExec->OpenLibrary("asl.library", 50);<br />
IAsl = (struct AslIFace*)IExec->GetInterface(AslBase, "main", 1, NULL);<br />
<br />
struct Library *IntuitionBase = IExec->OpenLibrary("intuition.library", 50);<br />
IIntuition = (struct IntuitionIFace*)IExec->GetInterface(IntuitionBase, "main", 1, NULL);<br />
<br />
if (IAsl != NULL && IIntuition != NULL)<br />
{<br />
IDOS->ParsePattern(sourcepattern, pat, DESTPATLENGTH);<br />
<br />
/* open a window that gets ACTIVEWINDOW events */<br />
if (window = IIntuition->OpenWindowTags(NULL,<br />
WA_Title, "ASL Hook Function Example",<br />
WA_IDCMP, IDCMP_ACTIVEWINDOW,<br />
WA_Flags, WFLG_DEPTHGADGET,<br />
TAG_END))<br />
{<br />
if (fr = IAsl->AllocFileRequest())<br />
{<br />
if (IAsl->AslRequestTags(fr,<br />
ASL_Dir, "SYS:Utilities",<br />
ASL_Window, window,<br />
ASL_TopEdge, 0,<br />
ASL_Height, 200,<br />
ASL_Hail, "Pick an icon, select save",<br />
ASL_HookFunc, HookFunc,<br />
ASL_FuncFlags, FILF_DOWILDFUNC | FILF_DOMSGFUNC | FILF_SAVE,<br />
ASL_OKText, "Save",<br />
TAG_END))<br />
{<br />
IDOS_>Printf("PATH=%s FILE=%s\n", fr->rf_Dir, fr->rf_File);<br />
IDOS->Printf("To combine the path and filename, copy the path\n");<br />
IDOS->Printf("to a buffer, add the filename with Dos AddPart().\n");<br />
}<br />
IAsl->FreeFileRequest(fr);<br />
}<br />
IIntuition->CloseWindow(window);<br />
}<br />
}<br />
}<br />
<br />
IExec->DropInterface((struct Interface*)IIntuition);<br />
IExec->CloseLibrary(IntuitionBase);<br />
<br />
IExec->DropInterface((struct Interface*)IAsl);<br />
IExec->CloseLibrary(AslBase);<br />
<br />
return 0;<br />
}<br />
<br />
uint32 HookFunc(int32 type, APTR obj, struct FileRequester *fr)<br />
{<br />
static BOOL returnvalue;<br />
switch(type)<br />
{<br />
case FILF_DOMSGFUNC:<br />
/* We got a message meant for the window */<br />
IDOS->Printf("You activated the window\n");<br />
return(obj);<br />
break;<br />
case FILF_DOWILDFUNC:<br />
/* We got an AnchorPath structure, should<br />
** the requester display this file? */<br />
<br />
/* MatchPattern() is a dos.library function that<br />
** compares a matching pattern (parsed by the<br />
** ParsePattern() DOS function) to a string and<br />
** returns true if they match. */<br />
returnvalue = IDOS->MatchPattern(pat,<br />
((struct AnchorPath *)obj)->ap_Info.fib_FileName);<br />
<br />
/* we have to negate MatchPattern()'s return value<br />
** because the file requester expects a zero for<br />
** a match not a TRUE value */<br />
return( ! returnvalue );<br />
break;<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
== Function Reference ==<br />
<br />
The following are brief descriptions of the ASL library functions. See the SDK for details on each function call.<br />
<br />
{| class="wikitable"<br />
! Function<br />
! Description<br />
|-<br />
| AllocAslRequest()<br />
| Allocates an ASL font or file requester from a TagItem array<br />
|-<br />
| AllocAslRequestTags()<br />
| Same as AllocAslRequest() but accepts tags directly<br />
|-<br />
| AslRequest()<br />
| Displays an ASL requester with options set up in a TagItem array<br />
|-<br />
| AslRequestTags()<br />
| Same as AslRequest() but accepts tags directly<br />
|-<br />
| FreeAslRequest()<br />
| Deallocates an ASL requester created with AllocAslRequest()<br />
|}</div>Costel Minceahttps://wiki.amigaos.net/w/index.php?title=GUI_Programming&diff=12277GUI Programming2022-04-06T08:55:15Z<p>Costel Mincea: </p>
<hr />
<div>== Background ==<br />
<br />
In AmigaOS, the face a program shows you – its [http://en.wikipedia.org/wiki/Graphical_user_interface graphical user interface] (GUI) – is created through a subsystem called [[Intuition_Library|Intuition]]. Older literature sometimes used to refer to Intuition as “the Amiga user interface” but this is really not the case. Despite being responsible for much of what you can ''see'' in the OS (including its windowing desktop environment, the [[UserDoc:Workbench|Workbench]]), Intuition itself remains ''invisible'' to the user. It is merely a system component providing ready-made [[#GUI elements|elements]] to build GUIs from, and a set of functions through which these elements are manipulated. Intuition also interconnects GUIs with the operating system and handles various communications that underlie application usage and control.<br />
<br />
Intuition’s functionality is further extended by a number of auxiliary system components, or [[#GUI toolkits|toolkits]]. Like most AmigaOS subsystems, Intuition and its extensions are implemented as libraries of functions that can be accessed from a higher-level programming language like C, C++, Modula-2 or AmigaE.<br />
<br />
== GUI Elements ==<br />
<br />
Amiga programs do not look or behave very differently from, say, Mac or Windows applications because their user interface is based on shared metaphors and familiar elements. There may be differences in naming conventions or programming techniques but the building blocks are similar. The following table summarizes the building blocks (GUI elements) that are provided by Intuition and its various extensions:<br />
<br />
{| class="wikitable"<br />
|-<br />
! GUI element types<br />
! Description<br />
! System component or toolkit providing this functionality<br />
|-<br />
| [[Intuition_Screens|screens]] || Virtual desktops on which windows are opened. || Intuition Library<br />
|-<br />
| [[Intuition_Windows|windows]] || Rectangular areas containing an interface through which a program communicates with the user, and vice versa. || Intuition Library, ReAction, MUI<br />
|-<br />
| [[Intuition_Menus|menus]] || Programmable sets of commands displayed as a pull-down list of options. || Intuition Library, GadTools Library<br />
|-<br />
| [[Intuition_Gadgets|gadgets]] || Various-purpose GUI controls (buttons, toolbars, gauges, text fields...) with a standardized look and behaviour. Often called “widgets” in other operating systems. || Intuition Library, GadTools Library, ReAction, MUI<br />
|-<br />
| [[Intuition_Images,_Line_Drawing_and_Text#Creating_Images|images]] || Non-selectable elements showing graphics or text. || Intuition Library, ReAction, MUI<br />
|-<br />
| [[Intuition_Requesters|requesters]] || Means for displaying information and for requesting input from the user. They would be called “dialogs”, “dialog boxes” or “dialog windows” in other OSes. || Intuition Library, ASL Library, ReAction, MUI<br />
|-<br />
| [[Intuition_Alerts|alerts]] || A method of emergency communication (such as system errors). || Exec Library, Intuition Library<br />
|-<br />
| [[Application_Library#Pop-up_notifications_(Ringhio_messages)|pop-up notifications]] || Automatic messages informing the user when things happen. Unlike requesters, notifications are “unobtrusive” and do not require any input from the user. || [[Application Library]]<br />
|-<br />
| [[Intuition_Images,_Line_Drawing_and_Text#Creating_Text|IntuiText]] || Formatted text to be placed at a specific position inside an Intuition element (screen, window, menu, gadget or requester). || Intuition Library<br />
|-<br />
| [[Intuition_Images,_Line_Drawing_and_Text#Creating_Borders|borders]] || Graphical structures made of lines that connect a series of defined points.. || Intuition Library<br />
|}<br />
<br />
== The Two Frameworks ==<br />
<br />
GUI programming in AmigaOS does not have to be done within a single framework or [http://en.wikipedia.org/wiki/Application_programming_interface API]. This fact can be confusing to newcomers. There are two frameworks in Intuition representing fundamentally different approaches to GUI programming:<br />
<br />
# The '''data structure-oriented framework''' is the original Intuition API. Within this framework, if you want to create a GUI element, you have to provide dedicated data structures for it; if you want to manipulate the element, you have to use a function designed for the particular action and type of element.<br />
<br />
# The '''object-oriented framework''' (called [[BOOPSI]]: Basic Object-Oriented Programming System for Intuition) is the extendable API. Within this framework, if you want to create a GUI element, you have to instantiate an ''object'' based upon a particular ''class''. Objects are manipulated through a small set of ''methods'' which are really just functions.<br />
<br />
Modern AmigaOS programmers generally do not directly use either of these frameworks. Although it is still possible to do so it also requires a lot more code to achieve even a simple GUI.<br />
<br />
Instead, programmers are encouraged to use one or more of the various toolkits provided.<br />
<br />
== GUI toolkits ==<br />
<br />
While the Intuition Library originally provided a datastructure-based set of basic GUI elements (screens, windows, menus, buttons & string gadgets, etc.) they have been supplanted by more modern tools for user interface programming. Most of the GUI-related functionality is now provided through various extensions to Intuition, or ''toolkits''. The following toolkits are installed by default in AmigaOS:<br />
<br />
=== GadTools ===<br />
<br />
[[GadTools_Library|GadTools]] is a datastructure-based toolkit. It is implemented as a single library and is not easily extensible. What is most useful about GadTools is the [[GadTools_Library#GadTools_Menus|menu building functionality]] (most of the other toolkits still use the menu build aspect of GadTools).<br />
<br />
GadTools was introduced in AmigaOS 2.x as a ready-made toolkit for easier, faster and more consistent GUI design. GadTools extended the original Intuition set with fancy new controls such as the [[GadTools_Library#Cycle_Gadgets|cycle gadget]], the [[GadTools_Library#Mutually-Exclusive_Gadgets|radiobutton]], or the [[GadTools_Library#Listview_Gadgets|listview]]. The gadgets shared similar imagery, thus giving Amiga GUIs a more uniform, standardized look. Apart from improving the gadget set, GadTools also greatly simplified the creation of menus (GadTools uses standard Intuition menus but provides its own build and layout system for them). On the other hand, there is a very limited support for images in GadTools.<br />
<br />
As of AmigaOS 4.1 Final Edition, GadTools is basically a legacy toolkit retained for compatibility.<br />
<br />
=== ASL ===<br />
<br />
[[ASL_Library|ASL]] is a datastructure-based toolkit. It is implemented as a single library and is not extensible.<br />
<br />
The Application Standard Library (ASL) is a toolkit designed to ease the programming of common requesters. There are currently three types of requester available: file requester, font requester and screenmode requester.<br />
<br />
=== ReAction ===<br />
<br />
[[ReAction]] is an object-oriented toolkit based on BOOPSI which is highly extensible.<br />
<br />
ReAction is a more modern toolkit which hides much of the complexity. It covers all the functionality of GadTools and ASL and uses and extends the original BOOPSI class set built into Intuition Library. ReAction is considered to be the standard Amiga GUI toolkit. Over the years it has been integrated into the Intuition/BOOPSI framework, and is no longer considered a separate component.<br />
<br />
=== MUI ===<br />
<br />
[http://en.wikipedia.org/wiki/Magic_User_Interface Magic User Interface] is an object-oriented toolkit based on BOOPSI which is highly extensible.<br />
<br />
MUI is a comprehensive third-party toolkit for application GUI design which can also incorporate GadTools menus and ASL. MUI is also available on older AmigaOS systems and various clone systems although the implementation differs so compatibility is not guaranteed.<br />
<br />
=== Qt, REBOL/View and Others ===<br />
<br />
Third party toolkits may also be used on AmigaOS just as well as the built-in toolkits listed above.<br />
<br />
Such toolkits generally work by opening an Intuition Screen and then rendering directly into that screen to create the GUI environment. Toolkits may also incorporate Intuition Windows and use them as a basic element. Native Intuition Menus may or may not be used as well.<br />
<br />
With the use of skinning, 3rd party GUIs can look and feel a lot like Amiga native GUIs. However, they can suffer from reduced speed due to the more intensive use of the CPU. Much of the speed problem can be alleviated through the use of hardware acceleration (e.g. compositing).<br />
<br />
== Choosing Toolkits ==<br />
<br />
* Choose the toolkit that works best for your application and your end users/customers.<br />
<br />
* GadTools gadgets are incompatible with all others and have their own [[GadTools_Library#Function_Reference|set of functions]] to be used with. There is no automatic layout system: GadTools gadgets are not scalable and are at fixed positions and dimensions. Due to its inherent limitations, using GadTools in modern applications can no longer be recommended.<br />
<br />
* If you require modern features like scalability, font sensitivity, automatic (re)layouting, or window iconification (the ability to collapse the program window into an icon on the Workbench screen), then use one of the object-oriented toolkits: ReAction or MUI.<br />
<br />
* The ASL toolkit is utilized by ReAction and MUI through dedicated classes. There is little need to use ASL directly in object-oriented GUIs.<br />
<br />
* The original BOOPSI class set built in Intuition is usable but somewhat limited. Some BOOPSI classes are now actually wrappers for ReAction classes.<br />
<br />
* Prefer not to mix datastructure-oriented and object-oriented GUI programming. Functions designed for Intuition windows, gadgets or images are not meant to be used on GUI objects created via ReAction. BOOPSI objects must solely be manipulated using [[BOOPSI_-_Object_Oriented_Intuition#Function_Reference|BOOPSI functions]] (methods).<br />
<br />
* Many new programmers seem to be confused about window programming. It's fairly easy:<br />
** ReAction elements (objects) must reside in a ''ReAction window'', that is, a window created through the Window Class, which is part of the toolkit. Such a window is manipulated as any other BOOPSI object.<br />
** Intuition or GadTools elements must reside in an ''Intuition window'', that is, a window created through functions OpenWindow() or OpenWindowTags(), which are both part of the Intuition Library. Such windows are manipulated using dedicated functions.<br />
<br />
* Despite both being based on BOOPSI, MUI and ReAction classes are not interchangeable. You cannot extend the functionality of ReAction with MUI classes and vice versa.</div>Costel Minceahttps://wiki.amigaos.net/w/index.php?title=ASL_Library&diff=12276ASL Library2022-04-06T08:54:21Z<p>Costel Mincea: </p>
<hr />
<div>{{WIP}}<br />
== ASL Library ==<br />
<br />
A)pplication S)tandard L)ibrary<br />
<br />
This article describes the asl.library. The sole purpose of this library is to provide standard file and font requesters for application programs.<br />
<br />
It is easier to understand the asl.library if you are familiar with some basic concepts of the Amiga operating system, especially TagItem arrays (described in [[Utility_Library|Utility Library]]), Intuition screens and windows, graphics library font structures, and AmigaDOS pattern matching.<br />
<br />
== About Requesters ==<br />
<br />
Requesters are temporary sub-windows used for confirming actions or selecting options. The most common type of requester is a file requester which is used to pick a file name for a load or save operation.<br />
<br />
Under earlier versions of the Amiga operating system there was limited support for requesters. Intuition provides simple requesters which can be used to request responses such as OK or Cancel from the user. More elaborate Intuition requesters can be created by adding additional features such as string gadgets, however the result of this is that each application writer develops their own style of requester. With asl.library, requesters are much easier to create and take less memory.<br />
<br />
Requesters are very flexible and can be used for many different purposes. The asl.library supports the three most common type of requesters:<br />
<br />
* File requesters for choosing a file name in a load or save operation<br />
* Font requesters for choosing a font in a text operation<br />
* Screen Mode requesters for choosing a new screen with specific attributes<br />
<br />
== Creating an ASL Requester ==<br />
<br />
Opening an ASL requester requires the use of three functions:<br />
<br />
<syntaxhighlight><br />
APTR request = AllocAslRequest( ULONG type, struct TagItem *tagList );<br />
APTR request = AllocAslRequestTags( uint32 type, Tag Tag1, ... );<br />
BOOL success = AslRequest( APTR request, struct TagItem *tagList );<br />
BOOL success = AslRequestTags( APTR request, Tag Tag1, ... );<br />
VOID FreeAslRequest( APTR request );<br />
</syntaxhighlight><br />
<br />
The first function you should call is AllocAslRequest(). This allocates the main data structure you will use, either a FileRequester structure or a FontRequester structure. You specify the type of requester you want for AllocAslRequest() by setting the type argument. This can be one of two values defined in &lt;libraries/asl.h&gt;: either ASL_FileRequest, to ask for a FileRequester structure, or ASL_FontRequest, to ask for a FontRequester structure.<br />
<br />
Both AllocAslRequest() and AslRequest() accept a TagItem array or tag list as an argument. The tag list is used to initialize or alter the values in the requester data structure.<br />
<br />
A single TagItem consists of a tag name and an associated tag value. Tag items that apply to the asl.library are defined in &lt;libraries/asl.h&gt;.<br />
<br />
Whichever requester type you use, you must allocate the requester structure with the AllocAslRequest() function call. Do not create the data structure yourself. The values in this structure are for ''read access only''. Any changes to them must be performed only through asl.library function calls.<br />
<br />
== Displaying an ASL Requester ==<br />
<br />
Once you have set up a requester structure with AllocAslRequest(), call AslRequest() to make the requester appear on screen. AslRequest() takes the requester data structure as an argument using it as a specification for the requester that it creates on screen.<br />
<br />
AslRequest() is always synchronous to the calling program. That is, control does not return to your program until the user makes a selection or cancels. AslRequest() returns TRUE, if the user selects a file (or a font). In that case the file (or font) name that the user selected is returned in the requester data structure. AslRequest() returns FALSE if the user cancels the requester or the requester failed for some reason.<br />
<br />
The contents of an ASL requester data structure are preserved across calls to AslRequest(). So, until the requester is freed, tag settings and user selections will remain in the data structure unless they are altered by tags in subsequent calls to AslRequest(). This is very useful because it allows the requester to remember and redisplay the user's previous selections. However, this also means that the programmer must assure that any addresses passed in ASL tags remain valid, or are refreshed on each call to AslRequest().<br />
<br />
Generally, options that you wish to specify only once, such as the initial position and size, should be specified as tags when you allocate the requester. Options that you wish to control for each use of the requester should be passed as tags each time the requester is opened with AslRequest().<br />
<br />
=== ASL Requesters and Custom Screens ===<br />
<br />
An application that uses a custom screen normally wants its requesters to open on its screen. Using the ASL_Window tag, a program can associate a requester with a specific window so that the requester appears on the same screen as the window. The ASL_Window tag is followed by a pointer to a window structure. ASL_Window works with both file and font requesters.<br />
<br />
Normally, a requester associated with a window (using ASL_Window) shares that window's IDCMP port for its communication. An application may not want to share an IDCMP port with the requester. Using the ASL_FuncFlags tag, a program can ask for a requester that creates its own IDCMP port. There are two flags that accomplish this. The first, FILF_NEWIDCMP, is used on file requesters. The other, FONF_NEWIDCMP, is used on font requesters.<br />
<br />
== Freeing an ASL Requester ==<br />
<br />
When you have finished with a requester use the FreeAslRequest() function to deallocate the requester data structure.<br />
<br />
== Common Tags Used by All Requester Types ==<br />
<br />
These tags apply to all three types of ASL requesters: the file requester, the font requester and the screen mode requester. Each tag in the<br />
list below is prepended with ASLxx_. The actual tag names used by ASL will be prepended with ASLFR_, ASLFO_ or ASLSM_ depending on what type of requester is being used.<br />
<br />
{| class="wikitable"<br />
! Tag Name<br />
! Used For<br />
|-<br />
| ASLxx_PubScreenName || Name of a public screen on which to open the requester.<br />
|-<br />
| ASLxx_Screen || Pointer to a screen on which to open the requester.<br />
|-<br />
| ASLxx_PrivateIDCMP || Specifies separate IDCMP for the requester window (this replaces the FILF_NEWIDCMP and FONF_NEWIDCMP flags in the ASL_FuncFlags tag used in V37).<br />
|-<br />
| ASLxx_IntuiMsgFunc || Function to call when an unknown message arrives at a shared IDCMP used by the requester window (this replaces the ASL_HookFunc tag and the FILF_DOMSGFUNC and FONF_DOMSGFUNC flags in the ASL_FuncFlags used in V37).<br />
|-<br />
| ASLxx_SleepWindow || Modal requester. Specifies that input should be blocked in the parent window.<br />
|-<br />
| ASLxx_UserData || A 32-bit value copied into the user data field of the requester structure.<br />
|-<br />
| ASLxx_TextAttr || Font to use for requester window gadgets and menus.<br />
|-<br />
| ASLxx_Locale || Locale (and language) to use for the requester window.<br />
|-<br />
| ASLxx_FilterFunc || Function to call for each item (file, font or mode) encountered. If the function returns TRUE, the item is displayed in the list view gadget, otherwise it is rejected and not displayed. (This replaces the ASL_HookFunc tag and the FILF_DOWILDFUNC and FONF_DOWILDFUNC flags in ASL_FuncFLags used in V37.)<br />
|}<br />
<br />
== Calling Custom Functions from a Requester ==<br />
<br />
The ASL_HookFunc tag passes an ASL requester a pointer to a custom function. The requester can use this function for two purposes. The first is to determine if the requester should display a particular file or font name. The other purpose is to process messages that the requester receives at its IDCMP port that are not meant for the requester. Hook functions are set up through flag values used with the ASL_FuncFlags tag:<br />
<br />
{| class="wikitable"<br />
! Hook Function Flag<br />
! Used For<br />
|-<br />
| FILF_DOWILDFUNC<br />
| Call user hook function on each name in a file requester<br />
|-<br />
| FONF_DOWILDFUNC<br />
| Call user hook function on each name in a font requester<br />
|-<br />
| FILF_DOMSGFUNC<br />
| Call user hook function for IDCMP messages not used by a file requester<br />
|-<br />
| FONF_DOMSGFUNC<br />
| Call user hook function for IDCMP messages not used by a font requester<br />
|}<br />
<br />
The FILF_DOWILDFUNC and FONF_DOWILDFUNC flags cause a requester to call the function you specify with the ASL_HookFunc tag for every file or font entry. The requester displays the file or font name only if your hook function tells it to. For a file requester, if your hook function returns a zero, the file requester will display the file name. For a font requester, if your hook function returns anything but zero, the font requester will display the font name and size.<br />
<br />
The FILF_DOMSGFUNC and FONF_DOMSGFUNC flags cause a requester to call your hook function whenever it receives an IntuiMessage that it cannot use at the IDCMP port that it shares with your window. (See the section on [[#ASL Requesters and Custom Screens|ASL Requesters and Custom Screens]] for more information about sharing IDCMP ports.) If the requester receives any messages that are not meant for the requester it will call your hook function (specified with the ASL_HookFunc tag). Your hook function is responsible for returning a pointer to the IntuiMessage. The requester will take care of replying to the message.<br />
<br />
=== Parameters Passed to Custom Hook Functions ===<br />
<br />
A requester always passes three parameters to your custom hook function:<br />
<br />
<syntaxhighlight><br />
ULONG MyHookFunc(ULONG type, CPTR object, CPTR AslRequester)<br />
</syntaxhighlight><br />
<br />
If MyHookFunc() is called from a file requester doing _DOWILDFUNC, the three parameters are:<br />
<br />
; type<br />
: FILF_DOWILDFUNC<br />
<br />
; object<br />
: pointer to an AnchorPath structure (from &lt;dos/dosasl.h&gt;)<br />
<br />
; AslRequester<br />
: pointer to the FileRequester that called the hook function<br />
<br />
The hook custom function should return a zero to display this file.<br />
<br />
The AnchorPath structure is a dos.library structure used in pattern matching. Refer to the ''AmigaDOS Manual, 3rd Edition'' for more information.<br />
<br />
If MyHookFunc() is called from a font requester doing _DOWILDFUNC, the three parameters are:<br />
<br />
; type<br />
: FONF_DOWILDFUNC<br />
<br />
; object<br />
: pointer to a TextAttr structure (from &lt;graphics/text.h&gt;)<br />
<br />
; AslRequester<br />
: pointer to the FontRequester that called the hook function<br />
<br />
The hook custom function should return non-zero to display this particular font size.<br />
<br />
If MyHookFunc() is called from a file or font requester doing _DOMSGFUNC, the three parameters are:<br />
<br />
; type<br />
: FILF_DOMSGFUNC (file requester) or FONF_DOMSGFUNC (font requester)<br />
<br />
; object<br />
: pointer to the IntuiMessage for the function to process<br />
<br />
; AslRequester<br />
: pointer to the FileRequester or FontRequester that called the hook function<br />
<br />
The hook custom function should return a pointer to the IntuiMessage.<br />
<br />
Notice that it is possible for a requester to use both _DOWILDFUNC and _DOMSGFUNC at the same time. Your hook function has to differentiate between the two cases by testing the type passed to it. It is not possible for a font and file requester to share a hook function for a _DOWILDFUNC, because FILF_DOWILDFUNC is defined to be the same value as FONF_DOWILDFUNC, so the hook function cannot tell if the object (from the prototype above) is a pointer to an AnchorPath structure or a pointer to a TextAttr structure. It is possible for font and file requesters to share one hook function for _DOMSGFUNC (even though FILF_DOMSGFUNC and FONF_DOMSGFUNC are equal) because, in this case, font and file requesters both call your hook function in the same manner.<br />
<br />
=== Example ASL Requester With Custom Hook Function ===<br />
<br />
The following example illustrates the use of a hook function for both _DOWILDFUNC and _DOMSGFUNC.<br />
<br />
<syntaxhighlight><br />
/*<br />
** filehook.c<br />
*/<br />
#include <exec/types.h><br />
#include <intuition/intuition.h><br />
#include <dos/dosasl.h><br />
#include <libraries/asl.h><br />
<br />
#include <proto/exec.h><br />
#include <proto/dos.h><br />
#include <proto/asl.h><br />
#include <proto/intuition.h><br />
<br />
#define DESTPATLENGTH 20<br />
<br />
struct AslIFace *IAsl = NULL;<br />
struct IntuitionIFace *IIntuition = NULL;<br />
<br />
struct Window *window = NULL;<br />
<br />
/* this is the pattern matching string that the hook function uses */<br />
CONST_STRPTR sourcepattern = "(#?.info)";<br />
TEXT pat[DESTPATLENGTH];<br />
<br />
uint32 HookFunc(int32 type, APTR obj, struct FileRequester *fr);<br />
<br />
<br />
int main(int argc, char **argv)<br />
{<br />
struct FileRequester *fr;<br />
<br />
struct Library *AslBase = IExec->OpenLibrary("asl.library", 50);<br />
IAsl = (struct AslIFace*)IExec->GetInterface(AslBase, "main", 1, NULL);<br />
<br />
struct Library *IntuitionBase = IExec->OpenLibrary("intuition.library", 50);<br />
IIntuition = (struct IntuitionIFace*)IExec->GetInterface(IntuitionBase, "main", 1, NULL);<br />
<br />
if (IAsl != NULL && IIntuition != NULL)<br />
{<br />
IDOS->ParsePattern(sourcepattern, pat, DESTPATLENGTH);<br />
<br />
/* open a window that gets ACTIVEWINDOW events */<br />
if (window = IIntuition->OpenWindowTags(NULL,<br />
WA_Title, "ASL Hook Function Example",<br />
WA_IDCMP, IDCMP_ACTIVEWINDOW,<br />
WA_Flags, WFLG_DEPTHGADGET,<br />
TAG_END))<br />
{<br />
if (fr = IAsl->AllocFileRequest())<br />
{<br />
if (IAsl->AslRequestTags(fr,<br />
ASL_Dir, "SYS:Utilities",<br />
ASL_Window, window,<br />
ASL_TopEdge, 0,<br />
ASL_Height, 200,<br />
ASL_Hail, "Pick an icon, select save",<br />
ASL_HookFunc, HookFunc,<br />
ASL_FuncFlags, FILF_DOWILDFUNC | FILF_DOMSGFUNC | FILF_SAVE,<br />
ASL_OKText, "Save",<br />
TAG_END))<br />
{<br />
IDOS_>Printf("PATH=%s FILE=%s\n", fr->rf_Dir, fr->rf_File);<br />
IDOS->Printf("To combine the path and filename, copy the path\n");<br />
IDOS->Printf("to a buffer, add the filename with Dos AddPart().\n");<br />
}<br />
IAsl->FreeFileRequest(fr);<br />
}<br />
IIntuition->CloseWindow(window);<br />
}<br />
}<br />
}<br />
<br />
IExec->DropInterface((struct Interface*)IIntuition);<br />
IExec->CloseLibrary(IntuitionBase);<br />
<br />
IExec->DropInterface((struct Interface*)IAsl);<br />
IExec->CloseLibrary(AslBase);<br />
<br />
return 0;<br />
}<br />
<br />
uint32 HookFunc(int32 type, APTR obj, struct FileRequester *fr)<br />
{<br />
static BOOL returnvalue;<br />
switch(type)<br />
{<br />
case FILF_DOMSGFUNC:<br />
/* We got a message meant for the window */<br />
IDOS->Printf("You activated the window\n");<br />
return(obj);<br />
break;<br />
case FILF_DOWILDFUNC:<br />
/* We got an AnchorPath structure, should<br />
** the requester display this file? */<br />
<br />
/* MatchPattern() is a dos.library function that<br />
** compares a matching pattern (parsed by the<br />
** ParsePattern() DOS function) to a string and<br />
** returns true if they match. */<br />
returnvalue = IDOS->MatchPattern(pat,<br />
((struct AnchorPath *)obj)->ap_Info.fib_FileName);<br />
<br />
/* we have to negate MatchPattern()'s return value<br />
** because the file requester expects a zero for<br />
** a match not a TRUE value */<br />
return( ! returnvalue );<br />
break;<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
== Function Reference ==<br />
<br />
The following are brief descriptions of the ASL library functions. See the SDK for details on each function call.<br />
<br />
{| class="wikitable"<br />
! Function<br />
! Description<br />
|-<br />
| AllocAslRequest()<br />
| Allocates an ASL font or file requester from a TagItem array<br />
|-<br />
| AllocAslRequestTags()<br />
| Same as AllocAslRequest() but accepts tags directly<br />
|-<br />
| AslRequest()<br />
| Displays an ASL requester with options set up in a TagItem array<br />
|-<br />
| AslRequestTags()<br />
| Same as AslRequest() but accepts tags directly<br />
|-<br />
| FreeAslRequest()<br />
| Deallocates an ASL requester created with AllocAslRequest()<br />
|}</div>Costel Minceahttps://wiki.amigaos.net/w/index.php?title=Blitter_Objects&diff=11087Blitter Objects2020-03-01T21:21:31Z<p>Costel Mincea: /* DBufPacket and Double-Buffering */</p>
<hr />
<div>== Using Bobs ==<br />
<br />
The following section describes how to define a Bob (blitter object). Like VSprites, a Bob is a software construct designed to make animation easier. The main advantage of a Bob over a VSprite is that it allows more colors and a width greater than 16 pixels to be defined.<br />
<br />
To create a Bob, you need both a Bob structure and a VSprite structure. The components common to all GELs - height, collision-handling information, position in the drawing area and pointers to the image definition - are part of the VSprite structure. The added features - such as drawing sequence, data about saving and restoring the background, and other features not applicable to VSprites - are further specified in the Bob structure.<br />
<br />
=== The VSprite Structure and Bobs ===<br />
<br />
The root VSprite structure is set up as described earlier for true VSprites, with the following exceptions:<br />
<br />
; Y, X<br />
: Bob position is always in pixels that are the same resolution as the display.<br />
<br />
; Flags<br />
: For Bobs, the VSPRITE flag must be cleared. SAVEBACK or OVERLAY can also be used.<br />
<br />
; Height, Width<br />
: Bob pixels are the size of the background pixels. The Width of Bobs may be greater than one word.<br />
<br />
; Depth<br />
: The Depth of a Bob may be up to as deep as the playfield, provided that enough image data is provided.<br />
<br />
; ImageData<br />
: This is still a pointer to the image, but the data there is organized differently.<br />
<br />
; SprColors<br />
: This pointer should be set to NULL for Bobs.<br />
<br />
; VSBob<br />
: This is a pointer to the Bob structure set up as described below.<br />
<br />
=== VSprite Flags and Bobs ===<br />
<br />
The bits in the VSprite.Flags field that apply to a Bob are the VSPRITE flag, the SAVEBACK flag and the OVERLAY flag. When a VSprite structure is used to define a Bob, the VSPRITE flag in the VSprite.Flags field must be set to zero. This tells the system that this GEL is a Bob type.<br />
<br />
To have the GEL routines save the background before the Bob is drawn and restore the background after the Bob is removed, specify the SAVEBACK flag (stands for "save the background") in the VSprite structure Flags field. If this flag is set, the SaveBuffer must have been allocated, which is where the system puts this saved background area. The buffer must be large enough to save all the background bitplanes, regardless of how many planes the Bob has. The size in words can be calculated as follows:<br />
<br />
<syntaxhighlight><br />
/* Note that Bob.Width is in units of words. */<br />
size = Bob.Width * Bob.Height * RastPort.BitMap.Depth;<br />
</syntaxhighlight><br />
<br />
To allocate this space, the graphics function AllocRaster() can be used. AllocRaster() takes the width in bits, so it is a convenient way to allocate the space needed. The makeBob() routine below shows another way to correctly allocate this buffer. For example:<br />
<br />
<syntaxhighlight><br />
/* space for 16 bits times 5 lines times 5 bitplanes */<br />
myBob.SaveBuffer = AllocRaster( 16, (5 * 5) );<br />
</syntaxhighlight><br />
<br />
{{Note|title=Warning|text=The SaveBuffer must be allocated from Chip memory and contain an even number of word-aligned bytes. The AllocRaster() function does this for you. The AllocRaster() function rounds the width value up to the next integer multiple of 16 bits which is greater than or equal to the current value an it obtains memory from the Chip memory pool.}}<br />
<br />
OVERLAY is the other VSprite.Flags item that applies to Bobs. If this flag is set, it means that the background's original pixels show through in any area where there are 0 bits in the Bob's shadow mask (ImageShadow, explained later). The space for the ImageShadow shadow mask must have been allocated and initialized. The ImageShadow mask must be allocated from Chip memory.<br />
<br />
If the OVERLAY bit is cleared, the system uses the ''entire rectangle of words'' that define the Bob image to ''replace'' the playfield area at the specified ''x,y'' coordinates. See the paragraphs below called "ImageShadow."<br />
<br />
=== The Bob Structure ===<br />
<br />
The Bob structure is defined in the include file &lt;graphics/gels.h&gt; as follows:<br />
<br />
<syntaxhighlight><br />
struct Bob<br />
{<br />
WORD Flags; /* general purpose flags */<br />
WORD *SaveBuffer;/* buffer for background save */<br />
WORD *ImageShadow; /* shadow mask of image */<br />
struct Bob *Before; /* draw this Bob before Bobs on this list */<br />
struct Bob *After; /* draw this Bob after Bobs on this list */<br />
struct VSprite *BobVSprite;/* this Bob's VSprite definition */<br />
struct AnimComp *BobComp; /* pointer to this Bob's AnimComp def */<br />
struct DBufPacket *DBuffer; /* pointer to this Bob's dBuf packet */<br />
BUserStuff BUserExt; /* Bob user extension */<br />
};<br />
</syntaxhighlight><br />
<br />
The Bob structure itself does not need to be in Chip memory. The (global) static declaration of a Bob structure could be done like so:<br />
<br />
<syntaxhighlight><br />
struct Bob myBob =<br />
{<br />
0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0<br />
};<br />
</syntaxhighlight><br />
<br />
However, since most of the Bob structure members are pointers, it is more common to allocate and set the Bob up dynamically. Refer to the makeBob() and freeBob() functions in the "animtools.c" example at the end of the article for an example of allocating, initializing and freeing a Bob structure.<br />
<br />
==== Linking Bob and VSprite Structures ====<br />
<br />
The VSprite and Bob structures must point to one another, so that the system can find the entire GEL. The structures are linked with statements like this:<br />
<br />
<syntaxhighlight><br />
myBob.BobVSprite = &myVSprite;<br />
myVSprite.VSBob = &myBob;<br />
</syntaxhighlight><br />
<br />
Now the system (and the application program) can go back and forth between the two structures to obtain the various Bob variables.<br />
<br />
=== Using Bob Flags ===<br />
<br />
The following paragraphs describe how to set the Flags field in the Bob structure (note that these flags do not apply to the Flags field of the VSprite structure).<br />
<br />
To tell the system not to erase the old image of the Bob when the Bob is moved, specify the SAVEBOB flag in the Bob structure Flags field. This makes the Bob behave like a paintbrush. It has the opposite effect of SAVEBACK.<br />
<br />
{{Note|title=It's Faster To Draw A New Bob|text=It takes longer to preserve and restore the raster image than simply to draw a new Bob image wherever required.}}<br />
<br />
If this Bob is part of an AnimComp, set the BOBISCOMP flag in the Bob structure to 1. If the flag is a 1, the pointer named BobComp must have been initialized. Otherwise, the system ignores the pointer, and it may be left alone (though it's good practice to initialize it to NULL). See "Animation Structures and Controls" for a discussion of AnimComps.<br />
<br />
This flag is used solely by the system, and should be left alone. When a Bob is waiting to be drawn, the system sets the BWAITING flag in the Bob structure to 1. This occurs only if the system has found a Before pointer in this Bob's structure that points to another Bob. Thus, the system flag BWAITING provides current draw-status to the system. Currently, the system clears this flag on return from each call to DrawGList().<br />
<br />
This is a system status flag that indicates to the system whether or not this Bob has already been drawn. Therefore, in the process of examining the various Before and After flags, the drawing routines can determine the drawing sequence. The system clears this flag on return from each call to DrawGList().<br />
<br />
To initiate the removal of a Bob during the next call to DrawGList(), set BOBSAWAY to 1. Either the application or the system may set this Bob structure system flag. The system restores the background where it has last drawn the Bob. The system will unlink the Bob from the system GEL list the next time DrawGList() is called, unless the application is using double-buffering. In that case, the Bob will not be unlinked and completely removed until two calls to DrawGList() have occurred and the Bob has been removed from both buffers. The RemBob() macro sets the BOBSAWAY flag.<br />
<br />
When a Bob has been completely removed, the system sets the BOBNIX flag to 1 on return from DrawGList(). In other words, when the background area has been fully restored and the Bob has been removed from the GEL list, this flag in is set to a 1. BOBNIX is especially significant when double-buffering because when an application asks for a Bob to be removed, the system must remove it from both the drawing buffer ''and'' from the display buffer. Once BOBNIX has been set, it means the Bob has been removed from both buffers and the application is free to reuse or deallocate the Bob.<br />
<br />
The SAVEPRESERVE flag is a double-buffer version of the SAVEBACK flag. If using double-buffering and wishing to save and restore the background, set SAVEBACK to 1. SAVEPRESERVE is used by the system to indicate whether the Bob in the "other" buffer has been restored; it is for system use only.<br />
<br />
=== Specifying the Size of a Bob ===<br />
<br />
Bobs do not have the 16-pixel width limit that applies to VSprites. To specify the overall size of a Bob, use the Height and Width members of the root VSprite structure. Specify the Width as the number of 16-bit words it takes to fully contain the object. The number of lines is still specified with the Height member in the VSprite data structure.<br />
<br />
As an example, suppose the Bob is 24 pixels wide and 20 lines tall. Use statements like the following to specify the size:<br />
<br />
<syntaxhighlight><br />
myVSprite.Height = 20; /* 20 lines tall. */<br />
myVSprite.Width = 2; /* 24 bits fit into two words. */<br />
</syntaxhighlight><br />
<br />
Because Bobs are drawn into the background playfield, the pixels of the Bob are the same size as the background pixels, and share the color palette of the ViewPort.<br />
<br />
=== Specifying the Shape of a Bob ===<br />
<br />
The layout of the data of a Bob's image is different from that of a VSprite because of the way the system retrieves data to draw Bobs. VSprite images are organized in a way convenient to the Sprite hardware; Bob images are set up for easy blitter manipulation. The ImageData pointer is still initialized to point to the first word of the image definition.<br />
<br />
{{Note|text=As with all image data, a Bob’s ImageData must be in Chip memory for access by the blitter.}}<br />
<br />
The sample image below shows the same image defined as a VSprite in the "Using Virtual Sprites" section above. The data here, however, is laid out for a Bob. The shape is 2 planes deep and is triangular:<br />
<br />
<pre><br />
<first bitplane data><br />
<br />
mem 1111 1111 1111 1111 Least significant bit of sprite line 1<br />
mem + 1 0011 1100 0011 1100 Least significant bit of sprite line 2<br />
mem + 2 0000 1100 0011 0000 Least significant bit of sprite line 3<br />
mem + 3 0000 0010 0100 0000 Least significant bit of sprite line 4<br />
mem + 4 0000 0001 1000 0000 Least significant bit of sprite line 5<br />
<br />
<second bitplane data><br />
<br />
mem + 5 1111 1111 1111 1111 Most significant bit of sprite line 1<br />
mem + 6 0011 0000 0000 1100 Most significant bit of sprite line 2<br />
mem + 7 0000 1111 1111 0000 Most significant bit of sprite line 3<br />
mem + 8 0000 0011 1100 0000 Most significant bit of sprite line 4<br />
mem + 9 0000 0001 1000 0000 Most significant bit of sprite line 5<br />
<br />
<more bitplanes of data if Bob is deeper><br />
</pre><br />
<br />
=== Specifying the Colors of a Bob ===<br />
<br />
Typically a five-bitplane, low-resolution mode display allows playfield pixels (and therefore, Bob pixels) to be selected from any of 32 active colors out of a system palette of 4,096 different color choices. Bob colors are limited to the colors used in the background playfield.<br />
<br />
The system ignores the sprColors member of the VSprite structure when the VSprite structure is the root of a Bob. Instead, the Bob's colors are determined by the combination of the Depth of the Bob image and its PlanePick, PlaneOnOff and ImageShadow members.<br />
<br />
Use the Depth member in the VSprite structure to indicate how many planes of image data is provided to define the Bob. This also defines how many colors the Bob will have. The combination of bits in corresponding ''x,y'' positions in each bitplane determines the color of the pixel at that position.<br />
<br />
For example, if a Depth of one plane is specified, then the bits of that image allow only two colors to be selected: one color for each bit that is a 0, a second color for each bit that is a 1. Likewise, if there are 5 planes of image data, all 32 colors can be used in the Bob. The Bob Depth must not exceed the background depth. Specify Depth using a statement such as the following:<br />
<br />
<syntaxhighlight><br />
myVSprite.Depth = 5; /* Allow a 32 color, 5-bitplane image. */<br />
</syntaxhighlight><br />
<br />
=== Other Items Influencing Bob Colors ===<br />
<br />
The three other members in the VSprite structure that affect the color of Bob pixels are ImageShadow, PlanePick, and PlaneOnOff.<br />
<br />
==== ImageShadow ====<br />
<br />
The ImageShadow member is a pointer to the shadow mask of a Bob. A shadow mask is the logical ''or'' of all bitplanes of a Bob image. The system uses the shadow mask in conjunction with PlaneOnOff, discussed below, for color selection. It also uses the shadow mask to "cookie cut" the bits that will be overwritten by this Bob, to save and later restore the background.<br />
<br />
The following figure shows the shadow mask of the image described above.<br />
<br />
<pre><br />
mem + 0 1111 1111 1111 1111 Shadow mask for line 1<br />
mem + 1 0011 1100 0011 1100 Shadow mask for line 2<br />
mem + 2 0000 1111 1111 0000 Shadow mask for line 3<br />
mem + 3 0000 0011 1100 0000 Shadow mask for line 4<br />
mem + 4 0000 0001 1000 0000 Shadow mask for line 5<br />
</pre><br />
<br />
Space for the ImageShadow must be provided and this pointer initialized to point to it. The amount of memory needed is equivalent to one plane of the image:<br />
<br />
<pre><br />
shadow_size = myBob-&gt;BobVSprite-&gt;Height * myBob-&gt;BobVSprite-&gt;Width;<br />
</pre><br />
<br />
The example image is 5 high and 1 word wide, so, 5 words must be made available.<br />
<br />
{{Note|text=The ImageShadow memory must be allocated from Chip memory (MEMF_CHIP).}}<br />
<br />
==== PlanePick ====<br />
<br />
Because the Depth of the Bob can be less than the background, the PlanePick member is provided so that the application can indicate which background bitplanes are to have image data put into them. The system starts with the least significant plane of the Bob, and scans PlanePick starting at the least significant bit, looking for a plane of the RastPort to put it in.<br />
<br />
For example, if PlanePick has a binary value of: 0 0 0 0 0 0 1 1 (0x03) then the system draws the first plane of the Bob's image into background plane 0 and the second plane into background plane 1.<br />
<br />
Alternatively, a PlanePick value of: 0 0 0 1 0 0 1 0 (0x12) directs the system to put the first Bob plane into plane 1, and the second Bob plane into plane 4.<br />
<br />
==== PlaneOnOff ====<br />
<br />
What happens to the background planes that aren't picked? The shadow mask is used to either set or clear the bits in those planes in the exact shape of the Bob if OVERLAY is set, otherwise the entire rectangle containing the Bob is used. The PlaneOnOff member tells the system whether to put down the shadow mask as zeros or ones for each plane. The relationship between bit positions in PlaneOnOff and background plane numbers is identical to PlanePick: the least significant bit position indicates the lowest-numbered bitplane. A zero bit clears the shadow mask shape in the corresponding plane, while a one bit sets the shadow mask shape. The planes Picked by PlanePick have image data - not shadow mask - blitted in.<br />
<br />
This provides a great deal of color versatility. One image definition can be used for many Bobs. By having different PlanePick / PlaneOnOff combinations, each Bob can use a different subset of the background color set.<br />
<br />
There is a member in the VSprite structure called CollMask (the collision mask, covered under "Detecting GEL Collisions") for which the application may also reserve some memory space. The ImageShadow and CollMask pointers usually, but not necessarily, point to the same data, which must be located in Chip memory. If they point to the same location, obviously, the memory only need be allocated once.<br />
<br />
An example of the kinds of statements that accomplish these actions (see the makeVSprite() and makeBob() examples for more details):<br />
<br />
<syntaxhighlight><br />
#define BOBW 1<br />
#define BOBH 5<br />
#define BOBD 2<br />
<br />
/* Data definition from example layout */<br />
uint16 chip BobData[]=<br />
{<br />
0xFFFF, 0x300C, 0x0FF0, 0x03C0, 0x0180,<br />
0xFFFF, 0x3E7C, 0x0C30, 0x03C0, 0x0180<br />
};<br />
<br />
/* Reserve space for the collision mask for this Bob */<br />
uint16 chip BobCollision[BOBW * BOBH];<br />
<br />
myVSprite.Width = BOBW; /* Image is 16 pixels wide (1 word) */<br />
myVSprite.Height = BOBH; /* 5 lines for each plane of the Bob */<br />
myVSprite.Depth = BOBD; /* 2 Planes are in ImageData */<br />
<br />
/* Show the system where it can find the data image of the Bob */<br />
myVSprite.ImageData = BobData;<br />
<br />
/* binary 0101, render image data into bitplanes 0 and 2 */<br />
myVSprite.PlanePick = 0x05;<br />
<br />
/* binary 0000, means colors 1, 4, and 5 will be used.<br />
* binary 0010 would mean colors 3, 6, and 7.<br />
* " 1000 " " " 9, C, and D.<br />
* " 1010 " " " B, E, and F.<br />
*/<br />
myVSprite.PlaneOnOff = 0x00;<br />
<br />
/* Where to put collision mask */<br />
myVSprite.CollMask = BobCollision;<br />
<br />
/* Tell the system where it can assemble a GEL shadow */<br />
/* Point to same area as CollMask */<br />
myBob.ImageShadow = BobCollision;<br />
<br />
/* Create the Sprite collision mask in the VSprite structure */<br />
IGraphics->InitMasks(&myVSprite);<br />
</syntaxhighlight><br />
<br />
=== Bob Priorities ===<br />
<br />
This subsection describes the choices for inter-Bob priorities. The inter-Bob priorities tell the system what order to render the Bobs. Bobs rendered earlier will appear to be behind later Bobs. A Bob drawn earlier is said to have the lower priority and a Bob drawn later is said to have the higher priority. Thus, the highest priority Bob will be drawn last and will never be obstructed by another Bob.<br />
<br />
==== Letting the System Decide Priorities ====<br />
<br />
The priority issue can be ignored and the system will render the Bobs as it finds them in the GelsInfo list. To do this, set the Bob’s Before and After pointers to NULL. Since the GelsInfo list is sorted by GEL x, y values, Bobs that are higher on the display will appear behind the lower ones, and Bobs that are more to the left on the display will appear behind Bobs on the right.<br />
<br />
As Bobs are moved about the display, their priorities will change.<br />
<br />
==== Specifying the Drawing Order ====<br />
<br />
To specify the priorities of the Bobs, use the Before and After pointers. Before points to the Bob that this Bob should be drawn before, and After points to the Bob that this Bob should be drawn after. By following these pointers, from Bob to Bob, the system can determine the order in which the Bobs should be drawn. (Take care to avoid circular dependencies in this list!)<br />
<br />
{{Note|text=This terminology is often confusing, but, due to historical reasons, cannot be changed. The system does ''not'' draw the Bobs on the Before list first, it draws the Bobs on the After list first. Next, it draws the current Bob, and, finally, the Bobs on the Before list.}}<br />
<br />
For example, to assure that myBob1 always appears in front of myBob2, The Before and After pointers must be initialized so that the system will always draw myBob1 after myBob2.<br />
<br />
<syntaxhighlight><br />
myBob2.Before = &myBob1; /* draw Bob2 before drawing Bob1 */<br />
myBob2.After = NULL; /* draw Bob2 after no other Bob */<br />
myBob1.After = &myBob2; /* draw Bob1 after drawing Bob2 */<br />
myBob1.Before = NULL; /* draw Bob1 before no other Bob */<br />
</syntaxhighlight><br />
<br />
As the system goes through the GelsInfo list, it checks the Bob's After pointer. If this is not NULL, it follows the After pointer until it hits a NULL. Then it starts rendering the Bobs, going back up the Before pointers until it hits a NULL. Then it continues through the GelsInfo list. So, it is important that ''all'' Before and After pointers of a group properly point to each other.<br />
<br />
{{Note|text=In a screen with a number of complex GELs, you may want to specify the Before and After order for Bobs that are not in the same AnimOb. This will keep large objects together. If you do not do this, you may have an object drawn with half of its Bobs in front of another object! Also, in sequences you only set the Before and After pointers for the active AnimComp in the sequence.}}<br />
<br />
=== Adding a Bob ===<br />
<br />
To add a Bob to the system GEL list, use the AddBob() routine. The Bob and VSprite structures must be correct and cohesive when this call is made. See the makeBob() and makeVSprite() routines in the animtools.c file listed at the end of this article for a detailed example of setting up Bobs and VSprites. See the setupGelSys() function for a more complete example of the initialization of the GELs system.<br />
<br />
For example:<br />
<br />
<syntaxhighlight><br />
struct GelsInfo myGelsInfo = {0};<br />
struct VSprite dummySpriteA = {0}, dummySpriteB = {0};<br />
struct Bob myBob = {0};<br />
struct RastPort rastport = {0};<br />
<br />
/* Done ONCE, for this GelsInfo. See setupGelSys() at the end of this<br />
** article for a more complete initialization of the Gel system<br />
*/<br />
IGraphics->InitGels(&dummySpriteA, &dummySpriteB, &myGelsInfo);<br />
<br />
/* Initialize the Bob members here, then AddBob() */<br />
IGraphics->AddBob(&myBob, &rastport);<br />
</syntaxhighlight><br />
<br />
=== Removing a Bob ===<br />
<br />
Two methods may be used to remove a Bob. The first method uses the RemBob() macro. RemBob() causes the system to remove the Bob during the next call to DrawGList() (or two calls to DrawGList() if the system is double-buffered). RemBob() asks the system to remove the Bob at the next convenient time. See the description of the BOBSAWAY and BOBNIX flags above. It is called as follows:<br />
<br />
<syntaxhighlight><br />
struct Bob myBob = {0};<br />
<br />
RemBob(&myBob);<br />
</syntaxhighlight><br />
<br />
The second method uses the RemIBob() routine. RemIBob() tells the system to remove this Bob immediately. For example:<br />
<br />
<syntaxhighlight><br />
struct Bob myBob = {0};<br />
struct RastPort rastport = {0};<br />
struct ViewPort viewport = {0};<br />
<br />
IGraphics->RemIBob(&myBob, &rastport, &viewport);<br />
</syntaxhighlight><br />
<br />
This causes the system to erase the Bob from the drawing area and causes the immediate erasure of any other Bob that had been drawn subsequent to (and on top of) this one. The system then unlinks the Bob from the system GEL list. To redraw the Bobs that were drawn on top of the one just removed, another call to DrawGList() must be made.<br />
<br />
=== Sorting and Displaying Bobs ===<br />
<br />
As with VSprites, the GelsInfo list must be sorted before any Bobs can be displayed. This is accomplished with the SortGList() function. For Bobs, the system uses the position information to decide inter-Bob priorities, if not explicitly set by using the Bob.Before and Bob.After pointers.<br />
<br />
Once the GelsInfo list has been sorted, the Bobs in the list can be displayed by calling DrawGList(). This call should then be followed by a call to WaitTOF() if the application wants to be sure that the Bobs are rendered before proceeding. Call these functions as follows:<br />
<br />
<syntaxhighlight><br />
struct RastPort myRastPort = {0}; /* Of course, these have to be initialized... */<br />
struct ViewPort myViewPort = {0};<br />
<br />
IGraphics->SortGList(&myRastPort);<br />
IGraphics->DrawGList(&myRastPort, &myViewPort); /* Draw the elements (Bobs only) */<br />
IGraphics->WaitTOF();<br />
</syntaxhighlight><br />
<br />
{{Note|title=Warning|text=If your GelsInfo list contains VSprites in addition to Bobs, you must also call MrgCop() and LoadView() to make all the GELs visible. Or, under Intuition, RethinkDisplay() must be called to make all the GELs visible.}}<br />
<br />
=== Changing Bobs ===<br />
<br />
The following characteristics of Bobs can be changed dynamically between calls to DrawGList():<br />
<br />
* To change the location of the Bob in the RastPort drawing area, adjust the x and y values in the VSprite structure associated with this Bob.<br />
* To change a Bob's appearance, the pointer to the ImageData in the associated VSprite structure may be changed. Note that a change in the ImageData also requires a change or recalculation of the ImageShadow, using InitMasks().<br />
* To change a Bob's colors modify the PlanePick, PlaneOnOff or Depth parameters in the VSprite structure associated with this Bob.<br />
* To change a Bob's display priorities, alter the Before and After pointers in the Bob structure.<br />
* To change the Bob into a paintbrush, specify the SAVEBOB flag in the Bob.Flags field.<br />
<br />
{{Note|title=Changes Are Not Immediately Seen|text=Neither these nor other changes are evident until SortGList() and then DrawGList() are called.}}<br />
<br />
=== Complete Bob Example ===<br />
<br />
This example must be linked with "animtools.c" and includes the header files "animtools.h" and "animtools_proto.h". These files are listed at the end of the article.<br />
<br />
<pre><br />
/* bob.c<br />
**<br />
** SAS/C V5.10a<br />
** lc -b1 -cfist -v -y bob.c<br />
** blink FROM LIB:c.o bob.o animtools.o LIB LIB:lc.lib LIB:amiga.lib TO bob<br />
*/<br />
#include &lt;exec/types.h&gt;<br />
#include &lt;exec/memory.h&gt;<br />
#include &lt;intuition/intuitionbase.h&gt;<br />
#include &lt;graphics/gfx.h&gt;<br />
#include &lt;graphics/gfxbase.h&gt;<br />
#include &lt;graphics/gels.h&gt;<br />
#include &lt;libraries/dos.h&gt;<br />
#include &lt;stdlib.h&gt;<br />
#include &quot;animtools.h&quot;<br />
<br />
VOID bobDrawGList(struct RastPort *rport, struct ViewPort *vport);<br />
VOID process_window(struct Window *win, struct Bob *myBob);<br />
VOID do_Bob(struct Window *win);<br />
<br />
struct GfxBase *GfxBase; /* pointer to Graphics library */<br />
struct IntuitionBase *IntuitionBase; /* pointer to Intuition library*/<br />
int return_code;<br />
#define GEL_SIZE 4 /* number of lines in the bob */<br />
<br />
/* Bob data - two sets that are alternated between. Note that this */<br />
/* data is at the resolution of the screen. */<br />
<br />
/* data is 2 planes by 2 words by GEL_SIZE lines */<br />
WORD chip bob_data1[2 * 2 * GEL_SIZE] =<br />
{<br />
/* plane 1 */<br />
0xffff, 0x0003, 0xfff0, 0x0003, 0xfff0, 0x0003, 0xffff, 0x0003,<br />
/* plane 2 */<br />
0x3fff, 0xfffc, 0x3ff0, 0x0ffc, 0x3ff0, 0x0ffc, 0x3fff, 0xfffc<br />
};<br />
<br />
/* data is 2 planes by 2 words by GEL_SIZE lines */<br />
WORD chip bob_data2[2 * 2 * GEL_SIZE] =<br />
{<br />
/* plane 1 */<br />
0xc000, 0xffff, 0xc000, 0x0fff, 0xc000, 0x0fff, 0xc000, 0xffff,<br />
/* plane 2 */<br />
0x3fff, 0xfffc, 0x3ff0, 0x0ffc, 0x3ff0, 0x0ffc, 0x3fff, 0xfffc<br />
};<br />
<br />
NEWBOB myNewBob = /* Data for the new bob structure defined in animtools.h */<br />
{ /* Initial image, WORD width, line height */<br />
bob_data2, 2, GEL_SIZE, /* Image depth, plane pick, plane on off, VSprite flags */<br />
2, 3, 0, SAVEBACK | OVERLAY, /* dbuf (0=false), raster depth, x,y position, hit mask, */<br />
0, 2, 160, 100, 0,0, /* me mask */<br />
};<br />
<br />
struct NewWindow myNewWindow =<br />
{ /* information for the new window */<br />
80, 20, 400, 150, -1, -1, CLOSEWINDOW | INTUITICKS,<br />
ACTIVATE | WINDOWCLOSE | WINDOWDEPTH | RMBTRAP,<br />
NULL, NULL, &quot;Bob&quot;, NULL, NULL, 0, 0, 0, 0, WBENCHSCREEN<br />
};<br />
<br />
/* Draw the Bobs into the RastPort. */<br />
VOID bobDrawGList(struct RastPort *rport, struct ViewPort *vport)<br />
{<br />
SortGList(rport);<br />
DrawGList(rport, vport);<br />
/* If the GelsList includes true VSprites, MrgCop() and LoadView() here */<br />
WaitTOF() ;<br />
}<br />
<br />
/* Process window and dynamically change bob: Get messages. Go away on CLOSEWINDOW.<br />
** Update and redisplay bob on INTUITICKS. Wait for more messages.<br />
*/<br />
VOID process_window(struct Window *win, struct Bob *myBob)<br />
{<br />
struct IntuiMessage *msg;<br />
<br />
FOREVER {<br />
Wait(1L &lt;&lt; win-&gt;UserPort-&gt;mp_SigBit);<br />
while (NULL != (msg = (struct IntuiMessage *)GetMsg(win-&gt;UserPort)))<br />
{<br />
/* only CLOSEWINDOW and INTUITICKS are active */<br />
if (msg-&gt;Class == CLOSEWINDOW)<br />
{<br />
ReplyMsg((struct Message *)msg);<br />
return;<br />
}<br />
/* Must be INTUITICKS: change x and y values on the fly. Note:<br />
** do not have to add window offset, Bob is relative to the<br />
** window (sprite relative to screen).<br />
*/<br />
myBob-&gt;BobVSprite-&gt;X = msg-&gt;MouseX + 20;<br />
myBob-&gt;BobVSprite-&gt;Y = msg-&gt;MouseY + 1;<br />
ReplyMsg((struct Message *)msg);<br />
}<br />
/* after getting a message, change image data on the fly */<br />
myBob-&gt;BobVSprite-&gt;ImageData =<br />
(myBob-&gt;BobVSprite-&gt;ImageData == bob_data1) ? bob_data2 : bob_data1;<br />
InitMasks(myBob-&gt;BobVSprite); /* set up masks for new image */<br />
bobDrawGList(win-&gt;RPort, ViewPortAddress(win));<br />
}<br />
}<br />
<br />
<br />
/* Working with the Bob: setup the GEL system, and get a new Bob (makeBob()).<br />
** Add the bob to the system and display. Use the Bob. When done, remove<br />
** the Bob and update the display without the bob. Cleanup everything.<br />
*/<br />
VOID do_Bob(struct Window *win)<br />
{<br />
struct Bob *myBob;<br />
struct GelsInfo *my_ginfo;<br />
<br />
if (NULL == (my_ginfo = setupGelSys(win-&gt;RPort, 0x03)))<br />
return_code = RETURN_WARN;<br />
else<br />
{<br />
if (NULL == (myBob = makeBob(&amp;myNewBob)))<br />
return_code = RETURN_WARN;<br />
else<br />
{<br />
AddBob(myBob, win-&gt;RPort);<br />
bobDrawGList(win-&gt;RPort, ViewPortAddress(win));<br />
process_window(win, myBob);<br />
RemBob(myBob);<br />
bobDrawGList(win-&gt;RPort, ViewPortAddress(win));<br />
freeBob(myBob, myNewBob.nb_RasDepth);<br />
}<br />
cleanupGelSys(my_ginfo,win-&gt;RPort);<br />
}<br />
}<br />
<br />
<br />
/* Example bob program: First open up the libraries and a window. */<br />
VOID main(int argc, char **argv)<br />
{<br />
struct Window *win;<br />
<br />
return_code = RETURN_OK;<br />
<br />
if (NULL == (GfxBase = (struct GfxBase *)OpenLibrary(GRAPHICSNAME,37L)))<br />
return_code = RETURN_FAIL;<br />
else<br />
{<br />
if (NULL == (IntuitionBase = (struct IntuitionBase *)OpenLibrary(INTUITIONNAME,37L)))<br />
return_code = RETURN_FAIL;<br />
else<br />
{<br />
if (NULL == (win = OpenWindow(&amp;myNewWindow)))<br />
return_code = RETURN_FAIL;<br />
else<br />
{<br />
do_Bob(win);<br />
CloseWindow(win);<br />
}<br />
CloseLibrary((struct Library *)IntuitionBase);<br />
}<br />
CloseLibrary((struct Library *)GfxBase);<br />
}<br />
exit(return_code);<br />
}<br />
</pre><br />
<br />
=== Double-Buffering ===<br />
<br />
Double-buffering is the technique of supplying two different memory areas in which the drawing routines may create images. The system displays one memory space while drawing into the other area. This eliminates the "flickering" that is visible when a single display is being rendered into at the same time that it is being displayed.<br />
<br />
{{Note|title=Double-buffering For One Means Double-buffering For All|text=If any of the Bobs is double-buffered, then ''all'' of them must be double-buffered.}}<br />
<br />
To find whether a Bob is to be double-buffered, the system examines the pointer named DBuffer in the Bob structure. If this pointer has a value of NULL, the system does not use double-buffering for this Bob. For example:<br />
<br />
<syntaxhighlight><br />
myBob.DBuffer = NULL; /* do this if this Bob is NOT double-buffered */<br />
</syntaxhighlight><br />
<br />
==== DBufPacket and Double-Buffering ====<br />
<br />
For double-buffering, a place must be provided for the system to store the extra information it needs. The system maintains these data, and does not expect the application to change them. The DBufPacket structure consists of the following members:<br />
<br />
* BufY, BufX</br>Lets the system keep track of where the object was located "in the last frame" (as compared to the Bob structure members called oldY and oldX that tell where the object was two frames ago). BufY and BufX provide for correct restoration of the background within the currently active drawing buffer.<br />
<br />
* BufPath</br>Assures that the system restores the backgrounds in the correct sequence; it relates to the VSprite members DrawPath and ClearPath.<br />
<br />
* BufBuffer</br>This field must be set to point to a buffer the same size as the Bob's SaveBuffer. This buffer is used to store the background for later restoration when the system moves the object. This buffer must be allocated from Chip memory.<br />
<br />
To create a double-buffered Bob, execute a code sequence similar to the following:<br />
<br />
<syntaxhighlight><br />
struct Bob myBob = {0};<br />
struct DBufPacket myDBufPacket = {0};<br />
<br />
/* Allocate a DBufPacket for myBob same size as previous example */<br />
if (NULL != (myDBufPacket.BufBuffer = IGraphics->AllocRaster(48, 20 * 5)))<br />
{<br />
/* tell Bob about its double buff status */<br />
myBob.DBuffer = myDBufPacket;<br />
}<br />
</syntaxhighlight><br />
<br />
The example routines makeBob() and freeBob() in the animtools.c listing at the end of this article show how to correctly allocate and free a double-buffered Bob.</div>Costel Minceahttps://wiki.amigaos.net/w/index.php?title=Blitter_Objects&diff=11086Blitter Objects2020-03-01T21:18:15Z<p>Costel Mincea: /* DBufPacket and Double-Buffering */</p>
<hr />
<div>== Using Bobs ==<br />
<br />
The following section describes how to define a Bob (blitter object). Like VSprites, a Bob is a software construct designed to make animation easier. The main advantage of a Bob over a VSprite is that it allows more colors and a width greater than 16 pixels to be defined.<br />
<br />
To create a Bob, you need both a Bob structure and a VSprite structure. The components common to all GELs - height, collision-handling information, position in the drawing area and pointers to the image definition - are part of the VSprite structure. The added features - such as drawing sequence, data about saving and restoring the background, and other features not applicable to VSprites - are further specified in the Bob structure.<br />
<br />
=== The VSprite Structure and Bobs ===<br />
<br />
The root VSprite structure is set up as described earlier for true VSprites, with the following exceptions:<br />
<br />
; Y, X<br />
: Bob position is always in pixels that are the same resolution as the display.<br />
<br />
; Flags<br />
: For Bobs, the VSPRITE flag must be cleared. SAVEBACK or OVERLAY can also be used.<br />
<br />
; Height, Width<br />
: Bob pixels are the size of the background pixels. The Width of Bobs may be greater than one word.<br />
<br />
; Depth<br />
: The Depth of a Bob may be up to as deep as the playfield, provided that enough image data is provided.<br />
<br />
; ImageData<br />
: This is still a pointer to the image, but the data there is organized differently.<br />
<br />
; SprColors<br />
: This pointer should be set to NULL for Bobs.<br />
<br />
; VSBob<br />
: This is a pointer to the Bob structure set up as described below.<br />
<br />
=== VSprite Flags and Bobs ===<br />
<br />
The bits in the VSprite.Flags field that apply to a Bob are the VSPRITE flag, the SAVEBACK flag and the OVERLAY flag. When a VSprite structure is used to define a Bob, the VSPRITE flag in the VSprite.Flags field must be set to zero. This tells the system that this GEL is a Bob type.<br />
<br />
To have the GEL routines save the background before the Bob is drawn and restore the background after the Bob is removed, specify the SAVEBACK flag (stands for "save the background") in the VSprite structure Flags field. If this flag is set, the SaveBuffer must have been allocated, which is where the system puts this saved background area. The buffer must be large enough to save all the background bitplanes, regardless of how many planes the Bob has. The size in words can be calculated as follows:<br />
<br />
<syntaxhighlight><br />
/* Note that Bob.Width is in units of words. */<br />
size = Bob.Width * Bob.Height * RastPort.BitMap.Depth;<br />
</syntaxhighlight><br />
<br />
To allocate this space, the graphics function AllocRaster() can be used. AllocRaster() takes the width in bits, so it is a convenient way to allocate the space needed. The makeBob() routine below shows another way to correctly allocate this buffer. For example:<br />
<br />
<syntaxhighlight><br />
/* space for 16 bits times 5 lines times 5 bitplanes */<br />
myBob.SaveBuffer = AllocRaster( 16, (5 * 5) );<br />
</syntaxhighlight><br />
<br />
{{Note|title=Warning|text=The SaveBuffer must be allocated from Chip memory and contain an even number of word-aligned bytes. The AllocRaster() function does this for you. The AllocRaster() function rounds the width value up to the next integer multiple of 16 bits which is greater than or equal to the current value an it obtains memory from the Chip memory pool.}}<br />
<br />
OVERLAY is the other VSprite.Flags item that applies to Bobs. If this flag is set, it means that the background's original pixels show through in any area where there are 0 bits in the Bob's shadow mask (ImageShadow, explained later). The space for the ImageShadow shadow mask must have been allocated and initialized. The ImageShadow mask must be allocated from Chip memory.<br />
<br />
If the OVERLAY bit is cleared, the system uses the ''entire rectangle of words'' that define the Bob image to ''replace'' the playfield area at the specified ''x,y'' coordinates. See the paragraphs below called "ImageShadow."<br />
<br />
=== The Bob Structure ===<br />
<br />
The Bob structure is defined in the include file &lt;graphics/gels.h&gt; as follows:<br />
<br />
<syntaxhighlight><br />
struct Bob<br />
{<br />
WORD Flags; /* general purpose flags */<br />
WORD *SaveBuffer;/* buffer for background save */<br />
WORD *ImageShadow; /* shadow mask of image */<br />
struct Bob *Before; /* draw this Bob before Bobs on this list */<br />
struct Bob *After; /* draw this Bob after Bobs on this list */<br />
struct VSprite *BobVSprite;/* this Bob's VSprite definition */<br />
struct AnimComp *BobComp; /* pointer to this Bob's AnimComp def */<br />
struct DBufPacket *DBuffer; /* pointer to this Bob's dBuf packet */<br />
BUserStuff BUserExt; /* Bob user extension */<br />
};<br />
</syntaxhighlight><br />
<br />
The Bob structure itself does not need to be in Chip memory. The (global) static declaration of a Bob structure could be done like so:<br />
<br />
<syntaxhighlight><br />
struct Bob myBob =<br />
{<br />
0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0<br />
};<br />
</syntaxhighlight><br />
<br />
However, since most of the Bob structure members are pointers, it is more common to allocate and set the Bob up dynamically. Refer to the makeBob() and freeBob() functions in the "animtools.c" example at the end of the article for an example of allocating, initializing and freeing a Bob structure.<br />
<br />
==== Linking Bob and VSprite Structures ====<br />
<br />
The VSprite and Bob structures must point to one another, so that the system can find the entire GEL. The structures are linked with statements like this:<br />
<br />
<syntaxhighlight><br />
myBob.BobVSprite = &myVSprite;<br />
myVSprite.VSBob = &myBob;<br />
</syntaxhighlight><br />
<br />
Now the system (and the application program) can go back and forth between the two structures to obtain the various Bob variables.<br />
<br />
=== Using Bob Flags ===<br />
<br />
The following paragraphs describe how to set the Flags field in the Bob structure (note that these flags do not apply to the Flags field of the VSprite structure).<br />
<br />
To tell the system not to erase the old image of the Bob when the Bob is moved, specify the SAVEBOB flag in the Bob structure Flags field. This makes the Bob behave like a paintbrush. It has the opposite effect of SAVEBACK.<br />
<br />
{{Note|title=It's Faster To Draw A New Bob|text=It takes longer to preserve and restore the raster image than simply to draw a new Bob image wherever required.}}<br />
<br />
If this Bob is part of an AnimComp, set the BOBISCOMP flag in the Bob structure to 1. If the flag is a 1, the pointer named BobComp must have been initialized. Otherwise, the system ignores the pointer, and it may be left alone (though it's good practice to initialize it to NULL). See "Animation Structures and Controls" for a discussion of AnimComps.<br />
<br />
This flag is used solely by the system, and should be left alone. When a Bob is waiting to be drawn, the system sets the BWAITING flag in the Bob structure to 1. This occurs only if the system has found a Before pointer in this Bob's structure that points to another Bob. Thus, the system flag BWAITING provides current draw-status to the system. Currently, the system clears this flag on return from each call to DrawGList().<br />
<br />
This is a system status flag that indicates to the system whether or not this Bob has already been drawn. Therefore, in the process of examining the various Before and After flags, the drawing routines can determine the drawing sequence. The system clears this flag on return from each call to DrawGList().<br />
<br />
To initiate the removal of a Bob during the next call to DrawGList(), set BOBSAWAY to 1. Either the application or the system may set this Bob structure system flag. The system restores the background where it has last drawn the Bob. The system will unlink the Bob from the system GEL list the next time DrawGList() is called, unless the application is using double-buffering. In that case, the Bob will not be unlinked and completely removed until two calls to DrawGList() have occurred and the Bob has been removed from both buffers. The RemBob() macro sets the BOBSAWAY flag.<br />
<br />
When a Bob has been completely removed, the system sets the BOBNIX flag to 1 on return from DrawGList(). In other words, when the background area has been fully restored and the Bob has been removed from the GEL list, this flag in is set to a 1. BOBNIX is especially significant when double-buffering because when an application asks for a Bob to be removed, the system must remove it from both the drawing buffer ''and'' from the display buffer. Once BOBNIX has been set, it means the Bob has been removed from both buffers and the application is free to reuse or deallocate the Bob.<br />
<br />
The SAVEPRESERVE flag is a double-buffer version of the SAVEBACK flag. If using double-buffering and wishing to save and restore the background, set SAVEBACK to 1. SAVEPRESERVE is used by the system to indicate whether the Bob in the "other" buffer has been restored; it is for system use only.<br />
<br />
=== Specifying the Size of a Bob ===<br />
<br />
Bobs do not have the 16-pixel width limit that applies to VSprites. To specify the overall size of a Bob, use the Height and Width members of the root VSprite structure. Specify the Width as the number of 16-bit words it takes to fully contain the object. The number of lines is still specified with the Height member in the VSprite data structure.<br />
<br />
As an example, suppose the Bob is 24 pixels wide and 20 lines tall. Use statements like the following to specify the size:<br />
<br />
<syntaxhighlight><br />
myVSprite.Height = 20; /* 20 lines tall. */<br />
myVSprite.Width = 2; /* 24 bits fit into two words. */<br />
</syntaxhighlight><br />
<br />
Because Bobs are drawn into the background playfield, the pixels of the Bob are the same size as the background pixels, and share the color palette of the ViewPort.<br />
<br />
=== Specifying the Shape of a Bob ===<br />
<br />
The layout of the data of a Bob's image is different from that of a VSprite because of the way the system retrieves data to draw Bobs. VSprite images are organized in a way convenient to the Sprite hardware; Bob images are set up for easy blitter manipulation. The ImageData pointer is still initialized to point to the first word of the image definition.<br />
<br />
{{Note|text=As with all image data, a Bob’s ImageData must be in Chip memory for access by the blitter.}}<br />
<br />
The sample image below shows the same image defined as a VSprite in the "Using Virtual Sprites" section above. The data here, however, is laid out for a Bob. The shape is 2 planes deep and is triangular:<br />
<br />
<pre><br />
<first bitplane data><br />
<br />
mem 1111 1111 1111 1111 Least significant bit of sprite line 1<br />
mem + 1 0011 1100 0011 1100 Least significant bit of sprite line 2<br />
mem + 2 0000 1100 0011 0000 Least significant bit of sprite line 3<br />
mem + 3 0000 0010 0100 0000 Least significant bit of sprite line 4<br />
mem + 4 0000 0001 1000 0000 Least significant bit of sprite line 5<br />
<br />
<second bitplane data><br />
<br />
mem + 5 1111 1111 1111 1111 Most significant bit of sprite line 1<br />
mem + 6 0011 0000 0000 1100 Most significant bit of sprite line 2<br />
mem + 7 0000 1111 1111 0000 Most significant bit of sprite line 3<br />
mem + 8 0000 0011 1100 0000 Most significant bit of sprite line 4<br />
mem + 9 0000 0001 1000 0000 Most significant bit of sprite line 5<br />
<br />
<more bitplanes of data if Bob is deeper><br />
</pre><br />
<br />
=== Specifying the Colors of a Bob ===<br />
<br />
Typically a five-bitplane, low-resolution mode display allows playfield pixels (and therefore, Bob pixels) to be selected from any of 32 active colors out of a system palette of 4,096 different color choices. Bob colors are limited to the colors used in the background playfield.<br />
<br />
The system ignores the sprColors member of the VSprite structure when the VSprite structure is the root of a Bob. Instead, the Bob's colors are determined by the combination of the Depth of the Bob image and its PlanePick, PlaneOnOff and ImageShadow members.<br />
<br />
Use the Depth member in the VSprite structure to indicate how many planes of image data is provided to define the Bob. This also defines how many colors the Bob will have. The combination of bits in corresponding ''x,y'' positions in each bitplane determines the color of the pixel at that position.<br />
<br />
For example, if a Depth of one plane is specified, then the bits of that image allow only two colors to be selected: one color for each bit that is a 0, a second color for each bit that is a 1. Likewise, if there are 5 planes of image data, all 32 colors can be used in the Bob. The Bob Depth must not exceed the background depth. Specify Depth using a statement such as the following:<br />
<br />
<syntaxhighlight><br />
myVSprite.Depth = 5; /* Allow a 32 color, 5-bitplane image. */<br />
</syntaxhighlight><br />
<br />
=== Other Items Influencing Bob Colors ===<br />
<br />
The three other members in the VSprite structure that affect the color of Bob pixels are ImageShadow, PlanePick, and PlaneOnOff.<br />
<br />
==== ImageShadow ====<br />
<br />
The ImageShadow member is a pointer to the shadow mask of a Bob. A shadow mask is the logical ''or'' of all bitplanes of a Bob image. The system uses the shadow mask in conjunction with PlaneOnOff, discussed below, for color selection. It also uses the shadow mask to "cookie cut" the bits that will be overwritten by this Bob, to save and later restore the background.<br />
<br />
The following figure shows the shadow mask of the image described above.<br />
<br />
<pre><br />
mem + 0 1111 1111 1111 1111 Shadow mask for line 1<br />
mem + 1 0011 1100 0011 1100 Shadow mask for line 2<br />
mem + 2 0000 1111 1111 0000 Shadow mask for line 3<br />
mem + 3 0000 0011 1100 0000 Shadow mask for line 4<br />
mem + 4 0000 0001 1000 0000 Shadow mask for line 5<br />
</pre><br />
<br />
Space for the ImageShadow must be provided and this pointer initialized to point to it. The amount of memory needed is equivalent to one plane of the image:<br />
<br />
<pre><br />
shadow_size = myBob-&gt;BobVSprite-&gt;Height * myBob-&gt;BobVSprite-&gt;Width;<br />
</pre><br />
<br />
The example image is 5 high and 1 word wide, so, 5 words must be made available.<br />
<br />
{{Note|text=The ImageShadow memory must be allocated from Chip memory (MEMF_CHIP).}}<br />
<br />
==== PlanePick ====<br />
<br />
Because the Depth of the Bob can be less than the background, the PlanePick member is provided so that the application can indicate which background bitplanes are to have image data put into them. The system starts with the least significant plane of the Bob, and scans PlanePick starting at the least significant bit, looking for a plane of the RastPort to put it in.<br />
<br />
For example, if PlanePick has a binary value of: 0 0 0 0 0 0 1 1 (0x03) then the system draws the first plane of the Bob's image into background plane 0 and the second plane into background plane 1.<br />
<br />
Alternatively, a PlanePick value of: 0 0 0 1 0 0 1 0 (0x12) directs the system to put the first Bob plane into plane 1, and the second Bob plane into plane 4.<br />
<br />
==== PlaneOnOff ====<br />
<br />
What happens to the background planes that aren't picked? The shadow mask is used to either set or clear the bits in those planes in the exact shape of the Bob if OVERLAY is set, otherwise the entire rectangle containing the Bob is used. The PlaneOnOff member tells the system whether to put down the shadow mask as zeros or ones for each plane. The relationship between bit positions in PlaneOnOff and background plane numbers is identical to PlanePick: the least significant bit position indicates the lowest-numbered bitplane. A zero bit clears the shadow mask shape in the corresponding plane, while a one bit sets the shadow mask shape. The planes Picked by PlanePick have image data - not shadow mask - blitted in.<br />
<br />
This provides a great deal of color versatility. One image definition can be used for many Bobs. By having different PlanePick / PlaneOnOff combinations, each Bob can use a different subset of the background color set.<br />
<br />
There is a member in the VSprite structure called CollMask (the collision mask, covered under "Detecting GEL Collisions") for which the application may also reserve some memory space. The ImageShadow and CollMask pointers usually, but not necessarily, point to the same data, which must be located in Chip memory. If they point to the same location, obviously, the memory only need be allocated once.<br />
<br />
An example of the kinds of statements that accomplish these actions (see the makeVSprite() and makeBob() examples for more details):<br />
<br />
<syntaxhighlight><br />
#define BOBW 1<br />
#define BOBH 5<br />
#define BOBD 2<br />
<br />
/* Data definition from example layout */<br />
uint16 chip BobData[]=<br />
{<br />
0xFFFF, 0x300C, 0x0FF0, 0x03C0, 0x0180,<br />
0xFFFF, 0x3E7C, 0x0C30, 0x03C0, 0x0180<br />
};<br />
<br />
/* Reserve space for the collision mask for this Bob */<br />
uint16 chip BobCollision[BOBW * BOBH];<br />
<br />
myVSprite.Width = BOBW; /* Image is 16 pixels wide (1 word) */<br />
myVSprite.Height = BOBH; /* 5 lines for each plane of the Bob */<br />
myVSprite.Depth = BOBD; /* 2 Planes are in ImageData */<br />
<br />
/* Show the system where it can find the data image of the Bob */<br />
myVSprite.ImageData = BobData;<br />
<br />
/* binary 0101, render image data into bitplanes 0 and 2 */<br />
myVSprite.PlanePick = 0x05;<br />
<br />
/* binary 0000, means colors 1, 4, and 5 will be used.<br />
* binary 0010 would mean colors 3, 6, and 7.<br />
* " 1000 " " " 9, C, and D.<br />
* " 1010 " " " B, E, and F.<br />
*/<br />
myVSprite.PlaneOnOff = 0x00;<br />
<br />
/* Where to put collision mask */<br />
myVSprite.CollMask = BobCollision;<br />
<br />
/* Tell the system where it can assemble a GEL shadow */<br />
/* Point to same area as CollMask */<br />
myBob.ImageShadow = BobCollision;<br />
<br />
/* Create the Sprite collision mask in the VSprite structure */<br />
IGraphics->InitMasks(&myVSprite);<br />
</syntaxhighlight><br />
<br />
=== Bob Priorities ===<br />
<br />
This subsection describes the choices for inter-Bob priorities. The inter-Bob priorities tell the system what order to render the Bobs. Bobs rendered earlier will appear to be behind later Bobs. A Bob drawn earlier is said to have the lower priority and a Bob drawn later is said to have the higher priority. Thus, the highest priority Bob will be drawn last and will never be obstructed by another Bob.<br />
<br />
==== Letting the System Decide Priorities ====<br />
<br />
The priority issue can be ignored and the system will render the Bobs as it finds them in the GelsInfo list. To do this, set the Bob’s Before and After pointers to NULL. Since the GelsInfo list is sorted by GEL x, y values, Bobs that are higher on the display will appear behind the lower ones, and Bobs that are more to the left on the display will appear behind Bobs on the right.<br />
<br />
As Bobs are moved about the display, their priorities will change.<br />
<br />
==== Specifying the Drawing Order ====<br />
<br />
To specify the priorities of the Bobs, use the Before and After pointers. Before points to the Bob that this Bob should be drawn before, and After points to the Bob that this Bob should be drawn after. By following these pointers, from Bob to Bob, the system can determine the order in which the Bobs should be drawn. (Take care to avoid circular dependencies in this list!)<br />
<br />
{{Note|text=This terminology is often confusing, but, due to historical reasons, cannot be changed. The system does ''not'' draw the Bobs on the Before list first, it draws the Bobs on the After list first. Next, it draws the current Bob, and, finally, the Bobs on the Before list.}}<br />
<br />
For example, to assure that myBob1 always appears in front of myBob2, The Before and After pointers must be initialized so that the system will always draw myBob1 after myBob2.<br />
<br />
<syntaxhighlight><br />
myBob2.Before = &myBob1; /* draw Bob2 before drawing Bob1 */<br />
myBob2.After = NULL; /* draw Bob2 after no other Bob */<br />
myBob1.After = &myBob2; /* draw Bob1 after drawing Bob2 */<br />
myBob1.Before = NULL; /* draw Bob1 before no other Bob */<br />
</syntaxhighlight><br />
<br />
As the system goes through the GelsInfo list, it checks the Bob's After pointer. If this is not NULL, it follows the After pointer until it hits a NULL. Then it starts rendering the Bobs, going back up the Before pointers until it hits a NULL. Then it continues through the GelsInfo list. So, it is important that ''all'' Before and After pointers of a group properly point to each other.<br />
<br />
{{Note|text=In a screen with a number of complex GELs, you may want to specify the Before and After order for Bobs that are not in the same AnimOb. This will keep large objects together. If you do not do this, you may have an object drawn with half of its Bobs in front of another object! Also, in sequences you only set the Before and After pointers for the active AnimComp in the sequence.}}<br />
<br />
=== Adding a Bob ===<br />
<br />
To add a Bob to the system GEL list, use the AddBob() routine. The Bob and VSprite structures must be correct and cohesive when this call is made. See the makeBob() and makeVSprite() routines in the animtools.c file listed at the end of this article for a detailed example of setting up Bobs and VSprites. See the setupGelSys() function for a more complete example of the initialization of the GELs system.<br />
<br />
For example:<br />
<br />
<syntaxhighlight><br />
struct GelsInfo myGelsInfo = {0};<br />
struct VSprite dummySpriteA = {0}, dummySpriteB = {0};<br />
struct Bob myBob = {0};<br />
struct RastPort rastport = {0};<br />
<br />
/* Done ONCE, for this GelsInfo. See setupGelSys() at the end of this<br />
** article for a more complete initialization of the Gel system<br />
*/<br />
IGraphics->InitGels(&dummySpriteA, &dummySpriteB, &myGelsInfo);<br />
<br />
/* Initialize the Bob members here, then AddBob() */<br />
IGraphics->AddBob(&myBob, &rastport);<br />
</syntaxhighlight><br />
<br />
=== Removing a Bob ===<br />
<br />
Two methods may be used to remove a Bob. The first method uses the RemBob() macro. RemBob() causes the system to remove the Bob during the next call to DrawGList() (or two calls to DrawGList() if the system is double-buffered). RemBob() asks the system to remove the Bob at the next convenient time. See the description of the BOBSAWAY and BOBNIX flags above. It is called as follows:<br />
<br />
<syntaxhighlight><br />
struct Bob myBob = {0};<br />
<br />
RemBob(&myBob);<br />
</syntaxhighlight><br />
<br />
The second method uses the RemIBob() routine. RemIBob() tells the system to remove this Bob immediately. For example:<br />
<br />
<syntaxhighlight><br />
struct Bob myBob = {0};<br />
struct RastPort rastport = {0};<br />
struct ViewPort viewport = {0};<br />
<br />
IGraphics->RemIBob(&myBob, &rastport, &viewport);<br />
</syntaxhighlight><br />
<br />
This causes the system to erase the Bob from the drawing area and causes the immediate erasure of any other Bob that had been drawn subsequent to (and on top of) this one. The system then unlinks the Bob from the system GEL list. To redraw the Bobs that were drawn on top of the one just removed, another call to DrawGList() must be made.<br />
<br />
=== Sorting and Displaying Bobs ===<br />
<br />
As with VSprites, the GelsInfo list must be sorted before any Bobs can be displayed. This is accomplished with the SortGList() function. For Bobs, the system uses the position information to decide inter-Bob priorities, if not explicitly set by using the Bob.Before and Bob.After pointers.<br />
<br />
Once the GelsInfo list has been sorted, the Bobs in the list can be displayed by calling DrawGList(). This call should then be followed by a call to WaitTOF() if the application wants to be sure that the Bobs are rendered before proceeding. Call these functions as follows:<br />
<br />
<syntaxhighlight><br />
struct RastPort myRastPort = {0}; /* Of course, these have to be initialized... */<br />
struct ViewPort myViewPort = {0};<br />
<br />
IGraphics->SortGList(&myRastPort);<br />
IGraphics->DrawGList(&myRastPort, &myViewPort); /* Draw the elements (Bobs only) */<br />
IGraphics->WaitTOF();<br />
</syntaxhighlight><br />
<br />
{{Note|title=Warning|text=If your GelsInfo list contains VSprites in addition to Bobs, you must also call MrgCop() and LoadView() to make all the GELs visible. Or, under Intuition, RethinkDisplay() must be called to make all the GELs visible.}}<br />
<br />
=== Changing Bobs ===<br />
<br />
The following characteristics of Bobs can be changed dynamically between calls to DrawGList():<br />
<br />
* To change the location of the Bob in the RastPort drawing area, adjust the x and y values in the VSprite structure associated with this Bob.<br />
* To change a Bob's appearance, the pointer to the ImageData in the associated VSprite structure may be changed. Note that a change in the ImageData also requires a change or recalculation of the ImageShadow, using InitMasks().<br />
* To change a Bob's colors modify the PlanePick, PlaneOnOff or Depth parameters in the VSprite structure associated with this Bob.<br />
* To change a Bob's display priorities, alter the Before and After pointers in the Bob structure.<br />
* To change the Bob into a paintbrush, specify the SAVEBOB flag in the Bob.Flags field.<br />
<br />
{{Note|title=Changes Are Not Immediately Seen|text=Neither these nor other changes are evident until SortGList() and then DrawGList() are called.}}<br />
<br />
=== Complete Bob Example ===<br />
<br />
This example must be linked with "animtools.c" and includes the header files "animtools.h" and "animtools_proto.h". These files are listed at the end of the article.<br />
<br />
<pre><br />
/* bob.c<br />
**<br />
** SAS/C V5.10a<br />
** lc -b1 -cfist -v -y bob.c<br />
** blink FROM LIB:c.o bob.o animtools.o LIB LIB:lc.lib LIB:amiga.lib TO bob<br />
*/<br />
#include &lt;exec/types.h&gt;<br />
#include &lt;exec/memory.h&gt;<br />
#include &lt;intuition/intuitionbase.h&gt;<br />
#include &lt;graphics/gfx.h&gt;<br />
#include &lt;graphics/gfxbase.h&gt;<br />
#include &lt;graphics/gels.h&gt;<br />
#include &lt;libraries/dos.h&gt;<br />
#include &lt;stdlib.h&gt;<br />
#include &quot;animtools.h&quot;<br />
<br />
VOID bobDrawGList(struct RastPort *rport, struct ViewPort *vport);<br />
VOID process_window(struct Window *win, struct Bob *myBob);<br />
VOID do_Bob(struct Window *win);<br />
<br />
struct GfxBase *GfxBase; /* pointer to Graphics library */<br />
struct IntuitionBase *IntuitionBase; /* pointer to Intuition library*/<br />
int return_code;<br />
#define GEL_SIZE 4 /* number of lines in the bob */<br />
<br />
/* Bob data - two sets that are alternated between. Note that this */<br />
/* data is at the resolution of the screen. */<br />
<br />
/* data is 2 planes by 2 words by GEL_SIZE lines */<br />
WORD chip bob_data1[2 * 2 * GEL_SIZE] =<br />
{<br />
/* plane 1 */<br />
0xffff, 0x0003, 0xfff0, 0x0003, 0xfff0, 0x0003, 0xffff, 0x0003,<br />
/* plane 2 */<br />
0x3fff, 0xfffc, 0x3ff0, 0x0ffc, 0x3ff0, 0x0ffc, 0x3fff, 0xfffc<br />
};<br />
<br />
/* data is 2 planes by 2 words by GEL_SIZE lines */<br />
WORD chip bob_data2[2 * 2 * GEL_SIZE] =<br />
{<br />
/* plane 1 */<br />
0xc000, 0xffff, 0xc000, 0x0fff, 0xc000, 0x0fff, 0xc000, 0xffff,<br />
/* plane 2 */<br />
0x3fff, 0xfffc, 0x3ff0, 0x0ffc, 0x3ff0, 0x0ffc, 0x3fff, 0xfffc<br />
};<br />
<br />
NEWBOB myNewBob = /* Data for the new bob structure defined in animtools.h */<br />
{ /* Initial image, WORD width, line height */<br />
bob_data2, 2, GEL_SIZE, /* Image depth, plane pick, plane on off, VSprite flags */<br />
2, 3, 0, SAVEBACK | OVERLAY, /* dbuf (0=false), raster depth, x,y position, hit mask, */<br />
0, 2, 160, 100, 0,0, /* me mask */<br />
};<br />
<br />
struct NewWindow myNewWindow =<br />
{ /* information for the new window */<br />
80, 20, 400, 150, -1, -1, CLOSEWINDOW | INTUITICKS,<br />
ACTIVATE | WINDOWCLOSE | WINDOWDEPTH | RMBTRAP,<br />
NULL, NULL, &quot;Bob&quot;, NULL, NULL, 0, 0, 0, 0, WBENCHSCREEN<br />
};<br />
<br />
/* Draw the Bobs into the RastPort. */<br />
VOID bobDrawGList(struct RastPort *rport, struct ViewPort *vport)<br />
{<br />
SortGList(rport);<br />
DrawGList(rport, vport);<br />
/* If the GelsList includes true VSprites, MrgCop() and LoadView() here */<br />
WaitTOF() ;<br />
}<br />
<br />
/* Process window and dynamically change bob: Get messages. Go away on CLOSEWINDOW.<br />
** Update and redisplay bob on INTUITICKS. Wait for more messages.<br />
*/<br />
VOID process_window(struct Window *win, struct Bob *myBob)<br />
{<br />
struct IntuiMessage *msg;<br />
<br />
FOREVER {<br />
Wait(1L &lt;&lt; win-&gt;UserPort-&gt;mp_SigBit);<br />
while (NULL != (msg = (struct IntuiMessage *)GetMsg(win-&gt;UserPort)))<br />
{<br />
/* only CLOSEWINDOW and INTUITICKS are active */<br />
if (msg-&gt;Class == CLOSEWINDOW)<br />
{<br />
ReplyMsg((struct Message *)msg);<br />
return;<br />
}<br />
/* Must be INTUITICKS: change x and y values on the fly. Note:<br />
** do not have to add window offset, Bob is relative to the<br />
** window (sprite relative to screen).<br />
*/<br />
myBob-&gt;BobVSprite-&gt;X = msg-&gt;MouseX + 20;<br />
myBob-&gt;BobVSprite-&gt;Y = msg-&gt;MouseY + 1;<br />
ReplyMsg((struct Message *)msg);<br />
}<br />
/* after getting a message, change image data on the fly */<br />
myBob-&gt;BobVSprite-&gt;ImageData =<br />
(myBob-&gt;BobVSprite-&gt;ImageData == bob_data1) ? bob_data2 : bob_data1;<br />
InitMasks(myBob-&gt;BobVSprite); /* set up masks for new image */<br />
bobDrawGList(win-&gt;RPort, ViewPortAddress(win));<br />
}<br />
}<br />
<br />
<br />
/* Working with the Bob: setup the GEL system, and get a new Bob (makeBob()).<br />
** Add the bob to the system and display. Use the Bob. When done, remove<br />
** the Bob and update the display without the bob. Cleanup everything.<br />
*/<br />
VOID do_Bob(struct Window *win)<br />
{<br />
struct Bob *myBob;<br />
struct GelsInfo *my_ginfo;<br />
<br />
if (NULL == (my_ginfo = setupGelSys(win-&gt;RPort, 0x03)))<br />
return_code = RETURN_WARN;<br />
else<br />
{<br />
if (NULL == (myBob = makeBob(&amp;myNewBob)))<br />
return_code = RETURN_WARN;<br />
else<br />
{<br />
AddBob(myBob, win-&gt;RPort);<br />
bobDrawGList(win-&gt;RPort, ViewPortAddress(win));<br />
process_window(win, myBob);<br />
RemBob(myBob);<br />
bobDrawGList(win-&gt;RPort, ViewPortAddress(win));<br />
freeBob(myBob, myNewBob.nb_RasDepth);<br />
}<br />
cleanupGelSys(my_ginfo,win-&gt;RPort);<br />
}<br />
}<br />
<br />
<br />
/* Example bob program: First open up the libraries and a window. */<br />
VOID main(int argc, char **argv)<br />
{<br />
struct Window *win;<br />
<br />
return_code = RETURN_OK;<br />
<br />
if (NULL == (GfxBase = (struct GfxBase *)OpenLibrary(GRAPHICSNAME,37L)))<br />
return_code = RETURN_FAIL;<br />
else<br />
{<br />
if (NULL == (IntuitionBase = (struct IntuitionBase *)OpenLibrary(INTUITIONNAME,37L)))<br />
return_code = RETURN_FAIL;<br />
else<br />
{<br />
if (NULL == (win = OpenWindow(&amp;myNewWindow)))<br />
return_code = RETURN_FAIL;<br />
else<br />
{<br />
do_Bob(win);<br />
CloseWindow(win);<br />
}<br />
CloseLibrary((struct Library *)IntuitionBase);<br />
}<br />
CloseLibrary((struct Library *)GfxBase);<br />
}<br />
exit(return_code);<br />
}<br />
</pre><br />
<br />
=== Double-Buffering ===<br />
<br />
Double-buffering is the technique of supplying two different memory areas in which the drawing routines may create images. The system displays one memory space while drawing into the other area. This eliminates the "flickering" that is visible when a single display is being rendered into at the same time that it is being displayed.<br />
<br />
{{Note|title=Double-buffering For One Means Double-buffering For All|text=If any of the Bobs is double-buffered, then ''all'' of them must be double-buffered.}}<br />
<br />
To find whether a Bob is to be double-buffered, the system examines the pointer named DBuffer in the Bob structure. If this pointer has a value of NULL, the system does not use double-buffering for this Bob. For example:<br />
<br />
<syntaxhighlight><br />
myBob.DBuffer = NULL; /* do this if this Bob is NOT double-buffered */<br />
</syntaxhighlight><br />
<br />
==== DBufPacket and Double-Buffering ====<br />
<br />
For double-buffering, a place must be provided for the system to store the extra information it needs. The system maintains these data, and does not expect the application to change them. The DBufPacket structure consists of the following members:<br />
<br />
BufY, BufX<br />
Lets the system keep track of where the object was located "in the last frame" (as compared to the Bob structure members called oldY and oldX that tell where the object was two frames ago). BufY and BufX provide for correct restoration of the background within the currently active drawing buffer.<br />
<br />
BufPath<br />
Assures that the system restores the backgrounds in the correct sequence; it relates to the VSprite members DrawPath and ClearPath.<br />
<br />
BufBuffer<br />
This field must be set to point to a buffer the same size as the Bob's SaveBuffer. This buffer is used to store the background for later restoration when the system moves the object. This buffer must be allocated from Chip memory.<br />
<br />
To create a double-buffered Bob, execute a code sequence similar to the following:<br />
<br />
<syntaxhighlight><br />
struct Bob myBob = {0};<br />
struct DBufPacket myDBufPacket = {0};<br />
<br />
/* Allocate a DBufPacket for myBob same size as previous example */<br />
if (NULL != (myDBufPacket.BufBuffer = IGraphics->AllocRaster(48, 20 * 5)))<br />
{<br />
/* tell Bob about its double buff status */<br />
myBob.DBuffer = myDBufPacket;<br />
}<br />
</syntaxhighlight><br />
<br />
The example routines makeBob() and freeBob() in the animtools.c listing at the end of this article show how to correctly allocate and free a double-buffered Bob.</div>Costel Minceahttps://wiki.amigaos.net/w/index.php?title=UserDoc:Main&diff=9151UserDoc:Main2017-06-10T16:02:59Z<p>Costel Mincea: /* AmigaOS platform targets */</p>
<hr />
<div>== Welcome to AmigaOS ==<br />
<br />
AmigaOS was born in 1985 and delivered what contemporary personal computer operating systems could only dream of. As the first "multimedia" operating system, it was trivial for AmigaOS computers to display animations while playing music and reading data from disks. Such multimedia and multitasking finesse drew many people to this system. Some of them are famous: [http://www.amigahistory.co.uk/warhol.html Andy Warhol], Sir Arthur C. Clarke, [http://www.polyphoto.com/upchug/AEcastro.html NASA], Hollywood and the TV broadcasting industry, and many others that thought [http://www.youtube.com/watch?v=PWeO5IkCssk only Amiga makes it possible].<br />
<br />
Today many people still think AmigaOS has something special that makes it more interesting and rewarding than other systems. This system allows the user to control the computer, not the other way around. It is a system you fully understand that is easier and more flexible to use. In other words, AmigaOS is '''more fun'''.<br />
<br />
=== AmigaOS: The flexible operating system ===<br />
AmigaOS is an operating system: a collection of efficient programs written to start the computer, let the user control the computer, and present feedback to the user.<br />
<br />
AmigaOS is designed with ease of use and flexibility in mind. To begin with, AmigaOS provides a clear view of your computer, your applications and files. A number of methods are available to let your computer serve you, whether graphically with a mouse, using the "Shell" command line, or by some other means the user prefers.<br />
<br />
AmigaOS strives to avoid stupid limitations that can be found on other systems. AmigaOS users can organise their files the way they like. There are few limits on file hierarchy, locations and file names. Drives don't have to be named with a letter or cryptic names (such as C:, or sda1), your files don't have to reside in your "Documents" folder and your hard drives aren't hidden from you. If you're not writing to drives and you want to "shut down", why wait for the OS to allow that? With AmigaOS, just hit the power switch. Done.<br />
<br />
An Amiga does not start with pre-installed applications serving some sales conglomerate, marketing organization or their big brother. AmigaOS does not do actions behind the user's back. As unique as it is today, the AmigaOS computer serves the user and not the other way around. With one of the largest proportions of user-programmers around, the trustworthy AmigaOS user-friendly ethic is mirrored in AmigaOS applications.<br />
<br />
Since the first versions more than twenty-five years ago, AmigaOS has also been designed to serve efficiently. Optimizing applications and OS code has always been the goal of programmers and developers of this operating system. The result is an operating system and applications that take less space on your hard drives, waste less time loading, consume less memory, require less processing power, and respond more quickly to the user.<br />
<br />
And every update of AmigaOS doesn't demand you must buy newer, more powerful hardware. AmigaOS currently runs on twenty year old 200MHz computers or brand new dual core 1,800MHz computers. It's the user's choice how they want to '''enjoy''' AmigaOS.<br />
<br />
=== Some AmigaOS features ===<br />
Here are some of the features of AmigaOS that make it easy to control your computer. Some of these concepts were copied by other operating systems which tend to show they are the correct way of doing things.<br />
<br />
* '''Small footprint:''' AmigaOS can work with 64 MB of memory. On disk, a default installation only takes around 200 MB. The smaller footprint translates into a more responsive user experience given any hardware.<br />
<br />
* '''Straightforward operating system design:''' With a clear layout and easy to understand names (Classes, Libs, Fonts, Prefs, Storage, etc.), you can easily understand what everything in AmigaOS is and what it does for you. Nothing is hidden from the user and the user is not restricted by AmigaOS.<br />
<br />
*'''User configurable graphic interface:''' Using the provided "preferences editors," the user can dramatically reconfigure how AmigaOS looks, sounds, runs and responds to every user whim.<br />
<br />
* '''File recognition based on file content:''' You can name a file '''whatever you want''', even without an extension. Examples: "my file" or "picture of Jay in Santa Clara". There is no need to add an extension to explain what the file is, like ".txt" or ".jpg". AmigaOS really examines the '''file content''' to recognise what type of file it is. <br />
<br />
* '''Logical assignments:''' Easily set and use logical names names for directories located anywhere on your system. For example, "Auto:" can point to your directory "car show pictures" buried on your media drive.<br />
<br />
* '''Ram disk concept:''' On AmigaOS there is a special disk called the '''Ram disk''' which represents a part of your computer memory. This area is not fixed. It automatically grows whenever you store files in it. For example, it's a great place to unpack files to install from there, greatly speeding up the installation.<br />
<br />
* '''Command line and graphical user interfaces:''' Both the the graphical user interface (GUI) and command line interface (where you type commands into a window with the keyboard) can be used to manage AmigaOS, its programs and files. Both interfaces are intergated with each other so you can easily use command lines from the GUI or open graphical elements from a command line.<br />
<br />
*'''ARexx Ports:''' Throughout AmigaOS and third party programs, "ARexx" message ports let one application talk with others so that apps work together to serve the user. AmigaOS also provides the lightweight ARexx and modern Python programming languages that can control AmigaOS and applications with ARexx ports.<br />
<br />
* '''Resident Commands:''' Commands can be made resident, i.e., they are kept in memory so that they can be reused with no loading time.<br />
<br />
* '''Restart only the operating system:''' if you feel the need to restart the system, you can do so by restarting '''only AmigaOS''' and not the whole computer.<br />
<br />
=== AmigaOS platform targets ===<br />
<br />
While the original versions of AmigaOS ran on computers of the eighties using Motorola 68k series CPU chips, the current AmigaOS runs on computers using PowerPC processor chips [http://www.amigaos.net/content/72/supported-hardware hardware]. These can be older Amiga computers (also called "Classic Amigas") with PPC "accelerator cards" or new generation Amiga PPC computers. <br />
<br />
In this guide, we will concentrate on the current AmigaOS running on the supported hardware:<br />
<br />
* [[AmigaOne X1000]], AmigaOne X5000 and AmigaOne A1222 models by [http://www.a-eon.com A-Eon Technology]<br />
<br />
* [[AmigaOne 500]], Sam460, Sam440ep and Sam440-flex models by [http://www.acube-systems.com ACube Systems]<br />
<br />
* [[Pegasos II]] model by [http://www.bplan-gmbh.de bplan GmbH]<br />
<br />
* [[AmigaOne XE and MicroA1-C]] models by [http://en.wikipedia.org/wiki/Eyetech Eyetech Group Ltd].<br />
<br />
* [[Classic Amiga]] 4000(T), 3000(T) and 1200 models by Commodore Business Machines (when equipped with PowerPC accelerator cards).<br />
<br />
== How does AmigaOS work? - Concepts ==<br />
<br />
In this page we will discuss [[UserDoc:How AmigaOS Works|how AmigaOS works]]:<br />
<br />
* [[UserDoc:How_AmigaOS_Works#The_most_important_components|The most important components]] (Exec, AmigaDOS, Intuition...)<br />
* [[UserDoc:How_AmigaOS_Works#How_is_my_data_stored.3F|how files and data are stored]]<br />
* [[UserDoc:How_AmigaOS_Works#All_AmigaOS_components|all AmigaOS components are described]]<br />
* [[UserDoc:How_AmigaOS_Works#AmigaOS_boot_procedure|how AmigaOS is booted on your Amiga computer]]<br />
* [[Workbench/Prefs|AmigaOS settings programs]]<br />
* ...<br />
<br />
== How to use AmigaOS? ==<br />
<br />
AmigaOS is a collection of components that oversee the computer hardware & data and provide the user with easy, understandable tools to manage and use them.<br />
<br />
In the following [[UserDoc:Introduction to AmigaOS|Introduction to AmigaOS pages]] we will discuss the basic concepts:<br />
<br />
* how to use AmigaOS<br />
* what the AmigaOS graphic user interface is composed of <br />
* what interfaces AmigaOS provides, including the [[UserDoc:Workbench|Workbench]], the [[UserDoc:Shell|Shell]] or scripting languages.<br />
<br />
From the introduction page, you can continue with more detailed pages on the [[UserDoc:Workbench|Workbench]] and the [[AmigaDOS manual]] . Now let's start with this [[UserDoc:Introduction to AmigaOS|Introduction to AmigaOS]].<br />
<br />
== Manuals ==<br />
<br />
[[UserDoc:AmigaOS File Systems|AmigaOS File Systems]] - AmigaOS File Systems<br />
<br />
[[AmigaOS Manual]] - AmigaOS Manual<br />
<br />
[[Bars & Pipes Professional]] - MIDI Sequencer</div>Costel Minceahttps://wiki.amigaos.net/w/index.php?title=Exec_Interrupts&diff=9100Exec Interrupts2017-01-19T10:28:43Z<p>Costel Mincea: /* Software Interrupts */</p>
<hr />
<div>{{NeedUpdate}}<br />
== Exec Interrupts ==<br />
<br />
== Interrupts ==<br />
<br />
Exec manages the decoding, dispatching, and sharing of all system interrupts. This includes control of hardware interrupts, software interrupts, task-relative interrupts (see the discussion of exceptions in [[Exec_Tasks|Exec Tasks]]), and interrupt disabling and enabling. In addition, Exec supports a more extended prioritization of interrupts than that provided in the CPU.<br />
<br />
The proper operation of multitasking depends heavily on the consistent management of the interrupt system. Task activities are often driven by inter-system communication that is originated by various interrupts.<br />
<br />
=== Sequence of Events During an Interrupt ===<br />
<br />
Before useful interrupt handling code can be executed, a considerable amount of hardware and software activity must occur. Each interrupt must propagate through several hardware and software interfaces before application code is finally dispatched:<br />
<br />
<ul><br />
<br />
<li><p>A hardware device decides to cause an interrupt and sends a signal to the interrupt control portions of the ''4703'' (Paula) custom chip.</p><br />
<p></p></li><br />
<br />
<li><p>The ''4703'' interrupt control logic notices this new signal and performs two primary operations. First, it records that the interrupt has been requested by setting a flag bit in the INTREQ register. Second, it examines the INTENA register to determine whether the corresponding interrupt and the interrupt master are enabled. If both are enabled, the ''4703'' generates an interrupt request by placing the priority level of the request onto the three ''68000'' interrupt control input lines (IPL0, IPL1, IPL2).</p><br />
<p></p></li><br />
<br />
<li><p>These three signals correspond to seven interrupt priority levels in the 68000. If the priority of the new interrupt is ''greater'' than the current processor priority, an interrupt sequence is initiated. The priority level of the new interrupt is used to index into the top seven words of the processor address space. The odd byte (a vector number) of the indexed word is fetched and then shifted left by two to create an offset into the processor's auto-vector interrupt table. The vector offsets used are in the range of $064 to $07C. These are labeled as ''interrupt autovectors'' in the ''68000'' manual. The auto-vector table appears in low memory on a ''68000'' system, but its location for other ''68000'' family processors is determined by the processor's CPU ''Vector Base Register'' (VBR). VBR can be accessed from supervisor mode with the MOVEC instruction.</p><br />
<p></p></li><br />
<br />
<li><p>The processor then switches into ''supervisor'' mode (if it is not already in that mode), and saves copies of the status register and program counter (PC) onto the top of the ''system'' stack (additional information may be saved by processors other than the ''68000''). The processor priority is then raised to the level of the active interrupt.</p></li><br />
<br />
<li><p>From the low memory vector address (calculated in step three above), a 32-bit ''autovector'' address is fetched and loaded into the program counter. This is an entry point into Exec's interrupt dispatcher.</p><br />
<p></p><br />
<p>Exec must now further decode the interrupt by examining the INTREQ and INTENA ''4703'' chip registers. Once the active interrupt has been determined, Exec indexes into an ExecBase array to fetch the interrupt's handler entry point and handler data pointer addresses.</p></li><br />
<br />
<li><p>Exec now turns control over to the interrupt handler by calling it as if it were a subroutine. This handler may deal with the interrupt directly or may propagate control further by invoking interrupt server chain processing.</p></li><br />
<br />
</ul><br />
<br />
You can see from the above discussion that the interrupt autovectors ''should never be altered by the user''. If you wish to provide your own system interrupt handler, you must use the Exec SetIntVector() function. You should not change the contents of any autovector location.<br />
<br />
Task multiplexing usually occurs as the result of an interrupt. When an interrupt has finished and the processor is about to return to user mode, Exec determines whether task-scheduling attention is required. If a task was signaled during interrupt processing, the task scheduler will be invoked. Because Exec uses preemptive task scheduling, it can be said that the interrupt subsystem is the heart of task multiplexing. If, for some reason, interrupts do not occur, a task might execute forever because it cannot be forced to relinquish the CPU.<br />
<br />
[[File:LibTable26-1.png|frame|center|Interrupts by Priority]]<br />
<br />
=== Interrupt Priorities ===<br />
<br />
Interrupts are prioritized in hardware and software. The 68000 CPU priority at which an interrupt executes is determined strictly by hardware. In addition to this, the software imposes a finer level of ''pseudo-priorities'' on interrupts with the same CPU priority. These pseudo-priorities determine the order in which simultaneous interrupts of the same CPU priority are processed. Multiple interrupts with the same CPU priority but a different pseudo-priority will not interrupt one another. Interrupts are serviced by either an exclusive handler or by server chains to which many servers may be attached, as shown in the Type field of the next table. The table above summarizes all interrupts by priority.<br />
<br />
The ''8520''s (also called ''CIA''s) are Amiga peripheral interface adapter chips that generate the INT2 and INT6 interrupts. For more information about them, see the ''Amiga Hardware Reference Manual''.<br />
<br />
As described in the Motorola ''68000 Programmer's Manual'', interrupts may nest only in the direction of higher priority. Because of the time-critical nature of many interrupts on the Amiga, the CPU priority level ''must never be changed'' by user or system code. When the system is running in user mode (multitasking), the CPU priority level must remain set at zero. When an interrupt occurs, the CPU priority is raised to the level appropriate for that interrupt. Lowering the CPU priority would permit unlimited interrupt recursion on the system stack and would "short-circuit" the interrupt-priority scheme.<br />
<br />
Because it is dangerous on the Amiga to hold off interrupts for any period of time, higher-level interrupt code must perform its business and exit promptly. If it is necessary to perform a time-consuming operation as the result of a high-priority interrupt, the operation should be deferred either by posting a ''software interrupt'' or by signalling a task. In this way, interrupt response time is kept to a minimum. Software interrupts are described in a later section.<br />
<br />
=== Nonmaskable Interrupt ===<br />
<br />
The ''68000'' provides a nonmaskable interrupt (NMI) of CPU priority 7. Although this interrupt cannot be generated by the Amiga hardware itself, it can be generated on the expansion bus by external hardware. Because this interrupt does not pass through the ''4703'' interrupt controller circuitry, it is capable of violating system code critical sections. In particular, it short-circuits the DISABLE mutual-exclusion mechanism. Code that uses NMI must not assume that it can access system data structures.<br />
<br />
Interrupts are serviced on the Amiga through the use of interrupt ''handlers'' and ''servers''. An interrupt handler is a system routine that exclusively handles all processing related to a particular ''4703'' interrupt. An interrupt server is one of possibly many system routines that are invoked as the result of a single ''4703'' interrupt. Interrupt servers provide a means of interrupt sharing. This concept is useful for general-purpose interrupts such as vertical blanking.<br />
<br />
At system start, Exec designates certain interrupts as handlers and others as server chains. The PORTS, COPER, VERTB, EXTER, and NMI interrupts are initialized as server chains. Therefore, each of these may execute multiple interrupt routines per each interrupt. All other interrupts are designated as handlers and are always used exclusively.<br />
<br />
=== Interrupt Data Structure ===<br />
<br />
Interrupt handlers and servers are defined by the Exec Interrupt structure. This structure specifies an interrupt routine entry point and data pointer. The C definition of this structure is as follows:<br />
<br />
<syntaxhighlight><br />
struct Interrupt<br />
{<br />
struct Node is_Node;<br />
APTR is_Data;<br />
VOID (*is_Code)();<br />
};<br />
</syntaxhighlight><br />
<br />
Once this structure has been properly initialized, it can be used for either a handler or a server.<br />
<br />
=== Environment ===<br />
<br />
Interrupts execute in an environment different from that of tasks. All interrupts execute in ''supervisor mode'' and utilize the single ''system stack''. This stack is large enough to handle extreme cases of nested interrupts (of higher priorities). Interrupt processing has no effect on task stack usage.<br />
<br />
All interrupt processing code, both handlers and servers, is invoked as assembly code subroutines. Normal assembly code register conventions dictate that the D0, D1, A0 and A1 registers be free for scratch use. In the case of an interrupt handler, some of these registers also contain data that may be useful to the handler code. See the section on handlers below.<br />
<br />
Because interrupt processing executes outside the context of most system activities, certain data structures will not be self-consistent and must be considered off limits for all practical purposes. This happens because certain system operations are not atomic in nature and might be interrupted only after executing part of an important instruction sequence. For example, memory allocation and deallocation routines do not disable interrupts. This results in the possibility of interrupting a memory-related routine. In such a case, a memory linked list may be inconsistent during and interrupt. Therefore, interrupt routines must not use any memory allocation or deallocation functions.<br />
<br />
In addition, interrupts may not call any system function which might allocate memory, wait, manipulate unprotected lists, or modify ExecBase-&gt;ThisTask data (for example Forbid(), Permit(), and mathieee libraries). In practice, this means that very few system calls may be used within interrupt code. The following functions may generally be used safely within interrupts:<br />
<br />
{| class="wikitable"<br />
| Alert()<br />
|-<br />
| Disable()<br />
|-<br />
| Enable()<br />
|-<br />
| Signal()<br />
|-<br />
| Cause()<br />
|-<br />
| GetMsg()<br />
|-<br />
| PutMsg()<br />
|-<br />
| ReplyMsg()<br />
|-<br />
| FindPort()<br />
|-<br />
| FindTask()<br />
|}<br />
<br />
and if you are manipulating your ''own'' List structures while in an interrupt:<br />
<br />
{| class="wikitable"<br />
| AddHead()<br />
|-<br />
| AddTail()<br />
|-<br />
| RemHead()<br />
|-<br />
| RemTail()<br />
|-<br />
| FindName()<br />
|-<br />
| FindIName()<br />
|-<br />
| GetHead()<br />
|-<br />
| GetTail()<br />
|-<br />
| GetSucc()<br />
|-<br />
| GetPred()<br />
|}<br />
<br />
In addition, certain devices (notably the timer device) specifically allow limited use of SendIO() and BeginIO() within interrupts.<br />
<br />
=== Interrupt Handlers ===<br />
<br />
As described above, an interrupt handler is a system routine that exclusively handles all processing related to a particular ''4703'' interrupt. There can only be one handler per ''4703'' interrupt. Every interrupt handler consists of an Interrupt structure (as defined above) and a single assembly code routine. Optionally, a data structure pointer may also be provided. This is particularly useful for ROM-resident interrupt code.<br />
<br />
An interrupt handler is passed control as if it were a subroutine of Exec. Once the handler has finished its business, it must return to Exec by executing an RTS (return from subroutine) instruction rather than an RTE (return from exception) instruction. Interrupt handlers should be kept very short to minimize service-time overhead and thus minimize the possibilities of interrupt overruns. As described above, an interrupt handler has the normal scratch registers at its disposal. In addition, A5 and A6 are free for use. These registers are saved by Exec as part of the interrupt initiation cycle.<br />
<br />
For the sake of efficiency, Exec passes certain register parameters to the handler (see the list below). These register values may be utilized to trim a few microseconds off the execution time of a handler. All of the following registers (D0/D1/A0/A1/A5/A6) may be used as scratch registers by an interrupt handler, and need not be restored prior to returning.<br />
<br />
{{Note|title=Don't Make Assumptions About Registers|text=Interrupt servers have different register usage rules (see the "Interrupt Servers" section).}}<br />
<br />
==== Interrupt Handler Register Usage ====<br />
<br />
Here are the register conventions for interrupt handlers.<br />
<br />
; D0<br />
: Contains no valid information.<br />
<br />
; D1<br />
: Contains the ''4703'' INTENAR and INTREQR registers values '''AND''''ed together. This results in an indication of which interrupts are enabled ''and'' active.<br />
<br />
; A0<br />
: Points to the base address of the Amiga custom chips. This information is useful for performing indexed instruction access to the chip registers.<br />
<br />
; A1<br />
: Points to the data area specified by the is_Data field of the Interrupt structure. Because this pointer is always fetched (regardless of whether you use it), it is to your advantage to make some use of it.<br />
<br />
; A5<br />
: Is used as a vector to your interrupt code.<br />
<br />
; A6<br />
: Points to the Exec library base (SysBase). You may use this register to call Exec functions or set it up as a base register to access your own library or device.<br />
<br />
Interrupt handlers are established by passing the Exec function SetIntVector(), your initialized Interrupt structure, and the ''4703'' interrupt bit number of interest. The parameters for this function are as follows:<br />
<br />
<syntaxhighlight><br />
SetIntVector(ULONG intNumber, struct Interrupt *interrupt)<br />
</syntaxhighlight><br />
<br />
The first argument is the bit number for which this interrupt server is to respond (example INTB_VERTB). The possible bits for interrupts are defined in &lt;hardware/intbits.h&gt;. The second argument is the address of an interrupt server node as described earlier in this article. Keep in mind that certain interrupts are established as server chains and should not be accessed as handlers.<br />
<br />
The following example demonstrates initialization and installation of an assembler interrupt handler. See the [[Resources|Resources]] for more information on allocating resources, and [[Serial_Device|Serial Device]] for the more common method of serial communications.<br />
<br />
<pre><br />
;/* rbf.c - Execute me to compile me with SAS C 5.10<br />
LC -d0 -b1 -cfistq -v -y -j73 rbf.c<br />
Blink FROM LIB:c.o,rbf.o,rbfhandler.o TO rbf LIBRARY LIB:LC.lib,LIB:Amiga.lib<br />
quit<br />
<br />
** rbf.c - serial receive buffer full interrupt handler example.<br />
** Must be linked with assembler handler rbfhandler.o<br />
**<br />
** To receive characters, this example requires ASCII serial input<br />
** at your Amiga's current serial hardware baud rate (ie. 9600 after<br />
** reboot, else last baud rate used)<br />
*/<br />
<br />
#include &lt;exec/execbase.h&gt;<br />
#include &lt;exec/memory.h&gt;<br />
#include &lt;exec/interrupts.h&gt;<br />
#include &lt;resources/misc.h&gt;<br />
#include &lt;hardware/custom.h&gt;<br />
#include &lt;hardware/intbits.h&gt;<br />
#include &lt;dos/dos.h&gt;<br />
<br />
#include &lt;clib/exec_protos.h&gt;<br />
#include &lt;clib/misc_protos.h&gt;<br />
<br />
#include &lt;stdio.h&gt;<br />
#include &lt;string.h&gt;<br />
<br />
#ifdef LATTICE<br />
int CXBRK(void) { return(0); } /* Disable Lattice CTRL/C handling */<br />
void chkabort(void) { return; } /* really */<br />
#endif<br />
<br />
#define BUFFERSIZE 256<br />
<br />
extern void RBFHandler(); /* proto for asm interrupt handler */<br />
void main(void);<br />
<br />
struct MiscResource *MiscBase;<br />
extern struct ExecBase *SysBase;<br />
extern struct Custom far custom; /* defined in amiga.lib */<br />
<br />
static UBYTE *allocname = &quot;rbf-example&quot;;<br />
<br />
struct RBFData {<br />
struct Task *rd_Task;<br />
ULONG rd_Signal;<br />
ULONG rd_BufferCount;<br />
UBYTE rd_CharBuffer[BUFFERSIZE + 2];<br />
UBYTE rd_FlagBuffer[BUFFERSIZE + 2];<br />
UBYTE rd_Name[32];<br />
};<br />
<br />
void main(void)<br />
{<br />
struct RBFData *rbfdata;<br />
UBYTE *currentuser;<br />
BYTE signr;<br />
struct Device *serdevice;<br />
struct Interrupt *rbfint, *priorint;<br />
BOOL priorenable;<br />
ULONG signal;<br />
<br />
if (MiscBase = OpenResource(&quot;misc.resource&quot;))<br />
{<br />
currentuser = AllocMiscResource(MR_SERIALPORT, allocname); /* Allocate the serial */<br />
if (currentuser) /* port registers. */<br />
{<br />
printf(&quot;serial hardware allocated by %s. Trying to remove it\n&quot;,<br />
currentuser); /* Hey! someone got it! */<br />
Forbid();<br />
if (serdevice = (struct Device *)FindName(&amp;SysBase-&gt;DeviceList, currentuser))<br />
RemDevice(serdevice);<br />
Permit();<br />
<br />
currentuser = AllocMiscResource(MR_SERIALPORT, allocname); /* and try again */<br />
}<br />
if (currentuser == NULL)<br />
{ /* Get the serial */<br />
currentuser = AllocMiscResource(MR_SERIALBITS, allocname); /* control bits. */<br />
if (currentuser)<br />
{<br />
printf(&quot;serial control allocated by %s\n&quot;, currentuser); /* Give up. */<br />
FreeMiscResource(MR_SERIALPORT);<br />
}<br />
else<br />
{ /* Got them both. */<br />
printf(&quot;serial hardware allocated\n&quot;);<br />
if ((signr = AllocSignal(-1)) != -1) /* Allocate a signal bit for the */<br />
{ /* interrupt handler to signal us. */<br />
if (rbfint = AllocMem(sizeof(struct Interrupt), MEMF_PUBLIC|MEMF_CLEAR))<br />
{<br />
if (rbfdata = AllocMem(sizeof(struct RBFData), MEMF_PUBLIC|MEMF_CLEAR))<br />
{<br />
rbfdata-&gt;rd_Task = FindTask(NULL); /* Init rfbdata structure. */<br />
rbfdata-&gt;rd_Signal = 1L &lt;&lt; signr;<br />
<br />
rbfint-&gt;is_Node.ln_Type = NT_INTERRUPT; /* Init interrupt node. */<br />
strcpy(rbfdata-&gt;rd_Name, allocname);<br />
rbfint-&gt;is_Node.ln_Name = rbfdata-&gt;rd_Name;<br />
rbfint-&gt;is_Data = (APTR)rbfdata;<br />
rbfint-&gt;is_Code = RBFHandler;<br />
/* Save state of RBF and */<br />
priorenable = custom.intenar &amp; INTF_RBF ? TRUE : FALSE; /* interrupt */<br />
custom.intena = INTF_RBF; /* disable it. */<br />
priorint = SetIntVector(INTB_RBF, rbfint);<br />
<br />
if (priorint) printf(&quot;replaced the %s RBF interrupt handler\n&quot;,<br />
priorint-&gt;is_Node.ln_Name);<br />
printf(&quot;enabling RBF interrupt\n&quot;);<br />
custom.intena = INTF_SETCLR | INTF_RBF;<br />
<br />
printf(&quot;waiting for buffer to fill up. Use CTRL-C to break\n&quot;);<br />
signal = Wait(1L &lt;&lt; signr | SIGBREAKF_CTRL_C);<br />
<br />
if (signal &amp; SIGBREAKF_CTRL_C) printf(&quot;&gt;break&lt;\n&quot;);<br />
printf(&quot;Character buffer contains:\n%s\n&quot;, rbfdata-&gt;rd_CharBuffer);<br />
<br />
custom.intena = INTF_RBF; /* Restore previous handler. */<br />
SetIntVector(INTB_RBF, priorint);<br />
/* Enable it if it was enabled */<br />
if (priorenable) custom.intena = INTF_SETCLR|INTF_RBF; /* before. */<br />
<br />
FreeMem(rbfdata, sizeof(struct RBFData));<br />
}<br />
else printf(&quot;can't allocate memory for rbf data\n&quot;);<br />
FreeMem(rbfint, sizeof(struct Interrupt));<br />
}<br />
else printf(&quot;can't allocate memory for interrupt structure\n&quot;);<br />
FreeSignal(signr);<br />
}<br />
else printf(&quot;can't allocate signal\n&quot;);<br />
<br />
FreeMiscResource(MR_SERIALBITS); /* release serial hardware */<br />
FreeMiscResource(MR_SERIALPORT);<br />
}<br />
}<br />
} /* There is no 'CloseResource()' function */<br />
}<br />
</pre><br />
<br />
The assembler interrupt handler code, RBFHandler, reads the complete word of serial input data from the serial hardware and then separates the character and flag bytes into separate buffers. When the buffers are full, the handler signals the main process causing main to print the character buffer contents, remove the handler, and exit.<br />
<br />
{{Note|text=The data structure containing the signal to use, task address pointer, and buffers is allocated and initialized in main(), and passed to the handler (shown below) via the is_Data pointer of the Interrupt structure.}}<br />
<br />
<pre><br />
* rbfhandler.asm. Example interrupt handler for rbf.<br />
*<br />
* Assembled with Howesoft Adapt 680x0 Macro Assembler Rel. 1.0<br />
* hx68 from: rbfhandler.asm to rbfhandler.o INCDIR include:<br />
* blink from lib:c.o rbf.o rbfhandler.o to rbf lib lib:lc.lib lib:amiga.lib<br />
*<br />
INCLUDE &quot;exec/types.i&quot;<br />
INCLUDE &quot;hardware/custom.i&quot;<br />
INCLUDE &quot;hardware/intbits.i&quot;<br />
<br />
XDEF _RBFHandler<br />
<br />
JSRLIB MACRO<br />
XREF _LVO\1<br />
JSR _LVO\1(A6)<br />
ENDM<br />
<br />
BUFLEN EQU 256<br />
<br />
STRUCTURE RBFDATA,0<br />
APTR rd_task<br />
ULONG rd_signal<br />
UWORD rd_buffercount<br />
STRUCT rd_charbuffer,BUFLEN+2<br />
STRUCT rd_flagbuffer,BUFLEN+2<br />
STRUCT rd_name,32<br />
LABEL RBFDATA_SIZEOF<br />
<br />
* Entered with:<br />
* D0 == scratch<br />
* D1 == INTENAT &amp; INTREQR (scratch)<br />
* A0 == custom chips (scratch)<br />
* A1 == is_Data which is RBFDATA structure (scratch)<br />
* A5 == vector to our code (scratch)<br />
* A6 == pointer to ExecBase (scratch)<br />
*<br />
* Note - This simple handler just receives one buffer full of serial<br />
* input data, signals main, then ignores all subsequent serial data.<br />
*<br />
section code<br />
<br />
_RBFHandler: ;entry to our interrupt handler<br />
<br />
MOVE.W serdatr(A0),D1 ;get the input word (flags and char)<br />
<br />
MOVE.W rd_buffercount(A1),D0 ;get our buffer index<br />
CMPI.W #BUFLEN,D0 ;no more room in our buffer ?<br />
BEQ.S ExitHandler ;yes - just exit (ignore new char)<br />
LEA.L rd_charbuffer(A1),A5 ;else get our character buffer address<br />
MOVE.B D1,0(A5,D0.W) ;store character in our character buffer<br />
LEA.L rd_flagbuffer(A1),A5 ;get our flag buffer address<br />
LSR.W #8,d1 ;shift flags down<br />
MOVE.B D1,0(A5,D0.W) ;store flags in flagbuffer<br />
<br />
ADDQ.W #1,D0 ;increment our buffer index<br />
MOVE.W D0,rd_buffercount(A1) ; and replace it<br />
CMPI.W #BUFLEN,D0 ;did our buffer just become full ?<br />
BNE.S ExitHandler ;no - we can exit<br />
MOVE.L A0,-(SP) ;yes - save custom<br />
MOVE.L rd_signal(A1),D0 ;get signal allocated in main()<br />
MOVE.L rd_task(A1),A1 ;and pointer to main task<br />
JSRLIB Signal ;tell main we are full<br />
MOVE.L (SP)+,A0 ;restore custom<br />
;Note: system call trashed D0-D1/A0-A1<br />
ExitHandler:<br />
MOVE.W #INTF_RBF,intreq(A0) ;clear the interrupt<br />
RTS ;return to exec<br />
<br />
END<br />
</pre><br />
<br />
=== Interrupt Servers ===<br />
<br />
As mentioned above, an interrupt server is one of possibly many system interrupt routines that are invoked as the result of a single ''4703'' interrupt. Interrupt servers provide an essential mechanism for interrupt sharing.<br />
<br />
Interrupt servers must be used for PORTS, COPER, VERTB, EXTER, or NMI interrupts. For these interrupts, all servers are linked together in a chain. Every server in the chain will be called in turn as long as the previous server returned with the processor's Z (zero) flag set. If you determine that an interrupt was specifically for your server, you should return with the processor's Z flag cleared (non-zero condition) so that the remaining servers on the chain will be skipped.<br />
<br />
{{Note|title=Use The Z Flag|text=VERTB (vertical blank) servers should ''always'' return with the Z (zero) flag set. The processor Z flag is used rather than the normal function convention of returning a result in D0 because it may be tested more quickly by Exec upon the server's return.}}<br />
<br />
The easiest way to set the condition code register is to do an immediate move to the D0 register as follows:<br />
<br />
<pre><br />
SetZflag_Calls_Next:<br />
MOVEQ #0,D0<br />
RTS<br />
<br />
ClrZflag_Ends_Chain:<br />
MOVEQ #1,D0<br />
RTS<br />
</pre><br />
<br />
The same Exec Interrupt structure used for handlers is also used for servers. Also, like interrupt handlers, servers must terminate their code with an RTS instruction.<br />
<br />
Interrupt servers are called in priority order. The priority of a server is specified in its is_Node.ln_Pri field. Higher-priority servers are called earlier than lower-priority servers. Adding and removing interrupt servers from a particular chain is accomplished with the Exec AddIntServer() and RemIntServer() functions. These functions require you to specify both the ''4703'' interrupt number and a properly initialized Interrupt structure.<br />
<br />
Servers have different register values passed than handlers do. A server cannot count on the D0, D1, A0, or A6 registers containing any useful information. However, the highest priority system vertical blank server currently expects to receive a pointer to the custom chips A0. Therefore, if you install a vertical blank server at priority 10 or greater, you must place custom ($DF F000) in A0 before exiting. Other than that, a server is free to use D0-D1 and A0-A1/A5-A6 as scratch.<br />
<br />
==== Interrupt Server Register Usage ====<br />
<br />
; D0<br />
: Scratch.<br />
<br />
; D1<br />
: Scratch.<br />
<br />
; A0<br />
: Scratch except in certain cases (see note above).<br />
<br />
; A1<br />
: Points to the data area specified by the is_Data field of the Interrupt structure. Because this pointer is always fetched (regardless of whether you use it), it is to your advantage to make some use of it (scratch).<br />
<br />
; A5<br />
: Points to your interrupt code (scratch).<br />
<br />
; A6<br />
: Scratch.<br />
<br />
In a server chain, the interrupt is cleared automatically by the system. Having a server clear its interrupt is not recommended and not necessary (clearing could cause the loss of an interrupt on PORTS or EXTER).<br />
<br />
Here is an example of a program to install and remove a low-priority vertical blank interrupt server:<br />
<br />
<pre><br />
;/* vertb.c - Execute me to compile me with SAS C 5.10<br />
LC -d0 -b1 -cfistq -v -y -j73 vertb.c<br />
Blink FROM LIB:c.o,vertb.o,vertbserver.o TO vertb LIBRARY LIB:LC.lib,LIB:Amiga.lib<br />
quit ; */<br />
/* vertb.c - Vertical blank interrupt server example. Must be linked with vertbserver.o. */<br />
<br />
#include &lt;exec/memory.h&gt;<br />
#include &lt;exec/interrupts.h&gt;<br />
#include &lt;dos/dos.h&gt;<br />
#include &lt;hardware/custom.h&gt;<br />
#include &lt;hardware/intbits.h&gt;<br />
#include &lt;clib/exec_protos.h&gt;<br />
#include &lt;stdio.h&gt;<br />
<br />
#ifdef LATTICE<br />
int CXBRK(void) { return(0); } /* Disable Lattice CTRL/C handling */<br />
void chkabort(void) { return; } /* really */<br />
#endif<br />
<br />
extern void VertBServer(); /* proto for asm interrupt server */<br />
<br />
void main(void)<br />
{<br />
struct Interrupt *vbint;<br />
ULONG counter = 0;<br />
ULONG endcount;<br />
/* Allocate memory for */<br />
if (vbint = AllocMem(sizeof(struct Interrupt), /* interrupt node. */<br />
MEMF_PUBLIC|MEMF_CLEAR))<br />
{<br />
vbint-&gt;is_Node.ln_Type = NT_INTERRUPT; /* Initialize the node. */<br />
vbint-&gt;is_Node.ln_Pri = -60;<br />
vbint-&gt;is_Node.ln_Name = &quot;VertB-Example&quot;;<br />
vbint-&gt;is_Data = (APTR)&amp;counter;<br />
vbint-&gt;is_Code = VertBServer;<br />
<br />
<br />
AddIntServer(INTB_VERTB, vbint); /* Kick this interrupt server to life. */<br />
<br />
printf(&quot;VBlank server will increment a counter every frame.\n&quot;);<br />
printf(&quot;counter started at zero, CTRL-C to remove server\n&quot;);<br />
<br />
Wait(SIGBREAKF_CTRL_C);<br />
endcount = counter;<br />
printf(&quot;%ld vertical blanks occurred\nRemoving server\n&quot;, endcount);<br />
<br />
RemIntServer(INTB_VERTB, vbint);<br />
FreeMem(vbint, sizeof(struct Interrupt));<br />
}<br />
else printf(&quot;Can't allocate memory for interrupt node\n&quot;);<br />
}<br />
</pre><br />
<br />
This is the assembler VertBServer installed by the C example:<br />
<br />
<pre><br />
* vertbserver.asm. Example simple interrupt server for vertical blank<br />
*<br />
* Assembled with Howesoft Adapt 680x0 Macro Assembler Rel. 1.0<br />
* hx68 from: vertbserver.asm to vertbserver.o INCDIR include:<br />
* blink from lib:c.o vertb.o vertbserver.o to vertb lib lib:lc.lib lib:amiga.lib<br />
*<br />
INCLUDE &quot;exec/types.i&quot;<br />
INCLUDE &quot;hardware/custom.i&quot;<br />
INCLUDE &quot;hardware/intbits.i&quot;<br />
<br />
XDEF _VertBServer<br />
<br />
* Entered with: A0 == scratch (execpt for highest pri vertb server)<br />
* D0 == scratch A1 == is_Data<br />
* D1 == scratch A5 == vector to interrupt code (scratch)<br />
* A6 == scratch<br />
*<br />
section code<br />
<br />
_VertBServer:<br />
ADDI.L #1,(a1) ; increments counter is_Data points to<br />
MOVEQ.L #0,d0 ; set Z flag to continue to process other vb-servers<br />
RTS ;return to exec<br />
END<br />
</pre><br />
<br />
== Software Interrupts ==<br />
<br />
Exec provides a means of generating ''software interrupts''. Software interrupts execute at a priority higher than that of tasks but lower than that of hardware interrupts, so they are often used to defer hardware interrupt processing to a lower priority. Software interrupts use the same Interrupt data structure as hardware interrupts. As described above, this structure contains pointers to both interrupt code and data, and should be initialized as node type NT_INTERRUPT (not NT_SOFTINT which is an internal Exec flag).<br />
<br />
A software interrupt is usually activated with the Cause() function. If this function is called from a task, the task will be interrupted and the software interrupt will occur. If it is called from a hardware interrupt, the software interrupt will not be processed until the system exits from its last hardware interrupt. If a software interrupt occurs from within another software interrupt, it is not processed until the current one is completed. However, individual software interrupts do not nest, and will not be caused if already running as a software interrupt.<br />
<br />
Software interrupts are prioritized. Unlike interrupt servers, software interrupts have only five allowable priority levels: -32, -16, 0, +16, and +32. The priority should be put into the ln_Pri field prior to calling Cause().<br />
<br />
Software interrupts can also be generated by message arrival at a PA_SOFTINT message port. The applications of this technique are limited since it is not permissible, with most devices, to send IO requests from within interrupt code. However, the timer.device does allow such interactions, so a self-perpetuating PA_SOFTINT timer port can provide an application with quite consistent timing under varying multitasking loads. The following example demonstrates use of a software interrupt and a PA_SOFTINT port. See the [[Exec_Messages_and_Ports|Exec Messages and Ports]] for more information about messages and ports.<br />
<br />
<syntaxhighlight><br />
/* timersoftint.c - Timer device software interrupt message port example. */<br />
<br />
#include <exec/memory.h><br />
#include <exec/interrupts.h><br />
#include <devices/timer.h><br />
#include <dos/dos.h><br />
#include <proto/exec.h><br />
#include <proto/dos.h><br />
<br />
#define MICRO_DELAY 1000<br />
#define OFF 0<br />
#define ON 1<br />
#define STOPPED 2<br />
<br />
struct TSIData {<br />
uint32 tsi_Counter;<br />
uint32 tsi_Flag;<br />
struct MsgPort *tsi_Port;<br />
};<br />
<br />
struct TSIData *tsidata;<br />
<br />
void tsoftcode(void); /* Prototype for our software interrupt code */<br />
<br />
int main()<br />
{<br />
uint32 endcount;<br />
<br />
/* Allocate message port, data & interrupt structures. */<br />
tsidata = IExec->AllocVecTags(sizeof(struct TSIData),<br />
AVT_Type, MEMF_SHARED,<br />
AVT_Lock, TRUE,<br />
TAG_END);<br />
<br />
/* Set up the (software)interrupt structure. Note that this task runs at */<br />
/* priority 0. Software interrupts may only be priority -32, -16, 0, +16, */<br />
/* +32. Also note that the correct node type for a software interrupt is */<br />
/* NT_INTERRUPT. (NT_SOFTINT is an internal Exec flag). This is the same */<br />
/* setup as that for a software interrupt which you Cause(). */<br />
struct Interrupt *softint = IExec->AllocSysObjectTags(ASOT_INTERRUPT,<br />
ASOINTR_Code, tsoftcode,<br />
ASOINTR_Data, tsidata,<br />
TAG_END);<br />
<br />
struct MsgPort *port = IExec->AllocSysObjectTags(ASOT_PORT,<br />
ASOPORT_AllocSig, FALSE,<br />
ASOPORT_Action, PA_SOFTINT,<br />
ASOPORT_Target, softint,<br />
TAG_END);<br />
<br />
if(tsidata != NULL && softint != NULL && port != NULL)<br />
{<br />
softint->is_Node.ln_Pri = 0;<br />
<br />
/* Allocate timerequest */<br />
struct TimeRequest *tr = IExec->AllocSysObjectTags(ASOT_IOREQUEST,<br />
ASOIOR_Size, sizeof(struct TimeRequest),<br />
ASOIOR_ReplyPort, port,<br />
TAG_END);<br />
<br />
if (tr != NULL)<br />
{<br />
/* Open timer.device. NULL is success. */<br />
if (!(IExec->OpenDevice("timer.device", UNIT_MICROHZ, (struct IORequest *)tr, 0)))<br />
{<br />
tsidata->tsi_Flag = ON; /* Init data structure to share globally. */<br />
tsidata->tsi_Port = port;<br />
<br />
/* Send of the first timerequest to start. IMPORTANT: Do NOT */<br />
/* BeginIO() to any device other than audio or timer from */<br />
/* within a software or hardware interrupt. The BeginIO() code */<br />
/* may allocate memory, wait or perform other functions which */<br />
/* are illegal or dangerous during interrupts. */<br />
IDOS->Printf("starting softint. CTRL-C to break...\n");<br />
<br />
tr->Request.io_Command = TR_ADDREQUEST; /* Initial iorequest to start */<br />
tr->Time.Microseconds = MICRO_DELAY; /* software interrupt. */<br />
IExec->BeginIO((struct IORequest *)tr);<br />
<br />
IExec->Wait(SIGBREAKF_CTRL_C);<br />
endcount = tsidata->tsi_Counter;<br />
IDOS->Printf("timer softint counted %lu milliseconds.\n", endcount);<br />
<br />
IDOS->Printf("Stopping timer...\n");<br />
tsidata->tsi_Flag = OFF;<br />
<br />
while (tsidata->tsi_Flag != STOPPED) IDOS->Delay(10);<br />
<br />
IExec->CloseDevice((struct IORequest *)tr);<br />
}<br />
else IDOS->Printf("couldn't open timer.device\n");<br />
}<br />
else IDOS->Printf("couldn't create timerequest\n");<br />
<br />
IExec->FreeSysObject(ASOT_IOREQUEST, tr);<br />
}<br />
<br />
IExec->FreeSysObject(ASOT_INTERRUPT, softint);<br />
IExec->FreeSysObject(ASOT_PORT, port);<br />
IExec->FreeVec(tsidata);<br />
<br />
return 0;<br />
}<br />
<br />
void tsoftcode(void)<br />
{<br />
/* Remove the message from the port. */<br />
struct TimeRequest *tr = (struct TimeRequest *)IExec->GetMsg(tsidata->tsi_Port);<br />
<br />
/* Keep on going if main() hasn't set flag to OFF. */<br />
if ((tr) && (tsidata->tsi_Flag == ON))<br />
{<br />
/* increment counter and re-send timerequest--IMPORTANT: This */<br />
/* self-perpetuating technique of calling BeginIO() during a software */<br />
/* interrupt may only be used with the audio and timer device. */<br />
tsidata->tsi_Counter++;<br />
tr->Request.io_Command = TR_ADDREQUEST;<br />
tr->Time.Microseconds = MICRO_DELAY;<br />
IExec->BeginIO((struct IORequest *)tr);<br />
}<br />
/* Tell main() we're out of here. */<br />
else tsidata->tsi_Flag = STOPPED;<br />
}<br />
</syntaxhighlight><br />
<br />
== Disabling Interrupts ==<br />
<br />
As mentioned in [[Exec_Tasks|Exec Tasks]], it is sometimes necessary to disable interrupts when examining or modifying certain shared system data structures. However, for proper system operation, interrupts should never be disabled unless absolutely necessary, and ''never for more than 250 microseconds''. Interrupt disabling is controlled with the Disable() and Enable() functions.<br />
<br />
In some system code, there are nested disabled sections. Such code requires that interrupts be disabled with the first Disable() and not re-enabled until the ''last'' Enable(). The system Enable() and Disable() functions are designed to permit this sort of nesting.<br />
<br />
Disable() increments a counter to track how many levels of disable have been issued. Only 126 levels of nesting are permitted. Enable() decrements the counter, and reenables interrupts when the last disable level has been exited.<br />
<br />
== Quick Interrupts ==<br />
<br />
One of the features of the Zorro III bus is the Quick Interrupt, also known as the vectored interrupt. This feature allows Zorro III<br />
hardware to supply a vector number to the system when an interrupt occurs. The system uses this vector number to go directly to an<br />
interrupt routine.<br />
<br />
=== Conventional Amiga Interrupts ===<br />
<br />
The Amiga handles normal interrupts from Zorro II cards using an interrupt server chain. There are two interrupts available from the<br />
Zorro II bus, the PORTS and EXTER interrupt server chains. If a driver for a Zorro II card needs to use an interrupt, it adds an interrupt routine to the appropriate chain. When the interrupt occurs, Exec calls each routine in the interrupt chain, which are sorted in priority order. Exec continues until it finds the routine that corresponds to the device that triggered the interrupt.<br />
<br />
The server chain allows several routines to share a single interrupt. This means that several devices trigger the same interrupt, so each interrupt routine must do some processing to determine if its card triggered the interrupt or if some other source caused the interrupt. For example, an interrupt routine might examine a register on its card to determine that the card triggered the interrupt.<br />
<br />
Although this scheme allows unrelated pieces of software to easily share an interrupt, it can make the interrupt overhead rather high.<br />
These two interrupt server chains also handle interrupts from the CIA chips, which are used to trigger a variety of events. As a result, these server chains can contain a multitude of interrupt routines.<br />
<br />
Consider what happens when a Zorro II card generates a PORTS interrupt. Exec has to perform some set up and then step through the PORTS server chain. Exec calls each interrupt routine in priority order looking for the routine that services this interrupt. If there are 20 interrupt routines of higher priority than the card's interrupt routine in the server chain, Exec has to call 20 other routines before it gets to the correct routine.<br />
<br />
=== Zorro III Quick Interrupts ===<br />
<br />
Quick interrupts avoid the overhead involved in Exec's interrupt server chains. Exec only helps set up the quick interrupt, which it does via the exec.library function ObtainQuickVector(). Once Exec has set up the quick interrupt routine, it does not intervene. Unlike conventional Amiga interrupt routines, which are called as subroutines from Exec's main interrupt code, the Amiga jumps directly to the quick interrupt routine using a private vector. This behavior requires quick interrupt routines to take some special precautions.<br />
<br />
There are two important differences between a conventional Amiga interrupt routine and a quick quick interrupt routine. A quick<br />
interrupt routine must save and restore all of the registers it changes, including D0, D1, A0, and A1. It must do this because, unlike<br />
regular interrupt routines, Exec doesn't do it for you. Also, a quick interrupt routine ends with a RTE (return from exception) instruction.<br />
<br />
If your quick interrupt routine is 100% self-contained and does not access any operating system structures or routines, then the work is rather simple. Just save the registers you use, perform your interrupt processing, restore the registers, and end with an RTE. If, however, the routine needs to call the OS or use an OS structure, it must check if the interrupt has been delayed. This is necessary in case the interrupt hit the CPU just after the CPU had told the hardware to hold off interrupts (see the Autodoc for ObtainQuickVector() to find out how to perform this test).<br />
<br />
As the Amiga OS is a dynamic operating system, quick interrupts are allocated by the OS. If your hardware/software wants to use a quick<br />
interrupt, it must allocate a vector with ObtainQuickVector(). This routine accepts a pointer to the quick interrupt code (not a pointer to an Interrupt structure). If Exec installed the vector, ObtainQuickVector() returns the vector number. When the quick<br />
interrupt occurs, the Zorro III card sends this vector number to the CPU, which tells the CPU where the interrupt code is.<br />
<br />
ObtainQuickVector() returns 0 if there are no more vectors. Since the number of vectors is limited, any Zorro III device that uses quick interrupts must be able to fall back to the Amiga's conventional interrupt scheme.<br />
<br />
== Function Reference ==<br />
<br />
The following chart gives a brief description of the Exec functions that control interrupts. See the SDK for details about each call.<br />
<br />
{| class="wikitable"<br />
! Interrupt Function<br />
! Description<br />
|-<br />
| AddIntServer()<br />
| Add an interrupt server to a system server chain.<br />
|-<br />
| Cause()<br />
| Cause a software interrupt.<br />
|-<br />
| Disable()<br />
| Disable interrupt processing.<br />
|-<br />
| Enable()<br />
| Restart system interrupt processing.<br />
|-<br />
| RemIntServer()<br />
| Remove an interrupt server from a system server chain.<br />
|-<br />
| SetIntVector()<br />
| Set a new handler for a system interrupt vector.<br />
|}</div>Costel Minceahttps://wiki.amigaos.net/w/index.php?title=Locale_Library&diff=9098Locale Library2016-12-18T09:27:22Z<p>Costel Mincea: /* Environment Variables */</p>
<hr />
<div>== Introduction ==<br />
<br />
Today, computer software is commonly marketed and used globally. But programs that work for users in one country or territory may not work so well in another, because local specifics can turn certain aspects into barriers hampering usability. An obvious barrier is language but there are others. For example, an accounting program would be an utter flop if it didn't support different numeric systems and currencies. Therefore, modern computer applications need to be designed to account for various local conditions, conventions and customs. Otherwise your product – free or commercial – can easily get rejected by users.<br />
<br />
The process of adapting software to the linguistic, cultural and technical requirements of a local market is called ''localization''. This process typically entails:<br />
<br />
* translation of the application's user interface into the target language<br />
* translation of the application's documentation and help files into the target language<br />
* adaptation to specific writing conventions such as punctuation, number formatting, date and time format etc.<br />
* use of local units of measurement, currency etc.<br />
* use of language-specific sorting rules<br />
* support for a particular character set<br />
* adaptation of keyboard shortcuts (where mnemonics are desirable to be preserved)<br />
* etc.<br />
<br />
Amiga software developers are encouraged to use the Locale Library to localize their applications. Additional tools are also available to help in the process.<br />
<br />
== Locale ==<br />
<br />
In the context of AmigaOS, the term ''locale'' refers to a set of parameters defining various language-specific and country-specific properties. Localized Amiga software takes these properties from system files stored on disk, instead of hardcoding them into the application. Thus, no recompiling is required: properly localized Amiga applications dynamically adapt themselves to the current locale.<br />
<br />
Locale settings are made on the user level, from the Locale editor found in your Prefs drawer. For example, a Danish user would normally use the editor to select a Danish locale for his/her system.<br />
<br />
=== Accessing Locale Parameters ===<br />
<br />
The Locale Library provides access to the respective settings and parameters via a public data structure called, quite predictably, ''Locale'' (see the <libraries/locale.h> include file for definition; the structure is rather extensive). The programmer can query about the individual locale parameters by calling OpenLocale() and then reading from the data structure, the pointer to which is returned as the function result. You will also need this pointer if you want to use certain Locale Library functions.<br />
<br />
OpenLocale() takes the name of the locale as parameter. Most applications will pass NULL, indicating the current system locale. The provided data structure is strictly read-only, and the pointer to it can no longer be used after you call CloseLocale().<br />
<br />
The following code fragment opens the current system locale, prints the English name of the associated language (as retrieved from the Locale structure), and closes the locale:<br />
<br />
<syntaxhighlight><br />
struct Locale *currentLocale;<br />
<br />
if ( (currentLocale = ILocale->OpenLocale(NULL)) )<br />
{<br />
IDOS->Printf("The language of this locale is %s.\n", currentLocale->loc_LanguageName);<br />
ILocale->CloseLocale(currentLocale);<br />
}<br />
</syntaxhighlight><br />
<br />
=== Standard Locale Strings ===<br />
<br />
The library also provides a set of commonly-used strings, the localized versions of which are part of each locale. These "standard" strings include:<br />
<br />
* the names of the days of the week (incl. their abbreviations and alternate forms)<br />
* month names (incl. their abbreviations and alternate forms)<br />
* time reference expressions like "today", "yesterday", "tomorrow" and "future"<br />
* the "yes/no" strings used as response in requester gadgets<br />
* the characters used as quotation marks in the particular language<br />
* the native name of the language ("Deutsch" for German, "Français" for French, etc.).<br />
<br />
An AmigaOS application – for example, a calendar or a [https://en.wikipedia.org/wiki/Personal_organizer personal organiser] – will not provide these strings but, rather, obtain them from the locale using GetLocaleStr() and a respective string code as defined in <libraries/locale.h>.<br />
<br />
The following code fragment opens the current system locale, prints the native name of the language and the localized name of the first month of the year, then closes the locale:<br />
<br />
<syntaxhighlight><br />
struct Locale *currentLocale;<br />
<br />
if ( (currentLocale = ILocale->OpenLocale(NULL)) )<br />
{<br />
IDOS->Printf("The native name of the language is %s.\n", <br />
ILocale->GetLocaleStr(currentLocale, LANG_NAME));<br />
IDOS->Printf("The first month is called %s in this language.\n", <br />
ILocale->GetLocaleStr(currentLocale, MON_1));<br />
ILocale->CloseLocale(currentLocale);<br />
}<br />
</syntaxhighlight><br />
<br />
=== Environment Variables ===<br />
<br />
Certain common locale parameters can also be retrieved from global environment variables that the library maintains. These include:<br />
<br />
; LanguageName<br />
: The name of the current default language as used in the system. This is the English name of the language, and it is the same value you would obtain from the ''loc_LanguageName'' field of the Locale structure as returned by OpenLocale(NULL).<br />
<br />
; Language<br />
: The name of the current default language as used in the system. This is the localized name of the language as it was used in the past, if available.<br />
<br />
; Charset<br />
: The MIME name of the current default character set as used in the system. Please note that this value does NOT correspond with that of the ''loc_CodeSet'' field of the Locale structure returned by OpenLocale(NULL). The ''Charset'' environmental variable contains the name of the character set (i.e. a string value), whereas ''loc_CodeSet'' provides its IANA number (that is, an integer value).<br />
<br />
In a CLI environment (the Shell, for example) you can use the AmigaDOS [[AmigaOS_Manual:_AmigaDOS_Command_Reference#GETENV|GETENV]] command to retrieve and display the respective variable value:<br />
<br />
1> GETENV LanguageName<br />
czech<br />
<br />
1> GETENV Charset<br />
ISO-8859-2<br />
<br />
In program code you need to call the DOS Library function GetVar(). The following snippet shows how to retrieve the name of the current character set:<br />
<br />
<syntaxhighlight><br />
char charSet[32];<br />
<br />
if ( IDOS->GetVar("Charset", charSet, sizeof(charSet), GVF_GLOBAL_ONLY) != -1 )<br />
{<br />
IDOS->Printf("The current default character set is %s\n", charSet);<br />
}<br />
</syntaxhighlight><br />
<br />
== Catalogs ==<br />
<br />
For most applications (regardless of the operating system), the grunt of the localization work lies in translating the user interface. This typically involves the translation of all text strings that are used and displayed by the program: window titles, menu- and button labels, various program messages etc. In AmigaOS, all strings translated into a particular language are put into a special binary file called the ''catalog'' (also referred to as ''locale catalog'' or ''message catalog'').<br />
<br />
A separate catalog file is needed for every language that is to be supported by the application, except English. A localized Amiga application is required to provide a full set of ''built-in strings'' in English to default to. These strings are part of the application executable and will be used if no catalog files are found – or, of course, if the English language is selected for the current [[#Locale|locale]].<br />
<br />
(to be continued)<br />
<br />
== Function Reference ==<br />
<br />
The following table gives a brief description of the Locale Library functions. See the SDK/Autodocs for details about each call.<br />
<br />
{| class="wikitable"<br />
! Function<br />
! Description<br />
|-<br />
| CloseCatalog()<br />
| Close a message catalog.<br />
|-<br />
| CloseLocale()<br />
| Close a locale.<br />
|-<br />
| ConvToLower()<br />
| Convert a character to lower case.<br />
|-<br />
| ConvToUpper()<br />
| Convert a character to upper case.<br />
|-<br />
| FormatDate()<br />
| Generate a date string based on a date formatting template.<br />
|-<br />
| FormatString()<br />
| Format data into a character stream, assume 16bit-aligned data.<br />
|-<br />
| FormatString32()<br />
| Format data into a character stream, assume 32bit-aligned data.<br />
|-<br />
| GetCatalogStr()<br />
| Get a string from a message catalog.<br />
|-<br />
| GetLocaleStr()<br />
| Get a standard string from a locale.<br />
|-<br />
| IsXXXX()<br />
| A set of similarly-named functions to determine whether a character is of a certain type.<br />
|-<br />
| OpenCatalog()<br />
| Open a message catalog.<br />
|-<br />
| OpenLocale()<br />
| Open a locale.<br />
|-<br />
| ParseDate()<br />
| Interpret a string according to the date formatting template and convert it into a DateStamp.<br />
|-<br />
| StrConvert()<br />
| Transform a string according to collation information.<br />
|-<br />
| StrnCmp()<br />
| Localized string comparison.<br />
|}</div>Costel Minceahttps://wiki.amigaos.net/w/index.php?title=Deprecated_Functions&diff=8546Deprecated Functions2016-04-29T13:16:14Z<p>Costel Mincea: /* Other */</p>
<hr />
<div>== Deprecated and Obsolete Functions ==<br />
<br />
With the introduction of AmigaOS 4.1 Final Edition, developers may have noticed additional compiler warnings when rebuilding their projects against the new SDK. While as much of the API has been maintained as is possible, some functions, structures, attributes, and tags have changed over time requiring the attention of application developers. To make life easier, the following is a handy guide to items that have been deprecated or made obsolete with this most recent release. If your code uses any of these items, please refer to the [[Autodocs:Main|Autodocs]] for the component noted to review. Some functions may need to be replaced and others may have changed behavior. It's always a good idea to review the [[SDK Release Notes|Release Notes]] with each SDK release, of course, too. <br />
<br />
This article is inclusive of code made obsolete or deprecated since V50 of the components listed below. Please feel free to edit the document based on your findings should the author have overlooked anything.<br />
<br />
== Components to Review ==<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/asl.doc.txt ASL Library] ===<br />
<br />
==== Deprecated functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement<br />
|-<br />
| AllocFileRequest<br />
| AllocAslRequest<br />
|-<br />
| FreeFileRequest <br />
| FreeAslRequest<br />
|-<br />
| RequestFile<br />
| AslRequest<br />
|}<br />
<br />
==== Other ====<br />
<br />
The following components in the ASL_FileRequest object are obsolete: ''ASLFR_HookFunc, ASLFO_HookFunc,'' and ''ASLFR_FilterFunc.'' For the latter, use ASLFR_FilterHook as a possible replacement.<br />
<br />
=== BOOPSI Classes/Gadgets ===<br />
<br />
Generally all BOOPSI gadget classes and superclasses had a #?_GetClass() function to return a pointer to the class itself. These functions are deprecated as of V52. Developers should use the gadget public class ID as a replacement. Some gadgets are listed separately in this article as they have other items now deprecated or obsolete; if a gadget is not listed herein, the above note regarding pointers should be the only item considered deprecated for it.<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/bsdsocket.doc.txt BSD Sockets Library] ===<br />
<br />
==== Deprecated Functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement<br />
|-<br />
| Errno<br />
| SocketBaseTags (with SBTC_ERRNO tag)<br />
|-<br />
| getdtablesize<br />
| SocketBaseTags (with SBTC_DTABLESIZE tag)<br />
|-<br />
| gethostid<br />
| n/a<br />
|-<br />
| SetErrnoPtr<br />
| SocketBaseTags (with SBTC_ERRNOPTR tag)<br />
|-<br />
| SetSocketSignals<br />
| SocketBaseTags<br />
|}<br />
<br />
==== Other ====<br />
<br />
* The following IoctlSocket() calls are considered deprecated: SIOCSIFADDR, SIOCSIFDSTADDR, SIOCSIFBRDADDR, SIOCGIFADDR, SIOCGIFDSTADDR, SIOCGIFBRDADDR, SIOCSIFFLAGS, SIOCGIFFLAGS, SIOCSIFMETRIC, and SIOCGIFMETRIC. <br />
* Several functions used in conjunction with SocketBaseTagList() are now deprecated as well: SBTC_FDCALLBACK, SBTC_IOERRNOSTRPTR, SBTC_S2ERRNOSTRPTR, SBTC_S2WERRNOSTRPTR, SBTC_SIGIOMASK, and SBTC_SIGURGMASK.h<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/chooser_gc.doc.txt Chooser Gadget] ===<br />
<br />
* The CHOOSER_GetClass function is no longer available. Use the "chooser.gadget" public class ID instead.<br />
* The chooser.gadget attribute CHOOSER_AutoFit is now unsupported<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/console.doc.txt Console Device] ===<br />
<br />
==== Deprecated Functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement (component)<br />
! scope="col"| Replacement (function)<br />
|-<br />
| CD_ASKDEFAULTKEYMAP<br />
| keymap.library<br />
| AskKeyMapDefault<br />
|-<br />
| CD_ASKKEYMAP<br />
| console.device<br />
| CD_ASKKEYMAP_POINTERS<br />
|-<br />
| CD_SETDEFAULTKEYMAP<br />
| keymap.library<br />
| SetKeyMapDefault<br />
|-<br />
| CD_SETKEYMAP<br />
| console.device<br />
| CD_SETKEYMAP_POINTERS<br />
|}<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/dos.doc.txt DOS Library] ===<br />
<br />
The collective changes to the DOS subsystem are substantial and developers are urged to review the [http://wiki.amigaos.net/amiga/autodocs/dos.obsolete.doc.txt Obsolete DOS documentation] as a starting point. Additionally with the introduction of the new [[AmigaDOS Vector-Port|Vector-Port]] API, use of [[AmigaDOS Packets|DOS packets]] is (for the most part) no longer needed. Please carefully read through the documentation when starting a new project with the release of V54.<br />
<br />
==== Deprecated Or Renamed Functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement<br />
|-<br />
|CreateProc<br />
|CreateNewProc<br />
|-<br />
|CurrentDir<br />
|SetCurrentDir<br />
|-<br />
|DeleteFile<br />
|Delete<br />
|-<br />
|DeviceProc<br />
|GetDeviceProc<br />
|-<br />
|ExAll<br />
|ExamineDir<br />
|-<br />
| Examine<br />
| ExamineObject<br />
|-<br />
| ExamineFH<br />
| ExamineObject<br />
|-<br />
|Execute<br />
|System<br />
|-<br />
|ExNext<br />
|ExamineDir<br />
|-<br />
|Flush<br />
|FFlush<br />
|-<br />
| FreeDosEntry<br />
| FreeDosObject<br />
|-<br />
| GetConsoleTask<br />
| GetConsolePort<br />
|-<br />
|GetCurrentDirName<br />
|GetCliCurrentDirName<br />
|-<br />
| GetFileSysTask<br />
| GetFileSysPort<br />
|-<br />
|GetProgramName<br />
|GetCliProgramName<br />
|-<br />
|GetPrompt<br />
|GetCliPrompt<br />
|-<br />
| MakeDosEntry<br />
| AllocDosObject<br />
|- <br />
| ReadItem<br />
| ReadLineItem<br />
|-<br />
|ReadLink<br />
|ReadSoftLink<br />
|-<br />
| Seek<br />
| SetFilePosition / GetFilePosition<br />
|-<br />
| SetConsoleTask<br />
| SetConsolePort<br />
|-<br />
|SetCurrentDirName<br />
|SetCliCurrentDirName<br />
|-<br />
|SetFileDate<br />
|SetDate<br />
|-<br />
| SetFileSize<br />
| ChangeFileSize<br />
|-<br />
| SetFileSysTask<br />
| SetFileSysPort<br />
|-<br />
| SetOwner<br />
| SetOwnerInfo<br />
|-<br />
|SetProgramName<br />
|SetCliProgramName<br />
|-<br />
|SetPrompt<br />
|SetCliPrompt<br />
|-<br />
| SetVBuf<br />
| SetFileHandleAttr<br />
|}<br />
<br />
==== Other ====<br />
<br />
* If you absolutely need backwards compatibility to old source, include ''dos/obsolete.h'' for old function names, structures and defines. '''Not recommended'''.<br />
* Several functions had name changes in V53. Please review ''dos/obsolete.h'' in the SDK includes if you haven't already updated prior to the release of V54.<br />
* Before V53, CreateDir() returned an exclusive lock on the new directory if it succeeded, it is now required that this be a a shared lock. Exclusive directory locks have been deprecated. Only files may actually have exclusive locks.<br />
* The id_NumSoftErrors and id_UnitNumber fields of the GDI_InfoData structure returned from GetDiskInfo() and Info() are considered deprecated.<br />
* The following error codes returned from IoErr() are considered obsolete: ERROR_TASK_TABLE_FULL, ERROR_NO_DEFAULT_DIR, ERROR_OBJECT_LINKED, and ERROR_UNLOCK_ERROR.<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/exec.doc.txt Exec Library] ===<br />
<br />
==== Deprecated Functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement<br />
|-<br />
| AllocEntry<br />
| AllocTaskMemEntry<br />
|-<br />
| AllocMem<br />
| AllocVecTagList or AllocVecTags<br />
|-<br />
| AllocVec<br />
| AllocVecTagList or AllocVecTags<br />
|-<br />
| CachePreDMA<br />
| StartDMA<br />
|-<br />
| CachePostDMA<br />
| EndDMA<br />
|-<br />
| CreatePool<br />
| AllocSysObject<br />
|-<br />
| MakeLibrary<br />
| CreateLibrary<br />
|-<br />
| AllocTrap<br />
| ''(for 68K only, no longer used)''<br />
|-<br />
| FreeTrap<br />
| ''(for 68K only, no longer used)''<br />
|-<br />
| GetCC<br />
| ''(for 68K only, no longer used)''<br />
|-<br />
| SetSR<br />
| ''(for 68K only, no longer used)''<br />
|}<br />
<br />
==== Memory Flags ====<br />
<br />
Allocating memory with modern Exec is slightly different than before. In addition to using AllocVecTagList or AllocVecTags rather than AllocMem, several flags are no longer relevant. Please review the article on [[Obsolete_Exec_Memory_Allocation|Obsolete Memory Allocation Techniques]] to note what to avoid. Developers should follow the documentation in the [[Exec Memory Allocation|Memory Allocation]] section instead.<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/libamiga_a.doc.txt libamiga.a] ===<br />
<br />
==== Deprecated Functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement (component)<br />
! scope="col"| Replacement (function)<br />
|-<br />
| BeginIO<br />
| exec.library<br />
| BeginIO<br />
|-<br />
| CreateExtIO<br />
| exec.library<br />
| CreateIORequest<br />
|-<br />
| CreatePort<br />
| exec.library<br />
| CreatePort<br />
|-<br />
| CreateStdIO<br />
| exec.library<br />
| CreateIORequest<br />
|-<br />
| CreateTask<br />
| exec.library<br />
| CreateTask<br />
|-<br />
| DeleteExtIO<br />
| exec.library<br />
| DeleteIORequest<br />
|-<br />
| DeletePort<br />
| exec.library<br />
| DeletePort<br />
|-<br />
| DeleteStdIO<br />
| exec.library<br />
| DeleteIORequest<br />
|-<br />
| DeleteTask<br />
| exec.library<br />
| DeleteTask<br />
|-<br />
| NewList<br />
| exec.library<br />
| NewList<br />
|}<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/listbrowser_gc.doc.txt Listbrowser Gadget] ===<br />
<br />
* The LISTBROWSER_GetClass function is no longer available. Use the "listbrowser.gadget" public class ID instead<br />
* The listbrowser.gadget attribute LISTBROWSER_FastRender is obsolete; there is no replacement.<br />
* The SetLBColumnInfoAttrsA function no longer accepts flags via LBCIA_Flags. One should use the equivalent tags instead.<br />
<br />
=== Math IEEE libraries (68K) ===<br />
<br />
As of V45 of mathieeedoubbas.library, mathieeedoubtrans.library, mathieeesingbas.library, and mathieeesingtrans.library, the mathieee.resources are no longer supported. It was felt that this solution was never very popular, neither very fast compared to a co-processor interface, and highly obsolete. This is doubly so in the PowerPC era of next-generation AmigaOne computers. They are included in the operating system merely for compatibility purposes and should not be used for new applications.<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/Picasso96API.doc.txt Picasso96 API Library] ===<br />
<br />
Starting with graphics.library V54, the vast majority of Picasso96 is now redundant. The graphics.library has been expanded and extended to seamlessly handle the traditional native (ECS, AGA) chip sets as well as modern graphics cards (RTG). Please carefully review the autodoc and consider migrating to the newer graphics.library-based API.<br />
<br />
==== Deprecated Functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement (component)<br />
! scope="col"| Replacement (function)<br />
|-<br />
| p96AllocBitMap<br />
| graphics.library<br />
| AllocBitMapTags<br />
|-<br />
| p96FreeBitMap<br />
| graphics.library<br />
| FreeBitMap<br />
|-<br />
| p96LockBitMap<br />
| graphics.library<br />
| LockBitMapTags<br />
|-<br />
| p96LockBitMapToBoard<br />
| graphics.library<br />
| LockBitMapToBoardTags<br />
|-<br />
| p96ReadPixel<br />
| graphics.library<br />
| ReadPixelColor<br />
|-<br />
| p96ReadPixelArray<br />
| graphics.library<br />
| ReadPixelArray<br />
|-<br />
| p96RectFill<br />
| graphics.library<br />
| RectFillColor<br />
|-<br />
| p96UnlockBitMap<br />
| graphics.library<br />
| UnlockBitMap<br />
|-<br />
| p96UnlockBitMapFromBoard<br />
| graphics.library<br />
| UnlockBitMapFromBoard<br />
|-<br />
| p96WritePixel<br />
| graphics.library<br />
| WritePixelColor<br />
|-<br />
| p96WritePixelArray<br />
| graphics.library<br />
| WritePixelArray<br />
|}<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/space_gc.doc.txt Space Gadget] ===<br />
<br />
* The SPACE_GetClass function is no longer available. Use the "space.gadget" public class ID instead.<br />
* The space.gadget SPACE_AreaBox tag is deprecated because it is unsafe to use in a multi-tasking environment. Use SPACE_RenderBox instead.<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/texteditor_gc.doc.txt Texteditor Gadget] ===<br />
<br />
* The TEXTEDITOR_GetClass function is no longer available. Use the "texteditor.gadget" public class ID instead.<br />
* The texteditor.gadget attributes GA_TEXTEDITOR_Prop_DeltaFactor and GA_TEXTEDITOR_HProp_DeltaFactor are now obsolete.<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/warp3d.doc.txt Warp3D Library] ===<br />
<br />
==== Deprecated functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement<br />
|-<br />
| W3D_GetDestFmt<br />
| W3D_Query<br />
|}<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/window_cl.doc.txt Window Class] ===<br />
<br />
* The WINDOW_HintInfo attribute for gadget HelpHints is now considered obsolete and only included for compatibility purposes. Developers should supply all of the hints via the GA_HintInfo attribute of each gadget, and set the WINDOW_GadgetHelp attribute for future projects.<br />
* The WINDOW_Layout tag has 2 aliased definitions which are now obsolete but still supported in the include files.</div>Costel Minceahttps://wiki.amigaos.net/w/index.php?title=Deprecated_Functions&diff=8545Deprecated Functions2016-04-29T13:13:27Z<p>Costel Mincea: /* Deprecated Functions */</p>
<hr />
<div>== Deprecated and Obsolete Functions ==<br />
<br />
With the introduction of AmigaOS 4.1 Final Edition, developers may have noticed additional compiler warnings when rebuilding their projects against the new SDK. While as much of the API has been maintained as is possible, some functions, structures, attributes, and tags have changed over time requiring the attention of application developers. To make life easier, the following is a handy guide to items that have been deprecated or made obsolete with this most recent release. If your code uses any of these items, please refer to the [[Autodocs:Main|Autodocs]] for the component noted to review. Some functions may need to be replaced and others may have changed behavior. It's always a good idea to review the [[SDK Release Notes|Release Notes]] with each SDK release, of course, too. <br />
<br />
This article is inclusive of code made obsolete or deprecated since V50 of the components listed below. Please feel free to edit the document based on your findings should the author have overlooked anything.<br />
<br />
== Components to Review ==<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/asl.doc.txt ASL Library] ===<br />
<br />
==== Deprecated functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement<br />
|-<br />
| AllocFileRequest<br />
| AllocAslRequest<br />
|-<br />
| FreeFileRequest <br />
| FreeAslRequest<br />
|-<br />
| RequestFile<br />
| AslRequest<br />
|}<br />
<br />
==== Other ====<br />
<br />
The following components in the ASL_FileRequest object are obsolete: ''ASLFR_HookFunc, ASLFO_HookFunc,'' and ''ASLFR_FilterFunc.'' For the latter, use ASLFR_FilterHook as a possible replacement.<br />
<br />
=== BOOPSI Classes/Gadgets ===<br />
<br />
Generally all BOOPSI gadget classes and superclasses had a #?_GetClass() function to return a pointer to the class itself. These functions are deprecated as of V52. Developers should use the gadget public class ID as a replacement. Some gadgets are listed separately in this article as they have other items now deprecated or obsolete; if a gadget is not listed herein, the above note regarding pointers should be the only item considered deprecated for it.<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/bsdsocket.doc.txt BSD Sockets Library] ===<br />
<br />
==== Deprecated Functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement<br />
|-<br />
| Errno<br />
| SocketBaseTags (with SBTC_ERRNO tag)<br />
|-<br />
| getdtablesize<br />
| SocketBaseTags (with SBTC_DTABLESIZE tag)<br />
|-<br />
| gethostid<br />
| n/a<br />
|-<br />
| SetErrnoPtr<br />
| SocketBaseTags (with SBTC_ERRNOPTR tag)<br />
|-<br />
| SetSocketSignals<br />
| SocketBaseTags<br />
|}<br />
<br />
==== Other ====<br />
<br />
* The following IoctlSocket() calls are considered deprecated: SIOCSIFADDR, SIOCSIFDSTADDR, SIOCSIFBRDADDR, SIOCGIFADDR, SIOCGIFDSTADDR, SIOCGIFBRDADDR, SIOCSIFFLAGS, SIOCGIFFLAGS, SIOCSIFMETRIC, and SIOCGIFMETRIC. <br />
* Several functions used in conjunction with SocketBaseTagList() are now deprecated as well: SBTC_FDCALLBACK, SBTC_IOERRNOSTRPTR, SBTC_S2ERRNOSTRPTR, SBTC_S2WERRNOSTRPTR, SBTC_SIGIOMASK, and SBTC_SIGURGMASK.h<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/chooser_gc.doc.txt Chooser Gadget] ===<br />
<br />
* The CHOOSER_GetClass function is no longer available. Use the "chooser.gadget" public class ID instead.<br />
* The chooser.gadget attribute CHOOSER_AutoFit is now unsupported<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/console.doc.txt Console Device] ===<br />
<br />
==== Deprecated Functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement (component)<br />
! scope="col"| Replacement (function)<br />
|-<br />
| CD_ASKDEFAULTKEYMAP<br />
| keymap.library<br />
| AskKeyMapDefault<br />
|-<br />
| CD_ASKKEYMAP<br />
| console.device<br />
| CD_ASKKEYMAP_POINTERS<br />
|-<br />
| CD_SETDEFAULTKEYMAP<br />
| keymap.library<br />
| SetKeyMapDefault<br />
|-<br />
| CD_SETKEYMAP<br />
| console.device<br />
| CD_SETKEYMAP_POINTERS<br />
|}<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/dos.doc.txt DOS Library] ===<br />
<br />
The collective changes to the DOS subsystem are substantial and developers are urged to review the [http://wiki.amigaos.net/amiga/autodocs/dos.obsolete.doc.txt Obsolete DOS documentation] as a starting point. Additionally with the introduction of the new [[AmigaDOS Vector-Port|Vector-Port]] API, use of [[AmigaDOS Packets|DOS packets]] is (for the most part) no longer needed. Please carefully read through the documentation when starting a new project with the release of V54.<br />
<br />
==== Deprecated Or Renamed Functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement<br />
|-<br />
|CreateProc<br />
|CreateNewProc<br />
|-<br />
|CurrentDir<br />
|SetCurrentDir<br />
|-<br />
|DeleteFile<br />
|Delete<br />
|-<br />
|DeviceProc<br />
|GetDeviceProc<br />
|-<br />
|ExAll<br />
|ExamineDir<br />
|-<br />
| Examine<br />
| ExamineObject<br />
|-<br />
| ExamineFH<br />
| ExamineObject<br />
|-<br />
|Execute<br />
|System<br />
|-<br />
|ExNext<br />
|ExamineDir<br />
|-<br />
|Flush<br />
|FFlush<br />
|-<br />
| FreeDosEntry<br />
| FreeDosObject<br />
|-<br />
| GetConsoleTask<br />
| GetConsolePort<br />
|-<br />
|GetCurrentDirName<br />
|GetCliCurrentDirName<br />
|-<br />
| GetFileSysTask<br />
| GetFileSysPort<br />
|-<br />
|GetProgramName<br />
|GetCliProgramName<br />
|-<br />
|GetPrompt<br />
|GetCliPrompt<br />
|-<br />
| MakeDosEntry<br />
| AllocDosObject<br />
|- <br />
| ReadItem<br />
| ReadLineItem<br />
|-<br />
|ReadLink<br />
|ReadSoftLink<br />
|-<br />
| Seek<br />
| SetFilePosition / GetFilePosition<br />
|-<br />
| SetConsoleTask<br />
| SetConsolePort<br />
|-<br />
|SetCurrentDirName<br />
|SetCliCurrentDirName<br />
|-<br />
|SetFileDate<br />
|SetDate<br />
|-<br />
| SetFileSize<br />
| ChangeFileSize<br />
|-<br />
| SetFileSysTask<br />
| SetFileSysPort<br />
|-<br />
| SetOwner<br />
| SetOwnerInfo<br />
|-<br />
|SetProgramName<br />
|SetCliProgramName<br />
|-<br />
|SetPrompt<br />
|SetCliPrompt<br />
|-<br />
| SetVBuf<br />
| SetFileHandleAttr<br />
|}<br />
<br />
==== Other ====<br />
<br />
* Several functions had name changes in V53. Please review ''dos/obsolete.h'' in the SDK includes if you haven't already updated prior to the release of V54.<br />
* Before V53, CreateDir() returned an exclusive lock on the new directory if it succeeded, it is now required that this be a a shared lock. Exclusive directory locks have been deprecated. Only files may actually have exclusive locks.<br />
* The id_NumSoftErrors and id_UnitNumber fields of the GDI_InfoData structure returned from GetDiskInfo() and Info() are considered deprecated.<br />
* The following error codes returned from IoErr() are considered obsolete: ERROR_TASK_TABLE_FULL, ERROR_NO_DEFAULT_DIR, ERROR_OBJECT_LINKED, and ERROR_UNLOCK_ERROR.<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/exec.doc.txt Exec Library] ===<br />
<br />
==== Deprecated Functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement<br />
|-<br />
| AllocEntry<br />
| AllocTaskMemEntry<br />
|-<br />
| AllocMem<br />
| AllocVecTagList or AllocVecTags<br />
|-<br />
| AllocVec<br />
| AllocVecTagList or AllocVecTags<br />
|-<br />
| CachePreDMA<br />
| StartDMA<br />
|-<br />
| CachePostDMA<br />
| EndDMA<br />
|-<br />
| CreatePool<br />
| AllocSysObject<br />
|-<br />
| MakeLibrary<br />
| CreateLibrary<br />
|-<br />
| AllocTrap<br />
| ''(for 68K only, no longer used)''<br />
|-<br />
| FreeTrap<br />
| ''(for 68K only, no longer used)''<br />
|-<br />
| GetCC<br />
| ''(for 68K only, no longer used)''<br />
|-<br />
| SetSR<br />
| ''(for 68K only, no longer used)''<br />
|}<br />
<br />
==== Memory Flags ====<br />
<br />
Allocating memory with modern Exec is slightly different than before. In addition to using AllocVecTagList or AllocVecTags rather than AllocMem, several flags are no longer relevant. Please review the article on [[Obsolete_Exec_Memory_Allocation|Obsolete Memory Allocation Techniques]] to note what to avoid. Developers should follow the documentation in the [[Exec Memory Allocation|Memory Allocation]] section instead.<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/libamiga_a.doc.txt libamiga.a] ===<br />
<br />
==== Deprecated Functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement (component)<br />
! scope="col"| Replacement (function)<br />
|-<br />
| BeginIO<br />
| exec.library<br />
| BeginIO<br />
|-<br />
| CreateExtIO<br />
| exec.library<br />
| CreateIORequest<br />
|-<br />
| CreatePort<br />
| exec.library<br />
| CreatePort<br />
|-<br />
| CreateStdIO<br />
| exec.library<br />
| CreateIORequest<br />
|-<br />
| CreateTask<br />
| exec.library<br />
| CreateTask<br />
|-<br />
| DeleteExtIO<br />
| exec.library<br />
| DeleteIORequest<br />
|-<br />
| DeletePort<br />
| exec.library<br />
| DeletePort<br />
|-<br />
| DeleteStdIO<br />
| exec.library<br />
| DeleteIORequest<br />
|-<br />
| DeleteTask<br />
| exec.library<br />
| DeleteTask<br />
|-<br />
| NewList<br />
| exec.library<br />
| NewList<br />
|}<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/listbrowser_gc.doc.txt Listbrowser Gadget] ===<br />
<br />
* The LISTBROWSER_GetClass function is no longer available. Use the "listbrowser.gadget" public class ID instead<br />
* The listbrowser.gadget attribute LISTBROWSER_FastRender is obsolete; there is no replacement.<br />
* The SetLBColumnInfoAttrsA function no longer accepts flags via LBCIA_Flags. One should use the equivalent tags instead.<br />
<br />
=== Math IEEE libraries (68K) ===<br />
<br />
As of V45 of mathieeedoubbas.library, mathieeedoubtrans.library, mathieeesingbas.library, and mathieeesingtrans.library, the mathieee.resources are no longer supported. It was felt that this solution was never very popular, neither very fast compared to a co-processor interface, and highly obsolete. This is doubly so in the PowerPC era of next-generation AmigaOne computers. They are included in the operating system merely for compatibility purposes and should not be used for new applications.<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/Picasso96API.doc.txt Picasso96 API Library] ===<br />
<br />
Starting with graphics.library V54, the vast majority of Picasso96 is now redundant. The graphics.library has been expanded and extended to seamlessly handle the traditional native (ECS, AGA) chip sets as well as modern graphics cards (RTG). Please carefully review the autodoc and consider migrating to the newer graphics.library-based API.<br />
<br />
==== Deprecated Functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement (component)<br />
! scope="col"| Replacement (function)<br />
|-<br />
| p96AllocBitMap<br />
| graphics.library<br />
| AllocBitMapTags<br />
|-<br />
| p96FreeBitMap<br />
| graphics.library<br />
| FreeBitMap<br />
|-<br />
| p96LockBitMap<br />
| graphics.library<br />
| LockBitMapTags<br />
|-<br />
| p96LockBitMapToBoard<br />
| graphics.library<br />
| LockBitMapToBoardTags<br />
|-<br />
| p96ReadPixel<br />
| graphics.library<br />
| ReadPixelColor<br />
|-<br />
| p96ReadPixelArray<br />
| graphics.library<br />
| ReadPixelArray<br />
|-<br />
| p96RectFill<br />
| graphics.library<br />
| RectFillColor<br />
|-<br />
| p96UnlockBitMap<br />
| graphics.library<br />
| UnlockBitMap<br />
|-<br />
| p96UnlockBitMapFromBoard<br />
| graphics.library<br />
| UnlockBitMapFromBoard<br />
|-<br />
| p96WritePixel<br />
| graphics.library<br />
| WritePixelColor<br />
|-<br />
| p96WritePixelArray<br />
| graphics.library<br />
| WritePixelArray<br />
|}<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/space_gc.doc.txt Space Gadget] ===<br />
<br />
* The SPACE_GetClass function is no longer available. Use the "space.gadget" public class ID instead.<br />
* The space.gadget SPACE_AreaBox tag is deprecated because it is unsafe to use in a multi-tasking environment. Use SPACE_RenderBox instead.<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/texteditor_gc.doc.txt Texteditor Gadget] ===<br />
<br />
* The TEXTEDITOR_GetClass function is no longer available. Use the "texteditor.gadget" public class ID instead.<br />
* The texteditor.gadget attributes GA_TEXTEDITOR_Prop_DeltaFactor and GA_TEXTEDITOR_HProp_DeltaFactor are now obsolete.<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/warp3d.doc.txt Warp3D Library] ===<br />
<br />
==== Deprecated functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement<br />
|-<br />
| W3D_GetDestFmt<br />
| W3D_Query<br />
|}<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/window_cl.doc.txt Window Class] ===<br />
<br />
* The WINDOW_HintInfo attribute for gadget HelpHints is now considered obsolete and only included for compatibility purposes. Developers should supply all of the hints via the GA_HintInfo attribute of each gadget, and set the WINDOW_GadgetHelp attribute for future projects.<br />
* The WINDOW_Layout tag has 2 aliased definitions which are now obsolete but still supported in the include files.</div>Costel Minceahttps://wiki.amigaos.net/w/index.php?title=Deprecated_Functions&diff=8544Deprecated Functions2016-04-29T10:47:35Z<p>Costel Mincea: /* Deprecated Functions */</p>
<hr />
<div>== Deprecated and Obsolete Functions ==<br />
<br />
With the introduction of AmigaOS 4.1 Final Edition, developers may have noticed additional compiler warnings when rebuilding their projects against the new SDK. While as much of the API has been maintained as is possible, some functions, structures, attributes, and tags have changed over time requiring the attention of application developers. To make life easier, the following is a handy guide to items that have been deprecated or made obsolete with this most recent release. If your code uses any of these items, please refer to the [[Autodocs:Main|Autodocs]] for the component noted to review. Some functions may need to be replaced and others may have changed behavior. It's always a good idea to review the [[SDK Release Notes|Release Notes]] with each SDK release, of course, too. <br />
<br />
This article is inclusive of code made obsolete or deprecated since V50 of the components listed below. Please feel free to edit the document based on your findings should the author have overlooked anything.<br />
<br />
== Components to Review ==<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/asl.doc.txt ASL Library] ===<br />
<br />
==== Deprecated functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement<br />
|-<br />
| AllocFileRequest<br />
| AllocAslRequest<br />
|-<br />
| FreeFileRequest <br />
| FreeAslRequest<br />
|-<br />
| RequestFile<br />
| AslRequest<br />
|}<br />
<br />
==== Other ====<br />
<br />
The following components in the ASL_FileRequest object are obsolete: ''ASLFR_HookFunc, ASLFO_HookFunc,'' and ''ASLFR_FilterFunc.'' For the latter, use ASLFR_FilterHook as a possible replacement.<br />
<br />
=== BOOPSI Classes/Gadgets ===<br />
<br />
Generally all BOOPSI gadget classes and superclasses had a #?_GetClass() function to return a pointer to the class itself. These functions are deprecated as of V52. Developers should use the gadget public class ID as a replacement. Some gadgets are listed separately in this article as they have other items now deprecated or obsolete; if a gadget is not listed herein, the above note regarding pointers should be the only item considered deprecated for it.<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/bsdsocket.doc.txt BSD Sockets Library] ===<br />
<br />
==== Deprecated Functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement<br />
|-<br />
| Errno<br />
| SocketBaseTags (with SBTC_ERRNO tag)<br />
|-<br />
| getdtablesize<br />
| SocketBaseTags (with SBTC_DTABLESIZE tag)<br />
|-<br />
| gethostid<br />
| n/a<br />
|-<br />
| SetErrnoPtr<br />
| SocketBaseTags (with SBTC_ERRNOPTR tag)<br />
|-<br />
| SetSocketSignals<br />
| SocketBaseTags<br />
|}<br />
<br />
==== Other ====<br />
<br />
* The following IoctlSocket() calls are considered deprecated: SIOCSIFADDR, SIOCSIFDSTADDR, SIOCSIFBRDADDR, SIOCGIFADDR, SIOCGIFDSTADDR, SIOCGIFBRDADDR, SIOCSIFFLAGS, SIOCGIFFLAGS, SIOCSIFMETRIC, and SIOCGIFMETRIC. <br />
* Several functions used in conjunction with SocketBaseTagList() are now deprecated as well: SBTC_FDCALLBACK, SBTC_IOERRNOSTRPTR, SBTC_S2ERRNOSTRPTR, SBTC_S2WERRNOSTRPTR, SBTC_SIGIOMASK, and SBTC_SIGURGMASK.h<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/chooser_gc.doc.txt Chooser Gadget] ===<br />
<br />
* The CHOOSER_GetClass function is no longer available. Use the "chooser.gadget" public class ID instead.<br />
* The chooser.gadget attribute CHOOSER_AutoFit is now unsupported<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/console.doc.txt Console Device] ===<br />
<br />
==== Deprecated Functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement (component)<br />
! scope="col"| Replacement (function)<br />
|-<br />
| CD_ASKDEFAULTKEYMAP<br />
| keymap.library<br />
| AskKeyMapDefault<br />
|-<br />
| CD_ASKKEYMAP<br />
| console.device<br />
| CD_ASKKEYMAP_POINTERS<br />
|-<br />
| CD_SETDEFAULTKEYMAP<br />
| keymap.library<br />
| SetKeyMapDefault<br />
|-<br />
| CD_SETKEYMAP<br />
| console.device<br />
| CD_SETKEYMAP_POINTERS<br />
|}<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/dos.doc.txt DOS Library] ===<br />
<br />
The collective changes to the DOS subsystem are substantial and developers are urged to review the [http://wiki.amigaos.net/amiga/autodocs/dos.obsolete.doc.txt Obsolete DOS documentation] as a starting point. Additionally with the introduction of the new [[AmigaDOS Vector-Port|Vector-Port]] API, use of [[AmigaDOS Packets|DOS packets]] is (for the most part) no longer needed. Please carefully read through the documentation when starting a new project with the release of V54.<br />
<br />
==== Deprecated Functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement<br />
|-<br />
|CreateProc<br />
|CreateNewProc<br />
|-<br />
|DeviceProc<br />
|GetDeviceProc<br />
|-<br />
|ExAll<br />
|ExamineDir<br />
|-<br />
| Examine<br />
| ExamineObject<br />
|-<br />
| ExamineFH<br />
| ExamineObject<br />
|-<br />
|Execute<br />
|System<br />
|-<br />
|ExNext<br />
|ExamineDir<br />
|-<br />
| FreeDosEntry<br />
| FreeDosObject<br />
|-<br />
| GetConsoleTask<br />
| GetConsolePort<br />
|-<br />
| GetFileSysTask<br />
| GetFileSysPort<br />
|-<br />
| MakeDosEntry<br />
| AllocDosObject<br />
|- <br />
| ReadItem<br />
| ReadLineItem<br />
|-<br />
| Seek<br />
| SetFilePosition / GetFilePosition<br />
|-<br />
| SetConsoleTask<br />
| SetConsolePort<br />
|-<br />
| SetFileSize<br />
| ChangeFileSize<br />
|-<br />
| SetFileSysTask<br />
| SetFileSysPort<br />
|-<br />
| SetOwner<br />
| SetOwnerInfo<br />
|-<br />
| SetVBuf<br />
| SetFileHandleAttr<br />
|}<br />
<br />
==== Other ====<br />
<br />
* Several functions had name changes in V53. Please review ''dos/obsolete.h'' in the SDK includes if you haven't already updated prior to the release of V54.<br />
* Before V53, CreateDir() returned an exclusive lock on the new directory if it succeeded, it is now required that this be a a shared lock. Exclusive directory locks have been deprecated. Only files may actually have exclusive locks.<br />
* The id_NumSoftErrors and id_UnitNumber fields of the GDI_InfoData structure returned from GetDiskInfo() and Info() are considered deprecated.<br />
* The following error codes returned from IoErr() are considered obsolete: ERROR_TASK_TABLE_FULL, ERROR_NO_DEFAULT_DIR, ERROR_OBJECT_LINKED, and ERROR_UNLOCK_ERROR.<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/exec.doc.txt Exec Library] ===<br />
<br />
==== Deprecated Functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement<br />
|-<br />
| AllocEntry<br />
| AllocTaskMemEntry<br />
|-<br />
| AllocMem<br />
| AllocVecTagList or AllocVecTags<br />
|-<br />
| AllocVec<br />
| AllocVecTagList or AllocVecTags<br />
|-<br />
| CachePreDMA<br />
| StartDMA<br />
|-<br />
| CachePostDMA<br />
| EndDMA<br />
|-<br />
| CreatePool<br />
| AllocSysObject<br />
|-<br />
| MakeLibrary<br />
| CreateLibrary<br />
|-<br />
| AllocTrap<br />
| ''(for 68K only, no longer used)''<br />
|-<br />
| FreeTrap<br />
| ''(for 68K only, no longer used)''<br />
|-<br />
| GetCC<br />
| ''(for 68K only, no longer used)''<br />
|-<br />
| SetSR<br />
| ''(for 68K only, no longer used)''<br />
|}<br />
<br />
==== Memory Flags ====<br />
<br />
Allocating memory with modern Exec is slightly different than before. In addition to using AllocVecTagList or AllocVecTags rather than AllocMem, several flags are no longer relevant. Please review the article on [[Obsolete_Exec_Memory_Allocation|Obsolete Memory Allocation Techniques]] to note what to avoid. Developers should follow the documentation in the [[Exec Memory Allocation|Memory Allocation]] section instead.<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/libamiga_a.doc.txt libamiga.a] ===<br />
<br />
==== Deprecated Functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement (component)<br />
! scope="col"| Replacement (function)<br />
|-<br />
| BeginIO<br />
| exec.library<br />
| BeginIO<br />
|-<br />
| CreateExtIO<br />
| exec.library<br />
| CreateIORequest<br />
|-<br />
| CreatePort<br />
| exec.library<br />
| CreatePort<br />
|-<br />
| CreateStdIO<br />
| exec.library<br />
| CreateIORequest<br />
|-<br />
| CreateTask<br />
| exec.library<br />
| CreateTask<br />
|-<br />
| DeleteExtIO<br />
| exec.library<br />
| DeleteIORequest<br />
|-<br />
| DeletePort<br />
| exec.library<br />
| DeletePort<br />
|-<br />
| DeleteStdIO<br />
| exec.library<br />
| DeleteIORequest<br />
|-<br />
| DeleteTask<br />
| exec.library<br />
| DeleteTask<br />
|-<br />
| NewList<br />
| exec.library<br />
| NewList<br />
|}<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/listbrowser_gc.doc.txt Listbrowser Gadget] ===<br />
<br />
* The LISTBROWSER_GetClass function is no longer available. Use the "listbrowser.gadget" public class ID instead<br />
* The listbrowser.gadget attribute LISTBROWSER_FastRender is obsolete; there is no replacement.<br />
* The SetLBColumnInfoAttrsA function no longer accepts flags via LBCIA_Flags. One should use the equivalent tags instead.<br />
<br />
=== Math IEEE libraries (68K) ===<br />
<br />
As of V45 of mathieeedoubbas.library, mathieeedoubtrans.library, mathieeesingbas.library, and mathieeesingtrans.library, the mathieee.resources are no longer supported. It was felt that this solution was never very popular, neither very fast compared to a co-processor interface, and highly obsolete. This is doubly so in the PowerPC era of next-generation AmigaOne computers. They are included in the operating system merely for compatibility purposes and should not be used for new applications.<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/Picasso96API.doc.txt Picasso96 API Library] ===<br />
<br />
Starting with graphics.library V54, the vast majority of Picasso96 is now redundant. The graphics.library has been expanded and extended to seamlessly handle the traditional native (ECS, AGA) chip sets as well as modern graphics cards (RTG). Please carefully review the autodoc and consider migrating to the newer graphics.library-based API.<br />
<br />
==== Deprecated Functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement (component)<br />
! scope="col"| Replacement (function)<br />
|-<br />
| p96AllocBitMap<br />
| graphics.library<br />
| AllocBitMapTags<br />
|-<br />
| p96FreeBitMap<br />
| graphics.library<br />
| FreeBitMap<br />
|-<br />
| p96LockBitMap<br />
| graphics.library<br />
| LockBitMapTags<br />
|-<br />
| p96LockBitMapToBoard<br />
| graphics.library<br />
| LockBitMapToBoardTags<br />
|-<br />
| p96ReadPixel<br />
| graphics.library<br />
| ReadPixelColor<br />
|-<br />
| p96ReadPixelArray<br />
| graphics.library<br />
| ReadPixelArray<br />
|-<br />
| p96RectFill<br />
| graphics.library<br />
| RectFillColor<br />
|-<br />
| p96UnlockBitMap<br />
| graphics.library<br />
| UnlockBitMap<br />
|-<br />
| p96UnlockBitMapFromBoard<br />
| graphics.library<br />
| UnlockBitMapFromBoard<br />
|-<br />
| p96WritePixel<br />
| graphics.library<br />
| WritePixelColor<br />
|-<br />
| p96WritePixelArray<br />
| graphics.library<br />
| WritePixelArray<br />
|}<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/space_gc.doc.txt Space Gadget] ===<br />
<br />
* The SPACE_GetClass function is no longer available. Use the "space.gadget" public class ID instead.<br />
* The space.gadget SPACE_AreaBox tag is deprecated because it is unsafe to use in a multi-tasking environment. Use SPACE_RenderBox instead.<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/texteditor_gc.doc.txt Texteditor Gadget] ===<br />
<br />
* The TEXTEDITOR_GetClass function is no longer available. Use the "texteditor.gadget" public class ID instead.<br />
* The texteditor.gadget attributes GA_TEXTEDITOR_Prop_DeltaFactor and GA_TEXTEDITOR_HProp_DeltaFactor are now obsolete.<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/warp3d.doc.txt Warp3D Library] ===<br />
<br />
==== Deprecated functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement<br />
|-<br />
| W3D_GetDestFmt<br />
| W3D_Query<br />
|}<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/window_cl.doc.txt Window Class] ===<br />
<br />
* The WINDOW_HintInfo attribute for gadget HelpHints is now considered obsolete and only included for compatibility purposes. Developers should supply all of the hints via the GA_HintInfo attribute of each gadget, and set the WINDOW_GadgetHelp attribute for future projects.<br />
* The WINDOW_Layout tag has 2 aliased definitions which are now obsolete but still supported in the include files.</div>Costel Minceahttps://wiki.amigaos.net/w/index.php?title=Deprecated_Functions&diff=8543Deprecated Functions2016-04-29T10:41:36Z<p>Costel Mincea: /* Deprecated Functions */</p>
<hr />
<div>== Deprecated and Obsolete Functions ==<br />
<br />
With the introduction of AmigaOS 4.1 Final Edition, developers may have noticed additional compiler warnings when rebuilding their projects against the new SDK. While as much of the API has been maintained as is possible, some functions, structures, attributes, and tags have changed over time requiring the attention of application developers. To make life easier, the following is a handy guide to items that have been deprecated or made obsolete with this most recent release. If your code uses any of these items, please refer to the [[Autodocs:Main|Autodocs]] for the component noted to review. Some functions may need to be replaced and others may have changed behavior. It's always a good idea to review the [[SDK Release Notes|Release Notes]] with each SDK release, of course, too. <br />
<br />
This article is inclusive of code made obsolete or deprecated since V50 of the components listed below. Please feel free to edit the document based on your findings should the author have overlooked anything.<br />
<br />
== Components to Review ==<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/asl.doc.txt ASL Library] ===<br />
<br />
==== Deprecated functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement<br />
|-<br />
| AllocFileRequest<br />
| AllocAslRequest<br />
|-<br />
| FreeFileRequest <br />
| FreeAslRequest<br />
|-<br />
| RequestFile<br />
| AslRequest<br />
|}<br />
<br />
==== Other ====<br />
<br />
The following components in the ASL_FileRequest object are obsolete: ''ASLFR_HookFunc, ASLFO_HookFunc,'' and ''ASLFR_FilterFunc.'' For the latter, use ASLFR_FilterHook as a possible replacement.<br />
<br />
=== BOOPSI Classes/Gadgets ===<br />
<br />
Generally all BOOPSI gadget classes and superclasses had a #?_GetClass() function to return a pointer to the class itself. These functions are deprecated as of V52. Developers should use the gadget public class ID as a replacement. Some gadgets are listed separately in this article as they have other items now deprecated or obsolete; if a gadget is not listed herein, the above note regarding pointers should be the only item considered deprecated for it.<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/bsdsocket.doc.txt BSD Sockets Library] ===<br />
<br />
==== Deprecated Functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement<br />
|-<br />
| Errno<br />
| SocketBaseTags (with SBTC_ERRNO tag)<br />
|-<br />
| getdtablesize<br />
| SocketBaseTags (with SBTC_DTABLESIZE tag)<br />
|-<br />
| gethostid<br />
| n/a<br />
|-<br />
| SetErrnoPtr<br />
| SocketBaseTags (with SBTC_ERRNOPTR tag)<br />
|-<br />
| SetSocketSignals<br />
| SocketBaseTags<br />
|}<br />
<br />
==== Other ====<br />
<br />
* The following IoctlSocket() calls are considered deprecated: SIOCSIFADDR, SIOCSIFDSTADDR, SIOCSIFBRDADDR, SIOCGIFADDR, SIOCGIFDSTADDR, SIOCGIFBRDADDR, SIOCSIFFLAGS, SIOCGIFFLAGS, SIOCSIFMETRIC, and SIOCGIFMETRIC. <br />
* Several functions used in conjunction with SocketBaseTagList() are now deprecated as well: SBTC_FDCALLBACK, SBTC_IOERRNOSTRPTR, SBTC_S2ERRNOSTRPTR, SBTC_S2WERRNOSTRPTR, SBTC_SIGIOMASK, and SBTC_SIGURGMASK.h<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/chooser_gc.doc.txt Chooser Gadget] ===<br />
<br />
* The CHOOSER_GetClass function is no longer available. Use the "chooser.gadget" public class ID instead.<br />
* The chooser.gadget attribute CHOOSER_AutoFit is now unsupported<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/console.doc.txt Console Device] ===<br />
<br />
==== Deprecated Functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement (component)<br />
! scope="col"| Replacement (function)<br />
|-<br />
| CD_ASKDEFAULTKEYMAP<br />
| keymap.library<br />
| AskKeyMapDefault<br />
|-<br />
| CD_ASKKEYMAP<br />
| console.device<br />
| CD_ASKKEYMAP_POINTERS<br />
|-<br />
| CD_SETDEFAULTKEYMAP<br />
| keymap.library<br />
| SetKeyMapDefault<br />
|-<br />
| CD_SETKEYMAP<br />
| console.device<br />
| CD_SETKEYMAP_POINTERS<br />
|}<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/dos.doc.txt DOS Library] ===<br />
<br />
The collective changes to the DOS subsystem are substantial and developers are urged to review the [http://wiki.amigaos.net/amiga/autodocs/dos.obsolete.doc.txt Obsolete DOS documentation] as a starting point. Additionally with the introduction of the new [[AmigaDOS Vector-Port|Vector-Port]] API, use of [[AmigaDOS Packets|DOS packets]] is (for the most part) no longer needed. Please carefully read through the documentation when starting a new project with the release of V54.<br />
<br />
==== Deprecated Functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement<br />
|-<br />
|CreateProc<br />
|CreateNewProc<br />
|-<br />
|DeviceProc<br />
|GetDeviceProc<br />
|-<br />
|ExAll<br />
|ExamineDir<br />
|-<br />
| Examine<br />
| ExamineObject<br />
|-<br />
| ExamineFH<br />
| ExamineObject<br />
|-<br />
|ExNext<br />
|ExamineDir<br />
|-<br />
| FreeDosEntry<br />
| FreeDosObject<br />
|-<br />
| GetConsoleTask<br />
| GetConsolePort<br />
|-<br />
| GetFileSysTask<br />
| GetFileSysPort<br />
|-<br />
| MakeDosEntry<br />
| AllocDosObject<br />
|- <br />
| ReadItem<br />
| ReadLineItem<br />
|-<br />
| Seek<br />
| SetFilePosition/GetFilePosition<br />
|-<br />
| SetConsoleTask<br />
| SetConsolePort<br />
|-<br />
| SetFileSysTask<br />
| SetFileSysPort<br />
|-<br />
| SetVBuf<br />
| SetFileHandleAttr<br />
|-<br />
| SetOwner<br />
| SetOwnerInfo<br />
|}<br />
<br />
==== Other ====<br />
<br />
* Several functions had name changes in V53. Please review ''dos/obsolete.h'' in the SDK includes if you haven't already updated prior to the release of V54.<br />
* Before V53, CreateDir() returned an exclusive lock on the new directory if it succeeded, it is now required that this be a a shared lock. Exclusive directory locks have been deprecated. Only files may actually have exclusive locks.<br />
* The id_NumSoftErrors and id_UnitNumber fields of the GDI_InfoData structure returned from GetDiskInfo() and Info() are considered deprecated.<br />
* The following error codes returned from IoErr() are considered obsolete: ERROR_TASK_TABLE_FULL, ERROR_NO_DEFAULT_DIR, ERROR_OBJECT_LINKED, and ERROR_UNLOCK_ERROR.<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/exec.doc.txt Exec Library] ===<br />
<br />
==== Deprecated Functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement<br />
|-<br />
| AllocEntry<br />
| AllocTaskMemEntry<br />
|-<br />
| AllocMem<br />
| AllocVecTagList or AllocVecTags<br />
|-<br />
| AllocVec<br />
| AllocVecTagList or AllocVecTags<br />
|-<br />
| CachePreDMA<br />
| StartDMA<br />
|-<br />
| CachePostDMA<br />
| EndDMA<br />
|-<br />
| CreatePool<br />
| AllocSysObject<br />
|-<br />
| MakeLibrary<br />
| CreateLibrary<br />
|-<br />
| AllocTrap<br />
| ''(for 68K only, no longer used)''<br />
|-<br />
| FreeTrap<br />
| ''(for 68K only, no longer used)''<br />
|-<br />
| GetCC<br />
| ''(for 68K only, no longer used)''<br />
|-<br />
| SetSR<br />
| ''(for 68K only, no longer used)''<br />
|}<br />
<br />
==== Memory Flags ====<br />
<br />
Allocating memory with modern Exec is slightly different than before. In addition to using AllocVecTagList or AllocVecTags rather than AllocMem, several flags are no longer relevant. Please review the article on [[Obsolete_Exec_Memory_Allocation|Obsolete Memory Allocation Techniques]] to note what to avoid. Developers should follow the documentation in the [[Exec Memory Allocation|Memory Allocation]] section instead.<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/libamiga_a.doc.txt libamiga.a] ===<br />
<br />
==== Deprecated Functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement (component)<br />
! scope="col"| Replacement (function)<br />
|-<br />
| BeginIO<br />
| exec.library<br />
| BeginIO<br />
|-<br />
| CreateExtIO<br />
| exec.library<br />
| CreateIORequest<br />
|-<br />
| CreatePort<br />
| exec.library<br />
| CreatePort<br />
|-<br />
| CreateStdIO<br />
| exec.library<br />
| CreateIORequest<br />
|-<br />
| CreateTask<br />
| exec.library<br />
| CreateTask<br />
|-<br />
| DeleteExtIO<br />
| exec.library<br />
| DeleteIORequest<br />
|-<br />
| DeletePort<br />
| exec.library<br />
| DeletePort<br />
|-<br />
| DeleteStdIO<br />
| exec.library<br />
| DeleteIORequest<br />
|-<br />
| DeleteTask<br />
| exec.library<br />
| DeleteTask<br />
|-<br />
| NewList<br />
| exec.library<br />
| NewList<br />
|}<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/listbrowser_gc.doc.txt Listbrowser Gadget] ===<br />
<br />
* The LISTBROWSER_GetClass function is no longer available. Use the "listbrowser.gadget" public class ID instead<br />
* The listbrowser.gadget attribute LISTBROWSER_FastRender is obsolete; there is no replacement.<br />
* The SetLBColumnInfoAttrsA function no longer accepts flags via LBCIA_Flags. One should use the equivalent tags instead.<br />
<br />
=== Math IEEE libraries (68K) ===<br />
<br />
As of V45 of mathieeedoubbas.library, mathieeedoubtrans.library, mathieeesingbas.library, and mathieeesingtrans.library, the mathieee.resources are no longer supported. It was felt that this solution was never very popular, neither very fast compared to a co-processor interface, and highly obsolete. This is doubly so in the PowerPC era of next-generation AmigaOne computers. They are included in the operating system merely for compatibility purposes and should not be used for new applications.<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/Picasso96API.doc.txt Picasso96 API Library] ===<br />
<br />
Starting with graphics.library V54, the vast majority of Picasso96 is now redundant. The graphics.library has been expanded and extended to seamlessly handle the traditional native (ECS, AGA) chip sets as well as modern graphics cards (RTG). Please carefully review the autodoc and consider migrating to the newer graphics.library-based API.<br />
<br />
==== Deprecated Functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement (component)<br />
! scope="col"| Replacement (function)<br />
|-<br />
| p96AllocBitMap<br />
| graphics.library<br />
| AllocBitMapTags<br />
|-<br />
| p96FreeBitMap<br />
| graphics.library<br />
| FreeBitMap<br />
|-<br />
| p96LockBitMap<br />
| graphics.library<br />
| LockBitMapTags<br />
|-<br />
| p96LockBitMapToBoard<br />
| graphics.library<br />
| LockBitMapToBoardTags<br />
|-<br />
| p96ReadPixel<br />
| graphics.library<br />
| ReadPixelColor<br />
|-<br />
| p96ReadPixelArray<br />
| graphics.library<br />
| ReadPixelArray<br />
|-<br />
| p96RectFill<br />
| graphics.library<br />
| RectFillColor<br />
|-<br />
| p96UnlockBitMap<br />
| graphics.library<br />
| UnlockBitMap<br />
|-<br />
| p96UnlockBitMapFromBoard<br />
| graphics.library<br />
| UnlockBitMapFromBoard<br />
|-<br />
| p96WritePixel<br />
| graphics.library<br />
| WritePixelColor<br />
|-<br />
| p96WritePixelArray<br />
| graphics.library<br />
| WritePixelArray<br />
|}<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/space_gc.doc.txt Space Gadget] ===<br />
<br />
* The SPACE_GetClass function is no longer available. Use the "space.gadget" public class ID instead.<br />
* The space.gadget SPACE_AreaBox tag is deprecated because it is unsafe to use in a multi-tasking environment. Use SPACE_RenderBox instead.<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/texteditor_gc.doc.txt Texteditor Gadget] ===<br />
<br />
* The TEXTEDITOR_GetClass function is no longer available. Use the "texteditor.gadget" public class ID instead.<br />
* The texteditor.gadget attributes GA_TEXTEDITOR_Prop_DeltaFactor and GA_TEXTEDITOR_HProp_DeltaFactor are now obsolete.<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/warp3d.doc.txt Warp3D Library] ===<br />
<br />
==== Deprecated functions ====<br />
<br />
{| class="wikitable"<br />
|-<br />
! scope="col"| Obsolete<br />
! scope="col"| Replacement<br />
|-<br />
| W3D_GetDestFmt<br />
| W3D_Query<br />
|}<br />
<br />
=== [http://wiki.amigaos.net/amiga/autodocs/window_cl.doc.txt Window Class] ===<br />
<br />
* The WINDOW_HintInfo attribute for gadget HelpHints is now considered obsolete and only included for compatibility purposes. Developers should supply all of the hints via the GA_HintInfo attribute of each gadget, and set the WINDOW_GadgetHelp attribute for future projects.<br />
* The WINDOW_Layout tag has 2 aliased definitions which are now obsolete but still supported in the include files.</div>Costel Mincea