TAPE -> ADFS (Part 2)
So, TAPE2DISK utility required; simple spec:
- Can be left to run automatically, lifting data from a tape and storing it on disc (well, a GoTEK!)
- Won’t need to support files larger than those that will fit in memory
- Want to reproduce the filename, load address, execution address (and, naturally, the length)
Just needed a reminder of *LOAD
and *SAVE
, so again.. a web search. Good grief - look what turns up - The BBC Microcomputer Advanced User Guide in PDF form (!) - I always had to borrow one, and now it has been scanned in and OCR’d. Thanks again to StarDot for hosting the archive of bbcdocs.com
. Its amazing that so much info is now available! In those pre-internet days, information wsa hard to get hold of - makes me wonder what we could have done with this availability…
A quick flick through the manual and reviewed *LOAD
(can just run *LOAD "" 2000
to grab the next file on cassette and store at &2000), and then use *SAVE
to write it back out (crucially with a replaced “load” address to match the original). Couldn’t recall how to build a “*” command from a string in BBC BASIC - and tripped over OSCLI()
- that’ll be it!
However. How do I get the load & execution address automatically? *OPT 1,2
would let me see it via *CAT
etc. - but I need a BASIC programme to see it. There’s a challenge…
More searching. Mind = blown; a full BBC memory map was published by 8-Bit Software Magazine, hosted on nerdoftheherd - namely, Part 1 and Part 2. Digging around, aided by the “Tape to Disc Transfer” articles by Albert Schofield, I was ready. I now know that:
-
03B2-03D0 Block header of most recent block read
- B2-BD Filename terminated by zero
- I can grab the filename, noting its zero-terminated, so:
filenameChar = &03B2 filename$ = "" REPEAT filename$ = filename$ + CHR$(?filenameChar) filenameChar = filenameChar + 1 UNTIL ?filenameChar = 0
- I can grab the filename, noting its zero-terminated, so:
- BE-C1 Load address
- Save that off to a variable:
loadAddress = !&03BE
- Save that off to a variable:
- C2-C5 Execution address
- Again, save that off to a variable:
execAddress = !&03C2
- Again, save that off to a variable:
- C6-C7 Block number
- 2 bytes this time, not 4, so:
blockNumber = ?&03C6 + &0100 * ?&03C7
- 2 bytes this time, not 4, so:
- C8-C9 Length of block
- 2 bytes again:
blockLength = ?&03C8 + &0100 * ?&03C9
- 2 bytes again:
- File length can be taken to be:
- 256 * (number of blocks - 1) + length of last block, or:
length = blockLength + &0100 * blockNumber
We’re in! A quick test to check that I’d built the
*SAVE
command correctly from the variables, by checking the newADFS
file against theTAPE
original, bingo! I then had to dig around to remind myself of the commands I needed to convert integers to a string in hex format (“STR$~(variable)
” - there’s a “tilda” that’s not mapped in the MODE 7 font).Full BASIC script is as follows - beware tildas not showing - also stored as a raw text file if you want to*SPOOL
it.100 REM T2D - a simple Tape to Disc copier 110 120 REM v1.0 - 2020-01-20 - Ian Grimstead 130 140 REM Assumes ADFS, doesn't do anything clever to 150 REM map "." to different characters or create 160 REM directories 170 180 REPEAT 190 200 PRINT 210 PRINT "Loading from TAPE..." 220 PRINT 230 *TAPE 240 startAddress = LOMEM + &0400 250 REM Show load, exec details... 260 *OPT 1,2 270 loadCommand$ = "*LOAD """" " + STR$~(startAddress) 280 REM PRINT loadCommand$ 290 OSCLI(loadCommand$) 300 310 filenameChar = &03B2 320 filename$ = "" 330 REPEAT 340 filename$ = filename$ + CHR$(?filenameChar) 350 filenameChar = filenameChar + 1 360 UNTIL ?filenameChar = 0 370 380 loadAddress = !&03BE 390 execAddress = !&03C2 400 blockNumber = ?&03C6 + &0100 * ?&03C7 410 blockLength = ?&03C8 + &0100 * ?&03C9 420 length = blockLength + &0100 * blockNumber 430 440 saveCommand$ = "*SAVE """ + filename$ + """ " + STR$~(startAddress) + " +" + STR$~(length) + " " + STR$~(execAddress) + " " + STR$~(loadAddress) 450 PRINT 460 PRINT "Saving to ADFS..." 470 *ADFS 480 REM PRINT saveCommand$ 490 OSCLI(saveCommand$) 500 PRINT "...saved" 510 520 UNTIL FALSE
Thought for the day: a C60 (that’s a 60 minute cassette) pulled in 160kB of data. Ouch. Took a handful of seconds to save to ADFS - I now remember the joy of floppy discs!
- 256 * (number of blocks - 1) + length of last block, or: