Page 1 of 1

Atom tape format checksum

Posted: Sat Oct 22, 2005 2:41 pm
by Fraser
http://homepage.ntlworld.com/kryten_dro ... /spa45.htm

Can anyone see how the checksum is calculated in the example? It is E3 in hex.

Posted: Sun Oct 23, 2005 11:02 am
by regregex
According to the article, it ought to be the sum of the ASCII values mod 256:

Code: Select all

  *   *   *   *   A   D   V   E   N   T   U   R   E  cr
 2A +2A +2A +2A +41 +44 +56 +45 +4E +54 +55 +52 +45 +0D = 0363 = 63 (mod 100)
The page gives a checksum of E3, this may be an OCR error for 63, or because these differ in bit 7 there may be some other cause. Without any other examples it's hard to say why the numbers don't match.

The CRC algorithm, incidentally, doesn't seem to match the Rocksoft(tm) model so parameterised implementations such as tomtorfs.c won't be able to emulate it.

Posted: Sun Oct 23, 2005 11:48 am
by Fraser
A checksum following the file name 'INDEX' is D0. The total is 22D before the checksum. The other values are quantity FF, GO 8000, MEM 8000. It surprises me if the checksum doesn't include all the data. With the BBC format the leading '*' is omitted from it.

Posted: Sun Oct 23, 2005 4:41 pm
by regregex
Maybe the last character is repeated:

Code: Select all

A+D+V+E+N+T+U+R+E+E = 02F3 (again, E3 may be a typo)
I+N+D+E+X+X         = 01D0
As before, "insufficient data" to know for certain. If you have an image of the OS ROMS (and the BASIC ROM images as well, to check the CRC algorithm against the results in the table) I'd appreciate a copy as a quick disassembly + search should give a clue.

Posted: Mon Oct 24, 2005 10:18 am
by Fraser
http://www.howell1964.freeserve.co.uk/A ... mMagic.htm

Some ROM routines are described here. The checksum is stored at 00DC.

http://web.tiscali.it/magazzinocartoniani/

The OS basic and FP ROMs are here. Maybe copies could be held at this site.

Flag byte?

Posted: Wed Oct 26, 2005 10:34 pm
by regregex
Thanks Fraser, the links are a great help. The Integer Basic image is corrupt though, being too long.

Anyway, here's what I've worked out from a disassembly: Near the beginning OSSAVE copies the user's parameter block to a fixed location:-

Code: Select all

C9..CA  address of file name
CB..CC  load address
CD..CE  exec address
CF..D0  first address
D1..D2  last+1 address
Then an approximate pseudocode runs as follows:-

Code: Select all

FAF8: D2[4..1] = CE[4..1]

D3..D4  first address
D5..D6  last+1 address

D0=0; D1=0;

D5w--; # w means a 16bit value
c=0; 
do {
  ror D2;
  CF=D5-D3; push status;
  D6-D4 (c=notborrow); ror D2;
  pop status;
  if c=1 (i.e. D5w >=D3w) {
    c=0
    if D5w != D3w {
      CF=&FF
      c=1
    }
  }
  FB29: ror D2;
  call FB3B -> write block
  D0++; D4++; CC++;
  rol D2;
} while c=1;
FB3B writes the block, including bytes D2..CB (downwards) in the header. The 'checksum' (stored in location &D2) therefore seems to be a flag byte:

Code: Select all

b5=1 if not the first block;
b6=1 if block contains data,
     i.e. if last+0 address >= address of first byte in this block.
     This bit is tested at &FB64 to skip writing data to the block.
     If clear then the length byte of the header is undefined;
b7=1 if not the last block.  When set this bit will be shifted
     to b5 of the next block flag.
b0..b4 contains:
     in the first block, b3..b7 of the high byte of the last+1 address;
     in subsequent blocks, b2..b6 of the previous flag byte.
So for ADVENTURE, the last+1 address is &3C00. Applying the above, we get a value of &C7 - still not reproducing the &E3 in the article! :x

Similarly we can deduce a value %.10..... for the file INDEX, according to this explanation, the file is at least 256 bytes long and ended between &8000..&87FF.

However as I've never owned an Atom, some or all of this could be complete rubbish :)

[Edit 27/Oct: one replacement with last+0, add FB3B description]
[Edit 26/Aug: reversed first assignment]
[Edit 12/Oct: push status register]

Posted: Thu Oct 27, 2005 4:16 pm
by Fraser
Here is some header file data for comparing:
2A 2A 2A 2A 49 4E 44 45 58 0D D0 00 00 FF 80 00 80 00
2A 2A 2A 2A 49 4E 44 45 58 0D 74 00 01 FF 80 00 81 00
2A 2A 2A 2A 49 4E 54 52 4F 44 55 43 54 49 4F 4E 0D C6 00 00 FF 33 99 28 00
2A 2A 2A 2A 49 4E 54 52 4F 44 55 43 54 49 4F 4E 0D F1 00 00 FF 33 99 29 00

Posted: Thu Oct 27, 2005 7:42 pm
by regregex
Fraser wrote:Here is some header file data for comparing:
[...]
2A 2A 2A 2A 49 4E 54 52 4F 44 55 43 54 49 4F 4E 0D F1 00 00 FF 33 99 29 00
Shurely:

