Add setyear to patch ProDOS year table in-memory

This commit is contained in:
mgcaret 2017-11-02 20:32:25 -07:00
parent 0f03e8ed17
commit cdf2db65d3
3 changed files with 185 additions and 1 deletions

View File

@ -5,7 +5,7 @@ BOOTDSK=~/vii_hd.2mg
CA65=ca65
LD65=utils/auto_origin.sh ld65
GENHELP=utils/gen_help.sh
MG_CMDS=at.info.p8c at.zones.p8c afp.userprefix.p8c afp.sessions.p8c alias.p8c at.boot.p8c deschw.p8c dmem.p8c nbp.lookup.p8c tardis.p8c nbp.parse.p8c iie.card.p8c idemu.p8c mig.insp.p8c fastchip.p8c afp.timezone.p8c
MG_CMDS=at.info.p8c at.zones.p8c afp.userprefix.p8c afp.sessions.p8c alias.p8c at.boot.p8c deschw.p8c dmem.p8c nbp.lookup.p8c tardis.p8c nbp.parse.p8c iie.card.p8c idemu.p8c mig.insp.p8c fastchip.p8c afp.timezone.p8c setyear.p8c
.PHONY: all
all: shk ;

View File

@ -80,6 +80,10 @@ Optionally, use undocumented features to display the user-selected startup slot.
View the contents of the Apple IIc Plus MIG RAM.
#### setyear
Patches the ProDOS ThunderClock driver year table in-memory.
## Building
Building the utilities requires a Unix-like environment with GNU Make and the usual set of Unix utilities such as sed, awk, egrep, etc.

180
setyear.s Normal file
View File

@ -0,0 +1,180 @@
; %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-2040
: 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