ROM Computer Magazine Archive ROM ISSUE 9 — DECEMBER/JANUARY 1985 / PAGE 44

Examining Atari DOS
by Bob Cockroft

    The following is an in depth explanation of how the disk drive manipulates data. In order to accurately display a number of concepts, I wrote 2 utilities: the File Finder and the Disk Modifier. Both of these programs are listed at the end of the article. Because I will be constantly referring to them, it would be helpful for you to type them in now.
    The disk is divided into three data organizing structures. The first and smallest structure is called the byte. This unit is used as a storage slot for one 8 bit number. In order to hold relatively large amounts of data, the disk contains thousands of these bytes. The second data organizing structure is the sector. It consists of 128 continuous bytes, positioned as a group at one specific location on the disk. Sectors are grouped into 40 concentric rings around the center of the disk. Being the last data structure, these rings are called tracks. Each or the 40 tracks contain 18 sectors for a total of 720 sectors per disk. Sectors 1 through 18 use the outermost track, while sectors 712 through 720 use the innermost.
    When a disk is being formatted, the head will move sequentially through the tracks, reorganizing the sectors. The DOS will then reserve a number of sectors for particular tasks. Two important reserve sections are the Disk Boot Records, and the Table of Contents.

Disk Boot Record

    The Disk Boot Records are stored in sectors 1 through 3. When the Atari computer is powered-up, the operating system reads sector 1, to receive its initial instruction. It is here the computer encounters the Disk Boot Record. Byte 0 of the Disk Boot Record contains no instruction(see Table 1 below). This byte is a boot flag that always equals zero. Byte 1 tells the computer how many consecutive sectors it is to read. Under most circumstances this byte has a value of `3' to represent the 3 sectors of the Boot Record. Bytes 2 and 3 specify the memory address where the Boot Record is to be stored. This value is set to $700 hex (1792 dec). Because the least significant byte always uses the first address, bytes 2 and 3 will have values of `0' and `7' respectively.

example: 1792 = 0 + 7 * 16^2

    Therefore, because of the instructions given in the first 5 bytes of the Boot Record, when the computer is powered-up, the operating system will read the first 3 sectors and store them into memory address $700 hex (1792 dec). This is called the first stage of the boot. A list of the next few bytes of the Boot Records are listed below.


Table 1
Disk Boot Record

Byte
 
Hex
Value
Description
0
700
   0
Boot flag always zero
1
701
   3
No. of consecutive sectors to read
2
702
   0
Boot Record memory
3
703
   7
address
4
704
 64
Initialization address
5
705
 21

6
706
 76
JMP XBCONT:Boot
7
707
 20
continuation
8
708
   7

9
709
   3
Max number of OPEN files
10
70A
   3
Max number of Disk Drives
11
70B
   0
Unused
12
70C
124
Buffer allocation
13
70D
 26
address
14
70E
   1
DOS flag: a non-zero indicates the disk contains a DOS file. One indicates a 128 byte sector disk, two indicates a 256 byte disk.
15
70F
   4
Points to the first
16
710
   0
sector of the DOS. SYS file
17
711
125
Sector link byte - points to the next sector to be read. It contains a zero when the end of the file has been reached
18
712
203
The start address of
19
713
   7
the DOS. SYS


    The second stage of the boot loads the File Management System of the DOS into memory. Most software does not use the second stage of the boot. The first byte of sector 1 would have a sector count that represented the entire program. In this way, software can be loaded before the computer is able to perform any other function.

Directory

    The directory is the area on the disk the computer designates for organizing the files. Stored on 9 sectors (360-368), this structure represents the single most important part of the disk. The directory can be divided into two sections: Table of Contents and File Directory.
    The Table of Contents is used by the DOS to keep track of which sectors contain file data and how much free space remains. The file structure of the entire disk is squeezed on to sector 360. To examine the Table of Contents, display sector 360 in hexadecimal form with the Files Finder. (see below)


Table 2

   bit:
HEX
1
1
2
3
4
5
6
7
00
02
C3
02
C1
01
00
00
00
08
00 00 00 00 00 00 00 00
10
00 00 00 00 00 00 00 00
18
00 00 00 00 00 00 00
00
20
00
00
00
00
00
00
0F FF
28
FF FF FF FF FF FF FF FF
30
FF 00
00
00
00
3F
FF
00
38
7F
FF FF FF FF FF FF FF
40
FF FF FF FF FF FF FF FF
48
FF FF FF FF FF FF FF FF
50
FF FF FF FF FF FF FF FF
58
FF FF FF FF FF FF FF FF
60
FF FF FF FF 00 00 00 00
68
00 00 00 00 00 00 00 00
70
00 00 00 00 00 00 00 00
78
00 00 00 00 00 00 00 00

    The bytes 1 and 2 specify the maximum number of sectors that are able to be used for data storage. These bytes use a hi/lo form and will normally contain a value of $2C3 hex (707 dec.). Bytes 3 and 4 indicate the number of free sectors remaining on the disk. On an empty disk these bytes will have a value of $2C3 hex (707 dec.), on a full disk they will have a value of $00. Each bit, from byte $0A to $63 corresponds to a particular sector. For example, byte $0A represents sectors 1 and 2, while byte $63 represents sectors 711 through 719. Sector 720 is not used by the DOS so that a buffer zone exists between the last usable sector and the end of the disk. Initially these sector bits are set to `1'. But as a file is stored on the disk, the bit corresponding to the sector where file is written will be given a value of `0'. When a file is deleted, the bits are set back to '1'
    By referring to the Table of Contents, the DOS is always able to determine which sectors are currently being used. This is of critical importance, particularly

  F = Free    U = Used
