Hooks are a feature of TI-OS that allow apps and programs to run their own code whenever an event occurs in the OS - for example, using a token hook, you can change how tokens are displayed in TI-OS.

A major limitation of hooks is that only one program can install a hook of a particular type. If another program wants to use the same type of hook, it must either prevent the first hook from using it or implement chaining logic.

Cap'n Hook seeks to prevent this problem by providing a common interface for programs to register their hooks with. This has a number of advantages over the OS's interface:

Multiple programs can use the same type of hook.
Individual programs do not have to implement chaining logic.
If a hook is changed by a program that does not use Cap'n Hook, the next time a program that does use Cap'n Hook is run, the old hooks are restored.
In case two hooks conflict with each other (for example, two programs both want to open a menu when a certain key is pressed), the user can assign them a priority to change which one will run.

Cap'n Hook does not currently provide a mechanism for storing hooks persistently. Hooks should be stored somewhere that is unlikely to be overwritten - for example, in a deleted appvar, which will persist until the next garbage collect.

Here's the download for both the library and the dev headers, and here's the assembly source and test program.

Original Post: "Creating a Standardized Hook Manager for the CE"

Currently, very few projects on the CE use hooks, and I believe this is likely to avoid causing issues with other programs that use them. I think that it would be a good idea to create a library that would provide an interface for managing hooks, rather than having all programs handle installing hooks themselves.

Right now I have a decent idea of how this would work in my head, but that doesn't really count for anything, so I created a GitHub gist explaining the basic idea. I'm posting this to get feedback, at this point mostly for any glaring issues with the concept. If there aren't any, I can start working on more polished design documentation and then start actually implementing it.

I'm currently not addressing memory management issues, only chaining issues, though that might change in the future.

Anyways, here's the GitHub gist:
I have improved the draft, formatting wise Razz

(Also added a const for the description string)
I think you should try this Smile I would recommend using some unused memory location rather than the D register though. Perhaps a negative flag location. Also I'm not sure I understand the point of subtypes. Are they really needed?

Also keep in mind we should probably have a wiki page with the registered hook IDs.
I've gone ahead and created a prototype, mostly written in C due to laziness, one of the three core virtues of programming. You can go ahead and check out a demo of it here: https://github.com/commandblockguy/capnhook.

As per Mateo's suggestions, I've removed subtypes since they're pointless and outside the scope of this library, and also changed the byte that determines whether more hooks will be run from d to bit 0 of (iy-10), an unused flag.

A few things to keep in mind:
Currently, the library is mostly written in C. I'll rewrite it in assembly for speed for the actual library, and remove the dependency on fileioc.
This is written in C11 because I'm too lazy to do int i; for(i...). It probably won't build on ZDS; use the llvm branch of the toolchain.
Currently, this is statically linked and part of a C project. This will eventually be a LibLoad library like graphx and fileioc.
This code is inefficient, both in terms of size and space. Later, I'll properly sort the database so that it can be accessed quickly, and probably change the getter functions to share most of their code.
Not everything I have planned is implemented yet - I want to make sure that what I currently have doesn't have any serious issues with it before continuing. I have the following planned:
Handling OS hooks that already have a hook from a program or app that does not use this library
Supporting localization hooks/language apps - I haven't looked into this much yet, but I'm pretty sure this would allow me to restore all of the hooks after a garbage collect or RAM reset
Allocating memory in a way that won't get clobbered on a garbage collect - I think Mateo said he had an idea for how to do this using relocation tables, in a similar way to how LibLoad does it. I may also provide this method as a library function, rather than leaving memory allocation to the user

If you have any other feedback, please be sure to let me know.

Don't attempt to use this prototype in actual programs - I will likely change the interface at some point and things will break.
I'm revisiting this project, despite it being a pretty weird time to do so.

I've added a bunch of tests so I can verify that the library behaves properly once I rewrite it in assembly.
In the process, I found a few major bugs in the prototype, which I've now fixed.
I also added documentation to the header file, so you can just read that instead of the rather messy github gist. I don't mention the return flag anywhere as of right now - I guess I could add that to the comment for hook_t.

I'm still looking for feedback on the interface, so take a look at the header file and let me know if you have any.
I've finally gotten this turned into an actual library - I wouldn't call it 100% release-ready, as it could still use some more optimization and bug-testing, but the interface shouldn't change from here to the final release. It should be stable enough for use in programs.

Here's the download for both the library and the dev headers, and here's the assembly source and test program.

