mirror of
https://github.com/a2stuff/prodos-drivers.git
synced 2025-02-08 23:30:31 +00:00
Add AE DClock driver, based on work by M.G. Fixes #3
This commit is contained in:
parent
cc49835c9f
commit
5cf3426967
2
Makefile
2
Makefile
@ -1,4 +1,4 @@
|
||||
targets := ns.clock cricket bbb selector ram.drv quit
|
||||
targets := ns.clock cricket dclock bbb selector ram.drv quit
|
||||
|
||||
.PHONY: all $(targets)
|
||||
|
||||
|
25
README.md
25
README.md
@ -2,7 +2,7 @@
|
||||
|
||||
[![Build Status](https://travis-ci.org/a2stuff/prodos-drivers.svg?branch=master)](https://travis-ci.org/a2stuff/prodos-drivers)
|
||||
|
||||
# What are ProDOS drivers/modifications?
|
||||
# What are ProDOS "drivers"?
|
||||
|
||||
The ProDOS operating system for the Apple II executes the first `.SYSTEM` file found in the boot directory on startup. A common pattern is to have the boot directory contain several "driver" files that customize ProDOS by installing drivers for hardware or modify specific parts of the operating system. These include:
|
||||
|
||||
@ -19,15 +19,36 @@ Early versions of these drivers would often invoke a specific file on completion
|
||||
|
||||
This repository collects several drivers and uses common code to chain to the next `.SYSTEM` file, suporting network drives.
|
||||
|
||||
## What is present here?
|
||||
|
||||
This repo includes The following drivers/modifications:
|
||||
|
||||
* Real-time Clock drivers
|
||||
* No-Slot Clock
|
||||
* Cricket!,
|
||||
* Applied Engineering DClock
|
||||
* RAM Disk drivers
|
||||
* RAMWorks Driver by Glen E. Bredon
|
||||
* Quit dispatcher/selector (`BYE` routines)
|
||||
* Selector (from ProDOS 1.x)
|
||||
* Bird's Better Bye (from ProDOS 2.0)
|
||||
* Buh-Bye (an enhanced version of Bird's Better Bye)
|
||||
|
||||
In addition, `QUIT.SYSTEM` is present which isn't a driver but which immediately invokes the QUIT handler (a.k.a. program selector).
|
||||
|
||||
Some date/time utilities for The Cricker! clock are also included.
|
||||
|
||||
## How do you use these?
|
||||
|
||||
The intent is that you use a tool like Copy II Plus or [Apple II DeskTop](https://github.com/a2stuff/a2d) to copy and arrange the SYSTEM files on your boot disk as you see fit. An example boot disk catalog might include:
|
||||
The intent is that you use a tool like Copy II Plus or [Apple II DeskTop](https://github.com/a2stuff/a2d) to copy and arrange the SYSTEM files on your boot disk as you see fit. An example boot disk image catalog that is used on multiple different hardware configurations might include:
|
||||
|
||||
* `PRODOS` - the operating system, e.g. [ProDOS 2.4](https://prodos8.com/)
|
||||
* `NS.CLOCK.SYSTEM` - install No-Slot Clock driver, if present
|
||||
* `DCLOCK.SYSTEM` - install DClock clock driver, if present
|
||||
* `CRICKET.SYSTEM` - install Cricket! clock driver, if present
|
||||
* `RAM.DRV.SYSTEM` - install RamWorks RAM disk driver, if present
|
||||
* `BUHBYE.SYSTEM` - install a customized Quit handler to replace the built-in one
|
||||
* `QUIT.SYSTEM` - invoke the Quit handler immediately, as a program selector
|
||||
* `BASIC.SYSTEM` - which will not be automatically invoked, but is available to manually invoke
|
||||
|
||||
Alternately, you might want to install some drivers then immediately launch into BASIC. In that case, put `BASIC.SYSTEM` after the drivers in place of `QUIT.SYSTEM`.
|
||||
|
34
dclock/Makefile
Normal file
34
dclock/Makefile
Normal file
@ -0,0 +1,34 @@
|
||||
|
||||
CAFLAGS = --target apple2enh --list-bytes 0
|
||||
LDFLAGS = --config apple2-asm.cfg
|
||||
|
||||
OUTDIR = out
|
||||
|
||||
HEADERS = $(wildcard *.inc) $(wildcard ../inc/*.inc)
|
||||
|
||||
TARGETS = \
|
||||
$(OUTDIR)/dclock.system.SYS
|
||||
|
||||
# For timestamps
|
||||
MM = $(shell date "+%-m")
|
||||
DD = $(shell date "+%-d")
|
||||
YY = $(shell date "+%-y")
|
||||
DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY)
|
||||
|
||||
.PHONY: clean all
|
||||
all: $(OUTDIR) $(TARGETS)
|
||||
|
||||
$(OUTDIR):
|
||||
mkdir -p $(OUTDIR)
|
||||
|
||||
clean:
|
||||
rm -f $(OUTDIR)/*.o
|
||||
rm -f $(OUTDIR)/*.list
|
||||
rm -f $(TARGETS)
|
||||
|
||||
$(OUTDIR)/%.o: %.s $(HEADERS)
|
||||
ca65 $(CAFLAGS) $(DEFINES) --listing $(basename $@).list -o $@ $<
|
||||
|
||||
$(OUTDIR)/%.SYS: $(OUTDIR)/%.o
|
||||
ld65 $(LDFLAGS) -o $@ $<
|
||||
xattr -wx prodos.AuxType '00 20' $@
|
13
dclock/README.md
Normal file
13
dclock/README.md
Normal file
@ -0,0 +1,13 @@
|
||||
# Applied Engineering DClock — ProDOS Clock Driver
|
||||
|
||||
This is based on a disassembly of the Applied Engineering driver for the DClock real time clock add on for the Apple IIc.
|
||||
|
||||
> NOTE: Currently untested!
|
||||
|
||||
Like other drivers here, this one will:
|
||||
|
||||
* Conditionally install, only if a DClock is detected.
|
||||
* Only attempts detection if there is not already a clock driver.
|
||||
* Only attempts detection if the system is a an Apple IIc
|
||||
* If detected, installs into ProDOS directly, following Technical Reference Manual requirements.
|
||||
* Chains to the next `.SYSTEM` file in the directory.
|
408
dclock/dclock.system.s
Normal file
408
dclock/dclock.system.s
Normal file
@ -0,0 +1,408 @@
|
||||
; Fully disassembled and analyzed source to AE
|
||||
; DCLOCK.SYSTEM by M.G. - 04/18/2017
|
||||
; https://gist.github.com/mgcaret/7f0d7aeec169e90809c7cfaab9bf183b
|
||||
; Further modified by @inexorabletash - 12/21/2020
|
||||
|
||||
; There are critical bugs in the original AE code:
|
||||
; * When driver loader is initially probing it corrupts the
|
||||
; Apple //c Memory Expansion Card:
|
||||
; - it saves, but fails to restore, data at address $080000
|
||||
; - it fails to reset slinky pointer, and *will* trash $080000-$080007
|
||||
; * When the clock is read, it corrupts data at address $08xx01
|
||||
; - John Brooks spotted this, [M.G.] totally missed this.
|
||||
; This version of the code has fixes permanently applied.
|
||||
|
||||
.setcpu "65C02"
|
||||
.linecont +
|
||||
.feature string_escapes
|
||||
|
||||
.include "apple2.inc"
|
||||
.include "apple2.mac"
|
||||
.include "opcodes.inc"
|
||||
|
||||
.include "../inc/apple2.inc"
|
||||
.include "../inc/macros.inc"
|
||||
.include "../inc/prodos.inc"
|
||||
|
||||
; zero page locations
|
||||
SCRATCH := $0B ; scratch value for BCD range checks
|
||||
SAVEBYTE := $0C ; slinky overwritten byte save location
|
||||
BCDTMP := $3A ; location clock driver uses for BCD->Binary
|
||||
|
||||
; buffers & other spaces
|
||||
INBUF := $0200 ; input buffer
|
||||
CLOCKBUF := $0300 ; clock buffer
|
||||
|
||||
; I/O and hardware
|
||||
C8OFF := $CFFF ; C8xx ROM off
|
||||
SLOT4ROM := $C400 ; Slot 4 ROM space
|
||||
SLOT4IO := $C0C0 ; Slot 4 I/O space
|
||||
DPTRL := SLOT4IO+0 ; Slinky data ptr low
|
||||
DPTRM := SLOT4IO+1 ; Slinky data ptr middle
|
||||
DPTRH := SLOT4IO+2 ; Slinky data ptr high
|
||||
DATA := SLOT4IO+3 ; Slinky data byte
|
||||
|
||||
;;; ************************************************************
|
||||
.include "../inc/driver_preamble.inc"
|
||||
;;; ************************************************************
|
||||
|
||||
;;; ============================================================
|
||||
;;;
|
||||
;;; Driver Installer
|
||||
;;;
|
||||
;;; ============================================================
|
||||
|
||||
.define PRODUCT "DClock"
|
||||
|
||||
;;; ============================================================
|
||||
;;; Ensure there is not a previous clock driver installed.
|
||||
;;; And that this is a IIc. And that the clock is present.
|
||||
|
||||
.proc maybe_install_driver
|
||||
lda MACHID
|
||||
and #$01 ; existing clock card?
|
||||
bne done
|
||||
|
||||
lda VERSION ; IIc identification byte 1
|
||||
cmp #$06
|
||||
bne done
|
||||
lda ZIDBYTE ; IIc identification byte 2
|
||||
cmp #$00
|
||||
bne done
|
||||
|
||||
jsr ClockRead
|
||||
jsr ValidTime
|
||||
bcc InstallDriver
|
||||
|
||||
;; Show failure message
|
||||
jsr zstrout
|
||||
scrcode "\r\r\r", PRODUCT, " - Not Found."
|
||||
.byte 0
|
||||
|
||||
done: rts
|
||||
.endproc
|
||||
|
||||
; ----------------------------------------------------------------------------
|
||||
; Install clock driver
|
||||
.proc InstallDriver
|
||||
|
||||
;; Copy into address at DATETIME vector, update the vector and
|
||||
;; update MACHID bits to signal a clock is present.
|
||||
ptr := $A5
|
||||
|
||||
;; Update absolute addresses within driver
|
||||
lda DATETIME+1
|
||||
sta ptr
|
||||
clc
|
||||
adc #(regulk - driver - 1)
|
||||
sta regulk_addr
|
||||
lda DATETIME+2
|
||||
sta ptr+1
|
||||
adc #0
|
||||
sta regulk_addr+1
|
||||
|
||||
;; Copy driver into appropriate bank
|
||||
lda RWRAM1
|
||||
lda RWRAM1
|
||||
ldy #sizeof_driver-1
|
||||
|
||||
loop: lda driver,y
|
||||
sta (ptr),y
|
||||
dey
|
||||
bpl loop
|
||||
|
||||
;; Set the "Recognizable Clock Card" bit
|
||||
lda MACHID
|
||||
ora #$01
|
||||
sta MACHID
|
||||
|
||||
lda #OPC_JMP_abs
|
||||
sta DATETIME
|
||||
|
||||
;; Invoke the driver to init the time
|
||||
jsr DATETIME
|
||||
|
||||
lda ROMIN2
|
||||
|
||||
;; Display success message
|
||||
jsr zstrout
|
||||
scrcode "\r\r\r", PRODUCT, " - Installed "
|
||||
.byte 0
|
||||
|
||||
;; Display the current date
|
||||
lda DATELO+1 ; month
|
||||
ror a
|
||||
pha
|
||||
lda DATELO
|
||||
pha
|
||||
rol a
|
||||
rol a
|
||||
rol a
|
||||
rol a
|
||||
and #%00001111
|
||||
jsr cout_number
|
||||
|
||||
lda #HI('/') ; /
|
||||
jsr COUT
|
||||
|
||||
pla ; day
|
||||
and #%00011111
|
||||
jsr cout_number
|
||||
|
||||
lda #HI('/') ; /
|
||||
jsr COUT
|
||||
|
||||
pla ; year
|
||||
jsr cout_number
|
||||
jsr CROUT
|
||||
|
||||
rts ; done!
|
||||
.endproc
|
||||
|
||||
; ----------------------------------------------------------------------------
|
||||
; enable slinky registers, set adddress and save byte we intend to trash
|
||||
.proc SlinkyEnable
|
||||
lda C8OFF ; not needed on //c, but release $C8xx firmware
|
||||
lda SLOT4ROM ; enable slinky registers
|
||||
lda #$08 ; set addr $080000
|
||||
sta DPTRH
|
||||
stz DPTRM
|
||||
stz DPTRL
|
||||
lda DATA ; read data byte
|
||||
sta SAVEBYTE ; save it to restore later
|
||||
rts
|
||||
.endproc
|
||||
; ----------------------------------------------------------------------------
|
||||
; Routine to restore trashed byte in slinky RAM
|
||||
.proc SlinkyRestore
|
||||
lda #$08 ; set adddr $080000
|
||||
sta DPTRH
|
||||
stz DPTRM
|
||||
stz DPTRL
|
||||
lda SAVEBYTE ; get saved byte
|
||||
sta DATA ; and put it back
|
||||
lda C8OFF ; not needed on //c, but release $C8xx firmware
|
||||
rts
|
||||
.endproc
|
||||
; ----------------------------------------------------------------------------
|
||||
; Write 8 bits to clock
|
||||
.proc ClockWrite8b
|
||||
ldx #$08 ; set adddr $080000
|
||||
stx DPTRH
|
||||
stz DPTRM
|
||||
: stz DPTRL ; restore low byte to 0
|
||||
sta DATA ; write byte
|
||||
lsr a ; next bit into 0 position
|
||||
dex
|
||||
bne :-
|
||||
rts
|
||||
.endproc
|
||||
; ----------------------------------------------------------------------------
|
||||
; unlock the clock by writing the magic bit sequence
|
||||
.proc ClockUnlock
|
||||
ldy #$08
|
||||
: lda unlock,y
|
||||
jsr ClockWrite8b ; write 8 bits
|
||||
dey
|
||||
bne :-
|
||||
rts
|
||||
unlock = * - 1
|
||||
.byte $5c, $a3, $3a, $c5, $5c, $a3, $3a, $c5
|
||||
.endproc
|
||||
; ----------------------------------------------------------------------------
|
||||
; Read 8 bits from the clock
|
||||
.proc ClockRead8b
|
||||
ldx #$08 ; set adddr $080000
|
||||
stz DPTRL
|
||||
stz DPTRM
|
||||
stx DPTRH
|
||||
: pha ; save accumulator
|
||||
lda DATA ; get data byte
|
||||
lsr a ; bit 0 into carry
|
||||
pla ; restore accumulator
|
||||
ror a ; put read bit into position
|
||||
dex
|
||||
bne :-
|
||||
rts
|
||||
.endproc
|
||||
; ----------------------------------------------------------------------------
|
||||
; read the clock data into memory at CLOCKBUF
|
||||
; WARNING: unfixed code never restores byte we trashed
|
||||
.proc ClockRead
|
||||
jsr SlinkyEnable
|
||||
jsr ClockUnlock
|
||||
ldy #$00
|
||||
: jsr ClockRead8b
|
||||
sta CLOCKBUF,y
|
||||
iny
|
||||
cpy #$08 ; have we read 8 bytes?
|
||||
bcc :- ; nope
|
||||
jsr SlinkyRestore
|
||||
rts
|
||||
.endproc
|
||||
; ----------------------------------------------------------------------------
|
||||
; validate the DClock data makes sense
|
||||
; return carry clear if it does, carry set if it does not
|
||||
.proc ValidTime
|
||||
; validate ms
|
||||
ldx #$00
|
||||
ldy #$99
|
||||
lda CLOCKBUF
|
||||
jsr CheckBCD
|
||||
bcs :+
|
||||
; validate seconds
|
||||
ldx #$00
|
||||
ldy #$59
|
||||
lda CLOCKBUF+$01
|
||||
jsr CheckBCD
|
||||
bcs :+
|
||||
; validate minutes
|
||||
ldx #$00
|
||||
ldy #$59
|
||||
lda CLOCKBUF+$02
|
||||
jsr CheckBCD
|
||||
bcs :+
|
||||
; validate hours
|
||||
ldx #$00
|
||||
ldy #$23
|
||||
lda CLOCKBUF+$03
|
||||
jsr CheckBCD
|
||||
bcs :+
|
||||
; validate day of week
|
||||
ldx #$01
|
||||
ldy #$07
|
||||
lda CLOCKBUF+$04
|
||||
jsr CheckBCD
|
||||
bcs :+
|
||||
; validate day of month
|
||||
ldx #$01
|
||||
ldy #$31
|
||||
lda CLOCKBUF+$05
|
||||
jsr CheckBCD
|
||||
bcs :+
|
||||
; validate month
|
||||
ldx #$01
|
||||
ldy #$12
|
||||
lda CLOCKBUF+$06
|
||||
jsr CheckBCD
|
||||
bcs :+
|
||||
; validate year
|
||||
ldx #$00
|
||||
ldy #$99
|
||||
lda CLOCKBUF+$07
|
||||
jsr CheckBCD
|
||||
bcs :+
|
||||
clc ; all good
|
||||
rts
|
||||
: sec ; problem
|
||||
rts
|
||||
.endproc
|
||||
; ----------------------------------------------------------------------------
|
||||
; Check BCD number in range of [x,y]
|
||||
; return carry clear if it is, carry set if it is not
|
||||
.proc CheckBCD
|
||||
sed ; decimal mode
|
||||
stx SCRATCH ; lower bound into scratch
|
||||
cmp SCRATCH ; compare it
|
||||
bcc :++ ; fail if out of range
|
||||
sty SCRATCH ; upper bound into scratch
|
||||
cmp SCRATCH ; compare it
|
||||
beq :+ ; OK if equal
|
||||
bcs :++ ; fail if out of range
|
||||
: cld ; in range
|
||||
clc
|
||||
rts
|
||||
: cld ; not in range
|
||||
sec
|
||||
rts
|
||||
.endproc
|
||||
|
||||
; ----------------------------------------------------------------------------
|
||||
; clock driver code inserted into ProDOS
|
||||
|
||||
driver:
|
||||
lda #$08 ; useless instruction
|
||||
php
|
||||
sei
|
||||
lda SLOT4ROM ; activate slinky registers
|
||||
; ($08 from above overwritten)
|
||||
stz DPTRL ; set slinky address to $08xx00
|
||||
ldy #$08 ; also counter for unlock bytes
|
||||
sty DPTRH
|
||||
lda DATA ; get destroyed byte
|
||||
; (slinky now at $08xx01)
|
||||
pha ; save value on stack
|
||||
; unlock dclock registers
|
||||
regulk_addr := *+1
|
||||
ubytlp: lda regulk,y ; self-modified
|
||||
ldx #$08 ; bit counter
|
||||
ubitlp: stz DPTRL ; reset pointer to $08xx00
|
||||
sta DATA ; write to $08xx00
|
||||
lsr a ; next bit into 0 position
|
||||
dex
|
||||
bne ubitlp
|
||||
dey
|
||||
bne ubytlp
|
||||
; now read 64 bits (8 bytes) from dclock
|
||||
ldx #$08 ; byte counter
|
||||
rbytlp: ldy #$08 ; bit counter
|
||||
rbitlp: pha
|
||||
lda DATA ; data byte
|
||||
lsr a ; bit 0 into carry
|
||||
pla
|
||||
ror a ; carry into bit 7
|
||||
dey
|
||||
bne rbitlp
|
||||
; got 8 bits now, convert from BCD to binary
|
||||
pha
|
||||
and #$0F
|
||||
sta BCDTMP
|
||||
pla
|
||||
and #$F0
|
||||
lsr a
|
||||
pha
|
||||
adc BCDTMP
|
||||
sta BCDTMP
|
||||
pla
|
||||
lsr a
|
||||
lsr a
|
||||
adc BCDTMP
|
||||
; place in input buffer, which is OK because the ThunderClock driver does this
|
||||
sta INBUF-1,x
|
||||
dex
|
||||
bne rbytlp
|
||||
; done copying, now put necessary values into ProDOS time locations
|
||||
; copy hours to ProDOS hours
|
||||
lda INBUF+4
|
||||
sta TIMEHI
|
||||
; copy minutes to ProDOS minutes
|
||||
lda INBUF+5
|
||||
sta TIMELO
|
||||
; copy month ...
|
||||
lda INBUF+1
|
||||
lsr a
|
||||
ror a
|
||||
ror a
|
||||
ror a
|
||||
; ... and day of month to ProDOS month/day
|
||||
ora INBUF+2
|
||||
sta DATELO
|
||||
; copy year and final bit of month to ProDOS year/month
|
||||
lda INBUF
|
||||
rol a
|
||||
sta DATEHI
|
||||
stz DPTRL ; set slinky back to $08xx00
|
||||
pla ; get saved byte
|
||||
sta DATA ; put it back
|
||||
plp
|
||||
rts
|
||||
; DS1215 unlock sequence (in reverse)
|
||||
regulk = * - 1
|
||||
.byte $5C, $A3, $3A, $C5, $5C, $A3, $3A, $C5
|
||||
|
||||
sizeof_driver := * - driver
|
||||
.assert sizeof_driver <= 125, error, "Clock code must be <= 125 bytes"
|
||||
|
||||
;;; ************************************************************
|
||||
.include "../inc/driver_postamble.inc"
|
||||
;;; ************************************************************
|
@ -53,6 +53,8 @@ INIT := $FB2F
|
||||
SETTXT := $FB39
|
||||
TABV := $FB5B
|
||||
SETPWRC := $FB6F
|
||||
VERSION := $FBB3
|
||||
ZIDBYTE := $FBC0
|
||||
BELL1 := $FBDD
|
||||
HOME := $FC58
|
||||
CLREOL := $FC9C
|
||||
|
@ -146,15 +146,18 @@ slot: .byte 0
|
||||
.proc install_driver
|
||||
ptr := $A5
|
||||
|
||||
;; Update absolute addresses within driver
|
||||
lda DATETIME+1
|
||||
sta ptr
|
||||
clc
|
||||
adc #(unlock - driver - 1)
|
||||
sta ld3+1
|
||||
sta unlock_addr
|
||||
lda DATETIME+2
|
||||
sta ptr+1
|
||||
adc #0
|
||||
sta ld3+2
|
||||
sta unlock_addr+1
|
||||
|
||||
;; Copy driver into appropriate bank
|
||||
lda RWRAM1
|
||||
lda RWRAM1
|
||||
ldy #sizeof_driver-1
|
||||
@ -227,7 +230,8 @@ ld1: lda $C304 ; self-modified
|
||||
|
||||
;; Unlock the NSC by bit-banging.
|
||||
uloop:
|
||||
ld3: lda unlock-1,x ; self-modified
|
||||
unlock_addr := *+1
|
||||
lda unlock-1,x ; self-modified
|
||||
sec
|
||||
ror a ; a bit at a time
|
||||
: pha
|
||||
|
@ -27,6 +27,7 @@ add_file "cricket/out/set.date.BIN" "set.date#062000" "/$VOLNAME/
|
||||
add_file "cricket/out/set.time.BIN" "set.time#062000" "/$VOLNAME/CRICKET.UTIL"
|
||||
add_file "cricket/out/test.BIN" "test#062000" "/$VOLNAME/CRICKET.UTIL"
|
||||
add_file "ns.clock/out/ns.clock.system.SYS" "ns.clock.system#FF0000" "/$VOLNAME"
|
||||
add_file "dclock/out/dclock.system.SYS" "dclock.system#FF0000" "/$VOLNAME"
|
||||
add_file "quit/out/quit.system.SYS" "quit.system#FF0000" "/$VOLNAME"
|
||||
add_file "ram.drv/out/ram.drv.system.SYS" "ram.drv.system#FF0000" "/$VOLNAME"
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user