more sane directory name, updated binaries
This commit is contained in:
1 parent
d4d32095d1
commit
76aaf298b8
697 files changed
+56
-56
No files matched your search
@@ -0,0 +1,172 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Tape (normal) part of the LOAD routine
|
||||
//
|
||||
|
||||
|
||||
// We have the following possible CPU frequencies:
|
||||
// - C64 PAL: CPU frequency 0.985248 MHz
|
||||
// - C64 NTSC: CPU frequency 1.022727 MHz
|
||||
// The clock difference is about 4% - it is unlikely to cause problems.
|
||||
//
|
||||
// We have to distinguish the following pulse lengths (http://sidpreservation.6581.org/tape-format/):
|
||||
// - S (short) tap value $30 (PAL: 352 us)
|
||||
// - M (medium) tap value $42 (PAL: 512 us)
|
||||
// - L (long) tap value $56 (PAL: 672 us)
|
||||
//
|
||||
// The TAP format (http://unusedino.de/ec64/technical/formats/tap.html) uses a resolution of 8 PAL ticks;
|
||||
// this implementation sets the timer for twice the precision (timer B is triggered every 4 CPU cycles),
|
||||
// probably an overkill, but in realityy it does not cost us anything.
|
||||
//
|
||||
// So - we have the following thresholds:
|
||||
// - S vs M $72 (in our units of 4 ticks)
|
||||
// - M vs L $98 (in our units of 4 ticks)
|
||||
//
|
||||
// We need to recognize the following pulse sequences:
|
||||
//
|
||||
// (S,M) = 0 bit
|
||||
// (M,S) = 1 bit
|
||||
// (L,M) = new-data marker
|
||||
// (L,S) = end-of-data marker
|
||||
|
||||
|
||||
#if CONFIG_TAPE_NORMAL
|
||||
|
||||
|
||||
#if !CONFIG_TAPE_AUTODETECT
|
||||
|
||||
load_tape_normal:
|
||||
|
||||
jsr tape_ditch_verify // only LOAD is supported, no VERIFY
|
||||
|
||||
// Start playing
|
||||
jsr tape_common_prepare_cia
|
||||
jsr tape_ask_play
|
||||
#if CONFIG_TAPE_HEAD_ALIGN
|
||||
jsr tape_prepare_reading
|
||||
#endif
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
load_tape_normal_header:
|
||||
|
||||
#else
|
||||
|
||||
load_tape_normal_takeover: // entry point for turbo->normal takeover
|
||||
|
||||
#endif
|
||||
|
||||
jsr load_MEMUSS_to_STAL
|
||||
|
||||
// Try to load header into tape buffer (we will restore MEMUSS later)
|
||||
|
||||
jsr tape_normal_get_pilot_header
|
||||
#if CONFIG_TAPE_AUTODETECT
|
||||
bcs load_tape_normal_switch_turbo // failed, try turbo
|
||||
#endif
|
||||
|
||||
jsr load_TAPE1_to_MEMUSS
|
||||
jsr tape_normal_get_data_1
|
||||
#if !CONFIG_TAPE_AUTODETECT
|
||||
bcs load_tape_normal_header // unable to read block, try again
|
||||
#else
|
||||
bcc !+
|
||||
load_tape_normal_switch_turbo:
|
||||
jsr lvs_STAL_to_MEMUSS
|
||||
jmp load_tape_turbo_takeover // unable to read block, try turbo instead
|
||||
!:
|
||||
#endif
|
||||
|
||||
#if CONFIG_TAPE_NO_ERROR_CORRECTION
|
||||
lda RIPRTY
|
||||
cmp #$01 // sets Carry if checksum verification fails
|
||||
#else
|
||||
jsr load_TAPE1_to_MEMUSS
|
||||
jsr tape_normal_get_data_2
|
||||
#endif
|
||||
#if !CONFIG_TAPE_AUTODETECT
|
||||
bcs load_tape_normal_header // block load error, try again
|
||||
#else
|
||||
bcs load_tape_normal_switch_turbo // block load error, try turbo instead
|
||||
#endif
|
||||
|
||||
// Check header type
|
||||
|
||||
ldy #$00
|
||||
lda (TAPE1),y
|
||||
|
||||
cmp #$05
|
||||
beq_16 tape_load_error // end of tape mark, nothing to load
|
||||
|
||||
cmp #$01
|
||||
beq !+
|
||||
cmp #$03
|
||||
#if !CONFIG_TAPE_AUTODETECT
|
||||
bne load_tape_normal_header // header types 1 and 3 are loadable, see Mapping the C64, page 77
|
||||
#else
|
||||
bne load_tape_normal_takeover
|
||||
#endif
|
||||
|
||||
lda #$01
|
||||
sta SA // this file is non-relocatable; override secondary address with 1
|
||||
!:
|
||||
// Restore MEMUSS, handle header
|
||||
|
||||
jsr lvs_STAL_to_MEMUSS
|
||||
jsr tape_handle_header
|
||||
#if !CONFIG_TAPE_AUTODETECT
|
||||
bcs load_tape_normal_header // if name does not match, look for other header
|
||||
#else
|
||||
bcs load_tape_normal_takeover
|
||||
#endif
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
load_tape_normal_payload:
|
||||
|
||||
// Retrieve data
|
||||
|
||||
jsr tape_normal_get_pilot_data
|
||||
ldy #$00 // no data size limit
|
||||
jsr tape_normal_get_data_1
|
||||
bcs_16 tape_load_error
|
||||
|
||||
jsr lvs_check_EAL
|
||||
bne_16 tape_load_error // amount of data read does not match header info
|
||||
|
||||
#if CONFIG_TAPE_NO_ERROR_CORRECTION
|
||||
lda RIPRTY
|
||||
cmp #$01 // sets Carry if checksum verification fails
|
||||
#else
|
||||
jsr lvs_STAL_to_MEMUSS
|
||||
jsr tape_normal_get_data_2
|
||||
#endif
|
||||
bcs_16 tape_load_error
|
||||
|
||||
jmp tape_load_success
|
||||
|
||||
|
||||
|
||||
load_TAPE1_to_MEMUSS: // set MEMUSS (start address) as tape buffer
|
||||
|
||||
lda TAPE1+1
|
||||
sta MEMUSS+1
|
||||
lda TAPE1+0
|
||||
sta MEMUSS+0
|
||||
|
||||
rts
|
||||
|
||||
load_MEMUSS_to_STAL: // preserve MEMUSS
|
||||
|
||||
lda MEMUSS+1
|
||||
sta STAL+1
|
||||
lda MEMUSS+0
|
||||
sta STAL+0
|
||||
|
||||
rts
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,161 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Tape (turbo) part of the LOAD routine
|
||||
//
|
||||
|
||||
// Initially based on routine by enthusi/Onslaught, found here:
|
||||
// - https://codebase64.pokefinder.org/doku.php?id=base:turbotape_loader_source
|
||||
// but heavily reworked since then. Still, original authors deserve credits!
|
||||
|
||||
|
||||
#if CONFIG_TAPE_TURBO
|
||||
|
||||
|
||||
#if !CONFIG_TAPE_AUTODETECT
|
||||
|
||||
load_tape_turbo:
|
||||
|
||||
#else
|
||||
|
||||
load_tape_auto:
|
||||
|
||||
#endif
|
||||
|
||||
jsr tape_ditch_verify // only LOAD is supported, no VERIFY
|
||||
|
||||
// Prepare for sound effects
|
||||
jsr tape_clean_sid
|
||||
|
||||
// Start playing
|
||||
jsr tape_common_prepare_cia
|
||||
jsr tape_ask_play
|
||||
#if CONFIG_TAPE_HEAD_ALIGN
|
||||
jsr tape_prepare_reading
|
||||
#endif
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
#if CONFIG_TAPE_AUTODETECT
|
||||
|
||||
load_tape_turbo_takeover: // entry point for normal->turbo takeover
|
||||
|
||||
jsr tape_common_autodetect
|
||||
bcc_16 load_tape_normal_takeover
|
||||
|
||||
#endif
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
load_tape_turbo_header:
|
||||
|
||||
// Read file header; structure described here:
|
||||
// - https://www.luigidifraia.com/c64/docs/tapeloaders.html#turbotape64
|
||||
//
|
||||
// 1 byte - file type (0 = data, odd value = relocatable, even value = non-relocatable)
|
||||
// 2 bytes - start address
|
||||
// 2 bytes - end address + 1
|
||||
// 1 byte - if $B0 (tape timing) contained at the time of saving
|
||||
// (we skip this one to match normal system header)
|
||||
// 16 bytes - filename, padded with 0x20
|
||||
|
||||
jsr tape_turbo_sync_header
|
||||
#if CONFIG_TAPE_AUTODETECT
|
||||
bcs_16 load_tape_normal_takeover // failure, probably not a turbo tape file
|
||||
#endif
|
||||
ldy #$00
|
||||
sta (TAPE1), y // store header type
|
||||
iny
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
load_tape_turbo_header_loop:
|
||||
|
||||
jsr tape_turbo_get_byte
|
||||
sta (TAPE1), y
|
||||
iny
|
||||
cpy #$05
|
||||
bne !+
|
||||
jsr tape_turbo_get_byte // tape timing - skip this one
|
||||
!:
|
||||
cpy #$C0 // header is 192 bytes long in total
|
||||
bne load_tape_turbo_header_loop
|
||||
|
||||
// For non-relocatable files, override secondary address
|
||||
ldy #$00 // XXX optimize out for 65C02
|
||||
lda (TAPE1), y
|
||||
beq !+
|
||||
and #$01
|
||||
bne !+
|
||||
lda #$01 // XXX for 65C02 just set the bit with one instruction
|
||||
sta SA
|
||||
!:
|
||||
// Handle the header
|
||||
|
||||
jsr tape_clean_sid
|
||||
jsr tape_handle_header
|
||||
bcs load_tape_turbo_header // if name does not match, look for other header
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
load_tape_turbo_payload:
|
||||
|
||||
// Copy helper byte store routine to RAM, provide default memory mapping
|
||||
|
||||
ldx #(__tape_turbo_bytestore_size - 1)
|
||||
!:
|
||||
lda tape_turbo_bytestore_source, x
|
||||
sta __tape_turbo_bytestore, x
|
||||
dex
|
||||
bpl !-
|
||||
|
||||
lda CPU_R6510
|
||||
sta __tape_turbo_bytestore_defmap
|
||||
|
||||
// Initial checksum value
|
||||
|
||||
lda #$00
|
||||
sta PRTY
|
||||
|
||||
// Read file payload
|
||||
!:
|
||||
jsr tape_turbo_sync_payload
|
||||
#if CONFIG_TAPE_AUTODETECT
|
||||
bcs !-
|
||||
#endif
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
load_tape_turbo_loop:
|
||||
|
||||
jsr tape_turbo_get_byte
|
||||
jsr __tape_turbo_bytestore // like 'sta (MEMUSS),y' - but under I/O
|
||||
|
||||
eor PRTY // handle checksum
|
||||
sta PRTY
|
||||
|
||||
// Advance MEMUSS (see Mapping the C64, page 36)
|
||||
#if !HAS_OPCODES_65CE02
|
||||
jsr lvs_advance_MEMUSS
|
||||
#else
|
||||
inw MEMUSS+0
|
||||
#endif
|
||||
jsr lvs_check_EAL
|
||||
bne load_tape_turbo_loop
|
||||
|
||||
// Get the checksum
|
||||
jsr tape_turbo_get_byte
|
||||
tax
|
||||
|
||||
// Silence audio
|
||||
jsr tape_clean_sid
|
||||
|
||||
// Verify the checksum
|
||||
cpx PRTY
|
||||
beq_16 tape_load_success
|
||||
jmp tape_load_error
|
||||
|
||||
|
||||
#endif // CONFIG_TAPE_TURBO
|
||||
@@ -0,0 +1,351 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Common routines for tape support
|
||||
//
|
||||
|
||||
|
||||
#if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO
|
||||
|
||||
|
||||
//
|
||||
// Loading terminated by user
|
||||
//
|
||||
|
||||
tape_break_error:
|
||||
|
||||
pla
|
||||
pla
|
||||
cli
|
||||
jmp kernalerror_ROUTINE_TERMINATED
|
||||
|
||||
|
||||
//
|
||||
// Ask user to press PLAY on tape deck,
|
||||
// Unless user cancelled loading, blank screen and start motor
|
||||
//
|
||||
|
||||
tape_ask_play:
|
||||
|
||||
#if !CONFIG_TAPE_NO_KEY_SENSE
|
||||
|
||||
// First check whether the button is already pressed
|
||||
|
||||
lda CPU_R6510
|
||||
and #$10
|
||||
beq tape_wait_play_done
|
||||
|
||||
#endif
|
||||
|
||||
// Display message
|
||||
|
||||
ldx #__MSG_KERNAL_PRESS_PLAY
|
||||
jsr print_kernal_message
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
#if !CONFIG_TAPE_NO_KEY_SENSE
|
||||
|
||||
tape_wait_play_loop:
|
||||
|
||||
jsr STOP
|
||||
bcs tape_break_error
|
||||
|
||||
lda CPU_R6510
|
||||
and #$10 // check for pressed button
|
||||
bne tape_wait_play_loop
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
#else
|
||||
|
||||
// The ROM is configured for tape adapter without the key sense - but it is still
|
||||
// possible, that regular Datasette or Tapuino is connected
|
||||
|
||||
lda CPU_R6510
|
||||
and #$10
|
||||
beq tape_wait_first_pulse // branch if button reported pressed, most likely really no key sense
|
||||
|
||||
// We have key sense - perform regular waiting
|
||||
!:
|
||||
jsr STOP
|
||||
bcs tape_break_error
|
||||
|
||||
lda CPU_R6510
|
||||
and #$10
|
||||
beq !-
|
||||
|
||||
tape_wait_first_pulse:
|
||||
|
||||
// We have no key sense - so just turn the motor on and wait for the first pulse
|
||||
|
||||
jsr tape_motor_on
|
||||
|
||||
!:
|
||||
jsr STOP
|
||||
bcs tape_break_error
|
||||
|
||||
lda #$10
|
||||
bit CIA1_ICR // $DC0D
|
||||
bne !-
|
||||
!:
|
||||
jsr STOP
|
||||
bcs tape_break_error
|
||||
|
||||
lda #$10
|
||||
bit CIA1_ICR // $DC0D
|
||||
beq !-
|
||||
|
||||
#endif
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_wait_play_done:
|
||||
|
||||
lda #$01
|
||||
sta CAS1 // set the interlock
|
||||
|
||||
#if CONFIG_TAPE_HEAD_ALIGN
|
||||
|
||||
rts
|
||||
|
||||
tape_prepare_reading:
|
||||
|
||||
#endif // CONFIG_TAPE_HEAD_ALIGN
|
||||
|
||||
#if CONFIG_MB_MEGA_65
|
||||
|
||||
// Display confirmation
|
||||
|
||||
ldx #__MSG_KERNAL_OK_SEARCHING
|
||||
jsr print_kernal_message
|
||||
|
||||
#endif
|
||||
|
||||
// Prepare for reading
|
||||
|
||||
jsr print_return
|
||||
jmp tape_screen_off_motor_on
|
||||
|
||||
|
||||
//
|
||||
// Handle file header - display it, decide whether load the file or not, etc.
|
||||
//
|
||||
|
||||
tape_handle_header:
|
||||
|
||||
#if !CONFIG_TAPE_NO_MOTOR_CONTROL
|
||||
|
||||
jsr tape_screen_on_motor_off
|
||||
|
||||
#endif
|
||||
|
||||
// Print FOUND + file name
|
||||
|
||||
ldx #__MSG_KERNAL_FOUND
|
||||
jsr print_kernal_message
|
||||
|
||||
ldy #$05
|
||||
!:
|
||||
lda (TAPE1), y
|
||||
jsr JCHROUT
|
||||
iny
|
||||
cpy #$15
|
||||
bne !-
|
||||
|
||||
#if !CONFIG_TAPE_NO_MOTOR_CONTROL
|
||||
|
||||
// Header, wait for user decision
|
||||
|
||||
jsr tape_header_get_decision
|
||||
bcs tape_break_error
|
||||
|
||||
#endif
|
||||
|
||||
// Check if file name matches
|
||||
|
||||
jsr tape_match_filename
|
||||
bcs tape_handle_header_skip
|
||||
|
||||
// Setup STAL and EAL
|
||||
|
||||
ldy #$01
|
||||
lda (TAPE1), y
|
||||
sta STAL+0
|
||||
|
||||
iny
|
||||
lda (TAPE1), y
|
||||
sta STAL+1
|
||||
|
||||
iny
|
||||
lda (TAPE1), y
|
||||
sta EAL+0
|
||||
|
||||
iny
|
||||
lda (TAPE1), y
|
||||
sta EAL+1
|
||||
|
||||
// Handle the secondary address, 0 means loading to location from MEMUSS
|
||||
|
||||
lda SA
|
||||
bne !+
|
||||
|
||||
// EAL = EAL - STAL
|
||||
|
||||
sec
|
||||
lda EAL+0
|
||||
sbc STAL+0
|
||||
sta EAL+0
|
||||
lda EAL+1
|
||||
sbc STAL+1
|
||||
sta EAL+1
|
||||
|
||||
// STAL = MEMUSS
|
||||
|
||||
lda MEMUSS+0
|
||||
sta STAL+0
|
||||
lda MEMUSS+1
|
||||
sta STAL+1
|
||||
|
||||
// EAL = EAL + STAL
|
||||
|
||||
clc
|
||||
lda EAL+0
|
||||
adc STAL+0
|
||||
sta EAL+0
|
||||
lda EAL+1
|
||||
adc STAL+1
|
||||
sta EAL+1
|
||||
!:
|
||||
// Setup MEMUSS (see Mapping the C64, page 36)
|
||||
|
||||
jsr lvs_STAL_to_MEMUSS
|
||||
|
||||
// Print LOADING and start address
|
||||
|
||||
jsr lvs_display_loading_verifying
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
#if !CONFIG_TAPE_NO_MOTOR_CONTROL
|
||||
|
||||
tape_handle_header_displayed:
|
||||
|
||||
// Load the file
|
||||
|
||||
jsr tape_screen_off_motor_on
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
#endif
|
||||
|
||||
tape_return_ok:
|
||||
|
||||
clc
|
||||
rts
|
||||
|
||||
tape_handle_header_skip:
|
||||
|
||||
// Skip this file
|
||||
|
||||
jsr print_return
|
||||
jsr tape_screen_off_motor_on
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_return_not_ok:
|
||||
|
||||
sec
|
||||
rts
|
||||
|
||||
|
||||
//
|
||||
// Check whether file name matches the pattern
|
||||
//
|
||||
|
||||
tape_match_filename:
|
||||
|
||||
lda FNLEN
|
||||
beq tape_return_ok // no pattern to match
|
||||
|
||||
ldy #$00
|
||||
|
||||
tape_match_loop:
|
||||
|
||||
lda #$20 // default byte, for padding
|
||||
cpy FNLEN
|
||||
bcs !+ // end of pattern
|
||||
lda (FNADDR), y // byte from pattern
|
||||
!:
|
||||
cmp #KEY_ASTERISK
|
||||
beq tape_return_ok
|
||||
|
||||
cmp (TAPE1), y
|
||||
bne tape_return_not_ok
|
||||
|
||||
iny
|
||||
cpy #$10
|
||||
bne tape_match_loop
|
||||
|
||||
clc
|
||||
rts
|
||||
|
||||
|
||||
#if !CONFIG_TAPE_NO_MOTOR_CONTROL
|
||||
|
||||
//
|
||||
// Get user decision whether to load the file or not
|
||||
//
|
||||
|
||||
tape_header_get_decision:
|
||||
|
||||
ldy #$00
|
||||
!:
|
||||
jsr udtim_keyboard
|
||||
lda STKEY
|
||||
bpl tape_header_wait_stop // STOP pressed
|
||||
and #$10
|
||||
beq tape_header_wait_space // SPACE pressed
|
||||
|
||||
ldx #$80
|
||||
jsr wait_x_bars // sets .X to 0
|
||||
dex
|
||||
jsr wait_x_bars
|
||||
|
||||
dey
|
||||
bne !-
|
||||
|
||||
// FALLTROUGH - timeout
|
||||
|
||||
tape_header_wait_space:
|
||||
|
||||
clc
|
||||
rts
|
||||
|
||||
tape_header_wait_stop:
|
||||
|
||||
sec
|
||||
rts
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// Report that file loading succeeded (or not)
|
||||
//
|
||||
|
||||
tape_load_success:
|
||||
|
||||
jsr tape_screen_on_motor_off
|
||||
jsr lvs_display_done
|
||||
jmp lvs_return_last_address
|
||||
|
||||
tape_load_error:
|
||||
|
||||
jsr tape_screen_on_motor_off
|
||||
jmp lvs_load_verify_error
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,102 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Tries to detect
|
||||
//
|
||||
// Carry clear - normal, Carry set - turbo
|
||||
//
|
||||
|
||||
#if CONFIG_TAPE_AUTODETECT
|
||||
|
||||
|
||||
tape_common_autodetect:
|
||||
|
||||
// Set screen color to something neutral, silence the audio
|
||||
lda #$0B
|
||||
sta VIC_EXTCOL
|
||||
lda #$00
|
||||
#if CONFIG_MB_MEGA_65
|
||||
sta SID_SIGVOL + __SID_R1_OFFSET
|
||||
sta SID_SIGVOL + __SID_L1_OFFSET
|
||||
#else
|
||||
sta SID_SIGVOL
|
||||
#endif
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_common_autodetect_retry:
|
||||
|
||||
// It is not trivial to distinguish between normal and turbo,
|
||||
// as short pulses of normal (and sync uses only shorts)
|
||||
// have similar lengths as long pulses of turbo
|
||||
|
||||
// Thus, the routine here reads certain amount of pulses
|
||||
// looking for evidence for either normal or turbo system;
|
||||
// in case of no evidence found, assume normal
|
||||
|
||||
lda #$00 // plus = probably normal, minus = turbo
|
||||
sta XSAV
|
||||
|
||||
ldy #$60 // $60 pulses cover 12 bytes of turbo recording
|
||||
jsr tape_common_get_pulse // first pulse might be a garbage, ignore it
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_common_autodetect_loop:
|
||||
|
||||
jsr tape_common_get_pulse // read pulse for detection attempt
|
||||
|
||||
// If garbage found, retry detection
|
||||
cmp #$28
|
||||
bcc tape_common_autodetect_retry // this is a VERY long pulse
|
||||
cmp #$E8
|
||||
bcs tape_common_autodetect_retry // this is a VERY short pulse
|
||||
|
||||
// First try to distinguish turbo short signal (reference: $CD)
|
||||
// from normal signals (reference: $A5 or lower), these values
|
||||
// give us threshold of ($CD + $A5) / 2 = $B9
|
||||
|
||||
cmp #$B9
|
||||
bcc !+
|
||||
dec XSAV // above $B9 (so signal is shorter), looks like turbo
|
||||
!:
|
||||
// Now try to distinguish turbo signals (reference: $B1 or higher)
|
||||
// from normal medium/long signals (reference: $7D or below), these values
|
||||
// give us threshold of ($B1 + $7D) / 2 = $97
|
||||
|
||||
cmp #$97
|
||||
bcs !+
|
||||
inc XSAV
|
||||
!:
|
||||
// The sync for turbo is not too long - if we have enough evidence,
|
||||
// assume turbo recording already
|
||||
|
||||
lda XSAV
|
||||
cmp #$FD
|
||||
beq tape_common_autodetect_turbo
|
||||
|
||||
// Next iteration
|
||||
dey
|
||||
bpl tape_common_autodetect_loop
|
||||
|
||||
// Last chance for turbo
|
||||
|
||||
lda XSAV
|
||||
bmi tape_common_autodetect_turbo
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_common_autodetect_normal:
|
||||
|
||||
clc
|
||||
rts
|
||||
|
||||
tape_common_autodetect_turbo:
|
||||
|
||||
sec
|
||||
rts
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,40 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Clear the SID settings - for sound effects during LOAD
|
||||
//
|
||||
|
||||
|
||||
#if CONFIG_TAPE_TURBO
|
||||
|
||||
|
||||
tape_clean_sid:
|
||||
|
||||
lda #$00
|
||||
ldy #$1C
|
||||
!:
|
||||
|
||||
#if CONFIG_MB_MEGA_65
|
||||
|
||||
// It should be safer than cleaning whole $D400-D47C range
|
||||
|
||||
sta __SID_BASE + __SID_R1_OFFSET, y
|
||||
sta __SID_BASE + __SID_R2_OFFSET, y
|
||||
sta __SID_BASE + __SID_L1_OFFSET, y
|
||||
sta __SID_BASE + __SID_L2_OFFSET, y
|
||||
|
||||
#else
|
||||
|
||||
sta __SID_BASE, y
|
||||
|
||||
#endif
|
||||
|
||||
dey
|
||||
bpl !-
|
||||
|
||||
rts
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,24 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Check if VERIFY asked - if yes, terminate loading
|
||||
//
|
||||
|
||||
|
||||
#if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO
|
||||
|
||||
|
||||
tape_ditch_verify:
|
||||
|
||||
lda VERCKK
|
||||
bne !+
|
||||
rts
|
||||
!:
|
||||
pla
|
||||
pla
|
||||
jmp lvs_device_not_found_error
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,33 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Tape helper routine - pulse reading
|
||||
//
|
||||
// Returns pulse length (with a bias, see comments) in .A
|
||||
//
|
||||
|
||||
|
||||
#if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO
|
||||
|
||||
|
||||
tape_common_get_pulse:
|
||||
|
||||
// Contrary to original ROM implementation we do not use interrupts
|
||||
// (see http://unusedino.de/ec64/technical/formats/tap.html) - busy wait
|
||||
// implementation is probably just shorter
|
||||
|
||||
lda #$10
|
||||
!:
|
||||
bit CIA1_ICR // $DC0D
|
||||
beq !- // busy loop to detect signal, restart timer afterwards
|
||||
lda CIA2_TIMBLO // $DD06
|
||||
ldx #%01010001 // start timer, force latch reload, count timer A underflows
|
||||
stx CIA2_CRB // $DD0F
|
||||
|
||||
cmp __pulse_threshold // default pulse check
|
||||
rts
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# * KERNAL_0 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Handle tape deck motor
|
||||
//
|
||||
|
||||
|
||||
#if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO
|
||||
|
||||
|
||||
tape_motor_off:
|
||||
|
||||
lda CPU_R6510
|
||||
ora #$20
|
||||
bne !+ // branch always
|
||||
|
||||
tape_motor_on:
|
||||
|
||||
lda CPU_R6510
|
||||
and #($FF - $20)
|
||||
!:
|
||||
sta CPU_R6510
|
||||
rts
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,65 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Prepare CIA timers for tape reading
|
||||
//
|
||||
|
||||
//
|
||||
// Checked under VICE, PAL, average of 256 pulses:
|
||||
//
|
||||
// normal - short - timer goes down to $A5
|
||||
// normal - medium - timer goes down to $7D
|
||||
// normal - long - timer goes down to $52
|
||||
//
|
||||
// turbo - short - timer goes down to $CD
|
||||
// turbo - long - timer goes down to $B1
|
||||
//
|
||||
//
|
||||
// Measurement subroutine: .A should contain timer value, $C000-$C002 zeroed
|
||||
//
|
||||
// clc
|
||||
// adc $C001
|
||||
// sta $C001
|
||||
// bcc !+
|
||||
// inc $C000
|
||||
// !:
|
||||
// inc $C002
|
||||
// beq !+
|
||||
// rts
|
||||
// !:
|
||||
// lda $C000
|
||||
// .break // .A contains our average
|
||||
// rts
|
||||
//
|
||||
|
||||
#if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO
|
||||
|
||||
|
||||
tape_common_prepare_cia:
|
||||
|
||||
// Setup CIA #2 timers
|
||||
|
||||
ldx #$03 // set timer A to 4 ticks
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_common_prepare_cia_by_x: // entry point for head align tool
|
||||
|
||||
stx CIA2_TIMALO // $DD04
|
||||
ldx #$00
|
||||
stx CIA2_TIMAHI // $DD05
|
||||
|
||||
stx CIA2_TIMBHI // $DD07
|
||||
dex // puts $FF - for running timer B as long as possible
|
||||
stx CIA2_TIMBLO // $DD06
|
||||
|
||||
// Let timer A run continuously
|
||||
|
||||
ldx #%00010001 // start timer, force latch reload
|
||||
stx CIA2_CRA // $DD0E
|
||||
|
||||
rts
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,72 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Handle screen (visible/blanked) + tape deck motor (on/off),
|
||||
// store/restore screen color
|
||||
//
|
||||
|
||||
|
||||
#if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO
|
||||
|
||||
|
||||
// XXX for Mega65 do not disable screen, just disable badline emulation
|
||||
|
||||
|
||||
tape_screen_on_motor_off:
|
||||
|
||||
jsr tape_motor_off
|
||||
|
||||
lda COLSTORE
|
||||
sta VIC_EXTCOL
|
||||
|
||||
#if !CONFIG_MB_MEGA_65
|
||||
|
||||
jmp screen_on
|
||||
|
||||
#else
|
||||
|
||||
// On Mega65 just reenable badline emulation
|
||||
|
||||
lda #$FF
|
||||
sta M65_BADL_SLI
|
||||
sta VIC_KEY
|
||||
|
||||
rts
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
tape_screen_off_motor_on:
|
||||
|
||||
// We do not want interrupts and CHROUT reenables them
|
||||
sei
|
||||
|
||||
// Clear keyboard buffer
|
||||
lda #$00
|
||||
sta NDX
|
||||
|
||||
// Set screen color
|
||||
lda VIC_EXTCOL
|
||||
sta COLSTORE
|
||||
|
||||
#if !CONFIG_MB_MEGA_65
|
||||
|
||||
jsr screen_off
|
||||
|
||||
#else
|
||||
|
||||
// On Mega65 we do not have to turn the screen off;
|
||||
// it is enough to disable badline emulation
|
||||
|
||||
jsr mega65_unhide
|
||||
lda #$00
|
||||
sta M65_BADL_SLI
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
jmp tape_motor_on
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,267 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Tape head alignemnt tool
|
||||
//
|
||||
|
||||
|
||||
#if CONFIG_TAPE_HEAD_ALIGN
|
||||
|
||||
|
||||
.label __ha_start = 12 // starting row of the chart
|
||||
.label __ha_rows = 11 // number of rows for scrolling
|
||||
|
||||
// Helper tables
|
||||
|
||||
.label __ha_offsets = $1000;
|
||||
.label __ha_masks = $1100;
|
||||
|
||||
// Generated code location
|
||||
|
||||
.label __ha_scroll = $1300;
|
||||
|
||||
// Flag for GFX effects - reuse BASIC numeric work area on zero page
|
||||
|
||||
.label __ha_gfxflag = TEMPF2; // 1 byte
|
||||
|
||||
|
||||
tape_head_align:
|
||||
|
||||
// Make sure user really wants to launch the tool
|
||||
|
||||
jsr tape_ask_play
|
||||
|
||||
// Disable interrupts, set proper I/O values
|
||||
|
||||
jsr CLALL
|
||||
|
||||
sei
|
||||
|
||||
jsr IOINIT
|
||||
// jsr CINT
|
||||
|
||||
jsr nmi_lock
|
||||
|
||||
// Prepare CIA timers
|
||||
|
||||
ldx #$02 // set timer A to 3 ticks
|
||||
jsr tape_common_prepare_cia_by_x
|
||||
|
||||
ldx #$FF // timer to control scroll speed
|
||||
stx CIA1_TIMBLO // $DC06
|
||||
stx CIA1_TIMBHI // $DC07
|
||||
|
||||
jsr tape_motor_on
|
||||
|
||||
// Clear color data ($0800)
|
||||
|
||||
ldy #$00
|
||||
!:
|
||||
lda #(CONFIG_COLOR_TXT * $10 + CONFIG_COLOR_BG)
|
||||
|
||||
sta $0800, y
|
||||
sta $0900, y
|
||||
sta $0A00, y
|
||||
sta $0B00, y
|
||||
|
||||
iny
|
||||
bne !-
|
||||
|
||||
// Clear bitmap data ($2000)
|
||||
|
||||
lda #$20
|
||||
sta SAL+1
|
||||
tya // put 0 to .A
|
||||
sta SAL+0
|
||||
!:
|
||||
sta (SAL), y
|
||||
iny
|
||||
bne !-
|
||||
|
||||
inc SAL+1
|
||||
ldx SAL+1
|
||||
cpx #$40
|
||||
bne !-
|
||||
|
||||
// Print help message
|
||||
|
||||
jsr tape_head_align_print_help
|
||||
|
||||
// Make sure the row where the chart is being created is not visible
|
||||
|
||||
lda #(CONFIG_COLOR_TXT * $10 + CONFIG_COLOR_TXT)
|
||||
ldy #$24
|
||||
!:
|
||||
sta $0800 + __ha_start * 40 + 1, y
|
||||
sta $0800 + __ha_start * 40 + 1 + (__ha_rows + 1) * 40, y
|
||||
|
||||
dey
|
||||
bne !-
|
||||
|
||||
// Set graphics mode
|
||||
|
||||
lda #$28 // graphics start at $2000, color at $0800
|
||||
sta VIC_YMCSB
|
||||
|
||||
lda #$3B // set bit 5 to enable graphic mode
|
||||
sta VIC_SCROLY
|
||||
|
||||
// Prepare lookup tables - to speed drawing, we are going to use two of them:
|
||||
// - byte offset table will tell us which byte in memory to alter
|
||||
// - mask will allow us to quickly put the pixel
|
||||
|
||||
ldx #$00 // loop index
|
||||
ldy #$00 // temporary value for mask calculation
|
||||
!:
|
||||
// Byte offset is simple, just zero the 3 least significant bits
|
||||
|
||||
txa
|
||||
and #%11111000
|
||||
sta __ha_offsets, x
|
||||
|
||||
// Mask changes with each iteration, use our temporary value in .Y
|
||||
|
||||
tya
|
||||
clc
|
||||
ror
|
||||
bne !+
|
||||
lda #%10000000
|
||||
!:
|
||||
tay
|
||||
sta __ha_masks, x
|
||||
|
||||
// Next iteration
|
||||
|
||||
inx
|
||||
bne !--
|
||||
|
||||
// Initialize flag for additional GFX effects
|
||||
|
||||
stx __ha_gfxflag // .X is 0 at this moment
|
||||
|
||||
// Generate helper code for screen scrolling
|
||||
|
||||
jsr tape_head_align_gen_code
|
||||
|
||||
// Provide new IRQ routine address
|
||||
|
||||
lda #<tape_head_align_irq
|
||||
sta CINV+0
|
||||
lda #>tape_head_align_irq
|
||||
sta CINV+1
|
||||
|
||||
// Setup raster interrupt routine - see https://www.c64-wiki.com/wiki/Raster_interrupt
|
||||
|
||||
lda #%01111111 // prevent CIA from generating interrupts
|
||||
sta CIA1_ICR // $DC0D
|
||||
|
||||
and VIC_SCROLY // clear the highest bit of RASTER
|
||||
sta VIC_SCROLY // $D011
|
||||
|
||||
lda #$FB // we want no badlines during the interrupt, this raster is 100% safe
|
||||
sta VIC_RASTER
|
||||
|
||||
lda #%00000001 // enable raster interrupts
|
||||
sta VIC_IRQMSK // $D01A
|
||||
cli
|
||||
|
||||
tape_head_align_loop_1:
|
||||
|
||||
// Check for STOP key
|
||||
|
||||
jsr udtim_keyboard
|
||||
jsr STOP
|
||||
bcs tape_head_align_quit
|
||||
|
||||
// Launch the timer
|
||||
|
||||
ldx #%00011001 // start timer, one-shot force latch reload, count system ticks
|
||||
stx CIA1_CRB // $DC0F
|
||||
|
||||
// Scroll the whole chart one line down
|
||||
|
||||
ldx #$00
|
||||
!:
|
||||
jsr __ha_scroll // scroll one column down, using fast generated code
|
||||
|
||||
txa
|
||||
clc
|
||||
adc #$08
|
||||
tax
|
||||
bne !-
|
||||
|
||||
// Draw decorations
|
||||
|
||||
lda __ha_gfxflag
|
||||
inc __ha_gfxflag
|
||||
clc
|
||||
adc #$08
|
||||
and #%00001100
|
||||
bne !+
|
||||
ldy #%11110001
|
||||
lda #%10001111
|
||||
bne !++
|
||||
!:
|
||||
ldy #%00000001
|
||||
lda #%10000000
|
||||
!:
|
||||
ora __ha_chart + 7 + 8 * 0
|
||||
sta __ha_chart + 7 + 8 * 0
|
||||
|
||||
tya
|
||||
ora __ha_chart + 7 + 8 * 31
|
||||
sta __ha_chart + 7 + 8 * 31
|
||||
|
||||
// Draw helper lines
|
||||
|
||||
lda __ha_gfxflag
|
||||
and #%00000010
|
||||
beq !+
|
||||
|
||||
// For 'normal'
|
||||
|
||||
lda #%00000001
|
||||
ora __ha_chart + 7 + 8 * 6
|
||||
sta __ha_chart + 7 + 8 * 6
|
||||
|
||||
lda #%00000001
|
||||
ora __ha_chart + 7 + 8 * 13
|
||||
sta __ha_chart + 7 + 8 * 13
|
||||
|
||||
// For 'turbo'
|
||||
|
||||
lda #%00010000
|
||||
ora __ha_chart + 7 + 8 * 21
|
||||
sta __ha_chart + 7 + 8 * 21
|
||||
!:
|
||||
// FALLTROUGH
|
||||
|
||||
tape_head_align_loop_2:
|
||||
|
||||
lda CIA1_TIMBLO
|
||||
and CIA1_TIMBHI
|
||||
eor #$FF
|
||||
|
||||
bne tape_head_align_loop_2
|
||||
beq tape_head_align_loop_1
|
||||
|
||||
|
||||
tape_head_align_quit:
|
||||
|
||||
// It makes no sense to return to system, as we already destroyed
|
||||
// a lot of memory; fust clear initial BASIC text area to prevent
|
||||
// data recovery attempts, and reset
|
||||
|
||||
ldx #$00
|
||||
txa
|
||||
!:
|
||||
sta $0800, x
|
||||
inx
|
||||
bne !-
|
||||
|
||||
jmp hw_entry_reset
|
||||
|
||||
|
||||
#endif // CONFIG_TAPE_HEAD_ALIGN
|
||||
@@ -0,0 +1,138 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Tape head alignemnt tool - helper code generator
|
||||
//
|
||||
|
||||
|
||||
#if CONFIG_TAPE_HEAD_ALIGN
|
||||
|
||||
|
||||
// Helper variables - reuse BASIC numeric work area on zero page
|
||||
|
||||
.label __ha_lda_addr = TEMPF1 + 0; // 2 bytes, for code generator
|
||||
.label __ha_sta_addr = TEMPF1 + 2; // 2 bytes, for code generator
|
||||
|
||||
|
||||
tape_head_align_gen_code:
|
||||
|
||||
// Setup generated code start address
|
||||
|
||||
lda #<__ha_scroll
|
||||
sta SAL+0
|
||||
lda #>__ha_scroll
|
||||
sta SAL+1
|
||||
|
||||
// Setup initial source and destination addresses
|
||||
|
||||
ldy #<(__ha_chart + __ha_rows * (8 * 40) + 6)
|
||||
sty __ha_lda_addr + 0
|
||||
iny
|
||||
sty __ha_sta_addr + 0
|
||||
|
||||
ldy #>(__ha_chart + __ha_rows * (8 * 40) + 6)
|
||||
sty __ha_lda_addr + 1
|
||||
sty __ha_sta_addr + 1
|
||||
|
||||
// Emit code to move 7 rows of one 8x8 cell
|
||||
!:
|
||||
ldx #$07
|
||||
!:
|
||||
jsr tape_head_align_gen_code_emit_pair
|
||||
|
||||
dec __ha_lda_addr + 0
|
||||
dec __ha_sta_addr + 0
|
||||
|
||||
dex
|
||||
bne !-
|
||||
|
||||
// Emit code to fetch a top row from the cell above
|
||||
|
||||
inc __ha_lda_addr + 0
|
||||
sec
|
||||
lda __ha_lda_addr + 0
|
||||
sbc #<(8 * 40 - 7)
|
||||
sta __ha_lda_addr + 0
|
||||
lda __ha_lda_addr + 1
|
||||
sbc #>(8 * 40 - 7)
|
||||
|
||||
sta __ha_lda_addr + 1
|
||||
|
||||
jsr tape_head_align_gen_code_emit_pair
|
||||
|
||||
// Prepare addresses for the next iteration
|
||||
|
||||
lda __ha_lda_addr + 0
|
||||
sta __ha_sta_addr + 0
|
||||
lda __ha_lda_addr + 1
|
||||
sta __ha_sta_addr + 1
|
||||
|
||||
dec __ha_lda_addr + 0
|
||||
|
||||
// Now, new iteration - if needed
|
||||
|
||||
lda __ha_sta_addr + 0
|
||||
cmp #<(__ha_chart + 7)
|
||||
bne !--
|
||||
lda __ha_sta_addr + 1
|
||||
cmp #>(__ha_chart + 7)
|
||||
bne !--
|
||||
|
||||
// Last pair to be generated starts from LDA #$00
|
||||
|
||||
lda #$A9
|
||||
jsr tape_head_align_gen_code_emit_byte
|
||||
lda #$00
|
||||
jsr tape_head_align_gen_code_emit_byte
|
||||
|
||||
jsr tape_head_align_gen_code_emit_sta
|
||||
|
||||
// Emit RTS and quit
|
||||
|
||||
lda #$60
|
||||
jmp tape_head_align_gen_code_emit_byte
|
||||
|
||||
|
||||
|
||||
tape_head_align_gen_code_emit_pair:
|
||||
|
||||
lda #$BD // LDA absolute, x
|
||||
jsr tape_head_align_gen_code_emit_byte
|
||||
|
||||
lda __ha_lda_addr + 0
|
||||
jsr tape_head_align_gen_code_emit_byte
|
||||
lda __ha_lda_addr + 1
|
||||
jsr tape_head_align_gen_code_emit_byte
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_head_align_gen_code_emit_sta:
|
||||
|
||||
lda #$9D // STA absolute, x
|
||||
jsr tape_head_align_gen_code_emit_byte
|
||||
|
||||
lda __ha_sta_addr + 0
|
||||
jsr tape_head_align_gen_code_emit_byte
|
||||
lda __ha_sta_addr + 1
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_head_align_gen_code_emit_byte:
|
||||
|
||||
ldy #$00
|
||||
sta (SAL), y
|
||||
#if HAS_OPCODES_65CE02
|
||||
inw SAL
|
||||
#else
|
||||
inc SAL+0
|
||||
bne !+
|
||||
inc SAL+1
|
||||
!:
|
||||
#endif
|
||||
|
||||
rts
|
||||
|
||||
|
||||
#endif // CONFIG_TAPE_HEAD_ALIGN
|
||||
@@ -0,0 +1,45 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Tape head alignemnt tool - reading pulses from tape
|
||||
//
|
||||
|
||||
|
||||
#if CONFIG_TAPE_HEAD_ALIGN
|
||||
|
||||
|
||||
tape_head_align_get_pulse:
|
||||
|
||||
// This routine differs from the one used to read pulse during tape reading:
|
||||
// - it is not as precise
|
||||
// - it terminates when timer reaches $FF
|
||||
// - it returns value in .Y
|
||||
|
||||
lda #$10
|
||||
!:
|
||||
// Loop to detect signal
|
||||
|
||||
ldy CIA2_TIMBLO // $DD06
|
||||
bit CIA1_ICR // $DC0D
|
||||
bne !+
|
||||
|
||||
cpy #$FF
|
||||
bne !-
|
||||
!:
|
||||
// FALLTROUGH
|
||||
|
||||
tape_head_align_get_pulse_start_timer:
|
||||
|
||||
// Start timer again, force latch reload, count timer A underflows
|
||||
|
||||
lda #%01010001
|
||||
sta CIA2_CRB // $DD0F
|
||||
|
||||
// Return with time elapsed in .Y
|
||||
|
||||
rts
|
||||
|
||||
|
||||
#endif // CONFIG_TAPE_HEAD_ALIGN
|
||||
@@ -0,0 +1,147 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Tape head alignemnt tool - prints out a help message on screen
|
||||
//
|
||||
|
||||
|
||||
#if CONFIG_TAPE_HEAD_ALIGN
|
||||
|
||||
|
||||
// Helper variable - reuse BASIC numeric work area on zero page
|
||||
|
||||
.label __ha_storage = TEMPF1; // 1 byte
|
||||
|
||||
|
||||
tape_head_align_print_help:
|
||||
|
||||
// Make screen font visible
|
||||
|
||||
lda CPU_R6510
|
||||
pha
|
||||
and #%11111011
|
||||
sta CPU_R6510
|
||||
|
||||
// Print help message
|
||||
|
||||
ldy #$00
|
||||
|
||||
// Retrieve address
|
||||
!:
|
||||
lda tape_head_align_help_text, y
|
||||
iny
|
||||
cmp #$FF
|
||||
beq tape_head_align_print_end
|
||||
sta EAL+0
|
||||
|
||||
lda tape_head_align_help_text, y
|
||||
iny
|
||||
sta EAL+1
|
||||
!:
|
||||
// Retrieve and print character
|
||||
|
||||
lda tape_head_align_help_text, y
|
||||
iny
|
||||
cmp #$FF
|
||||
beq !--
|
||||
|
||||
sty __ha_storage
|
||||
jsr tape_head_align_print_char
|
||||
ldy __ha_storage
|
||||
|
||||
bne !- // branch alwats
|
||||
|
||||
|
||||
tape_head_align_print_end:
|
||||
|
||||
// Restore normal memory configuration and quit
|
||||
|
||||
pla
|
||||
sta CPU_R6510
|
||||
rts
|
||||
|
||||
tape_head_align_print_string:
|
||||
|
||||
|
||||
|
||||
tape_head_align_print_char:
|
||||
|
||||
// Calculate start address of character in .A
|
||||
|
||||
sta SAL+0
|
||||
lda #$00
|
||||
sta SAL+1
|
||||
|
||||
asl SAL+0
|
||||
rol SAL+1
|
||||
asl SAL+0
|
||||
rol SAL+1
|
||||
asl SAL+0
|
||||
rol SAL+1
|
||||
|
||||
clc
|
||||
lda SAL+1
|
||||
adc #$D0
|
||||
sta SAL+1
|
||||
|
||||
// Print out the character
|
||||
|
||||
ldy #$07
|
||||
!:
|
||||
lda (SAL), y
|
||||
sta (EAL), y
|
||||
dey
|
||||
bpl !-
|
||||
|
||||
// Prepare EAL for the next character
|
||||
|
||||
lda EAL+0
|
||||
clc
|
||||
adc #$08
|
||||
sta EAL+0
|
||||
bne !+
|
||||
inc EAL+1
|
||||
!:
|
||||
rts
|
||||
|
||||
|
||||
//
|
||||
// Strings to print
|
||||
//
|
||||
|
||||
.encoding "screencode_upper"
|
||||
|
||||
|
||||
tape_head_align_help_text:
|
||||
|
||||
// Each string consists of:
|
||||
// - destination (start byte) address
|
||||
// - text in screencodes
|
||||
// - $FF to mark end
|
||||
|
||||
.word $2000 + (40 * 8) * 0 + 8 * 1
|
||||
.text "COMPUTER HAS TO TELL THE SIGNALS APART"
|
||||
.byte $FF
|
||||
|
||||
.word $2000 + (40 * 8) * 3 + 8 * 6
|
||||
.text "ALIGN HEAD FOR MINIMUM NOISE"
|
||||
.byte $FF
|
||||
|
||||
.word $2000 + (40 * 8) * 6 + 8 * 2
|
||||
.text "IF THE DECK HAS A PITCH (TAPE SPEED)"
|
||||
.byte $FF
|
||||
|
||||
.word $2000 + (40 * 8) * 7 + 8 * 1
|
||||
.text "CONTROL, TWEAK IT SO THAT DOTTED LINES"
|
||||
.byte $FF
|
||||
|
||||
.word $2000 + (40 * 8) * 8 + 8 * 5
|
||||
.text "ARE HALF A WAY BETWEEN SIGNALS"
|
||||
.byte $FF
|
||||
|
||||
.byte $FF // end of strings
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,75 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Tape head alignemnt tool - interrupt routine
|
||||
//
|
||||
|
||||
|
||||
#if CONFIG_TAPE_HEAD_ALIGN
|
||||
|
||||
|
||||
tape_head_align_irq:
|
||||
|
||||
// Acknowledge interrupt
|
||||
|
||||
asl VIC_IRQ
|
||||
|
||||
// Ignore 2 first pulses, they can be garbage
|
||||
|
||||
jsr tape_head_align_get_pulse
|
||||
jsr tape_head_align_get_pulse
|
||||
|
||||
// Now, we can retrieve pulses for the chart
|
||||
|
||||
ldx #$00
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_head_align_irq_loop:
|
||||
|
||||
jsr tape_head_align_get_pulse
|
||||
|
||||
// If we approached badlines again - we cannot use this measurement anymore
|
||||
|
||||
lda VIC_SCROLY
|
||||
bmi !+ // branch if lower border
|
||||
|
||||
lda VIC_RASTER
|
||||
cmp #$33 // first line where badline can occur
|
||||
bcs tape_head_align_irq_end
|
||||
!:
|
||||
// Draw pulse on the screen
|
||||
|
||||
cpy #$FF
|
||||
beq !+
|
||||
|
||||
// Center the chart horizontaly, with some margin from top
|
||||
|
||||
.label __ha_chart = $2000 + 8 * (40 * __ha_start + 4)
|
||||
|
||||
phx_trash_a
|
||||
|
||||
lda __ha_offsets, y
|
||||
tax
|
||||
lda __ha_masks, y
|
||||
ora __ha_chart + 7, x
|
||||
sta __ha_chart + 7, x
|
||||
|
||||
plx_trash_a
|
||||
!:
|
||||
// Next iteration
|
||||
|
||||
inx
|
||||
cpx #$40
|
||||
bne tape_head_align_irq_loop
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_head_align_irq_end:
|
||||
|
||||
jmp return_from_interrupt
|
||||
|
||||
|
||||
#endif // CONFIG_TAPE_HEAD_ALIGN
|
||||
@@ -0,0 +1,126 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Tape (normal) helper routine - reading speed calibration
|
||||
//
|
||||
// Needs pulse length in .A
|
||||
//
|
||||
|
||||
|
||||
#if CONFIG_TAPE_NORMAL
|
||||
|
||||
|
||||
tape_normal_calibrate_during_pilot: // reecalibration during the pilot
|
||||
|
||||
sta __normal_time_S
|
||||
|
||||
// We do not have any recent medium pulse measurement,
|
||||
// probably the only solution is to estimate it
|
||||
|
||||
lda #$FF
|
||||
sec
|
||||
sbc __normal_time_S
|
||||
|
||||
// We now have a difference from the starting point ($FF)
|
||||
|
||||
clc
|
||||
ror
|
||||
sta __normal_time_M // this is temporary only!
|
||||
|
||||
// We now have half the difference, substract it from
|
||||
// short pulse measurement result
|
||||
|
||||
lda __normal_time_S
|
||||
sec
|
||||
sbc __normal_time_M
|
||||
|
||||
// Add a small correction to gain $7D if starting from $A5. Dirty, ugly,
|
||||
// and imprecise hack - but in real life should be good enough
|
||||
|
||||
clc
|
||||
adc #$05
|
||||
sta __normal_time_M // estimated medium pulse length
|
||||
|
||||
jmp tape_normal_calibrate_common
|
||||
|
||||
|
||||
|
||||
tape_normal_calibrate_after_S: // recalibration after short pulse
|
||||
|
||||
sta __normal_time_S
|
||||
rts
|
||||
skip_2_bytes_trash_nvz
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_normal_calibrate_after_M: // recalibration after medium pulse
|
||||
|
||||
sta __normal_time_M
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_normal_calibrate_common:
|
||||
|
||||
// Now compare results with current threshold
|
||||
|
||||
lda __normal_time_S
|
||||
sec
|
||||
sbc __pulse_threshold
|
||||
clc
|
||||
adc __normal_time_M
|
||||
|
||||
cmp __pulse_threshold
|
||||
|
||||
beq tape_normal_calibrate_done // branch if no recalibration needed
|
||||
|
||||
// Correct the thresholds (default is $91 for the S/M one)
|
||||
|
||||
bcs tape_normal_calibrate_threshold_inc // branch if .A >= memory
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
|
||||
tape_normal_calibrate_threshold_dec:
|
||||
|
||||
lda __pulse_threshold
|
||||
cmp #($91-10)
|
||||
bcc tape_normal_calibrate_done // do not decrement thresholds too far
|
||||
|
||||
sec
|
||||
sbc #$02
|
||||
sta __pulse_threshold
|
||||
|
||||
lda __pulse_threshold_ML
|
||||
sec
|
||||
sbc #$03
|
||||
sta __pulse_threshold_ML
|
||||
|
||||
bne tape_normal_calibrate_done // branch always
|
||||
|
||||
|
||||
tape_normal_calibrate_threshold_inc:
|
||||
|
||||
lda __pulse_threshold
|
||||
cmp #($91+11)
|
||||
bcs tape_normal_calibrate_done // do not increment thresholds too far
|
||||
|
||||
clc
|
||||
adc #$02
|
||||
sta __pulse_threshold
|
||||
|
||||
lda __pulse_threshold_ML
|
||||
clc
|
||||
adc #$03
|
||||
sta __pulse_threshold_ML
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
|
||||
tape_normal_calibrate_done:
|
||||
|
||||
rts
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,68 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Tape (normal) helper routine - bit reading
|
||||
//
|
||||
// Returns bit in Zero flag, Carry set means error, on 0 bit .A is 0 too
|
||||
//
|
||||
|
||||
|
||||
#if CONFIG_TAPE_NORMAL
|
||||
|
||||
|
||||
tape_normal_get_bit:
|
||||
|
||||
// Fetch the first pulse
|
||||
|
||||
jsr tape_common_get_pulse
|
||||
bcc tape_normal_get_bit_1
|
||||
|
||||
// First impulse was short, second should be medium
|
||||
|
||||
jsr tape_normal_calibrate_after_S
|
||||
|
||||
jsr tape_common_get_pulse
|
||||
bcs tape_normal_get_bit_error
|
||||
|
||||
jsr tape_normal_calibrate_after_M
|
||||
|
||||
// We have a bit '0'
|
||||
|
||||
lda #$00
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_normal_get_bit_done:
|
||||
|
||||
sta VIC_EXTCOL
|
||||
clc
|
||||
rts
|
||||
|
||||
|
||||
tape_normal_get_bit_1:
|
||||
|
||||
// First impulse was medium, second should be short
|
||||
|
||||
jsr tape_normal_calibrate_after_M
|
||||
|
||||
jsr tape_common_get_pulse
|
||||
bcc tape_normal_get_bit_error
|
||||
|
||||
jsr tape_normal_calibrate_after_S
|
||||
|
||||
// We have a bit '1'
|
||||
|
||||
clc
|
||||
lda #$06
|
||||
bne tape_normal_get_bit_done // branch always
|
||||
|
||||
|
||||
tape_normal_get_bit_error:
|
||||
|
||||
sec
|
||||
rts
|
||||
|
||||
|
||||
#endif // CONFIG_TAPE_NORMAL
|
||||
@@ -0,0 +1,73 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Tape (normal) helper routine - byte reading
|
||||
//
|
||||
// Returns byte in .A (also sotred in INBIT), Carry flag set = error
|
||||
//
|
||||
|
||||
|
||||
#if CONFIG_TAPE_NORMAL
|
||||
|
||||
|
||||
tape_normal_get_byte:
|
||||
|
||||
// Init parity bit and canary bit
|
||||
lda #$01
|
||||
sta PRTY
|
||||
lda #%01111111 // canary bit is 0
|
||||
sta INBIT
|
||||
|
||||
// Now fetch individual bits
|
||||
|
||||
tape_normal_get_byte_loop:
|
||||
|
||||
jsr tape_normal_get_bit
|
||||
bcs tape_normal_get_byte_error
|
||||
beq !+
|
||||
|
||||
// Handle parity bit
|
||||
lda #$01
|
||||
eor PRTY
|
||||
sta PRTY
|
||||
|
||||
sec
|
||||
!: // moved bit state from Zero to Carry flag
|
||||
|
||||
ror INBIT // put the bit in
|
||||
bcs tape_normal_get_byte_loop // loop if no canary bit reached
|
||||
|
||||
// Byte retrieved (on stack), now we need to validate the parity
|
||||
|
||||
jsr tape_normal_get_bit
|
||||
bcs tape_normal_get_byte_error
|
||||
beq !+
|
||||
lda #$01
|
||||
!:
|
||||
eor PRTY
|
||||
bne tape_normal_get_byte_error
|
||||
|
||||
// Checksum validated succesfully
|
||||
|
||||
ldx #$0B
|
||||
// Carry already clear
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_normal_get_byte_done:
|
||||
|
||||
stx VIC_EXTCOL
|
||||
lda INBIT
|
||||
rts
|
||||
|
||||
|
||||
tape_normal_get_byte_error:
|
||||
|
||||
ldx #$09
|
||||
sec // make sure Carry is set to indicate error
|
||||
bcs tape_normal_get_byte_done
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,121 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Tape (normal) helper routine - data block (primary) reading
|
||||
//
|
||||
// Stores data starting from MEMUSS, Carry set means error, on 0 bit .A is 0 too
|
||||
// .Y not equal to 0 - returns error if data block is longer (length includes checksum)
|
||||
|
||||
|
||||
// XXX improve error handling - do not ignore second copy, handle damaged sync part
|
||||
|
||||
|
||||
#if CONFIG_TAPE_NORMAL
|
||||
|
||||
|
||||
tape_normal_get_data_1:
|
||||
|
||||
// Initialize checksum (RIPRTY, see http://sta.c64.org/cbm64mem.html)
|
||||
// and pointers for error log and correction mechanism
|
||||
lda #$00
|
||||
sta RIPRTY
|
||||
#if !CONFIG_TAPE_NO_ERROR_CORRECTION
|
||||
sta PTR2
|
||||
sta PTR1
|
||||
#endif
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_normal_get_data_1_block:
|
||||
|
||||
//
|
||||
// Read the 1st copy of the block
|
||||
//
|
||||
|
||||
// Read sync of the block
|
||||
ldy #$89
|
||||
jsr tape_normal_sync
|
||||
bcs tape_normal_get_data_1_fail
|
||||
jsr tape_normal_get_marker
|
||||
|
||||
tape_normal_get_data_1_loop:
|
||||
|
||||
jsr tape_normal_get_byte
|
||||
bcc tape_normal_get_data_1_loop_byte_OK
|
||||
|
||||
#if CONFIG_TAPE_NO_ERROR_CORRECTION
|
||||
|
||||
bcs tape_normal_get_data_1_fail
|
||||
|
||||
#else
|
||||
|
||||
// Problem reading a byte, try to add it to the error log
|
||||
|
||||
tsx
|
||||
cpx #$20 // just to be on a safe side
|
||||
bcc tape_normal_get_data_1_fail // branch if no more space in error log
|
||||
|
||||
ldx PTR1
|
||||
lda MEMUSS+0
|
||||
sta STACK, x
|
||||
inx
|
||||
lda MEMUSS+1
|
||||
sta STACK, x
|
||||
inx
|
||||
stx PTR1
|
||||
|
||||
// Addres added to error log, check if this was a checksum
|
||||
jsr tape_normal_get_marker
|
||||
bcc tape_normal_get_data_1_loop_advance
|
||||
bcs tape_normal_get_data_1_success
|
||||
|
||||
#endif
|
||||
|
||||
tape_normal_get_data_1_loop_byte_OK:
|
||||
|
||||
jsr tape_normal_get_marker
|
||||
bcc !+
|
||||
|
||||
// End of the block
|
||||
jsr tape_normal_update_checksum
|
||||
jmp tape_normal_get_data_1_success
|
||||
|
||||
!:
|
||||
// Store byte, calculate checksum
|
||||
lda INBIT
|
||||
ldy #$00
|
||||
#if ROM_LAYOUT_M65
|
||||
jsr tape_normal_byte_store
|
||||
#else
|
||||
sta (MEMUSS), y
|
||||
#endif
|
||||
jsr tape_normal_update_checksum
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_normal_get_data_1_loop_advance:
|
||||
|
||||
// Advance pointer
|
||||
#if !HAS_OPCODES_65CE02
|
||||
jsr lvs_advance_MEMUSS
|
||||
#else
|
||||
inw MEMUSS+0
|
||||
#endif
|
||||
|
||||
jmp tape_normal_get_data_1_loop
|
||||
|
||||
|
||||
tape_normal_get_data_1_success:
|
||||
|
||||
clc
|
||||
rts
|
||||
|
||||
tape_normal_get_data_1_fail:
|
||||
|
||||
sec
|
||||
rts
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,124 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Tape (normal) helper routine - data block (backup) reading
|
||||
//
|
||||
|
||||
|
||||
#if CONFIG_TAPE_NORMAL && !CONFIG_TAPE_NO_ERROR_CORRECTION
|
||||
|
||||
|
||||
tape_normal_get_data_2:
|
||||
|
||||
// First check if there is a need to read anything
|
||||
|
||||
lda PTR1
|
||||
beq tape_normal_get_data_2_log_checksum
|
||||
|
||||
// Read sync of the block
|
||||
|
||||
ldy #$09
|
||||
jsr tape_normal_sync
|
||||
bcs tape_normal_get_data_2_done // Carry already set, will indicate error
|
||||
jsr tape_normal_get_marker
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_normal_get_data_2_loop:
|
||||
|
||||
// Check if there are missing bytes to read
|
||||
lda PTR1
|
||||
cmp PTR2
|
||||
beq tape_normal_get_data_2_log_checksum // branch if no more errors to correct
|
||||
|
||||
// Read missing bytes
|
||||
|
||||
jsr tape_normal_get_byte
|
||||
bcc tape_normal_get_data_2_loop_byte_OK
|
||||
|
||||
// Problem reading a byte - just skip it
|
||||
|
||||
bcs tape_normal_get_data_2_loop_advance
|
||||
|
||||
tape_normal_get_data_2_loop_byte_OK:
|
||||
|
||||
jsr load_cmp_log_MEMUSS
|
||||
beq tape_normal_get_data_2_loop_from_log // branch if byte from the log
|
||||
|
||||
jsr tape_normal_get_marker
|
||||
bcs tape_normal_get_data_2_log_checksum // branch if end of blocks
|
||||
bcc tape_normal_get_data_2_loop_advance
|
||||
|
||||
|
||||
tape_normal_get_data_2_loop_from_log:
|
||||
|
||||
// This is a byte from the log
|
||||
|
||||
jsr tape_normal_get_marker
|
||||
bcs !+
|
||||
|
||||
lda INBIT
|
||||
ldy #$00
|
||||
#if ROM_LAYOUT_M65
|
||||
jsr tape_normal_byte_store
|
||||
#else
|
||||
sta (MEMUSS), y
|
||||
#endif
|
||||
!:
|
||||
jsr tape_normal_update_checksum
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_normal_get_data_2_loop_advance:
|
||||
|
||||
// Advance pointer
|
||||
#if !HAS_OPCODES_65CE02
|
||||
jsr lvs_advance_MEMUSS
|
||||
#else
|
||||
inw MEMUSS+0
|
||||
#endif
|
||||
|
||||
jmp tape_normal_get_data_2_loop
|
||||
|
||||
|
||||
tape_normal_get_data_2_log_checksum:
|
||||
|
||||
lda PTR1
|
||||
cmp PTR2
|
||||
bne tape_normal_get_data_2_done // Carry already set
|
||||
|
||||
// Validate checksum
|
||||
|
||||
lda RIPRTY
|
||||
cmp #$01 // sets Carry if checksum verification fails
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_normal_get_data_2_done:
|
||||
|
||||
rts
|
||||
|
||||
|
||||
load_cmp_log_MEMUSS:
|
||||
|
||||
ldx PTR2
|
||||
lda STACK+0, x
|
||||
cmp MEMUSS+0
|
||||
bne !+
|
||||
|
||||
lda STACK+1, x
|
||||
cmp MEMUSS+1
|
||||
bne !+
|
||||
|
||||
// MEMUSS matches address from the log
|
||||
|
||||
inc PTR2
|
||||
inc PTR2
|
||||
lda #$00 // to set Zero flag
|
||||
!:
|
||||
rts
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,53 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Tape (normal) helper routine - marker reading
|
||||
//
|
||||
// Reeturns marker type in Carry flag, set = end of data (normal marker) or failure (marker while sync)
|
||||
//
|
||||
|
||||
|
||||
#if CONFIG_TAPE_NORMAL
|
||||
|
||||
// (L,M) - end of byte, (L,S) - end of data
|
||||
|
||||
|
||||
tape_normal_get_marker:
|
||||
|
||||
|
||||
jsr tape_common_get_pulse
|
||||
cmp __pulse_threshold_ML
|
||||
bcs tape_normal_get_marker // too short for a long pulse
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_normal_get_marker_type:
|
||||
|
||||
jmp tape_common_get_pulse
|
||||
|
||||
|
||||
|
||||
!: // Not an entry point!!!
|
||||
|
||||
// XXX check for short pulses of turbo here
|
||||
|
||||
jsr tape_normal_calibrate_during_pilot // while sync use short pulses for calibration
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_normal_get_marker_while_sync:
|
||||
|
||||
// (L,M) - end of byte, (L,S) - end of data
|
||||
|
||||
jsr tape_common_get_pulse
|
||||
bcs !- // branch if short pulse
|
||||
|
||||
cmp __pulse_threshold_ML
|
||||
bcs tape_normal_get_marker_while_sync // too short for a long pulse
|
||||
|
||||
bcc tape_normal_get_marker_type // branch always
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,93 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Tape (turbo) helper routine - handling the pilot
|
||||
//
|
||||
|
||||
// Injest the pilot - series of short pulses. According to http://sidpreservation.6581.org/tape-format/
|
||||
// it consist of the following number of pulses:
|
||||
// - $6A00 for header
|
||||
// - $1A00 for data and seq block header
|
||||
// - $4F for repeated header/data
|
||||
|
||||
|
||||
#if CONFIG_TAPE_NORMAL
|
||||
|
||||
|
||||
tape_normal_get_pilot_header: // entry point, reset calibration, require 128x $40 pulses
|
||||
|
||||
// Reading the pilot header is the first action performed,
|
||||
// thus start by setting default thresholds
|
||||
|
||||
lda #$91
|
||||
sta __pulse_threshold
|
||||
lda #$67
|
||||
sta __pulse_threshold_ML
|
||||
|
||||
lda #$80
|
||||
skip_2_bytes_trash_nvz
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_normal_get_pilot_data: // entry point, require 4x $40 pulses
|
||||
|
||||
lda #$04
|
||||
skip_2_bytes_trash_nvz
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_normal_get_pilot_short: // entry point, require 1x $40 pulses
|
||||
|
||||
lda #$01
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_normal_get_pilot_common:
|
||||
|
||||
sta FSBLK
|
||||
|
||||
lda #$0B
|
||||
sta VIC_EXTCOL
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_normal_get_pilot_common_restart:
|
||||
|
||||
lda FSBLK
|
||||
sta ROPRTY
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_normal_get_pilot_common_loop_outer:
|
||||
|
||||
ldy #$40
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_normal_get_pilot_common_loop_inner:
|
||||
|
||||
jsr tape_common_get_pulse
|
||||
bcc tape_normal_get_pilot_common_restart // not a pilot - try again
|
||||
|
||||
#if CONFIG_TAPE_AUTODETECT
|
||||
// Try to distinguish turbo by cheecking for short signals
|
||||
cmp #$B9 // see comment in tape_common_autodetect.s
|
||||
bcs !+
|
||||
#endif
|
||||
|
||||
jsr tape_normal_calibrate_during_pilot
|
||||
|
||||
dey
|
||||
bne tape_normal_get_pilot_common_loop_inner
|
||||
|
||||
dec ROPRTY
|
||||
bne tape_normal_get_pilot_common_loop_outer
|
||||
|
||||
clc
|
||||
!:
|
||||
rts
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,45 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Tape (turbo) helper routine - synchronization handling
|
||||
//
|
||||
// .Y should contain start value (either $89 or $09)
|
||||
// Carry set = failed
|
||||
|
||||
|
||||
#if CONFIG_TAPE_NORMAL
|
||||
|
||||
|
||||
tape_normal_sync:
|
||||
|
||||
lda #$06
|
||||
sta VIC_EXTCOL
|
||||
|
||||
// Injest bytes of decreasing values
|
||||
|
||||
jsr tape_normal_get_marker_while_sync
|
||||
bcs tape_normal_sync_fail // branch if end of data marker
|
||||
|
||||
jsr tape_normal_get_byte
|
||||
bcs tape_normal_sync_fail
|
||||
|
||||
cpy INBIT // INBIT contains same value as .A
|
||||
bne tape_normal_sync_fail
|
||||
|
||||
dey
|
||||
and #%01111110
|
||||
bne tape_normal_sync // branch if not $80 and not $00
|
||||
|
||||
clc
|
||||
rts
|
||||
|
||||
|
||||
tape_normal_sync_fail:
|
||||
|
||||
sec
|
||||
rts
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Tape (normal) helper routine - checksum calculation
|
||||
//
|
||||
|
||||
|
||||
#if CONFIG_TAPE_NORMAL
|
||||
|
||||
|
||||
tape_normal_update_checksum:
|
||||
|
||||
lda INBIT
|
||||
eor RIPRTY
|
||||
sta RIPRTY
|
||||
|
||||
rts
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,57 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Tape (turbo) helper routine - storing byte uder I/O
|
||||
//
|
||||
// Has to preserve .A and .Y
|
||||
//
|
||||
|
||||
// This helper routine is meant to be copied to the start of CPU stack.
|
||||
// Original ROM tape loading routines uses this area to store information
|
||||
// about bytes that did not read properly for the first time
|
||||
// (see Mapping the C64, page 47); this mechanism is useless for turbo tape,
|
||||
// but it means we can safely use this area for our purposes
|
||||
|
||||
|
||||
#if CONFIG_TAPE_TURBO
|
||||
|
||||
|
||||
#if ROM_LAYOUT_M65
|
||||
.label __tape_turbo_bytestore_defmap = __tape_turbo_bytestore + 10
|
||||
#else
|
||||
.label __tape_turbo_bytestore_defmap = __tape_turbo_bytestore + 7
|
||||
#endif
|
||||
.label __tape_turbo_bytestore_size = __tape_turbo_bytestore_source_end - tape_turbo_bytestore_source
|
||||
|
||||
|
||||
tape_turbo_bytestore_source:
|
||||
|
||||
#if ROM_LAYOUT_M65
|
||||
jsr KERNAL_0.map_NORMAL
|
||||
#endif
|
||||
|
||||
// Set all memory as RAM, tape motor ON
|
||||
ldx #$00
|
||||
stx CPU_R6510
|
||||
|
||||
// Store byte in memory
|
||||
sta (MEMUSS), y
|
||||
|
||||
// Restore default memory layout
|
||||
ldx #$00 // value will be determined later, offset from start: 7 bytes
|
||||
stx CPU_R6510
|
||||
|
||||
#if ROM_LAYOUT_M65
|
||||
// Restore default map and quit
|
||||
jmp KERNAL_0.map_KERNAL_1
|
||||
#else
|
||||
// Go back
|
||||
rts
|
||||
#endif
|
||||
|
||||
__tape_turbo_bytestore_source_end:
|
||||
|
||||
|
||||
#endif // CONFIG_TAPE_TURBO
|
||||
@@ -0,0 +1,53 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Tape (turbo) helper routine - bit reading
|
||||
//
|
||||
|
||||
// Based on routine by enthusi/Onslaught, found here:
|
||||
// - https://codebase64.pokefinder.org/doku.php?id=base:turbotape_loader_source
|
||||
|
||||
|
||||
#if CONFIG_TAPE_TURBO
|
||||
|
||||
|
||||
tape_turbo_get_bit:
|
||||
|
||||
jsr tape_common_get_pulse
|
||||
bcs !+
|
||||
|
||||
clc
|
||||
ror
|
||||
sta __turbo_half_S // store half of the last measurement result for short pulse
|
||||
|
||||
lda #$01
|
||||
#if CONFIG_MB_MEGA_65
|
||||
sta SID_SIGVOL + __SID_R1_OFFSET
|
||||
sta SID_SIGVOL + __SID_L1_OFFSET
|
||||
#else
|
||||
sta SID_SIGVOL
|
||||
#endif
|
||||
lda #$06
|
||||
sta VIC_EXTCOL
|
||||
sec
|
||||
rts
|
||||
!:
|
||||
clc
|
||||
ror
|
||||
sta __turbo_half_L // store half of the last measurement result for long pulse
|
||||
|
||||
lda #$00
|
||||
#if CONFIG_MB_MEGA_65
|
||||
sta SID_SIGVOL + __SID_R1_OFFSET
|
||||
sta SID_SIGVOL + __SID_L1_OFFSET
|
||||
#else
|
||||
sta SID_SIGVOL
|
||||
#endif
|
||||
sta VIC_EXTCOL
|
||||
clc
|
||||
rts
|
||||
|
||||
|
||||
#endif // CONFIG_TAPE_TURBO
|
||||
@@ -0,0 +1,60 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Tape (turbo) helper routine - byte reading
|
||||
//
|
||||
// Returns byte in .A
|
||||
//
|
||||
|
||||
// Based on routine by enthusi/Onslaught, found here:
|
||||
// - https://codebase64.pokefinder.org/doku.php?id=base:turbotape_loader_source
|
||||
|
||||
|
||||
#if CONFIG_TAPE_TURBO
|
||||
|
||||
|
||||
tape_turbo_get_byte:
|
||||
|
||||
phx_trash_a
|
||||
lda #$01
|
||||
sta INBIT // init the to-be-read byte with 1 (canary bit to mark loop end)
|
||||
!:
|
||||
jsr tape_turbo_get_bit
|
||||
rol INBIT
|
||||
bcc !- // is the initial 1 shifted into carry already?
|
||||
plx_trash_a
|
||||
|
||||
// Compensate for tape speed variations
|
||||
|
||||
lda __turbo_half_S // half of the last value for bit '0'
|
||||
clc
|
||||
adc __turbo_half_L // half of the last value for bit '1'
|
||||
|
||||
sec
|
||||
sbc __pulse_threshold // now we have a diff between current threshold and calculated one
|
||||
beq tape_turbo_get_byte_done // branch if threshold correction not needed
|
||||
|
||||
bpl !+
|
||||
|
||||
lda __pulse_threshold
|
||||
cmp #($BF - 10)
|
||||
beq tape_turbo_get_byte_done // do not decrease threshold too far no matter what
|
||||
|
||||
dec __pulse_threshold
|
||||
bne tape_turbo_get_byte_done // branch always
|
||||
!:
|
||||
lda __pulse_threshold
|
||||
cmp #($BF + 10)
|
||||
beq tape_turbo_get_byte_done // do not increase threshold too far no matter what
|
||||
|
||||
inc __pulse_threshold
|
||||
|
||||
tape_turbo_get_byte_done:
|
||||
|
||||
lda INBIT
|
||||
rts
|
||||
|
||||
|
||||
#endif // CONFIG_TAPE_TURBO
|
||||
@@ -0,0 +1,77 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Tape (turbo) helper routine - synchronization handling
|
||||
//
|
||||
|
||||
// Based on routine by enthusi/Onslaught, found here:
|
||||
// - https://codebase64.pokefinder.org/doku.php?id=base:turbotape_loader_source
|
||||
|
||||
|
||||
#if CONFIG_TAPE_TURBO
|
||||
|
||||
|
||||
tape_turbo_sync_header:
|
||||
|
||||
// Initial pulse threshold
|
||||
lda #$BF // measured 128 bits '0' and 128 bits '1' under VICE, calculated average
|
||||
sta __pulse_threshold
|
||||
|
||||
// Synchronize with start of sync sequence
|
||||
jsr tape_turbo_sync_first
|
||||
#if CONFIG_TAPE_AUTODETECT
|
||||
bcs tape_turbo_sync_done
|
||||
#endif
|
||||
|
||||
// Perform synchronization, double loop, total $C0 * $04 iterations
|
||||
ldx #$C0
|
||||
!:
|
||||
ldy #$04
|
||||
!:
|
||||
stx XSAV
|
||||
jsr tape_turbo_get_byte
|
||||
cmp #$02
|
||||
bne tape_turbo_sync_header // branch if failure
|
||||
|
||||
dey
|
||||
bne !-
|
||||
ldx XSAV
|
||||
dex
|
||||
bne !--
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_turbo_sync_payload:
|
||||
|
||||
jsr tape_turbo_sync_first
|
||||
#if CONFIG_TAPE_AUTODETECT
|
||||
bcs tape_turbo_sync_done // this shopuld not happen
|
||||
#endif
|
||||
!:
|
||||
ldx #$09 // 9, 8, ...
|
||||
!:
|
||||
jsr tape_turbo_get_byte
|
||||
cmp #$02
|
||||
beq !-
|
||||
ldy #$00
|
||||
!:
|
||||
cpx INBIT
|
||||
bne tape_turbo_sync_payload
|
||||
jsr tape_turbo_get_byte
|
||||
dex
|
||||
bne !-
|
||||
|
||||
#if CONFIG_TAPE_AUTODETECT
|
||||
clc
|
||||
#endif
|
||||
|
||||
// FALLTROUGH
|
||||
|
||||
tape_turbo_sync_done:
|
||||
|
||||
rts
|
||||
|
||||
|
||||
#endif // CONFIG_TAPE_TURBO
|
||||
@@ -0,0 +1,53 @@
|
||||
// #LAYOUT# STD * #TAKE
|
||||
// #LAYOUT# M65 KERNAL_1 #TAKE
|
||||
// #LAYOUT# * * #IGNORE
|
||||
|
||||
//
|
||||
// Tape (turbo) helper routine - syynchronize to first byte with value $02
|
||||
//
|
||||
|
||||
#if CONFIG_TAPE_TURBO
|
||||
|
||||
|
||||
tape_turbo_sync_first:
|
||||
|
||||
#if CONFIG_TAPE_AUTODETECT
|
||||
|
||||
ldy #$00
|
||||
!:
|
||||
jsr tape_turbo_get_bit
|
||||
rol INBIT
|
||||
lda INBIT
|
||||
|
||||
cmp #$FF
|
||||
bne !+
|
||||
iny
|
||||
bpl !-
|
||||
bmi tape_turbo_sync_first_fail // suspiciously many $FF bytes, probably not a turbo tape
|
||||
!:
|
||||
cmp #$02
|
||||
bne tape_turbo_sync_first
|
||||
|
||||
clc
|
||||
rts
|
||||
|
||||
tape_turbo_sync_first_fail:
|
||||
|
||||
sec
|
||||
rts
|
||||
|
||||
#else // no CONFIG_TAPE_AUTODETECT
|
||||
|
||||
jsr tape_turbo_get_bit
|
||||
rol INBIT
|
||||
lda INBIT
|
||||
|
||||
cmp #$02
|
||||
bne tape_turbo_sync_first
|
||||
|
||||
rts
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
Reference in new issue
Block a user