When loading a game from the tape drive on a C64, if you wiggle the joystick around too much the program will not load correctly. Is there an explanation for this?
EDIT: Perhaps someone can try to reproduce this on their C64 and see if it's just me.
When loading a game from the tape drive on a C64, if you wiggle the joystick around too much the program will not load correctly. Is there an explanation for this?
EDIT: Perhaps someone can try to reproduce this on their C64 and see if it's just me.
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:
Memory address $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
$00A4: Parity
$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:
$00AC-$00AD
$00AE-$00AF
$00D7:
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.
Interrupts.
This is not a problem that is unique to the C64 but could be seen on many machines of the era. There is one CPU handling interrupts from various peripherals.
If the joystick is moved, or buttons pressed, it will generate an interrupt. When the tape drive is being read, that too may generate interrupts - probably from a timer device to read at set intervals.
If there are too many interrupts to handle, even if nothing is done with them, the CPU may miss a byte or two of input from the tape.
I used to encounter this all the time on processors from a number of manufacturers. It doesn't just affect tape drives, it was very common when reading from serial ports or modems which interrupted the CPU on every byte read.