Mastering Sideways ROM & RAM - Module 19 - Autoboot RFS ------------------------------------------------------- Most of the filing systems on the BBC microcomputer can be selected (booted in micro-speak) by holding down a filing system boot key and then pressing and releasing the Break key. The DFS can be booted with D+Break, the ADFS with A+Break or F+Break, the Tape Filing system with Space+Break and the Network Filing system with N+Break. You might expect the RFS to boot with R+Break but if you try it you will be disappointed, it does not work. The RFS is the only filing system that can not be booted in this way. In this module I will show you how to modify the RFS interpreter used in Module 18 to include booting the RFS with R+Break. The BBC B issues service call 3 on both hard and soft reset. The Master issues it only on hard reset. This service call is issued primarily to allow filing systems to be initialised on break rather than having to be reselected every time with an operating system command. Any service ROM can intercept this call to execute any routine but it should only trapped if a key exclusive to that ROM is pressed. The example program BOOTRFS will intercept service call 3 and use Osbyte &7A to read the internal key number of any key pressed and, if the internal key number for "R" is found, it will select and catalogue the RFS. Osbyte &7A has no entry parameters and returns the internal key number in the X register. The internal key numbers are not printed in the BBC B User Guide but the INKEY numbers are listed in the BASIC keyword section. The INKEY number can be converted into an Internal Key Number by Exclusive ORing it with &FF. For example, the INKEY number for R is -52. To find the internal key number type: >PRINT ~ -52 EOR &FF FFFFFF33 > and the answer, ignoring the leading Fs, is &33. Figure 19.1 shows the coding that needs to be added to a SWR interpreter to intercept service call 3 and auto-boot the RFS on Ctrl+R+Break. The auto-boot coding can be included in any SWR interpreter, it does not have to be in a ROM with RFS files. Figure 19.1 illustrates that if, after intercepting service call 3, Osbyte &7A returns with X=&33 then R+Break has been pressed and your program can use Osbyte &8D to select the RFS. The routine returns control to the MOS after balancing the stack and reseting the accumulator to zero. .trythree CMP #3 \ is it autoboot? BNE out \ branch if not autoboot PHA \ store A TXA PHA \ store X TYA PHA \ store Y LDA #&7A \ Osbyte &7A, no parameters JSR &FFF4 \ read internal key number CPX #&33 \ has R+Break been pressed? BEQ rbreak \ branch if it has PLA \ pull Y TAY \ restore Y PLA \ pull X TAX \ restore X PLA \ restore A RTS \ return to MOS .rbreak LDA #&8D \ Osbyte &8D, no parameters JSR &FFF4 \ *ROM PLA \ discard Y PLA \ discard X PLA \ discard A LDA #0 \ service recognised .out RTS \ return to MOS Figure 19.1 RFS Auto-boot SWR interpreter. ----------- ------------------------------ The auto-boot routine in figure 19.1 has been adapted for use in the auto-boot RFS header program BOOTRFS. This program must used with the RFSGEN program (introduced in Module 18) to create RFS ROM images. It can only be used with RFSGEN and should replace the RFSHEAD program to create an auto-booting RFS ROM image. If RFS ROM images are used in more than one ROM socket then a ROM image created with BOOTRFS should only be used in one of the ROM sockets. All the other ROM images should be created with RFSHEAD to keep their ROM headers as small as possible. BOOTRFS intercepts service call 3, selects and catalogues the RFS and exits with the RFS active. It uses the service call &0D and &0E interpreter introduced in Module 18. Service call 3 is intercepted (line 660) and if R+Break is detected (lines 720-750) control passes to the label ".rbreak" (line 820). Because it can take a couple of seconds to catalogue the RFS the keyboard is disabled to prevent unwanted input, particularly Escape (lines 830-860). The buffers are flushed (lines 870-890), the two zero page bytes used by the print subroutine are stored on the stack (lines 900-930) and a header to the catalogue is printed (lines 940-990). The RFS is selected (lines 1000-1010) and the Osbyte equivalent of *OPT1,2 is used to enable extended filing system messages (lines 1020-1050). The command line interpreter is instructed to catalogue the RFS (lines 1060-1080), the default *OPT 1,0 is reselected (lines 1090-1120) and a message informing the user that the RFS is active is printed (lines 1130-1190). The two zero page bytes used by the print subroutine are restored (lines 1200-1230), the keyboard is re-enabled (lines 1240-1270), and the stack balanced before returning control to the MOS with the accumulator reset to zero (lines 1280-1320). BOOTRFS is used to create RFS ROM images in the same way that RFSHEAD was used in module 18. Load the ROM image created by BOOTRFS into sideways RAM and press R+Break to select and catalogue the RFS. If you use the program DEMO you should get a screen display similar to that in figure 19.2. Acorn TUBE 6502 64K ROM Filing System Catalogue DEMO 08 08D1 00001900 00002194 ROM Filing System active BASIC > Figure 19.2 The display after R+Break. ----------- -------------------------- With the RFS active you can run the demonstration program by typing CHAIN "DEMO" or *RUN "DEMO". The supplied BASIC program DEMO has been written so that it can be *RUN as well as chained. Most BASIC programs can only be chained from the RFS, or any other filing systems. 10 REM: BOOTRFS 20 MODE7 30 HIMEM=&3C00 40 diff=&8000-HIMEM 50 H%=HIMEM 60 address=&A8 70 ROMnumber=&F4 80 phROM=&F5 90 ROMpoint=&F6 100 osasci=&FFE3 110 osnewl=&FFE7 120 osbyte=&FFF4 130 oscli=&FFF7 140 FOR pass = 0 TO 2 STEP 2 150 P%=HIMEM 160 [ OPT pass 170 BRK 180 BRK 190 BRK 200 JMP service+diff 210 OPT FNequb(&82) 220 OPT FNequb((copyright+diff) MOD 256) 230 BRK 240 OPT FNequs("BOOTRFS") 250 .copyright 260 BRK 270 OPT FNequs("(C)1987 Gordon Horsington") 280 BRK 290 .service 300 PHA 310 CMP #13 320 BNE fourteen 330 TYA 340 EOR #&F 350 CMP ROMnumber 360 BCC out 370 LDA #(lastbyte+diff) MOD 256 380 STA ROMpoint 390 LDA #(lastbyte+diff) DIV 256 400 STA ROMpoint+1 410 LDA ROMnumber 420 EOR #&F 430 STA phROM 440 .exit 450 PLA 460 LDA #0 470 RTS 480 .fourteen 490 CMP #14 500 BNE trythree 510 LDA phROM 520 EOR #&F 530 CMP ROMnumber 540 BNE out 550 LDY #0 560 LDA (ROMpoint),Y 570 TAY 580 INC ROMpoint 590 BNE exit 600 INC ROMpoint+1 610 JMP exit+diff 620 .out 630 PLA 640 RTS 650 .trythree 660 CMP #3 670 BNE out 680 TXA 690 PHA 700 TYA 710 PHA 720 LDA #&7A 730 JSR osbyte 740 CPX #&33 \ Is it R Break? 750 BEQ rbreak 760 PLA 770 TAY 780 PLA 790 TAX 800 PLA 810 RTS 820 .rbreak 830 LDA #&C9 840 LDX #1 850 LDY #0 860 JSR osbyte \ Disable keyboard 870 LDA #&0F 880 LDX #0 890 JSR osbyte \ Flush all buffers 900 LDA address 910 PHA 920 LDA address+1 930 PHA 940 LDX #(rfs+diff) MOD 256 950 LDY #(rfs+diff) DIV 256 960 JSR print+diff 970 LDX #(cat+diff) MOD 256 980 LDY #(cat+diff) DIV 256 990 JSR print+diff 1000 LDA #&8D 1010 JSR osbyte \ Select RFS 1020 LDA #&8B 1030 LDX #1 1040 LDY #2 1050 JSR osbyte \ *OPT1,2 1060 LDX #(dot+diff) MOD 256 1070 LDY #(dot+diff) DIV 256 1080 JSR oscli \ Catalogue RFS 1090 LDA #&8B 1100 LDX #0 1110 LDY #0 1120 JSR osbyte \ *OPT 1,0 1130 JSR osnewl 1140 LDX #(rfs+diff) MOD 256 1150 LDY #(rfs+diff) DIV 256 1160 JSR print+diff 1170 LDX #(act+diff) MOD 256 1180 LDY #(act+diff) DIV 256 1190 JSR print+diff 1200 PLA 1210 STA address+1 1220 PLA 1230 STA address 1240 LDA #&C9 1250 LDX #0 1260 LDY #0 1270 JSR osbyte \ Enable keyboard 1280 PLA 1290 PLA 1300 PLA 1310 LDA #0 1320 RTS 1330 .print 1340 STX address 1350 STY address+1 1360 LDY #&FF 1370 .printloop 1380 INY 1390 LDA (address),Y 1400 BEQ endprint 1410 JSR osasci 1420 JMP printloop+diff 1430 .endprint 1440 RTS 1450 .dot 1460 OPT FNequs("CAT") 1470 OPT FNequb(&0D) 1480 .rfs 1490 OPT FNequs("ROM Filing System ") 1500 BRK 1510 .cat 1520 OPT FNequs("Catalogue") 1530 OPT FNequb(&0D) 1540 BRK 1550 .act 1560 OPT FNequs("active") 1570 OPT FNequw(&0D0D) 1580 BRK 1590 .lastbyte 1600 ] 1610 NEXT 1620 O%=lastbyte 1630 CHAIN"RFSGEN" 1640 DEFFNequb(byte) 1650 ?P%=byte 1660 P%=P%+1 1670 =pass 1680 DEFFNequw(word) 1690 ?P%=word 1700 P%?1=word DIV 256 1710 P%=P%+2 1720 =pass 1730 DEFFNequd(double) 1740 !P%=double 1750 P%=P%+4 1760 =pass 1770 DEFFNequs(string$) 1780 $P%=string$ 1790 P%=P%+LEN(string$) 1800 =pass