Sector A A+1 A+2 A+3 A+4 A+5 A+6 A+7
Fr:/Usd F  F   U   F   U   F   F   F

bit:   0   1   2   3   4   5   6   7

value::1 : 1 : 0 : 1 : 0 : 1 : 1 : 1

  235 =1 + 2 + 0 + 8 + 0 + 32 +64 +128


Therefore: this byte will have a value of 235

when the computer is storing files on the disk. You may have noticed that even on a newly formatted disk, sectors 1,2 and 3 (bits 6,5,4 of byte OA$=0F$) always are occupied. The reason for this is that these first 3 sectors contain the Disk Boot Record. In addition, a group of 9 bytes, beginning at byte $37, are also permanently used. These by tes correspond to the sectors that are occupied by the directory (sectors 360-368).
    The second component of the Directory is the File Directory. Stored in sectors 361 through 368, this data structure contains a list of all the files on the disk along with their status, starting sector and size. Examine sector 361 with the File Finder while in character mode. If all is working correctly you should see the names of some, or perhaps all the files on your disk. Notice that file data is contained in an entry of 16 bytes. The first letter of the filename begins on the 6th byte of the entry, while the extension starts on the 12th. If any of the character bytes of the filespec are unused, they are left blank. The File Directory can use 8 sectors of 128 bytes a piece, for a total of 1024 bytes(8*128). Because each file uses 16 bytes, the File Directory can hold a maximum of 64 filenames(1024/16). Re-examine sector 361 with the File Finder, only this time use the hexadecimal mode. The first byte of each 16 byte entry is the status flag for the file. An unlocked file will set the status flag to $42(66 dec.), whereas a locked file has a status of $62(98 dec). If a file were deleted it would have a status of $80(128 dec). The second and third bytes of an entry display the file size in sectors. The fourth and fifth bytes point to the first sector of the file.

16 byte configuration

byte no. 1  2  3  4  5  6  7  8 ...
Value  : 42:01:00:04:00:54:45:53:..cont

Status: = $42 = Unlock file;byte 1
Size:
= $01 = 1 sector ;byte 2 & 3
First Sector:
= $04 = sector 4 ;byte 4 & 5

Bytes 6 through 16 contain the filename

Linking and File Organization


    If the Table of Contents of a disk which has had a large number of file additions and deletions were seen, the programs would appear to be quite fragmented. One file could start on sector 25 but then jump to sectors 30, 50, and 275. Because of `linking', files do not need to use sectors in numerical order. As a result, even sectors isolated by other files can be used to store data. When a new file is SAVEd, the DOS creates a corresponding 16 byte entry in the Directory. This entry includes the filename and status($43). The DOS will then search the Table of Contents for a free sector. Once a free sector has been found, its number is stored in the fourth and fifth bytes of the 16 byte entry as the starting sector of the file. (see below)

16 Byte Entry

Values in Hexadecimal

Byte no. 0  1  2  3  4  5  6  7    ...
Value   :43:00:00:09:00:14:49:15:..cont
     status:     :first:  start of
           :size :sector: filename
                    ^
                    :
                    ^

The first sector of this file
is sector 9


    Data is then stored on the first 124 bytes in the start sector. The 3 remaining bytes(125 - 127) are used by the DOS to direct or `link' itself to the next sector the file will use. The low 6 bits of byte 125 indicate the file identification number. The DOS uses this to determine which file a sector belongs to. The value of the indentification number represents the position the file has in the directory(0-63). Should the value not correspond to the order in which it appears in the File Directory, the DOS will produce an error. The two high bits of byte 125 and all of byte 126 are reserved so that they can point to the next sector of the file. The DOS will then scan the Table of Contents for the next free sector. Once a free sector has been located, its number is stored in bytes 125 and 126 of the previous sector used for data storage. In this way, each sector of a file is linked to the next. What makes the sector link is usually the way in which it stores data in 2 bytes. Most 2 byte configurations store data in lo/hi form, in other words, low byte first, and high byte second. For example, $600 hex would be stored as follows:

Memory location Value
1536 0    low byte
1537 6    high byte

    The sector link does not use 2 bytes in this manner. Instead, the value is stored in a modified high byte/ low byte form. Byte 126 is used as the low byte value, whereas bits 6 and 7 of byte 125 are used as the high values. When the last sector of a file has been reached, the sector pointers will indicate this by having a value of `0'. The last part of the sector link, byte 127, contains the number of bytes used in that sector. In most situations this byte will have a value of $7D(125 dec). The only exception would be the last sector of a file, where it is probably only partly filled. Only when the user closes a file will this partial sector be filled. A diagram of the sector link operations is given below.


Decimal version

Byte
No.
  Value
;Comment
125
32($20) ;32th Directory file
126
25($18) ;Sector 25 is the next
;sector in the file
127
125 ($7D) ;125 of bytes used
;from the current sector

    Use the File Finder to examine sectors that have a file stored on them. The link bytes(last 3 bytes) of any of the sectors you examine should have a display similar to the hexadecimal output given below. In addition, compare the values of the decimal version(above) with the hexadecimal version(below).


Hexadecimal version

bit:
HEX
0
1
2
3
4
5
6
7
00
C3
04
09
A0
C3
45
40
01
08
00
00
AA
D0
01
10
BF
25
10
35
99
63
A5
C2
00
05
75
18
21
56
5D
FF
FF
EF
A0
A9
20
10
00
01
12
15
A3
A2
05
28
07
05
A3
C2
04
47
59
84
30
38
FF
EA
47
36
84
30
38
38
48
57
95
04
57
48
04
48
40
FF
A4
47
47
39
E4
D3
FF
50
47
12
20
03
14
69
48
04
58
E6
48
FF
EA
A9
47
A2
47
60
47
07
35
13
03
93
03
37
68
E4
FF
AA
33
37
C3
B4
47
70
B4
47
A3
47
99
87
44
34
78
47
A9
10
48
72
20
18
7D

these
last 3 bytes
are the link bytes
    After the disk file has been closed, The DOS will write an up-dated version of the Table of Contents, which includes all the newly occupied sectors. It then up-dates the 16 byte File Directory entry by changing its status to $42(normal status), and by storing the file size(in sector) into bytes 1 and 2.(see below)


16 byte entry (values in HEX)
Byte no. 0  1  2  3  4  5  6  7 ...
Value   :42:05:00:09:00:14:A9:15:..cont
        :  :     :     :
     status:     :first: start of
           :size :sector: filename


    When a LOAD command is made, the DOS will first search the File Directory for the 16 byte entry of the specified file. Once it is found, the DOS will use bytes 3 and 4 to determine its first sector. Once the data has been read off this sector, the link bytes will point the DOS to the next sector of the file. This process of `linking' is repeated until all the sectors of the file have been read.

Types of Files

    The 3 main methods in which data is stored on the disk are untokenized, tokenized, and binary systems. An untokenized file is created whenever a file is stored on the disk by using the LIST command. This type of system does not use any method of reducing its size. Because a file of this type is stored in its original format, it will appear the same on the disk as it did while in the computer. Create an untokenized file and then use the File Finder's character mode to examine the sectors of this file. The file will appear recognizable. You should be able to read it off the screen as you could under normal circumstances.
    The tokenized file is created whenever a file is stored on the disk using the SAVE command. This type of arrangement uses a reducing system to modify the file so that it can be loaded into the computer more rapidly. As a result, the file appears, at best, barely recognizable when examined by the File Finder. In fact, only the PRINT and REM commands appear normally.
    The last main type data organization system is the binary file. This type of storage method is generally used in conjunction with the DOS's BINARY LOAD/ SAVE options in order to transfer machine code between the disk and memory. Create a binary file, and store it on the disk. Because a binary file does not need to be a workable machine language routine, use the BINARY SAVE option to store any portion of RAM. Once this is done, use the hexadecimal mode of the File Finder to examine the first sector of this file. Binary files start with two bytes of $FF. The next 2 bytes store in lo/hi form, the start address of the file. The 2 bytes that follow these store in lo/hi form the end address. When a binary load is completed, control is passed to the DOS menu. However, after the loading sequence, the DOS can be forced to pass control to any address by storing that address in locations $2E0 and $2E1. For example, if your binary file started a $600, store a $00 into address $2E0 and a $06 into address $2E1I. As a result the BINARY LOAD option will both load and run the file.

