TO THIS BOOK
If you are familiar with machine language, commented source code, and
hexadecimal numbers, you probably won't need to read this appendix. On
the other hand, if you don't know or are new to machine language — perhaps
some of the information here will help.
A knowledge of machine language is important to grasping the sense of the DOS since it is written in machine language. However, we will briefly cover some of the fundamentals, as they relate to the book, in the hope that this might be a starting point. One of the functions of this book is to reveal the inner workings of Atari DOS. A benefit of knowing how it works is that you are able to change it to suit yourself, to customize it.
First we'll examine the meaning of the various fields of information which are in the source code (page 59 on). Then, after a brief look at how to deal with hexadecimal numbers, we can make a modification to DOS step-by-step to show how it's done.
The book is divided into two sections: roughly the first half is a series of descriptions of the major subroutines of the disk operating system. The latter half is a commented source code of the DOS. In order to better understand what you can accomplish with all this information, we can set up a problem and solve it using the book.
What's “Commented Source
We'll change the DOS so that we could type in a disk command using lowercase letters. Unfortunately, the D: must be in uppercase, the program which makes this decision is in ROM and we can't get at it and change it. The rest of the command can be in lowercase, though, after we make our change to the DOS in RAM. After fixing it, any routine that uses the disk will accept lowercase as in D: open.
Before getting into the details of the modification there is some important preliminary information. What, for example, is “commented source code?”
Machine language differs in several respects from BASIC. When you write a program in BASIC, you never see how it looks to the computer. Instead you see something like this:
10 FORI=1 TO 100
20 NEXT I
This delay loop just creates a brief pause
in a program. If you RUN the above, the computer handles the problem of
translating the BASIC words into machine language. Anything the computer
does must be translated into machine language (ML). Translating (or interpreting)
a BASIC program takes place during the RUN of the program — that's why
BASIC is so slow compared to ML.
By contrast, ML is translated before it is RUN. Programming ML is done in two stages: 1. writing the source code and then 2. assembling it into object code. The computer does most of the drudgery of this because most ML is written by using a program called an assembler which handles many of the details. Some assemblers are so complex that using them can seem almost like programming in BASIC.
Here is how you might program the above example delay loop when using an assembler:
1000 LDY #64 ; SET COUNTER TO 100
1001 LOOP DEY
1002 BNE LOOP
Probably the most peculiar thing about this,
to the beginner, is how 64 stands for 100 (it's hex, we'll get to it in
a minute). The line numbers could be BASIC, but the instructions are 6502
mnemonics (memory aids). LDY means to load the Y register with 100 (decimal).
The next line is named (labeled) “loop” because assemblers don't say GOTO
1001. Instead, they use convenient names. In any event, the Y register
is decremented by DEY, it's lowered by one. So each time the program cycles
through the LOOP address, it will lower the counter one. Finally, the instruction
at 1002 says, Branch if Not Equal (to zero). In other words, GOTO LOOP
if Y hasn't yet counted down to zero. When Y reaches zero, the program
will continue on, following whatever instruction is in line 1003.
After the above program is written, though, it still cannot be RUN. There is the second step, the creation of object code (executable), the assembly process.
You tell the assembler to assemble this program. The result of that is an additional two “fields” (zones). Above, we have five fields: line number, label, mnemonic (instruction), operand (the #64), and a comment field which is the equivalent of BASIC REM statements. There will soon be a total of seven fields.
After assembly, the two new fields are the addresses and the object code (expressed as hex bytes). By the way, BASIC always assigns its programs a starting address in memory, but, in ML, the programmer must make this known to the assembler. It's not the computer's decision. Assume the computer were told to assemble the above example at address $2000 (this would be 8192, in decimal). The dollar sign means that a number is a hex number. The labels, mnemonics, and operands would be translated into object code and put into the computer's memory. As you'll see in the second half of this book, a printout of completed assembly looks like this:
2000 A000 1000
LDY #64 ;SET COUNTER TO 100
2002 88 1001 LOOP DEY
2003 DOFF 1002 BNE LOOP
Before concluding this brief overview of some fundamentals of machine language, we should explain how to read the numbers in the source code listings.
100 DIM H$(23),N$(9):OPEN#1,4,0,”K:”
130 GRAPHICS 0
140 PRINT “PLEASE CHOOSE:
150 PRINT “1 — Input HEX & get decimal back
160 PRINT “2 — Input DECIMAL to get hex bac
170 PRINT:PRINT “==>“;:GET#1,K
180 IF K<49 OR K>50 THEN 170
190 PRINT CHR$(K):ON K—48 GOTO 300,400
310 PRINT “HEX”;:INPUT N$:N=0
320 FOR 1=1 TO LEN(N$)
330 N=N*16+ASC(H$(ASC(N$(I))-47))-64:NEXT I
350 PRINT “$“;N$;”=”;N:PRINT:PRINT:GOTO 140
410 PRINT “DECIMAL”;:INPIJT N:M=4096
420 PRINT N;”$”;
430 FOR I=1 TO 4:J=INT(N/M)
440 PRINT H$(J+1,J+1);:N=N-M*J:M=M/16
450 NEXT I:PRINT:PRINT:GOTO 140
This program will turn a decimal number into
hex or vice versa. Hexadecimal is a base 16 number system, where decimal
is base ten. This means that you count from zero to fifteen before going
to the next column. For example, you count up zero one two. . . until you
reach nine in decimal. Then you go to the next column and have a one-zero
(10) to show that there is one in the “ten's column” and zero in the “one's
In hex, what was a “ten's column” becomes a “sixteen's column.” In other words, the symbol “10” means that there is one sixteen and zero “ones.” So, the decimal number 17 would be written in hex, as $11 (one sixteen plus one one). The decimal number 15 would, in hex, be $0F. After nine, we run out of digits, so the first few letters of the alphabet are used: A = 10, B = 11, C = 12, D = 13, E = 14, and F=15.
This explains how to “read” hex numbers if you don't want the program above to do it for you. The number $64 is decimal 100 because there are six 16's and four one's. 6 X 16+4= 100.
Addresses can be larger than two digits, up to a maximum of four. You might see an address such as $11F7 in the listings. The third column is the 256's and the fourth column is the 4096's. So to find out what this address is in decimal, you can multiply 7 X 1, 15 X 16, 1 X 256, and 1 X 4096. And add them all together.
A quicker way is to find out the first two, (15 x 16+7=247) and then multiply the second two by 256. It comes out the same. The second two would be $11 (17 in decimal) so 17 x 256 + 247 = 4599. It might be easier to just use the BASIC program to make the translations until hex becomes more familiar.
Making A Modification
Now that you have the entire source listing of DOS 2.0S, you can customize it to fit your needs.
You may have felt restricted by the limitations on file names. A file name can consist of eleven characters: up to eight characters plus an optional three-character extension. The first character must be from A-Z; subsequent characters can be from A-Z or 0-9. That's it. No punctuation. No imbedded spaces. No lowercase.
By changing only two locations in the file name decode section of DOS, many more characters are permitted. We will modify DOS to accept any ASCII characters in a file name except character graphics and inverse video. Additionally, the filename can start with a number (e.g. “D:3-D”). Unfortunately, there is no foolproof way to allow imbedded spaces such as “D:TIME OUT”.
The following fragment of code checks to see that a character of the file name falls in the range of A-Z. If the character is less than (carry clear) 65 [ASC(”A”)] or greater than or equal to (carry set) 91 ASC(”Z”) + 1], then the test fails. All we do is change the check for “A” to a check for “!“ (its number in the code is one greater than “space”), and the check for “Z” + 1 to “z” + 1 (lowercase z).
Included in this range of 90 characters are the numbers (48-57) and all punctuation. Since we start with 33, “space” is excluded. It is possible to permit imbedded spaces, but the file would then be inaccessible in certain situations where a space is used as a delimiter. You can allow it at your discretion, or even permit the entire (almost) ATASCII character set to be used by changing the limits to 0 and 255.
We change this to:
The changes can be made in BASIC with POKE 3818,33:POKE 3822,123 or change hex locations $0EEA to $21 and $0EEE to $7B. The section of code we're modifying is located between source line numbers 4072 through 4193. Remember to rewrite the modified DOS to disk with WRITE DOS FILES (Menu selection “H”) if you want your change to be permanent.
Other equally simple changes are also possible. You could change the wild-card character (“*”) to any other character by changing location $0EC7 to the desired character. A more ambitious task would be to increase the maximum file name length.
This brings up a final point — software compatibility. For example, if you changed the wild card character to “@,“you couldn't run any previous programs that assume “*” as the wild card character. Our change is less dangerous — if you allow lowercase file names, the unmodified DOS won't be able to access it, although it will look fine on the directory. This change has not been exhaustively tested for conflicts, so we can't guarantee its usage. Nevertheless, it seems quite useful and shows that some customizing can be accomplished with a few simple changes.
When experimenting, always keep a backup copy of your valuable disks in case something should go awry.
100 REM CHANGE DOS PROGRAM
110 REM FOR DOS 2.0S ONLY
120 REM CHANGE LOW RANGE CHECK FROM
130 REM 65 TO 33. THIS ALLOWS
140 REM ANY CHARACTER (EXCEPT
150 REM GRAPHICS AND INVERSE VIDEO)
160 REM TO START A FILENAME, INSTEAD
170 REM OF ONLY A THROUGH Z.
180 REM 0EE9 C941 CMP #'A
190 REM 0EE9 C921 CMP #'!
200 POKE 3818,33
210 REM CHANGE HIGH RANGE TO EXTEND
220 REM UP TO ASCII "Z"
230 REM (LOWERCASE Z)
240 REM 0EED C95B CMP #$5B
250 REM 0EED C97B CMP #$7B
260 REM POKE 3822,123
270 REM NO NEED TO CHANGE NUMERIC
280 REM CHECK SINCE IT IS NO
290 REM LONGER EXECUTED, THANKS
300 REM TO THE ABOVE CODE.
Care is necessary when making customizations. Only make the changes to a copy of your DOS — not the original “system master.” (You shouldn't be able to do this anyway, since the disk is “write-protected,” but better safe than sorry.) Remember that any files SAVEd with your custom DOS will probably not be compatible with the original, unchanged DOS. Alternation of the DOS can have unpredictable effects; we urge caution and cannot accept any liability for software or hardware damage incurred through the use of this book.
Things To Look Out For
These modifications could make a customized DOS incompatible with the original, unmodified DOS 2.0S:
1) File name changes (such as allowing lowercase, or increasing the length)Keeping these suggestions in mind, here are some ideas for modifications. You may need to type in and re-assemble (with your insertions) the entire DOS when making certain modifications.
2) Changes to DOS file structure (such as using a different “linking” system)
3) Removing error-checks. These built-in traps insure disk integrity and reliability. When you alter one, you could risk muddling one or more files. For example, if you allow an automatic “wild-card” feature, where an asterisk is assumed at the end of a file, it could cause havoc when performing a SCRATCH, RENAME, or UPDATE operation. Another example is removing some of the qualifications for “burst-I/O.” Remember that a lot of thought went into each design consideration.
1) Adding a STATUS check before a disk access. Have you ever noticed how long the drive will grind away when no disk is inserted? You can query the disk for its status, and even add a “Drive not ready” error message if the drive door is not closed or a disk is not inserted. Check your DOS manual for details.Remember that some of this is risky business. Keep backup disks for any disk you are “experimenting” with. That way, you should lose no important files.
2) Adding Disk Utility commands. These would be additional functions performed by the FMS, keyed to the “special command.” Some of the tasks performed by the Disk Utility Package could be a part of the DOS kernal, such as LOAD and SAVE binary files. You could even implement new commands such as “relative file” support, where you only give the DOS a “record number” to randomly access a file. The file could be divided into records of any length.
3) Allocate more sectors for the directory, thereby extending the maximum amount of directory entries.
4) Add a disk name and/or disk I.D. number (serial number?) to the disk (maybe on sector 720). It could even print out with the directory.
5) Given the extra “unused” bytes in the file name, add a byte for file type, such as program, data, object code, etc., and have it printed out with the directory, making it easy to identify files without having to use the extension. This would be hard to interface with software, however.
The publishers and authors of this book disclaim any responsibility for errors or problems caused by modification of Atari DOS 2.0s.
Return to Table of Contents | Previous Chapter