home *** CD-ROM | disk | FTP | other *** search
- ` DISK STRUKTURE
-
- As we all know disks contain tracks,data on the disk is stored on those
- tracks. There are 80 (official) cylinders on the disk, each cylinder
- containing two tracks (upper and lower).
-
- When we number things as 0-79, we really talk about cylinders, but
- usualy this numbering is called track numbering.
- The system numbers tracks 0-159 and numbering starts from lower side,
- where is track 0, track 1 is really cylinder 0 upper side.
- Data on these tracks is usually MFM-decoded. Each track contains 11
- sectors of 512 bytes of data. Each sector has a header, which tells us
- track number, sector number and some additional data.
-
- Contents of normal DOS-format track is;
-
- ...(gap)...(track)...(gap)...
-
- (gap) is normally 0-bytes decoded into MFM. 00 -> AAAA
- (track) contains 11 sectors which are:
-
- (00)(00)(sync)(sync)(header)(fill)(headerchecksum)(datachecksum)(data)
-
- (00) is zero byte (in MFM AAAA)
- (sync) is (A1)-bytes converted to MFM and clock pulse is dropped so that
- result is 4489, which is standard syncword. Any data never converts
- into this pattern (in MFM)
- (header) is sector header. More later.
- (fill) is 16 bytes of zeros. These are intended for use by dos, but dos
- doesn't use them.
- (headerchecksum) is checksum of header info. Checksum is calculated using
- exclusive-or and contains only databits.
- (datachecksum) is same for data.
- (data) is 512-byte data block.
-
-
- Sector header consists from;
-
- (format)(track)(sector)(length)
-
- (format) is FF for normal format
- (track) is track number
- (sector) is sector number
- (length) is count of sectors before gap (end of track)
-
-
- This stuff is converted into MFM before writing and is is done as follows:
-
- (sector header) is converted as one longword
- (fill) is converted as one 16-byte block
- (checksums) are converted as longword
- (data) is converted as one 512-byte block
-
-
- MFM conversion is in the following principle;
-
- Take two data bits and add one clock bit between them.
- Clock bit is 1, if both data bits are 0 otherwise 0.
-
- so 01001110 goes to;
-
- C0C1C0C0C1C1C1C0 -> 0001001001010100
-
- Each byte converts into a word.
-
- As streching bytes is quite hard to do on the Amiga, data is first split into
- two halves; odd and even.
-
- First even bits are converted and then odd ones.
-
- So in Amiga:
-
- 01001110 -> 0011 1010
- even odd
-
- C0C0C1C1C1C0C1C0 -> 0010010101000100
-
-
- This lead into faster operation, because extracting odd and even halves can be
- done by logical ops.
-
- Even_half = ((data & 0xAAAA) >> 1)
-
- Odd_half = (data & 0x5555)
-
-
- And values for clock bits are:
-
- clock_bit = not( previous_bit or next_bit )
-
- So
-
- Result = ( ~( (Half>>1) | (Half<<1) ) ) | Half
-
-
- Conversion of one block (in Amiga style) can be done with following code:
-
- ; Input:
- ; a0 - address of data to be converted
- ; a1 - address of destination block
- ; d0 - length of block (in bytes)
- ; d1 - continuation flag (is end of previous block ok)
- ;
- ; Result:
- ; decoded data in destination buffer
- ; checksum in d0
- ; d2,d3,d4 also used
-
- _encodeblock:
- movem.l d2-d4,-(sp) ; save working regs
- clr.l d4 ; initialize checksum
- move.l d1,-(sp) ; flag is saved
- move.l d0,d1 ; copy length into index
- move.l a1,-(sp) ; save start of dst buffer
- asr.l #1,d1 ; create word count
- bra 2$
-
- ; Copy loop first
-
- 1$:
- move.w (a0)+,d2 ; pick word from src
- move.w d2,0(a1,d0) ; put odd bits into latter half ...
- asr.w #1,d2 ; ... and even bits ...
- move.w d2,(a1)+ ; ... into first half
-
- 2$:
- dbra d1,1$ ; done
-
- ; Now convert from dst to dst one word at time
-
- move.l (sp)+,a1 ; restore dst address
- move.l (sp)+,d1 ; pick flag
- beq 4$ ; no continuation
- move.l -2(a1),d1 ; or previous block before this one
- bra 4$ ; last word is picked from there
-
- ; conversion loop as each word of source
- ; converts into longword we convert length count of words
-
-
- 3$:
- move.w (a1),d1 ; take first word to convert
- and.l #$55555555,d1 ; pick bits to convert
- move.l d1,d2 ; copy longword in reg ...
- move.l d1,d3 ; ... twice into work regs ...
- asr.l #1,d2 ; other is shifted right
- add.l d3,d3 ; and other left
- or.l d3,d2 ; combine these
- not.l d2 ; and complement
- or.l #$AAAAAAAA,d1 ; turn all clocks up
- and.l d2,d1 ; turn some of them down
- move.w d1,(a1)+ ; put resulting word into buffer
- eor.w d1,d4 ; update checksum
- swap d4 ; swap checksum
- swap d1 ; push last word into upper half
- 4$:
- dbra d0,3$ ; and here we go for next word
- swap d4 ; take checksum
- move.l d4,d0 ; put into result reg
- and.l #$55555555,d0 ; and drop clock bits
- movem.l (sp)+,d2-d4 ; restore regs
- rts ; and retrun into caller
-
-
-
-
- In real life this is done with the blitter, which may very well be slower if
- faster processors than normal are used. We need four blits for each block and
- for tiny blocks this is slower. But for large blocks, situaion is something
- else because blitter ops are effectively parallel with processor.
-
- Decoding a block is even easier and can be done with one blit. Very quick,
- except for single longword (as header).
-
- Decoding in principle is;
-
- data = (odd_word & 0x5555) | ((even_word & 0x5555)<<1)
-
- And can be done with following code
-
- ; long decodeblock( char * from, char * to, int len )
- ; a0 a1 d0
- _decodeblock:
- movem.l d2-d4,-(sp) ; save working regs
- clr.l d4 ; init checksum
- move.l d0,d1 ; save src legth for indexing
- asr.l #2,d0 ; src bytecount to dst wordcount
- bra 2$
-
- 1$:
- move.l (a0)+,d2 ; get even_word
- and.l #$55555555,d2 ; drop clockbits
- eor.l d2,d4 ; update checksum
- add.l d2,d2 ; shift left
- move.l -4(a0,d1),d3 ; get odd_word
- and.l #$55555555,d3 ; drop clocks
- eor.l d3,d4 ; update checksum
- or.l d3,d2 ; combine words
- move.l d2,(a1)+ ; save results
-
- 2$:
- dbra d0,1$ ; count words
- add.l d1,a0 ; update pointer
- move.l d4,d0 ; put checksum in result reg
- movem.l (sp)+,d2-d4 ; restore working regs
- rts ; go back where you belong
- ;
-
- Usually disks are decoded as MFM and standard sync word is used. There is no
- actual reason for this, but it is so.
-
-
-
- {2{A O T H E R T O P I C S
-
- {1 Length of a normal track is;
-
- 2 (zeros)
- 2 (syncs)
- 4 (header)
- 16 (zeros)
- 4 (header checksum)
- 4 (data checksum)
- +512 (data)
- ----
- 544 bytes (sector)
- * 11 (sector count)
- ----
- 5984 bytes (normally)
- * 2 ( factor from MFM-decode)
- -----
- 11968 bytes in MFM
-
- As each track is circular, between track end and track start there is gap,
- which is usually about 670 bytes.
-
-
- Normal variations to normal track format are;
-
-
- S I N G L E S E C T O R
- Track contains only one sector. Length of sector is about 11968, so it
- must be correctly found in order to copy it.
-
- N O N E M P T Y G A P
- Normally the gap is empty, but somebody may store some id data on it.
-
- L O N G T R A C K
- More data than normally is put into the track. Length of data is more
- than 11968 + gap. It is (oficially) impossible write these kind of disks
- on the Amiga (without extra hardware), but the Amiga is able to read them.
- Some other variations also exist and more are to come. With visual mode,
- it is possible to look at a track closely and analyze its contents (in
- your head).
-
- Normal track usually looks as follows:
-
- (end of track)(gap)(track)(gap)
- (start of track)
-
- In order to copy this correctly, end of write should be positioned on the
- latter gap. As we read little more than two track lengths into the buffer,
- we ensure that track is in buffer at least once. What we need to find
- is the position where the write originally terminated and use the same
- position. Sounds simple, but for normal track do the following;
-
- At the beginning, you are positioned at the last sync on the buffer. You
- know the thing here: Position and alignment.
- Search the syncs towards the start, until the alignment changes. This
- usually means that you have just passed the gap.
-
- Move back to the previous sync (alignment changes back) and put an
- end of write about 100 bytes before sync.
- Sometimes alignment stays the same for all syncs. This means that the length
- of physical track happens to be an even multiple of 8 (not too likely).
- You must recognize the gap from the destination between two consecutive
- syncs. Track syncs are about 1088 bytes from each other and a longer
- distance means a gap.
-
- This all applies to normal tracks, but usually you don't need to copy normal
- tracks with visual mode. On some disks, when dirty gaps are used, you
- should recognize gap and decide how to copy it correctly.
- Also, if index sync is needed, you should usually use visual mode.
-
- Always write a whole track (writing less than about 12500 bytes may leave
- some old contents visible). A track is circular, don't forget it. When
- writing more than about 12500 bytes, the last written stuff overwrites the
- first written data. This is usually wanted, because we normally write:
-
- (pregap)(track)(postgap)
-
- where pregap is partly overwritten with postgap. We don't exactly know
- how much, because of variations in drive speeds etc.
-