Code: Select all

[...] F1 00 01 FF 33 99 29 00
            ^^
(or, "Damn it boy, it's Littorina littorea, not Littorina littoralis. Don't they teach you anything?")

So the theory holds water, at least according to these snippets:

Code: Select all

    10000000  80  End address high
110 10000     D0  Block flag
   11010000   "
011 10100     74    "     "

    00110011  33
110 00110     C6
   11000110   "
111 10001     F1

Posted: Fri Oct 28, 2005 1:18 pm
by Fraser
Thanks Beardo. The other bits are probably just something left in a register that wasn't cleared.

I've seen a Atom file without a leading carrier tone at the end of a Acornsoft tape. It might be a version number like they did the BBC tapes. Theres only a few bytes:
31 38 2F 31 32 2F 38 31 20 44 4A 44 0D
1 8 / 1 2 / 8 1 SP D J D CR

Posted: Sun Nov 06, 2005 3:28 pm
by Fraser
How does the checksum work? What does it mean with "executing ?DC" ? The block above is probably a unnamed file.

Posted: Mon Nov 07, 2005 8:27 pm
by regregex
Fraser wrote:How does the checksum work?
Presumably, it's just a sum modulo 256 of the data in question. In other words, start with 00 in the accumulator, ADC each byte of the data (discarding carry-outs) and the result is in A. Locations F9F6..FA04 in the kernel are where the comparison takes place.

The CRC (which isn't in the kernel) can be done sort-of with Tomtorfs, if you run all but the last two bytes through this program, then XOR the last two bytes with the result and then reverse the bits:

Code: Select all

tomtorfs allbut2.bin 16 002D 1 0000 0000
What does it mean with "executing ?DC" ? The block above is probably a unnamed file.
?DC must have originally been a four-figure reference to a place in the kernel, which didn't OCR. Unfortunately kryten_droid doesn't provide an email address so we can't ask him what the book says! There won't be any code in &DC to execute.

As to the unnamed file, you mean the one I wrote? I was just suggesting what one of the headers you had written should look like according to the manual, for convenience I only repeated the last eight bytes.

Or if you meant the version string at the end of the Acornsoft tape, it doesn't comply to either the named or unnamed file standard.

[edit: changed tomtorfs command - calculating the CRC is non-trivial - I can post instructions if you like.]

Posted: Tue Nov 08, 2005 4:41 pm
by Fraser
That is how the checksum works.

I wonder is the Atom can read the version files?

MakeUEF V1.11 beta makes a report like this for Atom blocks:
Gap written, length 1.936599 seconds.


Security waves written, length 1 waves, as follows:
S,
The security waves start with a pulse.
Carrier tone written, length 4814 waves.
Baud rate of the preceding data was 1233.583

Atom data format header block written.
7 data blocks written.
Carrier tone written, length 1184 waves.
Baud rate of the preceding data was 1233.929

Atom data format data block written.
8 data blocks written.
Baud rate of the preceding data was 1233.383

Atom data block checksum written.
Security waves written, length 1 waves, as follows:
L,
The security waves end with a pulse.
Baud rate of the preceding data was 1232.609


The checksum is stored as a 8N1 byte and the rest is with the negative stop bits notation. I want to get that chunk changed to be independent of the baud rate format with negative stop bits.

UEF timebase simplification proposal

Posted: Tue Nov 08, 2005 7:27 pm
by regregex
I wouldn't know about reading the version files. You might be able to with calls to OSBGET, but maybe not from a *command. (I don;t have an Atom so can't experiment on this.)
Fraser wrote:The checksum is stored as a 8N1 byte and the rest is with the negative stop bits notation. I want to get that chunk changed to be independent of the baud rate format with negative stop bits.
For once I agree with you over UEF :) The mish-mash of timescales has got pretty messy (see the UEFwalk script).

I think that the baud rate format (proposed chunk 0117) should only apply to shift register stuff (i.e. data bytes, start bits and 'positive' stop bits.) For convenience these should continue to use the chunks 0100, 0104 and 0111 (in which chunk 0117 would only apply to the dummy byte &AA, not the hightones.) The chunks should always be considered shorthand forms of the low-level pulse train.

Where you have 'negative' stop bits these are obviously produced under CPU control so they should be measured in pulses. All other signals should be measured in pulses too. Chunk 0113 tells you how many pairs-of-long-pulses there are in a second.

Gaps should be measured in seconds, and should be the observed length of time the LINE IN went quiet. UEF producers can offer an estimate (in chunk 0113) of the pulse-pairs-per-second if the gap were a signal instead, but it would be up to the UEF reader whether to reproduce what was heard on tape or, by scaling, what came out of the LINE OUT of the recording computer (based on the nominal 1201.923 pulse-pairs-per-second predicted by the circuit diagram.)

In any case the version number would have to be bumped up to confirm use of the new timescales.

What do you think of this?

Posted: Tue Nov 08, 2005 7:48 pm
by Fraser
MakeUEF versions that I made only use 0116 for gaps. The way 0112 is is more generic than tieing it to the BBC frequency. It would be useful to rename 0112 and 0116.

I agree about the baud rate format affecting 0100, 0104 and 0111 only.