10 REM > RAMCard/s
   20 REM Byte-wide RAM Card in &FC00-&FC03
   30 :
   40 REM 01-May-2004 v0.10 JGH: Initial version
   50 REM 04-May-2004 v0.12 JGH: Can access disk images
   60 :
   70 ON ERROR REPORT:PRINT ERL:END
   80 :
   90 REM Workspace contents:
  100 REM ws+&000 - File buffer
  110 REM ws+&100 - Pathname
  120 REM ws+&200 - Port values
  130 REM ws+&204 - RAMCard size
  140 REM ws+&208 ->RAM
  150 REM ws+&20C - File PTR, byte 0 holds flags:
  160 REM           b0=buffer read, b1=buffer needs writing
  170 REM ws+&210 - flags
  180 :
  190 Service_6502Base=&80AD0
  200 DIM mcode% &8000:ver$="0.12"
  210 sp=13:link=14:pc=15
  220 FOR p=0 TO 1
  230   P%=0:O%=mcode%
  240   [OPT p*3+4
  250   EQUD 0:\start
  260   EQUD Initialise
  270   EQUD Finalise
  280   EQUD Service
  290   EQUD TitleStr
  300   EQUD HelpStr
  310   EQUD CommandTable
  320   EQUD 0:\ SWI chunk number
  330   EQUD 0:\ SWI chunk handler
  340   EQUD 0:\ SWI decoding table
  350   EQUD 0:\ SWI decoding code
  360   :
  370   .TitleStr
  380   EQUS "BBCRAMCard"
  390   EQUB 0
  400   ALIGN
  410   .HelpStr
  420   EQUS "BBCRAMCard"+CHR$9+ver$+" ("+MID$(TIME$,5,11)+")"
  430   EQUB 0
  440   ALIGN
  450   :
  460   .CommandTable
  470   EQUS "RAMCard":EQUB 0:ALIGN:EQUD RAMCard
  480   EQUD &00010001:EQUD RAMCard_Syntax:EQUD RAMCard_Help
  490   :
  500   EQUS "RAMCardLoad":EQUB 0:ALIGN:EQUD RAMCardLoad
  510   EQUD &00010001:EQUD RAMCardLoad_Syntax:EQUD RAMCardLoad_Help
  520   :
  530   EQUS "RAMCardSave":EQUB 0:ALIGN:EQUD RAMCardSave
  540   EQUD &00010001:EQUD RAMCardSave_Syntax:EQUD RAMCardSave_Help
  550   EQUB 0:ALIGN
  560   :
  570   .RAMCard_Help
  580   EQUS "Specifies a RAMCard image to access":EQUB 13
  590   .RAMCard_Syntax
  600   EQUS "Syntax: RAMCard <afsp>":EQUB 13
  610   EQUB 0:ALIGN
  620   :
  630   .RAMCardLoad_Help
  640   EQUS "Loads data into a RAMCard":EQUB 13
  650   .RAMCardLoad_Syntax
  660   EQUS "Syntax: RAMCardLoad <afsp>":EQUB 13
  670   EQUB 0:ALIGN
  680   :
  690   .RAMCardSave_Help
  700   EQUS "Saves data from a RAMCard":EQUB 13
  710   .RAMCardSave_Syntax
  720   EQUS "Syntax: RAMCardSave <afsp>":EQUB 13
  730   EQUB 0:ALIGN
  740   :
  750   :
  760   .Initialise
  770   stmfd  (sp)!,{link}
  780   ldr    r0,[r12]
  790   orrs   r0,r0,#0
  800   bne    Reinitialise  ; We already have workspace
  810   mov    r3,#512       ; We want 256+256+some bytes
  820   add    r3,r3,#128    ; buffer + filename + port values + ptr + flags, etc
  830   mov    r0,#6
  840   swi    "XOS_Module"
  850   ldmvsfd (sp)!,{pc}    ; Memory claim failed
  860   str    r2,[r12]      ; Store in w/s pointer
  870   add    r2,r2,#256
  880   mov    r0,#13
  890   strb   r0,[r2]       ; Clear filename entry
  900   add    r2,r2,#256
  910   mov    r0,#0
  920   str    r0,[r2],#4    ; &200 - Zero port values
  930   str    r0,[r2],#4    ; &204 - Zero RAMCard size
  940   str    r0,[r2],#4    ; &208 - Zero RAM address
  950   str    r0,[r2],#4    ; &20C - Zero file PTR
  960   str    r0,[r2],#4    ; &210 - Zero flags
  970   :
  980   mov    r3,#8*1024*1024 ; 8Mb ramdisk
  990   mov    r0,#6
 1000   swi    "XOS_Module"  ; If claim successful, then...
 1010   movvc  r3,#8*1024*1024 ; 8Mb ramdisk
 1020   ldrvc  r1,[r12]      ; Get workspace pointer back
 1030   addvc  r1,r1,#512    ; Point to variables
 1040   addvc  r1,r1,#4      ; Point to memory address
 1050   strvc  r3,[r1],#4    ; Store RAMCard size
 1060   strvc  r2,[r1],#4    ; Store address of memory
 1070   :
 1080   .Reinitialise
 1090   cmp    r0,r0         ; Clear flags, etc
 1100   ldmfd  (sp)!,{pc}
 1110   :
 1120   :
 1130   .Finalise
 1140   stmfd  (sp)!,{link}
 1150   ldr    r3,[r12]      ; Get pointer to module's workspace
 1160   orrs   r3,r3,#0
 1170   beq    Finalised     ; No workspace (shouldn't ever get called this way)
 1180   mov    r0,#7
 1190   add    r3,r3,#512    ; Point to variables
 1200   add    r3,r3,#8      ; Point to RAM address
 1210   ldr    r2,[r3]
 1220   orrs   r2,r2,#0
 1230   swine  "XOS_Module"  ; Release it
 1240   ldr    r2,[r12]      ; Pointer to module's workspace
 1250   mov    r0,#7
 1260   swi    "XOS_Module"  ; Release it
 1270   .Finalised
 1280   ldmfd  (sp)!,{pc}
 1290   :
 1300   :
 1310   .RAMCard             ; *RAMCard <filename>
 1320   stmfd  (sp)!,{r0-r5,link}
 1330   ldr    r12,[r12]     ; Get address of workspace
 1340   add    r2,r12,#256   ; r2=>filename buffer
 1350   mov    r3,#0         ; Offset into name
 1360   .RAMCardLoop
 1370   ldrb   r1,[r0,r3]    ; Get character
 1380   strb   r1,[r2,r3]    ; Store character
 1390   cmp    r1,#ASC"!"    ; Found <ctrl> char?
 1400   bcc    RAMCardNameDone ; Yes, stop
 1410   add    r3,r3,#1      ; Update index
 1420   cmp    r3,#255
 1430   bcc    RAMCardLoop   ; Loop while <256
 1440   .RAMCardNameDone
 1450   mov    r1,#13
 1460   strb   r1,[r2,r3]    ; Store terminating <cr>
 1470   add    r1,r12,#256   ; r0=>filename buffer
 1480   ldrb   r0,[r1]       ; Get first character
 1490   cmp    r0,#ASC"!"    ; Null filename?
 1500   movcc  r4,#0         ; Set size to zero
 1510   bcc    RAMCardNull   ; Jump to set size
 1520   mov    r0,#5
 1530   swi    "XOS_File"    ; Read file information
 1540   ands   r0,r0,#1      ; Is it a file?
 1550   moveq  r4,#0         ; Not a file - set length to zero
 1560   .RAMCardNull
 1570   add    r2,r12,#512   ; Point to variables
 1580   add    r2,r2,#4      ; Point to RAMCard size
 1590   str    r4,[r2],#8    ; Store size
 1600   mov    r4,#0
 1610   str    r4,[r2]       ; Zero PTR and flags
 1620   ldmfd  (sp)!,{r0-r5,pc}
 1630   :
 1640   :
 1650   .RAMCardLoad          ; *RAMCardLoad <filename>
 1660   stmfd  (sp)!,{r0-r5,link}
 1670   ldr    r12,[r12]     ; Get address of workspace
 1680   add    r2,r12,#512   ; Point to variables
 1690   add    r2,r2,#8      ; Point to RAM address
 1700   ldr    r1,[r2]       ; Get RAM address
 1710   orrs   r1,r1,#0
 1720   beq    RAMCardNoRAM  ; No RAM to load to
 1730   mov    r3,#0         ; Load to r2
 1740   mov    r2,r1         ; r2=address to load to
 1750   mov    r1,r0         ; r1=>filename
 1760   mov    r0,#&FF       ; r0=LOAD
 1770   swi    "OS_File"      ; Load the specified file
 1780   ldmfd  (sp)!,{r0-r5,pc}
 1790   :
 1800   :
 1810   .RAMCardSave
 1820   stmfd  (sp)!,{r0-r5,link}
 1830   ldr    r12,[r12]     ; Get address of workspace
 1840   add    r2,r12,#512   ; Point to variables
 1850   add    r2,r2,#4      ; Point to RAM address
 1860   ldr    r3,[r2],#4    ; Set RAMCard size
 1870   ldr    r1,[r2]       ; Get RAM address
 1880   orrs   r1,r1,#0
 1890   beq    RAMCardNoRAM  ; No RAM to load to
 1900   add    r5,r1,r3      ; r5=end address
 1910   mov    r4,r1         ; r4=start address
 1920   mov    r2,#&FD
 1930   orr    r2,r2,#&0F00  ; r2=&FFD - 'DATA'
 1940   mov    r1,r0         ; r1=>filename
 1950   mov    r0,#&0A       ; r0=SAVE as type
 1960   swi    "OS_File"      ; Save the specified file
 1970   ldmfd  (sp)!,{r0-r5,pc}
 1980   :
 1990   :
 2000   .RAMCardNoRAM
 2010   adr    r0,Error_NoRAM
 2020   swi    "OS_GenerateError"
 2030   ldmfd  (sp)!,{r0-r5,pc}
 2040   .Error_NoRAM
 2050   equd   &80AD0
 2060   equs   "No RAMCard memory"
 2070   equb   0
 2080   align
 2090   :
 2100   :
 2110   .Service
 2120   \ In r0=mem[0]
 2130   \    r1=Service_6502IN    - &80AD0
 2140   \    r1=Service_6502OUT   - &80AD1
 2150   \    r1=Service_6502Reset - &80AD2
 2160   \    r2=port
 2170   \    r3=value
 2180   \    r4=Module base
 2190   \
 2200   stmfd  (sp)!,{r1}      ; Check for Service_6502IN, 6502OUT or 6502Reset
 2210   and    r1,r1,#&FF000
 2220   cmp    r1,#&80000      ; &80xxx ?
 2230   ldmfd  (sp)!,{r1}
 2240   movne  pc,link         ; No
 2250   stmfd  (sp)!,{r1}
 2260   and    r1,r1,#&FF0
 2270   cmp    r1,#&AD0        ; &80ADx ?
 2280   ldmfd  (sp)!,{r1}
 2290   movne  pc,link         ; No
 2300   ldr    r12,[r12]       ; Get workspace address
 2310   stmfd  (sp)!,{r1}
 2320   and    r1,r1,#&F
 2330   cmp    r1,#&0          ; &80AD0 ?
 2340   beq    Service_6502IN
 2350   cmp    r1,#&1          ; &80AD1 ?
 2360   beq    Service_6502OUT
 2370   cmp    r1,#&2          ; &80AD2 ?
 2380   beq    Service_6502Reset
 2390   ldmfd  (sp)!,{r1}
 2400   mov    pc,link         ; No
 2410   :
 2420   :
 2430   .Service_6502Reset
 2440   ldmfd  (sp)!,{r1}      ; Restore call number
 2450   ;stmfd (sp)!,{link}
 2460   ;ldmfd (sp)!,{link}
 2470   mov    pc,link         ; Don't claim
 2480   :
 2490   :
 2500   .Service_6502IN        ; Read from &FC00,1,2,3
 2510   ldmfd  (sp)!,{r1}      ; Restore call number
 2520   stmfd  (sp)!,{r2}      ; Save port number
 2530   and    r2,r2,#&FF00    ; Lose bottom byte
 2540   cmp    r2,#&FC00       ; Port &FCxx ?
 2550   ldmfd  (sp)!,{r2}      ; Restore port number
 2560   movne  pc,link         ; No -> exit unclaimed
 2570                          ; Read &FCxx
 2580   stmfd  (sp)!,{r2}      ; Save port number
 2590   and    r2,r2,#&FF      ; Lose top byte
 2600   cmp    r2,#&04         ; Port <&FC04 ?
 2610   ldmfd  (sp)!,{r2}      ; Restore port number
 2620   movcs  pc,link         ; No -> exit unclaimed
 2630                          ; Read &FC00-3
 2640   ; r0=z80mem[0]
 2650   ; r1=corruptable
 2660   ; r2=port number - corruptable
 2670   ; r3=returns Read value
 2680   ; r4=corruptable
 2690   ; stack balanced
 2700   
 2710   ; &FC00-2 - b0-b23 address
 2720   ; &FC03   - byte port
 2730   
 2740   and    r2,r2,#3         ; r2=0/1/2/3
 2750   cmp    r2,#3
 2760   beq    ReadByte         ; Read a byte through the port
 2770   add    r2,r2,#512       ; r2 = offset to port values
 2780   ldrb   r3,[r12,r2]      ; Fetch byte from address latches
 2790   mov    r1,#0            ; Claim the call
 2800   mov    pc,link
 2810   :
 2820   .ReadByte
 2830   add    r2,r12,#512      ; Point to variables
 2840   ldr    r0,[r2],#4       ; Get port value
 2850   ldr    r1,[r2],#4       ; Get RAMCard size
 2860   cmp    r0,r1            ; Is port value past end of RAMCard?
 2870   bcs    ReadByteEnd      ; Reading from past end of RAM
 2880   add    r2,r12,#256      ; Point to filename
 2890   ldrb   r4,[r2]          ; Get filename first character
 2900   cmp    r4,#ASC"!"       ; Filename present?
 2910   bcs    ReadByteFile     ; Read from file
 2920   ldr    r1,[r2]          ; Get RAM address
 2930   orrs   r1,r1,#0         ; Any RAM available?
 2940   beq    ReadByteEnd      ; No RAM, just exit
 2950   ldrb   r3,[r1,r0]       ; Get byte from RAM
 2960   .ReadByteEnd
 2970   mov    r1,#0            ; Claim the call
 2980   mov    pc,link
 2990   :
 3000   .ReadByteFile
 3010   ; r0=port value
 3020   ; r1=RAMCard size
 3030   ; r2=>filename
 3040   ; r3=byte read
 3050   ; r4=spare
 3060   add    r2,r12,#512      ; Point to variables
 3070   add    r2,r2,#12        ; Point to PTR
 3080   ldr    r1,[r2]          ; r1=PTR, r0=port value
 3090   bic    r1,r1,#&FF       ; Remove flags in bottom byte
 3100   bic    r0,r0,#&FF       ; Remove offset within sector
 3110   cmp    r0,r1
 3120   bne    ReadByteBuffer   ; Need to read this sector
 3130   ldr    r1,[r2]          ; Get PTR+flags
 3140   ands   r1,r1,#1         ; Has buffer been read?
 3150   beq    ReadByteBuffer   ; Need to read this sector
 3160   .ReadByteGet
 3170   add    r0,r12,#512      ; Point to variables
 3180   ldr    r0,[r0]          ; Get port value
 3190   and    r0,r0,#&FF       ; Offset into this sector
 3200   ldrb   r3,[r12,r0]      ; Get byte from buffer
 3210   mov    r1,#0            ; Claim the call
 3220   mov    pc,link          ; And return
 3230   :
 3240   .ReadByteBuffer
 3250   stmfd  (sp)!,{link}     ; Save link as we're going to use SWIs
 3260   ldr    r1,[r2]          ; Get PTR+flags again
 3270   ands   r1,r1,#2         ; Has buffer been modified?
 3280   beq    ReadByteClean    ; No need to write buffer
 3290   add    r1,r12,#256      ; r1=>filename
 3300   mov    r0,#&C0
 3310   swi    "XOS_Find"       ; Open for update
 3320   mov    r1,r0            ; r1=handle
 3330   mov    r2,r12           ; r2=>buffer
 3340   mov    r3,#256          ; 256 bytes to write
 3350   add    r0,r12,#512      ; Point to variables
 3360   add    r0,r0,#12        ; Point to PTR
 3370   ldr    r4,[r0]          ; Get PTR
 3380   bic    r4,r4,#&FF       ; Lose flags in bottom byte
 3390   mov    r0,#1            ; Write with specified PTR
 3400   swi    "XOS_GBPB"       ; Write updated buffer
 3410   b      ReadByteUpdated
 3420   .ReadByteClean
 3430   add    r1,r12,#256      ; r1=>filename
 3440   mov    r0,#&40
 3450   swi    "XOS_Find"       ; Open for input
 3460   mov    r1,r0            ; r1=handle
 3470   .ReadByteUpdated
 3480   mov    r2,r12           ; r2=>buffer
 3490   mov    r3,#256          ; 256 bytes to read
 3500   add    r0,r12,#512      ; Point to variables
 3510   ldr    r4,[r0]          ; Get port value
 3520   bic    r4,r4,#&FF       ; Lose offset within sector
 3530   mov    r0,#3            ; Use specified PTR
 3540   swi    "XOS_GBPB"       ; Read to buffer
 3550   mov    r0,#0
 3560   swi    "XOS_Find"       ; Close file
 3570   add    r1,r12,#512      ; Point to variables
 3580   ldr    r4,[r1],#12      ; Get port value
 3590   bic    r4,r4,#&FF       ; Lose offset within sector
 3600   orr    r4,r4,#1         ; Flag 'buffer read'
 3610   str    r4,[r1]          ; Store current PTR+flags
 3620   ldmfd  (sp)!,{link}     ; Get link back
 3630   b      ReadByteGet      ; Get byte from buffer
 3640   :
 3650   :
 3660   .Service_6502OUT
 3670   ldmfd  (sp)!,{r1}      ; Restore call number
 3680   stmfd  (sp)!,{r2}      ; Save port number
 3690   and    r2,r2,#&FF00    ; Lose bottom byte
 3700   cmp    r2,#&FC00       ; Port &FCxx ?
 3710   ldmfd  (sp)!,{r2}      ; Restore port number
 3720   movne  pc,link         ; No -> exit unclaimed
 3730                          ; Read &FCxx
 3740   stmfd  (sp)!,{r2}      ; Save port number
 3750   and    r2,r2,#&FF      ; Lose top byte
 3760   cmp    r2,#&04         ; Port <&FC04 ?
 3770   ldmfd  (sp)!,{r2}      ; Restore port number
 3780   movcs  pc,link         ; No -> exit unclaimed
 3790                          ; Read &FC00-3
 3800   ; r0=z80mem[0]
 3810   ; r1=corruptable
 3820   ; r2=port number - corruptable
 3830   ; r3=Write value
 3840   ; r4=corruptable
 3850   ; stack balanced
 3860   
 3870   ; &FC00-2 - b0-b23 address
 3880   ; &FC04   - byte port
 3890   
 3900   and    r2,r2,#255      ; r2=0/1/2/3
 3910   cmp    r2,#3
 3920   beq    WriteByte       ; Write a byte through the port
 3930   add    r2,r2,#512      ; r2 = offset to port values
 3940   strb   r3,[r12,r2]     ; Store byte to address latches
 3950   mov    r1,#0           ; Claim the call
 3960   mov    pc,link
 3970   :
 3980   .WriteByte
 3990   add    r2,r12,#512      ; Point to variables
 4000   ldr    r0,[r2],#4       ; Get port value
 4010   ldr    r1,[r2],#4       ; Get RAMCard size
 4020   cmp    r0,r1            ; Is port value past end of RAM?
 4030   bcs    WriteByteEnd     ; Writing past end of RAM
 4040   add    r2,r12,#256      ; Point to filename
 4050   ldrb   r4,[r2]          ; Get filename first character
 4060   cmp    r4,#ASC"!"       ; Filename present?
 4070   bcs    WriteByteFile    ; Write to file
 4080   ldr    r1,[r2]          ; Get RAM address
 4090   orrs   r1,r1,#0         ; Any RAM available?
 4100   beq    WriteByteEnd     ; No RAM, exit
 4110   strb   r3,[r1,r0]       ; Put byte to RAM
 4120   .WriteByteEnd
 4130   mov    r1,#0            ; Claim the call
 4140   mov    pc,link
 4150   :
 4160   .WriteByteFile
 4170   ; r0=port value
 4180   ; r1=RAMCard size
 4190   ; r2=>filename
 4200   ; r3=byte to write
 4210   ; r4=spare
 4220   add    r2,r12,#512      ; Point to variables
 4230   add    r2,r2,#12        ; Point to PTR
 4240   ldr    r1,[r2]          ; r1=PTR, r0=port value
 4250   bic    r1,r1,#&FF       ; Remove flags in bottom byte
 4260   bic    r0,r0,#&FF       ; Remove offset within sector
 4270   cmp    r0,r1
 4280   bne    WriteByteBuffer  ; Need to read this sector
 4290   ldr    r1,[r2]          ; Get PTR+flags
 4300   ands   r1,r1,#1         ; Has buffer been read?
 4310   beq    WriteByteBuffer  ; Need to read this sector
 4320   .WriteByteGet
 4330   add    r0,r12,#512      ; Point to variables
 4340   ldr    r0,[r0]          ; Get port value
 4350   and    r0,r0,#&FF       ; Offset into this sector
 4360   strb   r3,[r12,r0]      ; Get byte from buffer
 4370   add    r2,r12,#512      ; Point to variables
 4380   add    r2,r2,#12        ; Point to PTR+flags
 4390   ldr    r0,[r2]
 4400   orr    r0,r0,#2         ; Flag 'buffer modified'
 4410   str    r0,[r2]
 4420   mov    r1,#0            ; Claim the call
 4430   mov    pc,link          ; And return
 4440   :
 4450   .WriteByteBuffer
 4460   stmfd  (sp)!,{r5,link}  ; Save link as we're going to use SWIs
 4470   mov    r5,r3            ; Save byte to write
 4480   ldr    r1,[r2]          ; Get PTR+flags again
 4490   ands   r1,r1,#2         ; Has buffer been modified?
 4500   beq    WriteByteClean   ; No need to write buffer
 4510   add    r1,r12,#256      ; r1=>filename
 4520   mov    r0,#&C0
 4530   swi    "XOS_Find"       ; Open for update
 4540   mov    r1,r0            ; r1=handle
 4550   mov    r2,r12           ; r2=>buffer
 4560   mov    r3,#256          ; 256 bytes to write
 4570   add    r0,r12,#512      ; Point to variables
 4580   add    r0,r0,#12        ; Point to PTR
 4590   ldr    r4,[r0]          ; Get PTR
 4600   bic    r4,r4,#&FF       ; Lose flags in bottom byte
 4610   mov    r0,#1            ; Write with specified PTR
 4620   swi    "XOS_GBPB"       ; Write updated buffer
 4630   b      WriteByteUpdated
 4640   .WriteByteClean
 4650   add    r1,r12,#256      ; r1=>filename
 4660   mov    r0,#&C0
 4670   swi    "XOS_Find"       ; Open for update
 4680   mov    r1,r0            ; r1=handle
 4690   .WriteByteUpdated
 4700   mov    r2,r12           ; r2=>buffer
 4710   mov    r3,#256          ; 256 bytes to read
 4720   add    r0,r12,#512      ; Point to variables
 4730   ldr    r4,[r0]          ; Get port value
 4740   bic    r4,r4,#&FF       ; Lose offset within sector
 4750   mov    r0,#3            ; Use specified PTR
 4760   swi    "XOS_GBPB"       ; Read to buffer
 4770   mov    r0,#0
 4780   swi    "XOS_Find"       ; Close file
 4790   add    r1,r12,#512      ; Point to variables
 4800   ldr    r4,[r1],#12      ; Get port value
 4810   bic    r4,r4,#&FF       ; Lose offset within sector
 4820   orr    r4,r4,#1         ; Flag 'buffer read'
 4830   str    r4,[r1]          ; Store current PTR+flags
 4840   mov    r3,r5            ; Get byte to write back to r3
 4850   ldmfd  (sp)!,{r5,link}  ; Get link back
 4860   b      WriteByteGet     ; Get byte from buffer
 4870   ;
 4880   ;
 4890   ;
 4900   ; *REALLY* slow method...
 4910   stmfd  (sp)!,{link}     ; Save link as we're going to use SWIs
 4920   mov    r4,r0            ; Save offset for later
 4930   mov    r1,r2            ; r1=>filename
 4940   mov    r0,#&C0          ; OPENUP
 4950   swi    "XOS_Find"
 4960   mov    r2,r4            ; r2=offset
 4970   mov    r1,r0            ; r1=handle
 4980   mov    r0,#1            ; r0='write ptr'
 4990   swi    "XOS_Args"       ; Set PTR
 5000   mov    r0,r3            ; Byte to write
 5010   swi    "XOS_BPut"       ; Write a byte
 5020   mov    r0,#0
 5030   swi    "XOS_Find"       ; Close file
 5040   ldmfd  (sp)!,{link}     ; Get link back
 5050   mov    r1,#0            ; Claim the call
 5060   mov    pc,link
 5070   :
 5080   :
 5090   ALIGN
 5100 ]NEXT
 5110 OSCLI"SAVE RAMCard "+STR$~mcode%+" "+STR$~O%
 5120 *SetType RAMCard Module
 5130 *Stamp RAMCard
 5140 END