Initial revision
[ssr] / StraySrc / Libraries / Sapphire / s / hour
1 ;
2 ; hour.s
3 ;
4 ; Handling of the hourglass (MDW)
5 ;
6 ; © 1994-1998 Straylight
7 ;
8
9 ;----- Licensing note -------------------------------------------------------
10 ;
11 ; This file is part of Straylight's Sapphire library.
12 ;
13 ; Sapphire is free software; you can redistribute it and/or modify
14 ; it under the terms of the GNU General Public License as published by
15 ; the Free Software Foundation; either version 2, or (at your option)
16 ; any later version.
17 ;
18 ; Sapphire is distributed in the hope that it will be useful,
19 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 ; GNU General Public License for more details.
22 ;
23 ; You should have received a copy of the GNU General Public License
24 ; along with Sapphire. If not, write to the Free Software Foundation,
25 ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26
27 ;----- Here is Wisdom -------------------------------------------------------;
28 ; The standard Hourglass system is OK but for one small problem: you can't
29 ; stop the thing and restart where you left off. So, we put a wrapper round
30 ; it so that we can do this. This involves keeping our own record of
31 ; exactly what's going on.
32 ;
33 ; This module is designed to be very small and unobtrusive, so you can have
34 ; dependencies on it all over without much hassle. The only external
35 ; dependency is on except, and wimp includes that anyway, so it's not really
36 ; a great problem.
37
38 ;----- Standard header ------------------------------------------------------
39
40 GET libs:header
41 GET libs:swis
42
43 ;----- External dependencies ------------------------------------------------
44
45 GET sapphire:except
46 GET sapphire:sapphire
47
48 ;----- Main code ------------------------------------------------------------
49
50 AREA |Sapphire$$Code|,CODE,READONLY
51
52 ; --- hour_init ---
53 ;
54 ; On entry: --
55 ;
56 ; On exit: --
57 ;
58 ; Use: Initialises the hour system, so it will display an hourglass
59 ; when necessary.
60 ;
61 ; Since this gets called at a random point during the Sapphire
62 ; initialisation, and we can rely on Hourglass keeping its
63 ; own count, the suggested way of handling everything properly
64 ; is as follows:
65 ;
66 ; SWI Hourglass_On
67 ; BL sapphire_init
68 ; SWI Hourglass_Off
69
70 EXPORT hour_init
71 hour_init ROUT
72
73 STMFD R13!,{R12,R14} ;Save some registers
74 WSPACE hour__wSpace ;Locate my workspace address
75
76 ; --- Make sure I haven't already done this ---
77
78 LDR R14,hour__flags ;Find my flags word nicely
79 TST R14,#hFlag__inited ;Am I initialised yet?
80 LDMNEFD R13!,{R12,PC}^ ;Yes -- return right now
81
82 ; --- Set up my workspace properly ---
83
84 STMFD R13!,{R0-R2} ;Save some more registers
85 MOV R0,#hFlag__inited ;Say I'm initialised
86 MOV R1,#0 ;No Hourglass count yet
87 MOV R2,#255 ;No other status stuff either
88 STMIA R12,{R0-R2} ;Save the stuff in workspace
89
90 ; --- Register my atexit handler ---
91
92 BL except_init ;Make sure except is awake
93 ADR R0,hour__exit ;Point to the handler
94 MOV R1,R12 ;Pass my workspace along
95 BL except_atExit ;Make sure I can tidy up
96
97 LDMFD R13!,{R0-R2,R12,PC}^ ;Return to caller
98
99 LTORG
100
101 hour__wSpace DCD 0
102
103 ; --- hour__exit ---
104 ;
105 ; On entry: --
106 ;
107 ; On exit: --
108 ;
109 ; Use: Kills off the Hourglass if it's displaying when the program
110 ; finally quits.
111
112 hour__exit ROUT
113
114 STMFD R13!,{R14} ;Store the return address
115 LDR R14,hour__count ;Find my Hourglass counter
116 CMP R14,#0 ;Is it not displaying?
117 SWIGT Hourglass_Off ;No -- turn it off then
118 LDMFD R13!,{PC}^ ;Return to caller finally
119
120 LTORG
121
122 ; --- hour_on ---
123 ;
124 ; On entry: --
125 ;
126 ; On exit: --
127 ;
128 ; Use: Turns the Hourglass on only if it isn't on already.
129 ; Otherwise its status is left as it was.
130
131 EXPORT hour_on
132 hour_on ROUT
133
134 STMFD R13!,{R12,R14} ;Save a couple of registers
135 WSPACE hour__wSpace ;Load my workspace pointer
136 LDR R14,hour__count ;Find my Hourglass counter
137 ADD R14,R14,#1 ;Bump the counter on one
138 STR R14,hour__count ;Store it back again
139 CMP R14,#1 ;Has it just been turned on?
140 SWIEQ Hourglass_On ;Yes -- turn it on then
141 LDMFD R13!,{R12,PC}^ ;Return to caller finally
142
143 LTORG
144
145 ; --- hour_off ---
146 ;
147 ; On entry: --
148 ;
149 ; On exit: --
150 ;
151 ; Use: Turns the Hourglass off if it's only been turned on once.
152 ; If the Hourglass gets turned off, all the information about
153 ; it (percentage and LEDs) get forgotten.
154
155 EXPORT hour_off
156 hour_off ROUT
157
158 STMFD R13!,{R12,R14} ;Save some registers
159 WSPACE hour__wSpace ;Load my workspace pointer
160 LDR R14,hour__count ;Find my Hourglass counter
161 SUBS R14,R14,#1 ;Decrement it nicely
162 MOVLT R14,#0 ;If negative, keep at zero
163 STR R14,hour__count ;Store counter back anyway
164 STRLE R14,hour__percent ;If turning off, zero percent
165 SWILE Hourglass_Off ;and turn Hourglass off too
166 LDMFD R13!,{R12,PC}^ ;Return to caller
167
168 LTORG
169
170 ; --- hour_percent ---
171 ;
172 ; On entry: R0 == percentage value to display, or -1 to remove
173 ;
174 ; On exit: --
175 ;
176 ; Use: Attaches a percentage display to the Hourglass.
177
178 EXPORT hour_percent
179 hour_percent ROUT
180
181 STMFD R13!,{R12,R14} ;Save some registers away
182 WSPACE hour__wSpace ;Find my workspace address
183 LDR R14,hour__count ;Get the counter out
184 CMP R14,#0 ;Has it been turned on yet?
185 STRGTB R0,hour__percent ;Yes -- store the percentage
186 SWIGT Hourglass_Percentage ;And display it properly
187 LDMFD R13!,{R12,PC}^ ;Return to caller
188
189 LTORG
190
191 ; --- hour_leds ---
192 ;
193 ; On entry: R0 == LED mask EOR value
194 ; R1 == LED mask AND value
195 ;
196 ; On exit: --
197 ;
198 ; Use: Changes the Hourglass LED status.
199
200 EXPORT hour_leds
201 hour_leds STMFD R13!,{R0,R1,R12,R14} ;Save some registers away
202 WSPACE hour__wSpace ;Find my workspace address
203 LDR R14,hour__count ;Get the counter out
204 CMP R14,#0 ;Has it been turned on yet?
205 LDMLEFD R13!,{R0,R1,R12,PC}^ ;No -- just return then
206 LDR R14,hour__leds ;Get the current LED state
207 AND R14,R14,R1 ;Apply the AND mask to it
208 EOR R0,R14,R0 ;Apply the EOR mask to it
209 LDR R0,hour__leds ;Store the status back again
210 MOV R1,#0 ;Clear all LED bits
211 SWI Hourglass_LEDs ;Now set the actual LEDs
212 LDMFD R13!,{R0,R1,R12,PC}^ ;Return to caller
213
214 LTORG
215
216 ; --- hour_suspend ---
217 ;
218 ; On entry: R0 == pointer to 2 word block to save status in
219 ;
220 ; On exit: --
221 ;
222 ; Use: Saves the Hourglass state in a block you've pointed at,
223 ; and disables the Hourglass. Useful if you want to do some
224 ; user interaction without polling (e.g. an error box).
225
226 EXPORT hour_suspend
227 hour_suspend ROUT
228
229 STMFD R13!,{R0-R2,R12,R14} ;Save a bunch of registers
230 WSPACE hour__wSpace ;Load my workspace address
231 LDMIB R12,{R1,R2} ;Load the Hourglass state
232 STMIA R0,{R1,R2} ;Save it in caller's block
233 CMP R1,#0 ;Is the Hourglass on ATM?
234 SWIGT Hourglass_Off ;Yes -- turn it off then
235 MOV R1,#0 ;Zero the counter
236 MOV R2,#255 ;And the other status bits
237 STMIB R12,{R1,R2} ;Save over my old state
238 LDMFD R13!,{R0-R2,R12,PC}^ ;Return to caller nicely
239
240 LTORG
241
242 ; --- hour_save ---
243 ;
244 ; On entry: R0 == pointer to 2 word block to save status in
245 ;
246 ; On exit: --
247 ;
248 ; Use: Saves the current Hourglass status without altering it.
249
250 EXPORT hour_save
251 hour_save ROUT
252
253 STMFD R13!,{R0-R2,R12,R14} ;Save a bunch of registers
254 WSPACE hour__wSpace ;Load my workspace address
255 LDMIB R12,{R1,R2} ;Load the Hourglass state
256 STMIA R0,{R1,R2} ;Save it in caller's block
257 LDMFD R13!,{R0-R2,R12,PC}^ ;Return to caller finally
258
259 LTORG
260
261 ; --- hour_resume, hour_restore ---
262 ;
263 ; On entry: R0 == pointer to 2 words filled by hour_suspend or hour_save
264 ;
265 ; On exit: --
266 ;
267 ; Use: Restores the Hourglass state to that saved away by one
268 ; of the previous two calls. This routine has two names.
269
270 EXPORT hour_resume
271 EXPORT hour_restore
272 hour_resume
273 hour_restore ROUT
274
275 STMFD R13!,{R0,R1,R12,R14} ;Save some registers away
276 WSPACE hour__wSpace ;Load my workspace address
277 LDR R14,hour__count ;Load the current counter
278
279 ; --- Restore the workspace contents ---
280
281 LDMIA R0,{R0,R1} ;Load the saved status
282 CMP R0,#0 ;Is the Hourglass on?
283 MOVLT R0,#0 ;If negative, restore to 0
284 MOVLE R1,#255 ;If off, force percent off
285 STMIB R12,{R0,R1} ;Save in my workspace
286
287 ; --- Now restore the Hourglass onness ---
288
289 MOVGT R0,#1 ;If now on, store as 1
290 CMP R14,#0 ;Is the old state on?
291 MOVLT R14,#0 ;Force result nonnegative
292 MOVGT R14,#1 ;If was on, store as 1
293 CMP R0,R14 ;Are the states the same?
294 SWIGT Hourglass_On ;If now on, was off, enable
295 SWILT Hourglass_Off ;If now off, was on, disable
296 CMP R0,#0 ;Is it now off?
297 LDMEQFD R13!,{R0,R1,R12,PC}^ ;Yes -- return to caller
298
299 ; --- Now restore other Hourglass bits ---
300
301 AND R0,R1,#&FF ;Get the percentage state
302 SWI Hourglass_Percentage ;Send that to the Hourglass
303 AND R0,R1,#&FF00 ;Get the LED state too
304 MOV R0,R0,LSR #8 ;Shift down to bottom of R0
305 MOV R1,#0 ;Don't leave old state there
306 SWI Hourglass_LEDs ;And restore LED state
307 LDMFD R13!,{R0,R1,R12,PC}^ ;Return, we did everything
308
309 LTORG
310
311 ;----- Workspace ------------------------------------------------------------
312
313 ^ 0,R12
314 hour__wStart # 0
315
316 hour__flags # 4 ;A flags word (see later)
317 hour__count # 4 ;no(hour_on) - no(hour_off)
318 hour__percent # 1 ;Current percentage displayed
319 hour__leds # 1 ;Current LED status
320 hour__padding # 2 ;Pad size to word boundary
321
322 hour__wSize EQU {VAR}-hour__wStart
323
324 hFlag__inited EQU (1<<0) ;Am I initialised yet?
325
326 AREA |Sapphire$$LibData|,CODE,READONLY
327
328 DCD hour__wSize
329 DCD hour__wSpace
330 DCD 0
331 DCD hour_init
332
333 ;----- That's all, folks ----------------------------------------------------
334
335 END