Sector Modifing Utility

    If you have accidentally erased a file that you needed, this utility may solve you problem. By making a simple modification to the File Directory, it is possible to retrieve a deleted file. When a file is erased, the DOS performs two functions. The first is to go to the Table of Contents, and set the bits that correspond to sectors used by the file, to `1'. All this does is tell the DOS that it is now able to use these sectors. The second function is to set the file's status flag to $80(delete mode). The significant thing, is that despite telling the DOS to delete, the file remains on the disk. Assuming programs that were stored after the original file was erased did not write over the deleted sectors, retrieving a file is simply a matter of finding it, and changing the status flag. This type of byte modification is exactly what the following program does. This would be a good time to type-in, or if you have the disk version, LOAD the Sector Modifier. Soon after RUNing this utility, it will ask you to identify the sector that is to be changed. Once the program has this input, the sector you identify will be loaded into the memory(1664-1792 dec) and a new screen containing 4 options will appear. The first two of these options control whether the stored sector will be displayed in hexadecimal or character form. The character display is useful when examining File Directory sectors because the filenames can be read off the screen. However, for the majority of applications, the hexadecimal display is the most convenient. The third option enables the user to choose another sector to examine. The fourth option is where any disk modification occurs. It does much the same thing for the disk as the POKE command does for memory. The value of any individual byte on the disk can be altered. All the utility will ask for is the byte number(relative to the start of the sector) and the new value. The modification to the sector is not made initially. The new value is POKEd into the memory locations that contain the copy of the sector (16641792 dec). This memory held sector is then stored on the disk over-top of the old sector.

Disk Routines

    In order to make the Sector Modifier I had to write a machine language subroutine to LOAD data from the disk, and another to SAVE data to the disk. Since that time, I have used these routines in a number of other machine language programs that require data transfer. Many programs, especially adventure games, can be enlarged by using the disk to storage surplus data. For example, the computer could have access to a number of scrolling map routines by storing the data for each display on disk. When a particular map is required, its data can be LOADed to computer. As a result, programs that do not need quick access to all of its subroutines are not confined to the computer's RAM limitations. By using many disks, programs can be as large as desired. For this reason, machine language subroutines that LOAD and SAVE are quite useful if applied effectively. At the same time, routines of this type are simple to make.
    Many of the addresses that are used to control the disk drive are located from $300 to $3013 HEX (768 to 779 dec). In order to provide a quick reference to the relevant addresses, I have listed them below.


Location

HEX
 
DEC LABEL ;FUNCTION
301
769
DUNIT ;Device number
302
770
DCOMND ;No. of operation
304
772
DBUFLO ;Address of the source
305
773
DBUFHI ;destination of data
30A
778
DAUX1 ;Disk sector number
30B
779
DAUX2 ;for read and write
;operations


    There are 5 steps in making a LOAD or SAVE subroutine. First, before any disk operation can occur, the drive number must be specified. This is done by storing the disk drive number at address $301 DUNIT(769 dec).
    The second step is to indicate what operation the disk drive is to perform. The disk operation is controlled by address $302 DCOMND (770 dec). This location reacts to values that correspond to specific commands. (see below)


Command
 
dec hex
Read (LOAD) 82
$52
Write (SAVE) 87
$57
Download 32
$20
Format 33
$21
Put 80
$50
Read spin 81
$51
Status 83
$53
Read address 84
$54
Verify sector 86
$56


    For example, if you wish to LOAD data from the disk to the computer, you would store `82' into $302(DCOMND). Conversely, if you wished to SAVE data, a `87' would be stored here. The same system is used for the rest of the commands.
    The third step is to decide what RAM address the data is to be transferred, either to or from. When the DCOMND ($302 hex) is given a Read(LOAD) command, the DOS refers to locations $304/ 305(DBUFLO/HI) to see where the disk data is to be stored in RAM. This value, in lo/hi byte form, will be the start address of the data LOADed from the disk. Because the disk drive will only Read or Write a complete sector, only blocks of 128 bytes can be transferred at one time. For example, if DBUFLO/HI were given a value of 1536($600 hex), and the DCOMND were given a Read(LOAD) command, any data LOADed from the disk would be stored from 1536 to 1536 + 128($600 + $80). However, when the DCOMND were given a Write(SAVE) command, the DOS would refer to DBUFLO/HI to see which part of RAM is to be stored on disk. For example, if the DBUFLO/HI were given a value of $600, while DCOMND was in SAVE mode, RAM bytes 1536 ($600) to 1664 ($680) would be stored on disk. Therefore, the location in free RAM where disk data is transferred(to and from), is left to the programmer's discretion. Addresses $600 to $6FF usually make an excellent transfer buffer. In fact, the LOAD and SAVE subroutines use the upper portion of these addresses for this purpose. ($680-$6FF)
    The fourth step is to indicate to the DOS which sector to Read from or Write to. To do this, store the number of the sector in which you want to Read or Write into locations $30A/30B(DAUX1/2). As a result, when the DCOMND is given the Read(LOAD) command, the DOS will examine locations $30A/30B to determine which sector to LOAD data from. Conversely, when the DCOMND is given a Write(SAVE) command, the DOS will examine locations $30A/30B to determine which sector to SAVE data to. The DAUX1/2 does much the same thing for the disk as the DBUFLO/HI does for the RAM.
    The final step is to start the disk drive. This is simply accomplished by jumping to the Disk handler($E453). In the LOAD and SAVE routines this is done on line 220 with the JSR command.


00010  .LI OFF
00020  .OR $3A98      ;START ADDRESS
00022 ******************************
00024 *                            *
00025 * LOAD ROUTINE /MACHINE CODE *
00027 *                            *
00028 ******************************
00030 DUNIT .EQ $301  ;DRIVE NUMBER
00040 DCOMND .EQ $302 ;DISK OPERATION
00050 DBUFLO .EQ $304 ;SOURCE OF DATA
00060 DBUFHI .EQ $305 ;READ FROM DISK
00070 DAUX1 .EQ $30A  ;DISK SECTOR TO
00080 DAUX2 .EQ $30B  ;BE READ
00100 START LDA #1
OO110  STA DUNIT     ;SET UP DRIVE 1
00120  LDA #82       ;LOAD INDICATOR
00130  STA DCOMND    ;DISK OPERATION
00140  LDA #128      ;BUFFER ADDRESS
00150  STA DBUFLO    ;OF THE DISK
00160  LDA #6        ;SECTOR DATA
00170  STA DBUFHI
00180  LDA $600      ;SECTOR TO READ
00190  STA DAUX1     ;LO BYTE
00200  LDA $601
00210  STA DAUX2     ;HI BYTE
00220  JSR $E453     ;START DRIVE
00230  RTS           ;RETURN TO BASIC


00010  .LI OFF
00020  .OR $3E80       ;START ADDRESS
00022 ******************************
00024 *                            *
00025 * SAVE ROUTINE /MACHINE CODE *
80027 *                            *
00028 ******************************
00030 DUNIT  .EQ $301  ;DRIVE NUMBER
00040 DVOMND  .EQ $302 ;DISK OPERATION
00050 DBUFLO  .EQ $304 ;SOURCE OF DATA
00060 DBUFHI  .EQ $305 ;WRITTEN TO DISK
00070 DAUX1  .EQ $30A  ;DISK SECTOR
00080 DAUX2  .EQ $30B  ;WRITTEN TO
00100 START LDA #1
00110  STA DUNIT      ;SET UP DRIVE 1
00120  LDA #07        ;SAVE INDICATOR
08138  STA DCOMND     ;DISK OPERATION
00148  LDA #128       ;ADDRESS OF DATA
00150  STA DBUFLO     ;WRITTEN TO DISK
00160  LDA #6
00170  STA DBUFHI
00180  LDA $603       ;THE SECTOR NUMBER
00190  STA DAUX1      ;WHICH CONTAINS
00200  LDA $604       ;THE DATA
00210  STA DAUX2      ;HI BYTE
00220  JSR $E453      ;START DRIVE
00238  RTS            ;RETURN TO BASIC


100 REM *******************

105 REM *                 *
118 RUN * SECTOR EXAMINER *
120 REM *                 *
122 REM *******************
130 DIM CAQ$(2),KAN$(71),BHA$(113),CAR
$(16),NU(128),OL$(20)
140 GRAPHICS 1:SETCOLOR 2,16,1
I50 POKE 752,1
160 POSITION 4,7
170 ? CHRS(125):? #6;"Please WAIT"
180 POKE 752,0
190 GOSUB 1000
200 REM *
210 REM * DISK SUBROUTINE *
220 REM *
230 RESTORE 240:FOR Y1=1 TO 64:READ W:
KAN$(Y1,Y1)=CHR$(W):NEXT Y1
232 REM *
235 REM * LOAD DATA FROM THE DISK AS1
*
238 REM *
240 DATA 104,104,104,104,141,1,6,162,8
2
250 DATA 201,83,144,2,162,87,142,0,6,1
69,6,141,5
260 DATA 3,169,128,141,4,3,169,1,141,1
,3,174
270 DATA 0,6,142,2,3,104,141,10,3,172,
1,6,140,11,3,32
280 DATA 83,228,160,0,140,213,0,172,3,
3,140,212,0,96
290 CAR$="0123456789ABCDEF"
300 OPEN #1,4,0,"K"
310 REM *
320 REM * MAIN DISPLAY
330 REM *
340 GRAPHICS 0
350 ? CHR$(125)
360 ? ," DISK EXAMINER"
370 ? :? :? "Enter the Sector you Want
  to"
380 ? "examine.  Put a '$' before any"
390 ? "hexadecimal    entries."
400 ?
410 ? "for example:"
420 ? :? "$FA = Hexaecimal"
430 ? "250  = Decimal"
440 POSITION 2,20:? CHR$(156);:? "Sect
or #";
450 INPUT BMA$
460 REM
470 REM * HEX NUMBER CONVERSION *
480 REM
490 IF BHA$(1,1)<>"$" THEN GOTO 590
500 BHA$=BHA$(2)
510 IF LEN(BHA$)>3 THEN 1590
520 IF LEN(BHA$)=2 THEN BHA$(3)=BHA$(1
):BHA$(2,2)=BHA$(1,1):BHA$(1,2)="0"
530 IF LEN(BHA$)=1 THEN BHA$(3)=BHA$(1
):BHA$(1,3)="00"
540 IF ASC(BHA$(1,1)>64 THEN BHA$(1,1
)=CHR$(ASC(BHA$(1,1))-7)
550 IF ASC(BHA$(2,2))>64 THEN BHA$(2,2
)=CHR$(ASC(BHA$(2,2))-7)
560 IF ASC(BHA$(3,3))>64 THEN BHA$(3,3
)=CHR$(ASC(BHA$(3,3))-7)
570 TE=(ASC(BHA$(3,3))-48)+16*(ASC(BHA
$(2,2))-48)+256*(ASC(BHA$(1,1))-48)
580 G070 630
590 TRAP 620
600 TE=VAL(BHA$)
610 GOTO 580
620 GOSUB 1590:TE=-1:GOTO 580
630 OL$=BHA$
640 HAN=TE
650 REM
660 REM ** READ SECTOR **
670 REM
680 X=USR(ADR(KAN$),82,HAN)
690 IF X=1 THEN 720
700 POSITION 2,19
710 ? "BAD SECTOR ";HAN
720 IF X=1 THEN G0SUB 770
730 GOTO 440
740 REM
750 REM ** DISPLAY SECTOR **
760 REM
770 TE=INT(HAN/256):? CHR$(125)
780 ? "SECTOR # = ";HAN;
790 ? " ($";
800 CSH=TE
810 TE=INT(TE/16)+1
820 CAQ$(1,1)=CAR$(TE,TE)
830 TE={CSH-(TE-1)*16)+1
840 CAQS(2,2)=CAR$(TE,TE)
850 TE=CSH:? CAQ$;
860 TE=HAN-256*INT(HAN/256)
870 CSH=TE
880 TE=INT(TE/16)+1
890 CAQS(1,1)=CAR$(TE,TE)
900 TE=(CSH-(TE-1)*16)+1
910 CAQ$(2,2)=CAR$(TE,TE)
920 TE=CSH:? CAQ$
930 ? ")"
940 X=USR(ADR(BRH$),1536+128)
950 OL$=BHA$
960 POSITION 2,20:? CHR$(156);:? "Sect
or # or Characters 'C'";:INPUT BHA$
970 IF BHA$="c" THEN ? "CALCULATING...
one moment":GOTO 1140

980 GOTO 490
990 REM
1000 REM ** DISPLAY MEM IN HEX **
1010 REM
1020 DIM BRH$(200)
1030 RESTORE 1040:FOR G1=1 TO 163:READ
  W:BRH$(G1,G1)=CHR$(W):NEXT G1: RETURN
1032 REM *
1035 REM * RAM TO SCREEN SUBROUTINE A2
 *
1038 REM *
1040 DATA 104,104,133,229,104,133,228,
169,0,72,104,72,16,7,169,155,32,164,24
6,104,96,169,155,32
1050 DATA 164,246,104,72,162,0,142,10,
6,160,0,224,0,240,72,169,32,32,164,246
,224,0,200,63
1060 DATA 74,74,74,74,201,10,48,2,105,
6,105,48,32,164,246,224,0,208,44,41,15
,201,18,48
1070 DATA 2,105,6,105,48,32,164,246,22
4,0,208,27,104,72,168,185,128,6,200,22
4,0,208,16,104
1080 DATA 162,5,142,10,6,24,105,1,72,4
1,7,208,24,240,155,238,10,6,174,10,6,2
24,1,240
1090 DATA 183,224,2,240,32,224,3,240,1
66,224,4,240,162,224,5,240,203,224,6,2
40,163,224,7,240
1100 DATA 195,224,8,240,174,224,9,240,
142,224,10,240,194,104,72,224,0,208,16
0
1110 REM
1120 REM * CONVERT HEX TO CHARACTERS *
1130 REM *

1140 BR=PEEK(88)+256*PEEK(89)
1150 E=3
1160 XC=0:W=1
1170 XR=BR+126
1180 P1=PEEK(XR)
1190 IF P1>30 THEN HB=P1-23:GOTO 1210
1200 "8=P1-16
1210 P=PEEKCXR+l)
1220 IF P>30 THEN LB=P-23:GOTO 1240
1230 LB=P-16
1240 NU(W)=HB*16+LB
1250 W=W+1
1260 XC=XC+1
1270 XR=XR+3
1280 IF W=128 THEN 1330
1290 IF XC>7 THEN XC=0:GOTO 1310
1300 GOTO 1180
1310 XR=XR+16
1320 GOTO 1180
1330 GRAPHICS 0
1340 Y=0
1350 Y1=3
1360 POSITION 5,1:? "SECTOR # ";OL$;"
(CHARACTERS)"
1370 FOR X=1 TO 128
1380 Y=Y+1
1390 IF NU(X)>251 THEN NU(X)=251
1400 IF Y>7 THEN POSITION Y*3+5,Y1:? C
HR$(NU(X));:Y=0:Y1=Y1+1:GOTO 1420
1410 POSITION Y*3+5,Y1:? CHR$(NU(X));
1420 NEXT X
1430 POSITION 3,3:? "00"
1440 POSITION 3,4:? "08"
1450 Y=3
1460 FOR X=10 TO 70 STEP 10
1470 Y=Y+2
1480 POSITION 3,Y:? X
1490 NEXT X
1500 Y=4
1510 FOR X=18 TO 78 STEP 10
1520 Y=Y+2
1530 POSITION 3,Y:? X
1540 NEXT X
1550 GOTO 440
1560 REM
1570 REM * INCORRECT *
1580 REM
1590 POSITION 2,19
1600 ? "   INCORRECT"
1610 GOTO 440

90 REM * CHECK DATA

100 DATA 8598,390,225,838,222,394,296,
9,923,150,332,925,950,635,857,637,175,
640
235 DATA 9200,508,646,111,571,371,771,
749,651,131,637,529,639,11,924,511,475
,965
390 DATA 6539,487,430,664,25,528,869,1
1,601,274,603,77,6,742,79,82,527,534
560 DATA 10819,541,969,842,840,98,840,
888,831,770,682,615,604,784,239,199,50
3,654
730 DATA 10254,838,602,865,604,937,498
677,775,265,555,469,559,241,753,782,2
72,562
900 DATA 8784,467,557,239,547,825,836,
95,43,850,609,105,641,115,817,687,658,
693
1040 DATA 10940,900,565,429,628,311,71
2,986,642,560,686,809,567,906,963,123,
295,858
1210 DATA 8886,160,198,816,246,714,851
884,434,69,930,931,932,59,585,638,206
,233
1380 DATA 10127,722,25,480,388,825,511
,521,590,706,723,478,832,587,718,719,4
74,828
1550 DATA 4137,887,651,481,653,255,326
,884

00010  .LI OFF

00020  .OR $4000      ;OBJECT CODE
00030 *****************************
00040 *                           *
00050 *           AS1             *
00060 *  LOAD DATA FROM THE DISK  *
00070 *                           *
00080 *****************************
00100 * MACHINE CODE 1
00110  PLA
00120 START PLA    ;PULL BYTES OF THE
00130  PLA         ;STACK
00140  PLA
00150  PLA
00160  PHA
00170  STA $601
00180  LDX #82     ;DETERMINE WHICH
00190  CMP #83     ;DISK OPERATION
00200  BCC L1      ;TO BE PERFORMED
00210  LDX #87     ;WRITE (Verify)
00220 L1 STX $600
00230  LDA #6
00240  STA $305    ;BUFFER ADDRESS
00250  LDA #128    ;OF THE DISK SECTOR
00260  STA $304    ;DATA
00270  LDA #1      ;DEVICE SERIAL BUS ID
00280  STA $301    ;SET TO DRIVE 1
00290  LDX $600
00300  STX $302    ;SET DISK OPERATION
00310  PLA         ;INPUT DISK SECTOR
00320  STA $30A    ;NUMBER
00330  LDY $601
00340  STY $30B
00350  JSR $D453
00360  LDY #0
00370  STY $D5     ;FLOATING POINT
00380  LDY $303    ;REGISTER
00390  STY $D4
00400  RTS         ;RETURN TO BASIC

00010  .L1 OFF

