136 lines
3.1 KiB
ArmAsm
136 lines
3.1 KiB
ArmAsm
|
||
//
|
||
// 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
|
||
|
||
|
||
// XXX use pilot to calibrate reading speed
|
||
|
||
|
||
#if CONFIG_TAPE_NORMAL
|
||
|
||
|
||
load_tape_normal:
|
||
|
||
jsr tape_ditch_verify // only LOAD is supported, no VERIFY
|
||
|
||
// Setup CIA #2 timers
|
||
|
||
ldx #$03 // set timer A to 4 ticks
|
||
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
|
||
|
||
// Temporarily store MEMUSS in EAL
|
||
|
||
lda MEMUSS+1
|
||
sta EAL+1
|
||
lda MEMUSS+0
|
||
sta EAL+0
|
||
|
||
// Start playing
|
||
|
||
jsr tape_ask_play
|
||
|
||
// FALLTROUGH
|
||
|
||
load_tape_normal_header:
|
||
|
||
// Try to load header into tape buffer
|
||
|
||
lda TAPE1+1
|
||
sta MEMUSS+1
|
||
lda TAPE1+0
|
||
sta MEMUSS+0
|
||
|
||
// Retrieve the header
|
||
|
||
jsr tape_normal_pilot_header
|
||
ldy #$C1 // size limit (including checksum)
|
||
jsr tape_normal_get_data
|
||
bcs load_tape_normal_header // unable to read block, try again
|
||
|
||
// Check header type
|
||
|
||
ldy #$00 // XXX probably can be optimized for 65C02
|
||
lda (TAPE1),y
|
||
|
||
cmp #$05
|
||
beq_far tape_load_error // end of tape mark, nothing to load
|
||
|
||
cmp #$01
|
||
beq !+
|
||
cmp #$03
|
||
bne load_tape_normal_header // header types 1 and 3 are loadable, see Mapping the C64, page 77
|
||
|
||
lda #$01
|
||
sta SA // this file is non-relocatable; override secondary address with 1
|
||
!:
|
||
// Handle the header
|
||
|
||
// Restore MEMUSS
|
||
|
||
lda EAL+1
|
||
sta MEMUSS+1
|
||
lda EAL+0
|
||
sta MEMUSS+0
|
||
|
||
// Handle the header
|
||
|
||
jsr tape_handle_header
|
||
bcs load_tape_normal_header // if name does not match, look for other header
|
||
|
||
// FALLTROUGH
|
||
|
||
load_tape_normal_payload:
|
||
|
||
// Retrieve data
|
||
|
||
jsr tape_normal_pilot_data
|
||
ldy #$00 // no data size limit
|
||
jsr tape_normal_get_data
|
||
bcs_far tape_load_error
|
||
|
||
jsr lvs_check_EAL
|
||
bne_far tape_load_error // amount of data read does not match header info
|
||
|
||
jmp tape_load_success
|
||
|
||
|
||
#endif
|