\documentstyle[a4,12pt]{article} \begin{document} \author{APM Manual pages} \title{ This file is a contributory file for matters relating to programming} \maketitle \parskip .1 in \setcounter{secnumdepth}{10} \parindent 0in \section{Preamble} \hspace*{ 0.3 in} the BBC micro. It is intended as a general repository for (non-pirate) \\ \hspace*{ 0.3 in} software for general consumption, bugs and fixes, comments, swap-shop \\ \hspace*{ 0.3 in} etc. etc. I (JHB) 've set it up to see what happens. You can contribute \\ \hspace*{ 0.3 in} material by setting up the alias beeb=fmac:suggbug-x after which the \\ \hspace*{ 0.3 in} command BEEB $<$optional filename$>$ will allow you to add material to the \\ \hspace*{ 0.3 in} file. \section{JHB \hspace{ 0.5 in} Item: \hspace{ 0.5 in} Preparing Filing system ROMs 33 18/01/85 17.09} \hspace*{ 2.1 in} MAKEROM A program to construct a "ROM image" from a number of individual files, which when blown into ROM and installed in a BBC micro, will allow the BBC to read the files using its ROM filing system. \hspace*{ 2.3 in} by \hspace*{ 1.7 in} Christopher J Adie Copyright (C) 1984 ERCC. This documentation and the accompanying program may be used and distributed for educational and academic purposes \hspace{ 0.2 in} only. \hspace{ 0.2 in} Copying \hspace{ 0.2 in} or publishing for commercial gain is prohibited. \subsection{Summary} This \hspace{ 0.2 in} document \hspace{ 0.2 in} describes how to take a number of files (of any description) on the BBC micro, and combine them together with some machine code into an output file which can then be blown onto ROM and installed in a BBC micro without disks. The main use of this is to provide a quick and easy way of loading one or more BASIC programs into a BBC without having to have a disk drive attached. \subsubsection{1 Introduction} The BBC micro has a number of "Filing Systems" which it uses for all file I/O operations. The major ones with which most users are likely to be familiar are the Tape Filing System and the Disk Filing System (DFS). Only one Filing System can be active at a time. The active Filing System can be changed using a star command such as *TAPE or *DISK. Each Filing System generally comes on a sideways ROM chip (an exception being *TAPE, which is on the operating system chip. As well as the above mentioned, there are a variety of other Filing Systems, such as the Econet Filing System (*NET), the IEEE488 Filing System (*IEEE), and the ROM Filing System (*ROM). It is the last which concerns us here. \subsubsection{2 Requirements} There are two kinds of ROM which are supported by this program. They are type numbers 2764 and 27128, holding 8 Kbytes and 16 Kbytes of data respectively. Note that this program will be of little use to you unless you have access to facilities for blowing these chips using a BBC micro. Decide which files you wish to store on ROM. Note that the total space available to you on the ROM is reduced by about 108 bytes, to allow for necessary machine code at the beginning of the ROM, and further reduced by up to 60 bytes for every file stored and by one further byte for every 256 bytes of file data stored. The program will tell you if there is no room for the file you wish to store. The output file will be in "ROM image" form, and should be suitable for blowing into EPROM using an EPROM programmer and corresponding software. \subsubsection{3 Operation} The program should be LOADed and RUN just like any other BASIC program. It will prompt for the ROM type (2764 or 27128) to which an appropriate response should be made. It will then obtain the file LOAD and EXECUTE addresses from the directory of the disk, and print them. The file will be stored on ROM together with this information. You are then asked for the name of the file on the ROM, which need not be the same as the name on disk. Readine the file from disk and formatting it for the ROM takes a few seconds. You are asked if you wish to store another file on the ROM, in which case it will go back and prompt for the file name on disk. Otherwise, it will ask for a filename to use for the output ROM image file. This is the file to program into your EPROM. \subsubsection{4 Use of ROM Filing System} Having installed the EPROM containing your files, you must select the ROM Filing System. Type *ROM followed by return. You will now be able to use *CAT to see what files you have and *INFO to look at their load and execute addresses. If one of the files is a BASIC program, it may be LOADed or CHAINed in the usual way. Note that if you enter LOAD "" or CHAIN "", the first file on the ROM will be accessed. Other files must be referred to by name. In this and some other respects, the ROM Filing System is more like the Tape Filing System than the DFS. Finally, you should note that it is impossible to write to files using the ROM Filing System. Thus, you cannot SAVE a BASIC program, for instance. \subsubsection{5 Reference} For further information, see the Advanced User Guide for the BBC Micro, by Bray, Dickens and Holmes. Relevant sections are Chapter 16, particularly sections 6.10 and 6.11, and section 15.4. \subsection{MAKEROM - ROM Filing System Generator Program} Contributed by ERCC Real Time Support Group \hspace{ 0.2 in} Tel 031 667 1081 ext 2611 This \hspace{ 0.2 in} document \hspace{ 0.2 in} describes how to take a number of files (of any description) on the BBC micro, and combine them together with some machine code into an output file which can then be blown onto ROM and installed in a BBC micro without disks. The main use of this is to provide a quick and easy way of loading one or more BASIC programs into a BBC without having to have a disk drive attached. \hspace*{ 0.2 in} 10REM ****************************************************** \\ \hspace*{ 0.2 in} 20REM * \hspace{ 0.3 in} MAKEROM - Generating a ROM Filing System \hspace{ 0.4 in} * \\ \hspace*{ 0.2 in} 30REM * \hspace{ 1.7 in} Paged ROM \hspace{ 1.2 in} * \\ \hspace*{ 0.2 in} 40REM * \hspace{ 3.5 in} * \\ \hspace*{ 0.2 in} 50REM * This program generates a ROM containing a filing * \\ \hspace*{ 0.2 in} 60REM * \hspace{ 0.3 in} system which accesses data files held in the \hspace{ 0.3 in} * \\ \hspace*{ 0.2 in} 70REM * \hspace{ 0.3 in} ROM itself. See the Advanced User Guide pages \hspace{ 0.2 in} * \\ \hspace*{ 0.2 in} 80REM * \hspace{ 0.3 in} 330-331 and 349f for more information. \hspace{ 0.7 in} * \\ \hspace*{ 0.2 in} 90REM * \hspace{ 3.5 in} * 100REM * Christopher J Adie ERCC RTSG 16 Nov 1983 V.1.0 * 110REM ****************************************************** 120REM 130 140MODE7 150B\%=\&3F00 \hspace{ 0.9 in} :REM B\% points to the bottom of the buffer. 160HIMEM=B\% 170 180DIM CODE 64 190OSFILE=\&FFDD 200offset = \&8000 - B\% 210 220PROCassemblesidecode 230 240REPEAT 250INPUT "ROM Type (2764/27128) ? "ROMTYPE\% 260UNTIL ROMTYPE\%=2764 OR ROMTYPE\%=27128 270endofROM = (ROMTYPE\% MOD 10)*2048 + B\% 275PRINT 280 290REPEAT 300PROCsavefile 310PRINT ~(endofROM-D\%);" bytes left" 320REPEAT 325PRINT 330INPUT "Another file (Y/N) ? "ANSWER\$ 340UNTIL ANSWER\$="Y" OR ANSWER\$="y" OR ANSWER\$="N" OR ANSWER\$="n" 350UNTIL ANSWER\$="N" OR ANSWER\$="n" 360?D\%=\&2B 370 380INPUT "ROM image filename ? "FILENAME\$ 390A\$=FNhex(B\%) 400B\$=FNhex(endofROM) 410OSCLI "SAVE "+FILENAME\$+" "+A\$+" "+B\$ 420END 430 440REM ------------------End of main program-------------------------- 450 460DEF FNhex(NUM\%) 470REM Return a string containing the hex equivalent of the argument 480LOCAL N1\%,N2\%,N3\%,N4\% 490N4\%=NUM\% MOD 16 : NUM\%=NUM\% DIV 16 500N3\%=NUM\% MOD 16 : NUM\%=NUM\% DIV 16 510N2\%=NUM\% MOD 16 : NUM\%=NUM\% DIV 16 520N1\%=NUM\% MOD 16 530=FNhexdgt(N1\%)+FNhexdgt(N2\%)+FNhexdgt(N3\%)+FNhexdgt(N4\%) 540 550DEF FNhexdgt(NX\%) 560REM Return character = the hex digit corresponding to the argument 570IF NX\%$<$10 THEN =CHR\$(NX\%+48) ELSE =CHR\$(NX\%+55) 580 590DEF PROCsavefile 600startoffile=D\% 610handle=FNgetfile 620PROCgetparameters 630filelength=EXT\#(handle) 650REPEAT 660INPUT "Filename on ROM ? "ROMfilename\$ 670UNTIL LEN(ROMfilename\$)$<$=10 675IF NOT FNenoughroom THEN PRINT"Insufficient room in ROM":CLOSE\# handle:ENDPROC 680bytesremaining=filelength 690block=0 700IF bytesremaining=0 THEN PRINT "File empty":CLOSE\# handle:ENDPROC 710IF bytesremaining$>$256 THEN PROCfirstblock ELSE PROClastblock:ENDPROC 720REPEAT 730block=block+1 740IF bytesremaining$>$256 THEN PROCsaveblock ELSE PROClastblock 750UNTIL bytesremaining=0 760ENDPROC 770 780DEF FNgetfile 790LOCAL X 800REPEAT 810INPUT "File to save ? "FILENAME\$ 820X=OPENIN(FILENAME\$) 830IF X=0 PRINT"File not found" 840UNTIL X$<$$>$0 850=X 860 870DEF PROCgetparameters 880LOCAL pblock,fname 890DIM pblock 18 900DIM fname 32 910\$fname=FILENAME\$+CHR\$(13) 920?pblock=fname MOD 256 930?(pblock+1)=fname DIV 256 940A\%=5 950X\%=pblock MOD 256 960Y\%=pblock DIV 256 970CALL OSFILE 980loadaddress=!(pblock+2) 990executionaddress=!(pblock+6) 1000PRINT "Load address is ";~loadaddress 1010PRINT "Execution address is ";~executionaddress 1020ENDPROC 1030 1040DEF FNenoughroom 1050LOCAL blocks,headerlength 1060blocks=((filelength-1)DIV256)+1 1070headerlength=21+LEN(ROMfilename\$) 1080IF blocks$>$1 THEN headerlength=2*headerlength 1090ROMfilelength=filelength+headerlength 1095IF blocks$>$2 THEN ROMfilelength=ROMfilelength+blocks-2 1096ROMfilelength=ROMfilelength+2*blocks 1100IF D\%+ROMfilelength+1$<$endofROM THEN =TRUE ELSE =FALSE 1110 1120DEF PROCfirstblock 1130PROCheader(0,256,FALSE) 1140PROCsavedata(256) 1150ENDPROC 1160 1170DEF PROClastblock 1180PROCheader(block,bytesremaining,TRUE) 1190PROCsavedata(bytesremaining) 1200CLOSE\# handle 1210ENDPROC 1220 1230DEF PROCsaveblock 1240?D\%=\&23 : D\%=D\%+1 1250PROCsavedata(256) 1260ENDPROC 1270 1280DEF PROCheader(blocknumber,blocklength,lastblock) 1300?D\%=\&2A:D\%=D\%+1 1305headerpointer=D\% 1310\$D\%=ROMfilename\$:D\%=D\%+LEN(ROMfilename\$) 1320?D\%=0:D\%=D\%+1 1330!D\%=loadaddress:D\%=D\%+4 1340!D\%=executionaddress:D\%=D\%+4 1350?D\%=blocknumber AND \&FF:?(D\%+1)=blocknumber DIV 256:D\%=D\%+2 1360?D\%=blocklength AND \&FF:?(D\%+1)=blocklength DIV 256:D\%=D\%+2 1370IF lastblock THEN blockflag=\&80 ELSE blockflag=0 1380?D\%=blockflag:D\%=D\%+1 1390!D\%=(startoffile+ROMfilelength+offset) OR \&FFFF0000:D\%=D\%+4 1400PROCappendCRC(headerpointer) 1410ENDPROC 1420 1430DEF PROCsavedata(length) 1440startofdata=D\% 1450FOR count=1 TO length 1460?D\%=BGET\#(handle) 1470D\%=D\%+1 1480NEXT count 1490PROCappendCRC(startofdata) 1500bytesremaining=bytesremaining-length 1510ENDPROC 1520 1530DEF PROCappendCRC(data) 1540LOCAL pass,pass1,pass2,H,L,lblk 1550pass1=0:pass2=2 1560lblk=D\%-data 1570H=D\%:L=D\%+1 1580FOR pass=pass1 TO pass2 STEP pass2-pass1 1590P\%=CODE 1600[OPT pass 1610LDA \#0 1620STA H \hspace{ 1.1 in} \Initialise CRC 1630STA L 1640TAY \hspace{ 1.2 in} \Initialise data pointer 1650.nbyt 1660LDA H 1670EOR data,Y 1680STA H 1690LDX \#8 1700.loop 1710LDA H 1720ROL A 1730BCC b7z 1740LDA H 1750EOR \#8 1760STA H 1770LDA L 1780EOR \#\&10 1790STA L 1800.b7z 1810ROL L 1820ROL H 1830DEX 1840BNE loop 1850INY 1860CPY \#lblk AND \&FF 1870BNE nbyt 1880RTS 1890] 1900NEXT pass 1910CALL CODE 1920D\%=D\%+2 1930ENDPROC 1940 1950 1960DEF PROCassemblesidecode 1970 1980pass1=4 : pass2=6 1990FOR pass=pass1 TO pass2 STEP pass2-pass1 2000P\%=\&8000 2010O\%=B\% 2020[OPT pass 2030 2040.startsidecode 2050BRK:BRK:BRK \hspace{ 1.1 in} \ No language entry point 2060JMP serviceentry 2070EQUB \&82 \hspace{ 1.3 in} \ Service, no language 2080EQUB (cstring-startsidecode) AND \&FF 2090EQUB 1 \hspace{ 1.5 in} \ Version number in binary 2100EQUS "ROM Filing System" 2110.cstring: EQUB 0 2120EQUS "(C) ERCC 1983" 2130EQUB 0 2140 2150.serviceentry \hspace{ 1.0 in} \ Despatch on the service call type 2160CMP \#\&0D 2170BNE not0D 2180JMP call0D 2190.not0D 2200CMP \#\&0E 2210BNE not0E 2220JMP call0E 2230.not0E 2240.exit \hspace{ 1.5 in} \ Call not recognised by this ROM 2250RTS 2260 2270.call0D \hspace{ 1.4 in} \ Initialise ROM filing system 2280PHA \hspace{ 1.7 in} \ Save the service call number 2290TYA \hspace{ 1.7 in} \ Logical ROM number 2300EOR \#\&0F \hspace{ 1.3 in} \ Adjust it 2310CMP \&F4 \hspace{ 1.4 in} \ Is it for us? 2320BCC notus \hspace{ 1.3 in} \ No, it is less, so this ROM done already 2330LDA \#data MOD 256 2340STA \&F6 2350LDA \#data DIV 256 2360STA \&F7 \hspace{ 1.4 in} \ Initialise data pointer at \&F6 and 7 2370LDA \&F4 \hspace{ 1.4 in} \ Get our ROM number 2380EOR \#\&0F \hspace{ 1.3 in} \ Readjust it 2390STA \&F5 \hspace{ 1.4 in} \ Pass over any higher non-filing-system ROMs 2400PLA \hspace{ 1.7 in} \ Discard service call number 2410LDA \#0 \hspace{ 1.5 in} \ Service type becomes no-op 2420RTS \hspace{ 1.7 in} \ Exit 2430 2440.notus 2450PLA \hspace{ 1.7 in} \ Call not for us, so restore service call no 2460RTS \hspace{ 1.7 in} \ And return 2470 2480.call0E \hspace{ 1.4 in} \ Byte request call 2490PHA \hspace{ 1.7 in} \ Save the service call number 2500LDA \&F5 \hspace{ 1.4 in} \ Get current ROM number 2510EOR \#\&0F 2520CMP \&F4 \hspace{ 1.4 in} \ Is it us? 2530BNE notus \hspace{ 1.3 in} \ No 2540LDY \#0 2550LDA (\&F6),Y \hspace{ 1.1 in} \ Get the data 2560TAY \hspace{ 1.7 in} \ Returned in Y 2570INC \&F6 2580BNE ninc7 \hspace{ 1.3 in} \ Increment data pointer 2590INC \&F7 2600.ninc7 2610PLA \hspace{ 1.7 in} \ Discard service type 2620LDA \#0 \hspace{ 1.5 in} \ Service type becomes no-op 2630RTS \hspace{ 1.7 in} \ Exit 2640 2650.endsidecode 2660.data 2670 2680] 2690NEXT pass 2700 2710D\% = data + (B\%-\&8000) 2720 2730ENDPROC Fails: Unbalanced brackets