Skip to content

Instantly share code, notes, and snippets.

@commandblockguy
Created February 19, 2020 04:17
Show Gist options
  • Save commandblockguy/8eb7fcfca46df2967903c3eb2adeb9db to your computer and use it in GitHub Desktop.
Save commandblockguy/8eb7fcfca46df2967903c3eb2adeb9db to your computer and use it in GitHub Desktop.
Random incomprehensible scrawlings about hook manager spec
Currently unnamed CE hook manager:
The system will have the following components:
Hook executors - Each TI-OS hook has an associated entry point which is responsible for calling all user hooks for that type.
Hook arrays - An null-terminated array of pointers to user hooks for a particular hook subtype, sorted by priority. The array is read by the hook executor each time it is called, and is completely overwritten by the hook manager each time a change is necessary.
Hook manager - A library that is responsible for installing the hook executors and maintaining the hook arrays. The hook manager is only called when installing, changing, or viewing metadata of user hooks.
Hook database - Internal data storage for the hook manager than consists of a list of hooks and their metadata.
User hooks:
User hooks are like OS hooks, but are called by the hook executor rather than TI-OS
Each hook must start with 0x83, like OS hooks
All valid OS hooks are valid user hooks provided that they have the lowest priority of all hooks of their type
Rather than taking the hook subtype in a, as with OS hooks, the hooks should be registered by subtype whenever possible
If a hook needs to process many values of a, a wildcard subtype can be used instead
In addition to returning the value that the OS expects, user hooks should return a value in d // is this used by anything?
If the return value of the function should be ignored and lower-priority user hooks should be processed, d should contain a non-zero value
If the return value of the function should be passed on to TI-OS, ignoring lower-priority user hooks, d should contain zero
Example program flow on hook fire:
User presses the 1 key
TI-OS calls the hook executor for the getcsc hook
Hook executor backs up relevant input registers
Hook executor calls the first wildcard user hook for the getcsc hook // should subtype-specific be processed before wildcards?
User hook indicates that further hooks should be processed rather than returning to the OS
Hook executor restores register backup
Next wilcard user hook is NULL - hook executor moves on to the specific hook type (a = 0x1B)
Hook executor calls the first subtype-specific user hook
User hook checks the scan code and decides to take no action
User hook indicates that further hooks should be processed rather than returning to the OS
Hook executor calls the next subtype-specific user hook
User hook checks the scan code and decides to open a menu
User hook indicates that control should be given back to the OS
Hook executor returns control to the OS
User hook installation procedure:
Create hook database if it does not exist
If hook to be installed is already in database:
If the entry is valid, return the pointer to it // should this behave differently?
Otherwise, update the entry with the new pointer
Otherwise, create a new entry for it
Refresh hooks for that OS hook type
Refreshing hooks for a particular OS hook type:
Check if the existing hook is our own hook executor
If not, and hook is valid, create a new minimum-priority wildcard hook entry for it
Copy the hook executor code into an appvar, ommitting unncessary portions (e.g. the wildcard checks if there are only subtype-specific hooks, or the return value checker if there is only one hook)
Get all addresses of hooks of each subtype from the database, sorted by priority and ignoring invalid hooks, and copy them into the appvar
Achive the appvar
Get the data pointer from the appvar // Is there a better way of allocating memory than this, besides making an app? - maybe Mateo's relocation table system?
Delete the appvar
Call the OS sethook call
User-facing hook manager functions (probably need some work in terms of interface):
(C syntax is used for returns and arguments, though the final library may not use C functions)
bool refresh_hooks(void) - regenerates hook executors and hook arrays for all types in the database. call at the beginning of the program to restore functionality.
user_hook_entry_t *install_hook(uint24_t id, void *hook, uint8_t type, uint8_t subtype, uint8_t priority, char *description) - installs and enables a user hook from a pointer. returns NULL if installation failed or a pointer to the hook entry in the hook database. if the hook is already installed, a pointer to the existing entry is returned.
bool uninstall_hook(user_hook_entry_t *entry) - uninstalls a user hook
user_hook_entry_t *get_entry_by_id(uint24_t id) - gets a pointer to a hook database entry by its unique id, or NULL if no such entry exists.
bool set_priority(user_hook_entry_t *entry, uint8_t priority) - sets the priority of a hook
bool check_hook_validity(user_hook_entry_t *entry) - checks if a user hook is valid
The hook database is stored in a regular appvar.
user_hook_entry_t:
uint24_t id
void *hook // pointer to the user hook
uint8_t type // enum for which OS hook to use
uint8_t subtype // which value of a this user hook should fire for, or a "wildcard" magic value which causes the hook to fire for all subtypes
uint8_t priority // process lowest priorities first
bool enabled
char description[64];
// Maybe add a checksum, in addition to the 0x83 ?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment