diff --git a/CONFIG.md b/CONFIG.md index ffef262c..5d2aad10 100644 --- a/CONFIG.md +++ b/CONFIG.md @@ -107,7 +107,7 @@ Needs over 1000 bytes in KERNAL segment. If unsure - enable. Adds a minimal turbo tape support - just LOAD command (device 7, like on _Action Replay_ and _Final_ cartridges) -Needs about 350 bytes in KERNAL segment. If unsure - enable. +Needs about 400 bytes in KERNAL segment. If unsure - enable. ## Multiple SID support @@ -211,6 +211,12 @@ If enabled, a simple DOS wedge is available from the direct mode - supports `@`, `@`, `@$`, `@$`, `@` NOTE: extra features and their syntax can change in the future! @@ -32,7 +33,7 @@ The following ROM features are currently missing: * BASIC expression parsing * floating point routines * tape (normal mode) support -* tape loading ignores secondary address +* tape loading ignores secondary address and has no pattern matching * IEC support for SAVE * RS-232 support * NMI handling is incomplete diff --git a/bin/basic_generic.rom b/bin/basic_generic.rom index 4df641d4..92d9c931 100644 Binary files a/bin/basic_generic.rom and b/bin/basic_generic.rom differ diff --git a/bin/basic_mega65.rom b/bin/basic_mega65.rom index fc64445f..13b667d0 100644 Binary files a/bin/basic_mega65.rom and b/bin/basic_mega65.rom differ diff --git a/bin/basic_testing.rom b/bin/basic_testing.rom index c5f9a87d..4f7b7003 100644 Binary files a/bin/basic_testing.rom and b/bin/basic_testing.rom differ diff --git a/bin/basic_ultimate64.rom b/bin/basic_ultimate64.rom index d6c333b7..7466b691 100644 Binary files a/bin/basic_ultimate64.rom and b/bin/basic_ultimate64.rom differ diff --git a/bin/kernal_generic.rom b/bin/kernal_generic.rom index dc594837..7134217e 100644 Binary files a/bin/kernal_generic.rom and b/bin/kernal_generic.rom differ diff --git a/bin/kernal_mega65.rom b/bin/kernal_mega65.rom index 939e42e9..cba79c6a 100644 Binary files a/bin/kernal_mega65.rom and b/bin/kernal_mega65.rom differ diff --git a/bin/kernal_testing.rom b/bin/kernal_testing.rom index 9b10448d..622723fe 100644 Binary files a/bin/kernal_testing.rom and b/bin/kernal_testing.rom differ diff --git a/bin/kernal_ultimate64.rom b/bin/kernal_ultimate64.rom index e53f8efe..9eab09cc 100644 Binary files a/bin/kernal_ultimate64.rom and b/bin/kernal_ultimate64.rom differ diff --git a/c64/,,config_generic.s b/c64/,,config_generic.s index e997bf79..09774f1b 100644 --- a/c64/,,config_generic.s +++ b/c64/,,config_generic.s @@ -75,7 +75,7 @@ #define CONFIG_PROGRAMMABLE_KEYS -.const CONFIG_KEYCMD_RUN = @"LOAD\"*\"" +.const CONFIG_KEYCMD_RUN = @"\$5FL" .const CONFIG_KEYCMD_F1 = @"@" .const CONFIG_KEYCMD_F2 = @"" @@ -106,6 +106,7 @@ #define CONFIG_PANIC_SCREEN #define CONFIG_DOS_WEDGE +#define CONFIG_TAPE_WEDGE #define CONFIG_BCD_SAFE_INTERRUPTS diff --git a/c64/,,config_mega65.s b/c64/,,config_mega65.s index 220d86f7..b5e6855b 100644 --- a/c64/,,config_mega65.s +++ b/c64/,,config_mega65.s @@ -77,7 +77,7 @@ #define CONFIG_PROGRAMMABLE_KEYS -.const CONFIG_KEYCMD_RUN = @"LOAD\"*\"" +.const CONFIG_KEYCMD_RUN = @"\$5FL" .const CONFIG_KEYCMD_F1 = @"@" .const CONFIG_KEYCMD_F2 = @"" @@ -108,6 +108,7 @@ #define CONFIG_PANIC_SCREEN #define CONFIG_DOS_WEDGE +#define CONFIG_TAPE_WEDGE #define CONFIG_BCD_SAFE_INTERRUPTS diff --git a/c64/,,config_testing.s b/c64/,,config_testing.s index d0550369..cdba7f9d 100644 --- a/c64/,,config_testing.s +++ b/c64/,,config_testing.s @@ -76,7 +76,7 @@ #define CONFIG_PROGRAMMABLE_KEYS -.const CONFIG_KEYCMD_RUN = @"LOAD\"*\"" +.const CONFIG_KEYCMD_RUN = @"\$5FL" .const CONFIG_KEYCMD_F1 = @"@" .const CONFIG_KEYCMD_F2 = @"" @@ -107,6 +107,7 @@ #define CONFIG_PANIC_SCREEN #define CONFIG_DOS_WEDGE +#define CONFIG_TAPE_WEDGE #define CONFIG_BCD_SAFE_INTERRUPTS diff --git a/c64/,,config_ultimate64.s b/c64/,,config_ultimate64.s index db0e9eeb..091f1974 100644 --- a/c64/,,config_ultimate64.s +++ b/c64/,,config_ultimate64.s @@ -75,7 +75,7 @@ #define CONFIG_PROGRAMMABLE_KEYS -.const CONFIG_KEYCMD_RUN = @"LOAD\"*\"" +.const CONFIG_KEYCMD_RUN = @"\$5FL" .const CONFIG_KEYCMD_F1 = @"@" .const CONFIG_KEYCMD_F2 = @"" @@ -106,6 +106,7 @@ #define CONFIG_PANIC_SCREEN #define CONFIG_DOS_WEDGE +#define CONFIG_TAPE_WEDGE #define CONFIG_BCD_SAFE_INTERRUPTS diff --git a/c64/aliases/,aliases_config.s b/c64/aliases/,aliases_config.s index dbc3a540..c994c313 100644 --- a/c64/aliases/,aliases_config.s +++ b/c64/aliases/,aliases_config.s @@ -213,6 +213,15 @@ +// Check that features are configured correctly +{ +#if CONFIG_TAPE_WEDGE && !CONFIG_TAPE_TURBO + .error "CONFIG_TAPE_WEDGE requires CONFIG_TAPE_TURBO" +#endif +} + + + // Handle processor configuration #if CONFIG_CPU_WDC_65C02 || CONFIG_CPU_CSG_65CE02 || CONFIG_CPU_WDC_65816 diff --git a/c64/basic/basic_main_loop.s b/c64/basic/basic_main_loop.s index 0c93e2a8..55ea6dce 100644 --- a/c64/basic/basic_main_loop.s +++ b/c64/basic/basic_main_loop.s @@ -62,17 +62,25 @@ rsl_l1: lda __tokenise_work1 beq basic_read_next_line -#if CONFIG_DOS_WEDGE + // Check if a wedge should take over + +#if CONFIG_DOS_WEDGE || CONFIG_TAPE_WEDGE + + ldx __tokenise_work1 // here is the size of input // Check if DOS wedge should take over lda BUF - cmp #$40 // '@' - bne !+ - ldx __tokenise_work1 // here is the size of input - jmp wedge_dos -!: -#endif // CONFIG_DOS_WEDGE +#if CONFIG_DOS_WEDGE + cmp #$40 // '@' + beq_far wedge_dos +#endif +#if CONFIG_TAPE_WEDGE + cmp #$1F // left arrow + beq_far wedge_tape +#endif + +#endif // Else, tokenise the line jsr tokenise_line diff --git a/c64/basic/wedge_tape.s b/c64/basic/wedge_tape.s new file mode 100644 index 00000000..9eaffab5 --- /dev/null +++ b/c64/basic/wedge_tape.s @@ -0,0 +1,36 @@ + +#if CONFIG_TAPE_WEDGE + + +// .X has to contain size of the buffer + +wedge_tape: + + lda #$FF + sta CURLIN+1 // in case of error do not print line number + + cpx #$02 + bne_far do_SYNTAX_error + + lda BUF+1 + cmp #$4C // 'L' + bne_far do_SYNTAX_error + + // Execute 'arrow + L' + + lda #$00 + sta FNLEN + + ldy #$01 + ldx #$07 // turbo tape device + jsr JSETFLS + + ldy TXTTAB+1 + ldx TXTTAB+0 + + jsr JLOAD + + jmp basic_main_loop + + +#endif // CONFIG_TAPE_WEDGE diff --git a/c64/kernal/tape/load_tape_turbo.s b/c64/kernal/tape/load_tape_turbo.s index e3ebfebf..496d6f61 100644 --- a/c64/kernal/tape/load_tape_turbo.s +++ b/c64/kernal/tape/load_tape_turbo.s @@ -9,7 +9,7 @@ // XXX use calibration bits to improve reading // XXX handle load address from Kernal API -// XXX add name matching +// XXX finish pattern matching #if CONFIG_TAPE_TURBO @@ -32,14 +32,15 @@ load_tape_turbo_header: // Read file header - jsr tape_turbo_sync + jsr tape_turbo_sync_header - ldy #$15 + ldy #$00 !: jsr tape_turbo_get_byte sta (TAPE1), y - dey - bpl !- + iny + cpy #$15 + bne !- jsr tape_handle_header bcs load_tape_turbo_header // if name does not match, look for other header @@ -50,7 +51,7 @@ load_tape_turbo_payload: // Read file payload - jsr tape_turbo_sync // .X gets set to 0 + jsr tape_turbo_sync_payload ldy #$00 sty PRTY // initial checksum value @@ -121,23 +122,43 @@ tape_turbo_get_bit: lsr rts - -tape_turbo_sync: +tape_turbo_sync_common: jsr tape_turbo_get_bit - rol ROPRTY - lda ROPRTY - cmp #$02 - bne tape_turbo_sync + rol ROPRTY + lda ROPRTY + cmp #$02 + bne tape_turbo_sync_common + rts + +tape_turbo_sync_header: + + ldx #$FF +!: + ldy #$03 +!: + jsr tape_turbo_sync_common + dey + bne !- + dex + bne !-- + + // FALLTROUGH + +tape_turbo_sync_payload: + + jsr tape_turbo_sync_common +!: ldx #$09 // 9,8,... is real turboTape !: // I sometimes used 8,7,6... to avoid it being listed in vice :) jsr tape_turbo_get_byte cmp #$02 beq !- + ldy #$00 !: cpx ROPRTY - bne tape_turbo_sync - jsr tape_turbo_get_byte + bne tape_turbo_sync_payload + jsr tape_turbo_get_byte dex bne !- diff --git a/c64/kernal/tape/tape_common.s b/c64/kernal/tape/tape_common.s index 0a8f97e0..95ccc478 100644 --- a/c64/kernal/tape/tape_common.s +++ b/c64/kernal/tape/tape_common.s @@ -22,6 +22,18 @@ tape_ditch_verify: jmp lvs_device_not_found_error +// +// Loading terminated by user +// + +tape_break_error: + + pla + pla + cli + jmp kernalerror_ROUTINE_TERMINATED + + // // Handle tape deck motor // @@ -92,13 +104,8 @@ tape_wait_play_loop: jsr udtim_keyboard jsr STOP - bcc !+ + bcs tape_break_error - // Stop key pressed - pla - pla - cli - jmp kernalerror_ROUTINE_TERMINATED !: lda CPU_R6510 and #$10 // check for pressed button @@ -118,49 +125,52 @@ tape_handle_header: // 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 $0B (tape timing) contained at the time of saving XXX handle this - // 16 bytes - filename, padded with 0x20 - // - // Out tape buffer contains header in reversed order + // 1 byte (skipped) - file type (0 = data, odd value = relocatable, even value = non-relocatable) + // 2 bytes - start address + // 2 bytes - end address + 1 + // 1 byte - if $0B (tape timing) contained at the time of saving + // 16 bytes - filename, padded with 0x20 // Print FOUND + file name ldx #__MSG_KERNAL_FOUND jsr print_kernal_message - ldy #$10 + ldy #$05 !: lda (TAPE1), y jsr JCHROUT - dey - bpl !- + iny + cpy #$15 + bne !- jsr print_return // Header, wait for user decision jsr tape_header_get_decision + bcs tape_break_error + + // Check if file name matches + +/* XXX does not work yet + jsr tape_match_filename bcs tape_handle_header_skip - - // XXX Perform filename matching - +*/ // Setup STAL and EAL - ldy #$15 + ldy #$00 lda (TAPE1), y sta STAL+0 - dey + iny lda (TAPE1), y sta STAL+1 - dey + iny lda (TAPE1), y sta EAL+0 - dey + iny lda (TAPE1), y sta EAL+1 @@ -172,6 +182,10 @@ tape_handle_header: jsr tape_screen_hide_motor_on + // FALLTROUGH + +tape_return_ok: + clc rts @@ -181,10 +195,47 @@ tape_handle_header_skip: jsr tape_screen_hide_motor_on + // FALLTROUGH + +tape_return_not_ok: + sec rts +// +// Check whether file name matches the pattern +// +/* XXX does not work yet +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 + beq !+ // end of pattern + lda (FNADDR), y // byte from pattern +!: + .break + cmp #KEY_ASTERISK + beq tape_return_ok + + cmp (TAPE1 + 5),y + bne tape_return_not_ok + + iny + cpy #$10 + bne tape_match_loop + + clc + rts +*/ + // // Get user decision whether to load the file or not // @@ -228,6 +279,7 @@ tape_load_success: jsr tape_screen_show_motor_off jsr lvs_display_done + jsr print_return cli jmp lvs_success_end