davex-mg-utils/setyear.s

181 lines
5.5 KiB
ArmAsm

; %help
; setyear - Patch the ProDOS year table in-memory
;
; usage: setyear <00-99> [-v] [-n]
;
; Patches the ProDOS year table to include the given year plus at least
; 4 more years beyond.
;
; Options: -v Show generated year table
; -n Don't actually patch ProDOS.
; %hend
.p02
.include "davex-mg.inc"
tmp = xczpage
year = tmp+1
count = year+1
;prbyte = $fdda
;cout = $fded
DX_start dx_mg_auto_origin ; load address
DX_info $01,$12,dx_cc_any,$00
DX_ptab
DX_parm $00,t_int1 ; year (two-digit)
DX_parm 'v',t_nil ; verbose
DX_parm 'n',t_nil ; no-patch
DX_end_ptab
DX_desc "Set ProDOS year table."
DX_main
lda #$00 ; parm
jsr xgetparm_n ; davex ensures this is here
cpy #100
bcs badparms
jsr mkyt
lda #'v'|$80 ; "verbose"
jsr xgetparm_ch
bcs :+ ; not given, don't display
jsr dispyt
: lda #'n'|$80 ; "no patch"
jsr xgetparm_ch
bcs :+ ; not given, do it
rts
; see if we can patch the driver
: lda $c08b
lda $c08b
ldx #$03
: lda $d7b4,x ; tdays table, at september
cmp tdaysv,x ; that what ProDOS has?
bne setyterr ; not the thunderclock driver
dex
bpl :-
; go ahead and patch
ldx #6
: lda yeartab,x
sta $d7b8,x ; address of year table in P8
dex
bpl :-
bit $c082 ; ROM back before exit
rts
setyterr: bit $c082 ; ROM back before death
lda #$01
jsr xredirect
jsr xmess
asc_hi "Can't patch clock driver!"
.byte $00
jmp exiterr
badparms: lda #$01
jsr xredirect
jsr xmess
asc_hi "Bad year!"
.byte $00
exiterr: lda #$ff
jsr xredirect
jmp xerr
;
.proc mkyt
tya
and #%00000011 ; divisible by 4?
bne :+ ; nope
dey ; avoid starting table on leap year
bpl :+ ; did't wrap around
ldy #99 ; 1999
: sty year
lda #$06 ; do for 6 years
sta count
yloop: lda year
cmp #40 ; 40 or greater?
bcs :+ ; Do not adjust for 1940-1999
adc #100 ; add 100 years for 2000-2039
: tay ; year
lda #1 ; day
tax ; month
jsr weekday
tax
ldy dayidx,x ; get index into ProDOS year table
lda year
cmp #100 ; need to account for incrementing past 100
bcc :+
sbc #100
: sta yeartab,y ; put year in the appropriate slot
inc year
dec count
bne yloop
; now fix leap year gap
ldy yeartab ; first year
ldx #$06 ; index of last year
lloop: lda yeartab,x
cmp #$ff ; not filled in?
bne :+
tya ; yes, use previous value
: sta yeartab,x ; write back
tay ; and save as new 'previous' value
dex
bpl lloop
rts
.endproc
.proc dispyt
lda #$00
sta year
lda #$07
sta count
prloop: ldx year
ldy yeartab,x
sty tmp
lda #$20
cpy #40
bcc :+
lda #$19
: jsr prbyte
lda tmp
cmp #$10
bcs :+
lda #'0'|$80
jsr cout
: ldy tmp
lda #$00
jsr xprdec_2
lda #$8d
jsr cout
inc year
dec count
bne prloop
rts
.endproc
; table to index into year-starts in P8 tclock driver
dayidx: .byte 1,0,6,5,4,3,2 ; MonSunSatFriThuWedTue
; Table we will copy into ProDOS
yeartab: .res 7,$ff
; table to validate the P8 tclock driver, 4 bytes at $d7b4
tdaysv: .byte 242,20,51,81
; adapted from http://6502.org/source/misc/dow.htm
; inputs: y = year (0-255 = 1900-2155)
; x = month
; a = day
; output: a = weekday (0 = Sunday)
.proc weekday
cpx #3 ; year starts in march to bypass
bcs march ; leap year problem
dey ; if jan or feb, decrement year
march: eor #$7f ; invert a so carry works right
cpy #200 ; carry will be 1 if 22nd century
adc mtab-1,x ; a is now day+month offset
sta tmp
tya ; get the year
jsr mod7 ; do a modulo to prevent overflow
sbc tmp ; combine with day+month
sta tmp
tya ; get the year again
lsr ; divide it by 4
lsr
clc ; add it to y+m+d and fall through
adc tmp
mod7: adc #7 ; returns (a+3) modulo 7
bcc mod7 ; for a in 0..255
rts
mtab: .byte 1,5,6,3,1,5,3,0,4,2,6,4 ; month offsets
.endproc
DX_end