The BBC and Master Computer Public Domain Library
Y2B Listing
Or
Back to y2k fix page
10 REM Y2K Fix (ADFS) PLUS 4.00"
20 REM For BBC Master 128 only
30 REM Co-processor compatible
40 address=&70
50 count=&DD10
60 flag =&DD11
70 length=&73
80 dir_flag=&74
90 file_num=&75
100 deleted=&76
110 escaping=&77
120 pblock=&DD00
130 deletion=&DD20
140 delblock=&DD27
150 process =&DD40
160 oldvec =&DFDE
170 OSBYTE=&FFF4
180 OSFIND=&FFCE
190 OSFILE=&FFDD
200 OSRDCH=&FFE0
210 OSASCI=&FFE3
220 OSNEWL=&FFE7
230 OSWRCH=&FFEE
240 oscli=&FFF7
250 res_init=&8FC9
260 :
270 zp=&A8
280 zp1=&A9
290 :
300 DIM C% 3000
310 FOR D% = 4 TO 7 STEP 3
320 P%=&8000
330 O%=C%
340 [OPT D%
350 EQUB &00
360 EQUW &00
370 JMP service
380 EQUB &82
390 EQUB copy-&8000
400 EQUB &04
410 .title
420 EQUS "Y2K Fix (ADFS) PLUS"
430 EQUB &00
440 EQUS "4.00"
450 .copy
460 EQUB &00
470 EQUS "(C) 2004 Raffaele Giaccio, Mark Bush"
480 EQUB &00
490 .service
500 CMP #&27
510 BEQ reset
520 CMP #&22
530 BEQ workspace
540 CMP #&24
550 BNE othercmds
560 DEY:RTS
570 .othercmds
580 PHA:PHX:PHY
590 CMP #&04
600 BEQ calljmp
610 CMP #&09
620 BEQ hlpjmp
630 \
640 .exit
650 PLY:PLX:PLA:RTS
660 .claimed
670 PLY:PLX:PLA:LDA#0:RTS
680 \
690 .hlpjmp JMP help
700 .calljmp JMP call
710 \
720 .workspace
730 PHA
740 TYA
750 STA &0DF0,X
760 INY
770 PLA
780 RTS
790 \
800 .reset
810 PHA
820 LDA &020C
830 STA oldvec
840 LDA &020D
850 STA oldvec+1
860 LDX #&00
870 LDY #&FF
880 LDA #&A8
890 JSR OSBYTE
900 STX zp
910 STY zp1
920 LDY #&12
930 LDA #hours MOD 256
940 STA (zp),Y
950 INY
960 LDA #hours DIV 256
970 STA (zp),Y
980 INY
990 LDX &F4
1000 TXA
1010 STA (zp),Y
1020 LDA &0DF0,X
1030 STA zp1
1040 LDA #&00
1050 STA zp
1060 LDA &020C
1070 SEC
1080 SBC #&01
1090 STA (zp)
1100 INC zp
1110 LDA &020D
1120 SBC #&00
1130 STA (zp)
1140 INC zp
1150 LDA #write MOD 256
1160 SEC
1170 SBC #&01
1180 STA (zp)
1190 INC zp
1200 LDA #write DIV 256
1210 SBC #&00
1220 STA (zp)
1230 LDA #&12
1240 STA &020C
1250 LDA #&FF
1260 STA &020D
1270 PLA
1280 RTS
1290 \
1300 .hours
1310 CMP #&0E
1320 BEQ clock
1330 JMP (oldvec)
1340 \
1350 .clock
1360 PHY
1370 PHX
1380 PHA
1390 PHA
1400 PHA
1410 PHA
1420 PHA
1430 PHA
1440 PHY
1450 LDX &F4
1460 LDA &0DF0,X
1470 STA zp1
1480 LDA #&00
1490 STA zp
1500 TSX
1510 LDA (zp)
1520 STA &0103,X
1530 INC zp
1540 LDA (zp)
1550 STA &0104,X
1560 INC zp
1570 LDA (zp)
1580 STA &0105,X
1590 INC zp
1600 LDA (zp)
1610 STA &0106,X
1620 PLY
1630 STY zp1
1640 LDA &0108,X
1650 STA zp
1660 LDA (zp)
1670 STA &0107,X
1680 LDA &0108,X
1690 TAX
1700 PLA
1710 RTS
1720 \
1730 .write
1740 PLA
1750 PHA
1760 CMP#&01
1770 BEQ done
1780 PHP
1790 TSX
1800 LDA &0103,X
1810 STA zp
1820 LDA &0104,X
1830 STA zp1
1840 LDA #ASC("2")
1850 LDY #&0B
1860 STA (zp),Y
1870 LDA #ASC("0")
1880 INY
1890 STA (zp),Y
1900 PLP
1910 .done
1920 TSX
1930 INX
1940 TXS
1950 PLX
1960 PLY
1970 LDA #&0E
1980 RTS
1990 \
2000 .call
2010 LDA (&F2),Y
2020 AND#&DF
2030 CMP#ASC"R":BNE call2
2040 INY:LDA (&F2),Y
2050 AND#&DF:CMP#ASC"E"
2060 BNE ex_jmp
2070 INY:LDA (&F2),Y
2080 AND#&DF:CMP#ASC"S"
2090 BNE ex_jmp
2100 JMP res_init
2110 \
2120 .ex_jmp JMP exit
2130 \
2140 .call2
2150 CMP#ASC"K"
2160 BEQ secondchr
2170 BRA commcall
2180 .secondchr INY
2190 LDA (&F2),Y
2200 AND#&DF
2210 CMP#ASC"L"
2220 BEQ endit0
2230 BRA commca
2240 .endit0
2250 JMP Key_show
2260 .commca DEY
2270 LDA (&F2),Y
2280 AND#&DF
2290 .commcall
2300 CMP#ASC"D"
2310 BEQ check_dr
2320 \
2330 LDX#0
2340 .commloop
2350 LDA(&F2),Y
2360 AND#&DF
2370 CMP name1,X
2380 BNE wipe_out
2390 INY:INX
2400 CPX#4
2410 BNE commloop
2420 LDA(&F2),Y:CMP#&0D
2430 BEQ wipe
2440 CMP#ASC" ":BEQ wipe
2450 BRA check_dr
2460 .wipe_out CMP#&0E
2470 BEQ check_dot:bra check_dr
2480 .check_dot CPX#3:BPL wipe
2490 .check_dr LDX#0
2500 .commloop2
2510 LDA(&F2),Y
2520 AND#&DF
2530 CMP#&0E
2540 BEQ check_dot2
2550 CMP comm1,X
2560 BNE zout
2570 INY:INX
2580 CPX#5
2590 BNE commloop2
2600 BRA overthis
2610 .check_dot2
2620 CPX#2
2630 BPL overthis
2640 .zout JMP exit
2650 .overthis
2660 INY
2670 LDA(&F2),Y
2680 CMP#&20
2690 BNE found
2700 BRA overthis
2710 .found
2720 STA process+6
2730 LDA#&0D
2740 STA process+7
2750 \
2760 LDX#0
2770 .Nmloop
2780 LDA comm0,X
2790 beq haltnow
2800 STA process,X
2810 INX
2820 BRA Nmloop
2830 .haltnow
2840 LDX #process MOD 256
2850 LDY #process DIV 256
2860 JSR oscli
2870 JMP claimed
2880 \
2890 .wipe LDX#0
2900 .Push LDA &70,X
2910 PHA:INX
2920 CPX#&08:BNE Push
2930 \
2940 LDX#0:.lp STZ &70,X:INX
2950 CPX#&0E:BNE lp:LDX#0
2960 .setup LDA name2,X
2970 STA deletion,X:INX
2980 CPX#7:BEQ exit_lp0
2990 BRA setup
3000 .exit_lp0
3010 \
3020 LDX#0
3030 .start
3040 LDA data,X
3050 STA address
3060 INX
3070 LDA data,X
3080 STA address+1
3090 LDY#0
3100 LDA(address)
3110 BEQ end11
3120 CMP#&24:BEQ incr
3130 BRA next01
3140 .incr INX:bra start
3150 .end11 JMP restore
3160 .next01 LDY#0
3170 .filesB LDA (address),Y
3180 BEQ end11
3190 CMP#&0D:BEQ typeB
3200 CMP#&8D:BEQ typeB
3210 CMP#&00:BEQ typeB
3220 STA process,Y:STA delblock,Y
3230 INY:CPY#10:BEQ type_crB
3240 BRA filesB
3250 .typeB LDA#&20:STA process,Y
3260 STA delblock,Y:INY
3270 CPY#10:BEQ type_crB:bra typeB
3280 .type_crB LDA#&0D:STA process,Y
3290 STA delblock,Y:STY length
3300 PHX:JSR erase:PLX
3310 LDA escaping:CMP#1:BEQ stop4
3320 LDA deleted:BEQ next03
3330 STZ deleted:BRA next01
3340 .next03 INX:BRA start
3350 .stop4 JMP restore
3360 \
3370 .erase STZ dir_flag
3380 STZ escaping
3390 LDA#0:STA pblock+14
3400 JSR file_type:LDA file_num
3410 CMP#0:BEQ stay3jmp
3420 CMP#&01:BEQ go
3430 CMP#&02:BEQ Pstay4
3440 CMP#&FF:BEQ stay3jmp
3450 RTS
3460 \
3470 .Pstay4 LDA#1
3480 STA dir_flag:BRA go
3490 .Jstay7 JMP stay7
3500 .stay3jmp jmp stay3
3510 .go LDX#0
3520 .e_loop0 LDA delblock,X
3530 CMP#&0D:BEQ go_out
3540 CMP#&80:BPL s:BRA re_pt
3550 .s SEC:LDA delblock,X
3560 SBC#&80:STA delblock,X
3570 .re_pt JSR OSWRCH
3580 INX:JMP e_loop0
3590 .go_out LDA#&0D:STA delblock,X
3600 \
3610 LDA dir_flag:BNE Jstay4:BRA Over
3620 .Jstay4 JMP stay4
3630 .Over
3640 .go22 LDX#0
3650 .YN_loop LDA question,X
3660 BEQ go_out2
3670 JSR OSWRCH
3680 INX:JMP YN_loop
3690 .go_out2 LDA#15:JSR OSWRCH
3700 LDA pblock+14:AND#&08:CMP#&08:BEQ Jstay7
3710 LDA pblock+14:AND#&09:CMP#&09:BEQ Jstay7
3720 .select
3730 LDA#21:LDX#0:JSR OSBYTE
3740 JSR OSRDCH
3750 CMP#&1B:BEQ stay5
3760 CMP#89:BEQ delete
3770 CMP#121:BEQ delete
3780 CMP#110:BEQ stay
3790 CMP#78:BEQ stay
3800 BNE select
3810 .delete JSR OSWRCH
3820 LDX #deletion MOD 256
3830 LDY #deletion DIV 256
3840 JSR oscli
3850 LDA#1:STA deleted
3860 JSR OSNEWL:RTS
3870 \
3880 .stay JSR OSWRCH
3890 .stay2 JSR OSNEWL:RTS
3900 .stay3 LDx#0:.L0 LDA delblock,X
3910 BEQ ty:CMP#13:BEQ ty:CMP#&80
3920 BPL subtr:bra prt:.subtr SEC:LDA delblock,X
3930 SBC#&80:STA delblock,X:BRA prt:CMP#&00:BEQ ty
3940 .prt JSR OSWRCH:INX:BRA L0:.ty LDX#0
3950 .L1 LDA name5,X:BEQ st:JSR OSASCI
3960 INX:BRA L1
3970 .st RTS
3980 \
3990 .stay4 LDX#0
4000 .show_dir LDA name3,X:BEQ end_stay04
4010 JSR OSWRCH:INX:BRA show_dir
4020 .end_stay04 JSR OSNEWL:STZ dir_flag:RTS
4030 .stay5 LDA#1:STA escaping:RTS
4040 .stay7 LDX#0:.L3 LDA name4,X:BEQ st2
4050 JSR OSWRCH:INX:BRA L3
4060 .st2 lda#7:jsr OSWRCH:jsr OSNEWL
4070 STZ pblock+14:RTS
4080 \
4090 .file_type
4100 LDA #process MOD 256:STA pblock
4110 LDA #process DIV 256:STA pblock+1
4120 LDA#length MOD 256:STA pblock+11
4130 LDA#length DIV 256:STA pblock+14
4140 LDA#&05
4150 LDX#pblock MOD 256
4160 LDY#pblock DIV 256
4170 JSR OSFILE
4180 STA file_num
4190 RTS
4200 \
4210 .restore
4220 LDX#&07
4230 .PULL
4240 PLA:STA &70,X
4250 DEX
4260 BPL PULL
4270 JMP claimed
4280 \
4290 .data
4300 EQUW &C405
4310 EQUD &C439C41F
4320 EQUD &C46DC453
4330 EQUD &C4A1C487
4340 EQUD &C4D5C4BB
4350 EQUD &C509C4EF
4360 EQUD &C53DC523
4370 EQUD &C571C557
4380 EQUD &C5A5C58B
4390 EQUD &C5D9C5BF
4400 EQUD &C60DC5F3
4410 EQUD &C641C627
4420 EQUD &C675C65B
4430 EQUD &C6A9C68F
4440 EQUD &C6DDC6C3
4450 EQUD &C711C6F7
4460 EQUD &C745C72B
4470 EQUD &C779C75F
4480 EQUD &C7ADC793
4490 EQUD &C7E1C7C7
4500 EQUD &C815C7FB
4510 EQUW &C82F
4520 EQUD &C863C849
4530 EQUD &C897C87D
4540 EQUD &C8CBC8B1
4550 EQUW &0000
4560 \
4570 .help
4580 jsr OSNEWL:LDX#0
4590 .loop LDA (&F2),Y:CMP#0D
4600 BEQ print:CMP#ASC".":BEQ print
4610 AND #&DF:CMP#63:BMI next
4620 CMP table,X:BNE stop0
4630 .next CMP#&0E:BEQ Rom_title
4640 CMP#&0D:BEQ Rom_title:INY:INX
4650 CPX#19:BNE loop
4660 .proceed CPX#0:BEQ print
4670 CPX#19:BEQ nextchr:BRA stop0
4680 .nextchr DEX:DEY:LDA (&F2),Y
4690 AND #&DF:CMP table,X:BNE stop0
4700 INY:LDA (&F2),Y:CMP#&0D:BEQ print
4710 CMP#ASC" ":BNE stop0:.print ldx#0
4720 .loophlp1 lda string,X:beq end0:jsr OSASCI
4730 inx:bra loophlp1: .end0 jsr OSNEWL
4740 .stop0 JMP exit
4750 .Rom_title CPX#0:BNE stop0
4760 ldx#0:.lp2 lda title,x:beq halt
4770 jsr OSWRCH:inx:bra lp2
4780 .halt jsr OSNEWL:JMP exit
4790 \
4800 .Key_show
4810 JSR OSNEWL
4820 LDX#0
4830 .loop11
4840 LDA string2,X
4850 beq stop11
4860 JSR OSASCI
4870 INX:BRA loop11
4880 .stop11 JSR OSNEWL
4890 LDA#&0E:JSR OSWRCH
4900 LDX#0
4910 STZ count
4920 .s_loop0
4930 LDY#0
4940 .keyloop
4950 LDA Kdata,X
4960 JSR OSWRCH
4970 INX:INY
4980 CPY#&08
4990 BNE keyloop
5000 \
5010 LDY#0
5020 .kcomloop
5030 LDA Kdata,x
5040 STA process,Y
5050 INX:INY
5060 CPY#&07
5070 BNE kcomloop
5080 PHX
5090 LDX#process MOD 256
5100 LDY#process DIV 256
5110 JSR oscli
5120 PLX
5130 inc count
5140 LDA count
5150 CMP#&10
5160 BNE s_loop0
5170 JMP claimed
5180 \
5190 .Kdata
5200 EQUS"*KEY 00 SHOW00":EQUB&0D
5210 EQUS"*KEY 01 SHOW01":EQUB&0D
5220 EQUS"*KEY 02 SHOW02":EQUB&0D
5230 EQUS"*KEY 03 SHOW03":EQUB&0D
5240 EQUS"*KEY 04 SHOW04":EQUB&0D
5250 EQUS"*KEY 05 SHOW05":EQUB&0D
5260 EQUS"*KEY 06 SHOW06":EQUB&0D
5270 EQUS"*KEY 07 SHOW07":EQUB&0D
5280 EQUS"*KEY 08 SHOW08":EQUB&0D
5290 EQUS"*KEY 09 SHOW09":EQUB&0D
5300 EQUS"*KEY 10 SHOW10":EQUB&0D
5310 EQUS"*KEY 11 SHOW11":EQUB&0D
5320 EQUS"*KEY 12 SHOW12":EQUB&0D
5330 EQUS"*KEY 13 SHOW13":EQUB&0D
5340 EQUS"*KEY 14 SHOW14":EQUB&0D
5350 EQUS"*KEY 15 SHOW15":EQUB&0D
5360 \
5370 .string equb&0D
5380 equs"Y2K Fix (ADFS) PLUS 4.00":equb&0D
5390 equs" CMOS clock millennium correction":equb&0D
5400 equs" <DRIVE> (id)":equb&0D
5410 equs" <KL>":EQUB&0D
5420 equs" <RES>":EQUB&0D
5430 equs" <WIPE>":equb&0D:equb&00
5440 \
5450 .string2 EQUS"Press 'SHIFT' if necessary."
5460 EQUB&0D:EQUB&00
5470 \
5480 .comm0 EQUS"*DIR :":EQUB&00
5490 .comm1 EQUS"DRIVE":EQUB&00
5500 .name1 EQUS"WIPE"
5510 .name2 EQUS"DELETE "
5520 .name3 EQUS " Directory":EQUB&00
5530 .name4 EQUS " Locked file":EQUB13:EQUB0
5540 .name5 EQUS " Protected file":EQUB13:EQUB0
5550 .question EQUS " DELETE (Y/N) :":EQUB0
5560 .table equs"Y2K FIX (ADFS) PLUS 4.00"
5570 EQUB0:nop:nop:nop:nop
5580 .dne:]:NEXT
5590 S$=STR$ ~C%:E$=STR$ ~(dne-&8000+C%)
5600 OSCLI "SAVE Y2KBROM "+S$+" "+E$
5610 OSCLI "SRLOAD Y2KBROM 8000 7"
5620 REM SAVE "Y2BROMS"
The listing for 'Y2BROMS' generates the machine code for
a ROM/ROM image, occupying from &8000 to about &8700; that is all that
is needed for *DRIVE, *KL, the millennium correction and *WIPE. There is a small
section of the listing incorporating the updated PANEL (*RES) routine. This
can be removed if you don't need this command in your ROM/Image by simply deleting
line 5100 and lines 2030 to 2140; renumber to tidy up.
Starting at lines 2000 to 2140;- the Panel utility is supplied on the Welcome
disc and is designed to run from &5FBD in main memory. It is a very fussy
piece of machine code. I have had to 'copy' the code from main memory to &9000
onwards, amend it, and then use a segment of machine code to download it back
down into main memory and initialize it when called by *Res. This code lies
at &8FC9, see the variable 'res_init' in the listing. Therefore, after sorting
out that the correct command is used in lines 2000 to 2190, a jump is made to
&8FC9 to get Panelrom working.
The first few lines of the program initialize variables, set &A8 and &A9
as the zero page basis for post-indexed indirect addressing for the millennium
correction (zp, zp1), and set-up the ROM header. &A8 and &A9 are in
MOS scratch space and can be used quite safely for our purposes without the
need to keep worrying about preserving zero page locations. Although I have
made some drastic alterations to Mark Bush's original programme, especially
further down the listing, I have tried to retain his basic programming structure.
General exit points are at 'exit' (unclaimed), and 'claimed' (claimed actions).
I push the registers onto the stack at 'othercmds' for commands (ROM service
call &04) and for * Help (call &09) and I pull the registers off on
exit from these routines, typically at the general exit points. For the sake
of speed, 'reset', &27, 'workspace' claim, &22 (using dynamic filing
system RAM to preserve PAGE), and &24 for confirming workspace allocation
are spared the usual general register stacking. I have saved a bit more code
and time in 'workspace' by pushing A, transferring & incrementing Y, and
simply pulling A back off the stack and exiting; and by doing the same in 'reset'
In lines 800 to 1280, 'reset' has evolved somewhat. Again, on resets, I push
A onto the stack to begin with then pull it off the stack at line 1270 and exit
immediately. Now, before the OSBYTE &A8 is executed, I store the old vector
in oldvec/oldvec+1. This saves a lot of code in 'hours' (used to be labelled
'TIM') where, if we are not dealing with OSWORD &0E, a jump to (oldvec)
in 'hours' in effect restores control to the Master via the pristine MOS routines.
This is where there is a substantial departure from Mark's programming. Basically,
the rest of 'reset' is as previously. 'TIM" which I now call 'hours', is
reduced to a mere 4 lines by making this jump to (oldvec). Typically, in MOS
3.20 this is &EF39.
'clock' is almost identical, except for some differences in stack manipulations.
'RET' is now denoted by 'write'. There are now some obvious differences in
the stack and stack pointer programming.
I believe that overall, efficiency of the Master's millennium correction clock
has substantially improved. You would do well to read Mark Bush's notes to get
an overview of the ideas behind the basic programming.
Perhaps this is a good point to state that I have tested the all programs and
the ROMs/ROM Images on my own Masters, as indeed I have extensively tested all
my programs. Any problems found to-date (though minor) have been documented.
All programs/listings/ideas are offered to you as is without any warranty, either
expressed or implied and I am not liable for any damage that may result from
their use. Please note that I retain copyright to all of my works, but you are
free to use my programs without charge for private use. Please advise me if
you intend to use my programs in public well in advance of the scheduled time,
or if you have any problems with any of them.
'call2'simply tries to recognise the command, *KL. If correctly called, a jump
is made to 'Key_show' (see lines 4800 to 5350), a routine which displays all
the Function Key definitions consecutively, very much like the *SHOW command
would do on a Master Compact. This involves very simple programming and if there
is something that you cannot understand about this, please email me at rafg1@bigpond.net.au
. Briefly, 'loop11' prints out advice about pressing the "Shift key".
Then the fist eight characters of each key string are read in from 'Kdata' and
printed. Next, the last seven characters of the key string are read in and stored
at 'process' where 'oscli' treats them as a command string (*SHOW
: &0D).
And so the MOS does all the work for each key assignment, which are all printed
out consecutively in the loop 's_loop0' until 'count' is incremented to 16 (&10)
when a jump to 'claimed' is made to end, return to BASIC and to claim the command
*kL.
There is virtually no change in programming for 'help" - it provides just
enough information for the user.
The ADFS wipe routine is basically unchanged, apart from some tidier programming.
This leaves *DRIVE. This command is recognised in lines 2490 to2650. The drive
id that is entered at the keyboard, etc. is stored at 'process + 6' followed
by a carriage return at 'process+7'. These are preceded by *DIR : and oscli
does the rest (lines 2760 to 2870). Simple but effective.
Finally, if you download the .zip file, you will find even more helpful details
and examples.
Raf Giaccio 06/06/2004