00020  .OR $3A98   ;STORE OBJECT CODE
80100 ******************************
00110 *                            *
00120 *            AS2             *
00130 *  RAM TO SCREEN SUBROUTINE  *
00140 *                            *
00150 ******************************
00160 START PLA    ;PULL BYTE OF STACK
00170  PLA
00180  STA $E5     ;STORE 'A' IN THE
00190  PLA         ;FLOATING POINT
00020  STA $E4     ;REGISTER 1
00210  LDA #0
00220  PHA         ;PUSH 'A' ON THE STACK
00230 L8 PLA
00240  PHA
00250  BPL L1
00260  LDA #155    ;MOVE THE CURSOR
00270  JSR $F6A4   ;ONE SPACE
00280  PLA
00290  RTS         ;RETURN TO BASIC
00300 *
00310 L1 LDA #155  ;MOVE THE CURSOR
00320  JSR $F6A4   ;ONE SPACE
00330  PLA
00340  PHA
00350  LDX #0      ;SET OPERATION
00360  STX $60A    ;COUNTER
00370  LDY #0      ;SET MEMORY COUNTER
00380  CPX #0
00390  BEQ CON     ;GOTO CONTROL SECTION
80400 *
00410 * SECTION 1
00420 *
00430 S1 LDA #32   ;MOVE THE CURSOR
00440  JSR $F6A4   ;ONE SPACE
00450  CPX #0
00460  BNE CON     ;RETURN TO CONTROL SECTION
00470 *
00480 * SECTION 2
00490 *
00500 S2 LSR       ;DETERMINE THE FIRST
00510  LSR         ;DIGIT OF THE
00520  LSR         ;BYTE NUMBER
00530  LSR
00540  CMP #10
00550  BMI L4
00560  ADC #6
00570 L4 ADC #48
00580  JSR $F6A4   ;DISPLAY MT
00590  CPX #0
00600  BNE CON     ;RETURN TO CONTROL SECTION
00610 *
00620 * SECTION 3
00630 *
00640 S3 AND #15   ;DETERMINE THE SECOND
00650  CMP #10     ;DIGIT OF THE
00660  BMI L5      ;BYTE NUMBER
00670  ADC #6
00680 L5 ADC #48
00690  JSR $F6A4   ;DISPLAY XT
00700  CPX #0
00710  BNE CON     ;RETURN TO CONTROL SECTION
00720 *
00730 * SECTION 4
00740 *
00750 S4 PLA
00760  PHA
00770  TAY         ;LOAD ONE BYTE OF
00780  LDA $680,Y  ;DATA FOR THE MEMORY
00790  INY         ;INCREMENT MEMORY COUNTER
00800  CPX #0
00810  BNE CON     ;RETURN TO CONTROL SECTION
00820 *
00830 * ENDING
00840 *
00850 EN PLA
00860  LDX #5      ;RESET OPERATION COUNTER
00870  STX $60A
00880  CLC
00890  ADC #l
00900  PHA
00910  AND #7
00920  BNE L7      ;NEXT NUMBER
00930  BEQ L8      ;NEXT LINE(Or end)
00970 CON INC $60A ;INCREMENT OPERATION COUNTER
00980  LDX $60A    ;LOAD OPERATION COUNTER
00990  CPX #1
01000  BEQ S2      ;GOTO SECTION 2
01010  CPX #2
01020  BEQ $31     ;GOTO SECTION 3 SUB
01030  CPX #3
01040  BEG S1      ;GOTO SECTION 1
01050  CPX #4
81060  BEQ S1      ;GOTO SECTION 1
01070 L7 CPX #5
01080  BEQ S4      ;GOTO SECTION 4
01090  CPX #6
B11OO  BEQ S2      ;GOTO SECTION 2
01110  CPX #7
01120  BEQ S4      ;GOTO SECTION 4
01130  CPX #8
01140  BEQ S3      ;GOTO SECTION 3
01150  CPX #9
01160  BEQ S1      ;GOTO SECTION 1
01170  CPX #10
01180  BEQ EN      ;GOTO END SECTION
01190 *
01200 * SECTION 3 SUB 1
01218 *
01220 S31 PLA
01230  PHA
01240  CPX #0
01250  BNE 53      ;TO SECTION 3

5 REM ***************

6 REM *             *
7 REM * FILE FINDER *
8 REM *             *
9 REM ***************
10 GRAPHICS 1
12 DIM A$(5),PH(5),MSH(5),NV$(5)
15 POKE 752,1
20 SETCOLOR 2,16,1
25 POSITION 0,8
30 ? #6;"LOADING MACHINE CODE"
49 REM * STORE SAVE ROUTINE *
50 FOR X=0 TO 35
52 READ D
55 POKE 16000+X,D
60 NEXT X
69 REM * STORE LOAD ROUTINE *
70 FOR X=0 TO 35
72 READ D
75 POKE 15000*X,D
80 NEXT X
100 POKE 14999,104
110 POKE 15999,104
120 REM *
122 REM * WHAT SECTOR TO MODIFY *
125 REM *
130 GRAPHICS 0:POKE 752,1
132 POSZTION 15,1:? "FILE FINDER"
135 POSZTION 2,4
140 ? "What sector to Modify(dec)":FOR
  X=1 TO 50:NEXT X:POKE 764,255:INPUT M
S
142 ZF MS<1 OR M5>719 THEN ? "(1-719)"
:GOTO 140
145 MSC=MS/256
150 MSM=(MSC-INT(MSC))*16
155 MSH(1)=INT(MSC)
160 MSM1=INT((MSM-INT(MSM))4*16+0.5)
165 MSH(2)=INT(MSM)*16+MSM1
210 POKE 1536,MSH(2)
220 POKE 1537,MSH(1)
230 POKE 1539,MSH(2)
240 POKE 1540,MSH(1)
250 X=USR(14999)
260 GOTO 1000
265 REM *
267 REM * DISPLAY BYTE NUMBERS *
268 REM *
270 GRAPHICS 0
271 POKE 752,1
272 POSITION 0,1:? "BYTE NO.     SECT
OR: ";MS:POSITION 2,2:? "dec
    HEX"
