├── ram.drv ├── orig │ └── RAM.SYSTEM.SYS ├── res │ ├── go.sh │ └── util.sh ├── README.md └── Makefile ├── inc ├── driver_postamble.inc ├── ascii.inc ├── apple2.inc ├── macros.inc ├── prodos.inc └── driver_preamble.inc ├── clocks ├── romx │ ├── README.md │ ├── Makefile │ └── romxrtc.system.s ├── fujinet │ ├── README.md │ ├── Makefile │ ├── smartport.inc │ └── fn.clock.system.s ├── ns.clock │ ├── README.md │ ├── Makefile │ └── ns.clock.system.s ├── Makefile ├── jumbo │ ├── README.md │ ├── Makefile │ └── clock.system.s ├── dclock │ ├── README.md │ ├── Makefile │ └── dclock.system.s ├── cricket │ ├── Makefile │ ├── set.time.s │ ├── set.date.s │ ├── README.md │ ├── set.datetime.s │ ├── prodos.mod.s │ ├── test.s │ └── cricket.system.s └── README.md ├── .gitignore ├── util ├── quit.system.s ├── home.system.s ├── pause.system.s ├── README.md ├── Makefile ├── me.first.system.s ├── date.s └── noclock.system.s ├── accelerators ├── Makefile └── zipchip │ ├── Makefile │ └── zipchip.system.s ├── Makefile ├── .github └── workflows │ └── main.yml ├── setup ├── Makefile ├── README.md └── setup.system.s ├── textcolors ├── bw.system.s ├── wb.system.s ├── pink.system.s ├── deepblue.system.s ├── gray.system.s ├── a2green.system.s ├── gsblue.system.s ├── mint.system.s ├── README.md └── Makefile ├── selectors ├── Makefile ├── README.md └── selector.system.s ├── package.sh └── README.md /ram.drv/orig/RAM.SYSTEM.SYS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a2stuff/prodos-drivers/HEAD/ram.drv/orig/RAM.SYSTEM.SYS -------------------------------------------------------------------------------- /inc/driver_postamble.inc: -------------------------------------------------------------------------------- 1 | .ifndef BUILD_SETUP_FILE 2 | 3 | poporg 4 | reloc_end := * 5 | 6 | .endif 7 | -------------------------------------------------------------------------------- /clocks/romx/README.md: -------------------------------------------------------------------------------- 1 | # ROMX ProDOS Clock Driver 2 | 3 | Original source c/o Jeff Mazur. 4 | 5 | `ROMXRTC.SETUP` is for use with [SETUP.SYSTEM](../../setup/README.md). 6 | -------------------------------------------------------------------------------- /ram.drv/res/go.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Run this from the ram.drv.system directory 4 | 5 | set -e 6 | source "res/util.sh" 7 | 8 | #do_make clean 9 | do_make all 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated files 2 | *.BIN 3 | *.SYS 4 | *.list 5 | 6 | # Reference copy of original binary 7 | orig 8 | 9 | # Build directory 10 | out 11 | 12 | # Directory mounted in Virtual ][ as a ProDOS volume 13 | mount 14 | 15 | # OS-specific files 16 | .DS_Store 17 | -------------------------------------------------------------------------------- /clocks/fujinet/README.md: -------------------------------------------------------------------------------- 1 | # FujiNet ProDOS Clock Driver 2 | 3 | [FujiNet](https://fujinet.online/) for Apple II provides a number of devices via SmartPort. Alongside four block and a network device it has a real time clock device. 4 | 5 | This driver is an adaptation of the other drivers in https://github.com/a2stuff/prodos-drivers 6 | 7 | `FN.CLOCK.SETUP` is for use with [SETUP.SYSTEM](../../setup/README.md). 8 | -------------------------------------------------------------------------------- /ram.drv/res/util.sh: -------------------------------------------------------------------------------- 1 | function cecho { 2 | case $1 in 3 | red) tput setaf 1 ; shift ;; 4 | green) tput setaf 2 ; shift ;; 5 | yellow) tput setaf 3 ; shift ;; 6 | esac 7 | echo -e "$@" 8 | tput sgr0 9 | } 10 | 11 | function do_make { 12 | make $MAKE_FLAGS "$1" \ 13 | && (cecho green "make $1 good") \ 14 | || (tput blink ; cecho red "MAKE $1 BAD" ; return 1) 15 | } 16 | -------------------------------------------------------------------------------- /util/quit.system.s: -------------------------------------------------------------------------------- 1 | 2 | .setcpu "6502" 3 | .include "apple2.inc" 4 | 5 | .include "../inc/apple2.inc" 6 | .include "../inc/prodos.inc" 7 | 8 | .org SYS_ADDR 9 | 10 | cld 11 | bit ROMIN2 12 | sta CLR80VID 13 | sta CLRALTCHAR 14 | sta CLR80COL 15 | jsr SETVID 16 | jsr SETKBD 17 | jsr SETNORM 18 | jsr INIT 19 | jsr HOME 20 | 21 | MLI_CALL QUIT, quit_params 22 | brk 23 | 24 | DEFINE_QUIT_PARAMS quit_params 25 | -------------------------------------------------------------------------------- /accelerators/Makefile: -------------------------------------------------------------------------------- 1 | targets := zipchip 2 | 3 | .PHONY: all $(targets) 4 | 5 | all: $(targets) 6 | 7 | export LOG_SUCCESS 8 | export LOG_FAILURE 9 | 10 | # Build all targets 11 | $(targets): 12 | @tput setaf 3 && echo "Building: $@" && tput sgr0 13 | @$(MAKE) -C $@ \ 14 | && (tput setaf 2 && echo "make $@ good" && tput sgr0) \ 15 | || (tput blink && tput setaf 1 && echo "MAKE $@ BAD" && tput sgr0 && false) 16 | 17 | # Clean all temporary/target files 18 | clean: 19 | @for dir in $(targets); do \ 20 | tput setaf 2 && echo "cleaning $$dir" && tput sgr0; \ 21 | $(MAKE) -C $$dir clean; \ 22 | done 23 | -------------------------------------------------------------------------------- /clocks/ns.clock/README.md: -------------------------------------------------------------------------------- 1 | # No Slot Clock ProDOS Driver 2 | 3 | Adapted from `NS.CLOCK.SYSTEM` (by "CAP"), with these changes: 4 | 5 | * Fixes a typo 6 | * Removes beeps 7 | * Is less chatty so you can have multiple clock drivers, e.g. if you use the same hard disk image across different hardware configurations 8 | * Uses file I/O rather than block I/O for chaining 9 | * Does not hard-code driver file name 10 | 11 | ## Other Utilities 12 | 13 | These `BRUN`able files are also built: 14 | * [SET.DATETIME](set.datetime.s) sets the No Slot Clock date/time. 15 | 16 | `NS.CLOCK.SETUP` is for use with [SETUP.SYSTEM](../../setup/README.md). 17 | -------------------------------------------------------------------------------- /clocks/Makefile: -------------------------------------------------------------------------------- 1 | targets := ns.clock cricket dclock romx fujinet jumbo 2 | 3 | .PHONY: all $(targets) 4 | 5 | all: $(targets) 6 | 7 | export LOG_SUCCESS 8 | export LOG_FAILURE 9 | 10 | # Build all targets 11 | $(targets): 12 | @tput setaf 3 && echo "Building: $@" && tput sgr0 13 | @$(MAKE) -C $@ \ 14 | && (tput setaf 2 && echo "make $@ good" && tput sgr0) \ 15 | || (tput blink && tput setaf 1 && echo "MAKE $@ BAD" && tput sgr0 && false) 16 | 17 | # Clean all temporary/target files 18 | clean: 19 | @for dir in $(targets); do \ 20 | tput setaf 2 && echo "cleaning $$dir" && tput sgr0; \ 21 | $(MAKE) -C $$dir clean; \ 22 | done 23 | -------------------------------------------------------------------------------- /ram.drv/README.md: -------------------------------------------------------------------------------- 1 | # Disassembly of Glen E. Bredon's `RAM.DRV.SYSTEM` for Apple II ProDOS 2 | 3 | This was started before realizing what the origin of the `RAM.SYSTEM` 4 | found on a MouseDesk 2.0 disk image file was. 5 | 6 | There is a more complete diassembly with commentary at: 7 | 8 | http://boutillon.free.fr/Underground/Outils/Ram_Drv_System/Ram_Drv_System.html 9 | 10 | ## Project Details 11 | 12 | * The `orig` branch compiles to to match the original. 13 | * The `master` branch has additions, including: 14 | * Chains to next `.SYSTEM` file in dir order (not hard coded) 15 | * Chains to next `.SYSTEM` file on non-block devices (e.g. file shares) 16 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | targets := clocks selectors accelerators ram.drv setup util textcolors 2 | 3 | .PHONY: all $(targets) package 4 | 5 | all: $(targets) 6 | 7 | export LOG_SUCCESS=1 8 | export LOG_FAILURE=1 9 | 10 | # Build all targets 11 | $(targets): 12 | @tput setaf 3 && echo "Building: $@" && tput sgr0 13 | @$(MAKE) -C $@ \ 14 | && (tput setaf 2 && echo "make $@ good" && tput sgr0) \ 15 | || (tput blink && tput setaf 1 && echo "MAKE $@ BAD" && tput sgr0 && false) 16 | 17 | # Clean all temporary/target files 18 | clean: 19 | @for dir in $(targets); do \ 20 | tput setaf 2 && echo "cleaning $$dir" && tput sgr0; \ 21 | $(MAKE) -C $$dir clean; \ 22 | done 23 | 24 | package: 25 | ./package.sh 26 | -------------------------------------------------------------------------------- /clocks/jumbo/README.md: -------------------------------------------------------------------------------- 1 | # "Jumbo" ProDOS Clock Driver 2 | 3 | This is an amalgamation of the other clock driver installers. Each one is tried in turn, until one successfully installs a clock driver. 4 | 5 | The drivers are (in order): 6 | 7 | * No-Slot Clock 8 | * ROMX 9 | * FujiNet 10 | * DClock 11 | * Cricket! 12 | 13 | By default, the installer logs on success so you can tell what clock was detected, but you can build with `LOG_SUCCESS=0` to prevent that. 14 | 15 | If ProDOS _already_ has a clock driver installed, the driver is checked for common Thunderclock year tables. If found, the table is updated in memory to cover 2023-2028. 16 | 17 | `CLOCK.SETUP` is for use with [SETUP.SYSTEM](../../setup/README.md). 18 | -------------------------------------------------------------------------------- /clocks/dclock/README.md: -------------------------------------------------------------------------------- 1 | # Applied Engineering DClock — ProDOS Clock Driver 2 | 3 | This is based on a disassembly of the Applied Engineering driver for the DClock real time clock add on for the Apple IIc. 4 | 5 | > NOTE: Currently untested! 6 | 7 | Like other drivers here, this one will: 8 | 9 | * Conditionally install, only if a DClock is detected. 10 | * Only attempts detection if there is not already a clock driver. 11 | * Only attempts detection if the system is a an Apple IIc 12 | * If detected, installs into ProDOS directly, following Technical Reference Manual requirements. 13 | * Chains to the next `.SYSTEM` file in the directory. 14 | 15 | `DCLOCK.SETUP` is for use with [SETUP.SYSTEM](../../setup/README.md). 16 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | tags: ['*'] 7 | pull_request: 8 | branches: [ main ] 9 | workflow_dispatch: 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v4 17 | - uses: a2stuff/build-install-ca65-action@v2 18 | - uses: a2stuff/build-install-cadius-action@v1 19 | 20 | - name: build 21 | env: 22 | TERM: xterm-256color 23 | run: > 24 | make && make package 25 | 26 | - name: deploy new version 27 | if: startsWith(github.ref, 'refs/tags/') 28 | uses: ncipollo/release-action@v1 29 | with: 30 | token: ${{ secrets.GITHUB_TOKEN }} 31 | artifacts: "prodos-drivers.po" 32 | -------------------------------------------------------------------------------- /util/home.system.s: -------------------------------------------------------------------------------- 1 | 2 | .setcpu "6502" 3 | .linecont + 4 | .feature string_escapes 5 | 6 | .include "apple2.inc" 7 | .include "apple2.mac" 8 | 9 | .include "../inc/apple2.inc" 10 | .include "../inc/macros.inc" 11 | .include "../inc/prodos.inc" 12 | .include "../inc/ascii.inc" 13 | 14 | ;;; ************************************************************ 15 | .include "../inc/driver_preamble.inc" 16 | ;;; ************************************************************ 17 | 18 | 19 | .proc maybe_install_driver 20 | jmp HOME 21 | .endproc 22 | 23 | ;;; ************************************************************ 24 | .include "../inc/driver_postamble.inc" 25 | ;;; ************************************************************ 26 | -------------------------------------------------------------------------------- /setup/Makefile: -------------------------------------------------------------------------------- 1 | 2 | CAFLAGS = --target apple2enh --list-bytes 0 3 | LDFLAGS = --config apple2-asm.cfg 4 | 5 | OUTDIR = ../out 6 | 7 | HEADERS = $(wildcard *.inc) $(wildcard ../inc/*.inc) 8 | 9 | TARGETS = \ 10 | $(OUTDIR)/setup.system.SYS 11 | 12 | # For timestamps 13 | MM = $(shell date "+%-m") 14 | DD = $(shell date "+%-d") 15 | YY = $(shell date "+%-y") 16 | DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY) 17 | 18 | XATTR := $(shell command -v xattr 2> /dev/null) 19 | 20 | .PHONY: clean all 21 | all: $(OUTDIR) $(TARGETS) 22 | 23 | $(OUTDIR): 24 | mkdir -p $(OUTDIR) 25 | 26 | clean: 27 | rm -f $(OUTDIR)/*.o 28 | rm -f $(OUTDIR)/*.list 29 | rm -f $(TARGETS) 30 | 31 | $(OUTDIR)/%.o: %.s $(HEADERS) 32 | ca65 $(CAFLAGS) $(DEFINES) --listing $(basename $@).list -o $@ $< 33 | 34 | $(OUTDIR)/%.SYS: $(OUTDIR)/%.o 35 | ld65 $(LDFLAGS) -o $@ $< 36 | -------------------------------------------------------------------------------- /inc/ascii.inc: -------------------------------------------------------------------------------- 1 | ;;; ============================================================ 2 | ;;; ASCII Code Points (also used as key codes) 3 | ;;; ============================================================ 4 | 5 | ASCII_BELL = $07 ; bell 6 | ASCII_LEFT = $08 ; left arrow 7 | ASCII_TAB = $09 ; tab 8 | ASCII_DOWN = $0A ; down arrow 9 | ASCII_UP = $0B ; up arrow 10 | ASCII_CR = $0D ; carriage return 11 | ASCII_RIGHT = $15 ; right arrow 12 | ASCII_SYN = $16 ; scroll text window up 13 | ASCII_ETB = $17 ; scroll text window down 14 | ASCII_CLEAR = $18 ; clear 15 | ASCII_EM = $19 ; move cursor to upper left 16 | ASCII_ESCAPE = $1B ; escape 17 | ASCII_DELETE = $7F ; delete 18 | -------------------------------------------------------------------------------- /textcolors/bw.system.s: -------------------------------------------------------------------------------- 1 | .setcpu "6502" 2 | 3 | .include "apple2.inc" 4 | .include "apple2.mac" 5 | 6 | .include "../inc/apple2.inc" 7 | .include "../inc/macros.inc" 8 | .include "../inc/prodos.inc" 9 | 10 | ;;; ************************************************************ 11 | .include "../inc/driver_preamble.inc" 12 | ;;; ************************************************************ 13 | 14 | .proc maybe_install_driver 15 | lda #$0f ; text: black on white 16 | sta TBCOLOR 17 | lda #$0f ; border: white 18 | sta CLOCKCTL 19 | 20 | rts 21 | .endproc 22 | 23 | ;;; ************************************************************ 24 | .include "../inc/driver_postamble.inc" 25 | ;;; ************************************************************ 26 | -------------------------------------------------------------------------------- /textcolors/wb.system.s: -------------------------------------------------------------------------------- 1 | .setcpu "6502" 2 | 3 | .include "apple2.inc" 4 | .include "apple2.mac" 5 | 6 | .include "../inc/apple2.inc" 7 | .include "../inc/macros.inc" 8 | .include "../inc/prodos.inc" 9 | 10 | ;;; ************************************************************ 11 | .include "../inc/driver_preamble.inc" 12 | ;;; ************************************************************ 13 | 14 | .proc maybe_install_driver 15 | lda #$f0 ; text: white on black 16 | sta TBCOLOR 17 | lda #$00 ; border: black 18 | sta CLOCKCTL 19 | 20 | rts 21 | .endproc 22 | 23 | ;;; ************************************************************ 24 | .include "../inc/driver_postamble.inc" 25 | ;;; ************************************************************ 26 | -------------------------------------------------------------------------------- /textcolors/pink.system.s: -------------------------------------------------------------------------------- 1 | .setcpu "6502" 2 | 3 | .include "apple2.inc" 4 | .include "apple2.mac" 5 | 6 | .include "../inc/apple2.inc" 7 | .include "../inc/macros.inc" 8 | .include "../inc/prodos.inc" 9 | 10 | ;;; ************************************************************ 11 | .include "../inc/driver_preamble.inc" 12 | ;;; ************************************************************ 13 | 14 | .proc maybe_install_driver 15 | lda #$5b ; text: gray on pink 16 | sta TBCOLOR 17 | lda #$07 ; border: light blue 18 | sta CLOCKCTL 19 | 20 | rts 21 | .endproc 22 | 23 | ;;; ************************************************************ 24 | .include "../inc/driver_postamble.inc" 25 | ;;; ************************************************************ 26 | -------------------------------------------------------------------------------- /textcolors/deepblue.system.s: -------------------------------------------------------------------------------- 1 | .setcpu "6502" 2 | 3 | .include "apple2.inc" 4 | .include "apple2.mac" 5 | 6 | .include "../inc/apple2.inc" 7 | .include "../inc/macros.inc" 8 | .include "../inc/prodos.inc" 9 | 10 | ;;; ************************************************************ 11 | .include "../inc/driver_preamble.inc" 12 | ;;; ************************************************************ 13 | 14 | .proc maybe_install_driver 15 | lda #$f2 ; text: white on dark blue 16 | sta TBCOLOR 17 | lda #$02 ; text: dark blue 18 | sta CLOCKCTL 19 | 20 | rts 21 | .endproc 22 | 23 | ;;; ************************************************************ 24 | .include "../inc/driver_postamble.inc" 25 | ;;; ************************************************************ 26 | -------------------------------------------------------------------------------- /textcolors/gray.system.s: -------------------------------------------------------------------------------- 1 | .setcpu "6502" 2 | 3 | .include "apple2.inc" 4 | .include "apple2.mac" 5 | 6 | .include "../inc/apple2.inc" 7 | .include "../inc/macros.inc" 8 | .include "../inc/prodos.inc" 9 | 10 | ;;; ************************************************************ 11 | .include "../inc/driver_preamble.inc" 12 | ;;; ************************************************************ 13 | 14 | .proc maybe_install_driver 15 | lda #$5a ; text: dark gray on light gray 16 | sta TBCOLOR 17 | lda #$0a ; border: gray 18 | sta CLOCKCTL 19 | 20 | rts 21 | .endproc 22 | 23 | ;;; ************************************************************ 24 | .include "../inc/driver_postamble.inc" 25 | ;;; ************************************************************ 26 | -------------------------------------------------------------------------------- /textcolors/a2green.system.s: -------------------------------------------------------------------------------- 1 | .setcpu "6502" 2 | 3 | .include "apple2.inc" 4 | .include "apple2.mac" 5 | 6 | .include "../inc/apple2.inc" 7 | .include "../inc/macros.inc" 8 | .include "../inc/prodos.inc" 9 | 10 | ;;; ************************************************************ 11 | .include "../inc/driver_preamble.inc" 12 | ;;; ************************************************************ 13 | 14 | .proc maybe_install_driver 15 | lda #$C0 ; text: bright greeen on black 16 | sta TBCOLOR 17 | lda #$00 ; border: black 18 | sta CLOCKCTL 19 | 20 | rts 21 | .endproc 22 | 23 | ;;; ************************************************************ 24 | .include "../inc/driver_postamble.inc" 25 | ;;; ************************************************************ 26 | -------------------------------------------------------------------------------- /textcolors/gsblue.system.s: -------------------------------------------------------------------------------- 1 | .setcpu "6502" 2 | 3 | .include "apple2.inc" 4 | .include "apple2.mac" 5 | 6 | .include "../inc/apple2.inc" 7 | .include "../inc/macros.inc" 8 | .include "../inc/prodos.inc" 9 | 10 | ;;; ************************************************************ 11 | .include "../inc/driver_preamble.inc" 12 | ;;; ************************************************************ 13 | 14 | .proc maybe_install_driver 15 | lda #$f6 ; border: white on medium blue 16 | sta TBCOLOR 17 | lda #$06 ; border: medium blue 18 | sta CLOCKCTL 19 | 20 | rts 21 | .endproc 22 | 23 | ;;; ************************************************************ 24 | .include "../inc/driver_postamble.inc" 25 | ;;; ************************************************************ 26 | -------------------------------------------------------------------------------- /textcolors/mint.system.s: -------------------------------------------------------------------------------- 1 | .setcpu "6502" 2 | 3 | .include "apple2.inc" 4 | .include "apple2.mac" 5 | 6 | .include "../inc/apple2.inc" 7 | .include "../inc/macros.inc" 8 | .include "../inc/prodos.inc" 9 | 10 | ;;; ************************************************************ 11 | .include "../inc/driver_preamble.inc" 12 | ;;; ************************************************************ 13 | 14 | .proc maybe_install_driver 15 | lda #$2e ; text: dark blue on bright green 16 | sta TBCOLOR 17 | lda #$0e ; border: bright green 18 | sta CLOCKCTL 19 | 20 | rts 21 | .endproc 22 | 23 | ;;; ************************************************************ 24 | .include "../inc/driver_postamble.inc" 25 | ;;; ************************************************************ 26 | -------------------------------------------------------------------------------- /util/pause.system.s: -------------------------------------------------------------------------------- 1 | 2 | .setcpu "6502" 3 | .linecont + 4 | .feature string_escapes 5 | 6 | .include "apple2.inc" 7 | .include "apple2.mac" 8 | 9 | .include "../inc/apple2.inc" 10 | .include "../inc/macros.inc" 11 | .include "../inc/prodos.inc" 12 | .include "../inc/ascii.inc" 13 | 14 | ;;; ************************************************************ 15 | .include "../inc/driver_preamble.inc" 16 | ;;; ************************************************************ 17 | 18 | 19 | .proc maybe_install_driver 20 | ldx #4 21 | : lda #$FF 22 | jsr WAIT 23 | dex 24 | bne :- 25 | rts 26 | .endproc 27 | 28 | ;;; ************************************************************ 29 | .include "../inc/driver_postamble.inc" 30 | ;;; ************************************************************ 31 | -------------------------------------------------------------------------------- /util/README.md: -------------------------------------------------------------------------------- 1 | # Utilities 2 | 3 | * [DATE](date.s) 4 | * Prints the current ProDOS date/time, to verify the time is set and updating. Run from the BASIC prompt: `-DATE` 5 | * [QUIT.SYSTEM](quit.system.s) 6 | * 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. 7 | * [PAUSE.SYSTEM](pause.system.s) 8 | * 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! 9 | * [ME.FIRST.SYSTEM](me.first.system.s) 10 | * Moves the current volume to the end of DEVLST. Niche, but useful in some circumstances. 11 | * [HOME.SYSTEM](home.system.s) 12 | * Clears the screen before invoking the next driver file. Useful if you want to start or end driver installs with a clear screen. 13 | * [NOCLOCK.SYSTEM](noclock.system.s) 14 | * If no real-time clock is present, prompt the user then set the ProDOS date/time. 15 | -------------------------------------------------------------------------------- /ram.drv/Makefile: -------------------------------------------------------------------------------- 1 | 2 | CAFLAGS = --target apple2enh --list-bytes 0 3 | LDFLAGS = --config apple2-asm.cfg 4 | 5 | OUTDIR = ../out 6 | 7 | HEADERS = $(wildcard *.inc) $(wildcard ../inc/*.inc) 8 | 9 | TARGETS = \ 10 | $(OUTDIR)/ram.drv.system.SYS \ 11 | $(OUTDIR)/ram.drv.setup.SYS 12 | 13 | export LOG_SUCCESS=1 14 | export LOG_FAILURE=1 15 | 16 | # For timestamps 17 | MM = $(shell date "+%-m") 18 | DD = $(shell date "+%-d") 19 | YY = $(shell date "+%-y") 20 | DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY) \ 21 | -D LOG_SUCCESS=$(LOG_SUCCESS) -D LOG_FAILURE=$(LOG_FAILURE) 22 | 23 | XATTR := $(shell command -v xattr 2> /dev/null) 24 | 25 | .PHONY: clean all 26 | all: $(OUTDIR) $(TARGETS) 27 | 28 | $(OUTDIR): 29 | mkdir -p $(OUTDIR) 30 | 31 | clean: 32 | rm -f $(OUTDIR)/*.o 33 | rm -f $(OUTDIR)/*.list 34 | rm -f $(TARGETS) 35 | 36 | $(OUTDIR)/%.o: %.s $(HEADERS) 37 | ca65 $(CAFLAGS) $(DEFINES) --listing $(basename $@).list -o $@ $< 38 | 39 | $(OUTDIR)/%.setup.o: %.system.s $(HEADERS) 40 | ca65 $(CAFLAGS) $(DEFINES) -D BUILD_SETUP_FILE --listing $(basename $@).list -o $@ $< 41 | 42 | $(OUTDIR)/%.SYS: $(OUTDIR)/%.o 43 | ld65 $(LDFLAGS) -o $@ $< 44 | -------------------------------------------------------------------------------- /clocks/dclock/Makefile: -------------------------------------------------------------------------------- 1 | 2 | CAFLAGS = --target apple2enh --list-bytes 0 3 | LDFLAGS = --config apple2-asm.cfg 4 | 5 | OUTDIR = ../../out 6 | 7 | HEADERS = $(wildcard *.inc) $(wildcard ../../inc/*.inc) 8 | 9 | TARGETS = \ 10 | $(OUTDIR)/dclock.system.SYS \ 11 | $(OUTDIR)/dclock.setup.SYS 12 | 13 | LOG_SUCCESS=1 14 | LOG_FAILURE=1 15 | 16 | # For timestamps 17 | MM = $(shell date "+%-m") 18 | DD = $(shell date "+%-d") 19 | YY = $(shell date "+%-y") 20 | DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY) \ 21 | -D LOG_SUCCESS=$(LOG_SUCCESS) -D LOG_FAILURE=$(LOG_FAILURE) 22 | 23 | XATTR := $(shell command -v xattr 2> /dev/null) 24 | 25 | .PHONY: clean all 26 | all: $(OUTDIR) $(TARGETS) 27 | 28 | $(OUTDIR): 29 | mkdir -p $(OUTDIR) 30 | 31 | clean: 32 | rm -f $(OUTDIR)/*.o 33 | rm -f $(OUTDIR)/*.list 34 | rm -f $(TARGETS) 35 | 36 | $(OUTDIR)/%.o: %.s $(HEADERS) 37 | ca65 $(CAFLAGS) $(DEFINES) --listing $(basename $@).list -o $@ $< 38 | 39 | $(OUTDIR)/%.setup.o: %.system.s $(HEADERS) 40 | ca65 $(CAFLAGS) $(DEFINES) -D BUILD_SETUP_FILE --listing $(basename $@).list -o $@ $< 41 | 42 | $(OUTDIR)/%.SYS: $(OUTDIR)/%.o 43 | ld65 $(LDFLAGS) -o $@ $< 44 | ifdef XATTR 45 | xattr -wx prodos.AuxType '00 20' $@ 46 | endif 47 | -------------------------------------------------------------------------------- /clocks/romx/Makefile: -------------------------------------------------------------------------------- 1 | 2 | CAFLAGS = --target apple2enh --list-bytes 0 3 | LDFLAGS = --config apple2-asm.cfg 4 | 5 | OUTDIR = ../../out 6 | 7 | HEADERS = $(wildcard *.inc) $(wildcard ../../inc/*.inc) 8 | 9 | TARGETS = \ 10 | $(OUTDIR)/romxrtc.system.SYS \ 11 | $(OUTDIR)/romxrtc.setup.SYS 12 | 13 | LOG_SUCCESS=1 14 | LOG_FAILURE=1 15 | 16 | # For timestamps 17 | MM = $(shell date "+%-m") 18 | DD = $(shell date "+%-d") 19 | YY = $(shell date "+%-y") 20 | DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY) \ 21 | -D LOG_SUCCESS=$(LOG_SUCCESS) -D LOG_FAILURE=$(LOG_FAILURE) 22 | 23 | XATTR := $(shell command -v xattr 2> /dev/null) 24 | 25 | .PHONY: clean all 26 | all: $(OUTDIR) $(TARGETS) 27 | 28 | $(OUTDIR): 29 | mkdir -p $(OUTDIR) 30 | 31 | clean: 32 | rm -f $(OUTDIR)/*.o 33 | rm -f $(OUTDIR)/*.list 34 | rm -f $(TARGETS) 35 | 36 | $(OUTDIR)/%.o: %.s $(HEADERS) 37 | ca65 $(CAFLAGS) $(DEFINES) --listing $(basename $@).list -o $@ $< 38 | 39 | $(OUTDIR)/%.setup.o: %.system.s $(HEADERS) 40 | ca65 $(CAFLAGS) $(DEFINES) -D BUILD_SETUP_FILE --listing $(basename $@).list -o $@ $< 41 | 42 | $(OUTDIR)/%.SYS: $(OUTDIR)/%.o 43 | ld65 $(LDFLAGS) -o $@ $< 44 | ifdef XATTR 45 | xattr -wx prodos.AuxType '00 20' $@ 46 | endif 47 | -------------------------------------------------------------------------------- /selectors/Makefile: -------------------------------------------------------------------------------- 1 | 2 | CAFLAGS = --target apple2enh --list-bytes 0 3 | LDFLAGS = --config apple2-asm.cfg 4 | 5 | OUTDIR = ../out 6 | 7 | HEADERS = $(wildcard *.inc) $(wildcard ../inc/*.inc) 8 | 9 | TARGETS = \ 10 | $(OUTDIR)/selector.system.SYS \ 11 | $(OUTDIR)/selector.setup.SYS \ 12 | $(OUTDIR)/bye.system.SYS \ 13 | $(OUTDIR)/bye.setup.SYS \ 14 | $(OUTDIR)/bbb.system.SYS \ 15 | $(OUTDIR)/bbb.setup.SYS \ 16 | $(OUTDIR)/buhbye.system.SYS \ 17 | $(OUTDIR)/buhbye.setup.SYS 18 | 19 | # For timestamps 20 | MM = $(shell date "+%-m") 21 | DD = $(shell date "+%-d") 22 | YY = $(shell date "+%-y") 23 | DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY) 24 | 25 | XATTR := $(shell command -v xattr 2> /dev/null) 26 | 27 | .PHONY: clean all 28 | all: $(OUTDIR) $(TARGETS) 29 | 30 | $(OUTDIR): 31 | mkdir -p $(OUTDIR) 32 | 33 | clean: 34 | rm -f $(OUTDIR)/*.o 35 | rm -f $(OUTDIR)/*.list 36 | rm -f $(TARGETS) 37 | 38 | $(OUTDIR)/%.o: %.s $(HEADERS) 39 | ca65 $(CAFLAGS) $(DEFINES) --listing $(basename $@).list -o $@ $< 40 | 41 | $(OUTDIR)/%.setup.o: %.system.s $(HEADERS) 42 | ca65 $(CAFLAGS) $(DEFINES) -D BUILD_SETUP_FILE --listing $(basename $@).list -o $@ $< 43 | 44 | $(OUTDIR)/%.SYS: $(OUTDIR)/%.o 45 | ld65 $(LDFLAGS) -o $@ $< 46 | -------------------------------------------------------------------------------- /accelerators/zipchip/Makefile: -------------------------------------------------------------------------------- 1 | 2 | CAFLAGS = --target apple2enh --list-bytes 0 3 | LDFLAGS = --config apple2-asm.cfg 4 | 5 | OUTDIR = ../../out 6 | 7 | HEADERS = $(wildcard *.inc) $(wildcard ../inc/*.inc) 8 | 9 | TARGETS = \ 10 | $(OUTDIR)/zipchip.system.SYS \ 11 | $(OUTDIR)/zipchip.setup.SYS 12 | 13 | LOG_SUCCESS=1 14 | LOG_FAILURE=1 15 | 16 | # For timestamps 17 | MM = $(shell date "+%-m") 18 | DD = $(shell date "+%-d") 19 | YY = $(shell date "+%-y") 20 | DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY) \ 21 | -D LOG_SUCCESS=$(LOG_SUCCESS) -D LOG_FAILURE=$(LOG_FAILURE) 22 | 23 | XATTR := $(shell command -v xattr 2> /dev/null) 24 | 25 | .PHONY: clean all 26 | all: $(OUTDIR) $(TARGETS) 27 | 28 | $(OUTDIR): 29 | mkdir -p $(OUTDIR) 30 | 31 | clean: 32 | rm -f $(OUTDIR)/*.o 33 | rm -f $(OUTDIR)/*.list 34 | rm -f $(TARGETS) 35 | 36 | $(OUTDIR)/%.o: %.s $(HEADERS) 37 | ca65 $(CAFLAGS) $(DEFINES) --listing $(basename $@).list -o $@ $< 38 | 39 | $(OUTDIR)/%.setup.o: %.system.s $(HEADERS) 40 | ca65 $(CAFLAGS) $(DEFINES) -D BUILD_SETUP_FILE --listing $(basename $@).list -o $@ $< 41 | 42 | $(OUTDIR)/%.BIN $(OUTDIR)/%.SYS: $(OUTDIR)/%.o 43 | ld65 $(LDFLAGS) -o $@ $< 44 | ifdef XATTR 45 | xattr -wx prodos.AuxType '00 20' $@ 46 | endif 47 | -------------------------------------------------------------------------------- /clocks/fujinet/Makefile: -------------------------------------------------------------------------------- 1 | 2 | CAFLAGS = --target apple2enh --list-bytes 0 3 | LDFLAGS = --config apple2-asm.cfg 4 | 5 | OUTDIR = ../../out 6 | 7 | HEADERS = $(wildcard *.inc) $(wildcard ../../inc/*.inc) 8 | 9 | TARGETS = \ 10 | $(OUTDIR)/fn.clock.system.SYS \ 11 | $(OUTDIR)/fn.clock.setup.SYS 12 | 13 | LOG_SUCCESS=1 14 | LOG_FAILURE=1 15 | 16 | # For timestamps 17 | MM = $(shell date "+%-m") 18 | DD = $(shell date "+%-d") 19 | YY = $(shell date "+%-y") 20 | DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY) \ 21 | -D LOG_SUCCESS=$(LOG_SUCCESS) -D LOG_FAILURE=$(LOG_FAILURE) 22 | 23 | XATTR := $(shell command -v xattr 2> /dev/null) 24 | 25 | .PHONY: clean all 26 | all: $(OUTDIR) $(TARGETS) 27 | 28 | $(OUTDIR): 29 | mkdir -p $(OUTDIR) 30 | 31 | clean: 32 | rm -f $(OUTDIR)/*.o 33 | rm -f $(OUTDIR)/*.list 34 | rm -f $(TARGETS) 35 | 36 | $(OUTDIR)/%.o: %.s $(HEADERS) 37 | ca65 $(CAFLAGS) $(DEFINES) --listing $(basename $@).list -o $@ $< 38 | 39 | $(OUTDIR)/%.setup.o: %.system.s $(HEADERS) 40 | ca65 $(CAFLAGS) $(DEFINES) -D BUILD_SETUP_FILE --listing $(basename $@).list -o $@ $< 41 | 42 | $(OUTDIR)/%.BIN $(OUTDIR)/%.SYS: $(OUTDIR)/%.o 43 | ld65 $(LDFLAGS) -o $@ $< 44 | ifdef XATTR 45 | xattr -wx prodos.AuxType '00 20' $@ 46 | endif 47 | -------------------------------------------------------------------------------- /textcolors/README.md: -------------------------------------------------------------------------------- 1 | # Text Color Utilities 2 | 3 | Author: @chrisparana 4 | 5 | These utilities will work with the Apple IIgs or on any Apple II equipped with a VidHD card. Each will set the color of the text, background, and border and then invoke the ProDOS quit handler immediately. 6 | 7 | Useful if you'd like to automatically set a theme at boot or select one manually afterwards. Originally created because I wanted my GS to use a different set of colors when booting my ProDOS 8 partition then what I have set as default in the Control Panel. 8 | 9 | To have these themes applied at boot, place one of the theme SYSTEM at the end of your load chain. 10 | 11 | --- 12 | 13 | [A2GREEN.SYSTEM](a2green.system.s) 14 | * Apple Monitor II green phosphor theme 15 | 16 | [BW.SYSTEM](bw.system.s) 17 | * White text on black background 18 | 19 | [DEEPBLUE.SYSTEM](deepblue.system.s) 20 | * White text on deep blue background 21 | 22 | [GRAY.SYSTEM](gray.system.s) 23 | * Dark gray text on light gray background 24 | 25 | [GSBLUE.SYSTEM](gsblue.system.s) 26 | * The Apple IIgs system defaults 27 | 28 | [MINT.SYSTEM](mint.system.s) 29 | * A minty flavored theme 30 | 31 | [PINK.SYSTEM](pink.system.s) 32 | * Dark gray text on a pink background with light blue borders 33 | 34 | [WB.SYSTEM](wb.system.s) 35 | * Black text on a black background 36 | -------------------------------------------------------------------------------- /util/Makefile: -------------------------------------------------------------------------------- 1 | 2 | CAFLAGS = --target apple2enh --list-bytes 0 3 | LDFLAGS = --config apple2-asm.cfg 4 | 5 | OUTDIR = ../out 6 | 7 | HEADERS = $(wildcard *.inc) $(wildcard ../inc/*.inc) 8 | 9 | TARGETS = \ 10 | $(OUTDIR)/quit.system.SYS \ 11 | $(OUTDIR)/pause.system.SYS \ 12 | $(OUTDIR)/pause.setup.SYS \ 13 | $(OUTDIR)/home.system.SYS \ 14 | $(OUTDIR)/home.setup.SYS \ 15 | $(OUTDIR)/me.first.system.SYS \ 16 | $(OUTDIR)/me.first.setup.SYS \ 17 | $(OUTDIR)/noclock.system.SYS \ 18 | $(OUTDIR)/noclock.setup.SYS \ 19 | $(OUTDIR)/date.BIN 20 | 21 | # For timestamps 22 | MM = $(shell date "+%-m") 23 | DD = $(shell date "+%-d") 24 | YY = $(shell date "+%-y") 25 | DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY) 26 | 27 | XATTR := $(shell command -v xattr 2> /dev/null) 28 | 29 | .PHONY: clean all 30 | all: $(OUTDIR) $(TARGETS) 31 | 32 | $(OUTDIR): 33 | mkdir -p $(OUTDIR) 34 | 35 | clean: 36 | rm -f $(OUTDIR)/*.o 37 | rm -f $(OUTDIR)/*.list 38 | rm -f $(TARGETS) 39 | 40 | $(OUTDIR)/%.o: %.s $(HEADERS) 41 | ca65 $(CAFLAGS) $(DEFINES) --listing $(basename $@).list -o $@ $< 42 | 43 | $(OUTDIR)/%.setup.o: %.system.s $(HEADERS) 44 | ca65 $(CAFLAGS) $(DEFINES) -D BUILD_SETUP_FILE --listing $(basename $@).list -o $@ $< 45 | 46 | $(OUTDIR)/%.BIN $(OUTDIR)/%.SYS: $(OUTDIR)/%.o 47 | ld65 $(LDFLAGS) -o $@ $< 48 | ifdef XATTR 49 | xattr -wx prodos.AuxType '00 20' $@ 50 | endif 51 | -------------------------------------------------------------------------------- /util/me.first.system.s: -------------------------------------------------------------------------------- 1 | 2 | .setcpu "6502" 3 | .linecont + 4 | .feature string_escapes 5 | 6 | .include "apple2.inc" 7 | .include "apple2.mac" 8 | 9 | .include "../inc/apple2.inc" 10 | .include "../inc/macros.inc" 11 | .include "../inc/prodos.inc" 12 | 13 | ;;; ************************************************************ 14 | .include "../inc/driver_preamble.inc" 15 | ;;; ************************************************************ 16 | 17 | .proc maybe_install_driver 18 | ;; Find the current device's index in the list 19 | ldx #0 20 | : lda DEVLST,x 21 | and #$F0 22 | cmp DEVNUM 23 | beq found 24 | inx 25 | cpx DEVCNT 26 | bcc :- 27 | bcs exit ; last one or not found 28 | 29 | ;; Save it 30 | found: ldy DEVLST,x 31 | 32 | ;; Move everything up 33 | : lda DEVLST+1,x 34 | sta DEVLST,x 35 | inx 36 | cpx DEVCNT 37 | bne :- 38 | 39 | ;; Place it at the end 40 | tya 41 | sta DEVLST,x 42 | 43 | exit: rts 44 | .endproc 45 | 46 | ;;; ************************************************************ 47 | .include "../inc/driver_postamble.inc" 48 | ;;; ************************************************************ 49 | -------------------------------------------------------------------------------- /clocks/jumbo/Makefile: -------------------------------------------------------------------------------- 1 | 2 | CAFLAGS = --target apple2enh --list-bytes 0 3 | LDFLAGS = --config apple2-asm.cfg 4 | 5 | OUTDIR = ../../out 6 | 7 | HEADERS = $(wildcard *.inc) $(wildcard ../../inc/*.inc) \ 8 | ../ns.clock/ns.clock.system.s \ 9 | ../romx/romxrtc.system.s \ 10 | ../dclock/dclock.system.s \ 11 | ../fujinet/fn.clock.system.s \ 12 | ../fujinet/smartport.inc \ 13 | ../cricket/cricket.system.s 14 | 15 | TARGETS = \ 16 | $(OUTDIR)/clock.system.SYS \ 17 | $(OUTDIR)/clock.setup.SYS 18 | 19 | LOG_SUCCESS=1 20 | LOG_FAILURE=1 21 | 22 | # For timestamps 23 | MM = $(shell date "+%-m") 24 | DD = $(shell date "+%-d") 25 | YY = $(shell date "+%-y") 26 | DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY) \ 27 | -D LOG_SUCCESS=$(LOG_SUCCESS) -D LOG_FAILURE=$(LOG_FAILURE) 28 | 29 | XATTR := $(shell command -v xattr 2> /dev/null) 30 | 31 | .PHONY: clean all 32 | all: $(OUTDIR) $(TARGETS) 33 | 34 | $(OUTDIR): 35 | mkdir -p $(OUTDIR) 36 | 37 | clean: 38 | rm -f $(OUTDIR)/*.o 39 | rm -f $(OUTDIR)/*.list 40 | rm -f $(TARGETS) 41 | 42 | $(OUTDIR)/%.o: %.s $(HEADERS) 43 | ca65 $(CAFLAGS) $(DEFINES) --listing $(basename $@).list -o $@ $< 44 | 45 | $(OUTDIR)/%.setup.o: %.system.s $(HEADERS) 46 | ca65 $(CAFLAGS) $(DEFINES) -D BUILD_SETUP_FILE --listing $(basename $@).list -o $@ $< 47 | 48 | $(OUTDIR)/%.SYS: $(OUTDIR)/%.o 49 | ld65 $(LDFLAGS) -o $@ $< 50 | ifdef XATTR 51 | xattr -wx prodos.AuxType '00 20' $@ 52 | endif 53 | -------------------------------------------------------------------------------- /clocks/ns.clock/Makefile: -------------------------------------------------------------------------------- 1 | 2 | CAFLAGS = --target apple2enh --list-bytes 0 3 | LDFLAGS = --config apple2-asm.cfg 4 | 5 | OUTDIR = ../../out 6 | UTILDIR = $(OUTDIR)/nsclock.util 7 | 8 | HEADERS = $(wildcard *.inc) $(wildcard ../../inc/*.inc) 9 | 10 | TARGETS = \ 11 | $(OUTDIR)/ns.clock.system.SYS \ 12 | $(OUTDIR)/ns.clock.setup.SYS \ 13 | $(UTILDIR)/set.datetime.BIN 14 | 15 | LOG_SUCCESS=1 16 | LOG_FAILURE=1 17 | 18 | # For timestamps 19 | MM = $(shell date "+%-m") 20 | DD = $(shell date "+%-d") 21 | YY = $(shell date "+%-y") 22 | DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY) \ 23 | -D LOG_SUCCESS=$(LOG_SUCCESS) -D LOG_FAILURE=$(LOG_FAILURE) 24 | 25 | XATTR := $(shell command -v xattr 2> /dev/null) 26 | 27 | .PHONY: clean all 28 | all: $(OUTDIR) $(UTILDIR) $(TARGETS) 29 | 30 | $(OUTDIR) $(UTILDIR): 31 | mkdir -p $@ 32 | 33 | clean: 34 | rm -f $(OUTDIR)/*.o 35 | rm -f $(OUTDIR)/*.list 36 | rm -f $(UTILDIR)/*.o 37 | rm -f $(UTILDIR)/*.list 38 | rm -f $(TARGETS) 39 | 40 | $(OUTDIR)/%.o $(UTILDIR)/%.o: %.s $(HEADERS) 41 | ca65 $(CAFLAGS) $(DEFINES) --listing $(basename $@).list -o $@ $< 42 | 43 | $(OUTDIR)/%.setup.o: %.system.s $(HEADERS) 44 | ca65 $(CAFLAGS) $(DEFINES) -D BUILD_SETUP_FILE --listing $(basename $@).list -o $@ $< 45 | 46 | $(OUTDIR)/%.SYS: $(OUTDIR)/%.o 47 | ld65 $(LDFLAGS) -o $@ $< 48 | 49 | $(UTILDIR)/%.BIN: $(UTILDIR)/%.o 50 | ld65 $(LDFLAGS) -o $@ $< 51 | ifdef XATTR 52 | xattr -wx prodos.AuxType '00 20' $@ 53 | endif 54 | -------------------------------------------------------------------------------- /textcolors/Makefile: -------------------------------------------------------------------------------- 1 | 2 | CAFLAGS = --target apple2enh --list-bytes 0 3 | LDFLAGS = --config apple2-asm.cfg 4 | 5 | OUTDIR = ../out 6 | 7 | HEADERS = $(wildcard *.inc) $(wildcard ../inc/*.inc) 8 | 9 | TARGETS = \ 10 | $(OUTDIR)/a2green.system.SYS \ 11 | $(OUTDIR)/a2green.setup.SYS \ 12 | $(OUTDIR)/bw.system.SYS \ 13 | $(OUTDIR)/bw.setup.SYS \ 14 | $(OUTDIR)/deepblue.system.SYS \ 15 | $(OUTDIR)/deepblue.setup.SYS \ 16 | $(OUTDIR)/gray.system.SYS \ 17 | $(OUTDIR)/gray.setup.SYS \ 18 | $(OUTDIR)/gsblue.system.SYS \ 19 | $(OUTDIR)/gsblue.setup.SYS \ 20 | $(OUTDIR)/mint.system.SYS \ 21 | $(OUTDIR)/mint.setup.SYS \ 22 | $(OUTDIR)/pink.system.SYS \ 23 | $(OUTDIR)/pink.setup.SYS \ 24 | $(OUTDIR)/wb.system.SYS \ 25 | $(OUTDIR)/wb.setup.SYS 26 | 27 | # For timestamps 28 | MM = $(shell date "+%-m") 29 | DD = $(shell date "+%-d") 30 | YY = $(shell date "+%-y") 31 | DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY) 32 | 33 | XATTR := $(shell command -v xattr 2> /dev/null) 34 | 35 | .PHONY: clean all 36 | all: $(OUTDIR) $(TARGETS) 37 | 38 | $(OUTDIR): 39 | mkdir -p $(OUTDIR) 40 | 41 | clean: 42 | rm -f $(OUTDIR)/*.o 43 | rm -f $(OUTDIR)/*.list 44 | rm -f $(TARGETS) 45 | 46 | $(OUTDIR)/%.o: %.s $(HEADERS) 47 | ca65 $(CAFLAGS) $(DEFINES) --listing $(basename $@).list -o $@ $< 48 | 49 | $(OUTDIR)/%.setup.o: %.system.s $(HEADERS) 50 | ca65 $(CAFLAGS) $(DEFINES) -D BUILD_SETUP_FILE --listing $(basename $@).list -o $@ $< 51 | 52 | $(OUTDIR)/%.BIN $(OUTDIR)/%.SYS: $(OUTDIR)/%.o 53 | ld65 $(LDFLAGS) -o $@ $< 54 | -------------------------------------------------------------------------------- /clocks/cricket/Makefile: -------------------------------------------------------------------------------- 1 | 2 | CAFLAGS = --target apple2enh --list-bytes 0 3 | LDFLAGS = --config apple2-asm.cfg 4 | 5 | OUTDIR = ../../out 6 | UTILDIR = $(OUTDIR)/cricket.util 7 | 8 | HEADERS = $(wildcard *.inc) $(wildcard ../../inc/*.inc) 9 | 10 | TARGETS = \ 11 | $(UTILDIR)/prodos.mod.BIN \ 12 | $(OUTDIR)/cricket.system.SYS \ 13 | $(OUTDIR)/cricket.setup.SYS \ 14 | $(UTILDIR)/test.BIN \ 15 | $(UTILDIR)/set.datetime.BIN \ 16 | $(UTILDIR)/set.time.BIN \ 17 | $(UTILDIR)/set.date.BIN 18 | 19 | LOG_SUCCESS=1 20 | LOG_FAILURE=1 21 | 22 | # For timestamps 23 | MM = $(shell date "+%-m") 24 | DD = $(shell date "+%-d") 25 | YY = $(shell date "+%-y") 26 | DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY) \ 27 | -D LOG_SUCCESS=$(LOG_SUCCESS) -D LOG_FAILURE=$(LOG_FAILURE) 28 | 29 | XATTR := $(shell command -v xattr 2> /dev/null) 30 | 31 | .PHONY: clean all 32 | all: $(OUTDIR) $(UTILDIR) $(TARGETS) 33 | 34 | $(OUTDIR) $(UTILDIR): 35 | mkdir -p $@ 36 | 37 | clean: 38 | rm -f $(OUTDIR)/*.o 39 | rm -f $(OUTDIR)/*.list 40 | rm -f $(UTILDIR)/*.o 41 | rm -f $(UTILDIR)/*.list 42 | rm -f $(TARGETS) 43 | 44 | $(OUTDIR)/%.o $(UTILDIR)/%.o: %.s $(HEADERS) 45 | ca65 $(CAFLAGS) $(DEFINES) --listing $(basename $@).list -o $@ $< 46 | 47 | $(OUTDIR)/%.setup.o: %.system.s $(HEADERS) 48 | ca65 $(CAFLAGS) $(DEFINES) -D BUILD_SETUP_FILE --listing $(basename $@).list -o $@ $< 49 | 50 | $(OUTDIR)/%.SYS: $(OUTDIR)/%.o 51 | ld65 $(LDFLAGS) -o $@ $< 52 | 53 | $(UTILDIR)/%.BIN: $(UTILDIR)/%.o 54 | ld65 $(LDFLAGS) -o $@ $< 55 | ifdef XATTR 56 | xattr -wx prodos.AuxType '00 20' $@ 57 | endif 58 | -------------------------------------------------------------------------------- /clocks/README.md: -------------------------------------------------------------------------------- 1 | # ProDOS Clock Drivers 2 | 3 | Other than the Apple IIgs model, the Apple II did not ship with a real-time system clock. Many third party [Apple II system clocks](https://en.wikipedia.org/wiki/Apple_II_system_clocks) were produced in the 1980s, and many new system clocks are available, either as entirely new designs or recreations. 4 | 5 | The ProDOS operating system for the Apple II personal computer line natively supports the Thunderclock real-time clock card, but there is a protocol for custom clock drivers to be installed: 6 | 7 | * Check `MACHID` bit 0 to see if a clock is already active; abort if so. 8 | * Optional: Probe hardware to determine if the clock is present; abort if not. 9 | * Relocate the clock driver to LC bank 1, at the address at `DATETIME`+1 10 | * Update `DATETIME` to be a `JMP` instruction. 11 | * Optional: Chain to the next `.SYSTEM` file. 12 | 13 | In addition: 14 | 15 | * The clock driver must fit into 125 bytes. 16 | * The driver may dirty $200-$207 but other memory must be restored if modified. 17 | * When invoked, the clock driver should read the clock hardware and encode the date and time into `DATELO`/`DATEHI` and `TIMELO`/`TIMEHI`. 18 | * ProDOS calls the clock driver when `GET_TIME` is called, and on every call (`CREATE`, `RENAME`, etc) that might need the date and time. 19 | 20 | See https://prodos8.com/docs/techref/adding-routines-to-prodos/ for more information. 21 | 22 | ## Included drivers 23 | 24 | This directory includes drivers for the following real-time clocks: 25 | 26 | * [No-Slot Clock](https://www.reactivemicro.com/product/no-slot-clock/) 27 | * [ROMX Real-Time Clock](https://theromexchange.com/) 28 | * [FujiNet Clock](https://fujinet.online/) 29 | * DClock 30 | * Cricket! 31 | 32 | All follow the above protocol: install only if there is not already a clock, probe for the clock before installing, and chain to the next driver. 33 | 34 | In addition, the "jumbo" directory combines the other driver installers to create a single unified clock driver installer. See its [README](jumbo/README.md) for more details. 35 | -------------------------------------------------------------------------------- /package.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Use Cadius to create a disk image for distribution 4 | # https://github.com/mach-kernel/cadius 5 | 6 | set -e 7 | 8 | PACKDIR=$(mktemp -d) 9 | IMGFILE="prodos-drivers.po" 10 | VOLNAME="drivers" 11 | 12 | rm -f "$IMGFILE" 13 | cadius CREATEVOLUME "$IMGFILE" "$VOLNAME" 140KB --no-case-bits --quiet 14 | cadius CREATEFOLDER "$IMGFILE" "/$VOLNAME/SETUPS" --no-case-bits --quiet 15 | 16 | add_file () { 17 | cp "$1" "$PACKDIR/$2" 18 | cadius ADDFILE "$IMGFILE" "$3" "$PACKDIR/$2" --no-case-bits --quiet 19 | } 20 | 21 | # Drivers 22 | 23 | for file in \ 24 | "bbb" "buhbye" "bye" "selector" \ 25 | "clock" "cricket" "dclock" "fn.clock" "ns.clock" "romxrtc" \ 26 | "ram.drv" \ 27 | "zipchip" \ 28 | "me.first" "pause" "home" "noclock"; do 29 | add_file "out/$file.system.SYS" "$file.system#FF0000" "/$VOLNAME" 30 | add_file "out/$file.setup.SYS" "$file.setup#FF0000" "/$VOLNAME/SETUPS" 31 | done 32 | add_file "out/setup.system.SYS" "setup.system#FF0000" "/$VOLNAME" 33 | add_file "out/quit.system.SYS" "quit.system#FF0000" "/$VOLNAME" 34 | 35 | # Utilities 36 | 37 | add_file "out/date.BIN" "date#062000" "/$VOLNAME" 38 | 39 | cadius CREATEFOLDER "$IMGFILE" "/$VOLNAME/CRICKET.UTIL" --no-case-bits --quiet 40 | add_file "out/cricket.util/set.datetime.BIN" "set.datetime#062000" "/$VOLNAME/CRICKET.UTIL" 41 | add_file "out/cricket.util/set.date.BIN" "set.date#062000" "/$VOLNAME/CRICKET.UTIL" 42 | add_file "out/cricket.util/set.time.BIN" "set.time#062000" "/$VOLNAME/CRICKET.UTIL" 43 | add_file "out/cricket.util/test.BIN" "test#062000" "/$VOLNAME/CRICKET.UTIL" 44 | 45 | cadius CREATEFOLDER "$IMGFILE" "/$VOLNAME/NSCLOCK.UTIL" --no-case-bits --quiet 46 | add_file "out/nsclock.util/set.datetime.BIN" "set.datetime#062000" "/$VOLNAME/NSCLOCK.UTIL" 47 | 48 | 49 | 50 | cadius CREATEFOLDER "$IMGFILE" "/$VOLNAME/TEXTCOLORS" --no-case-bits --quiet 51 | cadius CREATEFOLDER "$IMGFILE" "/$VOLNAME/SETUPS/TEXTCOLORS" --no-case-bits --quiet 52 | for file in a2green bw deepblue gray gsblue mint pink wb; do 53 | add_file "out/${file}.system.SYS" "${file}.system#FF0000" "/$VOLNAME/TEXTCOLORS" 54 | add_file "out/${file}.setup.SYS" "${file}.setup#FF0000" "/$VOLNAME/TEXTCOLORS/SETUPS" 55 | done 56 | 57 | rm -r "$PACKDIR" 58 | 59 | cadius CATALOG "$IMGFILE" 60 | -------------------------------------------------------------------------------- /util/date.s: -------------------------------------------------------------------------------- 1 | ;;; Query ProDOS and print the current date/time 2 | 3 | ;;; Output is: MM/DD/YY HH:MM 4 | 5 | .setcpu "6502" 6 | .org $2000 7 | 8 | .include "apple2.inc" 9 | 10 | .include "../inc/apple2.inc" 11 | .include "../inc/macros.inc" 12 | .include "../inc/prodos.inc" 13 | 14 | start: 15 | MLI_CALL GET_TIME, 0 16 | 17 | ;;; DATEHI ($BF91) DATELO ($BF90) 18 | ;;; 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 19 | ;;; +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ 20 | ;;; DATE: | year | month | day | 21 | ;;; +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ 22 | ;;; 23 | ;;; TIMEHI ($BF93) TIMELO ($BF92) 24 | ;;; 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 25 | ;;; +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ 26 | ;;; TIME: |0 0 0| hour | |0 0| minute | 27 | ;;; +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ 28 | 29 | ;; Date 30 | 31 | lda DATELO+1 ; month 32 | ror a 33 | pha 34 | lda DATELO 35 | pha 36 | rol a 37 | rol a 38 | rol a 39 | rol a 40 | and #%00001111 41 | jsr cout_number 42 | 43 | lda #HI('/') ; / 44 | jsr COUT 45 | 46 | pla ; day 47 | and #%00011111 48 | jsr cout_number 49 | 50 | lda #HI('/') ; / 51 | jsr COUT 52 | 53 | pla ; year 54 | jsr cout_number 55 | 56 | lda #HI(' ') 57 | jsr COUT 58 | jsr COUT 59 | 60 | ;; Time 61 | 62 | lda TIMELO+1 ; hour 63 | and #%00011111 64 | jsr cout_number 65 | 66 | lda #HI(':') ; ':' 67 | jsr COUT 68 | 69 | lda TIMELO ; minute 70 | and #%00111111 71 | jsr cout_number 72 | 73 | jsr CROUT 74 | 75 | rts 76 | 77 | ;;; ------------------------------------------------------------ 78 | 79 | .proc cout_number 80 | ldx #HI('0') 81 | cmp #10 ; >= 10? 82 | bcc tens 83 | 84 | ;; divide by 10, dividend(+'0') in x remainder in a 85 | : sbc #10 86 | inx 87 | cmp #10 88 | bcs :- 89 | 90 | tens: pha 91 | txa 92 | jsr COUT 93 | 94 | units: pla 95 | ora #HI('0') 96 | jsr COUT 97 | rts 98 | .endproc 99 | -------------------------------------------------------------------------------- /clocks/cricket/set.time.s: -------------------------------------------------------------------------------- 1 | ;;; SET.TIME utility for The Cricket! 2 | ;;; Prompts for time and sends Cricket "Set Time" sequence. 3 | 4 | .setcpu "6502" 5 | .linecont + 6 | .feature string_escapes 7 | 8 | .include "apple2.inc" 9 | .include "apple2.mac" 10 | 11 | .include "../../inc/apple2.inc" 12 | .include "../../inc/macros.inc" 13 | .include "../../inc/ascii.inc" 14 | 15 | .org $2000 16 | 17 | .proc main 18 | jsr zstrout 19 | scrcode "\rTime: HH:MM:SS\x08\x08\x08\x08\x08\x08\x08\x08" 20 | .byte 0 21 | 22 | jsr GETLN2 23 | 24 | php 25 | sei 26 | 27 | ;; Reset SSC 28 | sta KBDSTRB ; Port 2 DSR line connected to KBDSTRB 29 | lda #0 30 | sta COMMAND 31 | sta CONTROL 32 | 33 | ;; Configure SSC 34 | lda #%00001011 ; no parity/echo/interrupts, RTS low, DTR low 35 | sta COMMAND 36 | lda #%10011110 ; 9600 baud, 8 data bits, 2 stop bits 37 | sta CONTROL 38 | 39 | ;; Clock Commands 40 | ;; Set Time "ST HH:MM:SS" 41 | lda #HI('S') 42 | jsr sendbyte 43 | lda #HI('T') 44 | jsr sendbyte 45 | lda #HI(' ') 46 | jsr sendbyte 47 | 48 | ldx #0 49 | loop: lda INPUT_BUFFER,x 50 | jsr sendbyte 51 | inx 52 | cmp #HI(ASCII_CR) 53 | bne loop 54 | 55 | plp 56 | 57 | rts 58 | .endproc 59 | 60 | ;; Write byte in A to SSC 61 | .proc sendbyte 62 | pha 63 | : lda STATUS 64 | and #(1 << 4) ; transmit register empty? (bit 4) 65 | beq :- ; nope, keep waiting 66 | pla 67 | sta TDREG 68 | rts 69 | .endproc 70 | 71 | 72 | ;;; ------------------------------------------------------------ 73 | ;;; Output a high-ascii, null-terminated string. 74 | ;;; String immediately follows the JSR. 75 | 76 | .proc zstrout 77 | ptr := $A5 78 | 79 | pla ; read address from stack 80 | sta ptr 81 | pla 82 | sta ptr+1 83 | bne skip ; always (since data not on ZP) 84 | 85 | next: jsr COUT 86 | skip: inc ptr 87 | bne :+ 88 | inc ptr+1 89 | : ldy #0 90 | lda (ptr),y 91 | bne next 92 | 93 | lda ptr+1 ; restore address to stack 94 | pha 95 | lda ptr 96 | pha 97 | rts 98 | .endproc 99 | 100 | ;;; ------------------------------------------------------------ 101 | -------------------------------------------------------------------------------- /clocks/cricket/set.date.s: -------------------------------------------------------------------------------- 1 | ;;; SET.DATE utility for The Cricket! 2 | ;;; Prompts for date and sends Cricket "Set Date" sequence. 3 | 4 | .setcpu "6502" 5 | .linecont + 6 | .feature string_escapes 7 | 8 | .include "apple2.inc" 9 | .include "apple2.mac" 10 | 11 | .include "../../inc/apple2.inc" 12 | .include "../../inc/macros.inc" 13 | .include "../../inc/ascii.inc" 14 | 15 | .org $2000 16 | 17 | .proc main 18 | jsr zstrout 19 | scrcode "\rDate: WWW MM/DD/YY\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" 20 | .byte 0 21 | 22 | jsr GETLN2 23 | 24 | php 25 | sei 26 | 27 | ;; Reset SSC 28 | sta KBDSTRB ; Port 2 DSR line connected to KBDSTRB 29 | lda #0 30 | sta COMMAND 31 | sta CONTROL 32 | 33 | ;; Configure SSC 34 | lda #%00001011 ; no parity/echo/interrupts, RTS low, DTR low 35 | sta COMMAND 36 | lda #%10011110 ; 9600 baud, 8 data bits, 2 stop bits 37 | sta CONTROL 38 | 39 | ;; Clock Commands 40 | ;; Set Date "SD WWW MM/DD/YY" 41 | lda #HI('S') 42 | jsr sendbyte 43 | lda #HI('D') 44 | jsr sendbyte 45 | lda #HI(' ') 46 | jsr sendbyte 47 | 48 | ldx #0 49 | loop: lda INPUT_BUFFER,x 50 | jsr sendbyte 51 | inx 52 | cmp #HI(ASCII_CR) 53 | bne loop 54 | 55 | plp 56 | 57 | rts 58 | .endproc 59 | 60 | ;; Write byte in A to SSC 61 | .proc sendbyte 62 | pha 63 | : lda STATUS 64 | and #(1 << 4) ; transmit register empty? (bit 4) 65 | beq :- ; nope, keep waiting 66 | pla 67 | sta TDREG 68 | rts 69 | .endproc 70 | 71 | 72 | ;;; ------------------------------------------------------------ 73 | ;;; Output a high-ascii, null-terminated string. 74 | ;;; String immediately follows the JSR. 75 | 76 | .proc zstrout 77 | ptr := $A5 78 | 79 | pla ; read address from stack 80 | sta ptr 81 | pla 82 | sta ptr+1 83 | bne skip ; always (since data not on ZP) 84 | 85 | next: jsr COUT 86 | skip: inc ptr 87 | bne :+ 88 | inc ptr+1 89 | : ldy #0 90 | lda (ptr),y 91 | bne next 92 | 93 | lda ptr+1 ; restore address to stack 94 | pha 95 | lda ptr 96 | pha 97 | rts 98 | .endproc 99 | 100 | ;;; ------------------------------------------------------------ 101 | -------------------------------------------------------------------------------- /setup/README.md: -------------------------------------------------------------------------------- 1 | # SETUP.SYSTEM 2 | 3 | The November 1987 edition of Call-A.P.P.L.E features an article by Sean Nolan, ["SYSTEM.SETUP - A Proposed Startup File Standard"](https://www.callapple.org/magazines-4/call-a-p-p-l-e/setup-system-a-proposed-startup-file-standard/). The article was reprinted in [Beneath Apple DOS ProDOS 2020](https://archive.org/details/beneath-apple-dos-prodos-2020). The proposal combines the ProDOS-8 notion of running the first .SYSTEM file found on disk and the convention of chaining to the next .SYSTEM file, with the ProDOS-16 notion of enumerating a directory of startup files. A main `SETUP.SYSTEM` file is provided which enumerates all files in a `SETUPS/` directory. These "setup files" are BIN or SYS files which work like standard ProDOS-8 drivers. The advantages of this approach are: 4 | 5 | * The top level directory only needs one SYSTEM file plus `SETUPS/`, which reduces clutter. 6 | * Each individual setup file is simpler than stand-alone SYSTEM files, as they don't need to implement chaining. 7 | 8 | Which approach you use is a matter of taste. 9 | 10 | ## How do you use these? 11 | 12 | If you choose this approach, use a tool like Copy II Plus or [Apple II DeskTop](https://github.com/a2stuff/a2d) to copy and arrange `SETUP.SYSTEM` as the first `.SYSTEM` file in your root directory. Create a `SETUPS/` directory, and copy the appropriate `.SETUPS` files there. A boot disk image catalog that is used on multiple different hardware configurations might include: 13 | 14 | * `PRODOS` - the operating system, e.g. [ProDOS 2.4](https://prodos8.com/) 15 | * `SETUP.SYSTEM` - install No-Slot clock driver, if present 16 | * `SETUPS/` - directory used by `SETUP.SYSTEM`, which contains: 17 | * `SETUPS/HOME.SETUP` - start off with a blank screen 18 | * `SETUPS/NS.CLOCK.SETUP` - install No-Slot clock driver, if present 19 | * `SETUPS/ROMXRTC.SETUP` - install ROMX clock driver, if present 20 | * `SETUPS/FN.CLOCK.SETUP` - install FujiNet clock driver, if present 21 | * `SETUPS/DCLOCK.SETUP` - install DClock clock driver, if present 22 | * `SETUPS/CRICKET.SETUP` - install Cricket! clock driver, if present 23 | * `SETUPS/ZIPCHIP.SETUP` - slow the ZIP CHIP on speaker access, if present 24 | * `SETUPS/RAM.DRV.SETUP` - install RamWorks RAM disk driver, if present 25 | * `SETUPS/BUHBYE.SETUP` - install a customized Quit handler to replace the built-in one 26 | * `SETUPS/PAUSE.SETUP` - pause for a moment, so that you can inspect the output of the above 27 | * `QUIT.SYSTEM` - invoke the Quit handler immediately, as a program selector 28 | * `BASIC.SYSTEM` - which will not be automatically invoked, but is available to manually invoke 29 | 30 | ## Notes 31 | 32 | The `SETUP.SYSTEM` program is not modified from the published version except that it no longer clears the screen between running each file in `SETUPS/`, so that any logged output remains visible. 33 | -------------------------------------------------------------------------------- /clocks/cricket/README.md: -------------------------------------------------------------------------------- 1 | # _The Cricket!_ — ProDOS Clock Driver 2 | 3 | I acquired a Cricket sound/clock peripheral on eBay. Therefore it is now critical that we have a conforming ProDOS clock driver for it. 4 | 5 | > STATUS: Works on my machine! 6 | 7 | ## Background 8 | 9 | _"The Cricket!"_ by Street Electronics Corporation, released in 1984, is a hardware peripheral for the Apple //c computer. It plugs into the serial port and offers a multi-voice sound synthesizer, a speech synthesizer, and a real-time clock. 10 | 11 | The disks supplied with the device include: 12 | * `/CRICKET/PRODOS.MOD` which can be BRUN to patch ProDOS in memory with a clock driver. 13 | * A modified version of ProDOS 14 | * A utility to patch ProDOS on disk 15 | 16 | ## `CRICKET.SYSTEM` 17 | 18 | Like the `NS.CLOCK.SYSTEM` (by "CAP"), `CRICKET.SYSTEM` has these features: 19 | 20 | * [x] A ProDOS `.SYSTEM` file 21 | * [x] Detects the presence of a Cricket 22 | * [x] Installs a driver in memory following the ProDOS clock driver protocol 23 | * [x] Chains to the next `.SYSTEM` file (e.g. `BASIC.SYSTEM`) 24 | 25 | Successfully tested on real hardware. (Laser 128EX, an Apple //c clone — including at 3x speed!) 26 | 27 | ## Build 28 | 29 | Requires [cc65](https://github.com/cc65/cc65). The included `Makefile` is very specific to my machine - sorry about that. 30 | 31 | [CRICKET.SYSTEM](cricket.system.s) is the result of the build. 32 | 33 | ## Notes 34 | 35 | I ended up disassembling both [NS.CLOCK.SYSTEM](../ns.clock/ns.clock.system.s) (to understand the SYSTEM chaining - what a pain!) and The Cricket!'s [PRODOS.MOD](prodos.mod.s) and melding them together, adding in the detection routine following the protocol in the manual. 36 | 37 | ## Other Utilities 38 | 39 | These `BRUN`able files are also built: 40 | * [TEST](test.s) attempts to identify an SSC in Slot 2 and the Cricket via the ID sequence, to test routines. 41 | * [SET.DATETIME](set.datetime.s) sets the Cricket's current date and time. 42 | * [SET.DATE](set.date.s) sets the Cricket's current date. 43 | * [SET.TIME](set.time.s) sets the Cricket's current time. 44 | 45 | `CRICKET.SETUP` is for use with [SETUP.SYSTEM](../../setup/README.md) 46 | 47 | ## Resources 48 | 49 | Cricket disks on Asimov: 50 | * ftp://ftp.apple.asimov.net/pub/apple_II/images/hardware/sound/cricket_disk1.po 51 | * ftp://ftp.apple.asimov.net/pub/apple_II/images/hardware/sound/cricket_disk2.po 52 | 53 | Cricket Manual on Asimov: 54 | * ftp://ftp.apple.asimov.net/pub/apple_II/documentation/hardware/sound/Street%20Electronics%20The%20Cricket.pdf 55 | 56 | ## FYI... 57 | 58 | In the Cricket manual there is a short sample BASIC program to set the clock without the use of any assembly routines, using `PR#2` to talk to the serial card followed by `PRINT` statements. This does not appear to work from ProDOS with the clock driver in place - the time ends up temporarily scrambled until the clock sorts itself out again. Assembly language routines do work, however. I believe ProDOS attempts to read the clock during the execution of the basic program, which interferes the device. 59 | -------------------------------------------------------------------------------- /clocks/fujinet/smartport.inc: -------------------------------------------------------------------------------- 1 | ;;; ------------------------------------------------------------ 2 | ;;; Smartport access functions 3 | ;;; Derived from: http://mirrors.apple2.org.za/ground.icaen.uiowa.edu/MiscInfo/Programming/smartport.statusexample 4 | 5 | ;;; This function scans the slots to locate a SmartPort. 6 | ;;; On entry, X=$Cx, where x is the first slot to be checked. 7 | ;;; On exit, X=$Cy, where y is the highest numbered slot less than or 8 | ;;; equal to x which contains SmartPort firmware. If no SmartPort 9 | ;;; is found, C=1 and A=$00. 10 | ptr := $A5 ; Generic pointer 11 | 12 | .proc find_smartport 13 | LDA #$00 14 | STA ptr ; Set up the pointer 15 | try_slot: 16 | STX ptr+1 17 | LDY #$01 18 | LDA (ptr),Y ; Check the first ID byte 19 | CMP #$20 20 | BNE not_here 21 | LDY #$03 22 | LDA (ptr),Y ; and the second one 23 | CMP #$00 24 | BNE not_here 25 | LDY #$05 26 | LDA (ptr),Y ; and the third one 27 | CMP #$03 28 | BNE not_here 29 | LDY #$07 30 | LDA (ptr),Y ; and the fourth one 31 | CMP #$00 32 | BNE not_here 33 | LDX ptr+1 ; Match! Get the address back 34 | CLC 35 | RTS 36 | not_here: 37 | LDX ptr+1 ; Mismatch 38 | DEX ; Go down one slot 39 | CPX #$C1 40 | BCS try_slot ; Stop once we have gone past slot 1 41 | LDX #$00 42 | SEC ; Error - no SmartPort found 43 | RTS 44 | .endproc 45 | 46 | ;;; This function sets up the SP_CALL function for calling the 47 | ;;; SmartPort driver. On entry, X=$Cx, where x is the slot number 48 | ;;; containing a SmartPort driver. This should be checked via 49 | ;;; FIND_SMARTPORT if necessary - don't assume there is a SmartPort 50 | ;;; device in slot 5, for example! 51 | .proc setup_smartport 52 | LDA #$00 53 | STA ptr ; Set up the pointer 54 | STX ptr+1 55 | LDY #$FF 56 | LDA (ptr),Y ; Get the ProDOS driver entry point 57 | CLC 58 | ADC #$03 ; Get the SmartPort driver entry point 59 | STA sp_call_lo ; Store in the JSR 60 | STX sp_call_hi ; also store the high byte 61 | RTS 62 | .endproc 63 | 64 | ;;; This function return in X the number of devices available 65 | ;;; on a SmartPort 66 | .proc device_count 67 | LDA #$00 68 | STA st_unit 69 | STA st_code 70 | JSR sp_call 71 | BCS device_count_error 72 | LDX st_list+0 73 | RTS 74 | device_count_error: 75 | LDX #$00 76 | RTS 77 | .endproc 78 | 79 | ;;; This function returns in A the device type for a unit in X 80 | .proc unit_type 81 | STX st_unit 82 | LDA #$03 83 | STA st_code 84 | JSR sp_call 85 | BCS unit_type_error 86 | LDA st_list+21 87 | LDX st_unit 88 | RTS 89 | unit_type_error: 90 | LDA #$ff 91 | LDX st_unit 92 | RTS 93 | .endproc 94 | 95 | 96 | 97 | ;;; Status command parameters 98 | sp_call: JSR $0000 99 | sp_call_hi = *-1 100 | sp_call_lo = *-2 101 | .byte DRIVER_COMMAND_STATUS ; Command Status 102 | params_address: 103 | .word st_params 104 | RTS 105 | 106 | st_params: 107 | .byte $3 ; Parameter count 108 | st_unit:.byte $0 109 | .word st_list 110 | st_code:.byte $0 111 | st_list:.byte 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24 112 | -------------------------------------------------------------------------------- /inc/apple2.inc: -------------------------------------------------------------------------------- 1 | ;;; ============================================================ 2 | ;;; 3 | ;;; More Apple II Symbols 4 | ;;; 5 | ;;; ============================================================ 6 | 7 | ;;; ============================================================ 8 | ;;; Soft Switches 9 | ;;; ============================================================ 10 | 11 | ;;; I/O Soft Switches / Firmware 12 | 13 | RAMRDOFF := $C002 14 | RAMRDON := $C003 15 | RAMWRTOFF := $C004 16 | RAMWRTON := $C005 17 | ALTZPOFF := $C008 18 | ALTZPON := $C009 19 | 20 | CLR80VID := $C00C 21 | SET80VID := $C00D 22 | RDALTZP := $C016 23 | RD80STORE := $C018 24 | RDPAGE2 := $C01C 25 | 26 | TBCOLOR := $C022 ; IIgs: low nibble is text bg color, high is fg 27 | CLOCKCTL := $C034 ; IIgs: low nibble is border color 28 | 29 | BANKSEL := $C073 ; Select RamWorks bank 30 | 31 | ROMIN2 := $C082 ; Read ROM; no write 32 | ROMINWB1 := $C089 ; Read ROM; write RAM bank 1 33 | RWRAM1 := $C08B ; Read/write RAM bank 1 34 | 35 | ;;; ============================================================ 36 | ;;; I/O Registers (for Slot 2) 37 | ;;; ============================================================ 38 | 39 | TDREG := $C088 + $20 ; ACIA Transmit Register (write) 40 | RDREG := $C088 + $20 ; ACIA Receive Register (read) 41 | STATUS := $C089 + $20 ; ACIA Status/Reset Register 42 | COMMAND := $C08A + $20 ; ACIA Command Register (read/write) 43 | CONTROL := $C08B + $20 ; ACIA Control Register (read/write) 44 | 45 | ;;; ============================================================ 46 | ;;; Other Slots 47 | ;;; ============================================================ 48 | 49 | SLOT3 := $C300 50 | 51 | ;;; ============================================================ 52 | ;;; Monitor ROM routines 53 | ;;; ============================================================ 54 | 55 | INIT := $FB2F 56 | SETTXT := $FB39 57 | TABV := $FB5B 58 | SETPWRC := $FB6F 59 | VERSION := $FBB3 60 | ZIDBYTE := $FBC0 61 | BELL1 := $FBDD 62 | HOME := $FC58 63 | CLREOL := $FC9C 64 | WAIT := $FCA8 65 | RDKEY := $FD0C 66 | GETLN := $FD6A ; with prompt character 67 | GETLN2 := $FD6F ; no prompt character 68 | CROUT := $FD8E 69 | PRBYTE := $FDDA 70 | COUT := $FDED 71 | COUT1 := $FDF0 72 | SETINV := $FE80 73 | SETNORM := $FE84 74 | SETKBD := $FE89 75 | SETVID := $FE93 76 | BELL := $FF3A 77 | 78 | ;;; ============================================================ 79 | ;;; Applesoft ROM routines 80 | ;;; ============================================================ 81 | ;;; These require various ZP locations to be initialized. 82 | 83 | LINPRNT := $ED24 ; print X,A as integer 84 | 85 | ;;; ============================================================ 86 | ;;; Well-known RAM locations 87 | ;;; ============================================================ 88 | 89 | INPUT_BUFFER := $200 90 | RESETVEC := $3F2 91 | COL80HPOS := $57B 92 | 93 | ;;; ============================================================ 94 | ;;; Applesoft Zero Page Locations 95 | ;;; ============================================================ 96 | 97 | TEMPPT := $52 98 | TEMPST := $55 99 | SHIFT_SIGN_EXT := $A4 100 | SPEEDZ := $F1 101 | FLASH_BIT := $F3 102 | -------------------------------------------------------------------------------- /selectors/README.md: -------------------------------------------------------------------------------- 1 | # ProDOS Program Selectors ("BYE" commands) 2 | 3 | The ProDOS operating system for the Apple II personal computer line supported a quit routine (invoked from BASIC with the `BYE` command) allowing the user to launch a new system file once previous system file had exited. 4 | 5 | This selector code evolved over time, and the memory location that the routine was stored at was documented, allowing users to install customized versions coded to fit within a mere 768 bytes. 6 | 7 | ## ProDOS 1.0 through 1.8 - Selector 8 | 9 | The earliest versions of ProDOS supported a simple 40-column-friendly selector prompting: 10 | 11 | * `ENTER PREFIX (PRESS "RETURN" TO ACCEPT)"` 12 | * `ENTER PATHNAME OF NEXT APPLICATION` 13 | 14 | This was not particularly user friendly. 15 | 16 | ℹ️ If you want to use this selector with any version of ProDOS, add the `SELECTOR.SYSTEM` file to your boot sequence. You can follow it with `QUIT.SYSTEM` in your driver sequence to show the selector on startup. 17 | 18 | ## Bird's Better Bye 19 | 20 | [Alan Bird](https://alanlbird.wordpress.com/products/) wrote a replacement called **Bird's Better Bye** that would patch itself into ProDOS. Directories and system files could be selected with arrows keys and the Return key, Escape would back up a directory level, Tab would change drives. This also functioned in 40 column mode. 21 | 22 | ℹ️ If you want to use this selector with any version of ProDOS, add the `BBB.SYSTEM` file to your boot sequence. You can follow it with `QUIT.SYSTEM` in your driver sequence to show the selector on startup. 23 | 24 | ## ProDOS 1.9 and 2.0.x - 80-column Selector 25 | 26 | ProDOS 1.9 introduced a much improved menu-driven selector showing a list of files and allowing navigation of the file system with the keyboard. Directories and system files could be selected with arrows keys and the Return key, Escape would back up a directory level, Tab would change drives. This required 80 columns and a 65C02 processor, and took advantage of the [MouseText characters](https://en.wikipedia.org/wiki/MouseText) to show folder glyphs for directories. 27 | 28 | If these versions of ProDOS were started on systems without 40 column support, the previous version of the selector would be loaded instead (both were present in the PRODOS system file.) 29 | 30 | ℹ️ If you want to use this selector with any version of ProDOS, add the `BYE.SYSTEM` file to your boot sequence. You can follow it with `QUIT.SYSTEM` in your driver sequence to show the selector on startup. 31 | 32 | This was inspired by the work of Dave Cotter who created a similarly named file to patch the selector back in. It can be found at: http://www.lazilong.com/apple_ii/bye.sys/bye.html 33 | 34 | ## ProDOS 2.4 - Bitsy Bye 35 | 36 | The new (unofficial) releases of [ProDOS 2.4](http://www.callapple.org/uncategorized/announcing-prodos-2-4-for-all-apple-ii-computers/) by John Brooks include a replacement quit routine called Bitsy Bye, a collaboration with Peter Ferrie. This new quit routine is far more powerful, allowing access to BASIC and binary files (and more), drive selection, type-down, more entries, and so on. It uses only 40 columns, and does not require a 65C02 processor. 37 | 38 | ℹ️ If you want to use this selector, use a version of ProDOS 2.4 from https://prodos8.com/ 39 | 40 | ## Buh-Bye - Enhanced 80-column selector 41 | 42 | Since I prefered the look of the ProDOS 80-column selector to Bitsy Bye, but missed the type-down ability, I modified the 80-column selector to tighten up the code added seeking if an alphabetical key is typed. Hit 'C' and the list will scroll to the next file starting with 'C'. 43 | 44 | I erroneously thought that the ProDOS 80-column selector was _Bird's Better Bye_ and named this "Bell's Better Bird's Better Bye" or "Buh-Bye". 45 | 46 | ℹ️ If you want to use this selector with any version of ProDOS, add the `BUHBYE.SYSTEM` file to your boot sequence. You can follow it with `QUIT.SYSTEM` in your driver sequence to show the selector on startup. 47 | -------------------------------------------------------------------------------- /clocks/cricket/set.datetime.s: -------------------------------------------------------------------------------- 1 | ;;; SET.DATETIME utility for The Cricket! 2 | ;;; Prompts for date and time and updates Cricket. 3 | 4 | .setcpu "6502" 5 | .linecont + 6 | .feature string_escapes 7 | 8 | .include "apple2.inc" 9 | .include "apple2.mac" 10 | 11 | .include "../../inc/apple2.inc" 12 | .include "../../inc/macros.inc" 13 | .include "../../inc/ascii.inc" 14 | 15 | .org $2000 16 | 17 | .proc main 18 | ;; -------------------------------------------------- 19 | ;; Date 20 | 21 | jsr zstrout 22 | scrcode "\rDate: WWW MM/DD/YY\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" 23 | .byte 0 24 | 25 | jsr GETLN2 26 | 27 | php 28 | sei 29 | 30 | ;; Reset SSC 31 | sta KBDSTRB ; Port 2 DSR line connected to KBDSTRB 32 | lda #0 33 | sta COMMAND 34 | sta CONTROL 35 | 36 | ;; Configure SSC 37 | lda #%00001011 ; no parity/echo/interrupts, RTS low, DTR low 38 | sta COMMAND 39 | lda #%10011110 ; 9600 baud, 8 data bits, 2 stop bits 40 | sta CONTROL 41 | 42 | ;; Clock Commands 43 | ;; Set Date "SD WWW MM/DD/YY" 44 | lda #HI('S') 45 | jsr sendbyte 46 | lda #HI('D') 47 | jsr sendbyte 48 | lda #HI(' ') 49 | jsr sendbyte 50 | 51 | ldx #0 52 | : lda INPUT_BUFFER,x 53 | jsr sendbyte 54 | inx 55 | cmp #HI(ASCII_CR) 56 | bne :- 57 | 58 | plp 59 | 60 | ;; -------------------------------------------------- 61 | ;; Time 62 | 63 | jsr zstrout 64 | scrcode "\rTime: HH:MM:SS\x08\x08\x08\x08\x08\x08\x08\x08" 65 | .byte 0 66 | 67 | jsr GETLN2 68 | 69 | php 70 | sei 71 | 72 | ;; Reset SSC 73 | sta KBDSTRB ; Port 2 DSR line connected to KBDSTRB 74 | lda #0 75 | sta COMMAND 76 | sta CONTROL 77 | 78 | ;; Configure SSC 79 | lda #%00001011 ; no parity/echo/interrupts, RTS low, DTR low 80 | sta COMMAND 81 | lda #%10011110 ; 9600 baud, 8 data bits, 2 stop bits 82 | sta CONTROL 83 | 84 | ;; Clock Commands 85 | ;; Set Time "ST HH:MM:SS" 86 | lda #HI('S') 87 | jsr sendbyte 88 | lda #HI('T') 89 | jsr sendbyte 90 | lda #HI(' ') 91 | jsr sendbyte 92 | 93 | ldx #0 94 | : lda INPUT_BUFFER,x 95 | jsr sendbyte 96 | inx 97 | cmp #HI(ASCII_CR) 98 | bne :- 99 | 100 | plp 101 | 102 | rts 103 | .endproc 104 | 105 | ;; Write byte in A to SSC 106 | .proc sendbyte 107 | pha 108 | : lda STATUS 109 | and #(1 << 4) ; transmit register empty? (bit 4) 110 | beq :- ; nope, keep waiting 111 | pla 112 | sta TDREG 113 | rts 114 | .endproc 115 | 116 | 117 | ;;; ------------------------------------------------------------ 118 | ;;; Output a high-ascii, null-terminated string. 119 | ;;; String immediately follows the JSR. 120 | 121 | .proc zstrout 122 | ptr := $A5 123 | 124 | pla ; read address from stack 125 | sta ptr 126 | pla 127 | sta ptr+1 128 | bne skip ; always (since data not on ZP) 129 | 130 | next: jsr COUT 131 | skip: inc ptr 132 | bne :+ 133 | inc ptr+1 134 | : ldy #0 135 | lda (ptr),y 136 | bne next 137 | 138 | lda ptr+1 ; restore address to stack 139 | pha 140 | lda ptr 141 | pha 142 | rts 143 | .endproc 144 | 145 | -------------------------------------------------------------------------------- /inc/macros.inc: -------------------------------------------------------------------------------- 1 | ;;; ============================================================ 2 | ;;; Generic Macros 3 | ;;; ============================================================ 4 | 5 | .define _is_immediate(arg) (.match (.mid (0, 1, {arg}), #)) 6 | .define _is_register(arg) (.match ({arg}, x) .or .match ({arg}, y)) 7 | .define _is_y_register(arg) (.match ({arg}, y)) 8 | .define _immediate_value(arg) (.right (.tcount ({arg})-1, {arg})) 9 | 10 | .macro _op_lo op, arg 11 | .if _is_immediate {arg} 12 | op #<_immediate_value {arg} 13 | .else 14 | op arg 15 | .endif 16 | .endmacro 17 | 18 | .macro _op_hi op, arg 19 | .if _is_immediate {arg} 20 | op #>_immediate_value {arg} 21 | .else 22 | op arg+1 23 | .endif 24 | .endmacro 25 | 26 | ;;; ============================================================ 27 | ;;; Temporary org change, for relocated routines 28 | 29 | __pushorg_depth__ .set 0 30 | 31 | .macro pushorg addr 32 | ::__pushorg_depth__ .set ::__pushorg_depth__ + 1 33 | .ident(.sprintf("__pushorg_saved__%d", ::__pushorg_depth__)) := * 34 | .org addr 35 | .ident(.sprintf("__pushorg_start__%d", ::__pushorg_depth__)) := * 36 | .endmacro 37 | 38 | .macro poporg 39 | .org .ident(.sprintf("__pushorg_saved__%d", ::__pushorg_depth__)) + (* - .ident(.sprintf("__pushorg_start__%d", ::__pushorg_depth__))) 40 | ::__pushorg_depth__ .set ::__pushorg_depth__ - 1 41 | .endmacro 42 | 43 | ;;; ============================================================ 44 | ;;; Length-prefixed string 45 | ;;; 46 | ;;; Can include control chars by using: 47 | ;;; 48 | ;;; PASCAL_STRING {"abc",$0D,"def"} 49 | 50 | .macro PASCAL_STRING str,res 51 | .local data 52 | .local end 53 | .byte end - data 54 | data: .byte str 55 | end: 56 | .if .paramcount > 1 57 | .res res - (end - data), 0 58 | .endif 59 | .endmacro 60 | 61 | 62 | ;;; ============================================================ 63 | ;;; Common patterns 64 | 65 | .macro copy arg1, arg2, arg3, arg4 66 | .if _is_register {arg2} && _is_register {arg4} 67 | ;; indexed load/indexed store 68 | lda arg1,arg2 69 | sta arg3,arg4 70 | .elseif _is_register {arg2} 71 | ;; indexed load variant (arg2 is x or y) 72 | lda arg1,arg2 73 | sta arg3 74 | .elseif _is_register {arg3} 75 | ;; indexed store variant (arg3 is x or y) 76 | lda arg1 77 | sta arg2,arg3 78 | .else 79 | lda arg1 80 | sta arg2 81 | .endif 82 | .endmacro 83 | 84 | 85 | 86 | ;;; Copy 16-bit value 87 | ;;; copy16 #$1111, $2222 ; immediate, absolute 88 | ;;; copy16 $1111, $2222 ; absolute, absolute 89 | ;;; copy16 $1111,x, $2222 ; indirect load, absolute store 90 | ;;; copy16 $1111, $2222,x ; absolute load, indirect store 91 | ;;; copy16 $1111,x $2222,x ; indirect load, indirect store 92 | ;;; copy16 #$1111, $2222,x ; immediate load, indirect store 93 | .macro copy16 arg1, arg2, arg3, arg4 94 | .if _is_register {arg2} && _is_register {arg4} 95 | ;; indexed load/indexed store 96 | lda arg1,arg2 97 | sta arg3,arg4 98 | lda arg1+1,arg2 99 | sta arg3+1,arg4 100 | .elseif _is_register {arg2} 101 | ;; indexed load variant (arg2 is x or y) 102 | lda arg1,arg2 103 | sta arg3 104 | lda arg1+1,arg2 105 | sta arg3+1 106 | .elseif _is_register {arg3} 107 | ;; indexed store variant (arg3 is x or y) 108 | _op_lo lda, {arg1} 109 | sta arg2,arg3 110 | _op_hi lda, {arg1} 111 | sta arg2+1,arg3 112 | .else 113 | _op_lo lda, {arg1} 114 | sta arg2 115 | _op_hi lda, {arg1} 116 | sta arg2+1 117 | .endif 118 | .endmacro 119 | 120 | ;;; ============================================================ 121 | 122 | ;;; Set the high bit on the passed byte 123 | .define HI(c) ((c)|$80) 124 | -------------------------------------------------------------------------------- /clocks/cricket/prodos.mod.s: -------------------------------------------------------------------------------- 1 | ;;; The Cricket Clock - ProDOS Patcher 2 | ;;; Disassembled from /CRICKET/PRODOS.MOD 3 | ;;; Original: Street Electronics Corporation (C) 1984 4 | 5 | .setcpu "6502" 6 | .include "apple2.inc" 7 | .include "opcodes.inc" 8 | 9 | .include "../../inc/apple2.inc" 10 | .include "../../inc/prodos.inc" 11 | 12 | .org $300 13 | 14 | .proc install 15 | ptr := $42 16 | 17 | ;; Copy driver to target in ProDOS 18 | lda DATETIME+1 19 | sta ptr 20 | lda DATETIME+2 21 | sta ptr+1 22 | lda #OPC_JMP_abs ; JMP opcode 23 | sta DATETIME 24 | lda ROMIN ; Write bank 2 25 | lda ROMIN 26 | ldy #sizeof_driver-1 27 | loop: lda driver,y 28 | sta (ptr),y 29 | dey 30 | bpl loop 31 | 32 | ;; Simple exit when BRUN 33 | rts 34 | .endproc 35 | 36 | ;; Driver - relocatable code. Called by ProDOS to update date/time bytes 37 | .proc driver 38 | scratch := $3A ; ZP scratch location 39 | 40 | ;; Initialize 41 | php 42 | sei 43 | lda COMMAND ; save status of command register 44 | pha 45 | 46 | ;; Configure SSC 47 | lda #%00001011 ; no parity/echo/interrupts, RTS low, DTR low 48 | sta COMMAND 49 | lda #%10011110 ; 9600 baud, 8 data bits, 2 stop bits 50 | sta CONTROL 51 | 52 | ;; Send command 53 | : lda STATUS 54 | and #(1 << 4) ; transmit register empty? (bit 4) 55 | beq :- ; nope, keep waiting 56 | lda #('@' | $80) ; '@' command 57 | sta TDREG 58 | 59 | read_len := 7 ; read 7 bytes (w/m/d/y/H/M/S) 60 | 61 | ;; Read response, pushing to stack 62 | ldy #(read_len-1) 63 | 64 | rloop: ldx #0 ; x = retry loop counter low byte 65 | lda #3 ; scratch = retry loop counter high byte 66 | sta scratch ; ($300 iterations total) 67 | 68 | check: lda STATUS ; did we get it? 69 | and #(1 << 3) ; receive register full? (bit 3) 70 | bne ready ; yes, we read the value 71 | 72 | inx ; not yet, so keep trying 73 | bne check ; until counter runs out 74 | dec scratch 75 | bne check 76 | 77 | ;; Read failed - restore stack and exit 78 | reset: cpy #(read_len-1) ; anything left to restore? 79 | beq done ; nope, exit 80 | pla ; yep, clear it off the stack 81 | iny 82 | bne reset 83 | 84 | ;; Read succeeded - stuff it on the stack and continue 85 | ready: lda RDREG 86 | pha 87 | dey 88 | bpl rloop 89 | 90 | ;; Convert pushed response to ProDOS time field 91 | pla ; day of week (unused) 92 | 93 | pla ; minute 94 | sta TIMELO ; -- stored as-is (TIMELO 5-0) 95 | 96 | pla ; hour 97 | sta TIMELO+1 ; -- stored as-is (TIMELO 12-8) 98 | 99 | pla ; year 100 | sta DATELO+1 ; -- will be shifted up by 1 (DATELO 15-9) 101 | 102 | pla ; day 103 | and #%00011111 ; -- masked, stored as is (DATELO 4-0) 104 | sta DATELO 105 | 106 | pla ; month 107 | asl a ; -- shifted up (DATELO 8-5) 108 | asl a 109 | asl a 110 | asl a 111 | asl a 112 | ora DATELO ; -- merge low 5 bits 113 | sta DATELO 114 | rol DATELO+1 115 | 116 | pla ; seconds (unused) 117 | 118 | ;; Restore prior state 119 | done: pla ; restore saved command state 120 | sta COMMAND 121 | plp 122 | rts 123 | .endproc 124 | sizeof_driver := .sizeof(driver) 125 | -------------------------------------------------------------------------------- /clocks/jumbo/clock.system.s: -------------------------------------------------------------------------------- 1 | ;;; "Jumbo" Clock Driver 2 | ;;; 3 | ;;; Pulls in several clock drivers sources and tries each one in sequence. 4 | ;;; 5 | 6 | JUMBO_CLOCK_DRIVER = 1 7 | 8 | .setcpu "6502" 9 | .linecont + 10 | .feature string_escapes 11 | 12 | .include "apple2.inc" 13 | .include "apple2.mac" 14 | .include "opcodes.inc" 15 | 16 | .include "../../inc/apple2.inc" 17 | .include "../../inc/macros.inc" 18 | .include "../../inc/prodos.inc" 19 | .include "../../inc/ascii.inc" 20 | 21 | ;;; ************************************************************ 22 | .include "../../inc/driver_preamble.inc" 23 | ;;; ************************************************************ 24 | 25 | .scope ns_clock 26 | .include "../ns.clock/ns.clock.system.s" 27 | .endscope 28 | .scope romx 29 | .include "../romx/romxrtc.system.s" 30 | .endscope 31 | .scope dclock 32 | .include "../dclock/dclock.system.s" 33 | .endscope 34 | .scope fujinet 35 | .include "../fujinet/fn.clock.system.s" 36 | .endscope 37 | .scope cricket 38 | .include "../cricket/cricket.system.s" 39 | .endscope 40 | 41 | ;;; ============================================================ 42 | ;;; 43 | ;;; Driver Installer 44 | ;;; 45 | ;;; ============================================================ 46 | 47 | .undef PRODUCT 48 | .define PRODUCT "Jumbo Clock Driver" 49 | 50 | .proc maybe_install_driver 51 | lda MACHID 52 | and #$01 ; existing clock card? 53 | bne check_thunderclock 54 | 55 | jsr ns_clock::maybe_install_driver 56 | bcc ret 57 | 58 | jsr romx::maybe_install_driver 59 | bcc ret 60 | 61 | jsr dclock::maybe_install_driver 62 | bcc ret 63 | 64 | jsr fujinet::maybe_install_driver 65 | bcc ret 66 | 67 | jsr cricket::maybe_install_driver 68 | bcc ret 69 | 70 | ret: rts 71 | .endproc 72 | 73 | .proc check_thunderclock 74 | ;; Look for Thunderclock year table 75 | bit RWRAM1 76 | bit RWRAM1 77 | 78 | lda #table_1982 80 | jsr check_sig 81 | beq update_table 82 | 83 | lda #table_1986 85 | jsr check_sig 86 | beq update_table 87 | 88 | lda #table_1993 90 | jsr check_sig 91 | beq update_table 92 | 93 | lda #table_2018 95 | jsr check_sig 96 | beq update_table 97 | 98 | ;; Table not found - we have a clock but don't 99 | ;; know what it is, so don't log anything. 100 | bit ROMIN2 101 | rts 102 | 103 | ;; ---------------------------------------- 104 | 105 | ;; Copy the latest table into place 106 | update_table: 107 | ldx #SIG_LEN-1 108 | : lda table_2023,x 109 | sta SIG_ADDR,x 110 | dex 111 | bpl :- 112 | 113 | bit ROMIN2 114 | .if ::LOG_SUCCESS 115 | ;; Display success message, to confirm table updates. 116 | jsr log_message 117 | scrcode "ThunderClock - " 118 | .byte 0 119 | 120 | ;; Display the current date 121 | jsr cout_date 122 | .endif ; ::LOG_SUCCESS 123 | rts 124 | 125 | ;; ---------------------------------------- 126 | 127 | check_sig: 128 | ptr := $06 129 | sta ptr 130 | stx ptr+1 131 | ldy #SIG_LEN-1 132 | : lda (ptr),y 133 | cmp SIG_ADDR,y 134 | bne :+ ; Z=0 for no match 135 | dey 136 | bpl :- 137 | iny ; Z=1 for match 138 | : rts 139 | 140 | SIG_LEN = 7 141 | SIG_ADDR := $D7B8 142 | 143 | table_1982: ; ProDOS 1.1.1 144 | .byte $54, $54, $53, $52, $57, $56, $55 145 | 146 | table_1986: ; ProDOS 1.3 - 1.9 147 | .byte $5A, $59, $58, $58, $57, $56, $5B 148 | 149 | table_1993: ; ProDOS 2.0.3 150 | .byte $60, $5F, $5E, $5D, $62, $61, $60 151 | 152 | table_2018: ; ProDOS 2.4.2 153 | .byte $12, $17, $16, $15, $14, $14, $13 154 | 155 | table_2023: 156 | .byte $18, $17, $1C, $1B, $1A, $19, $18 157 | .endproc 158 | 159 | ;;; ************************************************************ 160 | .include "../../inc/driver_postamble.inc" 161 | ;;; ************************************************************ 162 | -------------------------------------------------------------------------------- /util/noclock.system.s: -------------------------------------------------------------------------------- 1 | .setcpu "6502" 2 | .linecont + 3 | .feature string_escapes 4 | 5 | .include "apple2.inc" 6 | .include "apple2.mac" 7 | .include "opcodes.inc" 8 | 9 | .include "../inc/apple2.inc" 10 | .include "../inc/macros.inc" 11 | .include "../inc/prodos.inc" 12 | 13 | ;;; ************************************************************ 14 | .include "../inc/driver_preamble.inc" 15 | ;;; ************************************************************ 16 | 17 | ;;; ============================================================ 18 | ;;; Ensure there is not a previous clock driver installed. 19 | 20 | .proc maybe_install_driver 21 | lda MACHID 22 | and #$01 ; existing clock card? 23 | beq prompt ; no, prompt for date/time 24 | 25 | rts ; yes, done! 26 | .endproc 27 | 28 | .proc prompt 29 | 30 | date: 31 | jsr log_message 32 | scrcode "Date: MM/DD/YY\x08\x08\x08\x08\x08\x08\x08\x08" 33 | ;; Offsets: .....01234567 34 | .byte 0 35 | 36 | jsr GETLN2 37 | 38 | lda INPUT_BUFFER+1 39 | jsr shift_into_tmp 40 | lda INPUT_BUFFER+0 41 | jsr shift_into_tmp 42 | jsr bcd_to_binary 43 | beq date 44 | cmp #13 45 | bcs date 46 | sta set_month 47 | 48 | lda INPUT_BUFFER+4 49 | jsr shift_into_tmp 50 | lda INPUT_BUFFER+3 51 | jsr shift_into_tmp 52 | jsr bcd_to_binary 53 | beq date 54 | cmp #32 55 | bcs date 56 | sta set_day 57 | 58 | lda INPUT_BUFFER+7 59 | jsr shift_into_tmp 60 | lda INPUT_BUFFER+6 61 | jsr shift_into_tmp 62 | jsr bcd_to_binary 63 | sta set_year 64 | 65 | ;; -------------------------------------------------- 66 | ;; Prompt for Time 67 | 68 | time: 69 | jsr log_message 70 | scrcode "Time: HH:MM\x08\x08\x08\x08\x08" 71 | ;; Offsets: .....01234567 72 | .byte 0 73 | 74 | jsr GETLN2 75 | 76 | lda INPUT_BUFFER+1 77 | jsr shift_into_tmp 78 | lda INPUT_BUFFER+0 79 | jsr shift_into_tmp 80 | jsr bcd_to_binary 81 | cmp #24 82 | bcs time 83 | sta set_hours 84 | 85 | lda INPUT_BUFFER+4 86 | jsr shift_into_tmp 87 | lda INPUT_BUFFER+3 88 | jsr shift_into_tmp 89 | jsr bcd_to_binary 90 | cmp #60 91 | bcs time 92 | sta set_minutes 93 | 94 | ;; -------------------------------------------------- 95 | ;; Set date/time 96 | 97 | ;; | DATEHI | | DATELO | 98 | ;; 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 99 | ;; +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ 100 | ;; | Year | Month | Day | 101 | ;; +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ 102 | 103 | 104 | lda set_month 105 | asl 106 | asl 107 | asl 108 | asl 109 | asl 110 | ora set_day 111 | sta DATELO 112 | lda set_year 113 | rol 114 | sta DATEHI 115 | 116 | lda set_minutes 117 | sta TIMELO 118 | lda set_hours 119 | sta TIMEHI 120 | 121 | ;;; -------------------------------------------------- 122 | 123 | bcd_to_binary: 124 | ldy #$FF ; result = -1 125 | sec 126 | sed 127 | : iny ; result += 1 128 | sbc #1 ; value -= 1 129 | bcs :- 130 | cld 131 | tya ; A = result 132 | rts 133 | 134 | ;;; -------------------------------------------------- 135 | 136 | shift_into_tmp: 137 | and #$0F 138 | ror 139 | ror tmp 140 | ror 141 | ror tmp 142 | ror 143 | ror tmp 144 | ror 145 | ror tmp 146 | 147 | lda tmp 148 | rts 149 | 150 | tmp: .byte 0 151 | .endproc 152 | 153 | ;;; ------------------------------------------------------------ 154 | 155 | set_year: .byte 0 156 | set_month: .byte 0 157 | set_day: .byte 0 158 | set_hours: .byte 0 159 | set_minutes: .byte 0 160 | set_seconds: .byte 0 161 | 162 | ;;; ************************************************************ 163 | .include "../inc/driver_postamble.inc" 164 | ;;; ************************************************************ 165 | -------------------------------------------------------------------------------- /clocks/cricket/test.s: -------------------------------------------------------------------------------- 1 | ;;; Test program for The Cricket! 2 | ;;; * Probes Slot 2 for Super Serial Card (or compatible) 3 | ;;; * Initializes SSC 4 | ;;; * Sends Cricket ID sequence 5 | 6 | .setcpu "6502" 7 | .linecont + 8 | .feature string_escapes 9 | 10 | .include "apple2.inc" 11 | .include "apple2.mac" 12 | .include "opcodes.inc" 13 | 14 | .include "../../inc/apple2.inc" 15 | .include "../../inc/macros.inc" 16 | .include "../../inc/ascii.inc" 17 | 18 | .org $2000 19 | 20 | read_delay_hi = $3 * 3 ; ($300 iterations is normal * 3.6MHz) 21 | 22 | .proc detect_cricket 23 | ;; Check Slot 2 for SSC. ID bytes per: 24 | ;; Apple II Technical Note #8: Pascal 1.1 Firmware Protocol ID Bytes 25 | lda $C205 26 | cmp #$38 27 | bne ssc_not_found 28 | lda $C207 29 | cmp #$18 30 | bne ssc_not_found 31 | lda $C20B 32 | cmp #$01 33 | bne ssc_not_found 34 | lda $C20C 35 | cmp #$31 36 | bne ssc_not_found 37 | 38 | jsr zstrout 39 | scrcode "SSC found.\r" 40 | .byte 0 41 | 42 | jmp init_ssc 43 | 44 | ssc_not_found: 45 | jsr zstrout 46 | scrcode "SSC not found.\r" 47 | .byte 0 48 | 49 | rts 50 | 51 | ;; TODO: Write NUL and check for 'C' ... version ... $8D (CR) 52 | ;; https://github.com/a2stuff/cricket/issues/3 53 | init_ssc: 54 | lda COMMAND ; save status of SSC registers 55 | sta saved_command 56 | lda CONTROL 57 | sta saved_control 58 | 59 | ;; Configure SSC 60 | lda #%00001011 ; no parity/echo/interrupts, RTS low, DTR low 61 | sta COMMAND 62 | lda #%10011110 ; 9600 baud, 8 data bits, 2 stop bits 63 | sta CONTROL 64 | 65 | ;; Miscellaneous Commands 66 | ;; Read Cricket ID code: 00 ($00) 67 | lda #0 68 | jsr sendbyte 69 | 70 | ;; "The Cricket will return a "C" (195, $C3) followed 71 | ;; by a version number (in ASCII) and a carriage return (141, 72 | ;; $8D)." 73 | jsr zstrout 74 | scrcode "Reading SSC: " 75 | .byte 0 76 | 77 | jsr readbyte 78 | bcs cricket_not_found ; timeout 79 | cmp #HI('C') ; = 'C' ? 80 | bne cricket_not_found 81 | 82 | jsr readbyte 83 | bcs cricket_not_found ; timeout 84 | bcc digit 85 | 86 | : jsr readbyte 87 | bcs cricket_not_found ; timeout 88 | cmp #HI(ASCII_CR) 89 | beq cricket_found 90 | digit: cmp #HI('0') ; < '0' ? 91 | bcc cricket_not_found 92 | cmp #HI('9' + 1) ; > '9' ? 93 | bcs cricket_not_found 94 | bcc :- 95 | 96 | jmp cricket_found 97 | 98 | cricket_found: 99 | jsr zstrout 100 | scrcode "\rCricket tentatively found.\r" 101 | .byte 0 102 | jmp exit 103 | 104 | cricket_not_found: 105 | jsr zstrout 106 | scrcode "\rCricket not identified.\r" 107 | .byte 0 108 | jmp exit 109 | 110 | exit: 111 | lda saved_control 112 | sta CONTROL 113 | lda saved_command 114 | sta COMMAND 115 | 116 | rts 117 | 118 | saved_command: .byte 0 119 | saved_control: .byte 0 120 | 121 | 122 | .endproc 123 | 124 | ;; Write byte in A 125 | .proc sendbyte 126 | pha 127 | : lda STATUS 128 | and #(1 << 4) ; transmit register empty? (bit 4) 129 | beq :- ; nope, keep waiting 130 | pla 131 | sta TDREG 132 | rts 133 | .endproc 134 | 135 | 136 | ;; Read byte into A, or carry set if timed out 137 | .proc readbyte 138 | tries := $100 * read_delay_hi 139 | counter := $A5 140 | 141 | lda #tries 144 | sta counter+1 145 | 146 | check: lda STATUS ; did we get it? 147 | and #(1 << 3) ; receive register full? (bit 3) 148 | bne ready ; yes, we read the value 149 | 150 | dec counter 151 | bne check 152 | dec counter+1 153 | bne check 154 | 155 | jsr zstrout 156 | scrcode "... timeout!" 157 | .byte 0 158 | 159 | sec ; failed 160 | rts 161 | 162 | ready: lda RDREG ; actually read the register 163 | pha 164 | jsr COUT 165 | pla 166 | clc 167 | rts 168 | .endproc 169 | 170 | 171 | 172 | ;;; ------------------------------------------------------------ 173 | ;;; Output a high-ascii, null-terminated string. 174 | ;;; String immediately follows the JSR. 175 | 176 | .proc zstrout 177 | ptr := $A5 178 | 179 | pla ; read address from stack 180 | sta ptr 181 | pla 182 | sta ptr+1 183 | bne skip ; always (since data not on ZP) 184 | 185 | next: jsr COUT 186 | skip: inc ptr 187 | bne :+ 188 | inc ptr+1 189 | : ldy #0 190 | lda (ptr),y 191 | bne next 192 | 193 | lda ptr+1 ; restore address to stack 194 | pha 195 | lda ptr 196 | pha 197 | rts 198 | .endproc 199 | 200 | ;;; ------------------------------------------------------------ 201 | -------------------------------------------------------------------------------- /accelerators/zipchip/zipchip.system.s: -------------------------------------------------------------------------------- 1 | ;;; ZIPCHIP.SYSTEM 2 | ;;; Configures the speaker to be temporarily slow, slots 1-4 fast 3 | ;;; TODO: Add a configuration utility 4 | 5 | .setcpu "6502" 6 | .linecont + 7 | .feature string_escapes 8 | 9 | .include "apple2.inc" 10 | .include "apple2.mac" 11 | .include "opcodes.inc" 12 | 13 | .include "../../inc/apple2.inc" 14 | .include "../../inc/macros.inc" 15 | .include "../../inc/prodos.inc" 16 | .include "../../inc/ascii.inc" 17 | 18 | ;;; ************************************************************ 19 | .include "../../inc/driver_preamble.inc" 20 | ;;; ************************************************************ 21 | 22 | ;; From ZIP Chip Manual v1 1987 23 | ZC_REG_LOCK := $C05A 24 | ;; Write: 25 | ;; $A5 Locks the ZIP CHIP. 26 | ;; 4 consecutive $5A writes unlock ZIP CHIP. 27 | ;; While unlocked, any write other than $A5 or 28 | ;; $5A will initiate an indefinate syncronous [sic] 29 | ;; sequence. 30 | kZCLock = $A5 31 | kZCUnlock = $5A 32 | 33 | ZC_REG_ENABLE := $C05B 34 | ;; Write - Any hex byte written will enable ZIP CHIP 35 | 36 | ZC_REG_STATUS := $C05B 37 | ;; Read - Read the current status of the following: 38 | ;; bit 0 & 1 - Ramsize where 39 | ;; RAMSIZE1 RAMSIZE0 SIZE 40 | ;; 0 0 8K 41 | ;; 0 1 16K 42 | ;; 1 0 32K 43 | ;; 1 1 64K 44 | ;; bit 2 - unused 45 | ;; bit 3 - Delay (for memory) 46 | ;; 0 = Fast Mode - Delay not in effect 47 | ;; 1 = Sync Mode - Delay in effect 48 | ;; bit 4 - Disabled/enabled 49 | ;; 0 = Chip Enabled 50 | ;; 1 = Chip Disabled 51 | ;; bit 5 - Paddle fast/normal 52 | ;; 0 = Fast Mode 53 | ;; 1 = Synchronous Mode (Normal) 54 | ;; bit 6 = Cache Updated by data read 55 | ;; 0 = No update 56 | ;; 1 = Yes cache updated 57 | ;; bit 7 = Clock Pulse - 1.0035 milliseconds 58 | ;; Edges occur at .50175 milliseconds 59 | 60 | ZC_REG_SLOTSPKR := $C05C 61 | ;; Read/Write - Slow/Speaker set and read 62 | ;; 0 = Set slot/speaker Fast 63 | ;; 1 = Set slot/speaker Normal 64 | ;; bit 0 - Speaker bit 4 - Slot 4 65 | ;; bit 1 - Slot 1 bit 5 - Slot 5 66 | ;; bit 2 - Slot 2 bit 6 - Slot 6 67 | ;; bit 3 - Slot 3 bit 7 - Slot 7 68 | 69 | ZC_REG_SYSSPEED := $C05D 70 | ;; Write - Set System Speed 71 | ;; bit 0 - unused bit 4 - Clk4/5 72 | ;; bit 1 - unused bit 5 - Clk5/6 73 | ;; bit 2 - Clk2/3 bit 6 - Clk/2 74 | ;; bit 3 - Clk3/4 bit 7 - Clk/4 75 | ;; NOTE: bit 6 and bit 7 yield Clk/3 76 | 77 | ZC_REG_SYNCOP := $C05E 78 | ;; Write - Enable/Disable Synchronous Operation 79 | ;; for I/O Devices 80 | ;; bit 0 through bit 6 - Not Used 81 | ;; bit 7 - Enable/Disable Delay 82 | ;; 0 = Enable Delay 83 | ;; 1 = Disable and Reset Delay 84 | 85 | ZC_REG_SOFTSW := $C05E 86 | ;; Read - Read Apple softswitches 87 | ;; 0 = False 88 | ;; 1 = True 89 | ;; bit 0 - ROMRD bit 4 - 80STORE 90 | ;; bit 1 - RAMBNK bit 5 - MWR 91 | ;; bit 2 - PAGE2 bit 6 - MRD 92 | ;; bit 3 - HIRES bit 7 - ALTZP 93 | 94 | ZC_REG_PDLBSLC := $C05F 95 | ;; Write - Paddle Speed, Bank Switch Language Card 96 | ;; bit 0 through bit 5 - Not Used 97 | ;; bit 6 - Paddle Set 98 | ;; 0 = Disable Paddle Delay 99 | ;; 1 = Enable Paddle Delay 100 | ;; bit 7 - Language Card Enable/Disable 101 | ;; 0 = Enable Cache of Language Card Memory 102 | ;; 1 = Disable Cache of Language Card Memory 103 | 104 | 105 | .undef PRODUCT 106 | .define PRODUCT "ZIP CHIP" 107 | 108 | .proc maybe_install_driver 109 | php ; timing sensitive 110 | sei 111 | 112 | ;; Unlock 113 | lda #kZCUnlock 114 | sta ZC_REG_LOCK 115 | sta ZC_REG_LOCK 116 | sta ZC_REG_LOCK 117 | sta ZC_REG_LOCK 118 | 119 | ;; ZIP CHIP present? 120 | lda ZC_REG_SLOTSPKR 121 | eor #$FF 122 | sta ZC_REG_SLOTSPKR 123 | cmp ZC_REG_SLOTSPKR 124 | bne no_zip 125 | eor #$FF 126 | sta ZC_REG_SLOTSPKR 127 | cmp ZC_REG_SLOTSPKR 128 | bne no_zip 129 | 130 | ;; Slow on speaker access, slots 1-4 fast, 5-7 normal 131 | lda #%11100001 ; bit 0 = Speaker, bit N = slot N 132 | sta ZC_REG_SLOTSPKR 133 | 134 | ;; Get size 135 | lda ZC_REG_STATUS 136 | and #%00000011 137 | asl 138 | tax 139 | lda size_table,x 140 | sta size 141 | lda size_table+1,x 142 | sta size+1 143 | 144 | ;; Lock 145 | lda #kZCLock 146 | sta ZC_REG_LOCK 147 | 148 | jsr log_message 149 | scrcode PRODUCT, " " 150 | size: .res 2 ; patched with cache size 151 | scrcode "K - Configured." 152 | .byte 0 153 | 154 | plp 155 | rts 156 | 157 | no_zip: 158 | jsr log_message 159 | scrcode PRODUCT, " - Not Found." 160 | .byte 0 161 | 162 | plp 163 | rts 164 | 165 | size_table: 166 | scrcode " 8" 167 | scrcode "16" 168 | scrcode "32" 169 | scrcode "64" 170 | 171 | 172 | 173 | .endproc 174 | 175 | 176 | ;;; ************************************************************ 177 | .include "../../inc/driver_postamble.inc" 178 | ;;; ************************************************************ 179 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ProDOS Drivers 2 | 3 | [![build](https://github.com/a2stuff/prodos-drivers/actions/workflows/main.yml/badge.svg)](https://github.com/a2stuff/prodos-drivers/actions/workflows/main.yml) 4 | 5 | Build with [ca65](https://cc65.github.io/doc/ca65.html) 6 | 7 | # What are ProDOS "drivers"? 8 | 9 | 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: 10 | 11 | * Real-time Clock drivers (e.g. No-Slot Clock, The Cricket!, AE DClock, etc) 12 | * In ProDOS 1.x, 2.0 and 2.4 the Thunderclock driver is built-in. 13 | * RAM Disk drivers (e.g. RamWorks) 14 | * In ProDOS 1.x, 2.0 and 2.4 only a 64K driver for /RAM is built-in. 15 | * Quit dispatcher/selector (`BYE` routines) 16 | * In ProDOS 1.0 and later, a 40-column friendly [selector](selector) prompts for a prefix then a path `ENTER PREFIX (PRESS "RETURN" TO ACCEPT)` 17 | * In ProDOS 1.9 and 2.0.x, on 80-column systems, a menu-driven selector is installed instead. 18 | * In ProDOS 2.4.x [Bitsy Bye](https://prodos8.com/bitsy-bye/) is built-in. 19 | 20 | Early versions of these drivers would often invoke a specific file on completion, sometimes user-configurable. The best versions of these drivers simply execute the following `.SYSTEM` file, although this is non-trivial code and often did not work with network drives. 21 | 22 | This repository collects several drivers and uses common code to chain to the next `.SYSTEM` file, supporting network drives. 23 | 24 | ## What is present here? 25 | 26 | This repo includes the following drivers/modifications: 27 | 28 | * Real-time Clock drivers 29 | * No-Slot Clock 30 | * The Cricket! 31 | * Applied Engineering DClock 32 | * ROMX Real-Time Clock 33 | * FujiNet Clock 34 | * A "jumbo" driver that includes all of the above (just called `CLOCK.SYSTEM`) 35 | * Accelerators 36 | * ZIP CHIP configuration (slow on speaker access, make slots 1-4 fast) 37 | * RAM Disk drivers 38 | * RamWorks Driver by Glen E. Bredon 39 | * Quit dispatcher/selector (`BYE` routines) 40 | * 40-column Selector (from ProDOS) 41 | * 80-column menu-driven Selector (from ProDOS 1.9 and 2.x) 42 | * Bird's Better Bye (a 40-column menu-driven selector) 43 | * Buh-Bye (an enhanced version of the ProDOS 80-column, menu-driven selector) 44 | * Text color themes 45 | * These set the IIgs (or VidHD) text/background/border colors 46 | 47 | In addition, `QUIT.SYSTEM` is present which isn't a driver but which immediately invokes the QUIT handler (a.k.a. program selector). This will happen automatically if the last driver can't find another `.SYSTEM` file, but `QUIT.SYSTEM` can be used to stop the chain if you have other `.SYSTEM` files in your root directory. 48 | 49 | If you don't have a real-time clock, `NOCLOCK.SYSTEM` will prompt you for the date/time on boot and set the ProDOS date/time, which will be used to record file creation/modification times. 50 | 51 | There's also `PAUSE.SYSTEM` which just waits for a fraction of a second before invoking the next driver file in case the log messages from the other installers goes by too fast for your taste, and `HOME.SYSTEM` in case you want the log messages to start off with a blank screen. 52 | 53 | Non-drivers that are included: 54 | * 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. 55 | * Some utilities for The Cricket! clock are also included. 56 | 57 | ## How do you use these? 58 | 59 | 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: 60 | 61 | * `PRODOS` - the operating system, e.g. [ProDOS 2.4](https://prodos8.com/) 62 | * `HOME.SYSTEM` - start off with a blank screen 63 | * `NS.CLOCK.SYSTEM` - install No-Slot clock driver, if present 64 | * `ROMXRTC.SYSTEM` - install ROMX clock driver, if present 65 | * `FN.CLOCK.SYSTEM` - install FujiNet clock driver, if present 66 | * `DCLOCK.SYSTEM` - install DClock clock driver, if present 67 | * `CRICKET.SYSTEM` - install The Cricket! clock driver, if present 68 | * `ZIPCHIP.SYSTEM` - slow the ZIP CHIP on speaker access, if present 69 | * `RAM.DRV.SYSTEM` - install RamWorks RAM disk driver, if present 70 | * `BUHBYE.SYSTEM` - install a customized Quit handler to replace the built-in one 71 | * `PAUSE.SYSTEM` - pause for a moment, so that you can inspect the output of the above 72 | * `QUIT.SYSTEM` - invoke the Quit handler immediately, as a program selector 73 | * `BASIC.SYSTEM` - which will not be automatically invoked, but is available to manually invoke 74 | 75 | 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`. 76 | 77 | ## Alternate Approach 78 | 79 | If you want to keep your volume directory tidier, consider using [SETUP.SYSTEM](./setup/README.md) instead. 80 | 81 | # Building 82 | 83 | Fetch, build, and install [cc65](http://cc65.github.io/cc65/): 84 | 85 | ``` 86 | git clone https://github.com/cc65/cc65 87 | make -C cc65 && make -C cc65 avail 88 | ``` 89 | 90 | Fetch and build this repo: 91 | 92 | ``` 93 | git clone https://github.com/a2stuff/prodos-drivers 94 | cd prodos-drivers 95 | make 96 | ``` 97 | 98 | To make a disk image, fetch, build and install [Cadius](https://github.com/mach-kernel/cadius): 99 | 100 | ``` 101 | git clone https://github.com/mach-kernel/cadius 102 | make -C cadius && make -C cadius install 103 | ``` 104 | 105 | Then you can: 106 | 107 | ``` 108 | cd prodos-drivers 109 | make && make package 110 | ``` 111 | 112 | This will produce `prodos-drivers.po`, a disk image for use with emulators or tools like [ADTPro](http://adtpro.com/). 113 | 114 | Notes: 115 | * Specify `LOG_SUCCESS=0` and/or `LOG_FAILURE=0` (e.g. `make LOG_SUCCESS=0`) to build with driver success and/or error logging suppressed. 116 | -------------------------------------------------------------------------------- /clocks/fujinet/fn.clock.system.s: -------------------------------------------------------------------------------- 1 | ;;; ProDOS driver for the Fujinet clock 2 | ;;; Adapted from: https://github.com/a2stuff/prodos-drivers/blob/main/cricket/cricket.system.s 3 | 4 | .ifndef JUMBO_CLOCK_DRIVER 5 | .setcpu "6502" 6 | .linecont + 7 | .feature string_escapes 8 | 9 | .include "apple2.inc" 10 | .include "apple2.mac" 11 | .include "opcodes.inc" 12 | 13 | .include "../../inc/apple2.inc" 14 | .include "../../inc/macros.inc" 15 | .include "../../inc/prodos.inc" 16 | .include "../../inc/ascii.inc" 17 | .endif ; JUMBO_CLOCK_DRIVER 18 | 19 | ;;; ************************************************************ 20 | .ifndef JUMBO_CLOCK_DRIVER 21 | .include "../../inc/driver_preamble.inc" 22 | .endif ; JUMBO_CLOCK_DRIVER 23 | ;;; ************************************************************ 24 | 25 | .include "./smartport.inc" 26 | 27 | FN_CLOCK_DEVICE_TYPE := $13 ; As defined on the Fujinet firmware 28 | 29 | ;;; ============================================================ 30 | ;;; 31 | ;;; Driver Installer 32 | ;;; 33 | ;;; ============================================================ 34 | 35 | .undef PRODUCT 36 | .define PRODUCT "Fujinet Clock" 37 | 38 | ;;; ============================================================ 39 | ;;; Ensure there is not a previous clock driver installed. 40 | 41 | .proc maybe_install_driver 42 | 43 | lda MACHID 44 | and #$01 ; existing clock card? 45 | beq detect_fujinet_clock ; nope, check for clock 46 | 47 | rts ; yes, done! 48 | .endproc 49 | 50 | ;;; ============================================================ 51 | ;;; Fujinet Clock Driver - copied into ProDOS 52 | ;;; ============================================================ 53 | 54 | .proc driver 55 | scratch := $3A ; ZP scratch location 56 | 57 | ;; Initialize 58 | php 59 | sei 60 | 61 | ;; Execute smartport command 62 | jsr $c50d ; To be changed to the detected slot and address 63 | drv_call_hi = *-1 64 | drv_call_lo = *-2 65 | .byte DRIVER_COMMAND_STATUS ; Command Status 66 | params_address: 67 | .word params - driver ; To be changed on relocation 68 | 69 | ;; Restore state and return 70 | sta $CFFF ; release C8xx ROM space 71 | plp 72 | rts 73 | 74 | params: .byte $03 ; Status param count 75 | port: .byte $00 ; Smartport device 76 | .word DATELO ; Write directly on the four bytes reserved by Prodos for date and time 77 | .byte 'P' ; Get datetime in ProDDOS format 78 | 79 | .endproc 80 | .assert .sizeof(driver) <= 125, error, "Clock code must be <= 125 bytes" 81 | 82 | 83 | ;;; ------------------------------------------------------------ 84 | ;;; Detect Fujinet Clock. 85 | 86 | .proc detect_fujinet_clock 87 | 88 | ;; Search for smartport cards 89 | ldx #$C7 ; Start the search from slot 7 90 | search_slot: 91 | jsr find_smartport 92 | bcs not_found 93 | 94 | ;; Find a Fujinet Clock device on this slot 95 | jsr setup_smartport 96 | jsr device_count 97 | cpx #$0 98 | beq continue_slot_search; no devices in the slot 99 | 100 | search_unit: 101 | jsr unit_type 102 | cmp #FN_CLOCK_DEVICE_TYPE 103 | beq found 104 | dex 105 | bne search_unit 106 | continue_slot_search: 107 | ldx sp_call_hi ; restore card 108 | dex 109 | cpx #$C0 110 | bne search_slot 111 | jmp not_found 112 | found: 113 | ; Modify the driver code with the detected data 114 | stx driver::port 115 | lda sp_call_lo 116 | sta driver::drv_call_lo 117 | lda sp_call_hi 118 | sta driver::drv_call_hi 119 | 120 | jmp install_driver 121 | 122 | not_found: 123 | .ifndef JUMBO_CLOCK_DRIVER 124 | .if ::LOG_FAILURE 125 | ;; Show failure message 126 | jsr log_message 127 | scrcode PRODUCT, " - Not Found." 128 | .byte 0 129 | .endif ; ::LOG_FAILURE 130 | .endif ; JUMBO_CLOCK_DRIVER 131 | 132 | sec ; failure 133 | rts 134 | .endproc 135 | 136 | ;;; ------------------------------------------------------------ 137 | ;;; Install Driver. Copy into address at DATETIME vector, 138 | ;;; update the vector and update MACHID bits to signal a clock 139 | ;;; is present. 140 | 141 | .proc install_driver 142 | ptr := $A5 143 | 144 | ;; Find driver destination 145 | lda DATETIME+1 146 | sta ptr 147 | lda DATETIME+2 148 | sta ptr+1 149 | 150 | ;; Fix pointers 151 | clc 152 | lda ptr 153 | adc driver::params_address 154 | sta driver::params_address 155 | lda ptr+1 156 | adc driver::params_address+1 157 | sta driver::params_address+1 158 | 159 | ;; Copy code 160 | lda RWRAM1 161 | lda RWRAM1 162 | ldy #.sizeof(driver)-1 163 | 164 | loop: lda driver,y 165 | sta (ptr),y 166 | dey 167 | bpl loop 168 | 169 | ;; Set the "Recognizable Clock Card" bit 170 | lda MACHID 171 | ora #$01 172 | sta MACHID 173 | 174 | lda #OPC_JMP_abs 175 | sta DATETIME 176 | 177 | ;; Invoke the driver to init the time 178 | jsr DATETIME 179 | 180 | lda ROMIN2 181 | 182 | .if ::LOG_SUCCESS 183 | ;; Display success message 184 | jsr log_message 185 | scrcode PRODUCT, " - " 186 | .byte 0 187 | 188 | ;; Display the current date 189 | jsr cout_date 190 | .endif ; ::LOG_SUCCESS 191 | 192 | clc ; success 193 | rts ; done! 194 | .endproc 195 | 196 | 197 | ;;; ************************************************************ 198 | .ifndef JUMBO_CLOCK_DRIVER 199 | .include "../../inc/driver_postamble.inc" 200 | .endif ; JUMBO_CLOCK_DRIVER 201 | ;;; ************************************************************ 202 | -------------------------------------------------------------------------------- /clocks/romx/romxrtc.system.s: -------------------------------------------------------------------------------- 1 | ;;; ROMX ProDOS RTC Driver 2 | ;;; Ver 0.91 3 | ;;; Ver 0.92 Added ZIP slowdowns 4 | ;;; Ver 0.93 Moved StubLoc to $0110 5 | ;;; Ver 0.94 Moved StubLoc to RTC_BUF + 7. Save/restore in stack 6 | ;;; Ver 0.95 Moved MaskTable to after Thunderclock reloc area 7 | ;;; 8 | ;;; Modifications by Joshua Bell inexorabletash@gmail.com 9 | ;;; * Converted to ca65 syntax and adapted to driver wrapper. 10 | 11 | .ifndef JUMBO_CLOCK_DRIVER 12 | .setcpu "6502" 13 | .linecont + 14 | .feature string_escapes 15 | 16 | .include "apple2.inc" 17 | .include "apple2.mac" 18 | .include "opcodes.inc" 19 | 20 | .include "../../inc/apple2.inc" 21 | .include "../../inc/macros.inc" 22 | .include "../../inc/prodos.inc" 23 | .endif ; JUMBO_CLOCK_DRIVER 24 | 25 | ;;; Uncomment the following to "fake" a clock with a fixed date. 26 | ;;; Used for testing without a real ROMX around. 27 | ;;; FAKE_CLOCK = 1 28 | 29 | ;;; ************************************************************ 30 | .ifndef JUMBO_CLOCK_DRIVER 31 | .include "../../inc/driver_preamble.inc" 32 | .endif ; JUMBO_CLOCK_DRIVER 33 | ;;; ************************************************************ 34 | 35 | ZipSlo := $C0E0 ; ZIP CHIP slowdown 36 | 37 | ;;; ROMX locations 38 | FWReadClock := $D8F0 ; Firmware clock driver routine 39 | SigCk := $DFFE ; ROMX sig bytes 40 | SEL_MBANK := $F851 ; Select Main bank reg 41 | 42 | ;;; ============================================================ 43 | ;;; 44 | ;;; Driver Installer 45 | ;;; 46 | ;;; ============================================================ 47 | 48 | .undef PRODUCT 49 | .define PRODUCT "ROMX Clock" 50 | 51 | ;;; ============================================================ 52 | ;;; Ensure there is not a previous clock driver installed. 53 | 54 | .ifdef FAKE_CLOCK 55 | 56 | maybe_install_driver := install_driver 57 | 58 | .else 59 | 60 | .proc maybe_install_driver 61 | lda MACHID 62 | and #$01 ; existing clock card? 63 | beq detect_romx ; nope, check for ROMX 64 | 65 | rts ; yes, done! 66 | .endproc 67 | 68 | ;;; ------------------------------------------------------------ 69 | 70 | .proc detect_romx 71 | ;; Try to detect ROMX and RTC 72 | bit ROMIN2 ; enable ROM 73 | bit ZipSlo ; disable ZIP 74 | bit $FACA ; enable ROMXe, temp bank 0 75 | bit $FACA 76 | bit $FAFE 77 | 78 | lda SigCk ; Check for ROMX signature bytes 79 | cmp #$4A 80 | bne nope 81 | lda SigCk+1 82 | cmp #$CD 83 | bne nope 84 | lda FWReadClock ; is RTC code there? 85 | cmp #$AD 86 | bne nope 87 | clc ; found clock! 88 | bcc :+ 89 | nope: sec ; not found 90 | : bit SEL_MBANK ; restore original bank (unconditionally) 91 | bcc install_driver ; found clock! 92 | 93 | .ifndef JUMBO_CLOCK_DRIVER 94 | .if ::LOG_FAILURE 95 | ;; Show failure message 96 | jsr log_message 97 | scrcode PRODUCT, " - Not Found." 98 | .byte 0 99 | .endif ; ::LOG_FAILURE 100 | .endif ; JUMBO_CLOCK_DRIVER 101 | 102 | sec ; failure 103 | rts 104 | .endproc 105 | 106 | .endif 107 | 108 | ;;; ------------------------------------------------------------ 109 | ;;; Install ROMX RTC Driver. Copy into address at DATETIME vector, 110 | ;;; update the vector and update MACHID bits to signal a clock 111 | ;;; is present. 112 | 113 | .proc install_driver 114 | ptr := $A5 115 | 116 | ;; Update absolute addresses within driver 117 | lda DATETIME+1 118 | sta ptr 119 | lda DATETIME+2 120 | sta ptr+1 121 | 122 | lda ptr 123 | clc 124 | adc RELOC1 125 | sta RELOC1 126 | lda ptr + 1 127 | adc RELOC1 + 1 128 | sta RELOC1 + 1 129 | 130 | lda ptr 131 | clc 132 | adc RELOC2 133 | sta RELOC2 134 | lda ptr + 1 135 | adc RELOC2 + 1 136 | sta RELOC2 + 1 137 | 138 | ;; Copy driver into appropriate bank 139 | lda RWRAM1 140 | lda RWRAM1 141 | ldy #ClockDrvSize-1 142 | 143 | loop: lda ClockDrv,y 144 | sta (ptr),y 145 | dey 146 | bpl loop 147 | 148 | ;; Set the "Recognizable Clock Card" bit 149 | lda MACHID 150 | ora #$01 151 | sta MACHID 152 | 153 | lda #OPC_JMP_abs 154 | sta DATETIME 155 | 156 | ;; Invoke the driver to init the time 157 | jsr DATETIME 158 | 159 | lda ROMIN2 160 | 161 | .if ::LOG_SUCCESS 162 | ;; Display success message 163 | jsr log_message 164 | scrcode PRODUCT, " - " 165 | .byte 0 166 | 167 | ;; Display the current date 168 | jsr cout_date 169 | .endif ; ::LOG_SUCCESS 170 | 171 | clc ; success 172 | rts ; done! 173 | .endproc 174 | 175 | ;;; ============================================================ 176 | ;;; ROMX RTC driver - Relocated into ProDOS clock driver space 177 | ;;; ============================================================ 178 | 179 | ;;; ROMX Firmware writes RTC data into this fixed location. 180 | ;;; It risks conflicting with some applications (e.g. A2DeskTop), 181 | ;;; so the data is saved/restored around clock reads. 182 | 183 | RTC_BUF := $02B0 ; use keyboard buffer 184 | StubLoc := RTC_BUF+7 ; RAM stub for ROMX 185 | 186 | 187 | ClockDrv: 188 | ;; -------------------------------------------------- 189 | ;; Enter driver 190 | 191 | php 192 | sei 193 | 194 | ;; -------------------------------------------------- 195 | ;; Copy the stub to RAM, and preserve RTC_BUF 196 | 197 | ldx #RamStubEnd-RamStub+7 ; preserve and copy stub to RAM 198 | : lda RTC_BUF,x 199 | pha 200 | RELOC1 := *+1 201 | lda RamStub-ClockDrv-7,x ; self-modified during relocation 202 | sta RTC_BUF,x 203 | dex 204 | bpl :- 205 | 206 | ;; -------------------------------------------------- 207 | ;; Read the clock into `RTC_BUF` 208 | 209 | jsr StubLoc 210 | 211 | ;; -------------------------------------------------- 212 | ;; Strip non-number bits, convert decimal to binary, push to stack 213 | 214 | ldy #6 215 | bufloop: 216 | lda RTC_BUF,y 217 | 218 | RELOC2 := *+1 219 | and MaskTable-1-ClockDrv,y ; self-modified during relocation 220 | 221 | ;; BCD to Binary 222 | ;; On entry, A=BCD value &00-&99 223 | ;; On exit, A=binary value 0-99 224 | ldx #$FF ; Start with result=-1 225 | sec ; Prepare for subtraction 226 | sed ; Switch to Decimal arithmetic 227 | : inx ; Add 1 to result 228 | sbc #1 ; Subtract 1 with BCD arithmetic 229 | bcs :- ; Loop until BCD value < 0 230 | cld ; Switch back to Binary arithmetic 231 | txa ; return in A 232 | 233 | ;; Push to stack 234 | pha 235 | dey 236 | bne bufloop ; 6..1 237 | 238 | ;; -------------------------------------------------- 239 | ;; Pull and place values into ProDOS time locations 240 | 241 | ;; (`RTC_BUF`+0 is not pushed) 242 | 243 | pla ; `RTC_BUF`+1 = minute 244 | sta TIMELO 245 | 246 | pla ; `RTC_BUF`+2 = hour 247 | sta TIMEHI 248 | 249 | pla ; `RTC_BUF`+3 = weekday (unused) 250 | 251 | pla ; `RTC_BUF`+4 = day 252 | sta DATELO 253 | 254 | pla ; `RTC_BUF`+5 = month 255 | asl a 256 | asl a 257 | asl a 258 | asl a 259 | asl a ; MSB will merge into DATEHI 260 | ora DATELO ; merge with day 261 | sta DATELO 262 | 263 | pla ; `RTC_BUF`+6 = year 264 | sta DATEHI 265 | rol DATEHI ; merge with MSB from month 266 | 267 | ;; -------------------------------------------------- 268 | ;; Restore what was originally at `RTC_BUF` 269 | ;; And fix //c+ cache while we're ad it! 270 | 271 | ldx #0 272 | : pla 273 | sta RTC_BUF,x 274 | lda $F8F0,x ; clear cache of $D8F0-D901 275 | inx 276 | cpx #RamStubEnd-RamStub+7+1 277 | bne :- 278 | 279 | ;; -------------------------------------------------- 280 | ;; Exit driver 281 | 282 | plp 283 | rts 284 | 285 | RamStub: 286 | .ifndef FAKE_CLOCK 287 | ;; Really read the ROMX RTC 288 | 289 | bit ROMIN2 ; enable ROM 290 | bit ZipSlo ; disable ZIP 291 | bit $FACA ; enable ROMXe, temp bank 0 292 | bit $FACA 293 | bit $FAFE 294 | jsr FWReadClock ; Call ROMX to read clock 295 | bit SEL_MBANK ; restore original bank 296 | bit LCBANK1 ; restore LC w/write 297 | bit LCBANK1 298 | .else 299 | ;; No ROMX RTC around? Provide fake data for testing. 300 | ;; October 5, 2021 12:34:56 301 | 302 | lda #$56 ; sec 303 | sta RTC_BUF+0 304 | lda #$34 ; min 305 | sta RTC_BUF+1 306 | lda #$12 ; hr 307 | sta RTC_BUF+2 308 | lda #$05 ; date 309 | sta RTC_BUF+4 310 | lda #$10 ; month 311 | sta RTC_BUF+5 312 | lda #$21 ; year 313 | sta RTC_BUF+6 314 | .endif 315 | 316 | rts 317 | RamStubEnd := * 318 | .assert RamStubEnd - RamStub < $20, error, "Stub too long" 319 | 320 | MaskTable: 321 | .byte $7f, $3f, $07, $3f, $1f, $ff 322 | ;; .... min hour wkdy date mnth year (`RTC_BUF` bytes 1..6) 323 | 324 | ClockDrvEnd := * 325 | ClockDrvSize = ClockDrvEnd - ClockDrv 326 | 327 | .assert ClockDrvSize <= 125, error, \ 328 | .sprintf("Clock driver must be <= 125 bytes, was %d bytes", ClockDrvSize) 329 | 330 | ;;; ************************************************************ 331 | .ifndef JUMBO_CLOCK_DRIVER 332 | .include "../../inc/driver_postamble.inc" 333 | .endif ; JUMBO_CLOCK_DRIVER 334 | ;;; ************************************************************ 335 | -------------------------------------------------------------------------------- /setup/setup.system.s: -------------------------------------------------------------------------------- 1 | ;;; 2 | ;;; SETUP.SYSTEM by Sean Nolan 3 | ;;; 4 | ;;; A Proposed Startup File Standard 5 | ;;; 6 | ;;; Published in Call-APPLE, November, 1987 7 | ;;; This program is in the public domain. 8 | ;;; 9 | ;;; This program mimics the ProDOS 16 10 | ;;; SYSTEM.SETUP convention. It can be used 11 | ;;; to install RAM disk drivers, clock 12 | ;;; drivers, and IIGS Classic Desk 13 | ;;; Accessories on bootup under ProDOS 8. 14 | ;;; 15 | ;;; This program loads and calls all BINary 16 | ;;; and SYStem files in a subdirectory named 17 | ;;; SETUPS. It then looks for the second 18 | ;;; system program in the volume directory 19 | ;;; whose name ends in ".SYSTEM", and runs 20 | ;;; that. 21 | ;;; 22 | ;;; 23 | 24 | ;;; Original code clears the screen before/after each driver. Skip it. 25 | NO_HOME = 1 26 | 27 | .define ORG .org 28 | .define DFB .byte 29 | .define DA .addr 30 | .define DS .res 31 | .define ASC .byte 32 | .define ASCH scrcode 33 | .feature labels_without_colons + 34 | .feature loose_string_term + 35 | .include "apple2.mac" 36 | 37 | .if 0 38 | TYP $FF ;save as a system file 39 | .endif 40 | ORG $BD00 ;load at $2000, but run at $BD00 41 | ;;; ****************** equates 42 | CH = $24 43 | IN2 = $280 44 | FILETYPE = IN2+16 45 | AUXCODE = IN2+31 46 | RESET = $3F2 47 | IOBUFFER = $B900 48 | PRODOS = $BF00 49 | QUITVECT = $BF03 50 | DEVNUM = $BF30 51 | BITMAP = $BF58 52 | INIT = $FB2F 53 | VTABZ = $FC24 54 | HOME = $FC58 55 | RDKEY = $FD0C 56 | SETVID = $FE93 57 | SETKBD = $FE89 58 | SETNORM = $FE84 59 | ;;; ****************** boot code 60 | VOLNAME = * ;The first 17 bytes are overwritten with the 61 | ;name of the volume from which this was run. 62 | LDX #1 ;mark page $BD as free in the system bitmap 63 | STX BITMAP+23 ;so we can put Online result in our code. 64 | DEX ;relocate this program to $BD00-BEFF 65 | LOOP1 LDA $2000,X 66 | STA $BD00,X 67 | LDA $2100,X 68 | STA $BE00,X 69 | INX 70 | BNE LOOP1 71 | DEX 72 | TXS ;init stack pointer 73 | JMP ENTER ;jump to relocated code 74 | DIRNAME DFB 6 ;DirName and VolName must be in the same page 75 | ASCH "SETUPS" 76 | 77 | ;;; ****** Get name of boot volume 78 | ENTER LDA DEVNUM ;get name of last volume accessed 79 | STA ONLINEN 80 | JSR PRODOS 81 | DFB $C5 ;ONLINE 82 | DA ONLINEP 83 | LDA VOLNAME+1 ;insert a slash nefore the name 84 | AND #$0F 85 | TAX 86 | INX 87 | STX VOLNAME 88 | LDA #$2F ;/ 89 | STA VOLNAME+1 90 | LDA QUITVECT+1 ;save original quit vector 91 | STA QUITMOD1+1 92 | LDA QUITVECT+2 93 | STA QUITMOD2+1 94 | ;;; ****** Clean up before & after calling files 95 | MAINLOOP LDX #2 ;point Reset vector and ProDOS 96 | LOOP3 LDA JUMP+1,X ;Quit vectors to MainLoop 97 | STA RESET,X 98 | LDA JUMP,X 99 | STA QUITVECT,X 100 | DEX 101 | BPL LOOP3 102 | TXS ;fix stack pointer (X=$FF) 103 | JSR CLOSE ;close all open files 104 | LDX #23 ;clear system bit map 105 | LDA #0 106 | LOOP2 STA BITMAP,X 107 | DEX 108 | BPL LOOP2 109 | LDA #$CF ;mark pages 0,1,4-7 as used 110 | STA BITMAP 111 | LDA #%111 ;mark pages $BD-$BF as used 112 | STA BITMAP+23 113 | LDA $C082 ;Language card off 114 | STA $C00C ;40-column 115 | STA $C00E ;normal character set 116 | STA $C000 ;80STORE off 117 | JSR SETNORM ;normal 118 | JSR INIT ;display text page 1 119 | JSR SETVID ;PR#0 120 | JSR SETKBD ;IN#0 121 | ;;; Make sure boot volume is around 122 | ;;; AND set prefix to the boot volume 123 | .if NO_HOME 124 | VOLMOUNT 125 | .else 126 | VOLMOUNT JSR HOME 127 | .endif 128 | JSR PRODOS ;set prefix to volume 129 | DFB $C6 ;SET PREFIX 130 | DA PFX2P 131 | BCC VOLOK 132 | LDX #13 133 | LOOP6 LDA VOLTEXT-1,X ;print message "insert volume" 134 | STA $5A8+4,X 135 | DEX 136 | BNE LOOP6 137 | LOOP7 LDA VOLNAME+1,X ;print volume name 138 | ORA #$80 139 | STA $5A8+19,X 140 | INX 141 | CPX VOLNAME 142 | BCC LOOP7 143 | LDA #35 ;go to CH=35, CV=11 144 | STA CH 145 | LDA #11 146 | JSR VTABZ 147 | JSR RDKEY ;wait for keypress 148 | JMP VOLMOUNT 149 | ;;; ****** Get name of next file at IN2 150 | VOLOK JSR NEXTFILE ;get name of next file at IN2 151 | BCS EXITLOOP ;if error, we're done with setup files 152 | ;;; ****** Load and call setup file 153 | JSR PRODOS ;set prefix to SETUPS 154 | DFB $C6 ;SET PREFIX 155 | DA PFX1P 156 | JSR READFILE ;read in file whose name is at IN@ 157 | ;and call it if there was no error. 158 | JUMP JMP MAINLOOP ;3 bytes here copied into ProDOS quit vector 159 | DFB $BD^$A5 ;3 bytes here are copied into reset vector 160 | EXITLOOP INC RESET+2 ;scramble reset vector 161 | QUITMOD1 LDA #0 ;restore original quit vector 162 | STA QUITVECT+1 163 | QUITMOD2 LDA #0 164 | STA QUITVECT+2 165 | ;;; ****** Look for second system program on disk 166 | LDA #0 ;modify NextFile routine so that it searches 167 | STA NUMBER+1 ;the volume directory for system files only. 168 | STA CHEKTYPE+1 169 | LDA #$CFFF 63 | ldy #<$CFFF 64 | sta ld4+2 65 | sty ld4+1 66 | sta st4+2 67 | sty st4+1 68 | lda #0 69 | sta slot 70 | lda #3 ; treat slot 0 as slot 3 71 | 72 | sloop: ora #$C0 ; A=$Cs 73 | pha 74 | jsr DetectZ80 75 | pla ; A=$Cs 76 | bcs next ; Z80 present, skip this slot 77 | 78 | sta st1+2 79 | rloop: sta ld1+2 80 | sta ld2+2 81 | sta st2+2 82 | 83 | lda #3 ; 3 tries - need valid results each time 84 | sta tries 85 | try: jsr driver ; try reading date/time 86 | lda DATELO+1 ; check result 87 | ror a 88 | lda DATELO 89 | rol a 90 | rol a 91 | rol a 92 | rol a 93 | and #$0F 94 | beq next 95 | cmp #13 ; month 96 | bcs next 97 | lda DATELO 98 | and #$1F 99 | beq next 100 | cmp #32 ; day 101 | bcs next 102 | lda TIMELO+1 103 | cmp #24 ; hours 104 | bcs next 105 | lda TIMELO 106 | cmp #60 ; minutes 107 | bcs next 108 | dec tries 109 | bne try 110 | beq install_driver ; all tries look valid 111 | next: inc slot 112 | lda slot 113 | cmp #8 114 | bcc sloop ; next slot 115 | bne not_found 116 | 117 | ;; Not found in slot ROM, try main ROMs ??? 118 | lda #>$C015 ; $C015 = RDCXROM (internal or slot ROM?) 119 | ldy #<$C015 120 | sta ld4+2 121 | sty ld4+1 122 | ldy #$07 ; $C007 = INTCXROM (read internal ROM) 123 | sta st1+2 124 | sty st1+1 125 | dey ; $C006 = SLOTCXROM (read slot ROM) 126 | sta st4+2 127 | sty st4+1 128 | lda #>$C800 129 | bne rloop 130 | 131 | ;; Restore date/time 132 | not_found: 133 | ldy #3 134 | : lda saved,y 135 | sta DATELO,y 136 | dey 137 | bpl :- 138 | 139 | .ifndef JUMBO_CLOCK_DRIVER 140 | .if ::LOG_FAILURE 141 | ;; Show failure message 142 | jsr log_message 143 | scrcode PRODUCT, " - Not Found." 144 | .byte 0 145 | .endif ; ::LOG_FAILURE 146 | .endif ; JUMBO_CLOCK_DRIVER 147 | 148 | sec ; failure 149 | rts 150 | 151 | saved: .byte 0, 0, 0, 0 152 | tries: .byte 3 153 | slot: .byte 0 154 | .endproc 155 | 156 | ;;; ------------------------------------------------------------ 157 | ;;; Install NSC Driver. Copy into address at DATETIME vector, 158 | ;;; update the vector and update MACHID bits to signal a clock 159 | ;;; is present. 160 | 161 | .proc install_driver 162 | ptr := $A5 163 | 164 | ;; Update absolute addresses within driver 165 | lda DATETIME+1 166 | sta ptr 167 | clc 168 | adc #(unlock - driver - 1) 169 | sta unlock_addr 170 | lda DATETIME+2 171 | sta ptr+1 172 | adc #0 173 | sta unlock_addr+1 174 | 175 | ;; Copy driver into appropriate bank 176 | lda RWRAM1 177 | lda RWRAM1 178 | ldy #sizeof_driver-1 179 | 180 | loop: lda driver,y 181 | sta (ptr),y 182 | dey 183 | bpl loop 184 | 185 | ;; Set the "Recognizable Clock Card" bit 186 | lda MACHID 187 | ora #$01 188 | sta MACHID 189 | 190 | lda #OPC_JMP_abs 191 | sta DATETIME 192 | 193 | ;; Invoke the driver to init the time 194 | jsr DATETIME 195 | 196 | lda ROMIN2 197 | 198 | .if ::LOG_SUCCESS 199 | ;; Display success message 200 | jsr log_message 201 | scrcode PRODUCT, " - " 202 | .byte 0 203 | 204 | ;; Display the current date 205 | jsr cout_date 206 | .endif ; ::LOG_SUCCESS 207 | 208 | clc ; success 209 | rts ; done! 210 | .endproc 211 | 212 | ;;; ------------------------------------------------------------ 213 | ;;; Detect Z80 214 | ;;; ------------------------------------------------------------ 215 | 216 | ;;; This routine gets swapped into $0FFD for execution 217 | .proc Z80Routine 218 | target := $0FFD 219 | ;; .org $FFFD 220 | patch := *+2 221 | .byte $32, $00, $e0 ; ld ($Es00),a ; s=slot being probed turn off Z80, next PC is $0000 222 | .byte $3e, $01 ; ld a,$01 223 | .byte $32, $08, $00 ; ld (flag),a 224 | .byte $c3, $fd, $ff ; jp $FFFD 225 | flag := * 226 | .byte $00 ; flag: .db $00 227 | .endproc 228 | .assert Z80Routine > Z80Routine::target + .sizeof(Z80Routine), error, "Z80 collision" 229 | 230 | ;;; Input: A = $Cn where n = slot number 231 | ;;; Output: C=1 if Z80 found in slot 232 | .proc DetectZ80 233 | ;; Location to poke to invoke Z80 234 | sta store+1 235 | 236 | ;; Convert $Cn to $En, update Z80 code 237 | ora #$E0 238 | sta Z80Routine::patch 239 | 240 | ;; Clear detection flag 241 | copy #0, Z80Routine::flag 242 | 243 | ;; Put routine in place 244 | jsr SwapRoutine 245 | 246 | ;; Try to invoke Z80 247 | php 248 | sei 249 | store := *+1 250 | sta $C000 ; self-modified 251 | plp 252 | 253 | ;; Restore memory 254 | jsr SwapRoutine 255 | 256 | ;; Flag will be set to 1 by routine if Z80 was present. 257 | lda Z80Routine::flag 258 | ror ; move flag into carry 259 | rts 260 | 261 | .proc SwapRoutine 262 | ldx #.sizeof(Z80Routine)-1 263 | : ldy Z80Routine::target,x 264 | lda Z80Routine,x 265 | sta Z80Routine::target,x 266 | tya 267 | sta Z80Routine,x 268 | dex 269 | bpl :- 270 | rts 271 | .endproc 272 | .endproc 273 | 274 | ;;; ============================================================ 275 | ;;; NSC driver - modified as needed and copied into ProDOS 276 | ;;; ============================================================ 277 | 278 | driver: 279 | php 280 | sei 281 | lda PTRIG ; Slow ZIP, IIc+ accelerator, etc 282 | lda $C00B ; Ultrawarp bug workaround c/o @bobbimanners 283 | ld4: lda $CFFF ; self-modified ($CFFF or RDCXROM) 284 | pha 285 | st1: sta $C300 ; self-modified ($Cn00 or INTCXROM) 286 | ld1: lda $C304 ; self-modified ($Cn04) 287 | ldx #8 288 | 289 | ;; -------------------------------------------------- 290 | ;; Unlock the NSC by bit-banging. 291 | uloop: 292 | unlock_addr := *+1 293 | lda unlock-1,x ; self-modified (during relocation) 294 | sec 295 | ror a ; a bit at a time 296 | : pha 297 | lda #0 298 | rol a 299 | tay 300 | ld2: lda $C300,y ; self-modified ($Cn00) 301 | pla 302 | lsr a 303 | bne :- 304 | dex 305 | bne uloop 306 | 307 | ;; -------------------------------------------------- 308 | ;; Read 8 bytes * 8 bits of clock data, push onto stack 309 | 310 | tmp := $200 311 | ldx #8 312 | bloop: ldy #8 313 | st2: 314 | : lda $C304 ; self-modified ($Cn04) 315 | ror a 316 | ror tmp 317 | dey 318 | bne :- 319 | 320 | ;; BCD to Binary - slow but tiny 321 | lda tmp ; A = value 322 | ldy #$FF ; result = -1 323 | sec 324 | sed 325 | : iny ; result += 1 326 | sbc #1 ; value -= 1 327 | bcs :- 328 | cld 329 | tya ; A = result 330 | 331 | ;; Push to stack 332 | pha 333 | dex 334 | bne bloop 335 | 336 | ;; -------------------------------------------------- 337 | ;; Now stack has y/m/d/w/H/M/S/F 338 | 339 | pla ; year 340 | sta DATELO+1 341 | 342 | pla ; month 343 | asl 344 | asl 345 | asl 346 | asl 347 | asl 348 | sta DATELO 349 | rol DATELO+1 350 | 351 | pla ; day 352 | ora DATELO 353 | sta DATELO 354 | 355 | pla ; skip week 356 | 357 | pla ; hour 358 | sta TIMELO+1 359 | 360 | pla ; minute 361 | sta TIMELO 362 | 363 | pla ; skip seconds 364 | pla ; skip fraction 365 | 366 | ;; -------------------------------------------------- 367 | ;; Finish up 368 | 369 | pla 370 | bmi done 371 | st4: sta $CFFF ; self-modified ($CFFF or SLOTCXROM) 372 | done: plp 373 | rts 374 | 375 | unlock: 376 | ;; NSC unlock sequence 377 | .byte $5C, $A3, $3A, $C5 378 | .byte $5C, $A3, $3A, $C5 379 | 380 | sizeof_driver := * - driver 381 | .assert sizeof_driver <= 125, error, "Clock code must be <= 125 bytes" 382 | 383 | ;;; ************************************************************ 384 | .ifndef JUMBO_CLOCK_DRIVER 385 | .include "../../inc/driver_postamble.inc" 386 | .endif ; JUMBO_CLOCK_DRIVER 387 | ;;; ************************************************************ 388 | -------------------------------------------------------------------------------- /clocks/cricket/cricket.system.s: -------------------------------------------------------------------------------- 1 | ;;; The Cricket Clock - ProDOS System 2 | ;;; Adapted from /CRICKET/PRODOS.MOD 3 | ;;; Original: Street Electronics Corporation (C) 1984 4 | 5 | ;;; Adapted from: /NO.SLOT.CLOCK/NS.CLOCK.SYSTEM 6 | ;;; Original by "CAP" 04/21/91 7 | ;;; http://www.apple2.org.za/gswv/a2zine/GS.WorldView/v1999/Oct/MISC/NSC.Disk.TXT 8 | 9 | .ifndef JUMBO_CLOCK_DRIVER 10 | .setcpu "6502" 11 | .linecont + 12 | .feature string_escapes 13 | 14 | .include "apple2.inc" 15 | .include "apple2.mac" 16 | .include "opcodes.inc" 17 | 18 | .include "../../inc/apple2.inc" 19 | .include "../../inc/macros.inc" 20 | .include "../../inc/prodos.inc" 21 | .include "../../inc/ascii.inc" 22 | .endif ; JUMBO_CLOCK_DRIVER 23 | 24 | ;;; ************************************************************ 25 | .ifndef JUMBO_CLOCK_DRIVER 26 | .include "../../inc/driver_preamble.inc" 27 | .endif ; JUMBO_CLOCK_DRIVER 28 | ;;; ************************************************************ 29 | 30 | ;;; ============================================================ 31 | ;;; 32 | ;;; Driver Installer 33 | ;;; 34 | ;;; ============================================================ 35 | 36 | read_delay_hi = $3 * 3 ; ($300 iterations is normal * 3.6MHz) 37 | 38 | .undef PRODUCT 39 | .define PRODUCT "Cricket Clock" 40 | 41 | ;;; ============================================================ 42 | ;;; Ensure there is not a previous clock driver installed. 43 | 44 | .proc maybe_install_driver 45 | lda MACHID 46 | and #$01 ; existing clock card? 47 | beq detect_cricket ; nope, check for Cricket 48 | 49 | rts ; yes, done! 50 | .endproc 51 | 52 | ;;; ------------------------------------------------------------ 53 | ;;; Detect Cricket. Detect SSC and if present probe device. 54 | 55 | .proc detect_cricket 56 | 57 | ;; Check Slot 2 for SSC. ID bytes per: 58 | ;; Apple II Technical Note #8: Pascal 1.1 Firmware Protocol ID Bytes 59 | lda $C205 60 | cmp #$38 61 | bne ssc_not_found 62 | lda $C207 63 | cmp #$18 64 | bne ssc_not_found 65 | lda $C20B 66 | cmp #$01 67 | bne ssc_not_found 68 | lda $C20C 69 | cmp #$31 70 | bne ssc_not_found 71 | 72 | beq init_ssc 73 | ssc_not_found: 74 | jmp not_found 75 | 76 | ;; Init SSC and try the "Read Cricket ID code" sequence. 77 | init_ssc: 78 | php 79 | sei 80 | lda COMMAND ; save status of SSC registers 81 | sta saved_command 82 | lda CONTROL 83 | sta saved_control 84 | 85 | ;; Reset the Cricket (stops any playing notes & ensures Cricket is listening) 86 | jsr reset_cricket 87 | jsr reset_cricket ; does it twice in original Cricket driver 88 | 89 | ;; Read Cricket ID code: 00 ($00) 90 | lda #0 91 | jsr sendbyte 92 | bcs cricket_not_found ; timeout 93 | 94 | ;; "The Cricket will return a "C" (195, $C3) followed by a 95 | ;; version number (in ASCII) and a carriage return (141, $8D)." 96 | jsr readbyte 97 | bcs cricket_not_found ; timeout 98 | cmp #HI('C') ; = 'C' ? 99 | bne cricket_not_found 100 | 101 | jsr readbyte 102 | bcs cricket_not_found ; timeout 103 | bcc digit 104 | 105 | : jsr readbyte 106 | bcs cricket_not_found ; timeout 107 | cmp #HI(ASCII_CR) 108 | beq cricket_found 109 | digit: cmp #HI('0') ; < '0' ? 110 | bcc cricket_not_found 111 | cmp #HI('9' + 1) ; > '9' ? 112 | bcs cricket_not_found 113 | bcc :- 114 | 115 | cricket_found: 116 | jsr restore_cmd_ctl 117 | plp 118 | jmp install_driver 119 | 120 | cricket_not_found: 121 | jsr restore_cmd_ctl 122 | plp 123 | ;; fall through... 124 | 125 | not_found: 126 | .ifndef JUMBO_CLOCK_DRIVER 127 | .if ::LOG_FAILURE 128 | ;; Show failure message 129 | jsr log_message 130 | scrcode PRODUCT, " - Not Found." 131 | .byte 0 132 | .endif ; ::LOG_FAILURE 133 | .endif ; JUMBO_CLOCK_DRIVER 134 | 135 | sec ; failure 136 | rts 137 | 138 | reset_cricket: 139 | ;; Reset SSC 140 | lda #0 141 | sta COMMAND ; hardware reset all Port 2 ACIA registers 142 | sta CONTROL 143 | 144 | ;; Configure SSC 145 | lda #%00001011 ; no parity/echo/interrupts, RTS low, DTR low 146 | sta COMMAND 147 | lda #%10011110 ; 9600 baud, 8 data bits, 2 stop bits 148 | sta CONTROL 149 | 150 | jsr readbyte ; done on original disk 151 | lda #HI(ASCII_CR) ; two carriage returns 152 | jsr sendbyte 153 | lda #HI(ASCII_CR) 154 | jsr sendbyte 155 | lda #HI('!') ; Reset Cricket (everything but time/date) 156 | jsr sendbyte 157 | rts 158 | 159 | restore_cmd_ctl: 160 | lda saved_control 161 | sta CONTROL 162 | lda saved_command 163 | sta COMMAND 164 | rts 165 | 166 | saved_command: .byte 0 167 | saved_control: .byte 0 168 | .endproc 169 | 170 | ;; Write byte in A 171 | .proc sendbyte 172 | tries := $100 * read_delay_hi 173 | counter := $A5 174 | 175 | pha 176 | 177 | lda #tries 180 | sta counter+1 181 | 182 | check: lda STATUS 183 | and #(1 << 4) ; transmit register empty? (bit 4) 184 | bne ready ; yes, ready to write 185 | 186 | dec counter 187 | bne check 188 | dec counter+1 189 | bne check 190 | 191 | pla 192 | sec ; failed 193 | rts 194 | 195 | ready: 196 | pla 197 | sta TDREG 198 | clc 199 | rts 200 | .endproc 201 | 202 | ;; Read byte into A, or carry set if timed out 203 | .proc readbyte 204 | tries := $100 * read_delay_hi 205 | counter := $A5 206 | 207 | lda #tries 210 | sta counter+1 211 | 212 | check: lda STATUS ; did we get it? 213 | and #(1 << 3) ; receive register full? (bit 3) 214 | bne ready ; yes, we read the value 215 | 216 | dec counter 217 | bne check 218 | dec counter+1 219 | bne check 220 | 221 | sec ; failed 222 | rts 223 | 224 | ready: lda RDREG ; actually read the register 225 | clc 226 | rts 227 | .endproc 228 | 229 | ;;; ------------------------------------------------------------ 230 | ;;; Install Cricket Driver. Copy into address at DATETIME vector, 231 | ;;; update the vector and update MACHID bits to signal a clock 232 | ;;; is present. 233 | 234 | .proc install_driver 235 | ptr := $A5 236 | 237 | lda DATETIME+1 238 | sta ptr 239 | lda DATETIME+2 240 | sta ptr+1 241 | lda RWRAM1 242 | lda RWRAM1 243 | ldy #sizeof_driver-1 244 | 245 | loop: lda driver,y 246 | sta (ptr),y 247 | dey 248 | bpl loop 249 | 250 | ;; Set the "Recognizable Clock Card" bit 251 | lda MACHID 252 | ora #$01 253 | sta MACHID 254 | 255 | lda #OPC_JMP_abs 256 | sta DATETIME 257 | 258 | ;; Invoke the driver to init the time 259 | jsr DATETIME 260 | 261 | lda ROMIN2 262 | 263 | .if ::LOG_SUCCESS 264 | ;; Display success message 265 | jsr log_message 266 | scrcode PRODUCT, " - " 267 | .byte 0 268 | 269 | ;; Display the current date 270 | jsr cout_date 271 | .endif ; ::LOG_SUCCESS 272 | 273 | clc ; success 274 | rts ; done! 275 | .endproc 276 | 277 | ;;; ============================================================ 278 | ;;; Cricket Clock Driver - copied into ProDOS 279 | ;;; ============================================================ 280 | 281 | .proc driver 282 | scratch := $3A ; ZP scratch location 283 | 284 | ;; Initialize 285 | php 286 | sei 287 | lda COMMAND ; save status of command register 288 | pha 289 | 290 | ;; Configure SSC 291 | lda #%00001011 ; no parity/echo/interrupts, RTS low, DTR low 292 | sta COMMAND 293 | lda #%10011110 ; 9600 baud, 8 data bits, 2 stop bits 294 | sta CONTROL 295 | 296 | ;; Send command 297 | : lda STATUS 298 | and #(1 << 4) ; transmit register empty? (bit 4) 299 | beq :- ; nope, keep waiting 300 | lda #HI('@') ; '@' command 301 | sta TDREG 302 | 303 | read_len := 7 ; read 7 bytes (w/m/d/y/H/M/S) 304 | 305 | ;; Read response, pushing to stack 306 | ldy #(read_len-1) 307 | 308 | rloop: ldx #0 ; x = retry loop counter low byte 309 | lda #read_delay_hi ; scratch = retry loop counter high byte 310 | sta scratch 311 | 312 | check: lda STATUS ; did we get it? 313 | and #(1 << 3) ; receive register full? (bit 3) 314 | bne ready ; yes, we read the value 315 | 316 | inx ; not yet, so keep trying 317 | bne check ; until counter runs out 318 | dec scratch 319 | bne check 320 | 321 | ;; Read failed - restore stack and exit 322 | reset: cpy #(read_len-1) ; anything left to restore? 323 | beq done ; nope, exit 324 | pla ; yep, clear it off the stack 325 | iny 326 | bne reset 327 | 328 | ;; Read succeeded - stuff it on the stack and continue 329 | ready: lda RDREG 330 | pha 331 | dey 332 | bpl rloop 333 | 334 | ;; Convert pushed response to ProDOS time field 335 | pla ; day of week (unused) 336 | 337 | pla ; minute 338 | sta TIMELO ; -- stored as-is (TIMELO 5-0) 339 | 340 | pla ; hour 341 | sta TIMELO+1 ; -- stored as-is (TIMELO 12-8) 342 | 343 | pla ; year 344 | sta DATELO+1 ; -- will be shifted up by 1 (DATELO 15-9) 345 | 346 | pla ; day 347 | and #%00011111 ; -- masked, stored as is (DATELO 4-0) 348 | sta DATELO 349 | 350 | pla ; month 351 | asl a ; -- shifted up (DATELO 8-5) 352 | asl a 353 | asl a 354 | asl a 355 | asl a 356 | ora DATELO ; -- merge low 5 bits 357 | sta DATELO 358 | rol DATELO+1 359 | 360 | pla ; seconds (unused) 361 | 362 | ;; Restore prior state 363 | done: pla ; restore saved command state 364 | sta COMMAND 365 | plp 366 | rts 367 | .endproc 368 | sizeof_driver := .sizeof(driver) 369 | .assert sizeof_driver <= 125, error, "Clock code must be <= 125 bytes" 370 | 371 | ;;; ************************************************************ 372 | .ifndef JUMBO_CLOCK_DRIVER 373 | .include "../../inc/driver_postamble.inc" 374 | .endif ; JUMBO_CLOCK_DRIVER 375 | ;;; ************************************************************ 376 | -------------------------------------------------------------------------------- /selectors/selector.system.s: -------------------------------------------------------------------------------- 1 | ;;; Disassembly of ProDOS QUIT handler (program selector) 2 | ;;; This is a 40-column selector that prompts for prefix/pathname, 3 | ;;; installed by default except on 80-column systems in 1.9 and 4 | ;;; later. 5 | ;;; 6 | ;;; Installer wrapper added by Joshua Bell inexorabletash@gmail.com 7 | 8 | .setcpu "6502" 9 | .linecont + 10 | .feature string_escapes 11 | 12 | .include "apple2.inc" 13 | .include "apple2.mac" 14 | 15 | .include "../inc/apple2.inc" 16 | .include "../inc/macros.inc" 17 | .include "../inc/prodos.inc" 18 | .include "../inc/ascii.inc" 19 | 20 | ;;; ************************************************************ 21 | .include "../inc/driver_preamble.inc" 22 | ;;; ************************************************************ 23 | 24 | ;;; ------------------------------------------------------------ 25 | 26 | ;;; ProDOS Technical Reference Manual, 5.1.5.2: 27 | ;;; 28 | ;;; ProDOS MLI call $65, the QUIT call, moves addresses $D100 through 29 | ;;; $D3FF from the second 4K bank of RAM of the language card to 30 | ;;; $1000, and executes a JMP to $1000. What initially resides in that 31 | ;;; area is Apple's dispatcher code. 32 | 33 | ;;; ------------------------------------------------------------ 34 | ;;; Installer 35 | ;;; ------------------------------------------------------------ 36 | 37 | max_size = $300 38 | 39 | .proc maybe_install_driver 40 | 41 | src := install_src 42 | end := install_src + install_size 43 | dst := $D100 ; Install location in ProDOS (bank 2) 44 | 45 | src_ptr := $19 46 | dst_ptr := $1B 47 | 48 | sta ALTZPOFF 49 | lda ROMIN 50 | lda ROMIN 51 | lda #>src 52 | sta src_ptr+1 53 | lda #dst 56 | sta dst_ptr+1 57 | lda #end 71 | bne loop 72 | lda src_ptr 73 | cmp #quit 127 | sta RESETVEC+1 128 | eor #$A5 129 | sta RESETVEC+2 130 | 131 | ;; Quit 80-column firmware 132 | lda #$95 ; Ctrl+U (quit 80 col firmware) 133 | jsr COUT 134 | 135 | ;; Reset I/O 136 | sta CLR80VID 137 | sta CLRALTCHAR 138 | sta CLR80COL 139 | jsr SETNORM 140 | jsr INIT 141 | jsr SETVID 142 | jsr SETKBD 143 | 144 | ;; Update System Bit Map 145 | ldx #BITMAP_SIZE-1 146 | lda #%00000001 ; protect page $BF 147 | : sta BITMAP,x 148 | lda #%00000000 ; nothing else protected until... 149 | dex 150 | bne :- 151 | lda #%11001111 ; ZP ($00), stack ($01), text page 1 ($04-$07) 152 | sta BITMAP 153 | 154 | ;; Determine lowercase support 155 | lda MACHID 156 | and #$88 ; IIe or IIc (or IIgs) ? 157 | bne :+ 158 | lda #$DF 159 | sta lowercase_mask ; lower case to upper case 160 | 161 | : rts 162 | .endproc 163 | 164 | ;;; ============================================================ 165 | ;;; Find and invoke the next .SYSTEM file 166 | ;;; ============================================================ 167 | 168 | online_buf := $1C00 169 | io_buf := $1C00 170 | dir_buf := $2000 171 | block_len = $200 172 | 173 | DEFINE_ON_LINE_PARAMS on_line_params,,online_buf 174 | DEFINE_OPEN_PARAMS open_params, PATHNAME, io_buf 175 | DEFINE_READ_PARAMS read_params, SYS_ADDR, SYS_LEN 176 | DEFINE_READ_PARAMS read_block_params, dir_buf, block_len 177 | DEFINE_CLOSE_PARAMS close_params 178 | 179 | 180 | .proc launch_next 181 | ;; Read directory and look for .SYSTEM files; find this 182 | ;; one, and invoke the following one. 183 | 184 | ptr := $A5 185 | num := $A7 186 | len := $A8 187 | 188 | ;; -------------------------------------------------- 189 | ;; Own name found? If not, just quit 190 | lda self_name 191 | bne :+ 192 | jmp quit 193 | 194 | ;; -------------------------------------------------- 195 | ;; Find name of boot device, copy into PATHNAME 196 | : lda devnum 197 | sta on_line_params::unit_num 198 | MLI_CALL ON_LINE, on_line_params 199 | bcc :+ 200 | jmp on_error 201 | 202 | : lda #'/' ; Prefix by '/' 203 | sta PATHNAME+1 204 | lda online_buf 205 | and #$0F ; Mask off length 206 | sta PATHNAME 207 | ldx #0 ; Copy name 208 | : lda online_buf+1,x 209 | sta PATHNAME+2,x 210 | inx 211 | cpx PATHNAME 212 | bne :- 213 | inx ; One more for '/' prefix 214 | stx PATHNAME 215 | 216 | ;; Open directory 217 | MLI_CALL OPEN, open_params 218 | bcc :+ 219 | jmp on_error 220 | : lda open_params::ref_num 221 | sta read_block_params::ref_num 222 | sta close_params::ref_num 223 | 224 | ;; Read first "block" 225 | MLI_CALL READ, read_block_params 226 | bcc :+ 227 | MLI_CALL CLOSE, close_params 228 | jmp on_error 229 | 230 | ;; Get sizes out of header 231 | : lda dir_buf + VolumeDirectoryHeader::entry_length 232 | sta entry_length_mod 233 | lda dir_buf + VolumeDirectoryHeader::entries_per_block 234 | sta entries_per_block_mod 235 | lda #1 236 | sta num 237 | 238 | ;; Set up pointers to entry 239 | lda #<(dir_buf + .sizeof(VolumeDirectoryHeader)) 240 | sta ptr 241 | lda #>(dir_buf + .sizeof(VolumeDirectoryHeader)) 242 | sta ptr+1 243 | 244 | ;; Process directory entry 245 | entry: ldy #FileEntry::file_type ; file_type 246 | lda (ptr),y 247 | cmp #$FF ; type=SYS 248 | bne next 249 | ldy #FileEntry::storage_type_name_length 250 | lda (ptr),y 251 | and #$30 ; regular file (not directory, pascal) 252 | beq next 253 | lda (ptr),y 254 | and #$0F ; name_length 255 | sta len 256 | tay 257 | 258 | ;; Compare suffix - is it .SYSTEM? 259 | ldx suffix 260 | : lda (ptr),y 261 | cmp suffix,x 262 | bne next 263 | dey 264 | dex 265 | bne :- 266 | 267 | ;; Yes; is it *this* .SYSTEM file? 268 | ldy self_name 269 | cpy len 270 | bne handle_sys_file 271 | : lda (ptr),y 272 | cmp self_name,y 273 | bne handle_sys_file 274 | dey 275 | bne :- 276 | sec 277 | ror found_self_flag 278 | 279 | ;; Move to the next entry 280 | next: lda ptr 281 | clc 282 | adc #$27 ; self-modified: entry_length 283 | entry_length_mod := *-1 284 | sta ptr 285 | bcc :+ 286 | inc ptr+1 287 | : inc num 288 | lda num 289 | cmp #$0D ; self-modified: entries_per_block 290 | entries_per_block_mod := *-1 291 | bcc entry 292 | 293 | ;; Read next "block" 294 | MLI_CALL READ, read_block_params 295 | bcs not_found 296 | 297 | ;; Set up pointers to entry 298 | lda #0 299 | sta num 300 | lda #<(dir_buf + $04) 301 | sta ptr 302 | lda #>(dir_buf + $04) 303 | sta ptr+1 304 | jmp entry 305 | 306 | ;; -------------------------------------------------- 307 | ;; Found a .SYSTEM file which is not this one; invoke 308 | ;; it if follows this one. 309 | handle_sys_file: 310 | bit found_self_flag 311 | bpl next 312 | 313 | MLI_CALL CLOSE, close_params 314 | 315 | ;; Compose the path to invoke. 316 | ldx PATHNAME 317 | inx 318 | lda #'/' 319 | sta PATHNAME,x 320 | ldy #0 321 | : iny 322 | inx 323 | lda (ptr),y 324 | sta PATHNAME,x 325 | cpy len 326 | bcc :- 327 | stx PATHNAME 328 | 329 | jmp invoke_system_file 330 | 331 | not_found: 332 | MLI_CALL CLOSE, close_params 333 | jmp quit 334 | .endproc 335 | 336 | ;;; ------------------------------------------------------------ 337 | ;;; Load/execute the system file in PATHNAME 338 | 339 | .proc invoke_system_file 340 | MLI_CALL OPEN, open_params 341 | bcs on_error 342 | 343 | lda open_params::ref_num 344 | sta read_params::ref_num 345 | sta close_params::ref_num 346 | 347 | MLI_CALL READ, read_params 348 | php 349 | MLI_CALL CLOSE, close_params 350 | plp 351 | bcs on_error 352 | 353 | jmp SYS_ADDR ; Invoke loaded SYSTEM file 354 | .endproc 355 | 356 | ;;; ------------------------------------------------------------ 357 | ;;; Error handler - invoked if any ProDOS error occurs. 358 | 359 | .proc on_error 360 | pha 361 | jsr zstrout 362 | scrcode "\r\r* Disk Error $" 363 | .byte 0 364 | 365 | pla 366 | jsr PRBYTE 367 | 368 | jsr zstrout 369 | scrcode " *\r" 370 | .byte 0 371 | 372 | bit KBDSTRB 373 | : lda KBD 374 | bpl :- 375 | bit KBDSTRB 376 | jmp quit 377 | .endproc 378 | 379 | .proc quit 380 | MLI_CALL QUIT, quit_params 381 | brk ; crash if QUIT fails 382 | 383 | DEFINE_QUIT_PARAMS quit_params 384 | .endproc 385 | 386 | ;;; ============================================================ 387 | ;;; Data 388 | 389 | suffix: 390 | PASCAL_STRING ".SYSTEM" 391 | 392 | found_self_flag: 393 | .byte 0 394 | 395 | .else 396 | 397 | ;;; ============================================================ 398 | ;;; Main routine 399 | ;;; ============================================================ 400 | 401 | .proc main 402 | jsr maybe_install_driver 403 | 404 | MLI_CALL QUIT, quit_params 405 | brk ; crash if QUIT fails 406 | 407 | DEFINE_QUIT_PARAMS quit_params 408 | .endproc 409 | 410 | .endif 411 | 412 | ;;; ============================================================ 413 | ;;; Common Routines 414 | ;;; ============================================================ 415 | 416 | ;;; ------------------------------------------------------------ 417 | ;;; Use this for logging the result of a driver. Uses `zstrout`. 418 | 419 | .proc log_message 420 | jsr CROUT 421 | jsr CROUT 422 | ;; fall through 423 | .endproc 424 | 425 | ;;; ------------------------------------------------------------ 426 | ;;; Output a high-ascii, null-terminated string. 427 | ;;; String immediately follows the JSR. 428 | 429 | .proc zstrout 430 | ptr := $A5 431 | 432 | pla ; read address from stack 433 | sta ptr 434 | pla 435 | sta ptr+1 436 | bne skip ; always (since data not on ZP) 437 | 438 | next: cmp #HI('a') ; lower-case? 439 | bcc :+ 440 | and lowercase_mask ; make upper-case if needed 441 | : jsr COUT 442 | skip: inc ptr 443 | bne :+ 444 | inc ptr+1 445 | : ldy #0 446 | lda (ptr),y 447 | bne next 448 | 449 | lda ptr+1 ; restore address to stack 450 | pha 451 | lda ptr 452 | pha 453 | rts 454 | .endproc 455 | 456 | lowercase_mask: 457 | .byte $FF ; Set to $DF on systems w/o lower-case 458 | 459 | ;;; ------------------------------------------------------------ 460 | ;;; COUT a 2-digit number in A 461 | 462 | .proc cout_number 463 | ldx #HI('0') 464 | cmp #10 ; >= 10? 465 | bcc tens 466 | 467 | ;; divide by 10, dividend(+'0') in x remainder in a 468 | : sbc #10 469 | inx 470 | cmp #10 471 | bcs :- 472 | 473 | tens: pha 474 | cpx #HI('0') 475 | beq units 476 | txa 477 | jsr COUT 478 | 479 | units: pla 480 | ora #HI('0') 481 | jsr COUT 482 | rts 483 | .endproc 484 | 485 | ;;; ------------------------------------------------------------ 486 | ;;; COUT the current ProDOS date 487 | 488 | .proc cout_date 489 | lda DATELO+1 ; month 490 | ror a 491 | pha 492 | lda DATELO 493 | pha 494 | rol a 495 | rol a 496 | rol a 497 | rol a 498 | and #%00001111 499 | jsr cout_number 500 | 501 | lda #HI('/') ; / 502 | jsr COUT 503 | 504 | pla ; day 505 | and #%00011111 506 | jsr cout_number 507 | 508 | lda #HI('/') ; / 509 | jsr COUT 510 | 511 | pla ; year 512 | jsr cout_number 513 | 514 | rts 515 | .endproc 516 | -------------------------------------------------------------------------------- /clocks/dclock/dclock.system.s: -------------------------------------------------------------------------------- 1 | ; Fully disassembled and analyzed source to AE 2 | ; DCLOCK.SYSTEM by M.G. - 04/18/2017 3 | ; https://gist.github.com/mgcaret/7f0d7aeec169e90809c7cfaab9bf183b 4 | ; Further modified by @inexorabletash - 12/21/2020 5 | 6 | ; There are critical bugs in the original AE code: 7 | ; * When driver loader is initially probing it corrupts the 8 | ; Apple //c Memory Expansion Card: 9 | ; - it saves, but fails to restore, data at address $080000 10 | ; - it fails to reset slinky pointer, and *will* trash $080000-$080007 11 | ; * When the clock is read, it corrupts data at address $08xx01 12 | ; - John Brooks spotted this, [M.G.] totally missed this. 13 | ; This version of the code has fixes permanently applied. 14 | 15 | .ifndef JUMBO_CLOCK_DRIVER 16 | .setcpu "6502" ; changed below 17 | .linecont + 18 | .feature string_escapes 19 | 20 | .include "apple2.inc" 21 | .include "apple2.mac" 22 | .include "opcodes.inc" 23 | 24 | .include "../../inc/apple2.inc" 25 | .include "../../inc/macros.inc" 26 | .include "../../inc/prodos.inc" 27 | .endif ; JUMBO_CLOCK_DRIVER 28 | 29 | ; zero page locations 30 | SCRATCH := $0B ; scratch value for BCD range checks 31 | SAVEBYTE := $0C ; slinky overwritten byte save location 32 | BCDTMP := $3A ; location clock driver uses for BCD->Binary 33 | 34 | ; buffers & other spaces 35 | INBUF := $0200 ; input buffer 36 | CLOCKBUF := $0300 ; clock buffer 37 | 38 | ; I/O and hardware 39 | C8OFF := $CFFF ; C8xx ROM off 40 | SLOT4ROM := $C400 ; Slot 4 ROM space 41 | SLOT4IO := $C0C0 ; Slot 4 I/O space 42 | DPTRL := SLOT4IO+0 ; Slinky data ptr low 43 | DPTRM := SLOT4IO+1 ; Slinky data ptr middle 44 | DPTRH := SLOT4IO+2 ; Slinky data ptr high 45 | DATA := SLOT4IO+3 ; Slinky data byte 46 | 47 | ;;; ************************************************************ 48 | .ifndef JUMBO_CLOCK_DRIVER 49 | .include "../../inc/driver_preamble.inc" 50 | .endif ; JUMBO_CLOCK_DRIVER 51 | ;;; ************************************************************ 52 | 53 | ;;; ============================================================ 54 | ;;; 55 | ;;; Driver Installer 56 | ;;; 57 | ;;; ============================================================ 58 | 59 | .undef PRODUCT 60 | .define PRODUCT "DClock" 61 | 62 | ;;; ============================================================ 63 | ;;; Ensure there is not a previous clock driver installed. 64 | ;;; And that this is a IIc. And that the clock is present. 65 | ;;; NOTE: Safe to run on a non-IIc (6502 opcodes, etc) 66 | 67 | .proc maybe_install_driver 68 | lda MACHID 69 | and #$01 ; existing clock card? 70 | bne done 71 | 72 | lda VERSION ; IIc identification byte 1 73 | cmp #$06 74 | bne done 75 | lda ZIDBYTE ; IIc identification byte 2 76 | cmp #$00 77 | bne done 78 | 79 | ;;; Since this is a IIc, okay to rely on 65C02 opcodes from here. 80 | .pushcpu 81 | .setcpu "65C02" 82 | 83 | jsr ClockRead 84 | jsr ValidTime 85 | bcc InstallDriver 86 | 87 | .ifndef JUMBO_CLOCK_DRIVER 88 | .if ::LOG_FAILURE 89 | ;; Show failure message 90 | jsr log_message 91 | scrcode PRODUCT, " - Not Found." 92 | .byte 0 93 | .endif ; ::LOG_FAILURE 94 | .endif ; JUMBO_CLOCK_DRIVER 95 | 96 | done: sec ; failure 97 | rts 98 | .endproc 99 | 100 | ; ---------------------------------------------------------------------------- 101 | ; Install clock driver 102 | .proc InstallDriver 103 | 104 | ;; Copy into address at DATETIME vector, update the vector and 105 | ;; update MACHID bits to signal a clock is present. 106 | ptr := $A5 107 | 108 | ;; Update absolute addresses within driver 109 | lda DATETIME+1 110 | sta ptr 111 | clc 112 | adc #(regulk - driver) 113 | sta regulk_addr 114 | lda DATETIME+2 115 | sta ptr+1 116 | adc #0 117 | sta regulk_addr+1 118 | 119 | ;; Copy driver into appropriate bank 120 | lda RWRAM1 121 | lda RWRAM1 122 | ldy #sizeof_driver-1 123 | 124 | loop: lda driver,y 125 | sta (ptr),y 126 | dey 127 | bpl loop 128 | 129 | ;; Set the "Recognizable Clock Card" bit 130 | lda MACHID 131 | ora #$01 132 | sta MACHID 133 | 134 | lda #OPC_JMP_abs 135 | sta DATETIME 136 | 137 | ;; Invoke the driver to init the time 138 | jsr DATETIME 139 | 140 | lda ROMIN2 141 | 142 | .if ::LOG_SUCCESS 143 | ;; Display success message 144 | jsr log_message 145 | scrcode PRODUCT, " - " 146 | .byte 0 147 | 148 | ;; Display the current date 149 | jsr cout_date 150 | .endif ; ::LOG_SUCCESS 151 | 152 | clc ; success 153 | rts ; done! 154 | .endproc 155 | 156 | ; ---------------------------------------------------------------------------- 157 | ; enable slinky registers, set adddress and save byte we intend to trash 158 | .proc SlinkyEnable 159 | lda C8OFF ; not needed on //c, but release $C8xx firmware 160 | lda SLOT4ROM ; enable slinky registers 161 | lda #$08 ; set addr $080000 162 | sta DPTRH 163 | stz DPTRM 164 | stz DPTRL 165 | lda DATA ; read data byte 166 | sta SAVEBYTE ; save it to restore later 167 | rts 168 | .endproc 169 | ; ---------------------------------------------------------------------------- 170 | ; Routine to restore trashed byte in slinky RAM 171 | .proc SlinkyRestore 172 | lda #$08 ; set adddr $080000 173 | sta DPTRH 174 | stz DPTRM 175 | stz DPTRL 176 | lda SAVEBYTE ; get saved byte 177 | sta DATA ; and put it back 178 | lda C8OFF ; not needed on //c, but release $C8xx firmware 179 | rts 180 | .endproc 181 | ; ---------------------------------------------------------------------------- 182 | ; Write 8 bits to clock 183 | .proc ClockWrite8b 184 | ldx #$08 ; set adddr $080000 185 | stx DPTRH 186 | stz DPTRM 187 | : stz DPTRL ; restore low byte to 0 188 | sta DATA ; write byte 189 | lsr a ; next bit into 0 position 190 | dex 191 | bne :- 192 | rts 193 | .endproc 194 | ; ---------------------------------------------------------------------------- 195 | ; unlock the clock by writing the magic bit sequence 196 | .proc ClockUnlock 197 | ldy #$08 198 | : lda unlock,y 199 | jsr ClockWrite8b ; write 8 bits 200 | dey 201 | bne :- 202 | rts 203 | unlock = * - 1 204 | .byte $5c, $a3, $3a, $c5, $5c, $a3, $3a, $c5 205 | .endproc 206 | ; ---------------------------------------------------------------------------- 207 | ; Read 8 bits from the clock 208 | .proc ClockRead8b 209 | ldx #$08 ; set adddr $080000 210 | stz DPTRL 211 | stz DPTRM 212 | stx DPTRH 213 | : pha ; save accumulator 214 | lda DATA ; get data byte 215 | lsr a ; bit 0 into carry 216 | pla ; restore accumulator 217 | ror a ; put read bit into position 218 | dex 219 | bne :- 220 | rts 221 | .endproc 222 | ; ---------------------------------------------------------------------------- 223 | ; read the clock data into memory at CLOCKBUF 224 | ; WARNING: unfixed code never restores byte we trashed 225 | .proc ClockRead 226 | jsr SlinkyEnable 227 | jsr ClockUnlock 228 | ldy #$00 229 | : jsr ClockRead8b 230 | sta CLOCKBUF,y 231 | iny 232 | cpy #$08 ; have we read 8 bytes? 233 | bcc :- ; nope 234 | jsr SlinkyRestore 235 | rts 236 | .endproc 237 | ; ---------------------------------------------------------------------------- 238 | ; validate the DClock data makes sense 239 | ; return carry clear if it does, carry set if it does not 240 | .proc ValidTime 241 | ; validate ms 242 | ldx #$00 243 | ldy #$99 244 | lda CLOCKBUF 245 | jsr CheckBCD 246 | bcs :+ 247 | ; validate seconds 248 | ldx #$00 249 | ldy #$59 250 | lda CLOCKBUF+$01 251 | jsr CheckBCD 252 | bcs :+ 253 | ; validate minutes 254 | ldx #$00 255 | ldy #$59 256 | lda CLOCKBUF+$02 257 | jsr CheckBCD 258 | bcs :+ 259 | ; validate hours 260 | ldx #$00 261 | ldy #$23 262 | lda CLOCKBUF+$03 263 | jsr CheckBCD 264 | bcs :+ 265 | ; validate day of week 266 | ldx #$01 267 | ldy #$07 268 | lda CLOCKBUF+$04 269 | jsr CheckBCD 270 | bcs :+ 271 | ; validate day of month 272 | ldx #$01 273 | ldy #$31 274 | lda CLOCKBUF+$05 275 | jsr CheckBCD 276 | bcs :+ 277 | ; validate month 278 | ldx #$01 279 | ldy #$12 280 | lda CLOCKBUF+$06 281 | jsr CheckBCD 282 | bcs :+ 283 | ; validate year 284 | ldx #$00 285 | ldy #$99 286 | lda CLOCKBUF+$07 287 | jsr CheckBCD 288 | bcs :+ 289 | clc ; all good 290 | rts 291 | : sec ; problem 292 | rts 293 | .endproc 294 | ; ---------------------------------------------------------------------------- 295 | ; Check BCD number in range of [x,y] 296 | ; return carry clear if it is, carry set if it is not 297 | .proc CheckBCD 298 | sed ; decimal mode 299 | stx SCRATCH ; lower bound into scratch 300 | cmp SCRATCH ; compare it 301 | bcc :++ ; fail if out of range 302 | sty SCRATCH ; upper bound into scratch 303 | cmp SCRATCH ; compare it 304 | beq :+ ; OK if equal 305 | bcs :++ ; fail if out of range 306 | : cld ; in range 307 | clc 308 | rts 309 | : cld ; not in range 310 | sec 311 | rts 312 | .endproc 313 | 314 | ; ---------------------------------------------------------------------------- 315 | ; clock driver code inserted into ProDOS 316 | 317 | driver: 318 | lda #$08 ; useless instruction 319 | php 320 | sei 321 | lda SLOT4ROM ; activate slinky registers 322 | ; ($08 from above overwritten) 323 | stz DPTRL ; set slinky address to $08xx00 324 | ldy #$08 ; also counter for unlock bytes 325 | sty DPTRH 326 | lda DATA ; get destroyed byte 327 | ; (slinky now at $08xx01) 328 | pha ; save value on stack 329 | ; unlock dclock registers 330 | regulk_addr := *+1 331 | ubytlp: lda regulk,y ; self-modified 332 | ldx #$08 ; bit counter 333 | ubitlp: stz DPTRL ; reset pointer to $08xx00 334 | sta DATA ; write to $08xx00 335 | lsr a ; next bit into 0 position 336 | dex 337 | bne ubitlp 338 | dey 339 | bne ubytlp 340 | ; now read 64 bits (8 bytes) from dclock 341 | ldx #$08 ; byte counter 342 | rbytlp: ldy #$08 ; bit counter 343 | rbitlp: pha 344 | lda DATA ; data byte 345 | lsr a ; bit 0 into carry 346 | pla 347 | ror a ; carry into bit 7 348 | dey 349 | bne rbitlp 350 | ; got 8 bits now, convert from BCD to binary 351 | pha 352 | and #$0F 353 | sta BCDTMP 354 | pla 355 | and #$F0 356 | lsr a 357 | pha 358 | adc BCDTMP 359 | sta BCDTMP 360 | pla 361 | lsr a 362 | lsr a 363 | adc BCDTMP 364 | ; place in input buffer, which is OK because the ThunderClock driver does this 365 | sta INBUF-1,x 366 | dex 367 | bne rbytlp 368 | ; done copying, now put necessary values into ProDOS time locations 369 | ; copy hours to ProDOS hours 370 | lda INBUF+4 371 | sta TIMEHI 372 | ; copy minutes to ProDOS minutes 373 | lda INBUF+5 374 | sta TIMELO 375 | ; copy month ... 376 | lda INBUF+1 377 | lsr a 378 | ror a 379 | ror a 380 | ror a 381 | ; ... and day of month to ProDOS month/day 382 | ora INBUF+2 383 | sta DATELO 384 | ; copy year and final bit of month to ProDOS year/month 385 | lda INBUF 386 | rol a 387 | sta DATEHI 388 | stz DPTRL ; set slinky back to $08xx00 389 | pla ; get saved byte 390 | sta DATA ; put it back 391 | plp 392 | rts 393 | ; DS1215 unlock sequence (in reverse) 394 | regulk = * - 1 395 | .byte $5C, $A3, $3A, $C5, $5C, $A3, $3A, $C5 396 | 397 | sizeof_driver := * - driver 398 | .assert sizeof_driver <= 125, error, "Clock code must be <= 125 bytes" 399 | 400 | .popcpu 401 | 402 | ;;; ************************************************************ 403 | .ifndef JUMBO_CLOCK_DRIVER 404 | .include "../../inc/driver_postamble.inc" 405 | .endif ; JUMBO_CLOCK_DRIVER 406 | ;;; ************************************************************ 407 | --------------------------------------------------------------------------------