chiark / gitweb /
Initial revision
[ssr] / StraySrc / Libraries / Sapphire / xfer / s / save
1 ;
2 ; xfer.save.s
3 ;
4 ; Saving data to other applications (MDW)
5 ;
6 ; © 1994 Straylight
7 ;
8
9 ;----- Standard header ------------------------------------------------------
10
11                 GET     libs:header
12                 GET     libs:swis
13
14 ;----- External dependencies ------------------------------------------------
15
16                 GET     sapphire:fastMove
17                 GET     sapphire:msgs
18                 GET     sapphire:sapphire
19                 GET     sapphire:string
20                 GET     sapphire:wimp
21                 GET     sapphire:win
22
23 ;----- Main code ------------------------------------------------------------
24
25                 AREA    |Sapphire$$Code|,CODE,READONLY
26
27 ; --- save ---
28 ;
29 ; On entry:     R0 == window handle to send to
30 ;               R1 == icon handle to send to
31 ;               R2 == estimated size of the data
32 ;               R3 == file type of data to send and flag:
33 ;                     bit 31: use R8 as below
34 ;               R4 == pointer to name of file (may be full path)
35 ;               R5 == address of handler block
36 ;               R6 == value to pass handlers in R10
37 ;               R7 == value to pass handlers in R12
38 ;               R8 == pointer to extra handler block (only if bit 31 of R3)
39 ;
40 ; On exit:      --
41 ;
42 ; Use:          Starts a save operation to another application.  The extra
43 ;               handler is used by systems like saveas which need to be
44 ;               aware of data transfer start/end conditions without
45 ;               interfering with the normal entry table.  This will not
46 ;               normally concern applications however.
47
48                 EXPORT  save
49 save            ROUT
50
51                 STMFD   R13!,{R0-R8,R12,R14}    ;Save a load of registers
52                 WSPACE  save__wSpace            ;Find my workspace pointer
53
54                 ; --- Save some information in workspace ---
55
56                 TST     R3,#&80000000           ;Is there an extra handler?
57                 MOVEQ   R8,#0                   ;No -- then clear pointer
58                 SUBNE   R8,R8,#sEntry__success  ;Otherwise, pad it out a bit
59                 BIC     R3,R3,#&FF000000        ;Clear the flag bits
60                 ADR     R14,save__handler       ;Save the handler information
61                 STMIA   R14,{R5-R8}             ;Save them for later
62
63                 MOV     R14,#0                  ;No buffer to send yet
64                 STR     R14,save__srcSize       ;So clear out its size
65                 STR     R14,save__acc           ;And clear RAM transfer acc
66                 MOV     R14,#sState__safe       ;Data is safe at the moment
67                 STR     R14,save__state         ;Clear out any old state info
68
69                 ; --- Get the leafname of the file ---
70
71                 MOV     R5,R4                   ;Point to the name start
72 00save          LDRB    R14,[R5],#1             ;Get a character from it
73                 CMP     R14,#'.'                ;Is it a directory separator?
74                 MOVEQ   R4,R5                   ;Yes -- update pointer
75                 CMP     R14,#32                 ;Is this the name end?
76                 BGE     %00save                 ;No -- go round for more
77
78                 ; --- Find the mouse position ---
79
80                 SUB     R13,R13,#36             ;Make way for a pointer block
81                 MOV     R1,R13                  ;Point to the new space
82                 SWI     Wimp_GetPointerInfo     ;Read the mouse position
83                 LDMIA   R1,{R7,R14}             ;Load the mouse coordinates
84                 ADD     R13,R13,#36             ;Reclaim the stack space
85                 LDMIA   R13,{R5,R6}             ;Load the window and icon
86
87                 ; --- Build the message at last ---
88
89                 ADD     R0,R11,#20              ;Start building msg body
90                 STMIA   R0!,{R5-R7,R14}         ;Save coords and window hnd
91                 STMIA   R0!,{R2,R3}             ;Save estimated size and type
92                 MOV     R1,R4                   ;Point to the filename
93                 BL      str_cpy                 ;Copy the name over
94                 ADD     R0,R0,#4                ;Include the null terminator
95                 SUB     R0,R0,R11               ;Get the final offset
96                 BIC     R0,R0,#3                ;Round off to word size
97                 STR     R0,[R11,#0]             ;Save the message size
98                 ADD     R0,R11,#12              ;Point into message header
99                 MOV     R1,#0                   ;This isn't a reply
100                 MOV     R2,#1                   ;The message code for save
101                 STMIA   R0,{R1,R2}              ;Store them in the message
102
103                 ; --- Send the message over ---
104
105                 MOV     R0,#18                  ;I want a bounce if it fails
106                 MOV     R1,R11                  ;Point to message in scratch
107                 LDMIA   R13,{R2,R3}             ;Load the window to send to
108                 SWI     Wimp_SendMessage        ;Send the message to it then
109
110                 ; --- Register the unknown handler to fix it all ---
111
112                 ADR     R0,save__unknown        ;Point to my handler
113                 MOV     R1,#0                   ;Nothing interesting in R4
114                 MOV     R2,#0                   ;Nothing interesting in R10
115                 MOV     R3,R12                  ;Pass my workspace pointer
116                 BL      win_unknownHandler      ;Add in the handler nicely
117                 LDMFD   R13!,{R0-R8,R12,PC}^    ;Restore registers and return
118
119                 LTORG
120
121 ; --- save__unknown ---
122 ;
123 ; On entry:     R0 == event code
124 ;               R1 == pointer to event data
125 ;
126 ; On exit:      --
127 ;
128 ; Use:          Handles unknown events during a save operation.
129
130 save__unknown   ROUT
131
132                 CMP     R0,#19                  ;Is this a message bounce?
133                 BEQ     %60save__unknown        ;Yes -- skip to handle it
134                 CMP     R0,#17                  ;Is this any sort of message?
135                 CMPNE   R0,#18                  ;Check both types
136                 MOVNE   PC,R14                  ;No -- return to caller
137
138                 ; --- Check the message codes ---
139
140                 STMFD   R13!,{R14}              ;Save the link to check it
141                 LDR     R14,[R1,#16]            ;Load the message code
142                 CMP     R14,#6                  ;Is it a RamFetch message?
143                 BEQ     %20save__unknown        ;Yes -- get a buffer to send
144                 CMP     R14,#4                  ;Is it a DataLoadAck?
145                 BEQ     %40save__unknown        ;Yes -- wrap scrap xfer up
146                 CMP     R14,#2                  ;Is it a DataSaveAck?
147                 LDMNEFD R13!,{PC}^              ;No -- return to caller
148
149                 ; --- It's a normal acknowledgement ---
150
151                 STMFD   R13!,{R0-R2,R10,R12}    ;Save some more registers
152                 ADD     R0,R1,#44               ;Point to the filename
153                 LDR     R1,[R1,#36]             ;Load the estimated size
154                 CMP     R1,#-1                  ;Is it an unsafe file?
155                 MOVLE   R1,#0                   ;Yes if est size < 0
156                 MOVGT   R1,#1                   ;No if est size >= 0
157                 STRLE   R1,save__state          ;Store the state away
158                 ADR     R14,save__handler       ;Point to the handler block
159                 LDMIA   R14,{R2,R10,R12}        ;Load the registers out
160                 ADDS    R0,R0,#0                ;Clear carry and overflow
161                 MOV     R14,PC                  ;Set up the return address
162                 ADD     PC,R2,#sEntry__save     ;Call the save routine
163                 WSPACE  save__wSpace            ;Load workspace pointer again
164                 BLVS    save__finish            ;Wrap everything up here
165                 BVS     %10save__unknown        ;It failed -- skip to the end
166
167                 ; --- Send the DataLoad message ---
168
169                 MOV     R0,R11                  ;Copy it to the scratchpad
170                 LDR     R1,[R13,#4]             ;Read from the message block
171                 LDR     R2,[R1,#0]              ;Message size, conveniently
172                 BL      fastMove                ;Copy it over quickly
173                 LDR     R14,[R1,#8]             ;Get his reference number
174                 STR     R14,[R1,#12]            ;Store it so I can reply
175                 MOV     R14,#3                  ;Send a DataLoad message
176                 STR     R14,[R1,#16]            ;Save it in the message code
177                 LDR     R2,[R1,#4]              ;Get his task handle out
178                 MOV     R0,#18                  ;Make sure I get a bounce
179                 SWI     Wimp_SendMessage        ;Send the message to him
180
181 10save__unknown LDMFD   R13!,{R0-R2,R10,R12,R14} ;Restore all the registers
182                 ORRS    PC,R14,#C_flag          ;Return with carry set
183
184                 ; --- It's a request for memory transfer ---
185
186 20save__unknown STMFD   R13!,{R0-R7,R10,R12}    ;Save some more registers
187                 LDR     R14,save__handler       ;Load the handlers block
188                 LDR     R14,[R14,#sEntry__send] ;Get the send entry
189                 CMP     R14,#0                  ;Is it defined properly?
190                 BEQ     %35save__unknown        ;No -- skip to the end
191
192                 ; --- Set things up for the main loop ---
193
194                 MOV     R6,#0                   ;No data sent yet
195                 LDR     R2,[R1,#4]              ;Load his task handle
196                 ADD     R3,R1,#20               ;Point to dest buffer info
197                 LDMIA   R3,{R3,R5}              ;Load his buffer info
198                 ADR     R1,save__srcBuff        ;Point to source buffer info
199                 LDMIA   R1,{R1,R7}              ;Load the information out
200
201                 ; --- Now for the main loop then ---
202
203 25save__unknown LDR     R14,save__state         ;Get the current state
204                 CMP     R14,#sState__xferred    ;Have we finished?
205                 BEQ     %30save__unknown        ;Yes -- skip to the end
206
207                 CMP     R7,#0                   ;Is there any data waiting?
208                 BNE     %30save__unknown        ;Yes -- skip the next bit
209
210                 ; --- Find some data from the client ---
211
212                 ADR     R14,save__handler       ;Point to the handler
213                 STMFD   R13!,{R2}               ;Save the old R2 value away
214                 LDR     R2,save__acc            ;Load caller's accumulator
215                 LDMIA   R14,{R0,R10,R12}        ;Get ready to call it
216                 ADDS    R0,R0,#0                ;Clear lots of flags
217                 MOV     R14,PC                  ;Set up the return address
218                 ADD     PC,R0,#sEntry__send     ;Get some data to send
219                 WSPACE  save__wSpace            ;Load my workspace again
220                 BLVS    save__finish            ;It failed -- wrap things up
221                 ADDVS   R13,R13,#4              ;Don't bother with acc.
222                 BVS     %35save__unknown        ;And skip to the end
223                 STRCC   R2,save__acc            ;Save accumulator back
224                 LDMFD   R13!,{R2}               ;Reload saved R2 value
225                 MOVCS   R14,#sState__xferred    ;If that's the last one...
226                 STRCS   R14,save__state         ;Save the state flag away
227                 MOV     R7,R1                   ;Copy the size and the...
228                 MOV     R1,R0                   ;... buffer pointers away
229
230                 ; --- Send another bufferfull ---
231
232 30save__unknown CMP     R5,R7                   ;Which one is bigger?
233                 MOVLT   R4,R5                   ;Choose the smaller as the...
234                 MOVGE   R4,R7                   ;... buffer size to send
235                 BL      wimp_taskHandle         ;Get my task handle ready
236                 SWI     Wimp_TransferBlock      ;Transfer the data across
237
238                 ; --- Set things up for the next go round ---
239
240                 ADD     R6,R6,R4                ;Bump the amount we've sent
241                 SUB     R7,R7,R4                ;Decrement the amount to send
242                 SUB     R5,R5,R4                ;And the destination buffer
243                 ADD     R1,R1,R4                ;But bump the buffer pointer
244                 ADD     R3,R3,R4                ;For both sides of the xfer
245
246                 ; --- Find out if we need to go again ---
247
248                 LDR     R14,save__state         ;Get my state variable again
249                 CMP     R14,#sState__xferred    ;Is the transfer proceeding?
250                 CMPNE   R5,#0                   ;And is he waiting for more?
251                 BNE     %25save__unknown        ;Yes -- loop back round then
252
253                 ; --- Update all the variables ---
254
255                 ADR     R14,save__srcBuff       ;Point to source buff address
256                 STMIA   R14,{R1,R7}             ;Save the updated values back
257
258                 ; --- Send the RamTransmit to the other task ---
259
260                 MOV     R0,#28                  ;Size of my message block
261                 LDR     R1,[R13,#4]             ;Get the address of original
262                 LDR     R3,[R1,#8]              ;Get his reference number
263                 MOV     R4,#7                   ;This is a RamTransmit
264                 LDR     R5,[R1,#20]             ;Get his buffer address
265                 STMIA   R11,{R0-R6}             ;Save all the information
266                 LDR     R7,[R1,#24]             ;Get the amount he expected
267                 CMP     R6,R7                   ;Have we filled his buffer?
268                 MOVLT   R0,#17                  ;No -- send as normal message
269                 MOVEQ   R0,#18                  ;Otherwise get bounces nicely
270                 LDR     R2,[R1,#4]              ;Get his task handle ready
271                 MOV     R1,R11                  ;Point to the scratch message
272                 SWI     Wimp_SendMessage        ;Send the message over
273
274                 ; --- Now tidy everthing up and leave ---
275
276                 CMP     R6,R7                   ;Did we fill his buffer?
277                 BEQ     %35save__unknown        ;Yes -- skip this next bit
278                 CMP     R0,#0                   ;Clear overflow flag
279                 BL      save__finish            ;Tidy everything up nicely
280
281 35save__unknown LDMFD   R13!,{R0-R7,R10,R12,R14} ;Load massive chunk of regs
282                 ORRS    PC,R14,#C_flag          ;I handled the event
283
284                 ; --- Handle a DataLoadAck message ---
285
286 40save__unknown CMP     R14,#0                  ;Clear the overflow flag
287                 LDMFD   R13!,{R14}              ;Load the return address
288                 ORR     R14,R14,#C_flag         ;Set C on eventual exit
289                 B       save__finish            ;Tidy everything up and leave
290
291                 ; --- Handle message bounces ---
292
293 60save__unknown STMFD   R13!,{R14}              ;Save a single register
294                 LDR     R14,[R1,#16]            ;Load the message code
295                 CMP     R14,#3                  ;Is it a bounced DataLoad?
296                 BEQ     %70save__unknown        ;Yes -- handle that properly
297                 CMP     R14,#7                  ;Is it a bounced RamTransit?
298                 CMPNE   R14,#1                  ;Or a bounced DataSave?
299                 LDMNEFD R13!,{PC}^              ;No -- return to caller then
300
301                 ; --- Receiver failed to reply to RamTransmit or DataSave ---
302                 ;
303                 ; There's probably a good reason for this, such as it ran
304                 ; out of memory, so we'd better just ignore it and tidy up.
305
306                 STMFD   R13!,{R0}               ;Save another register
307                 MOV     R14,#V_flag             ;Get the V flag's bit
308                 TEQVCP  R14,PC                  ;If V not set, toggle it!
309                 MOV     R0,#0                   ;Don't pass an error block
310                 BL      save__finish            ;Bring it all to a stop
311                 LDMFD   R13!,{R0,PC}^           ;Return to caller
312
313                 ; --- Failed to reply to a DataLoad ---
314                 ;
315                 ; There could be a loose temporary file lying around, so
316                 ; we'd better nobble it quickly.  It also seems to be
317                 ; traditional to moan if the DataLoadAck is not received.
318
319 70save__unknown STMFD   R13!,{R0-R2}            ;Save a few registers
320                 ADR     R0,save__delScrap       ;Point to the command skel
321                 ADD     R2,R1,#44               ;Point to the filename
322                 MOV     R1,R11                  ;Build it up in the scratch
323                 BL      str_subst               ;Build the command string
324                 SWI     XOS_CLI                 ;Perform the command and hope
325                 ADR     R0,save__dtDead         ;Point to an error message
326                 BL      msgs_error              ;Translate it cunningly
327                 MOV     R14,#V_flag             ;Get the V flag's bit
328                 TEQVCP  R14,PC                  ;If V not set, toggle it!
329                 BL      save__finish            ;Wrap everything up then
330                 LDMFD   R13!,{R0-R2,PC}^        ;Return to caller
331
332 save__delScrap  DCB     "%%Wipe %0 ~c~vfr",0
333 save__dtDead    DCD     1
334                 DCB     "saveDTDEAD",0
335
336                 LTORG
337
338 ; --- save__finish ---
339 ;
340 ; On entry:     R0 == pointer to error, or 0 if V set
341 ;
342 ; On exit:      --
343 ;
344 ; Use:          Finishes off a data transfer job nicely
345
346 save__finish    ROUT
347
348                 STMFD   R13!,{R0-R4,R10,R12,R14} ;Save some registers
349
350                 ; --- We need to remove the unknown handler first ---
351
352                 MOV     R10,PC                  ;Look after entry flags
353                 ADR     R0,save__unknown        ;Point to my handler
354                 MOV     R1,#0                   ;Nothing interesting in R4
355                 MOV     R2,#0                   ;Nothing interesting in R10
356                 MOV     R3,R12                  ;Pass my workspace pointer
357                 BL      win_removeUnknownHandler ;Kill off the handler
358                 TEQP    R10,#0                  ;Restore the saved flags
359                 MOVVS   R4,#4                   ;If so, offset handlers by 4
360                 MOVVC   R4,#0                   ;Otherwise, don't do it
361
362                 LDRVS   R0,[R13,#0]             ;Yes -- load error pointer
363                 MOVVS   R1,#1                   ;And pass 1 as button count
364                 LDRVC   R1,save__state          ;Load the state value
365                 ANDVC   R1,R1,#1                ;Leave the safeness flag
366                 LDRVC   R0,[R13,#4]             ;Load the message address
367                 ADDVC   R0,R0,#44               ;Point to the filename
368
369                 ; --- Now call the user routine ---
370
371                 ADR     R14,save__handler       ;Point to the handlers
372                 LDMIA   R14,{R2,R10,R12,R14}    ;Load all the stuff out
373
374                 MOVS    R3,R14                  ;Keep the extra handler
375                 ADD     R2,R2,R4                ;Offset the handler properly
376                 ADDNE   R3,R3,R4                ;And offset extra one too
377
378 10save__finish  MOV     R14,PC                  ;Set up return address
379                 ADD     PC,R2,#sEntry__success  ;Call the handler as required
380                 MOVS    R2,R3                   ;Copy the real handler over
381                 MOVNE   R3,#0                   ;If it was nonzero, zero it
382                 BNE     %10save__finish         ;And go round again for it
383
384                 LDMFD   R13!,{R0-R4,R10,R12,PC}^ ;Return to caller
385
386                 LTORG
387
388 save__wSpace    DCD     0
389
390 ;----- The save handler -----------------------------------------------------
391
392                 ^       0
393 sEntry__save    #       4                       ;Write to a file
394                                                 ;Entry:
395                                                 ;  R0 == pointer to file name
396                                                 ;  R1 == 0 if file unsafe,
397                                                 ;        non-0 if safe
398                                                 ;Exit:
399                                                 ;  --
400
401 sEntry__send    #       4                       ;Send a block of data
402                                                 ;Entry:
403                                                 ;  R2 == 0 for first call,
404                                                 ;        or R2 from previous
405                                                 ;Exit:
406                                                 ;  R0 == pointer to block
407                                                 ;  R1 == size of block
408                                                 ;  R2 == value to pass to
409                                                 ;        next call
410                                                 ;  CS if this is the last one
411
412 sEntry__success #       4                       ;Data transfer has finished
413                                                 ;Entry:
414                                                 ;  R0 == pointer to filename
415                                                 ;  R1 == safeness flag
416                                                 ;Exit:
417                                                 ;  --
418
419 sEntry__failed  #       4                       ;Data transfer failed
420                                                 ;Entry:
421                                                 ;  R0 == 0 or ptr to error
422                                                 ;  R1 == 1
423                                                 ;Exit:
424                                                 ;  --
425
426 ;----- Workspace ------------------------------------------------------------
427
428                 ^       0,R12
429 save__wStart    #       0
430
431                 ; --- Miscellaneous variables ---
432
433 save__state     #       4                       ;My current saving state
434
435                 ; --- The handler ---
436
437 save__handler   #       4                       ;Pointer to handler code
438 save__R10       #       4                       ;The R10 to pass to it
439 save__R12       #       4                       ;The R12 to pass to it
440 save__extra     #       4                       ;Special extra handler
441
442                 ; --- Variables for dealing with RAM transfer ---
443
444 save__srcBuff   #       4                       ;The source buffer to read
445 save__srcSize   #       4                       ;The source buffer size
446 save__acc       #       4                       ;The sender's counter thing
447
448 save__wSize     EQU     {VAR}-save__wStart
449
450                 ; --- Various state indicators ---
451                 ;
452                 ; These have been carefully arranged so that the safeness
453                 ; flag is the bottom bit of the state.  The state is changed
454                 ; from the default sState__safe when we detect that the file
455                 ; is not safe.
456
457 sState__unsafe  EQU     0                       ;File is unsafe as it is
458 sState__safe    EQU     1                       ;File is safe
459 sState__xferred EQU     2                       ;We've finished all that now
460
461                 AREA    |Sapphire$$LibData|,CODE,READONLY
462
463                 DCD     save__wSize
464                 DCD     save__wSpace
465                 DCD     256
466                 DCD     0
467
468 ;----- That's all, folks ----------------------------------------------------
469
470                 END