Compare commits

...

26 Commits
v1.6 ... main

Author SHA1 Message Date
Joshua Bell
1ed40ff2dc Actions: Rev a dependency 2024-01-31 20:29:50 -08:00
Joshua Bell
1d6b923783 Actions: Rev a couple dependencies 2024-01-31 20:26:41 -08:00
Joshua Bell
7aeb2e55ad Docs: fix readme link 2024-01-31 20:22:03 -08:00
Joshua Bell
7bbc96924b Add SETUP.SYSTEM and build .SETUP files
This is an alternate approach proposed by Sean Nolan in 1987 which
allows placing the driver files in a subdirectory of the root volume
to avoid clutter and file ordering issues. Only a SETUP.SYSTEM file is
needed at the top level, and the drivers go into a SETUPS/ directory.

All drivers here (except QUIT.SYSTEM and SETUP.SYSTEM itself) have
alternate forms built into the /DRIVERS/SETUPS/ directory as XYZ.SETUP
instead of XYZ.SYSTEM. If you choose to use SETUP.SYSTEM, place these
.SETUP files in your SETUPS/ directory. The naming doesn't matter -
any SYS or BIN file can be used - but this convention makes
distribution easier. These .SETUP files do **NOT** chain to the next
file - that's handled by SETUP.SYSTEM itself.

Resolves #16
2024-01-30 21:16:32 -08:00
Joshua Bell
537d79810b Jumbo: Patch ThunderClock driver for 2023-2028
If ProDOS finds a ThunderClock it installs a built-in driver for it.
The ThunderClock card gives day-of-week but not year. So the driver
uses the day/month/day-of-week to infer the year, using a 7-entry
table. This means the driver gives the wrong year unless it is
reasonably updated.

ProDOS 2.4.2 includes an update to handle 2018-2023 but that's about
to run out. https://github.com/ProDOS-8/ProDOS8-Testing/issues/72

Make the CLOCK.SYSTEM jumbo driver do the extra work of updating the
year table for the ThunderClock driver. This handles old versions of
ProDOS from 1.1 through 2.4.2, and the update handles 2023 through
2028. (In 2027 we can update again to handle through 2032.)
2023-12-04 20:28:25 -08:00
Joshua Bell
477c1f7764 Build: Use common out/ dir 2023-11-12 16:42:11 -08:00
Joshua Bell
b8ef97b42d Build: Fix header include path in clock Makefiles 2023-11-12 13:56:52 -08:00
Joshua Bell
764b4bd8fd ZIPCHIP.SYSTEM - log cache size 2023-11-12 12:46:37 -08:00
Joshua Bell
93e48784b9 Add ZIPCHIP.SYSTEM
This detects a ZIP CHIP and, if present, configures it to slow down
for speaker access, leaving the other settings alone.

In the future maybe there will be a configuration utility to control
the slots, as was included with the ZIP CHIP back in the day.
2023-11-11 14:24:28 -08:00
Joshua Bell
01175cf573 Prevent hang probing for The Cricket! in MAME on IIc/IIc+
In MAME, for the SSC in Slot 2, the STATUS flag never comes back with
ready-to-send, so the probe would hang. Introduce a timer, same as on
the receiving side, and timeout instead of hanging.

