\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
