> SoftRTC/src 2 Added module table, added some more comments : (#assem(0)::assem(2):sm_table 2FA$="*SAVE "+fname$+" "+~(mcode%+M%)+" "+~O%+" FFFF0000 FFFBBC00" <A$;:A$: F P: Zassem(pass%) d4ver$="0.10":date$="23 Nov 1992":fname$="SoftRTC" n7OSASCI=&FFE3:OSWRCH=&FFEE:OSNEWL=&FFE7:OSWORD=&FFF1 x4ws=&A8:tmp=ws+7:osw14=14:osw15=osw14+1:save=&D94  mcode% &1000, L%-1 :  pass%=pass% pass%+1 opt%=sm_pass(pass%)+8+16 [OPT opt% .ROMBase EQUB &00:EQUW RelocTable JMP Service #EQUB &82:EQUB copyright-ROMBase .ROMTitle EQUB ver$*10:EQUS "SoftRTC" %EQUB &00:EQUS ver$+" ("+date$+")" .copyright "EQUB &00:EQUS "(C)J.G.Harston"  EQUB &00 : "\ SERVICE 9 - *Help ,\ ----------------- 6 .Serv09 @LDA (&F2),Y J-CMP #13:BNE Serv9Exit :\ Not *Help TJSR OSNEWL ^ .Serv9a h LDX #0 r .Serv9Lp |1LDA &8009,X:BNE Serv9Chk :\ Display ROM title LDA #" ":BNE Serv9Char  .Serv9Chk CMP #" ":BEQ Serv9Done .Serv9Char JSR OSWRCH:INX:BNE Serv9Lp .Serv9Done JSR OSNEWL .Serv9Exit LDA #9:RTS : \ SERVICE 4 - *Command \ --------------------  .Serv04 LDX #0:TYA  .Serv4a PHA & .Serv4Lp 0LDA (&F2),Y:INY :CMP #".":BEQ Serv4Found D CMP TimeText,X:BEQ Serv4Step N #32 X CMP TimeText,X:BNE Serv4Next b.Serv4Step l:INX:TXA: #3:BNE Serv4Lp :\ Loop to match 4 characters v/LDA (&F2),Y:CMP #"@" :\ End of command? ABCC Serv4Found :\ or or .Serv4Next PLA:TAY:CPX #4:LDX #4 BCC Serv4a:TXA:RTS .Serv4Found PLA:JMP cmdTime :  .Service 7CMP #&01:BNE P%+5:JSR RTCRestore :\ CS=Restore time 4CMP #&0F:BCS P%+5:JSR RTCSave :\ CC=Save time 0CMP #&04:BEQ Serv04 :\ *command .CMP #&08:BEQ Serv08 :\ OSWORD -CMP #&09:BEQ Serv09 :\ *help RTS  : \ SERVICE 8 - OSWORD  \ ----------------- * .Serv08 4 LDA &EF >string terminated with CR .Osw14Convert  LDY #0 4LDA ws+4: #&07:JSR PutDay :\ Day LDA #",":JSR PutChar  5LDA ws+3: #&3F:JSR PutBCD:JSR PutSpace :\ Date 6LDA ws+2: #&1F:JSR PutMonth:JSR PutSpace :\ Month 7LDA ws+0:JSR PutBCD:LDA ws+1:JSR PutBCD :\ Year (LDA #".":JSR PutChar 2 LDX #&FD <.Osw14ConvLp1 F9LDA 255(ws+5-&FD),X: #&7F:JSR PutBCD :\ HH, MM, SS P.LDA #":":JSR PutChar:INX:BNE Osw14ConvLp1 ZDEY:LDA #13:STA (&F0),Y d: n.Osw14Done x LDY #0  .Osw14lp5 7PLA:STA ws,Y:INY:CPY #tmp-ws+1 :\ Restore workspace BCC Osw14lp5:LDA #0:RTS : 3.PutSpace :\ Store a space LDA #" ":BNE PutChar  .PutBCD #PHA:JSR HexTopDigit:JSR PutChar PLA:JSR HexDigit 7.PutChar :\ Store a character STA (&F0),Y:INY:RTS :  .PutDay A #&10:BNE PutDate  .PutMonth "CMP #16:BCC P%+4:SBC #6: #&0F " .PutDate ,STA ws+4:ASL A:ADC ws+4:TAX 6LDA #3:STA ws+4 @.PutDateLp J&LDA DateText,X:STA (&F0),Y:INX:INY TDEC ws+4:BNE PutDateLp:RTS ^: h .DateText r#EQUS "000JanFebMarAprMayJunJul" |#EQUS "AugSepOctNovDecDDDEEEFFF" #EQUS "000SunMonTueWedThuFriSat"  .TimeText EQUS "DATE":EQUS "TIME" : \ \ Read real-time clock %\ Returns ws=8-byte BCD time&date 3\ This routine implements low-level RTC reading  .Osw14RTC 2JSR RTCTimeRd :\ Read 1LDA #&05:LDY #&7E:LDX #&40 :\ Hours =JSR RTCDivide:CMP #&24:BCC Osw14RTCb :\ Not past midnight \ \ Increment date 7JSR RTCDate :\ A=day, Y=month %CMP DOWLengths,Y:BCC Osw14RTCupd4 &0 NCPX #29:BCC Osw14RTCupd4 X.Osw14notFeb b+LDA ws+3: #&E0 :\ Set to day=0 l0CLC:ADC #&20:TAX :\ Increment month v-LDA ws+4:ADC #0:TAY :\ Y=year+month (LSR A:BCC Osw14RTCupd3 :\ month<8 )CPX #&A0:BCC Osw14RTCupd3 :\ month<13 2INY:LDX #&20 :\ January next year .Osw14RTCupd3 4STX ws+3:STY ws+4 :\ Start of next month .Osw14RTCupd4 .INC ws+3 :\ Increment day )JSR RTCTimeWr:LDA #0 :\ Update \ .Osw14RTCb 1PHA :\ Hours 3LDY #&17:LDX #&70:JSR RTCDivide0:PHA :\ Minutes 3LDY #&00:LDX #&64:JSR RTCDivide0:PHA :\ Seconds 0JSR RTCDate:PHA:JSR BINtoBCD:STA ws+3:\ Date  1TYA:PHA:JSR BINtoBCD:STA ws+2 :\ Month 5LDA ws+4:LSR A:CLC:ADC #80:PHA :\ Year-1980  =LDY #18:CLC:ADC #100:SEC :\ Calculate century *.Osw14RTCc 4;INY:SBC #100:CMP #100:BCS Osw14RTCc :\ Convert to 0-99 >0JSR BINtoBCD:STA ws+1 :\ Year H8TYA:JSR BINtoBCD:STA ws+0 :\ Save Century R;PLA:TAY:PLA:TAX:PLA:JSR DayOfWeek :\ Get day of week \>STA ws+4:PLA:STA ws+7:PLA:STA ws+6 :\ Day, Hour, Minutes f3PLA:STA ws+5:RTS :\ Seconds p: z .RTCDate \ Get A=date, Y=month +LDA ws+4:LSR A:LDA ws+3:PHA:ROR A:LSR A 'LSR A:LSR A:LSR A:TAY:PLA: #31:RTS :  .RTCYear \ X<8 or X>7 0CPX #8:BCS RTCYearOk:LDX #7:\ Use 8-byte BCD .RTCYearLp 2LDA ws-1,X:STA ws,X:DEX :\ Adjust BCD block BNE RTCYearLp 9LDX #&19:LDA ws+1:BMI P%+4 :\ Use 1980-2099/2000-2079 4LDX #&20:STX ws+0 :\ Set for 7-byte BCD .RTCYearOk RTS : .RTCTimeRd $ LDA #1 . .RTCTime 8,TAX:LDA &F1:PHA:LDA &F0:PHA :\ Save CBLK BTYA:PHA:TXA:LDX #ws:LDY #0 LJSR OSWORD:PLA:TAY V/PLA:STA &F0:PLA:STA &F1:RTS :\ Restore CBLK `: j.RTCTimeWr tLDA #2:JSR RTCTime:CLC ~\ Continue to save : \ Save to restore on Break #\ ----------------------------- .RTCSave :\CC .RTCRestore :\CS PHP:SEI:PHA:TXA:PHA:TYA:PHA )LDY #4:LDX #&96:BIT &FFB3:\ Else=&296 )BPL RTCSaveLp:DEX :\ Elk =&295 .RTCSaveLp LDA &200,X:BCC RTCSave2 $LDA save,Y:STA &200,X:STA &205,X .RTCSave2 STA save,Y DEX:DEY:BPL RTCSaveLp PLA:TAY:PLA:TAX:PLA:PLP:RTS : ($\ Divide time in workspace by XY 27\ On exit A=BCD(result), ws=remainder, X=corrupted <.RTCDivide0 F LDA #0 P.RTCDivide ZSTX ws+5:STY ws+6:STA ws+7 dLDX #255:SEC n.RTCDivideLp xLDA ws+0:SBC ws+5:STA ws+0 LDA ws+1:SBC ws+6:STA ws+1 LDA ws+2:SBC ws+7:STA ws+2 INX:BCS RTCDivideLp LDA ws+0:ADC ws+5:STA ws+0 LDA ws+1:ADC ws+6:STA ws+1 LDA ws+2:ADC ws+7:STA ws+2 TXA :\ Continue via BCD : .BINtoBCD TAX:LDA #&99:SED .BINtoBCDlp !CLC:ADC #1:DEX:BPL BINtoBCDlp CLD:RTS .HexTopDigit LSR A:LSR A:LSR A:LSR A  .HexDigit "! #15:CMP #10:BCC P%+4:ADC #6 ,ADC #48:RTS 6: @\ Calculate day of week J\ --------------------- T+\ On entry A=day, X=month, Y=year-1900 ^/\ On exit A=day of week 1..7 for Sun..Sat h.DayOfWeek rKCPX #3:BCS DOWMarch :\ Year starts in March to bypass leap year problem |8DEY :\ If Jan or Feb, decrement year .DOWMarch 6 #&7F :\ Invert A so carry works right :CPY #200 :\ Carry will be 1 if 22nd century -ADC DOWMonths-1,X :\ A=day+month_offset STA tmp ?TYA:JSR DOWmod7 :\ Get the year 7 to prevent overflow ISBC tmp:STA tmp :\ A=day+month_offset+year using CLC from DOWmod7 +TYA:LSR A:LSR A :\ Get the year 4 NCLC:ADC tmp :\ A=day+month_offset+year+year/4, fall through to 7 .DOWmod7 ,ADC #7:BCC DOWmod7 :\ Reduce A to A 7 8ADC #0:RTS :\ Update to 1..7 and return CLC .DOWMonths 0EQUB 1:EQUB 5:EQUB 6:EQUB 3 :\ Month offsets EQUB 1:EQUB 5:EQUB 3:EQUB 0 EQUB 4:EQUB 2:EQUB 6:EQUB 4 &.DOWLengths 04EQUB 31:EQUB 31:EQUB 28:EQUB 31 :\ Month lengths :#EQUB 30:EQUB 31:EQUB 30:EQUB 31 D#EQUB 31:EQUB 30:EQUB 31:EQUB 30 N#EQUB 31:EQUB 31:EQUB 31:EQUB 31 X: b: l%\ OSWORD 15 - Set Real Time Clock v&\ ================================ .Osword15 )LDY #0:LDA (&F0),Y :\ Get command 5\ #05 :\ 5-byte centisecond time (CMP #07:BEQ Osw15a :\ 7-byte BCD 6CMP #08:BEQ Osw15a :\ "hh/mm/ss" or 8-byte BCD +CMP #11:BEQ Osw15a :\ "dd mmm yyyy" /CMP #15:CLC:BEQ Osw15a :\ "DDD,dd mmm yyyy" 4CMP #20:BEQ Osw15a :\ "dd mmm yyyy.hh/mm/ss" 8CMP #24:CLC:BEQ Osw15a :\ "DDD,dd mmm yyyy.hh/mm/ss" JMP Serv08Quit .Osw15a TAX:LDY #tmp-ws+1 .Osw15lp1 ,LDA ws-1,Y:PHA :\ Save workspace 4LDA (&F0),Y:STA ws-1,Y :\ And copy control block DEY:BNE Osw15lp1 +LDY #0:BCS P%+4:LDY #4 :\ Step past day *+TXA:CMP #8:BNE Osw15c :\ Check command 4.LDA ws+2:CMP #" ":TXA :\ Check for string > .Osw15c H-BCS Osw15String :\ Set from string R(JSR RTCYear :\ Check year \/SED:LDY #7 :\ Convert to binary f.Osw15BCDlp pLDA ws,Y:LDX #&FF:SEC z.BCDtoBINlp INX:SBC #1:BCS BCDtoBINlp /TXA:PHA:DEY :\ Stack binary data BPL Osw15BCDlp:CLD )TSX:LDA #0:STA &105,X :\ Set index=0 PLA:TAX:PLA:JMP Osw15Date : .Osw15String 'PHA:JSR RTCTimeRd:PLA :\ Read .CMP #11:BCC Osw15Time:PHA :\ Set time only #JSR GetDec: #31:PHA :\ Date LDX #0:STX tmp:INY:TYA .Osw15lp2 PHA  .Osw15lp3 5LDA (&F0),Y:CMP DateText+3,X :\ Match month name BEQ Osw15Match: #32 $#CMP DateText+3,X:BEQ Osw15Match . .Osw15lp4 87JSR Osw15Next:BCS Osw15lp4 :\ Step to next month BPLA:TAY:INC tmp:CPX #13*3 L-BCC Osw15lp2:BCS Osw15Quit2 :\ No match V.Osw15Match `"INY:JSR Osw15Next:BCS Osw15lp3 j*PLA:LDX tmp:INX:TXA:PHA :\ Month t)JSR GetDec:TAX:JSR GetDec2 :\ Year ~\ \ Write updated time&date /\ A=year, X=century, SP=>month, date, index 0\ This code implements low-level RTC writing .Osw15Date 2CLC:ADC #100:DEX:CPX #19 :\ cent*100+year .BCS Osw15Date:SBC #179 :\ Year-1980 .BMI Osw15Quit3 :\ Year<1980 .STA ws+4:PLA:CMP #8:ROL ws+4 :\ Year*2+b3 *ASL A:ASL A:ASL A:ASL A:ASL A :\ Month (STA ws+3:PLA:A ws+3:STA ws+3:\ Date 5PLA:BEQ Osw15Time1 :\ Time is on stack 3CMP #20:BCC Osw15Write :\ No time string \  .Osw15Time )JSR GetDec:STA ws+5 :\ Hour )JSR GetDec:TAX :\ Mins ()JSR GetDec:PHA :\ Secs 22TXA:PHA:LDA ws+5:PHA :\ Shuffle stack <\ F.Osw15Time1 PLDA #0:STA ws+1:STA ws+2 Z)PLA:STA ws+0:JSR wsTimes60 :\ Hour d)PLA:JSR wsAdd:JSR wsTimes60 :\ Mins n)PLA:JSR wsAdd:JSR wsTimes100 :\ Secs x\ .Osw15Write JSR RTCTimeWr :\ Write "PHA:PHA:PHA :\ Balance stack .Osw15Quit3 PLA .Osw15Quit2  PLA:PLA .Osw15Quit JMP Osw14Done : .Osw15Next %INX:LDA DateText+3,X:CMP #&60:RTS :  .GetDec INY  .GetDec2 "JSR GetDigit:STA tmp:ASL A ,ASL A:ADC tmp:ASL A:STA tmp 6 JSR GetDigit:CLC:ADC tmp:RTS @ .GetDigit JLDA (&F0),Y:INY: #15:RTS T: ^.wsTimes100 h(JSR wsTimes10:BCC wsTimes10 :\ n*100 r.wsTimes60 |&BIT SETV:JSR wsTimes6or10 :\ n*6 .wsTimes10 CLV .wsTimes6or10 &JSR wsTimes2 :\ n*2 &LDY ws+2:LDX ws+1:LDA ws+0 :\ n*2 &JSR wsTimes2:BVS wsTimesAdd :\ n*4 &JSR wsTimes2 :\ n*8 .wsTimesAdd 4ADC ws+0:STA ws+0 :\ n*8+n*2 = n*10 3TXA:ADC ws+1:STA ws+1 :\ or n*4+n*2 = n*6 TYA:ADC ws+2:STA ws+2  .SETV RTS  .wsTimes2 "ASL ws+0:ROL ws+1:ROL ws+2:RTS  .wsAdd &CLC:ADC ws+0:STA ws+0 0LDA #0:ADC ws+1:STA ws+1 :LDA #0:ADC ws+2:STA ws+2 DRTS N: X\ * - Display or set RTC b \ -------------------------- l .cmdTime v,JSR SkipSpc :\ Skip spaces 'CMP #13:BEQ cmdTimeRd :\ * #CMP #"?":BNE TimeSet :\ * ? .cmdTimeRd ,LDX #0:LDY #1:STX &100 :\ OSWORD 14,0 LDA #osw14:JSR OSWORD 1LDA &100:BEQ cmdTimeDone :\ Nothing returned  LDX #0 .cmdTimeLp 3CPX #32:BCS cmdTimeDone :\ Max. 32 characters -LDA &100,X:JSR OSASCI:INX :\ Print string CMP #13:BNE cmdTimeLp .cmdTimeDone LDA #0:RTS :  .TimeSet 'CMP #"=":BEQ P%+3:DEY :\ Skip '='  JSR SkipSpc:DEY:LDX #1 *.TimeSetLp1 45LDA (&F2),Y:STA &100,X :\ Copy to error buffer >CMP #13:BEQ TimeSetLp2 HINY:INX:BPL TimeSetLp1 R.TimeSetLp2 \3DEX:LDA &100,X:CMP #" ":\ Drop trailing spaces fBEQ TimeSetLp2 pSTX &100:LDA #osw15 z.LDX #0:LDY #1:JSR OSWORD :\ OSWORD 15,len 1JSR Osword15:LDA #0:RTS :\ Also do directly :  .SkipSpc LDA (&F2),Y:INY CMP #" ":BEQ SkipSpc RTS : ]:RelocTable=P% : : ݤsm_pass(pass%) pass%=0:M%=0 pass%=1:M%=O%-mcode% P%=&8100-128*(pass%2) O%=mcode%+M%*(pass%2)2 /pass%=1: O%+M%*2.125>L%:"Code overrun": $="4647",pass%+1,1) .: 8sm_table B>base80%=mcode%+M%:base81%=mcode%:byte%=0:count%=0:off%=0: LPbyte80%=base80%?off%:byte81%=base81%?off%: off%>=M%:byte80%=&80:byte81%=&80 V] ((byte81%-byte80%) &FE)<>0 "ERROR: Offset by more than one page at &";~&8000+off% `M (byte80% &C0)=&80:byte%=byte%2+128*(byte81%-byte80%):count%=count%+1 j1 count%=8:?O%=byte%:O%=O%+1:byte%=0:count%=0 t$off%=off%+1:off%>=M% count%=0 ~