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?

SSD Disc Image

Current version RTool v1.04 (8 December 2019)

Download SSD

Disc Contents

RTool

Comments stripped version. OK for PAGE at &2000

BAS2PRG

Program BASIC 2 into the EEPROM

V.RT104

Commented version. OK for PAGE at &1200

R.RT104

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/RAM utility
REM (C)2017-2019 Chris Morley
:
MODE7:IFHIMEM>&7C00:PRINT "Must run on BBC I/O processor":END
MODE&87:HIMEM=HIMEM-&4000:roms%=&80:mc%=&B40:ver$="1.04"
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$)
UNTIL FALSE

DATA I,romlist,,List ROMs
DATA *,oscli,<cmd>,Issue user OS Command
DATA .,cat,,Catalogue filesystem (*.)
DATA D,drive,<drive>,Change drive
DATA L,load,<afsp>,Load ROM image from file
DATA S,save,<afsp>,Save ROM image to file
DATA R,read,<bank>,Read ROM image
DATA P,program,<bank>,Write ROM image
DATA V,verify,<bank>,Verify ROM image
DATA E,erase,<bank>,Erase complete 64K EEPROM
DATA K,lock,<bank>,Lock (write protect) SRAM
DATA U,unlock,<bank>,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
R$="LOAD "+A$+" "+STR$~HIMEM
OSCLI R$
=R$

DEFFNsave
R$="SAVE "+A$+" "+STR$~HIMEM+"+4000"
OSCLI R$
=R$

DEFFNread
CALL copy_down
=""

DEFFNprogram
IF roms%?A% AND &01 THEN R$="EEPROM":CALL ee_write
IF roms%?A% AND &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 ee_erase
=""

DEFFNlock
CALL sr_lock
=""

DEFFNunlock
CALL sr_unlock
=""

DEFFNhelp
RESTORE
REPEAT:READ key$,func$,arg$,help$:IF help$<>"" THEN P.'" ";key$;" ";arg$;TAB(10);CHR$(134);help$;
UNTIL key$=""
=""

DEFPROCscan
REM Blank check
FOR A%=0TO15:S%=USR(ee_blankcheck) AND &FF
IF S%=&FF THEN roms%?A%=2 ELSE roms%?A%=0
N.

REM Writeable check
FOR A%=0TO15
S%=USR(sr_testw) AND &FF:IF S%=0 THEN roms%?A%=roms%?A% OR &10
CALL sr_unlock
S%=USR(sr_testw) AND &FF:IF S%=0 THEN roms%?A%=roms%?A% OR &20
IF roms%?A%=&20 THEN CALL sr_lock
N.

REM Find EEPROM
FOR A%=0TO3
IF (roms%?A% AND &20)=0 THEN S%=USR(ee_readid) AND &FFFF:IF S%=&5DBF THEN FOR J%=A%TO15STEP4:roms%?J%=roms%?J% OR 1:NEXT
NEXT

ENDPROC

DEFFNromlist
PROCscan
PRINT'"ROM Type  Title";
FOR A%=15 TO 0 STEP -1
PRINT';A%;CHR$(134);TAB(3);FNtype(A%);CHR$(131);TAB(10);
IF roms%?A% AND 2 THEN PRINT"(blank)"; ELSE CALL print_rom_title:VDU 8
NEXT
=""

DEFFNtype(R%)
A$="ROM"
IF (roms%?A% AND &01)=&01 THEN A$="EEPROM"
IF (roms%?A% AND &30)=&30 THEN A$="SRAM U"
IF (roms%?A% AND &30)=&20 THEN A$="SRAM L"
=A$

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=&7Bxx
LDY #0:STY src+0:STY dst+0  \ dst=&BF00, src=&7B00
RTS

.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
LDA rom:AND #3
ORA #&44:STA &F4:STA &FE30:LDY #&AA:STY &9555 \ EEPROM write &5555=&AA
AND #&43:STA &F4:STA &FE30:LDY #&55:STY &AAAA \ EEPROM write &2AAA=&55
ORA #&44:STA &F4:STA &FE30:STX &9555          \ EEPROM write &5555=cmd
LDA rom:ORA #&40:STA &FE30                    \ select correct ROM
RTS

