| Posted By
 SukkoPera on 2025-06-20 04:26:40
| Keyboard/Joystick Matrix
I have discovered an issue with the joystick swapper that is implemented in LittleSixteen V4.
When the swapper is activated, all I do is swap the enable signals of the two joystick buffers. This works perfectly for the direction signals but it doesn't work for the fire buttons, since one of the ports reports it on bit 6 while the other one reports it on bit 7 (while the directions use exactly the same bits).
A "proper" solution to this is not trivial and would require introducing at least one more chip, which I'd rather avoid.
A simple workaround, that can also be retrofit on exiting boards, is to have the button status reported on both bits for both ports. This works well and the only possible complication I see if that it will cause more "fake keypresses" than normal when reading the keyboard and joystick together: for instance, when the fire button of joystick 1 is pressed, X will be reported as pressed, in addition to the "normal" T. Similarly, for joystick 2, E will be reported as pressed in addition to the normal Shift.
So the question is: what is the opinion of senior programmers on this matter? Could this create any serious problems in existing games?
Thanks in advance!
|
|
Posted By
 bszggg on 2025-06-20 11:46:13
| Re: Keyboard/Joystick Matrix
I don't know the joy swapper project, but maybe you should test it in some 2 players game. (like spy us spy)
|
|
Posted By
 Proky on 2025-06-20 13:06:17
| Re: Keyboard/Joystick Matrix
In my opinion, this is not an ideal solution. Since the joystick was much less common on the Plus/4 (due to the different connector) than on the Commodore 64, a lot more games are controllable via the keyboard. A very widespread method was to map the left and right directions to the Z and X keys, and keyboard and joystick controls were not selectable but available simultaneously.
|
|
Posted By
 Crown on 2025-06-20 14:09:01
| Re: Keyboard/Joystick Matrix
The problem is that reading keyboard/joystick was not really documented properly back in the day. The issue is that a wrong coding pattern was used by most software, by putting the same mask selection value into $fd30 and $ff08 at the same time. Which reads both the keyboard and joystick at the same time. You probably can find this in some books as an example. And the ROM also provides a wrong example to follow as it always puts the same value both into $fd30 and $ff08.
The proper pattern is putting #$ff into $fd30 and the joystick selection mask into $ff08 to read joystick only, and put keyboard selection mask value into $fd30 and #$ff into $ff08 to read keyboard only. This is documented in Plus/4 Keyboard/Joystick Matrix
So software which uses this incorrect pattern might see an extra key being pressed instead of the joystick fire button, it really depends on whether that buttons has any meaning in that particular software, and what is the detection order.
One more thing, the RAM refresh cycles do execute $ff08 reads multiple times a frame, every 51.2 lines to be precise, if that overlaps with the keyboard/joystick read code, then it can cause a bug. This has not been properly investigated yet, but my assumption is that it is triggered if the read of $ff08 by the processor is preempted by the read of the RAM refresh cycle, so that the RAM refresh cycle reading $ff08 is after the write to $ff08 by the CPU and before the read of $ff08 by the CPU.
|
|
Posted By
 gerliczer on 2025-06-22 01:16:33
| Re: Keyboard/Joystick Matrix
One more thing, the RAM refresh cycles do execute $ff08 reads multiple times a frame, every 51.2 lines to be precise, if that overlaps with the keyboard/joystick read code, then it can cause a bug. This has not been properly investigated yet, but my assumption is that it is triggered if the read of $ff08 by the processor is preempted by the read of the RAM refresh cycle, so that the RAM refresh cycle reading $ff08 is after the write to $ff08 by the CPU and before the read of $ff08 by the CPU.
Interestingly, the mechanism assumed to cause a bug eerily resembles the operation of the procedure BSZ and TLC proposes to circumvent joystick reading problems with TEDs having dead Keyboard Latch. See the Let’s JoyTest! :) topic.
|
|
Posted By
 BSZ on 2025-06-21 17:54:43
