BBC Master 128 and Y2000
The hardware of
Acorn Computers' BBC Master 128 microcomputer includes a real-time
clock. Unfortunately the Machine Operating System (MOS) only handles
the real-time clock up to 1999. To quote page 26 of Acorn's "Welcome
Guide" for the Master series:
The CMOS RAM holds and maintains a
perpetual calendar which caters for all dates (including leap years)
until the year 2000.
When the guide was written in 1986, the year
2000 probably seemed like a long way in the future. However, I'm writing this
in 1999 and the year 2000 is pretty darn close.
The real-time clock integrated circuit in the BBC Master 128 is a 146818.
From reading a Hitachi datasheet for their HD146818, the IC provides a
one-hundred year calendar by storing just a 2-digit year. Furthermore,
when the year number is a multiple of 4 a leap year is assumed (so we
might have more trouble in the year 2100, which isn't a leap year).
Since the real-time clock IC doesn't know about the century, clearly it
is Acorn's MOS which is assuming that the date is in the 20th century.
I resolved to see what could be done to make the real-time clock work
into the 21st century.
My objective was to come up with a patch to the MOS ROM. This could
be implemented either by:
- burning a new 128K MOS ROM/EPROM, or
- by putting a new 16K ROM into an overlay board (e.g.
Vine Micros'
Master OS Overlay Board ).
( There is a alternative approach to the problem.
Doomsday
is a commercial sideways ROM which tackles several issues, including
the Y2000 problem ).
It doesn't seem possible to obtain an EPROM device which is a drop-in
replacement for the 128K MOS ROM. The MOS ROM is a
128K × 8 (1 megabit) device in a 28-pin 'dual in line' (DIL)
package, whereas the majority of 128K × 8 EPROMs (e.g.
27C010
) are in 32-pin DIL packages.
It is possible to create
an adaptor board to
enable a 32-pin DIL 128K × 8 EPROM to be used with the 28-pin DIL
MOS ROM socket on the main board. Then one needs to burn the
8 16K ROM images in the one EPROM. The ordering of the images is:
Megabit ROM Offset | Rom Number | ROM Name
|
---|
00000 | - | Operating System
|
04000 | 9 | 1770 DFS
|
08000 | 10 | Viewsheet
|
0C000 | 11 | Edit
|
10000 | 12 | BASIC
|
14000 | 13 | ADFS
|
18000 | 14 | View
|
1C000 | 15 | Terminal
|
I believe that Vine Micros no longer make or support their Master OS Overlay Board.
It was a popular add-on at the time, so you may already have one of them. If not,
please contact me, because we might be able to have clones of the board made.
Armed with my trusty machine code monitor, I set to work to look at the
OSWORD &0E (Read Real-time Clock) and &0F (Write Real-time clock) code.
Incidently, as part of this exercise I discovered the same documentation
error in Acorn's Master Series Reference Manual - Part 1 (page D.3-25)
and Adder Publishing's The New Advanced User Guide (page 356). When
using OSWORD &0F to write the date and time, the format of the
parameter block on entry should be:
XY = 24
XY+1 to XY+15 = <date string>
XY+16 = 46 (i.e. ASCII code for ".")
XY+17 to XY+25 = <time string>
Looking at the MOS code for handling the real-time clock, two observations
were made:
- The code which writes the date to the real-time clock totally ignores
the century supplied by the user.
- The code which converts a BCD clock value to a date/time string (i.e.
the code used by OSWORD &0E with XY=0 and XY=2) always returns "19"
as the century.
As a result of trying a few tests, I also discovered made an interesting
observation regarding the real-time clock IC:
- The day of the week (Monday, Tuesday, etc) is not coupled to the date, other
than when the date is incremented at midnight, the day of the week is
incremented too.
This allows the real-time clock IC to be set to a date in any century. One can
equally well set the real-time clock's date registers to Monday, 1 Jan 00 (e.g. 1900)
or Saturday 1 Jan 00 (e.g. 2000).
With this information, there are several different possible ways to solve
the 21st century problem:
- Leave the OSWORD &0F code alone, as it ignores the user-supplied century.
Change the OSWORD &0E code to always return "20" as the century.
This is a solution which works from 1 Jan 2000, but returns the wrong
year information for 1999. It would be a good fix to apply from 2000.
- Leave the OSWORD &0F code alone, as it ignores the user-supplied century.
Change the OSWORD &0E code, so that it returns "19" as the century for
two digit years greater than a certain number (e.g. 80), and returns
"20" for the century for years less than that number.
This would return the correct year information for a one hundred year
period (e.g. 1980 - 2079).
- Instead of storing the real 2 digit year number in the real-time clock
IC, store it with an offset (e.g. '00' in the IC is used to represent
1980, '20' to represent 2000, and '99' to represent 2079).
Provided the offset is a multiple of 4, the leap year calculation in
the IC is not affected.
This would need a change to the OSWORD &0F code, as it no longer could
ignore the user-supplied century, and would need to subtract the offset.
The OSWORD &0E code would need to be modified to determine the correct
century and add the offset.
Whilst option 3 is technically neat, it needs the most modifications to the
existing MOS. It also alters the meaning of the contents of the year register
within the real-time clock, and so might cause problems with 3rd party
software which directly reads the real-time clock IC.
Option 3 has thus not been investigated.
There are (at least) two versions of the MOS ROM for the BBC Master 128. The
original MOS ROM was version 3.20: some time later the alternative MOS
ROM was made available, this was version 3.50
(Both versions had buggy DFS code, which no doubt helped the sales of the Vine
Micros' overlay board.
- v3.20 had the 'CLOSE #0' bug in the ROMed DFS, which led Acorn to supply
later DFS ROM images on floppy disk.
- v3.50 had the 'Disc Write Protected' bug in the ROMed DFS, together with non-working
OSWORD &7D and &7E calls. When carrying out this current patching activity
I found that I was using my overlay board to supply
a patched DFS 2.45 ROM for MOS 3.50.
).
Patches for the original MOS ROM (v3.20)
For solution 1, there is a single byte to change.
This is at address &9881 in rom 15 (i.e. Terminal), which corresponds to offset
1D881 in the 1 Megabit ROM image.
Its current value is &19; change this to &20
to change the century number (note that the value is the century number in
BCD, not in decimal).
For solution 2, there is spare room in rom 15 for the
patch code at the end of page &B8: if using the overlay board approach,
this means one needs to burn a 16K ROM to overlay rom 15.
The patches are shown below. The Megabit ROM Offset is the
offset into the 1 Megabit ROM (useful if you've used my
BBC BASIC program to save the whole 1 Megabit ROM image to file).
The BBC Address is the address in the BBC memory
map (with ROM 15 active).
Megabit ROM Offset | BBC Address | Old byte | New Byte | | Old Code | New Code
|
---|
1D880 | 9880 | A9 | 20 | | LDA #&19 | JSR &B8E0
|
1D881 | 9881 | 19 | E0 | |
|
1D882 | 9882 | 20 | B8 | | JSR &9893
|
1D883 | 9883 | 93 | EA | | | NOP
|
1D884 | 9884 | 98 | EA | | | NOP
|
Megabit ROM Offset | BBC Address | Old byte | New Byte | | Old Code | New Code
|
---|
1F8E0 | B8E0 | FF | C9 | | (blank) | CMP #&38
|
1F8E1 | B8E1 | FF | 38 | | (blank)
|
1F8E2 | B8E2 | FF | A9 | | (blank) | LDA #&19
|
1F8E3 | B8E3 | FF | 19 | | (blank)
|
1F8E4 | B8E4 | FF | B0 | | (blank) | BCS &B8E8
|
1F8E5 | B8E5 | FF | 02 | | (blank)
|
1F8E6 | B8E6 | FF | A9 | | (blank) | LDA #&20
|
1F8E7 | B8E7 | FF | 20 | | (blank)
|
1F8E8 | B8E8 | FF | 4C | | (blank) | JMP &9893
|
1F8E9 | B8E9 | FF | 93 | | (blank)
|
1F8EA | B8EA | FF | 98 | | (blank)
|
Patches for the Alternative MOS ROM (v3.50)
For solution 1, there is a single byte to change.
This is at address &9664 in rom 15 (i.e. Terminal), which corresponds to offset
1D664 in the 1 Megabit ROM image.
Its current value is &19; change this to &20
to change the century number (note that the value is the century number in
BCD, not in decimal).
For solution 2, there is not room in rom 15 for the patch code. However
there is plenty of spare room in the OS area in page &FB:
if using the overlay board approach, this means one needs to burn 2 16K ROMs, to overlay
rom 15 and the OS.
The patches are shown below. The Megabit ROM Offset is the
offset into the 1 Megabit ROM (useful if you've used my
BBC BASIC program to save the whole 1 Megabit ROM image to file).
The BBC Address is the address in the BBC memory
map (with ROM 15 active).
Megabit ROM Offset | BBC Address | Old byte | New Byte | | Old Code | New Code
|
---|
1D663 | 9663 | A9 | 20 | | LDA #&19 | JSR &FBF0
|
1D664 | 9664 | 19 | F0
|
1D665 | 9665 | 20 | FB | | JSR &9676
|
1D666 | 9666 | 76 | EA | | | NOP
|
1D667 | 9667 | 96 | EA | | | NOP
|
Megabit ROM Offset | BBC Address | Old byte | New Byte | | Old Code | New Code
|
---|
03BF0 | FBF0 | FF | C9 | | (blank) | CMP #&38
|
03BF1 | FBF1 | FF | 38 | | (blank)
|
03BF2 | FBF2 | FF | A9 | | (blank) | LDA #&19
|
03BF3 | FBF3 | FF | 19 | | (blank)
|
03BF4 | FBF4 | FF | B0 | | (blank) | BCS &FBF8
|
03BF5 | FBF5 | FF | 02 | | (blank)
|
03BF6 | FBF6 | FF | A9 | | (blank) | LDA #&20
|
03BF7 | FBF7 | FF | 20 | | (blank)
|
03BF8 | FBF8 | FF | 4C | | (blank) | JMP &9676
|
03BF9 | FBF9 | FF | 76 | | (blank)
|
03BFA | FBFA | FF | 96 | | (blank)
|
Description of patch code
The code just prior to the
LDA #&19
JSR ...
writes the 2 digit year from the real-time clock
IC as a string in reverse order, so when it has finished writing the 2 digit
year the accumulator holds the ASCII code for the decade number in BCD (e.g.
&38 for the 80s, &39 for the 90s, and &30 for the 00s).
The patch tests whether the ASCII code for the decade number in BCD is 8 or 9:
if it is, "19" in BCD is used for the century, otherwise "20" in BCD is used
for the century.
This patch allows the year to be in the range 1980 - 2079. If the comparison
at address &B8E0 (MOS 3.20)/&FBF0 (MOS 3.50) was made with #&39, then the year would be allowed
in the range 1990-2089, giving an extra 10 years of operation.
Patching the MOS ROM
Provided that one patches one's existing OS ROM, I forsee no copyright problems.
Acorn have not replied to an e-mail asking what their position is, which I take
to mean that they're not interested.
One needs to download the existing code to a file, patch the file, and then burn
a new EPROM (or two).
Downloading the existing code
If using the Vine Micros' Master OS Overlay Board , then one needs
to download a copy of ROM 15 (Terminal) (for solutions 1 and 2).
For solution 2 with MOS 3.50, one also needs to download the OS area.
If burning a whole new 128K × 8 EPROM, one needs to download a copy of
ROMs 9-15 and the OS area.
The easiest solution is probably to use my
BBC BASIC program to save the whole 1 Megabit ROM image to file.
If you want to download the individual sideways ROMs to files, there
are many utilities to do this.
One also needs to download the OS area. It is slightly harder to download the
OS area, because it is overlaid in two areas:
- &C000-DFFF, by the Filing System RAM (HAZEL)
One needs to clear bit 3 of the ACCON register (at address &FE34) in order
to read the MOS ROM contents in this address range.
- &FC00-FEFF, by memory mapped I/O
The fact that there is code (for MOS 3.50) in these pages isn't directly mentioned
in the literature.
The BBC Master documentation refers to bit 6 of the ACCON register (at address
&FE34) as being for "hardware test". In fact, setting this bit maps the
MOS ROM in to pages &FC,&FD, and &FE (instead of memory-mapped I/O - FRED,
JIM, and SHEILA).
It appears that read operations read from the MOS ROM, but that write
operations (certainly to SHEILA) write to the memory-mapped I/O.
The startup routine in MOS 3.50 calls code in these pages (in MOS 3.20 these pages
just contain some informative text), and so when
patching MOS 3.50 one needs to ensure that the original code is preserved in these pages.
As it is slightly tricky to read these pages, here is a code fragment
which shows how to do the job:
Address | Code
|
---|
2000 | SEI
|
2001 | LDA &FE34
|
2004 | STA &20FF
|
2007 | ORA #&4C
|
2009 | STA &FE34
|
200C | LDY #&00
|
200E | LDA &FC00,Y
|
2011 | STA &2100,Y
|
2014 | LDA &FD00,Y
|
2017 | STA &2200,Y
|
210A | LDA &FE00,Y
|
210D | STA &2300,Y
|
2020 | INY
|
2021 | BNE &200E
|
2023 | LDA &20FF
|
2026 | STA &FE34
|
2029 | CLI
|
202A | BRK
|
Using the Vine Micros' Master OS Overlay Board
For solution 1, one needs to save a copy of ROM 15 (Terminal),
patch the single
byte concerned, burn a new EPROM with this patched image, and put it into the
Vine Micros' Master OS Overlay Board in a free socket. Jumper link 7
to the socket used.
For solution 2, follow the above steps, but there are more
bytes to patch in ROM 15.
If working with MOS 3.50, one also needs to patch the OS area: save a copy of the
OS area, patch the bytes, burn a new EPROM with this patched image, and put it into
the Vine Micros' Master OS Overlay Board in a free socket.
Jumper link 0 to the socket used.
Burning a new MOS ROM
What one needs to do is:
- Download the 8 16K ROM images (sideways ROMs 9-15, and the OS area) from the MOS ROM.
Use my BBC BASIC program to save the MOS image to file
to do this in one operation.
- Patch the appropriate images:
- If working with separate ROM images, assemble the 8 16K ROM images (sideways ROMs 9-15,
and the OS area) into a single 128K file, in the following order:
- OS area
- 1770 DFS
- Viewsheet
- Edit
- BASIC
- ADFS
- View
- Terminal
- Burn a 128K × 8 EPROM (27C010) with this image.
- Make an adaptor to enable one to plug a 32-pin EPROM into the 28-pin MOS ROM socket.
- Remove the MOS ROM from the board.
- Plug the adaptor into the board, and the EPROM into the adaptor.
- Turn the computer on, and see if it works.
Information supplied by Andrew Benham (G8FSL), Salisbury, Wilts SP1,
United Kingdom