Compare commits

...
14 Commits
Author SHA1 Message Date
chris b4b48b195d NOTICE: list the Arnitech controller option 2026-10-17 02:17:45 +02:00
chris 03e2d4a4b8 Arnitech controller: the TOD set at boot, and a jump table at $FF00
A new option, ARNITECH_CONTROLLER, on in the mc64 configuration only.
IOINIT starts timer A with CIA #1's TOD on 50 Hz, the mc64's mains, and
if the Arnitech controller's signature "ARNI" is at $DE80, latches its
clock and copies its real time into the TOD, hours first and tenths
last, flipping bit 7 of an hour of 12 first, since the CIA flips it
back when 12 is written. Without the signature the TOD is left alone.

The Arnitech jump table at $FF00: "ARNI", version $01, two entries, and
JMPs from $FF06: $FF06 finds the first Card slot holding a Card of the
type in A (carry clear, the slot in A, its Card window's low byte in
X; carry set if none or no controller), $FF09 sets the TOD as IOINIT
does. $FF48-$FF80 stay clear. The code is in new files under
src/kernal/arnitech; other configurations build as before.
2026-10-17 02:17:45 +02:00
chris 0ec343a727 NOTICE: list the serial-bus fixes that leave the bus released 2026-10-15 14:21:36 +02:00
chris 729a410079 Serial bus: UNLSN, UNTLK, and a missing device leave the bus released
UNLSN ended through iec_set_idle, which pulls CLK, so the C64 kept
holding CLK after UNLISTEN. UNTLK waited for the talker to pull CLK,
which no device does after UNTALK, timed out, and left CLK pulled with
carry set. And a serial routine that found no device also left CLK
pulled. A fastloader that waits for the drive to pull CLK after the
KERNAL's UNLSN (Turrican's) then went on too early.