| Re: Keyboard/Joystick Matrix
@gerliczer: This ram-refresh story isn't exactly what we've been circling around/exploiting, but it's interesting enough otherwise. 
It is worth writing a few words about this: think of your computer's RAM as a big spreadsheet. It consists of rows and columns. In our case, it consists of 256 rows and 256 columns. (256 × 256 = 65536 memory cells = 64K.) When the hardware (CPU or TED, it doesn't matter) wants to use a memory cell, RAM chips gets the number of row of the desired cell. And then RAM chips gets the column number, so the desired memory cycle can continue. The refresh cycle, however, is "simple": when the RAM chip receives the row number, all column cells in that row are refreshed. (This is done automatically by the RAM chip itself.)
In our machine, the 256 rows are given by the lower 8 bits of the address bus (2^8 = 256), the columns by the upper 8 bits. Since selecting 256 rows is enough to update the RAM, the TED must traverse the range $xx00..$xxFF. In which addresses the "xx" part could be anything, but in our case TED uses exactly the range $FF00..$FFFF for this purpose. TED has no special RAM refresh cycle, it performs simple memory reads in this range, which triggers the refresh of rows in RAM chips. (It will run 5 such cycles in each rasterline.)
However... The management of the ROM / RAM / I/O area is separated so that the RAM chips receive the row number in each cycle. However, if the memory cycle is in ROM or I/O space, the RAM chips do not receive a column number, so they will not perform the desired memory operation. (Except for the refresh... )
Because of the above, when refreshing RAM, it doesn't matter if there is I/O space and ROM within the address range $FF00..$FFFF, the refresh will happen anyway. Therefore TED can use this address range to refresh RAM.
However, TED has a strange feature that @Crown mentioned above: when TED does these refresh readings, it also reads its own registers! (If true, these register reads are also visible on the data bus. )
@Crown: At the end of the long text, the point is: I don't know how this could interfere with the handling of $FF08. The keyboard lines are stored by the register write, but the RAM refresh cycle is only read. The stored state of the lines, on the other hand, is not lost after one readout. As many times as you can read it out, you should get the same, as long as TED does not store a new state with a new $FF08 write.
(It's been long again. )
1 |
|
Posted By
 Lavina on 2025-06-21 18:05:44
 | Re: Keyboard/Joystick Matrix
Astonishing that this 4 decades old HW still holds so many mysteries! To inifinity and beyond!
|
|
Posted By
 SukkoPera on 2025-06-22 04:55:04
| Re: Keyboard/Joystick Matrix
Thanks for your comments, I'm really glad of seeing so many gurus jumping in! 
Although you just confirmed my fears and so I started looking into a proper solution. I think I found one which leaves the number of chips unchanged and it's "only" a lot of work...
More news hopefully soon!
|
|
Posted By
 Crown on 2025-06-22 05:02:18
| Re: Keyboard/Joystick Matrix
However, TED has a strange feature that @Crown mentioned above: when TED does these refresh readings, it also reads its own registers! (If true, these register reads are also visible on the data bus. happy )
Yes it is on the data bus, you can read it out with an unconnected memory read cycle right after, that was the method how I mapped the RAM refresh cycles back in the day. (Sidenote: a software modified Sidekick would be a really great tool to trigger and record bus accesses for measurement purposes, for various boundary scenarios, like this)
As the bug itself, treat it as unconfirmed yet. Back in the day when I did the One on One conversion, Pigmy asked for keyboard controls, and when we implemented it we ran into issues, which we never really fully explored yet, but circumstances pointed around the RAM refresh cycles as cause. Yeah in theory it souldn't cause an issue, but the saying is true here as well "Trust but verify", it's on my long list of to-dos to investigate 
|
|
Posted By
 siz on 2025-06-22 05:44:46
| Re: Keyboard/Joystick Matrix
My two cents: as long as the joystick read is gated (I mean fire is only allowed to pull down data lines when the select line is active) there shouldn't be a problem. Unless... of course bad programming can interfere where the coder did not AND mask the fire lines but compares them to the expected values. Those won't match.
|
|
Posted By
 SukkoPera on 2025-06-24 17:20:30
| Re: Keyboard/Joystick Matrix
Thanks but never mind, the board with the new circuit is complete. I "just" need to test the new circuit... 
But I like the new circuit because it makes use of "everything": the buffers I was using previously had 3 unused pins and that bothered me a lot! Now I have a 74x244 whose 2 halves handle all the directions of the joystick ports, and a 74x139 handling the buttons of both ports.
I will be very happy if it works! I even saved a little amount of board space, since the 139 is smaller than the 244.
UPDATE: The new circuit seems to work perfectly! Here's some schematics for those interested:

|
|
| |
Copyright © Plus/4 World Team, 2001-2025. Support Plus/4 World on Patreon |