chiark / gitweb /
Initial revision
[ssr] / StraySrc / Libraries / Sapphire / xfer / s / load
1 ;
2 ; xfer.load.s
3 ;
4 ; Loading and importing of files (MDW)
5 ;
6 ; © 1994 Straylight
7 ;
8
9 ;----- Standard header ------------------------------------------------------
10
11                 GET     libs:swis
12                 GET     libs:header
13
14 ;----- External dependencies ------------------------------------------------
15
16                 GET     sapphire:alloc
17                 GET     sapphire:event
18                 GET     sapphire:fastMove
19                 GET     sapphire:flex
20                 GET     sapphire:msgs
21                 GET     sapphire:sapphire
22                 GET     sapphire:string
23                 GET     sapphire:wimp
24                 GET     sapphire:win
25
26 ;----- Main code ------------------------------------------------------------
27
28                 AREA    |Sapphire$$Code|,CODE,READONLY
29
30 ; --- load ---
31 ;
32 ; On entry:     R0 == pointer to entry point block
33 ;               R1 == value of R10 to pass to entry points
34 ;               R2 == value of R12 to pass to entry points
35 ;
36 ; On exit:      --
37 ;
38 ; Use:          Attempts to load a file after receipt of a Message_DataSave,
39 ;               Message_DataLoad or Message_DataOpen.  If user entries for
40 ;               RAM transfer are provided, this is attempted, although the
41 ;               entries must also be aware that file transfer may be
42 ;               required.
43
44                 EXPORT  load
45 load            ROUT
46
47                 STMFD   R13!,{R0-R6,R10,R12,R14} ;Save a load of registers
48                 WSPACE  load__wSpace            ;Locate my workspace address
49
50                 ; --- Save the handler information ---
51
52                 ADR     R14,load__entries       ;Point to my entry info
53                 STMIA   R14,{R0-R2}             ;And save the handler info
54
55                 ; --- Read the current message ---
56
57                 BL      event_last              ;Read the actual last event
58                 CMP     R0,#17                  ;Is it a normal message?
59                 CMPNE   R0,#18                  ;Or a bouncy one?
60                 BNE     %90load                 ;Neither -- ignore it then
61
62                 LDR     R0,[R1,#16]             ;Load the message action
63                 CMP     R0,#1                   ;Is it a Message_DataSave?
64                 BEQ     %20load                 ;Yes -- handle it then
65                 CMP     R0,#3                   ;Is it a Message_DataLoad?
66                 BEQ     %50load                 ;Yes -- deal with that
67                 CMP     R0,#5                   ;Is it a Message_DataOpen?
68                 BEQ     %60load                 ;Yes -- deal with that too
69                 B       %90load                 ;Otherwise ignore it
70
71                 ; --- Deal with a Message_DataSave ---
72                 ;
73                 ; First, set up all the data in my workspace.
74
75 20load          MOV     R6,R1                   ;Keep the message pointer
76                 ADR     R0,load__message        ;Point to my message buffer
77                 LDR     R2,[R6,#0]              ;Get the message block size
78                 BL      fastMove                ;Copy it over nicely
79
80                 ; --- Find out if he can do RAM transfer ---
81
82                 LDR     R5,load__entries        ;Find his handler block
83                 LDR     R14,[R5,#lEntry__initBuf] ;Point to his initBuf entry
84                 CMP     R14,#0                  ;Is it defined?
85                 BEQ     %40load                 ;No -- just do scrap xfer
86
87                 ; --- Set up for RAM transfer ---
88
89                 ADR     R0,load__name           ;Point to the leafname
90                 LDR     R1,[R6,#36]             ;Load the estimated size
91                 MOV     R2,#0                   ;Pass a zero buffer handle
92                 ADR     R14,load__R10           ;Point to his R10/R12 values
93                 LDMIA   R14,{R10,R12}           ;Load them out ready
94                 ADDS    R0,R0,#0                ;Clear lots of flags
95                 MOV     R14,PC                  ;Set up a return address
96                 ADD     PC,R5,#lEntry__initBuf  ;Make him give me a buffer
97                 WSPACE  load__wSpace            ;Get my workspace back again
98                 STR     R10,load__R10           ;Save his returned R10 value
99                 BLVS    load__finish            ;If it failed, tidy it up
100                 BVS     %90load                 ;And return right now
101                 ADR     R14,load__buffStart     ;Point to the buffer info
102                 STMIA   R14,{R0-R2}             ;And save the buffer stuff
103                 MOV     R14,#0                  ;We've not read any data yet
104                 STR     R14,load__totalSize     ;So zero the total size
105
106                 ; --- Build the Message_RAMFetch ---
107
108                 MOV     R14,#28                 ;Size of a RAMFetch message
109                 STR     R14,[R11,#0]            ;Store it in the scratchpad
110                 ADD     R14,R11,#12             ;Point to your_ref word
111                 MOV     R2,R0                   ;Point to the buffer start
112                 MOV     R3,R1                   ;And get the buffer size
113                 LDR     R0,[R6,#8]              ;Load his reference number
114                 MOV     R1,#6                   ;The RAMFetch message code
115                 STMIA   R14,{R0-R3}             ;Save all that lot away
116                 MOV     R0,#18                  ;Make it bounce if ignored
117                 MOV     R1,R11                  ;Point to my message block
118                 LDR     R2,[R6,#4]              ;Load his task handle
119                 SWI     Wimp_SendMessage        ;And send along his message
120
121                 ; --- Set everything up for the acknowledgement ---
122
123                 MOV     R14,#lState__test       ;We're seeing if he'll cope
124                 STR     R14,load__state         ;So save this state info
125
126                 ADR     R0,load__unknown        ;Point to my unknown handler
127                 MOV     R1,#0                   ;Nothing interesting in R4
128                 MOV     R2,#0                   ;Nothing interesting in R10
129                 MOV     R3,R12                  ;Pass workspace in R12
130                 BL      win_unknownHandler      ;Register my unknown handler
131                 B       %90load                 ;And finish everything off
132
133                 ; --- Set up scrap transfer ---
134
135 40load          BL      load__doScrap           ;Start scrap transfer going
136                 B       %90load                 ;And finish everything off
137
138                 ; --- Handle a Message_DataLoad ---
139                 ;
140                 ; If this is *not* a reply to a Message_DataSaveAck then we
141                 ; should clear all the associated data from out message
142                 ; cache.
143
144 50load          LDR     R14,[R1,#12]            ;Load message's your_ref
145                 CMP     R14,#0                  ;Is this a new message?
146                 BNE     %70load                 ;No -- don't do setting up
147
148                 ; --- Handle a new Message_DataLoad or Message_DataOpen ---
149                 ;
150                 ; First, copy all the message data over
151
152 60load          ADR     R0,load__message        ;Point to my message buffer
153                 LDR     R2,[R1,#0]              ;Get the message block size
154                 BL      fastMove                ;Copy it over nicely
155
156                 ; --- Remember we're doing file transfer ---
157
158                 MOV     R14,#lState__file       ;This is file transfer
159                 STR     R14,load__state         ;Save this state value
160
161                 ; --- Send an immediate acknowledgement ---
162                 ;
163                 ; For a Message_DataOpen, this is very important -- if we
164                 ; don't, and the application dies, we then get started all
165                 ; over again from the command line, and probably die again
166                 ; if it's a duff file.  For a Message_DataLoad it doesn't
167                 ; matter too much, although I suspect we should really send
168                 ; the acknowledgement after we loaded the file.
169
170 70load          MOV     R6,R1                   ;Keep the message pointer
171                 ADD     R0,R11,#20              ;Copy to the scratchpad
172                 ADD     R1,R6,#20               ;Point to the message data
173                 LDR     R2,[R6,#0]              ;Get the message block size
174                 SUB     R2,R2,#20               ;Subtract the bit not copied
175                 BL      fastMove                ;Copy it over nicely
176
177                 LDR     R14,[R6,#0]             ;Load the message size word
178                 STR     R14,[R11,#0]            ;Save it in my dummy message
179                 LDR     R0,[R6,#8]              ;Load his my_ref field
180                 MOV     R1,#4                   ;This is Message_DataLoadAck
181                 ADD     R14,R11,#12             ;Point to the your_ref field
182                 STMIA   R14,{R0,R1}             ;Save them in there
183
184                 MOV     R0,#17                  ;Don't want acknowledgement
185                 MOV     R1,R11                  ;Point to the message block
186                 LDR     R2,[R6,#4]              ;Get his task handle ready
187                 SWI     Wimp_SendMessage        ;And acknowledge his message
188
189                 ; --- Tell the client to load the file ---
190
191                 ADR     R0,load__name           ;Point to apparent filename
192                 ADD     R1,R6,#44               ;Point to filename to load
193                 LDR     R2,load__state          ;Load state (safeness flag)
194                 ADR     R14,load__entries       ;Point to the entry data
195                 LDMIA   R14,{R5,R10,R12}        ;Load the important stuff
196                 ADDS    R0,R0,#0                ;Clear C and V flags
197                 MOV     R14,PC                  ;Set up his return address
198                 ADD     PC,R5,#lEntry__file     ;Tell him to load the file
199                 WSPACE  load__wSpace            ;Find my workspace again
200                 STR     R10,load__R10           ;Save the new R10 value
201                 BL      load__finish            ;Send a completed message
202
203                 ; --- Now delete the Wimp$Scrap file if we need to ---
204
205                 CMP     R2,#0                   ;Is the file `safe'?
206                 BNE     %90load                 ;Yes -- then do nothing
207                 MOV     R0,#27                  ;Wipe files please
208                 ADD     R1,R6,#44               ;Point to the filename
209                 MOV     R3,#&3                  ;No confirm, recurse
210                 SWI     XOS_FSControl           ;Do the Wipe job
211
212                 ; --- We finished at last! ---
213
214 90load          LDMFD   R13!,{R0-R6,R10,R12,PC}^ ;Return to caller
215
216                 LTORG
217
218 ; --- load__doScrap ---
219 ;
220 ; On entry:     --
221 ;
222 ; On exit:      --
223 ;
224 ; Use:          Sets everything up for Wimp$Scrap-type data transfer.
225
226 load__doScrap   ROUT
227
228                 STMFD   R13!,{R0-R4,R14}        ;Save some registers
229
230                 ; --- First, ensure the variable <Wimp$Scrap> exists ---
231
232                 ADR     R0,load__wimpScrap      ;Point to my variable name
233                 MOV     R1,R11                  ;Point to a convenient buffer
234                 MOV     R2,#256                 ;Get the buffer size
235                 MOV     R3,#0                   ;This is the first call
236                 MOV     R4,#0                   ;Don't expand or anything
237                 SWI     XOS_ReadVarVal          ;Read the variable value
238                 BLVS    load__finish            ;If it failed, abort now
239                 BVS     %90load__doScrap        ;And return to caller
240
241                 ; --- Build the message and send it ---
242
243                 ADD     R0,R11,#20              ;Point at scratch msg data
244                 ADR     R1,load__message+20     ;And the saved bits of data
245                 MOV     R2,#24                  ;All up to the filename
246                 BL      fastMove                ;Copy all that lot over
247
248                 MOV     R14,#60                 ;The size of this message
249                 STR     R14,[R11,#0]            ;Store it in the right place
250                 LDR     R0,load__message+8      ;Load the message's my_ref
251                 MOV     R1,#2                   ;This is Message_DataSaveAck
252                 ADD     R14,R11,#12             ;Point to your_ref
253                 STMIA   R14,{R0,R1}             ;Save your_ref and action
254
255                 ADD     R0,R11,#44              ;Point to the filename area
256                 ADR     R1,load__scrapVar       ;Point to the variable name
257                 BL      str_cpy                 ;Copy the string over
258
259                 MOV     R14,#-1                 ;Say that the data's not safe
260                 STR     R14,[R11,#36]           ;Save -1 as estimated size
261                 MOV     R0,#17                  ;This should be send normal
262                 MOV     R1,R11                  ;Point at my message
263                 LDR     R2,load__message+4      ;Load his task handle
264                 SWI     Wimp_SendMessage        ;Send the message back
265
266                 ; --- Now remember we're doing scrap transfer ---
267
268                 MOV     R14,#lState__scrap      ;Get the right state number
269                 STR     R14,load__state         ;And save it away nicely
270
271                 ; --- That's it -- we're done ---
272
273 90load__doScrap LDMFD   R13!,{R0-R4,PC}^        ;Return to caller
274
275 load__wimpScrap DCB     "Wimp$Scrap",0
276 load__scrapVar  DCB     "<Wimp$Scrap>",0
277
278                 LTORG
279
280 ; --- load__unknown ---
281 ;
282 ; On entry:     R0 == an event code
283 ;               R1 == pointer to event data
284 ;
285 ; On exit:      CS if we handled the event, CC otherwise
286 ;
287 ; Use:          Handles unknown events (i.e. user messages) during a RAM
288 ;               transfer.
289
290 load__unknown   ROUT
291
292                 CMP     R0,#17                  ;Is it a user message?
293                 CMPNE   R0,#18                  ;Or a bouncy user message?
294                 BEQ     %00load__unknown        ;Yes -- handle it then
295                 CMP     R0,#19                  ;Is it a bounced message?
296                 BEQ     %60load__unknown        ;Yes -- deal with that
297                 MOVS    PC,R14                  ;Nothing we could do about it
298
299                 ; --- Deal with a message ---
300
301 00load__unknown STMFD   R13!,{R14}              ;Save a register
302                 LDR     R14,[R1,#16]            ;Load the message code
303                 CMP     R14,#7                  ;Is it a Message_RAMTransmit?
304                 LDMNEFD R13!,{PC}^              ;No -- ignore it then
305
306                 ; --- Data transfer is go ---
307
308                 STMFD   R13!,{R0-R6,R10}        ;Save loads of registers
309                 MOV     R6,R1                   ;Look after the message ptr
310                 MOV     R14,#lState__ram        ;We're doing RAM transfer now
311                 STR     R14,load__state         ;So save this state away
312
313                 ; --- Have we finished data transfer yet? ---
314
315                 ADR     R14,load__buffStart     ;Point to the buffer info
316                 LDMIA   R14,{R0-R2}             ;Load all the buffer stuff
317                 LDR     R3,[R6,#24]             ;How much has he sent?
318                 LDR     R4,load__totalSize      ;Load the total so far
319                 ADD     R4,R4,R3                ;Add on this new size
320                 STR     R4,load__totalSize      ;And save back the new total
321                 CMP     R1,R3                   ;Has he sent enough data?
322                 BNE     %30load__unknown        ;No -- then it's all over
323
324                 ; --- Get some more buffer space ---
325
326                 ADR     R14,load__entries       ;Point at his entry info
327                 LDMIA   R14,{R5,R10,R12}        ;Load all his info out
328                 ADDS    R0,R0,#0                ;Clear C and V flags
329                 MOV     R14,PC                  ;Set up the return address
330                 ADD     PC,R5,#lEntry__extend   ;Extend your buffer please
331                 WSPACE  load__wSpace            ;Find my workspace again
332                 BVS     %40load__unknown        ;If it failed, kill buffer
333                 ADR     R14,load__buffStart     ;Point to the buffer info
334                 STMIA   R14,{R0-R2}             ;Save the buffer info again
335
336                 ; --- Send another RAMFetch along ---
337
338                 MOV     R14,#28                 ;Size of a RAMFetch message
339                 STR     R14,[R11,#0]            ;Store it in the scratchpad
340                 ADD     R14,R11,#12             ;Point to your_ref word
341                 MOV     R2,R0                   ;Point to the buffer start
342                 MOV     R3,R1                   ;And get the buffer size
343                 LDR     R0,[R6,#8]              ;Load his reference number
344                 MOV     R1,#6                   ;The RAMFetch message code
345                 STMIA   R14,{R0-R3}             ;Save all that lot away
346                 MOV     R0,#18                  ;Make it bounce if ignored
347                 MOV     R1,R11                  ;Point to my message block
348                 LDR     R2,[R6,#4]              ;Load his task handle
349                 SWI     Wimp_SendMessage        ;And send along his message
350                 B       %50load__unknown        ;Finish off everything
351
352                 ; --- Tell the client to wrap things up ---
353
354 30load__unknown ADR     R0,load__name           ;Point to the `filename'
355                 MOV     R1,R4                   ;Get the total data size
356                 ADR     R14,load__entries       ;Point at his entry info
357                 LDMIA   R14,{R5,R10,R12}        ;Load all his info out
358                 ADDS    R0,R0,#0                ;Clear C and V flags
359                 MOV     R14,PC                  ;Set up the return address
360                 ADD     PC,R5,#lEntry__doneBuf  ;Tidy up your buffer please
361                 WSPACE  load__wSpace            ;Find my workspace again
362                 BVS     %40load__unknown        ;If it failed, tidy up
363                 BL      load__finish            ;It's all over now
364
365                 ; --- Unattach this unknown handler ---
366
367                 ADR     R0,load__unknown        ;Point to my unknown handler
368                 MOV     R1,#0                   ;Nothing interesting in R4
369                 MOV     R2,#0                   ;Nothing interesting in R10
370                 MOV     R3,R12                  ;Pass workspace in R12
371                 BL      win_removeUnknownHandler ;Unattach the handler
372                 B       %50load__unknown        ;And return nicely
373
374                 ; --- Tidy up after buffer extension failed ---
375
376 40load__unknown MOV     R4,R0                   ;Look after the error pointer
377                 ADR     R14,load__buffStart     ;Point to the buffer info
378                 LDMIA   R14,{R0-R2}             ;Load it all out
379                 LDR     R12,load__R12           ;Find the client's R12
380                 MOV     R14,PC                  ;Set up a return address
381                 ADD     PC,R5,#lEntry__killBuf  ;Destroy the buffer
382                 WSPACE  load__wSpace            ;Find my workspace again
383                 MOV     R14,#V_flag             ;Get the V bit position
384                 TEQVCP  R14,PC                  ;If clear, set it again
385                 MOV     R0,R4                   ;Point at the error again
386                 BL      load__finish            ;Report the error
387
388                 ; --- We don't need the unknown handler any more ---
389
390                 ADR     R0,load__unknown        ;Point to my unknown handler
391                 MOV     R1,#0                   ;Nothing interesting in R4
392                 MOV     R2,#0                   ;Nothing interesting in R10
393                 MOV     R3,R12                  ;Pass workspace in R12
394                 BL      win_removeUnknownHandler ;Unattach the handler
395
396                 ; --- Return to caller ---
397
398 50load__unknown LDMFD   R13!,{R0-R6,R10,R14}    ;Unstack all the registers
399                 ORRS    PC,R14,#C_flag          ;And claim the event
400
401                 ; --- Handle a bounced message ---
402
403 60load__unknown STMFD   R13!,{R14}              ;Save a register
404                 LDR     R14,[R1,#16]            ;Load the message action
405                 CMP     R14,#6                  ;Is it one of my RAMFetches?
406                 LDMNEFD R13!,{PC}^              ;No -- ignore it then
407
408                 ; --- My RAMFetch bounced! ---
409
410                 LDR     R14,load__state         ;Get my current state?
411                 CMP     R14,#lState__test       ;Was I just testing the water
412                 BLEQ    load__doScrap           ;Yes -- set up for scrap xfer
413
414                 ; --- Shut down the data transfer ---
415
416                 STMFD   R13!,{R0-R3,R10}        ;Save some more registers
417                 ADR     R14,load__buffStart     ;Point to the buffer info
418                 LDMIA   R14,{R0-R2}             ;Load it all out
419                 ADR     R14,load__entries       ;Point to entry information
420                 LDMIA   R14,{R3,R10,R12}        ;Load all the stuff out
421                 MOV     R14,PC                  ;Set up a return address
422                 ADD     PC,R3,#lEntry__killBuf  ;Destroy the buffer
423                 WSPACE  load__wSpace            ;Find my workspace again
424                 MOV     R14,#V_flag             ;Get the V bit position
425                 TEQVCP  R14,PC                  ;If clear, set it again
426                 MOV     R0,#0                   ;Don't report any errors
427                 BL      load__finish            ;Report the error
428
429                 ; --- We don't need the unknown handler any more ---
430
431                 ADR     R0,load__unknown        ;Point to my unknown handler
432                 MOV     R1,#0                   ;Nothing interesting in R4
433                 MOV     R2,#0                   ;Nothing interesting in R10
434                 MOV     R3,R12                  ;Pass workspace in R12
435                 BL      win_removeUnknownHandler ;Unattach the handler
436
437                 LDMFD   R13!,{R0-R3,R10,R14}    ;Unstack all the registers
438                 ORRS    PC,R14,#C_flag          ;And return with C set
439
440                 LTORG
441
442 ; --- load__finish ---
443 ;
444 ; On entry:     VS and R0 points to error, or VC
445 ;
446 ; On exit:      R10 corrupted
447 ;
448 ; Use:          Calls the appropriate client routine for finishing off
449 ;               a load operation.
450
451 load__finish    ROUT
452
453                 STMFD   R13!,{R0-R2,R12,R14}    ;Save some registers
454                 MOVVS   R1,#1                   ;If error, set button count
455                 ADRVC   R0,load__name           ;Point to apparent name
456                 LDRVC   R1,load__state          ;And load my state
457                 AND     R1,R1,#1                ;Leave only safeness flag
458                 ADR     R14,load__entries       ;Point to the entry points
459                 LDMIA   R14,{R2,R10,R12}        ;Load the entry info
460                 ADDVS   R2,R2,#4                ;If error, call fail entry
461                 MOV     R14,PC                  ;Set up the return address
462                 ADD     PC,R2,#lEntry__done     ;Call the correct entry pt
463                 LDMFD   R13!,{R0-R2,R12,PC}^    ;Return to caller
464
465                 LTORG
466
467 ; --- load_initBuf ---
468 ;
469 ; On entry:     R1 == estimated file size
470 ;               R2 == pointer to flex anchor (unallocated)
471 ;
472 ; On exit:      R0 == pointer to buffer start
473 ;               R1 == buffer size
474 ;               May return an error
475 ;
476 ; Use:          Initialises a flex block for use as a RAM transfer buffer.
477 ;               This routine is suitable for use as the initBuf routine for
478 ;               RAM transfer loading.
479
480                 EXPORT  load_initBuf
481 load_initBuf    ROUT
482
483                 STMFD   R13!,{R14}              ;Save some registers
484                 MOV     R0,R2                   ;Point to caller's anchor
485                 BL      flex_alloc              ;Try to allocate the buffer
486                 MOVCS   R1,#4096                ;Otherwise assume 4K size
487                 BLCS    flex_alloc              ;And try again...
488                 BLCS    alloc_error             ;If it failed, get an error
489                 LDRCC   R0,[R0,#0]              ;Otherwise load buffer start
490                 LDMFD   R13!,{R14}              ;Restore the link register
491                 BICCCS  PC,R14,#V_flag          ;If no error, clear V on exit
492                 ORRCSS  PC,R14,#V_flag          ;Otherwise set it
493
494                 LTORG
495
496 ; --- load_killBuf ---
497 ;
498 ; On entry:     R2 == pointer to flex anchor
499 ;
500 ; On exit:      --
501 ;
502 ; Use:          Frees a flex block.  This routine should be used to free
503 ;               the buffer used for RAM transfer.
504
505                 EXPORT  load_killBuf
506 load_killBuf    ROUT
507
508                 STMFD   R13!,{R0,R14}           ;Save some registers
509                 MOV     R0,R2                   ;Point to the flex anchor
510                 BL      flex_free               ;Free the block
511                 MOV     R14,#0                  ;Get a zero word
512                 STR     R14,[R2,#0]             ;Write this over the anchor
513                 LDMFD   R13!,{R0,PC}^           ;Return to caller
514
515                 LTORG
516
517 ; --- load_extendBuf ---
518 ;
519 ; On entry:     R0 == pointer to previous buffer
520 ;               R1 == size of previous buffer
521 ;               R2 == pointer to flex anchor
522 ;
523 ; On exit:      R0 == pointer to a new buffer
524 ;               R1 == size of the new buffer
525 ;               May return an error
526 ;
527 ; Use:          Extends the flex block if it was initially too small.
528 ;               This routine is designed to be used as the extend routine
529 ;               during RAM transfer.
530
531                 EXPORT  load_extendBuf
532 load_extendBuf  ROUT
533
534                 STMFD   R13!,{R3,R14}           ;Save some registers
535                 MOV     R0,R2                   ;Point to the flex anchor
536                 BL      flex_size               ;Read the block's size
537                 MOV     R3,R0                   ;Look after the size
538                 MOV     R0,R2                   ;Point to the flex anchor
539                 ADD     R1,R3,#&1000            ;Extend buffer by 4K
540                 BL      flex_extend             ;Make more space for loading
541                 BLCS    alloc_error             ;If it failed, get an error
542                 LDRCC   R0,[R2,#0]              ;Otherwise load the anchor
543                 ADDCC   R0,R0,R3                ;And add the old size
544                 MOVCC   R1,#&1000               ;Get the buffer size
545                 LDMFD   R13!,{R3,R14}           ;Restore the registers
546                 BICCCS  PC,R14,#V_flag          ;If no error, clear V on exit
547                 ORRCSS  PC,R14,#V_flag          ;Otherwise set it
548
549                 LTORG
550
551 ; --- load_doneBuf ---
552 ;
553 ; On entry:     R1 == actual size of data
554 ;               R2 == pointer to flex anchor
555 ;
556 ; On exit:      --
557 ;
558 ; Use:          Sets the block into which the data has been loaded to the
559 ;               correct exact size.
560
561                 EXPORT  load_doneBuf
562 load_doneBuf    ROUT
563
564                 STMFD   R13!,{R0,R14}           ;Save some registers
565                 MOV     R0,R2                   ;Point to the anchor
566                 BL      flex_extend             ;Set the block's correct size
567                 LDMFD   R13!,{R0,PC}^           ;Return to caller
568
569                 LTORG
570
571 ; --- load_file ---
572 ;
573 ; On entry:     R1 == pointer to filename to load
574 ;               R2 == pointer to flex anchor
575 ;
576 ; On exit:      R0 == size of file loaded
577 ;               May return an error
578 ;
579 ; Use:          Loads a named file into a flex block for your delectation.
580
581                 EXPORT  load_file
582 load_file       ROUT
583
584                 STMFD   R13!,{R0-R6,R14}        ;Save some registers
585                 MOV     R6,R2                   ;Keep the flex anchor safe
586
587                 ; --- Find the file information ---
588
589                 MOV     R0,#17                  ;Read file information
590                 SWI     XOS_File                ;Find the file's size
591                 BVS     %90load_file            ;If it failed, handle error
592                 TST     R0,#1                   ;Is the object a file?
593                 BEQ     %80load_file            ;No -- get an error for it
594                 STR     R4,[R13,#0]             ;Save the file size in R0
595
596                 ; --- Allocate the flex block ---
597
598                 MOV     R1,R4                   ;Get the object size in R1
599                 MOV     R0,R6                   ;Point to caller's anchor
600                 BL      flex_alloc              ;Try to allocate the block
601                 BLCS    alloc_error             ;No memory -- get the message
602                 BCS     %90load_file            ;If it failed, handle error
603
604                 ; --- Load file into the flex block ---
605
606                 MOV     R0,#16                  ;Load the file
607                 LDR     R1,[R13,#4]             ;Load the filename address
608                 LDR     R2,[R6,#0]              ;Load the flex anchor
609                 MOV     R3,#0                   ;Load into my buffer please
610                 SWI     XOS_File                ;Try to do the load op
611                 BVS     %85load_file            ;If it failed, tidy up
612                 LDMFD   R13!,{R0-R6,R14}        ;Unstack registers
613                 BICS    PC,R14,#V_flag          ;And return with no error
614
615                 ; --- We found a bad object type ---
616
617 80load_file     MOV     R2,R0                   ;Get object type in R2
618                 MOV     R0,#19                  ;Get the error message
619                 SWI     XOS_File                ;Return pointer in R0
620                 B       %90load_file            ;Handle error in usual way
621
622                 ; --- Tidy up after various errors ---
623
624 85load_file     MOV     R1,R0                   ;Look after the error pointer
625                 MOV     R0,R6                   ;Point to the flex anchor
626                 BL      flex_free               ;Free up all tht memory
627                 MOV     R14,#0                  ;Get a zero word
628                 STR     R14,[R6,#0]             ;And zero out the anchor
629                 MOV     R0,R1                   ;Restore the error pointer
630
631 90load_file     ADD     R13,R13,#4              ;Don't restore R0 on exit
632                 LDMFD   R13!,{R1-R6,R14}        ;Unstack registers
633                 ORRS    PC,R14,#V_flag          ;And return with the error
634
635                 LTORG
636
637 load__wSpace    DCD     0
638
639 ;----- User entry points ----------------------------------------------------
640
641                 ^       0
642
643 lEntry__initBuf #       4                       ;Create a load buffer
644                                                 ;On entry:
645                                                 ;  R0 == ptr to `filename'
646                                                 ;  R1 == estimated file size
647                                                 ;  R2 == 0
648                                                 ;On exit:
649                                                 ;  R0 == ptr to buffer start
650                                                 ;  R1 == ptr to buffer end
651                                                 ;  R2 == buffer `handle'
652                                                 ;  R10 may be updated
653
654 lEntry__killBuf #       4                       ;Destroy the load buffer
655                                                 ;On entry:
656                                                 ;  R0 == ptr to buffer start
657                                                 ;  R1 == ptr to buffer end
658                                                 ;  R2 == buffer `handle'
659                                                 ;On exit:
660                                                 ;  --
661
662 lEntry__extend  #       4                       ;Extend the load buffer
663                                                 ;On entry:
664                                                 ;  R0 == ptr to buffer start
665                                                 ;  R1 == ptr to buffer end
666                                                 ;  R2 == buffer `handle'
667                                                 ;On exit:
668                                                 ;  R0-R2 updated
669
670 lEntry__doneBuf #       4                       ;All data is now loaded
671                                                 ;On entry:
672                                                 ;  R0 == ptr to `filename'
673                                                 ;  R1 == total size of data
674                                                 ;  R2 == buffer `handle'
675                                                 ;On exit:
676                                                 ;  --
677
678 lEntry__file    #       4                       ;Load data from a file
679                                                 ;On entry:
680                                                 ;  R0 == ptr to `filename'
681                                                 ;  R1 == file to load
682                                                 ;  R2 == 0 if file unsafe
683                                                 ;On exit:
684                                                 ;  R10 may be updated
685
686 lEntry__done    #       4                       ;Completed loading
687                                                 ;On entry:
688                                                 ;  R0 == ptr to `filename'
689                                                 ;  R1 == safeness indicator
690                                                 ;On exit:
691                                                 ;  --
692
693 lEntry__failed  #       4                       ;Failed to load file
694                                                 ;On entry:
695                                                 ;  R0 == pointer to error
696                                                 ;  R1 == 1
697                                                 ;On exit:
698                                                 ;  --
699
700 ; --- Explanation ---
701 ;
702 ; Loading is several orders of magnitude harder than saving, at a guess.
703 ; I've tried to make it fairly straightforward here -- there are a few
704 ; standard routines provided for simple things like loading into a flex
705 ; block, and a coroutine-based system for unified RAM/file transfer is
706 ; available.
707 ;
708 ; Like saving, loading is based around a table of branch instructions which
709 ; perform application-specific actions during the load operation.  All the
710 ; message passing protocol is hidden away, and all you have to do is write
711 ; the entries for the table.
712 ;
713 ; If you want to support RAM-transfer, you must provide three buffer
714 ; handling routines:
715 ;
716 ; * initBuf is called when load is attempting to start a RAM transfer with
717 ;   the saving application.  It should create a buffer of appropriate size
718 ;   (possibly based on the estimated file size already given).  You can
719 ;   declare a buffer handle at this point, which is passed to all other
720 ;   routines that need to deal with the buffer.  It may return an error.
721 ;
722 ;   If you can't handle RAM transfer, you should replace the branch
723 ;   instruction here with a null word.
724 ;
725 ; * extend is called if the previous buffer was filled and there is more
726 ;   data to come.  The address of the previous buffer is returned to you,
727 ;   so either you can process it there and then, or extend the buffer in
728 ;   some way.  You just have to return a new area of memory to fill with
729 ;   data.  It may return an error.
730 ;
731 ; * doneBuf is called when all the data has been loaded, so that the buffer
732 ;   can be set to the exact right size.
733 ;
734 ; * killBuf is called if the attempt to load via RAM transfer failed and
735 ;   the buffer has to be destroyed.  It is always called whenever there is
736 ;   a fault during RAM transfer, even if one of your other entry points
737 ;   raised the error.
738 ;
739 ; * file is called if you have to load a file from the filing system, either
740 ;   because RAM transfer failed or because you received a direct load from
741 ;   the Filer.  It may return an error.
742 ;
743 ; * done is called when the data transfer is successfully completed.
744 ;
745 ; * failed is called when the data transfer fails due to an error.
746
747 ;----- Workspace ------------------------------------------------------------
748
749                 ^       0,R12
750 load__wStart    #       0
751
752 load__state     #       4                       ;The current state (1 byte)
753
754 load__entries   #       4                       ;Pointer to entry pt block
755 load__R10       #       4                       ;Client's R10 value
756 load__R12       #       4                       ;Client's R12 value
757
758 load__buffStart #       4                       ;The buffer's start address
759 load__buffSize  #       4                       ;And its size
760 load__buffHnd   #       4                       ;Client's buffer handle
761
762 load__totalSize #       4                       ;How much data we've received
763
764 load__message   #       44                      ;The original load/save msg
765 load__name      #       212                     ;The file's apparent name
766
767 load__wSize     EQU     {VAR}-load__wStart
768
769                 ; --- States ---
770                 ;
771                 ; These have been carefully arranged so that we can return
772                 ; the safeness flag to various routines.  If we only
773                 ; consider files, then the state /is/ the safeness flag.
774                 ; Otherwise we only use the bottom bit of the state.
775
776 lState__scrap   EQU     0                       ;We're doing scrap transfer
777 lState__file    EQU     1                       ;We're loading from a file
778 lState__test    EQU     2                       ;We're testing RAM transfer
779 lState__ram     EQU     4                       ;We're doing RAM transfer
780
781                 AREA    |Sapphire$$LibData|,CODE,READONLY
782
783                 DCD     load__wSize
784                 DCD     load__wSpace
785                 DCD     256
786                 DCD     0
787
788 ;----- That's all, folks ----------------------------------------------------
789
790                 END