The contract (Michael Steil, "Commodore Peripheral Bus: Part 4",
https://www.pagetable.com/?p=1135): at the end of a transmission the
sender releases CLK and the receivers release DATA, so the bus is idle
again, and the controller releases ATN after each command; after
UNTALK "the current talker will then release the bus" (Part 2,
https://www.pagetable.com/?p=1031). UNLSN and UNTLK now share their end
and release CLK and DATA; the device-not-present exit releases ATN, CLK,
and DATA. Commodore's ROMs leave the same lines in the same scenarios,
as differential tests in arnitech show.

Not reported upstream (https://github.com/MEGA65/open-roms).
2026-10-15 14:21:36 +02:00
chris 7ee9d164e2 NOTICE: list the CLOSE fix for a device that does not answer 2026-10-15 02:50:48 +02:00
chris 51a2a43520 CLOSE: a device that does not answer sets ST to device not present
When LISTEN or the CLOSE command found no device on the serial bus,
close_iec freed the file number but left ST as it was, so READST after
the CLOSE said 0.

The contract: every device on the bus must answer ATN by pulling DATA,
and when none does the result is DEVICE NOT PRESENT (Michael Steil,
"Commodore Peripheral Bus: Part 2", https://www.pagetable.com/?p=1031);
the C64 Programmer's Reference Guide's READST reports that as ST bit 7
($80). close_iec now sets that bit when LISTEN or the CLOSE command
fails, and still frees the file number. Commodore's ROMs give the same
ST in the same scenario, as a differential test in arnitech shows.

Not reported upstream (https://github.com/MEGA65/open-roms).
2026-10-15 02:50:48 +02:00
chris ec7707d4cc NOTICE: list the serial-bus fix for a byte with no listener 2026-10-15 02:32:03 +02:00
chris 74ef17d292 Serial bus: a data byte with no listener says DEVICE NOT PRESENT
iec_tx_byte never checked that anyone was listening. With no listener,
DATA stays released, so the wait for listeners to be ready returned at
once, and a byte sent with EOI then waited forever for an EOI
acknowledgement that never came. UNLSN, which sends the byte CIOUT holds
back with EOI, hung the C64 after CHKOUT to a channel the drive refuses
(DOS 2.6 leaves the bus when no write channel is open), or to a channel
a CLOSE 15 has closed.

The contract (Michael Steil, "Commodore Peripheral Bus: Part 4",
https://www.pagetable.com/?p=1135): a listener holds DATA until the
talker releases CLK; if at the beginning of a byte no receiver pulls
DATA within 256 us, that is a DEVICE NOT PRESENT error. The C64
Programmer's Reference Guide's READST gives it as ST bit 7 ($80).
iec_tx_byte now waits up to about 256 us for DATA to be pulled, and
without it sets ST $80 and returns with DEVICE NOT PRESENT. Commodore's
ROMs give the same ST in the same scenarios, as a differential test in
arnitech shows.

Not reported upstream (https://github.com/MEGA65/open-roms).
2026-10-15 02:31:56 +02:00
chris b95a6ff057 NOTICE: list the serial-bus fixes of 2026-10-15
CIOUT's buffer, CLOSE's LISTEN/CLOSE/UNLISTEN, CHKIN's and CHKOUT's
secondary address, and TKSA's secondary address.
2026-10-15 02:19:08 +02:00
chris f1df180bf8 TKSA: send the secondary address the caller gives
TKSA ORed the accumulator with $90 before sending it. Its callers pass
the secondary address plus $60, as the routine's own comment asks, so
TKSA turned a TALK secondary address $60-$6F into $F0-$FF, the OPEN
command, on the bus.

The contract (C64 Programmer's Reference Guide, TKSA; Michael Steil,
"Commodore Peripheral Bus: Part 2", https://www.pagetable.com/?p=1031,
which gives TKSA's argument as A = $60 + secondary address): TKSA sends
the byte in A as the secondary address to the device told to TALK.
TKSA now sends A as it is.

Upstream: https://github.com/MEGA65/open-roms/issues/116 (bug 1)
2026-10-15 02:18:55 +02:00
chris 340bbefd06 CHKIN, CHKOUT: address the channel by the file's secondary address
chkin_iec and ckout_iec read the secondary address from LAT, the table
of logical file numbers, instead of SAT, the table of secondary
addresses. A file whose number differed from its secondary address,
such as OPEN 3,8,2, was read from or written to the wrong channel, and
the read-only and write-only checks tested the file number.

The contract (Michael Steil, "Commodore Peripheral Bus: Part 2",
https://www.pagetable.com/?p=1031): CHKIN sends TALK and CHKOUT sends
LISTEN, each followed by the secondary address OPEN was given; Compute!'s
Mapping the Commodore 64 (p. 52) keeps the logical file numbers at
$0259 (LAT) and the secondary addresses at $026D (SAT). Both routines
now read SAT.

Not reported upstream (https://github.com/MEGA65/open-roms); it may be
what upstream issue #117's OPEN 1,8,0,"$" test met:
https://github.com/MEGA65/open-roms/issues/117
2026-10-15 02:17:03 +02:00
chris 29124377fc CLOSE: send LISTEN, CLOSE, UNLISTEN to a serial device
close_iec sent its CLOSE command under ATN without first addressing the
device with LISTEN and without UNLISTEN after it, and built the command
with ORA $E0 (zero page) instead of ORA #$E0, so the byte it sent was
the secondary address ORed with whatever $E0 held. The drive never
learned of the CLOSE, so a file written on a channel was never written
to the disk.

The contract (Michael Steil, "Commodore Peripheral Bus: Part 2",
https://www.pagetable.com/?p=1031): CLOSE of a file on a serial device
sends LISTEN, then $E0 plus the secondary address, then UNLISTEN.
close_iec now does that, as iec_close_load already does for LOAD.

Not reported upstream (https://github.com/MEGA65/open-roms).
2026-10-15 02:15:38 +02:00
chris 264e9792a5 CIOUT: buffer the byte where iec_tx_byte sends it from
CIOUT kept the byte to send next in BSOUR ($95), but iec_tx_byte, which
CIOUT and iec_tx_flush (called by UNLSN, UNTLK, LISTEN, TALK) use to
send it, transmits TBTCNT ($A4). So every byte CHROUT sent to a serial
device was whatever TBTCNT held, and a file written with CHKOUT and
CHROUT held the wrong bytes.

The contract (C64 Programmer's Reference Guide, CIOUT): CIOUT sends a
byte to the listening device, always holding one back so that the last
byte goes with EOI when UNLSN ends the transfer. CIOUT now buffers the
byte in TBTCNT, the one-line fix of upstream PR #113; changing the send
path to read BSOUR would also move LOAD's and SAVE's bytes.

Upstream: https://github.com/MEGA65/open-roms/pull/113
2026-10-15 02:15:38 +02:00
chris 840c5f1b61 Add the mc64 configuration, the Firmware of arnitech's mc64
A copy of the c64 configuration with its own ID ($6D), the brand "MC64",
and BCD_SAFE_INTERRUPTS off, plus its Makefile targets
build/kernal_mc64.rom and build/basic_mc64.rom, made the same way as the
c64 ones. NOTICE says who modified the fork, when, and what changed.
2026-10-14 18:32:24 +02:00
18 changed files with 443 additions and 15 deletions

No files matched your search

+6
View File
@@ -289,6 +289,12 @@ On the most widespread CPUs the D flag is not cleared upon entering interrupts.
Feature needs 2 bytes in KERNAL segmment (for CPUs needing the patch), but at the same time allows optimizations allowing to gain some more bytes. If unsure - enable.
### `ARNITECH_CONTROLLER`
For the mc64 computers of arnitech only, whose expansion port holds the Arnitech controller at `$DE80`. IOINIT puts CIA #1's TOD on 50 Hz and, if the controller's signature `"ARNI"` is at `$DE80`, sets the TOD from the controller's clock. The Arnitech jump table at `$FF00` (`src/kernal/arnitech/ff00.arnitech_jumptable.s`) wraps the controller's registers.
Feature needs about 120 bytes in KERNAL segment, and the page at `$FF00`. Disable on any other machine.
## Eye candy
### `COLORS_BRAND`
+21
View File
@@ -45,6 +45,7 @@ SRCDIR_KERNAL = $(SRCDIR_COMMON) \
src/kernal \
src/kernal/,stubs \
src/kernal/assets \
src/kernal/arnitech \
src/kernal/board_crt \
src/kernal/board_m65 \
src/kernal/board_u64 \
@@ -137,6 +138,7 @@ GEN_ZMAC_H = $(DIR_ZMAC_TMP)/doc.inl
# List of build directories
DIR_C64 = build/target_c64
DIR_MC64 = build/target_mc64
DIR_CUS = build/target_custom
DIR_GEN = build/target_generic
DIR_GENCRT = build/target_generic_crt
@@ -151,6 +153,7 @@ DIR_X16 = build/target_cx16
CFG_CUS = src/,,config_custom.s
CFG_C64 = src/,,config_c64.s
CFG_MC64 = src/,,config_mc64.s
CFG_GEN = src/,,config_generic.s
CFG_GENCRT = src/,,config_generic_crt.s
CFG_TST38 = src/,,config_testing_38K.s
@@ -164,6 +167,7 @@ CFG_U64CRT = src/,,config_ultimate64_crt.s
GEN_STR_CUS = $(DIR_CUS)/,generated/,packed_strings.s
GEN_STR_C64 = $(DIR_C64)/,generated/,packed_strings.s
GEN_STR_MC64 = $(DIR_MC64)/,generated/,packed_strings.s
GEN_STR_GEN = $(DIR_GEN)/,generated/,packed_strings.s
GEN_STR_GENCRT = $(DIR_GENCRT)/,generated/,packed_strings.s
GEN_STR_TST38 = $(DIR_TST38)/,generated/,packed_strings.s
@@ -212,6 +216,7 @@ TARGET_CHR_PXL = build/chargen_pxlfont.rom
TARGET_CUS_B = build/basic_custom.rom
TARGET_C64_B = build/basic_c64.rom
TARGET_MC64_B = build/basic_mc64.rom
TARGET_GEN_B = build/basic_generic.rom
TARGET_GENCRT_B = build/basic_generic_crt.rom
TARGET_TST38_B = build/basic_testing_38K.rom
@@ -221,6 +226,7 @@ TARGET_U64CRT_B = build/basic_ultimate64_crt.rom
TARGET_CUS_K = build/kernal_custom.rom
TARGET_C64_K = build/kernal_c64.rom
TARGET_MC64_K = build/kernal_mc64.rom
TARGET_GEN_K = build/kernal_generic.rom
TARGET_GENCRT_K = build/kernal_generic_crt.rom
TARGET_TST38_K = build/kernal_testing_38K.rom
@@ -237,6 +243,7 @@ TARGET_X16_x = build/cx16-dummy.rom
TARGET_LIST_CUS = $(TARGET_CUS_B) $(TARGET_CUS_K)
TARGET_LIST_C64 = $(TARGET_C64_B) $(TARGET_C64_K)
TARGET_LIST_MC64 = $(TARGET_MC64_B) $(TARGET_MC64_K)
TARGET_LIST_GEN = $(TARGET_GEN_B) $(TARGET_GEN_K)
TARGET_LIST_GENCRT = $(TARGET_GENCRT_B) $(TARGET_GENCRT_K) $(TARGET_GENCRT_X)
TARGET_LIST_TST38 = $(TARGET_TST38_B) $(TARGET_TST38_K)
@@ -249,6 +256,7 @@ TARGET_Z80TEST = ./build/cpm/Z80TEST.COM
TARGET_LIST = $(TARGET_CHR_ORF) \
$(TARGET_LIST_CUS) \
$(TARGET_LIST_C64) \
$(TARGET_LIST_MC64) \
$(TARGET_LIST_GEN) \
$(TARGET_LIST_GENCRT) \
$(TARGET_LIST_TST38) \
@@ -385,6 +393,8 @@ $(DIR_CUS)/OUTB_x.BIN $(DIR_CUS)/BASIC_combined.vs: \
$(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_BASIC) $(CFG_CUS) $(GEN_STR_CUS) $(DIR_CUS)/KERNAL_combined.sym
$(DIR_C64)/OUTB_x.BIN $(DIR_C64)/BASIC_combined.vs: \
$(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_BASIC) $(CFG_C64) $(GEN_STR_C64) $(DIR_C64)/KERNAL_combined.sym
$(DIR_MC64)/OUTB_x.BIN $(DIR_MC64)/BASIC_combined.vs: \
$(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_BASIC) $(CFG_MC64) $(GEN_STR_MC64) $(DIR_MC64)/KERNAL_combined.sym
$(DIR_GEN)/OUTB_x.BIN $(DIR_GEN)/BASIC_combined.vs: \
$(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_BASIC) $(CFG_GEN) $(GEN_STR_GEN) $(DIR_GEN)/KERNAL_combined.sym
$(DIR_TST38)/OUTB_x.BIN $(DIR_TST38)/BASIC_combined.vs: \
@@ -398,6 +408,8 @@ $(DIR_CUS)/OUTK_x.BIN $(DIR_CUS)/KERNAL_combined.vs $(DIR_CUS)/KERNAL_combined.s
$(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_KERNAL) $(CFG_CUS) $(GEN_STR_CUS)
$(DIR_C64)/OUTK_x.BIN $(DIR_C64)/KERNAL_combined.vs $(DIR_C64)/KERNAL_combined.sym: \
$(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_KERNAL) $(CFG_C64) $(GEN_STR_C64)
$(DIR_MC64)/OUTK_x.BIN $(DIR_MC64)/KERNAL_combined.vs $(DIR_MC64)/KERNAL_combined.sym: \
$(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_KERNAL) $(CFG_MC64) $(GEN_STR_MC64)
$(DIR_GEN)/OUTK_x.BIN $(DIR_GEN)/KERNAL_combined.vs $(DIR_GEN)/KERNAL_combined.sym: \
$(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_KERNAL) $(CFG_GEN) $(GEN_STR_GEN)
$(DIR_TST38)/OUTK_x.BIN $(DIR_TST38)/KERNAL_combined.vs $(DIR_TST38)/KERNAL_combined.sym: \
@@ -457,6 +469,7 @@ $(DIR_X16)/kernal.seg_1 $(DIR_X16)/KERNAL_1_combined.vs $(DIR_X16)/KERNAL_1_comb
$(DIR_CUS)/OUTx_x.BIN: $(DIR_CUS)/OUTB_x.BIN $(DIR_CUS)/OUTK_x.BIN
$(DIR_C64)/OUTx_x.BIN: $(DIR_C64)/OUTB_x.BIN $(DIR_C64)/OUTK_x.BIN
$(DIR_MC64)/OUTx_x.BIN: $(DIR_MC64)/OUTB_x.BIN $(DIR_MC64)/OUTK_x.BIN
$(DIR_GEN)/OUTx_x.BIN: $(DIR_GEN)/OUTB_x.BIN $(DIR_GEN)/OUTK_x.BIN
$(DIR_GENCRT)/OUTx_0.BIN: $(DIR_GENCRT)/OUTB_0.BIN $(DIR_GENCRT)/OUTK_0.BIN
$(DIR_TST38)/OUTx_x.BIN: $(DIR_TST38)/OUTB_x.BIN $(DIR_TST38)/OUTK_x.BIN
@@ -468,6 +481,7 @@ $(DIR_X16)/OUTx_0.BIN: $(DIR_X16)/OUTB_0.BIN $(DIR_X16)/OUTK_0.BIN
$(TARGET_CUS_B): $(DIR_CUS)/OUTx_x.BIN
$(TARGET_C64_B): $(DIR_C64)/OUTx_x.BIN
$(TARGET_MC64_B): $(DIR_MC64)/OUTx_x.BIN
$(TARGET_GEN_B): $(DIR_GEN)/OUTx_x.BIN
$(TARGET_TST38_B): $(DIR_TST38)/OUTx_x.BIN
$(TARGET_TST60_B): $(DIR_TST60)/OUTx_x.BIN
@@ -475,6 +489,7 @@ $(TARGET_U64_B): $(DIR_U64)/OUTx_x.BIN
$(TARGET_CUS_K): $(DIR_CUS)/OUTx_x.BIN
$(TARGET_C64_K): $(DIR_C64)/OUTx_x.BIN
$(TARGET_MC64_K): $(DIR_MC64)/OUTx_x.BIN
$(TARGET_GEN_K): $(DIR_GEN)/OUTx_x.BIN
$(TARGET_TST38_K): $(DIR_TST38)/OUTx_x.BIN
$(TARGET_TST60_K): $(DIR_TST60)/OUTx_x.BIN
@@ -482,6 +497,7 @@ $(TARGET_U64_K): $(DIR_U64)/OUTx_x.BIN
build/symbols_custom.vs: $(DIR_CUS)/BASIC_combined.vs $(DIR_CUS)/KERNAL_combined.vs
build/symbols_c64.vs: $(DIR_C64)/BASIC_combined.vs $(DIR_C64)/KERNAL_combined.vs
build/symbols_mc64.vs: $(DIR_MC64)/BASIC_combined.vs $(DIR_MC64)/KERNAL_combined.vs
build/symbols_generic.vs: $(DIR_GEN)/BASIC_combined.vs $(DIR_GEN)/KERNAL_combined.vs
build/symbols_generic_crt.vs: $(DIR_GENCRT)/BASIC_0_combined.vs $(DIR_GENCRT)/KERNAL_0_combined.vs
build/symbols_testing_38K.vs: $(DIR_TST38)/BASIC_combined.vs $(DIR_TST38)/KERNAL_combined.vs
@@ -499,6 +515,10 @@ $(GEN_STR_C64): $(TOOL_GENERATE_STRINGS) $(CFG_C64)
@mkdir -p $(DIR_C64)/,generated
$(TOOL_GENERATE_STRINGS) -o $@ -c $(CFG_C64)
$(GEN_STR_MC64): $(TOOL_GENERATE_STRINGS) $(CFG_MC64)
@mkdir -p $(DIR_MC64)/,generated
$(TOOL_GENERATE_STRINGS) -o $@ -c $(CFG_MC64)
$(GEN_STR_GEN): $(TOOL_GENERATE_STRINGS) $(CFG_GEN)
@mkdir -p $(DIR_GEN)/,generated
$(TOOL_GENERATE_STRINGS) -o $@ -c $(CFG_GEN)
@@ -541,6 +561,7 @@ build/,generated/,z80_tables.s: $(TOOL_GENERATE_Z80_TABLES)
GEN_STR_custom = $(GEN_STR_CUS)
GEN_STR_c64 = $(GEN_STR_C64)
GEN_STR_mc64 = $(GEN_STR_MC64)
GEN_STR_generic = $(GEN_STR_GEN)
GEN_STR_generic_crt = $(GEN_STR_GENCRT)
GEN_STR_testing_38K = $(GEN_STR_TST38)
+39
View File
@@ -0,0 +1,39 @@
This is a modified version of MEGA65 Open ROMs (https://github.com/MEGA65/open-roms),
forked at upstream commit ad178dbe4d48cd6a317737a8e0e7e662f7e33d32.
Modified by Christian Werner, 2026-10-14, 2026-10-15, and 2026-10-17, for the mc64
computers of arnitech, a set of Minecraft mods (https://git.susdog.de/chris/arnitech). The
fork lives at https://git.susdog.de/chris/open-roms, branch mc64.
Changes:
- src/,,config_mc64.s: a new build configuration, copied from src/,,config_c64.s, with its
own config ID ($6D), the brand "MC64", and BCD_SAFE_INTERRUPTS turned off.
- Makefile: targets for that configuration, build/kernal_mc64.rom and build/basic_mc64.rom,
made the same way as the c64 ones.
- src/kernal/iec/ciout.s (2026-10-15): CIOUT buffers its byte in TBTCNT, where the send
routine takes it from, not in BSOUR (upstream PR #113).
- src/kernal/iec/close_iec.s (2026-10-15): CLOSE sends LISTEN, $E0 plus the secondary
address, and UNLISTEN; it sent a command ORed with zero page $E0 and no LISTEN.
- src/kernal/iec/chkin_iec.s, ckout_iec.s (2026-10-15): CHKIN and CHKOUT take the secondary
address from SAT, not from LAT, the logical file numbers.
- src/kernal/iec/tksa.s (2026-10-15): TKSA sends the secondary address it is given, without
ORing $90 into it (upstream issue #116).
- src/kernal/iec/iec_tx_byte.s (2026-10-15): a data byte that no listener holds DATA for
sets ST to $80 (device not present) and returns, instead of waiting forever.
- src/kernal/iec/close_iec.s (2026-10-15): a CLOSE that finds no device sets ST to $80
(device not present), and still frees the file number.
- src/kernal/iec/unlsn.s, untlk.s (2026-10-15): UNLSN and UNTLK end with CLK, DATA, and ATN
released; UNLSN left CLK pulled, and UNTLK waited for a talker to pull CLK, which after
UNTALK none does, and then left CLK pulled.
- src/kernal/iec/iec_return.s (2026-10-15): a serial routine that finds no device releases
CLK, DATA, and ATN; it left CLK pulled.
- src/,,config_mc64.s, src/aliases/,aliases_hardware_arnitech.s, src/kernal/arnitech/
(new), Makefile, src/kernal/init/fda3.ioinit.s, CONFIG.md (2026-10-17): a new option,
ARNITECH_CONTROLLER, on in the mc64 configuration only. IOINIT sets CIA #1's TOD on 50 Hz
and, if the Arnitech controller's signature is at $DE80, from the controller's clock. The
Arnitech jump table at $FF00 wraps the controller's registers: "ARNI", a version, an entry
count, and JMPs from $FF06 to find a Card by its type and to set the TOD.
- NOTICE: this file.
The licence terms are unchanged; see LICENSE, COPYING, and COPYING.LESSER.
+133
View File
@@ -0,0 +1,133 @@
;; #CONFIG# ID $6D ; should be 1 byte, different for each config file!
;
; Please read CONFIG.md before modifying this file!
;
; Idea:
; The Firmware of arnitech's mc64 computers, a Minecraft mod
; Same as the 'c64' configuration, except:
; - the banner names mc64
; - BCD_SAFE_INTERRUPTS is off, for IRQ entry timing closer to the original
; - ARNITECH_CONTROLLER: IOINIT sets CIA1's TOD on 50 Hz and from the Arnitech controller's clock,
; and the Arnitech jump table is at $FF00 (src/kernal/arnitech)
; --- Hardware platform and brand
;; #CONFIG# PLATFORM_COMMODORE_64 YES
;; #CONFIG# BRAND_CUSTOM "MC64"
; --- Processor instruction set
;; #CONFIG# CPU_MOS_6502 YES
;; #CONFIG# CPU_DTV_6502 NO
;; #CONFIG# CPU_RCW_65C02 NO
;; #CONFIG# CPU_WDC_65C02 NO
;; #CONFIG# CPU_WDC_65816 NO
;; #CONFIG# CPU_CSG_65CE02 NO
; --- Memory model
;; #CONFIG# MEMORY_MODEL_38K YES
;; #CONFIG# MEMORY_MODEL_46K NO
;; #CONFIG# MEMORY_MODEL_50K NO
;; #CONFIG# MEMORY_MODEL_60K NO
; --- IEC bus configuration
;; #CONFIG# IEC YES
;; #CONFIG# IEC_DOLPHINDOS NO
;; #CONFIG# IEC_DOLPHINDOS_FAST NO
;; #CONFIG# IEC_JIFFYDOS NO
;; #CONFIG# IEC_JIFFYDOS_BLANK NO
; --- Tape deck configuration
;; #CONFIG# TAPE_NORMAL YES
;; #CONFIG# TAPE_TURBO NO
;; #CONFIG# TAPE_AUTODETECT NO
;; #CONFIG# TAPE_NO_KEY_SENSE NO
;; #CONFIG# TAPE_NO_MOTOR_CONTROL NO
; --- Sound support
;; #CONFIG# SID_2ND_ADDRESS NO
;; #CONFIG# SID_3RD_ADDRESS NO
;; #CONFIG# SID_D4XX NO
;; #CONFIG# SID_D5XX NO
;; #CONFIG# SID_D6XX NO
;; #CONFIG# SID_D7XX NO
; --- Keyboard settings
;; #CONFIG# KEYBOARD_C128 NO
;; #CONFIG# KEYBOARD_C128_CAPS_LOCK NO
;; #CONFIG# KEY_REPEAT_DEFAULT NO
;; #CONFIG# KEY_REPEAT_ALWAYS NO
;; #CONFIG# KEY_FAST_SCAN YES
;; #CONFIG# JOY1_CURSOR YES
;; #CONFIG# JOY2_CURSOR YES
;; #CONFIG# PROGRAMMABLE_KEYS YES
;; #CONFIG# KEYCMD_RUN "\5FL"
;; #CONFIG# KEYCMD_F1 "@8$"
;; #CONFIG# KEYCMD_F2 "LOAD"
;; #CONFIG# KEYCMD_F3 "@9$"
;; #CONFIG# KEYCMD_F4 "RUN:"
;; #CONFIG# KEYCMD_F5 "@10$"
;; #CONFIG# KEYCMD_F6 NO
;; #CONFIG# KEYCMD_F7 "@11$"
;; #CONFIG# KEYCMD_F8 NO
;; #CONFIG# KEYCMD_HELP "LIST"
; --- Screen editor
;; #CONFIG# EDIT_STOPQUOTE YES
; --- Software features
;; #CONFIG# PANIC_SCREEN YES
;; #CONFIG# DOS_WEDGE NO
;; #CONFIG# TAPE_WEDGE NO
;; #CONFIG# TAPE_HEAD_ALIGN NO
;; #CONFIG# BCD_SAFE_INTERRUPTS NO
;; #CONFIG# ARNITECH_CONTROLLER YES
; --- BASIC features
;; #CONFIG# ORIGINAL_UNPATCHED_BASIC YES
;; #CONFIG# TRANSCENDENTAL_FUNCTIONS YES
; --- Eye candy
;; #CONFIG# COLORS_BRAND NO
;; #CONFIG# BANNER_SIMPLE YES
;; #CONFIG# BANNER_FANCY NO
;; #CONFIG# SHOW_FEATURES YES
; --- Debug options
;; #CONFIG# DBG_STUBS_BRK NO
;; #CONFIG# DBG_PRINTF NO
; --- Other
;; #CONFIG# COMPRESSION_LVL_2 NO
+26
View File
@@ -0,0 +1,26 @@
;
; Names of the Arnitech controller's registers, on the expansion port's I/O1 (mc64 only)
;
; See arnitech's ADR 0023, "The Arnitech controller answers $DE80-$DE9F, and six Card windows
; follow it" (https://git.susdog.de/chris/arnitech, docs/adr/0023-arnitech-controller-register-map.md)
;
!ifdef CONFIG_ARNITECH_CONTROLLER {
!addr ARNITECH_SIGNATURE = $DE80 ; "ARNI", 4 bytes
!addr ARNITECH_VERSION = $DE84
!addr ARNITECH_SLOT_COUNT = $DE85 ; Card slots in this Case
!addr ARNITECH_IRQ_STATUS = $DE86
!addr ARNITECH_IRQ_MASK = $DE87
!addr ARNITECH_SLOT_TABLE = $DE88 ; the type of the Card in slots 0-5, $00 for none
!addr ARNITECH_CLOCK_LATCH = $DE90 ; a read copies the clock into $DE91-$DE9E
!addr ARNITECH_CLOCK_TEN = $DE91 ; real time as CIA1's TOD reads it: tenths,
!addr ARNITECH_CLOCK_SEC = $DE92 ; seconds,
!addr ARNITECH_CLOCK_MIN = $DE93 ; minutes,
!addr ARNITECH_CLOCK_HRS = $DE94 ; hours, BCD 1-12, bit 7 PM
!addr ARNITECH_CARD_WINDOW = $DEA0 ; slot n's Card window at $DEA0 + 16 * n
}
+64
View File
@@ -0,0 +1,64 @@
;; #LAYOUT# STD * #TAKE
;; #LAYOUT# * * #IGNORE
;
; The Arnitech controller (mc64 only, arnitech's ADR 0023): its signature and its Slot table
;
!ifdef CONFIG_ARNITECH_CONTROLLER {
;
; Whether the controller answers: its signature "ARNI" at $DE80, compared with the jump table's.
; Out: carry clear if it does, carry set if not. A and X are not kept, Y is.
;
arnitech_check_signature:
ldx #$03
@1:
lda ARNITECH_SIGNATURE, x
cmp arnitech_jumptable, x
bne @2
dex
bpl @1
clc
rts
@2:
sec
rts
;
; ARNI_FINDCARD, $FF06: see ff00.arnitech_jumptable.s
;
arnitech_find_card:
pha
jsr arnitech_check_signature
pla
bcs @2 ; no controller
ldx #$00
@1:
cpx ARNITECH_SLOT_COUNT
bcs @2 ; past the last slot, carry set
cmp ARNITECH_SLOT_TABLE, x
beq @3
inx
bne @1 ; always taken
@2:
rts
@3:
txa
pha
asl
asl
asl
asl ; 16 * slot
clc
adc #<ARNITECH_CARD_WINDOW
tax
pla
rts ; carry clear
}
+58
View File
@@ -0,0 +1,58 @@
;; #LAYOUT# STD * #TAKE
;; #LAYOUT# * * #IGNORE
;
; CIA1's TOD from the Arnitech controller's real time (mc64 only, arnitech's ADR 0023)
;
; The controller lays its time out as the TOD reads it, so the copy goes hours first, which stops
; the TOD, and tenths last, which starts it. The CIA flips the PM bit when an hour of 12 is
; written (VICE does so too), so an hour of 12 has bit 7 flipped first.
;
!ifdef CONFIG_ARNITECH_CONTROLLER {
;
; ARNI_SETTOD, $FF09: see ff00.arnitech_jumptable.s
;
arnitech_set_tod:
lda CIA1_CRA
ora #$80 ; TOD on 50 Hz, the mc64's mains
sta CIA1_CRA
; FALLTHROUGH
;
; The copy alone, for IOINIT, which has set CRA already.
; Out: carry clear if set, carry set if no controller answers. A and X are not kept, Y is.
;
arnitech_tod_from_clock:
jsr arnitech_check_signature
bcs @2
lda ARNITECH_CLOCK_LATCH ; copies the clock into $DE91-$DE9E
ldx ARNITECH_CLOCK_HRS
txa
and #$7F
cmp #$12
bne @1
txa
eor #$80 ; the CIA flips it back
tax
@1:
stx CIA1_TODHRS ; stops the TOD
lda ARNITECH_CLOCK_MIN
sta CIA1_TODMIN
lda ARNITECH_CLOCK_SEC
sta CIA1_TODSEC
lda ARNITECH_CLOCK_TEN
sta CIA1_TODTEN ; starts it
clc
@2:
rts
}
@@ -0,0 +1,40 @@
;; #LAYOUT# STD * #TAKE
;; #LAYOUT# * * #IGNORE
;
; The Arnitech jump table (mc64 only): thin wrappers over the Arnitech controller's registers
; (arnitech's ADR 0023), at fixed addresses. Software finds it by reading "ARNI" at $FF00 with
; the KERNAL banked in; on any other KERNAL it uses the registers themselves, which work the same.
; Entries are only ever added, after the last, with the version and count raised; $FF48-$FF80
; stay clear, for the stock IRQ entry, CINT, and the KERNAL revision byte.
;
; $FF00-$FF03 "ARNI"
; $FF04 version of the table, $01
; $FF05 number of entries
;
; $FF06 ARNI_FINDCARD - finds the first Card slot holding a Card of a given type
; In: A = the Card's type ($01 Redstone Card, $02 Internet Card; $00 finds an empty slot)
; Out: carry clear if found: A = the slot (0-5), X = the low byte of its Card window
; ($DEA0 + 16 * slot, so LDA $DE00,X reads the window's first byte);
; carry set if no slot holds one, or no controller answers (a Cartridge switched it off)
; Y is kept; A and X are not, when none is found
;
; $FF09 ARNI_SETTOD - sets CIA1's TOD from the controller's real time, as IOINIT does at boot
; In: nothing; CIA1's CRB bit 7 must be 0, or the time goes into the TOD alarm
; Out: carry clear if set: the TOD on 50 Hz (CIA1 CRA bit 7) and started at the time the
; controller's clock latch read; carry set if no controller answers, with the TOD
; untouched but on 50 Hz all the same
; A and X are not kept, Y is
;
!ifdef CONFIG_ARNITECH_CONTROLLER {
arnitech_jumptable:
!byte $41, $52, $4E, $49 ; "ARNI"
!byte $01 ; version
!byte $02 ; entries
jmp arnitech_find_card ; $FF06
jmp arnitech_set_tod ; $FF09
}
+2 -2
View File
@@ -14,7 +14,7 @@ chkin_iec:
; Fail if the file is open for writing (secondary address 1)
lda LAT, Y
lda SAT, Y
cmp #$01
+beq chkin_file_not_input
@@ -24,7 +24,7 @@ chkin_iec:
jsr TALK
+bcs chkinout_device_not_present
lda LAT, Y
lda SAT, Y
ora #$60
jsr TKSA
+bcs chkinout_device_not_present
+3 -2
View File
@@ -28,9 +28,10 @@ CIOUT:
ciout_store_in_buffer:
; Store in the buffer data to be sent next, return
; Store in the buffer data to be sent next, return; iec_tx_byte
; sends the byte from TBTCNT, so that is our buffer, not BSOUR
pla
sta BSOUR
sta TBTCNT
rts
ciout_send_byte:
+2 -2
View File
@@ -14,7 +14,7 @@ ckout_iec:
; Fail if the file is open for reading (secondary address 0)
lda LAT, Y
lda SAT, Y
+beq ckout_file_not_output
; Send LISTEN + SECOND first
@@ -23,7 +23,7 @@ ckout_iec:
jsr LISTEN
+bcs chkinout_device_not_present
lda LAT, Y
lda SAT, Y
ora #$60
jsr SECOND
+bcs chkinout_device_not_present
+14 -2
View File
@@ -23,11 +23,23 @@ close_iec:
jsr iec_close_load
jmp close_remove_from_table
@1:
ora $E0 ; CLOSE command
; LISTEN, CLOSE, UNLISTEN - see https://www.pagetable.com/?p=1031
lda FAT, y
jsr LISTEN
bcs close_iec_not_present
lda SAT, y
ora #$E0 ; CLOSE command
sta TBTCNT
jsr iec_tx_command
bcs close_iec_end
bcs close_iec_not_present
jsr iec_tx_command_finalize
jsr UNLSN
jmp close_remove_from_table
close_iec_not_present:
; The file is closed all the same; READST says device not present
jsr kernalstatus_DEVICE_NOT_FOUND
; FALLTROUGH
+2 -2
View File
@@ -36,8 +36,8 @@ iec_return_success:
iec_return_DEVICE_NOT_FOUND:
; Set IEC line to normal idle state
jsr iec_set_idle
; Nobody answers: release all lines, so the bus is idle - see https://www.pagetable.com/?p=1135
jsr iec_release_atn_clk_data
; BSOUR is certainly not valid anymore
lda #$00
+11
View File
@@ -51,6 +51,17 @@ iec_tx_byte:
+phx_trash_a
+phy_trash_a
; A listener holds DATA until we release CLK; if nobody pulls it
; within 256us, no device is present - see https://www.pagetable.com/?p=1135
ldx #$18
@0:
lda CIA2_PRA
bpl @1 ; branch if DATA is pulled
dex
bne @0
jsr kernalstatus_DEVICE_NOT_FOUND
jmp iec_return_DEVICE_NOT_FOUND
@1:
; Notify all devices that we are going to send a byte
; and it is going to be a data byte (released ATN)
jsr iec_release_atn_clk_data
-2
View File
@@ -28,8 +28,6 @@ TKSA:
; - https://www.lemon64.com/forum/viewtopic.php?t=57694&sid=531ba3592bcffadef2ac8b9162f2e529
; - https://www.pagetable.com/?p=1031 (Kernal API description)
ora #$90
jmp common_untlk_tksa
} else {
+9 -1
View File
@@ -42,7 +42,15 @@ UNLSN:
; Buffer empty, send the command
lda #$3F
jmp common_open_close_unlsn_second
common_unlsn_untlk: ; common part of UNLSN and UNTLK
jsr common_open_close_unlsn_second
bcs @1
; The transmission is over: release CLK and DATA too, so the bus is idle - see https://www.pagetable.com/?p=1135
jmp iec_release_clk_data
@1:
rts
} else {
+3 -2
View File
@@ -39,10 +39,11 @@ UNTLK:
sta IECPROTO
}
; Buffer empty, send the command
; Buffer empty, send the command; the talker releases the bus - see https://www.pagetable.com/?p=1031
lda #$5F
jmp common_unlsn_untlk
common_untlk_tksa: ; common part of UNTLK and TKSA
common_untlk_tksa: ; the rest of TKSA
; XXX - for TKSA, is it really the right place to do a turnaround? I have some doubts
; (it forces us to send the TKSA command 'manually' sometimes), but
+10
View File
@@ -168,8 +168,18 @@ IOINIT_skip_DOS:
jsr setup_irq_timer
; Enable timer A to run continuously (http://codebase64.org/doku.php?id=base:timerinterrupts)
!ifdef CONFIG_ARNITECH_CONTROLLER {
; ... with the TOD on 50 Hz, the mc64's mains, set from the Arnitech controller's clock
ldx #$91
stx CIA1_CRA ; $DC0E
jsr arnitech_tod_from_clock
} else {
ldx #$11
stx CIA1_CRA ; $DC0E
}
; Enable timer interrupt
ldx #$81