I still haven't written an example yet, and the test program is a decent test but a terrible example of how to use the library. I'll probably fork the programs that currently use hooks (which I believe is just Cesium and ICE, at the moment) to see if I can get them to work with this library.
Great job, can't wait to see a "real life" example, seems useful!
Great work on this project! I imagine that this will make creating hooks on the CE significantly easier, and I'm looking forward to seeing some examples and figuring it out for myself (and hopefully using it in some future programs).
I've noticed a lot of interest in hooks as of late, especially Iambian's font utility, so I decided to work more on this project.

Earlier today, I changed the library so that it makes a copy of the hooks in flash rather than simply taking a user-provided pointer (though you can still do that by setting the size to 0). This has a few benefits - most obviously, it means that the user no longer has to copy the hooks to flash themselves. Additionally, it allows the library to automatically relocate hooks during a garbage collect, preventing them from being deleted or disabled, by hooking into the garbage collect itself. I haven't implemented this yet, though.

In the process, I broke the API, but it seems like nobody was using that anyway.

I also realized that I'm not properly handling some of the hook types in the event that none of the user hooks for that type request to return a value, which I'll fix soon.

Finally, I plan on adding a few actual examples for installing hooks from both C and assembly programs. I'll probably create an example hook that adds a menu with string operations to alpha+vars.
I've added a few example programs to the repo:

First, a nifty program that adds string operations to their own column in the vars menu. No more pressing 2nd+0+L+down+down+down+down+down+down to get the length of a string!
Here's the download for the program itself. I'll probably upload it to the Cemetech archives after I release capnhook (which should be soon!). It probably won't run on the latest pre-release, as the API has changed - I'll see if I can get that updated tomorrow.
This example is written entirely in assembly, and shows how to load the library using LibLoad, how to install a hook, and how to use a menu hook.

I've also written an example that uses C (though the hook itself is still written in assembly). It prints every hook that triggers, as well as the contents of the registers at the time, to the CEmu console. You'll need to run make install in the /src/ directory before building, to add the library file to your toolchain.

If you have any other suggestions for small example programs, let me know - I want to make sure that there are plenty of examples so that it's clear how to use the library and the common hook types.
I just released a new pre-release version.

I'm considering changing how the library is implemented - right now it copies hooks to an appvar, archives the appvar, then deletes the appvar, keeping track of where the hook is located in the hook database. This has the downside that hooks get deleted during a garbage collect, which I could probably get around but it would make the library significantly more complicated.
I'm thinking about changing this so that each hook is given its own appvar with a unique name (based on the hook ID), which is not deleted. That way, after a garbage collect, I just have to find the new location of each hook registered in the database, which is much simpler. The downside is that the appvars list would get cluttered, and also that people might delete hooks without knowing what they're for.
commandblockguy wrote:
I'm thinking about changing this so that each hook is given its own appvar with a unique name (based on the hook ID), which is not deleted. That way, after a garbage collect, I just have to find the new location of each hook registered in the database, which is much simpler. The downside is that the appvars list would get cluttered, and also that people might delete hooks without knowing what they're for.

Couldn't you store all the hooks in a single AppVar and index them using the hook IDs?
I'm not sure how feasible that is, but it would prevent clutter in the AppVar list.
I've decided to remove the garbage collection protection from the library:
SAX wrote:
<MateoC> I don't understand why you are making the hook manager so complex
<MateoC> it's dumb
<commandz> Should I ditch the garbage collect protection stuff, then?
<MateoC> yes
<commandz> aight
<MateoC> It would make things a lot easier
<MateoC> then if people complain you could add it :P

I've reverted the master branch to the commit before I switched to the appvar-based system. The old master branch is still around as the "appvar" branch, in case I decide to re-expand the scope of the library in the future.

Since that cuts down on the complexity of things, I'll probably release the initial version of the library soon. I want to make a few optimizations to it first, though.
I've made another pre-release: https://github.com/commandblockguy/capnhook/releases/tag/v1.0-beta.3
This one adds a function hook_Next, which you can use to list all of the hooks tracked by capnhook. This might be useful for making a program that allows you to adjust the priorities of different hooks, for example.

This will probably be the last pre-release before the actual release - if there are no bugs in it, I may just end up re-releasing as v1.0. This means this is your last chance to complain about stuff :p.

As always, if you have any suggestions for how to improve the library, including ideas for examples or optimizations, please let me know.
Release time!

Not much changed since the last pre-release - I just fixed a crash and changed the makefiles slightly.
666th post, and just a few days early of spooky season, nice
Nice work! This is going to be super helpful indeed Smile.
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum