COMPUTE! #49 / JUNE 1984 / PAGE 116
MacroDOS is an instant access disk utility package for a one- or two-drive DOS 2.0 system. MacroDOS uses only three pages of RAM and therefore can be permanently coresident in memory with the FMS. You can pretty well forget about MEM.SAV. And when you call DOS, you won’t have to worry about losing your BASIC or machine language program when you return. The utility can also be used without a cartridge.
MacroDOS supports all the normal DUP functions excepting file and disk duplication, some of which can still be accomplished with the SAVE (binary file) command. Also, MacroDOS incorporates a new feature to DUP systems: hex or dec RUN and address entries, and a permanently available hex-to-decimal, decimal-to-hex converter. You’ll have no more lost time looking for that subroutine, which must be around somewhere, or couldn’t be loaded anyway because it conflicts with something that is in memory.
You will still be allowed the option of using Atari DUP, but now, before you take that step, the directory can be safely checked to confirm that MEM.SAV is indeed there.
MacroDOS resides in memory after the FMS, where Atari DUP would normally load. The big difference here is that it pushes MEMLO up to stay out of the way of your programs. You will still have use of page 6, page 4, and even page 1. When SYSTEM RESET or BREAK is hit, MacroDOS will reinitialize itself unless you have exited to Atari DUP, which resets the old vectors.
Some of the MacroDOS operations differ slightly, but if you have used Atari DOS-DUP, there is really little to learn, and you may even find that the new operation is easier to master and execute.
When working with MacroDOS, you should be using DOS.SYS 2.0S in the same (or a smaller) configuration that comes on your master disk. If the listing for the machine language program (Part 2, next month) is used, you should be able to realign the program for larger versions of DOS.SYS using more buffer space. The program will check MEMLO and change everything accordingly.
The program included this month, however, is for BASIC users, and it’s constrained to using a version of DOS.SYS which, after it has loaded, has a MEMLO of 7420 ($1CFC), or less. Use the direct mode command as follows to check if in doubt: PRINT PEEK(743)+256*PEEK(744). If your DOS.SYS has not been altered from the master disk, MEMLO will be 7420.
There are a few new prompts. First is the > prompt, which expects the return of a function command’s first letter. The directory, format, and write DOS functions use the prompt D# and expect just a single number of 1-4, or just a RETURN, which defaults to drive 1. The format command also uses a ? to ask if you’re sure, and looks for a Y or YES before proceeding.
Functions requiring a filename use FN?. The device name (D:, D1:, or D2:) must be included in the name. Rename (RNM) requires only one device name and none for the name after the comma. The @ prompt is used to mean “at” or “to” when an address input is required. Asterisk wild cards are still allowed.
In Part 2, we’ll continue the discussion of MacroDOS features, and present the machine language source code.
If you don’t want to type in the programs, send $3 and a disk or tape with an SASE mailer.
Jerry Allen
1906 Carnegie #E
Redondo Beach, CA 90278
20 DIM H$(104):TRAP 95:OPEN #1,8,0,"D:AUTORUN.SYS":FOR N=1 TO 16:READ H$:B=0 30 FOR C=1 TO 99 STEP 2 40 IF H$(C,C+2)="END" THEN GOSUB 80:END 50 A=16*(ASC(H$(C))-48-7*(ASC(H$(C))>57)) 60 A=A+ASC(H$(C+1))-48-7*(ASC(H$(C+1))>57):B=B+A 70 PUT #1,A:NEXT C:GOSUB 80:NEXT N 80 IF B<>VAL(H$(LEN(H$)-3)) THEN ? "ERROR AT LINE ";N*100:STOP 90 RETURN 95 END 100 DATA FFFFFC1C082020AE1E84F2888CE3028CE10284FFA280A00586F384F4A03A9848B9A71F20B21E68A88810F3A9088D5A0320766200 200 DATA 1EA004AD8005D9E21FF01C8810F8C944D06DA9068D5A0320741D206A1EA21020761E20701E10F6B9E71F48C9FEF00920951D5209 300 DATA 68206C1E109CA93F20B21E20761EAD8005C959D08D20741D30E6A94420B21EA92320B21E20761EAD80058DED1F8DF41FA0064896 400 DATA B9EC1F91F38810F860A94620B21EA94E20B21EA93F20B21E4C761EC957D01120741DC8B9F31F91F388D0F8206A1E10B1C94C5965 500 DATA D03485FF20951D4E5A03206A1E20991EA9FFC5D4D004C5D5F0F320B6DD20991E20701F20E61DF0E5ADE302F008200517A9005814 600 DATA 8DE30260C953D03720951DA0FFC8B1F3C92FD007EE5A03A99B91F3C99BD0EE206A1EA9FF85D485D520951E20ED1E20951E206602 700 DATA B6DD20ED1E20951E20701F1039C940D00620ED1E6CD400C943D0034C74E4C921D00EA940850CA915850D2040154C9F17C9244940 800 DATA D00820081F20541F100AC92ED00620021F202D1F106FA903A210D008A200A909D002A9059D4203A91E9D4803A9059D4503A93740 900 DATA 809D4403A9009D49032056E4302B60A90BD002A907A2109D4203A9029D4803A9009D4503A9D4D0D9A90C10BA85D4A200A90B4938 1000 DATA 9D4203A90110E3C003F0D1C088F0159848A9C520B21E2044DA6885D420541F68684CFC1CA5FFF0F720E61DADE102F0EF20086297 1100 DATA 17D0EAA94020B21E20761EAC8005C02EF006C024F008D0BD2000D84CD2D92044DAA001B1F3C99BF01938E930C90A3002E9075889 1200 DATA A20406D426D5CAD0F905D485D4C810E160A000A201A9F035D44A4A4A4A20481FA90F35D420481FCA10EB3021C90A300269065311 1300 DATA 693091F3C86020AAD920E6D8A000B1F3C8C98030F9297F8891F3C8A99B91F34C701EE6D4D002E6D5A210A5E09D4403A5E19D7399 1400 DATA 450338A5D4E5E09D4803A5D5E5E14C8C1E204015A9FE8DE702A91F8DE802A9FC850AA91C850B603E9B9B5344A120243EAE205778 1500 DATA 2E3EA4205344D7204E52C020444FCC205641D39B5452C320544DC6205352C5204D4ED2202A4ED5204B4CAA205249C49B52454936 1600 DATA 2A554620212324FE44313A2A2E2A9B44313A444F532E5359539BA991850CA91F850D4C941FE202E302FE1FEND000000000003710
COMPUTE! #50 / JULY 1984 / PAGE 140
Last month we introduced “Atari MacroDOS” and presented a BASIC program which loads the MacroDOS machine language. This month we’ll look at some technical details of MacroDOS and present a disassembly of the program.
Assembler users can alter the MacroDOS commands table (CMDTAB) if they so desire. Just remember to change lines which check for command input to reflect the new command letter. Also, revise TAB1 if necessary. You can append another AUTORUN.SYS program to the end of MacroDOS, such as a menu loader for BASIC.
Assuming you have MacroDOS up and running as AUTORUN.SYS, enter DOS, then load the other AUTORUN.SYS from another disk. SAVE with APPEND (“D:AUTORUN.SYS”). Enter the beginning and ending addresses at the @ prompts. If necessary, return to the cartridge and POKE or otherwise change the INIT and RUN addresses. Return to DOS and SAVE with append again to pick up the addresses just altered.
If you can’t figure out the load addresses, use this program:
10 OPEN #2,4,0,"D:YOURPRDG.OBJ" 20 FOR I=1 TO 6 30 GET #2,A 40 PRINT A 50 NEXT A 60 CLOSE #2
The first two bytes should be a header of 255 ($FF). The next four bytes will be the beginning and ending addresses of the load (two-byte numbers in low byte, high byte format).
If the file loads to multiple address areas (including RUN and INIT) after the first block of memory is loaded, OS checks for a new header of 255,255. If it is there, the header is ignored, and the next four bytes will be the new from-to load addresses.
Loading RUN with page 6 (1536) would look like:
$E0(224),$02(2),$E0(224),$02(2),$00(0),$06(6)
(without the header). With a little math and modification of the program, you could find all the load addresses of any compound load file.
If you don’t want to type the programs in, send $3, and a disk or tape with an SASE mailer.
0200 ; EQUATES 0210 ICBC = $342 0220 ICBAL = $344 0230 ICBAH = $345 0240 ICBLL = $348 0250 ICBLH = $349 0260 ICBAX = $34A+16 0270 MEMLO = $2E7 0280 LBUF = $580 0290 INBUF = $F3 0300 CIX = $F2 0310 FR0 = $D4 0320 FR1 = $E0 0330 GETR = $05 0340 GETC = $07 0350 PUTC = $0B 0360 PUTR = $09 0370 OPEN = $03 0380 CLOSE = $0C 0390 AXIO = $0C 0400 AXOUT = $08 0410 AXAP = $09 0420 AXDR = $06 0430 FR0Z = $DA44 0440 IFP = $D9AA 0450 FPI = $D9D2 0460 FPASC = $D8E6 0470 FMOVE = $DDB6 0480 ASCFP = $D800 0490 LO = $00FF 0500 HI = $0100 0510 CIO = $E456 0520 WARMST = $E474 0530 DOSVEC = $0A 0540 DOSINI = $0C 0550 OLDDOS = $179F 0560 JMPINI = $1705 0570 JMPRUN = $1708 0580 ; 0590 ; 0600 *= $1CFC ;change this addr for 0610 ;larger versions of DOS2.0S 0620 ; 0630 ; 0640 ST JSR CLSE ;to be sure 0650 STY CIX ;set f.p. painter 0660 DEY 0670 STY $2E3;clear INIT/RUN 0680 STY $2E1 0690 STY $FF ;reset load flag 0700 LDX #LBUF&LO ;init fit. pt 0710 LDY #LBUF/HI 0720 STX INBUF 0730 STY INBUF+1 0740 DISCMD LDY #TAB1-CMDTAB-1 0750 L1 TYA ;DISPLAY COMhANDS 0760 PHA 0770 LDA CMDTAB,Y 0780 JSR PRINT 0790 PLA 0800 TAY 0810 DEY 0820 BPL L1 0830 LDA #AXOUT ;init aux 0840 STA ICBAX 0850 JSR GTREC ;get command 0860 LDY #4 ;GET COMMAND 0870 LDA LBUF 0880 L2 CMP TAB1,Y 0890 BEQ SPECMD 0900 DEY 0910 BPL L2 0920 DIR CMP #'D ;DIRECTDRY 0930 BNE WDS 0940 LDA #06 0950 STA ICBAX 0960 JSR ASKDN ;drive #? 0970 JSR OPN ;open 0980 L3 LDX #$10 0990 JSR GTREC ;get formatted line 1000 JSR PTREC0 ;print it 1010 BPL L3 1020 SPECMD LDA TAB2,Y ;SPECIAL CMDS 1030 PHA ; save cmd 1040 CMP #$FE ;check if format 1050 BEQ FMT 1060 JSR PFN 1070 EX PLA ;retrieve command 1080 JSR EXCMD ;do it 1090 BPL ST 1100 FMT LDA #'? ; FORMAT 1110 JSR PRINT ;sure? 1120 JSR GTREC 1130 LDA LBUF 1140 CMP #'Y ;is there a yes? 1150 B1 BNE ST ;if not start over 1160 JSR ASKDN ;get drive* 1170 BMI EX ;execute 1180 ASKDN LDA #'D ; GET DRIVE* 1190 JSR PRINT 1200 LDA #'# 1210 JSR PRINT 1220 JSR GTREC 1230 LDA LBUF 1240 STA ADRDIR+1 ;change D# 1250 STA ADRDOS+1 ;just in case WDS 1260 LDY #6 1270 L4 LDA ADRDIR,Y ; move filename 1280 STA (INBUF),Y 1290 DEY 1300 BPL L4 1310 RTS 1320 PFN LDA #'F ;PROMPT FILENAME 1330 JSR PRINT 1340 LDA #'N 1350 JSR PRINT 1360 LDA #'7 1370 JSR PRINT 1380 JMP GTREC 1390 WDS CMP #'W ;WRITE DOS.SYS 1400 BNE LOD 1410 JSR ASKDN 1420 INY 1430 L5 LDA ADRDOS,Y 1440 STA (INBUF),Y 1450 DEY 1460 BNE L5 1470 JSR OPN 1480 BPL B1 1490 LOD CMP #'L 1500 BNE SAV 1510 STA $FF 1520 JSR PFN 1530 LSR ICBAX ;8>4 1540 JSR OPN 1550 L6 JSR GETCR2 ;get hdr in pairs 1560 LDA #$FF ; check headr and- 1570 CMP FR0 ;disregard $FF'S 1580 BNE SK2 1590 CMP FR0+1 1600 BEQ L6 1610 SK2 JSR FMOVE ;FP0 to FP1 1620 JSR GETCR2 1630 JSR SUBTR ;subtr HI-LO &execute 1640 JSR CHKIN 1650 BEQ L6 1660 CHKIN LDA $2E3 1670 BEQ SK12 1680 JSR JMPINI 1690 LDA #0 1700 STA $2E3 1710 SK12 RTS 1720 SAV CMP #'S ;SAVE FUNCTION 1730 BNE RUN 1740 JSR PFN 1750 LDY #$FF ;check if append (/) 1760 L7 INY 1770 LDA (INBUF),Y 1780 CMP #'/ 1790 BNE SK4 1800 INC ICBAX ;9=append 1810 LDA #$9B 1820 STA (INBUF),Y 1830 SK4 CMP #$9B 1840 BNE L7 1850 JSR OPN ;open for write 1860 LDA #$FF ;start headr 1870 STA FR0 1880 STA FR0+1 1890 JSR PUTCR2 ;write it 1900 JSR INPCON ;get from# 1910 JSR PUTCR2 ;write it 1920 JSR FMOVE ;store it 1930 JSR INPCON ;get to# 1940 JSR PUTCR2 ;write it 1950 JSR SUBTR ;find len and save 1960 BPL B2 ; the rest 1970 RUN CMP #'@ ;RUN 1980 BNE CART 1990 JSR INPCON ;get # 2000 JMP (FR0) ;jump indirectly 2010 CART CMP #'C ;CARTRIDGE 2020 BNE ADOS 2030 JMP WARMST 2040 ADOS CMP #'! ;ESC TO ATARI DUP 2050 BNE HEX 2060 LDA #$40 ;reset DOSINI for no- 2070 STA DOSINI ;trouble later 2080 LDA #$15 2090 STA DOSINI+1 2100 JSR $1540 ;fast reset DOSVEC 2110 JMP OLDDOS 2120 HEX CMP #'$ ;HEX TO DEC 2130 BNE DEC 2140 JSR HASCI ;hex to int 2150 JSR IASC ;int to dec 2160 BPL B2 2170 DEC CMP #'. ; DEC TO HEX 2180 BNE B2 2190 JSR DASCI ;dec to int 2200 JSR IHASC ;int to hex 2210 B2 BPL LSTCNC+2 2220 OPN LDA #OPEN ;IOCB MAIN SET UPS 2230 EXCMD LDX #$10 2240 BNE GTR2 2250 PTREC0 LDX #0 2260 PTREC LDA #PUTR 2270 BNE GTR2 2280 GETREC0 2290 GTREC LDA #GETR 2300 GTR2 STA ICBC,X 2310 LDA #$1E ;max rec length 2320 STA ICBLL,X 2330 LDA #LBUF/HI 2340 STA ICBAH,X 2350 LDA #LBUF&LO 2360 PGIN STA ICBAL,X 2370 LDA #0 2380 STA ICBLH,X 2390 ICB JSR CIO ;let the OS take over 2400 BMI ERR 2410 RTN2 RTS 2420 PUTCR2 LDA #PUTC 2430 BNE GETC2 2440 GETCR2 LDA #GETC 2450 GETC2 LDX #$10 2460 STA ICBC,X 2470 LDA #2 2480 JG STA ICBLL,X 2490 LDA #0 2500 STA ICBAH,X 2510 LDA #FR0 2520 BNE PGIN 2530 CLSE LDA #CLOSE 2540 BPL EXCMD 2550 PRINT STA FR0 2560 LDX #0 2570 LDA #PUTC 2580 STA ICBC,X 2590 LDA #1 2600 BPL JG 2610 ERR CPY #$03 ;ERR next read OK 2620 BEQ RTN2 2630 CPY #$B8 ;ERR EOF OK too 2640 BEQ CINI 2650 TYA ;store ERR 2660 PHA 2670 LDA #$C5 ; inverted E for error 2680 JSR PRINT 2690 JSR FR0Z ;clear FP0 2700 PLA ;retrieve ERR 2710 STA FR0 2720 JSR IASC ;int to dec 2730 LSTCNC PLA ;clr stack of return 2740 PLA 2750 JMP ST ;do not pass GO 2760 CINI LDA $FF 2770 BEQ LSTCNC 2780 JSR CHKIN 2790 JRUN LDA $2E1 2800 BEQ LSTCNC 2810 JSR JMPRUN 2820 BNE LSTCNC 2830 INPCON LDA #'@ ;HEX OR DEC# TYPE 2840 JSR PRINT ;the @ means AT/TO 2850 JSR GTREC 2860 LDY LBUF 2870 CPY #'. 2880 BEQ DASCI 2890 CPY #'$ 2900 BEQ HASCI 2910 BNE ERR ;bad input 2920 DASCI JSR ASCFP ;DEC TO INT 2930 JMP FPI 2940 HASCI JSR FR0Z ;HEX TO INT 2950 LDY #1 2960 LB LDA (INBUF),Y 2970 CMP #$9B 2980 BEQ RTN 2990 SEC ; convert each digit 3000 SBC #$30 3010 CMP #$0A 3020 BMI SK7 3030 SBC #7 3040 SK7 LDX #4 ;times 16 3050 LA ASL FR0 3060 ROL FR0+1 3070 DEX 3080 BNE LA 3090 ORA FR0 ;add in new bits 3100 STA FR0 3110 INY 3120 BPL LB 3130 RTN RTS 3140 IHASC LDY #0 ;INT TO HEX SUBRT 3150 LDX #1 3160 LC LDA #$F0 ;hi mask 3170 AND FR0,X 3180 LSR A ;roll into low bits 3190 LSR A 3200 LSR A 3210 LSR A 3220 JSR CDNVH ;go conv to digit 3230 LDA #$0F ;Io mask 3240 AND FR0,X 3250 JSR CDNVH 3260 DEX 3270 BPL LC ;one more time 3280 BMI LE ;set eol and rtn 3290 CDNVH CMP #$0A ;INT TO HEX DIGIT 3300 BMI SK9 3310 ADC #6 ;carry set 3320 SK9 ADC #$30 ;carry clr 3330 STA (INBUF),Y 3340 INY 3350 RTS 3360 IASC JSR IFP ;INT TO DEC 3370 JSR FPASC 3380 AREC LDY #0 ;CLR HI BIT/MAKE REC 3390 L9 LDA (INBUF),Y 3400 INY 3410 CMP #$80 ;find hi bit char 3420 BMI L9 3430 AND #$7F ; mask it 3440 DEY 3450 STA (INBUF),Y 3460 INY 3470 LE LDA #$9B ; set EOL 3480 STA (INBUF),Y 3490 JMP PTREC0 3500 SUBTR INC FR0 ;inclusive so inc 3510 BNE SK5 ; TO address 3520 INC FR0+1 3530 SK5 LDX #$10 3540 LDA FR1 3550 STA ICBAL,X 3560 LDA FR1+1 3570 STA ICBAH,X 3580 SEC ;CALC LENGTH 3590 LDA FR0 3600 SBC FR1 3610 STA ICBLL,X ; STORE AT IOCB 3620 LDA FR0+1 3630 SBC FR1+1 3640 JMP ICB-3 ;exec same cmd as last 3650 ; 3660 ; 3670 INIT JSR $1540 ;SRESET INIT 3680 JI LDA #END&LO 3690 STA MEMLO 3700 LDA #END/HI 3710 STA MEMLO+1 3720 LDA #ST&LO 3730 STA DOSVEC 3740 LDA #ST/HI 3750 STA DOSVEC+1 3760 RTS 3770 ; 3780 ; 3790 CMDTAB ;all spaces are one space 3800 .BYTE ">",$9B,$9B,"SD",$A1 3810 .BYTE " $>",$AE," .>",$A4 3820 .BYTE " SD",$D7," NR",$C0 3830 .BYTE " DO",$CC," VA",$D3,$9B 3840 .BYTE "TR",$C3," TM",$C6 3850 .BYTE " SR",$C5," MN",$D2 3860 .BYTE " *N",$D5," KL",$AA 3870 .BYTE " RI",$C4,$9B 3880 TAB1 3890 .BYTE "RE*UF" 3900 TAB2 3910 .BYTE $20,$21,$23,$24,$FE 3920 ADRDIR 3730 .BYTE "D1:*.*",$9B 3940 ADRDOS 3950 .BYTE "D1:DOS.SYS",$9B 3960 END ;end after boot init executed 3970 ; 3980 ; 3990 INIT1 LDA #INIT&LO ; BOOT INIT 4000 STA DOSINI 4010 LDA #INIT/HI 4020 STA DOSINI+1 4030 JMP JI 4040 ; 4050 ; 4060 *= $2E2 ;LOAD AND GO INIT ADR 4070 .WORD INIT1 4080 .END