Similar to 14e72b7384
2023-10-22 17:08:34 -04:00
Joshua Bell
18a73004c4 The Cricket!: Fix SSC reset for Laser 128EX
The change in b182a53d made resetting/detecting The Cricket! fail on
my Laser 128EX, likely due to startup config of the SSC not being
the same as on an Apple //c. This should be a superset of the change,
but compat testing will be needed.
2023-10-14 19:40:09 -07:00
Joshua Bell
ed2fa6e7d2 No-Slot Clock: Hit PTRIG to slow ZIP/IIc+ accelerator before reading
This appears to improve reliability when reading the NSC on the
IIc+. More data is probably needed before declaring this a really
good solution, but "it works on my machine!"
2023-10-06 22:11:36 -07:00
Joshua Bell
a519d0c619 Cricket: Make SET.TIME/SET.DATETIME time inputs 24-hour by default
The Cricket! can accept both 12-hour (with AM/PM suffix) and 24-hour
times. Unify with the No-Slot Clock UI and prompt for 24-hour.
2023-07-17 08:11:50 -07:00
frankmilliron
b182a53dfa
The Cricket!: fix hang on Total Replay (#19)
* The Cricket!: fix hang on Total Replay

The Cricket reset command sends Total Replay into an endless loop when launched, presumably because of an interrupt situation (TR just does RTI on an interrupt). Toggling the COMMAND and CONTROL settings seems to allow TR to function properly, while also allowing the Cricket initialization code to silence any playing notes.

* The Cricket!: Reset Cricket before probing

Finds the Cricket every single time this way. Occasionally the driver would miss finding it due to it being in a wait state. Sending a reset first fixes that.

* The Cricket!: make sure registers are toggled for TR
2023-07-17 08:11:30 -07:00
frankmilliron
9401723f0d
The Cricket!: further refinements to 'SSC init' (#18)
//c technical reference includes a 'hardware reset' for three of the ACIA registers. Here we reset all three.
2023-07-16 13:30:04 -07:00
Joshua Bell
ec4a0eeb1e The Cricket!: Issue "Reset Cricket" sequence when detecting
This stops any active music playback, which is handy if you did a warm
boot in the middle of playback, and your The Cricket! is stuck playing
the same note constantly but you don't want to power-cycle the device
which will unset the RTC.

c/o @frankmilliron
2023-06-25 21:08:08 -07:00
Joshua Bell
caeb237321 The Cricket!: Reset SSC ACIA before probing/setting
... and don't bother saving/restoring registers during install,
as this will only follow a boot or OS restart.

Suggested by @frankmilliron

Also inhibit interrupts in the SET.XXX utilities for good measure.
2023-06-25 12:06:40 -07:00
Joshua Bell
c01d26042a The Cricket!: Add unified SET.DATETIME util 2023-06-25 11:46:35 -07:00
Joshua Bell
8ca57b2fac NSClock: Incorporate @bobbimanners Ultrawarp bug workaround
For context, see:
https://github.com/bobbimanners/ProDOS-Utils/blob/master/No_Slot_Clock/README.md
2023-06-25 11:37:59 -07:00
Joshua Bell
e706385fe9 No Slot Clock: Add SET.DATETIME utility 2023-06-24 20:10:24 -07:00
frankmilliron
774889ec2e
Improve Cricket! detection on ROM4 //c (#17)
* Improve Cricket! detection on ROM4 //c

* Add PHP/PLP
2023-05-15 18:21:31 -07:00
Joshua Bell
5211dc6296 Add build options to suppress success and/or failure logging 2023-05-01 19:47:10 -07:00
Joshua Bell
ee5fbeda2d Workflows: bump ca65 action to v2 2023-03-02 20:02:25 -08:00
Joshua Bell
d37691dead Jumbo clock driver: Include success logging 2023-01-31 20:01:05 -08:00
Joshua Bell
1ddae4fab7 No Slot Clock: Shave bytes and better comments
* Replace BCD->Binary with smaller routine
* Replace most absolute use of $200-7 with stack
* Remove unneeded sentinel byte at end of unlock sequence

Leaves 9 bytes free in driver.
2023-01-27 18:30:42 -08:00
Joshua Bell
d9e72d3c1e NSC: Probe for Z80 card before probing for NSC to avoid hang
The NSC driver installer starts off by checking each slot, bit-banging
into the card's memory space to try and detect an NSC installed. If a
Z80 card is encountered before the NSC is hit, the Z80 card is
activated, causing the 6502 to halt.

Borrow the Z80 detection routine from A2D's This Apple and verify that
there isn't a Z80 in the slot before we start bit-banging.

Fixes #15
2023-01-01 17:12:21 -08:00
40 changed files with 1955 additions and 164 deletions

View File

@ -13,8 +13,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: a2stuff/build-install-ca65-action@v1
- uses: actions/checkout@v4
- uses: a2stuff/build-install-ca65-action@v2
- uses: a2stuff/build-install-cadius-action@v1
- name: build
@ -25,7 +25,7 @@ jobs:
- name: deploy new version
if: startsWith(github.ref, 'refs/tags/')
uses: ncipollo/release-action@v1.11.2
uses: ncipollo/release-action@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
artifacts: "prodos-drivers.po"

View File

@ -1,9 +1,12 @@
targets := clocks selectors ram.drv util textcolors
targets := clocks selectors accelerators ram.drv setup util textcolors
.PHONY: all $(targets) package
all: $(targets)
export LOG_SUCCESS=1
export LOG_FAILURE=1
# Build all targets
$(targets):
@tput setaf 3 && echo "Building: $@" && tput sgr0

View File

@ -32,6 +32,8 @@ This repo includes the following drivers/modifications:
* ROMX Real-Time Clock
* FujiNet Clock
* A "jumbo" driver that includes all of the above (just called `CLOCK.SYSTEM`)
* Accelerators
* ZIP CHIP configuration (sets the chip to slow on speaker access)
* RAM Disk drivers
* RAMWorks Driver by Glen E. Bredon
* Quit dispatcher/selector (`BYE` routines)
@ -60,6 +62,7 @@ The intent is that you use a tool like Copy II Plus or [Apple II DeskTop](https:
* `FN.CLOCK.SYSTEM` - install FujiNet clock driver, if present
* `DCLOCK.SYSTEM` - install DClock clock driver, if present
* `CRICKET.SYSTEM` - install Cricket! clock driver, if present
* `ZIPCHIP.SYSTEM` - slow the ZIP CHIP on speaker access, if present
* `RAM.DRV.SYSTEM` - install RamWorks RAM disk driver, if present
* `BUHBYE.SYSTEM` - install a customized Quit handler to replace the built-in one
* `PAUSE.SYSTEM` - pause for a moment, so that you can inspect the output of the above
@ -67,3 +70,43 @@ The intent is that you use a tool like Copy II Plus or [Apple II DeskTop](https:
* `BASIC.SYSTEM` - which will not be automatically invoked, but is available to manually invoke
Alternately, you might want to install some drivers then immediately launch into BASIC. In that case, put `BASIC.SYSTEM` after the drivers in place of `QUIT.SYSTEM`.
## Alternate Approach
If you want to keep your volume directory tidier, consider using [SETUP.SYSTEM](./setup/README.md) instead.
# Building
Fetch, build, and install [cc65](http://cc65.github.io/cc65/):
```
git clone https://github.com/cc65/cc65
make -C cc65 && make -C cc65 avail
```
Fetch and build this repo:
```
git clone https://github.com/a2stuff/prodos-drivers
cd prodos-drivers
make
```
To make a disk image, fetch, build and install [Cadius](https://github.com/mach-kernel/cadius):
```
git clone https://github.com/mach-kernel/cadius
make -C cadius && make -C cadius install
```
Then you can:
```
cd prodos-drivers
make && make package
```
This will produce `prodos-drivers.po`, a disk image for use with emulators or tools like [ADTPro](http://adtpro.com/).
Notes:
* 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.

22
accelerators/Makefile Normal file
View File

@ -0,0 +1,22 @@
targets := zipchip
.PHONY: all $(targets)
all: $(targets)
export LOG_SUCCESS
export LOG_FAILURE
# Build all targets
$(targets):
@tput setaf 3 && echo "Building: $@" && tput sgr0
@$(MAKE) -C $@ \
&& (tput setaf 2 && echo "make $@ good" && tput sgr0) \
|| (tput blink && tput setaf 1 && echo "MAKE $@ BAD" && tput sgr0 && false)
# Clean all temporary/target files
clean:
@for dir in $(targets); do \
tput setaf 2 && echo "cleaning $$dir" && tput sgr0; \
$(MAKE) -C $$dir clean; \
done

View File

@ -0,0 +1,46 @@
CAFLAGS = --target apple2enh --list-bytes 0
LDFLAGS = --config apple2-asm.cfg
OUTDIR = ../../out
HEADERS = $(wildcard *.inc) $(wildcard ../inc/*.inc)
TARGETS = \
$(OUTDIR)/zipchip.system.SYS \
$(OUTDIR)/zipchip.setup.SYS
LOG_SUCCESS=1
LOG_FAILURE=1
# For timestamps
MM = $(shell date "+%-m")
DD = $(shell date "+%-d")
YY = $(shell date "+%-y")
DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY) \
-D LOG_SUCCESS=$(LOG_SUCCESS) -D LOG_FAILURE=$(LOG_FAILURE)
XATTR := $(shell command -v xattr 2> /dev/null)
.PHONY: clean all
all: $(OUTDIR) $(TARGETS)
$(OUTDIR):
mkdir -p $(OUTDIR)
clean:
rm -f $(OUTDIR)/*.o
rm -f $(OUTDIR)/*.list
rm -f $(TARGETS)
$(OUTDIR)/%.o: %.s $(HEADERS)
ca65 $(CAFLAGS) $(DEFINES) --listing $(basename $@).list -o $@ $<
$(OUTDIR)/%.setup.o: %.system.s $(HEADERS)
ca65 $(CAFLAGS) $(DEFINES) -D BUILD_SETUP_FILE --listing $(basename $@).list -o $@ $<
$(OUTDIR)/%.BIN $(OUTDIR)/%.SYS: $(OUTDIR)/%.o
ld65 $(LDFLAGS) -o $@ $<
ifdef XATTR
xattr -wx prodos.AuxType '00 20' $@
endif

View File

@ -0,0 +1,179 @@
;;; ZIPCHIP.SYSTEM
;;; Configures the speaker to be temporarily slow
;;; TODO: Add a configuration utility
.setcpu "6502"
.linecont +
.feature string_escapes
.include "apple2.inc"
.include "apple2.mac"
.include "opcodes.inc"
.include "../../inc/apple2.inc"
.include "../../inc/macros.inc"
.include "../../inc/prodos.inc"
.include "../../inc/ascii.inc"
;;; ************************************************************
.include "../../inc/driver_preamble.inc"
;;; ************************************************************
;; From ZIP Chip Manual v1 1987
ZC_REG_LOCK := $C05A
;; Write:
;; $A5 Locks the ZIP CHIP.
;; 4 consecutive $5A writes unlock ZIP CHIP.
;; While unlocked, any write other than $A5 or
;; $5A will initiate an indefinate syncronous [sic]
;; sequence.
kZCLock = $A5
kZCUnlock = $5A
ZC_REG_ENABLE := $C05B
;; Write - Any hex byte written will enable ZIP CHIP
ZC_REG_STATUS := $C05B
;; Read - Read the current status of the following:
;; bit 0 & 1 - Ramsize where
;; RAMSIZE1 RAMSIZE0 SIZE
;; 0 0 8K
;; 0 1 16K
;; 1 0 32K
;; 1 1 64K
;; bit 2 - unused
;; bit 3 - Delay (for memory)
;; 0 = Fast Mode - Delay not in effect
;; 1 = Sync Mode - Delay in effect
;; bit 4 - Disabled/enabled
;; 0 = Chip Enabled
;; 1 = Chip Disabled
;; bit 5 - Paddle fast/normal
;; 0 = Fast Mode
;; 1 = Synchronous Mode (Normal)
;; bit 6 = Cache Updated by data read
;; 0 = No update
;; 1 = Yes cache updated
;; bit 7 = Clock Pulse - 1.0035 milliseconds
;; Edges occur at .50175 milliseconds
ZC_REG_SLOTSPKR := $C05C
;; Read/Write - Slow/Speaker set and read
;; 0 = Set slot/speaker Fast
;; 1 = Set slot/speaker Normal
;; bit 0 - Speaker bit 4 - Slot 4
;; bit 1 - Slot 1 bit 5 - Slot 5
;; bit 2 - Slot 2 bit 6 - Slot 6
;; bit 3 - Slot 3 bit 7 - Slot 7
ZC_REG_SYSSPEED := $C05D
;; Write - Set System Speed
;; bit 0 - unused bit 4 - Clk4/5
;; bit 1 - unused bit 5 - Clk5/6
;; bit 2 - Clk2/3 bit 6 - Clk/2
;; bit 3 - Clk3/4 bit 7 - Clk/4
;; NOTE: bit 6 and bit 7 yield Clk/3
ZC_REG_SYNCOP := $C05E
;; Write - Enable/Disable Synchronous Operation
;; for I/O Devices
;; bit 0 through bit 6 - Not Used
;; bit 7 - Enable/Disable Delay
;; 0 = Enable Delay
;; 1 = Disable and Reset Delay
ZC_REG_SOFTSW := $C05E
;; Read - Read Apple softswitches
;; 0 = False
;; 1 = True
;; bit 0 - ROMRD bit 4 - 80STORE
;; bit 1 - RAMBNK bit 5 - MWR
;; bit 2 - PAGE2 bit 6 - MRD
;; bit 3 - HIRES bit 7 - ALTZP
ZC_REG_PDLBSLC := $C05F
;; Write - Paddle Speed, Bank Switch Language Card
;; bit 0 through bit 5 - Not Used
;; bit 6 - Paddle Set
;; 0 = Disable Paddle Delay
;; 1 = Enable Paddle Delay
;; bit 7 - Language Card Enable/Disable
;; 0 = Enable Cache of Language Card Memory
;; 1 = Disable Cache of Language Card Memory
.undef PRODUCT
.define PRODUCT "ZIP CHIP"
.proc maybe_install_driver
php ; timing sensitive
sei
;; Unlock
lda #kZCUnlock
sta ZC_REG_LOCK
sta ZC_REG_LOCK
sta ZC_REG_LOCK
sta ZC_REG_LOCK
;; ZIP CHIP present?
lda ZC_REG_SLOTSPKR
eor #$FF
sta ZC_REG_SLOTSPKR
cmp ZC_REG_SLOTSPKR
bne no_zip
eor #$FF
sta ZC_REG_SLOTSPKR
cmp ZC_REG_SLOTSPKR
bne no_zip
;; Slow on speaker access
lda ZC_REG_SLOTSPKR
ora #%00000001 ; bit 0 = Speaker
sta ZC_REG_SLOTSPKR
;; Get size
lda ZC_REG_STATUS
and #%00000011
asl
tax
lda size_table,x
sta size
lda size_table+1,x
sta size+1
;; Lock
lda #kZCLock
sta ZC_REG_LOCK
jsr log_message
scrcode PRODUCT, " "
size: .res 2 ; patched with cache size
scrcode "K - Configured."
.byte 0
plp
rts
no_zip:
jsr log_message
scrcode PRODUCT, " - Not Found."
.byte 0
plp
rts
size_table:
scrcode " 8"
scrcode "16"
scrcode "32"
scrcode "64"
.endproc
;;; ************************************************************
.include "../../inc/driver_postamble.inc"
;;; ************************************************************

View File

@ -4,6 +4,9 @@ targets := ns.clock cricket dclock romx fujinet jumbo
all: $(targets)
export LOG_SUCCESS
export LOG_FAILURE
# Build all targets
$(targets):
@tput setaf 3 && echo "Building: $@" && tput sgr0

View File

@ -2,40 +2,55 @@
CAFLAGS = --target apple2enh --list-bytes 0
LDFLAGS = --config apple2-asm.cfg
OUTDIR = out
OUTDIR = ../../out
UTILDIR = $(OUTDIR)/cricket.util
HEADERS = $(wildcard *.inc) $(wildcard ../inc/*.inc)
HEADERS = $(wildcard *.inc) $(wildcard ../../inc/*.inc)
TARGETS = \
$(OUTDIR)/prodos.mod.BIN \
$(UTILDIR)/prodos.mod.BIN \
$(OUTDIR)/cricket.system.SYS \
$(OUTDIR)/test.BIN \
$(OUTDIR)/set.time.BIN \
$(OUTDIR)/set.date.BIN
$(OUTDIR)/cricket.setup.SYS \
$(UTILDIR)/test.BIN \
$(UTILDIR)/set.datetime.BIN \
$(UTILDIR)/set.time.BIN \
$(UTILDIR)/set.date.BIN
LOG_SUCCESS=1
LOG_FAILURE=1
# For timestamps
MM = $(shell date "+%-m")
DD = $(shell date "+%-d")
YY = $(shell date "+%-y")
DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY)
DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY) \
-D LOG_SUCCESS=$(LOG_SUCCESS) -D LOG_FAILURE=$(LOG_FAILURE)
XATTR := $(shell command -v xattr 2> /dev/null)
.PHONY: clean all
all: $(OUTDIR) $(TARGETS)
all: $(OUTDIR) $(UTILDIR) $(TARGETS)
$(OUTDIR):
mkdir -p $(OUTDIR)
$(OUTDIR) $(UTILDIR):
mkdir -p $@
clean:
rm -f $(OUTDIR)/*.o
rm -f $(OUTDIR)/*.list
rm -f $(UTILDIR)/*.o
rm -f $(UTILDIR)/*.list
rm -f $(TARGETS)
$(OUTDIR)/%.o: %.s $(HEADERS)
$(OUTDIR)/%.o $(UTILDIR)/%.o: %.s $(HEADERS)
ca65 $(CAFLAGS) $(DEFINES) --listing $(basename $@).list -o $@ $<
$(OUTDIR)/%.BIN $(OUTDIR)/%.SYS: $(OUTDIR)/%.o
$(OUTDIR)/%.setup.o: %.system.s $(HEADERS)
ca65 $(CAFLAGS) $(DEFINES) -D BUILD_SETUP_FILE --listing $(basename $@).list -o $@ $<
$(OUTDIR)/%.SYS: $(OUTDIR)/%.o
ld65 $(LDFLAGS) -o $@ $<
$(UTILDIR)/%.BIN: $(UTILDIR)/%.o
ld65 $(LDFLAGS) -o $@ $<
ifdef XATTR
xattr -wx prodos.AuxType '00 20' $@

View File

@ -38,9 +38,12 @@ I ended up disassembling both [NS.CLOCK.SYSTEM](../ns.clock/ns.clock.system.s) (
These `BRUN`able files are also built:
* [TEST](test.s) attempts to identify an SSC in Slot 2 and the Cricket via the ID sequence, to test routines.
* [SET.DATETIME](set.datetime.s) sets the Cricket's current date and time.
* [SET.DATE](set.date.s) sets the Cricket's current date.
* [SET.TIME](set.time.s) sets the Cricket's current time.
`CRICKET.SETUP` is for use with [SETUP.SYSTEM](../../setup/README.md)
## Resources
Cricket disks on Asimov:

View File

@ -35,9 +35,8 @@
read_delay_hi = $3 * 3 ; ($300 iterations is normal * 3.6MHz)
.ifndef JUMBO_CLOCK_DRIVER
.undef PRODUCT
.define PRODUCT "Cricket Clock"
.endif ; JUMBO_CLOCK_DRIVER
;;; ============================================================
;;; Ensure there is not a previous clock driver installed.
@ -76,20 +75,21 @@ ssc_not_found:
;; Init SSC and try the "Read Cricket ID code" sequence.
init_ssc:
php
sei
lda COMMAND ; save status of SSC registers
sta saved_command
lda CONTROL
sta saved_control
;; Configure SSC
lda #%00001011 ; no parity/echo/interrupts, RTS low, DTR low
sta COMMAND
lda #%10011110 ; 9600 baud, 8 data bits, 2 stop bits
sta CONTROL
;; Reset the Cricket (stops any playing notes & ensures Cricket is listening)
jsr reset_cricket
jsr reset_cricket ; does it twice in original Cricket driver
;; Read Cricket ID code: 00 ($00)
lda #0
jsr sendbyte
bcs cricket_not_found ; timeout
;; "The Cricket will return a "C" (195, $C3) followed by a
;; version number (in ASCII) and a carriage return (141, $8D)."
@ -114,23 +114,48 @@ digit: cmp #HI('0') ; < '0' ?
cricket_found:
jsr restore_cmd_ctl
plp
jmp install_driver
cricket_not_found:
jsr restore_cmd_ctl
plp
;; fall through...
not_found:
.ifndef JUMBO_CLOCK_DRIVER
.if ::LOG_FAILURE
;; Show failure message
jsr log_message
scrcode PRODUCT, " - Not Found."
.byte 0
.endif ; ::LOG_FAILURE
.endif ; JUMBO_CLOCK_DRIVER
sec ; failure
rts
reset_cricket:
;; Reset SSC
lda #0
sta COMMAND ; hardware reset all Port 2 ACIA registers
sta CONTROL
;; Configure SSC
lda #%00001011 ; no parity/echo/interrupts, RTS low, DTR low
sta COMMAND
lda #%10011110 ; 9600 baud, 8 data bits, 2 stop bits
sta CONTROL
jsr readbyte ; done on original disk
lda #HI(ASCII_CR) ; two carriage returns
jsr sendbyte
lda #HI(ASCII_CR)
jsr sendbyte
lda #HI('!') ; Reset Cricket (everything but time/date)
jsr sendbyte
rts
restore_cmd_ctl:
lda saved_control
sta CONTROL
@ -144,12 +169,33 @@ saved_control: .byte 0
;; Write byte in A
.proc sendbyte
tries := $100 * read_delay_hi
counter := $A5
pha
: lda STATUS
lda #<tries
sta counter
lda #>tries
sta counter+1
check: lda STATUS
and #(1 << 4) ; transmit register empty? (bit 4)
beq :- ; nope, keep waiting
bne ready ; yes, ready to write
dec counter
bne check
dec counter+1
bne check
pla
sec ; failed
rts
ready:
pla
sta TDREG
clc
rts
.endproc
@ -214,7 +260,7 @@ loop: lda driver,y
lda ROMIN2
.ifndef JUMBO_CLOCK_DRIVER
.if ::LOG_SUCCESS
;; Display success message
jsr log_message
scrcode PRODUCT, " - "
@ -222,7 +268,7 @@ loop: lda driver,y
;; Display the current date
jsr cout_date
.endif ; JUMBO_CLOCK_DRIVER
.endif ; ::LOG_SUCCESS
clc ; success
rts ; done!

View File

@ -21,6 +21,15 @@
jsr GETLN2
php
sei
;; Reset SSC
sta KBDSTRB ; Port 2 DSR line connected to KBDSTRB
lda #0
sta COMMAND
sta CONTROL
;; Configure SSC
lda #%00001011 ; no parity/echo/interrupts, RTS low, DTR low
sta COMMAND
@ -43,6 +52,8 @@ loop: lda INPUT_BUFFER,x
cmp #HI(ASCII_CR)
bne loop
plp
rts
.endproc

View File

@ -0,0 +1,144 @@
;;; SET.DATETIME utility for The Cricket!
;;; Prompts for date and time and updates Cricket.
.setcpu "6502"
.linecont +
.feature string_escapes
.include "apple2.inc"
.include "apple2.mac"
.include "../../inc/apple2.inc"
.include "../../inc/macros.inc"
.include "../../inc/ascii.inc"
.org $2000
.proc main
;; --------------------------------------------------
;; Date
jsr zstrout
scrcode "\rDate: WWW MM/DD/YY\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08"
.byte 0
jsr GETLN2
php
sei
;; Reset SSC
sta KBDSTRB ; Port 2 DSR line connected to KBDSTRB
lda #0
sta COMMAND
sta CONTROL
;; Configure SSC
lda #%00001011 ; no parity/echo/interrupts, RTS low, DTR low
sta COMMAND
lda #%10011110 ; 9600 baud, 8 data bits, 2 stop bits
sta CONTROL
;; Clock Commands
;; Set Date "SD WWW MM/DD/YY"
lda #HI('S')
jsr sendbyte
lda #HI('D')
jsr sendbyte
lda #HI(' ')
jsr sendbyte
ldx #0
: lda INPUT_BUFFER,x
jsr sendbyte
inx
cmp #HI(ASCII_CR)
bne :-
plp
;; --------------------------------------------------
;; Time
jsr zstrout
scrcode "\rTime: HH:MM:SS\x08\x08\x08\x08\x08\x08\x08\x08"
.byte 0
jsr GETLN2
php
sei
;; Reset SSC
sta KBDSTRB ; Port 2 DSR line connected to KBDSTRB
lda #0
sta COMMAND
sta CONTROL
;; Configure SSC
lda #%00001011 ; no parity/echo/interrupts, RTS low, DTR low
sta COMMAND
lda #%10011110 ; 9600 baud, 8 data bits, 2 stop bits
sta CONTROL
;; Clock Commands
;; Set Time "ST HH:MM:SS"
lda #HI('S')
jsr sendbyte
lda #HI('T')
jsr sendbyte
lda #HI(' ')
jsr sendbyte
ldx #0
: lda INPUT_BUFFER,x
jsr sendbyte
inx
cmp #HI(ASCII_CR)
bne :-
plp
rts
.endproc
;; Write byte in A to SSC
.proc sendbyte
pha
: lda STATUS
and #(1 << 4) ; transmit register empty? (bit 4)
beq :- ; nope, keep waiting
pla
sta TDREG
rts
.endproc
;;; ------------------------------------------------------------
;;; Output a high-ascii, null-terminated string.
;;; String immediately follows the JSR.
.proc zstrout
ptr := $A5
pla ; read address from stack
sta ptr
pla
sta ptr+1
bne skip ; always (since data not on ZP)
next: jsr COUT
skip: inc ptr
bne :+
inc ptr+1
: ldy #0
lda (ptr),y
bne next
lda ptr+1 ; restore address to stack
pha
lda ptr
pha
rts
.endproc

View File

@ -16,11 +16,20 @@
.proc main
jsr zstrout
scrcode "\rTime: HH:MM:SS XM\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08"
scrcode "\rTime: HH:MM:SS\x08\x08\x08\x08\x08\x08\x08\x08"
.byte 0
jsr GETLN2
php
sei
;; Reset SSC
sta KBDSTRB ; Port 2 DSR line connected to KBDSTRB
lda #0
sta COMMAND
sta CONTROL
;; Configure SSC
lda #%00001011 ; no parity/echo/interrupts, RTS low, DTR low
sta COMMAND
@ -28,7 +37,7 @@
sta CONTROL
;; Clock Commands
;; Set Time "ST HH:MM:SS:XM"
;; Set Time "ST HH:MM:SS"
lda #HI('S')
jsr sendbyte
lda #HI('T')
@ -43,6 +52,8 @@ loop: lda INPUT_BUFFER,x
cmp #HI(ASCII_CR)
bne loop
plp
rts
.endproc

View File

@ -2,18 +2,23 @@
CAFLAGS = --target apple2enh --list-bytes 0
LDFLAGS = --config apple2-asm.cfg
OUTDIR = out
OUTDIR = ../../out
HEADERS = $(wildcard *.inc) $(wildcard ../inc/*.inc)
HEADERS = $(wildcard *.inc) $(wildcard ../../inc/*.inc)
TARGETS = \
$(OUTDIR)/dclock.system.SYS
$(OUTDIR)/dclock.system.SYS \
$(OUTDIR)/dclock.setup.SYS
LOG_SUCCESS=1
LOG_FAILURE=1
# For timestamps
MM = $(shell date "+%-m")
DD = $(shell date "+%-d")
YY = $(shell date "+%-y")
DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY)
DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY) \
-D LOG_SUCCESS=$(LOG_SUCCESS) -D LOG_FAILURE=$(LOG_FAILURE)
XATTR := $(shell command -v xattr 2> /dev/null)
@ -31,6 +36,9 @@ clean:
$(OUTDIR)/%.o: %.s $(HEADERS)
ca65 $(CAFLAGS) $(DEFINES) --listing $(basename $@).list -o $@ $<
$(OUTDIR)/%.setup.o: %.system.s $(HEADERS)
ca65 $(CAFLAGS) $(DEFINES) -D BUILD_SETUP_FILE --listing $(basename $@).list -o $@ $<
$(OUTDIR)/%.SYS: $(OUTDIR)/%.o
ld65 $(LDFLAGS) -o $@ $<
ifdef XATTR

View File

@ -11,3 +11,5 @@ Like other drivers here, this one will:
* Only attempts detection if the system is a an Apple IIc
* If detected, installs into ProDOS directly, following Technical Reference Manual requirements.
* Chains to the next `.SYSTEM` file in the directory.
`DCLOCK.SETUP` is for use with [SETUP.SYSTEM](../../setup/README.md).

View File

@ -56,9 +56,8 @@ DATA := SLOT4IO+3 ; Slinky data byte
;;;
;;; ============================================================
.ifndef JUMBO_CLOCK_DRIVER
.undef PRODUCT
.define PRODUCT "DClock"
.endif ; JUMBO_CLOCK_DRIVER
;;; ============================================================
;;; Ensure there is not a previous clock driver installed.
@ -86,10 +85,12 @@ DATA := SLOT4IO+3 ; Slinky data byte
bcc InstallDriver
.ifndef JUMBO_CLOCK_DRIVER
.if ::LOG_FAILURE
;; Show failure message
jsr log_message
scrcode PRODUCT, " - Not Found."
.byte 0
.endif ; ::LOG_FAILURE
.endif ; JUMBO_CLOCK_DRIVER
done: sec ; failure
@ -138,7 +139,7 @@ loop: lda driver,y
lda ROMIN2
.ifndef JUMBO_CLOCK_DRIVER
.if ::LOG_SUCCESS
;; Display success message
jsr log_message
scrcode PRODUCT, " - "
@ -146,7 +147,7 @@ loop: lda driver,y
;; Display the current date
jsr cout_date
.endif ; JUMBO_CLOCK_DRIVER
.endif ; ::LOG_SUCCESS
clc ; success
rts ; done!

View File

@ -2,18 +2,23 @@
CAFLAGS = --target apple2enh --list-bytes 0
LDFLAGS = --config apple2-asm.cfg
OUTDIR = out
OUTDIR = ../../out
HEADERS = $(wildcard *.inc) $(wildcard ../inc/*.inc)
HEADERS = $(wildcard *.inc) $(wildcard ../../inc/*.inc)
TARGETS = \
$(OUTDIR)/fn.clock.system.SYS
$(OUTDIR)/fn.clock.system.SYS \
$(OUTDIR)/fn.clock.setup.SYS
LOG_SUCCESS=1
LOG_FAILURE=1
# For timestamps
MM = $(shell date "+%-m")
DD = $(shell date "+%-d")
YY = $(shell date "+%-y")
DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY)
DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY) \
-D LOG_SUCCESS=$(LOG_SUCCESS) -D LOG_FAILURE=$(LOG_FAILURE)
XATTR := $(shell command -v xattr 2> /dev/null)
@ -31,6 +36,9 @@ clean:
$(OUTDIR)/%.o: %.s $(HEADERS)
ca65 $(CAFLAGS) $(DEFINES) --listing $(basename $@).list -o $@ $<
$(OUTDIR)/%.setup.o: %.system.s $(HEADERS)
ca65 $(CAFLAGS) $(DEFINES) -D BUILD_SETUP_FILE --listing $(basename $@).list -o $@ $<
$(OUTDIR)/%.BIN $(OUTDIR)/%.SYS: $(OUTDIR)/%.o
ld65 $(LDFLAGS) -o $@ $<
ifdef XATTR

View File

@ -4,6 +4,4 @@
This driver is an adaptation of the other drivers in https://github.com/a2stuff/prodos-drivers
`FN.CLOCK.SETUP` is for use with [SETUP.SYSTEM](../../setup/README.md).

View File

@ -32,9 +32,8 @@ FN_CLOCK_DEVICE_TYPE := $13 ; As defined on the Fujinet firmware
;;;
;;; ============================================================
.ifndef JUMBO_CLOCK_DRIVER
.undef PRODUCT
.define PRODUCT "Fujinet Clock"
.endif ; JUMBO_CLOCK_DRIVER
;;; ============================================================
;;; Ensure there is not a previous clock driver installed.
@ -122,10 +121,12 @@ found:
not_found:
.ifndef JUMBO_CLOCK_DRIVER
.if ::LOG_FAILURE
;; Show failure message
jsr log_message
scrcode PRODUCT, " - Not Found."
.byte 0
.endif ; ::LOG_FAILURE
.endif ; JUMBO_CLOCK_DRIVER
sec ; failure
@ -178,7 +179,7 @@ loop: lda driver,y
lda ROMIN2
.ifndef JUMBO_CLOCK_DRIVER
.if ::LOG_SUCCESS
;; Display success message
jsr log_message
scrcode PRODUCT, " - "
@ -186,7 +187,7 @@ loop: lda driver,y
;; Display the current date
jsr cout_date
.endif ; JUMBO_CLOCK_DRIVER
.endif ; ::LOG_SUCCESS
clc ; success
rts ; done!

View File

@ -2,9 +2,9 @@
CAFLAGS = --target apple2enh --list-bytes 0
LDFLAGS = --config apple2-asm.cfg
OUTDIR = out
OUTDIR = ../../out
HEADERS = $(wildcard *.inc) $(wildcard ../inc/*.inc) \
HEADERS = $(wildcard *.inc) $(wildcard ../../inc/*.inc) \
../ns.clock/ns.clock.system.s \
../romx/romxrtc.system.s \
../dclock/dclock.system.s \
@ -12,15 +12,19 @@ HEADERS = $(wildcard *.inc) $(wildcard ../inc/*.inc) \
../fujinet/smartport.inc \
../cricket/cricket.system.s
TARGETS = \
$(OUTDIR)/clock.system.SYS
$(OUTDIR)/clock.system.SYS \
$(OUTDIR)/clock.setup.SYS
LOG_SUCCESS=1
LOG_FAILURE=1
# For timestamps
MM = $(shell date "+%-m")
DD = $(shell date "+%-d")
YY = $(shell date "+%-y")
DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY)
DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY) \
-D LOG_SUCCESS=$(LOG_SUCCESS) -D LOG_FAILURE=$(LOG_FAILURE)
XATTR := $(shell command -v xattr 2> /dev/null)
@ -38,6 +42,9 @@ clean:
$(OUTDIR)/%.o: %.s $(HEADERS)
ca65 $(CAFLAGS) $(DEFINES) --listing $(basename $@).list -o $@ $<
$(OUTDIR)/%.setup.o: %.system.s $(HEADERS)
ca65 $(CAFLAGS) $(DEFINES) -D BUILD_SETUP_FILE --listing $(basename $@).list -o $@ $<
$(OUTDIR)/%.SYS: $(OUTDIR)/%.o
ld65 $(LDFLAGS) -o $@ $<
ifdef XATTR

View File

@ -10,4 +10,8 @@ The drivers are (in order):
* DClock
* Cricket!
The installer is silent - no output is shown on either failure or success.
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.
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.
`CLOCK.SETUP` is for use with [SETUP.SYSTEM](../../setup/README.md).

View File

@ -44,12 +44,13 @@
;;;
;;; ============================================================
.undef PRODUCT
.define PRODUCT "Jumbo Clock Driver"
.proc maybe_install_driver
lda MACHID
and #$01 ; existing clock card?
bne ret
bne check_thunderclock
jsr ns_clock::maybe_install_driver
bcc ret
@ -69,6 +70,91 @@
ret: rts
.endproc
.proc check_thunderclock
;; Look for Thunderclock year table
bit RWRAM1
bit RWRAM1
lda #<table_1982
ldx #>table_1982
jsr check_sig
beq update_table
lda #<table_1986
ldx #>table_1986
jsr check_sig
beq update_table
lda #<table_1993
ldx #>table_1993
jsr check_sig
beq update_table
lda #<table_2018
ldx #>table_2018
jsr check_sig
beq update_table
;; Table not found - we have a clock but don't
;; know what it is, so don't log anything.
bit ROMIN2
rts
;; ----------------------------------------
;; Copy the latest table into place
update_table:
ldx #SIG_LEN-1
: lda table_2023,x
sta SIG_ADDR,x
dex
bpl :-
bit ROMIN2
.if ::LOG_SUCCESS
;; Display success message, to confirm table updates.
jsr log_message
scrcode "ThunderClock - "
.byte 0
;; Display the current date
jsr cout_date
.endif ; ::LOG_SUCCESS
rts
;; ----------------------------------------
check_sig:
ptr := $06
sta ptr
stx ptr+1
ldy #SIG_LEN-1
: lda (ptr),y
cmp SIG_ADDR,y
bne :+ ; Z=0 for no match
dey
bpl :-
iny ; Z=1 for match
: rts
SIG_LEN = 7
SIG_ADDR := $D7B8
table_1982: ; ProDOS 1.1.1
.byte $54, $54, $53, $52, $57, $56, $55
table_1986: ; ProDOS 1.3 - 1.9
.byte $5A, $59, $58, $58, $57, $56, $5B
table_1993: ; ProDOS 2.0.3
.byte $60, $5F, $5E, $5D, $62, $61, $60
table_2018: ; ProDOS 2.4.2
.byte $12, $17, $16, $15, $14, $14, $13
table_2023:
.byte $18, $17, $1C, $1B, $1A, $19, $18
.endproc
;;; ************************************************************
.include "../../inc/driver_postamble.inc"

View File

@ -2,37 +2,52 @@
CAFLAGS = --target apple2enh --list-bytes 0
LDFLAGS = --config apple2-asm.cfg
OUTDIR = out
OUTDIR = ../../out
UTILDIR = $(OUTDIR)/nsclock.util
HEADERS = $(wildcard *.inc) $(wildcard ../inc/*.inc)
HEADERS = $(wildcard *.inc) $(wildcard ../../inc/*.inc)
TARGETS = \
$(OUTDIR)/ns.clock.system.SYS
$(OUTDIR)/ns.clock.system.SYS \
$(OUTDIR)/ns.clock.setup.SYS \
$(UTILDIR)/set.datetime.BIN
LOG_SUCCESS=1
LOG_FAILURE=1
# For timestamps
MM = $(shell date "+%-m")
DD = $(shell date "+%-d")
YY = $(shell date "+%-y")
DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY)
DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY) \
-D LOG_SUCCESS=$(LOG_SUCCESS) -D LOG_FAILURE=$(LOG_FAILURE)
XATTR := $(shell command -v xattr 2> /dev/null)
.PHONY: clean all
all: $(OUTDIR) $(TARGETS)
all: $(OUTDIR) $(UTILDIR) $(TARGETS)
$(OUTDIR):
mkdir -p $(OUTDIR)
$(OUTDIR) $(UTILDIR):
mkdir -p $@
clean:
rm -f $(OUTDIR)/*.o
rm -f $(OUTDIR)/*.list
rm -f $(UTILDIR)/*.o
rm -f $(UTILDIR)/*.list
rm -f $(TARGETS)
$(OUTDIR)/%.o: %.s $(HEADERS)
$(OUTDIR)/%.o $(UTILDIR)/%.o: %.s $(HEADERS)
ca65 $(CAFLAGS) $(DEFINES) --listing $(basename $@).list -o $@ $<
$(OUTDIR)/%.setup.o: %.system.s $(HEADERS)
ca65 $(CAFLAGS) $(DEFINES) -D BUILD_SETUP_FILE --listing $(basename $@).list -o $@ $<
$(OUTDIR)/%.SYS: $(OUTDIR)/%.o
ld65 $(LDFLAGS) -o $@ $<
$(UTILDIR)/%.BIN: $(UTILDIR)/%.o
ld65 $(LDFLAGS) -o $@ $<
ifdef XATTR
xattr -wx prodos.AuxType '00 20' $@
endif

View File

@ -7,3 +7,10 @@ Adapted from `NS.CLOCK.SYSTEM` (by "CAP"), with these changes:
* Is less chatty so you can have multiple clock drivers, e.g. if you use the same hard disk image across different hardware configurations
* Uses file I/O rather than block I/O for chaining
* Does not hard-code driver file name
## Other Utilities
These `BRUN`able files are also built:
* [SET.DATETIME](set.datetime.s) sets the No Slot Clock date/time.
`NS.CLOCK.SETUP` is for use with [SETUP.SYSTEM](../../setup/README.md).

View File

@ -31,9 +31,8 @@
;;;
;;; ============================================================
.ifndef JUMBO_CLOCK_DRIVER
.undef PRODUCT
.define PRODUCT "No-Slot Clock"
.endif ; JUMBO_CLOCK_DRIVER
;;; ============================================================
;;; Ensure there is not a previous clock driver installed.
@ -71,6 +70,11 @@
lda #3 ; treat slot 0 as slot 3
sloop: ora #$C0 ; A=$Cs
pha
jsr DetectZ80
pla ; A=$Cs
bcs next ; Z80 present, skip this slot
sta st1+2
rloop: sta ld1+2
sta ld2+2
@ -111,14 +115,14 @@ next: inc slot
bne not_found
;; Not found in slot ROM, try main ROMs ???
lda #>$C015
lda #>$C015 ; $C015 = RDCXROM (internal or slot ROM?)
ldy #<$C015
sta ld4+2
sty ld4+1
ldy #$07
ldy #$07 ; $C007 = INTCXROM (read internal ROM)
sta st1+2
sty st1+1
dey
dey ; $C006 = SLOTCXROM (read slot ROM)
sta st4+2
sty st4+1
lda #>$C800
@ -133,10 +137,12 @@ not_found:
bpl :-
.ifndef JUMBO_CLOCK_DRIVER
.if ::LOG_FAILURE
;; Show failure message
jsr log_message
scrcode PRODUCT, " - Not Found."
.byte 0
.endif ; ::LOG_FAILURE
.endif ; JUMBO_CLOCK_DRIVER
sec ; failure
@ -189,7 +195,7 @@ loop: lda driver,y
lda ROMIN2
.ifndef JUMBO_CLOCK_DRIVER
.if ::LOG_SUCCESS
;; Display success message
jsr log_message
scrcode PRODUCT, " - "
@ -197,12 +203,74 @@ loop: lda driver,y
;; Display the current date
jsr cout_date
.endif ; JUMBO_CLOCK_DRIVER
.endif ; ::LOG_SUCCESS
clc ; success
rts ; done!
.endproc
;;; ------------------------------------------------------------
;;; Detect Z80
;;; ------------------------------------------------------------
;;; This routine gets swapped into $0FFD for execution
.proc Z80Routine
target := $0FFD
;; .org $FFFD
patch := *+2
.byte $32, $00, $e0 ; ld ($Es00),a ; s=slot being probed turn off Z80, next PC is $0000
.byte $3e, $01 ; ld a,$01
.byte $32, $08, $00 ; ld (flag),a
.byte $c3, $fd, $ff ; jp $FFFD
flag := *
.byte $00 ; flag: .db $00
.endproc
.assert Z80Routine > Z80Routine::target + .sizeof(Z80Routine), error, "Z80 collision"
;;; Input: A = $Cn where n = slot number
;;; Output: C=1 if Z80 found in slot
.proc DetectZ80
;; Location to poke to invoke Z80
sta store+1
;; Convert $Cn to $En, update Z80 code
ora #$E0
sta Z80Routine::patch
;; Clear detection flag
copy #0, Z80Routine::flag
;; Put routine in place
jsr SwapRoutine
;; Try to invoke Z80
php
sei
store := *+1
sta $C000 ; self-modified
plp
;; Restore memory
jsr SwapRoutine
;; Flag will be set to 1 by routine if Z80 was present.
lda Z80Routine::flag
ror ; move flag into carry
rts
.proc SwapRoutine
ldx #.sizeof(Z80Routine)-1
: ldy Z80Routine::target,x
lda Z80Routine,x
sta Z80Routine::target,x
tya
sta Z80Routine,x
dex
bpl :-
rts
.endproc
.endproc
;;; ============================================================
;;; NSC driver - modified as needed and copied into ProDOS
;;; ============================================================
@ -210,83 +278,97 @@ loop: lda driver,y
driver:
php
sei
ld4: lda $CFFF ; self-modified
lda PTRIG ; Slow ZIP, IIc+ accelerator, etc
lda $C00B ; Ultrawarp bug workaround c/o @bobbimanners
ld4: lda $CFFF ; self-modified ($CFFF or RDCXROM)
pha
st1: sta $C300 ; self-modified
ld1: lda $C304 ; self-modified
st1: sta $C300 ; self-modified ($Cn00 or INTCXROM)
ld1: lda $C304 ; self-modified ($Cn04)
ldx #8
;; --------------------------------------------------
;; Unlock the NSC by bit-banging.
uloop:
unlock_addr := *+1
lda unlock-1,x ; self-modified
lda unlock-1,x ; self-modified (during relocation)
sec
ror a ; a bit at a time
: pha
lda #0
rol a
tay
ld2: lda $C300,y ; self-modified
ld2: lda $C300,y ; self-modified ($Cn00)
pla
lsr a
bne :-
dex
bne uloop
;; Read 8 bytes * 8 bits of clock data into $200...$207
;; --------------------------------------------------
;; Read 8 bytes * 8 bits of clock data, push onto stack
tmp := $200
ldx #8
bloop: ldy #8
st2:
: lda $C304 ; self-modified
: lda $C304 ; self-modified ($Cn04)
ror a
ror $01FF,x
ror tmp
dey
bne :-
lda $01FF,x ; got 8 bits
lsr a ; BCD to binary
lsr a ; shift out tens
lsr a
lsr a
tay
beq donebcd
lda $01FF,x
and #$0F ; mask out units
clc
: adc #10 ; and add tens as needed
dey
bne :-
sta $01FF,x
donebcd:
;; BCD to Binary - slow but tiny
lda tmp ; A = value
ldy #$FF ; result = -1
sec
sed
: iny ; result += 1
sbc #1 ; value -= 1
bcs :-
cld
tya ; A = result
;; Push to stack
pha
dex
bne bloop
;; Now $200...$207 is y/m/d/w/H/M/S/f
;; --------------------------------------------------
;; Now stack has y/m/d/w/H/M/S/F
;; Update ProDOS date/time.
lda $0204 ; hour
sta TIMELO+1
pla ; year
sta DATELO+1
lda $0205 ; minute
sta TIMELO
pla ; month
asl
asl
asl
asl
asl
sta DATELO
rol DATELO+1
lda $0201 ; month
asl a
asl a
asl a
asl a
asl a
ora $0202 ; day
pla ; day
ora DATELO
sta DATELO
lda $0200 ; year
rol a
sta DATELO+1
pla ; skip week
pla ; hour
sta TIMELO+1
pla ; minute
sta TIMELO
pla ; skip seconds
pla ; skip fraction
;; --------------------------------------------------
;; Finish up
pla
bmi done
st4: sta $CFFF ; self-modified
st4: sta $CFFF ; self-modified ($CFFF or SLOTCXROM)
done: plp
rts
@ -294,12 +376,10 @@ unlock:
;; NSC unlock sequence
.byte $5C, $A3, $3A, $C5
.byte $5C, $A3, $3A, $C5
.byte $00
sizeof_driver := * - driver
.assert sizeof_driver <= 125, error, "Clock code must be <= 125 bytes"
;;; ************************************************************
.ifndef JUMBO_CLOCK_DRIVER
.include "../../inc/driver_postamble.inc"

View File

@ -0,0 +1,581 @@
.setcpu "6502"
.linecont +
.feature string_escapes
.include "apple2.inc"
.include "apple2.mac"
.include "opcodes.inc"
.include "../../inc/apple2.inc"
.include "../../inc/macros.inc"
.include "../../inc/prodos.inc"
;;; ------------------------------------------------------------
.define PRODUCT "No-Slot Clock"
;;; ------------------------------------------------------------
.org $2000
.proc main
jsr detect_nsc
bcc :+
rts
:
;; --------------------------------------------------
;; Prompt for Date
date:
jsr zstrout
scrcode "\rDate: WWW MM/DD/YY\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08"
.byte 0
jsr GETLN2
lda INPUT_BUFFER+4
jsr shift_into_tmp
lda INPUT_BUFFER+5
jsr shift_into_tmp
sta set_month
jsr bcd_to_binary
cmp #13
bcs date
lda INPUT_BUFFER+7
jsr shift_into_tmp
lda INPUT_BUFFER+8
jsr shift_into_tmp
sta set_date
jsr bcd_to_binary
cmp #32
bcs date
lda INPUT_BUFFER+10
jsr shift_into_tmp
lda INPUT_BUFFER+11
jsr shift_into_tmp
sta set_year
ldx #0
ldy #1
dow_loop:
CHAR_MASK = $5F ; clear high bit and force uppercase
lda INPUT_BUFFER+0
and #CHAR_MASK
cmp wkdays,x
bne next
lda INPUT_BUFFER+1
and #CHAR_MASK
cmp wkdays+1,x
bne next
lda INPUT_BUFFER+2
and #CHAR_MASK
cmp wkdays+2,x
bne next
sty set_dow
jmp time
next: inx
inx
inx
iny
cpy #8
bcc dow_loop
jmp date
;; --------------------------------------------------
;; Prompt for Time
time:
jsr zstrout
scrcode "\rTime: HH:MM:SS\x08\x08\x08\x08\x08\x08\x08\x08"
.byte 0
jsr GETLN2
lda INPUT_BUFFER+0
jsr shift_into_tmp
lda INPUT_BUFFER+1
jsr shift_into_tmp
sta set_hours
jsr bcd_to_binary
cmp #24
bcs time
lda INPUT_BUFFER+3
jsr shift_into_tmp
lda INPUT_BUFFER+4
jsr shift_into_tmp
sta set_minutes
jsr bcd_to_binary
cmp #60
bcs time
lda INPUT_BUFFER+6
jsr shift_into_tmp
lda INPUT_BUFFER+7
jsr shift_into_tmp
sta set_seconds
jsr bcd_to_binary
cmp #60
bcs time
;; --------------------------------------------------
;; Set NSC
jmp set_datetime
;;; --------------------------------------------------
bcd_to_binary:
ldy #$FF ; result = -1
sec
sed
: iny ; result += 1
sbc #1 ; value -= 1
bcs :-
cld
tya ; A = result
rts
;;; --------------------------------------------------
shift_into_tmp:
pha
lda tmp
asl
asl
asl
asl
sta tmp
pla
and #%00001111
ora tmp
sta tmp
rts
tmp: .byte 0
.endproc
;;; ------------------------------------------------------------
set_year: .byte 0
set_month: .byte 0
set_date: .byte 0
set_dow: .byte 0
set_hours: .byte 0
set_minutes: .byte 0
set_seconds: .byte 0
set_hundredths: .byte 0
wkdays: .byte "MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"
;;; ------------------------------------------------------------
.proc detect_nsc
;; Preserve date/time
ldy #3 ; copy 4 bytes
: lda DATELO,y
sta saved,y
dey
bpl :-
;; Check slot ROMs
lda #>$CFFF
ldy #<$CFFF
sta ld4+2
sty ld4+1
sta st4+2
sty st4+1
lda #0
sta slot
lda #3 ; treat slot 0 as slot 3
sloop: ora #$C0 ; A=$Cs
pha
jsr DetectZ80
pla ; A=$Cs
bcs next ; Z80 present, skip this slot
sta st1+2
rloop: sta ld1+2
sta ld2+2
sta st2+2
lda #3 ; 3 tries - need valid results each time
sta tries
try: jsr driver ; try reading date/time
lda DATELO+1 ; check result
ror a
lda DATELO
rol a
rol a
rol a
rol a
and #$0F
beq next
cmp #13 ; month
bcs next
lda DATELO
and #$1F
beq next
cmp #32 ; day
bcs next
lda TIMELO+1
cmp #24 ; hours
bcs next
lda TIMELO
cmp #60 ; minutes
bcs next
dec tries
bne try
beq found
next: inc slot
lda slot
cmp #8
bcc sloop ; next slot
bne not_found
;; Not found in slot ROM, try main ROMs ???
lda #>$C015 ; $C015 = RDCXROM (internal or slot ROM?)
ldy #<$C015
sta ld4+2
sty ld4+1
ldy #$07 ; $C007 = INTCXROM (read internal ROM)
sta st1+2
sty st1+1
dey ; $C006 = SLOTCXROM (read slot ROM)
sta st4+2
sty st4+1
lda #>$C800
bne rloop
;; Restore date/time
not_found:
ldy #3
: lda saved,y
sta DATELO,y
dey
bpl :-
;; Show failure message
jsr zstrout
scrcode PRODUCT, " - Not Found."
.byte 0
sec ; failure
rts
found:
clc ; success
rts
saved: .byte 0, 0, 0, 0
tries: .byte 3
slot: .byte 0
.endproc
;;; ------------------------------------------------------------
;;; Detect Z80
;;; ------------------------------------------------------------
;;; This routine gets swapped into $0FFD for execution
.proc Z80Routine
target := $0FFD
;; .org $FFFD
patch := *+2
.byte $32, $00, $e0 ; ld ($Es00),a ; s=slot being probed turn off Z80, next PC is $0000
.byte $3e, $01 ; ld a,$01
.byte $32, $08, $00 ; ld (flag),a
.byte $c3, $fd, $ff ; jp $FFFD
flag := *
.byte $00 ; flag: .db $00
.endproc
.assert Z80Routine > Z80Routine::target + .sizeof(Z80Routine), error, "Z80 collision"
;;; Input: A = $Cn where n = slot number
;;; Output: C=1 if Z80 found in slot
.proc DetectZ80
;; Location to poke to invoke Z80
sta store+1
;; Convert $Cn to $En, update Z80 code
ora #$E0
sta Z80Routine::patch
;; Clear detection flag
copy #0, Z80Routine::flag
;; Put routine in place
jsr SwapRoutine
;; Try to invoke Z80
php
sei
store := *+1
sta $C000 ; self-modified
plp
;; Restore memory
jsr SwapRoutine
;; Flag will be set to 1 by routine if Z80 was present.
lda Z80Routine::flag
ror ; move flag into carry
rts
.proc SwapRoutine
ldx #.sizeof(Z80Routine)-1
: ldy Z80Routine::target,x
lda Z80Routine,x
sta Z80Routine::target,x
tya
sta Z80Routine,x
dex
bpl :-
rts
.endproc
.endproc
;;; ============================================================
;;; NSC driver - modified as needed and copied into ProDOS
;;; ============================================================
driver:
php
sei
lda $C00B ; Ultrawarp bug workaround c/o @bobbimanners
ld4: lda $CFFF ; self-modified ($CFFF or RDCXROM)
pha
st1: sta $C300 ; self-modified ($Cn00 or INTCXROM)
ld1: lda $C304 ; self-modified ($Cn04)
ldx #8
;; --------------------------------------------------
;; Unlock the NSC by bit-banging.
uloop:
unlock_addr := *+1
lda unlock-1,x ; self-modified (during relocation)
sec
ror a ; a bit at a time
: pha
lda #0
rol a
tay
ld2: lda $C300,y ; self-modified ($Cn00)
pla
lsr a
bne :-
dex
bne uloop
;; --------------------------------------------------
;; Read 8 bytes * 8 bits of clock data, push onto stack
tmp := $200
ldx #8
bloop: ldy #8
st2:
: lda $C304 ; self-modified ($Cn04)
ror a
ror tmp
dey
bne :-
;; BCD to Binary - slow but tiny
lda tmp ; A = value
ldy #$FF ; result = -1
sec
sed
: iny ; result += 1
sbc #1 ; value -= 1
bcs :-
cld
tya ; A = result
;; Push to stack
pha
dex
bne bloop
;; --------------------------------------------------
;; Now stack has y/m/d/w/H/M/S/F
pla ; year
sta DATELO+1
pla ; month
asl
asl
asl
asl
asl
sta DATELO
rol DATELO+1
pla ; day
ora DATELO
sta DATELO
pla ; skip week
pla ; hour
sta TIMELO+1
pla ; minute
sta TIMELO
pla ; skip seconds
pla ; skip fraction
;; --------------------------------------------------
;; Finish up
pla
bmi done
st4: sta $CFFF ; self-modified ($CFFF or SLOTCXROM)
done: plp
rts
unlock:
;; NSC unlock sequence
.byte $5C, $A3, $3A, $C5
.byte $5C, $A3, $3A, $C5
sizeof_driver := * - driver
.assert sizeof_driver <= 125, error, "Clock code must be <= 125 bytes"
;;; ============================================================
.proc set_datetime
jsr patch_from_driver
php
sei
lda $C00B ; Ultrawarp bug workaround c/o @bobbimanners
ld4: lda $CFFF ; self-modified ($CFFF or RDCXROM)
pha
st1: sta $C300 ; self-modified ($Cn00 or INTCXROM)
ld1: lda $C304 ; self-modified ($Cn04)
ldx #8
;; --------------------------------------------------
;; Unlock the NSC by bit-banging.
uloop:
unlock_addr := *+1
lda unlock-1,x ; self-modified (during relocation)
sec
ror a ; a bit at a time
: pha
lda #0
rol a
tay
ld2: lda $C300,y ; self-modified ($Cn00)
pla
lsr a
bne :-
dex
bne uloop
;; --------------------------------------------------
;; Push data onto stack
lda set_year
pha
lda set_month
pha
lda set_date
pha
lda set_dow
pha
lda set_hours
pha
lda set_minutes
pha
lda set_seconds
pha
lda #$00 ; Hundredths
pha
;; --------------------------------------------------
;; Loop over and write all 64 bits into register
tmp := $200
lda #8 ; bytes
sta count
bloop: ldx #8 ; bits
: pla ; current byte
ror a ; shift out bit to write
pha ; not done with this
lda #0
rol a ; shift into low bit
tay ; and into Y to use as index
st2:
lda $C300,y ; self-modified ($Cn00)
dex ; next bit
bne :-
pla ; next byte
dec count
bne bloop
;; --------------------------------------------------
;; Finish up
pla
bmi done
st4: sta $CFFF ; self-modified ($CFFF or SLOTCXROM)
done: plp
rts
count: .byte 0
.endproc
;;; --------------------------------------------------
.proc patch_from_driver
copy ld1+2, set_datetime::ld1+2
copy ld2+2, set_datetime::ld2+2
copy16 ld4+1, set_datetime::ld4+1
copy16 st1+1, set_datetime::st1+1
copy st2+2, set_datetime::st2+2
copy16 st4+1, set_datetime::st4+1
rts
.endproc
;;; ------------------------------------------------------------
;;; Output a high-ascii, null-terminated string.
;;; String immediately follows the JSR.
.proc zstrout
ptr := $A5
pla ; read address from stack
sta ptr
pla
sta ptr+1
bne skip ; always (since data not on ZP)
next: jsr COUT
skip: inc ptr
bne :+
inc ptr+1
: ldy #0
lda (ptr),y
bne next
lda ptr+1 ; restore address to stack
pha
lda ptr
pha
rts
.endproc

View File

@ -2,18 +2,23 @@
CAFLAGS = --target apple2enh --list-bytes 0
LDFLAGS = --config apple2-asm.cfg
OUTDIR = out
OUTDIR = ../../out
HEADERS = $(wildcard *.inc) $(wildcard ../inc/*.inc)
HEADERS = $(wildcard *.inc) $(wildcard ../../inc/*.inc)
TARGETS = \
$(OUTDIR)/romxrtc.system.SYS
$(OUTDIR)/romxrtc.system.SYS \
$(OUTDIR)/romxrtc.setup.SYS
LOG_SUCCESS=1
LOG_FAILURE=1
# For timestamps
MM = $(shell date "+%-m")
DD = $(shell date "+%-d")
YY = $(shell date "+%-y")
DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY)
DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY) \
-D LOG_SUCCESS=$(LOG_SUCCESS) -D LOG_FAILURE=$(LOG_FAILURE)
XATTR := $(shell command -v xattr 2> /dev/null)
@ -31,6 +36,9 @@ clean:
$(OUTDIR)/%.o: %.s $(HEADERS)
ca65 $(CAFLAGS) $(DEFINES) --listing $(basename $@).list -o $@ $<
$(OUTDIR)/%.setup.o: %.system.s $(HEADERS)
ca65 $(CAFLAGS) $(DEFINES) -D BUILD_SETUP_FILE --listing $(basename $@).list -o $@ $<
$(OUTDIR)/%.SYS: $(OUTDIR)/%.o
ld65 $(LDFLAGS) -o $@ $<
ifdef XATTR

View File

@ -1,3 +1,5 @@
# ROMX ProDOS Clock Driver
Original source c/o Jeff Mazur.
`ROMXRTC.SETUP` is for use with [SETUP.SYSTEM](../../setup/README.md).

View File

@ -45,9 +45,8 @@ SEL_MBANK := $F851 ; Select Main bank reg
;;;
;;; ============================================================
.ifndef JUMBO_CLOCK_DRIVER
.undef PRODUCT
.define PRODUCT "ROMX Clock"
.endif ; JUMBO_CLOCK_DRIVER
;;; ============================================================
;;; Ensure there is not a previous clock driver installed.
@ -92,10 +91,12 @@ nope: sec ; not found
bcc install_driver ; found clock!
.ifndef JUMBO_CLOCK_DRIVER
.if ::LOG_FAILURE
;; Show failure message
jsr log_message
scrcode PRODUCT, " - Not Found."
.byte 0
.endif ; ::LOG_FAILURE
.endif ; JUMBO_CLOCK_DRIVER
sec ; failure
@ -157,7 +158,7 @@ loop: lda ClockDrv,y
lda ROMIN2
.ifndef JUMBO_CLOCK_DRIVER
.if ::LOG_SUCCESS
;; Display success message
jsr log_message
scrcode PRODUCT, " - "
@ -165,7 +166,7 @@ loop: lda ClockDrv,y
;; Display the current date
jsr cout_date
.endif ; JUMBO_CLOCK_DRIVER
.endif ; ::LOG_SUCCESS
clc ; success
rts ; done!

View File

@ -1,3 +1,6 @@
.ifndef BUILD_SETUP_FILE
poporg
reloc_end := *
.endif

View File

@ -1,15 +1,20 @@
.define PRODUCT "Unknown"
;;; ------------------------------------------------------------
;; SYS files load at $2000; relocates self to $1000
.org SYS_ADDR
.ifndef BUILD_SETUP_FILE
dst_addr := $1000
;;; ------------------------------------------------------------
jmp relocate
.else
jmp main
.endif
.byte MM, DD, YY ; version date stamp
.ifndef BUILD_SETUP_FILE
;;; ------------------------------------------------------------
;;; Relocate this code from $2000 (.SYSTEM start location) to $1000
;;; and start executing there. This is done so that the next .SYSTEM
@ -387,6 +392,23 @@ suffix:
found_self_flag:
.byte 0
.else
;;; ============================================================
;;; Main routine
;;; ============================================================
.proc main
jsr maybe_install_driver
MLI_CALL QUIT, quit_params
brk ; crash if QUIT fails
DEFINE_QUIT_PARAMS quit_params
.endproc
.endif
;;; ============================================================
;;; Common Routines
;;; ============================================================

View File

@ -11,35 +11,47 @@ VOLNAME="drivers"
rm -f "$IMGFILE"
cadius CREATEVOLUME "$IMGFILE" "$VOLNAME" 140KB --no-case-bits --quiet
cadius CREATEFOLDER "$IMGFILE" "/$VOLNAME/CRICKET.UTIL" --no-case-bits --quiet
cadius CREATEFOLDER "$IMGFILE" "/$VOLNAME/SETUPS" --no-case-bits --quiet
add_file () {
cp "$1" "$PACKDIR/$2"
cadius ADDFILE "$IMGFILE" "$3" "$PACKDIR/$2" --no-case-bits --quiet
}
add_file "clocks/cricket/out/cricket.system.SYS" "cricket.system#FF0000" "/$VOLNAME"
add_file "clocks/cricket/out/set.date.BIN" "set.date#062000" "/$VOLNAME/CRICKET.UTIL"
add_file "clocks/cricket/out/set.time.BIN" "set.time#062000" "/$VOLNAME/CRICKET.UTIL"
add_file "clocks/cricket/out/test.BIN" "test#062000" "/$VOLNAME/CRICKET.UTIL"
add_file "clocks/dclock/out/dclock.system.SYS" "dclock.system#FF0000" "/$VOLNAME"
add_file "clocks/ns.clock/out/ns.clock.system.SYS" "ns.clock.system#FF0000" "/$VOLNAME"
add_file "clocks/romx/out/romxrtc.system.SYS" "romxrtc.system#FF0000" "/$VOLNAME"
add_file "clocks/fujinet/out/fn.clock.system.SYS" "fn.clock.system#FF0000" "/$VOLNAME"
add_file "clocks/jumbo/out/clock.system.SYS" "clock.system#FF0000" "/$VOLNAME"
add_file "ram.drv/out/ram.drv.system.SYS" "ram.drv.system#FF0000" "/$VOLNAME"
add_file "selectors/out/bbb.system.SYS" "bbb.system#FF0000" "/$VOLNAME"
add_file "selectors/out/buhbye.system.SYS" "buhbye.system#FF0000" "/$VOLNAME"
add_file "selectors/out/bye.system.SYS" "bye.system#FF0000" "/$VOLNAME"
add_file "selectors/out/selector.system.SYS" "selector.system#FF0000" "/$VOLNAME"
add_file "util/out/quit.system.SYS" "quit.system#FF0000" "/$VOLNAME"
add_file "util/out/pause.system.SYS" "pause.system#FF0000" "/$VOLNAME"
add_file "util/out/me.first.system.SYS" "me.first.system#FF0000" "/$VOLNAME"
add_file "util/out/date.BIN" "date#062000" "/$VOLNAME"
# Drivers
for file in \
"bbb" "buhbye" "bye" "selector" \
"clock" "cricket" "dclock" "fn.clock" "ns.clock" "romxrtc" \
"ram.drv" \
"zipchip" \
"me.first" "pause"; do
add_file "out/$file.system.SYS" "$file.system#FF0000" "/$VOLNAME"
add_file "out/$file.setup.SYS" "$file.setup#FF0000" "/$VOLNAME/SETUPS"
done
add_file "out/setup.system.SYS" "setup.system#FF0000" "/$VOLNAME"
add_file "out/quit.system.SYS" "quit.system#FF0000" "/$VOLNAME"
# Utilities
add_file "out/date.BIN" "date#062000" "/$VOLNAME"
cadius CREATEFOLDER "$IMGFILE" "/$VOLNAME/CRICKET.UTIL" --no-case-bits --quiet
add_file "out/cricket.util/set.datetime.BIN" "set.datetime#062000" "/$VOLNAME/CRICKET.UTIL"
add_file "out/cricket.util/set.date.BIN" "set.date#062000" "/$VOLNAME/CRICKET.UTIL"
add_file "out/cricket.util/set.time.BIN" "set.time#062000" "/$VOLNAME/CRICKET.UTIL"
add_file "out/cricket.util/test.BIN" "test#062000" "/$VOLNAME/CRICKET.UTIL"
cadius CREATEFOLDER "$IMGFILE" "/$VOLNAME/NSCLOCK.UTIL" --no-case-bits --quiet
add_file "out/nsclock.util/set.datetime.BIN" "set.datetime#062000" "/$VOLNAME/NSCLOCK.UTIL"
cadius CREATEFOLDER "$IMGFILE" "/$VOLNAME/TEXTCOLORS" --no-case-bits --quiet
cadius CREATEFOLDER "$IMGFILE" "/$VOLNAME/SETUPS/TEXTCOLORS" --no-case-bits --quiet
for file in a2green bw deepblue gray gsblue mint pink wb; do
add_file "textcolors/out/${file}.system.SYS" "${file}.system#FF0000" "/$VOLNAME/TEXTCOLORS"
add_file "out/${file}.system.SYS" "${file}.system#FF0000" "/$VOLNAME/TEXTCOLORS"
add_file "out/${file}.setup.SYS" "${file}.setup#FF0000" "/$VOLNAME/TEXTCOLORS/SETUPS"
done
rm -r "$PACKDIR"

View File

@ -2,18 +2,23 @@
CAFLAGS = --target apple2enh --list-bytes 0
LDFLAGS = --config apple2-asm.cfg
OUTDIR = out
OUTDIR = ../out
HEADERS = $(wildcard *.inc) $(wildcard ../inc/*.inc)
TARGETS = \
$(OUTDIR)/ram.drv.system.SYS
$(OUTDIR)/ram.drv.system.SYS \
$(OUTDIR)/ram.drv.setup.SYS
export LOG_SUCCESS=1
export LOG_FAILURE=1
# For timestamps
MM = $(shell date "+%-m")
DD = $(shell date "+%-d")
YY = $(shell date "+%-y")
DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY)
DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY) \
-D LOG_SUCCESS=$(LOG_SUCCESS) -D LOG_FAILURE=$(LOG_FAILURE)
XATTR := $(shell command -v xattr 2> /dev/null)
@ -31,8 +36,8 @@ clean:
$(OUTDIR)/%.o: %.s $(HEADERS)
ca65 $(CAFLAGS) $(DEFINES) --listing $(basename $@).list -o $@ $<
$(OUTDIR)/%.setup.o: %.system.s $(HEADERS)
ca65 $(CAFLAGS) $(DEFINES) -D BUILD_SETUP_FILE --listing $(basename $@).list -o $@ $<
$(OUTDIR)/%.SYS: $(OUTDIR)/%.o
ld65 $(LDFLAGS) -o $@ $<
ifdef XATTR
xattr -wx prodos.AuxType '00 20' $@
endif

View File

@ -30,6 +30,7 @@
;;; ============================================================
;;; Configuration Parameters
.undef PRODUCT
.define PRODUCT "RAMWorks RAM Disk"
zp_sig_addr := $06
@ -37,7 +38,6 @@ zp_sig_addr := $06
zpproc_addr := $B0
zpproc_relay_addr := $2D0
data_buf := $1C00 ; I/O when chaining to next SYS file
driver_target := $FF00 ; Install location in ProDOS
@ -406,9 +406,11 @@ finish: bit ROMIN2
install_success:
sta ALTZPOFF
.if ::LOG_SUCCESS
jsr log_message
scrcode PRODUCT, " - "
.byte 0
.endif ; ::LOG_SUCCESS
;; Initialize Applesoft zero page locations required by LINPRNT
copy #0, SHIFT_SIGN_EXT ; required by FP routines
@ -429,9 +431,11 @@ install_success:
install_failure:
sta ALTZPOFF
.if ::LOG_FAILURE
jsr log_message
scrcode PRODUCT, " - Not Found"
.byte 0
.endif ; ::LOG_FAILURE
rts
@ -706,8 +710,6 @@ map2 := *+2+$80 ; len: $80
stash_00 := *+2+$100 ; len: $80
stash_01 := *+2+$180 ; len: $80
.assert stash_01+$80 < data_buf, error, "Too long"
;;; ************************************************************
.include "../inc/driver_postamble.inc"
;;; ************************************************************

View File

@ -2,15 +2,19 @@
CAFLAGS = --target apple2enh --list-bytes 0
LDFLAGS = --config apple2-asm.cfg
OUTDIR = out
OUTDIR = ../out
HEADERS = $(wildcard *.inc) $(wildcard ../inc/*.inc)
TARGETS = \
$(OUTDIR)/selector.system.SYS \
$(OUTDIR)/selector.setup.SYS \
$(OUTDIR)/bye.system.SYS \
$(OUTDIR)/bye.setup.SYS \
$(OUTDIR)/bbb.system.SYS \
$(OUTDIR)/buhbye.system.SYS
$(OUTDIR)/bbb.setup.SYS \
$(OUTDIR)/buhbye.system.SYS \
$(OUTDIR)/buhbye.setup.SYS
# For timestamps
MM = $(shell date "+%-m")
@ -34,8 +38,8 @@ clean:
$(OUTDIR)/%.o: %.s $(HEADERS)
ca65 $(CAFLAGS) $(DEFINES) --listing $(basename $@).list -o $@ $<
$(OUTDIR)/%.setup.o: %.system.s $(HEADERS)
ca65 $(CAFLAGS) $(DEFINES) -D BUILD_SETUP_FILE --listing $(basename $@).list -o $@ $<
$(OUTDIR)/%.SYS: $(OUTDIR)/%.o
ld65 $(LDFLAGS) -o $@ $<
ifdef XATTR
xattr -wx prodos.AuxType '00 20' $@
endif

35
setup/Makefile Normal file
View File

@ -0,0 +1,35 @@
CAFLAGS = --target apple2enh --list-bytes 0
LDFLAGS = --config apple2-asm.cfg
OUTDIR = ../out
HEADERS = $(wildcard *.inc) $(wildcard ../inc/*.inc)
TARGETS = \
$(OUTDIR)/setup.system.SYS
# For timestamps
MM = $(shell date "+%-m")
DD = $(shell date "+%-d")
YY = $(shell date "+%-y")
DEFINES = -D DD=$(DD) -D MM=$(MM) -D YY=$(YY)
XATTR := $(shell command -v xattr 2> /dev/null)
.PHONY: clean all
all: $(OUTDIR) $(TARGETS)
$(OUTDIR):
mkdir -p $(OUTDIR)
clean:
rm -f $(OUTDIR)/*.o
rm -f $(OUTDIR)/*.list
rm -f $(TARGETS)
$(OUTDIR)/%.o: %.s $(HEADERS)
ca65 $(CAFLAGS) $(DEFINES) --listing $(basename $@).list -o $@ $<
$(OUTDIR)/%.SYS: $(OUTDIR)/%.o
ld65 $(LDFLAGS) -o $@ $<

30
setup/README.md Normal file
View File

@ -0,0 +1,30 @@
# SETUP.SYSTEM
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:
* The top level directory only needs one SYSTEM file plus `SETUPS/`, which reduces clutter.
* Each individual setup file is simpler than stand-alone SYSTEM files, as they don't need to implement chaining.
Which approach you use is a matter of taste.
## How do you use these?
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:
* `PRODOS` - the operating system, e.g. [ProDOS 2.4](https://prodos8.com/)
* `SETUP.SYSTEM` - install No-Slot clock driver, if present
* `QUIT.SYSTEM` - invoke the Quit handler immediately, as a program selector
* `BASIC.SYSTEM` - which will not be automatically invoked, but is available to manually invoke
* `SETUPS/NS.CLOCK.SYSTEM` - install No-Slot clock driver, if present
* `SETUPS/ROMXRTC.SYSTEM` - install ROMX clock driver, if present
* `SETUPS/FN.CLOCK.SYSTEM` - install FujiNet clock driver, if present
* `SETUPS/DCLOCK.SYSTEM` - install DClock clock driver, if present
* `SETUPS/CRICKET.SYSTEM` - install Cricket! clock driver, if present
* `SETUPS/ZIPCHIP.SYSTEM` - slow the ZIP CHIP on speaker access, if present
* `SETUPS/RAM.DRV.SYSTEM` - install RamWorks RAM disk driver, if present
* `SETUPS/BUHBYE.SYSTEM` - install a customized Quit handler to replace the built-in one
* `SETUPS/PAUSE.SYSTEM` - pause for a moment, so that you can inspect the output of the above
## Notes
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.

329
setup/setup.system.s Normal file
View File

@ -0,0 +1,329 @@
;;;
;;; SETUP.SYSTEM by Sean Nolan
;;;
;;; A Proposed Startup File Standard
;;;
;;; Published in Call-APPLE, November, 1987
;;; This program is in the public domain.
;;;
;;; This program mimics the ProDOS 16
;;; SYSTEM.SETUP convention. It can be used
;;; to install RAM disk drivers, clock
;;; drivers, and IIGS Classic Desk
;;; Accessories on bootup under ProDOS 8.
;;;
;;; This program loads and calls all BINary
;;; and SYStem files in a subdirectory named
;;; SETUPS. It then looks for the second
;;; system program in the volume directory
;;; whose name ends in ".SYSTEM", and runs
;;; that.
;;;
;;;
;;; Original code clears the screen before/after each driver. Skip it.
NO_HOME = 1
.define ORG .org
.define DFB .byte
.define DA .addr
.define DS .res
.define ASC .byte
.define ASCH scrcode
.feature labels_without_colons +
.feature loose_string_term +
.include "apple2.mac"
.if 0
TYP $FF ;save as a system file
.endif
ORG $BD00 ;load at $2000, but run at $BD00
;;; ****************** equates
CH = $24
IN2 = $280
FILETYPE = IN2+16
AUXCODE = IN2+31
RESET = $3F2
IOBUFFER = $B900
PRODOS = $BF00
QUITVECT = $BF03
DEVNUM = $BF30
BITMAP = $BF58
INIT = $FB2F
VTABZ = $FC24
HOME = $FC58
RDKEY = $FD0C
SETVID = $FE93
SETKBD = $FE89
SETNORM = $FE84
;;; ****************** boot code
VOLNAME = * ;The first 17 bytes are overwritten with the
;name of the volume from which this was run.
LDX #1 ;mark page $BD as free in the system bitmap
STX BITMAP+23 ;so we can put Online result in our code.
DEX ;relocate this program to $BD00-BEFF
LOOP1 LDA $2000,X
STA $BD00,X
LDA $2100,X
STA $BE00,X
INX
BNE LOOP1
DEX
TXS ;init stack pointer
JMP ENTER ;jump to relocated code
DIRNAME DFB 6 ;DirName and VolName must be in the same page
ASCH "SETUPS"
;;; ****** Get name of boot volume
ENTER LDA DEVNUM ;get name of last volume accessed
STA ONLINEN
JSR PRODOS
DFB $C5 ;ONLINE
DA ONLINEP
LDA VOLNAME+1 ;insert a slash nefore the name
AND #$0F
TAX
INX
STX VOLNAME
LDA #$2F ;/
STA VOLNAME+1
LDA QUITVECT+1 ;save original quit vector
STA QUITMOD1+1
LDA QUITVECT+2
STA QUITMOD2+1
;;; ****** Clean up before &amp; after calling files
MAINLOOP LDX #2 ;point Reset vector and ProDOS
LOOP3 LDA JUMP+1,X ;Quit vectors to MainLoop
STA RESET,X
LDA JUMP,X
STA QUITVECT,X
DEX
BPL LOOP3
TXS ;fix stack pointer (X=$FF)
JSR CLOSE ;close all open files
LDX #23 ;clear system bit map
LDA #0
LOOP2 STA BITMAP,X
DEX
BPL LOOP2
LDA #$CF ;mark pages 0,1,4-7 as used
STA BITMAP
LDA #%111 ;mark pages $BD-$BF as used
STA BITMAP+23
LDA $C082 ;Language card off
STA $C00C ;40-column
STA $C00E ;normal character set
STA $C000 ;80STORE off
JSR SETNORM ;normal
JSR INIT ;display text page 1
JSR SETVID ;PR#0
JSR SETKBD ;IN#0
;;; Make sure boot volume is around
;;; AND set prefix to the boot volume
.if NO_HOME
VOLMOUNT
.else
VOLMOUNT JSR HOME
.endif
JSR PRODOS ;set prefix to volume
DFB $C6 ;SET PREFIX
DA PFX2P
BCC VOLOK
LDX #13
LOOP6 LDA VOLTEXT-1,X ;print message "insert volume"
STA $5A8+4,X
DEX
BNE LOOP6
LOOP7 LDA VOLNAME+1,X ;print volume name
ORA #$80
STA $5A8+19,X
INX
CPX VOLNAME
BCC LOOP7
LDA #35 ;go to CH=35, CV=11
STA CH
LDA #11
JSR VTABZ
JSR RDKEY ;wait for keypress
JMP VOLMOUNT
;;; ****** Get name of next file at IN2
VOLOK JSR NEXTFILE ;get name of next file at IN2
BCS EXITLOOP ;if error, we're done with setup files
;;; ****** Load and call setup file
JSR PRODOS ;set prefix to SETUPS
DFB $C6 ;SET PREFIX
DA PFX1P
JSR READFILE ;read in file whose name is at IN@
;and call it if there was no error.
JUMP JMP MAINLOOP ;3 bytes here copied into ProDOS quit vector
DFB $BD^$A5 ;3 bytes here are copied into reset vector
EXITLOOP INC RESET+2 ;scramble reset vector
QUITMOD1 LDA #0 ;restore original quit vector
STA QUITVECT+1
QUITMOD2 LDA #0
STA QUITVECT+2
;;; ****** Look for second system program on disk
LDA #0 ;modify NextFile routine so that it searches
STA NUMBER+1 ;the volume directory for system files only.
STA CHEKTYPE+1
LDA #<VOLNAME ;NamePtr+1 does not bneed to be changed
STA NAMEPTR ;since VolName and DirName are in the same page
NEXTSYS JSR NEXTFILE
BCS QUIT
LDX IN2 ;see if file ends with ".SYSTEM"
LDY #6
LOOP4 LDA IN2,X ;I expect pathname at IN2 in low ASCII
CMP SYSTEXT,Y
BNE NEXTSYS
DEX
DEY
BPL LOOP4
INC MOD+1
MOD LDA #$FF ;the first .SYSTEM program we find is this
BEQ NEXTSYS ;one, so skip it and look for next one.
JSR READFILE ;if successful, never come back
QUIT JSR PRODOS
DFB $65 ;QUIT
DA QUITP
SYSTEXT ASC '.SYSTEM'
;;; Get name of next system file or binary file
;;;
;;; This routine is set up to look for both SYSTEM and
;;; BINary files in the SETUPs subdirectory. It is later
;;; modified to search for SYSTEM files only in the
;;; volume directory. The locations which are changed
;;; are ChekType+1, Number+1, and NamePtr (in the Open
;;; parametr list)
;;;
;;; Returns carry if not found, clear if found.
NEXTFILE JSR PRODOS
DFB $C8 ;OPEN
DA OPENP
BCS CLOSE
LDA OPENN
STA MARKN
STA READN
JSR PRODOS ;Read in first 39 bytes of directory to
DFB $CA ;IN2. This gets the number of entries per
DA READP ;block and number of bytes per entry.
BCS CLOSE
LDA IN2+35 ;save number of bytes per directory entry
STA ENTSIZE+1
LDA IN2+36 ;save number of entries per directory block
STA ENTRIES+1
NEXTENT INC NUMBER+1
NUMBER LDA #0 ;self-modified operand
;;; Retrieve catalog entry #A
LDX #$FE ;build page index in X
LOOP5 INX
INX
ENTRIES CMP #13
BCC OK
SBC ENTRIES+1
BCS LOOP5 ;always
OK TAY
LDA #4 ;1st entry per directory block starts 4 bytes in
LOOP10 DEY
BMI OK2
CLC
ENTSIZE ADC #39 ;add size of directory entry
BCC LOOP10
INX
BNE LOOP10 ;always
OK2 STA MARK ;save mark in file
STX MARK+1
JSR PRODOS ;set the mark
DFB $CE ;SET_MARK
DA MARKP
BCS CLOSE
JSR PRODOS ;read in directory info
DFB $CA ;READ
DA READP
BCS CLOSE
LDA IN2 ;make sure that file is not deleted
BEQ NEXTENT
AND #$0F
STA IN2
LDA FILETYPE ;make sure file type is correct
EOR #$FF ;we look for system programs...
BEQ CLOSE
CHEKTYPE EOR 6^$FF ;...and binary ones.
BNE NEXTENT
CLOSE PHP ;close all files - do not change carry
JSR PRODOS
DFB $CC ;CLOSE
DA CLOSEP
PLP
ANRTS RTS
;;; Read file and call it.
;;; Name should be found at IN2
;;; Prefix must be set.
READFILE LDX FILETYPE ;if a system program, set to read to $2000
LDA #$20
INX
BEQ SETDEST
LDX AUXCODE ;else, set to read in file at address
LDA AUXCODE+1 ;found in auxcode
SETDEST STX READ2D
STA READ2D+1
JSR PRODOS ;Open file
DFB $C8 ;OPEN
DA OPEN2P
BCS CLOSE
LDA OPEN2N
STA READ2N
JSR PRODOS ;Read file into memory
DFB $CA ;READ
DA READ2P
JSR CLOSE
BCS ANRTS
JMP (READ2D) ;call the file just loaded
;;; ****** ProDOS MLI parameter lists
ONLINEP DFB 2 ;Online parameter list
ONLINEN DS 1
DA VOLNAME+1
;;;
PFX1P DFB 1 ;to set prefix to SETUP
DA DIRNAME
;;;
PFX2P DFB 1 ;to set prefix to volume directory
DA VOLNAME
;;;
QUITP DFB 4,0,0,0,0,0,0
;;;
CLOSEP DFB 1,0 ;close all files
;;;
OPENP DFB 3 ;open directory
NAMEPTR DA DIRNAME ;pathname pointer
DA IOBUFFER
OPENN DS 1 ;reference number
;;;
MARKP DFB 2 ;set mark in directory
MARKN DS 1
MARK DS 3
;;;
READP DFB 4 ;read directory
READN DS 1
DA IN2 ;target address
DA 39 ;length
DS 2
;;;
OPEN2P DFB 3 ;open setup or system file
DA IN2
DA IOBUFFER
OPEN2N DS 1
;;;
READ2P DFB 4 ;read setup or system file
READ2N DS 1
READ2D DS 2 ;destination of file is self-mod here
DA $B900-$800 ;ask for largest possible that will fit
DS 2
;;;
VOLTEXT ASCH "INSERT VOLUME"
.if 0
CHK ;checksum - eor for all previous bytes
.else
.byte $E8
.endif

View File

@ -2,19 +2,28 @@
CAFLAGS = --target apple2enh --list-bytes 0
LDFLAGS = --config apple2-asm.cfg
OUTDIR = out
OUTDIR = ../out
HEADERS = $(wildcard *.inc) $(wildcard ../inc/*.inc)
TARGETS = \
$(OUTDIR)/a2green.system.SYS \
$(OUTDIR)/a2green.setup.SYS \
$(OUTDIR)/bw.system.SYS \
$(OUTDIR)/bw.setup.SYS \
$(OUTDIR)/deepblue.system.SYS \
$(OUTDIR)/deepblue.setup.SYS \
$(OUTDIR)/gray.system.SYS \
$(OUTDIR)/gray.setup.SYS \
$(OUTDIR)/gsblue.system.SYS \
$(OUTDIR)/gsblue.setup.SYS \
$(OUTDIR)/mint.system.SYS \
$(OUTDIR)/mint.setup.SYS \
$(OUTDIR)/pink.system.SYS \
$(OUTDIR)/wb.system.SYS
$(OUTDIR)/pink.setup.SYS \
$(OUTDIR)/wb.system.SYS \
$(OUTDIR)/wb.setup.SYS
# For timestamps
MM = $(shell date "+%-m")
DD = $(shell date "+%-d")
@ -37,8 +46,8 @@ clean:
$(OUTDIR)/%.o: %.s $(HEADERS)
ca65 $(CAFLAGS) $(DEFINES) --listing $(basename $@).list -o $@ $<
$(OUTDIR)/%.setup.o: %.system.s $(HEADERS)
ca65 $(CAFLAGS) $(DEFINES) -D BUILD_SETUP_FILE --listing $(basename $@).list -o $@ $<
$(OUTDIR)/%.BIN $(OUTDIR)/%.SYS: $(OUTDIR)/%.o
ld65 $(LDFLAGS) -o $@ $<
ifdef XATTR
xattr -wx prodos.AuxType '00 20' $@
endif

View File

@ -2,14 +2,16 @@
CAFLAGS = --target apple2enh --list-bytes 0
LDFLAGS = --config apple2-asm.cfg
OUTDIR = out
OUTDIR = ../out
HEADERS = $(wildcard *.inc) $(wildcard ../inc/*.inc)
TARGETS = \
$(OUTDIR)/quit.system.SYS \
$(OUTDIR)/pause.system.SYS \
$(OUTDIR)/pause.setup.SYS \
$(OUTDIR)/me.first.system.SYS \
$(OUTDIR)/me.first.setup.SYS \
$(OUTDIR)/date.BIN
# For timestamps
@ -34,6 +36,9 @@ clean:
$(OUTDIR)/%.o: %.s $(HEADERS)
ca65 $(CAFLAGS) $(DEFINES) --listing $(basename $@).list -o $@ $<
$(OUTDIR)/%.setup.o: %.system.s $(HEADERS)
ca65 $(CAFLAGS) $(DEFINES) -D BUILD_SETUP_FILE --listing $(basename $@).list -o $@ $<
$(OUTDIR)/%.BIN $(OUTDIR)/%.SYS: $(OUTDIR)/%.o
ld65 $(LDFLAGS) -o $@ $<
ifdef XATTR