2 -With AllocMem() and malloc() my concern is that I read that you need to store certain things (images, sound) in chip memory and to do this you would use AllocMem and specify chipmem as one of the parameters. What I was reading implied that malloc would just use any available memory.
Correct. If you need specific memory for a specific purpose, malloc() is not a good idea. malloc() works for the average ANSI-C program, though not for Amiga-specific stuff.
The only thing I don't like is that some things use hooks and I just can't get my head around how the hooks work.
The calls are made from the MUI code into your code so you can customize its function. The parameters are, of course, prepared by the MUI code. What exactly they are I cannot tell you, I do not know MUI precise enough, though the general principle is the same. A "hook" is essentially a function you provide as "plug in" to an interface of a third party. Essentially, a "function pointer" with a bit of added functionality. How that all works is - hopefully - documented in the MUI documentation.
When declaring pointers i've read people say that you shold set them to null or 0. Then when you have freed them you should set them back to null or 0.
Some people say this is a must while others say it isn't important and just causes extra work.
In general, setting them to zero after releasing them is a good safeguard against dangling pointers, and the overhead is typically not worth thinking about. In best case, the compiler will find out itself that the assignment is useless.
There are of course obvious cases where the "set to zero" is useless, and in such obvious cases, it does no harm just to leave it away:
void ReleaseString(char *name)
{
free(name);
name = NULL; /* obviously pointless */
}
In this case, it is quite pointless to set "name" to NULL simply because it is not used afterwards, and because the caller of "ReleaseString" might still hold a pointer, namely the argument to the function just called, so it doesn't help either.
Nevertheless, the compiler will typically tell you that it removed a "dead assignment" and no overhead is created. Should you ever extend the function later on (unlikely in the above example, though), the assignment is already there, so it is also a matter of "conservative programming" to leave it were it is.
Some people complain if the code is not super-optimized, but I disagree. First make the program run, then make it run fast. Writing fast code is an art by itself, and you typically get *not* fast code by only eliminating dead assignments.
init_hook(&disphook, (HOOKFUNC)dispfunct, NULL); //call to init hook
void init_hook(struct Hook *hook, HOOKFUNC entry, APTR data) // hook function
{
hook->h_Entry = (HOOKFUNC)HookEntry;
hook->h_SubEntry = (HOOKFUNC)entry;
hook->h_Data = (APTR)data;
}
I guess this is setting up the values in the hook structure.
Right. That's a little bit of data around the actual function.
Though I'm not sure what HookEntry is or what data would be expected.
hook->h_Data is for your own hook to use. Thus, it's not MUI that should read this pointer. It is for you to place something there you'd need.
hook->h_Entry is the entry point of your hook. This is where MUI goes if it "calls your hook". The tricky part is not hook->h_Entry, but hook>h_SubEntry. The reason for this is as follows: Some compilers require a short "set up" function to load the base registers correctly. In such a case, you would set hook->h_Entry to some "compiler trampile function", ideally provided by the compiler vendor. This trampoline function would load registers as needed for the specific compiler, and would then call by itself your function through "hook->h_SubEntry".
Whether you need that or your compiler needs that is something I cannot answer in general. The SAS/C compiler, for example, does not need it, though it is in general necessary to declare the hook function with "__saveds", a compiler magic that tells the compiler that it needs to reload some important registers from within the function to operate correctly, because the function is called from somewhere outside, plus a parameter "__asm" that also tells the compiler where to pick the arguments from.
Hence, a typical SAS/C hook function looks like this:
unsigned long __asm __saveds myHookFunction(register __a0 struct Hook *hk,register __a2 APTR object, register __a1 APTR message)
{
...
}
But again, this is very compiler specific, and the above magic only works for SAS/C. For any other compiler, hook->hk_Entry should be some compiler magic (documented, hopefully, in the compiler manual) and hook->hk_SubEntry points to your code.
I'm also guessing that the 2nd patameter passed is the function that you would call
LONG dispfunct(struct Hook *hook, const char **array, struct ListItems *item)
{
if (rom)
array[0] = item->Name;
else
array[0] = "\033bName";
return(0);
}
and this is where I really get confused.
Hooks just receive three pointers (in registers a0,a2 and a1). What they actually *mean* is part of the infrastructure the hook is used for. In other words, the MUI documentation should say what the "object" and the "message" of the hook is. It seems, in this particular case (though I do not know) that "object" is a character array and "message" is a pointer to struct ListItems. Again, please check the MUI docs for this.
I call this hook in the MUI List with MUIA_List_DisplayHook, &disphook .
How does it know what array and items are as I don't appear to pass anything to them??
The array and the list items are prepared by MUI, and it calls your code with these arguments. the function should probably better be declared as
LONG dispfunct(struct Hook *hook, APTR carray, APTR citem)
{
const char **array = (const char **)carray;
struct ListItems *items = (struct ListItems *)citem;
....
}
because this would make more clear that the code actually receives carray and citem as "generic pointers", and you explicitly need to tell the compiler what they are. The hook declaration itself (as defined in the utility library) does *not* know. It only knows that three parameters are coming. One "struct Hook *", and two other generic pointers of unknown type. You have (or should) convert them manually to what they actually mean.
What they actually mean is specific to the use case of the hook, so in this case, MUI listviews. It should state somewhere in the manual.