ROM Tool
About
ROM Tool (RT) is a simple BASIC utility to program sideways RAM and EEPROM modules with ROM images.
Written in BBC BASIC 2 for an Acorn BBC Microcomputer Model A/B.
The commented version requires PAGE at &1200 or below. The uncommented version will run with PAGE at &2000 so should work with multiple filesystems loaded (e.g. DFS & MMFS, ADFS etc).
Permission is freely given to copy and modify this source for non-commercial use.
How do I transfer this to my BBC?
Special thanks to Jonathan Harston for bug fixes and feature improvements.
SSD Disc Image
Current version RTool v1.06 (10 April 2022)
Download RTool v1.06 SSD (10 April 2022)
Download RTool v1.05 SSD (16 January 2022)
Disc Contents
|
RTool |
Comments stripped version. OK for PAGE at &2000 |
|
BAS2PRG |
Program BASIC 2 into the EEPROM |
|
V.RT106 |
Commented version. OK for PAGE at &1200 |
|
R.RT106 |
ROM FS image for *ROM file system |
|
SRTEST |
Sideways RAM test program |
|
EETEST |
EEPROM test program |
|
ORTEST |
OS RAM test program |
Instructions
Mount disc image then CHAIN"RTOOL" to run. Press ? for command summary/help.
Basic version
RTool requires BASIC version 2 or later. Most machines will already have a BASIC2 ROM fitted.
To find out which BASIC you have press BREAK then type REPORT at the prompt. It will display "(C)1981 Acorn" for BASIC1 or "(C)1982 Acorn" for BASIC2.
BASIC2 is a useful upgrade. You can program BASIC2 into the EEPROM with CHAIN"BAS2PRG" on the tools disk. Follow the on screen instructions. When BASIC2 is programmed you should turn off the machine and remove your original BASIC1 ROM. BASIC2 will run from the EEPROM module.
Most users will want BASIC to be the highest priority ROM so it starts when the machine is turned on. To do this load BASIC2 into the highest bank number of your EEPROM and insert the EEPROM module in the right most ROM socket of the BBC Micro.
Automate RTool
RTool is a BASIC program which means you can automate it with !BOOT or *EXEC.
For example on a floppy disc (or solid state disc image).
*OPT4,3 *BUILD !BOOT CHAIN"RTOOL" L:0.R.RT102 P4 Q <ESCAPE>
On SHIFT+BREAK (or *EXEC !BOOT) this !BOOT file would run RTool, load ROM image R.RT101 from drive 0, program it to slot/bank 4 and quit.
Source
REM BooBip.com
REM BASIC sideways EEPROM/FLASH/RAM utility
REM (C)2017-2022 Chris Morley
:
MODE7:IFHIMEM>&7C00:PRINT "Must run on BBC I/O processor":END
MODE&87:HIMEM=HIMEM-&4000:roms%=&80:mc%=&B20:ver$="1.06"
*FX18
PROCassemble
PRINT"BooBip.com"'"BASIC sideways EEPROM/RAM utility v";ver$
P.FNromlist
ON ERROR REPORT:PRINT
REPEAT:PRINT"? ";:K$=GET$:IF K$>"`":K$=CHR$(ASCK$-32)
F$="unrecognised":A$=""
RESTORE
REPEAT:READ key$,func$,arg$,help$:IF key$=K$ THEN F$=func$:A$=arg$
UNTIL key$=""
PRINT K$;" ";
IF A$<>"" THEN INPUT LINE ""A$:A%=VAL(A$):IF A$=""THENF$="argument"
PRINT EVAL("FN"+F$);:IF POS THEN PRINT
UNTIL FALSE
DATA I,romlist,,List ROMs
DATA *,oscli,,Issue user OS Command
DATA .,cat,,Catalogue filesystem (*.)
DATA D,drive,,Change drive
DATA L,load,,Load ROM image from file
DATA S,save,,Save ROM image to file
DATA R,read,,Read ROM image from bank
DATA C,clear,,Clear ROM image buffer
DATA P,program,,Write ROM image to bank
DATA V,verify,,Verify ROM image in bank
DATA E,erase,,Erase ROM bank
DATA M,chiperase,,Erase module
DATA K,lock,,Lock (write protect) SRAM
DATA U,unlock,,Unlock (write enable) SRAM
DATA Q,quit,,Quit
DATA B,reset,,Reboot computer
DATA ?,help,,Display this help
DATA ,,,
DEFFNunrecognised="Unrecognised command. ? for help"
DEFFNargument="Missing argument. ? for help"
DEFFNquit
PRINT:END
=""
DEFFNreset
*KEY10OLD|MRUN|M
*FX143,15,255
CALL !-4
=""
DEFFNoscli
OSCLI(A$)
=""
DEFFNcat
PRINT:*CAT
=""
DEFFNdrive
OSCLI("DIR :"+A$)
=""
DEFFNload
CALL fill
R$="LOAD "+A$+" "+STR$~HIMEM
OSCLI R$
=R$
DEFFNsave
R$="SAVE "+A$+" "+STR$~HIMEM+"+4000"
OSCLI R$
=R$
DEFFNread
CALL copy_down
=""
DEFFNclear
CALL fill
=""
DEFFNprogram
R$="IGNORED"
IF FNr(1) THEN R$="EEPROM":CALL ee_write
IF FNr(2) THEN R$="FLASH":CALL f_erase:CALL f_write
IF FNr(&20) THEN R$="SRAM":CALL sr_unlock:CALL copy_up:CALL sr_lock
="Program "+R$+" bank "+STR$(A%)
DEFFNverify
S%=USR(verify) AND 255
IF S% THEN R$=" OK" ELSE R$=CHR$(129)+"failed"
="Verify"+R$
DEFFNerase
CALL fill
IF FNr(1) THEN CALL ee_write
IF FNr(2) THEN CALL f_erase
IF FNr(&20) THEN CALL sr_unlock:CALL copy_up
=""
DEFFNchiperase
IF FNr(3) THEN PRINT"Confirm erase entire module Y/N?":K$=GET$:IF K$="Y" CALL ee_erase
=""
DEFFNlock
CALL sr_lock
=""
DEFFNunlock
CALL sr_unlock
=""
DEFFNhelp
RESTORE:REPEAT
READ key$,func$,arg$,help$:IF key$<>"" THEN PRINT'" ";key$;" ";arg$;TAB(10);CHR$(134);help$;
UNTIL key$=""
=""
DEFPROCscan
FOR A%=0TO15:T%=0
REM Blank check
S%=USR(blankcheck) AND &FF:IF S%=&FF THEN T%=128
REM Writeable check
S%=USR(sr_testw) AND &FF:IF S%=0 THEN T%=T% OR &10
CALL sr_unlock
S%=USR(sr_testw) AND &FF:IF S%=0 THEN T%=T% OR &20
IF T%=&20 THEN CALL sr_lock
roms%?A%=T%
N.
REM Find EEPROM/FLASH
FOR A%=0TO3
B%=0:FOR J%=A%TO15STEP4:B%=B%ORroms%?J%:N.
IF (B% AND &20)=0 THEN R%=FNcheckid:FOR J%=A%TO15STEP4:roms%?J%=roms%?J% OR R%:NEXT
NEXT
ENDPROC
DEFFNromlist
PROCscan
PRINT'"ROM Type Title";
FOR A%=15 TO 0 STEP -1
C%=131:IF A%=?&24B C%=133
PRINT';A%;CHR$(134);TAB(3);FNtype;CHR$(C%);TAB(10);
IF FNr(&80) THEN PRINT"(blank)"; ELSE CALL print_rom_title:VDU 8
NEXT
REM P.'"Free ";HIMEM-LOMEM
=""
DEFFNtype
R$="ROM"
IF FNr(1) THEN R$="EEPROM"
IF FNr(2) THEN R$="FLASH "
IF FNr(&30)=&30 THEN R$="SRAM U"
IF FNr(&30)=&20 THEN R$="SRAM L"
=R$
DEFFNcheckid
J%=0:S%=USR(ee_readid) AND &FFFF
IF S%=&5DBF THEN J%=1
IF S%=&B5BF THEN J%=2
=J%
DEFFNr(M%)=roms%?A% AND M%
REM EEPROM detect, program & erase subroutines
DEFPROCassemble
bufpage%=HIMEM DIV 256
src=&70:dst=src+2:rom=src+4
FOR pass%=0TO2STEP2
P%=mc%
[opt pass%
.copyright
EQUB 0:EQUS "(C)"
.set_addrs
LDA #&BF:STA dst+1 \ dst=&BFxx
LDA #bufpage%+&3F:STA src+1 \ src=buf+&3F00, eg &7Bxx
LDY #0:STY src+0:STY dst+0 \ dst=&BF00, src=&7B00, Y=0
RTS
.prologue
STA rom
PLA:TAY:PLA:TAX \ stash return address
PHP:SEI \ save IRQ state & disable interrupts
LDA &F4:PHA \ save current ROM
TXA:PHA:TYA:PHA \ stack return address
JSR set_addrs
.selectROM
LDA #0
.selectROM_Cmd
ORA rom
.selectROM_A
STA &F4:STA &FE30 \ select ROM
RTS
\*******************
\ JEDEC magic sequence
\ params; ROM# in rom, command in X
\ returns; (nothing)
.magic
JSR magicpre
ORA #&44:JSR selectROM_A:STX &9555 \ chip write &5555=cmd
LDA #&40:JMP selectROM_Cmd \ select correct ROM
.magicpre
LDA rom:AND #3
ORA #&44:JSR selectROM_A:LDY #&AA:STY &9555 \ chip write &5555=&AA
AND #&43:JSR selectROM_A:LDY #&55:STY &AAAA \ chip write &2AAA=&55
RTS
\*******************
\ JEDEC read chip ID
\ params; ROM# in A
\ returns; Mfg ID in X Chip ID in A
.ee_readid
JSR prologue
LDX #&90:JSR magic \ chip enter ID mode
LDA &8000:PHA:LDA &8001:PHA \ read mfg & id
LDX #&F0:JSR magic \ chip leave ID mode
PLA:TAX:PLA
JMP cleanexit
\*******************
\ EEPROM erase chip
\ params; ROM# in A
\ returns; (nothing)
.ee_erase
JSR prologue
LDX #&80:JSR magic:LDX #&10:JSR magic \ JEDEC chip erase sequence
JSR ee_wait
JMP cleanexit
\*******************
\ EEPROM write
\ params; ROM# in A
\ returns; (nothing)
.ee_write
JSR prologue
.ee_pagewrite
LDX #&A0:JSR magic \ select ROM and EEPROM enter page program mode
LDY#0
.ee_pagewrite1:LDA (src),Y:STA (dst),Y:INY:BPL ee_pagewrite1 \copy 128 bytes data
JSR ee_wait
LDX #&A0:JSR magic
LDY#&80
.ee_pagewrite2:LDA (src),Y:STA (dst),Y:INY:BMI ee_pagewrite2 \copy 128 bytes data
JSR ee_wait
DEC src+1:DEC dst+1
BMI ee_pagewrite \ loop while still data to copy
JMP cleanexit
.ee_wait
LDX &8000:CPX &8000
BNE ee_wait:RTS \ wait for write to complete
\*******************
\ FLASH erase
\ params; ROM# in A
\ returns; (nothing)
.f_erase
JSR prologue
.fe_loop
LDX #&80:JSR magic
JSR magicpre
LDA #&40:JSR selectROM_Cmd \ select correct ROM
LDA #&30:STA (dst),Y:JSR ee_wait \ erase 4K block
LDA dst+1:SEC:SBC #&10:STA dst+1:BMI fe_loop
JMP cleanexit
\*******************
\ FLASH write
\ params; ROM# in A
\ returns; (nothing)
.f_write
JSR prologue
.fw_loop
TYA:PHA
LDX #&A0:JSR magic \ JEDEC write & select ROM
PLA:TAY
LDA (src),Y:STA (dst),Y
JSR ee_wait \ wait for write to complete
INY:BNE fw_loop \ copy 256 bytes
DEC src+1:DEC dst+1
BMI fw_loop \ loop while still in ROM
JMP cleanexit
\*******************
\ blank check
\ params; ROM# in A
\ returns; A=&FF if blank
.blankcheck
JSR prologue
LDA #&FF:LDX #&BF:STX bc_tploop+2:LDX #0 \initialise loop
.bc_tploop:AND &8000,X:INX:BNE bc_tploop
CMP #&FF:BNE cleanexit
DEC bc_tploop+2
BMI bc_tploop
.cleanexit
TAY \ save result
PLA:JSR selectROM_A \ restore previous ROM
PLP:TYA:RTS \ restore IRQs, return A=result
\*******************
\ Print ROM title
\ params; ROM# in A
\ returns; (nothing)
.print_rom_title
ORA #&40 \ set EE/FLASH we to show even if module inhibited
JSR prologue
LDX &8007 \ get copyright offset
LDY #0 \ offset to check bytes
.copyrightloop
LDA copyright,Y:CMP &8000,X \ check ROM (C) string
BNE cleanexit \ no valid ROM, exit
INX:INY
CPY #4:BNE copyrightloop \ check four bytes
.copyrightok
LDX #9
.printloop
CPX #39:BCS prtexit \ wrapped past end of screen line
LDA &8000,X:BMI prtexit \ end if >&7F
BNE prtout:LDA #32 \ convert NULL to SPC
.prtout
CMP #32:BCC prtexit \ end if control code
JSR &FFEE \ print character
INX:CPX &8007:BNE printloop \ loop until arrived at (C) string
.prtexit
JMP cleanexit
\*******************
\ Copy low memory to sideways RAM
\ params; ROM# in A
\ returns; (nothing)
.copy_up
JSR prologue
.copy_loop2
LDA (src),Y:STA (dst),Y \ copy 256 bytes
INY:BNE copy_loop2
DEC src+1:DEC dst+1
BMI copy_loop2 \ loop while still in ROM
JMP cleanexit
\*******************
\ Copy ROM to low memory
\ params; ROM# in A
\ returns; (nothing)
.copy_down
JSR prologue
.copy_loop
LDA (dst),Y:STA (src),Y \ copy 256 bytes opposite way
INY:BNE copy_loop
DEC src+1:DEC dst+1
BMI copy_loop \ loop while still in ROM
JMP cleanexit
\*******************
\ Fill low memory with &FF
\ params; (nothing)
\ returns; (nothing)
.fill
JSR set_addrs \ dst=&BF00, src=&7B00, Y=0
LDA #&FF
.fill_loop1
STA (src),Y \ fill 256 bytes
INY:BNE fill_loop1
DEC src+1:DEC dst+1 \ use dst for count
BMI fill_loop1 \ loop while still in ROM
RTS
\*******************
\ Verify ROM
\ params; ROM# in A
\ returns; &FF=Ok, &00=Bad
.verify
JSR prologue
.verify_loop
LDA (src),Y:CMP (dst),Y \ verify 256 bytes
BNE verify_bad
INY:BNE verify_loop
DEC src+1:DEC dst+1
BMI verify_loop \ loop while still in ROM
LDA #&FF:JMP cleanexit \ &FF=Ok
.verify_bad
LDA #&00:JMP cleanexit \ &00=Bad
\*******************
\ Set write protect sideways RAM
\ params; ROM# in A
\ returns; (nothing)
.sr_lock
JSR prologue
LDA #&20:JSR selectROM_Cmd \ set up
JMP cleanexit
\*******************
\ Clear write protect sideways RAM
\ params; ROM# in A
\ returns; (nothing)
.sr_unlock
JSR prologue
LDA #&30:JSR selectROM_Cmd \ set up
JMP cleanexit
\*******************
\ Test writeable sideways RAM
\ params; ROM# in A
\ returns; A=0 if writeable
.sr_testw
JSR prologue
LDY#0
LDX &8008:TXA \ test binary version byte
EOR #&FF:STA &8008,Y:EOR &8008 \ test if writeable. abs,Y to work around PLD v1 bug
PHA:TXA:STA &8008,Y:PLA \ restore binary version byte
JSR ee_wait \ wait in case slot is EE without WP & active BASIC
JMP cleanexit
]:NEXT
REM P."MC size=";(P%-mc%),~P%
ENDPROC
