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

@@ -0,0 +1,55 @@
// Registers according to Ultimate 64 Command Interface description,
// https://1541u-documentation.readthedocs.io/en/latest/command%20interface.html
// and ultimate_dos_v1.0.pdf and command_interface_v1.0.pdf by Gideon Zweijtzer
// Command interface registers
.label U64_CONTROL_STATUS = $DF1C // write = CONTROL, read = STATUS
.label U64_COMMAND_DATA_IDENTIFY = $DF1D // write = COMMAND_DATA, read = IDENTIFICATION
.label U64_RESPONSE_DATA = $DF1E // read only
.label U64_STATUS_DATA = $DF1F // read only
// Constant for U64_IDENTIFICATION register
.const U64_MAGIC_ID = $C9
// Constants for U64_CONTROL register
.const U64_CTRL_BIT_PUSH_CMD = $01
.const U64_CTRL_BIT_DATA_ACC = $02
.const U64_CTRL_BIT_ABORT = $04
.const U64_CTRL_BIT_CLR_ERR = $08
// Constants for U64_STATUS register
.const U64_STAT_BIT_CMD_BUSY = $01
.const U64_STAT_BIT_DATA_ACC = $02
.const U64_STAT_BIT_ABORT_P = $04
.const U64_STAT_BIT_ERROR = $08
.const U64_STAT_MASK_STATE = $30 // two bits!
.const U64_STAT_BIT_STAT_AV = $40
.const U64_STAT_BIT_DATA_AV = $80
// Interface targets
.const U64_TARGET_DOS1 = $01
.const U64_TARGET_DOS2 = $02
// DOS command codes
.const U64_DOS_CMD_IDENTIFY = $01
.const U64_DOS_CMD_OPEN_FILE = $02
.const U64_DOS_CMD_CLOSE_FILE = $03
.const U64_DOS_CMD_READ_DATA = $04
.const U64_DOS_CMD_WRITE_DATA = $05
.const U64_DOS_CMD_FILE_SEEK = $06
.const U64_DOS_CMD_FILE_INFO = $07
.const U64_DOS_CMD_CHANGE_DIR = $11
.const U64_DOS_CMD_GET_PATH = $12
.const U64_DOS_CMD_OPEN_DIR = $13
.const U64_DOS_CMD_READ_DIR = $14
.const U64_DOS_CMD_COPY_UI_PATH = $15
.const U64_DOS_CMD_LOAD_REU = $21
.const U64_DOS_CMD_SAVE_REU = $22
.const U64_DOS_CMD_ECHO = $F0
// DOS file opening constants
.const U64_FA_READ = $01
.const U64_FA_WRITE = $02
.const U64_FA_CREATE_NEW = $03
.const U64_FA_CREATE_ALWAYS = $04
+134
View File
@@ -0,0 +1,134 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// LOAD routine hook for fast loading via UltiDOS
//
u64_load:
// First check whether the command interface is enabled
lda U64_IDENTIFICATION
cmp #U64_MAGIC_ID
beq !+
u64_load_skip:
rts
!:
// XXX find out which device number softIEC is mapped to
lda current_device_number
cmp #$20 // for now use device number 32
bne u64_load_skip
// Takeover the flow completely
pla
pla
// Display SEARCHING FOR + filename
jsr lvs_display_searching_for
// Whatever the interface was doing - ask to abort it
jsr u64_load_abort
// Send a command to open the file
lda #U64_DOS_CMD_OPEN_FILE
jsr u64_load_send_cmd
lda #U64_FA_READ
jsr u64_load_send_cmd
jsr u64_load_send_filename
jsr u64_load_finalize_cmd
// Check status
jsr u64_load_check_status
bcs lvs_file_not_found_error
// Load first two bytes to determine start address
// XXX
jsr printf
.text "DBG: NOT IMPLEMENTED"
.byte $0D,0
jmp lvs_wrap_around_error
rts
u64_load_abort:
lda #U64_CTRL_BIT_ABORT
sta U64_CONTROL
!:
lda U64_STATUS
bne !-
rts
u64_load_send_cmd:
ldx #U64_TARGET_DOS2
stx U64_COMMAND_DATA // target
sta U64_COMMAND_DATA // command code
rts
u64_load_send_filename:
ldy #0
u64_load_send_filename_loop:
cpy FNLEN
bne !+
rts
!:
ldx #<current_filename_ptr
jsr peek_under_roms
iny
sta U64_COMMAND_DATA
jmp u64_load_send_filename_loop
u64_load_finalize_cmd:
// Push the command for execution
lda #U64_CTRL_BIT_PUSH_CMD
sta U64_CONTROL
// Wait till it is complete
!:
lda U64_STATUS
and #U64_STAT_BIT_CMD_BUSY
bne !-
rts
u64_load_check_status:
// Wait till status is available
lda U64_STATUS
and #U64_STAT_BIT_STAT_AV
beq u64_load_check_status
// Status is ready - check the first character
lda U64_STATUS_DATA
jsr JCHROUT // XXX for test only
cmp #$30 // '0'
bne u64_load_check_status_wrong
// Check the second status character
lda U64_STATUS
and #U64_STAT_BIT_STAT_AV
beq u64_load_check_status_ok
lda U64_STATUS_DATA
jsr JCHROUT // XXX for test only
cmp #$30 // '0'
beq u64_load_check_status_ok
// FALLTROUGH
u64_load_check_status_wrong:
sec
bcs !+
u64_load_check_status_ok:
clc
!:
// Now empty the status queue
lda U64_STATUS
and #U64_STAT_BIT_STAT_AV
beq !+
lda U64_STATUS_DATA
jsr JCHROUT // XXX for test only
jmp !-
!:
rts
+8
View File
@@ -0,0 +1,8 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
// XXX provide documentation and implementation
STUB_IMPLEMENTATION()
+5
View File
@@ -0,0 +1,5 @@
This is a well-known address, needed even for some BASIC programming - it's a common target for a SYS command. See for example here:
- http://ready64.org/articoli/_files/043_pokesc64.txt
sys 59062 - Advance Cursor
+5
View File
@@ -0,0 +1,5 @@
This is a well-known address, needed even for some BASIC programming - it's a common target for a SYS command. See for example here:
- http://ready64.org/articoli/_files/043_pokesc64.txt
sys 59137 - Previous Line
+8
View File
@@ -0,0 +1,8 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
// XXX provide documentation and implementation
STUB_IMPLEMENTATION()
+8
View File
@@ -0,0 +1,8 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
// Screen CHROUT
STUB_IMPLEMENTATION()
+3
View File
@@ -0,0 +1,3 @@
This routine is called at least by the Final Cartridge III. See:
- https://github.com/mist64/final_cartridge/blob/master/core/kernal_c64.i
@@ -0,0 +1,8 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
// Insert line at top of screen
STUB_IMPLEMENTATION()
+3
View File
@@ -0,0 +1,3 @@
This routine is called at least by the Final Cartridge III. See:
- https://github.com/mist64/final_cartridge/blob/master/core/kernal_c64.i
+1
View File
@@ -0,0 +1 @@
Routine is called by Lemmings game, purpose unknown so far
+8
View File
@@ -0,0 +1,8 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
// XXX provide documentation and implementation
STUB_IMPLEMENTATION()
+8
View File
@@ -0,0 +1,8 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
// IEC close
STUB_IMPLEMENTATION()
+3
View File
@@ -0,0 +1,3 @@
This routine is called at least by the Final Cartridge III. See:
- https://github.com/mist64/final_cartridge/blob/master/core/kernal_c64.i
+4
View File
@@ -0,0 +1,4 @@
This routine is probably used by many cartridges and other software to initialize parts of the system. At least the UCart uses it - see here:
- https://www.elektroda.pl/rtvforum/topic3293027.html
+8
View File
@@ -0,0 +1,8 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
// XXX provide documentation and implementation
STUB_IMPLEMENTATION()
+9
View File
@@ -0,0 +1,9 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# X16 * #IGNORE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
cartridge_signature:
.byte $C3,$C2,$CD,$38,$30
+10
View File
@@ -0,0 +1,10 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
// CHR$ codes for the 16 colours
colour_codes:
.byte 144,5,28,159,156,30,31,158
.byte 129,149,150,151,152,153,154,155
+6
View File
@@ -0,0 +1,6 @@
A color code table, see here:
- https://csdb.dk/forums/index.php?roomid=7&topicid=487
CCGMS termina program expects it to be under original location, see here:
- https://raw.githubusercontent.com/spathiwa/ccgmsterm/master/original/5a.gs
+3
View File
@@ -0,0 +1,3 @@
Location of the default Kernal vector values, described in Compute's Mapping the Commodore 64, page 237
It is referenced by GEOS - see https://github.com/mist64/geos/blob/master/inc/c64.inc
+29
View File
@@ -0,0 +1,29 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Default values for Kernal vectors - described in:
//
// - [RG64] C64 Programmers Reference Guide - page 293 (RESTOR), 304 (VECTOR)
// - [CM64] Computes Mapping the Commodore 64 - page 237
//
vector_defaults:
.word default_irq_handler // CINV
.word default_brk_handler // CBINV
.word default_nmi_handler // NMINV
.word OPEN // IOPEN
.word CLOSE // ICLOSE
.word CHKIN // ICHKIN
.word CKOUT // ICKOUT
.word CLRCHN // ICLRCH
.word CHRIN // IBASIN
.word CHROUT // IBSOUT
.word STOP // ISTOP
.word GETIN // IGETIN
.word CLALL // ICLALL
.word default_brk_handler // USRCMD
.word LOAD // ILOAD
.word SAVE // ISAVE
+8
View File
@@ -0,0 +1,8 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
filename_any:
.text "*"
+26
View File
@@ -0,0 +1,26 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Values for IRQ generation timer - original idea was:
//
// (This value was calculated by running a custom IRQ handler on a C64
// with original KERNAL, and writing the values of $DC04/5 to the screen
// in the IRQ handler to see roughly what value the timers must be set to)
// ldy #<16380
// ldx #>16380
// Current values selected on the following assumptions:
//
// PAL C64 (https://codebase64.org/doku.php?id=base:cpu_clocking),
// is clocked at 0.985248 MHz, so that 1/60s is 16421 ($4025) CPU cycles
//
// NTSC C64 (https://codebase64.org/doku.php?id=base:cpu_clocking),
// is clocked at 1.022727 MHz, so that 1/60s is 17045 ($4295) CPU cycles
irq_timing_hi: // high bytes
.byte >17045 // NTSC
.byte >16421 // PAL
+26
View File
@@ -0,0 +1,26 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Values for IRQ generation timer - original idea was:
//
// (This value was calculated by running a custom IRQ handler on a C64
// with original KERNAL, and writing the values of $DC04/5 to the screen
// in the IRQ handler to see roughly what value the timers must be set to)
// ldy #<16380
// ldx #>16380
// Current values selected on the following assumptions:
//
// PAL C64 (https://codebase64.org/doku.php?id=base:cpu_clocking),
// is clocked at 0.985248 MHz, so that 1/60s is 16421 ($4025) CPU cycles
//
// NTSC C64 (https://codebase64.org/doku.php?id=base:cpu_clocking),
// is clocked at 1.022727 MHz, so that 1/60s is 17045 ($4295) CPU cycles
irq_timing_lo: // low bytes
.byte <17045 // NTSC
.byte <16421 // PAL
+98
View File
@@ -0,0 +1,98 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Messages to be prined out by Kernal
//
.encoding "petscii_upper"
// Double underscore prevents labels from being passed to VICE (would confuse monitor)
.label __MSG_KERNAL_SEARCHING_FOR = __msg_kernalsearching_for - __msg_kernal_first
.label __MSG_KERNAL_LOADING = __msg_kernalloading - __msg_kernal_first
.label __MSG_KERNAL_VERIFYING = __msg_kernalverifying - __msg_kernal_first
.label __MSG_KERNAL_SAVING = __msg_kernalsaving - __msg_kernal_first
.label __MSG_KERNAL_FROM_HEX = __msg_kernalfrom_hex - __msg_kernal_first
.label __MSG_KERNAL_TO_HEX = __msg_kernalto_hex - __msg_kernal_first
#if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO
.label __MSG_KERNAL_PRESS_PLAY = __msg_kernalplay - __msg_kernal_first
.label __MSG_KERNAL_FOUND = __msg_kernalfound - __msg_kernal_first
#if CONFIG_MB_MEGA_65
.label __MSG_KERNAL_OK_SEARCHING = __msg_kernaloksearching - __msg_kernal_first
#endif
#endif
#if CONFIG_PANIC_SCREEN
.label __MSG_KERNAL_PANIC = __msg_kernalpanic - __msg_kernal_first
.label __MSG_KERNAL_PANIC_ROM_MISMATCH = __msg_kernalpanic_rom_mismatch - __msg_kernal_first
#endif
__msg_kernal_first:
__msg_kernalsearching_for:
.byte $0D
.text "SEARCHING FOR"
.byte $80 + $20 // end of string mark + space
__msg_kernalloading:
.byte $0D
.text "LOADIN"
.byte $80 + $47 // end of string mark + 'G'
__msg_kernalverifying:
.byte $0D
.text "VERIFYIN"
.byte $80 + $47 // end of string mark + 'G'
__msg_kernalsaving:
.byte $0D
.text "SAVING"
.byte $80 + $20 // end of string mark + space
__msg_kernalfrom_hex:
.text " FROM "
.byte $80 + $24 // end of string mark + '$'
__msg_kernalto_hex:
.text " TO "
.byte $80 + $24 // end of string mark + '$'
#if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO
__msg_kernalplay:
.byte $0D
.text "PRESS PLAY ON TAPE"
.byte $80 + $0D // end of string mark + return
__msg_kernalfound:
.text "FOUND"
.byte $80 + $20 // end of string mark + space
#if CONFIG_MB_MEGA_65
__msg_kernaloksearching:
.text "OK"
.byte $0D, $0D
.text "SEARCHIN"
.byte $80 + $47 // end of string mark + 'G'
#endif
#endif
#if CONFIG_PANIC_SCREEN
__msg_kernalpanic:
.text "KERNAL PANI"
.byte $80 + $43 // end of string mark + 'C'
__msg_kernalpanic_rom_mismatch:
.text " - ROM MISMATC"
.byte $80 + $48 // end of string mark + 'H'
#endif // CONFIG_PANIC_SCREEN
+128
View File
@@ -0,0 +1,128 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Command string definitions for programmable keys
//
#if CONFIG_PROGRAMMABLE_KEYS
.macro PROGRAMMABLE_KEY_CODE(STR, CODE)
{
.if (STR.size() > 0)
{
.byte CODE
}
}
.macro PROGRAMMABLE_KEY_STRING(STR)
{
.if (STR.size() > 0)
{
.text STR
.byte $00
}
}
.macro PROGRAMMABLE_KEY_OFFSET(STR, LABEL)
{
.if (STR.size() > 0)
{
.byte LABEL - programmable_keys_strings
}
}
programmable_keys_codes:
PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_RUN, KEY_RUN)
PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F1, KEY_F1)
PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F2, KEY_F2)
PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F3, KEY_F3)
PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F4, KEY_F4)
PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F5, KEY_F5)
PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F6, KEY_F6)
PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F7, KEY_F7)
PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F8, KEY_F8)
#if !CONFIG_LEGACY_SCNKEY && (CONFIG_KEYBOARD_C128 || CONFIG_KEYBOARD_C65)
PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_HELP, KEY_HELP)
#endif
#if !CONFIG_LEGACY_SCNKEY && CONFIG_KEYBOARD_C65
PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F9, KEY_F9)
PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F10, KEY_F10)
PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F11, KEY_F11)
PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F12, KEY_F12)
PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F13, KEY_F13)
PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F14, KEY_F14)
#endif
__programmable_keys_codes_end:
programmable_keys_strings:
__str_offset_RUN: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_RUN)
__str_offset_F1: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F1)
__str_offset_F2: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F2)
__str_offset_F3: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F3)
__str_offset_F4: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F4)
__str_offset_F5: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F5)
__str_offset_F6: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F6)
__str_offset_F7: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F7)
__str_offset_F8: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F8)
#if !CONFIG_LEGACY_SCNKEY && (CONFIG_KEYBOARD_C128 || CONFIG_KEYBOARD_C65)
__str_offset_HELP: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_HELP)
#endif
#if !CONFIG_LEGACY_SCNKEY && CONFIG_KEYBOARD_C65
__str_offset_F9: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F9)
__str_offset_F10: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F10)
__str_offset_F11: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F11)
__str_offset_F12: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F12)
__str_offset_F13: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F13)
__str_offset_F14: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F14)
#endif
__programmable_keys_strings_end:
{
.var offset = __programmable_keys_strings_end - programmable_keys_strings
.if (offset >= 255) .error "Programmable keys took too much space"
}
programmable_keys_offsets:
PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_RUN, __str_offset_RUN)
PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F1, __str_offset_F1)
PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F2, __str_offset_F2)
PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F3, __str_offset_F3)
PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F4, __str_offset_F4)
PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F5, __str_offset_F5)
PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F6, __str_offset_F6)
PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F7, __str_offset_F7)
PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F8, __str_offset_F8)
#if !CONFIG_LEGACY_SCNKEY && (CONFIG_KEYBOARD_C128 || CONFIG_KEYBOARD_C65)
PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_HELP, __str_offset_HELP)
#endif
#if !CONFIG_LEGACY_SCNKEY && CONFIG_KEYBOARD_C65
PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F9, __str_offset_F9)
PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F10, __str_offset_F10)
PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F11, __str_offset_F11)
PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F12, __str_offset_F12)
PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F13, __str_offset_F13)
PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F14, __str_offset_F14)
#endif
#endif // CONFIG_PROGRAMMABLE_KEYS
+1
View File
@@ -0,0 +1 @@
This particular address is not for interoperability - we had to choose some fixed location foor the extended ROM jumptable, beginning of the mapped memory block is just sane.
@@ -0,0 +1,54 @@
// #LAYOUT# M65 KERNAL_0 #TAKE-FLOAT
// #LAYOUT# M65 KERNAL_1 #TAKE
// #LAYOUT# * * #IGNORE
//
// Definitions for communication with Mega65 segment KERNAL_1 from KERNAL_0
//
#if SEGMENT_KERNAL_0
// Label definitions
.label VK1__IOINIT = $4000 + 2 * 0
.label VK1__RAMTAS = $4000 + 2 * 1
.label VK1__setup_vicii = $4000 + 2 * 2
.label VK1__load_tape_normal = $4000 + 2 * 3
.label VK1__load_tape_turbo = $4000 + 2 * 4
.label VK1__load_tape_auto = $4000 + 2 * 5
.label VK1__tape_head_align = $4000 + 2 * 6
#else
// Vector table (OpenROMs private!)
.word IOINIT
.word RAMTAS
.word setup_vicii
#if CONFIG_TAPE_NORMAL && !CONFIG_TAPE_AUTODETECT
.word load_tape_normal
#else
.word $0000
#endif
#if CONFIG_TAPE_TURBO && !CONFIG_TAPE_AUTODETECT
.word load_tape_turbo
#else
.word $0000
#endif
#if CONFIG_TAPE_AUTODETECT
.word load_tape_auto
#else
.word $0000
#endif
#if CONFIG_TAPE_HEAD_ALIGN
.word tape_head_align
#else
.word $0000
#endif
#endif
+68
View File
@@ -0,0 +1,68 @@
// #LAYOUT# M65 KERNAL_1 #TAKE
// #LAYOUT# * * #IGNORE
//
// Definitions for calling Mega65 segment KERNAL_0 routines from KERNAL_1
//
#import "KERNAL_0_combined.sym"
.label STOP = KERNAL_0.STOP
.label hw_entry_reset = KERNAL_0.hw_entry_reset
.label return_from_interrupt = KERNAL_0.return_from_interrupt
.label clrchn_reset = KERNAL_0.clrchn_reset
.label udtim_keyboard = KERNAL_0.udtim_keyboard
.label setup_irq_timer = KERNAL_0.setup_irq_timer
.label wait_x_bars = KERNAL_0.wait_x_bars
#if CONFIG_IEC
.label iec_set_idle = KERNAL_0.iec_set_idle
#endif
#if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO
.label mega65_unhide = KERNAL_0.mega65_unhide
.label tape_motor_on = KERNAL_0.tape_motor_on
.label tape_motor_off = KERNAL_0.tape_motor_off
.label lvs_display_loading_verifying = KERNAL_0.proxy_K1_lvs_display_loading_verifying
.label lvs_display_done = KERNAL_0.proxy_K1_lvs_display_done
.label lvs_return_last_address = KERNAL_0.proxy_K1_lvs_return_last_address
.label lvs_device_not_found_error = KERNAL_0.proxy_K1_lvs_device_not_found_error
.label lvs_load_verify_error = KERNAL_0.proxy_K1_lvs_load_verify_error
.label lvs_check_EAL = KERNAL_0.lvs_check_EAL
.label lvs_STAL_to_MEMUSS = KERNAL_0.lvs_STAL_to_MEMUSS
.label kernalerror_ROUTINE_TERMINATED = KERNAL_0.proxy_K1_kernalerror_ROUTINE_TERMINATED
.label print_kernal_message = KERNAL_0.proxy_K1_print_kernal_message
.label print_return = KERNAL_0.proxy_K1_print_return
.label __MSG_KERNAL_PRESS_PLAY = KERNAL_0.__MSG_KERNAL_PRESS_PLAY
.label __MSG_KERNAL_OK_SEARCHING = KERNAL_0.__MSG_KERNAL_OK_SEARCHING
.label __MSG_KERNAL_FOUND = KERNAL_0.__MSG_KERNAL_FOUND
#endif
#if CONFIG_TAPE_NORMAL
.label tape_normal_byte_store = KERNAL_0.tape_normal_byte_store
#endif
#if CONFIG_TAPE_HEAD_ALIGN
.label CLALL = KERNAL_0.proxy_K1_CLALL
.label nmi_lock = KERNAL_0.nmi_lock
#endif
+56
View File
@@ -0,0 +1,56 @@
// #LAYOUT# M65 KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// ROM mapping routines for Mega65
//
// Available memory maps:
// - NORMAL - nothing mapped in
// - KERNAL_1 - for calling KERNAL_1 segment code
map_NORMAL:
php
pha
phx
phy
phz
lda #$00
tax
tay
taz
// FALLTROUGH
map_end:
map
eom
plz
ply
plx
pla
plp
rts
map_KERNAL_1:
php
pha
phx
phy
phz
lda #$00
tay
taz
ldx #$42 // 0x4000 <- map 8KB from 0x20000
bne map_end
+69
View File
@@ -0,0 +1,69 @@
// #LAYOUT# M65 KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Proxies for calling Mega65 segment KERNAL_0 routines from KERNAL_1
//
#if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO
proxy_K1_kernalerror_ROUTINE_TERMINATED:
jsr map_NORMAL
jmp kernalerror_ROUTINE_TERMINATED
proxy_K1_lvs_display_loading_verifying:
jsr map_NORMAL
jsr lvs_display_loading_verifying
jmp map_KERNAL_1
proxy_K1_lvs_display_done:
jsr map_NORMAL
jsr lvs_display_done
jmp map_KERNAL_1
proxy_K1_lvs_return_last_address:
jsr map_NORMAL
jmp lvs_return_last_address
proxy_K1_lvs_device_not_found_error:
jsr map_NORMAL
jmp lvs_device_not_found_error
proxy_K1_lvs_load_verify_error:
jsr map_NORMAL
jmp lvs_load_verify_error
proxy_K1_print_kernal_message:
jsr map_NORMAL
jsr print_kernal_message
jmp map_KERNAL_1
proxy_K1_print_return:
jsr map_NORMAL
jsr print_return
jmp map_KERNAL_1
#endif
#if CONFIG_TAPE_HEAD_ALIGN
proxy_K1_CLALL:
jsr map_NORMAL
jsr CLALL
jmp map_KERNAL_1
#endif
@@ -0,0 +1,50 @@
// #LAYOUT# M65 KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// ROM routine call redirect for tape routines
//
#if CONFIG_TAPE_NORMAL && !CONFIG_TAPE_AUTODETECT
load_tape_normal:
jsr map_KERNAL_1
jsr_ind VK1__load_tape_normal
jmp map_NORMAL
#endif
#if CONFIG_TAPE_TURBO && !CONFIG_TAPE_AUTODETECT
load_tape_turbo:
jsr map_KERNAL_1
jsr_ind VK1__load_tape_turbo
jmp map_NORMAL
#endif
#if CONFIG_TAPE_AUTODETECT
load_tape_auto:
jsr map_KERNAL_1
jsr_ind VK1__load_tape_auto
jmp map_NORMAL
#endif
#if CONFIG_TAPE_HEAD_ALIGN
tape_head_align:
jsr map_KERNAL_1
jsr_ind VK1__tape_head_align
jmp map_NORMAL
#endif
@@ -0,0 +1,19 @@
// #LAYOUT# M65 KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Tape (normal) helper routine - byte storage when banking change is needed
//
#if CONFIG_TAPE_NORMAL
tape_normal_byte_store:
jsr map_NORMAL
sta (MEMUSS), y
jmp map_KERNAL_1
#endif
+24
View File
@@ -0,0 +1,24 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# X16 * #IGNORE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Routine to unhide Mega65 extra registers
//
#if CONFIG_KEYBOARD_C65 || (CONFIG_MB_MEGA_65 && (CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO))
mega65_unhide:
lda #$A5
sta VIC_KEY
lda #$96
sta VIC_KEY
rts
#endif
+7
View File
@@ -0,0 +1,7 @@
// #LAYOUT# X16 KERNAL_1 #TAKE
// #LAYOUT# * * #IGNORE
// Dummy, just to have anything in segment 1
brk
+44
View File
@@ -0,0 +1,44 @@
// #LAYOUT# X16 KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
// Stubs for Commander X16 support
scnkey_set_keytab:
STUB_IMPLEMENTATION()
clear_screen:
STUB_IMPLEMENTATION()
setup_vicii:
STUB_IMPLEMENTATION()
cursor_blink:
STUB_IMPLEMENTATION()
chrin_keyboard:
STUB_IMPLEMENTATION()
chrout_screen:
STUB_IMPLEMENTATION()
IOINIT:
STUB_IMPLEMENTATION()
SCNKEY:
STUB_IMPLEMENTATION()
SCREEN:
STUB_IMPLEMENTATION()
screen_calculate_pointers:
STUB_IMPLEMENTATION()
setup_pal_ntsc:
STUB_IMPLEMENTATION()
wait_x_bars:
STUB_IMPLEMENTATION()
udtim_keyboard:
STUB_IMPLEMENTATION()
+94
View File
@@ -0,0 +1,94 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
// Kernal error codes are described in 'Commodore 64 Programmers Reference Guide', page 306
kernalerror_ROUTINE_TERMINATED: // by a STOP key
lda #K_ERR_ROUTINE_TERMINATED
skip_2_bytes_trash_nvz
// FALLTROUGH
kernalerror_TOO_MANY_OPEN_FILES:
lda #K_ERR_TOO_MANY_OPEN_FILES
skip_2_bytes_trash_nvz
// FALLTROUGH
kernalerror_FILE_ALREADY_OPEN:
lda #K_ERR_FILE_ALREADY_OPEN
skip_2_bytes_trash_nvz
// FALLTROUGH
kernalerror_FILE_NOT_OPEN:
lda #K_ERR_FILE_NOT_OPEN
skip_2_bytes_trash_nvz
// FALLTROUGH
kernalerror_FILE_NOT_FOUND:
lda #K_ERR_FILE_NOT_FOUND
skip_2_bytes_trash_nvz
// FALLTROUGH
kernalerror_DEVICE_NOT_FOUND:
lda #K_ERR_DEVICE_NOT_FOUND
skip_2_bytes_trash_nvz
// FALLTROUGH
kernalerror_FILE_NOT_INPUT:
lda #K_ERR_FILE_NOT_INPUT
skip_2_bytes_trash_nvz
// FALLTROUGH
kernalerror_FILE_NOT_OUTPUT:
lda #K_ERR_FILE_NOT_OUTPUT
skip_2_bytes_trash_nvz
// FALLTROUGH
kernalerror_FILE_NAME_MISSING:
lda #K_ERR_FILE_NAME_MISSING
skip_2_bytes_trash_nvz
// FALLTROUGH
kernalerror_ILLEGAL_DEVICE_NUMBER:
lda #K_ERR_ILLEGAL_DEVICE_NUMBER
skip_2_bytes_trash_nvz
// FALLTROUGH
#if CONFIG_IEC_JIFFYDOS
kernalerror_IEC_TIMEOUT_READ:
lda #K_STS_TIMEOUT_READ
skip_2_bytes_trash_nvz
// FALLTROUGH
#endif // CONFIG_IEC_JIFFYDOS
kernalerror_TOP_MEM_RS232:
lda #K_ERR_TOP_MEM_RS232
sec
rts
+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
@@ -0,0 +1,36 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Advertise burst IEC protocol support to the receiver
//
//
// Based on idea by Pasi 'Albert' Ojala and description from
// https://sites.google.com/site/h2obsession/CBM/C128/fast-serial-for-uiec
//
#if CONFIG_IEC_BURST_CIA1
burst_advertise:
#if CONFIG_IEC_JIFFYDOS
// Skip if other protocol (only JiffyDOS is possible at this moment) already detected
lda IECPROTO
bmi !+
bne burst_advertise_done
!:
#endif
panic #$FF // XXX implement this
burst_advertise_done:
rts
#endif
@@ -0,0 +1,60 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Advertise burst IEC protocol support to the receiver
//
//
// Based on idea by Pasi 'Albert' Ojala and description from
// https://sites.google.com/site/h2obsession/CBM/C128/fast-serial-for-uiec
//
#if CONFIG_IEC_BURST_CIA2
burst_advertise:
#if CONFIG_IEC_JIFFYDOS
// Skip if other protocol (only JiffyDOS is possible at this moment) already detected
lda IECPROTO
bmi !+
bne burst_advertise_done
!:
#endif
// Make sure this is not done under ATN
jst iec_release_atn
// Set the clock rate to the fastest possible
ldy #$01
sty CIA2_TIMALO
dey
sty CIA2_TIMAHI
// Prepare registers for transfer
lda #$C1
sta CIA2_CRA // start timer A, serial out, TOD 50Hz
bit CIA2_ICR // clear interrupt register
// Send test byte
lda #$FF // $FF keeps DATA released, see https://www.c64-wiki.com/wiki/Fast_serial_bus_protocol
sta CIA2_SDR
// Wait until byte sent
lda #$08 // interrupt mask
!:
bit CIA2_ICR
beq !-
// FALLTROUGH
burst_advertise_done:
rts
#endif
+31
View File
@@ -0,0 +1,31 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Advertise burst IEC protocol support to the receiver
//
#if CONFIG_IEC_BURST_MEGA_65
burst_advertise:
#if CONFIG_IEC_JIFFYDOS
// Skip if other protocol (only JiffyDOS is possible at this moment) already detected
lda IECPROTO
bmi !+
bne burst_advertise_done:
!:
#endif
panic #$FF // XXX implement this
burst_advertise_done:
rts
#endif
+65
View File
@@ -0,0 +1,65 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Helper routine for JiffyDOS detection
//
// The standard parallel cable (used by SpeedDOS, DolphinDOS 2, etc.) connects the following UserPort lines:
// - PB0-PB7 - CIA2_PRB ($DD01), CIA #2 port B
// - PC2, FLAG2 - CIA2_ICR ($DD0D), CIA #2 handshaking line
//
// See:
// - http://sta.c64.org/cbmpar41c.html
// - http://sta.c64.org/cbmpar71c.html
// - Commodore 64 Programers Referencee Guide, pages 360-361, 429
// - Computes Mapping the C64, page 183
#if CONFIG_IEC_DOLPHINDOS
dolphindos_detect:
// Make sure the port settings are correct
lda #$7F
sta CIA2_ICR // disable interrupt generation
lda #$00
sta CIA2_DDRB // set all port B lines as input
// According to logs collected from modified VICE emulator, original DolphinDOS ROM
// constantly reads $DD0D and $DD01 until handshake bit of $DD0D is set, or some kind
// of timeout occurs
ldx #$20
dolphindos_detect_loop:
lda CIA2_ICR
cmp #$10
beq dolphindos_detect_success
lda CIA2_PRB // XXX do we need this read?
dex
bne dolphindos_detect_loop
// FALLTROUGH - protocol not detected
dolphindos_detect_fail:
rts
dolphindos_detect_success:
// Protocol detected
lda #$02
sta IECPROTO
rts
#endif // CONFIG_IEC_DOLPHINDOS
+122
View File
@@ -0,0 +1,122 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// DolphinDOS protocol support for IEC - optimized load loop
//
#if CONFIG_IEC_DOLPHINDOS && !CONFIG_MEMORY_MODEL_60K
dolphindos_load:
// Timing is critical for some parts, do not allow interrupts
sei
// A trick to shorten EAL update time
ldy #$00
#if CONFIG_IEC_DOLPHINDOS_FAST
// Another trick: prepare values for quickly setting/releasing DATA
lda CIA2_PRA
and #$FF - BIT_CIA2_PRA_DAT_OUT - BIT_CIA2_PRA_CLK_OUT - BIT_CIA2_PRA_ATN_OUT
sta IECPROTO // release DATA
ora #BIT_CIA2_PRA_DAT_OUT
sta TBTCNT // pull DATA
#endif
// FALLTROUGH
dolphindos_load_loop:
#if !CONFIG_IEC_DOLPHINDOS_FAST
// Check if this was EOI
bit IOSTATUS
bvs dolphindos_load_end
#endif
// Wait for the talker to release the CLK line
!:
bit CIA2_PRA
bvc !-
// Release the DATA to signal we are ready
#if !CONFIG_IEC_DOLPHINDOS_FAST
lda CIA2_PRA
and #$FF - BIT_CIA2_PRA_DAT_OUT // release
#else
lda IECPROTO
#endif
sta CIA2_PRA
#if !CONFIG_IEC_DOLPHINDOS_FAST
// Check if EOI
jsr iec_rx_check_eoi // can damage .X, but this is safe
#else
// Check if EOI - inlined code to avoid wasting cycles on RTS
ldx #$13
!:
bit CIA2_PRA
bvc dolphindos_load_no_eoi
dex
bne !-
// EOI - mark it and retrieve the last byte
jsr iec_rx_check_eoi_confirm
lda CIA2_PRB
sta (EAL),y
// Update EAL for the last time
sec
jsr iec_update_EAL_by_Y
// Restore proper IECPROTO value
lda #$02
sta IECPROTO
// End of load loop
jmp load_iec_loop_end
dolphindos_load_no_eoi:
#endif
// Retrieve and store byte
lda CIA2_PRB
sta (EAL),y
// Pull DATA to acknowledge
#if !CONFIG_IEC_DOLPHINDOS_FAST
lda CIA2_PRA
ora #BIT_CIA2_PRA_DAT_OUT
#else
lda TBTCNT
#endif
sta CIA2_PRA
// Handle EAL
iny
bne dolphindos_load_loop
inc EAL+1
jmp dolphindos_load_loop
#if !CONFIG_IEC_DOLPHINDOS_FAST
dolphindos_load_end:
// Update EAL
clc
jsr iec_update_EAL_by_Y
// End of load loop
jmp load_iec_loop_end
#endif
#endif // CONFIG_IEC_DOLPHINDOS and not CONFIG_MEMORY_MODEL_60K
+42
View File
@@ -0,0 +1,42 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Helper table for encoding lower nibble for JiffyDOS,
// values found by observing the actual transfer using
// original ROMs
//
// Similar tables are probably used by nearly all the disk turbo loaders,
// either on the C64 or drive side, soometimes generated in RAM on the fly;
// example disk turbo presented below has a very similar table - but the
// values are in reversed order:
// - https://www.pagetable.com/?p=568
#if CONFIG_IEC_JIFFYDOS
jiffydos_bittable:
.byte $00
.byte $80 // $10 + $70
.byte $20
.byte $A0 // $30 + $70
.byte $40
.byte $C0 // $50 + $70
.byte $60
.byte $E0 // $70 + $70
.byte $10 // $80 - $70
.byte $90
.byte $30 // $A0 - $70
.byte $B0
.byte $50 // $C0 - $70
.byte $D0
.byte $70 // $E0 - $70
.byte $F0
#endif // CONFIG_IEC_JIFFYDOS
+54
View File
@@ -0,0 +1,54 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Helper routine for JiffyDOS detection
//
// Detection is done by inserting a long delay (above 400us?) during sending command last bit, see:
// - https://sites.google.com/site/h2obsession/CBM/C128/JiffySoft128
// - https://github.com/rkrajnc/sd2iec/blob/master/src/iec.c
// The 'iec.s' suggests, that the drive should respond by pulling data
// The original JiffyDOS ROM seems to perform detection with every command
// (even though for many of them it always fails) and we have to replicate
// this behaviour for compatibility with at least 1541 JiffyDOS ROM
#if CONFIG_IEC_JIFFYDOS
jiffydos_detect:
ldy #$25 // 400us is nearly 410 cycles on NTSC
// loop iteration below is 11 cycles,
// and several cycles were already used
jiffydos_detect_loop:
lda CIA2_PRA // 4 cycles
bpl jiffydos_detected // 2 cycles
dey // 2 cycles
bne jiffydos_detect_loop // 3 cycles if branch
lda IECPROTO
bpl jiffydos_detect_end // no detection requested, preserve existing protocol
lda #$00 // normal protocol
beq jiffydos_store_proto // branch always
jiffydos_detected:
jsr iec_wait_for_data_release // guessed from VICE logs
lda #$01 // JiffyDOS protocol
// FALLTROUGH
jiffydos_store_proto:
sta IECPROTO
// FALLTROUGH
jiffydos_detect_end:
rts
#endif // CONFIG_IEC_JIFFYDOS
+175
View File
@@ -0,0 +1,175 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// JiffyDOS protocol support for IEC - optimized load loop
//
#if CONFIG_IEC_JIFFYDOS && !CONFIG_MEMORY_MODEL_60K
// Note: original JiffyDOS LOAD loop checks for RUN/STOP key every time a sector is read,
// see description at https://sites.google.com/site/h2obsession/CBM/C128/JiffySoft128
//
// For simplicity and some space savings, our routine does not check the RUN/STOP key at all;
// the protocol is fast enough (especially with modern flash mediums) that probably nobody
// will want to terminate the loading.
jiffydos_load:
// XXX implement JiffyDOS optimized LOAD protocol, this one is ineffective
// Timing is critical, do not allow interrupts
sei
#if CONFIG_IEC_JIFFYDOS_BLANK
// Preserve register with screen status (blank/visible)
lda VIC_SCROLY
sta TBTCNT
// Blank screen to make sure no sprite/badline will interrupt
jsr screen_off
// Preserve 3 lowest bits of CIA2_PRA XXX deduplicate this
lda CIA2_PRA
and #%00000111
sta C3PO
#else
// Store previous sprite status in temporary variable
jsr jiffydos_prepare
sta TBTCNT
#endif
// A trick to shorten EAL update time
ldy #$FF
// FALLTROUGH
jiffydos_load_loop:
// Wait until device is ready to send (releases CLK)
jsr iec_wait_for_clk_release
// Prepare 'start sending' message
lda CIA2_PRA
and #$FF - BIT_CIA2_PRA_DAT_OUT // release
#if CONFIG_IEC_JIFFYDOS_BLANK
// It seems JiffyDOS needs some time here; waste few cycles
nop
jsr iec_wait_rts
// Ask device to start sending bits
sta CIA2_PRA
#else
// Wait for appropriate moment, ask device to start sending bits
tax
jsr jiffydos_wait_line
stx CIA2_PRA // cycles: 4
#endif
// Prepare 'data pull' byte, cycles: 3 + 2 + 2 = 7
lda C3PO
ora #BIT_CIA2_PRA_DAT_OUT // pull
tax
// Delay, JiffyDOS needs some time, 4 cycles
nop
nop
// Get bits, cycles: 4 + 2 + 2 = 8
lda CIA2_PRA // bits 0 and 1 on CLK/DATA
lsr
lsr
// Delay, JiffyDOS needs some time, 2 cycles
nop
// Get bits, cycles: 4 + 2 + 2 = 8
ora CIA2_PRA // bits 2 and 3 on CLK/DATA
lsr
lsr
// Get bits, cycles: 3 + 4 + 2 + 2 = 11
eor C3PO
eor CIA2_PRA // bits 4 and 5 on CLK/DATA
lsr
lsr
// Get bits, cycles: 3 + 4 = 7
eor C3PO
eor CIA2_PRA // bits 6 and 7 on CLK/DATA
// Store retrieved byte, cycles: 2 + 6 = 8
iny // NTSC needs this delay
sta (EAL),y // not compatible with CONFIG_MEMORY_MODEL_60K
// Retrieve status bits, cycles: 4
bit CIA2_PRA
// Pull DATA at the end, cycles: 4
stx CIA2_PRA
// If CLK line not active - this was the last byte
bvs jiffydos_load_end
// Handle EAL
cpy #$FF
bne jiffydos_load_loop
inc EAL+1
jmp jiffydos_load_loop
jiffydos_load_end:
// Save last byte
tax
// Update EAL
sec
jsr iec_update_EAL_by_Y
// Indicate that no byte waits in output buffer
lda #$00
sta C3PO
// Restore proper IECPROTO value
lda #$01
sta IECPROTO
#if CONFIG_IEC_JIFFYDOS_BLANK
// Restore screen state
lda TBTCNT
sta VIC_SCROLY
#else
// Re-enable sprites
lda TBTCNT
sta VIC_SPENA
#endif
// Store last byte as unoptimized LOAD routine would
stx TBTCNT
// No need to re-enable interrupts; other IEC routines
// called by LOAD will do this nevertheless
// End of load loop
jmp load_iec_loop_end
#endif // CONFIG_IEC_JIFFYDOS and not CONFIG_MEMORY_MODEL_60K
+32
View File
@@ -0,0 +1,32 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// JiffyDOS transfer preparation routine
//
#if CONFIG_IEC_JIFFYDOS
jiffydos_prepare:
// We need to preserve 3 lowest bits of CIA2_PRA, they contain important
// data - fortunately, the bits are never changed by external devices
// Use C3PO for this, as afterwards we have to set there 0 nevertheless
lda CIA2_PRA
and #%00000111
sta C3PO
// Hide sprites; JiffyDOS timing regime is very strict, before transmitting
// anything we need to make sure nothing will steal the cycles
lda VIC_SPENA
ldx #$00
stx VIC_SPENA
rts
#endif // CONFIG_IEC_JIFFYDOS
+121
View File
@@ -0,0 +1,121 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// JiffyDOS protocol support for IEC - byte reception
//
#if CONFIG_IEC_JIFFYDOS
jiffydos_rx_byte:
// Timing is critical, do not allow interrupts
sei
// Store .X and .Y on the stack - preserve them
phx_trash_a
phy_trash_a
// Store previous sprite status on stack
jsr jiffydos_prepare
pha
// Wait until device is ready to send (releases CLK)
jsr iec_wait_for_clk_release
// Prepare 'start sending' message
lda CIA2_PRA
and #$FF - BIT_CIA2_PRA_DAT_OUT // release
tax
// Wait for appropriate moment
jsr jiffydos_wait_line
// Ask device to start sending bits
stx CIA2_PRA // cycles: 4
// Prepare 'data pull' byte, cycles: 3 + 2 + 2 = 7
lda C3PO
ora #BIT_CIA2_PRA_DAT_OUT // pull
tax
// Delay, JiffyDOS needs some time, 4 cycles
nop
nop
// Get bits, cycles: 4 + 2 + 2 = 8
lda CIA2_PRA // bits 0 and 1 on CLK/DATA
lsr
lsr
// Wait for the drive, cycles: 2
nop
// Get bits, cycles: 4 + 2 + 2 = 8
ora CIA2_PRA // bits 2 and 3 on CLK/DATA
lsr
lsr
// Get bits, cycles: 3 + 4 + 2 + 2 = 11
eor C3PO
eor CIA2_PRA // bits 4 and 5 on CLK/DATA
lsr
lsr
// Get bits, cycles: 3 + 4 = 7
eor C3PO
eor CIA2_PRA // bits 6 and 7 on CLK/DATA
// Preserve read byte, cycles: 3
sta TBTCNT // $A4 is a byte buffer according to http://sta.c64.org/cbm64mem.html
// Delay, JiffyDOS needs some time; for PAL one NOP would be enough,
// but NTSC machines are clocked slightly faster; cycles: 4
nop
nop
// Retrieve status bits, cycles: 4
bit CIA2_PRA
// Pull DATA at the end, cycles: 4
stx CIA2_PRA
// If CLK line active - success
bvc jiffydos_rx_byte_end
// EOI or error, released DATA (highest byte set to 1) means error - see protocol analysis by Michael Steil, step R7a
lda CIA2_PRA
bmi jiffydos_rx_byte_error
// EOI - no error
jsr kernalstatus_EOI
// FALLTROUGH
jiffydos_rx_byte_end:
// Indicate that no byte waits in output buffer
lda #$00
sta C3PO
// Restore proper IECPROTO value
lda #$01
sta IECPROTO
// Re-enable sprites
pla
sta VIC_SPENA
// End byte reception
jmp iec_rx_end
jiffydos_rx_byte_error:
jsr kernalerror_IEC_TIMEOUT_READ
bcs jiffydos_rx_byte_end // branch always
#endif // CONFIG_IEC_JIFFYDOS
+111
View File
@@ -0,0 +1,111 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// JiffyDOS protocol support for IEC - byte transfer
//
#if CONFIG_IEC_JIFFYDOS
jiffydos_tx_byte:
// Timing is critical, do not allow interrupts
sei
// If EOI requested (carry flag set), mark this in IECPROTO as 0
bcc !+
dec IECPROTO // turns 1 into 0
!:
// Store .X and .Y on the stack - preserve them
phx_trash_a
phy_trash_a
// Make sure we are not sending data on ATN
jsr iec_release_atn
// Store previous sprite status on stack
jsr jiffydos_prepare
pha
// Prepare nibbles to send
lda TBTCNT
and #$0F
tax
lda jiffydos_bittable, X // low nibble has to be encoded
pha
lda TBTCNT
and #$F0
pha
// Prepare value for device notification
ldx C3PO
// Wait till receiver is ready
jsr iec_wait_for_data_release
// Wait till it is safe to send data
jsr jiffydos_wait_line
// Notify device that we are going to send byte by releasing everything
stx CIA2_PRA // cycles: 4
// Send high nibble; cycles: 4 + 3 + 4 + 2 + 2 + 2 + 3 + 4 = 24
pla // retrieve high nibble from stack
ora C3PO // restore VIC-II and RS-232 bits
sta CIA2_PRA // bits 4 and 5 on CLK/DATA
lsr // move bits 6 and 7 to positions 4 and 5
lsr
and #%00110000 // clear everything but CLK/DATA
ora C3PO
sta CIA2_PRA // bits 6 and 7 on CLK/DATA
// Send low nibble; cycles: 4 + 3 + 4 + 2 + 2 + 2 + 4 = 21
pla // retrieve low nibble from stack
ora C3PO // restore VIC-II and RS-232 bits
sta CIA2_PRA
lsr
lsr
and #%00110000 // clear everything but CLK/DATA
sta CIA2_PRA
// Signal EOI if needed; cycles till no EOI: 3 + 3 + 2 + 2 + 4 = 14
lda C3PO
ldx IECPROTO
beq jiffydos_tx_byte_wait_eoi
// FALLTROUGH
jiffydos_tx_byte_finalize:
ora #BIT_CIA2_PRA_CLK_OUT // pull CLK
sta CIA2_PRA
// Restore proper IECPROTO value
lda #$01
sta IECPROTO
// Re-enable sprites and interrupts
pla
sta VIC_SPENA
cli
// Return success
jmp iec_return_success
jiffydos_tx_byte_wait_eoi:
sta CIA2_PRA
jsr iec_wait20us
lda C3PO
// According to protocol analysis by Michael Steil (step S8) we should pull the DATA here
// to signal there was no error; but DATA pulled by the controller is a normal state
// (which should be stored in C3PO), so there is nothing to do here.
jmp jiffydos_tx_byte_finalize
#endif // CONFIG_IEC_JIFFYDOS
+37
View File
@@ -0,0 +1,37 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// JiffyDOS helper routine to wait for appropriate moment,
// where no badline will interrupt the transmission
//
#if CONFIG_IEC_JIFFYDOS
jiffydos_wait_line:
// One might try to optimize the code by checking for disabled screen
// (bit 4 of VIC_SCROLY); problem: VIC checks this bit only once per frame:
// - https://www.lemon64.com/forum/viewtopic.php?t=56582
// so it would complicated the code
// Avoid 2 lines before the badline, otherwise VIC will ruin the synchronization
lda VIC_RASTER
cmp #$2E
bcc jiffydos_wait_line_done // we are safe, border - lot of time till badline
!:
lda VIC_RASTER // carry+ is definitely set here!
sbc VIC_SCROLY
and #$07 // we want 8 lowest bits
cmp #$06
bcs !-
jiffydos_wait_line_done:
rts
#endif // CONFIG_IEC_JIFFYDOS
+23
View File
@@ -0,0 +1,23 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# X16 * #IGNORE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
// c64 prg p263
cartridge_check:
ldx #$05
!:
lda CART_SIG-1,x
cmp cartridge_signature-1,x
bne cartridge_check_end
dex
bne !-
// FALLTROUGH
cartridge_check_end:
rts
+76
View File
@@ -0,0 +1,76 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// This is a part CINT which initializes screen and keyboard
//
// For more details see:
// - [RG64] C64 Programmers Reference Guide - page 280
// - [CM64] Computes Mapping the Commodore 64 - page 242
//
cint_screen_keyboard:
// Setup KEYLOG vector
lda #<scnkey_set_keytab
sta KEYLOG+0
lda #>scnkey_set_keytab
sta KEYLOG+1
// Initialise cursor blink flags (Computes Mapping the 64 p215)
lda #$01
sta BLNCT
sta BLNSW
// Enable cursor repeat - XXX make it configurable
#if CONFIG_KEY_REPEAT_DEFAULT && !CONFIG_KEY_REPEAT_ALWAYS
lda #$80
sta RPTFLG
#endif
// Set keyboard decode vector (Computes Mapping the 64 p215)
#if CONFIG_LEGACY_SCNKEY
// Set initial variables for our improved keyboard scan routine
lda #$FF
ldx #6
!: sta BufferOld,x
dex
bpl !-
sta BufferQuantity
// Set key repeat delay (Computes Mapping the 64 p215)
// Making some numbers up here: Repeat every ~1/10th sec
// But require key to be held for ~1/3sec before
// repeating (Computes Mapping the 64 p58)
// Not needed for default keyboard scanning code
ldx #22-2 // Fudge factor to match speed
stx DELAY
#endif
// Set current colour for text (Computes Mapping the 64 p215)
ldx #CONFIG_COLOR_TXT
stx COLOR
// Set maximum keyboard buffer size (Computes Mapping the 64 p215)
ldx #10
stx XMAX
// Put non-zero value in MODE to enable case switch
ldx #$00
stx MODE
// Fallthrough/jump to screen clear routine (Computes Mapping the 64 p215)
jmp clear_screen
+25
View File
@@ -0,0 +1,25 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Part of the official Kernal routine, described in:
//
// - [RG64] C64 Programmers Reference Guide - page 280
// - [CM64] Computes Mapping the Commodore 64 - page 242
//
// CPU registers that has to be preserved (see [RG64]): none
//
cint_legacy: // $E518
// Setup video and I/O
// See here: https://csdb.dk/forums/index.php?roomid=11&topicid=17048&firstpost=22
jsr setup_vicii
// Code below must be placed under $E51B, or some code will break - see here:
// - https://csdb.dk/forums/index.php?roomid=11&topicid=17048&firstpost=2
// Game 'Operacja Proboszcz' is one example.
jmp cint_screen_keyboard // XXX try to fit the code here
+3
View File
@@ -0,0 +1,3 @@
Game 'Operacja Proboszcz' explicitly calls $E51B - thus, it is sane
to place old CINT routine in it's original place
+71
View File
@@ -0,0 +1,71 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# M65 KERNAL_0 #TAKE
// #LAYOUT# M65 KERNAL_1 #TAKE-FLOAT
// #LAYOUT# X16 * #IGNORE
// #LAYOUT# * * #IGNORE
//
// Well-known Kernal routine, described in:
//
// - [CM64] Computes Mapping the Commodore 64 - page 215
//
setup_vicii:
#if (ROM_LAYOUT_M65 && SEGMENT_KERNAL_0)
jsr map_KERNAL_1
jsr_ind VK1__setup_vicii
jmp map_NORMAL
#else
// Clear everything - turn off sprites (observed hanging around after
// running programs and resetting), etc.
lda #$00
ldx #$2E
!:
sta __VIC_BASE, x
dex
bpl !-
#if !CONFIG_MB_MEGA_65 && !CONFIG_MB_ULTIMATE_64
// Disable C128 extra keys - just to be sure they will not interfere with anything
stx VIC_XSCAN
// Disable the C128 2MHz mode, it prevents VIC-II display from working correctly
stx VIC_CLKRATE
#endif
// Set up default IO values
// - [CM64] page 129 - VIC_SCROLY
// - [CM64] pages 140-144 - VIC_SCROLX
// - [CM64] pages 145-146 - VIC_YMCSB
lda #$1B // according to [CM64] page 137 some software assumes oldest bit is 0
sta VIC_SCROLY
lda #$C8
sta VIC_SCROLX // 40 column etc
lda #$14
sta VIC_YMCSB
lda #$0F
sta VIC_IRQ // clear all interrupts
// We use a different colour scheme of white text on all blue by default,
// but brand-specific color scheme can also be enabled
lda #CONFIG_COLOR_BG
sta VIC_EXTCOL
sta VIC_BGCOL0
// Setup default I/O devices
jmp clrchn_reset
#endif // ROM layout
+71
View File
@@ -0,0 +1,71 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
// Resources describing the C64 reset sequence:
// https://www.c64-wiki.com/wiki/Reset_(Process)
hw_entry_reset:
// The GPL program at https://github.com/Klaus2m5/6502_65C02_functional_tests/blob/master/6502_functional_test.a65
// uses the similar initial reset sequence, affirmed by c64 PRG p269
sei // disable the interrupts, as fast as possible - they are disabled in case of HW reset,
// but this routine can be also called manually
cld // required for all CPUs - due to possibility of manual call
#if HAS_OPCODES_65CE02
see // disable extended stack
#endif
ldx #$FF
txs
#if ROM_LAYOUT_M65
jsr map_NORMAL // we want normal memory mapping
#endif
#if CONFIG_PLATFORM_COMMODORE_64
// The following routine is based on reading the public KERNAL jumptable routine
// list, and making unimaginative assumptions about what should be done on reset.
// Also, https://codebase64.org/doku.php?id=base:assembling_your_own_cart_rom_image was used
// as it shows example startup sequence, to be followe by cartridge creators
// C64 PRG p269
jsr cartridge_check
bne !+
jmp (ICART_COLD_START)
!:
// Disable the screen (and set 40 columns) to prevent visual glitches later
ldx #$28
stx VIC_SCROLX
#endif
// Initialising IO is obviously required. Also indicated by c64 prg p269.
jsr JIOINIT
// Setting up the screen and testing ram is obviously required
// also affirmed by p269 of c64 prg
jsr JRAMTAS // called RANTAM on Codebase64 wiki
// Resetting IO vectors is obviously required, if we want interrupts to run
// also affirmed by c64 prg p269
jsr JRESTOR
// "Compute's Mapping the 64" p236
jsr JCINT
// What do we do when finished? A C64 jumps into the BASIC ROM
cli // allow interrupts to happen
// c64 prg p269
jmp (IBASIC_COLD_START)
+5
View File
@@ -0,0 +1,5 @@
System reset routine has to be placed under it's original location due to 'SYS 64738' being extremaly popular to reset the C64,
to the point it went into popular culture.
https://twitter.com/hashtag/SYS64738?src=hash
https://www.computerhope.com/jargon/s/sys64738.htm
+3
View File
@@ -0,0 +1,3 @@
RRAMTAS is an important startup routine, frequentl called b cartridges - unfortunately, we can't count on them calling it
via the jumptable, as even some tutorials on the web advise to call it directly - see for example here:
https://codebase64.org/doku.php?id=base:assembling_your_own_cart_rom_image
+115
View File
@@ -0,0 +1,115 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# M65 KERNAL_0 #TAKE
// #LAYOUT# M65 KERNAL_1 #TAKE-FLOAT
// #LAYOUT# X16 KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Official Kernal routine, described in:
//
// - [RG64] C64 Programmers Reference Guide - page 291
// - [CM64] Computes Mapping the Commodore 64 - page 237
//
// CPU registers that has to be preserved (see [RG64]): none
//
RAMTAS:
#if (ROM_LAYOUT_M65 && SEGMENT_KERNAL_0)
jsr map_KERNAL_1
jsr_ind VK1__RAMTAS
jmp map_NORMAL
#else
// C64 Programmers Reference guide p291:
// Clear $0000-$0101, $0200-$03ff
// PGS: $0000, $0001 are CPU IO ports, so should not get written to
// How many ways are there to efficiently erase these two pages
// of RAM? We would like to avoid any unnecessary byte similarity
// with the C64 KERNAL. Thus we do $0300 before $0200, even though
// with the longer sequence of identicale bytes we see no basis for
// it being copyrightable. Again, we just want to redue the attack
// surface for any misguided suit.
ldy #$00
lda #$00
!:
sta $0300,Y
sta $0200,Y
sta $0002,Y // that is why we do not use .X for index, we do not want zeropage addressing here!
iny
bne !-
// Allocate cassette buffer
ldx #<$033C
stx TAPE1+0
ldx #>$033C
stx TAPE1+1
#if CONFIG_PLATFORM_COMMODORE_64
// Set screen address pointer ("Compute's Mapping the 64" p238)
// This is obvious boiler plate containing no creative input, but to avoid
// unnecessarily similarity to the C64 KERNAL, we use X instead of A to do this,
// and several following
ldx #>$0400
stx HIBASE
// Set BASIC start text pointer
// (remember, that low memory is 0 initialized at this moment)
ldx #>$0800
stx MEMSTR+1
// Work out RAM size and put in MEMSIZK
// Try to modify $8000, if it fails then RAM ends at $7FFF, else $9FFF
ldx $8000
inx
stx $8000
cpx $8000
bne ramtas_32k
// FALLTROUGH
ramtas_40k:
// 40K RAM - restore memory content, set MEMSIZK
ldy #$A0
!:
sty MEMSIZK+1
// Always restore memory, cartridge might have RAM under ROM
dex
stx $8000
rts
ramtas_32k:
// 32K RAM - restore memory content, set MEMSIZK
ldy #$80
bne !- // branch always
#elif CONFIG_PLATFORM_COMMANDER_X16
ldx #>$0800
stx MEMSTR+1
ldy #$9F
sty MEMSIZK+1
#else
.error "Please fill-in RAMTAS"
#endif // platform
#endif // ROM layout
+174
View File
@@ -0,0 +1,174 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# M65 KERNAL_0 #TAKE
// #LAYOUT# M65 KERNAL_1 #TAKE-FLOAT
// #LAYOUT# X16 * #IGNORE
// #LAYOUT# * * #IGNORE
//
// Official Kernal routine, described in:
//
// - [RG64] C64 Programmers Reference Guide - page 285
// - [CM64] Computes Mapping the Commodore 64 - page 238
//
// CPU registers that has to be preserved (see [RG64]): none
//
IOINIT:
#if (ROM_LAYOUT_M65 && SEGMENT_KERNAL_0)
jsr map_KERNAL_1
jsr_ind VK1__IOINIT
jmp map_NORMAL
#else
//
// First initialize the CPU port, to make sure we have correct memory map
//
// We want BASIC and KERNAL ROMs mapped, and datasette motor off
// (https://www.c64-wiki.com/wiki/Zeropage)
// Work around for VICE bug: Writing $00 before $01 results in rubbish in $01
// after. https://sourceforge.net/p/vice-emu/bugs/1057/
ldx #$27
stx CPU_R6510
ldx #$2F // checked real ROM value
stx CPU_D6510
//
// Now prevent the CIAs from generating interrupts, who knows what damage they can do
//
// Disable IRQ generation for both CIAs - see [CM64], page 149
ldx #$7F
stx CIA1_ICR // $DC0D
stx CIA2_ICR // $DD0D
// See discussion here:
// https://www.lemon64.com/forum/viewtopic.php?t=41744&sid=e294c254db2ba671cde643f100aae341
// It seems that initializing this register to $7F is the best idea - UDTIM key scanning
// also leaves this at $7F
stx CIA1_PRA // $DC00
//
// Now silence the SID chip(s), depending on the configuration - we want them silent ASAP
//
lda #$00
#if !CONFIG_MB_MEGA_65
// First the standard chip (skip if it is covered by whole $D4XX range)
#if !CONFIG_SID_D4XX
sta SID_SIGVOL
#endif // !CONFIG_SID_D4XX
// Silence manually configured 2nd and 3rd SIDs
#if CONFIG_SID_2ND
sta SID_SIGVOL - __SID_BASE + CONFIG_SID_2ND_ADDRESS
#endif // CONFIG_SID_2ND
#if CONFIG_SID_3RD
sta SID_SIGVOL - __SID_BASE + CONFIG_SID_3RD_ADDRESS
#endif // CONFIG_SID_3RD
// Silence whole D4XX and D5XX ranges (if configured)
#if CONFIG_SID_D4XX || CONFIG_SID_D5XX
ldy #$00
!:
#if CONFIG_SID_D4XX
sta SID_SIGVOL + $000, Y
#endif // CONFIG_SID_D4XX
#if CONFIG_SID_D5XX
sta SID_SIGVOL + $100, Y
#endif // CONFIG_SID_D4XX
tya
clc
adc #$20
tay
bne !-
#endif // CONFIG_SID_D4XX || CONFIG_SID_D5XX
#else
// Mega65 specific handling - it contains 4 SIDs
sta SID_SIGVOL + __SID_R1_OFFSET
sta SID_SIGVOL + __SID_R2_OFFSET
sta SID_SIGVOL + __SID_L1_OFFSET
sta SID_SIGVOL + __SID_L2_OFFSET
#endif // CONFIG_MB_MEGA_65
//
// Now continue the CIAs initialization
//
// For CIA #1 we need port A as output and port B as input to scan the keyboard
ldx #$FF
stx CIA1_DDRA // $DC02
inx
stx CIA1_DDRB // $DC03
stx CIA2_DDRB // $DD03 // XXX this port is used for RS-232, value here is most likely wrong!
#if CONFIG_KEYBOARD_C65 || CONFIG_KEYBOARD_C65_CAPS_LOCK
lda #$02
sta C65_EXTKEYS_DDR // output for most keys, input for CAPS LOCK bit
#endif
// Set DDR on CIA2 for IEC bus, VIC-II banking (see [CM64], $DDOO description on page 193)
lda #$3F
sta CIA2_DDRA // $DD02
// Checked using VICE that original ROM initializes timers this way
ldx #$08
stx CIA1_CRB // $DC0F
stx CIA2_CRA // $DD0E
stx CIA2_CRB // $DD0F
// Set VIC-II bank - at least the 'Operacja Proboszcz' game needs this within IOINIT
// Checked on original ROMs, that it sets bit #2 (RS-232 output) high
ldx #%00000111 // XXX adapt this to IEC idle state, JMP at the end won't be needed
stx CIA2_PRA // $DD00
// Put something sane in the IRQ timer
jsr setup_irq_timer
// Enable timer A to run continuously (http://codebase64.org/doku.php?id=base:timerinterrupts)
ldx #$11
stx CIA1_CRA // $DC0E
// Enable timer interrupt
ldx #$81
stx CIA1_ICR // $DC0D
#if CONFIG_IEC
// Set IEC bus to its initial idle state
jmp iec_set_idle
#else
rts
#endif
#endif // ROM layout
+17
View File
@@ -0,0 +1,17 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Official Kernal routine, described in:
//
// - [RG64] C64 Programmers Reference Guide - page 280
// - [CM64] Computes Mapping the Commodore 64 - page 242
//
// CPU registers that has to be preserved (see [RG64]): none
//
CINT:
jsr cint_legacy
jmp setup_pal_ntsc
Loaded 100 of 697 files, more files were not shown because too many files have changed in this diff. Show more