ROM Extraction Utility
Version 1.01
written by Gerald Holdsworth

Utility to extract the ROM image from any ROM slot and save to disc. This can also be acheived using *SRSAVE with some sideways ROM software, but the BBC Master will only allow you to use this command on ROM slots 4, 5, 6 and 7.

Written for Acorn Electron, BBC Micro Model B, B+, Master, Master ET, and Master Compact. It may work on other machines, depending on what is returned by *FX0. This should be compiled on a Master series computer.

The code below will create a !BOOT file, which detects the machine it is running on so it can run the appropriate !BOOTx, as well as the 6 !BOOTx files for each of the machines.

Code for 'ROM Extraction Utility':
   10REM>S.ExROM
   20MODE135
   30*KEY1MO.128|M*BE|M
   40size%=&300:REM Size of code
   50compile%=&8000-size%
   60HIMEM=compile%
   70rom=&70
   80basic=&71
   90addr=&72
  100romad=&74
  110prtad=&76
  120romtbl=&78
  130oswrch=&FFEE
  140osnewl=&FFE7
  150osrdch=&FFE0
  160osfile=&FFDD
  170osbyte=&FFF4
  180oscli=&FFF7
  190PRINT"Compiling code for"CHR$130"!BOOT"
  200FORi=4TO6STEP2
  210P%=&2F00:O%=&7F00
  220[OPTi
  230LDA #0
  240LDX #1
  250JSR osbyte
  260TXA
  270CLC
  280ADC #48
  290STA mach
  300LDX #(boot MOD &100)
  310LDY #(boot DIV &100)
  320JSR oscli
  330RTS
  340.boot EQUS "RUN !BOOT"
  350.mach EQUB 0:EQUB 13
  360]
  370NEXT
  380OSCLI"SAVE !BOOT 7F00 "+STR$~(O%)+" 2F00 2F00"
  390title$="ROM Extraction Utility 1.01"
  400written$="written by Gerald J Holdsworth"
  410copy$="(c)2014 GJH Software"
  420rom$="Please enter ROM number:"
  430file$="Please enter filename:"
  440DATA"Acorn Electron","BBC Micro B","BBC Micro B+","BBC Master 128","BBC Master ET","BBC Master Compact"
  450FORc=0TO5
  460READc$
  470PRINT"Compiling code for"CHR$130c$
  480REM Mode to run in
  490IFc<3mode=7ELSEmode=135
  500IFc=0mode=6
  510REM Where the code will load and execute
  520code%=&8000-(size%+&4000)
  530IFc<3code%=&7C00-(size%+&4000)
  540IFc=0code%=&6000-(size%+&4000)
  550FORi=4TO6STEP2
  560P%=code%:O%=compile%
  570[OPTi
  580.file     EQUS "R."
  590.filename EQUS "ROMDUMP"
  600          EQUB 0
  610.block    EQUW file
  620          EQUW &0000
  630          EQUW &0000
  640          EQUW &FFFF
  650          EQUW &FFFF
  660          EQUW buffer
  670          EQUW &0000
  680          EQUW buffer+&4000
  690          EQUW &0000
  700.title    EQUB FNmode7(c,141)
  710          EQUB FNmode7(c,129)
  720          EQUS "     "+title$
  730          EQUB 13
  740          EQUB 0
  750.cpyrght  EQUB 31:EQUB (40-(1+LENwritten$))DIV2:EQUB 2
  760          EQUB FNmode7(c,130)
  770          EQUS written$
  780          EQUB 31:EQUB (40-(1+LENcopy$))DIV2:EQUB 3
  790          EQUB FNmode7(c,132)
  800          EQUS copy$
  810          EQUB 0
  820.romlabel EQUS rom$
  830          EQUB FNmode7(c,130)
  840          EQUB 0
  850.fnmlabel EQUS file$
  860          EQUB FNmode7(c,130)
  870          EQUB 0
  880.saving   EQUS "Saving..."
  890          EQUB 0
  900.another  EQUS "         "
  910          EQUB 11
  920          EQUB 0
  930.empty    EQUS ""
  940          EQUB 0
  950.delete   EQUB 127
  960          EQUB 7
  970          EQUB 0
  980.code
  990LDA #0                  \ find out machine we're running on
 1000LDX #1
 1010JSR osbyte
 1020CPX #c
 1030BEQ bbc
 1040RTS
 1050.bbc                    \ Running on correct machine
 1060LDA #(buffer MOD &100)  \ Setup for post-indexed addressing
 1070STA addr
 1080LDA #0
 1090STA romad
 1100LDA #(buffer DIV &100)
 1110STA addr+1
 1120LDA #&80
 1130STA romad+1
 1140LDA #170
 1150LDX #0
 1160LDY #255
 1170JSR osbyte              \ *FX170 - get ROM info table
 1180STX romtbl
 1190STY romtbl+1
 1200LDA #22                 \ MODE 6,7 or 135
 1210JSR oswrch
 1220LDA #mode
 1230JSR oswrch
 1240]
 1250IFc>0[OPTi:LDA#0:STArom:.dblheight:]
 1260[OPTi
 1270 LDX #(title MOD &100)
 1280 LDY #(title DIV &100)
 1290 JSR print
 1300]
 1310IFc>0[OPTi:INCrom:LDArom:CMP#2:BNEdblheight:]
 1320[OPTi
 1330LDX #(cpyrght MOD &100) \ print the copyright string
 1340LDY #(cpyrght DIV &100)
 1350JSR print
 1360LDA &F4                 \ save the current paged ROM
 1370STA basic
 1380LDX #0                  \ print ROM titles
 1390.romloop
 1400 LDA #31                \ PRINTTAB(0 or 20,rom DIV 2 + 4)
 1410 JSR oswrch
 1420 TXA
 1430 STA rom
 1440 LDA #20
 1450 LSR rom
 1460 BCS col20
 1470 LDA #0
 1480 .col20
 1490 JSR oswrch
 1500 LDA rom
 1510 CLC
 1520 ADC #4
 1530 JSR oswrch
 1540 LDA #FNmode7(c,131)    \ print ROM number in yellow
 1550 JSR oswrch
 1560 TXA
 1570 CLC
 1580 ADC #48
 1590 CMP #58
 1600 BCC lessten
 1610 ADC #6
 1620 .lessten
 1630 JSR oswrch
 1640 LDA #58                \ print colon
 1650 JSR oswrch
 1660 TXA
 1670 JSR pagerom            \ page in ROM, if valid
 1680 LDA &8006              \ test if it is a ROM or RAM
 1690 STA rom                \ and if it is a valid ROM image
 1700 LDA #&FF
 1710 STA &8006              \ if it is a ROM, this value will not
 1720 LDA &8006              \ change
 1730 CMP #&FF
 1740 BNE isrom
 1750 LDA rom                \ but will if RAM, so set back
 1760 STA &8006
 1770 LDA #FNmode7(i,129)    \ red if RAM
 1780 OPT FNjmp(i,c,colour)
 1790.escape3 JMP escape
 1800 .isrom
 1810 LDA #FNmode7(i,134)    \ cyan if ROM
 1820 .colour
 1830 JSR oswrch
 1840 TXA
 1850 TAY
 1860 LDA (romtbl),Y         \ use lookup table to see if valid image
 1870 BEQ isempty
 1880 .isbasic               \ get and print the titles
 1890 OPT FNphx(i,c)
 1900 LDX #&09
 1910 LDY #&80
 1920 JSR print
 1930 OPT FNplx(i,c)
 1940 OPT FNjmp(i,c,noprint)
 1950 .isempty
 1960 OPT FNphx(i,c)
 1970 LDX #(empty MOD &100)
 1980 LDY #(empty DIV &100)
 1990 JSR print
 2000 OPT FNplx(i,c)
 2010 .noprint               \ finished
 2020 JSR osnewl
 2030 INX                    \ next one
 2040 CPX #16
 2050 BEQ endofromloop       \ is it the last one?
 2060 OPT FNjmp(i,c,romloop)
 2070.endofromloop
 2080LDX #(romlabel MOD &100)\ ask for ROM number
 2090LDY #(romlabel DIV &100)
 2100JSR print
 2110.getrom
 2120 JSR osrdch
 2130 CMP #27
 2140 BEQ escape3
 2150 CMP #48
 2160 BCC getrom
 2170 CMP #71
 2180 BCS getrom
 2190 CMP #58
 2200 BCC printrom
 2210 CMP #65
 2220 BCC getrom
 2230.printrom
 2240JSR oswrch
 2250CMP #65
 2260BCC storerom
 2270CLC
 2280SBC #6
 2290.storerom
 2300SEC
 2310SBC #48
 2320STA rom
 2330TAY                     \ check if valid ROM from
 2340LDA (romtbl),Y          \ OS lookup table
 2350BNE ok
 2390LDX #(delete MOD &100)  \ unless it is not a valid image
 2400LDY #(delete DIV &100)
 2410JSR print
 2420OPT FNjmp(i,c,getrom)   \ so get another
 2430.ok
 2440JSR osnewl              \ now get the filename
 2450LDX #(fnmlabel MOD &100)
 2460LDY #(fnmlabel DIV &100)
 2470JSR print
 2480LDX #(filename MOD &100)
 2490LDY #(filename DIV &100)
 2500JSR print
 2510DEY                     \ Y still holds the length of the filename
 2520.getfile
 2530 JSR osrdch
 2540 CMP #13
 2550 BEQ enterpressed
 2560 CPY #0
 2570 BEQ nodelete
 2580 CMP #127
 2590 BNE nodelete
 2600 DEY
 2610 JSR oswrch
 2620 OPT FNjmp(i,c,getfile)
 2630 .nodelete
 2640 CMP #27
 2650 BEQ escape2
 2660 CPY #7                 \ filename length is restricted to 7
 2670 BEQ getfile            \ characters, as this is the DFS length
 2680 JSR validfile
 2690 CMP #0
 2700 BEQ getfile
 2710 STA filename,Y
 2720 JSR oswrch
 2730 INY
 2740 OPT FNjmp(i,c,getfile)
 2750.escape2
 2760OPT FNjmp(i,c,escape)
 2770.enterpressed
 2780STA filename,Y
 2790JSR osnewl
 2800LDX #(saving MOD &100)  \ now save the image
 2810LDY #(saving DIV &100)
 2820JSR print
 2822LDA rom
 2824JSR pagerom             \ page selected ROM in
 2830.loop0
 2840 LDY #0
 2850 .loop1
 2860  LDA (romad),Y         \ first copy to memory
 2870  STA (addr),Y          \ otherwise, we'll save the FS ROM
 2880  INY
 2890  BNE loop1
 2900 INC romad+1
 2910 INC addr+1
 2920 LDA romad+1
 2930 CMP #&C0
 2940 BNE loop0
 2950LDA #0
 2960LDX #(block MOD &100)
 2970LDY #(block DIV &100)
 2980JSR osfile              \ then to disc
 2990LDA #13
 3000JSR oswrch
 3010LDX #(another MOD &100)
 3020LDY #(another DIV &100)
 3030JSR print
 3040.escape                 \ exit program
 3050LDA #126
 3060JSR osbyte
 3070JSR osnewl
 3080LDA basic
 3090JSR pagerom
 3100RTS
 3110.print                  \ print function
 3120STX prtad
 3130STY prtad+1
 3140LDY #0
 3150.printloop
 3160 LDA (prtad),Y
 3170 JSR &FFE3
 3180 INY
 3190 CMP #0
 3200 BNE printloop
 3210RTS
 3220.validfile              \ check for valid filename characters
 3230CMP #48
 3240BCC novalid
 3250CMP #123
 3260BCS novalid
 3270CMP #97
 3280BCS exit
 3290CMP #91
 3300BCS novalid
 3310CMP #58
 3320BCC exit
 3330CMP #65
 3340BCS exit
 3350.novalid
 3360LDA #0
 3370.exit
 3380RTS
 3390.pagerom                \ page ROM in function
 3400OPT FNpagerom(i,c)
 3410RTS
 3420.buffer
 3430]
 3440NEXT
 3450OSCLI "SAVE !BOOT"+STR$c+" "+STR$~(compile%)+" "+STR$~(O%)+" "+STR$~(code)+" "+STR$~(code%)
 3460PRINT"Code size:"CHR$129;P%-code%;CHR$135"bytes"
 3470NEXT
 3480*OPT4 2
 3490END
 3500DEFFNmode7(c,chr)
 3510IFc=0=32ELSE=chr
 3520DEFFNjmp(i,c,label)
 3530IFc<3[OPTi:JMP label:]ELSE[OPTi:BRA label:]
 3540=i
 3550DEFFNphx(i,c)
 3560IFc<3[OPTi:TXA:PHA:]ELSE[OPTi:PHX:]
 3570=i
 3580DEFFNplx(i,c)
 3590IFc<3[OPTi:PLA:TAX:]ELSE[OPTi:PLX:]
 3600=i
 3610DEFFNpagerom(i,c)
 3620IFc>0[OPTi:STA&F4:STA&FE30:]ELSE[OPTi:PHA:LDA#&C:STA&F4:STA&FE05:PLA:STA&F4:STA&FE05:]
 3630=i
Click here to download.

If you would like to email me, put gerald@ in front of the domain name, insead of www..
©2011-2020 Gerald Holdsworth IT Services