Skip to main content

FORMATTING DISKS IN MACHINE CODE
- or -
THE EXCESSIVE INSPIRATION OF AN EDITOR BEING POORED ALL OVER
THOSE WHO JUST WANT TO KNOW SOME MORE ABOUT MACHINE CODE
PROGRAMMING

By Stefan Posthuma

The pale streetlights cast an eldritch gleam upon the wet
pavement. Stooping deeply against the gusts of rain that were
being blown into my face, I hurried onwards to the inviting
warmth of my home. The wind cut through my clothing like a newly
forged blade through soft flesh. Dark clouds obscured the bleak
moon and ominous thoughts crept into my mind as I looked up to
the threatening dome of the sky. Clenching my teeth, I continued
wading through the grey storm. Some trees were standing grimly
alongside the road, deprived of all their leaves.
I quickened my pace as the warm, yellow lights of my house
penetrated the grey curtains of rain. When I opened the door, a
thick blanket of warm air seemed to wrap itself around me, but
the ill cold had nested itself deeply into my body. The hot air
only managed to warm the surface of my stiff limbs, and it could
not touch the icy fist that had clenched my heart. I entered my
room and took off my soaked jacket. When I was drying my hair
with a towel, I noticed the small envelope lying on my desk.
I dropped the towel immediately as I noticed the handwriting on
the envelope. The frail but gentle handwriting was unmistakably
hers. Rays of hope penetrated the dark regions of my mind when I
opened the envelope. After reading the sweet words, the cold fist
seemed to loosen its grip, but I was too numb to really
understand the words and blankly, I slipped the paper back into
the envelope. Then I noticed it.
I slowly became aware of a very faint smell that woke me up from
a cold trance. Grabbing the paper again, I held it close to my
face and the enchanting smell reached me. She must have left it
behind unintentionally as it was very weak. But it had a very
powerful effect on me. It spread itself through my body,
expelling the cold with its relishing touch. Life started flowing
through me as the sinister clouds left my mind and a smile formed
itself upon my lips. I heaved myself upright and threw the malice
from me and sighed deeply, driving the last bits of cold from my
being. Joy filled my heart as I beheld the picture placed on the
shelf above my desk. Then I turned the paper and read the closing
words:

'Veel liefs,

Alida'

****

Sorry 'bout this, but I was just enormously inspired as the
above is based on a real experience and I just had to let it out.
Anyway, I was going to tell you all about the formatting of
diskettes in machine code.
Much has been said about the formatting of diskettes, and I just
like to add my thing to it. I will tell you how to format
diskettes in machine code in such a way that you can use it in
GfA BASIC.
I think every program that can save files should at least have
an option to format a diskette. I mean nothing is more
frustrating then when you find out you don't have one diskette
left with enough space on it to save the great thing you just
made. Now formatting disks is quite easy and would be nice to
write a small, compact routine that does the job. Nothing is
better that some good machine code in these cases.
I wrote a routine when I reprogrammed the ST NEWS format disk
option. I decided to do it in machine code because I just like
programming in machine code and I thought it would be nice to do
it. Well, HOW do you do it then?
Lucky for us programmers, the designers of the TOS operating
system have included some XBIOS routines that do all the
difficult things. All that left to us is the creating of a
bootsector and the loop that formats 80 tracks. There is nothing
more to it.

We need some control over our routine from GfA. We need three
parameters: the number of sides, the format buffer (more on this
later) and the drive we want to format (A or B drive). So we
construct an array to hold these three parameters:

Dim Parm%(2)
Let buf$=Space$(8192) ! 8 Kb buffer
Parm%(0)=1 ! 0=single sided, 1=double sided
Parm%(1)=Varptr(Buf$) ! address of buffer
Parm%(2)=0 ! 0: drive A, 1: drive B

First we format all 80 tracks of the floppy using the Xbios(10)
routine (flopfmt). This routine formats one track. It needs
several parameters:

Virgin: default value being written in sectors. Zero is
fine
Magic: has to be $87654321
Interleave: we'll keep it normal, so 1
Side: 0 or 1
Track: track # to be formatted
Spt: sectors per track. Normally 9
Dev: drive number, 0=A, 1=B
Filler: unused longword
Buffer: scratchpad for routine. must be at least 8Kb long

So the first thing we do is build a loop that call this routine
for each track to be formatted.

After formatting all tracks, we need to construct a bootsector.
The bootsector is the first sector of side 0 and contains some
crucial information about the way the disk is formatted. There is
an Xbios routine that can construct a nice bootsector, ready for
us to write to disk. It is Xbios(18), 'protobt'. It needs some
parameters:

execflag: this will determine wheter the bootsector is executable
or not. 0 means not exectable, 1 means executable and
-1 means that nothing will be changed.
disktype: 2 =80 tracks, single sided.
3 =80 tracks, double sided.
-1=don't change disktype.
serial: 24-bits serial number of diskette. If this is $01000000
the system will generate its own serial number.
buffer: address of 512 buffer containg bootsector.

