25

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.

WW.
  • 353
  • 2
  • 6
  • 5
    I've never come across this phenomenon. Is it reproducible on emulators too? Does it also happen if you mash the keyboard? – Omar and Lorraine 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
  • @wizzwizz4 I mean the actual joystick. It might have required them both to be moved. I can't remember. – WW. Oct 19 '17 at 21:52
  • 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
  • Just a wild guess: maybe you didn't just moved the joystick, but also the table it was on, along with the tape drive ;) Moving tape drive during load could cause load errors ;) – Adam Oct 20 '17 at 15:15
  • 1
    I've heard of this phenomenon before, if that lends any credence. – NibblyPig Oct 27 '17 at 10:08
  • As @LeoB suggested, it MAY be an EMI (Electromagnetic interference) issue. But that would require the tape to be VERY susceptible to noise in the first place (bad design). I guess the 5V supply voltage of the joystick port is directly supplied from the common power supply net. When the joystick is moved, there is a moment when the two metallic plates are at an infinitesimally small distance. This can cause arcing, even at very low voltages. Arcing can be a source of noise (electrical fast transients) that can couple back to the 5V supply voltage, potentially interfering with other components. – Rev Nov 15 '17 at 12:45
  • 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 =) – Steve I Dec 09 '17 at 15:05
  • @Rev1.0 If the signal quality on the tape is marginal, couldn't pretty much anything mean the difference between loading and not? IOW try a different tape, try a different tape drive, try adjusting the volume level, etc. – snips-n-snails Dec 09 '17 at 21:39
  • 1
    and I thought my friend was crazy for saying that.. back in the day :D – Thomas Jun 20 '19 at 11:58

2 Answers2

19

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.

chicks
  • 397
  • 1
  • 4
  • 15
wizofwor
  • 2,788
  • 2
  • 14
  • 38
-4

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.

Chenmunka
  • 8,141
  • 3
  • 39
  • 65
  • @Wilson: Depends where the interrupts were coming from. I can't speak for the C64 but many machines shared interrupts between devices. You can't disable them all. – Chenmunka Oct 19 '17 at 08:53
  • 6
    @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 08:55
  • @Raffzahn: This is where I defer to those with better knowledge of the C64. I've certainly seen multiple input devices triggering the IRQ line of other 6502 systems (and 6809, 9900) causing just this effect. – Chenmunka Oct 19 '17 at 10:58
  • 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. – followed Monica to Codidact Oct 19 '17 at 12:46
  • I was under the impression that tape input generated an interrupt upon every upward transition across zero, and that to respond to that the ROM (okay, 'KERNEL', if I must) references one of the timers in order to classify the length of the wave, reloads the timer and then sits around for the next interrupt. That's exactly how a Vic-20 works, and I believed the logic had carried forward. As per Raffzahn and berendi, neither the keyboard nor joystick generate interrupts of their own, but the tape does issue interrupts. – Tommy Oct 19 '17 at 13:14
  • 3
    Heh @Chenmunka you can get the peer pressure badge now ;-). – Stephen Kitt Oct 19 '17 at 14:17
  • @Chenmunka Certainly when reading from the tape you need enough attention from the CPU to make sure you don't miss anything. But I'm surprised the same thing can happen with serial ports; these generally have handshaking so that the transmission will not go too fast for the receiver. Can you point to a system where this is not the case? – Omar and Lorraine Oct 19 '17 at 15:02
  • 1
    @Tommy right, it's not a timer interrupt anymore, unless there is a timeout. The ROM is called KERNAL though. – followed Monica to Codidact Oct 19 '17 at 15:20
  • @berendi haha, my brain tried to embrace the misspelling, but even then my hands wouldn't play along. I'm a fool. Always proof-read! – Tommy Oct 19 '17 at 15:48
  • 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
  • @Raffzahn: The amount of time required to service the keyboard interrupt will be affected by whether or not keys are pressed. If timing is at all "close" to exceeding limits when keys aren't pushed, it would hardly be unexpected that pushing keys might increase the service time enough to cause trouble. – supercat May 02 '18 at 18:08
  • 3
    @supercat Just, THERE IS NO KEYBOARD INTERRUPT. – Raffzahn May 03 '18 at 06:51
  • @Raffzahn: The time required by the timer-tick interrupt is significantly increased when keys are pushed. I should have said "keyboard service routine" rather than "keyboard interrupt", but the point is that pushing keys increase the time spend in interrupt service. – supercat May 04 '18 at 00:34