diff --git a/Makefile b/Makefile index c0a0a88..d6a5672 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -targets := ns.clock cricket dclock selectors ram.drv quit pause +targets := ns.clock cricket dclock romx selectors ram.drv util .PHONY: all $(targets) package diff --git a/README.md b/README.md index ed8d445..e5a9f25 100644 --- a/README.md +++ b/README.md @@ -23,12 +23,13 @@ This repository collects several drivers and uses common code to chain to the ne ## What is present here? -This repo includes The following drivers/modifications: +This repo includes the following drivers/modifications: * Real-time Clock drivers * No-Slot Clock * Cricket! * Applied Engineering DClock + * ROMX Real-Time Clock * RAM Disk drivers * RAMWorks Driver by Glen E. Bredon * Quit dispatcher/selector (`BYE` routines) @@ -41,14 +42,17 @@ In addition, `QUIT.SYSTEM` is present which isn't a driver but which immediately There's also `PAUSE.SYSTEM` which just waits for a fraction of a second before invoking the next driver file. (Why? In case the log messages from the other installers goes by too fast!) -Some date/time utilities for The Cricker! clock are also included. +Non-drivers that are included: +* The `DATE` binary file can be `BRUN` (or just `-DATE`) to show the current ProDOS Date/Time, to verify that the clock driver is working. +* Some utilities for The Cricket! 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. A 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 +* `NS.CLOCK.SYSTEM` - install No-Slot clock driver, if present +* `ROMXRTC.SYSTEM` - install ROMX 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 diff --git a/cricket/Makefile b/cricket/Makefile index 1ccdeca..94c8ea0 100644 --- a/cricket/Makefile +++ b/cricket/Makefile @@ -10,7 +10,6 @@ TARGETS = \ $(OUTDIR)/prodos.mod.BIN \ $(OUTDIR)/cricket.system.SYS \ $(OUTDIR)/test.BIN \ - $(OUTDIR)/date.BIN \ $(OUTDIR)/set.time.BIN \ $(OUTDIR)/set.date.BIN diff --git a/cricket/README.md b/cricket/README.md index 2773378..0624b8d 100644 --- a/cricket/README.md +++ b/cricket/README.md @@ -37,7 +37,6 @@ I ended up disassembling both [NS.CLOCK.SYSTEM](../ns.clock/ns.clock.system.s) ( ## Other Utilities These `BRUN`able files are also built: -* [DATE](date.s) just prints the current ProDOS date/time, to verify the time is set and updating. It does not depend on having a Cricket. * [TEST](test.s) attempts to identify an SSC in Slot 2 and the Cricket via the ID sequence, to test routines. * [SET.DATE](set.date.s) sets the Cricket's current date. * [SET.TIME](set.time.s) sets the Cricket's current time. diff --git a/cricket/cricket.system.s b/cricket/cricket.system.s index e7c2bff..ca4e59b 100644 --- a/cricket/cricket.system.s +++ b/cricket/cricket.system.s @@ -210,30 +210,7 @@ loop: lda driver,y .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 cout_date rts ; done! .endproc diff --git a/cricket/test.s b/cricket/test.s index 5ef9fad..95f2d30 100644 --- a/cricket/test.s +++ b/cricket/test.s @@ -49,7 +49,7 @@ ssc_not_found: rts ;; TODO: Write NUL and check for 'C' ... version ... $8D (CR) - ;; https://github.com/inexorabletash/cricket/issues/3 + ;; https://github.com/a2stuff/cricket/issues/3 init_ssc: lda COMMAND ; save status of SSC registers sta saved_command diff --git a/dclock/dclock.system.s b/dclock/dclock.system.s index 9584984..3038bbe 100644 --- a/dclock/dclock.system.s +++ b/dclock/dclock.system.s @@ -130,30 +130,7 @@ loop: lda driver,y .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 cout_date rts ; done! .endproc diff --git a/inc/driver_preamble.inc b/inc/driver_preamble.inc index a05c553..e7874fb 100644 --- a/inc/driver_preamble.inc +++ b/inc/driver_preamble.inc @@ -457,3 +457,35 @@ units: pla jsr COUT rts .endproc + +;;; ------------------------------------------------------------ +;;; COUT the current ProDOS date + +.proc cout_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 + + rts +.endproc diff --git a/ns.clock/ns.clock.system.s b/ns.clock/ns.clock.system.s index 22f8d59..26527fd 100644 --- a/ns.clock/ns.clock.system.s +++ b/ns.clock/ns.clock.system.s @@ -3,7 +3,7 @@ ;;; http://www.apple2.org.za/gswv/a2zine/GS.WorldView/v1999/Oct/MISC/NSC.Disk.TXT ;;; Modification history available at: -;;; https://github.com/a2stuff/cricket +;;; https://github.com/a2stuff/prodos-drivers .setcpu "6502" .linecont + @@ -186,30 +186,7 @@ loop: lda driver,y .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 cout_date rts ; done! .endproc diff --git a/package.sh b/package.sh index 26a105e..c737c1d 100755 --- a/package.sh +++ b/package.sh @@ -19,19 +19,20 @@ add_file () { } add_file "cricket/out/cricket.system.SYS" "cricket.system#FF0000" "/$VOLNAME" -add_file "cricket/out/date.BIN" "date#062000" "/$VOLNAME/CRICKET.UTIL" add_file "cricket/out/set.date.BIN" "set.date#062000" "/$VOLNAME/CRICKET.UTIL" 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 "dclock/out/dclock.system.SYS" "dclock.system#FF0000" "/$VOLNAME" add_file "ns.clock/out/ns.clock.system.SYS" "ns.clock.system#FF0000" "/$VOLNAME" -add_file "quit/out/quit.system.SYS" "quit.system#FF0000" "/$VOLNAME" -add_file "pause/out/pause.system.SYS" "pause.system#FF0000" "/$VOLNAME" +add_file "romx/out/romxrtc.system.SYS" "romxrtc.system#FF0000" "/$VOLNAME" add_file "ram.drv/out/ram.drv.system.SYS" "ram.drv.system#FF0000" "/$VOLNAME" add_file "selectors/out/bbb.system.SYS" "bbb.system#FF0000" "/$VOLNAME" add_file "selectors/out/buhbye.system.SYS" "buhbye.system#FF0000" "/$VOLNAME" add_file "selectors/out/bye.system.SYS" "bye.system#FF0000" "/$VOLNAME" add_file "selectors/out/selector.system.SYS" "selector.system#FF0000" "/$VOLNAME" +add_file "util/out/quit.system.SYS" "quit.system#FF0000" "/$VOLNAME" +add_file "util/out/pause.system.SYS" "pause.system#FF0000" "/$VOLNAME" +add_file "util/out/date.BIN" "date#062000" "/$VOLNAME" rm -r "$PACKDIR" diff --git a/quit/README.md b/quit/README.md deleted file mode 100644 index 0d058af..0000000 --- a/quit/README.md +++ /dev/null @@ -1,4 +0,0 @@ - -## QUIT.SYSTEM - -This just invokes the ProDOS quit handler immediately. It can be used as the last in a chain of "driver" installers to invoke the program selector (e.g. [Bitsy Bye](https://prodos8.com/bitsy-bye/), [Bird's Better Bye](../bbb), etc) diff --git a/pause/Makefile b/romx/Makefile similarity index 95% rename from pause/Makefile rename to romx/Makefile index ccfec40..fb40c71 100644 --- a/pause/Makefile +++ b/romx/Makefile @@ -7,7 +7,7 @@ OUTDIR = out HEADERS = $(wildcard *.inc) $(wildcard ../inc/*.inc) TARGETS = \ - $(OUTDIR)/pause.system.SYS + $(OUTDIR)/romxrtc.system.SYS # For timestamps MM = $(shell date "+%-m") diff --git a/romx/README.md b/romx/README.md new file mode 100644 index 0000000..1dd9ca4 --- /dev/null +++ b/romx/README.md @@ -0,0 +1,3 @@ +# ROMX ProDOS Clock Driver + +Original source c/o Jeff Mazur. diff --git a/romx/romxrtc.system.s b/romx/romxrtc.system.s new file mode 100644 index 0000000..9fc918f --- /dev/null +++ b/romx/romxrtc.system.s @@ -0,0 +1,329 @@ +;;; ROMX ProDOS RTC Driver +;;; Based on: +;;; * Ver 0.91 +;;; * Ver 0.92 Added ZIP slowdowns - 11-Aug-2021 - +;;; Modifications by Joshua Bell inexorabletash@gmail.com +;;; * Converted to ca65 syntax and adapted to driver wrapper. +;;; * Driver core rewritten to ensure that $220 and up are saved/restored. + + .setcpu "6502" + .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" + +;;; Uncomment the following to "fake" a clock with a fixed date. +;;; Used for testing without a real ROMX around. +;;; FAKE_CLOCK = 1 + +;;; ************************************************************ + .include "../inc/driver_preamble.inc" +;;; ************************************************************ + +ZipSlo := $C0E0 ; ZIP CHIP slowdown + +;;; ROMX locations +FWReadClock := $D8F0 ; Firmware clock driver routine +SigCk := $DFFE ; ROMX sig bytes +SEL_MBANK := $F851 ; Select Main bank reg + +;;; ============================================================ +;;; +;;; Driver Installer +;;; +;;; ============================================================ + + .define PRODUCT "ROMX Clock" + +;;; ============================================================ +;;; Ensure there is not a previous clock driver installed. + +.proc maybe_install_driver + lda MACHID + and #$01 ; existing clock card? + beq detect_romx ; nope, check for ROMX + + rts ; yes, done! +.endproc + +;;; ------------------------------------------------------------ + +.proc detect_romx + ;; Preserve date/time + ldy #3 ; copy 4 bytes +: lda DATELO,y + sta saved,y + dey + bpl :- + +.ifndef FAKE_CLOCK + ;; Try to detect ROMX and RTC + bit ROMIN2 ; enable ROM + bit ZipSlo ; disable ZIP + bit $FACA ; enable ROMXe, temp bank 0 + bit $FACA + bit $FAFE + + lda SigCk ; Check for ROMX signature bytes + cmp #$4A + bne not_found + lda SigCk+1 + cmp #$CD + bne not_found + lda FWReadClock ; is RTC code there? + cmp #$AD + php + bit SEL_MBANK ; restore original bank + plp + bne not_found +.endif + jmp install_driver ; found clock! + +not_found: + ;; Restore date/time + ldy #3 +: lda saved,y + sta DATELO,y + dey + bpl :- + + ;; Show failure message + jsr log_message + scrcode PRODUCT, " - Not Found." + .byte 0 + + rts + +saved: .byte 0, 0, 0, 0 +.endproc + +;;; ------------------------------------------------------------ +;;; Install ROMX RTC Driver. Copy into address at DATETIME vector, +;;; update the vector and update MACHID bits to signal a clock +;;; is present. + +.proc install_driver + ptr := $A5 + + ;; Update absolute addresses within driver + lda DATETIME+1 + sta ptr + lda DATETIME+2 + sta ptr+1 + + lda ptr + clc + adc RELOC1 + sta RELOC1 + lda ptr + 1 + adc RELOC1 + 1 + sta RELOC1 + 1 + + lda ptr + clc + adc RELOC2 + sta RELOC2 + lda ptr + 1 + adc RELOC2 + 1 + sta RELOC2 + 1 + + ;; Copy driver into appropriate bank + lda RWRAM1 + lda RWRAM1 + ldy #ClockDrvSize-1 + +loop: lda ClockDrv,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 log_message + scrcode PRODUCT, " - " + .byte 0 + + ;; Display the current date + jsr cout_date + + rts ; done! +.endproc + +;;; ============================================================ +;;; ROMX RTC driver - Relocated into ProDOS clock driver space +;;; ============================================================ + +;;; The first ~$20 bytes of $200 (input buffer) are safe to +;;; overwrite. They are also used by the built-in Thunderclock +;;; slot-clock driver in ProDOS ($200-$20C). + +StubLoc := $0200 ; RAM stub for ROMX (<$20 bytes) + +;;; ROMX Firmware writes RTC data into this fixed location. +;;; It risks conflicting with some applications (e.g. A2DeskTop), +;;; so the data is saved/restored around clock reads. + +RTC_BUF := $02B0 + +ClockDrv: + ;; -------------------------------------------------- + ;; Enter driver + + php + sei + + ;; -------------------------------------------------- + ;; Copy the stub to RAM, and preserve RTC_BUF + + ldx #RamStubEnd-RamStub-1 ; copy stub to RAM + RELOC1 := *+1 +: lda RamStub - ClockDrv,x ; self-modified during relocation + sta StubLoc,x + lda RTC_BUF,x ; save `RTC_BUF` too (way more than needed) + pha + dex + bpl :- + + ;; -------------------------------------------------- + ;; Read the clock into `RTC_BUF` + + jsr StubLoc + + ;; -------------------------------------------------- + ;; Strip non-number bits, convert decimal to binary, push to stack + + ldy #6 +bufloop: + lda RTC_BUF,y + + RELOC2 := *+1 + and MaskTable-1 - ClockDrv,y ; self-modified during relocation + + ;; BCD to Binary + ;; On entry, A=BCD value &00-&99 + ;; On exit, A=binary value 0-99 + ldx #$FF ; Start with result=-1 + sec ; Prepare for subtraction + sed ; Switch to Decimal arithmetic +: inx ; Add 1 to result + sbc #1 ; Subtract 1 with BCD arithmetic + bcs :- ; Loop until BCD value < 0 + cld ; Switch back to Binary arithmetic + txa ; return in A + + ;; Push to stack + pha + dey + bne bufloop ; 6..1 + + ;; -------------------------------------------------- + ;; Pull and place values into ProDOS time locations + + ;; (`RTC_BUF`+0 is not pushed) + + pla ; `RTC_BUF`+1 = minute + sta TIMELO + + pla ; `RTC_BUF`+2 = hour + sta TIMEHI + + pla ; `RTC_BUF`+3 = weekday (unused) + + pla ; `RTC_BUF`+4 = day + sta DATELO + + pla ; `RTC_BUF`+5 = month + asl a + asl a + asl a + asl a + asl a ; MSB will merge into DATEHI + ora DATELO ; merge with day + sta DATELO + + pla ; `RTC_BUF`+6 = year + sta DATEHI + rol DATEHI ; merge with MSB from month + + ;; -------------------------------------------------- + ;; Restore what was originally at `RTC_BUF` + + ldx #0 +: pla + sta RTC_BUF,x + inx + cpx #RamStubEnd-RamStub + bne :- + + ;; -------------------------------------------------- + ;; Exit driver + + plp + rts + +MaskTable: + .byte $7f, $3f, $07, $3f, $1f, $ff + ;; .... min hour wkdy date mnth year (`RTC_BUF` bytes 1..6) + +RamStub: +.ifndef FAKE_CLOCK + ;; Really read the ROMX RTC + + bit ROMIN2 ; enable ROM + bit ZipSlo ; disable ZIP + bit $FACA ; enable ROMXe, temp bank 0 + bit $FACA + bit $FAFE + jsr FWReadClock ; Call ROMX to read clock + bit SEL_MBANK ; restore original bank + bit LCBANK1 ; restore LC w/write + bit LCBANK1 +.else + ;; No ROMX RTC around? Provide fake data for testing. + ;; October 5, 2021 12:34:56 + + lda #$56 ; sec + sta RTC_BUF+0 + lda #$34 ; min + sta RTC_BUF+1 + lda #$12 ; hr + sta RTC_BUF+2 + lda #$05 ; date + sta RTC_BUF+4 + lda #$10 ; month + sta RTC_BUF+5 + lda #$21 ; year + sta RTC_BUF+6 +.endif + + rts +RamStubEnd := * + .assert RamStubEnd - RamStub < $20, error, "Stub too long" + +ClockDrvEnd := * +ClockDrvSize = ClockDrvEnd - ClockDrv + + .assert ClockDrvSize <= 125, error, \ + .sprintf("Clock driver must be <= 125 bytes, was %d bytes", ClockDrvSize) + +;;; ************************************************************ + .include "../inc/driver_postamble.inc" +;;; ************************************************************ diff --git a/quit/Makefile b/util/Makefile similarity index 84% rename from quit/Makefile rename to util/Makefile index d1c4a1a..9fd9fde 100644 --- a/quit/Makefile +++ b/util/Makefile @@ -7,7 +7,9 @@ OUTDIR = out HEADERS = $(wildcard *.inc) $(wildcard ../inc/*.inc) TARGETS = \ - $(OUTDIR)/quit.system.SYS + $(OUTDIR)/quit.system.SYS \ + $(OUTDIR)/pause.system.SYS \ + $(OUTDIR)/date.BIN # For timestamps MM = $(shell date "+%-m") @@ -31,7 +33,7 @@ clean: $(OUTDIR)/%.o: %.s $(HEADERS) ca65 $(CAFLAGS) $(DEFINES) --listing $(basename $@).list -o $@ $< -$(OUTDIR)/%.SYS: $(OUTDIR)/%.o +$(OUTDIR)/%.BIN $(OUTDIR)/%.SYS: $(OUTDIR)/%.o ld65 $(LDFLAGS) -o $@ $< ifdef XATTR xattr -wx prodos.AuxType '00 20' $@ diff --git a/util/README.md b/util/README.md new file mode 100644 index 0000000..3e62ef7 --- /dev/null +++ b/util/README.md @@ -0,0 +1,8 @@ +# Utilities + +* [DATE](date.s) + * Prints the current ProDOS date/time, to verify the time is set and updating. Run from the BASIC prompt: `-DATE` +* [QUIT.SYSTEM](quit.system.s) + * This invokes the ProDOS quit handler immediately. It can be used as the last in a chain of "driver" installers to invoke the program selector, e.g. if you want to also keep `BASIC.SYSTEM` in your root directory but not launch it. +* [PAUSE.SYSTEM](pause.system.s) + * Waits for a fraction of a second before invoking the next driver file. Useful in case the log messages from the driver installers go by too quickly! diff --git a/cricket/date.s b/util/date.s similarity index 63% rename from cricket/date.s rename to util/date.s index 65b0f59..6d567b5 100644 --- a/cricket/date.s +++ b/util/date.s @@ -1,5 +1,4 @@ ;;; Query ProDOS and print the current date/time -;;; (No dependency on Cricket clock) ;;; Output is: MM/DD/YY HH:MM @@ -15,41 +14,17 @@ start: MLI_CALL GET_TIME, 0 -;;; Standard format: -;;; -;;; 49041 ($BF91) 49040 ($BF90) +;;; DATEHI ($BF91) DATELO ($BF90) ;;; 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 ;;; +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ ;;; DATE: | year | month | day | ;;; +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ ;;; -;;; 49043 ($BF93) 49042 ($BF92) +;;; TIMEHI ($BF93) TIMELO ($BF92) ;;; 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 ;;; +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ ;;; TIME: |0 0 0| hour | |0 0| minute | ;;; +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ -;;; -;;; Extended format (ProDOS 2.5): -;;; https://groups.google.com/d/topic/comp.sys.apple2/6MwlJSKTmQc/discussion -;;; -;;; 49039 ($BF8F) 49038 ($BF8E) -;;; 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 -;;; +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ -;;; xTIME: | xSeconds | xMilliseconds | -;;; +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ -;;; -;;; 49041 ($BF91) 49040 ($BF90) -;;; 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 -;;; +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ -;;; DATE: | year | month | day | -;;; +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ -;;; -;;; 49043 ($BF93) 49042 ($BF92) -;;; 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 -;;; +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ -;;; TIME: |xYear| hour | |0 0| minute | -;;; +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ - ;; Date @@ -76,8 +51,7 @@ start: jsr COUT pla ; year - ;; TODO: Shift in xYear bits - jsr cout_number ; TODO: Support 16-bit numbers + jsr cout_number lda #HI(' ') jsr COUT @@ -100,9 +74,6 @@ start: rts -pm_flag: - .byte 0 - ;;; ------------------------------------------------------------ .proc cout_number diff --git a/pause/pause.system.s b/util/pause.system.s similarity index 100% rename from pause/pause.system.s rename to util/pause.system.s diff --git a/quit/quit.system.s b/util/quit.system.s similarity index 100% rename from quit/quit.system.s rename to util/quit.system.s