23

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.

  • 5
    I've never come across this phenomenon. Is it reproducible on emulators too? Does it also happen if you mash the keyboard? – Wilson Oct 19 '17 at 14:59
  • 2
    Do you mean the joystick connection or the joystick analogue input device (the actual joystick)? – wizzwizz4 Oct 19 '17 at 15:40
  • 1
    I have never encountered this issue either - however, the U1 CIA chip controls keyboard, joystick, and tape - do you get the same behaviour when you press keys? The U1 CIA chip is unshielded and depending on board version may be socketed. – PhasedOut Oct 19 '17 at 20:10
  • 3
    I'm not much of an EE to post this as an answer, but from experience, any bit glitch in the tape interface ADC of a home computer would result in losing sync and a load error. Waggling the joystick(s) causes variations in power draw, which could cause slight variations in voltage at the input of the ADC. If it happens that a variation happened when the voltage was near the critical level between 0 and 1, a glitch could occur (reading a stray 1 instead of 0, or a 0 instead of 1). – Leo B. Oct 19 '17 at 22:29
  • 2
    I just joined and can't comment at the moment, so I post it as an answer and hope you guys are kind. For comparison I just loaded some games from tape (using TurboTape fastloader) on a physical 1985 breadbin C64. No load errors occur if I wiggle a joystick in port 1 or 2 while loading (incl. pressing fire). If you want further hardware information or tests just comment =) – Stefan I Dec 9 '17 at 15:05
17

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

  • for datasette: Pointer to current byte during SAVE
  • for keyboard: Pointer to line in screen memory to be scrolled during scroll

$00AE-$00AF

  • for datasette: End address for LOAD/VERIFY or SAVE
  • for keyboard: Pointer to line in Color RAM to be scrolled during scroll

$00D7:

  • 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.

TLDR:

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.

  • Why would those locations get hit when keystrokes aren't being sent to the screen? – supercat May 2 '18 at 18:06
-3

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.

  • 5
    @Chenmunka Not realy, at least not on the C64. The C64 keyboard (and thus the joystick lines) are not run via an IRQ. In fact, the CIA can not issue an interruptfor port lines changes. Only timers, clock, shift register and FLAG input can do so. Also, during cassette load IRQ is disabled. If at all, only an NMI from CIA2 could interfere here. But agin, no interrupt just for port changes. – Raffzahn Oct 19 '17 at 8:55
  • 1
    The keyboard state is normally checked in a timer interrupt, periodically interrupting the main program. This is reversed during tape operations, the work is done in the (reprogrammed) timer interrupt, and the main loop just polls a few flags, and checks for unshifted RUN/STOP. – berendi Oct 19 '17 at 12:46
  • 3
    Heh @Chenmunka you can get the peer pressure badge now ;-). – Stephen Kitt Oct 19 '17 at 14:17
  • 2
    @Wilson serial ports are a fairly sore point on Commodores; on the Vic-20 a hardware bug in the VIA meant the late adoption of a software workaround for serial communication — the CPU directly controls all communications and timing on a bit-by-bit basis. The C64 uses CIAs, which include a fix for that bug, but the accidental omission of a signal on the board has a similar effect. The C64 also uses the CPU directly to control all serial communications, bit by bit. The C128 finally has fully-working hardware serial ports. – Tommy Oct 19 '17 at 15:52
  • 2
    @supercat Just, THERE IS NO KEYBOARD INTERRUPT. – Raffzahn May 3 '18 at 6:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.