; ; xfer.load.s ; ; Loading and importing of files (MDW) ; ; © 1994 Straylight ; ;----- Standard header ------------------------------------------------------ GET libs:swis GET libs:header ;----- External dependencies ------------------------------------------------ GET sapphire:alloc GET sapphire:event GET sapphire:fastMove GET sapphire:flex GET sapphire:msgs GET sapphire:sapphire GET sapphire:string GET sapphire:wimp GET sapphire:win ;----- Main code ------------------------------------------------------------ AREA |Sapphire$$Code|,CODE,READONLY ; --- load --- ; ; On entry: R0 == pointer to entry point block ; R1 == value of R10 to pass to entry points ; R2 == value of R12 to pass to entry points ; ; On exit: -- ; ; Use: Attempts to load a file after receipt of a Message_DataSave, ; Message_DataLoad or Message_DataOpen. If user entries for ; RAM transfer are provided, this is attempted, although the ; entries must also be aware that file transfer may be ; required. EXPORT load load ROUT STMFD R13!,{R0-R6,R10,R12,R14} ;Save a load of registers WSPACE load__wSpace ;Locate my workspace address ; --- Save the handler information --- ADR R14,load__entries ;Point to my entry info STMIA R14,{R0-R2} ;And save the handler info ; --- Read the current message --- BL event_last ;Read the actual last event CMP R0,#17 ;Is it a normal message? CMPNE R0,#18 ;Or a bouncy one? BNE %90load ;Neither -- ignore it then LDR R0,[R1,#16] ;Load the message action CMP R0,#1 ;Is it a Message_DataSave? BEQ %20load ;Yes -- handle it then CMP R0,#3 ;Is it a Message_DataLoad? BEQ %50load ;Yes -- deal with that CMP R0,#5 ;Is it a Message_DataOpen? BEQ %60load ;Yes -- deal with that too B %90load ;Otherwise ignore it ; --- Deal with a Message_DataSave --- ; ; First, set up all the data in my workspace. 20load MOV R6,R1 ;Keep the message pointer ADR R0,load__message ;Point to my message buffer LDR R2,[R6,#0] ;Get the message block size BL fastMove ;Copy it over nicely ; --- Find out if he can do RAM transfer --- LDR R5,load__entries ;Find his handler block LDR R14,[R5,#lEntry__initBuf] ;Point to his initBuf entry CMP R14,#0 ;Is it defined? BEQ %40load ;No -- just do scrap xfer ; --- Set up for RAM transfer --- ADR R0,load__name ;Point to the leafname LDR R1,[R6,#36] ;Load the estimated size MOV R2,#0 ;Pass a zero buffer handle ADR R14,load__R10 ;Point to his R10/R12 values LDMIA R14,{R10,R12} ;Load them out ready ADDS R0,R0,#0 ;Clear lots of flags MOV R14,PC ;Set up a return address ADD PC,R5,#lEntry__initBuf ;Make him give me a buffer WSPACE load__wSpace ;Get my workspace back again STR R10,load__R10 ;Save his returned R10 value BLVS load__finish ;If it failed, tidy it up BVS %90load ;And return right now ADR R14,load__buffStart ;Point to the buffer info STMIA R14,{R0-R2} ;And save the buffer stuff MOV R14,#0 ;We've not read any data yet STR R14,load__totalSize ;So zero the total size ; --- Build the Message_RAMFetch --- MOV R14,#28 ;Size of a RAMFetch message STR R14,[R11,#0] ;Store it in the scratchpad ADD R14,R11,#12 ;Point to your_ref word MOV R2,R0 ;Point to the buffer start MOV R3,R1 ;And get the buffer size LDR R0,[R6,#8] ;Load his reference number MOV R1,#6 ;The RAMFetch message code STMIA R14,{R0-R3} ;Save all that lot away MOV R0,#18 ;Make it bounce if ignored MOV R1,R11 ;Point to my message block LDR R2,[R6,#4] ;Load his task handle SWI Wimp_SendMessage ;And send along his message ; --- Set everything up for the acknowledgement --- MOV R14,#lState__test ;We're seeing if he'll cope STR R14,load__state ;So save this state info ADR R0,load__unknown ;Point to my unknown handler MOV R1,#0 ;Nothing interesting in R4 MOV R2,#0 ;Nothing interesting in R10 MOV R3,R12 ;Pass workspace in R12 BL win_unknownHandler ;Register my unknown handler B %90load ;And finish everything off ; --- Set up scrap transfer --- 40load BL load__doScrap ;Start scrap transfer going B %90load ;And finish everything off ; --- Handle a Message_DataLoad --- ; ; If this is *not* a reply to a Message_DataSaveAck then we ; should clear all the associated data from out message ; cache. 50load LDR R14,[R1,#12] ;Load message's your_ref CMP R14,#0 ;Is this a new message? BNE %70load ;No -- don't do setting up ; --- Handle a new Message_DataLoad or Message_DataOpen --- ; ; First, copy all the message data over 60load ADR R0,load__message ;Point to my message buffer LDR R2,[R1,#0] ;Get the message block size BL fastMove ;Copy it over nicely ; --- Remember we're doing file transfer --- MOV R14,#lState__file ;This is file transfer STR R14,load__state ;Save this state value ; --- Send an immediate acknowledgement --- ; ; For a Message_DataOpen, this is very important -- if we ; don't, and the application dies, we then get started all ; over again from the command line, and probably die again ; if it's a duff file. For a Message_DataLoad it doesn't ; matter too much, although I suspect we should really send ; the acknowledgement after we loaded the file. 70load MOV R6,R1 ;Keep the message pointer ADD R0,R11,#20 ;Copy to the scratchpad ADD R1,R6,#20 ;Point to the message data LDR R2,[R6,#0] ;Get the message block size SUB R2,R2,#20 ;Subtract the bit not copied BL fastMove ;Copy it over nicely LDR R14,[R6,#0] ;Load the message size word STR R14,[R11,#0] ;Save it in my dummy message LDR R0,[R6,#8] ;Load his my_ref field MOV R1,#4 ;This is Message_DataLoadAck ADD R14,R11,#12 ;Point to the your_ref field STMIA R14,{R0,R1} ;Save them in there MOV R0,#17 ;Don't want acknowledgement MOV R1,R11 ;Point to the message block LDR R2,[R6,#4] ;Get his task handle ready SWI Wimp_SendMessage ;And acknowledge his message ; --- Tell the client to load the file --- ADR R0,load__name ;Point to apparent filename ADD R1,R6,#44 ;Point to filename to load LDR R2,load__state ;Load state (safeness flag) ADR R14,load__entries ;Point to the entry data LDMIA R14,{R5,R10,R12} ;Load the important stuff ADDS R0,R0,#0 ;Clear C and V flags MOV R14,PC ;Set up his return address ADD PC,R5,#lEntry__file ;Tell him to load the file WSPACE load__wSpace ;Find my workspace again STR R10,load__R10 ;Save the new R10 value BL load__finish ;Send a completed message ; --- Now delete the Wimp$Scrap file if we need to --- CMP R2,#0 ;Is the file `safe'? BNE %90load ;Yes -- then do nothing MOV R0,#27 ;Wipe files please ADD R1,R6,#44 ;Point to the filename MOV R3,#&3 ;No confirm, recurse SWI XOS_FSControl ;Do the Wipe job ; --- We finished at last! --- 90load LDMFD R13!,{R0-R6,R10,R12,PC}^ ;Return to caller LTORG ; --- load__doScrap --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Sets everything up for Wimp$Scrap-type data transfer. load__doScrap ROUT STMFD R13!,{R0-R4,R14} ;Save some registers ; --- First, ensure the variable exists --- ADR R0,load__wimpScrap ;Point to my variable name MOV R1,R11 ;Point to a convenient buffer MOV R2,#256 ;Get the buffer size MOV R3,#0 ;This is the first call MOV R4,#0 ;Don't expand or anything SWI XOS_ReadVarVal ;Read the variable value BLVS load__finish ;If it failed, abort now BVS %90load__doScrap ;And return to caller ; --- Build the message and send it --- ADD R0,R11,#20 ;Point at scratch msg data ADR R1,load__message+20 ;And the saved bits of data MOV R2,#24 ;All up to the filename BL fastMove ;Copy all that lot over MOV R14,#60 ;The size of this message STR R14,[R11,#0] ;Store it in the right place LDR R0,load__message+8 ;Load the message's my_ref MOV R1,#2 ;This is Message_DataSaveAck ADD R14,R11,#12 ;Point to your_ref STMIA R14,{R0,R1} ;Save your_ref and action ADD R0,R11,#44 ;Point to the filename area ADR R1,load__scrapVar ;Point to the variable name BL str_cpy ;Copy the string over MOV R14,#-1 ;Say that the data's not safe STR R14,[R11,#36] ;Save -1 as estimated size MOV R0,#17 ;This should be send normal MOV R1,R11 ;Point at my message LDR R2,load__message+4 ;Load his task handle SWI Wimp_SendMessage ;Send the message back ; --- Now remember we're doing scrap transfer --- MOV R14,#lState__scrap ;Get the right state number STR R14,load__state ;And save it away nicely ; --- That's it -- we're done --- 90load__doScrap LDMFD R13!,{R0-R4,PC}^ ;Return to caller load__wimpScrap DCB "Wimp$Scrap",0 load__scrapVar DCB "",0 LTORG ; --- load__unknown --- ; ; On entry: R0 == an event code ; R1 == pointer to event data ; ; On exit: CS if we handled the event, CC otherwise ; ; Use: Handles unknown events (i.e. user messages) during a RAM ; transfer. load__unknown ROUT CMP R0,#17 ;Is it a user message? CMPNE R0,#18 ;Or a bouncy user message? BEQ %00load__unknown ;Yes -- handle it then CMP R0,#19 ;Is it a bounced message? BEQ %60load__unknown ;Yes -- deal with that MOVS PC,R14 ;Nothing we could do about it ; --- Deal with a message --- 00load__unknown STMFD R13!,{R14} ;Save a register LDR R14,[R1,#16] ;Load the message code CMP R14,#7 ;Is it a Message_RAMTransmit? LDMNEFD R13!,{PC}^ ;No -- ignore it then ; --- Data transfer is go --- STMFD R13!,{R0-R6,R10} ;Save loads of registers MOV R6,R1 ;Look after the message ptr MOV R14,#lState__ram ;We're doing RAM transfer now STR R14,load__state ;So save this state away ; --- Have we finished data transfer yet? --- ADR R14,load__buffStart ;Point to the buffer info LDMIA R14,{R0-R2} ;Load all the buffer stuff LDR R3,[R6,#24] ;How much has he sent? LDR R4,load__totalSize ;Load the total so far ADD R4,R4,R3 ;Add on this new size STR R4,load__totalSize ;And save back the new total CMP R1,R3 ;Has he sent enough data? BNE %30load__unknown ;No -- then it's all over ; --- Get some more buffer space --- ADR R14,load__entries ;Point at his entry info LDMIA R14,{R5,R10,R12} ;Load all his info out ADDS R0,R0,#0 ;Clear C and V flags MOV R14,PC ;Set up the return address ADD PC,R5,#lEntry__extend ;Extend your buffer please WSPACE load__wSpace ;Find my workspace again BVS %40load__unknown ;If it failed, kill buffer ADR R14,load__buffStart ;Point to the buffer info STMIA R14,{R0-R2} ;Save the buffer info again ; --- Send another RAMFetch along --- MOV R14,#28 ;Size of a RAMFetch message STR R14,[R11,#0] ;Store it in the scratchpad ADD R14,R11,#12 ;Point to your_ref word MOV R2,R0 ;Point to the buffer start MOV R3,R1 ;And get the buffer size LDR R0,[R6,#8] ;Load his reference number MOV R1,#6 ;The RAMFetch message code STMIA R14,{R0-R3} ;Save all that lot away MOV R0,#18 ;Make it bounce if ignored MOV R1,R11 ;Point to my message block LDR R2,[R6,#4] ;Load his task handle SWI Wimp_SendMessage ;And send along his message B %50load__unknown ;Finish off everything ; --- Tell the client to wrap things up --- 30load__unknown ADR R0,load__name ;Point to the `filename' MOV R1,R4 ;Get the total data size ADR R14,load__entries ;Point at his entry info LDMIA R14,{R5,R10,R12} ;Load all his info out ADDS R0,R0,#0 ;Clear C and V flags MOV R14,PC ;Set up the return address ADD PC,R5,#lEntry__doneBuf ;Tidy up your buffer please WSPACE load__wSpace ;Find my workspace again BVS %40load__unknown ;If it failed, tidy up BL load__finish ;It's all over now ; --- Unattach this unknown handler --- ADR R0,load__unknown ;Point to my unknown handler MOV R1,#0 ;Nothing interesting in R4 MOV R2,#0 ;Nothing interesting in R10 MOV R3,R12 ;Pass workspace in R12 BL win_removeUnknownHandler ;Unattach the handler B %50load__unknown ;And return nicely ; --- Tidy up after buffer extension failed --- 40load__unknown MOV R4,R0 ;Look after the error pointer ADR R14,load__buffStart ;Point to the buffer info LDMIA R14,{R0-R2} ;Load it all out LDR R12,load__R12 ;Find the client's R12 MOV R14,PC ;Set up a return address ADD PC,R5,#lEntry__killBuf ;Destroy the buffer WSPACE load__wSpace ;Find my workspace again MOV R14,#V_flag ;Get the V bit position TEQVCP R14,PC ;If clear, set it again MOV R0,R4 ;Point at the error again BL load__finish ;Report the error ; --- We don't need the unknown handler any more --- ADR R0,load__unknown ;Point to my unknown handler MOV R1,#0 ;Nothing interesting in R4 MOV R2,#0 ;Nothing interesting in R10 MOV R3,R12 ;Pass workspace in R12 BL win_removeUnknownHandler ;Unattach the handler ; --- Return to caller --- 50load__unknown LDMFD R13!,{R0-R6,R10,R14} ;Unstack all the registers ORRS PC,R14,#C_flag ;And claim the event ; --- Handle a bounced message --- 60load__unknown STMFD R13!,{R14} ;Save a register LDR R14,[R1,#16] ;Load the message action CMP R14,#6 ;Is it one of my RAMFetches? LDMNEFD R13!,{PC}^ ;No -- ignore it then ; --- My RAMFetch bounced! --- LDR R14,load__state ;Get my current state? CMP R14,#lState__test ;Was I just testing the water BLEQ load__doScrap ;Yes -- set up for scrap xfer ; --- Shut down the data transfer --- STMFD R13!,{R0-R3,R10} ;Save some more registers ADR R14,load__buffStart ;Point to the buffer info LDMIA R14,{R0-R2} ;Load it all out ADR R14,load__entries ;Point to entry information LDMIA R14,{R3,R10,R12} ;Load all the stuff out MOV R14,PC ;Set up a return address ADD PC,R3,#lEntry__killBuf ;Destroy the buffer WSPACE load__wSpace ;Find my workspace again MOV R14,#V_flag ;Get the V bit position TEQVCP R14,PC ;If clear, set it again MOV R0,#0 ;Don't report any errors BL load__finish ;Report the error ; --- We don't need the unknown handler any more --- ADR R0,load__unknown ;Point to my unknown handler MOV R1,#0 ;Nothing interesting in R4 MOV R2,#0 ;Nothing interesting in R10 MOV R3,R12 ;Pass workspace in R12 BL win_removeUnknownHandler ;Unattach the handler LDMFD R13!,{R0-R3,R10,R14} ;Unstack all the registers ORRS PC,R14,#C_flag ;And return with C set LTORG ; --- load__finish --- ; ; On entry: VS and R0 points to error, or VC ; ; On exit: R10 corrupted ; ; Use: Calls the appropriate client routine for finishing off ; a load operation. load__finish ROUT STMFD R13!,{R0-R2,R12,R14} ;Save some registers MOVVS R1,#1 ;If error, set button count ADRVC R0,load__name ;Point to apparent name LDRVC R1,load__state ;And load my state AND R1,R1,#1 ;Leave only safeness flag ADR R14,load__entries ;Point to the entry points LDMIA R14,{R2,R10,R12} ;Load the entry info ADDVS R2,R2,#4 ;If error, call fail entry MOV R14,PC ;Set up the return address ADD PC,R2,#lEntry__done ;Call the correct entry pt LDMFD R13!,{R0-R2,R12,PC}^ ;Return to caller LTORG ; --- load_initBuf --- ; ; On entry: R1 == estimated file size ; R2 == pointer to flex anchor (unallocated) ; ; On exit: R0 == pointer to buffer start ; R1 == buffer size ; May return an error ; ; Use: Initialises a flex block for use as a RAM transfer buffer. ; This routine is suitable for use as the initBuf routine for ; RAM transfer loading. EXPORT load_initBuf load_initBuf ROUT STMFD R13!,{R14} ;Save some registers MOV R0,R2 ;Point to caller's anchor BL flex_alloc ;Try to allocate the buffer MOVCS R1,#4096 ;Otherwise assume 4K size BLCS flex_alloc ;And try again... BLCS alloc_error ;If it failed, get an error LDRCC R0,[R0,#0] ;Otherwise load buffer start LDMFD R13!,{R14} ;Restore the link register BICCCS PC,R14,#V_flag ;If no error, clear V on exit ORRCSS PC,R14,#V_flag ;Otherwise set it LTORG ; --- load_killBuf --- ; ; On entry: R2 == pointer to flex anchor ; ; On exit: -- ; ; Use: Frees a flex block. This routine should be used to free ; the buffer used for RAM transfer. EXPORT load_killBuf load_killBuf ROUT STMFD R13!,{R0,R14} ;Save some registers MOV R0,R2 ;Point to the flex anchor BL flex_free ;Free the block MOV R14,#0 ;Get a zero word STR R14,[R2,#0] ;Write this over the anchor LDMFD R13!,{R0,PC}^ ;Return to caller LTORG ; --- load_extendBuf --- ; ; On entry: R0 == pointer to previous buffer ; R1 == size of previous buffer ; R2 == pointer to flex anchor ; ; On exit: R0 == pointer to a new buffer ; R1 == size of the new buffer ; May return an error ; ; Use: Extends the flex block if it was initially too small. ; This routine is designed to be used as the extend routine ; during RAM transfer. EXPORT load_extendBuf load_extendBuf ROUT STMFD R13!,{R3,R14} ;Save some registers MOV R0,R2 ;Point to the flex anchor BL flex_size ;Read the block's size MOV R3,R0 ;Look after the size MOV R0,R2 ;Point to the flex anchor ADD R1,R3,#&1000 ;Extend buffer by 4K BL flex_extend ;Make more space for loading BLCS alloc_error ;If it failed, get an error LDRCC R0,[R2,#0] ;Otherwise load the anchor ADDCC R0,R0,R3 ;And add the old size MOVCC R1,#&1000 ;Get the buffer size LDMFD R13!,{R3,R14} ;Restore the registers BICCCS PC,R14,#V_flag ;If no error, clear V on exit ORRCSS PC,R14,#V_flag ;Otherwise set it LTORG ; --- load_doneBuf --- ; ; On entry: R1 == actual size of data ; R2 == pointer to flex anchor ; ; On exit: -- ; ; Use: Sets the block into which the data has been loaded to the ; correct exact size. EXPORT load_doneBuf load_doneBuf ROUT STMFD R13!,{R0,R14} ;Save some registers MOV R0,R2 ;Point to the anchor BL flex_extend ;Set the block's correct size LDMFD R13!,{R0,PC}^ ;Return to caller LTORG ; --- load_file --- ; ; On entry: R1 == pointer to filename to load ; R2 == pointer to flex anchor ; ; On exit: R0 == size of file loaded ; May return an error ; ; Use: Loads a named file into a flex block for your delectation. EXPORT load_file load_file ROUT STMFD R13!,{R0-R6,R14} ;Save some registers MOV R6,R2 ;Keep the flex anchor safe ; --- Find the file information --- MOV R0,#17 ;Read file information SWI XOS_File ;Find the file's size BVS %90load_file ;If it failed, handle error TST R0,#1 ;Is the object a file? BEQ %80load_file ;No -- get an error for it STR R4,[R13,#0] ;Save the file size in R0 ; --- Allocate the flex block --- MOV R1,R4 ;Get the object size in R1 MOV R0,R6 ;Point to caller's anchor BL flex_alloc ;Try to allocate the block BLCS alloc_error ;No memory -- get the message BCS %90load_file ;If it failed, handle error ; --- Load file into the flex block --- MOV R0,#16 ;Load the file LDR R1,[R13,#4] ;Load the filename address LDR R2,[R6,#0] ;Load the flex anchor MOV R3,#0 ;Load into my buffer please SWI XOS_File ;Try to do the load op BVS %85load_file ;If it failed, tidy up LDMFD R13!,{R0-R6,R14} ;Unstack registers BICS PC,R14,#V_flag ;And return with no error ; --- We found a bad object type --- 80load_file MOV R2,R0 ;Get object type in R2 MOV R0,#19 ;Get the error message SWI XOS_File ;Return pointer in R0 B %90load_file ;Handle error in usual way ; --- Tidy up after various errors --- 85load_file MOV R1,R0 ;Look after the error pointer MOV R0,R6 ;Point to the flex anchor BL flex_free ;Free up all tht memory MOV R14,#0 ;Get a zero word STR R14,[R6,#0] ;And zero out the anchor MOV R0,R1 ;Restore the error pointer 90load_file ADD R13,R13,#4 ;Don't restore R0 on exit LDMFD R13!,{R1-R6,R14} ;Unstack registers ORRS PC,R14,#V_flag ;And return with the error LTORG load__wSpace DCD 0 ;----- User entry points ---------------------------------------------------- ^ 0 lEntry__initBuf # 4 ;Create a load buffer ;On entry: ; R0 == ptr to `filename' ; R1 == estimated file size ; R2 == 0 ;On exit: ; R0 == ptr to buffer start ; R1 == ptr to buffer end ; R2 == buffer `handle' ; R10 may be updated lEntry__killBuf # 4 ;Destroy the load buffer ;On entry: ; R0 == ptr to buffer start ; R1 == ptr to buffer end ; R2 == buffer `handle' ;On exit: ; -- lEntry__extend # 4 ;Extend the load buffer ;On entry: ; R0 == ptr to buffer start ; R1 == ptr to buffer end ; R2 == buffer `handle' ;On exit: ; R0-R2 updated lEntry__doneBuf # 4 ;All data is now loaded ;On entry: ; R0 == ptr to `filename' ; R1 == total size of data ; R2 == buffer `handle' ;On exit: ; -- lEntry__file # 4 ;Load data from a file ;On entry: ; R0 == ptr to `filename' ; R1 == file to load ; R2 == 0 if file unsafe ;On exit: ; R10 may be updated lEntry__done # 4 ;Completed loading ;On entry: ; R0 == ptr to `filename' ; R1 == safeness indicator ;On exit: ; -- lEntry__failed # 4 ;Failed to load file ;On entry: ; R0 == pointer to error ; R1 == 1 ;On exit: ; -- ; --- Explanation --- ; ; Loading is several orders of magnitude harder than saving, at a guess. ; I've tried to make it fairly straightforward here -- there are a few ; standard routines provided for simple things like loading into a flex ; block, and a coroutine-based system for unified RAM/file transfer is ; available. ; ; Like saving, loading is based around a table of branch instructions which ; perform application-specific actions during the load operation. All the ; message passing protocol is hidden away, and all you have to do is write ; the entries for the table. ; ; If you want to support RAM-transfer, you must provide three buffer ; handling routines: ; ; * initBuf is called when load is attempting to start a RAM transfer with ; the saving application. It should create a buffer of appropriate size ; (possibly based on the estimated file size already given). You can ; declare a buffer handle at this point, which is passed to all other ; routines that need to deal with the buffer. It may return an error. ; ; If you can't handle RAM transfer, you should replace the branch ; instruction here with a null word. ; ; * extend is called if the previous buffer was filled and there is more ; data to come. The address of the previous buffer is returned to you, ; so either you can process it there and then, or extend the buffer in ; some way. You just have to return a new area of memory to fill with ; data. It may return an error. ; ; * doneBuf is called when all the data has been loaded, so that the buffer ; can be set to the exact right size. ; ; * killBuf is called if the attempt to load via RAM transfer failed and ; the buffer has to be destroyed. It is always called whenever there is ; a fault during RAM transfer, even if one of your other entry points ; raised the error. ; ; * file is called if you have to load a file from the filing system, either ; because RAM transfer failed or because you received a direct load from ; the Filer. It may return an error. ; ; * done is called when the data transfer is successfully completed. ; ; * failed is called when the data transfer fails due to an error. ;----- Workspace ------------------------------------------------------------ ^ 0,R12 load__wStart # 0 load__state # 4 ;The current state (1 byte) load__entries # 4 ;Pointer to entry pt block load__R10 # 4 ;Client's R10 value load__R12 # 4 ;Client's R12 value load__buffStart # 4 ;The buffer's start address load__buffSize # 4 ;And its size load__buffHnd # 4 ;Client's buffer handle load__totalSize # 4 ;How much data we've received load__message # 44 ;The original load/save msg load__name # 212 ;The file's apparent name load__wSize EQU {VAR}-load__wStart ; --- States --- ; ; These have been carefully arranged so that we can return ; the safeness flag to various routines. If we only ; consider files, then the state /is/ the safeness flag. ; Otherwise we only use the bottom bit of the state. lState__scrap EQU 0 ;We're doing scrap transfer lState__file EQU 1 ;We're loading from a file lState__test EQU 2 ;We're testing RAM transfer lState__ram EQU 4 ;We're doing RAM transfer AREA |Sapphire$$LibData|,CODE,READONLY DCD load__wSize DCD load__wSpace DCD 256 DCD 0 ;----- That's all, folks ---------------------------------------------------- END