WimpSWIVe 0.05 - Wimp SWI trapping module by AjC of DoggySoft Requires BAX 1.00 or later to compile. Source best viewed in a big mode, 114 column formatting Note - the list of SWI traps is checked through _backwards_ when looking for pre-trapping code. This means that traps at the start of the list get called _after_ those at end. This may confuse some people. ;-) trapped_chunk=&400C0 specialswi=&400F5-&400C0 chainchunks=512 os_module_claim=6 os_module_release=7 os_module_extend=13 Workblock constants - wimpprivateword MUST be the first item (don't ask why...) w=0 :wk_wimpprivateword=w w+=4:wk_wimpswihandler=w w+=4:wk_chainptr=w w+=4:wk_numberoftraps=w code 100000 0,"Error in compilation, pass "+ pass+": "+ $+", at line "+ pass=4 O%=code:P%=0 [OPT pass Equd 0 Equd mod_init Equd mod_quit Equd mod_service Equd mod_title Equd mod_help Equd 0 .mod_chunk Equd trapped_chunk Equd swi_handler Equd swi_table Equd 0 .mod_title Equz "WimpSWIVe" Align .mod_help Equs "WimpSWIVe"+ 2" Equz "0.05 (30 Oct 1995)" Align .swi_table Equz "Wimp" Equz "Initialise" Equz "CreateWindow" Equz "CreateIcon" Equz "DeleteWindow" Equz "DeleteIcon" Equz "OpenWindow" Equz "CloseWindow" Equz "Poll" Equz "RedrawWindow" Equz "UpdateWindow" Equz "GetRectangle" Equz "GetWindowState" Equz "GetWindowInfo" Equz "SetIconState" Equz "GetIconState" Equz "GetPointerInfo" Equz "DragBox" Equz "ForceRedraw" I Equz "SetCaretPosition" J Equz "GetCaretPosition" Equz "CreateMenu" Equz "DecodeMenu" Equz "WhichIcon" Equz "SetExtent" Equz "SetPointerShape" Equz "OpenTemplate" Equz "CloseTemplate" Equz "LoadTemplate" Equz "ProcessKey" Equz "CloseDown" Equz "StartTask" Equz "ReportError" W Equz "GetWindowOutline" Equz "PollIdle" Equz "PlotIcon" Equz "SetMode" Equz "SetPalette" Equz "ReadPalette" Equz "SetColour" Equz "SendMessage" Equz "CreateSubMenu" Equz "SpriteOp" Equz "BaseOfSprites" Equz "BlockCopy" Equz "SlotSize" Equz "ReadPixTrans" Equz "ClaimFreeMemory" Equz "CommandWindow" Equz "TextColour" Equz "TransferBlock" Equz "ReadSysInfo" Equz "SetFontColours" Equz "GetMenuState" Equz "RegisterFilter" Equz "AddMessages" Equz "RemoveMessages" o Equz "SetColourMapping" Equz "TextOp" q Equz "SetWatchdogState" Equz "Extend" Equz "ResizeIcon" Equb 0 .wimpmodulename Equz "WindowManager" Align z .wswi Equs "WSWI" .error_cantquit Equd 0 ~V Equz "WimpSWIVe cannot be quit right now, as some clients are still using it" Align .error_badrelease Equd 0 % Equz "Bad WimpSWIVe release" Align .mod_init StmFd R13!,{R0-R5,R14} ! Mov R0,#os_module_claim Mov R3,#w Q Swi "XOS_Module" ; claim workspace AddVs R13,R13,#4 LdmVsFd R13!,{R1-R5,Pc} .init_jumpin Str R2,[R12] Mov R12,R2 Mov R0,#18 Adr R1,wimpmodulename a Swi "XOS_Module" ; find out details of WIMP module AddVs R13,R13,#4 LdmVsFd R13!,{R1-R5,Pc} * Str R4,[R12,#wk_wimpprivateword] Ldr R0,[R3,#&20] Add R3,R3,R0 \ Str R3,[R12,#wk_wimpswihandler] ; store details in workspace Mov R0,#0 ( Str R0,[R12,#wk_numberoftraps] ! Mov R0,#os_module_claim Mov R3,#chainchunks Swi "XOS_Module" AddVs R13,R13,#4 LdmVsFd R13!,{R1-R5,Pc} ^ Str R2,[R12,#wk_chainptr] ; initialise null vector chain LdmFd R13!,{R0-R5,Pc}^ .mod_quit StmFd R13!,{R0-R3,R14} Ldr R12,[R12] ( Ldr R0,[R12,#wk_numberoftraps] Teq R0,#0 LdmNeFd R13!,{R0-R3,R14} AdrNe R0,error_cantquit ] OrrNeS Pc,R14,#1<<28 ; check we're allowed to quit # Mov R0,#os_module_release # Ldr R2,[R12,#wk_chainptr] Swi "XOS_Module" # Mov R0,#os_module_release Mov R2,R12 _ Swi "XOS_Module" ; free claimed RMA then go away LdmFd R13!,{R0-R3,Pc}^ .mod_service Teq R1,#&27 MovNeS Pc,R14 Ldr R12,[R12] StmFd R13!,{R0-R5,R14} d B init_jumpin ; re-init when reset service happens .swi_handler Ldr R12,[R12] StmFd R13!,{R9,R10,R14} Mov R14,#0 v StmFd R13!,{R14} ; unset post-flag, initially no post-trapping required Teq R11,#specialswi LdrEq R14,wswi TeqEq R0,R14 t BEq ourspecialswi ; check if the WimpSWIVe control SWI has been called # Ldr R9,[R12,#wk_chainptr] ) Ldr R10,[R12,#wk_numberoftraps] Add R9,R9,R10,Lsl#4 .checkchainlooppre Sub R9,R9,#16 SubS R10,R10,#1 BMi swi_donepre Ldr R14,[R9] Tst R14,#1<<6 BNe preloopallswis And R14,R14,#63 Teq R14,R11 j BNe checkchainlooppre ; go through chain looking for SWI to trap .preloopallswis Ldr R14,[R9,#12] Teq R14,#0 MovNe R14,#1 m StrNe R14,[R13] ; set the post-flag if post-trapping required Ldr R14,[R9,#8] Teq R14,#0 h BEq checkchainlooppre ; if no pre-trapping to do, back to loop StmFd R13!,{R9,R10,R12} Orr R10,R14,#3 Orr R10,R10,#1<<27 Ldr R12,[R9,#4] Mov R9,R11 ! Adr R14,backfrompretrap Orr R14,R14,#3 Orr R14,R14,#1<<27 MovS Pc,R10 Y.backfrompretrap ; call a pre-trap routine Mov R10,Pc And R10,R10,#&F0000000 Cmn R9,#1 LdrEq R9,[R13,#24] BicEq R9,R9,#&F0000000 OrrEq R9,R9,R10 s StrEq R9,[R13,#24] ; if interception, update return PSR with new flags LdmFd R13!,{R9,R10,R12} BNe checkchainlooppre LdmFd R13!,{R14} Teq R14,#0 LdmEqFd R13!,{R9,R10,Pc}^ ) Ldr R14,[R12,#wk_numberoftraps] Sub R10,R14,R10 Sub R10,R10,#1 t B checkchainlooppost ; if interception, act as if SWI had been executed - t ; jump into post-trap loop with chain pointer intact t ; so that any post-code is called whose pre-code has m ; already been done. (Only if post-flag set.) .swi_donepre LdmFd R13!,{R14} Teq R14,#0 LdmEqFd R13!,{R9,R10,R14} r LdrEq Pc,[R12,#wk_wimpswihandler] ; pass on to real SWI if no post-trapping required LdmFd R13!,{R9,R10} StmFd R13!,{R12} ! Adr R14,backfromrealswi Orr R14,R14,#3 Orr R14,R14,#1<<27 ) Ldr Pc,[R12,#wk_wimpswihandler] \.backfromrealswi ; call the swi and post-trap LdmFd R13!,{R12} StmFd R13!,{R9,R10} Mov R10,Pc And R10,R10,#&F0000000 Ldr R9,[R13,#8] Bic R9,R9,#&F0000000 Orr R9,R9,R10 b Str R9,[R13,#8] ; update return PSR with new flags # Ldr R9,[R12,#wk_chainptr] ) Ldr R10,[R12,#wk_numberoftraps] Sub R9,R9,#16 .checkchainlooppost Add R9,R9,#16 SubS R10,R10,#1 LdmMiFd R13!,{R9,R10,Pc}^ Ldr R14,[R9] Tst R14,#1<<6 BNe postloopallswis And R14,R14,#63 Teq R14,R11 o BNe checkchainlooppost ; go through chain looking for SWI to post-trap .postloopallswis Ldr R14,[R9,#12] Teq R14,#0 d BEq checkchainlooppost ; if not post-trapping, back to loop StmFd R13!,{R9,R10,R12} Ldr R12,[R13,#20] And R12,R12,#&F0000000 Orr R10,R14,#3 Orr R10,R10,#1<<27 !` Orr R10,R10,R12 ; pass returned flags to routine "" Adr R14,backfromposttrap Orr R14,R14,R12 Orr R14,R14,#3 Orr R14,R14,#1<<27 Ldr R12,[R9,#4] Mov R9,R11 MovS Pc,R10 )Z.backfromposttrap ; call a post-trap routine Mov R10,Pc + And R10,R10,#&F0000000 Ldr R9,[R13,#20] Bic R9,R9,#&F0000000 Orr R9,R9,R10 /b Str R9,[R13,#20] ; update return PSR with new flags LdmFd R13!,{R9,R10,R12} 1 B checkchainlooppost .ourspecialswi StmFd R13!,{R0-R4} Tst R1,#1<<31 BEq ourswi_release 7^ B ourswi_claim ; split into claim and release .ourswi_claim :( Ldr R0,[R12,#wk_numberoftraps] Add R1,R0,#1 Mov R0,R0,Lsl#4 Mov R1,R1,Lsl#4 Mov R2,#chainchunks Sub R2,R2,#1 Bic R0,R0,R2 Bic R1,R1,R2 Teq R0,R1 C$ BEq claim_noneedtoaddchunk D" Mov R0,#os_module_extend E# Ldr R2,[R12,#wk_chainptr] Mov R3,#chainchunks Swi "XOS_Module" BVs ourswi_error I` Str R2,[R12,#wk_chainptr] ; claim extra memory if required .claim_noneedtoaddchunk LdmFd R13,{R0-R4} Tst R1,#1<<30 Mp BEq claim_add_lowpriority ; more complex routine needed for low-prio traps Bic R1,R1,#1<<31 O# Ldr R0,[R12,#wk_chainptr] P) Ldr R14,[R12,#wk_numberoftraps] Add R0,R0,R14,Lsl#4 Ra StmIa R0,{R1-R4} ; copy information to chain block S( Ldr R0,[R12,#wk_numberoftraps] Add R0,R0,#1 Ul Str R0,[R12,#wk_numberoftraps] ; increment numberoftraps, adding it to list LdmFd R13!,{R0-R4,R14} Wr LdmFd R13!,{R9,R10,Pc}^ ; and intercept SWI, having replaced functionality .claim_add_lowpriority Z# Ldr R0,[R12,#wk_chainptr] [( Ldr R1,[R12,#wk_numberoftraps] .claim_lowprioloop Cmp R1,#0 BLe claim_lowputtit Ldr R14,[R0] Tst R14,#1<<30 AddEq R0,R0,#16 SubEq R1,R1,#1 ct BEq claim_lowprioloop ; find first entry in list to be hi-pri, or list end Add R2,R0,R1,Lsl#4 .claim_budgeuploop Cmp R2,R0 BLe claim_lowputtit Ldr R14,[R2,#-16]! Str R14,[R2,#16] Ldr R14,[R2,#4] Str R14,[R2,#20] Ldr R14,[R2,#8] Str R14,[R2,#24] Ldr R14,[R2,#12] Str R14,[R2,#28] pa B claim_budgeuploop ; shift up all entries after this .claim_lowputtit Ldr R14,[R13,#4] Bic R14,R14,#1<<31 Str R14,[R0] Ldr R14,[R13,#8] Str R14,[R0,#4] Ldr R14,[R13,#12] Str R14,[R0,#8] Ldr R14,[R13,#16] zZ Str R14,[R0,#12] ; copy new entry into list {( Ldr R0,[R12,#wk_numberoftraps] Add R0,R0,#1 }Y Str R0,[R12,#wk_numberoftraps] ; increment numberoftraps LdmFd R13!,{R0-R4,R14} r LdmFd R13!,{R9,R10,Pc}^ ; and intercept SWI, having replaced functionality .ourswi_release # Ldr R9,[R12,#wk_chainptr] ) Ldr R10,[R12,#wk_numberoftraps] .checkchainreleaseloop SubS R10,R10,#1 ! AdrMi R0,error_badrelease l BMi ourswi_error ; complain if we reached the end of the list Ldr R0,[R9] And R0,R0,#63 And R14,R1,#63 Teq R0,R14 LdrEq R0,[R9,#4] TeqEq R0,R2 LdrEq R0,[R9,#8] TeqEq R0,R3 LdrEq R0,[R9,#12] TeqEq R0,R4 AddNe R9,R9,#16 l BNe checkchainreleaseloop ; check if values match, try next lot if not Add R0,R9,#16 .releaseblockmoveloop Teq R10,#0 LdmGtIa R0!,{R1-R4} StmGtIa R9!,{R1-R4} SubGt R10,R10,#1 ` BGt releaseblockmoveloop ; shove list after released down ( Ldr R0,[R12,#wk_numberoftraps] Sub R1,R0,#1 Mov R0,R0,Lsl#4 Mov R1,R1,Lsl#4 Mov R2,#chainchunks Sub R2,R2,#1 Bic R0,R0,R2 Bic R1,R1,R2 Teq R0,R1 ) BEq release_noneedtoremovechunk " Mov R0,#os_module_extend # Ldr R2,[R12,#wk_chainptr] Mov R3,#chainchunks Rsb R3,R3,#0 Swi "XOS_Module" h Str R2,[R12,#wk_chainptr] ; release any extra chunks we don't need .release_noneedtoremovechunk ( Ldr R0,[R12,#wk_numberoftraps] Sub R0,R0,#1 r Str R0,[R12,#wk_numberoftraps] ; take one off, leaving things nice and consistent LdmFd R13!,{R0-R4,R14} r LdmFd R13!,{R9,R10,Pc}^ ; and intercept SWI, having replaced functionality .ourswi_error Mov R9,R0 LdmFd R13!,{R0-R4,R14} Mov R0,R9 LdmFd R13!,{R9,R10,R14} Q OrrS Pc,R14,#1<<28 ; return an error g Equs 10+"In an emergency, we walk."+ 10+"And... anything below here is probably a virus." "OS_File",10,"WimpSWIVe",&FFA,,code,O%