;HookMan v0.02 ;Brandon Wilson ;HookMan is a hook chaining manager for the TI-83/84 Plus series of graphing calculators. ;It allows chains of each hook to be installed, enabling more than one application to use a particular hook. ;It also re-enables hooks on RAM reset, making it unnecessary to re-install the hooks whenever your calculator crashes. ; This works whether you use any of the chaining features or not. ;NOTE: because this application modifies itself, it's important that it be signed before testing it in an emulator ; (meaning don't load the .hex file, always sign it and load the .8xk file instead). ;v0.01 Changelog ;Initial release for the Cemetech programming contest ;Here's the plan: ;GUI: ; The GUI will allow adding the current non-HookMan hook into the chain for that particular hook, and re-ordering ; of specific applications for that hook. ; The main idea: ; Load all of the hook blocks into RAM for editing. ; Have a main menu with each hook listed, and the ability to dig deeper into each one: ; Examples: ; RawKey Hook: ; NameOfApplication1 or "RAM Hook (address)" ; NameOfApplication2 or "RAM Hook (address)" ; NameOfApplication3 or "RAM Hook (address)" ; NameOfApplication4 or "RAM Hook (address)" ; GetKey Hook: ; NameOfApplication1 or "RAM Hook (address)" ; NameOfApplication2 or "RAM Hook (address)" ; NameOfApplication3 or "RAM Hook (address)" ; Silent Link Hook: ; NameOfApplication1 or "RAM Hook (address)" ; NameOfApplication2 or "RAM Hook (address)" ; Link Activity Hook: ; NameOfApplication1 or "RAM Hook (address)" ; You can highlight each entry, and press [+] or [-] (maybe have soft keys for this as well) to move items up and down. ; Hooks will be executed in the order that you see. ; If the first hook in the chain cancels the action, the next one is not executed. ; Each hook will have its own block describing the chain: ; DB bHookIDByte1 ; DW bNumberOfHooks ; DW wHookAddress1 ; DB bHookPage1 ; DB bExtraByte1 ; DW wHookAddress2 ; DB bHookPage2 ; DB bExtraByte2 ; ... ; All of the blocks will be stored in random places THROUGHOUT THIS APPLICATION. ; All editing will be done in RAM copies of each hook block, then written wherever possible in the application: ; The application will have to put up a "SAVING" screen, and defragment itself when necessary. ; At the end of application execution, a cache in RAM will be generated: ; 83+: 52-byte block at userMem will be regenerated: ; DB aIDString ;"HKMN" ; DW wHook1BlockAddress ;address of block in HookMan application for this hook ; DW wHook2BlockAddress ; and so on ; 83+SE/84+/84+SE: same 52-byte block at 82:4000h (maybe at userMem instead if that ends up being faster) ;Install: ; Install all 24 hooks with our own version: ; Each hook will look up its block using the stolen RAM, then go through each hook in the chain and run them. ; Install an OS patch which will not erase any of the hook blocks, nor hook flags: ; Scan for code that erases RAM on boot: ; Seems to always be (on page 0): ; ld hl,8000h ; ld de,8001h ; ld bc,7FFFh ;I've seen it as 8000h instead ; ld (hl),0 ; ldir ; I think we can replace this (minus BC value) with a page 0 jump (place the address at the end of page 0) and put ; replacement code somewhere else (like page 1Bh/3Bh/7Bh, maybe even scan for this): ; Replacement code: ; Save iy+33h, iy+34h, iy+35h, iy+36h. ; Zero out everything from 8000h to 9B77h. ; Zero out everything from 9BD8h to 0FFFFh. ; Scan for code that erases RAM during MEM resets. ; Seems to be (on page 75h, OS 2.41): ; ld hl,8000h ; ld de,8001h ; ld bc,1BC3h ; ld (hl),0 ; ldir ; It seems to be in two pieces, this being the second piece: ; ld hl,9BD0h ; ld de,9BD1h ; ld bc,642Fh ; ld (hl),0 ; ldir ; I think if we do the same thing as above (minus BC value), we'll be safe. ; Scan for code that erases RAM during self-test. ; Seems to be (on page 6): ; ld de,8D4Fh ; call doRAMCheck ; jr nz,doFunkySelfTestAbort ; Or: ; ld de,0C000h ; call doRAMCheck ; jr nz,secondRAMCheckFailed ; I think we can do a scan for this (minus "doRAMCheck" and the jumps) and NOP it out. ; It couldn't hurt to look into "doRAMCheck" and make sure it starts out as: ; ld hl,0 ; or a ; sbc hl,de ; ex de,hl ; push de ; push hl ; It's probably best to limit this to page 6, but if we do the above check, we can probably let it slide. ; I think the patch should have some sort of key override on boot so that hooks can be disabled if we REALLY REALLY want it. ; We might even be able to have custom key combinations, sort of like a password. ; Keep track of all of these changes and store them in the application somewhere (special hook ID byte, maybe). ;Uninstall: ; Revert all changes using the application data from above (special hook ID byte, maybe). ; Disable all hooks. ;Integrated Hooks: ; I'm thinking of having the ability for programs/applications to embed hooks into this application, the main purpose being ; a safe haven for small (previously RAM) hooks not worthy of a 16KB Flash application. ; With the defragmenting and application storage code already written, I don't think it would be too bad to add. ; So here's the plan for that: ; Provide an interface for assembly programmers to include block of code in application: ; Pass in the size of the hook and the "name" for it (8 bytes max.) ; and a flags byte (zero initially, set bit 0 for no defragmenting, set bit 1 for visual progress, set bit 2 to preserve "invalid" hooks) ; Return carry set if the space isn't there, otherwise return page and address in AHL (so it can just install the hook and move on) ; The interfaces: ; Hard-coded address to call for above routine ; RunAppLib interface for one routine (InstHook) and the hard-coded address ; I think the biggest deal is just the documentation, and a usb8x-like include file and example code for both interfaces. ; Although an EXTREME downside to this is that the hook won't know where it's running from, so no calls or offsets. ; It could copy itself to RAM and then run if necessary. Or get its address from the stack (call start \ start: pop ix) ; Makes this whole thing kind of useless except for very special cases, but oh well, it's a quick addition. ;TODO: also add import/export config to/from appvar functions. include "settings.inc" NOLIST include "ti83plus.inc" LIST include "equates.inc" include "header.asm" SEGMENT MAIN GLOBALS ON EXTERN PutSApp,VPutSApp,VPutSAppCenter,DisplayPressAnyKey,InvalidateHookBlock EXTERN InstallHookMan,UninstallHookMan,StartManager,LoadConfigFromStorageArea,ClearHookConfiguration EXTERN swapSectorPage Var appEnd,2 Var menuAddr,2 Var numChoices,1 Var topItem,1 Var selectedItem,1 DispAbout: B_CALL ForceFullScreen B_CALL ClrLCDFull ld hl,1 ld (curRow),hl ld hl,sAboutText call PutSApp ld hl,Splash_DS ld de,appBackUpScreen ld bc,57 ldir ld hl,appBackUpScreen ld de,49*256+5 B_CALL DisplayImage ld hl,57*256+9 ld (penCol),hl ld hl,Intro_Web call VPutSAppCenter ld hl,30*256+29 ld (penCol),hl ld hl,Intro_Version call VPutSAppCenter ld a,37 ld (penRow),a ld hl,Intro_Build call VPutSAppCenter xor a ld (kbdKey),a ld (kbdScanCode),a B_CALL GetKey StartApp: B_CALL GrBufClr ld (iy+hookManFlags),0 B_CALL FindSwapSector ld (swapSectorPage),a ld hl,4006h ld bc,(4004h) ld a,c ld c,b ld b,a add hl,bc ;$$: in a,(6) ; inc hl ; B_CALL GetFieldSize ; add hl,bc ; ld a,(hl) ; inc a ; jr nz,$B ; inc hl ; ld a,(hl) ; dec hl ; inc a ; jr nz,$B ld bc,10+3+64 ;get well past the signature add hl,bc ;I'm REALLY not sure on this logic, but HL should be at a safe end for the application ld (appEnd),hl ld hl,mainMenu ld (menuAddr),hl DrawMenu: B_CALL ForceFullScreen B_CALL ClrLCDFull B_CALL HomeUp ld hl,(menuAddr) call PutSApp ld de,0001h ld b,(hl) ld a,b ld (numChoices),a inc hl $$: push bc ld (curRow),de push de call PutSApp pop de inc e inc hl inc hl pop bc djnz $B keyLoop: B_CALL GetKey cp kQuit jr z,ExitApp cp kClear jr z,ExitApp cp k1 jr c,keyLoop sub k1 ld b,a ld a,(numChoices) dec a cp b jp m,keyLoop inc b push bc ld hl,(menuAddr) xor a ld bc,20 cpir inc hl pop de dec hl dec hl $$: inc hl inc hl xor a ld bc,20 cpir dec d jr nz,$B ld e,(hl) inc hl ld d,(hl) ex de,hl jp (hl) LoadConfiguration: B_CALL ClrLCDFull B_CALL HomeUp ld hl,(appEnd) call GetNextAppStorageBlock jr c,$F xor a call LoadConfigFromStorageArea ld hl,sConfigLoaded call PutSApp call DisplayPressAnyKey B_CALL GetKey jr StartApp $$: ld hl,sNoConfigFound call PutSApp call DisplayPressAnyKey B_CALL GetKey jr StartApp sNoConfigFound: DB "No stored " DB "configuration " DB "found! " DB "Install hooks, " DB "then add to the " DB "chains from the " DB "main menu.",0 sConfigLoaded: DB "Stored " DB "configuration " DB "has been loaded " DB "successfully!",0 ClearConfiguration: B_CALL ClrLCDFull B_CALL HomeUp ld a,24 $$: push af call InvalidateHookBlock pop af dec a jr nz,$B call ClearHookConfiguration ld hl,sConfigCleared call PutSApp call DisplayPressAnyKey B_CALL GetKey jr StartApp sConfigCleared: DB "Configuration " DB "successfully " DB "cleared!",0 DisableHooks: B_CALL ClrLCDFull B_CALL HomeUp call ClearHookConfiguration ld hl,sHooksDisabled call PutSApp call DisplayPressAnyKey B_CALL GetKey jr StartApp sHooksDisabled: DB "Stored " DB "configuration " DB "has been " DB "successfully " DB "unloaded!",0 GetNextAppStorageBlock: ld a,(hl) inc hl ld c,(hl) inc hl ld b,(hl) inc hl add hl,bc inc a scf ret z dec a jr z,GetNextAppStorageBlock or a ret ExitApp: B_CALL ClrLCDFull B_CALL GrBufClr B_CALL DelRes ;invalidate statVars B_JUMP JForceCmdNoChar mainMenu: DB "HookMan ",VER_STRING,0 DB 7 DB "1) Install",0 DW InstallHookMan DB "2) Manage Hooks",0 DW StartManager DB "3) Load Config",0 DW LoadConfiguration DB "4) Unload Config",0 DW DisableHooks DB "5) Clear Config",0 DW ClearConfiguration DB "6) Uninstall",0 DW UninstallHookMan DB "7) About",0 DW DispAbout Splash_DS: DB 5, 86 DB 231,188,199,107,220,28,204,107,222,103, 28 DB 214,25, 172,107, 26,49,172,105,140,214,176 DB 215,25, 236,123,154,25,172,105,140,214,152 DB 214,25, 172,107, 26,13,172,105,140,214,140 DB 231,153,167,107,220,56,207, 49,158,102,184 sAboutText: DB " HookMan " DB " Brandon Wilson ",0 Intro_Web: DB "detachedsolutions.com",0 Intro_Version: DB "Version ",VER_STRING,0 Intro_Build: DB "Build ",BUILD_STRING,0