Commodore 64 uses two CIA (Complex Interface Adapter) chips. CIA#1 is responsible for the keyboard, joystick, paddles, datasette and IRQ control, while CIA#2 controls the serial bus, RS-232, VIC memory and NMI.
If you check the CIA#1 address map you will see that:
$DC00 (Port A) is used for keyboard matrix columns and Joystick #2 at the same time, while address
$DC01 (Port B) is used for keyboard matrix rows and Joystick #1. This means that there is no difference between joystick and keyboard inputs for the standard interrupt service routine. When there is a keyboard or joystick input, the service routine reads ports A and B and updates relevant addresses.
Memory locations used during datasette and keyboard access (taken from the memory map provided at sta.c64.org (http://sta.c64.org/cbm64mem.html) are listed below:
== Memory Locations used during datasette access ==
$0090: Value of ST variable, device status for datasette input/output.
$0091: Stop key indicator
$0093: LOAD/VERIFY switch
$0096: End of tape indicator
$0097: Temporary area for saving original value of X register
$0098: Number of files currently open (0-10)
$009B: Parity bit
$009C: Byte ready indicator
$009D: System error display switch
$009E: Byte to be put into output buffer, block header type, length of file name during datasette input/output, error counter during LOAD from datasette.
$009F: Aux counter
$00A3: bit counter
$00A5: Counter of sync mark
$00A6: Offset of current byte
$00AB: Computer block checksum
$00AC-$00AD: Pointer to current byte during SAVE
$00AE-$00AF: End address for LOAD/VERIFY or SAVE
$00B2-$00B3: Pointer to datasette buffer (Default: $033C)
$00B4: Bit counter
$00BD: Byte buffer
$00BE: Block counter
$00C0: Datasette motor switch
$00C1-$00C2: Start address during LOAD/VERIFY/SAVE
$00D7: Bit buffer during datasette input./Block checksum during datasette output.
== Memory Locations used during keyboard access ==
$00C5: Keyboard matrix code of key previously pressed
$00C6: Length of Keyboard Buffer
$00C7: Reverse mode switch
$00C8: Length of line minus 1
$00C9: Cursor row
$00CA: Cursor column
$00CB: Matrix code of key currently pressed
$00CE: Screen code character under cursor
$00CF: Cursor phase switch
$00D0: End of line switch
$00D1-$00D2: Pointer to current line
$00D3: Pointer to current column
$00D4: Quotation mode switch
$00D5: Length of current screen line minus 1
$00D6: Current Cursor row
$00D7: Petscii code of character during screen input
$00D8: Number of insertions
$00D9-$00F1: High byte of pointers to each line in screen memory (25 bytes)
$00F2: Temporary area during scroll
$00F3-$00F5: Pointer to current line in COLOR RAM
$0277-$0280: Keyboard buffer (10 bytes)
$0289: Maximum length of keyboard buffer
$028A: Keyboard repeat switch
$028B: Delay counter during repeat sequence, for delaying between successive repeats
$028C: Repeat sequence delay counter, for delaying before first repetition
$028D: Shift key indicator
$028E: Previous value of shift key indicator.
$0291: Commodore-Shift switch
$0292: Scroll direction switch during scrolling the screen
Apparently some the addresses are the same, e.g:
- for datasette: Pointer to current byte during SAVE
- for keyboard: Pointer to line in screen memory to be scrolled during scroll
- for datasette: End address for LOAD/VERIFY or SAVE
- for keyboard: Pointer to line in Color RAM to be scrolled during scroll
- for datasette: PETSCII code of character during screen input/output.
- for keyboard: Bit buffer during datasette input. / Block checksum during datasette output.
This means keyboard input (or joystick input misinterpreted as keyboard input) can easily interfere with the datasette loader. Some fast loaders are able to avoid this by using different memory schemes or by disabling keyboard input during loading. IMHO the Commodore engineers should have implemented it into the kernel from the beginning.
Because of the way the CIA chip interfaces with the rest of the system, the KERNAL interrupt service routine (which is located in
$EA31 by default) doesn't differentiate keyboard and joystick inputs. When there is a joystick input the service routine updates memory locations associated with the keyboard. This interferes with the datasette operations as some of the keyboard addresses are shared with datasette.