SADOS+ is the disk operating system AERCO supplied with its FD-ZX floppy disk interface for the ZX81 and TS1000. It is a BASIC menu program that calls the machine code in the interface’s EPROM at address 12288. The menu offers C to copy a disk (with two drives), D for disk utilities, E to enter names in the directory, F to format the disk in drive A, H for a hex monitor, L to load memory from disk, S to save memory to disk, and Q to quit. The disk is divided into numbered pages. L lists the page names and loads a page by number, and S saves memory to a page you choose. Option 99 on the directory screen prints a hard copy.
There are two versions on the disk. “SADOS+ 16K (40 TRACK)” on page 1 is the boot program and handles twenty 16K pages. “SADOS+ 64K” on page 2 handles six 64K pages instead. Both title screens are dated 8/83. You need a real ZX81 or TS1000 with the AERCO FD-ZX interface; the disk boots with RAND USR 13303. In an emulator the programs show the menu and the directory, but the disk functions do nothing.
The disk is labelled “COPY OF ORIGINALLY SUPPLIED AERCO ‘SADOS’ DISK”. Its directory lists only the two SADOS+ programs. Pages 10, 11 and 20, which are not in the directory, hold leftover copies of page 1. The copies on pages 10 and 20 match it, but the one on page 11 is damaged and is not in the download. The download holds the two programs as .p files, the complete disk image and a README on the page format. BBDOS by Bill Bell later replaced SADOS with a DOS that handles files by name.
Program Analysis
Program Structure
- Lines 100-225: the main menu, read with
INKEY$, and the L option. L prints the directory fromQ$and loads the chosen page withRAND USR (BASE+2+P)(16K) orRAND USR (BASE+3+(P-1)*3)/(BASE+4+(P-1)*3)(64K). - Lines 230-260: S asks for a page number and calls
RAND USR (BASE+432+P)(16K) or(BASE+1712+P)(64K). - Line 265 onward: format, after an “OK TO ERASE ALL FILES ON DISC A?” check, then
RAND USR (BASE+1024). Later lines handle disk copy, entering directory names, the disk utilities and the hex monitor.
Notable Techniques
- The directory is not stored separately on the disk. It is the string array
Q$(20,24)inside the page 1 program, so changing a name means saving SADOS itself again. - Each page is a raw memory image starting at 16393. Loading a page replaces the whole BASIC system, including SADOS, with the program that was saved.
Potential Issues
- In the 64K version, line 216 skips line 217 only for pages above 3. Pages 1-3 run
RAND USR (BASE+3+(P-1)*3)and then fall through to line 218’sRAND USR (BASE+4+(P-1)*3). That appears harmless only if the first call never returns.
The programs came from an AERCO FD-ZX disk in Joe’s collection, read with a new reader for FD-ZX disk images. In ZEsarUX, both versions were loaded on an emulated ZX81 and showed their menus and directory screens. The disk functions were not tested, because they need the AERCO interface.
Source Code
100 LET BASE=12288
105 FAST
110 CLS
115 PRINT " WELCOME TO SADOS+ 16K 8/83",,,,,"C COPY DISC (REQUIRES 2 DRIVES)",,"D DISC UTILITIES",,,"E ENTER NAMES IN DIRECTORY",,,"F FORMAT DISC IN DRIVE A",,,"H HEX MONITOR",,,,"L LOAD MEMORY FROM DISC",,,"Q QUIT",,,,"S SAVE MEMORY ON DISC"
120 SLOW
125 IF INKEY$ ="" THEN GOTO 0125
127 LET C$=INKEY$
130 IF C$<>"Q" THEN GOTO 0145
135 FAST
140 STOP
145 IF C$="C" THEN GOTO 0430
150 IF C$="E" THEN GOTO 0300
155 IF C$="H" THEN GOTO 0670
160 IF C$="D" THEN GOTO 0485
165 IF C$<>"L" THEN GOTO 0230
170 FAST
175 CLS
180 PRINT AT 0,0;" 1. ";Q$(1)," 2. ";Q$(2)," 3. ";Q$(3)," 4. ";Q$(4)," 5. ";Q$(5)," 6. ";Q$(6)," 7. ";Q$(7)," 8. ";Q$(8)," 9. ";Q$(9),"10. ";Q$(10),"11. ";Q$(11),"12. ";Q$(12),"13. ";Q$(13),"14. ";Q$(14),"15. ";Q$(15),"16. ";Q$(16),"17. ";Q$(17),"18. ";Q$(18),"19. ";Q$(19),"20. ";Q$(20),"99. HARD COPY",," 0. RETURN TO MENU"
185 SLOW
190 INPUT P
195 IF P=0 THEN GOTO 0105
200 IF P<>99 THEN GOTO 0215
205 PRINT AT 20,0;" "
210 COPY
215 IF P>20 THEN GOTO 0170
220 RAND USR (BASE+2+P)
225 GOTO 0105
230 IF C$<>"S" THEN GOTO 0265
235 PRINT AT 21,0;"ENTER PAGE NUMBER 1 TO 20"
240 INPUT P
245 IF P=0 THEN GOTO 0105
250 IF P>20 THEN GOTO 0240
255 RAND USR (BASE+432+P)
260 GOTO 0105
265 IF C$<>"F" THEN GOTO 0125
270 GOSUB 0635
275 PRINT AT 19,0;"OK TO ERASE ALL FILES ON DISC A? (Y/N) "
280 IF INKEY$ ="N" THEN GOTO 0105
285 IF INKEY$ <>"Y" THEN GOTO 0280
290 IF INKEY$ ="Y" THEN RAND USR (BASE+1024)
295 GOTO 0105
300 FAST
305 CLS
310 PRINT AT 3,0;"ENTER PROGRAM NUMBER:(1 TO 20)",,,"0 TO ABORT"
315 INPUT CC
320 IF CC<=0 THEN GOTO 0105
325 IF CC>20 THEN GOTO 0305
330 PRINT AT 3,20;" ";CC;" ",,,"ENTER NAME OF PROGRAM:"
335 INPUT Q$(CC)
340 PRINT AT 5,0;CC;".";" ";Q$(CC),,,"IS THIS CORRECT? (Y/N)"
345 SLOW
350 IF INKEY$ ="" THEN GOTO 0350
355 IF INKEY$ ="N" THEN GOTO 0300
360 IF INKEY$ ="Y" THEN GOTO 0370
365 IF INKEY$ <>"Y" THEN GOTO 0350
370 FAST
375 CLS
380 PRINT AT 6,0;" ";CC;". ";Q$(CC),,," THE ABOVE HAS BEEN ENTERED",,," INTO THE DIRECTORY.",,,"MORE DIRECTORY ENTRIES? (Y/N)"
385 SLOW
390 IF INKEY$ <>"" THEN GOTO 0390
395 IF INKEY$ ="" THEN GOTO 0395
400 IF INKEY$ ="Y" THEN GOTO 0300
405 PRINT ,,"SAVE DOS ON DISC PAGE 1? (Y/N)"
407 LET P=1
410 IF INKEY$ <>"" THEN GOTO 0410
415 IF INKEY$ ="" THEN GOTO 0415
420 IF INKEY$ ="Y" THEN RAND USR (BASE+433)
425 GOTO 0105
430 FAST
435 CLS
440 PRINT " DISC COPY ROUTINE",,,,,,,"PLACE ORIGINAL DISC IN DRIVE B",,,"PLACE FORMATTED DISC IN DRIVE A",,,"PRESS C TO COPY",,,,"PRESS Q TO ABORT"
445 SLOW
450 IF INKEY$ <>"" THEN GOTO 0450
455 IF INKEY$ ="" THEN GOTO 0455
460 IF INKEY$ ="Q" THEN GOTO 0105
465 IF INKEY$ ="C" THEN GOTO 0475
470 GOTO 0455
475 RAND USR (BASE+1472)
480 GOTO 0105
485 FAST
490 CLS
495 PRINT " DISC CONTROL UTILITIES",,,,,,,"C CLEAR DIRECTORY",,,"D SET DATA MODE",,,"P SET PROGRAM MODE",,,"R RETURN TO MAIN MENU",,,"T TRANSFER DISC DRIVE"
500 SLOW
505 IF INKEY$ <>"" THEN GOTO 0505
510 IF INKEY$ ="R" THEN GOTO 0105
515 IF INKEY$ <>"C" THEN GOTO 0550
520 CLS
525 DIM Q$(20,24)
530 PRINT AT 10,5;"DIRECTORY IS NOW BLANK"
535 FOR Z=1 TO 30
540 NEXT Z
545 GOTO 0105
550 IF INKEY$ <>"D" THEN GOTO 0565
555 RAND USR (BASE+1610)
560 GOTO 0105
565 IF INKEY$ <>"P" THEN GOTO 0580
570 RAND USR (BASE+1603)
575 GOTO 0105
580 IF INKEY$ <>"T" THEN GOTO 0510
585 PRINT AT 19,0;"SELECT DRIVE: A/B/C/D Q TO QUIT"
590 IF INKEY$ ="" THEN GOTO 0590
595 IF INKEY$ ="Q" THEN GOTO 0105
600 LET D=CODE INKEY$
605 IF D<38 OR D>41 THEN GOTO 0590
610 RAND USR (BASE+977+D-38)
615 GOSUB 0635
620 RAND USR (BASE+512)
625 RAND USR (BASE+564)
630 GOTO 0105
635 PRINT AT 19,0;"(S)INGLE (D)OUBLE DENSITY (Q)UIT"
640 IF INKEY$ ="" THEN GOTO 0640
645 IF INKEY$ ="Q" THEN GOTO 0105
650 IF INKEY$ ="S" THEN RAND USR (BASE+752)
655 IF INKEY$ ="D" THEN RAND USR (BASE+1002)
660 IF INKEY$ <>"D" AND INKEY$ <>"S" THEN GOTO 0640
665 RETURN
670 FAST
675 CLS
680 GOSUB 0985
685 SCROLL
690 PRINT "HEX START ADR"
695 INPUT H$
700 IF H$="Q" THEN GOTO 1
705 GOSUB 1075
710 LET DADR=DEC
715 IF DADR<0 THEN LET DADR=DADR+65536
720 IF DADR>65535 THEN LET DADR=DADR-65536
725 SCROLL
730 GOSUB 0925
735 INPUT H$
740 IF H$="Q" THEN GOTO 1
745 IF H$<>"" THEN GOTO 0760
750 LET DADR=DADR+1
755 GOTO 0715
760 IF H$<>":" THEN GOTO 0775
765 LET DADR=DADR-16
770 GOTO 0715
775 IF H$<>"Z" THEN GOTO 0790
780 LET DADR=DADR-1
785 GOTO 0715
790 IF H$<>"S" THEN GOTO 0805
795 LET DADR=DADR+16
800 GOTO 0715
805 IF H$<>" LPRINT " THEN GOTO 0820
810 LET DADR=DADR+256
815 GOTO 0715
820 IF LEN H$<2 THEN GOTO 1010
825 IF H$(1)<>"R" THEN GOTO 0840
830 LET H$=H$(LEN H$-(LEN H$-2) TO )
835 GOTO 0700
840 IF H$(1)<>"G" THEN GOTO 0860
845 LET H$=H$(LEN H$-(LEN H$-2) TO )
850 GOTO VAL H$
855 GOTO 0715
860 IF H$(1)<>"H" THEN GOTO 0880
865 LET H$=H$(LEN H$-(LEN H$-2) TO )
870 GOSUB VAL H$
875 GOTO 0715
880 GOTO 0885
885 LET H$=H$((LEN H$-1) TO )
890 GOSUB 1075
895 IF DEC<0 THEN GOTO 0715
900 IF DEC>255 THEN GOTO 0715
905 POKE DADR,DEC
910 PRINT AT 21,0;
915 GOSUB 0925
920 GOTO 0750
925 LET DEC=DADR
930 GOSUB 1040
935 PRINT " (";DEC;")";
940 PRINT AT 21,13;"= ";
945 LET DDATA=PEEK DADR
950 LET C$=CHR$ DDATA
955 LET DEC=DDATA
960 GOSUB 1020
965 PRINT " (";DDATA;") ";
970 PRINT AT 21,24;" "
975 PRINT AT 21,24 ;C$
980 RETURN
985 PRINT AT 14,0;" HIMON 1.9 14 AUG 82"
990 PRINT "Q=QUIT R(ADR)=RSTRT ENT=INC 1"
995 PRINT "S=+16 (SH)S=+256 Z=-1 :=-16"
1000 PRINT "G(LIN)=GOTO H(LIN)=GOSUB"
1005 RETURN
1010 GOSUB 0985
1015 GOTO 0735
1020 LET DEC1=INT (DEC/16)
1025 PRINT CHR$ (DEC1+28);
1030 PRINT CHR$ (DEC-16*DEC1+28);
1035 RETURN
1040 LET DDEC=DEC
1045 LET DEC=INT (DDEC/256)
1050 GOSUB 1020
1055 LET DEC=DDEC-256*DEC
1060 GOSUB 1020
1065 LET DEC=DDEC
1070 RETURN
1075 LET VALH=1
1080 LET DEC=0
1085 IF LEN H$>4 THEN LET H$=H$(LEN H$-3 TO )
1090 LET LENH=LEN H$
1095 IF LENH<=0 THEN RETURN
1100 LET DEC=DEC+(CODE H$(LENH)-28)*VALH
1105 LET VALH=VALH*16
1110 LET LENH=LENH-1
1115 GOTO 1095Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.