In order to immunize the disk as efficiently as possible, we
need to make an executable bootsector. The bootsector code will
contain only and RTS instruction, so it will be totally harmless.
Also the first four bytes of the bootsector should be $6038001C.
This will make the bootsector immune to a lot of known viruses.
First, we will prepare a bootsector containing this information.
Then we will call the Xbios(18) routine, and then we will write
the bootsector to the floppy using the Xbios(9), 'flopwr'
routine. After doing all this, the disk will be formatted and
ready to use!

Well, time for some machine code!

format: move.l 4(sp),a0 ! get address of parameters
move.w #79,d5 ! 80 tracks
move.l (a0),d6 ! get #sides
move.l 4(a0),a6 ! format buffer
move.l 8(a0),d4 ! device (drive A or B)

loop: move.w d6,d7 ! d6=sides
loop1: bsr frmt ! format track
bne error ! something went wrong
bsr mess ! inform user
dbra d7,loop1 ! next side
dbra d5,loop ! next track

All tracks have been formatted now, and we have to make a
bootsector now. We use the format buffer for creating the
bootsector.

boot: move.l #$6038001c,(a6) ! immuzine factor
move.w #$4e75,$3a(a6) ! RTS in bootcode
move.w #1,-(sp) ! 1: executable
moveq.w #2,d0 ! 80 tracks single sided
or.w d6,d0 ! double-sided?
move.w d0,-(sp)
move.l #$1000000,-(sp) ! create random serial
move.l a6,-(sp) ! format buffer
move.w #18,-(sp) ! protobt
trap #14
add.l #14,sp

move.w #1,-(sp) ! 1 sector
clr.l -(sp) ! side 0, track 0
move.w #1,-(sp) ! sector 1
move.w d4,-(sp) ! device
clr.l -(sp) ! filler
move.l a6,-(sp) ! buffer
move.w #9,-(sp) ! flopwr
trap #14
add.l #20,sp

error: rts

The format track routine, calls Xbios(10)

frmt: move.w #$0,-(sp) ! virgin
move.l #$87654321,-(sp) ! magic
move.w #1,-(sp) ! interleave
move.w d7,-(sp) ! side
move.w d5,-(sp) ! track
move.w #9,-(sp) ! sect./track
move.w d4,-(sp) ! device
clr.l -(sp) ! filler
move.l a6,-(sp) ! buffer
move.w #10,-(sp) ! flopfmt
trap #14
add.l #26,sp
tst.w d0
rts

This will inform the user about what's going on. A message will
be put on the screen telling you about which track and side are
being formatted.

mess: move.w d7,d0 ! side in D0
add.b #'1',d0 ! make ASCII digit
lea side(pc),a0 ! addres to put side
move.b d0,(a0) ! store it
move.w #80,d0 ! 80 tracks
sub.b d5,d0 ! tracks count 80 to 1
lea track(pc),a0 ! address to put track
cmp.b #10,d0 ! track# > 10?
bcc.s mess1 ! yes
move.b #'0',(a0)+ ! no, first digit a '0'
bra.s mess2 ! put next digit
mess1: divs #10,d0 ! divide by 10
move.b d0,d1 ! result in d1
add.b #'0',d1 ! make ASCII digit
move.b d1,(a0)+ ! store it
swap d0 ! get rest
mess2: add.b #'0',d0 ! make ASCII digit
move.b d0,(a0) ! store it
movem.l a0-a1/d0-d1,-(sp) ! save registers
pea message(pc) ! address of message
move.w #9,-(sp) ! prline
trap #1
addq.l #6,sp
movem.l (sp)+,a0-a1/d0-d1 ! restore registers
rts

message: dc.b 27,'Y00' ; cursor to top of screen
dc.b 'Formatting side '
side: ds.b 1
dc.b ' track '
track: ds.b 2
dc.b 0

Well, that's about it. You might have wondered why I took all
the trouble of programming it in machine code. I think it is just
fun to write interesting stuff like this in machine code instead
of GfA BASIC. It is also more compact and efficient.

The source of this little routine can be found in the PROGRAMS
folder on this ST NEWS disk. Assemble it to a .TOS file. Then
BLOAD it into a string variable of GfA BASIC. Create the
parameter table as described above and call it like this:

M%=Varptr(Mc$)
E%=C:M%(L:Varptr(Parm%(0)))
If E%<0
Error E% occured
Endif

Fine. Have fun programming and keep on using the ST!

Disclaimer
The text of the articles is identical to the originals like they appeared in old ST NEWS issues. Please take into consideration that the author(s) was (were) a lot younger and less responsible back then. So bad jokes, bad English, youthful arrogance, insults, bravura, over-crediting and tastelessness should be taken with at least a grain of salt. Any contact and/or payment information, as well as deadlines/release dates of any kind should be regarded as outdated. Due to the fact that these pages are not actually contained in an Atari executable here, references to scroll texts, featured demo screens and hidden articles may also be irrelevant.