\*******************
\ EEPROM read chip ID
\ params; ROM# in A
\ returns; Mfg ID in X Chip ID in A
.ee_readid
STA rom:PHP:SEI             \store flags & disable interrupts
LDA &F4:PHA                 \ save current ROM
LDX #&90:JSR magic          \ EEPROM enter ID mode
LDA &8000:PHA:LDA &8001:PHA \ read mfg & id
LDX #&F0:JSR magic          \ EEPROM leave ID mode
PLA:TAX:PLA
JMP cleanexit

\*******************
\ EEPROM erase chip
\ params; ROM# in A
\ returns; (nothing)
.ee_erase
STA rom:PHP:SEI                       \store flags & disable interrupts
LDA &F4:PHA                           \ save current ROM
LDX #&80:JSR magic:LDX #&10:JSR magic \ EEPROM erase sequence
jsr ee_wait
JMP cleanexit

\*******************
\ EEPROM write
\ params; ROM# in A
\ returns; (nothing)
.ee_write
STA rom:PHP:SEI    \store flags & disable interrupts
LDA &F4:PHA        \ save current ROM
jsr set_addrs      \ src=&7B00, dest=&BF00
.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 \ EEPROM enter page program mode
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 \ wait for write to complete
RTS

\*******************
\ EEPROM blank check
\ params; ROM# in A
\ returns; A=&FF if blank
.ee_blankcheck
STA rom:PHP:SEI     \ store flags & disable interrupts
LDA &F4:PHA         \ save current ROM
JSR selectROM       \ select ROM
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
STA rom:PHP:SEI             \ store flags & disable interrupts
LDA &F4:PHA                 \ save current ROM
JSR selectROM               \ select ROM
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
LDA &8000,X:BNE prtout:LDA #32 \ convert NULL to SPC
.prtout
JSR &FFEE                   \ print character
INX:CPX &8007:BNE printloop \ loop until arrived at (C) string
JMP cleanexit

\*******************
\ Copy low memory to sideways RAM
\ params; ROM# in A
\ returns; (nothing)
.copy_up
STA rom:PHP:SEI             \ store flags & disable interrupts
LDA &F4:PHA                 \ save current ROM
JSR selectROM               \ select ROM
JSR set_addrs               \ dst=&BF00, src=&3B00
.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
STA rom:PHP:SEI             \ store flags & disable interrupts
LDA &F4:PHA                 \ save current ROM
JSR selectROM               \ select ROM
JSR set_addrs               \ dst=&BF00, src=&3B00
.copy_loop1
LDA (dst),Y:STA (src),Y     \ copy 256 bytes opposite way
INY:BNE copy_loop1
DEC src+1:DEC dst+1
BMI copy_loop1              \ loop while still in ROM
JMP cleanexit

\*******************
\ Verify ROM
\ params; ROM# in A
\ returns; &FF=Ok, &00=Bad
.verify
STA rom:PHP:SEI             \ store flags & disable interrupts
LDA &F4:PHA                 \ save current ROM
JSR selectROM               \ select ROM
JSR set_addrs               \ dst=&BF00, src=&3B00
.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
STA rom:PHP:SEI             \ store flags & disable interrupts
LDA &F4:PHA                 \ save current ROM
LDA #&20:JSR selectROM_Cmd  \ set up
JMP cleanexit

\*******************
\ Clear write protect sideways RAM
\ params; ROM# in A
\ returns; (nothing)
.sr_unlock
STA rom:PHP:SEI             \ store flags & disable interrupts
LDA &F4:PHA                 \ save current ROM
LDA #&30:JSR selectROM_Cmd  \ set up
JMP cleanexit

\*******************
\ Test writeable sideways RAM
\ params; ROM# in A
\ returns; A=0 if writeable
.sr_testw
STA rom:PHP:SEI              \ store flags & disable interrupts
LDA &F4:PHA                  \ save current ROM
JSR selectROM                \ select ROM
LDY#0
LDX &8008:TXA                \ test binary version byte
EOR #&FF:STA &8008,Y:EOR &8008 \ test if writeable
PHA:TXA:STA &8008,Y:PLA      \ restore binary version byte
JSR ee_wait \ do in case slot is EE without WP & active BASIC
JMP cleanexit

]
NEXT
REM P."MC size=";(P%-mc%),~P%
ENDPROC