; ; hour.s ; ; Handling of the hourglass (MDW) ; ; © 1994-1998 Straylight ; ;----- Licensing note ------------------------------------------------------- ; ; This file is part of Straylight's Sapphire library. ; ; Sapphire is free software; you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation; either version 2, or (at your option) ; any later version. ; ; Sapphire is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with Sapphire. If not, write to the Free Software Foundation, ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;----- Here is Wisdom -------------------------------------------------------; ; The standard Hourglass system is OK but for one small problem: you can't ; stop the thing and restart where you left off. So, we put a wrapper round ; it so that we can do this. This involves keeping our own record of ; exactly what's going on. ; ; This module is designed to be very small and unobtrusive, so you can have ; dependencies on it all over without much hassle. The only external ; dependency is on except, and wimp includes that anyway, so it's not really ; a great problem. ;----- Standard header ------------------------------------------------------ GET libs:header GET libs:swis ;----- External dependencies ------------------------------------------------ GET sapphire:except GET sapphire:sapphire ;----- Main code ------------------------------------------------------------ AREA |Sapphire$$Code|,CODE,READONLY ; --- hour_init --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Initialises the hour system, so it will display an hourglass ; when necessary. ; ; Since this gets called at a random point during the Sapphire ; initialisation, and we can rely on Hourglass keeping its ; own count, the suggested way of handling everything properly ; is as follows: ; ; SWI Hourglass_On ; BL sapphire_init ; SWI Hourglass_Off EXPORT hour_init hour_init ROUT STMFD R13!,{R12,R14} ;Save some registers WSPACE hour__wSpace ;Locate my workspace address ; --- Make sure I haven't already done this --- LDR R14,hour__flags ;Find my flags word nicely TST R14,#hFlag__inited ;Am I initialised yet? LDMNEFD R13!,{R12,PC}^ ;Yes -- return right now ; --- Set up my workspace properly --- STMFD R13!,{R0-R2} ;Save some more registers MOV R0,#hFlag__inited ;Say I'm initialised MOV R1,#0 ;No Hourglass count yet MOV R2,#255 ;No other status stuff either STMIA R12,{R0-R2} ;Save the stuff in workspace ; --- Register my atexit handler --- BL except_init ;Make sure except is awake ADR R0,hour__exit ;Point to the handler MOV R1,R12 ;Pass my workspace along BL except_atExit ;Make sure I can tidy up LDMFD R13!,{R0-R2,R12,PC}^ ;Return to caller LTORG hour__wSpace DCD 0 ; --- hour__exit --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Kills off the Hourglass if it's displaying when the program ; finally quits. hour__exit ROUT STMFD R13!,{R14} ;Store the return address LDR R14,hour__count ;Find my Hourglass counter CMP R14,#0 ;Is it not displaying? SWIGT Hourglass_Off ;No -- turn it off then LDMFD R13!,{PC}^ ;Return to caller finally LTORG ; --- hour_on --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Turns the Hourglass on only if it isn't on already. ; Otherwise its status is left as it was. EXPORT hour_on hour_on ROUT STMFD R13!,{R12,R14} ;Save a couple of registers WSPACE hour__wSpace ;Load my workspace pointer LDR R14,hour__count ;Find my Hourglass counter ADD R14,R14,#1 ;Bump the counter on one STR R14,hour__count ;Store it back again CMP R14,#1 ;Has it just been turned on? SWIEQ Hourglass_On ;Yes -- turn it on then LDMFD R13!,{R12,PC}^ ;Return to caller finally LTORG ; --- hour_off --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Turns the Hourglass off if it's only been turned on once. ; If the Hourglass gets turned off, all the information about ; it (percentage and LEDs) get forgotten. EXPORT hour_off hour_off ROUT STMFD R13!,{R12,R14} ;Save some registers WSPACE hour__wSpace ;Load my workspace pointer LDR R14,hour__count ;Find my Hourglass counter SUBS R14,R14,#1 ;Decrement it nicely MOVLT R14,#0 ;If negative, keep at zero STR R14,hour__count ;Store counter back anyway STRLE R14,hour__percent ;If turning off, zero percent SWILE Hourglass_Off ;and turn Hourglass off too LDMFD R13!,{R12,PC}^ ;Return to caller LTORG ; --- hour_percent --- ; ; On entry: R0 == percentage value to display, or -1 to remove ; ; On exit: -- ; ; Use: Attaches a percentage display to the Hourglass. EXPORT hour_percent hour_percent ROUT STMFD R13!,{R12,R14} ;Save some registers away WSPACE hour__wSpace ;Find my workspace address LDR R14,hour__count ;Get the counter out CMP R14,#0 ;Has it been turned on yet? STRGTB R0,hour__percent ;Yes -- store the percentage SWIGT Hourglass_Percentage ;And display it properly LDMFD R13!,{R12,PC}^ ;Return to caller LTORG ; --- hour_leds --- ; ; On entry: R0 == LED mask EOR value ; R1 == LED mask AND value ; ; On exit: -- ; ; Use: Changes the Hourglass LED status. EXPORT hour_leds hour_leds STMFD R13!,{R0,R1,R12,R14} ;Save some registers away WSPACE hour__wSpace ;Find my workspace address LDR R14,hour__count ;Get the counter out CMP R14,#0 ;Has it been turned on yet? LDMLEFD R13!,{R0,R1,R12,PC}^ ;No -- just return then LDR R14,hour__leds ;Get the current LED state AND R14,R14,R1 ;Apply the AND mask to it EOR R0,R14,R0 ;Apply the EOR mask to it LDR R0,hour__leds ;Store the status back again MOV R1,#0 ;Clear all LED bits SWI Hourglass_LEDs ;Now set the actual LEDs LDMFD R13!,{R0,R1,R12,PC}^ ;Return to caller LTORG ; --- hour_suspend --- ; ; On entry: R0 == pointer to 2 word block to save status in ; ; On exit: -- ; ; Use: Saves the Hourglass state in a block you've pointed at, ; and disables the Hourglass. Useful if you want to do some ; user interaction without polling (e.g. an error box). EXPORT hour_suspend hour_suspend ROUT STMFD R13!,{R0-R2,R12,R14} ;Save a bunch of registers WSPACE hour__wSpace ;Load my workspace address LDMIB R12,{R1,R2} ;Load the Hourglass state STMIA R0,{R1,R2} ;Save it in caller's block CMP R1,#0 ;Is the Hourglass on ATM? SWIGT Hourglass_Off ;Yes -- turn it off then MOV R1,#0 ;Zero the counter MOV R2,#255 ;And the other status bits STMIB R12,{R1,R2} ;Save over my old state LDMFD R13!,{R0-R2,R12,PC}^ ;Return to caller nicely LTORG ; --- hour_save --- ; ; On entry: R0 == pointer to 2 word block to save status in ; ; On exit: -- ; ; Use: Saves the current Hourglass status without altering it. EXPORT hour_save hour_save ROUT STMFD R13!,{R0-R2,R12,R14} ;Save a bunch of registers WSPACE hour__wSpace ;Load my workspace address LDMIB R12,{R1,R2} ;Load the Hourglass state STMIA R0,{R1,R2} ;Save it in caller's block LDMFD R13!,{R0-R2,R12,PC}^ ;Return to caller finally LTORG ; --- hour_resume, hour_restore --- ; ; On entry: R0 == pointer to 2 words filled by hour_suspend or hour_save ; ; On exit: -- ; ; Use: Restores the Hourglass state to that saved away by one ; of the previous two calls. This routine has two names. EXPORT hour_resume EXPORT hour_restore hour_resume hour_restore ROUT STMFD R13!,{R0,R1,R12,R14} ;Save some registers away WSPACE hour__wSpace ;Load my workspace address LDR R14,hour__count ;Load the current counter ; --- Restore the workspace contents --- LDMIA R0,{R0,R1} ;Load the saved status CMP R0,#0 ;Is the Hourglass on? MOVLT R0,#0 ;If negative, restore to 0 MOVLE R1,#255 ;If off, force percent off STMIB R12,{R0,R1} ;Save in my workspace ; --- Now restore the Hourglass onness --- MOVGT R0,#1 ;If now on, store as 1 CMP R14,#0 ;Is the old state on? MOVLT R14,#0 ;Force result nonnegative MOVGT R14,#1 ;If was on, store as 1 CMP R0,R14 ;Are the states the same? SWIGT Hourglass_On ;If now on, was off, enable SWILT Hourglass_Off ;If now off, was on, disable CMP R0,#0 ;Is it now off? LDMEQFD R13!,{R0,R1,R12,PC}^ ;Yes -- return to caller ; --- Now restore other Hourglass bits --- AND R0,R1,#&FF ;Get the percentage state SWI Hourglass_Percentage ;Send that to the Hourglass AND R0,R1,#&FF00 ;Get the LED state too MOV R0,R0,LSR #8 ;Shift down to bottom of R0 MOV R1,#0 ;Don't leave old state there SWI Hourglass_LEDs ;And restore LED state LDMFD R13!,{R0,R1,R12,PC}^ ;Return, we did everything LTORG ;----- Workspace ------------------------------------------------------------ ^ 0,R12 hour__wStart # 0 hour__flags # 4 ;A flags word (see later) hour__count # 4 ;no(hour_on) - no(hour_off) hour__percent # 1 ;Current percentage displayed hour__leds # 1 ;Current LED status hour__padding # 2 ;Pad size to word boundary hour__wSize EQU {VAR}-hour__wStart hFlag__inited EQU (1<<0) ;Am I initialised yet? AREA |Sapphire$$LibData|,CODE,READONLY DCD hour__wSize DCD hour__wSpace DCD 0 DCD hour_init ;----- That's all, folks ---------------------------------------------------- END