×   Main Menu ALL The 8BS News Manuals (New menu) Links Worth a Look Tools Disc and Basic Webring Site Map 8BS Guestbook Old Guest Book Me The Barnsley Rovers   
8-Bit Software

The BBC and Master Computer Public Domain Library

Y2K Fix BASIC Listing

     10 REM Y2K fix for CMOS clock
     20 REM Copyright (C) Mark Bush 2002
     30 REM For BBC Micros with CMOS clock
     40 :
     50 REM Uses 2 bytes of zero page at
     60 REM &70, &71, preserving contents
     70 REM and a page of static RAM (only
     80 REM 4 bytes are used).
     90 :
    100 ZP=&70
    110 ZP1=&71
    120 OSBYTE=&FFF4
    130 DIM C% 1000
    140 FOR D% = 4 TO 7 STEP 3
    150 P%=&8000
    160 O%=C%
    170 [OPT D%
    180 \ setup ROM header
    190 EQUB &00
    200 EQUW &00
    210 JMP SERVICE
    220 EQUB &82           \ code for a normal service ROM
    230 EQUB COPY-&8000
    240 EQUB &02
    250 EQUS "MJB Y2K Fix"
    260 EQUB &00
    270 EQUS "2.00"
    280 .COPY
    290 EQUB &00
    300 EQUS "(C)2002 Mark Bush"
    310 EQUB &00
    320 .SERVICE
    330 CMP #&02   \ claim static RAM
    340 BEQ WKSP
    350 CMP #&27   \ a reset has occurred
    360 BEQ RESET
    370 RTS
    380 .WKSP
    390 TYA
    400 STA &0DF0,X  \ save our workspace page number
    410 LDA #&02
    420 INY       \ claim 1 page for our use
    430 RTS
    440 .RESET
    450 \ after a reset, the MOS vectors will have been reset
    460 \ so we need to redo the redirection of OSWORD through
    470 \ our routine
    480 TYA
    490 PHA
    500 \ save zero page locations
    510 LDA ZP
    520 PHA
    530 LDA ZP1
    540 PHA
    550 \ OSBYTE &A8 retrieves start of extended vector area
    560 LDX #&00
    570 LDY #&FF
    580 LDA #&A8
    590 JSR OSBYTE
    600 \ (X;Y) returned
    610 STX ZP
    620 STY ZP1
    630 \ each vector is 3 bytes long and OSWORD is the 7th so
    640 \ we need to offset 18 bytes (6 vectors) to reach it
    650 LDY #&12
    660 \ save new vector as:
    670 \ byte 1: target low byte
    680 \ byte 2: target high byte
    690 \ byte 3: ROM number to page in to access target
    700 LDA #TIM MOD 256
    710 STA (ZP),Y
    720 INY
    730 LDA #TIM DIV 256
    740 STA (ZP),Y
    750 INY
    760 LDX &F4   \ our ROM number
    770 STA (ZP),Y
    780 \ retrieve our saved workspace page number
    790 LDA &0DF0,X
    800 STA ZP1
    810 LDA #&00
    820 STA ZP
    830 \ get current address of the OSWORD routine (which may
    840 \ already be redirected) and save 1 less in our workspace
    850 \ (we use the trick of pushing the address on the stack
    860 \ and using RTS to go there which adds 1 to the address)
    870 LDA &020C
    880 SEC
    890 SBC #&01
    900 STA (ZP)
    910 INC ZP
    920 LDA &020D
    930 SBC #&00
    940 STA (ZP)
    950 \ do the same for the address we want OSWORD to return to
    960 \ for call &0E so we can process the output
    970 INC ZP
    980 LDA #RET MOD 256
    990 SEC
   1000 SBC #&01
   1010 STA (ZP)
   1020 INC ZP
   1030 LDA #RET DIV 256
   1040 SBC #&00
   1050 STA (ZP)
   1060 \ restore the zero page locations
   1070 PLA
   1080 STA ZP1
   1090 PLA
   1100 STA ZP
   1110 \ set WORDV to now redirect through extended vectors
   1120 LDA #&12
   1130 STA &020C
   1140 LDA #&FF
   1150 STA &020D
   1160 \ restore state and return
   1170 PLA
   1180 TAY
   1190 LDA #&27
   1200 RTS
   1210 .TIM
   1220 \ OSWORD now always redirects here first
   1230 \ check if it is call &0E for the CMOS
   1240 \ clock routine
   1250 CMP #&0E
   1260 BEQ CLOCK
   1270 \ save call number
   1280 PHA
   1290 \ keep 2 stack places for the OSWORD address
   1300 \ to return to
   1310 PHA
   1320 PHA
   1330 \ preserve X
   1340 TXA
   1350 PHA
   1360 \ preserve zero page locations
   1370 LDA ZP
   1380 PHA
   1390 LDA ZP1
   1400 PHA
   1410 \ get our ROM number, retrieve our workspace page and
   1420 \ extract the saved OSWORD address and put it in the
   1430 \ stack over the 2 places saved for it above
   1440 LDX &F4
   1450 LDA &0DF0,X
   1460 STA ZP1
   1470 LDA #&00
   1480 STA ZP
   1490 TSX
   1500 LDA (ZP)
   1510 STA &0105,X
   1520 INC ZP
   1530 LDA (ZP)
   1540 STA &0106,X
   1550 \ restore zero page
   1560 PLA
   1570 STA ZP1
   1580 PLA
   1590 STA ZP
   1600 \ restore X and A
   1610 PLA
   1620 TAX
   1630 PLA
   1640 \ stack now has the address (less 1) of OSWORD
   1650 \ so RTS will go there as if it had been called
   1660 \ normally
   1670 RTS
   1680 .CLOCK
   1690 \ we now know that we are in the CMOS clock OSWORD (&0E)
   1700 \ preserve Y and X
   1710 TYA
   1720 PHA
   1730 TXA
   1740 PHA
   1750 \ keep 1 space to hold the type of call this is (X;Y):
   1760 \ 0: return string of date and time
   1770 \ 1: return BCD format not including the century
   1780 \ 2: turn BCD format into string format
   1790 PHA
   1800 \ keep 4 stack places
   1810 \ these will be the OSWORD address and our address of
   1820 \ RET so that a return from the real OSWORD comes back to us
   1830 PHA
   1840 PHA
   1850 PHA
   1860 PHA
   1870 \ preserve zero page locations
   1880 LDA ZP
   1890 PHA
   1900 LDA ZP1
   1910 PHA
   1920 \ as before, get the OSWORD and RET addresses and
   1930 \ put them into their places in the stack
   1940 LDX &F4
   1950 LDA &0DF0,X
   1960 STA ZP1
   1970 LDA #&00
   1980 STA ZP
   1990 TSX
   2000 \ OSWORD address
   2010 LDA (ZP)
   2020 STA &0103,X
   2030 INC ZP
   2040 LDA (ZP)
   2050 STA &0104,X
   2060 \ RET address
   2070 INC ZP
   2080 LDA (ZP)
   2090 STA &0105,X
   2100 INC ZP
   2110 LDA (ZP)
   2120 STA &0106,X
   2130 \ save (X;Y)
   2140 STY ZP1
   2150 LDA &0108,X
   2160 STA ZP
   2170 LDA (ZP)
   2180 STA &0107,X
   2190 \ restore X
   2200 LDA &0108,X
   2210 TAX
   2220 \ restore zero page
   2230 PLA
   2240 STA ZP1
   2250 PLA
   2260 STA ZP
   2270 \ restore A
   2280 LDA #&0E
   2290 \ "return" to OSWORD
   2300 RTS
   2310 .RET
   2320 \ OSWORD will return to this point
   2330 \ retrieve the call type (X;Y)
   2340 PLA
   2350 \ if it is 1 then we are done
   2360 CMP #&01
   2370 BEQ DONE
   2380 \ otherwise preserve zero page locations
   2390 LDA ZP
   2400 PHA
   2410 LDA ZP1
   2420 PHA
   2430 \ get X and Y to access the return string
   2440 TSX
   2450 LDA &0103,X
   2460 STA ZP
   2470 LDA &0104,X
   2480 STA ZP1
   2490 \ set century to "20"
   2500 LDA #ASC("2")
   2510 LDY #&0B
   2520 STA (ZP),Y
   2530 LDA #ASC("0")
   2540 INY
   2550 STA (ZP),Y
   2560 \ restore zero page
   2570 PLA
   2580 STA ZP1
   2590 PLA
   2600 STA ZP
   2610 .DONE
   2620 \ we are done
   2630 \ restore X, Y and A and return
   2640 PLA
   2650 TAX
   2660 PLA
   2670 TAY
   2680 LDA #&0E
   2690 RTS
   2700 .DNE
   2710 ]
   2720 NEXT
   2730 S$=STR$ ~C%
   2740 E$=STR$ ~(DNE-&8000+C%)
   2750 OSCLI "SAVE Y2KROM "+S$+" "+E$