273 FOR X=0 TO 15
274 POSITION 2,X+3
275 ? X*8
284 NEXT X
298 REM *
299 REM * DISPLAY TO SCREEN *
305 REM *
310 FOR X=1664 TO 1792 STEP 8
320 FOR Y=1 TO 8
330 PD=PEEK(X+Y-1)
340 PHC=PD/16
350 PH(2)=INT((PHC-INT(PHC))*16+0.5)
360 PH(1)=INT(PHC)
365 FOR WA=1 TO 2
370 POSITION Y*3+WA+4,INT((X-1664)/8)+
3
380 IF PH(WA)>9 THEN 400
390 ? PH(WA)
395 GOTO 470
400 IF PH(WA)=10 THEN A$="A"
410 IF PH(WA)=11 THEN A$="B"
420 IF PH(WA)=12 THEN AS="C"
430 IF PH(WA)=13 THEN A$="D"
440 IF PH(WA)=14 THEN A$="E"
450 IF PH(WA)=15 THEN A$="F"
460 ? A$
470 NEXT WA
475 IF X+Y>1791 THEN 490
480 NEXT Y
485 NEXT X
490 ? :7 "Press the SPACE BAR to COnti
nue"
500 IF PEEK(764)<>33 THEN 500
510 GOTO 1000
690 REM *
692 REM * DISPLAY CHARACTERS *
695 REM *
700 GRAPHICS 0
702 POKE 752,1
704 POSITION 0,1:? "BYTE NO.    SECTOR
: ";MS:POSITION 2,2:? "dec         CHA
R"

705 FOR X=0 TO 15
710 POSITION 2,X+3
725 ? X*8
735 NEXT X
740 FOR X=1664 TO 1792 STEP 8
750 FOR Y=1 TO 8
760 PD=PEEK(X+Y-1)
770 P0SITION Y*3+4,INT((X-1664)/8)+3
780 ? CHR$(PD)
800 IF X+Y>1791 THEN 830
810 NEXT Y
820 NEXT X
830 ? :? "Press the SPACE BAR to conti
nue"
840 IF PEEK(764)<>33 THEN 840
850 GOTO 1000
990 REM *
994 REM * MAIN LOOP *
995 REM *
1000 GRAPHICS 0
1005 POKE 752,1
1010 POSITION 13,1
1015 ? "FILE FINDER"
1018 POSITION 7,3
1020 ? "What do you want 'to do?"
1025 POSITION 1,6
1030 ? "For character interpretation p
ress 'C'"
1040 POSITION 1,7
1050 ? "For HEX interpretation press
     '
H'"
1054 POSITION 1,8
1055 ? "To select a new sector press
     'N'"
1060 POSITION 2,10
1070 ? "To make modification press 'M'
"
1080 POSITION 5,12
1090 ? "INPUT?"
1095 POKE 764,255

1100 IF PEEK(764)=18 THEN 700
1110 IF PEEK(764)=57 THEN 270
1120 IF PEEK(764)=37 THEN 2000
1125 IF PEEK(764)=35 THEN 130
1130 GOTO 1100
2000 POSITION 0,14
2020 ? "Modify what byte number?(answe
r in dec.)"
2022 POKE 764,255
2625 FOR X=1 TO 50:NEXT X
2030 POSITION 5,15
2040 INPUT BN
2050 POSITION 0,16
2060 ? "Change to what value(DEC. OR $
HEX)"
2070 POSITION 5,17
2080 INPUT NV$
2085 IF NV$(1,1)="$" THEN DH=16:GOTO 4
000
2087 GOTO 3800
2090 POKE 1664+BN,NV
2100 POSITION 2,18
2110 ? "OK"
2120 X=USR(15999)
2130 GOTO 130
3800 IF LEN(NV$)=3 THEN LN=100
3810 IF LEN(NV$)=2 THEN LN=10:GOTO 391
0
3820 IF LEN(NV$)=1 THEN LN=1:GOTO 3920
3900 N100=(ASC(NV$(3,3))-48)*INT(LN/10
0)
3910 N10=(ASC(NV$(2,2))-48)*INT(LN/10)
3920 N1=(ASC(NV$1,1))-48)*LN
3930 NV=N100+N10+N1
3940 IF NV<0 OR NV>255 THEN 2070
3950 GOTO 2090
3990 REM *
3995 REM * CONVERT TO DECIMAL *
3997 REM *
4000 IF ASC(NV$(2,2))>64 THEN HB=ASC(N
V$(2,2))-55:GOTO 4020
4010 HB=ASC(NV$(2,2))-48
4015 IF LEN(NV$)<3 THEN LB=HB:HB=0:GOT
O 4040
4020 IF ASC(NV$(3,3))>64 THEN LB=ASC(N
V$(3,3))-55:GOTO 4040
4030 LB=ASC(NV$(3,3))-48
4040 NV=HB*DH+LB
4050 GOTO 2090
7999 REM * MACHINE CODE (SAVE routine)
 *
8000 DATA 169,1,141,1,3,169,87,141,2,3
,169,128,141,4,3,169,6,141,5,3,173,3,6
,141
8010 DATA 10,3,173,4,6,141,11,3,32,83,
228,96
9999 REM * MACHINE CODE CLOAD routine)
 *
10000 DATA 169,1,141,1,3,169,82,141,2,
3,169,128,141,4,3,169,6,141,5,3,173,0,
6,141
10010 DATA 10,3,173,1,6,141,11,3,32,83
,228,96