REM >ArcSendHD REM vim:ai:et:sts=2:sw=2 REM Send the contents of an Acorn Archimedes hard disk over a serial link. REM Specifically, mine's an A310 with a 40MB ST506-ish disk. REM Adam Sampson : REM How to use SYS: REM http://www.apdl.co.uk/riscworld/volume5/issue2/basicv/chap14.htm : drive% = 4 REM 8=19200, 7=9600, 6=4800 (as for *FX7) rate% = 8 : PROCcrcARM PROCsendARM : REM Serial SWIs mostly described here: REM http://www.chiark.greenend.org.uk/~theom/riscos/docs/RISCOS2/kernel/Serial.txt REM Disable serial receive SYS "OS_Byte", 2, 0 REM Use RTS/CTS, ignore DCD and DSR REM However, this has no effect on pre-RiscPC Arcs -- this app note describes REM how to build a serial cable for older machines: REM http://acorn.chriswhy.co.uk/docs/Acorn/AN/234.pdf SYS "OS_SerialOp", 0, 6, 0 REM 8N1 SYS "OS_SerialOp", 1, 0 REM Receive rate SYS "OS_SerialOp", 5, rate% REM Transmit rate SYS "OS_SerialOp", 6, rate% REM Enable serial receive SYS "OS_Byte", 2, 2 : len% = 40 DIM ping% len% ping%?0 = ASC("p") FOR i% = 1 TO len% - 1 ping%?i% = 64 + i% NEXT PROCpayload(ping%, len%) : REM This is based on SectorOp by James Bursa DIM r% 100 SYS "ADFS_DescribeDisc", ":" + STR$(drive%), r% totalbytes% = r%!16 REM FIXME: large disks have more size bits in r%!24 secbytes% = 2^r%?0 PRINT "Disc size: "; totalbytes% PRINT "Sector size: "; secbytes% PRINT "Sectors per head: "; r%?1 PRINT "Heads per track: "; r%?2 tracksecs% = r%?1 * r%?2 sectors% = (totalbytes% / (secbytes% * tracksecs%)) * tracksecs% PRINT "Total sectors: "; sectors% INPUT "Start at sector"; sector% : headbytes% = 1 + 4 gather%=32 payloadbytes% = headbytes% + (secbytes% * gather%) DIM buf% payloadbytes% : startsec% = sector% starttime% = TIME : WHILE sector% < sectors% elapsed% = TIME - starttime% IF elapsed% > 0 THEN PRINT "Rate: "; ((sector% - startsec%) * secbytes% * 100) / elapsed%; " bps" : buf%?0 = ASC("w") buf%!1 = sector% * secbytes% : PRINT "Reading sectors "; sector%; " to "; sector% + gather% - 1; " of "; sectors%; "..."; FOR i% = 0 TO gather% - 1 secbuf% = buf% + headbytes% + (secbytes% * i%) REM ADFS_SectorDiscOp on later RISC OS (addr in sectors) REM ADFS_SectorOp on slightly later RISC OS (addr in sectors) REM But on my A310 only this exists! (addr in bytes) SYS "ADFS_DiscOp",, 1, drive%<<29 OR (sector% * secbytes%), secbuf%, secbytes% sector% = sector% + 1 NEXT PRINT "OK: "; buf%?headbytes% : PROCpayload(buf%, payloadbytes%) ENDWHILE : END : DEF PROCpayload(mem%,num%) LOCAL head%, c% DIM head% 10 head%?0 = 149 head%?1 = 20 head%!2 = num% head%!6 = FNcrc(mem%, num%) REPEAT PRINT "Sending "; num%; "..."; PROCsend(head%, 10) PROCsend(mem%, num%) c% = FNread PRINT CHR$(c%) UNTIL CHR$(c%) = "y" ENDPROC : REM This is J.G.Harston's implementation of the Zip CRC-32, from: REM http://mdfs.net/Info/Comp/Comms/CRC32.htm : DEF FNcrcBASIC(mem%,num%) LOCAL S%,A%,B%,O% S%=-1 FORA%=mem%TOmem%+num%-1:S%=S%EOR?A%:FORB%=1TO8:O%=S%:S%=(((S%+(S%<0))DIV2)AND&7FFFFFFF):IFO%AND1:S%=S%EOR&EDB88320 NEXT:NEXT =NOT S% : DEF FNcrc(mem%,num%) !addr=mem%:!num=num%:!crc=-1:CALL Calc =NOT !crc : DEFPROCcrcARM:DIM Calc 79:FORP=0TO1 P%=Calc:[OPT P*2:LDR R0,addr:LDR R1,num LDR R2,crc:LDR R3,xor .bl:LDRB R4,[R0],#1:EOR R2,R2,R4:MOV R4,#8 .rl:MOVS R2,R2,LSR #1:EORCS R2,R2,R3 SUBS R4,R4,#1:BNE rl:SUBS R1,R1,#1:BNE bl STR R2,crc:MOV R15,R14:.xor:EQUD &EDB88320 .addr:EQUD 0:.num:EQUD 0:.crc:EQUD 0:]:NEXT:ENDPROC : REM Serial I/O : REM This works, but only at about 250 cps on an A310 DEF PROCsendBASIC(mem%,num%) LOCAL i%, f% FOR i% = 0 TO num% - 1 REPEAT SYS "OS_SerialOp", 3, mem%?i% TO ; f% UNTIL (f% AND 2) = 0 NEXT ENDPROC : REM Faster serial send - reusing addr/num from above DEFPROCsend(mem%,num%) !addr=mem%:!num=num%:CALL Send ENDPROC : DEFPROCsendARM DIM Send 200 FOR P = 0 TO 1 P% = Send [OPT P*2 LDR R4,addr:LDR R5,num .next:MOV R0,#3 LDRB R1,[R4],#1 .again:SWI "OS_SerialOp" BCS again SUBS R5,R5,#1:BNE next MOV R15,R14 ] NEXT ENDPROC : DEF FNread LOCAL c%, f% REPEAT SYS "OS_SerialOp", 4, 0 TO , c%; f% UNTIL (f% AND 2) = 0 =c% :