more sane directory name, updated binaries

This commit is contained in:
FeralChild64 committed 2020-06-26 19:44:01 +02:00
1 parent d4d32095d1
commit 76aaf298b8
697 files changed
+56 -56

No files matched your search

+33
View File
@@ -0,0 +1,33 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Official Kernal routine, described in:
//
// - [RG64] C64 Programmers Reference Guide - page 274
// - [CM64] Computes Mapping the Commodore 64 - page 224/225
//
// CPU registers that has to be preserved (see [RG64]): .Y
//
ACPTR:
lda IOSTATUS
beq !+
clc
lda #$0D // tested on real ROMs
rts
!:
#if CONFIG_IEC
#if CONFIG_IEC_JIFFYDOS
jmp iec_rx_dispatch
#else
jmp iec_rx_byte
#endif
#else
jmp kernalerror_ILLEGAL_DEVICE_NUMBER
#endif
+34
View File
@@ -0,0 +1,34 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// IEC part of the CHKIN routine
//
#if CONFIG_IEC
chkin_iec:
// Fail if the file is open for writing (secondary address 1)
lda LAT, Y
cmp #$01
beq_16 chkin_file_not_input
// Send TALK + TKSA first
lda FAT,Y
jsr TALK
bcs_16 chkinout_device_not_present
lda LAT, Y
ora #$60
jsr TKSA
bcs_16 chkinout_device_not_present
jmp chkin_set_device
#endif // CONFIG_IEC
+13
View File
@@ -0,0 +1,13 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// IEC part of the CHRIN routine
//
chrin_iec:
// XXX is this really all?
jmp JACPTR
+15
View File
@@ -0,0 +1,15 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// IEC part of the CHROUT routine
//
chrout_iec:
lda SCHAR
jsr JCIOUT
bcc_16 chrout_done_success
jmp chrout_done_fail
+52
View File
@@ -0,0 +1,52 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Official Kernal routine, described in:
//
// - [RG64] C64 Programmers Reference Guide - page 279/280
// - [CM64] Computes Mapping the Commodore 64 - page 224
//
// CPU registers that has to be preserved (see [RG64]): .X, .Y
//
CIOUT:
#if CONFIG_IEC
pha
lda C3PO
bne ciout_send_byte
// Nothing to send - set buffer as valid, store byte there
inc C3PO
// Clear carry flag to indicate success
clc
ciout_store_in_buffer:
// Store in the buffer data to be sent next, return
pla
sta BSOUR
rts
ciout_send_byte:
clc // send without EOI
#if CONFIG_IEC_JIFFYDOS
jsr iec_tx_dispatch
#else
jsr iec_tx_byte
#endif
inc C3PO // tx byte routine sets to 0, but we still have something to send
jmp ciout_store_in_buffer
#else
sec // indicate failure
rts
#endif
+34
View File
@@ -0,0 +1,34 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// IEC part of the CKOUT routine
//
#if CONFIG_IEC
ckout_iec:
// Fail if the file is open for reading (secondary address 0)
lda LAT, Y
beq_16 ckout_file_not_output
// Send LISTEN + SECOND first
lda FAT,Y
jsr LISTEN
bcs_16 chkinout_device_not_present
lda LAT, Y
ora #$60
jsr SECOND
bcs_16 chkinout_device_not_present
jmp ckout_set_device
#endif // CONFIG_IEC
+38
View File
@@ -0,0 +1,38 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// IEC part of the CLOSE routine
//
#if CONFIG_IEC
// .Y contains LAT/FAT/SAT table index, it should stay this way
close_iec:
jsr iec_tx_flush // make sure no byte is awaiting
lda SAT, y // get secondary address
cmp #$60
bne !+
// workaround for using CLOSE on reading executable - XXX is this a proper way?
jsr iec_close_load
jmp close_remove_from_table
!:
ora $E0 // CLOSE command
sta TBTCNT
jsr iec_tx_command
bcs close_iec_end
jsr iec_tx_command_finalize
close_iec_end:
jmp close_remove_from_table
#endif // CONFIG_IEC
+33
View File
@@ -0,0 +1,33 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// IEC part of the CLRCHN routine
//
#if CONFIG_IEC
clrchn_iec:
// Check input device
lda DFLTN
jsr iec_check_devnum_oc
bcs !+
// It was IEC device - send UNTALK first
jsr UNTLK
!:
// Check output device
lda DFLTO
jsr iec_check_devnum_oc
// If it was IEC device - send UNLSN first
bcc_16 UNLSN
rts
#endif // CONFIG_IEC
+36
View File
@@ -0,0 +1,36 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Checks whether device number (in .A) is a correct IEC device number
//
// Preserves .A, .X and .Y
//
#if CONFIG_IEC
iec_check_devnum_lvs: // for load/verify/save
cmp #$08 // below 8 are illegal for load/save
bcc iec_check_devnum_failed
// FALLTROUGH
iec_check_devnum_oc: // for open/close
cmp #$04 // below 4 are illegal, reserved for non-IEC devices on Commodore
bcc iec_check_devnum_failed
// 31 and above are illegal too, due to IEC command encoding scheme,
// see https://www.pagetable.com/?p=1031
cmp #$1F // sets carry for 31 or above
rts
iec_check_devnum_failed:
sec // indicate non-IEC device
rts
#endif // CONFIG_IEC
+34
View File
@@ -0,0 +1,34 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Common part of CLOSE and LOAD/SAVE routines for IEC
//
#if CONFIG_IEC
iec_close_load:
tax
// Command drive to stop talking before closing the file
jsr UNTLK
txa
jsr LISTEN
lda #$E0 // CLOSE command
sta TBTCNT
jsr iec_tx_command
jsr iec_tx_command_finalize
// Tell drive to unlisten
jsr UNLSN
rts
#endif // CONFIG_IEC
+26
View File
@@ -0,0 +1,26 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Kernal internal IEC routine
//
// - https://www.pagetable.com/?p=1031, https://github.com/mist64/cbmbus_doc
//
#if CONFIG_IEC
iec_cmd_close:
jsr iec_check_channel_openclose
bcc !+
jmp kernalerror_FILE_NOT_INPUT
!:
ora #$E0
jmp common_open_close_unlsn_second
#endif // CONFIG_IEC
+71
View File
@@ -0,0 +1,71 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Kernal internal IEC routine
//
// - https://www.pagetable.com/?p=1031, https://github.com/mist64/cbmbus_doc
//
#if CONFIG_IEC
iec_cmd_open: // similar to TKSA, but without turnaround
jsr iec_check_channel_openclose
bcc !+
jmp kernalerror_FILE_NOT_INPUT
!:
ora #$F0
#if CONFIG_IEC_BURST_CIA1 || CONFIG_IEC_BURST_CIA2 || CONFIG_IEC_BURST_MEGA_65
pha
jsr burst_advertise
pla
#endif
#if CONFIG_IEC_DOLPHINDOS
sta TBTCNT
jsr iec_tx_command
bcs !+ // branch if error
jsr dolphindos_detect
jmp iec_tx_command_finalize
#else
// FALLTROUGH
#endif
common_open_close_unlsn_second: // common part of several commands
sta TBTCNT
jsr iec_tx_command
bcs !+ // branch if error
jmp iec_tx_command_finalize
!:
rts
iec_check_channel_openclose:
// Due to OPEN/CLOSE/TKSA/SECOND command encoding (see https://www.pagetable.com/?p=1031),
// allowed channels are 0-15; report error if out of range
cmp #$10
bcc !+
// Workaround to allow reading executable files and disk directory
// using OPEN routine - see https://www.pagetable.com/?p=273 for
// example usage
cmp #$60
beq !+
sec // mark unsuitable channel number
rts
!:
clc // mark suitable channel number
rts
#endif // CONFIG_IEC
+88
View File
@@ -0,0 +1,88 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Helper IEC routines to pull/release certain lines
//
// Order of operation is set for extra robustness, on non-emulated hardware
// lines might need few cycles to stabilize (released CLK = DATA considered valid),
// see page 10 of http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
//
#if CONFIG_IEC
iec_pull_atn_clk_release_data:
lda CIA2_PRA
ora #BIT_CIA2_PRA_ATN_OUT // pull
sta CIA2_PRA
// FALLTROUGH
iec_pull_clk_release_data:
lda CIA2_PRA
ora #BIT_CIA2_PRA_CLK_OUT // pull
sta CIA2_PRA
!:
and #$FF - BIT_CIA2_PRA_DAT_OUT // release
bne iec_pull_release_end // branch always
iec_pull_clk_release_data_oneshot:
lda CIA2_PRA
ora #BIT_CIA2_PRA_CLK_OUT // pull
bne !- // branch always
iec_release_atn_clk_data:
lda CIA2_PRA
and #$FF - BIT_CIA2_PRA_ATN_OUT // release
sta CIA2_PRA
// FALLTROUGH
iec_release_clk_data:
lda CIA2_PRA
and #$FF - BIT_CIA2_PRA_DAT_OUT // release
sta CIA2_PRA
and #$FF - BIT_CIA2_PRA_CLK_OUT // release
jmp iec_pull_release_end
iec_release_clk_pull_data:
lda CIA2_PRA
ora #BIT_CIA2_PRA_DAT_OUT // pull
sta CIA2_PRA
and #$FF - BIT_CIA2_PRA_CLK_OUT // release
bne iec_pull_release_end // branch always
iec_pull_data_release_atn_clk:
lda CIA2_PRA
ora #BIT_CIA2_PRA_DAT_OUT // pull
sta CIA2_PRA
and #$FF - BIT_CIA2_PRA_CLK_OUT // release
sta CIA2_PRA
// FALLTROUGH
iec_release_atn:
lda CIA2_PRA
and #$FF - BIT_CIA2_PRA_ATN_OUT // release
// FALLTROUGH
iec_pull_release_end:
sta CIA2_PRA
rts
#endif // CONFIG_IEC
+44
View File
@@ -0,0 +1,44 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Helper routines to return with error/success
//
// All of them restore X/Y registers from stack,
// they take care about Carry flag,
// error return reeset IEC line to default state,
// take care about .A and IOSTATUS
//
#if CONFIG_IEC
iec_return_success:
// BSOUR is certainly not valid anymore
lda #$00
sta C3PO
// Restore registers
ply_trash_a
plx_trash_a
// Report success
clc
rts
iec_return_DEVICE_NOT_FOUND:
// Set IEC line to normal idle state
jsr iec_set_idle
// BSOUR is certainly not valid anymore
lda #$00
sta C3PO
// Restore registers
ply_trash_a
plx_trash_a
// Report error
jmp kernalerror_DEVICE_NOT_FOUND
#endif // CONFIG_IEC
+161
View File
@@ -0,0 +1,161 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
// Receive a byte from the IEC bus.
// Implemented based on https://www.pagetable.com/?p=1135, https://github.com/mist64/cbmbus_doc,
// http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf (page 11)
//
// Preserves .X and .Y registers
#if CONFIG_IEC
#if CONFIG_IEC_JIFFYDOS
iec_rx_dispatch:
lda IECPROTO
cmp #$01
beq_16 jiffydos_rx_byte
// FALLTROUGH
#endif // CONFIG_IEC_JIFFYDOS
iec_rx_byte:
// Store .X and .Y on the stack - preserve them
phx_trash_a
phy_trash_a
// Timing is critical here - execute on disabled IRQs
// The best practice would be to do PHP first, but it seems this is not
// what the original ROM does; furthermore, pushing additional bytes to
// stack can wreck autostart softwaree loading at $0100
sei
// First, we wait for the talker to release the CLK line
jsr iec_wait_for_clk_release
// We then release the DATA to signal we are ready
// We can use this routine, since we were not pulling CLK anyway
jsr iec_release_clk_data
// Wait till data line is released (someone else might be holding it)
jsr iec_wait_for_data_release
// Check if EOI
jsr iec_rx_check_eoi
#if CONFIG_IEC_DOLPHINDOS
// Check if DolphinDOS was detected
lda IECPROTO
cmp #$02
bne iec_rx_no_dolphindos
// For DolphinDOS just fetch the byte from parallel port
lda CIA2_PRB
pha
jmp iec_rx_acknowledge
iec_rx_no_dolphindos:
#endif // CONFIG_IEC_DOLPHINDOS
// Latch input bits in on rising edge of CLK, eight times for eight bits.
ldx #7
// Get empty byte to load into.
lda #$00
pha
iec_rx_bit_loop:
// Wait for CLK to release
jsr iec_wait_for_clk_release
// (we do this implicitly below, with a tighter routine,
// so that we do not have timing problems, as the requirements
// are quite tight. Basically we need to read the clock and data
// bit from the same byte read.
// DATA now has the next bit, but inverted (well, except that it turns out not to be).
// DATA is in bit 7, which is a bit annoying.
// But we can clock it out with a ROL instruction
// so that it is in C. We can then ROR it into the
// partial data byte.
// We use ROR so that we shift in from the top, so that
// the first bit we shift in ends up in bit 0 after all
// 8 bits have been read.
// ODD: For some reason we don't need to invert the
// received bits. This is weird, because we invert them
// on the way out, and everything in the protocol seems
// to indicate that we sould do so. But experimentation
// has confirmed the bits don't need inversion on reception.
// Move data bit into C flag, and loop until bit 6 clears
// i.e., the clock has been released.
!: lda CIA2_PRA
rol
bpl !-
// Pull it into the data byte
pla
ror
pha
// Wait for CLK to be pulled again, over 300 usec (307 cycles on NTSC)
// consider this a timeout
ldy #$19 // 2 cycles
iec_rx_clk_wait2:
lda CIA2_PRA // 4 cycles
rol // 2 cycles, to put CLK in as the last bit
bpl !+ // 2 cycles if not jumped
dey // 2 cycles
bne iec_rx_clk_wait2 // 3 cycles if jumped
// Timeout
jsr kernalstatus_EOI
pla
jmp iec_rx_end
!:
// More bits?
dex
bpl iec_rx_bit_loop
// FALLTROUGH
iec_rx_acknowledge:
// Then we must within 1000 usec acknowledge the byte by
// pulling DATA. At this point, CLK is pulled by the
// talker and DATA by us, i.e., we are ready to receive
// the next byte. (p11).
jsr iec_release_clk_pull_data
// Retrieve the received byte
pla
// Restore registers
sta TBTCNT // $A4 is a byte buffer according to http://sta.c64.org/cbm64mem.html
// FALLTROUGH
iec_rx_end:
ply_trash_a
plx_trash_a
lda TBTCNT
clc
cli
rts
#endif // CONFIG_IEC
+44
View File
@@ -0,0 +1,44 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Helper routine to check for EOI while receiving byte from IEC
//
#if CONFIG_IEC
iec_rx_check_eoi:
// Wait for talker to pull CLK.
// If over 200 usec (205 cycles on NTSC machine) , then it is EOI.
// Loop iteraction takes 11 cycles, 19 full iterations are enough
ldx #$13 // 2 cycles
!:
bit CIA2_PRA // 4 cycles
bvc iec_rx_check_eoi_done // 2 cycles if not jumped
dex // 2 cycles
bne !- // 3 cycles if jumped
// FALLTROUGH
iec_rx_check_eoi_confirm:
// Timeout - either this is the last byte of stream, or the stream is empty at all.
// Mark end of stream in IOSTATUS
jsr kernalstatus_EOI
// Pull data for 60 usec to confirm it
jsr iec_release_clk_pull_data
jsr iec_wait60us
jsr iec_release_clk_data
iec_rx_check_eoi_done:
rts
#endif // CONFIG_IEC
+49
View File
@@ -0,0 +1,49 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Sends file (stream) name to IEC device
//
#if CONFIG_IEC
iec_send_file_name:
ldy #0
iec_send_file_name_loop:
cpy FNLEN
beq iec_send_file_name_done
#if CONFIG_MEMORY_MODEL_60K
ldx #<FNADDR+0
jsr peek_under_roms
#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K
jsr peek_under_roms_via_FNADDR
#else // CONFIG_MEMORY_MODEL_38K
lda (FNADDR),y
#endif
iny
// Set Carry flag on the last file name character, to mark EOI
cpy FNLEN
clc
bne !+
sec
!:
// Transmit one character
sta TBTCNT
#if CONFIG_IEC_JIFFYDOS
jsr iec_tx_dispatch
#else
jsr iec_tx_byte
#endif
jmp iec_send_file_name_loop
iec_send_file_name_done:
jmp UNLSN
#endif // CONFIG_IEC
+17
View File
@@ -0,0 +1,17 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
#if CONFIG_IEC
iec_set_idle:
lda CIA2_PRA
ora #BIT_CIA2_PRA_CLK_OUT // pull
and #$FF - BIT_CIA2_PRA_DAT_OUT - BIT_CIA2_PRA_ATN_OUT // release
sta CIA2_PRA
rts
#endif // CONFIG_IEC
+45
View File
@@ -0,0 +1,45 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
// According to http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
// pages 7--8.
// See also https://www.pagetable.com/?p=1135, https://github.com/mist64/cbmbus_doc
#if CONFIG_IEC
iec_turnaround_to_listen:
// Store .X and .Y on the stack - preserve them
phx_trash_a
phy_trash_a
// Timing is critical here - execute on disabled IRQs
php
sei
// Pull DATA, release CLK and ATN (we are not sending commands)
jsr iec_pull_data_release_atn_clk
// Wait for clock line to be pulled by the drive
ldx #$FF // XXX should we really use that high number?
!:
lda CIA2_PRA
rol // to put BIT_CIA2_PRA_CLK_IN as the last (sign) bit
bpl !+
dex
bne !-
// Timeout - XXX what errors do original Kernal report?
plp
jmp iec_return_DEVICE_NOT_FOUND
// CLK is pulled by the device, OK
!:
plp
jmp iec_return_success
#endif // CONFIG_IEC
+37
View File
@@ -0,0 +1,37 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
// According to http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
// pages 7--8.
// See also https://www.pagetable.com/?p=1135, https://github.com/mist64/cbmbus_doc
#if CONFIG_IEC
iec_turnaround_to_talk:
// Store .X and .Y on the stack - preserve them
phx_trash_a
phy_trash_a
// Timing is critical here - execute on disabled IRQs
php
sei
// First make sure both CLK, DATA and ATN are released at our side
jsr iec_release_atn
jsr iec_release_clk_data
// Wait till device releases CLK line
jsr iec_wait_for_clk_release
// Pull CLK line, it should be held by talker
jsr iec_pull_clk_release_data
plp
jmp iec_return_success
#endif // CONFIG_IEC
+166
View File
@@ -0,0 +1,166 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
// Implemented based on https://www.pagetable.com/?p=1135, https://github.com/mist64/cbmbus_doc
// Expects byte to send in TBTCNT ($A4 is a byte buffer according to http://sta.c64.org/cbm64mem.html)
// Carry flag set = signal EOI
//
// Preserves .X and .Y registers
#if CONFIG_IEC
#if CONFIG_IEC_JIFFYDOS
iec_tx_dispatch:
php // preserve C flag for EOI indication
lda IECPROTO
cmp #$01
bne !+
plp
jmp jiffydos_tx_byte
!:
plp
// FALLTROUGH
#endif // CONFIG_IEC_JIFFYDOS
iec_tx_byte:
// Store .X and .Y on the stack - preserve them
phx_trash_a
phy_trash_a
// 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
// Common part of iec_tx_byte and iec_tx_command
// Implemented based on https://www.pagetable.com/?p=1135, https://github.com/mist64/cbmbus_doc
// and http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
iec_tx_common:
// Timing is critical here - execute on disabled IRQs
// The best practice would be to do PHP first, but it seems this is not
// what the original ROM does; furthermore, pushing additional bytes to
// stack can wreck autostart software loading at $0100
sei
// Wait till all receivers are ready, they should all release DATA
jsr iec_wait_for_data_release
bcc !+
// At this point a delay 256 usec or more is considered EOI,
// receiver should now acknowledge it by pulling data for at least 60 usec
// Keep the implementation as simple as possible: data should be released now
// so wait until it is pushed and released again
jsr iec_wait_for_data_pull
jsr iec_wait_for_data_release
!:
#if CONFIG_IEC_DOLPHINDOS
// Check if DolphinDOS was detected
lda IECPROTO
cmp #$02
bne iec_tx_no_dolphindos
// For DolphinDOS just push the byte to parallel port (set it to output first)
lda #$FF
sta CIA2_DDRB
lda TBTCNT
sta CIA2_PRB
// Pull CLK to indicate data is now valid (we should not hold DATA nevertheless)
jsr iec_pull_clk_release_data_oneshot
// Finish the flow
jmp iec_tx_common_finalize
iec_tx_no_dolphindos:
#endif // CONFIG_IEC_DOLPHINDOS
// Pull CLK back to indicate that DATA is not valid, keep it for 60us
// We can use this routine as we don't hold DATA anyway (and its state doesn't even matter)
jsr iec_pull_clk_release_data_oneshot
jsr iec_wait60us
// Now, we can start transmission of 8 bits of data
ldx #7
iec_tx_common_sendbit:
#if CONFIG_IEC_JIFFYDOS
bne !+ // branch if not sending the last bit
lda IECPROTO
beq !+ // branch if standard protocol
// JiffyDOS ROM performs detection loop on every command; it seems we have to
// replicate this behaviour for compatibility with at least 1541 JiffyDOS ROM
jsr jiffydos_detect
!:
#endif // CONFIG_IEC_JIFFYDOS
// Is next bit 0 or 1?
lda TBTCNT
lsr
sta TBTCNT
bcs !+
// Bit is 0
jsr iec_release_clk_pull_data
jmp iec_tx_common_bit_is_sent
!:
// Bit is 1
jsr iec_release_clk_data
iec_tx_common_bit_is_sent:
// Wait 20us, so that device(s) can pick DATA
jsr iec_wait20us
// Pull CLK for 20us again, before sending the next bit
// or performing any other action
jsr iec_pull_clk_release_data_oneshot
jsr iec_wait20us
// More bits to send?
dex
bpl iec_tx_common_sendbit
// FALLTROUGH
iec_tx_common_finalize:
cli
// Give devices time to tell if they are busy by pulling DATA
// They should do it within 1ms
ldx #$FF
!:
lda CIA2_PRA
// BPL here is checking that bit 7 clears,
// i.e, that the DATA line is pulled by drive
bpl !+
dex
bne !-
bmi !+
jmp iec_return_DEVICE_NOT_FOUND
!:
jmp iec_return_success
#endif // CONFIG_IEC
+46
View File
@@ -0,0 +1,46 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
// Implemented based on https://www.pagetable.com/?p=1135, https://github.com/mist64/cbmbus_doc
// Expects byte to send in TBTCNT ($A4 is a byte buffer according to http://sta.c64.org/cbm64mem.html)
// Carry flag set = signal EOI
//
// Preserves .X and .Y registers
#if CONFIG_IEC
iec_tx_command:
// Store .X and .Y on the stack - preserve them
phx_trash_a
phy_trash_a
// Notify all devices that we are going to send a byte
// and it is going to be a command (pulled ATN)
jsr iec_pull_atn_clk_release_data
// Give devices time to respond (response is mandatory!) by pulling DATA
jsr iec_wait1ms
lda CIA2_PRA // pulled DATA = highest bit 0 = 'plus'
bpl !+
jmp iec_return_DEVICE_NOT_FOUND
!:
// At least one device responded, but they are still allowed to stall
// (can be busy processing something), we have to wait till they are all
// ready (or bored with DOS attack...)
// Release back CLK, keep DATA released - to ask devices for status.
jsr iec_release_clk_data
// Common part of iec_txbyte and iec_tx_common - waits for devices
// and transmits a byte
clc // Carry flag set is used for EOI mark
jmp iec_tx_common
#endif // CONFIG_IEC
+27
View File
@@ -0,0 +1,27 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
// Routine to finalize some IEC commands - which do not end in turnaround and are not followed by others
// Implemented based on https://www.pagetable.com/?p=1135, https://github.com/mist64/cbmbus_doc
#if CONFIG_IEC
iec_tx_command_finalize:
// Store .X and .Y on the stack - preserve them
phx_trash_a
phy_trash_a
// Give device some time to complete command reception, release ATN,
// give it some time again before (possible) next command
jsr iec_wait20us
jsr iec_set_idle
jsr iec_wait20us
jmp iec_return_success
#endif // CONFIG_IEC
+25
View File
@@ -0,0 +1,25 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
// Flush the IEC output buffer (if not empty) - send byte with EOI
//
// Preserves .X, .Y and .A registers
#if CONFIG_IEC
iec_tx_flush:
pha
lda C3PO
beq !+
sec // send it with EOI
jsr iec_tx_byte // send the command regardless of the status
!:
pla
rts
#endif // CONFIG_IEC
+24
View File
@@ -0,0 +1,24 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Common EAL update routine
//
#if (CONFIG_IEC_JIFFYDOS || CONFIG_IEC_DOLPHINDOS) && !CONFIG_MEMORY_MODEL_60K
iec_update_EAL_by_Y: // note: Carry has to be set by caller!
tya
adc EAL+0
sta EAL+0
bcc !+
inc EAL+1
!:
rts
#endif
+37
View File
@@ -0,0 +1,37 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# X16 * #IGNORE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Wait 1 ms (1000 usec)
//
// On NTSC this means 1023 cycles (slightly less on PAL, but we have to be sure).
// We cant count on badlines, as the screen might be disabled.
// Delay here is implemented using VIC-II raster register. Since one raster is
// 63 cycles, we need at least 17 full rasters to be 100% sure we wait enough
#if CONFIG_IEC
iec_wait1ms:
ldx #18 // we probably won't start with the beginning of raster
#endif // CONFIG_IEC
wait_x_bars: // additional entry point for delayy in screen and tape support
// has to preserve .Y and put .X to 0
lda VIC_RASTER
!:
cmp VIC_RASTER
beq !-
lda VIC_RASTER
dex
bne !-
iec_wait_rts: // dummy RTS, for very short waits
rts
+31
View File
@@ -0,0 +1,31 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
#if CONFIG_IEC
iec_wait20us:
// Wait 20usec
// PAL:
// - CPU frequency 0.985248 MHz, we need to waste at least 20 cycles
// NTSC:
// - CPU frequency 1.022727 MHz, we need to waste at least 21 cycles
// Waste cycles by reading some unimportant memory location
// in order not to clutter VICE debug logs
ora $03FF // 4 cycles
ora $03FF // 4 cycles
rts // 6 cycles
// 6 cycles JSR to routine,
// 14 cycles routine with RTS
// 1 cycle to fetch next instruction
// ---
// 21 cycles
#endif // CONFIG_IEC
+36
View File
@@ -0,0 +1,36 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Note: damages .X
//
#if CONFIG_IEC
iec_wait60us:
// Wait 60usec
// PAL:
// - CPU frequency 0.985248 MHz, we need to waste at least 60 cycles
// NTSC:
// - CPU frequency 1.022727 MHz, we need to waste at least 62 cycles
// Waste cycles in a loop
ldx #$0A // 2 cycles
!: dex // 2 cycles * 10
bpl !- // 3 cycles * 9 + 2 cycles
rts // 6 cycles
// 6 cycles JSR to routine,
// 57 cycles routine with RTS
// 1 cycle to fetch next instruction
// ---
// 64 cycles
#endif // CONFIG_IEC
+16
View File
@@ -0,0 +1,16 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
#if CONFIG_IEC
iec_wait_for_clk_release:
bit CIA2_PRA
bvc iec_wait_for_clk_release
rts
#endif // CONFIG_IEC
+18
View File
@@ -0,0 +1,18 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
#if CONFIG_IEC
iec_wait_for_data_pull:
lda CIA2_PRA
// Check the highest bit, which is DATA IN,
// (highest bit set = negative value)
bmi iec_wait_for_data_pull
rts
#endif // CONFIG_IEC
@@ -0,0 +1,17 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
#if CONFIG_IEC
iec_wait_for_data_release:
lda CIA2_PRA
// Check the highest bit, which is DATA IN,
// (highest bit set = negative value)
bpl iec_wait_for_data_release
rts
#endif // CONFIG_IEC
+38
View File
@@ -0,0 +1,38 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Official Kernal routine, described in:
//
// - [RG64] C64 Programmers Reference Guide - page 285
// - [CM64] Computes Mapping the Commodore 64 - page 223
// - https://www.pagetable.com/?p=1031, https://github.com/mist64/cbmbus_doc
// - http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
//
// CPU registers that has to be preserved (see [RG64]): .X, .Y
//
LISTEN:
#if CONFIG_IEC
// According to serial-bus.pdf (page 15) this routine flushes the IEC out buffer
jsr iec_tx_flush
// Check whether device number is correct
jsr iec_check_devnum_oc
bcc !+
jmp kernalerror_DEVICE_NOT_FOUND
!:
// Encode and execute the command
ora #$20
jmp common_talk_listen
#else
jmp kernalerror_ILLEGAL_DEVICE_NUMBER
#endif
+197
View File
@@ -0,0 +1,197 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// IEC part of the LOAD routine
//
#if CONFIG_IEC
load_iec_dev_not_found:
jmp lvs_device_not_found_error
load_iec_file_not_found:
jmp kernalerror_FILE_NOT_FOUND
load_iec_error:
lda FA
jsr iec_close_load
jmp lvs_load_verify_error
load_break_error:
pla
lda FA
jsr iec_close_load
jmp kernalerror_ROUTINE_TERMINATED
load_iec:
// Check file name
lda FNLEN
beq_16 kernalerror_FILE_NAME_MISSING
// Display SEARCHING FOR + filename
jsr lvs_display_searching_for
// http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
// p13, 16; also p16 tells us this routine does not mess with the file
// table in the C64, only in the drive.
// Call device to LISTEN (p16)
lda FA
jsr LISTEN
bcs load_iec_dev_not_found
// Open channel 0 (reserved for file reading)
lda #$00
jsr iec_cmd_open
bcs load_iec_dev_not_found
// Send file name
jsr iec_send_file_name
bcs load_iec_error
// Now command device to talk (p16)
lda FA
jsr TALK
bcs load_iec_error
#if CONFIG_IEC_BURST_CIA1 || CONFIG_IEC_BURST_CIA2 || CONFIG_IEC_BURST_MEGA_65
jsr burst_advertise
#endif
lda #$60 // open channel / data (p3) , required according to p13
sta TBTCNT
jsr iec_tx_command
bcs load_iec_error
#if CONFIG_IEC_DOLPHINDOS
jsr dolphindos_detect
#endif
// We are currently talker, so do the IEC turn around so that we
// are the listener (p16)
jsr iec_turnaround_to_listen
bcs load_iec_error
// Get load address
jsr load_iec_get_addr_byte
sta EAL+0
jsr load_iec_get_addr_byte
sta EAL+1
// If secondary address is 0, override EAL with STAL
lda SA
bne !+
lda STAL+0
sta EAL+0
lda STAL+1
sta EAL+1
!:
// Display start address
jsr lvs_display_loading_verifying
#if (CONFIG_IEC_JIFFYDOS || CONFIG_IEC_DOLPHINDOS) && !CONFIG_MEMORY_MODEL_60K
// If feasible, use protocol-specific optimized LOAD loop
lda VERCKK
bne load_iec_loop // branch if VERIFY
lda IECPROTO
#if CONFIG_IEC_JIFFYDOS
cmp #$01
beq_16 jiffydos_load // branch if JiffyDOS
#endif
#if CONFIG_IEC_DOLPHINDOS
cmp #$02
beq_16 dolphindos_load // branch if DolphinDOS
#endif
#endif
load_iec_loop:
// We are now ready to receive bytes
#if CONFIG_IEC_JIFFYDOS
jsr iec_rx_dispatch
#else
jsr iec_rx_byte
#endif
bcs load_iec_error
// Handle the byte (store in memory / verify)
jsr lvs_handle_byte_load_verify
bcs load_iec_error
// Advance pointer to data; it is OK if it advances past $FFFF,
// one autostart technique does exactly this
#if !HAS_OPCODES_65CE02
inc EAL+0
bne !+
inc EAL+1
!:
#else
inw EAL+0
#endif
// Handle STOP key; it is probably an overkill to do it
// with every byte, once per 32 bytes should be enough
lda EAL
and #$1F
bne !+
phx_trash_a
jsr udtim_keyboard
jsr STOP
bcs_16 load_break_error
plx_trash_a
!:
// Check for EOI - if so, this was the last byte
bit IOSTATUS
bvc load_iec_loop
// FALLTROUGH
load_iec_loop_end:
// Display end address
jsr lvs_display_done
// Close file on drive
lda FA
jsr iec_close_load
// Return last address
jmp lvs_return_last_address
load_iec_get_addr_byte:
#if CONFIG_IEC_JIFFYDOS
jsr iec_rx_dispatch
#else // no turbo supported
jsr iec_rx_byte
#endif
bcs !+
lda IOSTATUS
and #K_STS_EOI
bne !+
lda TBTCNT
rts
!:
pla
pla
jmp load_iec_file_not_found
#endif // CONFIG_IEC
+43
View File
@@ -0,0 +1,43 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// IEC part of the OPEN routine
//
#if CONFIG_IEC
open_iec:
// Check for command to send
ldy FNLEN
beq open_iec_done
// We have a command to send to IEC device
jsr LISTEN
bcc !+
jmp kernalerror_DEVICE_NOT_FOUND
!:
lda SA
jsr iec_cmd_open
bcc !+
jmp kernalerror_DEVICE_NOT_FOUND
!:
#if CONFIG_MEMORY_MODEL_60K
// We need our helpers to get to filenames under ROMs or IO area
jsr install_ram_routines
#endif
// Send command ('file name')
jsr iec_send_file_name
open_iec_done:
jmp open_done_success
#endif // CONFIG_IEC
+132
View File
@@ -0,0 +1,132 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// IEC part of the SAVE routine
//
#if CONFIG_IEC
save_iec_dev_not_found:
jmp lvs_device_not_found_error
save_iec:
// Check file name
lda FNLEN
beq_16 kernalerror_FILE_NAME_MISSING
// Display SAVING
jsr lvs_display_saving
// Call device to LISTEN
lda FA
jsr LISTEN
bcs save_iec_dev_not_found
// Open channel 1 (reserved for file writing)
lda #$01
jsr iec_cmd_open
bcs save_iec_dev_not_found
// Send file name
jsr iec_send_file_name
bcs save_iec_dev_not_found
// Call device to LISTEN once again
lda FA
jsr LISTEN
bcs save_iec_dev_not_found
#if CONFIG_IEC_BURST_CIA1 || CONFIG_IEC_BURST_CIA2 || CONFIG_IEC_BURST_MEGA_65
jsr burst_advertise
#endif
lda #$61 // open channel / data (p3) , required according to p13
sta TBTCNT
jsr iec_tx_command
bcs save_iec_dev_not_found
#if CONFIG_IEC_DOLPHINDOS
jsr dolphindos_detect
#endif
// Save start address
lda STAL+0
sta TBTCNT
clc
#if CONFIG_IEC_JIFFYDOS
jsr iec_tx_dispatch
#else
jsr iec_tx_byte
#endif
lda STAL+1
sta TBTCNT
clc
#if CONFIG_IEC_JIFFYDOS
jsr iec_tx_dispatch
#else
jsr iec_tx_byte
#endif
jsr lvs_STAL_to_MEMUSS
ldy #$00
iec_save_loop:
// Retrieve byte to send
#if CONFIG_MEMORY_MODEL_60K
ldx #<MEMUSS+0
jsr peek_under_roms
#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K
jsr peek_under_roms_via_MEMUSS
#else // CONFIG_MEMORY_MODEL_38K
lda (MEMUSS),y
#endif
// Send the byte
sta TBTCNT
clc
#if CONFIG_IEC_JIFFYDOS
jsr iec_tx_dispatch
#else
jsr iec_tx_byte
#endif
// Next iteration
#if !HAS_OPCODES_65CE02
jsr lvs_advance_MEMUSS
#else
inw MEMUSS+0
#endif
jsr lvs_check_EAL
bne iec_save_loop
iec_save_loop_end:
// Close file on drive
lda FA
jsr UNLSN
lda FA
jsr LISTEN
lda #$E1 // CLOSE command
sta TBTCNT
jsr iec_tx_command
jsr iec_tx_command_finalize
// Tell drive to unlisten
lda FA
jsr UNLSN
// Return success
clc
rts
#endif // CONFIG_IEC
+33
View File
@@ -0,0 +1,33 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Official Kernal routine, described in:
//
// - [RG64] C64 Programmers Reference Guide - page 296
// - [CM64] Computes Mapping the Commodore 64 - page 223/224
// - https://www.pagetable.com/?p=1031, , https://github.com/mist64/cbmbus_doc
//
// CPU registers that has to be preserved (see [RG64]): .X, .Y
//
SECOND:
#if CONFIG_IEC
// Due to OPEN/CLOSE/TKSA/SECOND command encoding, allowed channels are 0-15; it is the caller
// responsibility, hovewer, to provide value ORed with $60
// - https://www.lemon64.com/forum/viewtopic.php?t=57694&sid=531ba3592bcffadef2ac8b9162f2e529
// - https://www.pagetable.com/?p=1031 (Kernal API description)
// XXX consider checking whether value is in range (contrary to original ROM implementation)
jmp common_open_close_unlsn_second
#else
jmp kernalerror_ILLEGAL_DEVICE_NUMBER
#endif
+51
View File
@@ -0,0 +1,51 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Official Kernal routine, described in:
//
// - [RG64] C64 Programmers Reference Guide - page 301/302
// - [CM64] Computes Mapping the Commodore 64 - page 223
// - https://www.pagetable.com/?p=1031, https://github.com/mist64/cbmbus_doc
// - http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
//
// CPU registers that has to be preserved (see [RG64]): .X, .Y
//
TALK:
#if CONFIG_IEC
// According to serial-bus.pdf (page 15) this routine flushes the IEC out buffer
jsr iec_tx_flush
// Check whether device number is correct
jsr iec_check_devnum_oc
bcc !+
jmp kernalerror_DEVICE_NOT_FOUND
!:
// Encode and execute the command
ora #$40
// FALLTROUGH
common_talk_listen: // common part of TALK and LISTEN
sta TBTCNT
#if CONFIG_IEC_JIFFYDOS || CONFIG_IEC_DOLPHINDOS
lda #$FF // force JiffyDOS detection, clear DolphinDOS mark
sta IECPROTO
#endif
jmp iec_tx_command
#else
jmp kernalerror_ILLEGAL_DEVICE_NUMBER
#endif
+33
View File
@@ -0,0 +1,33 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Official Kernal routine, described in:
//
// - [RG64] C64 Programmers Reference Guide - page 302
// - [CM64] Computes Mapping the Commodore 64 - page 224
// - https://www.pagetable.com/?p=1031, https://github.com/mist64/cbmbus_doc
//
// CPU registers that has to be preserved (see [RG64]): .X, .Y
//
TKSA:
#if CONFIG_IEC
// Due to OPEN/CLOSE/TKSA/SECOND command encoding, allowed channels are 0-15; it is the caller
// responsibility, hovewer, to provide value ORed with $60
// - 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
jmp kernalerror_ILLEGAL_DEVICE_NUMBER
#endif
+40
View File
@@ -0,0 +1,40 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Official Kernal routine, described in:
//
// - [RG64] C64 Programmers Reference Guide - page 303
// - [CM64] Computes Mapping the Commodore 64 - page 224
// - https://www.pagetable.com/?p=1031, , https://github.com/mist64/cbmbus_doc
// - http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
//
// CPU registers that has to be preserved (see [RG64]): .X, .Y
//
UNLSN:
#if CONFIG_IEC
// According to serial-bus.pdf (page 15) this routine flushes the IEC out buffer
jsr iec_tx_flush
#if CONFIG_IEC_JIFFYDOS || CONFIG_IEC_DOLPHINDOS
lda #$FF // do not use JiffyDOS / DolphinDOS anymore, trigger JiffyDOS detection
sta IECPROTO
#endif
// Buffer empty, send the command
lda #$3F
jmp common_open_close_unlsn_second
#else
jmp kernalerror_ILLEGAL_DEVICE_NUMBER
#endif
+51
View File
@@ -0,0 +1,51 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Official Kernal routine, described in:
//
// - [RG64] C64 Programmers Reference Guide - page 304
// - [CM64] Computes Mapping the Commodore 64 - page 224
// - https://www.pagetable.com/?p=1031, , https://github.com/mist64/cbmbus_doc
// - http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
//
// CPU registers that has to be preserved (see [RG64]): .X, .Y
//
UNTLK:
#if CONFIG_IEC
// According to serial-bus.pdf (page 15) this routine flushes the IEC out buffer
jsr iec_tx_flush
#if CONFIG_IEC_JIFFYDOS || CONFIG_IEC_DOLPHINDOS
lda #$FF // do not use JiffyDOS / DolphinDOS anymore, trigger JiffyDOS detection
sta IECPROTO
#endif
// Buffer empty, send the command
lda #$5F
common_untlk_tksa: // common part of UNTLK and TKSA
sta TBTCNT
jsr iec_tx_command
bcs !+ // branch if error
// 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
// Luigi Di Fraia (https://luigidifraia.wordpress.com/2017/06/27/codebase64-on-the-kernal-behaviour/)
// claims TKSA Kernal routine actually does the turnaround
jmp iec_turnaround_to_listen
!:
rts
#else
jmp kernalerror_ILLEGAL_DEVICE_NUMBER
#endif