In fact it was 542 bytes previously, but now is 538 bytes. Seems to work if loaded on M128 at &DCD0 or on BBC at &8C0, so here it is so far. It's part commented, but mostly only where I needed to know what it was doing. It will either build the original 510 byte version or build a 7-bit year compatible version of 538 bytes:
Actually, I have just noticed that my routine to print the 2 year digits is very similar to the original Acorn code to print the 2 digits of the day of the month at ddb8, so I wonder if I could re-use that and save more bytes.
Code:
100REM Acorn *DATE Source Code 200REM Reverse engineered from 510-byte M128 Library1 *DATE 300REM Original code (C) Acorn a long time ago 400REM Disassembly, commentary and Y2K fixes (C) Ian Wolstenholme 2025 500REM Version 1.0 20/ii/2025 WIP 600REM Done on Station 201 700REM Assembling with y2kfix=TRUE will build a version of *DATE which 800REM will correctly report the file server date in the range 1981 to 2080 900REM with the correct day of week for dates after 31/3/1984 1000REM Assembling with y2kfix=FALSE will build an identical version of *DATE 1100REM to the 510 byte version on L4Support Library1 (also with the 31/3/1984 1200REM day bug) using the original load address of &900 or &DD00 1300REM ***NOTE*** Y2KFIX version is too long to load safely in M128 workspace 1400REM at &DD00 which if doing so will corrupt the filing system name table 1500REM held in page &DF; appears to work if loaded at &DCD0 1600REM BBC B Y2KFIX is also too long to load safely at original &900 addr 1700REM as this will overwrite the FKey buffer in page &B; appears to work 1800REM if loaded at &8C0 1900DIM code 768 2000load=&DCD0:REM &8C0 for BBC B 2100osword=&FFF1 2200oswrch=&FFEE 2300osnewl=&FFE7 2400y2kfix=TRUE 2500FORB%=4 TO 7 STEP3 2600P%=load:O%=code 2700[OPTB% 2800.fsdate 2900] 3000IFy2kfix ELSE PROCsetup 3100[OPTB% 3200 LDA #&14 \ 3300 LDX#osblk MOD256 \ Point to control block 3400 LDY#osblk DIV256 \ 3500 JSR osword \ Call OSWORD 3600 LDA #&09 \ print "Today is " 3700 JSR de1a \ 3800 JSR getday \ print day of week stub 3900 LDA #&11 \ print "day the " 4000 JSR de1a 4100 JSR ddb8 \ print date and th etc. 4200 LDA #&15 \ print " of " 4300 JSR de1a 4400 LDA dee2 \ print month 4500 AND #&0F 4600 ADC #&06 4700 JSR de31 4800] 4900IFy2kfix THEN PROCpry2k ELSEPROCpryear 5000[OPTB% 5100.getday LDA dee2 \ Routine to get day of week, Get low byte of date 5200 LSR A 5300 LSR A 5400 LSR A 5500 LSR A \ Shift 4 bits, now A=year low bits 5600 STA def9 \ Store in def9 5700] 5800IFy2kfix THEN PROC7bityear 5900[OPTB% 6000 TAX \ X=A 6100 INX \ X=X+1 6200 LSR A 6300 LSR A \ Shift A 2 bits 6400 STA defa \ Store A in defa 6500 LDA dee2 \ A=months/years 6600 AND #&0F \ Get months 6700 CMP #&03 \ A=3 ? 6800 PHA \ Push A 6900 LDX defa \ X=defa, stored earlier 7000 BCC dd7c \ Branch if A>=3 7100 LDX def9 \ X=year, n.b. includes 7 bit year if used 7200 INX \ X=X+1 7300 TXA \ A=X 7400 LDX defa \ X=defa 7500 AND #&03 \ 7600 BNE dd7c \ If A<>3 goto dd7c 7700 INX \ Otherwise X=X+1 7800.dd7c DEX \ X=X-1 7900 STX defa \ Store X in defa 8000 PLA \ A=months 8100 PHA \ Push A 8200 TAX \ X=A=months 8300 CMP #&03 \ 8400 BCC dd88 \ If A<3 goto dd88 8500 DEX \ Otherwise X=X-1 8600.dd88 DEX \ X=X-1 8700 TXA \ A=X 8800 ASL A \ Shift A 1 bit 8900 STA defb \ Store A in defb 9000 PLA \ A=months 9100 TAX \ X=A 9200 CMP #&09 \ 9300 BCC dd95 \ If A<9 goto dd95 9400 INX \ Otherwise X=X+1 9500.dd95 TXA \ A=X 9600 LSR A \ Shift A 1 bit 9700 CLC \ Clear carry 9800 ADC defb \ Add defb 9900 ADC dee1 \ Add dee110000 ADC defa \ Add defa10100 ADC def9 \ Add def910200 SEC \ Set carry10300 SBC #&03 \ A=A-310400.dda7 CMP #&07 \10500 BCC ddb0 \ if A<7 goto ddb010600 SEC \ Set carry10700 SBC #&07 \ A=A-710800 BPL dda7 \ If A>0 goto dda710900.ddb0 JSR de3111000 LDA #&0E11100 JMP de1a \ End of getday routine11200.ddb8 LDA #&FF11300 STA defb11400 LDA dee111500 SEC11600.ddc1 INC defb11700 SBC #&0A11800 BCS ddc111900 ADC #&0A12000 STA defd12100 LDA defb12200 BEQ ddd712300 ORA #&3012400 JSR oswrch12500.ddd7 LDA defd12600 ORA #&3012700 JSR oswrch12800 LDX defb12900 CPX #&0113000 BEQ prth13100 CMP #&3113200 BEQ prst13300 CMP #&3213400 BEQ prnd13500 CMP #&3313600 BEQ prrd13700.prth LDA #&74 \ print th13800 JSR oswrch13900 LDA #&6814000 JMP oswrch14100.prst LDA #&73 \ print st14200 JSR oswrch14300 LDA #&7414400 JMP oswrch14500.prnd LDA #&6E \ print nd14600 JSR oswrch14700 LDA #&6414800 JMP oswrch14900.prrd LDA #&72 \ print rd15000 JSR oswrch15100 LDA #&6415200 JMP oswrch15300.de1a STA defb \ Store A in defb15400 LDY defc \ Load Y with defc (=0 on first visit here)15500.de20 LDA today,Y \ print Today string beginning at Y offset15600 JSR oswrch \ Call OSWRCH15700 INY \ Inc Y15800 CPY defb \ Check if stored value of A15900 BNE de20 \ Continue round loop if not16000 STY defc \ Store Y in defc16100 CLC \ Clear carry16200 RTS \ Return16300.de31 TAX16400 LDA offset,X16500 TAX16600 LDA days,X16700 JSR oswrch16800 INX16900.de3d LDA days,X17000 CMP #&5B17100 BCC de4a17200 JSR oswrch17300 INX17400 BNE de3d17500.de4a RTS17600.offset EQUB 0 \ Offset table for strings, point to Sun17700 EQUB 3 \ point to Mon etc...17800 EQUB 6 \17900 EQUB &0A \18000 EQUB &10 \18100 EQUB &15 \18200 EQUB &18 \18300 EQUB &1D \ point to January18400 EQUB &24 \18500 EQUB &2C \18600 EQUB &31 \18700 EQUB &36 \18800 EQUB &39 \18900 EQUB &3D \19000 EQUB &41 \19100 EQUB &47 \19200 EQUB &50 \19300 EQUB &57 \19400 EQUB &5F \ point to December19500.days EQUS"SunMonTuesWednesThursFriSatur"19600.months EQUS"JanuaryFebruaryMarchAprilMayJuneJulyAugustSeptemberOctoberNovemberDecember"19700.today EQUS"Today is day the of 19"19800]19900IFy2kfix PROCy2kosblk ELSEPROCosblk20000[OPTB%20100.def9 EQUB 020200.defa EQUB 020300.defb EQUB 020400.defc EQUB 020500.defd EQUB 020600]20700IFy2kfix ELSE [OPTB%:.defe EQUB0 :]20800[OPTB%20900]21000NEXT21100PRINT"DATE assembles as ";O%-code-1;" bytes. Save using:"21200PRINT" *SAVE DATEY2K ";~code;" ";~O%-1;" ";~load OR &FFFF0000;" ";~load OR &FFFF000021300END21400DEFPROCpry2k21500REM Cope with all years 1981 to 208021600[OPTB%21700.pry2k LDAdef9 \ Get year21800 CMP#19 \ Yr>2000?21900 BCSy2kcont \ Branch to y2kcont22000 ADC#8122100 STAdef922200 JMPstartpr \ Add 81 to year if C20th22300.y2kcont SBC#19 \ Deduct 19 to get actual C21st year22400 STAdef922500\ LDX#&1622600 LDA#ASC"2"22700 STAtoday+&1622800\ INX22900 LDA#ASC"0"23000 STAtoday+&17 \ Overwrite today string "19" with "20"23100.startpr23200 LDA#&1823300 JSRde1a \ Use original print routine for century23400 LDAdef9 \ Restore A23500 TAY23600 LDX#&FF:SEC23700.pr10 INX23800 SBC#1023900 BCSpr1024000 ADC#1024100 JSRprit24200 TAX24300 JSRprit24400 JMPosnewl24500.prit PHA24600 TXA24700 ORA#4824800 JSRoswrch24900 PLA25000 RTS25100]25200ENDPROC25300DEFPROCpryear25400REM Original Acorn code to print year in 1980 or 90s only25500[OPTB%25600.pryr25700 LDA #&18 \ print " 19"25800 JSR de1a25900 LDA def9 \ A=year26000 ADC #&31 \ Add &31 ="1"26100 LDY #&38 \ Y=&38 ="8"26200 CMP #&3A \ A=&3A?26300 BCC dd45 \ Branch if A>&3A26400 SBC #&0A \ A=A-1026500 INY \ Y=Y+1, increment decade26600.dd45 TAX \ X=A26700 TYA \ A=Y (="8" or "9")26800 JSR oswrch \ print decade digit26900 TXA \ A=X27000 JSR oswrch \ print unit digit27100 JMP osnewl \ CR and exit27200]27300ENDPROC27400DEFPROC7bityear27500REM Support 7-bit years stored in 2-byte date/time field27600[OPTB%27700 LDA dee1 \ Load low byte of date27800 AND#&E0 \ Get top 3 bits for year27900 LSR A \ Shift left 1 bit, value is now offset28000 CLC \ Clear carry28100 ADCdef9 \ Add 4 bit year already stored28200 STA def9 \ Update def928300 LDA dee1 \ Reload low byte of date28400 AND#&1F \ Get low 5 bits for day of month28500 STA dee1 \ Store28600 LDAdef9 \ Update A to 7 bit year28700]28800ENDPROC28900DEFPROCosblk29000REM Original Acorn code OSWORD block memory reservation29100[OPTB%29200.osblk EQUD 029300.dee1 EQUB 029400.dee2 EQUD 029500 EQUD 029600 EQUD 029700 EQUD 029800 EQUD 029900 EQUW 030000 EQUB 030100]30200ENDPROC30300DEFPROCy2kosblk30400REM Y2KFix OSWORD block, pre-fill with values and only use 6 bytes30500[OPTB%30600.osblk EQUB030700 EQUB&930800 EQUB030900 EQUB&1031000.dee1 EQUB031100.dee2 EQUB031200]31300ENDPROC31400DEFPROCsetup31500REM Original Acorn start of code to load values into OSWORD block31600[OPTB%31700 LDA #&09 \ Set up OSWORD &14 call with function code31800 STA osblk+1 \ &10 - read FS time and date31900 LDA #&1032000 STA osblk+332100]32200ENDPROC
Statistics: Posted by BeebMaster — Thu Feb 20, 2025 11:47 pm